summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--UPDATING6
-rw-r--r--contrib/elftoolchain/elfcopy/sections.c18
-rw-r--r--contrib/elftoolchain/libdwarf/libdwarf_attr.c5
-rw-r--r--contrib/elftoolchain/libelftc/elftc_string_table.c37
-rw-r--r--contrib/elftoolchain/libelftc/elftc_string_table_create.38
-rw-r--r--contrib/elftoolchain/libelftc/libelftc.h4
-rw-r--r--contrib/gcc/config/rs6000/tramp.asm3
-rw-r--r--contrib/ipfilter/man/ipmon.82
-rw-r--r--contrib/ipfilter/tools/ipmon.c5
-rw-r--r--contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp3
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp3
-rw-r--r--etc/mtree/BSD.include.dist4
-rw-r--r--gnu/usr.bin/cc/cc_tools/Makefile.hdrs3
-rw-r--r--include/Makefile20
-rw-r--r--lib/Makefile1
-rw-r--r--lib/libbe/be_access.c32
-rw-r--r--lib/libc/gen/Symbol.map1
-rw-r--r--lib/libc/gen/_pthread_stubs.c2
-rw-r--r--lib/libc/gen/libc_dlopen.c5
-rw-r--r--lib/libc/gen/opendir.c4
-rw-r--r--lib/libc/gen/telldir.c4
-rw-r--r--lib/libc/include/libc_private.h1
-rw-r--r--lib/libc/powerpc/SYS.h7
-rw-r--r--lib/libc/powerpc/gen/_ctx_start.S9
-rw-r--r--lib/libc/powerpc/sys/cerror.S23
-rw-r--r--lib/libc/stdlib/realpath.c6
-rw-r--r--lib/libc/sys/mmap.236
-rw-r--r--lib/libc/sys/mprotect.236
-rw-r--r--lib/libjail/jail.c1
-rw-r--r--lib/libnandfs/Makefile10
-rw-r--r--lib/libnandfs/Makefile.depend17
-rw-r--r--lib/libnandfs/libnandfs.h67
-rw-r--r--lib/libnandfs/nandfs.c249
-rw-r--r--lib/libsecureboot/h/libsecureboot.h5
-rw-r--r--lib/libsecureboot/libsecureboot-priv.h2
-rw-r--r--lib/libsecureboot/local.trust.mk9
-rw-r--r--lib/libsecureboot/openpgp/opgp_key.c49
-rw-r--r--lib/libsecureboot/readfile.c39
-rw-r--r--lib/libsecureboot/verify_file.c29
-rw-r--r--lib/libsecureboot/vets.c138
-rw-r--r--lib/libthr/thread/thr_init.c1
-rw-r--r--lib/libusb/libusb10.h4
-rw-r--r--lib/libusb/libusb10_hotplug.c35
-rwxr-xr-xlibexec/rc/rc.d/motd12
-rw-r--r--libexec/rtld-elf/debug.h4
-rw-r--r--libexec/rtld-elf/powerpc/reloc.c27
-rw-r--r--libexec/rtld-elf/powerpc/rtld_start.S63
-rw-r--r--libexec/rtld-elf/rtld.c6
-rw-r--r--libexec/rtld-elf/rtld.h4
-rw-r--r--libexec/rtld-elf/rtld_printf.h1
-rw-r--r--release/Makefile.mirrors4
-rw-r--r--release/picobsd/bridge/PICOBSD1
-rwxr-xr-xrelease/picobsd/build/picobsd4
-rw-r--r--release/picobsd/qemu/PICOBSD1
-rw-r--r--sbin/Makefile2
-rw-r--r--sbin/bectl/bectl.c37
-rwxr-xr-xsbin/bectl/tests/bectl_test.sh24
-rw-r--r--sbin/camcontrol/camcontrol.c24
-rw-r--r--sbin/dhclient/options.c3
-rw-r--r--sbin/dhclient/packet.c4
-rw-r--r--sbin/ipf/ipmon/Makefile3
-rw-r--r--sbin/ipfw/ipfw.88
-rw-r--r--sbin/ipfw/ipfw2.c26
-rw-r--r--sbin/ipfw/ipfw2.h1
-rw-r--r--sbin/nandfs/Makefile10
-rw-r--r--sbin/nandfs/Makefile.depend18
-rw-r--r--sbin/nandfs/lssnap.c114
-rw-r--r--sbin/nandfs/mksnap.c82
-rw-r--r--sbin/nandfs/nandfs.879
-rw-r--r--sbin/nandfs/nandfs.c76
-rw-r--r--sbin/nandfs/nandfs.h42
-rw-r--r--sbin/nandfs/rmsnap.c89
-rw-r--r--sbin/newfs_nandfs/Makefile9
-rw-r--r--sbin/newfs_nandfs/Makefile.depend20
-rw-r--r--sbin/newfs_nandfs/newfs_nandfs.874
-rw-r--r--sbin/newfs_nandfs/newfs_nandfs.c1183
-rw-r--r--sbin/swapon/swapon.89
-rw-r--r--sbin/swapon/swapon.c60
-rw-r--r--share/examples/etc/make.conf6
-rw-r--r--share/man/man4/Makefile2
-rw-r--r--share/man/man4/gpio.443
-rw-r--r--share/man/man4/nand.4145
-rw-r--r--share/man/man4/nandsim.493
-rw-r--r--share/man/man4/owc.420
-rw-r--r--share/man/man4/random.41
-rw-r--r--share/man/man5/Makefile4
-rw-r--r--share/man/man5/fstab.56
-rw-r--r--share/man/man5/nandfs.5132
-rw-r--r--share/man/man9/Makefile2
-rw-r--r--share/man/man9/VOP_REVOKE.94
-rw-r--r--share/man/man9/iflibdi.96
-rw-r--r--share/man/man9/pwm.993
-rw-r--r--share/man/man9/pwmbus.981
-rw-r--r--share/man/man9/vm_map_protect.919
-rw-r--r--share/misc/bsd-family-tree5
-rw-r--r--share/mk/bsd.cpu.mk4
-rw-r--r--share/mk/bsd.libnames.mk1
-rw-r--r--share/mk/src.libnames.mk1
-rw-r--r--share/mk/src.opts.mk1
-rw-r--r--stand/arm/uboot/conf.c3
-rw-r--r--stand/arm/uboot/version1
-rw-r--r--stand/common/part.c8
-rw-r--r--stand/common/part.h1
-rw-r--r--stand/common/paths.h5
-rw-r--r--stand/efi/include/Protocol/Http.h523
-rw-r--r--stand/efi/include/Protocol/Ip4Config2.h324
-rw-r--r--stand/efi/include/Protocol/ServiceBinding.h95
-rw-r--r--stand/efi/include/efidevp.h22
-rw-r--r--stand/efi/include/efilib.h1
-rw-r--r--stand/efi/libefi/Makefile1
-rw-r--r--stand/efi/libefi/efihttp.c776
-rw-r--r--stand/efi/loader/conf.c2
-rw-r--r--stand/efi/loader/copy.c4
-rw-r--r--stand/efi/loader/main.c5
-rw-r--r--stand/i386/loader/conf.c3
-rw-r--r--stand/libsa/Makefile3
-rw-r--r--stand/libsa/nandfs.c1061
-rw-r--r--stand/libsa/stand.h2
-rw-r--r--stand/loader.mk3
-rw-r--r--stand/mips/uboot/conf.c3
-rw-r--r--stand/mips/uboot/version1
-rw-r--r--sys/amd64/amd64/pmap.c133
-rw-r--r--sys/amd64/conf/GENERIC1
-rw-r--r--sys/amd64/conf/MINIMAL3
-rw-r--r--sys/amd64/sgx/sgx.c2
-rw-r--r--sys/amd64/vmm/vmm_instruction_emul.c95
-rw-r--r--sys/arm/allwinner/files.allwinner1
-rw-r--r--sys/arm/conf/ALPINE1
-rw-r--r--sys/arm/conf/ARMADA38X1
-rw-r--r--sys/arm/conf/ARMADAXP1
-rw-r--r--sys/arm/conf/DB-78XXX5
-rw-r--r--sys/arm/conf/DB-88F5XXX1
-rw-r--r--sys/arm/conf/DB-88F6XXX5
-rw-r--r--sys/arm/conf/DOCKSTAR1
-rw-r--r--sys/arm/conf/DREAMPLUG-10019
-rw-r--r--sys/arm/conf/EFIKA_MX1
-rw-r--r--sys/arm/conf/GENERIC4
-rw-r--r--sys/arm/conf/IMX531
-rw-r--r--sys/arm/conf/IMX61
-rw-r--r--sys/arm/conf/NOTES61
-rw-r--r--sys/arm/conf/NOTES.armv533
-rw-r--r--sys/arm/conf/NOTES.armv764
-rw-r--r--sys/arm/conf/RPI-B1
-rw-r--r--sys/arm/conf/RT13101
-rw-r--r--sys/arm/conf/SHEEVAPLUG5
-rw-r--r--sys/arm/conf/SOCFPGA1
-rw-r--r--sys/arm/conf/TEGRA1241
-rw-r--r--sys/arm/conf/TS78001
-rw-r--r--sys/arm/conf/VERSATILEPB1
-rw-r--r--sys/arm/conf/VYBRID5
-rw-r--r--sys/arm/conf/ZEDBOARD1
-rw-r--r--sys/arm/freescale/vybrid/vf_nfc.c528
-rw-r--r--sys/arm/mv/files.arm71
-rw-r--r--sys/arm/mv/files.mv1
-rw-r--r--sys/arm/ti/am335x/am335x_ehrpwm.c308
-rw-r--r--sys/arm64/acpica/acpi_iort.c34
-rw-r--r--sys/arm64/arm64/freebsd32_machdep.c10
-rw-r--r--sys/arm64/arm64/gic_v3.c4
-rw-r--r--sys/arm64/arm64/gic_v3_var.h3
-rw-r--r--sys/arm64/arm64/gicv3_its.c4
-rw-r--r--sys/arm64/arm64/machdep.c31
-rw-r--r--sys/arm64/arm64/pmap.c129
-rw-r--r--sys/arm64/conf/GENERIC1
-rw-r--r--sys/cam/ata/ata_all.c25
-rw-r--r--sys/cam/ata/ata_all.h1
-rw-r--r--sys/cam/ata/ata_xpt.c23
-rw-r--r--sys/cam/cam_xpt.c101
-rw-r--r--sys/cam/ctl/ctl_error.c6
-rw-r--r--sys/cam/scsi/scsi_all.c4
-rw-r--r--sys/cam/scsi/scsi_da.c19
-rw-r--r--sys/cam/scsi/scsi_enc.c49
-rw-r--r--sys/cam/scsi/scsi_enc.h36
-rw-r--r--sys/cam/scsi/scsi_enc_internal.h25
-rw-r--r--sys/cam/scsi/scsi_enc_safte.c27
-rw-r--r--sys/cam/scsi/scsi_enc_ses.c296
-rw-r--r--sys/cam/scsi/scsi_ses.h31
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c19
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/multilist.c22
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h2
-rw-r--r--sys/compat/linuxkpi/common/include/asm/atomic-long.h1
-rw-r--r--sys/compat/linuxkpi/common/include/linux/rculist.h27
-rw-r--r--sys/conf/NOTES24
-rw-r--r--sys/conf/files55
-rw-r--r--sys/conf/files.amd643
-rw-r--r--sys/conf/files.arm6
-rw-r--r--sys/conf/files.arm642
-rw-r--r--sys/conf/files.powerpc4
-rw-r--r--sys/conf/kern.opts.mk1
-rw-r--r--sys/conf/makeLINT.mk5
-rw-r--r--sys/conf/options8
-rw-r--r--sys/contrib/ipfilter/netinet/fil.c42
-rw-r--r--sys/contrib/ipfilter/netinet/ip_compat.h185
-rw-r--r--sys/contrib/ipfilter/netinet/ip_fil.h1
-rw-r--r--sys/ddb/db_ps.c2
-rw-r--r--sys/dev/ahci/ahci.c48
-rw-r--r--sys/dev/ahci/ahci.h8
-rw-r--r--sys/dev/ahci/ahciem.c125
-rw-r--r--sys/dev/altera/msgdma/msgdma.c13
-rw-r--r--sys/dev/altera/msgdma/msgdma.h64
-rw-r--r--sys/dev/cxgbe/tom/t4_cpl_io.c25
-rw-r--r--sys/dev/cxgbe/tom/t4_ddp.c2
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.h2
-rw-r--r--sys/dev/drm2/ttm/ttm_bo_vm.c2
-rw-r--r--sys/dev/gpio/gpiobus.c185
-rw-r--r--sys/dev/gpio/gpiobusvar.h14
-rw-r--r--sys/dev/gpio/ofw_gpiobus.c4
-rw-r--r--sys/dev/iicbus/ad7418.c9
-rw-r--r--sys/dev/nand/nand.c826
-rw-r--r--sys/dev/nand/nand.h415
-rw-r--r--sys/dev/nand/nand_bbt.c275
-rw-r--r--sys/dev/nand/nand_cdev.c454
-rw-r--r--sys/dev/nand/nand_dev.h92
-rw-r--r--sys/dev/nand/nand_ecc_pos.h58
-rw-r--r--sys/dev/nand/nand_generic.c1366
-rw-r--r--sys/dev/nand/nand_geom.c467
-rw-r--r--sys/dev/nand/nand_id.c70
-rw-r--r--sys/dev/nand/nand_if.m168
-rw-r--r--sys/dev/nand/nandbus.c542
-rw-r--r--sys/dev/nand/nandbus.h51
-rw-r--r--sys/dev/nand/nandbus_if.m100
-rw-r--r--sys/dev/nand/nandsim.c670
-rw-r--r--sys/dev/nand/nandsim.h177
-rw-r--r--sys/dev/nand/nandsim_chip.c898
-rw-r--r--sys/dev/nand/nandsim_chip.h161
-rw-r--r--sys/dev/nand/nandsim_ctrl.c398
-rw-r--r--sys/dev/nand/nandsim_log.c188
-rw-r--r--sys/dev/nand/nandsim_log.h54
-rw-r--r--sys/dev/nand/nandsim_swap.c383
-rw-r--r--sys/dev/nand/nandsim_swap.h66
-rw-r--r--sys/dev/nand/nfc_fsl.c717
-rw-r--r--sys/dev/nand/nfc_fsl.h99
-rw-r--r--sys/dev/nand/nfc_if.m165
-rw-r--r--sys/dev/nand/nfc_mv.c238
-rw-r--r--sys/dev/nand/nfc_rb.c321
-rw-r--r--sys/dev/ow/owc_gpiobus.c6
-rw-r--r--sys/dev/usb/usb_hub_acpi.c17
-rw-r--r--sys/dev/virtio/scsi/virtio_scsi.c23
-rw-r--r--sys/fs/cuse/cuse.c47
-rw-r--r--sys/fs/fifofs/fifo_vnops.c2
-rw-r--r--sys/fs/nandfs/bmap.c625
-rw-r--r--sys/fs/nandfs/bmap.h42
-rw-r--r--sys/fs/nandfs/nandfs.h312
-rw-r--r--sys/fs/nandfs/nandfs_alloc.c366
-rw-r--r--sys/fs/nandfs/nandfs_bmap.c232
-rw-r--r--sys/fs/nandfs/nandfs_buffer.c85
-rw-r--r--sys/fs/nandfs/nandfs_cleaner.c622
-rw-r--r--sys/fs/nandfs/nandfs_cpfile.c778
-rw-r--r--sys/fs/nandfs/nandfs_dat.c346
-rw-r--r--sys/fs/nandfs/nandfs_dir.c316
-rw-r--r--sys/fs/nandfs/nandfs_fs.h567
-rw-r--r--sys/fs/nandfs/nandfs_ifile.c215
-rw-r--r--sys/fs/nandfs/nandfs_mount.h52
-rw-r--r--sys/fs/nandfs/nandfs_segment.c1314
-rw-r--r--sys/fs/nandfs/nandfs_subr.c1091
-rw-r--r--sys/fs/nandfs/nandfs_subr.h240
-rw-r--r--sys/fs/nandfs/nandfs_sufile.c571
-rw-r--r--sys/fs/nandfs/nandfs_vfsops.c1601
-rw-r--r--sys/fs/nandfs/nandfs_vnops.c2454
-rw-r--r--sys/fs/smbfs/smbfs_io.c4
-rw-r--r--sys/geom/geom_flashmap.c24
-rw-r--r--sys/i386/conf/GENERIC1
-rw-r--r--sys/i386/conf/MINIMAL3
-rw-r--r--sys/kern/Make.tags.inc2
-rw-r--r--sys/kern/kern_descrip.c4
-rw-r--r--sys/kern/kern_mib.c3
-rw-r--r--sys/kern/kern_rangelock.c71
-rw-r--r--sys/kern/kern_sig.c19
-rw-r--r--sys/kern/sys_pipe.c2
-rw-r--r--sys/kern/uipc_socket.c2
-rw-r--r--sys/kern/vfs_vnops.c5
-rw-r--r--sys/mips/conf/BCM1
-rw-r--r--sys/mips/conf/BERI_DE4_BASE1
-rw-r--r--sys/mips/conf/DIR-825B11
-rw-r--r--sys/mips/conf/ERL1
-rw-r--r--sys/mips/conf/JZ47801
-rw-r--r--sys/mips/conf/OCTEON11
-rw-r--r--sys/mips/conf/PB921
-rw-r--r--sys/mips/conf/PICOSTATION_M2HP3
-rw-r--r--sys/mips/conf/WZR-300HP2
-rw-r--r--sys/mips/conf/WZR-HPAG300H2
-rw-r--r--sys/mips/conf/X10001
-rw-r--r--sys/mips/conf/std.AR53121
-rw-r--r--sys/mips/conf/std.AR53151
-rw-r--r--sys/mips/conf/std.AR_MIPS_BASE3
-rw-r--r--sys/mips/conf/std.BERI1
-rw-r--r--sys/mips/conf/std.MALTA1
-rw-r--r--sys/mips/conf/std.XLP1
-rw-r--r--sys/mips/mediatek/std.mediatek3
-rw-r--r--sys/mips/mediatek/std.rt28803
-rw-r--r--sys/modules/Makefile7
-rw-r--r--sys/modules/nand/Makefile10
-rw-r--r--sys/modules/nandfs/Makefile12
-rw-r--r--sys/modules/nandsim/Makefile9
-rw-r--r--sys/net/if_vxlan.c2
-rw-r--r--sys/net/iflib.c19
-rw-r--r--sys/net/vnet.h3
-rw-r--r--sys/netinet/in.h6
-rw-r--r--sys/netinet/in_mcast.c433
-rw-r--r--sys/netinet/in_pcb.c32
-rw-r--r--sys/netinet/in_var.h52
-rw-r--r--sys/netinet/ip_carp.c100
-rw-r--r--sys/netinet/ip_fw.h1
-rw-r--r--sys/netinet/ip_mroute.c5
-rw-r--r--sys/netinet/ip_output.c13
-rw-r--r--sys/netinet/ip_var.h10
-rw-r--r--sys/netinet/tcp_subr.c6
-rw-r--r--sys/netinet6/in6.h5
-rw-r--r--sys/netinet6/in6_ifattach.c2
-rw-r--r--sys/netinet6/in6_mcast.c441
-rw-r--r--sys/netinet6/in6_pcb.c25
-rw-r--r--sys/netinet6/in6_var.h52
-rw-r--r--sys/netinet6/ip6_var.h11
-rw-r--r--sys/netipsec/key.c2
-rw-r--r--sys/netpfil/ipfw/ip_fw2.c48
-rw-r--r--sys/netpfil/ipfw/ip_fw_sockopt.c5
-rw-r--r--sys/netpfil/pf/if_pfsync.c45
-rw-r--r--sys/powerpc/conf/GENERIC1
-rw-r--r--sys/powerpc/conf/GENERIC641
-rw-r--r--sys/powerpc/conf/MPC85XX1
-rw-r--r--sys/powerpc/conf/MPC85XXSPE1
-rw-r--r--sys/powerpc/conf/QORIQ641
-rw-r--r--sys/powerpc/conf/dpaa/DPAA1
-rw-r--r--sys/powerpc/include/trap.h2
-rw-r--r--sys/powerpc/powerpc/machdep.c13
-rw-r--r--sys/powerpc/powerpc/trap.c14
-rw-r--r--sys/riscv/conf/GENERIC1
-rw-r--r--sys/sparc64/conf/GENERIC1
-rw-r--r--sys/sys/_types.h1
-rw-r--r--sys/sys/boot.h2
-rw-r--r--sys/sys/file.h5
-rw-r--r--sys/sys/filio.h12
-rw-r--r--sys/sys/mman.h8
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/pcpu.h3
-rw-r--r--sys/sys/pmckern.h2
-rw-r--r--sys/sys/random.h25
-rw-r--r--sys/sys/rangelock.h4
-rw-r--r--sys/sys/types.h2
-rw-r--r--sys/sys/vnode.h4
-rw-r--r--sys/ufs/ffs/ffs_softdep.c23
-rw-r--r--sys/vm/device_pager.c2
-rw-r--r--sys/vm/vm_fault.c2
-rw-r--r--sys/vm/vm_map.c6
-rw-r--r--sys/vm/vm_mmap.c45
-rw-r--r--sys/vm/vm_object.c8
-rw-r--r--sys/vm/vm_page.c15
-rw-r--r--sys/vm/vm_page.h2
-rw-r--r--targets/pseudo/userland/Makefile.depend9
-rw-r--r--targets/pseudo/userland/lib/Makefile.depend4
-rw-r--r--tests/sys/netinet/socket_afinet.c2
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc2
-rwxr-xr-xtools/tools/nanobsd/defaults.sh4
-rw-r--r--tools/tools/nanobsd/pcengines/ALIX_DSK1
-rw-r--r--tools/tools/tinybsd/conf/bridge/TINYBSD1
-rw-r--r--tools/tools/tinybsd/conf/default/TINYBSD1
-rw-r--r--tools/tools/tinybsd/conf/firewall/TINYBSD1
-rw-r--r--tools/tools/tinybsd/conf/minimal/TINYBSD1
-rw-r--r--tools/tools/tinybsd/conf/vpn/TINYBSD1
-rw-r--r--tools/tools/tinybsd/conf/wireless/TINYBSD1
-rw-r--r--tools/tools/tinybsd/conf/wrap/TINYBSD1
-rw-r--r--usr.bin/calendar/calendars/hr_HR.ISO8859-2/calendar.praznici32
-rw-r--r--usr.bin/top/display.c6
-rw-r--r--usr.bin/top/machine.c25
-rw-r--r--usr.bin/uname/uname.110
-rw-r--r--usr.bin/uname/uname.c19
-rw-r--r--usr.bin/vtfontcvt/vtfontcvt.c13
-rw-r--r--usr.sbin/Makefile2
-rw-r--r--usr.sbin/bhyve/Makefile3
-rw-r--r--usr.sbin/bhyve/audio.c284
-rw-r--r--usr.sbin/bhyve/audio.h88
-rw-r--r--usr.sbin/bhyve/bhyve.814
-rw-r--r--usr.sbin/bhyve/hda_codec.c952
-rw-r--r--usr.sbin/bhyve/hda_reg.h1369
-rw-r--r--usr.sbin/bhyve/hdac_reg.h271
-rw-r--r--usr.sbin/bhyve/net_utils.c18
-rw-r--r--usr.sbin/bhyve/pci_hda.c1331
-rw-r--r--usr.sbin/bhyve/pci_hda.h92
-rw-r--r--usr.sbin/bhyve/pci_virtio_scsi.c3
-rw-r--r--usr.sbin/bsnmpd/modules/snmp_lm75/snmp_lm75.c1
-rw-r--r--usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c2
-rw-r--r--usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def2
-rw-r--r--usr.sbin/kbdcontrol/kbdcontrol.c5
-rw-r--r--usr.sbin/mountd/mountd.c2
-rw-r--r--usr.sbin/nandsim/Makefile8
-rw-r--r--usr.sbin/nandsim/Makefile.depend17
-rw-r--r--usr.sbin/nandsim/nandsim.8229
-rw-r--r--usr.sbin/nandsim/nandsim.c1399
-rw-r--r--usr.sbin/nandsim/nandsim_cfgparse.c961
-rw-r--r--usr.sbin/nandsim/nandsim_cfgparse.h88
-rw-r--r--usr.sbin/nandsim/nandsim_rcfile.c442
-rw-r--r--usr.sbin/nandsim/nandsim_rcfile.h72
-rw-r--r--usr.sbin/nandsim/sample.conf174
-rw-r--r--usr.sbin/nandtool/Makefile10
-rw-r--r--usr.sbin/nandtool/Makefile.depend20
-rw-r--r--usr.sbin/nandtool/nand_erase.c116
-rw-r--r--usr.sbin/nandtool/nand_info.c88
-rw-r--r--usr.sbin/nandtool/nand_read.c141
-rw-r--r--usr.sbin/nandtool/nand_readoob.c113
-rw-r--r--usr.sbin/nandtool/nand_write.c145
-rw-r--r--usr.sbin/nandtool/nand_writeoob.c115
-rw-r--r--usr.sbin/nandtool/nandtool.8184
-rw-r--r--usr.sbin/nandtool/nandtool.c285
-rw-r--r--usr.sbin/nandtool/nandtool.h59
-rw-r--r--usr.sbin/nandtool/usage.h114
-rw-r--r--usr.sbin/usbdump/usbdump.c15
405 files changed, 9763 insertions, 32314 deletions
diff --git a/UPDATING b/UPDATING
index 95d109c9fa42..cc1be0a2e235 100644
--- a/UPDATING
+++ b/UPDATING
@@ -43,6 +43,12 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
sysctls have been removed. If you felt the need to set any of them to
a non-default value, please tell asomers@FreeBSD.org why.
+20190620:
+ Entropy collection and the /dev/random device are no longer optional
+ components. The "device random" option has been removed.
+ Implementations of distilling algorithms can still be made loadable
+ with "options RANDOM_LOADABLE" (e.g., random_fortuna.ko).
+
20190612:
Clang, llvm, lld, lldb, compiler-rt, libc++, libunwind and openmp have
been upgraded to 8.0.1. Please see the 20141231 entry below for
diff --git a/contrib/elftoolchain/elfcopy/sections.c b/contrib/elftoolchain/elfcopy/sections.c
index 93dbf4422863..2bd094d2bfbe 100644
--- a/contrib/elftoolchain/elfcopy/sections.c
+++ b/contrib/elftoolchain/elfcopy/sections.c
@@ -1398,7 +1398,23 @@ update_shdr(struct elfcopy *ecp, int update_link)
void
init_shstrtab(struct elfcopy *ecp)
{
+ Elf_Scn *shstrtab;
+ GElf_Shdr shdr;
struct section *s;
+ size_t indx, sizehint;
+
+ if (elf_getshstrndx(ecp->ein, &indx) != 0) {
+ shstrtab = elf_getscn(ecp->ein, indx);
+ if (shstrtab == NULL)
+ errx(EXIT_FAILURE, "elf_getscn failed: %s",
+ elf_errmsg(-1));
+ if (gelf_getshdr(shstrtab, &shdr) != &shdr)
+ errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
+ elf_errmsg(-1));
+ sizehint = shdr.sh_size;
+ } else {
+ sizehint = 0;
+ }
if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL)
err(EXIT_FAILURE, "calloc failed");
@@ -1410,7 +1426,7 @@ init_shstrtab(struct elfcopy *ecp)
s->loadable = 0;
s->type = SHT_STRTAB;
s->vma = 0;
- s->strtab = elftc_string_table_create(0);
+ s->strtab = elftc_string_table_create(sizehint);
add_to_shstrtab(ecp, "");
add_to_shstrtab(ecp, ".symtab");
diff --git a/contrib/elftoolchain/libdwarf/libdwarf_attr.c b/contrib/elftoolchain/libdwarf/libdwarf_attr.c
index dfbbc484c352..ea05374d051c 100644
--- a/contrib/elftoolchain/libdwarf/libdwarf_attr.c
+++ b/contrib/elftoolchain/libdwarf/libdwarf_attr.c
@@ -100,7 +100,6 @@ _dwarf_attr_init(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *offsetp,
uint64_t form, int indirect, Dwarf_Error *error)
{
struct _Dwarf_Attribute atref;
- Dwarf_Section *str;
int ret;
ret = DW_DLE_NONE;
@@ -183,9 +182,7 @@ _dwarf_attr_init(Dwarf_Debug dbg, Dwarf_Section *ds, uint64_t *offsetp,
break;
case DW_FORM_strp:
atref.u[0].u64 = dbg->read(ds->ds_data, offsetp, dwarf_size);
- str = _dwarf_find_section(dbg, ".debug_str");
- assert(str != NULL);
- atref.u[1].s = (char *) str->ds_data + atref.u[0].u64;
+ atref.u[1].s = _dwarf_strtab_get_table(dbg) + atref.u[0].u64;
break;
case DW_FORM_ref_sig8:
atref.u[0].u64 = 8;
diff --git a/contrib/elftoolchain/libelftc/elftc_string_table.c b/contrib/elftoolchain/libelftc/elftc_string_table.c
index c0da15eed794..37fcc36d407b 100644
--- a/contrib/elftoolchain/libelftc/elftc_string_table.c
+++ b/contrib/elftoolchain/libelftc/elftc_string_table.c
@@ -44,7 +44,7 @@ ELFTC_VCSID("$Id: elftc_string_table.c 2869 2013-01-06 13:29:18Z jkoshy $");
#define ELFTC_STRING_TABLE_POOL_SIZE_INCREMENT (4*1024)
struct _Elftc_String_Table_Entry {
- int ste_idx;
+ ssize_t ste_idx;
SLIST_ENTRY(_Elftc_String_Table_Entry) ste_next;
};
@@ -64,9 +64,9 @@ struct _Elftc_String_Table_Entry {
} while (0)
struct _Elftc_String_Table {
- unsigned int st_len; /* length and flags */
+ size_t st_len; /* length and flags */
int st_nbuckets;
- int st_string_pool_size;
+ size_t st_string_pool_size;
char *st_string_pool;
SLIST_HEAD(_Elftc_String_Table_Bucket,
_Elftc_String_Table_Entry) st_buckets[];
@@ -86,7 +86,7 @@ elftc_string_table_find_hash_entry(Elftc_String_Table *st, const char *string,
*rhashindex = hashindex;
SLIST_FOREACH(ste, &st->st_buckets[hashindex], ste_next) {
- s = st->st_string_pool + abs(ste->ste_idx);
+ s = st->st_string_pool + labs(ste->ste_idx);
assert(s > st->st_string_pool &&
s < st->st_string_pool + st->st_string_pool_size);
@@ -102,7 +102,7 @@ static int
elftc_string_table_add_to_pool(Elftc_String_Table *st, const char *string)
{
char *newpool;
- int len, newsize, stlen;
+ size_t len, newsize, stlen;
len = strlen(string) + 1; /* length, including the trailing NUL */
stlen = ELFTC_STRING_TABLE_LENGTH(st);
@@ -119,17 +119,17 @@ elftc_string_table_add_to_pool(Elftc_String_Table *st, const char *string)
st->st_string_pool_size = newsize;
}
- strcpy(st->st_string_pool + stlen, string);
+ memcpy(st->st_string_pool + stlen, string, len);
ELFTC_STRING_TABLE_UPDATE_LENGTH(st, stlen + len);
return (stlen);
}
Elftc_String_Table *
-elftc_string_table_create(int sizehint)
+elftc_string_table_create(size_t sizehint)
{
- int n, nbuckets, tablesize;
struct _Elftc_String_Table *st;
+ int n, nbuckets, tablesize;
if (sizehint < ELFTC_STRING_TABLE_DEFAULT_SIZE)
sizehint = ELFTC_STRING_TABLE_DEFAULT_SIZE;
@@ -173,13 +173,13 @@ elftc_string_table_destroy(Elftc_String_Table *st)
}
Elftc_String_Table *
-elftc_string_table_from_section(Elf_Scn *scn, int sizehint)
+elftc_string_table_from_section(Elf_Scn *scn, size_t sizehint)
{
- int len;
Elf_Data *d;
GElf_Shdr sh;
const char *s, *end;
Elftc_String_Table *st;
+ size_t len;
/* Verify the type of the section passed in. */
if (gelf_getshdr(scn, &sh) == NULL ||
@@ -235,7 +235,8 @@ elftc_string_table_image(Elftc_String_Table *st, size_t *size)
char *r, *s, *end;
struct _Elftc_String_Table_Entry *ste;
struct _Elftc_String_Table_Bucket *head;
- int copied, hashindex, offset, length, newsize;
+ size_t copied, offset, length, newsize;
+ int hashindex;
/*
* For the common case of a string table has not seen
@@ -303,8 +304,9 @@ elftc_string_table_image(Elftc_String_Table *st, size_t *size)
size_t
elftc_string_table_insert(Elftc_String_Table *st, const char *string)
{
- int hashindex, idx;
struct _Elftc_String_Table_Entry *ste;
+ ssize_t idx;
+ int hashindex;
hashindex = 0;
@@ -326,7 +328,7 @@ elftc_string_table_insert(Elftc_String_Table *st, const char *string)
idx = ste->ste_idx;
if (idx < 0) /* Undelete. */
- ste->ste_idx = idx = (- idx);
+ ste->ste_idx = idx = -idx;
return (idx);
}
@@ -334,8 +336,9 @@ elftc_string_table_insert(Elftc_String_Table *st, const char *string)
size_t
elftc_string_table_lookup(Elftc_String_Table *st, const char *string)
{
- int hashindex, idx;
struct _Elftc_String_Table_Entry *ste;
+ ssize_t idx;
+ int hashindex;
ste = elftc_string_table_find_hash_entry(st, string, &hashindex);
@@ -350,17 +353,17 @@ elftc_string_table_lookup(Elftc_String_Table *st, const char *string)
int
elftc_string_table_remove(Elftc_String_Table *st, const char *string)
{
- int idx;
struct _Elftc_String_Table_Entry *ste;
+ ssize_t idx;
ste = elftc_string_table_find_hash_entry(st, string, NULL);
if (ste == NULL || (idx = ste->ste_idx) < 0)
return (ELFTC_FAILURE);
- assert(idx > 0 && idx < (int) ELFTC_STRING_TABLE_LENGTH(st));
+ assert(idx > 0 && (size_t)idx < ELFTC_STRING_TABLE_LENGTH(st));
- ste->ste_idx = (- idx);
+ ste->ste_idx = -idx;
ELFTC_STRING_TABLE_SET_COMPACTION_FLAG(st);
diff --git a/contrib/elftoolchain/libelftc/elftc_string_table_create.3 b/contrib/elftoolchain/libelftc/elftc_string_table_create.3
index 36c7290d9f46..c3cf864af29c 100644
--- a/contrib/elftoolchain/libelftc/elftc_string_table_create.3
+++ b/contrib/elftoolchain/libelftc/elftc_string_table_create.3
@@ -24,7 +24,7 @@
.\"
.\" $Id: elftc_string_table_create.3 3645 2018-10-15 20:17:14Z jkoshy $
.\"
-.Dd January 5, 2013
+.Dd June 19, 2019
.Dt ELFTC_STRING_TABLE_CREATE 3
.Os
.Sh NAME
@@ -40,11 +40,11 @@
.Sh SYNOPSIS
.In libelftc.h
.Ft "Elftc_String_Table *"
-.Fn elftc_string_table_create "int sizehint"
-.Ft int
+.Fn elftc_string_table_create "size_t sizehint"
+.Ft void
.Fn elftc_string_table_destroy "Elftc_String_Table *table"
.Ft "Elftc_String_Table *"
-.Fn elftc_string_table_from_section "Elf_Scn *scn" "int sizehint"
+.Fn elftc_string_table_from_section "Elf_Scn *scn" "size_t sizehint"
.Ft "const char *"
.Fo elftc_string_table_image
.Fa "Elftc_String_Table *table"
diff --git a/contrib/elftoolchain/libelftc/libelftc.h b/contrib/elftoolchain/libelftc/libelftc.h
index a235097e6910..a404dfe34e9c 100644
--- a/contrib/elftoolchain/libelftc/libelftc.h
+++ b/contrib/elftoolchain/libelftc/libelftc.h
@@ -77,10 +77,10 @@ int elftc_demangle(const char *_mangledname, char *_buffer,
size_t _bufsize, unsigned int _flags);
const char *elftc_reloc_type_str(unsigned int mach, unsigned int type);
int elftc_set_timestamps(const char *_filename, struct stat *_sb);
-Elftc_String_Table *elftc_string_table_create(int _hint);
+Elftc_String_Table *elftc_string_table_create(size_t _sizehint);
void elftc_string_table_destroy(Elftc_String_Table *_table);
Elftc_String_Table *elftc_string_table_from_section(Elf_Scn *_scn,
- int _hint);
+ size_t _sizehint);
const char *elftc_string_table_image(Elftc_String_Table *_table,
size_t *_sz);
size_t elftc_string_table_insert(Elftc_String_Table *_table,
diff --git a/contrib/gcc/config/rs6000/tramp.asm b/contrib/gcc/config/rs6000/tramp.asm
index 013cac363b68..fe05401e039c 100644
--- a/contrib/gcc/config/rs6000/tramp.asm
+++ b/contrib/gcc/config/rs6000/tramp.asm
@@ -38,6 +38,7 @@
.file "tramp.asm"
.section ".text"
#include "ppc-asm.h"
+ #include "auto-host.h"
#ifndef __powerpc64__
.type trampoline_initial,@object
@@ -105,7 +106,7 @@ FUNC_START(__trampoline_setup)
blr
.Labort:
-#if defined SHARED && defined HAVE_AS_REL16
+#if (defined(__PIC__) || defined(__pic__)) && defined HAVE_AS_REL16
bcl 20,31,1f
1: mflr r30
addis r30,r30,_GLOBAL_OFFSET_TABLE_-1b@ha
diff --git a/contrib/ipfilter/man/ipmon.8 b/contrib/ipfilter/man/ipmon.8
index 126f4a7b15ee..aa20e5b3a49d 100644
--- a/contrib/ipfilter/man/ipmon.8
+++ b/contrib/ipfilter/man/ipmon.8
@@ -27,7 +27,7 @@ ipmon \- monitors /dev/ipl for logged packets
.LP
\fBipmon\fP opens \fB/dev/ipl\fP for reading and awaits data to be saved from
the packet filter. The binary data read from the device is reprinted in
-human readable for, however, IP#'s are not mapped back to hostnames, nor are
+human readable form, however, IP#'s are not mapped back to hostnames, nor are
ports mapped back to service names. The output goes to standard output by
default or a filename, if given on the command line. Should the \fB\-s\fP
option be used, output is instead sent to \fBsyslogd(8)\fP. Messages sent
diff --git a/contrib/ipfilter/tools/ipmon.c b/contrib/ipfilter/tools/ipmon.c
index 4e4d9cc28f9e..d7ad1a228378 100644
--- a/contrib/ipfilter/tools/ipmon.c
+++ b/contrib/ipfilter/tools/ipmon.c
@@ -1438,7 +1438,10 @@ printipflog:
static void usage(prog)
char *prog;
{
- fprintf(stderr, "%s: [-NFhstvxX] [-f <logfile>]\n", prog);
+ fprintf(stderr, "Usage: %s [ -abDFhnpstvxX ] [ -B <binary-logfile> ] [ -C <config-file> ]\n"
+ "\t[ -f <device> ] [ -L <facility> ] [ -N <device> ]\n"
+ "\t[ -o [NSI] ] [ -O [NSI] ] [ -P <pidfile> ] [ -S <device> ]\n"
+ "\t[ <filename> ]\n", prog);
exit(1);
}
diff --git a/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
index 1fdf74549dec..57244ddff552 100644
--- a/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
+++ b/contrib/llvm/lib/Target/PowerPC/PPCSubtarget.cpp
@@ -138,7 +138,8 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
if (isDarwin())
HasLazyResolverStubs = true;
- if (TargetTriple.isOSNetBSD() || TargetTriple.isOSOpenBSD())
+ if ((TargetTriple.isOSFreeBSD() && TargetTriple.getOSMajorVersion() >= 13)
+ || TargetTriple.isOSNetBSD() || TargetTriple.isOSOpenBSD())
SecurePlt = true;
if (HasSPE && IsPPC64)
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp
index 791f1206cf25..a85ff8d30a2e 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -116,7 +116,8 @@ ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Tripl
const ArgList &Args) {
if (Args.getLastArg(options::OPT_msecure_plt))
return ppc::ReadGOTPtrMode::SecurePlt;
- if (Triple.isOSOpenBSD())
+ if ((Triple.isOSFreeBSD() && Triple.getOSMajorVersion() >= 13) ||
+ Triple.isOSOpenBSD())
return ppc::ReadGOTPtrMode::SecurePlt;
else
return ppc::ReadGOTPtrMode::Bss;
diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist
index b0e305558f1a..b774449a17bf 100644
--- a/etc/mtree/BSD.include.dist
+++ b/etc/mtree/BSD.include.dist
@@ -138,8 +138,6 @@
mpilib
..
..
- nand
- ..
nvme
..
ofw
@@ -184,8 +182,6 @@
..
msdosfs
..
- nandfs
- ..
nfs
..
nullfs
diff --git a/gnu/usr.bin/cc/cc_tools/Makefile.hdrs b/gnu/usr.bin/cc/cc_tools/Makefile.hdrs
index f2576f7fdf0a..dc5bcb7a2d94 100644
--- a/gnu/usr.bin/cc/cc_tools/Makefile.hdrs
+++ b/gnu/usr.bin/cc/cc_tools/Makefile.hdrs
@@ -21,6 +21,9 @@ TARGET_INC+= ${GCC_CPU}/${GCC_CPU}.h
TARGET_INC+= ${GCC_CPU}/unix.h
TARGET_INC+= ${GCC_CPU}/att.h
.endif
+.if ${TARGET_CPUARCH} == "powerpc"
+TARGET_INC+= ${GCC_CPU}/secureplt.h
+.endif
TARGET_INC+= dbxelf.h
TARGET_INC+= elfos-undef.h
TARGET_INC+= elfos.h
diff --git a/include/Makefile b/include/Makefile
index bd0ddc10b492..8893eba97ea9 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -48,7 +48,7 @@ LSUBDIRS= cam/ata cam/mmc cam/nvme cam/scsi \
dev/ic dev/iicbus dev/io dev/mfi dev/mmc dev/nvme \
dev/ofw dev/pbio dev/pci ${_dev_powermac_nvram} dev/ppbus dev/pwm \
dev/smbus dev/speaker dev/tcp_log dev/veriexec dev/vkbd dev/wi \
- fs/devfs fs/fdescfs fs/msdosfs fs/nandfs fs/nfs fs/nullfs \
+ fs/devfs fs/fdescfs fs/msdosfs fs/nfs fs/nullfs \
fs/procfs fs/smbfs fs/udf fs/unionfs \
geom/cache geom/concat geom/eli geom/gate geom/journal geom/label \
geom/mirror geom/mountver geom/multipath geom/nop \
@@ -158,7 +158,7 @@ copies: .PHONY .META
done; \
fi
.endfor
-.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci:Ndev/veriexec} ${LSUBSUBDIRS}
+.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/pci:Ndev/veriexec} ${LSUBSUBDIRS}
cd ${SRCTOP}/sys; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \
${SDESTDIR}${INCLUDEDIR}/$i
@@ -174,13 +174,6 @@ copies: .PHONY .META
cd ${SRCTOP}/sys/dev/bktr; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 ioctl_*.h \
${SDESTDIR}${INCLUDEDIR}/dev/bktr
-.if ${MK_NAND} != "no"
- cd ${SRCTOP}/sys/dev/nand; \
- ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 nandsim.h \
- ${SDESTDIR}${INCLUDEDIR}/dev/nand; \
- ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 nand_dev.h \
- ${SDESTDIR}${INCLUDEDIR}/dev/nand
-.endif
cd ${SRCTOP}/sys/dev/evdev; \
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 input.h \
${SDESTDIR}${INCLUDEDIR}/dev/evdev; \
@@ -268,7 +261,7 @@ symlinks: .PHONY .META
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/$i/$$h ${SDESTDIR}${INCLUDEDIR}/$i; \
done
.endfor
-.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci:Ndev/veriexec}
+.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/pci:Ndev/veriexec}
cd ${SRCTOP}/sys/$i; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/$i/$$h ${SDESTDIR}${INCLUDEDIR}/$i; \
@@ -289,13 +282,6 @@ symlinks: .PHONY .META
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/bktr/$$h \
${SDESTDIR}${INCLUDEDIR}/dev/bktr; \
done
-.if ${MK_NAND} != "no"
- cd ${SRCTOP}/sys/dev/nand; \
- for h in nandsim.h nand_dev.h; do \
- ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/nand/$$h \
- ${SDESTDIR}${INCLUDEDIR}/dev/nand; \
- done
-.endif
cd ${SRCTOP}/sys/dev/evdev; \
for h in input.h input-event-codes.h uinput.h; do \
ln -fs ../../../../sys/dev/evdev/$$h \
diff --git a/lib/Makefile b/lib/Makefile
index f5e89b0712c4..33f31f7f7ed6 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -174,7 +174,6 @@ SUBDIR.${MK_GOOGLETEST}+= googletest
SUBDIR.${MK_LIBTHR}+= libthr
SUBDIR.${MK_LLVM_LIBUNWIND}+= libgcc_eh
SUBDIR.${MK_LLVM_LIBUNWIND}+= libgcc_s
-SUBDIR.${MK_NAND}+= libnandfs
SUBDIR.${MK_NETGRAPH}+= libnetgraph
SUBDIR.${MK_NIS}+= libypclnt
diff --git a/lib/libbe/be_access.c b/lib/libbe/be_access.c
index d3e415bdbd42..9c267bd2f9a6 100644
--- a/lib/libbe/be_access.c
+++ b/lib/libbe/be_access.c
@@ -89,25 +89,31 @@ be_mount_iter(zfs_handle_t *zfs_hdl, void *data)
return (0);
}
- if (zfs_prop_get_int(zfs_hdl, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF)
- return (0);
+ /*
+ * canmount and mountpoint are both ignored for the BE dataset, because
+ * the rest of the system (kernel and loader) will effectively do the
+ * same.
+ */
+ if (info->depth == 0) {
+ snprintf(tmp, BE_MAXPATHLEN, "%s", info->mountpoint);
+ } else {
+ if (zfs_prop_get_int(zfs_hdl, ZFS_PROP_CANMOUNT) ==
+ ZFS_CANMOUNT_OFF)
+ return (0);
- if (zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, zfs_mnt, BE_MAXPATHLEN,
- NULL, NULL, 0, 1))
- return (1);
+ if (zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, zfs_mnt,
+ BE_MAXPATHLEN, NULL, NULL, 0, 1))
+ return (1);
- if (strcmp("none", zfs_mnt) == 0) {
/*
- * mountpoint=none; we'll mount it at info->mountpoint assuming
- * we're at the root. If we're not at the root, we're likely
- * at some intermediate dataset (e.g. zroot/var) that will have
- * children that may need to be mounted.
+ * We've encountered mountpoint=none at some intermediate
+ * dataset (e.g. zroot/var) that will have children that may
+ * need to be mounted. Skip mounting it, but iterate through
+ * the children.
*/
- if (info->depth > 0)
+ if (strcmp("none", zfs_mnt) == 0)
goto skipmount;
- snprintf(tmp, BE_MAXPATHLEN, "%s", info->mountpoint);
- } else {
mountpoint = be_mountpoint_augmented(info->lbh, zfs_mnt);
snprintf(tmp, BE_MAXPATHLEN, "%s%s", info->mountpoint,
mountpoint);
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 9c6b969ea8d3..703cfe796a38 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -338,6 +338,7 @@ FBSD_1.2 {
getutxid;
getutxline;
getutxuser;
+ pthread_getthreadid_np;
pututxline;
sem_close;
sem_destroy;
diff --git a/lib/libc/gen/_pthread_stubs.c b/lib/libc/gen/_pthread_stubs.c
index 89325a39b48a..870cbf2152ee 100644
--- a/lib/libc/gen/_pthread_stubs.c
+++ b/lib/libc/gen/_pthread_stubs.c
@@ -130,6 +130,7 @@ pthread_func_entry_t __thr_jtable[PJT_MAX] = {
{PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_CONSISTENT */
{PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEXATTR_GETROBUST */
{PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEXATTR_SETROBUST */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_GETTHREADID_NP */
};
/*
@@ -248,6 +249,7 @@ STUB_FUNC1(pthread_rwlock_trywrlock, PJT_RWLOCK_TRYWRLOCK, int, void *)
STUB_FUNC1(pthread_rwlock_unlock, PJT_RWLOCK_UNLOCK, int, void *)
STUB_FUNC1(pthread_rwlock_wrlock, PJT_RWLOCK_WRLOCK, int, void *)
STUB_FUNC(pthread_self, PJT_SELF, pthread_t)
+STUB_FUNC(pthread_getthreadid_np, PJT_GETTHREADID_NP, int)
STUB_FUNC2(pthread_setspecific, PJT_SETSPECIFIC, int, pthread_key_t, void *)
STUB_FUNC3(pthread_sigmask, PJT_SIGMASK, int, int, void *, void *)
STUB_FUNC3(pthread_atfork, PJT_ATFORK, int, void *, void *, void*)
diff --git a/lib/libc/gen/libc_dlopen.c b/lib/libc/gen/libc_dlopen.c
index fe28d56f8cb0..5c386b649456 100644
--- a/lib/libc/gen/libc_dlopen.c
+++ b/lib/libc/gen/libc_dlopen.c
@@ -48,8 +48,8 @@ libc_dlopen(const char *path, int mode)
if (__libc_restricted_mode) {
_rtld_error("Service unavailable -- libc in restricted mode");
return (NULL);
- } else
- return (dlopen(path, mode));
+ }
+ return (dlopen(path, mode));
}
void
@@ -57,6 +57,5 @@ __FreeBSD_libc_enter_restricted_mode(void)
{
__libc_restricted_mode = 1;
- return;
}
diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c
index f264dd956a4c..98354e028dc4 100644
--- a/lib/libc/gen/opendir.c
+++ b/lib/libc/gen/opendir.c
@@ -99,8 +99,8 @@ static int
opendir_compar(const void *p1, const void *p2)
{
- return (strcmp((*(const struct dirent **)p1)->d_name,
- (*(const struct dirent **)p2)->d_name));
+ return (strcmp((*(const struct dirent * const *)p1)->d_name,
+ (*(const struct dirent * const *)p2)->d_name));
}
/*
diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c
index 12309cf93266..d801345fc24c 100644
--- a/lib/libc/gen/telldir.c
+++ b/lib/libc/gen/telldir.c
@@ -63,8 +63,8 @@ telldir(DIR *dirp)
* 2) Otherwise, see if it's already been recorded in the linked list
* 3) Otherwise, malloc a new one
*/
- if (dirp->dd_seek < (1ul << DD_SEEK_BITS) &&
- dirp->dd_loc < (1ul << DD_LOC_BITS)) {
+ if (dirp->dd_seek < (off_t)(1l << DD_SEEK_BITS) &&
+ dirp->dd_loc < (1l << DD_LOC_BITS)) {
ddloc.s.is_packed = 1;
ddloc.s.loc = dirp->dd_loc;
ddloc.s.seek = dirp->dd_seek;
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
index 116764b399b9..529ae6b17c41 100644
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -176,6 +176,7 @@ typedef enum {
PJT_MUTEX_CONSISTENT,
PJT_MUTEXATTR_GETROBUST,
PJT_MUTEXATTR_SETROBUST,
+ PJT_GETTHREADID_NP,
PJT_MAX
} pjt_index_t;
diff --git a/lib/libc/powerpc/SYS.h b/lib/libc/powerpc/SYS.h
index 63a5ec47c4b4..e9b6d3226c97 100644
--- a/lib/libc/powerpc/SYS.h
+++ b/lib/libc/powerpc/SYS.h
@@ -44,7 +44,7 @@
#define SYSCALL(name) \
.text; \
.align 2; \
-2: b PIC_PLT(CNAME(HIDENAME(cerror))); \
+2: b CNAME(HIDENAME(cerror)); \
ENTRY(__sys_##name); \
WEAK_REFERENCE(__sys_##name, name); \
WEAK_REFERENCE(__sys_##name, _##name); \
@@ -58,15 +58,14 @@ ENTRY(__sys_##name); \
WEAK_REFERENCE(__sys_##name, _##name); \
_SYSCALL(name); \
bnslr; \
- b PIC_PLT(CNAME(HIDENAME(cerror)))
+ b CNAME(HIDENAME(cerror))
#define RSYSCALL(name) \
.text; \
.align 2; \
-2: b PIC_PLT(CNAME(HIDENAME(cerror))); \
ENTRY(__sys_##name); \
WEAK_REFERENCE(__sys_##name, name); \
WEAK_REFERENCE(__sys_##name, _##name); \
_SYSCALL(name); \
bnslr; \
- b PIC_PLT(CNAME(HIDENAME(cerror)))
+ b CNAME(HIDENAME(cerror))
diff --git a/lib/libc/powerpc/gen/_ctx_start.S b/lib/libc/powerpc/gen/_ctx_start.S
index 4b9fc1d53ae0..70b4a9d91c8c 100644
--- a/lib/libc/powerpc/gen/_ctx_start.S
+++ b/lib/libc/powerpc/gen/_ctx_start.S
@@ -35,11 +35,18 @@
mtlr %r14
blrl /* branch to start function */
mr %r3,%r15 /* pass pointer to ucontext as argument */
- bl PIC_PLT(CNAME(_ctx_done)) /* branch to ctxt completion func */
+ bl CNAME(_ctx_done) /* branch to ctxt completion func */
+
/*
* we should never return from the
* above branch.
*/
+ /* Don't bother saving off %r30, we're already in a bad state. */
+ bcl 20,31,1f
+1: mflr %r30
+ mr %r3,%r30 # save for _DYNAMIC
+ addis %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@ha
+ addi %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@l
bl PIC_PLT(CNAME(abort)) /* abort */
END(_cts_start)
diff --git a/lib/libc/powerpc/sys/cerror.S b/lib/libc/powerpc/sys/cerror.S
index 7667cb8361d3..c2bc994b9c33 100644
--- a/lib/libc/powerpc/sys/cerror.S
+++ b/lib/libc/powerpc/sys/cerror.S
@@ -40,16 +40,27 @@ __FBSDID("$FreeBSD$");
*/
HIDENAME(cerror):
mflr %r0
- stwu %r1,-16(%r1) /* allocate new stack frame */
- stw %r0,20(%r1) /* and save lr, r31 */
- stw %r31,8(%r1)
+ stwu %r1,-20(%r1) /* allocate new stack frame */
+ stw %r0,24(%r1) /* and save lr, r31 */
+ stw %r31,12(%r1)
+#ifdef __PIC__
+ stw %r30,8(%r1)
+ bcl 20,31,1f
+1:
+ mflr %r30
+ addis %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@ha
+ addi %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@l
+#endif
mr %r31,%r3 /* stash errval in callee-saved register */
bl PIC_PLT(CNAME(__error))
stw %r31,0(%r3) /* store errval into &errno */
- lwz %r0,20(%r1)
- lwz %r31,8(%r1)
+ lwz %r0,24(%r1)
+ lwz %r31,12(%r1)
+#ifdef __PIC__
+ lwz %r30,8(%r1)
+#endif
mtlr %r0
- la %r1,16(%r1)
+ la %r1,20(%r1)
li %r3,-1
li %r4,-1
blr /* return to callers caller */
diff --git a/lib/libc/stdlib/realpath.c b/lib/libc/stdlib/realpath.c
index 9b0ba94473cb..99dc388c4db6 100644
--- a/lib/libc/stdlib/realpath.c
+++ b/lib/libc/stdlib/realpath.c
@@ -91,7 +91,7 @@ realpath1(const char *path, char *resolved)
*/
p = strchr(left, '/');
- next_token_len = p != NULL ? p - left : left_len;
+ next_token_len = p != NULL ? (size_t)(p - left) : left_len;
memcpy(next_token, left, next_token_len);
next_token[next_token_len] = '\0';
@@ -146,7 +146,7 @@ realpath1(const char *path, char *resolved)
return (NULL);
}
slen = readlink(resolved, symlink, sizeof(symlink));
- if (slen <= 0 || slen >= sizeof(symlink)) {
+ if (slen <= 0 || slen >= (ssize_t)sizeof(symlink)) {
if (slen < 0)
; /* keep errno from readlink(2) call */
else if (slen == 0)
@@ -173,7 +173,7 @@ realpath1(const char *path, char *resolved)
*/
if (p != NULL) {
if (symlink[slen - 1] != '/') {
- if (slen + 1 >= sizeof(symlink)) {
+ if (slen + 1 >= (ssize_t)sizeof(symlink)) {
errno = ENAMETOOLONG;
return (NULL);
}
diff --git a/lib/libc/sys/mmap.2 b/lib/libc/sys/mmap.2
index 607a0a636352..8a3c7c45f139 100644
--- a/lib/libc/sys/mmap.2
+++ b/lib/libc/sys/mmap.2
@@ -28,7 +28,7 @@
.\" @(#)mmap.2 8.4 (Berkeley) 5/11/95
.\" $FreeBSD$
.\"
-.Dd June 22, 2017
+.Dd June 20, 2019
.Dt MMAP 2
.Os
.Sh NAME
@@ -113,6 +113,22 @@ Pages may be written.
Pages may be executed.
.El
.Pp
+In addition to these protection flags,
+.Fx
+provides the ability to set the maximum protection of a region allocated by
+.Nm
+and later altered by
+.Xr mprotect 2 .
+This is accomplished by
+.Em or Ns 'ing
+one or more
+.Dv PROT_
+values wrapped in the
+.Dv PROT_MAX()
+macro into the
+.Fa prot
+argument.
+.Pp
The
.Fa flags
argument specifies the type of the mapped object, mapping options and
@@ -416,6 +432,11 @@ An invalid value was passed in the
.Fa prot
argument.
.It Bq Er EINVAL
+The
+.Fa prot
+argument contains permissions which are not a subset of the specified
+maximum permissions.
+.It Bq Er EINVAL
An undefined option was set in the
.Fa flags
argument.
@@ -521,3 +542,16 @@ was specified and insufficient memory was available.
.Xr munmap 2 ,
.Xr getpagesize 3 ,
.Xr getpagesizes 3
+.Sh HISTORY
+The
+.Nm
+system call was first documented in
+.Bx 4.2
+and implemented in
+.Bx 4.4 .
+.\" XXX: lots of missing history of FreeBSD additions.
+.Pp
+The
+.Dv PROT_MAX
+functionality was introduced in
+.Fx 13 .
diff --git a/lib/libc/sys/mprotect.2 b/lib/libc/sys/mprotect.2
index 3be81c6582a3..2c165f093861 100644
--- a/lib/libc/sys/mprotect.2
+++ b/lib/libc/sys/mprotect.2
@@ -28,7 +28,7 @@
.\" @(#)mprotect.2 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
-.Dd August 3, 2016
+.Dd June 20, 2019
.Dt MPROTECT 2
.Os
.Sh NAME
@@ -65,6 +65,22 @@ The pages can be written.
.It Dv PROT_EXEC
The pages can be executed.
.El
+.Pp
+In addition to these protection flags,
+.Fx
+provides the ability to set the maximum protection of a region
+(which prevents
+.Nm
+from upgrading the permissions).
+This is accomplished by
+.Em or Ns 'ing
+one or more
+.Dv PROT_
+values wrapped in the
+.Dv PROT_MAX()
+macro into the
+.Fa prot
+argument.
.Sh RETURN VALUES
.Rv -std mprotect
.Sh ERRORS
@@ -78,6 +94,15 @@ The virtual address range specified by the
and
.Fa len
arguments is not valid.
+.It Bq Er EINVAL
+The
+.Fa prot
+argument contains unhandled bits.
+.It Bq Er EINVAL
+The
+.Fa prot
+argument contains permissions which are not a subset of the specified
+maximum permissions.
.It Bq Er EACCES
The calling process was not allowed to change
the protection to the value specified by
@@ -93,5 +118,12 @@ argument.
.Sh HISTORY
The
.Fn mprotect
-system call first appeared in
+system call was first documented in
+.Bx 4.2
+and first appeared in
.Bx 4.4 .
+.Pp
+The
+.Dv PROT_MAX
+functionality was introduced in
+.Fx 13 .
diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c
index ad05f5273f2c..6a35cdc6dde5 100644
--- a/lib/libjail/jail.c
+++ b/lib/libjail/jail.c
@@ -30,7 +30,6 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/types.h>
#include <sys/jail.h>
#include <sys/linker.h>
#include <sys/socket.h>
diff --git a/lib/libnandfs/Makefile b/lib/libnandfs/Makefile
deleted file mode 100644
index e900c3c6eab4..000000000000
--- a/lib/libnandfs/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# $FreeBSD$
-
-PACKAGE=lib${LIB}
-LIB= nandfs
-SRCS+= nandfs.c
-INCS= libnandfs.h
-
-CFLAGS += -I${.CURDIR}
-
-.include <bsd.lib.mk>
diff --git a/lib/libnandfs/Makefile.depend b/lib/libnandfs/Makefile.depend
deleted file mode 100644
index 6cfaab1c3644..000000000000
--- a/lib/libnandfs/Makefile.depend
+++ /dev/null
@@ -1,17 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/lib/libnandfs/libnandfs.h b/lib/libnandfs/libnandfs.h
deleted file mode 100644
index 53cd04946d0e..000000000000
--- a/lib/libnandfs/libnandfs.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _LIBNANDFS_NANDFS_H
-#define _LIBNANDFS_NANDFS_H
-
-struct nandfs {
- struct nandfs_fsdata n_fsdata;
- struct nandfs_super_block n_sb;
- char n_ioc[MNAMELEN];
- char n_dev[MNAMELEN];
- int n_iocfd;
- int n_devfd;
- int n_flags;
- char n_errmsg[120];
-};
-
-int nandfs_iserror(struct nandfs *);
-const char *nandfs_errmsg(struct nandfs *);
-
-void nandfs_init(struct nandfs *, const char *);
-void nandfs_destroy(struct nandfs *);
-
-const char *nandfs_dev(struct nandfs *);
-
-int nandfs_open(struct nandfs *);
-void nandfs_close(struct nandfs *);
-
-int nandfs_get_cpstat(struct nandfs *, struct nandfs_cpstat *);
-
-ssize_t nandfs_get_cp(struct nandfs *, uint64_t,
- struct nandfs_cpinfo *, size_t);
-
-ssize_t nandfs_get_snap(struct nandfs *, uint64_t,
- struct nandfs_cpinfo *, size_t);
-
-int nandfs_make_snap(struct nandfs *, uint64_t *);
-int nandfs_delete_snap(struct nandfs *, uint64_t);
-
-#endif /* _LIBNANDFS_NANDFS_H */
diff --git a/lib/libnandfs/nandfs.c b/lib/libnandfs/nandfs.c
deleted file mode 100644
index f1dd771ae8fd..000000000000
--- a/lib/libnandfs/nandfs.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <sys/stdint.h>
-#include <sys/ucred.h>
-#include <sys/disk.h>
-#include <sys/mount.h>
-
-#include <fs/nandfs/nandfs_fs.h>
-#include <libnandfs.h>
-
-#define NANDFS_IS_VALID 0x1
-#define NANDFS_IS_OPENED 0x2
-#define NANDFS_IS_OPENED_DEV 0x4
-#define NANDFS_IS_ERROR 0x8
-
-#define DEBUG
-#undef DEBUG
-#ifdef DEBUG
-#define NANDFS_DEBUG(fmt, args...) do { \
- printf("libnandfs:" fmt "\n", ##args); } while (0)
-#else
-#define NANDFS_DEBUG(fmt, args...)
-#endif
-
-#define NANDFS_ASSERT_VALID(fs) assert((fs)->n_flags & NANDFS_IS_VALID)
-#define NANDFS_ASSERT_VALID_DEV(fs) \
- assert(((fs)->n_flags & (NANDFS_IS_VALID | NANDFS_IS_OPENED_DEV)) == \
- (NANDFS_IS_VALID | NANDFS_IS_OPENED_DEV))
-
-int
-nandfs_iserror(struct nandfs *fs)
-{
-
- NANDFS_ASSERT_VALID(fs);
-
- return (fs->n_flags & NANDFS_IS_ERROR);
-}
-
-const char *
-nandfs_errmsg(struct nandfs *fs)
-{
-
- NANDFS_ASSERT_VALID(fs);
-
- assert(nandfs_iserror(fs));
- assert(fs->n_errmsg);
- return (fs->n_errmsg);
-}
-
-static void
-nandfs_seterr(struct nandfs *fs, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(fs->n_errmsg, sizeof(fs->n_errmsg), fmt, ap);
- va_end(ap);
- fs->n_flags |= NANDFS_IS_ERROR;
-}
-
-const char *
-nandfs_dev(struct nandfs *fs)
-{
-
- NANDFS_ASSERT_VALID(fs);
- return (fs->n_dev);
-}
-
-void
-nandfs_init(struct nandfs *fs, const char *dir)
-{
-
- snprintf(fs->n_ioc, sizeof(fs->n_ioc), "%s/%s", dir, ".");
- fs->n_iocfd = -1;
- fs->n_flags = NANDFS_IS_VALID;
-}
-
-void
-nandfs_destroy(struct nandfs *fs)
-{
-
- assert(fs->n_iocfd == -1);
- fs->n_flags &=
- ~(NANDFS_IS_ERROR | NANDFS_IS_VALID);
- assert(fs->n_flags == 0);
-}
-
-int
-nandfs_open(struct nandfs *fs)
-{
- struct nandfs_fsinfo fsinfo;
-
- fs->n_flags |= NANDFS_IS_OPENED;
-
- fs->n_iocfd = open(fs->n_ioc, O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP |
- S_IWGRP | S_IROTH | S_IWOTH);
- if (fs->n_iocfd == -1) {
- nandfs_seterr(fs, "couldn't open %s: %s", fs->n_ioc,
- strerror(errno));
- return (-1);
- }
-
- if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_FSINFO, &fsinfo) == -1) {
- nandfs_seterr(fs, "couldn't fetch fsinfo: %s",
- strerror(errno));
- return (-1);
- }
-
- memcpy(&fs->n_fsdata, &fsinfo.fs_fsdata, sizeof(fs->n_fsdata));
- memcpy(&fs->n_sb, &fsinfo.fs_super, sizeof(fs->n_sb));
- snprintf(fs->n_dev, sizeof(fs->n_dev), "%s", fsinfo.fs_dev);
-
- return (0);
-}
-
-void
-nandfs_close(struct nandfs *fs)
-{
-
- NANDFS_ASSERT_VALID(fs);
- assert(fs->n_flags & NANDFS_IS_OPENED);
-
- close(fs->n_iocfd);
- fs->n_iocfd = -1;
- fs->n_flags &= ~NANDFS_IS_OPENED;
-}
-
-int
-nandfs_get_cpstat(struct nandfs *fs, struct nandfs_cpstat *cpstat)
-{
-
- NANDFS_ASSERT_VALID(fs);
-
- if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_CPSTAT, cpstat) == -1) {
- nandfs_seterr(fs, "ioctl NANDFS_IOCTL_GET_CPSTAT: %s",
- strerror(errno));
- return (-1);
- }
-
- return (0);
-}
-
-static ssize_t
-nandfs_get_cpinfo(struct nandfs *fs, uint64_t cno, int mode,
- struct nandfs_cpinfo *cpinfo, size_t nci)
-{
- struct nandfs_argv args;
-
- NANDFS_ASSERT_VALID(fs);
-
- args.nv_base = (u_long)cpinfo;
- args.nv_nmembs = nci;
- args.nv_index = cno;
- args.nv_flags = mode;
-
- if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_CPINFO, &args) == -1) {
- nandfs_seterr(fs, "ioctl NANDFS_IOCTL_GET_CPINFO: %s",
- strerror(errno));
- return (-1);
- }
-
- return (args.nv_nmembs);
-}
-
-ssize_t
-nandfs_get_cp(struct nandfs *fs, uint64_t cno, struct nandfs_cpinfo *cpinfo,
- size_t nci)
-{
-
- return (nandfs_get_cpinfo(fs, cno, NANDFS_CHECKPOINT, cpinfo, nci));
-}
-
-ssize_t
-nandfs_get_snap(struct nandfs *fs, uint64_t cno, struct nandfs_cpinfo *cpinfo,
- size_t nci)
-{
-
- return (nandfs_get_cpinfo(fs, cno, NANDFS_SNAPSHOT, cpinfo, nci));
-}
-
-int
-nandfs_make_snap(struct nandfs *fs, uint64_t *cno)
-{
-
- NANDFS_ASSERT_VALID(fs);
-
- if (ioctl(fs->n_iocfd, NANDFS_IOCTL_MAKE_SNAP, cno) == -1) {
- nandfs_seterr(fs, "ioctl NANDFS_IOCTL_MAKE_SNAP: %s",
- strerror(errno));
- return (-1);
- }
-
- return (0);
-}
-
-int
-nandfs_delete_snap(struct nandfs *fs, uint64_t cno)
-{
-
- NANDFS_ASSERT_VALID(fs);
-
- if (ioctl(fs->n_iocfd, NANDFS_IOCTL_DELETE_SNAP, &cno) == -1) {
- nandfs_seterr(fs, "ioctl NANDFS_IOCTL_DELETE_SNAP: %s",
- strerror(errno));
- return (-1);
- }
-
- return (0);
-}
diff --git a/lib/libsecureboot/h/libsecureboot.h b/lib/libsecureboot/h/libsecureboot.h
index 81984fde5f3e..d7d72e880744 100644
--- a/lib/libsecureboot/h/libsecureboot.h
+++ b/lib/libsecureboot/h/libsecureboot.h
@@ -42,6 +42,7 @@
#include <bearssl.h>
+unsigned char * read_fd(int, size_t);
#ifndef NEED_BRSSL_H
unsigned char * read_file(const char *, size_t *);
#endif
@@ -51,8 +52,12 @@ extern int DebugVe;
#define DEBUG_PRINTF(n, x) if (DebugVe >= n) printf x
int ve_trust_init(void);
+size_t ve_trust_anchors_add_buf(unsigned char *, size_t);
+size_t ve_trust_anchors_revoke(unsigned char *, size_t);
int ve_trust_add(const char *);
void ve_debug_set(int);
+void ve_anchor_verbose_set(int);
+int ve_anchor_verbose_get(void);
void ve_utc_set(time_t utc);
char *ve_error_get(void);
int ve_error_set(const char *, ...) __printflike(1,2);
diff --git a/lib/libsecureboot/libsecureboot-priv.h b/lib/libsecureboot/libsecureboot-priv.h
index c6a90d2c7404..bdf0c5c0c9bb 100644
--- a/lib/libsecureboot/libsecureboot-priv.h
+++ b/lib/libsecureboot/libsecureboot-priv.h
@@ -56,6 +56,8 @@ int is_verified(struct stat *stp);
void add_verify_status(struct stat *stp, int status);
int openpgp_trust_init(void);
+int openpgp_trust_add_buf(unsigned char *, size_t);
+int openpgp_trust_revoke(const char *);
int openpgp_self_tests(void);
int efi_secure_boot_enabled(void);
diff --git a/lib/libsecureboot/local.trust.mk b/lib/libsecureboot/local.trust.mk
index 4ba4c862e929..b28e5ee2d1ef 100644
--- a/lib/libsecureboot/local.trust.mk
+++ b/lib/libsecureboot/local.trust.mk
@@ -33,6 +33,10 @@ VE_SIGNATURE_EXT_LIST+= \
sig
.endif
+# add OpenPGP support - possibly dormant
+VE_SIGNATURE_LIST+= OPENPGP
+VE_SIGNATURE_EXT_LIST+= asc
+
SIGNER ?= ${SB_TOOLS_PATH:U/volume/buildtools/bin}/sign.py
.if exists(${SIGNER})
@@ -42,7 +46,12 @@ SIGN_ECDSA= ${PYTHON} ${SIGNER} -u ${SIGN_HOST}:${ECDSA_PORT} -h sha256
RSA2_PORT:= ${163%y:L:gmtime}
SIGN_RSA2= ${PYTHON} ${SIGNER} -u ${SIGN_HOST}:${RSA2_PORT} -h sha256
+# deal with quirk of our .esig format
+XCFLAGS.vets+= -DVE_ECDSA_HASH_AGAIN
+
.if !empty(OPENPGP_SIGN_URL)
+XCFLAGS.opgp_key+= -DHAVE_TA_ASC_H
+
VE_SIGNATURE_LIST+= OPENPGP
VE_SIGNATURE_EXT_LIST+= asc
diff --git a/lib/libsecureboot/openpgp/opgp_key.c b/lib/libsecureboot/openpgp/opgp_key.c
index dc0d8fa2934d..c108cd2fa328 100644
--- a/lib/libsecureboot/openpgp/opgp_key.c
+++ b/lib/libsecureboot/openpgp/opgp_key.c
@@ -209,13 +209,54 @@ openpgp_trust_add(OpenPGP_key *key)
LIST_INIT(&trust_list);
}
- if (key) {
- DEBUG_PRINTF(2, ("openpgp_trust_add(%s)\n", key->id));
+ if (key && openpgp_trust_get(key->id) == NULL) {
+ if (ve_anchor_verbose_get())
+ printf("openpgp_trust_add(%s)\n", key->id);
LIST_INSERT_HEAD(&trust_list, key, entries);
}
}
/**
+ * @brief add trust anchor from buf
+ */
+int
+openpgp_trust_add_buf(unsigned char *buf, size_t nbytes)
+{
+ OpenPGP_key *key;
+
+ if ((key = load_key_buf(buf, nbytes))) {
+ openpgp_trust_add(key);
+ }
+ return (key != NULL);
+}
+
+
+/**
+ * @brief if keyID is in our list clobber it
+ *
+ * @return true if keyID removed
+ */
+int
+openpgp_trust_revoke(const char *keyID)
+{
+ OpenPGP_key *key, *tkey;
+
+ openpgp_trust_add(NULL); /* initialize if needed */
+
+ LIST_FOREACH(key, &trust_list, entries) {
+ if (strcmp(key->id, keyID) == 0) {
+ tkey = key;
+ LIST_REMOVE(tkey, entries);
+ printf("openpgp_trust_revoke(%s)\n", key->id);
+ memset(key, 0, sizeof(OpenPGP_key));
+ free(key);
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/**
* @brief if keyID is in our list return the key
*
* @return key or NULL
@@ -251,7 +292,9 @@ load_key_file(const char *kfile)
return (key);
}
+#ifdef HAVE_TA_ASC_H
#include <ta_asc.h>
+#endif
#ifndef _STANDALONE
/* we can lookup keyID in filesystem */
@@ -330,8 +373,8 @@ openpgp_trust_init(void)
}
}
}
- }
#endif
+ }
return (once);
}
diff --git a/lib/libsecureboot/readfile.c b/lib/libsecureboot/readfile.c
index f632922143ce..ff9f9f6f6d60 100644
--- a/lib/libsecureboot/readfile.c
+++ b/lib/libsecureboot/readfile.c
@@ -28,21 +28,13 @@ __FBSDID("$FreeBSD$");
#include <libsecureboot.h>
unsigned char *
-read_file(const char *path, size_t *len)
+read_fd(int fd, size_t len)
{
- int fd, m, n, x;
- struct stat st;
+ int m, n, x;
unsigned char *buf;
- if (len)
- *len = 0;
- if ((fd = open(path, O_RDONLY)) < 0)
- return (NULL);
- fstat(fd, &st);
- if (len)
- *len = st.st_size;
- buf = malloc(st.st_size + 1);
- for (x = 0, m = st.st_size; m > 0; ) {
+ buf = malloc(len + 1);
+ for (x = 0, m = len; m > 0; ) {
n = read(fd, &buf[x], m);
if (n < 0)
break;
@@ -51,11 +43,30 @@ read_file(const char *path, size_t *len)
x += n;
}
}
- close(fd);
if (m == 0) {
- buf[st.st_size] = '\0';
+ buf[len] = '\0';
return (buf);
}
free(buf);
return (NULL);
}
+
+unsigned char *
+read_file(const char *path, size_t *len)
+{
+ struct stat st;
+ unsigned char *ucp;
+ int fd;
+
+ if (len)
+ *len = 0;
+ if ((fd = open(path, O_RDONLY)) < 0)
+ return (NULL);
+ fstat(fd, &st);
+ ucp = read_fd(fd, st.st_size);
+ close(fd);
+ if (len != NULL && ucp != NULL)
+ *len = st.st_size;
+ return (ucp);
+}
+
diff --git a/lib/libsecureboot/verify_file.c b/lib/libsecureboot/verify_file.c
index e8b00451133f..bb092dda2ed2 100644
--- a/lib/libsecureboot/verify_file.c
+++ b/lib/libsecureboot/verify_file.c
@@ -246,7 +246,9 @@ severity_guess(const char *filename)
}
static void
-verify_tweak(char *tweak, int *accept_no_fp, int *verbose, int *verifying)
+verify_tweak(int fd, off_t off, struct stat *stp,
+ char *tweak, int *accept_no_fp,
+ int *verbose, int *verifying)
{
if (strcmp(tweak, "off") == 0) {
*verifying = 0;
@@ -268,6 +270,25 @@ verify_tweak(char *tweak, int *accept_no_fp, int *verbose, int *verifying)
*verbose = 1;
} else if (strcmp(tweak, "quiet") == 0) {
*verbose = 0;
+ } else if (strncmp(tweak, "trust", 5) == 0) {
+ /* content is trust anchor to add or revoke */
+ unsigned char *ucp;
+ size_t num;
+
+ if (off > 0)
+ lseek(fd, 0, SEEK_SET);
+ ucp = read_fd(fd, stp->st_size);
+ if (ucp == NULL)
+ return;
+ if (strstr(tweak, "revoke")) {
+ num = ve_trust_anchors_revoke(ucp, stp->st_size);
+ DEBUG_PRINTF(3, ("revoked %d trust anchors\n",
+ (int) num));
+ } else {
+ num = ve_trust_anchors_add_buf(ucp, stp->st_size);
+ DEBUG_PRINTF(3, ("added %d trust anchors\n",
+ (int) num));
+ }
}
}
@@ -317,8 +338,10 @@ verify_file(int fd, const char *filename, off_t off, int severity)
rc = verifying ? VE_NOT_CHECKED : VE_NOT_VERIFYING;
ve_status_set(0, rc);
ve_status_state = VE_STATUS_NONE;
- if (verifying)
+ if (verifying) {
ve_self_tests();
+ ve_anchor_verbose_set(1);
+ }
}
if (!verifying)
return (0);
@@ -367,7 +390,7 @@ verify_file(int fd, const char *filename, off_t off, int severity)
cp++;
if (strncmp(cp, "loader.ve.", 10) == 0) {
cp += 10;
- verify_tweak(cp,
+ verify_tweak(fd, off, &st, cp,
&accept_no_fp, &verbose,
&verifying);
}
diff --git a/lib/libsecureboot/vets.c b/lib/libsecureboot/vets.c
index 73e3db7722d5..87fb190577eb 100644
--- a/lib/libsecureboot/vets.c
+++ b/lib/libsecureboot/vets.c
@@ -55,6 +55,20 @@ static anchor_list trust_anchors = VEC_INIT;
static anchor_list forbidden_anchors = VEC_INIT;
static digest_list forbidden_digests = VEC_INIT;
+static int anchor_verbose = 0;
+
+void
+ve_anchor_verbose_set(int n)
+{
+ anchor_verbose = n;
+}
+
+int
+ve_anchor_verbose_get(void)
+{
+ return (anchor_verbose);
+}
+
void
ve_debug_set(int n)
{
@@ -116,6 +130,47 @@ free_cert_contents(br_x509_certificate *xc)
xfree(xc->data);
}
+/*
+ * a bit of a dance to get commonName from a certificate
+ */
+static char *
+x509_cn_get(br_x509_certificate *xc, char *buf, size_t len)
+{
+ br_x509_minimal_context mc;
+ br_name_element cn;
+ unsigned char cn_oid[4];
+ int err;
+
+ if (buf == NULL)
+ return (buf);
+ /*
+ * We want the commonName field
+ * the OID we want is 2,5,4,3 - but DER encoded
+ */
+ cn_oid[0] = 3;
+ cn_oid[1] = 0x55;
+ cn_oid[2] = 4;
+ cn_oid[3] = 3;
+ cn.oid = cn_oid;
+ cn.buf = buf;
+ cn.len = len;
+ cn.buf[0] = '\0';
+
+ br_x509_minimal_init(&mc, &br_sha256_vtable, NULL, 0);
+ br_x509_minimal_set_name_elements(&mc, &cn, 1);
+ /* the below actually does the work - updates cn.status */
+ mc.vtable->start_chain(&mc.vtable, NULL);
+ mc.vtable->start_cert(&mc.vtable, xc->data_len);
+ mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
+ mc.vtable->end_cert(&mc.vtable);
+ /* we don' actually care about cert status - just its name */
+ err = mc.vtable->end_chain(&mc.vtable);
+
+ if (!cn.status)
+ buf = NULL;
+ return (buf);
+}
+
/* ASN parsing related defines */
#define ASN1_PRIMITIVE_TAG 0x1F
#define ASN1_INF_LENGTH 0x80
@@ -184,7 +239,8 @@ ve_forbidden_digest_add(hash_data *digest, size_t num)
}
static size_t
-ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors)
+ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors,
+ char *anchors_name)
{
br_x509_trust_anchor ta;
size_t u;
@@ -194,6 +250,15 @@ ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors)
break;
}
VEC_ADD(*anchors, ta);
+ if (anchor_verbose && anchors_name) {
+ char buf[64];
+ char *cp;
+
+ cp = x509_cn_get(&xcs[u], buf, sizeof(buf));
+ if (cp) {
+ printf("x509_anchor(%s) %s\n", cp, anchors_name);
+ }
+ }
}
return (u);
}
@@ -205,13 +270,68 @@ ve_anchors_add(br_x509_certificate *xcs, size_t num, anchor_list *anchors)
size_t
ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
{
- return (ve_anchors_add(xcs, num, &trust_anchors));
+ return (ve_anchors_add(xcs, num, &trust_anchors, "trusted"));
}
size_t
ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
{
- return (ve_anchors_add(xcs, num, &forbidden_anchors));
+ return (ve_anchors_add(xcs, num, &forbidden_anchors, "forbidden"));
+}
+
+
+/**
+ * @brief add trust anchors in buf
+ *
+ * Assume buf contains x509 certificates, but if not and
+ * we support OpenPGP try adding as that.
+ *
+ * @return number of anchors added
+ */
+size_t
+ve_trust_anchors_add_buf(unsigned char *buf, size_t len)
+{
+ br_x509_certificate *xcs;
+ size_t num;
+
+ num = 0;
+ xcs = parse_certificates(buf, len, &num);
+ if (xcs != NULL) {
+ num = ve_trust_anchors_add(xcs, num);
+#ifdef VE_OPENPGP_SUPPORT
+ } else {
+ num = openpgp_trust_add_buf(buf, len);
+#endif
+ }
+ return (num);
+}
+
+/**
+ * @brief revoke trust anchors in buf
+ *
+ * Assume buf contains x509 certificates, but if not and
+ * we support OpenPGP try revoking keyId
+ *
+ * @return number of anchors revoked
+ */
+size_t
+ve_trust_anchors_revoke(unsigned char *buf, size_t len)
+{
+ br_x509_certificate *xcs;
+ size_t num;
+
+ num = 0;
+ xcs = parse_certificates(buf, len, &num);
+ if (xcs != NULL) {
+ num = ve_forbidden_anchors_add(xcs, num);
+#ifdef VE_OPENPGP_SUPPORT
+ } else {
+ if (buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+ num = openpgp_trust_revoke((char *)buf);
+#endif
+ }
+ return (num);
}
/**
@@ -221,11 +341,7 @@ ve_forbidden_anchors_add(br_x509_certificate *xcs, size_t num)
int
ve_trust_init(void)
{
-#ifdef TRUST_ANCHOR_STR
- br_x509_certificate *xcs;
-#endif
static int once = -1;
- size_t num;
if (once >= 0)
return (once);
@@ -240,10 +356,8 @@ ve_trust_init(void)
#endif
#ifdef TRUST_ANCHOR_STR
- xcs = parse_certificates(__DECONST(unsigned char *, TRUST_ANCHOR_STR),
- sizeof(TRUST_ANCHOR_STR), &num);
- if (xcs != NULL)
- num = ve_trust_anchors_add(xcs, num);
+ ve_trust_anchors_add_buf(__DECONST(unsigned char *, TRUST_ANCHOR_STR),
+ sizeof(TRUST_ANCHOR_STR));
#endif
once = (int) VEC_LEN(trust_anchors);
#ifdef VE_OPENPGP_SUPPORT
@@ -552,6 +666,7 @@ verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
br_sha256_init(&ctx);
br_sha256_update(&ctx, fcp, flen);
br_sha256_out(&ctx, rhbuf);
+#ifdef VE_ECDSA_HASH_AGAIN
hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE);
/* now hash that */
if (hex) {
@@ -559,6 +674,7 @@ verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
br_sha256_update(&ctx, hex, strlen(hex));
br_sha256_out(&ctx, rhbuf);
}
+#endif
ec = br_ec_get_default();
vrfy = br_ecdsa_vrfy_asn1_get_default();
if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data,
diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c
index 1568529e8c51..7b043a38b1f2 100644
--- a/lib/libthr/thread/thr_init.c
+++ b/lib/libthr/thread/thr_init.c
@@ -272,6 +272,7 @@ static pthread_func_t jmp_table[][2] = {
{DUAL_ENTRY(_pthread_mutex_consistent)},/* PJT_MUTEX_CONSISTENT */
{DUAL_ENTRY(_pthread_mutexattr_getrobust)},/* PJT_MUTEXATTR_GETROBUST */
{DUAL_ENTRY(_pthread_mutexattr_setrobust)},/* PJT_MUTEXATTR_SETROBUST */
+ {DUAL_ENTRY(_pthread_getthreadid_np)}, /* PJT_GETTHREADID_NP */
};
static int init_once = 0;
diff --git a/lib/libusb/libusb10.h b/lib/libusb/libusb10.h
index c3deb562c6d4..5caa56666c32 100644
--- a/lib/libusb/libusb10.h
+++ b/lib/libusb/libusb10.h
@@ -89,6 +89,8 @@ struct libusb_hotplug_callback_handle_struct {
void *user_data;
};
+TAILQ_HEAD(libusb_device_head, libusb_device);
+
struct libusb_context {
int debug;
int debug_fixed;
@@ -106,7 +108,7 @@ struct libusb_context {
TAILQ_HEAD(, libusb_super_pollfd) pollfds;
TAILQ_HEAD(, libusb_super_transfer) tr_done;
TAILQ_HEAD(, libusb_hotplug_callback_handle_struct) hotplug_cbh;
- TAILQ_HEAD(, libusb_device) hotplug_devs;
+ struct libusb_device_head hotplug_devs;
struct libusb_super_pollfd ctx_poll;
diff --git a/lib/libusb/libusb10_hotplug.c b/lib/libusb/libusb10_hotplug.c
index 162cf2bbb5af..96e3bf9a12ca 100644
--- a/lib/libusb/libusb10_hotplug.c
+++ b/lib/libusb/libusb10_hotplug.c
@@ -1,6 +1,6 @@
/* $FreeBSD$ */
/*-
- * Copyright (c) 2016 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2016-2019 Hans Petter Selasky. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -85,20 +85,35 @@ libusb_hotplug_filter(libusb_context *ctx, libusb_hotplug_callback_handle pcbh,
return (pcbh->fn(ctx, dev, event, pcbh->user_data));
}
+static int
+libusb_hotplug_enumerate(libusb_context *ctx, struct libusb_device_head *phead)
+{
+ libusb_device **ppdev;
+ ssize_t count;
+ ssize_t x;
+
+ count = libusb_get_device_list(ctx, &ppdev);
+ if (count < 0)
+ return (-1);
+
+ for (x = 0; x != count; x++)
+ TAILQ_INSERT_TAIL(phead, ppdev[x], hotplug_entry);
+
+ libusb_free_device_list(ppdev, 0);
+ return (0);
+}
+
static void *
libusb_hotplug_scan(void *arg)
{
- TAILQ_HEAD(, libusb_device) hotplug_devs;
+ struct libusb_device_head hotplug_devs;
libusb_hotplug_callback_handle acbh;
libusb_hotplug_callback_handle bcbh;
libusb_context *ctx = arg;
- libusb_device **ppdev;
libusb_device *temp;
libusb_device *adev;
libusb_device *bdev;
unsigned do_loop = 1;
- ssize_t count;
- ssize_t x;
while (do_loop) {
usleep(4000000);
@@ -108,14 +123,8 @@ libusb_hotplug_scan(void *arg)
TAILQ_INIT(&hotplug_devs);
if (ctx->hotplug_handler != NO_THREAD) {
- count = libusb_get_device_list(ctx, &ppdev);
- if (count < 0)
+ if (libusb_hotplug_enumerate(ctx, &hotplug_devs) < 0)
continue;
- for (x = 0; x != count; x++) {
- TAILQ_INSERT_TAIL(&hotplug_devs, ppdev[x],
- hotplug_entry);
- }
- libusb_free_device_list(ppdev, 0);
} else {
do_loop = 0;
}
@@ -191,6 +200,8 @@ int libusb_hotplug_register_callback(libusb_context *ctx,
HOTPLUG_LOCK(ctx);
if (ctx->hotplug_handler == NO_THREAD) {
+ libusb_hotplug_enumerate(ctx, &ctx->hotplug_devs);
+
if (pthread_create(&ctx->hotplug_handler, NULL,
&libusb_hotplug_scan, ctx) != 0)
ctx->hotplug_handler = NO_THREAD;
diff --git a/libexec/rc/rc.d/motd b/libexec/rc/rc.d/motd
index acb376723e80..2c06187c1d2a 100755
--- a/libexec/rc/rc.d/motd
+++ b/libexec/rc/rc.d/motd
@@ -37,11 +37,15 @@ motd_start()
uname -v | sed -e 's,^\([^#]*\) #\(.* [1-2][0-9][0-9][0-9]\).*/\([^\]*\) $,\1 (\3) #\2,' > ${T}
awk '{if (NR == 1) {if ($1 == "FreeBSD") {next} else {print "\n"$0}} else {print}}' < /etc/motd >> ${T}
- cmp -s $T /etc/motd || {
- cp $T /etc/motd
+ if ! cmp -s $T /etc/motd; then
+ mv -f $T /etc/.motd.tmp
+ fsync /etc/.motd.tmp
+ mv -f /etc/.motd.tmp /etc/motd
chmod ${PERMS} /etc/motd
- }
- rm -f $T
+ fsync /etc
+ else
+ rm -f $T
+ fi
check_startmsgs && echo '.'
}
diff --git a/libexec/rtld-elf/debug.h b/libexec/rtld-elf/debug.h
index 1ad0323b42f9..4dcefbabdb45 100644
--- a/libexec/rtld-elf/debug.h
+++ b/libexec/rtld-elf/debug.h
@@ -37,7 +37,7 @@
#include <sys/cdefs.h>
#include <string.h>
-#include <unistd.h>
+#include "rtld_printf.h"
void debug_printf(const char *, ...) __printflike(1, 2);
extern int debug;
@@ -57,7 +57,7 @@ extern int debug;
#define assert(cond) ((cond) ? (void) 0 : \
(msg(_MYNAME ": assert failed: " __FILE__ ":" \
__XSTRING(__LINE__) "\n"), abort()))
-#define msg(s) write(STDOUT_FILENO, s, strlen(s))
+#define msg(s) rtld_putstr(s)
#define trace() msg(_MYNAME ": " __XSTRING(__LINE__) "\n")
diff --git a/libexec/rtld-elf/powerpc/reloc.c b/libexec/rtld-elf/powerpc/reloc.c
index 382417ca3490..c923c7326079 100644
--- a/libexec/rtld-elf/powerpc/reloc.c
+++ b/libexec/rtld-elf/powerpc/reloc.c
@@ -57,6 +57,8 @@
#define JMPTAB_BASE(N) (18 + N*2 + ((N > PLT_EXTENDED_BEGIN) ? \
(N - PLT_EXTENDED_BEGIN)*2 : 0))
+void _rtld_bind_secureplt_start(void);
+
/*
* Process the R_PPC_COPY relocations
*/
@@ -361,6 +363,11 @@ reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela)
if (reloff < 0)
return (-1);
+ if (obj->gotptr != NULL) {
+ *where += (Elf_Addr)obj->relocbase;
+ return (0);
+ }
+
pltlongresolve = obj->pltgot + 5;
pltresolve = pltlongresolve + 5;
@@ -425,7 +432,7 @@ reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused)
* Sync the icache for the byte range represented by the
* trampoline routines and call slots.
*/
- if (obj->pltgot != NULL)
+ if (obj->pltgot != NULL && obj->gotptr == NULL)
__syncicache(obj->pltgot, JMPTAB_BASE(N)*4);
return (0);
@@ -501,6 +508,14 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target,
*/
offset = target - (Elf_Addr)wherep;
+ if (obj->gotptr != NULL) {
+ assert(wherep >= (Elf_Word *)obj->pltgot);
+ assert(wherep <
+ (Elf_Word *)obj->pltgot + obj->pltrelasize);
+ *wherep = target;
+ goto out;
+ }
+
if (abs((int)offset) < 32*1024*1024) { /* inside 32MB? */
/* b value # branch directly */
*wherep = 0x48000000 | (offset & 0x03fffffc);
@@ -579,6 +594,16 @@ init_pltgot(Obj_Entry *obj)
return;
}
+ /* Handle Secure-PLT first, if applicable. */
+ if (obj->gotptr != NULL) {
+ obj->gotptr[1] = (Elf_Addr)_rtld_bind_secureplt_start;
+ obj->gotptr[2] = (Elf_Addr)obj;
+ dbg("obj %s secure-plt gotptr=%p start=%p obj=%p",
+ obj->path, obj->gotptr,
+ (void *)obj->gotptr[1], (void *)obj->gotptr[2]);
+ return;
+ }
+
/*
* From the SVR4 PPC ABI:
*
diff --git a/libexec/rtld-elf/powerpc/rtld_start.S b/libexec/rtld-elf/powerpc/rtld_start.S
index 28ec19bad110..5a2cd7bd2652 100644
--- a/libexec/rtld-elf/powerpc/rtld_start.S
+++ b/libexec/rtld-elf/powerpc/rtld_start.S
@@ -52,35 +52,22 @@ _ENTRY(.rtld_start)
* - use link-time constants to determine offset to the
* _DYNAMIC section and the GOT. Add these to the PC to
* convert to absolute addresses.
- * - sync icache to allow execution of the SVR4 ABI-specified
- * blrl instruction preceding the GOT
- * - Use this instruction to determine the GOT absolute address
* - read GOT[0], which is the SVR4 ABI-specified link-time
* value of _DYNAMIC. Subtract this value from the absolute
* value to determine the load address
* - call reloc_non_plt_self() to fix up ld-elf.so's relocations
*/
- bl 1f
- .long _DYNAMIC-.
- .long _GLOBAL_OFFSET_TABLE_-. /* branch lr + 4 */
-1:
- mflr %r3 /* PC value at .long */
- lwz %r4,4(%r3)
- add %r4,%r4,%r3 /* &_GLOBAL_OFFSET_TABLE-4, blrl insn. */
- dcbst %r0,%r4 /* sync i-cache with d-cache */
- sync
- icbi %r0,%r4
- isync
-
- lwz %r4,0(%r3) /* offset to _DYNAMIC */
- add %r3,%r4,%r3 /* r3 = &_DYNAMIC, absolute value */
-
- bl _GLOBAL_OFFSET_TABLE_@local-4
- mflr %r4 /* &_GLOBAL_OFFSET_TABLE_, absolute value */
- lwz %r4,0(%r4) /* linker &_DYNAMIC, from got[0] */
- subf %r4,%r4,%r3 /* subtract to calculate relocbase */
-
- bl reloc_non_plt_self@plt /* reloc_non_plt_self(&_DYNAMIC,base) */
+ bcl 20,31,1f
+1: mflr %r30
+ mr %r3,%r30 # save for _DYNAMIC
+ addis %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@ha
+ addi %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@l
+ addis %r3,%r3,_DYNAMIC-1b@ha # get _DYNAMIC actual address
+ addi %r3,%r3,_DYNAMIC-1b@l
+ lwz %r28,0(%r30) # get base-relative &_DYNAMIC
+ sub %r28,%r3,%r28 # r28 = relocbase
+ mr %r4,%r28 # r4 = relocbase
+ bl reloc_non_plt_self /* reloc_non_plt_self(&_DYNAMIC,base) */
/*
* The _rtld() function likes to see a stack layout containing
@@ -95,7 +82,7 @@ _ENTRY(.rtld_start)
addi %r4,%r1,8 /* &exit_proc on stack */
addi %r5,%r1,12 /* &obj_main on stack */
- bl _rtld@plt /* &_start = _rtld(sp, &exit_proc, &obj_main)*/
+ bl _rtld /* &_start = _rtld(sp, &exit_proc, &obj_main)*/
mtlr %r3
/*
@@ -115,6 +102,29 @@ _ENTRY(.rtld_start)
sc
/*
+ * _rtld_bind_secureplt_start()
+ *
+ * Call into the MI binder (Secure-PLT stub).
+ * secure-plt expects %r11 to be the offset to the rela entry.
+ * bss-plt expects %r11 to be index of the rela entry.
+ * So for bss-plt, we multiply the index by 12 to get the offset.
+ */
+_ENTRY(_rtld_bind_secureplt_start)
+ stwu %r1,-160(%r1) # stack space for 29 regs + r0/lr/cr
+ stw %r0,20(%r1) # save r0
+
+ /*
+ * Instead of division which is costly we will use multiplicative
+ * inverse. a / n = ((a * inv(n)) >> 32)
+ * where inv(n) = (0x100000000 + n - 1) / n
+ */
+ mr %r0,%r11
+ lis %r11,0x15555556@h # load multiplicative inverse of 12
+ ori %r11,%r11,0x15555556@l
+ mulhwu %r11,%r11,%r0 # get high half of multiplication
+ b 1f
+
+/*
* _rtld_bind_start()
*
* Call into the MI binder. This routine is reached via the PLT call cell,
@@ -129,6 +139,7 @@ _ENTRY(.rtld_start)
_ENTRY(_rtld_bind_start)
stwu %r1,-160(%r1) # stack space for 29 regs + r0/lr/cr
stw %r0,20(%r1) # save r0
+1:
mflr %r0
stw %r0,16(%r1) # save lr
mfcr %r0
@@ -137,7 +148,7 @@ _ENTRY(_rtld_bind_start)
mr %r3,%r12 # obj
mulli %r4,%r11,12 # rela index * sizeof(Elf_Rela)
- bl _rtld_bind@PLT # target addr = _rtld_bind(obj, reloff)
+ bl _rtld_bind # target addr = _rtld_bind(obj, reloff)
mtctr %r3 # move absolute target addr into ctr
lmw %r3,24(%r1) # restore r3-r31
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 7cdd5c58c5dc..ece58e138235 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -1286,10 +1286,16 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
#endif
+#ifdef __powerpc__
#ifdef __powerpc64__
case DT_PPC64_GLINK:
obj->glink = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr);
break;
+#else
+ case DT_PPC_GOT:
+ obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
+ break;
+#endif
#endif
case DT_FLAGS_1:
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index d7ef9d56b8d0..fc9f10255811 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -190,8 +190,12 @@ typedef struct Struct_Obj_Entry {
Elf_Word gotsym; /* First dynamic symbol in GOT */
Elf_Addr *mips_pltgot; /* Second PLT GOT */
#endif
+#ifdef __powerpc__
#ifdef __powerpc64__
Elf_Addr glink; /* GLINK PLT call stub section */
+#else
+ Elf_Addr *gotptr; /* GOT pointer (secure-plt only) */
+#endif
#endif
const Elf_Verneed *verneed; /* Required versions. */
diff --git a/libexec/rtld-elf/rtld_printf.h b/libexec/rtld-elf/rtld_printf.h
index 5cfcc6d062f1..3d3a0480ecce 100644
--- a/libexec/rtld-elf/rtld_printf.h
+++ b/libexec/rtld-elf/rtld_printf.h
@@ -31,6 +31,7 @@
#define RTLD_PRINTF_H 1
#include <sys/cdefs.h>
+#include <stdarg.h>
#include <unistd.h>
int rtld_snprintf(char *buf, size_t bufsize, const char *fmt, ...)
diff --git a/release/Makefile.mirrors b/release/Makefile.mirrors
index 44589d698c3c..6857ff0eafb1 100644
--- a/release/Makefile.mirrors
+++ b/release/Makefile.mirrors
@@ -19,6 +19,7 @@ FTPDIR?= ${RELEASEDIR}/ftp-stage
.if exists(${RELEASEDIR})
STAGE_TARGETS?= iso-images-stage
.endif
+SRCBRANCH!= ${SVN_CMD} info --show-item relative-url ${WORLDDIR}
.if (defined(EMBEDDED_TARGET) && !empty(EMBEDDED_TARGET)) || (defined(EMBEDDEDBUILD) && !empty(EMBEDDEDBUILD))
. if ${TARGET:Marm*} != "" || ${EMBEDDED_TARGET:Marm*} != ""
@@ -185,6 +186,9 @@ iso-images-stage:
.if exists(${RELEASEDIR}/ftp)
mkdir -p ${FTP_DIR}
cp -p ${RELEASEDIR}/ftp/*.txz ${RELEASEDIR}/ftp/MANIFEST ${FTP_DIR}
+ echo ${BUILDDATE} > ${FTP_DIR}/BUILDDATE
+ echo ${SRCBRANCH} > ${FTP_DIR}/SRCBRANCH
+ echo r${SVNREVISION} > ${FTP_DIR}/REVISION
cd ${TLD}/${TARGET} && \
ln -s ${TARGET_ARCH}/${REVISION}-${BRANCH} \
${REVISION}-${BRANCH}
diff --git a/release/picobsd/bridge/PICOBSD b/release/picobsd/bridge/PICOBSD
index bc1185d61c64..c06091dcb888 100644
--- a/release/picobsd/bridge/PICOBSD
+++ b/release/picobsd/bridge/PICOBSD
@@ -50,7 +50,6 @@ device if_bridge
# qemu, so we set HZ explicitly.
options HZ=1000
-device random # used by ssh
device pci
# Floppy drives
diff --git a/release/picobsd/build/picobsd b/release/picobsd/build/picobsd
index 807f9acd7242..2d057ed81c5c 100755
--- a/release/picobsd/build/picobsd
+++ b/release/picobsd/build/picobsd
@@ -437,7 +437,7 @@ populate_floppy_fs() { # OK
${MY_TREE}/floppy.tree.${SITE} ; do
if [ -d ${FLOPPY_TREE} ] ; then
(cd ${FLOPPY_TREE} ; tar -cf - \
- --exclude .svn ${excl} . ) | \
+ --exclude .git --exclude .svn ${excl} . ) | \
(cd ${dst} ; tar x${o_tarv}f - )
log "Copied from ${FLOPPY_TREE}"
fi
@@ -698,7 +698,7 @@ populate_mfs_tree() {
for MFS_TREE in ${PICO_TREE}/mfs_tree ${MY_TREE}/mfs_tree ; do
if [ -d ${MFS_TREE} ] ; then
log "Copy ${MFS_TREE} ..."
- (cd ${MFS_TREE} ; tar -cf - --exclude .svn . ) | \
+ (cd ${MFS_TREE} ; tar -cf - --exclude .git --exclude .svn . ) | \
(cd ${dst} ; tar x${o_tarv}f - )
fi
done
diff --git a/release/picobsd/qemu/PICOBSD b/release/picobsd/qemu/PICOBSD
index 16b175385b0a..f3a9f9ccaf28 100644
--- a/release/picobsd/qemu/PICOBSD
+++ b/release/picobsd/qemu/PICOBSD
@@ -56,7 +56,6 @@ device if_bridge
# qemu, so we set HZ explicitly.
options HZ=1000
-device random # used by ssh
device pci
# Floppy drives
diff --git a/sbin/Makefile b/sbin/Makefile
index 78c581e357a1..72da4c5bb058 100644
--- a/sbin/Makefile
+++ b/sbin/Makefile
@@ -79,8 +79,6 @@ SUBDIR.${MK_IPFILTER}+= ipf
SUBDIR.${MK_IPFW}+= ipfw
SUBDIR.${MK_IPFW}+= natd
SUBDIR.${MK_ISCSI}+= iscontrol
-SUBDIR.${MK_NAND}+= nandfs
-SUBDIR.${MK_NAND}+= newfs_nandfs
SUBDIR.${MK_NVME}+= nvmecontrol
SUBDIR.${MK_OPENSSL}+= decryptcore
SUBDIR.${MK_PF}+= pfctl
diff --git a/sbin/bectl/bectl.c b/sbin/bectl/bectl.c
index 366fa048a893..5119759deb97 100644
--- a/sbin/bectl/bectl.c
+++ b/sbin/bectl/bectl.c
@@ -184,7 +184,8 @@ bectl_cmd_activate(int argc, char *argv[])
static int
bectl_cmd_create(int argc, char *argv[])
{
- char *atpos, *bootenv, *snapname, *source;
+ char snapshot[BE_MAXPATHLEN];
+ char *atpos, *bootenv, *snapname;
int err, opt;
bool recursive;
@@ -214,6 +215,8 @@ bectl_cmd_create(int argc, char *argv[])
}
bootenv = *argv;
+
+ err = BE_ERR_SUCCESS;
if ((atpos = strchr(bootenv, '@')) != NULL) {
/*
* This is the "create a snapshot variant". No new boot
@@ -221,24 +224,22 @@ bectl_cmd_create(int argc, char *argv[])
*/
*atpos++ = '\0';
err = be_snapshot(be, bootenv, atpos, recursive, NULL);
- } else if (snapname != NULL) {
- if (strchr(snapname, '@') != NULL)
- err = be_create_from_existing_snap(be, bootenv,
- snapname);
- else
- err = be_create_from_existing(be, bootenv, snapname);
} else {
- if ((snapname = strchr(bootenv, '@')) != NULL) {
- *(snapname++) = '\0';
- if ((err = be_snapshot(be, be_active_path(be),
- snapname, true, NULL)) != BE_ERR_SUCCESS)
- fprintf(stderr, "failed to create snapshot\n");
- asprintf(&source, "%s@%s", be_active_path(be), snapname);
- err = be_create_from_existing_snap(be, bootenv,
- source);
- return (err);
- } else
- err = be_create(be, bootenv);
+ if (snapname == NULL)
+ /* Create from currently booted BE */
+ err = be_snapshot(be, be_active_path(be), NULL,
+ recursive, snapshot);
+ else if (strchr(snapname, '@') != NULL)
+ /* Create from given snapshot */
+ strlcpy(snapshot, snapname, sizeof(snapshot));
+ else
+ /* Create from given BE */
+ err = be_snapshot(be, snapname, NULL, recursive,
+ snapshot);
+
+ if (err == BE_ERR_SUCCESS)
+ err = be_create_depth(be, bootenv, snapshot,
+ recursive == true ? -1 : 0);
}
switch (err) {
diff --git a/sbin/bectl/tests/bectl_test.sh b/sbin/bectl/tests/bectl_test.sh
index 6d268c00b178..e551e501b790 100755
--- a/sbin/bectl/tests/bectl_test.sh
+++ b/sbin/bectl/tests/bectl_test.sh
@@ -99,11 +99,35 @@ bectl_create_body()
mount=${cwd}/mnt
bectl_create_setup ${zpool} ${disk} ${mount}
+
+ # Create a child dataset that will be used to test creation
+ # of recursive and non-recursive boot environments.
+ atf_check zfs create -o mountpoint=/usr -o canmount=noauto \
+ ${zpool}/ROOT/default/usr
+
# Test standard creation, creation of a snapshot, and creation from a
# snapshot.
atf_check bectl -r ${zpool}/ROOT create -e default default2
atf_check bectl -r ${zpool}/ROOT create default2@test_snap
atf_check bectl -r ${zpool}/ROOT create -e default2@test_snap default3
+
+ # Test standard creation, creation of a snapshot, and creation from a
+ # snapshot for recursive boot environments.
+ atf_check bectl -r ${zpool}/ROOT create -r -e default recursive
+ atf_check bectl -r ${zpool}/ROOT create -r recursive@test_snap
+ atf_check bectl -r ${zpool}/ROOT create -r -e recursive@test_snap recursive-snap
+
+ # Test that non-recursive boot environments have no child datasets.
+ atf_check -e not-empty -s not-exit:0 \
+ zfs list "${zpool}/ROOT/default2/usr"
+ atf_check -e not-empty -s not-exit:0 \
+ zfs list "${zpool}/ROOT/default3/usr"
+
+ # Test that recursive boot environments have child datasets.
+ atf_check -o not-empty \
+ zfs list "${zpool}/ROOT/recursive/usr"
+ atf_check -o not-empty \
+ zfs list "${zpool}/ROOT/recursive-snap/usr"
}
bectl_create_cleanup()
{
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
index 0784fab75a0e..99d59e59d86c 100644
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -2326,9 +2326,11 @@ ata_do_identify(struct cam_device *device, int retry_count, int timeout,
}
}
+ ident_buf = (struct ata_params *)ptr;
+ ata_param_fixup(ident_buf);
+
error = 1;
for (i = 0; i < sizeof(struct ata_params) / 2; i++) {
- ptr[i] = le16toh(ptr[i]);
if (ptr[i] != 0)
error = 0;
}
@@ -2346,26 +2348,6 @@ ata_do_identify(struct cam_device *device, int retry_count, int timeout,
return (error);
}
- ident_buf = (struct ata_params *)ptr;
- if (strncmp(ident_buf->model, "FX", 2) &&
- strncmp(ident_buf->model, "NEC", 3) &&
- strncmp(ident_buf->model, "Pioneer", 7) &&
- strncmp(ident_buf->model, "SHARP", 5)) {
- ata_bswap(ident_buf->model, sizeof(ident_buf->model));
- ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
- ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
- ata_bswap(ident_buf->media_serial, sizeof(ident_buf->media_serial));
- }
- ata_btrim(ident_buf->model, sizeof(ident_buf->model));
- ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
- ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
- ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
- ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
- ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
- ata_btrim(ident_buf->media_serial, sizeof(ident_buf->media_serial));
- ata_bpack(ident_buf->media_serial, ident_buf->media_serial,
- sizeof(ident_buf->media_serial));
-
*ident_bufp = ident_buf;
return (0);
diff --git a/sbin/dhclient/options.c b/sbin/dhclient/options.c
index 3b05e3ff1889..dc4cceab8418 100644
--- a/sbin/dhclient/options.c
+++ b/sbin/dhclient/options.c
@@ -896,6 +896,5 @@ do_packet(struct interface_info *interface, struct dhcp_packet *packet,
/* Free the data associated with the options. */
for (i = 0; i < 256; i++)
- if (tp.options[i].len && tp.options[i].data)
- free(tp.options[i].data);
+ free(tp.options[i].data);
}
diff --git a/sbin/dhclient/packet.c b/sbin/dhclient/packet.c
index 2328d577386d..21726aaaeb84 100644
--- a/sbin/dhclient/packet.c
+++ b/sbin/dhclient/packet.c
@@ -183,7 +183,7 @@ decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from,
ip_packets_seen++;
if (wrapsum(checksum(buf + bufix, ip_len, 0)) != 0) {
ip_packets_bad_checksum++;
- if (ip_packets_seen > 4 &&
+ if (ip_packets_seen > 4 && ip_packets_bad_checksum != 0 &&
(ip_packets_seen / ip_packets_bad_checksum) < 2) {
note("%d bad IP checksums seen in %d packets",
ip_packets_bad_checksum, ip_packets_seen);
@@ -235,7 +235,7 @@ decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from,
udp_packets_seen++;
if (usum && usum != sum) {
udp_packets_bad_checksum++;
- if (udp_packets_seen > 4 &&
+ if (udp_packets_seen > 4 && udp_packets_bad_checksum != 0 &&
(udp_packets_seen / udp_packets_bad_checksum) < 2) {
note("%d bad udp checksums in %d packets",
udp_packets_bad_checksum, udp_packets_seen);
diff --git a/sbin/ipf/ipmon/Makefile b/sbin/ipf/ipmon/Makefile
index 5d76a05ae44a..8227811db2ad 100644
--- a/sbin/ipf/ipmon/Makefile
+++ b/sbin/ipf/ipmon/Makefile
@@ -3,7 +3,8 @@
PACKAGE= ipf
PROG= ipmon
SRCS= ${GENHDRS} ipmon.c ipmon_y.c ipmon_l.c
-MAN= ipmon.8
+MAN= ipmon.5 ipmon.8
+MLINKS= ipmon.5 ipmon.conf.5
CFLAGS+= -DLOGFAC=LOG_LOCAL0 -I.
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index fcba4a4b03f2..bcc8017a571b 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 24, 2019
+.Dd June 21, 2019
.Dt IPFW 8
.Os
.Sh NAME
@@ -1989,6 +1989,12 @@ a non-zero offset.
See the
.Cm frag
option for details on matching fragmented packets.
+.It Cm tcpmss Ar tcpmss-list
+Matches TCP packets whose MSS (maximum segment size) value is set to
+.Ar tcpmss-list ,
+which is either a single value or a list of values or ranges
+specified in the same way as
+.Ar ports .
.It Cm tcpseq Ar seq
TCP packets only.
Match if the TCP header sequence number field is set to
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index 3e73fa3b8736..c2d89fcbf72f 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -338,6 +338,7 @@ static struct _s_x rule_options[] = {
{ "tcpdatalen", TOK_TCPDATALEN },
{ "tcpflags", TOK_TCPFLAGS },
{ "tcpflgs", TOK_TCPFLAGS },
+ { "tcpmss", TOK_TCPMSS },
{ "tcpoptions", TOK_TCPOPTS },
{ "tcpopts", TOK_TCPOPTS },
{ "tcpseq", TOK_TCPSEQ },
@@ -881,6 +882,7 @@ static struct _s_x _port_name[] = {
{"ipttl", O_IPTTL},
{"mac-type", O_MAC_TYPE},
{"tcpdatalen", O_TCPDATALEN},
+ {"tcpmss", O_TCPMSS},
{"tcpwin", O_TCPWIN},
{"tagged", O_TAGGED},
{NULL, 0}
@@ -1588,6 +1590,7 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
case O_IPTTL:
case O_IPLEN:
case O_TCPDATALEN:
+ case O_TCPMSS:
case O_TCPWIN:
if (F_LEN(cmd) == 1) {
switch (cmd->opcode) {
@@ -1603,6 +1606,9 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
case O_TCPDATALEN:
s = "tcpdatalen";
break;
+ case O_TCPMSS:
+ s = "tcpmss";
+ break;
case O_TCPWIN:
s = "tcpwin";
break;
@@ -2217,6 +2223,8 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
}
print_proto(bp, fo, &state);
+ if (co->do_compact != 0 && (rule->flags & IPFW_RULE_NOOPT))
+ goto justopts;
/* Print source */
bprintf(bp, " from");
@@ -4389,6 +4397,8 @@ chkarg:
}
OR_BLOCK(get_proto);
+ first_cmd = cmd; /* update pointer to use in compact form */
+
/*
* "from", mandatory
*/
@@ -4460,6 +4470,8 @@ chkarg:
cmd = next_cmd(cmd, &cblen);
}
}
+ if (first_cmd == cmd)
+ rule->flags |= IPFW_RULE_NOOPT;
read_options:
prev = NULL;
@@ -4709,14 +4721,18 @@ read_options:
av++;
break;
+ case TOK_TCPMSS:
case TOK_TCPWIN:
- NEED1("tcpwin requires length");
+ NEED1("tcpmss/tcpwin requires size");
if (strpbrk(*av, "-,")) {
- if (!add_ports(cmd, *av, 0, O_TCPWIN, cblen))
- errx(EX_DATAERR, "invalid tcpwin len %s", *av);
+ if (add_ports(cmd, *av, 0,
+ i == TOK_TCPWIN ? O_TCPWIN : O_TCPMSS,
+ cblen) == NULL)
+ errx(EX_DATAERR, "invalid %s size %s",
+ s, *av);
} else
- fill_cmd(cmd, O_TCPWIN, 0,
- strtoul(*av, NULL, 0));
+ fill_cmd(cmd, i == TOK_TCPWIN ? O_TCPWIN :
+ O_TCPMSS, 0, strtoul(*av, NULL, 0));
av++;
break;
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index e6c209d65bab..215416eecc8a 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -151,6 +151,7 @@ enum tokens {
TOK_TCPOPTS,
TOK_TCPSEQ,
TOK_TCPACK,
+ TOK_TCPMSS,
TOK_TCPWIN,
TOK_ICMPTYPES,
TOK_MAC,
diff --git a/sbin/nandfs/Makefile b/sbin/nandfs/Makefile
deleted file mode 100644
index 40af5775c510..000000000000
--- a/sbin/nandfs/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# $FreeBSD$
-
-PACKAGE=nandfs
-PROG= nandfs
-SRCS= nandfs.c lssnap.c mksnap.c rmsnap.c
-MAN= nandfs.8
-
-LIBADD= nandfs
-
-.include <bsd.prog.mk>
diff --git a/sbin/nandfs/Makefile.depend b/sbin/nandfs/Makefile.depend
deleted file mode 100644
index 1269878d50ef..000000000000
--- a/sbin/nandfs/Makefile.depend
+++ /dev/null
@@ -1,18 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libnandfs \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/sbin/nandfs/lssnap.c b/sbin/nandfs/lssnap.c
deleted file mode 100644
index cb240fb1da84..000000000000
--- a/sbin/nandfs/lssnap.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Semihalf under sponsorship
- * from the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-#include <sys/types.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sysexits.h>
-#include <time.h>
-
-#include <fs/nandfs/nandfs_fs.h>
-#include <libnandfs.h>
-
-#include "nandfs.h"
-
-#define NCPINFO 512
-
-static void
-lssnap_usage(void)
-{
-
- fprintf(stderr, "usage:\n");
- fprintf(stderr, "\tlssnap node\n");
-}
-
-static void
-print_cpinfo(struct nandfs_cpinfo *cpinfo)
-{
- struct tm tm;
- time_t t;
- char timebuf[128];
-
- t = (time_t)cpinfo->nci_create;
- localtime_r(&t, &tm);
- strftime(timebuf, sizeof(timebuf), "%F %T", &tm);
-
- printf("%20llu %s\n", (unsigned long long)cpinfo->nci_cno, timebuf);
-}
-
-int
-nandfs_lssnap(int argc, char **argv)
-{
- struct nandfs_cpinfo *cpinfos;
- struct nandfs fs;
- uint64_t next;
- int error, nsnap, i;
-
- if (argc != 1) {
- lssnap_usage();
- return (EX_USAGE);
- }
-
- cpinfos = malloc(sizeof(*cpinfos) * NCPINFO);
- if (cpinfos == NULL) {
- fprintf(stderr, "cannot allocate memory\n");
- return (-1);
- }
-
- nandfs_init(&fs, argv[0]);
- error = nandfs_open(&fs);
- if (error == -1) {
- fprintf(stderr, "nandfs_open: %s\n", nandfs_errmsg(&fs));
- goto out;
- }
-
- for (next = 1; next != 0; next = cpinfos[nsnap - 1].nci_next) {
- nsnap = nandfs_get_snap(&fs, next, cpinfos, NCPINFO);
- if (nsnap < 1)
- break;
-
- for (i = 0; i < nsnap; i++)
- print_cpinfo(&cpinfos[i]);
- }
-
- if (nsnap == -1)
- fprintf(stderr, "nandfs_get_snap: %s\n", nandfs_errmsg(&fs));
-
-out:
- nandfs_close(&fs);
- nandfs_destroy(&fs);
- free(cpinfos);
- return (error);
-}
diff --git a/sbin/nandfs/mksnap.c b/sbin/nandfs/mksnap.c
deleted file mode 100644
index f75eda3834a9..000000000000
--- a/sbin/nandfs/mksnap.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Semihalf under sponsorship
- * from the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-#include <sys/types.h>
-
-#include <stdio.h>
-#include <sysexits.h>
-
-#include <fs/nandfs/nandfs_fs.h>
-#include <libnandfs.h>
-
-#include "nandfs.h"
-
-static void
-mksnap_usage(void)
-{
-
- fprintf(stderr, "usage:\n");
- fprintf(stderr, "\tmksnap node\n");
-}
-
-int
-nandfs_mksnap(int argc, char **argv)
-{
- struct nandfs fs;
- uint64_t cpno;
- int error;
-
- if (argc != 1) {
- mksnap_usage();
- return (EX_USAGE);
- }
-
- nandfs_init(&fs, argv[0]);
- error = nandfs_open(&fs);
- if (error == -1) {
- fprintf(stderr, "nandfs_open: %s\n", nandfs_errmsg(&fs));
- goto out;
- }
-
- error = nandfs_make_snap(&fs, &cpno);
- if (error == -1)
- fprintf(stderr, "nandfs_make_snap: %s\n", nandfs_errmsg(&fs));
- else
- printf("%jd\n", cpno);
-
-out:
- nandfs_close(&fs);
- nandfs_destroy(&fs);
- return (error);
-}
diff --git a/sbin/nandfs/nandfs.8 b/sbin/nandfs/nandfs.8
deleted file mode 100644
index 9995905d3c68..000000000000
--- a/sbin/nandfs/nandfs.8
+++ /dev/null
@@ -1,79 +0,0 @@
-.\"
-.\" Copyright (c) 2012 The FreeBSD Foundation
-.\" All rights reserved.
-.\"
-.\" This software was developed by Semihalf under sponsorship
-.\" from the FreeBSD Foundation.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\"
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd September 10, 2016
-.Dt NANDFS 8
-.Os
-.Sh NAME
-.Nm nandfs
-.Nd manage mounted NAND FS
-.Sh SYNOPSIS
-.Nm
-.Cm lssnap
-.Ar node
-.Nm
-.Cm mksnap
-.Ar node
-.Nm
-.Cm rmsnap
-.Ar snapshot node
-.Sh DESCRIPTION
-The
-.Nm
-utility allows the management of snapshots on a mounted NAND FS.
-.Sh EXAMPLES
-Create a snapshot of filesystem mounted on
-.Em /nand .
-.Bd -literal -offset 2n
-.Li # Ic nandfs mksnap /nand
-1
-.Ed
-.Pp
-List snapshots of filesystem mounted on
-.Em /nand .
-.Bd -literal -offset 2n
-.Li # Ic nandfs lssnap /nand
-1 2012-02-28 18:49:45 ss 138 2
-.Ed
-.Pp
-Remove snapshot 1 of filesystem mounted on
-.Em /nand .
-.Bd -literal -offset 2n
-.Li # Ic nandfs rmsnap 1 /nand
-.Ed
-.Sh HISTORY
-The
-.Nm
-utility appeared in
-.Fx 10.0 .
-.Sh AUTHORS
-This utility and manual page were written by
-.An Mateusz Guzik .
diff --git a/sbin/nandfs/nandfs.c b/sbin/nandfs/nandfs.c
deleted file mode 100644
index b319b58bc5c1..000000000000
--- a/sbin/nandfs/nandfs.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Semihalf under sponsorship
- * from the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sysexits.h>
-
-#include "nandfs.h"
-
-static void
-usage(void)
-{
-
- fprintf(stderr, "usage: nandfs [lssnap | mksnap | rmsnap <snap>] "
- "node\n");
- exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
- int error = 0;
- char *cmd;
-
- if (argc < 2)
- usage();
-
- cmd = argv[1];
- argc -= 2;
- argv += 2;
-
- if (strcmp(cmd, "lssnap") == 0)
- error = nandfs_lssnap(argc, argv);
- else if (strcmp(cmd, "mksnap") == 0)
- error = nandfs_mksnap(argc, argv);
- else if (strcmp(cmd, "rmsnap") == 0)
- error = nandfs_rmsnap(argc, argv);
- else
- usage();
-
- return (error);
-}
diff --git a/sbin/nandfs/nandfs.h b/sbin/nandfs/nandfs.h
deleted file mode 100644
index 993d9338e904..000000000000
--- a/sbin/nandfs/nandfs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Semihalf under sponsorship
- * from the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef NANDFS_H
-#define NANDFS_H
-
-int nandfs_lssnap(int, char **);
-int nandfs_mksnap(int, char **);
-int nandfs_rmsnap(int, char **);
-
-#endif /* !NANDFS_H */
diff --git a/sbin/nandfs/rmsnap.c b/sbin/nandfs/rmsnap.c
deleted file mode 100644
index c07439d694ef..000000000000
--- a/sbin/nandfs/rmsnap.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Semihalf under sponsorship
- * from the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-#include <sys/types.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <sysexits.h>
-
-#include <fs/nandfs/nandfs_fs.h>
-#include <libnandfs.h>
-
-#include "nandfs.h"
-
-static void
-rmsnap_usage(void)
-{
-
- fprintf(stderr, "usage:\n");
- fprintf(stderr, "\trmsnap snap node\n");
-}
-
-int
-nandfs_rmsnap(int argc, char **argv)
-{
- struct nandfs fs;
- uint64_t cpno;
- int error;
-
- if (argc != 2) {
- rmsnap_usage();
- return (EX_USAGE);
- }
-
- cpno = strtoll(argv[0], (char **)NULL, 10);
- if (cpno == 0) {
- fprintf(stderr, "%s must be a number greater than 0\n",
- argv[0]);
- return (EX_USAGE);
- }
-
- nandfs_init(&fs, argv[1]);
- error = nandfs_open(&fs);
- if (error == -1) {
- fprintf(stderr, "nandfs_open: %s\n", nandfs_errmsg(&fs));
- goto out;
- }
-
- error = nandfs_delete_snap(&fs, cpno);
- if (error == -1)
- fprintf(stderr, "nandfs_delete_snap: %s\n", nandfs_errmsg(&fs));
-
-out:
- nandfs_close(&fs);
- nandfs_destroy(&fs);
- return (error);
-}
diff --git a/sbin/newfs_nandfs/Makefile b/sbin/newfs_nandfs/Makefile
deleted file mode 100644
index 9b1b3009c400..000000000000
--- a/sbin/newfs_nandfs/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# $FreeBSD$
-
-PACKAGE=nandfs
-PROG= newfs_nandfs
-MAN= newfs_nandfs.8
-
-LIBADD= geom
-
-.include <bsd.prog.mk>
diff --git a/sbin/newfs_nandfs/Makefile.depend b/sbin/newfs_nandfs/Makefile.depend
deleted file mode 100644
index 0220673c9076..000000000000
--- a/sbin/newfs_nandfs/Makefile.depend
+++ /dev/null
@@ -1,20 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libexpat \
- lib/libgeom \
- lib/libsbuf \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/sbin/newfs_nandfs/newfs_nandfs.8 b/sbin/newfs_nandfs/newfs_nandfs.8
deleted file mode 100644
index fe3216394109..000000000000
--- a/sbin/newfs_nandfs/newfs_nandfs.8
+++ /dev/null
@@ -1,74 +0,0 @@
-.\"
-.\" Copyright (c) 2010 Semihalf
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd October 1, 2013
-.Dt NEWFS_NANDFS 8
-.Os
-.Sh NAME
-.Nm newfs_nandfs
-.Nd construct a new NAND FS file system
-.Sh SYNOPSIS
-.Nm
-.Op Fl b Ar blocsize
-.Op Fl B Ar blocks-per-segment
-.Op Fl L Ar label
-.Op Fl m Ar reserved-segment-percent
-.Ar device
-.Sh DESCRIPTION
-The
-.Nm
-utility creates a NAND FS file system on device.
-.Pp
-The options are as follow:
-.Bl -tag -width indent
-.It Fl b Ar blocksize
-Size of block (1024 if not specified).
-.It Fl B Ar blocks_per_segment
-Number of blocks per segment (2048 if not specified).
-.It Fl L Ar label
-Volume label (up to 16 characters).
-.It Fl m Ar reserved_block_percent
-Percentage of reserved blocks (5 if not specified).
-.El
-.Sh EXIT STATUS
-Exit status is 0 on success and 1 on error.
-.Sh EXAMPLES
-Create a file system, using default parameters, on
-.Pa /dev/ada0s1 :
-.Bd -literal -offset indent
-newfs_nandfs /dev/ada0s1
-.Ed
-.Sh SEE ALSO
-.Xr gpart 8 ,
-.Xr newfs 8
-.Sh HISTORY
-The
-.Nm
-utility first appeared in
-.Fx 10.0 .
-.Sh AUTHORS
-.An Grzegorz Bernacki
diff --git a/sbin/newfs_nandfs/newfs_nandfs.c b/sbin/newfs_nandfs/newfs_nandfs.c
deleted file mode 100644
index e432cc6e6420..000000000000
--- a/sbin/newfs_nandfs/newfs_nandfs.c
+++ /dev/null
@@ -1,1183 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/fdcio.h>
-#include <sys/disk.h>
-#include <sys/disklabel.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/endian.h>
-#include <sys/stddef.h>
-#include <sys/uuid.h>
-#include <sys/dirent.h>
-#include <sys/stat.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <libgeom.h>
-#include <paths.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <fs/nandfs/nandfs_fs.h>
-#include <dev/nand/nand_dev.h>
-
-#define DEBUG
-#undef DEBUG
-#ifdef DEBUG
-#define debug(fmt, args...) do { \
- printf("nandfs:" fmt "\n", ##args); } while (0)
-#else
-#define debug(fmt, args...)
-#endif
-
-#define NANDFS_FIRST_BLOCK nandfs_first_block()
-#define NANDFS_FIRST_CNO 1
-#define NANDFS_BLOCK_BAD 1
-#define NANDFS_BLOCK_GOOD 0
-
-struct file_info {
- uint64_t ino;
- const char *name;
- uint32_t mode;
- uint64_t size;
- uint8_t nblocks;
- uint32_t *blocks;
- struct nandfs_inode *inode;
-};
-
-static struct file_info user_files[] = {
- { NANDFS_ROOT_INO, NULL, S_IFDIR | 0755, 0, 1, NULL, NULL },
-};
-
-static struct file_info ifile =
- { NANDFS_IFILE_INO, NULL, 0, 0, -1, NULL, NULL };
-static struct file_info sufile =
- { NANDFS_SUFILE_INO, NULL, 0, 0, -1, NULL, NULL };
-static struct file_info cpfile =
- { NANDFS_CPFILE_INO, NULL, 0, 0, -1, NULL, NULL };
-static struct file_info datfile =
- { NANDFS_DAT_INO, NULL, 0, 0, -1, NULL, NULL };
-
-struct nandfs_block {
- LIST_ENTRY(nandfs_block) block_link;
- uint32_t number;
- uint64_t offset;
- void *data;
-};
-
-static LIST_HEAD(, nandfs_block) block_head =
- LIST_HEAD_INITIALIZER(&block_head);
-
-/* Storage geometry */
-static off_t mediasize;
-static ssize_t sectorsize;
-static uint64_t nsegments;
-static uint64_t erasesize;
-static uint64_t segsize;
-
-static struct nandfs_fsdata fsdata;
-static struct nandfs_super_block super_block;
-
-static int is_nand;
-
-/* Nandfs parameters */
-static size_t blocksize = NANDFS_DEF_BLOCKSIZE;
-static long blocks_per_segment;
-static long rsv_segment_percent = 5;
-static time_t nandfs_time;
-static uint32_t bad_segments_count = 0;
-static uint32_t *bad_segments = NULL;
-static uint8_t fsdata_blocks_state[NANDFS_NFSAREAS];
-
-static u_char *volumelabel = NULL;
-
-static struct nandfs_super_root *sr;
-
-static uint32_t nuserfiles;
-static uint32_t seg_nblocks;
-static uint32_t seg_endblock;
-
-#define SIZE_TO_BLOCK(size) howmany(size, blocksize)
-
-static uint32_t
-nandfs_first_block(void)
-{
- uint32_t i, first_free, start_bad_segments = 0;
-
- for (i = 0; i < bad_segments_count; i++) {
- if (i == bad_segments[i])
- start_bad_segments++;
- else
- break;
- }
-
- first_free = SIZE_TO_BLOCK(NANDFS_DATA_OFFSET_BYTES(erasesize) +
- (start_bad_segments * segsize));
-
- if (first_free < (uint32_t)blocks_per_segment)
- return (blocks_per_segment);
- else
- return (first_free);
-}
-
-static void
-usage(void)
-{
-
- fprintf(stderr,
- "usage: newfs_nandfs [ -options ] device\n"
- "where the options are:\n"
- "\t-b block-size\n"
- "\t-B blocks-per-segment\n"
- "\t-L volume label\n"
- "\t-m reserved-segments-percentage\n");
- exit(1);
-}
-
-static int
-nandfs_log2(unsigned n)
-{
- unsigned count;
-
- /*
- * N.B. this function will return 0 if supplied 0.
- */
- for (count = 0; n/2; count++)
- n /= 2;
- return count;
-}
-
-/* from NetBSD's src/sys/net/if_ethersubr.c */
-static uint32_t
-crc32_le(uint32_t crc, const uint8_t *buf, size_t len)
-{
- static const uint32_t crctab[] = {
- 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
- 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
- 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
- 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
- };
- size_t i;
-
- crc = crc ^ ~0U;
-
- for (i = 0; i < len; i++) {
- crc ^= buf[i];
- crc = (crc >> 4) ^ crctab[crc & 0xf];
- crc = (crc >> 4) ^ crctab[crc & 0xf];
- }
-
- return (crc ^ ~0U);
-}
-
-static void *
-get_block(uint32_t block_nr, uint64_t offset)
-{
- struct nandfs_block *block, *new_block;
-
- LIST_FOREACH(block, &block_head, block_link) {
- if (block->number == block_nr)
- return block->data;
- }
-
- debug("allocating block %x\n", block_nr);
-
- new_block = malloc(sizeof(*block));
- if (!new_block)
- err(1, "cannot allocate block");
-
- new_block->number = block_nr;
- new_block->offset = offset;
- new_block->data = malloc(blocksize);
- if (!new_block->data)
- err(1, "cannot allocate block data");
-
- memset(new_block->data, 0, blocksize);
-
- LIST_INSERT_HEAD(&block_head, new_block, block_link);
-
- return (new_block->data);
-}
-
-static int
-nandfs_seg_usage_blk_offset(uint64_t seg, uint64_t *blk, uint64_t *offset)
-{
- uint64_t off;
- uint16_t seg_size;
-
- seg_size = sizeof(struct nandfs_segment_usage);
-
- off = roundup(sizeof(struct nandfs_sufile_header), seg_size);
- off += (seg * seg_size);
-
- *blk = off / blocksize;
- *offset = (off % blocksize) / seg_size;
- return (0);
-}
-
-static uint32_t
-segment_size(void)
-{
- u_int size;
-
- size = sizeof(struct nandfs_segment_summary );
- size += seg_nblocks * sizeof(struct nandfs_binfo_v);
-
- if (size > blocksize)
- err(1, "segsum info bigger that blocksize");
-
- return (size);
-}
-
-
-static void
-prepare_blockgrouped_file(uint32_t block)
-{
- struct nandfs_block_group_desc *desc;
- uint32_t i, entries;
-
- desc = (struct nandfs_block_group_desc *)get_block(block, 0);
- entries = blocksize / sizeof(struct nandfs_block_group_desc);
- for (i = 0; i < entries; i++)
- desc[i].bg_nfrees = blocksize * 8;
-}
-
-static void
-alloc_blockgrouped_file(uint32_t block, uint32_t entry)
-{
- struct nandfs_block_group_desc *desc;
- uint32_t desc_nr;
- uint32_t *bitmap;
-
- desc = (struct nandfs_block_group_desc *)get_block(block, 0);
- bitmap = (uint32_t *)get_block(block + 1, 1);
-
- bitmap += (entry >> 5);
- if (*bitmap & (1 << (entry % 32))) {
- printf("nandfs: blockgrouped entry %d already allocated\n",
- entry);
- }
- *bitmap |= (1 << (entry % 32));
-
- desc_nr = entry / (blocksize * 8);
- desc[desc_nr].bg_nfrees--;
-}
-
-
-static uint64_t
-count_su_blocks(void)
-{
- uint64_t maxblk, blk, offset, i;
-
- maxblk = blk = 0;
-
- for (i = 0; i < bad_segments_count; i++) {
- nandfs_seg_usage_blk_offset(bad_segments[i], &blk, &offset);
- debug("bad segment at block:%jx off: %jx", blk, offset);
- if (blk > maxblk)
- maxblk = blk;
- }
-
- debug("bad segment needs %#jx", blk);
- if (blk >= NANDFS_NDADDR) {
- printf("nandfs: file too big (%jd > %d)\n", blk, NANDFS_NDADDR);
- exit(2);
- }
-
- sufile.size = (blk + 1) * blocksize;
- return (blk + 1);
-}
-
-static void
-count_seg_blocks(void)
-{
- uint32_t i;
-
- for (i = 0; i < nuserfiles; i++)
- if (user_files[i].nblocks) {
- seg_nblocks += user_files[i].nblocks;
- user_files[i].blocks = malloc(user_files[i].nblocks * sizeof(uint32_t));
- }
-
- ifile.nblocks = 2 +
- SIZE_TO_BLOCK(sizeof(struct nandfs_inode) * (NANDFS_USER_INO + 1));
- ifile.blocks = malloc(ifile.nblocks * sizeof(uint32_t));
- seg_nblocks += ifile.nblocks;
-
- cpfile.nblocks =
- SIZE_TO_BLOCK((NANDFS_CPFILE_FIRST_CHECKPOINT_OFFSET + 1) *
- sizeof(struct nandfs_checkpoint));
- cpfile.blocks = malloc(cpfile.nblocks * sizeof(uint32_t));
- seg_nblocks += cpfile.nblocks;
-
- if (!bad_segments) {
- sufile.nblocks =
- SIZE_TO_BLOCK((NANDFS_SUFILE_FIRST_SEGMENT_USAGE_OFFSET + 1) *
- sizeof(struct nandfs_segment_usage));
- } else {
- debug("bad blocks found: extra space for sufile");
- sufile.nblocks = count_su_blocks();
- }
-
- sufile.blocks = malloc(sufile.nblocks * sizeof(uint32_t));
- seg_nblocks += sufile.nblocks;
-
- datfile.nblocks = 2 +
- SIZE_TO_BLOCK((seg_nblocks) * sizeof(struct nandfs_dat_entry));
- datfile.blocks = malloc(datfile.nblocks * sizeof(uint32_t));
- seg_nblocks += datfile.nblocks;
-}
-
-static void
-assign_file_blocks(uint64_t start_block)
-{
- uint32_t i, j;
-
- for (i = 0; i < nuserfiles; i++)
- for (j = 0; j < user_files[i].nblocks; j++) {
- debug("user file %d at block %d at %#jx",
- i, j, (uintmax_t)start_block);
- user_files[i].blocks[j] = start_block++;
- }
-
- for (j = 0; j < ifile.nblocks; j++) {
- debug("ifile block %d at %#jx", j, (uintmax_t)start_block);
- ifile.blocks[j] = start_block++;
- }
-
- for (j = 0; j < cpfile.nblocks; j++) {
- debug("cpfile block %d at %#jx", j, (uintmax_t)start_block);
- cpfile.blocks[j] = start_block++;
- }
-
- for (j = 0; j < sufile.nblocks; j++) {
- debug("sufile block %d at %#jx", j, (uintmax_t)start_block);
- sufile.blocks[j] = start_block++;
- }
-
- for (j = 0; j < datfile.nblocks; j++) {
- debug("datfile block %d at %#jx", j, (uintmax_t)start_block);
- datfile.blocks[j] = start_block++;
- }
-
- /* add one for superroot */
- debug("sr at block %#jx", (uintmax_t)start_block);
- sr = (struct nandfs_super_root *)get_block(start_block++, 0);
- seg_endblock = start_block;
-}
-
-static void
-save_datfile(void)
-{
-
- prepare_blockgrouped_file(datfile.blocks[0]);
-}
-
-static uint64_t
-update_datfile(uint64_t block)
-{
- struct nandfs_dat_entry *dat;
- static uint64_t vblock = 0;
- uint64_t allocated, i, off;
-
- if (vblock == 0) {
- alloc_blockgrouped_file(datfile.blocks[0], vblock);
- vblock++;
- }
- allocated = vblock;
- i = vblock / (blocksize / sizeof(*dat));
- off = vblock % (blocksize / sizeof(*dat));
- vblock++;
-
- dat = (struct nandfs_dat_entry *)get_block(datfile.blocks[2 + i], 2 + i);
-
- alloc_blockgrouped_file(datfile.blocks[0], allocated);
- dat[off].de_blocknr = block;
- dat[off].de_start = NANDFS_FIRST_CNO;
- dat[off].de_end = UINTMAX_MAX;
-
- return (allocated);
-}
-
-static union nandfs_binfo *
-update_block_info(union nandfs_binfo *binfo, struct file_info *file)
-{
- nandfs_daddr_t vblock;
- uint32_t i;
-
- for (i = 0; i < file->nblocks; i++) {
- debug("%s: blk %x", __func__, i);
- if (file->ino != NANDFS_DAT_INO) {
- vblock = update_datfile(file->blocks[i]);
- binfo->bi_v.bi_vblocknr = vblock;
- binfo->bi_v.bi_blkoff = i;
- binfo->bi_v.bi_ino = file->ino;
- file->inode->i_db[i] = vblock;
- } else {
- binfo->bi_dat.bi_blkoff = i;
- binfo->bi_dat.bi_ino = file->ino;
- file->inode->i_db[i] = datfile.blocks[i];
- }
- binfo++;
- }
-
- return (binfo);
-}
-
-static void
-save_segsum(struct nandfs_segment_summary *ss)
-{
- union nandfs_binfo *binfo;
- struct nandfs_block *block;
- uint32_t sum_bytes, i;
- uint8_t crc_data, crc_skip;
-
- sum_bytes = segment_size();
- ss->ss_magic = NANDFS_SEGSUM_MAGIC;
- ss->ss_bytes = sizeof(struct nandfs_segment_summary);
- ss->ss_flags = NANDFS_SS_LOGBGN | NANDFS_SS_LOGEND | NANDFS_SS_SR;
- ss->ss_seq = 1;
- ss->ss_create = nandfs_time;
-
- ss->ss_next = nandfs_first_block() + blocks_per_segment;
- /* nblocks = segment blocks + segsum block + superroot */
- ss->ss_nblocks = seg_nblocks + 2;
- ss->ss_nbinfos = seg_nblocks;
- ss->ss_sumbytes = sum_bytes;
-
- crc_skip = sizeof(ss->ss_datasum) + sizeof(ss->ss_sumsum);
- ss->ss_sumsum = crc32_le(0, (uint8_t *)ss + crc_skip,
- sum_bytes - crc_skip);
- crc_data = 0;
-
- binfo = (union nandfs_binfo *)(ss + 1);
- for (i = 0; i < nuserfiles; i++) {
- if (user_files[i].nblocks)
- binfo = update_block_info(binfo, &user_files[i]);
- }
-
- binfo = update_block_info(binfo, &ifile);
- binfo = update_block_info(binfo, &cpfile);
- binfo = update_block_info(binfo, &sufile);
- update_block_info(binfo, &datfile);
-
- /* save superroot crc */
- crc_skip = sizeof(sr->sr_sum);
- sr->sr_sum = crc32_le(0, (uint8_t *)sr + crc_skip,
- NANDFS_SR_BYTES - crc_skip);
-
- /* segment checksup */
- crc_skip = sizeof(ss->ss_datasum);
- LIST_FOREACH(block, &block_head, block_link) {
- if (block->number < NANDFS_FIRST_BLOCK)
- continue;
- if (block->number == NANDFS_FIRST_BLOCK)
- crc_data = crc32_le(0,
- (uint8_t *)block->data + crc_skip,
- blocksize - crc_skip);
- else
- crc_data = crc32_le(crc_data, (uint8_t *)block->data,
- blocksize);
- }
- ss->ss_datasum = crc_data;
-}
-
-static void
-create_fsdata(void)
-{
- struct uuid tmp;
-
- memset(&fsdata, 0, sizeof(struct nandfs_fsdata));
-
- fsdata.f_magic = NANDFS_FSDATA_MAGIC;
- fsdata.f_nsegments = nsegments;
- fsdata.f_erasesize = erasesize;
- fsdata.f_first_data_block = NANDFS_FIRST_BLOCK;
- fsdata.f_blocks_per_segment = blocks_per_segment;
- fsdata.f_r_segments_percentage = rsv_segment_percent;
- fsdata.f_rev_level = NANDFS_CURRENT_REV;
- fsdata.f_sbbytes = NANDFS_SB_BYTES;
- fsdata.f_bytes = NANDFS_FSDATA_CRC_BYTES;
- fsdata.f_ctime = nandfs_time;
- fsdata.f_log_block_size = nandfs_log2(blocksize) - 10;
- fsdata.f_errors = 1;
- fsdata.f_inode_size = sizeof(struct nandfs_inode);
- fsdata.f_dat_entry_size = sizeof(struct nandfs_dat_entry);
- fsdata.f_checkpoint_size = sizeof(struct nandfs_checkpoint);
- fsdata.f_segment_usage_size = sizeof(struct nandfs_segment_usage);
-
- uuidgen(&tmp, 1);
- fsdata.f_uuid = tmp;
-
- if (volumelabel)
- memcpy(fsdata.f_volume_name, volumelabel, 16);
-
- fsdata.f_sum = crc32_le(0, (const uint8_t *)&fsdata,
- NANDFS_FSDATA_CRC_BYTES);
-}
-
-static void
-save_fsdata(void *data)
-{
-
- memcpy(data, &fsdata, sizeof(fsdata));
-}
-
-static void
-create_super_block(void)
-{
-
- memset(&super_block, 0, sizeof(struct nandfs_super_block));
-
- super_block.s_magic = NANDFS_SUPER_MAGIC;
- super_block.s_last_cno = NANDFS_FIRST_CNO;
- super_block.s_last_pseg = NANDFS_FIRST_BLOCK;
- super_block.s_last_seq = 1;
- super_block.s_free_blocks_count =
- (nsegments - bad_segments_count) * blocks_per_segment;
- super_block.s_mtime = 0;
- super_block.s_wtime = nandfs_time;
- super_block.s_state = NANDFS_VALID_FS;
-
- super_block.s_sum = crc32_le(0, (const uint8_t *)&super_block,
- NANDFS_SB_BYTES);
-}
-
-static void
-save_super_block(void *data)
-{
-
- memcpy(data, &super_block, sizeof(super_block));
-}
-
-static void
-save_super_root(void)
-{
-
- sr->sr_bytes = NANDFS_SR_BYTES;
- sr->sr_flags = 0;
- sr->sr_nongc_ctime = nandfs_time;
- datfile.inode = &sr->sr_dat;
- cpfile.inode = &sr->sr_cpfile;
- sufile.inode = &sr->sr_sufile;
-}
-
-static struct nandfs_dir_entry *
-add_de(void *block, struct nandfs_dir_entry *de, uint64_t ino,
- const char *name, uint8_t type)
-{
- uint16_t reclen;
-
- /* modify last de */
- de->rec_len = NANDFS_DIR_REC_LEN(de->name_len);
- de = (void *)((uint8_t *)de + de->rec_len);
-
- reclen = blocksize - ((uintptr_t)de - (uintptr_t)block);
- if (reclen < NANDFS_DIR_REC_LEN(strlen(name))) {
- printf("nandfs: too many dir entries for one block\n");
- return (NULL);
- }
-
- de->inode = ino;
- de->rec_len = reclen;
- de->name_len = strlen(name);
- de->file_type = type;
- memset(de->name, 0,
- (strlen(name) + NANDFS_DIR_PAD - 1) & ~NANDFS_DIR_ROUND);
- memcpy(de->name, name, strlen(name));
-
- return (de);
-}
-
-static struct nandfs_dir_entry *
-make_dir(void *block, uint64_t ino, uint64_t parent_ino)
-{
- struct nandfs_dir_entry *de = (struct nandfs_dir_entry *)block;
-
- /* create '..' entry */
- de->inode = parent_ino;
- de->rec_len = NANDFS_DIR_REC_LEN(2);
- de->name_len = 2;
- de->file_type = DT_DIR;
- memset(de->name, 0, NANDFS_DIR_NAME_LEN(2));
- memcpy(de->name, "..", 2);
-
- /* create '.' entry */
- de = (void *)((uint8_t *)block + NANDFS_DIR_REC_LEN(2));
- de->inode = ino;
- de->rec_len = blocksize - NANDFS_DIR_REC_LEN(2);
- de->name_len = 1;
- de->file_type = DT_DIR;
- memset(de->name, 0, NANDFS_DIR_NAME_LEN(1));
- memcpy(de->name, ".", 1);
-
- return (de);
-}
-
-static void
-save_root_dir(void)
-{
- struct file_info *root = &user_files[0];
- struct nandfs_dir_entry *de;
- uint32_t i;
- void *block;
-
- block = get_block(root->blocks[0], 0);
-
- de = make_dir(block, root->ino, root->ino);
- for (i = 1; i < nuserfiles; i++)
- de = add_de(block, de, user_files[i].ino, user_files[i].name,
- IFTODT(user_files[i].mode));
-
- root->size = ((uintptr_t)de - (uintptr_t)block) +
- NANDFS_DIR_REC_LEN(de->name_len);
-}
-
-static void
-save_sufile(void)
-{
- struct nandfs_sufile_header *header;
- struct nandfs_segment_usage *su;
- uint64_t blk, i, off;
- void *block;
- int start;
-
- /*
- * At the beginning just zero-out everything
- */
- for (i = 0; i < sufile.nblocks; i++)
- get_block(sufile.blocks[i], 0);
-
- start = 0;
-
- block = get_block(sufile.blocks[start], 0);
- header = (struct nandfs_sufile_header *)block;
- header->sh_ncleansegs = nsegments - bad_segments_count - 1;
- header->sh_ndirtysegs = 1;
- header->sh_last_alloc = 1;
-
- su = (struct nandfs_segment_usage *)header;
- off = NANDFS_SUFILE_FIRST_SEGMENT_USAGE_OFFSET;
- /* Allocate data segment */
- su[off].su_lastmod = nandfs_time;
- /* nblocks = segment blocks + segsum block + superroot */
- su[off].su_nblocks = seg_nblocks + 2;
- su[off].su_flags = NANDFS_SEGMENT_USAGE_DIRTY;
- off++;
- /* Allocate next segment */
- su[off].su_lastmod = nandfs_time;
- su[off].su_nblocks = 0;
- su[off].su_flags = NANDFS_SEGMENT_USAGE_DIRTY;
- for (i = 0; i < bad_segments_count; i++) {
- nandfs_seg_usage_blk_offset(bad_segments[i], &blk, &off);
- debug("storing bad_segments[%jd]=%x at %jx off %jx\n", i,
- bad_segments[i], blk, off);
- block = get_block(sufile.blocks[blk],
- off * sizeof(struct nandfs_segment_usage *));
- su = (struct nandfs_segment_usage *)block;
- su[off].su_lastmod = nandfs_time;
- su[off].su_nblocks = 0;
- su[off].su_flags = NANDFS_SEGMENT_USAGE_ERROR;
- }
-}
-
-static void
-save_cpfile(void)
-{
- struct nandfs_cpfile_header *header;
- struct nandfs_checkpoint *cp, *initial_cp;
- int i, entries = blocksize / sizeof(struct nandfs_checkpoint);
- uint64_t cno;
-
- header = (struct nandfs_cpfile_header *)get_block(cpfile.blocks[0], 0);
- header->ch_ncheckpoints = 1;
- header->ch_nsnapshots = 0;
-
- cp = (struct nandfs_checkpoint *)header;
-
- /* fill first checkpoint data*/
- initial_cp = &cp[NANDFS_CPFILE_FIRST_CHECKPOINT_OFFSET];
- initial_cp->cp_flags = 0;
- initial_cp->cp_checkpoints_count = 0;
- initial_cp->cp_cno = NANDFS_FIRST_CNO;
- initial_cp->cp_create = nandfs_time;
- initial_cp->cp_nblk_inc = seg_endblock - 1;
- initial_cp->cp_blocks_count = seg_nblocks;
- memset(&initial_cp->cp_snapshot_list, 0,
- sizeof(struct nandfs_snapshot_list));
-
- ifile.inode = &initial_cp->cp_ifile_inode;
-
- /* mark rest of cp as invalid */
- cno = NANDFS_FIRST_CNO + 1;
- i = NANDFS_CPFILE_FIRST_CHECKPOINT_OFFSET + 1;
- for (; i < entries; i++) {
- cp[i].cp_cno = cno++;
- cp[i].cp_flags = NANDFS_CHECKPOINT_INVALID;
- }
-}
-
-static void
-init_inode(struct nandfs_inode *inode, struct file_info *file)
-{
-
- inode->i_blocks = file->nblocks;
- inode->i_ctime = nandfs_time;
- inode->i_mtime = nandfs_time;
- inode->i_mode = file->mode & 0xffff;
- inode->i_links_count = 1;
-
- if (file->size > 0)
- inode->i_size = file->size;
- else
- inode->i_size = 0;
-
- if (file->ino == NANDFS_USER_INO)
- inode->i_flags = SF_NOUNLINK|UF_NOUNLINK;
- else
- inode->i_flags = 0;
-}
-
-static void
-save_ifile(void)
-{
- struct nandfs_inode *inode;
- struct file_info *file;
- uint64_t ino, blk, off;
- uint32_t i;
-
- prepare_blockgrouped_file(ifile.blocks[0]);
- for (i = 0; i <= NANDFS_USER_INO; i++)
- alloc_blockgrouped_file(ifile.blocks[0], i);
-
- for (i = 0; i < nuserfiles; i++) {
- file = &user_files[i];
- ino = file->ino;
- blk = ino / (blocksize / sizeof(*inode));
- off = ino % (blocksize / sizeof(*inode));
- inode =
- (struct nandfs_inode *)get_block(ifile.blocks[2 + blk], 2 + blk);
- file->inode = &inode[off];
- init_inode(file->inode, file);
- }
-
- init_inode(ifile.inode, &ifile);
- init_inode(cpfile.inode, &cpfile);
- init_inode(sufile.inode, &sufile);
- init_inode(datfile.inode, &datfile);
-}
-
-static int
-create_fs(void)
-{
- uint64_t start_block;
- uint32_t segsum_size;
- char *data;
- int i;
-
- nuserfiles = nitems(user_files);
-
- /* Count and assign blocks */
- count_seg_blocks();
- segsum_size = segment_size();
- start_block = NANDFS_FIRST_BLOCK + SIZE_TO_BLOCK(segsum_size);
- assign_file_blocks(start_block);
-
- /* Create super root structure */
- save_super_root();
-
- /* Create root directory */
- save_root_dir();
-
- /* Fill in file contents */
- save_sufile();
- save_cpfile();
- save_ifile();
- save_datfile();
-
- /* Save fsdata and superblocks */
- create_fsdata();
- create_super_block();
-
- for (i = 0; i < NANDFS_NFSAREAS; i++) {
- if (fsdata_blocks_state[i] != NANDFS_BLOCK_GOOD)
- continue;
-
- data = get_block((i * erasesize)/blocksize, 0);
- save_fsdata(data);
-
- data = get_block((i * erasesize + NANDFS_SBLOCK_OFFSET_BYTES) /
- blocksize, 0);
- if (blocksize > NANDFS_SBLOCK_OFFSET_BYTES)
- data += NANDFS_SBLOCK_OFFSET_BYTES;
- save_super_block(data);
- memset(data + sizeof(struct nandfs_super_block), 0xff,
- (blocksize - sizeof(struct nandfs_super_block) -
- NANDFS_SBLOCK_OFFSET_BYTES));
- }
-
- /* Save segment summary and CRCs */
- save_segsum(get_block(NANDFS_FIRST_BLOCK, 0));
-
- return (0);
-}
-
-static void
-write_fs(int fda)
-{
- struct nandfs_block *block;
- char *data;
- u_int ret;
-
- /* Overwrite next block with ff if not nand device */
- if (!is_nand) {
- data = get_block(seg_endblock, 0);
- memset(data, 0xff, blocksize);
- }
-
- LIST_FOREACH(block, &block_head, block_link) {
- lseek(fda, block->number * blocksize, SEEK_SET);
- ret = write(fda, block->data, blocksize);
- if (ret != blocksize)
- err(1, "cannot write filesystem data");
- }
-}
-
-static void
-check_parameters(void)
-{
- int i;
-
- /* check blocksize */
- if ((blocksize < NANDFS_MIN_BLOCKSIZE) || (blocksize > MAXBSIZE) ||
- ((blocksize - 1) & blocksize)) {
- errx(1, "Bad blocksize (%zu). Must be in range [%u-%u] "
- "and a power of two.", blocksize, NANDFS_MIN_BLOCKSIZE,
- MAXBSIZE);
- }
-
- /* check blocks per segments */
- if ((blocks_per_segment < NANDFS_SEG_MIN_BLOCKS) ||
- ((blocksize - 1) & blocksize))
- errx(1, "Bad blocks per segment (%lu). Must be greater than "
- "%u and a power of two.", blocks_per_segment,
- NANDFS_SEG_MIN_BLOCKS);
-
- /* check reserved segment percentage */
- if ((rsv_segment_percent < 1) || (rsv_segment_percent > 99))
- errx(1, "Bad reserved segment percentage. "
- "Must in range 1..99.");
-
- /* check volume label */
- i = 0;
- if (volumelabel) {
- while (isalnum(volumelabel[++i]))
- ;
-
- if (volumelabel[i] != '\0') {
- errx(1, "bad volume label. "
- "Valid characters are alphanumerics.");
- }
-
- if (strlen(volumelabel) >= 16)
- errx(1, "Bad volume label. Length is longer than %d.",
- 16);
- }
-
- nandfs_time = time(NULL);
-}
-
-static void
-print_parameters(void)
-{
-
- printf("filesystem parameters:\n");
- printf("blocksize: %#zx sectorsize: %#zx\n", blocksize, sectorsize);
- printf("erasesize: %#jx mediasize: %#jx\n", erasesize, mediasize);
- printf("segment size: %#jx blocks per segment: %#x\n", segsize,
- (uint32_t)blocks_per_segment);
-}
-
-/*
- * Exit with error if file system is mounted.
- */
-static void
-check_mounted(const char *fname, mode_t mode)
-{
- struct statfs *mp;
- const char *s1, *s2;
- size_t len;
- int n, r;
-
- if (!(n = getmntinfo(&mp, MNT_NOWAIT)))
- err(1, "getmntinfo");
-
- len = strlen(_PATH_DEV);
- s1 = fname;
- if (!strncmp(s1, _PATH_DEV, len))
- s1 += len;
-
- r = S_ISCHR(mode) && s1 != fname && *s1 == 'r';
-
- for (; n--; mp++) {
- s2 = mp->f_mntfromname;
-
- if (!strncmp(s2, _PATH_DEV, len))
- s2 += len;
- if ((r && s2 != mp->f_mntfromname && !strcmp(s1 + 1, s2)) ||
- !strcmp(s1, s2))
- errx(1, "%s is mounted on %s", fname, mp->f_mntonname);
- }
-}
-
-static void
-calculate_geometry(int fd)
-{
- struct chip_param_io chip_params;
- char ident[DISK_IDENT_SIZE];
- char medianame[MAXPATHLEN];
-
- /* Check storage type */
- g_get_ident(fd, ident, DISK_IDENT_SIZE);
- g_get_name(ident, medianame, MAXPATHLEN);
- debug("device name: %s", medianame);
-
- is_nand = (strstr(medianame, "gnand") != NULL);
- debug("is_nand = %d", is_nand);
-
- sectorsize = g_sectorsize(fd);
- debug("sectorsize: %#zx", sectorsize);
-
- /* Get storage size */
- mediasize = g_mediasize(fd);
- debug("mediasize: %#jx", mediasize);
-
- /* Get storage erase unit size */
- if (!is_nand)
- erasesize = NANDFS_DEF_ERASESIZE;
- else if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) != -1)
- erasesize = chip_params.page_size * chip_params.pages_per_block;
- else
- errx(1, "Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
-
- debug("erasesize: %#jx", (uintmax_t)erasesize);
-
- if (blocks_per_segment == 0) {
- if (erasesize >= NANDFS_MIN_SEGSIZE)
- blocks_per_segment = erasesize / blocksize;
- else
- blocks_per_segment = NANDFS_MIN_SEGSIZE / blocksize;
- }
-
- /* Calculate number of segments */
- segsize = blocksize * blocks_per_segment;
- nsegments = ((mediasize - NANDFS_NFSAREAS * erasesize) / segsize) - 2;
- debug("segsize: %#jx", segsize);
- debug("nsegments: %#jx", nsegments);
-}
-
-static void
-erase_device(int fd)
-{
- int rest, failed;
- uint64_t i, nblocks;
- off_t offset;
-
- failed = 0;
- for (i = 0; i < NANDFS_NFSAREAS; i++) {
- debug("Deleting %jx\n", i * erasesize);
- if (g_delete(fd, i * erasesize, erasesize)) {
- printf("cannot delete %jx\n", i * erasesize);
- fsdata_blocks_state[i] = NANDFS_BLOCK_BAD;
- failed++;
- } else
- fsdata_blocks_state[i] = NANDFS_BLOCK_GOOD;
- }
-
- if (failed == NANDFS_NFSAREAS) {
- printf("%d first blocks not usable. Unable to create "
- "filesystem.\n", failed);
- exit(1);
- }
-
- for (i = 0; i < nsegments; i++) {
- offset = NANDFS_NFSAREAS * erasesize + i * segsize;
- if (g_delete(fd, offset, segsize)) {
- printf("cannot delete segment %jx (offset %jd)\n",
- i, offset);
- bad_segments_count++;
- bad_segments = realloc(bad_segments,
- bad_segments_count * sizeof(uint32_t));
- bad_segments[bad_segments_count - 1] = i;
- }
- }
-
- if (bad_segments_count == nsegments) {
- printf("no valid segments\n");
- exit(1);
- }
-
- /* Delete remaining blocks at the end of device */
- rest = mediasize % segsize;
- nblocks = rest / erasesize;
- for (i = 0; i < nblocks; i++) {
- offset = (segsize * nsegments) + (i * erasesize);
- if (g_delete(fd, offset, erasesize)) {
- printf("cannot delete space after last segment "
- "- probably a bad block\n");
- }
- }
-}
-
-static void
-erase_initial(int fd)
-{
- char buf[512];
- u_int i;
-
- memset(buf, 0xff, sizeof(buf));
-
- lseek(fd, 0, SEEK_SET);
- for (i = 0; i < NANDFS_NFSAREAS * erasesize; i += sizeof(buf))
- write(fd, buf, sizeof(buf));
-}
-
-static void
-create_nandfs(int fd)
-{
-
- create_fs();
-
- write_fs(fd);
-}
-
-static void
-print_summary(void)
-{
-
- printf("filesystem was created successfully\n");
- printf("total segments: %#jx valid segments: %#jx\n", nsegments,
- nsegments - bad_segments_count);
- printf("total space: %ju MB free: %ju MB\n",
- (nsegments *
- blocks_per_segment * blocksize) / (1024 * 1024),
- ((nsegments - bad_segments_count) *
- blocks_per_segment * blocksize) / (1024 * 1024));
-}
-
-int
-main(int argc, char *argv[])
-{
- struct stat sb;
- char buf[MAXPATHLEN];
- const char opts[] = "b:B:L:m:";
- const char *fname;
- int ch, fd;
-
- while ((ch = getopt(argc, argv, opts)) != -1) {
- switch (ch) {
- case 'b':
- blocksize = strtol(optarg, (char **)NULL, 10);
- if (blocksize == 0)
- usage();
- break;
- case 'B':
- blocks_per_segment = strtol(optarg, (char **)NULL, 10);
- if (blocks_per_segment == 0)
- usage();
- break;
- case 'L':
- volumelabel = optarg;
- break;
- case 'm':
- rsv_segment_percent = strtol(optarg, (char **)NULL, 10);
- if (rsv_segment_percent == 0)
- usage();
- break;
- default:
- usage();
- }
- }
-
- argc -= optind;
- argv += optind;
- if (argc < 1 || argc > 2)
- usage();
-
- /* construct proper device path */
- fname = *argv++;
- if (!strchr(fname, '/')) {
- snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname);
- if (!(fname = strdup(buf)))
- err(1, NULL);
- }
-
- fd = g_open(fname, 1);
- if (fd == -1)
- err(1, "Cannot open %s", fname);
-
- if (fstat(fd, &sb) == -1)
- err(1, "Cannot stat %s", fname);
- if (!S_ISCHR(sb.st_mode))
- warnx("%s is not a character device", fname);
-
- check_mounted(fname, sb.st_mode);
-
- calculate_geometry(fd);
-
- check_parameters();
-
- print_parameters();
-
- if (is_nand)
- erase_device(fd);
- else
- erase_initial(fd);
-
- create_nandfs(fd);
-
- print_summary();
-
- g_close(fd);
-
- return (0);
-}
-
-
diff --git a/sbin/swapon/swapon.8 b/sbin/swapon/swapon.8
index 058f681ce5ce..f69dd484a93b 100644
--- a/sbin/swapon/swapon.8
+++ b/sbin/swapon/swapon.8
@@ -28,7 +28,7 @@
.\" @(#)swapon.8 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd October 21, 2016
+.Dd June 21, 2019
.Dt SWAPON 8
.Os
.Sh NAME
@@ -38,7 +38,7 @@
.Nm swapon
.Oo Fl F Ar fstab
.Oc
-.Fl aLq | Ar
+.Fl aLq | E Ar
.Nm swapoff
.Oo Fl F Ar fstab
.Oc
@@ -86,6 +86,11 @@ If the
option is used,
informational messages will not be
written to standard output when a swap device is added.
+The
+.Fl E
+option causes each of following devices to receive a
+.Dv BIO_DELETE
+command to mark all blocks as unused.
.Pp
The
.Nm swapoff
diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c
index 83201535b4ab..e6c8b7eb215d 100644
--- a/sbin/swapon/swapon.c
+++ b/sbin/swapon/swapon.c
@@ -44,7 +44,7 @@ static char sccsid[] = "@(#)swapon.c 8.1 (Berkeley) 6/5/93";
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/types.h>
+#include <sys/disk.h>
#include <sys/mdioctl.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
@@ -77,7 +77,7 @@ static int run_cmd(int *, const char *, ...) __printflike(2, 3);
static enum { SWAPON, SWAPOFF, SWAPCTL } orig_prog, which_prog = SWAPCTL;
-static int qflag;
+static int Eflag, qflag;
int
main(int argc, char **argv)
@@ -100,7 +100,7 @@ main(int argc, char **argv)
doall = 0;
etc_fstab = NULL;
- while ((ch = getopt(argc, argv, "AadghklLmqsUF:")) != -1) {
+ while ((ch = getopt(argc, argv, "AadEghklLmqsUF:")) != -1) {
switch(ch) {
case 'A':
if (which_prog == SWAPCTL) {
@@ -121,6 +121,12 @@ main(int argc, char **argv)
else
usage();
break;
+ case 'E':
+ if (which_prog == SWAPON)
+ Eflag = 2;
+ else
+ usage();
+ break;
case 'g':
hflag = 'G';
break;
@@ -182,8 +188,10 @@ main(int argc, char **argv)
strstr(fsp->fs_mntops, "late") == NULL &&
late != 0)
continue;
+ Eflag |= (strstr(fsp->fs_mntops, "trimonce") != NULL);
swfile = swap_on_off(fsp->fs_spec, 1,
fsp->fs_mntops);
+ Eflag &= ~1;
if (swfile == NULL) {
ret = 1;
continue;
@@ -378,12 +386,22 @@ swap_on_geli_args(const char *mntops)
return (NULL);
}
} else if (strcmp(token, "notrim") == 0) {
+ if (Eflag) {
+ warn("Options \"notrim\" and "
+ "\"trimonce\" conflict");
+ free(ops);
+ return (NULL);
+ }
Tflag = " -T ";
} else if (strcmp(token, "late") == 0) {
/* ignore known option */
} else if (strcmp(token, "noauto") == 0) {
/* ignore known option */
- } else if (strcmp(token, "sw") != 0) {
+ } else if (strcmp(token, "sw") == 0) {
+ /* ignore known option */
+ } else if (strcmp(token, "trimonce") == 0) {
+ /* ignore known option */
+ } else {
warnx("Invalid option: %s", token);
free(ops);
return (NULL);
@@ -721,14 +739,42 @@ run_cmd(int *ofd, const char *cmdline, ...)
return (WEXITSTATUS(status));
}
+static void
+swap_trim(const char *name)
+{
+ struct stat sb;
+ off_t ioarg[2], sz;
+ int fd;
+
+ fd = open(name, O_WRONLY);
+ if (fd < 0)
+ errx(1, "Cannot open %s", name);
+ if (fstat(fd, &sb) < 0)
+ errx(1, "Cannot stat %s", name);
+ if (S_ISREG(sb.st_mode))
+ sz = sb.st_size;
+ else if (S_ISCHR(sb.st_mode)) {
+ if (ioctl(fd, DIOCGMEDIASIZE, &sz) != 0)
+ err(1, "ioctl(DIOCGMEDIASIZE)");
+ } else
+ errx(1, "%s has an invalid file type", name);
+ ioarg[0] = 0;
+ ioarg[1] = sz;
+ if (ioctl(fd, DIOCGDELETE, ioarg) != 0)
+ warn("ioctl(DIOCGDELETE)");
+ close(fd);
+}
+
static const char *
swap_on_off_sfile(const char *name, int doingall)
{
int error;
- if (which_prog == SWAPON)
+ if (which_prog == SWAPON) {
+ if (Eflag)
+ swap_trim(name);
error = swapon(name);
- else /* SWAPOFF */
+ } else /* SWAPOFF */
error = swapoff(name);
if (error == -1) {
@@ -759,6 +805,8 @@ usage(void)
fprintf(stderr, "usage: %s ", getprogname());
switch(orig_prog) {
case SWAPON:
+ fprintf(stderr, "[-F fstab] -aLq | [-E] file ...\n");
+ break;
case SWAPOFF:
fprintf(stderr, "[-F fstab] -aLq | file ...\n");
break;
diff --git a/share/examples/etc/make.conf b/share/examples/etc/make.conf
index 8a9fa90ac12a..f9463c334631 100644
--- a/share/examples/etc/make.conf
+++ b/share/examples/etc/make.conf
@@ -49,6 +49,12 @@
# icelake-client, cannonlake, knm, skylake-avx512, knl,
# goldmont, skylake, broadwell, haswell, ivybridge,
# sandybridge, westmere, nehalem, silvermont, bonnell
+# ARM architecture: armv5, armv5te, armv6, armv6t2, arm1176jzf-s, armv7,
+# armv7-a, armv7ve, generic-armv7-a, cortex-a5,
+# cortex-a7, cortex-a8, cortex-a9, cortex-a12,
+# cortex-a15, cortex-a17
+# ARM64 architechture: cortex-a53, cortex-a57, cortex-a72,
+# exynos-m1
#
# (?= allows to buildworld for a different CPUTYPE.)
#
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index a810d9153349..13c3069b8172 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -303,8 +303,6 @@ MAN= aac.4 \
mx25l.4 \
mxge.4 \
my.4 \
- nand.4 \
- nandsim.4 \
${_ndis.4} \
net80211.4 \
netdump.4 \
diff --git a/share/man/man4/gpio.4 b/share/man/man4/gpio.4
index 0e2c8cdb1423..da95c39f8e98 100644
--- a/share/man/man4/gpio.4
+++ b/share/man/man4/gpio.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 5, 2013
+.Dd June 27, 2019
.Dt GPIO 4
.Os
.Sh NAME
@@ -103,12 +103,50 @@ passed to the kernel, being either statically compiled in, or by a variety
of ways where the boot loader (or Open Firmware enabled system) passes the
DTS blob to the kernel at boot.
.Pp
+On a
+.Xr device.hints 5
+based system these hints can be used to configure drivers for devices
+attached to
+.Nm
+pins:
+.Bl -tag -width ".Va hint.driver.unit.pin_list"
+.It Va hint.driver.unit.at
+The
+.Nm gpiobus
+where the device is attached.
+For example,
+.Qq gpiobus0 .
+.Ar driver
+and
+.Ar unit
+are the driver name and the unit number for the device driver.
+.It Va hint.driver.unit.pins
+This is a bitmask of the pins on the
+.Nm gpiobus
+that are connected to the device.
+The pins will be allocated to the specified driver instance.
+Only pins with numbers from 0 to 31 can be specified using this hint.
+.It Va hint.driver.unit.pin_list
+This is a list of pin numbers of pins on the
+.Nm gpiobus
+that are connected to the device.
+The pins will be allocated to the specified driver instance.
+This is a more user friendly alternative to the
+.Ar pins
+hint.
+Additionally, this hint allows specifying pin numbers greater than 31.
+The numbers can be decimal or hexadecimal with 0x prefix.
+Any non-digit character can be used as a separator.
+For example, it can be a comma, a slash or a space.
+The separator can be followed by any number of space characters.
+.El
+.Pp
The following
.Xr device.hints 5
are only provided by the
.Cd ar71xx_gpio
driver:
-.Bl -tag -width ".Va hint.gpioiic.%d.atXXX"
+.Bl -tag -width ".Va hint.gpio.function_clear"
.It Va hint.gpio.%d.pinmask
This is a bitmask of pins on the GPIO board that we would like to expose
for use to the host operating system.
@@ -133,6 +171,7 @@ of some device in a system.
.Xr gpioiic 4 ,
.Xr gpioled 4 ,
.Xr iicbus 4 ,
+.Xr device.hints 5 ,
.Xr gpioctl 8
.Sh HISTORY
The
diff --git a/share/man/man4/nand.4 b/share/man/man4/nand.4
deleted file mode 100644
index 5c868a1151e6..000000000000
--- a/share/man/man4/nand.4
+++ /dev/null
@@ -1,145 +0,0 @@
-.\"
-.\" Copyright (c) 2012 The FreeBSD Foundation
-.\" All rights reserved.
-.\"
-.\" This documentation was written by Semihalf under sponsorship from
-.\" the FreeBSD Foundation.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd March 8, 2012
-.Dt NAND 4
-.Os
-.Sh NAME
-.Nm nand
-.Nd NAND Flash framework
-.Sh SYNOPSIS
-.Cd "device nand"
-.Sh DESCRIPTION
-The
-.Fx
-.Nm
-framework consists of a set of interfaces that aim to provide an extensible,
-object oriented environment for NAND controllers and NAND Flash memory chips
-from various hardware vendors, and to allow for uniform and flexible
-management of the NAND devices.
-It comprises of the following major components:
-.Bl -bullet
-.It
-NAND Flash controller (NFC) interface.
-.Pp
-Defines methods which allow to send commands as well as send/receive data
-between the controller and a NAND chip.
-Back-end drivers for specific NAND
-controllers plug into this interface and implement low-level routines for a
-given NAND controller.
-.Pp
-This layer implements basic functionality of a NAND Flash controller.
-It allows to send command and address to chip, drive CS (chip select line),
-as well as read/write to the selected NAND chip.
-This layer is independent of
-NAND chip devices actually connected to the controller.
-.It
-NAND chip interface.
-.Pp
-Provides basic operations like read page, program page, erase block.
-Currently three generic classes of drivers are available, which provide
-support for the following chips:
-.Bl -bullet
-.It
-large page
-.It
-small page
-.It
-ONFI-compliant
-.El
-.Pp
-This layer implements basic operations to be performed on a NAND chip, like
-read, program, erase, get status etc.
-Since these operations use specific
-commands (depending on the vendor), each chip has potentially its own
-implementation of the commands set.
-.Pp
-The framework is extensible so it is also possible to create a custom command
-set for a non standard chip support.
-.It
-NANDbus.
-.Pp
-This layer is responsible for enumerating NAND chips in the system and
-establishing the hierarchy between chips and their supervising controllers.
-.Pp
-Its main purpose is detecting type of NAND chips connected to a given chip
-select (CS line).
-It also allows manages locking access to the NAND
-controller.
-NANDbus passes requests from an active chip to the chip controller.
-.It
-NAND character / GEOM device.
-.Pp
-For each NAND chip found in a system a character and GEOM devices are created
-which allows to read / write directly to a device, as well as perform other
-specific operations (like via ioctl).
-.Pp
-There are two GEOM devices created for each NAND chip:
-.Bl -bullet
-.It
-raw device
-.It
-normal device
-.El
-.Pp
-Raw device allows to bypass ECC checking when reading/writing to it, while
-normal device always uses ECC algorithm to validate the read data.
-.Pp
-NAND character devices will be created for each NAND chip detected while
-probing the NAND controller.
-.El
-.Sh SEE ALSO
-.Xr libnandfs 3 ,
-.Xr gnand 4 ,
-.Xr nandsim 4 ,
-.Xr nandfs 5 ,
-.Xr makefs 8 ,
-.Xr mount_nandfs 8 ,
-.Xr nandfs 8 ,
-.Xr nandsim 8 ,
-.Xr nandtool 8 ,
-.Xr newfs_nandfs 8 ,
-.Xr umount_nandfs 8
-.Sh STANDARDS
-Open NAND Flash Interface Working Group
-.Pq Vt ONFI .
-.Sh HISTORY
-The
-.Nm
-framework support first appeared in
-.Fx 10.0 .
-.Sh AUTHORS
-.An -nosplit
-The
-.Nm
-framework was designed and developed by
-.An Grzegorz Bernacki .
-This manual page was written by
-.An Rafal Jaworowski .
diff --git a/share/man/man4/nandsim.4 b/share/man/man4/nandsim.4
deleted file mode 100644
index bf8d624eeb8a..000000000000
--- a/share/man/man4/nandsim.4
+++ /dev/null
@@ -1,93 +0,0 @@
-.\"
-.\" Copyright (c) 2012 The FreeBSD Foundation
-.\" All rights reserved.
-.\"
-.\" This documentation was written by Semihalf under sponsorship from
-.\" the FreeBSD Foundation.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd March 8, 2012
-.Dt NANDSIM 4
-.Os
-.Sh NAME
-.Nm nandsim
-.Nd NAND Flash simulator driver
-.Sh SYNOPSIS
-.Cd "device nand"
-.Cd "device nandsim"
-.Cd "options ALQ"
-.Sh DESCRIPTION
-The
-.Nm
-is part of the
-.Fx
-NAND framework
-.Xr nand 4
-and can be characterized with the following highlights:
-.Bl -bullet
-.It
-plugs into the
-.Xr nand 4
-framework APIs as if it were a hardware controller (hanging on the nexus bus)
-with real NAND chips connected to it
-.It
-physically part of the kernel code (either statically linked into the kernel
-image or built as a module)
-.It
-controlled with a user space program
-.Xr nandsim 8
-.El
-.Pp
-From the user perspective, the
-.Nm
-allows for imitating ONFI-compliant NAND Flash devices as if they were
-attached to the system via a virtual controller.
-.Pp
-Some
-.Nm
-features rely on the ability to log contents to a file, which is achieved
-through the
-.Xr alq 9
-facility.
-.Sh SEE ALSO
-.Xr nand 4 ,
-.Xr nandsim.conf 5 ,
-.Xr nandsim 8
-.Sh STANDARDS
-Open NAND Flash Interface Working Group
-.Pq Vt ONFI .
-.Sh HISTORY
-The
-.Nm
-support first appeared in
-.Fx 10.0 .
-.Sh AUTHORS
-.An -nosplit
-The
-.Nm
-kernel driver was developed by
-.An Grzegorz Bernacki .
-This manual page was written by
-.An Rafal Jaworowski .
diff --git a/share/man/man4/owc.4 b/share/man/man4/owc.4
index 43d6cb776ae4..06c4e909ac96 100644
--- a/share/man/man4/owc.4
+++ b/share/man/man4/owc.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 20, 2015
+.Dd June 26, 2019
.Dt OWC 4
.Os
.Sh NAME
@@ -69,6 +69,24 @@ For more details about the
.Va gpios
property, please consult
.Pa /usr/src/sys/dts/bindings-gpio.txt .
+.Pp
+On a
+.Xr device.hints 5
+based system these values are required for the
+.Nm :
+.Bl -tag -width ".Va hint.owc.%d.atXXX"
+.It Va hint.owc.%d.at
+The
+.Nm gpiobus
+you are attaching to.
+.It Va hint.owc.%d.pins
+This is a bitmask that defines a pin on the
+.Nm gpiobus
+that is to be used for the 1-Wire bus.
+For instance, to configure pin 10, use the bitmask of 0x400.
+Please note that this mask should have only one bit set
+(any other bits - i.e., pins - will be ignored).
+.El
.Sh SEE ALSO
.Xr gpiobus 4 ,
.Xr ow 4 ,
diff --git a/share/man/man4/random.4 b/share/man/man4/random.4
index 0ccad03aeda4..3b3f9b2330e3 100644
--- a/share/man/man4/random.4
+++ b/share/man/man4/random.4
@@ -30,7 +30,6 @@
.Nm random
.Nd the entropy device
.Sh SYNOPSIS
-.Cd "device random"
.Cd "options RANDOM_LOADABLE"
.Cd "options RANDOM_ENABLE_ETHER"
.Cd "options RANDOM_ENABLE_UMA"
diff --git a/share/man/man5/Makefile b/share/man/man5/Makefile
index b5ec870f75ff..119869128acb 100644
--- a/share/man/man5/Makefile
+++ b/share/man/man5/Makefile
@@ -101,10 +101,6 @@ MAN+= freebsd-update.conf.5
MAN+= hesiod.conf.5
.endif
-.if ${MK_NAND} != "no"
-MAN+= nandfs.5
-.endif
-
.if ${MK_PF} != "no"
MAN+= pf.conf.5 \
pf.os.5
diff --git a/share/man/man5/fstab.5 b/share/man/man5/fstab.5
index 062ab601851f..f4e9ce2b653e 100644
--- a/share/man/man5/fstab.5
+++ b/share/man/man5/fstab.5
@@ -216,6 +216,12 @@ then the special file is made available as a piece of swap
space by the
.Xr swapon 8
command at the end of the system reboot procedure.
+For swap devices, the keyword
+.Dq trimonce
+triggers the delivery of a
+.Dv BIO_DELETE
+command to the device to mark
+all blocks as unused.
For vnode-backed swap spaces,
.Dq file
is supported in the
diff --git a/share/man/man5/nandfs.5 b/share/man/man5/nandfs.5
deleted file mode 100644
index 7e895993674d..000000000000
--- a/share/man/man5/nandfs.5
+++ /dev/null
@@ -1,132 +0,0 @@
-.\"
-.\" Copyright (c) 2010 Semihalf
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd Nov 11, 2010
-.Dt NANDFS 5
-.Os
-.Sh NAME
-.Nm nandfs
-.Nd NAND Flash file system
-.Sh SYNOPSIS
-To compile support for the
-.Nm ,
-place the following in your kernel configuration file:
-.Bd -ragged -offset indent
-.Cd "options NANDFS"
-.Ed
-.Pp
-Even though the NAND FS can be used with any storage media, it has been
-optimized and designed towards NAND Flash devices, so typically the following
-driver is used:
-.Bd -ragged -offset indent
-.Cd "device nand"
-.Ed
-.Sh DESCRIPTION
-The
-.Nm
-driver enables
-.Fx
-with support for NAND-oriented file system.
-.Pp
-It is a log-structured style file system with the following major features and
-characteristics:
-.Bl -bullet
-.It
-Hard links, symbolic links support
-.It
-Block journaling
-.It
-Copy-On-Write
-.It
-Snapshots (continuous, taken automatically, simultaneously mountable)
-.It
-Quick crash recovery at mount time
-.It
-64-bit data structures; supports many files, large files and volumes
-.It
-POSIX file permissions
-.It
-Checksum / ECC
-.El
-.Sh EXAMPLES
-The most common usage is mounting the file system:
-.Pp
-.Dl "mount -t nandfs /dev/<gnandN> /mnt"
-.Pp
-or:
-.Dl "mount_nandfs /dev/<gnandN> /mnt"
-.Pp
-where
-.Ar gnandN
-is the GEOM device representing a Flash partition (slice) containing the
-.Nm
-structure, and
-.Pa /mnt
-is a mount point.
-.Pp
-It is possible to define an entry in
-.Pa /etc/fstab
-for the
-.Nm :
-.Bd -literal
-/dev/gnand0 /flash nandfs rw 0 0
-.Ed
-.Pp
-This will mount a
-.Nm
-partition at the specified mount point during system boot.
-.Sh SEE ALSO
-.Xr gnand 4 ,
-.Xr nand 4 ,
-.Xr mount_nandfs 8 ,
-.Xr nandfs 8 ,
-.Xr nandsim 8 ,
-.Xr nandtool 8 ,
-.Xr umount_nandfs 8
-.Sh HISTORY
-The NAND FS concepts are based on NILFS principles and initial implementation
-was derived from early read-only NILFS NetBSD code.
-Since then the NAND FS
-code diverged significantly and is by no means compatible with NILFS.
-.Pp
-The NAND Flash file system first appeared in
-.Fx 10.0 .
-.Sh AUTHORS
-.An -nosplit
-The NAND FS was written by
-.An Grzegorz Bernacki
-with the help of
-.An Mateusz Guzik ,
-based on the NetBSD code created by
-.An Reinoud Zandijk .
-Additional help and support by
-.An Lukasz Plachno ,
-.An Jan Sieka
-and
-.An Lukasz Wojcik .
-This manual page was written by
-.An Rafal Jaworowski .
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index 682eb2a39502..a4fb56b891b9 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -270,7 +270,6 @@ MAN= accept_filter.9 \
proc_rwmem.9 \
pseudofs.9 \
psignal.9 \
- pwm.9 \
pwmbus.9 \
random.9 \
random_harvest.9 \
@@ -1670,6 +1669,7 @@ MLINKS+=proc_rwmem.9 proc_readmem.9 \
MLINKS+=psignal.9 gsignal.9 \
psignal.9 pgsignal.9 \
psignal.9 tdsignal.9
+MLINKS+=pwmbus.9 pwm.9
MLINKS+=random.9 arc4rand.9 \
random.9 arc4random.9 \
random.9 is_random_seeded.9 \
diff --git a/share/man/man9/VOP_REVOKE.9 b/share/man/man9/VOP_REVOKE.9
index 3557ce1109e8..610fdb7142aa 100644
--- a/share/man/man9/VOP_REVOKE.9
+++ b/share/man/man9/VOP_REVOKE.9
@@ -34,7 +34,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 5, 2002
+.Dd June 20, 2019
.Dt VOP_REVOKE 9
.Os
.Sh NAME
@@ -61,7 +61,7 @@ to signify that all access will be revoked; any other value is invalid.
.Sh LOCKS
The
.Fa vp
-must be unlocked on entry, and will remain unlocked upon return.
+must be exclusively locked on entry, and will remain locked upon return.
.Sh SEE ALSO
.Xr make_dev_alias 9 ,
.Xr vnode 9
diff --git a/share/man/man9/iflibdi.9 b/share/man/man9/iflibdi.9
index 84340d502080..c37832ede6af 100644
--- a/share/man/man9/iflibdi.9
+++ b/share/man/man9/iflibdi.9
@@ -1,5 +1,5 @@
.\" $FreeBSD$
-.Dd May 24, 2017
+.Dd May 21, 2019
.Dt IFLIBDI 9
.Os
.Sh NAME
@@ -194,10 +194,10 @@ Allocate and initialize the
\fIif_ctx_t\fP structure.
Setup and initialize the MSI or MSI/X interrupt queues if necessary.
Allocate memory for queues and qset structure setup.
-.It Fn iflib_device_irq_alloc
+.It Fn iflib_irq_alloc
Allocate an interrupt resource for a given rid value with an associated filter
and handler function.
-.It Fn iflib_device_irq_alloc_generic
+.It Fn iflib_irq_alloc_generic
Performs the same function as iflib_device_irq_alloc along with the additional
functionality of adding a taskgroup.
The data fields and callback function are determined by the type of interrupt,
diff --git a/share/man/man9/pwm.9 b/share/man/man9/pwm.9
deleted file mode 100644
index f7564a4eeca3..000000000000
--- a/share/man/man9/pwm.9
+++ /dev/null
@@ -1,93 +0,0 @@
-.\" Copyright (c) 2018 Emmanuel Vadot <manu@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 DEVELOPERS ``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 DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd January 12, 2019
-.Dt PWM 9
-.Os
-.Sh NAME
-.Nm pwm ,
-.Nm PWM_GET_BUS ,
-.Nm PWM_CHANNEL_CONFIG ,
-.Nm PWM_CHANNEL_GET_CONFIG ,
-.Nm PWM_CHANNEL_SET_FLAGS ,
-.Nm PWM_CHANNEL_GET_FLAGS ,
-.Nm PWM_CHANNEL_ENABLE ,
-.Nm PWM_CHANNEL_IS_ENABLED ,
-.Nm PWM_CHANNEL_MAX
-.Nd PWM methods
-.Sh SYNOPSIS
-.Cd "device pwm"
-.In "pwm_if.h"
-.Ft device_t
-.Fn PWM_GET_BUS "device_t dev"
-.Ft int
-.Fn PWM_CHANNEL_CONFIG "device_t dev" "int channel" "uint64_t period" "uint64_t duty"
-.Ft int
-.Fn PWM_CHANNEL_GET_CONFIG "device_t dev" "int channel" "uint64_t *period" "uint64_t *duty"
-.Ft int
-.Fn PWM_CHANNEL_SET_FLAGS "device_t dev" "int channel" "uint32_t flags"
-.Ft int
-.Fn PWM_CHANNEL_GET_FLAGS "device_t dev" "int channel" "uint32_t *flags"
-.Ft int
-.Fn PWM_CHANNEL_ENABLE "device_t dev" "int channel" "bool enable"
-.Ft int
-.Fn PWM_CHANNEL_IS_ENABLED "device_t dev" "int channel" "bool *enabled"
-.Ft int
-.Fn PWM_CHANNEL_MAX "device_t dev" "int channel" "int *nchannel"
-.Sh DESCRIPTION
-The PWM (Pulse-Width Modulation) interface allows the device driver to register to a global
-bus so other devices in the kernel can use them in a generic way.
-.Sh INTERFACE
-.Bl -tag -width indent
-.It Fn PWM_GET_BUS "device_t dev"
-Return the bus device.
-.It Fn PWM_CHANNEL_CONFIG "device_t dev" "int channel" "uint64_t period" "uint64_t duty"
-Configure the period and duty (in nanoseconds) in the PWM controller for the specified channel.
-Returns 0 on success or
-.Er EINVAL
-if the values are not supported by the controller or
-.Er EBUSY
-is the PWM controller is in use and does not support changing the value on the fly.
-.It Fn PWM_CHANNEL_GET_CONFIG "device_t dev" "int channel" "uint64_t *period" "uint64_t *duty"
-Get the current configuration of the period and duty for the specified channel.
-.It Fn PWM_CHANNEL_SET_FLAGS "device_t dev" "int channel" "uint32_t flags"
-Set the flags of the channel (like inverted polarity).
-.It Fn PWM_CHANNEL_GET_FLAGS "device_t dev" "int channel" "uint32_t *flags"
-Get the current flags for the channel.
-.It Fn PWM_CHANNEL_ENABLE "device_t dev" "int channel" "bool enable"
-Enable the PWM channel.
-.It Fn PWM_CHANNEL_ISENABLED "device_t dev" "int channel" "bool *enable"
-Test if the PWM channel is enabled.
-.It Fn PWM_CHANNEL_MAX "device_t dev" "int channel" "int *nchannel"
-Get the maximum number of channels supported by the controller.
-.El
-.Sh HISTORY
-The
-.Nm pwm
-interface first appeared in
-.Fx 13.0 .
-The
-.Nm pwm
-interface and manual page was written by
-.An Emmanuel Vadot Aq Mt manu@FreeBSD.org .
diff --git a/share/man/man9/pwmbus.9 b/share/man/man9/pwmbus.9
index ba987eaf77a5..5b0915c10812 100644
--- a/share/man/man9/pwmbus.9
+++ b/share/man/man9/pwmbus.9
@@ -22,70 +22,85 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 12, 2018
+.Dd June 21, 2019
.Dt PWMBUS 9
.Os
.Sh NAME
.Nm pwmbus ,
-.Nm pwmbus_attach_bus ,
-.Nm PWMBUS_GET_BUS ,
.Nm PWMBUS_CHANNEL_CONFIG ,
+.Nm PWMBUS_CHANNEL_COUNT ,
+.Nm PWMBUS_CHANNEL_ENABLE ,
.Nm PWMBUS_CHANNEL_GET_CONFIG ,
-.Nm PWMBUS_CHANNEL_SET_FLAGS ,
.Nm PWMBUS_CHANNEL_GET_FLAGS ,
-.Nm PWMBUS_CHANNEL_ENABLE ,
.Nm PWMBUS_CHANNEL_IS_ENABLED ,
-.Nm PWMBUS_CHANNEL_MAX
+.Nm PWMBUS_CHANNEL_SET_FLAGS ,
+.Nm PWMBUS_GET_BUS
.Nd PWMBUS methods
.Sh SYNOPSIS
.Cd "device pwm"
.In "pwmbus_if.h"
-.Ft device_t
-.Fn pwmbus_attach_bus "device_t dev"
.Ft int
.Fn PWMBUS_CHANNEL_CONFIG "device_t bus" "int channel" "uint64_t period" "uint64_t duty"
.Ft int
-.Fn PWMBUS_CHANNEL_GET_CONFIG "device_t bus" "int channel" "uint64_t *period" "uint64_t *duty"
+.Fn PWMBUS_CHANNEL_COUNT "device_t bus" "int channel" "int *nchannel"
.Ft int
-.Fn PWMBUS_CHANNEL_SET_FLAGS "device_t bus" "int channel" "uint32_t flags"
+.Fn PWMBUS_CHANNEL_ENABLE "device_t bus" "int channel" "bool enable"
.Ft int
-.Fn PWMBUS_CHANNEL_GET_FLAGS "device_t bus" "int channel" "uint32_t *flags"
+.Fn PWMBUS_CHANNEL_GET_CONFIG "device_t bus" "int channel" "uint64_t *period" "uint64_t *duty"
.Ft int
-.Fn PWMBUS_CHANNEL_ENABLE "device_t bus" "int channel" "bool enable"
+.Fn PWMBUS_CHANNEL_GET_FLAGS "device_t bus" "int channel" "uint32_t *flags"
.Ft int
.Fn PWMBUS_CHANNEL_IS_ENABLED "device_t bus" "int channel" "bool *enabled"
.Ft int
-.Fn PWMBUS_CHANNEL_MAX "device_t bus" "int channel" "int *nchannel"
+.Fn PWMBUS_CHANNEL_SET_FLAGS "device_t bus" "int channel" "uint32_t flags"
.Sh DESCRIPTION
-The PWMBUS (Pulse-Width Modulation) interface allows the device driver to register to a global
-bus so other devices in the kernel can use them in a generic way
+The PWMBUS (Pulse-Width Modulation) interface allows a device driver to
+register to a global bus so other devices in the kernel can use them in a
+generic way.
+.Pp
+For all
+.Nm
+methods, the
+.Va period
+argument is the duration in nanoseconds of one complete on-off cycle, and the
+.Va duty
+argument is the duration in nanoseconds of the on portion of that cycle.
+.Pp
+Some PWM hardware is organized as a single controller with multiple channels.
+Channel numbers count up from zero.
+When multiple channels are present, they sometimes share a common clock or
+other resources.
+In such cases, changing the period or duty cycle of any one channel may affect
+other channels within the hardware which share the same resources.
+Consult the documentation for the underlying PWM hardware device driver for
+details on channels that share resources.
.Sh INTERFACE
.Bl -tag -width indent
-.It Fn pwmbus_attach_bus "device_t dev"
-Attach the
-.Nm pwmbus
-to the device driver
.It Fn PWMBUS_CHANNEL_CONFIG "device_t bus" "int channel" "uint64_t period" "uint64_t duty"
-Configure the period and duty (in nanoseconds) in the PWM controller on the bus for the specified channel.
+Configure the period and duty (in nanoseconds) in the PWM controller on the bus
+for the specified channel.
Returns 0 on success or
.Er EINVAL
-is the values are not supported by the controller or
+if the values are not supported by the controller or
.Er EBUSY
-is the PWMBUS controller is in use and doesn't support changing the value on the fly.
+if the PWMBUS controller is in use and does not support changing the value on
+the fly.
+.It Fn PWMBUS_CHANNEL_COUNT "device_t bus" "int *nchannel"
+Get the number of channels supported by the controller.
+.It Fn PWMBUS_CHANNEL_ENABLE "device_t bus" "int channel" "bool enable"
+Enable the PWM channel.
.It Fn PWMBUS_CHANNEL_GET_CONFIG "device_t bus" "int channel" "uint64_t *period" "uint64_t *duty"
Get the current configuration of the period and duty for the specified channel.
-.It Fn PWMBUS_CHANNEL_SET_FLAGS "device_t bus" "int channel" "uint32_t flags"
-Set the flags of the channel (like inverted polarity), if the driver or controller
-doesn't support this a default method is used.
.It Fn PWMBUS_CHANNEL_GET_FLAGS "device_t bus" "int channel" "uint32_t *flags"
-Get the current flags for the channel, if the driver or controller
-doesn't support this, a default method is used.
-.It Fn PWMBUS_CHANNEL_ENABLE "device_t bus" "int channel" "bool enable"
-Enable the PWM channel.
-.It Fn PWMBUS_CHANNEL_ISENABLED "device_t bus" "int channel" "bool *enable"
-Test if the PWM channel is enabled.
-.It PWMBUS_CHANNEL_MAX "device_t bus" "int channel" "int *nchannel"
-Get the maximum number of channel supported by the controller.
+Get the current flags for the channel.
+If the driver or controller
+does not support this, a default method returns a flags value of zero.
+.It Fn PWMBUS_CHANNEL_IS_ENABLED "device_t bus" "int channel" "bool *enable"
+Test whether the PWM channel is enabled.
+.It Fn PWMBUS_CHANNEL_SET_FLAGS "device_t bus" "int channel" "uint32_t flags"
+Set the flags of the channel (such as inverted polarity).
+If the driver or controller does not support this a do-nothing default method
+is used.
.El
.Sh HISTORY
The
diff --git a/share/man/man9/vm_map_protect.9 b/share/man/man9/vm_map_protect.9
index c4b5a738abe7..5e58074ebda7 100644
--- a/share/man/man9/vm_map_protect.9
+++ b/share/man/man9/vm_map_protect.9
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 19, 2003
+.Dd June 20, 2019
.Dt VM_MAP_PROTECT 9
.Os
.Sh NAME
@@ -51,6 +51,11 @@ within the map
.Fa map
to
.Fa new_prot .
+The value specified by
+.Fa new_prot
+may not include any protection bits that are not set in
+.Va max_protection
+on every entry within the range.
.Pp
If
.Fa set_max
@@ -59,7 +64,12 @@ is TRUE,
is treated as the new
.Va max_protection
setting for each underlying entry.
-Otherwise, only the
+Protection bits not included
+.Fa new_prot
+will be cleared from existing entries.
+If
+.Fa set_max
+is FALSE only the
.Va protection
field is affected.
.Pp
@@ -86,6 +96,11 @@ would exceed
for an entry within the range,
.Dv KERN_PROTECTION_FAILURE
is returned.
+If a copy-on-write mapping is transitioned from read-only to
+read-write, and too little swap space is available for backing the
+copied pages,
+.Dv KERN_RESOURCE_SHORTAGE
+is returned.
.Sh SEE ALSO
.Xr vm_map 9
.Sh AUTHORS
diff --git a/share/misc/bsd-family-tree b/share/misc/bsd-family-tree
index 81741ca34446..6f386cbc0b08 100644
--- a/share/misc/bsd-family-tree
+++ b/share/misc/bsd-family-tree
@@ -135,7 +135,7 @@ FreeBSD 4.0 | | | | | NetBSD 1.4.2 | |
| FreeBSD 3.5.1 | | | | | | |
| | | | | | | |
*---FreeBSD 4.1 | | | | | | |
- | | | | (?) | | | |
+ | | | | | | | | |
| FreeBSD 4.1.1 | | / | | | |
| | | | / | | | |
| FreeBSD 4.2 Darwin/ | NetBSD 1.4.3 | |
@@ -399,6 +399,8 @@ FreeBSD 5.2 | | | |
| | | NetBSD | |
| | | 8.1 | DragonFly 5.6
| | | | |
+ | | | | DragonFly 5.6.1
+ | | | | |
FreeBSD 13 -current | NetBSD -current OpenBSD -current DragonFly -current
| | | | |
v v v v v
@@ -783,6 +785,7 @@ DragonFly 5.4.1 2018-12-24 [DFB]
OpenBSD 6.5 2019-05-01 [OBD]
NetBSD 8.1 2019-06-04 [NBD]
DragonFly 5.6 2019-06-17 [DFB]
+DragonFly 5.6.1 2019-06-19 [DFB]
Bibliography
------------------------
diff --git a/share/mk/bsd.cpu.mk b/share/mk/bsd.cpu.mk
index acf1f5922593..c16ab5a85bf6 100644
--- a/share/mk/bsd.cpu.mk
+++ b/share/mk/bsd.cpu.mk
@@ -369,6 +369,10 @@ CFLAGS += -mfloat-abi=softfp
.endif
.endif
+.if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "powerpcspe"
+LDFLAGS+= -Wl,--secure-plt
+.endif
+
.if ${MACHINE_ARCH} == "powerpcspe"
CFLAGS += -mcpu=8548 -Wa,-me500 -mspe=yes -mabi=spe -mfloat-gprs=double
.endif
diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk
index b2675fce7cf3..1bea2ff10786 100644
--- a/share/mk/bsd.libnames.mk
+++ b/share/mk/bsd.libnames.mk
@@ -104,7 +104,6 @@ LIBMLX4?= ${LIBDESTDIR}${LIBDIR_BASE}/libmlx4.a
LIBMLX5?= ${LIBDESTDIR}${LIBDIR_BASE}/libmlx5.a
LIBMP?= ${LIBDESTDIR}${LIBDIR_BASE}/libmp.a
LIBMT?= ${LIBDESTDIR}${LIBDIR_BASE}/libmt.a
-LIBNANDFS?= ${LIBDESTDIR}${LIBDIR_BASE}/libnandfs.a
LIBNCURSES?= ${LIBDESTDIR}${LIBDIR_BASE}/libncurses.a
LIBNCURSESW?= ${LIBDESTDIR}${LIBDIR_BASE}/libncursesw.a
LIBNETGRAPH?= ${LIBDESTDIR}${LIBDIR_BASE}/libnetgraph.a
diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk
index d08a8653de3a..fcb03aaaedcd 100644
--- a/share/mk/src.libnames.mk
+++ b/share/mk/src.libnames.mk
@@ -135,7 +135,6 @@ _LIBRARIES= \
memstat \
mp \
mt \
- nandfs \
ncurses \
ncursesw \
netgraph \
diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk
index 96e3c94a948f..03d089b8246b 100644
--- a/share/mk/src.opts.mk
+++ b/share/mk/src.opts.mk
@@ -206,7 +206,6 @@ __DEFAULT_NO_OPTIONS = \
LOADER_FORCE_LE \
LOADER_VERBOSE \
LOADER_VERIEXEC_PASS_MANIFEST \
- NAND \
OFED_EXTRA \
OPENLDAP \
RPCBIND_WARMSTART_SUPPORT \
diff --git a/stand/arm/uboot/conf.c b/stand/arm/uboot/conf.c
index 777a7b20340c..077541220f92 100644
--- a/stand/arm/uboot/conf.c
+++ b/stand/arm/uboot/conf.c
@@ -59,9 +59,6 @@ struct fs_ops *file_system[] = {
#if defined(LOADER_EXT2FS_SUPPORT)
&ext2fs_fsops,
#endif
-#if defined(LOADER_NANDFS_SUPPORT)
- &nandfs_fsops,
-#endif
#if defined(LOADER_NFS_SUPPORT)
&nfs_fsops,
#endif
diff --git a/stand/arm/uboot/version b/stand/arm/uboot/version
index 486c4125cc0d..ec46b388b281 100644
--- a/stand/arm/uboot/version
+++ b/stand/arm/uboot/version
@@ -3,6 +3,7 @@ $FreeBSD$
NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this
file is important. Make sure the current version number is on line 6.
+1.3: Remove NAND FS support.
1.2: Extended with NAND FS support.
1.1: Flattened Device Tree blob support.
1.0: Added storage support. Booting from HDD, USB, etc. is now possible.
diff --git a/stand/common/part.c b/stand/common/part.c
index ec9697c6a10b..8eb4c065b473 100644
--- a/stand/common/part.c
+++ b/stand/common/part.c
@@ -57,7 +57,6 @@ 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;
static const uuid_t gpt_uuid_freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
static const uuid_t gpt_uuid_freebsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM;
@@ -91,7 +90,6 @@ static struct parttypes {
{ PART_EFI, "EFI" },
{ PART_FREEBSD, "FreeBSD" },
{ PART_FREEBSD_BOOT, "FreeBSD boot" },
- { PART_FREEBSD_NANDFS, "FreeBSD nandfs" },
{ PART_FREEBSD_UFS, "FreeBSD UFS" },
{ PART_FREEBSD_ZFS, "FreeBSD ZFS" },
{ PART_FREEBSD_SWAP, "FreeBSD swap" },
@@ -141,8 +139,6 @@ gpt_parttype(uuid_t type)
return (PART_FREEBSD_SWAP);
else if (uuid_equal(&type, &gpt_uuid_freebsd_vinum, NULL))
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);
@@ -445,8 +441,6 @@ bsd_parttype(uint8_t type)
{
switch (type) {
- case FS_NANDFS:
- return (PART_FREEBSD_NANDFS);
case FS_SWAP:
return (PART_FREEBSD_SWAP);
case FS_BSDFFS:
@@ -527,8 +521,6 @@ vtoc8_parttype(uint16_t type)
{
switch (type) {
- case VTOC_TAG_FREEBSD_NANDFS:
- return (PART_FREEBSD_NANDFS);
case VTOC_TAG_FREEBSD_SWAP:
return (PART_FREEBSD_SWAP);
case VTOC_TAG_FREEBSD_UFS:
diff --git a/stand/common/part.h b/stand/common/part.h
index 3eac476b6d66..490db6746c38 100644
--- a/stand/common/part.h
+++ b/stand/common/part.h
@@ -45,7 +45,6 @@ enum partition_type {
PART_EFI,
PART_FREEBSD,
PART_FREEBSD_BOOT,
- PART_FREEBSD_NANDFS,
PART_FREEBSD_UFS,
PART_FREEBSD_ZFS,
PART_FREEBSD_SWAP,
diff --git a/stand/common/paths.h b/stand/common/paths.h
index 9ed45e646a3e..b32313770129 100644
--- a/stand/common/paths.h
+++ b/stand/common/paths.h
@@ -29,11 +29,14 @@
#ifndef _PATHS_H_
#define _PATHS_H_
+#include <sys/boot.h> /* To get kernel path */
+
#define PATH_DOTCONFIG "/boot.config"
#define PATH_CONFIG "/boot/config"
#define PATH_LOADER "/boot/loader"
#define PATH_LOADER_EFI "/boot/loader.efi"
#define PATH_LOADER_ZFS "/boot/zfsloader"
-#define PATH_KERNEL "/boot/kernel/kernel"
+#define PATH_LOADER_CONF "/boot/loader.conf"
+#define PATH_DEFAULTS_LOADER_CONF "/boot/defaults/loader.conf"
#endif /* _PATHS_H_ */
diff --git a/stand/efi/include/Protocol/Http.h b/stand/efi/include/Protocol/Http.h
new file mode 100644
index 000000000000..54f49ab5e35c
--- /dev/null
+++ b/stand/efi/include/Protocol/Http.h
@@ -0,0 +1,523 @@
+/* $FreeBSD$ */
+/** @file
+ This file defines the EFI HTTP Protocol interface. It is split into
+ the following two main sections:
+ HTTP Service Binding Protocol (HTTPSB)
+ HTTP Protocol (HTTP)
+
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ @par Revision Reference:
+ This Protocol is introduced in UEFI Specification 2.5
+
+**/
+
+#ifndef __EFI_HTTP_PROTOCOL_H__
+#define __EFI_HTTP_PROTOCOL_H__
+
+#define EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \
+ { \
+ 0xbdc8e6af, 0xd9bc, 0x4379, {0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \
+ }
+
+#define EFI_HTTP_PROTOCOL_GUID \
+ { \
+ 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42, 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b } \
+ }
+
+typedef struct _EFI_HTTP_PROTOCOL EFI_HTTP_PROTOCOL;
+
+///
+/// EFI_HTTP_VERSION
+///
+typedef enum {
+ HttpVersion10,
+ HttpVersion11,
+ HttpVersionUnsupported
+} EFI_HTTP_VERSION;
+
+///
+/// EFI_HTTP_METHOD
+///
+typedef enum {
+ HttpMethodGet,
+ HttpMethodPost,
+ HttpMethodPatch,
+ HttpMethodOptions,
+ HttpMethodConnect,
+ HttpMethodHead,
+ HttpMethodPut,
+ HttpMethodDelete,
+ HttpMethodTrace,
+ HttpMethodMax
+} EFI_HTTP_METHOD;
+
+///
+/// EFI_HTTP_STATUS_CODE
+///
+typedef enum {
+ HTTP_STATUS_UNSUPPORTED_STATUS = 0,
+ HTTP_STATUS_100_CONTINUE,
+ HTTP_STATUS_101_SWITCHING_PROTOCOLS,
+ HTTP_STATUS_200_OK,
+ HTTP_STATUS_201_CREATED,
+ HTTP_STATUS_202_ACCEPTED,
+ HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION,
+ HTTP_STATUS_204_NO_CONTENT,
+ HTTP_STATUS_205_RESET_CONTENT,
+ HTTP_STATUS_206_PARTIAL_CONTENT,
+ HTTP_STATUS_300_MULTIPLE_CHOICES,
+ HTTP_STATUS_301_MOVED_PERMANENTLY,
+ HTTP_STATUS_302_FOUND,
+ HTTP_STATUS_303_SEE_OTHER,
+ HTTP_STATUS_304_NOT_MODIFIED,
+ HTTP_STATUS_305_USE_PROXY,
+ HTTP_STATUS_307_TEMPORARY_REDIRECT,
+ HTTP_STATUS_400_BAD_REQUEST,
+ HTTP_STATUS_401_UNAUTHORIZED,
+ HTTP_STATUS_402_PAYMENT_REQUIRED,
+ HTTP_STATUS_403_FORBIDDEN,
+ HTTP_STATUS_404_NOT_FOUND,
+ HTTP_STATUS_405_METHOD_NOT_ALLOWED,
+ HTTP_STATUS_406_NOT_ACCEPTABLE,
+ HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED,
+ HTTP_STATUS_408_REQUEST_TIME_OUT,
+ HTTP_STATUS_409_CONFLICT,
+ HTTP_STATUS_410_GONE,
+ HTTP_STATUS_411_LENGTH_REQUIRED,
+ HTTP_STATUS_412_PRECONDITION_FAILED,
+ HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE,
+ HTTP_STATUS_414_REQUEST_URI_TOO_LARGE,
+ HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE,
+ HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED,
+ HTTP_STATUS_417_EXPECTATION_FAILED,
+ HTTP_STATUS_500_INTERNAL_SERVER_ERROR,
+ HTTP_STATUS_501_NOT_IMPLEMENTED,
+ HTTP_STATUS_502_BAD_GATEWAY,
+ HTTP_STATUS_503_SERVICE_UNAVAILABLE,
+ HTTP_STATUS_504_GATEWAY_TIME_OUT,
+ HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED,
+ HTTP_STATUS_308_PERMANENT_REDIRECT
+} EFI_HTTP_STATUS_CODE;
+
+///
+/// EFI_HTTPv4_ACCESS_POINT
+///
+typedef struct {
+ ///
+ /// Set to TRUE to instruct the EFI HTTP instance to use the default address
+ /// information in every TCP connection made by this instance. In addition, when set
+ /// to TRUE, LocalAddress and LocalSubnet are ignored.
+ ///
+ BOOLEAN UseDefaultAddress;
+ ///
+ /// If UseDefaultAddress is set to FALSE, this defines the local IP address to be
+ /// used in every TCP connection opened by this instance.
+ ///
+ EFI_IPv4_ADDRESS LocalAddress;
+ ///
+ /// If UseDefaultAddress is set to FALSE, this defines the local subnet to be used
+ /// in every TCP connection opened by this instance.
+ ///
+ EFI_IPv4_ADDRESS LocalSubnet;
+ ///
+ /// This defines the local port to be used in
+ /// every TCP connection opened by this instance.
+ ///
+ UINT16 LocalPort;
+} EFI_HTTPv4_ACCESS_POINT;
+
+///
+/// EFI_HTTPv6_ACCESS_POINT
+///
+typedef struct {
+ ///
+ /// Local IP address to be used in every TCP connection opened by this instance.
+ ///
+ EFI_IPv6_ADDRESS LocalAddress;
+ ///
+ /// Local port to be used in every TCP connection opened by this instance.
+ ///
+ UINT16 LocalPort;
+} EFI_HTTPv6_ACCESS_POINT;
+
+///
+/// EFI_HTTP_CONFIG_DATA_ACCESS_POINT
+///
+
+
+typedef struct {
+ ///
+ /// HTTP version that this instance will support.
+ ///
+ EFI_HTTP_VERSION HttpVersion;
+ ///
+ /// Time out (in milliseconds) when blocking for requests.
+ ///
+ UINT32 TimeOutMillisec;
+ ///
+ /// Defines behavior of EFI DNS and TCP protocols consumed by this instance. If
+ /// FALSE, this instance will use EFI_DNS4_PROTOCOL and EFI_TCP4_PROTOCOL. If TRUE,
+ /// this instance will use EFI_DNS6_PROTOCOL and EFI_TCP6_PROTOCOL.
+ ///
+ BOOLEAN LocalAddressIsIPv6;
+
+ union {
+ ///
+ /// When LocalAddressIsIPv6 is FALSE, this points to the local address, subnet, and
+ /// port used by the underlying TCP protocol.
+ ///
+ EFI_HTTPv4_ACCESS_POINT *IPv4Node;
+ ///
+ /// When LocalAddressIsIPv6 is TRUE, this points to the local IPv6 address and port
+ /// used by the underlying TCP protocol.
+ ///
+ EFI_HTTPv6_ACCESS_POINT *IPv6Node;
+ } AccessPoint;
+} EFI_HTTP_CONFIG_DATA;
+
+///
+/// EFI_HTTP_REQUEST_DATA
+///
+typedef struct {
+ ///
+ /// The HTTP method (e.g. GET, POST) for this HTTP Request.
+ ///
+ EFI_HTTP_METHOD Method;
+ ///
+ /// The URI of a remote host. From the information in this field, the HTTP instance
+ /// will be able to determine whether to use HTTP or HTTPS and will also be able to
+ /// determine the port number to use. If no port number is specified, port 80 (HTTP)
+ /// is assumed. See RFC 3986 for more details on URI syntax.
+ ///
+ CHAR16 *Url;
+} EFI_HTTP_REQUEST_DATA;
+
+///
+/// EFI_HTTP_RESPONSE_DATA
+///
+typedef struct {
+ ///
+ /// Response status code returned by the remote host.
+ ///
+ EFI_HTTP_STATUS_CODE StatusCode;
+} EFI_HTTP_RESPONSE_DATA;
+
+///
+/// EFI_HTTP_HEADER
+///
+typedef struct {
+ ///
+ /// Null terminated string which describes a field name. See RFC 2616 Section 14 for
+ /// detailed information about field names.
+ ///
+ CHAR8 *FieldName;
+ ///
+ /// Null terminated string which describes the corresponding field value. See RFC 2616
+ /// Section 14 for detailed information about field values.
+ ///
+ CHAR8 *FieldValue;
+} EFI_HTTP_HEADER;
+
+///
+/// EFI_HTTP_MESSAGE
+///
+typedef struct {
+ ///
+ /// HTTP message data.
+ ///
+ union {
+ ///
+ /// When the token is used to send a HTTP request, Request is a pointer to storage that
+ /// contains such data as URL and HTTP method.
+ ///
+ EFI_HTTP_REQUEST_DATA *Request;
+ ///
+ /// When used to await a response, Response points to storage containing HTTP response
+ /// status code.
+ ///
+ EFI_HTTP_RESPONSE_DATA *Response;
+ } Data;
+ ///
+ /// Number of HTTP header structures in Headers list. On request, this count is
+ /// provided by the caller. On response, this count is provided by the HTTP driver.
+ ///
+ UINTN HeaderCount;
+ ///
+ /// Array containing list of HTTP headers. On request, this array is populated by the
+ /// caller. On response, this array is allocated and populated by the HTTP driver. It
+ /// is the responsibility of the caller to free this memory on both request and
+ /// response.
+ ///
+ EFI_HTTP_HEADER *Headers;
+ ///
+ /// Length in bytes of the HTTP body. This can be zero depending on the HttpMethod type.
+ ///
+ UINTN BodyLength;
+ ///
+ /// Body associated with the HTTP request or response. This can be NULL depending on
+ /// the HttpMethod type.
+ ///
+ VOID *Body;
+} EFI_HTTP_MESSAGE;
+
+
+///
+/// EFI_HTTP_TOKEN
+///
+typedef struct {
+ ///
+ /// This Event will be signaled after the Status field is updated by the EFI HTTP
+ /// Protocol driver. The type of Event must be EFI_NOTIFY_SIGNAL. The Task Priority
+ /// Level (TPL) of Event must be lower than or equal to TPL_CALLBACK.
+ ///
+ EFI_EVENT Event;
+ ///
+ /// Status will be set to one of the following value if the HTTP request is
+ /// successfully sent or if an unexpected error occurs:
+ /// EFI_SUCCESS: The HTTP request was successfully sent to the remote host.
+ /// EFI_HTTP_ERROR: The response message was successfully received but contains a
+ /// HTTP error. The response status code is returned in token.
+ /// EFI_ABORTED: The HTTP request was cancelled by the caller and removed from
+ /// the transmit queue.
+ /// EFI_TIMEOUT: The HTTP request timed out before reaching the remote host.
+ /// EFI_DEVICE_ERROR: An unexpected system or network error occurred.
+ ///
+ EFI_STATUS Status;
+ ///
+ /// Pointer to storage containing HTTP message data.
+ ///
+ EFI_HTTP_MESSAGE *Message;
+} EFI_HTTP_TOKEN;
+
+/**
+ Returns the operational parameters for the current HTTP child instance.
+
+ The GetModeData() function is used to read the current mode data (operational
+ parameters) for this HTTP protocol instance.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+ @param[out] HttpConfigData Point to buffer for operational parameters of this
+ HTTP instance. It is the responsibility of the caller
+ to allocate the memory for HttpConfigData and
+ HttpConfigData->AccessPoint.IPv6Node/IPv4Node. In fact,
+ it is recommended to allocate sufficient memory to record
+ IPv6Node since it is big enough for all possibilities.
+
+ @retval EFI_SUCCESS Operation succeeded.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ HttpConfigData is NULL.
+ HttpConfigData->AccessPoint.IPv4Node or
+ HttpConfigData->AccessPoint.IPv6Node is NULL.
+ @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been started.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_GET_MODE_DATA)(
+ IN EFI_HTTP_PROTOCOL *This,
+ OUT EFI_HTTP_CONFIG_DATA *HttpConfigData
+ );
+
+/**
+ Initialize or brutally reset the operational parameters for this EFI HTTP instance.
+
+ The Configure() function does the following:
+ When HttpConfigData is not NULL Initialize this EFI HTTP instance by configuring
+ timeout, local address, port, etc.
+ When HttpConfigData is NULL, reset this EFI HTTP instance by closing all active
+ connections with remote hosts, canceling all asynchronous tokens, and flush request
+ and response buffers without informing the appropriate hosts.
+
+ No other EFI HTTP function can be executed by this instance until the Configure()
+ function is executed and returns successfully.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+ @param[in] HttpConfigData Pointer to the configure data to configure the instance.
+
+ @retval EFI_SUCCESS Operation succeeded.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ HttpConfigData->LocalAddressIsIPv6 is FALSE and
+ HttpConfigData->AccessPoint.IPv4Node is NULL.
+ HttpConfigData->LocalAddressIsIPv6 is TRUE and
+ HttpConfigData->AccessPoint.IPv6Node is NULL.
+ @retval EFI_ALREADY_STARTED Reinitialize this HTTP instance without calling
+ Configure() with NULL to reset it.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources when
+ executing Configure().
+ @retval EFI_UNSUPPORTED One or more options in ConfigData are not supported
+ in the implementation.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_CONFIGURE)(
+ IN EFI_HTTP_PROTOCOL *This,
+ IN EFI_HTTP_CONFIG_DATA *HttpConfigData OPTIONAL
+ );
+
+/**
+ The Request() function queues an HTTP request to this HTTP instance,
+ similar to Transmit() function in the EFI TCP driver. When the HTTP request is sent
+ successfully, or if there is an error, Status in token will be updated and Event will
+ be signaled.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+ @param[in] Token Pointer to storage containing HTTP request token.
+
+ @retval EFI_SUCCESS Outgoing data was processed.
+ @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been started.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_TIMEOUT Data was dropped out of the transmit or receive queue.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Token is NULL.
+ Token->Message is NULL.
+ Token->Message->Body is not NULL,
+ Token->Message->BodyLength is non-zero, and
+ Token->Message->Data is NULL, but a previous call to
+ Request()has not been completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.
+ @retval EFI_UNSUPPORTED The HTTP method is not supported in current implementation.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_REQUEST) (
+ IN EFI_HTTP_PROTOCOL *This,
+ IN EFI_HTTP_TOKEN *Token
+ );
+
+/**
+ Abort an asynchronous HTTP request or response token.
+
+ The Cancel() function aborts a pending HTTP request or response transaction. If
+ Token is not NULL and the token is in transmit or receive queues when it is being
+ cancelled, its Token->Status will be set to EFI_ABORTED and then Token->Event will
+ be signaled. If the token is not in one of the queues, which usually means that the
+ asynchronous operation has completed, EFI_NOT_FOUND is returned. If Token is NULL,
+ all asynchronous tokens issued by Request() or Response() will be aborted.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+ @param[in] Token Point to storage containing HTTP request or response
+ token.
+
+ @retval EFI_SUCCESS Request and Response queues are successfully flushed.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_STARTED This instance hasn't been configured.
+ @retval EFI_NOT_FOUND The asynchronous request or response token is not
+ found.
+ @retval EFI_UNSUPPORTED The implementation does not support this function.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_CANCEL)(
+ IN EFI_HTTP_PROTOCOL *This,
+ IN EFI_HTTP_TOKEN *Token
+ );
+
+/**
+ The Response() function queues an HTTP response to this HTTP instance, similar to
+ Receive() function in the EFI TCP driver. When the HTTP Response is received successfully,
+ or if there is an error, Status in token will be updated and Event will be signaled.
+
+ The HTTP driver will queue a receive token to the underlying TCP instance. When data
+ is received in the underlying TCP instance, the data will be parsed and Token will
+ be populated with the response data. If the data received from the remote host
+ contains an incomplete or invalid HTTP header, the HTTP driver will continue waiting
+ (asynchronously) for more data to be sent from the remote host before signaling
+ Event in Token.
+
+ It is the responsibility of the caller to allocate a buffer for Body and specify the
+ size in BodyLength. If the remote host provides a response that contains a content
+ body, up to BodyLength bytes will be copied from the receive buffer into Body and
+ BodyLength will be updated with the amount of bytes received and copied to Body. This
+ allows the client to download a large file in chunks instead of into one contiguous
+ block of memory. Similar to HTTP request, if Body is not NULL and BodyLength is
+ non-zero and all other fields are NULL or 0, the HTTP driver will queue a receive
+ token to underlying TCP instance. If data arrives in the receive buffer, up to
+ BodyLength bytes of data will be copied to Body. The HTTP driver will then update
+ BodyLength with the amount of bytes received and copied to Body.
+
+ If the HTTP driver does not have an open underlying TCP connection with the host
+ specified in the response URL, Request() will return EFI_ACCESS_DENIED. This is
+ consistent with RFC 2616 recommendation that HTTP clients should attempt to maintain
+ an open TCP connection between client and host.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+ @param[in] Token Pointer to storage containing HTTP response token.
+
+ @retval EFI_SUCCESS Allocation succeeded.
+ @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been
+ initialized.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Token is NULL.
+ Token->Message->Headers is NULL.
+ Token->Message is NULL.
+ Token->Message->Body is not NULL,
+ Token->Message->BodyLength is non-zero, and
+ Token->Message->Data is NULL, but a previous call to
+ Response() has not been completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.
+ @retval EFI_ACCESS_DENIED An open TCP connection is not present with the host
+ specified by response URL.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_RESPONSE) (
+ IN EFI_HTTP_PROTOCOL *This,
+ IN EFI_HTTP_TOKEN *Token
+ );
+
+/**
+ The Poll() function can be used by network drivers and applications to increase the
+ rate that data packets are moved between the communication devices and the transmit
+ and receive queues.
+
+ In some systems, the periodic timer event in the managed network driver may not poll
+ the underlying communications device fast enough to transmit and/or receive all data
+ packets without missing incoming packets or dropping outgoing packets. Drivers and
+ applications that are experiencing packet loss should try calling the Poll() function
+ more often.
+
+ @param[in] This Pointer to EFI_HTTP_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed..
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_READY No incoming or outgoing data is processed.
+ @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been started.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_HTTP_POLL) (
+ IN EFI_HTTP_PROTOCOL *This
+ );
+
+///
+/// The EFI HTTP protocol is designed to be used by EFI drivers and applications to
+/// create and transmit HTTP Requests, as well as handle HTTP responses that are
+/// returned by a remote host. This EFI protocol uses and relies on an underlying EFI
+/// TCP protocol.
+///
+struct _EFI_HTTP_PROTOCOL {
+ EFI_HTTP_GET_MODE_DATA GetModeData;
+ EFI_HTTP_CONFIGURE Configure;
+ EFI_HTTP_REQUEST Request;
+ EFI_HTTP_CANCEL Cancel;
+ EFI_HTTP_RESPONSE Response;
+ EFI_HTTP_POLL Poll;
+};
+
+extern EFI_GUID gEfiHttpServiceBindingProtocolGuid;
+extern EFI_GUID gEfiHttpProtocolGuid;
+
+#endif
diff --git a/stand/efi/include/Protocol/Ip4Config2.h b/stand/efi/include/Protocol/Ip4Config2.h
new file mode 100644
index 000000000000..47241d7ad7d4
--- /dev/null
+++ b/stand/efi/include/Protocol/Ip4Config2.h
@@ -0,0 +1,324 @@
+/* $FreeBSD$ */
+/** @file
+ This file provides a definition of the EFI IPv4 Configuration II
+ Protocol.
+
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at<BR>
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+@par Revision Reference:
+This Protocol is introduced in UEFI Specification 2.5
+
+**/
+#ifndef __EFI_IP4CONFIG2_PROTOCOL_H__
+#define __EFI_IP4CONFIG2_PROTOCOL_H__
+
+/* #include <Protocol/Ip4.h> */
+
+#define EFI_IP4_CONFIG2_PROTOCOL_GUID \
+ { \
+ 0x5b446ed1, 0xe30b, 0x4faa, {0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \
+ }
+
+typedef struct _EFI_IP4_CONFIG2_PROTOCOL EFI_IP4_CONFIG2_PROTOCOL;
+
+
+///
+/// EFI_IP4_CONFIG2_DATA_TYPE
+///
+typedef enum {
+ ///
+ /// The interface information of the communication device this EFI
+ /// IPv4 Configuration II Protocol instance manages. This type of
+ /// data is read only. The corresponding Data is of type
+ /// EFI_IP4_CONFIG2_INTERFACE_INFO.
+ ///
+ Ip4Config2DataTypeInterfaceInfo,
+ ///
+ /// The general configuration policy for the EFI IPv4 network stack
+ /// running on the communication device this EFI IPv4
+ /// Configuration II Protocol instance manages. The policy will
+ /// affect other configuration settings. The corresponding Data is of
+ /// type EFI_IP4_CONFIG2_POLICY.
+ ///
+ Ip4Config2DataTypePolicy,
+ ///
+ /// The station addresses set manually for the EFI IPv4 network
+ /// stack. It is only configurable when the policy is
+ /// Ip4Config2PolicyStatic. The corresponding Data is of
+ /// type EFI_IP4_CONFIG2_MANUAL_ADDRESS. When DataSize
+ /// is 0 and Data is NULL, the existing configuration is cleared
+ /// from the EFI IPv4 Configuration II Protocol instance.
+ ///
+ Ip4Config2DataTypeManualAddress,
+ ///
+ /// The gateway addresses set manually for the EFI IPv4 network
+ /// stack running on the communication device this EFI IPv4
+ /// Configuration II Protocol manages. It is not configurable when
+ /// the policy is Ip4Config2PolicyDhcp. The gateway
+ /// addresses must be unicast IPv4 addresses. The corresponding
+ /// Data is a pointer to an array of EFI_IPv4_ADDRESS instances.
+ /// When DataSize is 0 and Data is NULL, the existing configuration
+ /// is cleared from the EFI IPv4 Configuration II Protocol instance.
+ ///
+ Ip4Config2DataTypeGateway,
+ ///
+ /// The DNS server list for the EFI IPv4 network stack running on
+ /// the communication device this EFI IPv4 Configuration II
+ /// Protocol manages. It is not configurable when the policy is
+ /// Ip4Config2PolicyDhcp. The DNS server addresses must be
+ /// unicast IPv4 addresses. The corresponding Data is a pointer to
+ /// an array of EFI_IPv4_ADDRESS instances. When DataSize
+ /// is 0 and Data is NULL, the existing configuration is cleared
+ /// from the EFI IPv4 Configuration II Protocol instance.
+ ///
+ Ip4Config2DataTypeDnsServer,
+ Ip4Config2DataTypeMaximum
+} EFI_IP4_CONFIG2_DATA_TYPE;
+
+///
+/// EFI_IP4_CONFIG2_INTERFACE_INFO related definitions
+///
+#define EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE 32
+
+///
+/// EFI_IP4_CONFIG2_INTERFACE_INFO
+///
+typedef struct {
+ ///
+ /// The name of the interface. It is a NULL-terminated Unicode string.
+ ///
+ CHAR16 Name[EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE];
+ ///
+ /// The interface type of the network interface. See RFC 1700,
+ /// section "Number Hardware Type".
+ ///
+ UINT8 IfType;
+ ///
+ /// The size, in bytes, of the network interface's hardware address.
+ ///
+ UINT32 HwAddressSize;
+ ///
+ /// The hardware address for the network interface.
+ ///
+ EFI_MAC_ADDRESS HwAddress;
+ ///
+ /// The station IPv4 address of this EFI IPv4 network stack.
+ ///
+ EFI_IPv4_ADDRESS StationAddress;
+ ///
+ /// The subnet address mask that is associated with the station address.
+ ///
+ EFI_IPv4_ADDRESS SubnetMask;
+ ///
+ /// Size of the following RouteTable, in bytes. May be zero.
+ ///
+ UINT32 RouteTableSize;
+ ///
+ /// The route table of the IPv4 network stack runs on this interface.
+ /// Set to NULL if RouteTableSize is zero. Type EFI_IP4_ROUTE_TABLE is defined in
+ /// EFI_IP4_PROTOCOL.GetModeData().
+ ///
+ EFI_IP4_ROUTE_TABLE *RouteTable OPTIONAL;
+} EFI_IP4_CONFIG2_INTERFACE_INFO;
+
+///
+/// EFI_IP4_CONFIG2_POLICY
+///
+typedef enum {
+ ///
+ /// Under this policy, the Ip4Config2DataTypeManualAddress,
+ /// Ip4Config2DataTypeGateway and Ip4Config2DataTypeDnsServer configuration
+ /// data are required to be set manually. The EFI IPv4 Protocol will get all
+ /// required configuration such as IPv4 address, subnet mask and
+ /// gateway settings from the EFI IPv4 Configuration II protocol.
+ ///
+ Ip4Config2PolicyStatic,
+ ///
+ /// Under this policy, the Ip4Config2DataTypeManualAddress,
+ /// Ip4Config2DataTypeGateway and Ip4Config2DataTypeDnsServer configuration data are
+ /// not allowed to set via SetData(). All of these configurations are retrieved from DHCP
+ /// server or other auto-configuration mechanism.
+ ///
+ Ip4Config2PolicyDhcp,
+ Ip4Config2PolicyMax
+} EFI_IP4_CONFIG2_POLICY;
+
+///
+/// EFI_IP4_CONFIG2_MANUAL_ADDRESS
+///
+typedef struct {
+ ///
+ /// The IPv4 unicast address.
+ ///
+ EFI_IPv4_ADDRESS Address;
+ ///
+ /// The subnet mask.
+ ///
+ EFI_IPv4_ADDRESS SubnetMask;
+} EFI_IP4_CONFIG2_MANUAL_ADDRESS;
+
+/**
+ Set the configuration for the EFI IPv4 network stack running on the communication device this EFI
+ IPv4 Configuration II Protocol instance manages.
+
+ This function is used to set the configuration data of type DataType for the EFI IPv4 network stack
+ running on the communication device this EFI IPv4 Configuration II Protocol instance manages.
+ The successfully configured data is valid after system reset or power-off.
+ The DataSize is used to calculate the count of structure instances in the Data for some
+ DataType that multiple structure instances are allowed.
+ This function is always non-blocking. When setting some typeof configuration data, an
+ asynchronous process is invoked to check the correctness of the data, such as doing address conflict
+ detection on the manually set local IPv4 address. EFI_NOT_READY is returned immediately to
+ indicate that such an asynchronous process is invoked and the process is not finished yet. The caller
+ willing to get the result of the asynchronous process is required to call RegisterDataNotify()
+ to register an event on the specified configuration data. Once the event is signaled, the caller can call
+ GetData()to get back the configuration data in order to know the result. For other types of
+ configuration data that do not require an asynchronous configuration process, the result of the
+ operation is immediately returned.
+
+ @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+ @param[in] DataType The type of data to set.
+ @param[in] DataSize Size of the buffer pointed to by Data in bytes.
+ @param[in] Data The data buffer to set. The type ofthe data buffer is associated
+ with the DataType.
+
+ @retval EFI_SUCCESS The specified configuration data for the EFI IPv4 network stack is set
+ successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
+ This is NULL.
+ One or more fields in Data and DataSize do not match the
+ requirement of the data type indicated by DataType.
+ @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified configuration
+ data can not be set under the current policy.
+ @retval EFI_ACCESS_DENIED Another set operation on the specified configuration data is already in process.
+ @retval EFI_NOT_READY An asynchronous process is invoked to set the specified configuration data and
+ the process is not finished yet.
+ @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type indicated by DataType.
+ @retval EFI_UNSUPPORTED This DataType is not supported.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_SET_DATA) (
+ IN EFI_IP4_CONFIG2_PROTOCOL *This,
+ IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
+ IN UINTN DataSize,
+ IN VOID *Data
+ );
+
+/**
+ Get the configuration data for the EFI IPv4 network stack running on the communication device this
+ EFI IPv4 Configuration II Protocol instance manages.
+
+ This function returns the configuration data of type DataType for the EFI IPv4 network stack
+ running on the communication device this EFI IPv4 Configuration II Protocol instance manages.
+ The caller is responsible for allocating the buffer usedto return the specified configuration data and
+ the required size will be returned to the caller if the size of the buffer is too small.
+ EFI_NOT_READY is returned if the specified configuration data is not ready due to an already in
+ progress asynchronous configuration process. The caller can call RegisterDataNotify() to
+ register an event on the specified configuration data. Once the asynchronous configuration process is
+ finished, the event will be signaled and a subsequent GetData() call will return the specified
+ configuration data.
+
+ @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+ @param[in] DataType The type of data to get.
+ @param[out] DataSize On input, in bytes, the size of Data. On output, in bytes, the size
+ of buffer required to store the specified configuration data.
+ @param[in] Data The data buffer in which the configuration data is returned. The
+ type of the data buffer is associated with the DataType. Ignored
+ if DataSize is 0.
+
+ @retval EFI_SUCCESS The specified configuration data is got successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
+ This is NULL.
+ DataSize is NULL.
+ Data is NULL if *DataSizeis not zero.
+ @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data
+ and the required size is returned in DataSize.
+ @retval EFI_NOT_READY The specified configuration data is not ready due to an already in
+ progress asynchronous configuration process.
+ @retval EFI_NOT_FOUND The specified configuration data is not found.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_GET_DATA) (
+ IN EFI_IP4_CONFIG2_PROTOCOL *This,
+ IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
+ IN OUT UINTN *DataSize,
+ IN VOID *Data OPTIONAL
+ );
+
+/**
+ Register an event that is to be signaled whenever a configuration process on the specified
+ configuration data is done.
+
+ This function registers an event that is to be signaled whenever a configuration process on the
+ specified configuration data is done. An event can be registered for different DataType
+ simultaneously and the caller is responsible for determining which type of configuration data causes
+ the signaling of the event in such case.
+
+ @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+ @param[in] DataType The type of data to unregister the event for.
+ @param[in] Event The event to register.
+
+ @retval EFI_SUCCESS The notification event for the specified configuration data is
+ registered.
+ @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
+ @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not supported.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_REGISTER_NOTIFY) (
+ IN EFI_IP4_CONFIG2_PROTOCOL *This,
+ IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
+ IN EFI_EVENT Event
+ );
+
+/**
+ Remove a previously registered event for the specified configuration data.
+
+ This function removes a previously registeredevent for the specified configuration data.
+
+ @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
+ @param[in] DataType The type of data to remove the previously registered event for.
+ @param[in] Event The event to unregister.
+
+ @retval EFI_SUCCESS The event registered for the specified configuration data is removed.
+ @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
+ @retval EFI_NOT_FOUND The Eventhas not been registered for the specified DataType.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_IP4_CONFIG2_UNREGISTER_NOTIFY) (
+ IN EFI_IP4_CONFIG2_PROTOCOL *This,
+ IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
+ IN EFI_EVENT Event
+ );
+
+///
+/// The EFI_IP4_CONFIG2_PROTOCOL is designed to be the central repository for the common
+/// configurations and the administrator configurable settings for the EFI IPv4 network stack.
+/// An EFI IPv4 Configuration II Protocol instance will be installed on each communication device that
+/// the EFI IPv4 network stack runs on.
+///
+struct _EFI_IP4_CONFIG2_PROTOCOL {
+ EFI_IP4_CONFIG2_SET_DATA SetData;
+ EFI_IP4_CONFIG2_GET_DATA GetData;
+ EFI_IP4_CONFIG2_REGISTER_NOTIFY RegisterDataNotify;
+ EFI_IP4_CONFIG2_UNREGISTER_NOTIFY UnregisterDataNotify;
+};
+
+extern EFI_GUID gEfiIp4Config2ProtocolGuid;
+
+#endif
+
diff --git a/stand/efi/include/Protocol/ServiceBinding.h b/stand/efi/include/Protocol/ServiceBinding.h
new file mode 100644
index 000000000000..39602b086e5b
--- /dev/null
+++ b/stand/efi/include/Protocol/ServiceBinding.h
@@ -0,0 +1,95 @@
+/* $FreeBSD$ */
+/** @file
+ UEFI Service Binding Protocol is defined in UEFI specification.
+
+ The file defines the generic Service Binding Protocol functions.
+ It provides services that are required to create and destroy child
+ handles that support a given set of protocols.
+
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_SERVICE_BINDING_H__
+#define __EFI_SERVICE_BINDING_H__
+
+///
+/// Forward reference for pure ANSI compatibility
+///
+typedef struct _EFI_SERVICE_BINDING_PROTOCOL EFI_SERVICE_BINDING_PROTOCOL;
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child
+ @retval other The child handle was not created
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SERVICE_BINDING_CREATE_CHILD)(
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN OUT EFI_HANDLE *ChildHandle
+ );
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SERVICE_BINDING_DESTROY_CHILD)(
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ );
+
+///
+/// The EFI_SERVICE_BINDING_PROTOCOL provides member functions to create and destroy
+/// child handles. A driver is responsible for adding protocols to the child handle
+/// in CreateChild() and removing protocols in DestroyChild(). It is also required
+/// that the CreateChild() function opens the parent protocol BY_CHILD_CONTROLLER
+/// to establish the parent-child relationship, and closes the protocol in DestroyChild().
+/// The pseudo code for CreateChild() and DestroyChild() is provided to specify the
+/// required behavior, not to specify the required implementation. Each consumer of
+/// a software protocol is responsible for calling CreateChild() when it requires the
+/// protocol and calling DestroyChild() when it is finished with that protocol.
+///
+struct _EFI_SERVICE_BINDING_PROTOCOL {
+ EFI_SERVICE_BINDING_CREATE_CHILD CreateChild;
+ EFI_SERVICE_BINDING_DESTROY_CHILD DestroyChild;
+};
+
+#endif
diff --git a/stand/efi/include/efidevp.h b/stand/efi/include/efidevp.h
index 6f320260952e..70e506efa50b 100644
--- a/stand/efi/include/efidevp.h
+++ b/stand/efi/include/efidevp.h
@@ -232,6 +232,8 @@ typedef struct _IPv4_DEVICE_PATH {
UINT16 RemotePort;
UINT16 Protocol;
BOOLEAN StaticIpAddress;
+ EFI_IPv4_ADDRESS GatewayIpAddress;
+ EFI_IPv4_ADDRESS SubnetMask;
} IPv4_DEVICE_PATH;
#define MSG_IPv6_DP 0x0d
@@ -294,6 +296,26 @@ typedef struct _SATA_DEVICE_PATH {
UINT16 Lun;
} SATA_DEVICE_PATH;
+
+/* DNS Device Path SubType */
+#define MSG_DNS_DP 0x1F
+typedef struct {
+ EFI_DEVICE_PATH Header;
+ /* Indicates the DNS server address is IPv4 or IPv6 address. */
+ UINT8 IsIPv6;
+ /* Instance of the DNS server address. */
+ /* XXX: actually EFI_IP_ADDRESS */
+ EFI_IPv4_ADDRESS DnsServerIp[];
+} DNS_DEVICE_PATH;
+
+/* Uniform Resource Identifiers (URI) Device Path SubType */
+#define MSG_URI_DP 0x18
+typedef struct {
+ EFI_DEVICE_PATH Header;
+ /* Instance of the URI pursuant to RFC 3986. */
+ CHAR8 Uri[];
+} URI_DEVICE_PATH;
+
#define MEDIA_DEVICE_PATH 0x04
#define MEDIA_HARDDRIVE_DP 0x01
diff --git a/stand/efi/include/efilib.h b/stand/efi/include/efilib.h
index 91fa294965a3..6ca41d848384 100644
--- a/stand/efi/include/efilib.h
+++ b/stand/efi/include/efilib.h
@@ -42,6 +42,7 @@ extern EFI_RUNTIME_SERVICES *RS;
extern struct devsw efipart_fddev;
extern struct devsw efipart_cddev;
extern struct devsw efipart_hddev;
+extern struct devsw efihttp_dev;
extern struct devsw efinet_dev;
extern struct netif_driver efinetif;
diff --git a/stand/efi/libefi/Makefile b/stand/efi/libefi/Makefile
index 9b0330815900..7ca1a1f92fd7 100644
--- a/stand/efi/libefi/Makefile
+++ b/stand/efi/libefi/Makefile
@@ -12,6 +12,7 @@ SRCS= delay.c \
efi_driver_utils.c \
efichar.c \
efienv.c \
+ efihttp.c \
efinet.c \
efipart.c \
efizfs.c \
diff --git a/stand/efi/libefi/efihttp.c b/stand/efi/libefi/efihttp.c
new file mode 100644
index 000000000000..abe2e28821ea
--- /dev/null
+++ b/stand/efi/libefi/efihttp.c
@@ -0,0 +1,776 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2019 Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#include <stand.h>
+#include <net.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include <efiprot.h>
+#include <Protocol/Http.h>
+#include <Protocol/Ip4Config2.h>
+#include <Protocol/ServiceBinding.h>
+
+/* Poll timeout in milliseconds */
+static const int EFIHTTP_POLL_TIMEOUT = 300000;
+
+static EFI_GUID http_guid = EFI_HTTP_PROTOCOL_GUID;
+static EFI_GUID httpsb_guid = EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
+static EFI_GUID ip4config2_guid = EFI_IP4_CONFIG2_PROTOCOL_GUID;
+
+static bool efihttp_init_done = false;
+
+static int efihttp_dev_init(void);
+static int efihttp_dev_strategy(void *devdata, int rw, daddr_t blk, size_t size,
+ char *buf, size_t *rsize);
+static int efihttp_dev_open(struct open_file *f, ...);
+static int efihttp_dev_close(struct open_file *f);
+
+static int efihttp_fs_open(const char *path, struct open_file *f);
+static int efihttp_fs_close(struct open_file *f);
+static int efihttp_fs_read(struct open_file *f, void *buf, size_t size,
+ size_t *resid);
+static int efihttp_fs_write(struct open_file *f, const void *buf, size_t size,
+ size_t *resid);
+static off_t efihttp_fs_seek(struct open_file *f, off_t offset, int where);
+static int efihttp_fs_stat(struct open_file *f, struct stat *sb);
+static int efihttp_fs_readdir(struct open_file *f, struct dirent *d);
+
+struct open_efihttp {
+ EFI_HTTP_PROTOCOL *http;
+ EFI_HANDLE http_handle;
+ EFI_HANDLE dev_handle;
+ char *uri_base;
+};
+
+struct file_efihttp {
+ ssize_t size;
+ off_t offset;
+ char *path;
+ bool is_dir;
+};
+
+struct devsw efihttp_dev = {
+ .dv_name = "http",
+ .dv_type = DEVT_NET,
+ .dv_init = efihttp_dev_init,
+ .dv_strategy = efihttp_dev_strategy,
+ .dv_open = efihttp_dev_open,
+ .dv_close = efihttp_dev_close,
+ .dv_ioctl = noioctl,
+ .dv_print = NULL,
+ .dv_cleanup = NULL,
+};
+
+struct fs_ops efihttp_fsops = {
+ .fs_name = "efihttp",
+ .fo_open = efihttp_fs_open,
+ .fo_close = efihttp_fs_close,
+ .fo_read = efihttp_fs_read,
+ .fo_write = efihttp_fs_write,
+ .fo_seek = efihttp_fs_seek,
+ .fo_stat = efihttp_fs_stat,
+ .fo_readdir = efihttp_fs_readdir,
+};
+
+static void EFIAPI
+notify(EFI_EVENT event, void *context)
+{
+ bool *b;
+
+ b = (bool *)context;
+ *b = true;
+}
+
+static int
+setup_ipv4_config2(EFI_HANDLE handle, MAC_ADDR_DEVICE_PATH *mac,
+ IPv4_DEVICE_PATH *ipv4, DNS_DEVICE_PATH *dns)
+{
+ EFI_IP4_CONFIG2_PROTOCOL *ip4config2;
+ EFI_STATUS status;
+
+ status = BS->OpenProtocol(handle, &ip4config2_guid,
+ (void **)&ip4config2, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+ if (ipv4) {
+ setenv("boot.netif.hwaddr",
+ ether_sprintf((u_char *)mac->MacAddress.Addr), 1);
+ setenv("boot.netif.ip",
+ inet_ntoa(*(struct in_addr *)ipv4->LocalIpAddress.Addr), 1);
+ setenv("boot.netif.netmask",
+ intoa(*(n_long *)ipv4->SubnetMask.Addr), 1);
+ setenv("boot.netif.gateway",
+ inet_ntoa(*(struct in_addr *)ipv4->GatewayIpAddress.Addr),
+ 1);
+ status = ip4config2->SetData(ip4config2,
+ Ip4Config2DataTypePolicy, sizeof(EFI_IP4_CONFIG2_POLICY),
+ &(EFI_IP4_CONFIG2_POLICY) { Ip4Config2PolicyStatic });
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+
+ status = ip4config2->SetData(ip4config2,
+ Ip4Config2DataTypeManualAddress,
+ sizeof(EFI_IP4_CONFIG2_MANUAL_ADDRESS),
+ &(EFI_IP4_CONFIG2_MANUAL_ADDRESS) {
+ .Address = ipv4->LocalIpAddress,
+ .SubnetMask = ipv4->SubnetMask });
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+
+ if (ipv4->GatewayIpAddress.Addr[0] != 0) {
+ status = ip4config2->SetData(ip4config2,
+ Ip4Config2DataTypeGateway, sizeof(EFI_IPv4_ADDRESS),
+ &ipv4->GatewayIpAddress);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+ }
+
+ if (dns) {
+ status = ip4config2->SetData(ip4config2,
+ Ip4Config2DataTypeDnsServer,
+ sizeof(EFI_IPv4_ADDRESS), &dns->DnsServerIp);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+ }
+ } else {
+ status = ip4config2->SetData(ip4config2,
+ Ip4Config2DataTypePolicy, sizeof(EFI_IP4_CONFIG2_POLICY),
+ &(EFI_IP4_CONFIG2_POLICY) { Ip4Config2PolicyDhcp });
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+ }
+
+ return (0);
+}
+
+static int
+efihttp_dev_init(void)
+{
+ EFI_DEVICE_PATH *imgpath, *devpath;
+ URI_DEVICE_PATH *uri;
+ EFI_HANDLE handle;
+ EFI_STATUS status;
+ int err;
+ bool found_http;
+
+ imgpath = efi_lookup_image_devpath(IH);
+ if (imgpath == NULL)
+ return (ENXIO);
+ devpath = imgpath;
+ found_http = false;
+ for (; !IsDevicePathEnd(devpath);
+ devpath = NextDevicePathNode(devpath)) {
+ if (DevicePathType(devpath) != MESSAGING_DEVICE_PATH ||
+ DevicePathSubType(devpath) != MSG_URI_DP)
+ continue;
+ uri = (URI_DEVICE_PATH *)devpath;
+ if (strncmp("http", uri->Uri, 4) == 0)
+ found_http = true;
+ }
+ if (!found_http)
+ return (ENXIO);
+
+ status = BS->LocateDevicePath(&httpsb_guid, &imgpath, &handle);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+
+ err = efi_register_handles(&efihttp_dev, &handle, NULL, 1);
+ if (!err)
+ efihttp_init_done = true;
+
+ return (err);
+}
+
+static int
+efihttp_dev_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf,
+ size_t *rsize)
+{
+ return (EIO);
+}
+
+static int
+efihttp_dev_open(struct open_file *f, ...)
+{
+ EFI_HTTP_CONFIG_DATA config;
+ EFI_HTTPv4_ACCESS_POINT config_access;
+ DNS_DEVICE_PATH *dns;
+ EFI_DEVICE_PATH *devpath, *imgpath;
+ EFI_SERVICE_BINDING_PROTOCOL *sb;
+ IPv4_DEVICE_PATH *ipv4;
+ MAC_ADDR_DEVICE_PATH *mac;
+ URI_DEVICE_PATH *uri;
+ struct devdesc *dev;
+ struct open_efihttp *oh;
+ char *c;
+ EFI_HANDLE handle;
+ EFI_STATUS status;
+ int err, len;
+
+ if (!efihttp_init_done)
+ return (ENXIO);
+
+ imgpath = efi_lookup_image_devpath(IH);
+ if (imgpath == NULL)
+ return (ENXIO);
+ devpath = imgpath;
+ status = BS->LocateDevicePath(&httpsb_guid, &devpath, &handle);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+ ipv4 = NULL;
+ dns = NULL;
+ uri = NULL;
+ for (; !IsDevicePathEnd(imgpath);
+ imgpath = NextDevicePathNode(imgpath)) {
+ if (DevicePathType(imgpath) != MESSAGING_DEVICE_PATH)
+ continue;
+ switch (DevicePathSubType(imgpath)) {
+ case MSG_MAC_ADDR_DP:
+ mac = (MAC_ADDR_DEVICE_PATH *)imgpath;
+ break;
+ case MSG_IPv4_DP:
+ ipv4 = (IPv4_DEVICE_PATH *)imgpath;
+ break;
+ case MSG_DNS_DP:
+ dns = (DNS_DEVICE_PATH *)imgpath;
+ break;
+ case MSG_URI_DP:
+ uri = (URI_DEVICE_PATH *)imgpath;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (uri == NULL)
+ return (ENXIO);
+
+ err = setup_ipv4_config2(handle, mac, ipv4, dns);
+ if (err)
+ return (err);
+
+ oh = calloc(1, sizeof(struct open_efihttp));
+ if (!oh)
+ return (ENOMEM);
+ oh->dev_handle = handle;
+ dev = (struct devdesc *)f->f_devdata;
+ dev->d_opendata = oh;
+
+ status = BS->OpenProtocol(handle, &httpsb_guid, (void **)&sb, IH, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(status)) {
+ err = efi_status_to_errno(status);
+ goto end;
+ }
+
+ status = sb->CreateChild(sb, &oh->http_handle);
+ if (EFI_ERROR(status)) {
+ err = efi_status_to_errno(status);
+ goto end;
+ }
+
+ status = BS->OpenProtocol(oh->http_handle, &http_guid,
+ (void **)&oh->http, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(status)) {
+ sb->DestroyChild(sb, oh->http_handle);
+ err = efi_status_to_errno(status);
+ goto end;
+ }
+
+ config.HttpVersion = HttpVersion11;
+ config.TimeOutMillisec = 0;
+ config.LocalAddressIsIPv6 = FALSE;
+ config.AccessPoint.IPv4Node = &config_access;
+ config_access.UseDefaultAddress = TRUE;
+ config_access.LocalPort = 0;
+ status = oh->http->Configure(oh->http, &config);
+ if (EFI_ERROR(status)) {
+ sb->DestroyChild(sb, oh->http_handle);
+ err = efi_status_to_errno(status);
+ goto end;
+ }
+
+ /*
+ * Here we make attempt to construct a "base" URI by stripping
+ * the last two path components from the loaded URI under the
+ * assumption that it is something like:
+ *
+ * http://127.0.0.1/foo/boot/loader.efi
+ *
+ * hoping to arriving at:
+ *
+ * http://127.0.0.1/foo/
+ */
+ len = DevicePathNodeLength(&uri->Header) - sizeof(URI_DEVICE_PATH);
+ oh->uri_base = malloc(len + 1);
+ if (oh->uri_base == NULL) {
+ err = ENOMEM;
+ goto end;
+ }
+ strncpy(oh->uri_base, uri->Uri, len);
+ oh->uri_base[len] = '\0';
+ c = strrchr(oh->uri_base, '/');
+ if (c != NULL)
+ *c = '\0';
+ c = strrchr(oh->uri_base, '/');
+ if (c != NULL && *(c + 1) != '\0')
+ *(c + 1) = '\0';
+
+ err = 0;
+end:
+ if (err != 0) {
+ free(dev->d_opendata);
+ dev->d_opendata = NULL;
+ }
+ return (err);
+}
+
+static int
+efihttp_dev_close(struct open_file *f)
+{
+ EFI_SERVICE_BINDING_PROTOCOL *sb;
+ struct devdesc *dev;
+ struct open_efihttp *oh;
+ EFI_STATUS status;
+
+ dev = (struct devdesc *)f->f_devdata;
+ oh = (struct open_efihttp *)dev->d_opendata;
+ status = BS->OpenProtocol(oh->dev_handle, &httpsb_guid, (void **)&sb,
+ IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+ sb->DestroyChild(sb, oh->http_handle);
+ free(oh->uri_base);
+ free(oh);
+ dev->d_opendata = NULL;
+ return (0);
+}
+
+static int
+_efihttp_fs_open(const char *path, struct open_file *f)
+{
+ EFI_HTTP_CONFIG_DATA config;
+ EFI_HTTPv4_ACCESS_POINT config_access;
+ EFI_HTTP_TOKEN token;
+ EFI_HTTP_MESSAGE message;
+ EFI_HTTP_REQUEST_DATA request;
+ EFI_HTTP_RESPONSE_DATA response;
+ EFI_HTTP_HEADER headers[3];
+ char *host, *hostp;
+ char *c;
+ struct devdesc *dev;
+ struct open_efihttp *oh;
+ struct file_efihttp *fh;
+ EFI_STATUS status;
+ int i;
+ int polltime;
+ bool done;
+
+ dev = (struct devdesc *)f->f_devdata;
+ oh = (struct open_efihttp *)dev->d_opendata;
+ fh = calloc(1, sizeof(struct file_efihttp));
+ if (fh == NULL)
+ return (ENOMEM);
+ f->f_fsdata = fh;
+ fh->path = strdup(path);
+
+ /*
+ * Reset the HTTP state.
+ *
+ * EDK II's persistent HTTP connection handling is graceless,
+ * assuming that all connections are persistent regardless of
+ * any Connection: header or HTTP version reported by the
+ * server, and failing to send requests when a more sane
+ * implementation would seem to be just reestablishing the
+ * closed connection.
+ *
+ * In the hopes of having some robustness, we indicate to the
+ * server that we will close the connection by using a
+ * Connection: close header. And then here we manually
+ * unconfigure and reconfigure the http instance to force the
+ * connection closed.
+ */
+ memset(&config, 0, sizeof(config));
+ memset(&config_access, 0, sizeof(config_access));
+ config.AccessPoint.IPv4Node = &config_access;
+ status = oh->http->GetModeData(oh->http, &config);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+ status = oh->http->Configure(oh->http, NULL);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+ status = oh->http->Configure(oh->http, &config);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+
+ /* Send the read request */
+ done = false;
+ status = BS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, notify,
+ &done, &token.Event);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+
+ /* extract the host portion of the URL */
+ host = strdup(oh->uri_base);
+ if (host == NULL)
+ return (ENOMEM);
+ hostp = host;
+ /* Remove the protocol scheme */
+ c = strchr(host, '/');
+ if (c != NULL && *(c + 1) == '/')
+ hostp = (c + 2);
+
+ /* Remove any path information */
+ c = strchr(hostp, '/');
+ if (c != NULL)
+ *c = '\0';
+
+ token.Status = EFI_NOT_READY;
+ token.Message = &message;
+ message.Data.Request = &request;
+ message.HeaderCount = 3;
+ message.Headers = headers;
+ message.BodyLength = 0;
+ message.Body = NULL;
+ request.Method = HttpMethodGet;
+ request.Url = calloc(strlen(oh->uri_base) + strlen(path) + 1, 2);
+ headers[0].FieldName = "Host";
+ headers[0].FieldValue = hostp;
+ headers[1].FieldName = "Connection";
+ headers[1].FieldValue = "close";
+ headers[2].FieldName = "Accept";
+ headers[2].FieldValue = "*/*";
+ cpy8to16(oh->uri_base, request.Url, strlen(oh->uri_base));
+ cpy8to16(path, request.Url + strlen(oh->uri_base), strlen(path));
+ status = oh->http->Request(oh->http, &token);
+ free(request.Url);
+ free(host);
+ if (EFI_ERROR(status)) {
+ BS->CloseEvent(token.Event);
+ return (efi_status_to_errno(status));
+ }
+
+ polltime = 0;
+ while (!done && polltime < EFIHTTP_POLL_TIMEOUT) {
+ status = oh->http->Poll(oh->http);
+ if (EFI_ERROR(status))
+ break;
+
+ if (!done) {
+ delay(100 * 1000);
+ polltime += 100;
+ }
+ }
+ BS->CloseEvent(token.Event);
+ if (EFI_ERROR(token.Status))
+ return (efi_status_to_errno(token.Status));
+
+ /* Wait for the read response */
+ done = false;
+ status = BS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, notify,
+ &done, &token.Event);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
+ token.Status = EFI_NOT_READY;
+ token.Message = &message;
+ message.Data.Response = &response;
+ message.HeaderCount = 0;
+ message.Headers = NULL;
+ message.BodyLength = 0;
+ message.Body = NULL;
+ response.StatusCode = HTTP_STATUS_UNSUPPORTED_STATUS;
+ status = oh->http->Response(oh->http, &token);
+ if (EFI_ERROR(status)) {
+ BS->CloseEvent(token.Event);
+ return (efi_status_to_errno(status));
+ }
+
+ polltime = 0;
+ while (!done && polltime < EFIHTTP_POLL_TIMEOUT) {
+ status = oh->http->Poll(oh->http);
+ if (EFI_ERROR(status))
+ break;
+
+ if (!done) {
+ delay(100 * 1000);
+ polltime += 100;
+ }
+ }
+ BS->CloseEvent(token.Event);
+ if (EFI_ERROR(token.Status)) {
+ BS->FreePool(message.Headers);
+ return (efi_status_to_errno(token.Status));
+ }
+ if (response.StatusCode != HTTP_STATUS_200_OK) {
+ BS->FreePool(message.Headers);
+ return (EIO);
+ }
+ fh->size = 0;
+ fh->is_dir = false;
+ for (i = 0; i < message.HeaderCount; i++) {
+ if (strcasecmp(message.Headers[i].FieldName,
+ "Content-Length") == 0)
+ fh->size = strtoul(message.Headers[i].FieldValue, NULL,
+ 10);
+ else if (strcasecmp(message.Headers[i].FieldName,
+ "Content-type") == 0) {
+ if (strncmp(message.Headers[i].FieldValue, "text/html",
+ 9) == 0)
+ fh->is_dir = true;
+ }
+ }
+
+ return (0);
+}
+
+static int
+efihttp_fs_open(const char *path, struct open_file *f)
+{
+ char *path_slash;
+ int err;
+
+ if (!efihttp_init_done)
+ return (ENXIO);
+ /*
+ * If any path fails to open, try with a trailing slash in
+ * case it's a directory.
+ */
+ err = _efihttp_fs_open(path, f);
+ if (err != 0) {
+ path_slash = malloc(strlen(path) + 2);
+ if (path_slash == NULL)
+ return (ENOMEM);
+ strcpy(path_slash, path);
+ strcat(path_slash, "/");
+ err = _efihttp_fs_open(path_slash, f);
+ free(path_slash);
+ }
+ return (err);
+}
+
+static int
+efihttp_fs_close(struct open_file *f)
+{
+ return (0);
+}
+
+static int
+_efihttp_fs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
+{
+ EFI_HTTP_TOKEN token;
+ EFI_HTTP_MESSAGE message;
+ EFI_STATUS status;
+ struct devdesc *dev;
+ struct open_efihttp *oh;
+ struct file_efihttp *fh;
+ bool done;
+ int polltime;
+
+ fh = (struct file_efihttp *)f->f_fsdata;
+
+ if (fh->size > 0 && fh->offset >= fh->size) {
+ if (resid != NULL)
+ *resid = size;
+
+ return 0;
+ }
+
+ dev = (struct devdesc *)f->f_devdata;
+ oh = (struct open_efihttp *)dev->d_opendata;
+ done = false;
+ status = BS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, notify,
+ &done, &token.Event);
+ if (EFI_ERROR(status)) {
+ return (efi_status_to_errno(status));
+ }
+ token.Status = EFI_NOT_READY;
+ token.Message = &message;
+ message.Data.Request = NULL;
+ message.HeaderCount = 0;
+ message.Headers = NULL;
+ message.BodyLength = size;
+ message.Body = buf;
+ status = oh->http->Response(oh->http, &token);
+ if (status == EFI_CONNECTION_FIN) {
+ if (resid)
+ *resid = size;
+ return (0);
+ } else if (EFI_ERROR(status)) {
+ BS->CloseEvent(token.Event);
+ return (efi_status_to_errno(status));
+ }
+ polltime = 0;
+ while (!done && polltime < EFIHTTP_POLL_TIMEOUT) {
+ status = oh->http->Poll(oh->http);
+ if (EFI_ERROR(status))
+ break;
+
+ if (!done) {
+ delay(100 * 1000);
+ polltime += 100;
+ }
+ }
+ BS->CloseEvent(token.Event);
+ if (token.Status == EFI_CONNECTION_FIN) {
+ if (resid)
+ *resid = size;
+ return (0);
+ } else if (EFI_ERROR(token.Status))
+ return (efi_status_to_errno(token.Status));
+ if (resid)
+ *resid = size - message.BodyLength;
+ fh->offset += message.BodyLength;
+ return (0);
+}
+
+static int
+efihttp_fs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
+{
+ size_t res;
+ int err;
+
+ while (size > 0) {
+ err = _efihttp_fs_read(f, buf, size, &res);
+ if (err != 0 || res == size)
+ goto end;
+ buf += (size - res);
+ size = res;
+ }
+end:
+ if (resid)
+ *resid = size;
+ return (err);
+}
+
+static int
+efihttp_fs_write(struct open_file *f, const void *buf, size_t size, size_t *resid)
+{
+ return (EIO);
+}
+
+static off_t
+efihttp_fs_seek(struct open_file *f, off_t offset, int where)
+{
+ struct file_efihttp *fh;
+ char *path;
+ void *buf;
+ size_t res, res2;
+ int err;
+
+ fh = (struct file_efihttp *)f->f_fsdata;
+ if (where == SEEK_SET && fh->offset == offset)
+ return (0);
+ if (where == SEEK_SET && fh->offset < offset) {
+ buf = malloc(1500);
+ res = offset - fh->offset;
+ while (res > 0) {
+ err = _efihttp_fs_read(f, buf, min(1500, res), &res2);
+ if (err != 0) {
+ free(buf);
+ return (err);
+ }
+ res -= min(1500, res) - res2;
+ }
+ free(buf);
+ return (0);
+ } else if (where == SEEK_SET) {
+ path = fh->path;
+ fh->path = NULL;
+ efihttp_fs_close(f);
+ err = efihttp_fs_open(path, f);
+ free(path);
+ if (err != 0)
+ return (err);
+ return efihttp_fs_seek(f, offset, where);
+ }
+ return (EIO);
+}
+
+static int
+efihttp_fs_stat(struct open_file *f, struct stat *sb)
+{
+ struct file_efihttp *fh;
+
+ fh = (struct file_efihttp *)f->f_fsdata;
+ memset(sb, 0, sizeof(*sb));
+ sb->st_nlink = 1;
+ sb->st_mode = 0777 | (fh->is_dir ? S_IFDIR : S_IFREG);
+ sb->st_size = fh->size;
+ return (0);
+}
+
+static int
+efihttp_fs_readdir(struct open_file *f, struct dirent *d)
+{
+ static char *dirbuf = NULL, *db2, *cursor;
+ static int dirbuf_len = 0;
+ char *end;
+ struct file_efihttp *fh;
+
+ fh = (struct file_efihttp *)f->f_fsdata;
+ if (dirbuf_len < fh->size) {
+ db2 = realloc(dirbuf, fh->size);
+ if (db2 == NULL) {
+ free(dirbuf);
+ return (ENOMEM);
+ } else
+ dirbuf = db2;
+
+ dirbuf_len = fh->size;
+ }
+
+ if (fh->offset != fh->size) {
+ efihttp_fs_seek(f, 0, SEEK_SET);
+ efihttp_fs_read(f, dirbuf, dirbuf_len, NULL);
+ cursor = dirbuf;
+ }
+
+ cursor = strstr(cursor, "<a href=\"");
+ if (cursor == NULL)
+ return (ENOENT);
+ cursor += 9;
+ end = strchr(cursor, '"');
+ if (*(end - 1) == '/') {
+ end--;
+ d->d_type = DT_DIR;
+ } else
+ d->d_type = DT_REG;
+ memcpy(d->d_name, cursor, end - cursor);
+ d->d_name[end - cursor] = '\0';
+
+ return (0);
+}
diff --git a/stand/efi/loader/conf.c b/stand/efi/loader/conf.c
index 2e4d35f88a6c..d08ded39b4f2 100644
--- a/stand/efi/loader/conf.c
+++ b/stand/efi/loader/conf.c
@@ -39,6 +39,7 @@ struct devsw *devsw[] = {
&efipart_fddev,
&efipart_cddev,
&efipart_hddev,
+ &efihttp_dev, /* ordering with efinet_dev matters */
&efinet_dev,
&vdisk_dev,
#ifdef EFI_ZFS_BOOT
@@ -54,6 +55,7 @@ struct fs_ops *file_system[] = {
&dosfs_fsops,
&ufs_fsops,
&cd9660_fsops,
+ &efihttp_fsops,
&tftp_fsops,
&nfs_fsops,
&gzipfs_fsops,
diff --git a/stand/efi/loader/copy.c b/stand/efi/loader/copy.c
index a19b048c9beb..e134c22c091e 100644
--- a/stand/efi/loader/copy.c
+++ b/stand/efi/loader/copy.c
@@ -176,8 +176,12 @@ out:
#endif /* __i386__ || __amd64__ */
#ifndef EFI_STAGING_SIZE
+#if defined(__amd64__)
+#define EFI_STAGING_SIZE 100
+#else
#define EFI_STAGING_SIZE 64
#endif
+#endif
EFI_PHYSICAL_ADDRESS staging, staging_end;
int stage_offset_set = 0;
diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c
index 8b3ba741178c..60d8c1442518 100644
--- a/stand/efi/loader/main.c
+++ b/stand/efi/loader/main.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/reboot.h>
#include <sys/boot.h>
+#include <paths.h>
#include <stdint.h>
#include <string.h>
#include <setjmp.h>
@@ -237,8 +238,8 @@ sanity_check_currdev(void)
{
struct stat st;
- return (stat("/boot/defaults/loader.conf", &st) == 0 ||
- stat("/boot/kernel/kernel", &st) == 0);
+ return (stat(PATH_DEFAULTS_LOADER_CONF, &st) == 0 ||
+ stat(PATH_KERNEL, &st) == 0);
}
#ifdef EFI_ZFS_BOOT
diff --git a/stand/i386/loader/conf.c b/stand/i386/loader/conf.c
index 02f1160cd1a4..c70a53d4191a 100644
--- a/stand/i386/loader/conf.c
+++ b/stand/i386/loader/conf.c
@@ -84,9 +84,6 @@ struct fs_ops *file_system[] = {
#if defined(LOADER_CD9660_SUPPORT)
&cd9660_fsops,
#endif
-#if defined(LOADER_NANDFS_SUPPORT)
- &nandfs_fsops,
-#endif
#ifdef LOADER_NFS_SUPPORT
&nfs_fsops,
#endif
diff --git a/stand/libsa/Makefile b/stand/libsa/Makefile
index b09b23c79d93..72a9775298d0 100644
--- a/stand/libsa/Makefile
+++ b/stand/libsa/Makefile
@@ -145,9 +145,6 @@ SRCS+= ufs.c nfs.c cd9660.c tftp.c gzipfs.c bzipfs.c
SRCS+= dosfs.c ext2fs.c
SRCS+= splitfs.c
SRCS+= pkgfs.c
-.if ${MK_NAND} != "no"
-SRCS+= nandfs.c
-.endif
# kernel ufs support
.PATH: ${SRCTOP}/sys/ufs/ffs
diff --git a/stand/libsa/nandfs.c b/stand/libsa/nandfs.c
deleted file mode 100644
index b3e72243e995..000000000000
--- a/stand/libsa/nandfs.c
+++ /dev/null
@@ -1,1061 +0,0 @@
-/*-
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/stdint.h>
-#include <ufs/ufs/dinode.h>
-#include <fs/nandfs/nandfs_fs.h>
-#include "stand.h"
-#include "string.h"
-#include "zlib.h"
-
-#define DEBUG
-#undef DEBUG
-#ifdef DEBUG
-#define NANDFS_DEBUG(fmt, args...) do { \
- printf("NANDFS_DEBUG:" fmt "\n", ##args); } while (0)
-#else
-#define NANDFS_DEBUG(fmt, args...)
-#endif
-
-struct nandfs_mdt {
- uint32_t entries_per_block;
- uint32_t entries_per_group;
- uint32_t blocks_per_group;
- uint32_t groups_per_desc_block; /* desc is super group */
- uint32_t blocks_per_desc_block; /* desc is super group */
-};
-
-struct bmap_buf {
- LIST_ENTRY(bmap_buf) list;
- nandfs_daddr_t blknr;
- uint64_t *map;
-};
-
-struct nandfs_node {
- struct nandfs_inode *inode;
- LIST_HEAD(, bmap_buf) bmap_bufs;
-};
-struct nandfs {
- int nf_blocksize;
- int nf_sectorsize;
- int nf_cpno;
-
- struct open_file *nf_file;
- struct nandfs_node *nf_opened_node;
- u_int nf_offset;
- uint8_t *nf_buf;
- int64_t nf_buf_blknr;
-
- struct nandfs_fsdata *nf_fsdata;
- struct nandfs_super_block *nf_sb;
- struct nandfs_segment_summary nf_segsum;
- struct nandfs_checkpoint nf_checkpoint;
- struct nandfs_super_root nf_sroot;
- struct nandfs_node nf_ifile;
- struct nandfs_node nf_datfile;
- struct nandfs_node nf_cpfile;
- struct nandfs_mdt nf_datfile_mdt;
- struct nandfs_mdt nf_ifile_mdt;
-
- int nf_nindir[NANDFS_NIADDR];
-};
-
-static int nandfs_open(const char *, struct open_file *);
-static int nandfs_close(struct open_file *);
-static int nandfs_read(struct open_file *, void *, size_t, size_t *);
-static off_t nandfs_seek(struct open_file *, off_t, int);
-static int nandfs_stat(struct open_file *, struct stat *);
-static int nandfs_readdir(struct open_file *, struct dirent *);
-
-static int nandfs_buf_read(struct nandfs *, void **, size_t *);
-static struct nandfs_node *nandfs_lookup_path(struct nandfs *, const char *);
-static int nandfs_read_inode(struct nandfs *, struct nandfs_node *,
- nandfs_lbn_t, u_int, void *, int);
-static int nandfs_read_blk(struct nandfs *, nandfs_daddr_t, void *, int);
-static int nandfs_bmap_lookup(struct nandfs *, struct nandfs_node *,
- nandfs_lbn_t, nandfs_daddr_t *, int);
-static int nandfs_get_checkpoint(struct nandfs *, uint64_t,
- struct nandfs_checkpoint *);
-static nandfs_daddr_t nandfs_vtop(struct nandfs *, nandfs_daddr_t);
-static void nandfs_calc_mdt_consts(int, struct nandfs_mdt *, int);
-static void nandfs_mdt_trans(struct nandfs_mdt *, uint64_t,
- nandfs_daddr_t *, uint32_t *);
-static int ioread(struct open_file *, off_t, void *, u_int);
-static int nandfs_probe_sectorsize(struct open_file *);
-
-struct fs_ops nandfs_fsops = {
- "nandfs",
- nandfs_open,
- nandfs_close,
- nandfs_read,
- null_write,
- nandfs_seek,
- nandfs_stat,
- nandfs_readdir
-};
-
-#define NINDIR(fs) ((fs)->nf_blocksize / sizeof(nandfs_daddr_t))
-
-/* from NetBSD's src/sys/net/if_ethersubr.c */
-static uint32_t
-nandfs_crc32(uint32_t crc, const uint8_t *buf, size_t len)
-{
- static const uint32_t crctab[] = {
- 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
- 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
- 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
- 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
- };
- size_t i;
-
- crc = crc ^ ~0U;
- for (i = 0; i < len; i++) {
- crc ^= buf[i];
- crc = (crc >> 4) ^ crctab[crc & 0xf];
- crc = (crc >> 4) ^ crctab[crc & 0xf];
- }
- return (crc ^ ~0U);
-}
-
-static int
-nandfs_check_fsdata_crc(struct nandfs_fsdata *fsdata)
-{
- uint32_t fsdata_crc, comp_crc;
-
- if (fsdata->f_magic != NANDFS_FSDATA_MAGIC)
- return (0);
-
- /* Preserve crc */
- fsdata_crc = fsdata->f_sum;
-
- /* Calculate */
- fsdata->f_sum = (0);
- comp_crc = nandfs_crc32(0, (uint8_t *)fsdata, fsdata->f_bytes);
-
- /* Restore */
- fsdata->f_sum = fsdata_crc;
-
- /* Check CRC */
- return (fsdata_crc == comp_crc);
-}
-
-static int
-nandfs_check_superblock_crc(struct nandfs_fsdata *fsdata,
- struct nandfs_super_block *super)
-{
- uint32_t super_crc, comp_crc;
-
- /* Check super block magic */
- if (super->s_magic != NANDFS_SUPER_MAGIC)
- return (0);
-
- /* Preserve CRC */
- super_crc = super->s_sum;
-
- /* Calculate */
- super->s_sum = (0);
- comp_crc = nandfs_crc32(0, (uint8_t *)super, fsdata->f_sbbytes);
-
- /* Restore */
- super->s_sum = super_crc;
-
- /* Check CRC */
- return (super_crc == comp_crc);
-}
-
-static int
-nandfs_find_super_block(struct nandfs *fs, struct open_file *f)
-{
- struct nandfs_super_block *sb;
- int i, j, n, s;
- int sectors_to_read, error;
-
- sb = malloc(fs->nf_sectorsize);
- if (sb == NULL)
- return (ENOMEM);
-
- memset(fs->nf_sb, 0, sizeof(*fs->nf_sb));
-
- sectors_to_read = (NANDFS_NFSAREAS * fs->nf_fsdata->f_erasesize) /
- fs->nf_sectorsize;
- for (i = 0; i < sectors_to_read; i++) {
- NANDFS_DEBUG("reading i %d offset %d\n", i,
- i * fs->nf_sectorsize);
- error = ioread(f, i * fs->nf_sectorsize, (char *)sb,
- fs->nf_sectorsize);
- if (error) {
- NANDFS_DEBUG("error %d\n", error);
- continue;
- }
- n = fs->nf_sectorsize / sizeof(struct nandfs_super_block);
- s = 0;
- if ((i * fs->nf_sectorsize) % fs->nf_fsdata->f_erasesize == 0) {
- if (fs->nf_sectorsize == sizeof(struct nandfs_fsdata))
- continue;
- else {
- s += (sizeof(struct nandfs_fsdata) /
- sizeof(struct nandfs_super_block));
- }
- }
-
- for (j = s; j < n; j++) {
- if (!nandfs_check_superblock_crc(fs->nf_fsdata, &sb[j]))
- continue;
- NANDFS_DEBUG("magic %x wtime %jd, lastcp 0x%jx\n",
- sb[j].s_magic, sb[j].s_wtime, sb[j].s_last_cno);
- if (sb[j].s_last_cno > fs->nf_sb->s_last_cno)
- memcpy(fs->nf_sb, &sb[j], sizeof(*fs->nf_sb));
- }
- }
-
- free(sb);
-
- return (fs->nf_sb->s_magic != 0 ? 0 : EINVAL);
-}
-
-static int
-nandfs_find_fsdata(struct nandfs *fs, struct open_file *f)
-{
- int offset, error, i;
-
- NANDFS_DEBUG("starting\n");
-
- offset = 0;
- for (i = 0; i < 64 * NANDFS_NFSAREAS; i++) {
- error = ioread(f, offset, (char *)fs->nf_fsdata,
- sizeof(struct nandfs_fsdata));
- if (error)
- return (error);
- if (fs->nf_fsdata->f_magic == NANDFS_FSDATA_MAGIC) {
- NANDFS_DEBUG("found at %x, volume %s\n", offset,
- fs->nf_fsdata->f_volume_name);
- if (nandfs_check_fsdata_crc(fs->nf_fsdata))
- break;
- }
- offset += fs->nf_sectorsize;
- }
-
- return (error);
-}
-
-static int
-nandfs_read_structures(struct nandfs *fs, struct open_file *f)
-{
- int error;
-
- error = nandfs_find_fsdata(fs, f);
- if (error)
- return (error);
-
- error = nandfs_find_super_block(fs, f);
-
- if (error == 0)
- NANDFS_DEBUG("selected sb with w_time %jd last_pseg %jx\n",
- fs->nf_sb->s_wtime, fs->nf_sb->s_last_pseg);
-
- return (error);
-}
-
-static int
-nandfs_mount(struct nandfs *fs, struct open_file *f)
-{
- int err = 0, level;
- uint64_t last_pseg;
-
- fs->nf_fsdata = malloc(sizeof(struct nandfs_fsdata));
- fs->nf_sb = malloc(sizeof(struct nandfs_super_block));
-
- err = nandfs_read_structures(fs, f);
- if (err) {
- free(fs->nf_fsdata);
- free(fs->nf_sb);
- return (err);
- }
-
- fs->nf_blocksize = 1 << (fs->nf_fsdata->f_log_block_size + 10);
-
- NANDFS_DEBUG("using superblock with wtime %jd\n", fs->nf_sb->s_wtime);
-
- fs->nf_cpno = fs->nf_sb->s_last_cno;
- last_pseg = fs->nf_sb->s_last_pseg;
-
- /*
- * Calculate indirect block levels.
- */
- nandfs_daddr_t mult;
-
- mult = 1;
- for (level = 0; level < NANDFS_NIADDR; level++) {
- mult *= NINDIR(fs);
- fs->nf_nindir[level] = mult;
- }
-
- nandfs_calc_mdt_consts(fs->nf_blocksize, &fs->nf_datfile_mdt,
- fs->nf_fsdata->f_dat_entry_size);
-
- nandfs_calc_mdt_consts(fs->nf_blocksize, &fs->nf_ifile_mdt,
- fs->nf_fsdata->f_inode_size);
-
- err = ioread(f, last_pseg * fs->nf_blocksize, &fs->nf_segsum,
- sizeof(struct nandfs_segment_summary));
- if (err) {
- free(fs->nf_sb);
- free(fs->nf_fsdata);
- return (err);
- }
-
- err = ioread(f, (last_pseg + fs->nf_segsum.ss_nblocks - 1) *
- fs->nf_blocksize, &fs->nf_sroot, sizeof(struct nandfs_super_root));
- if (err) {
- free(fs->nf_sb);
- free(fs->nf_fsdata);
- return (err);
- }
-
- fs->nf_datfile.inode = &fs->nf_sroot.sr_dat;
- LIST_INIT(&fs->nf_datfile.bmap_bufs);
- fs->nf_cpfile.inode = &fs->nf_sroot.sr_cpfile;
- LIST_INIT(&fs->nf_cpfile.bmap_bufs);
-
- err = nandfs_get_checkpoint(fs, fs->nf_cpno, &fs->nf_checkpoint);
- if (err) {
- free(fs->nf_sb);
- free(fs->nf_fsdata);
- return (err);
- }
-
- NANDFS_DEBUG("checkpoint cp_cno=%lld\n", fs->nf_checkpoint.cp_cno);
- NANDFS_DEBUG("checkpoint cp_inodes_count=%lld\n",
- fs->nf_checkpoint.cp_inodes_count);
- NANDFS_DEBUG("checkpoint cp_ifile_inode.i_blocks=%lld\n",
- fs->nf_checkpoint.cp_ifile_inode.i_blocks);
-
- fs->nf_ifile.inode = &fs->nf_checkpoint.cp_ifile_inode;
- LIST_INIT(&fs->nf_ifile.bmap_bufs);
- return (0);
-}
-
-#define NINDIR(fs) ((fs)->nf_blocksize / sizeof(nandfs_daddr_t))
-
-static int
-nandfs_open(const char *path, struct open_file *f)
-{
- struct nandfs *fs;
- struct nandfs_node *node;
- int err, bsize, level;
-
- NANDFS_DEBUG("nandfs_open('%s', %p)\n", path, f);
-
- fs = malloc(sizeof(struct nandfs));
- f->f_fsdata = fs;
- fs->nf_file = f;
-
- bsize = nandfs_probe_sectorsize(f);
- if (bsize < 0) {
- printf("Cannot probe medium sector size\n");
- return (EINVAL);
- }
-
- fs->nf_sectorsize = bsize;
-
- /*
- * Calculate indirect block levels.
- */
- nandfs_daddr_t mult;
-
- mult = 1;
- for (level = 0; level < NANDFS_NIADDR; level++) {
- mult *= NINDIR(fs);
- fs->nf_nindir[level] = mult;
- }
-
- NANDFS_DEBUG("fs %p nf_sectorsize=%x\n", fs, fs->nf_sectorsize);
-
- err = nandfs_mount(fs, f);
- if (err) {
- NANDFS_DEBUG("Cannot mount nandfs: %s\n", strerror(err));
- return (err);
- }
-
- node = nandfs_lookup_path(fs, path);
- if (node == NULL)
- return (EINVAL);
-
- fs->nf_offset = 0;
- fs->nf_buf = NULL;
- fs->nf_buf_blknr = -1;
- fs->nf_opened_node = node;
- LIST_INIT(&fs->nf_opened_node->bmap_bufs);
- return (0);
-}
-
-static void
-nandfs_free_node(struct nandfs_node *node)
-{
- struct bmap_buf *bmap, *tmp;
-
- free(node->inode);
- LIST_FOREACH_SAFE(bmap, &node->bmap_bufs, list, tmp) {
- LIST_REMOVE(bmap, list);
- free(bmap->map);
- free(bmap);
- }
- free(node);
-}
-
-static int
-nandfs_close(struct open_file *f)
-{
- struct nandfs *fs = f->f_fsdata;
-
- NANDFS_DEBUG("nandfs_close(%p)\n", f);
-
- if (fs->nf_buf != NULL)
- free(fs->nf_buf);
-
- nandfs_free_node(fs->nf_opened_node);
- free(fs->nf_sb);
- free(fs);
- return (0);
-}
-
-static int
-nandfs_read(struct open_file *f, void *addr, size_t size, size_t *resid)
-{
- struct nandfs *fs = (struct nandfs *)f->f_fsdata;
- size_t csize, buf_size;
- void *buf;
- int error = 0;
-
- NANDFS_DEBUG("nandfs_read(file=%p, addr=%p, size=%d)\n", f, addr, size);
-
- while (size != 0) {
- if (fs->nf_offset >= fs->nf_opened_node->inode->i_size)
- break;
-
- error = nandfs_buf_read(fs, &buf, &buf_size);
- if (error)
- break;
-
- csize = size;
- if (csize > buf_size)
- csize = buf_size;
-
- bcopy(buf, addr, csize);
-
- fs->nf_offset += csize;
- addr = (char *)addr + csize;
- size -= csize;
- }
-
- if (resid)
- *resid = size;
- return (error);
-}
-
-static off_t
-nandfs_seek(struct open_file *f, off_t offset, int where)
-{
- struct nandfs *fs = f->f_fsdata;
- off_t off;
- u_int size;
-
- NANDFS_DEBUG("nandfs_seek(file=%p, offset=%lld, where=%d)\n", f,
- offset, where);
-
- size = fs->nf_opened_node->inode->i_size;
-
- switch (where) {
- case SEEK_SET:
- off = 0;
- break;
- case SEEK_CUR:
- off = fs->nf_offset;
- break;
- case SEEK_END:
- off = size;
- break;
- default:
- errno = EINVAL;
- return (-1);
- }
-
- off += offset;
- if (off < 0 || off > size) {
- errno = EINVAL;
- return(-1);
- }
-
- fs->nf_offset = (u_int)off;
-
- return (off);
-}
-
-static int
-nandfs_stat(struct open_file *f, struct stat *sb)
-{
- struct nandfs *fs = f->f_fsdata;
-
- NANDFS_DEBUG("nandfs_stat(file=%p, stat=%p)\n", f, sb);
-
- sb->st_size = fs->nf_opened_node->inode->i_size;
- sb->st_mode = fs->nf_opened_node->inode->i_mode;
- sb->st_uid = fs->nf_opened_node->inode->i_uid;
- sb->st_gid = fs->nf_opened_node->inode->i_gid;
- return (0);
-}
-
-static int
-nandfs_readdir(struct open_file *f, struct dirent *d)
-{
- struct nandfs *fs = f->f_fsdata;
- struct nandfs_dir_entry *dirent;
- void *buf;
- size_t buf_size;
-
- NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)\n", f, d);
-
- if (fs->nf_offset >= fs->nf_opened_node->inode->i_size) {
- NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p) ENOENT\n",
- f, d);
- return (ENOENT);
- }
-
- if (nandfs_buf_read(fs, &buf, &buf_size)) {
- NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)"
- "buf_read failed\n", f, d);
- return (EIO);
- }
-
- NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p) moving forward\n",
- f, d);
-
- dirent = (struct nandfs_dir_entry *)buf;
- fs->nf_offset += dirent->rec_len;
- strncpy(d->d_name, dirent->name, dirent->name_len);
- d->d_name[dirent->name_len] = '\0';
- d->d_type = dirent->file_type;
- return (0);
-}
-
-static int
-nandfs_buf_read(struct nandfs *fs, void **buf_p, size_t *size_p)
-{
- nandfs_daddr_t blknr, blkoff;
-
- blknr = fs->nf_offset / fs->nf_blocksize;
- blkoff = fs->nf_offset % fs->nf_blocksize;
-
- if (blknr != fs->nf_buf_blknr) {
- if (fs->nf_buf == NULL)
- fs->nf_buf = malloc(fs->nf_blocksize);
-
- if (nandfs_read_inode(fs, fs->nf_opened_node, blknr, 1,
- fs->nf_buf, 0))
- return (EIO);
-
- fs->nf_buf_blknr = blknr;
- }
-
- *buf_p = fs->nf_buf + blkoff;
- *size_p = fs->nf_blocksize - blkoff;
-
- NANDFS_DEBUG("nandfs_buf_read buf_p=%p size_p=%d\n", *buf_p, *size_p);
-
- if (*size_p > fs->nf_opened_node->inode->i_size - fs->nf_offset)
- *size_p = fs->nf_opened_node->inode->i_size - fs->nf_offset;
-
- return (0);
-}
-
-static struct nandfs_node *
-nandfs_lookup_node(struct nandfs *fs, uint64_t ino)
-{
- uint64_t blocknr;
- int entrynr;
- struct nandfs_inode *buffer;
- struct nandfs_node *node;
- struct nandfs_inode *inode;
-
- NANDFS_DEBUG("nandfs_lookup_node ino=%lld\n", ino);
-
- if (ino == 0) {
- printf("nandfs_lookup_node: invalid inode requested\n");
- return (NULL);
- }
-
- buffer = malloc(fs->nf_blocksize);
- inode = malloc(sizeof(struct nandfs_inode));
- node = malloc(sizeof(struct nandfs_node));
-
- nandfs_mdt_trans(&fs->nf_ifile_mdt, ino, &blocknr, &entrynr);
-
- if (nandfs_read_inode(fs, &fs->nf_ifile, blocknr, 1, buffer, 0))
- return (NULL);
-
- memcpy(inode, &buffer[entrynr], sizeof(struct nandfs_inode));
- node->inode = inode;
- free(buffer);
- return (node);
-}
-
-static struct nandfs_node *
-nandfs_lookup_path(struct nandfs *fs, const char *path)
-{
- struct nandfs_node *node;
- struct nandfs_dir_entry *dirent;
- char *namebuf;
- uint64_t i, done, pinode, inode;
- int nlinks = 0, counter, len, link_len, nameidx;
- uint8_t *buffer, *orig;
- char *strp, *lpath;
-
- buffer = malloc(fs->nf_blocksize);
- orig = buffer;
-
- namebuf = malloc(2 * MAXPATHLEN + 2);
- strncpy(namebuf, path, MAXPATHLEN);
- namebuf[MAXPATHLEN] = '\0';
- done = nameidx = 0;
- lpath = namebuf;
-
- /* Get the root inode */
- node = nandfs_lookup_node(fs, NANDFS_ROOT_INO);
- inode = NANDFS_ROOT_INO;
-
- while ((strp = strsep(&lpath, "/")) != NULL) {
- if (*strp == '\0')
- continue;
- if ((node->inode->i_mode & IFMT) != IFDIR) {
- nandfs_free_node(node);
- node = NULL;
- goto out;
- }
-
- len = strlen(strp);
- NANDFS_DEBUG("%s: looking for %s\n", __func__, strp);
- for (i = 0; i < node->inode->i_blocks; i++) {
- if (nandfs_read_inode(fs, node, i, 1, orig, 0)) {
- node = NULL;
- goto out;
- }
-
- buffer = orig;
- done = counter = 0;
- while (1) {
- dirent =
- (struct nandfs_dir_entry *)(void *)buffer;
- NANDFS_DEBUG("%s: dirent.name = %s\n",
- __func__, dirent->name);
- NANDFS_DEBUG("%s: dirent.rec_len = %d\n",
- __func__, dirent->rec_len);
- NANDFS_DEBUG("%s: dirent.inode = %lld\n",
- __func__, dirent->inode);
- if (len == dirent->name_len &&
- (strncmp(strp, dirent->name, len) == 0) &&
- dirent->inode != 0) {
- nandfs_free_node(node);
- node = nandfs_lookup_node(fs,
- dirent->inode);
- pinode = inode;
- inode = dirent->inode;
- done = 1;
- break;
- }
-
- counter += dirent->rec_len;
- buffer += dirent->rec_len;
-
- if (counter == fs->nf_blocksize)
- break;
- }
-
- if (done)
- break;
- }
-
- if (!done) {
- node = NULL;
- goto out;
- }
-
- NANDFS_DEBUG("%s: %.*s has mode %o\n", __func__,
- dirent->name_len, dirent->name, node->inode->i_mode);
-
- if ((node->inode->i_mode & IFMT) == IFLNK) {
- NANDFS_DEBUG("%s: %.*s is symlink\n",
- __func__, dirent->name_len, dirent->name);
- link_len = node->inode->i_size;
-
- if (++nlinks > MAXSYMLINKS) {
- nandfs_free_node(node);
- node = NULL;
- goto out;
- }
-
- if (nandfs_read_inode(fs, node, 0, 1, orig, 0)) {
- nandfs_free_node(node);
- node = NULL;
- goto out;
- }
-
- NANDFS_DEBUG("%s: symlink is %.*s\n",
- __func__, link_len, (char *)orig);
-
- nameidx = (nameidx == 0) ? MAXPATHLEN + 1 : 0;
- bcopy((char *)orig, namebuf + nameidx,
- (unsigned)link_len);
- if (lpath != NULL) {
- namebuf[nameidx + link_len++] = '/';
- strncpy(namebuf + nameidx + link_len, lpath,
- MAXPATHLEN - link_len);
- namebuf[nameidx + MAXPATHLEN] = '\0';
- } else
- namebuf[nameidx + link_len] = '\0';
-
- NANDFS_DEBUG("%s: strp=%s, lpath=%s, namebuf0=%s, "
- "namebuf1=%s, idx=%d\n", __func__, strp, lpath,
- namebuf + 0, namebuf + MAXPATHLEN + 1, nameidx);
-
- lpath = namebuf + nameidx;
-
- nandfs_free_node(node);
-
- /*
- * If absolute pathname, restart at root. Otherwise
- * continue with out parent inode.
- */
- inode = (orig[0] == '/') ? NANDFS_ROOT_INO : pinode;
- node = nandfs_lookup_node(fs, inode);
- }
- }
-
-out:
- free(namebuf);
- free(orig);
- return (node);
-}
-
-static int
-nandfs_read_inode(struct nandfs *fs, struct nandfs_node *node,
- nandfs_daddr_t blknr, u_int nblks, void *buf, int raw)
-{
- uint64_t *pblks;
- uint64_t *vblks;
- u_int i;
- int error;
-
- pblks = malloc(nblks * sizeof(uint64_t));
- vblks = malloc(nblks * sizeof(uint64_t));
-
- NANDFS_DEBUG("nandfs_read_inode fs=%p node=%p blknr=%lld nblks=%d\n",
- fs, node, blknr, nblks);
- for (i = 0; i < nblks; i++) {
- error = nandfs_bmap_lookup(fs, node, blknr + i, &vblks[i], raw);
- if (error) {
- free(pblks);
- free(vblks);
- return (error);
- }
- if (raw == 0)
- pblks[i] = nandfs_vtop(fs, vblks[i]);
- else
- pblks[i] = vblks[i];
- }
-
- for (i = 0; i < nblks; i++) {
- if (ioread(fs->nf_file, pblks[i] * fs->nf_blocksize, buf,
- fs->nf_blocksize)) {
- free(pblks);
- free(vblks);
- return (EIO);
- }
-
- buf = (void *)((uintptr_t)buf + fs->nf_blocksize);
- }
-
- free(pblks);
- free(vblks);
- return (0);
-}
-
-static int
-nandfs_read_blk(struct nandfs *fs, nandfs_daddr_t blknr, void *buf, int phys)
-{
- uint64_t pblknr;
-
- pblknr = (phys ? blknr : nandfs_vtop(fs, blknr));
-
- return (ioread(fs->nf_file, pblknr * fs->nf_blocksize, buf,
- fs->nf_blocksize));
-}
-
-static int
-nandfs_get_checkpoint(struct nandfs *fs, uint64_t cpno,
- struct nandfs_checkpoint *cp)
-{
- uint64_t blocknr;
- int blockoff, cp_per_block, dlen;
- uint8_t *buf;
-
- NANDFS_DEBUG("nandfs_get_checkpoint(fs=%p cpno=%lld)\n", fs, cpno);
-
- buf = malloc(fs->nf_blocksize);
-
- cpno += NANDFS_CPFILE_FIRST_CHECKPOINT_OFFSET - 1;
- dlen = fs->nf_fsdata->f_checkpoint_size;
- cp_per_block = fs->nf_blocksize / dlen;
- blocknr = cpno / cp_per_block;
- blockoff = (cpno % cp_per_block) * dlen;
-
- if (nandfs_read_inode(fs, &fs->nf_cpfile, blocknr, 1, buf, 0)) {
- free(buf);
- return (EINVAL);
- }
-
- memcpy(cp, buf + blockoff, sizeof(struct nandfs_checkpoint));
- free(buf);
-
- return (0);
-}
-
-static uint64_t *
-nandfs_get_map(struct nandfs *fs, struct nandfs_node *node, nandfs_daddr_t blknr,
- int phys)
-{
- struct bmap_buf *bmap;
- uint64_t *map;
-
- LIST_FOREACH(bmap, &node->bmap_bufs, list) {
- if (bmap->blknr == blknr)
- return (bmap->map);
- }
-
- map = malloc(fs->nf_blocksize);
- if (nandfs_read_blk(fs, blknr, map, phys)) {
- free(map);
- return (NULL);
- }
-
- bmap = malloc(sizeof(struct bmap_buf));
- bmap->blknr = blknr;
- bmap->map = map;
-
- LIST_INSERT_HEAD(&node->bmap_bufs, bmap, list);
-
- NANDFS_DEBUG("%s:(node=%p, map=%p)\n", __func__, node, map);
- return (map);
-}
-
-static int
-nandfs_bmap_lookup(struct nandfs *fs, struct nandfs_node *node,
- nandfs_lbn_t lblknr, nandfs_daddr_t *vblknr, int phys)
-{
- struct nandfs_inode *ino;
- nandfs_daddr_t ind_block_num;
- uint64_t *map;
- int idx;
- int level;
-
- ino = node->inode;
-
- if (lblknr < NANDFS_NDADDR) {
- *vblknr = ino->i_db[lblknr];
- return (0);
- }
-
- lblknr -= NANDFS_NDADDR;
-
- /*
- * nindir[0] = NINDIR
- * nindir[1] = NINDIR**2
- * nindir[2] = NINDIR**3
- * etc
- */
- for (level = 0; level < NANDFS_NIADDR; level++) {
- NANDFS_DEBUG("lblknr=%jx fs->nf_nindir[%d]=%d\n", lblknr, level, fs->nf_nindir[level]);
- if (lblknr < fs->nf_nindir[level])
- break;
- lblknr -= fs->nf_nindir[level];
- }
-
- if (level == NANDFS_NIADDR) {
- /* Block number too high */
- NANDFS_DEBUG("lblknr %jx too high\n", lblknr);
- return (EFBIG);
- }
-
- ind_block_num = ino->i_ib[level];
-
- for (; level >= 0; level--) {
- if (ind_block_num == 0) {
- *vblknr = 0; /* missing */
- return (0);
- }
-
- twiddle(1);
- NANDFS_DEBUG("calling get_map with %jx\n", ind_block_num);
- map = nandfs_get_map(fs, node, ind_block_num, phys);
- if (map == NULL)
- return (EIO);
-
- if (level > 0) {
- idx = lblknr / fs->nf_nindir[level - 1];
- lblknr %= fs->nf_nindir[level - 1];
- } else
- idx = lblknr;
-
- ind_block_num = ((nandfs_daddr_t *)map)[idx];
- }
-
- *vblknr = ind_block_num;
-
- return (0);
-}
-
-static nandfs_daddr_t
-nandfs_vtop(struct nandfs *fs, nandfs_daddr_t vblocknr)
-{
- nandfs_lbn_t blocknr;
- nandfs_daddr_t pblocknr;
- int entrynr;
- struct nandfs_dat_entry *dat;
-
- dat = malloc(fs->nf_blocksize);
- nandfs_mdt_trans(&fs->nf_datfile_mdt, vblocknr, &blocknr, &entrynr);
-
- if (nandfs_read_inode(fs, &fs->nf_datfile, blocknr, 1, dat, 1)) {
- free(dat);
- return (0);
- }
-
- NANDFS_DEBUG("nandfs_vtop entrynr=%d vblocknr=%lld pblocknr=%lld\n",
- entrynr, vblocknr, dat[entrynr].de_blocknr);
-
- pblocknr = dat[entrynr].de_blocknr;
- free(dat);
- return (pblocknr);
-}
-
-static void
-nandfs_calc_mdt_consts(int blocksize, struct nandfs_mdt *mdt, int entry_size)
-{
-
- mdt->entries_per_group = blocksize * 8; /* bits in sector */
- mdt->entries_per_block = blocksize / entry_size;
- mdt->blocks_per_group =
- (mdt->entries_per_group -1) / mdt->entries_per_block + 1 + 1;
- mdt->groups_per_desc_block =
- blocksize / sizeof(struct nandfs_block_group_desc);
- mdt->blocks_per_desc_block =
- mdt->groups_per_desc_block * mdt->blocks_per_group + 1;
-}
-
-static void
-nandfs_mdt_trans(struct nandfs_mdt *mdt, uint64_t index,
- nandfs_daddr_t *blocknr, uint32_t *entry_in_block)
-{
- nandfs_daddr_t blknr;
- uint64_t group, group_offset, blocknr_in_group;
- uint64_t desc_block, desc_offset;
-
- /* Calculate our offset in the file */
- group = index / mdt->entries_per_group;
- group_offset = index % mdt->entries_per_group;
- desc_block = group / mdt->groups_per_desc_block;
- desc_offset = group % mdt->groups_per_desc_block;
- blocknr_in_group = group_offset / mdt->entries_per_block;
-
- /* To descgroup offset */
- blknr = 1 + desc_block * mdt->blocks_per_desc_block;
-
- /* To group offset */
- blknr += desc_offset * mdt->blocks_per_group;
-
- /* To actual file block */
- blknr += 1 + blocknr_in_group;
-
- *blocknr = blknr;
- *entry_in_block = group_offset % mdt->entries_per_block;
-}
-
-static int
-ioread(struct open_file *f, off_t pos, void *buf, u_int length)
-{
- void *buffer;
- int err;
- int bsize = ((struct nandfs *)f->f_fsdata)->nf_sectorsize;
- u_int off, nsec;
-
- off = pos % bsize;
- pos /= bsize;
- nsec = howmany(length, bsize);
-
- NANDFS_DEBUG("pos=%lld length=%d off=%d nsec=%d\n", pos, length,
- off, nsec);
-
- buffer = malloc(nsec * bsize);
-
- err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, pos,
- nsec * bsize, buffer, NULL);
-
- memcpy(buf, (void *)((uintptr_t)buffer + off), length);
- free(buffer);
-
- return (err);
-}
-
-static int
-nandfs_probe_sectorsize(struct open_file *f)
-{
- void *buffer;
- int i, err;
-
- buffer = malloc(16 * 1024);
-
- NANDFS_DEBUG("probing for sector size: ");
-
- for (i = 512; i < (16 * 1024); i <<= 1) {
- NANDFS_DEBUG("%d ", i);
- err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 0, i,
- buffer, NULL);
-
- if (err == 0) {
- NANDFS_DEBUG("found");
- free(buffer);
- return (i);
- }
- }
-
- free(buffer);
- NANDFS_DEBUG("not found\n");
- return (-1);
-}
diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h
index 5e44e31ff2d9..3d0cb4ff0c50 100644
--- a/stand/libsa/stand.h
+++ b/stand/libsa/stand.h
@@ -119,13 +119,13 @@ extern struct fs_ops ufs_fsops;
extern struct fs_ops tftp_fsops;
extern struct fs_ops nfs_fsops;
extern struct fs_ops cd9660_fsops;
-extern struct fs_ops nandfs_fsops;
extern struct fs_ops gzipfs_fsops;
extern struct fs_ops bzipfs_fsops;
extern struct fs_ops dosfs_fsops;
extern struct fs_ops ext2fs_fsops;
extern struct fs_ops splitfs_fsops;
extern struct fs_ops pkgfs_fsops;
+extern struct fs_ops efihttp_fsops;
/* where values for lseek(2) */
#define SEEK_SET 0 /* set file offset to offset */
diff --git a/stand/loader.mk b/stand/loader.mk
index bd24f33bc6b1..a7fbd6c12dd9 100644
--- a/stand/loader.mk
+++ b/stand/loader.mk
@@ -99,9 +99,6 @@ CFLAGS+= -DLOADER_EXT2FS_SUPPORT
.if ${LOADER_MSDOS_SUPPORT:Uno} == "yes"
CFLAGS+= -DLOADER_MSDOS_SUPPORT
.endif
-.if ${LOADER_NANDFS_SUPPORT:U${MK_NAND}} == "yes"
-CFLAGS+= -DLOADER_NANDFS_SUPPORT
-.endif
.if ${LOADER_UFS_SUPPORT:Uyes} == "yes"
CFLAGS+= -DLOADER_UFS_SUPPORT
.endif
diff --git a/stand/mips/uboot/conf.c b/stand/mips/uboot/conf.c
index f711a8cec5f2..922f7680b616 100644
--- a/stand/mips/uboot/conf.c
+++ b/stand/mips/uboot/conf.c
@@ -62,9 +62,6 @@ struct fs_ops *file_system[] = {
#if defined(LOADER_EXT2FS_SUPPORT)
&ext2fs_fsops,
#endif
-#if defined(LOADER_NANDFS_SUPPORT)
- &nandfs_fsops,
-#endif
#if defined(LOADER_NFS_SUPPORT)
&nfs_fsops,
#endif
diff --git a/stand/mips/uboot/version b/stand/mips/uboot/version
index 486c4125cc0d..ec46b388b281 100644
--- a/stand/mips/uboot/version
+++ b/stand/mips/uboot/version
@@ -3,6 +3,7 @@ $FreeBSD$
NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this
file is important. Make sure the current version number is on line 6.
+1.3: Remove NAND FS support.
1.2: Extended with NAND FS support.
1.1: Flattened Device Tree blob support.
1.0: Added storage support. Booting from HDD, USB, etc. is now possible.
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index d7a35b5c9cfc..a0a2eb0baa6b 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -484,6 +484,9 @@ static struct pmap_invl_gen pmap_invl_gen_head = {
.next = NULL,
};
static u_long pmap_invl_gen = 1;
+static int pmap_invl_waiters;
+static struct callout pmap_invl_callout;
+static bool pmap_invl_callout_inited;
#define PMAP_ASSERT_NOT_IN_DI() \
KASSERT(pmap_not_in_di(), ("DI already started"))
@@ -538,6 +541,34 @@ pmap_thread_init_invl_gen_l(struct thread *td)
invl_gen->gen = 0;
}
+static void
+pmap_delayed_invl_wait_block(u_long *m_gen, u_long *invl_gen)
+{
+ struct turnstile *ts;
+
+ ts = turnstile_trywait(&invl_gen_ts);
+ if (*m_gen > atomic_load_long(invl_gen))
+ turnstile_wait(ts, NULL, TS_SHARED_QUEUE);
+ else
+ turnstile_cancel(ts);
+}
+
+static void
+pmap_delayed_invl_finish_unblock(u_long new_gen)
+{
+ struct turnstile *ts;
+
+ turnstile_chain_lock(&invl_gen_ts);
+ ts = turnstile_lookup(&invl_gen_ts);
+ if (new_gen != 0)
+ pmap_invl_gen = new_gen;
+ if (ts != NULL) {
+ turnstile_broadcast(ts, TS_SHARED_QUEUE);
+ turnstile_unpend(ts);
+ }
+ turnstile_chain_unlock(&invl_gen_ts);
+}
+
/*
* Start a new Delayed Invalidation (DI) block of code, executed by
* the current thread. Within a DI block, the current thread may
@@ -582,24 +613,15 @@ static void
pmap_delayed_invl_finish_l(void)
{
struct pmap_invl_gen *invl_gen, *next;
- struct turnstile *ts;
invl_gen = &curthread->td_md.md_invl_gen;
KASSERT(invl_gen->gen != 0, ("missed invl_start"));
mtx_lock(&invl_gen_mtx);
next = LIST_NEXT(invl_gen, link);
- if (next == NULL) {
- turnstile_chain_lock(&invl_gen_ts);
- ts = turnstile_lookup(&invl_gen_ts);
- pmap_invl_gen = invl_gen->gen;
- if (ts != NULL) {
- turnstile_broadcast(ts, TS_SHARED_QUEUE);
- turnstile_unpend(ts);
- }
- turnstile_chain_unlock(&invl_gen_ts);
- } else {
+ if (next == NULL)
+ pmap_delayed_invl_finish_unblock(invl_gen->gen);
+ else
next->gen = invl_gen->gen;
- }
LIST_REMOVE(invl_gen, link);
mtx_unlock(&invl_gen_mtx);
invl_gen->gen = 0;
@@ -856,6 +878,8 @@ again:
goto again;
}
critical_exit();
+ if (atomic_load_int(&pmap_invl_waiters) > 0)
+ pmap_delayed_invl_finish_unblock(0);
if (invl_gen->saved_pri != 0) {
thread_lock(td);
sched_prio(td, invl_gen->saved_pri);
@@ -888,6 +912,9 @@ DB_SHOW_COMMAND(di_queue, pmap_di_queue)
static long invl_wait;
SYSCTL_LONG(_vm_pmap, OID_AUTO, invl_wait, CTLFLAG_RD, &invl_wait, 0,
"Number of times DI invalidation blocked pmap_remove_all/write");
+static long invl_wait_slow;
+SYSCTL_LONG(_vm_pmap, OID_AUTO, invl_wait_slow, CTLFLAG_RD, &invl_wait_slow, 0,
+ "Number of slow invalidation waits for lockless DI");
#endif
static u_long *
@@ -897,6 +924,27 @@ pmap_delayed_invl_genp(vm_page_t m)
return (&pv_invl_gen[pa_index(VM_PAGE_TO_PHYS(m)) % NPV_LIST_LOCKS]);
}
+static void
+pmap_delayed_invl_callout_func(void *arg __unused)
+{
+
+ if (atomic_load_int(&pmap_invl_waiters) == 0)
+ return;
+ pmap_delayed_invl_finish_unblock(0);
+}
+
+static void
+pmap_delayed_invl_callout_init(void *arg __unused)
+{
+
+ if (pmap_di_locked())
+ return;
+ callout_init(&pmap_invl_callout, 1);
+ pmap_invl_callout_inited = true;
+}
+SYSINIT(pmap_di_callout, SI_SUB_CPU + 1, SI_ORDER_ANY,
+ pmap_delayed_invl_callout_init, NULL);
+
/*
* Ensure that all currently executing DI blocks, that need to flush
* TLB for the given page m, actually flushed the TLB at the time the
@@ -914,7 +962,6 @@ pmap_delayed_invl_genp(vm_page_t m)
static void
pmap_delayed_invl_wait_l(vm_page_t m)
{
- struct turnstile *ts;
u_long *m_gen;
#ifdef PV_STATS
bool accounted = false;
@@ -928,11 +975,7 @@ pmap_delayed_invl_wait_l(vm_page_t m)
accounted = true;
}
#endif
- ts = turnstile_trywait(&invl_gen_ts);
- if (*m_gen > pmap_invl_gen)
- turnstile_wait(ts, NULL, TS_SHARED_QUEUE);
- else
- turnstile_cancel(ts);
+ pmap_delayed_invl_wait_block(m_gen, &pmap_invl_gen);
}
}
@@ -940,19 +983,53 @@ static void
pmap_delayed_invl_wait_u(vm_page_t m)
{
u_long *m_gen;
-#ifdef PV_STATS
- bool accounted = false;
-#endif
+ struct lock_delay_arg lda;
+ bool fast;
+ fast = true;
m_gen = pmap_delayed_invl_genp(m);
+ lock_delay_arg_init(&lda, &di_delay);
while (*m_gen > atomic_load_long(&pmap_invl_gen_head.gen)) {
-#ifdef PV_STATS
- if (!accounted) {
- atomic_add_long(&invl_wait, 1);
- accounted = true;
+ if (fast || !pmap_invl_callout_inited) {
+ PV_STAT(atomic_add_long(&invl_wait, 1));
+ lock_delay(&lda);
+ fast = false;
+ } else {
+ /*
+ * The page's invalidation generation number
+ * is still below the current thread's number.
+ * Prepare to block so that we do not waste
+ * CPU cycles or worse, suffer livelock.
+ *
+ * Since it is impossible to block without
+ * racing with pmap_delayed_invl_finish_u(),
+ * prepare for the race by incrementing
+ * pmap_invl_waiters and arming a 1-tick
+ * callout which will unblock us if we lose
+ * the race.
+ */
+ atomic_add_int(&pmap_invl_waiters, 1);
+
+ /*
+ * Re-check the current thread's invalidation
+ * generation after incrementing
+ * pmap_invl_waiters, so that there is no race
+ * with pmap_delayed_invl_finish_u() setting
+ * the page generation and checking
+ * pmap_invl_waiters. The only race allowed
+ * is for a missed unblock, which is handled
+ * by the callout.
+ */
+ if (*m_gen >
+ atomic_load_long(&pmap_invl_gen_head.gen)) {
+ callout_reset(&pmap_invl_callout, 1,
+ pmap_delayed_invl_callout_func, NULL);
+ PV_STAT(atomic_add_long(&invl_wait_slow, 1));
+ pmap_delayed_invl_wait_block(m_gen,
+ &pmap_invl_gen_head.gen);
+ }
+ atomic_add_int(&pmap_invl_waiters, -1);
}
-#endif
- kern_yield(PRI_USER);
}
}
@@ -4921,6 +4998,7 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
pmap_delayed_invl_start();
PMAP_LOCK(pmap);
+ pmap_pkru_on_remove(pmap, sva, eva);
/*
* special handling of removing one page. a very
@@ -5014,7 +5092,6 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
out:
if (anyvalid)
pmap_invalidate_all(pmap);
- pmap_pkru_on_remove(pmap, sva, eva);
PMAP_UNLOCK(pmap);
pmap_delayed_invl_finish();
vm_page_free_pages_toq(&free, true);
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 520f64734bb9..f04b60f3ca66 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -309,7 +309,6 @@ device wpi # Intel 3945ABG wireless NICs.
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device padlock_rng # VIA Padlock RNG
device rdrand_rng # Intel Bull Mountain RNG
device ether # Ethernet support
diff --git a/sys/amd64/conf/MINIMAL b/sys/amd64/conf/MINIMAL
index 481a7ce96e44..211e00e7de46 100644
--- a/sys/amd64/conf/MINIMAL
+++ b/sys/amd64/conf/MINIMAL
@@ -10,7 +10,7 @@
# some features (ACL, GJOURNAL) that GENERIC includes.
# o acpi as a module has been reported flakey and not well tested, so
# is included in the kernel.
-# o random is included due to uncertaty...
+# o (non-loaded) random is included due to uncertainty...
# o Many networking things are included
#
# For now, please run changes to these list past imp@freebsd.org
@@ -131,7 +131,6 @@ device agp # support several AGP chipsets
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device padlock_rng # VIA Padlock RNG
device rdrand_rng # Intel Bull Mountain RNG
device ether # Ethernet support
diff --git a/sys/amd64/sgx/sgx.c b/sys/amd64/sgx/sgx.c
index d47d4a3596a5..3d45b60de3ef 100644
--- a/sys/amd64/sgx/sgx.c
+++ b/sys/amd64/sgx/sgx.c
@@ -358,7 +358,7 @@ sgx_page_remove(struct sgx_softc *sc, vm_page_t p)
uint64_t offs;
vm_page_lock(p);
- vm_page_remove(p);
+ (void)vm_page_remove(p);
vm_page_unlock(p);
dprintf("%s: p->pidx %ld\n", __func__, p->pindex);
diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c
index 230da1881ef0..f3afa23d8281 100644
--- a/sys/amd64/vmm/vmm_instruction_emul.c
+++ b/sys/amd64/vmm/vmm_instruction_emul.c
@@ -78,6 +78,7 @@ enum {
VIE_OP_TYPE_BITTEST,
VIE_OP_TYPE_TWOB_GRP15,
VIE_OP_TYPE_ADD,
+ VIE_OP_TYPE_TEST,
VIE_OP_TYPE_LAST
};
@@ -221,6 +222,12 @@ static const struct vie_op one_byte_opcodes[256] = {
.op_byte = 0x8F,
.op_type = VIE_OP_TYPE_POP,
},
+ [0xF7] = {
+ /* XXX Group 3 extended opcode - not just TEST */
+ .op_byte = 0xF7,
+ .op_type = VIE_OP_TYPE_TEST,
+ .op_flags = VIE_OP_F_IMM,
+ },
[0xFF] = {
/* XXX Group 5 extended opcode - not just PUSH */
.op_byte = 0xFF,
@@ -450,6 +457,41 @@ getaddflags(int opsize, uint64_t x, uint64_t y)
return (getaddflags64(x, y));
}
+/*
+ * Return the status flags that would result from doing (x & y).
+ */
+#define GETANDFLAGS(sz) \
+static u_long \
+getandflags##sz(uint##sz##_t x, uint##sz##_t y) \
+{ \
+ u_long rflags; \
+ \
+ __asm __volatile("and %2,%1; pushfq; popq %0" : \
+ "=r" (rflags), "+r" (x) : "m" (y)); \
+ return (rflags); \
+} struct __hack
+
+GETANDFLAGS(8);
+GETANDFLAGS(16);
+GETANDFLAGS(32);
+GETANDFLAGS(64);
+
+static u_long
+getandflags(int opsize, uint64_t x, uint64_t y)
+{
+ KASSERT(opsize == 1 || opsize == 2 || opsize == 4 || opsize == 8,
+ ("getandflags: invalid operand size %d", opsize));
+
+ if (opsize == 1)
+ return (getandflags8(x, y));
+ else if (opsize == 2)
+ return (getandflags16(x, y));
+ else if (opsize == 4)
+ return (getandflags32(x, y));
+ else
+ return (getandflags64(x, y));
+}
+
static int
emulate_mov(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
@@ -1219,6 +1261,55 @@ emulate_cmp(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
}
static int
+emulate_test(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
+{
+ int error, size;
+ uint64_t op1, rflags, rflags2;
+
+ size = vie->opsize;
+ error = EINVAL;
+
+ switch (vie->op.op_byte) {
+ case 0xF7:
+ /*
+ * F7 /0 test r/m16, imm16
+ * F7 /0 test r/m32, imm32
+ * REX.W + F7 /0 test r/m64, imm32 sign-extended to 64
+ *
+ * Test mem (ModRM:r/m) with immediate and set status
+ * flags according to the results. The comparison is
+ * performed by anding the immediate from the first
+ * operand and then setting the status flags.
+ */
+ if ((vie->reg & 7) != 0)
+ return (EINVAL);
+
+ error = memread(vm, vcpuid, gpa, &op1, size, arg);
+ if (error)
+ return (error);
+
+ rflags2 = getandflags(size, op1, vie->immediate);
+ break;
+ default:
+ return (EINVAL);
+ }
+ error = vie_read_register(vm, vcpuid, VM_REG_GUEST_RFLAGS, &rflags);
+ if (error)
+ return (error);
+
+ /*
+ * OF and CF are cleared; the SF, ZF and PF flags are set according
+ * to the result; AF is undefined.
+ */
+ rflags &= ~RFLAGS_STATUS_BITS;
+ rflags |= rflags2 & (PSL_PF | PSL_Z | PSL_N);
+
+ error = vie_update_register(vm, vcpuid, VM_REG_GUEST_RFLAGS, rflags, 8);
+ return (error);
+}
+
+static int
emulate_add(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
{
@@ -1643,6 +1734,10 @@ vmm_emulate_instruction(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
error = emulate_add(vm, vcpuid, gpa, vie, memread,
memwrite, memarg);
break;
+ case VIE_OP_TYPE_TEST:
+ error = emulate_test(vm, vcpuid, gpa, vie,
+ memread, memwrite, memarg);
+ break;
default:
error = EINVAL;
break;
diff --git a/sys/arm/allwinner/files.allwinner b/sys/arm/allwinner/files.allwinner
index 73367b391c3a..dd801c016d49 100644
--- a/sys/arm/allwinner/files.allwinner
+++ b/sys/arm/allwinner/files.allwinner
@@ -28,7 +28,6 @@ dev/usb/controller/generic_ohci.c optional ohci
dev/usb/controller/generic_usb_if.m optional ohci
arm/allwinner/aw_sid.c optional aw_sid
arm/allwinner/aw_thermal.c optional aw_thermal
-dev/iicbus/sy8106a.c optional sy8106a
arm/allwinner/aw_cir.c optional aw_cir evdev
arm/allwinner/aw_reset.c standard
diff --git a/sys/arm/conf/ALPINE b/sys/arm/conf/ALPINE
index 6b35f120aefb..76689b5805c9 100644
--- a/sys/arm/conf/ALPINE
+++ b/sys/arm/conf/ALPINE
@@ -41,7 +41,6 @@ device al_udma # Universal DMA
# Pseudo devices
device loop
-device random
device pty
device md
device gpio
diff --git a/sys/arm/conf/ARMADA38X b/sys/arm/conf/ARMADA38X
index 29ea724172be..b82c18d79c52 100644
--- a/sys/arm/conf/ARMADA38X
+++ b/sys/arm/conf/ARMADA38X
@@ -25,7 +25,6 @@ options SMP
options VM_KMEM_SIZE_MAX=0x9CCD000
# Pseudo devices
-device random
device pty
device loop
device md
diff --git a/sys/arm/conf/ARMADAXP b/sys/arm/conf/ARMADAXP
index 5e891e51fba7..7f73d69ece7a 100644
--- a/sys/arm/conf/ARMADAXP
+++ b/sys/arm/conf/ARMADAXP
@@ -46,7 +46,6 @@ options NO_FFS_SNAPSHOT
options NO_SWAPPING
# Pseudo devices
-device random
device pty
device loop
device md
diff --git a/sys/arm/conf/DB-78XXX b/sys/arm/conf/DB-78XXX
index aa474bcc43a1..44df77cf45f1 100644
--- a/sys/arm/conf/DB-78XXX
+++ b/sys/arm/conf/DB-78XXX
@@ -20,7 +20,6 @@ options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
options TMPFS # Efficient memory filesystem
options FFS # Berkeley Fast Filesystem
-options NANDFS # NAND Filesystem
options NFSCL # Network Filesystem Client
options NFSLOCKD # Network Lock Manager
options NFS_ROOT # NFS usable as /, requires NFSCL
@@ -45,7 +44,6 @@ device pci
# Pseudo devices
device loop
device md
-device random
# Serial ports
device uart
@@ -75,9 +73,6 @@ device ds133x
# SATA
device mvs
-# NAND
-device nand
-
# GPIO
device gpio
diff --git a/sys/arm/conf/DB-88F5XXX b/sys/arm/conf/DB-88F5XXX
index 0199e8663336..a13a7002332d 100644
--- a/sys/arm/conf/DB-88F5XXX
+++ b/sys/arm/conf/DB-88F5XXX
@@ -44,7 +44,6 @@ device pci
# Pseudo devices
device md
device loop
-device random
# Serial ports
device uart
diff --git a/sys/arm/conf/DB-88F6XXX b/sys/arm/conf/DB-88F6XXX
index fa2810c97122..66a385ddbe40 100644
--- a/sys/arm/conf/DB-88F6XXX
+++ b/sys/arm/conf/DB-88F6XXX
@@ -17,7 +17,6 @@ options INET # InterNETworking
options INET6 # IPv6 communications protocols
options TCP_HHOOK # hhook(9) framework for TCP
options FFS # Berkeley Fast Filesystem
-options NANDFS # NAND Filesystem
options NFSCL # Network Filesystem Client
options NFSLOCKD # Network Lock Manager
options NFS_ROOT # NFS usable as /, requires NFSCL
@@ -46,7 +45,6 @@ device pci
# Pseudo devices
device loop
device md
-device random
# Serial ports
device uart
@@ -79,9 +77,6 @@ device twsi
# SATA
device mvs
-# NAND
-device nand
-
# GPIO
device gpio
diff --git a/sys/arm/conf/DOCKSTAR b/sys/arm/conf/DOCKSTAR
index 5684d29ef87b..6f26d4290801 100644
--- a/sys/arm/conf/DOCKSTAR
+++ b/sys/arm/conf/DOCKSTAR
@@ -68,7 +68,6 @@ device gif # IPv6 and IPv4 tunneling
device loop # Network loopback
device md # Memory/malloc disk
device pty # BSD-style compatibility pseudo ttys
-device random # Entropy device
device tuntap # Packet tunnel.
device ether # Required for all ethernet devices
device vlan # 802.1Q VLAN support
diff --git a/sys/arm/conf/DREAMPLUG-1001 b/sys/arm/conf/DREAMPLUG-1001
index 5d6928470e5d..18b2dee86fac 100644
--- a/sys/arm/conf/DREAMPLUG-1001
+++ b/sys/arm/conf/DREAMPLUG-1001
@@ -71,7 +71,6 @@ device gif # IPv6 and IPv4 tunneling
device loop # Network loopback
device md # Memory/malloc disk
device pty # BSD-style compatibility pseudo ttys
-device random # Entropy device
device tuntap # Packet tunnel.
device ether # Required for all ethernet devices
device vlan # 802.1Q VLAN support
@@ -158,14 +157,6 @@ options ALTQ_PRIQ # Priority Queueing
options ALTQ_NOPCC # Required if the TSC is unusable
#options ALTQ_DEBUG
-# To use this configuration with the (rare) model 1001N (nand flash),
-# create a kernel config file that looks like this:
-#
-# include DREAMPLUG-1001
-# nomakeoptions FDT_DTS_FILE
-# makeoptions FDT_DTS_FILE=dreamplug-1001N.dts
-# device nand
-
# Flattened Device Tree
options FDT # Configure using FDT/DTB data
options FDT_DTB_STATIC
diff --git a/sys/arm/conf/EFIKA_MX b/sys/arm/conf/EFIKA_MX
index 248060b6cf04..be5f5f35570d 100644
--- a/sys/arm/conf/EFIKA_MX
+++ b/sys/arm/conf/EFIKA_MX
@@ -57,7 +57,6 @@ device bpf # Berkeley packet filter
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
#device vlan # 802.1Q VLAN support
#device tuntap # Packet tunnel.
diff --git a/sys/arm/conf/GENERIC b/sys/arm/conf/GENERIC
index d32baa63a667..34be5898c7eb 100644
--- a/sys/arm/conf/GENERIC
+++ b/sys/arm/conf/GENERIC
@@ -121,7 +121,6 @@ device pl011
device pty
device snp
device md # Memory "disks"
-device random # Entropy device
device firmware # firmware assist module
device pl310 # PL310 L2 cache controller
device psci
@@ -175,6 +174,9 @@ device ti_spi
# ADC support
device ti_adc
+# PWM
+device pwm
+
# Watchdog support
# If we don't enable the watchdog driver, the BealeBone could potentially
# reboot automatically because the boot loader might have enabled the
diff --git a/sys/arm/conf/IMX53 b/sys/arm/conf/IMX53
index 7b7d67bbca9c..be18afda6094 100644
--- a/sys/arm/conf/IMX53
+++ b/sys/arm/conf/IMX53
@@ -44,7 +44,6 @@ device bpf # Berkeley packet filter
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
#device vlan # 802.1Q VLAN support
#device tuntap # Packet tunnel.
diff --git a/sys/arm/conf/IMX6 b/sys/arm/conf/IMX6
index 3baf9f06f039..4dbebdfccd1f 100644
--- a/sys/arm/conf/IMX6
+++ b/sys/arm/conf/IMX6
@@ -49,7 +49,6 @@ device mpcore_timer
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
device md # Memory "disks"
diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES
index 559146b58014..518cf4050ad9 100644
--- a/sys/arm/conf/NOTES
+++ b/sys/arm/conf/NOTES
@@ -1,44 +1,22 @@
# $FreeBSD$
-machine arm
-
-cpu CPU_ARM9E
-
-files "../mv/files.mv"
-files "../mv/discovery/files.db78xxx"
-files "../mv/kirkwood/files.kirkwood"
-files "../mv/orion/files.db88f5xxx"
-files "../mv/orion/files.ts7800"
-
-makeoptions CONF_CFLAGS+="-march=armv5te"
-makeoptions LDFLAGS="-zmuldefs"
-makeoptions KERNPHYSADDR=0x00000000
-
options FDT
-options SOC_MV_DISCOVERY
-options SOC_MV_KIRKWOOD
-options SOC_MV_ORION
-
-options ARM_MANY_BOARD
-device nand
-
-# IIC
-device twsi
-
-nooptions SMP
-nooptions MAXCPU
+# Undo options from sys/conf/NOTES that we do not want...
nooptions COMPAT_FREEBSD4
nooptions COMPAT_FREEBSD5
nooptions COMPAT_FREEBSD6
nooptions COMPAT_FREEBSD7
nooptions COMPAT_FREEBSD9
-nooption PPC_PROBE_CHIPSET
+nooptions PPC_PROBE_CHIPSET
+nooptions MAXCPU # value is set in machine/param.h
+
+# Devices in sys/conf/NOTES for which no such hardware exists on arm,
+# or the drivers don't compile...
nodevice fdc
nodevice sym
-nodevice ukbd
nodevice sc
nodevice blank_saver
@@ -58,28 +36,9 @@ nodevice cxgbe
nodevice cxgbev
nodevice snd_cmi
-#
-# Enable the kernel DTrace hooks which are required to load the DTrace
-# kernel modules.
-#
-options KDTRACE_HOOKS
-
-# DTrace core
-# NOTE: introduces CDDL-licensed components into the kernel
-#device dtrace
-
-# DTrace modules
-#device dtrace_profile
-#device dtrace_sdt
-#device dtrace_fbt
-#device dtrace_systrace
-#device dtrace_prototype
-#device dtnfscl
-#device dtmalloc
-
-# Alternatively include all the DTrace modules
-#device dtraceall
-
-# These aren't known to work on arm and/or don't compile
nodevice mpr
nodevice mps
+
+# Add devices which are specific to various arm platforms...
+
+device twsi # i2c controller on Marvel and Allwinner
diff --git a/sys/arm/conf/NOTES.armv5 b/sys/arm/conf/NOTES.armv5
new file mode 100644
index 000000000000..1e8825980448
--- /dev/null
+++ b/sys/arm/conf/NOTES.armv5
@@ -0,0 +1,33 @@
+# armv5-specific changes for doing a LINT build.
+#
+# The contents of sys/conf/NOTES, sys/arm/conf/NOTES, and this file are
+# concatenated (in that order) to create the LINT-V5 kernel config file.
+#
+# $FreeBSD$
+
+#NO_UNIVERSE
+
+machine arm arm
+cpu CPU_ARM9E
+
+files "../mv/files.mv"
+files "../mv/discovery/files.db78xxx"
+files "../mv/kirkwood/files.kirkwood"
+files "../mv/orion/files.db88f5xxx"
+files "../mv/orion/files.ts7800"
+
+makeoptions CONF_CFLAGS+="-march=armv5te"
+makeoptions LDFLAGS="-zmuldefs"
+makeoptions KERNPHYSADDR=0x00000000
+
+# Undo options from sys/conf/NOTES that we do not want...
+
+nooptions SMP # All armv5 are single-core
+
+# Add options for armv5 that are not in sys/conf/NOTES...
+
+options ARM_MANY_BOARD
+
+options SOC_MV_DISCOVERY
+options SOC_MV_KIRKWOOD
+options SOC_MV_ORION
diff --git a/sys/arm/conf/NOTES.armv7 b/sys/arm/conf/NOTES.armv7
new file mode 100644
index 000000000000..e8a19034b001
--- /dev/null
+++ b/sys/arm/conf/NOTES.armv7
@@ -0,0 +1,64 @@
+# armv7-specific changes for doing a LINT build.
+#
+# The contents of sys/conf/NOTES, sys/arm/conf/NOTES, and this file are
+# concatenated (in that order) to create the LINT-V7 kernel config file.
+#
+# $FreeBSD$
+
+
+#NO_UNIVERSE
+
+machine arm armv7
+cpu CPU_CORTEXA
+cpu CPU_MV_PJ4B
+makeoptions CONF_CFLAGS+="-march=armv7a"
+
+# Add options for armv7 that are not in sys/conf/NOTES...
+
+options ARM_L2_PIPT # Only L2 PIPT is supported
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options INTRNG # Include INTRNG framework
+options LINUX_BOOT_ABI # Process metadata passed from U-Boot
+options PLATFORM # Include platform_if support
+options SMP # Most v7 SoCs are multicore
+options VFP # Enable floating point hardware support
+
+# NOTE: dtrace introduces CDDL-licensed components into the kernel
+device dtrace # dtrace core
+device dtraceall # include all dtrace modules
+options KDTRACE_HOOKS
+
+# Add misc devices which are specific to various arm platforms...
+
+device generic_timer # ARM Generic Timer
+device gic # Interrupt controller
+device gpio # gpio interface and bus
+device mpcore_timer # ARM MPCore Timer
+device pl310 # PL310 L2 cache controller
+device pmu # PMU support (for CCNT).
+
+# Add EXT_RESOURCES pseudo devices...
+
+options EXT_RESOURCES
+device clk
+device phy
+device hwreset
+device nvmem
+device regulator
+device syscon
+
+# Build SOC-specific modules...
+
+makeoptions MODULES_EXTRA+="allwinner"
+makeoptions MODULES_EXTRA+="arm_ti"
+makeoptions MODULES_EXTRA+="imx"
+
+# Build dtb files...
+
+makeoptions MODULES_EXTRA+="dtb/allwinner"
+makeoptions MODULES_EXTRA+="dtb/am335x"
+makeoptions MODULES_EXTRA+="dtb/imx6"
+makeoptions MODULES_EXTRA+="dtb/nvidia"
+makeoptions MODULES_EXTRA+="dtb/omap4"
+makeoptions MODULES_EXTRA+="dtb/rpi"
+makeoptions MODULES_EXTRA+="dtb/zynq"
diff --git a/sys/arm/conf/RPI-B b/sys/arm/conf/RPI-B
index e1f132105c20..e456d33742b8 100644
--- a/sys/arm/conf/RPI-B
+++ b/sys/arm/conf/RPI-B
@@ -65,7 +65,6 @@ device iicbus
device bcm2835_bsc
device md
-device random # Entropy device
# USB support
device usb
diff --git a/sys/arm/conf/RT1310 b/sys/arm/conf/RT1310
index 3ade997821be..08fde3516ac1 100644
--- a/sys/arm/conf/RT1310
+++ b/sys/arm/conf/RT1310
@@ -51,7 +51,6 @@ options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
device loop
device md
device pty
-device random
# Serial ports
device uart
diff --git a/sys/arm/conf/SHEEVAPLUG b/sys/arm/conf/SHEEVAPLUG
index ff60f82bcf60..d7d161956ce4 100644
--- a/sys/arm/conf/SHEEVAPLUG
+++ b/sys/arm/conf/SHEEVAPLUG
@@ -19,7 +19,6 @@ options INET # InterNETworking
options INET6 # IPv6 communications protocols
options TCP_HHOOK # hhook(9) framework for TCP
options FFS # Berkeley Fast Filesystem
-options NANDFS # NAND Filesystem
options NFSCL # Network Filesystem Client
options NFSLOCKD # Network Lock Manager
options NFS_ROOT # NFS usable as /, requires NFSCL
@@ -46,7 +45,6 @@ options BOOTP_WIRED_TO=mge0
# Pseudo devices
device loop
-device random
# Serial ports
device uart
@@ -73,9 +71,6 @@ device scbus
device pass
device da
-# NAND
-device nand
-
# GPIO
device gpio
diff --git a/sys/arm/conf/SOCFPGA b/sys/arm/conf/SOCFPGA
index b740ef1b84c9..cd78e17e08a4 100644
--- a/sys/arm/conf/SOCFPGA
+++ b/sys/arm/conf/SOCFPGA
@@ -58,7 +58,6 @@ device dwmmc
# Pseudo devices
device loop
-device random
device pty
device md
device gpio
diff --git a/sys/arm/conf/TEGRA124 b/sys/arm/conf/TEGRA124
index a830519d909e..c44939b67301 100644
--- a/sys/arm/conf/TEGRA124
+++ b/sys/arm/conf/TEGRA124
@@ -43,7 +43,6 @@ device regulator
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device vlan # 802.1Q VLAN support
#device tuntap # Packet tunnel.
device md # Memory "disks"
diff --git a/sys/arm/conf/TS7800 b/sys/arm/conf/TS7800
index 17b237af46dd..15e9a77342d5 100644
--- a/sys/arm/conf/TS7800
+++ b/sys/arm/conf/TS7800
@@ -45,7 +45,6 @@ device pci
# Pseudo devices
device md
device loop
-device random
# Serial ports
device uart
diff --git a/sys/arm/conf/VERSATILEPB b/sys/arm/conf/VERSATILEPB
index 8c3e76cc2e87..3312f6d4f9e8 100644
--- a/sys/arm/conf/VERSATILEPB
+++ b/sys/arm/conf/VERSATILEPB
@@ -66,7 +66,6 @@ options SC_DFLT_FONT # compile font in
makeoptions SC_DFLT_FONT=cp437
device md
-device random # Entropy device
options PLATFORM
diff --git a/sys/arm/conf/VYBRID b/sys/arm/conf/VYBRID
index 4ff18320df1a..b114c6e3e923 100644
--- a/sys/arm/conf/VYBRID
+++ b/sys/arm/conf/VYBRID
@@ -26,7 +26,6 @@ makeoptions WERROR="-Werror"
options SCHED_4BSD # 4BSD scheduler
options PLATFORM # Platform based SoC
-#options NANDFS # NAND Filesystem
#options SMP # Enable multiple cores
# NFS root from boopt/dhcp
@@ -37,7 +36,6 @@ options PLATFORM # Platform based SoC
#options BOOTP_WIRED_TO=ffec0
#options ROOTDEVNAME=\"nfs:10.5.0.1:/tftpboot/cosmic\"
-#options ROOTDEVNAME=\"nandfs:/dev/gnand0s.root\"
options ROOTDEVNAME=\"ufs:/dev/da0\"
options MUTEX_NOINLINE
@@ -59,7 +57,6 @@ device sdhci # generic sdhci
# Pseudo devices
device loop
-device random
device pty
device md
device gpio
@@ -81,8 +78,6 @@ device pass
#device atadisk
#device mvs
-device nand
-
# Serial ports
device uart
diff --git a/sys/arm/conf/ZEDBOARD b/sys/arm/conf/ZEDBOARD
index 274d96642d6b..187d636c2e49 100644
--- a/sys/arm/conf/ZEDBOARD
+++ b/sys/arm/conf/ZEDBOARD
@@ -48,7 +48,6 @@ device pl310 # PL310 L2 cache controller
device mpcore_timer
device loop
-device random
device ether
device cgem # Zynq-7000 gig ethernet device
device mii
diff --git a/sys/arm/freescale/vybrid/vf_nfc.c b/sys/arm/freescale/vybrid/vf_nfc.c
deleted file mode 100644
index cdefa2564864..000000000000
--- a/sys/arm/freescale/vybrid/vf_nfc.c
+++ /dev/null
@@ -1,528 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
- * 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.
- */
-
-/*
- * Vybrid Family NAND Flash Controller (NFC)
- * Chapter 31, Vybrid Reference Manual, Rev. 5, 07/2013
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/time.h>
-
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-
-#include <machine/bus.h>
-
-#include "nfc_if.h"
-
-#include <arm/freescale/vybrid/vf_common.h>
-
-enum addr_type {
- ADDR_NONE,
- ADDR_ID,
- ADDR_ROW,
- ADDR_ROWCOL
-};
-
-struct fsl_nfc_fcm {
- uint32_t addr_bits;
- enum addr_type addr_type;
- uint32_t col_addr_bits;
- uint32_t row_addr_bits;
- u_int read_ptr;
- u_int addr_ptr;
- u_int command;
- u_int code;
-};
-
-struct vf_nand_softc {
- struct nand_softc nand_dev;
- bus_space_handle_t bsh;
- bus_space_tag_t bst;
- struct resource *res[2];
- struct fsl_nfc_fcm fcm;
-};
-
-static struct resource_spec nfc_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE },
- { SYS_RES_IRQ, 0, RF_ACTIVE },
- { -1, 0 }
-};
-
-static int vf_nand_attach(device_t);
-static int vf_nand_probe(device_t);
-static int vf_nand_send_command(device_t, uint8_t);
-static int vf_nand_send_address(device_t, uint8_t);
-static int vf_nand_start_command(device_t);
-static uint8_t vf_nand_read_byte(device_t);
-static void vf_nand_read_buf(device_t, void *, uint32_t);
-static void vf_nand_write_buf(device_t, void *, uint32_t);
-static int vf_nand_select_cs(device_t, uint8_t);
-static int vf_nand_read_rnb(device_t);
-
-#define CMD_READ_PAGE 0x7EE0
-#define CMD_PROG_PAGE 0x7FC0
-#define CMD_PROG_PAGE_DMA 0xFFC8
-#define CMD_ERASE 0x4EC0
-#define CMD_READ_ID 0x4804
-#define CMD_READ_STATUS 0x4068
-#define CMD_RESET 0x4040
-#define CMD_RANDOM_IN 0x7140
-#define CMD_RANDOM_OUT 0x70E0
-
-#define CMD_BYTE2_PROG_PAGE 0x10
-#define CMD_BYTE2_PAGE_READ 0x30
-#define CMD_BYTE2_ERASE 0xD0
-
-#define NFC_CMD1 0x3F00 /* Flash command 1 */
-#define NFC_CMD2 0x3F04 /* Flash command 2 */
-#define NFC_CAR 0x3F08 /* Column address */
-#define NFC_RAR 0x3F0C /* Row address */
-#define NFC_RPT 0x3F10 /* Flash command repeat */
-#define NFC_RAI 0x3F14 /* Row address increment */
-#define NFC_SR1 0x3F18 /* Flash status 1 */
-#define NFC_SR2 0x3F1C /* Flash status 2 */
-#define NFC_DMA_CH1 0x3F20 /* DMA channel 1 address */
-#define NFC_DMACFG 0x3F24 /* DMA configuration */
-#define NFC_SWAP 0x3F28 /* Cach swap */
-#define NFC_SECSZ 0x3F2C /* Sector size */
-#define NFC_CFG 0x3F30 /* Flash configuration */
-#define NFC_DMA_CH2 0x3F34 /* DMA channel 2 address */
-#define NFC_ISR 0x3F38 /* Interrupt status */
-
-#define ECCMODE_SHIFT 17
-#define AIAD_SHIFT 5
-#define AIBN_SHIFT 4
-#define PAGECOUNT_SHIFT 0
-#define BITWIDTH_SHIFT 7
-#define BITWIDTH8 0
-#define BITWIDTH16 1
-#define PAGECOUNT_MASK 0xf
-
-#define CMD2_BYTE1_SHIFT 24
-#define CMD2_CODE_SHIFT 8
-#define CMD2_BUFNO_SHIFT 1
-#define CMD2_START_SHIFT 0
-
-static device_method_t vf_nand_methods[] = {
- DEVMETHOD(device_probe, vf_nand_probe),
- DEVMETHOD(device_attach, vf_nand_attach),
- DEVMETHOD(nfc_start_command, vf_nand_start_command),
- DEVMETHOD(nfc_send_command, vf_nand_send_command),
- DEVMETHOD(nfc_send_address, vf_nand_send_address),
- DEVMETHOD(nfc_read_byte, vf_nand_read_byte),
- DEVMETHOD(nfc_read_buf, vf_nand_read_buf),
- DEVMETHOD(nfc_write_buf, vf_nand_write_buf),
- DEVMETHOD(nfc_select_cs, vf_nand_select_cs),
- DEVMETHOD(nfc_read_rnb, vf_nand_read_rnb),
- { 0, 0 },
-};
-
-static driver_t vf_nand_driver = {
- "nand",
- vf_nand_methods,
- sizeof(struct vf_nand_softc),
-};
-
-static devclass_t vf_nand_devclass;
-DRIVER_MODULE(vf_nand, simplebus, vf_nand_driver, vf_nand_devclass, 0, 0);
-
-static int
-vf_nand_probe(device_t dev)
-{
-
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
-
- if (!ofw_bus_is_compatible(dev, "fsl,mvf600-nand"))
- return (ENXIO);
-
- device_set_desc(dev, "Vybrid Family NAND controller");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-vf_nand_attach(device_t dev)
-{
- struct vf_nand_softc *sc;
- int err;
- int reg;
-
- sc = device_get_softc(dev);
- if (bus_alloc_resources(dev, nfc_spec, sc->res)) {
- device_printf(dev, "could not allocate resources!\n");
- return (ENXIO);
- }
-
- sc->bst = rman_get_bustag(sc->res[0]);
- sc->bsh = rman_get_bushandle(sc->res[0]);
-
- /* Size in bytes of one elementary transfer unit */
- WRITE4(sc, NFC_SECSZ, 2048);
-
- /* Flash mode width */
- reg = READ4(sc, NFC_CFG);
- reg |= (BITWIDTH16 << BITWIDTH_SHIFT);
-
- /* No correction, ECC bypass */
- reg &= ~(0x7 << ECCMODE_SHIFT);
-
- /* Disable Auto-incrementing of flash row address */
- reg &= ~(0x1 << AIAD_SHIFT);
-
- /* Disable Auto-incrementing of buffer numbers */
- reg &= ~(0x1 << AIBN_SHIFT);
-
- /*
- * Number of virtual pages (in one physical flash page)
- * to be programmed or read, etc.
- */
- reg &= ~(PAGECOUNT_MASK);
- reg |= (1 << PAGECOUNT_SHIFT);
- WRITE4(sc, NFC_CFG, reg);
-
- nand_init(&sc->nand_dev, dev, NAND_ECC_NONE, 0, 0, NULL, NULL);
- err = nandbus_create(dev);
- return (err);
-}
-
-static int
-vf_nand_start_command(device_t dev)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- int reg;
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- nand_debug(NDBG_DRV,"vf_nand: start command %x", fcm->command);
-
- /* CMD2 */
- reg = READ4(sc, NFC_CMD2);
- reg &= ~(0xff << CMD2_BYTE1_SHIFT);
- reg |= (fcm->command << CMD2_BYTE1_SHIFT);
- WRITE4(sc, NFC_CMD2, reg);
-
- /* CMD1 */
- if ((fcm->command == NAND_CMD_READ) ||
- (fcm->command == NAND_CMD_PROG) ||
- (fcm->command == NAND_CMD_ERASE)) {
- reg = READ4(sc, NFC_CMD1);
- reg &= ~(0xff << 24);
-
- if (fcm->command == NAND_CMD_READ)
- reg |= (CMD_BYTE2_PAGE_READ << 24);
- else if (fcm->command == NAND_CMD_PROG)
- reg |= (CMD_BYTE2_PROG_PAGE << 24);
- else if (fcm->command == NAND_CMD_ERASE)
- reg |= (CMD_BYTE2_ERASE << 24);
-
- WRITE4(sc, NFC_CMD1, reg);
- }
-
- /* We work with 1st buffer */
- reg = READ4(sc, NFC_CMD2);
- reg &= ~(0xf << CMD2_BUFNO_SHIFT);
- reg |= (0 << CMD2_BUFNO_SHIFT);
- WRITE4(sc, NFC_CMD2, reg);
-
- /* Cmd CODE */
- reg = READ4(sc, NFC_CMD2);
- reg &= ~(0xffff << CMD2_CODE_SHIFT);
- reg |= (fcm->code << CMD2_CODE_SHIFT);
- WRITE4(sc, NFC_CMD2, reg);
-
- /* Col */
- if (fcm->addr_type == ADDR_ROWCOL) {
- reg = READ4(sc, NFC_CAR);
- reg &= ~(0xffff);
- reg |= fcm->col_addr_bits;
- nand_debug(NDBG_DRV,"setting CAR to 0x%08x\n", reg);
- WRITE4(sc, NFC_CAR, reg);
- }
-
- /* Row */
- reg = READ4(sc, NFC_RAR);
- reg &= ~(0xffffff);
- if (fcm->addr_type == ADDR_ID)
- reg |= fcm->addr_bits;
- else
- reg |= fcm->row_addr_bits;
- WRITE4(sc, NFC_RAR, reg);
-
- /* Start */
- reg = READ4(sc, NFC_CMD2);
- reg |= (1 << CMD2_START_SHIFT);
- WRITE4(sc, NFC_CMD2, reg);
-
- /* Wait command completion */
- while (READ4(sc, NFC_CMD2) & (1 << CMD2_START_SHIFT))
- ;
-
- return (0);
-}
-
-static int
-vf_nand_send_command(device_t dev, uint8_t command)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
-
- nand_debug(NDBG_DRV,"vf_nand: send command %x", command);
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- if ((command == NAND_CMD_READ_END) ||
- (command == NAND_CMD_PROG_END) ||
- (command == NAND_CMD_ERASE_END)) {
- return (0);
- }
-
- fcm->command = command;
-
- fcm->code = 0;
- fcm->read_ptr = 0;
- fcm->addr_type = 0;
- fcm->addr_bits = 0;
-
- fcm->addr_ptr = 0;
- fcm->col_addr_bits = 0;
- fcm->row_addr_bits = 0;
-
- switch (command) {
- case NAND_CMD_READ:
- fcm->code = CMD_READ_PAGE;
- fcm->addr_type = ADDR_ROWCOL;
- break;
- case NAND_CMD_PROG:
- fcm->code = CMD_PROG_PAGE;
- fcm->addr_type = ADDR_ROWCOL;
- break;
- case NAND_CMD_PROG_END:
- break;
- case NAND_CMD_ERASE_END:
- break;
- case NAND_CMD_RESET:
- fcm->code = CMD_RESET;
- break;
- case NAND_CMD_READ_ID:
- fcm->code = CMD_READ_ID;
- fcm->addr_type = ADDR_ID;
- break;
- case NAND_CMD_READ_PARAMETER:
- fcm->code = CMD_READ_PAGE;
- fcm->addr_type = ADDR_ID;
- break;
- case NAND_CMD_STATUS:
- fcm->code = CMD_READ_STATUS;
- break;
- case NAND_CMD_ERASE:
- fcm->code = CMD_ERASE;
- fcm->addr_type = ADDR_ROW;
- break;
- default:
- nand_debug(NDBG_DRV, "unknown command %d\n", command);
- return (1);
- }
-
- return (0);
-}
-
-static int
-vf_nand_send_address(device_t dev, uint8_t addr)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
-
- nand_debug(NDBG_DRV,"vf_nand: send address %x", addr);
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- nand_debug(NDBG_DRV, "setting addr #%d to 0x%02x\n", fcm->addr_ptr, addr);
-
- if (fcm->addr_type == ADDR_ID) {
- fcm->addr_bits = addr;
- } else if (fcm->addr_type == ADDR_ROWCOL) {
-
- if (fcm->addr_ptr < 2)
- fcm->col_addr_bits |= (addr << (fcm->addr_ptr * 8));
- else
- fcm->row_addr_bits |= (addr << ((fcm->addr_ptr - 2) * 8));
-
- } else if (fcm->addr_type == ADDR_ROW)
- fcm->row_addr_bits |= (addr << (fcm->addr_ptr * 8));
-
- fcm->addr_ptr += 1;
-
- return (0);
-}
-
-static uint8_t
-vf_nand_read_byte(device_t dev)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint8_t data;
- int sr1, sr2;
- int b;
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- sr1 = READ4(sc, NFC_SR1);
- sr2 = READ4(sc, NFC_SR2);
-
- data = 0;
- if (fcm->addr_type == ADDR_ID) {
- b = 32 - ((fcm->read_ptr + 1) * 8);
- data = (sr1 >> b) & 0xff;
- fcm->read_ptr++;
- } else if (fcm->command == NAND_CMD_STATUS) {
- data = sr2 & 0xff;
- }
-
- nand_debug(NDBG_DRV,"vf_nand: read %x", data);
- return (data);
-}
-
-static void
-vf_nand_read_buf(device_t dev, void* buf, uint32_t len)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint16_t *tmp;
- uint8_t *b;
- int i;
-
- b = (uint8_t*)buf;
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- nand_debug(NDBG_DRV, "vf_nand: read_buf len %d", len);
-
- if (fcm->command == NAND_CMD_READ_PARAMETER) {
- tmp = malloc(len, M_DEVBUF, M_NOWAIT);
- bus_read_region_2(sc->res[0], 0x0, tmp, len);
-
- for (i = 0; i < len; i += 2) {
- b[i] = tmp[i+1];
- b[i+1] = tmp[i];
- }
-
- free(tmp, M_DEVBUF);
-
-#ifdef NAND_DEBUG
- for (i = 0; i < len; i++) {
- if (!(i % 16))
- printf("%s", i == 0 ? "vf_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
- }
-#endif
-
- } else {
-
- for (i = 0; i < len; i++) {
- b[i] = READ1(sc, i);
-
-#ifdef NAND_DEBUG
- if (!(i % 16))
- printf("%s", i == 0 ? "vf_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
-#endif
- }
-
- }
-}
-
-static void
-vf_nand_write_buf(device_t dev, void* buf, uint32_t len)
-{
- struct vf_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint8_t *b;
- int i;
-
- b = (uint8_t*)buf;
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- nand_debug(NDBG_DRV,"vf_nand: write_buf len %d", len);
-
- for (i = 0; i < len; i++) {
- WRITE1(sc, i, b[i]);
-
-#ifdef NAND_DEBUG
- if (!(i % 16))
- printf("%s", i == 0 ? "vf_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
-#endif
-
- }
-}
-
-static int
-vf_nand_select_cs(device_t dev, uint8_t cs)
-{
-
- if (cs > 0)
- return (ENODEV);
-
- return (0);
-}
-
-static int
-vf_nand_read_rnb(device_t dev)
-{
-
- /* no-op */
- return (0); /* ready */
-}
diff --git a/sys/arm/mv/files.arm7 b/sys/arm/mv/files.arm7
index d27357480cae..a6138042bc80 100644
--- a/sys/arm/mv/files.arm7
+++ b/sys/arm/mv/files.arm7
@@ -29,7 +29,6 @@ dev/iicbus/twsi/mv_twsi.c optional twsi
dev/mge/if_mge.c optional mge
dev/neta/if_mvneta_fdt.c optional neta fdt
dev/neta/if_mvneta.c optional neta mdio mii
-dev/nand/nfc_mv.c optional nand
dev/mvs/mvs_soc.c optional mvs
dev/uart/uart_dev_ns8250.c optional uart
dev/uart/uart_dev_snps.c optional uart
diff --git a/sys/arm/mv/files.mv b/sys/arm/mv/files.mv
index ee027f059441..1dc45105450c 100644
--- a/sys/arm/mv/files.mv
+++ b/sys/arm/mv/files.mv
@@ -26,7 +26,6 @@ dev/iicbus/twsi/mv_twsi.c optional twsi
dev/mge/if_mge.c optional mge
dev/neta/if_mvneta_fdt.c optional neta fdt
dev/neta/if_mvneta.c optional neta mdio mii
-dev/nand/nfc_mv.c optional nand
dev/mvs/mvs_soc.c optional mvs
dev/uart/uart_dev_ns8250.c optional uart
dev/uart/uart_dev_snps.c optional uart
diff --git a/sys/arm/ti/am335x/am335x_ehrpwm.c b/sys/arm/ti/am335x/am335x_ehrpwm.c
index 53cb3bb78249..cbb947038ba9 100644
--- a/sys/arm/ti/am335x/am335x_ehrpwm.c
+++ b/sys/arm/ti/am335x/am335x_ehrpwm.c
@@ -45,21 +45,43 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include "pwmbus_if.h"
+
#include "am335x_pwm.h"
+/*******************************************************************************
+ * Enhanced resolution PWM driver. Many of the advanced featues of the hardware
+ * are not supported by this driver. What is implemented here is simple
+ * variable-duty-cycle PWM output.
+ *
+ * Note that this driver was historically configured using a set of sysctl
+ * variables/procs, and later gained support for the PWM(9) API. The sysctl
+ * code is still present to support existing apps, but that interface is
+ * considered deprecated.
+ *
+ * An important caveat is that the original sysctl interface and the new PWM API
+ * cannot both be used at once. If both interfaces are used to change
+ * configuration, it's quite likely you won't get the expected results. Also,
+ * reading the sysctl values after configuring via PWM will not return the right
+ * results.
+ ******************************************************************************/
+
/* In ticks */
#define DEFAULT_PWM_PERIOD 1000
#define PWM_CLOCK 100000000UL
+#define NS_PER_SEC 1000000000
+
#define PWM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define PWM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define PWM_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
#define PWM_LOCK_INIT(_sc) mtx_init(&(_sc)->sc_mtx, \
device_get_nameunit(_sc->sc_dev), "am335x_ehrpwm softc", MTX_DEF)
#define PWM_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
-#define EPWM_READ2(_sc, reg) bus_read_2((_sc)->sc_mem_res, reg);
+#define EPWM_READ2(_sc, reg) bus_read_2((_sc)->sc_mem_res, reg)
#define EPWM_WRITE2(_sc, reg, value) \
- bus_write_2((_sc)->sc_mem_res, reg, value);
+ bus_write_2((_sc)->sc_mem_res, reg, value)
#define EPWM_TBCTL 0x00
#define TBCTL_FREERUN (2 << 14)
@@ -119,6 +141,11 @@ __FBSDID("$FreeBSD$");
#define AQCTL_ZRO_TOGGLE (3 << 0)
#define EPWM_AQSFRC 0x1a
#define EPWM_AQCSFRC 0x1c
+#define AQCSFRC_OFF 0
+#define AQCSFRC_LO 1
+#define AQCSFRC_HI 2
+#define AQCSFRC_MASK 3
+#define AQCSFRC(chan, hilo) ((hilo) << (2 * chan))
/* Trip-Zone module */
#define EPWM_TZCTL 0x28
@@ -135,12 +162,21 @@ static device_detach_t am335x_ehrpwm_detach;
static int am335x_ehrpwm_clkdiv[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+struct ehrpwm_channel {
+ u_int duty; /* on duration, in ns */
+ bool enabled; /* channel enabled? */
+ bool inverted; /* signal inverted? */
+};
+#define NUM_CHANNELS 2
+
struct am335x_ehrpwm_softc {
device_t sc_dev;
+ device_t sc_busdev;
struct mtx sc_mtx;
struct resource *sc_mem_res;
int sc_mem_rid;
- /* sysctl for configuration */
+
+ /* Things used for configuration via sysctl [deprecated]. */
int sc_pwm_clkdiv;
int sc_pwm_freq;
struct sysctl_oid *sc_clkdiv_oid;
@@ -151,23 +187,130 @@ struct am335x_ehrpwm_softc {
uint32_t sc_pwm_period;
uint32_t sc_pwm_dutyA;
uint32_t sc_pwm_dutyB;
-};
-
-static device_method_t am335x_ehrpwm_methods[] = {
- DEVMETHOD(device_probe, am335x_ehrpwm_probe),
- DEVMETHOD(device_attach, am335x_ehrpwm_attach),
- DEVMETHOD(device_detach, am335x_ehrpwm_detach),
- DEVMETHOD_END
+ /* Things used for configuration via pwm(9) api. */
+ u_int sc_clkfreq; /* frequency in Hz */
+ u_int sc_clktick; /* duration in ns */
+ u_int sc_period; /* duration in ns */
+ struct ehrpwm_channel sc_channels[NUM_CHANNELS];
};
-static driver_t am335x_ehrpwm_driver = {
- "am335x_ehrpwm",
- am335x_ehrpwm_methods,
- sizeof(struct am335x_ehrpwm_softc),
+static struct ofw_compat_data compat_data[] = {
+ {"ti,am33xx-ehrpwm", true},
+ {NULL, false},
};
+SIMPLEBUS_PNP_INFO(compat_data);
-static devclass_t am335x_ehrpwm_devclass;
+static void
+am335x_ehrpwm_cfg_duty(struct am335x_ehrpwm_softc *sc, u_int chan, u_int duty)
+{
+ u_int tbcmp;
+
+ if (duty == 0)
+ tbcmp = 0;
+ else
+ tbcmp = max(1, duty / sc->sc_clktick);
+
+ sc->sc_channels[chan].duty = tbcmp * sc->sc_clktick;
+
+ PWM_LOCK_ASSERT(sc);
+ EPWM_WRITE2(sc, (chan == 0) ? EPWM_CMPA : EPWM_CMPB, tbcmp);
+}
+
+static void
+am335x_ehrpwm_cfg_enable(struct am335x_ehrpwm_softc *sc, u_int chan, bool enable)
+{
+ uint16_t regval;
+
+ sc->sc_channels[chan].enabled = enable;
+
+ /*
+ * Turn off any existing software-force of the channel, then force
+ * it in the right direction (high or low) if it's not being enabled.
+ */
+ PWM_LOCK_ASSERT(sc);
+ regval = EPWM_READ2(sc, EPWM_AQCSFRC);
+ regval &= ~AQCSFRC(chan, AQCSFRC_MASK);
+ if (!sc->sc_channels[chan].enabled) {
+ if (sc->sc_channels[chan].inverted)
+ regval |= AQCSFRC(chan, AQCSFRC_HI);
+ else
+ regval |= AQCSFRC(chan, AQCSFRC_LO);
+ }
+ EPWM_WRITE2(sc, EPWM_AQCSFRC, regval);
+}
+
+static bool
+am335x_ehrpwm_cfg_period(struct am335x_ehrpwm_softc *sc, u_int period)
+{
+ uint16_t regval;
+ u_int clkdiv, hspclkdiv, pwmclk, pwmtick, tbprd;
+
+ /* Can't do a period shorter than 2 clock ticks. */
+ if (period < 2 * NS_PER_SEC / PWM_CLOCK) {
+ sc->sc_clkfreq = 0;
+ sc->sc_clktick = 0;
+ sc->sc_period = 0;
+ return (false);
+ }
+
+ /*
+ * Figure out how much we have to divide down the base 100MHz clock so
+ * that we can express the requested period as a 16-bit tick count.
+ */
+ tbprd = 0;
+ for (clkdiv = 0; clkdiv < 8; ++clkdiv) {
+ const u_int cd = 1 << clkdiv;
+ for (hspclkdiv = 0; hspclkdiv < 8; ++hspclkdiv) {
+ const u_int cdhs = max(1, hspclkdiv * 2);
+ pwmclk = PWM_CLOCK / (cd * cdhs);
+ pwmtick = NS_PER_SEC / pwmclk;
+ if (period / pwmtick < 65536) {
+ tbprd = period / pwmtick;
+ break;
+ }
+ }
+ if (tbprd != 0)
+ break;
+ }
+
+ /* Handle requested period too long for available clock divisors. */
+ if (tbprd == 0)
+ return (false);
+
+ /*
+ * If anything has changed from the current settings, reprogram the
+ * clock divisors and period register.
+ */
+ if (sc->sc_clkfreq != pwmclk || sc->sc_clktick != pwmtick ||
+ sc->sc_period != tbprd * pwmtick) {
+
+ sc->sc_clkfreq = pwmclk;
+ sc->sc_clktick = pwmtick;
+ sc->sc_period = tbprd * pwmtick;
+
+ PWM_LOCK_ASSERT(sc);
+ regval = EPWM_READ2(sc, EPWM_TBCTL);
+ regval &= ~(TBCTL_CLKDIV_MASK | TBCTL_HSPCLKDIV_MASK);
+ regval |= TBCTL_CLKDIV(clkdiv) | TBCTL_HSPCLKDIV(hspclkdiv);
+ EPWM_WRITE2(sc, EPWM_TBCTL, regval);
+ EPWM_WRITE2(sc, EPWM_TBPRD, tbprd - 1);
+#if 0
+ device_printf(sc->sc_dev, "clkdiv %u hspclkdiv %u tbprd %u "
+ "clkfreq %u Hz clktick %u ns period got %u requested %u\n",
+ clkdiv, hspclkdiv, tbprd - 1,
+ sc->sc_clkfreq, sc->sc_clktick, sc->sc_period, period);
+#endif
+ /*
+ * If the period changed, that invalidates the current CMP
+ * registers (duty values), just zero them out.
+ */
+ am335x_ehrpwm_cfg_duty(sc, 0, 0);
+ am335x_ehrpwm_cfg_duty(sc, 1, 0);
+ }
+
+ return (true);
+}
static void
am335x_ehrpwm_freq(struct am335x_ehrpwm_softc *sc)
@@ -331,13 +474,89 @@ am335x_ehrpwm_sysctl_period(SYSCTL_HANDLER_ARGS)
}
static int
+am335x_ehrpwm_channel_count(device_t dev, u_int *nchannel)
+{
+
+ *nchannel = NUM_CHANNELS;
+
+ return (0);
+}
+
+static int
+am335x_ehrpwm_channel_config(device_t dev, u_int channel, u_int period, u_int duty)
+{
+ struct am335x_ehrpwm_softc *sc;
+ bool status;
+
+ if (channel >= NUM_CHANNELS)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ PWM_LOCK(sc);
+ status = am335x_ehrpwm_cfg_period(sc, period);
+ if (status)
+ am335x_ehrpwm_cfg_duty(sc, channel, duty);
+ PWM_UNLOCK(sc);
+
+ return (status ? 0 : EINVAL);
+}
+
+static int
+am335x_ehrpwm_channel_get_config(device_t dev, u_int channel,
+ u_int *period, u_int *duty)
+{
+ struct am335x_ehrpwm_softc *sc;
+
+ if (channel >= NUM_CHANNELS)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ *period = sc->sc_period;
+ *duty = sc->sc_channels[channel].duty;
+ return (0);
+}
+
+static int
+am335x_ehrpwm_channel_enable(device_t dev, u_int channel, bool enable)
+{
+ struct am335x_ehrpwm_softc *sc;
+
+ if (channel >= NUM_CHANNELS)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ PWM_LOCK(sc);
+ am335x_ehrpwm_cfg_enable(sc, channel, enable);
+ PWM_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+am335x_ehrpwm_channel_is_enabled(device_t dev, u_int channel, bool *enabled)
+{
+ struct am335x_ehrpwm_softc *sc;
+
+ if (channel >= NUM_CHANNELS)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ *enabled = sc->sc_channels[channel].enabled;
+
+ return (0);
+}
+
+static int
am335x_ehrpwm_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (!ofw_bus_is_compatible(dev, "ti,am33xx-ehrpwm"))
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
return (ENXIO);
device_set_desc(dev, "AM335x EHRPWM");
@@ -365,7 +584,7 @@ am335x_ehrpwm_attach(device_t dev)
goto fail;
}
- /* Init backlight interface */
+ /* Init sysctl interface */
ctx = device_get_sysctl_ctx(sc->sc_dev);
tree = device_get_sysctl_tree(sc->sc_dev);
@@ -414,7 +633,13 @@ am335x_ehrpwm_attach(device_t dev)
EPWM_WRITE2(sc, EPWM_TZCTL, 0xf);
reg = EPWM_READ2(sc, EPWM_TZFLG);
- return (0);
+ if ((sc->sc_busdev = device_add_child(dev, "pwmbus", -1)) == NULL) {
+ device_printf(dev, "Cannot add child pwmbus\n");
+ // This driver can still do things even without the bus child.
+ }
+
+ bus_generic_probe(dev);
+ return (bus_generic_attach(dev));
fail:
PWM_LOCK_DESTROY(sc);
if (sc->sc_mem_res)
@@ -428,13 +653,22 @@ static int
am335x_ehrpwm_detach(device_t dev)
{
struct am335x_ehrpwm_softc *sc;
+ int error;
sc = device_get_softc(dev);
+ if ((error = bus_generic_detach(sc->sc_dev)) != 0)
+ return (error);
+
PWM_LOCK(sc);
+
+ if (sc->sc_busdev != NULL)
+ device_delete_child(dev, sc->sc_busdev);
+
if (sc->sc_mem_res)
bus_release_resource(dev, SYS_RES_MEMORY,
sc->sc_mem_rid, sc->sc_mem_res);
+
PWM_UNLOCK(sc);
PWM_LOCK_DESTROY(sc);
@@ -442,6 +676,44 @@ am335x_ehrpwm_detach(device_t dev)
return (0);
}
+static phandle_t
+am335x_ehrpwm_get_node(device_t bus, device_t dev)
+{
+
+ /*
+ * Share our controller node with our pwmbus child; it instantiates
+ * devices by walking the children contained within our node.
+ */
+ return ofw_bus_get_node(bus);
+}
+
+static device_method_t am335x_ehrpwm_methods[] = {
+ DEVMETHOD(device_probe, am335x_ehrpwm_probe),
+ DEVMETHOD(device_attach, am335x_ehrpwm_attach),
+ DEVMETHOD(device_detach, am335x_ehrpwm_detach),
+
+ /* ofw_bus_if */
+ DEVMETHOD(ofw_bus_get_node, am335x_ehrpwm_get_node),
+
+ /* pwm interface */
+ DEVMETHOD(pwmbus_channel_count, am335x_ehrpwm_channel_count),
+ DEVMETHOD(pwmbus_channel_config, am335x_ehrpwm_channel_config),
+ DEVMETHOD(pwmbus_channel_get_config, am335x_ehrpwm_channel_get_config),
+ DEVMETHOD(pwmbus_channel_enable, am335x_ehrpwm_channel_enable),
+ DEVMETHOD(pwmbus_channel_is_enabled, am335x_ehrpwm_channel_is_enabled),
+
+ DEVMETHOD_END
+};
+
+static driver_t am335x_ehrpwm_driver = {
+ "pwm",
+ am335x_ehrpwm_methods,
+ sizeof(struct am335x_ehrpwm_softc),
+};
+
+static devclass_t am335x_ehrpwm_devclass;
+
DRIVER_MODULE(am335x_ehrpwm, am335x_pwmss, am335x_ehrpwm_driver, am335x_ehrpwm_devclass, 0, 0);
MODULE_VERSION(am335x_ehrpwm, 1);
MODULE_DEPEND(am335x_ehrpwm, am335x_pwmss, 1, 1, 1);
+MODULE_DEPEND(am335x_ehrpwm, pwmbus, 1, 1, 1);
diff --git a/sys/arm64/acpica/acpi_iort.c b/sys/arm64/acpica/acpi_iort.c
index edd87474c9c9..10a501254bc6 100644
--- a/sys/arm64/acpica/acpi_iort.c
+++ b/sys/arm64/acpica/acpi_iort.c
@@ -370,19 +370,44 @@ srat_resolve_its_pxm(ACPI_SUBTABLE_HEADER *entry, void *arg)
ACPI_SRAT_GIC_ITS_AFFINITY *gicits;
struct iort_node *its_node;
struct iort_its_entry *its_entry;
- int i, matches;
+ int *map_counts;
+ int i, matches, dom;
if (entry->Type != ACPI_SRAT_TYPE_GIC_ITS_AFFINITY)
return;
matches = 0;
+ map_counts = arg;
gicits = (ACPI_SRAT_GIC_ITS_AFFINITY *)entry;
+ dom = acpi_map_pxm_to_vm_domainid(gicits->ProximityDomain);
+
+ /*
+ * Catch firmware and config errors. map_counts keeps a
+ * count of ProximityDomain values mapping to a domain ID
+ */
+#if MAXMEMDOM > 1
+ if (dom == -1)
+ printf("Firmware Error: Proximity Domain %d could not be"
+ " mapped for GIC ITS ID %d!\n",
+ gicits->ProximityDomain, gicits->ItsId);
+#endif
+ /* use dom + 1 as index to handle the case where dom == -1 */
+ i = ++map_counts[dom + 1];
+ if (i > 1) {
+#ifdef NUMA
+ if (dom != -1)
+ printf("ERROR: Multiple Proximity Domains map to the"
+ " same NUMA domain %d!\n", dom);
+#else
+ printf("WARNING: multiple Proximity Domains in SRAT but NUMA"
+ " NOT enabled!\n");
+#endif
+ }
TAILQ_FOREACH(its_node, &its_groups, next) {
its_entry = its_node->entries.its;
for (i = 0; i < its_node->nentries; i++, its_entry++) {
if (its_entry->its_id == gicits->ItsId) {
- its_entry->pxm = acpi_map_pxm_to_vm_domainid(
- gicits->ProximityDomain);
+ its_entry->pxm = dom;
matches++;
}
}
@@ -401,6 +426,7 @@ iort_post_process_its(void)
ACPI_TABLE_MADT *madt;
ACPI_TABLE_SRAT *srat;
vm_paddr_t madt_pa, srat_pa;
+ int map_counts[MAXMEMDOM + 1] = { 0 };
/* Check ITS block in MADT */
madt_pa = acpi_find_table(ACPI_SIG_MADT);
@@ -417,7 +443,7 @@ iort_post_process_its(void)
srat = acpi_map_table(srat_pa, ACPI_SIG_SRAT);
KASSERT(srat != NULL, ("can't map SRAT!"));
acpi_walk_subtables(srat + 1, (char *)srat + srat->Header.Length,
- srat_resolve_its_pxm, NULL);
+ srat_resolve_its_pxm, map_counts);
acpi_unmap_table(srat);
}
return (0);
diff --git a/sys/arm64/arm64/freebsd32_machdep.c b/sys/arm64/arm64/freebsd32_machdep.c
index aeac4605f2f5..2e25fe062b19 100644
--- a/sys/arm64/arm64/freebsd32_machdep.c
+++ b/sys/arm64/arm64/freebsd32_machdep.c
@@ -122,6 +122,7 @@ static void
get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
{
struct pcb *curpcb;
+ int i;
critical_enter();
curpcb = curthread->td_pcb;
@@ -137,8 +138,8 @@ get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
("Called get_fpcontext while the kernel is using the VFP"));
KASSERT((curpcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
("Non-userspace FPU flags set in get_fpcontext"));
- memcpy(mcp->mcv_reg, curpcb->pcb_fpustate.vfp_regs,
- sizeof(mcp->mcv_reg));
+ for (i = 0; i < 32; i++)
+ mcp->mcv_reg[i] = (uint64_t)curpcb->pcb_fpustate.vfp_regs[i];
mcp->mcv_fpscr = VFP_FPSCR_FROM_SRCR(curpcb->pcb_fpustate.vfp_fpcr,
curpcb->pcb_fpustate.vfp_fpsr);
}
@@ -149,13 +150,14 @@ static void
set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
{
struct pcb *pcb;
+ int i;
critical_enter();
pcb = td->td_pcb;
if (td == curthread)
vfp_discard(td);
- memcpy(pcb->pcb_fpustate.vfp_regs, mcp->mcv_reg,
- sizeof(pcb->pcb_fpustate.vfp_regs));
+ for (i = 0; i < 32; i++)
+ pcb->pcb_fpustate.vfp_regs[i] = mcp->mcv_reg[i];
pcb->pcb_fpustate.vfp_fpsr = VFP_FPSR_FROM_FPSCR(mcp->mcv_fpscr);
pcb->pcb_fpustate.vfp_fpcr = VFP_FPSR_FROM_FPSCR(mcp->mcv_fpscr);
critical_exit();
diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c
index af08ee992bb6..a83ef576e30e 100644
--- a/sys/arm64/arm64/gic_v3.c
+++ b/sys/arm64/arm64/gic_v3.c
@@ -390,10 +390,6 @@ gic_v3_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case GICV3_IVAR_NIRQS:
*result = (NIRQ - sc->gic_nirqs) / sc->gic_nchildren;
return (0);
- case GICV3_IVAR_REDIST_VADDR:
- *result = (uintptr_t)rman_get_virtual(
- &sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res);
- return (0);
case GICV3_IVAR_REDIST:
*result = (uintptr_t)sc->gic_redists.pcpu[PCPU_GET(cpuid)];
return (0);
diff --git a/sys/arm64/arm64/gic_v3_var.h b/sys/arm64/arm64/gic_v3_var.h
index 27dec4d72190..1257484a5e57 100644
--- a/sys/arm64/arm64/gic_v3_var.h
+++ b/sys/arm64/arm64/gic_v3_var.h
@@ -94,11 +94,10 @@ MALLOC_DECLARE(M_GIC_V3);
/* ivars */
#define GICV3_IVAR_NIRQS 1000
-#define GICV3_IVAR_REDIST_VADDR 1001
+/* 1001 was GICV3_IVAR_REDIST_VADDR */
#define GICV3_IVAR_REDIST 1002
__BUS_ACCESSOR(gicv3, nirqs, GICV3, NIRQS, u_int);
-__BUS_ACCESSOR(gicv3, redist_vaddr, GICV3, REDIST_VADDR, void *);
__BUS_ACCESSOR(gicv3, redist, GICV3, REDIST, void *);
/* Device methods */
diff --git a/sys/arm64/arm64/gicv3_its.c b/sys/arm64/arm64/gicv3_its.c
index f347a36c12cc..2701a7e8df0a 100644
--- a/sys/arm64/arm64/gicv3_its.c
+++ b/sys/arm64/arm64/gicv3_its.c
@@ -747,9 +747,7 @@ gicv3_its_attach(device_t dev)
if (domain < MAXMEMDOM)
CPU_COPY(&cpuset_domain[domain], &sc->sc_cpus);
} else {
- /* XXX : cannot handle more than one ITS per cpu */
- if (device_get_unit(dev) == 0)
- CPU_COPY(&all_cpus, &sc->sc_cpus);
+ CPU_COPY(&all_cpus, &sc->sc_cpus);
}
/* Allocate the command circular buffer */
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
index b8ecfc08e676..4356add12aa0 100644
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -194,6 +194,16 @@ fill_regs(struct thread *td, struct reg *regs)
memcpy(regs->x, frame->tf_x, sizeof(regs->x));
+#ifdef COMPAT_FREEBSD32
+ /*
+ * We may be called here for a 32bits process, if we're using a
+ * 64bits debugger. If so, put PC and SPSR where it expects it.
+ */
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+ regs->x[15] = frame->tf_elr;
+ regs->x[16] = frame->tf_spsr;
+ }
+#endif
return (0);
}
@@ -211,6 +221,17 @@ set_regs(struct thread *td, struct reg *regs)
memcpy(frame->tf_x, regs->x, sizeof(frame->tf_x));
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+ /*
+ * We may be called for a 32bits process if we're using
+ * a 64bits debugger. If so, get PC and SPSR from where
+ * it put it.
+ */
+ frame->tf_elr = regs->x[15];
+ frame->tf_spsr = regs->x[16] & PSR_FLAGS;
+ }
+#endif
return (0);
}
@@ -283,8 +304,9 @@ fill_regs32(struct thread *td, struct reg32 *regs)
tf = td->td_frame;
for (i = 0; i < 13; i++)
regs->r[i] = tf->tf_x[i];
- regs->r_sp = tf->tf_sp;
- regs->r_lr = tf->tf_lr;
+ /* For arm32, SP is r13 and LR is r14 */
+ regs->r_sp = tf->tf_x[13];
+ regs->r_lr = tf->tf_x[14];
regs->r_pc = tf->tf_elr;
regs->r_cpsr = tf->tf_spsr;
@@ -300,8 +322,9 @@ set_regs32(struct thread *td, struct reg32 *regs)
tf = td->td_frame;
for (i = 0; i < 13; i++)
tf->tf_x[i] = regs->r[i];
- tf->tf_sp = regs->r_sp;
- tf->tf_lr = regs->r_lr;
+ /* For arm 32, SP is r13 an LR is r14 */
+ tf->tf_x[13] = regs->r_sp;
+ tf->tf_x[14] = regs->r_lr;
tf->tf_elr = regs->r_pc;
tf->tf_spsr = regs->r_cpsr;
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index df34873025dd..bf74bb55f038 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -2510,6 +2510,82 @@ pmap_remove_l3(pmap_t pmap, pt_entry_t *l3, vm_offset_t va,
}
/*
+ * Remove the specified range of addresses from the L3 page table that is
+ * identified by the given L2 entry.
+ */
+static void
+pmap_remove_l3_range(pmap_t pmap, pd_entry_t l2e, vm_offset_t sva,
+ vm_offset_t eva, struct spglist *free, struct rwlock **lockp)
+{
+ struct md_page *pvh;
+ struct rwlock *new_lock;
+ pt_entry_t *l3, old_l3;
+ vm_offset_t va;
+ vm_page_t m;
+
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ KASSERT(rounddown2(sva, L2_SIZE) + L2_SIZE == roundup2(eva, L2_SIZE),
+ ("pmap_remove_l3_range: range crosses an L3 page table boundary"));
+ va = eva;
+ for (l3 = pmap_l2_to_l3(&l2e, sva); sva != eva; l3++, sva += L3_SIZE) {
+ if (!pmap_l3_valid(pmap_load(l3))) {
+ if (va != eva) {
+ pmap_invalidate_range(pmap, va, sva);
+ va = eva;
+ }
+ continue;
+ }
+ old_l3 = pmap_load_clear(l3);
+ if ((old_l3 & ATTR_SW_WIRED) != 0)
+ pmap->pm_stats.wired_count--;
+ pmap_resident_count_dec(pmap, 1);
+ if ((old_l3 & ATTR_SW_MANAGED) != 0) {
+ m = PHYS_TO_VM_PAGE(old_l3 & ~ATTR_MASK);
+ if (pmap_page_dirty(old_l3))
+ vm_page_dirty(m);
+ if ((old_l3 & ATTR_AF) != 0)
+ vm_page_aflag_set(m, PGA_REFERENCED);
+ new_lock = PHYS_TO_PV_LIST_LOCK(VM_PAGE_TO_PHYS(m));
+ if (new_lock != *lockp) {
+ if (*lockp != NULL) {
+ /*
+ * Pending TLB invalidations must be
+ * performed before the PV list lock is
+ * released. Otherwise, a concurrent
+ * pmap_remove_all() on a physical page
+ * could return while a stale TLB entry
+ * still provides access to that page.
+ */
+ if (va != eva) {
+ pmap_invalidate_range(pmap, va,
+ sva);
+ va = eva;
+ }
+ rw_wunlock(*lockp);
+ }
+ *lockp = new_lock;
+ rw_wlock(*lockp);
+ }
+ pmap_pvh_free(&m->md, pmap, sva);
+ if (TAILQ_EMPTY(&m->md.pv_list) &&
+ (m->flags & PG_FICTITIOUS) == 0) {
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ if (TAILQ_EMPTY(&pvh->pv_list))
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ }
+ }
+ if (va == eva)
+ va = sva;
+ if (pmap_unuse_pt(pmap, sva, l2e, free)) {
+ sva += L3_SIZE;
+ break;
+ }
+ }
+ if (va != eva)
+ pmap_invalidate_range(pmap, va, sva);
+}
+
+/*
* Remove the given range of addresses from the specified map.
*
* It is assumed that the start and end are properly
@@ -2519,9 +2595,9 @@ void
pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
{
struct rwlock *lock;
- vm_offset_t va, va_next;
+ vm_offset_t va_next;
pd_entry_t *l0, *l1, *l2;
- pt_entry_t l3_paddr, *l3;
+ pt_entry_t l3_paddr;
struct spglist free;
/*
@@ -2594,28 +2670,8 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
if (va_next > eva)
va_next = eva;
- va = va_next;
- for (l3 = pmap_l2_to_l3(l2, sva); sva != va_next; l3++,
- sva += L3_SIZE) {
- if (l3 == NULL)
- panic("l3 == NULL");
- if (pmap_load(l3) == 0) {
- if (va != va_next) {
- pmap_invalidate_range(pmap, va, sva);
- va = va_next;
- }
- continue;
- }
- if (va == va_next)
- va = sva;
- if (pmap_remove_l3(pmap, l3, sva, l3_paddr, &free,
- &lock)) {
- sva += L3_SIZE;
- break;
- }
- }
- if (va != va_next)
- pmap_invalidate_range(pmap, va, sva);
+ pmap_remove_l3_range(pmap, l3_paddr, sva, va_next, &free,
+ &lock);
}
if (lock != NULL)
rw_wunlock(lock);
@@ -3352,7 +3408,7 @@ validate:
__func__, pmap, va, new_l3);
}
} else {
- /* New mappig */
+ /* New mapping */
pmap_load_store(l3, new_l3);
dsb(ishst);
}
@@ -3419,8 +3475,7 @@ pmap_enter_l2(pmap_t pmap, vm_offset_t va, pd_entry_t new_l2, u_int flags,
vm_page_t m, struct rwlock **lockp)
{
struct spglist free;
- pd_entry_t *l2, *l3, old_l2;
- vm_offset_t sva;
+ pd_entry_t *l2, old_l2;
vm_page_t l2pg, mt;
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
@@ -3449,13 +3504,8 @@ pmap_enter_l2(pmap_t pmap, vm_offset_t va, pd_entry_t new_l2, u_int flags,
(void)pmap_remove_l2(pmap, l2, va,
pmap_load(pmap_l1(pmap, va)), &free, lockp);
else
- for (sva = va; sva < va + L2_SIZE; sva += PAGE_SIZE) {
- l3 = pmap_l2_to_l3(l2, sva);
- if (pmap_l3_valid(pmap_load(l3)) &&
- pmap_remove_l3(pmap, l3, sva, old_l2, &free,
- lockp) != 0)
- break;
- }
+ pmap_remove_l3_range(pmap, old_l2, va, va + L2_SIZE,
+ &free, lockp);
vm_page_free_pages_toq(&free, true);
if (va >= VM_MAXUSER_ADDRESS) {
/*
@@ -3656,6 +3706,9 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
l3 = pmap_l2_to_l3(pde, va);
}
+ /*
+ * Abort if a mapping already exists.
+ */
if (pmap_load(l3) != 0) {
if (mpte != NULL) {
mpte->wire_count--;
@@ -3705,7 +3758,15 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
cpu_icache_sync_range(PHYS_TO_DMAP(pa), PAGE_SIZE);
pmap_load_store(l3, l3_val);
+
+ /*
+ * XXX In principle, because this L3 entry was invalid, we should not
+ * need to perform a TLB invalidation here. However, in practice,
+ * when simply performing a "dsb ishst" here, processes are being
+ * terminated due to bus errors and segmentation violations.
+ */
pmap_invalidate_page(pmap, va);
+
return (mpte);
}
diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC
index 8e3f04fe1db1..2adee9db99d4 100644
--- a/sys/arm64/conf/GENERIC
+++ b/sys/arm64/conf/GENERIC
@@ -293,7 +293,6 @@ device aw_cir
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c
index 76d65ae5e405..9a4cdbed071b 100644
--- a/sys/cam/ata/ata_all.c
+++ b/sys/cam/ata/ata_all.c
@@ -1238,3 +1238,28 @@ ata_zac_mgmt_in(struct ccb_ataio *ataio, uint32_t retries,
ataio->aux = auxiliary;
}
}
+
+void
+ata_param_fixup(struct ata_params *ident_buf)
+{
+ int16_t *ptr;
+
+ for (ptr = (int16_t *)ident_buf;
+ ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) {
+ *ptr = le16toh(*ptr);
+ }
+ if (strncmp(ident_buf->model, "FX", 2) &&
+ strncmp(ident_buf->model, "NEC", 3) &&
+ strncmp(ident_buf->model, "Pioneer", 7) &&
+ strncmp(ident_buf->model, "SHARP", 5)) {
+ ata_bswap(ident_buf->model, sizeof(ident_buf->model));
+ ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
+ ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
+ }
+ ata_btrim(ident_buf->model, sizeof(ident_buf->model));
+ ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
+ ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
+ ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
+ ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
+ ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
+}
diff --git a/sys/cam/ata/ata_all.h b/sys/cam/ata/ata_all.h
index 087d6820f980..ca635253511c 100644
--- a/sys/cam/ata/ata_all.h
+++ b/sys/cam/ata/ata_all.h
@@ -135,6 +135,7 @@ void ata_read_log(struct ccb_ataio *ataio, uint32_t retries,
uint16_t block_count, uint32_t protocol,
uint8_t *data_ptr, uint32_t dxfer_len, uint32_t timeout);
+void ata_param_fixup(struct ata_params *ident_buf);
void ata_bswap(int8_t *buf, int len);
void ata_btrim(int8_t *buf, int len);
void ata_bpack(int8_t *src, int8_t *dst, int len);
diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c
index 94dc435b099b..017db8854b08 100644
--- a/sys/cam/ata/ata_xpt.c
+++ b/sys/cam/ata/ata_xpt.c
@@ -893,14 +893,13 @@ noerror:
case PROBE_IDENTIFY:
{
struct ccb_pathinq cpi;
- int16_t *ptr;
int veto = 0;
+ /*
+ * Convert to host byte order, and fix the strings.
+ */
ident_buf = &softc->ident_data;
- for (ptr = (int16_t *)ident_buf;
- ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) {
- *ptr = le16toh(*ptr);
- }
+ ata_param_fixup(ident_buf);
/*
* Allow others to veto this ATA disk attachment. This
@@ -912,20 +911,6 @@ noerror:
goto device_fail;
}
- if (strncmp(ident_buf->model, "FX", 2) &&
- strncmp(ident_buf->model, "NEC", 3) &&
- strncmp(ident_buf->model, "Pioneer", 7) &&
- strncmp(ident_buf->model, "SHARP", 5)) {
- ata_bswap(ident_buf->model, sizeof(ident_buf->model));
- ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
- ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
- }
- ata_btrim(ident_buf->model, sizeof(ident_buf->model));
- ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
- ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
- ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
- ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
- ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
/* Device may need spin-up before IDENTIFY become valid. */
if ((ident_buf->specconf == 0x37c8 ||
ident_buf->specconf == 0x738c) &&
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 2217ecc6d2ff..4736c7212a2c 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -1244,6 +1244,7 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
{
int ret = -1, l, o;
struct ccb_dev_advinfo cdai;
+ struct scsi_vpd_device_id *did;
struct scsi_vpd_id_descriptor *idd;
xpt_path_assert(path, MA_OWNED);
@@ -1253,6 +1254,7 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
cdai.flags = CDAI_FLAG_NONE;
cdai.bufsiz = len;
+ cdai.buf = buf;
if (!strcmp(attr, "GEOM::ident"))
cdai.buftype = CDAI_TYPE_SERIAL_NUM;
@@ -1262,44 +1264,49 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
strcmp(attr, "GEOM::lunname") == 0) {
cdai.buftype = CDAI_TYPE_SCSI_DEVID;
cdai.bufsiz = CAM_SCSI_DEVID_MAXLEN;
+ cdai.buf = malloc(cdai.bufsiz, M_CAMXPT, M_NOWAIT);
+ if (cdai.buf == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
} else
goto out;
- cdai.buf = malloc(cdai.bufsiz, M_CAMXPT, M_NOWAIT|M_ZERO);
- if (cdai.buf == NULL) {
- ret = ENOMEM;
- goto out;
- }
xpt_action((union ccb *)&cdai); /* can only be synchronous */
if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
if (cdai.provsiz == 0)
goto out;
- if (cdai.buftype == CDAI_TYPE_SCSI_DEVID) {
+ switch(cdai.buftype) {
+ case CDAI_TYPE_SCSI_DEVID:
+ did = (struct scsi_vpd_device_id *)cdai.buf;
if (strcmp(attr, "GEOM::lunid") == 0) {
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_naa);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_naa);
if (idd == NULL)
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_eui64);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_eui64);
if (idd == NULL)
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_uuid);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_uuid);
if (idd == NULL)
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_md5);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_md5);
} else
idd = NULL;
+
if (idd == NULL)
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_t10);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_t10);
if (idd == NULL)
- idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
- cdai.provsiz, scsi_devid_is_lun_name);
+ idd = scsi_get_devid(did, cdai.provsiz,
+ scsi_devid_is_lun_name);
if (idd == NULL)
- goto out;
+ break;
+
ret = 0;
- if ((idd->proto_codeset & SVPD_ID_CODESET_MASK) == SVPD_ID_CODESET_ASCII) {
+ if ((idd->proto_codeset & SVPD_ID_CODESET_MASK) ==
+ SVPD_ID_CODESET_ASCII) {
if (idd->length < len) {
for (l = 0; l < idd->length; l++)
buf[l] = idd->identifier[l] ?
@@ -1307,40 +1314,50 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
buf[l] = 0;
} else
ret = EFAULT;
- } else if ((idd->proto_codeset & SVPD_ID_CODESET_MASK) == SVPD_ID_CODESET_UTF8) {
+ break;
+ }
+ if ((idd->proto_codeset & SVPD_ID_CODESET_MASK) ==
+ SVPD_ID_CODESET_UTF8) {
l = strnlen(idd->identifier, idd->length);
if (l < len) {
bcopy(idd->identifier, buf, l);
buf[l] = 0;
} else
ret = EFAULT;
- } else if ((idd->id_type & SVPD_ID_TYPE_MASK) == SVPD_ID_TYPE_UUID
- && idd->identifier[0] == 0x10) {
- if ((idd->length - 2) * 2 + 4 < len) {
- for (l = 2, o = 0; l < idd->length; l++) {
- if (l == 6 || l == 8 || l == 10 || l == 12)
- o += sprintf(buf + o, "-");
- o += sprintf(buf + o, "%02x",
- idd->identifier[l]);
- }
- } else
- ret = EFAULT;
- } else {
- if (idd->length * 2 < len) {
- for (l = 0; l < idd->length; l++)
- sprintf(buf + l * 2, "%02x",
- idd->identifier[l]);
- } else
+ break;
+ }
+ if ((idd->id_type & SVPD_ID_TYPE_MASK) ==
+ SVPD_ID_TYPE_UUID && idd->identifier[0] == 0x10) {
+ if ((idd->length - 2) * 2 + 4 >= len) {
ret = EFAULT;
+ break;
+ }
+ for (l = 2, o = 0; l < idd->length; l++) {
+ if (l == 6 || l == 8 || l == 10 || l == 12)
+ o += sprintf(buf + o, "-");
+ o += sprintf(buf + o, "%02x",
+ idd->identifier[l]);
+ }
+ break;
}
- } else {
- ret = 0;
- if (strlcpy(buf, cdai.buf, len) >= len)
+ if (idd->length * 2 < len) {
+ for (l = 0; l < idd->length; l++)
+ sprintf(buf + l * 2, "%02x",
+ idd->identifier[l]);
+ } else
+ ret = EFAULT;
+ break;
+ default:
+ if (cdai.provsiz < len) {
+ cdai.buf[cdai.provsiz] = 0;
+ ret = 0;
+ } else
ret = EFAULT;
+ break;
}
out:
- if (cdai.buf != NULL)
+ if ((char *)cdai.buf != buf)
free(cdai.buf, M_CAMXPT);
return ret;
}
diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c
index 17e9e3a51d80..dae4deb9e5e7 100644
--- a/sys/cam/ctl/ctl_error.c
+++ b/sys/cam/ctl/ctl_error.c
@@ -81,6 +81,12 @@ ctl_set_sense_data_va(struct scsi_sense_data *sense_data, u_int *sense_len,
*/
if (sense_format == SSD_TYPE_NONE) {
/*
+ * SPC-3 and up require some UAs to be returned as fixed.
+ */
+ if (asc == 0x29 || (asc == 0x2A && ascq == 0x01))
+ sense_format = SSD_TYPE_FIXED;
+ else
+ /*
* If the format isn't specified, we only return descriptor
* sense if the LUN exists and descriptor sense is turned
* on for that LUN.
diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c
index 1d92c4d8e915..5ab37e3f6416 100644
--- a/sys/cam/scsi/scsi_all.c
+++ b/sys/cam/scsi/scsi_all.c
@@ -5574,6 +5574,7 @@ scsi_devid_is_naa_ieee_reg(uint8_t *bufp)
{
struct scsi_vpd_id_descriptor *descr;
struct scsi_vpd_id_naa_basic *naa;
+ int n;
descr = (struct scsi_vpd_id_descriptor *)bufp;
naa = (struct scsi_vpd_id_naa_basic *)descr->identifier;
@@ -5581,7 +5582,8 @@ scsi_devid_is_naa_ieee_reg(uint8_t *bufp)
return 0;
if (descr->length < sizeof(struct scsi_vpd_id_naa_ieee_reg))
return 0;
- if ((naa->naa >> SVPD_ID_NAA_NAA_SHIFT) != SVPD_ID_NAA_IEEE_REG)
+ n = naa->naa >> SVPD_ID_NAA_NAA_SHIFT;
+ if (n != SVPD_ID_NAA_LOCAL_REG && n != SVPD_ID_NAA_IEEE_REG)
return 0;
return 1;
}
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index a89c40e19a7b..f2f60d35b2e2 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -64,6 +64,9 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_ccb.h>
#include <cam/cam_periph.h>
#include <cam/cam_xpt_periph.h>
+#ifdef _KERNEL
+#include <cam/cam_xpt_internal.h>
+#endif /* _KERNEL */
#include <cam/cam_sim.h>
#include <cam/cam_iosched.h>
@@ -3613,15 +3616,7 @@ out:
break;
}
- ata_params = (struct ata_params*)
- malloc(sizeof(*ata_params), M_SCSIDA,M_NOWAIT|M_ZERO);
-
- if (ata_params == NULL) {
- xpt_print(periph->path, "Couldn't malloc ata_params "
- "data\n");
- /* da_free_periph??? */
- break;
- }
+ ata_params = &periph->path->device->ident_data;
scsi_ata_identify(&start_ccb->csio,
/*retries*/da_retry_count,
@@ -5192,7 +5187,7 @@ dadone_probeata(struct cam_periph *periph, union ccb *done_ccb)
struct da_softc *softc;
u_int32_t priority;
int continue_probe;
- int error, i;
+ int error;
int16_t *ptr;
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone_probeata\n"));
@@ -5210,8 +5205,7 @@ dadone_probeata(struct cam_periph *periph, union ccb *done_ccb)
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
uint16_t old_rate;
- for (i = 0; i < sizeof(*ata_params) / 2; i++)
- ptr[i] = le16toh(ptr[i]);
+ ata_param_fixup(ata_params);
if (ata_params->support_dsm & ATA_SUPPORT_DSM_TRIM &&
(softc->quirks & DA_Q_NO_UNMAP) == 0) {
dadeleteflag(softc, DA_DELETE_ATA_TRIM, 1);
@@ -5295,7 +5289,6 @@ dadone_probeata(struct cam_periph *periph, union ccb *done_ccb)
}
}
- free(ata_params, M_SCSIDA);
if ((softc->zone_mode == DA_ZONE_HOST_AWARE)
|| (softc->zone_mode == DA_ZONE_HOST_MANAGED)) {
/*
diff --git a/sys/cam/scsi/scsi_enc.c b/sys/cam/scsi/scsi_enc.c
index 363f27db5f78..ec190232fff9 100644
--- a/sys/cam/scsi/scsi_enc.c
+++ b/sys/cam/scsi/scsi_enc.c
@@ -81,6 +81,17 @@ static enctyp enc_type(struct ccb_getdev *);
SYSCTL_NODE(_kern_cam, OID_AUTO, enc, CTLFLAG_RD, 0,
"CAM Enclosure Services driver");
+#if defined(DEBUG) || defined(ENC_DEBUG)
+int enc_verbose = 1;
+#else
+int enc_verbose = 0;
+#endif
+SYSCTL_INT(_kern_cam_enc, OID_AUTO, verbose, CTLFLAG_RWTUN,
+ &enc_verbose, 0, "Enable verbose logging");
+
+const char *elm_type_names[] = ELM_TYPE_NAMES;
+CTASSERT(nitems(elm_type_names) - 1 == ELMTYP_LAST);
+
static struct periph_driver encdriver = {
enc_init, "ses",
TAILQ_HEAD_INITIALIZER(encdriver.units), /* generation */ 0
@@ -232,11 +243,17 @@ enc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
struct enc_softc *softc;
softc = (struct enc_softc *)periph->softc;
- if (xpt_path_path_id(periph->path) != path_id
- || softc == NULL
- || (softc->enc_flags & ENC_FLAG_INITIALIZED)
- == 0
- || softc->enc_vec.device_found == NULL)
+
+ /* Check this SEP is ready. */
+ if (softc == NULL || (softc->enc_flags &
+ ENC_FLAG_INITIALIZED) == 0 ||
+ softc->enc_vec.device_found == NULL)
+ continue;
+
+ /* Check this SEP may manage this device. */
+ if (xpt_path_path_id(periph->path) != path_id &&
+ (softc->enc_type != ENC_SEMB_SES ||
+ cgd->protocol != PROTO_ATA))
continue;
softc->enc_vec.device_found(softc);
@@ -432,7 +449,7 @@ enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag,
encioc_element_t kelm;
kelm.elm_idx = i;
kelm.elm_subenc_id = cache->elm_map[i].subenclosure;
- kelm.elm_type = cache->elm_map[i].enctype;
+ kelm.elm_type = cache->elm_map[i].elm_type;
error = copyout(&kelm, &uelm[i], sizeof(kelm));
if (error)
break;
@@ -684,14 +701,8 @@ enc_type(struct ccb_getdev *cgd)
buflen = min(sizeof(cgd->inq_data),
SID_ADDITIONAL_LENGTH(&cgd->inq_data));
- if ((iqd[0] & 0x1f) == T_ENCLOSURE) {
- if ((iqd[2] & 0x7) > 2) {
- return (ENC_SES);
- } else {
- return (ENC_SES_SCSI2);
- }
- return (ENC_NONE);
- }
+ if ((iqd[0] & 0x1f) == T_ENCLOSURE)
+ return (ENC_SES);
#ifdef SES_ENABLE_PASSTHROUGH
if ((iqd[6] & 0x40) && (iqd[2] & 0x7) >= 2) {
@@ -928,7 +939,6 @@ enc_ctor(struct cam_periph *periph, void *arg)
switch (enc->enc_type) {
case ENC_SES:
- case ENC_SES_SCSI2:
case ENC_SES_PASSTHROUGH:
case ENC_SEMB_SES:
err = ses_softc_init(enc);
@@ -1017,17 +1027,14 @@ enc_ctor(struct cam_periph *periph, void *arg)
case ENC_NONE:
tname = "No ENC device";
break;
- case ENC_SES_SCSI2:
- tname = "SCSI-2 ENC Device";
- break;
case ENC_SES:
- tname = "SCSI-3 ENC Device";
+ tname = "SES Device";
break;
case ENC_SES_PASSTHROUGH:
- tname = "ENC Passthrough Device";
+ tname = "SES Passthrough Device";
break;
case ENC_SAFT:
- tname = "SAF-TE Compliant Device";
+ tname = "SAF-TE Device";
break;
case ENC_SEMB_SES:
tname = "SEMB SES Device";
diff --git a/sys/cam/scsi/scsi_enc.h b/sys/cam/scsi/scsi_enc.h
index fc7e3bd3f1c6..f9abe099e337 100644
--- a/sys/cam/scsi/scsi_enc.h
+++ b/sys/cam/scsi/scsi_enc.h
@@ -120,10 +120,42 @@ typedef enum {
ELMTYP_SCSI_INI = 0x15,
ELMTYP_SUBENC = 0x16,
ELMTYP_ARRAY_DEV = 0x17,
- ELMTYP_SAS_EXP = 0x18, /* SAS expander */
- ELMTYP_SAS_CONN = 0x19 /* SAS connector */
+ ELMTYP_SAS_EXP = 0x18, /* SAS Expander */
+ ELMTYP_SAS_CONN = 0x19, /* SAS Connector */
+ ELMTYP_LAST = ELMTYP_SAS_CONN
} elm_type_t;
+#define ELM_TYPE_NAMES { \
+ "Unspecified", \
+ "Device Slot", \
+ "Power Supply", \
+ "Cooling", \
+ "Temperature Sensors", \
+ "Door", \
+ "Audible alarm", \
+ "Enclosure Services Controller Electronics", \
+ "SCC Controller Electronics", \
+ "Nonvolatile Cache", \
+ "Invalid Operation Reason", \
+ "Uninterruptible Power Supply", \
+ "Display", \
+ "Key Pad Entry", \
+ "Enclosure", \
+ "SCSI Port/Transceiver", \
+ "Language", \
+ "Communication Port", \
+ "Voltage Sensor", \
+ "Current Sensor", \
+ "SCSI Target Port", \
+ "SCSI Initiator Port", \
+ "Simple Subenclosure", \
+ "Array Device Slot", \
+ "SAS Expander", \
+ "SAS Connector" \
+}
+
+extern const char *elm_type_names[];
+
typedef struct encioc_element {
/* Element Index */
unsigned int elm_idx;
diff --git a/sys/cam/scsi/scsi_enc_internal.h b/sys/cam/scsi/scsi_enc_internal.h
index 0d4bdffda4f9..293da3ee7386 100644
--- a/sys/cam/scsi/scsi_enc_internal.h
+++ b/sys/cam/scsi/scsi_enc_internal.h
@@ -36,17 +36,15 @@
#ifndef __SCSI_ENC_INTERNAL_H__
#define __SCSI_ENC_INTERNAL_H__
+#include <sys/sysctl.h>
+
typedef struct enc_element {
- uint32_t
- enctype : 8, /* enclosure type */
- subenclosure : 8, /* subenclosure id */
- svalid : 1, /* enclosure information valid */
- overall_status_elem: 1,/*
- * This object represents generic
- * status about all objects of this
- * type.
- */
- priv : 14; /* private data, per object */
+ uint8_t elm_idx; /* index of element */
+ uint8_t elm_type; /* element type */
+ uint8_t subenclosure; /* subenclosure id */
+ uint8_t type_elm_idx; /* index of element within type */
+ uint8_t svalid; /* enclosure information valid */
+ uint16_t priv; /* private data, per object */
uint8_t encstat[4]; /* state && stats */
uint8_t *physical_path; /* Device physical path data. */
u_int physical_path_len; /* Length of device path data. */
@@ -55,10 +53,8 @@ typedef struct enc_element {
typedef enum {
ENC_NONE,
- ENC_SES_SCSI2,
ENC_SES,
ENC_SES_PASSTHROUGH,
- ENC_SEN,
ENC_SAFT,
ENC_SEMB_SES,
ENC_SEMB_SAFT
@@ -206,6 +202,9 @@ enc_softc_init_t ses_softc_init;
/* SAF-TE interface */
enc_softc_init_t safte_softc_init;
+SYSCTL_DECL(_kern_cam_enc);
+extern int enc_verbose;
+
/* Helper macros */
MALLOC_DECLARE(M_SCSIENC);
#define ENC_CFLAGS CAM_RETRY_SELTO
@@ -218,7 +217,7 @@ MALLOC_DECLARE(M_SCSIENC);
#else
#define ENC_DLOG if (0) enc_log
#endif
-#define ENC_VLOG if (bootverbose) enc_log
+#define ENC_VLOG if (enc_verbose) enc_log
#define ENC_MALLOC(amt) malloc(amt, M_SCSIENC, M_NOWAIT)
#define ENC_MALLOCZ(amt) malloc(amt, M_SCSIENC, M_ZERO|M_NOWAIT)
/* Cast away const avoiding GCC warnings. */
diff --git a/sys/cam/scsi/scsi_enc_safte.c b/sys/cam/scsi/scsi_enc_safte.c
index 8afcc323991a..94219cde7a89 100644
--- a/sys/cam/scsi/scsi_enc_safte.c
+++ b/sys/cam/scsi/scsi_enc_safte.c
@@ -227,7 +227,6 @@ static char *safte_2little = "Too Little Data Returned (%d) at line %d\n";
}
int emulate_array_devices = 1;
-SYSCTL_DECL(_kern_cam_enc);
SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RWTUN,
&emulate_array_devices, 0, "Emulate Array Devices for SAF-TE");
@@ -302,21 +301,21 @@ safte_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
* in later fetches of status.
*/
for (i = 0; i < cfg->Nfans; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_FAN;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_FAN;
cfg->pwroff = (uint8_t) r;
for (i = 0; i < cfg->Npwr; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_POWER;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_POWER;
for (i = 0; i < cfg->DoorLock; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_DOORLOCK;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_DOORLOCK;
if (cfg->Nspkrs > 0)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_ALARM;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_ALARM;
for (i = 0; i < cfg->Ntherm; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
for (i = 0; i <= cfg->Ntstats; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
cfg->slotoff = (uint8_t) r;
for (i = 0; i < cfg->Nslots; i++)
- enc->enc_cache.elm_map[r++].enctype =
+ enc->enc_cache.elm_map[r++].elm_type =
emulate_array_devices ? ELMTYP_ARRAY_DEV :
ELMTYP_DEVICE;
@@ -506,7 +505,7 @@ safte_process_status(enc_softc_t *enc, struct enc_fsm_state *state,
*/
for (i = 0; i < cfg->Nslots; i++) {
SAFT_BAIL(r, xfer_len);
- if (cache->elm_map[cfg->slotoff + i].enctype == ELMTYP_DEVICE)
+ if (cache->elm_map[cfg->slotoff + i].elm_type == ELMTYP_DEVICE)
cache->elm_map[cfg->slotoff + i].encstat[1] = buf[r];
r++;
}
@@ -679,7 +678,7 @@ safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
oid = cfg->slotoff;
for (r = i = 0; i < cfg->Nslots; i++, r += 4) {
SAFT_BAIL(r+3, xfer_len);
- if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV)
+ if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV)
cache->elm_map[oid].encstat[1] = 0;
cache->elm_map[oid].encstat[2] &= SESCTL_RQSID;
cache->elm_map[oid].encstat[3] = 0;
@@ -706,7 +705,7 @@ safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT;
if (buf[r+0] & 0x40)
cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL;
- if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV) {
+ if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV) {
if (buf[r+0] & 0x01)
cache->elm_map[oid].encstat[1] |= 0x80;
if (buf[r+0] & 0x04)
@@ -772,7 +771,7 @@ safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
} else {
ep = &enc->enc_cache.elm_map[idx];
- switch (ep->enctype) {
+ switch (ep->elm_type) {
case ELMTYP_DEVICE:
case ELMTYP_ARRAY_DEV:
switch (cfg->current_request_stage) {
@@ -782,7 +781,7 @@ safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
ep->priv |= 0x40;
if (req->elm_stat[3] & SESCTL_RQSFLT)
ep->priv |= 0x02;
- if (ep->enctype == ELMTYP_ARRAY_DEV) {
+ if (ep->elm_type == ELMTYP_ARRAY_DEV) {
if (req->elm_stat[1] & 0x01)
ep->priv |= 0x200;
if (req->elm_stat[1] & 0x02)
@@ -971,7 +970,7 @@ safte_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
if (idx == SES_SETSTATUS_ENC_IDX)
type = -1;
else
- type = enc->enc_cache.elm_map[idx].enctype;
+ type = enc->enc_cache.elm_map[idx].elm_type;
if (type == ELMTYP_DEVICE || type == ELMTYP_ARRAY_DEV)
enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
else
diff --git a/sys/cam/scsi/scsi_enc_ses.c b/sys/cam/scsi/scsi_enc_ses.c
index 5e9d2dc94d2d..e5a18d5d9a45 100644
--- a/sys/cam/scsi/scsi_enc_ses.c
+++ b/sys/cam/scsi/scsi_enc_ses.c
@@ -102,6 +102,7 @@ typedef struct ses_addl_status {
union {
union ses_fcobj_hdr *fc;
union ses_elm_sas_hdr *sas;
+ struct ses_elm_ata_hdr *ata;
} proto_hdr;
union ses_addl_data proto_data; /* array sizes stored in header */
} ses_add_status_t;
@@ -444,6 +445,7 @@ ses_iter_next(struct ses_iterator *iter)
iter->type_element_index = ITERATOR_INDEX_END;
iter->global_element_index = ITERATOR_INDEX_END;
iter->individual_element_index = ITERATOR_INDEX_END;
+ iter->saved_individual_element_index = ITERATOR_INDEX_END;
return (NULL);
}
@@ -468,17 +470,12 @@ ses_iter_next(struct ses_iterator *iter)
*/
iter->type_index++;
iter->type_element_index = 0;
- iter->saved_individual_element_index
- = iter->individual_element_index;
iter->individual_element_index = ITERATOR_INDEX_INVALID;
}
if (iter->type_element_index > 0) {
- if (iter->type_element_index == 1) {
- iter->individual_element_index
- = iter->saved_individual_element_index;
- }
- iter->individual_element_index++;
+ iter->individual_element_index =
+ ++iter->saved_individual_element_index;
}
return (&iter->cache->elm_map[iter->global_element_index]);
@@ -829,14 +826,6 @@ ses_devids_iter(enc_softc_t *enc, enc_element_t *elm,
elmpriv = elm->elm_private;
addl = &(elmpriv->addl);
- /*
- * Don't assume this object has additional status information, or
- * that it is a SAS device, or that it is a device slot device.
- */
- if (addl->hdr == NULL || addl->proto_hdr.sas == NULL
- || addl->proto_data.sasdev_phys == NULL)
- return;
-
devid_record_size = SVPD_DEVICE_ID_DESC_HDR_LEN
+ sizeof(struct scsi_vpd_id_naa_ieee_reg);
for (i = 0; i < addl->proto_hdr.sas->base_hdr.num_phys; i++) {
@@ -954,11 +943,40 @@ static void
ses_paths_iter(enc_softc_t *enc, enc_element_t *elm,
ses_path_callback_t *callback, void *callback_arg)
{
- ses_path_iter_args_t args;
+ ses_element_t *elmpriv;
+ struct ses_addl_status *addl;
+
+ elmpriv = elm->elm_private;
+ addl = &(elmpriv->addl);
+
+ if (addl->hdr == NULL)
+ return;
- args.callback = callback;
- args.callback_arg = callback_arg;
- ses_devids_iter(enc, elm, ses_path_iter_devid_callback, &args);
+ if (addl->proto_hdr.sas != NULL &&
+ addl->proto_data.sasdev_phys != NULL) {
+ ses_path_iter_args_t args;
+
+ args.callback = callback;
+ args.callback_arg = callback_arg;
+ ses_devids_iter(enc, elm, ses_path_iter_devid_callback, &args);
+ } else if (addl->proto_hdr.ata != NULL) {
+ struct cam_path *path;
+ struct ccb_getdev cgd;
+
+ if (xpt_create_path(&path, /*periph*/NULL,
+ scsi_4btoul(addl->proto_hdr.ata->bus),
+ scsi_4btoul(addl->proto_hdr.ata->target), 0)
+ != CAM_REQ_CMP)
+ return;
+
+ xpt_setup_ccb(&cgd.ccb_h, path, CAM_PRIORITY_NORMAL);
+ cgd.ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action((union ccb *)&cgd);
+ if (cgd.ccb_h.status == CAM_REQ_CMP)
+ callback(enc, elm, path, callback_arg);
+
+ xpt_free_path(path);
+ }
}
/**
@@ -1063,6 +1081,10 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
ret = EIO;
devid = NULL;
+ elmpriv = elm->elm_private;
+ if (elmpriv->addl.hdr == NULL)
+ goto out;
+
/*
* Assemble the components of the physical path starting with
* the device ID of the enclosure itself.
@@ -1095,7 +1117,6 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
scsi_8btou64(idd->identifier), iter->type_index,
iter->type_element_index);
/* Append the element descriptor if one exists */
- elmpriv = elm->elm_private;
if (elmpriv->descr != NULL && elmpriv->descr_len > 0) {
sbuf_cat(&sb, "/elmdesc@");
for (i = 0, c = elmpriv->descr; i < elmpriv->descr_len;
@@ -1461,9 +1482,10 @@ ses_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
iter.global_element_index, iter.type_index, nelm,
iter.type_element_index);
thdr = ses_cache->ses_types[iter.type_index].hdr;
+ element->elm_idx = iter.global_element_index;
+ element->elm_type = thdr->etype_elm_type;
element->subenclosure = thdr->etype_subenc;
- element->enctype = thdr->etype_elm_type;
- element->overall_status_elem = iter.type_element_index == 0;
+ element->type_elm_idx = iter.type_element_index;
element->elm_private = malloc(sizeof(ses_element_t),
M_SCSIENC, M_WAITOK|M_ZERO);
ENC_DLOG(enc, "%s: creating elmpriv %d(%d,%d) subenc %d "
@@ -1667,6 +1689,8 @@ static int ses_get_elm_addlstatus_fc(enc_softc_t *, enc_cache_t *,
uint8_t *, int);
static int ses_get_elm_addlstatus_sas(enc_softc_t *, enc_cache_t *, uint8_t *,
int, int, int, int);
+static int ses_get_elm_addlstatus_ata(enc_softc_t *, enc_cache_t *, uint8_t *,
+ int, int, int, int);
/**
* \brief Parse the additional status element data for each object.
@@ -1685,7 +1709,6 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
struct ses_iterator iter, titer;
int eip;
int err;
- int ignore_index = 0;
int length;
int offset;
enc_cache_t *enc_cache;
@@ -1756,7 +1779,7 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
elm_hdr = (struct ses_elm_addlstatus_base_hdr *)&buf[offset];
eip = ses_elm_addlstatus_eip(elm_hdr);
- if (eip && !ignore_index) {
+ if (eip) {
struct ses_elm_addlstatus_eip_hdr *eip_hdr;
int expected_index, index;
ses_elem_index_type_t index_type;
@@ -1769,17 +1792,44 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
index_type = SES_ELEM_INDEX_INDIVIDUAL;
expected_index = iter.individual_element_index;
}
+ if (eip_hdr->element_index < expected_index) {
+ ENC_VLOG(enc, "%s: provided %selement index "
+ "%d is lower then expected %d\n",
+ __func__, (eip_hdr->byte2 &
+ SES_ADDL_EIP_EIIOE) ? "global " : "",
+ eip_hdr->element_index, expected_index);
+ goto badindex;
+ }
titer = iter;
telement = ses_iter_seek_to(&titer,
eip_hdr->element_index, index_type);
- if (telement != NULL &&
- (ses_typehasaddlstatus(enc, titer.type_index) !=
- TYPE_ADDLSTATUS_NONE ||
- titer.type_index > ELMTYP_SAS_CONN)) {
+ if (telement == NULL) {
+ ENC_VLOG(enc, "%s: provided %selement index "
+ "%d does not exist\n", __func__,
+ (eip_hdr->byte2 & SES_ADDL_EIP_EIIOE) ?
+ "global " : "", eip_hdr->element_index);
+ goto badindex;
+ }
+ if (ses_typehasaddlstatus(enc, titer.type_index) ==
+ TYPE_ADDLSTATUS_NONE) {
+ ENC_VLOG(enc, "%s: provided %selement index "
+ "%d can't have additional status\n",
+ __func__,
+ (eip_hdr->byte2 & SES_ADDL_EIP_EIIOE) ?
+ "global " : "", eip_hdr->element_index);
+badindex:
+ /*
+ * If we expected mandatory element, we may
+ * guess it was just a wrong index and we may
+ * use the status. If element was optional,
+ * then we have no idea where status belongs.
+ */
+ if (status_type == TYPE_ADDLSTATUS_OPTIONAL)
+ break;
+ } else {
iter = titer;
element = telement;
- } else
- ignore_index = 1;
+ }
if (eip_hdr->byte2 & SES_ADDL_EIP_EIIOE)
index = iter.global_element_index;
@@ -1796,40 +1846,46 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
}
}
elmpriv = element->elm_private;
- elmpriv->addl.hdr = elm_hdr;
ENC_DLOG(enc, "%s: global element index=%d, type index=%d "
"type element index=%d, offset=0x%x, "
"byte0=0x%x, length=0x%x\n", __func__,
iter.global_element_index, iter.type_index,
- iter.type_element_index, offset, elmpriv->addl.hdr->byte0,
- elmpriv->addl.hdr->length);
+ iter.type_element_index, offset, elm_hdr->byte0,
+ elm_hdr->length);
/* Skip to after the length field */
offset += sizeof(struct ses_elm_addlstatus_base_hdr);
/* Make sure the descriptor is within bounds */
- if ((offset + elmpriv->addl.hdr->length) > length) {
+ if ((offset + elm_hdr->length) > length) {
ENC_VLOG(enc, "Element %d Beyond End "
"of Additional Element Status Descriptors\n",
iter.global_element_index);
break;
}
+ /* Skip elements marked as invalid. */
+ if (ses_elm_addlstatus_invalid(elm_hdr)) {
+ offset += elm_hdr->length;
+ continue;
+ }
+ elmpriv->addl.hdr = elm_hdr;
+
/* Advance to the protocol data, skipping eip bytes if needed */
offset += (eip * SES_EIP_HDR_EXTRA_LEN);
- proto_info_len = elmpriv->addl.hdr->length
+ proto_info_len = elm_hdr->length
- (eip * SES_EIP_HDR_EXTRA_LEN);
/* Errors in this block are ignored as they are non-fatal */
- switch(ses_elm_addlstatus_proto(elmpriv->addl.hdr)) {
+ switch(ses_elm_addlstatus_proto(elm_hdr)) {
case SPSP_PROTO_FC:
- if (elmpriv->addl.hdr->length == 0)
+ if (elm_hdr->length == 0)
break;
ses_get_elm_addlstatus_fc(enc, enc_cache,
&buf[offset], proto_info_len);
break;
case SPSP_PROTO_SAS:
- if (elmpriv->addl.hdr->length <= 2)
+ if (elm_hdr->length <= 2)
break;
ses_get_elm_addlstatus_sas(enc, enc_cache,
&buf[offset],
@@ -1837,10 +1893,17 @@ ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
eip, iter.type_index,
iter.global_element_index);
break;
+ case SPSP_PROTO_ATA:
+ ses_get_elm_addlstatus_ata(enc, enc_cache,
+ &buf[offset],
+ proto_info_len,
+ eip, iter.type_index,
+ iter.global_element_index);
+ break;
default:
ENC_VLOG(enc, "Element %d: Unknown Additional Element "
"Protocol 0x%x\n", iter.global_element_index,
- ses_elm_addlstatus_proto(elmpriv->addl.hdr));
+ ses_elm_addlstatus_proto(elm_hdr));
break;
}
@@ -2165,18 +2228,16 @@ ses_get_elm_addlstatus_fc(enc_softc_t *enc, enc_cache_t *enc_cache,
}
#define SES_PRINT_PORTS(p, type) do { \
- sbuf_printf(sbp, " %s(", type); \
- if (((p) & SES_SASOBJ_DEV_PHY_PROTOMASK) == 0) \
- sbuf_printf(sbp, " None"); \
- else { \
+ if (((p) & SES_SASOBJ_DEV_PHY_PROTOMASK) != 0) { \
+ sbuf_printf(sbp, " %s (", type); \
if ((p) & SES_SASOBJ_DEV_PHY_SMP) \
sbuf_printf(sbp, " SMP"); \
if ((p) & SES_SASOBJ_DEV_PHY_STP) \
sbuf_printf(sbp, " STP"); \
if ((p) & SES_SASOBJ_DEV_PHY_SSP) \
sbuf_printf(sbp, " SSP"); \
+ sbuf_printf(sbp, " )"); \
} \
- sbuf_printf(sbp, " )"); \
} while(0)
/**
@@ -2186,11 +2247,10 @@ ses_get_elm_addlstatus_fc(enc_softc_t *enc, enc_cache_t *enc_cache,
* \param sesname SES device name associated with the object.
* \param sbp Sbuf to print to.
* \param obj The object to print the data for.
- * \param periph_name Peripheral string associated with the object.
*/
static void
ses_print_addl_data_sas_type0(char *sesname, struct sbuf *sbp,
- enc_element_t *obj, char *periph_name)
+ enc_element_t *obj)
{
int i;
ses_element_t *elmpriv;
@@ -2199,16 +2259,12 @@ ses_print_addl_data_sas_type0(char *sesname, struct sbuf *sbp,
elmpriv = obj->elm_private;
addl = &(elmpriv->addl);
- if (addl->proto_hdr.sas == NULL)
- return;
- sbuf_printf(sbp, "%s: %s: SAS Device Slot Element:",
- sesname, periph_name);
- sbuf_printf(sbp, " %d Phys", addl->proto_hdr.sas->base_hdr.num_phys);
+ sbuf_printf(sbp, ", SAS Slot: %d%s phys",
+ addl->proto_hdr.sas->base_hdr.num_phys,
+ ses_elm_sas_type0_not_all_phys(addl->proto_hdr.sas) ? "+" : "");
if (ses_elm_addlstatus_eip(addl->hdr))
- sbuf_printf(sbp, " at Slot %d",
+ sbuf_printf(sbp, " at slot %d",
addl->proto_hdr.sas->type0_eip.dev_slot_num);
- if (ses_elm_sas_type0_not_all_phys(addl->proto_hdr.sas))
- sbuf_printf(sbp, ", Not All Phys");
sbuf_printf(sbp, "\n");
if (addl->proto_data.sasdev_phys == NULL)
return;
@@ -2219,9 +2275,8 @@ ses_print_addl_data_sas_type0(char *sesname, struct sbuf *sbp,
/* Spec says all other fields are specific values */
sbuf_printf(sbp, " SATA device\n");
else {
- sbuf_printf(sbp, " SAS device type %d id %d\n",
+ sbuf_printf(sbp, " SAS device type %d phy %d",
ses_elm_sas_dev_phy_dev_type(phy), phy->phy_id);
- sbuf_printf(sbp, "%s: phy %d: protocols:", sesname, i);
SES_PRINT_PORTS(phy->initiator_ports, "Initiator");
SES_PRINT_PORTS(phy->target_ports, "Target");
sbuf_printf(sbp, "\n");
@@ -2235,32 +2290,16 @@ ses_print_addl_data_sas_type0(char *sesname, struct sbuf *sbp,
#undef SES_PRINT_PORTS
/**
- * \brief Report whether a given enclosure object is an expander.
- *
- * \param enc SES softc associated with object.
- * \param obj Enclosure object to report for.
- *
- * \return 1 if true, 0 otherwise.
- */
-static int
-ses_obj_is_expander(enc_softc_t *enc, enc_element_t *obj)
-{
- return (obj->enctype == ELMTYP_SAS_EXP);
-}
-
-/**
* \brief Print the additional element status data for this object, for SAS
* type 1 objects. See SES2 r20 Sections 6.1.13.3.3 and 6.1.13.3.4.
*
- * \param enc SES enclosure, needed for type identification.
* \param sesname SES device name associated with the object.
* \param sbp Sbuf to print to.
* \param obj The object to print the data for.
- * \param periph_name Peripheral string associated with the object.
*/
static void
-ses_print_addl_data_sas_type1(enc_softc_t *enc, char *sesname,
- struct sbuf *sbp, enc_element_t *obj, char *periph_name)
+ses_print_addl_data_sas_type1(char *sesname, struct sbuf *sbp,
+ enc_element_t *obj)
{
int i, num_phys;
ses_element_t *elmpriv;
@@ -2270,12 +2309,10 @@ ses_print_addl_data_sas_type1(enc_softc_t *enc, char *sesname,
elmpriv = obj->elm_private;
addl = &(elmpriv->addl);
- if (addl->proto_hdr.sas == NULL)
- return;
- sbuf_printf(sbp, "%s: %s: SAS ", sesname, periph_name);
- if (ses_obj_is_expander(enc, obj)) {
+ sbuf_printf(sbp, ", SAS ");
+ if (obj->elm_type == ELMTYP_SAS_EXP) {
num_phys = addl->proto_hdr.sas->base_hdr.num_phys;
- sbuf_printf(sbp, "Expander: %d Phys", num_phys);
+ sbuf_printf(sbp, "Expander: %d phys", num_phys);
if (addl->proto_data.sasexp_phys == NULL)
return;
for (i = 0;i < num_phys;i++) {
@@ -2286,7 +2323,7 @@ ses_print_addl_data_sas_type1(enc_softc_t *enc, char *sesname,
}
} else {
num_phys = addl->proto_hdr.sas->base_hdr.num_phys;
- sbuf_printf(sbp, "Port: %d Phys", num_phys);
+ sbuf_printf(sbp, "Port: %d phys", num_phys);
if (addl->proto_data.sasport_phys == NULL)
return;
for (i = 0;i < num_phys;i++) {
@@ -2302,6 +2339,24 @@ ses_print_addl_data_sas_type1(enc_softc_t *enc, char *sesname,
}
/**
+ * \brief Print the additional element status data for this object, for
+ * ATA objects.
+ *
+ * \param sbp Sbuf to print to.
+ * \param obj The object to print the data for.
+ */
+static void
+ses_print_addl_data_ata(struct sbuf *sbp, enc_element_t *obj)
+{
+ ses_element_t *elmpriv = obj->elm_private;
+ struct ses_addl_status *addl = &elmpriv->addl;
+ struct ses_elm_ata_hdr *ata = addl->proto_hdr.ata;
+
+ sbuf_printf(sbp, ", SATA Slot: scbus%d target %d\n",
+ scsi_4btoul(ata->bus), scsi_4btoul(ata->target));
+}
+
+/**
* \brief Print the additional element status data for this object.
*
* \param enc SES softc associated with the object.
@@ -2332,27 +2387,45 @@ ses_print_addl_data(enc_softc_t *enc, enc_element_t *obj)
sbuf_printf(&sesname, "%s%d", enc->periph->periph_name,
enc->periph->unit_number);
sbuf_finish(&sesname);
+ sbuf_printf(&out, "%s: %s in ", sbuf_data(&sesname), sbuf_data(&name));
if (elmpriv->descr != NULL)
- sbuf_printf(&out, "%s: %s: Element descriptor: '%s'\n",
- sbuf_data(&sesname), sbuf_data(&name), elmpriv->descr);
+ sbuf_printf(&out, "'%s'", elmpriv->descr);
+ else {
+ if (obj->elm_type <= ELMTYP_LAST)
+ sbuf_cat(&out, elm_type_names[obj->elm_type]);
+ else
+ sbuf_printf(&out, "<Type 0x%02x>", obj->elm_type);
+ sbuf_printf(&out, " %d", obj->type_elm_idx);
+ if (obj->subenclosure != 0)
+ sbuf_printf(&out, " of subenc %d", obj->subenclosure);
+ }
switch(ses_elm_addlstatus_proto(addl->hdr)) {
+ case SPSP_PROTO_FC:
+ goto noaddl; /* stubbed for now */
case SPSP_PROTO_SAS:
+ if (addl->proto_hdr.sas == NULL)
+ goto noaddl;
switch(ses_elm_sas_descr_type(addl->proto_hdr.sas)) {
case SES_SASOBJ_TYPE_SLOT:
ses_print_addl_data_sas_type0(sbuf_data(&sesname),
- &out, obj, sbuf_data(&name));
+ &out, obj);
break;
case SES_SASOBJ_TYPE_OTHER:
- ses_print_addl_data_sas_type1(enc, sbuf_data(&sesname),
- &out, obj, sbuf_data(&name));
+ ses_print_addl_data_sas_type1(sbuf_data(&sesname),
+ &out, obj);
break;
default:
- break;
+ goto noaddl;
}
break;
- case SPSP_PROTO_FC: /* stubbed for now */
+ case SPSP_PROTO_ATA:
+ if (addl->proto_hdr.ata == NULL)
+ goto noaddl;
+ ses_print_addl_data_ata(&out, obj);
break;
default:
+noaddl:
+ sbuf_cat(&out, "\n");
break;
}
sbuf_finish(&out);
@@ -2457,7 +2530,7 @@ ses_get_elm_addlstatus_sas_type1(enc_softc_t *enc, enc_cache_t *enc_cache,
goto out;
/* Process expanders differently from other type1 cases */
- if (ses_obj_is_expander(enc, obj)) {
+ if (obj->elm_type == ELMTYP_SAS_EXP) {
offset += sizeof(struct ses_elm_sas_type1_expander_hdr);
physz = addl->proto_hdr.sas->base_hdr.num_phys *
sizeof(struct ses_elm_sas_expander_phy);
@@ -2565,6 +2638,53 @@ out:
return (err);
}
+/**
+ * \brief Update the softc with the additional element status data for this
+ * object, for ATA objects.
+ *
+ * \param enc SES softc to be updated.
+ * \param buf The additional element status response buffer.
+ * \param bufsiz Size of the response buffer.
+ * \param eip The EIP bit value.
+ * \param tidx Type index for this object.
+ * \param nobj Number of objects attached to the SES softc.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_get_elm_addlstatus_ata(enc_softc_t *enc, enc_cache_t *enc_cache,
+ uint8_t *buf, int bufsiz, int eip, int tidx,
+ int nobj)
+{
+ int err;
+ ses_cache_t *ses_cache;
+
+ if (bufsiz < sizeof(struct ses_elm_ata_hdr)) {
+ err = EIO;
+ goto out;
+ }
+
+ ses_cache = enc_cache->private;
+ switch(ses_cache->ses_types[tidx].hdr->etype_elm_type) {
+ case ELMTYP_DEVICE:
+ case ELMTYP_ARRAY_DEV:
+ break;
+ default:
+ ENC_VLOG(enc, "Element %d has Additional Status, "
+ "invalid for SES element type 0x%x\n", nobj,
+ ses_cache->ses_types[tidx].hdr->etype_elm_type);
+ err = ENODEV;
+ goto out;
+ }
+
+ ((ses_element_t *)enc_cache->elm_map[nobj].elm_private)
+ ->addl.proto_hdr.ata = (struct ses_elm_ata_hdr *)buf;
+ err = 0;
+
+out:
+ return (err);
+}
+
static void
ses_softc_invalidate(enc_softc_t *enc)
{
diff --git a/sys/cam/scsi/scsi_ses.h b/sys/cam/scsi/scsi_ses.h
index 779b3a97a00d..b9c69cbcfe30 100644
--- a/sys/cam/scsi/scsi_ses.h
+++ b/sys/cam/scsi/scsi_ses.h
@@ -2181,15 +2181,27 @@ struct ses_status_page_hdr {
#define SESCTL_DISABLE 0x20
#define SESCTL_RSTSWAP 0x10
-
-/* Control bits, Device Elements, byte 2 */
-#define SESCTL_DRVLCK 0x40 /* "DO NOT REMOVE" */
+/* Control bits, Array Device Slot Elements, byte 1 */
+#define SESCTL_RQSOK 0x80 /* RQST OK */
+#define SESCTL_RQSRSV 0x40 /* RQST RSVD DEVICE */
+#define SESCTL_RQSSPR 0x20 /* RQST HOT SPARE */
+#define SESCTL_RQSCCH 0x10 /* RQST CONS CHECK */
+#define SESCTL_RQSCRA 0x08 /* RQST IN CRIT ARRAY */
+#define SESCTL_RQSFAA 0x04 /* RQST IN FAILED ARRAY */
+#define SESCTL_RQSRR 0x02 /* RQST REBUI/REMAP */
+#define SESCTL_RQSRRA 0x01 /* RQST R/R ABORT */
+/* Control bits, [Array] Device Slot Elements, byte 2 */
+#define SESCTL_RQSACT 0x80 /* RQST ACTIVE */
+#define SESCTL_DRVLCK 0x40 /* DO NOT REMOVE */
+#define SESCTL_RQSMSN 0x10 /* RQST MISSING */
#define SESCTL_RQSINS 0x08 /* RQST INSERT */
#define SESCTL_RQSRMV 0x04 /* RQST REMOVE */
#define SESCTL_RQSID 0x02 /* RQST IDENT */
-/* Control bits, Device Elements, byte 3 */
+/* Control bits, [Array] Device Slot Elements, byte 3 */
#define SESCTL_RQSFLT 0x20 /* RQST FAULT */
#define SESCTL_DEVOFF 0x10 /* DEVICE OFF */
+#define SESCTL_ENBYPA 0x08 /* ENABLE BYP A */
+#define SESCTL_ENBYPB 0x04 /* ENABLE BYP B */
/* Control bits, Generic, byte 3 */
#define SESCTL_RQSTFAIL 0x40
@@ -2399,6 +2411,17 @@ union ses_elm_sas_hdr {
int ses_elm_sas_type0_not_all_phys(union ses_elm_sas_hdr *);
int ses_elm_sas_descr_type(union ses_elm_sas_hdr *);
+/*
+ * This structure for SPSP_PROTO_ATA is not defined by SES specs,
+ * but purely my own design to make AHCI EM interoperate with SES.
+ * Since no other software I know can talk to SEMB, and we do not
+ * expose this this outside, it should be safe to do what we want.
+ */
+struct ses_elm_ata_hdr {
+ uint8_t bus[4];
+ uint8_t target[4];
+};
+
struct ses_elm_addlstatus_base_hdr {
uint8_t byte0;
/*
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
index 2e36e0e5eec1..71d9cd7b6f17 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
@@ -1334,6 +1334,8 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
zio_t *zio;
list_t *list;
dbuf_dirty_record_t *dr;
+ int num_sublists;
+ multilist_t *ml;
blkptr_t *blkptr_copy = kmem_alloc(sizeof (*os->os_rootbp), KM_SLEEP);
*blkptr_copy = *os->os_rootbp;
@@ -1402,10 +1404,13 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
}
}
- for (int i = 0;
- i < multilist_get_num_sublists(os->os_dirty_dnodes[txgoff]); i++) {
+ ml = os->os_dirty_dnodes[txgoff];
+ num_sublists = multilist_get_num_sublists(ml);
+ for (int i = 0; i < num_sublists; i++) {
+ if (multilist_sublist_is_empty_idx(ml, i))
+ continue;
sync_dnodes_arg_t *sda = kmem_alloc(sizeof (*sda), KM_SLEEP);
- sda->sda_list = os->os_dirty_dnodes[txgoff];
+ sda->sda_list = ml;
sda->sda_sublist_idx = i;
sda->sda_tx = tx;
(void) taskq_dispatch(dmu_objset_pool(os)->dp_sync_taskq,
@@ -1619,6 +1624,8 @@ userquota_updates_task(void *arg)
void
dmu_objset_do_userquota_updates(objset_t *os, dmu_tx_t *tx)
{
+ int num_sublists;
+
if (!dmu_objset_userused_enabled(os))
return;
@@ -1632,8 +1639,10 @@ dmu_objset_do_userquota_updates(objset_t *os, dmu_tx_t *tx)
DMU_OT_USERGROUP_USED, DMU_OT_NONE, 0, tx));
}
- for (int i = 0;
- i < multilist_get_num_sublists(os->os_synced_dnodes); i++) {
+ num_sublists = multilist_get_num_sublists(os->os_synced_dnodes);
+ for (int i = 0; i < num_sublists; i++) {
+ if (multilist_sublist_is_empty_idx(os->os_synced_dnodes, i))
+ continue;
userquota_updates_arg_t *uua =
kmem_alloc(sizeof (*uua), KM_SLEEP);
uua->uua_os = os;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/multilist.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/multilist.c
index b61d1358c8a8..f517454d3d6d 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/multilist.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/multilist.c
@@ -360,6 +360,28 @@ multilist_sublist_remove(multilist_sublist_t *mls, void *obj)
list_remove(&mls->mls_list, obj);
}
+int
+multilist_sublist_is_empty(multilist_sublist_t *mls)
+{
+ ASSERT(MUTEX_HELD(&mls->mls_lock));
+ return (list_is_empty(&mls->mls_list));
+}
+
+int
+multilist_sublist_is_empty_idx(multilist_t *ml, unsigned int sublist_idx)
+{
+ multilist_sublist_t *mls;
+ int empty;
+
+ ASSERT3U(sublist_idx, <, ml->ml_num_sublists);
+ mls = &ml->ml_sublists[sublist_idx];
+ ASSERT(!MUTEX_HELD(&mls->mls_lock));
+ mutex_enter(&mls->mls_lock);
+ empty = list_is_empty(&mls->mls_list);
+ mutex_exit(&mls->mls_lock);
+ return (empty);
+}
+
void *
multilist_sublist_head(multilist_sublist_t *mls)
{
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h
index 7f386fb7c3be..a3b44e60eb97 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/multilist.h
@@ -89,6 +89,8 @@ void multilist_sublist_insert_head(multilist_sublist_t *, void *);
void multilist_sublist_insert_tail(multilist_sublist_t *, void *);
void multilist_sublist_move_forward(multilist_sublist_t *mls, void *obj);
void multilist_sublist_remove(multilist_sublist_t *, void *);
+int multilist_sublist_is_empty(multilist_sublist_t *);
+int multilist_sublist_is_empty_idx(multilist_t *, unsigned int);
void *multilist_sublist_head(multilist_sublist_t *);
void *multilist_sublist_tail(multilist_sublist_t *);
diff --git a/sys/compat/linuxkpi/common/include/asm/atomic-long.h b/sys/compat/linuxkpi/common/include/asm/atomic-long.h
index d7f839f2541f..108d7f4f7b3a 100644
--- a/sys/compat/linuxkpi/common/include/asm/atomic-long.h
+++ b/sys/compat/linuxkpi/common/include/asm/atomic-long.h
@@ -42,6 +42,7 @@ typedef struct {
} atomic_long_t;
#define atomic_long_add(i, v) atomic_long_add_return((i), (v))
+#define atomic_long_sub(i, v) atomic_long_add_return(-(i), (v))
#define atomic_long_inc_return(v) atomic_long_add_return(1, (v))
#define atomic_long_inc_not_zero(v) atomic_long_add_unless((v), 1, 0)
diff --git a/sys/compat/linuxkpi/common/include/linux/rculist.h b/sys/compat/linuxkpi/common/include/linux/rculist.h
index e4823de7a3bf..0a4ad499c380 100644
--- a/sys/compat/linuxkpi/common/include/linux/rculist.h
+++ b/sys/compat/linuxkpi/common/include/linux/rculist.h
@@ -33,6 +33,25 @@
#include <linux/list.h>
#include <linux/rcupdate.h>
+#define list_entry_rcu(ptr, type, member) \
+ container_of(READ_ONCE(ptr), type, member)
+
+#define list_next_rcu(head) (*((struct list_head **)(&(head)->next)))
+
+#define list_for_each_entry_rcu(pos, head, member) \
+ for (pos = list_entry_rcu((head)->next, typeof(*(pos)), member); \
+ &(pos)->member != (head); \
+ pos = list_entry_rcu((pos)->member.next, typeof(*(pos)), member))
+
+static inline void
+list_add_rcu(struct list_head *new, struct list_head *prev)
+{
+ new->next = prev->next;
+ new->prev = prev;
+ rcu_assign_pointer(list_next_rcu(prev), new);
+ prev->prev = new;
+}
+
#define hlist_first_rcu(head) (*((struct hlist_node **)(&(head)->first)))
#define hlist_next_rcu(node) (*((struct hlist_node **)(&(node)->next)))
#define hlist_pprev_rcu(node) (*((struct hlist_node **)((node)->pprev)))
@@ -47,8 +66,12 @@ hlist_add_behind_rcu(struct hlist_node *n, struct hlist_node *prev)
n->next->pprev = &n->next;
}
-#define hlist_for_each_entry_rcu(pos, head, member) \
- hlist_for_each_entry(pos, head, member)
+#define hlist_for_each_entry_rcu(pos, head, member) \
+ for (pos = hlist_entry_safe (rcu_dereference_raw(hlist_first_rcu(head)),\
+ typeof(*(pos)), member); \
+ (pos); \
+ pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu( \
+ &(pos)->member)), typeof(*(pos)), member))
static inline void
hlist_del_rcu(struct hlist_node *n)
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 30ae142ba29b..dfa5ff68d802 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1170,9 +1170,6 @@ options NFS_DEBUG # Enable NFS Debugging
#
options EXT2FS
-# Cryptographically secure random number generator; /dev/random
-device random
-
# The system memory devices; /dev/mem, /dev/kmem
device mem
@@ -2424,14 +2421,19 @@ device iicoc # OpenCores I2C controller support
# I2C peripheral devices
#
+device ad7418 # Analog Devices temp and voltage sensor
device ds1307 # Dallas DS1307 RTC and compatible
device ds13rtc # All Dallas/Maxim ds13xx chips
device ds1672 # Dallas DS1672 RTC
device ds3231 # Dallas DS3231 RTC + temperature
device icee # AT24Cxxx and compatible EEPROMs
+device isl12xx # Intersil ISL12xx RTC
device lm75 # LM75 compatible temperature sensor
device nxprtc # NXP RTCs: PCA/PFC212x PCA/PCF85xx
+device rtc8583 # Epson RTC-8583
device s35390a # Seiko Instruments S-35390A RTC
+device sy8106a # Silergy Corp. SY8106A buck regulator
+device syr827 # Silergy Corp. DC/DC regulator
# Parallel-Port Bus
#
@@ -2479,6 +2481,22 @@ device pps
device lpbb
device pcfclock
+# General Purpose I/O pins
+device gpio # gpio interfaces and bus support
+device gpiobacklight # sysctl control of gpio-based backlight
+device gpioiic # i2c via gpio bitbang
+device gpiokeys # kbd(4) glue for gpio-based key input
+device gpioled # led(4) gpio glue
+device gpiopower # event handler for gpio-based powerdown
+device gpiopps # Pulse per second input from gpio pin
+device gpioregulator # extres/regulator glue for gpio pin
+device gpiospi # SPI via gpio bitbang
+device gpioths # 1-wire temp/humidity sensor on gpio pin
+
+# Pulse width modulation
+device pwmbus # pwm interface and bus support
+device pwmc # userland control access to pwm outputs
+
#
# Etherswitch framework and drivers
#
diff --git a/sys/conf/files b/sys/conf/files
index dd67e0ec7a68..c62a9e285e47 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -686,14 +686,14 @@ crypto/des/des_ecb.c optional crypto | ipsec | ipsec_support | netsmb
crypto/des/des_setkey.c optional crypto | ipsec | ipsec_support | netsmb
crypto/rc4/rc4.c optional netgraph_mppc_encryption | kgssapi
crypto/rijndael/rijndael-alg-fst.c optional crypto | ekcd | geom_bde | \
- ipsec | ipsec_support | random !random_loadable | wlan_ccmp
-crypto/rijndael/rijndael-api-fst.c optional ekcd | geom_bde | random !random_loadable
+ ipsec | ipsec_support | !random_loadable | wlan_ccmp
+crypto/rijndael/rijndael-api-fst.c optional ekcd | geom_bde | !random_loadable
crypto/rijndael/rijndael-api.c optional crypto | ipsec | ipsec_support | \
wlan_ccmp
crypto/sha1.c optional carp | crypto | ether | ipsec | \
ipsec_support | netgraph_mppc_encryption | sctp
crypto/sha2/sha256c.c optional crypto | ekcd | geom_bde | ipsec | \
- ipsec_support | random !random_loadable | sctp | zfs
+ ipsec_support | !random_loadable | sctp | zfs
crypto/sha2/sha512c.c optional crypto | geom_bde | ipsec | \
ipsec_support | zfs
crypto/skein/skein.c optional crypto | zfs
@@ -1708,7 +1708,7 @@ dev/fdt/fdt_clock_if.m optional fdt fdt_clock
dev/fdt/fdt_common.c optional fdt
dev/fdt/fdt_pinctrl.c optional fdt fdt_pinctrl
dev/fdt/fdt_pinctrl_if.m optional fdt fdt_pinctrl
-dev/fdt/fdt_slicer.c optional fdt cfi | fdt nand | fdt mx25l | fdt n25q | fdt at45d
+dev/fdt/fdt_slicer.c optional fdt cfi | fdt mx25l | fdt n25q | fdt at45d
dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static \
dependency "${FDT_DTS_FILE:T:R}.dtb"
dev/fdt/simplebus.c optional fdt
@@ -1751,7 +1751,7 @@ dev/gpio/gpiospi.c optional gpiospi
dev/gpio/gpioths.c optional gpioths
dev/gpio/gpio_if.m optional gpio
dev/gpio/gpiobus_if.m optional gpio
-dev/gpio/gpiopps.c optional gpiopps
+dev/gpio/gpiopps.c optional gpiopps fdt
dev/gpio/ofw_gpiobus.c optional fdt gpio
dev/hifn/hifn7751.c optional hifn
dev/hme/if_hme.c optional hme
@@ -1775,7 +1775,7 @@ dev/iicbus/ds13rtc.c optional ds13rtc | ds133x | ds1374
dev/iicbus/ds1672.c optional ds1672
dev/iicbus/ds3231.c optional ds3231
dev/iicbus/rtc8583.c optional rtc8583
-dev/iicbus/syr827.c optional ext_resources syr827
+dev/iicbus/syr827.c optional syr827 ext_resources fdt
dev/iicbus/icee.c optional icee
dev/iicbus/if_ic.c optional ic
dev/iicbus/iic.c optional iic
@@ -1792,7 +1792,9 @@ dev/iicbus/isl12xx.c optional isl12xx
dev/iicbus/lm75.c optional lm75
dev/iicbus/nxprtc.c optional nxprtc | pcf8563
dev/iicbus/ofw_iicbus.c optional fdt iicbus
+dev/iicbus/rtc8583.c optional rtc8583
dev/iicbus/s35390a.c optional s35390a
+dev/iicbus/sy8106a.c optional sy8106a ext_resources fdt
dev/iir/iir.c optional iir
dev/iir/iir_ctrl.c optional iir
dev/iir/iir_pci.c optional iir pci
@@ -2455,21 +2457,6 @@ dev/mxge/mxge_ethp_z8e.c optional mxge pci
dev/mxge/mxge_rss_eth_z8e.c optional mxge pci
dev/mxge/mxge_rss_ethp_z8e.c optional mxge pci
dev/my/if_my.c optional my
-dev/nand/nand.c optional nand
-dev/nand/nand_bbt.c optional nand
-dev/nand/nand_cdev.c optional nand
-dev/nand/nand_generic.c optional nand
-dev/nand/nand_geom.c optional nand
-dev/nand/nand_id.c optional nand
-dev/nand/nandbus.c optional nand
-dev/nand/nandbus_if.m optional nand
-dev/nand/nand_if.m optional nand
-dev/nand/nandsim.c optional nandsim nand
-dev/nand/nandsim_chip.c optional nandsim nand
-dev/nand/nandsim_ctrl.c optional nandsim nand
-dev/nand/nandsim_log.c optional nandsim nand
-dev/nand/nandsim_swap.c optional nandsim nand
-dev/nand/nfc_if.m optional nand
dev/netmap/if_ptnet.c optional netmap inet
dev/netmap/netmap.c optional netmap
dev/netmap/netmap_bdg.c optional netmap
@@ -2766,11 +2753,11 @@ rt2860.fw optional rt2860fw | ralfw \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "rt2860.fw"
-dev/random/random_infra.c optional random
-dev/random/random_harvestq.c optional random
-dev/random/randomdev.c optional random !random_loadable
-dev/random/fortuna.c optional random !random_loadable
-dev/random/hash.c optional random !random_loadable
+dev/random/random_infra.c standard
+dev/random/random_harvestq.c standard
+dev/random/randomdev.c optional !random_loadable
+dev/random/fortuna.c optional !random_loadable
+dev/random/hash.c optional !random_loadable
dev/rc/rc.c optional rc
dev/rccgpio/rccgpio.c optional rccgpio gpio
dev/re/if_re.c optional re
@@ -3497,20 +3484,6 @@ fs/msdosfs/msdosfs_iconv.c optional msdosfs_iconv
fs/msdosfs/msdosfs_lookup.c optional msdosfs
fs/msdosfs/msdosfs_vfsops.c optional msdosfs
fs/msdosfs/msdosfs_vnops.c optional msdosfs
-fs/nandfs/bmap.c optional nandfs
-fs/nandfs/nandfs_alloc.c optional nandfs
-fs/nandfs/nandfs_bmap.c optional nandfs
-fs/nandfs/nandfs_buffer.c optional nandfs
-fs/nandfs/nandfs_cleaner.c optional nandfs
-fs/nandfs/nandfs_cpfile.c optional nandfs
-fs/nandfs/nandfs_dat.c optional nandfs
-fs/nandfs/nandfs_dir.c optional nandfs
-fs/nandfs/nandfs_ifile.c optional nandfs
-fs/nandfs/nandfs_segment.c optional nandfs
-fs/nandfs/nandfs_subr.c optional nandfs
-fs/nandfs/nandfs_sufile.c optional nandfs
-fs/nandfs/nandfs_vfsops.c optional nandfs
-fs/nandfs/nandfs_vnops.c optional nandfs
fs/nfs/nfs_commonkrpc.c optional nfscl | nfsd
fs/nfs/nfs_commonsubs.c optional nfscl | nfsd
fs/nfs/nfs_commonport.c optional nfscl | nfsd
@@ -3598,7 +3571,7 @@ geom/geom_disk.c standard
geom/geom_dump.c standard
geom/geom_event.c standard
geom/geom_fox.c optional geom_fox
-geom/geom_flashmap.c optional fdt cfi | fdt nand | fdt mx25l | mmcsd | fdt n25q | fdt at45d
+geom/geom_flashmap.c optional fdt cfi | fdt mx25l | mmcsd | fdt n25q | fdt at45d
geom/geom_io.c standard
geom/geom_kern.c standard
geom/geom_map.c optional geom_map
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 1d399122c50c..81cd730a5c34 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -389,6 +389,9 @@ dev/qlxgbe/ql_isr.c optional qlxgbe pci
dev/qlxgbe/ql_misc.c optional qlxgbe pci
dev/qlxgbe/ql_os.c optional qlxgbe pci
dev/qlxgbe/ql_reset.c optional qlxgbe pci
+dev/qlxgbe/ql_fw.c optional qlxgbe pci
+dev/qlxgbe/ql_boot.c optional qlxgbe pci
+dev/qlxgbe/ql_minidump.c optional qlxgbe pci
dev/qlnx/qlnxe/ecore_cxt.c optional qlnxe pci \
compile-with "${LINUXKPI_C}"
dev/qlnx/qlnxe/ecore_dbg_fw_funcs.c optional qlnxe pci \
diff --git a/sys/conf/files.arm b/sys/conf/files.arm
index 6134b20e1177..8d890144b277 100644
--- a/sys/conf/files.arm
+++ b/sys/conf/files.arm
@@ -166,6 +166,12 @@ cloudabi32_vdso_blob.o optional compat_cloudabi32 \
clean "cloudabi32_vdso_blob.o"
#
+#
+ukbdmap.h optional ukbd_dflt_keymap \
+ compile-with "kbdcontrol -P ${S:S/sys$/share/}/vt/keymaps -P ${S:S/sys$/share/}/syscons/keymaps -L ${UKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > ukbdmap.h" \
+ no-obj no-implicit-rule before-depend \
+ clean "ukbdmap.h"
+
# Annapurna support
arm/annapurna/alpine/alpine_ccu.c optional al_ccu fdt
arm/annapurna/alpine/alpine_nb_service.c optional al_nb_service fdt
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index f8d9beba599d..b8c023425293 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -87,7 +87,7 @@ arm/broadcom/bcm2835/bcm2835_ft5406.c optional evdev bcm2835_ft5406 soc_brcm_bc
arm/broadcom/bcm2835/bcm2835_gpio.c optional gpio soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm2835_intr.c optional soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm2835_mbox.c optional soc_brcm_bcm2837 fdt
-arm/broadcom/bcm2835/bcm2835_rng.c optional random !random_loadable soc_brcm_bcm2837 fdt
+arm/broadcom/bcm2835/bcm2835_rng.c optional !random_loadable soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm2835_sdhci.c optional sdhci soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm2835_sdhost.c optional sdhci soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm2835_spi.c optional bcm2835_spi soc_brcm_bcm2837 fdt
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index cbda69a0d7cf..5383595b1411 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -43,8 +43,6 @@ dev/iicbus/max6690.c optional max6690 powermac
dev/iicbus/ofw_iicbus.c optional iicbus aim
dev/ipmi/ipmi.c optional ipmi
dev/ipmi/ipmi_opal.c optional powernv ipmi
-dev/nand/nfc_fsl.c optional nand mpc85xx
-dev/nand/nfc_rb.c optional nand mpc85xx
# Most ofw stuff below is brought in by conf/files for options FDT, but
# we always want it, even on non-FDT platforms.
dev/fdt/simplebus.c standard
@@ -62,7 +60,7 @@ dev/ofw/ofw_standard.c optional aim powerpc
dev/ofw/ofw_subr.c standard
dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac
dev/quicc/quicc_bfe_fdt.c optional quicc mpc85xx
-dev/random/darn.c optional powerpc64 random !random_loadable
+dev/random/darn.c optional powerpc64 !random_loadable
dev/scc/scc_bfe_macio.c optional scc powermac
dev/sdhci/fsl_sdhci.c optional mpc85xx sdhci
dev/sec/sec.c optional sec mpc85xx
diff --git a/sys/conf/kern.opts.mk b/sys/conf/kern.opts.mk
index 33aa0bcba989..58f125efbd06 100644
--- a/sys/conf/kern.opts.mk
+++ b/sys/conf/kern.opts.mk
@@ -52,7 +52,6 @@ __DEFAULT_YES_OPTIONS = \
__DEFAULT_NO_OPTIONS = \
EXTRA_TCP_STACKS \
KERNEL_RETPOLINE \
- NAND \
OFED \
RATELIMIT
diff --git a/sys/conf/makeLINT.mk b/sys/conf/makeLINT.mk
index 52dddf5a97d7..d3a414c14ff6 100644
--- a/sys/conf/makeLINT.mk
+++ b/sys/conf/makeLINT.mk
@@ -47,6 +47,11 @@ LINT: ${NOTES} ${MAKELINT_SED}
echo "nodevice txp" >> ${.TARGET}-NOIP
echo "nodevice netmap" >> ${.TARGET}-NOIP
.endif
+.if ${TARGET} == "arm"
+ cat ${.TARGET} ${.CURDIR}/NOTES.armv5 > ${.TARGET}-V5
+ cat ${.TARGET} ${.CURDIR}/NOTES.armv7 > ${.TARGET}-V7
+ rm ${.TARGET}
+.endif
.if ${TARGET} == "mips"
echo "machine ${TARGET} ${TARGET_ARCH}" >> ${.TARGET}
.endif
diff --git a/sys/conf/options b/sys/conf/options
index df394936b9d4..c4c3bb7eed67 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -256,7 +256,6 @@ FDESCFS opt_dontuse.h
FFS opt_dontuse.h
FUSEFS opt_dontuse.h
MSDOSFS opt_dontuse.h
-NANDFS opt_dontuse.h
NULLFS opt_dontuse.h
PROCFS opt_dontuse.h
PSEUDOFS opt_dontuse.h
@@ -734,7 +733,6 @@ DEV_PCI opt_pci.h
DEV_PF opt_pf.h
DEV_PFLOG opt_pf.h
DEV_PFSYNC opt_pf.h
-DEV_RANDOM opt_global.h
DEV_SPLASH opt_splash.h
DEV_VLAN opt_vlan.h
@@ -863,6 +861,12 @@ AH_INTERRUPT_DEBUGGING opt_ah.h
# XXX do not use this for AR9130
AH_AR5416_INTERRUPT_MITIGATION opt_ah.h
+# options for the Altera mSGDMA driver (altera_msgdma)
+ALTERA_MSGDMA_DESC_STD opt_altera_msgdma.h
+ALTERA_MSGDMA_DESC_EXT opt_altera_msgdma.h
+ALTERA_MSGDMA_DESC_PF_STD opt_altera_msgdma.h
+ALTERA_MSGDMA_DESC_PF_EXT opt_altera_msgdma.h
+
# options for the Broadcom BCM43xx driver (bwi)
BWI_DEBUG opt_bwi.h
BWI_DEBUG_VERBOSE opt_bwi.h
diff --git a/sys/contrib/ipfilter/netinet/fil.c b/sys/contrib/ipfilter/netinet/fil.c
index a0d008dbd2d7..1d142165c341 100644
--- a/sys/contrib/ipfilter/netinet/fil.c
+++ b/sys/contrib/ipfilter/netinet/fil.c
@@ -1723,29 +1723,31 @@ ipf_pr_ipv4hdr(fin)
* calculate the byte offset that it represents.
*/
off &= IP_MF|IP_OFFMASK;
+ if (off == 1 && p == IPPROTO_TCP) {
+ fin->fin_flx |= FI_SHORT; /* RFC 3128 */
+ DT1(ipf_fi_tcp_frag_off_1, fr_info_t *, fin);
+ }
if (off != 0) {
int morefrag = off & IP_MF;
fi->fi_flx |= FI_FRAG;
off &= IP_OFFMASK;
- if (off != 0) {
- fin->fin_flx |= FI_FRAGBODY;
- off <<= 3;
- if ((off + fin->fin_dlen > 65535) ||
- (fin->fin_dlen == 0) ||
- ((morefrag != 0) && ((fin->fin_dlen & 7) != 0))) {
- /*
- * The length of the packet, starting at its
- * offset cannot exceed 65535 (0xffff) as the
- * length of an IP packet is only 16 bits.
- *
- * Any fragment that isn't the last fragment
- * must have a length greater than 0 and it
- * must be an even multiple of 8.
- */
- fi->fi_flx |= FI_BAD;
- DT1(ipf_fi_bad_fragbody_gt_65535, fr_info_t *, fin);
- }
+ fin->fin_flx |= FI_FRAGBODY;
+ off <<= 3;
+ if ((off + fin->fin_dlen > 65535) ||
+ (fin->fin_dlen == 0) ||
+ ((morefrag != 0) && ((fin->fin_dlen & 7) != 0))) {
+ /*
+ * The length of the packet, starting at its
+ * offset cannot exceed 65535 (0xffff) as the
+ * length of an IP packet is only 16 bits.
+ *
+ * Any fragment that isn't the last fragment
+ * must have a length greater than 0 and it
+ * must be an even multiple of 8.
+ */
+ fi->fi_flx |= FI_BAD;
+ DT1(ipf_fi_bad_fragbody_gt_65535, fr_info_t *, fin);
}
}
fin->fin_off = off;
@@ -7472,10 +7474,6 @@ ipf_resolvedest(softc, base, fdp, v)
}
fdp->fd_ptr = ifp;
- if ((ifp != NULL) && (ifp != (void *)-1)) {
- fdp->fd_local = ipf_deliverlocal(softc, v, ifp, &fdp->fd_ip6);
- }
-
return errval;
}
diff --git a/sys/contrib/ipfilter/netinet/ip_compat.h b/sys/contrib/ipfilter/netinet/ip_compat.h
index 777495b39aed..75f4d7c116ce 100644
--- a/sys/contrib/ipfilter/netinet/ip_compat.h
+++ b/sys/contrib/ipfilter/netinet/ip_compat.h
@@ -829,190 +829,9 @@ typedef struct tcpiphdr tcpiphdr_t;
#undef IPOPT_AH
#define IPOPT_AH 256+IPPROTO_AH
-#ifndef TCPOPT_EOL
-# define TCPOPT_EOL 0
-#endif
-#ifndef TCPOPT_NOP
-# define TCPOPT_NOP 1
-#endif
-#ifndef TCPOPT_MAXSEG
-# define TCPOPT_MAXSEG 2
-#endif
-#ifndef TCPOLEN_MAXSEG
-# define TCPOLEN_MAXSEG 4
-#endif
-#ifndef TCPOPT_WINDOW
-# define TCPOPT_WINDOW 3
-#endif
-#ifndef TCPOLEN_WINDOW
-# define TCPOLEN_WINDOW 3
-#endif
-#ifndef TCPOPT_SACK_PERMITTED
-# define TCPOPT_SACK_PERMITTED 4
-#endif
-#ifndef TCPOLEN_SACK_PERMITTED
-# define TCPOLEN_SACK_PERMITTED 2
-#endif
-#ifndef TCPOPT_SACK
-# define TCPOPT_SACK 5
-#endif
-#ifndef TCPOPT_TIMESTAMP
-# define TCPOPT_TIMESTAMP 8
-#endif
+# define ICMP_UNREACH_ADMIN_PROHIBIT ICMP_UNREACH_FILTER_PROHIB
+# define ICMP_UNREACH_FILTER ICMP_UNREACH_FILTER_PROHIB
-#ifndef ICMP_MINLEN
-# define ICMP_MINLEN 8
-#endif
-#ifndef ICMP_ECHOREPLY
-# define ICMP_ECHOREPLY 0
-#endif
-#ifndef ICMP_UNREACH
-# define ICMP_UNREACH 3
-#endif
-#ifndef ICMP_UNREACH_NET
-# define ICMP_UNREACH_NET 0
-#endif
-#ifndef ICMP_UNREACH_HOST
-# define ICMP_UNREACH_HOST 1
-#endif
-#ifndef ICMP_UNREACH_PROTOCOL
-# define ICMP_UNREACH_PROTOCOL 2
-#endif
-#ifndef ICMP_UNREACH_PORT
-# define ICMP_UNREACH_PORT 3
-#endif
-#ifndef ICMP_UNREACH_NEEDFRAG
-# define ICMP_UNREACH_NEEDFRAG 4
-#endif
-#ifndef ICMP_UNREACH_SRCFAIL
-# define ICMP_UNREACH_SRCFAIL 5
-#endif
-#ifndef ICMP_UNREACH_NET_UNKNOWN
-# define ICMP_UNREACH_NET_UNKNOWN 6
-#endif
-#ifndef ICMP_UNREACH_HOST_UNKNOWN
-# define ICMP_UNREACH_HOST_UNKNOWN 7
-#endif
-#ifndef ICMP_UNREACH_ISOLATED
-# define ICMP_UNREACH_ISOLATED 8
-#endif
-#ifndef ICMP_UNREACH_NET_PROHIB
-# define ICMP_UNREACH_NET_PROHIB 9
-#endif
-#ifndef ICMP_UNREACH_HOST_PROHIB
-# define ICMP_UNREACH_HOST_PROHIB 10
-#endif
-#ifndef ICMP_UNREACH_TOSNET
-# define ICMP_UNREACH_TOSNET 11
-#endif
-#ifndef ICMP_UNREACH_TOSHOST
-# define ICMP_UNREACH_TOSHOST 12
-#endif
-#ifndef ICMP_UNREACH_ADMIN_PROHIBIT
-# define ICMP_UNREACH_ADMIN_PROHIBIT 13
-#endif
-#ifndef ICMP_UNREACH_FILTER
-# define ICMP_UNREACH_FILTER 13
-#endif
-#ifndef ICMP_UNREACH_HOST_PRECEDENCE
-# define ICMP_UNREACH_HOST_PRECEDENCE 14
-#endif
-#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
-# define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
-#endif
-#ifndef ICMP_SOURCEQUENCH
-# define ICMP_SOURCEQUENCH 4
-#endif
-#ifndef ICMP_REDIRECT_NET
-# define ICMP_REDIRECT_NET 0
-#endif
-#ifndef ICMP_REDIRECT_HOST
-# define ICMP_REDIRECT_HOST 1
-#endif
-#ifndef ICMP_REDIRECT_TOSNET
-# define ICMP_REDIRECT_TOSNET 2
-#endif
-#ifndef ICMP_REDIRECT_TOSHOST
-# define ICMP_REDIRECT_TOSHOST 3
-#endif
-#ifndef ICMP_ALTHOSTADDR
-# define ICMP_ALTHOSTADDR 6
-#endif
-#ifndef ICMP_TIMXCEED
-# define ICMP_TIMXCEED 11
-#endif
-#ifndef ICMP_TIMXCEED_INTRANS
-# define ICMP_TIMXCEED_INTRANS 0
-#endif
-#ifndef ICMP_TIMXCEED_REASS
-# define ICMP_TIMXCEED_REASS 1
-#endif
-#ifndef ICMP_PARAMPROB
-# define ICMP_PARAMPROB 12
-#endif
-#ifndef ICMP_PARAMPROB_ERRATPTR
-# define ICMP_PARAMPROB_ERRATPTR 0
-#endif
-#ifndef ICMP_PARAMPROB_OPTABSENT
-# define ICMP_PARAMPROB_OPTABSENT 1
-#endif
-#ifndef ICMP_PARAMPROB_LENGTH
-# define ICMP_PARAMPROB_LENGTH 2
-#endif
-#ifndef ICMP_TSTAMP
-# define ICMP_TSTAMP 13
-#endif
-#ifndef ICMP_TSTAMPREPLY
-# define ICMP_TSTAMPREPLY 14
-#endif
-#ifndef ICMP_IREQ
-# define ICMP_IREQ 15
-#endif
-#ifndef ICMP_IREQREPLY
-# define ICMP_IREQREPLY 16
-#endif
-#ifndef ICMP_MASKREQ
-# define ICMP_MASKREQ 17
-#endif
-#ifndef ICMP_MASKREPLY
-# define ICMP_MASKREPLY 18
-#endif
-#ifndef ICMP_TRACEROUTE
-# define ICMP_TRACEROUTE 30
-#endif
-#ifndef ICMP_DATACONVERR
-# define ICMP_DATACONVERR 31
-#endif
-#ifndef ICMP_MOBILE_REDIRECT
-# define ICMP_MOBILE_REDIRECT 32
-#endif
-#ifndef ICMP_IPV6_WHEREAREYOU
-# define ICMP_IPV6_WHEREAREYOU 33
-#endif
-#ifndef ICMP_IPV6_IAMHERE
-# define ICMP_IPV6_IAMHERE 34
-#endif
-#ifndef ICMP_MOBILE_REGREQUEST
-# define ICMP_MOBILE_REGREQUEST 35
-#endif
-#ifndef ICMP_MOBILE_REGREPLY
-# define ICMP_MOBILE_REGREPLY 36
-#endif
-#ifndef ICMP_SKIP
-# define ICMP_SKIP 39
-#endif
-#ifndef ICMP_PHOTURIS
-# define ICMP_PHOTURIS 40
-#endif
-#ifndef ICMP_PHOTURIS_UNKNOWN_INDEX
-# define ICMP_PHOTURIS_UNKNOWN_INDEX 1
-#endif
-#ifndef ICMP_PHOTURIS_AUTH_FAILED
-# define ICMP_PHOTURIS_AUTH_FAILED 2
-#endif
-#ifndef ICMP_PHOTURIS_DECRYPT_FAILED
-# define ICMP_PHOTURIS_DECRYPT_FAILED 3
-#endif
#ifndef IPVERSION
# define IPVERSION 4
#endif
diff --git a/sys/contrib/ipfilter/netinet/ip_fil.h b/sys/contrib/ipfilter/netinet/ip_fil.h
index f3185c6458d7..032cf0dea853 100644
--- a/sys/contrib/ipfilter/netinet/ip_fil.h
+++ b/sys/contrib/ipfilter/netinet/ip_fil.h
@@ -560,7 +560,6 @@ typedef struct frdest {
addrfamily_t fd_addr;
fr_dtypes_t fd_type;
int fd_name;
- int fd_local;
} frdest_t;
#define fd_ip6 fd_addr.adf_addr
diff --git a/sys/ddb/db_ps.c b/sys/ddb/db_ps.c
index 72bf0edd9161..82e50e0ca85d 100644
--- a/sys/ddb/db_ps.c
+++ b/sys/ddb/db_ps.c
@@ -481,7 +481,7 @@ DB_SHOW_COMMAND(proc, db_show_proc)
dump_args(p);
db_printf("\n");
}
- db_printf(" repear: %p reapsubtree: %d\n",
+ db_printf(" reaper: %p reapsubtree: %d\n",
p->p_reaper, p->p_reapsubtree);
db_printf(" sigparent: %d\n", p->p_sigparent);
db_printf(" vmspace: %p\n", p->p_vmspace);
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 4a17fb535498..435661107e95 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -186,6 +186,7 @@ ahci_attach(device_t dev)
ctlr->ccc = 0;
resource_int_value(device_get_name(dev),
device_get_unit(dev), "ccc", &ctlr->ccc);
+ mtx_init(&ctlr->ch_mtx, "AHCI channels lock", NULL, MTX_DEF);
/* Setup our own memory management for channels. */
ctlr->sc_iomem.rm_start = rman_get_start(ctlr->r_mem);
@@ -379,6 +380,7 @@ ahci_detach(device_t dev)
/* Free memory. */
rman_fini(&ctlr->sc_iomem);
ahci_free_mem(dev);
+ mtx_destroy(&ctlr->ch_mtx);
return (0);
}
@@ -666,6 +668,50 @@ ahci_get_dma_tag(device_t dev, device_t child)
return (ctlr->dma_tag);
}
+void
+ahci_attached(device_t dev, struct ahci_channel *ch)
+{
+ struct ahci_controller *ctlr = device_get_softc(dev);
+
+ mtx_lock(&ctlr->ch_mtx);
+ ctlr->ch[ch->unit] = ch;
+ mtx_unlock(&ctlr->ch_mtx);
+}
+
+void
+ahci_detached(device_t dev, struct ahci_channel *ch)
+{
+ struct ahci_controller *ctlr = device_get_softc(dev);
+
+ mtx_lock(&ctlr->ch_mtx);
+ mtx_lock(&ch->mtx);
+ ctlr->ch[ch->unit] = NULL;
+ mtx_unlock(&ch->mtx);
+ mtx_unlock(&ctlr->ch_mtx);
+}
+
+struct ahci_channel *
+ahci_getch(device_t dev, int n)
+{
+ struct ahci_controller *ctlr = device_get_softc(dev);
+ struct ahci_channel *ch;
+
+ KASSERT(n >= 0 && n < AHCI_MAX_PORTS, ("Bad channel number %d", n));
+ mtx_lock(&ctlr->ch_mtx);
+ ch = ctlr->ch[n];
+ if (ch != NULL)
+ mtx_lock(&ch->mtx);
+ mtx_unlock(&ctlr->ch_mtx);
+ return (ch);
+}
+
+void
+ahci_putch(struct ahci_channel *ch)
+{
+
+ mtx_unlock(&ch->mtx);
+}
+
static int
ahci_ch_probe(device_t dev)
{
@@ -824,6 +870,7 @@ ahci_ch_attach(device_t dev)
ahci_ch_pm, ch);
}
mtx_unlock(&ch->mtx);
+ ahci_attached(device_get_parent(dev), ch);
ctx = device_get_sysctl_ctx(dev);
tree = device_get_sysctl_tree(dev);
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "disable_phy",
@@ -849,6 +896,7 @@ ahci_ch_detach(device_t dev)
{
struct ahci_channel *ch = device_get_softc(dev);
+ ahci_detached(device_get_parent(dev), ch);
mtx_lock(&ch->mtx);
xpt_async(AC_LOST_DEVICE, ch->path, NULL);
/* Forget about reset. */
diff --git a/sys/dev/ahci/ahci.h b/sys/dev/ahci/ahci.h
index fc53d346f17f..27b3970dadfc 100644
--- a/sys/dev/ahci/ahci.h
+++ b/sys/dev/ahci/ahci.h
@@ -524,6 +524,8 @@ struct ahci_controller {
} interrupt[AHCI_MAX_PORTS];
void (*ch_start)(struct ahci_channel *);
int dma_coherent; /* DMA is cache-coherent */
+ struct mtx ch_mtx; /* Lock for attached channels */
+ struct ahci_channel *ch[AHCI_MAX_PORTS]; /* Attached channels */
};
enum ahci_err_type {
@@ -654,5 +656,11 @@ int ahci_ctlr_reset(device_t dev);
int ahci_ctlr_setup(device_t dev);
void ahci_free_mem(device_t dev);
+/* Functions to allow AHCI EM to access other channels. */
+void ahci_attached(device_t dev, struct ahci_channel *ch);
+void ahci_detached(device_t dev, struct ahci_channel *ch);
+struct ahci_channel * ahci_getch(device_t dev, int n);
+void ahci_putch(struct ahci_channel *ch);
+
extern devclass_t ahci_devclass;
diff --git a/sys/dev/ahci/ahciem.c b/sys/dev/ahci/ahciem.c
index 9bb4d9717763..a6f22fac5639 100644
--- a/sys/dev/ahci/ahciem.c
+++ b/sys/dev/ahci/ahciem.c
@@ -294,14 +294,14 @@ ahci_em_setleds(device_t dev, int c)
enc = device_get_softc(dev);
val = 0;
- if (enc->status[c][2] & 0x80) /* Activity */
+ if (enc->status[c][2] & SESCTL_RQSACT) /* Activity */
val |= (1 << 0);
- if (enc->status[c][2] & SESCTL_RQSID) /* Identification */
+ if (enc->status[c][1] & SESCTL_RQSRR) /* Rebuild */
+ val |= (1 << 6) | (1 << 3);
+ else if (enc->status[c][2] & SESCTL_RQSID) /* Identification */
val |= (1 << 3);
else if (enc->status[c][3] & SESCTL_RQSFLT) /* Fault */
val |= (1 << 6);
- else if (enc->status[c][1] & 0x02) /* Rebuild */
- val |= (1 << 6) | (1 << 3);
timeout = 10000;
while (ATA_INL(enc->r_memc, 0) & (AHCI_EM_TM | AHCI_EM_RST) &&
@@ -366,9 +366,12 @@ static void
ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
{
struct ahci_enclosure *enc;
+ struct ahci_channel *ch;
struct ses_status_page *page;
struct ses_status_array_dev_slot *ads, *ads0;
struct ses_elm_desc_hdr *elmd;
+ struct ses_elm_addlstatus_eip_hdr *elma;
+ struct ses_elm_ata_hdr *elmb;
uint8_t *buf;
int i;
@@ -391,7 +394,7 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
strncpy(&buf[3], device_get_nameunit(dev), 7);
strncpy(&buf[10], "AHCI ", SID_VENDOR_SIZE);
strncpy(&buf[18], "SGPIO Enclosure ", SID_PRODUCT_SIZE);
- strncpy(&buf[34], "1.00", SID_REVISION_SIZE);
+ strncpy(&buf[34], "2.00", SID_REVISION_SIZE);
strncpy(&buf[39], "0001", 4);
strncpy(&buf[43], "S-E-S ", 6);
strncpy(&buf[49], "2.00", 4);
@@ -403,14 +406,15 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
page = (struct ses_status_page *)buf;
if (ccb->ataio.cmd.lba_low == 0x02 &&
ccb->ataio.cmd.features == 0x00 &&
- ccb->ataio.cmd.sector_count >= 2) {
+ ccb->ataio.cmd.sector_count >= 3) {
bzero(buf, ccb->ataio.dxfer_len);
page->hdr.page_code = 0;
- scsi_ulto2b(4, page->hdr.length);
- buf[4] = 0;
- buf[5] = 1;
- buf[6] = 2;
- buf[7] = 7;
+ scsi_ulto2b(5, page->hdr.length);
+ buf[4] = 0x00;
+ buf[5] = 0x01;
+ buf[6] = 0x02;
+ buf[7] = 0x07;
+ buf[8] = 0x0a;
ccb->ccb_h.status = CAM_REQ_CMP;
goto out;
}
@@ -418,26 +422,30 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
/* SEMB RECEIVE DIAGNOSTIC RESULT (1) */
if (ccb->ataio.cmd.lba_low == 0x02 &&
ccb->ataio.cmd.features == 0x01 &&
- ccb->ataio.cmd.sector_count >= 13) {
+ ccb->ataio.cmd.sector_count >= 16) {
struct ses_enc_desc *ed;
struct ses_elm_type_desc *td;
bzero(buf, ccb->ataio.dxfer_len);
page->hdr.page_code = 0x01;
- scsi_ulto2b(4 + 4 + 36 + 4, page->hdr.length);
+ scsi_ulto2b(4 + sizeof(*ed) + sizeof(*td) + 11,
+ page->hdr.length);
ed = (struct ses_enc_desc *)&buf[8];
ed->byte0 = 0x11;
ed->subenc_id = 0;
ed->num_types = 1;
ed->length = 36;
+ ed->logical_id[0] = 0x30; /* NAA Locally Assigned. */
+ strncpy(&ed->logical_id[1], device_get_nameunit(dev), 7);
strncpy(ed->vendor_id, "AHCI ", SID_VENDOR_SIZE);
strncpy(ed->product_id, "SGPIO Enclosure ", SID_PRODUCT_SIZE);
- strncpy(ed->product_rev, " ", SID_REVISION_SIZE);
+ strncpy(ed->product_rev, "2.00", SID_REVISION_SIZE);
td = (struct ses_elm_type_desc *)ses_enc_desc_next(ed);
td->etype_elm_type = 0x17;
td->etype_maxelt = enc->channels;
td->etype_subenc = 0;
- td->etype_txt_len = 0;
+ td->etype_txt_len = 11;
+ snprintf((char *)(td + 1), 12, "Drive Slots");
ccb->ccb_h.status = CAM_REQ_CMP;
goto out;
}
@@ -453,10 +461,22 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
for (i = 0; i < enc->channels; i++) {
ads = &page->elements[i + 1].array_dev_slot;
memcpy(ads, enc->status[i], 4);
- ads->common.bytes[0] |=
- (enc->ichannels & (1 << i)) ?
- SES_OBJSTAT_UNKNOWN :
- SES_OBJSTAT_NOTINSTALLED;
+ ch = ahci_getch(device_get_parent(dev), i);
+ if (ch == NULL) {
+ ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
+ continue;
+ }
+ if (ch->pm_present)
+ ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
+ else if (ch->devices)
+ ads->common.bytes[0] |= SES_OBJSTAT_OK;
+ else if (ch->disablephy)
+ ads->common.bytes[0] |= SES_OBJSTAT_NOTAVAIL;
+ else
+ ads->common.bytes[0] |= SES_OBJSTAT_NOTINSTALLED;
+ if (ch->disablephy)
+ ads->common.bytes[3] |= SESCTL_DEVOFF;
+ ahci_putch(ch);
}
ccb->ccb_h.status = CAM_REQ_CMP;
goto out;
@@ -471,21 +491,21 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
ads = &page->elements[i + 1].array_dev_slot;
if (ads->common.bytes[0] & SESCTL_CSEL) {
enc->status[i][0] = 0;
- enc->status[i][1] =
- ads->bytes[0] & 0x02;
- enc->status[i][2] =
- ads->bytes[1] & (0x80 | SESCTL_RQSID);
- enc->status[i][3] =
- ads->bytes[2] & SESCTL_RQSFLT;
+ enc->status[i][1] = ads->bytes[0] &
+ SESCTL_RQSRR;
+ enc->status[i][2] = ads->bytes[1] &
+ (SESCTL_RQSACT | SESCTL_RQSID);
+ enc->status[i][3] = ads->bytes[2] &
+ SESCTL_RQSFLT;
ahci_em_setleds(dev, i);
} else if (ads0->common.bytes[0] & SESCTL_CSEL) {
enc->status[i][0] = 0;
- enc->status[i][1] =
- ads0->bytes[0] & 0x02;
- enc->status[i][2] =
- ads0->bytes[1] & (0x80 | SESCTL_RQSID);
- enc->status[i][3] =
- ads0->bytes[2] & SESCTL_RQSFLT;
+ enc->status[i][1] = ads0->bytes[0] &
+ SESCTL_RQSRR;
+ enc->status[i][2] = ads0->bytes[1] &
+ (SESCTL_RQSACT | SESCTL_RQSID);
+ enc->status[i][3] = ads0->bytes[2] &
+ SESCTL_RQSFLT;
ahci_em_setleds(dev, i);
}
}
@@ -496,15 +516,48 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
/* SEMB RECEIVE DIAGNOSTIC RESULT (7) */
if (ccb->ataio.cmd.lba_low == 0x02 &&
ccb->ataio.cmd.features == 0x07 &&
- ccb->ataio.cmd.sector_count >= (3 + 3 * enc->channels)) {
+ ccb->ataio.cmd.sector_count >= (6 + 3 * enc->channels)) {
bzero(buf, ccb->ataio.dxfer_len);
page->hdr.page_code = 0x07;
- scsi_ulto2b(4 + 4 + 12 * enc->channels,
+ scsi_ulto2b(4 + 15 + 11 * enc->channels, page->hdr.length);
+ elmd = (struct ses_elm_desc_hdr *)&buf[8];
+ scsi_ulto2b(11, elmd->length);
+ snprintf((char *)(elmd + 1), 12, "Drive Slots");
+ for (i = 0; i < enc->channels; i++) {
+ elmd = (struct ses_elm_desc_hdr *)&buf[8 + 15 + 11 * i];
+ scsi_ulto2b(7, elmd->length);
+ snprintf((char *)(elmd + 1), 8, "Slot %02d", i);
+ }
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ goto out;
+ }
+
+ /* SEMB RECEIVE DIAGNOSTIC RESULT (a) */
+ if (ccb->ataio.cmd.lba_low == 0x02 &&
+ ccb->ataio.cmd.features == 0x0a &&
+ ccb->ataio.cmd.sector_count >= (2 + 3 * enc->channels)) {
+ bzero(buf, ccb->ataio.dxfer_len);
+ page->hdr.page_code = 0x0a;
+ scsi_ulto2b(4 + (sizeof(*elma) + sizeof(*elmb)) * enc->channels,
page->hdr.length);
for (i = 0; i < enc->channels; i++) {
- elmd = (struct ses_elm_desc_hdr *)&buf[8 + 4 + 12 * i];
- scsi_ulto2b(8, elmd->length);
- snprintf((char *)(elmd + 1), 9, "SLOT %03d", i);
+ elma = (struct ses_elm_addlstatus_eip_hdr *)&buf[
+ 8 + (sizeof(*elma) + sizeof(*elmb)) * i];
+ elma->base.byte0 = 0x10 | SPSP_PROTO_ATA;
+ elma->base.length = 2 + sizeof(*elmb);
+ elma->byte2 = 0x01;
+ elma->element_index = 1 + i;
+ ch = ahci_getch(device_get_parent(dev), i);
+ if (ch == NULL) {
+ elma->base.byte0 |= 0x80;
+ continue;
+ }
+ if (ch->devices == 0 || ch->pm_present)
+ elma->base.byte0 |= 0x80;
+ elmb = (struct ses_elm_ata_hdr *)(elma + 1);
+ scsi_ulto4b(cam_sim_path(ch->sim), elmb->bus);
+ scsi_ulto4b(0, elmb->target);
+ ahci_putch(ch);
}
ccb->ccb_h.status = CAM_REQ_CMP;
goto out;
diff --git a/sys/dev/altera/msgdma/msgdma.c b/sys/dev/altera/msgdma/msgdma.c
index c60c7ccfe352..9acb313f91f5 100644
--- a/sys/dev/altera/msgdma/msgdma.c
+++ b/sys/dev/altera/msgdma/msgdma.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <dev/xdma/xdma.h>
#include "xdma_if.h"
+#include "opt_altera_msgdma.h"
#include <dev/altera/msgdma/msgdma.h>
@@ -470,8 +471,8 @@ msgdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan,
struct msgdma_channel *chan;
struct msgdma_desc *desc;
struct msgdma_softc *sc;
- uint32_t src_addr_lo;
- uint32_t dst_addr_lo;
+ bus_addr_t src_addr_lo;
+ bus_addr_t dst_addr_lo;
uint32_t len;
uint32_t tmp;
int i;
@@ -481,14 +482,18 @@ msgdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan,
chan = (struct msgdma_channel *)xchan->chan;
for (i = 0; i < sg_n; i++) {
- src_addr_lo = (uint32_t)sg[i].src_addr;
- dst_addr_lo = (uint32_t)sg[i].dst_addr;
+ src_addr_lo = sg[i].src_addr;
+ dst_addr_lo = sg[i].dst_addr;
len = (uint32_t)sg[i].len;
dprintf("%s: src %x dst %x len %d\n", __func__,
src_addr_lo, dst_addr_lo, len);
desc = chan->descs[chan->idx_head];
+#if defined(ALTERA_MSGDMA_DESC_EXT) || defined(ALTERA_MSGDMA_DESC_PF_EXT)
+ desc->read_hi = htole32(src_addr_lo >> 32);
+ desc->write_hi = htole32(dst_addr_lo >> 32);
+#endif
desc->read_lo = htole32(src_addr_lo);
desc->write_lo = htole32(dst_addr_lo);
desc->length = htole32(len);
diff --git a/sys/dev/altera/msgdma/msgdma.h b/sys/dev/altera/msgdma/msgdma.h
index e10a233902a2..498fb93d86bf 100644
--- a/sys/dev/altera/msgdma/msgdma.h
+++ b/sys/dev/altera/msgdma/msgdma.h
@@ -30,6 +30,8 @@
* $FreeBSD$
*/
+#include "opt_altera_msgdma.h"
+
/* Altera mSGDMA registers. */
#define DMA_STATUS 0x00
#define STATUS_RESETTING (1 << 6)
@@ -75,15 +77,36 @@
#define WRITE4_DESC(_sc, _reg, _val) \
bus_space_write_4(_sc->bst_d, _sc->bsh_d, _reg, htole32(_val))
-/* Prefetcher-disabled descriptor format. */
-struct msgdma_desc_nonpf {
- uint32_t src_addr;
- uint32_t dst_addr;
+#if defined(ALTERA_MSGDMA_DESC_STD)
+
+/* Standard descriptor format with prefetcher disabled. */
+struct msgdma_desc {
+ uint32_t read_lo;
+ uint32_t write_lo;
uint32_t length;
uint32_t control;
};
-/* Prefetcher-enabled descriptor format. */
+#elif defined(ALTERA_MSGDMA_DESC_EXT)
+
+/* Extended descriptor format with prefetcher disabled. */
+struct msgdma_desc {
+ uint32_t read_lo;
+ uint32_t write_lo;
+ uint32_t length;
+ uint8_t write_burst;
+ uint8_t read_burst;
+ uint16_t seq_num;
+ uint16_t write_stride;
+ uint16_t read_stride;
+ uint32_t read_hi;
+ uint32_t write_hi;
+ uint32_t control;
+};
+
+#elif defined(ALTERA_MSGDMA_DESC_PF_STD)
+
+/* Standard descriptor format with prefetcher enabled. */
struct msgdma_desc {
uint32_t read_lo;
uint32_t write_lo;
@@ -94,3 +117,34 @@ struct msgdma_desc {
uint32_t reserved;
uint32_t control;
};
+
+#elif defined(ALTERA_MSGDMA_DESC_PF_EXT)
+
+/* Extended descriptor format with prefetcher enabled. */
+struct msgdma_desc {
+ uint32_t read_lo;
+ uint32_t write_lo;
+ uint32_t length;
+ uint32_t next;
+ uint32_t transferred;
+ uint32_t status;
+ uint32_t reserved;
+ uint8_t write_burst;
+ uint8_t read_burst;
+ uint16_t seq_num;
+ uint16_t write_stride;
+ uint16_t read_stride;
+ uint32_t read_hi;
+ uint32_t write_hi;
+ uint32_t next_hi;
+ uint32_t reserved1;
+ uint32_t reserved2;
+ uint32_t reserved3;
+ uint32_t control;
+};
+
+#else
+
+#error "mSGDMA descriptor format (kernel option) is not set."
+
+#endif
diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c
index 27ef745c764c..fd4f376d8676 100644
--- a/sys/dev/cxgbe/tom/t4_cpl_io.c
+++ b/sys/dev/cxgbe/tom/t4_cpl_io.c
@@ -74,7 +74,7 @@ __FBSDID("$FreeBSD$");
#include "tom/t4_tom.h"
static void t4_aiotx_cancel(struct kaiocb *job);
-static void t4_aiotx_queue_toep(struct toepcb *toep);
+static void t4_aiotx_queue_toep(struct socket *so, struct toepcb *toep);
static size_t
aiotx_mbuf_pgoff(struct mbuf *m)
@@ -785,7 +785,7 @@ t4_push_frames(struct adapter *sc, struct toepcb *toep, int drop)
if (sowwakeup) {
if (!TAILQ_EMPTY(
&toep->aiotx_jobq))
- t4_aiotx_queue_toep(
+ t4_aiotx_queue_toep(so,
toep);
sowwakeup_locked(so);
} else
@@ -829,7 +829,7 @@ t4_push_frames(struct adapter *sc, struct toepcb *toep, int drop)
}
if (sowwakeup) {
if (!TAILQ_EMPTY(&toep->aiotx_jobq))
- t4_aiotx_queue_toep(toep);
+ t4_aiotx_queue_toep(so, toep);
sowwakeup_locked(so);
} else
SOCKBUF_UNLOCK(sb);
@@ -1821,7 +1821,7 @@ do_fw4_ack(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
tls_ofld->sb_off -= plen;
}
if (!TAILQ_EMPTY(&toep->aiotx_jobq))
- t4_aiotx_queue_toep(toep);
+ t4_aiotx_queue_toep(so, toep);
sowwakeup_locked(so); /* unlocks so_snd */
}
SOCKBUF_UNLOCK_ASSERT(sb);
@@ -2195,10 +2195,10 @@ static void
t4_aiotx_task(void *context, int pending)
{
struct toepcb *toep = context;
- struct inpcb *inp = toep->inp;
- struct socket *so = inp->inp_socket;
+ struct socket *so;
struct kaiocb *job;
+ so = toep->aiotx_so;
CURVNET_SET(toep->vnet);
SOCKBUF_LOCK(&so->so_snd);
while (!TAILQ_EMPTY(&toep->aiotx_jobq) && sowriteable(so)) {
@@ -2209,15 +2209,17 @@ t4_aiotx_task(void *context, int pending)
t4_aiotx_process_job(toep, so, job);
}
- toep->aiotx_task_active = false;
+ toep->aiotx_so = NULL;
SOCKBUF_UNLOCK(&so->so_snd);
CURVNET_RESTORE();
free_toepcb(toep);
+ SOCK_LOCK(so);
+ sorele(so);
}
static void
-t4_aiotx_queue_toep(struct toepcb *toep)
+t4_aiotx_queue_toep(struct socket *so, struct toepcb *toep)
{
SOCKBUF_LOCK_ASSERT(&toep->inp->inp_socket->so_snd);
@@ -2225,9 +2227,10 @@ t4_aiotx_queue_toep(struct toepcb *toep)
CTR3(KTR_CXGBE, "%s: queueing aiotx task for tid %d, active = %s",
__func__, toep->tid, toep->aiotx_task_active ? "true" : "false");
#endif
- if (toep->aiotx_task_active)
+ if (toep->aiotx_so != NULL)
return;
- toep->aiotx_task_active = true;
+ soref(so);
+ toep->aiotx_so = so;
hold_toepcb(toep);
soaio_enqueue(&toep->aiotx_task);
}
@@ -2284,7 +2287,7 @@ t4_aio_queue_aiotx(struct socket *so, struct kaiocb *job)
panic("new job was cancelled");
TAILQ_INSERT_TAIL(&toep->aiotx_jobq, job, list);
if (sowriteable(so))
- t4_aiotx_queue_toep(toep);
+ t4_aiotx_queue_toep(so, toep);
SOCKBUF_UNLOCK(&so->so_snd);
return (0);
}
diff --git a/sys/dev/cxgbe/tom/t4_ddp.c b/sys/dev/cxgbe/tom/t4_ddp.c
index 47062e634bbf..f3f03e0faa2c 100644
--- a/sys/dev/cxgbe/tom/t4_ddp.c
+++ b/sys/dev/cxgbe/tom/t4_ddp.c
@@ -220,7 +220,7 @@ release_ddp_resources(struct toepcb *toep)
int i;
DDP_LOCK(toep);
- toep->flags |= DDP_DEAD;
+ toep->ddp.flags |= DDP_DEAD;
for (i = 0; i < nitems(toep->ddp.db); i++) {
free_ddp_buffer(toep->td, &toep->ddp.db[i]);
}
diff --git a/sys/dev/cxgbe/tom/t4_tom.h b/sys/dev/cxgbe/tom/t4_tom.h
index db9e50cd39e1..d4ff4490abad 100644
--- a/sys/dev/cxgbe/tom/t4_tom.h
+++ b/sys/dev/cxgbe/tom/t4_tom.h
@@ -194,7 +194,7 @@ struct toepcb {
TAILQ_HEAD(, kaiocb) aiotx_jobq;
struct task aiotx_task;
- bool aiotx_task_active;
+ struct socket *aiotx_so;
/* Tx software descriptor */
uint8_t txsd_total;
diff --git a/sys/dev/drm2/ttm/ttm_bo_vm.c b/sys/dev/drm2/ttm/ttm_bo_vm.c
index 6f7184857ce6..43d027fc5cd9 100644
--- a/sys/dev/drm2/ttm/ttm_bo_vm.c
+++ b/sys/dev/drm2/ttm/ttm_bo_vm.c
@@ -115,7 +115,7 @@ ttm_bo_vm_fault(vm_object_t vm_obj, vm_ooffset_t offset,
vm_object_pip_add(vm_obj, 1);
if (*mres != NULL) {
vm_page_lock(*mres);
- vm_page_remove(*mres);
+ (void)vm_page_remove(*mres);
vm_page_unlock(*mres);
}
retry:
diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c
index 133b72185d7f..64fadb382a02 100644
--- a/sys/dev/gpio/gpiobus.c
+++ b/sys/dev/gpio/gpiobus.c
@@ -255,13 +255,6 @@ gpiobus_alloc_ivars(struct gpiobus_ivar *devi)
M_NOWAIT | M_ZERO);
if (devi->pins == NULL)
return (ENOMEM);
- devi->flags = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (devi->flags == NULL) {
- free(devi->pins, M_DEVBUF);
- return (ENOMEM);
- }
-
return (0);
}
@@ -269,14 +262,11 @@ void
gpiobus_free_ivars(struct gpiobus_ivar *devi)
{
- if (devi->flags) {
- free(devi->flags, M_DEVBUF);
- devi->flags = NULL;
- }
if (devi->pins) {
free(devi->pins, M_DEVBUF);
devi->pins = NULL;
}
+ devi->npins = 0;
}
int
@@ -326,6 +316,34 @@ gpiobus_release_pin(device_t bus, uint32_t pin)
}
static int
+gpiobus_acquire_child_pins(device_t dev, device_t child)
+{
+ struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
+ int i;
+
+ for (i = 0; i < devi->npins; i++) {
+ /* Reserve the GPIO pin. */
+ if (gpiobus_acquire_pin(dev, devi->pins[i]) != 0) {
+ device_printf(child, "cannot acquire pin %d\n",
+ devi->pins[i]);
+ while (--i >= 0) {
+ (void)gpiobus_release_pin(dev,
+ devi->pins[i]);
+ }
+ gpiobus_free_ivars(devi);
+ return (EBUSY);
+ }
+ }
+ for (i = 0; i < devi->npins; i++) {
+ /* Use the child name as pin name. */
+ GPIOBUS_PIN_SETNAME(dev, devi->pins[i],
+ device_get_nameunit(child));
+
+ }
+ return (0);
+}
+
+static int
gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
{
struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
@@ -349,17 +367,66 @@ gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
for (i = 0; i < 32; i++) {
if ((mask & (1 << i)) == 0)
continue;
- /* Reserve the GPIO pin. */
- if (gpiobus_acquire_pin(sc->sc_busdev, i) != 0) {
- gpiobus_free_ivars(devi);
- return (EINVAL);
- }
devi->pins[npins++] = i;
- /* Use the child name as pin name. */
- GPIOBUS_PIN_SETNAME(sc->sc_busdev, i,
- device_get_nameunit(child));
}
+ if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0)
+ return (EINVAL);
+ return (0);
+}
+
+static int
+gpiobus_parse_pin_list(struct gpiobus_softc *sc, device_t child,
+ const char *pins)
+{
+ struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
+ const char *p;
+ char *endp;
+ unsigned long pin;
+ int i, npins;
+
+ npins = 0;
+ p = pins;
+ for (;;) {
+ pin = strtoul(p, &endp, 0);
+ if (endp == p)
+ break;
+ npins++;
+ if (*endp == '\0')
+ break;
+ p = endp + 1;
+ }
+
+ if (*endp != '\0') {
+ device_printf(child, "garbage in the pin list: %s\n", endp);
+ return (EINVAL);
+ }
+ if (npins == 0) {
+ device_printf(child, "empty pin list\n");
+ return (EINVAL);
+ }
+
+ devi->npins = npins;
+ if (gpiobus_alloc_ivars(devi) != 0) {
+ device_printf(child, "cannot allocate device ivars\n");
+ return (EINVAL);
+ }
+
+ i = 0;
+ p = pins;
+ for (;;) {
+ pin = strtoul(p, &endp, 0);
+
+ devi->pins[i] = pin;
+
+ if (*endp == '\0')
+ break;
+ i++;
+ p = endp + 1;
+ }
+
+ if (gpiobus_acquire_child_pins(sc->sc_busdev, child) != 0)
+ return (EINVAL);
return (0);
}
@@ -539,15 +606,26 @@ gpiobus_hinted_child(device_t bus, const char *dname, int dunit)
struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus);
struct gpiobus_ivar *devi;
device_t child;
- int irq, pins;
+ const char *pins;
+ int irq, pinmask;
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
devi = GPIOBUS_IVAR(child);
- resource_int_value(dname, dunit, "pins", &pins);
- if (gpiobus_parse_pins(sc, child, pins)) {
- resource_list_free(&devi->rl);
- free(devi, M_DEVBUF);
- device_delete_child(bus, child);
+ if (resource_int_value(dname, dunit, "pins", &pinmask) == 0) {
+ if (gpiobus_parse_pins(sc, child, pinmask)) {
+ resource_list_free(&devi->rl);
+ free(devi, M_DEVBUF);
+ device_delete_child(bus, child);
+ return;
+ }
+ }
+ else if (resource_string_value(dname, dunit, "pin_list", &pins) == 0) {
+ if (gpiobus_parse_pin_list(sc, child, pins)) {
+ resource_list_free(&devi->rl);
+ free(devi, M_DEVBUF);
+ device_delete_child(bus, child);
+ return;
+ }
}
if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0)
@@ -574,6 +652,61 @@ gpiobus_set_resource(device_t dev, device_t child, int type, int rid,
return (0);
}
+static int
+gpiobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct gpiobus_ivar *devi;
+
+ devi = GPIOBUS_IVAR(child);
+ switch (which) {
+ case GPIOBUS_IVAR_NPINS:
+ *result = devi->npins;
+ break;
+ case GPIOBUS_IVAR_PINS:
+ /* Children do not ever need to directly examine this. */
+ return (ENOTSUP);
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
+static int
+gpiobus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct gpiobus_ivar *devi;
+ const uint32_t *ptr;
+ int i;
+
+ devi = GPIOBUS_IVAR(child);
+ switch (which) {
+ case GPIOBUS_IVAR_NPINS:
+ /* GPIO ivars are set once. */
+ if (devi->npins != 0) {
+ return (EBUSY);
+ }
+ devi->npins = value;
+ if (gpiobus_alloc_ivars(devi) != 0) {
+ device_printf(child, "cannot allocate device ivars\n");
+ devi->npins = 0;
+ return (ENOMEM);
+ }
+ break;
+ case GPIOBUS_IVAR_PINS:
+ ptr = (const uint32_t *)value;
+ for (i = 0; i < devi->npins; i++)
+ devi->pins[i] = ptr[i];
+ if (gpiobus_acquire_child_pins(dev, child) != 0)
+ return (EBUSY);
+ break;
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
static struct resource *
gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
@@ -833,6 +966,8 @@ static device_method_t gpiobus_methods[] = {
DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str),
DEVMETHOD(bus_child_location_str, gpiobus_child_location_str),
DEVMETHOD(bus_hinted_child, gpiobus_hinted_child),
+ DEVMETHOD(bus_read_ivar, gpiobus_read_ivar),
+ DEVMETHOD(bus_write_ivar, gpiobus_write_ivar),
/* GPIO protocol */
DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus),
diff --git a/sys/dev/gpio/gpiobusvar.h b/sys/dev/gpio/gpiobusvar.h
index 5aa363a23daf..08f0ccf904d0 100644
--- a/sys/dev/gpio/gpiobusvar.h
+++ b/sys/dev/gpio/gpiobusvar.h
@@ -107,10 +107,22 @@ struct gpiobus_ivar
{
struct resource_list rl; /* isr resource list */
uint32_t npins; /* pins total */
- uint32_t *flags; /* pins flags */
uint32_t *pins; /* pins map */
};
+enum gpiobus_ivars {
+ GPIOBUS_IVAR_NPINS = 10500,
+ GPIOBUS_IVAR_PINS,
+};
+
+#define GPIOBUS_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(gpiobus, var, GPIOBUS, ivar, type)
+
+GPIOBUS_ACCESSOR(npins, NPINS, uint32_t)
+GPIOBUS_ACCESSOR(pins, PINS, const uint32_t *)
+
+#undef GPIOBUS_ACCESSOR
+
#ifdef FDT
struct ofw_gpiobus_devinfo {
struct gpiobus_ivar opd_dinfo;
diff --git a/sys/dev/gpio/ofw_gpiobus.c b/sys/dev/gpio/ofw_gpiobus.c
index 698701c8769d..3c48c62feed3 100644
--- a/sys/dev/gpio/ofw_gpiobus.c
+++ b/sys/dev/gpio/ofw_gpiobus.c
@@ -321,10 +321,8 @@ ofw_gpiobus_setup_devinfo(device_t bus, device_t child, phandle_t node)
ofw_gpiobus_destroy_devinfo(bus, dinfo);
return (NULL);
}
- for (i = 0; i < devi->npins; i++) {
- devi->flags[i] = pins[i].flags;
+ for (i = 0; i < devi->npins; i++)
devi->pins[i] = pins[i].pin;
- }
free(pins, M_DEVBUF);
/* Parse the interrupt resources. */
if (ofw_bus_intr_to_rl(bus, node, &dinfo->opd_dinfo.rl, NULL) != 0) {
diff --git a/sys/dev/iicbus/ad7418.c b/sys/dev/iicbus/ad7418.c
index 457b3626c8ef..034597768790 100644
--- a/sys/dev/iicbus/ad7418.c
+++ b/sys/dev/iicbus/ad7418.c
@@ -35,18 +35,9 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/bus.h>
-#include <sys/resource.h>
-#include <sys/rman.h>
#include <sys/sysctl.h>
#include <sys/sx.h>
-#include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/cpufunc.h>
-#include <machine/frame.h>
-#include <machine/resource.h>
-#include <machine/intr.h>
-
#include <dev/iicbus/iiconf.h>
#include "iicbus_if.h"
diff --git a/sys/dev/nand/nand.c b/sys/dev/nand/nand.c
deleted file mode 100644
index 6997ef7f8a0d..000000000000
--- a/sys/dev/nand/nand.c
+++ /dev/null
@@ -1,826 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/callout.h>
-#include <sys/sysctl.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include <dev/nand/nand_ecc_pos.h>
-#include "nfc_if.h"
-#include "nand_if.h"
-#include "nandbus_if.h"
-#include <machine/stdarg.h>
-
-#define NAND_RESET_DELAY 1000 /* tRST */
-#define NAND_ERASE_DELAY 3000 /* tBERS */
-#define NAND_PROG_DELAY 700 /* tPROG */
-#define NAND_READ_DELAY 50 /* tR */
-
-#define BIT0(x) ((x) & 0x1)
-#define BIT1(x) (BIT0(x >> 1))
-#define BIT2(x) (BIT0(x >> 2))
-#define BIT3(x) (BIT0(x >> 3))
-#define BIT4(x) (BIT0(x >> 4))
-#define BIT5(x) (BIT0(x >> 5))
-#define BIT6(x) (BIT0(x >> 6))
-#define BIT7(x) (BIT0(x >> 7))
-
-#define SOFTECC_SIZE 256
-#define SOFTECC_BYTES 3
-
-int nand_debug_flag = 0;
-SYSCTL_INT(_debug, OID_AUTO, nand_debug, CTLFLAG_RWTUN, &nand_debug_flag, 0,
- "NAND subsystem debug flag");
-
-MALLOC_DEFINE(M_NAND, "NAND", "NAND dynamic data");
-
-static void calculate_ecc(const uint8_t *, uint8_t *);
-static int correct_ecc(uint8_t *, uint8_t *, uint8_t *);
-
-void
-nand_debug(int level, const char *fmt, ...)
-{
- va_list ap;
-
- if (!(nand_debug_flag & level))
- return;
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
- printf("\n");
-}
-
-void
-nand_init(struct nand_softc *nand, device_t dev, int ecc_mode,
- int ecc_bytes, int ecc_size, uint16_t *eccposition, char *cdev_name)
-{
-
- nand->ecc.eccmode = ecc_mode;
- nand->chip_cdev_name = cdev_name;
-
- if (ecc_mode == NAND_ECC_SOFT) {
- nand->ecc.eccbytes = SOFTECC_BYTES;
- nand->ecc.eccsize = SOFTECC_SIZE;
- } else if (ecc_mode != NAND_ECC_NONE) {
- nand->ecc.eccbytes = ecc_bytes;
- nand->ecc.eccsize = ecc_size;
- if (eccposition)
- nand->ecc.eccpositions = eccposition;
- }
-}
-
-void
-nand_onfi_set_params(struct nand_chip *chip, struct onfi_chip_params *params)
-{
- struct chip_geom *cg;
-
- cg = &chip->chip_geom;
-
- init_chip_geom(cg, params->luns, params->blocks_per_lun,
- params->pages_per_block, params->bytes_per_page,
- params->spare_bytes_per_page);
- chip->t_bers = params->t_bers;
- chip->t_prog = params->t_prog;
- chip->t_r = params->t_r;
- chip->t_ccs = params->t_ccs;
-
- if (params->features & ONFI_FEAT_16BIT)
- chip->flags |= NAND_16_BIT;
-}
-
-void
-nand_set_params(struct nand_chip *chip, struct nand_params *params)
-{
- struct chip_geom *cg;
- uint32_t blocks_per_chip;
-
- cg = &chip->chip_geom;
- blocks_per_chip = (params->chip_size << 20) /
- (params->page_size * params->pages_per_block);
-
- init_chip_geom(cg, 1, blocks_per_chip,
- params->pages_per_block, params->page_size,
- params->oob_size);
-
- chip->t_bers = NAND_ERASE_DELAY;
- chip->t_prog = NAND_PROG_DELAY;
- chip->t_r = NAND_READ_DELAY;
- chip->t_ccs = 0;
-
- if (params->flags & NAND_16_BIT)
- chip->flags |= NAND_16_BIT;
-}
-
-int
-nand_init_stat(struct nand_chip *chip)
-{
- struct block_stat *blk_stat;
- struct page_stat *pg_stat;
- struct chip_geom *cg;
- uint32_t blks, pgs;
-
- cg = &chip->chip_geom;
- blks = cg->blks_per_lun * cg->luns;
- blk_stat = malloc(sizeof(struct block_stat) * blks, M_NAND,
- M_WAITOK | M_ZERO);
- if (!blk_stat)
- return (ENOMEM);
-
- pgs = blks * cg->pgs_per_blk;
- pg_stat = malloc(sizeof(struct page_stat) * pgs, M_NAND,
- M_WAITOK | M_ZERO);
- if (!pg_stat) {
- free(blk_stat, M_NAND);
- return (ENOMEM);
- }
-
- chip->blk_stat = blk_stat;
- chip->pg_stat = pg_stat;
-
- return (0);
-}
-
-void
-nand_destroy_stat(struct nand_chip *chip)
-{
-
- free(chip->pg_stat, M_NAND);
- free(chip->blk_stat, M_NAND);
-}
-
-int
-init_chip_geom(struct chip_geom *cg, uint32_t luns, uint32_t blks_per_lun,
- uint32_t pgs_per_blk, uint32_t pg_size, uint32_t oob_size)
-{
- int shift;
-
- if (!cg)
- return (-1);
-
- cg->luns = luns;
- cg->blks_per_lun = blks_per_lun;
- cg->blks_per_chip = blks_per_lun * luns;
- cg->pgs_per_blk = pgs_per_blk;
-
- cg->page_size = pg_size;
- cg->oob_size = oob_size;
- cg->block_size = cg->page_size * cg->pgs_per_blk;
- cg->chip_size = cg->block_size * cg->blks_per_chip;
-
- shift = fls(cg->pgs_per_blk - 1);
- cg->pg_mask = (1 << shift) - 1;
- cg->blk_shift = shift;
-
- if (cg->blks_per_lun > 0) {
- shift = fls(cg->blks_per_lun - 1);
- cg->blk_mask = ((1 << shift) - 1) << cg->blk_shift;
- } else {
- shift = 0;
- cg->blk_mask = 0;
- }
-
- cg->lun_shift = shift + cg->blk_shift;
- shift = fls(cg->luns - 1);
- cg->lun_mask = ((1 << shift) - 1) << cg->lun_shift;
-
- nand_debug(NDBG_NAND, "Masks: lun 0x%x blk 0x%x page 0x%x\n"
- "Shifts: lun %d blk %d",
- cg->lun_mask, cg->blk_mask, cg->pg_mask,
- cg->lun_shift, cg->blk_shift);
-
- return (0);
-}
-
-int
-nand_row_to_blkpg(struct chip_geom *cg, uint32_t row, uint32_t *lun,
- uint32_t *blk, uint32_t *pg)
-{
-
- if (!cg || !lun || !blk || !pg)
- return (-1);
-
- if (row & ~(cg->lun_mask | cg->blk_mask | cg->pg_mask)) {
- nand_debug(NDBG_NAND,"Address out of bounds\n");
- return (-1);
- }
-
- *lun = (row & cg->lun_mask) >> cg->lun_shift;
- *blk = (row & cg->blk_mask) >> cg->blk_shift;
- *pg = (row & cg->pg_mask);
-
- nand_debug(NDBG_NAND,"address %x-%x-%x\n", *lun, *blk, *pg);
-
- return (0);
-}
-
-int page_to_row(struct chip_geom *cg, uint32_t page, uint32_t *row)
-{
- uint32_t lun, block, pg_in_blk;
-
- if (!cg || !row)
- return (-1);
-
- block = page / cg->pgs_per_blk;
- pg_in_blk = page % cg->pgs_per_blk;
-
- lun = block / cg->blks_per_lun;
- block = block % cg->blks_per_lun;
-
- *row = (lun << cg->lun_shift) & cg->lun_mask;
- *row |= ((block << cg->blk_shift) & cg->blk_mask);
- *row |= (pg_in_blk & cg->pg_mask);
-
- return (0);
-}
-
-int
-nand_check_page_boundary(struct nand_chip *chip, uint32_t page)
-{
- struct chip_geom* cg;
-
- cg = &chip->chip_geom;
- if (page >= (cg->pgs_per_blk * cg->blks_per_lun * cg->luns)) {
- nand_debug(NDBG_GEN,"%s: page number too big %#x\n",
- __func__, page);
- return (1);
- }
-
- return (0);
-}
-
-void
-nand_get_chip_param(struct nand_chip *chip, struct chip_param_io *param)
-{
- struct chip_geom *cg;
-
- cg = &chip->chip_geom;
- param->page_size = cg->page_size;
- param->oob_size = cg->oob_size;
-
- param->blocks = cg->blks_per_lun * cg->luns;
- param->pages_per_block = cg->pgs_per_blk;
-}
-
-static uint16_t *
-default_software_ecc_positions(struct nand_chip *chip)
-{
- /* If positions have been set already, use them. */
- if (chip->nand->ecc.eccpositions)
- return (chip->nand->ecc.eccpositions);
-
- /*
- * XXX Note that the following logic isn't really sufficient, especially
- * in the ONFI case where the number of ECC bytes can be dictated by
- * values in the parameters page, and that could lead to needing more
- * byte positions than exist within the tables of software-ecc defaults.
- */
- if (chip->chip_geom.oob_size >= 128)
- return (default_software_ecc_positions_128);
- if (chip->chip_geom.oob_size >= 64)
- return (default_software_ecc_positions_64);
- else if (chip->chip_geom.oob_size >= 16)
- return (default_software_ecc_positions_16);
-
- return (NULL);
-}
-
-static void
-calculate_ecc(const uint8_t *buf, uint8_t *ecc)
-{
- uint8_t p8, byte;
- int i;
-
- memset(ecc, 0, 3);
-
- for (i = 0; i < 256; i++) {
- byte = buf[i];
- ecc[0] ^= (BIT0(byte) ^ BIT2(byte) ^ BIT4(byte) ^
- BIT6(byte)) << 2;
- ecc[0] ^= (BIT1(byte) ^ BIT3(byte) ^ BIT5(byte) ^
- BIT7(byte)) << 3;
- ecc[0] ^= (BIT0(byte) ^ BIT1(byte) ^ BIT4(byte) ^
- BIT5(byte)) << 4;
- ecc[0] ^= (BIT2(byte) ^ BIT3(byte) ^ BIT6(byte) ^
- BIT7(byte)) << 5;
- ecc[0] ^= (BIT0(byte) ^ BIT1(byte) ^ BIT2(byte) ^
- BIT3(byte)) << 6;
- ecc[0] ^= (BIT4(byte) ^ BIT5(byte) ^ BIT6(byte) ^
- BIT7(byte)) << 7;
-
- p8 = BIT0(byte) ^ BIT1(byte) ^ BIT2(byte) ^
- BIT3(byte) ^ BIT4(byte) ^ BIT5(byte) ^ BIT6(byte) ^
- BIT7(byte);
-
- if (p8) {
- ecc[2] ^= (0x1 << BIT0(i));
- ecc[2] ^= (0x4 << BIT1(i));
- ecc[2] ^= (0x10 << BIT2(i));
- ecc[2] ^= (0x40 << BIT3(i));
-
- ecc[1] ^= (0x1 << BIT4(i));
- ecc[1] ^= (0x4 << BIT5(i));
- ecc[1] ^= (0x10 << BIT6(i));
- ecc[1] ^= (0x40 << BIT7(i));
- }
- }
- ecc[0] = ~ecc[0];
- ecc[1] = ~ecc[1];
- ecc[2] = ~ecc[2];
- ecc[0] |= 3;
-}
-
-static int
-correct_ecc(uint8_t *buf, uint8_t *calc_ecc, uint8_t *read_ecc)
-{
- uint8_t ecc0, ecc1, ecc2, onesnum, bit, byte;
- uint16_t addr = 0;
-
- ecc0 = calc_ecc[0] ^ read_ecc[0];
- ecc1 = calc_ecc[1] ^ read_ecc[1];
- ecc2 = calc_ecc[2] ^ read_ecc[2];
-
- if (!ecc0 && !ecc1 && !ecc2)
- return (ECC_OK);
-
- addr = BIT3(ecc0) | (BIT5(ecc0) << 1) | (BIT7(ecc0) << 2);
- addr |= (BIT1(ecc2) << 3) | (BIT3(ecc2) << 4) |
- (BIT5(ecc2) << 5) | (BIT7(ecc2) << 6);
- addr |= (BIT1(ecc1) << 7) | (BIT3(ecc1) << 8) |
- (BIT5(ecc1) << 9) | (BIT7(ecc1) << 10);
-
- onesnum = 0;
- while (ecc0 || ecc1 || ecc2) {
- if (ecc0 & 1)
- onesnum++;
- if (ecc1 & 1)
- onesnum++;
- if (ecc2 & 1)
- onesnum++;
-
- ecc0 >>= 1;
- ecc1 >>= 1;
- ecc2 >>= 1;
- }
-
- if (onesnum == 11) {
- /* Correctable error */
- bit = addr & 7;
- byte = addr >> 3;
- buf[byte] ^= (1 << bit);
- return (ECC_CORRECTABLE);
- } else if (onesnum == 1) {
- /* ECC error */
- return (ECC_ERROR_ECC);
- } else {
- /* Uncorrectable error */
- return (ECC_UNCORRECTABLE);
- }
-
- return (0);
-}
-
-int
-nand_softecc_get(device_t dev, uint8_t *buf, int pagesize, uint8_t *ecc)
-{
- int steps = pagesize / SOFTECC_SIZE;
- int i = 0, j = 0;
-
- for (; i < (steps * SOFTECC_BYTES);
- i += SOFTECC_BYTES, j += SOFTECC_SIZE) {
- calculate_ecc(&buf[j], &ecc[i]);
- }
-
- return (0);
-}
-
-int
-nand_softecc_correct(device_t dev, uint8_t *buf, int pagesize,
- uint8_t *readecc, uint8_t *calcecc)
-{
- int steps = pagesize / SOFTECC_SIZE;
- int i = 0, j = 0, ret = 0;
-
- for (i = 0; i < (steps * SOFTECC_BYTES);
- i += SOFTECC_BYTES, j += SOFTECC_SIZE) {
- ret += correct_ecc(&buf[j], &calcecc[i], &readecc[i]);
- if (ret < 0)
- return (ret);
- }
-
- return (ret);
-}
-
-static int
-offset_to_page(struct chip_geom *cg, uint32_t offset)
-{
-
- return (offset / cg->page_size);
-}
-
-int
-nand_read_pages(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len)
-{
- struct chip_geom *cg;
- struct nand_ecc_data *eccd;
- struct page_stat *pg_stat;
- device_t nandbus;
- void *oob = NULL;
- uint8_t *ptr;
- uint16_t *eccpos = NULL;
- uint32_t page, num, steps = 0;
- int i, retval = 0, needwrite;
-
- nand_debug(NDBG_NAND,"%p read page %x[%x]", chip, offset, len);
- cg = &chip->chip_geom;
- eccd = &chip->nand->ecc;
- page = offset_to_page(cg, offset);
- num = len / cg->page_size;
-
- if (eccd->eccmode != NAND_ECC_NONE) {
- steps = cg->page_size / eccd->eccsize;
- eccpos = default_software_ecc_positions(chip);
- oob = malloc(cg->oob_size, M_NAND, M_WAITOK);
- }
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- ptr = (uint8_t *)buf;
- while (num--) {
- pg_stat = &(chip->pg_stat[page]);
-
- if (NAND_READ_PAGE(chip->dev, page, ptr, cg->page_size, 0)) {
- retval = ENXIO;
- break;
- }
-
- if (eccd->eccmode != NAND_ECC_NONE) {
- if (NAND_GET_ECC(chip->dev, ptr, eccd->ecccalculated,
- &needwrite)) {
- retval = ENXIO;
- break;
- }
- nand_debug(NDBG_ECC,"%s: ECC calculated:",
- __func__);
- if (nand_debug_flag & NDBG_ECC)
- for (i = 0; i < (eccd->eccbytes * steps); i++)
- printf("%x ", eccd->ecccalculated[i]);
-
- nand_debug(NDBG_ECC,"\n");
-
- if (NAND_READ_OOB(chip->dev, page, oob, cg->oob_size,
- 0)) {
- retval = ENXIO;
- break;
- }
- for (i = 0; i < (eccd->eccbytes * steps); i++)
- eccd->eccread[i] = ((uint8_t *)oob)[eccpos[i]];
-
- nand_debug(NDBG_ECC,"%s: ECC read:", __func__);
- if (nand_debug_flag & NDBG_ECC)
- for (i = 0; i < (eccd->eccbytes * steps); i++)
- printf("%x ", eccd->eccread[i]);
- nand_debug(NDBG_ECC,"\n");
-
- retval = NAND_CORRECT_ECC(chip->dev, ptr, eccd->eccread,
- eccd->ecccalculated);
-
- nand_debug(NDBG_ECC, "NAND_CORRECT_ECC() returned %d",
- retval);
-
- if (retval == 0)
- pg_stat->ecc_stat.ecc_succeded++;
- else if (retval > 0) {
- pg_stat->ecc_stat.ecc_corrected += retval;
- retval = ECC_CORRECTABLE;
- } else {
- pg_stat->ecc_stat.ecc_failed++;
- break;
- }
- }
-
- pg_stat->page_read++;
- page++;
- ptr += cg->page_size;
- }
-
- NANDBUS_UNLOCK(nandbus);
-
- if (oob)
- free(oob, M_NAND);
-
- return (retval);
-}
-
-int
-nand_read_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len)
-{
- struct chip_geom *cg;
- device_t nandbus;
- uint8_t *ptr;
- uint32_t page, num, end, begin = 0, begin_off;
- int retval = 0;
-
- cg = &chip->chip_geom;
- page = offset_to_page(cg, offset);
- begin_off = offset - page * cg->page_size;
- if (begin_off) {
- begin = cg->page_size - begin_off;
- len -= begin;
- }
- num = len / cg->page_size;
- end = len % cg->page_size;
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- ptr = (uint8_t *)buf;
- if (begin_off) {
- if (NAND_READ_PAGE(chip->dev, page, ptr, begin, begin_off)) {
- NANDBUS_UNLOCK(nandbus);
- return (ENXIO);
- }
-
- page++;
- ptr += begin;
- }
-
- while (num--) {
- if (NAND_READ_PAGE(chip->dev, page, ptr, cg->page_size, 0)) {
- NANDBUS_UNLOCK(nandbus);
- return (ENXIO);
- }
-
- page++;
- ptr += cg->page_size;
- }
-
- if (end)
- if (NAND_READ_PAGE(chip->dev, page, ptr, end, 0)) {
- NANDBUS_UNLOCK(nandbus);
- return (ENXIO);
- }
-
- NANDBUS_UNLOCK(nandbus);
-
- return (retval);
-}
-
-
-int
-nand_prog_pages(struct nand_chip *chip, uint32_t offset, uint8_t *buf,
- uint32_t len)
-{
- struct chip_geom *cg;
- struct page_stat *pg_stat;
- struct nand_ecc_data *eccd;
- device_t nandbus;
- uint32_t page, num;
- uint8_t *oob = NULL;
- uint16_t *eccpos = NULL;
- int steps = 0, i, needwrite, err = 0;
-
- nand_debug(NDBG_NAND,"%p prog page %x[%x]", chip, offset, len);
-
- eccd = &chip->nand->ecc;
- cg = &chip->chip_geom;
- page = offset_to_page(cg, offset);
- num = len / cg->page_size;
-
- if (eccd->eccmode != NAND_ECC_NONE) {
- steps = cg->page_size / eccd->eccsize;
- oob = malloc(cg->oob_size, M_NAND, M_WAITOK);
- eccpos = default_software_ecc_positions(chip);
- }
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- while (num--) {
- if (NAND_PROGRAM_PAGE(chip->dev, page, buf, cg->page_size, 0)) {
- err = ENXIO;
- break;
- }
-
- if (eccd->eccmode != NAND_ECC_NONE) {
- if (NAND_GET_ECC(chip->dev, buf, &eccd->ecccalculated,
- &needwrite)) {
- err = ENXIO;
- break;
- }
- nand_debug(NDBG_ECC,"ECC calculated:");
- if (nand_debug_flag & NDBG_ECC)
- for (i = 0; i < (eccd->eccbytes * steps); i++)
- printf("%x ", eccd->ecccalculated[i]);
-
- nand_debug(NDBG_ECC,"\n");
-
- if (needwrite) {
- if (NAND_READ_OOB(chip->dev, page, oob, cg->oob_size,
- 0)) {
- err = ENXIO;
- break;
- }
-
- for (i = 0; i < (eccd->eccbytes * steps); i++)
- oob[eccpos[i]] = eccd->ecccalculated[i];
-
- if (NAND_PROGRAM_OOB(chip->dev, page, oob,
- cg->oob_size, 0)) {
- err = ENXIO;
- break;
- }
- }
- }
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_written++;
-
- page++;
- buf += cg->page_size;
- }
-
- NANDBUS_UNLOCK(nandbus);
-
- if (oob)
- free(oob, M_NAND);
-
- return (err);
-}
-
-int
-nand_prog_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len)
-{
- struct chip_geom *cg;
- device_t nandbus;
- uint8_t *ptr;
- uint32_t page, num, end, begin = 0, begin_off;
- int retval = 0;
-
- cg = &chip->chip_geom;
- page = offset_to_page(cg, offset);
- begin_off = offset - page * cg->page_size;
- if (begin_off) {
- begin = cg->page_size - begin_off;
- len -= begin;
- }
- num = len / cg->page_size;
- end = len % cg->page_size;
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- ptr = (uint8_t *)buf;
- if (begin_off) {
- if (NAND_PROGRAM_PAGE(chip->dev, page, ptr, begin, begin_off)) {
- NANDBUS_UNLOCK(nandbus);
- return (ENXIO);
- }
-
- page++;
- ptr += begin;
- }
-
- while (num--) {
- if (NAND_PROGRAM_PAGE(chip->dev, page, ptr, cg->page_size, 0)) {
- NANDBUS_UNLOCK(nandbus);
- return (ENXIO);
- }
-
- page++;
- ptr += cg->page_size;
- }
-
- if (end)
- retval = NAND_PROGRAM_PAGE(chip->dev, page, ptr, end, 0);
-
- NANDBUS_UNLOCK(nandbus);
-
- return (retval);
-}
-
-int
-nand_read_oob(struct nand_chip *chip, uint32_t page, void *buf,
- uint32_t len)
-{
- device_t nandbus;
- int retval = 0;
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- retval = NAND_READ_OOB(chip->dev, page, buf, len, 0);
-
- NANDBUS_UNLOCK(nandbus);
-
- return (retval);
-}
-
-
-int
-nand_prog_oob(struct nand_chip *chip, uint32_t page, void *buf,
- uint32_t len)
-{
- device_t nandbus;
- int retval = 0;
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- retval = NAND_PROGRAM_OOB(chip->dev, page, buf, len, 0);
-
- NANDBUS_UNLOCK(nandbus);
-
- return (retval);
-}
-
-int
-nand_erase_blocks(struct nand_chip *chip, off_t offset, size_t len)
-{
- device_t nandbus;
- struct chip_geom *cg;
- uint32_t block, num_blocks;
- int err = 0;
-
- cg = &chip->chip_geom;
- if ((offset % cg->block_size) || (len % cg->block_size))
- return (EINVAL);
-
- block = offset / cg->block_size;
- num_blocks = len / cg->block_size;
- nand_debug(NDBG_NAND,"%p erase blocks %d[%d]", chip, block, num_blocks);
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- while (num_blocks--) {
- if (!nand_check_bad_block(chip, block)) {
- if (NAND_ERASE_BLOCK(chip->dev, block)) {
- nand_debug(NDBG_NAND,"%p erase blocks %d error",
- chip, block);
- nand_mark_bad_block(chip, block);
- err = ENXIO;
- }
- } else
- err = ENXIO;
-
- block++;
- }
-
- NANDBUS_UNLOCK(nandbus);
-
- if (err)
- nand_update_bbt(chip);
-
- return (err);
-}
-
-MODULE_VERSION(nand, 1);
diff --git a/sys/dev/nand/nand.h b/sys/dev/nand/nand.h
deleted file mode 100644
index 06902601b8d0..000000000000
--- a/sys/dev/nand/nand.h
+++ /dev/null
@@ -1,415 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _DEV_NAND_H_
-#define _DEV_NAND_H_
-
-#include <sys/bus.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/sx.h>
-#include <sys/taskqueue.h>
-#include <sys/queue.h>
-#include <sys/bio.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/malloc.h>
-
-#include <dev/nand/nand_dev.h>
-
-MALLOC_DECLARE(M_NAND);
-
-/* Read commands */
-#define NAND_CMD_READ 0x00
-#define NAND_CMD_CHNG_READ_COL 0x05
-#define NAND_CMD_READ_END 0x30
-#define NAND_CMD_READ_CACHE 0x31
-#define NAND_CMD_READ_CPBK 0x35
-#define NAND_CMD_READ_CACHE_END 0x3F
-#define NAND_CMD_CHNG_READ_COL_END 0xE0
-
-/* Erase commands */
-#define NAND_CMD_ERASE 0x60
-#define NAND_CMD_ERASE_END 0xD0
-#define NAND_CMD_ERASE_INTLV 0xD1
-
-/* Program commands */
-#define NAND_CMD_PROG 0x80
-#define NAND_CMD_CHNG_WRITE_COL 0x85
-#define NAND_CMD_PROG_END 0x10
-#define NAND_CMD_PROG_INTLV 0x11
-#define NAND_CMD_PROG_CACHE 0x15
-
-/* Misc commands */
-#define NAND_CMD_STATUS 0x70
-#define NAND_CMD_STATUS_ENH 0x78
-#define NAND_CMD_READ_ID 0x90
-#define NAND_CMD_READ_PARAMETER 0xec
-#define NAND_CMD_READ_UNIQUE_ID 0xed
-#define NAND_CMD_GET_FEATURE 0xee
-#define NAND_CMD_SET_FEATURE 0xef
-
-/* Reset commands */
-#define NAND_CMD_SYNCH_RESET 0xfc
-#define NAND_CMD_RESET 0xff
-
-/* Small page flash commands */
-#define NAND_CMD_SMALLA 0x00
-#define NAND_CMD_SMALLB 0x01
-#define NAND_CMD_SMALLOOB 0x50
-
-#define NAND_STATUS_FAIL 0x1
-#define NAND_STATUS_FAILC 0x2
-#define NAND_STATUS_ARDY 0x20
-#define NAND_STATUS_RDY 0x40
-#define NAND_STATUS_WP 0x80
-
-#define NAND_LP_OOB_COLUMN_START 0x800
-#define NAND_LP_OOBSZ 0x40
-#define NAND_SP_OOB_COLUMN_START 0x200
-#define NAND_SP_OOBSZ 0x10
-
-#define PAGE_PARAM_LENGTH 0x100
-#define PAGE_PARAMETER_DEF 0x0
-#define PAGE_PARAMETER_RED_1 0x100
-#define PAGE_PARAMETER_RED_2 0x200
-
-#define ONFI_SIG_ADDR 0x20
-
-#define NAND_MAX_CHIPS 0x4
-#define NAND_MAX_OOBSZ 512
-#define NAND_MAX_PAGESZ 16384
-
-#define NAND_SMALL_PAGE_SIZE 0x200
-
-#define NAND_16_BIT 0x00000001
-
-#define NAND_ECC_NONE 0x0
-#define NAND_ECC_SOFT 0x1
-#define NAND_ECC_FULLHW 0x2
-#define NAND_ECC_PARTHW 0x4
-#define NAND_ECC_MODE_MASK 0x7
-
-#define ECC_OK 0
-#define ECC_CORRECTABLE 1
-#define ECC_ERROR_ECC (-1)
-#define ECC_UNCORRECTABLE (-2)
-
-#define NAND_MAN_SAMSUNG 0xec
-#define NAND_MAN_HYNIX 0xad
-#define NAND_MAN_STMICRO 0x20
-#define NAND_MAN_MICRON 0x2c
-
-struct nand_id {
- uint8_t man_id;
- uint8_t dev_id;
-};
-
-struct nand_params {
- struct nand_id id;
- char *name;
- uint32_t chip_size;
- uint32_t page_size;
- uint32_t oob_size;
- uint32_t pages_per_block;
- uint32_t flags;
-};
-
-/* nand debug levels */
-#define NDBG_NAND 0x01
-#define NDBG_CDEV 0x02
-#define NDBG_GEN 0x04
-#define NDBG_GEOM 0x08
-#define NDBG_BUS 0x10
-#define NDBG_SIM 0x20
-#define NDBG_CTRL 0x40
-#define NDBG_DRV 0x80
-#define NDBG_ECC 0x100
-
-/* nand_debug_function */
-void nand_debug(int level, const char *fmt, ...);
-extern int nand_debug_flag;
-
-/* ONFI features bit*/
-#define ONFI_FEAT_16BIT 0x01
-#define ONFI_FEAT_MULT_LUN 0x02
-#define ONFI_FEAT_INTLV_OPS 0x04
-#define ONFI_FEAT_CPBK_RESTRICT 0x08
-#define ONFI_FEAT_SRC_SYNCH 0x10
-
-/* ONFI optional commands bits */
-#define ONFI_OPTCOM_PROG_CACHE 0x01
-#define ONFI_OPTCOM_READ_CACHE 0x02
-#define ONFI_OPTCOM_GETSET_FEAT 0x04
-#define ONFI_OPTCOM_STATUS_ENH 0x08
-#define ONFI_OPTCOM_COPYBACK 0x10
-#define ONFI_OPTCOM_UNIQUE_ID 0x20
-
-
-/* Layout of parameter page is defined in ONFI */
-struct onfi_params {
- char signature[4];
- uint16_t rev;
- uint16_t features;
- uint16_t optional_commands;
- uint8_t primary_advanced_command;
- uint8_t res1;
- uint16_t extended_parameter_page_length;
- uint8_t parameter_page_count;
- uint8_t res2[17];
- char manufacturer_name[12];
- char device_model[20];
- uint8_t manufacturer_id;
- uint8_t manufacture_date_yy;
- uint8_t manufacture_date_ww;
- uint8_t res3[13];
- uint32_t bytes_per_page;
- uint16_t spare_bytes_per_page;
- uint32_t bytes_per_partial_page;
- uint16_t spare_bytes_per_partial_page;
- uint32_t pages_per_block;
- uint32_t blocks_per_lun;
- uint8_t luns;
- uint8_t address_cycles;
- uint8_t bits_per_cell;
- uint16_t max_bad_block_per_lun;
- uint16_t block_endurance;
- uint8_t guaranteed_valid_blocks;
- uint16_t valid_block_endurance;
- uint8_t programs_per_page;
- uint8_t partial_prog_attr;
- uint8_t bits_of_ecc;
- uint8_t interleaved_addr_bits;
- uint8_t interleaved_oper_attr;
- uint8_t eznand_support;
- uint8_t res4[12];
- uint8_t pin_capacitance;
- uint16_t asynch_timing_mode_support;
- uint16_t asynch_prog_cache_timing_mode_support;
- uint16_t t_prog; /* us, max page program time */
- uint16_t t_bers; /* us, max block erase time */
- uint16_t t_r; /* us, max page read time */
- uint16_t t_ccs; /* ns, min change column setup time */
- uint16_t source_synch_timing_mode_support;
- uint8_t source_synch_feat;
- uint16_t clk_input_capacitance;
- uint16_t io_capacitance;
- uint16_t input_capacitance;
- uint8_t input_capacitance_max;
- uint8_t driver_strength_support;
- uint16_t t_r_interleaved;
- uint16_t t_adl;
- uint16_t t_r_eznand;
- uint8_t nv_ddr2_features;
- uint8_t nv_ddr2_warmup_cycles;
- uint8_t res5[4];
- uint16_t vendor_rev;
- uint8_t vendor_spec[88];
- uint16_t crc;
-}__attribute__((packed));
-CTASSERT(sizeof(struct onfi_params) == 256);
-
-struct onfi_chip_params {
- uint32_t blocks_per_lun;
- uint32_t pages_per_block;
- uint32_t bytes_per_page;
- uint32_t spare_bytes_per_page;
- uint16_t t_bers;
- uint16_t t_prog;
- uint16_t t_r;
- uint16_t t_ccs;
- uint16_t features;
- uint8_t address_cycles;
- uint8_t luns;
-};
-
-struct nand_ecc_data {
- int eccsize; /* Number of data bytes per ECC step */
- int eccmode;
- int eccbytes; /* Number of ECC bytes per step */
-
- uint16_t *eccpositions; /* Positions of ecc bytes */
- uint8_t ecccalculated[NAND_MAX_OOBSZ];
- uint8_t eccread[NAND_MAX_OOBSZ];
-};
-
-struct ecc_stat {
- uint32_t ecc_succeded;
- uint32_t ecc_corrected;
- uint32_t ecc_failed;
-};
-
-struct page_stat {
- struct ecc_stat ecc_stat;
- uint32_t page_read;
- uint32_t page_raw_read;
- uint32_t page_written;
- uint32_t page_raw_written;
-};
-
-struct block_stat {
- uint32_t block_erased;
-};
-
-struct chip_geom {
- uint32_t chip_size;
- uint32_t block_size;
- uint32_t page_size;
- uint32_t oob_size;
-
- uint32_t luns;
- uint32_t blks_per_lun;
- uint32_t blks_per_chip;
- uint32_t pgs_per_blk;
-
- uint32_t pg_mask;
- uint32_t blk_mask;
- uint32_t lun_mask;
- uint8_t blk_shift;
- uint8_t lun_shift;
-};
-
-struct nand_chip {
- device_t dev;
- struct nand_id id;
- struct chip_geom chip_geom;
-
- uint16_t t_prog; /* us, max page program time */
- uint16_t t_bers; /* us, max block erase time */
- uint16_t t_r; /* us, max page read time */
- uint16_t t_ccs; /* ns, min change column setup time */
- uint8_t num;
- uint8_t flags;
-
- struct page_stat *pg_stat;
- struct block_stat *blk_stat;
- struct nand_softc *nand;
- struct nand_bbt *bbt;
- struct nand_ops *ops;
- struct cdev *cdev;
-
- struct disk *ndisk;
- struct disk *rdisk;
- struct bio_queue_head bioq; /* bio queue */
- struct mtx qlock; /* bioq lock */
- struct taskqueue *tq; /* private task queue for i/o request */
- struct task iotask; /* i/o processing */
-
-};
-
-struct nand_softc {
- uint8_t flags;
-
- char *chip_cdev_name;
- struct nand_ecc_data ecc;
-};
-
-/* NAND ops */
-int nand_erase_blocks(struct nand_chip *chip, off_t offset, size_t len);
-int nand_prog_pages(struct nand_chip *chip, uint32_t offset, uint8_t *buf,
- uint32_t len);
-int nand_read_pages(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len);
-int nand_read_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len);
-int nand_prog_pages_raw(struct nand_chip *chip, uint32_t offset, void *buf,
- uint32_t len);
-int nand_read_oob(struct nand_chip *chip, uint32_t page, void *buf,
- uint32_t len);
-int nand_prog_oob(struct nand_chip *chip, uint32_t page, void *buf,
- uint32_t len);
-
-int nand_select_cs(device_t dev, uint8_t cs);
-
-int nand_read_parameter(struct nand_softc *nand, struct onfi_params *param);
-int nand_synch_reset(struct nand_softc *nand);
-int nand_chng_read_col(device_t dev, uint32_t col, void *buf, size_t len);
-int nand_chng_write_col(device_t dev, uint32_t col, void *buf, size_t len);
-int nand_get_feature(device_t dev, uint8_t feat, void* buf);
-int nand_set_feature(device_t dev, uint8_t feat, void* buf);
-
-
-int nand_erase_block_intlv(device_t dev, uint32_t block);
-int nand_copyback_read(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len);
-int nand_copyback_prog(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len);
-int nand_copyback_prog_intlv(device_t dev, uint32_t page);
-int nand_prog_cache(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len, uint8_t end);
-int nand_prog_intlv(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len);
-int nand_read_cache(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len, uint8_t end);
-
-int nand_write_ecc(struct nand_softc *nand, uint32_t page, uint8_t *data);
-int nand_read_ecc(struct nand_softc *nand, uint32_t page, uint8_t *data);
-
-int nand_softecc_get(device_t dev, uint8_t *buf, int pagesize, uint8_t *ecc);
-int nand_softecc_correct(device_t dev, uint8_t *buf, int pagesize,
- uint8_t *readecc, uint8_t *calcecc);
-
-/* Chip initialization */
-void nand_init(struct nand_softc *nand, device_t dev, int ecc_mode,
- int ecc_bytes, int ecc_size, uint16_t* eccposition, char* cdev_name);
-void nand_detach(struct nand_softc *nand);
-struct nand_params *nand_get_params(struct nand_id *id);
-
-void nand_onfi_set_params(struct nand_chip *chip, struct onfi_chip_params *params);
-void nand_set_params(struct nand_chip *chip, struct nand_params *params);
-int nand_init_stat(struct nand_chip *chip);
-void nand_destroy_stat(struct nand_chip *chip);
-
-/* BBT */
-int nand_init_bbt(struct nand_chip *chip);
-void nand_destroy_bbt(struct nand_chip *chip);
-int nand_update_bbt(struct nand_chip *chip);
-int nand_mark_bad_block(struct nand_chip* chip, uint32_t block_num);
-int nand_check_bad_block(struct nand_chip* chip, uint32_t block_num);
-
-/* cdev creation/removal */
-int nand_make_dev(struct nand_chip* chip);
-void nand_destroy_dev(struct nand_chip *chip);
-
-int create_geom_disk(struct nand_chip* chip);
-int create_geom_raw_disk(struct nand_chip *chip);
-void destroy_geom_disk(struct nand_chip *chip);
-void destroy_geom_raw_disk(struct nand_chip *chip);
-
-int init_chip_geom(struct chip_geom* cg, uint32_t luns, uint32_t blks_per_lun,
- uint32_t pgs_per_blk, uint32_t pg_size, uint32_t oob_size);
-int nand_row_to_blkpg(struct chip_geom *cg, uint32_t row, uint32_t *lun,
- uint32_t *blk, uint32_t *pg);
-int page_to_row(struct chip_geom *cg, uint32_t page, uint32_t *row);
-int nand_check_page_boundary(struct nand_chip *chip, uint32_t page);
-void nand_get_chip_param(struct nand_chip *chip, struct chip_param_io *param);
-
-#endif /* _DEV_NAND_H_ */
diff --git a/sys/dev/nand/nand_bbt.c b/sys/dev/nand/nand_bbt.c
deleted file mode 100644
index d99ed67523a2..000000000000
--- a/sys/dev/nand/nand_bbt.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/cdefs.h>
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
-#include <sys/malloc.h>
-#include <sys/bus.h>
-
-#include <dev/nand/nand.h>
-
-#include "nand_if.h"
-
-#define BBT_PRIMARY_PATTERN 0x01020304
-#define BBT_SECONDARY_PATTERN 0x05060708
-
-enum bbt_place {
- BBT_NONE,
- BBT_PRIMARY,
- BBT_SECONDARY
-};
-
-struct nand_bbt {
- struct nand_chip *chip;
- uint32_t primary_map;
- uint32_t secondary_map;
- enum bbt_place active;
- struct bbt_header *hdr;
- uint32_t tab_len;
- uint32_t *table;
-};
-
-struct bbt_header {
- uint32_t pattern;
- int32_t seq_nr;
-};
-
-static int nand_bbt_save(struct nand_bbt *);
-static int nand_bbt_load_hdr(struct nand_bbt *, struct bbt_header *, int8_t);
-static int nand_bbt_load_table(struct nand_bbt *);
-static int nand_bbt_prescan(struct nand_bbt *);
-
-int
-nand_init_bbt(struct nand_chip *chip)
-{
- struct chip_geom *cg;
- struct nand_bbt *bbt;
- int err;
-
- cg = &chip->chip_geom;
-
- bbt = malloc(sizeof(struct nand_bbt), M_NAND, M_ZERO | M_WAITOK);
- if (!bbt) {
- device_printf(chip->dev,
- "Cannot allocate memory for bad block struct");
- return (ENOMEM);
- }
-
- bbt->chip = chip;
- bbt->active = BBT_NONE;
- bbt->primary_map = cg->chip_size - cg->block_size;
- bbt->secondary_map = cg->chip_size - 2 * cg->block_size;
- bbt->tab_len = cg->blks_per_chip * sizeof(uint32_t);
- bbt->hdr = malloc(sizeof(struct bbt_header) + bbt->tab_len, M_NAND,
- M_WAITOK);
- if (!bbt->hdr) {
- device_printf(chip->dev, "Cannot allocate %d bytes for BB "
- "Table", bbt->tab_len);
- free(bbt, M_NAND);
- return (ENOMEM);
- }
- bbt->hdr->seq_nr = 0;
- bbt->table = (uint32_t *)((uint8_t *)bbt->hdr +
- sizeof(struct bbt_header));
-
- err = nand_bbt_load_table(bbt);
- if (err) {
- free(bbt->table, M_NAND);
- free(bbt, M_NAND);
- return (err);
- }
-
- chip->bbt = bbt;
- if (bbt->active == BBT_NONE) {
- bbt->active = BBT_PRIMARY;
- memset(bbt->table, 0xff, bbt->tab_len);
- nand_bbt_prescan(bbt);
- nand_bbt_save(bbt);
- } else
- device_printf(chip->dev, "Found BBT table for chip\n");
-
- return (0);
-}
-
-void
-nand_destroy_bbt(struct nand_chip *chip)
-{
-
- if (chip->bbt) {
- nand_bbt_save(chip->bbt);
-
- free(chip->bbt->hdr, M_NAND);
- free(chip->bbt, M_NAND);
- chip->bbt = NULL;
- }
-}
-
-int
-nand_update_bbt(struct nand_chip *chip)
-{
-
- nand_bbt_save(chip->bbt);
-
- return (0);
-}
-
-static int
-nand_bbt_save(struct nand_bbt *bbt)
-{
- enum bbt_place next;
- uint32_t addr;
- int32_t err;
-
- if (bbt->active == BBT_PRIMARY) {
- addr = bbt->secondary_map;
- bbt->hdr->pattern = BBT_SECONDARY_PATTERN;
- next = BBT_SECONDARY;
- } else {
- addr = bbt->primary_map;
- bbt->hdr->pattern = BBT_PRIMARY_PATTERN;
- next = BBT_PRIMARY;
- }
-
- err = nand_erase_blocks(bbt->chip, addr,
- bbt->chip->chip_geom.block_size);
- if (err)
- return (err);
-
- bbt->hdr->seq_nr++;
-
- err = nand_prog_pages_raw(bbt->chip, addr, bbt->hdr,
- bbt->tab_len + sizeof(struct bbt_header));
- if (err)
- return (err);
-
- bbt->active = next;
- return (0);
-}
-
-static int
-nand_bbt_load_hdr(struct nand_bbt *bbt, struct bbt_header *hdr, int8_t primary)
-{
- uint32_t addr;
-
- if (primary)
- addr = bbt->primary_map;
- else
- addr = bbt->secondary_map;
-
- return (nand_read_pages_raw(bbt->chip, addr, hdr,
- sizeof(struct bbt_header)));
-}
-
-static int
-nand_bbt_load_table(struct nand_bbt *bbt)
-{
- struct bbt_header hdr1, hdr2;
- uint32_t address = 0;
- int err = 0;
-
- bzero(&hdr1, sizeof(hdr1));
- bzero(&hdr2, sizeof(hdr2));
-
- nand_bbt_load_hdr(bbt, &hdr1, 1);
- if (hdr1.pattern == BBT_PRIMARY_PATTERN) {
- bbt->active = BBT_PRIMARY;
- address = bbt->primary_map;
- } else
- bzero(&hdr1, sizeof(hdr1));
-
-
- nand_bbt_load_hdr(bbt, &hdr2, 0);
- if ((hdr2.pattern == BBT_SECONDARY_PATTERN) &&
- (hdr2.seq_nr > hdr1.seq_nr)) {
- bbt->active = BBT_SECONDARY;
- address = bbt->secondary_map;
- } else
- bzero(&hdr2, sizeof(hdr2));
-
- if (bbt->active != BBT_NONE)
- err = nand_read_pages_raw(bbt->chip, address, bbt->hdr,
- bbt->tab_len + sizeof(struct bbt_header));
-
- return (err);
-}
-
-static int
-nand_bbt_prescan(struct nand_bbt *bbt)
-{
- int32_t i;
- uint8_t bad;
- bool printed_hash = 0;
-
- device_printf(bbt->chip->dev, "No BBT found. Prescan chip...\n");
- for (i = 0; i < bbt->chip->chip_geom.blks_per_chip; i++) {
- if (NAND_IS_BLK_BAD(bbt->chip->dev, i, &bad))
- return (ENXIO);
-
- if (bad) {
- device_printf(bbt->chip->dev, "Bad block(%d)\n", i);
- bbt->table[i] = 0x0FFFFFFF;
- }
- if (!(i % 100)) {
- printf("#");
- printed_hash = 1;
- }
- }
-
- if (printed_hash)
- printf("\n");
-
- return (0);
-}
-
-int
-nand_check_bad_block(struct nand_chip *chip, uint32_t block_number)
-{
-
- if (!chip || !chip->bbt)
- return (0);
-
- if ((chip->bbt->table[block_number] & 0xF0000000) == 0)
- return (1);
-
- return (0);
-}
-
-int
-nand_mark_bad_block(struct nand_chip *chip, uint32_t block_number)
-{
-
- chip->bbt->table[block_number] = 0x0FFFFFFF;
-
- return (0);
-}
diff --git a/sys/dev/nand/nand_cdev.c b/sys/dev/nand/nand_cdev.c
deleted file mode 100644
index 53c62dbc2913..000000000000
--- a/sys/dev/nand/nand_cdev.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/bus.h>
-#include <sys/malloc.h>
-#include <sys/uio.h>
-#include <sys/bio.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include <dev/nand/nand_dev.h>
-#include "nand_if.h"
-#include "nandbus_if.h"
-
-static int nand_page_stat(struct nand_chip *, struct page_stat_io *);
-static int nand_block_stat(struct nand_chip *, struct block_stat_io *);
-
-static d_ioctl_t nand_ioctl;
-static d_open_t nand_open;
-static d_strategy_t nand_strategy;
-
-static struct cdevsw nand_cdevsw = {
- .d_version = D_VERSION,
- .d_name = "nand",
- .d_open = nand_open,
- .d_read = physread,
- .d_write = physwrite,
- .d_ioctl = nand_ioctl,
- .d_strategy = nand_strategy,
-};
-
-static int
-offset_to_page(struct chip_geom *cg, uint32_t offset)
-{
-
- return (offset / cg->page_size);
-}
-
-static int
-offset_to_page_off(struct chip_geom *cg, uint32_t offset)
-{
-
- return (offset % cg->page_size);
-}
-
-int
-nand_make_dev(struct nand_chip *chip)
-{
- struct nandbus_ivar *ivar;
- device_t parent, nandbus;
- int parent_unit, unit;
- char *name;
-
- ivar = device_get_ivars(chip->dev);
- nandbus = device_get_parent(chip->dev);
-
- if (ivar->chip_cdev_name) {
- name = ivar->chip_cdev_name;
-
- /*
- * If we got distinct name for chip device we can enumarete it
- * based on contoller number.
- */
- parent = device_get_parent(nandbus);
- } else {
- name = "nand";
- parent = nandbus;
- }
-
- parent_unit = device_get_unit(parent);
- unit = parent_unit * 4 + chip->num;
- chip->cdev = make_dev(&nand_cdevsw, unit, UID_ROOT, GID_WHEEL,
- 0666, "%s%d.%d", name, parent_unit, chip->num);
-
- if (chip->cdev == NULL)
- return (ENXIO);
-
- if (bootverbose)
- device_printf(chip->dev, "Created cdev %s%d.%d for chip "
- "[0x%0x, 0x%0x]\n", name, parent_unit, chip->num,
- ivar->man_id, ivar->dev_id);
-
- chip->cdev->si_drv1 = chip;
-
- return (0);
-}
-
-void
-nand_destroy_dev(struct nand_chip *chip)
-{
-
- if (chip->cdev)
- destroy_dev(chip->cdev);
-}
-
-static int
-nand_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
-
- return (0);
-}
-
-static int
-nand_read(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
-{
- struct chip_geom *cg;
- device_t nandbus;
- int start_page, count, off, err = 0;
- uint8_t *ptr, *tmp;
-
- nand_debug(NDBG_CDEV, "Read from chip%d [%p] at %d\n", chip->num,
- chip, offset);
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- cg = &chip->chip_geom;
- start_page = offset_to_page(cg, offset);
- off = offset_to_page_off(cg, offset);
- count = (len > cg->page_size - off) ? cg->page_size - off : len;
-
- ptr = (uint8_t *)buf;
- while (len > 0) {
- if (len < cg->page_size) {
- tmp = malloc(cg->page_size, M_NAND, M_WAITOK);
- if (!tmp) {
- err = ENOMEM;
- break;
- }
- err = NAND_READ_PAGE(chip->dev, start_page,
- tmp, cg->page_size, 0);
- if (err) {
- free(tmp, M_NAND);
- break;
- }
- bcopy(tmp + off, ptr, count);
- free(tmp, M_NAND);
- } else {
- err = NAND_READ_PAGE(chip->dev, start_page,
- ptr, cg->page_size, 0);
- if (err)
- break;
- }
-
- len -= count;
- start_page++;
- ptr += count;
- count = (len > cg->page_size) ? cg->page_size : len;
- off = 0;
- }
-
- NANDBUS_UNLOCK(nandbus);
- return (err);
-}
-
-static int
-nand_write(struct nand_chip *chip, uint32_t offset, void* buf, uint32_t len)
-{
- struct chip_geom *cg;
- device_t nandbus;
- int off, start_page, err = 0;
- uint8_t *ptr;
-
- nand_debug(NDBG_CDEV, "Write to chip %d [%p] at %d\n", chip->num,
- chip, offset);
-
- nandbus = device_get_parent(chip->dev);
- NANDBUS_LOCK(nandbus);
- NANDBUS_SELECT_CS(device_get_parent(chip->dev), chip->num);
-
- cg = &chip->chip_geom;
- start_page = offset_to_page(cg, offset);
- off = offset_to_page_off(cg, offset);
-
- if (off != 0 || (len % cg->page_size) != 0) {
- printf("Not aligned write start [0x%08x] size [0x%08x]\n",
- off, len);
- NANDBUS_UNLOCK(nandbus);
- return (EINVAL);
- }
-
- ptr = (uint8_t *)buf;
- while (len > 0) {
- err = NAND_PROGRAM_PAGE(chip->dev, start_page, ptr,
- cg->page_size, 0);
- if (err)
- break;
-
- len -= cg->page_size;
- start_page++;
- ptr += cg->page_size;
- }
-
- NANDBUS_UNLOCK(nandbus);
- return (err);
-}
-
-static void
-nand_strategy(struct bio *bp)
-{
- struct nand_chip *chip;
- struct cdev *dev;
- int err = 0;
-
- dev = bp->bio_dev;
- chip = dev->si_drv1;
-
- nand_debug(NDBG_CDEV, "Strategy %s on chip %d [%p]\n",
- bp->bio_cmd == BIO_READ ? "READ" : "WRITE",
- chip->num, chip);
-
- if (bp->bio_cmd == BIO_READ) {
- err = nand_read(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- } else {
- err = nand_write(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- }
-
- if (err == 0)
- bp->bio_resid = 0;
- else {
- bp->bio_error = EIO;
- bp->bio_flags |= BIO_ERROR;
- bp->bio_resid = bp->bio_bcount;
- }
-
- biodone(bp);
-}
-
-static int
-nand_oob_access(struct nand_chip *chip, uint32_t page, uint32_t offset,
- uint32_t len, uint8_t *data, uint8_t write)
-{
- struct chip_geom *cg;
- uint8_t *buf = NULL;
- int ret = 0;
-
- cg = &chip->chip_geom;
-
- buf = malloc(cg->oob_size, M_NAND, M_WAITOK);
- if (!buf)
- return (ENOMEM);
-
- memset(buf, 0xff, cg->oob_size);
-
- if (!write) {
- ret = nand_read_oob(chip, page, buf, cg->oob_size);
- copyout(buf, data, len);
- } else {
- copyin(data, buf, len);
- ret = nand_prog_oob(chip, page, buf, cg->oob_size);
- }
-
- free(buf, M_NAND);
-
- return (ret);
-}
-
-static int
-nand_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
- struct thread *td)
-{
- struct nand_chip *chip;
- struct chip_geom *cg;
- struct nand_oob_rw *oob_rw = NULL;
- struct nand_raw_rw *raw_rw = NULL;
- device_t nandbus;
- size_t bufsize = 0, len = 0;
- size_t raw_size;
- off_t off;
- uint8_t *buf = NULL;
- int ret = 0;
- uint8_t status;
-
- chip = (struct nand_chip *)dev->si_drv1;
- cg = &chip->chip_geom;
- nandbus = device_get_parent(chip->dev);
-
- if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) {
- raw_rw = (struct nand_raw_rw *)data;
- raw_size = cg->pgs_per_blk * (cg->page_size + cg->oob_size);
-
- /* Check if len is not bigger than chip size */
- if (raw_rw->len > raw_size)
- return (EFBIG);
-
- /*
- * Do not ask for too much memory, in case of large transfers
- * read/write in 16-pages chunks
- */
- bufsize = 16 * (cg->page_size + cg->oob_size);
- if (raw_rw->len < bufsize)
- bufsize = raw_rw->len;
-
- buf = malloc(bufsize, M_NAND, M_WAITOK);
- len = raw_rw->len;
- off = 0;
- }
- switch(cmd) {
- case NAND_IO_ERASE:
- ret = nand_erase_blocks(chip, ((off_t *)data)[0],
- ((off_t *)data)[1]);
- break;
-
- case NAND_IO_OOB_READ:
- oob_rw = (struct nand_oob_rw *)data;
- ret = nand_oob_access(chip, oob_rw->page, 0,
- oob_rw->len, oob_rw->data, 0);
- break;
-
- case NAND_IO_OOB_PROG:
- oob_rw = (struct nand_oob_rw *)data;
- ret = nand_oob_access(chip, oob_rw->page, 0,
- oob_rw->len, oob_rw->data, 1);
- break;
-
- case NAND_IO_GET_STATUS:
- NANDBUS_LOCK(nandbus);
- ret = NANDBUS_GET_STATUS(nandbus, &status);
- if (ret == 0)
- *(uint8_t *)data = status;
- NANDBUS_UNLOCK(nandbus);
- break;
-
- case NAND_IO_RAW_PROG:
- while (len > 0) {
- if (len < bufsize)
- bufsize = len;
- ret = copyin(raw_rw->data + off, buf, bufsize);
- if (ret)
- break;
- ret = nand_prog_pages_raw(chip, raw_rw->off + off, buf,
- bufsize);
- if (ret)
- break;
- len -= bufsize;
- off += bufsize;
- }
- break;
-
- case NAND_IO_RAW_READ:
- while (len > 0) {
- if (len < bufsize)
- bufsize = len;
-
- ret = nand_read_pages_raw(chip, raw_rw->off + off, buf,
- bufsize);
- if (ret)
- break;
-
- ret = copyout(buf, raw_rw->data + off, bufsize);
- if (ret)
- break;
- len -= bufsize;
- off += bufsize;
- }
- break;
-
- case NAND_IO_PAGE_STAT:
- ret = nand_page_stat(chip, (struct page_stat_io *)data);
- break;
-
- case NAND_IO_BLOCK_STAT:
- ret = nand_block_stat(chip, (struct block_stat_io *)data);
- break;
-
- case NAND_IO_GET_CHIP_PARAM:
- nand_get_chip_param(chip, (struct chip_param_io *)data);
- break;
-
- default:
- printf("Unknown nand_ioctl request \n");
- ret = EIO;
- }
-
- if (buf)
- free(buf, M_NAND);
-
- return (ret);
-}
-
-static int
-nand_page_stat(struct nand_chip *chip, struct page_stat_io *page_stat)
-{
- struct chip_geom *cg;
- struct page_stat *stat;
- int num_pages;
-
- cg = &chip->chip_geom;
- num_pages = cg->pgs_per_blk * cg->blks_per_lun * cg->luns;
- if (page_stat->page_num >= num_pages)
- return (EINVAL);
-
- stat = &chip->pg_stat[page_stat->page_num];
- page_stat->page_read = stat->page_read;
- page_stat->page_written = stat->page_written;
- page_stat->page_raw_read = stat->page_raw_read;
- page_stat->page_raw_written = stat->page_raw_written;
- page_stat->ecc_succeded = stat->ecc_stat.ecc_succeded;
- page_stat->ecc_corrected = stat->ecc_stat.ecc_corrected;
- page_stat->ecc_failed = stat->ecc_stat.ecc_failed;
-
- return (0);
-}
-
-static int
-nand_block_stat(struct nand_chip *chip, struct block_stat_io *block_stat)
-{
- struct chip_geom *cg;
- uint32_t block_num = block_stat->block_num;
-
- cg = &chip->chip_geom;
- if (block_num >= cg->blks_per_lun * cg->luns)
- return (EINVAL);
-
- block_stat->block_erased = chip->blk_stat[block_num].block_erased;
-
- return (0);
-}
diff --git a/sys/dev/nand/nand_dev.h b/sys/dev/nand/nand_dev.h
deleted file mode 100644
index bd00c4d4b3b4..000000000000
--- a/sys/dev/nand/nand_dev.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _DEV_NAND_CDEV_H_
-#define _DEV_NAND_CDEV_H_
-
-#include <sys/ioccom.h>
-#include <sys/param.h>
-
-struct nand_raw_rw {
- off_t off;
- off_t len;
- uint8_t *data;
-};
-
-struct nand_oob_rw {
- uint32_t page;
- off_t len;
- uint8_t *data;
-};
-
-#define NAND_IOCTL_GROUP 'N'
-#define NAND_IO_ERASE _IOWR(NAND_IOCTL_GROUP, 0x0, off_t[2])
-
-#define NAND_IO_OOB_READ _IOWR(NAND_IOCTL_GROUP, 0x1, struct nand_oob_rw)
-
-#define NAND_IO_OOB_PROG _IOWR(NAND_IOCTL_GROUP, 0x2, struct nand_oob_rw)
-
-#define NAND_IO_RAW_READ _IOWR(NAND_IOCTL_GROUP, 0x3, struct nand_raw_rw)
-
-#define NAND_IO_RAW_PROG _IOWR(NAND_IOCTL_GROUP, 0x4, struct nand_raw_rw)
-
-#define NAND_IO_GET_STATUS _IOWR(NAND_IOCTL_GROUP, 0x5, uint8_t)
-
-struct page_stat_io {
- uint32_t page_num;
- uint32_t page_read;
- uint32_t page_written;
- uint32_t page_raw_read;
- uint32_t page_raw_written;
- uint32_t ecc_succeded;
- uint32_t ecc_corrected;
- uint32_t ecc_failed;
-};
-#define NAND_IO_PAGE_STAT _IOWR(NAND_IOCTL_GROUP, 0x6, \
- struct page_stat_io)
-
-struct block_stat_io {
- uint32_t block_num;
- uint32_t block_erased;
-};
-#define NAND_IO_BLOCK_STAT _IOWR(NAND_IOCTL_GROUP, 0x7, \
- struct block_stat_io)
-
-struct chip_param_io {
- uint32_t page_size;
- uint32_t oob_size;
-
- uint32_t blocks;
- uint32_t pages_per_block;
-};
-#define NAND_IO_GET_CHIP_PARAM _IOWR(NAND_IOCTL_GROUP, 0x8, \
- struct chip_param_io)
-
-#endif /* _DEV_NAND_CDEV_H_ */
diff --git a/sys/dev/nand/nand_ecc_pos.h b/sys/dev/nand/nand_ecc_pos.h
deleted file mode 100644
index 835f45e6c083..000000000000
--- a/sys/dev/nand/nand_ecc_pos.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _DEV_NAND_ECC_POS_H_
-#define _DEV_NAND_ECC_POS_H_
-
-static uint16_t default_software_ecc_positions_16[] = {2, 0, 1, 7, 4, 6};
-
-static uint16_t default_software_ecc_positions_64[] = {
-
- 42, 40, 41, 45, 43, 44, 48, 46,
- 47, 51, 49, 50, 54, 52, 53, 57,
- 55, 56, 60, 58, 59, 63, 61, 62
-};
-
-static uint16_t default_software_ecc_positions_128[] = {
- 8, 9, 10, 11, 12, 13,
- 18, 19, 20, 21, 22, 23,
- 28, 29, 30, 31, 32, 33,
- 38, 39, 40, 41, 42, 43,
- 48, 49, 50, 51, 52, 53,
- 58, 59, 60, 61, 62, 63,
- 68, 69, 70, 71, 72, 73,
- 78, 79, 80, 81, 82, 83,
- 88, 89, 90, 91, 92, 93,
- 98, 99, 100, 101, 102, 103,
- 108, 109, 110, 111, 112, 113,
- 118, 119, 120, 121, 122, 123,
-};
-#endif /* _DEV_NAND_ECC_POS_H_ */
-
diff --git a/sys/dev/nand/nand_generic.c b/sys/dev/nand/nand_generic.c
deleted file mode 100644
index cc6ef9bd57b0..000000000000
--- a/sys/dev/nand/nand_generic.c
+++ /dev/null
@@ -1,1366 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* Generic NAND driver */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/endian.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/time.h>
-#include <sys/malloc.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include "nfc_if.h"
-#include "nand_if.h"
-#include "nandbus_if.h"
-
-
-static int onfi_nand_probe(device_t dev);
-static int large_nand_probe(device_t dev);
-static int small_nand_probe(device_t dev);
-static int generic_nand_attach(device_t dev);
-static int generic_nand_detach(device_t dev);
-
-static int generic_erase_block(device_t, uint32_t);
-static int generic_erase_block_intlv(device_t, uint32_t);
-static int generic_read_page (device_t, uint32_t, void *, uint32_t, uint32_t);
-static int generic_read_oob(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int generic_program_page(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int generic_program_page_intlv(device_t, uint32_t, void *, uint32_t,
- uint32_t);
-static int generic_program_oob(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int generic_is_blk_bad(device_t, uint32_t, uint8_t *);
-static int generic_get_ecc(device_t, void *, void *, int *);
-static int generic_correct_ecc(device_t, void *, void *, void *);
-
-static int small_read_page(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int small_read_oob(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int small_program_page(device_t, uint32_t, void *, uint32_t, uint32_t);
-static int small_program_oob(device_t, uint32_t, void *, uint32_t, uint32_t);
-
-static int onfi_is_blk_bad(device_t, uint32_t, uint8_t *);
-static int onfi_read_parameter(struct nand_chip *, struct onfi_chip_params *);
-
-static int nand_send_address(device_t, int32_t, int32_t, int8_t);
-
-static device_method_t onand_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, onfi_nand_probe),
- DEVMETHOD(device_attach, generic_nand_attach),
- DEVMETHOD(device_detach, generic_nand_detach),
-
- DEVMETHOD(nand_read_page, generic_read_page),
- DEVMETHOD(nand_program_page, generic_program_page),
- DEVMETHOD(nand_program_page_intlv, generic_program_page_intlv),
- DEVMETHOD(nand_read_oob, generic_read_oob),
- DEVMETHOD(nand_program_oob, generic_program_oob),
- DEVMETHOD(nand_erase_block, generic_erase_block),
- DEVMETHOD(nand_erase_block_intlv, generic_erase_block_intlv),
-
- DEVMETHOD(nand_is_blk_bad, onfi_is_blk_bad),
- DEVMETHOD(nand_get_ecc, generic_get_ecc),
- DEVMETHOD(nand_correct_ecc, generic_correct_ecc),
- { 0, 0 }
-};
-
-static device_method_t lnand_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, large_nand_probe),
- DEVMETHOD(device_attach, generic_nand_attach),
- DEVMETHOD(device_detach, generic_nand_detach),
-
- DEVMETHOD(nand_read_page, generic_read_page),
- DEVMETHOD(nand_program_page, generic_program_page),
- DEVMETHOD(nand_read_oob, generic_read_oob),
- DEVMETHOD(nand_program_oob, generic_program_oob),
- DEVMETHOD(nand_erase_block, generic_erase_block),
-
- DEVMETHOD(nand_is_blk_bad, generic_is_blk_bad),
- DEVMETHOD(nand_get_ecc, generic_get_ecc),
- DEVMETHOD(nand_correct_ecc, generic_correct_ecc),
- { 0, 0 }
-};
-
-static device_method_t snand_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, small_nand_probe),
- DEVMETHOD(device_attach, generic_nand_attach),
- DEVMETHOD(device_detach, generic_nand_detach),
-
- DEVMETHOD(nand_read_page, small_read_page),
- DEVMETHOD(nand_program_page, small_program_page),
- DEVMETHOD(nand_read_oob, small_read_oob),
- DEVMETHOD(nand_program_oob, small_program_oob),
- DEVMETHOD(nand_erase_block, generic_erase_block),
-
- DEVMETHOD(nand_is_blk_bad, generic_is_blk_bad),
- DEVMETHOD(nand_get_ecc, generic_get_ecc),
- DEVMETHOD(nand_correct_ecc, generic_correct_ecc),
- { 0, 0 }
-};
-
-devclass_t onand_devclass;
-devclass_t lnand_devclass;
-devclass_t snand_devclass;
-
-driver_t onand_driver = {
- "onand",
- onand_methods,
- sizeof(struct nand_chip)
-};
-
-driver_t lnand_driver = {
- "lnand",
- lnand_methods,
- sizeof(struct nand_chip)
-};
-
-driver_t snand_driver = {
- "snand",
- snand_methods,
- sizeof(struct nand_chip)
-};
-
-DRIVER_MODULE(onand, nandbus, onand_driver, onand_devclass, 0, 0);
-DRIVER_MODULE(lnand, nandbus, lnand_driver, lnand_devclass, 0, 0);
-DRIVER_MODULE(snand, nandbus, snand_driver, snand_devclass, 0, 0);
-
-static int
-onfi_nand_probe(device_t dev)
-{
- struct nandbus_ivar *ivar;
-
- ivar = device_get_ivars(dev);
- if (ivar && ivar->is_onfi) {
- device_set_desc(dev, "ONFI compliant NAND");
- return (BUS_PROBE_DEFAULT);
- }
-
- return (ENODEV);
-}
-
-static int
-large_nand_probe(device_t dev)
-{
- struct nandbus_ivar *ivar;
-
- ivar = device_get_ivars(dev);
- if (ivar && !ivar->is_onfi && ivar->params->page_size >= 512) {
- device_set_desc(dev, ivar->params->name);
- return (BUS_PROBE_DEFAULT);
- }
-
- return (ENODEV);
-}
-
-static int
-small_nand_probe(device_t dev)
-{
- struct nandbus_ivar *ivar;
-
- ivar = device_get_ivars(dev);
- if (ivar && !ivar->is_onfi && ivar->params->page_size == 512) {
- device_set_desc(dev, ivar->params->name);
- return (BUS_PROBE_DEFAULT);
- }
-
- return (ENODEV);
-}
-
-static int
-generic_nand_attach(device_t dev)
-{
- struct nand_chip *chip;
- struct nandbus_ivar *ivar;
- struct onfi_chip_params *onfi_chip_params;
- device_t nandbus, nfc;
- int err;
-
- chip = device_get_softc(dev);
- chip->dev = dev;
-
- ivar = device_get_ivars(dev);
- chip->id.man_id = ivar->man_id;
- chip->id.dev_id = ivar->dev_id;
- chip->num = ivar->cs;
-
- /* TODO remove when HW ECC supported */
- nandbus = device_get_parent(dev);
- nfc = device_get_parent(nandbus);
-
- chip->nand = device_get_softc(nfc);
-
- if (ivar->is_onfi) {
- onfi_chip_params = malloc(sizeof(struct onfi_chip_params),
- M_NAND, M_WAITOK | M_ZERO);
-
- if (onfi_read_parameter(chip, onfi_chip_params)) {
- nand_debug(NDBG_GEN,"Could not read parameter page!\n");
- free(onfi_chip_params, M_NAND);
- return (ENXIO);
- }
-
- nand_onfi_set_params(chip, onfi_chip_params);
- /* Set proper column and row cycles */
- ivar->cols = (onfi_chip_params->address_cycles >> 4) & 0xf;
- ivar->rows = onfi_chip_params->address_cycles & 0xf;
- free(onfi_chip_params, M_NAND);
-
- } else {
- nand_set_params(chip, ivar->params);
- }
-
- err = nand_init_stat(chip);
- if (err) {
- generic_nand_detach(dev);
- return (err);
- }
-
- err = nand_init_bbt(chip);
- if (err) {
- generic_nand_detach(dev);
- return (err);
- }
-
- err = nand_make_dev(chip);
- if (err) {
- generic_nand_detach(dev);
- return (err);
- }
-
- err = create_geom_disk(chip);
- if (err) {
- generic_nand_detach(dev);
- return (err);
- }
-
- return (0);
-}
-
-static int
-generic_nand_detach(device_t dev)
-{
- struct nand_chip *chip;
-
- chip = device_get_softc(dev);
-
- nand_destroy_bbt(chip);
- destroy_geom_disk(chip);
- nand_destroy_dev(chip);
- nand_destroy_stat(chip);
-
- return (0);
-}
-
-static int
-can_write(device_t nandbus)
-{
- uint8_t status;
-
- if (NANDBUS_WAIT_READY(nandbus, &status))
- return (0);
-
- if (!(status & NAND_STATUS_WP)) {
- nand_debug(NDBG_GEN,"Chip is write-protected");
- return (0);
- }
-
- return (1);
-}
-
-static int
-check_fail(device_t nandbus)
-{
- uint8_t status;
-
- NANDBUS_WAIT_READY(nandbus, &status);
- if (status & NAND_STATUS_FAIL) {
- nand_debug(NDBG_GEN,"Status failed %x", status);
- return (ENXIO);
- }
-
- return (0);
-}
-
-static uint16_t
-onfi_crc(const void *buf, size_t buflen)
-{
- int i, j;
- uint16_t crc;
- const uint8_t *bufptr;
-
- bufptr = buf;
- crc = 0x4f4e;
- for (j = 0; j < buflen; j++) {
- crc ^= *bufptr++ << 8;
- for (i = 0; i < 8; i++)
- if (crc & 0x8000)
- crc = (crc << 1) ^ 0x8005;
- else
- crc <<= 1;
- }
- return crc;
-}
-
-static int
-onfi_read_parameter(struct nand_chip *chip, struct onfi_chip_params *chip_params)
-{
- device_t nandbus;
- struct onfi_params params;
- int found, sigcount, trycopy;
-
- nand_debug(NDBG_GEN,"read parameter");
-
- nandbus = device_get_parent(chip->dev);
-
- NANDBUS_SELECT_CS(nandbus, chip->num);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_READ_PARAMETER))
- return (ENXIO);
-
- if (nand_send_address(chip->dev, -1, -1, PAGE_PARAMETER_DEF))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- /*
- * XXX Bogus DELAY, we really need a nandbus_wait_ready() here, but it's
- * not accessible from here (static to nandbus).
- */
- DELAY(1000);
-
- /*
- * The ONFI spec mandates a minimum of three copies of the parameter
- * data, so loop up to 3 times trying to find good data. Each copy is
- * validated by a signature of "ONFI" and a crc. There is a very strange
- * rule that the signature is valid if any 2 of the 4 bytes are correct.
- */
- for (found= 0, trycopy = 0; !found && trycopy < 3; trycopy++) {
- NANDBUS_READ_BUFFER(nandbus, &params, sizeof(struct onfi_params));
- sigcount = params.signature[0] == 'O';
- sigcount += params.signature[1] == 'N';
- sigcount += params.signature[2] == 'F';
- sigcount += params.signature[3] == 'I';
- if (sigcount < 2)
- continue;
- if (onfi_crc(&params, 254) != params.crc)
- continue;
- found = 1;
- }
- if (!found)
- return (ENXIO);
-
- chip_params->luns = params.luns;
- chip_params->blocks_per_lun = le32dec(&params.blocks_per_lun);
- chip_params->pages_per_block = le32dec(&params.pages_per_block);
- chip_params->bytes_per_page = le32dec(&params.bytes_per_page);
- chip_params->spare_bytes_per_page = le16dec(&params.spare_bytes_per_page);
- chip_params->t_bers = le16dec(&params.t_bers);
- chip_params->t_prog = le16dec(&params.t_prog);
- chip_params->t_r = le16dec(&params.t_r);
- chip_params->t_ccs = le16dec(&params.t_ccs);
- chip_params->features = le16dec(&params.features);
- chip_params->address_cycles = params.address_cycles;
-
- return (0);
-}
-
-static int
-send_read_page(device_t nand, uint8_t start_command, uint8_t end_command,
- uint32_t row, uint32_t column)
-{
- device_t nandbus = device_get_parent(nand);
-
- if (NANDBUS_SEND_COMMAND(nandbus, start_command))
- return (ENXIO);
-
- if (nand_send_address(nand, row, column, -1))
- return (ENXIO);
-
- if (NANDBUS_SEND_COMMAND(nandbus, end_command))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-generic_read_page(device_t nand, uint32_t page, void *buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p raw read page %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (send_read_page(nand, NAND_CMD_READ, NAND_CMD_READ_END, row,
- offset))
- return (ENXIO);
-
- DELAY(chip->t_r);
-
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_read++;
-
- return (0);
-}
-
-static int
-generic_read_oob(device_t nand, uint32_t page, void* buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p raw read oob %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page)) {
- nand_debug(NDBG_GEN,"page boundary check failed: %08x\n", page);
- return (ENXIO);
- }
-
- page_to_row(&chip->chip_geom, page, &row);
-
- offset += chip->chip_geom.page_size;
-
- if (send_read_page(nand, NAND_CMD_READ, NAND_CMD_READ_END, row,
- offset))
- return (ENXIO);
-
- DELAY(chip->t_r);
-
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-send_start_program_page(device_t nand, uint32_t row, uint32_t column)
-{
- device_t nandbus = device_get_parent(nand);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_PROG))
- return (ENXIO);
-
- if (nand_send_address(nand, row, column, -1))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-send_end_program_page(device_t nandbus, uint8_t end_command)
-{
-
- if (NANDBUS_SEND_COMMAND(nandbus, end_command))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-generic_program_page(device_t nand, uint32_t page, void *buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p raw prog page %x[%x] at %x", nand, page, len,
- offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (send_start_program_page(nand, row, offset))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_END))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_written++;
-
- return (0);
-}
-
-static int
-generic_program_page_intlv(device_t nand, uint32_t page, void *buf,
- uint32_t len, uint32_t offset)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p raw prog page %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (send_start_program_page(nand, row, offset))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_INTLV))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_written++;
-
- return (0);
-}
-
-static int
-generic_program_oob(device_t nand, uint32_t page, void* buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p raw prog oob %x[%x] at %x", nand, page, len,
- offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
- offset += chip->chip_geom.page_size;
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (send_start_program_page(nand, row, offset))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_END))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-send_erase_block(device_t nand, uint32_t row, uint8_t second_command)
-{
- device_t nandbus = device_get_parent(nand);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_ERASE))
- return (ENXIO);
-
- if (nand_send_address(nand, row, -1, -1))
- return (ENXIO);
-
- if (NANDBUS_SEND_COMMAND(nandbus, second_command))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-generic_erase_block(device_t nand, uint32_t block)
-{
- struct block_stat *blk_stat;
- struct nand_chip *chip;
- device_t nandbus;
- int row;
-
- nand_debug(NDBG_GEN,"%p erase block %x", nand, block);
- nandbus = device_get_parent(nand);
- chip = device_get_softc(nand);
-
- if (block >= (chip->chip_geom.blks_per_lun * chip->chip_geom.luns))
- return (ENXIO);
-
- row = (block << chip->chip_geom.blk_shift) &
- chip->chip_geom.blk_mask;
-
- nand_debug(NDBG_GEN,"%p erase block row %x", nand, row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- send_erase_block(nand, row, NAND_CMD_ERASE_END);
-
- DELAY(chip->t_bers);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- blk_stat = &(chip->blk_stat[block]);
- blk_stat->block_erased++;
-
- return (0);
-}
-
-static int
-generic_erase_block_intlv(device_t nand, uint32_t block)
-{
- struct block_stat *blk_stat;
- struct nand_chip *chip;
- device_t nandbus;
- int row;
-
- nand_debug(NDBG_GEN,"%p erase block %x", nand, block);
- nandbus = device_get_parent(nand);
- chip = device_get_softc(nand);
-
- if (block >= (chip->chip_geom.blks_per_lun * chip->chip_geom.luns))
- return (ENXIO);
-
- row = (block << chip->chip_geom.blk_shift) &
- chip->chip_geom.blk_mask;
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- send_erase_block(nand, row, NAND_CMD_ERASE_INTLV);
-
- DELAY(chip->t_bers);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- blk_stat = &(chip->blk_stat[block]);
- blk_stat->block_erased++;
-
- return (0);
-
-}
-
-static int
-onfi_is_blk_bad(device_t device, uint32_t block_number, uint8_t *bad)
-{
- struct nand_chip *chip;
- int page_number, i, j, err;
- uint8_t *oob;
-
- chip = device_get_softc(device);
-
- oob = malloc(chip->chip_geom.oob_size, M_NAND, M_WAITOK);
-
- page_number = block_number * chip->chip_geom.pgs_per_blk;
- *bad = 0;
- /* Check OOB of first and last page */
- for (i = 0; i < 2; i++, page_number+= chip->chip_geom.pgs_per_blk - 1) {
- err = generic_read_oob(device, page_number, oob,
- chip->chip_geom.oob_size, 0);
- if (err) {
- device_printf(device, "%s: cannot allocate oob\n",
- __func__);
- free(oob, M_NAND);
- return (ENOMEM);
- }
-
- for (j = 0; j < chip->chip_geom.oob_size; j++) {
- if (!oob[j]) {
- *bad = 1;
- free(oob, M_NAND);
- return (0);
- }
- }
- }
-
- free(oob, M_NAND);
-
- return (0);
-}
-
-static int
-send_small_read_page(device_t nand, uint8_t start_command,
- uint32_t row, uint32_t column)
-{
- device_t nandbus = device_get_parent(nand);
-
- if (NANDBUS_SEND_COMMAND(nandbus, start_command))
- return (ENXIO);
-
- if (nand_send_address(nand, row, column, -1))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-
-static int
-small_read_page(device_t nand, uint32_t page, void *buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p small read page %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (offset < 256) {
- if (send_small_read_page(nand, NAND_CMD_SMALLA, row, offset))
- return (ENXIO);
- } else {
- offset -= 256;
- if (send_small_read_page(nandbus, NAND_CMD_SMALLB, row, offset))
- return (ENXIO);
- }
-
- DELAY(chip->t_r);
-
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_read++;
-
- return (0);
-}
-
-static int
-small_read_oob(device_t nand, uint32_t page, void *buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p small read oob %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (send_small_read_page(nand, NAND_CMD_SMALLOOB, row, 0))
- return (ENXIO);
-
- DELAY(chip->t_r);
-
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_read++;
-
- return (0);
-}
-
-static int
-small_program_page(device_t nand, uint32_t page, void* buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p small prog page %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (offset < 256) {
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_SMALLA))
- return (ENXIO);
- } else {
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_SMALLB))
- return (ENXIO);
- }
-
- if (send_start_program_page(nand, row, offset))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_END))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-static int
-small_program_oob(device_t nand, uint32_t page, void* buf, uint32_t len,
- uint32_t offset)
-{
- struct nand_chip *chip;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"%p small prog oob %x[%x] at %x", nand, page, len, offset);
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_SMALLOOB))
- return (ENXIO);
-
- if (send_start_program_page(nand, row, offset))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_END))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-int
-nand_send_address(device_t nand, int32_t row, int32_t col, int8_t id)
-{
- struct nandbus_ivar *ivar;
- device_t nandbus;
- uint8_t addr;
- int err = 0;
- int i;
-
- nandbus = device_get_parent(nand);
- ivar = device_get_ivars(nand);
-
- if (id != -1) {
- nand_debug(NDBG_GEN,"send_address: send id %02x", id);
- err = NANDBUS_SEND_ADDRESS(nandbus, id);
- }
-
- if (!err && col != -1) {
- for (i = 0; i < ivar->cols; i++, col >>= 8) {
- addr = (uint8_t)(col & 0xff);
- nand_debug(NDBG_GEN,"send_address: send address column "
- "%02x", addr);
- err = NANDBUS_SEND_ADDRESS(nandbus, addr);
- if (err)
- break;
- }
- }
-
- if (!err && row != -1) {
- for (i = 0; i < ivar->rows; i++, row >>= 8) {
- addr = (uint8_t)(row & 0xff);
- nand_debug(NDBG_GEN,"send_address: send address row "
- "%02x", addr);
- err = NANDBUS_SEND_ADDRESS(nandbus, addr);
- if (err)
- break;
- }
- }
-
- return (err);
-}
-
-static int
-generic_is_blk_bad(device_t dev, uint32_t block, uint8_t *bad)
-{
- struct nand_chip *chip;
- int page_number, err, i;
- uint8_t *oob;
-
- chip = device_get_softc(dev);
-
- oob = malloc(chip->chip_geom.oob_size, M_NAND, M_WAITOK);
-
- page_number = block * chip->chip_geom.pgs_per_blk;
- *bad = 0;
-
- /* Check OOB of first and second page */
- for (i = 0; i < 2; i++) {
- err = NAND_READ_OOB(dev, page_number + i, oob,
- chip->chip_geom.oob_size, 0);
- if (err) {
- device_printf(dev, "%s: cannot allocate OOB\n",
- __func__);
- free(oob, M_NAND);
- return (ENOMEM);
- }
-
- if (!oob[0]) {
- *bad = 1;
- free(oob, M_NAND);
- return (0);
- }
- }
-
- free(oob, M_NAND);
-
- return (0);
-}
-
-static int
-generic_get_ecc(device_t dev, void *buf, void *ecc, int *needwrite)
-{
- struct nand_chip *chip = device_get_softc(dev);
- struct chip_geom *cg = &chip->chip_geom;
-
- return (NANDBUS_GET_ECC(device_get_parent(dev), buf, cg->page_size,
- ecc, needwrite));
-}
-
-static int
-generic_correct_ecc(device_t dev, void *buf, void *readecc, void *calcecc)
-{
- struct nand_chip *chip = device_get_softc(dev);
- struct chip_geom *cg = &chip->chip_geom;
-
- return (NANDBUS_CORRECT_ECC(device_get_parent(dev), buf,
- cg->page_size, readecc, calcecc));
-}
-
-
-#if 0
-int
-nand_chng_read_col(device_t nand, uint32_t col, void *buf, size_t len)
-{
- struct nand_chip *chip;
- device_t nandbus;
-
- chip = device_get_softc(nand);
- nandbus = device_get_parent(nand);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_CHNG_READ_COL))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, -1, col, -1))
- return (ENXIO);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_CHNG_READ_COL_END))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- if (buf != NULL && len > 0)
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- return (0);
-}
-
-int
-nand_chng_write_col(device_t dev, uint32_t col, void *buf,
- size_t len)
-{
- struct nand_chip *chip;
- device_t nandbus;
-
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_CHNG_WRITE_COL))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, -1, col, -1))
- return (ENXIO);
-
- if (buf != NULL && len > 0)
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_CHNG_READ_COL_END))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-
-int
-nand_copyback_read(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN," raw read page %x[%x] at %x", page, col, len);
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (send_read_page(nand, NAND_CMD_READ, NAND_CMD_READ_CPBK, row, 0))
- return (ENXIO);
-
- DELAY(chip->t_r);
- if (check_fail(nandbus))
- return (ENXIO);
-
- if (buf != NULL && len > 0)
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_read++;
-
- return (0);
-}
-
-int
-nand_copyback_prog(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"copyback prog page %x[%x]", page, len);
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_CHNG_WRITE_COL))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, row, col, -1))
- return (ENXIO);
-
- if (buf != NULL && len > 0)
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_END))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_written++;
-
- return (0);
-}
-
-int
-nand_copyback_prog_intlv(device_t dev, uint32_t page)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
-
- nand_debug(NDBG_GEN,"cache prog page %x", page);
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (send_start_program_page(nand, row, 0))
- return (ENXIO);
-
- if (send_end_program_page(nandbus, NAND_CMD_PROG_INTLV))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_written++;
-
- return (0);
-}
-
-int
-nand_prog_cache(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len, uint8_t end)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
- uint8_t command;
-
- nand_debug(NDBG_GEN,"cache prog page %x[%x]", page, len);
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (!can_write(nandbus))
- return (ENXIO);
-
- if (send_start_program_page(dev, row, 0))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, len);
-
- if (end)
- command = NAND_CMD_PROG_END;
- else
- command = NAND_CMD_PROG_CACHE;
-
- if (send_end_program_page(nandbus, command))
- return (ENXIO);
-
- DELAY(chip->t_prog);
-
- if (check_fail(nandbus))
- return (ENXIO);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_written++;
-
- return (0);
-}
-
-int
-nand_read_cache(device_t dev, uint32_t page, uint32_t col,
- void *buf, size_t len, uint8_t end)
-{
- struct nand_chip *chip;
- struct page_stat *pg_stat;
- device_t nandbus;
- uint32_t row;
- uint8_t command;
-
- nand_debug(NDBG_GEN,"cache read page %x[%x] ", page, len);
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (nand_check_page_boundary(chip, page))
- return (ENXIO);
-
- page_to_row(&chip->chip_geom, page, &row);
-
- if (page != -1) {
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_READ))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, row, col, -1))
- return (ENXIO);
- }
-
- if (end)
- command = NAND_CMD_READ_CACHE_END;
- else
- command = NAND_CMD_READ_CACHE;
-
- if (NANDBUS_SEND_COMMAND(nandbus, command))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- DELAY(chip->t_r);
- if (check_fail(nandbus))
- return (ENXIO);
-
- if (buf != NULL && len > 0)
- NANDBUS_READ_BUFFER(nandbus, buf, len);
-
- pg_stat = &(chip->pg_stat[page]);
- pg_stat->page_raw_read++;
-
- return (0);
-}
-
-int
-nand_get_feature(device_t dev, uint8_t feat, void *buf)
-{
- struct nand_chip *chip;
- device_t nandbus;
-
- nand_debug(NDBG_GEN,"nand get feature");
-
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_GET_FEATURE))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, -1, -1, feat))
- return (ENXIO);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- DELAY(chip->t_r);
- NANDBUS_READ_BUFFER(nandbus, buf, 4);
-
- return (0);
-}
-
-int
-nand_set_feature(device_t dev, uint8_t feat, void *buf)
-{
- struct nand_chip *chip;
- device_t nandbus;
-
- nand_debug(NDBG_GEN,"nand set feature");
-
- chip = device_get_softc(dev);
- nandbus = device_get_parent(dev);
-
- if (NANDBUS_SEND_COMMAND(nandbus, NAND_CMD_SET_FEATURE))
- return (ENXIO);
-
- if (NANDBUS_SEND_ADDRESS(nandbus, -1, -1, feat))
- return (ENXIO);
-
- NANDBUS_WRITE_BUFFER(nandbus, buf, 4);
-
- if (NANDBUS_START_COMMAND(nandbus))
- return (ENXIO);
-
- return (0);
-}
-#endif
diff --git a/sys/dev/nand/nand_geom.c b/sys/dev/nand/nand_geom.c
deleted file mode 100644
index b814ffc4e0a9..000000000000
--- a/sys/dev/nand/nand_geom.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/bus.h>
-#include <sys/malloc.h>
-#include <sys/uio.h>
-#include <sys/bio.h>
-#include <geom/geom.h>
-#include <geom/geom_disk.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include <dev/nand/nand_dev.h>
-#include "nand_if.h"
-#include "nandbus_if.h"
-
-#define BIO_NAND_STD ((void *)1)
-#define BIO_NAND_RAW ((void *)2)
-
-static disk_ioctl_t nand_ioctl;
-static disk_getattr_t nand_getattr;
-static disk_strategy_t nand_strategy;
-static disk_strategy_t nand_strategy_raw;
-
-static int
-nand_read(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
-{
-
- nand_debug(NDBG_GEOM, "Read from chip %d [%p] at %d", chip->num, chip,
- offset);
-
- return (nand_read_pages(chip, offset, buf, len));
-}
-
-static int
-nand_write(struct nand_chip *chip, uint32_t offset, void* buf, uint32_t len)
-{
-
- nand_debug(NDBG_GEOM, "Write to chip %d [%p] at %d", chip->num, chip,
- offset);
-
- return (nand_prog_pages(chip, offset, buf, len));
-}
-
-static int
-nand_read_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
-{
- nand_debug(NDBG_GEOM, "Raw read from chip %d [%p] at %d", chip->num,
- chip, offset);
-
- return (nand_read_pages_raw(chip, offset, buf, len));
-}
-
-static int
-nand_write_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
-{
-
- nand_debug(NDBG_GEOM, "Raw write to chip %d [%p] at %d", chip->num,
- chip, offset);
-
- return (nand_prog_pages_raw(chip, offset, buf, len));
-}
-
-static void
-nand_strategy(struct bio *bp)
-{
- struct nand_chip *chip;
-
- chip = (struct nand_chip *)bp->bio_disk->d_drv1;
-
- bp->bio_driver1 = BIO_NAND_STD;
-
- nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]",
- bp->bio_cmd == BIO_READ ? "READ" :
- (bp->bio_cmd == BIO_WRITE ? "WRITE" :
- (bp->bio_cmd == BIO_DELETE ? "DELETE" : "UNKNOWN")),
- chip->num, chip);
-
- mtx_lock(&chip->qlock);
- bioq_insert_tail(&chip->bioq, bp);
- mtx_unlock(&chip->qlock);
- taskqueue_enqueue(chip->tq, &chip->iotask);
-}
-
-static void
-nand_strategy_raw(struct bio *bp)
-{
- struct nand_chip *chip;
-
- chip = (struct nand_chip *)bp->bio_disk->d_drv1;
-
- /* Inform taskqueue that it's a raw access */
- bp->bio_driver1 = BIO_NAND_RAW;
-
- nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]",
- bp->bio_cmd == BIO_READ ? "READ" :
- (bp->bio_cmd == BIO_WRITE ? "WRITE" :
- (bp->bio_cmd == BIO_DELETE ? "DELETE" : "UNKNOWN")),
- chip->num, chip);
-
- mtx_lock(&chip->qlock);
- bioq_insert_tail(&chip->bioq, bp);
- mtx_unlock(&chip->qlock);
- taskqueue_enqueue(chip->tq, &chip->iotask);
-}
-
-static int
-nand_oob_access(struct nand_chip *chip, uint32_t page, uint32_t offset,
- uint32_t len, uint8_t *data, uint8_t write)
-{
- struct chip_geom *cg;
- int ret = 0;
-
- cg = &chip->chip_geom;
-
- if (!write)
- ret = nand_read_oob(chip, page, data, cg->oob_size);
- else
- ret = nand_prog_oob(chip, page, data, cg->oob_size);
-
- return (ret);
-}
-
-static int
-nand_getattr(struct bio *bp)
-{
- struct nand_chip *chip;
- struct chip_geom *cg;
- device_t dev;
- int val;
-
- if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL)
- return (ENXIO);
-
- chip = (struct nand_chip *)bp->bio_disk->d_drv1;
- cg = &(chip->chip_geom);
-
- dev = device_get_parent(chip->dev);
- dev = device_get_parent(dev);
-
- if (strcmp(bp->bio_attribute, "NAND::device") == 0) {
- if (bp->bio_length != sizeof(dev))
- return (EFAULT);
- bcopy(&dev, bp->bio_data, sizeof(dev));
- } else {
- if (strcmp(bp->bio_attribute, "NAND::oobsize") == 0)
- val = cg->oob_size;
- else if (strcmp(bp->bio_attribute, "NAND::pagesize") == 0)
- val = cg->page_size;
- else if (strcmp(bp->bio_attribute, "NAND::blocksize") == 0)
- val = cg->block_size;
- else
- return (-1);
- if (bp->bio_length != sizeof(val))
- return (EFAULT);
- bcopy(&val, bp->bio_data, sizeof(val));
- }
- bp->bio_completed = bp->bio_length;
- return (0);
-}
-
-static int
-nand_ioctl(struct disk *ndisk, u_long cmd, void *data, int fflag,
- struct thread *td)
-{
- struct nand_chip *chip;
- struct chip_geom *cg;
- struct nand_oob_rw *oob_rw = NULL;
- struct nand_raw_rw *raw_rw = NULL;
- device_t nandbus;
- size_t bufsize = 0, len = 0;
- size_t raw_size;
- off_t off;
- uint8_t *buf = NULL;
- int ret = 0;
- uint8_t status;
-
- chip = (struct nand_chip *)ndisk->d_drv1;
- cg = &chip->chip_geom;
- nandbus = device_get_parent(chip->dev);
-
- if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) {
- raw_rw = (struct nand_raw_rw *)data;
- raw_size = cg->pgs_per_blk * (cg->page_size + cg->oob_size);
-
- /* Check if len is not bigger than chip size */
- if (raw_rw->len > raw_size)
- return (EFBIG);
-
- /*
- * Do not ask for too much memory, in case of large transfers
- * read/write in 16-pages chunks
- */
- bufsize = 16 * (cg->page_size + cg->oob_size);
- if (raw_rw->len < bufsize)
- bufsize = raw_rw->len;
-
- buf = malloc(bufsize, M_NAND, M_WAITOK);
- len = raw_rw->len;
- off = 0;
- }
-
- switch (cmd) {
- case NAND_IO_ERASE:
- ret = nand_erase_blocks(chip, ((off_t *)data)[0],
- ((off_t *)data)[1]);
- break;
-
- case NAND_IO_OOB_READ:
- oob_rw = (struct nand_oob_rw *)data;
- ret = nand_oob_access(chip, oob_rw->page, 0,
- oob_rw->len, oob_rw->data, 0);
- break;
-
- case NAND_IO_OOB_PROG:
- oob_rw = (struct nand_oob_rw *)data;
- ret = nand_oob_access(chip, oob_rw->page, 0,
- oob_rw->len, oob_rw->data, 1);
- break;
-
- case NAND_IO_GET_STATUS:
- NANDBUS_LOCK(nandbus);
- ret = NANDBUS_GET_STATUS(nandbus, &status);
- if (ret == 0)
- *(uint8_t *)data = status;
- NANDBUS_UNLOCK(nandbus);
- break;
-
- case NAND_IO_RAW_PROG:
- while (len > 0) {
- if (len < bufsize)
- bufsize = len;
-
- ret = copyin(raw_rw->data + off, buf, bufsize);
- if (ret)
- break;
- ret = nand_prog_pages_raw(chip, raw_rw->off + off, buf,
- bufsize);
- if (ret)
- break;
- len -= bufsize;
- off += bufsize;
- }
- break;
-
- case NAND_IO_RAW_READ:
- while (len > 0) {
- if (len < bufsize)
- bufsize = len;
-
- ret = nand_read_pages_raw(chip, raw_rw->off + off, buf,
- bufsize);
- if (ret)
- break;
-
- ret = copyout(buf, raw_rw->data + off, bufsize);
- if (ret)
- break;
- len -= bufsize;
- off += bufsize;
- }
- break;
-
- case NAND_IO_GET_CHIP_PARAM:
- nand_get_chip_param(chip, (struct chip_param_io *)data);
- break;
-
- default:
- printf("Unknown nand_ioctl request \n");
- ret = EIO;
- }
-
- if (buf)
- free(buf, M_NAND);
-
- return (ret);
-}
-
-static void
-nand_io_proc(void *arg, int pending)
-{
- struct nand_chip *chip = arg;
- struct bio *bp;
- int err = 0;
-
- for (;;) {
- mtx_lock(&chip->qlock);
- bp = bioq_takefirst(&chip->bioq);
- mtx_unlock(&chip->qlock);
- if (bp == NULL)
- break;
-
- if (bp->bio_driver1 == BIO_NAND_STD) {
- if (bp->bio_cmd == BIO_READ) {
- err = nand_read(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- } else if (bp->bio_cmd == BIO_WRITE) {
- err = nand_write(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- }
- } else if (bp->bio_driver1 == BIO_NAND_RAW) {
- if (bp->bio_cmd == BIO_READ) {
- err = nand_read_raw(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- } else if (bp->bio_cmd == BIO_WRITE) {
- err = nand_write_raw(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_data, bp->bio_bcount);
- }
- } else
- panic("Unknown access type in bio->bio_driver1\n");
-
- if (bp->bio_cmd == BIO_DELETE) {
- nand_debug(NDBG_GEOM, "Delete on chip%d offset %lld "
- "length %ld\n", chip->num, bp->bio_offset,
- bp->bio_bcount);
- err = nand_erase_blocks(chip,
- bp->bio_offset & 0xffffffff,
- bp->bio_bcount);
- }
-
- if (err == 0 || err == ECC_CORRECTABLE)
- bp->bio_resid = 0;
- else {
- nand_debug(NDBG_GEOM,"nand_[read|write|erase_blocks] "
- "error: %d\n", err);
-
- bp->bio_error = EIO;
- bp->bio_flags |= BIO_ERROR;
- bp->bio_resid = bp->bio_bcount;
- }
- biodone(bp);
- }
-}
-
-int
-create_geom_disk(struct nand_chip *chip)
-{
- struct disk *ndisk, *rdisk;
-
- /* Create the disk device */
- ndisk = disk_alloc();
- ndisk->d_strategy = nand_strategy;
- ndisk->d_ioctl = nand_ioctl;
- ndisk->d_getattr = nand_getattr;
- ndisk->d_name = "gnand";
- ndisk->d_drv1 = chip;
- ndisk->d_maxsize = chip->chip_geom.block_size;
- ndisk->d_sectorsize = chip->chip_geom.page_size;
- ndisk->d_mediasize = chip->chip_geom.chip_size;
- ndisk->d_unit = chip->num +
- 10 * device_get_unit(device_get_parent(chip->dev));
-
- /*
- * When using BBT, make two last blocks of device unavailable
- * to user (because those are used to store BBT table).
- */
- if (chip->bbt != NULL)
- ndisk->d_mediasize -= (2 * chip->chip_geom.block_size);
-
- ndisk->d_flags = DISKFLAG_CANDELETE;
-
- snprintf(ndisk->d_ident, sizeof(ndisk->d_ident),
- "nand: Man:0x%02x Dev:0x%02x", chip->id.man_id, chip->id.dev_id);
- ndisk->d_rotation_rate = DISK_RR_NON_ROTATING;
-
- disk_create(ndisk, DISK_VERSION);
-
- /* Create the RAW disk device */
- rdisk = disk_alloc();
- rdisk->d_strategy = nand_strategy_raw;
- rdisk->d_ioctl = nand_ioctl;
- rdisk->d_getattr = nand_getattr;
- rdisk->d_name = "gnand.raw";
- rdisk->d_drv1 = chip;
- rdisk->d_maxsize = chip->chip_geom.block_size;
- rdisk->d_sectorsize = chip->chip_geom.page_size;
- rdisk->d_mediasize = chip->chip_geom.chip_size;
- rdisk->d_unit = chip->num +
- 10 * device_get_unit(device_get_parent(chip->dev));
-
- rdisk->d_flags = DISKFLAG_CANDELETE;
-
- snprintf(rdisk->d_ident, sizeof(rdisk->d_ident),
- "nand_raw: Man:0x%02x Dev:0x%02x", chip->id.man_id,
- chip->id.dev_id);
- rdisk->d_rotation_rate = DISK_RR_NON_ROTATING;
-
- disk_create(rdisk, DISK_VERSION);
-
- chip->ndisk = ndisk;
- chip->rdisk = rdisk;
-
- mtx_init(&chip->qlock, "NAND I/O lock", NULL, MTX_DEF);
- bioq_init(&chip->bioq);
-
- TASK_INIT(&chip->iotask, 0, nand_io_proc, chip);
- chip->tq = taskqueue_create("nand_taskq", M_WAITOK,
- taskqueue_thread_enqueue, &chip->tq);
- taskqueue_start_threads(&chip->tq, 1, PI_DISK, "nand taskq");
-
- if (bootverbose)
- device_printf(chip->dev, "Created gnand%d for chip [0x%0x, "
- "0x%0x]\n", ndisk->d_unit, chip->id.man_id,
- chip->id.dev_id);
-
- return (0);
-}
-
-void
-destroy_geom_disk(struct nand_chip *chip)
-{
- struct bio *bp;
-
- taskqueue_free(chip->tq);
- disk_destroy(chip->ndisk);
- disk_destroy(chip->rdisk);
-
- mtx_lock(&chip->qlock);
- for (;;) {
- bp = bioq_takefirst(&chip->bioq);
- if (bp == NULL)
- break;
- bp->bio_error = EIO;
- bp->bio_flags |= BIO_ERROR;
- bp->bio_resid = bp->bio_bcount;
-
- biodone(bp);
- }
- mtx_unlock(&chip->qlock);
-
- mtx_destroy(&chip->qlock);
-}
diff --git a/sys/dev/nand/nand_id.c b/sys/dev/nand/nand_id.c
deleted file mode 100644
index 7259c951bfc9..000000000000
--- a/sys/dev/nand/nand_id.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-
-#include <dev/nand/nand.h>
-
-struct nand_params nand_ids[] = {
- { { NAND_MAN_SAMSUNG, 0x75 }, "Samsung K9F5608U0B NAND 32MiB 8-bit",
- 0x20, 0x200, 0x10, 0x20, 0 },
- { { NAND_MAN_SAMSUNG, 0xf1 }, "Samsung K9F1G08U0A NAND 128MiB 3,3V 8-bit",
- 0x80, 0x800, 0x40, 0x40, 0 },
- { { NAND_MAN_SAMSUNG, 0xda }, "Samsung K9F2G08U0A NAND 256MiB 3,3V 8-bit",
- 0x100, 0x800, 0x40, 0x40, 0 },
- { { NAND_MAN_SAMSUNG, 0xdc }, "Samsung NAND 512MiB 3,3V 8-bit",
- 0x200, 0x800, 0x40, 0x40, 0 },
- { { NAND_MAN_SAMSUNG, 0xd3 }, "Samsung NAND 1GiB 3,3V 8-bit",
- 0x400, 0x800, 0x40, 0x40, 0 },
- { { NAND_MAN_HYNIX, 0x76 }, "Hynix NAND 64MiB 3,3V 8-bit",
- 0x40, 0x200, 0x10, 0x20, 0 },
- { { NAND_MAN_HYNIX, 0xdc }, "Hynix NAND 512MiB 3,3V 8-bit",
- 0x200, 0x800, 0x40, 0x40, 0 },
- { { NAND_MAN_HYNIX, 0x79 }, "Hynix NAND 128MB 3,3V 8-bit",
- 0x80, 0x200, 0x10, 0x20, 0 },
- { { NAND_MAN_STMICRO, 0xf1 }, "STMicro 128MB 3,3V 8-bit",
- 0x80, 2048, 64, 0x40, 0 },
- { { NAND_MAN_MICRON, 0xcc }, "Micron NAND 512MiB 3,3V 16-bit",
- 0x200, 2048, 64, 0x40, 0 },
-};
-
-struct nand_params *nand_get_params(struct nand_id *id)
-{
- int i;
-
- for (i = 0; i < nitems(nand_ids); i++)
- if (nand_ids[i].id.man_id == id->man_id &&
- nand_ids[i].id.dev_id == id->dev_id)
- return (&nand_ids[i]);
-
- return (NULL);
-}
diff --git a/sys/dev/nand/nand_if.m b/sys/dev/nand/nand_if.m
deleted file mode 100644
index 49c8879b6890..000000000000
--- a/sys/dev/nand/nand_if.m
+++ /dev/null
@@ -1,168 +0,0 @@
-#-
-# Copyright (C) 2009-2012 Semihalf
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-
-# NAND chip interface description
-#
-
-#include <sys/bus.h>
-#include <dev/nand/nand.h>
-
-INTERFACE nand;
-
-CODE {
- static int nand_method_not_supported(device_t dev)
- {
- return (ENOENT);
- }
-};
-
-# Read NAND page
-#
-# Return values:
-# 0: Success
-#
-METHOD int read_page {
- device_t dev;
- uint32_t page;
- void* buf;
- uint32_t len;
- uint32_t offset;
-};
-
-# Program NAND page
-#
-# Return values:
-# 0: Success
-#
-METHOD int program_page {
- device_t dev;
- uint32_t page;
- void* buf;
- uint32_t len;
- uint32_t offset;
-};
-
-# Program NAND page interleaved
-#
-# Return values:
-# 0: Success
-#
-METHOD int program_page_intlv {
- device_t dev;
- uint32_t page;
- void* buf;
- uint32_t len;
- uint32_t offset;
-} DEFAULT nand_method_not_supported;
-
-# Read NAND oob
-#
-# Return values:
-# 0: Success
-#
-METHOD int read_oob {
- device_t dev;
- uint32_t page;
- void* buf;
- uint32_t len;
- uint32_t offset;
-};
-
-# Program NAND oob
-#
-# Return values:
-# 0: Success
-#
-METHOD int program_oob {
- device_t dev;
- uint32_t page;
- void* buf;
- uint32_t len;
- uint32_t offset;
-};
-
-# Erase NAND block
-#
-# Return values:
-# 0: Success
-#
-METHOD int erase_block {
- device_t dev;
- uint32_t block;
-};
-
-# Erase NAND block interleaved
-#
-# Return values:
-# 0: Success
-#
-METHOD int erase_block_intlv {
- device_t dev;
- uint32_t block;
-} DEFAULT nand_method_not_supported;
-
-# NAND get status
-#
-# Return values:
-# 0: Success
-#
-METHOD int get_status {
- device_t dev;
- uint8_t *status;
-};
-
-# NAND check if block is bad
-#
-# Return values:
-# 0: Success
-#
-METHOD int is_blk_bad {
- device_t dev;
- uint32_t block_number;
- uint8_t *bad;
-};
-
-# NAND get ECC
-#
-#
-METHOD int get_ecc {
- device_t dev;
- void *buf;
- void *ecc;
- int *needwrite;
-};
-
-# NAND correct ECC
-#
-#
-METHOD int correct_ecc {
- device_t dev;
- void *buf;
- void *readecc;
- void *calcecc;
-};
-
diff --git a/sys/dev/nand/nandbus.c b/sys/dev/nand/nandbus.c
deleted file mode 100644
index 003c1797af64..000000000000
--- a/sys/dev/nand/nandbus.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/proc.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/condvar.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include "nand_if.h"
-#include "nandbus_if.h"
-#include "nfc_if.h"
-
-#define NAND_NCS 4
-
-static int nandbus_probe(device_t dev);
-static int nandbus_attach(device_t dev);
-static int nandbus_detach(device_t dev);
-
-static int nandbus_child_location_str(device_t, device_t, char *, size_t);
-static int nandbus_child_pnpinfo_str(device_t, device_t, char *, size_t);
-
-static int nandbus_get_status(device_t, uint8_t *);
-static void nandbus_read_buffer(device_t, void *, uint32_t);
-static int nandbus_select_cs(device_t, uint8_t);
-static int nandbus_send_command(device_t, uint8_t);
-static int nandbus_send_address(device_t, uint8_t);
-static int nandbus_start_command(device_t);
-static int nandbus_wait_ready(device_t, uint8_t *);
-static void nandbus_write_buffer(device_t, void *, uint32_t);
-static int nandbus_get_ecc(device_t, void *, uint32_t, void *, int *);
-static int nandbus_correct_ecc(device_t, void *, int, void *, void *);
-static void nandbus_lock(device_t);
-static void nandbus_unlock(device_t);
-
-static int nand_readid(device_t, uint8_t *, uint8_t *);
-static int nand_probe_onfi(device_t, uint8_t *);
-static int nand_reset(device_t);
-
-struct nandbus_softc {
- device_t dev;
- struct cv nandbus_cv;
- struct mtx nandbus_mtx;
- uint8_t busy;
-};
-
-static device_method_t nandbus_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, nandbus_probe),
- DEVMETHOD(device_attach, nandbus_attach),
- DEVMETHOD(device_detach, nandbus_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
-
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
- DEVMETHOD(bus_child_pnpinfo_str, nandbus_child_pnpinfo_str),
- DEVMETHOD(bus_child_location_str, nandbus_child_location_str),
-
- /* nandbus interface */
- DEVMETHOD(nandbus_get_status, nandbus_get_status),
- DEVMETHOD(nandbus_read_buffer, nandbus_read_buffer),
- DEVMETHOD(nandbus_select_cs, nandbus_select_cs),
- DEVMETHOD(nandbus_send_command, nandbus_send_command),
- DEVMETHOD(nandbus_send_address, nandbus_send_address),
- DEVMETHOD(nandbus_start_command,nandbus_start_command),
- DEVMETHOD(nandbus_wait_ready, nandbus_wait_ready),
- DEVMETHOD(nandbus_write_buffer, nandbus_write_buffer),
- DEVMETHOD(nandbus_get_ecc, nandbus_get_ecc),
- DEVMETHOD(nandbus_correct_ecc, nandbus_correct_ecc),
- DEVMETHOD(nandbus_lock, nandbus_lock),
- DEVMETHOD(nandbus_unlock, nandbus_unlock),
- { 0, 0 }
-};
-
-devclass_t nandbus_devclass;
-
-driver_t nandbus_driver = {
- "nandbus",
- nandbus_methods,
- sizeof(struct nandbus_softc)
-};
-
-DRIVER_MODULE(nandbus, nand, nandbus_driver, nandbus_devclass, 0, 0);
-
-int
-nandbus_create(device_t nfc)
-{
- device_t child;
-
- child = device_add_child(nfc, "nandbus", -1);
- if (!child)
- return (ENODEV);
-
- bus_generic_attach(nfc);
-
- return(0);
-}
-
-void
-nandbus_destroy(device_t nfc)
-{
- device_t *children;
- int nchildren, i;
-
- mtx_lock(&Giant);
- /* Detach & delete all children */
- if (!device_get_children(nfc, &children, &nchildren)) {
- for (i = 0; i < nchildren; i++)
- device_delete_child(nfc, children[i]);
-
- free(children, M_TEMP);
- }
- mtx_unlock(&Giant);
-}
-
-static int
-nandbus_probe(device_t dev)
-{
-
- device_set_desc(dev, "NAND bus");
-
- return (0);
-}
-
-static int
-nandbus_attach(device_t dev)
-{
- device_t child, nfc;
- struct nand_id chip_id;
- struct nandbus_softc *sc;
- struct nandbus_ivar *ivar;
- struct nand_softc *nfc_sc;
- struct nand_params *chip_params;
- uint8_t cs, onfi;
-
- sc = device_get_softc(dev);
- sc->dev = dev;
-
- nfc = device_get_parent(dev);
- nfc_sc = device_get_softc(nfc);
-
- mtx_init(&sc->nandbus_mtx, "nandbus lock", NULL, MTX_DEF);
- cv_init(&sc->nandbus_cv, "nandbus cv");
-
- /* Check each possible CS for existing nand devices */
- for (cs = 0; cs < NAND_NCS; cs++) {
- nand_debug(NDBG_BUS,"probe chip select %x", cs);
-
- /* Select & reset chip */
- if (nandbus_select_cs(dev, cs))
- break;
-
- if (nand_reset(dev))
- continue;
-
- /* Read manufacturer and device id */
- if (nand_readid(dev, &chip_id.man_id, &chip_id.dev_id))
- continue;
-
- if (chip_id.man_id == 0xff)
- continue;
-
- /*
- * First try to get info from the table. If that fails, see if
- * the chip can provide ONFI info. We check the table first to
- * allow table entries to override info from chips that are
- * known to provide bad ONFI data.
- */
- onfi = 0;
- chip_params = nand_get_params(&chip_id);
- if (chip_params == NULL) {
- nand_probe_onfi(dev, &onfi);
- }
-
- /*
- * At this point it appears there is a chip at this chipselect,
- * so if we can't work with it, whine about it.
- */
- if (chip_params == NULL && onfi == 0) {
- if (bootverbose || (nand_debug_flag & NDBG_BUS))
- printf("Chip params not found, chipsel: %d "
- "(manuf: 0x%0x, chipid: 0x%0x, onfi: %d)\n",
- cs, chip_id.man_id, chip_id.dev_id, onfi);
- continue;
- }
-
- ivar = malloc(sizeof(struct nandbus_ivar),
- M_NAND, M_WAITOK);
-
- if (onfi == 1) {
- ivar->cs = cs;
- ivar->cols = 0;
- ivar->rows = 0;
- ivar->params = NULL;
- ivar->man_id = chip_id.man_id;
- ivar->dev_id = chip_id.dev_id;
- ivar->is_onfi = onfi;
- ivar->chip_cdev_name = nfc_sc->chip_cdev_name;
-
- child = device_add_child(dev, NULL, -1);
- device_set_ivars(child, ivar);
- continue;
- }
-
- ivar->cs = cs;
- ivar->cols = 1;
- ivar->rows = 2;
- ivar->params = chip_params;
- ivar->man_id = chip_id.man_id;
- ivar->dev_id = chip_id.dev_id;
- ivar->is_onfi = onfi;
- ivar->chip_cdev_name = nfc_sc->chip_cdev_name;
-
- /*
- * Check what type of device we have.
- * devices bigger than 32MiB have on more row (3)
- */
- if (chip_params->chip_size > 32)
- ivar->rows++;
- /* Large page devices have one more col (2) */
- if (chip_params->chip_size >= 128 &&
- chip_params->page_size > 512)
- ivar->cols++;
-
- child = device_add_child(dev, NULL, -1);
- device_set_ivars(child, ivar);
- }
-
- bus_generic_attach(dev);
- return (0);
-}
-
-static int
-nandbus_detach(device_t dev)
-{
- struct nandbus_softc *sc;
-
- sc = device_get_softc(dev);
-
- bus_generic_detach(dev);
-
- mtx_destroy(&sc->nandbus_mtx);
- cv_destroy(&sc->nandbus_cv);
-
- return (0);
-}
-
-static int
-nandbus_child_location_str(device_t bus, device_t child, char *buf,
- size_t buflen)
-{
- struct nandbus_ivar *ivar = device_get_ivars(child);
-
- snprintf(buf, buflen, "at cs#%d", ivar->cs);
- return (0);
-}
-
-static int
-nandbus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
- size_t buflen)
-{
- // XXX man id, model id ????
- *buf = '\0';
- return (0);
-}
-
-static int
-nand_readid(device_t bus, uint8_t *man_id, uint8_t *dev_id)
-{
- device_t nfc;
-
- if (!bus || !man_id || !dev_id)
- return (EINVAL);
-
- nand_debug(NDBG_BUS,"read id");
-
- nfc = device_get_parent(bus);
-
- if (NFC_SEND_COMMAND(nfc, NAND_CMD_READ_ID)) {
- nand_debug(NDBG_BUS,"Error : could not send READ ID command");
- return (ENXIO);
- }
-
- if (NFC_SEND_ADDRESS(nfc, 0)) {
- nand_debug(NDBG_BUS,"Error : could not sent address to chip");
- return (ENXIO);
- }
-
- if (NFC_START_COMMAND(nfc) != 0) {
- nand_debug(NDBG_BUS,"Error : could not start command");
- return (ENXIO);
- }
-
- DELAY(25);
-
- *man_id = NFC_READ_BYTE(nfc);
- *dev_id = NFC_READ_BYTE(nfc);
-
- nand_debug(NDBG_BUS,"manufacturer id: %x chip id: %x", *man_id,
- *dev_id);
-
- return (0);
-}
-
-static int
-nand_probe_onfi(device_t bus, uint8_t *onfi_compliant)
-{
- device_t nfc;
- char onfi_id[] = {'O', 'N', 'F', 'I', '\0'};
- int i;
-
- nand_debug(NDBG_BUS,"probing ONFI");
-
- nfc = device_get_parent(bus);
-
- if (NFC_SEND_COMMAND(nfc, NAND_CMD_READ_ID)) {
- nand_debug(NDBG_BUS,"Error : could not sent READ ID command");
- return (ENXIO);
- }
-
- if (NFC_SEND_ADDRESS(nfc, ONFI_SIG_ADDR)) {
- nand_debug(NDBG_BUS,"Error : could not sent address to chip");
- return (ENXIO);
- }
-
- if (NFC_START_COMMAND(nfc) != 0) {
- nand_debug(NDBG_BUS,"Error : could not start command");
- return (ENXIO);
- }
- for (i = 0; onfi_id[i] != '\0'; i++)
- if (NFC_READ_BYTE(nfc) != onfi_id[i]) {
- nand_debug(NDBG_BUS,"ONFI non-compliant");
- *onfi_compliant = 0;
- return (0);
- }
-
- nand_debug(NDBG_BUS,"ONFI compliant");
- *onfi_compliant = 1;
-
- return (0);
-}
-
-static int
-nand_reset(device_t bus)
-{
- device_t nfc;
- nand_debug(NDBG_BUS,"resetting...");
-
- nfc = device_get_parent(bus);
-
- if (NFC_SEND_COMMAND(nfc, NAND_CMD_RESET) != 0) {
- nand_debug(NDBG_BUS,"Error : could not sent RESET command");
- return (ENXIO);
- }
-
- if (NFC_START_COMMAND(nfc) != 0) {
- nand_debug(NDBG_BUS,"Error : could not start RESET command");
- return (ENXIO);
- }
-
- DELAY(1000);
-
- return (0);
-}
-
-void
-nandbus_lock(device_t dev)
-{
- struct nandbus_softc *sc;
-
- sc = device_get_softc(dev);
-
- mtx_lock(&sc->nandbus_mtx);
- if (sc->busy)
- cv_wait(&sc->nandbus_cv, &sc->nandbus_mtx);
- sc->busy = 1;
- mtx_unlock(&sc->nandbus_mtx);
-}
-
-void
-nandbus_unlock(device_t dev)
-{
- struct nandbus_softc *sc;
-
- sc = device_get_softc(dev);
-
- mtx_lock(&sc->nandbus_mtx);
- sc->busy = 0;
- cv_signal(&sc->nandbus_cv);
- mtx_unlock(&sc->nandbus_mtx);
-}
-
-int
-nandbus_select_cs(device_t dev, uint8_t cs)
-{
-
- return (NFC_SELECT_CS(device_get_parent(dev), cs));
-}
-
-int
-nandbus_send_command(device_t dev, uint8_t command)
-{
- int err;
-
- if ((err = NFC_SEND_COMMAND(device_get_parent(dev), command)))
- nand_debug(NDBG_BUS,"Err: Could not send command %x, err %x",
- command, err);
-
- return (err);
-}
-
-int
-nandbus_send_address(device_t dev, uint8_t address)
-{
- int err;
-
- if ((err = NFC_SEND_ADDRESS(device_get_parent(dev), address)))
- nand_debug(NDBG_BUS,"Err: Could not send address %x, err %x",
- address, err);
-
- return (err);
-}
-
-int
-nandbus_start_command(device_t dev)
-{
- int err;
-
- if ((err = NFC_START_COMMAND(device_get_parent(dev))))
- nand_debug(NDBG_BUS,"Err: Could not start command, err %x",
- err);
-
- return (err);
-}
-
-void
-nandbus_read_buffer(device_t dev, void *buf, uint32_t len)
-{
-
- NFC_READ_BUF(device_get_parent(dev), buf, len);
-}
-
-void
-nandbus_write_buffer(device_t dev, void *buf, uint32_t len)
-{
-
- NFC_WRITE_BUF(device_get_parent(dev), buf, len);
-}
-
-int
-nandbus_get_status(device_t dev, uint8_t *status)
-{
- int err;
-
- if ((err = NANDBUS_SEND_COMMAND(dev, NAND_CMD_STATUS)))
- return (err);
- if ((err = NANDBUS_START_COMMAND(dev)))
- return (err);
-
- *status = NFC_READ_BYTE(device_get_parent(dev));
-
- return (0);
-}
-
-int
-nandbus_wait_ready(device_t dev, uint8_t *status)
-{
- struct timeval tv, tv2;
-
- tv2.tv_sec = 0;
- tv2.tv_usec = 50 * 5000; /* 250ms */
-
- getmicrotime(&tv);
- timevaladd(&tv, &tv2);
-
- do {
- if (NANDBUS_GET_STATUS(dev, status))
- return (ENXIO);
-
- if (*status & NAND_STATUS_RDY)
- return (0);
-
- getmicrotime(&tv2);
- } while (timevalcmp(&tv2, &tv, <=));
-
- return (EBUSY);
-}
-
-int
-nandbus_get_ecc(device_t dev, void *buf, uint32_t pagesize, void *ecc,
- int *needwrite)
-{
-
- return (NFC_GET_ECC(device_get_parent(dev), buf, pagesize, ecc, needwrite));
-}
-
-int
-nandbus_correct_ecc(device_t dev, void *buf, int pagesize, void *readecc,
- void *calcecc)
-{
-
- return (NFC_CORRECT_ECC(device_get_parent(dev), buf, pagesize,
- readecc, calcecc));
-}
-
diff --git a/sys/dev/nand/nandbus.h b/sys/dev/nand/nandbus.h
deleted file mode 100644
index 6dd4cbf26daa..000000000000
--- a/sys/dev/nand/nandbus.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDBUS_H_
-#define _NANDBUS_H_
-
-struct nandbus_ivar {
- uint8_t cs;
- uint8_t cols;
- uint8_t rows;
- uint8_t man_id;
- uint8_t dev_id;
- uint8_t is_onfi;
- char *chip_cdev_name;
- struct nand_params *params;
-};
-
-extern devclass_t nandbus_devclass;
-extern driver_t nandbus_driver;
-
-int nandbus_create(device_t nfc);
-void nandbus_destroy(device_t nfc);
-
-#endif /* _NANDBUS_H_ */
diff --git a/sys/dev/nand/nandbus_if.m b/sys/dev/nand/nandbus_if.m
deleted file mode 100644
index e914e18de661..000000000000
--- a/sys/dev/nand/nandbus_if.m
+++ /dev/null
@@ -1,100 +0,0 @@
-#-
-# Copyright (C) 2009-2012 Semihalf
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-
-# NAND bus interface description
-#
-
-#include <sys/bus.h>
-#include <dev/nand/nand.h>
-
-INTERFACE nandbus;
-
-METHOD int get_status {
- device_t dev;
- uint8_t * status;
-};
-
-METHOD void read_buffer {
- device_t dev;
- void * buf;
- uint32_t len;
-};
-
-METHOD int select_cs {
- device_t dev;
- uint8_t cs;
-};
-
-METHOD int send_command {
- device_t dev;
- uint8_t command;
-};
-
-METHOD int send_address {
- device_t dev;
- uint8_t address;
-};
-
-METHOD int start_command {
- device_t dev;
-};
-
-METHOD int wait_ready {
- device_t dev;
- uint8_t * status;
-}
-
-METHOD void write_buffer {
- device_t dev;
- void * buf;
- uint32_t len;
-};
-
-METHOD int get_ecc {
- device_t dev;
- void * buf;
- uint32_t pagesize;
- void * ecc;
- int * needwrite;
-};
-
-METHOD int correct_ecc {
- device_t dev;
- void * buf;
- int pagesize;
- void * readecc;
- void * calcecc;
-};
-
-METHOD void lock {
- device_t dev;
-};
-
-METHOD void unlock {
- device_t dev;
-};
-
diff --git a/sys/dev/nand/nandsim.c b/sys/dev/nand/nandsim.c
deleted file mode 100644
index 4639a15700a2..000000000000
--- a/sys/dev/nand/nandsim.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* Simulated NAND controller driver */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandsim.h>
-#include <dev/nand/nandsim_chip.h>
-#include <dev/nand/nandsim_log.h>
-#include <dev/nand/nandsim_swap.h>
-
-struct sim_param sim;
-struct sim_ctrl_conf ctrls[MAX_SIM_DEV];
-
-static struct cdev *nandsim_dev;
-static d_ioctl_t nandsim_ioctl;
-
-static void nandsim_init_sim_param(struct sim_param *);
-static int nandsim_create_ctrl(struct sim_ctrl *);
-static int nandsim_destroy_ctrl(int);
-static int nandsim_ctrl_status(struct sim_ctrl *);
-static int nandsim_create_chip(struct sim_chip *);
-static int nandsim_destroy_chip(struct sim_ctrl_chip *);
-static int nandsim_chip_status(struct sim_chip *);
-static int nandsim_start_ctrl(int);
-static int nandsim_stop_ctrl(int);
-static int nandsim_inject_error(struct sim_error *);
-static int nandsim_get_block_state(struct sim_block_state *);
-static int nandsim_set_block_state(struct sim_block_state *);
-static int nandsim_modify(struct sim_mod *);
-static int nandsim_dump(struct sim_dump *);
-static int nandsim_restore(struct sim_dump *);
-static int nandsim_freeze(struct sim_ctrl_chip *);
-static void nandsim_print_log(struct sim_log *);
-static struct nandsim_chip *get_nandsim_chip(uint8_t, uint8_t);
-
-static struct cdevsw nandsim_cdevsw = {
- .d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
- .d_ioctl = nandsim_ioctl,
- .d_name = "nandsim",
-};
-
-int
-nandsim_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
- int flags, struct thread *td)
-{
- int ret = 0;
-
- switch (cmd) {
- case NANDSIM_SIM_PARAM:
- nandsim_init_sim_param((struct sim_param *)data);
- break;
- case NANDSIM_CREATE_CTRL:
- ret = nandsim_create_ctrl((struct sim_ctrl *)data);
- break;
- case NANDSIM_DESTROY_CTRL:
- ret = nandsim_destroy_ctrl(*(int *)data);
- break;
- case NANDSIM_STATUS_CTRL:
- ret = nandsim_ctrl_status((struct sim_ctrl *)data);
- break;
- case NANDSIM_CREATE_CHIP:
- ret = nandsim_create_chip((struct sim_chip *)data);
- break;
- case NANDSIM_DESTROY_CHIP:
- ret = nandsim_destroy_chip((struct sim_ctrl_chip *)data);
- break;
- case NANDSIM_STATUS_CHIP:
- ret = nandsim_chip_status((struct sim_chip *)data);
- break;
- case NANDSIM_MODIFY:
- ret = nandsim_modify((struct sim_mod *)data);
- break;
- case NANDSIM_START_CTRL:
- ret = nandsim_start_ctrl(*(int *)data);
- break;
- case NANDSIM_STOP_CTRL:
- ret = nandsim_stop_ctrl(*(int *)data);
- break;
- case NANDSIM_INJECT_ERROR:
- ret = nandsim_inject_error((struct sim_error *)data);
- break;
- case NANDSIM_SET_BLOCK_STATE:
- ret = nandsim_set_block_state((struct sim_block_state *)data);
- break;
- case NANDSIM_GET_BLOCK_STATE:
- ret = nandsim_get_block_state((struct sim_block_state *)data);
- break;
- case NANDSIM_PRINT_LOG:
- nandsim_print_log((struct sim_log *)data);
- break;
- case NANDSIM_DUMP:
- ret = nandsim_dump((struct sim_dump *)data);
- break;
- case NANDSIM_RESTORE:
- ret = nandsim_restore((struct sim_dump *)data);
- break;
- case NANDSIM_FREEZE:
- ret = nandsim_freeze((struct sim_ctrl_chip *)data);
- break;
- default:
- ret = EINVAL;
- break;
- }
-
- return (ret);
-}
-
-static void
-nandsim_init_sim_param(struct sim_param *param)
-{
-
- if (!param)
- return;
-
- nand_debug(NDBG_SIM,"log level:%d output %d", param->log_level,
- param->log_output);
- nandsim_log_level = param->log_level;
- nandsim_log_output = param->log_output;
-}
-
-static int
-nandsim_create_ctrl(struct sim_ctrl *ctrl)
-{
- struct sim_ctrl_conf *sim_ctrl;
-
- nand_debug(NDBG_SIM,"create controller num:%d cs:%d",ctrl->num,
- ctrl->num_cs);
-
- if (ctrl->num >= MAX_SIM_DEV) {
- return (EINVAL);
- }
-
- sim_ctrl = &ctrls[ctrl->num];
- if(sim_ctrl->created)
- return (EEXIST);
-
- sim_ctrl->num = ctrl->num;
- sim_ctrl->num_cs = ctrl->num_cs;
- sim_ctrl->ecc = ctrl->ecc;
- memcpy(sim_ctrl->ecc_layout, ctrl->ecc_layout,
- MAX_ECC_BYTES * sizeof(ctrl->ecc_layout[0]));
- strlcpy(sim_ctrl->filename, ctrl->filename,
- FILENAME_SIZE);
- sim_ctrl->created = 1;
-
- return (0);
-}
-
-static int
-nandsim_destroy_ctrl(int ctrl_num)
-{
-
- nand_debug(NDBG_SIM,"destroy controller num:%d", ctrl_num);
-
- if (ctrl_num >= MAX_SIM_DEV) {
- return (EINVAL);
- }
-
- if (!ctrls[ctrl_num].created) {
- return (ENODEV);
- }
-
- if (ctrls[ctrl_num].running) {
- return (EBUSY);
- }
-
- memset(&ctrls[ctrl_num], 0, sizeof(ctrls[ctrl_num]));
-
- return (0);
-}
-
-static int
-nandsim_ctrl_status(struct sim_ctrl *ctrl)
-{
-
- nand_debug(NDBG_SIM,"status controller num:%d cs:%d",ctrl->num,
- ctrl->num_cs);
-
- if (ctrl->num >= MAX_SIM_DEV) {
- return (EINVAL);
- }
-
- ctrl->num_cs = ctrls[ctrl->num].num_cs;
- ctrl->ecc = ctrls[ctrl->num].ecc;
- memcpy(ctrl->ecc_layout, ctrls[ctrl->num].ecc_layout,
- MAX_ECC_BYTES * sizeof(ctrl->ecc_layout[0]));
- strlcpy(ctrl->filename, ctrls[ctrl->num].filename,
- FILENAME_SIZE);
- ctrl->running = ctrls[ctrl->num].running;
- ctrl->created = ctrls[ctrl->num].created;
-
- return (0);
-}
-
-static int
-nandsim_create_chip(struct sim_chip *chip)
-{
- struct sim_chip *sim_chip;
-
- nand_debug(NDBG_SIM,"create chip num:%d at ctrl:%d", chip->num,
- chip->ctrl_num);
-
- if (chip->ctrl_num >= MAX_SIM_DEV ||
- chip->num >= MAX_CTRL_CS) {
- return (EINVAL);
- }
-
- if (ctrls[chip->ctrl_num].chips[chip->num]) {
- return (EEXIST);
- }
-
- sim_chip = malloc(sizeof(*sim_chip), M_NANDSIM,
- M_WAITOK);
- if (sim_chip == NULL) {
- return (ENOMEM);
- }
-
- memcpy(sim_chip, chip, sizeof(*sim_chip));
- ctrls[chip->ctrl_num].chips[chip->num] = sim_chip;
- sim_chip->created = 1;
-
- return (0);
-}
-
-static int
-nandsim_destroy_chip(struct sim_ctrl_chip *chip)
-{
- struct sim_ctrl_conf *ctrl_conf;
-
- nand_debug(NDBG_SIM,"destroy chip num:%d at ctrl:%d", chip->chip_num,
- chip->ctrl_num);
-
- if (chip->ctrl_num >= MAX_SIM_DEV ||
- chip->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- ctrl_conf = &ctrls[chip->ctrl_num];
-
- if (!ctrl_conf->created || !ctrl_conf->chips[chip->chip_num])
- return (ENODEV);
-
- if (ctrl_conf->running)
- return (EBUSY);
-
- free(ctrl_conf->chips[chip->chip_num], M_NANDSIM);
- ctrl_conf->chips[chip->chip_num] = NULL;
-
- return (0);
-}
-
-static int
-nandsim_chip_status(struct sim_chip *chip)
-{
- struct sim_ctrl_conf *ctrl_conf;
-
- nand_debug(NDBG_SIM,"status for chip num:%d at ctrl:%d", chip->num,
- chip->ctrl_num);
-
- if (chip->ctrl_num >= MAX_SIM_DEV &&
- chip->num >= MAX_CTRL_CS)
- return (EINVAL);
-
- ctrl_conf = &ctrls[chip->ctrl_num];
- if (!ctrl_conf->chips[chip->num])
- chip->created = 0;
- else
- memcpy(chip, ctrl_conf->chips[chip->num], sizeof(*chip));
-
- return (0);
-}
-
-static int
-nandsim_start_ctrl(int num)
-{
- device_t nexus, ndev;
- devclass_t nexus_devclass;
- int ret = 0;
-
- nand_debug(NDBG_SIM,"start ctlr num:%d", num);
-
- if (num >= MAX_SIM_DEV)
- return (EINVAL);
-
- if (!ctrls[num].created)
- return (ENODEV);
-
- if (ctrls[num].running)
- return (EBUSY);
-
- /* We will add our device as a child of the nexus0 device */
- if (!(nexus_devclass = devclass_find("nexus")) ||
- !(nexus = devclass_get_device(nexus_devclass, 0)))
- return (EFAULT);
-
- /*
- * Create a newbus device representing this frontend instance
- *
- * XXX powerpc nexus doesn't implement bus_add_child, so child
- * must be added by device_add_child().
- */
-#if defined(__powerpc__)
- ndev = device_add_child(nexus, "nandsim", num);
-#else
- ndev = BUS_ADD_CHILD(nexus, 0, "nandsim", num);
-#endif
- if (!ndev)
- return (EFAULT);
-
- mtx_lock(&Giant);
- ret = device_probe_and_attach(ndev);
- mtx_unlock(&Giant);
-
- if (ret == 0) {
- ctrls[num].sim_ctrl_dev = ndev;
- ctrls[num].running = 1;
- }
-
- return (ret);
-}
-
-static int
-nandsim_stop_ctrl(int num)
-{
- device_t nexus;
- devclass_t nexus_devclass;
- int ret = 0;
-
- nand_debug(NDBG_SIM,"stop controller num:%d", num);
-
- if (num >= MAX_SIM_DEV) {
- return (EINVAL);
- }
-
- if (!ctrls[num].created || !ctrls[num].running) {
- return (ENODEV);
- }
-
- /* We will add our device as a child of the nexus0 device */
- if (!(nexus_devclass = devclass_find("nexus")) ||
- !(nexus = devclass_get_device(nexus_devclass, 0))) {
- return (ENODEV);
- }
-
- mtx_lock(&Giant);
- if (ctrls[num].sim_ctrl_dev) {
- ret = device_delete_child(nexus, ctrls[num].sim_ctrl_dev);
- ctrls[num].sim_ctrl_dev = NULL;
- }
- mtx_unlock(&Giant);
-
- ctrls[num].running = 0;
-
- return (ret);
-}
-
-static struct nandsim_chip *
-get_nandsim_chip(uint8_t ctrl_num, uint8_t chip_num)
-{
- struct nandsim_softc *sc;
-
- if (!ctrls[ctrl_num].sim_ctrl_dev)
- return (NULL);
-
- sc = device_get_softc(ctrls[ctrl_num].sim_ctrl_dev);
- return (sc->chips[chip_num]);
-}
-
-static void
-nandsim_print_log(struct sim_log *sim_log)
-{
- struct nandsim_softc *sc;
- int len1, len2;
-
- if (!ctrls[sim_log->ctrl_num].sim_ctrl_dev)
- return;
-
- sc = device_get_softc(ctrls[sim_log->ctrl_num].sim_ctrl_dev);
- if (sc->log_buff) {
- len1 = strlen(&sc->log_buff[sc->log_idx + 1]);
- if (len1 >= sim_log->len)
- len1 = sim_log->len;
- copyout(&sc->log_buff[sc->log_idx + 1], sim_log->log, len1);
- len2 = strlen(sc->log_buff);
- if (len2 >= (sim_log->len - len1))
- len2 = (sim_log->len - len1);
- copyout(sc->log_buff, &sim_log->log[len1], len2);
- sim_log->len = len1 + len2;
- }
-}
-
-static int
-nandsim_inject_error(struct sim_error *error)
-{
- struct nandsim_chip *chip;
- struct block_space *bs;
- struct onfi_params *param;
- int page, page_size, block, offset;
-
- nand_debug(NDBG_SIM,"inject error for chip %d at ctrl %d\n",
- error->chip_num, error->ctrl_num);
-
- if (error->ctrl_num >= MAX_SIM_DEV ||
- error->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- if (!ctrls[error->ctrl_num].created || !ctrls[error->ctrl_num].running)
- return (ENODEV);
-
- chip = get_nandsim_chip(error->ctrl_num, error->chip_num);
- param = &chip->params;
- page_size = param->bytes_per_page + param->spare_bytes_per_page;
- block = error->page_num / param->pages_per_block;
- page = error->page_num % param->pages_per_block;
-
- bs = get_bs(chip->swap, block, 1);
- if (!bs)
- return (EINVAL);
-
- offset = (page * page_size) + error->column;
- memset(&bs->blk_ptr[offset], error->pattern, error->len);
-
- return (0);
-}
-
-static int
-nandsim_set_block_state(struct sim_block_state *bs)
-{
- struct onfi_params *params;
- struct nandsim_chip *chip;
- int blocks;
-
- nand_debug(NDBG_SIM,"set block state for %d:%d block %d\n",
- bs->chip_num, bs->ctrl_num, bs->block_num);
-
- if (bs->ctrl_num >= MAX_SIM_DEV ||
- bs->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- chip = get_nandsim_chip(bs->ctrl_num, bs->chip_num);
- params = &chip->params;
- blocks = params->luns * params->blocks_per_lun;
-
- if (bs->block_num > blocks)
- return (EINVAL);
-
- chip->blk_state[bs->block_num].is_bad = bs->state;
-
- if (bs->wearout >= 0)
- chip->blk_state[bs->block_num].wear_lev = bs->wearout;
-
- return (0);
-}
-
-static int
-nandsim_get_block_state(struct sim_block_state *bs)
-{
- struct onfi_params *params;
- struct nandsim_chip *chip;
- int blocks;
-
- if (bs->ctrl_num >= MAX_SIM_DEV ||
- bs->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- nand_debug(NDBG_SIM,"get block state for %d:%d block %d\n",
- bs->chip_num, bs->ctrl_num, bs->block_num);
-
- chip = get_nandsim_chip(bs->ctrl_num, bs->chip_num);
- params = &chip->params;
- blocks = params->luns * params->blocks_per_lun;
-
- if (bs->block_num > blocks)
- return (EINVAL);
-
- bs->state = chip->blk_state[bs->block_num].is_bad;
- bs->wearout = chip->blk_state[bs->block_num].wear_lev;
-
- return (0);
-}
-
-static int
-nandsim_dump(struct sim_dump *dump)
-{
- struct nandsim_chip *chip;
- struct block_space *bs;
- int blk_size;
-
- nand_debug(NDBG_SIM,"dump chip %d %d\n", dump->ctrl_num, dump->chip_num);
-
- if (dump->ctrl_num >= MAX_SIM_DEV ||
- dump->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- chip = get_nandsim_chip(dump->ctrl_num, dump->chip_num);
- blk_size = chip->cg.block_size +
- (chip->cg.oob_size * chip->cg.pgs_per_blk);
-
- bs = get_bs(chip->swap, dump->block_num, 0);
- if (!bs)
- return (EINVAL);
-
- if (dump->len > blk_size)
- dump->len = blk_size;
-
- copyout(bs->blk_ptr, dump->data, dump->len);
-
- return (0);
-}
-
-static int
-nandsim_restore(struct sim_dump *dump)
-{
- struct nandsim_chip *chip;
- struct block_space *bs;
- int blk_size;
-
- nand_debug(NDBG_SIM,"restore chip %d %d\n", dump->ctrl_num,
- dump->chip_num);
-
- if (dump->ctrl_num >= MAX_SIM_DEV ||
- dump->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- chip = get_nandsim_chip(dump->ctrl_num, dump->chip_num);
- blk_size = chip->cg.block_size +
- (chip->cg.oob_size * chip->cg.pgs_per_blk);
-
- bs = get_bs(chip->swap, dump->block_num, 1);
- if (!bs)
- return (EINVAL);
-
- if (dump->len > blk_size)
- dump->len = blk_size;
-
-
- copyin(dump->data, bs->blk_ptr, dump->len);
-
- return (0);
-}
-
-static int
-nandsim_freeze(struct sim_ctrl_chip *ctrl_chip)
-{
- struct nandsim_chip *chip;
-
- if (ctrl_chip->ctrl_num >= MAX_SIM_DEV ||
- ctrl_chip->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- chip = get_nandsim_chip(ctrl_chip->ctrl_num, ctrl_chip->chip_num);
- nandsim_chip_freeze(chip);
-
- return (0);
-}
-
-static int
-nandsim_modify(struct sim_mod *mod)
-{
- struct sim_chip *sim_conf = NULL;
- struct nandsim_chip *sim_chip = NULL;
-
- nand_debug(NDBG_SIM,"modify ctlr %d chip %d", mod->ctrl_num,
- mod->chip_num);
-
- if (mod->field != SIM_MOD_LOG_LEVEL) {
- if (mod->ctrl_num >= MAX_SIM_DEV ||
- mod->chip_num >= MAX_CTRL_CS)
- return (EINVAL);
-
- sim_conf = ctrls[mod->ctrl_num].chips[mod->chip_num];
- sim_chip = get_nandsim_chip(mod->ctrl_num, mod->chip_num);
- }
-
- switch (mod->field) {
- case SIM_MOD_LOG_LEVEL:
- nandsim_log_level = mod->new_value;
- break;
- case SIM_MOD_ERASE_TIME:
- sim_conf->erase_time = sim_chip->erase_delay = mod->new_value;
- break;
- case SIM_MOD_PROG_TIME:
- sim_conf->prog_time = sim_chip->prog_delay = mod->new_value;
- break;
- case SIM_MOD_READ_TIME:
- sim_conf->read_time = sim_chip->read_delay = mod->new_value;
- break;
- case SIM_MOD_ERROR_RATIO:
- sim_conf->error_ratio = mod->new_value;
- sim_chip->error_ratio = mod->new_value;
- break;
- default:
- break;
- }
-
- return (0);
-}
-static int
-nandsim_modevent(module_t mod __unused, int type, void *data __unused)
-{
- struct sim_ctrl_chip chip_ctrl;
- int i, j;
-
- switch (type) {
- case MOD_LOAD:
- nandsim_dev = make_dev(&nandsim_cdevsw, 0,
- UID_ROOT, GID_WHEEL, 0600, "nandsim.ioctl");
- break;
- case MOD_UNLOAD:
- for (i = 0; i < MAX_SIM_DEV; i++) {
- nandsim_stop_ctrl(i);
- chip_ctrl.ctrl_num = i;
- for (j = 0; j < MAX_CTRL_CS; j++) {
- chip_ctrl.chip_num = j;
- nandsim_destroy_chip(&chip_ctrl);
- }
- nandsim_destroy_ctrl(i);
- }
- destroy_dev(nandsim_dev);
- break;
- case MOD_SHUTDOWN:
- break;
- default:
- return (EOPNOTSUPP);
- }
- return (0);
-}
-
-DEV_MODULE(nandsim, nandsim_modevent, NULL);
-MODULE_VERSION(nandsim, 1);
-MODULE_DEPEND(nandsim, nand, 1, 1, 1);
-MODULE_DEPEND(nandsim, alq, 1, 1, 1);
diff --git a/sys/dev/nand/nandsim.h b/sys/dev/nand/nandsim.h
deleted file mode 100644
index d4b225113bfd..000000000000
--- a/sys/dev/nand/nandsim.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDSIM_H_
-#define _NANDSIM_H_
-
-#include <sys/ioccom.h>
-#include <sys/types.h>
-
-#define MAX_SIM_DEV 4
-#define MAX_CTRL_CS 4
-#define MAX_ECC_BYTES 512
-#define MAX_BAD_BLOCKS 512
-#define DEV_MODEL_STR_SIZE 21
-#define MAN_STR_SIZE 13
-#define FILENAME_SIZE 20
-
-#define MAX_CHIPS (MAX_SIM_DEV*MAX_CTRL_CS)
-
-#define NANDSIM_OUTPUT_NONE 0x0
-#define NANDSIM_OUTPUT_CONSOLE 0x1
-#define NANDSIM_OUTPUT_RAM 0x2
-#define NANDSIM_OUTPUT_FILE 0x3
-
-struct sim_ctrl_chip {
- uint8_t ctrl_num;
- uint8_t chip_num;
-};
-
-#define NANDSIM_BASE 'A'
-
-struct sim_param {
- uint8_t log_level;
- uint8_t log_output;
-};
-
-#define NANDSIM_SIM_PARAM _IOW(NANDSIM_BASE, 1, struct sim_param)
-
-struct sim_ctrl {
- uint8_t running;
- uint8_t created;
- uint8_t num;
- uint8_t num_cs;
- uint8_t ecc;
- char filename[FILENAME_SIZE];
- uint16_t ecc_layout[MAX_ECC_BYTES];
-};
-#define NANDSIM_CREATE_CTRL _IOW(NANDSIM_BASE, 2, struct sim_ctrl)
-#define NANDSIM_DESTROY_CTRL _IOW(NANDSIM_BASE, 3, int)
-
-struct sim_chip {
- uint8_t num;
- uint8_t ctrl_num;
- uint8_t created;
- uint8_t device_id;
- uint8_t manufact_id;
- char device_model[DEV_MODEL_STR_SIZE];
- char manufacturer[MAN_STR_SIZE];
- uint8_t col_addr_cycles;
- uint8_t row_addr_cycles;
- uint8_t features;
- uint8_t width;
- uint32_t page_size;
- uint32_t oob_size;
- uint32_t pgs_per_blk;
- uint32_t blks_per_lun;
- uint32_t luns;
-
- uint32_t prog_time;
- uint32_t erase_time;
- uint32_t read_time;
- uint32_t ccs_time;
-
- uint32_t error_ratio;
- uint32_t wear_level;
- uint32_t bad_block_map[MAX_BAD_BLOCKS];
- uint8_t is_wp;
-};
-
-#define NANDSIM_CREATE_CHIP _IOW(NANDSIM_BASE, 3, struct sim_chip)
-
-struct sim_chip_destroy {
- uint8_t ctrl_num;
- uint8_t chip_num;
-};
-#define NANDSIM_DESTROY_CHIP _IOW(NANDSIM_BASE, 4, struct sim_chip_destroy)
-
-#define NANDSIM_START_CTRL _IOW(NANDSIM_BASE, 5, int)
-#define NANDSIM_STOP_CTRL _IOW(NANDSIM_BASE, 6, int)
-#define NANDSIM_RESTART_CTRL _IOW(NANDSIM_BASE, 7, int)
-
-#define NANDSIM_STATUS_CTRL _IOWR(NANDSIM_BASE, 8, struct sim_ctrl)
-#define NANDSIM_STATUS_CHIP _IOWR(NANDSIM_BASE, 9, struct sim_chip)
-
-struct sim_mod {
- uint8_t chip_num;
- uint8_t ctrl_num;
- uint32_t field;
- uint32_t new_value;
-};
-#define SIM_MOD_LOG_LEVEL 0
-#define SIM_MOD_ERASE_TIME 1
-#define SIM_MOD_PROG_TIME 2
-#define SIM_MOD_READ_TIME 3
-#define SIM_MOD_CCS_TIME 4
-#define SIM_MOD_ERROR_RATIO 5
-
-#define NANDSIM_MODIFY _IOW(NANDSIM_BASE, 10, struct sim_mod)
-#define NANDSIM_FREEZE _IOW(NANDSIM_BASE, 11, struct sim_ctrl_chip)
-
-struct sim_error {
- uint8_t ctrl_num;
- uint8_t chip_num;
- uint32_t page_num;
- uint32_t column;
- uint32_t len;
- uint32_t pattern;
-};
-#define NANDSIM_INJECT_ERROR _IOW(NANDSIM_BASE, 20, struct sim_error)
-
-#define NANDSIM_GOOD_BLOCK 0
-#define NANDSIM_BAD_BLOCK 1
-struct sim_block_state {
- uint8_t ctrl_num;
- uint8_t chip_num;
- uint32_t block_num;
- int wearout;
- uint8_t state;
-};
-#define NANDSIM_SET_BLOCK_STATE _IOW(NANDSIM_BASE, 21, struct sim_block_state)
-#define NANDSIM_GET_BLOCK_STATE _IOWR(NANDSIM_BASE, 22, struct sim_block_state)
-
-struct sim_log {
- uint8_t ctrl_num;
- char* log;
- size_t len;
-};
-#define NANDSIM_PRINT_LOG _IOWR(NANDSIM_BASE, 23, struct sim_log)
-
-struct sim_dump {
- uint8_t ctrl_num;
- uint8_t chip_num;
- uint32_t block_num;
- uint32_t len;
- void* data;
-};
-#define NANDSIM_DUMP _IOWR(NANDSIM_BASE, 24, struct sim_dump)
-#define NANDSIM_RESTORE _IOWR(NANDSIM_BASE, 25, struct sim_dump)
-
-#endif /* _NANDSIM_H_ */
diff --git a/sys/dev/nand/nandsim_chip.c b/sys/dev/nand/nandsim_chip.c
deleted file mode 100644
index b7ab83b9d208..000000000000
--- a/sys/dev/nand/nandsim_chip.c
+++ /dev/null
@@ -1,898 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/sched.h>
-#include <sys/kthread.h>
-#include <sys/unistd.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandsim_chip.h>
-#include <dev/nand/nandsim_log.h>
-#include <dev/nand/nandsim_swap.h>
-
-MALLOC_DEFINE(M_NANDSIM, "NANDsim", "NANDsim dynamic data");
-
-#define NANDSIM_CHIP_LOCK(chip) mtx_lock(&(chip)->ns_lock)
-#define NANDSIM_CHIP_UNLOCK(chip) mtx_unlock(&(chip)->ns_lock)
-
-static nandsim_evh_t erase_evh;
-static nandsim_evh_t idle_evh;
-static nandsim_evh_t poweron_evh;
-static nandsim_evh_t reset_evh;
-static nandsim_evh_t read_evh;
-static nandsim_evh_t readid_evh;
-static nandsim_evh_t readparam_evh;
-static nandsim_evh_t write_evh;
-
-static void nandsim_loop(void *);
-static void nandsim_undefined(struct nandsim_chip *, uint8_t);
-static void nandsim_bad_address(struct nandsim_chip *, uint8_t *);
-static void nandsim_ignore_address(struct nandsim_chip *, uint8_t);
-static void nandsim_sm_error(struct nandsim_chip *);
-static void nandsim_start_handler(struct nandsim_chip *, nandsim_evh_t);
-
-static void nandsim_callout_eh(void *);
-static int nandsim_delay(struct nandsim_chip *, int);
-
-static int nandsim_bbm_init(struct nandsim_chip *, uint32_t, uint32_t *);
-static int nandsim_blk_state_init(struct nandsim_chip *, uint32_t, uint32_t);
-static void nandsim_blk_state_destroy(struct nandsim_chip *);
-static int nandchip_is_block_valid(struct nandsim_chip *, int);
-
-static void nandchip_set_status(struct nandsim_chip *, uint8_t);
-static void nandchip_clear_status(struct nandsim_chip *, uint8_t);
-
-struct proc *nandsim_proc;
-
-struct nandsim_chip *
-nandsim_chip_init(struct nandsim_softc* sc, uint8_t chip_num,
- struct sim_chip *sim_chip)
-{
- struct nandsim_chip *chip;
- struct onfi_params *chip_param;
- char swapfile[20];
- uint32_t size;
- int error;
-
- chip = malloc(sizeof(*chip), M_NANDSIM, M_WAITOK | M_ZERO);
-
- mtx_init(&chip->ns_lock, "nandsim lock", NULL, MTX_DEF);
- callout_init(&chip->ns_callout, 1);
- STAILQ_INIT(&chip->nandsim_events);
-
- chip->chip_num = chip_num;
- chip->ctrl_num = sim_chip->ctrl_num;
- chip->sc = sc;
-
- if (!sim_chip->is_wp)
- nandchip_set_status(chip, NAND_STATUS_WP);
-
- chip_param = &chip->params;
-
- chip->id.dev_id = sim_chip->device_id;
- chip->id.man_id = sim_chip->manufact_id;
-
- chip->error_ratio = sim_chip->error_ratio;
- chip->wear_level = sim_chip->wear_level;
- chip->prog_delay = sim_chip->prog_time;
- chip->erase_delay = sim_chip->erase_time;
- chip->read_delay = sim_chip->read_time;
-
- chip_param->t_prog = sim_chip->prog_time;
- chip_param->t_bers = sim_chip->erase_time;
- chip_param->t_r = sim_chip->read_time;
- bcopy("onfi", &chip_param->signature, 4);
-
- chip_param->manufacturer_id = sim_chip->manufact_id;
- strncpy(chip_param->manufacturer_name, sim_chip->manufacturer, 12);
- chip_param->manufacturer_name[11] = 0;
- strncpy(chip_param->device_model, sim_chip->device_model, 20);
- chip_param->device_model[19] = 0;
-
- chip_param->bytes_per_page = sim_chip->page_size;
- chip_param->spare_bytes_per_page = sim_chip->oob_size;
- chip_param->pages_per_block = sim_chip->pgs_per_blk;
- chip_param->blocks_per_lun = sim_chip->blks_per_lun;
- chip_param->luns = sim_chip->luns;
-
- init_chip_geom(&chip->cg, chip_param->luns, chip_param->blocks_per_lun,
- chip_param->pages_per_block, chip_param->bytes_per_page,
- chip_param->spare_bytes_per_page);
-
- chip_param->address_cycles = sim_chip->row_addr_cycles |
- (sim_chip->col_addr_cycles << 4);
- chip_param->features = sim_chip->features;
- if (sim_chip->width == 16)
- chip_param->features |= ONFI_FEAT_16BIT;
-
- size = chip_param->blocks_per_lun * chip_param->luns;
-
- error = nandsim_blk_state_init(chip, size, sim_chip->wear_level);
- if (error) {
- mtx_destroy(&chip->ns_lock);
- free(chip, M_NANDSIM);
- return (NULL);
- }
-
- error = nandsim_bbm_init(chip, size, sim_chip->bad_block_map);
- if (error) {
- mtx_destroy(&chip->ns_lock);
- nandsim_blk_state_destroy(chip);
- free(chip, M_NANDSIM);
- return (NULL);
- }
-
- nandsim_start_handler(chip, poweron_evh);
-
- nand_debug(NDBG_SIM,"Create thread for chip%d [%8p]", chip->chip_num,
- chip);
- /* Create chip thread */
- error = kproc_kthread_add(nandsim_loop, chip, &nandsim_proc,
- &chip->nandsim_td, RFSTOPPED | RFHIGHPID,
- 0, "nandsim", "chip");
- if (error) {
- mtx_destroy(&chip->ns_lock);
- nandsim_blk_state_destroy(chip);
- free(chip, M_NANDSIM);
- return (NULL);
- }
-
- thread_lock(chip->nandsim_td);
- sched_class(chip->nandsim_td, PRI_REALTIME);
- sched_add(chip->nandsim_td, SRQ_BORING);
- thread_unlock(chip->nandsim_td);
-
- size = (chip_param->bytes_per_page +
- chip_param->spare_bytes_per_page) *
- chip_param->pages_per_block;
-
- sprintf(swapfile, "chip%d%d.swp", chip->ctrl_num, chip->chip_num);
- chip->swap = nandsim_swap_init(swapfile, chip_param->blocks_per_lun *
- chip_param->luns, size);
- if (!chip->swap)
- nandsim_chip_destroy(chip);
-
- /* Wait for new thread to enter main loop */
- tsleep(chip->nandsim_td, PWAIT, "ns_chip", 1 * hz);
-
- return (chip);
-}
-
-static int
-nandsim_blk_state_init(struct nandsim_chip *chip, uint32_t size,
- uint32_t wear_lev)
-{
- int i;
-
- if (!chip || size == 0)
- return (-1);
-
- chip->blk_state = malloc(size * sizeof(struct nandsim_block_state),
- M_NANDSIM, M_WAITOK | M_ZERO);
-
- for (i = 0; i < size; i++) {
- if (wear_lev)
- chip->blk_state[i].wear_lev = wear_lev;
- else
- chip->blk_state[i].wear_lev = -1;
- }
-
- return (0);
-}
-
-static void
-nandsim_blk_state_destroy(struct nandsim_chip *chip)
-{
-
- if (chip && chip->blk_state)
- free(chip->blk_state, M_NANDSIM);
-}
-
-static int
-nandsim_bbm_init(struct nandsim_chip *chip, uint32_t size,
- uint32_t *sim_bbm)
-{
- uint32_t index;
- int i;
-
- if ((chip == NULL) || (size == 0))
- return (-1);
-
- if (chip->blk_state == NULL)
- return (-1);
-
- if (sim_bbm == NULL)
- return (0);
-
- for (i = 0; i < MAX_BAD_BLOCKS; i++) {
- index = sim_bbm[i];
-
- if (index == 0xffffffff)
- break;
- else if (index > size)
- return (-1);
- else
- chip->blk_state[index].is_bad = 1;
- }
-
- return (0);
-}
-
-void
-nandsim_chip_destroy(struct nandsim_chip *chip)
-{
- struct nandsim_ev *ev;
-
- ev = create_event(chip, NANDSIM_EV_EXIT, 0);
- if (ev)
- send_event(ev);
-}
-
-void
-nandsim_chip_freeze(struct nandsim_chip *chip)
-{
-
- chip->flags |= NANDSIM_CHIP_FROZEN;
-}
-
-static void
-nandsim_loop(void *arg)
-{
- struct nandsim_chip *chip = (struct nandsim_chip *)arg;
- struct nandsim_ev *ev;
-
- nand_debug(NDBG_SIM,"Start main loop for chip%d [%8p]", chip->chip_num,
- chip);
- for(;;) {
- NANDSIM_CHIP_LOCK(chip);
- if (!(chip->flags & NANDSIM_CHIP_ACTIVE)) {
- chip->flags |= NANDSIM_CHIP_ACTIVE;
- wakeup(chip->nandsim_td);
- }
-
- if (STAILQ_EMPTY(&chip->nandsim_events)) {
- nand_debug(NDBG_SIM,"Chip%d [%8p] going sleep",
- chip->chip_num, chip);
- msleep(chip, &chip->ns_lock, PRIBIO, "nandev", 0);
- }
-
- ev = STAILQ_FIRST(&chip->nandsim_events);
- STAILQ_REMOVE_HEAD(&chip->nandsim_events, links);
- NANDSIM_CHIP_UNLOCK(chip);
- if (ev->type == NANDSIM_EV_EXIT) {
- NANDSIM_CHIP_LOCK(chip);
- destroy_event(ev);
- wakeup(ev);
- while (!STAILQ_EMPTY(&chip->nandsim_events)) {
- ev = STAILQ_FIRST(&chip->nandsim_events);
- STAILQ_REMOVE_HEAD(&chip->nandsim_events,
- links);
- destroy_event(ev);
- wakeup(ev);
- }
- NANDSIM_CHIP_UNLOCK(chip);
- nandsim_log(chip, NANDSIM_LOG_SM, "destroyed\n");
- mtx_destroy(&chip->ns_lock);
- nandsim_blk_state_destroy(chip);
- nandsim_swap_destroy(chip->swap);
- free(chip, M_NANDSIM);
- nandsim_proc = NULL;
-
- kthread_exit();
- }
-
- if (!(chip->flags & NANDSIM_CHIP_FROZEN)) {
- nand_debug(NDBG_SIM,"Chip [%x] get event [%x]",
- chip->chip_num, ev->type);
- chip->ev_handler(chip, ev->type, ev->data);
- }
-
- wakeup(ev);
- destroy_event(ev);
- }
-
-}
-
-struct nandsim_ev *
-create_event(struct nandsim_chip *chip, uint8_t type, uint8_t data_size)
-{
- struct nandsim_ev *ev;
-
- ev = malloc(sizeof(*ev), M_NANDSIM, M_NOWAIT | M_ZERO);
- if (!ev) {
- nand_debug(NDBG_SIM,"Cannot create event");
- return (NULL);
- }
-
- if (data_size > 0)
- ev->data = malloc(sizeof(*ev), M_NANDSIM, M_NOWAIT | M_ZERO);
- ev->type = type;
- ev->chip = chip;
-
- return (ev);
-}
-
-void
-destroy_event(struct nandsim_ev *ev)
-{
-
- if (ev->data)
- free(ev->data, M_NANDSIM);
- free(ev, M_NANDSIM);
-}
-
-int
-send_event(struct nandsim_ev *ev)
-{
- struct nandsim_chip *chip = ev->chip;
-
- if (!(chip->flags & NANDSIM_CHIP_FROZEN)) {
- nand_debug(NDBG_SIM,"Chip%d [%p] send event %x",
- chip->chip_num, chip, ev->type);
-
- NANDSIM_CHIP_LOCK(chip);
- STAILQ_INSERT_TAIL(&chip->nandsim_events, ev, links);
- NANDSIM_CHIP_UNLOCK(chip);
-
- wakeup(chip);
- if ((ev->type != NANDSIM_EV_TIMEOUT) && chip->nandsim_td &&
- (curthread != chip->nandsim_td))
- tsleep(ev, PWAIT, "ns_ev", 5 * hz);
- }
-
- return (0);
-}
-
-static void
-nandsim_callout_eh(void *arg)
-{
- struct nandsim_ev *ev = (struct nandsim_ev *)arg;
-
- send_event(ev);
-}
-
-static int
-nandsim_delay(struct nandsim_chip *chip, int timeout)
-{
- struct nandsim_ev *ev;
- struct timeval delay;
- int tm;
-
- nand_debug(NDBG_SIM,"Chip[%d] Set delay: %d", chip->chip_num, timeout);
-
- ev = create_event(chip, NANDSIM_EV_TIMEOUT, 0);
- if (!ev)
- return (-1);
-
- chip->sm_state = NANDSIM_STATE_TIMEOUT;
- tm = (timeout/10000) * (hz / 100);
- if (callout_reset(&chip->ns_callout, tm, nandsim_callout_eh, ev))
- return (-1);
-
- delay.tv_sec = chip->read_delay / 1000000;
- delay.tv_usec = chip->read_delay % 1000000;
- timevaladd(&chip->delay_tv, &delay);
-
- return (0);
-}
-
-static void
-nandsim_start_handler(struct nandsim_chip *chip, nandsim_evh_t evh)
-{
- struct nandsim_ev *ev;
-
- chip->ev_handler = evh;
-
- nand_debug(NDBG_SIM,"Start handler %p for chip%d [%p]", evh,
- chip->chip_num, chip);
- ev = create_event(chip, NANDSIM_EV_START, 0);
- if (!ev)
- nandsim_sm_error(chip);
-
- send_event(ev);
-}
-
-static void
-nandchip_set_data(struct nandsim_chip *chip, uint8_t *data, uint32_t len,
- uint32_t idx)
-{
-
- nand_debug(NDBG_SIM,"Chip [%x] data %p [%x] at %x", chip->chip_num,
- data, len, idx);
- chip->data.data_ptr = data;
- chip->data.size = len;
- chip->data.index = idx;
-}
-
-static int
-nandchip_chip_space(struct nandsim_chip *chip, int32_t row, int32_t column,
- size_t size, uint8_t writing)
-{
- struct block_space *blk_space;
- uint32_t lun, block, page, offset, block_size;
- int err;
-
- block_size = chip->cg.block_size +
- (chip->cg.oob_size * chip->cg.pgs_per_blk);
-
- err = nand_row_to_blkpg(&chip->cg, row, &lun, &block, &page);
- if (err) {
- nand_debug(NDBG_SIM,"cannot get address\n");
- return (-1);
- }
-
- if (!nandchip_is_block_valid(chip, block)) {
- nandchip_set_data(chip, NULL, 0, 0);
- return (-1);
- }
-
- blk_space = get_bs(chip->swap, block, writing);
- if (!blk_space) {
- nandchip_set_data(chip, NULL, 0, 0);
- return (-1);
- }
-
- if (size > block_size)
- size = block_size;
-
- if (size == block_size) {
- offset = 0;
- column = 0;
- } else
- offset = page * (chip->cg.page_size + chip->cg.oob_size);
-
- nandchip_set_data(chip, &blk_space->blk_ptr[offset], size, column);
-
- return (0);
-}
-
-static int
-nandchip_get_addr_byte(struct nandsim_chip *chip, void *data, uint32_t *value)
-{
- int ncycles = 0;
- uint8_t byte;
- uint8_t *buffer;
-
- buffer = (uint8_t *)value;
- byte = *((uint8_t *)data);
-
- KASSERT((chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW ||
- chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL),
- ("unexpected state"));
-
- if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) {
- ncycles = chip->params.address_cycles & 0xf;
- buffer[chip->sm_addr_cycle++] = byte;
- } else if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL) {
- ncycles = (chip->params.address_cycles >> 4) & 0xf;
- buffer[chip->sm_addr_cycle++] = byte;
- }
-
- nand_debug(NDBG_SIM, "Chip [%x] read addr byte: %02x (%d of %d)\n",
- chip->chip_num, byte, chip->sm_addr_cycle, ncycles);
-
- if (chip->sm_addr_cycle == ncycles) {
- chip->sm_addr_cycle = 0;
- return (0);
- }
-
- return (1);
-}
-
-static int
-nandchip_is_block_valid(struct nandsim_chip *chip, int block_num)
-{
-
- if (!chip || !chip->blk_state)
- return (0);
-
- if (chip->blk_state[block_num].wear_lev == 0 ||
- chip->blk_state[block_num].is_bad)
- return (0);
-
- return (1);
-}
-
-static void
-nandchip_set_status(struct nandsim_chip *chip, uint8_t flags)
-{
-
- chip->chip_status |= flags;
-}
-
-static void
-nandchip_clear_status(struct nandsim_chip *chip, uint8_t flags)
-{
-
- chip->chip_status &= ~flags;
-}
-
-uint8_t
-nandchip_get_status(struct nandsim_chip *chip)
-{
- return (chip->chip_status);
-}
-
-void
-nandsim_chip_timeout(struct nandsim_chip *chip)
-{
- struct timeval tv;
-
- getmicrotime(&tv);
-
- if (chip->sm_state == NANDSIM_STATE_TIMEOUT &&
- timevalcmp(&tv, &chip->delay_tv, >=)) {
- nandchip_set_status(chip, NAND_STATUS_RDY);
- }
-}
-void
-poweron_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- uint8_t cmd;
-
- if (type == NANDSIM_EV_START)
- chip->sm_state = NANDSIM_STATE_IDLE;
- else if (type == NANDSIM_EV_CMD) {
- cmd = *(uint8_t *)data;
- switch(cmd) {
- case NAND_CMD_RESET:
- nandsim_log(chip, NANDSIM_LOG_SM, "in RESET state\n");
- nandsim_start_handler(chip, reset_evh);
- break;
- default:
- nandsim_undefined(chip, type);
- break;
- }
- } else
- nandsim_undefined(chip, type);
-}
-
-void
-idle_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- uint8_t cmd;
-
- if (type == NANDSIM_EV_START) {
- nandsim_log(chip, NANDSIM_LOG_SM, "in IDLE state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_CMD;
- } else if (type == NANDSIM_EV_CMD) {
- nandchip_clear_status(chip, NAND_STATUS_FAIL);
- getmicrotime(&chip->delay_tv);
- cmd = *(uint8_t *)data;
- switch(cmd) {
- case NAND_CMD_READ_ID:
- nandsim_start_handler(chip, readid_evh);
- break;
- case NAND_CMD_READ_PARAMETER:
- nandsim_start_handler(chip, readparam_evh);
- break;
- case NAND_CMD_READ:
- nandsim_start_handler(chip, read_evh);
- break;
- case NAND_CMD_PROG:
- nandsim_start_handler(chip, write_evh);
- break;
- case NAND_CMD_ERASE:
- nandsim_start_handler(chip, erase_evh);
- break;
- default:
- nandsim_undefined(chip, type);
- break;
- }
- } else
- nandsim_undefined(chip, type);
-}
-
-void
-readid_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- struct onfi_params *params;
- uint8_t addr;
-
- params = &chip->params;
-
- if (type == NANDSIM_EV_START) {
- nandsim_log(chip, NANDSIM_LOG_SM, "in READID state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_BYTE;
- } else if (type == NANDSIM_EV_ADDR) {
-
- addr = *((uint8_t *)data);
-
- if (addr == 0x0)
- nandchip_set_data(chip, (uint8_t *)&chip->id, 2, 0);
- else if (addr == ONFI_SIG_ADDR)
- nandchip_set_data(chip, (uint8_t *)&params->signature,
- 4, 0);
- else
- nandsim_bad_address(chip, &addr);
-
- nandsim_start_handler(chip, idle_evh);
- } else
- nandsim_undefined(chip, type);
-}
-
-void
-readparam_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- struct onfi_params *params;
- uint8_t addr;
-
- params = &chip->params;
-
- if (type == NANDSIM_EV_START) {
- nandsim_log(chip, NANDSIM_LOG_SM, "in READPARAM state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_BYTE;
- } else if (type == NANDSIM_EV_ADDR) {
- addr = *((uint8_t *)data);
-
- if (addr == 0) {
- nandchip_set_data(chip, (uint8_t *)params,
- sizeof(*params), 0);
- } else
- nandsim_bad_address(chip, &addr);
-
- nandsim_start_handler(chip, idle_evh);
- } else
- nandsim_undefined(chip, type);
-}
-
-void
-read_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- static uint32_t column = 0, row = 0;
- uint32_t size;
- uint8_t cmd;
-
- size = chip->cg.page_size + chip->cg.oob_size;
-
- switch (type) {
- case NANDSIM_EV_START:
- nandsim_log(chip, NANDSIM_LOG_SM, "in READ state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_COL;
- break;
- case NANDSIM_EV_ADDR:
- if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL) {
- if (nandchip_get_addr_byte(chip, data, &column))
- break;
-
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_ROW;
- } else if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) {
- if (nandchip_get_addr_byte(chip, data, &row))
- break;
-
- chip->sm_state = NANDSIM_STATE_WAIT_CMD;
- } else
- nandsim_ignore_address(chip, *((uint8_t *)data));
- break;
- case NANDSIM_EV_CMD:
- cmd = *(uint8_t *)data;
- if (chip->sm_state == NANDSIM_STATE_WAIT_CMD &&
- cmd == NAND_CMD_READ_END) {
- if (chip->read_delay != 0 &&
- nandsim_delay(chip, chip->read_delay) == 0)
- nandchip_clear_status(chip, NAND_STATUS_RDY);
- else {
- nandchip_chip_space(chip, row, column, size, 0);
- nandchip_set_status(chip, NAND_STATUS_RDY);
- nandsim_start_handler(chip, idle_evh);
- }
- } else
- nandsim_undefined(chip, type);
- break;
- case NANDSIM_EV_TIMEOUT:
- if (chip->sm_state == NANDSIM_STATE_TIMEOUT) {
- nandchip_chip_space(chip, row, column, size, 0);
- nandchip_set_status(chip, NAND_STATUS_RDY);
- nandsim_start_handler(chip, idle_evh);
- } else
- nandsim_undefined(chip, type);
- break;
- }
-}
-void
-write_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- static uint32_t column, row;
- uint32_t size;
- uint8_t cmd;
- int err;
-
- size = chip->cg.page_size + chip->cg.oob_size;
-
- switch(type) {
- case NANDSIM_EV_START:
- nandsim_log(chip, NANDSIM_LOG_SM, "in WRITE state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_COL;
- break;
- case NANDSIM_EV_ADDR:
- if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL) {
- if (nandchip_get_addr_byte(chip, data, &column))
- break;
-
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_ROW;
- } else if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) {
- if (nandchip_get_addr_byte(chip, data, &row))
- break;
-
- err = nandchip_chip_space(chip, row, column, size, 1);
- if (err == -1)
- nandchip_set_status(chip, NAND_STATUS_FAIL);
-
- chip->sm_state = NANDSIM_STATE_WAIT_CMD;
- } else
- nandsim_ignore_address(chip, *((uint8_t *)data));
- break;
- case NANDSIM_EV_CMD:
- cmd = *(uint8_t *)data;
- if (chip->sm_state == NANDSIM_STATE_WAIT_CMD &&
- cmd == NAND_CMD_PROG_END) {
- if (chip->prog_delay != 0 &&
- nandsim_delay(chip, chip->prog_delay) == 0)
- nandchip_clear_status(chip, NAND_STATUS_RDY);
- else {
- nandchip_set_status(chip, NAND_STATUS_RDY);
- nandsim_start_handler(chip, idle_evh);
- }
- } else
- nandsim_undefined(chip, type);
- break;
- case NANDSIM_EV_TIMEOUT:
- if (chip->sm_state == NANDSIM_STATE_TIMEOUT) {
- nandsim_start_handler(chip, idle_evh);
- nandchip_set_status(chip, NAND_STATUS_RDY);
- } else
- nandsim_undefined(chip, type);
- break;
- }
-}
-
-void
-erase_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
- static uint32_t row, block_size;
- uint32_t lun, block, page;
- int err;
- uint8_t cmd;
-
- block_size = chip->cg.block_size +
- (chip->cg.oob_size * chip->cg.pgs_per_blk);
-
- switch (type) {
- case NANDSIM_EV_START:
- nandsim_log(chip, NANDSIM_LOG_SM, "in ERASE state\n");
- chip->sm_state = NANDSIM_STATE_WAIT_ADDR_ROW;
- break;
- case NANDSIM_EV_CMD:
- cmd = *(uint8_t *)data;
- if (chip->sm_state == NANDSIM_STATE_WAIT_CMD &&
- cmd == NAND_CMD_ERASE_END) {
- if (chip->data.data_ptr != NULL &&
- chip->data.size == block_size)
- memset(chip->data.data_ptr, 0xff, block_size);
- else
- nand_debug(NDBG_SIM,"Bad block erase data\n");
-
- err = nand_row_to_blkpg(&chip->cg, row, &lun,
- &block, &page);
- if (!err) {
- if (chip->blk_state[block].wear_lev > 0)
- chip->blk_state[block].wear_lev--;
- }
-
- if (chip->erase_delay != 0 &&
- nandsim_delay(chip, chip->erase_delay) == 0)
- nandchip_clear_status(chip, NAND_STATUS_RDY);
- else {
- nandchip_set_status(chip, NAND_STATUS_RDY);
- nandsim_start_handler(chip, idle_evh);
- }
- } else
- nandsim_undefined(chip, type);
- break;
- case NANDSIM_EV_ADDR:
- if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) {
- if (nandchip_get_addr_byte(chip, data, &row))
- break;
-
- err = nandchip_chip_space(chip, row, 0, block_size, 1);
- if (err == -1) {
- nandchip_set_status(chip, NAND_STATUS_FAIL);
- }
- chip->sm_state = NANDSIM_STATE_WAIT_CMD;
- } else
- nandsim_ignore_address(chip, *((uint8_t *)data));
- break;
- case NANDSIM_EV_TIMEOUT:
- if (chip->sm_state == NANDSIM_STATE_TIMEOUT) {
- nandchip_set_status(chip, NAND_STATUS_RDY);
- nandsim_start_handler(chip, idle_evh);
- } else
- nandsim_undefined(chip, type);
- break;
- }
-}
-
-void
-reset_evh(struct nandsim_chip *chip, uint32_t type, void *data)
-{
-
- if (type == NANDSIM_EV_START) {
- nandsim_log(chip, NANDSIM_LOG_SM, "in RESET state\n");
- chip->sm_state = NANDSIM_STATE_TIMEOUT;
- nandchip_set_data(chip, NULL, 0, 0);
- DELAY(500);
- nandsim_start_handler(chip, idle_evh);
- } else
- nandsim_undefined(chip, type);
-}
-
-static void
-nandsim_undefined(struct nandsim_chip *chip, uint8_t type)
-{
-
- nandsim_log(chip, NANDSIM_LOG_ERR,
- "ERR: Chip received ev %x in state %x\n",
- type, chip->sm_state);
- nandsim_start_handler(chip, idle_evh);
-}
-
-static void
-nandsim_bad_address(struct nandsim_chip *chip, uint8_t *addr)
-{
-
- nandsim_log(chip, NANDSIM_LOG_ERR,
- "ERR: Chip received out of range address"
- "%02x%02x - %02x%02x%02x\n", addr[0], addr[1], addr[2],
- addr[3], addr[4]);
-}
-
-static void
-nandsim_ignore_address(struct nandsim_chip *chip, uint8_t byte)
-{
- nandsim_log(chip, NANDSIM_LOG_SM, "ignored address byte: %d\n", byte);
-}
-
-static void
-nandsim_sm_error(struct nandsim_chip *chip)
-{
-
- nandsim_log(chip, NANDSIM_LOG_ERR, "ERR: State machine error."
- "Restart required.\n");
-}
diff --git a/sys/dev/nand/nandsim_chip.h b/sys/dev/nand/nandsim_chip.h
deleted file mode 100644
index 86ced5ea2bf2..000000000000
--- a/sys/dev/nand/nandsim_chip.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDSIM_CHIP_H
-#define _NANDSIM_CHIP_H
-
-#include <sys/malloc.h>
-#include <sys/callout.h>
-#include <dev/nand/nand.h>
-#include <dev/nand/nandsim.h>
-#include <dev/nand/nandsim_swap.h>
-
-MALLOC_DECLARE(M_NANDSIM);
-
-#define MAX_CS_NUM 4
-struct nandsim_chip;
-
-typedef void nandsim_evh_t(struct nandsim_chip *chip, uint32_t ev, void *data);
-
-enum addr_type {
- ADDR_NONE,
- ADDR_ID,
- ADDR_ROW,
- ADDR_ROWCOL
-};
-
-struct nandsim_softc {
- struct nand_softc nand_dev;
- device_t dev;
-
- struct nandsim_chip *chips[MAX_CS_NUM];
- struct nandsim_chip *active_chip;
-
- uint8_t address_cycle;
- enum addr_type address_type;
- int log_idx;
- char *log_buff;
- struct alq *alq;
-};
-
-struct nandsim_ev {
- STAILQ_ENTRY(nandsim_ev) links;
- struct nandsim_chip *chip;
- uint8_t type;
- void *data;
-};
-
-struct nandsim_data {
- uint8_t *data_ptr;
- uint32_t index;
- uint32_t size;
-};
-
-struct nandsim_block_state {
- int32_t wear_lev;
- uint8_t is_bad;
-};
-
-#define NANDSIM_CHIP_ACTIVE 0x1
-#define NANDSIM_CHIP_FROZEN 0x2
-#define NANDSIM_CHIP_GET_STATUS 0x4
-
-struct nandsim_chip {
- struct nandsim_softc *sc;
- struct thread *nandsim_td;
-
- STAILQ_HEAD(, nandsim_ev) nandsim_events;
- nandsim_evh_t *ev_handler;
- struct mtx ns_lock;
- struct callout ns_callout;
-
- struct chip_geom cg;
- struct nand_id id;
- struct onfi_params params;
- struct nandsim_data data;
- struct nandsim_block_state *blk_state;
-
- struct chip_swap *swap;
-
- uint32_t error_ratio;
- uint32_t wear_level;
- uint32_t sm_state;
- uint32_t sm_addr_cycle;
-
- uint32_t erase_delay;
- uint32_t prog_delay;
- uint32_t read_delay;
- struct timeval delay_tv;
-
- uint8_t flags;
- uint8_t chip_status;
- uint8_t ctrl_num;
- uint8_t chip_num;
-};
-
-struct sim_ctrl_conf {
- uint8_t num;
- uint8_t num_cs;
- uint8_t ecc;
- uint8_t running;
- uint8_t created;
- device_t sim_ctrl_dev;
- struct sim_chip *chips[MAX_CTRL_CS];
- uint16_t ecc_layout[MAX_ECC_BYTES];
- char filename[FILENAME_SIZE];
-};
-
-#define NANDSIM_STATE_IDLE 0x0
-#define NANDSIM_STATE_WAIT_ADDR_BYTE 0x1
-#define NANDSIM_STATE_WAIT_CMD 0x2
-#define NANDSIM_STATE_TIMEOUT 0x3
-#define NANDSIM_STATE_WAIT_ADDR_ROW 0x4
-#define NANDSIM_STATE_WAIT_ADDR_COL 0x5
-
-#define NANDSIM_EV_START 0x1
-#define NANDSIM_EV_CMD 0x2
-#define NANDSIM_EV_ADDR 0x3
-#define NANDSIM_EV_TIMEOUT 0x4
-#define NANDSIM_EV_EXIT 0xff
-
-struct nandsim_chip *nandsim_chip_init(struct nandsim_softc *,
- uint8_t, struct sim_chip *);
-void nandsim_chip_destroy(struct nandsim_chip *);
-void nandsim_chip_freeze(struct nandsim_chip *);
-void nandsim_chip_timeout(struct nandsim_chip *);
-int nandsim_chip_check_bad_block(struct nandsim_chip *, int);
-
-uint8_t nandchip_get_status(struct nandsim_chip *);
-
-void destroy_event(struct nandsim_ev *);
-int send_event(struct nandsim_ev *);
-struct nandsim_ev *create_event(struct nandsim_chip *, uint8_t, uint8_t);
-
-#endif /* _NANDSIM_CHIP_H */
diff --git a/sys/dev/nand/nandsim_ctrl.c b/sys/dev/nand/nandsim_ctrl.c
deleted file mode 100644
index bc203902fe7e..000000000000
--- a/sys/dev/nand/nandsim_ctrl.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* Simulated NAND controller driver */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/time.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include <dev/nand/nandsim.h>
-#include <dev/nand/nandsim_log.h>
-#include <dev/nand/nandsim_chip.h>
-#include "nfc_if.h"
-
-#define ADDRESS_SIZE 5
-
-extern struct sim_ctrl_conf ctrls[MAX_SIM_DEV];
-
-static void byte_corrupt(struct nandsim_chip *, uint8_t *);
-
-static int nandsim_attach(device_t);
-static int nandsim_detach(device_t);
-static int nandsim_probe(device_t);
-
-static uint8_t nandsim_read_byte(device_t);
-static uint16_t nandsim_read_word(device_t);
-static int nandsim_select_cs(device_t, uint8_t);
-static void nandsim_write_byte(device_t, uint8_t);
-static void nandsim_write_word(device_t, uint16_t);
-static void nandsim_read_buf(device_t, void *, uint32_t);
-static void nandsim_write_buf(device_t, void *, uint32_t);
-static int nandsim_send_command(device_t, uint8_t);
-static int nandsim_send_address(device_t, uint8_t);
-
-static device_method_t nandsim_methods[] = {
- DEVMETHOD(device_probe, nandsim_probe),
- DEVMETHOD(device_attach, nandsim_attach),
- DEVMETHOD(device_detach, nandsim_detach),
-
- DEVMETHOD(nfc_select_cs, nandsim_select_cs),
- DEVMETHOD(nfc_send_command, nandsim_send_command),
- DEVMETHOD(nfc_send_address, nandsim_send_address),
- DEVMETHOD(nfc_read_byte, nandsim_read_byte),
- DEVMETHOD(nfc_read_word, nandsim_read_word),
- DEVMETHOD(nfc_write_byte, nandsim_write_byte),
- DEVMETHOD(nfc_read_buf, nandsim_read_buf),
- DEVMETHOD(nfc_write_buf, nandsim_write_buf),
-
- { 0, 0 },
-};
-
-static driver_t nandsim_driver = {
- "nandsim",
- nandsim_methods,
- sizeof(struct nandsim_softc),
-};
-
-static devclass_t nandsim_devclass;
-DRIVER_MODULE(nandsim, nexus, nandsim_driver, nandsim_devclass, 0, 0);
-DRIVER_MODULE(nandbus, nandsim, nandbus_driver, nandbus_devclass, 0, 0);
-
-static int
-nandsim_probe(device_t dev)
-{
-
- device_set_desc(dev, "NAND controller simulator");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-nandsim_attach(device_t dev)
-{
- struct nandsim_softc *sc;
- struct sim_ctrl_conf *params;
- struct sim_chip *chip;
- uint16_t *eccpos;
- int i, err;
-
- sc = device_get_softc(dev);
- params = &ctrls[device_get_unit(dev)];
-
- if (strlen(params->filename) == 0)
- snprintf(params->filename, FILENAME_SIZE, "ctrl%d.log",
- params->num);
-
- nandsim_log_init(sc, params->filename);
- for (i = 0; i < params->num_cs; i++) {
- chip = params->chips[i];
- if (chip && chip->device_id != 0) {
- sc->chips[i] = nandsim_chip_init(sc, i, chip);
- if (chip->features & ONFI_FEAT_16BIT)
- sc->nand_dev.flags |= NAND_16_BIT;
- }
- }
-
- if (params->ecc_layout[0] != 0xffff)
- eccpos = params->ecc_layout;
- else
- eccpos = NULL;
-
- nand_init(&sc->nand_dev, dev, params->ecc, 0, 0, eccpos, "nandsim");
-
- err = nandbus_create(dev);
-
- return (err);
-}
-
-static int
-nandsim_detach(device_t dev)
-{
- struct nandsim_softc *sc;
- struct sim_ctrl_conf *params;
- int i;
-
- sc = device_get_softc(dev);
- params = &ctrls[device_get_unit(dev)];
-
- for (i = 0; i < params->num_cs; i++)
- if (sc->chips[i] != NULL)
- nandsim_chip_destroy(sc->chips[i]);
-
- nandsim_log_close(sc);
-
- return (0);
-}
-
-static int
-nandsim_select_cs(device_t dev, uint8_t cs)
-{
- struct nandsim_softc *sc;
-
- sc = device_get_softc(dev);
-
- if (cs >= MAX_CS_NUM)
- return (EINVAL);
-
- sc->active_chip = sc->chips[cs];
-
- if (sc->active_chip)
- nandsim_log(sc->active_chip, NANDSIM_LOG_EV,
- "Select cs %d\n", cs);
-
- return (0);
-}
-
-static int
-nandsim_send_command(device_t dev, uint8_t command)
-{
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
- struct nandsim_ev *ev;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip == NULL)
- return (0);
-
- nandsim_log(chip, NANDSIM_LOG_EV, "Send command %x\n", command);
-
- switch (command) {
- case NAND_CMD_READ_ID:
- case NAND_CMD_READ_PARAMETER:
- sc->address_type = ADDR_ID;
- break;
- case NAND_CMD_ERASE:
- sc->address_type = ADDR_ROW;
- break;
- case NAND_CMD_READ:
- case NAND_CMD_PROG:
- sc->address_type = ADDR_ROWCOL;
- break;
- default:
- sc->address_type = ADDR_NONE;
- break;
- }
-
- if (command == NAND_CMD_STATUS)
- chip->flags |= NANDSIM_CHIP_GET_STATUS;
- else {
- ev = create_event(chip, NANDSIM_EV_CMD, 1);
- *(uint8_t *)ev->data = command;
- send_event(ev);
- }
-
- return (0);
-}
-
-static int
-nandsim_send_address(device_t dev, uint8_t addr)
-{
- struct nandsim_ev *ev;
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip == NULL)
- return (0);
-
- KASSERT((sc->address_type != ADDR_NONE), ("unexpected address"));
- nandsim_log(chip, NANDSIM_LOG_EV, "Send addr %x\n", addr);
-
- ev = create_event(chip, NANDSIM_EV_ADDR, 1);
-
- *((uint8_t *)(ev->data)) = addr;
-
- send_event(ev);
- return (0);
-}
-
-static uint8_t
-nandsim_read_byte(device_t dev)
-{
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
- uint8_t ret = 0xff;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN)) {
- if (chip->flags & NANDSIM_CHIP_GET_STATUS) {
- nandsim_chip_timeout(chip);
- ret = nandchip_get_status(chip);
- chip->flags &= ~NANDSIM_CHIP_GET_STATUS;
- } else if (chip->data.index < chip->data.size) {
- ret = chip->data.data_ptr[chip->data.index++];
- byte_corrupt(chip, &ret);
- }
- nandsim_log(chip, NANDSIM_LOG_DATA, "read %02x\n", ret);
- }
-
- return (ret);
-}
-
-static uint16_t
-nandsim_read_word(device_t dev)
-{
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
- uint16_t *data_ptr;
- uint16_t ret = 0xffff;
- uint8_t *byte_ret = (uint8_t *)&ret;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN)) {
- if (chip->data.index < chip->data.size - 1) {
- data_ptr =
- (uint16_t *)&(chip->data.data_ptr[chip->data.index]);
- ret = *data_ptr;
- chip->data.index += 2;
- byte_corrupt(chip, byte_ret);
- byte_corrupt(chip, byte_ret + 1);
- }
- nandsim_log(chip, NANDSIM_LOG_DATA, "read %04x\n", ret);
- }
-
- return (ret);
-}
-
-static void
-nandsim_write_byte(device_t dev, uint8_t byte)
-{
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN) &&
- (chip->data.index < chip->data.size)) {
- byte_corrupt(chip, &byte);
- chip->data.data_ptr[chip->data.index] &= byte;
- chip->data.index++;
- nandsim_log(chip, NANDSIM_LOG_DATA, "write %02x\n", byte);
- }
-}
-
-static void
-nandsim_write_word(device_t dev, uint16_t word)
-{
- struct nandsim_softc *sc;
- struct nandsim_chip *chip;
- uint16_t *data_ptr;
- uint8_t *byte_ptr = (uint8_t *)&word;
-
- sc = device_get_softc(dev);
- chip = sc->active_chip;
-
- if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN)) {
- if ((chip->data.index + 1) < chip->data.size) {
- byte_corrupt(chip, byte_ptr);
- byte_corrupt(chip, byte_ptr + 1);
- data_ptr =
- (uint16_t *)&(chip->data.data_ptr[chip->data.index]);
- *data_ptr &= word;
- chip->data.index += 2;
- }
-
- nandsim_log(chip, NANDSIM_LOG_DATA, "write %04x\n", word);
- }
-}
-
-static void
-nandsim_read_buf(device_t dev, void *buf, uint32_t len)
-{
- struct nandsim_softc *sc;
- uint16_t *buf16 = (uint16_t *)buf;
- uint8_t *buf8 = (uint8_t *)buf;
- int i;
-
- sc = device_get_softc(dev);
-
- if (sc->nand_dev.flags & NAND_16_BIT) {
- for (i = 0; i < len / 2; i++)
- buf16[i] = nandsim_read_word(dev);
- } else {
- for (i = 0; i < len; i++)
- buf8[i] = nandsim_read_byte(dev);
- }
-}
-
-static void
-nandsim_write_buf(device_t dev, void *buf, uint32_t len)
-{
- struct nandsim_softc *sc;
- uint16_t *buf16 = (uint16_t *)buf;
- uint8_t *buf8 = (uint8_t *)buf;
- int i;
-
- sc = device_get_softc(dev);
-
- if (sc->nand_dev.flags & NAND_16_BIT) {
- for (i = 0; i < len / 2; i++)
- nandsim_write_word(dev, buf16[i]);
- } else {
- for (i = 0; i < len; i++)
- nandsim_write_byte(dev, buf8[i]);
- }
-}
-
-static void
-byte_corrupt(struct nandsim_chip *chip, uint8_t *byte)
-{
- uint32_t rand;
- uint8_t bit;
-
- rand = random();
- if ((rand % 1000000) < chip->error_ratio) {
- bit = rand % 8;
- if (*byte & (1 << bit))
- *byte &= ~(1 << bit);
- else
- *byte |= (1 << bit);
- }
-}
diff --git a/sys/dev/nand/nandsim_log.c b/sys/dev/nand/nandsim_log.c
deleted file mode 100644
index 0bd316ace4e2..000000000000
--- a/sys/dev/nand/nandsim_log.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/proc.h>
-#include <sys/alq.h>
-#include <sys/time.h>
-
-#include <machine/stdarg.h>
-
-#include <dev/nand/nandsim_log.h>
-
-int nandsim_log_level;
-int nandsim_log_output;
-int log_size = NANDSIM_RAM_LOG_SIZE;
-
-static int nandsim_entry_size = NANDSIM_ENTRY_SIZE;
-static int nandsim_entry_count = NANDSIM_ENTRY_COUNT;
-static int str_index = 0;
-static char string[NANDSIM_ENTRY_SIZE + 1] = {0};
-
-int
-nandsim_log_init(struct nandsim_softc *sc, char *filename)
-{
- int error = 0;
-
- if (nandsim_log_output == NANDSIM_OUTPUT_FILE) {
- error = alq_open(&sc->alq, filename,
- curthread->td_ucred, 0644,
- nandsim_entry_size, nandsim_entry_count);
- } else if (nandsim_log_output == NANDSIM_OUTPUT_RAM) {
- sc->log_buff = malloc(log_size, M_NANDSIM, M_WAITOK | M_ZERO);
- if (!sc->log_buff)
- error = ENOMEM;
- }
-
- return (error);
-}
-
-void
-nandsim_log_close(struct nandsim_softc *sc)
-{
-
- if (nandsim_log_output == NANDSIM_OUTPUT_FILE) {
- memset(&string[str_index], 0, NANDSIM_ENTRY_SIZE - str_index);
- alq_write(sc->alq, (void *) string, ALQ_NOWAIT);
- str_index = 0;
- string[0] = '\0';
- alq_close(sc->alq);
- } else if (nandsim_log_output == NANDSIM_OUTPUT_RAM) {
- free(sc->log_buff, M_NANDSIM);
- sc->log_buff = NULL;
- }
-}
-
-void
-nandsim_log(struct nandsim_chip *chip, int level, const char *fmt, ...)
-{
- char hdr[TIME_STR_SIZE];
- char tmp[NANDSIM_ENTRY_SIZE];
- struct nandsim_softc *sc;
- struct timeval currtime;
- va_list ap;
- int hdr_len, len, rest;
-
- if (nandsim_log_output == NANDSIM_OUTPUT_NONE)
- return;
-
- if (chip == NULL)
- return;
-
- sc = chip->sc;
- if (!sc->alq && nandsim_log_output == NANDSIM_OUTPUT_FILE)
- return;
-
- if (level <= nandsim_log_level) {
- microtime(&currtime);
- hdr_len = sprintf(hdr, "%08jd.%08li [chip:%d, ctrl:%d]: ",
- (intmax_t)currtime.tv_sec, currtime.tv_usec,
- chip->chip_num, chip->ctrl_num);
-
- switch(nandsim_log_output) {
- case NANDSIM_OUTPUT_CONSOLE:
- printf("%s", hdr);
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
- break;
- case NANDSIM_OUTPUT_RAM:
- va_start(ap, fmt);
- len = vsnprintf(tmp, NANDSIM_ENTRY_SIZE - 1, fmt, ap);
- tmp[NANDSIM_ENTRY_SIZE - 1] = 0;
- va_end(ap);
-
- rest = log_size - sc->log_idx - 1;
- if (rest >= hdr_len) {
- bcopy(hdr, &sc->log_buff[sc->log_idx],
- hdr_len);
- sc->log_idx += hdr_len;
- sc->log_buff[sc->log_idx] = 0;
- } else {
- bcopy(hdr, &sc->log_buff[sc->log_idx], rest);
- bcopy(&hdr[rest], sc->log_buff,
- hdr_len - rest);
- sc->log_idx = hdr_len - rest;
- sc->log_buff[sc->log_idx] = 0;
- }
-
- rest = log_size - sc->log_idx - 1;
- if (rest >= len) {
- bcopy(tmp, &sc->log_buff[sc->log_idx], len);
- sc->log_idx += len;
- sc->log_buff[sc->log_idx] = 0;
- } else {
- bcopy(tmp, &sc->log_buff[sc->log_idx], rest);
- bcopy(&tmp[rest], sc->log_buff, len - rest);
- sc->log_idx = len - rest;
- sc->log_buff[sc->log_idx] = 0;
- }
-
- break;
-
- case NANDSIM_OUTPUT_FILE:
- va_start(ap, fmt);
- len = vsnprintf(tmp, NANDSIM_ENTRY_SIZE - 1, fmt, ap);
- tmp[NANDSIM_ENTRY_SIZE - 1] = 0;
- va_end(ap);
-
- rest = NANDSIM_ENTRY_SIZE - str_index;
- if (rest >= hdr_len) {
- strcat(string, hdr);
- str_index += hdr_len;
- } else {
- strlcat(string, hdr, NANDSIM_ENTRY_SIZE + 1);
- alq_write(sc->alq, (void *) string,
- ALQ_NOWAIT);
- strcpy(string, &hdr[rest]);
- str_index = hdr_len - rest;
- }
- rest = NANDSIM_ENTRY_SIZE - str_index;
- if (rest >= len) {
- strcat(string, tmp);
- str_index += len;
- } else {
- strlcat(string, tmp, NANDSIM_ENTRY_SIZE + 1);
- alq_write(sc->alq, (void *) string,
- ALQ_NOWAIT);
- strcpy(string, &tmp[rest]);
- str_index = len - rest;
- }
- break;
- default:
- break;
- }
- }
-}
diff --git a/sys/dev/nand/nandsim_log.h b/sys/dev/nand/nandsim_log.h
deleted file mode 100644
index 5e5a055a4053..000000000000
--- a/sys/dev/nand/nandsim_log.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDSIM_LOG_H
-#define _NANDSIM_LOG_H
-
-#include <dev/nand/nandsim_chip.h>
-
-#define NANDSIM_ENTRY_SIZE 128
-#define NANDSIM_ENTRY_COUNT 1024
-#define NANDSIM_RAM_LOG_SIZE 16384
-#define TIME_STR_SIZE 40
-
-#define NANDSIM_LOG_ERR 1
-#define NANDSIM_LOG_SM 5
-#define NANDSIM_LOG_EV 10
-#define NANDSIM_LOG_DATA 15
-
-extern int nandsim_log_level;
-extern int nandsim_log_output;
-
-int nandsim_log_init(struct nandsim_softc *, char *);
-void nandsim_log_close(struct nandsim_softc *);
-void nandsim_log(struct nandsim_chip *, int, const char *, ...);
-
-#endif /* _NANDSIM_LOG_H */
-
diff --git a/sys/dev/nand/nandsim_swap.c b/sys/dev/nand/nandsim_swap.c
deleted file mode 100644
index 78e14e9557bd..000000000000
--- a/sys/dev/nand/nandsim_swap.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/queue.h>
-#include <sys/fcntl.h>
-#include <sys/proc.h>
-#include <sys/namei.h>
-#include <sys/lock.h>
-#include <sys/vnode.h>
-#include <sys/mount.h>
-
-#include <dev/nand/nandsim_chip.h>
-#include <dev/nand/nandsim_swap.h>
-
-static int init_block_state(struct chip_swap *);
-static void destroy_block_state(struct chip_swap *);
-
-static int create_buffers(struct chip_swap *);
-static void destroy_buffers(struct chip_swap *);
-
-static int swap_file_open(struct chip_swap *, const char *);
-static void swap_file_close(struct chip_swap *);
-static int swap_file_write(struct chip_swap *, struct block_state *);
-static int swap_file_read(struct chip_swap *, struct block_state *);
-
-#define CHIP_SWAP_CMODE 0600
-#define CHIP_SWAP_BLOCKSPACES 2
-
-static int
-init_block_state(struct chip_swap *swap)
-{
- struct block_state *blk_state;
- int i;
-
- if (swap == NULL)
- return (-1);
-
- blk_state = malloc(swap->nof_blks * sizeof(struct block_state),
- M_NANDSIM, M_WAITOK | M_ZERO);
-
- for (i = 0; i < swap->nof_blks; i++)
- blk_state[i].offset = 0xffffffff;
-
- swap->blk_state = blk_state;
-
- return (0);
-}
-
-static void
-destroy_block_state(struct chip_swap *swap)
-{
-
- if (swap == NULL)
- return;
-
- if (swap->blk_state != NULL)
- free(swap->blk_state, M_NANDSIM);
-}
-
-static int
-create_buffers(struct chip_swap *swap)
-{
- struct block_space *block_space;
- void *block;
- int i;
-
- for (i = 0; i < CHIP_SWAP_BLOCKSPACES; i++) {
- block_space = malloc(sizeof(*block_space), M_NANDSIM, M_WAITOK);
- block = malloc(swap->blk_size, M_NANDSIM, M_WAITOK);
- block_space->blk_ptr = block;
- SLIST_INSERT_HEAD(&swap->free_bs, block_space, free_link);
- nand_debug(NDBG_SIM,"created blk_space %p[%p]\n", block_space,
- block);
- }
-
- if (i == 0)
- return (-1);
-
- return (0);
-}
-
-static void
-destroy_buffers(struct chip_swap *swap)
-{
- struct block_space *blk_space;
-
- if (swap == NULL)
- return;
-
- blk_space = SLIST_FIRST(&swap->free_bs);
- while (blk_space) {
- SLIST_REMOVE_HEAD(&swap->free_bs, free_link);
- nand_debug(NDBG_SIM,"destroyed blk_space %p[%p]\n",
- blk_space, blk_space->blk_ptr);
- free(blk_space->blk_ptr, M_NANDSIM);
- free(blk_space, M_NANDSIM);
- blk_space = SLIST_FIRST(&swap->free_bs);
- }
-
- blk_space = STAILQ_FIRST(&swap->used_bs);
- while (blk_space) {
- STAILQ_REMOVE_HEAD(&swap->used_bs, used_link);
- nand_debug(NDBG_SIM,"destroyed blk_space %p[%p]\n",
- blk_space, blk_space->blk_ptr);
- free(blk_space->blk_ptr, M_NANDSIM);
- free(blk_space, M_NANDSIM);
- blk_space = STAILQ_FIRST(&swap->used_bs);
- }
-}
-
-static int
-swap_file_open(struct chip_swap *swap, const char *swap_file)
-{
- struct nameidata nd;
- int flags, error;
-
- NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, swap_file,
- curthread);
-
- flags = FWRITE | FREAD | O_NOFOLLOW | O_CREAT | O_TRUNC;
-
- error = vn_open(&nd, &flags, CHIP_SWAP_CMODE, NULL);
- if (error) {
- nand_debug(NDBG_SIM,"Cannot create swap file %s", swap_file);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- return (error);
- }
-
- swap->swap_cred = crhold(curthread->td_ucred);
- NDFREE(&nd, NDF_ONLY_PNBUF);
-
- /* We just unlock so we hold a reference */
- VOP_UNLOCK(nd.ni_vp, 0);
-
- swap->swap_vp = nd.ni_vp;
-
- return (0);
-}
-
-static void
-swap_file_close(struct chip_swap *swap)
-{
-
- if (swap == NULL)
- return;
-
- if (swap->swap_vp == NULL)
- return;
-
- vn_close(swap->swap_vp, FWRITE, swap->swap_cred, curthread);
- crfree(swap->swap_cred);
-}
-
-static int
-swap_file_write(struct chip_swap *swap, struct block_state *blk_state)
-{
- struct block_space *blk_space;
- struct thread *td;
- struct mount *mp;
- struct vnode *vp;
- struct uio auio;
- struct iovec aiov;
-
- if (swap == NULL || blk_state == NULL)
- return (-1);
-
- blk_space = blk_state->blk_sp;
- if (blk_state->offset == -1) {
- blk_state->offset = swap->swap_offset;
- swap->swap_offset += swap->blk_size;
- }
-
- nand_debug(NDBG_SIM,"saving %p[%p] at %x\n",
- blk_space, blk_space->blk_ptr, blk_state->offset);
-
- bzero(&aiov, sizeof(aiov));
- bzero(&auio, sizeof(auio));
-
- aiov.iov_base = blk_space->blk_ptr;
- aiov.iov_len = swap->blk_size;
- td = curthread;
- vp = swap->swap_vp;
-
- auio.uio_iov = &aiov;
- auio.uio_offset = blk_state->offset;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_rw = UIO_WRITE;
- auio.uio_iovcnt = 1;
- auio.uio_resid = swap->blk_size;
- auio.uio_td = td;
-
- vn_start_write(vp, &mp, V_WAIT);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- VOP_WRITE(vp, &auio, IO_UNIT, swap->swap_cred);
- VOP_UNLOCK(vp, 0);
- vn_finished_write(mp);
-
- return (0);
-}
-
-static int
-swap_file_read(struct chip_swap *swap, struct block_state *blk_state)
-{
- struct block_space *blk_space;
- struct thread *td;
- struct vnode *vp;
- struct uio auio;
- struct iovec aiov;
-
- if (swap == NULL || blk_state == NULL)
- return (-1);
-
- blk_space = blk_state->blk_sp;
-
- nand_debug(NDBG_SIM,"restore %p[%p] at %x\n",
- blk_space, blk_space->blk_ptr, blk_state->offset);
-
- bzero(&aiov, sizeof(aiov));
- bzero(&auio, sizeof(auio));
-
- aiov.iov_base = blk_space->blk_ptr;
- aiov.iov_len = swap->blk_size;
- td = curthread;
- vp = swap->swap_vp;
-
- auio.uio_iov = &aiov;
- auio.uio_offset = blk_state->offset;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_rw = UIO_READ;
- auio.uio_iovcnt = 1;
- auio.uio_resid = swap->blk_size;
- auio.uio_td = td;
-
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- VOP_READ(vp, &auio, 0, swap->swap_cred);
- VOP_UNLOCK(vp, 0);
-
- return (0);
-}
-
-struct chip_swap *
-nandsim_swap_init(const char *swap_file, uint32_t nof_blks, uint32_t blk_size)
-{
- struct chip_swap *swap;
- int err = 0;
-
- if ((swap_file == NULL) || (nof_blks == 0) || (blk_size == 0))
- return (NULL);
-
- swap = malloc(sizeof(*swap), M_NANDSIM, M_WAITOK | M_ZERO);
-
- SLIST_INIT(&swap->free_bs);
- STAILQ_INIT(&swap->used_bs);
- swap->blk_size = blk_size;
- swap->nof_blks = nof_blks;
-
- err = init_block_state(swap);
- if (err) {
- nandsim_swap_destroy(swap);
- return (NULL);
- }
-
- err = create_buffers(swap);
- if (err) {
- nandsim_swap_destroy(swap);
- return (NULL);
- }
-
- err = swap_file_open(swap, swap_file);
- if (err) {
- nandsim_swap_destroy(swap);
- return (NULL);
- }
-
- return (swap);
-}
-
-void
-nandsim_swap_destroy(struct chip_swap *swap)
-{
-
- if (swap == NULL)
- return;
-
- destroy_block_state(swap);
- destroy_buffers(swap);
- swap_file_close(swap);
- free(swap, M_NANDSIM);
-}
-
-struct block_space *
-get_bs(struct chip_swap *swap, uint32_t block, uint8_t writing)
-{
- struct block_state *blk_state, *old_blk_state = NULL;
- struct block_space *blk_space;
-
- if (swap == NULL || (block >= swap->nof_blks))
- return (NULL);
-
- blk_state = &swap->blk_state[block];
- nand_debug(NDBG_SIM,"blk_state %x\n", blk_state->status);
-
- if (blk_state->status & BLOCK_ALLOCATED) {
- blk_space = blk_state->blk_sp;
- } else {
- blk_space = SLIST_FIRST(&swap->free_bs);
- if (blk_space) {
- SLIST_REMOVE_HEAD(&swap->free_bs, free_link);
- STAILQ_INSERT_TAIL(&swap->used_bs, blk_space,
- used_link);
- } else {
- blk_space = STAILQ_FIRST(&swap->used_bs);
- old_blk_state = blk_space->blk_state;
- STAILQ_REMOVE_HEAD(&swap->used_bs, used_link);
- STAILQ_INSERT_TAIL(&swap->used_bs, blk_space,
- used_link);
- if (old_blk_state->status & BLOCK_DIRTY) {
- swap_file_write(swap, old_blk_state);
- old_blk_state->status &= ~BLOCK_DIRTY;
- old_blk_state->status |= BLOCK_SWAPPED;
- }
- }
- }
-
- if (blk_space == NULL)
- return (NULL);
-
- if (old_blk_state != NULL) {
- old_blk_state->status &= ~BLOCK_ALLOCATED;
- old_blk_state->blk_sp = NULL;
- }
-
- blk_state->blk_sp = blk_space;
- blk_space->blk_state = blk_state;
-
- if (!(blk_state->status & BLOCK_ALLOCATED)) {
- if (blk_state->status & BLOCK_SWAPPED)
- swap_file_read(swap, blk_state);
- else
- memset(blk_space->blk_ptr, 0xff, swap->blk_size);
- blk_state->status |= BLOCK_ALLOCATED;
- }
-
- if (writing)
- blk_state->status |= BLOCK_DIRTY;
-
- nand_debug(NDBG_SIM,"get_bs returned %p[%p] state %x\n", blk_space,
- blk_space->blk_ptr, blk_state->status);
-
- return (blk_space);
-}
diff --git a/sys/dev/nand/nandsim_swap.h b/sys/dev/nand/nandsim_swap.h
deleted file mode 100644
index c9eb0be63a9c..000000000000
--- a/sys/dev/nand/nandsim_swap.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDSIM_SWAP_CHIP_H_
-#define _NANDSIM_SWAP_CHIP_H_
-
-struct block_space {
- SLIST_ENTRY(block_space) free_link;
- STAILQ_ENTRY(block_space) used_link;
- struct block_state *blk_state;
- uint8_t *blk_ptr;
-};
-
-#define BLOCK_ALLOCATED 0x1
-#define BLOCK_SWAPPED 0x2
-#define BLOCK_DIRTY 0x4
-
-struct block_state {
- struct block_space *blk_sp;
- uint32_t offset;
- uint8_t status;
-};
-
-struct chip_swap {
- struct block_state *blk_state;
- SLIST_HEAD(,block_space) free_bs;
- STAILQ_HEAD(,block_space) used_bs;
- struct ucred *swap_cred;
- struct vnode *swap_vp;
- uint32_t swap_offset;
- uint32_t blk_size;
- uint32_t nof_blks;
-};
-
-struct chip_swap *nandsim_swap_init(const char *, uint32_t, uint32_t);
-void nandsim_swap_destroy(struct chip_swap *);
-struct block_space *get_bs(struct chip_swap *, uint32_t, uint8_t);
-
-#endif /* _NANDSIM_SWAP_CHIP_H_ */
diff --git a/sys/dev/nand/nfc_fsl.c b/sys/dev/nand/nfc_fsl.c
deleted file mode 100644
index 992cfeb784fe..000000000000
--- a/sys/dev/nand/nfc_fsl.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2012 Juniper Networks, Inc.
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-/*
- * TODO :
- *
- * -- test support for small pages
- * -- support for reading ONFI parameters
- * -- support for cached and interleaving commands
- * -- proper setting of AL bits in FMR
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <sys/sysctl.h>
-#include <sys/time.h>
-#include <sys/kdb.h>
-
-#include <machine/bus.h>
-
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <powerpc/mpc85xx/lbc.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-
-#include "nfc_fsl.h"
-
-#include "nfc_if.h"
-
-#define LBC_READ(regname) lbc_read_reg(dev, (LBC85XX_ ## regname))
-#define LBC_WRITE(regname, val) lbc_write_reg(dev, (LBC85XX_ ## regname), val)
-
-enum addr_type {
- ADDR_NONE,
- ADDR_ID,
- ADDR_ROW,
- ADDR_ROWCOL
-};
-
-struct fsl_nfc_fcm {
- /* Read-only after initialization */
- uint32_t reg_fmr;
-
- /* To be preserved across "start_command" */
- u_int buf_ofs;
- u_int read_ptr;
- u_int status:1;
-
- /* Command state -- cleared by "start_command" */
- uint32_t fcm_startzero;
- uint32_t reg_fcr;
- uint32_t reg_fir;
- uint32_t reg_mdr;
- uint32_t reg_fbcr;
- uint32_t reg_fbar;
- uint32_t reg_fpar;
- u_int cmdnr;
- u_int opnr;
- u_int pg_ofs;
- enum addr_type addr_type;
- u_int addr_bytes;
- u_int row_addr;
- u_int column_addr;
- u_int data_fir:8;
- uint32_t fcm_endzero;
-};
-
-struct fsl_nand_softc {
- struct nand_softc nand_dev;
- device_t dev;
- struct resource *res;
- int rid; /* Resourceid */
- struct lbc_devinfo *dinfo;
- struct fsl_nfc_fcm fcm;
- uint8_t col_cycles;
- uint8_t row_cycles;
- uint16_t pgsz; /* Page size */
-};
-
-static int fsl_nand_attach(device_t dev);
-static int fsl_nand_probe(device_t dev);
-static int fsl_nand_detach(device_t dev);
-
-static int fsl_nfc_select_cs(device_t dev, uint8_t cs);
-static int fsl_nfc_read_rnb(device_t dev);
-static int fsl_nfc_send_command(device_t dev, uint8_t command);
-static int fsl_nfc_send_address(device_t dev, uint8_t address);
-static uint8_t fsl_nfc_read_byte(device_t dev);
-static int fsl_nfc_start_command(device_t dev);
-static void fsl_nfc_read_buf(device_t dev, void *buf, uint32_t len);
-static void fsl_nfc_write_buf(device_t dev, void *buf, uint32_t len);
-
-static device_method_t fsl_nand_methods[] = {
- DEVMETHOD(device_probe, fsl_nand_probe),
- DEVMETHOD(device_attach, fsl_nand_attach),
- DEVMETHOD(device_detach, fsl_nand_detach),
-
- DEVMETHOD(nfc_select_cs, fsl_nfc_select_cs),
- DEVMETHOD(nfc_read_rnb, fsl_nfc_read_rnb),
- DEVMETHOD(nfc_start_command, fsl_nfc_start_command),
- DEVMETHOD(nfc_send_command, fsl_nfc_send_command),
- DEVMETHOD(nfc_send_address, fsl_nfc_send_address),
- DEVMETHOD(nfc_read_byte, fsl_nfc_read_byte),
- DEVMETHOD(nfc_read_buf, fsl_nfc_read_buf),
- DEVMETHOD(nfc_write_buf, fsl_nfc_write_buf),
- { 0, 0 },
-};
-
-static driver_t fsl_nand_driver = {
- "nand",
- fsl_nand_methods,
- sizeof(struct fsl_nand_softc),
-};
-
-static devclass_t fsl_nand_devclass;
-
-DRIVER_MODULE(fsl_nand, lbc, fsl_nand_driver, fsl_nand_devclass,
- 0, 0);
-
-static int fsl_nand_build_address(device_t dev, uint32_t page, uint32_t column);
-static int fsl_nand_chip_preprobe(device_t dev, struct nand_id *id);
-
-#ifdef NAND_DEBUG_TIMING
-static device_t fcm_devs[8];
-#endif
-
-#define CMD_SHIFT(cmd_num) (24 - ((cmd_num) * 8))
-#define OP_SHIFT(op_num) (28 - ((op_num) * 4))
-
-#define FSL_LARGE_PAGE_SIZE (2112)
-#define FSL_SMALL_PAGE_SIZE (528)
-
-static void
-fsl_nand_init_regs(struct fsl_nand_softc *sc)
-{
- uint32_t or_v, br_v;
- device_t dev;
-
- dev = sc->dev;
-
- sc->fcm.reg_fmr = (15 << FMR_CWTO_SHIFT);
-
- /*
- * Setup 4 row cycles and hope that chip ignores superfluous address
- * bytes.
- */
- sc->fcm.reg_fmr |= (2 << FMR_AL_SHIFT);
-
- /* Reprogram BR(x) */
- br_v = lbc_read_reg(dev, LBC85XX_BR(sc->dinfo->di_bank));
- br_v &= 0xffff8000;
- br_v |= 1 << 11; /* 8-bit port size */
- br_v |= 0 << 9; /* No ECC checking and generation */
- br_v |= 1 << 5; /* FCM machine */
- br_v |= 1; /* Valid */
- lbc_write_reg(dev, LBC85XX_BR(sc->dinfo->di_bank), br_v);
-
- /* Reprogram OR(x) */
- or_v = lbc_read_reg(dev, LBC85XX_OR(sc->dinfo->di_bank));
- or_v &= 0xfffffc00;
- or_v |= 0x03AE; /* Default POR timing */
- lbc_write_reg(dev, LBC85XX_OR(sc->dinfo->di_bank), or_v);
-
- if (or_v & OR_FCM_PAGESIZE) {
- sc->pgsz = FSL_LARGE_PAGE_SIZE;
- sc->col_cycles = 2;
- nand_debug(NDBG_DRV, "%s: large page NAND device at #%d",
- device_get_nameunit(dev), sc->dinfo->di_bank);
- } else {
- sc->pgsz = FSL_SMALL_PAGE_SIZE;
- sc->col_cycles = 1;
- nand_debug(NDBG_DRV, "%s: small page NAND device at #%d",
- device_get_nameunit(dev), sc->dinfo->di_bank);
- }
-}
-
-static int
-fsl_nand_probe(device_t dev)
-{
-
- if (!ofw_bus_is_compatible(dev, "fsl,elbc-fcm-nand"))
- return (ENXIO);
-
- device_set_desc(dev, "Freescale localbus FCM Controller");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-fsl_nand_attach(device_t dev)
-{
- struct fsl_nand_softc *sc;
- struct nand_id id;
- struct nand_params *param;
- uint32_t num_pages;
-
- sc = device_get_softc(dev);
- sc->dev = dev;
- sc->dinfo = device_get_ivars(dev);
-
- sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
- RF_ACTIVE);
- if (sc->res == NULL) {
- device_printf(dev, "could not allocate resources!\n");
- return (ENXIO);
- }
-
- bzero(&sc->fcm, sizeof(sc->fcm));
-
- /* Init register and check if HW ECC turned on */
- fsl_nand_init_regs(sc);
-
- /* Chip is probed, so determine number of row address cycles */
- fsl_nand_chip_preprobe(dev, &id);
- param = nand_get_params(&id);
- if (param != NULL) {
- num_pages = (param->chip_size << 20) / param->page_size;
- while(num_pages) {
- sc->row_cycles++;
- num_pages >>= 8;
- }
-
- sc->fcm.reg_fmr &= ~(FMR_AL);
- sc->fcm.reg_fmr |= (sc->row_cycles - 2) << FMR_AL_SHIFT;
- }
-
- nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL);
-
-#ifdef NAND_DEBUG_TIMING
- fcm_devs[sc->dinfo->di_bank] = dev;
-#endif
-
- return (nandbus_create(dev));
-}
-
-static int
-fsl_nand_detach(device_t dev)
-{
- struct fsl_nand_softc *sc;
-
- sc = device_get_softc(dev);
-
- if (sc->res != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
-
- return (0);
-}
-
-static int
-fsl_nfc_select_cs(device_t dev, uint8_t cs)
-{
-
- // device_printf(dev, "%s(cs=%u)\n", __func__, cs);
- return ((cs > 0) ? EINVAL : 0);
-}
-
-static int
-fsl_nfc_read_rnb(device_t dev)
-{
-
- // device_printf(dev, "%s()\n", __func__);
- return (0);
-}
-
-static int
-fsl_nfc_send_command(device_t dev, uint8_t command)
-{
- struct fsl_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint8_t fir_op;
-
- // device_printf(dev, "%s(command=%u)\n", __func__, command);
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- if (command == NAND_CMD_PROG_END) {
- fcm->reg_fir |= (FIR_OP_WB << OP_SHIFT(fcm->opnr));
- fcm->opnr++;
- }
- fcm->reg_fcr |= command << CMD_SHIFT(fcm->cmdnr);
- fir_op = (fcm->cmdnr == 0) ? FIR_OP_CW0 : FIR_OP_CM(fcm->cmdnr);
- fcm->cmdnr++;
-
- fcm->reg_fir |= (fir_op << OP_SHIFT(fcm->opnr));
- fcm->opnr++;
-
- switch (command) {
- case NAND_CMD_READ_ID:
- fcm->data_fir = FIR_OP_RBW;
- fcm->addr_type = ADDR_ID;
- break;
- case NAND_CMD_SMALLOOB:
- fcm->pg_ofs += 256;
- /*FALLTHROUGH*/
- case NAND_CMD_SMALLB:
- fcm->pg_ofs += 256;
- /*FALLTHROUGH*/
- case NAND_CMD_READ: /* NAND_CMD_SMALLA */
- fcm->data_fir = FIR_OP_RBW;
- fcm->addr_type = ADDR_ROWCOL;
- break;
- case NAND_CMD_STATUS:
- fcm->data_fir = FIR_OP_RS;
- fcm->status = 1;
- break;
- case NAND_CMD_ERASE:
- fcm->addr_type = ADDR_ROW;
- break;
- case NAND_CMD_PROG:
- fcm->addr_type = ADDR_ROWCOL;
- break;
- }
- return (0);
-}
-
-static int
-fsl_nfc_send_address(device_t dev, uint8_t addr)
-{
- struct fsl_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint32_t addr_bits;
-
- // device_printf(dev, "%s(address=%u)\n", __func__, addr);
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- KASSERT(fcm->addr_type != ADDR_NONE,
- ("controller doesn't expect address cycle"));
-
- addr_bits = addr;
-
- if (fcm->addr_type == ADDR_ID) {
- fcm->reg_fir |= (FIR_OP_UA << OP_SHIFT(fcm->opnr));
- fcm->opnr++;
-
- fcm->reg_fbcr = 5;
- fcm->reg_fbar = 0;
- fcm->reg_fpar = 0;
- fcm->reg_mdr = addr_bits;
- fcm->buf_ofs = 0;
- fcm->read_ptr = 0;
- return (0);
- }
-
- if (fcm->addr_type == ADDR_ROW) {
- addr_bits <<= fcm->addr_bytes * 8;
- fcm->row_addr |= addr_bits;
- fcm->addr_bytes++;
- if (fcm->addr_bytes < sc->row_cycles)
- return (0);
- } else {
- if (fcm->addr_bytes < sc->col_cycles) {
- addr_bits <<= fcm->addr_bytes * 8;
- fcm->column_addr |= addr_bits;
- } else {
- addr_bits <<= (fcm->addr_bytes - sc->col_cycles) * 8;
- fcm->row_addr |= addr_bits;
- }
- fcm->addr_bytes++;
- if (fcm->addr_bytes < (sc->row_cycles + sc->col_cycles))
- return (0);
- }
-
- return (fsl_nand_build_address(dev, fcm->row_addr, fcm->column_addr));
-}
-
-static int
-fsl_nand_build_address(device_t dev, uint32_t row, uint32_t column)
-{
- struct fsl_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint32_t byte_count = 0;
- uint32_t block_address = 0;
- uint32_t page_address = 0;
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- fcm->read_ptr = 0;
- fcm->buf_ofs = 0;
-
- if (fcm->addr_type == ADDR_ROWCOL) {
- fcm->reg_fir |= (FIR_OP_CA << OP_SHIFT(fcm->opnr));
- fcm->opnr++;
-
- column += fcm->pg_ofs;
- fcm->pg_ofs = 0;
-
- page_address |= column;
-
- if (column != 0) {
- byte_count = sc->pgsz - column;
- fcm->read_ptr = column;
- }
- }
-
- fcm->reg_fir |= (FIR_OP_PA << OP_SHIFT(fcm->opnr));
- fcm->opnr++;
-
- if (sc->pgsz == FSL_LARGE_PAGE_SIZE) {
- block_address = row >> 6;
- page_address |= ((row << FPAR_LP_PI_SHIFT) & FPAR_LP_PI);
- fcm->buf_ofs = (row & 1) * 4096;
- } else {
- block_address = row >> 5;
- page_address |= ((row << FPAR_SP_PI_SHIFT) & FPAR_SP_PI);
- fcm->buf_ofs = (row & 7) * 1024;
- }
-
- fcm->reg_fbcr = byte_count;
- fcm->reg_fbar = block_address;
- fcm->reg_fpar = page_address;
- return (0);
-}
-
-static int
-fsl_nfc_start_command(device_t dev)
-{
- struct fsl_nand_softc *sc;
- struct fsl_nfc_fcm *fcm;
- uint32_t fmr, ltesr_v;
- int error, timeout;
-
- // device_printf(dev, "%s()\n", __func__);
-
- sc = device_get_softc(dev);
- fcm = &sc->fcm;
-
- fmr = fcm->reg_fmr | FMR_OP;
-
- if (fcm->data_fir)
- fcm->reg_fir |= (fcm->data_fir << OP_SHIFT(fcm->opnr));
-
- LBC_WRITE(FIR, fcm->reg_fir);
- LBC_WRITE(FCR, fcm->reg_fcr);
-
- LBC_WRITE(FMR, fmr);
-
- LBC_WRITE(FBCR, fcm->reg_fbcr);
- LBC_WRITE(FBAR, fcm->reg_fbar);
- LBC_WRITE(FPAR, fcm->reg_fpar);
-
- if (fcm->addr_type == ADDR_ID)
- LBC_WRITE(MDR, fcm->reg_mdr);
-
- nand_debug(NDBG_DRV, "BEFORE:\nFMR=%#x, FIR=%#x, FCR=%#x", fmr,
- fcm->reg_fir, fcm->reg_fcr);
- nand_debug(NDBG_DRV, "MDR=%#x, FBAR=%#x, FPAR=%#x, FBCR=%#x",
- LBC_READ(MDR), fcm->reg_fbar, fcm->reg_fpar, fcm->reg_fbcr);
-
- LBC_WRITE(LSOR, sc->dinfo->di_bank);
-
- timeout = (cold) ? FSL_FCM_WAIT_TIMEOUT : ~0;
- error = 0;
- ltesr_v = LBC_READ(LTESR);
- while (!error && (ltesr_v & LTESR_CC) == 0) {
- if (cold) {
- DELAY(1000);
- timeout--;
- if (timeout < 0)
- error = EWOULDBLOCK;
- } else
- error = tsleep(device_get_parent(sc->dev), PRIBIO,
- "nfcfsl", hz);
- ltesr_v = LBC_READ(LTESR);
- }
- if (error)
- nand_debug(NDBG_DRV, "Command complete wait timeout\n");
-
- nand_debug(NDBG_DRV, "AFTER:\nLTESR=%#x, LTEDR=%#x, LTEIR=%#x,"
- " LTEATR=%#x, LTEAR=%#x, LTECCR=%#x", ltesr_v,
- LBC_READ(LTEDR), LBC_READ(LTEIR), LBC_READ(LTEATR),
- LBC_READ(LTEAR), LBC_READ(LTECCR));
-
- bzero(&fcm->fcm_startzero,
- __rangeof(struct fsl_nfc_fcm, fcm_startzero, fcm_endzero));
-
- if (fcm->status)
- sc->fcm.reg_mdr = LBC_READ(MDR);
-
- /* Even if timeout occurred, we should perform steps below */
- LBC_WRITE(LTESR, ltesr_v);
- LBC_WRITE(LTEATR, 0);
-
- return (error);
-}
-
-static uint8_t
-fsl_nfc_read_byte(device_t dev)
-{
- struct fsl_nand_softc *sc = device_get_softc(dev);
- uint32_t offset;
-
- // device_printf(dev, "%s()\n", __func__);
-
- /*
- * LBC controller allows us to read status into a MDR instead of FCM
- * buffer. If last operation requested before read_byte() was STATUS,
- * then return MDR instead of reading a single byte from a buffer.
- */
- if (sc->fcm.status) {
- sc->fcm.status = 0;
- return (sc->fcm.reg_mdr);
- }
-
- KASSERT(sc->fcm.read_ptr < sc->pgsz,
- ("Attempt to read beyond buffer %x %x", sc->fcm.read_ptr,
- sc->pgsz));
-
- offset = sc->fcm.buf_ofs + sc->fcm.read_ptr;
- sc->fcm.read_ptr++;
- return (bus_read_1(sc->res, offset));
-}
-
-static void
-fsl_nfc_read_buf(device_t dev, void *buf, uint32_t len)
-{
- struct fsl_nand_softc *sc = device_get_softc(dev);
- uint32_t offset;
- int bytesleft = 0;
-
- // device_printf(dev, "%s(buf=%p, len=%u)\n", __func__, buf, len);
-
- nand_debug(NDBG_DRV, "REQUEST OF 0x%0x B (BIB=0x%0x, NTR=0x%0x)",
- len, sc->pgsz, sc->fcm.read_ptr);
-
- bytesleft = MIN((unsigned int)len, sc->pgsz - sc->fcm.read_ptr);
-
- offset = sc->fcm.buf_ofs + sc->fcm.read_ptr;
- bus_read_region_1(sc->res, offset, buf, bytesleft);
- sc->fcm.read_ptr += bytesleft;
-}
-
-static void
-fsl_nfc_write_buf(device_t dev, void *buf, uint32_t len)
-{
- struct fsl_nand_softc *sc = device_get_softc(dev);
- uint32_t offset;
- int bytesleft = 0;
-
- // device_printf(dev, "%s(buf=%p, len=%u)\n", __func__, buf, len);
-
- KASSERT(len <= sc->pgsz - sc->fcm.read_ptr,
- ("Attempt to write beyond buffer"));
-
- bytesleft = MIN((unsigned int)len, sc->pgsz - sc->fcm.read_ptr);
-
- nand_debug(NDBG_DRV, "REQUEST TO WRITE 0x%0x (BIB=0x%0x, NTR=0x%0x)",
- bytesleft, sc->pgsz, sc->fcm.read_ptr);
-
- offset = sc->fcm.buf_ofs + sc->fcm.read_ptr;
- bus_write_region_1(sc->res, offset, buf, bytesleft);
- sc->fcm.read_ptr += bytesleft;
-}
-
-static int
-fsl_nand_chip_preprobe(device_t dev, struct nand_id *id)
-{
-
- if (fsl_nfc_send_command(dev, NAND_CMD_RESET) != 0)
- return (ENXIO);
-
- if (fsl_nfc_start_command(dev) != 0)
- return (ENXIO);
-
- DELAY(1000);
-
- if (fsl_nfc_send_command(dev, NAND_CMD_READ_ID))
- return (ENXIO);
-
- if (fsl_nfc_send_address(dev, 0))
- return (ENXIO);
-
- if (fsl_nfc_start_command(dev) != 0)
- return (ENXIO);
-
- DELAY(25);
-
- id->man_id = fsl_nfc_read_byte(dev);
- id->dev_id = fsl_nfc_read_byte(dev);
-
- nand_debug(NDBG_DRV, "manufacturer id: %x chip id: %x",
- id->man_id, id->dev_id);
-
- return (0);
-}
-
-#ifdef NAND_DEBUG_TIMING
-
-static SYSCTL_NODE(_debug, OID_AUTO, fcm, CTLFLAG_RD, 0, "FCM timing");
-
-static u_int csct = 1; /* 22: Chip select to command time (trlx). */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, csct, CTLFLAG_RW, &csct, 1,
- "Chip select to command time: determines how far in advance -LCSn is "
- "asserted prior to any bus activity during a NAND Flash access handled "
- "by the FCM. This helps meet chip-select setup times for slow memories.");
-
-static u_int cst = 1; /* 23: Command setup time (trlx). */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, cst, CTLFLAG_RW, &cst, 1,
- "Command setup time: determines the delay of -LFWE assertion relative to "
- "the command, address, or data change when the external memory access "
- "is handled by the FCM.");
-
-static u_int cht = 1; /* 24: Command hold time (trlx). */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, cht, CTLFLAG_RW, &cht, 1,
- "Command hold time: determines the -LFWE negation prior to the command, "
- "address, or data change when the external memory access is handled by "
- "the FCM.");
-
-static u_int scy = 2; /* 25-27: Cycle length in bus clocks */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, scy, CTLFLAG_RW, &scy, 2,
- "Cycle length in bus clocks: see RM");
-
-static u_int rst = 1; /* 28: Read setup time (trlx). */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, rst, CTLFLAG_RW, &rst, 1,
- "Read setup time: determines the delay of -LFRE assertion relative to "
- "sampling of read data when the external memory access is handled by "
- "the FCM.");
-
-static u_int trlx = 1; /* 29: Timing relaxed. */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, trlx, CTLFLAG_RW, &trlx, 1,
- "Timing relaxed: modifies the settings of timing parameters for slow "
- "memories. See RM");
-
-static u_int ehtr = 1; /* 30: Extended hold time on read accesses. */
-SYSCTL_UINT(_debug_fcm, OID_AUTO, ehtr, CTLFLAG_RW, &ehtr, 1,
- "Extended hold time on read accesses: indicates with TRLX how many "
- "cycles are inserted between a read access from the current bank and "
- "the next access.");
-
-static u_int
-fsl_nand_get_timing(void)
-{
- u_int timing;
-
- timing = ((csct & 1) << 9) | ((cst & 1) << 8) | ((cht & 1) << 7) |
- ((scy & 7) << 4) | ((rst & 1) << 3) | ((trlx & 1) << 2) |
- ((ehtr & 1) << 1);
-
- printf("nfc_fsl: timing = %u\n", timing);
- return (timing);
-}
-
-static int
-fsl_sysctl_program(SYSCTL_HANDLER_ARGS)
-{
- struct fsl_nand_softc *sc;
- int error, i;
- device_t dev;
- uint32_t or_v;
-
- error = sysctl_wire_old_buffer(req, sizeof(int));
- if (error == 0) {
- i = 0;
- error = sysctl_handle_int(oidp, &i, 0, req);
- }
- if (error != 0 || req->newptr == NULL)
- return (error);
-
- for (i = 0; i < 8; i++) {
- dev = fcm_devs[i];
- if (dev == NULL)
- continue;
- sc = device_get_softc(dev);
-
- /* Reprogram OR(x) */
- or_v = lbc_read_reg(dev, LBC85XX_OR(sc->dinfo->di_bank));
- or_v &= 0xfffffc00;
- or_v |= fsl_nand_get_timing();
- lbc_write_reg(dev, LBC85XX_OR(sc->dinfo->di_bank), or_v);
- }
- return (0);
-}
-
-SYSCTL_PROC(_debug_fcm, OID_AUTO, program, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
- fsl_sysctl_program, "I", "write to program FCM with current values");
-
-#endif /* NAND_DEBUG_TIMING */
diff --git a/sys/dev/nand/nfc_fsl.h b/sys/dev/nand/nfc_fsl.h
deleted file mode 100644
index 5410da558171..000000000000
--- a/sys/dev/nand/nfc_fsl.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2012 Juniper Networks, Inc.
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _NAND_NFC_FSL_H_
-#define _NAND_NFC_FSL_H_
-
-/* LBC BR/OR Registers layout definitions */
-#define BR_V 0x00000001
-#define BR_V_SHIFT 0
-#define BR_MSEL 0x000000E0
-#define BR_MSEL_SHIFT 5
-#define BR_DECC_CHECK_MODE 0x00000600
-#define BR_DECC_CHECK_GEN 0x00000400
-
-#define OR_FCM_PAGESIZE 0x00000400
-
-/* Options definitions */
-#define NAND_OPT_ECC_MODE_HW 1
-#define NAND_OPT_ECC_MODE_SOFT (1 << 1)
-
-/* FMR - Flash Mode Register */
-#define FMR_CWTO 0xF000
-#define FMR_CWTO_SHIFT 12
-#define FMR_BOOT 0x0800
-#define FMR_ECCM 0x0100
-#define FMR_AL 0x0030
-#define FMR_AL_SHIFT 4
-#define FMR_OP 0x0003
-#define FMR_OP_SHIFT 0
-
-#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
-#define FIR_OP_CA 0x1 /* Issue current column address */
-#define FIR_OP_PA 0x2 /* Issue current block+page address */
-#define FIR_OP_UA 0x3 /* Issue user defined address */
-#define FIR_OP_CM(x) (4 + (x)) /* Issue command from FCR[CMD(x)] */
-#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
-#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
-#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
-#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
-#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
-#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
-#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
-#define FIR_OP_RSW 0xF /* Wait then read 1 or 2 bytes */
-
-/* LTESR - Transfer Error Status Register */
-#define LTESR_BM 0x80000000
-#define LTESR_FCT 0x40000000
-#define LTESR_PAR 0x20000000
-#define LTESR_WP 0x04000000
-#define LTESR_ATMW 0x00800000
-#define LTESR_ATMR 0x00400000
-#define LTESR_CS 0x00080000
-#define LTESR_CC 0x00000001
-
-#define LTESR_NAND_MASK (LTESR_FCT | LTESR_CC | LTESR_CS)
-
-/* FPAR - Flash Page Address Register */
-#define FPAR_SP_PI 0x00007C00
-#define FPAR_SP_PI_SHIFT 10
-#define FPAR_SP_MS 0x00000200
-#define FPAR_SP_CI 0x000001FF
-#define FPAR_SP_CI_SHIFT 0
-#define FPAR_LP_PI 0x0003F000
-#define FPAR_LP_PI_SHIFT 12
-#define FPAR_LP_MS 0x00000800
-#define FPAR_LP_CI 0x000007FF
-#define FPAR_LP_CI_SHIFT 0
-
-#define FSL_FCM_WAIT_TIMEOUT 10
-
-#endif /* _NAND_NFC_FSL_H_ */
diff --git a/sys/dev/nand/nfc_if.m b/sys/dev/nand/nfc_if.m
deleted file mode 100644
index a4e1099220ac..000000000000
--- a/sys/dev/nand/nfc_if.m
+++ /dev/null
@@ -1,165 +0,0 @@
-#-
-# Copyright (C) 2009-2012 Semihalf
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-
-# NAND controller interface description
-#
-
-#include <sys/bus.h>
-#include <dev/nand/nand.h>
-
-INTERFACE nfc;
-
-CODE {
- static int nfc_default_method(device_t dev)
- {
- return (0);
- }
-
- static int nfc_softecc_get(device_t dev, void *buf, int pagesize,
- void *ecc, int *needwrite)
- {
- *needwrite = 1;
- return (nand_softecc_get(dev, buf, pagesize, ecc));
- }
-
- static int nfc_softecc_correct(device_t dev, void *buf, int pagesize,
- void *readecc, void *calcecc)
- {
- return (nand_softecc_correct(dev, buf, pagesize, readecc,
- calcecc));
- }
-};
-
-# Send command to a NAND chip
-#
-# Return values:
-# 0: Success
-#
-METHOD int send_command {
- device_t dev;
- uint8_t command;
-};
-
-# Send address to a NAND chip
-#
-# Return values:
-# 0: Success
-#
-METHOD int send_address {
- device_t dev;
- uint8_t address;
-};
-
-# Read byte
-#
-# Return values:
-# byte read
-#
-METHOD uint8_t read_byte {
- device_t dev;
-};
-
-# Write byte
-#
-METHOD void write_byte {
- device_t dev;
- uint8_t byte;
-};
-
-# Read word
-#
-# Return values:
-# word read
-#
-METHOD uint16_t read_word {
- device_t dev;
-};
-
-# Write word
-#
-METHOD void write_word {
- device_t dev;
- uint16_t word;
-};
-
-# Read buf
-#
-METHOD void read_buf {
- device_t dev;
- void *buf;
- uint32_t len;
-};
-
-# Write buf
-#
-METHOD void write_buf {
- device_t dev;
- void *buf;
- uint32_t len;
-};
-
-# Select CS
-#
-METHOD int select_cs {
- device_t dev;
- uint8_t cs;
-};
-
-# Read ready/busy signal
-#
-METHOD int read_rnb {
- device_t dev;
-};
-
-# Start command
-#
-# Return values:
-# 0: Success
-#
-METHOD int start_command {
- device_t dev;
-} DEFAULT nfc_default_method;
-
-# Generate ECC or get it from H/W
-#
-METHOD int get_ecc {
- device_t dev;
- void *buf;
- int pagesize;
- void *ecc;
- int *needwrite;
-} DEFAULT nfc_softecc_get;
-
-# Correct ECC
-#
-METHOD int correct_ecc {
- device_t dev;
- void *buf;
- int pagesize;
- void *readecc;
- void *calcecc;
-} DEFAULT nfc_softecc_correct;
diff --git a/sys/dev/nand/nfc_mv.c b/sys/dev/nand/nfc_mv.c
deleted file mode 100644
index 0d78d34d9912..000000000000
--- a/sys/dev/nand/nfc_mv.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* Integrated NAND controller driver */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/time.h>
-
-#include <machine/bus.h>
-#include <machine/fdt.h>
-#include <arm/mv/mvvar.h>
-#include <arm/mv/mvwin.h>
-
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-#include "nfc_if.h"
-
-#define MV_NAND_DATA (0x00)
-#define MV_NAND_COMMAND (0x01)
-#define MV_NAND_ADDRESS (0x02)
-
-struct mv_nand_softc {
- struct nand_softc nand_dev;
- bus_space_handle_t sc_handle;
- bus_space_tag_t sc_tag;
- struct resource *res;
- int rid;
-};
-
-static int mv_nand_attach(device_t);
-static int mv_nand_probe(device_t);
-static int mv_nand_send_command(device_t, uint8_t);
-static int mv_nand_send_address(device_t, uint8_t);
-static uint8_t mv_nand_read_byte(device_t);
-static void mv_nand_read_buf(device_t, void *, uint32_t);
-static void mv_nand_write_buf(device_t, void *, uint32_t);
-static int mv_nand_select_cs(device_t, uint8_t);
-static int mv_nand_read_rnb(device_t);
-
-static device_method_t mv_nand_methods[] = {
- DEVMETHOD(device_probe, mv_nand_probe),
- DEVMETHOD(device_attach, mv_nand_attach),
-
- DEVMETHOD(nfc_send_command, mv_nand_send_command),
- DEVMETHOD(nfc_send_address, mv_nand_send_address),
- DEVMETHOD(nfc_read_byte, mv_nand_read_byte),
- DEVMETHOD(nfc_read_buf, mv_nand_read_buf),
- DEVMETHOD(nfc_write_buf, mv_nand_write_buf),
- DEVMETHOD(nfc_select_cs, mv_nand_select_cs),
- DEVMETHOD(nfc_read_rnb, mv_nand_read_rnb),
-
- { 0, 0 },
-};
-
-static driver_t mv_nand_driver = {
- "nand",
- mv_nand_methods,
- sizeof(struct mv_nand_softc),
-};
-
-static devclass_t mv_nand_devclass;
-DRIVER_MODULE(mv_nand, localbus, mv_nand_driver, mv_nand_devclass, 0, 0);
-
-static int
-mv_nand_probe(device_t dev)
-{
-
- if (!ofw_bus_is_compatible(dev, "mrvl,nfc"))
- return (ENXIO);
-
- device_set_desc(dev, "Marvell NAND controller");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-mv_nand_attach(device_t dev)
-{
- struct mv_nand_softc *sc;
- int err;
-
- sc = device_get_softc(dev);
- sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
- RF_ACTIVE);
- if (sc->res == NULL) {
- device_printf(dev, "could not allocate resources!\n");
- return (ENXIO);
- }
-
- sc->sc_tag = rman_get_bustag(sc->res);
- sc->sc_handle = rman_get_bushandle(sc->res);
-
- nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL);
-
- err = nandbus_create(dev);
-
- return (err);
-}
-
-static int
-mv_nand_send_command(device_t dev, uint8_t command)
-{
- struct mv_nand_softc *sc;
-
- nand_debug(NDBG_DRV,"mv_nand: send command %x", command);
-
- sc = device_get_softc(dev);
- bus_space_write_1(sc->sc_tag, sc->sc_handle, MV_NAND_COMMAND, command);
- return (0);
-}
-
-static int
-mv_nand_send_address(device_t dev, uint8_t addr)
-{
- struct mv_nand_softc *sc;
-
- nand_debug(NDBG_DRV,"mv_nand: send address %x", addr);
-
- sc = device_get_softc(dev);
- bus_space_write_1(sc->sc_tag, sc->sc_handle, MV_NAND_ADDRESS, addr);
- return (0);
-}
-
-static uint8_t
-mv_nand_read_byte(device_t dev)
-{
- struct mv_nand_softc *sc;
- uint8_t data;
-
- sc = device_get_softc(dev);
- data = bus_space_read_1(sc->sc_tag, sc->sc_handle, MV_NAND_DATA);
-
- nand_debug(NDBG_DRV,"mv_nand: read %x", data);
-
- return (data);
-}
-
-static void
-mv_nand_read_buf(device_t dev, void* buf, uint32_t len)
-{
- struct mv_nand_softc *sc;
- int i;
- uint8_t *b = (uint8_t*)buf;
-
- sc = device_get_softc(dev);
-
- for (i = 0; i < len; i++) {
- b[i] = bus_space_read_1(sc->sc_tag, sc->sc_handle,
- MV_NAND_DATA);
-#ifdef NAND_DEBUG
- if (!(i % 16))
- printf("%s", i == 0 ? "mv_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
-#endif
- }
-}
-
-static void
-mv_nand_write_buf(device_t dev, void* buf, uint32_t len)
-{
- struct mv_nand_softc *sc;
- int i;
- uint8_t *b = (uint8_t*)buf;
-
- sc = device_get_softc(dev);
-
- for (i = 0; i < len; i++) {
-#ifdef NAND_DEBUG
- if (!(i % 16))
- printf("%s", i == 0 ? "mv_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
-#endif
- bus_space_write_1(sc->sc_tag, sc->sc_handle, MV_NAND_DATA,
- b[i]);
- }
-}
-
-static int
-mv_nand_select_cs(device_t dev, uint8_t cs)
-{
-
- if (cs > 0)
- return (ENODEV);
-
- return (0);
-}
-
-static int
-mv_nand_read_rnb(device_t dev)
-{
-
- /* no-op */
- return (0); /* ready */
-}
diff --git a/sys/dev/nand/nfc_rb.c b/sys/dev/nand/nfc_rb.c
deleted file mode 100644
index 1102b3abb9c4..000000000000
--- a/sys/dev/nand/nfc_rb.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*-
- * Copyright (C) 2015 Justin Hibbits
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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.
- */
-
-/* RouterBoard 600/800 NAND controller driver. */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/malloc.h>
-#include <sys/rman.h>
-#include <sys/slicer.h>
-
-#include <geom/geom_disk.h>
-
-#include <machine/bus.h>
-
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <dev/nand/nand.h>
-#include <dev/nand/nandbus.h>
-
-#include <powerpc/mpc85xx/mpc85xx.h>
-
-#include "nfc_if.h"
-#include "gpio_if.h"
-
-#define RB_NAND_DATA (0x00)
-
-struct rb_nand_softc {
- struct nand_softc nand_dev;
- struct resource *sc_mem;
- int rid;
- device_t sc_gpio;
- uint32_t sc_rdy_pin;
- uint32_t sc_nce_pin;
- uint32_t sc_cle_pin;
- uint32_t sc_ale_pin;
-};
-
-static int rb_nand_attach(device_t);
-static int rb_nand_probe(device_t);
-static int rb_nand_send_command(device_t, uint8_t);
-static int rb_nand_send_address(device_t, uint8_t);
-static uint8_t rb_nand_read_byte(device_t);
-static void rb_nand_read_buf(device_t, void *, uint32_t);
-static void rb_nand_write_buf(device_t, void *, uint32_t);
-static int rb_nand_select_cs(device_t, uint8_t);
-static int rb_nand_read_rnb(device_t);
-
-static device_method_t rb_nand_methods[] = {
- DEVMETHOD(device_probe, rb_nand_probe),
- DEVMETHOD(device_attach, rb_nand_attach),
-
- DEVMETHOD(nfc_send_command, rb_nand_send_command),
- DEVMETHOD(nfc_send_address, rb_nand_send_address),
- DEVMETHOD(nfc_read_byte, rb_nand_read_byte),
- DEVMETHOD(nfc_read_buf, rb_nand_read_buf),
- DEVMETHOD(nfc_write_buf, rb_nand_write_buf),
- DEVMETHOD(nfc_select_cs, rb_nand_select_cs),
- DEVMETHOD(nfc_read_rnb, rb_nand_read_rnb),
-
- { 0, 0 },
-};
-
-static driver_t rb_nand_driver = {
- "nand",
- rb_nand_methods,
- sizeof(struct rb_nand_softc),
-};
-
-static devclass_t rb_nand_devclass;
-DRIVER_MODULE(rb_nand, ofwbus, rb_nand_driver, rb_nand_devclass, 0, 0);
-
-#if 0
-static const struct nand_ecc_data rb_ecc = {
- .eccsize = 6,
- .eccmode = NAND_ECC_SOFT,
- .eccbytes = 6,
- .eccpositions = { 8, 9, 10, 13, 14, 15 },
-};
-#endif
-
-/* Slicer operates on the NAND controller, so we have to find the chip. */
-static int
-rb_nand_slicer(device_t dev, const char *provider __unused,
- struct flash_slice *slices, int *nslices)
-{
- struct nand_chip *chip;
- device_t *children;
- int n;
-
- if (device_get_children(dev, &children, &n) != 0) {
- panic("Slicer called on controller with no child!");
- }
- dev = children[0];
- free(children, M_TEMP);
-
- if (device_get_children(dev, &children, &n) != 0) {
- panic("Slicer called on controller with nandbus but no child!");
- }
- dev = children[0];
- free(children, M_TEMP);
-
- chip = device_get_softc(dev);
- *nslices = 2;
- slices[0].base = 0;
- slices[0].size = 4 * 1024 * 1024;
- slices[0].label = "boot";
-
- slices[1].base = 4 * 1024 * 1024;
- slices[1].size = chip->ndisk->d_mediasize - slices[0].size;
- slices[1].label = "rootfs";
-
- return (0);
-}
-
-static int
-rb_nand_probe(device_t dev)
-{
- const char *device_type;
-
- device_type = ofw_bus_get_type(dev);
-
- if (!device_type || strcmp(device_type, "rb,nand"))
- return (ENXIO);
-
- device_set_desc(dev, "RouterBoard 333/600/800 NAND controller");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-rb_nand_attach(device_t dev)
-{
- struct rb_nand_softc *sc;
- phandle_t node;
- uint32_t ale[2],cle[2],nce[2],rdy[2];
- u_long size,start;
- int err;
-
- sc = device_get_softc(dev);
- node = ofw_bus_get_node(dev);
-
- if (OF_getprop(node, "ale", ale, sizeof(ale)) <= 0) {
- return (ENXIO);
- }
- if (OF_getprop(node, "cle", cle, sizeof(cle)) <= 0) {
- return (ENXIO);
- }
- if (OF_getprop(node, "nce", nce, sizeof(nce)) <= 0) {
- return (ENXIO);
- }
- if (OF_getprop(node, "rdy", rdy, sizeof(rdy)) <= 0) {
- return (ENXIO);
- }
-
- if (ale[0] != cle[0] || ale[0] != nce[0] || ale[0] != rdy[0]) {
- device_printf(dev, "GPIO handles for signals must match.\n");
- return (ENXIO);
- }
- sc->sc_ale_pin = ale[1];
- sc->sc_cle_pin = cle[1];
- sc->sc_nce_pin = nce[1];
- sc->sc_rdy_pin = rdy[1];
-
- sc->sc_gpio = OF_device_from_xref(ale[0]);
- if (sc->sc_gpio == NULL) {
- device_printf(dev, "No GPIO resource found!\n");
- return (ENXIO);
- }
-
- sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
- RF_ACTIVE);
- if (sc->sc_mem == NULL) {
- device_printf(dev, "could not allocate resources!\n");
- return (ENXIO);
- }
-
- start = rman_get_start(sc->sc_mem);
- size = rman_get_size(sc->sc_mem);
- if (law_enable(OCP85XX_TGTIF_LBC, start, size) != 0) {
- bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->sc_mem);
- device_printf(dev, "could not allocate local address window.\n");
- return (ENXIO);
- }
-
- flash_register_slicer(rb_nand_slicer, FLASH_SLICES_TYPE_NAND, TRUE);
-
- nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL);
-
- err = nandbus_create(dev);
-
- return (err);
-}
-
-static int
-rb_nand_send_command(device_t dev, uint8_t command)
-{
- struct rb_nand_softc *sc;
-
- nand_debug(NDBG_DRV,"rb_nand: send command %x", command);
-
- sc = device_get_softc(dev);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 1);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 0);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_nce_pin, 0);
- bus_write_1(sc->sc_mem, RB_NAND_DATA, command);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 0);
- return (0);
-}
-
-static int
-rb_nand_send_address(device_t dev, uint8_t addr)
-{
- struct rb_nand_softc *sc;
-
- nand_debug(NDBG_DRV,"rb_nand: send address %x", addr);
-
- sc = device_get_softc(dev);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 0);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 1);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_nce_pin, 0);
- bus_write_1(sc->sc_mem, RB_NAND_DATA, addr);
- GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 0);
- return (0);
-}
-
-static uint8_t
-rb_nand_read_byte(device_t dev)
-{
- struct rb_nand_softc *sc;
- uint8_t data;
-
- sc = device_get_softc(dev);
- data = bus_read_1(sc->sc_mem, RB_NAND_DATA);
-
- nand_debug(NDBG_DRV,"rb_nand: read %x", data);
-
- return (data);
-}
-
-static void
-rb_nand_read_buf(device_t dev, void* buf, uint32_t len)
-{
- struct rb_nand_softc *sc;
-
- sc = device_get_softc(dev);
-
- bus_read_region_1(sc->sc_mem, RB_NAND_DATA, buf, len);
-}
-
-static void
-rb_nand_write_buf(device_t dev, void* buf, uint32_t len)
-{
- struct rb_nand_softc *sc;
- int i;
- uint8_t *b = (uint8_t*)buf;
-
- sc = device_get_softc(dev);
-
- for (i = 0; i < len; i++) {
-#ifdef NAND_DEBUG
- if (!(i % 16))
- printf("%s", i == 0 ? "rb_nand:\n" : "\n");
- printf(" %x", b[i]);
- if (i == len - 1)
- printf("\n");
-#endif
- bus_write_1(sc->sc_mem, RB_NAND_DATA, b[i]);
- }
-}
-
-static int
-rb_nand_select_cs(device_t dev, uint8_t cs)
-{
-
- if (cs > 0)
- return (ENODEV);
-
- return (0);
-}
-
-static int
-rb_nand_read_rnb(device_t dev)
-{
- struct rb_nand_softc *sc;
- uint32_t rdy_bit;
-
- sc = device_get_softc(dev);
- GPIO_PIN_GET(sc->sc_gpio, sc->sc_rdy_pin, &rdy_bit);
-
- return (rdy_bit); /* ready */
-}
diff --git a/sys/dev/ow/owc_gpiobus.c b/sys/dev/ow/owc_gpiobus.c
index f03d01432b03..24a18789bea8 100644
--- a/sys/dev/ow/owc_gpiobus.c
+++ b/sys/dev/ow/owc_gpiobus.c
@@ -416,5 +416,7 @@ static driver_t owc_gpiobus_driver = {
sizeof(struct owc_gpiobus_softc),
};
-DRIVER_MODULE(owc_gpiobus_fdt, gpiobus, owc_gpiobus_driver, owc_gpiobus_devclass, 0, 0);
-MODULE_DEPEND(owc_gpiobus_fdt, ow, 1, 1, 1);
+DRIVER_MODULE(owc_gpiobus, gpiobus, owc_gpiobus_driver, owc_gpiobus_devclass, 0, 0);
+MODULE_DEPEND(owc_gpiobus, ow, 1, 1, 1);
+MODULE_DEPEND(owc_gpiobus, gpiobus, 1, 1, 1);
+MODULE_VERSION(owc_gpiobus, 1);
diff --git a/sys/dev/usb/usb_hub_acpi.c b/sys/dev/usb/usb_hub_acpi.c
index 5dd9f06ebaa4..b536a3d282e9 100644
--- a/sys/dev/usb/usb_hub_acpi.c
+++ b/sys/dev/usb/usb_hub_acpi.c
@@ -243,13 +243,14 @@ acpi_uhub_parse_pld(device_t dev, unsigned int port, ACPI_HANDLE ah)
}
ACPI_STATUS
-acpi_uhub_find_rh(device_t dev, ACPI_HANDLE * ah){
+acpi_uhub_find_rh(device_t dev, ACPI_HANDLE * ah)
+{
device_t grand;
ACPI_HANDLE gah;
+ *ah = NULL;
grand = device_get_parent(device_get_parent(dev));
if ((gah = acpi_get_handle(grand)) == NULL) {
- *ah = NULL;
return AE_ERROR;
}
return AcpiWalkNamespace(ACPI_TYPE_DEVICE, gah, 1,
@@ -257,7 +258,8 @@ acpi_uhub_find_rh(device_t dev, ACPI_HANDLE * ah){
}
ACPI_STATUS
-acpi_usb_hub_port_probe_cb(ACPI_HANDLE ah, UINT32 lv, void *ctx, void **rv){
+acpi_usb_hub_port_probe_cb(ACPI_HANDLE ah, UINT32 lv, void *ctx, void **rv)
+{
ACPI_DEVICE_INFO *devinfo;
device_t dev = ctx;
struct acpi_uhub_softc *sc = device_get_softc(dev);
@@ -281,7 +283,8 @@ acpi_usb_hub_port_probe_cb(ACPI_HANDLE ah, UINT32 lv, void *ctx, void **rv){
}
ACPI_STATUS
-acpi_usb_hub_port_probe(device_t dev, ACPI_HANDLE ah){
+acpi_usb_hub_port_probe(device_t dev, ACPI_HANDLE ah)
+{
return AcpiWalkNamespace(ACPI_TYPE_DEVICE,
ah, 1,
acpi_usb_hub_port_probe_cb,
@@ -293,6 +296,9 @@ acpi_uhub_root_probe(device_t dev)
ACPI_HANDLE ah;
ACPI_STATUS status;
+ if(acpi_disabled("usb")) {
+ return ENXIO;
+ }
status = acpi_uhub_find_rh(dev, &ah);
if (ACPI_SUCCESS(status)
&& ah != NULL
@@ -308,7 +314,7 @@ acpi_uhub_probe(device_t dev)
{
ACPI_HANDLE ah = acpi_get_handle(dev);
- if (ah && (uhub_probe(dev) <= 0)) {
+ if (!acpi_disabled("usb") && ah && (uhub_probe(dev) <= 0)) {
/*success prior than non - acpi hub*/
return (BUS_PROBE_DEFAULT + 1);
}
@@ -335,7 +341,6 @@ acpi_uhub_root_attach(device_t dev)
sc->nports = uh->nports;
sc->porthandle = malloc(sizeof(ACPI_HANDLE) * uh->nports,
M_USBDEV, M_WAITOK | M_ZERO);
- acpi_uhub_find_rh(dev, &devhandle);
acpi_usb_hub_port_probe(dev, devhandle);
return 0;
diff --git a/sys/dev/virtio/scsi/virtio_scsi.c b/sys/dev/virtio/scsi/virtio_scsi.c
index ec98178d5697..6f2dfbcac5a4 100644
--- a/sys/dev/virtio/scsi/virtio_scsi.c
+++ b/sys/dev/virtio/scsi/virtio_scsi.c
@@ -81,6 +81,7 @@ static void vtscsi_read_config(struct vtscsi_softc *,
struct virtio_scsi_config *);
static int vtscsi_maximum_segments(struct vtscsi_softc *, int);
static int vtscsi_alloc_virtqueues(struct vtscsi_softc *);
+static void vtscsi_check_sizes(struct vtscsi_softc *);
static void vtscsi_write_device_config(struct vtscsi_softc *);
static int vtscsi_reinit(struct vtscsi_softc *);
@@ -311,6 +312,8 @@ vtscsi_attach(device_t dev)
goto fail;
}
+ vtscsi_check_sizes(sc);
+
error = vtscsi_init_event_vq(sc);
if (error) {
device_printf(dev, "cannot populate the eventvq\n");
@@ -478,6 +481,26 @@ vtscsi_alloc_virtqueues(struct vtscsi_softc *sc)
}
static void
+vtscsi_check_sizes(struct vtscsi_softc *sc)
+{
+ int rqsize;
+
+ if ((sc->vtscsi_flags & VTSCSI_FLAG_INDIRECT) == 0) {
+ /*
+ * Ensure the assertions in virtqueue_enqueue(),
+ * even if the hypervisor reports a bad seg_max.
+ */
+ rqsize = virtqueue_size(sc->vtscsi_request_vq);
+ if (sc->vtscsi_max_nsegs > rqsize) {
+ device_printf(sc->vtscsi_dev,
+ "clamping seg_max (%d %d)\n", sc->vtscsi_max_nsegs,
+ rqsize);
+ sc->vtscsi_max_nsegs = rqsize;
+ }
+ }
+}
+
+static void
vtscsi_write_device_config(struct vtscsi_softc *sc)
{
diff --git a/sys/fs/cuse/cuse.c b/sys/fs/cuse/cuse.c
index 578bf3eda74f..765fe308af7b 100644
--- a/sys/fs/cuse/cuse.c
+++ b/sys/fs/cuse/cuse.c
@@ -671,8 +671,6 @@ cuse_server_unref(struct cuse_server *pcs)
TAILQ_REMOVE(&cuse_server_head, pcs, entry);
- cuse_free_unit_by_id_locked(pcs, -1);
-
while ((pcsd = TAILQ_FIRST(&pcs->hdev)) != NULL) {
TAILQ_REMOVE(&pcs->hdev, pcsd, entry);
cuse_unlock();
@@ -680,6 +678,8 @@ cuse_server_unref(struct cuse_server *pcs)
cuse_lock();
}
+ cuse_free_unit_by_id_locked(pcs, -1);
+
while ((mem = TAILQ_FIRST(&pcs->hmem)) != NULL) {
TAILQ_REMOVE(&pcs->hmem, mem, entry);
cuse_unlock();
@@ -699,12 +699,38 @@ cuse_server_unref(struct cuse_server *pcs)
free(pcs, M_CUSE);
}
+static int
+cuse_server_do_close(struct cuse_server *pcs)
+{
+ int retval;
+
+ cuse_lock();
+ cuse_server_is_closing(pcs);
+ /* final client wakeup, if any */
+ cuse_server_wakeup_all_client_locked(pcs);
+
+ knlist_clear(&pcs->selinfo.si_note, 1);
+
+ retval = pcs->refs;
+ cuse_unlock();
+
+ return (retval);
+}
+
static void
cuse_server_free(void *arg)
{
struct cuse_server *pcs = arg;
- /* drop refcount */
+ /*
+ * The final server unref should be done by the server thread
+ * to prevent deadlock in the client cdevpriv destructor,
+ * which cannot destroy itself.
+ */
+ while (cuse_server_do_close(pcs) != 1)
+ pause("W", hz);
+
+ /* drop final refcount */
cuse_server_unref(pcs);
}
@@ -746,21 +772,10 @@ static int
cuse_server_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
struct cuse_server *pcs;
- int error;
- error = cuse_server_get(&pcs);
- if (error != 0)
- goto done;
+ if (cuse_server_get(&pcs) == 0)
+ cuse_server_do_close(pcs);
- cuse_lock();
- cuse_server_is_closing(pcs);
- /* final client wakeup, if any */
- cuse_server_wakeup_all_client_locked(pcs);
-
- knlist_clear(&pcs->selinfo.si_note, 1);
- cuse_unlock();
-
-done:
return (0);
}
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index 96dd05a18323..b4fefbde79a6 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -174,7 +174,7 @@ fifo_open(ap)
if (fip->fi_writers > 0)
wakeup(&fip->fi_writers);
}
- fp->f_seqcount = fpipe->pipe_wgen - fip->fi_writers;
+ fp->f_pipegen = fpipe->pipe_wgen - fip->fi_writers;
}
if (ap->a_mode & FWRITE) {
if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
diff --git a/sys/fs/nandfs/bmap.c b/sys/fs/nandfs/bmap.c
deleted file mode 100644
index 5721cf0157bc..000000000000
--- a/sys/fs/nandfs/bmap.c
+++ /dev/null
@@ -1,625 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/namei.h>
-#include <sys/kernel.h>
-#include <sys/stat.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/signalvar.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/lockf.h>
-#include <sys/ktr.h>
-#include <sys/kdb.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-#include <vm/vnode_pager.h>
-
-#include <machine/_inttypes.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-#include <vm/vnode_pager.h>
-
-#include "nandfs_mount.h"
-#include "nandfs.h"
-#include "nandfs_subr.h"
-#include "bmap.h"
-
-static int bmap_getlbns(struct nandfs_node *, nandfs_lbn_t,
- struct nandfs_indir *, int *);
-
-int
-bmap_lookup(struct nandfs_node *node, nandfs_lbn_t lblk, nandfs_daddr_t *vblk)
-{
- struct nandfs_inode *ip;
- struct nandfs_indir a[NANDFS_NIADDR + 1], *ap;
- nandfs_daddr_t daddr;
- struct buf *bp;
- int error;
- int num, *nump;
-
- DPRINTF(BMAP, ("%s: node %p lblk %jx enter\n", __func__, node, lblk));
- ip = &node->nn_inode;
-
- ap = a;
- nump = &num;
-
- error = bmap_getlbns(node, lblk, ap, nump);
- if (error)
- return (error);
-
- if (num == 0) {
- *vblk = ip->i_db[lblk];
- return (0);
- }
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx trying ip->i_ib[%x]\n", __func__,
- node, lblk, ap->in_off));
- daddr = ip->i_ib[ap->in_off];
- for (bp = NULL, ++ap; --num; ap++) {
- if (daddr == 0) {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx returning with "
- "vblk 0\n", __func__, node, lblk));
- *vblk = 0;
- return (0);
- }
- if (ap->in_lbn == lblk) {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx ap->in_lbn=%jx "
- "returning address of indirect block (%jx)\n",
- __func__, node, lblk, ap->in_lbn, daddr));
- *vblk = daddr;
- return (0);
- }
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx reading block "
- "ap->in_lbn=%jx\n", __func__, node, lblk, ap->in_lbn));
-
- error = nandfs_bread_meta(node, ap->in_lbn, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- daddr = ((nandfs_daddr_t *)bp->b_data)[ap->in_off];
- brelse(bp);
- }
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx returning with %jx\n", __func__,
- node, lblk, daddr));
- *vblk = daddr;
-
- return (0);
-}
-
-int
-bmap_dirty_meta(struct nandfs_node *node, nandfs_lbn_t lblk, int force)
-{
- struct nandfs_indir a[NANDFS_NIADDR+1], *ap;
-#ifdef DEBUG
- nandfs_daddr_t daddr;
-#endif
- struct buf *bp;
- int error;
- int num, *nump;
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx\n", __func__, node, lblk));
-
- ap = a;
- nump = &num;
-
- error = bmap_getlbns(node, lblk, ap, nump);
- if (error)
- return (error);
-
- /*
- * Direct block, nothing to do
- */
- if (num == 0)
- return (0);
-
- DPRINTF(BMAP, ("%s: node %p reading blocks\n", __func__, node));
-
- for (bp = NULL, ++ap; --num; ap++) {
- error = nandfs_bread_meta(node, ap->in_lbn, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
-#ifdef DEBUG
- daddr = ((nandfs_daddr_t *)bp->b_data)[ap->in_off];
- MPASS(daddr != 0 || node->nn_ino == 3);
-#endif
-
- error = nandfs_dirty_buf_meta(bp, force);
- if (error)
- return (error);
- }
-
- return (0);
-}
-
-int
-bmap_insert_block(struct nandfs_node *node, nandfs_lbn_t lblk,
- nandfs_daddr_t vblk)
-{
- struct nandfs_inode *ip;
- struct nandfs_indir a[NANDFS_NIADDR+1], *ap;
- struct buf *bp;
- nandfs_daddr_t daddr;
- int error;
- int num, *nump, i;
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx\n", __func__, node, lblk,
- vblk));
-
- ip = &node->nn_inode;
-
- ap = a;
- nump = &num;
-
- error = bmap_getlbns(node, lblk, ap, nump);
- if (error)
- return (error);
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx got num=%d\n", __func__,
- node, lblk, vblk, num));
-
- if (num == 0) {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx direct block\n", __func__,
- node, lblk));
- ip->i_db[lblk] = vblk;
- return (0);
- }
-
- DPRINTF(BMAP, ("%s: node %p lblk=%jx indirect block level %d\n",
- __func__, node, lblk, ap->in_off));
-
- if (num == 1) {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx indirect block: inserting "
- "%jx as vblk for indirect block %d\n", __func__, node,
- lblk, vblk, ap->in_off));
- ip->i_ib[ap->in_off] = vblk;
- return (0);
- }
-
- bp = NULL;
- daddr = ip->i_ib[a[0].in_off];
- for (i = 1; i < num; i++) {
- if (bp)
- brelse(bp);
- if (daddr == 0) {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx create "
- "block %jx %d\n", __func__, node, lblk, vblk,
- a[i].in_lbn, a[i].in_off));
- error = nandfs_bcreate_meta(node, a[i].in_lbn, NOCRED,
- 0, &bp);
- if (error)
- return (error);
- } else {
- DPRINTF(BMAP, ("%s: node %p lblk=%jx vblk=%jx read "
- "block %jx %d\n", __func__, node, daddr, vblk,
- a[i].in_lbn, a[i].in_off));
- error = nandfs_bread_meta(node, a[i].in_lbn, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- }
- daddr = ((nandfs_daddr_t *)bp->b_data)[a[i].in_off];
- }
- i--;
-
- DPRINTF(BMAP,
- ("%s: bmap node %p lblk=%jx vblk=%jx inserting vblk level %d at "
- "offset %d at %jx\n", __func__, node, lblk, vblk, i, a[i].in_off,
- daddr));
-
- if (!bp) {
- nandfs_error("%s: cannot find indirect block\n", __func__);
- return (-1);
- }
- ((nandfs_daddr_t *)bp->b_data)[a[i].in_off] = vblk;
-
- error = nandfs_dirty_buf_meta(bp, 0);
- if (error) {
- nandfs_warning("%s: dirty failed buf: %p\n", __func__, bp);
- return (error);
- }
- DPRINTF(BMAP, ("%s: exiting node %p lblk=%jx vblk=%jx\n", __func__,
- node, lblk, vblk));
-
- return (error);
-}
-
-CTASSERT(NANDFS_NIADDR <= 3);
-#define SINGLE 0 /* index of single indirect block */
-#define DOUBLE 1 /* index of double indirect block */
-#define TRIPLE 2 /* index of triple indirect block */
-
-static __inline nandfs_lbn_t
-lbn_offset(struct nandfs_device *fsdev, int level)
-{
- nandfs_lbn_t res;
-
- for (res = 1; level > 0; level--)
- res *= MNINDIR(fsdev);
- return (res);
-}
-
-static nandfs_lbn_t
-blocks_inside(struct nandfs_device *fsdev, int level, struct nandfs_indir *nip)
-{
- nandfs_lbn_t blocks;
-
- for (blocks = 1; level >= SINGLE; level--, nip++) {
- MPASS(nip->in_off >= 0 && nip->in_off < MNINDIR(fsdev));
- blocks += nip->in_off * lbn_offset(fsdev, level);
- }
-
- return (blocks);
-}
-
-static int
-bmap_truncate_indirect(struct nandfs_node *node, int level, nandfs_lbn_t *left,
- int *cleaned, struct nandfs_indir *ap, struct nandfs_indir *fp,
- nandfs_daddr_t *copy)
-{
- struct buf *bp;
- nandfs_lbn_t i, lbn, nlbn, factor, tosub;
- struct nandfs_device *fsdev;
- int error, lcleaned, modified;
-
- DPRINTF(BMAP, ("%s: node %p level %d left %jx\n", __func__,
- node, level, *left));
-
- fsdev = node->nn_nandfsdev;
-
- MPASS(ap->in_off >= 0 && ap->in_off < MNINDIR(fsdev));
-
- factor = lbn_offset(fsdev, level);
- lbn = ap->in_lbn;
-
- error = nandfs_bread_meta(node, lbn, NOCRED, 0, &bp);
- if (error) {
- if (bp != NULL)
- brelse(bp);
- return (error);
- }
-
- bcopy(bp->b_data, copy, fsdev->nd_blocksize);
- bqrelse(bp);
-
- modified = 0;
-
- i = ap->in_off;
-
- if (ap != fp)
- ap++;
- for (nlbn = lbn + 1 - i * factor; i >= 0 && *left > 0; i--,
- nlbn += factor) {
- lcleaned = 0;
-
- DPRINTF(BMAP,
- ("%s: node %p i=%jx nlbn=%jx left=%jx ap=%p vblk %jx\n",
- __func__, node, i, nlbn, *left, ap, copy[i]));
-
- if (copy[i] == 0) {
- tosub = blocks_inside(fsdev, level - 1, ap);
- if (tosub > *left)
- tosub = 0;
-
- *left -= tosub;
- } else {
- if (level > SINGLE) {
- if (ap == fp)
- ap->in_lbn = nlbn;
-
- error = bmap_truncate_indirect(node, level - 1,
- left, &lcleaned, ap, fp,
- copy + MNINDIR(fsdev));
- if (error)
- return (error);
- } else {
- error = nandfs_bdestroy(node, copy[i]);
- if (error)
- return (error);
- lcleaned = 1;
- *left -= 1;
- }
- }
-
- if (lcleaned) {
- if (level > SINGLE) {
- error = nandfs_vblock_end(fsdev, copy[i]);
- if (error)
- return (error);
- }
- copy[i] = 0;
- modified++;
- }
-
- ap = fp;
- }
-
- if (i == -1)
- *cleaned = 1;
-
- error = nandfs_bread_meta(node, lbn, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- if (modified)
- bcopy(copy, bp->b_data, fsdev->nd_blocksize);
-
- /* Force success even if we can't dirty the buffer metadata when freeing space */
- nandfs_dirty_buf_meta(bp, 1);
-
- return (0);
-}
-
-int
-bmap_truncate_mapping(struct nandfs_node *node, nandfs_lbn_t lastblk,
- nandfs_lbn_t todo)
-{
- struct nandfs_inode *ip;
- struct nandfs_indir a[NANDFS_NIADDR + 1], f[NANDFS_NIADDR], *ap;
- nandfs_daddr_t indir_lbn[NANDFS_NIADDR];
- nandfs_daddr_t *copy;
- int error, level;
- nandfs_lbn_t left, tosub;
- struct nandfs_device *fsdev;
- int cleaned, i;
- int num, *nump;
-
- DPRINTF(BMAP, ("%s: node %p lastblk %jx truncating by %jx\n", __func__,
- node, lastblk, todo));
-
- ip = &node->nn_inode;
- fsdev = node->nn_nandfsdev;
-
- ap = a;
- nump = &num;
-
- error = bmap_getlbns(node, lastblk, ap, nump);
- if (error)
- return (error);
-
- indir_lbn[SINGLE] = -NANDFS_NDADDR;
- indir_lbn[DOUBLE] = indir_lbn[SINGLE] - MNINDIR(fsdev) - 1;
- indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - MNINDIR(fsdev)
- * MNINDIR(fsdev) - 1;
-
- for (i = 0; i < NANDFS_NIADDR; i++) {
- f[i].in_off = MNINDIR(fsdev) - 1;
- f[i].in_lbn = 0xdeadbeef;
- }
-
- left = todo;
-
-#ifdef DEBUG
- a[num].in_off = -1;
-#endif
-
- ap++;
- num -= 2;
-
- if (num < 0)
- goto direct;
-
- copy = malloc(MNINDIR(fsdev) * sizeof(nandfs_daddr_t) * (num + 1),
- M_NANDFSTEMP, M_WAITOK);
-
- for (level = num; level >= SINGLE && left > 0; level--) {
- cleaned = 0;
-
- if (ip->i_ib[level] == 0) {
- tosub = blocks_inside(fsdev, level, ap);
- if (tosub > left)
- left = 0;
- else
- left -= tosub;
- } else {
- if (ap == f)
- ap->in_lbn = indir_lbn[level];
- error = bmap_truncate_indirect(node, level, &left,
- &cleaned, ap, f, copy);
- if (error) {
- free(copy, M_NANDFSTEMP);
- nandfs_error("%s: error %d when truncate "
- "at level %d\n", __func__, error, level);
- return (error);
- }
- }
-
- if (cleaned) {
- nandfs_vblock_end(fsdev, ip->i_ib[level]);
- ip->i_ib[level] = 0;
- }
-
- ap = f;
- }
-
- free(copy, M_NANDFSTEMP);
-
-direct:
- if (num < 0)
- i = lastblk;
- else
- i = NANDFS_NDADDR - 1;
-
- for (; i >= 0 && left > 0; i--) {
- if (ip->i_db[i] != 0) {
- error = nandfs_bdestroy(node, ip->i_db[i]);
- if (error) {
- nandfs_error("%s: cannot destroy "
- "block %jx, error %d\n", __func__,
- (uintmax_t)ip->i_db[i], error);
- return (error);
- }
- ip->i_db[i] = 0;
- }
-
- left--;
- }
-
- KASSERT(left == 0,
- ("truncated wrong number of blocks (%jd should be 0)", left));
-
- return (error);
-}
-
-nandfs_lbn_t
-get_maxfilesize(struct nandfs_device *fsdev)
-{
- struct nandfs_indir f[NANDFS_NIADDR];
- nandfs_lbn_t max;
- int i;
-
- max = NANDFS_NDADDR;
-
- for (i = 0; i < NANDFS_NIADDR; i++) {
- f[i].in_off = MNINDIR(fsdev) - 1;
- max += blocks_inside(fsdev, i, f);
- }
-
- max *= fsdev->nd_blocksize;
-
- return (max);
-}
-
-/*
- * This is ufs_getlbns with minor modifications.
- */
-/*
- * Create an array of logical block number/offset pairs which represent the
- * path of indirect blocks required to access a data block. The first "pair"
- * contains the logical block number of the appropriate single, double or
- * triple indirect block and the offset into the inode indirect block array.
- * Note, the logical block number of the inode single/double/triple indirect
- * block appears twice in the array, once with the offset into the i_ib and
- * once with the offset into the page itself.
- */
-static int
-bmap_getlbns(struct nandfs_node *node, nandfs_lbn_t bn, struct nandfs_indir *ap, int *nump)
-{
- nandfs_daddr_t blockcnt;
- nandfs_lbn_t metalbn, realbn;
- struct nandfs_device *fsdev;
- int i, numlevels, off;
-
- fsdev = node->nn_nandfsdev;
-
- DPRINTF(BMAP, ("%s: node %p bn=%jx mnindir=%zd enter\n", __func__,
- node, bn, MNINDIR(fsdev)));
-
- if (nump)
- *nump = 0;
- numlevels = 0;
- realbn = bn;
-
- if (bn < 0)
- bn = -bn;
-
- /* The first NANDFS_NDADDR blocks are direct blocks. */
- if (bn < NANDFS_NDADDR)
- return (0);
-
- /*
- * Determine the number of levels of indirection. After this loop
- * is done, blockcnt indicates the number of data blocks possible
- * at the previous level of indirection, and NANDFS_NIADDR - i is the
- * number of levels of indirection needed to locate the requested block.
- */
- for (blockcnt = 1, i = NANDFS_NIADDR, bn -= NANDFS_NDADDR;; i--, bn -= blockcnt) {
- DPRINTF(BMAP, ("%s: blockcnt=%jd i=%d bn=%jd\n", __func__,
- blockcnt, i, bn));
- if (i == 0)
- return (EFBIG);
- blockcnt *= MNINDIR(fsdev);
- if (bn < blockcnt)
- break;
- }
-
- /* Calculate the address of the first meta-block. */
- if (realbn >= 0)
- metalbn = -(realbn - bn + NANDFS_NIADDR - i);
- else
- metalbn = -(-realbn - bn + NANDFS_NIADDR - i);
-
- /*
- * At each iteration, off is the offset into the bap array which is
- * an array of disk addresses at the current level of indirection.
- * The logical block number and the offset in that block are stored
- * into the argument array.
- */
- ap->in_lbn = metalbn;
- ap->in_off = off = NANDFS_NIADDR - i;
-
- DPRINTF(BMAP, ("%s: initial: ap->in_lbn=%jx ap->in_off=%d\n", __func__,
- metalbn, off));
-
- ap++;
- for (++numlevels; i <= NANDFS_NIADDR; i++) {
- /* If searching for a meta-data block, quit when found. */
- if (metalbn == realbn)
- break;
-
- blockcnt /= MNINDIR(fsdev);
- off = (bn / blockcnt) % MNINDIR(fsdev);
-
- ++numlevels;
- ap->in_lbn = metalbn;
- ap->in_off = off;
-
- DPRINTF(BMAP, ("%s: in_lbn=%jx in_off=%d\n", __func__,
- ap->in_lbn, ap->in_off));
- ++ap;
-
- metalbn -= -1 + off * blockcnt;
- }
- if (nump)
- *nump = numlevels;
-
- DPRINTF(BMAP, ("%s: numlevels=%d\n", __func__, numlevels));
-
- return (0);
-}
diff --git a/sys/fs/nandfs/bmap.h b/sys/fs/nandfs/bmap.h
deleted file mode 100644
index a4784f7a88f9..000000000000
--- a/sys/fs/nandfs/bmap.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _BMAP_H
-#define _BMAP_H
-
-#include "nandfs_fs.h"
-
-int bmap_lookup(struct nandfs_node *, nandfs_lbn_t, nandfs_daddr_t *);
-int bmap_insert_block(struct nandfs_node *, nandfs_lbn_t, nandfs_daddr_t);
-int bmap_truncate_mapping(struct nandfs_node *, nandfs_lbn_t, nandfs_lbn_t);
-int bmap_dirty_meta(struct nandfs_node *, nandfs_lbn_t, int);
-
-nandfs_lbn_t get_maxfilesize(struct nandfs_device *);
-
-#endif /* _BMAP_H */
diff --git a/sys/fs/nandfs/nandfs.h b/sys/fs/nandfs/nandfs.h
deleted file mode 100644
index 9a9b28a1bc0b..000000000000
--- a/sys/fs/nandfs/nandfs.h
+++ /dev/null
@@ -1,312 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs.h,v 1.1 2009/07/18 16:31:42 reinoud
- *
- * $FreeBSD$
- */
-
-#ifndef _FS_NANDFS_NANDFS_H_
-#define _FS_NANDFS_NANDFS_H_
-
-#include <sys/param.h>
-#include <sys/proc.h>
-#include <sys/condvar.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-
-#include <sys/queue.h>
-#include <sys/uio.h>
-#include <sys/mutex.h>
-
-#include <sys/disk.h>
-#include <sys/kthread.h>
-#include "nandfs_fs.h"
-
-MALLOC_DECLARE(M_NANDFSTEMP);
-
-/* Debug categories */
-#define NANDFS_DEBUG_VOLUMES 0x000001
-#define NANDFS_DEBUG_BLOCK 0x000004
-#define NANDFS_DEBUG_LOCKING 0x000008
-#define NANDFS_DEBUG_NODE 0x000010
-#define NANDFS_DEBUG_LOOKUP 0x000020
-#define NANDFS_DEBUG_READDIR 0x000040
-#define NANDFS_DEBUG_TRANSLATE 0x000080
-#define NANDFS_DEBUG_STRATEGY 0x000100
-#define NANDFS_DEBUG_READ 0x000200
-#define NANDFS_DEBUG_WRITE 0x000400
-#define NANDFS_DEBUG_IFILE 0x000800
-#define NANDFS_DEBUG_ATTR 0x001000
-#define NANDFS_DEBUG_EXTATTR 0x002000
-#define NANDFS_DEBUG_ALLOC 0x004000
-#define NANDFS_DEBUG_CPFILE 0x008000
-#define NANDFS_DEBUG_DIRHASH 0x010000
-#define NANDFS_DEBUG_NOTIMPL 0x020000
-#define NANDFS_DEBUG_SHEDULE 0x040000
-#define NANDFS_DEBUG_SEG 0x080000
-#define NANDFS_DEBUG_SYNC 0x100000
-#define NANDFS_DEBUG_PARANOIA 0x200000
-#define NANDFS_DEBUG_VNCALL 0x400000
-#define NANDFS_DEBUG_BUF 0x1000000
-#define NANDFS_DEBUG_BMAP 0x2000000
-#define NANDFS_DEBUG_DAT 0x4000000
-#define NANDFS_DEBUG_GENERIC 0x8000000
-#define NANDFS_DEBUG_CLEAN 0x10000000
-
-extern int nandfs_verbose;
-
-#define DPRINTF(name, arg) { \
- if (nandfs_verbose & NANDFS_DEBUG_##name) {\
- printf arg;\
- };\
- }
-#define DPRINTFIF(name, cond, arg) { \
- if (nandfs_verbose & NANDFS_DEBUG_##name) { \
- if (cond) printf arg;\
- };\
- }
-
-#define VFSTONANDFS(mp) ((struct nandfsmount *)((mp)->mnt_data))
-#define VTON(vp) ((struct nandfs_node *)(vp)->v_data)
-#define NTOV(xp) ((xp)->nn_vnode)
-
-int nandfs_init(struct vfsconf *);
-int nandfs_uninit(struct vfsconf *);
-
-extern struct vop_vector nandfs_vnodeops;
-extern struct vop_vector nandfs_system_vnodeops;
-
-struct nandfs_node;
-
-/* Structure and derivatives */
-struct nandfs_mdt {
- uint32_t entries_per_block;
- uint32_t entries_per_group;
- uint32_t blocks_per_group;
- uint32_t groups_per_desc_block; /* desc is super group */
- uint32_t blocks_per_desc_block; /* desc is super group */
-};
-
-struct nandfs_segment {
- LIST_ENTRY(nandfs_segment) seg_link;
-
- struct nandfs_device *fsdev;
-
- TAILQ_HEAD(, buf) segsum;
- TAILQ_HEAD(, buf) data;
-
- uint64_t seg_num;
- uint64_t seg_next;
- uint64_t start_block;
- uint32_t num_blocks;
-
- uint32_t nblocks;
- uint32_t nbinfos;
- uint32_t segsum_blocks;
- uint32_t segsum_bytes;
- uint32_t bytes_left;
- char *current_off;
-};
-
-struct nandfs_seginfo {
- LIST_HEAD( ,nandfs_segment) seg_list;
- struct nandfs_segment *curseg;
- struct nandfs_device *fsdev;
- uint32_t blocks;
- uint8_t reiterate;
-};
-
-#define NANDFS_FSSTOR_FAILED 1
-struct nandfs_fsarea {
- int offset;
- int flags;
- int last_used;
-};
-
-extern int nandfs_cleaner_enable;
-extern int nandfs_cleaner_interval;
-extern int nandfs_cleaner_segments;
-
-struct nandfs_device {
- struct vnode *nd_devvp;
- struct g_consumer *nd_gconsumer;
-
- struct thread *nd_syncer;
- struct thread *nd_cleaner;
- int nd_syncer_exit;
- int nd_cleaner_exit;
-
- struct nandfs_fsarea nd_fsarea[NANDFS_NFSAREAS];
- int nd_last_fsarea;
-
- STAILQ_HEAD(nandfs_mnts, nandfsmount) nd_mounts;
- SLIST_ENTRY(nandfs_device) nd_next_device;
-
- /* FS structures */
- struct nandfs_fsdata nd_fsdata;
- struct nandfs_super_block nd_super;
- struct nandfs_segment_summary nd_last_segsum;
- struct nandfs_super_root nd_super_root;
- struct nandfs_node *nd_dat_node;
- struct nandfs_node *nd_cp_node;
- struct nandfs_node *nd_su_node;
- struct nandfs_node *nd_gc_node;
-
- struct nandfs_mdt nd_dat_mdt;
- struct nandfs_mdt nd_ifile_mdt;
-
- struct timespec nd_ts;
-
- /* Synchronization */
- struct mtx nd_mutex;
- struct mtx nd_sync_mtx;
- struct cv nd_sync_cv;
- struct mtx nd_clean_mtx;
- struct cv nd_clean_cv;
- struct lock nd_seg_const;
-
- struct nandfs_seginfo *nd_seginfo;
-
- /* FS geometry */
- uint64_t nd_devsize;
- uint64_t nd_maxfilesize;
- uint32_t nd_blocksize;
- uint32_t nd_erasesize;
-
- uint32_t nd_devblocksize;
-
- uint32_t nd_segs_reserved;
-
- /* Segment usage */
- uint64_t nd_clean_segs;
- uint64_t *nd_free_base;
- uint64_t nd_free_count;
- uint64_t nd_dirty_bufs;
-
- /* Running values */
- uint64_t nd_seg_sequence;
- uint64_t nd_seg_num;
- uint64_t nd_next_seg_num;
- uint64_t nd_last_pseg;
- uint64_t nd_last_cno;
- uint64_t nd_last_ino;
- uint64_t nd_fakevblk;
-
- int nd_mount_state;
- int nd_refcnt;
- int nd_syncing;
- int nd_cleaning;
-};
-
-extern SLIST_HEAD(_nandfs_devices, nandfs_device) nandfs_devices;
-
-#define NANDFS_FORCE_SYNCER 0x1
-#define NANDFS_UMOUNT 0x2
-
-#define SYNCER_UMOUNT 0x0
-#define SYNCER_VFS_SYNC 0x1
-#define SYNCER_BDFLUSH 0x2
-#define SYNCER_FFORCE 0x3
-#define SYNCER_FSYNC 0x4
-#define SYNCER_ROUPD 0x5
-
-static __inline int
-nandfs_writelockflags(struct nandfs_device *fsdev, int flags)
-{
- int error = 0;
-
- if (lockstatus(&fsdev->nd_seg_const) != LK_EXCLUSIVE)
- error = lockmgr(&fsdev->nd_seg_const, flags | LK_SHARED, NULL);
-
- return (error);
-}
-
-static __inline void
-nandfs_writeunlock(struct nandfs_device *fsdev)
-{
-
- if (lockstatus(&fsdev->nd_seg_const) != LK_EXCLUSIVE)
- lockmgr(&(fsdev)->nd_seg_const, LK_RELEASE, NULL);
-}
-
-#define NANDFS_WRITELOCKFLAGS(fsdev, flags) nandfs_writelockflags(fsdev, flags)
-
-#define NANDFS_WRITELOCK(fsdev) NANDFS_WRITELOCKFLAGS(fsdev, 0)
-
-#define NANDFS_WRITEUNLOCK(fsdev) nandfs_writeunlock(fsdev)
-
-#define NANDFS_WRITEASSERT(fsdev) lockmgr_assert(&(fsdev)->nd_seg_const, KA_LOCKED)
-
-/* Specific mountpoint; head or a checkpoint/snapshot */
-struct nandfsmount {
- STAILQ_ENTRY(nandfsmount) nm_next_mount;
-
- struct mount *nm_vfs_mountp;
- struct nandfs_device *nm_nandfsdev;
- struct nandfs_args nm_mount_args;
- struct nandfs_node *nm_ifile_node;
-
- uint8_t nm_flags;
- int8_t nm_ronly;
-};
-
-struct nandfs_node {
- struct vnode *nn_vnode;
- struct nandfsmount *nn_nmp;
- struct nandfs_device *nn_nandfsdev;
- struct lockf *nn_lockf;
-
- uint64_t nn_ino;
- struct nandfs_inode nn_inode;
-
- uint64_t nn_diroff;
- uint32_t nn_flags;
-};
-
-#define IN_ACCESS 0x0001 /* Inode access time update request */
-#define IN_CHANGE 0x0002 /* Inode change time update request */
-#define IN_UPDATE 0x0004 /* Inode was written to; update mtime*/
-#define IN_MODIFIED 0x0008 /* node has been modified */
-#define IN_RENAME 0x0010 /* node is being renamed. */
-
-/* File permissions. */
-#define IEXEC 0000100 /* Executable. */
-#define IWRITE 0000200 /* Writeable. */
-#define IREAD 0000400 /* Readable. */
-#define ISVTX 0001000 /* Sticky bit. */
-#define ISGID 0002000 /* Set-gid. */
-#define ISUID 0004000 /* Set-uid. */
-
-#define PRINT_NODE_FLAGS \
- "\10\1IN_ACCESS\2IN_CHANGE\3IN_UPDATE\4IN_MODIFIED\5IN_RENAME"
-
-#define NANDFS_GATHER(x) ((x)->b_flags |= B_FS_FLAG1)
-#define NANDFS_UNGATHER(x) ((x)->b_flags &= ~B_FS_FLAG1)
-#define NANDFS_ISGATHERED(x) ((x)->b_flags & B_FS_FLAG1)
-
-#endif /* !_FS_NANDFS_NANDFS_H_ */
diff --git a/sys/fs/nandfs/nandfs_alloc.c b/sys/fs/nandfs/nandfs_alloc.c
deleted file mode 100644
index afff174d130d..000000000000
--- a/sys/fs/nandfs/nandfs_alloc.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-static void
-nandfs_get_desc_block_nr(struct nandfs_mdt *mdt, uint64_t desc,
- uint64_t *desc_block)
-{
-
- *desc_block = desc * mdt->blocks_per_desc_block;
-}
-
-static void
-nandfs_get_group_block_nr(struct nandfs_mdt *mdt, uint64_t group,
- uint64_t *group_block)
-{
- uint64_t desc, group_off;
-
- desc = group / mdt->groups_per_desc_block;
- group_off = group % mdt->groups_per_desc_block;
- *group_block = desc * mdt->blocks_per_desc_block +
- 1 + group_off * mdt->blocks_per_group;
-}
-
-static void
-init_desc_block(struct nandfs_mdt *mdt, uint8_t *block_data)
-{
- struct nandfs_block_group_desc *desc;
- uint32_t i;
-
- desc = (struct nandfs_block_group_desc *) block_data;
- for (i = 0; i < mdt->groups_per_desc_block; i++)
- desc[i].bg_nfrees = mdt->entries_per_group;
-}
-
-int
-nandfs_find_free_entry(struct nandfs_mdt *mdt, struct nandfs_node *node,
- struct nandfs_alloc_request *req)
-{
- nandfs_daddr_t desc, group, maxgroup, maxdesc, pos = 0;
- nandfs_daddr_t start_group, start_desc;
- nandfs_daddr_t desc_block, group_block;
- nandfs_daddr_t file_blocks;
- struct nandfs_block_group_desc *descriptors;
- struct buf *bp, *bp2;
- uint32_t *mask, i, mcount, msize;
- int error;
-
- file_blocks = node->nn_inode.i_blocks;
- maxgroup = 0x100000000ull / mdt->entries_per_group;
- maxdesc = maxgroup / mdt->groups_per_desc_block;
- start_group = req->entrynum / mdt->entries_per_group;
- start_desc = start_group / mdt->groups_per_desc_block;
-
- bp = bp2 = NULL;
-restart:
- for (desc = start_desc; desc < maxdesc; desc++) {
- nandfs_get_desc_block_nr(mdt, desc, &desc_block);
-
- if (bp)
- brelse(bp);
- if (desc_block < file_blocks) {
- error = nandfs_bread(node, desc_block, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- } else {
- error = nandfs_bcreate(node, desc_block, NOCRED, 0,
- &bp);
- if (error)
- return (error);
- file_blocks++;
- init_desc_block(mdt, bp->b_data);
- }
-
- descriptors = (struct nandfs_block_group_desc *) bp->b_data;
- for (group = start_group; group < mdt->groups_per_desc_block;
- group++) {
- if (descriptors[group].bg_nfrees > 0) {
- nandfs_get_group_block_nr(mdt, group,
- &group_block);
-
- if (bp2)
- brelse(bp2);
- if (group_block < file_blocks) {
- error = nandfs_bread(node, group_block,
- NOCRED, 0, &bp2);
- if (error) {
- brelse(bp);
- return (error);
- }
- } else {
- error = nandfs_bcreate(node,
- group_block, NOCRED, 0, &bp2);
- if (error)
- return (error);
- file_blocks++;
- }
- mask = (uint32_t *)bp2->b_data;
- msize = (sizeof(uint32_t) * __CHAR_BIT);
- mcount = mdt->entries_per_group / msize;
- for (i = 0; i < mcount; i++) {
- if (mask[i] == UINT32_MAX)
- continue;
-
- pos = ffs(~mask[i]) - 1;
- pos += (msize * i);
- pos += (group * mdt->entries_per_group);
- pos += desc * group *
- mdt->groups_per_desc_block *
- mdt->entries_per_group;
- goto found;
- }
- }
- }
- start_group = 0;
- }
-
- if (start_desc != 0) {
- maxdesc = start_desc;
- start_desc = 0;
- req->entrynum = 0;
- goto restart;
- }
-
- return (ENOENT);
-
-found:
- req->entrynum = pos;
- req->bp_desc = bp;
- req->bp_bitmap = bp2;
- DPRINTF(ALLOC, ("%s: desc: %p bitmap: %p entry: %#jx\n",
- __func__, req->bp_desc, req->bp_bitmap, (uintmax_t)pos));
-
- return (0);
-}
-
-int
-nandfs_find_entry(struct nandfs_mdt* mdt, struct nandfs_node *nnode,
- struct nandfs_alloc_request *req)
-{
- uint64_t dblock, bblock, eblock;
- uint32_t offset;
- int error;
-
- nandfs_mdt_trans_blk(mdt, req->entrynum, &dblock, &bblock, &eblock,
- &offset);
-
- error = nandfs_bread(nnode, dblock, NOCRED, 0, &req->bp_desc);
- if (error) {
- brelse(req->bp_desc);
- return (error);
- }
-
- error = nandfs_bread(nnode, bblock, NOCRED, 0, &req->bp_bitmap);
- if (error) {
- brelse(req->bp_desc);
- brelse(req->bp_bitmap);
- return (error);
- }
-
- error = nandfs_bread(nnode, eblock, NOCRED, 0, &req->bp_entry);
- if (error) {
- brelse(req->bp_desc);
- brelse(req->bp_bitmap);
- brelse(req->bp_entry);
- return (error);
- }
-
- DPRINTF(ALLOC,
- ("%s: desc_buf: %p bitmap_buf %p entry_buf %p offset %x\n",
- __func__, req->bp_desc, req->bp_bitmap, req->bp_entry, offset));
-
- return (0);
-}
-
-static __inline void
-nandfs_calc_idx_entry(struct nandfs_mdt* mdt, uint32_t entrynum,
- uint64_t *group, uint64_t *bitmap_idx, uint64_t *bitmap_off)
-{
-
- /* Find group_desc index */
- entrynum = entrynum %
- (mdt->entries_per_group * mdt->groups_per_desc_block);
- *group = entrynum / mdt->entries_per_group;
- /* Find bitmap index and bit offset */
- entrynum = entrynum % mdt->entries_per_group;
- *bitmap_idx = entrynum / (sizeof(uint32_t) * __CHAR_BIT);
- *bitmap_off = entrynum % (sizeof(uint32_t) * __CHAR_BIT);
-}
-
-int
-nandfs_free_entry(struct nandfs_mdt* mdt, struct nandfs_alloc_request *req)
-{
- struct nandfs_block_group_desc *descriptors;
- uint64_t bitmap_idx, bitmap_off;
- uint64_t group;
- uint32_t *mask, maskrw;
-
- nandfs_calc_idx_entry(mdt, req->entrynum, &group, &bitmap_idx,
- &bitmap_off);
-
- DPRINTF(ALLOC, ("nandfs_free_entry: req->entrynum=%jx bitmap_idx=%jx"
- " bitmap_off=%jx group=%jx\n", (uintmax_t)req->entrynum,
- (uintmax_t)bitmap_idx, (uintmax_t)bitmap_off, (uintmax_t)group));
-
- /* Update counter of free entries for group */
- descriptors = (struct nandfs_block_group_desc *) req->bp_desc->b_data;
- descriptors[group].bg_nfrees++;
-
- /* Set bit to indicate that entry is taken */
- mask = (uint32_t *)req->bp_bitmap->b_data;
- maskrw = mask[bitmap_idx];
- KASSERT(maskrw & (1 << bitmap_off), ("freeing unallocated vblock"));
- maskrw &= ~(1 << bitmap_off);
- mask[bitmap_idx] = maskrw;
-
- /* Make descriptor, bitmap and entry buffer dirty */
- if (nandfs_dirty_buf(req->bp_desc, 0) == 0) {
- nandfs_dirty_buf(req->bp_bitmap, 1);
- nandfs_dirty_buf(req->bp_entry, 1);
- } else {
- brelse(req->bp_bitmap);
- brelse(req->bp_entry);
- return (-1);
- }
-
- return (0);
-}
-
-int
-nandfs_alloc_entry(struct nandfs_mdt* mdt, struct nandfs_alloc_request *req)
-{
- struct nandfs_block_group_desc *descriptors;
- uint64_t bitmap_idx, bitmap_off;
- uint64_t group;
- uint32_t *mask, maskrw;
-
- nandfs_calc_idx_entry(mdt, req->entrynum, &group, &bitmap_idx,
- &bitmap_off);
-
- DPRINTF(ALLOC, ("nandfs_alloc_entry: req->entrynum=%jx bitmap_idx=%jx"
- " bitmap_off=%jx group=%jx\n", (uintmax_t)req->entrynum,
- (uintmax_t)bitmap_idx, (uintmax_t)bitmap_off, (uintmax_t)group));
-
- /* Update counter of free entries for group */
- descriptors = (struct nandfs_block_group_desc *) req->bp_desc->b_data;
- descriptors[group].bg_nfrees--;
-
- /* Clear bit to indicate that entry is free */
- mask = (uint32_t *)req->bp_bitmap->b_data;
- maskrw = mask[bitmap_idx];
- maskrw |= 1 << bitmap_off;
- mask[bitmap_idx] = maskrw;
-
- /* Make descriptor, bitmap and entry buffer dirty */
- if (nandfs_dirty_buf(req->bp_desc, 0) == 0) {
- nandfs_dirty_buf(req->bp_bitmap, 1);
- nandfs_dirty_buf(req->bp_entry, 1);
- } else {
- brelse(req->bp_bitmap);
- brelse(req->bp_entry);
- return (-1);
- }
-
- return (0);
-}
-
-void
-nandfs_abort_entry(struct nandfs_alloc_request *req)
-{
-
- brelse(req->bp_desc);
- brelse(req->bp_bitmap);
- brelse(req->bp_entry);
-}
-
-int
-nandfs_get_entry_block(struct nandfs_mdt *mdt, struct nandfs_node *node,
- struct nandfs_alloc_request *req, uint32_t *entry, int create)
-{
- struct buf *bp;
- nandfs_lbn_t blocknr;
- int error;
-
- /* Find buffer number for given entry */
- nandfs_mdt_trans(mdt, req->entrynum, &blocknr, entry);
- DPRINTF(ALLOC, ("%s: ino %#jx entrynum:%#jx block:%#jx entry:%x\n",
- __func__, (uintmax_t)node->nn_ino, (uintmax_t)req->entrynum,
- (uintmax_t)blocknr, *entry));
-
- /* Read entry block or create if 'create' parameter is not zero */
- bp = NULL;
-
- if (blocknr < node->nn_inode.i_blocks)
- error = nandfs_bread(node, blocknr, NOCRED, 0, &bp);
- else if (create)
- error = nandfs_bcreate(node, blocknr, NOCRED, 0, &bp);
- else
- error = E2BIG;
-
- if (error) {
- DPRINTF(ALLOC, ("%s: ino %#jx block %#jx entry %x error %d\n",
- __func__, (uintmax_t)node->nn_ino, (uintmax_t)blocknr,
- *entry, error));
- if (bp)
- brelse(bp);
- return (error);
- }
-
- MPASS(nandfs_vblk_get(bp) != 0 || node->nn_ino == NANDFS_DAT_INO);
-
- req->bp_entry = bp;
- return (0);
-}
diff --git a/sys/fs/nandfs/nandfs_bmap.c b/sys/fs/nandfs/nandfs_bmap.c
deleted file mode 100644
index 6a1c2b0775d5..000000000000
--- a/sys/fs/nandfs/nandfs_bmap.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_subr.c,v 1.4 2009/07/29 17:06:57 reinoud
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/namei.h>
-#include <sys/kernel.h>
-#include <sys/stat.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/signalvar.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/lockf.h>
-#include <sys/ktr.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-#include <vm/vnode_pager.h>
-
-#include <machine/_inttypes.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-#include <vm/vnode_pager.h>
-
-#include "nandfs_mount.h"
-#include "nandfs.h"
-#include "nandfs_subr.h"
-#include "bmap.h"
-
-nandfs_lbn_t
-nandfs_get_maxfilesize(struct nandfs_device *fsdev)
-{
-
- return (get_maxfilesize(fsdev));
-}
-
-int
-nandfs_bmap_lookup(struct nandfs_node *node, nandfs_lbn_t lblk,
- nandfs_daddr_t *vblk)
-{
- int error = 0;
-
- if (node->nn_ino == NANDFS_GC_INO && lblk >= 0)
- *vblk = lblk;
- else
- error = bmap_lookup(node, lblk, vblk);
-
- DPRINTF(TRANSLATE, ("%s: error %d ino %#jx lblocknr %#jx -> %#jx\n",
- __func__, error, (uintmax_t)node->nn_ino, (uintmax_t)lblk,
- (uintmax_t)*vblk));
-
- if (error)
- nandfs_error("%s: returned %d", __func__, error);
-
- return (error);
-}
-
-int
-nandfs_bmap_insert_block(struct nandfs_node *node, nandfs_lbn_t lblk,
- struct buf *bp)
-{
- struct nandfs_device *fsdev;
- nandfs_daddr_t vblk;
- int error;
-
- fsdev = node->nn_nandfsdev;
-
- vblk = 0;
- if (node->nn_ino != NANDFS_DAT_INO) {
- error = nandfs_vblock_alloc(fsdev, &vblk);
- if (error)
- return (error);
- }
-
- nandfs_buf_set(bp, NANDFS_VBLK_ASSIGNED);
- nandfs_vblk_set(bp, vblk);
-
- error = bmap_insert_block(node, lblk, vblk);
- if (error) {
- nandfs_vblock_free(fsdev, vblk);
- return (error);
- }
-
- return (0);
-}
-
-int
-nandfs_bmap_dirty_blocks(struct nandfs_node *node, struct buf *bp, int force)
-{
- int error;
-
- error = bmap_dirty_meta(node, bp->b_lblkno, force);
- if (error)
- nandfs_error("%s: cannot dirty buffer %p\n",
- __func__, bp);
-
- return (error);
-}
-
-static int
-nandfs_bmap_update_mapping(struct nandfs_node *node, nandfs_lbn_t lblk,
- nandfs_daddr_t blknr)
-{
- int error;
-
- DPRINTF(BMAP,
- ("%s: node: %p ino: %#jx lblk: %#jx vblk: %#jx\n",
- __func__, node, (uintmax_t)node->nn_ino, (uintmax_t)lblk,
- (uintmax_t)blknr));
-
- error = bmap_insert_block(node, lblk, blknr);
-
- return (error);
-}
-
-int
-nandfs_bmap_update_block(struct nandfs_node *node, struct buf *bp,
- nandfs_lbn_t blknr)
-{
- nandfs_lbn_t lblk;
- int error;
-
- lblk = bp->b_lblkno;
- nandfs_vblk_set(bp, blknr);
-
- DPRINTF(BMAP, ("%s: node: %p ino: %#jx bp: %p lblk: %#jx blk: %#jx\n",
- __func__, node, (uintmax_t)node->nn_ino, bp,
- (uintmax_t)lblk, (uintmax_t)blknr));
-
- error = nandfs_bmap_update_mapping(node, lblk, blknr);
- if (error) {
- nandfs_error("%s: cannot update lblk:%jx to blk:%jx for "
- "node:%p, error:%d\n", __func__, (uintmax_t)lblk,
- (uintmax_t)blknr, node, error);
- return (error);
- }
-
- return (error);
-}
-
-int
-nandfs_bmap_update_dat(struct nandfs_node *node, nandfs_daddr_t oldblk,
- struct buf *bp)
-{
- struct nandfs_device *fsdev;
- nandfs_daddr_t vblk = 0;
- int error;
-
- if (node->nn_ino == NANDFS_DAT_INO)
- return (0);
-
- if (nandfs_buf_check(bp, NANDFS_VBLK_ASSIGNED)) {
- nandfs_buf_clear(bp, NANDFS_VBLK_ASSIGNED);
- return (0);
- }
-
- fsdev = node->nn_nandfsdev;
-
- /* First alloc new virtual block.... */
- error = nandfs_vblock_alloc(fsdev, &vblk);
- if (error)
- return (error);
-
- error = nandfs_bmap_update_block(node, bp, vblk);
- if (error)
- return (error);
-
- /* Then we can end up with old one */
- nandfs_vblock_end(fsdev, oldblk);
-
- DPRINTF(BMAP,
- ("%s: ino %#jx block %#jx: update vblk %#jx to %#jx\n",
- __func__, (uintmax_t)node->nn_ino, (uintmax_t)bp->b_lblkno,
- (uintmax_t)oldblk, (uintmax_t)vblk));
- return (error);
-}
-
-int
-nandfs_bmap_truncate_mapping(struct nandfs_node *node, nandfs_lbn_t oblk,
- nandfs_lbn_t nblk)
-{
- nandfs_lbn_t todo;
- int error;
-
- todo = oblk - nblk;
-
- DPRINTF(BMAP, ("%s: node %p oblk %jx nblk %jx truncate by %jx\n",
- __func__, node, oblk, nblk, todo));
-
- error = bmap_truncate_mapping(node, oblk, todo);
- if (error)
- return (error);
-
- return (error);
-}
diff --git a/sys/fs/nandfs/nandfs_buffer.c b/sys/fs/nandfs/nandfs_buffer.c
deleted file mode 100644
index 57089718554f..000000000000
--- a/sys/fs/nandfs/nandfs_buffer.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/buf.h>
-#include <sys/namei.h>
-#include <sys/vnode.h>
-#include <sys/bio.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-struct buf *
-nandfs_geteblk(int size, int flags)
-{
- struct buf *bp;
-
- /*
- * XXX
- * Right now we can call geteblk with GB_NOWAIT_BD flag, which means
- * it can return NULL. But we cannot afford to get NULL, hence this panic.
- */
- bp = geteblk(size, flags);
- if (bp == NULL)
- panic("geteblk returned NULL");
-
- return (bp);
-}
-
-void
-nandfs_dirty_bufs_increment(struct nandfs_device *fsdev)
-{
-
- mtx_lock(&fsdev->nd_mutex);
- KASSERT(fsdev->nd_dirty_bufs >= 0, ("negative nd_dirty_bufs"));
- fsdev->nd_dirty_bufs++;
- mtx_unlock(&fsdev->nd_mutex);
-}
-
-void
-nandfs_dirty_bufs_decrement(struct nandfs_device *fsdev)
-{
-
- mtx_lock(&fsdev->nd_mutex);
- KASSERT(fsdev->nd_dirty_bufs > 0,
- ("decrementing not-positive nd_dirty_bufs"));
- fsdev->nd_dirty_bufs--;
- mtx_unlock(&fsdev->nd_mutex);
-}
diff --git a/sys/fs/nandfs/nandfs_cleaner.c b/sys/fs/nandfs/nandfs_cleaner.c
deleted file mode 100644
index 3241c8701bfc..000000000000
--- a/sys/fs/nandfs/nandfs_cleaner.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/buf.h>
-#include <sys/namei.h>
-#include <sys/vnode.h>
-#include <sys/bio.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-#define NANDFS_CLEANER_KILL 1
-
-static void nandfs_cleaner(struct nandfs_device *);
-static int nandfs_cleaner_clean_segments(struct nandfs_device *,
- struct nandfs_vinfo *, uint32_t, struct nandfs_period *, uint32_t,
- struct nandfs_bdesc *, uint32_t, uint64_t *, uint32_t);
-
-static int
-nandfs_process_bdesc(struct nandfs_device *nffsdev, struct nandfs_bdesc *bd,
- uint64_t nmembs);
-
-static void
-nandfs_wakeup_wait_cleaner(struct nandfs_device *fsdev, int reason)
-{
-
- mtx_lock(&fsdev->nd_clean_mtx);
- if (reason == NANDFS_CLEANER_KILL)
- fsdev->nd_cleaner_exit = 1;
- if (fsdev->nd_cleaning == 0) {
- fsdev->nd_cleaning = 1;
- wakeup(&fsdev->nd_cleaning);
- }
- cv_wait(&fsdev->nd_clean_cv, &fsdev->nd_clean_mtx);
- mtx_unlock(&fsdev->nd_clean_mtx);
-}
-
-int
-nandfs_start_cleaner(struct nandfs_device *fsdev)
-{
- int error;
-
- MPASS(fsdev->nd_cleaner == NULL);
-
- fsdev->nd_cleaner_exit = 0;
-
- error = kthread_add((void(*)(void *))nandfs_cleaner, fsdev, NULL,
- &fsdev->nd_cleaner, 0, 0, "nandfs_cleaner");
- if (error)
- printf("nandfs: could not start cleaner: %d\n", error);
-
- return (error);
-}
-
-int
-nandfs_stop_cleaner(struct nandfs_device *fsdev)
-{
-
- MPASS(fsdev->nd_cleaner != NULL);
- nandfs_wakeup_wait_cleaner(fsdev, NANDFS_CLEANER_KILL);
- fsdev->nd_cleaner = NULL;
-
- DPRINTF(CLEAN, ("cleaner stopped\n"));
- return (0);
-}
-
-static int
-nandfs_cleaner_finished(struct nandfs_device *fsdev)
-{
- int exit;
-
- mtx_lock(&fsdev->nd_clean_mtx);
- fsdev->nd_cleaning = 0;
- if (!fsdev->nd_cleaner_exit) {
- DPRINTF(CLEAN, ("%s: sleep\n", __func__));
- msleep(&fsdev->nd_cleaning, &fsdev->nd_clean_mtx, PRIBIO, "-",
- hz * nandfs_cleaner_interval);
- }
- exit = fsdev->nd_cleaner_exit;
- cv_broadcast(&fsdev->nd_clean_cv);
- mtx_unlock(&fsdev->nd_clean_mtx);
- if (exit) {
- DPRINTF(CLEAN, ("%s: no longer active\n", __func__));
- return (1);
- }
-
- return (0);
-}
-
-static void
-print_suinfo(struct nandfs_suinfo *suinfo, int nsegs)
-{
- int i;
-
- for (i = 0; i < nsegs; i++) {
- DPRINTF(CLEAN, ("%jx %jd %c%c%c %10u\n",
- suinfo[i].nsi_num, suinfo[i].nsi_lastmod,
- (suinfo[i].nsi_flags &
- (NANDFS_SEGMENT_USAGE_ACTIVE) ? 'a' : '-'),
- (suinfo[i].nsi_flags &
- (NANDFS_SEGMENT_USAGE_DIRTY) ? 'd' : '-'),
- (suinfo[i].nsi_flags &
- (NANDFS_SEGMENT_USAGE_ERROR) ? 'e' : '-'),
- suinfo[i].nsi_blocks));
- }
-}
-
-static int
-nandfs_cleaner_vblock_is_alive(struct nandfs_device *fsdev,
- struct nandfs_vinfo *vinfo, struct nandfs_cpinfo *cp, uint32_t ncps)
-{
- int64_t idx, min, max;
-
- if (vinfo->nvi_end >= fsdev->nd_last_cno)
- return (1);
-
- if (ncps == 0)
- return (0);
-
- if (vinfo->nvi_end < cp[0].nci_cno ||
- vinfo->nvi_start > cp[ncps - 1].nci_cno)
- return (0);
-
- idx = min = 0;
- max = ncps - 1;
- while (min <= max) {
- idx = (min + max) / 2;
- if (vinfo->nvi_start == cp[idx].nci_cno)
- return (1);
- if (vinfo->nvi_start < cp[idx].nci_cno)
- max = idx - 1;
- else
- min = idx + 1;
- }
-
- return (vinfo->nvi_end >= cp[idx].nci_cno);
-}
-
-static void
-nandfs_cleaner_vinfo_mark_alive(struct nandfs_device *fsdev,
- struct nandfs_vinfo *vinfo, uint32_t nmembs, struct nandfs_cpinfo *cp,
- uint32_t ncps)
-{
- uint32_t i;
-
- for (i = 0; i < nmembs; i++)
- vinfo[i].nvi_alive =
- nandfs_cleaner_vblock_is_alive(fsdev, &vinfo[i], cp, ncps);
-}
-
-static int
-nandfs_cleaner_bdesc_is_alive(struct nandfs_device *fsdev,
- struct nandfs_bdesc *bdesc)
-{
- int alive;
-
- alive = bdesc->bd_oblocknr == bdesc->bd_blocknr;
- if (!alive)
- MPASS(abs(bdesc->bd_oblocknr - bdesc->bd_blocknr) > 2);
-
- return (alive);
-}
-
-static void
-nandfs_cleaner_bdesc_mark_alive(struct nandfs_device *fsdev,
- struct nandfs_bdesc *bdesc, uint32_t nmembs)
-{
- uint32_t i;
-
- for (i = 0; i < nmembs; i++)
- bdesc[i].bd_alive = nandfs_cleaner_bdesc_is_alive(fsdev,
- &bdesc[i]);
-}
-
-static void
-nandfs_cleaner_iterate_psegment(struct nandfs_device *fsdev,
- struct nandfs_segment_summary *segsum, union nandfs_binfo *binfo,
- nandfs_daddr_t blk, struct nandfs_vinfo **vipp, struct nandfs_bdesc **bdpp)
-{
- int i;
-
- DPRINTF(CLEAN, ("%s nbinfos %x\n", __func__, segsum->ss_nbinfos));
- for (i = 0; i < segsum->ss_nbinfos; i++) {
- if (binfo[i].bi_v.bi_ino == NANDFS_DAT_INO) {
- (*bdpp)->bd_oblocknr = blk + segsum->ss_nblocks -
- segsum->ss_nbinfos + i;
- /*
- * XXX Hack
- */
- if (segsum->ss_flags & NANDFS_SS_SR)
- (*bdpp)->bd_oblocknr--;
- (*bdpp)->bd_level = binfo[i].bi_dat.bi_level;
- (*bdpp)->bd_offset = binfo[i].bi_dat.bi_blkoff;
- (*bdpp)++;
- } else {
- (*vipp)->nvi_ino = binfo[i].bi_v.bi_ino;
- (*vipp)->nvi_vblocknr = binfo[i].bi_v.bi_vblocknr;
- (*vipp)++;
- }
- }
-}
-
-static int
-nandfs_cleaner_iterate_segment(struct nandfs_device *fsdev, uint64_t segno,
- struct nandfs_vinfo **vipp, struct nandfs_bdesc **bdpp, int *select)
-{
- struct nandfs_segment_summary *segsum;
- union nandfs_binfo *binfo;
- struct buf *bp;
- uint32_t nblocks;
- nandfs_daddr_t curr, start, end;
- int error = 0;
-
- nandfs_get_segment_range(fsdev, segno, &start, &end);
-
- DPRINTF(CLEAN, ("%s: segno %jx start %jx end %jx\n", __func__, segno,
- start, end));
-
- *select = 0;
-
- for (curr = start; curr < end; curr += nblocks) {
- error = nandfs_dev_bread(fsdev, curr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- nandfs_error("%s: couldn't load segment summary of %jx: %d\n",
- __func__, segno, error);
- return (error);
- }
-
- segsum = (struct nandfs_segment_summary *)bp->b_data;
- binfo = (union nandfs_binfo *)(bp->b_data + segsum->ss_bytes);
-
- if (!nandfs_segsum_valid(segsum)) {
- brelse(bp);
- nandfs_error("nandfs: invalid summary of segment %jx\n", segno);
- return (error);
- }
-
- DPRINTF(CLEAN, ("%s: %jx magic %x bytes %x nblocks %x nbinfos "
- "%x\n", __func__, segno, segsum->ss_magic, segsum->ss_bytes,
- segsum->ss_nblocks, segsum->ss_nbinfos));
-
- nandfs_cleaner_iterate_psegment(fsdev, segsum, binfo, curr,
- vipp, bdpp);
- nblocks = segsum->ss_nblocks;
- brelse(bp);
- }
-
- if (error == 0)
- *select = 1;
-
- return (error);
-}
-
-static int
-nandfs_cleaner_choose_segment(struct nandfs_device *fsdev, uint64_t **segpp,
- uint64_t nsegs, uint64_t *rseg)
-{
- struct nandfs_suinfo *suinfo;
- uint64_t i, ssegs;
- int error;
-
- suinfo = malloc(sizeof(*suinfo) * nsegs, M_NANDFSTEMP,
- M_ZERO | M_WAITOK);
-
- if (*rseg >= fsdev->nd_fsdata.f_nsegments)
- *rseg = 0;
-
-retry:
- error = nandfs_get_segment_info_filter(fsdev, suinfo, nsegs, *rseg,
- &ssegs, NANDFS_SEGMENT_USAGE_DIRTY,
- NANDFS_SEGMENT_USAGE_ACTIVE | NANDFS_SEGMENT_USAGE_ERROR |
- NANDFS_SEGMENT_USAGE_GC);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- goto out;
- }
- if (ssegs == 0 && *rseg != 0) {
- *rseg = 0;
- goto retry;
- }
- if (ssegs > 0) {
- print_suinfo(suinfo, ssegs);
-
- for (i = 0; i < ssegs; i++) {
- (**segpp) = suinfo[i].nsi_num;
- (*segpp)++;
- }
- *rseg = suinfo[i - 1].nsi_num + 1;
- }
-
-out:
- free(suinfo, M_NANDFSTEMP);
- return (error);
-}
-
-static int
-nandfs_cleaner_body(struct nandfs_device *fsdev, uint64_t *rseg)
-{
- struct nandfs_vinfo *vinfo, *vip, *vipi;
- struct nandfs_bdesc *bdesc, *bdp, *bdpi;
- struct nandfs_cpstat cpstat;
- struct nandfs_cpinfo *cpinfo = NULL;
- uint64_t *segnums, *segp;
- int select, selected;
- int error = 0;
- int nsegs;
- int i;
-
- nsegs = nandfs_cleaner_segments;
-
- vip = vinfo = malloc(sizeof(*vinfo) *
- fsdev->nd_fsdata.f_blocks_per_segment * nsegs, M_NANDFSTEMP,
- M_ZERO | M_WAITOK);
- bdp = bdesc = malloc(sizeof(*bdesc) *
- fsdev->nd_fsdata.f_blocks_per_segment * nsegs, M_NANDFSTEMP,
- M_ZERO | M_WAITOK);
- segp = segnums = malloc(sizeof(*segnums) * nsegs, M_NANDFSTEMP,
- M_WAITOK);
-
- error = nandfs_cleaner_choose_segment(fsdev, &segp, nsegs, rseg);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- goto out;
- }
-
- if (segnums == segp)
- goto out;
-
- selected = 0;
- for (i = 0; i < segp - segnums; i++) {
- error = nandfs_cleaner_iterate_segment(fsdev, segnums[i], &vip,
- &bdp, &select);
- if (error) {
- /*
- * XXX deselect (see below)?
- */
- goto out;
- }
- if (!select)
- segnums[i] = NANDFS_NOSEGMENT;
- else {
- error = nandfs_markgc_segment(fsdev, segnums[i]);
- if (error) {
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out;
- }
- selected++;
- }
- }
-
- if (selected == 0) {
- MPASS(vinfo == vip);
- MPASS(bdesc == bdp);
- goto out;
- }
-
- error = nandfs_get_cpstat(fsdev->nd_cp_node, &cpstat);
- if (error) {
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out;
- }
-
- if (cpstat.ncp_nss != 0) {
- cpinfo = malloc(sizeof(struct nandfs_cpinfo) * cpstat.ncp_nss,
- M_NANDFSTEMP, M_WAITOK);
- error = nandfs_get_cpinfo(fsdev->nd_cp_node, 1, NANDFS_SNAPSHOT,
- cpinfo, cpstat.ncp_nss, NULL);
- if (error) {
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out_locked;
- }
- }
-
- NANDFS_WRITELOCK(fsdev);
- DPRINTF(CLEAN, ("%s: got lock\n", __func__));
-
- error = nandfs_get_dat_vinfo(fsdev, vinfo, vip - vinfo);
- if (error) {
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out_locked;
- }
-
- nandfs_cleaner_vinfo_mark_alive(fsdev, vinfo, vip - vinfo, cpinfo,
- cpstat.ncp_nss);
-
- error = nandfs_get_dat_bdescs(fsdev, bdesc, bdp - bdesc);
- if (error) {
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
- goto out_locked;
- }
-
- nandfs_cleaner_bdesc_mark_alive(fsdev, bdesc, bdp - bdesc);
-
- DPRINTF(CLEAN, ("got:\n"));
- for (vipi = vinfo; vipi < vip; vipi++) {
- DPRINTF(CLEAN, ("v ino %jx vblocknr %jx start %jx end %jx "
- "alive %d\n", vipi->nvi_ino, vipi->nvi_vblocknr,
- vipi->nvi_start, vipi->nvi_end, vipi->nvi_alive));
- }
- for (bdpi = bdesc; bdpi < bdp; bdpi++) {
- DPRINTF(CLEAN, ("b oblocknr %jx blocknr %jx offset %jx "
- "alive %d\n", bdpi->bd_oblocknr, bdpi->bd_blocknr,
- bdpi->bd_offset, bdpi->bd_alive));
- }
- DPRINTF(CLEAN, ("end list\n"));
-
- error = nandfs_cleaner_clean_segments(fsdev, vinfo, vip - vinfo, NULL,
- 0, bdesc, bdp - bdesc, segnums, segp - segnums);
- if (error)
- nandfs_error("%s:%d\n", __FILE__, __LINE__);
-
-out_locked:
- NANDFS_WRITEUNLOCK(fsdev);
-out:
- free(cpinfo, M_NANDFSTEMP);
- free(segnums, M_NANDFSTEMP);
- free(bdesc, M_NANDFSTEMP);
- free(vinfo, M_NANDFSTEMP);
-
- return (error);
-}
-
-static void
-nandfs_cleaner(struct nandfs_device *fsdev)
-{
- uint64_t checked_seg = 0;
- int error;
-
- while (!nandfs_cleaner_finished(fsdev)) {
- if (!nandfs_cleaner_enable || rebooting)
- continue;
-
- DPRINTF(CLEAN, ("%s: run started\n", __func__));
-
- fsdev->nd_cleaning = 1;
-
- error = nandfs_cleaner_body(fsdev, &checked_seg);
-
- DPRINTF(CLEAN, ("%s: run finished error %d\n", __func__,
- error));
- }
-
- DPRINTF(CLEAN, ("%s: exiting\n", __func__));
- kthread_exit();
-}
-
-static int
-nandfs_cleaner_clean_segments(struct nandfs_device *nffsdev,
- struct nandfs_vinfo *vinfo, uint32_t nvinfo,
- struct nandfs_period *pd, uint32_t npd,
- struct nandfs_bdesc *bdesc, uint32_t nbdesc,
- uint64_t *segments, uint32_t nsegs)
-{
- struct nandfs_node *gc;
- struct buf *bp;
- uint32_t i;
- int error = 0;
-
- gc = nffsdev->nd_gc_node;
-
- DPRINTF(CLEAN, ("%s: enter\n", __func__));
-
- VOP_LOCK(NTOV(gc), LK_EXCLUSIVE);
- for (i = 0; i < nvinfo; i++) {
- if (!vinfo[i].nvi_alive)
- continue;
- DPRINTF(CLEAN, ("%s: read vblknr:%#jx blk:%#jx\n",
- __func__, (uintmax_t)vinfo[i].nvi_vblocknr,
- (uintmax_t)vinfo[i].nvi_blocknr));
- error = nandfs_bread(nffsdev->nd_gc_node, vinfo[i].nvi_blocknr,
- NULL, 0, &bp);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- VOP_UNLOCK(NTOV(gc), 0);
- goto out;
- }
- nandfs_vblk_set(bp, vinfo[i].nvi_vblocknr);
- nandfs_buf_set(bp, NANDFS_VBLK_ASSIGNED);
- nandfs_dirty_buf(bp, 1);
- }
- VOP_UNLOCK(NTOV(gc), 0);
-
- /* Delete checkpoints */
- for (i = 0; i < npd; i++) {
- DPRINTF(CLEAN, ("delete checkpoint: %jx\n",
- (uintmax_t)pd[i].p_start));
- error = nandfs_delete_cp(nffsdev->nd_cp_node, pd[i].p_start,
- pd[i].p_end);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- goto out;
- }
- }
-
- /* Update vblocks */
- for (i = 0; i < nvinfo; i++) {
- if (vinfo[i].nvi_alive)
- continue;
- DPRINTF(CLEAN, ("freeing vblknr: %jx\n", vinfo[i].nvi_vblocknr));
- error = nandfs_vblock_free(nffsdev, vinfo[i].nvi_vblocknr);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- goto out;
- }
- }
-
- error = nandfs_process_bdesc(nffsdev, bdesc, nbdesc);
- if (error) {
- nandfs_error("%s:%d", __FILE__, __LINE__);
- goto out;
- }
-
- /* Add segments to clean */
- if (nffsdev->nd_free_count) {
- nffsdev->nd_free_base = realloc(nffsdev->nd_free_base,
- (nffsdev->nd_free_count + nsegs) * sizeof(uint64_t),
- M_NANDFSTEMP, M_WAITOK | M_ZERO);
- memcpy(&nffsdev->nd_free_base[nffsdev->nd_free_count], segments,
- nsegs * sizeof(uint64_t));
- nffsdev->nd_free_count += nsegs;
- } else {
- nffsdev->nd_free_base = malloc(nsegs * sizeof(uint64_t),
- M_NANDFSTEMP, M_WAITOK|M_ZERO);
- memcpy(nffsdev->nd_free_base, segments,
- nsegs * sizeof(uint64_t));
- nffsdev->nd_free_count = nsegs;
- }
-
-out:
-
- DPRINTF(CLEAN, ("%s: exit error %d\n", __func__, error));
-
- return (error);
-}
-
-static int
-nandfs_process_bdesc(struct nandfs_device *nffsdev, struct nandfs_bdesc *bd,
- uint64_t nmembs)
-{
- struct nandfs_node *dat_node;
- struct buf *bp;
- uint64_t i;
- int error;
-
- dat_node = nffsdev->nd_dat_node;
-
- VOP_LOCK(NTOV(dat_node), LK_EXCLUSIVE);
-
- for (i = 0; i < nmembs; i++) {
- if (!bd[i].bd_alive)
- continue;
- DPRINTF(CLEAN, ("%s: idx %jx offset %jx\n",
- __func__, i, bd[i].bd_offset));
- if (bd[i].bd_level) {
- error = nandfs_bread_meta(dat_node, bd[i].bd_offset,
- NULL, 0, &bp);
- if (error) {
- nandfs_error("%s: cannot read dat node "
- "level:%d\n", __func__, bd[i].bd_level);
- brelse(bp);
- VOP_UNLOCK(NTOV(dat_node), 0);
- return (error);
- }
- nandfs_dirty_buf_meta(bp, 1);
- nandfs_bmap_dirty_blocks(VTON(bp->b_vp), bp, 1);
- } else {
- error = nandfs_bread(dat_node, bd[i].bd_offset, NULL,
- 0, &bp);
- if (error) {
- nandfs_error("%s: cannot read dat node\n",
- __func__);
- brelse(bp);
- VOP_UNLOCK(NTOV(dat_node), 0);
- return (error);
- }
- nandfs_dirty_buf(bp, 1);
- }
- DPRINTF(CLEAN, ("%s: bp: %p\n", __func__, bp));
- }
-
- VOP_UNLOCK(NTOV(dat_node), 0);
-
- return (0);
-}
diff --git a/sys/fs/nandfs/nandfs_cpfile.c b/sys/fs/nandfs/nandfs_cpfile.c
deleted file mode 100644
index 8c9a695879e4..000000000000
--- a/sys/fs/nandfs/nandfs_cpfile.c
+++ /dev/null
@@ -1,778 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include "nandfs_mount.h"
-#include "nandfs.h"
-#include "nandfs_subr.h"
-
-
-static int
-nandfs_checkpoint_size(struct nandfs_device *fsdev)
-{
-
- return (fsdev->nd_fsdata.f_checkpoint_size);
-}
-
-static int
-nandfs_checkpoint_blk_offset(struct nandfs_device *fsdev, uint64_t cn,
- uint64_t *blk, uint64_t *offset)
-{
- uint64_t off;
- uint16_t cp_size, cp_per_blk;
-
- KASSERT((cn), ("checkpoing cannot be zero"));
-
- cp_size = fsdev->nd_fsdata.f_checkpoint_size;
- cp_per_blk = fsdev->nd_blocksize / cp_size;
- off = roundup(sizeof(struct nandfs_cpfile_header), cp_size) / cp_size;
- off += (cn - 1);
-
- *blk = off / cp_per_blk;
- *offset = (off % cp_per_blk) * cp_size;
-
- return (0);
-}
-
-static int
-nandfs_checkpoint_blk_remaining(struct nandfs_device *fsdev, uint64_t cn,
- uint64_t blk, uint64_t offset)
-{
- uint16_t cp_size, cp_remaining;
-
- cp_size = fsdev->nd_fsdata.f_checkpoint_size;
- cp_remaining = (fsdev->nd_blocksize - offset) / cp_size;
-
- return (cp_remaining);
-}
-
-int
-nandfs_get_checkpoint(struct nandfs_device *fsdev, struct nandfs_node *cp_node,
- uint64_t cn)
-{
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- if (cn != fsdev->nd_last_cno && cn != (fsdev->nd_last_cno + 1)) {
- return (-1);
- }
-
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (-1);
- }
-
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (-1);
-
-
- nandfs_checkpoint_blk_offset(fsdev, cn, &blk, &offset);
-
- if (blk != 0) {
- if (blk < cp_node->nn_inode.i_blocks)
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- else
- error = nandfs_bcreate(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- if (bp)
- brelse(bp);
- return (-1);
- }
-
- nandfs_dirty_buf(bp, 1);
- }
-
- DPRINTF(CPFILE, ("%s: cn:%#jx entry block:%#jx offset:%#jx\n",
- __func__, (uintmax_t)cn, (uintmax_t)blk, (uintmax_t)offset));
-
- return (0);
-}
-
-int
-nandfs_set_checkpoint(struct nandfs_device *fsdev, struct nandfs_node *cp_node,
- uint64_t cn, struct nandfs_inode *ifile_inode, uint64_t nblocks)
-{
- struct nandfs_cpfile_header *cnh;
- struct nandfs_checkpoint *cnp;
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- if (cn != fsdev->nd_last_cno && cn != (fsdev->nd_last_cno + 1)) {
- nandfs_error("%s: trying to set invalid chekpoint %jx - %jx\n",
- __func__, cn, fsdev->nd_last_cno);
- return (-1);
- }
-
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return error;
- }
-
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- cnh->ch_ncheckpoints++;
-
- nandfs_checkpoint_blk_offset(fsdev, cn, &blk, &offset);
-
- if(blk != 0) {
- brelse(bp);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return error;
- }
- }
-
- cnp = (struct nandfs_checkpoint *)((uint8_t *)bp->b_data + offset);
- cnp->cp_flags = 0;
- cnp->cp_checkpoints_count = 1;
- memset(&cnp->cp_snapshot_list, 0, sizeof(struct nandfs_snapshot_list));
- cnp->cp_cno = cn;
- cnp->cp_create = fsdev->nd_ts.tv_sec;
- cnp->cp_nblk_inc = nblocks;
- cnp->cp_blocks_count = 0;
- memcpy (&cnp->cp_ifile_inode, ifile_inode, sizeof(cnp->cp_ifile_inode));
-
- DPRINTF(CPFILE, ("%s: cn:%#jx ctime:%#jx nblk:%#jx\n",
- __func__, (uintmax_t)cn, (uintmax_t)cnp->cp_create,
- (uintmax_t)nblocks));
-
- brelse(bp);
- return (0);
-}
-
-static int
-nandfs_cp_mounted(struct nandfs_device *nandfsdev, uint64_t cno)
-{
- struct nandfsmount *nmp;
- int mounted = 0;
-
- mtx_lock(&nandfsdev->nd_mutex);
- /* No double-mounting of the same checkpoint */
- STAILQ_FOREACH(nmp, &nandfsdev->nd_mounts, nm_next_mount) {
- if (nmp->nm_mount_args.cpno == cno) {
- mounted = 1;
- break;
- }
- }
- mtx_unlock(&nandfsdev->nd_mutex);
-
- return (mounted);
-}
-
-static int
-nandfs_cp_set_snapshot(struct nandfs_node *cp_node, uint64_t cno)
-{
- struct nandfs_device *fsdev;
- struct nandfs_cpfile_header *cnh;
- struct nandfs_checkpoint *cnp;
- struct nandfs_snapshot_list *list;
- struct buf *bp;
- uint64_t blk, prev_blk, offset;
- uint64_t curr, prev;
- int error;
-
- fsdev = cp_node->nn_nandfsdev;
-
- /* Get snapshot data */
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- if (cnp->cp_flags & NANDFS_CHECKPOINT_INVALID) {
- brelse(bp);
- return (ENOENT);
- }
- if ((cnp->cp_flags & NANDFS_CHECKPOINT_SNAPSHOT)) {
- brelse(bp);
- return (EINVAL);
- }
-
- brelse(bp);
- /* Get list from header */
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- list = &cnh->ch_snapshot_list;
- prev = list->ssl_prev;
- brelse(bp);
- prev_blk = ~(0);
- curr = 0;
- while (prev > cno) {
- curr = prev;
- nandfs_checkpoint_blk_offset(fsdev, prev, &prev_blk, &offset);
- error = nandfs_bread(cp_node, prev_blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- prev = list->ssl_prev;
- brelse(bp);
- }
-
- if (curr == 0) {
- nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- list = &cnh->ch_snapshot_list;
- } else {
- nandfs_checkpoint_blk_offset(fsdev, curr, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- }
-
- list->ssl_prev = cno;
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
-
- /* Update snapshot for cno */
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- list->ssl_prev = prev;
- list->ssl_next = curr;
- cnp->cp_flags |= NANDFS_CHECKPOINT_SNAPSHOT;
- nandfs_dirty_buf(bp, 1);
-
- if (prev == 0) {
- nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- list = &cnh->ch_snapshot_list;
- } else {
- /* Update snapshot list for prev */
- nandfs_checkpoint_blk_offset(fsdev, prev, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- }
- list->ssl_next = cno;
- nandfs_dirty_buf(bp, 1);
-
- /* Update header */
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- cnh->ch_nsnapshots++;
- nandfs_dirty_buf(bp, 1);
-
- return (0);
-}
-
-static int
-nandfs_cp_clr_snapshot(struct nandfs_node *cp_node, uint64_t cno)
-{
- struct nandfs_device *fsdev;
- struct nandfs_cpfile_header *cnh;
- struct nandfs_checkpoint *cnp;
- struct nandfs_snapshot_list *list;
- struct buf *bp;
- uint64_t blk, offset, snapshot_cnt;
- uint64_t next, prev;
- int error;
-
- fsdev = cp_node->nn_nandfsdev;
-
- /* Get snapshot data */
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- if (cnp->cp_flags & NANDFS_CHECKPOINT_INVALID) {
- brelse(bp);
- return (ENOENT);
- }
- if (!(cnp->cp_flags & NANDFS_CHECKPOINT_SNAPSHOT)) {
- brelse(bp);
- return (EINVAL);
- }
-
- list = &cnp->cp_snapshot_list;
- next = list->ssl_next;
- prev = list->ssl_prev;
- brelse(bp);
-
- /* Get previous snapshot */
- if (prev != 0) {
- nandfs_checkpoint_blk_offset(fsdev, prev, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- } else {
- nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- list = &cnh->ch_snapshot_list;
- }
-
- list->ssl_next = next;
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
- /* Get next snapshot */
- if (next != 0) {
- nandfs_checkpoint_blk_offset(fsdev, next, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- } else {
- nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- list = &cnh->ch_snapshot_list;
- }
- list->ssl_prev = prev;
- nandfs_dirty_buf(bp, 1);
-
- /* Update snapshot list for cno */
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- error = nandfs_bread(cp_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- list = &cnp->cp_snapshot_list;
- list->ssl_prev = 0;
- list->ssl_next = 0;
- cnp->cp_flags &= !NANDFS_CHECKPOINT_SNAPSHOT;
- nandfs_dirty_buf(bp, 1);
-
- /* Update header */
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- snapshot_cnt = cnh->ch_nsnapshots;
- snapshot_cnt--;
- cnh->ch_nsnapshots = snapshot_cnt;
- nandfs_dirty_buf(bp, 1);
-
- return (0);
-}
-
-int
-nandfs_chng_cpmode(struct nandfs_node *node, struct nandfs_cpmode *ncpm)
-{
- struct nandfs_device *fsdev;
- uint64_t cno = ncpm->ncpm_cno;
- int mode = ncpm->ncpm_mode;
- int ret;
-
- fsdev = node->nn_nandfsdev;
- VOP_LOCK(NTOV(node), LK_EXCLUSIVE);
- switch (mode) {
- case NANDFS_CHECKPOINT:
- if (nandfs_cp_mounted(fsdev, cno)) {
- ret = EBUSY;
- } else
- ret = nandfs_cp_clr_snapshot(node, cno);
- break;
- case NANDFS_SNAPSHOT:
- ret = nandfs_cp_set_snapshot(node, cno);
- break;
- default:
- ret = EINVAL;
- break;
- }
- VOP_UNLOCK(NTOV(node), 0);
-
- return (ret);
-}
-
-static void
-nandfs_cpinfo_fill(struct nandfs_checkpoint *cnp, struct nandfs_cpinfo *nci)
-{
-
- nci->nci_flags = cnp->cp_flags;
- nci->nci_pad = 0;
- nci->nci_cno = cnp->cp_cno;
- nci->nci_create = cnp->cp_create;
- nci->nci_nblk_inc = cnp->cp_nblk_inc;
- nci->nci_blocks_count = cnp->cp_blocks_count;
- nci->nci_next = cnp->cp_snapshot_list.ssl_next;
- DPRINTF(CPFILE, ("%s: cn:%#jx ctime:%#jx\n",
- __func__, (uintmax_t)cnp->cp_cno,
- (uintmax_t)cnp->cp_create));
-}
-
-static int
-nandfs_get_cpinfo_cp(struct nandfs_node *node, uint64_t cno,
- struct nandfs_cpinfo *nci, uint32_t mnmembs, uint32_t *nmembs)
-{
- struct nandfs_device *fsdev;
- struct buf *bp;
- uint64_t blk, offset, last_cno, i;
- uint16_t remaining;
- int error;
-#ifdef INVARIANTS
- uint64_t testblk, testoffset;
-#endif
-
- if (cno == 0) {
- return (ENOENT);
- }
-
- if (mnmembs < 1) {
- return (EINVAL);
- }
-
- fsdev = node->nn_nandfsdev;
- last_cno = fsdev->nd_last_cno;
- DPRINTF(CPFILE, ("%s: cno:%#jx mnmembs: %#jx last:%#jx\n", __func__,
- (uintmax_t)cno, (uintmax_t)mnmembs,
- (uintmax_t)fsdev->nd_last_cno));
-
- /*
- * do {
- * get block
- * read checkpoints until we hit last checkpoint, end of block or
- * requested number
- * } while (last read checkpoint <= last checkpoint on fs &&
- * read checkpoints < request number);
- */
- *nmembs = i = 0;
- do {
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- remaining = nandfs_checkpoint_blk_remaining(fsdev, cno,
- blk, offset);
- error = nandfs_bread(node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- while (cno <= last_cno && i < mnmembs && remaining) {
-#ifdef INVARIANTS
- nandfs_checkpoint_blk_offset(fsdev, cno, &testblk,
- &testoffset);
- KASSERT(testblk == blk, ("testblk != blk"));
- KASSERT(testoffset == offset, ("testoffset != offset"));
-#endif
- DPRINTF(CPFILE, ("%s: cno %#jx\n", __func__,
- (uintmax_t)cno));
-
- nandfs_cpinfo_fill((struct nandfs_checkpoint *)
- (bp->b_data + offset), nci);
- offset += nandfs_checkpoint_size(fsdev);
- i++;
- nci++;
- cno++;
- (*nmembs)++;
- remaining--;
- }
- brelse(bp);
- } while (cno <= last_cno && i < mnmembs);
-
- return (0);
-}
-
-static int
-nandfs_get_cpinfo_sp(struct nandfs_node *node, uint64_t cno,
- struct nandfs_cpinfo *nci, uint32_t mnmembs, uint32_t *nmembs)
-{
- struct nandfs_checkpoint *cnp;
- struct nandfs_cpfile_header *cnh;
- struct nandfs_device *fsdev;
- struct buf *bp = NULL;
- uint64_t curr = 0;
- uint64_t blk, offset, curr_cno;
- uint32_t flag;
- int i, error;
-
- if (cno == 0 || cno == ~(0))
- return (ENOENT);
-
- fsdev = node->nn_nandfsdev;
- curr_cno = cno;
-
- if (nmembs)
- *nmembs = 0;
- if (curr_cno == 1) {
- /* Get list from header */
- error = nandfs_bread(node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- curr_cno = cnh->ch_snapshot_list.ssl_next;
- brelse(bp);
- bp = NULL;
-
- /* No snapshots */
- if (curr_cno == 0)
- return (0);
- }
-
- for (i = 0; i < mnmembs; i++, nci++) {
- nandfs_checkpoint_blk_offset(fsdev, curr_cno, &blk, &offset);
- if (i == 0 || curr != blk) {
- if (bp)
- brelse(bp);
- error = nandfs_bread(node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (ENOENT);
- }
- curr = blk;
- }
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- flag = cnp->cp_flags;
- if (!(flag & NANDFS_CHECKPOINT_SNAPSHOT) ||
- (flag & NANDFS_CHECKPOINT_INVALID))
- break;
-
- nci->nci_flags = flag;
- nci->nci_pad = 0;
- nci->nci_cno = cnp->cp_cno;
- nci->nci_create = cnp->cp_create;
- nci->nci_nblk_inc = cnp->cp_nblk_inc;
- nci->nci_blocks_count = cnp->cp_blocks_count;
- nci->nci_next = cnp->cp_snapshot_list.ssl_next;
- if (nmembs)
- (*nmembs)++;
-
- curr_cno = nci->nci_next;
- if (!curr_cno)
- break;
- }
-
- brelse(bp);
-
- return (0);
-}
-
-int
-nandfs_get_cpinfo(struct nandfs_node *node, uint64_t cno, uint16_t flags,
- struct nandfs_cpinfo *nci, uint32_t nmembs, uint32_t *nnmembs)
-{
- int error;
-
- VOP_LOCK(NTOV(node), LK_EXCLUSIVE);
- switch (flags) {
- case NANDFS_CHECKPOINT:
- error = nandfs_get_cpinfo_cp(node, cno, nci, nmembs, nnmembs);
- break;
- case NANDFS_SNAPSHOT:
- error = nandfs_get_cpinfo_sp(node, cno, nci, nmembs, nnmembs);
- break;
- default:
- error = EINVAL;
- break;
- }
- VOP_UNLOCK(NTOV(node), 0);
-
- return (error);
-}
-
-int
-nandfs_get_cpinfo_ioctl(struct nandfs_node *node, struct nandfs_argv *nargv)
-{
- struct nandfs_cpinfo *nci;
- uint64_t cno = nargv->nv_index;
- void *buf = (void *)((uintptr_t)nargv->nv_base);
- uint16_t flags = nargv->nv_flags;
- uint32_t nmembs = 0;
- int error;
-
- if (nargv->nv_nmembs > NANDFS_CPINFO_MAX)
- return (EINVAL);
-
- nci = malloc(sizeof(struct nandfs_cpinfo) * nargv->nv_nmembs,
- M_NANDFSTEMP, M_WAITOK | M_ZERO);
-
- error = nandfs_get_cpinfo(node, cno, flags, nci, nargv->nv_nmembs, &nmembs);
-
- if (error == 0) {
- nargv->nv_nmembs = nmembs;
- error = copyout(nci, buf,
- sizeof(struct nandfs_cpinfo) * nmembs);
- }
-
- free(nci, M_NANDFSTEMP);
- return (error);
-}
-
-int
-nandfs_delete_cp(struct nandfs_node *node, uint64_t start, uint64_t end)
-{
- struct nandfs_checkpoint *cnp;
- struct nandfs_device *fsdev;
- struct buf *bp;
- uint64_t cno = start, blk, offset;
- int error;
-
- DPRINTF(CPFILE, ("%s: delete cno %jx-%jx\n", __func__, start, end));
- VOP_LOCK(NTOV(node), LK_EXCLUSIVE);
- fsdev = node->nn_nandfsdev;
- for (cno = start; cno <= end; cno++) {
- if (!cno)
- continue;
-
- nandfs_checkpoint_blk_offset(fsdev, cno, &blk, &offset);
- error = nandfs_bread(node, blk, NOCRED, 0, &bp);
- if (error) {
- VOP_UNLOCK(NTOV(node), 0);
- brelse(bp);
- return (error);
- }
-
- cnp = (struct nandfs_checkpoint *)(bp->b_data + offset);
- if (cnp->cp_flags & NANDFS_CHECKPOINT_SNAPSHOT) {
- brelse(bp);
- VOP_UNLOCK(NTOV(node), 0);
- return (0);
- }
-
- cnp->cp_flags |= NANDFS_CHECKPOINT_INVALID;
-
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
- }
- VOP_UNLOCK(NTOV(node), 0);
-
- return (0);
-}
-
-int
-nandfs_make_snap(struct nandfs_device *fsdev, uint64_t *cno)
-{
- struct nandfs_cpmode cpm;
- int error;
-
- *cno = cpm.ncpm_cno = fsdev->nd_last_cno;
- cpm.ncpm_mode = NANDFS_SNAPSHOT;
- error = nandfs_chng_cpmode(fsdev->nd_cp_node, &cpm);
- return (error);
-}
-
-int
-nandfs_delete_snap(struct nandfs_device *fsdev, uint64_t cno)
-{
- struct nandfs_cpmode cpm;
- int error;
-
- cpm.ncpm_cno = cno;
- cpm.ncpm_mode = NANDFS_CHECKPOINT;
- error = nandfs_chng_cpmode(fsdev->nd_cp_node, &cpm);
- return (error);
-}
-
-int nandfs_get_cpstat(struct nandfs_node *cp_node, struct nandfs_cpstat *ncp)
-{
- struct nandfs_device *fsdev;
- struct nandfs_cpfile_header *cnh;
- struct buf *bp;
- int error;
-
- VOP_LOCK(NTOV(cp_node), LK_EXCLUSIVE);
- fsdev = cp_node->nn_nandfsdev;
-
- /* Get header */
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (error);
- }
- cnh = (struct nandfs_cpfile_header *) bp->b_data;
- ncp->ncp_cno = fsdev->nd_last_cno;
- ncp->ncp_ncps = cnh->ch_ncheckpoints;
- ncp->ncp_nss = cnh->ch_nsnapshots;
- DPRINTF(CPFILE, ("%s: cno:%#jx ncps:%#jx nss:%#jx\n",
- __func__, ncp->ncp_cno, ncp->ncp_ncps, ncp->ncp_nss));
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
-
- return (0);
-}
diff --git a/sys/fs/nandfs/nandfs_dat.c b/sys/fs/nandfs/nandfs_dat.c
deleted file mode 100644
index e81a117589f8..000000000000
--- a/sys/fs/nandfs/nandfs_dat.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-int
-nandfs_vblock_alloc(struct nandfs_device *nandfsdev, nandfs_daddr_t *vblock)
-{
- struct nandfs_node *dat;
- struct nandfs_mdt *mdt;
- struct nandfs_alloc_request req;
- struct nandfs_dat_entry *dat_entry;
- uint64_t start;
- uint32_t entry;
- int locked, error;
-
- dat = nandfsdev->nd_dat_node;
- mdt = &nandfsdev->nd_dat_mdt;
- start = nandfsdev->nd_last_cno + 1;
-
- locked = NANDFS_VOP_ISLOCKED(NTOV(dat));
- if (!locked)
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- req.entrynum = 0;
-
- /* Alloc vblock number */
- error = nandfs_find_free_entry(mdt, dat, &req);
- if (error) {
- nandfs_error("%s: cannot find free vblk entry\n",
- __func__);
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
- }
-
- /* Read/create buffer */
- error = nandfs_get_entry_block(mdt, dat, &req, &entry, 1);
- if (error) {
- nandfs_error("%s: cannot get free vblk entry\n",
- __func__);
- nandfs_abort_entry(&req);
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
- }
-
- /* Fill out vblock data */
- dat_entry = (struct nandfs_dat_entry *) req.bp_entry->b_data;
- dat_entry[entry].de_start = start;
- dat_entry[entry].de_end = UINTMAX_MAX;
- dat_entry[entry].de_blocknr = 0;
-
- /* Commit allocation */
- error = nandfs_alloc_entry(mdt, &req);
- if (error) {
- nandfs_error("%s: cannot get free vblk entry\n",
- __func__);
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
- }
-
- /* Return allocated vblock */
- *vblock = req.entrynum;
- DPRINTF(DAT, ("%s: allocated vblock %#jx\n",
- __func__, (uintmax_t)*vblock));
-
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
-}
-
-int
-nandfs_vblock_assign(struct nandfs_device *nandfsdev, nandfs_daddr_t vblock,
- nandfs_lbn_t block)
-{
- struct nandfs_node *dat;
- struct nandfs_mdt *mdt;
- struct nandfs_alloc_request req;
- struct nandfs_dat_entry *dat_entry;
- uint32_t entry;
- int locked, error;
-
- dat = nandfsdev->nd_dat_node;
- mdt = &nandfsdev->nd_dat_mdt;
-
- locked = NANDFS_VOP_ISLOCKED(NTOV(dat));
- if (!locked)
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- req.entrynum = vblock;
-
- error = nandfs_get_entry_block(mdt, dat, &req, &entry, 0);
- if (!error) {
- dat_entry = (struct nandfs_dat_entry *) req.bp_entry->b_data;
- dat_entry[entry].de_blocknr = block;
-
- DPRINTF(DAT, ("%s: assing vblock %jx->%jx\n",
- __func__, (uintmax_t)vblock, (uintmax_t)block));
-
- /*
- * It is mostly called from syncer() so
- * we want to force making buf dirty
- */
- error = nandfs_dirty_buf(req.bp_entry, 1);
- }
-
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
-
- return (error);
-}
-
-int
-nandfs_vblock_end(struct nandfs_device *nandfsdev, nandfs_daddr_t vblock)
-{
- struct nandfs_node *dat;
- struct nandfs_mdt *mdt;
- struct nandfs_alloc_request req;
- struct nandfs_dat_entry *dat_entry;
- uint64_t end;
- uint32_t entry;
- int locked, error;
-
- dat = nandfsdev->nd_dat_node;
- mdt = &nandfsdev->nd_dat_mdt;
- end = nandfsdev->nd_last_cno;
-
- locked = NANDFS_VOP_ISLOCKED(NTOV(dat));
- if (!locked)
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- req.entrynum = vblock;
-
- error = nandfs_get_entry_block(mdt, dat, &req, &entry, 0);
- if (!error) {
- dat_entry = (struct nandfs_dat_entry *) req.bp_entry->b_data;
- dat_entry[entry].de_end = end;
- DPRINTF(DAT, ("%s: end vblock %#jx at checkpoint %#jx\n",
- __func__, (uintmax_t)vblock, (uintmax_t)end));
-
- /*
- * It is mostly called from syncer() so
- * we want to force making buf dirty
- */
- error = nandfs_dirty_buf(req.bp_entry, 1);
- }
-
- if (!locked)
- VOP_UNLOCK(NTOV(dat), 0);
-
- return (error);
-}
-
-int
-nandfs_vblock_free(struct nandfs_device *nandfsdev, nandfs_daddr_t vblock)
-{
- struct nandfs_node *dat;
- struct nandfs_mdt *mdt;
- struct nandfs_alloc_request req;
- int error;
-
- dat = nandfsdev->nd_dat_node;
- mdt = &nandfsdev->nd_dat_mdt;
-
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- req.entrynum = vblock;
-
- error = nandfs_find_entry(mdt, dat, &req);
- if (!error) {
- DPRINTF(DAT, ("%s: vblk %#jx\n", __func__, (uintmax_t)vblock));
- nandfs_free_entry(mdt, &req);
- }
-
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
-}
-
-int
-nandfs_get_dat_vinfo_ioctl(struct nandfs_device *nandfsdev, struct nandfs_argv *nargv)
-{
- struct nandfs_vinfo *vinfo;
- size_t size;
- int error;
-
- if (nargv->nv_nmembs > NANDFS_VINFO_MAX)
- return (EINVAL);
-
- size = sizeof(struct nandfs_vinfo) * nargv->nv_nmembs;
- vinfo = malloc(size, M_NANDFSTEMP, M_WAITOK|M_ZERO);
-
- error = copyin((void *)(uintptr_t)nargv->nv_base, vinfo, size);
- if (error) {
- free(vinfo, M_NANDFSTEMP);
- return (error);
- }
-
- error = nandfs_get_dat_vinfo(nandfsdev, vinfo, nargv->nv_nmembs);
- if (error == 0)
- error = copyout(vinfo, (void *)(uintptr_t)nargv->nv_base, size);
- free(vinfo, M_NANDFSTEMP);
- return (error);
-}
-
-int
-nandfs_get_dat_vinfo(struct nandfs_device *nandfsdev, struct nandfs_vinfo *vinfo,
- uint32_t nmembs)
-{
- struct nandfs_node *dat;
- struct nandfs_mdt *mdt;
- struct nandfs_alloc_request req;
- struct nandfs_dat_entry *dat_entry;
- uint32_t i, idx;
- int error = 0;
-
- dat = nandfsdev->nd_dat_node;
- mdt = &nandfsdev->nd_dat_mdt;
-
- DPRINTF(DAT, ("%s: nmembs %#x\n", __func__, nmembs));
-
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
-
- for (i = 0; i < nmembs; i++) {
- req.entrynum = vinfo[i].nvi_vblocknr;
-
- error = nandfs_get_entry_block(mdt, dat,&req, &idx, 0);
- if (error)
- break;
-
- dat_entry = ((struct nandfs_dat_entry *) req.bp_entry->b_data);
- vinfo[i].nvi_start = dat_entry[idx].de_start;
- vinfo[i].nvi_end = dat_entry[idx].de_end;
- vinfo[i].nvi_blocknr = dat_entry[idx].de_blocknr;
-
- DPRINTF(DAT, ("%s: vinfo: %jx[%jx-%jx]->%jx\n",
- __func__, vinfo[i].nvi_vblocknr, vinfo[i].nvi_start,
- vinfo[i].nvi_end, vinfo[i].nvi_blocknr));
-
- brelse(req.bp_entry);
- }
-
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
-}
-
-int
-nandfs_get_dat_bdescs_ioctl(struct nandfs_device *nffsdev,
- struct nandfs_argv *nargv)
-{
- struct nandfs_bdesc *bd;
- size_t size;
- int error;
-
- size = nargv->nv_nmembs * sizeof(struct nandfs_bdesc);
- bd = malloc(size, M_NANDFSTEMP, M_WAITOK);
- error = copyin((void *)(uintptr_t)nargv->nv_base, bd, size);
- if (error) {
- free(bd, M_NANDFSTEMP);
- return (error);
- }
-
- error = nandfs_get_dat_bdescs(nffsdev, bd, nargv->nv_nmembs);
-
- if (error == 0)
- error = copyout(bd, (void *)(uintptr_t)nargv->nv_base, size);
-
- free(bd, M_NANDFSTEMP);
- return (error);
-}
-
-int
-nandfs_get_dat_bdescs(struct nandfs_device *nffsdev, struct nandfs_bdesc *bd,
- uint32_t nmembs)
-{
- struct nandfs_node *dat_node;
- uint64_t map;
- uint32_t i;
- int error = 0;
-
- dat_node = nffsdev->nd_dat_node;
-
- VOP_LOCK(NTOV(dat_node), LK_EXCLUSIVE);
-
- for (i = 0; i < nmembs; i++) {
- DPRINTF(CLEAN,
- ("%s: bd ino:%#jx oblk:%#jx blocknr:%#jx off:%#jx\n",
- __func__, (uintmax_t)bd[i].bd_ino,
- (uintmax_t)bd[i].bd_oblocknr, (uintmax_t)bd[i].bd_blocknr,
- (uintmax_t)bd[i].bd_offset));
-
- error = nandfs_bmap_lookup(dat_node, bd[i].bd_offset, &map);
- if (error)
- break;
- bd[i].bd_blocknr = map;
- }
-
- VOP_UNLOCK(NTOV(dat_node), 0);
- return (error);
-}
diff --git a/sys/fs/nandfs/nandfs_dir.c b/sys/fs/nandfs/nandfs_dir.c
deleted file mode 100644
index 404edecfaa08..000000000000
--- a/sys/fs/nandfs/nandfs_dir.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_subr.c,v 1.4 2009/07/29 17:06:57 reinoud
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/namei.h>
-#include <sys/kernel.h>
-#include <sys/stat.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/signalvar.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/lockf.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-
-#include "nandfs_mount.h"
-#include "nandfs.h"
-#include "nandfs_subr.h"
-
-int
-nandfs_add_dirent(struct vnode *dvp, uint64_t ino, char *nameptr, long namelen,
- uint8_t type)
-{
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfs_dir_entry *dirent, *pdirent;
- uint32_t blocksize = dir_node->nn_nandfsdev->nd_blocksize;
- uint64_t filesize = dir_node->nn_inode.i_size;
- uint64_t inode_blks = dir_node->nn_inode.i_blocks;
- uint32_t off, rest;
- uint8_t *pos;
- struct buf *bp;
- int error;
-
- pdirent = NULL;
- bp = NULL;
- if (inode_blks) {
- error = nandfs_bread(dir_node, inode_blks - 1, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- pos = bp->b_data;
- off = 0;
- while (off < blocksize) {
- pdirent = (struct nandfs_dir_entry *) (pos + off);
- if (!pdirent->rec_len) {
- pdirent = NULL;
- break;
- }
- off += pdirent->rec_len;
- }
-
- if (pdirent)
- rest = pdirent->rec_len -
- NANDFS_DIR_REC_LEN(pdirent->name_len);
- else
- rest = blocksize;
-
- if (rest < NANDFS_DIR_REC_LEN(namelen)) {
- /* Do not update pdirent as new block is created */
- pdirent = NULL;
- brelse(bp);
- /* Set to NULL to create new */
- bp = NULL;
- filesize += rest;
- }
- }
-
- /* If no bp found create new */
- if (!bp) {
- error = nandfs_bcreate(dir_node, inode_blks, NOCRED, 0, &bp);
- if (error)
- return (error);
- off = 0;
- pos = bp->b_data;
- }
-
- /* Modify pdirent if exists */
- if (pdirent) {
- DPRINTF(LOOKUP, ("modify pdirent %p\n", pdirent));
- /* modify last de */
- off -= pdirent->rec_len;
- pdirent->rec_len =
- NANDFS_DIR_REC_LEN(pdirent->name_len);
- off += pdirent->rec_len;
- }
-
- /* Create new dirent */
- dirent = (struct nandfs_dir_entry *) (pos + off);
- dirent->rec_len = blocksize - off;
- dirent->inode = ino;
- dirent->name_len = namelen;
- memset(dirent->name, 0, NANDFS_DIR_NAME_LEN(namelen));
- memcpy(dirent->name, nameptr, namelen);
- dirent->file_type = type;
-
- filesize += NANDFS_DIR_REC_LEN(dirent->name_len);
-
- DPRINTF(LOOKUP, ("create dir_entry '%.*s' at %p with size %x "
- "new filesize: %jx\n",
- (int)namelen, dirent->name, dirent, dirent->rec_len,
- (uintmax_t)filesize));
-
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
- dir_node->nn_inode.i_size = filesize;
- dir_node->nn_flags |= IN_CHANGE | IN_UPDATE;
- vnode_pager_setsize(dvp, filesize);
-
- return (0);
-}
-
-int
-nandfs_remove_dirent(struct vnode *dvp, struct nandfs_node *node,
- struct componentname *cnp)
-{
- struct nandfs_node *dir_node;
- struct nandfs_dir_entry *dirent, *pdirent;
- struct buf *bp;
- uint64_t filesize, blocknr, ino, offset;
- uint32_t blocksize, limit, off;
- uint16_t newsize;
- uint8_t *pos;
- int error, found;
-
- dir_node = VTON(dvp);
- filesize = dir_node->nn_inode.i_size;
- if (!filesize)
- return (0);
-
- if (node) {
- offset = node->nn_diroff;
- ino = node->nn_ino;
- } else {
- offset = dir_node->nn_diroff;
- ino = NANDFS_WHT_INO;
- }
-
- dirent = pdirent = NULL;
- blocksize = dir_node->nn_nandfsdev->nd_blocksize;
- blocknr = offset / blocksize;
-
- DPRINTF(LOOKUP, ("rm direntry dvp %p node %p ino %#jx at off %#jx\n",
- dvp, node, (uintmax_t)ino, (uintmax_t)offset));
-
- error = nandfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- pos = bp->b_data;
- off = 0;
- found = 0;
- limit = offset % blocksize;
- pdirent = (struct nandfs_dir_entry *) bp->b_data;
- while (off <= limit) {
- dirent = (struct nandfs_dir_entry *) (pos + off);
-
- if ((off == limit) &&
- (dirent->inode == ino)) {
- found = 1;
- break;
- }
- if (dirent->inode != 0)
- pdirent = dirent;
- off += dirent->rec_len;
- }
-
- if (!found) {
- nandfs_error("cannot find entry to remove");
- brelse(bp);
- return (error);
- }
- DPRINTF(LOOKUP,
- ("rm dirent ino %#jx at %#x with size %#x\n",
- (uintmax_t)dirent->inode, off, dirent->rec_len));
-
- newsize = (uintptr_t)dirent - (uintptr_t)pdirent;
- newsize += dirent->rec_len;
- pdirent->rec_len = newsize;
- dirent->inode = 0;
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
- dir_node->nn_flags |= IN_CHANGE | IN_UPDATE;
- /* If last one modify filesize */
- if ((offset + NANDFS_DIR_REC_LEN(dirent->name_len)) == filesize) {
- filesize = blocknr * blocksize +
- ((uintptr_t)pdirent - (uintptr_t)pos) +
- NANDFS_DIR_REC_LEN(pdirent->name_len);
- dir_node->nn_inode.i_size = filesize;
- }
-
- return (0);
-}
-
-int
-nandfs_update_parent_dir(struct vnode *dvp, uint64_t newparent)
-{
- struct nandfs_dir_entry *dirent;
- struct nandfs_node *dir_node;
- struct buf *bp;
- int error;
-
- dir_node = VTON(dvp);
- error = nandfs_bread(dir_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- dirent = (struct nandfs_dir_entry *)bp->b_data;
- dirent->inode = newparent;
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
- return (0);
-}
-
-int
-nandfs_update_dirent(struct vnode *dvp, struct nandfs_node *fnode,
- struct nandfs_node *tnode)
-{
- struct nandfs_node *dir_node;
- struct nandfs_dir_entry *dirent;
- struct buf *bp;
- uint64_t file_size, blocknr;
- uint32_t blocksize, off;
- uint8_t *pos;
- int error;
-
- dir_node = VTON(dvp);
- file_size = dir_node->nn_inode.i_size;
- if (!file_size)
- return (0);
-
- DPRINTF(LOOKUP,
- ("chg direntry dvp %p ino %#jx to in %#jx at off %#jx\n",
- dvp, (uintmax_t)tnode->nn_ino, (uintmax_t)fnode->nn_ino,
- (uintmax_t)tnode->nn_diroff));
-
- blocksize = dir_node->nn_nandfsdev->nd_blocksize;
- blocknr = tnode->nn_diroff / blocksize;
- off = tnode->nn_diroff % blocksize;
- error = nandfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- pos = bp->b_data;
- dirent = (struct nandfs_dir_entry *) (pos + off);
- KASSERT((dirent->inode == tnode->nn_ino),
- ("direntry mismatch"));
-
- dirent->inode = fnode->nn_ino;
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
-
- return (0);
-}
-
-int
-nandfs_init_dir(struct vnode *dvp, uint64_t ino, uint64_t parent_ino)
-{
-
- if (nandfs_add_dirent(dvp, parent_ino, "..", 2, DT_DIR) ||
- nandfs_add_dirent(dvp, ino, ".", 1, DT_DIR)) {
- nandfs_error("%s: cannot initialize dir ino:%jd(pino:%jd)\n",
- __func__, ino, parent_ino);
- return (-1);
- }
- return (0);
-}
diff --git a/sys/fs/nandfs/nandfs_fs.h b/sys/fs/nandfs/nandfs_fs.h
deleted file mode 100644
index 9cb440ebcb90..000000000000
--- a/sys/fs/nandfs/nandfs_fs.h
+++ /dev/null
@@ -1,567 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Original definitions written by Koji Sato <koji@osrg.net>
- * and Ryusuke Konishi <ryusuke@osrg.net>
- * From: NetBSD: nandfs_fs.h,v 1.1 2009/07/18 16:31:42 reinoud
- *
- * $FreeBSD$
- */
-
-#ifndef _NANDFS_FS_H
-#define _NANDFS_FS_H
-
-#include <sys/uuid.h>
-
-#define MNINDIR(fsdev) ((fsdev)->nd_blocksize / sizeof(nandfs_daddr_t))
-
-/*
- * Inode structure. There are a few dedicated inode numbers that are
- * defined here first.
- */
-#define NANDFS_WHT_INO 1 /* Whiteout ino */
-#define NANDFS_ROOT_INO 2 /* Root file inode */
-#define NANDFS_DAT_INO 3 /* DAT file */
-#define NANDFS_CPFILE_INO 4 /* checkpoint file */
-#define NANDFS_SUFILE_INO 5 /* segment usage file */
-#define NANDFS_IFILE_INO 6 /* ifile */
-#define NANDFS_GC_INO 7 /* Cleanerd node */
-#define NANDFS_ATIME_INO 8 /* Atime file (reserved) */
-#define NANDFS_XATTR_INO 9 /* Xattribute file (reserved) */
-#define NANDFS_SKETCH_INO 10 /* Sketch file (obsolete) */
-#define NANDFS_USER_INO 11 /* First user's file inode number */
-
-#define NANDFS_SYS_NODE(ino) \
- (((ino) >= NANDFS_DAT_INO) && ((ino) <= NANDFS_GC_INO))
-
-#define NANDFS_NDADDR 12 /* Direct addresses in inode. */
-#define NANDFS_NIADDR 3 /* Indirect addresses in inode. */
-
-typedef int64_t nandfs_daddr_t;
-typedef int64_t nandfs_lbn_t;
-
-struct nandfs_inode {
- uint64_t i_blocks; /* 0: size in device blocks */
- uint64_t i_size; /* 8: size in bytes */
- uint64_t i_ctime; /* 16: creation time in seconds */
- uint64_t i_mtime; /* 24: modification time in seconds part*/
- uint32_t i_ctime_nsec; /* 32: creation time nanoseconds part */
- uint32_t i_mtime_nsec; /* 36: modification time in nanoseconds */
- uint32_t i_uid; /* 40: user id */
- uint32_t i_gid; /* 44: group id */
- uint16_t i_mode; /* 48: file mode */
- uint16_t i_links_count; /* 50: number of references to the inode*/
- uint32_t i_flags; /* 52: NANDFS_*_FL flags */
- nandfs_daddr_t i_special; /* 56: special */
- nandfs_daddr_t i_db[NANDFS_NDADDR]; /* 64: Direct disk blocks. */
- nandfs_daddr_t i_ib[NANDFS_NIADDR]; /* 160: Indirect disk blocks. */
- uint64_t i_xattr; /* 184: reserved for extended attributes*/
- uint32_t i_generation; /* 192: file generation for NFS */
- uint32_t i_pad[15]; /* 196: make it 64 bits aligned */
-};
-
-#ifdef _KERNEL
-CTASSERT(sizeof(struct nandfs_inode) == 256);
-#endif
-
-/*
- * Each checkpoint/snapshot has a super root.
- *
- * The super root holds the inodes of the three system files: `dat', `cp' and
- * 'su' files. All other FS state is defined by those.
- *
- * It is CRC checksum'ed and time stamped.
- */
-
-struct nandfs_super_root {
- uint32_t sr_sum; /* check-sum */
- uint16_t sr_bytes; /* byte count of this structure */
- uint16_t sr_flags; /* reserved for flags */
- uint64_t sr_nongc_ctime; /* timestamp, not for cleaner(?) */
- struct nandfs_inode sr_dat; /* DAT, virt->phys translation inode */
- struct nandfs_inode sr_cpfile; /* CP, checkpoints inode */
- struct nandfs_inode sr_sufile; /* SU, segment usage inode */
-};
-
-#define NANDFS_SR_MDT_OFFSET(inode_size, i) \
- ((uint32_t)&((struct nandfs_super_root *)0)->sr_dat + \
- (inode_size) * (i))
-
-#define NANDFS_SR_DAT_OFFSET(inode_size) NANDFS_SR_MDT_OFFSET(inode_size, 0)
-#define NANDFS_SR_CPFILE_OFFSET(inode_size) NANDFS_SR_MDT_OFFSET(inode_size, 1)
-#define NANDFS_SR_SUFILE_OFFSET(inode_size) NANDFS_SR_MDT_OFFSET(inode_size, 2)
-#define NANDFS_SR_BYTES (sizeof(struct nandfs_super_root))
-
-/*
- * The superblock describes the basic structure and mount history. It also
- * records some sizes of structures found on the disc for sanity checks.
- *
- * The superblock is stored at two places: NANDFS_SB_OFFSET_BYTES and
- * NANDFS_SB2_OFFSET_BYTES.
- */
-
-/* File system states stored on media in superblock's sbp->s_state */
-#define NANDFS_VALID_FS 0x0001 /* cleanly unmounted and all is ok */
-#define NANDFS_ERROR_FS 0x0002 /* there were errors detected, fsck */
-#define NANDFS_RESIZE_FS 0x0004 /* resize required, XXX unknown flag*/
-#define NANDFS_MOUNT_STATE_BITS "\20\1VALID_FS\2ERROR_FS\3RESIZE_FS"
-
-/*
- * Brief description of control structures:
- *
- * NANDFS_NFSAREAS first blocks contain fsdata and some amount of super blocks.
- * Simple round-robin policy is used in order to choose which block will
- * contain new super block.
- *
- * Simple case with 2 blocks:
- * 1: fsdata sblock1 [sblock3 [sblock5 ..]]
- * 2: fsdata sblock2 [sblock4 [sblock6 ..]]
- */
-struct nandfs_fsdata {
- uint16_t f_magic;
- uint16_t f_bytes;
-
- uint32_t f_sum; /* checksum of fsdata */
- uint32_t f_rev_level; /* major disk format revision */
-
- uint64_t f_ctime; /* creation time (execution time
- of newfs) */
- /* Block size represented as: blocksize = 1 << (f_log_block_size + 10) */
- uint32_t f_log_block_size;
-
- uint16_t f_inode_size; /* size of an inode */
- uint16_t f_dat_entry_size; /* size of a dat entry */
- uint16_t f_checkpoint_size; /* size of a checkpoint */
- uint16_t f_segment_usage_size; /* size of a segment usage */
-
- uint16_t f_sbbytes; /* byte count of CRC calculation
- for super blocks. s_reserved
- is excluded! */
-
- uint16_t f_errors; /* behaviour on detecting errors */
-
- uint32_t f_erasesize;
- uint64_t f_nsegments; /* number of segm. in filesystem */
- nandfs_daddr_t f_first_data_block; /* 1st seg disk block number */
- uint32_t f_blocks_per_segment; /* number of blocks per segment */
- uint32_t f_r_segments_percentage; /* reserved segments percentage */
-
- struct uuid f_uuid; /* 128-bit uuid for volume */
- char f_volume_name[16]; /* volume name */
- uint32_t f_pad[104];
-} __packed;
-
-#ifdef _KERNEL
-CTASSERT(sizeof(struct nandfs_fsdata) == 512);
-#endif
-
-struct nandfs_super_block {
- uint16_t s_magic; /* magic value for identification */
-
- uint32_t s_sum; /* check sum of super block */
-
- uint64_t s_last_cno; /* last checkpoint number */
- uint64_t s_last_pseg; /* addr part. segm. written last */
- uint64_t s_last_seq; /* seq.number of seg written last */
- uint64_t s_free_blocks_count; /* free blocks count */
-
- uint64_t s_mtime; /* mount time */
- uint64_t s_wtime; /* write time */
- uint16_t s_state; /* file system state */
-
- char s_last_mounted[64]; /* directory where last mounted */
-
- uint32_t s_c_interval; /* commit interval of segment */
- uint32_t s_c_block_max; /* threshold of data amount for
- the segment construction */
- uint32_t s_reserved[32]; /* padding to end of the block */
-} __packed;
-
-#ifdef _KERNEL
-CTASSERT(sizeof(struct nandfs_super_block) == 256);
-#endif
-
-#define NANDFS_FSDATA_MAGIC 0xf8da
-#define NANDFS_SUPER_MAGIC 0x8008
-
-#define NANDFS_NFSAREAS 4
-#define NANDFS_DATA_OFFSET_BYTES(esize) (NANDFS_NFSAREAS * (esize))
-
-#define NANDFS_SBLOCK_OFFSET_BYTES (sizeof(struct nandfs_fsdata))
-
-#define NANDFS_DEF_BLOCKSIZE 4096
-#define NANDFS_MIN_BLOCKSIZE 512
-
-#define NANDFS_DEF_ERASESIZE (2 << 16)
-
-#define NANDFS_MIN_SEGSIZE NANDFS_DEF_ERASESIZE
-
-#define NANDFS_CURRENT_REV 9 /* current major revision */
-
-#define NANDFS_FSDATA_CRC_BYTES offsetof(struct nandfs_fsdata, f_pad)
-/* Bytes count of super_block for CRC-calculation */
-#define NANDFS_SB_BYTES offsetof(struct nandfs_super_block, s_reserved)
-
-/* Maximal count of links to a file */
-#define NANDFS_LINK_MAX 32000
-
-/*
- * Structure of a directory entry.
- *
- * Note that they can't span blocks; the rec_len fills out.
- */
-
-#define NANDFS_NAME_LEN 255
-struct nandfs_dir_entry {
- uint64_t inode; /* inode number */
- uint16_t rec_len; /* directory entry length */
- uint8_t name_len; /* name length */
- uint8_t file_type;
- char name[NANDFS_NAME_LEN]; /* file name */
- char pad;
-};
-
-/*
- * NANDFS_DIR_PAD defines the directory entries boundaries
- *
- * NOTE: It must be a multiple of 8
- */
-#define NANDFS_DIR_PAD 8
-#define NANDFS_DIR_ROUND (NANDFS_DIR_PAD - 1)
-#define NANDFS_DIR_NAME_OFFSET (offsetof(struct nandfs_dir_entry, name))
-#define NANDFS_DIR_REC_LEN(name_len) \
- (((name_len) + NANDFS_DIR_NAME_OFFSET + NANDFS_DIR_ROUND) \
- & ~NANDFS_DIR_ROUND)
-#define NANDFS_DIR_NAME_LEN(name_len) \
- (NANDFS_DIR_REC_LEN(name_len) - NANDFS_DIR_NAME_OFFSET)
-
-/*
- * NiLFS/NANDFS devides the disc into fixed length segments. Each segment is
- * filled with one or more partial segments of variable lengths.
- *
- * Each partial segment has a segment summary header followed by updates of
- * files and optionally a super root.
- */
-
-/*
- * Virtual to physical block translation information. For data blocks it maps
- * logical block number bi_blkoff to virtual block nr bi_vblocknr. For non
- * datablocks it is the virtual block number assigned to an indirect block
- * and has no bi_blkoff. The physical block number is the next
- * available data block in the partial segment after all the binfo's.
- */
-struct nandfs_binfo_v {
- uint64_t bi_ino; /* file's inode */
- uint64_t bi_vblocknr; /* assigned virtual block number */
- uint64_t bi_blkoff; /* for file's logical block number */
-};
-
-/*
- * DAT allocation. For data blocks just the logical block number that maps on
- * the next available data block in the partial segment after the binfo's.
- */
-struct nandfs_binfo_dat {
- uint64_t bi_ino;
- uint64_t bi_blkoff; /* DAT file's logical block number */
- uint8_t bi_level; /* whether this is meta block */
- uint8_t bi_pad[7];
-};
-
-#ifdef _KERNEL
-CTASSERT(sizeof(struct nandfs_binfo_v) == sizeof(struct nandfs_binfo_dat));
-#endif
-
-/* Convenience union for both types of binfo's */
-union nandfs_binfo {
- struct nandfs_binfo_v bi_v;
- struct nandfs_binfo_dat bi_dat;
-};
-
-/* Indirect buffers path */
-struct nandfs_indir {
- nandfs_daddr_t in_lbn;
- int in_off;
-};
-
-/* The (partial) segment summary */
-struct nandfs_segment_summary {
- uint32_t ss_datasum; /* CRC of complete data block */
- uint32_t ss_sumsum; /* CRC of segment summary only */
- uint32_t ss_magic; /* magic to identify segment summary */
- uint16_t ss_bytes; /* size of segment summary structure */
- uint16_t ss_flags; /* NANDFS_SS_* flags */
- uint64_t ss_seq; /* sequence number of this segm. sum */
- uint64_t ss_create; /* creation timestamp in seconds */
- uint64_t ss_next; /* blocknumber of next segment */
- uint32_t ss_nblocks; /* number of blocks used by summary */
- uint32_t ss_nbinfos; /* number of binfo structures */
- uint32_t ss_sumbytes; /* total size of segment summary */
- uint32_t ss_pad;
- /* stream of binfo structures */
-};
-
-#define NANDFS_SEGSUM_MAGIC 0x8e680011 /* segment summary magic number */
-
-/* Segment summary flags */
-#define NANDFS_SS_LOGBGN 0x0001 /* begins a logical segment */
-#define NANDFS_SS_LOGEND 0x0002 /* ends a logical segment */
-#define NANDFS_SS_SR 0x0004 /* has super root */
-#define NANDFS_SS_SYNDT 0x0008 /* includes data only updates */
-#define NANDFS_SS_GC 0x0010 /* segment written for cleaner operation */
-#define NANDFS_SS_FLAG_BITS "\20\1LOGBGN\2LOGEND\3SR\4SYNDT\5GC"
-
-/* Segment summary constrains */
-#define NANDFS_SEG_MIN_BLOCKS 16 /* minimum number of blocks in a
- full segment */
-#define NANDFS_PSEG_MIN_BLOCKS 2 /* minimum number of blocks in a
- partial segment */
-#define NANDFS_MIN_NRSVSEGS 8 /* minimum number of reserved
- segments */
-
-/*
- * Structure of DAT/inode file.
- *
- * A DAT file is divided into groups. The maximum number of groups is the
- * number of block group descriptors that fit into one block; this descriptor
- * only gives the number of free entries in the associated group.
- *
- * Each group has a block sized bitmap indicating if an entry is taken or
- * empty. Each bit stands for a DAT entry.
- *
- * The inode file has exactly the same format only the entries are inode
- * entries.
- */
-
-struct nandfs_block_group_desc {
- uint32_t bg_nfrees; /* num. free entries in block group */
-};
-
-/* DAT entry in a super root's DAT file */
-struct nandfs_dat_entry {
- uint64_t de_blocknr; /* block number */
- uint64_t de_start; /* valid from checkpoint */
- uint64_t de_end; /* valid till checkpoint */
- uint64_t de_rsv; /* reserved for future use */
-};
-
-/*
- * Structure of CP file.
- *
- * A snapshot is just a checkpoint only it's protected against removal by the
- * cleaner. The snapshots are kept on a double linked list of checkpoints.
- */
-struct nandfs_snapshot_list {
- uint64_t ssl_next; /* checkpoint nr. forward */
- uint64_t ssl_prev; /* checkpoint nr. back */
-};
-
-/* Checkpoint entry structure */
-struct nandfs_checkpoint {
- uint32_t cp_flags; /* NANDFS_CHECKPOINT_* flags */
- uint32_t cp_checkpoints_count; /* ZERO, not used anymore? */
- struct nandfs_snapshot_list cp_snapshot_list; /* list of snapshots */
- uint64_t cp_cno; /* checkpoint number */
- uint64_t cp_create; /* creation timestamp */
- uint64_t cp_nblk_inc; /* number of blocks incremented */
- uint64_t cp_blocks_count; /* reserved (might be deleted) */
- struct nandfs_inode cp_ifile_inode; /* inode file inode */
-};
-
-/* Checkpoint flags */
-#define NANDFS_CHECKPOINT_SNAPSHOT 1
-#define NANDFS_CHECKPOINT_INVALID 2
-#define NANDFS_CHECKPOINT_SKETCH 4
-#define NANDFS_CHECKPOINT_MINOR 8
-#define NANDFS_CHECKPOINT_BITS "\20\1SNAPSHOT\2INVALID\3SKETCH\4MINOR"
-
-/* Header of the checkpoint file */
-struct nandfs_cpfile_header {
- uint64_t ch_ncheckpoints; /* number of checkpoints */
- uint64_t ch_nsnapshots; /* number of snapshots */
- struct nandfs_snapshot_list ch_snapshot_list; /* snapshot list */
-};
-
-#define NANDFS_CPFILE_FIRST_CHECKPOINT_OFFSET \
- ((sizeof(struct nandfs_cpfile_header) + \
- sizeof(struct nandfs_checkpoint) - 1) / \
- sizeof(struct nandfs_checkpoint))
-
-
-#define NANDFS_NOSEGMENT 0xffffffff
-
-/*
- * Structure of SU file.
- *
- * The segment usage file sums up how each of the segments are used. They are
- * indexed by their segment number.
- */
-
-/* Segment usage entry */
-struct nandfs_segment_usage {
- uint64_t su_lastmod; /* last modified timestamp */
- uint32_t su_nblocks; /* number of blocks in segment */
- uint32_t su_flags; /* NANDFS_SEGMENT_USAGE_* flags */
-};
-
-/* Segment usage flag */
-#define NANDFS_SEGMENT_USAGE_ACTIVE 1
-#define NANDFS_SEGMENT_USAGE_DIRTY 2
-#define NANDFS_SEGMENT_USAGE_ERROR 4
-#define NANDFS_SEGMENT_USAGE_GC 8
-#define NANDFS_SEGMENT_USAGE_BITS "\20\1ACTIVE\2DIRTY\3ERROR"
-
-/* Header of the segment usage file */
-struct nandfs_sufile_header {
- uint64_t sh_ncleansegs; /* number of segments marked clean */
- uint64_t sh_ndirtysegs; /* number of segments marked dirty */
- uint64_t sh_last_alloc; /* last allocated segment number */
-};
-
-#define NANDFS_SUFILE_FIRST_SEGMENT_USAGE_OFFSET \
- ((sizeof(struct nandfs_sufile_header) + \
- sizeof(struct nandfs_segment_usage) - 1) / \
- sizeof(struct nandfs_segment_usage))
-
-struct nandfs_seg_stat {
- uint64_t nss_nsegs;
- uint64_t nss_ncleansegs;
- uint64_t nss_ndirtysegs;
- uint64_t nss_ctime;
- uint64_t nss_nongc_ctime;
- uint64_t nss_prot_seq;
-};
-
-enum {
- NANDFS_CHECKPOINT,
- NANDFS_SNAPSHOT
-};
-
-#define NANDFS_CPINFO_MAX 512
-
-struct nandfs_cpinfo {
- uint32_t nci_flags;
- uint32_t nci_pad;
- uint64_t nci_cno;
- uint64_t nci_create;
- uint64_t nci_nblk_inc;
- uint64_t nci_blocks_count;
- uint64_t nci_next;
-};
-
-#define NANDFS_SEGMENTS_MAX 512
-
-struct nandfs_suinfo {
- uint64_t nsi_num;
- uint64_t nsi_lastmod;
- uint32_t nsi_blocks;
- uint32_t nsi_flags;
-};
-
-#define NANDFS_VINFO_MAX 512
-
-struct nandfs_vinfo {
- uint64_t nvi_ino;
- uint64_t nvi_vblocknr;
- uint64_t nvi_start;
- uint64_t nvi_end;
- uint64_t nvi_blocknr;
- int nvi_alive;
-};
-
-struct nandfs_cpmode {
- uint64_t ncpm_cno;
- uint32_t ncpm_mode;
- uint32_t ncpm_pad;
-};
-
-struct nandfs_argv {
- uint64_t nv_base;
- uint32_t nv_nmembs;
- uint16_t nv_size;
- uint16_t nv_flags;
- uint64_t nv_index;
-};
-
-struct nandfs_cpstat {
- uint64_t ncp_cno;
- uint64_t ncp_ncps;
- uint64_t ncp_nss;
-};
-
-struct nandfs_period {
- uint64_t p_start;
- uint64_t p_end;
-};
-
-struct nandfs_vdesc {
- uint64_t vd_ino;
- uint64_t vd_cno;
- uint64_t vd_vblocknr;
- struct nandfs_period vd_period;
- uint64_t vd_blocknr;
- uint64_t vd_offset;
- uint32_t vd_flags;
- uint32_t vd_pad;
-};
-
-struct nandfs_bdesc {
- uint64_t bd_ino;
- uint64_t bd_oblocknr;
- uint64_t bd_blocknr;
- uint64_t bd_offset;
- uint32_t bd_level;
- uint32_t bd_alive;
-};
-
-#ifndef _KERNEL
-#ifndef MNAMELEN
-#define MNAMELEN 1024
-#endif
-#endif
-
-struct nandfs_fsinfo {
- struct nandfs_fsdata fs_fsdata;
- struct nandfs_super_block fs_super;
- char fs_dev[MNAMELEN];
-};
-
-#define NANDFS_MAX_MOUNTS 65535
-
-#define NANDFS_IOCTL_GET_SUSTAT _IOR('N', 100, struct nandfs_seg_stat)
-#define NANDFS_IOCTL_CHANGE_CPMODE _IOWR('N', 101, struct nandfs_cpmode)
-#define NANDFS_IOCTL_GET_CPINFO _IOWR('N', 102, struct nandfs_argv)
-#define NANDFS_IOCTL_DELETE_CP _IOWR('N', 103, uint64_t[2])
-#define NANDFS_IOCTL_GET_CPSTAT _IOR('N', 104, struct nandfs_cpstat)
-#define NANDFS_IOCTL_GET_SUINFO _IOWR('N', 105, struct nandfs_argv)
-#define NANDFS_IOCTL_GET_VINFO _IOWR('N', 106, struct nandfs_argv)
-#define NANDFS_IOCTL_GET_BDESCS _IOWR('N', 107, struct nandfs_argv)
-#define NANDFS_IOCTL_GET_FSINFO _IOR('N', 108, struct nandfs_fsinfo)
-#define NANDFS_IOCTL_MAKE_SNAP _IOWR('N', 109, uint64_t)
-#define NANDFS_IOCTL_DELETE_SNAP _IOWR('N', 110, uint64_t)
-#define NANDFS_IOCTL_SYNC _IOWR('N', 111, uint64_t)
-
-#endif /* _NANDFS_FS_H */
diff --git a/sys/fs/nandfs/nandfs_ifile.c b/sys/fs/nandfs/nandfs_ifile.c
deleted file mode 100644
index 2c10bbac1ffe..000000000000
--- a/sys/fs/nandfs/nandfs_ifile.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-int
-nandfs_node_create(struct nandfsmount *nmp, struct nandfs_node **node,
- uint16_t mode)
-{
- struct nandfs_alloc_request req;
- struct nandfs_device *nandfsdev;
- struct nandfs_mdt *mdt;
- struct nandfs_node *ifile;
- struct nandfs_inode *inode;
- struct vnode *vp;
- uint32_t entry;
- int error = 0;
-
- nandfsdev = nmp->nm_nandfsdev;
- mdt = &nandfsdev->nd_ifile_mdt;
- ifile = nmp->nm_ifile_node;
- vp = NTOV(ifile);
-
- VOP_LOCK(vp, LK_EXCLUSIVE);
- /* Allocate new inode in ifile */
- req.entrynum = nandfsdev->nd_last_ino + 1;
- error = nandfs_find_free_entry(mdt, ifile, &req);
- if (error) {
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- error = nandfs_get_entry_block(mdt, ifile, &req, &entry, 1);
- if (error) {
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- /* Inode initialization */
- inode = ((struct nandfs_inode *) req.bp_entry->b_data) + entry;
- nandfs_inode_init(inode, mode);
-
- error = nandfs_alloc_entry(mdt, &req);
- if (error) {
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- VOP_UNLOCK(vp, 0);
-
- nandfsdev->nd_last_ino = req.entrynum;
- error = nandfs_get_node(nmp, req.entrynum, node);
- DPRINTF(IFILE, ("%s: node: %p ino: %#jx\n",
- __func__, node, (uintmax_t)((*node)->nn_ino)));
-
- return (error);
-}
-
-int
-nandfs_node_destroy(struct nandfs_node *node)
-{
- struct nandfs_alloc_request req;
- struct nandfsmount *nmp;
- struct nandfs_mdt *mdt;
- struct nandfs_node *ifile;
- struct vnode *vp;
- int error = 0;
-
- nmp = node->nn_nmp;
- req.entrynum = node->nn_ino;
- mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
- ifile = nmp->nm_ifile_node;
- vp = NTOV(ifile);
-
- DPRINTF(IFILE, ("%s: destroy node: %p ino: %#jx\n",
- __func__, node, (uintmax_t)node->nn_ino));
- VOP_LOCK(vp, LK_EXCLUSIVE);
-
- error = nandfs_find_entry(mdt, ifile, &req);
- if (error) {
- nandfs_error("%s: finding entry error:%d node %p(%jx)",
- __func__, error, node, node->nn_ino);
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- nandfs_inode_destroy(&node->nn_inode);
-
- error = nandfs_free_entry(mdt, &req);
- if (error) {
- nandfs_error("%s: freing entry error:%d node %p(%jx)",
- __func__, error, node, node->nn_ino);
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- VOP_UNLOCK(vp, 0);
- DPRINTF(IFILE, ("%s: freed node %p ino %#jx\n",
- __func__, node, (uintmax_t)node->nn_ino));
- return (error);
-}
-
-int
-nandfs_node_update(struct nandfs_node *node)
-{
- struct nandfs_alloc_request req;
- struct nandfsmount *nmp;
- struct nandfs_mdt *mdt;
- struct nandfs_node *ifile;
- struct nandfs_inode *inode;
- uint32_t index;
- int error = 0;
-
- nmp = node->nn_nmp;
- ifile = nmp->nm_ifile_node;
- ASSERT_VOP_LOCKED(NTOV(ifile), __func__);
-
- req.entrynum = node->nn_ino;
- mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
-
- DPRINTF(IFILE, ("%s: node:%p ino:%#jx\n",
- __func__, &node->nn_inode, (uintmax_t)node->nn_ino));
-
- error = nandfs_get_entry_block(mdt, ifile, &req, &index, 0);
- if (error) {
- printf("nandfs_get_entry_block returned with ERROR=%d\n",
- error);
- return (error);
- }
-
- inode = ((struct nandfs_inode *) req.bp_entry->b_data) + index;
- memcpy(inode, &node->nn_inode, sizeof(*inode));
- error = nandfs_dirty_buf(req.bp_entry, 0);
-
- return (error);
-}
-
-int
-nandfs_get_node_entry(struct nandfsmount *nmp, struct nandfs_inode **inode,
- uint64_t ino, struct buf **bp)
-{
- struct nandfs_alloc_request req;
- struct nandfs_mdt *mdt;
- struct nandfs_node *ifile;
- struct vnode *vp;
- uint32_t index;
- int error = 0;
-
- req.entrynum = ino;
- mdt = &nmp->nm_nandfsdev->nd_ifile_mdt;
- ifile = nmp->nm_ifile_node;
- vp = NTOV(ifile);
-
- VOP_LOCK(vp, LK_EXCLUSIVE);
- error = nandfs_get_entry_block(mdt, ifile, &req, &index, 0);
- if (error) {
- VOP_UNLOCK(vp, 0);
- return (error);
- }
-
- *inode = ((struct nandfs_inode *) req.bp_entry->b_data) + index;
- *bp = req.bp_entry;
- VOP_UNLOCK(vp, 0);
- return (0);
-}
-
diff --git a/sys/fs/nandfs/nandfs_mount.h b/sys/fs/nandfs/nandfs_mount.h
deleted file mode 100644
index cc6e30eb0bbd..000000000000
--- a/sys/fs/nandfs/nandfs_mount.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-4-Clause
- *
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the
- * NetBSD Project. See http://www.NetBSD.org/ for
- * information about NetBSD.
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_mount.h,v 1.1 2009/07/18 16:31:42 reinoud
- *
- * $FreeBSD$
- */
-
-#ifndef _FS_NANDFS_NANDFS_MOUNT_H_
-#define _FS_NANDFS_NANDFS_MOUNT_H_
-
-/*
- * Arguments to mount NANDFS filingsystem.
- */
-
-struct nandfs_args {
- char *fspec; /* mount specifier */
- int64_t cpno; /* checkpoint number */
-};
-
-#endif /* !_FS_NANDFS_NANDFS_MOUNT_H_ */
-
diff --git a/sys/fs/nandfs/nandfs_segment.c b/sys/fs/nandfs/nandfs_segment.c
deleted file mode 100644
index 36efc89af409..000000000000
--- a/sys/fs/nandfs/nandfs_segment.c
+++ /dev/null
@@ -1,1314 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_ddb.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/gsb_crc32.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/rwlock.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/libkern.h>
-
-#include <ddb/ddb.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include <geom/geom.h>
-#include <geom/geom_vfs.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-static int
-nandfs_new_segment(struct nandfs_device *fsdev)
-{
- int error = 0;
- uint64_t new;
-
- error = nandfs_alloc_segment(fsdev, &new);
- if (!error) {
- fsdev->nd_seg_num = fsdev->nd_next_seg_num;
- fsdev->nd_next_seg_num = new;
- }
- DPRINTF(SYNC, ("%s: new segment %jx next %jx error %d\n",
- __func__, (uintmax_t)fsdev->nd_seg_num, (uintmax_t)new, error));
- if (error)
- nandfs_error("%s: cannot create segment error %d\n",
- __func__, error);
-
- return (error);
-}
-
-static int
-create_segment(struct nandfs_seginfo *seginfo)
-{
- struct nandfs_segment *seg;
- struct nandfs_device *fsdev;
- struct nandfs_segment *prev;
- struct buf *bp;
- uint64_t start_block, curr;
- uint32_t blks_per_seg, nblocks;
- int error;
-
- fsdev = seginfo->fsdev;
- prev = seginfo->curseg;
- blks_per_seg = fsdev->nd_fsdata.f_blocks_per_segment;
- nblocks = fsdev->nd_last_segsum.ss_nblocks;
-
- if (!prev) {
- vfs_timestamp(&fsdev->nd_ts);
- /* Touch current segment */
- error = nandfs_touch_segment(fsdev, fsdev->nd_seg_num);
- if (error) {
- nandfs_error("%s: cannot preallocate segment %jx\n",
- __func__, fsdev->nd_seg_num);
- return (error);
- }
- error = nandfs_touch_segment(fsdev, 0);
- if (error) {
- nandfs_error("%s: cannot dirty block with segment 0\n",
- __func__);
- return (error);
- }
- start_block = fsdev->nd_last_pseg + (uint64_t)nblocks;
- /*
- * XXX Hack
- */
- if (blks_per_seg - (start_block % blks_per_seg) - 1 == 0)
- start_block++;
- curr = nandfs_get_segnum_of_block(fsdev, start_block);
- /* Allocate new segment if last one is full */
- if (fsdev->nd_seg_num != curr) {
- error = nandfs_new_segment(fsdev);
- if (error) {
- nandfs_error("%s: cannot create new segment\n",
- __func__);
- return (error);
- }
- /*
- * XXX Hack
- */
- nandfs_get_segment_range(fsdev, fsdev->nd_seg_num, &start_block, NULL);
- }
- } else {
- nandfs_get_segment_range(fsdev, fsdev->nd_next_seg_num,
- &start_block, NULL);
-
- /* Touch current segment and allocate and touch new one */
- error = nandfs_new_segment(fsdev);
- if (error) {
- nandfs_error("%s: cannot create next segment\n",
- __func__);
- return (error);
- }
-
- /* Reiterate in case new buf is dirty */
- seginfo->reiterate = 1;
- }
-
- /* Allocate and initialize nandfs_segment structure */
- seg = malloc(sizeof(*seg), M_DEVBUF, M_WAITOK|M_ZERO);
- TAILQ_INIT(&seg->segsum);
- TAILQ_INIT(&seg->data);
- seg->fsdev = fsdev;
- seg->start_block = start_block;
- seg->num_blocks = blks_per_seg - (start_block % blks_per_seg) - 1;
- seg->seg_num = fsdev->nd_seg_num;
- seg->seg_next = fsdev->nd_next_seg_num;
- seg->segsum_blocks = 1;
- seg->bytes_left = fsdev->nd_blocksize -
- sizeof(struct nandfs_segment_summary);
- seg->segsum_bytes = sizeof(struct nandfs_segment_summary);
-
- /* Allocate buffer for segment summary */
- bp = getblk(fsdev->nd_devvp, nandfs_block_to_dblock(fsdev,
- seg->start_block), fsdev->nd_blocksize, 0, 0, 0);
- bzero(bp->b_data, seginfo->fsdev->nd_blocksize);
- bp->b_bufobj = &seginfo->fsdev->nd_devvp->v_bufobj;
- bp->b_flags |= B_MANAGED;
-
- /* Add buffer to segment */
- TAILQ_INSERT_TAIL(&seg->segsum, bp, b_cluster.cluster_entry);
- seg->current_off = bp->b_data + sizeof(struct nandfs_segment_summary);
-
- DPRINTF(SYNC, ("%s: seg %p : initial settings: start %#jx size :%#x\n",
- __func__, seg, (uintmax_t)seg->start_block, seg->num_blocks));
- DPRINTF(SYNC, ("%s: seg->seg_num %#jx cno %#jx next %#jx\n", __func__,
- (uintmax_t)seg->seg_num, (uintmax_t)(fsdev->nd_last_cno + 1),
- (uintmax_t)seg->seg_next));
-
- if (!prev)
- LIST_INSERT_HEAD(&seginfo->seg_list, seg, seg_link);
- else
- LIST_INSERT_AFTER(prev, seg, seg_link);
-
- seginfo->curseg = seg;
-
- return (0);
-}
-
-static int
-delete_segment(struct nandfs_seginfo *seginfo)
-{
- struct nandfs_segment *seg, *tseg;
- struct buf *bp, *tbp;
-
- LIST_FOREACH_SAFE(seg, &seginfo->seg_list, seg_link, tseg) {
- TAILQ_FOREACH_SAFE(bp, &seg->segsum, b_cluster.cluster_entry,
- tbp) {
- TAILQ_REMOVE(&seg->segsum, bp, b_cluster.cluster_entry);
- bp->b_flags &= ~B_MANAGED;
- brelse(bp);
- }
-
- LIST_REMOVE(seg, seg_link);
- free(seg, M_DEVBUF);
- }
-
- return (0);
-}
-
-static int
-create_seginfo(struct nandfs_device *fsdev, struct nandfs_seginfo **seginfo)
-{
- struct nandfs_seginfo *info;
-
- info = malloc(sizeof(*info), M_DEVBUF, M_WAITOK);
-
- LIST_INIT(&info->seg_list);
- info->fsdev = fsdev;
- info->curseg = NULL;
- info->blocks = 0;
- *seginfo = info;
- fsdev->nd_seginfo = info;
- return (0);
-}
-
-static int
-delete_seginfo(struct nandfs_seginfo *seginfo)
-{
- struct nandfs_device *nffsdev;
-
- nffsdev = seginfo->fsdev;
- delete_segment(seginfo);
- nffsdev->nd_seginfo = NULL;
- free(seginfo, M_DEVBUF);
-
- return (0);
-}
-
-static int
-nandfs_create_superroot_block(struct nandfs_seginfo *seginfo,
- struct buf **newbp)
-{
- struct buf *bp;
- int error;
-
- bp = nandfs_geteblk(seginfo->fsdev->nd_blocksize, GB_NOWAIT_BD);
-
- bzero(bp->b_data, seginfo->fsdev->nd_blocksize);
- bp->b_bufobj = &seginfo->fsdev->nd_devvp->v_bufobj;
- bp->b_flags |= B_MANAGED;
-
- if (!(seginfo->curseg) || !seginfo->curseg->num_blocks) {
- error = create_segment(seginfo);
- if (error) {
- brelse(bp);
- nandfs_error("%s: no segment for superroot\n",
- __func__);
- return (error);
- }
- }
-
- TAILQ_INSERT_TAIL(&seginfo->curseg->data, bp, b_cluster.cluster_entry);
-
- seginfo->curseg->nblocks++;
- seginfo->curseg->num_blocks--;
- seginfo->blocks++;
-
- *newbp = bp;
- return (0);
-}
-
-static int
-nandfs_add_superroot(struct nandfs_seginfo *seginfo)
-{
- struct nandfs_device *fsdev;
- struct nandfs_super_root *sr;
- struct buf *bp = NULL;
- uint64_t crc_skip;
- uint32_t crc_calc;
- int error;
-
- fsdev = seginfo->fsdev;
-
- error = nandfs_create_superroot_block(seginfo, &bp);
- if (error) {
- nandfs_error("%s: cannot add superroot\n", __func__);
- return (error);
- }
-
- sr = (struct nandfs_super_root *)bp->b_data;
- /* Save superroot CRC */
- sr->sr_bytes = NANDFS_SR_BYTES;
- sr->sr_flags = 0;
- sr->sr_nongc_ctime = 0;
-
- memcpy(&sr->sr_dat, &fsdev->nd_dat_node->nn_inode,
- sizeof(struct nandfs_inode));
- memcpy(&sr->sr_cpfile, &fsdev->nd_cp_node->nn_inode,
- sizeof(struct nandfs_inode));
- memcpy(&sr->sr_sufile, &fsdev->nd_su_node->nn_inode,
- sizeof(struct nandfs_inode));
-
- crc_skip = sizeof(sr->sr_sum);
- crc_calc = crc32((uint8_t *)sr + crc_skip, NANDFS_SR_BYTES - crc_skip);
-
- sr->sr_sum = crc_calc;
-
- bp->b_flags |= B_MANAGED;
- bp->b_bufobj = &seginfo->fsdev->nd_devvp->v_bufobj;
-
- bp->b_flags &= ~B_INVAL;
- nandfs_dirty_bufs_increment(fsdev);
- DPRINTF(SYNC, ("%s: bp:%p\n", __func__, bp));
-
- return (0);
-}
-
-static int
-nandfs_add_segsum_block(struct nandfs_seginfo *seginfo, struct buf **newbp)
-{
- struct nandfs_device *fsdev;
- nandfs_daddr_t blk;
- struct buf *bp;
- int error;
-
- if (!(seginfo->curseg) || seginfo->curseg->num_blocks <= 1) {
- error = create_segment(seginfo);
- if (error) {
- nandfs_error("%s: error:%d when creating segment\n",
- __func__, error);
- return (error);
- }
- *newbp = TAILQ_FIRST(&seginfo->curseg->segsum);
- return (0);
- }
-
- fsdev = seginfo->fsdev;
- blk = nandfs_block_to_dblock(fsdev, seginfo->curseg->start_block +
- seginfo->curseg->segsum_blocks);
-
- bp = getblk(fsdev->nd_devvp, blk, fsdev->nd_blocksize, 0, 0, 0);
-
- bzero(bp->b_data, seginfo->fsdev->nd_blocksize);
- bp->b_bufobj = &seginfo->fsdev->nd_devvp->v_bufobj;
- bp->b_flags |= B_MANAGED;
-
- TAILQ_INSERT_TAIL(&seginfo->curseg->segsum, bp,
- b_cluster.cluster_entry);
- seginfo->curseg->num_blocks--;
-
- seginfo->curseg->segsum_blocks++;
- seginfo->curseg->bytes_left = seginfo->fsdev->nd_blocksize;
- seginfo->curseg->current_off = bp->b_data;
- seginfo->blocks++;
-
- *newbp = bp;
-
- DPRINTF(SYNC, ("%s: bp %p\n", __func__, bp));
-
- return (0);
-}
-
-static int
-nandfs_add_blocks(struct nandfs_seginfo *seginfo, struct nandfs_node *node,
- struct buf *bp)
-{
- union nandfs_binfo *binfo;
- struct buf *seg_bp;
- int error;
-
- if (!(seginfo->curseg) || !seginfo->curseg->num_blocks) {
- error = create_segment(seginfo);
- if (error) {
- nandfs_error("%s: error:%d when creating segment\n",
- __func__, error);
- return (error);
- }
- }
-
- if (seginfo->curseg->bytes_left < sizeof(union nandfs_binfo)) {
- error = nandfs_add_segsum_block(seginfo, &seg_bp);
- if (error) {
- nandfs_error("%s: error:%d when adding segsum\n",
- __func__, error);
- return (error);
- }
- }
- binfo = (union nandfs_binfo *)seginfo->curseg->current_off;
-
- if (node->nn_ino != NANDFS_DAT_INO) {
- binfo->bi_v.bi_blkoff = bp->b_lblkno;
- binfo->bi_v.bi_ino = node->nn_ino;
- } else {
- binfo->bi_dat.bi_blkoff = bp->b_lblkno;
- binfo->bi_dat.bi_ino = node->nn_ino;
- if (NANDFS_IS_INDIRECT(bp))
- binfo->bi_dat.bi_level = 1;
- else
- binfo->bi_dat.bi_level = 0;
- }
- binfo++;
-
- seginfo->curseg->bytes_left -= sizeof(union nandfs_binfo);
- seginfo->curseg->segsum_bytes += sizeof(union nandfs_binfo);
- seginfo->curseg->current_off = (char *)binfo;
-
- TAILQ_INSERT_TAIL(&seginfo->curseg->data, bp, b_cluster.cluster_entry);
-
- seginfo->curseg->nbinfos++;
- seginfo->curseg->nblocks++;
- seginfo->curseg->num_blocks--;
- seginfo->blocks++;
-
- DPRINTF(SYNC, ("%s: bp (%p) number %x (left %x)\n",
- __func__, bp, seginfo->curseg->nblocks,
- seginfo->curseg->num_blocks));
- return (0);
-}
-
-static int
-nandfs_iterate_dirty_buf(struct vnode *vp, struct nandfs_seginfo *seginfo,
- uint8_t hold)
-{
- struct buf *bp, *tbd;
- struct bufobj *bo;
- struct nandfs_node *node;
- int error;
-
- node = VTON(vp);
- bo = &vp->v_bufobj;
-
- ASSERT_VOP_ELOCKED(vp, __func__);
-
- /* Iterate dirty data bufs */
- TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, tbd) {
- DPRINTF(SYNC, ("%s: vp (%p): bp (%p) with lblkno %jx ino %jx "
- "add buf\n", __func__, vp, bp, bp->b_lblkno, node->nn_ino));
-
- if (!(NANDFS_ISGATHERED(bp))) {
- error = nandfs_bmap_update_dat(node,
- nandfs_vblk_get(bp), bp);
- if (error)
- return (error);
- NANDFS_GATHER(bp);
- nandfs_add_blocks(seginfo, node, bp);
- }
- }
-
- return (0);
-}
-
-static int
-nandfs_iterate_system_vnode(struct nandfs_node *node,
- struct nandfs_seginfo *seginfo)
-{
- struct vnode *vp;
- int nblocks;
- uint8_t hold = 0;
-
- if (node->nn_ino != NANDFS_IFILE_INO)
- hold = 1;
-
- vp = NTOV(node);
-
- nblocks = vp->v_bufobj.bo_dirty.bv_cnt;
- DPRINTF(SYNC, ("%s: vp (%p): nblocks %x ino %jx\n",
- __func__, vp, nblocks, node->nn_ino));
-
- if (nblocks)
- nandfs_iterate_dirty_buf(vp, seginfo, hold);
-
- return (0);
-}
-
-static int
-nandfs_iterate_dirty_vnodes(struct mount *mp, struct nandfs_seginfo *seginfo)
-{
- struct nandfs_node *nandfs_node;
- struct vnode *vp, *mvp;
- struct thread *td;
- struct bufobj *bo;
- int error, update;
-
- td = curthread;
-
- MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) {
- update = 0;
-
- if (mp->mnt_syncer == vp || VOP_ISLOCKED(vp)) {
- VI_UNLOCK(vp);
- continue;
- }
- if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK | LK_NOWAIT, td) != 0)
- continue;
-
- nandfs_node = VTON(vp);
- if (nandfs_node->nn_flags & IN_MODIFIED) {
- nandfs_node->nn_flags &= ~(IN_MODIFIED);
- update = 1;
- }
-
- bo = &vp->v_bufobj;
- BO_LOCK(bo);
- if (vp->v_bufobj.bo_dirty.bv_cnt) {
- error = nandfs_iterate_dirty_buf(vp, seginfo, 0);
- if (error) {
- nandfs_error("%s: cannot iterate vnode:%p "
- "err:%d\n", __func__, vp, error);
- vput(vp);
- BO_UNLOCK(bo);
- return (error);
- }
- update = 1;
- } else
- vput(vp);
- BO_UNLOCK(bo);
-
- if (update)
- nandfs_node_update(nandfs_node);
- }
-
- return (0);
-}
-
-static int
-nandfs_update_phys_block(struct nandfs_device *fsdev, struct buf *bp,
- uint64_t phys_blknr, union nandfs_binfo *binfo)
-{
- struct nandfs_node *node, *dat;
- struct vnode *vp;
- uint64_t new_blknr;
- int error;
-
- vp = bp->b_vp;
- node = VTON(vp);
- new_blknr = nandfs_vblk_get(bp);
- dat = fsdev->nd_dat_node;
-
- DPRINTF(BMAP, ("%s: ino %#jx lblk %#jx: vblk %#jx -> %#jx\n",
- __func__, (uintmax_t)node->nn_ino, (uintmax_t)bp->b_lblkno,
- (uintmax_t)new_blknr, (uintmax_t)phys_blknr));
-
- if (node->nn_ino != NANDFS_DAT_INO) {
- KASSERT((new_blknr != 0), ("vblk for bp %p is 0", bp));
-
- nandfs_vblock_assign(fsdev, new_blknr, phys_blknr);
- binfo->bi_v.bi_vblocknr = new_blknr;
- binfo->bi_v.bi_blkoff = bp->b_lblkno;
- binfo->bi_v.bi_ino = node->nn_ino;
- } else {
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- error = nandfs_bmap_update_block(node, bp, phys_blknr);
- if (error) {
- nandfs_error("%s: error updating block:%jx for bp:%p\n",
- __func__, (uintmax_t)phys_blknr, bp);
- VOP_UNLOCK(NTOV(dat), 0);
- return (error);
- }
- VOP_UNLOCK(NTOV(dat), 0);
- binfo->bi_dat.bi_blkoff = bp->b_lblkno;
- binfo->bi_dat.bi_ino = node->nn_ino;
- if (NANDFS_IS_INDIRECT(bp))
- binfo->bi_dat.bi_level = 1;
- else
- binfo->bi_dat.bi_level = 0;
- }
-
- return (0);
-}
-
-#define NBINFO(off) ((off) + sizeof(union nandfs_binfo))
-static int
-nandfs_segment_assign_pblk(struct nandfs_segment *nfsseg)
-{
- struct nandfs_device *fsdev;
- union nandfs_binfo *binfo;
- struct buf *bp, *seg_bp;
- uint64_t blocknr;
- uint32_t curr_off, blocksize;
- int error;
-
- fsdev = nfsseg->fsdev;
- blocksize = fsdev->nd_blocksize;
-
- blocknr = nfsseg->start_block + nfsseg->segsum_blocks;
- seg_bp = TAILQ_FIRST(&nfsseg->segsum);
- DPRINTF(SYNC, ("%s: seg:%p segsum bp:%p data:%p\n",
- __func__, nfsseg, seg_bp, seg_bp->b_data));
-
- binfo = (union nandfs_binfo *)(seg_bp->b_data +
- sizeof(struct nandfs_segment_summary));
- curr_off = sizeof(struct nandfs_segment_summary);
-
- TAILQ_FOREACH(bp, &nfsseg->data, b_cluster.cluster_entry) {
- KASSERT((bp->b_vp), ("bp %p has not vp", bp));
-
- DPRINTF(BMAP, ("\n\n%s: assign buf %p for ino %#jx next %p\n",
- __func__, bp, (uintmax_t)VTON(bp->b_vp)->nn_ino,
- TAILQ_NEXT(bp, b_cluster.cluster_entry)));
-
- if (NBINFO(curr_off) > blocksize) {
- seg_bp = TAILQ_NEXT(seg_bp, b_cluster.cluster_entry);
- binfo = (union nandfs_binfo *)seg_bp->b_data;
- curr_off = 0;
- DPRINTF(SYNC, ("%s: next segsum %p data %p\n",
- __func__, seg_bp, seg_bp->b_data));
- }
-
- error = nandfs_update_phys_block(fsdev, bp, blocknr, binfo);
- if (error) {
- nandfs_error("%s: err:%d when updatinng phys block:%jx"
- " for bp:%p and binfo:%p\n", __func__, error,
- (uintmax_t)blocknr, bp, binfo);
- return (error);
- }
- binfo++;
- curr_off = NBINFO(curr_off);
-
- blocknr++;
- }
-
- return (0);
-}
-
-static int
-nandfs_seginfo_assign_pblk(struct nandfs_seginfo *seginfo)
-{
- struct nandfs_segment *nfsseg;
- int error = 0;
-
- LIST_FOREACH(nfsseg, &seginfo->seg_list, seg_link) {
- error = nandfs_segment_assign_pblk(nfsseg);
- if (error)
- break;
- }
-
- return (error);
-}
-
-static struct nandfs_segment_summary *
-nandfs_fill_segsum(struct nandfs_segment *seg, int has_sr)
-{
- struct nandfs_segment_summary *ss;
- struct nandfs_device *fsdev;
- struct buf *bp;
- uint32_t rest, segsum_size, blocksize, crc_calc;
- uint16_t flags;
- uint8_t *crc_area, crc_skip;
-
- DPRINTF(SYNC, ("%s: seg %#jx nblocks %#x sumbytes %#x\n",
- __func__, (uintmax_t) seg->seg_num,
- seg->nblocks + seg->segsum_blocks,
- seg->segsum_bytes));
-
- fsdev = seg->fsdev;
-
- flags = NANDFS_SS_LOGBGN | NANDFS_SS_LOGEND;
- if (has_sr)
- flags |= NANDFS_SS_SR;
-
- bp = TAILQ_FIRST(&seg->segsum);
- ss = (struct nandfs_segment_summary *) bp->b_data;
- ss->ss_magic = NANDFS_SEGSUM_MAGIC;
- ss->ss_bytes = sizeof(struct nandfs_segment_summary);
- ss->ss_flags = flags;
- ss->ss_seq = ++(fsdev->nd_seg_sequence);
- ss->ss_create = fsdev->nd_ts.tv_sec;
- nandfs_get_segment_range(fsdev, seg->seg_next, &ss->ss_next, NULL);
- ss->ss_nblocks = seg->nblocks + seg->segsum_blocks;
- ss->ss_nbinfos = seg->nbinfos;
- ss->ss_sumbytes = seg->segsum_bytes;
-
- crc_skip = sizeof(ss->ss_datasum) + sizeof(ss->ss_sumsum);
- blocksize = seg->fsdev->nd_blocksize;
-
- segsum_size = seg->segsum_bytes - crc_skip;
- rest = min(seg->segsum_bytes, blocksize) - crc_skip;
- crc_area = (uint8_t *)ss + crc_skip;
- crc_calc = ~0U;
- while (segsum_size > 0) {
- crc_calc = crc32_raw(crc_area, rest, crc_calc);
- segsum_size -= rest;
- if (!segsum_size)
- break;
- bp = TAILQ_NEXT(bp, b_cluster.cluster_entry);
- crc_area = (uint8_t *)bp->b_data;
- rest = segsum_size <= blocksize ? segsum_size : blocksize;
- }
- ss->ss_sumsum = crc_calc ^ ~0U;
-
- return (ss);
-
-}
-
-static int
-nandfs_save_buf(struct buf *bp, uint64_t blocknr, struct nandfs_device *fsdev)
-{
- struct bufobj *bo;
- int error;
-
- bo = &fsdev->nd_devvp->v_bufobj;
-
- bp->b_blkno = nandfs_block_to_dblock(fsdev, blocknr);
- bp->b_iooffset = dbtob(bp->b_blkno);
-
- KASSERT(bp->b_bufobj != NULL, ("no bufobj for %p", bp));
- if (bp->b_bufobj != bo) {
- BO_LOCK(bp->b_bufobj);
- BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK,
- BO_LOCKPTR(bp->b_bufobj));
- KASSERT(BUF_ISLOCKED(bp), ("Problem with locking buffer"));
- }
-
- DPRINTF(SYNC, ("%s: buf: %p offset %#jx blk %#jx size %#x\n",
- __func__, bp, (uintmax_t)bp->b_offset, (uintmax_t)blocknr,
- fsdev->nd_blocksize));
-
- NANDFS_UNGATHER(bp);
- nandfs_buf_clear(bp, 0xffffffff);
- bp->b_flags &= ~(B_ASYNC|B_INVAL|B_MANAGED);
- error = bwrite(bp);
- if (error) {
- nandfs_error("%s: error:%d when writing buffer:%p\n",
- __func__, error, bp);
- return (error);
- }
- return (error);
-}
-
-static void
-nandfs_clean_buf(struct nandfs_device *fsdev, struct buf *bp)
-{
-
- DPRINTF(SYNC, ("%s: buf: %p\n", __func__, bp));
-
- NANDFS_UNGATHER(bp);
- nandfs_buf_clear(bp, 0xffffffff);
- bp->b_flags &= ~(B_ASYNC|B_INVAL|B_MANAGED);
- nandfs_undirty_buf_fsdev(fsdev, bp);
-}
-
-static void
-nandfs_clean_segblocks(struct nandfs_segment *seg, uint8_t unlock)
-{
- struct nandfs_device *fsdev = seg->fsdev;
- struct nandfs_segment *next_seg;
- struct buf *bp, *tbp, *next_bp;
- struct vnode *vp, *next_vp;
-
- VOP_LOCK(fsdev->nd_devvp, LK_EXCLUSIVE);
- TAILQ_FOREACH_SAFE(bp, &seg->segsum, b_cluster.cluster_entry, tbp) {
- TAILQ_REMOVE(&seg->segsum, bp, b_cluster.cluster_entry);
- nandfs_clean_buf(fsdev, bp);
- }
-
- TAILQ_FOREACH_SAFE(bp, &seg->data, b_cluster.cluster_entry, tbp) {
- TAILQ_REMOVE(&seg->data, bp, b_cluster.cluster_entry);
-
- /*
- * If bp is not super-root and vnode is not currently
- * locked lock it.
- */
- vp = bp->b_vp;
- next_vp = NULL;
- next_bp = TAILQ_NEXT(bp, b_cluster.cluster_entry);
- if (!next_bp) {
- next_seg = LIST_NEXT(seg, seg_link);
- if (next_seg)
- next_bp = TAILQ_FIRST(&next_seg->data);
- }
-
- if (next_bp)
- next_vp = next_bp->b_vp;
-
- nandfs_clean_buf(fsdev, bp);
-
- if (unlock && vp != NULL && next_vp != vp &&
- !NANDFS_SYS_NODE(VTON(vp)->nn_ino))
- vput(vp);
-
- nandfs_dirty_bufs_decrement(fsdev);
- }
-
- VOP_UNLOCK(fsdev->nd_devvp, 0);
-}
-
-static int
-nandfs_save_segblocks(struct nandfs_segment *seg, uint8_t unlock)
-{
- struct nandfs_device *fsdev = seg->fsdev;
- struct nandfs_segment *next_seg;
- struct buf *bp, *tbp, *next_bp;
- struct vnode *vp, *next_vp;
- uint64_t blocknr;
- uint32_t i = 0;
- int error = 0;
-
- VOP_LOCK(fsdev->nd_devvp, LK_EXCLUSIVE);
- TAILQ_FOREACH_SAFE(bp, &seg->segsum, b_cluster.cluster_entry, tbp) {
- TAILQ_REMOVE(&seg->segsum, bp, b_cluster.cluster_entry);
- blocknr = seg->start_block + i;
- error = nandfs_save_buf(bp, blocknr, fsdev);
- if (error) {
- nandfs_error("%s: error saving buf: %p blocknr:%jx\n",
- __func__, bp, (uintmax_t)blocknr);
- goto out;
- }
- i++;
- }
-
- i = 0;
- TAILQ_FOREACH_SAFE(bp, &seg->data, b_cluster.cluster_entry, tbp) {
- TAILQ_REMOVE(&seg->data, bp, b_cluster.cluster_entry);
-
- blocknr = seg->start_block + seg->segsum_blocks + i;
- /*
- * If bp is not super-root and vnode is not currently
- * locked lock it.
- */
- vp = bp->b_vp;
- next_vp = NULL;
- next_bp = TAILQ_NEXT(bp, b_cluster.cluster_entry);
- if (!next_bp) {
- next_seg = LIST_NEXT(seg, seg_link);
- if (next_seg)
- next_bp = TAILQ_FIRST(&next_seg->data);
- }
-
- if (next_bp)
- next_vp = next_bp->b_vp;
-
- error = nandfs_save_buf(bp, blocknr, fsdev);
- if (error) {
- nandfs_error("%s: error saving buf: %p blknr: %jx\n",
- __func__, bp, (uintmax_t)blocknr);
- if (unlock && vp != NULL && next_vp != vp &&
- !NANDFS_SYS_NODE(VTON(vp)->nn_ino))
- vput(vp);
- goto out;
- }
-
- if (unlock && vp != NULL && next_vp != vp &&
- !NANDFS_SYS_NODE(VTON(vp)->nn_ino))
- vput(vp);
-
- i++;
- nandfs_dirty_bufs_decrement(fsdev);
- }
-out:
- if (error) {
- nandfs_clean_segblocks(seg, unlock);
- VOP_UNLOCK(fsdev->nd_devvp, 0);
- return (error);
- }
-
- VOP_UNLOCK(fsdev->nd_devvp, 0);
- return (error);
-}
-
-
-static void
-clean_seginfo(struct nandfs_seginfo *seginfo, uint8_t unlock)
-{
- struct nandfs_segment *seg;
-
- DPRINTF(SYNC, ("%s: seginfo %p\n", __func__, seginfo));
-
- LIST_FOREACH(seg, &seginfo->seg_list, seg_link) {
- nandfs_clean_segblocks(seg, unlock);
- }
-}
-
-static int
-save_seginfo(struct nandfs_seginfo *seginfo, uint8_t unlock)
-{
- struct nandfs_segment *seg;
- struct nandfs_device *fsdev;
- struct nandfs_segment_summary *ss;
- int error = 0;
-
- fsdev = seginfo->fsdev;
-
- DPRINTF(SYNC, ("%s: seginfo %p\n", __func__, seginfo));
-
- LIST_FOREACH(seg, &seginfo->seg_list, seg_link) {
- if (LIST_NEXT(seg, seg_link)) {
- nandfs_fill_segsum(seg, 0);
- error = nandfs_save_segblocks(seg, unlock);
- if (error) {
- nandfs_error("%s: error:%d saving seg:%p\n",
- __func__, error, seg);
- goto out;
- }
- } else {
- ss = nandfs_fill_segsum(seg, 1);
- fsdev->nd_last_segsum = *ss;
- error = nandfs_save_segblocks(seg, unlock);
- if (error) {
- nandfs_error("%s: error:%d saving seg:%p\n",
- __func__, error, seg);
- goto out;
- }
- fsdev->nd_last_cno++;
- fsdev->nd_last_pseg = seg->start_block;
- }
- }
-out:
- if (error)
- clean_seginfo(seginfo, unlock);
- return (error);
-}
-
-static void
-nandfs_invalidate_bufs(struct nandfs_device *fsdev, uint64_t segno)
-{
- uint64_t start, end;
- struct buf *bp, *tbd;
- struct bufobj *bo;
-
- nandfs_get_segment_range(fsdev, segno, &start, &end);
-
- bo = &NTOV(fsdev->nd_gc_node)->v_bufobj;
-
- BO_LOCK(bo);
-restart_locked_gc:
- TAILQ_FOREACH_SAFE(bp, &bo->bo_clean.bv_hd, b_bobufs, tbd) {
- if (!(bp->b_lblkno >= start && bp->b_lblkno <= end))
- continue;
-
- if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL))
- goto restart_locked_gc;
-
- bremfree(bp);
- bp->b_flags |= (B_INVAL | B_RELBUF);
- bp->b_flags &= ~(B_ASYNC | B_MANAGED);
- BO_UNLOCK(bo);
- brelse(bp);
- BO_LOCK(bo);
- }
- BO_UNLOCK(bo);
-}
-
-/* Process segments marks to free by cleaner */
-static void
-nandfs_process_segments(struct nandfs_device *fsdev)
-{
- uint64_t saved_segment;
- int i;
-
- if (fsdev->nd_free_base) {
- saved_segment = nandfs_get_segnum_of_block(fsdev,
- fsdev->nd_super.s_last_pseg);
- for (i = 0; i < fsdev->nd_free_count; i++) {
- if (fsdev->nd_free_base[i] == NANDFS_NOSEGMENT)
- continue;
- /* Update superblock if clearing segment point by it */
- if (fsdev->nd_free_base[i] == saved_segment) {
- nandfs_write_superblock(fsdev);
- saved_segment = nandfs_get_segnum_of_block(
- fsdev, fsdev->nd_super.s_last_pseg);
- }
- nandfs_invalidate_bufs(fsdev, fsdev->nd_free_base[i]);
- nandfs_clear_segment(fsdev, fsdev->nd_free_base[i]);
- }
-
- free(fsdev->nd_free_base, M_NANDFSTEMP);
- fsdev->nd_free_base = NULL;
- fsdev->nd_free_count = 0;
- }
-}
-
-/* Collect and write dirty buffers */
-int
-nandfs_sync_file(struct vnode *vp)
-{
- struct nandfs_device *fsdev;
- struct nandfs_node *nandfs_node;
- struct nandfsmount *nmp;
- struct nandfs_node *dat, *su, *ifile, *cp;
- struct nandfs_seginfo *seginfo = NULL;
- struct nandfs_segment *seg;
- int update, error;
- int cno_changed;
-
- ASSERT_VOP_LOCKED(vp, __func__);
- DPRINTF(SYNC, ("%s: START\n", __func__));
-
- error = 0;
- nmp = VFSTONANDFS(vp->v_mount);
- fsdev = nmp->nm_nandfsdev;
-
- dat = fsdev->nd_dat_node;
- su = fsdev->nd_su_node;
- cp = fsdev->nd_cp_node;
- ifile = nmp->nm_ifile_node;
-
- NANDFS_WRITEASSERT(fsdev);
- if (lockmgr(&fsdev->nd_seg_const, LK_UPGRADE, NULL) != 0) {
- DPRINTF(SYNC, ("%s: lost shared lock\n", __func__));
- if (lockmgr(&fsdev->nd_seg_const, LK_EXCLUSIVE, NULL) != 0)
- panic("couldn't lock exclusive");
- }
- DPRINTF(SYNC, ("%s: got lock\n", __func__));
-
- VOP_LOCK(NTOV(su), LK_EXCLUSIVE);
- create_seginfo(fsdev, &seginfo);
-
- update = 0;
-
- nandfs_node = VTON(vp);
- if (nandfs_node->nn_flags & IN_MODIFIED) {
- nandfs_node->nn_flags &= ~(IN_MODIFIED);
- update = 1;
- }
-
- if (vp->v_bufobj.bo_dirty.bv_cnt) {
- error = nandfs_iterate_dirty_buf(vp, seginfo, 0);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
- nandfs_error("%s: err:%d iterating dirty bufs vp:%p",
- __func__, error, vp);
- return (error);
- }
- update = 1;
- }
-
- if (update) {
- VOP_LOCK(NTOV(ifile), LK_EXCLUSIVE);
- error = nandfs_node_update(nandfs_node);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- VOP_UNLOCK(NTOV(ifile), 0);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
- nandfs_error("%s: err:%d updating vp:%p",
- __func__, error, vp);
- return (error);
- }
- VOP_UNLOCK(NTOV(ifile), 0);
- }
-
- cno_changed = 0;
- if (seginfo->blocks) {
- VOP_LOCK(NTOV(cp), LK_EXCLUSIVE);
- cno_changed = 1;
- /* Create new checkpoint */
- error = nandfs_get_checkpoint(fsdev, cp, fsdev->nd_last_cno + 1);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- VOP_UNLOCK(NTOV(cp), 0);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
- nandfs_error("%s: err:%d getting cp:%jx",
- __func__, error, fsdev->nd_last_cno + 1);
- return (error);
- }
-
- /* Reiterate all blocks and assign physical block number */
- nandfs_seginfo_assign_pblk(seginfo);
-
- /* Fill checkpoint data */
- error = nandfs_set_checkpoint(fsdev, cp, fsdev->nd_last_cno + 1,
- &ifile->nn_inode, seginfo->blocks);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- VOP_UNLOCK(NTOV(cp), 0);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
- nandfs_error("%s: err:%d setting cp:%jx",
- __func__, error, fsdev->nd_last_cno + 1);
- return (error);
- }
-
- VOP_UNLOCK(NTOV(cp), 0);
- LIST_FOREACH(seg, &seginfo->seg_list, seg_link)
- nandfs_update_segment(fsdev, seg->seg_num,
- seg->nblocks + seg->segsum_blocks);
-
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- error = save_seginfo(seginfo, 0);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- VOP_UNLOCK(NTOV(dat), 0);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
- nandfs_error("%s: err:%d updating seg",
- __func__, error);
- return (error);
- }
- VOP_UNLOCK(NTOV(dat), 0);
- }
-
- VOP_UNLOCK(NTOV(su), 0);
-
- delete_seginfo(seginfo);
- lockmgr(&fsdev->nd_seg_const, LK_DOWNGRADE, NULL);
-
- if (cno_changed && !error) {
- if (nandfs_cps_between_sblocks != 0 &&
- fsdev->nd_last_cno % nandfs_cps_between_sblocks == 0)
- nandfs_write_superblock(fsdev);
- }
-
- ASSERT_VOP_LOCKED(vp, __func__);
- DPRINTF(SYNC, ("%s: END error %d\n", __func__, error));
- return (error);
-}
-
-int
-nandfs_segment_constructor(struct nandfsmount *nmp, int flags)
-{
- struct nandfs_device *fsdev;
- struct nandfs_seginfo *seginfo = NULL;
- struct nandfs_segment *seg;
- struct nandfs_node *dat, *su, *ifile, *cp, *gc;
- int cno_changed, error;
-
- DPRINTF(SYNC, ("%s: START\n", __func__));
- fsdev = nmp->nm_nandfsdev;
-
- lockmgr(&fsdev->nd_seg_const, LK_EXCLUSIVE, NULL);
- DPRINTF(SYNC, ("%s: git lock\n", __func__));
-again:
- create_seginfo(fsdev, &seginfo);
-
- dat = fsdev->nd_dat_node;
- su = fsdev->nd_su_node;
- cp = fsdev->nd_cp_node;
- gc = fsdev->nd_gc_node;
- ifile = nmp->nm_ifile_node;
-
- VOP_LOCK(NTOV(su), LK_EXCLUSIVE);
- VOP_LOCK(NTOV(ifile), LK_EXCLUSIVE);
- VOP_LOCK(NTOV(gc), LK_EXCLUSIVE);
- VOP_LOCK(NTOV(cp), LK_EXCLUSIVE);
-
- nandfs_iterate_system_vnode(gc, seginfo);
- nandfs_iterate_dirty_vnodes(nmp->nm_vfs_mountp, seginfo);
- nandfs_iterate_system_vnode(ifile, seginfo);
- nandfs_iterate_system_vnode(su, seginfo);
-
- cno_changed = 0;
- if (seginfo->blocks || flags) {
- cno_changed = 1;
- /* Create new checkpoint */
- error = nandfs_get_checkpoint(fsdev, cp, fsdev->nd_last_cno + 1);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- goto error_locks;
- }
-
- /* Collect blocks from system files */
- nandfs_iterate_system_vnode(cp, seginfo);
- nandfs_iterate_system_vnode(su, seginfo);
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- nandfs_iterate_system_vnode(dat, seginfo);
- VOP_UNLOCK(NTOV(dat), 0);
-reiterate:
- seginfo->reiterate = 0;
- nandfs_iterate_system_vnode(su, seginfo);
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- nandfs_iterate_system_vnode(dat, seginfo);
- VOP_UNLOCK(NTOV(dat), 0);
- if (seginfo->reiterate)
- goto reiterate;
- if (!(seginfo->curseg) || !seginfo->curseg->num_blocks) {
- error = create_segment(seginfo);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- goto error_locks;
- }
- goto reiterate;
- }
-
- /* Reiterate all blocks and assign physical block number */
- nandfs_seginfo_assign_pblk(seginfo);
-
- /* Fill superroot */
- error = nandfs_add_superroot(seginfo);
- if (error) {
- clean_seginfo(seginfo, 0);
- delete_seginfo(seginfo);
- goto error_locks;
- }
- KASSERT(!(seginfo->reiterate), ("reiteration after superroot"));
-
- /* Fill checkpoint data */
- nandfs_set_checkpoint(fsdev, cp, fsdev->nd_last_cno + 1,
- &ifile->nn_inode, seginfo->blocks);
-
- LIST_FOREACH(seg, &seginfo->seg_list, seg_link)
- nandfs_update_segment(fsdev, seg->seg_num,
- seg->nblocks + seg->segsum_blocks);
-
- VOP_LOCK(NTOV(dat), LK_EXCLUSIVE);
- error = save_seginfo(seginfo, 1);
- if (error) {
- clean_seginfo(seginfo, 1);
- delete_seginfo(seginfo);
- goto error_dat;
- }
- VOP_UNLOCK(NTOV(dat), 0);
- }
-
- VOP_UNLOCK(NTOV(cp), 0);
- VOP_UNLOCK(NTOV(gc), 0);
- VOP_UNLOCK(NTOV(ifile), 0);
-
- nandfs_process_segments(fsdev);
-
- VOP_UNLOCK(NTOV(su), 0);
-
- delete_seginfo(seginfo);
-
- /*
- * XXX: a hack, will go away soon
- */
- if ((NTOV(dat)->v_bufobj.bo_dirty.bv_cnt != 0 ||
- NTOV(cp)->v_bufobj.bo_dirty.bv_cnt != 0 ||
- NTOV(gc)->v_bufobj.bo_dirty.bv_cnt != 0 ||
- NTOV(ifile)->v_bufobj.bo_dirty.bv_cnt != 0 ||
- NTOV(su)->v_bufobj.bo_dirty.bv_cnt != 0) &&
- (flags & NANDFS_UMOUNT)) {
- DPRINTF(SYNC, ("%s: RERUN\n", __func__));
- goto again;
- }
-
- MPASS(fsdev->nd_free_base == NULL);
-
- lockmgr(&fsdev->nd_seg_const, LK_RELEASE, NULL);
-
- if (cno_changed) {
- if ((nandfs_cps_between_sblocks != 0 &&
- fsdev->nd_last_cno % nandfs_cps_between_sblocks == 0) ||
- flags & NANDFS_UMOUNT)
- nandfs_write_superblock(fsdev);
- }
-
- DPRINTF(SYNC, ("%s: END\n", __func__));
- return (0);
-error_dat:
- VOP_UNLOCK(NTOV(dat), 0);
-error_locks:
- VOP_UNLOCK(NTOV(cp), 0);
- VOP_UNLOCK(NTOV(gc), 0);
- VOP_UNLOCK(NTOV(ifile), 0);
- VOP_UNLOCK(NTOV(su), 0);
- lockmgr(&fsdev->nd_seg_const, LK_RELEASE, NULL);
-
- return (error);
-}
-
-#ifdef DDB
-/*
- * Show details about the given NANDFS mount point.
- */
-DB_SHOW_COMMAND(nandfs, db_show_nandfs)
-{
- struct mount *mp;
- struct nandfs_device *nffsdev;
- struct nandfs_segment *seg;
- struct nandfsmount *nmp;
- struct buf *bp;
- struct vnode *vp;
-
- if (!have_addr) {
- db_printf("\nUsage: show nandfs <mount_addr>\n");
- return;
- }
-
- mp = (struct mount *)addr;
- db_printf("%p %s on %s (%s)\n", mp, mp->mnt_stat.f_mntfromname,
- mp->mnt_stat.f_mntonname, mp->mnt_stat.f_fstypename);
-
-
- nmp = (struct nandfsmount *)(mp->mnt_data);
- nffsdev = nmp->nm_nandfsdev;
- db_printf("dev vnode:%p\n", nffsdev->nd_devvp);
- db_printf("blocksize:%jx last cno:%jx last pseg:%jx seg num:%jx\n",
- (uintmax_t)nffsdev->nd_blocksize, (uintmax_t)nffsdev->nd_last_cno,
- (uintmax_t)nffsdev->nd_last_pseg, (uintmax_t)nffsdev->nd_seg_num);
- db_printf("system nodes: dat:%p cp:%p su:%p ifile:%p gc:%p\n",
- nffsdev->nd_dat_node, nffsdev->nd_cp_node, nffsdev->nd_su_node,
- nmp->nm_ifile_node, nffsdev->nd_gc_node);
-
- if (nffsdev->nd_seginfo != NULL) {
- LIST_FOREACH(seg, &nffsdev->nd_seginfo->seg_list, seg_link) {
- db_printf("seg: %p\n", seg);
- TAILQ_FOREACH(bp, &seg->segsum,
- b_cluster.cluster_entry)
- db_printf("segbp %p\n", bp);
- TAILQ_FOREACH(bp, &seg->data,
- b_cluster.cluster_entry) {
- vp = bp->b_vp;
- db_printf("bp:%p bp->b_vp:%p ino:%jx\n", bp, vp,
- (uintmax_t)(vp ? VTON(vp)->nn_ino : 0));
- }
- }
- }
-}
-#endif
diff --git a/sys/fs/nandfs/nandfs_subr.c b/sys/fs/nandfs/nandfs_subr.c
deleted file mode 100644
index 0a3f65a50543..000000000000
--- a/sys/fs/nandfs/nandfs_subr.c
+++ /dev/null
@@ -1,1091 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_subr.c,v 1.4 2009/07/29 17:06:57 reinoud
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/gsb_crc32.h>
-#include <sys/namei.h>
-#include <sys/resourcevar.h>
-#include <sys/kernel.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/signalvar.h>
-#include <sys/malloc.h>
-#include <sys/dirent.h>
-#include <sys/lockf.h>
-#include <sys/libkern.h>
-
-#include <geom/geom.h>
-#include <geom/geom_vfs.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-
-#include <machine/_inttypes.h>
-#include "nandfs_mount.h"
-#include "nandfs.h"
-#include "nandfs_subr.h"
-
-MALLOC_DEFINE(M_NANDFSMNT, "nandfs_mount", "NANDFS mount");
-MALLOC_DEFINE(M_NANDFSTEMP, "nandfs_tmt", "NANDFS tmp");
-
-uma_zone_t nandfs_node_zone;
-
-void nandfs_bdflush(struct bufobj *bo, struct buf *bp);
-int nandfs_bufsync(struct bufobj *bo, int waitfor);
-
-struct buf_ops buf_ops_nandfs = {
- .bop_name = "buf_ops_nandfs",
- .bop_write = bufwrite,
- .bop_strategy = bufstrategy,
- .bop_sync = nandfs_bufsync,
- .bop_bdflush = nandfs_bdflush,
-};
-
-int
-nandfs_bufsync(struct bufobj *bo, int waitfor)
-{
- struct vnode *vp;
- int error = 0;
-
- vp = bo2vnode(bo);
-
- ASSERT_VOP_LOCKED(vp, __func__);
- error = nandfs_sync_file(vp);
- if (error)
- nandfs_warning("%s: cannot flush buffers err:%d\n",
- __func__, error);
-
- return (error);
-}
-
-void
-nandfs_bdflush(bo, bp)
- struct bufobj *bo;
- struct buf *bp;
-{
- struct vnode *vp;
- int error;
-
- if (bo->bo_dirty.bv_cnt <= ((dirtybufthresh * 8) / 10))
- return;
-
- vp = bp->b_vp;
- if (NANDFS_SYS_NODE(VTON(vp)->nn_ino))
- return;
-
- if (NANDFS_IS_INDIRECT(bp))
- return;
-
- error = nandfs_sync_file(vp);
- if (error)
- nandfs_warning("%s: cannot flush buffers err:%d\n",
- __func__, error);
-}
-
-int
-nandfs_init(struct vfsconf *vfsp)
-{
-
- nandfs_node_zone = uma_zcreate("nandfs node zone",
- sizeof(struct nandfs_node), NULL, NULL, NULL, NULL, 0, 0);
-
- return (0);
-}
-
-int
-nandfs_uninit(struct vfsconf *vfsp)
-{
-
- uma_zdestroy(nandfs_node_zone);
- return (0);
-}
-
-/* Basic calculators */
-uint64_t
-nandfs_get_segnum_of_block(struct nandfs_device *nandfsdev,
- nandfs_daddr_t blocknr)
-{
- uint64_t segnum, blks_per_seg;
-
- MPASS(blocknr >= nandfsdev->nd_fsdata.f_first_data_block);
-
- blks_per_seg = nandfsdev->nd_fsdata.f_blocks_per_segment;
-
- segnum = blocknr / blks_per_seg;
- segnum -= nandfsdev->nd_fsdata.f_first_data_block / blks_per_seg;
-
- DPRINTF(SYNC, ("%s: returning blocknr %jx -> segnum %jx\n", __func__,
- blocknr, segnum));
-
- return (segnum);
-}
-
-void
-nandfs_get_segment_range(struct nandfs_device *nandfsdev, uint64_t segnum,
- uint64_t *seg_start, uint64_t *seg_end)
-{
- uint64_t blks_per_seg;
-
- blks_per_seg = nandfsdev->nd_fsdata.f_blocks_per_segment;
- *seg_start = nandfsdev->nd_fsdata.f_first_data_block +
- blks_per_seg * segnum;
- if (seg_end != NULL)
- *seg_end = *seg_start + blks_per_seg -1;
-}
-
-void nandfs_calc_mdt_consts(struct nandfs_device *nandfsdev,
- struct nandfs_mdt *mdt, int entry_size)
-{
- uint32_t blocksize = nandfsdev->nd_blocksize;
-
- mdt->entries_per_group = blocksize * 8;
- mdt->entries_per_block = blocksize / entry_size;
-
- mdt->blocks_per_group =
- (mdt->entries_per_group -1) / mdt->entries_per_block + 1 + 1;
- mdt->groups_per_desc_block =
- blocksize / sizeof(struct nandfs_block_group_desc);
- mdt->blocks_per_desc_block =
- mdt->groups_per_desc_block * mdt->blocks_per_group + 1;
-}
-
-int
-nandfs_dev_bread(struct nandfs_device *nandfsdev, nandfs_lbn_t blocknr,
- struct ucred *cred, int flags, struct buf **bpp)
-{
- int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE;
- int error;
-
- DPRINTF(BLOCK, ("%s: read from block %jx vp %p\n", __func__,
- blocknr * blk2dev, nandfsdev->nd_devvp));
- error = bread(nandfsdev->nd_devvp, blocknr * blk2dev,
- nandfsdev->nd_blocksize, NOCRED, bpp);
- if (error)
- nandfs_error("%s: cannot read from device - blk:%jx\n",
- __func__, blocknr);
- return (error);
-}
-
-/* Read on a node */
-int
-nandfs_bread(struct nandfs_node *node, nandfs_lbn_t blocknr,
- struct ucred *cred, int flags, struct buf **bpp)
-{
- nandfs_daddr_t vblk;
- int error;
-
- DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node),
- blocknr));
-
- error = bread(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize,
- cred, bpp);
-
- KASSERT(error == 0, ("%s: vp:%p lbn:%#jx err:%d\n", __func__,
- NTOV(node), blocknr, error));
-
- if (!nandfs_vblk_get(*bpp) &&
- ((*bpp)->b_flags & B_CACHE) && node->nn_ino != NANDFS_DAT_INO) {
- nandfs_bmap_lookup(node, blocknr, &vblk);
- nandfs_vblk_set(*bpp, vblk);
- }
- return (error);
-}
-
-int
-nandfs_bread_meta(struct nandfs_node *node, nandfs_lbn_t blocknr,
- struct ucred *cred, int flags, struct buf **bpp)
-{
- nandfs_daddr_t vblk;
- int error;
-
- DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node),
- blocknr));
-
- error = bread(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize,
- cred, bpp);
-
- KASSERT(error == 0, ("%s: vp:%p lbn:%#jx err:%d\n", __func__,
- NTOV(node), blocknr, error));
-
- if (!nandfs_vblk_get(*bpp) &&
- ((*bpp)->b_flags & B_CACHE) && node->nn_ino != NANDFS_DAT_INO) {
- nandfs_bmap_lookup(node, blocknr, &vblk);
- nandfs_vblk_set(*bpp, vblk);
- }
-
- return (error);
-}
-
-int
-nandfs_bdestroy(struct nandfs_node *node, nandfs_daddr_t vblk)
-{
- int error;
-
- if (!NANDFS_SYS_NODE(node->nn_ino))
- NANDFS_WRITEASSERT(node->nn_nandfsdev);
-
- error = nandfs_vblock_end(node->nn_nandfsdev, vblk);
- if (error) {
- nandfs_error("%s: ending vblk: %jx failed\n",
- __func__, (uintmax_t)vblk);
- return (error);
- }
- node->nn_inode.i_blocks--;
-
- return (0);
-}
-
-int
-nandfs_bcreate(struct nandfs_node *node, nandfs_lbn_t blocknr,
- struct ucred *cred, int flags, struct buf **bpp)
-{
- int error;
-
- ASSERT_VOP_LOCKED(NTOV(node), __func__);
- if (!NANDFS_SYS_NODE(node->nn_ino))
- NANDFS_WRITEASSERT(node->nn_nandfsdev);
-
- DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node),
- blocknr));
-
- *bpp = getblk(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize,
- 0, 0, 0);
-
- KASSERT((*bpp), ("%s: vp:%p lbn:%#jx\n", __func__,
- NTOV(node), blocknr));
-
- if (*bpp) {
- vfs_bio_clrbuf(*bpp);
- (*bpp)->b_blkno = ~(0); /* To avoid VOP_BMAP in bdwrite */
- error = nandfs_bmap_insert_block(node, blocknr, *bpp);
- if (error) {
- nandfs_warning("%s: failed bmap insert node:%p"
- " blk:%jx\n", __func__, node, blocknr);
- brelse(*bpp);
- return (error);
- }
- node->nn_inode.i_blocks++;
-
- return (0);
- }
-
- return (-1);
-}
-
-int
-nandfs_bcreate_meta(struct nandfs_node *node, nandfs_lbn_t blocknr,
- struct ucred *cred, int flags, struct buf **bpp)
-{
- struct nandfs_device *fsdev;
- nandfs_daddr_t vblk;
- int error;
-
- ASSERT_VOP_LOCKED(NTOV(node), __func__);
- NANDFS_WRITEASSERT(node->nn_nandfsdev);
-
- DPRINTF(BLOCK, ("%s: vp:%p lbn:%#jx\n", __func__, NTOV(node),
- blocknr));
-
- fsdev = node->nn_nandfsdev;
-
- *bpp = getblk(NTOV(node), blocknr, node->nn_nandfsdev->nd_blocksize,
- 0, 0, 0);
-
- KASSERT((*bpp), ("%s: vp:%p lbn:%#jx\n", __func__,
- NTOV(node), blocknr));
-
- memset((*bpp)->b_data, 0, fsdev->nd_blocksize);
-
- vfs_bio_clrbuf(*bpp);
- (*bpp)->b_blkno = ~(0); /* To avoid VOP_BMAP in bdwrite */
-
- nandfs_buf_set(*bpp, NANDFS_VBLK_ASSIGNED);
-
- if (node->nn_ino != NANDFS_DAT_INO) {
- error = nandfs_vblock_alloc(fsdev, &vblk);
- if (error) {
- nandfs_buf_clear(*bpp, NANDFS_VBLK_ASSIGNED);
- brelse(*bpp);
- return (error);
- }
- } else
- vblk = fsdev->nd_fakevblk++;
-
- nandfs_vblk_set(*bpp, vblk);
-
- nandfs_bmap_insert_block(node, blocknr, *bpp);
- return (0);
-}
-
-/* Translate index to a file block number and an entry */
-void
-nandfs_mdt_trans(struct nandfs_mdt *mdt, uint64_t index,
- nandfs_lbn_t *blocknr, uint32_t *entry_in_block)
-{
- uint64_t blknr;
- uint64_t group, group_offset, blocknr_in_group;
- uint64_t desc_block, desc_offset;
-
- /* Calculate our offset in the file */
- group = index / mdt->entries_per_group;
- group_offset = index % mdt->entries_per_group;
- desc_block = group / mdt->groups_per_desc_block;
- desc_offset = group % mdt->groups_per_desc_block;
- blocknr_in_group = group_offset / mdt->entries_per_block;
-
- /* To descgroup offset */
- blknr = 1 + desc_block * mdt->blocks_per_desc_block;
-
- /* To group offset */
- blknr += desc_offset * mdt->blocks_per_group;
-
- /* To actual file block */
- blknr += 1 + blocknr_in_group;
-
- *blocknr = blknr;
- *entry_in_block = group_offset % mdt->entries_per_block;
-}
-
-void
-nandfs_mdt_trans_blk(struct nandfs_mdt *mdt, uint64_t index,
- uint64_t *desc, uint64_t *bitmap, nandfs_lbn_t *blocknr,
- uint32_t *entry_in_block)
-{
- uint64_t blknr;
- uint64_t group, group_offset, blocknr_in_group;
- uint64_t desc_block, desc_offset;
-
- /* Calculate our offset in the file */
- group = index / mdt->entries_per_group;
- group_offset = index % mdt->entries_per_group;
- desc_block = group / mdt->groups_per_desc_block;
- desc_offset = group % mdt->groups_per_desc_block;
- blocknr_in_group = group_offset / mdt->entries_per_block;
-
- /* To descgroup offset */
- *desc = desc_block * mdt->blocks_per_desc_block;
- blknr = 1 + desc_block * mdt->blocks_per_desc_block;
-
- /* To group offset */
- blknr += desc_offset * mdt->blocks_per_group;
- *bitmap = blknr;
-
- /* To actual file block */
- blknr += 1 + blocknr_in_group;
-
- *blocknr = blknr;
- *entry_in_block = group_offset % mdt->entries_per_block;
-
- DPRINTF(ALLOC,
- ("%s: desc_buf: %jx bitmap_buf: %jx entry_buf: %jx entry: %x\n",
- __func__, (uintmax_t)*desc, (uintmax_t)*bitmap,
- (uintmax_t)*blocknr, *entry_in_block));
-}
-
-int
-nandfs_vtop(struct nandfs_node *node, nandfs_daddr_t vblocknr,
- nandfs_daddr_t *pblocknr)
-{
- struct nandfs_node *dat_node;
- struct nandfs_dat_entry *entry;
- struct buf *bp;
- nandfs_lbn_t ldatblknr;
- uint32_t entry_in_block;
- int locked, error;
-
- if (node->nn_ino == NANDFS_DAT_INO || node->nn_ino == NANDFS_GC_INO) {
- *pblocknr = vblocknr;
- return (0);
- }
-
- /* only translate valid vblocknrs */
- if (vblocknr == 0)
- return (0);
-
- dat_node = node->nn_nandfsdev->nd_dat_node;
- nandfs_mdt_trans(&node->nn_nandfsdev->nd_dat_mdt, vblocknr, &ldatblknr,
- &entry_in_block);
-
- locked = NANDFS_VOP_ISLOCKED(NTOV(dat_node));
- if (!locked)
- VOP_LOCK(NTOV(dat_node), LK_SHARED);
- error = nandfs_bread(dat_node, ldatblknr, NOCRED, 0, &bp);
- if (error) {
- DPRINTF(TRANSLATE, ("vtop: can't read in DAT block %#jx!\n",
- (uintmax_t)ldatblknr));
- brelse(bp);
- VOP_UNLOCK(NTOV(dat_node), 0);
- return (error);
- }
-
- /* Get our translation */
- entry = ((struct nandfs_dat_entry *) bp->b_data) + entry_in_block;
- DPRINTF(TRANSLATE, ("\tentry %p data %p entry_in_block %x\n",
- entry, bp->b_data, entry_in_block))
- DPRINTF(TRANSLATE, ("\tvblk %#jx -> %#jx for cp [%#jx-%#jx]\n",
- (uintmax_t)vblocknr, (uintmax_t)entry->de_blocknr,
- (uintmax_t)entry->de_start, (uintmax_t)entry->de_end));
-
- *pblocknr = entry->de_blocknr;
- brelse(bp);
- if (!locked)
- VOP_UNLOCK(NTOV(dat_node), 0);
-
- MPASS(*pblocknr >= node->nn_nandfsdev->nd_fsdata.f_first_data_block ||
- *pblocknr == 0);
-
- return (0);
-}
-
-int
-nandfs_segsum_valid(struct nandfs_segment_summary *segsum)
-{
-
- return (segsum->ss_magic == NANDFS_SEGSUM_MAGIC);
-}
-
-int
-nandfs_load_segsum(struct nandfs_device *fsdev, nandfs_daddr_t blocknr,
- struct nandfs_segment_summary *segsum)
-{
- struct buf *bp;
- int error;
-
- DPRINTF(VOLUMES, ("nandfs: try segsum at block %jx\n",
- (uintmax_t)blocknr));
-
- error = nandfs_dev_bread(fsdev, blocknr, NOCRED, 0, &bp);
- if (error)
- return (error);
-
- memcpy(segsum, bp->b_data, sizeof(struct nandfs_segment_summary));
- brelse(bp);
-
- if (!nandfs_segsum_valid(segsum)) {
- DPRINTF(VOLUMES, ("%s: bad magic pseg:%jx\n", __func__,
- blocknr));
- return (EINVAL);
- }
-
- return (error);
-}
-
-static int
-nandfs_load_super_root(struct nandfs_device *nandfsdev,
- struct nandfs_segment_summary *segsum, uint64_t pseg)
-{
- struct nandfs_super_root super_root;
- struct buf *bp;
- uint64_t blocknr;
- uint32_t super_root_crc, comp_crc;
- int off, error;
-
- /* Check if there is a superroot */
- if ((segsum->ss_flags & NANDFS_SS_SR) == 0) {
- DPRINTF(VOLUMES, ("%s: no super root in pseg:%jx\n", __func__,
- pseg));
- return (ENOENT);
- }
-
- /* Get our super root, located at the end of the pseg */
- blocknr = pseg + segsum->ss_nblocks - 1;
- DPRINTF(VOLUMES, ("%s: try at %#jx\n", __func__, (uintmax_t)blocknr));
-
- error = nandfs_dev_bread(nandfsdev, blocknr, NOCRED, 0, &bp);
- if (error)
- return (error);
-
- memcpy(&super_root, bp->b_data, sizeof(struct nandfs_super_root));
- brelse(bp);
-
- /* Check super root CRC */
- super_root_crc = super_root.sr_sum;
- off = sizeof(super_root.sr_sum);
- comp_crc = crc32((uint8_t *)&super_root + off,
- NANDFS_SR_BYTES - off);
-
- if (super_root_crc != comp_crc) {
- DPRINTF(VOLUMES, ("%s: invalid crc:%#x [expect:%#x]\n",
- __func__, super_root_crc, comp_crc));
- return (EINVAL);
- }
-
- nandfsdev->nd_super_root = super_root;
- DPRINTF(VOLUMES, ("%s: got valid superroot\n", __func__));
-
- return (0);
-}
-
-/*
- * Search for the last super root recorded.
- */
-int
-nandfs_search_super_root(struct nandfs_device *nandfsdev)
-{
- struct nandfs_super_block *super;
- struct nandfs_segment_summary segsum;
- uint64_t seg_start, seg_end, cno, seq, create, pseg;
- uint64_t segnum;
- int error, found;
-
- error = found = 0;
-
- /* Search for last super root */
- pseg = nandfsdev->nd_super.s_last_pseg;
- segnum = nandfs_get_segnum_of_block(nandfsdev, pseg);
-
- cno = nandfsdev->nd_super.s_last_cno;
- create = seq = 0;
- DPRINTF(VOLUMES, ("%s: start in pseg %#jx\n", __func__,
- (uintmax_t)pseg));
-
- for (;;) {
- error = nandfs_load_segsum(nandfsdev, pseg, &segsum);
- if (error)
- break;
-
- if (segsum.ss_seq < seq || segsum.ss_create < create)
- break;
-
- /* Try to load super root */
- if (segsum.ss_flags & NANDFS_SS_SR) {
- error = nandfs_load_super_root(nandfsdev, &segsum, pseg);
- if (error)
- break; /* confused */
- found = 1;
-
- super = &nandfsdev->nd_super;
- nandfsdev->nd_last_segsum = segsum;
- super->s_last_pseg = pseg;
- super->s_last_cno = cno++;
- super->s_last_seq = segsum.ss_seq;
- super->s_state = NANDFS_VALID_FS;
- seq = segsum.ss_seq;
- create = segsum.ss_create;
- } else {
- seq = segsum.ss_seq;
- create = segsum.ss_create;
- }
-
- /* Calculate next partial segment location */
- pseg += segsum.ss_nblocks;
- DPRINTF(VOLUMES, ("%s: next partial seg is %jx\n", __func__,
- (uintmax_t)pseg));
-
- /* Did we reach the end of the segment? if so, go to the next */
- nandfs_get_segment_range(nandfsdev, segnum, &seg_start,
- &seg_end);
- if (pseg >= seg_end) {
- pseg = segsum.ss_next;
- DPRINTF(VOLUMES,
- (" partial seg oor next is %jx[%jx - %jx]\n",
- (uintmax_t)pseg, (uintmax_t)seg_start,
- (uintmax_t)seg_end));
- }
- segnum = nandfs_get_segnum_of_block(nandfsdev, pseg);
- }
-
- if (error && !found)
- return (error);
-
- return (0);
-}
-
-int
-nandfs_get_node_raw(struct nandfs_device *nandfsdev, struct nandfsmount *nmp,
- uint64_t ino, struct nandfs_inode *inode, struct nandfs_node **nodep)
-{
- struct nandfs_node *node;
- struct vnode *nvp;
- struct mount *mp;
- int error;
-
- *nodep = NULL;
-
- /* Associate with mountpoint if present */
- if (nmp) {
- mp = nmp->nm_vfs_mountp;
- error = getnewvnode("nandfs", mp, &nandfs_vnodeops, &nvp);
- if (error)
- return (error);
- } else {
- mp = NULL;
- error = getnewvnode("snandfs", mp, &nandfs_system_vnodeops,
- &nvp);
- if (error)
- return (error);
- }
-
- if (mp)
- NANDFS_WRITELOCK(nandfsdev);
-
- DPRINTF(IFILE, ("%s: ino: %#jx -> vp: %p\n",
- __func__, (uintmax_t)ino, nvp));
- /* Lock node */
- lockmgr(nvp->v_vnlock, LK_EXCLUSIVE, NULL);
-
- if (mp) {
- error = insmntque(nvp, mp);
- if (error != 0) {
- *nodep = NULL;
- return (error);
- }
- }
-
- node = uma_zalloc(nandfs_node_zone, M_WAITOK | M_ZERO);
-
- /* Crosslink */
- node->nn_vnode = nvp;
- nvp->v_bufobj.bo_ops = &buf_ops_nandfs;
- node->nn_nmp = nmp;
- node->nn_nandfsdev = nandfsdev;
- nvp->v_data = node;
-
- /* Initiase NANDFS node */
- node->nn_ino = ino;
- if (inode != NULL)
- node->nn_inode = *inode;
-
- nandfs_vinit(nvp, ino);
-
- /* Return node */
- *nodep = node;
- DPRINTF(IFILE, ("%s: ino:%#jx vp:%p node:%p\n",
- __func__, (uintmax_t)ino, nvp, *nodep));
-
- return (0);
-}
-
-int
-nandfs_get_node(struct nandfsmount *nmp, uint64_t ino,
- struct nandfs_node **nodep)
-{
- struct nandfs_device *nandfsdev;
- struct nandfs_inode inode, *entry;
- struct vnode *nvp, *vpp;
- struct thread *td;
- struct buf *bp;
- uint64_t ivblocknr;
- uint32_t entry_in_block;
- int error;
-
- /* Look up node in hash table */
- td = curthread;
- *nodep = NULL;
-
- if ((ino < NANDFS_ATIME_INO) && (ino != NANDFS_ROOT_INO)) {
- printf("nandfs_get_node: system ino %"PRIu64" not in mount "
- "point!\n", ino);
- return (ENOENT);
- }
-
- error = vfs_hash_get(nmp->nm_vfs_mountp, ino, LK_EXCLUSIVE, td, &nvp,
- NULL, NULL);
- if (error)
- return (error);
-
- if (nvp != NULL) {
- *nodep = (struct nandfs_node *)nvp->v_data;
- return (0);
- }
-
- /* Look up inode structure in mountpoints ifile */
- nandfsdev = nmp->nm_nandfsdev;
- nandfs_mdt_trans(&nandfsdev->nd_ifile_mdt, ino, &ivblocknr,
- &entry_in_block);
-
- VOP_LOCK(NTOV(nmp->nm_ifile_node), LK_SHARED);
- error = nandfs_bread(nmp->nm_ifile_node, ivblocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(nmp->nm_ifile_node), 0);
- return (ENOENT);
- }
-
- /* Get inode entry */
- entry = (struct nandfs_inode *) bp->b_data + entry_in_block;
- memcpy(&inode, entry, sizeof(struct nandfs_inode));
- brelse(bp);
- VOP_UNLOCK(NTOV(nmp->nm_ifile_node), 0);
-
- /* Get node */
- error = nandfs_get_node_raw(nmp->nm_nandfsdev, nmp, ino, &inode, nodep);
- if (error) {
- *nodep = NULL;
- return (error);
- }
-
- nvp = (*nodep)->nn_vnode;
- error = vfs_hash_insert(nvp, ino, 0, td, &vpp, NULL, NULL);
- if (error) {
- *nodep = NULL;
- return (error);
- }
-
- return (error);
-}
-
-void
-nandfs_dispose_node(struct nandfs_node **nodep)
-{
- struct nandfs_node *node;
- struct vnode *vp;
-
- /* Protect against rogue values */
- node = *nodep;
- if (!node) {
- return;
- }
- DPRINTF(NODE, ("nandfs_dispose_node: %p\n", *nodep));
-
- vp = NTOV(node);
- vp->v_data = NULL;
-
- /* Free our associated memory */
- uma_zfree(nandfs_node_zone, node);
-
- *nodep = NULL;
-}
-
-int
-nandfs_lookup_name_in_dir(struct vnode *dvp, const char *name, int namelen,
- uint64_t *ino, int *found, uint64_t *off)
-{
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfs_dir_entry *ndirent;
- struct buf *bp;
- uint64_t file_size, diroffset, blkoff;
- uint64_t blocknr;
- uint32_t blocksize = dir_node->nn_nandfsdev->nd_blocksize;
- uint8_t *pos, name_len;
- int error;
-
- *found = 0;
-
- DPRINTF(VNCALL, ("%s: %s file\n", __func__, name));
- if (dvp->v_type != VDIR) {
- return (ENOTDIR);
- }
-
- /* Get directory filesize */
- file_size = dir_node->nn_inode.i_size;
-
- /* Walk the directory */
- diroffset = 0;
- blocknr = 0;
- blkoff = 0;
- error = nandfs_bread(dir_node, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (EIO);
- }
-
- while (diroffset < file_size) {
- if (blkoff >= blocksize) {
- blkoff = 0; blocknr++;
- brelse(bp);
- error = nandfs_bread(dir_node, blocknr, NOCRED, 0,
- &bp);
- if (error) {
- brelse(bp);
- return (EIO);
- }
- }
-
- /* Read in one dirent */
- pos = (uint8_t *) bp->b_data + blkoff;
- ndirent = (struct nandfs_dir_entry *) pos;
- name_len = ndirent->name_len;
-
- if ((name_len == namelen) &&
- (strncmp(name, ndirent->name, name_len) == 0) &&
- (ndirent->inode != 0)) {
- *ino = ndirent->inode;
- *off = diroffset;
- DPRINTF(LOOKUP, ("found `%.*s` with ino %"PRIx64"\n",
- name_len, ndirent->name, *ino));
- *found = 1;
- break;
- }
-
- /* Advance */
- diroffset += ndirent->rec_len;
- blkoff += ndirent->rec_len;
- }
- brelse(bp);
-
- return (error);
-}
-
-int
-nandfs_get_fsinfo(struct nandfsmount *nmp, struct nandfs_fsinfo *fsinfo)
-{
- struct nandfs_device *fsdev;
-
- fsdev = nmp->nm_nandfsdev;
-
- memcpy(&fsinfo->fs_fsdata, &fsdev->nd_fsdata, sizeof(fsdev->nd_fsdata));
- memcpy(&fsinfo->fs_super, &fsdev->nd_super, sizeof(fsdev->nd_super));
- snprintf(fsinfo->fs_dev, sizeof(fsinfo->fs_dev),
- "%s", nmp->nm_vfs_mountp->mnt_stat.f_mntfromname);
-
- return (0);
-}
-
-void
-nandfs_inode_init(struct nandfs_inode *inode, uint16_t mode)
-{
- struct timespec ts;
-
- vfs_timestamp(&ts);
-
- inode->i_blocks = 0;
- inode->i_size = 0;
- inode->i_ctime = ts.tv_sec;
- inode->i_ctime_nsec = ts.tv_nsec;
- inode->i_mtime = ts.tv_sec;
- inode->i_mtime_nsec = ts.tv_nsec;
- inode->i_mode = mode;
- inode->i_links_count = 1;
- if (S_ISDIR(mode))
- inode->i_links_count = 2;
- inode->i_flags = 0;
-
- inode->i_special = 0;
- memset(inode->i_db, 0, sizeof(inode->i_db));
- memset(inode->i_ib, 0, sizeof(inode->i_ib));
-}
-
-void
-nandfs_inode_destroy(struct nandfs_inode *inode)
-{
-
- MPASS(inode->i_blocks == 0);
- bzero(inode, sizeof(*inode));
-}
-
-int
-nandfs_fs_full(struct nandfs_device *nffsdev)
-{
- uint64_t space, bps;
-
- bps = nffsdev->nd_fsdata.f_blocks_per_segment;
- space = (nffsdev->nd_clean_segs - 1) * bps;
-
- DPRINTF(BUF, ("%s: bufs:%jx space:%jx\n", __func__,
- (uintmax_t)nffsdev->nd_dirty_bufs, (uintmax_t)space));
-
- if (nffsdev->nd_dirty_bufs + (nffsdev->nd_segs_reserved * bps) >= space)
- return (1);
-
- return (0);
-}
-
-static int
-_nandfs_dirty_buf(struct buf *bp, int dirty_meta, int force)
-{
- struct nandfs_device *nffsdev;
- struct nandfs_node *node;
- uint64_t ino, bps;
-
- if (NANDFS_ISGATHERED(bp)) {
- bqrelse(bp);
- return (0);
- }
- if ((bp->b_flags & (B_MANAGED | B_DELWRI)) == (B_MANAGED | B_DELWRI)) {
- bqrelse(bp);
- return (0);
- }
-
- node = VTON(bp->b_vp);
- nffsdev = node->nn_nandfsdev;
- DPRINTF(BUF, ("%s: buf:%p\n", __func__, bp));
- ino = node->nn_ino;
-
- if (nandfs_fs_full(nffsdev) && !NANDFS_SYS_NODE(ino) && !force) {
- brelse(bp);
- return (ENOSPC);
- }
-
- bp->b_flags |= B_MANAGED;
- bdwrite(bp);
-
- nandfs_dirty_bufs_increment(nffsdev);
-
- KASSERT((bp->b_vp), ("vp missing for bp"));
- KASSERT((nandfs_vblk_get(bp) || ino == NANDFS_DAT_INO),
- ("bp vblk is 0"));
-
- /*
- * To maintain consistency of FS we need to force making
- * meta buffers dirty, even if free space is low.
- */
- if (dirty_meta && ino != NANDFS_GC_INO)
- nandfs_bmap_dirty_blocks(VTON(bp->b_vp), bp, 1);
-
- bps = nffsdev->nd_fsdata.f_blocks_per_segment;
-
- if (nffsdev->nd_dirty_bufs >= (bps * nandfs_max_dirty_segs)) {
- mtx_lock(&nffsdev->nd_sync_mtx);
- if (nffsdev->nd_syncing == 0) {
- DPRINTF(SYNC, ("%s: wakeup gc\n", __func__));
- nffsdev->nd_syncing = 1;
- wakeup(&nffsdev->nd_syncing);
- }
- mtx_unlock(&nffsdev->nd_sync_mtx);
- }
-
- return (0);
-}
-
-int
-nandfs_dirty_buf(struct buf *bp, int force)
-{
-
- return (_nandfs_dirty_buf(bp, 1, force));
-}
-
-int
-nandfs_dirty_buf_meta(struct buf *bp, int force)
-{
-
- return (_nandfs_dirty_buf(bp, 0, force));
-}
-
-void
-nandfs_undirty_buf_fsdev(struct nandfs_device *nffsdev, struct buf *bp)
-{
-
- BUF_ASSERT_HELD(bp);
-
- if (bp->b_flags & B_DELWRI) {
- bp->b_flags &= ~(B_DELWRI|B_MANAGED);
- nandfs_dirty_bufs_decrement(nffsdev);
- }
- /*
- * Since it is now being written, we can clear its deferred write flag.
- */
- bp->b_flags &= ~B_DEFERRED;
-
- brelse(bp);
-}
-
-void
-nandfs_undirty_buf(struct buf *bp)
-{
- struct nandfs_node *node;
-
- node = VTON(bp->b_vp);
-
- nandfs_undirty_buf_fsdev(node->nn_nandfsdev, bp);
-}
-
-void
-nandfs_vblk_set(struct buf *bp, nandfs_daddr_t blocknr)
-{
-
- nandfs_daddr_t *vblk = (nandfs_daddr_t *)(&bp->b_fsprivate1);
- *vblk = blocknr;
-}
-
-nandfs_daddr_t
-nandfs_vblk_get(struct buf *bp)
-{
-
- nandfs_daddr_t *vblk = (nandfs_daddr_t *)(&bp->b_fsprivate1);
- return (*vblk);
-}
-
-void
-nandfs_buf_set(struct buf *bp, uint32_t bits)
-{
- uintptr_t flags;
-
- flags = (uintptr_t)bp->b_fsprivate3;
- flags |= (uintptr_t)bits;
- bp->b_fsprivate3 = (void *)flags;
-}
-
-void
-nandfs_buf_clear(struct buf *bp, uint32_t bits)
-{
- uintptr_t flags;
-
- flags = (uintptr_t)bp->b_fsprivate3;
- flags &= ~(uintptr_t)bits;
- bp->b_fsprivate3 = (void *)flags;
-}
-
-int
-nandfs_buf_check(struct buf *bp, uint32_t bits)
-{
- uintptr_t flags;
-
- flags = (uintptr_t)bp->b_fsprivate3;
- if (flags & bits)
- return (1);
- return (0);
-}
-
-int
-nandfs_erase(struct nandfs_device *fsdev, off_t offset, size_t size)
-{
- DPRINTF(BLOCK, ("%s: performing erase at offset %jx size %zx\n",
- __func__, offset, size));
-
- MPASS(size % fsdev->nd_erasesize == 0);
-
- return (g_delete_data(fsdev->nd_gconsumer, offset, size));
-}
-
-int
-nandfs_vop_islocked(struct vnode *vp)
-{
- int islocked;
-
- islocked = VOP_ISLOCKED(vp);
- return (islocked == LK_EXCLUSIVE || islocked == LK_SHARED);
-}
-
-nandfs_daddr_t
-nandfs_block_to_dblock(struct nandfs_device *fsdev, nandfs_lbn_t block)
-{
-
- return (btodb(block * fsdev->nd_blocksize));
-}
diff --git a/sys/fs/nandfs/nandfs_subr.h b/sys/fs/nandfs/nandfs_subr.h
deleted file mode 100644
index 36c2c9dc2ff2..000000000000
--- a/sys/fs/nandfs/nandfs_subr.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_subr.h,v 1.1 2009/07/18 16:31:42 reinoud
- *
- * $FreeBSD$
- */
-
-#ifndef _FS_NANDFS_NANDFS_SUBR_H_
-#define _FS_NANDFS_NANDFS_SUBR_H_
-
-struct nandfs_mdt;
-
-struct nandfs_alloc_request
-{
- uint64_t entrynum;
- struct buf *bp_desc;
- struct buf *bp_bitmap;
- struct buf *bp_entry;
-};
-
-/* Segment creation */
-void nandfs_wakeup_wait_sync(struct nandfs_device *, int);
-int nandfs_segment_constructor(struct nandfsmount *, int);
-int nandfs_sync_file(struct vnode *);
-
-/* Basic calculators */
-uint64_t nandfs_get_segnum_of_block(struct nandfs_device *, nandfs_daddr_t);
-void nandfs_get_segment_range(struct nandfs_device *, uint64_t, uint64_t *,
- uint64_t *);
-void nandfs_calc_mdt_consts(struct nandfs_device *, struct nandfs_mdt *, int);
-
-/* Log reading / volume helpers */
-int nandfs_search_super_root(struct nandfs_device *);
-
-/* Reading */
-int nandfs_dev_bread(struct nandfs_device *, nandfs_daddr_t, struct ucred *,
- int, struct buf **);
-int nandfs_bread(struct nandfs_node *, nandfs_lbn_t, struct ucred *, int,
- struct buf **);
-int nandfs_bread_meta(struct nandfs_node *, nandfs_lbn_t, struct ucred *, int,
- struct buf **);
-int nandfs_bdestroy(struct nandfs_node *, nandfs_daddr_t);
-int nandfs_bcreate(struct nandfs_node *, nandfs_lbn_t, struct ucred *, int,
- struct buf **);
-int nandfs_bcreate_meta(struct nandfs_node *, nandfs_lbn_t, struct ucred *,
- int, struct buf **);
-int nandfs_bread_create(struct nandfs_node *, nandfs_lbn_t, struct ucred *,
- int, struct buf **);
-
-/* vtop operations */
-int nandfs_vtop(struct nandfs_node *, nandfs_daddr_t, nandfs_daddr_t *);
-
-/* Node action implementators */
-int nandfs_vinit(struct vnode *, uint64_t);
-int nandfs_get_node(struct nandfsmount *, uint64_t, struct nandfs_node **);
-int nandfs_get_node_raw(struct nandfs_device *, struct nandfsmount *, uint64_t,
- struct nandfs_inode *, struct nandfs_node **);
-void nandfs_dispose_node(struct nandfs_node **);
-
-void nandfs_itimes(struct vnode *);
-int nandfs_lookup_name_in_dir(struct vnode *, const char *, int, uint64_t *,
- int *, uint64_t *);
-int nandfs_create_node(struct vnode *, struct vnode **, struct vattr *,
- struct componentname *);
-void nandfs_delete_node(struct nandfs_node *);
-
-int nandfs_chsize(struct vnode *, u_quad_t, struct ucred *);
-int nandfs_dir_detach(struct nandfsmount *, struct nandfs_node *,
- struct nandfs_node *, struct componentname *);
-int nandfs_dir_attach(struct nandfsmount *, struct nandfs_node *,
- struct nandfs_node *, struct vattr *, struct componentname *);
-
-int nandfs_dirty_buf(struct buf *, int);
-int nandfs_dirty_buf_meta(struct buf *, int);
-int nandfs_fs_full(struct nandfs_device *);
-void nandfs_undirty_buf_fsdev(struct nandfs_device *, struct buf *);
-void nandfs_undirty_buf(struct buf *);
-
-void nandfs_clear_buf(struct buf *);
-void nandfs_buf_set(struct buf *, uint32_t);
-void nandfs_buf_clear(struct buf *, uint32_t);
-int nandfs_buf_check(struct buf *, uint32_t);
-
-int nandfs_find_free_entry(struct nandfs_mdt *, struct nandfs_node *,
- struct nandfs_alloc_request *);
-int nandfs_find_entry(struct nandfs_mdt *, struct nandfs_node *,
- struct nandfs_alloc_request *);
-int nandfs_alloc_entry(struct nandfs_mdt *, struct nandfs_alloc_request *);
-void nandfs_abort_entry(struct nandfs_alloc_request *);
-int nandfs_free_entry(struct nandfs_mdt *, struct nandfs_alloc_request *);
-int nandfs_get_entry_block(struct nandfs_mdt *, struct nandfs_node *,
- struct nandfs_alloc_request *, uint32_t *, int);
-
-/* Inode management. */
-int nandfs_node_create(struct nandfsmount *, struct nandfs_node **, uint16_t);
-int nandfs_node_destroy(struct nandfs_node *);
-int nandfs_node_update(struct nandfs_node *);
-int nandfs_get_node_entry(struct nandfsmount *, struct nandfs_inode **,
- uint64_t, struct buf **);
-void nandfs_mdt_trans_blk(struct nandfs_mdt *, uint64_t, uint64_t *,
- uint64_t *, nandfs_lbn_t *, uint32_t *);
-
-/* vblock management */
-void nandfs_mdt_trans(struct nandfs_mdt *, uint64_t, nandfs_lbn_t *, uint32_t *);
-int nandfs_vblock_alloc(struct nandfs_device *, nandfs_daddr_t *);
-int nandfs_vblock_end(struct nandfs_device *, nandfs_daddr_t);
-int nandfs_vblock_assign(struct nandfs_device *, nandfs_daddr_t,
- nandfs_lbn_t);
-int nandfs_vblock_free(struct nandfs_device *, nandfs_daddr_t);
-
-/* Checkpoint management */
-int nandfs_get_checkpoint(struct nandfs_device *, struct nandfs_node *,
- uint64_t);
-int nandfs_set_checkpoint(struct nandfs_device *, struct nandfs_node *,
- uint64_t, struct nandfs_inode *, uint64_t);
-
-/* Segment management */
-int nandfs_alloc_segment(struct nandfs_device *, uint64_t *);
-int nandfs_update_segment(struct nandfs_device *, uint64_t, uint32_t);
-int nandfs_free_segment(struct nandfs_device *, uint64_t);
-int nandfs_clear_segment(struct nandfs_device *, uint64_t);
-int nandfs_touch_segment(struct nandfs_device *, uint64_t);
-int nandfs_markgc_segment(struct nandfs_device *, uint64_t);
-
-int nandfs_bmap_insert_block(struct nandfs_node *, nandfs_lbn_t, struct buf *);
-int nandfs_bmap_update_block(struct nandfs_node *, struct buf *, nandfs_lbn_t);
-int nandfs_bmap_update_dat(struct nandfs_node *, nandfs_daddr_t, struct buf *);
-int nandfs_bmap_dirty_blocks(struct nandfs_node *, struct buf *, int);
-int nandfs_bmap_truncate_mapping(struct nandfs_node *, nandfs_lbn_t,
- nandfs_lbn_t);
-int nandfs_bmap_lookup(struct nandfs_node *, nandfs_lbn_t, nandfs_daddr_t *);
-
-/* dirent */
-int nandfs_add_dirent(struct vnode *, uint64_t, char *, long, uint8_t);
-int nandfs_remove_dirent(struct vnode *, struct nandfs_node *,
- struct componentname *);
-int nandfs_update_dirent(struct vnode *, struct nandfs_node *,
- struct nandfs_node *);
-int nandfs_init_dir(struct vnode *, uint64_t, uint64_t);
-int nandfs_update_parent_dir(struct vnode *, uint64_t);
-
-void nandfs_vblk_set(struct buf *, nandfs_daddr_t);
-nandfs_daddr_t nandfs_vblk_get(struct buf *);
-
-void nandfs_inode_init(struct nandfs_inode *, uint16_t);
-void nandfs_inode_destroy(struct nandfs_inode *);
-
-/* ioctl */
-int nandfs_get_seg_stat(struct nandfs_device *, struct nandfs_seg_stat *);
-int nandfs_chng_cpmode(struct nandfs_node *, struct nandfs_cpmode *);
-int nandfs_get_cpinfo_ioctl(struct nandfs_node *, struct nandfs_argv *);
-int nandfs_delete_cp(struct nandfs_node *, uint64_t start, uint64_t);
-int nandfs_make_snap(struct nandfs_device *, uint64_t *);
-int nandfs_delete_snap(struct nandfs_device *, uint64_t);
-int nandfs_get_cpstat(struct nandfs_node *, struct nandfs_cpstat *);
-int nandfs_get_segment_info_ioctl(struct nandfs_device *, struct nandfs_argv *);
-int nandfs_get_dat_vinfo_ioctl(struct nandfs_device *, struct nandfs_argv *);
-int nandfs_get_dat_bdescs_ioctl(struct nandfs_device *, struct nandfs_argv *);
-int nandfs_get_fsinfo(struct nandfsmount *, struct nandfs_fsinfo *);
-
-int nandfs_get_cpinfo(struct nandfs_node *, uint64_t, uint16_t,
- struct nandfs_cpinfo *, uint32_t, uint32_t *);
-
-nandfs_lbn_t nandfs_get_maxfilesize(struct nandfs_device *);
-
-int nandfs_write_superblock(struct nandfs_device *);
-
-extern int nandfs_sync_interval;
-extern int nandfs_max_dirty_segs;
-extern int nandfs_cps_between_sblocks;
-
-struct buf *nandfs_geteblk(int, int);
-
-void nandfs_dirty_bufs_increment(struct nandfs_device *);
-void nandfs_dirty_bufs_decrement(struct nandfs_device *);
-
-int nandfs_start_cleaner(struct nandfs_device *);
-int nandfs_stop_cleaner(struct nandfs_device *);
-
-int nandfs_segsum_valid(struct nandfs_segment_summary *);
-int nandfs_load_segsum(struct nandfs_device *, nandfs_daddr_t,
- struct nandfs_segment_summary *);
-int nandfs_get_segment_info(struct nandfs_device *, struct nandfs_suinfo *,
- uint32_t, uint64_t);
-int nandfs_get_segment_info_filter(struct nandfs_device *,
- struct nandfs_suinfo *, uint32_t, uint64_t, uint64_t *, uint32_t, uint32_t);
-int nandfs_get_dat_vinfo(struct nandfs_device *, struct nandfs_vinfo *,
- uint32_t);
-int nandfs_get_dat_bdescs(struct nandfs_device *, struct nandfs_bdesc *,
- uint32_t);
-
-#define NANDFS_VBLK_ASSIGNED 1
-
-#define NANDFS_IS_INDIRECT(bp) ((bp)->b_lblkno < 0)
-
-int nandfs_erase(struct nandfs_device *, off_t, size_t);
-
-#define NANDFS_VOP_ISLOCKED(vp) nandfs_vop_islocked((vp))
-int nandfs_vop_islocked(struct vnode *vp);
-
-nandfs_daddr_t nandfs_block_to_dblock(struct nandfs_device *, nandfs_lbn_t);
-
-#define DEBUG_MODE
-#if defined(DEBUG_MODE)
-#define nandfs_error panic
-#define nandfs_warning printf
-#elif defined(TEST_MODE)
-#define nandfs_error printf
-#define nandfs_warning printf
-#else
-#define nandfs_error(...)
-#define nandfs_warning(...)
-#endif
-
-#endif /* !_FS_NANDFS_NANDFS_SUBR_H_ */
diff --git a/sys/fs/nandfs/nandfs_sufile.c b/sys/fs/nandfs/nandfs_sufile.c
deleted file mode 100644
index 5276008de096..000000000000
--- a/sys/fs/nandfs/nandfs_sufile.c
+++ /dev/null
@@ -1,571 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_page.h>
-
-#include <geom/geom.h>
-#include <geom/geom_vfs.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-#define SU_USAGE_OFF(bp, offset) \
- ((struct nandfs_segment_usage *)((bp)->b_data + offset))
-
-static int
-nandfs_seg_usage_blk_offset(struct nandfs_device *fsdev, uint64_t seg,
- uint64_t *blk, uint64_t *offset)
-{
- uint64_t off;
- uint16_t seg_size;
-
- seg_size = fsdev->nd_fsdata.f_segment_usage_size;
-
- off = roundup(sizeof(struct nandfs_sufile_header), seg_size);
- off += (seg * seg_size);
-
- *blk = off / fsdev->nd_blocksize;
- *offset = off % fsdev->nd_blocksize;
- return (0);
-}
-
-/* Alloc new segment */
-int
-nandfs_alloc_segment(struct nandfs_device *fsdev, uint64_t *seg)
-{
- struct nandfs_node *su_node;
- struct nandfs_sufile_header *su_header;
- struct nandfs_segment_usage *su_usage;
- struct buf *bp_header, *bp;
- uint64_t blk, vblk, offset, i, rest, nsegments;
- uint16_t seg_size;
- int error, found;
-
- seg_size = fsdev->nd_fsdata.f_segment_usage_size;
- nsegments = fsdev->nd_fsdata.f_nsegments;
-
- su_node = fsdev->nd_su_node;
- ASSERT_VOP_LOCKED(NTOV(su_node), __func__);
-
- /* Read header buffer */
- error = nandfs_bread(su_node, 0, NOCRED, 0, &bp_header);
- if (error) {
- brelse(bp_header);
- return (error);
- }
-
- su_header = (struct nandfs_sufile_header *)bp_header->b_data;
-
- /* Get last allocated segment */
- i = su_header->sh_last_alloc + 1;
-
- found = 0;
- bp = NULL;
- while (!found) {
- nandfs_seg_usage_blk_offset(fsdev, i, &blk, &offset);
- if(blk != 0) {
- error = nandfs_bmap_lookup(su_node, blk, &vblk);
- if (error) {
- nandfs_error("%s: cannot find vblk for blk "
- "blk:%jx\n", __func__, blk);
- return (error);
- }
- if (vblk)
- error = nandfs_bread(su_node, blk, NOCRED, 0,
- &bp);
- else
- error = nandfs_bcreate(su_node, blk, NOCRED, 0,
- &bp);
- if (error) {
- nandfs_error("%s: cannot create/read "
- "vblk:%jx\n", __func__, vblk);
- if (bp)
- brelse(bp);
- return (error);
- }
-
- su_usage = SU_USAGE_OFF(bp, offset);
- } else {
- su_usage = SU_USAGE_OFF(bp_header, offset);
- bp = bp_header;
- }
-
- rest = (fsdev->nd_blocksize - offset) / seg_size;
- /* Go through all su usage in block */
- while (rest) {
- /* When last check start from beginning */
- if (i == nsegments)
- break;
-
- if (!su_usage->su_flags) {
- su_usage->su_flags = 1;
- found = 1;
- break;
- }
- su_usage++;
- i++;
-
- /* If all checked return error */
- if (i == su_header->sh_last_alloc) {
- DPRINTF(SEG, ("%s: cannot allocate segment \n",
- __func__));
- brelse(bp_header);
- if (blk != 0)
- brelse(bp);
- return (1);
- }
- rest--;
- }
- if (!found) {
- /* Otherwise read another block */
- if (blk != 0)
- brelse(bp);
- if (i == nsegments) {
- blk = 0;
- i = 0;
- } else
- blk++;
- offset = 0;
- }
- }
-
- if (found) {
- *seg = i;
- su_header->sh_last_alloc = i;
- su_header->sh_ncleansegs--;
- su_header->sh_ndirtysegs++;
-
- fsdev->nd_super.s_free_blocks_count = su_header->sh_ncleansegs *
- fsdev->nd_fsdata.f_blocks_per_segment;
- fsdev->nd_clean_segs--;
-
- /*
- * It is mostly called from syncer() so we want to force
- * making buf dirty.
- */
- error = nandfs_dirty_buf(bp_header, 1);
- if (error) {
- if (bp && bp != bp_header)
- brelse(bp);
- return (error);
- }
- if (bp && bp != bp_header)
- nandfs_dirty_buf(bp, 1);
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)i));
-
- return (0);
- }
-
- DPRINTF(SEG, ("%s: failed\n", __func__));
-
- return (1);
-}
-
-/*
- * Make buffer dirty, it will be updated soon but first it need to be
- * gathered by syncer.
- */
-int
-nandfs_touch_segment(struct nandfs_device *fsdev, uint64_t seg)
-{
- struct nandfs_node *su_node;
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- su_node = fsdev->nd_su_node;
- ASSERT_VOP_LOCKED(NTOV(su_node), __func__);
-
- nandfs_seg_usage_blk_offset(fsdev, seg, &blk, &offset);
-
- error = nandfs_bread(su_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- nandfs_error("%s: cannot preallocate new segment\n", __func__);
- return (error);
- } else
- nandfs_dirty_buf(bp, 1);
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)seg));
- return (error);
-}
-
-/* Update block count of segment */
-int
-nandfs_update_segment(struct nandfs_device *fsdev, uint64_t seg, uint32_t nblks)
-{
- struct nandfs_node *su_node;
- struct nandfs_segment_usage *su_usage;
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- su_node = fsdev->nd_su_node;
- ASSERT_VOP_LOCKED(NTOV(su_node), __func__);
-
- nandfs_seg_usage_blk_offset(fsdev, seg, &blk, &offset);
-
- error = nandfs_bread(su_node, blk, NOCRED, 0, &bp);
- if (error) {
- nandfs_error("%s: read block:%jx to update\n",
- __func__, blk);
- brelse(bp);
- return (error);
- }
-
- su_usage = SU_USAGE_OFF(bp, offset);
- su_usage->su_lastmod = fsdev->nd_ts.tv_sec;
- su_usage->su_flags = NANDFS_SEGMENT_USAGE_DIRTY;
- su_usage->su_nblocks += nblks;
-
- DPRINTF(SEG, ("%s: seg:%#jx inc:%#x cur:%#x\n", __func__,
- (uintmax_t)seg, nblks, su_usage->su_nblocks));
-
- nandfs_dirty_buf(bp, 1);
-
- return (0);
-}
-
-/* Make segment free */
-int
-nandfs_free_segment(struct nandfs_device *fsdev, uint64_t seg)
-{
- struct nandfs_node *su_node;
- struct nandfs_sufile_header *su_header;
- struct nandfs_segment_usage *su_usage;
- struct buf *bp_header, *bp;
- uint64_t blk, offset;
- int error;
-
- su_node = fsdev->nd_su_node;
- ASSERT_VOP_LOCKED(NTOV(su_node), __func__);
-
- /* Read su header */
- error = nandfs_bread(su_node, 0, NOCRED, 0, &bp_header);
- if (error) {
- brelse(bp_header);
- return (error);
- }
-
- su_header = (struct nandfs_sufile_header *)bp_header->b_data;
- nandfs_seg_usage_blk_offset(fsdev, seg, &blk, &offset);
-
- /* Read su usage block if other than su header block */
- if (blk != 0) {
- error = nandfs_bread(su_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- brelse(bp_header);
- return (error);
- }
- } else
- bp = bp_header;
-
- /* Reset su usage data */
- su_usage = SU_USAGE_OFF(bp, offset);
- su_usage->su_lastmod = fsdev->nd_ts.tv_sec;
- su_usage->su_nblocks = 0;
- su_usage->su_flags = 0;
-
- /* Update clean/dirty counter in header */
- su_header->sh_ncleansegs++;
- su_header->sh_ndirtysegs--;
-
- /*
- * Make buffers dirty, called by cleaner
- * so force dirty even if no much space left
- * on device
- */
- nandfs_dirty_buf(bp_header, 1);
- if (bp != bp_header)
- nandfs_dirty_buf(bp, 1);
-
- /* Update free block count */
- fsdev->nd_super.s_free_blocks_count = su_header->sh_ncleansegs *
- fsdev->nd_fsdata.f_blocks_per_segment;
- fsdev->nd_clean_segs++;
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)seg));
-
- return (0);
-}
-
-static int
-nandfs_bad_segment(struct nandfs_device *fsdev, uint64_t seg)
-{
- struct nandfs_node *su_node;
- struct nandfs_segment_usage *su_usage;
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- su_node = fsdev->nd_su_node;
- ASSERT_VOP_LOCKED(NTOV(su_node), __func__);
-
- nandfs_seg_usage_blk_offset(fsdev, seg, &blk, &offset);
-
- error = nandfs_bread(su_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- su_usage = SU_USAGE_OFF(bp, offset);
- su_usage->su_lastmod = fsdev->nd_ts.tv_sec;
- su_usage->su_flags = NANDFS_SEGMENT_USAGE_ERROR;
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)seg));
-
- nandfs_dirty_buf(bp, 1);
-
- return (0);
-}
-
-int
-nandfs_markgc_segment(struct nandfs_device *fsdev, uint64_t seg)
-{
- struct nandfs_node *su_node;
- struct nandfs_segment_usage *su_usage;
- struct buf *bp;
- uint64_t blk, offset;
- int error;
-
- su_node = fsdev->nd_su_node;
-
- VOP_LOCK(NTOV(su_node), LK_EXCLUSIVE);
-
- nandfs_seg_usage_blk_offset(fsdev, seg, &blk, &offset);
-
- error = nandfs_bread(su_node, blk, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(su_node), 0);
- return (error);
- }
-
- su_usage = SU_USAGE_OFF(bp, offset);
- MPASS((su_usage->su_flags & NANDFS_SEGMENT_USAGE_GC) == 0);
- su_usage->su_flags |= NANDFS_SEGMENT_USAGE_GC;
-
- brelse(bp);
- VOP_UNLOCK(NTOV(su_node), 0);
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)seg));
-
- return (0);
-}
-
-int
-nandfs_clear_segment(struct nandfs_device *fsdev, uint64_t seg)
-{
- uint64_t offset, segsize;
- uint32_t bps, bsize;
- int error = 0;
-
- bps = fsdev->nd_fsdata.f_blocks_per_segment;
- bsize = fsdev->nd_blocksize;
- segsize = bsize * bps;
- nandfs_get_segment_range(fsdev, seg, &offset, NULL);
- offset *= bsize;
-
- DPRINTF(SEG, ("%s: seg:%#jx\n", __func__, (uintmax_t)seg));
-
- /* Erase it and mark it bad when fail */
- if (nandfs_erase(fsdev, offset, segsize))
- error = nandfs_bad_segment(fsdev, seg);
-
- if (error)
- return (error);
-
- /* Mark it free */
- error = nandfs_free_segment(fsdev, seg);
-
- return (error);
-}
-
-int
-nandfs_get_seg_stat(struct nandfs_device *nandfsdev,
- struct nandfs_seg_stat *nss)
-{
- struct nandfs_sufile_header *suhdr;
- struct nandfs_node *su_node;
- struct buf *bp;
- int err;
-
- su_node = nandfsdev->nd_su_node;
-
- NANDFS_WRITELOCK(nandfsdev);
- VOP_LOCK(NTOV(su_node), LK_SHARED);
- err = nandfs_bread(nandfsdev->nd_su_node, 0, NOCRED, 0, &bp);
- if (err) {
- brelse(bp);
- VOP_UNLOCK(NTOV(su_node), 0);
- NANDFS_WRITEUNLOCK(nandfsdev);
- return (-1);
- }
-
- suhdr = (struct nandfs_sufile_header *)bp->b_data;
- nss->nss_nsegs = nandfsdev->nd_fsdata.f_nsegments;
- nss->nss_ncleansegs = suhdr->sh_ncleansegs;
- nss->nss_ndirtysegs = suhdr->sh_ndirtysegs;
- nss->nss_ctime = 0;
- nss->nss_nongc_ctime = nandfsdev->nd_ts.tv_sec;
- nss->nss_prot_seq = nandfsdev->nd_seg_sequence;
-
- brelse(bp);
- VOP_UNLOCK(NTOV(su_node), 0);
-
- NANDFS_WRITEUNLOCK(nandfsdev);
-
- return (0);
-}
-
-int
-nandfs_get_segment_info_ioctl(struct nandfs_device *fsdev,
- struct nandfs_argv *nargv)
-{
- struct nandfs_suinfo *nsi;
- int error;
-
- if (nargv->nv_nmembs > NANDFS_SEGMENTS_MAX)
- return (EINVAL);
-
- nsi = malloc(sizeof(struct nandfs_suinfo) * nargv->nv_nmembs,
- M_NANDFSTEMP, M_WAITOK | M_ZERO);
-
- error = nandfs_get_segment_info(fsdev, nsi, nargv->nv_nmembs,
- nargv->nv_index);
-
- if (error == 0)
- error = copyout(nsi, (void *)(uintptr_t)nargv->nv_base,
- sizeof(struct nandfs_suinfo) * nargv->nv_nmembs);
-
- free(nsi, M_NANDFSTEMP);
- return (error);
-}
-
-int
-nandfs_get_segment_info(struct nandfs_device *fsdev, struct nandfs_suinfo *nsi,
- uint32_t nmembs, uint64_t segment)
-{
-
- return (nandfs_get_segment_info_filter(fsdev, nsi, nmembs, segment,
- NULL, 0, 0));
-}
-
-int
-nandfs_get_segment_info_filter(struct nandfs_device *fsdev,
- struct nandfs_suinfo *nsi, uint32_t nmembs, uint64_t segment,
- uint64_t *nsegs, uint32_t filter, uint32_t nfilter)
-{
- struct nandfs_segment_usage *su;
- struct nandfs_node *su_node;
- struct buf *bp;
- uint64_t curr, blocknr, blockoff, i;
- uint32_t flags;
- int err = 0;
-
- curr = ~(0);
-
- lockmgr(&fsdev->nd_seg_const, LK_EXCLUSIVE, NULL);
- su_node = fsdev->nd_su_node;
-
- VOP_LOCK(NTOV(su_node), LK_SHARED);
-
- bp = NULL;
- if (nsegs != NULL)
- *nsegs = 0;
- for (i = 0; i < nmembs; segment++) {
- if (segment == fsdev->nd_fsdata.f_nsegments)
- break;
-
- nandfs_seg_usage_blk_offset(fsdev, segment, &blocknr,
- &blockoff);
-
- if (i == 0 || curr != blocknr) {
- if (bp != NULL)
- brelse(bp);
- err = nandfs_bread(su_node, blocknr, NOCRED,
- 0, &bp);
- if (err) {
- goto out;
- }
- curr = blocknr;
- }
-
- su = SU_USAGE_OFF(bp, blockoff);
- flags = su->su_flags;
- if (segment == fsdev->nd_seg_num ||
- segment == fsdev->nd_next_seg_num)
- flags |= NANDFS_SEGMENT_USAGE_ACTIVE;
-
- if (nfilter != 0 && (flags & nfilter) != 0)
- continue;
- if (filter != 0 && (flags & filter) == 0)
- continue;
-
- nsi->nsi_num = segment;
- nsi->nsi_lastmod = su->su_lastmod;
- nsi->nsi_blocks = su->su_nblocks;
- nsi->nsi_flags = flags;
- nsi++;
- i++;
- if (nsegs != NULL)
- (*nsegs)++;
- }
-
-out:
- if (bp != NULL)
- brelse(bp);
- VOP_UNLOCK(NTOV(su_node), 0);
- lockmgr(&fsdev->nd_seg_const, LK_RELEASE, NULL);
-
- return (err);
-}
diff --git a/sys/fs/nandfs/nandfs_vfsops.c b/sys/fs/nandfs/nandfs_vfsops.c
deleted file mode 100644
index f703044728ef..000000000000
--- a/sys/fs/nandfs/nandfs_vfsops.c
+++ /dev/null
@@ -1,1601 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_vfsops.c,v 1.1 2009/07/18 16:31:42 reinoud Exp
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/fcntl.h>
-#include <sys/gsb_crc32.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/proc.h>
-#include <sys/priv.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/sysctl.h>
-#include <sys/libkern.h>
-
-#include <geom/geom.h>
-#include <geom/geom_vfs.h>
-
-#include <machine/_inttypes.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-static MALLOC_DEFINE(M_NANDFSMNT, "nandfs_mount", "NANDFS mount structure");
-
-#define NANDFS_SET_SYSTEMFILE(vp) { \
- (vp)->v_vflag |= VV_SYSTEM; \
- vref(vp); \
- vput(vp); }
-
-#define NANDFS_UNSET_SYSTEMFILE(vp) { \
- VOP_LOCK(vp, LK_EXCLUSIVE); \
- MPASS(vp->v_bufobj.bo_dirty.bv_cnt == 0); \
- (vp)->v_vflag &= ~VV_SYSTEM; \
- vgone(vp); \
- vput(vp); }
-
-/* Globals */
-struct _nandfs_devices nandfs_devices;
-
-/* Parameters */
-int nandfs_verbose = 0;
-
-static void
-nandfs_tunable_init(void *arg)
-{
-
- TUNABLE_INT_FETCH("vfs.nandfs.verbose", &nandfs_verbose);
-}
-SYSINIT(nandfs_tunables, SI_SUB_VFS, SI_ORDER_ANY, nandfs_tunable_init, NULL);
-
-static SYSCTL_NODE(_vfs, OID_AUTO, nandfs, CTLFLAG_RD, 0, "NAND filesystem");
-static SYSCTL_NODE(_vfs_nandfs, OID_AUTO, mount, CTLFLAG_RD, 0,
- "NANDFS mountpoints");
-SYSCTL_INT(_vfs_nandfs, OID_AUTO, verbose, CTLFLAG_RW, &nandfs_verbose, 0, "");
-
-#define NANDFS_CONSTR_INTERVAL 5
-int nandfs_sync_interval = NANDFS_CONSTR_INTERVAL; /* sync every 5 seconds */
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, sync_interval, CTLFLAG_RW,
- &nandfs_sync_interval, 0, "");
-
-#define NANDFS_MAX_DIRTY_SEGS 5
-int nandfs_max_dirty_segs = NANDFS_MAX_DIRTY_SEGS; /* sync when 5 dirty seg */
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, max_dirty_segs, CTLFLAG_RW,
- &nandfs_max_dirty_segs, 0, "");
-
-#define NANDFS_CPS_BETWEEN_SBLOCKS 5
-int nandfs_cps_between_sblocks = NANDFS_CPS_BETWEEN_SBLOCKS; /* write superblock every 5 checkpoints */
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, cps_between_sblocks, CTLFLAG_RW,
- &nandfs_cps_between_sblocks, 0, "");
-
-#define NANDFS_CLEANER_ENABLE 1
-int nandfs_cleaner_enable = NANDFS_CLEANER_ENABLE;
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, cleaner_enable, CTLFLAG_RW,
- &nandfs_cleaner_enable, 0, "");
-
-#define NANDFS_CLEANER_INTERVAL 5
-int nandfs_cleaner_interval = NANDFS_CLEANER_INTERVAL;
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, cleaner_interval, CTLFLAG_RW,
- &nandfs_cleaner_interval, 0, "");
-
-#define NANDFS_CLEANER_SEGMENTS 5
-int nandfs_cleaner_segments = NANDFS_CLEANER_SEGMENTS;
-SYSCTL_UINT(_vfs_nandfs, OID_AUTO, cleaner_segments, CTLFLAG_RW,
- &nandfs_cleaner_segments, 0, "");
-
-static int nandfs_mountfs(struct vnode *devvp, struct mount *mp);
-static vfs_mount_t nandfs_mount;
-static vfs_root_t nandfs_root;
-static vfs_statfs_t nandfs_statfs;
-static vfs_unmount_t nandfs_unmount;
-static vfs_vget_t nandfs_vget;
-static vfs_sync_t nandfs_sync;
-static const char *nandfs_opts[] = {
- "snap", "from", "noatime", NULL
-};
-
-/* System nodes */
-static int
-nandfs_create_system_nodes(struct nandfs_device *nandfsdev)
-{
- int error;
-
- error = nandfs_get_node_raw(nandfsdev, NULL, NANDFS_DAT_INO,
- &nandfsdev->nd_super_root.sr_dat, &nandfsdev->nd_dat_node);
- if (error)
- goto errorout;
-
- error = nandfs_get_node_raw(nandfsdev, NULL, NANDFS_CPFILE_INO,
- &nandfsdev->nd_super_root.sr_cpfile, &nandfsdev->nd_cp_node);
- if (error)
- goto errorout;
-
- error = nandfs_get_node_raw(nandfsdev, NULL, NANDFS_SUFILE_INO,
- &nandfsdev->nd_super_root.sr_sufile, &nandfsdev->nd_su_node);
- if (error)
- goto errorout;
-
- error = nandfs_get_node_raw(nandfsdev, NULL, NANDFS_GC_INO,
- NULL, &nandfsdev->nd_gc_node);
- if (error)
- goto errorout;
-
- NANDFS_SET_SYSTEMFILE(NTOV(nandfsdev->nd_dat_node));
- NANDFS_SET_SYSTEMFILE(NTOV(nandfsdev->nd_cp_node));
- NANDFS_SET_SYSTEMFILE(NTOV(nandfsdev->nd_su_node));
- NANDFS_SET_SYSTEMFILE(NTOV(nandfsdev->nd_gc_node));
-
- DPRINTF(VOLUMES, ("System vnodes: dat: %p cp: %p su: %p\n",
- NTOV(nandfsdev->nd_dat_node), NTOV(nandfsdev->nd_cp_node),
- NTOV(nandfsdev->nd_su_node)));
- return (0);
-
-errorout:
- nandfs_dispose_node(&nandfsdev->nd_gc_node);
- nandfs_dispose_node(&nandfsdev->nd_dat_node);
- nandfs_dispose_node(&nandfsdev->nd_cp_node);
- nandfs_dispose_node(&nandfsdev->nd_su_node);
-
- return (error);
-}
-
-static void
-nandfs_release_system_nodes(struct nandfs_device *nandfsdev)
-{
-
- if (!nandfsdev)
- return;
- if (nandfsdev->nd_refcnt > 0)
- return;
-
- if (nandfsdev->nd_gc_node)
- NANDFS_UNSET_SYSTEMFILE(NTOV(nandfsdev->nd_gc_node));
- if (nandfsdev->nd_dat_node)
- NANDFS_UNSET_SYSTEMFILE(NTOV(nandfsdev->nd_dat_node));
- if (nandfsdev->nd_cp_node)
- NANDFS_UNSET_SYSTEMFILE(NTOV(nandfsdev->nd_cp_node));
- if (nandfsdev->nd_su_node)
- NANDFS_UNSET_SYSTEMFILE(NTOV(nandfsdev->nd_su_node));
-}
-
-static int
-nandfs_check_fsdata_crc(struct nandfs_fsdata *fsdata)
-{
- uint32_t fsdata_crc, comp_crc;
-
- if (fsdata->f_magic != NANDFS_FSDATA_MAGIC)
- return (0);
-
- /* Preserve CRC */
- fsdata_crc = fsdata->f_sum;
-
- /* Calculate */
- fsdata->f_sum = (0);
- comp_crc = crc32((uint8_t *)fsdata, fsdata->f_bytes);
-
- /* Restore */
- fsdata->f_sum = fsdata_crc;
-
- /* Check CRC */
- return (fsdata_crc == comp_crc);
-}
-
-static int
-nandfs_check_superblock_crc(struct nandfs_fsdata *fsdata,
- struct nandfs_super_block *super)
-{
- uint32_t super_crc, comp_crc;
-
- /* Check super block magic */
- if (super->s_magic != NANDFS_SUPER_MAGIC)
- return (0);
-
- /* Preserve CRC */
- super_crc = super->s_sum;
-
- /* Calculate */
- super->s_sum = (0);
- comp_crc = crc32((uint8_t *)super, fsdata->f_sbbytes);
-
- /* Restore */
- super->s_sum = super_crc;
-
- /* Check CRC */
- return (super_crc == comp_crc);
-}
-
-static void
-nandfs_calc_superblock_crc(struct nandfs_fsdata *fsdata,
- struct nandfs_super_block *super)
-{
- uint32_t comp_crc;
-
- /* Calculate */
- super->s_sum = 0;
- comp_crc = crc32((uint8_t *)super, fsdata->f_sbbytes);
-
- /* Restore */
- super->s_sum = comp_crc;
-}
-
-static int
-nandfs_is_empty(u_char *area, int size)
-{
- int i;
-
- for (i = 0; i < size; i++)
- if (area[i] != 0xff)
- return (0);
-
- return (1);
-}
-
-static __inline int
-nandfs_sblocks_in_esize(struct nandfs_device *fsdev)
-{
-
- return ((fsdev->nd_erasesize - NANDFS_SBLOCK_OFFSET_BYTES) /
- sizeof(struct nandfs_super_block));
-}
-
-static __inline int
-nandfs_max_sblocks(struct nandfs_device *fsdev)
-{
-
- return (NANDFS_NFSAREAS * nandfs_sblocks_in_esize(fsdev));
-}
-
-static __inline int
-nandfs_sblocks_in_block(struct nandfs_device *fsdev)
-{
-
- return (fsdev->nd_devblocksize / sizeof(struct nandfs_super_block));
-}
-
-#if 0
-static __inline int
-nandfs_sblocks_in_first_block(struct nandfs_device *fsdev)
-{
- int n;
-
- n = nandfs_sblocks_in_block(fsdev) -
- NANDFS_SBLOCK_OFFSET_BYTES / sizeof(struct nandfs_super_block);
- if (n < 0)
- n = 0;
-
- return (n);
-}
-#endif
-
-static int
-nandfs_write_superblock_at(struct nandfs_device *fsdev,
- struct nandfs_fsarea *fstp)
-{
- struct nandfs_super_block *super, *supert;
- struct buf *bp;
- int sb_per_sector, sbs_in_fsd, read_block;
- int index, pos, error;
- off_t offset;
-
- DPRINTF(SYNC, ("%s: last_used %d nandfs_sblocks_in_esize %d\n",
- __func__, fstp->last_used, nandfs_sblocks_in_esize(fsdev)));
- if (fstp->last_used == nandfs_sblocks_in_esize(fsdev) - 1)
- index = 0;
- else
- index = fstp->last_used + 1;
-
- super = &fsdev->nd_super;
- supert = NULL;
-
- sb_per_sector = nandfs_sblocks_in_block(fsdev);
- sbs_in_fsd = sizeof(struct nandfs_fsdata) /
- sizeof(struct nandfs_super_block);
- index += sbs_in_fsd;
- offset = fstp->offset;
-
- DPRINTF(SYNC, ("%s: offset %#jx s_last_pseg %#jx s_last_cno %#jx "
- "s_last_seq %#jx wtime %jd index %d\n", __func__, offset,
- super->s_last_pseg, super->s_last_cno, super->s_last_seq,
- super->s_wtime, index));
-
- read_block = btodb(offset + rounddown(index, sb_per_sector) *
- sizeof(struct nandfs_super_block));
-
- DPRINTF(SYNC, ("%s: read_block %#x\n", __func__, read_block));
-
- if (index == sbs_in_fsd) {
- error = nandfs_erase(fsdev, offset, fsdev->nd_erasesize);
- if (error)
- return (error);
-
- error = bread(fsdev->nd_devvp, btodb(offset),
- fsdev->nd_devblocksize, NOCRED, &bp);
- if (error) {
- printf("NANDFS: couldn't read initial data: %d\n",
- error);
- brelse(bp);
- return (error);
- }
- memcpy(bp->b_data, &fsdev->nd_fsdata, sizeof(fsdev->nd_fsdata));
- /*
- * 0xff-out the rest. This bp could be cached, so potentially
- * b_data contains stale super blocks.
- *
- * We don't mind cached bp since most of the time we just add
- * super blocks to already 0xff-out b_data and don't need to
- * perform actual read.
- */
- if (fsdev->nd_devblocksize > sizeof(fsdev->nd_fsdata))
- memset(bp->b_data + sizeof(fsdev->nd_fsdata), 0xff,
- fsdev->nd_devblocksize - sizeof(fsdev->nd_fsdata));
- error = bwrite(bp);
- if (error) {
- printf("NANDFS: cannot rewrite initial data at %jx\n",
- offset);
- return (error);
- }
- }
-
- error = bread(fsdev->nd_devvp, read_block, fsdev->nd_devblocksize,
- NOCRED, &bp);
- if (error) {
- brelse(bp);
- return (error);
- }
-
- supert = (struct nandfs_super_block *)(bp->b_data);
- pos = index % sb_per_sector;
-
- DPRINTF(SYNC, ("%s: storing at %d\n", __func__, pos));
- memcpy(&supert[pos], super, sizeof(struct nandfs_super_block));
-
- /*
- * See comment above in code that performs erase.
- */
- if (pos == 0)
- memset(&supert[1], 0xff,
- (sb_per_sector - 1) * sizeof(struct nandfs_super_block));
-
- error = bwrite(bp);
- if (error) {
- printf("NANDFS: cannot update superblock at %jx\n", offset);
- return (error);
- }
-
- DPRINTF(SYNC, ("%s: fstp->last_used %d -> %d\n", __func__,
- fstp->last_used, index - sbs_in_fsd));
- fstp->last_used = index - sbs_in_fsd;
-
- return (0);
-}
-
-int
-nandfs_write_superblock(struct nandfs_device *fsdev)
-{
- struct nandfs_super_block *super;
- struct timespec ts;
- int error;
- int i, j;
-
- vfs_timestamp(&ts);
-
- super = &fsdev->nd_super;
-
- super->s_last_pseg = fsdev->nd_last_pseg;
- super->s_last_cno = fsdev->nd_last_cno;
- super->s_last_seq = fsdev->nd_seg_sequence;
- super->s_wtime = ts.tv_sec;
-
- nandfs_calc_superblock_crc(&fsdev->nd_fsdata, super);
-
- error = 0;
- for (i = 0, j = fsdev->nd_last_fsarea; i < NANDFS_NFSAREAS;
- i++, j = (j + 1 % NANDFS_NFSAREAS)) {
- if (fsdev->nd_fsarea[j].flags & NANDFS_FSSTOR_FAILED) {
- DPRINTF(SYNC, ("%s: skipping %d\n", __func__, j));
- continue;
- }
- error = nandfs_write_superblock_at(fsdev, &fsdev->nd_fsarea[j]);
- if (error) {
- printf("NANDFS: writing superblock at offset %d failed:"
- "%d\n", j * fsdev->nd_erasesize, error);
- fsdev->nd_fsarea[j].flags |= NANDFS_FSSTOR_FAILED;
- } else
- break;
- }
-
- if (i == NANDFS_NFSAREAS) {
- printf("NANDFS: superblock was not written\n");
- /*
- * TODO: switch to read-only?
- */
- return (error);
- } else
- fsdev->nd_last_fsarea = (j + 1) % NANDFS_NFSAREAS;
-
- return (0);
-}
-
-static int
-nandfs_select_fsdata(struct nandfs_device *fsdev,
- struct nandfs_fsdata *fsdatat, struct nandfs_fsdata **fsdata, int nfsds)
-{
- int i;
-
- *fsdata = NULL;
- for (i = 0; i < nfsds; i++) {
- DPRINTF(VOLUMES, ("%s: i %d f_magic %x f_crc %x\n", __func__,
- i, fsdatat[i].f_magic, fsdatat[i].f_sum));
- if (!nandfs_check_fsdata_crc(&fsdatat[i]))
- continue;
- *fsdata = &fsdatat[i];
- break;
- }
-
- return (*fsdata != NULL ? 0 : EINVAL);
-}
-
-static int
-nandfs_select_sb(struct nandfs_device *fsdev,
- struct nandfs_super_block *supert, struct nandfs_super_block **super,
- int nsbs)
-{
- int i;
-
- *super = NULL;
- for (i = 0; i < nsbs; i++) {
- if (!nandfs_check_superblock_crc(&fsdev->nd_fsdata, &supert[i]))
- continue;
- DPRINTF(SYNC, ("%s: i %d s_last_cno %jx s_magic %x "
- "s_wtime %jd\n", __func__, i, supert[i].s_last_cno,
- supert[i].s_magic, supert[i].s_wtime));
- if (*super == NULL || supert[i].s_last_cno >
- (*super)->s_last_cno)
- *super = &supert[i];
- }
-
- return (*super != NULL ? 0 : EINVAL);
-}
-
-static int
-nandfs_read_structures_at(struct nandfs_device *fsdev,
- struct nandfs_fsarea *fstp, struct nandfs_fsdata *fsdata,
- struct nandfs_super_block *super)
-{
- struct nandfs_super_block *tsuper, *tsuperd;
- struct buf *bp;
- int error, read_size;
- int i;
- int offset;
-
- offset = fstp->offset;
-
- if (fsdev->nd_erasesize > MAXBSIZE)
- read_size = MAXBSIZE;
- else
- read_size = fsdev->nd_erasesize;
-
- error = bread(fsdev->nd_devvp, btodb(offset), read_size, NOCRED, &bp);
- if (error) {
- printf("couldn't read: %d\n", error);
- brelse(bp);
- fstp->flags |= NANDFS_FSSTOR_FAILED;
- return (error);
- }
-
- tsuper = super;
-
- memcpy(fsdata, bp->b_data, sizeof(struct nandfs_fsdata));
- memcpy(tsuper, (bp->b_data + sizeof(struct nandfs_fsdata)),
- read_size - sizeof(struct nandfs_fsdata));
- brelse(bp);
-
- tsuper += (read_size - sizeof(struct nandfs_fsdata)) /
- sizeof(struct nandfs_super_block);
-
- for (i = 1; i < fsdev->nd_erasesize / read_size; i++) {
- error = bread(fsdev->nd_devvp, btodb(offset + i * read_size),
- read_size, NOCRED, &bp);
- if (error) {
- printf("couldn't read: %d\n", error);
- brelse(bp);
- fstp->flags |= NANDFS_FSSTOR_FAILED;
- return (error);
- }
- memcpy(tsuper, bp->b_data, read_size);
- tsuper += read_size / sizeof(struct nandfs_super_block);
- brelse(bp);
- }
-
- tsuper -= 1;
- fstp->last_used = nandfs_sblocks_in_esize(fsdev) - 1;
- for (tsuperd = super - 1; (tsuper != tsuperd); tsuper -= 1) {
- if (nandfs_is_empty((u_char *)tsuper, sizeof(*tsuper)))
- fstp->last_used--;
- else
- break;
- }
-
- DPRINTF(VOLUMES, ("%s: last_used %d\n", __func__, fstp->last_used));
-
- return (0);
-}
-
-static int
-nandfs_read_structures(struct nandfs_device *fsdev)
-{
- struct nandfs_fsdata *fsdata, *fsdatat;
- struct nandfs_super_block *sblocks, *ssblock;
- u_int nsbs, nfsds, i;
- int error = 0;
- int nrsbs;
-
- nfsds = NANDFS_NFSAREAS;
- nsbs = nandfs_max_sblocks(fsdev);
-
- fsdatat = malloc(sizeof(struct nandfs_fsdata) * nfsds, M_NANDFSTEMP,
- M_WAITOK | M_ZERO);
- sblocks = malloc(sizeof(struct nandfs_super_block) * nsbs, M_NANDFSTEMP,
- M_WAITOK | M_ZERO);
-
- nrsbs = 0;
- for (i = 0; i < NANDFS_NFSAREAS; i++) {
- fsdev->nd_fsarea[i].offset = i * fsdev->nd_erasesize;
- error = nandfs_read_structures_at(fsdev, &fsdev->nd_fsarea[i],
- &fsdatat[i], sblocks + nrsbs);
- if (error)
- continue;
- nrsbs += (fsdev->nd_fsarea[i].last_used + 1);
- if (fsdev->nd_fsarea[fsdev->nd_last_fsarea].last_used >
- fsdev->nd_fsarea[i].last_used)
- fsdev->nd_last_fsarea = i;
- }
-
- if (nrsbs == 0) {
- printf("nandfs: no valid superblocks found\n");
- error = EINVAL;
- goto out;
- }
-
- error = nandfs_select_fsdata(fsdev, fsdatat, &fsdata, nfsds);
- if (error)
- goto out;
- memcpy(&fsdev->nd_fsdata, fsdata, sizeof(struct nandfs_fsdata));
-
- error = nandfs_select_sb(fsdev, sblocks, &ssblock, nsbs);
- if (error)
- goto out;
-
- memcpy(&fsdev->nd_super, ssblock, sizeof(struct nandfs_super_block));
-out:
- free(fsdatat, M_NANDFSTEMP);
- free(sblocks, M_NANDFSTEMP);
-
- if (error == 0)
- DPRINTF(VOLUMES, ("%s: selected sb with w_time %jd "
- "last_pseg %#jx\n", __func__, fsdev->nd_super.s_wtime,
- fsdev->nd_super.s_last_pseg));
-
- return (error);
-}
-
-static void
-nandfs_unmount_base(struct nandfs_device *nandfsdev)
-{
- int error;
-
- if (!nandfsdev)
- return;
-
- /* Remove all our information */
- error = vinvalbuf(nandfsdev->nd_devvp, V_SAVE, 0, 0);
- if (error) {
- /*
- * Flushing buffers failed when fs was umounting, can't do
- * much now, just printf error and continue with umount.
- */
- nandfs_error("%s(): error:%d when umounting FS\n",
- __func__, error);
- }
-
- /* Release the device's system nodes */
- nandfs_release_system_nodes(nandfsdev);
-}
-
-static void
-nandfs_get_ncleanseg(struct nandfs_device *nandfsdev)
-{
- struct nandfs_seg_stat nss;
-
- nandfs_get_seg_stat(nandfsdev, &nss);
- nandfsdev->nd_clean_segs = nss.nss_ncleansegs;
- DPRINTF(VOLUMES, ("nandfs_mount: clean segs: %jx\n",
- (uintmax_t)nandfsdev->nd_clean_segs));
-}
-
-
-static int
-nandfs_mount_base(struct nandfs_device *nandfsdev, struct mount *mp,
- struct nandfs_args *args)
-{
- uint32_t log_blocksize;
- int error;
-
- /* Flush out any old buffers remaining from a previous use. */
- if ((error = vinvalbuf(nandfsdev->nd_devvp, V_SAVE, 0, 0)))
- return (error);
-
- error = nandfs_read_structures(nandfsdev);
- if (error) {
- printf("nandfs: could not get valid filesystem structures\n");
- return (error);
- }
-
- if (nandfsdev->nd_fsdata.f_rev_level != NANDFS_CURRENT_REV) {
- printf("nandfs: unsupported file system revision: %d "
- "(supported is %d).\n", nandfsdev->nd_fsdata.f_rev_level,
- NANDFS_CURRENT_REV);
- return (EINVAL);
- }
-
- if (nandfsdev->nd_fsdata.f_erasesize != nandfsdev->nd_erasesize) {
- printf("nandfs: erasesize mismatch (device %#x, fs %#x)\n",
- nandfsdev->nd_erasesize, nandfsdev->nd_fsdata.f_erasesize);
- return (EINVAL);
- }
-
- /* Get our blocksize */
- log_blocksize = nandfsdev->nd_fsdata.f_log_block_size;
- nandfsdev->nd_blocksize = (uint64_t) 1 << (log_blocksize + 10);
- DPRINTF(VOLUMES, ("%s: blocksize:%x\n", __func__,
- nandfsdev->nd_blocksize));
-
- DPRINTF(VOLUMES, ("%s: accepted super block with cp %#jx\n", __func__,
- (uintmax_t)nandfsdev->nd_super.s_last_cno));
-
- /* Calculate dat structure parameters */
- nandfs_calc_mdt_consts(nandfsdev, &nandfsdev->nd_dat_mdt,
- nandfsdev->nd_fsdata.f_dat_entry_size);
- nandfs_calc_mdt_consts(nandfsdev, &nandfsdev->nd_ifile_mdt,
- nandfsdev->nd_fsdata.f_inode_size);
-
- /* Search for the super root and roll forward when needed */
- if (nandfs_search_super_root(nandfsdev)) {
- printf("Cannot find valid SuperRoot\n");
- return (EINVAL);
- }
-
- nandfsdev->nd_mount_state = nandfsdev->nd_super.s_state;
- if (nandfsdev->nd_mount_state != NANDFS_VALID_FS) {
- printf("FS is seriously damaged, needs repairing\n");
- printf("aborting mount\n");
- return (EINVAL);
- }
-
- /*
- * FS should be ok now. The superblock and the last segsum could be
- * updated from the repair so extract running values again.
- */
- nandfsdev->nd_last_pseg = nandfsdev->nd_super.s_last_pseg;
- nandfsdev->nd_seg_sequence = nandfsdev->nd_super.s_last_seq;
- nandfsdev->nd_seg_num = nandfs_get_segnum_of_block(nandfsdev,
- nandfsdev->nd_last_pseg);
- nandfsdev->nd_next_seg_num = nandfs_get_segnum_of_block(nandfsdev,
- nandfsdev->nd_last_segsum.ss_next);
- nandfsdev->nd_ts.tv_sec = nandfsdev->nd_last_segsum.ss_create;
- nandfsdev->nd_last_cno = nandfsdev->nd_super.s_last_cno;
- nandfsdev->nd_fakevblk = 1;
- /*
- * FIXME: bogus calculation. Should use actual number of usable segments
- * instead of total amount.
- */
- nandfsdev->nd_segs_reserved =
- nandfsdev->nd_fsdata.f_nsegments *
- nandfsdev->nd_fsdata.f_r_segments_percentage / 100;
- nandfsdev->nd_last_ino = NANDFS_USER_INO;
- DPRINTF(VOLUMES, ("%s: last_pseg %#jx last_cno %#jx last_seq %#jx\n"
- "fsdev: last_seg: seq %#jx num %#jx, next_seg_num %#jx "
- "segs_reserved %#jx\n",
- __func__, (uintmax_t)nandfsdev->nd_last_pseg,
- (uintmax_t)nandfsdev->nd_last_cno,
- (uintmax_t)nandfsdev->nd_seg_sequence,
- (uintmax_t)nandfsdev->nd_seg_sequence,
- (uintmax_t)nandfsdev->nd_seg_num,
- (uintmax_t)nandfsdev->nd_next_seg_num,
- (uintmax_t)nandfsdev->nd_segs_reserved));
-
- DPRINTF(VOLUMES, ("nandfs_mount: accepted super root\n"));
-
- /* Create system vnodes for DAT, CP and SEGSUM */
- error = nandfs_create_system_nodes(nandfsdev);
- if (error)
- nandfs_unmount_base(nandfsdev);
-
- nandfs_get_ncleanseg(nandfsdev);
-
- return (error);
-}
-
-static void
-nandfs_unmount_device(struct nandfs_device *nandfsdev)
-{
-
- /* Is there anything? */
- if (nandfsdev == NULL)
- return;
-
- /* Remove the device only if we're the last reference */
- nandfsdev->nd_refcnt--;
- if (nandfsdev->nd_refcnt >= 1)
- return;
-
- MPASS(nandfsdev->nd_syncer == NULL);
- MPASS(nandfsdev->nd_cleaner == NULL);
- MPASS(nandfsdev->nd_free_base == NULL);
-
- /* Unmount our base */
- nandfs_unmount_base(nandfsdev);
-
- /* Remove from our device list */
- SLIST_REMOVE(&nandfs_devices, nandfsdev, nandfs_device, nd_next_device);
-
- DROP_GIANT();
- g_topology_lock();
- g_vfs_close(nandfsdev->nd_gconsumer);
- g_topology_unlock();
- PICKUP_GIANT();
-
- DPRINTF(VOLUMES, ("closing device\n"));
-
- /* Clear our mount reference and release device node */
- vrele(nandfsdev->nd_devvp);
-
- dev_rel(nandfsdev->nd_devvp->v_rdev);
-
- /* Free our device info */
- cv_destroy(&nandfsdev->nd_sync_cv);
- mtx_destroy(&nandfsdev->nd_sync_mtx);
- cv_destroy(&nandfsdev->nd_clean_cv);
- mtx_destroy(&nandfsdev->nd_clean_mtx);
- mtx_destroy(&nandfsdev->nd_mutex);
- lockdestroy(&nandfsdev->nd_seg_const);
- free(nandfsdev, M_NANDFSMNT);
-}
-
-static int
-nandfs_check_mounts(struct nandfs_device *nandfsdev, struct mount *mp,
- struct nandfs_args *args)
-{
- struct nandfsmount *nmp;
- uint64_t last_cno;
-
- /* no double-mounting of the same checkpoint */
- STAILQ_FOREACH(nmp, &nandfsdev->nd_mounts, nm_next_mount) {
- if (nmp->nm_mount_args.cpno == args->cpno)
- return (EBUSY);
- }
-
- /* Allow readonly mounts without questioning here */
- if (mp->mnt_flag & MNT_RDONLY)
- return (0);
-
- /* Read/write mount */
- STAILQ_FOREACH(nmp, &nandfsdev->nd_mounts, nm_next_mount) {
- /* Only one RW mount on this device! */
- if ((nmp->nm_vfs_mountp->mnt_flag & MNT_RDONLY)==0)
- return (EROFS);
- /* RDONLY on last mountpoint is device busy */
- last_cno = nmp->nm_nandfsdev->nd_super.s_last_cno;
- if (nmp->nm_mount_args.cpno == last_cno)
- return (EBUSY);
- }
-
- /* OK for now */
- return (0);
-}
-
-static int
-nandfs_mount_device(struct vnode *devvp, struct mount *mp,
- struct nandfs_args *args, struct nandfs_device **nandfsdev_p)
-{
- struct nandfs_device *nandfsdev;
- struct g_provider *pp;
- struct g_consumer *cp;
- struct cdev *dev;
- uint32_t erasesize;
- int error, size;
- int ronly;
-
- DPRINTF(VOLUMES, ("Mounting NANDFS device\n"));
-
- ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
-
- /* Look up device in our nandfs_mountpoints */
- *nandfsdev_p = NULL;
- SLIST_FOREACH(nandfsdev, &nandfs_devices, nd_next_device)
- if (nandfsdev->nd_devvp == devvp)
- break;
-
- if (nandfsdev) {
- DPRINTF(VOLUMES, ("device already mounted\n"));
- error = nandfs_check_mounts(nandfsdev, mp, args);
- if (error)
- return error;
- nandfsdev->nd_refcnt++;
- *nandfsdev_p = nandfsdev;
-
- if (!ronly) {
- DROP_GIANT();
- g_topology_lock();
- error = g_access(nandfsdev->nd_gconsumer, 0, 1, 0);
- g_topology_unlock();
- PICKUP_GIANT();
- }
- return (error);
- }
-
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
- dev = devvp->v_rdev;
- dev_ref(dev);
- DROP_GIANT();
- g_topology_lock();
- error = g_vfs_open(devvp, &cp, "nandfs", ronly ? 0 : 1);
- pp = g_dev_getprovider(dev);
- g_topology_unlock();
- PICKUP_GIANT();
- VOP_UNLOCK(devvp, 0);
- if (error) {
- dev_rel(dev);
- return (error);
- }
-
- nandfsdev = malloc(sizeof(struct nandfs_device), M_NANDFSMNT, M_WAITOK | M_ZERO);
-
- /* Initialise */
- nandfsdev->nd_refcnt = 1;
- nandfsdev->nd_devvp = devvp;
- nandfsdev->nd_syncing = 0;
- nandfsdev->nd_cleaning = 0;
- nandfsdev->nd_gconsumer = cp;
- cv_init(&nandfsdev->nd_sync_cv, "nandfssync");
- mtx_init(&nandfsdev->nd_sync_mtx, "nffssyncmtx", NULL, MTX_DEF);
- cv_init(&nandfsdev->nd_clean_cv, "nandfsclean");
- mtx_init(&nandfsdev->nd_clean_mtx, "nffscleanmtx", NULL, MTX_DEF);
- mtx_init(&nandfsdev->nd_mutex, "nandfsdev lock", NULL, MTX_DEF);
- lockinit(&nandfsdev->nd_seg_const, PVFS, "nffssegcon", VLKTIMEOUT,
- LK_CANRECURSE);
- STAILQ_INIT(&nandfsdev->nd_mounts);
-
- nandfsdev->nd_devsize = pp->mediasize;
- nandfsdev->nd_devblocksize = pp->sectorsize;
-
- size = sizeof(erasesize);
- error = g_io_getattr("NAND::blocksize", nandfsdev->nd_gconsumer, &size,
- &erasesize);
- if (error) {
- DPRINTF(VOLUMES, ("couldn't get erasesize: %d\n", error));
-
- if (error == ENOIOCTL || error == EOPNOTSUPP) {
- /*
- * We conclude that this is not NAND storage
- */
- erasesize = NANDFS_DEF_ERASESIZE;
- } else {
- DROP_GIANT();
- g_topology_lock();
- g_vfs_close(nandfsdev->nd_gconsumer);
- g_topology_unlock();
- PICKUP_GIANT();
- dev_rel(dev);
- free(nandfsdev, M_NANDFSMNT);
- return (error);
- }
- }
- nandfsdev->nd_erasesize = erasesize;
-
- DPRINTF(VOLUMES, ("%s: erasesize %x\n", __func__,
- nandfsdev->nd_erasesize));
-
- /* Register nandfs_device in list */
- SLIST_INSERT_HEAD(&nandfs_devices, nandfsdev, nd_next_device);
-
- error = nandfs_mount_base(nandfsdev, mp, args);
- if (error) {
- /* Remove all our information */
- nandfs_unmount_device(nandfsdev);
- return (EINVAL);
- }
-
- nandfsdev->nd_maxfilesize = nandfs_get_maxfilesize(nandfsdev);
-
- *nandfsdev_p = nandfsdev;
- DPRINTF(VOLUMES, ("NANDFS device mounted ok\n"));
-
- return (0);
-}
-
-static int
-nandfs_mount_checkpoint(struct nandfsmount *nmp)
-{
- struct nandfs_cpfile_header *cphdr;
- struct nandfs_checkpoint *cp;
- struct nandfs_inode ifile_inode;
- struct nandfs_node *cp_node;
- struct buf *bp;
- uint64_t ncp, nsn, cpno, fcpno, blocknr, last_cno;
- uint32_t off, dlen;
- int cp_per_block, error;
-
- cpno = nmp->nm_mount_args.cpno;
- if (cpno == 0)
- cpno = nmp->nm_nandfsdev->nd_super.s_last_cno;
-
- DPRINTF(VOLUMES, ("%s: trying to mount checkpoint number %"PRIu64"\n",
- __func__, cpno));
-
- cp_node = nmp->nm_nandfsdev->nd_cp_node;
-
- VOP_LOCK(NTOV(cp_node), LK_SHARED);
- /* Get cpfile header from 1st block of cp file */
- error = nandfs_bread(cp_node, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (error);
- }
-
- cphdr = (struct nandfs_cpfile_header *) bp->b_data;
- ncp = cphdr->ch_ncheckpoints;
- nsn = cphdr->ch_nsnapshots;
-
- brelse(bp);
-
- DPRINTF(VOLUMES, ("mount_nandfs: checkpoint header read in\n"));
- DPRINTF(VOLUMES, ("\tNumber of checkpoints %"PRIu64"\n", ncp));
- DPRINTF(VOLUMES, ("\tNumber of snapshots %"PRIu64"\n", nsn));
-
- /* Read in our specified checkpoint */
- dlen = nmp->nm_nandfsdev->nd_fsdata.f_checkpoint_size;
- cp_per_block = nmp->nm_nandfsdev->nd_blocksize / dlen;
-
- fcpno = cpno + NANDFS_CPFILE_FIRST_CHECKPOINT_OFFSET - 1;
- blocknr = fcpno / cp_per_block;
- off = (fcpno % cp_per_block) * dlen;
- error = nandfs_bread(cp_node, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- printf("mount_nandfs: couldn't read cp block %"PRIu64"\n",
- fcpno);
- return (EINVAL);
- }
-
- /* Needs to be a valid checkpoint */
- cp = (struct nandfs_checkpoint *) ((uint8_t *) bp->b_data + off);
- if (cp->cp_flags & NANDFS_CHECKPOINT_INVALID) {
- printf("mount_nandfs: checkpoint marked invalid\n");
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (EINVAL);
- }
-
- /* Is this really the checkpoint we want? */
- if (cp->cp_cno != cpno) {
- printf("mount_nandfs: checkpoint file corrupt? "
- "expected cpno %"PRIu64", found cpno %"PRIu64"\n",
- cpno, cp->cp_cno);
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (EINVAL);
- }
-
- /* Check if it's a snapshot ! */
- last_cno = nmp->nm_nandfsdev->nd_super.s_last_cno;
- if (cpno != last_cno) {
- /* Only allow snapshots if not mounting on the last cp */
- if ((cp->cp_flags & NANDFS_CHECKPOINT_SNAPSHOT) == 0) {
- printf( "mount_nandfs: checkpoint %"PRIu64" is not a "
- "snapshot\n", cpno);
- brelse(bp);
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (EINVAL);
- }
- }
-
- ifile_inode = cp->cp_ifile_inode;
- brelse(bp);
-
- /* Get ifile inode */
- error = nandfs_get_node_raw(nmp->nm_nandfsdev, NULL, NANDFS_IFILE_INO,
- &ifile_inode, &nmp->nm_ifile_node);
- if (error) {
- printf("mount_nandfs: can't read ifile node\n");
- VOP_UNLOCK(NTOV(cp_node), 0);
- return (EINVAL);
- }
-
- NANDFS_SET_SYSTEMFILE(NTOV(nmp->nm_ifile_node));
- VOP_UNLOCK(NTOV(cp_node), 0);
- /* Get root node? */
-
- return (0);
-}
-
-static void
-free_nandfs_mountinfo(struct mount *mp)
-{
- struct nandfsmount *nmp = VFSTONANDFS(mp);
-
- if (nmp == NULL)
- return;
-
- free(nmp, M_NANDFSMNT);
-}
-
-void
-nandfs_wakeup_wait_sync(struct nandfs_device *nffsdev, int reason)
-{
- char *reasons[] = {
- "umount",
- "vfssync",
- "bdflush",
- "fforce",
- "fsync",
- "ro_upd"
- };
-
- DPRINTF(SYNC, ("%s: %s\n", __func__, reasons[reason]));
- mtx_lock(&nffsdev->nd_sync_mtx);
- if (nffsdev->nd_syncing)
- cv_wait(&nffsdev->nd_sync_cv, &nffsdev->nd_sync_mtx);
- if (reason == SYNCER_UMOUNT)
- nffsdev->nd_syncer_exit = 1;
- nffsdev->nd_syncing = 1;
- wakeup(&nffsdev->nd_syncing);
- cv_wait(&nffsdev->nd_sync_cv, &nffsdev->nd_sync_mtx);
-
- mtx_unlock(&nffsdev->nd_sync_mtx);
-}
-
-static void
-nandfs_gc_finished(struct nandfs_device *nffsdev, int exit)
-{
- int error;
-
- mtx_lock(&nffsdev->nd_sync_mtx);
- nffsdev->nd_syncing = 0;
- DPRINTF(SYNC, ("%s: cleaner finish\n", __func__));
- cv_broadcast(&nffsdev->nd_sync_cv);
- mtx_unlock(&nffsdev->nd_sync_mtx);
- if (!exit) {
- error = tsleep(&nffsdev->nd_syncing, PRIBIO, "-",
- hz * nandfs_sync_interval);
- DPRINTF(SYNC, ("%s: cleaner waked up: %d\n",
- __func__, error));
- }
-}
-
-static void
-nandfs_syncer(struct nandfsmount *nmp)
-{
- struct nandfs_device *nffsdev;
- struct mount *mp;
- int flags, error;
-
- mp = nmp->nm_vfs_mountp;
- nffsdev = nmp->nm_nandfsdev;
- tsleep(&nffsdev->nd_syncing, PRIBIO, "-", hz * nandfs_sync_interval);
-
- while (!nffsdev->nd_syncer_exit) {
- DPRINTF(SYNC, ("%s: syncer run\n", __func__));
- nffsdev->nd_syncing = 1;
-
- flags = (nmp->nm_flags & (NANDFS_FORCE_SYNCER | NANDFS_UMOUNT));
-
- error = nandfs_segment_constructor(nmp, flags);
- if (error)
- nandfs_error("%s: error:%d when creating segments\n",
- __func__, error);
-
- nmp->nm_flags &= ~flags;
-
- nandfs_gc_finished(nffsdev, 0);
- }
-
- MPASS(nffsdev->nd_cleaner == NULL);
- error = nandfs_segment_constructor(nmp,
- NANDFS_FORCE_SYNCER | NANDFS_UMOUNT);
- if (error)
- nandfs_error("%s: error:%d when creating segments\n",
- __func__, error);
- nandfs_gc_finished(nffsdev, 1);
- nffsdev->nd_syncer = NULL;
- MPASS(nffsdev->nd_free_base == NULL);
-
- DPRINTF(SYNC, ("%s: exiting\n", __func__));
- kthread_exit();
-}
-
-static int
-start_syncer(struct nandfsmount *nmp)
-{
- int error;
-
- MPASS(nmp->nm_nandfsdev->nd_syncer == NULL);
-
- DPRINTF(SYNC, ("%s: start syncer\n", __func__));
-
- nmp->nm_nandfsdev->nd_syncer_exit = 0;
-
- error = kthread_add((void(*)(void *))nandfs_syncer, nmp, NULL,
- &nmp->nm_nandfsdev->nd_syncer, 0, 0, "nandfs_syncer");
-
- if (error)
- printf("nandfs: could not start syncer: %d\n", error);
-
- return (error);
-}
-
-static int
-stop_syncer(struct nandfsmount *nmp)
-{
-
- MPASS(nmp->nm_nandfsdev->nd_syncer != NULL);
-
- nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_UMOUNT);
-
- DPRINTF(SYNC, ("%s: stop syncer\n", __func__));
- return (0);
-}
-
-/*
- * Mount null layer
- */
-static int
-nandfs_mount(struct mount *mp)
-{
- struct nandfsmount *nmp;
- struct vnode *devvp;
- struct nameidata nd;
- struct vfsoptlist *opts;
- struct thread *td;
- char *from;
- int error = 0, flags;
-
- DPRINTF(VOLUMES, ("%s: mp = %p\n", __func__, (void *)mp));
-
- td = curthread;
- opts = mp->mnt_optnew;
-
- if (vfs_filteropt(opts, nandfs_opts))
- return (EINVAL);
-
- /*
- * Update is a no-op
- */
- if (mp->mnt_flag & MNT_UPDATE) {
- nmp = VFSTONANDFS(mp);
- if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0)) {
- return (error);
- }
- if (!(nmp->nm_ronly) && vfs_flagopt(opts, "ro", NULL, 0)) {
- vn_start_write(NULL, &mp, V_WAIT);
- error = VFS_SYNC(mp, MNT_WAIT);
- if (error)
- return (error);
- vn_finished_write(mp);
-
- flags = WRITECLOSE;
- if (mp->mnt_flag & MNT_FORCE)
- flags |= FORCECLOSE;
-
- nandfs_wakeup_wait_sync(nmp->nm_nandfsdev,
- SYNCER_ROUPD);
- error = vflush(mp, 0, flags, td);
- if (error)
- return (error);
-
- nandfs_stop_cleaner(nmp->nm_nandfsdev);
- stop_syncer(nmp);
- DROP_GIANT();
- g_topology_lock();
- g_access(nmp->nm_nandfsdev->nd_gconsumer, 0, -1, 0);
- g_topology_unlock();
- PICKUP_GIANT();
- MNT_ILOCK(mp);
- mp->mnt_flag |= MNT_RDONLY;
- MNT_IUNLOCK(mp);
- nmp->nm_ronly = 1;
-
- } else if ((nmp->nm_ronly) &&
- !vfs_flagopt(opts, "ro", NULL, 0)) {
- /*
- * Don't allow read-write snapshots.
- */
- if (nmp->nm_mount_args.cpno != 0)
- return (EROFS);
- /*
- * If upgrade to read-write by non-root, then verify
- * that user has necessary permissions on the device.
- */
- devvp = nmp->nm_nandfsdev->nd_devvp;
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
- error = VOP_ACCESS(devvp, VREAD | VWRITE,
- td->td_ucred, td);
- if (error) {
- error = priv_check(td, PRIV_VFS_MOUNT_PERM);
- if (error) {
- VOP_UNLOCK(devvp, 0);
- return (error);
- }
- }
-
- VOP_UNLOCK(devvp, 0);
- DROP_GIANT();
- g_topology_lock();
- error = g_access(nmp->nm_nandfsdev->nd_gconsumer, 0, 1,
- 0);
- g_topology_unlock();
- PICKUP_GIANT();
- if (error)
- return (error);
-
- MNT_ILOCK(mp);
- mp->mnt_flag &= ~MNT_RDONLY;
- MNT_IUNLOCK(mp);
- error = start_syncer(nmp);
- if (error == 0)
- error = nandfs_start_cleaner(nmp->nm_nandfsdev);
- if (error) {
- DROP_GIANT();
- g_topology_lock();
- g_access(nmp->nm_nandfsdev->nd_gconsumer, 0, -1,
- 0);
- g_topology_unlock();
- PICKUP_GIANT();
- return (error);
- }
-
- nmp->nm_ronly = 0;
- }
- return (0);
- }
-
- from = vfs_getopts(opts, "from", &error);
- if (error)
- return (error);
-
- /*
- * Find device node
- */
- NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF, UIO_SYSSPACE, from, curthread);
- error = namei(&nd);
- if (error)
- return (error);
- NDFREE(&nd, NDF_ONLY_PNBUF);
-
- devvp = nd.ni_vp;
-
- if (!vn_isdisk(devvp, &error)) {
- vput(devvp);
- return (error);
- }
-
- /* Check the access rights on the mount device */
- error = VOP_ACCESS(devvp, VREAD, curthread->td_ucred, curthread);
- if (error)
- error = priv_check(curthread, PRIV_VFS_MOUNT_PERM);
- if (error) {
- vput(devvp);
- return (error);
- }
-
- vfs_getnewfsid(mp);
-
- error = nandfs_mountfs(devvp, mp);
- if (error)
- return (error);
- vfs_mountedfrom(mp, from);
-
- return (0);
-}
-
-static int
-nandfs_mountfs(struct vnode *devvp, struct mount *mp)
-{
- struct nandfsmount *nmp = NULL;
- struct nandfs_args *args = NULL;
- struct nandfs_device *nandfsdev;
- char *from;
- int error, ronly;
- char *cpno;
-
- ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
-
- if (devvp->v_rdev->si_iosize_max != 0)
- mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
- VOP_UNLOCK(devvp, 0);
-
- if (mp->mnt_iosize_max > MAXPHYS)
- mp->mnt_iosize_max = MAXPHYS;
-
- from = vfs_getopts(mp->mnt_optnew, "from", &error);
- if (error)
- goto error;
-
- error = vfs_getopt(mp->mnt_optnew, "snap", (void **)&cpno, NULL);
- if (error == ENOENT)
- cpno = NULL;
- else if (error)
- goto error;
-
- args = (struct nandfs_args *)malloc(sizeof(struct nandfs_args),
- M_NANDFSMNT, M_WAITOK | M_ZERO);
-
- if (cpno != NULL)
- args->cpno = strtoul(cpno, (char **)NULL, 10);
- else
- args->cpno = 0;
- args->fspec = from;
-
- if (args->cpno != 0 && !ronly) {
- error = EROFS;
- goto error;
- }
-
- printf("WARNING: NANDFS is considered to be a highly experimental "
- "feature in FreeBSD.\n");
-
- error = nandfs_mount_device(devvp, mp, args, &nandfsdev);
- if (error)
- goto error;
-
- nmp = (struct nandfsmount *) malloc(sizeof(struct nandfsmount),
- M_NANDFSMNT, M_WAITOK | M_ZERO);
-
- mp->mnt_data = nmp;
- nmp->nm_vfs_mountp = mp;
- nmp->nm_ronly = ronly;
- MNT_ILOCK(mp);
- mp->mnt_flag |= MNT_LOCAL;
- mp->mnt_kern_flag |= MNTK_USES_BCACHE;
- MNT_IUNLOCK(mp);
- nmp->nm_nandfsdev = nandfsdev;
- /* Add our mountpoint */
- STAILQ_INSERT_TAIL(&nandfsdev->nd_mounts, nmp, nm_next_mount);
-
- if (args->cpno > nandfsdev->nd_last_cno) {
- printf("WARNING: supplied checkpoint number (%jd) is greater "
- "than last known checkpoint on filesystem (%jd). Mounting"
- " checkpoint %jd\n", (uintmax_t)args->cpno,
- (uintmax_t)nandfsdev->nd_last_cno,
- (uintmax_t)nandfsdev->nd_last_cno);
- args->cpno = nandfsdev->nd_last_cno;
- }
-
- /* Setting up other parameters */
- nmp->nm_mount_args = *args;
- free(args, M_NANDFSMNT);
- error = nandfs_mount_checkpoint(nmp);
- if (error) {
- nandfs_unmount(mp, MNT_FORCE);
- goto unmounted;
- }
-
- if (!ronly) {
- error = start_syncer(nmp);
- if (error == 0)
- error = nandfs_start_cleaner(nmp->nm_nandfsdev);
- if (error)
- nandfs_unmount(mp, MNT_FORCE);
- }
-
- return (0);
-
-error:
- if (args != NULL)
- free(args, M_NANDFSMNT);
-
- if (nmp != NULL) {
- free(nmp, M_NANDFSMNT);
- mp->mnt_data = NULL;
- }
-unmounted:
- return (error);
-}
-
-static int
-nandfs_unmount(struct mount *mp, int mntflags)
-{
- struct nandfs_device *nandfsdev;
- struct nandfsmount *nmp;
- int error;
- int flags = 0;
-
- DPRINTF(VOLUMES, ("%s: mp = %p\n", __func__, (void *)mp));
-
- if (mntflags & MNT_FORCE)
- flags |= FORCECLOSE;
-
- nmp = mp->mnt_data;
- nandfsdev = nmp->nm_nandfsdev;
-
- error = vflush(mp, 0, flags | SKIPSYSTEM, curthread);
- if (error)
- return (error);
-
- if (!(nmp->nm_ronly)) {
- nandfs_stop_cleaner(nandfsdev);
- stop_syncer(nmp);
- }
-
- if (nmp->nm_ifile_node)
- NANDFS_UNSET_SYSTEMFILE(NTOV(nmp->nm_ifile_node));
-
- /* Remove our mount point */
- STAILQ_REMOVE(&nandfsdev->nd_mounts, nmp, nandfsmount, nm_next_mount);
-
- /* Unmount the device itself when we're the last one */
- nandfs_unmount_device(nandfsdev);
-
- free_nandfs_mountinfo(mp);
-
- /*
- * Finally, throw away the null_mount structure
- */
- mp->mnt_data = 0;
- MNT_ILOCK(mp);
- mp->mnt_flag &= ~MNT_LOCAL;
- MNT_IUNLOCK(mp);
-
- return (0);
-}
-
-static int
-nandfs_statfs(struct mount *mp, struct statfs *sbp)
-{
- struct nandfsmount *nmp;
- struct nandfs_device *nandfsdev;
- struct nandfs_fsdata *fsdata;
- struct nandfs_super_block *sb;
- struct nandfs_block_group_desc *groups;
- struct nandfs_node *ifile;
- struct nandfs_mdt *mdt;
- struct buf *bp;
- int i, error;
- uint32_t entries_per_group;
- uint64_t files = 0;
-
- nmp = mp->mnt_data;
- nandfsdev = nmp->nm_nandfsdev;
- fsdata = &nandfsdev->nd_fsdata;
- sb = &nandfsdev->nd_super;
- ifile = nmp->nm_ifile_node;
- mdt = &nandfsdev->nd_ifile_mdt;
- entries_per_group = mdt->entries_per_group;
-
- VOP_LOCK(NTOV(ifile), LK_SHARED);
- error = nandfs_bread(ifile, 0, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- VOP_UNLOCK(NTOV(ifile), 0);
- return (error);
- }
-
- groups = (struct nandfs_block_group_desc *)bp->b_data;
-
- for (i = 0; i < mdt->groups_per_desc_block; i++)
- files += (entries_per_group - groups[i].bg_nfrees);
-
- brelse(bp);
- VOP_UNLOCK(NTOV(ifile), 0);
-
- sbp->f_bsize = nandfsdev->nd_blocksize;
- sbp->f_iosize = sbp->f_bsize;
- sbp->f_blocks = fsdata->f_blocks_per_segment * fsdata->f_nsegments;
- sbp->f_bfree = sb->s_free_blocks_count;
- sbp->f_bavail = sbp->f_bfree;
- sbp->f_files = files;
- sbp->f_ffree = 0;
- return (0);
-}
-
-static int
-nandfs_root(struct mount *mp, int flags, struct vnode **vpp)
-{
- struct nandfsmount *nmp = VFSTONANDFS(mp);
- struct nandfs_node *node;
- int error;
-
- error = nandfs_get_node(nmp, NANDFS_ROOT_INO, &node);
- if (error)
- return (error);
-
- KASSERT(NTOV(node)->v_vflag & VV_ROOT,
- ("root_vp->v_vflag & VV_ROOT"));
-
- *vpp = NTOV(node);
-
- return (error);
-}
-
-static int
-nandfs_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
-{
- struct nandfsmount *nmp = VFSTONANDFS(mp);
- struct nandfs_node *node;
- int error;
-
- error = nandfs_get_node(nmp, ino, &node);
- if (node)
- *vpp = NTOV(node);
-
- return (error);
-}
-
-static int
-nandfs_sync(struct mount *mp, int waitfor)
-{
- struct nandfsmount *nmp = VFSTONANDFS(mp);
-
- DPRINTF(SYNC, ("%s: mp %p waitfor %d\n", __func__, mp, waitfor));
-
- /*
- * XXX: A hack to be removed soon
- */
- if (waitfor == MNT_LAZY)
- return (0);
- if (waitfor == MNT_SUSPEND)
- return (0);
- nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_VFS_SYNC);
- return (0);
-}
-
-static struct vfsops nandfs_vfsops = {
- .vfs_init = nandfs_init,
- .vfs_mount = nandfs_mount,
- .vfs_root = nandfs_root,
- .vfs_statfs = nandfs_statfs,
- .vfs_uninit = nandfs_uninit,
- .vfs_unmount = nandfs_unmount,
- .vfs_vget = nandfs_vget,
- .vfs_sync = nandfs_sync,
-};
-
-VFS_SET(nandfs_vfsops, nandfs, VFCF_LOOPBACK);
diff --git a/sys/fs/nandfs/nandfs_vnops.c b/sys/fs/nandfs/nandfs_vnops.c
deleted file mode 100644
index 5027d6adbbc1..000000000000
--- a/sys/fs/nandfs/nandfs_vnops.c
+++ /dev/null
@@ -1,2454 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf
- * Copyright (c) 2008, 2009 Reinoud Zandijk
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * From: NetBSD: nilfs_vnops.c,v 1.2 2009/08/26 03:40:48 elad
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/lockf.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/unistd.h>
-#include <sys/vnode.h>
-#include <sys/buf.h>
-#include <sys/bio.h>
-#include <sys/fcntl.h>
-#include <sys/dirent.h>
-#include <sys/rwlock.h>
-#include <sys/stat.h>
-#include <sys/priv.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-#include <vm/vnode_pager.h>
-
-#include <machine/_inttypes.h>
-
-#include <fs/nandfs/nandfs_mount.h>
-#include <fs/nandfs/nandfs.h>
-#include <fs/nandfs/nandfs_subr.h>
-
-extern uma_zone_t nandfs_node_zone;
-static void nandfs_read_filebuf(struct nandfs_node *, struct buf *);
-static void nandfs_itimes_locked(struct vnode *);
-static int nandfs_truncate(struct vnode *, uint64_t);
-
-static vop_pathconf_t nandfs_pathconf;
-
-#define UPDATE_CLOSE 0
-#define UPDATE_WAIT 0
-
-static int
-nandfs_inactive(struct vop_inactive_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- int error = 0;
-
- DPRINTF(VNCALL, ("%s: vp:%p node:%p\n", __func__, vp, node));
-
- if (node == NULL) {
- DPRINTF(NODE, ("%s: inactive NULL node\n", __func__));
- return (0);
- }
-
- if (node->nn_inode.i_mode != 0 && !(node->nn_inode.i_links_count)) {
- nandfs_truncate(vp, 0);
- error = nandfs_node_destroy(node);
- if (error)
- nandfs_error("%s: destroy node: %p\n", __func__, node);
- node->nn_flags = 0;
- vrecycle(vp);
- }
-
- return (error);
-}
-
-static int
-nandfs_reclaim(struct vop_reclaim_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *nandfs_node = VTON(vp);
- struct nandfs_device *fsdev = nandfs_node->nn_nandfsdev;
- uint64_t ino = nandfs_node->nn_ino;
-
- DPRINTF(VNCALL, ("%s: vp:%p node:%p\n", __func__, vp, nandfs_node));
-
- /* Invalidate all entries to a particular vnode. */
- cache_purge(vp);
-
- /* Destroy the vm object and flush associated pages. */
- vnode_destroy_vobject(vp);
-
- /* Remove from vfs hash if not system vnode */
- if (!NANDFS_SYS_NODE(nandfs_node->nn_ino))
- vfs_hash_remove(vp);
-
- /* Dispose all node knowledge */
- nandfs_dispose_node(&nandfs_node);
-
- if (!NANDFS_SYS_NODE(ino))
- NANDFS_WRITEUNLOCK(fsdev);
-
- return (0);
-}
-
-static int
-nandfs_read(struct vop_read_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_device *nandfsdev = node->nn_nandfsdev;
- struct uio *uio = ap->a_uio;
- struct buf *bp;
- uint64_t size;
- uint32_t blocksize;
- off_t bytesinfile;
- ssize_t toread, off;
- daddr_t lbn;
- ssize_t resid;
- int error = 0;
-
- if (uio->uio_resid == 0)
- return (0);
-
- size = node->nn_inode.i_size;
- if (uio->uio_offset >= size)
- return (0);
-
- blocksize = nandfsdev->nd_blocksize;
- bytesinfile = size - uio->uio_offset;
-
- resid = omin(uio->uio_resid, bytesinfile);
-
- while (resid) {
- lbn = uio->uio_offset / blocksize;
- off = uio->uio_offset & (blocksize - 1);
-
- toread = omin(resid, blocksize - off);
-
- DPRINTF(READ, ("nandfs_read bn: 0x%jx toread: 0x%zx (0x%x)\n",
- (uintmax_t)lbn, toread, blocksize));
-
- error = nandfs_bread(node, lbn, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- break;
- }
-
- error = uiomove(bp->b_data + off, toread, uio);
- if (error) {
- brelse(bp);
- break;
- }
-
- brelse(bp);
- resid -= toread;
- }
-
- return (error);
-}
-
-static int
-nandfs_write(struct vop_write_args *ap)
-{
- struct nandfs_device *fsdev;
- struct nandfs_node *node;
- struct vnode *vp;
- struct uio *uio;
- struct buf *bp;
- uint64_t file_size, vblk;
- uint32_t blocksize;
- ssize_t towrite, off;
- daddr_t lbn;
- ssize_t resid;
- int error, ioflag, modified;
-
- vp = ap->a_vp;
- uio = ap->a_uio;
- ioflag = ap->a_ioflag;
- node = VTON(vp);
- fsdev = node->nn_nandfsdev;
-
- if (nandfs_fs_full(fsdev))
- return (ENOSPC);
-
- DPRINTF(WRITE, ("nandfs_write called %#zx at %#jx\n",
- uio->uio_resid, (uintmax_t)uio->uio_offset));
-
- if (uio->uio_offset < 0)
- return (EINVAL);
- if (uio->uio_resid == 0)
- return (0);
-
- blocksize = fsdev->nd_blocksize;
- file_size = node->nn_inode.i_size;
-
- switch (vp->v_type) {
- case VREG:
- if (ioflag & IO_APPEND)
- uio->uio_offset = file_size;
- break;
- case VDIR:
- return (EISDIR);
- case VLNK:
- break;
- default:
- panic("%s: bad file type vp: %p", __func__, vp);
- }
-
- /* If explicitly asked to append, uio_offset can be wrong? */
- if (ioflag & IO_APPEND)
- uio->uio_offset = file_size;
-
- resid = uio->uio_resid;
- modified = error = 0;
-
- while (uio->uio_resid) {
- lbn = uio->uio_offset / blocksize;
- off = uio->uio_offset & (blocksize - 1);
-
- towrite = omin(uio->uio_resid, blocksize - off);
-
- DPRINTF(WRITE, ("%s: lbn: 0x%jd toread: 0x%zx (0x%x)\n",
- __func__, (uintmax_t)lbn, towrite, blocksize));
-
- error = nandfs_bmap_lookup(node, lbn, &vblk);
- if (error)
- break;
-
- DPRINTF(WRITE, ("%s: lbn: 0x%jd toread: 0x%zx (0x%x) "
- "vblk=%jx\n", __func__, (uintmax_t)lbn, towrite, blocksize,
- vblk));
-
- if (vblk != 0)
- error = nandfs_bread(node, lbn, NOCRED, 0, &bp);
- else
- error = nandfs_bcreate(node, lbn, NOCRED, 0, &bp);
-
- DPRINTF(WRITE, ("%s: vp %p bread bp %p lbn %#jx\n", __func__,
- vp, bp, (uintmax_t)lbn));
- if (error) {
- if (bp)
- brelse(bp);
- break;
- }
-
- error = uiomove((char *)bp->b_data + off, (int)towrite, uio);
- if (error)
- break;
-
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- break;
-
- modified++;
- }
-
- /* XXX proper handling when only part of file was properly written */
- if (modified) {
- if (resid > uio->uio_resid && ap->a_cred &&
- ap->a_cred->cr_uid != 0)
- node->nn_inode.i_mode &= ~(ISUID | ISGID);
-
- if (file_size < uio->uio_offset + uio->uio_resid) {
- node->nn_inode.i_size = uio->uio_offset +
- uio->uio_resid;
- node->nn_flags |= IN_CHANGE | IN_UPDATE;
- vnode_pager_setsize(vp, uio->uio_offset +
- uio->uio_resid);
- nandfs_itimes(vp);
- }
- }
-
- DPRINTF(WRITE, ("%s: return:%d\n", __func__, error));
-
- return (error);
-}
-
-static int
-nandfs_lookup(struct vop_cachedlookup_args *ap)
-{
- struct vnode *dvp, **vpp;
- struct componentname *cnp;
- struct ucred *cred;
- struct thread *td;
- struct nandfs_node *dir_node, *node;
- struct nandfsmount *nmp;
- uint64_t ino, off;
- const char *name;
- int namelen, nameiop, islastcn, mounted_ro;
- int error, found;
-
- DPRINTF(VNCALL, ("%s\n", __func__));
-
- dvp = ap->a_dvp;
- vpp = ap->a_vpp;
- *vpp = NULL;
-
- cnp = ap->a_cnp;
- cred = cnp->cn_cred;
- td = cnp->cn_thread;
-
- dir_node = VTON(dvp);
- nmp = dir_node->nn_nmp;
-
- /* Simplify/clarification flags */
- nameiop = cnp->cn_nameiop;
- islastcn = cnp->cn_flags & ISLASTCN;
- mounted_ro = dvp->v_mount->mnt_flag & MNT_RDONLY;
-
- /*
- * If requesting a modify on the last path element on a read-only
- * filingsystem, reject lookup;
- */
- if (islastcn && mounted_ro && (nameiop == DELETE || nameiop == RENAME))
- return (EROFS);
-
- if (dir_node->nn_inode.i_links_count == 0)
- return (ENOENT);
-
- /*
- * Obviously, the file is not (anymore) in the namecache, we have to
- * search for it. There are three basic cases: '.', '..' and others.
- *
- * Following the guidelines of VOP_LOOKUP manpage and tmpfs.
- */
- error = 0;
- if ((cnp->cn_namelen == 1) && (cnp->cn_nameptr[0] == '.')) {
- DPRINTF(LOOKUP, ("\tlookup '.'\n"));
- /* Special case 1 '.' */
- VREF(dvp);
- *vpp = dvp;
- /* Done */
- } else if (cnp->cn_flags & ISDOTDOT) {
- /* Special case 2 '..' */
- DPRINTF(LOOKUP, ("\tlookup '..'\n"));
-
- /* Get our node */
- name = "..";
- namelen = 2;
- error = nandfs_lookup_name_in_dir(dvp, name, namelen, &ino,
- &found, &off);
- if (error)
- goto out;
- if (!found)
- error = ENOENT;
-
- /* First unlock parent */
- VOP_UNLOCK(dvp, 0);
-
- if (error == 0) {
- DPRINTF(LOOKUP, ("\tfound '..'\n"));
- /* Try to create/reuse the node */
- error = nandfs_get_node(nmp, ino, &node);
-
- if (!error) {
- DPRINTF(LOOKUP,
- ("\tnode retrieved/created OK\n"));
- *vpp = NTOV(node);
- }
- }
-
- /* Try to relock parent */
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
- } else {
- DPRINTF(LOOKUP, ("\tlookup file\n"));
- /* All other files */
- /* Look up filename in the directory returning its inode */
- name = cnp->cn_nameptr;
- namelen = cnp->cn_namelen;
- error = nandfs_lookup_name_in_dir(dvp, name, namelen,
- &ino, &found, &off);
- if (error)
- goto out;
- if (!found) {
- DPRINTF(LOOKUP, ("\tNOT found\n"));
- /*
- * UGH, didn't find name. If we're creating or
- * renaming on the last name this is OK and we ought
- * to return EJUSTRETURN if its allowed to be created.
- */
- error = ENOENT;
- if ((nameiop == CREATE || nameiop == RENAME) &&
- islastcn) {
- error = VOP_ACCESS(dvp, VWRITE, cred, td);
- if (!error) {
- /* keep the component name */
- cnp->cn_flags |= SAVENAME;
- error = EJUSTRETURN;
- }
- }
- /* Done */
- } else {
- if (ino == NANDFS_WHT_INO)
- cnp->cn_flags |= ISWHITEOUT;
-
- if ((cnp->cn_flags & ISWHITEOUT) &&
- (nameiop == LOOKUP))
- return (ENOENT);
-
- if ((nameiop == DELETE) && islastcn) {
- if ((cnp->cn_flags & ISWHITEOUT) &&
- (cnp->cn_flags & DOWHITEOUT)) {
- cnp->cn_flags |= SAVENAME;
- dir_node->nn_diroff = off;
- return (EJUSTRETURN);
- }
-
- error = VOP_ACCESS(dvp, VWRITE, cred,
- cnp->cn_thread);
- if (error)
- return (error);
-
- /* Try to create/reuse the node */
- error = nandfs_get_node(nmp, ino, &node);
- if (!error) {
- *vpp = NTOV(node);
- node->nn_diroff = off;
- }
-
- if ((dir_node->nn_inode.i_mode & ISVTX) &&
- cred->cr_uid != 0 &&
- cred->cr_uid != dir_node->nn_inode.i_uid &&
- node->nn_inode.i_uid != cred->cr_uid) {
- vput(*vpp);
- *vpp = NULL;
- return (EPERM);
- }
- } else if ((nameiop == RENAME) && islastcn) {
- error = VOP_ACCESS(dvp, VWRITE, cred,
- cnp->cn_thread);
- if (error)
- return (error);
-
- /* Try to create/reuse the node */
- error = nandfs_get_node(nmp, ino, &node);
- if (!error) {
- *vpp = NTOV(node);
- node->nn_diroff = off;
- }
- } else {
- /* Try to create/reuse the node */
- error = nandfs_get_node(nmp, ino, &node);
- if (!error) {
- *vpp = NTOV(node);
- node->nn_diroff = off;
- }
- }
- }
- }
-
-out:
- /*
- * Store result in the cache if requested. If we are creating a file,
- * the file might not be found and thus putting it into the namecache
- * might be seen as negative caching.
- */
- if ((cnp->cn_flags & MAKEENTRY) != 0)
- cache_enter(dvp, *vpp, cnp);
-
- return (error);
-
-}
-
-static int
-nandfs_getattr(struct vop_getattr_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct vattr *vap = ap->a_vap;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_inode *inode = &node->nn_inode;
-
- DPRINTF(VNCALL, ("%s: vp: %p\n", __func__, vp));
- nandfs_itimes(vp);
-
- /* Basic info */
- VATTR_NULL(vap);
- vap->va_atime.tv_sec = inode->i_mtime;
- vap->va_atime.tv_nsec = inode->i_mtime_nsec;
- vap->va_mtime.tv_sec = inode->i_mtime;
- vap->va_mtime.tv_nsec = inode->i_mtime_nsec;
- vap->va_ctime.tv_sec = inode->i_ctime;
- vap->va_ctime.tv_nsec = inode->i_ctime_nsec;
- vap->va_type = IFTOVT(inode->i_mode);
- vap->va_mode = inode->i_mode & ~S_IFMT;
- vap->va_nlink = inode->i_links_count;
- vap->va_uid = inode->i_uid;
- vap->va_gid = inode->i_gid;
- vap->va_rdev = inode->i_special;
- vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
- vap->va_fileid = node->nn_ino;
- vap->va_size = inode->i_size;
- vap->va_blocksize = node->nn_nandfsdev->nd_blocksize;
- vap->va_gen = 0;
- vap->va_flags = inode->i_flags;
- vap->va_bytes = inode->i_blocks * vap->va_blocksize;
- vap->va_filerev = 0;
- vap->va_vaflags = 0;
-
- return (0);
-}
-
-static int
-nandfs_vtruncbuf(struct vnode *vp, uint64_t nblks)
-{
- struct nandfs_device *nffsdev;
- struct bufobj *bo;
- struct buf *bp, *nbp;
-
- bo = &vp->v_bufobj;
- nffsdev = VTON(vp)->nn_nandfsdev;
-
- ASSERT_VOP_LOCKED(vp, "nandfs_truncate");
-restart:
- BO_LOCK(bo);
-restart_locked:
- TAILQ_FOREACH_SAFE(bp, &bo->bo_clean.bv_hd, b_bobufs, nbp) {
- if (bp->b_lblkno < nblks)
- continue;
- if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL))
- goto restart_locked;
-
- bremfree(bp);
- bp->b_flags |= (B_INVAL | B_RELBUF);
- bp->b_flags &= ~(B_ASYNC | B_MANAGED);
- BO_UNLOCK(bo);
- brelse(bp);
- BO_LOCK(bo);
- }
-
- TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
- if (bp->b_lblkno < nblks)
- continue;
- if (BUF_LOCK(bp,
- LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK,
- BO_LOCKPTR(bo)) == ENOLCK)
- goto restart;
- bp->b_flags |= (B_INVAL | B_RELBUF);
- bp->b_flags &= ~(B_ASYNC | B_MANAGED);
- brelse(bp);
- nandfs_dirty_bufs_decrement(nffsdev);
- BO_LOCK(bo);
- }
-
- BO_UNLOCK(bo);
-
- return (0);
-}
-
-static int
-nandfs_truncate(struct vnode *vp, uint64_t newsize)
-{
- struct nandfs_device *nffsdev;
- struct nandfs_node *node;
- struct nandfs_inode *inode;
- struct buf *bp = NULL;
- uint64_t oblks, nblks, vblk, size, rest;
- int error;
-
- node = VTON(vp);
- nffsdev = node->nn_nandfsdev;
- inode = &node->nn_inode;
-
- /* Calculate end of file */
- size = inode->i_size;
-
- if (newsize == size) {
- node->nn_flags |= IN_CHANGE | IN_UPDATE;
- nandfs_itimes(vp);
- return (0);
- }
-
- if (newsize > size) {
- inode->i_size = newsize;
- vnode_pager_setsize(vp, newsize);
- node->nn_flags |= IN_CHANGE | IN_UPDATE;
- nandfs_itimes(vp);
- return (0);
- }
-
- nblks = howmany(newsize, nffsdev->nd_blocksize);
- oblks = howmany(size, nffsdev->nd_blocksize);
- rest = newsize % nffsdev->nd_blocksize;
-
- if (rest) {
- error = nandfs_bmap_lookup(node, nblks - 1, &vblk);
- if (error)
- return (error);
-
- if (vblk != 0)
- error = nandfs_bread(node, nblks - 1, NOCRED, 0, &bp);
- else
- error = nandfs_bcreate(node, nblks - 1, NOCRED, 0, &bp);
-
- if (error) {
- if (bp)
- brelse(bp);
- return (error);
- }
-
- bzero((char *)bp->b_data + rest,
- (u_int)(nffsdev->nd_blocksize - rest));
- error = nandfs_dirty_buf(bp, 0);
- if (error)
- return (error);
- }
-
- DPRINTF(VNCALL, ("%s: vp %p oblks %jx nblks %jx\n", __func__, vp, oblks,
- nblks));
-
- error = nandfs_bmap_truncate_mapping(node, oblks - 1, nblks - 1);
- if (error) {
- if (bp)
- nandfs_undirty_buf(bp);
- return (error);
- }
-
- error = nandfs_vtruncbuf(vp, nblks);
- if (error) {
- if (bp)
- nandfs_undirty_buf(bp);
- return (error);
- }
-
- inode->i_size = newsize;
- vnode_pager_setsize(vp, newsize);
- node->nn_flags |= IN_CHANGE | IN_UPDATE;
- nandfs_itimes(vp);
-
- return (error);
-}
-
-static void
-nandfs_itimes_locked(struct vnode *vp)
-{
- struct nandfs_node *node;
- struct nandfs_inode *inode;
- struct timespec ts;
-
- ASSERT_VI_LOCKED(vp, __func__);
-
- node = VTON(vp);
- inode = &node->nn_inode;
-
- if ((node->nn_flags & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
- return;
-
- if (((vp->v_mount->mnt_kern_flag &
- (MNTK_SUSPENDED | MNTK_SUSPEND)) == 0) ||
- (node->nn_flags & (IN_CHANGE | IN_UPDATE)))
- node->nn_flags |= IN_MODIFIED;
-
- vfs_timestamp(&ts);
- if (node->nn_flags & IN_UPDATE) {
- inode->i_mtime = ts.tv_sec;
- inode->i_mtime_nsec = ts.tv_nsec;
- }
- if (node->nn_flags & IN_CHANGE) {
- inode->i_ctime = ts.tv_sec;
- inode->i_ctime_nsec = ts.tv_nsec;
- }
-
- node->nn_flags &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
-}
-
-void
-nandfs_itimes(struct vnode *vp)
-{
-
- VI_LOCK(vp);
- nandfs_itimes_locked(vp);
- VI_UNLOCK(vp);
-}
-
-static int
-nandfs_chmod(struct vnode *vp, int mode, struct ucred *cred, struct thread *td)
-{
- struct nandfs_node *node = VTON(vp);
- struct nandfs_inode *inode = &node->nn_inode;
- uint16_t nmode;
- int error = 0;
-
- DPRINTF(VNCALL, ("%s: vp %p, mode %x, cred %p, td %p\n", __func__, vp,
- mode, cred, td));
- /*
- * To modify the permissions on a file, must possess VADMIN
- * for that file.
- */
- if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
- return (error);
-
- /*
- * Privileged processes may set the sticky bit on non-directories,
- * as well as set the setgid bit on a file with a group that the
- * process is not a member of. Both of these are allowed in
- * jail(8).
- */
- if (vp->v_type != VDIR && (mode & S_ISTXT)) {
- if (priv_check_cred(cred, PRIV_VFS_STICKYFILE))
- return (EFTYPE);
- }
- if (!groupmember(inode->i_gid, cred) && (mode & ISGID)) {
- error = priv_check_cred(cred, PRIV_VFS_SETGID);
- if (error)
- return (error);
- }
-
- /*
- * Deny setting setuid if we are not the file owner.
- */
- if ((mode & ISUID) && inode->i_uid != cred->cr_uid) {
- error = priv_check_cred(cred, PRIV_VFS_ADMIN);
- if (error)
- return (error);
- }
-
- nmode = inode->i_mode;
- nmode &= ~ALLPERMS;
- nmode |= (mode & ALLPERMS);
- inode->i_mode = nmode;
- node->nn_flags |= IN_CHANGE;
-
- DPRINTF(VNCALL, ("%s: to mode %x\n", __func__, nmode));
-
- return (error);
-}
-
-static int
-nandfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred,
- struct thread *td)
-{
- struct nandfs_node *node = VTON(vp);
- struct nandfs_inode *inode = &node->nn_inode;
- uid_t ouid;
- gid_t ogid;
- int error = 0;
-
- if (uid == (uid_t)VNOVAL)
- uid = inode->i_uid;
- if (gid == (gid_t)VNOVAL)
- gid = inode->i_gid;
- /*
- * To modify the ownership of a file, must possess VADMIN for that
- * file.
- */
- if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred, td)))
- return (error);
- /*
- * To change the owner of a file, or change the group of a file to a
- * group of which we are not a member, the caller must have
- * privilege.
- */
- if (((uid != inode->i_uid && uid != cred->cr_uid) ||
- (gid != inode->i_gid && !groupmember(gid, cred))) &&
- (error = priv_check_cred(cred, PRIV_VFS_CHOWN)))
- return (error);
- ogid = inode->i_gid;
- ouid = inode->i_uid;
-
- inode->i_gid = gid;
- inode->i_uid = uid;
-
- node->nn_flags |= IN_CHANGE;
- if ((inode->i_mode & (ISUID | ISGID)) &&
- (ouid != uid || ogid != gid)) {
- if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID))
- inode->i_mode &= ~(ISUID | ISGID);
- }
- DPRINTF(VNCALL, ("%s: vp %p, cred %p, td %p - ret OK\n", __func__, vp,
- cred, td));
- return (0);
-}
-
-static int
-nandfs_setattr(struct vop_setattr_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_inode *inode = &node->nn_inode;
- struct vattr *vap = ap->a_vap;
- struct ucred *cred = ap->a_cred;
- struct thread *td = curthread;
- uint32_t flags;
- int error = 0;
-
- if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
- (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
- (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
- (vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
- DPRINTF(VNCALL, ("%s: unsettable attribute\n", __func__));
- return (EINVAL);
- }
-
- if (vap->va_flags != VNOVAL) {
- DPRINTF(VNCALL, ("%s: vp:%p td:%p flags:%lx\n", __func__, vp,
- td, vap->va_flags));
-
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- /*
- * Callers may only modify the file flags on objects they
- * have VADMIN rights for.
- */
- if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
- return (error);
- /*
- * Unprivileged processes are not permitted to unset system
- * flags, or modify flags if any system flags are set.
- * Privileged non-jail processes may not modify system flags
- * if securelevel > 0 and any existing system flags are set.
- * Privileged jail processes behave like privileged non-jail
- * processes if the PR_ALLOW_CHFLAGS permission bit is set;
- * otherwise, they behave like unprivileged processes.
- */
-
- flags = inode->i_flags;
- if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS)) {
- if (flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
- error = securelevel_gt(cred, 0);
- if (error)
- return (error);
- }
- /* Snapshot flag cannot be set or cleared */
- if (((vap->va_flags & SF_SNAPSHOT) != 0 &&
- (flags & SF_SNAPSHOT) == 0) ||
- ((vap->va_flags & SF_SNAPSHOT) == 0 &&
- (flags & SF_SNAPSHOT) != 0))
- return (EPERM);
-
- inode->i_flags = vap->va_flags;
- } else {
- if (flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
- (vap->va_flags & UF_SETTABLE) != vap->va_flags)
- return (EPERM);
-
- flags &= SF_SETTABLE;
- flags |= (vap->va_flags & UF_SETTABLE);
- inode->i_flags = flags;
- }
- node->nn_flags |= IN_CHANGE;
- if (vap->va_flags & (IMMUTABLE | APPEND))
- return (0);
- }
- if (inode->i_flags & (IMMUTABLE | APPEND))
- return (EPERM);
-
- if (vap->va_size != (u_quad_t)VNOVAL) {
- DPRINTF(VNCALL, ("%s: vp:%p td:%p size:%jx\n", __func__, vp, td,
- (uintmax_t)vap->va_size));
-
- switch (vp->v_type) {
- case VDIR:
- return (EISDIR);
- case VLNK:
- case VREG:
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- if ((inode->i_flags & SF_SNAPSHOT) != 0)
- return (EPERM);
- break;
- default:
- return (0);
- }
-
- if (vap->va_size > node->nn_nandfsdev->nd_maxfilesize)
- return (EFBIG);
-
- KASSERT((vp->v_type == VREG), ("Set size %d", vp->v_type));
- nandfs_truncate(vp, vap->va_size);
- node->nn_flags |= IN_CHANGE;
-
- return (0);
- }
-
- if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- DPRINTF(VNCALL, ("%s: vp:%p td:%p uid/gid %x/%x\n", __func__,
- vp, td, vap->va_uid, vap->va_gid));
- error = nandfs_chown(vp, vap->va_uid, vap->va_gid, cred, td);
- if (error)
- return (error);
- }
-
- if (vap->va_mode != (mode_t)VNOVAL) {
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- DPRINTF(VNCALL, ("%s: vp:%p td:%p mode %x\n", __func__, vp, td,
- vap->va_mode));
-
- error = nandfs_chmod(vp, (int)vap->va_mode, cred, td);
- if (error)
- return (error);
- }
- if (vap->va_atime.tv_sec != VNOVAL ||
- vap->va_mtime.tv_sec != VNOVAL ||
- vap->va_birthtime.tv_sec != VNOVAL) {
- DPRINTF(VNCALL, ("%s: vp:%p td:%p time a/m/b %jx/%jx/%jx\n",
- __func__, vp, td, (uintmax_t)vap->va_atime.tv_sec,
- (uintmax_t)vap->va_mtime.tv_sec,
- (uintmax_t)vap->va_birthtime.tv_sec));
-
- if (vap->va_atime.tv_sec != VNOVAL)
- node->nn_flags |= IN_ACCESS;
- if (vap->va_mtime.tv_sec != VNOVAL)
- node->nn_flags |= IN_CHANGE | IN_UPDATE;
- if (vap->va_birthtime.tv_sec != VNOVAL)
- node->nn_flags |= IN_MODIFIED;
- nandfs_itimes(vp);
- return (0);
- }
-
- return (0);
-}
-
-static int
-nandfs_open(struct vop_open_args *ap)
-{
- struct nandfs_node *node = VTON(ap->a_vp);
- uint64_t filesize;
-
- DPRINTF(VNCALL, ("nandfs_open called ap->a_mode %x\n", ap->a_mode));
-
- if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
- return (EOPNOTSUPP);
-
- if ((node->nn_inode.i_flags & APPEND) &&
- (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
- return (EPERM);
-
- filesize = node->nn_inode.i_size;
- vnode_create_vobject(ap->a_vp, filesize, ap->a_td);
-
- return (0);
-}
-
-static int
-nandfs_close(struct vop_close_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
-
- DPRINTF(VNCALL, ("%s: vp %p node %p\n", __func__, vp, node));
-
- mtx_lock(&vp->v_interlock);
- if (vp->v_usecount > 1)
- nandfs_itimes_locked(vp);
- mtx_unlock(&vp->v_interlock);
-
- return (0);
-}
-
-static int
-nandfs_check_possible(struct vnode *vp, struct vattr *vap, mode_t mode)
-{
-
- /* Check if we are allowed to write */
- switch (vap->va_type) {
- case VDIR:
- case VLNK:
- case VREG:
- /*
- * Normal nodes: check if we're on a read-only mounted
- * filingsystem and bomb out if we're trying to write.
- */
- if ((mode & VMODIFY_PERMS) && (vp->v_mount->mnt_flag & MNT_RDONLY))
- return (EROFS);
- break;
- case VBLK:
- case VCHR:
- case VSOCK:
- case VFIFO:
- /*
- * Special nodes: even on read-only mounted filingsystems
- * these are allowed to be written to if permissions allow.
- */
- break;
- default:
- /* No idea what this is */
- return (EINVAL);
- }
-
- /* No one may write immutable files */
- if ((mode & VWRITE) && (VTON(vp)->nn_inode.i_flags & IMMUTABLE))
- return (EPERM);
-
- return (0);
-}
-
-static int
-nandfs_check_permitted(struct vnode *vp, struct vattr *vap, mode_t mode,
- struct ucred *cred)
-{
-
- return (vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid, mode,
- cred, NULL));
-}
-
-static int
-nandfs_advlock(struct vop_advlock_args *ap)
-{
- struct nandfs_node *nvp;
- quad_t size;
-
- nvp = VTON(ap->a_vp);
- size = nvp->nn_inode.i_size;
- return (lf_advlock(ap, &(nvp->nn_lockf), size));
-}
-
-static int
-nandfs_access(struct vop_access_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- accmode_t accmode = ap->a_accmode;
- struct ucred *cred = ap->a_cred;
- struct vattr vap;
- int error;
-
- DPRINTF(VNCALL, ("%s: vp:%p mode: %x\n", __func__, vp, accmode));
-
- error = VOP_GETATTR(vp, &vap, NULL);
- if (error)
- return (error);
-
- error = nandfs_check_possible(vp, &vap, accmode);
- if (error)
- return (error);
-
- error = nandfs_check_permitted(vp, &vap, accmode, cred);
-
- return (error);
-}
-
-static int
-nandfs_print(struct vop_print_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *nvp = VTON(vp);
-
- printf("\tvp=%p, nandfs_node=%p\n", vp, nvp);
- printf("nandfs inode %#jx\n", (uintmax_t)nvp->nn_ino);
- printf("flags = 0x%b\n", (u_int)nvp->nn_flags, PRINT_NODE_FLAGS);
-
- return (0);
-}
-
-static void
-nandfs_read_filebuf(struct nandfs_node *node, struct buf *bp)
-{
- struct nandfs_device *nandfsdev = node->nn_nandfsdev;
- struct buf *nbp;
- nandfs_daddr_t vblk, pblk;
- nandfs_lbn_t from;
- uint32_t blocksize;
- int error = 0;
- int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE;
-
- /*
- * Translate all the block sectors into a series of buffers to read
- * asynchronously from the nandfs device. Note that this lookup may
- * induce readin's too.
- */
-
- blocksize = nandfsdev->nd_blocksize;
- if (bp->b_bcount / blocksize != 1)
- panic("invalid b_count in bp %p\n", bp);
-
- from = bp->b_blkno;
-
- DPRINTF(READ, ("\tread in from inode %#jx blkno %#jx"
- " count %#lx\n", (uintmax_t)node->nn_ino, from,
- bp->b_bcount));
-
- /* Get virtual block numbers for the vnode's buffer span */
- error = nandfs_bmap_lookup(node, from, &vblk);
- if (error) {
- bp->b_error = EINVAL;
- bp->b_ioflags |= BIO_ERROR;
- bufdone(bp);
- return;
- }
-
- /* Translate virtual block numbers to physical block numbers */
- error = nandfs_vtop(node, vblk, &pblk);
- if (error) {
- bp->b_error = EINVAL;
- bp->b_ioflags |= BIO_ERROR;
- bufdone(bp);
- return;
- }
-
- /* Issue translated blocks */
- bp->b_resid = bp->b_bcount;
-
- /* Note virtual block 0 marks not mapped */
- if (vblk == 0) {
- vfs_bio_clrbuf(bp);
- bufdone(bp);
- return;
- }
-
- nbp = bp;
- nbp->b_blkno = pblk * blk2dev;
- bp->b_iooffset = dbtob(nbp->b_blkno);
- MPASS(bp->b_iooffset >= 0);
- BO_STRATEGY(&nandfsdev->nd_devvp->v_bufobj, nbp);
- nandfs_vblk_set(bp, vblk);
- DPRINTF(READ, ("read_filebuf : ino %#jx blk %#jx -> "
- "%#jx -> %#jx [bp %p]\n", (uintmax_t)node->nn_ino,
- (uintmax_t)(from), (uintmax_t)vblk,
- (uintmax_t)pblk, nbp));
-}
-
-static void
-nandfs_write_filebuf(struct nandfs_node *node, struct buf *bp)
-{
- struct nandfs_device *nandfsdev = node->nn_nandfsdev;
-
- bp->b_iooffset = dbtob(bp->b_blkno);
- MPASS(bp->b_iooffset >= 0);
- BO_STRATEGY(&nandfsdev->nd_devvp->v_bufobj, bp);
-}
-
-static int
-nandfs_strategy(struct vop_strategy_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct buf *bp = ap->a_bp;
- struct nandfs_node *node = VTON(vp);
-
-
- /* check if we ought to be here */
- KASSERT((vp->v_type != VBLK && vp->v_type != VCHR),
- ("nandfs_strategy on type %d", vp->v_type));
-
- /* Translate if needed and pass on */
- if (bp->b_iocmd == BIO_READ) {
- nandfs_read_filebuf(node, bp);
- return (0);
- }
-
- /* Send to segment collector */
- nandfs_write_filebuf(node, bp);
- return (0);
-}
-
-static int
-nandfs_readdir(struct vop_readdir_args *ap)
-{
- struct uio *uio = ap->a_uio;
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_dir_entry *ndirent;
- struct dirent dirent;
- struct buf *bp;
- uint64_t file_size, diroffset, transoffset, blkoff;
- uint64_t blocknr;
- uint32_t blocksize = node->nn_nandfsdev->nd_blocksize;
- uint8_t *pos, name_len;
- int error;
-
- DPRINTF(READDIR, ("nandfs_readdir called\n"));
-
- if (vp->v_type != VDIR)
- return (ENOTDIR);
-
- file_size = node->nn_inode.i_size;
- DPRINTF(READDIR, ("nandfs_readdir filesize %jd resid %zd\n",
- (uintmax_t)file_size, uio->uio_resid ));
-
- /* We are called just as long as we keep on pushing data in */
- error = 0;
- if ((uio->uio_offset < file_size) &&
- (uio->uio_resid >= sizeof(struct dirent))) {
- diroffset = uio->uio_offset;
- transoffset = diroffset;
-
- blocknr = diroffset / blocksize;
- blkoff = diroffset % blocksize;
- error = nandfs_bread(node, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (EIO);
- }
- while (diroffset < file_size) {
- DPRINTF(READDIR, ("readdir : offset = %"PRIu64"\n",
- diroffset));
- if (blkoff >= blocksize) {
- blkoff = 0; blocknr++;
- brelse(bp);
- error = nandfs_bread(node, blocknr, NOCRED, 0,
- &bp);
- if (error) {
- brelse(bp);
- return (EIO);
- }
- }
-
- /* Read in one dirent */
- pos = (uint8_t *)bp->b_data + blkoff;
- ndirent = (struct nandfs_dir_entry *)pos;
-
- name_len = ndirent->name_len;
- memset(&dirent, 0, sizeof(dirent));
- dirent.d_fileno = ndirent->inode;
- if (dirent.d_fileno) {
- dirent.d_type = ndirent->file_type;
- dirent.d_namlen = name_len;
- strncpy(dirent.d_name, ndirent->name, name_len);
- dirent.d_reclen = GENERIC_DIRSIZ(&dirent);
- /* NOTE: d_off is the offset of the *next* entry. */
- dirent.d_off = diroffset + ndirent->rec_len;
- dirent_terminate(&dirent);
- DPRINTF(READDIR, ("copying `%*.*s`\n", name_len,
- name_len, dirent.d_name));
- }
-
- /*
- * If there isn't enough space in the uio to return a
- * whole dirent, break off read
- */
- if (uio->uio_resid < GENERIC_DIRSIZ(&dirent))
- break;
-
- /* Transfer */
- if (dirent.d_fileno)
- uiomove(&dirent, dirent.d_reclen, uio);
-
- /* Advance */
- diroffset += ndirent->rec_len;
- blkoff += ndirent->rec_len;
-
- /* Remember the last entry we transferred */
- transoffset = diroffset;
- }
- brelse(bp);
-
- /* Pass on last transferred offset */
- uio->uio_offset = transoffset;
- }
-
- if (ap->a_eofflag)
- *ap->a_eofflag = (uio->uio_offset >= file_size);
-
- return (error);
-}
-
-static int
-nandfs_dirempty(struct vnode *dvp, uint64_t parentino, struct ucred *cred)
-{
- struct nandfs_node *dnode = VTON(dvp);
- struct nandfs_dir_entry *dirent;
- uint64_t file_size = dnode->nn_inode.i_size;
- uint64_t blockcount = dnode->nn_inode.i_blocks;
- uint64_t blocknr;
- uint32_t blocksize = dnode->nn_nandfsdev->nd_blocksize;
- uint32_t limit;
- uint32_t off;
- uint8_t *pos;
- struct buf *bp;
- int error;
-
- DPRINTF(LOOKUP, ("%s: dvp %p parentino %#jx cred %p\n", __func__, dvp,
- (uintmax_t)parentino, cred));
-
- KASSERT((file_size != 0), ("nandfs_dirempty for NULL dir %p", dvp));
-
- blocknr = 0;
- while (blocknr < blockcount) {
- error = nandfs_bread(dnode, blocknr, NOCRED, 0, &bp);
- if (error) {
- brelse(bp);
- return (0);
- }
-
- pos = (uint8_t *)bp->b_data;
- off = 0;
-
- if (blocknr == (blockcount - 1))
- limit = file_size % blocksize;
- else
- limit = blocksize;
-
- while (off < limit) {
- dirent = (struct nandfs_dir_entry *)(pos + off);
- off += dirent->rec_len;
-
- if (dirent->inode == 0)
- continue;
-
- switch (dirent->name_len) {
- case 0:
- break;
- case 1:
- if (dirent->name[0] != '.')
- goto notempty;
-
- KASSERT(dirent->inode == dnode->nn_ino,
- (".'s inode does not match dir"));
- break;
- case 2:
- if (dirent->name[0] != '.' &&
- dirent->name[1] != '.')
- goto notempty;
-
- KASSERT(dirent->inode == parentino,
- ("..'s inode does not match parent"));
- break;
- default:
- goto notempty;
- }
- }
-
- brelse(bp);
- blocknr++;
- }
-
- return (1);
-notempty:
- brelse(bp);
- return (0);
-}
-
-static int
-nandfs_link(struct vop_link_args *ap)
-{
- struct vnode *tdvp = ap->a_tdvp;
- struct vnode *vp = ap->a_vp;
- struct componentname *cnp = ap->a_cnp;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_inode *inode = &node->nn_inode;
- int error;
-
- if (inode->i_links_count >= NANDFS_LINK_MAX)
- return (EMLINK);
-
- if (inode->i_flags & (IMMUTABLE | APPEND))
- return (EPERM);
-
- /* Update link count */
- inode->i_links_count++;
-
- /* Add dir entry */
- error = nandfs_add_dirent(tdvp, node->nn_ino, cnp->cn_nameptr,
- cnp->cn_namelen, IFTODT(inode->i_mode));
- if (error) {
- inode->i_links_count--;
- }
-
- node->nn_flags |= IN_CHANGE;
- nandfs_itimes(vp);
- DPRINTF(VNCALL, ("%s: tdvp %p vp %p cnp %p\n",
- __func__, tdvp, vp, cnp));
-
- return (0);
-}
-
-static int
-nandfs_create(struct vop_create_args *ap)
-{
- struct vnode *dvp = ap->a_dvp;
- struct vnode **vpp = ap->a_vpp;
- struct componentname *cnp = ap->a_cnp;
- uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfsmount *nmp = dir_node->nn_nmp;
- struct nandfs_node *node;
- int error;
-
- DPRINTF(VNCALL, ("%s: dvp %p\n", __func__, dvp));
-
- if (nandfs_fs_full(dir_node->nn_nandfsdev))
- return (ENOSPC);
-
- /* Create new vnode/inode */
- error = nandfs_node_create(nmp, &node, mode);
- if (error)
- return (error);
- node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
- node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
-
- /* Add new dir entry */
- error = nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
- cnp->cn_namelen, IFTODT(mode));
- if (error) {
- if (nandfs_node_destroy(node)) {
- nandfs_error("%s: error destroying node %p\n",
- __func__, node);
- }
- return (error);
- }
- *vpp = NTOV(node);
- if ((cnp->cn_flags & MAKEENTRY) != 0)
- cache_enter(dvp, *vpp, cnp);
-
- DPRINTF(VNCALL, ("created file vp %p nandnode %p ino %jx\n", *vpp, node,
- (uintmax_t)node->nn_ino));
- return (0);
-}
-
-static int
-nandfs_remove(struct vop_remove_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *dvp = ap->a_dvp;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_node *dnode = VTON(dvp);
- struct componentname *cnp = ap->a_cnp;
-
- DPRINTF(VNCALL, ("%s: dvp %p vp %p nandnode %p ino %#jx link %d\n",
- __func__, dvp, vp, node, (uintmax_t)node->nn_ino,
- node->nn_inode.i_links_count));
-
- if (vp->v_type == VDIR)
- return (EISDIR);
-
- /* Files marked as immutable or append-only cannot be deleted. */
- if ((node->nn_inode.i_flags & (IMMUTABLE | APPEND | NOUNLINK)) ||
- (dnode->nn_inode.i_flags & APPEND))
- return (EPERM);
-
- nandfs_remove_dirent(dvp, node, cnp);
- node->nn_inode.i_links_count--;
- node->nn_flags |= IN_CHANGE;
-
- return (0);
-}
-
-/*
- * Check if source directory is in the path of the target directory.
- * Target is supplied locked, source is unlocked.
- * The target is always vput before returning.
- */
-static int
-nandfs_checkpath(struct nandfs_node *src, struct nandfs_node *dest,
- struct ucred *cred)
-{
- struct vnode *vp;
- int error, rootino;
- struct nandfs_dir_entry dirent;
-
- vp = NTOV(dest);
- if (src->nn_ino == dest->nn_ino) {
- error = EEXIST;
- goto out;
- }
- rootino = NANDFS_ROOT_INO;
- error = 0;
- if (dest->nn_ino == rootino)
- goto out;
-
- for (;;) {
- if (vp->v_type != VDIR) {
- error = ENOTDIR;
- break;
- }
-
- error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirent,
- NANDFS_DIR_REC_LEN(2), (off_t)0, UIO_SYSSPACE,
- IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED,
- NULL, NULL);
- if (error != 0)
- break;
- if (dirent.name_len != 2 ||
- dirent.name[0] != '.' ||
- dirent.name[1] != '.') {
- error = ENOTDIR;
- break;
- }
- if (dirent.inode == src->nn_ino) {
- error = EINVAL;
- break;
- }
- if (dirent.inode == rootino)
- break;
- vput(vp);
- if ((error = VFS_VGET(vp->v_mount, dirent.inode,
- LK_EXCLUSIVE, &vp)) != 0) {
- vp = NULL;
- break;
- }
- }
-
-out:
- if (error == ENOTDIR)
- printf("checkpath: .. not a directory\n");
- if (vp != NULL)
- vput(vp);
- return (error);
-}
-
-static int
-nandfs_rename(struct vop_rename_args *ap)
-{
- struct vnode *tvp = ap->a_tvp;
- struct vnode *tdvp = ap->a_tdvp;
- struct vnode *fvp = ap->a_fvp;
- struct vnode *fdvp = ap->a_fdvp;
- struct componentname *tcnp = ap->a_tcnp;
- struct componentname *fcnp = ap->a_fcnp;
- int doingdirectory = 0, oldparent = 0, newparent = 0;
- int error = 0;
-
- struct nandfs_node *fdnode, *fnode, *fnode1;
- struct nandfs_node *tdnode = VTON(tdvp);
- struct nandfs_node *tnode;
-
- uint32_t tdflags, fflags, fdflags;
- uint16_t mode;
-
- DPRINTF(VNCALL, ("%s: fdvp:%p fvp:%p tdvp:%p tdp:%p\n", __func__, fdvp,
- fvp, tdvp, tvp));
-
- /*
- * Check for cross-device rename.
- */
- if ((fvp->v_mount != tdvp->v_mount) ||
- (tvp && (fvp->v_mount != tvp->v_mount))) {
- error = EXDEV;
-abortit:
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- vrele(fdvp);
- vrele(fvp);
- return (error);
- }
-
- tdflags = tdnode->nn_inode.i_flags;
- if (tvp &&
- ((VTON(tvp)->nn_inode.i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
- (tdflags & APPEND))) {
- error = EPERM;
- goto abortit;
- }
-
- /*
- * Renaming a file to itself has no effect. The upper layers should
- * not call us in that case. Temporarily just warn if they do.
- */
- if (fvp == tvp) {
- printf("nandfs_rename: fvp == tvp (can't happen)\n");
- error = 0;
- goto abortit;
- }
-
- if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
- goto abortit;
-
- fdnode = VTON(fdvp);
- fnode = VTON(fvp);
-
- if (fnode->nn_inode.i_links_count >= NANDFS_LINK_MAX) {
- VOP_UNLOCK(fvp, 0);
- error = EMLINK;
- goto abortit;
- }
-
- fflags = fnode->nn_inode.i_flags;
- fdflags = fdnode->nn_inode.i_flags;
-
- if ((fflags & (NOUNLINK | IMMUTABLE | APPEND)) ||
- (fdflags & APPEND)) {
- VOP_UNLOCK(fvp, 0);
- error = EPERM;
- goto abortit;
- }
-
- mode = fnode->nn_inode.i_mode;
- if ((mode & S_IFMT) == S_IFDIR) {
- /*
- * Avoid ".", "..", and aliases of "." for obvious reasons.
- */
-
- if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
- (fdvp == fvp) ||
- ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT) ||
- (fnode->nn_flags & IN_RENAME)) {
- VOP_UNLOCK(fvp, 0);
- error = EINVAL;
- goto abortit;
- }
- fnode->nn_flags |= IN_RENAME;
- doingdirectory = 1;
- DPRINTF(VNCALL, ("%s: doingdirectory dvp %p\n", __func__,
- tdvp));
- oldparent = fdnode->nn_ino;
- }
-
- vrele(fdvp);
-
- tnode = NULL;
- if (tvp)
- tnode = VTON(tvp);
-
- /*
- * Bump link count on fvp while we are moving stuff around. If we
- * crash before completing the work, the link count may be wrong
- * but correctable.
- */
- fnode->nn_inode.i_links_count++;
-
- /* Check for in path moving XXX */
- error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread);
- VOP_UNLOCK(fvp, 0);
- if (oldparent != tdnode->nn_ino)
- newparent = tdnode->nn_ino;
- if (doingdirectory && newparent) {
- if (error) /* write access check above */
- goto bad;
- if (tnode != NULL)
- vput(tvp);
-
- error = nandfs_checkpath(fnode, tdnode, tcnp->cn_cred);
- if (error)
- goto out;
-
- VREF(tdvp);
- error = relookup(tdvp, &tvp, tcnp);
- if (error)
- goto out;
- vrele(tdvp);
- tdnode = VTON(tdvp);
- tnode = NULL;
- if (tvp)
- tnode = VTON(tvp);
- }
-
- /*
- * If the target doesn't exist, link the target to the source and
- * unlink the source. Otherwise, rewrite the target directory to
- * reference the source and remove the original entry.
- */
-
- if (tvp == NULL) {
- /*
- * Account for ".." in new directory.
- */
- if (doingdirectory && fdvp != tdvp)
- tdnode->nn_inode.i_links_count++;
-
- DPRINTF(VNCALL, ("%s: new entry in dvp:%p\n", __func__, tdvp));
- /*
- * Add name in new directory.
- */
- error = nandfs_add_dirent(tdvp, fnode->nn_ino, tcnp->cn_nameptr,
- tcnp->cn_namelen, IFTODT(fnode->nn_inode.i_mode));
- if (error) {
- if (doingdirectory && fdvp != tdvp)
- tdnode->nn_inode.i_links_count--;
- goto bad;
- }
-
- vput(tdvp);
- } else {
- /*
- * If the parent directory is "sticky", then the user must
- * own the parent directory, or the destination of the rename,
- * otherwise the destination may not be changed (except by
- * root). This implements append-only directories.
- */
- if ((tdnode->nn_inode.i_mode & S_ISTXT) &&
- tcnp->cn_cred->cr_uid != 0 &&
- tcnp->cn_cred->cr_uid != tdnode->nn_inode.i_uid &&
- tnode->nn_inode.i_uid != tcnp->cn_cred->cr_uid) {
- error = EPERM;
- goto bad;
- }
- /*
- * Target must be empty if a directory and have no links
- * to it. Also, ensure source and target are compatible
- * (both directories, or both not directories).
- */
- mode = tnode->nn_inode.i_mode;
- if ((mode & S_IFMT) == S_IFDIR) {
- if (!nandfs_dirempty(tvp, tdnode->nn_ino,
- tcnp->cn_cred)) {
- error = ENOTEMPTY;
- goto bad;
- }
- if (!doingdirectory) {
- error = ENOTDIR;
- goto bad;
- }
- /*
- * Update name cache since directory is going away.
- */
- cache_purge(tdvp);
- } else if (doingdirectory) {
- error = EISDIR;
- goto bad;
- }
-
- DPRINTF(VNCALL, ("%s: update entry dvp:%p\n", __func__, tdvp));
- /*
- * Change name tcnp in tdvp to point at fvp.
- */
- error = nandfs_update_dirent(tdvp, fnode, tnode);
- if (error)
- goto bad;
-
- if (doingdirectory && !newparent)
- tdnode->nn_inode.i_links_count--;
-
- vput(tdvp);
-
- tnode->nn_inode.i_links_count--;
- vput(tvp);
- tnode = NULL;
- }
-
- /*
- * Unlink the source.
- */
- fcnp->cn_flags &= ~MODMASK;
- fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
- VREF(fdvp);
- error = relookup(fdvp, &fvp, fcnp);
- if (error == 0)
- vrele(fdvp);
- if (fvp != NULL) {
- fnode1 = VTON(fvp);
- fdnode = VTON(fdvp);
- } else {
- /*
- * From name has disappeared.
- */
- if (doingdirectory)
- panic("nandfs_rename: lost dir entry");
- vrele(ap->a_fvp);
- return (0);
- }
-
- DPRINTF(VNCALL, ("%s: unlink source fnode:%p\n", __func__, fnode));
-
- /*
- * Ensure that the directory entry still exists and has not
- * changed while the new name has been entered. If the source is
- * a file then the entry may have been unlinked or renamed. In
- * either case there is no further work to be done. If the source
- * is a directory then it cannot have been rmdir'ed; its link
- * count of three would cause a rmdir to fail with ENOTEMPTY.
- * The IN_RENAME flag ensures that it cannot be moved by another
- * rename.
- */
- if (fnode != fnode1) {
- if (doingdirectory)
- panic("nandfs: lost dir entry");
- } else {
- /*
- * If the source is a directory with a
- * new parent, the link count of the old
- * parent directory must be decremented
- * and ".." set to point to the new parent.
- */
- if (doingdirectory && newparent) {
- DPRINTF(VNCALL, ("%s: new parent %#jx -> %#jx\n",
- __func__, (uintmax_t) oldparent,
- (uintmax_t) newparent));
- error = nandfs_update_parent_dir(fvp, newparent);
- if (!error) {
- fdnode->nn_inode.i_links_count--;
- fdnode->nn_flags |= IN_CHANGE;
- }
- }
- error = nandfs_remove_dirent(fdvp, fnode, fcnp);
- if (!error) {
- fnode->nn_inode.i_links_count--;
- fnode->nn_flags |= IN_CHANGE;
- }
- fnode->nn_flags &= ~IN_RENAME;
- }
- if (fdnode)
- vput(fdvp);
- if (fnode)
- vput(fvp);
- vrele(ap->a_fvp);
- return (error);
-
-bad:
- DPRINTF(VNCALL, ("%s: error:%d\n", __func__, error));
- if (tnode)
- vput(NTOV(tnode));
- vput(NTOV(tdnode));
-out:
- if (doingdirectory)
- fnode->nn_flags &= ~IN_RENAME;
- if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
- fnode->nn_inode.i_links_count--;
- fnode->nn_flags |= IN_CHANGE;
- fnode->nn_flags &= ~IN_RENAME;
- vput(fvp);
- } else
- vrele(fvp);
- return (error);
-}
-
-static int
-nandfs_mkdir(struct vop_mkdir_args *ap)
-{
- struct vnode *dvp = ap->a_dvp;
- struct vnode **vpp = ap->a_vpp;
- struct componentname *cnp = ap->a_cnp;
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfs_inode *dir_inode = &dir_node->nn_inode;
- struct nandfs_node *node;
- struct nandfsmount *nmp = dir_node->nn_nmp;
- uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
- int error;
-
- DPRINTF(VNCALL, ("%s: dvp %p\n", __func__, dvp));
-
- if (nandfs_fs_full(dir_node->nn_nandfsdev))
- return (ENOSPC);
-
- if (dir_inode->i_links_count >= NANDFS_LINK_MAX)
- return (EMLINK);
-
- error = nandfs_node_create(nmp, &node, mode);
- if (error)
- return (error);
-
- node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
- node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
-
- *vpp = NTOV(node);
-
- error = nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
- cnp->cn_namelen, IFTODT(mode));
- if (error) {
- vput(*vpp);
- return (error);
- }
-
- dir_node->nn_inode.i_links_count++;
- dir_node->nn_flags |= IN_CHANGE;
-
- error = nandfs_init_dir(NTOV(node), node->nn_ino, dir_node->nn_ino);
- if (error) {
- vput(NTOV(node));
- return (error);
- }
-
- DPRINTF(VNCALL, ("created dir vp %p nandnode %p ino %jx\n", *vpp, node,
- (uintmax_t)node->nn_ino));
- return (0);
-}
-
-static int
-nandfs_mknod(struct vop_mknod_args *ap)
-{
- struct vnode *dvp = ap->a_dvp;
- struct vnode **vpp = ap->a_vpp;
- struct vattr *vap = ap->a_vap;
- uint16_t mode = MAKEIMODE(vap->va_type, vap->va_mode);
- struct componentname *cnp = ap->a_cnp;
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfsmount *nmp = dir_node->nn_nmp;
- struct nandfs_node *node;
- int error;
-
- if (nandfs_fs_full(dir_node->nn_nandfsdev))
- return (ENOSPC);
-
- error = nandfs_node_create(nmp, &node, mode);
- if (error)
- return (error);
- node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
- node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
- if (vap->va_rdev != VNOVAL)
- node->nn_inode.i_special = vap->va_rdev;
-
- *vpp = NTOV(node);
-
- if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
- cnp->cn_namelen, IFTODT(mode))) {
- vput(*vpp);
- return (ENOTDIR);
- }
-
- node->nn_flags |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
-
- return (0);
-}
-
-static int
-nandfs_symlink(struct vop_symlink_args *ap)
-{
- struct vnode **vpp = ap->a_vpp;
- struct vnode *dvp = ap->a_dvp;
- uint16_t mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
- struct componentname *cnp = ap->a_cnp;
- struct nandfs_node *dir_node = VTON(dvp);
- struct nandfsmount *nmp = dir_node->nn_nmp;
- struct nandfs_node *node;
- int len, error;
-
- if (nandfs_fs_full(dir_node->nn_nandfsdev))
- return (ENOSPC);
-
- error = nandfs_node_create(nmp, &node, S_IFLNK | mode);
- if (error)
- return (error);
- node->nn_inode.i_gid = dir_node->nn_inode.i_gid;
- node->nn_inode.i_uid = cnp->cn_cred->cr_uid;
-
- *vpp = NTOV(node);
-
- if (nandfs_add_dirent(dvp, node->nn_ino, cnp->cn_nameptr,
- cnp->cn_namelen, IFTODT(mode))) {
- vput(*vpp);
- return (ENOTDIR);
- }
-
-
- len = strlen(ap->a_target);
- error = vn_rdwr(UIO_WRITE, *vpp, __DECONST(void *, ap->a_target),
- len, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK,
- cnp->cn_cred, NOCRED, NULL, NULL);
- if (error)
- vput(*vpp);
-
- return (error);
-}
-
-static int
-nandfs_readlink(struct vop_readlink_args *ap)
-{
- struct vnode *vp = ap->a_vp;
-
- return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
-}
-
-static int
-nandfs_rmdir(struct vop_rmdir_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *dvp = ap->a_dvp;
- struct componentname *cnp = ap->a_cnp;
- struct nandfs_node *node, *dnode;
- uint32_t dflag, flag;
- int error = 0;
-
- node = VTON(vp);
- dnode = VTON(dvp);
-
- /* Files marked as immutable or append-only cannot be deleted. */
- if ((node->nn_inode.i_flags & (IMMUTABLE | APPEND | NOUNLINK)) ||
- (dnode->nn_inode.i_flags & APPEND))
- return (EPERM);
-
- DPRINTF(VNCALL, ("%s: dvp %p vp %p nandnode %p ino %#jx\n", __func__,
- dvp, vp, node, (uintmax_t)node->nn_ino));
-
- if (node->nn_inode.i_links_count < 2)
- return (EINVAL);
-
- if (!nandfs_dirempty(vp, dnode->nn_ino, cnp->cn_cred))
- return (ENOTEMPTY);
-
- /* Files marked as immutable or append-only cannot be deleted. */
- dflag = dnode->nn_inode.i_flags;
- flag = node->nn_inode.i_flags;
- if ((dflag & APPEND) ||
- (flag & (NOUNLINK | IMMUTABLE | APPEND))) {
- return (EPERM);
- }
-
- if (vp->v_mountedhere != 0)
- return (EINVAL);
-
- nandfs_remove_dirent(dvp, node, cnp);
- dnode->nn_inode.i_links_count -= 1;
- dnode->nn_flags |= IN_CHANGE;
-
- cache_purge(dvp);
-
- error = nandfs_truncate(vp, (uint64_t)0);
- if (error)
- return (error);
-
- node->nn_inode.i_links_count -= 2;
- node->nn_flags |= IN_CHANGE;
-
- cache_purge(vp);
-
- return (error);
-}
-
-static int
-nandfs_fsync(struct vop_fsync_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- int locked;
-
- DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx\n", __func__, vp,
- node, (uintmax_t)node->nn_ino));
-
- /*
- * Start syncing vnode only if inode was modified or
- * there are some dirty buffers
- */
- if (VTON(vp)->nn_flags & IN_MODIFIED ||
- vp->v_bufobj.bo_dirty.bv_cnt) {
- locked = VOP_ISLOCKED(vp);
- VOP_UNLOCK(vp, 0);
- nandfs_wakeup_wait_sync(node->nn_nandfsdev, SYNCER_FSYNC);
- VOP_LOCK(vp, locked | LK_RETRY);
- }
-
- return (0);
-}
-
-static int
-nandfs_bmap(struct vop_bmap_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *nnode = VTON(vp);
- struct nandfs_device *nandfsdev = nnode->nn_nandfsdev;
- nandfs_daddr_t l2vmap, v2pmap;
- int error;
- int blk2dev = nandfsdev->nd_blocksize / DEV_BSIZE;
-
- DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx\n", __func__, vp,
- nnode, (uintmax_t)nnode->nn_ino));
-
- if (ap->a_bop != NULL)
- *ap->a_bop = &nandfsdev->nd_devvp->v_bufobj;
- if (ap->a_bnp == NULL)
- return (0);
- if (ap->a_runp != NULL)
- *ap->a_runp = 0;
- if (ap->a_runb != NULL)
- *ap->a_runb = 0;
-
- /*
- * Translate all the block sectors into a series of buffers to read
- * asynchronously from the nandfs device. Note that this lookup may
- * induce readin's too.
- */
-
- /* Get virtual block numbers for the vnode's buffer span */
- error = nandfs_bmap_lookup(nnode, ap->a_bn, &l2vmap);
- if (error)
- return (-1);
-
- /* Translate virtual block numbers to physical block numbers */
- error = nandfs_vtop(nnode, l2vmap, &v2pmap);
- if (error)
- return (-1);
-
- /* Note virtual block 0 marks not mapped */
- if (l2vmap == 0)
- *ap->a_bnp = -1;
- else
- *ap->a_bnp = v2pmap * blk2dev; /* in DEV_BSIZE */
-
- DPRINTF(VNCALL, ("%s: vp %p nandnode %p ino %#jx lblk %jx -> blk %jx\n",
- __func__, vp, nnode, (uintmax_t)nnode->nn_ino, (uintmax_t)ap->a_bn,
- (uintmax_t)*ap->a_bnp ));
-
- return (0);
-}
-
-static void
-nandfs_force_syncer(struct nandfsmount *nmp)
-{
-
- nmp->nm_flags |= NANDFS_FORCE_SYNCER;
- nandfs_wakeup_wait_sync(nmp->nm_nandfsdev, SYNCER_FFORCE);
-}
-
-static int
-nandfs_ioctl(struct vop_ioctl_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- u_long command = ap->a_command;
- caddr_t data = ap->a_data;
- struct nandfs_node *node = VTON(vp);
- struct nandfs_device *nandfsdev = node->nn_nandfsdev;
- struct nandfsmount *nmp = node->nn_nmp;
- uint64_t *tab, *cno;
- struct nandfs_seg_stat *nss;
- struct nandfs_cpmode *ncpm;
- struct nandfs_argv *nargv;
- struct nandfs_cpstat *ncp;
- int error;
-
- DPRINTF(VNCALL, ("%s: %x\n", __func__, (uint32_t)command));
-
- error = priv_check(ap->a_td, PRIV_VFS_MOUNT);
- if (error)
- return (error);
-
- if (nmp->nm_ronly) {
- switch (command) {
- case NANDFS_IOCTL_GET_FSINFO:
- case NANDFS_IOCTL_GET_SUSTAT:
- case NANDFS_IOCTL_GET_CPINFO:
- case NANDFS_IOCTL_GET_CPSTAT:
- case NANDFS_IOCTL_GET_SUINFO:
- case NANDFS_IOCTL_GET_VINFO:
- case NANDFS_IOCTL_GET_BDESCS:
- break;
- default:
- return (EROFS);
- }
- }
-
- switch (command) {
- case NANDFS_IOCTL_GET_FSINFO:
- error = nandfs_get_fsinfo(nmp, (struct nandfs_fsinfo *)data);
- break;
- case NANDFS_IOCTL_GET_SUSTAT:
- nss = (struct nandfs_seg_stat *)data;
- error = nandfs_get_seg_stat(nandfsdev, nss);
- break;
- case NANDFS_IOCTL_CHANGE_CPMODE:
- ncpm = (struct nandfs_cpmode *)data;
- error = nandfs_chng_cpmode(nandfsdev->nd_cp_node, ncpm);
- nandfs_force_syncer(nmp);
- break;
- case NANDFS_IOCTL_GET_CPINFO:
- nargv = (struct nandfs_argv *)data;
- error = nandfs_get_cpinfo_ioctl(nandfsdev->nd_cp_node, nargv);
- break;
- case NANDFS_IOCTL_DELETE_CP:
- tab = (uint64_t *)data;
- error = nandfs_delete_cp(nandfsdev->nd_cp_node, tab[0], tab[1]);
- nandfs_force_syncer(nmp);
- break;
- case NANDFS_IOCTL_GET_CPSTAT:
- ncp = (struct nandfs_cpstat *)data;
- error = nandfs_get_cpstat(nandfsdev->nd_cp_node, ncp);
- break;
- case NANDFS_IOCTL_GET_SUINFO:
- nargv = (struct nandfs_argv *)data;
- error = nandfs_get_segment_info_ioctl(nandfsdev, nargv);
- break;
- case NANDFS_IOCTL_GET_VINFO:
- nargv = (struct nandfs_argv *)data;
- error = nandfs_get_dat_vinfo_ioctl(nandfsdev, nargv);
- break;
- case NANDFS_IOCTL_GET_BDESCS:
- nargv = (struct nandfs_argv *)data;
- error = nandfs_get_dat_bdescs_ioctl(nandfsdev, nargv);
- break;
- case NANDFS_IOCTL_SYNC:
- cno = (uint64_t *)data;
- nandfs_force_syncer(nmp);
- *cno = nandfsdev->nd_last_cno;
- error = 0;
- break;
- case NANDFS_IOCTL_MAKE_SNAP:
- cno = (uint64_t *)data;
- error = nandfs_make_snap(nandfsdev, cno);
- nandfs_force_syncer(nmp);
- break;
- case NANDFS_IOCTL_DELETE_SNAP:
- cno = (uint64_t *)data;
- error = nandfs_delete_snap(nandfsdev, *cno);
- nandfs_force_syncer(nmp);
- break;
- default:
- error = ENOTTY;
- break;
- }
-
- return (error);
-}
-
-/*
- * Whiteout vnode call
- */
-static int
-nandfs_whiteout(struct vop_whiteout_args *ap)
-{
- struct vnode *dvp = ap->a_dvp;
- struct componentname *cnp = ap->a_cnp;
- int error = 0;
-
- switch (ap->a_flags) {
- case LOOKUP:
- return (0);
- case CREATE:
- /* Create a new directory whiteout */
-#ifdef INVARIANTS
- if ((cnp->cn_flags & SAVENAME) == 0)
- panic("nandfs_whiteout: missing name");
-#endif
- error = nandfs_add_dirent(dvp, NANDFS_WHT_INO, cnp->cn_nameptr,
- cnp->cn_namelen, DT_WHT);
- break;
-
- case DELETE:
- /* Remove an existing directory whiteout */
- cnp->cn_flags &= ~DOWHITEOUT;
- error = nandfs_remove_dirent(dvp, NULL, cnp);
- break;
- default:
- panic("nandf_whiteout: unknown op: %d", ap->a_flags);
- }
-
- return (error);
-}
-
-static int
-nandfs_pathconf(struct vop_pathconf_args *ap)
-{
- int error;
-
- error = 0;
- switch (ap->a_name) {
- case _PC_LINK_MAX:
- *ap->a_retval = NANDFS_LINK_MAX;
- break;
- case _PC_NAME_MAX:
- *ap->a_retval = NANDFS_NAME_LEN;
- break;
- case _PC_PIPE_BUF:
- if (ap->a_vp->v_type == VDIR || ap->a_vp->v_type == VFIFO)
- *ap->a_retval = PIPE_BUF;
- else
- error = EINVAL;
- break;
- case _PC_CHOWN_RESTRICTED:
- *ap->a_retval = 1;
- break;
- case _PC_NO_TRUNC:
- *ap->a_retval = 1;
- break;
- case _PC_ALLOC_SIZE_MIN:
- *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_bsize;
- break;
- case _PC_FILESIZEBITS:
- *ap->a_retval = 64;
- break;
- case _PC_REC_INCR_XFER_SIZE:
- *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
- break;
- case _PC_REC_MAX_XFER_SIZE:
- *ap->a_retval = -1; /* means ``unlimited'' */
- break;
- case _PC_REC_MIN_XFER_SIZE:
- *ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
- break;
- default:
- error = vop_stdpathconf(ap);
- break;
- }
- return (error);
-}
-
-static int
-nandfs_vnlock1(struct vop_lock1_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- int error, vi_locked;
-
- /*
- * XXX can vnode go away while we are sleeping?
- */
- vi_locked = mtx_owned(&vp->v_interlock);
- if (vi_locked)
- VI_UNLOCK(vp);
- error = NANDFS_WRITELOCKFLAGS(node->nn_nandfsdev,
- ap->a_flags & LK_NOWAIT);
- if (vi_locked && !error)
- VI_LOCK(vp);
- if (error)
- return (error);
-
- error = vop_stdlock(ap);
- if (error) {
- NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
- return (error);
- }
-
- return (0);
-}
-
-static int
-nandfs_vnunlock(struct vop_unlock_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
- int error;
-
- error = vop_stdunlock(ap);
- if (error)
- return (error);
-
- NANDFS_WRITEUNLOCK(node->nn_nandfsdev);
-
- return (0);
-}
-
-/*
- * Global vfs data structures
- */
-struct vop_vector nandfs_vnodeops = {
- .vop_default = &default_vnodeops,
- .vop_access = nandfs_access,
- .vop_advlock = nandfs_advlock,
- .vop_bmap = nandfs_bmap,
- .vop_close = nandfs_close,
- .vop_create = nandfs_create,
- .vop_fsync = nandfs_fsync,
- .vop_getattr = nandfs_getattr,
- .vop_inactive = nandfs_inactive,
- .vop_cachedlookup = nandfs_lookup,
- .vop_ioctl = nandfs_ioctl,
- .vop_link = nandfs_link,
- .vop_lookup = vfs_cache_lookup,
- .vop_mkdir = nandfs_mkdir,
- .vop_mknod = nandfs_mknod,
- .vop_open = nandfs_open,
- .vop_pathconf = nandfs_pathconf,
- .vop_print = nandfs_print,
- .vop_read = nandfs_read,
- .vop_readdir = nandfs_readdir,
- .vop_readlink = nandfs_readlink,
- .vop_reclaim = nandfs_reclaim,
- .vop_remove = nandfs_remove,
- .vop_rename = nandfs_rename,
- .vop_rmdir = nandfs_rmdir,
- .vop_whiteout = nandfs_whiteout,
- .vop_write = nandfs_write,
- .vop_setattr = nandfs_setattr,
- .vop_strategy = nandfs_strategy,
- .vop_symlink = nandfs_symlink,
- .vop_lock1 = nandfs_vnlock1,
- .vop_unlock = nandfs_vnunlock,
-};
-
-struct vop_vector nandfs_system_vnodeops = {
- .vop_default = &default_vnodeops,
- .vop_close = nandfs_close,
- .vop_inactive = nandfs_inactive,
- .vop_reclaim = nandfs_reclaim,
- .vop_strategy = nandfs_strategy,
- .vop_fsync = nandfs_fsync,
- .vop_bmap = nandfs_bmap,
- .vop_access = VOP_PANIC,
- .vop_advlock = VOP_PANIC,
- .vop_create = VOP_PANIC,
- .vop_getattr = VOP_PANIC,
- .vop_cachedlookup = VOP_PANIC,
- .vop_ioctl = VOP_PANIC,
- .vop_link = VOP_PANIC,
- .vop_lookup = VOP_PANIC,
- .vop_mkdir = VOP_PANIC,
- .vop_mknod = VOP_PANIC,
- .vop_open = VOP_PANIC,
- .vop_pathconf = VOP_PANIC,
- .vop_print = VOP_PANIC,
- .vop_read = VOP_PANIC,
- .vop_readdir = VOP_PANIC,
- .vop_readlink = VOP_PANIC,
- .vop_remove = VOP_PANIC,
- .vop_rename = VOP_PANIC,
- .vop_rmdir = VOP_PANIC,
- .vop_whiteout = VOP_PANIC,
- .vop_write = VOP_PANIC,
- .vop_setattr = VOP_PANIC,
- .vop_symlink = VOP_PANIC,
-};
-
-static int
-nandfsfifo_close(struct vop_close_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nandfs_node *node = VTON(vp);
-
- DPRINTF(VNCALL, ("%s: vp %p node %p\n", __func__, vp, node));
-
- mtx_lock(&vp->v_interlock);
- if (vp->v_usecount > 1)
- nandfs_itimes_locked(vp);
- mtx_unlock(&vp->v_interlock);
-
- return (fifo_specops.vop_close(ap));
-}
-
-struct vop_vector nandfs_fifoops = {
- .vop_default = &fifo_specops,
- .vop_fsync = VOP_PANIC,
- .vop_access = nandfs_access,
- .vop_close = nandfsfifo_close,
- .vop_getattr = nandfs_getattr,
- .vop_inactive = nandfs_inactive,
- .vop_pathconf = nandfs_pathconf,
- .vop_print = nandfs_print,
- .vop_read = VOP_PANIC,
- .vop_reclaim = nandfs_reclaim,
- .vop_setattr = nandfs_setattr,
- .vop_write = VOP_PANIC,
- .vop_lock1 = nandfs_vnlock1,
- .vop_unlock = nandfs_vnunlock,
-};
-
-int
-nandfs_vinit(struct vnode *vp, uint64_t ino)
-{
- struct nandfs_node *node;
-
- ASSERT_VOP_LOCKED(vp, __func__);
-
- node = VTON(vp);
-
- /* Check if we're fetching the root */
- if (ino == NANDFS_ROOT_INO)
- vp->v_vflag |= VV_ROOT;
-
- if (ino != NANDFS_GC_INO)
- vp->v_type = IFTOVT(node->nn_inode.i_mode);
- else
- vp->v_type = VREG;
-
- if (vp->v_type == VFIFO)
- vp->v_op = &nandfs_fifoops;
-
- return (0);
-}
diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c
index 4edba5c761e7..fa6a14024213 100644
--- a/sys/fs/smbfs/smbfs_io.c
+++ b/sys/fs/smbfs/smbfs_io.c
@@ -375,9 +375,6 @@ smbfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td
*/
if (error == EINTR
|| (!error && (bp->b_flags & B_NEEDCOMMIT))) {
- int s;
-
- s = splbio();
bp->b_flags &= ~(B_INVAL|B_NOCACHE);
if ((bp->b_flags & B_ASYNC) == 0)
bp->b_flags |= B_EINTR;
@@ -387,7 +384,6 @@ smbfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td
}
if ((bp->b_flags & B_ASYNC) == 0)
bp->b_flags |= B_EINTR;
- splx(s);
} else {
if (error) {
bp->b_ioflags |= BIO_ERROR;
diff --git a/sys/geom/geom_flashmap.c b/sys/geom/geom_flashmap.c
index ac7344a34bb6..71007a4f7936 100644
--- a/sys/geom/geom_flashmap.c
+++ b/sys/geom/geom_flashmap.c
@@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
#include <geom/geom_flashmap.h>
#include <geom/geom_slice.h>
-#include <dev/nand/nand_dev.h>
-
struct g_flashmap_slice {
off_t sl_start;
off_t sl_end;
@@ -65,7 +63,6 @@ static struct {
{ "MMC::device", NULL }
};
-static g_ioctl_t g_flashmap_ioctl;
static g_taste_t g_flashmap_taste;
static int g_flashmap_load(device_t dev, struct g_provider *pp,
@@ -127,26 +124,6 @@ g_flashmap_modify(struct g_flashmap *gfp, struct g_geom *gp,
return (0);
}
-static int
-g_flashmap_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag,
- struct thread *td)
-{
- struct g_consumer *cp;
- struct g_geom *gp;
-
- if (cmd != NAND_IO_GET_CHIP_PARAM)
- return (ENOIOCTL);
-
- cp = LIST_FIRST(&pp->geom->consumer);
- if (cp == NULL)
- return (ENOIOCTL);
- gp = cp->provider->geom;
- if (gp->ioctl == NULL)
- return (ENOIOCTL);
-
- return (gp->ioctl(cp->provider, cmd, data, fflag, td));
-}
-
static struct g_geom *
g_flashmap_taste(struct g_class *mp, struct g_provider *pp, int flags)
{
@@ -245,7 +222,6 @@ static struct g_class g_flashmap_class = {
.name = FLASHMAP_CLASS_NAME,
.version = G_VERSION,
.taste = g_flashmap_taste,
- .ioctl = g_flashmap_ioctl,
};
DECLARE_GEOM_CLASS(g_flashmap_class, g_flashmap);
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index dab73ee51da6..ddeabf5952c8 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -292,7 +292,6 @@ device wpi # Intel 3945ABG wireless NICs.
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device padlock_rng # VIA Padlock RNG
device rdrand_rng # Intel Bull Mountain RNG
device ether # Ethernet support
diff --git a/sys/i386/conf/MINIMAL b/sys/i386/conf/MINIMAL
index 0b0bd23f40b4..0f1d268d013e 100644
--- a/sys/i386/conf/MINIMAL
+++ b/sys/i386/conf/MINIMAL
@@ -10,7 +10,7 @@
# some features (ACL, GJOURNAL) that GENERIC includes.
# o acpi as a module has been reported flakey and not well tested, so
# is included in the kernel.
-# o random is included due to uncertaty...
+# o (non-loaded) random is included due to uncertainty...
# o Many networking things are included
#
# For now, please run changes to these list past imp@freebsd.org
@@ -132,7 +132,6 @@ device agp # support several AGP chipsets
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device padlock_rng # VIA Padlock RNG
device rdrand_rng # Intel Bull Mountain RNG
device ether # Ethernet support
diff --git a/sys/kern/Make.tags.inc b/sys/kern/Make.tags.inc
index 50aed68dbf40..cdefa98a32f6 100644
--- a/sys/kern/Make.tags.inc
+++ b/sys/kern/Make.tags.inc
@@ -28,7 +28,6 @@ COMM= ${SYS}/sys/vnode.h \
${SYS}/fs/fifofs/*.[ch] \
${SYS}/fs/fuse/*.[ch] \
${SYS}/fs/msdosfs/*.[ch] \
- ${SYS}/fs/nandfs/*.[ch] \
${SYS}/fs/nfs/*.[ch] \
${SYS}/fs/nfsclient/*.[ch] \
${SYS}/fs/nfsserver/*.[ch] \
@@ -82,7 +81,6 @@ COMMDIR2= ${SYS}/dev/alc \
${SYS}/fs/fifofs \
${SYS}/fs/fuse \
${SYS}/fs/msdosfs \
- ${SYS}/fs/nandfs \
${SYS}/fs/nfs \
${SYS}/fs/nfsclient \
${SYS}/fs/nfsserver \
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 4d09eea37d56..4bc1a1546820 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -780,7 +780,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
}
if (arg >= 0) {
bsize = fp->f_vnode->v_mount->mnt_stat.f_iosize;
- fp->f_seqcount = (arg + bsize - 1) / bsize;
+ arg = MIN(arg, INT_MAX - bsize + 1);
+ fp->f_seqcount = MIN(IO_SEQMAX,
+ (arg + bsize - 1) / bsize);
atomic_set_int(&fp->f_flag, FRDAHEAD);
} else {
atomic_clear_int(&fp->f_flag, FRDAHEAD);
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index a92f6488c39f..54cdff148247 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include "opt_config.h"
#include <sys/param.h>
+#include <sys/boot.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/limits.h>
@@ -136,7 +137,7 @@ SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD|CTLFLAG_CAPRD,
SYSCTL_NULL_INT_PTR, 0, "Whether saved set-group/user ID is available");
#endif
-char kernelname[MAXPATHLEN] = "/boot/kernel/kernel"; /* XXX bloat */
+char kernelname[MAXPATHLEN] = PATH_KERNEL; /* XXX bloat */
SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, CTLFLAG_RW | CTLFLAG_MPSAFE,
kernelname, sizeof kernelname, "Name of kernel file booted");
diff --git a/sys/kern/kern_rangelock.c b/sys/kern/kern_rangelock.c
index 35bd6e864d37..b434ac4b4c1c 100644
--- a/sys/kern/kern_rangelock.c
+++ b/sys/kern/kern_rangelock.c
@@ -141,15 +141,33 @@ out:
static void
rangelock_unlock_locked(struct rangelock *lock, struct rl_q_entry *entry,
- struct mtx *ilk)
+ struct mtx *ilk, bool do_calc_block)
{
MPASS(lock != NULL && entry != NULL && ilk != NULL);
mtx_assert(ilk, MA_OWNED);
- KASSERT(entry != lock->rl_currdep, ("stuck currdep"));
+
+ if (!do_calc_block) {
+ /*
+ * This is the case where rangelock_enqueue() has been called
+ * with trylock == true and just inserted this entry in the
+ * queue.
+ * If rl_currdep is this entry, rl_currdep needs to
+ * be set to the next entry in the rl_waiters list.
+ * However, since this entry is the last entry in the
+ * list, the next entry is NULL.
+ */
+ if (lock->rl_currdep == entry) {
+ KASSERT(TAILQ_NEXT(lock->rl_currdep, rl_q_link) == NULL,
+ ("rangelock_enqueue: next entry not NULL"));
+ lock->rl_currdep = NULL;
+ }
+ } else
+ KASSERT(entry != lock->rl_currdep, ("stuck currdep"));
TAILQ_REMOVE(&lock->rl_waiters, entry, rl_q_link);
- rangelock_calc_block(lock);
+ if (do_calc_block)
+ rangelock_calc_block(lock);
mtx_unlock(ilk);
if (curthread->td_rlqe == NULL)
curthread->td_rlqe = entry;
@@ -164,7 +182,7 @@ rangelock_unlock(struct rangelock *lock, void *cookie, struct mtx *ilk)
MPASS(lock != NULL && cookie != NULL && ilk != NULL);
mtx_lock(ilk);
- rangelock_unlock_locked(lock, cookie, ilk);
+ rangelock_unlock_locked(lock, cookie, ilk, true);
}
/*
@@ -185,7 +203,7 @@ rangelock_unlock_range(struct rangelock *lock, void *cookie, off_t start,
mtx_lock(ilk);
if (entry->rl_q_end == end) {
- rangelock_unlock_locked(lock, cookie, ilk);
+ rangelock_unlock_locked(lock, cookie, ilk, true);
return (NULL);
}
entry->rl_q_end = end;
@@ -196,11 +214,11 @@ rangelock_unlock_range(struct rangelock *lock, void *cookie, off_t start,
/*
* Add the lock request to the queue of the pending requests for
- * rangelock. Sleep until the request can be granted.
+ * rangelock. Sleep until the request can be granted unless trylock == true.
*/
static void *
rangelock_enqueue(struct rangelock *lock, off_t start, off_t end, int mode,
- struct mtx *ilk)
+ struct mtx *ilk, bool trylock)
{
struct rl_q_entry *entry;
struct thread *td;
@@ -226,11 +244,28 @@ rangelock_enqueue(struct rangelock *lock, off_t start, off_t end, int mode,
*/
TAILQ_INSERT_TAIL(&lock->rl_waiters, entry, rl_q_link);
+ /*
+ * If rl_currdep == NULL, there is no entry waiting for a conflicting
+ * range to be resolved, so set rl_currdep to this entry. If there is
+ * no conflicting entry for this entry, rl_currdep will be set back to
+ * NULL by rangelock_calc_block().
+ */
if (lock->rl_currdep == NULL)
lock->rl_currdep = entry;
rangelock_calc_block(lock);
- while (!(entry->rl_q_flags & RL_LOCK_GRANTED))
+ while (!(entry->rl_q_flags & RL_LOCK_GRANTED)) {
+ if (trylock) {
+ /*
+ * For this case, the range is not actually locked
+ * yet, but removal from the list requires the same
+ * steps, except for not doing a rangelock_calc_block()
+ * call, since rangelock_calc_block() was called above.
+ */
+ rangelock_unlock_locked(lock, entry, ilk, false);
+ return (NULL);
+ }
msleep(entry, ilk, 0, "range", 0);
+ }
mtx_unlock(ilk);
return (entry);
}
@@ -239,12 +274,28 @@ void *
rangelock_rlock(struct rangelock *lock, off_t start, off_t end, struct mtx *ilk)
{
- return (rangelock_enqueue(lock, start, end, RL_LOCK_READ, ilk));
+ return (rangelock_enqueue(lock, start, end, RL_LOCK_READ, ilk, false));
+}
+
+void *
+rangelock_tryrlock(struct rangelock *lock, off_t start, off_t end,
+ struct mtx *ilk)
+{
+
+ return (rangelock_enqueue(lock, start, end, RL_LOCK_READ, ilk, true));
}
void *
rangelock_wlock(struct rangelock *lock, off_t start, off_t end, struct mtx *ilk)
{
- return (rangelock_enqueue(lock, start, end, RL_LOCK_WRITE, ilk));
+ return (rangelock_enqueue(lock, start, end, RL_LOCK_WRITE, ilk, false));
+}
+
+void *
+rangelock_trywlock(struct rangelock *lock, off_t start, off_t end,
+ struct mtx *ilk)
+{
+
+ return (rangelock_enqueue(lock, start, end, RL_LOCK_WRITE, ilk, true));
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 044865a489a6..8a1ee1e53cbe 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -3415,10 +3415,16 @@ corefile_open_last(struct thread *td, char *name, int indexpos,
}
if (oldvp != NULL) {
- if (nextvp == NULL)
- nextvp = oldvp;
- else
+ if (nextvp == NULL) {
+ if ((td->td_proc->p_flag & P_SUGID) != 0) {
+ error = EFAULT;
+ vnode_close_locked(td, oldvp);
+ } else {
+ nextvp = oldvp;
+ }
+ } else {
vnode_close_locked(td, oldvp);
+ }
}
if (error != 0) {
if (nextvp != NULL)
@@ -3538,6 +3544,8 @@ corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td,
oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE |
(capmode_coredump ? VN_OPEN_NOCAPCHECK : 0);
flags = O_CREAT | FWRITE | O_NOFOLLOW;
+ if ((td->td_proc->p_flag & P_SUGID) != 0)
+ flags |= O_EXCL;
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred,
@@ -3614,10 +3622,11 @@ coredump(struct thread *td)
/*
* Don't dump to non-regular files or files with links.
- * Do not dump into system files.
+ * Do not dump into system files. Effective user must own the corefile.
*/
if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred) != 0 ||
- vattr.va_nlink != 1 || (vp->v_vflag & VV_SYSTEM) != 0) {
+ vattr.va_nlink != 1 || (vp->v_vflag & VV_SYSTEM) != 0 ||
+ vattr.va_uid != cred->cr_uid) {
VOP_UNLOCK(vp, 0);
error = EFAULT;
goto out;
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index eafb902601d7..3c04e8607a71 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -1414,7 +1414,7 @@ pipe_poll(struct file *fp, int events, struct ucred *active_cred,
levents = events &
(POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | POLLRDBAND);
if (rpipe->pipe_state & PIPE_NAMED && fp->f_flag & FREAD && levents &&
- fp->f_seqcount == rpipe->pipe_wgen)
+ fp->f_pipegen == rpipe->pipe_wgen)
events |= POLLINIGNEOF;
if ((events & POLLINIGNEOF) == 0) {
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index e38f8c06bbb3..05be168e8a84 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1044,7 +1044,7 @@ sofree(struct socket *so)
*
* We used to do a lot of socket buffer and socket locking here, as
* well as invoke sorflush() and perform wakeups. The direct call to
- * dom_dispose() and sbrelease_internal() are an inlining of what was
+ * dom_dispose() and sbdestroy() are an inlining of what was
* necessary from sorflush().
*
* Notice that the socket buffer and kqueue state are torn down
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 7871e536b56e..aba141c26249 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -499,9 +499,8 @@ sequential_heuristic(struct uio *uio, struct file *fp)
* closely related to the best I/O size for real disks than
* to any block size used by software.
*/
- fp->f_seqcount += howmany(uio->uio_resid, 16384);
- if (fp->f_seqcount > IO_SEQMAX)
- fp->f_seqcount = IO_SEQMAX;
+ fp->f_seqcount += lmin(IO_SEQMAX,
+ howmany(uio->uio_resid, 16384));
return (fp->f_seqcount << IO_SEQSHIFT);
}
diff --git a/sys/mips/conf/BCM b/sys/mips/conf/BCM
index 5c2753279a23..27d93766c354 100644
--- a/sys/mips/conf/BCM
+++ b/sys/mips/conf/BCM
@@ -82,7 +82,6 @@ device uart
#Base
device loop
device ether
-device random
device md
#Performance
diff --git a/sys/mips/conf/BERI_DE4_BASE b/sys/mips/conf/BERI_DE4_BASE
index 0985d60e60d1..7719009ccf5a 100644
--- a/sys/mips/conf/BERI_DE4_BASE
+++ b/sys/mips/conf/BERI_DE4_BASE
@@ -44,6 +44,7 @@ options DEVICE_POLLING
#
# DMA support
#
+options ALTERA_MSGDMA_DESC_PF_STD
device xdma
device altera_softdma
device altera_msgdma
diff --git a/sys/mips/conf/DIR-825B1 b/sys/mips/conf/DIR-825B1
index 80a1d17c0ac0..8b43cf1b22ca 100644
--- a/sys/mips/conf/DIR-825B1
+++ b/sys/mips/conf/DIR-825B1
@@ -21,7 +21,6 @@ hints "DIR-825B1.hints"
# Since the kernel image must fit inside 1024KiB, we have to build almost
# everything as modules.
-# nodevice random
nodevice gpio
nodevice gpioled
nodevice gif
diff --git a/sys/mips/conf/ERL b/sys/mips/conf/ERL
index f12f6228bd95..a0e79450c871 100644
--- a/sys/mips/conf/ERL
+++ b/sys/mips/conf/ERL
@@ -149,7 +149,6 @@ device wlan_amrr # AMRR transmit rate control algorithm
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/mips/conf/JZ4780 b/sys/mips/conf/JZ4780
index a3716cbe4873..459f908857a6 100644
--- a/sys/mips/conf/JZ4780
+++ b/sys/mips/conf/JZ4780
@@ -68,7 +68,6 @@ device miibus
device bpf
device md
device uart
-device random
device fdt_pinctrl
diff --git a/sys/mips/conf/OCTEON1 b/sys/mips/conf/OCTEON1
index 6c536f0d6ed4..256b66eff71f 100644
--- a/sys/mips/conf/OCTEON1
+++ b/sys/mips/conf/OCTEON1
@@ -184,7 +184,6 @@ device ral # Ralink Technology RT2500 wireless NICs.
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/mips/conf/PB92 b/sys/mips/conf/PB92
index 4d3e890d0f96..64a0e6db120b 100644
--- a/sys/mips/conf/PB92
+++ b/sys/mips/conf/PB92
@@ -133,5 +133,4 @@ device loop
device ether
#device md
#device bpf
-device random
#device if_bridge
diff --git a/sys/mips/conf/PICOSTATION_M2HP b/sys/mips/conf/PICOSTATION_M2HP
index e331f7764d2d..38e3d69c0509 100644
--- a/sys/mips/conf/PICOSTATION_M2HP
+++ b/sys/mips/conf/PICOSTATION_M2HP
@@ -68,6 +68,3 @@ device arswitch
# Enable GPIO
device gpio
device gpioled
-
-# RNG
-device random
diff --git a/sys/mips/conf/WZR-300HP b/sys/mips/conf/WZR-300HP
index 217e444f1b89..dd767888a1e9 100644
--- a/sys/mips/conf/WZR-300HP
+++ b/sys/mips/conf/WZR-300HP
@@ -49,4 +49,4 @@ device hwpmc
# load these via modules, shrink kernel
nodevice if_bridge
nodevice bridgestp
-nodevice random
+options RANDOM_LOADABLE
diff --git a/sys/mips/conf/WZR-HPAG300H b/sys/mips/conf/WZR-HPAG300H
index b46f9de3eb8d..3337af682f2c 100644
--- a/sys/mips/conf/WZR-HPAG300H
+++ b/sys/mips/conf/WZR-HPAG300H
@@ -49,4 +49,4 @@ device hwpmc
# load these via modules, shrink kernel
nodevice if_bridge
nodevice bridgestp
-nodevice random
+options RANDOM_LOADABLE
diff --git a/sys/mips/conf/X1000 b/sys/mips/conf/X1000
index 907ea814de8f..8f10337218a5 100644
--- a/sys/mips/conf/X1000
+++ b/sys/mips/conf/X1000
@@ -63,7 +63,6 @@ device miibus
device bpf
device md
device uart
-device random
device fdt_pinctrl
diff --git a/sys/mips/conf/std.AR5312 b/sys/mips/conf/std.AR5312
index a3b055bfb743..56a45cb4c869 100644
--- a/sys/mips/conf/std.AR5312
+++ b/sys/mips/conf/std.AR5312
@@ -72,7 +72,6 @@ device loop
device ether
device md
device bpf
-device random
options ARGE_DEBUG # Enable if_arge debugging for now
diff --git a/sys/mips/conf/std.AR5315 b/sys/mips/conf/std.AR5315
index c9f85f6c0813..74a888c32f85 100644
--- a/sys/mips/conf/std.AR5315
+++ b/sys/mips/conf/std.AR5315
@@ -72,7 +72,6 @@ device loop
device ether
device md
device bpf
-device random
options ARGE_DEBUG # Enable if_arge debugging for now
diff --git a/sys/mips/conf/std.AR_MIPS_BASE b/sys/mips/conf/std.AR_MIPS_BASE
index 37544a9b6660..ab0947a391ea 100644
--- a/sys/mips/conf/std.AR_MIPS_BASE
+++ b/sys/mips/conf/std.AR_MIPS_BASE
@@ -25,9 +25,6 @@ makeoptions MODULES_OVERRIDE+="gpio ar71xx if_gif if_vlan if_gre if_tuntap"
makeoptions MODULES_OVERRIDE+="if_bridge bridgestp usb"
makeoptions MODULES_OVERRIDE+="alq"
-# Random - required during early boot!
-device random
-
# net80211
options IEEE80211_DEBUG
options IEEE80211_SUPPORT_MESH
diff --git a/sys/mips/conf/std.BERI b/sys/mips/conf/std.BERI
index 903af51875af..07f907b760df 100644
--- a/sys/mips/conf/std.BERI
+++ b/sys/mips/conf/std.BERI
@@ -61,5 +61,4 @@ device ether
device geom_map
device loop
device md
-device random
device snp
diff --git a/sys/mips/conf/std.MALTA b/sys/mips/conf/std.MALTA
index 4c1965650fba..26940db1b92f 100644
--- a/sys/mips/conf/std.MALTA
+++ b/sys/mips/conf/std.MALTA
@@ -55,4 +55,3 @@ device miibus
device bpf
device md
device uart
-device random
diff --git a/sys/mips/conf/std.XLP b/sys/mips/conf/std.XLP
index 5330c19b3657..cbc13746fd06 100644
--- a/sys/mips/conf/std.XLP
+++ b/sys/mips/conf/std.XLP
@@ -66,7 +66,6 @@ makeoptions FDT_DTS_FILE=xlp-basic.dts
# Pseudo
device loop
-device random
device md
device bpf
diff --git a/sys/mips/mediatek/std.mediatek b/sys/mips/mediatek/std.mediatek
index 7806da8f099a..d8c351aab36f 100644
--- a/sys/mips/mediatek/std.mediatek
+++ b/sys/mips/mediatek/std.mediatek
@@ -74,9 +74,6 @@ device fdt_pinctrl
# UART support
device uart
-# random support
-device random
-
# loop device support
device loop
diff --git a/sys/mips/mediatek/std.rt2880 b/sys/mips/mediatek/std.rt2880
index 8040585e9cb9..397a0bc322da 100644
--- a/sys/mips/mediatek/std.rt2880
+++ b/sys/mips/mediatek/std.rt2880
@@ -73,9 +73,6 @@ device fdt_pinctrl
# UART support
device uart
-# random support
-device random
-
# loop device support
device loop
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index a9a5c5ed98ef..876a13f19ea9 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -255,8 +255,6 @@ SUBDIR= \
${_mwlfw} \
mxge \
my \
- ${_nandfs} \
- ${_nandsim} \
${_nctgpio} \
${_ndis} \
${_netgraph} \
@@ -489,11 +487,6 @@ _mlx5ib= mlx5ib
.endif
.endif
-.if ${MK_NAND} != "no" || defined(ALL_MODULES)
-_nandfs= nandfs
-_nandsim= nandsim
-.endif
-
.if ${MK_NETGRAPH} != "no" || defined(ALL_MODULES)
_netgraph= netgraph
.endif
diff --git a/sys/modules/nand/Makefile b/sys/modules/nand/Makefile
deleted file mode 100644
index c9d9962e897f..000000000000
--- a/sys/modules/nand/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${SRCTOP}/sys/dev/nand
-
-KMOD = nand
-SRCS= nand.c nand_bbt.c nand_cdev.c nand_generic.c nand_geom.c \
- nand_id.c nandbus.c nandbus_if.c nand_if.c nfc_if.c \
- nand_if.h device_if.h bus_if.h nfc_if.h nandbus_if.h
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/nandfs/Makefile b/sys/modules/nandfs/Makefile
deleted file mode 100644
index f13858c57c7b..000000000000
--- a/sys/modules/nandfs/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${SRCTOP}/sys/fs/nandfs
-
-KMOD= nandfs
-SRCS= vnode_if.h opt_ddb.h \
- bmap.c nandfs_bmap.c nandfs_dir.c nandfs_subr.c nandfs_vfsops.c \
- nandfs_vnops.c nandfs_alloc.c nandfs_cpfile.c nandfs_dat.c \
- nandfs_ifile.c nandfs_segment.c nandfs_sufile.c nandfs_buffer.c \
- nandfs_cleaner.c
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/nandsim/Makefile b/sys/modules/nandsim/Makefile
deleted file mode 100644
index 4f0aeca9eb4b..000000000000
--- a/sys/modules/nandsim/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${SRCTOP}/sys/dev/nand
-
-KMOD= nandsim
-SRCS= nandsim.c nandsim_chip.c nandsim_swap.c nandsim_ctrl.c nandsim_log.c\
- bus_if.h device_if.h vnode_if.h nfc_if.h nand_if.h
-
-.include <bsd.kmod.mk>
diff --git a/sys/net/if_vxlan.c b/sys/net/if_vxlan.c
index 81065bcec431..5e35baae2dbc 100644
--- a/sys/net/if_vxlan.c
+++ b/sys/net/if_vxlan.c
@@ -1134,7 +1134,7 @@ vxlan_socket_mc_join_group(struct vxlan_socket *vso,
* If we really need to, we can of course look in the INP's
* membership list:
* sotoinpcb(vso->vxlso_sock)->inp_moptions->
- * imo_membership[]->inm_ifp
+ * imo_head[]->imf_inm->inm_ifp
* similarly to imo_match_group().
*/
source->in4.sin_addr = local->in4.sin_addr;
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index d932e9373be0..e33c2bec61e2 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -3580,10 +3580,10 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx)
iflib_txq_t txq = r->cookie;
if_ctx_t ctx = txq->ift_ctx;
if_t ifp = ctx->ifc_ifp;
- struct mbuf **mp, *m;
- int i, count, consumed, pkt_sent, bytes_sent, mcast_sent, avail;
- int reclaimed, err, in_use_prev, desc_used;
- bool do_prefetch, ring, rang;
+ struct mbuf *m, **mp;
+ int avail, bytes_sent, consumed, count, err, i, in_use_prev;
+ int mcast_sent, pkt_sent, reclaimed, txq_avail;
+ bool do_prefetch, rang, ring;
if (__predict_false(!(if_getdrvflags(ifp) & IFF_DRV_RUNNING) ||
!LINK_ACTIVE(ctx))) {
@@ -3621,16 +3621,15 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx)
avail, ctx->ifc_flags, TXQ_AVAIL(txq));
#endif
do_prefetch = (ctx->ifc_flags & IFC_PREFETCH);
- avail = TXQ_AVAIL(txq);
+ txq_avail = TXQ_AVAIL(txq);
err = 0;
- for (desc_used = i = 0; i < count && avail > MAX_TX_DESC(ctx) + 2; i++) {
+ for (i = 0; i < count && txq_avail > MAX_TX_DESC(ctx) + 2; i++) {
int rem = do_prefetch ? count - i : 0;
mp = _ring_peek_one(r, cidx, i, rem);
MPASS(mp != NULL && *mp != NULL);
if (__predict_false(*mp == (struct mbuf *)txq)) {
consumed++;
- reclaimed++;
continue;
}
in_use_prev = txq->ift_in_use;
@@ -3649,10 +3648,9 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx)
DBG_COUNTER_INC(tx_sent);
bytes_sent += m->m_pkthdr.len;
mcast_sent += !!(m->m_flags & M_MCAST);
- avail = TXQ_AVAIL(txq);
+ txq_avail = TXQ_AVAIL(txq);
txq->ift_db_pending += (txq->ift_in_use - in_use_prev);
- desc_used += (txq->ift_in_use - in_use_prev);
ETHER_BPF_MTAP(ifp, m);
if (__predict_false(!(ifp->if_drv_flags & IFF_DRV_RUNNING)))
break;
@@ -6155,9 +6153,6 @@ iflib_tx_credits_update(if_ctx_t ctx, iflib_txq_t txq)
int credits_pre = txq->ift_cidx_processed;
#endif
- if (ctx->isc_txd_credits_update == NULL)
- return (0);
-
bus_dmamap_sync(txq->ift_ifdi->idi_tag, txq->ift_ifdi->idi_map,
BUS_DMASYNC_POSTREAD);
if ((credits = ctx->isc_txd_credits_update(ctx->ifc_softc, txq->ift_id, true)) == 0)
diff --git a/sys/net/vnet.h b/sys/net/vnet.h
index b4168750e026..a8c9887ed506 100644
--- a/sys/net/vnet.h
+++ b/sys/net/vnet.h
@@ -273,7 +273,8 @@ extern struct sx vnet_sxlock;
/* struct _hack is to stop this from being used with static data */
#define VNET_DEFINE(t, n) \
struct _hack; t VNET_NAME(n) __section(VNET_SETNAME) __used
-#if defined(KLD_MODULE) && (defined(__aarch64__) || defined(__riscv))
+#if defined(KLD_MODULE) && (defined(__aarch64__) || defined(__riscv) \
+ || defined(__powerpc64__))
/*
* As with DPCPU_DEFINE_STATIC we are unable to mark this data as static
* in modules on some architectures.
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index 148d51eff36a..cfa168f99be6 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -505,13 +505,9 @@ __END_DECLS
#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
/*
- * The imo_membership vector for each socket is now dynamically allocated at
- * run-time, bounded by USHRT_MAX, and is reallocated when needed, sized
- * according to a power-of-two increment.
+ * Limit for IPv4 multicast memberships
*/
-#define IP_MIN_MEMBERSHIPS 31
#define IP_MAX_MEMBERSHIPS 4095
-#define IP_MAX_SOURCE_FILTER 1024 /* XXX to be unused */
/*
* Default resource limits for IPv4 multicast source filtering.
diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c
index 2980c1a463ca..ac5c6a03ab54 100644
--- a/sys/netinet/in_mcast.c
+++ b/sys/netinet/in_mcast.c
@@ -94,7 +94,9 @@ static MALLOC_DEFINE(M_IPMSOURCE, "ip_msource",
/*
* Locking:
- * - Lock order is: Giant, INP_WLOCK, IN_MULTI_LIST_LOCK, IGMP_LOCK, IF_ADDR_LOCK.
+ *
+ * - Lock order is: Giant, IN_MULTI_LOCK, INP_WLOCK,
+ * IN_MULTI_LIST_LOCK, IGMP_LOCK, IF_ADDR_LOCK.
* - The IF_ADDR_LOCK is implicitly taken by inm_lookup() earlier, however
* it can be taken by code in net/if.c also.
* - ip_moptions and in_mfilter are covered by the INP_WLOCK.
@@ -144,12 +146,11 @@ static int imf_prune(struct in_mfilter *, const struct sockaddr_in *);
static void imf_purge(struct in_mfilter *);
static void imf_rollback(struct in_mfilter *);
static void imf_reap(struct in_mfilter *);
-static int imo_grow(struct ip_moptions *);
-static size_t imo_match_group(const struct ip_moptions *,
+static struct in_mfilter *
+ imo_match_group(const struct ip_moptions *,
const struct ifnet *, const struct sockaddr *);
static struct in_msource *
- imo_match_source(const struct ip_moptions *, const size_t,
- const struct sockaddr *);
+ imo_match_source(struct in_mfilter *, const struct sockaddr *);
static void ims_merge(struct ip_msource *ims,
const struct in_msource *lims, const int rollback);
static int in_getmulti(struct ifnet *, const struct in_addr *,
@@ -333,6 +334,26 @@ imf_init(struct in_mfilter *imf, const int st0, const int st1)
imf->imf_st[1] = st1;
}
+struct in_mfilter *
+ip_mfilter_alloc(const int mflags, const int st0, const int st1)
+{
+ struct in_mfilter *imf;
+
+ imf = malloc(sizeof(*imf), M_INMFILTER, mflags);
+ if (imf != NULL)
+ imf_init(imf, st0, st1);
+
+ return (imf);
+}
+
+void
+ip_mfilter_free(struct in_mfilter *imf)
+{
+
+ imf_purge(imf);
+ free(imf, M_INMFILTER);
+}
+
/*
* Function for looking up an in_multi record for an IPv4 multicast address
* on a given interface. ifp must be valid. If no record found, return NULL.
@@ -379,89 +400,30 @@ inm_lookup(struct ifnet *ifp, const struct in_addr ina)
}
/*
- * Resize the ip_moptions vector to the next power-of-two minus 1.
- * May be called with locks held; do not sleep.
- */
-static int
-imo_grow(struct ip_moptions *imo)
-{
- struct in_multi **nmships;
- struct in_multi **omships;
- struct in_mfilter *nmfilters;
- struct in_mfilter *omfilters;
- size_t idx;
- size_t newmax;
- size_t oldmax;
-
- nmships = NULL;
- nmfilters = NULL;
- omships = imo->imo_membership;
- omfilters = imo->imo_mfilters;
- oldmax = imo->imo_max_memberships;
- newmax = ((oldmax + 1) * 2) - 1;
-
- if (newmax <= IP_MAX_MEMBERSHIPS) {
- nmships = (struct in_multi **)realloc(omships,
- sizeof(struct in_multi *) * newmax, M_IPMOPTS, M_NOWAIT);
- nmfilters = (struct in_mfilter *)realloc(omfilters,
- sizeof(struct in_mfilter) * newmax, M_INMFILTER, M_NOWAIT);
- if (nmships != NULL && nmfilters != NULL) {
- /* Initialize newly allocated source filter heads. */
- for (idx = oldmax; idx < newmax; idx++) {
- imf_init(&nmfilters[idx], MCAST_UNDEFINED,
- MCAST_EXCLUDE);
- }
- imo->imo_max_memberships = newmax;
- imo->imo_membership = nmships;
- imo->imo_mfilters = nmfilters;
- }
- }
-
- if (nmships == NULL || nmfilters == NULL) {
- if (nmships != NULL)
- free(nmships, M_IPMOPTS);
- if (nmfilters != NULL)
- free(nmfilters, M_INMFILTER);
- return (ETOOMANYREFS);
- }
-
- return (0);
-}
-
-/*
* Find an IPv4 multicast group entry for this ip_moptions instance
* which matches the specified group, and optionally an interface.
* Return its index into the array, or -1 if not found.
*/
-static size_t
+static struct in_mfilter *
imo_match_group(const struct ip_moptions *imo, const struct ifnet *ifp,
const struct sockaddr *group)
{
const struct sockaddr_in *gsin;
- struct in_multi **pinm;
- int idx;
- int nmships;
+ struct in_mfilter *imf;
+ struct in_multi *inm;
gsin = (const struct sockaddr_in *)group;
- /* The imo_membership array may be lazy allocated. */
- if (imo->imo_membership == NULL || imo->imo_num_memberships == 0)
- return (-1);
-
- nmships = imo->imo_num_memberships;
- pinm = &imo->imo_membership[0];
- for (idx = 0; idx < nmships; idx++, pinm++) {
- if (*pinm == NULL)
+ IP_MFILTER_FOREACH(imf, &imo->imo_head) {
+ inm = imf->imf_inm;
+ if (inm == NULL)
continue;
- if ((ifp == NULL || ((*pinm)->inm_ifp == ifp)) &&
- in_hosteq((*pinm)->inm_addr, gsin->sin_addr)) {
+ if ((ifp == NULL || (inm->inm_ifp == ifp)) &&
+ in_hosteq(inm->inm_addr, gsin->sin_addr)) {
break;
}
}
- if (idx >= nmships)
- idx = -1;
-
- return (idx);
+ return (imf);
}
/*
@@ -472,22 +434,13 @@ imo_match_group(const struct ip_moptions *imo, const struct ifnet *ifp,
* it exists, which may not be the desired behaviour.
*/
static struct in_msource *
-imo_match_source(const struct ip_moptions *imo, const size_t gidx,
- const struct sockaddr *src)
+imo_match_source(struct in_mfilter *imf, const struct sockaddr *src)
{
struct ip_msource find;
- struct in_mfilter *imf;
struct ip_msource *ims;
const sockunion_t *psa;
KASSERT(src->sa_family == AF_INET, ("%s: !AF_INET", __func__));
- KASSERT(gidx != -1 && gidx < imo->imo_num_memberships,
- ("%s: invalid index %d\n", __func__, (int)gidx));
-
- /* The imo_mfilters array may be lazy allocated. */
- if (imo->imo_mfilters == NULL)
- return (NULL);
- imf = &imo->imo_mfilters[gidx];
/* Source trees are keyed in host byte order. */
psa = (const sockunion_t *)src;
@@ -507,14 +460,14 @@ int
imo_multi_filter(const struct ip_moptions *imo, const struct ifnet *ifp,
const struct sockaddr *group, const struct sockaddr *src)
{
- size_t gidx;
+ struct in_mfilter *imf;
struct in_msource *ims;
int mode;
KASSERT(ifp != NULL, ("%s: null ifp", __func__));
- gidx = imo_match_group(imo, ifp, group);
- if (gidx == -1)
+ imf = imo_match_group(imo, ifp, group);
+ if (imf == NULL)
return (MCAST_NOTGMEMBER);
/*
@@ -526,8 +479,8 @@ imo_multi_filter(const struct ip_moptions *imo, const struct ifnet *ifp,
* NOTE: We are comparing group state here at IGMP t1 (now)
* with socket-layer t0 (since last downcall).
*/
- mode = imo->imo_mfilters[gidx].imf_st[1];
- ims = imo_match_source(imo, gidx, src);
+ mode = imf->imf_st[1];
+ ims = imo_match_source(imf, src);
if ((ims == NULL && mode == MCAST_INCLUDE) ||
(ims != NULL && ims->imsl_st[0] != mode))
@@ -1452,7 +1405,6 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
struct ip_moptions *imo;
struct in_msource *ims;
struct in_multi *inm;
- size_t idx;
uint16_t fmode;
int error, doblock;
@@ -1531,20 +1483,18 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
return (EINVAL);
+ IN_MULTI_LOCK();
+
/*
* Check if we are actually a member of this group.
*/
imo = inp_findmoptions(inp);
- idx = imo_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->imo_mfilters == NULL) {
+ imf = imo_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_inp_locked;
}
-
- KASSERT(imo->imo_mfilters != NULL,
- ("%s: imo_mfilters not allocated", __func__));
- imf = &imo->imo_mfilters[idx];
- inm = imo->imo_membership[idx];
+ inm = imf->imf_inm;
/*
* Attempting to use the delta-based API on an
@@ -1562,7 +1512,7 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
* Asked to unblock, but nothing to unblock.
* If adding a new block entry, allocate it.
*/
- ims = imo_match_source(imo, idx, &ssa->sa);
+ ims = imo_match_source(imf, &ssa->sa);
if ((ims != NULL && doblock) || (ims == NULL && !doblock)) {
CTR3(KTR_IGMPV3, "%s: source 0x%08x %spresent", __func__,
ntohl(ssa->sin.sin_addr.s_addr), doblock ? "" : "not ");
@@ -1593,14 +1543,13 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
/*
* Begin state merge transaction at IGMP layer.
*/
- IN_MULTI_LOCK();
CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
IN_MULTI_LIST_LOCK();
error = inm_merge(inm, imf);
if (error) {
CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__);
IN_MULTI_LIST_UNLOCK();
- goto out_in_multi_locked;
+ goto out_imf_rollback;
}
CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__);
@@ -1609,9 +1558,6 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
if (error)
CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__);
-out_in_multi_locked:
-
- IN_MULTI_UNLOCK();
out_imf_rollback:
if (error)
imf_rollback(imf);
@@ -1622,6 +1568,7 @@ out_imf_rollback:
out_inp_locked:
INP_WUNLOCK(inp);
+ IN_MULTI_UNLOCK();
return (error);
}
@@ -1636,9 +1583,6 @@ static struct ip_moptions *
inp_findmoptions(struct inpcb *inp)
{
struct ip_moptions *imo;
- struct in_multi **immp;
- struct in_mfilter *imfp;
- size_t idx;
INP_WLOCK(inp);
if (inp->inp_moptions != NULL)
@@ -1647,29 +1591,16 @@ inp_findmoptions(struct inpcb *inp)
INP_WUNLOCK(inp);
imo = malloc(sizeof(*imo), M_IPMOPTS, M_WAITOK);
- immp = malloc(sizeof(*immp) * IP_MIN_MEMBERSHIPS, M_IPMOPTS,
- M_WAITOK | M_ZERO);
- imfp = malloc(sizeof(struct in_mfilter) * IP_MIN_MEMBERSHIPS,
- M_INMFILTER, M_WAITOK);
imo->imo_multicast_ifp = NULL;
imo->imo_multicast_addr.s_addr = INADDR_ANY;
imo->imo_multicast_vif = -1;
imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
imo->imo_multicast_loop = in_mcast_loop;
- imo->imo_num_memberships = 0;
- imo->imo_max_memberships = IP_MIN_MEMBERSHIPS;
- imo->imo_membership = immp;
-
- /* Initialize per-group source filters. */
- for (idx = 0; idx < IP_MIN_MEMBERSHIPS; idx++)
- imf_init(&imfp[idx], MCAST_UNDEFINED, MCAST_EXCLUDE);
- imo->imo_mfilters = imfp;
+ STAILQ_INIT(&imo->imo_head);
INP_WLOCK(inp);
if (inp->inp_moptions != NULL) {
- free(imfp, M_INMFILTER);
- free(immp, M_IPMOPTS);
free(imo, M_IPMOPTS);
return (inp->inp_moptions);
}
@@ -1680,32 +1611,25 @@ inp_findmoptions(struct inpcb *inp)
static void
inp_gcmoptions(struct ip_moptions *imo)
{
- struct in_mfilter *imf;
+ struct in_mfilter *imf;
struct in_multi *inm;
struct ifnet *ifp;
- size_t idx, nmships;
-
- nmships = imo->imo_num_memberships;
- for (idx = 0; idx < nmships; ++idx) {
- imf = imo->imo_mfilters ? &imo->imo_mfilters[idx] : NULL;
- if (imf)
- imf_leave(imf);
- inm = imo->imo_membership[idx];
- ifp = inm->inm_ifp;
- if (ifp != NULL) {
- CURVNET_SET(ifp->if_vnet);
- (void)in_leavegroup(inm, imf);
- CURVNET_RESTORE();
- } else {
- (void)in_leavegroup(inm, imf);
+
+ while ((imf = ip_mfilter_first(&imo->imo_head)) != NULL) {
+ ip_mfilter_remove(&imo->imo_head, imf);
+
+ imf_leave(imf);
+ if ((inm = imf->imf_inm) != NULL) {
+ if ((ifp = inm->inm_ifp) != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ (void)in_leavegroup(inm, imf);
+ CURVNET_RESTORE();
+ } else {
+ (void)in_leavegroup(inm, imf);
+ }
}
- if (imf)
- imf_purge(imf);
+ ip_mfilter_free(imf);
}
-
- if (imo->imo_mfilters)
- free(imo->imo_mfilters, M_INMFILTER);
- free(imo->imo_membership, M_IPMOPTS);
free(imo, M_IPMOPTS);
}
@@ -1741,7 +1665,7 @@ inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
struct sockaddr_storage *ptss;
struct sockaddr_storage *tss;
int error;
- size_t idx, nsrcs, ncsrcs;
+ size_t nsrcs, ncsrcs;
INP_WLOCK_ASSERT(inp);
@@ -1768,12 +1692,11 @@ inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
* Lookup group on the socket.
*/
gsa = (sockunion_t *)&msfr.msfr_group;
- idx = imo_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->imo_mfilters == NULL) {
+ imf = imo_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
INP_WUNLOCK(inp);
return (EADDRNOTAVAIL);
}
- imf = &imo->imo_mfilters[idx];
/*
* Ignore memberships which are in limbo.
@@ -2033,14 +1956,11 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
struct ip_moptions *imo;
struct in_multi *inm;
struct in_msource *lims;
- size_t idx;
int error, is_new;
ifp = NULL;
- imf = NULL;
lims = NULL;
error = 0;
- is_new = 0;
memset(&gsr, 0, sizeof(struct group_source_req));
gsa = (sockunion_t *)&gsr.gsr_group;
@@ -2148,13 +2068,25 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0)
return (EADDRNOTAVAIL);
+ IN_MULTI_LOCK();
+
+ /*
+ * Find the membership in the membership list.
+ */
imo = inp_findmoptions(inp);
- idx = imo_match_group(imo, ifp, &gsa->sa);
- if (idx == -1) {
+ imf = imo_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
is_new = 1;
+ inm = NULL;
+
+ if (ip_mfilter_count(&imo->imo_head) >= IP_MAX_MEMBERSHIPS) {
+ error = ENOMEM;
+ goto out_inp_locked;
+ }
} else {
- inm = imo->imo_membership[idx];
- imf = &imo->imo_mfilters[idx];
+ is_new = 0;
+ inm = imf->imf_inm;
+
if (ssa->ss.ss_family != AF_UNSPEC) {
/*
* MCAST_JOIN_SOURCE_GROUP on an exclusive membership
@@ -2181,7 +2113,7 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
* full-state SSM API with the delta-based API,
* which is discouraged in the relevant RFCs.
*/
- lims = imo_match_source(imo, idx, &ssa->sa);
+ lims = imo_match_source(imf, &ssa->sa);
if (lims != NULL /*&&
lims->imsl_st[1] == MCAST_INCLUDE*/) {
error = EADDRNOTAVAIL;
@@ -2214,27 +2146,6 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
*/
INP_WLOCK_ASSERT(inp);
- if (is_new) {
- if (imo->imo_num_memberships == imo->imo_max_memberships) {
- error = imo_grow(imo);
- if (error)
- goto out_inp_locked;
- }
- /*
- * Allocate the new slot upfront so we can deal with
- * grafting the new source filter in same code path
- * as for join-source on existing membership.
- */
- idx = imo->imo_num_memberships;
- imo->imo_membership[idx] = NULL;
- imo->imo_num_memberships++;
- KASSERT(imo->imo_mfilters != NULL,
- ("%s: imf_mfilters vector was not allocated", __func__));
- imf = &imo->imo_mfilters[idx];
- KASSERT(RB_EMPTY(&imf->imf_sources),
- ("%s: imf_sources not empty", __func__));
- }
-
/*
* Graft new source into filter list for this inpcb's
* membership of the group. The in_multi may not have
@@ -2250,7 +2161,11 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
/* Membership starts in IN mode */
if (is_new) {
CTR1(KTR_IGMPV3, "%s: new join w/source", __func__);
- imf_init(imf, MCAST_UNDEFINED, MCAST_INCLUDE);
+ imf = ip_mfilter_alloc(M_NOWAIT, MCAST_UNDEFINED, MCAST_INCLUDE);
+ if (imf == NULL) {
+ error = ENOMEM;
+ goto out_inp_locked;
+ }
} else {
CTR2(KTR_IGMPV3, "%s: %s source", __func__, "allow");
}
@@ -2259,34 +2174,41 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
CTR1(KTR_IGMPV3, "%s: merge imf state failed",
__func__);
error = ENOMEM;
- goto out_imo_free;
+ goto out_inp_locked;
}
} else {
/* No address specified; Membership starts in EX mode */
if (is_new) {
CTR1(KTR_IGMPV3, "%s: new join w/o source", __func__);
- imf_init(imf, MCAST_UNDEFINED, MCAST_EXCLUDE);
+ imf = ip_mfilter_alloc(M_NOWAIT, MCAST_UNDEFINED, MCAST_EXCLUDE);
+ if (imf == NULL) {
+ error = ENOMEM;
+ goto out_inp_locked;
+ }
}
}
/*
* Begin state merge transaction at IGMP layer.
*/
- in_pcbref(inp);
- INP_WUNLOCK(inp);
- IN_MULTI_LOCK();
-
if (is_new) {
+ in_pcbref(inp);
+ INP_WUNLOCK(inp);
+
error = in_joingroup_locked(ifp, &gsa->sin.sin_addr, imf,
- &inm);
+ &imf->imf_inm);
+
+ INP_WLOCK(inp);
+ if (in_pcbrele_wlocked(inp)) {
+ error = ENXIO;
+ goto out_inp_unlocked;
+ }
if (error) {
CTR1(KTR_IGMPV3, "%s: in_joingroup_locked failed",
__func__);
- IN_MULTI_LIST_UNLOCK();
- goto out_imo_free;
+ goto out_inp_locked;
}
- inm_acquire(inm);
- imo->imo_membership[idx] = inm;
+ inm_acquire(imf->imf_inm);
} else {
CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
IN_MULTI_LIST_LOCK();
@@ -2295,7 +2217,9 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
CTR1(KTR_IGMPV3, "%s: failed to merge inm state",
__func__);
IN_MULTI_LIST_UNLOCK();
- goto out_in_multi_locked;
+ imf_rollback(imf);
+ imf_reap(imf);
+ goto out_inp_locked;
}
CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__);
error = igmp_change_state(inm);
@@ -2303,40 +2227,30 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
if (error) {
CTR1(KTR_IGMPV3, "%s: failed igmp downcall",
__func__);
- goto out_in_multi_locked;
+ imf_rollback(imf);
+ imf_reap(imf);
+ goto out_inp_locked;
}
}
+ if (is_new)
+ ip_mfilter_insert(&imo->imo_head, imf);
-out_in_multi_locked:
+ imf_commit(imf);
+ imf = NULL;
+out_inp_locked:
+ INP_WUNLOCK(inp);
+out_inp_unlocked:
IN_MULTI_UNLOCK();
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp))
- return (ENXIO);
- if (error) {
- imf_rollback(imf);
- if (is_new)
- imf_purge(imf);
- else
- imf_reap(imf);
- } else {
- imf_commit(imf);
- }
-out_imo_free:
- if (error && is_new) {
- inm = imo->imo_membership[idx];
- if (inm != NULL) {
+ if (is_new && imf) {
+ if (imf->imf_inm != NULL) {
IN_MULTI_LIST_LOCK();
- inm_release_deferred(inm);
+ inm_release_deferred(imf->imf_inm);
IN_MULTI_LIST_UNLOCK();
}
- imo->imo_membership[idx] = NULL;
- --imo->imo_num_memberships;
+ ip_mfilter_free(imf);
}
-
-out_inp_locked:
- INP_WUNLOCK(inp);
return (error);
}
@@ -2355,12 +2269,12 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
struct ip_moptions *imo;
struct in_msource *ims;
struct in_multi *inm;
- size_t idx;
- int error, is_final;
+ int error;
+ bool is_final;
ifp = NULL;
error = 0;
- is_final = 1;
+ is_final = true;
memset(&gsr, 0, sizeof(struct group_source_req));
gsa = (sockunion_t *)&gsr.gsr_group;
@@ -2460,20 +2374,21 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
return (EINVAL);
+ IN_MULTI_LOCK();
+
/*
- * Find the membership in the membership array.
+ * Find the membership in the membership list.
*/
imo = inp_findmoptions(inp);
- idx = imo_match_group(imo, ifp, &gsa->sa);
- if (idx == -1) {
+ imf = imo_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_inp_locked;
}
- inm = imo->imo_membership[idx];
- imf = &imo->imo_mfilters[idx];
+ inm = imf->imf_inm;
if (ssa->ss.ss_family != AF_UNSPEC)
- is_final = 0;
+ is_final = false;
/*
* Begin state merge transaction at socket layer.
@@ -2485,13 +2400,14 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
* MCAST_LEAVE_SOURCE_GROUP is only valid for inclusive memberships.
*/
if (is_final) {
+ ip_mfilter_remove(&imo->imo_head, imf);
imf_leave(imf);
} else {
if (imf->imf_st[0] == MCAST_EXCLUDE) {
error = EADDRNOTAVAIL;
goto out_inp_locked;
}
- ims = imo_match_source(imo, idx, &ssa->sa);
+ ims = imo_match_source(imf, &ssa->sa);
if (ims == NULL) {
CTR3(KTR_IGMPV3, "%s: source 0x%08x %spresent",
__func__, ntohl(ssa->sin.sin_addr.s_addr), "not ");
@@ -2510,17 +2426,7 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
/*
* Begin state merge transaction at IGMP layer.
*/
- in_pcbref(inp);
- INP_WUNLOCK(inp);
- IN_MULTI_LOCK();
-
- if (is_final) {
- /*
- * Give up the multicast address record to which
- * the membership points.
- */
- (void)in_leavegroup_locked(inm, imf);
- } else {
+ if (!is_final) {
CTR1(KTR_IGMPV3, "%s: merge inm state", __func__);
IN_MULTI_LIST_LOCK();
error = inm_merge(inm, imf);
@@ -2528,7 +2434,9 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
CTR1(KTR_IGMPV3, "%s: failed to merge inm state",
__func__);
IN_MULTI_LIST_UNLOCK();
- goto out_in_multi_locked;
+ imf_rollback(imf);
+ imf_reap(imf);
+ goto out_inp_locked;
}
CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__);
@@ -2537,38 +2445,27 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
if (error) {
CTR1(KTR_IGMPV3, "%s: failed igmp downcall",
__func__);
+ imf_rollback(imf);
+ imf_reap(imf);
+ goto out_inp_locked;
}
}
-
-out_in_multi_locked:
-
- IN_MULTI_UNLOCK();
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp))
- return (ENXIO);
-
- if (error)
- imf_rollback(imf);
- else
- imf_commit(imf);
-
+ imf_commit(imf);
imf_reap(imf);
- if (is_final) {
- /* Remove the gap in the membership and filter array. */
- KASSERT(RB_EMPTY(&imf->imf_sources),
- ("%s: imf_sources not empty", __func__));
- for (++idx; idx < imo->imo_num_memberships; ++idx) {
- imo->imo_membership[idx - 1] = imo->imo_membership[idx];
- imo->imo_mfilters[idx - 1] = imo->imo_mfilters[idx];
- }
- imf_init(&imo->imo_mfilters[idx - 1], MCAST_UNDEFINED,
- MCAST_EXCLUDE);
- imo->imo_num_memberships--;
- }
-
out_inp_locked:
INP_WUNLOCK(inp);
+
+ if (is_final && imf) {
+ /*
+ * Give up the multicast address record to which
+ * the membership points.
+ */
+ (void) in_leavegroup_locked(imf->imf_inm, imf);
+ ip_mfilter_free(imf);
+ }
+
+ IN_MULTI_UNLOCK();
return (error);
}
@@ -2658,7 +2555,6 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
struct in_mfilter *imf;
struct ip_moptions *imo;
struct in_multi *inm;
- size_t idx;
int error;
error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq),
@@ -2690,18 +2586,19 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
if (ifp == NULL)
return (EADDRNOTAVAIL);
+ IN_MULTI_LOCK();
+
/*
* Take the INP write lock.
* Check if this socket is a member of this group.
*/
imo = inp_findmoptions(inp);
- idx = imo_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->imo_mfilters == NULL) {
+ imf = imo_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_inp_locked;
}
- inm = imo->imo_membership[idx];
- imf = &imo->imo_mfilters[idx];
+ inm = imf->imf_inm;
/*
* Begin state merge transaction at socket layer.
@@ -2778,7 +2675,6 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
goto out_imf_rollback;
INP_WLOCK_ASSERT(inp);
- IN_MULTI_LOCK();
/*
* Begin state merge transaction at IGMP layer.
@@ -2789,7 +2685,7 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
if (error) {
CTR1(KTR_IGMPV3, "%s: failed to merge inm state", __func__);
IN_MULTI_LIST_UNLOCK();
- goto out_in_multi_locked;
+ goto out_imf_rollback;
}
CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__);
@@ -2798,10 +2694,6 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
if (error)
CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__);
-out_in_multi_locked:
-
- IN_MULTI_UNLOCK();
-
out_imf_rollback:
if (error)
imf_rollback(imf);
@@ -2812,6 +2704,7 @@ out_imf_rollback:
out_inp_locked:
INP_WUNLOCK(inp);
+ IN_MULTI_UNLOCK();
return (error);
}
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 17fa34895595..b68475afa655 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -86,6 +86,9 @@ __FBSDID("$FreeBSD$");
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
#include <netinet/in_pcb.h>
+#ifdef INET
+#include <netinet/in_var.h>
+#endif
#include <netinet/ip_var.h>
#include <netinet/tcp_var.h>
#ifdef TCPHPTS
@@ -93,16 +96,13 @@ __FBSDID("$FreeBSD$");
#endif
#include <netinet/udp.h>
#include <netinet/udp_var.h>
-#endif
-#ifdef INET
-#include <netinet/in_var.h>
-#endif
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/in6_pcb.h>
#include <netinet6/in6_var.h>
#include <netinet6/ip6_var.h>
#endif /* INET6 */
+#endif
#include <netipsec/ipsec_support.h>
@@ -1779,8 +1779,9 @@ void
in_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
{
struct inpcb *inp;
+ struct in_multi *inm;
+ struct in_mfilter *imf;
struct ip_moptions *imo;
- int i, gap;
INP_INFO_WLOCK(pcbinfo);
CK_LIST_FOREACH(inp, pcbinfo->ipi_listhead, inp_list) {
@@ -1801,17 +1802,18 @@ in_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
*
* XXX This can all be deferred to an epoch_call
*/
- for (i = 0, gap = 0; i < imo->imo_num_memberships;
- i++) {
- if (imo->imo_membership[i]->inm_ifp == ifp) {
- IN_MULTI_LOCK_ASSERT();
- in_leavegroup_locked(imo->imo_membership[i], NULL);
- gap++;
- } else if (gap != 0)
- imo->imo_membership[i - gap] =
- imo->imo_membership[i];
+restart:
+ IP_MFILTER_FOREACH(imf, &imo->imo_head) {
+ if ((inm = imf->imf_inm) == NULL)
+ continue;
+ if (inm->inm_ifp != ifp)
+ continue;
+ ip_mfilter_remove(&imo->imo_head, imf);
+ IN_MULTI_LOCK_ASSERT();
+ in_leavegroup_locked(inm, NULL);
+ ip_mfilter_free(imf);
+ goto restart;
}
- imo->imo_num_memberships -= gap;
}
INP_WUNLOCK(inp);
}
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
index 5b7a464bd3e8..50112481f236 100644
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -232,9 +232,61 @@ struct in_mfilter {
struct ip_msource_tree imf_sources; /* source list for (S,G) */
u_long imf_nsrc; /* # of source entries */
uint8_t imf_st[2]; /* state before/at commit */
+ struct in_multi *imf_inm; /* associated multicast address */
+ STAILQ_ENTRY(in_mfilter) imf_entry; /* list entry */
};
/*
+ * Helper types and functions for IPv4 multicast filters.
+ */
+STAILQ_HEAD(ip_mfilter_head, in_mfilter);
+
+struct in_mfilter *ip_mfilter_alloc(int mflags, int st0, int st1);
+void ip_mfilter_free(struct in_mfilter *);
+
+static inline void
+ip_mfilter_init(struct ip_mfilter_head *head)
+{
+
+ STAILQ_INIT(head);
+}
+
+static inline struct in_mfilter *
+ip_mfilter_first(const struct ip_mfilter_head *head)
+{
+
+ return (STAILQ_FIRST(head));
+}
+
+static inline void
+ip_mfilter_insert(struct ip_mfilter_head *head, struct in_mfilter *imf)
+{
+
+ STAILQ_INSERT_TAIL(head, imf, imf_entry);
+}
+
+static inline void
+ip_mfilter_remove(struct ip_mfilter_head *head, struct in_mfilter *imf)
+{
+
+ STAILQ_REMOVE(head, imf, in_mfilter, imf_entry);
+}
+
+#define IP_MFILTER_FOREACH(imf, head) \
+ STAILQ_FOREACH(imf, head, imf_entry)
+
+static inline size_t
+ip_mfilter_count(struct ip_mfilter_head *head)
+{
+ struct in_mfilter *imf;
+ size_t num = 0;
+
+ STAILQ_FOREACH(imf, head, imf_entry)
+ num++;
+ return (num);
+}
+
+/*
* IPv4 group descriptor.
*
* For every entry on an ifnet's if_multiaddrs list which represents
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 9c24fb9fdd67..819a0f9c75e6 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -1371,25 +1371,24 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
case AF_INET:
{
struct ip_moptions *imo = &cif->cif_imo;
+ struct in_mfilter *imf;
struct in_addr addr;
- if (imo->imo_membership)
+ if (ip_mfilter_first(&imo->imo_head) != NULL)
return (0);
- imo->imo_membership = (struct in_multi **)malloc(
- (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_CARP,
- M_WAITOK);
- imo->imo_mfilters = NULL;
- imo->imo_max_memberships = IP_MIN_MEMBERSHIPS;
+ imf = ip_mfilter_alloc(M_WAITOK, 0, 0);
+ ip_mfilter_init(&imo->imo_head);
imo->imo_multicast_vif = -1;
addr.s_addr = htonl(INADDR_CARP_GROUP);
if ((error = in_joingroup(ifp, &addr, NULL,
- &imo->imo_membership[0])) != 0) {
- free(imo->imo_membership, M_CARP);
+ &imf->imf_inm)) != 0) {
+ ip_mfilter_free(imf);
break;
}
- imo->imo_num_memberships++;
+
+ ip_mfilter_insert(&imo->imo_head, imf);
imo->imo_multicast_ifp = ifp;
imo->imo_multicast_ttl = CARP_DFLTTL;
imo->imo_multicast_loop = 0;
@@ -1400,17 +1399,16 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
case AF_INET6:
{
struct ip6_moptions *im6o = &cif->cif_im6o;
+ struct in6_mfilter *im6f[2];
struct in6_addr in6;
- struct in6_multi *in6m;
- if (im6o->im6o_membership)
+ if (ip6_mfilter_first(&im6o->im6o_head))
return (0);
- im6o->im6o_membership = (struct in6_multi **)malloc(
- (sizeof(struct in6_multi *) * IPV6_MIN_MEMBERSHIPS), M_CARP,
- M_ZERO | M_WAITOK);
- im6o->im6o_mfilters = NULL;
- im6o->im6o_max_memberships = IPV6_MIN_MEMBERSHIPS;
+ im6f[0] = ip6_mfilter_alloc(M_WAITOK, 0, 0);
+ im6f[1] = ip6_mfilter_alloc(M_WAITOK, 0, 0);
+
+ ip6_mfilter_init(&im6o->im6o_head);
im6o->im6o_multicast_hlim = CARP_DFLTTL;
im6o->im6o_multicast_ifp = ifp;
@@ -1419,17 +1417,15 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
in6.s6_addr16[0] = htons(0xff02);
in6.s6_addr8[15] = 0x12;
if ((error = in6_setscope(&in6, ifp, NULL)) != 0) {
- free(im6o->im6o_membership, M_CARP);
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m = NULL;
- if ((error = in6_joingroup(ifp, &in6, NULL, &in6m, 0)) != 0) {
- free(im6o->im6o_membership, M_CARP);
+ if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[0]->im6f_in6m, 0)) != 0) {
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m_acquire(in6m);
- im6o->im6o_membership[0] = in6m;
- im6o->im6o_num_memberships++;
/* Join solicited multicast address. */
bzero(&in6, sizeof(in6));
@@ -1438,20 +1434,21 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
in6.s6_addr32[2] = htonl(1);
in6.s6_addr32[3] = 0;
in6.s6_addr8[12] = 0xff;
+
if ((error = in6_setscope(&in6, ifp, NULL)) != 0) {
- in6_leavegroup(im6o->im6o_membership[0], NULL);
- free(im6o->im6o_membership, M_CARP);
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m = NULL;
- if ((error = in6_joingroup(ifp, &in6, NULL, &in6m, 0)) != 0) {
- in6_leavegroup(im6o->im6o_membership[0], NULL);
- free(im6o->im6o_membership, M_CARP);
+
+ if ((error = in6_joingroup(ifp, &in6, NULL, &im6f[1]->im6f_in6m, 0)) != 0) {
+ in6_leavegroup(im6f[0]->im6f_in6m, NULL);
+ ip6_mfilter_free(im6f[0]);
+ ip6_mfilter_free(im6f[1]);
break;
}
- in6m_acquire(in6m);
- im6o->im6o_membership[1] = in6m;
- im6o->im6o_num_memberships++;
+ ip6_mfilter_insert(&im6o->im6o_head, im6f[0]);
+ ip6_mfilter_insert(&im6o->im6o_head, im6f[1]);
break;
}
#endif
@@ -1466,35 +1463,38 @@ carp_multicast_setup(struct carp_if *cif, sa_family_t sa)
static void
carp_multicast_cleanup(struct carp_if *cif, sa_family_t sa)
{
-
+#ifdef INET
+ struct ip_moptions *imo = &cif->cif_imo;
+ struct in_mfilter *imf;
+#endif
+#ifdef INET6
+ struct ip6_moptions *im6o = &cif->cif_im6o;
+ struct in6_mfilter *im6f;
+#endif
sx_assert(&carp_sx, SA_XLOCKED);
switch (sa) {
#ifdef INET
case AF_INET:
- if (cif->cif_naddrs == 0) {
- struct ip_moptions *imo = &cif->cif_imo;
-
- in_leavegroup(imo->imo_membership[0], NULL);
- KASSERT(imo->imo_mfilters == NULL,
- ("%s: imo_mfilters != NULL", __func__));
- free(imo->imo_membership, M_CARP);
- imo->imo_membership = NULL;
+ if (cif->cif_naddrs != 0)
+ break;
+ while ((imf = ip_mfilter_first(&imo->imo_head)) != NULL) {
+ ip_mfilter_remove(&imo->imo_head, imf);
+ in_leavegroup(imf->imf_inm, NULL);
+ ip_mfilter_free(imf);
}
break;
#endif
#ifdef INET6
case AF_INET6:
- if (cif->cif_naddrs6 == 0) {
- struct ip6_moptions *im6o = &cif->cif_im6o;
-
- in6_leavegroup(im6o->im6o_membership[0], NULL);
- in6_leavegroup(im6o->im6o_membership[1], NULL);
- KASSERT(im6o->im6o_mfilters == NULL,
- ("%s: im6o_mfilters != NULL", __func__));
- free(im6o->im6o_membership, M_CARP);
- im6o->im6o_membership = NULL;
+ if (cif->cif_naddrs6 != 0)
+ break;
+
+ while ((im6f = ip6_mfilter_first(&im6o->im6o_head)) != NULL) {
+ ip6_mfilter_remove(&im6o->im6o_head, im6f);
+ in6_leavegroup(im6f->im6f_in6m, NULL);
+ ip6_mfilter_free(im6f);
}
break;
#endif
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index de0cc29db1d2..7a01c82ba58b 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -293,6 +293,7 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
O_EXTERNAL_DATA, /* variable length data */
O_SKIP_ACTION, /* none */
+ O_TCPMSS, /* arg1=MSS value */
O_LAST_OPCODE /* not an opcode! */
};
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index 0439d353575d..14ebb6ef1007 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -1680,7 +1680,6 @@ static void
send_packet(struct vif *vifp, struct mbuf *m)
{
struct ip_moptions imo;
- struct in_multi *imm[2];
int error __unused;
VIF_LOCK_ASSERT();
@@ -1689,9 +1688,7 @@ send_packet(struct vif *vifp, struct mbuf *m)
imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1;
imo.imo_multicast_loop = 1;
imo.imo_multicast_vif = -1;
- imo.imo_num_memberships = 0;
- imo.imo_max_memberships = 2;
- imo.imo_membership = &imm[0];
+ STAILQ_INIT(&imo.imo_head);
/*
* Re-entrancy should not be a problem here, because
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 99b8c3662be5..2a7eb7f56286 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -109,20 +109,24 @@ extern int in_mcast_loop;
extern struct protosw inetsw[];
static inline int
-ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, struct inpcb *inp,
- struct sockaddr_in *dst, int *fibnum, int *error)
+ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, int flags,
+ struct inpcb *inp, struct sockaddr_in *dst, int *fibnum, int *error)
{
struct m_tag *fwd_tag = NULL;
struct mbuf *m;
struct in_addr odst;
struct ip *ip;
+ int pflags = PFIL_OUT;
+
+ if (flags & IP_FORWARDING)
+ pflags |= PFIL_FWD;
m = *mp;
ip = mtod(m, struct ip *);
/* Run through list of hooks for output packets. */
odst.s_addr = ip->ip_dst.s_addr;
- switch (pfil_run_hooks(V_inet_pfil_head, mp, ifp, PFIL_OUT, inp)) {
+ switch (pfil_run_hooks(V_inet_pfil_head, mp, ifp, pflags, inp)) {
case PFIL_DROPPED:
*error = EPERM;
/* FALLTHROUGH */
@@ -653,7 +657,8 @@ sendit:
/* Jump over all PFIL processing if hooks are not active. */
if (PFIL_HOOKED_OUT(V_inet_pfil_head)) {
- switch (ip_output_pfil(&m, ifp, inp, dst, &fibnum, &error)) {
+ switch (ip_output_pfil(&m, ifp, flags, inp, dst, &fibnum,
+ &error)) {
case 1: /* Finished */
goto done;
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 38602efb3f4e..7580a7b45212 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -82,6 +82,7 @@ struct ipoption {
char ipopt_list[MAX_IPOPTLEN]; /* options proper */
};
+#if defined(_NETINET_IN_VAR_H_) && defined(_KERNEL)
/*
* Structure attached to inpcb.ip_moptions and
* passed to ip_output when IP multicast options are in use.
@@ -93,12 +94,11 @@ struct ip_moptions {
u_long imo_multicast_vif; /* vif num outgoing multicasts */
u_char imo_multicast_ttl; /* TTL for outgoing multicasts */
u_char imo_multicast_loop; /* 1 => hear sends if a member */
- u_short imo_num_memberships; /* no. memberships this socket */
- u_short imo_max_memberships; /* max memberships this socket */
- struct in_multi **imo_membership; /* group memberships */
- struct in_mfilter *imo_mfilters; /* source filters */
- struct epoch_context imo_epoch_ctx;
+ struct ip_mfilter_head imo_head; /* group membership list */
};
+#else
+struct ip_moptions;
+#endif
struct ipstat {
uint64_t ips_total; /* total packets received */
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 4ac87cb0d470..8f767305f97d 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -798,8 +798,12 @@ register_tcp_functions_as_names(struct tcp_function_block *blk, int wait,
}
}
+ if (blk->tfb_flags & TCP_FUNC_BEING_REMOVED) {
+ *num_names = 0;
+ return (EINVAL);
+ }
+
refcount_init(&blk->tfb_refcnt, 0);
- blk->tfb_flags = 0;
blk->tfb_id = atomic_fetchadd_int(&next_tcp_stack_id, 1);
for (i = 0; i < *num_names; i++) {
n = malloc(sizeof(struct tcp_function), M_TCPFUNCTIONS, wait);
diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h
index 37d6ad40289e..56ab11460af2 100644
--- a/sys/netinet6/in6.h
+++ b/sys/netinet6/in6.h
@@ -523,11 +523,8 @@ struct route_in6 {
#define IPV6_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
/*
- * The im6o_membership vector for each socket is now dynamically allocated at
- * run-time, bounded by USHRT_MAX, and is reallocated when needed, sized
- * according to a power-of-two increment.
+ * Limit for IPv6 multicast memberships
*/
-#define IPV6_MIN_MEMBERSHIPS 31
#define IPV6_MAX_MEMBERSHIPS 4095
/*
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index a1a707449bf2..7ce680f2f91a 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -774,9 +774,11 @@ _in6_ifdetach(struct ifnet *ifp, int purgeulp)
in6_purgeaddr(ifa);
}
if (purgeulp) {
+ IN6_MULTI_LOCK();
in6_pcbpurgeif0(&V_udbinfo, ifp);
in6_pcbpurgeif0(&V_ulitecbinfo, ifp);
in6_pcbpurgeif0(&V_ripcbinfo, ifp);
+ IN6_MULTI_UNLOCK();
}
/* leave from all multicast groups joined */
in6_purgemaddrs(ifp);
diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c
index 5557a7c76564..f68b0a84d17d 100644
--- a/sys/netinet6/in6_mcast.c
+++ b/sys/netinet6/in6_mcast.c
@@ -102,7 +102,8 @@ RB_GENERATE(ip6_msource_tree, ip6_msource, im6s_link, ip6_msource_cmp);
/*
* Locking:
- * - Lock order is: Giant, INP_WLOCK, IN6_MULTI_LOCK, MLD_LOCK, IF_ADDR_LOCK.
+ * - Lock order is: Giant, IN6_MULTI_LOCK, INP_WLOCK,
+ * IN6_MULTI_LIST_LOCK, MLD_LOCK, IF_ADDR_LOCK.
* - The IF_ADDR_LOCK is implicitly taken by in6m_lookup() earlier, however
* it can be taken by code in net/if.c also.
* - ip6_moptions and in6_mfilter are covered by the INP_WLOCK.
@@ -134,12 +135,11 @@ static int im6f_prune(struct in6_mfilter *, const struct sockaddr_in6 *);
static void im6f_purge(struct in6_mfilter *);
static void im6f_rollback(struct in6_mfilter *);
static void im6f_reap(struct in6_mfilter *);
-static int im6o_grow(struct ip6_moptions *);
-static size_t im6o_match_group(const struct ip6_moptions *,
+static struct in6_mfilter *
+ im6o_match_group(const struct ip6_moptions *,
const struct ifnet *, const struct sockaddr *);
static struct in6_msource *
- im6o_match_source(const struct ip6_moptions *, const size_t,
- const struct sockaddr *);
+ im6o_match_source(struct in6_mfilter *, const struct sockaddr *);
static void im6s_merge(struct ip6_msource *ims,
const struct in6_msource *lims, const int rollback);
static int in6_getmulti(struct ifnet *, const struct in6_addr *,
@@ -228,55 +228,25 @@ im6f_init(struct in6_mfilter *imf, const int st0, const int st1)
imf->im6f_st[1] = st1;
}
-/*
- * Resize the ip6_moptions vector to the next power-of-two minus 1.
- * May be called with locks held; do not sleep.
- */
-static int
-im6o_grow(struct ip6_moptions *imo)
+struct in6_mfilter *
+ip6_mfilter_alloc(const int mflags, const int st0, const int st1)
{
- struct in6_multi **nmships;
- struct in6_multi **omships;
- struct in6_mfilter *nmfilters;
- struct in6_mfilter *omfilters;
- size_t idx;
- size_t newmax;
- size_t oldmax;
-
- nmships = NULL;
- nmfilters = NULL;
- omships = imo->im6o_membership;
- omfilters = imo->im6o_mfilters;
- oldmax = imo->im6o_max_memberships;
- newmax = ((oldmax + 1) * 2) - 1;
-
- if (newmax <= IPV6_MAX_MEMBERSHIPS) {
- nmships = (struct in6_multi **)realloc(omships,
- sizeof(struct in6_multi *) * newmax, M_IP6MOPTS, M_NOWAIT);
- nmfilters = (struct in6_mfilter *)realloc(omfilters,
- sizeof(struct in6_mfilter) * newmax, M_IN6MFILTER,
- M_NOWAIT);
- if (nmships != NULL && nmfilters != NULL) {
- /* Initialize newly allocated source filter heads. */
- for (idx = oldmax; idx < newmax; idx++) {
- im6f_init(&nmfilters[idx], MCAST_UNDEFINED,
- MCAST_EXCLUDE);
- }
- imo->im6o_max_memberships = newmax;
- imo->im6o_membership = nmships;
- imo->im6o_mfilters = nmfilters;
- }
- }
+ struct in6_mfilter *imf;
- if (nmships == NULL || nmfilters == NULL) {
- if (nmships != NULL)
- free(nmships, M_IP6MOPTS);
- if (nmfilters != NULL)
- free(nmfilters, M_IN6MFILTER);
- return (ETOOMANYREFS);
- }
+ imf = malloc(sizeof(*imf), M_IN6MFILTER, mflags);
- return (0);
+ if (imf != NULL)
+ im6f_init(imf, st0, st1);
+
+ return (imf);
+}
+
+void
+ip6_mfilter_free(struct in6_mfilter *imf)
+{
+
+ im6f_purge(imf);
+ free(imf, M_IN6MFILTER);
}
/*
@@ -284,36 +254,27 @@ im6o_grow(struct ip6_moptions *imo)
* which matches the specified group, and optionally an interface.
* Return its index into the array, or -1 if not found.
*/
-static size_t
+static struct in6_mfilter *
im6o_match_group(const struct ip6_moptions *imo, const struct ifnet *ifp,
const struct sockaddr *group)
{
const struct sockaddr_in6 *gsin6;
- struct in6_multi **pinm;
- int idx;
- int nmships;
+ struct in6_mfilter *imf;
+ struct in6_multi *inm;
- gsin6 = (const struct sockaddr_in6 *)group;
+ gsin6 = (const struct sockaddr_in6 *)group;
- /* The im6o_membership array may be lazy allocated. */
- if (imo->im6o_membership == NULL || imo->im6o_num_memberships == 0)
- return (-1);
-
- nmships = imo->im6o_num_memberships;
- pinm = &imo->im6o_membership[0];
- for (idx = 0; idx < nmships; idx++, pinm++) {
- if (*pinm == NULL)
+ IP6_MFILTER_FOREACH(imf, &imo->im6o_head) {
+ inm = imf->im6f_in6m;
+ if (inm == NULL)
continue;
- if ((ifp == NULL || ((*pinm)->in6m_ifp == ifp)) &&
- IN6_ARE_ADDR_EQUAL(&(*pinm)->in6m_addr,
+ if ((ifp == NULL || (inm->in6m_ifp == ifp)) &&
+ IN6_ARE_ADDR_EQUAL(&inm->in6m_addr,
&gsin6->sin6_addr)) {
break;
}
}
- if (idx >= nmships)
- idx = -1;
-
- return (idx);
+ return (imf);
}
/*
@@ -328,22 +289,13 @@ im6o_match_group(const struct ip6_moptions *imo, const struct ifnet *ifp,
* it exists, which may not be the desired behaviour.
*/
static struct in6_msource *
-im6o_match_source(const struct ip6_moptions *imo, const size_t gidx,
- const struct sockaddr *src)
+im6o_match_source(struct in6_mfilter *imf, const struct sockaddr *src)
{
struct ip6_msource find;
- struct in6_mfilter *imf;
struct ip6_msource *ims;
const sockunion_t *psa;
KASSERT(src->sa_family == AF_INET6, ("%s: !AF_INET6", __func__));
- KASSERT(gidx != -1 && gidx < imo->im6o_num_memberships,
- ("%s: invalid index %d\n", __func__, (int)gidx));
-
- /* The im6o_mfilters array may be lazy allocated. */
- if (imo->im6o_mfilters == NULL)
- return (NULL);
- imf = &imo->im6o_mfilters[gidx];
psa = (const sockunion_t *)src;
find.im6s_addr = psa->sin6.sin6_addr;
@@ -363,14 +315,14 @@ int
im6o_mc_filter(const struct ip6_moptions *imo, const struct ifnet *ifp,
const struct sockaddr *group, const struct sockaddr *src)
{
- size_t gidx;
+ struct in6_mfilter *imf;
struct in6_msource *ims;
int mode;
KASSERT(ifp != NULL, ("%s: null ifp", __func__));
- gidx = im6o_match_group(imo, ifp, group);
- if (gidx == -1)
+ imf = im6o_match_group(imo, ifp, group);
+ if (imf == NULL)
return (MCAST_NOTGMEMBER);
/*
@@ -382,8 +334,8 @@ im6o_mc_filter(const struct ip6_moptions *imo, const struct ifnet *ifp,
* NOTE: We are comparing group state here at MLD t1 (now)
* with socket-layer t0 (since last downcall).
*/
- mode = imo->im6o_mfilters[gidx].im6f_st[1];
- ims = im6o_match_source(imo, gidx, src);
+ mode = imf->im6f_st[1];
+ ims = im6o_match_source(imf, src);
if ((ims == NULL && mode == MCAST_INCLUDE) ||
(ims != NULL && ims->im6sl_st[0] != mode))
@@ -1447,7 +1399,6 @@ in6p_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
struct ip6_moptions *imo;
struct in6_msource *ims;
struct in6_multi *inm;
- size_t idx;
uint16_t fmode;
int error, doblock;
#ifdef KTR
@@ -1504,16 +1455,12 @@ in6p_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
* Check if we are actually a member of this group.
*/
imo = in6p_findmoptions(inp);
- idx = im6o_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->im6o_mfilters == NULL) {
+ imf = im6o_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_in6p_locked;
}
-
- KASSERT(imo->im6o_mfilters != NULL,
- ("%s: im6o_mfilters not allocated", __func__));
- imf = &imo->im6o_mfilters[idx];
- inm = imo->im6o_membership[idx];
+ inm = imf->im6f_in6m;
/*
* Attempting to use the delta-based API on an
@@ -1531,7 +1478,7 @@ in6p_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
* Asked to unblock, but nothing to unblock.
* If adding a new block entry, allocate it.
*/
- ims = im6o_match_source(imo, idx, &ssa->sa);
+ ims = im6o_match_source(imf, &ssa->sa);
if ((ims != NULL && doblock) || (ims == NULL && !doblock)) {
CTR3(KTR_MLD, "%s: source %s %spresent", __func__,
ip6_sprintf(ip6tbuf, &ssa->sin6.sin6_addr),
@@ -1601,9 +1548,6 @@ static struct ip6_moptions *
in6p_findmoptions(struct inpcb *inp)
{
struct ip6_moptions *imo;
- struct in6_multi **immp;
- struct in6_mfilter *imfp;
- size_t idx;
INP_WLOCK(inp);
if (inp->in6p_moptions != NULL)
@@ -1612,27 +1556,14 @@ in6p_findmoptions(struct inpcb *inp)
INP_WUNLOCK(inp);
imo = malloc(sizeof(*imo), M_IP6MOPTS, M_WAITOK);
- immp = malloc(sizeof(*immp) * IPV6_MIN_MEMBERSHIPS, M_IP6MOPTS,
- M_WAITOK | M_ZERO);
- imfp = malloc(sizeof(struct in6_mfilter) * IPV6_MIN_MEMBERSHIPS,
- M_IN6MFILTER, M_WAITOK);
imo->im6o_multicast_ifp = NULL;
imo->im6o_multicast_hlim = V_ip6_defmcasthlim;
imo->im6o_multicast_loop = in6_mcast_loop;
- imo->im6o_num_memberships = 0;
- imo->im6o_max_memberships = IPV6_MIN_MEMBERSHIPS;
- imo->im6o_membership = immp;
-
- /* Initialize per-group source filters. */
- for (idx = 0; idx < IPV6_MIN_MEMBERSHIPS; idx++)
- im6f_init(&imfp[idx], MCAST_UNDEFINED, MCAST_EXCLUDE);
- imo->im6o_mfilters = imfp;
+ STAILQ_INIT(&imo->im6o_head);
INP_WLOCK(inp);
if (inp->in6p_moptions != NULL) {
- free(imfp, M_IN6MFILTER);
- free(immp, M_IP6MOPTS);
free(imo, M_IP6MOPTS);
return (inp->in6p_moptions);
}
@@ -1652,33 +1583,26 @@ in6p_findmoptions(struct inpcb *inp)
static void
inp_gcmoptions(struct ip6_moptions *imo)
{
- struct in6_mfilter *imf;
+ struct in6_mfilter *imf;
struct in6_multi *inm;
struct ifnet *ifp;
- size_t idx, nmships;
-
- nmships = imo->im6o_num_memberships;
- for (idx = 0; idx < nmships; ++idx) {
- imf = imo->im6o_mfilters ? &imo->im6o_mfilters[idx] : NULL;
- if (imf)
- im6f_leave(imf);
- inm = imo->im6o_membership[idx];
- ifp = inm->in6m_ifp;
- if (ifp != NULL) {
- CURVNET_SET(ifp->if_vnet);
- (void)in6_leavegroup(inm, imf);
- CURVNET_RESTORE();
- } else {
- (void)in6_leavegroup(inm, imf);
- }
- if (imf)
- im6f_purge(imf);
- }
- if (imo->im6o_mfilters)
- free(imo->im6o_mfilters, M_IN6MFILTER);
- free(imo->im6o_membership, M_IP6MOPTS);
- free(imo, M_IP6MOPTS);
+ while ((imf = ip6_mfilter_first(&imo->im6o_head)) != NULL) {
+ ip6_mfilter_remove(&imo->im6o_head, imf);
+
+ im6f_leave(imf);
+ if ((inm = imf->im6f_in6m) != NULL) {
+ if ((ifp = inm->in6m_ifp) != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ (void)in6_leavegroup(inm, imf);
+ CURVNET_RESTORE();
+ } else {
+ (void)in6_leavegroup(inm, imf);
+ }
+ }
+ ip6_mfilter_free(imf);
+ }
+ free(imo, M_IP6MOPTS);
}
void
@@ -1707,7 +1631,7 @@ in6p_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
struct sockaddr_storage *ptss;
struct sockaddr_storage *tss;
int error;
- size_t idx, nsrcs, ncsrcs;
+ size_t nsrcs, ncsrcs;
INP_WLOCK_ASSERT(inp);
@@ -1741,12 +1665,11 @@ in6p_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
/*
* Lookup group on the socket.
*/
- idx = im6o_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->im6o_mfilters == NULL) {
+ imf = im6o_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
INP_WUNLOCK(inp);
return (EADDRNOTAVAIL);
}
- imf = &imo->im6o_mfilters[idx];
/*
* Ignore memberships which are in limbo.
@@ -1943,15 +1866,12 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
struct ip6_moptions *imo;
struct in6_multi *inm;
struct in6_msource *lims;
- size_t idx;
int error, is_new;
SLIST_INIT(&inmh);
ifp = NULL;
- imf = NULL;
lims = NULL;
error = 0;
- is_new = 0;
memset(&gsr, 0, sizeof(struct group_source_req));
gsa = (sockunion_t *)&gsr.gsr_group;
@@ -2052,13 +1972,25 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
*/
(void)in6_setscope(&gsa->sin6.sin6_addr, ifp, NULL);
+ IN6_MULTI_LOCK();
+
+ /*
+ * Find the membership in the membership list.
+ */
imo = in6p_findmoptions(inp);
- idx = im6o_match_group(imo, ifp, &gsa->sa);
- if (idx == -1) {
+ imf = im6o_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
is_new = 1;
+ inm = NULL;
+
+ if (ip6_mfilter_count(&imo->im6o_head) >= IPV6_MAX_MEMBERSHIPS) {
+ error = ENOMEM;
+ goto out_in6p_locked;
+ }
} else {
- inm = imo->im6o_membership[idx];
- imf = &imo->im6o_mfilters[idx];
+ is_new = 0;
+ inm = imf->im6f_in6m;
+
if (ssa->ss.ss_family != AF_UNSPEC) {
/*
* MCAST_JOIN_SOURCE_GROUP on an exclusive membership
@@ -2085,7 +2017,7 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
* full-state SSM API with the delta-based API,
* which is discouraged in the relevant RFCs.
*/
- lims = im6o_match_source(imo, idx, &ssa->sa);
+ lims = im6o_match_source(imf, &ssa->sa);
if (lims != NULL /*&&
lims->im6sl_st[1] == MCAST_INCLUDE*/) {
error = EADDRNOTAVAIL;
@@ -2113,27 +2045,6 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
*/
INP_WLOCK_ASSERT(inp);
- if (is_new) {
- if (imo->im6o_num_memberships == imo->im6o_max_memberships) {
- error = im6o_grow(imo);
- if (error)
- goto out_in6p_locked;
- }
- /*
- * Allocate the new slot upfront so we can deal with
- * grafting the new source filter in same code path
- * as for join-source on existing membership.
- */
- idx = imo->im6o_num_memberships;
- imo->im6o_membership[idx] = NULL;
- imo->im6o_num_memberships++;
- KASSERT(imo->im6o_mfilters != NULL,
- ("%s: im6f_mfilters vector was not allocated", __func__));
- imf = &imo->im6o_mfilters[idx];
- KASSERT(RB_EMPTY(&imf->im6f_sources),
- ("%s: im6f_sources not empty", __func__));
- }
-
/*
* Graft new source into filter list for this inpcb's
* membership of the group. The in6_multi may not have
@@ -2149,7 +2060,11 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
/* Membership starts in IN mode */
if (is_new) {
CTR1(KTR_MLD, "%s: new join w/source", __func__);
- im6f_init(imf, MCAST_UNDEFINED, MCAST_INCLUDE);
+ imf = ip6_mfilter_alloc(M_NOWAIT, MCAST_UNDEFINED, MCAST_INCLUDE);
+ if (imf == NULL) {
+ error = ENOMEM;
+ goto out_in6p_locked;
+ }
} else {
CTR2(KTR_MLD, "%s: %s source", __func__, "allow");
}
@@ -2158,81 +2073,88 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
CTR1(KTR_MLD, "%s: merge imf state failed",
__func__);
error = ENOMEM;
- goto out_im6o_free;
+ goto out_in6p_locked;
}
} else {
/* No address specified; Membership starts in EX mode */
if (is_new) {
CTR1(KTR_MLD, "%s: new join w/o source", __func__);
- im6f_init(imf, MCAST_UNDEFINED, MCAST_EXCLUDE);
+ imf = ip6_mfilter_alloc(M_NOWAIT, MCAST_UNDEFINED, MCAST_EXCLUDE);
+ if (imf == NULL) {
+ error = ENOMEM;
+ goto out_in6p_locked;
+ }
}
}
/*
* Begin state merge transaction at MLD layer.
*/
- in_pcbref(inp);
- INP_WUNLOCK(inp);
- IN6_MULTI_LOCK();
-
if (is_new) {
+ in_pcbref(inp);
+ INP_WUNLOCK(inp);
+
error = in6_joingroup_locked(ifp, &gsa->sin6.sin6_addr, imf,
- &inm, 0);
+ &imf->im6f_in6m, 0);
+
+ INP_WLOCK(inp);
+ if (in_pcbrele_wlocked(inp)) {
+ error = ENXIO;
+ goto out_in6p_unlocked;
+ }
if (error) {
- IN6_MULTI_UNLOCK();
- goto out_im6o_free;
+ goto out_in6p_locked;
}
/*
* NOTE: Refcount from in6_joingroup_locked()
* is protecting membership.
*/
- imo->im6o_membership[idx] = inm;
} else {
CTR1(KTR_MLD, "%s: merge inm state", __func__);
IN6_MULTI_LIST_LOCK();
error = in6m_merge(inm, imf);
- if (error)
+ if (error) {
CTR1(KTR_MLD, "%s: failed to merge inm state",
__func__);
- else {
- CTR1(KTR_MLD, "%s: doing mld downcall", __func__);
- error = mld_change_state(inm, 0);
- if (error)
- CTR1(KTR_MLD, "%s: failed mld downcall",
- __func__);
+ IN6_MULTI_LIST_UNLOCK();
+ im6f_rollback(imf);
+ im6f_reap(imf);
+ goto out_in6p_locked;
}
+ CTR1(KTR_MLD, "%s: doing mld downcall", __func__);
+ error = mld_change_state(inm, 0);
IN6_MULTI_LIST_UNLOCK();
- }
- IN6_MULTI_UNLOCK();
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp))
- return (ENXIO);
- if (error) {
- im6f_rollback(imf);
- if (is_new)
- im6f_purge(imf);
- else
+ if (error) {
+ CTR1(KTR_MLD, "%s: failed mld downcall",
+ __func__);
+ im6f_rollback(imf);
im6f_reap(imf);
- } else {
- im6f_commit(imf);
- }
-
-out_im6o_free:
- if (error && is_new) {
- inm = imo->im6o_membership[idx];
- if (inm != NULL) {
- IN6_MULTI_LIST_LOCK();
- in6m_rele_locked(&inmh, inm);
- IN6_MULTI_LIST_UNLOCK();
+ goto out_in6p_locked;
}
- imo->im6o_membership[idx] = NULL;
- --imo->im6o_num_memberships;
}
+ if (is_new)
+ ip6_mfilter_insert(&imo->im6o_head, imf);
+
+ im6f_commit(imf);
+ imf = NULL;
+
out_in6p_locked:
INP_WUNLOCK(inp);
- in6m_release_list_deferred(&inmh);
+out_in6p_unlocked:
+ IN6_MULTI_UNLOCK();
+
+ if (is_new && imf) {
+ if (imf->im6f_in6m != NULL) {
+ struct in6_multi_head inmh;
+
+ SLIST_INIT(&inmh);
+ SLIST_INSERT_HEAD(&inmh, imf->im6f_in6m, in6m_defer);
+ in6m_release_list_deferred(&inmh);
+ }
+ ip6_mfilter_free(imf);
+ }
return (error);
}
@@ -2251,8 +2173,8 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
struct in6_msource *ims;
struct in6_multi *inm;
uint32_t ifindex;
- size_t idx;
- int error, is_final;
+ int error;
+ bool is_final;
#ifdef KTR
char ip6tbuf[INET6_ADDRSTRLEN];
#endif
@@ -2260,7 +2182,7 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
ifp = NULL;
ifindex = 0;
error = 0;
- is_final = 1;
+ is_final = true;
memset(&gsr, 0, sizeof(struct group_source_req));
gsa = (sockunion_t *)&gsr.gsr_group;
@@ -2378,20 +2300,21 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
CTR2(KTR_MLD, "%s: ifp = %p", __func__, ifp);
KASSERT(ifp != NULL, ("%s: ifp did not resolve", __func__));
+ IN6_MULTI_LOCK();
+
/*
- * Find the membership in the membership array.
+ * Find the membership in the membership list.
*/
imo = in6p_findmoptions(inp);
- idx = im6o_match_group(imo, ifp, &gsa->sa);
- if (idx == -1) {
+ imf = im6o_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_in6p_locked;
}
- inm = imo->im6o_membership[idx];
- imf = &imo->im6o_mfilters[idx];
+ inm = imf->im6f_in6m;
if (ssa->ss.ss_family != AF_UNSPEC)
- is_final = 0;
+ is_final = false;
/*
* Begin state merge transaction at socket layer.
@@ -2403,13 +2326,14 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
* MCAST_LEAVE_SOURCE_GROUP is only valid for inclusive memberships.
*/
if (is_final) {
+ ip6_mfilter_remove(&imo->im6o_head, imf);
im6f_leave(imf);
} else {
if (imf->im6f_st[0] == MCAST_EXCLUDE) {
error = EADDRNOTAVAIL;
goto out_in6p_locked;
}
- ims = im6o_match_source(imo, idx, &ssa->sa);
+ ims = im6o_match_source(imf, &ssa->sa);
if (ims == NULL) {
CTR3(KTR_MLD, "%s: source %p %spresent", __func__,
ip6_sprintf(ip6tbuf, &ssa->sin6.sin6_addr),
@@ -2429,60 +2353,47 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
/*
* Begin state merge transaction at MLD layer.
*/
- in_pcbref(inp);
- INP_WUNLOCK(inp);
- IN6_MULTI_LOCK();
-
- if (is_final) {
- /*
- * Give up the multicast address record to which
- * the membership points.
- */
- (void)in6_leavegroup_locked(inm, imf);
- } else {
+ if (!is_final) {
CTR1(KTR_MLD, "%s: merge inm state", __func__);
IN6_MULTI_LIST_LOCK();
error = in6m_merge(inm, imf);
- if (error)
+ if (error) {
CTR1(KTR_MLD, "%s: failed to merge inm state",
__func__);
- else {
- CTR1(KTR_MLD, "%s: doing mld downcall", __func__);
- error = mld_change_state(inm, 0);
- if (error)
- CTR1(KTR_MLD, "%s: failed mld downcall",
- __func__);
+ IN6_MULTI_LIST_UNLOCK();
+ im6f_rollback(imf);
+ im6f_reap(imf);
+ goto out_in6p_locked;
}
+
+ CTR1(KTR_MLD, "%s: doing mld downcall", __func__);
+ error = mld_change_state(inm, 0);
IN6_MULTI_LIST_UNLOCK();
+ if (error) {
+ CTR1(KTR_MLD, "%s: failed mld downcall",
+ __func__);
+ im6f_rollback(imf);
+ im6f_reap(imf);
+ goto out_in6p_locked;
+ }
}
- IN6_MULTI_UNLOCK();
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp))
- return (ENXIO);
-
- if (error)
- im6f_rollback(imf);
- else
- im6f_commit(imf);
-
+ im6f_commit(imf);
im6f_reap(imf);
- if (is_final) {
- /* Remove the gap in the membership array. */
- KASSERT(RB_EMPTY(&imf->im6f_sources),
- ("%s: im6f_sources not empty", __func__));
- for (++idx; idx < imo->im6o_num_memberships; ++idx) {
- imo->im6o_membership[idx - 1] = imo->im6o_membership[idx];
- imo->im6o_mfilters[idx - 1] = imo->im6o_mfilters[idx];
- }
- im6f_init(&imo->im6o_mfilters[idx - 1], MCAST_UNDEFINED,
- MCAST_EXCLUDE);
- imo->im6o_num_memberships--;
- }
-
out_in6p_locked:
INP_WUNLOCK(inp);
+
+ if (is_final && imf) {
+ /*
+ * Give up the multicast address record to which
+ * the membership points.
+ */
+ (void)in6_leavegroup_locked(inm, imf);
+ ip6_mfilter_free(imf);
+ }
+
+ IN6_MULTI_UNLOCK();
return (error);
}
@@ -2540,7 +2451,6 @@ in6p_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
struct in6_mfilter *imf;
struct ip6_moptions *imo;
struct in6_multi *inm;
- size_t idx;
int error;
error = sooptcopyin(sopt, &msfr, sizeof(struct __msfilterreq),
@@ -2577,13 +2487,12 @@ in6p_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
* Check if this socket is a member of this group.
*/
imo = in6p_findmoptions(inp);
- idx = im6o_match_group(imo, ifp, &gsa->sa);
- if (idx == -1 || imo->im6o_mfilters == NULL) {
+ imf = im6o_match_group(imo, ifp, &gsa->sa);
+ if (imf == NULL) {
error = EADDRNOTAVAIL;
goto out_in6p_locked;
}
- inm = imo->im6o_membership[idx];
- imf = &imo->im6o_mfilters[idx];
+ inm = imf->im6f_in6m;
/*
* Begin state merge transaction at socket layer.
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index c27464b1e3e7..abad883dc623 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -802,8 +802,9 @@ void
in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
{
struct inpcb *in6p;
+ struct in6_multi *inm;
+ struct in6_mfilter *imf;
struct ip6_moptions *im6o;
- int i, gap;
INP_INFO_WLOCK(pcbinfo);
CK_LIST_FOREACH(in6p, pcbinfo->ipi_listhead, inp_list) {
@@ -824,18 +825,18 @@ in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
* Drop multicast group membership if we joined
* through the interface being detached.
*/
- gap = 0;
- for (i = 0; i < im6o->im6o_num_memberships; i++) {
- if (im6o->im6o_membership[i]->in6m_ifp ==
- ifp) {
- in6_leavegroup(im6o->im6o_membership[i], NULL);
- gap++;
- } else if (gap != 0) {
- im6o->im6o_membership[i - gap] =
- im6o->im6o_membership[i];
- }
+restart:
+ IP6_MFILTER_FOREACH(imf, &im6o->im6o_head) {
+ if ((inm = imf->im6f_in6m) == NULL)
+ continue;
+ if (inm->in6m_ifp != ifp)
+ continue;
+ ip6_mfilter_remove(&im6o->im6o_head, imf);
+ IN6_MULTI_LOCK_ASSERT();
+ in6_leavegroup_locked(inm, NULL);
+ ip6_mfilter_free(imf);
+ goto restart;
}
- im6o->im6o_num_memberships -= gap;
}
INP_WUNLOCK(in6p);
}
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index 3e965c2d4b32..3e535310b29e 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -602,9 +602,61 @@ struct in6_mfilter {
struct ip6_msource_tree im6f_sources; /* source list for (S,G) */
u_long im6f_nsrc; /* # of source entries */
uint8_t im6f_st[2]; /* state before/at commit */
+ struct in6_multi *im6f_in6m; /* associated multicast address */
+ STAILQ_ENTRY(in6_mfilter) im6f_entry; /* list entry */
};
/*
+ * Helper types and functions for IPv4 multicast filters.
+ */
+STAILQ_HEAD(ip6_mfilter_head, in6_mfilter);
+
+struct in6_mfilter *ip6_mfilter_alloc(int mflags, int st0, int st1);
+void ip6_mfilter_free(struct in6_mfilter *);
+
+static inline void
+ip6_mfilter_init(struct ip6_mfilter_head *head)
+{
+
+ STAILQ_INIT(head);
+}
+
+static inline struct in6_mfilter *
+ip6_mfilter_first(const struct ip6_mfilter_head *head)
+{
+
+ return (STAILQ_FIRST(head));
+}
+
+static inline void
+ip6_mfilter_insert(struct ip6_mfilter_head *head, struct in6_mfilter *imf)
+{
+
+ STAILQ_INSERT_TAIL(head, imf, im6f_entry);
+}
+
+static inline void
+ip6_mfilter_remove(struct ip6_mfilter_head *head, struct in6_mfilter *imf)
+{
+
+ STAILQ_REMOVE(head, imf, in6_mfilter, im6f_entry);
+}
+
+#define IP6_MFILTER_FOREACH(imf, head) \
+ STAILQ_FOREACH(imf, head, im6f_entry)
+
+static inline size_t
+ip6_mfilter_count(struct ip6_mfilter_head *head)
+{
+ struct in6_mfilter *imf;
+ size_t num = 0;
+
+ STAILQ_FOREACH(imf, head, im6f_entry)
+ num++;
+ return (num);
+}
+
+/*
* Legacy KAME IPv6 multicast membership descriptor.
*/
struct in6_multi_mship {
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index 40f502abcd08..45ee4425fb74 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -110,6 +110,7 @@ struct ip6_direct_ctx {
uint32_t ip6dc_off; /* offset to next header */
};
+#if defined(_NETINET6_IN6_VAR_H_) && defined(_KERNEL)
/*
* Structure attached to inpcb.in6p_moptions and
* passed to ip6_output when IPv6 multicast options are in use.
@@ -119,13 +120,11 @@ struct ip6_moptions {
struct ifnet *im6o_multicast_ifp; /* ifp for outgoing multicasts */
u_char im6o_multicast_hlim; /* hoplimit for outgoing multicasts */
u_char im6o_multicast_loop; /* 1 >= hear sends if a member */
- u_short im6o_num_memberships; /* no. memberships this socket */
- u_short im6o_max_memberships; /* max memberships this socket */
- struct in6_multi **im6o_membership; /* group memberships */
- struct in6_mfilter *im6o_mfilters; /* source filters */
- struct epoch_context imo6_epoch_ctx;
+ struct ip6_mfilter_head im6o_head; /* group membership list */
};
-
+#else
+struct ip6_moptions;
+#endif
/*
* Control options for outgoing packets
*/
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index d54427410b92..82a84a412538 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -7164,7 +7164,7 @@ key_register(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
return key_senderror(so, m, ENOBUFS);
MGETHDR(n, M_NOWAIT, MT_DATA);
- if (len > MHLEN) {
+ if (n != NULL && len > MHLEN) {
if (!(MCLGET(n, M_NOWAIT))) {
m_freem(n);
n = NULL;
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
index a4a3830132eb..535be037b6cc 100644
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -331,10 +331,10 @@ ipopts_match(struct ip *ip, ipfw_insn *cmd)
}
static int
-tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd)
+tcpopts_parse(struct tcphdr *tcp, uint16_t *mss)
{
- int optlen, bits = 0;
u_char *cp = (u_char *)(tcp + 1);
+ int optlen, bits = 0;
int x = (tcp->th_off << 2) - sizeof(struct tcphdr);
for (; x > 0; x -= optlen, cp += optlen) {
@@ -350,12 +350,13 @@ tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd)
}
switch (opt) {
-
default:
break;
case TCPOPT_MAXSEG:
bits |= IP_FW_TCPOPT_MSS;
+ if (mss != NULL)
+ *mss = be16dec(cp + 2);
break;
case TCPOPT_WINDOW:
@@ -370,10 +371,16 @@ tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd)
case TCPOPT_TIMESTAMP:
bits |= IP_FW_TCPOPT_TS;
break;
-
}
}
- return (flags_match(cmd, bits));
+ return (bits);
+}
+
+static int
+tcpopts_match(struct tcphdr *tcp, ipfw_insn *cmd)
+{
+
+ return (flags_match(cmd, tcpopts_parse(tcp, NULL)));
}
static int
@@ -1712,6 +1719,11 @@ do { \
default:
break;
}
+ } else {
+ if (offset == 1 && proto == IPPROTO_TCP) {
+ /* RFC 3128 */
+ goto pullup_failed;
+ }
}
UPDATE_POINTERS();
@@ -2316,6 +2328,31 @@ do { \
TCP(ulp)->th_ack);
break;
+ case O_TCPMSS:
+ if (proto == IPPROTO_TCP &&
+ (args->f_id._flags & TH_SYN) != 0 &&
+ ulp != NULL) {
+ uint16_t mss, *p;
+ int i;
+
+ PULLUP_LEN(hlen, ulp,
+ (TCP(ulp)->th_off << 2));
+ if ((tcpopts_parse(TCP(ulp), &mss) &
+ IP_FW_TCPOPT_MSS) == 0)
+ break;
+ if (cmdlen == 1) {
+ match = (cmd->arg1 == mss);
+ break;
+ }
+ /* Otherwise we have ranges. */
+ p = ((ipfw_insn_u16 *)cmd)->ports;
+ i = cmdlen - 1;
+ for (; !match && i > 0; i--, p += 2)
+ match = (mss >= p[0] &&
+ mss <= p[1]);
+ }
+ break;
+
case O_TCPWIN:
if (proto == IPPROTO_TCP && offset == 0) {
uint16_t x;
@@ -3332,6 +3369,7 @@ vnet_ipfw_init(const void *unused)
/* fill and insert the default rule */
rule = ipfw_alloc_rule(chain, sizeof(struct ip_fw));
+ rule->flags |= IPFW_RULE_NOOPT;
rule->cmd_len = 1;
rule->cmd[0].len = 1;
rule->cmd[0].opcode = default_to_accept ? O_ACCEPT : O_DENY;
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
index a83e75447633..297b01ca7d3d 100644
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -1176,7 +1176,9 @@ move_objects(struct ip_fw_chain *ch, ipfw_range_tlv *rt)
}
}
return (c);
-}/*
+}
+
+/*
* Changes set of given rule rannge @rt
* with each other.
*
@@ -1907,6 +1909,7 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci)
case O_IPTTL:
case O_IPLEN:
case O_TCPDATALEN:
+ case O_TCPMSS:
case O_TCPWIN:
case O_TAGGED:
if (cmdlen < 1 || cmdlen > 31)
diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c
index 45b1e090f95c..0566593b7616 100644
--- a/sys/netpfil/pf/if_pfsync.c
+++ b/sys/netpfil/pf/if_pfsync.c
@@ -264,7 +264,7 @@ static void pfsync_push(struct pfsync_bucket *);
static void pfsync_push_all(struct pfsync_softc *);
static void pfsyncintr(void *);
static int pfsync_multicast_setup(struct pfsync_softc *, struct ifnet *,
- void *);
+ struct in_mfilter *imf);
static void pfsync_multicast_cleanup(struct pfsync_softc *);
static void pfsync_pointers_init(void);
static void pfsync_pointers_uninit(void);
@@ -430,8 +430,7 @@ pfsync_clone_destroy(struct ifnet *ifp)
pfsync_drop(sc);
if_free(ifp);
- if (sc->sc_imo.imo_membership)
- pfsync_multicast_cleanup(sc);
+ pfsync_multicast_cleanup(sc);
mtx_destroy(&sc->sc_mtx);
mtx_destroy(&sc->sc_bulk_mtx);
@@ -1373,10 +1372,9 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCSETPFSYNC:
{
- struct ip_moptions *imo = &sc->sc_imo;
+ struct in_mfilter *imf = NULL;
struct ifnet *sifp;
struct ip *ip;
- void *mship = NULL;
if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0)
return (error);
@@ -1396,8 +1394,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
pfsyncr.pfsyncr_syncpeer.s_addr == 0 ||
pfsyncr.pfsyncr_syncpeer.s_addr ==
htonl(INADDR_PFSYNC_GROUP)))
- mship = malloc((sizeof(struct in_multi *) *
- IP_MIN_MEMBERSHIPS), M_PFSYNC, M_WAITOK | M_ZERO);
+ imf = ip_mfilter_alloc(M_WAITOK, 0, 0);
PFSYNC_LOCK(sc);
if (pfsyncr.pfsyncr_syncpeer.s_addr == 0)
@@ -1419,8 +1416,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
if (sc->sc_sync_if)
if_rele(sc->sc_sync_if);
sc->sc_sync_if = NULL;
- if (imo->imo_membership)
- pfsync_multicast_cleanup(sc);
+ pfsync_multicast_cleanup(sc);
PFSYNC_UNLOCK(sc);
break;
}
@@ -1436,14 +1432,13 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
PFSYNC_BUCKET_UNLOCK(&sc->sc_buckets[c]);
}
- if (imo->imo_membership)
- pfsync_multicast_cleanup(sc);
+ pfsync_multicast_cleanup(sc);
if (sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
- error = pfsync_multicast_setup(sc, sifp, mship);
+ error = pfsync_multicast_setup(sc, sifp, imf);
if (error) {
if_rele(sifp);
- free(mship, M_PFSYNC);
+ ip_mfilter_free(imf);
PFSYNC_UNLOCK(sc);
return (error);
}
@@ -2353,7 +2348,8 @@ pfsyncintr(void *arg)
}
static int
-pfsync_multicast_setup(struct pfsync_softc *sc, struct ifnet *ifp, void *mship)
+pfsync_multicast_setup(struct pfsync_softc *sc, struct ifnet *ifp,
+ struct in_mfilter *imf)
{
struct ip_moptions *imo = &sc->sc_imo;
int error;
@@ -2361,16 +2357,14 @@ pfsync_multicast_setup(struct pfsync_softc *sc, struct ifnet *ifp, void *mship)
if (!(ifp->if_flags & IFF_MULTICAST))
return (EADDRNOTAVAIL);
- imo->imo_membership = (struct in_multi **)mship;
- imo->imo_max_memberships = IP_MIN_MEMBERSHIPS;
imo->imo_multicast_vif = -1;
if ((error = in_joingroup(ifp, &sc->sc_sync_peer, NULL,
- &imo->imo_membership[0])) != 0) {
- imo->imo_membership = NULL;
+ &imf->imf_inm)) != 0)
return (error);
- }
- imo->imo_num_memberships++;
+
+ ip_mfilter_init(&imo->imo_head);
+ ip_mfilter_insert(&imo->imo_head, imf);
imo->imo_multicast_ifp = ifp;
imo->imo_multicast_ttl = PFSYNC_DFLTTL;
imo->imo_multicast_loop = 0;
@@ -2382,10 +2376,13 @@ static void
pfsync_multicast_cleanup(struct pfsync_softc *sc)
{
struct ip_moptions *imo = &sc->sc_imo;
+ struct in_mfilter *imf;
- in_leavegroup(imo->imo_membership[0], NULL);
- free(imo->imo_membership, M_PFSYNC);
- imo->imo_membership = NULL;
+ while ((imf = ip_mfilter_first(&imo->imo_head)) != NULL) {
+ ip_mfilter_remove(&imo->imo_head, imf);
+ in_leavegroup(imf->imf_inm, NULL);
+ ip_mfilter_free(imf);
+ }
imo->imo_multicast_ifp = NULL;
}
@@ -2404,7 +2401,7 @@ pfsync_detach_ifnet(struct ifnet *ifp)
* is going away. We do need to ensure we don't try to do
* cleanup later.
*/
- sc->sc_imo.imo_membership = NULL;
+ ip_mfilter_init(&sc->sc_imo.imo_head);
sc->sc_imo.imo_multicast_ifp = NULL;
sc->sc_sync_if = NULL;
}
diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC
index dc19d7a85598..78d83c9ba12d 100644
--- a/sys/powerpc/conf/GENERIC
+++ b/sys/powerpc/conf/GENERIC
@@ -162,7 +162,6 @@ device fxp # Intel EtherExpress PRO/100B (82557, 82558)
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64
index dc3d54e371c9..409062047b24 100644
--- a/sys/powerpc/conf/GENERIC64
+++ b/sys/powerpc/conf/GENERIC64
@@ -183,7 +183,6 @@ device rl # RealTek 8129/8139
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/powerpc/conf/MPC85XX b/sys/powerpc/conf/MPC85XX
index 3eeba5f54ec4..7962bdc22db0 100644
--- a/sys/powerpc/conf/MPC85XX
+++ b/sys/powerpc/conf/MPC85XX
@@ -93,7 +93,6 @@ device mmcsd
device pass
device pci
device quicc
-device random
#device rl
device scbus
device scc
diff --git a/sys/powerpc/conf/MPC85XXSPE b/sys/powerpc/conf/MPC85XXSPE
index 1d649c1b36b9..2cea302361a3 100644
--- a/sys/powerpc/conf/MPC85XXSPE
+++ b/sys/powerpc/conf/MPC85XXSPE
@@ -94,7 +94,6 @@ device mmcsd
device pass
device pci
device quicc
-device random
#device rl
device scbus
device scc
diff --git a/sys/powerpc/conf/QORIQ64 b/sys/powerpc/conf/QORIQ64
index eecc0eb8e06b..1661829a6d25 100644
--- a/sys/powerpc/conf/QORIQ64
+++ b/sys/powerpc/conf/QORIQ64
@@ -99,7 +99,6 @@ device mmc
device mmcsd
device pass
device pci
-device random
#device rl
device scbus
device scc
diff --git a/sys/powerpc/conf/dpaa/DPAA b/sys/powerpc/conf/dpaa/DPAA
index 2cbc908ec120..4aa24c188acc 100644
--- a/sys/powerpc/conf/dpaa/DPAA
+++ b/sys/powerpc/conf/dpaa/DPAA
@@ -96,7 +96,6 @@ device pci
# Pseudo devices
device ether # Ethernet support
device loop # Network loopback
-device random # Entropy device
device bpf # Berkeley packet filter
device md # Memory "disks"
diff --git a/sys/powerpc/include/trap.h b/sys/powerpc/include/trap.h
index 5017a7535d29..56b789c248ef 100644
--- a/sys/powerpc/include/trap.h
+++ b/sys/powerpc/include/trap.h
@@ -130,7 +130,7 @@
/* Macros to extract register information */
#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f) /* source or target */
#define EXC_ALI_RA(dsisr) (dsisr & 0x1f)
-#define EXC_ALI_SPE_REG(instr) ((instr >> 21) & 0x1f)
+#define EXC_ALI_INST_RST(instr) ((instr >> 21) & 0x1f)
/*
* SRR1 bits for program exception traps. These identify what caused
diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c
index 6fb874e31d9c..0bd6a11197ab 100644
--- a/sys/powerpc/powerpc/machdep.c
+++ b/sys/powerpc/powerpc/machdep.c
@@ -595,3 +595,16 @@ bzero(void *buf, size_t len)
len--;
}
}
+
+/* __stack_chk_fail_local() is called in secure-plt (32-bit). */
+#if !defined(__powerpc64__)
+extern void __stack_chk_fail(void);
+void __stack_chk_fail_local(void);
+
+void
+__stack_chk_fail_local(void)
+{
+
+ __stack_chk_fail();
+}
+#endif
diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c
index 0200c7bbd142..3cc04fbc75ad 100644
--- a/sys/powerpc/powerpc/trap.c
+++ b/sys/powerpc/powerpc/trap.c
@@ -788,7 +788,7 @@ static int
fix_unaligned(struct thread *td, struct trapframe *frame)
{
struct thread *fputhread;
-#ifdef __SPE__
+#ifdef BOOKE
uint32_t inst;
#endif
int indicator, reg;
@@ -799,7 +799,7 @@ fix_unaligned(struct thread *td, struct trapframe *frame)
if (indicator & ESR_SPE) {
if (copyin((void *)frame->srr0, &inst, sizeof(inst)) != 0)
return (-1);
- reg = EXC_ALI_SPE_REG(inst);
+ reg = EXC_ALI_INST_RST(inst);
fpr = (double *)td->td_pcb->pcb_vec.vr[reg];
fputhread = PCPU_GET(vecthread);
@@ -829,12 +829,22 @@ fix_unaligned(struct thread *td, struct trapframe *frame)
return (0);
}
#else
+#ifdef BOOKE
+ indicator = (frame->cpu.booke.esr & ESR_ST) ? EXC_ALI_STFD : EXC_ALI_LFD;
+#else
indicator = EXC_ALI_OPCODE_INDICATOR(frame->cpu.aim.dsisr);
+#endif
switch (indicator) {
case EXC_ALI_LFD:
case EXC_ALI_STFD:
+#ifdef BOOKE
+ if (copyin((void *)frame->srr0, &inst, sizeof(inst)) != 0)
+ return (-1);
+ reg = EXC_ALI_INST_RST(inst);
+#else
reg = EXC_ALI_RST(frame->cpu.aim.dsisr);
+#endif
fpr = &td->td_pcb->pcb_fpu.fpr[reg].fpr;
fputhread = PCPU_GET(fputhread);
diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC
index 559e9166daa9..5b647977879f 100644
--- a/sys/riscv/conf/GENERIC
+++ b/sys/riscv/conf/GENERIC
@@ -137,7 +137,6 @@ options ZSTDIO # zstd-compressed kernel and user dumps
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC
index 285adadf332c..75fe3f842577 100644
--- a/sys/sparc64/conf/GENERIC
+++ b/sys/sparc64/conf/GENERIC
@@ -224,7 +224,6 @@ device ath_rate_sample # SampleRate tx rate control for ath
# Pseudo devices.
device crypto # core crypto support
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tuntap # Packet tunnel.
diff --git a/sys/sys/_types.h b/sys/sys/_types.h
index 22a37c53389a..020ba025ea98 100644
--- a/sys/sys/_types.h
+++ b/sys/sys/_types.h
@@ -68,6 +68,7 @@ typedef unsigned int __useconds_t; /* microseconds (unsigned) */
typedef int __cpuwhich_t; /* which parameter for cpuset. */
typedef int __cpulevel_t; /* level parameter for cpuset. */
typedef int __cpusetid_t; /* cpuset identifier. */
+typedef __int64_t __daddr_t; /* bwrite(3), FIOBMAP2, etc */
/*
* Unusual type definitions.
diff --git a/sys/sys/boot.h b/sys/sys/boot.h
index 68b9e1e0daf3..7874d9663736 100644
--- a/sys/sys/boot.h
+++ b/sys/sys/boot.h
@@ -32,6 +32,8 @@
#ifndef _SYS_BOOT_H_
#define _SYS_BOOT_H_
+#define PATH_KERNEL "/boot/kernel/kernel"
+
int boot_env_to_howto(void);
void boot_howto_to_env(int howto);
int boot_parse_arg(char *v);
diff --git a/sys/sys/file.h b/sys/sys/file.h
index 82af5e6b1bbe..942380c1647f 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -179,7 +179,10 @@ struct file {
/*
* DTYPE_VNODE specific fields.
*/
- int f_seqcount; /* (a) Count of sequential accesses. */
+ union {
+ int16_t f_seqcount; /* (a) Count of sequential accesses. */
+ int f_pipegen;
+ };
off_t f_nextoff; /* next expected read/write offset. */
union {
struct cdev_privdata *fvn_cdevpriv;
diff --git a/sys/sys/filio.h b/sys/sys/filio.h
index e85db9cff4d1..c5cf3d4432e9 100644
--- a/sys/sys/filio.h
+++ b/sys/sys/filio.h
@@ -40,7 +40,7 @@
#ifndef _SYS_FILIO_H_
#define _SYS_FILIO_H_
-#include <sys/types.h>
+#include <sys/_types.h>
#include <sys/ioccom.h>
/* Generic file-descriptor ioctl's. */
@@ -64,12 +64,12 @@ struct fiodgname_arg {
#define FIOSEEKDATA _IOWR('f', 97, off_t) /* SEEK_DATA */
#define FIOSEEKHOLE _IOWR('f', 98, off_t) /* SEEK_HOLE */
struct fiobmap2_arg {
- int64_t bn;
- int runp;
- int runb;
+ __daddr_t bn;
+ int runp;
+ int runb;
};
-/* Get the file's bmap info for the logical block bn */
-#define FIOBMAP2 _IOWR('f', 99, struct fiobmap2_arg)
+/* Get the file's bmap info for the logical block bn. */
+#define FIOBMAP2 _IOWR('f', 99, struct fiobmap2_arg)
#ifdef _KERNEL
#ifdef COMPAT_FREEBSD32
diff --git a/sys/sys/mman.h b/sys/sys/mman.h
index b2fad0e47579..1b1b4bcc2cb9 100644
--- a/sys/sys/mman.h
+++ b/sys/sys/mman.h
@@ -55,6 +55,14 @@
#define PROT_READ 0x01 /* pages can be read */
#define PROT_WRITE 0x02 /* pages can be written */
#define PROT_EXEC 0x04 /* pages can be executed */
+#if __BSD_VISIBLE
+#define _PROT_ALL (PROT_READ | PROT_WRITE | PROT_EXEC)
+#define PROT_EXTRACT(prot) ((prot) & _PROT_ALL)
+
+#define _PROT_MAX_SHIFT 16
+#define PROT_MAX(prot) ((prot) << _PROT_MAX_SHIFT)
+#define PROT_MAX_EXTRACT(prot) (((prot) >> _PROT_MAX_SHIFT) & _PROT_ALL)
+#endif
/*
* Flags contain sharing type and options.
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 2534537558c5..9a68762388f2 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -60,7 +60,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1300032 /* Master, propagated to newvers */
+#define __FreeBSD_version 1300034 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff --git a/sys/sys/pcpu.h b/sys/sys/pcpu.h
index 38785cd26c94..3672d6070deb 100644
--- a/sys/sys/pcpu.h
+++ b/sys/sys/pcpu.h
@@ -85,7 +85,8 @@ extern uintptr_t dpcpu_off[];
/* struct _hack is to stop this from being used with the static keyword. */
#define DPCPU_DEFINE(t, n) \
struct _hack; t DPCPU_NAME(n) __section(DPCPU_SETNAME) __used
-#if defined(KLD_MODULE) && (defined(__aarch64__) || defined(__riscv))
+#if defined(KLD_MODULE) && (defined(__aarch64__) || defined(__riscv) \
+ || defined(__powerpc64__))
/*
* On some architectures the compiler will use PC-relative load to
* find the address of DPCPU data with the static keyword. We then
diff --git a/sys/sys/pmckern.h b/sys/sys/pmckern.h
index e892d658a1ca..5b337f8d76df 100644
--- a/sys/sys/pmckern.h
+++ b/sys/sys/pmckern.h
@@ -226,7 +226,7 @@ do { \
*/
#define PMC_CALL_HOOK_UNLOCKED(t, cmd, arg) \
do { \
- if (pmc_hook != NULL) \
+ if (pmc_hook != NULL) \
(pmc_hook)((t), (cmd), (arg)); \
} while (0)
diff --git a/sys/sys/random.h b/sys/sys/random.h
index aa8c5f02c32e..8bcbe470cfc1 100644
--- a/sys/sys/random.h
+++ b/sys/sys/random.h
@@ -37,26 +37,9 @@
struct uio;
-#if defined(DEV_RANDOM)
void read_random(void *, u_int);
int read_random_uio(struct uio *, bool);
bool is_random_seeded(void);
-#else
-static __inline int
-read_random_uio(void *a __unused, u_int b __unused)
-{
- return (0);
-}
-static __inline void
-read_random(void *a __unused, u_int b __unused)
-{
-}
-static __inline bool
-is_random_seeded(void)
-{
- return (false);
-}
-#endif
/*
* Note: if you add or remove members of random_entropy_source, remember to
@@ -101,7 +84,6 @@ _Static_assert(ENTROPYSOURCE <= 32,
#define RANDOM_LEGACY_BOOT_ENTROPY_MODULE "/boot/entropy"
#define RANDOM_CACHED_BOOT_ENTROPY_MODULE "boot_entropy_cache"
-#if defined(DEV_RANDOM)
extern u_int hc_source_mask;
void random_harvest_queue_(const void *, u_int, enum random_entropy_source);
void random_harvest_fast_(const void *, u_int);
@@ -133,13 +115,6 @@ random_harvest_direct(const void *entropy, u_int size, enum random_entropy_sourc
void random_harvest_register_source(enum random_entropy_source);
void random_harvest_deregister_source(enum random_entropy_source);
-#else
-#define random_harvest_queue(a, b, c) do {} while (0)
-#define random_harvest_fast(a, b, c) do {} while (0)
-#define random_harvest_direct(a, b, c) do {} while (0)
-#define random_harvest_register_source(a) do {} while (0)
-#define random_harvest_deregister_source(a) do {} while (0)
-#endif
#if defined(RANDOM_ENABLE_UMA)
#define random_harvest_fast_uma(a, b, c) random_harvest_fast(a, b, c)
diff --git a/sys/sys/rangelock.h b/sys/sys/rangelock.h
index 732bd9406d48..9a8a107aed8f 100644
--- a/sys/sys/rangelock.h
+++ b/sys/sys/rangelock.h
@@ -75,8 +75,12 @@ void *rangelock_unlock_range(struct rangelock *lock, void *cookie,
off_t start, off_t end, struct mtx *ilk);
void *rangelock_rlock(struct rangelock *lock, off_t start, off_t end,
struct mtx *ilk);
+void *rangelock_tryrlock(struct rangelock *lock, off_t start, off_t end,
+ struct mtx *ilk);
void *rangelock_wlock(struct rangelock *lock, off_t start, off_t end,
struct mtx *ilk);
+void *rangelock_trywlock(struct rangelock *lock, off_t start, off_t end,
+ struct mtx *ilk);
void rlqentry_free(struct rl_q_entry *rlqe);
#endif /* _KERNEL */
diff --git a/sys/sys/types.h b/sys/sys/types.h
index 39d8d63262e8..c3ece22e58b8 100644
--- a/sys/sys/types.h
+++ b/sys/sys/types.h
@@ -101,7 +101,7 @@ typedef __clockid_t clockid_t;
#endif
typedef __critical_t critical_t; /* Critical section value */
-typedef __int64_t daddr_t; /* disk address */
+typedef __daddr_t daddr_t; /* disk address */
#ifndef _DEV_T_DECLARED
typedef __dev_t dev_t; /* device number or struct cdev */
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 50eae14026af..9c0dc25f3f83 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -722,8 +722,12 @@ int vn_io_fault_pgmove(vm_page_t ma[], vm_offset_t offset, int xfersize,
VI_MTX(vp))
#define vn_rangelock_rlock(vp, start, end) \
rangelock_rlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
+#define vn_rangelock_tryrlock(vp, start, end) \
+ rangelock_tryrlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
#define vn_rangelock_wlock(vp, start, end) \
rangelock_wlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
+#define vn_rangelock_trywlock(vp, start, end) \
+ rangelock_trywlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
int vfs_cache_lookup(struct vop_lookup_args *ap);
void vfs_timestamp(struct timespec *);
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 3a4a20b8565c..8d43e5528e18 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -2110,7 +2110,6 @@ pagedep_find(pagedephd, ino, lbn, pagedeppp)
* Look up a pagedep. Return 1 if found, 0 otherwise.
* If not found, allocate if DEPALLOC flag is passed.
* Found or allocated entry is returned in pagedeppp.
- * This routine must be called with splbio interrupts blocked.
*/
static int
pagedep_lookup(mp, bp, ino, lbn, flags, pagedeppp)
@@ -2202,7 +2201,6 @@ inodedep_find(inodedephd, inum, inodedeppp)
* Look up an inodedep. Return 1 if found, 0 if not found.
* If not found, allocate if DEPALLOC flag is passed.
* Found or allocated entry is returned in inodedeppp.
- * This routine must be called with splbio interrupts blocked.
*/
static int
inodedep_lookup(mp, inum, flags, inodedeppp)
@@ -5478,7 +5476,6 @@ jnewblk_merge(new, old, wkhd)
/*
* Replace an old allocdirect dependency with a newer one.
- * This routine must be called with splbio interrupts blocked.
*/
static void
allocdirect_merge(adphead, newadp, oldadp)
@@ -7534,7 +7531,6 @@ free_newblk(newblk)
/*
* Free a newdirblk. Clear the NEWBLOCK flag on its associated pagedep.
- * This routine must be called with splbio interrupts blocked.
*/
static void
free_newdirblk(newdirblk)
@@ -7665,7 +7661,6 @@ softdep_freefile(pvp, ino, mode)
/*
* Check to see if an inode has never been written to disk. If
* so free the inodedep and return success, otherwise return failure.
- * This routine must be called with splbio interrupts blocked.
*
* If we still have a bitmap dependency, then the inode has never
* been written to disk. Drop the dependency as it is no longer
@@ -8897,8 +8892,7 @@ cancel_diradd(dap, dirrem, jremref, dotremref, dotdotremref)
}
/*
- * Free a diradd dependency structure. This routine must be called
- * with splbio interrupts blocked.
+ * Free a diradd dependency structure.
*/
static void
free_diradd(dap, wkhd)
@@ -11195,9 +11189,7 @@ softdep_disk_write_complete(bp)
}
/*
- * Called from within softdep_disk_write_complete above. Note that
- * this routine is always called from interrupt level with further
- * splbio interrupts blocked.
+ * Called from within softdep_disk_write_complete above.
*/
static void
handle_allocdirect_partdone(adp, wkhd)
@@ -11209,6 +11201,7 @@ handle_allocdirect_partdone(adp, wkhd)
struct inodedep *inodedep;
long bsize;
+ LOCK_OWNED(VFSTOUFS(adp->ad_block.nb_list.wk_mp));
if ((adp->ad_state & ALLCOMPLETE) != ALLCOMPLETE)
return;
/*
@@ -11818,7 +11811,6 @@ handle_written_indirdep(indirdep, bp, bpp, flags)
/*
* Process a diradd entry after its dependent inode has been written.
- * This routine must be called with splbio interrupts blocked.
*/
static void
diradd_inode_written(dap, inodedep)
@@ -11826,6 +11818,7 @@ diradd_inode_written(dap, inodedep)
struct inodedep *inodedep;
{
+ LOCK_OWNED(VFSTOUFS(dap->da_list.wk_mp));
dap->da_state |= COMPLETE;
complete_diradd(dap);
WORKLIST_INSERT(&inodedep->id_pendinghd, &dap->da_list);
@@ -12386,8 +12379,7 @@ retry:
/*
* Merge the a new inode dependency list (such as id_newinoupdt) into an
- * old inode dependency list (such as id_inoupdt). This routine must be
- * called with splbio interrupts blocked.
+ * old inode dependency list (such as id_inoupdt).
*/
static void
merge_inode_lists(newlisthead, oldlisthead)
@@ -12397,6 +12389,8 @@ merge_inode_lists(newlisthead, oldlisthead)
struct allocdirect *listadp, *newadp;
newadp = TAILQ_FIRST(newlisthead);
+ if (newadp != NULL)
+ LOCK_OWNED(VFSTOUFS(newadp->ad_block.nb_list.wk_mp));
for (listadp = TAILQ_FIRST(oldlisthead); listadp && newadp;) {
if (listadp->ad_offset < newadp->ad_offset) {
listadp = TAILQ_NEXT(listadp, ad_next);
@@ -12891,7 +12885,6 @@ out:
/*
* Flush the dependencies associated with an inodedep.
- * Called with splbio blocked.
*/
static int
flush_inodedep_deps(vp, mp, ino)
@@ -12956,7 +12949,6 @@ restart:
/*
* Flush an inode dependency list.
- * Called with splbio blocked.
*/
static int
flush_deplist(listhead, waitfor, errorp)
@@ -13098,7 +13090,6 @@ flush_newblk_dep(vp, mp, lbn)
/*
* Eliminate a pagedep dependency by flushing out all its diradd dependencies.
- * Called with splbio blocked.
*/
static int
flush_pagedep_deps(pvp, mp, diraddhdp)
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index c27d60869def..7dce4778f951 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -236,7 +236,7 @@ cdev_pager_free_page(vm_object_t object, vm_page_t m)
KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("unmanaged %p", m));
pmap_remove_all(m);
vm_page_lock(m);
- vm_page_remove(m);
+ (void)vm_page_remove(m);
vm_page_unlock(m);
} else if (object->type == OBJT_DEVICE)
dev_pager_free_page(object, m);
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 4268db264d52..ae0103595ae7 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -1144,7 +1144,7 @@ readrest:
fs.object == fs.first_object->backing_object) {
vm_page_lock(fs.m);
vm_page_dequeue(fs.m);
- vm_page_remove(fs.m);
+ (void)vm_page_remove(fs.m);
vm_page_unlock(fs.m);
vm_page_lock(fs.first_m);
vm_page_replace_checked(fs.m, fs.first_object,
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 912031702070..38afe6308cc8 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2472,11 +2472,8 @@ again:
VM_MAP_RANGE_CHECK(map, start, end);
- if (vm_map_lookup_entry(map, start, &entry)) {
- vm_map_clip_start(map, entry, start);
- } else {
+ if (!vm_map_lookup_entry(map, start, &entry))
entry = entry->next;
- }
/*
* Make a first pass to check for protection violations.
@@ -2515,6 +2512,7 @@ again:
* now will do cow due to allowed write (e.g. debugger sets
* breakpoint on text segment)
*/
+ vm_map_clip_start(map, entry, start);
for (current = entry; current->start < end; current = current->next) {
vm_map_clip_end(map, current, end);
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index cd483527af71..24864889060c 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -103,6 +103,9 @@ SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RWTUN, &old_mlock, 0,
static int mincore_mapped = 1;
SYSCTL_INT(_vm, OID_AUTO, mincore_mapped, CTLFLAG_RWTUN, &mincore_mapped, 0,
"mincore reports mappings, not residency");
+static int imply_prot_max = 0;
+SYSCTL_INT(_vm, OID_AUTO, imply_prot_max, CTLFLAG_RWTUN, &imply_prot_max, 0,
+ "Imply maximum page permissions in mmap() when none are specified");
#ifdef MAP_32BIT
#define MAP_32BIT_MAX_ADDR ((vm_offset_t)1 << 31)
@@ -187,9 +190,25 @@ kern_mmap(struct thread *td, uintptr_t addr0, size_t len, int prot, int flags,
vm_offset_t addr;
vm_size_t pageoff, size;
vm_prot_t cap_maxprot;
- int align, error;
+ int align, error, max_prot;
cap_rights_t rights;
+ if ((prot & ~(_PROT_ALL | PROT_MAX(_PROT_ALL))) != 0)
+ return (EINVAL);
+ max_prot = PROT_MAX_EXTRACT(prot);
+ prot = PROT_EXTRACT(prot);
+ if (max_prot != 0 && (max_prot & prot) != prot)
+ return (EINVAL);
+ /*
+ * Always honor PROT_MAX if set. If not, default to all
+ * permissions unless we're implying maximum permissions.
+ *
+ * XXX: should be tunable per process and ABI.
+ */
+ if (max_prot == 0)
+ max_prot = (imply_prot_max && prot != PROT_NONE) ?
+ prot : _PROT_ALL;
+
vms = td->td_proc->p_vmspace;
fp = NULL;
AUDIT_ARG_FD(fd);
@@ -335,7 +354,7 @@ kern_mmap(struct thread *td, uintptr_t addr0, size_t len, int prot, int flags,
* This relies on VM_PROT_* matching PROT_*.
*/
error = vm_mmap_object(&vms->vm_map, &addr, size, prot,
- VM_PROT_ALL, flags, NULL, pos, FALSE, td);
+ max_prot, flags, NULL, pos, FALSE, td);
} else {
/*
* Mapping file, get fp for validation and don't let the
@@ -363,7 +382,7 @@ kern_mmap(struct thread *td, uintptr_t addr0, size_t len, int prot, int flags,
/* This relies on VM_PROT_* matching PROT_*. */
error = fo_mmap(fp, &vms->vm_map, &addr, size, prot,
- cap_maxprot, flags, pos, td);
+ max_prot & cap_maxprot, flags, pos, td);
}
if (error == 0)
@@ -594,9 +613,13 @@ kern_mprotect(struct thread *td, uintptr_t addr0, size_t size, int prot)
{
vm_offset_t addr;
vm_size_t pageoff;
+ int vm_error, max_prot;
addr = addr0;
- prot = (prot & VM_PROT_ALL);
+ if ((prot & ~(_PROT_ALL | PROT_MAX(_PROT_ALL))) != 0)
+ return (EINVAL);
+ max_prot = PROT_MAX_EXTRACT(prot);
+ prot = PROT_EXTRACT(prot);
pageoff = (addr & PAGE_MASK);
addr -= pageoff;
size += pageoff;
@@ -610,8 +633,18 @@ kern_mprotect(struct thread *td, uintptr_t addr0, size_t size, int prot)
if (addr + size < addr)
return (EINVAL);
- switch (vm_map_protect(&td->td_proc->p_vmspace->vm_map, addr,
- addr + size, prot, FALSE)) {
+ vm_error = KERN_SUCCESS;
+ if (max_prot != 0) {
+ if ((max_prot & prot) != prot)
+ return (EINVAL);
+ vm_error = vm_map_protect(&td->td_proc->p_vmspace->vm_map,
+ addr, addr + size, max_prot, TRUE);
+ }
+ if (vm_error == KERN_SUCCESS)
+ vm_error = vm_map_protect(&td->td_proc->p_vmspace->vm_map,
+ addr, addr + size, prot, FALSE);
+
+ switch (vm_error) {
case KERN_SUCCESS:
return (0);
case KERN_PROTECTION_FAILURE:
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 9fd90f04b6d9..7c3575e646cf 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -1595,10 +1595,8 @@ vm_object_collapse_scan(vm_object_t object, int op)
vm_page_lock(p);
KASSERT(!pmap_page_is_mapped(p),
("freeing mapped page %p", p));
- if (!vm_page_wired(p))
+ if (vm_page_remove(p))
vm_page_free(p);
- else
- vm_page_remove(p);
vm_page_unlock(p);
continue;
}
@@ -1639,10 +1637,8 @@ vm_object_collapse_scan(vm_object_t object, int op)
vm_page_lock(p);
KASSERT(!pmap_page_is_mapped(p),
("freeing mapped page %p", p));
- if (!vm_page_wired(p))
+ if (vm_page_remove(p))
vm_page_free(p);
- else
- vm_page_remove(p);
vm_page_unlock(p);
continue;
}
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index a90961ce57b5..e43817b812a0 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -1458,20 +1458,21 @@ vm_page_insert_radixdone(vm_page_t m, vm_object_t object, vm_page_t mpred)
* vm_page_remove:
*
* Removes the specified page from its containing object, but does not
- * invalidate any backing storage.
+ * invalidate any backing storage. Return true if the page may be safely
+ * freed and false otherwise.
*
* The object must be locked. The page must be locked if it is managed.
*/
-void
+bool
vm_page_remove(vm_page_t m)
{
vm_object_t object;
vm_page_t mrem;
+ object = m->object;
+
if ((m->oflags & VPO_UNMANAGED) == 0)
vm_page_assert_locked(m);
- if ((object = m->object) == NULL)
- return;
VM_OBJECT_ASSERT_WLOCKED(object);
if (vm_page_xbusied(m))
vm_page_xunbusy_maybelocked(m);
@@ -1495,6 +1496,7 @@ vm_page_remove(vm_page_t m)
vdrop(object->handle);
m->object = NULL;
+ return (!vm_page_wired(m));
}
/*
@@ -1665,7 +1667,7 @@ vm_page_rename(vm_page_t m, vm_object_t new_object, vm_pindex_t new_pindex)
*/
m->pindex = opidx;
vm_page_lock(m);
- vm_page_remove(m);
+ (void)vm_page_remove(m);
/* Return back to the new pindex to complete vm_page_insert(). */
m->pindex = new_pindex;
@@ -3436,7 +3438,8 @@ vm_page_free_prep(vm_page_t m)
if (vm_page_sbusied(m))
panic("vm_page_free_prep: freeing busy page %p", m);
- vm_page_remove(m);
+ if (m->object != NULL)
+ (void)vm_page_remove(m);
/*
* If fictitious remove object association and
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index d1938d2a1bd8..57f9f6e9081c 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -561,7 +561,7 @@ bool vm_page_reclaim_contig(int req, u_long npages, vm_paddr_t low,
bool vm_page_reclaim_contig_domain(int domain, int req, u_long npages,
vm_paddr_t low, vm_paddr_t high, u_long alignment, vm_paddr_t boundary);
void vm_page_reference(vm_page_t m);
-void vm_page_remove (vm_page_t);
+bool vm_page_remove(vm_page_t);
int vm_page_rename (vm_page_t, vm_object_t, vm_pindex_t);
vm_page_t vm_page_replace(vm_page_t mnew, vm_object_t object,
vm_pindex_t pindex);
diff --git a/targets/pseudo/userland/Makefile.depend b/targets/pseudo/userland/Makefile.depend
index 934d7be54ed7..469d34993b46 100644
--- a/targets/pseudo/userland/Makefile.depend
+++ b/targets/pseudo/userland/Makefile.depend
@@ -772,15 +772,6 @@ DIRDEPS+= \
DIRDEPS+= usr.sbin/efidp
.endif
-.if ${MK_NAND} != "no"
-DIRDEPS+= \
- sbin/nandfs \
- sbin/newfs_nandfs \
- usr.sbin/nandsim \
- usr.sbin/nandtool \
-
-.endif
-
DIRDEPS.amd64= \
sbin/bsdlabel \
sbin/fdisk \
diff --git a/targets/pseudo/userland/lib/Makefile.depend b/targets/pseudo/userland/lib/Makefile.depend
index 2139d18204ca..6e2e549278a7 100644
--- a/targets/pseudo/userland/lib/Makefile.depend
+++ b/targets/pseudo/userland/lib/Makefile.depend
@@ -215,10 +215,6 @@ DIRDEPS+= \
DIRDEPS+= stand/libsa32
.endif
-.if ${MK_NAND} != "no"
-DIRDEPS+= lib/libnandfs
-.endif
-
.if ${MK_CASPER} != "no"
DIRDEPS+= \
lib/libcasper/libcasper \
diff --git a/tests/sys/netinet/socket_afinet.c b/tests/sys/netinet/socket_afinet.c
index d45f70165519..47744d69b587 100644
--- a/tests/sys/netinet/socket_afinet.c
+++ b/tests/sys/netinet/socket_afinet.c
@@ -51,6 +51,8 @@ ATF_TC_BODY(socket_afinet_bind_zero, tc)
int sd, rc;
struct sockaddr_in sin;
+ atf_tc_skip("doesn't work when mac_portacl(4) loaded (bug238781)");
+
sd = socket(PF_INET, SOCK_DGRAM, 0);
ATF_CHECK(sd >= 0);
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index 58592329e11d..c8a2235b5bc0 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -3350,6 +3350,8 @@ OLD_FILES+=usr/share/man/man5/ipf.5.gz
OLD_FILES+=usr/share/man/man5/ipf.conf.5.gz
OLD_FILES+=usr/share/man/man5/ipf6.conf.5.gz
OLD_FILES+=usr/share/man/man5/ipfilter.5.gz
+OLD_FILES+=usr/share/man/man8/ipmon.5.gz
+OLD_FILES+=usr/share/man/man5/ipmon.conf.5.gz
OLD_FILES+=usr/share/man/man5/ipnat.5.gz
OLD_FILES+=usr/share/man/man5/ipnat.conf.5.gz
OLD_FILES+=usr/share/man/man5/ippool.5.gz
diff --git a/tools/tools/nanobsd/defaults.sh b/tools/tools/nanobsd/defaults.sh
index 0002373be658..86acab65f67d 100755
--- a/tools/tools/nanobsd/defaults.sh
+++ b/tools/tools/nanobsd/defaults.sh
@@ -778,8 +778,9 @@ cust_pkgng ( ) (
# Mount packages into chroot
mkdir -p ${NANO_WORLDDIR}/_.p
mount -t nullfs -o noatime -o ro ${NANO_PACKAGE_DIR} ${NANO_WORLDDIR}/_.p
+ mount -t devfs devfs ${NANO_WORLDDIR}/dev
- trap "umount ${NANO_WORLDDIR}/_.p ; rm -rf ${NANO_WORLDDIR}/_.p" 1 2 15 EXIT
+ trap "umount ${NANO_WORLDDIR}/dev; umount ${NANO_WORLDDIR}/_.p ; rm -rf ${NANO_WORLDDIR}/_.p" 1 2 15 EXIT
# Install pkg-* package
CR "${PKGCMD} add /_.p/${_NANO_PKG_PACKAGE}"
@@ -804,6 +805,7 @@ cust_pkgng ( ) (
CR0 "${PKGCMD} info"
trap - 1 2 15 EXIT
+ umount ${NANO_WORLDDIR}/dev
umount ${NANO_WORLDDIR}/_.p
rm -rf ${NANO_WORLDDIR}/_.p
)
diff --git a/tools/tools/nanobsd/pcengines/ALIX_DSK b/tools/tools/nanobsd/pcengines/ALIX_DSK
index 96ae724d736b..e11f7de4f2f4 100644
--- a/tools/tools/nanobsd/pcengines/ALIX_DSK
+++ b/tools/tools/nanobsd/pcengines/ALIX_DSK
@@ -65,7 +65,6 @@ device ath_hal
device ath_rate_sample
device wi
device loop
-device random
device ether
device tun
device pty
diff --git a/tools/tools/tinybsd/conf/bridge/TINYBSD b/tools/tools/tinybsd/conf/bridge/TINYBSD
index 0788aea40e44..5d99ad95700d 100644
--- a/tools/tools/tinybsd/conf/bridge/TINYBSD
+++ b/tools/tools/tinybsd/conf/bridge/TINYBSD
@@ -130,7 +130,6 @@ device wi # WaveLAN/Intersil/Symbol 802.11 wireless NICs.
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
diff --git a/tools/tools/tinybsd/conf/default/TINYBSD b/tools/tools/tinybsd/conf/default/TINYBSD
index 6052764b3f81..841a19e8ee49 100644
--- a/tools/tools/tinybsd/conf/default/TINYBSD
+++ b/tools/tools/tinybsd/conf/default/TINYBSD
@@ -140,7 +140,6 @@ device wi # WaveLAN/Intersil/Symbol 802.11 wireless NICs.
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device ppp # Kernel PPP
device tun # Packet tunnel.
diff --git a/tools/tools/tinybsd/conf/firewall/TINYBSD b/tools/tools/tinybsd/conf/firewall/TINYBSD
index f410c139e371..994280346bbd 100644
--- a/tools/tools/tinybsd/conf/firewall/TINYBSD
+++ b/tools/tools/tinybsd/conf/firewall/TINYBSD
@@ -129,7 +129,6 @@ device wlan # 802.11 support
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
diff --git a/tools/tools/tinybsd/conf/minimal/TINYBSD b/tools/tools/tinybsd/conf/minimal/TINYBSD
index 2cd1f9af9ae6..74e3c0506bcf 100644
--- a/tools/tools/tinybsd/conf/minimal/TINYBSD
+++ b/tools/tools/tinybsd/conf/minimal/TINYBSD
@@ -65,7 +65,6 @@ device pmtimer
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
diff --git a/tools/tools/tinybsd/conf/vpn/TINYBSD b/tools/tools/tinybsd/conf/vpn/TINYBSD
index 956c13b00413..4fd064ef8fc7 100644
--- a/tools/tools/tinybsd/conf/vpn/TINYBSD
+++ b/tools/tools/tinybsd/conf/vpn/TINYBSD
@@ -130,7 +130,6 @@ device xe # Xircom pccard Ethernet
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device ppp # Kernel PPP
device tun # Packet tunnel.
diff --git a/tools/tools/tinybsd/conf/wireless/TINYBSD b/tools/tools/tinybsd/conf/wireless/TINYBSD
index aa7ddceb7895..afcd47ca4462 100644
--- a/tools/tools/tinybsd/conf/wireless/TINYBSD
+++ b/tools/tools/tinybsd/conf/wireless/TINYBSD
@@ -136,7 +136,6 @@ device wi # WaveLAN/Intersil/Symbol 802.11 wireless NICs.
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device pty # Pseudo-ttys (telnet etc)
device md # Memory "disks"
diff --git a/tools/tools/tinybsd/conf/wrap/TINYBSD b/tools/tools/tinybsd/conf/wrap/TINYBSD
index c3ce7954b278..2ef7c6742cbd 100644
--- a/tools/tools/tinybsd/conf/wrap/TINYBSD
+++ b/tools/tools/tinybsd/conf/wrap/TINYBSD
@@ -102,7 +102,6 @@ device ath_rate_sample
# Pseudo devices.
device loop # Network loopback
-device random # Entropy device
device ether # Ethernet support
device ppp # Kernel PPP
device tun # Packet tunnel.
diff --git a/usr.bin/calendar/calendars/hr_HR.ISO8859-2/calendar.praznici b/usr.bin/calendar/calendars/hr_HR.ISO8859-2/calendar.praznici
index 60ae5e30bd2f..491ec6a4f3f3 100644
--- a/usr.bin/calendar/calendars/hr_HR.ISO8859-2/calendar.praznici
+++ b/usr.bin/calendar/calendars/hr_HR.ISO8859-2/calendar.praznici
@@ -10,31 +10,31 @@
LANG=hr_HR.ISO8859-2
/* dr¾avni praznici */
-01/01 Nova godina
-05/01 Praznik rada
-05/30 Tjelovo
-06/22 Dan antifa¹istièke borbe
-06/25 Dan dr¾avnosti
-08/05 Dan domovinske zahvalnosti
-10/08 Dan neovisnosti
-
-/* katolièki blagdani */
-01/06 Sveta tri kralja
-Easter-2 Veliki petak
+01/01 Nova godina
+01/06 Bogojavljenje ili Sveta tri kralja
Easter Uskrs
Easter+1 Uskrsni ponedjeljak
-Easter+49 Duhovi
-Easter+50 Duhovni ponedjeljak
-Easter+39 Uza¹a¹æe
+05/01 Praznik rada
+Easter+60 Tijelovo
+06/22 Dan antifa¹istièke borbe
+06/25 Dan dr¾avnosti
+08/05 Dan pobjede i domovinske zahvalnosti i Dan hrvatskih branitelja
08/15 Velika Gospa
+10/08 Dan neovisnosti
11/01 Svi sveti
12/25 Bo¾iæ
-12/26 Stjepandan
+12/26 Sveti Stjepan
+
+/* katolièki blagdani */
+Easter-2 Veliki petak
+Easter+39 Uza¹a¹æe
+Easter+49 Duhovi
+Easter+50 Duhovni ponedjeljak
/* godi¹nja doba */
03/21* Poèetak proljeæa
06/21* Poèetak ljeta
-09/21* Poèetak jesena
+09/23* Poèetak jeseni
12/21* Poèetak zime
/* ljetno vrijeme */
diff --git a/usr.bin/top/display.c b/usr.bin/top/display.c
index 539ddb4d536e..00534fd7f411 100644
--- a/usr.bin/top/display.c
+++ b/usr.bin/top/display.c
@@ -675,6 +675,9 @@ i_swap(int *stats)
{
swap_buffer = setup_buffer(swap_buffer, 0);
+ if (swap_names == NULL)
+ return;
+
fputs("\nSwap: ", stdout);
lastline++;
@@ -690,6 +693,9 @@ u_swap(int *stats)
new = setup_buffer(new, 0);
+ if (swap_names == NULL)
+ return;
+
/* format the new line */
summary_format(new, stats, swap_names);
line_update(swap_buffer, new, x_swap, y_swap);
diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c
index 563efc624e24..dd2b7a110419 100644
--- a/usr.bin/top/machine.c
+++ b/usr.bin/top/machine.c
@@ -150,6 +150,7 @@ static const char *swapnames[] = {
};
static int swap_stats[nitems(swapnames)];
+static int has_swap;
/* these are for keeping track of the proc array */
@@ -248,12 +249,12 @@ update_layout(void)
y_mem = 3;
y_arc = 4;
y_carc = 5;
- y_swap = 4 + arc_enabled + carc_enabled;
- y_idlecursor = 5 + arc_enabled + carc_enabled;
- y_message = 5 + arc_enabled + carc_enabled;
- y_header = 6 + arc_enabled + carc_enabled;
- y_procs = 7 + arc_enabled + carc_enabled;
- Header_lines = 7 + arc_enabled + carc_enabled;
+ y_swap = 3 + arc_enabled + carc_enabled + has_swap;
+ y_idlecursor = 4 + arc_enabled + carc_enabled + has_swap;
+ y_message = 4 + arc_enabled + carc_enabled + has_swap;
+ y_header = 5 + arc_enabled + carc_enabled + has_swap;
+ y_procs = 6 + arc_enabled + carc_enabled + has_swap;
+ Header_lines = 6 + arc_enabled + carc_enabled + has_swap;
if (pcpu_stats) {
y_mem += ncpus - 1;
@@ -273,7 +274,7 @@ machine_init(struct statics *statics)
{
int i, j, empty, pagesize;
uint64_t arc_size;
- int carc_en;
+ int carc_en, nswapdev;
size_t size;
size = sizeof(smpmode);
@@ -298,6 +299,11 @@ machine_init(struct statics *statics)
if (kd == NULL)
return (-1);
+ size = sizeof(nswapdev);
+ if (sysctlbyname("vm.nswapdev", &nswapdev, &size, NULL,
+ 0) == 0 && nswapdev != 0)
+ has_swap = 1;
+
GETSYSCTL("kern.ccpu", ccpu);
/* this is used in calculating WCPU -- calculate it ahead of time */
@@ -332,7 +338,10 @@ machine_init(struct statics *statics)
statics->carc_names = carcnames;
else
statics->carc_names = NULL;
- statics->swap_names = swapnames;
+ if (has_swap)
+ statics->swap_names = swapnames;
+ else
+ statics->swap_names = NULL;
statics->order_names = ordernames;
/* Allocate state for per-CPU stats. */
diff --git a/usr.bin/uname/uname.1 b/usr.bin/uname/uname.1
index 2a5a03f5162f..a3ccc893c1a9 100644
--- a/usr.bin/uname/uname.1
+++ b/usr.bin/uname/uname.1
@@ -28,7 +28,7 @@
.\" @(#)uname.1 8.3 (Berkeley) 4/8/94
.\" $FreeBSD$
.\"
-.Dd May 31, 2017
+.Dd June 27, 2019
.Dt UNAME 1
.Os
.Sh NAME
@@ -36,7 +36,7 @@
.Nd display information about the system
.Sh SYNOPSIS
.Nm
-.Op Fl aiKmnoprsUv
+.Op Fl abiKmnoprsUv
.Sh DESCRIPTION
The
.Nm
@@ -53,6 +53,8 @@ Behave as though the options
and
.Fl v
were specified.
+.It Fl b
+Write the kernel's linker-generated build-id to standard output.
.It Fl i
Write the kernel ident to standard output.
.It Fl K
@@ -152,3 +154,7 @@ and
.Fl U
extension flags appeared in
.Fx 10.0 .
+The
+.Fl b
+extension flag appeared in
+.Fx 13.0 .
diff --git a/usr.bin/uname/uname.c b/usr.bin/uname/uname.c
index c3bf57303b3c..e97b9c3cb744 100644
--- a/usr.bin/uname/uname.c
+++ b/usr.bin/uname/uname.c
@@ -67,9 +67,10 @@ static const char sccsid[] = "@(#)uname.c 8.2 (Berkeley) 5/4/95";
#define IFLAG 0x40
#define UFLAG 0x80
#define KFLAG 0x100
+#define BFLAG 0x200
typedef void (*get_t)(void);
-static get_t get_ident, get_platform, get_hostname, get_arch,
+static get_t get_buildid, get_ident, get_platform, get_hostname, get_arch,
get_release, get_sysname, get_kernvers, get_uservers, get_version;
static void native_ident(void);
@@ -81,11 +82,13 @@ static void native_sysname(void);
static void native_version(void);
static void native_kernvers(void);
static void native_uservers(void);
+static void native_buildid(void);
static void print_uname(u_int);
static void setup_get(void);
static void usage(void);
-static char *ident, *platform, *hostname, *arch, *release, *sysname, *version, *kernvers, *uservers;
+static char *buildid, *ident, *platform, *hostname, *arch, *release, *sysname,
+ *version, *kernvers, *uservers;
static int space;
int
@@ -97,11 +100,14 @@ main(int argc, char *argv[])
setup_get();
flags = 0;
- while ((ch = getopt(argc, argv, "aiKmnoprsUv")) != -1)
+ while ((ch = getopt(argc, argv, "abiKmnoprsUv")) != -1)
switch(ch) {
case 'a':
flags |= (MFLAG | NFLAG | RFLAG | SFLAG | VFLAG);
break;
+ case 'b':
+ flags |= BFLAG;
+ break;
case 'i':
flags |= IFLAG;
break;
@@ -169,6 +175,7 @@ setup_get(void)
CHECK_ENV("i", ident);
CHECK_ENV("K", kernvers);
CHECK_ENV("U", uservers);
+ CHECK_ENV("b", buildid);
}
#define PRINT_FLAG(flags,flag,var) \
@@ -194,6 +201,7 @@ print_uname(u_int flags)
PRINT_FLAG(flags, IFLAG, ident);
PRINT_FLAG(flags, KFLAG, kernvers);
PRINT_FLAG(flags, UFLAG, uservers);
+ PRINT_FLAG(flags, BFLAG, buildid);
printf("\n");
}
@@ -261,6 +269,9 @@ NATIVE_SYSCTL2_GET(arch, CTL_HW, HW_MACHINE_ARCH) {
NATIVE_SYSCTLNAME_GET(ident, "kern.ident") {
} NATIVE_SET;
+NATIVE_SYSCTLNAME_GET(buildid, "kern.build_id") {
+} NATIVE_SET;
+
static void
native_uservers(void)
{
@@ -282,6 +293,6 @@ native_kernvers(void)
static void
usage(void)
{
- fprintf(stderr, "usage: uname [-aiKmnoprsUv]\n");
+ fprintf(stderr, "usage: uname [-abiKmnoprsUv]\n");
exit(1);
}
diff --git a/usr.bin/vtfontcvt/vtfontcvt.c b/usr.bin/vtfontcvt/vtfontcvt.c
index 70ec7cf31812..e34308d5d365 100644
--- a/usr.bin/vtfontcvt/vtfontcvt.c
+++ b/usr.bin/vtfontcvt/vtfontcvt.c
@@ -335,9 +335,11 @@ parse_bdf(FILE *fp, unsigned int map_idx)
break;
}
}
- } else if (strncmp(ln, "FONTBOUNDINGBOX ", 16) == 0 &&
- sscanf(ln + 16, "%d %d %d %d", &fbbw, &fbbh, &fbbox,
- &fbboy) == 4) {
+ } else if (strncmp(ln, "FONTBOUNDINGBOX ", 16) == 0) {
+ if (sscanf(ln + 16, "%d %d %d %d", &fbbw, &fbbh, &fbbox,
+ &fbboy) != 4)
+ errx(1, "invalid FONTBOUNDINGBOX at line %u",
+ linenum);
set_width(fbbw);
set_height(fbbh);
break;
@@ -353,8 +355,9 @@ parse_bdf(FILE *fp, unsigned int map_idx)
linenum++;
ln[length - 1] = '\0';
- if (strncmp(ln, "DWIDTH ", 7) == 0 &&
- sscanf(ln + 7, "%d %d", &dwidth, &dwy) == 2) {
+ if (strncmp(ln, "DWIDTH ", 7) == 0) {
+ if (sscanf(ln + 7, "%d %d", &dwidth, &dwy) != 2)
+ errx(1, "invalid DWIDTH at line %u", linenum);
if (dwy != 0 || (dwidth != fbbw && dwidth * 2 != fbbw))
errx(1, "bitmap with unsupported DWIDTH %d %d at line %u",
dwidth, dwy, linenum);
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index d52364bac84e..508573b23bc1 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -166,8 +166,6 @@ SUBDIR.${MK_NS_CACHING}+= nscd
SUBDIR.${MK_LPR}+= lpr
SUBDIR.${MK_MAN_UTILS}+= manctl
SUBDIR.${MK_MLX5TOOL}+= mlx5tool
-SUBDIR.${MK_NAND}+= nandsim
-SUBDIR.${MK_NAND}+= nandtool
SUBDIR.${MK_NETGRAPH}+= flowctl
SUBDIR.${MK_NETGRAPH}+= ngctl
SUBDIR.${MK_NETGRAPH}+= nghook
diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile
index 85fdf11928b1..e203a57c18a3 100644
--- a/usr.sbin/bhyve/Makefile
+++ b/usr.sbin/bhyve/Makefile
@@ -16,6 +16,7 @@ BHYVE_SYSDIR?=${SRCTOP}
SRCS= \
atkbdc.c \
acpi.c \
+ audio.c \
bhyvegc.c \
bhyverun.c \
block_if.c \
@@ -27,6 +28,7 @@ SRCS= \
dbgport.c \
fwctl.c \
gdb.c \
+ hda_codec.c \
inout.c \
ioapic.c \
mem.c \
@@ -36,6 +38,7 @@ SRCS= \
pci_ahci.c \
pci_e82545.c \
pci_emul.c \
+ pci_hda.c \
pci_fbuf.c \
pci_hostbridge.c \
pci_irq.c \
diff --git a/usr.sbin/bhyve/audio.c b/usr.sbin/bhyve/audio.c
new file mode 100644
index 000000000000..dda575813332
--- /dev/null
+++ b/usr.sbin/bhyve/audio.c
@@ -0,0 +1,284 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2016 Alex Teaca <iateaca@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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$");
+
+#ifndef WITHOUT_CAPSICUM
+#include <sys/capsicum.h>
+#include <capsicum_helpers.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <err.h>
+#include <sysexits.h>
+
+#include "audio.h"
+#include "pci_hda.h"
+
+/*
+ * Audio Player internal data structures
+ */
+
+struct audio {
+ int fd;
+ uint8_t dir;
+ uint8_t inited;
+ char dev_name[64];
+};
+
+/*
+ * Audio Player module function definitions
+ */
+
+/*
+ * audio_init - initialize an instance of audio player
+ * @dev_name - the backend sound device used to play / capture
+ * @dir - dir = 1 for write mode, dir = 0 for read mode
+ */
+struct audio *
+audio_init(const char *dev_name, uint8_t dir)
+{
+ struct audio *aud = NULL;
+#ifndef WITHOUT_CAPSICUM
+ cap_rights_t rights;
+ cap_ioctl_t cmds[] = {
+ SNDCTL_DSP_RESET, SNDCTL_DSP_SETFMT, SNDCTL_DSP_CHANNELS,
+ SNDCTL_DSP_SPEED,
+#ifdef DEBUG_HDA
+ SNDCTL_DSP_GETOSPACE, SNDCTL_DSP_GETISPACE,
+#endif
+ };
+#endif
+
+ assert(dev_name);
+
+ aud = calloc(1, sizeof(*aud));
+ if (!aud)
+ return NULL;
+
+ if (strlen(dev_name) < sizeof(aud->dev_name))
+ memcpy(aud->dev_name, dev_name, strlen(dev_name) + 1);
+ else {
+ DPRINTF("dev_name too big\n");
+ free(aud);
+ return NULL;
+ }
+
+ aud->dir = dir;
+
+ aud->fd = open(aud->dev_name, aud->dir ? O_WRONLY : O_RDONLY, 0);
+ if (aud->fd == -1) {
+ DPRINTF("Failed to open dev: %s, errno: %d\n",
+ aud->dev_name, errno);
+ return (NULL);
+ }
+
+#ifndef WITHOUT_CAPSICUM
+ cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_WRITE);
+ if (caph_rights_limit(aud->fd, &rights) == -1)
+ errx(EX_OSERR, "Unable to apply rights for sandbox");
+ if (caph_ioctls_limit(aud->fd, cmds, nitems(cmds)) == -1)
+ errx(EX_OSERR, "Unable to limit ioctl rights for sandbox");
+#endif
+
+ return aud;
+}
+
+/*
+ * audio_set_params - reset the sound device and set the audio params
+ * @aud - the audio player to be configured
+ * @params - the audio parameters to be set
+ */
+int
+audio_set_params(struct audio *aud, struct audio_params *params)
+{
+ int audio_fd;
+ int format, channels, rate;
+ int err;
+#if DEBUG_HDA == 1
+ audio_buf_info info;
+#endif
+
+ assert(aud);
+ assert(params);
+
+ if ((audio_fd = aud->fd) < 0) {
+ DPRINTF("Incorrect audio device descriptor for %s\n",
+ aud->dev_name);
+ return (-1);
+ }
+
+ /* Reset the device if it was previously opened */
+ if (aud->inited) {
+ err = ioctl(audio_fd, SNDCTL_DSP_RESET, NULL);
+ if (err == -1) {
+ DPRINTF("Failed to reset fd: %d, errno: %d\n",
+ aud->fd, errno);
+ return (-1);
+ }
+ } else
+ aud->inited = 1;
+
+ /* Set the Format (Bits per Sample) */
+ format = params->format;
+ err = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format);
+ if (err == -1) {
+ DPRINTF("Fail to set fmt: 0x%x errno: %d\n",
+ params->format, errno);
+ return -1;
+ }
+
+ /* The device does not support the requested audio format */
+ if (format != params->format) {
+ DPRINTF("Mismatch format: 0x%x params->format: 0x%x\n",
+ format, params->format);
+ return -1;
+ }
+
+ /* Set the Number of Channels */
+ channels = params->channels;
+ err = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels);
+ if (err == -1) {
+ DPRINTF("Fail to set channels: %d errno: %d\n",
+ params->channels, errno);
+ return -1;
+ }
+
+ /* The device does not support the requested no. of channels */
+ if (channels != params->channels) {
+ DPRINTF("Mismatch channels: %d params->channels: %d\n",
+ channels, params->channels);
+ return -1;
+ }
+
+ /* Set the Sample Rate / Speed */
+ rate = params->rate;
+ err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate);
+ if (err == -1) {
+ DPRINTF("Fail to set speed: %d errno: %d\n",
+ params->rate, errno);
+ return -1;
+ }
+
+ /* The device does not support the requested rate / speed */
+ if (rate != params->rate) {
+ DPRINTF("Mismatch rate: %d params->rate: %d\n",
+ rate, params->rate);
+ return -1;
+ }
+
+#if DEBUG_HDA == 1
+ err = ioctl(audio_fd, aud->dir ? SNDCTL_DSP_GETOSPACE :
+ SNDCTL_DSP_GETISPACE, &info);
+ if (err == -1) {
+ DPRINTF("Fail to get audio buf info errno: %d\n", errno);
+ return -1;
+ }
+ DPRINTF("fragstotal: 0x%x fragsize: 0x%x\n",
+ info.fragstotal, info.fragsize);
+#endif
+ return 0;
+}
+
+/*
+ * audio_playback - plays samples to the sound device using blocking operations
+ * @aud - the audio player used to play the samples
+ * @buf - the buffer containing the samples
+ * @count - the number of bytes in buffer
+ */
+int
+audio_playback(struct audio *aud, const void *buf, size_t count)
+{
+ int audio_fd = -1;
+ ssize_t len = 0, total = 0;
+
+ assert(aud);
+ assert(aud->dir);
+ assert(buf);
+
+ audio_fd = aud->fd;
+ assert(audio_fd != -1);
+
+ total = 0;
+ while (total < count) {
+ len = write(audio_fd, buf + total, count - total);
+ if (len == -1) {
+ DPRINTF("Fail to write to fd: %d, errno: %d\n",
+ audio_fd, errno);
+ return -1;
+ }
+
+ total += len;
+ }
+
+ return 0;
+}
+
+/*
+ * audio_record - records samples from the sound device using
+ * blocking operations.
+ * @aud - the audio player used to capture the samples
+ * @buf - the buffer to receive the samples
+ * @count - the number of bytes to capture in buffer
+ * Returns -1 on error and 0 on success
+ */
+int
+audio_record(struct audio *aud, void *buf, size_t count)
+{
+ int audio_fd = -1;
+ ssize_t len = 0, total = 0;
+
+ assert(aud);
+ assert(!aud->dir);
+ assert(buf);
+
+ audio_fd = aud->fd;
+ assert(audio_fd != -1);
+
+ total = 0;
+ while (total < count) {
+ len = read(audio_fd, buf + total, count - total);
+ if (len == -1) {
+ DPRINTF("Fail to write to fd: %d, errno: %d\n",
+ audio_fd, errno);
+ return -1;
+ }
+
+ total += len;
+ }
+
+ return 0;
+}
diff --git a/usr.sbin/bhyve/audio.h b/usr.sbin/bhyve/audio.h
new file mode 100644
index 000000000000..2b559a43e5df
--- /dev/null
+++ b/usr.sbin/bhyve/audio.h
@@ -0,0 +1,88 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2016 Alex Teaca <iateaca@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 _AUDIO_EMUL_H_
+#define _AUDIO_EMUL_H_
+
+#include <sys/types.h>
+#include <sys/soundcard.h>
+
+/*
+ * Audio Player data structures
+ */
+
+struct audio;
+
+struct audio_params {
+ int channels;
+ int format;
+ int rate;
+};
+
+/*
+ * Audio Player API
+ */
+
+/*
+ * audio_init - initialize an instance of audio player
+ * @dev_name - the backend sound device used to play / capture
+ * @dir - dir = 1 for write mode, dir = 0 for read mode
+ * Returns NULL on error and the address of the audio player instance
+ */
+struct audio *audio_init(const char *dev_name, uint8_t dir);
+
+/*
+ * audio_set_params - reset the sound device and set the audio params
+ * @aud - the audio player to be configured
+ * @params - the audio parameters to be set
+ * Returns -1 on error and 0 on success
+ */
+int audio_set_params(struct audio *aud, struct audio_params *params);
+
+/*
+ * audio_playback - plays samples to the sound device using blocking operations
+ * @aud - the audio player used to play the samples
+ * @buf - the buffer containing the samples
+ * @count - the number of bytes in buffer
+ * Returns -1 on error and 0 on success
+ */
+int audio_playback(struct audio *aud, const void *buf, size_t count);
+
+/*
+ * audio_record - records samples from the sound device using blocking
+ * operations.
+ * @aud - the audio player used to capture the samples
+ * @buf - the buffer to receive the samples
+ * @count - the number of bytes to capture in buffer
+ * Returns -1 on error and 0 on success
+ */
+int audio_record(struct audio *aud, void *buf, size_t count);
+
+#endif /* _AUDIO_EMUL_H_ */
diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8
index 2f2236e8ce38..3ab9e4e67dde 100644
--- a/usr.sbin/bhyve/bhyve.8
+++ b/usr.sbin/bhyve/bhyve.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 11, 2018
+.Dd June 24, 2019
.Dt BHYVE 8
.Os
.Sh NAME
@@ -248,6 +248,8 @@ Raw framebuffer device attached to VNC server.
eXtensible Host Controller Interface (xHCI) USB controller.
.It Li nvme
NVM Express (NVMe) controller.
+.It Li hda
+High Definition Audio Controller.
.El
.It Op Ar conf
This optional parameter describes the backend for device emulations.
@@ -475,6 +477,16 @@ Sector size (defaults to blockif sector size).
.It Li ser
Serial number with maximum 20 characters.
.El
+.Pp
+HD Audio devices:
+.Bl -tag -width 10n
+.It Li play
+Playback device, typically
+.Ar /dev/dsp0 .
+.It Li rec
+Recording device, typically
+.Ar /dev/dsp0 .
+.El
.El
.It Fl S
Wire guest memory.
diff --git a/usr.sbin/bhyve/hda_codec.c b/usr.sbin/bhyve/hda_codec.c
new file mode 100644
index 000000000000..82f5fb1eed92
--- /dev/null
+++ b/usr.sbin/bhyve/hda_codec.c
@@ -0,0 +1,952 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2016 Alex Teaca <iateaca@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 <pthread.h>
+#include <pthread_np.h>
+#include <unistd.h>
+
+#include "pci_hda.h"
+#include "audio.h"
+
+/*
+ * HDA Codec defines
+ */
+#define INTEL_VENDORID 0x8086
+
+#define HDA_CODEC_SUBSYSTEM_ID ((INTEL_VENDORID << 16) | 0x01)
+#define HDA_CODEC_ROOT_NID 0x00
+#define HDA_CODEC_FG_NID 0x01
+#define HDA_CODEC_AUDIO_OUTPUT_NID 0x02
+#define HDA_CODEC_PIN_OUTPUT_NID 0x03
+#define HDA_CODEC_AUDIO_INPUT_NID 0x04
+#define HDA_CODEC_PIN_INPUT_NID 0x05
+
+#define HDA_CODEC_STREAMS_COUNT 0x02
+#define HDA_CODEC_STREAM_OUTPUT 0x00
+#define HDA_CODEC_STREAM_INPUT 0x01
+
+#define HDA_CODEC_PARAMS_COUNT 0x14
+#define HDA_CODEC_CONN_LIST_COUNT 0x01
+#define HDA_CODEC_RESPONSE_EX_UNSOL 0x10
+#define HDA_CODEC_RESPONSE_EX_SOL 0x00
+#define HDA_CODEC_AMP_NUMSTEPS 0x4a
+
+#define HDA_CODEC_SUPP_STREAM_FORMATS_PCM \
+ (1 << HDA_PARAM_SUPP_STREAM_FORMATS_PCM_SHIFT)
+
+#define HDA_CODEC_FMT_BASE_MASK (0x01 << 14)
+
+#define HDA_CODEC_FMT_MULT_MASK (0x07 << 11)
+#define HDA_CODEC_FMT_MULT_2 (0x01 << 11)
+#define HDA_CODEC_FMT_MULT_3 (0x02 << 11)
+#define HDA_CODEC_FMT_MULT_4 (0x03 << 11)
+
+#define HDA_CODEC_FMT_DIV_MASK 0x07
+#define HDA_CODEC_FMT_DIV_SHIFT 8
+
+#define HDA_CODEC_FMT_BITS_MASK (0x07 << 4)
+#define HDA_CODEC_FMT_BITS_8 (0x00 << 4)
+#define HDA_CODEC_FMT_BITS_16 (0x01 << 4)
+#define HDA_CODEC_FMT_BITS_24 (0x03 << 4)
+#define HDA_CODEC_FMT_BITS_32 (0x04 << 4)
+
+#define HDA_CODEC_FMT_CHAN_MASK (0x0f << 0)
+
+#define HDA_CODEC_AUDIO_WCAP_OUTPUT \
+ (0x00 << HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
+#define HDA_CODEC_AUDIO_WCAP_INPUT \
+ (0x01 << HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
+#define HDA_CODEC_AUDIO_WCAP_PIN \
+ (0x04 << HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
+#define HDA_CODEC_AUDIO_WCAP_CONN_LIST \
+ (1 << HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_SHIFT)
+#define HDA_CODEC_AUDIO_WCAP_FORMAT_OVR \
+ (1 << HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR_SHIFT)
+#define HDA_CODEC_AUDIO_WCAP_AMP_OVR \
+ (1 << HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR_SHIFT)
+#define HDA_CODEC_AUDIO_WCAP_OUT_AMP \
+ (1 << HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP_SHIFT)
+#define HDA_CODEC_AUDIO_WCAP_IN_AMP \
+ (1 << HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP_SHIFT)
+#define HDA_CODEC_AUDIO_WCAP_STEREO \
+ (1 << HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_SHIFT)
+
+#define HDA_CODEC_PIN_CAP_OUTPUT \
+ (1 << HDA_PARAM_PIN_CAP_OUTPUT_CAP_SHIFT)
+#define HDA_CODEC_PIN_CAP_INPUT \
+ (1 << HDA_PARAM_PIN_CAP_INPUT_CAP_SHIFT)
+#define HDA_CODEC_PIN_CAP_PRESENCE_DETECT \
+ (1 << HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP_SHIFT)
+
+#define HDA_CODEC_OUTPUT_AMP_CAP_MUTE_CAP \
+ (1 << HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP_SHIFT)
+#define HDA_CODEC_OUTPUT_AMP_CAP_STEPSIZE \
+ (0x03 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT)
+#define HDA_CODEC_OUTPUT_AMP_CAP_NUMSTEPS \
+ (HDA_CODEC_AMP_NUMSTEPS << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT)
+#define HDA_CODEC_OUTPUT_AMP_CAP_OFFSET \
+ (HDA_CODEC_AMP_NUMSTEPS << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT)
+
+#define HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE 0x80
+#define HDA_CODEC_SET_AMP_GAIN_MUTE_GAIN_MASK 0x7f
+
+#define HDA_CODEC_PIN_SENSE_PRESENCE_PLUGGED (1 << 31)
+#define HDA_CODEC_PIN_WIDGET_CTRL_OUT_ENABLE \
+ (1 << HDA_CMD_GET_PIN_WIDGET_CTRL_OUT_ENABLE_SHIFT)
+#define HDA_CODEC_PIN_WIDGET_CTRL_IN_ENABLE \
+ (1 << HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE_SHIFT)
+
+#define HDA_CONFIG_DEFAULTCONF_COLOR_BLACK \
+ (0x01 << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT)
+#define HDA_CONFIG_DEFAULTCONF_COLOR_RED \
+ (0x05 << HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT)
+
+#define HDA_CODEC_BUF_SIZE HDA_FIFO_SIZE
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+
+/*
+ * HDA Audio Context data structures
+ */
+
+typedef void (*transfer_func_t)(void *arg);
+typedef int (*setup_func_t)(void *arg);
+
+struct hda_audio_ctxt {
+ char name[64];
+ uint8_t run;
+ uint8_t started;
+ void *priv;
+ pthread_t tid;
+ pthread_mutex_t mtx;
+ pthread_cond_t cond;
+ setup_func_t do_setup;
+ transfer_func_t do_transfer;
+};
+
+/*
+ * HDA Audio Context module function declarations
+ */
+
+static void *hda_audio_ctxt_thr(void *arg);
+static int hda_audio_ctxt_init(struct hda_audio_ctxt *actx, const char *tname,
+ transfer_func_t do_transfer, setup_func_t do_setup, void *priv);
+static int hda_audio_ctxt_start(struct hda_audio_ctxt *actx);
+static int hda_audio_ctxt_stop(struct hda_audio_ctxt *actx);
+
+/*
+ * HDA Codec data structures
+ */
+
+struct hda_codec_softc;
+
+typedef uint32_t (*verb_func_t)(struct hda_codec_softc *sc, uint16_t verb,
+ uint16_t payload);
+
+struct hda_codec_stream {
+ uint8_t buf[HDA_CODEC_BUF_SIZE];
+ uint8_t channel;
+ uint16_t fmt;
+ uint8_t stream;
+
+ uint8_t left_gain;
+ uint8_t right_gain;
+ uint8_t left_mute;
+ uint8_t right_mute;
+
+ struct audio *aud;
+ struct hda_audio_ctxt actx;
+};
+
+struct hda_codec_softc {
+ uint32_t no_nodes;
+ uint32_t subsystem_id;
+ const uint32_t (*get_parameters)[HDA_CODEC_PARAMS_COUNT];
+ const uint8_t (*conn_list)[HDA_CODEC_CONN_LIST_COUNT];
+ const uint32_t *conf_default;
+ const uint8_t *pin_ctrl_default;
+ const verb_func_t *verb_handlers;
+
+ struct hda_codec_inst *hci;
+ struct hda_codec_stream streams[HDA_CODEC_STREAMS_COUNT];
+};
+
+/*
+ * HDA Codec module function declarations
+ */
+static int hda_codec_init(struct hda_codec_inst *hci, const char *play,
+ const char *rec, const char *opts);
+static int hda_codec_reset(struct hda_codec_inst *hci);
+static int hda_codec_command(struct hda_codec_inst *hci, uint32_t cmd_data);
+static int hda_codec_notify(struct hda_codec_inst *hci, uint8_t run,
+ uint8_t stream, uint8_t dir);
+
+static int hda_codec_parse_format(uint16_t fmt, struct audio_params *params);
+
+static uint32_t hda_codec_audio_output_nid(struct hda_codec_softc *sc,
+ uint16_t verb, uint16_t payload);
+static void hda_codec_audio_output_do_transfer(void *arg);
+static int hda_codec_audio_output_do_setup(void *arg);
+static uint32_t hda_codec_audio_input_nid(struct hda_codec_softc *sc,
+ uint16_t verb, uint16_t payload);
+static void hda_codec_audio_input_do_transfer(void *arg);
+static int hda_codec_audio_input_do_setup(void *arg);
+
+static uint32_t hda_codec_audio_inout_nid(struct hda_codec_stream *st,
+ uint16_t verb, uint16_t payload);
+
+/*
+ * HDA Codec global data
+ */
+
+#define HDA_CODEC_ROOT_DESC \
+ [HDA_CODEC_ROOT_NID] = { \
+ [HDA_PARAM_VENDOR_ID] = INTEL_VENDORID, \
+ [HDA_PARAM_REVISION_ID] = 0xffff, \
+ /* 1 Subnode, StartNid = 1 */ \
+ [HDA_PARAM_SUB_NODE_COUNT] = 0x00010001, \
+ }, \
+
+#define HDA_CODEC_FG_COMMON_DESC \
+ [HDA_PARAM_FCT_GRP_TYPE] = HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO,\
+ /* B8 - B32, 8.0 - 192.0kHz */ \
+ [HDA_PARAM_SUPP_PCM_SIZE_RATE] = (0x1f << 16) | 0x7ff, \
+ [HDA_PARAM_SUPP_STREAM_FORMATS] = HDA_CODEC_SUPP_STREAM_FORMATS_PCM,\
+ [HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
+ [HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
+ [HDA_PARAM_GPIO_COUNT] = 0x00, \
+
+#define HDA_CODEC_FG_OUTPUT_DESC \
+ [HDA_CODEC_FG_NID] = { \
+ /* 2 Subnodes, StartNid = 2 */ \
+ [HDA_PARAM_SUB_NODE_COUNT] = 0x00020002, \
+ HDA_CODEC_FG_COMMON_DESC \
+ }, \
+
+#define HDA_CODEC_FG_INPUT_DESC \
+ [HDA_CODEC_FG_NID] = { \
+ /* 2 Subnodes, StartNid = 4 */ \
+ [HDA_PARAM_SUB_NODE_COUNT] = 0x00040002, \
+ HDA_CODEC_FG_COMMON_DESC \
+ }, \
+
+#define HDA_CODEC_FG_DUPLEX_DESC \
+ [HDA_CODEC_FG_NID] = { \
+ /* 4 Subnodes, StartNid = 2 */ \
+ [HDA_PARAM_SUB_NODE_COUNT] = 0x00020004, \
+ HDA_CODEC_FG_COMMON_DESC \
+ }, \
+
+#define HDA_CODEC_OUTPUT_DESC \
+ [HDA_CODEC_AUDIO_OUTPUT_NID] = { \
+ [HDA_PARAM_AUDIO_WIDGET_CAP] = \
+ HDA_CODEC_AUDIO_WCAP_OUTPUT | \
+ HDA_CODEC_AUDIO_WCAP_FORMAT_OVR | \
+ HDA_CODEC_AUDIO_WCAP_AMP_OVR | \
+ HDA_CODEC_AUDIO_WCAP_OUT_AMP | \
+ HDA_CODEC_AUDIO_WCAP_STEREO, \
+ /* B16, 16.0 - 192.0kHz */ \
+ [HDA_PARAM_SUPP_PCM_SIZE_RATE] = (0x02 << 16) | 0x7fc, \
+ [HDA_PARAM_SUPP_STREAM_FORMATS] = \
+ HDA_CODEC_SUPP_STREAM_FORMATS_PCM, \
+ [HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
+ [HDA_PARAM_CONN_LIST_LENGTH] = 0x00, \
+ [HDA_PARAM_OUTPUT_AMP_CAP] = \
+ HDA_CODEC_OUTPUT_AMP_CAP_MUTE_CAP | \
+ HDA_CODEC_OUTPUT_AMP_CAP_STEPSIZE | \
+ HDA_CODEC_OUTPUT_AMP_CAP_NUMSTEPS | \
+ HDA_CODEC_OUTPUT_AMP_CAP_OFFSET, \
+ }, \
+ [HDA_CODEC_PIN_OUTPUT_NID] = { \
+ [HDA_PARAM_AUDIO_WIDGET_CAP] = \
+ HDA_CODEC_AUDIO_WCAP_PIN | \
+ HDA_CODEC_AUDIO_WCAP_CONN_LIST | \
+ HDA_CODEC_AUDIO_WCAP_STEREO, \
+ [HDA_PARAM_PIN_CAP] = HDA_CODEC_PIN_CAP_OUTPUT | \
+ HDA_CODEC_PIN_CAP_PRESENCE_DETECT,\
+ [HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
+ [HDA_PARAM_CONN_LIST_LENGTH] = 0x01, \
+ [HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
+ }, \
+
+#define HDA_CODEC_INPUT_DESC \
+ [HDA_CODEC_AUDIO_INPUT_NID] = { \
+ [HDA_PARAM_AUDIO_WIDGET_CAP] = \
+ HDA_CODEC_AUDIO_WCAP_INPUT | \
+ HDA_CODEC_AUDIO_WCAP_CONN_LIST | \
+ HDA_CODEC_AUDIO_WCAP_FORMAT_OVR | \
+ HDA_CODEC_AUDIO_WCAP_AMP_OVR | \
+ HDA_CODEC_AUDIO_WCAP_IN_AMP | \
+ HDA_CODEC_AUDIO_WCAP_STEREO, \
+ /* B16, 16.0 - 192.0kHz */ \
+ [HDA_PARAM_SUPP_PCM_SIZE_RATE] = (0x02 << 16) | 0x7fc, \
+ [HDA_PARAM_SUPP_STREAM_FORMATS] = \
+ HDA_CODEC_SUPP_STREAM_FORMATS_PCM, \
+ [HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
+ [HDA_PARAM_CONN_LIST_LENGTH] = 0x01, \
+ [HDA_PARAM_INPUT_AMP_CAP] = \
+ HDA_CODEC_OUTPUT_AMP_CAP_MUTE_CAP | \
+ HDA_CODEC_OUTPUT_AMP_CAP_STEPSIZE | \
+ HDA_CODEC_OUTPUT_AMP_CAP_NUMSTEPS | \
+ HDA_CODEC_OUTPUT_AMP_CAP_OFFSET, \
+ }, \
+ [HDA_CODEC_PIN_INPUT_NID] = { \
+ [HDA_PARAM_AUDIO_WIDGET_CAP] = \
+ HDA_CODEC_AUDIO_WCAP_PIN | \
+ HDA_CODEC_AUDIO_WCAP_STEREO, \
+ [HDA_PARAM_PIN_CAP] = HDA_CODEC_PIN_CAP_INPUT | \
+ HDA_CODEC_PIN_CAP_PRESENCE_DETECT, \
+ [HDA_PARAM_INPUT_AMP_CAP] = 0x00, /* None */ \
+ [HDA_PARAM_OUTPUT_AMP_CAP] = 0x00, /* None */ \
+ }, \
+
+static const uint32_t
+hda_codec_output_parameters[][HDA_CODEC_PARAMS_COUNT] = {
+ HDA_CODEC_ROOT_DESC
+ HDA_CODEC_FG_OUTPUT_DESC
+ HDA_CODEC_OUTPUT_DESC
+};
+
+static const uint32_t
+hda_codec_input_parameters[][HDA_CODEC_PARAMS_COUNT] = {
+ HDA_CODEC_ROOT_DESC
+ HDA_CODEC_FG_INPUT_DESC
+ HDA_CODEC_INPUT_DESC
+};
+
+static const uint32_t
+hda_codec_duplex_parameters[][HDA_CODEC_PARAMS_COUNT] = {
+ HDA_CODEC_ROOT_DESC
+ HDA_CODEC_FG_DUPLEX_DESC
+ HDA_CODEC_OUTPUT_DESC
+ HDA_CODEC_INPUT_DESC
+};
+
+#define HDA_CODEC_NODES_COUNT (ARRAY_SIZE(hda_codec_duplex_parameters))
+
+static const uint8_t
+hda_codec_conn_list[HDA_CODEC_NODES_COUNT][HDA_CODEC_CONN_LIST_COUNT] = {
+ [HDA_CODEC_PIN_OUTPUT_NID] = {HDA_CODEC_AUDIO_OUTPUT_NID},
+ [HDA_CODEC_AUDIO_INPUT_NID] = {HDA_CODEC_PIN_INPUT_NID},
+};
+
+static const uint32_t
+hda_codec_conf_default[HDA_CODEC_NODES_COUNT] = {
+ [HDA_CODEC_PIN_OUTPUT_NID] = \
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK |
+ HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT |
+ HDA_CONFIG_DEFAULTCONF_COLOR_BLACK |
+ (0x01 << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT),
+ [HDA_CODEC_PIN_INPUT_NID] = HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK |
+ HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN |
+ HDA_CONFIG_DEFAULTCONF_COLOR_RED |
+ (0x02 << HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT),
+};
+
+static const uint8_t
+hda_codec_pin_ctrl_default[HDA_CODEC_NODES_COUNT] = {
+ [HDA_CODEC_PIN_OUTPUT_NID] = HDA_CODEC_PIN_WIDGET_CTRL_OUT_ENABLE,
+ [HDA_CODEC_PIN_INPUT_NID] = HDA_CODEC_PIN_WIDGET_CTRL_IN_ENABLE,
+};
+
+static const
+verb_func_t hda_codec_verb_handlers[HDA_CODEC_NODES_COUNT] = {
+ [HDA_CODEC_AUDIO_OUTPUT_NID] = hda_codec_audio_output_nid,
+ [HDA_CODEC_AUDIO_INPUT_NID] = hda_codec_audio_input_nid,
+};
+
+/*
+ * HDA Codec module function definitions
+ */
+
+static int
+hda_codec_init(struct hda_codec_inst *hci, const char *play,
+ const char *rec, const char *opts)
+{
+ struct hda_codec_softc *sc = NULL;
+ struct hda_codec_stream *st = NULL;
+ int err;
+
+ if (!(play || rec))
+ return (-1);
+
+ DPRINTF("cad: 0x%x opts: %s\n", hci->cad, opts);
+
+ sc = calloc(1, sizeof(*sc));
+ if (!sc)
+ return (-1);
+
+ if (play && rec)
+ sc->get_parameters = hda_codec_duplex_parameters;
+ else {
+ if (play)
+ sc->get_parameters = hda_codec_output_parameters;
+ else
+ sc->get_parameters = hda_codec_input_parameters;
+ }
+ sc->subsystem_id = HDA_CODEC_SUBSYSTEM_ID;
+ sc->no_nodes = HDA_CODEC_NODES_COUNT;
+ sc->conn_list = hda_codec_conn_list;
+ sc->conf_default = hda_codec_conf_default;
+ sc->pin_ctrl_default = hda_codec_pin_ctrl_default;
+ sc->verb_handlers = hda_codec_verb_handlers;
+ DPRINTF("HDA Codec nodes: %d\n", sc->no_nodes);
+
+ /*
+ * Initialize the Audio Output stream
+ */
+ if (play) {
+ st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
+
+ err = hda_audio_ctxt_init(&st->actx, "hda-audio-output",
+ hda_codec_audio_output_do_transfer,
+ hda_codec_audio_output_do_setup, sc);
+ assert(!err);
+
+ st->aud = audio_init(play, 1);
+ if (!st->aud) {
+ DPRINTF("Fail to init the output audio player\n");
+ return (-1);
+ }
+ }
+
+ /*
+ * Initialize the Audio Input stream
+ */
+ if (rec) {
+ st = &sc->streams[HDA_CODEC_STREAM_INPUT];
+
+ err = hda_audio_ctxt_init(&st->actx, "hda-audio-input",
+ hda_codec_audio_input_do_transfer,
+ hda_codec_audio_input_do_setup, sc);
+ assert(!err);
+
+ st->aud = audio_init(rec, 0);
+ if (!st->aud) {
+ DPRINTF("Fail to init the input audio player\n");
+ return (-1);
+ }
+ }
+
+ sc->hci = hci;
+ hci->priv = sc;
+
+ return (0);
+}
+
+static int
+hda_codec_reset(struct hda_codec_inst *hci)
+{
+ struct hda_ops *hops = NULL;
+ struct hda_codec_softc *sc = NULL;
+ struct hda_codec_stream *st = NULL;
+ int i;
+
+ assert(hci);
+
+ hops = hci->hops;
+ assert(hops);
+
+ sc = (struct hda_codec_softc *)hci->priv;
+ assert(sc);
+
+ for (i = 0; i < HDA_CODEC_STREAMS_COUNT; i++) {
+ st = &sc->streams[i];
+ st->left_gain = HDA_CODEC_AMP_NUMSTEPS;
+ st->right_gain = HDA_CODEC_AMP_NUMSTEPS;
+ st->left_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE;
+ st->right_mute = HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE;
+ }
+
+ DPRINTF("cad: 0x%x\n", hci->cad);
+
+ if (!hops->signal) {
+ DPRINTF("The controller ops does not implement \
+ the signal function\n");
+ return (-1);
+ }
+
+ return (hops->signal(hci));
+}
+
+static int
+hda_codec_command(struct hda_codec_inst *hci, uint32_t cmd_data)
+{
+ struct hda_codec_softc *sc = NULL;
+ struct hda_ops *hops = NULL;
+ uint8_t cad = 0, nid = 0;
+ uint16_t verb = 0, payload = 0;
+ uint32_t res = 0;
+
+ /* 4 bits */
+ cad = (cmd_data >> HDA_CMD_CAD_SHIFT) & 0x0f;
+ /* 8 bits */
+ nid = (cmd_data >> HDA_CMD_NID_SHIFT) & 0xff;
+
+ if ((cmd_data & 0x70000) == 0x70000) {
+ /* 12 bits */
+ verb = (cmd_data >> HDA_CMD_VERB_12BIT_SHIFT) & 0x0fff;
+ /* 8 bits */
+ payload = cmd_data & 0xff;
+ } else {
+ /* 4 bits */
+ verb = (cmd_data >> HDA_CMD_VERB_4BIT_SHIFT) & 0x0f;
+ /* 16 bits */
+ payload = cmd_data & 0xffff;
+ }
+
+ assert(cad == hci->cad);
+ assert(hci);
+
+ hops = hci->hops;
+ assert(hops);
+
+ sc = (struct hda_codec_softc *)hci->priv;
+ assert(sc);
+
+ assert(nid < sc->no_nodes);
+
+ if (!hops->response) {
+ DPRINTF("The controller ops does not implement \
+ the response function\n");
+ return (-1);
+ }
+
+ switch (verb) {
+ case HDA_CMD_VERB_GET_PARAMETER:
+ res = sc->get_parameters[nid][payload];
+ break;
+ case HDA_CMD_VERB_GET_CONN_LIST_ENTRY:
+ res = sc->conn_list[nid][0];
+ break;
+ case HDA_CMD_VERB_GET_PIN_WIDGET_CTRL:
+ res = sc->pin_ctrl_default[nid];
+ break;
+ case HDA_CMD_VERB_GET_PIN_SENSE:
+ res = HDA_CODEC_PIN_SENSE_PRESENCE_PLUGGED;
+ break;
+ case HDA_CMD_VERB_GET_CONFIGURATION_DEFAULT:
+ res = sc->conf_default[nid];
+ break;
+ case HDA_CMD_VERB_GET_SUBSYSTEM_ID:
+ res = sc->subsystem_id;
+ break;
+ default:
+ assert(sc->verb_handlers);
+ if (sc->verb_handlers[nid])
+ res = sc->verb_handlers[nid](sc, verb, payload);
+ else
+ DPRINTF("Unknown VERB: 0x%x\n", verb);
+ break;
+ }
+
+ DPRINTF("cad: 0x%x nid: 0x%x verb: 0x%x payload: 0x%x response: 0x%x\n",
+ cad, nid, verb, payload, res);
+
+ return (hops->response(hci, res, HDA_CODEC_RESPONSE_EX_SOL));
+}
+
+static int
+hda_codec_notify(struct hda_codec_inst *hci, uint8_t run,
+ uint8_t stream, uint8_t dir)
+{
+ struct hda_codec_softc *sc = NULL;
+ struct hda_codec_stream *st = NULL;
+ struct hda_audio_ctxt *actx = NULL;
+ int i;
+ int err;
+
+ assert(hci);
+ assert(stream);
+
+ sc = (struct hda_codec_softc *)hci->priv;
+ assert(sc);
+
+ i = dir ? HDA_CODEC_STREAM_OUTPUT : HDA_CODEC_STREAM_INPUT;
+ st = &sc->streams[i];
+
+ DPRINTF("run: %d, stream: 0x%x, st->stream: 0x%x dir: %d\n",
+ run, stream, st->stream, dir);
+
+ if (stream != st->stream) {
+ DPRINTF("Stream not found\n");
+ return (0);
+ }
+
+ actx = &st->actx;
+
+ if (run)
+ err = hda_audio_ctxt_start(actx);
+ else
+ err = hda_audio_ctxt_stop(actx);
+
+ return (err);
+}
+
+static int
+hda_codec_parse_format(uint16_t fmt, struct audio_params *params)
+{
+ uint8_t div = 0;
+
+ assert(params);
+
+ /* Compute the Sample Rate */
+ params->rate = (fmt & HDA_CODEC_FMT_BASE_MASK) ? 44100 : 48000;
+
+ switch (fmt & HDA_CODEC_FMT_MULT_MASK) {
+ case HDA_CODEC_FMT_MULT_2:
+ params->rate *= 2;
+ break;
+ case HDA_CODEC_FMT_MULT_3:
+ params->rate *= 3;
+ break;
+ case HDA_CODEC_FMT_MULT_4:
+ params->rate *= 4;
+ break;
+ }
+
+ div = (fmt >> HDA_CODEC_FMT_DIV_SHIFT) & HDA_CODEC_FMT_DIV_MASK;
+ params->rate /= (div + 1);
+
+ /* Compute the Bits per Sample */
+ switch (fmt & HDA_CODEC_FMT_BITS_MASK) {
+ case HDA_CODEC_FMT_BITS_8:
+ params->format = AFMT_U8;
+ break;
+ case HDA_CODEC_FMT_BITS_16:
+ params->format = AFMT_S16_LE;
+ break;
+ case HDA_CODEC_FMT_BITS_24:
+ params->format = AFMT_S24_LE;
+ break;
+ case HDA_CODEC_FMT_BITS_32:
+ params->format = AFMT_S32_LE;
+ break;
+ default:
+ DPRINTF("Unknown format bits: 0x%x\n",
+ fmt & HDA_CODEC_FMT_BITS_MASK);
+ return (-1);
+ }
+
+ /* Compute the Number of Channels */
+ params->channels = (fmt & HDA_CODEC_FMT_CHAN_MASK) + 1;
+
+ return (0);
+}
+
+static uint32_t
+hda_codec_audio_output_nid(struct hda_codec_softc *sc, uint16_t verb,
+ uint16_t payload)
+{
+ struct hda_codec_stream *st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
+ int res;
+
+ res = hda_codec_audio_inout_nid(st, verb, payload);
+
+ return (res);
+}
+
+static void
+hda_codec_audio_output_do_transfer(void *arg)
+{
+ struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
+ struct hda_codec_inst *hci = NULL;
+ struct hda_ops *hops = NULL;
+ struct hda_codec_stream *st = NULL;
+ struct audio *aud = NULL;
+ int err;
+
+ hci = sc->hci;
+ assert(hci);
+
+ hops = hci->hops;
+ assert(hops);
+
+ st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
+ aud = st->aud;
+
+ err = hops->transfer(hci, st->stream, 1, st->buf, sizeof(st->buf));
+ if (err)
+ return;
+
+ err = audio_playback(aud, st->buf, sizeof(st->buf));
+ assert(!err);
+}
+
+static int
+hda_codec_audio_output_do_setup(void *arg)
+{
+ struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
+ struct hda_codec_stream *st = NULL;
+ struct audio *aud = NULL;
+ struct audio_params params;
+ int err;
+
+ st = &sc->streams[HDA_CODEC_STREAM_OUTPUT];
+ aud = st->aud;
+
+ err = hda_codec_parse_format(st->fmt, &params);
+ if (err)
+ return (-1);
+
+ DPRINTF("rate: %d, channels: %d, format: 0x%x\n",
+ params.rate, params.channels, params.format);
+
+ return (audio_set_params(aud, &params));
+}
+
+static uint32_t
+hda_codec_audio_input_nid(struct hda_codec_softc *sc, uint16_t verb,
+ uint16_t payload)
+{
+ struct hda_codec_stream *st = &sc->streams[HDA_CODEC_STREAM_INPUT];
+ int res;
+
+ res = hda_codec_audio_inout_nid(st, verb, payload);
+
+ return (res);
+}
+
+static void
+hda_codec_audio_input_do_transfer(void *arg)
+{
+ struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
+ struct hda_codec_inst *hci = NULL;
+ struct hda_ops *hops = NULL;
+ struct hda_codec_stream *st = NULL;
+ struct audio *aud = NULL;
+ int err;
+
+ hci = sc->hci;
+ assert(hci);
+
+ hops = hci->hops;
+ assert(hops);
+
+ st = &sc->streams[HDA_CODEC_STREAM_INPUT];
+ aud = st->aud;
+
+ err = audio_record(aud, st->buf, sizeof(st->buf));
+ assert(!err);
+
+ hops->transfer(hci, st->stream, 0, st->buf, sizeof(st->buf));
+}
+
+static int
+hda_codec_audio_input_do_setup(void *arg)
+{
+ struct hda_codec_softc *sc = (struct hda_codec_softc *)arg;
+ struct hda_codec_stream *st = NULL;
+ struct audio *aud = NULL;
+ struct audio_params params;
+ int err;
+
+ st = &sc->streams[HDA_CODEC_STREAM_INPUT];
+ aud = st->aud;
+
+ err = hda_codec_parse_format(st->fmt, &params);
+ if (err)
+ return (-1);
+
+ DPRINTF("rate: %d, channels: %d, format: 0x%x\n",
+ params.rate, params.channels, params.format);
+
+ return (audio_set_params(aud, &params));
+}
+
+static uint32_t
+hda_codec_audio_inout_nid(struct hda_codec_stream *st, uint16_t verb,
+ uint16_t payload)
+{
+ uint32_t res = 0;
+ uint8_t mute = 0;
+ uint8_t gain = 0;
+
+ DPRINTF("%s verb: 0x%x, payload, 0x%x\n", st->actx.name, verb, payload);
+
+ switch (verb) {
+ case HDA_CMD_VERB_GET_CONV_FMT:
+ res = st->fmt;
+ break;
+ case HDA_CMD_VERB_SET_CONV_FMT:
+ st->fmt = payload;
+ break;
+ case HDA_CMD_VERB_GET_AMP_GAIN_MUTE:
+ if (payload & HDA_CMD_GET_AMP_GAIN_MUTE_LEFT) {
+ res = st->left_gain | st->left_mute;
+ DPRINTF("GET_AMP_GAIN_MUTE_LEFT: 0x%x\n", res);
+ } else {
+ res = st->right_gain | st->right_mute;
+ DPRINTF("GET_AMP_GAIN_MUTE_RIGHT: 0x%x\n", res);
+ }
+ break;
+ case HDA_CMD_VERB_SET_AMP_GAIN_MUTE:
+ mute = payload & HDA_CODEC_SET_AMP_GAIN_MUTE_MUTE;
+ gain = payload & HDA_CODEC_SET_AMP_GAIN_MUTE_GAIN_MASK;
+
+ if (payload & HDA_CMD_SET_AMP_GAIN_MUTE_LEFT) {
+ st->left_mute = mute;
+ st->left_gain = gain;
+ DPRINTF("SET_AMP_GAIN_MUTE_LEFT: \
+ mute: 0x%x gain: 0x%x\n", mute, gain);
+ }
+
+ if (payload & HDA_CMD_SET_AMP_GAIN_MUTE_RIGHT) {
+ st->right_mute = mute;
+ st->right_gain = gain;
+ DPRINTF("SET_AMP_GAIN_MUTE_RIGHT: \
+ mute: 0x%x gain: 0x%x\n", mute, gain);
+ }
+ break;
+ case HDA_CMD_VERB_GET_CONV_STREAM_CHAN:
+ res = (st->stream << 4) | st->channel;
+ break;
+ case HDA_CMD_VERB_SET_CONV_STREAM_CHAN:
+ st->channel = payload & 0x0f;
+ st->stream = (payload >> 4) & 0x0f;
+ DPRINTF("st->channel: 0x%x st->stream: 0x%x\n",
+ st->channel, st->stream);
+ if (!st->stream)
+ hda_audio_ctxt_stop(&st->actx);
+ break;
+ default:
+ DPRINTF("Unknown VERB: 0x%x\n", verb);
+ break;
+ }
+
+ return (res);
+}
+
+struct hda_codec_class hda_codec = {
+ .name = "hda_codec",
+ .init = hda_codec_init,
+ .reset = hda_codec_reset,
+ .command = hda_codec_command,
+ .notify = hda_codec_notify,
+};
+
+HDA_EMUL_SET(hda_codec);
+
+
+/*
+ * HDA Audio Context module function definitions
+ */
+
+static void *
+hda_audio_ctxt_thr(void *arg)
+{
+ struct hda_audio_ctxt *actx = arg;
+
+ DPRINTF("Start Thread: %s\n", actx->name);
+
+ pthread_mutex_lock(&actx->mtx);
+ while (1) {
+ while (!actx->run)
+ pthread_cond_wait(&actx->cond, &actx->mtx);
+
+ actx->do_transfer(actx->priv);
+ }
+ pthread_mutex_unlock(&actx->mtx);
+
+ pthread_exit(NULL);
+ return (NULL);
+}
+
+static int
+hda_audio_ctxt_init(struct hda_audio_ctxt *actx, const char *tname,
+ transfer_func_t do_transfer, setup_func_t do_setup, void *priv)
+{
+ int err;
+
+ assert(actx);
+ assert(tname);
+ assert(do_transfer);
+ assert(do_setup);
+ assert(priv);
+
+ memset(actx, 0, sizeof(*actx));
+
+ actx->run = 0;
+ actx->do_transfer = do_transfer;
+ actx->do_setup = do_setup;
+ actx->priv = priv;
+ if (strlen(tname) < sizeof(actx->name))
+ memcpy(actx->name, tname, strlen(tname) + 1);
+ else
+ strcpy(actx->name, "unknown");
+
+ err = pthread_mutex_init(&actx->mtx, NULL);
+ assert(!err);
+
+ err = pthread_cond_init(&actx->cond, NULL);
+ assert(!err);
+
+ err = pthread_create(&actx->tid, NULL, hda_audio_ctxt_thr, actx);
+ assert(!err);
+
+ pthread_set_name_np(actx->tid, tname);
+
+ actx->started = 1;
+
+ return (0);
+}
+
+static int
+hda_audio_ctxt_start(struct hda_audio_ctxt *actx)
+{
+ int err = 0;
+
+ assert(actx);
+ assert(actx->started);
+
+ /* The stream is supposed to be stopped */
+ if (actx->run)
+ return (-1);
+
+ pthread_mutex_lock(&actx->mtx);
+ err = (* actx->do_setup)(actx->priv);
+ if (!err) {
+ actx->run = 1;
+ pthread_cond_signal(&actx->cond);
+ }
+ pthread_mutex_unlock(&actx->mtx);
+
+ return (err);
+}
+
+static int
+hda_audio_ctxt_stop(struct hda_audio_ctxt *actx)
+{
+ actx->run = 0;
+ return (0);
+}
diff --git a/usr.sbin/bhyve/hda_reg.h b/usr.sbin/bhyve/hda_reg.h
new file mode 100644
index 000000000000..b3034bf9f417
--- /dev/null
+++ b/usr.sbin/bhyve/hda_reg.h
@@ -0,0 +1,1369 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _HDA_REG_H_
+#define _HDA_REG_H_
+
+/****************************************************************************
+ * HDA Device Verbs
+ ****************************************************************************/
+
+/* HDA Command */
+#define HDA_CMD_VERB_MASK 0x000fffff
+#define HDA_CMD_VERB_SHIFT 0
+#define HDA_CMD_NID_MASK 0x0ff00000
+#define HDA_CMD_NID_SHIFT 20
+#define HDA_CMD_CAD_MASK 0xf0000000
+#define HDA_CMD_CAD_SHIFT 28
+
+#define HDA_CMD_VERB_4BIT_SHIFT 16
+#define HDA_CMD_VERB_12BIT_SHIFT 8
+
+#define HDA_CMD_VERB_4BIT(verb, payload) \
+ (((verb) << HDA_CMD_VERB_4BIT_SHIFT) | (payload))
+#define HDA_CMD_4BIT(cad, nid, verb, payload) \
+ (((cad) << HDA_CMD_CAD_SHIFT) | \
+ ((nid) << HDA_CMD_NID_SHIFT) | \
+ (HDA_CMD_VERB_4BIT((verb), (payload))))
+
+#define HDA_CMD_VERB_12BIT(verb, payload) \
+ (((verb) << HDA_CMD_VERB_12BIT_SHIFT) | (payload))
+#define HDA_CMD_12BIT(cad, nid, verb, payload) \
+ (((cad) << HDA_CMD_CAD_SHIFT) | \
+ ((nid) << HDA_CMD_NID_SHIFT) | \
+ (HDA_CMD_VERB_12BIT((verb), (payload))))
+
+/* Get Parameter */
+#define HDA_CMD_VERB_GET_PARAMETER 0xf00
+
+#define HDA_CMD_GET_PARAMETER(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_PARAMETER, (payload)))
+
+/* Connection Select Control */
+#define HDA_CMD_VERB_GET_CONN_SELECT_CONTROL 0xf01
+#define HDA_CMD_VERB_SET_CONN_SELECT_CONTROL 0x701
+
+#define HDA_CMD_GET_CONN_SELECT_CONTROL(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_CONN_SELECT_CONTROL, 0x0))
+#define HDA_CMD_SET_CONNECTION_SELECT_CONTROL(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONN_SELECT_CONTROL, (payload)))
+
+/* Connection List Entry */
+#define HDA_CMD_VERB_GET_CONN_LIST_ENTRY 0xf02
+
+#define HDA_CMD_GET_CONN_LIST_ENTRY(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_CONN_LIST_ENTRY, (payload)))
+
+#define HDA_CMD_GET_CONN_LIST_ENTRY_SIZE_SHORT 1
+#define HDA_CMD_GET_CONN_LIST_ENTRY_SIZE_LONG 2
+
+/* Processing State */
+#define HDA_CMD_VERB_GET_PROCESSING_STATE 0xf03
+#define HDA_CMD_VERB_SET_PROCESSING_STATE 0x703
+
+#define HDA_CMD_GET_PROCESSING_STATE(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_PROCESSING_STATE, 0x0))
+#define HDA_CMD_SET_PROCESSING_STATE(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_PROCESSING_STATE, (payload)))
+
+#define HDA_CMD_GET_PROCESSING_STATE_STATE_OFF 0x00
+#define HDA_CMD_GET_PROCESSING_STATE_STATE_ON 0x01
+#define HDA_CMD_GET_PROCESSING_STATE_STATE_BENIGN 0x02
+
+/* Coefficient Index */
+#define HDA_CMD_VERB_GET_COEFF_INDEX 0xd
+#define HDA_CMD_VERB_SET_COEFF_INDEX 0x5
+
+#define HDA_CMD_GET_COEFF_INDEX(cad, nid) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_COEFF_INDEX, 0x0))
+#define HDA_CMD_SET_COEFF_INDEX(cad, nid, payload) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_COEFF_INDEX, (payload)))
+
+/* Processing Coefficient */
+#define HDA_CMD_VERB_GET_PROCESSING_COEFF 0xc
+#define HDA_CMD_VERB_SET_PROCESSING_COEFF 0x4
+
+#define HDA_CMD_GET_PROCESSING_COEFF(cad, nid) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_PROCESSING_COEFF, 0x0))
+#define HDA_CMD_SET_PROCESSING_COEFF(cad, nid, payload) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_PROCESSING_COEFF, (payload)))
+
+/* Amplifier Gain/Mute */
+#define HDA_CMD_VERB_GET_AMP_GAIN_MUTE 0xb
+#define HDA_CMD_VERB_SET_AMP_GAIN_MUTE 0x3
+
+#define HDA_CMD_GET_AMP_GAIN_MUTE(cad, nid, payload) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_AMP_GAIN_MUTE, (payload)))
+#define HDA_CMD_SET_AMP_GAIN_MUTE(cad, nid, payload) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_AMP_GAIN_MUTE, (payload)))
+
+#define HDA_CMD_GET_AMP_GAIN_MUTE_INPUT 0x0000
+#define HDA_CMD_GET_AMP_GAIN_MUTE_OUTPUT 0x8000
+#define HDA_CMD_GET_AMP_GAIN_MUTE_RIGHT 0x0000
+#define HDA_CMD_GET_AMP_GAIN_MUTE_LEFT 0x2000
+
+#define HDA_CMD_GET_AMP_GAIN_MUTE_MUTE_MASK 0x00000008
+#define HDA_CMD_GET_AMP_GAIN_MUTE_MUTE_SHIFT 7
+#define HDA_CMD_GET_AMP_GAIN_MUTE_GAIN_MASK 0x00000007
+#define HDA_CMD_GET_AMP_GAIN_MUTE_GAIN_SHIFT 0
+
+#define HDA_CMD_GET_AMP_GAIN_MUTE_MUTE(rsp) \
+ (((rsp) & HDA_CMD_GET_AMP_GAIN_MUTE_MUTE_MASK) >> \
+ HDA_CMD_GET_AMP_GAIN_MUTE_MUTE_SHIFT)
+#define HDA_CMD_GET_AMP_GAIN_MUTE_GAIN(rsp) \
+ (((rsp) & HDA_CMD_GET_AMP_GAIN_MUTE_GAIN_MASK) >> \
+ HDA_CMD_GET_AMP_GAIN_MUTE_GAIN_SHIFT)
+
+#define HDA_CMD_SET_AMP_GAIN_MUTE_OUTPUT 0x8000
+#define HDA_CMD_SET_AMP_GAIN_MUTE_INPUT 0x4000
+#define HDA_CMD_SET_AMP_GAIN_MUTE_LEFT 0x2000
+#define HDA_CMD_SET_AMP_GAIN_MUTE_RIGHT 0x1000
+#define HDA_CMD_SET_AMP_GAIN_MUTE_INDEX_MASK 0x0f00
+#define HDA_CMD_SET_AMP_GAIN_MUTE_INDEX_SHIFT 8
+#define HDA_CMD_SET_AMP_GAIN_MUTE_MUTE 0x0080
+#define HDA_CMD_SET_AMP_GAIN_MUTE_GAIN_MASK 0x0007
+#define HDA_CMD_SET_AMP_GAIN_MUTE_GAIN_SHIFT 0
+
+#define HDA_CMD_SET_AMP_GAIN_MUTE_INDEX(index) \
+ (((index) << HDA_CMD_SET_AMP_GAIN_MUTE_INDEX_SHIFT) & \
+ HDA_CMD_SET_AMP_GAIN_MUTE_INDEX_MASK)
+#define HDA_CMD_SET_AMP_GAIN_MUTE_GAIN(index) \
+ (((index) << HDA_CMD_SET_AMP_GAIN_MUTE_GAIN_SHIFT) & \
+ HDA_CMD_SET_AMP_GAIN_MUTE_GAIN_MASK)
+
+/* Converter format */
+#define HDA_CMD_VERB_GET_CONV_FMT 0xa
+#define HDA_CMD_VERB_SET_CONV_FMT 0x2
+
+#define HDA_CMD_GET_CONV_FMT(cad, nid) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_CONV_FMT, 0x0))
+#define HDA_CMD_SET_CONV_FMT(cad, nid, payload) \
+ (HDA_CMD_4BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONV_FMT, (payload)))
+
+/* Digital Converter Control */
+#define HDA_CMD_VERB_GET_DIGITAL_CONV_FMT1 0xf0d
+#define HDA_CMD_VERB_GET_DIGITAL_CONV_FMT2 0xf0e
+#define HDA_CMD_VERB_SET_DIGITAL_CONV_FMT1 0x70d
+#define HDA_CMD_VERB_SET_DIGITAL_CONV_FMT2 0x70e
+
+#define HDA_CMD_GET_DIGITAL_CONV_FMT(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_DIGITAL_CONV_FMT1, 0x0))
+#define HDA_CMD_SET_DIGITAL_CONV_FMT1(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_DIGITAL_CONV_FMT1, (payload)))
+#define HDA_CMD_SET_DIGITAL_CONV_FMT2(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_DIGITAL_CONV_FMT2, (payload)))
+
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_CC_MASK 0x7f00
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_CC_SHIFT 8
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_L_MASK 0x0080
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_L_SHIFT 7
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_PRO_MASK 0x0040
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_PRO_SHIFT 6
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_NAUDIO_MASK 0x0020
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_NAUDIO_SHIFT 5
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_COPY_MASK 0x0010
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_COPY_SHIFT 4
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_PRE_MASK 0x0008
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_PRE_SHIFT 3
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_VCFG_MASK 0x0004
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_VCFG_SHIFT 2
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_V_MASK 0x0002
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_V_SHIFT 1
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN_MASK 0x0001
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN_SHIFT 0
+
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_CC(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_CC_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_CC_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_L(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_L_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_L_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_PRO(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_PRO_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_PRO_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_NAUDIO(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_NAUDIO_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_NAUDIO_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_COPY(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_COPY_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_COPY_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_PRE(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_PRE_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_PRE_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_VCFG(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_VCFG_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_VCFG_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_V(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_V_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_V_SHIFT)
+#define HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN(rsp) \
+ (((rsp) & HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN_MASK) >> \
+ HDA_CMD_GET_DIGITAL_CONV_FMT_DIGEN_SHIFT)
+
+#define HDA_CMD_SET_DIGITAL_CONV_FMT1_L 0x80
+#define HDA_CMD_SET_DIGITAL_CONV_FMT1_PRO 0x40
+#define HDA_CMD_SET_DIGITAL_CONV_FMT1_NAUDIO 0x20
+#define HDA_CMD_SET_DIGITAL_CONV_FMT1_COPY 0x10
+#define HDA_CMD_SET_DIGITAL_CONV_FMT1_PRE 0x08
+#define HDA_CMD_SET_DIGITAL_CONV_FMT1_VCFG 0x04
+#define HDA_CMD_SET_DIGITAL_CONV_FMT1_V 0x02
+#define HDA_CMD_SET_DIGITAL_CONV_FMT1_DIGEN 0x01
+
+/* Power State */
+#define HDA_CMD_VERB_GET_POWER_STATE 0xf05
+#define HDA_CMD_VERB_SET_POWER_STATE 0x705
+
+#define HDA_CMD_GET_POWER_STATE(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_POWER_STATE, 0x0))
+#define HDA_CMD_SET_POWER_STATE(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_POWER_STATE, (payload)))
+
+#define HDA_CMD_POWER_STATE_D0 0x00
+#define HDA_CMD_POWER_STATE_D1 0x01
+#define HDA_CMD_POWER_STATE_D2 0x02
+#define HDA_CMD_POWER_STATE_D3 0x03
+
+#define HDA_CMD_POWER_STATE_ACT_MASK 0x000000f0
+#define HDA_CMD_POWER_STATE_ACT_SHIFT 4
+#define HDA_CMD_POWER_STATE_SET_MASK 0x0000000f
+#define HDA_CMD_POWER_STATE_SET_SHIFT 0
+
+#define HDA_CMD_GET_POWER_STATE_ACT(rsp) \
+ (((rsp) & HDA_CMD_POWER_STATE_ACT_MASK) >> \
+ HDA_CMD_POWER_STATE_ACT_SHIFT)
+#define HDA_CMD_GET_POWER_STATE_SET(rsp) \
+ (((rsp) & HDA_CMD_POWER_STATE_SET_MASK) >> \
+ HDA_CMD_POWER_STATE_SET_SHIFT)
+
+#define HDA_CMD_SET_POWER_STATE_ACT(ps) \
+ (((ps) << HDA_CMD_POWER_STATE_ACT_SHIFT) & \
+ HDA_CMD_POWER_STATE_ACT_MASK)
+#define HDA_CMD_SET_POWER_STATE_SET(ps) \
+ (((ps) << HDA_CMD_POWER_STATE_SET_SHIFT) & \
+ HDA_CMD_POWER_STATE_ACT_MASK)
+
+/* Converter Stream, Channel */
+#define HDA_CMD_VERB_GET_CONV_STREAM_CHAN 0xf06
+#define HDA_CMD_VERB_SET_CONV_STREAM_CHAN 0x706
+
+#define HDA_CMD_GET_CONV_STREAM_CHAN(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_CONV_STREAM_CHAN, 0x0))
+#define HDA_CMD_SET_CONV_STREAM_CHAN(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONV_STREAM_CHAN, (payload)))
+
+#define HDA_CMD_CONV_STREAM_CHAN_STREAM_MASK 0x000000f0
+#define HDA_CMD_CONV_STREAM_CHAN_STREAM_SHIFT 4
+#define HDA_CMD_CONV_STREAM_CHAN_CHAN_MASK 0x0000000f
+#define HDA_CMD_CONV_STREAM_CHAN_CHAN_SHIFT 0
+
+#define HDA_CMD_GET_CONV_STREAM_CHAN_STREAM(rsp) \
+ (((rsp) & HDA_CMD_CONV_STREAM_CHAN_STREAM_MASK) >> \
+ HDA_CMD_CONV_STREAM_CHAN_STREAM_SHIFT)
+#define HDA_CMD_GET_CONV_STREAM_CHAN_CHAN(rsp) \
+ (((rsp) & HDA_CMD_CONV_STREAM_CHAN_CHAN_MASK) >> \
+ HDA_CMD_CONV_STREAM_CHAN_CHAN_SHIFT)
+
+#define HDA_CMD_SET_CONV_STREAM_CHAN_STREAM(param) \
+ (((param) << HDA_CMD_CONV_STREAM_CHAN_STREAM_SHIFT) & \
+ HDA_CMD_CONV_STREAM_CHAN_STREAM_MASK)
+#define HDA_CMD_SET_CONV_STREAM_CHAN_CHAN(param) \
+ (((param) << HDA_CMD_CONV_STREAM_CHAN_CHAN_SHIFT) & \
+ HDA_CMD_CONV_STREAM_CHAN_CHAN_MASK)
+
+/* Input Converter SDI Select */
+#define HDA_CMD_VERB_GET_INPUT_CONVERTER_SDI_SELECT 0xf04
+#define HDA_CMD_VERB_SET_INPUT_CONVERTER_SDI_SELECT 0x704
+
+#define HDA_CMD_GET_INPUT_CONVERTER_SDI_SELECT(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_INPUT_CONVERTER_SDI_SELECT, 0x0))
+#define HDA_CMD_SET_INPUT_CONVERTER_SDI_SELECT(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_INPUT_CONVERTER_SDI_SELECT, (payload)))
+
+/* Pin Widget Control */
+#define HDA_CMD_VERB_GET_PIN_WIDGET_CTRL 0xf07
+#define HDA_CMD_VERB_SET_PIN_WIDGET_CTRL 0x707
+
+#define HDA_CMD_GET_PIN_WIDGET_CTRL(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_PIN_WIDGET_CTRL, 0x0))
+#define HDA_CMD_SET_PIN_WIDGET_CTRL(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_PIN_WIDGET_CTRL, (payload)))
+
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE_MASK 0x00000080
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE_SHIFT 7
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_OUT_ENABLE_MASK 0x00000040
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_OUT_ENABLE_SHIFT 6
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE_MASK 0x00000020
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE_SHIFT 5
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK 0x00000007
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE_SHIFT 0
+
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE(rsp) \
+ (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE_MASK) >> \
+ HDA_CMD_GET_PIN_WIDGET_CTRL_HPHN_ENABLE_SHIFT)
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_OUT_ENABLE(rsp) \
+ (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_OUT_ENABLE_MASK) >> \
+ HDA_GET_CMD_PIN_WIDGET_CTRL_OUT_ENABLE_SHIFT)
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE(rsp) \
+ (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE_MASK) >> \
+ HDA_CMD_GET_PIN_WIDGET_CTRL_IN_ENABLE_SHIFT)
+#define HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE(rsp) \
+ (((rsp) & HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK) >> \
+ HDA_CMD_GET_PIN_WIDGET_CTRL_VREF_ENABLE_SHIFT)
+
+#define HDA_CMD_SET_PIN_WIDGET_CTRL_HPHN_ENABLE 0x80
+#define HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE 0x40
+#define HDA_CMD_SET_PIN_WIDGET_CTRL_IN_ENABLE 0x20
+#define HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK 0x07
+#define HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_SHIFT 0
+
+#define HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE(param) \
+ (((param) << HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_SHIFT) & \
+ HDA_CMD_SET_PIN_WIDGET_CTRL_VREF_ENABLE_MASK)
+
+#define HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_HIZ 0
+#define HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_50 1
+#define HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_GROUND 2
+#define HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_80 4
+#define HDA_CMD_PIN_WIDGET_CTRL_VREF_ENABLE_100 5
+
+/* Unsolicited Response */
+#define HDA_CMD_VERB_GET_UNSOLICITED_RESPONSE 0xf08
+#define HDA_CMD_VERB_SET_UNSOLICITED_RESPONSE 0x708
+
+#define HDA_CMD_GET_UNSOLICITED_RESPONSE(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_UNSOLICITED_RESPONSE, 0x0))
+#define HDA_CMD_SET_UNSOLICITED_RESPONSE(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_UNSOLICITED_RESPONSE, (payload)))
+
+#define HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE_MASK 0x00000080
+#define HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE_SHIFT 7
+#define HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG_MASK 0x0000001f
+#define HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG_SHIFT 0
+
+#define HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE(rsp) \
+ (((rsp) & HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE_MASK) >> \
+ HDA_CMD_GET_UNSOLICITED_RESPONSE_ENABLE_SHIFT)
+#define HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG(rsp) \
+ (((rsp) & HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG_MASK) >> \
+ HDA_CMD_GET_UNSOLICITED_RESPONSE_TAG_SHIFT)
+
+#define HDA_CMD_SET_UNSOLICITED_RESPONSE_ENABLE 0x80
+#define HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG_MASK 0x3f
+#define HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG_SHIFT 0
+
+#define HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG(param) \
+ (((param) << HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG_SHIFT) & \
+ HDA_CMD_SET_UNSOLICITED_RESPONSE_TAG_MASK)
+
+/* Pin Sense */
+#define HDA_CMD_VERB_GET_PIN_SENSE 0xf09
+#define HDA_CMD_VERB_SET_PIN_SENSE 0x709
+
+#define HDA_CMD_GET_PIN_SENSE(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_PIN_SENSE, 0x0))
+#define HDA_CMD_SET_PIN_SENSE(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_PIN_SENSE, (payload)))
+
+#define HDA_CMD_GET_PIN_SENSE_PRESENCE_DETECT 0x80000000
+#define HDA_CMD_GET_PIN_SENSE_ELD_VALID 0x40000000
+#define HDA_CMD_GET_PIN_SENSE_IMP_SENSE_MASK 0x7fffffff
+#define HDA_CMD_GET_PIN_SENSE_IMP_SENSE_SHIFT 0
+
+#define HDA_CMD_GET_PIN_SENSE_IMP_SENSE(rsp) \
+ (((rsp) & HDA_CMD_GET_PIN_SENSE_IMP_SENSE_MASK) >> \
+ HDA_CMD_GET_PIN_SENSE_IMP_SENSE_SHIFT)
+
+#define HDA_CMD_GET_PIN_SENSE_IMP_SENSE_INVALID 0x7fffffff
+
+#define HDA_CMD_SET_PIN_SENSE_LEFT_CHANNEL 0x00
+#define HDA_CMD_SET_PIN_SENSE_RIGHT_CHANNEL 0x01
+
+/* EAPD/BTL Enable */
+#define HDA_CMD_VERB_GET_EAPD_BTL_ENABLE 0xf0c
+#define HDA_CMD_VERB_SET_EAPD_BTL_ENABLE 0x70c
+
+#define HDA_CMD_GET_EAPD_BTL_ENABLE(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_EAPD_BTL_ENABLE, 0x0))
+#define HDA_CMD_SET_EAPD_BTL_ENABLE(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_EAPD_BTL_ENABLE, (payload)))
+
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP_MASK 0x00000004
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP_SHIFT 2
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_EAPD_MASK 0x00000002
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_EAPD_SHIFT 1
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_BTL_MASK 0x00000001
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_BTL_SHIFT 0
+
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP(rsp) \
+ (((rsp) & HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP_MASK) >> \
+ HDA_CMD_GET_EAPD_BTL_ENABLE_LR_SWAP_SHIFT)
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_EAPD(rsp) \
+ (((rsp) & HDA_CMD_GET_EAPD_BTL_ENABLE_EAPD_MASK) >> \
+ HDA_CMD_GET_EAPD_BTL_ENABLE_EAPD_SHIFT)
+#define HDA_CMD_GET_EAPD_BTL_ENABLE_BTL(rsp) \
+ (((rsp) & HDA_CMD_GET_EAPD_BTL_ENABLE_BTL_MASK) >> \
+ HDA_CMD_GET_EAPD_BTL_ENABLE_BTL_SHIFT)
+
+#define HDA_CMD_SET_EAPD_BTL_ENABLE_LR_SWAP 0x04
+#define HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD 0x02
+#define HDA_CMD_SET_EAPD_BTL_ENABLE_BTL 0x01
+
+/* GPI Data */
+#define HDA_CMD_VERB_GET_GPI_DATA 0xf10
+#define HDA_CMD_VERB_SET_GPI_DATA 0x710
+
+#define HDA_CMD_GET_GPI_DATA(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPI_DATA, 0x0))
+#define HDA_CMD_SET_GPI_DATA(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPI_DATA, (payload)))
+
+/* GPI Wake Enable Mask */
+#define HDA_CMD_VERB_GET_GPI_WAKE_ENABLE_MASK 0xf11
+#define HDA_CMD_VERB_SET_GPI_WAKE_ENABLE_MASK 0x711
+
+#define HDA_CMD_GET_GPI_WAKE_ENABLE_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPI_WAKE_ENABLE_MASK, 0x0))
+#define HDA_CMD_SET_GPI_WAKE_ENABLE_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPI_WAKE_ENABLE_MASK, (payload)))
+
+/* GPI Unsolicited Enable Mask */
+#define HDA_CMD_VERB_GET_GPI_UNSOLICITED_ENABLE_MASK 0xf12
+#define HDA_CMD_VERB_SET_GPI_UNSOLICITED_ENABLE_MASK 0x712
+
+#define HDA_CMD_GET_GPI_UNSOLICITED_ENABLE_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPI_UNSOLICITED_ENABLE_MASK, 0x0))
+#define HDA_CMD_SET_GPI_UNSOLICITED_ENABLE_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPI_UNSOLICITED_ENABLE_MASK, (payload)))
+
+/* GPI Sticky Mask */
+#define HDA_CMD_VERB_GET_GPI_STICKY_MASK 0xf13
+#define HDA_CMD_VERB_SET_GPI_STICKY_MASK 0x713
+
+#define HDA_CMD_GET_GPI_STICKY_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPI_STICKY_MASK, 0x0))
+#define HDA_CMD_SET_GPI_STICKY_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPI_STICKY_MASK, (payload)))
+
+/* GPO Data */
+#define HDA_CMD_VERB_GET_GPO_DATA 0xf14
+#define HDA_CMD_VERB_SET_GPO_DATA 0x714
+
+#define HDA_CMD_GET_GPO_DATA(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPO_DATA, 0x0))
+#define HDA_CMD_SET_GPO_DATA(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPO_DATA, (payload)))
+
+/* GPIO Data */
+#define HDA_CMD_VERB_GET_GPIO_DATA 0xf15
+#define HDA_CMD_VERB_SET_GPIO_DATA 0x715
+
+#define HDA_CMD_GET_GPIO_DATA(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_DATA, 0x0))
+#define HDA_CMD_SET_GPIO_DATA(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_DATA, (payload)))
+
+/* GPIO Enable Mask */
+#define HDA_CMD_VERB_GET_GPIO_ENABLE_MASK 0xf16
+#define HDA_CMD_VERB_SET_GPIO_ENABLE_MASK 0x716
+
+#define HDA_CMD_GET_GPIO_ENABLE_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_ENABLE_MASK, 0x0))
+#define HDA_CMD_SET_GPIO_ENABLE_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_ENABLE_MASK, (payload)))
+
+/* GPIO Direction */
+#define HDA_CMD_VERB_GET_GPIO_DIRECTION 0xf17
+#define HDA_CMD_VERB_SET_GPIO_DIRECTION 0x717
+
+#define HDA_CMD_GET_GPIO_DIRECTION(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_DIRECTION, 0x0))
+#define HDA_CMD_SET_GPIO_DIRECTION(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_DIRECTION, (payload)))
+
+/* GPIO Wake Enable Mask */
+#define HDA_CMD_VERB_GET_GPIO_WAKE_ENABLE_MASK 0xf18
+#define HDA_CMD_VERB_SET_GPIO_WAKE_ENABLE_MASK 0x718
+
+#define HDA_CMD_GET_GPIO_WAKE_ENABLE_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_WAKE_ENABLE_MASK, 0x0))
+#define HDA_CMD_SET_GPIO_WAKE_ENABLE_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_WAKE_ENABLE_MASK, (payload)))
+
+/* GPIO Unsolicited Enable Mask */
+#define HDA_CMD_VERB_GET_GPIO_UNSOLICITED_ENABLE_MASK 0xf19
+#define HDA_CMD_VERB_SET_GPIO_UNSOLICITED_ENABLE_MASK 0x719
+
+#define HDA_CMD_GET_GPIO_UNSOLICITED_ENABLE_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_UNSOLICITED_ENABLE_MASK, 0x0))
+#define HDA_CMD_SET_GPIO_UNSOLICITED_ENABLE_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_UNSOLICITED_ENABLE_MASK, (payload)))
+
+/* GPIO_STICKY_MASK */
+#define HDA_CMD_VERB_GET_GPIO_STICKY_MASK 0xf1a
+#define HDA_CMD_VERB_SET_GPIO_STICKY_MASK 0x71a
+
+#define HDA_CMD_GET_GPIO_STICKY_MASK(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_GPIO_STICKY_MASK, 0x0))
+#define HDA_CMD_SET_GPIO_STICKY_MASK(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_GPIO_STICKY_MASK, (payload)))
+
+/* Beep Generation */
+#define HDA_CMD_VERB_GET_BEEP_GENERATION 0xf0a
+#define HDA_CMD_VERB_SET_BEEP_GENERATION 0x70a
+
+#define HDA_CMD_GET_BEEP_GENERATION(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_BEEP_GENERATION, 0x0))
+#define HDA_CMD_SET_BEEP_GENERATION(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_BEEP_GENERATION, (payload)))
+
+/* Volume Knob */
+#define HDA_CMD_VERB_GET_VOLUME_KNOB 0xf0f
+#define HDA_CMD_VERB_SET_VOLUME_KNOB 0x70f
+
+#define HDA_CMD_GET_VOLUME_KNOB(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_VOLUME_KNOB, 0x0))
+#define HDA_CMD_SET_VOLUME_KNOB(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_VOLUME_KNOB, (payload)))
+
+/* Subsystem ID */
+#define HDA_CMD_VERB_GET_SUBSYSTEM_ID 0xf20
+#define HDA_CMD_VERB_SET_SUSBYSTEM_ID1 0x720
+#define HDA_CMD_VERB_SET_SUBSYSTEM_ID2 0x721
+#define HDA_CMD_VERB_SET_SUBSYSTEM_ID3 0x722
+#define HDA_CMD_VERB_SET_SUBSYSTEM_ID4 0x723
+
+#define HDA_CMD_GET_SUBSYSTEM_ID(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_SUBSYSTEM_ID, 0x0))
+#define HDA_CMD_SET_SUBSYSTEM_ID1(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_SUSBYSTEM_ID1, (payload)))
+#define HDA_CMD_SET_SUBSYSTEM_ID2(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_SUSBYSTEM_ID2, (payload)))
+#define HDA_CMD_SET_SUBSYSTEM_ID3(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_SUSBYSTEM_ID3, (payload)))
+#define HDA_CMD_SET_SUBSYSTEM_ID4(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_SUSBYSTEM_ID4, (payload)))
+
+/* Configuration Default */
+#define HDA_CMD_VERB_GET_CONFIGURATION_DEFAULT 0xf1c
+#define HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT1 0x71c
+#define HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT2 0x71d
+#define HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT3 0x71e
+#define HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT4 0x71f
+
+#define HDA_CMD_GET_CONFIGURATION_DEFAULT(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_CONFIGURATION_DEFAULT, 0x0))
+#define HDA_CMD_SET_CONFIGURATION_DEFAULT1(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT1, (payload)))
+#define HDA_CMD_SET_CONFIGURATION_DEFAULT2(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT2, (payload)))
+#define HDA_CMD_SET_CONFIGURATION_DEFAULT3(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT3, (payload)))
+#define HDA_CMD_SET_CONFIGURATION_DEFAULT4(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONFIGURATION_DEFAULT4, (payload)))
+
+/* Stripe Control */
+#define HDA_CMD_VERB_GET_STRIPE_CONTROL 0xf24
+#define HDA_CMD_VERB_SET_STRIPE_CONTROL 0x724
+
+#define HDA_CMD_GET_STRIPE_CONTROL(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_STRIPE_CONTROL, 0x0))
+#define HDA_CMD_SET_STRIPE_CONTROL(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_STRIPE_CONTROL, (payload)))
+
+/* Channel Count Control */
+#define HDA_CMD_VERB_GET_CONV_CHAN_COUNT 0xf2d
+#define HDA_CMD_VERB_SET_CONV_CHAN_COUNT 0x72d
+
+#define HDA_CMD_GET_CONV_CHAN_COUNT(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_CONV_CHAN_COUNT, 0x0))
+#define HDA_CMD_SET_CONV_CHAN_COUNT(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_CONV_CHAN_COUNT, (payload)))
+
+#define HDA_CMD_VERB_GET_HDMI_DIP_SIZE 0xf2e
+
+#define HDA_CMD_GET_HDMI_DIP_SIZE(cad, nid, arg) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_HDMI_DIP_SIZE, (arg)))
+
+#define HDA_CMD_VERB_GET_HDMI_ELDD 0xf2f
+
+#define HDA_CMD_GET_HDMI_ELDD(cad, nid, off) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_HDMI_ELDD, (off)))
+
+#define HDA_CMD_VERB_GET_HDMI_DIP_INDEX 0xf30
+#define HDA_CMD_VERB_SET_HDMI_DIP_INDEX 0x730
+
+#define HDA_CMD_GET_HDMI_DIP_INDEX(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_HDMI_DIP_INDEX, 0x0))
+#define HDA_CMD_SET_HDMI_DIP_INDEX(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_HDMI_DIP_INDEX, (payload)))
+
+#define HDA_CMD_VERB_GET_HDMI_DIP_DATA 0xf31
+#define HDA_CMD_VERB_SET_HDMI_DIP_DATA 0x731
+
+#define HDA_CMD_GET_HDMI_DIP_DATA(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_HDMI_DIP_DATA, 0x0))
+#define HDA_CMD_SET_HDMI_DIP_DATA(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_HDMI_DIP_DATA, (payload)))
+
+#define HDA_CMD_VERB_GET_HDMI_DIP_XMIT 0xf32
+#define HDA_CMD_VERB_SET_HDMI_DIP_XMIT 0x732
+
+#define HDA_CMD_GET_HDMI_DIP_XMIT(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_HDMI_DIP_XMIT, 0x0))
+#define HDA_CMD_SET_HDMI_DIP_XMIT(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_HDMI_DIP_XMIT, (payload)))
+
+#define HDA_CMD_VERB_GET_HDMI_CP_CTRL 0xf33
+#define HDA_CMD_VERB_SET_HDMI_CP_CTRL 0x733
+
+#define HDA_CMD_VERB_GET_HDMI_CHAN_SLOT 0xf34
+#define HDA_CMD_VERB_SET_HDMI_CHAN_SLOT 0x734
+
+#define HDA_CMD_GET_HDMI_CHAN_SLOT(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_GET_HDMI_CHAN_SLOT, 0x0))
+#define HDA_CMD_SET_HDMI_CHAN_SLOT(cad, nid, payload) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_SET_HDMI_CHAN_SLOT, (payload)))
+
+#define HDA_HDMI_CODING_TYPE_REF_STREAM_HEADER 0
+#define HDA_HDMI_CODING_TYPE_LPCM 1
+#define HDA_HDMI_CODING_TYPE_AC3 2
+#define HDA_HDMI_CODING_TYPE_MPEG1 3
+#define HDA_HDMI_CODING_TYPE_MP3 4
+#define HDA_HDMI_CODING_TYPE_MPEG2 5
+#define HDA_HDMI_CODING_TYPE_AACLC 6
+#define HDA_HDMI_CODING_TYPE_DTS 7
+#define HDA_HDMI_CODING_TYPE_ATRAC 8
+#define HDA_HDMI_CODING_TYPE_SACD 9
+#define HDA_HDMI_CODING_TYPE_EAC3 10
+#define HDA_HDMI_CODING_TYPE_DTS_HD 11
+#define HDA_HDMI_CODING_TYPE_MLP 12
+#define HDA_HDMI_CODING_TYPE_DST 13
+#define HDA_HDMI_CODING_TYPE_WMAPRO 14
+#define HDA_HDMI_CODING_TYPE_REF_CTX 15
+
+/* Function Reset */
+#define HDA_CMD_VERB_FUNCTION_RESET 0x7ff
+
+#define HDA_CMD_FUNCTION_RESET(cad, nid) \
+ (HDA_CMD_12BIT((cad), (nid), \
+ HDA_CMD_VERB_FUNCTION_RESET, 0x0))
+
+
+/****************************************************************************
+ * HDA Device Parameters
+ ****************************************************************************/
+
+/* Vendor ID */
+#define HDA_PARAM_VENDOR_ID 0x00
+
+#define HDA_PARAM_VENDOR_ID_VENDOR_ID_MASK 0xffff0000
+#define HDA_PARAM_VENDOR_ID_VENDOR_ID_SHIFT 16
+#define HDA_PARAM_VENDOR_ID_DEVICE_ID_MASK 0x0000ffff
+#define HDA_PARAM_VENDOR_ID_DEVICE_ID_SHIFT 0
+
+#define HDA_PARAM_VENDOR_ID_VENDOR_ID(param) \
+ (((param) & HDA_PARAM_VENDOR_ID_VENDOR_ID_MASK) >> \
+ HDA_PARAM_VENDOR_ID_VENDOR_ID_SHIFT)
+#define HDA_PARAM_VENDOR_ID_DEVICE_ID(param) \
+ (((param) & HDA_PARAM_VENDOR_ID_DEVICE_ID_MASK) >> \
+ HDA_PARAM_VENDOR_ID_DEVICE_ID_SHIFT)
+
+/* Revision ID */
+#define HDA_PARAM_REVISION_ID 0x02
+
+#define HDA_PARAM_REVISION_ID_MAJREV_MASK 0x00f00000
+#define HDA_PARAM_REVISION_ID_MAJREV_SHIFT 20
+#define HDA_PARAM_REVISION_ID_MINREV_MASK 0x000f0000
+#define HDA_PARAM_REVISION_ID_MINREV_SHIFT 16
+#define HDA_PARAM_REVISION_ID_REVISION_ID_MASK 0x0000ff00
+#define HDA_PARAM_REVISION_ID_REVISION_ID_SHIFT 8
+#define HDA_PARAM_REVISION_ID_STEPPING_ID_MASK 0x000000ff
+#define HDA_PARAM_REVISION_ID_STEPPING_ID_SHIFT 0
+
+#define HDA_PARAM_REVISION_ID_MAJREV(param) \
+ (((param) & HDA_PARAM_REVISION_ID_MAJREV_MASK) >> \
+ HDA_PARAM_REVISION_ID_MAJREV_SHIFT)
+#define HDA_PARAM_REVISION_ID_MINREV(param) \
+ (((param) & HDA_PARAM_REVISION_ID_MINREV_MASK) >> \
+ HDA_PARAM_REVISION_ID_MINREV_SHIFT)
+#define HDA_PARAM_REVISION_ID_REVISION_ID(param) \
+ (((param) & HDA_PARAM_REVISION_ID_REVISION_ID_MASK) >> \
+ HDA_PARAM_REVISION_ID_REVISION_ID_SHIFT)
+#define HDA_PARAM_REVISION_ID_STEPPING_ID(param) \
+ (((param) & HDA_PARAM_REVISION_ID_STEPPING_ID_MASK) >> \
+ HDA_PARAM_REVISION_ID_STEPPING_ID_SHIFT)
+
+/* Subordinate Node Cound */
+#define HDA_PARAM_SUB_NODE_COUNT 0x04
+
+#define HDA_PARAM_SUB_NODE_COUNT_START_MASK 0x00ff0000
+#define HDA_PARAM_SUB_NODE_COUNT_START_SHIFT 16
+#define HDA_PARAM_SUB_NODE_COUNT_TOTAL_MASK 0x000000ff
+#define HDA_PARAM_SUB_NODE_COUNT_TOTAL_SHIFT 0
+
+#define HDA_PARAM_SUB_NODE_COUNT_START(param) \
+ (((param) & HDA_PARAM_SUB_NODE_COUNT_START_MASK) >> \
+ HDA_PARAM_SUB_NODE_COUNT_START_SHIFT)
+#define HDA_PARAM_SUB_NODE_COUNT_TOTAL(param) \
+ (((param) & HDA_PARAM_SUB_NODE_COUNT_TOTAL_MASK) >> \
+ HDA_PARAM_SUB_NODE_COUNT_TOTAL_SHIFT)
+
+/* Function Group Type */
+#define HDA_PARAM_FCT_GRP_TYPE 0x05
+
+#define HDA_PARAM_FCT_GRP_TYPE_UNSOL_MASK 0x00000100
+#define HDA_PARAM_FCT_GRP_TYPE_UNSOL_SHIFT 8
+#define HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MASK 0x000000ff
+#define HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_SHIFT 0
+
+#define HDA_PARAM_FCT_GRP_TYPE_UNSOL(param) \
+ (((param) & HDA_PARAM_FCT_GRP_TYPE_UNSOL_MASK) >> \
+ HDA_PARAM_FCT_GROUP_TYPE_UNSOL_SHIFT)
+#define HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE(param) \
+ (((param) & HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MASK) >> \
+ HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_SHIFT)
+
+#define HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_AUDIO 0x01
+#define HDA_PARAM_FCT_GRP_TYPE_NODE_TYPE_MODEM 0x02
+
+/* Audio Function Group Capabilities */
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP 0x08
+
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_BEEP_GEN_MASK 0x00010000
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_BEEP_GEN_SHIFT 16
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_INPUT_DELAY_MASK 0x00000f00
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_INPUT_DELAY_SHIFT 8
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY_MASK 0x0000000f
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY_SHIFT 0
+
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_BEEP_GEN(param) \
+ (((param) & HDA_PARAM_AUDIO_FCT_GRP_CAP_BEEP_GEN_MASK) >> \
+ HDA_PARAM_AUDIO_FCT_GRP_CAP_BEEP_GEN_SHIFT)
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_INPUT_DELAY(param) \
+ (((param) & HDA_PARAM_AUDIO_FCT_GRP_CAP_INPUT_DELAY_MASK) >> \
+ HDA_PARAM_AUDIO_FCT_GRP_CAP_INPUT_DELAY_SHIFT)
+#define HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY(param) \
+ (((param) & HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY_MASK) >> \
+ HDA_PARAM_AUDIO_FCT_GRP_CAP_OUTPUT_DELAY_SHIFT)
+
+/* Audio Widget Capabilities */
+#define HDA_PARAM_AUDIO_WIDGET_CAP 0x09
+
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK 0x00f00000
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT 20
+#define HDA_PARAM_AUDIO_WIDGET_CAP_DELAY_MASK 0x000f0000
+#define HDA_PARAM_AUDIO_WIDGET_CAP_DELAY_SHIFT 16
+#define HDA_PARAM_AUDIO_WIDGET_CAP_CC_EXT_MASK 0x0000e000
+#define HDA_PARAM_AUDIO_WIDGET_CAP_CC_EXT_SHIFT 13
+#define HDA_PARAM_AUDIO_WIDGET_CAP_CP_MASK 0x00001000
+#define HDA_PARAM_AUDIO_WIDGET_CAP_CP_SHIFT 12
+#define HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP_MASK 0x00000800
+#define HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP_SHIFT 11
+#define HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL_MASK 0x00000400
+#define HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL_SHIFT 10
+#define HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK 0x00000200
+#define HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_SHIFT 9
+#define HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_MASK 0x00000100
+#define HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_SHIFT 8
+#define HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP_MASK 0x00000080
+#define HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP_SHIFT 7
+#define HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET_MASK 0x00000040
+#define HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET_SHIFT 6
+#define HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE_MASK 0x00000020
+#define HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE_SHIFT 5
+#define HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR_MASK 0x00000010
+#define HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR_SHIFT 4
+#define HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR_MASK 0x00000008
+#define HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR_SHIFT 3
+#define HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP_MASK 0x00000004
+#define HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP_SHIFT 2
+#define HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP_MASK 0x00000002
+#define HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP_SHIFT 1
+#define HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_MASK 0x00000001
+#define HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_SHIFT 0
+
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_DELAY(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_DELAY_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_DELAY_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_CC(param) \
+ ((((param) & HDA_PARAM_AUDIO_WIDGET_CAP_CC_EXT_MASK) >> \
+ (HDA_PARAM_AUDIO_WIDGET_CAP_CC_EXT_SHIFT - 1)) | \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_SHIFT))
+#define HDA_PARAM_AUDIO_WIDGET_CAP_CP(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_CP_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_CP_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_LR_SWAP_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_POWER_CTRL_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_CONN_LIST_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_UNSOL_CAP_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_PROC_WIDGET_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_STRIPE_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_FORMAT_OVR_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_AMP_OVR_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_OUT_AMP_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_IN_AMP_SHIFT)
+#define HDA_PARAM_AUDIO_WIDGET_CAP_STEREO(param) \
+ (((param) & HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_MASK) >> \
+ HDA_PARAM_AUDIO_WIDGET_CAP_STEREO_SHIFT)
+
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_OUTPUT 0x0
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_INPUT 0x1
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_MIXER 0x2
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_AUDIO_SELECTOR 0x3
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX 0x4
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_POWER_WIDGET 0x5
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VOLUME_WIDGET 0x6
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET 0x7
+#define HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_VENDOR_WIDGET 0xf
+
+/* Supported PCM Size, Rates */
+
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE 0x0a
+
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT_MASK 0x00100000
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT_SHIFT 20
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT_MASK 0x00080000
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT_SHIFT 19
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT_MASK 0x00040000
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT_SHIFT 18
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT_MASK 0x00020000
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT_SHIFT 17
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT_MASK 0x00010000
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT_SHIFT 16
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_MASK 0x00000001
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_SHIFT 0
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_MASK 0x00000002
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_SHIFT 1
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_MASK 0x00000004
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_SHIFT 2
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_MASK 0x00000008
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_SHIFT 3
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_MASK 0x00000010
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_SHIFT 4
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_MASK 0x00000020
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_SHIFT 5
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_MASK 0x00000040
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_SHIFT 6
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_MASK 0x00000080
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_SHIFT 7
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_MASK 0x00000100
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_SHIFT 8
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_MASK 0x00000200
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_SHIFT 9
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_MASK 0x00000400
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_SHIFT 10
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_MASK 0x00000800
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_SHIFT 11
+
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_32BIT_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_24BIT_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_20BIT_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_16BIT_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_8BIT_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_8KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_11KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_16KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_22KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_32KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_44KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_48KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_88KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_96KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_176KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_192KHZ_SHIFT)
+#define HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ(param) \
+ (((param) & HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_MASK) >> \
+ HDA_PARAM_SUPP_PCM_SIZE_RATE_384KHZ_SHIFT)
+
+/* Supported Stream Formats */
+#define HDA_PARAM_SUPP_STREAM_FORMATS 0x0b
+
+#define HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK 0x00000004
+#define HDA_PARAM_SUPP_STREAM_FORMATS_AC3_SHIFT 2
+#define HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32_MASK 0x00000002
+#define HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32_SHIFT 1
+#define HDA_PARAM_SUPP_STREAM_FORMATS_PCM_MASK 0x00000001
+#define HDA_PARAM_SUPP_STREAM_FORMATS_PCM_SHIFT 0
+
+#define HDA_PARAM_SUPP_STREAM_FORMATS_AC3(param) \
+ (((param) & HDA_PARAM_SUPP_STREAM_FORMATS_AC3_MASK) >> \
+ HDA_PARAM_SUPP_STREAM_FORMATS_AC3_SHIFT)
+#define HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32(param) \
+ (((param) & HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32_MASK) >> \
+ HDA_PARAM_SUPP_STREAM_FORMATS_FLOAT32_SHIFT)
+#define HDA_PARAM_SUPP_STREAM_FORMATS_PCM(param) \
+ (((param) & HDA_PARAM_SUPP_STREAM_FORMATS_PCM_MASK) >> \
+ HDA_PARAM_SUPP_STREAM_FORMATS_PCM_SHIFT)
+
+/* Pin Capabilities */
+#define HDA_PARAM_PIN_CAP 0x0c
+
+#define HDA_PARAM_PIN_CAP_HBR_MASK 0x08000000
+#define HDA_PARAM_PIN_CAP_HBR_SHIFT 27
+#define HDA_PARAM_PIN_CAP_DP_MASK 0x01000000
+#define HDA_PARAM_PIN_CAP_DP_SHIFT 24
+#define HDA_PARAM_PIN_CAP_EAPD_CAP_MASK 0x00010000
+#define HDA_PARAM_PIN_CAP_EAPD_CAP_SHIFT 16
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_MASK 0x0000ff00
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_SHIFT 8
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK 0x00002000
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_100_SHIFT 13
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK 0x00001000
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_80_SHIFT 12
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND_MASK 0x00000400
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND_SHIFT 10
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK 0x00000200
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_50_SHIFT 9
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ_MASK 0x00000100
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ_SHIFT 8
+#define HDA_PARAM_PIN_CAP_HDMI_MASK 0x00000080
+#define HDA_PARAM_PIN_CAP_HDMI_SHIFT 7
+#define HDA_PARAM_PIN_CAP_BALANCED_IO_PINS_MASK 0x00000040
+#define HDA_PARAM_PIN_CAP_BALANCED_IO_PINS_SHIFT 6
+#define HDA_PARAM_PIN_CAP_INPUT_CAP_MASK 0x00000020
+#define HDA_PARAM_PIN_CAP_INPUT_CAP_SHIFT 5
+#define HDA_PARAM_PIN_CAP_OUTPUT_CAP_MASK 0x00000010
+#define HDA_PARAM_PIN_CAP_OUTPUT_CAP_SHIFT 4
+#define HDA_PARAM_PIN_CAP_HEADPHONE_CAP_MASK 0x00000008
+#define HDA_PARAM_PIN_CAP_HEADPHONE_CAP_SHIFT 3
+#define HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP_MASK 0x00000004
+#define HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP_SHIFT 2
+#define HDA_PARAM_PIN_CAP_TRIGGER_REQD_MASK 0x00000002
+#define HDA_PARAM_PIN_CAP_TRIGGER_REQD_SHIFT 1
+#define HDA_PARAM_PIN_CAP_IMP_SENSE_CAP_MASK 0x00000001
+#define HDA_PARAM_PIN_CAP_IMP_SENSE_CAP_SHIFT 0
+
+#define HDA_PARAM_PIN_CAP_HBR(param) \
+ (((param) & HDA_PARAM_PIN_CAP_HBR_MASK) >> \
+ HDA_PARAM_PIN_CAP_HBR_SHIFT)
+#define HDA_PARAM_PIN_CAP_DP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_DP_MASK) >> \
+ HDA_PARAM_PIN_CAP_DP_SHIFT)
+#define HDA_PARAM_PIN_CAP_EAPD_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_EAPD_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_EAPD_CAP_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_100(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_100_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_100_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_80(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_80_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_80_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_GROUND_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_50(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_50_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_50_SHIFT)
+#define HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ(param) \
+ (((param) & HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ_MASK) >> \
+ HDA_PARAM_PIN_CAP_VREF_CTRL_HIZ_SHIFT)
+#define HDA_PARAM_PIN_CAP_HDMI(param) \
+ (((param) & HDA_PARAM_PIN_CAP_HDMI_MASK) >> \
+ HDA_PARAM_PIN_CAP_HDMI_SHIFT)
+#define HDA_PARAM_PIN_CAP_BALANCED_IO_PINS(param) \
+ (((param) & HDA_PARAM_PIN_CAP_BALANCED_IO_PINS_MASK) >> \
+ HDA_PARAM_PIN_CAP_BALANCED_IO_PINS_SHIFT)
+#define HDA_PARAM_PIN_CAP_INPUT_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_INPUT_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_INPUT_CAP_SHIFT)
+#define HDA_PARAM_PIN_CAP_OUTPUT_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_OUTPUT_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_OUTPUT_CAP_SHIFT)
+#define HDA_PARAM_PIN_CAP_HEADPHONE_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_HEADPHONE_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_HEADPHONE_CAP_SHIFT)
+#define HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_PRESENCE_DETECT_CAP_SHIFT)
+#define HDA_PARAM_PIN_CAP_TRIGGER_REQD(param) \
+ (((param) & HDA_PARAM_PIN_CAP_TRIGGER_REQD_MASK) >> \
+ HDA_PARAM_PIN_CAP_TRIGGER_REQD_SHIFT)
+#define HDA_PARAM_PIN_CAP_IMP_SENSE_CAP(param) \
+ (((param) & HDA_PARAM_PIN_CAP_IMP_SENSE_CAP_MASK) >> \
+ HDA_PARAM_PIN_CAP_IMP_SENSE_CAP_SHIFT)
+
+/* Input Amplifier Capabilities */
+#define HDA_PARAM_INPUT_AMP_CAP 0x0d
+
+#define HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP_MASK 0x80000000
+#define HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP_SHIFT 31
+#define HDA_PARAM_INPUT_AMP_CAP_STEPSIZE_MASK 0x007f0000
+#define HDA_PARAM_INPUT_AMP_CAP_STEPSIZE_SHIFT 16
+#define HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS_MASK 0x00007f00
+#define HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS_SHIFT 8
+#define HDA_PARAM_INPUT_AMP_CAP_OFFSET_MASK 0x0000007f
+#define HDA_PARAM_INPUT_AMP_CAP_OFFSET_SHIFT 0
+
+#define HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP(param) \
+ (((param) & HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP_MASK) >> \
+ HDA_PARAM_INPUT_AMP_CAP_MUTE_CAP_SHIFT)
+#define HDA_PARAM_INPUT_AMP_CAP_STEPSIZE(param) \
+ (((param) & HDA_PARAM_INPUT_AMP_CAP_STEPSIZE_MASK) >> \
+ HDA_PARAM_INPUT_AMP_CAP_STEPSIZE_SHIFT)
+#define HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS(param) \
+ (((param) & HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS_MASK) >> \
+ HDA_PARAM_INPUT_AMP_CAP_NUMSTEPS_SHIFT)
+#define HDA_PARAM_INPUT_AMP_CAP_OFFSET(param) \
+ (((param) & HDA_PARAM_INPUT_AMP_CAP_OFFSET_MASK) >> \
+ HDA_PARAM_INPUT_AMP_CAP_OFFSET_SHIFT)
+
+/* Output Amplifier Capabilities */
+#define HDA_PARAM_OUTPUT_AMP_CAP 0x12
+
+#define HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP_MASK 0x80000000
+#define HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP_SHIFT 31
+#define HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_MASK 0x007f0000
+#define HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT 16
+#define HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_MASK 0x00007f00
+#define HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT 8
+#define HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_MASK 0x0000007f
+#define HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT 0
+
+#define HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP(param) \
+ (((param) & HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP_MASK) >> \
+ HDA_PARAM_OUTPUT_AMP_CAP_MUTE_CAP_SHIFT)
+#define HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE(param) \
+ (((param) & HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_MASK) >> \
+ HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT)
+#define HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS(param) \
+ (((param) & HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_MASK) >> \
+ HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT)
+#define HDA_PARAM_OUTPUT_AMP_CAP_OFFSET(param) \
+ (((param) & HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_MASK) >> \
+ HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT)
+
+/* Connection List Length */
+#define HDA_PARAM_CONN_LIST_LENGTH 0x0e
+
+#define HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM_MASK 0x00000080
+#define HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM_SHIFT 7
+#define HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH_MASK 0x0000007f
+#define HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH_SHIFT 0
+
+#define HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM(param) \
+ (((param) & HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM_MASK) >> \
+ HDA_PARAM_CONN_LIST_LENGTH_LONG_FORM_SHIFT)
+#define HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH(param) \
+ (((param) & HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH_MASK) >> \
+ HDA_PARAM_CONN_LIST_LENGTH_LIST_LENGTH_SHIFT)
+
+/* Supported Power States */
+#define HDA_PARAM_SUPP_POWER_STATES 0x0f
+
+#define HDA_PARAM_SUPP_POWER_STATES_D3_MASK 0x00000008
+#define HDA_PARAM_SUPP_POWER_STATES_D3_SHIFT 3
+#define HDA_PARAM_SUPP_POWER_STATES_D2_MASK 0x00000004
+#define HDA_PARAM_SUPP_POWER_STATES_D2_SHIFT 2
+#define HDA_PARAM_SUPP_POWER_STATES_D1_MASK 0x00000002
+#define HDA_PARAM_SUPP_POWER_STATES_D1_SHIFT 1
+#define HDA_PARAM_SUPP_POWER_STATES_D0_MASK 0x00000001
+#define HDA_PARAM_SUPP_POWER_STATES_D0_SHIFT 0
+
+#define HDA_PARAM_SUPP_POWER_STATES_D3(param) \
+ (((param) & HDA_PARAM_SUPP_POWER_STATES_D3_MASK) >> \
+ HDA_PARAM_SUPP_POWER_STATES_D3_SHIFT)
+#define HDA_PARAM_SUPP_POWER_STATES_D2(param) \
+ (((param) & HDA_PARAM_SUPP_POWER_STATES_D2_MASK) >> \
+ HDA_PARAM_SUPP_POWER_STATES_D2_SHIFT)
+#define HDA_PARAM_SUPP_POWER_STATES_D1(param) \
+ (((param) & HDA_PARAM_SUPP_POWER_STATES_D1_MASK) >> \
+ HDA_PARAM_SUPP_POWER_STATES_D1_SHIFT)
+#define HDA_PARAM_SUPP_POWER_STATES_D0(param) \
+ (((param) & HDA_PARAM_SUPP_POWER_STATES_D0_MASK) >> \
+ HDA_PARAM_SUPP_POWER_STATES_D0_SHIFT)
+
+/* Processing Capabilities */
+#define HDA_PARAM_PROCESSING_CAP 0x10
+
+#define HDA_PARAM_PROCESSING_CAP_NUMCOEFF_MASK 0x0000ff00
+#define HDA_PARAM_PROCESSING_CAP_NUMCOEFF_SHIFT 8
+#define HDA_PARAM_PROCESSING_CAP_BENIGN_MASK 0x00000001
+#define HDA_PARAM_PROCESSING_CAP_BENIGN_SHIFT 0
+
+#define HDA_PARAM_PROCESSING_CAP_NUMCOEFF(param) \
+ (((param) & HDA_PARAM_PROCESSING_CAP_NUMCOEFF_MASK) >> \
+ HDA_PARAM_PROCESSING_CAP_NUMCOEFF_SHIFT)
+#define HDA_PARAM_PROCESSING_CAP_BENIGN(param) \
+ (((param) & HDA_PARAM_PROCESSING_CAP_BENIGN_MASK) >> \
+ HDA_PARAM_PROCESSING_CAP_BENIGN_SHIFT)
+
+/* GPIO Count */
+#define HDA_PARAM_GPIO_COUNT 0x11
+
+#define HDA_PARAM_GPIO_COUNT_GPI_WAKE_MASK 0x80000000
+#define HDA_PARAM_GPIO_COUNT_GPI_WAKE_SHIFT 31
+#define HDA_PARAM_GPIO_COUNT_GPI_UNSOL_MASK 0x40000000
+#define HDA_PARAM_GPIO_COUNT_GPI_UNSOL_SHIFT 30
+#define HDA_PARAM_GPIO_COUNT_NUM_GPI_MASK 0x00ff0000
+#define HDA_PARAM_GPIO_COUNT_NUM_GPI_SHIFT 16
+#define HDA_PARAM_GPIO_COUNT_NUM_GPO_MASK 0x0000ff00
+#define HDA_PARAM_GPIO_COUNT_NUM_GPO_SHIFT 8
+#define HDA_PARAM_GPIO_COUNT_NUM_GPIO_MASK 0x000000ff
+#define HDA_PARAM_GPIO_COUNT_NUM_GPIO_SHIFT 0
+
+#define HDA_PARAM_GPIO_COUNT_GPI_WAKE(param) \
+ (((param) & HDA_PARAM_GPIO_COUNT_GPI_WAKE_MASK) >> \
+ HDA_PARAM_GPIO_COUNT_GPI_WAKE_SHIFT)
+#define HDA_PARAM_GPIO_COUNT_GPI_UNSOL(param) \
+ (((param) & HDA_PARAM_GPIO_COUNT_GPI_UNSOL_MASK) >> \
+ HDA_PARAM_GPIO_COUNT_GPI_UNSOL_SHIFT)
+#define HDA_PARAM_GPIO_COUNT_NUM_GPI(param) \
+ (((param) & HDA_PARAM_GPIO_COUNT_NUM_GPI_MASK) >> \
+ HDA_PARAM_GPIO_COUNT_NUM_GPI_SHIFT)
+#define HDA_PARAM_GPIO_COUNT_NUM_GPO(param) \
+ (((param) & HDA_PARAM_GPIO_COUNT_NUM_GPO_MASK) >> \
+ HDA_PARAM_GPIO_COUNT_NUM_GPO_SHIFT)
+#define HDA_PARAM_GPIO_COUNT_NUM_GPIO(param) \
+ (((param) & HDA_PARAM_GPIO_COUNT_NUM_GPIO_MASK) >> \
+ HDA_PARAM_GPIO_COUNT_NUM_GPIO_SHIFT)
+
+/* Volume Knob Capabilities */
+#define HDA_PARAM_VOLUME_KNOB_CAP 0x13
+
+#define HDA_PARAM_VOLUME_KNOB_CAP_DELTA_MASK 0x00000080
+#define HDA_PARAM_VOLUME_KNOB_CAP_DELTA_SHIFT 7
+#define HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_MASK 0x0000007f
+#define HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_SHIFT 0
+
+#define HDA_PARAM_VOLUME_KNOB_CAP_DELTA(param) \
+ (((param) & HDA_PARAM_VOLUME_KNOB_CAP_DELTA_MASK) >> \
+ HDA_PARAM_VOLUME_KNOB_CAP_DELTA_SHIFT)
+#define HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS(param) \
+ (((param) & HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_MASK) >> \
+ HDA_PARAM_VOLUME_KNOB_CAP_NUM_STEPS_SHIFT)
+
+
+#define HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK 0x0000000f
+#define HDA_CONFIG_DEFAULTCONF_SEQUENCE_SHIFT 0
+#define HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK 0x000000f0
+#define HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT 4
+#define HDA_CONFIG_DEFAULTCONF_MISC_MASK 0x00000f00
+#define HDA_CONFIG_DEFAULTCONF_MISC_SHIFT 8
+#define HDA_CONFIG_DEFAULTCONF_COLOR_MASK 0x0000f000
+#define HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT 12
+#define HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK 0x000f0000
+#define HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_SHIFT 16
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_MASK 0x00f00000
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT 20
+#define HDA_CONFIG_DEFAULTCONF_LOCATION_MASK 0x3f000000
+#define HDA_CONFIG_DEFAULTCONF_LOCATION_SHIFT 24
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK 0xc0000000
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT 30
+
+#define HDA_CONFIG_DEFAULTCONF_SEQUENCE(conf) \
+ (((conf) & HDA_CONFIG_DEFAULTCONF_SEQUENCE_MASK) >> \
+ HDA_CONFIG_DEFAULTCONF_SEQUENCE_SHIFT)
+#define HDA_CONFIG_DEFAULTCONF_ASSOCIATION(conf) \
+ (((conf) & HDA_CONFIG_DEFAULTCONF_ASSOCIATION_MASK) >> \
+ HDA_CONFIG_DEFAULTCONF_ASSOCIATION_SHIFT)
+#define HDA_CONFIG_DEFAULTCONF_MISC(conf) \
+ (((conf) & HDA_CONFIG_DEFAULTCONF_MISC_MASK) >> \
+ HDA_CONFIG_DEFAULTCONF_MISC_SHIFT)
+#define HDA_CONFIG_DEFAULTCONF_COLOR(conf) \
+ (((conf) & HDA_CONFIG_DEFAULTCONF_COLOR_MASK) >> \
+ HDA_CONFIG_DEFAULTCONF_COLOR_SHIFT)
+#define HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE(conf) \
+ (((conf) & HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_MASK) >> \
+ HDA_CONFIG_DEFAULTCONF_CONNECTION_TYPE_SHIFT)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE(conf) \
+ (((conf) & HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) >> \
+ HDA_CONFIG_DEFAULTCONF_DEVICE_SHIFT)
+#define HDA_CONFIG_DEFAULTCONF_LOCATION(conf) \
+ (((conf) & HDA_CONFIG_DEFAULTCONF_LOCATION_MASK) >> \
+ HDA_CONFIG_DEFAULTCONF_LOCATION_SHIFT)
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY(conf) \
+ (((conf) & HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) >> \
+ HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_SHIFT)
+
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK (0<<30)
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE (1<<30)
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED (2<<30)
+#define HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_BOTH (3<<30)
+
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT (0<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_SPEAKER (1<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT (2<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_CD (3<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_OUT (4<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_OUT (5<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_LINE (6<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_MODEM_HANDSET (7<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN (8<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_AUX (9<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN (10<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_TELEPHONY (11<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_SPDIF_IN (12<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_DIGITAL_OTHER_IN (13<<20)
+#define HDA_CONFIG_DEFAULTCONF_DEVICE_OTHER (15<<20)
+
+#endif /* _HDA_REG_H_ */
diff --git a/usr.sbin/bhyve/hdac_reg.h b/usr.sbin/bhyve/hdac_reg.h
new file mode 100644
index 000000000000..35272e5135cb
--- /dev/null
+++ b/usr.sbin/bhyve/hdac_reg.h
@@ -0,0 +1,271 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _HDAC_REG_H_
+#define _HDAC_REG_H_
+
+/****************************************************************************
+ * HDA Controller Register Set
+ ****************************************************************************/
+#define HDAC_GCAP 0x00 /* 2 - Global Capabilities*/
+#define HDAC_VMIN 0x02 /* 1 - Minor Version */
+#define HDAC_VMAJ 0x03 /* 1 - Major Version */
+#define HDAC_OUTPAY 0x04 /* 2 - Output Payload Capability */
+#define HDAC_INPAY 0x06 /* 2 - Input Payload Capability */
+#define HDAC_GCTL 0x08 /* 4 - Global Control */
+#define HDAC_WAKEEN 0x0c /* 2 - Wake Enable */
+#define HDAC_STATESTS 0x0e /* 2 - State Change Status */
+#define HDAC_GSTS 0x10 /* 2 - Global Status */
+#define HDAC_OUTSTRMPAY 0x18 /* 2 - Output Stream Payload Capability */
+#define HDAC_INSTRMPAY 0x1a /* 2 - Input Stream Payload Capability */
+#define HDAC_INTCTL 0x20 /* 4 - Interrupt Control */
+#define HDAC_INTSTS 0x24 /* 4 - Interrupt Status */
+#define HDAC_WALCLK 0x30 /* 4 - Wall Clock Counter */
+#define HDAC_SSYNC 0x38 /* 4 - Stream Synchronization */
+#define HDAC_CORBLBASE 0x40 /* 4 - CORB Lower Base Address */
+#define HDAC_CORBUBASE 0x44 /* 4 - CORB Upper Base Address */
+#define HDAC_CORBWP 0x48 /* 2 - CORB Write Pointer */
+#define HDAC_CORBRP 0x4a /* 2 - CORB Read Pointer */
+#define HDAC_CORBCTL 0x4c /* 1 - CORB Control */
+#define HDAC_CORBSTS 0x4d /* 1 - CORB Status */
+#define HDAC_CORBSIZE 0x4e /* 1 - CORB Size */
+#define HDAC_RIRBLBASE 0x50 /* 4 - RIRB Lower Base Address */
+#define HDAC_RIRBUBASE 0x54 /* 4 - RIRB Upper Base Address */
+#define HDAC_RIRBWP 0x58 /* 2 - RIRB Write Pointer */
+#define HDAC_RINTCNT 0x5a /* 2 - Response Interrupt Count */
+#define HDAC_RIRBCTL 0x5c /* 1 - RIRB Control */
+#define HDAC_RIRBSTS 0x5d /* 1 - RIRB Status */
+#define HDAC_RIRBSIZE 0x5e /* 1 - RIRB Size */
+#define HDAC_ICOI 0x60 /* 4 - Immediate Command Output Interface */
+#define HDAC_ICII 0x64 /* 4 - Immediate Command Input Interface */
+#define HDAC_ICIS 0x68 /* 2 - Immediate Command Status */
+#define HDAC_DPIBLBASE 0x70 /* 4 - DMA Position Buffer Lower Base */
+#define HDAC_DPIBUBASE 0x74 /* 4 - DMA Position Buffer Upper Base */
+#define HDAC_SDCTL0 0x80 /* 3 - Stream Descriptor Control */
+#define HDAC_SDCTL1 0x81 /* 3 - Stream Descriptor Control */
+#define HDAC_SDCTL2 0x82 /* 3 - Stream Descriptor Control */
+#define HDAC_SDSTS 0x83 /* 1 - Stream Descriptor Status */
+#define HDAC_SDLPIB 0x84 /* 4 - Link Position in Buffer */
+#define HDAC_SDCBL 0x88 /* 4 - Cyclic Buffer Length */
+#define HDAC_SDLVI 0x8C /* 2 - Last Valid Index */
+#define HDAC_SDFIFOS 0x90 /* 2 - FIFOS */
+#define HDAC_SDFMT 0x92 /* 2 - fmt */
+#define HDAC_SDBDPL 0x98 /* 4 - Buffer Descriptor Pointer Lower Base */
+#define HDAC_SDBDPU 0x9C /* 4 - Buffer Descriptor Pointer Upper Base */
+
+#define _HDAC_ISDOFFSET(n, iss, oss) (0x80 + ((n) * 0x20))
+#define _HDAC_ISDCTL(n, iss, oss) (0x00 + _HDAC_ISDOFFSET(n, iss, oss))
+#define _HDAC_ISDSTS(n, iss, oss) (0x03 + _HDAC_ISDOFFSET(n, iss, oss))
+#define _HDAC_ISDPICB(n, iss, oss) (0x04 + _HDAC_ISDOFFSET(n, iss, oss))
+#define _HDAC_ISDCBL(n, iss, oss) (0x08 + _HDAC_ISDOFFSET(n, iss, oss))
+#define _HDAC_ISDLVI(n, iss, oss) (0x0c + _HDAC_ISDOFFSET(n, iss, oss))
+#define _HDAC_ISDFIFOD(n, iss, oss) (0x10 + _HDAC_ISDOFFSET(n, iss, oss))
+#define _HDAC_ISDFMT(n, iss, oss) (0x12 + _HDAC_ISDOFFSET(n, iss, oss))
+#define _HDAC_ISDBDPL(n, iss, oss) (0x18 + _HDAC_ISDOFFSET(n, iss, oss))
+#define _HDAC_ISDBDPU(n, iss, oss) (0x1c + _HDAC_ISDOFFSET(n, iss, oss))
+
+#define _HDAC_OSDOFFSET(n, iss, oss) (0x80 + ((iss) * 0x20) + ((n) * 0x20))
+#define _HDAC_OSDCTL(n, iss, oss) (0x00 + _HDAC_OSDOFFSET(n, iss, oss))
+#define _HDAC_OSDSTS(n, iss, oss) (0x03 + _HDAC_OSDOFFSET(n, iss, oss))
+#define _HDAC_OSDPICB(n, iss, oss) (0x04 + _HDAC_OSDOFFSET(n, iss, oss))
+#define _HDAC_OSDCBL(n, iss, oss) (0x08 + _HDAC_OSDOFFSET(n, iss, oss))
+#define _HDAC_OSDLVI(n, iss, oss) (0x0c + _HDAC_OSDOFFSET(n, iss, oss))
+#define _HDAC_OSDFIFOD(n, iss, oss) (0x10 + _HDAC_OSDOFFSET(n, iss, oss))
+#define _HDAC_OSDFMT(n, iss, oss) (0x12 + _HDAC_OSDOFFSET(n, iss, oss))
+#define _HDAC_OSDBDPL(n, iss, oss) (0x18 + _HDAC_OSDOFFSET(n, iss, oss))
+#define _HDAC_OSDBDPU(n, iss, oss) (0x1c + _HDAC_OSDOFFSET(n, iss, oss))
+
+#define _HDAC_BSDOFFSET(n, iss, oss) \
+ (0x80 + ((iss) * 0x20) + ((oss) * 0x20) + ((n) * 0x20))
+#define _HDAC_BSDCTL(n, iss, oss) (0x00 + _HDAC_BSDOFFSET(n, iss, oss))
+#define _HDAC_BSDSTS(n, iss, oss) (0x03 + _HDAC_BSDOFFSET(n, iss, oss))
+#define _HDAC_BSDPICB(n, iss, oss) (0x04 + _HDAC_BSDOFFSET(n, iss, oss))
+#define _HDAC_BSDCBL(n, iss, oss) (0x08 + _HDAC_BSDOFFSET(n, iss, oss))
+#define _HDAC_BSDLVI(n, iss, oss) (0x0c + _HDAC_BSDOFFSET(n, iss, oss))
+#define _HDAC_BSDFIFOD(n, iss, oss) (0x10 + _HDAC_BSDOFFSET(n, iss, oss))
+#define _HDAC_BSDFMT(n, iss, oss) (0x12 + _HDAC_BSDOFFSET(n, iss, oss))
+#define _HDAC_BSDBDPL(n, iss, oss) (0x18 + _HDAC_BSDOFFSET(n, iss, oss))
+#define _HDAC_BSDBDBU(n, iss, oss) (0x1c + _HDAC_BSDOFFSET(n, iss, oss))
+
+/****************************************************************************
+ * HDA Controller Register Fields
+ ****************************************************************************/
+
+/* GCAP - Global Capabilities */
+#define HDAC_GCAP_64OK 0x0001
+#define HDAC_GCAP_NSDO_MASK 0x0006
+#define HDAC_GCAP_NSDO_SHIFT 1
+#define HDAC_GCAP_BSS_MASK 0x00f8
+#define HDAC_GCAP_BSS_SHIFT 3
+#define HDAC_GCAP_ISS_MASK 0x0f00
+#define HDAC_GCAP_ISS_SHIFT 8
+#define HDAC_GCAP_OSS_MASK 0xf000
+#define HDAC_GCAP_OSS_SHIFT 12
+
+#define HDAC_GCAP_NSDO_1SDO 0x00
+#define HDAC_GCAP_NSDO_2SDO 0x02
+#define HDAC_GCAP_NSDO_4SDO 0x04
+
+#define HDAC_GCAP_BSS(gcap) \
+ (((gcap) & HDAC_GCAP_BSS_MASK) >> HDAC_GCAP_BSS_SHIFT)
+#define HDAC_GCAP_ISS(gcap) \
+ (((gcap) & HDAC_GCAP_ISS_MASK) >> HDAC_GCAP_ISS_SHIFT)
+#define HDAC_GCAP_OSS(gcap) \
+ (((gcap) & HDAC_GCAP_OSS_MASK) >> HDAC_GCAP_OSS_SHIFT)
+#define HDAC_GCAP_NSDO(gcap) \
+ (((gcap) & HDAC_GCAP_NSDO_MASK) >> HDAC_GCAP_NSDO_SHIFT)
+
+/* GCTL - Global Control */
+#define HDAC_GCTL_CRST 0x00000001
+#define HDAC_GCTL_FCNTRL 0x00000002
+#define HDAC_GCTL_UNSOL 0x00000100
+
+/* WAKEEN - Wake Enable */
+#define HDAC_WAKEEN_SDIWEN_MASK 0x7fff
+#define HDAC_WAKEEN_SDIWEN_SHIFT 0
+
+/* STATESTS - State Change Status */
+#define HDAC_STATESTS_SDIWAKE_MASK 0x7fff
+#define HDAC_STATESTS_SDIWAKE_SHIFT 0
+
+#define HDAC_STATESTS_SDIWAKE(statests, n) \
+ (((((statests) & HDAC_STATESTS_SDIWAKE_MASK) >> \
+ HDAC_STATESTS_SDIWAKE_SHIFT) >> (n)) & 0x0001)
+
+/* GSTS - Global Status */
+#define HDAC_GSTS_FSTS 0x0002
+
+/* INTCTL - Interrut Control */
+#define HDAC_INTCTL_SIE_MASK 0x3fffffff
+#define HDAC_INTCTL_SIE_SHIFT 0
+#define HDAC_INTCTL_CIE 0x40000000
+#define HDAC_INTCTL_GIE 0x80000000
+
+/* INTSTS - Interrupt Status */
+#define HDAC_INTSTS_SIS_MASK 0x3fffffff
+#define HDAC_INTSTS_SIS_SHIFT 0
+#define HDAC_INTSTS_CIS 0x40000000
+#define HDAC_INTSTS_GIS 0x80000000
+
+/* SSYNC - Stream Synchronization */
+#define HDAC_SSYNC_SSYNC_MASK 0x3fffffff
+#define HDAC_SSYNC_SSYNC_SHIFT 0
+
+/* CORBWP - CORB Write Pointer */
+#define HDAC_CORBWP_CORBWP_MASK 0x00ff
+#define HDAC_CORBWP_CORBWP_SHIFT 0
+
+/* CORBRP - CORB Read Pointer */
+#define HDAC_CORBRP_CORBRP_MASK 0x00ff
+#define HDAC_CORBRP_CORBRP_SHIFT 0
+#define HDAC_CORBRP_CORBRPRST 0x8000
+
+/* CORBCTL - CORB Control */
+#define HDAC_CORBCTL_CMEIE 0x01
+#define HDAC_CORBCTL_CORBRUN 0x02
+
+/* CORBSTS - CORB Status */
+#define HDAC_CORBSTS_CMEI 0x01
+
+/* CORBSIZE - CORB Size */
+#define HDAC_CORBSIZE_CORBSIZE_MASK 0x03
+#define HDAC_CORBSIZE_CORBSIZE_SHIFT 0
+#define HDAC_CORBSIZE_CORBSZCAP_MASK 0xf0
+#define HDAC_CORBSIZE_CORBSZCAP_SHIFT 4
+
+#define HDAC_CORBSIZE_CORBSIZE_2 0x00
+#define HDAC_CORBSIZE_CORBSIZE_16 0x01
+#define HDAC_CORBSIZE_CORBSIZE_256 0x02
+
+#define HDAC_CORBSIZE_CORBSZCAP_2 0x10
+#define HDAC_CORBSIZE_CORBSZCAP_16 0x20
+#define HDAC_CORBSIZE_CORBSZCAP_256 0x40
+
+#define HDAC_CORBSIZE_CORBSIZE(corbsize) \
+ (((corbsize) & HDAC_CORBSIZE_CORBSIZE_MASK) >> HDAC_CORBSIZE_CORBSIZE_SHIFT)
+
+/* RIRBWP - RIRB Write Pointer */
+#define HDAC_RIRBWP_RIRBWP_MASK 0x00ff
+#define HDAC_RIRBWP_RIRBWP_SHIFT 0
+#define HDAC_RIRBWP_RIRBWPRST 0x8000
+
+/* RINTCTN - Response Interrupt Count */
+#define HDAC_RINTCNT_MASK 0x00ff
+#define HDAC_RINTCNT_SHIFT 0
+
+/* RIRBCTL - RIRB Control */
+#define HDAC_RIRBCTL_RINTCTL 0x01
+#define HDAC_RIRBCTL_RIRBDMAEN 0x02
+#define HDAC_RIRBCTL_RIRBOIC 0x04
+
+/* RIRBSTS - RIRB Status */
+#define HDAC_RIRBSTS_RINTFL 0x01
+#define HDAC_RIRBSTS_RIRBOIS 0x04
+
+/* RIRBSIZE - RIRB Size */
+#define HDAC_RIRBSIZE_RIRBSIZE_MASK 0x03
+#define HDAC_RIRBSIZE_RIRBSIZE_SHIFT 0
+#define HDAC_RIRBSIZE_RIRBSZCAP_MASK 0xf0
+#define HDAC_RIRBSIZE_RIRBSZCAP_SHIFT 4
+
+#define HDAC_RIRBSIZE_RIRBSIZE_2 0x00
+#define HDAC_RIRBSIZE_RIRBSIZE_16 0x01
+#define HDAC_RIRBSIZE_RIRBSIZE_256 0x02
+
+#define HDAC_RIRBSIZE_RIRBSZCAP_2 0x10
+#define HDAC_RIRBSIZE_RIRBSZCAP_16 0x20
+#define HDAC_RIRBSIZE_RIRBSZCAP_256 0x40
+
+#define HDAC_RIRBSIZE_RIRBSIZE(rirbsize) \
+ (((rirbsize) & HDAC_RIRBSIZE_RIRBSIZE_MASK) >> HDAC_RIRBSIZE_RIRBSIZE_SHIFT)
+
+/* DPLBASE - DMA Position Lower Base Address */
+#define HDAC_DPLBASE_DPLBASE_MASK 0xffffff80
+#define HDAC_DPLBASE_DPLBASE_SHIFT 7
+#define HDAC_DPLBASE_DPLBASE_DMAPBE 0x00000001
+
+/* SDCTL - Stream Descriptor Control */
+#define HDAC_SDCTL_SRST 0x000001
+#define HDAC_SDCTL_RUN 0x000002
+#define HDAC_SDCTL_IOCE 0x000004
+#define HDAC_SDCTL_FEIE 0x000008
+#define HDAC_SDCTL_DEIE 0x000010
+#define HDAC_SDCTL2_STRIPE_MASK 0x03
+#define HDAC_SDCTL2_STRIPE_SHIFT 0
+#define HDAC_SDCTL2_TP 0x04
+#define HDAC_SDCTL2_DIR 0x08
+#define HDAC_SDCTL2_STRM_MASK 0xf0
+#define HDAC_SDCTL2_STRM_SHIFT 4
+
+#define HDAC_SDSTS_DESE (1 << 4)
+#define HDAC_SDSTS_FIFOE (1 << 3)
+#define HDAC_SDSTS_BCIS (1 << 2)
+
+#endif /* _HDAC_REG_H_ */
diff --git a/usr.sbin/bhyve/net_utils.c b/usr.sbin/bhyve/net_utils.c
index dc29124e84bd..32b15fc7f54b 100644
--- a/usr.sbin/bhyve/net_utils.c
+++ b/usr.sbin/bhyve/net_utils.c
@@ -21,17 +21,21 @@
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
*/
-#include "net_utils.h"
-#include "bhyverun.h"
-#include <md5.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
#include <net/ethernet.h>
-#include <string.h>
-#include <stdio.h>
+
#include <errno.h>
+#include <md5.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "bhyverun.h"
+#include "net_utils.h"
int
net_parsemac(char *mac_str, uint8_t *mac_addr)
diff --git a/usr.sbin/bhyve/pci_hda.c b/usr.sbin/bhyve/pci_hda.c
new file mode 100644
index 000000000000..ace88274ac91
--- /dev/null
+++ b/usr.sbin/bhyve/pci_hda.c
@@ -0,0 +1,1331 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2016 Alex Teaca <iateaca@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 <time.h>
+
+#include "pci_hda.h"
+#include "bhyverun.h"
+#include "pci_emul.h"
+#include "hdac_reg.h"
+
+/*
+ * HDA defines
+ */
+#define PCIR_HDCTL 0x40
+#define INTEL_VENDORID 0x8086
+#define HDA_INTEL_82801G 0x27d8
+
+#define HDA_IOSS_NO 0x08
+#define HDA_OSS_NO 0x04
+#define HDA_ISS_NO 0x04
+#define HDA_CODEC_MAX 0x0f
+#define HDA_LAST_OFFSET \
+ (0x2084 + ((HDA_ISS_NO) * 0x20) + ((HDA_OSS_NO) * 0x20))
+#define HDA_SET_REG_TABLE_SZ \
+ (0x80 + ((HDA_ISS_NO) * 0x20) + ((HDA_OSS_NO) * 0x20))
+#define HDA_CORB_ENTRY_LEN 0x04
+#define HDA_RIRB_ENTRY_LEN 0x08
+#define HDA_BDL_ENTRY_LEN 0x10
+#define HDA_DMA_PIB_ENTRY_LEN 0x08
+#define HDA_STREAM_TAGS_CNT 0x10
+#define HDA_STREAM_REGS_BASE 0x80
+#define HDA_STREAM_REGS_LEN 0x20
+
+#define HDA_DMA_ACCESS_LEN (sizeof(uint32_t))
+#define HDA_BDL_MAX_LEN 0x0100
+
+#define HDAC_SDSTS_FIFORDY (1 << 5)
+
+#define HDA_RIRBSTS_IRQ_MASK (HDAC_RIRBSTS_RINTFL | HDAC_RIRBSTS_RIRBOIS)
+#define HDA_STATESTS_IRQ_MASK ((1 << HDA_CODEC_MAX) - 1)
+#define HDA_SDSTS_IRQ_MASK \
+ (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS)
+
+/*
+ * HDA data structures
+ */
+
+struct hda_softc;
+
+typedef void (*hda_set_reg_handler)(struct hda_softc *sc, uint32_t offset,
+ uint32_t old);
+
+struct hda_bdle {
+ uint32_t addrh;
+ uint32_t addrl;
+ uint32_t ioc;
+ uint32_t len;
+} __packed;
+
+struct hda_bdle_desc {
+ void *addr;
+ uint8_t ioc;
+ uint32_t len;
+};
+
+struct hda_codec_cmd_ctl {
+ char *name;
+ void *dma_vaddr;
+ uint8_t run;
+ uint16_t rp;
+ uint16_t size;
+ uint16_t wp;
+};
+
+struct hda_stream_desc {
+ uint8_t dir;
+ uint8_t run;
+ uint8_t stream;
+
+ /* bp is the no. of bytes transferred in the current bdle */
+ uint32_t bp;
+ /* be is the no. of bdles transferred in the bdl */
+ uint32_t be;
+
+ uint32_t bdl_cnt;
+ struct hda_bdle_desc bdl[HDA_BDL_MAX_LEN];
+};
+
+struct hda_softc {
+ struct pci_devinst *pci_dev;
+ uint32_t regs[HDA_LAST_OFFSET];
+
+ uint8_t lintr;
+ uint8_t rirb_cnt;
+ uint64_t wall_clock_start;
+
+ struct hda_codec_cmd_ctl corb;
+ struct hda_codec_cmd_ctl rirb;
+
+ uint8_t codecs_no;
+ struct hda_codec_inst *codecs[HDA_CODEC_MAX];
+
+ /* Base Address of the DMA Position Buffer */
+ void *dma_pib_vaddr;
+
+ struct hda_stream_desc streams[HDA_IOSS_NO];
+ /* 2 tables for output and input */
+ uint8_t stream_map[2][HDA_STREAM_TAGS_CNT];
+};
+
+/*
+ * HDA module function declarations
+ */
+static inline void hda_set_reg_by_offset(struct hda_softc *sc, uint32_t offset,
+ uint32_t value);
+static inline uint32_t hda_get_reg_by_offset(struct hda_softc *sc,
+ uint32_t offset);
+static inline void hda_set_field_by_offset(struct hda_softc *sc,
+ uint32_t offset, uint32_t mask, uint32_t value);
+
+static uint8_t hda_parse_config(const char *opts, const char *key, char *val);
+static struct hda_softc *hda_init(const char *opts);
+static void hda_update_intr(struct hda_softc *sc);
+static void hda_response_interrupt(struct hda_softc *sc);
+static int hda_codec_constructor(struct hda_softc *sc,
+ struct hda_codec_class *codec, const char *play, const char *rec,
+ const char *opts);
+static struct hda_codec_class *hda_find_codec_class(const char *name);
+
+static int hda_send_command(struct hda_softc *sc, uint32_t verb);
+static int hda_notify_codecs(struct hda_softc *sc, uint8_t run,
+ uint8_t stream, uint8_t dir);
+static void hda_reset(struct hda_softc *sc);
+static void hda_reset_regs(struct hda_softc *sc);
+static void hda_stream_reset(struct hda_softc *sc, uint8_t stream_ind);
+static int hda_stream_start(struct hda_softc *sc, uint8_t stream_ind);
+static int hda_stream_stop(struct hda_softc *sc, uint8_t stream_ind);
+static uint32_t hda_read(struct hda_softc *sc, uint32_t offset);
+static int hda_write(struct hda_softc *sc, uint32_t offset, uint8_t size,
+ uint32_t value);
+
+static inline void hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p);
+static int hda_corb_start(struct hda_softc *sc);
+static int hda_corb_run(struct hda_softc *sc);
+static int hda_rirb_start(struct hda_softc *sc);
+
+static void *hda_dma_get_vaddr(struct hda_softc *sc, uint64_t dma_paddr,
+ size_t len);
+static void hda_dma_st_dword(void *dma_vaddr, uint32_t data);
+static uint32_t hda_dma_ld_dword(void *dma_vaddr);
+
+static inline uint8_t hda_get_stream_by_offsets(uint32_t offset,
+ uint8_t reg_offset);
+static inline uint32_t hda_get_offset_stream(uint8_t stream_ind);
+
+static void hda_set_gctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
+static void hda_set_statests(struct hda_softc *sc, uint32_t offset,
+ uint32_t old);
+static void hda_set_corbwp(struct hda_softc *sc, uint32_t offset, uint32_t old);
+static void hda_set_corbctl(struct hda_softc *sc, uint32_t offset,
+ uint32_t old);
+static void hda_set_rirbctl(struct hda_softc *sc, uint32_t offset,
+ uint32_t old);
+static void hda_set_rirbsts(struct hda_softc *sc, uint32_t offset,
+ uint32_t old);
+static void hda_set_dpiblbase(struct hda_softc *sc, uint32_t offset,
+ uint32_t old);
+static void hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
+static void hda_set_sdctl2(struct hda_softc *sc, uint32_t offset, uint32_t old);
+static void hda_set_sdsts(struct hda_softc *sc, uint32_t offset, uint32_t old);
+
+static int hda_signal_state_change(struct hda_codec_inst *hci);
+static int hda_response(struct hda_codec_inst *hci, uint32_t response,
+ uint8_t unsol);
+static int hda_transfer(struct hda_codec_inst *hci, uint8_t stream,
+ uint8_t dir, void *buf, size_t count);
+
+static void hda_set_pib(struct hda_softc *sc, uint8_t stream_ind, uint32_t pib);
+static uint64_t hda_get_clock_ns(void);
+
+/*
+ * PCI HDA function declarations
+ */
+static int pci_hda_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts);
+static void pci_hda_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size, uint64_t value);
+static uint64_t pci_hda_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size);
+/*
+ * HDA global data
+ */
+
+static const hda_set_reg_handler hda_set_reg_table[] = {
+ [HDAC_GCTL] = hda_set_gctl,
+ [HDAC_STATESTS] = hda_set_statests,
+ [HDAC_CORBWP] = hda_set_corbwp,
+ [HDAC_CORBCTL] = hda_set_corbctl,
+ [HDAC_RIRBCTL] = hda_set_rirbctl,
+ [HDAC_RIRBSTS] = hda_set_rirbsts,
+ [HDAC_DPIBLBASE] = hda_set_dpiblbase,
+
+#define HDAC_ISTREAM(n, iss, oss) \
+ [_HDAC_ISDCTL(n, iss, oss)] = hda_set_sdctl, \
+ [_HDAC_ISDCTL(n, iss, oss) + 2] = hda_set_sdctl2, \
+ [_HDAC_ISDSTS(n, iss, oss)] = hda_set_sdsts, \
+
+#define HDAC_OSTREAM(n, iss, oss) \
+ [_HDAC_OSDCTL(n, iss, oss)] = hda_set_sdctl, \
+ [_HDAC_OSDCTL(n, iss, oss) + 2] = hda_set_sdctl2, \
+ [_HDAC_OSDSTS(n, iss, oss)] = hda_set_sdsts, \
+
+ HDAC_ISTREAM(0, HDA_ISS_NO, HDA_OSS_NO)
+ HDAC_ISTREAM(1, HDA_ISS_NO, HDA_OSS_NO)
+ HDAC_ISTREAM(2, HDA_ISS_NO, HDA_OSS_NO)
+ HDAC_ISTREAM(3, HDA_ISS_NO, HDA_OSS_NO)
+
+ HDAC_OSTREAM(0, HDA_ISS_NO, HDA_OSS_NO)
+ HDAC_OSTREAM(1, HDA_ISS_NO, HDA_OSS_NO)
+ HDAC_OSTREAM(2, HDA_ISS_NO, HDA_OSS_NO)
+ HDAC_OSTREAM(3, HDA_ISS_NO, HDA_OSS_NO)
+
+ [HDA_SET_REG_TABLE_SZ] = NULL,
+};
+
+static const uint16_t hda_corb_sizes[] = {
+ [HDAC_CORBSIZE_CORBSIZE_2] = 2,
+ [HDAC_CORBSIZE_CORBSIZE_16] = 16,
+ [HDAC_CORBSIZE_CORBSIZE_256] = 256,
+ [HDAC_CORBSIZE_CORBSIZE_MASK] = 0,
+};
+
+static const uint16_t hda_rirb_sizes[] = {
+ [HDAC_RIRBSIZE_RIRBSIZE_2] = 2,
+ [HDAC_RIRBSIZE_RIRBSIZE_16] = 16,
+ [HDAC_RIRBSIZE_RIRBSIZE_256] = 256,
+ [HDAC_RIRBSIZE_RIRBSIZE_MASK] = 0,
+};
+
+static struct hda_ops hops = {
+ .signal = hda_signal_state_change,
+ .response = hda_response,
+ .transfer = hda_transfer,
+};
+
+struct pci_devemu pci_de_hda = {
+ .pe_emu = "hda",
+ .pe_init = pci_hda_init,
+ .pe_barwrite = pci_hda_write,
+ .pe_barread = pci_hda_read
+};
+
+PCI_EMUL_SET(pci_de_hda);
+
+SET_DECLARE(hda_codec_class_set, struct hda_codec_class);
+
+#if DEBUG_HDA == 1
+FILE *dbg;
+#endif
+
+/*
+ * HDA module function definitions
+ */
+
+static inline void
+hda_set_reg_by_offset(struct hda_softc *sc, uint32_t offset, uint32_t value)
+{
+ assert(offset < HDA_LAST_OFFSET);
+ sc->regs[offset] = value;
+}
+
+static inline uint32_t
+hda_get_reg_by_offset(struct hda_softc *sc, uint32_t offset)
+{
+ assert(offset < HDA_LAST_OFFSET);
+ return sc->regs[offset];
+}
+
+static inline void
+hda_set_field_by_offset(struct hda_softc *sc, uint32_t offset,
+ uint32_t mask, uint32_t value)
+{
+ uint32_t reg_value = 0;
+
+ reg_value = hda_get_reg_by_offset(sc, offset);
+
+ reg_value &= ~mask;
+ reg_value |= (value & mask);
+
+ hda_set_reg_by_offset(sc, offset, reg_value);
+}
+
+static uint8_t
+hda_parse_config(const char *opts, const char *key, char *val)
+{
+ char buf[64];
+ char *s = buf;
+ char *tmp = NULL;
+ size_t len;
+ int i;
+
+ if (!opts)
+ return (0);
+
+ len = strlen(opts);
+ if (len >= sizeof(buf)) {
+ DPRINTF("Opts too big\n");
+ return (0);
+ }
+
+ DPRINTF("opts: %s\n", opts);
+
+ strcpy(buf, opts);
+
+ for (i = 0; i < len; i++)
+ if (buf[i] == ',') {
+ buf[i] = 0;
+ tmp = buf + i + 1;
+ break;
+ }
+
+ if (!memcmp(s, key, strlen(key))) {
+ strncpy(val, s + strlen(key), 64);
+ return (1);
+ }
+
+ if (!tmp)
+ return (0);
+
+ s = tmp;
+ if (!memcmp(s, key, strlen(key))) {
+ strncpy(val, s + strlen(key), 64);
+ return (1);
+ }
+
+ return (0);
+}
+
+static struct hda_softc *
+hda_init(const char *opts)
+{
+ struct hda_softc *sc = NULL;
+ struct hda_codec_class *codec = NULL;
+ char play[64];
+ char rec[64];
+ int err, p, r;
+
+#if DEBUG_HDA == 1
+ dbg = fopen("/tmp/bhyve_hda.log", "w+");
+#endif
+
+ DPRINTF("opts: %s\n", opts);
+
+ sc = calloc(1, sizeof(*sc));
+ if (!sc)
+ return (NULL);
+
+ hda_reset_regs(sc);
+
+ /*
+ * TODO search all the codecs declared in opts
+ * For now we play with one single codec
+ */
+ codec = hda_find_codec_class("hda_codec");
+ if (codec) {
+ p = hda_parse_config(opts, "play=", play);
+ r = hda_parse_config(opts, "rec=", rec);
+ DPRINTF("play: %s rec: %s\n", play, rec);
+ if (p | r) {
+ err = hda_codec_constructor(sc, codec, p ? \
+ play : NULL, r ? rec : NULL, NULL);
+ assert(!err);
+ }
+ }
+
+ return (sc);
+}
+
+static void
+hda_update_intr(struct hda_softc *sc)
+{
+ struct pci_devinst *pi = sc->pci_dev;
+ uint32_t intctl = hda_get_reg_by_offset(sc, HDAC_INTCTL);
+ uint32_t intsts = 0;
+ uint32_t sdsts = 0;
+ uint32_t rirbsts = 0;
+ uint32_t wakeen = 0;
+ uint32_t statests = 0;
+ uint32_t off = 0;
+ int i;
+
+ /* update the CIS bits */
+ rirbsts = hda_get_reg_by_offset(sc, HDAC_RIRBSTS);
+ if (rirbsts & (HDAC_RIRBSTS_RINTFL | HDAC_RIRBSTS_RIRBOIS))
+ intsts |= HDAC_INTSTS_CIS;
+
+ wakeen = hda_get_reg_by_offset(sc, HDAC_WAKEEN);
+ statests = hda_get_reg_by_offset(sc, HDAC_STATESTS);
+ if (statests & wakeen)
+ intsts |= HDAC_INTSTS_CIS;
+
+ /* update the SIS bits */
+ for (i = 0; i < HDA_IOSS_NO; i++) {
+ off = hda_get_offset_stream(i);
+ sdsts = hda_get_reg_by_offset(sc, off + HDAC_SDSTS);
+ if (sdsts & HDAC_SDSTS_BCIS)
+ intsts |= (1 << i);
+ }
+
+ /* update the GIS bit */
+ if (intsts)
+ intsts |= HDAC_INTSTS_GIS;
+
+ hda_set_reg_by_offset(sc, HDAC_INTSTS, intsts);
+
+ if ((intctl & HDAC_INTCTL_GIE) && ((intsts & \
+ ~HDAC_INTSTS_GIS) & intctl)) {
+ if (!sc->lintr) {
+ pci_lintr_assert(pi);
+ sc->lintr = 1;
+ }
+ } else {
+ if (sc->lintr) {
+ pci_lintr_deassert(pi);
+ sc->lintr = 0;
+ }
+ }
+}
+
+static void
+hda_response_interrupt(struct hda_softc *sc)
+{
+ uint8_t rirbctl = hda_get_reg_by_offset(sc, HDAC_RIRBCTL);
+
+ if ((rirbctl & HDAC_RIRBCTL_RINTCTL) && sc->rirb_cnt) {
+ sc->rirb_cnt = 0;
+ hda_set_field_by_offset(sc, HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL,
+ HDAC_RIRBSTS_RINTFL);
+ hda_update_intr(sc);
+ }
+}
+
+static int
+hda_codec_constructor(struct hda_softc *sc, struct hda_codec_class *codec,
+ const char *play, const char *rec, const char *opts)
+{
+ struct hda_codec_inst *hci = NULL;
+
+ if (sc->codecs_no >= HDA_CODEC_MAX)
+ return (-1);
+
+ hci = calloc(1, sizeof(struct hda_codec_inst));
+ if (!hci)
+ return (-1);
+
+ hci->hda = sc;
+ hci->hops = &hops;
+ hci->cad = sc->codecs_no;
+ hci->codec = codec;
+
+ sc->codecs[sc->codecs_no++] = hci;
+
+ if (!codec->init) {
+ DPRINTF("This codec does not implement the init function\n");
+ return (-1);
+ }
+
+ return (codec->init(hci, play, rec, opts));
+}
+
+static struct hda_codec_class *
+hda_find_codec_class(const char *name)
+{
+ struct hda_codec_class **pdpp = NULL, *pdp = NULL;
+
+ SET_FOREACH(pdpp, hda_codec_class_set) {
+ pdp = *pdpp;
+ if (!strcmp(pdp->name, name)) {
+ return (pdp);
+ }
+ }
+
+ return (NULL);
+}
+
+static int
+hda_send_command(struct hda_softc *sc, uint32_t verb)
+{
+ struct hda_codec_inst *hci = NULL;
+ struct hda_codec_class *codec = NULL;
+ uint8_t cad = (verb >> HDA_CMD_CAD_SHIFT) & 0x0f;
+
+ hci = sc->codecs[cad];
+ if (!hci)
+ return (-1);
+
+ DPRINTF("cad: 0x%x verb: 0x%x\n", cad, verb);
+
+ codec = hci->codec;
+ assert(codec);
+
+ if (!codec->command) {
+ DPRINTF("This codec does not implement the command function\n");
+ return (-1);
+ }
+
+ return (codec->command(hci, verb));
+}
+
+static int
+hda_notify_codecs(struct hda_softc *sc, uint8_t run, uint8_t stream,
+ uint8_t dir)
+{
+ struct hda_codec_inst *hci = NULL;
+ struct hda_codec_class *codec = NULL;
+ int err;
+ int i;
+
+ /* Notify each codec */
+ for (i = 0; i < sc->codecs_no; i++) {
+ hci = sc->codecs[i];
+ assert(hci);
+
+ codec = hci->codec;
+ assert(codec);
+
+ if (codec->notify) {
+ err = codec->notify(hci, run, stream, dir);
+ if (!err)
+ break;
+ }
+ }
+
+ return (i == sc->codecs_no ? (-1) : 0);
+}
+
+static void
+hda_reset(struct hda_softc *sc)
+{
+ int i;
+ struct hda_codec_inst *hci = NULL;
+ struct hda_codec_class *codec = NULL;
+
+ hda_reset_regs(sc);
+
+ /* Reset each codec */
+ for (i = 0; i < sc->codecs_no; i++) {
+ hci = sc->codecs[i];
+ assert(hci);
+
+ codec = hci->codec;
+ assert(codec);
+
+ if (codec->reset)
+ codec->reset(hci);
+ }
+
+ sc->wall_clock_start = hda_get_clock_ns();
+}
+
+static void
+hda_reset_regs(struct hda_softc *sc)
+{
+ uint32_t off = 0;
+ uint8_t i;
+
+ DPRINTF("Reset the HDA controller registers ...\n");
+
+ memset(sc->regs, 0, sizeof(sc->regs));
+
+ hda_set_reg_by_offset(sc, HDAC_GCAP,
+ HDAC_GCAP_64OK |
+ (HDA_ISS_NO << HDAC_GCAP_ISS_SHIFT) |
+ (HDA_OSS_NO << HDAC_GCAP_OSS_SHIFT));
+ hda_set_reg_by_offset(sc, HDAC_VMAJ, 0x01);
+ hda_set_reg_by_offset(sc, HDAC_OUTPAY, 0x3c);
+ hda_set_reg_by_offset(sc, HDAC_INPAY, 0x1d);
+ hda_set_reg_by_offset(sc, HDAC_CORBSIZE,
+ HDAC_CORBSIZE_CORBSZCAP_256 | HDAC_CORBSIZE_CORBSIZE_256);
+ hda_set_reg_by_offset(sc, HDAC_RIRBSIZE,
+ HDAC_RIRBSIZE_RIRBSZCAP_256 | HDAC_RIRBSIZE_RIRBSIZE_256);
+
+ for (i = 0; i < HDA_IOSS_NO; i++) {
+ off = hda_get_offset_stream(i);
+ hda_set_reg_by_offset(sc, off + HDAC_SDFIFOS, HDA_FIFO_SIZE);
+ }
+}
+
+static void
+hda_stream_reset(struct hda_softc *sc, uint8_t stream_ind)
+{
+ struct hda_stream_desc *st = &sc->streams[stream_ind];
+ uint32_t off = hda_get_offset_stream(stream_ind);
+
+ DPRINTF("Reset the HDA stream: 0x%x\n", stream_ind);
+
+ /* Reset the Stream Descriptor registers */
+ memset(sc->regs + HDA_STREAM_REGS_BASE + off, 0, HDA_STREAM_REGS_LEN);
+
+ /* Reset the Stream Descriptor */
+ memset(st, 0, sizeof(*st));
+
+ hda_set_field_by_offset(sc, off + HDAC_SDSTS,
+ HDAC_SDSTS_FIFORDY, HDAC_SDSTS_FIFORDY);
+ hda_set_field_by_offset(sc, off + HDAC_SDCTL0,
+ HDAC_SDCTL_SRST, HDAC_SDCTL_SRST);
+}
+
+static int
+hda_stream_start(struct hda_softc *sc, uint8_t stream_ind)
+{
+ struct hda_stream_desc *st = &sc->streams[stream_ind];
+ struct hda_bdle_desc *bdle_desc = NULL;
+ struct hda_bdle *bdle = NULL;
+ uint32_t lvi = 0;
+ uint32_t bdl_cnt = 0;
+ uint64_t bdpl = 0;
+ uint64_t bdpu = 0;
+ uint64_t bdl_paddr = 0;
+ void *bdl_vaddr = NULL;
+ uint32_t bdle_sz = 0;
+ uint64_t bdle_addrl = 0;
+ uint64_t bdle_addrh = 0;
+ uint64_t bdle_paddr = 0;
+ void *bdle_vaddr = NULL;
+ uint32_t off = hda_get_offset_stream(stream_ind);
+ uint32_t sdctl = 0;
+ uint8_t strm = 0;
+ uint8_t dir = 0;
+ int i;
+
+ assert(!st->run);
+
+ lvi = hda_get_reg_by_offset(sc, off + HDAC_SDLVI);
+ bdpl = hda_get_reg_by_offset(sc, off + HDAC_SDBDPL);
+ bdpu = hda_get_reg_by_offset(sc, off + HDAC_SDBDPU);
+
+ bdl_cnt = lvi + 1;
+ assert(bdl_cnt <= HDA_BDL_MAX_LEN);
+
+ bdl_paddr = bdpl | (bdpu << 32);
+ bdl_vaddr = hda_dma_get_vaddr(sc, bdl_paddr,
+ HDA_BDL_ENTRY_LEN * bdl_cnt);
+ if (!bdl_vaddr) {
+ DPRINTF("Fail to get the guest virtual address\n");
+ return (-1);
+ }
+
+ DPRINTF("stream: 0x%x bdl_cnt: 0x%x bdl_paddr: 0x%lx\n",
+ stream_ind, bdl_cnt, bdl_paddr);
+
+ st->bdl_cnt = bdl_cnt;
+
+ bdle = (struct hda_bdle *)bdl_vaddr;
+ for (i = 0; i < bdl_cnt; i++, bdle++) {
+ bdle_sz = bdle->len;
+ assert(!(bdle_sz % HDA_DMA_ACCESS_LEN));
+
+ bdle_addrl = bdle->addrl;
+ bdle_addrh = bdle->addrh;
+
+ bdle_paddr = bdle_addrl | (bdle_addrh << 32);
+ bdle_vaddr = hda_dma_get_vaddr(sc, bdle_paddr, bdle_sz);
+ if (!bdle_vaddr) {
+ DPRINTF("Fail to get the guest virtual address\n");
+ return (-1);
+ }
+
+ bdle_desc = &st->bdl[i];
+ bdle_desc->addr = bdle_vaddr;
+ bdle_desc->len = bdle_sz;
+ bdle_desc->ioc = bdle->ioc;
+
+ DPRINTF("bdle: 0x%x bdle_sz: 0x%x\n", i, bdle_sz);
+ }
+
+ sdctl = hda_get_reg_by_offset(sc, off + HDAC_SDCTL0);
+ strm = (sdctl >> 20) & 0x0f;
+ dir = stream_ind >= HDA_ISS_NO;
+
+ DPRINTF("strm: 0x%x, dir: 0x%x\n", strm, dir);
+
+ sc->stream_map[dir][strm] = stream_ind;
+ st->stream = strm;
+ st->dir = dir;
+ st->bp = 0;
+ st->be = 0;
+
+ hda_set_pib(sc, stream_ind, 0);
+
+ st->run = 1;
+
+ hda_notify_codecs(sc, 1, strm, dir);
+
+ return (0);
+}
+
+static int
+hda_stream_stop(struct hda_softc *sc, uint8_t stream_ind)
+{
+ struct hda_stream_desc *st = &sc->streams[stream_ind];
+ uint8_t strm = st->stream;
+ uint8_t dir = st->dir;
+
+ DPRINTF("stream: 0x%x, strm: 0x%x, dir: 0x%x\n", stream_ind, strm, dir);
+
+ st->run = 0;
+
+ hda_notify_codecs(sc, 0, strm, dir);
+
+ return (0);
+}
+
+static uint32_t
+hda_read(struct hda_softc *sc, uint32_t offset)
+{
+ if (offset == HDAC_WALCLK)
+ return (24 * (hda_get_clock_ns() - \
+ sc->wall_clock_start) / 1000);
+
+ return (hda_get_reg_by_offset(sc, offset));
+}
+
+static int
+hda_write(struct hda_softc *sc, uint32_t offset, uint8_t size, uint32_t value)
+{
+ uint32_t old = hda_get_reg_by_offset(sc, offset);
+ uint32_t masks[] = {0x00000000, 0x000000ff, 0x0000ffff,
+ 0x00ffffff, 0xffffffff};
+ hda_set_reg_handler set_reg_handler = hda_set_reg_table[offset];
+
+ hda_set_field_by_offset(sc, offset, masks[size], value);
+
+ if (set_reg_handler)
+ set_reg_handler(sc, offset, old);
+
+ return (0);
+}
+
+static inline void
+hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p)
+{
+#if DEBUG_HDA == 1
+ char *name = p->name;
+#endif
+ DPRINTF("%s size: %d\n", name, p->size);
+ DPRINTF("%s dma_vaddr: %p\n", name, p->dma_vaddr);
+ DPRINTF("%s wp: 0x%x\n", name, p->wp);
+ DPRINTF("%s rp: 0x%x\n", name, p->rp);
+}
+
+static int
+hda_corb_start(struct hda_softc *sc)
+{
+ struct hda_codec_cmd_ctl *corb = &sc->corb;
+ uint8_t corbsize = 0;
+ uint64_t corblbase = 0;
+ uint64_t corbubase = 0;
+ uint64_t corbpaddr = 0;
+
+ corb->name = "CORB";
+
+ corbsize = hda_get_reg_by_offset(sc, HDAC_CORBSIZE) & \
+ HDAC_CORBSIZE_CORBSIZE_MASK;
+ corb->size = hda_corb_sizes[corbsize];
+
+ if (!corb->size) {
+ DPRINTF("Invalid corb size\n");
+ return (-1);
+ }
+
+ corblbase = hda_get_reg_by_offset(sc, HDAC_CORBLBASE);
+ corbubase = hda_get_reg_by_offset(sc, HDAC_CORBUBASE);
+
+ corbpaddr = corblbase | (corbubase << 32);
+ DPRINTF("CORB dma_paddr: %p\n", (void *)corbpaddr);
+
+ corb->dma_vaddr = hda_dma_get_vaddr(sc, corbpaddr,
+ HDA_CORB_ENTRY_LEN * corb->size);
+ if (!corb->dma_vaddr) {
+ DPRINTF("Fail to get the guest virtual address\n");
+ return (-1);
+ }
+
+ corb->wp = hda_get_reg_by_offset(sc, HDAC_CORBWP);
+ corb->rp = hda_get_reg_by_offset(sc, HDAC_CORBRP);
+
+ corb->run = 1;
+
+ hda_print_cmd_ctl_data(corb);
+
+ return (0);
+}
+
+static int
+hda_corb_run(struct hda_softc *sc)
+{
+ struct hda_codec_cmd_ctl *corb = &sc->corb;
+ uint32_t verb = 0;
+ int err;
+
+ corb->wp = hda_get_reg_by_offset(sc, HDAC_CORBWP);
+
+ while (corb->rp != corb->wp && corb->run) {
+ corb->rp++;
+ corb->rp %= corb->size;
+
+ verb = hda_dma_ld_dword(corb->dma_vaddr + \
+ HDA_CORB_ENTRY_LEN * corb->rp);
+
+ err = hda_send_command(sc, verb);
+ assert(!err);
+ }
+
+ hda_set_reg_by_offset(sc, HDAC_CORBRP, corb->rp);
+
+ if (corb->run)
+ hda_response_interrupt(sc);
+
+ return (0);
+}
+
+static int
+hda_rirb_start(struct hda_softc *sc)
+{
+ struct hda_codec_cmd_ctl *rirb = &sc->rirb;
+ uint8_t rirbsize = 0;
+ uint64_t rirblbase = 0;
+ uint64_t rirbubase = 0;
+ uint64_t rirbpaddr = 0;
+
+ rirb->name = "RIRB";
+
+ rirbsize = hda_get_reg_by_offset(sc, HDAC_RIRBSIZE) & \
+ HDAC_RIRBSIZE_RIRBSIZE_MASK;
+ rirb->size = hda_rirb_sizes[rirbsize];
+
+ if (!rirb->size) {
+ DPRINTF("Invalid rirb size\n");
+ return (-1);
+ }
+
+ rirblbase = hda_get_reg_by_offset(sc, HDAC_RIRBLBASE);
+ rirbubase = hda_get_reg_by_offset(sc, HDAC_RIRBUBASE);
+
+ rirbpaddr = rirblbase | (rirbubase << 32);
+ DPRINTF("RIRB dma_paddr: %p\n", (void *)rirbpaddr);
+
+ rirb->dma_vaddr = hda_dma_get_vaddr(sc, rirbpaddr,
+ HDA_RIRB_ENTRY_LEN * rirb->size);
+ if (!rirb->dma_vaddr) {
+ DPRINTF("Fail to get the guest virtual address\n");
+ return (-1);
+ }
+
+ rirb->wp = hda_get_reg_by_offset(sc, HDAC_RIRBWP);
+ rirb->rp = 0x0000;
+
+ rirb->run = 1;
+
+ hda_print_cmd_ctl_data(rirb);
+
+ return (0);
+}
+
+static void *
+hda_dma_get_vaddr(struct hda_softc *sc, uint64_t dma_paddr, size_t len)
+{
+ struct pci_devinst *pi = sc->pci_dev;
+
+ assert(pi);
+
+ return (paddr_guest2host(pi->pi_vmctx, (uintptr_t)dma_paddr, len));
+}
+
+static void
+hda_dma_st_dword(void *dma_vaddr, uint32_t data)
+{
+ *(uint32_t*)dma_vaddr = data;
+}
+
+static uint32_t
+hda_dma_ld_dword(void *dma_vaddr)
+{
+ return (*(uint32_t*)dma_vaddr);
+}
+
+static inline uint8_t
+hda_get_stream_by_offsets(uint32_t offset, uint8_t reg_offset)
+{
+ uint8_t stream_ind = (offset - reg_offset) >> 5;
+
+ assert(stream_ind < HDA_IOSS_NO);
+
+ return (stream_ind);
+}
+
+static inline uint32_t
+hda_get_offset_stream(uint8_t stream_ind)
+{
+ return (stream_ind << 5);
+}
+
+static void
+hda_set_gctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ uint32_t value = hda_get_reg_by_offset(sc, offset);
+
+ if (!(value & HDAC_GCTL_CRST)) {
+ hda_reset(sc);
+ }
+}
+
+static void
+hda_set_statests(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ uint32_t value = hda_get_reg_by_offset(sc, offset);
+
+ hda_set_reg_by_offset(sc, offset, old);
+
+ /* clear the corresponding bits written by the software (guest) */
+ hda_set_field_by_offset(sc, offset, value & HDA_STATESTS_IRQ_MASK, 0);
+
+ hda_update_intr(sc);
+}
+
+static void
+hda_set_corbwp(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ hda_corb_run(sc);
+}
+
+static void
+hda_set_corbctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ uint32_t value = hda_get_reg_by_offset(sc, offset);
+ int err;
+ struct hda_codec_cmd_ctl *corb = NULL;
+
+ if (value & HDAC_CORBCTL_CORBRUN) {
+ if (!(old & HDAC_CORBCTL_CORBRUN)) {
+ err = hda_corb_start(sc);
+ assert(!err);
+ }
+ } else {
+ corb = &sc->corb;
+ memset(corb, 0, sizeof(*corb));
+ }
+
+ hda_corb_run(sc);
+}
+
+static void
+hda_set_rirbctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ uint32_t value = hda_get_reg_by_offset(sc, offset);
+ int err;
+ struct hda_codec_cmd_ctl *rirb = NULL;
+
+ if (value & HDAC_RIRBCTL_RIRBDMAEN) {
+ err = hda_rirb_start(sc);
+ assert(!err);
+ } else {
+ rirb = &sc->rirb;
+ memset(rirb, 0, sizeof(*rirb));
+ }
+}
+
+static void
+hda_set_rirbsts(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ uint32_t value = hda_get_reg_by_offset(sc, offset);
+
+ hda_set_reg_by_offset(sc, offset, old);
+
+ /* clear the corresponding bits written by the software (guest) */
+ hda_set_field_by_offset(sc, offset, value & HDA_RIRBSTS_IRQ_MASK, 0);
+
+ hda_update_intr(sc);
+}
+
+static void
+hda_set_dpiblbase(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ uint32_t value = hda_get_reg_by_offset(sc, offset);
+ uint64_t dpiblbase = 0;
+ uint64_t dpibubase = 0;
+ uint64_t dpibpaddr = 0;
+
+ if ((value & HDAC_DPLBASE_DPLBASE_DMAPBE) != (old & \
+ HDAC_DPLBASE_DPLBASE_DMAPBE)) {
+ if (value & HDAC_DPLBASE_DPLBASE_DMAPBE) {
+ dpiblbase = value & HDAC_DPLBASE_DPLBASE_MASK;
+ dpibubase = hda_get_reg_by_offset(sc, HDAC_DPIBUBASE);
+
+ dpibpaddr = dpiblbase | (dpibubase << 32);
+ DPRINTF("DMA Position In Buffer dma_paddr: %p\n",
+ (void *)dpibpaddr);
+
+ sc->dma_pib_vaddr = hda_dma_get_vaddr(sc, dpibpaddr,
+ HDA_DMA_PIB_ENTRY_LEN * HDA_IOSS_NO);
+ if (!sc->dma_pib_vaddr) {
+ DPRINTF("Fail to get the guest \
+ virtual address\n");
+ assert(0);
+ }
+ } else {
+ DPRINTF("DMA Position In Buffer Reset\n");
+ sc->dma_pib_vaddr = NULL;
+ }
+ }
+}
+
+static void
+hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ uint8_t stream_ind = hda_get_stream_by_offsets(offset, HDAC_SDCTL0);
+ uint32_t value = hda_get_reg_by_offset(sc, offset);
+ int err;
+
+ DPRINTF("stream_ind: 0x%x old: 0x%x value: 0x%x\n",
+ stream_ind, old, value);
+
+ if (value & HDAC_SDCTL_SRST) {
+ hda_stream_reset(sc, stream_ind);
+ }
+
+ if ((value & HDAC_SDCTL_RUN) != (old & HDAC_SDCTL_RUN)) {
+ if (value & HDAC_SDCTL_RUN) {
+ err = hda_stream_start(sc, stream_ind);
+ assert(!err);
+ } else {
+ err = hda_stream_stop(sc, stream_ind);
+ assert(!err);
+ }
+ }
+}
+
+static void
+hda_set_sdctl2(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ uint32_t value = hda_get_reg_by_offset(sc, offset);
+
+ hda_set_field_by_offset(sc, offset - 2, 0x00ff0000, value << 16);
+}
+
+static void
+hda_set_sdsts(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+ uint32_t value = hda_get_reg_by_offset(sc, offset);
+
+ hda_set_reg_by_offset(sc, offset, old);
+
+ /* clear the corresponding bits written by the software (guest) */
+ hda_set_field_by_offset(sc, offset, value & HDA_SDSTS_IRQ_MASK, 0);
+
+ hda_update_intr(sc);
+}
+
+static int
+hda_signal_state_change(struct hda_codec_inst *hci)
+{
+ struct hda_softc *sc = NULL;
+ uint32_t sdiwake = 0;
+
+ assert(hci);
+ assert(hci->hda);
+
+ DPRINTF("cad: 0x%x\n", hci->cad);
+
+ sc = hci->hda;
+ sdiwake = 1 << hci->cad;
+
+ hda_set_field_by_offset(sc, HDAC_STATESTS, sdiwake, sdiwake);
+ hda_update_intr(sc);
+
+ return (0);
+}
+
+static int
+hda_response(struct hda_codec_inst *hci, uint32_t response, uint8_t unsol)
+{
+ struct hda_softc *sc = NULL;
+ struct hda_codec_cmd_ctl *rirb = NULL;
+ uint32_t response_ex = 0;
+ uint8_t rintcnt = 0;
+
+ assert(hci);
+ assert(hci->cad <= HDA_CODEC_MAX);
+
+ response_ex = hci->cad | unsol;
+
+ sc = hci->hda;
+ assert(sc);
+
+ rirb = &sc->rirb;
+
+ if (rirb->run) {
+ rirb->wp++;
+ rirb->wp %= rirb->size;
+
+ hda_dma_st_dword(rirb->dma_vaddr + HDA_RIRB_ENTRY_LEN * \
+ rirb->wp, response);
+ hda_dma_st_dword(rirb->dma_vaddr + HDA_RIRB_ENTRY_LEN * \
+ rirb->wp + 0x04, response_ex);
+
+ hda_set_reg_by_offset(sc, HDAC_RIRBWP, rirb->wp);
+
+ sc->rirb_cnt++;
+ }
+
+ rintcnt = hda_get_reg_by_offset(sc, HDAC_RINTCNT);
+ if (sc->rirb_cnt == rintcnt)
+ hda_response_interrupt(sc);
+
+ return (0);
+}
+
+static int
+hda_transfer(struct hda_codec_inst *hci, uint8_t stream, uint8_t dir,
+ void *buf, size_t count)
+{
+ struct hda_softc *sc = NULL;
+ struct hda_stream_desc *st = NULL;
+ struct hda_bdle_desc *bdl = NULL;
+ struct hda_bdle_desc *bdle_desc = NULL;
+ uint8_t stream_ind = 0;
+ uint32_t lpib = 0;
+ uint32_t off = 0;
+ size_t left = 0;
+ uint8_t irq = 0;
+
+ assert(hci);
+ assert(hci->hda);
+ assert(buf);
+ assert(!(count % HDA_DMA_ACCESS_LEN));
+
+ if (!stream) {
+ DPRINTF("Invalid stream\n");
+ return (-1);
+ }
+
+ sc = hci->hda;
+
+ assert(stream < HDA_STREAM_TAGS_CNT);
+ stream_ind = sc->stream_map[dir][stream];
+
+ if (!dir)
+ assert(stream_ind < HDA_ISS_NO);
+ else
+ assert(stream_ind >= HDA_ISS_NO && stream_ind < HDA_IOSS_NO);
+
+ st = &sc->streams[stream_ind];
+ if (!st->run) {
+ DPRINTF("Stream 0x%x stopped\n", stream);
+ return (-1);
+ }
+
+ assert(st->stream == stream);
+
+ off = hda_get_offset_stream(stream_ind);
+
+ lpib = hda_get_reg_by_offset(sc, off + HDAC_SDLPIB);
+
+ bdl = st->bdl;
+
+ assert(st->be < st->bdl_cnt);
+ assert(st->bp < bdl[st->be].len);
+
+ left = count;
+ while (left) {
+ bdle_desc = &bdl[st->be];
+
+ if (dir)
+ *(uint32_t *)buf = \
+ hda_dma_ld_dword(bdle_desc->addr + st->bp);
+ else
+ hda_dma_st_dword(bdle_desc->addr + st->bp,
+ *(uint32_t *)buf);
+
+ buf += HDA_DMA_ACCESS_LEN;
+ st->bp += HDA_DMA_ACCESS_LEN;
+ lpib += HDA_DMA_ACCESS_LEN;
+ left -= HDA_DMA_ACCESS_LEN;
+
+ if (st->bp == bdle_desc->len) {
+ st->bp = 0;
+ if (bdle_desc->ioc)
+ irq = 1;
+ st->be++;
+ if (st->be == st->bdl_cnt) {
+ st->be = 0;
+ lpib = 0;
+ }
+ bdle_desc = &bdl[st->be];
+ }
+ }
+
+ hda_set_pib(sc, stream_ind, lpib);
+
+ if (irq) {
+ hda_set_field_by_offset(sc, off + HDAC_SDSTS,
+ HDAC_SDSTS_BCIS, HDAC_SDSTS_BCIS);
+ hda_update_intr(sc);
+ }
+
+ return (0);
+}
+
+static void
+hda_set_pib(struct hda_softc *sc, uint8_t stream_ind, uint32_t pib)
+{
+ uint32_t off = hda_get_offset_stream(stream_ind);
+
+ hda_set_reg_by_offset(sc, off + HDAC_SDLPIB, pib);
+ /* LPIB Alias */
+ hda_set_reg_by_offset(sc, 0x2000 + off + HDAC_SDLPIB, pib);
+ if (sc->dma_pib_vaddr)
+ *(uint32_t *)(sc->dma_pib_vaddr + stream_ind * \
+ HDA_DMA_PIB_ENTRY_LEN) = pib;
+}
+
+static uint64_t hda_get_clock_ns(void)
+{
+ struct timespec ts;
+ int err;
+
+ err = clock_gettime(CLOCK_MONOTONIC, &ts);
+ assert(!err);
+
+ return (ts.tv_sec * 1000000000LL + ts.tv_nsec);
+}
+
+/*
+ * PCI HDA function definitions
+ */
+static int
+pci_hda_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+ struct hda_softc *sc = NULL;
+
+ assert(ctx != NULL);
+ assert(pi != NULL);
+
+ pci_set_cfgdata16(pi, PCIR_VENDOR, INTEL_VENDORID);
+ pci_set_cfgdata16(pi, PCIR_DEVICE, HDA_INTEL_82801G);
+
+ pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_MULTIMEDIA_HDA);
+ pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_MULTIMEDIA);
+
+ /* select the Intel HDA mode */
+ pci_set_cfgdata8(pi, PCIR_HDCTL, 0x01);
+
+ /* allocate one BAR register for the Memory address offsets */
+ pci_emul_alloc_bar(pi, 0, PCIBAR_MEM32, HDA_LAST_OFFSET);
+
+ /* allocate an IRQ pin for our slot */
+ pci_lintr_request(pi);
+
+ sc = hda_init(opts);
+ if (!sc)
+ return (-1);
+
+ sc->pci_dev = pi;
+ pi->pi_arg = sc;
+
+ return (0);
+}
+
+static void
+pci_hda_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size, uint64_t value)
+{
+ struct hda_softc *sc = pi->pi_arg;
+ int err;
+
+ assert(sc);
+ assert(baridx == 0);
+ assert(size <= 4);
+
+ DPRINTF("offset: 0x%lx value: 0x%lx\n", offset, value);
+
+ err = hda_write(sc, offset, size, value);
+ assert(!err);
+}
+
+static uint64_t
+pci_hda_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size)
+{
+ struct hda_softc *sc = pi->pi_arg;
+ uint64_t value = 0;
+
+ assert(sc);
+ assert(baridx == 0);
+ assert(size <= 4);
+
+ value = hda_read(sc, offset);
+
+ DPRINTF("offset: 0x%lx value: 0x%lx\n", offset, value);
+
+ return (value);
+}
diff --git a/usr.sbin/bhyve/pci_hda.h b/usr.sbin/bhyve/pci_hda.h
new file mode 100644
index 000000000000..8ed050cc8f40
--- /dev/null
+++ b/usr.sbin/bhyve/pci_hda.h
@@ -0,0 +1,92 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2016 Alex Teaca <iateaca@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 _HDA_EMUL_H_
+#define _HDA_EMUL_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/kernel.h>
+
+#include "hda_reg.h"
+
+/*
+ * HDA Debug Log
+ */
+#define DEBUG_HDA 1
+#if DEBUG_HDA == 1
+extern FILE *dbg;
+#define DPRINTF(fmt, arg...) \
+do {fprintf(dbg, "%s-%d: " fmt, __func__, __LINE__, ##arg); \
+fflush(dbg); } while (0)
+#else
+#define DPRINTF(fmt, arg...)
+#endif
+
+#define HDA_FIFO_SIZE 0x100
+
+struct hda_softc;
+struct hda_codec_class;
+
+struct hda_codec_inst {
+ uint8_t cad;
+ struct hda_codec_class *codec;
+ struct hda_softc *hda;
+ struct hda_ops *hops;
+ void *priv;
+};
+
+struct hda_codec_class {
+ char *name;
+ int (*init)(struct hda_codec_inst *hci, const char *play,
+ const char *rec, const char *opts);
+ int (*reset)(struct hda_codec_inst *hci);
+ int (*command)(struct hda_codec_inst *hci, uint32_t cmd_data);
+ int (*notify)(struct hda_codec_inst *hci, uint8_t run, uint8_t stream,
+ uint8_t dir);
+};
+
+struct hda_ops {
+ int (*signal)(struct hda_codec_inst *hci);
+ int (*response)(struct hda_codec_inst *hci, uint32_t response,
+ uint8_t unsol);
+ int (*transfer)(struct hda_codec_inst *hci, uint8_t stream,
+ uint8_t dir, void *buf, size_t count);
+};
+
+#define HDA_EMUL_SET(x) DATA_SET(hda_codec_class_set, x);
+
+#endif /* _HDA_EMUL_H_ */
diff --git a/usr.sbin/bhyve/pci_virtio_scsi.c b/usr.sbin/bhyve/pci_virtio_scsi.c
index 283dd83b6e08..9d9fa822e01d 100644
--- a/usr.sbin/bhyve/pci_virtio_scsi.c
+++ b/usr.sbin/bhyve/pci_virtio_scsi.c
@@ -309,7 +309,8 @@ pci_vtscsi_reset(void *vsc)
/* initialize config structure */
sc->vss_config = (struct pci_vtscsi_config){
.num_queues = VTSCSI_REQUESTQ,
- .seg_max = VTSCSI_MAXSEG,
+ /* Leave room for the request and the response. */
+ .seg_max = VTSCSI_MAXSEG - 2,
.max_sectors = 2,
.cmd_per_lun = 1,
.event_info_size = sizeof(struct pci_vtscsi_event),
diff --git a/usr.sbin/bsnmpd/modules/snmp_lm75/snmp_lm75.c b/usr.sbin/bsnmpd/modules/snmp_lm75/snmp_lm75.c
index 1822f7801e80..a55050b851d3 100644
--- a/usr.sbin/bsnmpd/modules/snmp_lm75/snmp_lm75.c
+++ b/usr.sbin/bsnmpd/modules/snmp_lm75/snmp_lm75.c
@@ -100,7 +100,6 @@ lm75_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
module = mod;
lm75_sensors = 0;
- openlog("snmp_lm75", LOG_NDELAY | LOG_PID, LOG_DAEMON);
return(0);
}
diff --git a/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c b/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c
index 7d4398264322..d20f7bccfe26 100644
--- a/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c
+++ b/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c
@@ -907,7 +907,7 @@ pf_tbladdr(struct snmp_context __unused *ctx, struct snmp_value __unused *val,
}
int
-pf_altq(struct snmp_context __unused *ctx, struct snmp_value *val,
+pf_altq_num(struct snmp_context __unused *ctx, struct snmp_value *val,
u_int sub, u_int __unused vindex, enum snmp_op op)
{
asn_subid_t which = val->var.subs[sub - 1];
diff --git a/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def b/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def
index 1dfa14ce4c2a..b545c1e79fae 100644
--- a/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def
+++ b/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def
@@ -174,7 +174,7 @@
)
)
(10 pfAltq
- (1 pfAltqQueueNumber INTEGER32 pf_altq GET)
+ (1 pfAltqQueueNumber INTEGER32 pf_altq_num GET)
(2 pfAltqQueueTable
(1 pfAltqQueueEntry : INTEGER32 pf_altqq
(1 pfAltqQueueIndex INTEGER32)
diff --git a/usr.sbin/kbdcontrol/kbdcontrol.c b/usr.sbin/kbdcontrol/kbdcontrol.c
index 3144e44d72b3..f4651acea840 100644
--- a/usr.sbin/kbdcontrol/kbdcontrol.c
+++ b/usr.sbin/kbdcontrol/kbdcontrol.c
@@ -1220,9 +1220,12 @@ main(int argc, char **argv)
int opt;
/* Collect any -P arguments, regardless of where they appear. */
- while ((opt = getopt(argc, argv, optstring)) != -1)
+ while ((opt = getopt(argc, argv, optstring)) != -1) {
if (opt == 'P')
add_keymap_path(optarg);
+ if (opt == '?')
+ usage();
+ }
optind = optreset = 1;
while ((opt = getopt(argc, argv, optstring)) != -1)
diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c
index 7d1685914742..79d6ac7f5693 100644
--- a/usr.sbin/mountd/mountd.c
+++ b/usr.sbin/mountd/mountd.c
@@ -385,8 +385,8 @@ strsep_quote(char **stringp, const char *delim)
*dstptr++ = *srcptr++;
}
- *dstptr = 0; /* Terminate the string */
*stringp = (*srcptr == '\0') ? NULL : srcptr + 1;
+ *dstptr = 0; /* Terminate the string */
return (retval);
}
diff --git a/usr.sbin/nandsim/Makefile b/usr.sbin/nandsim/Makefile
deleted file mode 100644
index 9269ab5de34f..000000000000
--- a/usr.sbin/nandsim/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# $FreeBSD$
-
-PROG= nandsim
-SRCS= nandsim.c nandsim_rcfile.c nandsim_cfgparse.c
-BINDIR= /usr/sbin
-MAN= nandsim.8
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/nandsim/Makefile.depend b/usr.sbin/nandsim/Makefile.depend
deleted file mode 100644
index 6cfaab1c3644..000000000000
--- a/usr.sbin/nandsim/Makefile.depend
+++ /dev/null
@@ -1,17 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/nandsim/nandsim.8 b/usr.sbin/nandsim/nandsim.8
deleted file mode 100644
index 0951cc7a1aac..000000000000
--- a/usr.sbin/nandsim/nandsim.8
+++ /dev/null
@@ -1,229 +0,0 @@
-.\" Copyright (c) 2010 Semihalf
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd August 10, 2010
-.Dt NANDSIM 8
-.Os
-.Sh NAME
-.Nm nandsim
-.Nd NAND simulator control program
-.Sh SYNOPSIS
-.Nm
-.Ic status
-.Aq ctrl_no | Fl -all | Fl a
-.Op Fl v
-.Nm
-.Ic conf
-.Aq filename
-.Nm
-.Ic start
-.Aq ctrl_no
-.Nm
-.Ic mod
-.Aq ctrl_no:cs_no | Fl l Aq loglevel
-.Op Fl p Aq prog_time
-.Op Fl e Aq erase_time
-.Op Fl r Aq read_time
-.Op Fl E Aq error_ratio
-.Op Fl h
-.Nm
-.Ic stop
-.Aq ctrl_no
-.Nm
-.Ic error
-.Aq ctrl_no:cs_no
-.Aq page_num
-.Aq column
-.Aq length
-.Aq pattern
-.Nm
-.Ic bb
-.Aq ctrl_no:cs_no
-.Op blk_num,blk_num2,...
-.Op Fl U
-.Op Fl L
-.Nm
-.Ic freeze
-.Op ctrl_no
-.Nm
-.Ic log
-.Aq ctrl_no | Fl -all | Fl a
-.Nm
-.Ic stats
-.Aq ctrl_no:cs_no
-.Aq page_num
-.Nm
-.Ic dump
-.Aq ctrl_no:cs_no
-.Aq filename
-.Nm
-.Ic restore
-.Aq ctrl_no:chip_no
-.Aq filename
-.Nm
-.Ic destroy
-.Aq ctrl_no[:cs_no] | Fl -all | Fl a
-.Nm
-.Ic help
-.Op Fl v
-.Sh COMMAND DESCRIPTION
-Controllers and chips are arranged into a simple hierarchy.
-There can be up to 4 controllers configured, each with 4 chip select (CS) lines.
-A given chip is connected to one of the chip selects.
-.Pp
-Controllers are specified as
-.Aq ctrl_no ;
-chip selects are specified as
-.Aq cs_no .
-.Bl -tag -width periphlist
-.It Ic status
-Gets controller(s) status. If
-.Fl a
-or
-.Fl -all
-flag is specified - command will print status of every controller
-currently available.
-Optional flag
-.Fl v
-causes printing complete information about the controller, and all
-chips attached to it.
-.It Ic conf
-Reads simulator configuration from a specified file (this includes
-the simulation "layout" i.e. controllers-chips assignments).
-Configuration changes for an already started simulation require a
-full stop-start cycle in order to take effect i.e.:
-.Bl -column
-.It nandsim stop ...
-.It nandsim destroy ...
-.Pp
-.It << edit config file >>
-.Pp
-.It nandsim conf ...
-.It nandsim start ...
-.El
-.It Ic mod
-Alters simulator parameters on-the-fly.
-If controller number and CS pair is not specified, the general
-simulator parameters (not specific to a controller or a chip) will be modified.
-Changing chip's parameters requires specifying both controller number and CS
-to which the given chip is connected.
-Parameters which can be altered:
-.Pp
-General simulator related:
-.Bl -tag -width flag
-.It Fl l Aq log_level
-change logging level to
-.Aq log_level
-.El
-.Pp
-Chip related:
-.Bl -tag -width flag
-.It Fl p Aq prog_time
-change prog time for specified chip to
-.Aq prog_time
-.It Fl e Aq erase_time
-change erase time for specified chip to
-.Aq erase_time
-.It Fl r Aq read_time
-change read time for specified chip to
-.Aq read_time
-.It Fl E Aq error_ratio
-change error ratio for specified chip to
-.Aq error_ratio .
-Error ratio is a number of errors per million read/write bytes.
-.El
-.Pp
-Additionally, flag
-.Fl h
-will list parameters which can be altered.
-.El
-.Bl -tag -width periphlist
-.It Ic bb
-Marks/unmarks a specified block as bad.
-To mark/unmark the bad condition an a block, the following parameters
-have to be supplied: controller number, CS number, and at least one
-block number.
-It is possible to specify multiple blocks, by separating blocks numbers
-with a comma.
-The following options can be used for the 'bb' command:
-.Bl -tag -width flag
-.It Fl U
-unmark the bad previously marked block as bad.
-.It Fl L
-list all blocks marked as bad on a given chip.
-.El
-.It Ic log
-Prints activity log of the specified controller to stdout; if
-controller number is not specified, logs for all available
-controllers are printed.
-.It Ic stats
-Print statistics of the selected controller, chip and page.
-Statistics includes read count, write count, raw read count, raw
-write count, ECC stats (succeeded corrections, failed correction).
-.It Ic dump
-Dumps a snaphot of a single chip (including data and bad blocks
-information, wearout level) into the file.
-.It Ic restore
-Restores chip state from a dump-file snapshot (produced previously
-with the 'dump' command).
-.It Ic start
-Starts a controller i.e. the simulation.
-.It Ic stop
-Stops an already started controller; if the controller number is not
-supplied, attempts to stop all currently working controllers.
-.It Ic destroy
-Removes existing active chip/controller and its configuration from
-memory and releases the resources.
-Specifying flag
-.Fl a
-or
-.Fl -all
-causes removal of every chip and controller.
-Controller must be stopped in order to be destroyed.
-.It Ic error
-Directly overwrites a certain number of bytes in the specified page
-at a given offset with a supplied pattern (which mimics the
-corruption of flash contents).
-.It Ic help
-Prints synopsis,
-.Fl v
-gives more verbose output.
-.It Ic freeze
-Stops simulation of given controller (simulates power-loss).
-All commands issues to any chip on this controller are ignored.
-.El
-.Sh SEE ALSO
-.Xr nand 4 ,
-.Xr nandsim 4 ,
-.Xr nandsim.conf 5
-.Sh HISTORY
-The
-.Nm
-utility first appeared in
-.Fx 10.0 .
-.Sh AUTHORS
-This utility was written by
-.An Lukasz Wojcik .
diff --git a/usr.sbin/nandsim/nandsim.c b/usr.sbin/nandsim/nandsim.c
deleted file mode 100644
index 10eadcbc940d..000000000000
--- a/usr.sbin/nandsim/nandsim.c
+++ /dev/null
@@ -1,1399 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL 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.
- */
-
-/*
- * Control application for the NAND simulator.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <dev/nand/nandsim.h>
-#include <dev/nand/nand_dev.h>
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <sysexits.h>
-
-#include "nandsim_cfgparse.h"
-
-#define SIMDEVICE "/dev/nandsim.ioctl"
-
-#define error(fmt, args...) do { \
- printf("ERROR: " fmt "\n", ##args); } while (0)
-
-#define warn(fmt, args...) do { \
- printf("WARNING: " fmt "\n", ##args); } while (0)
-
-#define DEBUG
-#undef DEBUG
-
-#ifdef DEBUG
-#define debug(fmt, args...) do { \
- printf("NANDSIM_CONF:" fmt "\n", ##args); } while (0)
-#else
-#define debug(fmt, args...) do {} while(0)
-#endif
-
-#define NANDSIM_RAM_LOG_SIZE 16384
-
-#define MSG_NOTRUNNING "Controller#%d is not running.Please start" \
- " it first."
-#define MSG_RUNNING "Controller#%d is already running!"
-#define MSG_CTRLCHIPNEEDED "You have to specify ctrl_no:cs_no pair!"
-#define MSG_STATUSACQCTRLCHIP "Could not acquire status for ctrl#%d chip#%d"
-#define MSG_STATUSACQCTRL "Could not acquire status for ctrl#%d"
-#define MSG_NOCHIP "There is no such chip configured (chip#%d "\
- "at ctrl#%d)!"
-
-#define MSG_NOCTRL "Controller#%d is not configured!"
-#define MSG_NOTCONFIGDCTRLCHIP "Chip connected to ctrl#%d at cs#%d " \
- "is not configured."
-
-typedef int (commandfunc_t)(int , char **);
-
-static struct nandsim_command *getcommand(char *);
-static int parse_devstring(char *, int *, int *);
-static void printchip(struct sim_chip *, uint8_t);
-static void printctrl(struct sim_ctrl *);
-static int opendev(int *);
-static commandfunc_t cmdstatus;
-static commandfunc_t cmdconf;
-static commandfunc_t cmdstart;
-static commandfunc_t cmdstop;
-static commandfunc_t cmdmod;
-static commandfunc_t cmderror;
-static commandfunc_t cmdbb;
-static commandfunc_t cmdfreeze;
-static commandfunc_t cmdlog;
-static commandfunc_t cmdstats;
-static commandfunc_t cmddump;
-static commandfunc_t cmdrestore;
-static commandfunc_t cmddestroy;
-static commandfunc_t cmdhelp;
-static int checkusage(int, int, char **);
-static int is_chip_created(int, int, int *);
-static int is_ctrl_created(int, int *);
-static int is_ctrl_running(int, int *);
-static int assert_chip_connected(int , int);
-static int printstats(int, int, uint32_t, int);
-
-struct nandsim_command {
- const char *cmd_name; /* Command name */
- commandfunc_t *commandfunc; /* Ptr to command function */
- uint8_t req_argc; /* Mandatory arguments count */
- const char *usagestring; /* Usage string */
-};
-
-static struct nandsim_command commands[] = {
- {"status", cmdstatus, 1,
- "status <ctl_no|--all|-a> [-v]\n" },
- {"conf", cmdconf, 1,
- "conf <filename>\n" },
- {"start", cmdstart, 1,
- "start <ctrl_no>\n" },
- {"mod", cmdmod, 2,
- "mod [-l <loglevel>] | <ctl_no:cs_no> [-p <prog_time>]\n"
- "\t[-e <erase_time>] [-r <read_time>]\n"
- "\t[-E <error_ratio>] | [-h]\n" },
- {"stop", cmdstop, 1,
- "stop <ctrl_no>\n" },
- {"error", cmderror, 5,
- "error <ctrl_no:cs_no> <page_num> <column> <length> <pattern>\n" },
- {"bb", cmdbb, 2,
- "bb <ctl_no:cs_no> [blk_num1,blk_num2,..] [-U] [-L]\n" },
- {"freeze", cmdfreeze, 1,
- "freeze [ctrl_no]\n" },
- {"log", cmdlog, 1,
- "log <ctrl_no|--all|-a>\n" },
- {"stats", cmdstats, 2,
- "stats <ctrl_no:cs_no> <pagenumber>\n" },
- {"dump", cmddump, 2,
- "dump <ctrl_no:cs_no> <filename>\n" },
- {"restore", cmdrestore, 2,
- "restore <ctrl_no:chip_no> <filename>\n" },
- {"destroy", cmddestroy, 1,
- "destroy <ctrl_no[:cs_no]|--all|-a>\n" },
- {"help", cmdhelp, 0,
- "help [-v]" },
- {NULL, NULL, 0, NULL},
-};
-
-
-/* Parse command name, and start appropriate function */
-static struct nandsim_command*
-getcommand(char *arg)
-{
- struct nandsim_command *opts;
-
- for (opts = commands; (opts != NULL) &&
- (opts->cmd_name != NULL); opts++) {
- if (strcmp(opts->cmd_name, arg) == 0)
- return (opts);
- }
- return (NULL);
-}
-
-/*
- * Parse given string in format <ctrl_no>:<cs_no>, if possible -- set
- * ctrl and/or cs, and return 0 (success) or 1 (in case of error).
- *
- * ctrl == 0xff && chip == 0xff : '--all' flag specified
- * ctrl != 0xff && chip != 0xff : both ctrl & chip were specified
- * ctrl != 0xff && chip == 0xff : only ctrl was specified
- */
-static int
-parse_devstring(char *str, int *ctrl, int *cs)
-{
- char *tmpstr;
- unsigned int num = 0;
-
- /* Ignore white spaces at the beginning */
- while (isspace(*str) && (*str != '\0'))
- str++;
-
- *ctrl = 0xff;
- *cs = 0xff;
- if (strcmp(str, "--all") == 0 ||
- strcmp(str, "-a") == 0) {
- /* If --all or -a is specified, ctl==chip==0xff */
- debug("CTRL=%d CHIP=%d\n", *ctrl, *cs);
- return (0);
- }
- /* Separate token and try to convert it to int */
- tmpstr = (char *)strtok(str, ":");
- if ((tmpstr != NULL) && (*tmpstr != '\0')) {
- if (convert_arguint(tmpstr, &num) != 0)
- return (1);
-
- if (num > MAX_SIM_DEV - 1) {
- error("Invalid ctrl_no supplied: %s. Valid ctrl_no "
- "value must lie between 0 and 3!", tmpstr);
- return (1);
- }
-
- *ctrl = num;
- tmpstr = (char *)strtok(NULL, ":");
-
- if ((tmpstr != NULL) && (*tmpstr != '\0')) {
- if (convert_arguint(tmpstr, &num) != 0)
- return (1);
-
- /* Check if chip_no is valid */
- if (num > MAX_CTRL_CS - 1) {
- error("Invalid chip_no supplied: %s. Valid "
- "chip_no value must lie between 0 and 3!",
- tmpstr);
- return (1);
- }
- *cs = num;
- }
- } else
- /* Empty devstring supplied */
- return (1);
-
- debug("CTRL=%d CHIP=%d\n", *ctrl, *cs);
- return (0);
-}
-
-static int
-opendev(int *fd)
-{
-
- *fd = open(SIMDEVICE, O_RDWR);
- if (*fd == -1) {
- error("Could not open simulator device file (%s)!",
- SIMDEVICE);
- return (EX_OSFILE);
- }
- return (EX_OK);
-}
-
-static int
-opencdev(int *cdevd, int ctrl, int chip)
-{
- char fname[255];
-
- sprintf(fname, "/dev/nandsim%d.%d", ctrl, chip);
- *cdevd = open(fname, O_RDWR);
- if (*cdevd == -1)
- return (EX_NOINPUT);
-
- return (EX_OK);
-}
-
-/*
- * Check if given arguments count match requirements. If no, or
- * --help (-h) flag is specified -- return 1 (print usage)
- */
-static int
-checkusage(int gargc, int argsreqd, char **gargv)
-{
-
- if (gargc < argsreqd + 2 || (gargc >= (argsreqd + 2) &&
- (strcmp(gargv[1], "--help") == 0 ||
- strcmp(gargv[1], "-h") == 0)))
- return (1);
-
- return (0);
-}
-
-static int
-cmdstatus(int gargc, char **gargv)
-{
- int chip = 0, ctl = 0, err = 0, fd, idx, idx2, start, stop;
- uint8_t verbose = 0;
- struct sim_ctrl ctrlconf;
- struct sim_chip chipconf;
-
- err = parse_devstring(gargv[2], &ctl, &chip);
- if (err) {
- return (EX_USAGE);
- } else if (ctl == 0xff) {
- /* Every controller */
- start = 0;
- stop = MAX_SIM_DEV-1;
- } else {
- /* Specified controller only */
- start = ctl;
- stop = ctl;
- }
-
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- for (idx = 0; idx < gargc; idx ++)
- if (strcmp(gargv[idx], "-v") == 0 ||
- strcmp(gargv[idx], "--verbose") == 0)
- verbose = 1;
-
- for (idx = start; idx <= stop; idx++) {
- ctrlconf.num = idx;
- err = ioctl(fd, NANDSIM_STATUS_CTRL, &ctrlconf);
- if (err) {
- err = EX_SOFTWARE;
- error(MSG_STATUSACQCTRL, idx);
- continue;
- }
-
- printctrl(&ctrlconf);
-
- for (idx2 = 0; idx2 < MAX_CTRL_CS; idx2++) {
- chipconf.num = idx2;
- chipconf.ctrl_num = idx;
-
- err = ioctl(fd, NANDSIM_STATUS_CHIP, &chipconf);
- if (err) {
- err = EX_SOFTWARE;
- error(MSG_STATUSACQCTRL, idx);
- continue;
- }
-
- printchip(&chipconf, verbose);
- }
- }
- close(fd);
- return (err);
-}
-
-static int
-cmdconf(int gargc __unused, char **gargv)
-{
- int err;
-
- err = parse_config(gargv[2], SIMDEVICE);
- if (err)
- return (EX_DATAERR);
-
- return (EX_OK);
-}
-
-static int
-cmdstart(int gargc __unused, char **gargv)
-{
- int chip = 0, ctl = 0, err = 0, fd, running, state;
-
- err = parse_devstring(gargv[2], &ctl, &chip);
- if (err)
- return (EX_USAGE);
-
- err = is_ctrl_created(ctl, &state);
- if (err) {
- return (EX_SOFTWARE);
- } else if (state == 0) {
- error(MSG_NOCTRL, ctl);
- return (EX_SOFTWARE);
- }
-
- err = is_ctrl_running(ctl, &running);
- if (err)
- return (EX_SOFTWARE);
-
- if (running) {
- warn(MSG_RUNNING, ctl);
- } else {
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- err = ioctl(fd, NANDSIM_START_CTRL, &ctl);
- close(fd);
- if (err) {
- error("Cannot start controller#%d", ctl);
- err = EX_SOFTWARE;
- }
- }
- return (err);
-}
-
-static int
-cmdstop(int gargc __unused, char **gargv)
-{
- int chip = 0, ctl = 0, err = 0, fd, running;
-
- err = parse_devstring(gargv[2], &ctl, &chip);
- if (err)
- return (EX_USAGE);
-
- err = is_ctrl_running(ctl, &running);
- if (err)
- return (EX_SOFTWARE);
-
- if (!running) {
- error(MSG_NOTRUNNING, ctl);
- } else {
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- err = ioctl(fd, NANDSIM_STOP_CTRL, &ctl);
- close(fd);
- if (err) {
- error("Cannot stop controller#%d", ctl);
- err = EX_SOFTWARE;
- }
- }
-
- return (err);
-}
-
-static int
-cmdmod(int gargc __unused, char **gargv)
-{
- int chip, ctl, err = 0, fd = -1, i;
- struct sim_mod mods;
-
- if (gargc >= 4) {
- if (strcmp(gargv[2], "--loglevel") == 0 || strcmp(gargv[2],
- "-l") == 0) {
- /* Set loglevel (ctrl:chip pair independent) */
- mods.field = SIM_MOD_LOG_LEVEL;
-
- if (convert_arguint(gargv[3], &mods.new_value) != 0)
- return (EX_SOFTWARE);
-
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- err = ioctl(fd, NANDSIM_MODIFY, &mods);
- if (err) {
- error("simulator parameter %s could not be "
- "modified !", gargv[3]);
- close(fd);
- return (EX_SOFTWARE);
- }
-
- debug("request : loglevel = %d\n", mods.new_value);
- close(fd);
- return (EX_OK);
- }
- }
-
- err = parse_devstring(gargv[2], &ctl, &chip);
- if (err)
- return (EX_USAGE);
-
- else if (chip == 0xff) {
- error(MSG_CTRLCHIPNEEDED);
- return (EX_USAGE);
- }
-
- if (!assert_chip_connected(ctl, chip))
- return (EX_SOFTWARE);
-
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- /* Find out which flags were passed */
- for (i = 3; i < gargc; i++) {
-
- if (convert_arguint(gargv[i + 1], &mods.new_value) != 0)
- continue;
-
- if (strcmp(gargv[i], "--prog-time") == 0 ||
- strcmp(gargv[i], "-p") == 0) {
-
- mods.field = SIM_MOD_PROG_TIME;
- debug("request : progtime = %d\n", mods.new_value);
-
- } else if (strcmp(gargv[i], "--erase-time") == 0 ||
- strcmp(gargv[i], "-e") == 0) {
-
- mods.field = SIM_MOD_ERASE_TIME;
- debug("request : eraseime = %d\n", mods.new_value);
-
- } else if (strcmp(gargv[i], "--read-time") == 0 ||
- strcmp(gargv[i], "-r") == 0) {
-
- mods.field = SIM_MOD_READ_TIME;
- debug("request : read_time = %d\n", mods.new_value);
-
- } else if (strcmp(gargv[i], "--error-ratio") == 0 ||
- strcmp(gargv[i], "-E") == 0) {
-
- mods.field = SIM_MOD_ERROR_RATIO;
- debug("request : error_ratio = %d\n", mods.new_value);
-
- } else {
- /* Flag not recognized, or nothing specified. */
- error("Unrecognized flag:%s\n", gargv[i]);
- if (fd >= 0)
- close(fd);
- return (EX_USAGE);
- }
-
- mods.chip_num = chip;
- mods.ctrl_num = ctl;
-
- /* Call appropriate ioctl */
- err = ioctl(fd, NANDSIM_MODIFY, &mods);
- if (err) {
- error("simulator parameter %s could not be modified! ",
- gargv[i]);
- continue;
- }
- i++;
- }
- close(fd);
- return (EX_OK);
-}
-
-static int
-cmderror(int gargc __unused, char **gargv)
-{
- uint32_t page, column, len, pattern;
- int chip = 0, ctl = 0, err = 0, fd;
- struct sim_error sim_err;
-
- err = parse_devstring(gargv[2], &ctl, &chip);
- if (err)
- return (EX_USAGE);
-
- if (chip == 0xff) {
- error(MSG_CTRLCHIPNEEDED);
- return (EX_USAGE);
- }
-
- if (convert_arguint(gargv[3], &page) ||
- convert_arguint(gargv[4], &column) ||
- convert_arguint(gargv[5], &len) ||
- convert_arguint(gargv[6], &pattern))
- return (EX_SOFTWARE);
-
- if (!assert_chip_connected(ctl, chip))
- return (EX_SOFTWARE);
-
- sim_err.page_num = page;
- sim_err.column = column;
- sim_err.len = len;
- sim_err.pattern = pattern;
- sim_err.ctrl_num = ctl;
- sim_err.chip_num = chip;
-
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- err = ioctl(fd, NANDSIM_INJECT_ERROR, &sim_err);
-
- close(fd);
- if (err) {
- error("Could not inject error !");
- return (EX_SOFTWARE);
- }
- return (EX_OK);
-}
-
-static int
-cmdbb(int gargc, char **gargv)
-{
- struct sim_block_state bs;
- struct chip_param_io cparams;
- uint32_t blkidx;
- int c, cdevd, chip = 0, ctl = 0, err = 0, fd, idx;
- uint8_t flagL = 0, flagU = 0;
- int *badblocks = NULL;
-
- /* Check for --list/-L or --unmark/-U flags */
- for (idx = 3; idx < gargc; idx++) {
- if (strcmp(gargv[idx], "--list") == 0 ||
- strcmp(gargv[idx], "-L") == 0)
- flagL = idx;
- if (strcmp(gargv[idx], "--unmark") == 0 ||
- strcmp(gargv[idx], "-U") == 0)
- flagU = idx;
- }
-
- if (flagL == 2 || flagU == 2 || flagU == 3)
- return (EX_USAGE);
-
- err = parse_devstring(gargv[2], &ctl, &chip);
- if (err) {
- return (EX_USAGE);
- }
- if (chip == 0xff || ctl == 0xff) {
- error(MSG_CTRLCHIPNEEDED);
- return (EX_USAGE);
- }
-
- bs.ctrl_num = ctl;
- bs.chip_num = chip;
-
- if (!assert_chip_connected(ctl, chip))
- return (EX_SOFTWARE);
-
- if (opencdev(&cdevd, ctl, chip) != EX_OK)
- return (EX_OSFILE);
-
- err = ioctl(cdevd, NAND_IO_GET_CHIP_PARAM, &cparams);
- if (err)
- return (EX_SOFTWARE);
-
- close(cdevd);
-
- bs.ctrl_num = ctl;
- bs.chip_num = chip;
-
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- if (flagL != 3) {
- /*
- * Flag -L was specified either after blocklist or was not
- * specified at all.
- */
- c = parse_intarray(gargv[3], &badblocks);
-
- for (idx = 0; idx < c; idx++) {
- bs.block_num = badblocks[idx];
- /* Do not change wearout */
- bs.wearout = -1;
- bs.state = (flagU == 0) ? NANDSIM_BAD_BLOCK :
- NANDSIM_GOOD_BLOCK;
-
- err = ioctl(fd, NANDSIM_SET_BLOCK_STATE, &bs);
- if (err) {
- error("Could not set bad block(%d) for "
- "controller (%d)!",
- badblocks[idx], ctl);
- err = EX_SOFTWARE;
- break;
- }
- }
- }
- if (flagL != 0) {
- /* If flag -L was specified (anywhere) */
- for (blkidx = 0; blkidx < cparams.blocks; blkidx++) {
- bs.block_num = blkidx;
- /* Do not change the wearout */
- bs.wearout = -1;
- err = ioctl(fd, NANDSIM_GET_BLOCK_STATE, &bs);
- if (err) {
- error("Could not acquire block state");
- err = EX_SOFTWARE;
- continue;
- }
- printf("Block#%d: wear count: %d %s\n", blkidx,
- bs.wearout,
- (bs.state == NANDSIM_BAD_BLOCK) ? "BAD":"GOOD");
- }
- }
- close(fd);
- return (err);
-}
-
-static int
-cmdfreeze(int gargc __unused, char **gargv)
-{
- int chip = 0, ctl = 0, err = 0, fd, i, start = 0, state, stop = 0;
- struct sim_ctrl_chip ctrlchip;
-
- err = parse_devstring(gargv[2], &ctl, &chip);
- if (err)
- return (EX_USAGE);
-
- if (ctl == 0xff) {
- error("You have to specify at least controller number");
- return (EX_USAGE);
- }
-
- if (ctl != 0xff && chip == 0xff) {
- start = 0;
- stop = MAX_CTRL_CS - 1;
- } else {
- start = chip;
- stop = chip;
- }
-
- ctrlchip.ctrl_num = ctl;
-
- err = is_ctrl_running(ctl, &state);
- if (err)
- return (EX_SOFTWARE);
- if (state == 0) {
- error(MSG_NOTRUNNING, ctl);
- return (EX_SOFTWARE);
- }
-
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- for (i = start; i <= stop; i++) {
- err = is_chip_created(ctl, i, &state);
- if (err)
- return (EX_SOFTWARE);
- else if (state == 0) {
- continue;
- }
-
- ctrlchip.chip_num = i;
- err = ioctl(fd, NANDSIM_FREEZE, &ctrlchip);
- if (err) {
- error("Could not freeze ctrl#%d chip#%d", ctl, i);
- close(fd);
- return (EX_SOFTWARE);
- }
- }
- close(fd);
- return (EX_OK);
-}
-
-static int
-cmdlog(int gargc __unused, char **gargv)
-{
- struct sim_log log;
- int chip = 0, ctl = 0, err = 0, fd, idx, start = 0, stop = 0;
- char *logbuf;
-
- err = parse_devstring(gargv[2], &ctl, &chip);
- if (err)
- return (EX_USAGE);
-
- logbuf = (char *)malloc(sizeof(char) * NANDSIM_RAM_LOG_SIZE);
- if (logbuf == NULL) {
- error("Not enough memory to create log buffer");
- return (EX_SOFTWARE);
- }
-
- memset(logbuf, 0, NANDSIM_RAM_LOG_SIZE);
- log.log = logbuf;
- log.len = NANDSIM_RAM_LOG_SIZE;
-
- if (ctl == 0xff) {
- start = 0;
- stop = MAX_SIM_DEV-1;
- } else {
- start = ctl;
- stop = ctl;
- }
-
- if (opendev(&fd) != EX_OK) {
- free(logbuf);
- return (EX_OSFILE);
- }
-
- /* Print logs for selected controller(s) */
- for (idx = start; idx <= stop; idx++) {
- log.ctrl_num = idx;
-
- err = ioctl(fd, NANDSIM_PRINT_LOG, &log);
- if (err) {
- error("Could not get log for controller %d!", idx);
- continue;
- }
-
- printf("Logs for controller#%d:\n%s\n", idx, logbuf);
- }
-
- free(logbuf);
- close(fd);
- return (EX_OK);
-}
-
-static int
-cmdstats(int gargc __unused, char **gargv)
-{
- int cdevd, chip = 0, ctl = 0, err = 0;
- uint32_t pageno = 0;
-
- err = parse_devstring(gargv[2], &ctl, &chip);
-
- if (err)
- return (EX_USAGE);
-
- if (chip == 0xff) {
- error(MSG_CTRLCHIPNEEDED);
- return (EX_USAGE);
- }
-
- if (convert_arguint(gargv[3], &pageno) != 0)
- return (EX_USAGE);
-
- if (!assert_chip_connected(ctl, chip))
- return (EX_SOFTWARE);
-
- if (opencdev(&cdevd, ctl, chip) != EX_OK)
- return (EX_OSFILE);
-
- err = printstats(ctl, chip, pageno, cdevd);
- if (err) {
- close(cdevd);
- return (EX_SOFTWARE);
- }
- close(cdevd);
- return (EX_OK);
-}
-
-static int
-cmddump(int gargc __unused, char **gargv)
-{
- struct sim_dump dump;
- struct sim_block_state bs;
- struct chip_param_io cparams;
- int chip = 0, ctl = 0, err = EX_OK, fd, dumpfd;
- uint32_t blkidx, bwritten = 0, totalwritten = 0;
- void *buf;
-
- err = parse_devstring(gargv[2], &ctl, &chip);
- if (err)
- return (EX_USAGE);
-
- if (chip == 0xff || ctl == 0xff) {
- error(MSG_CTRLCHIPNEEDED);
- return (EX_USAGE);
- }
-
- if (!assert_chip_connected(ctl, chip))
- return (EX_SOFTWARE);
-
- if (opencdev(&fd, ctl, chip) != EX_OK)
- return (EX_OSFILE);
-
- err = ioctl(fd, NAND_IO_GET_CHIP_PARAM, &cparams);
- if (err) {
- error("Cannot get parameters for chip %d:%d", ctl, chip);
- close(fd);
- return (EX_SOFTWARE);
- }
- close(fd);
-
- dump.ctrl_num = ctl;
- dump.chip_num = chip;
-
- dump.len = cparams.pages_per_block * (cparams.page_size +
- cparams.oob_size);
-
- buf = malloc(dump.len);
- if (buf == NULL) {
- error("Could not allocate memory!");
- return (EX_SOFTWARE);
- }
- dump.data = buf;
-
- errno = 0;
- dumpfd = open(gargv[3], O_WRONLY | O_CREAT, 0666);
- if (dumpfd == -1) {
- error("Cannot create dump file.");
- free(buf);
- return (EX_SOFTWARE);
- }
-
- if (opendev(&fd)) {
- close(dumpfd);
- free(buf);
- return (EX_SOFTWARE);
- }
-
- bs.ctrl_num = ctl;
- bs.chip_num = chip;
-
- /* First uint32_t in file shall contain block count */
- if (write(dumpfd, &cparams, sizeof(cparams)) < (int)sizeof(cparams)) {
- error("Error writing to dumpfile!");
- close(fd);
- close(dumpfd);
- free(buf);
- return (EX_SOFTWARE);
- }
-
- /*
- * First loop acquires blocks states and writes them to
- * the dump file.
- */
- for (blkidx = 0; blkidx < cparams.blocks; blkidx++) {
- bs.block_num = blkidx;
- err = ioctl(fd, NANDSIM_GET_BLOCK_STATE, &bs);
- if (err) {
- error("Could not get bad block(%d) for "
- "controller (%d)!", blkidx, ctl);
- close(fd);
- close(dumpfd);
- free(buf);
- return (EX_SOFTWARE);
- }
-
- bwritten = write(dumpfd, &bs, sizeof(bs));
- if (bwritten != sizeof(bs)) {
- error("Error writing to dumpfile");
- close(fd);
- close(dumpfd);
- free(buf);
- return (EX_SOFTWARE);
- }
- }
-
- /* Second loop dumps the data */
- for (blkidx = 0; blkidx < cparams.blocks; blkidx++) {
- debug("Block#%d...", blkidx);
- dump.block_num = blkidx;
-
- err = ioctl(fd, NANDSIM_DUMP, &dump);
- if (err) {
- error("Could not dump ctrl#%d chip#%d "
- "block#%d", ctl, chip, blkidx);
- err = EX_SOFTWARE;
- break;
- }
-
- bwritten = write(dumpfd, dump.data, dump.len);
- if (bwritten != dump.len) {
- error("Error writing to dumpfile");
- err = EX_SOFTWARE;
- break;
- }
- debug("OK!\n");
- totalwritten += bwritten;
- }
- printf("%d out of %d B written.\n", totalwritten, dump.len * blkidx);
-
- close(fd);
- close(dumpfd);
- free(buf);
- return (err);
-}
-
-static int
-cmdrestore(int gargc __unused, char **gargv)
-{
- struct sim_dump dump;
- struct sim_block_state bs;
- struct stat filestat;
- int chip = 0, ctl = 0, err = 0, fd, dumpfd = -1;
- uint32_t blkidx, blksz, fsize = 0, expfilesz;
- void *buf;
- struct chip_param_io cparams, dumpcparams;
-
- err = parse_devstring(gargv[2], &ctl, &chip);
- if (err)
- return (EX_USAGE);
- else if (ctl == 0xff) {
- error(MSG_CTRLCHIPNEEDED);
- return (EX_USAGE);
- }
-
- if (!assert_chip_connected(ctl, chip))
- return (EX_SOFTWARE);
-
- /* Get chip geometry */
- if (opencdev(&fd, ctl, chip) != EX_OK)
- return (EX_OSFILE);
-
- err = ioctl(fd, NAND_IO_GET_CHIP_PARAM, &cparams);
- if (err) {
- error("Cannot get parameters for chip %d:%d", ctl, chip);
- close(fd);
- return (err);
- }
- close(fd);
-
- /* Obtain dump file size */
- errno = 0;
- if (stat(gargv[3], &filestat) != 0) {
- error("Could not acquire file size! : %s",
- strerror(errno));
- return (EX_IOERR);
- }
-
- fsize = filestat.st_size;
- blksz = cparams.pages_per_block * (cparams.page_size +
- cparams.oob_size);
-
- /* Expected dump file size for chip */
- expfilesz = cparams.blocks * (blksz + sizeof(bs)) + sizeof(cparams);
-
- if (fsize != expfilesz) {
- error("File size does not match chip geometry (file size: %d"
- ", dump size: %d)", fsize, expfilesz);
- return (EX_SOFTWARE);
- }
-
- dumpfd = open(gargv[3], O_RDONLY);
- if (dumpfd == -1) {
- error("Could not open dump file!");
- return (EX_IOERR);
- }
-
- /* Read chip params saved in dumpfile */
- read(dumpfd, &dumpcparams, sizeof(dumpcparams));
-
- /* XXX */
- if (bcmp(&dumpcparams, &cparams, sizeof(cparams)) != 0) {
- error("Supplied dump is created for a chip with different "
- "chip configuration!");
- close(dumpfd);
- return (EX_SOFTWARE);
- }
-
- if (opendev(&fd) != EX_OK) {
- close(dumpfd);
- return (EX_OSFILE);
- }
-
- buf = malloc(blksz);
- if (buf == NULL) {
- error("Could not allocate memory for block buffer");
- close(dumpfd);
- close(fd);
- return (EX_SOFTWARE);
- }
-
- dump.ctrl_num = ctl;
- dump.chip_num = chip;
- dump.data = buf;
- /* Restore block states and wearouts */
- for (blkidx = 0; blkidx < cparams.blocks; blkidx++) {
- dump.block_num = blkidx;
- if (read(dumpfd, &bs, sizeof(bs)) != sizeof(bs)) {
- error("Error reading dumpfile");
- close(dumpfd);
- close(fd);
- free(buf);
- return (EX_SOFTWARE);
- }
- bs.ctrl_num = ctl;
- bs.chip_num = chip;
- debug("BLKIDX=%d BLOCKS=%d CTRL=%d CHIP=%d STATE=%d\n"
- "WEAROUT=%d BS.CTRL_NUM=%d BS.CHIP_NUM=%d\n",
- blkidx, cparams.blocks, dump.ctrl_num, dump.chip_num,
- bs.state, bs.wearout, bs.ctrl_num, bs.chip_num);
-
- err = ioctl(fd, NANDSIM_SET_BLOCK_STATE, &bs);
- if (err) {
- error("Could not set bad block(%d) for "
- "controller: %d, chip: %d!", blkidx, ctl, chip);
- close(dumpfd);
- close(fd);
- free(buf);
- return (EX_SOFTWARE);
- }
- }
- /* Restore data */
- for (blkidx = 0; blkidx < cparams.blocks; blkidx++) {
- errno = 0;
- dump.len = read(dumpfd, buf, blksz);
- if (errno) {
- error("Failed to read block#%d from dumpfile.", blkidx);
- err = EX_SOFTWARE;
- break;
- }
- dump.block_num = blkidx;
- err = ioctl(fd, NANDSIM_RESTORE, &dump);
- if (err) {
- error("Could not restore block#%d of ctrl#%d chip#%d"
- ": %s", blkidx, ctl, chip, strerror(errno));
- err = EX_SOFTWARE;
- break;
- }
- }
-
- free(buf);
- close(dumpfd);
- close(fd);
- return (err);
-
-}
-
-static int
-cmddestroy(int gargc __unused, char **gargv)
-{
- int chip = 0, ctl = 0, err = 0, fd, idx, idx2, state;
- int chipstart, chipstop, ctrlstart, ctrlstop;
- struct sim_chip_destroy chip_destroy;
-
- err = parse_devstring(gargv[2], &ctl, &chip);
-
- if (err)
- return (EX_USAGE);
-
- if (ctl == 0xff) {
- /* Every chip at every controller */
- ctrlstart = chipstart = 0;
- ctrlstop = MAX_SIM_DEV - 1;
- chipstop = MAX_CTRL_CS - 1;
- } else {
- ctrlstart = ctrlstop = ctl;
- if (chip == 0xff) {
- /* Every chip at selected controller */
- chipstart = 0;
- chipstop = MAX_CTRL_CS - 1;
- } else
- /* Selected chip at selected controller */
- chipstart = chipstop = chip;
- }
- debug("CTRLSTART=%d CTRLSTOP=%d CHIPSTART=%d CHIPSTOP=%d\n",
- ctrlstart, ctrlstop, chipstart, chipstop);
- for (idx = ctrlstart; idx <= ctrlstop; idx++) {
- err = is_ctrl_created(idx, &state);
- if (err) {
- error("Could not acquire ctrl#%d state. Cannot "
- "destroy controller.", idx);
- return (EX_SOFTWARE);
- }
- if (state == 0) {
- continue;
- }
- err = is_ctrl_running(idx, &state);
- if (err) {
- error(MSG_STATUSACQCTRL, idx);
- return (EX_SOFTWARE);
- }
- if (state != 0) {
- error(MSG_RUNNING, ctl);
- return (EX_SOFTWARE);
- }
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- for (idx2 = chipstart; idx2 <= chipstop; idx2++) {
- err = is_chip_created(idx, idx2, &state);
- if (err) {
- error(MSG_STATUSACQCTRLCHIP, idx2, idx);
- continue;
- }
- if (state == 0)
- /* There is no such chip running */
- continue;
- chip_destroy.ctrl_num = idx;
- chip_destroy.chip_num = idx2;
- ioctl(fd, NANDSIM_DESTROY_CHIP,
- &chip_destroy);
- }
- /* If chip isn't explicitly specified -- destroy ctrl */
- if (chip == 0xff) {
- err = ioctl(fd, NANDSIM_DESTROY_CTRL, &idx);
- if (err) {
- error("Could not destroy ctrl#%d", idx);
- continue;
- }
- }
- close(fd);
- }
- return (err);
-}
-
-int
-main(int argc, char **argv)
-{
- struct nandsim_command *cmdopts;
- int retcode = 0;
-
- if (argc < 2) {
- cmdhelp(argc, argv);
- retcode = EX_USAGE;
- } else {
- cmdopts = getcommand(argv[1]);
- if (cmdopts != NULL && cmdopts->commandfunc != NULL) {
- if (checkusage(argc, cmdopts->req_argc, argv) == 1) {
- /* Print command specific usage */
- printf("nandsim %s", cmdopts->usagestring);
- return (EX_USAGE);
- }
- retcode = cmdopts->commandfunc(argc, argv);
-
- if (retcode == EX_USAGE) {
- /* Print command-specific usage */
- printf("nandsim %s", cmdopts->usagestring);
- } else if (retcode == EX_OSFILE) {
- error("Could not open device file");
- }
-
- } else {
- error("Unknown command!");
- retcode = EX_USAGE;
- }
- }
- return (retcode);
-}
-
-static int
-cmdhelp(int gargc __unused, char **gargv __unused)
-{
- struct nandsim_command *opts;
-
- printf("usage: nandsim <command> [command params] [params]\n\n");
-
- for (opts = commands; (opts != NULL) &&
- (opts->cmd_name != NULL); opts++)
- printf("nandsim %s", opts->usagestring);
-
- printf("\n");
- return (EX_OK);
-}
-
-static void
-printchip(struct sim_chip *chip, uint8_t verbose)
-{
-
- if (chip->created == 0)
- return;
- if (verbose > 0) {
- printf("\n[Chip info]\n");
- printf("num= %d\nctrl_num=%d\ndevice_id=%02x"
- "\tmanufacturer_id=%02x\ndevice_model=%s\nmanufacturer="
- "%s\ncol_addr_cycles=%d\nrow_addr_cycles=%d"
- "\npage_size=%d\noob_size=%d\npages_per_block=%d\n"
- "blocks_per_lun=%d\nluns=%d\n\nprog_time=%d\n"
- "erase_time=%d\nread_time=%d\n"
- "error_ratio=%d\nwear_level=%d\nwrite_protect=%c\n"
- "chip_width=%db\n", chip->num, chip->ctrl_num,
- chip->device_id, chip->manufact_id,chip->device_model,
- chip->manufacturer, chip->col_addr_cycles,
- chip->row_addr_cycles, chip->page_size,
- chip->oob_size, chip->pgs_per_blk, chip->blks_per_lun,
- chip->luns,chip->prog_time, chip->erase_time,
- chip->read_time, chip->error_ratio, chip->wear_level,
- (chip->is_wp == 0) ? 'N':'Y', chip->width);
- } else {
- printf("[Chip info]\n");
- printf("\tnum=%d\n\tdevice_model=%s\n\tmanufacturer=%s\n"
- "\tpage_size=%d\n\twrite_protect=%s\n",
- chip->num, chip->device_model, chip->manufacturer,
- chip->page_size, (chip->is_wp == 0) ? "NO":"YES");
- }
-}
-
-static void
-printctrl(struct sim_ctrl *ctrl)
-{
- int i;
-
- if (ctrl->created == 0) {
- printf(MSG_NOCTRL "\n", ctrl->num);
- return;
- }
- printf("\n[Controller info]\n");
- printf("\trunning: %s\n", ctrl->running ? "yes" : "no");
- printf("\tnum cs: %d\n", ctrl->num_cs);
- printf("\tecc: %d\n", ctrl->ecc);
- printf("\tlog_filename: %s\n", ctrl->filename);
- printf("\tecc_layout:");
- for (i = 0; i < MAX_ECC_BYTES; i++) {
- if (ctrl->ecc_layout[i] == 0xffff)
- break;
- else
- printf("%c%d", i%16 ? ' ' : '\n',
- ctrl->ecc_layout[i]);
- }
- printf("\n");
-}
-
-static int
-is_ctrl_running(int ctrl_no, int *running)
-{
- struct sim_ctrl ctrl;
- int err, fd;
-
- ctrl.num = ctrl_no;
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- err = ioctl(fd, NANDSIM_STATUS_CTRL, &ctrl);
- if (err) {
- error(MSG_STATUSACQCTRL, ctrl_no);
- close(fd);
- return (err);
- }
- *running = ctrl.running;
- close(fd);
- return (0);
-}
-
-static int
-is_ctrl_created(int ctrl_no, int *created)
-{
- struct sim_ctrl ctrl;
- int err, fd;
-
- ctrl.num = ctrl_no;
-
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- err = ioctl(fd, NANDSIM_STATUS_CTRL, &ctrl);
- if (err) {
- error("Could not acquire conf for ctrl#%d", ctrl_no);
- close(fd);
- return (err);
- }
- *created = ctrl.created;
- close(fd);
- return (0);
-}
-
-static int
-is_chip_created(int ctrl_no, int chip_no, int *created)
-{
- struct sim_chip chip;
- int err, fd;
-
- chip.ctrl_num = ctrl_no;
- chip.num = chip_no;
-
- if (opendev(&fd) != EX_OK)
- return (EX_OSFILE);
-
- err = ioctl(fd, NANDSIM_STATUS_CHIP, &chip);
- if (err) {
- error("Could not acquire conf for chip#%d", chip_no);
- close(fd);
- return (err);
- }
- *created = chip.created;
- close(fd);
- return (0);
-}
-
-static int
-assert_chip_connected(int ctrl_no, int chip_no)
-{
- int created, running;
-
- if (is_ctrl_created(ctrl_no, &created))
- return (0);
-
- if (!created) {
- error(MSG_NOCTRL, ctrl_no);
- return (0);
- }
-
- if (is_chip_created(ctrl_no, chip_no, &created))
- return (0);
-
- if (!created) {
- error(MSG_NOTCONFIGDCTRLCHIP, ctrl_no, chip_no);
- return (0);
- }
-
- if (is_ctrl_running(ctrl_no, &running))
- return (0);
-
- if (!running) {
- error(MSG_NOTRUNNING, ctrl_no);
- return (0);
- }
-
- return (1);
-}
-
-static int
-printstats(int ctrlno, int chipno, uint32_t pageno, int cdevd)
-{
- struct page_stat_io pstats;
- struct block_stat_io bstats;
- struct chip_param_io cparams;
- uint32_t blkidx;
- int err;
-
- /* Gather information about chip */
- err = ioctl(cdevd, NAND_IO_GET_CHIP_PARAM, &cparams);
-
- if (err) {
- error("Could not acquire chip info for chip attached to cs#"
- "%d, ctrl#%d", chipno, ctrlno);
- return (EX_SOFTWARE);
- }
-
- blkidx = (pageno / cparams.pages_per_block);
- bstats.block_num = blkidx;
-
- err = ioctl(cdevd, NAND_IO_BLOCK_STAT, &bstats);
- if (err) {
- error("Could not acquire block#%d statistics!", blkidx);
- return (ENXIO);
- }
-
- printf("Block #%d erased: %d\n", blkidx, bstats.block_erased);
- pstats.page_num = pageno;
-
- err = ioctl(cdevd, NAND_IO_PAGE_STAT, &pstats);
- if (err) {
- error("Could not acquire page statistics!");
- return (ENXIO);
- }
-
- debug("BLOCKIDX = %d PAGENO (REL. TO BLK) = %d\n", blkidx,
- pstats.page_num);
-
- printf("Page#%d : reads:%d writes:%d \n\traw reads:%d raw writes:%d "
- "\n\tecc_succeeded:%d ecc_corrected:%d ecc_failed:%d\n",
- pstats.page_num, pstats.page_read, pstats.page_written,
- pstats.page_raw_read, pstats.page_raw_written,
- pstats.ecc_succeded, pstats.ecc_corrected, pstats.ecc_failed);
- return (0);
-}
diff --git a/usr.sbin/nandsim/nandsim_cfgparse.c b/usr.sbin/nandsim/nandsim_cfgparse.c
deleted file mode 100644
index 4a310fb58a0f..000000000000
--- a/usr.sbin/nandsim/nandsim_cfgparse.c
+++ /dev/null
@@ -1,961 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-
-#include <dev/nand/nandsim.h>
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sysexits.h>
-#include <unistd.h>
-
-#include "nandsim_cfgparse.h"
-
-#define warn(fmt, args...) do { \
- printf("WARNING: " fmt "\n", ##args); } while (0)
-
-#define error(fmt, args...) do { \
- printf("ERROR: " fmt "\n", ##args); } while (0)
-
-#define MSG_MANDATORYKEYMISSING "mandatory key \"%s\" value belonging to " \
- "section \"%s\" is missing!\n"
-
-#define DEBUG
-#undef DEBUG
-
-#ifdef DEBUG
-#define debug(fmt, args...) do { \
- printf("NANDSIM_CONF:" fmt "\n", ##args); } while (0)
-#else
-#define debug(fmt, args...) do {} while(0)
-#endif
-
-#define STRBUFSIZ 2000
-
-/* Macros extracts type and type size */
-#define TYPE(x) ((x) & 0xf8)
-#define SIZE(x) (((x) & 0x07))
-
-/* Erase/Prog/Read time max and min values */
-#define DELAYTIME_MIN 10000
-#define DELAYTIME_MAX 10000000
-
-/* Structure holding configuration for controller. */
-static struct sim_ctrl ctrl_conf;
-/* Structure holding configuration for chip. */
-static struct sim_chip chip_conf;
-
-static struct nandsim_key nandsim_ctrl_keys[] = {
- {"num_cs", 1, VALUE_UINT | SIZE_8, (void *)&ctrl_conf.num_cs, 0},
- {"ctrl_num", 1, VALUE_UINT | SIZE_8, (void *)&ctrl_conf.num, 0},
-
- {"ecc_layout", 1, VALUE_UINTARRAY | SIZE_16,
- (void *)&ctrl_conf.ecc_layout, MAX_ECC_BYTES},
-
- {"filename", 0, VALUE_STRING,
- (void *)&ctrl_conf.filename, FILENAME_SIZE},
-
- {"ecc", 0, VALUE_BOOL, (void *)&ctrl_conf.ecc, 0},
- {NULL, 0, 0, NULL, 0},
-};
-
-static struct nandsim_key nandsim_chip_keys[] = {
- {"chip_cs", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.num, 0},
- {"chip_ctrl", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.ctrl_num,
- 0},
- {"device_id", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.device_id,
- 0},
- {"manufacturer_id", 1, VALUE_UINT | SIZE_8,
- (void *)&chip_conf.manufact_id, 0},
- {"model", 0, VALUE_STRING, (void *)&chip_conf.device_model,
- DEV_MODEL_STR_SIZE},
- {"manufacturer", 0, VALUE_STRING, (void *)&chip_conf.manufacturer,
- MAN_STR_SIZE},
- {"page_size", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.page_size,
- 0},
- {"oob_size", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.oob_size,
- 0},
- {"pages_per_block", 1, VALUE_UINT | SIZE_32,
- (void *)&chip_conf.pgs_per_blk, 0},
- {"blocks_per_lun", 1, VALUE_UINT | SIZE_32,
- (void *)&chip_conf.blks_per_lun, 0},
- {"luns", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.luns, 0},
- {"column_addr_cycle", 1,VALUE_UINT | SIZE_8,
- (void *)&chip_conf.col_addr_cycles, 0},
- {"row_addr_cycle", 1, VALUE_UINT | SIZE_8,
- (void *)&chip_conf.row_addr_cycles, 0},
- {"program_time", 0, VALUE_UINT | SIZE_32,
- (void *)&chip_conf.prog_time, 0},
- {"erase_time", 0, VALUE_UINT | SIZE_32,
- (void *)&chip_conf.erase_time, 0},
- {"read_time", 0, VALUE_UINT | SIZE_32,
- (void *)&chip_conf.read_time, 0},
- {"width", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.width, 0},
- {"wear_out", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.wear_level,
- 0},
- {"bad_block_map", 0, VALUE_UINTARRAY | SIZE_32,
- (void *)&chip_conf.bad_block_map, MAX_BAD_BLOCKS},
- {NULL, 0, 0, NULL, 0},
-};
-
-static struct nandsim_section sections[] = {
- {"ctrl", (struct nandsim_key *)&nandsim_ctrl_keys},
- {"chip", (struct nandsim_key *)&nandsim_chip_keys},
- {NULL, NULL},
-};
-
-static uint8_t logoutputtoint(char *, int *);
-static uint8_t validate_chips(struct sim_chip *, int, struct sim_ctrl *, int);
-static uint8_t validate_ctrls(struct sim_ctrl *, int);
-static int configure_sim(const char *, struct rcfile *);
-static int create_ctrls(struct rcfile *, struct sim_ctrl **, int *);
-static int create_chips(struct rcfile *, struct sim_chip **, int *);
-static void destroy_ctrls(struct sim_ctrl *);
-static void destroy_chips(struct sim_chip *);
-static int validate_section_config(struct rcfile *, const char *, int);
-
-int
-convert_argint(char *arg, int *value)
-{
-
- if (arg == NULL || value == NULL)
- return (EINVAL);
-
- errno = 0;
- *value = (int)strtol(arg, NULL, 0);
- if (*value == 0 && errno != 0) {
- error("Cannot convert to number argument \'%s\'", arg);
- return (EINVAL);
- }
- return (0);
-}
-
-int
-convert_arguint(char *arg, unsigned int *value)
-{
-
- if (arg == NULL || value == NULL)
- return (EINVAL);
-
- errno = 0;
- *value = (unsigned int)strtol(arg, NULL, 0);
- if (*value == 0 && errno != 0) {
- error("Cannot convert to number argument \'%s\'", arg);
- return (EINVAL);
- }
- return (0);
-}
-
-/* Parse given ',' separated list of bytes into buffer. */
-int
-parse_intarray(char *array, int **buffer)
-{
- char *tmp, *tmpstr, *origstr;
- unsigned int currbufp = 0, i;
- unsigned int count = 0, from = 0, to = 0;
-
- /* Remove square braces */
- if (array[0] == '[')
- array ++;
- if (array[strlen(array)-1] == ']')
- array[strlen(array)-1] = ',';
-
- from = strlen(array);
- origstr = (char *)malloc(sizeof(char) * from);
- strcpy(origstr, array);
-
- tmpstr = (char *)strtok(array, ",");
- /* First loop checks for how big int array we need to allocate */
- while (tmpstr != NULL) {
- errno = 0;
- if ((tmp = strchr(tmpstr, '-')) != NULL) {
- *tmp = ' ';
- if (convert_arguint(tmpstr, &from) ||
- convert_arguint(tmp, &to)) {
- free(origstr);
- return (EINVAL);
- }
-
- count += to - from + 1;
- } else {
- if (convert_arguint(tmpstr, &from)) {
- free(origstr);
- return (EINVAL);
- }
- count++;
- }
- tmpstr = (char *)strtok(NULL, ",");
- }
-
- if (count == 0)
- goto out;
-
- /* Allocate buffer of ints */
- tmpstr = (char *)strtok(origstr, ",");
- *buffer = malloc(count * sizeof(int));
-
- /* Second loop is just inserting converted values into int array */
- while (tmpstr != NULL) {
- errno = 0;
- if ((tmp = strchr(tmpstr, '-')) != NULL) {
- *tmp = ' ';
- from = strtol(tmpstr, NULL, 0);
- to = strtol(tmp, NULL, 0);
- tmpstr = strtok(NULL, ",");
- for (i = from; i <= to; i ++)
- (*buffer)[currbufp++] = i;
- continue;
- }
- errno = 0;
- from = (int)strtol(tmpstr, NULL, 0);
- (*buffer)[currbufp++] = from;
- tmpstr = (char *)strtok(NULL, ",");
- }
-out:
- free(origstr);
- return (count);
-}
-
-/* Convert logoutput strings literals into appropriate ints. */
-static uint8_t
-logoutputtoint(char *logoutput, int *output)
-{
- int out;
-
- if (strcmp(logoutput, "file") == 0)
- out = NANDSIM_OUTPUT_FILE;
-
- else if (strcmp(logoutput, "console") == 0)
- out = NANDSIM_OUTPUT_CONSOLE;
-
- else if (strcmp(logoutput, "ram") == 0)
- out = NANDSIM_OUTPUT_RAM;
-
- else if (strcmp(logoutput, "none") == 0)
- out = NANDSIM_OUTPUT_NONE;
- else
- out = -1;
-
- *output = out;
-
- if (out == -1)
- return (EINVAL);
- else
- return (0);
-}
-
-static int
-configure_sim(const char *devfname, struct rcfile *f)
-{
- struct sim_param sim_conf;
- char buf[255];
- int err, tmpv, fd;
-
- err = rc_getint(f, "sim", 0, "log_level", &tmpv);
-
- if (tmpv < 0 || tmpv > 255 || err) {
- error("Bad log level specified (%d)\n", tmpv);
- return (ENOTSUP);
- } else
- sim_conf.log_level = tmpv;
-
- rc_getstring(f, "sim", 0, "log_output", 255, (char *)&buf);
-
- tmpv = -1;
- err = logoutputtoint((char *)&buf, &tmpv);
- if (err) {
- error("Log output specified in config file does not seem to "
- "be valid (%s)!", (char *)&buf);
- return (ENOTSUP);
- }
-
- sim_conf.log_output = tmpv;
-
- fd = open(devfname, O_RDWR);
- if (fd == -1) {
- error("could not open simulator device file (%s)!",
- devfname);
- return (EX_OSFILE);
- }
-
- err = ioctl(fd, NANDSIM_SIM_PARAM, &sim_conf);
- if (err) {
- error("simulator parameters could not be modified: %s",
- strerror(errno));
- close(fd);
- return (ENXIO);
- }
-
- close(fd);
- return (EX_OK);
-}
-
-static int
-create_ctrls(struct rcfile *f, struct sim_ctrl **ctrls, int *cnt)
-{
- int count, i;
- struct sim_ctrl *ctrlsptr;
-
- count = rc_getsectionscount(f, "ctrl");
- if (count > MAX_SIM_DEV) {
- error("Too many CTRL sections specified(%d)", count);
- return (ENOTSUP);
- } else if (count == 0) {
- error("No ctrl sections specified");
- return (ENOENT);
- }
-
- ctrlsptr = (struct sim_ctrl *)malloc(sizeof(struct sim_ctrl) * count);
- if (ctrlsptr == NULL) {
- error("Could not allocate memory for ctrl configuration");
- return (ENOMEM);
- }
-
- for (i = 0; i < count; i++) {
- bzero((void *)&ctrl_conf, sizeof(ctrl_conf));
-
- /*
- * ECC layout have to end up with 0xffff, so
- * we're filling buffer with 0xff. If ecc_layout is
- * defined in config file, values will be overridden.
- */
- memset((void *)&ctrl_conf.ecc_layout, 0xff,
- sizeof(ctrl_conf.ecc_layout));
-
- if (validate_section_config(f, "ctrl", i) != 0) {
- free(ctrlsptr);
- return (EINVAL);
- }
-
- if (parse_section(f, "ctrl", i) != 0) {
- free(ctrlsptr);
- return (EINVAL);
- }
-
- memcpy(&ctrlsptr[i], &ctrl_conf, sizeof(ctrl_conf));
- /* Try to create ctrl with config parsed */
- debug("NUM=%d\nNUM_CS=%d\nECC=%d\nFILENAME=%s\nECC_LAYOUT[0]"
- "=%d\nECC_LAYOUT[1]=%d\n\n",
- ctrlsptr[i].num, ctrlsptr[i].num_cs, ctrlsptr[i].ecc,
- ctrlsptr[i].filename, ctrlsptr[i].ecc_layout[0],
- ctrlsptr[i].ecc_layout[1]);
- }
- *cnt = count;
- *ctrls = ctrlsptr;
- return (0);
-}
-
-static void
-destroy_ctrls(struct sim_ctrl *ctrls)
-{
-
- free(ctrls);
-}
-
-static int
-create_chips(struct rcfile *f, struct sim_chip **chips, int *cnt)
-{
- struct sim_chip *chipsptr;
- int count, i;
-
- count = rc_getsectionscount(f, "chip");
- if (count > (MAX_CTRL_CS * MAX_SIM_DEV)) {
- error("Too many chip sections specified(%d)", count);
- return (ENOTSUP);
- } else if (count == 0) {
- error("No chip sections specified");
- return (ENOENT);
- }
-
- chipsptr = (struct sim_chip *)malloc(sizeof(struct sim_chip) * count);
- if (chipsptr == NULL) {
- error("Could not allocate memory for chip configuration");
- return (ENOMEM);
- }
-
- for (i = 0; i < count; i++) {
- bzero((void *)&chip_conf, sizeof(chip_conf));
-
- /*
- * Bad block map have to end up with 0xffff, so
- * we're filling array with 0xff. If bad block map is
- * defined in config file, values will be overridden.
- */
- memset((void *)&chip_conf.bad_block_map, 0xff,
- sizeof(chip_conf.bad_block_map));
-
- if (validate_section_config(f, "chip", i) != 0) {
- free(chipsptr);
- return (EINVAL);
- }
-
- if (parse_section(f, "chip", i) != 0) {
- free(chipsptr);
- return (EINVAL);
- }
-
- memcpy(&chipsptr[i], &chip_conf, sizeof(chip_conf));
-
- /* Try to create chip with config parsed */
- debug("CHIP:\nNUM=%d\nCTRL_NUM=%d\nDEVID=%d\nMANID=%d\n"
- "PAGE_SZ=%d\nOOBSZ=%d\nREAD_T=%d\nDEVMODEL=%s\n"
- "MAN=%s\nCOLADDRCYCLES=%d\nROWADDRCYCLES=%d\nCHWIDTH=%d\n"
- "PGS/BLK=%d\nBLK/LUN=%d\nLUNS=%d\nERR_RATIO=%d\n"
- "WEARLEVEL=%d\nISWP=%d\n\n\n\n",
- chipsptr[i].num, chipsptr[i].ctrl_num,
- chipsptr[i].device_id, chipsptr[i].manufact_id,
- chipsptr[i].page_size, chipsptr[i].oob_size,
- chipsptr[i].read_time, chipsptr[i].device_model,
- chipsptr[i].manufacturer, chipsptr[i].col_addr_cycles,
- chipsptr[i].row_addr_cycles, chipsptr[i].width,
- chipsptr[i].pgs_per_blk, chipsptr[i].blks_per_lun,
- chipsptr[i].luns, chipsptr[i].error_ratio,
- chipsptr[i].wear_level, chipsptr[i].is_wp);
- }
- *cnt = count;
- *chips = chipsptr;
- return (0);
-}
-
-static void
-destroy_chips(struct sim_chip *chips)
-{
-
- free(chips);
-}
-
-int
-parse_config(char *cfgfname, const char *devfname)
-{
- int err = 0, fd;
- unsigned int chipsectionscnt, ctrlsectionscnt, i;
- struct rcfile *f;
- struct sim_chip *chips;
- struct sim_ctrl *ctrls;
-
- err = rc_open(cfgfname, "r", &f);
- if (err) {
- error("could not open configuration file (%s)", cfgfname);
- return (EX_NOINPUT);
- }
-
- /* First, try to configure simulator itself. */
- if (configure_sim(devfname, f) != EX_OK) {
- rc_close(f);
- return (EINVAL);
- }
-
- debug("SIM CONFIGURED!\n");
- /* Then create controllers' configs */
- if (create_ctrls(f, &ctrls, &ctrlsectionscnt) != 0) {
- rc_close(f);
- return (ENXIO);
- }
- debug("CTRLS CONFIG READ!\n");
-
- /* Then create chips' configs */
- if (create_chips(f, &chips, &chipsectionscnt) != 0) {
- destroy_ctrls(ctrls);
- rc_close(f);
- return (ENXIO);
- }
- debug("CHIPS CONFIG READ!\n");
-
- if (validate_ctrls(ctrls, ctrlsectionscnt) != 0) {
- destroy_ctrls(ctrls);
- destroy_chips(chips);
- rc_close(f);
- return (EX_SOFTWARE);
- }
- if (validate_chips(chips, chipsectionscnt, ctrls,
- ctrlsectionscnt) != 0) {
- destroy_ctrls(ctrls);
- destroy_chips(chips);
- rc_close(f);
- return (EX_SOFTWARE);
- }
-
- /* Open device */
- fd = open(devfname, O_RDWR);
- if (fd == -1) {
- error("could not open simulator device file (%s)!",
- devfname);
- rc_close(f);
- destroy_chips(chips);
- destroy_ctrls(ctrls);
- return (EX_OSFILE);
- }
-
- debug("SIM CONFIG STARTED!\n");
-
- /* At this stage, both ctrls' and chips' configs should be valid */
- for (i = 0; i < ctrlsectionscnt; i++) {
- err = ioctl(fd, NANDSIM_CREATE_CTRL, &ctrls[i]);
- if (err) {
- if (err == EEXIST)
- error("Controller#%d already created\n",
- ctrls[i].num);
- else if (err == EINVAL)
- error("Incorrect controller number (%d)\n",
- ctrls[i].num);
- else
- error("Could not created controller#%d\n",
- ctrls[i].num);
- /* Errors during controller creation stops parsing */
- close(fd);
- rc_close(f);
- destroy_ctrls(ctrls);
- destroy_chips(chips);
- return (ENXIO);
- }
- debug("CTRL#%d CONFIG STARTED!\n", i);
- }
-
- for (i = 0; i < chipsectionscnt; i++) {
- err = ioctl(fd, NANDSIM_CREATE_CHIP, &chips[i]);
- if (err) {
- if (err == EEXIST)
- error("Chip#%d for controller#%d already "
- "created\n", chips[i].num,
- chips[i].ctrl_num);
- else if (err == EINVAL)
- error("Incorrect chip number (%d:%d)\n",
- chips[i].num, chips[i].ctrl_num);
- else
- error("Could not create chip (%d:%d)\n",
- chips[i].num, chips[i].ctrl_num);
- error("Could not start chip#%d\n", i);
- destroy_chips(chips);
- destroy_ctrls(ctrls);
- close(fd);
- rc_close(f);
- return (ENXIO);
- }
- }
- debug("CHIPS CONFIG STARTED!\n");
-
- close(fd);
- rc_close(f);
- destroy_chips(chips);
- destroy_ctrls(ctrls);
- return (0);
-}
-
-/*
- * Function tries to get appropriate value for given key, convert it to
- * array of ints (of given size), and perform all the necessary checks and
- * conversions.
- */
-static int
-get_argument_intarray(const char *sect_name, int sectno,
- struct nandsim_key *key, struct rcfile *f)
-{
- char strbuf[STRBUFSIZ];
- int *intbuf;
- int getres;
- uint32_t cnt, i = 0;
-
- getres = rc_getstring(f, sect_name, sectno, key->keyname, STRBUFSIZ,
- (char *)&strbuf);
-
- if (getres != 0) {
- if (key->mandatory != 0) {
- error(MSG_MANDATORYKEYMISSING, key->keyname,
- sect_name);
- return (EINVAL);
- } else
- /* Non-mandatory key, not present -- skip */
- return (0);
- }
- cnt = parse_intarray((char *)&strbuf, &intbuf);
- cnt = (cnt <= key->maxlength) ? cnt : key->maxlength;
-
- for (i = 0; i < cnt; i++) {
- if (SIZE(key->valuetype) == SIZE_8)
- *((uint8_t *)(key->field) + i) =
- (uint8_t)intbuf[i];
- else if (SIZE(key->valuetype) == SIZE_16)
- *((uint16_t *)(key->field) + i) =
- (uint16_t)intbuf[i];
- else
- *((uint32_t *)(key->field) + i) =
- (uint32_t)intbuf[i];
- }
- free(intbuf);
- return (0);
-}
-
-/*
- * Function tries to get appropriate value for given key, convert it to
- * int of certain length.
- */
-static int
-get_argument_int(const char *sect_name, int sectno, struct nandsim_key *key,
- struct rcfile *f)
-{
- int getres;
- uint32_t val;
-
- getres = rc_getint(f, sect_name, sectno, key->keyname, &val);
- if (getres != 0) {
-
- if (key->mandatory != 0) {
- error(MSG_MANDATORYKEYMISSING, key->keyname,
- sect_name);
-
- return (EINVAL);
- } else
- /* Non-mandatory key, not present -- skip */
- return (0);
- }
- if (SIZE(key->valuetype) == SIZE_8)
- *(uint8_t *)(key->field) = (uint8_t)val;
- else if (SIZE(key->valuetype) == SIZE_16)
- *(uint16_t *)(key->field) = (uint16_t)val;
- else
- *(uint32_t *)(key->field) = (uint32_t)val;
- return (0);
-}
-
-/* Function tries to get string value for given key */
-static int
-get_argument_string(const char *sect_name, int sectno,
- struct nandsim_key *key, struct rcfile *f)
-{
- char strbuf[STRBUFSIZ];
- int getres;
-
- getres = rc_getstring(f, sect_name, sectno, key->keyname, STRBUFSIZ,
- strbuf);
-
- if (getres != 0) {
- if (key->mandatory != 0) {
- error(MSG_MANDATORYKEYMISSING, key->keyname,
- sect_name);
- return (1);
- } else
- /* Non-mandatory key, not present -- skip */
- return (0);
- }
- strncpy(key->field, (char *)&strbuf, (size_t)(key->maxlength - 1));
- return (0);
-}
-
-/* Function tries to get on/off value for given key */
-static int
-get_argument_bool(const char *sect_name, int sectno, struct nandsim_key *key,
- struct rcfile *f)
-{
- int getres, val;
-
- getres = rc_getbool(f, sect_name, sectno, key->keyname, &val);
- if (getres != 0) {
- if (key->mandatory != 0) {
- error(MSG_MANDATORYKEYMISSING, key->keyname,
- sect_name);
- return (1);
- } else
- /* Non-mandatory key, not present -- skip */
- return (0);
- }
- *(uint8_t *)key->field = (uint8_t)val;
- return (0);
-}
-
-int
-parse_section(struct rcfile *f, const char *sect_name, int sectno)
-{
- struct nandsim_key *key;
- struct nandsim_section *sect = (struct nandsim_section *)&sections;
- int getres = 0;
-
- while (1) {
- if (sect == NULL)
- return (EINVAL);
-
- if (strcmp(sect->name, sect_name) == 0)
- break;
- else
- sect++;
- }
- key = sect->keys;
- do {
- debug("->Section: %s, Key: %s, type: %d, size: %d",
- sect_name, key->keyname, TYPE(key->valuetype),
- SIZE(key->valuetype)/2);
-
- switch (TYPE(key->valuetype)) {
- case VALUE_UINT:
- /* Single int value */
- getres = get_argument_int(sect_name, sectno, key, f);
-
- if (getres != 0)
- return (getres);
-
- break;
- case VALUE_UINTARRAY:
- /* Array of ints */
- getres = get_argument_intarray(sect_name,
- sectno, key, f);
-
- if (getres != 0)
- return (getres);
-
- break;
- case VALUE_STRING:
- /* Array of chars */
- getres = get_argument_string(sect_name, sectno, key,
- f);
-
- if (getres != 0)
- return (getres);
-
- break;
- case VALUE_BOOL:
- /* Boolean value (true/false/on/off/yes/no) */
- getres = get_argument_bool(sect_name, sectno, key,
- f);
-
- if (getres != 0)
- return (getres);
-
- break;
- }
- } while ((++key)->keyname != NULL);
-
- return (0);
-}
-
-static uint8_t
-validate_chips(struct sim_chip *chips, int chipcnt,
- struct sim_ctrl *ctrls, int ctrlcnt)
-{
- int cchipcnt, i, width, j, id, max;
-
- cchipcnt = chipcnt;
- for (chipcnt -= 1; chipcnt >= 0; chipcnt--) {
- if (chips[chipcnt].num >= MAX_CTRL_CS) {
- error("chip no. too high (%d)!!\n",
- chips[chipcnt].num);
- return (EINVAL);
- }
-
- if (chips[chipcnt].ctrl_num >= MAX_SIM_DEV) {
- error("controller no. too high (%d)!!\n",
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- }
-
- if (chips[chipcnt].width != 8 &&
- chips[chipcnt].width != 16) {
- error("invalid width:%d for chip#%d",
- chips[chipcnt].width, chips[chipcnt].num);
- return (EINVAL);
- }
-
- /* Check if page size is > 512 and if its power of 2 */
- if (chips[chipcnt].page_size < 512 ||
- (chips[chipcnt].page_size &
- (chips[chipcnt].page_size - 1)) != 0) {
- error("invalid page size:%d for chip#%d at ctrl#%d!!"
- "\n", chips[chipcnt].page_size,
- chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- }
-
- /* Check if controller no. ctrl_num is configured */
- for (i = 0, id = -1; i < ctrlcnt && id == -1; i++)
- if (ctrls[i].num == chips[chipcnt].ctrl_num)
- id = i;
-
- if (i == ctrlcnt && id == -1) {
- error("Missing configuration for controller %d"
- " (at least one chip is connected to it)",
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- } else {
- /*
- * Controller is configured -> check oob_size
- * validity
- */
- i = 0;
- max = ctrls[id].ecc_layout[0];
- while (i < MAX_ECC_BYTES &&
- ctrls[id].ecc_layout[i] != 0xffff) {
-
- if (ctrls[id].ecc_layout[i] > max)
- max = ctrls[id].ecc_layout[i];
- i++;
- }
-
- if (chips[chipcnt].oob_size < (unsigned)i) {
- error("OOB size for chip#%d at ctrl#%d is "
- "smaller than ecc layout length!",
- chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- exit(EINVAL);
- }
-
- if (chips[chipcnt].oob_size < (unsigned)max) {
- error("OOB size for chip#%d at ctrl#%d is "
- "smaller than maximal ecc position in "
- "defined layout!", chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- exit(EINVAL);
- }
-
-
- }
-
- if ((chips[chipcnt].erase_time < DELAYTIME_MIN ||
- chips[chipcnt].erase_time > DELAYTIME_MAX) &&
- chips[chipcnt].erase_time != 0) {
- error("Invalid erase time value for chip#%d at "
- "ctrl#%d",
- chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- }
-
- if ((chips[chipcnt].prog_time < DELAYTIME_MIN ||
- chips[chipcnt].prog_time > DELAYTIME_MAX) &&
- chips[chipcnt].prog_time != 0) {
- error("Invalid prog time value for chip#%d at "
- "ctr#%d!",
- chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- }
-
- if ((chips[chipcnt].read_time < DELAYTIME_MIN ||
- chips[chipcnt].read_time > DELAYTIME_MAX) &&
- chips[chipcnt].read_time != 0) {
- error("Invalid read time value for chip#%d at "
- "ctrl#%d!",
- chips[chipcnt].num,
- chips[chipcnt].ctrl_num);
- return (EINVAL);
- }
- }
- /* Check if chips attached to the same controller, have same width */
- for (i = 0; i < ctrlcnt; i++) {
- width = -1;
- for (j = 0; j < cchipcnt; j++) {
- if (chips[j].ctrl_num == i) {
- if (width == -1) {
- width = chips[j].width;
- } else {
- if (width != chips[j].width) {
- error("Chips attached to "
- "ctrl#%d have different "
- "widths!\n", i);
- return (EINVAL);
- }
- }
- }
- }
- }
-
- return (0);
-}
-
-static uint8_t
-validate_ctrls(struct sim_ctrl *ctrl, int ctrlcnt)
-{
- for (ctrlcnt -= 1; ctrlcnt >= 0; ctrlcnt--) {
- if (ctrl[ctrlcnt].num > MAX_SIM_DEV) {
- error("Controller no. too high (%d)!!\n",
- ctrl[ctrlcnt].num);
- return (EINVAL);
- }
- if (ctrl[ctrlcnt].num_cs > MAX_CTRL_CS) {
- error("Too many CS (%d)!!\n", ctrl[ctrlcnt].num_cs);
- return (EINVAL);
- }
- if (ctrl[ctrlcnt].ecc != 0 && ctrl[ctrlcnt].ecc != 1) {
- error("ECC is set to neither 0 nor 1 !\n");
- return (EINVAL);
- }
- }
-
- return (0);
-}
-
-static int validate_section_config(struct rcfile *f, const char *sect_name,
- int sectno)
-{
- struct nandsim_key *key;
- struct nandsim_section *sect;
- char **keys_tbl;
- int i, match;
-
- for (match = 0, sect = (struct nandsim_section *)&sections;
- sect != NULL; sect++) {
- if (strcmp(sect->name, sect_name) == 0) {
- match = 1;
- break;
- }
- }
-
- if (match == 0)
- return (EINVAL);
-
- keys_tbl = rc_getkeys(f, sect_name, sectno);
- if (keys_tbl == NULL)
- return (ENOMEM);
-
- for (i = 0; keys_tbl[i] != NULL; i++) {
- key = sect->keys;
- match = 0;
- do {
- if (strcmp(keys_tbl[i], key->keyname) == 0) {
- match = 1;
- break;
- }
- } while ((++key)->keyname != NULL);
-
- if (match == 0) {
- error("Invalid key in config file: %s\n", keys_tbl[i]);
- free(keys_tbl);
- return (EINVAL);
- }
- }
-
- free(keys_tbl);
- return (0);
-}
diff --git a/usr.sbin/nandsim/nandsim_cfgparse.h b/usr.sbin/nandsim/nandsim_cfgparse.h
deleted file mode 100644
index 12365666ad93..000000000000
--- a/usr.sbin/nandsim/nandsim_cfgparse.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (C) 2009-2012 Semihalf
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL 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 _NANDSIM_CONFPARSER_H_
-#define _NANDSIM_CONFPARSER_H_
-
-#define VALUE_UINT 0x08
-#define VALUE_INT 0x10
-#define VALUE_UINTARRAY 0x18
-#define VALUE_INTARRAY 0x20
-#define VALUE_STRING 0x28
-#define VALUE_CHAR 0x40
-#define VALUE_BOOL 0x48
-
-#define SIZE_8 0x01
-#define SIZE_16 0x02
-#define SIZE_32 0x04
-
-#include "nandsim_rcfile.h"
-
-/*
- * keyname = name of a key,
- * mandatory = is key mandatory in section belonging to, 0=false 1=true
- * valuetype = what kind of value is assigned to that key, e.g.
- * VALUE_UINT | SIZE_8 -- unsigned uint size 8 bits;
- * VALUE_UINTARRAY | SIZE_8 -- array of uints 8-bit long;
- * VALUE_BOOL -- 'on', 'off','true','false','yes' or 'no'
- * literals;
- * VALUE_STRING -- strings
- * field = ptr to the field that should hold value for parsed value
- * maxlength = contains maximum length of an array (used only with either
- * VALUE_STRING or VALUE_(U)INTARRAY value types.
- */
-struct nandsim_key {
- const char *keyname;
- uint8_t mandatory;
- uint8_t valuetype;
- void *field;
- uint32_t maxlength;
-};
-struct nandsim_section {
- const char *name;
- struct nandsim_key *keys;
-};
-
-struct nandsim_config {
- struct sim_param **simparams;
- struct sim_chip **simchips;
- struct sim_ctrl **simctrls;
- int chipcnt;
- int ctrlcnt;
-};
-
-int parse_intarray(char *, int **);
-int parse_config(char *, const char *);
-int parse_section(struct rcfile *, const char *, int);
-int compare_configs(struct nandsim_config *, struct nandsim_config *);
-int convert_argint(char *, int *);
-int convert_arguint(char *, unsigned int *);
-
-#endif /* _NANDSIM_CONFPARSER_H_ */
diff --git a/usr.sbin/nandsim/nandsim_rcfile.c b/usr.sbin/nandsim/nandsim_rcfile.c
deleted file mode 100644
index 8e9cca17f37b..000000000000
--- a/usr.sbin/nandsim/nandsim_rcfile.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * Copyright (c) 1999, Boris Popov
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY 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.
- *
- * from: FreeBSD: src/lib/libncp/ncpl_rcfile.c,v 1.5 2007/01/09 23:27:39 imp Exp
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <pwd.h>
-#include <unistd.h>
-
-#include "nandsim_rcfile.h"
-
-SLIST_HEAD(rcfile_head, rcfile);
-static struct rcfile_head pf_head = {NULL};
-static struct rcsection *rc_findsect(struct rcfile *rcp,
- const char *sectname, int sect_id);
-static struct rcsection *rc_addsect(struct rcfile *rcp,
- const char *sectname);
-static int rc_sect_free(struct rcsection *rsp);
-static struct rckey *rc_sect_findkey(struct rcsection *rsp,
- const char *keyname);
-static struct rckey *rc_sect_addkey(struct rcsection *rsp, const char *name,
- char *value);
-static void rc_key_free(struct rckey *p);
-static void rc_parse(struct rcfile *rcp);
-
-static struct rcfile* rc_find(const char *filename);
-
-/*
- * open rcfile and load its content, if already open - return previous handle
- */
-int
-rc_open(const char *filename, const char *mode,struct rcfile **rcfile)
-{
- struct rcfile *rcp;
- FILE *f;
- rcp = rc_find(filename);
- if (rcp) {
- *rcfile = rcp;
- return (0);
- }
- f = fopen (filename, mode);
- if (f == NULL)
- return errno;
- rcp = malloc(sizeof(struct rcfile));
- if (rcp == NULL) {
- fclose(f);
- return ENOMEM;
- }
- bzero(rcp, sizeof(struct rcfile));
- rcp->rf_name = strdup(filename);
- rcp->rf_f = f;
- SLIST_INSERT_HEAD(&pf_head, rcp, rf_next);
- rc_parse(rcp);
- *rcfile = rcp;
- return (0);
-}
-
-int
-rc_close(struct rcfile *rcp)
-{
- struct rcsection *p,*n;
-
- fclose(rcp->rf_f);
- for (p = SLIST_FIRST(&rcp->rf_sect); p; ) {
- n = p;
- p = SLIST_NEXT(p,rs_next);
- rc_sect_free(n);
- }
- free(rcp->rf_name);
- SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next);
- free(rcp);
- return (0);
-}
-
-static struct rcfile*
-rc_find(const char *filename)
-{
- struct rcfile *p;
-
- SLIST_FOREACH(p, &pf_head, rf_next)
- if (strcmp (filename, p->rf_name) == 0)
- return (p);
- return (0);
-}
-
-/* Find section with given name and id */
-static struct rcsection *
-rc_findsect(struct rcfile *rcp, const char *sectname, int sect_id)
-{
- struct rcsection *p;
-
- SLIST_FOREACH(p, &rcp->rf_sect, rs_next)
- if (strcmp(p->rs_name, sectname) == 0 && p->rs_id == sect_id)
- return (p);
- return (NULL);
-}
-
-static struct rcsection *
-rc_addsect(struct rcfile *rcp, const char *sectname)
-{
- struct rcsection *p;
- int id = 0;
- p = rc_findsect(rcp, sectname, 0);
- if (p) {
- /*
- * If section with that name already exists -- add one more,
- * same named, but with different id (higher by one)
- */
- while (p != NULL) {
- id = p->rs_id + 1;
- p = rc_findsect(rcp, sectname, id);
- }
- }
- p = malloc(sizeof(*p));
- if (!p)
- return (NULL);
- p->rs_name = strdup(sectname);
- p->rs_id = id;
- SLIST_INIT(&p->rs_keys);
- SLIST_INSERT_HEAD(&rcp->rf_sect, p, rs_next);
- return (p);
-}
-
-static int
-rc_sect_free(struct rcsection *rsp)
-{
- struct rckey *p,*n;
-
- for (p = SLIST_FIRST(&rsp->rs_keys); p; ) {
- n = p;
- p = SLIST_NEXT(p,rk_next);
- rc_key_free(n);
- }
- free(rsp->rs_name);
- free(rsp);
- return (0);
-}
-
-static struct rckey *
-rc_sect_findkey(struct rcsection *rsp, const char *keyname)
-{
- struct rckey *p;
-
- SLIST_FOREACH(p, &rsp->rs_keys, rk_next)
- if (strcmp(p->rk_name, keyname)==0)
- return (p);
- return (NULL);
-}
-
-static struct rckey *
-rc_sect_addkey(struct rcsection *rsp, const char *name, char *value)
-{
- struct rckey *p;
- p = rc_sect_findkey(rsp, name);
- if (p) {
- free(p->rk_value);
- } else {
- p = malloc(sizeof(*p));
- if (!p)
- return (NULL);
- SLIST_INSERT_HEAD(&rsp->rs_keys, p, rk_next);
- p->rk_name = strdup(name);
- }
- p->rk_value = value ? strdup(value) : strdup("");
- return (p);
-}
-
-static void
-rc_key_free(struct rckey *p)
-{
- free(p->rk_value);
- free(p->rk_name);
- free(p);
-}
-
-enum { stNewLine, stHeader, stSkipToEOL, stGetKey, stGetValue};
-
-static void
-rc_parse(struct rcfile *rcp)
-{
- FILE *f = rcp->rf_f;
- int state = stNewLine, c;
- struct rcsection *rsp = NULL;
- struct rckey *rkp = NULL;
- char buf[2048];
- char *next = buf, *last = &buf[sizeof(buf)-1];
-
- while ((c = getc (f)) != EOF) {
- if (c == '\r')
- continue;
- if (state == stNewLine) {
- next = buf;
- if (isspace(c))
- continue; /* skip leading junk */
- if (c == '[') {
- state = stHeader;
- rsp = NULL;
- continue;
- }
- if (c == '#' || c == ';') {
- state = stSkipToEOL;
- } else { /* something meaningful */
- state = stGetKey;
- }
- }
- if (state == stSkipToEOL || next == last) {/* ignore long lines */
- if (c == '\n') {
- state = stNewLine;
- next = buf;
- }
- continue;
- }
- if (state == stHeader) {
- if (c == ']') {
- *next = 0;
- next = buf;
- rsp = rc_addsect(rcp, buf);
- state = stSkipToEOL;
- } else
- *next++ = c;
- continue;
- }
- if (state == stGetKey) {
- if (c == ' ' || c == '\t')/* side effect: 'key name='*/
- continue; /* become 'keyname=' */
- if (c == '\n') { /* silently ignore ... */
- state = stNewLine;
- continue;
- }
- if (c != '=') {
- *next++ = c;
- continue;
- }
- *next = 0;
- if (rsp == NULL) {
- fprintf(stderr, "Key '%s' defined before "
- "section\n", buf);
- state = stSkipToEOL;
- continue;
- }
- rkp = rc_sect_addkey(rsp, buf, NULL);
- next = buf;
- state = stGetValue;
- continue;
- }
- /* only stGetValue left */
- if (state != stGetValue) {
- fprintf(stderr, "Well, I can't parse file "
- "'%s'\n",rcp->rf_name);
- state = stSkipToEOL;
- }
- if (c != '\n') {
- *next++ = c;
- continue;
- }
- *next = 0;
- rkp->rk_value = strdup(buf);
- state = stNewLine;
- rkp = NULL;
- } /* while */
- if (c == EOF && state == stGetValue) {
- *next = 0;
- rkp->rk_value = strdup(buf);
- }
-}
-
-int
-rc_getstringptr(struct rcfile *rcp, const char *section, int sect_id,
- const char *key, char **dest)
-{
- struct rcsection *rsp;
- struct rckey *rkp;
-
- *dest = NULL;
- rsp = rc_findsect(rcp, section, sect_id);
- if (!rsp)
- return (ENOENT);
- rkp = rc_sect_findkey(rsp,key);
- if (!rkp)
- return (ENOENT);
- *dest = rkp->rk_value;
- return (0);
-}
-
-int
-rc_getstring(struct rcfile *rcp, const char *section, int sect_id,
- const char *key, unsigned int maxlen, char *dest)
-{
- char *value;
- int error;
-
- error = rc_getstringptr(rcp, section, sect_id, key, &value);
- if (error)
- return (error);
- if (strlen(value) >= maxlen) {
- fprintf(stderr, "line too long for key '%s' in section '%s',"
- "max = %d\n",key, section, maxlen);
- return (EINVAL);
- }
- strcpy(dest,value);
- return (0);
-}
-
-int
-rc_getint(struct rcfile *rcp, const char *section, int sect_id,
- const char *key, int *value)
-{
- struct rcsection *rsp;
- struct rckey *rkp;
-
- rsp = rc_findsect(rcp, section, sect_id);
- if (!rsp)
- return (ENOENT);
- rkp = rc_sect_findkey(rsp,key);
- if (!rkp)
- return (ENOENT);
- errno = 0;
- *value = strtol(rkp->rk_value,NULL,0);
- if (errno) {
- fprintf(stderr, "invalid int value '%s' for key '%s' in "
- "section '%s'\n",rkp->rk_value,key,section);
- return (errno);
- }
- return (0);
-}
-
-/*
- * 1,yes,true
- * 0,no,false
- */
-int
-rc_getbool(struct rcfile *rcp, const char *section, int sect_id,
- const char *key, int *value)
-{
- struct rcsection *rsp;
- struct rckey *rkp;
- char *p;
-
- rsp = rc_findsect(rcp, section, sect_id);
- if (!rsp)
- return (ENOENT);
- rkp = rc_sect_findkey(rsp,key);
- if (!rkp)
- return (ENOENT);
- p = rkp->rk_value;
- while (*p && isspace(*p)) p++;
- if (*p == '0' || strcasecmp(p,"no") == 0 ||
- strcasecmp(p, "false") == 0 ||
- strcasecmp(p, "off") == 0) {
- *value = 0;
- return (0);
- }
- if (*p == '1' || strcasecmp(p,"yes") == 0 ||
- strcasecmp(p, "true") == 0 ||
- strcasecmp(p, "on") == 0) {
- *value = 1;
- return (0);
- }
- fprintf(stderr, "invalid boolean value '%s' for key '%s' in section "
- "'%s' \n",p, key, section);
- return (EINVAL);
-}
-
-/* Count how many sections with given name exists in configuration. */
-int rc_getsectionscount(struct rcfile *f, const char *sectname)
-{
- struct rcsection *p;
- int count = 0;
-
- p = rc_findsect(f, sectname, 0);
- if (p) {
- while (p != NULL) {
- count = p->rs_id + 1;
- p = rc_findsect(f, sectname, count);
- }
- return (count);
- } else
- return (0);
-}
-
-char **
-rc_getkeys(struct rcfile *rcp, const char *sectname, int sect_id)
-{
- struct rcsection *rsp;
- struct rckey *p;
- char **names_tbl;
- int i = 0, count = 0;
-
- rsp = rc_findsect(rcp, sectname, sect_id);
- if (rsp == NULL)
- return (NULL);
-
- SLIST_FOREACH(p, &rsp->rs_keys, rk_next)
- count++;
-
- names_tbl = malloc(sizeof(char *) * (count + 1));
- if (names_tbl == NULL)
- return (NULL);
-
- SLIST_FOREACH(p, &rsp->rs_keys, rk_next)
- names_tbl[i++] = p->rk_name;
-
- names_tbl[i] = NULL;
- return (names_tbl);
-}
-
diff --git a/usr.sbin/nandsim/nandsim_rcfile.h b/usr.sbin/nandsim/nandsim_rcfile.h
deleted file mode 100644
index d92ae870f0fc..000000000000
--- a/usr.sbin/nandsim/nandsim_rcfile.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * Copyright (c) 1999, Boris Popov
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY 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$
- *
- * from: FreeBSD: src/lib/libncp/ncpl_rcfile.c,v 1.5 2007/01/09 23:27:39 imp Exp
- */
-
-#ifndef _SIMRC_H_
-#define _SIMRC_H_
-
-#include <sys/queue.h>
-
-struct rckey {
- SLIST_ENTRY(rckey) rk_next;
- char *rk_name; /* key name */
- char *rk_value; /* key value */
-};
-
-struct rcsection {
- SLIST_ENTRY(rcsection) rs_next;
- SLIST_HEAD(rckey_head,rckey) rs_keys; /* key list */
- char *rs_name; /* section name */
- int rs_id; /* allow few same named */
-};
-
-struct rcfile {
- SLIST_ENTRY(rcfile) rf_next;
- SLIST_HEAD(rcsec_head, rcsection) rf_sect; /* sections list */
- char *rf_name; /* file name */
- FILE *rf_f; /* file desc */
-};
-
-int rc_open(const char *, const char *,struct rcfile **);
-int rc_close(struct rcfile *);
-int rc_getstringptr(struct rcfile *, const char *, int, const char *,
- char **);
-int rc_getstring(struct rcfile *, const char *, int, const char *,
- unsigned int, char *);
-int rc_getint(struct rcfile *, const char *, int, const char *, int *);
-int rc_getbool(struct rcfile *, const char *, int, const char *, int *);
-int rc_getsectionscount(struct rcfile *, const char *);
-char **rc_getkeys(struct rcfile *, const char *, int);
-
-#endif /* _SIMRC_H_ */
diff --git a/usr.sbin/nandsim/sample.conf b/usr.sbin/nandsim/sample.conf
deleted file mode 100644
index bc534e109fe5..000000000000
--- a/usr.sbin/nandsim/sample.conf
+++ /dev/null
@@ -1,174 +0,0 @@
-#-
-# Copyright (C) 2009-2012 Semihalf
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-
-#
-# Sample NANDsim configuration file.
-#
-
-#############################################################################
-#
-# [sim] General (common) simulator configuration section.
-#
-[sim]
-# log_level=0..255
-log_level=11
-
-# log_output=[none, console, ram, file]
-#
-# When log_output=file is specified, each [ctrl] section must have a
-# corresponding 'log_filename' field provided, which specifies log file name
-# to be used.
-log_output=none
-
-#############################################################################
-#
-# [ctrl] Controller configuration section.
-#
-# There can be a number of controllers defined for simulation, each has a
-# dedicated [ctrl] section. With a given controller there are associated
-# subordinate NAND chips, which are tied to chip select lines.
-#
-[ctrl]
-# The number of this controller.
-# ctrl_num=0..3
-ctrl_num=0
-
-# The number of chip selects available at this controller.
-# num_cs=1..4
-num_cs=1
-
-# ECC enable flag.
-# ecc=[on|off]
-ecc=on
-
-# ECC layout. This is the list of byte offsets within OOB area, which comprise
-# the ECC contents set.
-#
-# ecc_layout=[byte1, byte2-byte3, ..byten]
-ecc_layout=[0-53]
-
-# Absolute path to the log file for this controller.
-#log_filename=/var/log/nandsim-ctl0.log
-
-
-#############################################################################
-#
-# [chip] Chip configuration section.
-#
-# There can be a number of individual NAND chip devices defined for
-# simulation, and each has a dedicated [chip] section.
-#
-# A particular chip needs to be associated with its parent NAND controller by
-# specifying the following fields: controller number (chip_ctrl) and the chip
-# select line it is connected to (chip_cs). The chip can be connected to only
-# a single (and unique) controller:cs pair.
-#
-[chip]
-# The number of parent controller. This has to fit one of the controller
-# instance number (ctrl_num from [ctrl] section).
-# chip_ctrl=0..3
-chip_ctrl=0
-
-# Chip select line.
-# chip_cs=0..3
-chip_cs=0
-
-# ONFI device identifier.
-# device_id=0x00..0xff
-device_id=0xd3
-
-# ONFI manufacturer identifier.
-# manufacturer_id=0x00..0xff
-manufacturer_id=0xec
-
-# Textual description of the chip.
-# model="model_name"
-model="k9xxg08uxM:1GiB 3,3V 8-bit"
-
-# Textual name of the chip manufacturer.
-# manufacturer="manufacturer name"
-manufacturer="SAMSUNG"
-
-# page_size=[must be power of 2 and >= 512] (in bytes)
-page_size=2048
-# oob_size=[>0]
-oob_size=64
-# pages_per_block=n*32
-pages_per_block=64
-# blocks_per_lun=[>0]
-blocks_per_lun=4096
-# luns=1..N
-luns=1
-# column_addr_cycle=[1,2]
-column_addr_cycle=2
-# row_addr_cycle=[1,2,3]
-row_addr_cycle=3
-
-# program_time= (in us)
-program_time=0
-# erase_time= (in us)
-erase_time=0
-# read_time= (in us)
-read_time=0
-# ccs_time= (in us)
-#ccs_time=200
-
-# Simulate write-protect on the chip.
-# write_protect=[yes|no]
-#write_protect=no
-
-# Blocks wear-out threshold. Each block has a counter of program-erase cycles;
-# when this counter reaches 'wear_out' value a given block is treated as a bad
-# block (access will report error).
-#
-# Setting wear_out to 0 means that blocks will never wear out.
-#
-# wear_out=0..100000
-wear_out=50000
-
-# Errors per million read/write bytes. This simulates an accidental read/write
-# block error, which can happen in real devices with certain probability. Note
-# this isn't a bad block condition i.e. the block at which the read/write
-# operation is simulated to fail here remains usable, only the operation has
-# not succeeded (this is where ECC comes into play and is supposed to correct
-# such problems).
-#
-# error_ratio=0..1000000
-#error_ratio=50
-
-# Chip data bus width. All chips connected to the same controller must have
-# the same bus width.
-#
-# width=[8|16]
-width=8
-
-# Bad block map. NANDsim emulates bad block behavior upon accessing a block
-# with number from the specified list.
-#
-# bad_block_map=[bad_block1, bad_block2-bad_block3, ..bad_blockn]
-bad_block_map=[100-200]
-
diff --git a/usr.sbin/nandtool/Makefile b/usr.sbin/nandtool/Makefile
deleted file mode 100644
index c01c2fdedbbf..000000000000
--- a/usr.sbin/nandtool/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# $FreeBSD$
-
-PROG= nandtool
-SRCS= nandtool.c nand_read.c nand_write.c nand_erase.c nand_info.c
-SRCS+= nand_readoob.c nand_writeoob.c
-BINDIR= /usr/sbin
-LIBADD= geom
-MAN= nandtool.8
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/nandtool/Makefile.depend b/usr.sbin/nandtool/Makefile.depend
deleted file mode 100644
index 0220673c9076..000000000000
--- a/usr.sbin/nandtool/Makefile.depend
+++ /dev/null
@@ -1,20 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libexpat \
- lib/libgeom \
- lib/libsbuf \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/nandtool/nand_erase.c b/usr.sbin/nandtool/nand_erase.c
deleted file mode 100644
index e9742d15ddf9..000000000000
--- a/usr.sbin/nandtool/nand_erase.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/disk.h>
-#include <libgeom.h>
-#include <dev/nand/nand_dev.h>
-#include "nandtool.h"
-
-int nand_erase(struct cmd_param *params)
-{
- struct chip_param_io chip_params;
- char *dev;
- int fd = -1, ret = 0;
- off_t pos, count;
- off_t start, nblocks, i;
- int block_size, mult;
-
- if (!(dev = param_get_string(params, "dev"))) {
- fprintf(stderr, "Please supply valid 'dev' parameter.\n");
- return (1);
- }
-
- if (param_has_value(params, "count"))
- count = param_get_intx(params, "count");
- else
- count = 1;
-
- if ((fd = g_open(dev, 1)) < 0) {
- perrorf("Cannot open %s", dev);
- return (1);
- }
-
- if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
- perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
- ret = 1;
- goto out;
- }
-
- block_size = chip_params.page_size * chip_params.pages_per_block;
-
- if (param_has_value(params, "page")) {
- pos = chip_params.page_size * param_get_intx(params, "page");
- mult = chip_params.page_size;
- } else if (param_has_value(params, "block")) {
- pos = block_size * param_get_intx(params, "block");
- mult = block_size;
- } else if (param_has_value(params, "pos")) {
- pos = param_get_intx(params, "pos");
- mult = 1;
- } else {
- /* Erase whole chip */
- if (ioctl(fd, DIOCGMEDIASIZE, &count) == -1) {
- ret = 1;
- goto out;
- }
-
- pos = 0;
- mult = 1;
- }
-
- if (pos % block_size) {
- fprintf(stderr, "Position must be block-size aligned!\n");
- ret = 1;
- goto out;
- }
-
- count *= mult;
- start = pos / block_size;
- nblocks = count / block_size;
-
- for (i = 0; i < nblocks; i++) {
- if (g_delete(fd, (start + i) * block_size, block_size) == -1) {
- perrorf("Cannot erase block %d - probably a bad block",
- start + i);
- ret = 1;
- }
- }
-
-out:
- g_close(fd);
-
- return (ret);
-}
-
diff --git a/usr.sbin/nandtool/nand_info.c b/usr.sbin/nandtool/nand_info.c
deleted file mode 100644
index 79f84abd1136..000000000000
--- a/usr.sbin/nandtool/nand_info.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <libgeom.h>
-#include <sys/disk.h>
-#include <dev/nand/nand_dev.h>
-#include "nandtool.h"
-
-int nand_info(struct cmd_param *params)
-{
- struct chip_param_io chip_params;
- int fd = -1, ret = 0;
- int block_size;
- off_t chip_size, media_size;
- const char *dev;
-
- if ((dev = param_get_string(params, "dev")) == NULL) {
- fprintf(stderr, "Please supply 'dev' parameter, eg. "
- "'dev=/dev/gnand0'\n");
- return (1);
- }
-
- if ((fd = g_open(dev, 1)) == -1) {
- perrorf("Cannot open %s", dev);
- return (1);
- }
-
- if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
- perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
- ret = 1;
- goto out;
- }
-
- if (ioctl(fd, DIOCGMEDIASIZE, &media_size) == -1) {
- perrorf("Cannot ioctl(DIOCGMEDIASIZE)");
- ret = 1;
- goto out;
- }
-
- block_size = chip_params.page_size * chip_params.pages_per_block;
- chip_size = block_size * chip_params.blocks;
-
- printf("Device:\t\t\t%s\n", dev);
- printf("Page size:\t\t%d bytes\n", chip_params.page_size);
- printf("Block size:\t\t%d bytes (%d KB)\n", block_size,
- block_size / 1024);
- printf("OOB size per page:\t%d bytes\n", chip_params.oob_size);
- printf("Chip size:\t\t%jd MB\n", (uintmax_t)(chip_size / 1024 / 1024));
- printf("Slice size:\t\t%jd MB\n",
- (uintmax_t)(media_size / 1024 / 1024));
-
-out:
- g_close(fd);
-
- return (ret);
-}
diff --git a/usr.sbin/nandtool/nand_read.c b/usr.sbin/nandtool/nand_read.c
deleted file mode 100644
index 395b0c3fa7f5..000000000000
--- a/usr.sbin/nandtool/nand_read.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <libgeom.h>
-#include <sys/disk.h>
-#include <dev/nand/nand_dev.h>
-#include "nandtool.h"
-
-int nand_read(struct cmd_param *params)
-{
- struct chip_param_io chip_params;
- int fd = -1, out_fd = -1, done = 0, ret = 0;
- char *dev, *out;
- int pos, count, mult, block_size;
- uint8_t *buf = NULL;
-
- if (!(dev = param_get_string(params, "dev"))) {
- fprintf(stderr, "You must specify 'dev' parameter\n");
- return (1);
- }
-
- if ((out = param_get_string(params, "out"))) {
- out_fd = open(out, O_WRONLY|O_CREAT, 0666);
- if (out_fd == -1) {
- perrorf("Cannot open %s for writing", out);
- return (1);
- }
- }
-
- if ((fd = g_open(dev, 1)) == -1) {
- perrorf("Cannot open %s", dev);
- ret = 1;
- goto out;
- }
-
- if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
- perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
- ret = 1;
- goto out;
- }
-
- block_size = chip_params.page_size * chip_params.pages_per_block;
-
- if (param_has_value(params, "page")) {
- pos = chip_params.page_size * param_get_int(params, "page");
- mult = chip_params.page_size;
- } else if (param_has_value(params, "block")) {
- pos = block_size * param_get_int(params, "block");
- mult = block_size;
- } else if (param_has_value(params, "pos")) {
- pos = param_get_int(params, "pos");
- mult = 1;
- if (pos % chip_params.page_size) {
- fprintf(stderr, "Position must be page-size aligned!\n");
- ret = 1;
- goto out;
- }
- } else {
- fprintf(stderr, "You must specify one of: 'block', 'page',"
- "'pos' arguments\n");
- ret = 1;
- goto out;
- }
-
- if (!(param_has_value(params, "count")))
- count = mult;
- else
- count = param_get_int(params, "count") * mult;
-
- if (!(buf = malloc(chip_params.page_size))) {
- perrorf("Cannot allocate buffer [size %x]",
- chip_params.page_size);
- ret = 1;
- goto out;
- }
-
- lseek(fd, pos, SEEK_SET);
-
- while (done < count) {
- if ((ret = read(fd, buf, chip_params.page_size)) !=
- (int32_t)chip_params.page_size) {
- perrorf("read error (read %d bytes)", ret);
- goto out;
- }
-
- if (out_fd != -1) {
- done += ret;
- if ((ret = write(out_fd, buf, chip_params.page_size)) !=
- (int32_t)chip_params.page_size) {
- perrorf("write error (written %d bytes)", ret);
- ret = 1;
- goto out;
- }
- } else {
- hexdumpoffset(buf, chip_params.page_size, done);
- done += ret;
- }
- }
-
-out:
- g_close(fd);
- if (out_fd != -1)
- close(out_fd);
- if (buf)
- free(buf);
-
- return (ret);
-}
-
diff --git a/usr.sbin/nandtool/nand_readoob.c b/usr.sbin/nandtool/nand_readoob.c
deleted file mode 100644
index 6c5bb372c3e0..000000000000
--- a/usr.sbin/nandtool/nand_readoob.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <libgeom.h>
-#include <sys/types.h>
-#include <sys/disk.h>
-#include <dev/nand/nand_dev.h>
-#include "nandtool.h"
-
-int nand_read_oob(struct cmd_param *params)
-{
- struct chip_param_io chip_params;
- struct nand_oob_rw req;
- char *dev, *out;
- int fd = -1, fd_out = -1, ret = 0;
- int page;
- uint8_t *buf = NULL;
-
- if ((page = param_get_int(params, "page")) < 0) {
- fprintf(stderr, "You must supply valid 'page' argument.\n");
- return (1);
- }
-
- if (!(dev = param_get_string(params, "dev"))) {
- fprintf(stderr, "You must supply 'dev' argument.\n");
- return (1);
- }
-
- if ((out = param_get_string(params, "out"))) {
- if ((fd_out = open(out, O_WRONLY | O_CREAT, 0666)) == -1) {
- perrorf("Cannot open %s", out);
- ret = 1;
- goto out;
- }
- }
-
- if ((fd = g_open(dev, 1)) == -1) {
- perrorf("Cannot open %s", dev);
- ret = 1;
- goto out;
- }
-
- if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
- perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
- ret = 1;
- goto out;
- }
-
- buf = malloc(chip_params.oob_size);
- if (buf == NULL) {
- perrorf("Cannot allocate %d bytes\n", chip_params.oob_size);
- ret = 1;
- goto out;
- }
-
- req.page = page;
- req.len = chip_params.oob_size;
- req.data = buf;
-
- if (ioctl(fd, NAND_IO_OOB_READ, &req) == -1) {
- perrorf("Cannot read OOB from %s", dev);
- ret = 1;
- goto out;
- }
-
- if (fd_out != -1)
- write(fd_out, buf, chip_params.oob_size);
- else
- hexdump(buf, chip_params.oob_size);
-
-out:
- close(fd_out);
-
- if (fd != -1)
- g_close(fd);
- if (buf)
- free(buf);
-
- return (ret);
-}
-
diff --git a/usr.sbin/nandtool/nand_write.c b/usr.sbin/nandtool/nand_write.c
deleted file mode 100644
index 481f1a453538..000000000000
--- a/usr.sbin/nandtool/nand_write.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <libgeom.h>
-#include <sys/disk.h>
-#include <dev/nand/nand_dev.h>
-#include "nandtool.h"
-
-int nand_write(struct cmd_param *params)
-{
- struct chip_param_io chip_params;
- char *dev, *file;
- int in_fd = -1, ret = 0, done = 0;
- int fd, block_size, mult, pos, count;
- uint8_t *buf = NULL;
-
- if (!(dev = param_get_string(params, "dev"))) {
- fprintf(stderr, "Please supply 'dev' argument.\n");
- return (1);
- }
-
- if (!(file = param_get_string(params, "in"))) {
- fprintf(stderr, "Please supply 'in' argument.\n");
- return (1);
- }
-
- if ((fd = g_open(dev, 1)) == -1) {
- perrorf("Cannot open %s", dev);
- return (1);
- }
-
- if ((in_fd = open(file, O_RDONLY)) == -1) {
- perrorf("Cannot open file %s", file);
- ret = 1;
- goto out;
- }
-
- if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
- perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
- ret = 1;
- goto out;
- }
-
- block_size = chip_params.page_size * chip_params.pages_per_block;
-
- if (param_has_value(params, "page")) {
- pos = chip_params.page_size * param_get_int(params, "page");
- mult = chip_params.page_size;
- } else if (param_has_value(params, "block")) {
- pos = block_size * param_get_int(params, "block");
- mult = block_size;
- } else if (param_has_value(params, "pos")) {
- pos = param_get_int(params, "pos");
- mult = 1;
- if (pos % chip_params.page_size) {
- fprintf(stderr, "Position must be page-size "
- "aligned!\n");
- ret = 1;
- goto out;
- }
- } else {
- fprintf(stderr, "You must specify one of: 'block', 'page',"
- "'pos' arguments\n");
- ret = 1;
- goto out;
- }
-
- if (!(param_has_value(params, "count")))
- count = mult;
- else
- count = param_get_int(params, "count") * mult;
-
- if (!(buf = malloc(chip_params.page_size))) {
- perrorf("Cannot allocate buffer [size %x]",
- chip_params.page_size);
- ret = 1;
- goto out;
- }
-
- lseek(fd, pos, SEEK_SET);
-
- while (done < count) {
- if ((ret = read(in_fd, buf, chip_params.page_size)) !=
- (int32_t)chip_params.page_size) {
- if (ret > 0) {
- /* End of file ahead, truncate here */
- break;
- } else {
- perrorf("Cannot read from %s", file);
- ret = 1;
- goto out;
- }
- }
-
- if ((ret = write(fd, buf, chip_params.page_size)) !=
- (int32_t)chip_params.page_size) {
- ret = 1;
- goto out;
- }
-
- done += ret;
- }
-
-out:
- g_close(fd);
- if (in_fd != -1)
- close(in_fd);
- if (buf)
- free(buf);
-
- return (ret);
-}
-
diff --git a/usr.sbin/nandtool/nand_writeoob.c b/usr.sbin/nandtool/nand_writeoob.c
deleted file mode 100644
index f1143b8a382a..000000000000
--- a/usr.sbin/nandtool/nand_writeoob.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <libgeom.h>
-#include <sys/disk.h>
-#include <dev/nand/nand_dev.h>
-#include "nandtool.h"
-
-int nand_write_oob(struct cmd_param *params)
-{
- struct chip_param_io chip_params;
- struct nand_oob_rw req;
- char *dev, *in;
- int fd = -1, fd_in = -1, ret = 0;
- uint8_t *buf = NULL;
- int page;
-
- if (!(dev = param_get_string(params, "dev"))) {
- fprintf(stderr, "Please supply valid 'dev' parameter.\n");
- return (1);
- }
-
- if (!(in = param_get_string(params, "in"))) {
- fprintf(stderr, "Please supply valid 'in' parameter.\n");
- return (1);
- }
-
- if ((page = param_get_int(params, "page")) < 0) {
- fprintf(stderr, "Please supply valid 'page' parameter.\n");
- return (1);
- }
-
- if ((fd = g_open(dev, 1)) == -1) {
- perrorf("Cannot open %s", dev);
- return (1);
- }
-
- if ((fd_in = open(in, O_RDONLY)) == -1) {
- perrorf("Cannot open %s", in);
- ret = 1;
- goto out;
- }
-
- if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
- perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
- ret = 1;
- goto out;
- }
-
- buf = malloc(chip_params.oob_size);
- if (buf == NULL) {
- perrorf("Cannot allocate %d bytes\n", chip_params.oob_size);
- ret = 1;
- goto out;
- }
-
- if (read(fd_in, buf, chip_params.oob_size) == -1) {
- perrorf("Cannot read from %s", in);
- ret = 1;
- goto out;
- }
-
- req.page = page;
- req.len = chip_params.oob_size;
- req.data = buf;
-
- if (ioctl(fd, NAND_IO_OOB_PROG, &req) == -1) {
- perrorf("Cannot write OOB to %s", dev);
- ret = 1;
- goto out;
- }
-
-out:
- g_close(fd);
- if (fd_in != -1)
- close(fd_in);
- if (buf)
- free(buf);
-
- return (ret);
-}
-
-
diff --git a/usr.sbin/nandtool/nandtool.8 b/usr.sbin/nandtool/nandtool.8
deleted file mode 100644
index 8f8f1deffddf..000000000000
--- a/usr.sbin/nandtool/nandtool.8
+++ /dev/null
@@ -1,184 +0,0 @@
-.\" Copyright (c) 2010 Semihalf
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd April 10, 2012
-.Dt NANDTOOL 8
-.Os
-.Sh NAME
-.Nm nandtool
-.Nd NAND devices swiss army knife
-.Sh SYNOPSIS
-.Nm
-.Ar command
-.Op Ar operands ...
-.Sh DESCRIPTION
-The
-.Nm
-utility can be used to perform various operations on
-.Xr gnand 4
-devices (read, write, erase,
-read and write OOB area and to get info about NAND flash chip).
-.Pp
-The following commands are available:
-.Bl -tag -width ".Cm of Ns = Ns Ar file"
-.It Cm read Ns
-Read pages from NAND device.
-.It Cm write Ns
-Write pages to NAND device.
-.It Cm erase Ns
-Erase blocks.
-Requires offset aligned to block granularity.
-.It Cm info Ns
-Get information about NAND chip (page size, block size, OOB area size, chip size
-and media size)
-.It Cm readoob Ns
-Read OOB area from specified page.
-.It Cm writeoob Ns
-Write OOB area bound to specified page.
-.It Cm help Ns
-Get usage info.
-.El
-.Sh COMMAND read
-The following operands are available for
-.Nm
-.Cm read
-command:
-.Bl -tag -width ".Cm of Ns = Ns Ar file"
-.It Cm dev Ns = Ns Ar <path>
-Path to a
-.Xr gnand 4
-device node, required for all operations.
-.It Cm out Ns = Ns Ar <file>
-Output file path. If not specified, page contents
-will be dumped to stdout in format similar to
-.Xr hexdump 1
-.It Cm page Ns = Ns Ar <n>
-Offset on device, expressed as page number.
-.It Cm block Ns = Ns Ar <n>
-Offset on device, expressed as block number.
-.It Cm pos Ns = Ns Ar <n>
-Offset on device, expressed in bytes (however, must be aligned
-to page granularity).
-.It Cm count Ns = Ns Ar <n>
-Count of objects (pages, blocks, bytes).
-.El
-.Sh COMMAND readoob
-The following operands are available for
-.Nm
-.Cm readoob
-command:
-.Bl -tag -width ".Cm of Ns = Ns Ar file"
-.It Cm dev Ns = Ns Ar <path>
-Path to NAND device node.
-.It Cm page Ns = Ns Ar <n>
-Offset on device, expressed as page number.
-.It Cm out Ns = Ns Ar <file>
-Output file path, optional.
-.El
-.Sh COMMAND write
-The following operands are available for
-.Nm
-.Cm write
-command:
-.Bl -tag -width ".Cm of Ns = Ns Ar file"
-.It Cm dev Ns = Ns Ar <path>
-Path to NAND device node.
-.It Cm page Ns = Ns Ar <n>
-Offset on device, expressed as page number.
-.It Cm block Ns = Ns Ar <n>
-Offset on device, expressed as block number.
-.It Cm pos Ns = Ns Ar <n>
-Offset on device, expressed in bytes (however, must be aligned
-to page granularity).
-.It Cm in Ns = Ns Ar <file>
-Input file path.
-.El
-.Sh COMMAND writeoob
-The following operands are available for
-.Nm
-.Cm writeoob
-command:
-.Bl -tag -width ".Cm of Ns = Ns Ar file"
-.It Cm dev Ns = Ns Ar <path>
-Path to NAND device node.
-.It Cm page Ns = Ns Ar <n>
-Offset on device, expressed as page number.
-.It Cm in Ns = Ns Ar <file>
-Input file path.
-.El
-.Sh COMMAND erase
-The following operands are available for
-.Nm
-.Cm erase
-command:
-.Bl -tag -width ".Cm of Ns = Ns Ar file"
-.It Cm dev Ns = Ns Ar <path>
-Path to NAND device node.
-.It Cm page Ns = Ns Ar <n>
-Offset on device, expressed as page number.
-.It Cm block Ns = Ns Ar <n>
-Offset on device, expressed as block number.
-.It Cm pos Ns = Ns Ar <n>
-Offset on device, epressed in bytes (however, must be aligned
-to block granularity).
-.It Cm count Ns = Ns Ar <n>
-Count of objects (pages, blocks, bytes).
-.El
-.Pp
-WARNING: The only required parameter for the \fBerase\fP command is
-.Ar dev .
-When no other arguments are provided the whole device is erased!
-.Sh COMMAND info
-There is only one operand available for
-.Nm
-.Cm info
-command:
-.Bl -tag -width ".Cm of Ns = Ns Ar file"
-.It Cm dev Ns = Ns Ar <path>
-Path to NAND device node.
-.El
-.Sh COMMAND help
-There is only one operand available for
-.Nm
-.Cm help
-command:
-.Bl -tag -width ".Cm of Ns = Ns Ar file"
-.It Cm topic Ns = Ns Ar <name>
-Help topic.
-.El
-.Sh EXIT STATUS
-.Ex -std
-If the supplied argument
-.Ar dev
-points to a device node other than gnand<num> or gnand.raw<num> both
-.Nm
-.Cm readoob
-and
-.Nm
-.Cm writeoob
-return error.
-.Sh SEE ALSO
-.Xr gnand 4
diff --git a/usr.sbin/nandtool/nandtool.c b/usr.sbin/nandtool/nandtool.c
deleted file mode 100644
index e87ed7342e6d..000000000000
--- a/usr.sbin/nandtool/nandtool.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <sysexits.h>
-#include <libgeom.h>
-#include "nandtool.h"
-#include "usage.h"
-
-int usage(struct cmd_param *);
-
-static const struct {
- const char *name;
- const char *usage;
- int (*handler)(struct cmd_param *);
-} commands[] = {
- { "help", nand_help_usage, usage },
- { "read", nand_read_usage, nand_read },
- { "write", nand_write_usage, nand_write },
- { "erase", nand_erase_usage, nand_erase },
- { "readoob", nand_read_oob_usage, nand_read_oob },
- { "writeoob", nand_write_oob_usage, nand_write_oob },
- { "info", nand_info_usage, nand_info },
- { NULL, NULL, NULL },
-};
-
-static char *
-_param_get_stringx(struct cmd_param *params, const char *name, int doexit)
-{
- int i;
-
- for (i = 0; params[i].name[0] != '\0'; i++) {
- if (!strcmp(params[i].name, name))
- return params[i].value;
- }
-
- if (doexit) {
- perrorf("Missing parameter %s", name);
- exit(1);
- }
- return (NULL);
-}
-
-char *
-param_get_string(struct cmd_param *params, const char *name)
-{
-
- return (_param_get_stringx(params, name, 0));
-}
-
-static int
-_param_get_intx(struct cmd_param *params, const char *name, int doexit)
-{
- int ret;
- char *str = _param_get_stringx(params, name, doexit);
-
- if (!str)
- return (-1);
-
- errno = 0;
- ret = (int)strtol(str, (char **)NULL, 10);
- if (errno) {
- if (doexit) {
- perrorf("Invalid value for parameter %s", name);
- exit(1);
- }
- return (-1);
- }
-
- return (ret);
-}
-
-int
-param_get_intx(struct cmd_param *params, const char *name)
-{
-
- return (_param_get_intx(params, name, 1));
-}
-
-int
-param_get_int(struct cmd_param *params, const char *name)
-{
-
- return (_param_get_intx(params, name, 0));
-}
-
-int
-param_get_boolean(struct cmd_param *params, const char *name)
-{
- char *str = param_get_string(params, name);
-
- if (!str)
- return (0);
-
- if (!strcmp(str, "true") || !strcmp(str, "yes"))
- return (1);
-
- return (0);
-}
-
-int
-param_has_value(struct cmd_param *params, const char *name)
-{
- int i;
-
- for (i = 0; params[i].name[0] != '\0'; i++) {
- if (!strcmp(params[i].name, name))
- return (1);
- }
-
- return (0);
-}
-
-int
-param_get_count(struct cmd_param *params)
-{
- int i;
-
- for (i = 0; params[i].name[0] != '\0'; i++);
-
- return (i);
-}
-
-void
-hexdumpoffset(uint8_t *buf, int length, int off)
-{
- int i, j;
- for (i = 0; i < length; i += 16) {
- printf("%08x: ", off + i);
-
- for (j = 0; j < 16; j++)
- printf("%02x ", buf[i+j]);
-
- printf("| ");
-
- for (j = 0; j < 16; j++) {
- printf("%c", isalnum(buf[i+j])
- ? buf[i+j]
- : '.');
- }
-
- printf("\n");
- }
-}
-
-void
-hexdump(uint8_t *buf, int length)
-{
-
- hexdumpoffset(buf, length, 0);
-}
-
-void *
-xmalloc(size_t len)
-{
- void *ret = malloc(len);
-
- if (!ret) {
- fprintf(stderr, "Cannot allocate buffer of %zd bytes. "
- "Exiting.\n", len);
- exit(EX_OSERR);
- }
-
- return (ret);
-}
-
-void
-perrorf(const char *format, ...)
-{
- va_list args;
-
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
- fprintf(stderr, ": %s\n", strerror(errno));
-}
-
-int
-usage(struct cmd_param *params)
-{
- int i;
-
- if (!params || !param_get_count(params)) {
- fprintf(stderr, "Usage: nandtool <command> [arguments...]\n");
- fprintf(stderr, "Arguments are in form 'name=value'.\n\n");
- fprintf(stderr, "Available commands:\n");
-
- for (i = 0; commands[i].name != NULL; i++)
- fprintf(stderr, "\t%s\n", commands[i].name);
-
- fprintf(stderr, "\n");
- fprintf(stderr, "For information about particular command, "
- "type:\n");
- fprintf(stderr, "'nandtool help topic=<command>'\n");
- } else if (param_has_value(params, "topic")) {
- for (i = 0; commands[i].name != NULL; i++) {
- if (!strcmp(param_get_string(params, "topic"),
- commands[i].name)) {
- fprintf(stderr, commands[i].usage, "nandtool");
- return (0);
- }
- }
-
- fprintf(stderr, "No such command\n");
- return (EX_SOFTWARE);
- } else {
- fprintf(stderr, "Wrong arguments given. Try: 'nandtool help'\n");
- }
-
- return (EX_USAGE);
-}
-
-int
-main(int argc, const char *argv[])
-{
- struct cmd_param *params;
- int i, ret, idx;
-
- if (argc < 2) {
- usage(NULL);
- return (0);
- }
-
- params = malloc(sizeof(struct cmd_param) * (argc - 1));
-
- for (i = 2, idx = 0; i < argc; i++, idx++) {
- if (sscanf(argv[i], "%63[^=]=%63s", params[idx].name,
- params[idx].value) < 2) {
- fprintf(stderr, "Syntax error in argument %d. "
- "Argument should be in form 'name=value'.\n", i);
- free(params);
- return (-1);
- }
- }
-
- params[idx].name[0] = '\0';
- params[idx].value[0] = '\0';
-
- for (i = 0; commands[i].name != NULL; i++) {
- if (!strcmp(commands[i].name, argv[1])) {
- ret = commands[i].handler(params);
- free(params);
- return (ret);
- }
- }
-
- free(params);
- fprintf(stderr, "Unknown command. Try '%s help'\n", argv[0]);
-
- return (-1);
-}
-
diff --git a/usr.sbin/nandtool/nandtool.h b/usr.sbin/nandtool/nandtool.h
deleted file mode 100644
index c0dd1c095444..000000000000
--- a/usr.sbin/nandtool/nandtool.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef __UTILS_H
-#define __UTILS_H
-
-struct cmd_param
-{
- char name[64];
- char value[64];
-};
-
-char *param_get_string(struct cmd_param *, const char *);
-int param_get_int(struct cmd_param *, const char *);
-int param_get_intx(struct cmd_param *, const char *);
-int param_get_boolean(struct cmd_param *, const char *);
-int param_has_value(struct cmd_param *, const char *);
-int param_get_count(struct cmd_param *);
-void perrorf(const char *, ...);
-void hexdumpoffset(uint8_t *, int, int);
-void hexdump(uint8_t *, int);
-void *xmalloc(size_t);
-
-/* Command handlers */
-int nand_read(struct cmd_param *);
-int nand_write(struct cmd_param *);
-int nand_read_oob(struct cmd_param *);
-int nand_write_oob(struct cmd_param *);
-int nand_erase(struct cmd_param *);
-int nand_info(struct cmd_param *);
-
-#endif /* __UTILS_H */
diff --git a/usr.sbin/nandtool/usage.h b/usr.sbin/nandtool/usage.h
deleted file mode 100644
index 0dbb70a2c99d..000000000000
--- a/usr.sbin/nandtool/usage.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2010-2012 Semihalf.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef __USAGE_H
-#define __USAGE_H
-
-static const char nand_help_usage[] =
- "Usage: %s help topic=<cmd>\n"
- "\n"
- "Arguments:\n"
- "\tcmd\t- [help|read|write|erase|readoob|writeoob|info]\n"
- "\n";
-
-static const char nand_read_usage[] =
- "Usage: %s read dev=<gnand_device> (block|page|pos)=n [count=n]\n"
- "\n"
- "Arguments:\n"
- "\tdev\t- path to gnand device node\n"
- "\tblock\t- starting block or\n"
- "\tpage\t- starting page or\n"
- "\tpos\t- starting position (in bytes, must be page-aligned)\n"
- "\tout\t- output file (hexdump to stdout if not supplied)\n"
- "\n"
- "Note that you can only specify only one of: 'block', 'page', 'pos'\n"
- "parameters at once. 'count' parameter is meaningful in terms of used\n"
- "unit (page, block or byte).\n";
-
-static const char nand_write_usage[] =
- "Usage: %s write dev=<gnand_device> in=<file> (block|page|pos)=n [count=n]\n"
- "\n"
- "Arguments:\n"
- "\tdev\t- path to gnand device node\n"
- "\tin\t- path to input file which be writed to gnand\n"
- "\tblock\t- starting block or\n"
- "\tpage\t- starting page or\n"
- "\tpos\t- starting position (in bytes, must be page-aligned)\n"
- "\tcount\t- byte/page/block count\n"
- "\n"
- "";
-
-static const char nand_erase_usage[] =
- "Usage: %s erase dev=<gnand_device> (block|page|pos)=n [count=n]\n"
- "\n"
- "Arguments:\n"
- "\tdev\t- path to gnand device node\n"
- "\tblock\t- starting block or\n"
- "\tpage\t- starting page or\n"
- "\tpos\t- starting position (in bytes, muse be block-aligned)\n"
- "\tcount\t- byte/page/block count\n"
- "\n"
- "NOTE: position and count for erase operation MUST be block-aligned\n";
-
-static const char nand_read_oob_usage[] =
- "Usage: %s readoob dev=<gnand_device> page=n [out=file] [count=n]\n"
- "\n"
- "Arguments:\n"
- "\tdev\t- path to gnand device node\n"
- "\tpage\t- page (page) number\n"
- "\tout\t- outut file (hexdump to stdout if not supplied)\n"
- "\tcount\t- page count (default is 1)\n"
- "\n"
- "If you supply count parameter with value other than 1, data will be\n"
- "read from subsequent page's OOB areas\n";
-
-static const char nand_write_oob_usage[] =
- "Usage: %s writeoob dev=<gnand_device> in=<file> page=n [count=n]\n"
- "\n"
- "\tdev\t- path to gnand device node\n"
- "\tin\t- path to file containing data which will be written\n"
- "\tpage\t- page (page) number\n"
- "\n"
- "If you supply count parameter with value other than 1, data will be\n"
- "written to subsequent page's OOB areas\n";
-
-static const char nand_info_usage[] =
- "Usage: %s info dev=<gnand_device>\n"
- "\n"
- "Arguments:\n"
- "\tdev\t- path to gnand device node\n";
-
-static const char nand_stats_usage[] =
- "Usage: %s stats dev=<gnand_device> (page|block)=<n>\n"
- "\n"
- "Arguments:\n"
- "\tdev\t- path to gnand device node\n";
-
-#endif /* __USAGE_H */
diff --git a/usr.sbin/usbdump/usbdump.c b/usr.sbin/usbdump/usbdump.c
index ef4476f55d8c..a38d08a252af 100644
--- a/usr.sbin/usbdump/usbdump.c
+++ b/usr.sbin/usbdump/usbdump.c
@@ -149,7 +149,9 @@ static const char *errstr_table[USB_ERR_MAX] = {
[USB_ERR_NOT_LOCKED] = "NOT_LOCKED",
};
-static const char *xfertype_table[4] = {
+#define USB_XFERTYPE_MAX 4
+
+static const char *xfertype_table[USB_XFERTYPE_MAX] = {
[UE_CONTROL] = "CTRL",
[UE_ISOCHRONOUS] = "ISOC",
[UE_BULK] = "BULK",
@@ -320,6 +322,15 @@ usb_speedstr(uint8_t speed)
return (speed_table[speed]);
}
+static const char *
+usb_xferstr(uint8_t type)
+{
+ if (type >= USB_XFERTYPE_MAX || xfertype_table[type] == NULL)
+ return ("UNKN");
+ else
+ return (xfertype_table[type]);
+}
+
static void
print_flags(uint32_t flags)
{
@@ -496,7 +507,7 @@ print_apacket(const struct header_32 *hdr, const uint8_t *ptr, int ptr_len)
(int)len, buf, tv.tv_usec,
(int)up->up_busunit, (int)up->up_address,
(up->up_type == USBPF_XFERTAP_SUBMIT) ? "SUBM" : "DONE",
- xfertype_table[up->up_xfertype],
+ usb_xferstr(up->up_xfertype),
(unsigned int)up->up_endpoint,
usb_speedstr(up->up_speed),
(int)up->up_frames,