summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2010-05-06 17:37:23 +0000
committermckusick <mckusick@FreeBSD.org>2010-05-06 17:37:23 +0000
commitb25e55dcc52d6203a9ae995ca470a66b6483f71d (patch)
tree781f2c991a11a3806fdb0891b7a615cb77ebe3ab
parent3a0f5972a0de87aebef1af257922515700da4217 (diff)
parentf3856c6cf2fb115757967b7e32bdeb21bd27d1ee (diff)
downloadFreeBSD-src-b25e55dcc52d6203a9ae995ca470a66b6483f71d.zip
FreeBSD-src-b25e55dcc52d6203a9ae995ca470a66b6483f71d.tar.gz
Final update to current version of head in preparation for reintegration.
-rw-r--r--UPDATING8
-rw-r--r--bin/sh/eval.c4
-rw-r--r--bin/sh/var.c75
-rw-r--r--bin/sh/var.h2
-rw-r--r--cddl/contrib/opensolaris/cmd/zfs/zfs_main.c2
-rw-r--r--cddl/contrib/opensolaris/cmd/zpool/zpool_main.c12
-rw-r--r--cddl/contrib/opensolaris/cmd/ztest/ztest.c2
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h1
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c15
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c9
-rw-r--r--contrib/telnet/telnet/commands.c3
-rw-r--r--contrib/telnet/telnet/externs.h1
-rw-r--r--contrib/telnet/telnet/network.c2
-rw-r--r--contrib/telnet/telnet/sys_bsd.c10
-rw-r--r--contrib/telnet/telnet/telnet.c1
-rw-r--r--contrib/telnet/telnet/terminal.c16
-rw-r--r--contrib/tzcode/zic/private.h2
-rw-r--r--crypto/openssh/ChangeLog118
-rw-r--r--crypto/openssh/README4
-rw-r--r--crypto/openssh/auth-options.c6
-rw-r--r--crypto/openssh/auth2-pubkey.c31
-rw-r--r--crypto/openssh/channels.c6
-rw-r--r--crypto/openssh/clientloop.c3
-rw-r--r--crypto/openssh/config.h15
-rw-r--r--crypto/openssh/config.h.in12
-rw-r--r--crypto/openssh/defines.h2
-rw-r--r--crypto/openssh/key.c15
-rw-r--r--crypto/openssh/key.h3
-rw-r--r--crypto/openssh/loginrec.c9
-rw-r--r--crypto/openssh/logintest.c2
-rw-r--r--crypto/openssh/openbsd-compat/bsd-arc4random.c4
-rw-r--r--crypto/openssh/servconf.c19
-rw-r--r--crypto/openssh/session.c8
-rw-r--r--crypto/openssh/ssh-keygen.143
-rw-r--r--crypto/openssh/ssh-keygen.c5
-rw-r--r--crypto/openssh/ssh-pkcs11-helper.c4
-rw-r--r--crypto/openssh/ssh.19
-rw-r--r--crypto/openssh/ssh_config2
-rw-r--r--crypto/openssh/ssh_config.512
-rw-r--r--crypto/openssh/sshd_config2
-rw-r--r--crypto/openssh/sshd_config.52
-rw-r--r--crypto/openssh/version.h6
-rw-r--r--etc/network.subr2
-rwxr-xr-xetc/rc.d/named14
-rw-r--r--gnu/usr.bin/groff/tmac/mdoc.local1
-rw-r--r--lib/libc/sys/getrusage.212
-rw-r--r--lib/libpam/modules/pam_krb5/pam_krb5.86
-rw-r--r--lib/libpam/modules/pam_krb5/pam_krb5.c53
-rw-r--r--lib/libpmc/libpmc.c9
-rw-r--r--lib/libufs/cgroup.c2
-rw-r--r--libexec/tftpd/Makefile13
-rw-r--r--libexec/tftpd/tftp-file.c257
-rw-r--r--libexec/tftpd/tftp-file.h37
-rw-r--r--libexec/tftpd/tftp-io.c478
-rw-r--r--libexec/tftpd/tftp-io.h47
-rw-r--r--libexec/tftpd/tftp-options.c390
-rw-r--r--libexec/tftpd/tftp-options.h62
-rw-r--r--libexec/tftpd/tftp-transfer.c318
-rw-r--r--libexec/tftpd/tftp-transfer.h31
-rw-r--r--libexec/tftpd/tftp-utils.c320
-rw-r--r--libexec/tftpd/tftp-utils.h124
-rw-r--r--libexec/tftpd/tftpd.817
-rw-r--r--libexec/tftpd/tftpd.c826
-rw-r--r--sbin/camcontrol/camcontrol.88
-rw-r--r--sbin/camcontrol/camcontrol.c20
-rw-r--r--sbin/hastd/hast.conf.57
-rw-r--r--sbin/hastd/hast.h3
-rw-r--r--sbin/hastd/hastd.c57
-rw-r--r--sbin/hastd/metadata.c2
-rw-r--r--sbin/hastd/parse.y32
-rw-r--r--sbin/hastd/primary.c10
-rw-r--r--sbin/hastd/proto.c26
-rw-r--r--sbin/hastd/proto.h1
-rw-r--r--sbin/hastd/proto_common.c4
-rw-r--r--sbin/hastd/proto_tcp4.c78
-rw-r--r--sbin/hastd/secondary.c6
-rw-r--r--sbin/hastd/token.l1
-rw-r--r--sbin/ifconfig/ifconfig.86
-rw-r--r--sbin/ifconfig/ifieee80211.c2
-rw-r--r--sbin/tunefs/tunefs.c15
-rw-r--r--share/man/man4/Makefile1
-rw-r--r--share/man/man4/bwn.42
-rw-r--r--share/man/man4/cas.45
-rw-r--r--share/man/man4/msk.44
-rw-r--r--share/man/man4/mvs.4176
-rw-r--r--share/man/man4/ng_bridge.410
-rw-r--r--share/man/man4/ng_hub.415
-rw-r--r--share/man/man4/sge.410
-rw-r--r--share/man/man4/vlan.42
-rw-r--r--share/man/man9/ieee80211.96
-rw-r--r--share/man/man9/ieee80211_node.94
-rw-r--r--sys/amd64/amd64/exception.S79
-rw-r--r--sys/amd64/amd64/identcpu.c4
-rw-r--r--sys/amd64/amd64/io.c40
-rw-r--r--sys/amd64/amd64/pmap.c17
-rw-r--r--sys/amd64/amd64/trap.c86
-rw-r--r--sys/amd64/include/iodev.h21
-rw-r--r--sys/amd64/include/pmap.h2
-rw-r--r--sys/amd64/include/proc.h4
-rw-r--r--sys/amd64/include/specialreg.h2
-rw-r--r--sys/amd64/include/vmparam.h4
-rw-r--r--sys/amd64/include/xen/xenfunc.h31
-rw-r--r--sys/amd64/include/xen/xenvar.h26
-rw-r--r--sys/arm/arm/cpufunc.c99
-rw-r--r--sys/arm/arm/cpufunc_asm_fa526.S4
-rw-r--r--sys/arm/arm/elf_trampoline.c2
-rw-r--r--sys/arm/arm/identcpu.c4
-rw-r--r--sys/arm/arm/pmap.c13
-rw-r--r--sys/arm/at91/if_ate.c4
-rw-r--r--sys/arm/include/cpuconf.h6
-rw-r--r--sys/arm/include/cpufunc.h12
-rw-r--r--sys/arm/include/pmap.h2
-rw-r--r--sys/arm/include/proc.h2
-rw-r--r--sys/arm/mv/files.mv1
-rw-r--r--sys/arm/xscale/ixp425/if_npe.c2
-rw-r--r--sys/boot/forth/loader.conf8
-rw-r--r--sys/boot/sparc64/loader/main.c8
-rw-r--r--sys/cam/ata/ata_pmp.c20
-rw-r--r--sys/cam/ata/ata_xpt.c155
-rw-r--r--sys/cam/cam_ccb.h9
-rw-r--r--sys/cam/cam_xpt.c31
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c6
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c28
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c33
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c21
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c9
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_byteswap.c37
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c14
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c43
-rw-r--r--sys/compat/linux/linux_ioctl.c31
-rw-r--r--sys/compat/x86bios/x86bios.c140
-rw-r--r--sys/conf/NOTES11
-rw-r--r--sys/conf/files5
-rw-r--r--sys/conf/files.sparc641
-rw-r--r--sys/conf/kmod.mk2
-rw-r--r--sys/conf/options1
-rw-r--r--sys/conf/options.arm1
-rwxr-xr-xsys/contrib/dev/acpica/acpica_prep.sh2
-rw-r--r--sys/contrib/dev/acpica/changes.txt66
-rw-r--r--sys/contrib/dev/acpica/common/adisasm.c6
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompile.c6
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompiler.h100
-rw-r--r--sys/contrib/dev/acpica/compiler/asldefine.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslfiles.c30
-rw-r--r--sys/contrib/dev/acpica/compiler/aslglobal.h3
-rw-r--r--sys/contrib/dev/acpica/compiler/asllisting.c247
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmain.c31
-rw-r--r--sys/contrib/dev/acpica/compiler/aslpredef.c78
-rw-r--r--sys/contrib/dev/acpica/compiler/aslresource.c294
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype1.c562
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype1i.c668
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2.c2394
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2d.c814
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2e.c646
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2q.c793
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2w.c774
-rw-r--r--sys/contrib/dev/acpica/compiler/asltypes.h22
-rw-r--r--sys/contrib/dev/acpica/debugger/dbcmds.c2
-rw-r--r--sys/contrib/dev/acpica/debugger/dbdisply.c14
-rw-r--r--sys/contrib/dev/acpica/events/evgpe.c2
-rw-r--r--sys/contrib/dev/acpica/events/evgpeblk.c774
-rw-r--r--sys/contrib/dev/acpica/events/evgpeinit.c763
-rw-r--r--sys/contrib/dev/acpica/events/evgpeutil.c452
-rw-r--r--sys/contrib/dev/acpica/executer/exconfig.c21
-rw-r--r--sys/contrib/dev/acpica/executer/exoparg1.c2
-rw-r--r--sys/contrib/dev/acpica/executer/exsystem.c8
-rw-r--r--sys/contrib/dev/acpica/include/acevents.h74
-rw-r--r--sys/contrib/dev/acpica/include/acglobal.h7
-rw-r--r--sys/contrib/dev/acpica/include/acinterp.h2
-rw-r--r--sys/contrib/dev/acpica/include/aclocal.h16
-rw-r--r--sys/contrib/dev/acpica/include/acpiosxf.h4
-rw-r--r--sys/contrib/dev/acpica/include/acpixf.h30
-rw-r--r--sys/contrib/dev/acpica/include/actypes.h2
-rw-r--r--sys/contrib/dev/acpica/include/amlresrc.h6
-rw-r--r--sys/contrib/dev/acpica/osunixxf.c4
-rw-r--r--sys/contrib/dev/acpica/tables/tbfind.c2
-rw-r--r--sys/contrib/dev/acpica/tables/tbinstal.c52
-rw-r--r--sys/contrib/dev/acpica/tables/tbutils.c15
-rw-r--r--sys/contrib/dev/acpica/tables/tbxface.c20
-rw-r--r--sys/contrib/dev/acpica/utilities/utcopy.c20
-rw-r--r--sys/contrib/dev/acpica/utilities/utglobal.c4
-rw-r--r--sys/contrib/dev/acpica/utilities/uttrack.c108
-rw-r--r--sys/contrib/ipfilter/netinet/ip_auth.c5
-rw-r--r--sys/dev/acpica/Osd/OsdHardware.c25
-rw-r--r--sys/dev/ae/if_ae.c2
-rw-r--r--sys/dev/agp/agp.c8
-rw-r--r--sys/dev/agp/agp_i810.c6
-rw-r--r--sys/dev/ahci/ahci.c236
-rw-r--r--sys/dev/ahci/ahci.h1
-rw-r--r--sys/dev/ale/if_ale.c37
-rw-r--r--sys/dev/an/if_an.c4
-rw-r--r--sys/dev/ata/ata-all.c65
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_reset.c8
-rw-r--r--sys/dev/ath/if_ath.c4
-rw-r--r--sys/dev/atkbdc/atkbdc.c76
-rw-r--r--sys/dev/atkbdc/atkbdc_ebus.c1
-rw-r--r--sys/dev/atkbdc/atkbdc_isa.c7
-rw-r--r--sys/dev/atkbdc/atkbdcreg.h1
-rw-r--r--sys/dev/bce/if_bce.c1131
-rw-r--r--sys/dev/bce/if_bcereg.h622
-rw-r--r--sys/dev/bwi/if_bwi.c4
-rw-r--r--sys/dev/bwn/if_bwn.c4
-rw-r--r--sys/dev/cas/if_cas.c232
-rw-r--r--sys/dev/cas/if_casreg.h12
-rw-r--r--sys/dev/ce/if_ce.c8
-rw-r--r--sys/dev/ciss/ciss.c2
-rw-r--r--sys/dev/cm/smc90cx6.c2
-rw-r--r--sys/dev/cp/if_cp.c4
-rw-r--r--sys/dev/cs/if_cs.c2
-rw-r--r--sys/dev/ctau/if_ct.c4
-rw-r--r--sys/dev/cx/if_cx.c4
-rw-r--r--sys/dev/cxgb/cxgb_ioctl.h29
-rw-r--r--sys/dev/cxgb/cxgb_main.c277
-rw-r--r--sys/dev/cxgb/sys/mvec.h42
-rw-r--r--sys/dev/cxgb/sys/uipc_mvec.c44
-rw-r--r--sys/dev/drm/via_dmablit.c8
-rw-r--r--sys/dev/drm/via_video.c2
-rw-r--r--sys/dev/e1000/if_em.c27
-rw-r--r--sys/dev/ed/if_ed.c4
-rw-r--r--sys/dev/ep/if_ep.c4
-rw-r--r--sys/dev/esp/esp_sbus.c4
-rw-r--r--sys/dev/ex/if_ex.c2
-rw-r--r--sys/dev/fe/if_fe.c2
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c18
-rw-r--r--sys/dev/ie/if_ie.c2
-rw-r--r--sys/dev/iicbus/if_ic.c2
-rw-r--r--sys/dev/io/iodev.c146
-rw-r--r--sys/dev/io/iodev.h44
-rw-r--r--sys/dev/ipw/if_ipw.c4
-rw-r--r--sys/dev/isp/isp_pci.c9
-rw-r--r--sys/dev/isp/isp_sbus.c8
-rw-r--r--sys/dev/iwi/if_iwi.c4
-rw-r--r--sys/dev/iwn/if_iwn.c4
-rw-r--r--sys/dev/le/lance.c4
-rw-r--r--sys/dev/malo/if_malo.c4
-rw-r--r--sys/dev/md/md.c2
-rw-r--r--sys/dev/mii/brgphy.c10
-rw-r--r--sys/dev/mii/e1000phy.c2
-rw-r--r--sys/dev/mii/miidevs1
-rw-r--r--sys/dev/mpt/mpt.c2
-rw-r--r--sys/dev/mpt/mpt.h10
-rw-r--r--sys/dev/mpt/mpt_cam.c9
-rw-r--r--sys/dev/mpt/mpt_pci.c5
-rw-r--r--sys/dev/msk/if_msk.c48
-rw-r--r--sys/dev/msk/if_mskreg.h12
-rw-r--r--sys/dev/mvs/mvs.c2173
-rw-r--r--sys/dev/mvs/mvs.h650
-rw-r--r--sys/dev/mvs/mvs_if.m34
-rw-r--r--sys/dev/mvs/mvs_pci.c507
-rw-r--r--sys/dev/mvs/mvs_soc.c437
-rw-r--r--sys/dev/mwl/if_mwl.c4
-rw-r--r--sys/dev/my/if_my.c4
-rw-r--r--sys/dev/nxge/if_nxge.c2
-rw-r--r--sys/dev/pdq/pdq_ifsubr.c2
-rw-r--r--sys/dev/ppbus/if_plip.c2
-rw-r--r--sys/dev/quicc/quicc_bfe.h1
-rw-r--r--sys/dev/ral/rt2560.c4
-rw-r--r--sys/dev/ral/rt2661.c4
-rw-r--r--sys/dev/sbni/if_sbni.c2
-rw-r--r--sys/dev/sge/if_sge.c355
-rw-r--r--sys/dev/sge/if_sgereg.h32
-rw-r--r--sys/dev/siis/siis.c79
-rw-r--r--sys/dev/siis/siis.h1
-rw-r--r--sys/dev/smc/if_smc.c2
-rw-r--r--sys/dev/sn/if_sn.c4
-rw-r--r--sys/dev/snc/dp83932.c2
-rw-r--r--sys/dev/sound/pcm/buffer.c24
-rw-r--r--sys/dev/sound/pcm/buffer.h12
-rw-r--r--sys/dev/sym/sym_hipd.c13
-rw-r--r--sys/dev/ti/if_ti.c2
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c2
-rw-r--r--sys/dev/usb/net/uhso.c4
-rw-r--r--sys/dev/usb/net/usb_ethernet.c4
-rw-r--r--sys/dev/usb/wlan/if_rum.c4
-rw-r--r--sys/dev/usb/wlan/if_run.c4
-rw-r--r--sys/dev/usb/wlan/if_uath.c4
-rw-r--r--sys/dev/usb/wlan/if_upgt.c2
-rw-r--r--sys/dev/usb/wlan/if_ural.c4
-rw-r--r--sys/dev/usb/wlan/if_urtw.c4
-rw-r--r--sys/dev/usb/wlan/if_zyd.c2
-rw-r--r--sys/dev/vx/if_vx.c2
-rw-r--r--sys/dev/wi/if_wi.c4
-rw-r--r--sys/dev/wl/if_wl.c2
-rw-r--r--sys/dev/wpi/if_wpi.c4
-rw-r--r--sys/dev/xe/if_xe.c2
-rw-r--r--sys/dev/xen/netfront/netfront.c32
-rw-r--r--sys/fs/ext2fs/ext2_readwrite.c14
-rw-r--r--sys/fs/ext2fs/ext2_vnops.c3
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c15
-rw-r--r--sys/fs/nfsclient/nfs_clbio.c42
-rw-r--r--sys/fs/nfsclient/nfs_clnode.c3
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c4
-rw-r--r--sys/fs/nwfs/nwfs_io.c34
-rw-r--r--sys/fs/smbfs/smbfs_io.c44
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c49
-rw-r--r--sys/geom/geom.h3
-rw-r--r--sys/geom/geom_subr.c98
-rw-r--r--sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c12
-rw-r--r--sys/i386/i386/identcpu.c4
-rw-r--r--sys/i386/i386/io.c40
-rw-r--r--sys/i386/i386/pmap.c11
-rw-r--r--sys/i386/include/iodev.h21
-rw-r--r--sys/i386/include/pmap.h3
-rw-r--r--sys/i386/include/proc.h2
-rw-r--r--sys/i386/include/specialreg.h2
-rw-r--r--sys/i386/include/xen/xenfunc.h29
-rw-r--r--sys/i386/include/xen/xenvar.h27
-rw-r--r--sys/i386/xen/pmap.c124
-rw-r--r--sys/ia64/ia64/iodev_machdep.c104
-rw-r--r--sys/ia64/ia64/pmap.c24
-rw-r--r--sys/ia64/include/iodev.h33
-rw-r--r--sys/ia64/include/pmap.h2
-rw-r--r--sys/ia64/include/proc.h4
-rw-r--r--sys/kern/imgact_elf.c11
-rw-r--r--sys/kern/kern_exec.c10
-rw-r--r--sys/kern/kern_gzio.c8
-rw-r--r--sys/kern/kern_ntptime.c119
-rw-r--r--sys/kern/kern_proc.c10
-rw-r--r--sys/kern/kern_resource.c40
-rw-r--r--sys/kern/kern_sig.c22
-rw-r--r--sys/kern/kern_thread.c5
-rw-r--r--sys/kern/subr_bufring.c45
-rw-r--r--sys/kern/subr_taskqueue.c11
-rw-r--r--sys/kern/subr_uio.c2
-rw-r--r--sys/kern/subr_witness.c9
-rw-r--r--sys/kern/sys_pipe.c12
-rw-r--r--sys/kern/sys_process.c8
-rw-r--r--sys/kern/uipc_cow.c11
-rw-r--r--sys/kern/uipc_mbuf.c3
-rw-r--r--sys/kern/uipc_syscalls.c6
-rw-r--r--sys/kern/vfs_bio.c49
-rw-r--r--sys/kern/vfs_vnops.c19
-rw-r--r--sys/mips/adm5120/if_admsw.c4
-rw-r--r--sys/mips/atheros/if_arge.c4
-rw-r--r--sys/mips/cavium/uart_dev_oct16550.c5
-rw-r--r--sys/mips/conf/AR71XX11
-rw-r--r--sys/mips/include/pmap.h2
-rw-r--r--sys/mips/include/proc.h4
-rw-r--r--sys/mips/mips/db_trace.c2
-rw-r--r--sys/mips/mips/pmap.c25
-rw-r--r--sys/modules/Makefile1
-rw-r--r--sys/modules/acpi/acpi/Makefile4
-rw-r--r--sys/modules/mvs/Makefile10
-rw-r--r--sys/modules/usb/usb/Makefile2
-rw-r--r--sys/net/bpf.c11
-rw-r--r--sys/net/bpf_zerocopy.c6
-rw-r--r--sys/net/flowtable.c2
-rw-r--r--sys/net/if.c10
-rw-r--r--sys/net/if_ef.c2
-rw-r--r--sys/net/if_gif.c22
-rw-r--r--sys/net/if_gif.h4
-rw-r--r--sys/net/if_gre.c2
-rw-r--r--sys/net/if_stf.c2
-rw-r--r--sys/net/route.c12
-rw-r--r--sys/net80211/ieee80211.c4
-rw-r--r--sys/net80211/ieee80211_amrr.c20
-rw-r--r--sys/net80211/ieee80211_ht.h3
-rw-r--r--sys/net80211/ieee80211_node.c2
-rw-r--r--sys/net80211/ieee80211_rssadapt.c18
-rw-r--r--sys/net80211/ieee80211_var.h3
-rw-r--r--sys/netgraph/ng_base.c52
-rw-r--r--sys/netgraph/ng_bridge.c18
-rw-r--r--sys/netgraph/ng_bridge.h1
-rw-r--r--sys/netgraph/ng_eiface.c2
-rw-r--r--sys/netgraph/ng_fec.c2
-rw-r--r--sys/netgraph/ng_hub.c74
-rw-r--r--sys/netgraph/ng_hub.h5
-rw-r--r--sys/netgraph/ng_iface.c4
-rw-r--r--sys/netgraph/ng_pipe.c19
-rw-r--r--sys/netgraph/ng_tty.c2
-rw-r--r--sys/netinet/icmp6.h1
-rw-r--r--sys/netinet/if_ether.c10
-rw-r--r--sys/netinet/igmp.c17
-rw-r--r--sys/netinet/in.c11
-rw-r--r--sys/netinet/in_gif.c2
-rw-r--r--sys/netinet/in_proto.c1
-rw-r--r--sys/netinet/in_rmx.c21
-rw-r--r--sys/netinet/ip_icmp.c59
-rw-r--r--sys/netinet/ip_icmp.h1
-rw-r--r--sys/netinet/ip_input.c72
-rw-r--r--sys/netinet/ip_var.h13
-rw-r--r--sys/netinet/raw_ip.c23
-rw-r--r--sys/netinet/tcp_hostcache.c4
-rw-r--r--sys/netinet/tcp_input.c39
-rw-r--r--sys/netinet/tcp_output.c21
-rw-r--r--sys/netinet/tcp_reass.c21
-rw-r--r--sys/netinet/tcp_sack.c17
-rw-r--r--sys/netinet/tcp_subr.c90
-rw-r--r--sys/netinet/tcp_syncache.c19
-rw-r--r--sys/netinet/tcp_timewait.c8
-rw-r--r--sys/netinet/tcp_var.h56
-rw-r--r--sys/netinet/udp_usrreq.c7
-rw-r--r--sys/netinet/udp_var.h10
-rw-r--r--sys/netinet6/frag6.c5
-rw-r--r--sys/netinet6/icmp6.c21
-rw-r--r--sys/netinet6/in6.c25
-rw-r--r--sys/netinet6/in6_gif.c9
-rw-r--r--sys/netinet6/in6_ifattach.c11
-rw-r--r--sys/netinet6/in6_proto.c84
-rw-r--r--sys/netinet6/in6_rmx.c23
-rw-r--r--sys/netinet6/in6_src.c32
-rw-r--r--sys/netinet6/in6_var.h9
-rw-r--r--sys/netinet6/ip6_input.c107
-rw-r--r--sys/netinet6/ip6_mroute.c19
-rw-r--r--sys/netinet6/ip6_var.h53
-rw-r--r--sys/netinet6/nd6.c77
-rw-r--r--sys/netinet6/nd6.h9
-rw-r--r--sys/netinet6/nd6_nbr.c8
-rw-r--r--sys/netinet6/nd6_rtr.c12
-rw-r--r--sys/netinet6/raw_ip6.c6
-rw-r--r--sys/netinet6/scope6.c12
-rw-r--r--sys/netipsec/ah_var.h5
-rw-r--r--sys/netipsec/esp_var.h3
-rw-r--r--sys/netipsec/ipcomp_var.h3
-rw-r--r--sys/netipsec/ipip_var.h3
-rw-r--r--sys/netipsec/ipsec.c1
-rw-r--r--sys/netipsec/ipsec.h44
-rw-r--r--sys/netipsec/ipsec6.h11
-rw-r--r--sys/netipsec/key.c45
-rw-r--r--sys/netipsec/xform_esp.c3
-rw-r--r--sys/nfsclient/nfs_bio.c41
-rw-r--r--sys/pc98/pc98/machdep.c12
-rw-r--r--sys/pci/if_rl.c4
-rw-r--r--sys/powerpc/aim/mmu_oea.c10
-rw-r--r--sys/powerpc/aim/mmu_oea64.c9
-rw-r--r--sys/powerpc/booke/pmap.c27
-rw-r--r--sys/powerpc/include/pmap.h2
-rw-r--r--sys/powerpc/include/proc.h2
-rw-r--r--sys/security/audit/audit_bsm.c1
-rw-r--r--sys/sparc64/include/asi.h7
-rw-r--r--sys/sparc64/include/cache.h4
-rw-r--r--sys/sparc64/include/mcntl.h62
-rw-r--r--sys/sparc64/include/pmap.h2
-rw-r--r--sys/sparc64/include/proc.h2
-rw-r--r--sys/sparc64/sparc64/cache.c20
-rw-r--r--sys/sparc64/sparc64/cheetah.c15
-rw-r--r--sys/sparc64/sparc64/identcpu.c24
-rw-r--r--sys/sparc64/sparc64/interrupt.S7
-rw-r--r--sys/sparc64/sparc64/machdep.c6
-rw-r--r--sys/sparc64/sparc64/mp_locore.S22
-rw-r--r--sys/sparc64/sparc64/mp_machdep.c9
-rw-r--r--sys/sparc64/sparc64/pmap.c38
-rw-r--r--sys/sparc64/sparc64/tick.c9
-rw-r--r--sys/sparc64/sparc64/zeus.c65
-rw-r--r--sys/sun4v/include/pmap.h2
-rw-r--r--sys/sun4v/include/proc.h2
-rw-r--r--sys/sun4v/sun4v/pmap.c23
-rw-r--r--sys/sys/_task.h16
-rw-r--r--sys/sys/buf_ring.h42
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/proc.h44
-rw-r--r--sys/sys/resource.h1
-rw-r--r--sys/sys/resourcevar.h2
-rw-r--r--sys/sys/taskqueue.h1
-rw-r--r--sys/sys/vnode.h1
-rw-r--r--sys/ufs/ffs/ffs_softdep.c174
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c4
-rw-r--r--sys/ufs/ffs/ffs_vnops.c23
-rw-r--r--sys/vm/device_pager.c19
-rw-r--r--sys/vm/phys_pager.c8
-rw-r--r--sys/vm/sg_pager.c9
-rw-r--r--sys/vm/swap_pager.c42
-rw-r--r--sys/vm/uma_core.c12
-rw-r--r--sys/vm/vm_contig.c19
-rw-r--r--sys/vm/vm_fault.c79
-rw-r--r--sys/vm/vm_glue.c52
-rw-r--r--sys/vm/vm_kern.c2
-rw-r--r--sys/vm/vm_map.c6
-rw-r--r--sys/vm/vm_mmap.c2
-rw-r--r--sys/vm/vm_object.c104
-rw-r--r--sys/vm/vm_page.c149
-rw-r--r--sys/vm/vm_page.h46
-rw-r--r--sys/vm/vm_pageout.c114
-rw-r--r--sys/vm/vm_param.h8
-rw-r--r--sys/vm/vnode_pager.c85
-rw-r--r--tools/regression/bin/sh/builtins/locale1.0133
-rw-r--r--tools/tools/nanobsd/nanobsd.sh4
-rw-r--r--usr.bin/chpass/Makefile2
-rw-r--r--usr.bin/find/find.c9
-rw-r--r--usr.bin/find/function.c8
-rw-r--r--usr.bin/find/ls.c8
-rw-r--r--usr.bin/find/main.c8
-rw-r--r--usr.bin/find/misc.c9
-rw-r--r--usr.bin/find/operator.c8
-rw-r--r--usr.bin/find/option.c8
-rw-r--r--usr.bin/gzip/gzip.16
-rw-r--r--usr.bin/gzip/gzip.c2
-rw-r--r--usr.bin/pathchk/pathchk.116
-rw-r--r--usr.bin/pathchk/pathchk.c18
-rw-r--r--usr.bin/script/script.c24
-rw-r--r--usr.bin/tftp/Makefile6
-rw-r--r--usr.bin/tftp/main.c656
-rw-r--r--usr.bin/tftp/tftp.160
-rw-r--r--usr.bin/tftp/tftp.c576
-rw-r--r--usr.bin/tftp/tftp.h42
-rw-r--r--usr.sbin/acpi/acpidb/Makefile5
-rw-r--r--usr.sbin/acpi/iasl/Makefile6
-rw-r--r--usr.sbin/config/config.h1
-rw-r--r--usr.sbin/config/configvers.h2
-rw-r--r--usr.sbin/config/main.c58
-rw-r--r--usr.sbin/config/mkmakefile.c45
-rw-r--r--usr.sbin/config/mkoptions.c168
-rw-r--r--usr.sbin/cxgbtool/cxgbtool.c186
-rw-r--r--usr.sbin/jail/jail.82
-rwxr-xr-xusr.sbin/mergemaster/mergemaster.sh14
508 files changed, 20053 insertions, 9034 deletions
diff --git a/UPDATING b/UPDATING
index 553e961..937f917 100644
--- a/UPDATING
+++ b/UPDATING
@@ -22,6 +22,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW:
machines to maximize performance. (To disable malloc debugging, run
ln -s aj /etc/malloc.conf.)
+
+20100429:
+ 'vm_page's are now hashed by physical address to an array of mutexes.
+ Currently this is only used to serialize access to hold_count. Over
+ time the page queue mutex will be peeled away. This changes the size
+ of pmap on every architecture. And requires all callers of vm_page_hold
+ and vm_page_unhold to be updated.
+
20100402:
WITH_CTF can now be specified in src.conf (not recommended, there
are some problems with static executables), make.conf (would also
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index e93fb14..c4495d0 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -937,6 +937,8 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
cmdentry.special = 1;
if (cmdentry.special)
listsetvar(cmdenviron);
+ if (argc > 0)
+ bltinsetlocale();
commandname = argv[0];
argptr = argv + 1;
nextopt_optptr = NULL; /* initialize nextopt */
@@ -944,6 +946,8 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
flushall();
cmddone:
+ if (argc > 0)
+ bltinunsetlocale();
cmdenviron = NULL;
out1 = &output;
out2 = &errout;
diff --git a/bin/sh/var.c b/bin/sh/var.c
index d46e2c3..75de239 100644
--- a/bin/sh/var.c
+++ b/bin/sh/var.c
@@ -122,6 +122,14 @@ STATIC const struct varinit varinit[] = {
STATIC struct var *vartab[VTABSIZE];
+STATIC const char *const locale_names[7] = {
+ "LC_COLLATE", "LC_CTYPE", "LC_MONETARY",
+ "LC_NUMERIC", "LC_TIME", "LC_MESSAGES", NULL
+};
+STATIC const int locale_categories[7] = {
+ LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES, 0
+};
+
STATIC struct var **hashvar(const char *);
STATIC int varequal(const char *, const char *);
STATIC int localevar(const char *);
@@ -258,11 +266,7 @@ setvar(const char *name, const char *val, int flags)
STATIC int
localevar(const char *s)
{
- static const char *lnames[7] = {
- "ALL", "COLLATE", "CTYPE", "MONETARY",
- "NUMERIC", "TIME", NULL
- };
- const char **ss;
+ const char *const *ss;
if (*s != 'L')
return 0;
@@ -270,8 +274,10 @@ localevar(const char *s)
return 1;
if (strncmp(s + 1, "C_", 2) != 0)
return 0;
- for (ss = lnames; *ss ; ss++)
- if (varequal(s + 3, *ss))
+ if (varequal(s + 3, "ALL"))
+ return 1;
+ for (ss = locale_names; *ss ; ss++)
+ if (varequal(s + 3, *ss + 3))
return 1;
return 0;
}
@@ -437,6 +443,61 @@ bltinlookup(const char *name, int doall)
}
+/*
+ * Set up locale for a builtin (LANG/LC_* assignments).
+ */
+void
+bltinsetlocale(void)
+{
+ struct strlist *lp;
+ int act = 0;
+ char *loc, *locdef;
+ int i;
+
+ for (lp = cmdenviron ; lp ; lp = lp->next) {
+ if (localevar(lp->text)) {
+ act = 1;
+ break;
+ }
+ }
+ if (!act)
+ return;
+ loc = bltinlookup("LC_ALL", 0);
+ INTOFF;
+ if (loc != NULL) {
+ setlocale(LC_ALL, loc);
+ INTON;
+ return;
+ }
+ locdef = bltinlookup("LANG", 0);
+ for (i = 0; locale_names[i] != NULL; i++) {
+ loc = bltinlookup(locale_names[i], 0);
+ if (loc == NULL)
+ loc = locdef;
+ if (loc != NULL)
+ setlocale(locale_categories[i], loc);
+ }
+ INTON;
+}
+
+/*
+ * Undo the effect of bltinlocaleset().
+ */
+void
+bltinunsetlocale(void)
+{
+ struct strlist *lp;
+
+ INTOFF;
+ for (lp = cmdenviron ; lp ; lp = lp->next) {
+ if (localevar(lp->text)) {
+ setlocale(LC_ALL, "");
+ return;
+ }
+ }
+ INTON;
+}
+
/*
* Generate a list of exported variables. This routine is used to construct
diff --git a/bin/sh/var.h b/bin/sh/var.h
index 9c792c8..6a02630 100644
--- a/bin/sh/var.h
+++ b/bin/sh/var.h
@@ -107,6 +107,8 @@ struct strlist;
void listsetvar(struct strlist *);
char *lookupvar(const char *);
char *bltinlookup(const char *, int);
+void bltinsetlocale(void);
+void bltinunsetlocale(void);
char **environment(void);
int showvarscmd(int, char **);
int exportcmd(int, char **);
diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
index 79428f7..a9d3c01 100644
--- a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
+++ b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
@@ -1790,7 +1790,7 @@ zfs_do_list(int argc, char **argv)
boolean_t scripted = B_FALSE;
static char default_fields[] =
"name,used,available,referenced,mountpoint";
- int types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME;
+ int types = ZFS_TYPE_DATASET;
boolean_t types_specified = B_FALSE;
char *fields = NULL;
list_cbdata_t cb = { 0 };
diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
index 2970371..eef60e6 100644
--- a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
+++ b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
@@ -879,17 +879,21 @@ int
zpool_do_export(int argc, char **argv)
{
boolean_t force = B_FALSE;
+ boolean_t hardforce = B_FALSE;
int c;
zpool_handle_t *zhp;
int ret;
int i;
/* check options */
- while ((c = getopt(argc, argv, "f")) != -1) {
+ while ((c = getopt(argc, argv, "fF")) != -1) {
switch (c) {
case 'f':
force = B_TRUE;
break;
+ case 'F':
+ hardforce = B_TRUE;
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -919,8 +923,12 @@ zpool_do_export(int argc, char **argv)
continue;
}
- if (zpool_export(zhp, force) != 0)
+ if (hardforce) {
+ if (zpool_export_force(zhp) != 0)
+ ret = 1;
+ } else if (zpool_export(zhp, force) != 0) {
ret = 1;
+ }
zpool_close(zhp);
}
diff --git a/cddl/contrib/opensolaris/cmd/ztest/ztest.c b/cddl/contrib/opensolaris/cmd/ztest/ztest.c
index b7ca302..9744a0a 100644
--- a/cddl/contrib/opensolaris/cmd/ztest/ztest.c
+++ b/cddl/contrib/opensolaris/cmd/ztest/ztest.c
@@ -3039,7 +3039,7 @@ ztest_spa_import_export(char *oldname, char *newname)
/*
* Export it.
*/
- error = spa_export(oldname, &config, B_FALSE);
+ error = spa_export(oldname, &config, B_FALSE, B_FALSE);
if (error)
fatal(0, "spa_export('%s') = %d", oldname, error);
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
index a959494..a77317e 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
@@ -289,6 +289,7 @@ extern int zpool_get_errlog(zpool_handle_t *, nvlist_t **);
* Import and export functions
*/
extern int zpool_export(zpool_handle_t *, boolean_t);
+extern int zpool_export_force(zpool_handle_t *);
extern int zpool_import(libzfs_handle_t *, nvlist_t *, const char *,
char *altroot);
extern int zpool_import_props(libzfs_handle_t *, nvlist_t *, const char *,
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
index c3cb547..0369062 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
@@ -1096,7 +1096,7 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
* mounted datasets in the pool.
*/
int
-zpool_export(zpool_handle_t *zhp, boolean_t force)
+zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce)
{
zfs_cmd_t zc = { 0 };
char msg[1024];
@@ -1109,6 +1109,7 @@ zpool_export(zpool_handle_t *zhp, boolean_t force)
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
zc.zc_cookie = force;
+ zc.zc_guid = hardforce;
if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
switch (errno) {
@@ -1129,6 +1130,18 @@ zpool_export(zpool_handle_t *zhp, boolean_t force)
return (0);
}
+int
+zpool_export(zpool_handle_t *zhp, boolean_t force)
+{
+ return (zpool_export_common(zhp, force, B_FALSE));
+}
+
+int
+zpool_export_force(zpool_handle_t *zhp)
+{
+ return (zpool_export_common(zhp, B_TRUE, B_TRUE));
+}
+
/*
* zpool_import() is a contracted interface. Should be kept the same
* if possible.
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c b/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
index 6a9d67a..d95dd1d 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
@@ -355,14 +355,21 @@ write_type(void *arg1, void *arg2)
for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next)
i++; /* count up enum members */
+ if (i > CTF_MAX_VLEN) {
+ warning("enum %s has too many values: %d > %d\n",
+ tdesc_name(tp), i, CTF_MAX_VLEN);
+ i = CTF_MAX_VLEN;
+ }
+
ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i);
write_sized_type_rec(b, &ctt, tp->t_size);
- for (ep = tp->t_emem; ep != NULL; ep = ep->el_next) {
+ for (ep = tp->t_emem; ep != NULL && i > 0; ep = ep->el_next) {
offset = strtab_insert(&b->ctb_strtab, ep->el_name);
cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset);
cte.cte_value = ep->el_number;
ctf_buf_write(b, &cte, sizeof (cte));
+ i--;
}
break;
diff --git a/contrib/telnet/telnet/commands.c b/contrib/telnet/telnet/commands.c
index a64d763..c39b187 100644
--- a/contrib/telnet/telnet/commands.c
+++ b/contrib/telnet/telnet/commands.c
@@ -2491,8 +2491,7 @@ tn(int argc, char *argv[])
env_export("USER");
}
(void) call(status, "status", "notmuch", 0);
- if (setjmp(peerdied) == 0)
- telnet(user);
+ telnet(user);
(void) NetClose(net);
ExitString("Connection closed by foreign host.\n",1);
/*NOTREACHED*/
diff --git a/contrib/telnet/telnet/externs.h b/contrib/telnet/telnet/externs.h
index cfa1aec..e07aebb 100644
--- a/contrib/telnet/telnet/externs.h
+++ b/contrib/telnet/telnet/externs.h
@@ -233,7 +233,6 @@ extern void
SetNetTrace(char *); /* Function to change where debugging goes */
extern jmp_buf
- peerdied,
toplevel; /* For error conditions. */
extern void
diff --git a/contrib/telnet/telnet/network.c b/contrib/telnet/telnet/network.c
index bb75d63..b140d60 100644
--- a/contrib/telnet/telnet/network.c
+++ b/contrib/telnet/telnet/network.c
@@ -158,7 +158,7 @@ netflush(void)
perror(hostname);
(void)NetClose(net);
ring_clear_mark(&netoring);
- longjmp(peerdied, -1);
+ ExitString("Connection closed by foreign host.\n", 1);
/*NOTREACHED*/
}
n = 0;
diff --git a/contrib/telnet/telnet/sys_bsd.c b/contrib/telnet/telnet/sys_bsd.c
index 45ef1e2..9fba74f 100644
--- a/contrib/telnet/telnet/sys_bsd.c
+++ b/contrib/telnet/telnet/sys_bsd.c
@@ -809,14 +809,6 @@ NetNonblockingIO(int fd, int onoff)
*/
/* ARGSUSED */
-static SIG_FUNC_RET
-deadpeer(int sig __unused)
-{
- setcommandmode();
- longjmp(peerdied, -1);
-}
-
-/* ARGSUSED */
SIG_FUNC_RET
intr(int sig __unused)
{
@@ -884,7 +876,7 @@ sys_telnet_init(void)
{
(void) signal(SIGINT, intr);
(void) signal(SIGQUIT, intr2);
- (void) signal(SIGPIPE, deadpeer);
+ (void) signal(SIGPIPE, SIG_IGN);
#ifdef SIGWINCH
(void) signal(SIGWINCH, sendwin);
#endif
diff --git a/contrib/telnet/telnet/telnet.c b/contrib/telnet/telnet/telnet.c
index 28237bd..8c457cf 100644
--- a/contrib/telnet/telnet/telnet.c
+++ b/contrib/telnet/telnet/telnet.c
@@ -146,7 +146,6 @@ unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
#endif
jmp_buf toplevel;
-jmp_buf peerdied;
int flushline;
int linemode;
diff --git a/contrib/telnet/telnet/terminal.c b/contrib/telnet/telnet/terminal.c
index 3dda1c5..596c2b8 100644
--- a/contrib/telnet/telnet/terminal.c
+++ b/contrib/telnet/telnet/terminal.c
@@ -111,7 +111,8 @@ init_terminal(void)
}
/*
- * Send as much data as possible to the terminal.
+ * Send as much data as possible to the terminal, else exits if
+ * it encounters a permanent failure when writing to the tty.
*
* Return value:
* -1: No useful work done, data waiting to go out.
@@ -152,8 +153,19 @@ ttyflush(int drop)
}
ring_consumed(&ttyoring, n);
}
- if (n < 0)
+ if (n < 0) {
+ if (errno == EAGAIN || errno == EINTR) {
+ return -1;
+ } else {
+ ring_consumed(&ttyoring, ring_full_count(&ttyoring));
+ setconnmode(0);
+ setcommandmode();
+ NetClose(net);
+ fprintf(stderr, "Write error on local output.\n");
+ exit(1);
+ }
return -1;
+ }
if (n == n0) {
if (n0)
return -1;
diff --git a/contrib/tzcode/zic/private.h b/contrib/tzcode/zic/private.h
index ecbf612..d00bf9b 100644
--- a/contrib/tzcode/zic/private.h
+++ b/contrib/tzcode/zic/private.h
@@ -34,7 +34,7 @@ static const char privatehid[] = "@(#)private.h 8.6";
#endif /* !defined NOID */
#endif /* !defined lint */
-#define GRANDPARENTED "Local time zone must be set--see zic manual page"
+#define GRANDPARENTED "Local time zone must be set--use tzsetup"
/*
** Defaults for preprocessor symbols.
diff --git a/crypto/openssh/ChangeLog b/crypto/openssh/ChangeLog
index d6e4a4a..a08e1a7 100644
--- a/crypto/openssh/ChangeLog
+++ b/crypto/openssh/ChangeLog
@@ -1,4 +1,120 @@
-20100307
+20100410
+ - (dtucker) [configure.ac] Put the check for the existence of getaddrinfo
+ back so we disable the IPv6 tests if we don't have it.
+
+20100409
+ - (dtucker) [contrib/cygwin/Makefile] Don't overwrite files with the wrong
+ ones. Based on a patch from Roumen Petrov.
+ - (dtucker) [configure.ac] Bug #1744: use pkg-config for libedit flags if we
+ have it and the path is not provided to --with-libedit. Based on a patch
+ from Iain Morgan.
+ - (dtucker) [configure.ac defines.h loginrec.c logintest.c] Bug #1732: enable
+ utmpx support on FreeBSD where possible. Patch from Ed Schouten, ok djm@
+
+20100326
+ - (djm) [openbsd-compat/bsd-arc4random.c] Fix preprocessor detection
+ for arc4random_buf() and arc4random_uniform(); from Josh Gilkerson
+ - (dtucker) [configure.ac] Bug #1741: Add section for Haiku, patch originally
+ by Ingo Weinhold via Scott McCreary, ok djm@
+ - (djm) OpenBSD CVS Sync
+ - djm@cvs.openbsd.org 2010/03/25 23:38:28
+ [servconf.c]
+ from portable: getcwd(NULL, 0) doesn't work on all platforms, so
+ use a stack buffer; ok dtucker@
+ - djm@cvs.openbsd.org 2010/03/26 00:26:58
+ [ssh.1]
+ mention that -S none disables connection sharing; from Colin Watson
+ - (djm) [session.c] Allow ChrootDirectory to work on SELinux platforms -
+ set up SELinux execution context before chroot() call. From Russell
+ Coker via Colin watson; bz#1726 ok dtucker@
+ - (djm) [channels.c] Check for EPFNOSUPPORT as a socket() errno; bz#1721
+ ok dtucker@
+ - (dtucker) Bug #1725: explicitly link libX11 into gnome-ssh-askpass2 using
+ pkg-config, patch from Colin Watson. Needed for newer linkers (ie gold).
+ - (djm) [contrib/ssh-copy-id] Don't blow up when the agent has no keys;
+ bz#1723 patch from Adeodato Simóvia Colin Watson; ok dtucker@
+ - (dtucker) OpenBSD CVS Sync
+ - dtucker@cvs.openbsd.org 2010/03/26 01:06:13
+ [ssh_config.5]
+ Reformat default value of PreferredAuthentications entry (current
+ formatting implies ", " is acceptable as a separator, which it's not.
+ ok djm@
+
+20100324
+ - (dtucker) [contrib/cygwin/ssh-host-config] Mount the Windows directory
+ containing the services file explicitely case-insensitive. This allows to
+ tweak the Windows services file reliably. Patch from vinschen at redhat.
+
+20100321
+ - (djm) OpenBSD CVS Sync
+ - jmc@cvs.openbsd.org 2010/03/08 09:41:27
+ [ssh-keygen.1]
+ sort the list of constraints (to -O); ok djm
+ - jmc@cvs.openbsd.org 2010/03/10 07:40:35
+ [ssh-keygen.1]
+ typos; from Ross Richardson
+ closes prs 6334 and 6335
+ - djm@cvs.openbsd.org 2010/03/10 23:27:17
+ [auth2-pubkey.c]
+ correct certificate logging and make it more consistent between
+ authorized_keys and TrustedCAKeys; ok markus@
+ - djm@cvs.openbsd.org 2010/03/12 01:06:25
+ [servconf.c]
+ unbreak AuthorizedKeys option with a $HOME-relative path; reported by
+ vinschen AT redhat.com, ok dtucker@
+ - markus@cvs.openbsd.org 2010/03/12 11:37:40
+ [servconf.c]
+ do not prepend AuthorizedKeysFile with getcwd(), unbreaks relative paths
+ free() (not xfree()) the buffer returned by getcwd()
+ - djm@cvs.openbsd.org 2010/03/13 21:10:38
+ [clientloop.c]
+ protocol conformance fix: send language tag when disconnecting normally;
+ spotted by 1.41421 AT gmail.com, ok markus@ deraadt@
+ - djm@cvs.openbsd.org 2010/03/13 21:45:46
+ [ssh-keygen.1]
+ Certificates are named *-cert.pub, not *_cert.pub; committing a diff
+ from stevesk@ ok me
+ - jmc@cvs.openbsd.org 2010/03/13 23:38:13
+ [ssh-keygen.1]
+ fix a formatting error (args need quoted); noted by stevesk
+ - stevesk@cvs.openbsd.org 2010/03/15 19:40:02
+ [key.c key.h ssh-keygen.c]
+ also print certificate type (user or host) for ssh-keygen -L
+ ok djm kettenis
+ - stevesk@cvs.openbsd.org 2010/03/16 15:46:52
+ [auth-options.c]
+ spelling in error message. ok djm kettenis
+ - djm@cvs.openbsd.org 2010/03/16 16:36:49
+ [version.h]
+ crank version to openssh-5.5 since we have a few fixes since 5.4;
+ requested deraadt@ kettenis@
+ - (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
+ [contrib/suse/openssh.spec] Crank version numbers
+
+20100314
+ - (djm) [ssh-pkcs11-helper.c] Move #ifdef to after #defines to fix
+ compilation failure when !HAVE_DLOPEN. Reported by felix-mindrot
+ AT fefe.de
+ - (djm) [Makefile.in] Respecify -lssh after -lopenbsd-compat for
+ ssh-pkcs11-helper to repair static builds (we do the same for
+ ssh-keyscan). Reported by felix-mindrot AT fefe.de
+
+20100312
+ - (tim) [Makefile.in] Now that scard is gone, no need to make $(datadir)
+ - (tim) [Makefile.in] Add missing $(EXEEXT) to install targets.
+ Patch from Corinna Vinschen.
+ - (tim) [contrib/cygwin/Makefile] Fix list of documentation files to install
+ on a Cygwin installation. Patch from Corinna Vinschen.
+
+20100311
+ - (tim) [contrib/suse/openssh.spec] crank version number here too.
+ report by imorgan AT nas.nasa.gov
+
+20100309
+ - (dtucker) [configure.ac] Use a proper AC_CHECK_DECL for BROKEN_GETADDRINFO
+ so setting it in CFLAGS correctly skips IPv6 tests.
+
+20100428
- (djm) OpenBSD CVS Sync
- djm@cvs.openbsd.org 2010/03/07 22:16:01
[ssh-keygen.c]
diff --git a/crypto/openssh/README b/crypto/openssh/README
index 0ecb670..a29f200 100644
--- a/crypto/openssh/README
+++ b/crypto/openssh/README
@@ -1,4 +1,4 @@
-See http://www.openssh.com/txt/release-5.4 for the release notes.
+See http://www.openssh.com/txt/release-5.5 for the release notes.
- A Japanese translation of this document and of the OpenSSH FAQ is
- available at http://www.unixuser.org/~haruyama/security/openssh/index.html
@@ -62,4 +62,4 @@ References -
[6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9
[7] http://www.openssh.com/faq.html
-$Id: README,v 1.72 2010/03/07 22:41:02 djm Exp $
+$Id: README,v 1.73 2010/03/21 19:11:55 djm Exp $
diff --git a/crypto/openssh/auth-options.c b/crypto/openssh/auth-options.c
index 1293017..69b314f 100644
--- a/crypto/openssh/auth-options.c
+++ b/crypto/openssh/auth-options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-options.c,v 1.48 2010/03/07 11:57:13 dtucker Exp $ */
+/* $OpenBSD: auth-options.c,v 1.49 2010/03/16 15:46:52 stevesk Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -434,7 +434,7 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw)
goto out;
}
if (strlen(command) != clen) {
- error("force-command constrain contains \\0");
+ error("force-command constraint contains \\0");
goto out;
}
if (cert_forced_command != NULL) {
@@ -454,7 +454,7 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw)
goto out;
}
if (strlen(allowed) != clen) {
- error("source-address constrain contains \\0");
+ error("source-address constraint contains \\0");
goto out;
}
if (cert_source_address_done++) {
diff --git a/crypto/openssh/auth2-pubkey.c b/crypto/openssh/auth2-pubkey.c
index 51aa774..c4cadf4 100644
--- a/crypto/openssh/auth2-pubkey.c
+++ b/crypto/openssh/auth2-pubkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.21 2010/03/04 10:36:03 djm Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.22 2010/03/10 23:27:17 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -240,22 +240,26 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
continue;
if (!key_equal(found, key->cert->signature_key))
continue;
- debug("matching CA found: file %s, line %lu",
- file, linenum);
fp = key_fingerprint(found, SSH_FP_MD5,
SSH_FP_HEX);
- verbose("Found matching %s CA: %s",
- key_type(found), fp);
- xfree(fp);
+ debug("matching CA found: file %s, line %lu, %s %s",
+ file, linenum, key_type(found), fp);
if (key_cert_check_authority(key, 0, 0, pw->pw_name,
&reason) != 0) {
+ xfree(fp);
error("%s", reason);
auth_debug_add("%s", reason);
continue;
}
if (auth_cert_constraints(&key->cert->constraints,
- pw) != 0)
+ pw) != 0) {
+ xfree(fp);
continue;
+ }
+ verbose("Accepted certificate ID \"%s\" "
+ "signed by %s CA %s via %s", key->cert->key_id,
+ key_type(found), fp, file);
+ xfree(fp);
found_key = 1;
break;
} else if (!key_is_cert_authority && key_equal(found, key)) {
@@ -281,15 +285,15 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
static int
user_cert_trusted_ca(struct passwd *pw, Key *key)
{
- char *key_fp, *ca_fp;
+ char *ca_fp;
const char *reason;
int ret = 0;
if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
return 0;
- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
- ca_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ ca_fp = key_fingerprint(key->cert->signature_key,
+ SSH_FP_MD5, SSH_FP_HEX);
if (key_in_file(key->cert->signature_key,
options.trusted_user_ca_keys, 1) != 1) {
@@ -306,13 +310,12 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
if (auth_cert_constraints(&key->cert->constraints, pw) != 0)
goto out;
- verbose("%s certificate %s allowed by trusted %s key %s",
- key_type(key), key_fp, key_type(key->cert->signature_key), ca_fp);
+ verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s",
+ key->cert->key_id, key_type(key->cert->signature_key), ca_fp,
+ options.trusted_user_ca_keys);
ret = 1;
out:
- if (key_fp != NULL)
- xfree(key_fp);
if (ca_fp != NULL)
xfree(ca_fp);
return ret;
diff --git a/crypto/openssh/channels.c b/crypto/openssh/channels.c
index d8c53a4..a55d278 100644
--- a/crypto/openssh/channels.c
+++ b/crypto/openssh/channels.c
@@ -3252,7 +3252,11 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
sock = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
if (sock < 0) {
- if ((errno != EINVAL) && (errno != EAFNOSUPPORT)) {
+ if ((errno != EINVAL) && (errno != EAFNOSUPPORT)
+#ifdef EPFNOSUPPORT
+ && (errno != EPFNOSUPPORT)
+#endif
+ ) {
error("socket: %.100s", strerror(errno));
freeaddrinfo(aitop);
return -1;
diff --git a/crypto/openssh/clientloop.c b/crypto/openssh/clientloop.c
index 6ffef95..9ab56b4 100644
--- a/crypto/openssh/clientloop.c
+++ b/crypto/openssh/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.218 2010/01/28 00:21:18 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.219 2010/03/13 21:10:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1484,6 +1484,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
packet_start(SSH2_MSG_DISCONNECT);
packet_put_int(SSH2_DISCONNECT_BY_APPLICATION);
packet_put_cstring("disconnected by user");
+ packet_put_cstring(""); /* language tag */
packet_send();
packet_write_wait();
}
diff --git a/crypto/openssh/config.h b/crypto/openssh/config.h
index 66e3c7a..01fc523 100644
--- a/crypto/openssh/config.h
+++ b/crypto/openssh/config.h
@@ -124,7 +124,7 @@
#define DISABLE_WTMPX 1
/* Enable for PKCS#11 support */
-#define ENABLE_PKCS11
+#define ENABLE_PKCS11 /**/
/* Builtin PRNG command timeout */
#define ENTROPY_TIMEOUT_MSEC 200
@@ -456,6 +456,9 @@
/* Define to 1 if you have the `getutxline' function. */
#define HAVE_GETUTXLINE 1
+/* Define to 1 if you have the `getutxuser' function. */
+#define HAVE_GETUTXUSER 1
+
/* Define to 1 if you have the `get_default_context_with_level' function. */
/* #undef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL */
@@ -552,6 +555,9 @@
/* Define if system has libiaf that supports set_id */
/* #undef HAVE_LIBIAF */
+/* Define to 1 if you have the `network' library (-lnetwork). */
+/* #undef HAVE_LIBNETWORK */
+
/* Define to 1 if you have the `nsl' library (-lnsl). */
/* #undef HAVE_LIBNSL */
@@ -805,6 +811,9 @@
/* Define to 1 if you have the `setutent' function. */
/* #undef HAVE_SETUTENT */
+/* Define to 1 if you have the `setutxdb' function. */
+#define HAVE_SETUTXDB 1
+
/* Define to 1 if you have the `setutxent' function. */
#define HAVE_SETUTXENT 1
@@ -1416,8 +1425,8 @@
/* Define if you want SELinux support. */
/* #undef WITH_SELINUX */
-/* Define to 1 if your processor stores words with the most significant byte
- first (like Motorola and SPARC, unlike Intel and VAX). */
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel and VAX). */
#if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
#elif ! defined __LITTLE_ENDIAN__
diff --git a/crypto/openssh/config.h.in b/crypto/openssh/config.h.in
index a61dec6..a43ad57 100644
--- a/crypto/openssh/config.h.in
+++ b/crypto/openssh/config.h.in
@@ -80,9 +80,6 @@
/* Define if you want to specify the path to your lastlog file */
#undef CONF_LASTLOG_FILE
-/* Define if you want to specify the path to your utmpx file */
-#undef CONF_UTMPX_FILE
-
/* Define if you want to specify the path to your utmp file */
#undef CONF_UTMP_FILE
@@ -455,6 +452,9 @@
/* Define to 1 if you have the `getutxline' function. */
#undef HAVE_GETUTXLINE
+/* Define to 1 if you have the `getutxuser' function. */
+#undef HAVE_GETUTXUSER
+
/* Define to 1 if you have the `get_default_context_with_level' function. */
#undef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
@@ -551,6 +551,9 @@
/* Define if system has libiaf that supports set_id */
#undef HAVE_LIBIAF
+/* Define to 1 if you have the `network' library (-lnetwork). */
+#undef HAVE_LIBNETWORK
+
/* Define to 1 if you have the `nsl' library (-lnsl). */
#undef HAVE_LIBNSL
@@ -804,6 +807,9 @@
/* Define to 1 if you have the `setutent' function. */
#undef HAVE_SETUTENT
+/* Define to 1 if you have the `setutxdb' function. */
+#undef HAVE_SETUTXDB
+
/* Define to 1 if you have the `setutxent' function. */
#undef HAVE_SETUTXENT
diff --git a/crypto/openssh/defines.h b/crypto/openssh/defines.h
index e592249..fe25170 100644
--- a/crypto/openssh/defines.h
+++ b/crypto/openssh/defines.h
@@ -25,7 +25,7 @@
#ifndef _DEFINES_H
#define _DEFINES_H
-/* $Id: defines.h,v 1.159 2010/01/13 23:44:34 tim Exp $ */
+/* $Id: defines.h,v 1.160 2010/04/09 08:13:27 dtucker Exp $ */
/* Constants */
diff --git a/crypto/openssh/key.c b/crypto/openssh/key.c
index 0d0c912..66592c7 100644
--- a/crypto/openssh/key.c
+++ b/crypto/openssh/key.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.c,v 1.85 2010/03/04 01:44:57 djm Exp $ */
+/* $OpenBSD: key.c,v 1.86 2010/03/15 19:40:02 stevesk Exp $ */
/*
* read_bignum():
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -802,6 +802,19 @@ key_type(const Key *k)
}
const char *
+key_cert_type(const Key *k)
+{
+ switch (k->cert->type) {
+ case SSH2_CERT_TYPE_USER:
+ return "user";
+ case SSH2_CERT_TYPE_HOST:
+ return "host";
+ default:
+ return "unknown";
+ }
+}
+
+const char *
key_ssh_name(const Key *k)
{
switch (k->type) {
diff --git a/crypto/openssh/key.h b/crypto/openssh/key.h
index 6a2e049..4f17777 100644
--- a/crypto/openssh/key.h
+++ b/crypto/openssh/key.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.h,v 1.28 2010/02/26 20:29:54 djm Exp $ */
+/* $OpenBSD: key.h,v 1.29 2010/03/15 19:40:02 stevesk Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -82,6 +82,7 @@ int key_equal(const Key *, const Key *);
char *key_fingerprint(Key *, enum fp_type, enum fp_rep);
u_char *key_fingerprint_raw(Key *, enum fp_type, u_int *);
const char *key_type(const Key *);
+const char *key_cert_type(const Key *);
int key_write(const Key *, FILE *);
int key_read(Key *, char **);
u_int key_size(const Key *);
diff --git a/crypto/openssh/loginrec.c b/crypto/openssh/loginrec.c
index e6eaf0b..62962ac 100644
--- a/crypto/openssh/loginrec.c
+++ b/crypto/openssh/loginrec.c
@@ -510,6 +510,10 @@ getlast_entry(struct logininfo *li)
#ifdef USE_LASTLOG
return(lastlog_get_entry(li));
#else /* !USE_LASTLOG */
+#if defined(USE_UTMPX) && defined(HAVE_SETUTXDB) && \
+ defined(UTXDB_LASTLOGIN) && defined(HAVE_GETUTXUSER)
+ return (utmpx_get_entry(li));
+#endif
#if 1
return (utmpx_get_entry(li));
@@ -1614,7 +1618,8 @@ lastlog_get_entry(struct logininfo *li)
#endif /* HAVE_GETLASTLOGXBYNAME */
#endif /* USE_LASTLOG */
-#if 1
+#if defined(USE_UTMPX) && defined(HAVE_SETUTXDB) && \
+ defined(UTXDB_LASTLOGIN) && defined(HAVE_GETUTXUSER)
int
utmpx_get_entry(struct logininfo *li)
{
@@ -1637,7 +1642,7 @@ utmpx_get_entry(struct logininfo *li)
endutxent();
return (1);
}
-#endif
+#endif /* USE_UTMPX && HAVE_SETUTXDB && UTXDB_LASTLOGIN && HAVE_GETUTXUSER */
#ifdef USE_BTMP
/*
diff --git a/crypto/openssh/logintest.c b/crypto/openssh/logintest.c
index 7e9fbbf..4897ae0 100644
--- a/crypto/openssh/logintest.c
+++ b/crypto/openssh/logintest.c
@@ -264,7 +264,7 @@ showOptions(void)
printf("\tUSE_UTMP (UTMP_FILE=%s)\n", UTMP_FILE);
#endif
#ifdef USE_UTMPX
- printf("\tUSE_UTMPX (UTMPX_FILE=%s)\n", UTMPX_FILE);
+ printf("\tUSE_UTMPX\n");
#endif
#ifdef USE_WTMP
printf("\tUSE_WTMP (WTMP_FILE=%s)\n", WTMP_FILE);
diff --git a/crypto/openssh/openbsd-compat/bsd-arc4random.c b/crypto/openssh/openbsd-compat/bsd-arc4random.c
index 9d4c869..d7c5862 100644
--- a/crypto/openssh/openbsd-compat/bsd-arc4random.c
+++ b/crypto/openssh/openbsd-compat/bsd-arc4random.c
@@ -84,7 +84,7 @@ arc4random_stir(void)
}
#endif /* !HAVE_ARC4RANDOM */
-#ifndef ARC4RANDOM_BUF
+#ifndef HAVE_ARC4RANDOM_BUF
void
arc4random_buf(void *_buf, size_t n)
{
@@ -102,7 +102,7 @@ arc4random_buf(void *_buf, size_t n)
}
#endif /* !HAVE_ARC4RANDOM_BUF */
-#ifndef ARC4RANDOM_UNIFORM
+#ifndef HAVE_ARC4RANDOM_UNIFORM
/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding "modulo bias".
diff --git a/crypto/openssh/servconf.c b/crypto/openssh/servconf.c
index 603c586..626f38c 100644
--- a/crypto/openssh/servconf.c
+++ b/crypto/openssh/servconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.c,v 1.204 2010/03/04 10:36:03 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.207 2010/03/25 23:38:28 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -474,15 +474,14 @@ parse_token(const char *cp, const char *filename,
char *
derelativise_path(const char *path)
{
- char *expanded, *ret, *cwd;
+ char *expanded, *ret, cwd[MAXPATHLEN];
expanded = tilde_expand_filename(path, getuid());
if (*expanded == '/')
return expanded;
- if ((cwd = getcwd(NULL, 0)) == NULL)
+ if (getcwd(cwd, sizeof(cwd)) == NULL)
fatal("%s: getcwd: %s", __func__, strerror(errno));
xasprintf(&ret, "%s/%s", cwd, expanded);
- xfree(cwd);
xfree(expanded);
return ret;
}
@@ -1227,7 +1226,17 @@ process_server_config_line(ServerOptions *options, char *line,
charptr = (opcode == sAuthorizedKeysFile) ?
&options->authorized_keys_file :
&options->authorized_keys_file2;
- goto parse_filename;
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing file name.",
+ filename, linenum);
+ if (*activep && *charptr == NULL) {
+ *charptr = tilde_expand_filename(arg, getuid());
+ /* increase optional counter */
+ if (intptr != NULL)
+ *intptr = *intptr + 1;
+ }
+ break;
case sClientAliveInterval:
intptr = &options->client_alive_interval;
diff --git a/crypto/openssh/session.c b/crypto/openssh/session.c
index aad0979..c11a68a 100644
--- a/crypto/openssh/session.c
+++ b/crypto/openssh/session.c
@@ -1581,6 +1581,10 @@ do_setusercontext(struct passwd *pw)
}
#endif /* HAVE_SETPCRED */
+#ifdef WITH_SELINUX
+ ssh_selinux_setup_exec_context(pw->pw_name);
+#endif
+
if (options.chroot_directory != NULL &&
strcasecmp(options.chroot_directory, "none") != 0) {
tmp = tilde_expand_filename(options.chroot_directory,
@@ -1605,10 +1609,6 @@ do_setusercontext(struct passwd *pw)
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
-
-#ifdef WITH_SELINUX
- ssh_selinux_setup_exec_context(pw->pw_name);
-#endif
}
static void
diff --git a/crypto/openssh/ssh-keygen.1 b/crypto/openssh/ssh-keygen.1
index 0da6354..6931842 100644
--- a/crypto/openssh/ssh-keygen.1
+++ b/crypto/openssh/ssh-keygen.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-keygen.1,v 1.88 2010/03/08 00:28:55 djm Exp $
+.\" $OpenBSD: ssh-keygen.1,v 1.92 2010/03/13 23:38:13 jmc Exp $
.\" $FreeBSD$
.\"
.\" -*- nroff -*-
@@ -38,7 +38,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd March 8 2010
+.Dd March 13 2010
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
@@ -308,8 +308,15 @@ Please see the
section for details.
The constraints that are valid for user certificates are:
.Bl -tag -width Ds
-.It Ic no-x11-forwarding
-Disable X11 forwarding (permitted by default).
+.It Ic clear
+Clear all enabled permissions.
+This is useful for clearing the default set of permissions so permissions may
+be added individually.
+.It Ic force-command Ns = Ns Ar command
+Forces the execution of
+.Ar command
+instead of any shell or command specified by the user when
+the certificate is used for authentication.
.It Ic no-agent-forwarding
Disable
.Xr ssh-agent 1
@@ -324,12 +331,8 @@ Disable execution of
by
.Xr sshd 8
(permitted by default).
-.It Ic clear
-Clear all enabled permissions.
-This is useful for clearing the default set of permissions so permissions may
-be added individually.
-.It Ic permit-x11-forwarding
-Allows X11 forwarding.
+.It Ic no-x11-forwarding
+Disable X11 forwarding (permitted by default).
.It Ic permit-agent-forwarding
Allows
.Xr ssh-agent 1
@@ -343,14 +346,10 @@ Allows execution of
.Pa ~/.ssh/rc
by
.Xr sshd 8 .
-.It Ic force-command=command
-Forces the execution of
-.Ar command
-instead of any shell or command specified by the user when
-the certificate is used for authentication.
-.It Ic source-address=address_list
-Restrict the source addresses from which the certificate is considered valid
-from.
+.It Ic permit-x11-forwarding
+Allows X11 forwarding.
+.It Ic source-address Ns = Ns Ar address_list
+Restrict the source addresses from which the certificate is considered valid.
The
.Ar address_list
is a comma-separated list of one or more address/netmask pairs in CIDR
@@ -415,7 +414,7 @@ in YYYYMMDDHHMMSS format or a relative time (to the current time) consisting
of a minus sign followed by a relative time in the format described in the
.Sx TIME FORMATS
section of
-.Xr ssh_config 5 .
+.Xr sshd_config 5 .
The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMMSS time or
a relative time starting with a plus character.
.Pp
@@ -520,7 +519,7 @@ To generate a user certificate:
.Dl $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub
.Pp
The resultant certificate will be placed in
-.Pa /path/to/user_key_cert.pub .
+.Pa /path/to/user_key-cert.pub .
A host certificate requires the
.Fl h
option:
@@ -528,7 +527,7 @@ option:
.Dl $ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub
.Pp
The host certificate will be output to
-.Pa /path/to/host_key_cert.pub .
+.Pa /path/to/host_key-cert.pub .
In both cases,
.Ar key_id
is a "key identifier" that is logged by the server when the certificate
@@ -540,7 +539,7 @@ By default, generated certificates are valid for all users or hosts.
To generate a certificate for a specified set of principals:
.Pp
.Dl $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub
-.Dl $ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub
+.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub"
.Pp
Additional limitations on the validity and use of user certificates may
be specified through certificate constraints.
diff --git a/crypto/openssh/ssh-keygen.c b/crypto/openssh/ssh-keygen.c
index dd662c9..37e516f 100644
--- a/crypto/openssh/ssh-keygen.c
+++ b/crypto/openssh/ssh-keygen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.184 2010/03/07 22:16:01 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.185 2010/03/15 19:40:02 stevesk Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1393,7 +1393,8 @@ do_show_cert(struct passwd *pw)
SSH_FP_MD5, SSH_FP_HEX);
printf("%s:\n", identity_file);
- printf(" %s certificate %s\n", key_type(key), key_fp);
+ printf(" %s %s certificate %s\n", key_type(key),
+ key_cert_type(key), key_fp);
printf(" Signed by %s CA %s\n",
key_type(key->cert->signature_key), ca_fp);
printf(" Key ID \"%s\"\n", key->cert->key_id);
diff --git a/crypto/openssh/ssh-pkcs11-helper.c b/crypto/openssh/ssh-pkcs11-helper.c
index d3bfb98..8e3f57a 100644
--- a/crypto/openssh/ssh-pkcs11-helper.c
+++ b/crypto/openssh/ssh-pkcs11-helper.c
@@ -17,8 +17,6 @@
#include "includes.h"
-#ifdef ENABLE_PKCS11
-
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
@@ -39,6 +37,8 @@
#include "authfd.h"
#include "ssh-pkcs11.h"
+#ifdef ENABLE_PKCS11
+
/* borrows code from sftp-server and ssh-agent */
struct pkcs11_keyinfo {
diff --git a/crypto/openssh/ssh.1 b/crypto/openssh/ssh.1
index e3a826e..80f8d8c 100644
--- a/crypto/openssh/ssh.1
+++ b/crypto/openssh/ssh.1
@@ -34,9 +34,9 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh.1,v 1.302 2010/03/05 10:28:21 djm Exp $
+.\" $OpenBSD: ssh.1,v 1.303 2010/03/26 00:26:58 djm Exp $
.\" $FreeBSD$
-.Dd March 5 2010
+.Dd March 26 2010
.Dt SSH 1
.Os
.Sh NAME
@@ -560,7 +560,10 @@ argument is
the listen port will be dynamically allocated on the server and reported
to the client at run time.
.It Fl S Ar ctl_path
-Specifies the location of a control socket for connection sharing.
+Specifies the location of a control socket for connection sharing
+or the string
+.Dq none
+to disable connection sharing.
Refer to the description of
.Cm ControlPath
and
diff --git a/crypto/openssh/ssh_config b/crypto/openssh/ssh_config
index 1edf164..3bda1b9 100644
--- a/crypto/openssh/ssh_config
+++ b/crypto/openssh/ssh_config
@@ -46,4 +46,4 @@
# PermitLocalCommand no
# VisualHostKey no
# ProxyCommand ssh -q -W %h:%p gateway.example.com
-# VersionAddendum FreeBSD-20100308
+# VersionAddendum FreeBSD-20100428
diff --git a/crypto/openssh/ssh_config.5 b/crypto/openssh/ssh_config.5
index 0f67fdc..88afdad 100644
--- a/crypto/openssh/ssh_config.5
+++ b/crypto/openssh/ssh_config.5
@@ -34,9 +34,9 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh_config.5,v 1.129 2010/03/05 10:28:21 djm Exp $
+.\" $OpenBSD: ssh_config.5,v 1.130 2010/03/26 01:06:13 dtucker Exp $
.\" $FreeBSD$
-.Dd March 5 2010
+.Dd March 26 2010
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@@ -735,11 +735,7 @@ This allows a client to prefer one method (e.g.\&
over another method (e.g.\&
.Cm password )
The default for this option is:
-.Do gssapi-with-mic ,
-hostbased,
-publickey,
-keyboard-interactive,
-password
+.Do gssapi-with-mic,hostbased,publickey,keyboard-interactive,password
.Dc .
.It Cm Protocol
Specifies the protocol versions
@@ -1087,7 +1083,7 @@ in
Specifies a string to append to the regular version string to identify
OS- or site-specific modifications.
The default is
-.Dq FreeBSD-20100308 .
+.Dq FreeBSD-20100428 .
.It Cm VisualHostKey
If this flag is set to
.Dq yes ,
diff --git a/crypto/openssh/sshd_config b/crypto/openssh/sshd_config
index 44b7582..3c700f0 100644
--- a/crypto/openssh/sshd_config
+++ b/crypto/openssh/sshd_config
@@ -14,7 +14,7 @@
# Note that some of FreeBSD's defaults differ from OpenBSD's, and
# FreeBSD has a few additional options.
-#VersionAddendum FreeBSD-20100308
+#VersionAddendum FreeBSD-20100428
#Port 22
#AddressFamily any
diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5
index d0d3053..bd667d7 100644
--- a/crypto/openssh/sshd_config.5
+++ b/crypto/openssh/sshd_config.5
@@ -988,7 +988,7 @@ The default is
Specifies a string to append to the regular version string to identify
OS- or site-specific modifications.
The default is
-.Dq FreeBSD-20100308 .
+.Dq FreeBSD-20100428 .
.It Cm X11DisplayOffset
Specifies the first display number available for
.Xr sshd 8 Ns 's
diff --git a/crypto/openssh/version.h b/crypto/openssh/version.h
index d1d1452..6cc8d84 100644
--- a/crypto/openssh/version.h
+++ b/crypto/openssh/version.h
@@ -1,12 +1,12 @@
-/* $OpenBSD: version.h,v 1.57 2010/03/07 22:01:32 djm Exp $ */
+/* $OpenBSD: version.h,v 1.58 2010/03/16 16:36:49 djm Exp $ */
/* $FreeBSD$ */
#ifndef SSH_VERSION
#define SSH_VERSION (ssh_version_get())
#define SSH_RELEASE (ssh_version_get())
-#define SSH_VERSION_BASE "OpenSSH_5.4p1"
-#define SSH_VERSION_ADDENDUM "FreeBSD-20100308"
+#define SSH_VERSION_BASE "OpenSSH_5.5p1"
+#define SSH_VERSION_ADDENDUM "FreeBSD-20100428"
const char *ssh_version_get(void);
void ssh_version_set_addendum(const char *);
diff --git a/etc/network.subr b/etc/network.subr
index 52c99db..d0b309a 100644
--- a/etc/network.subr
+++ b/etc/network.subr
@@ -399,6 +399,8 @@ ipv6if()
$_if|"$_if "*|*" $_if"|*" $_if "*|[Aa][Uu][Tt][Oo])
# True if $ifconfig_IF_ipv6 is defined.
_tmpargs=`_ifconfig_getargs $_if ipv6`
+ # Also true if ipv6_prefix_IF is defined
+ [ -n "$_tmpargs" ] || _tmpargs=`get_if_var $_if ipv6_prefix_IF`
;;
esac
diff --git a/etc/rc.d/named b/etc/rc.d/named
index 346b6fc..81db646 100755
--- a/etc/rc.d/named
+++ b/etc/rc.d/named
@@ -192,6 +192,13 @@ named_prestart()
$confgen_command
fi
+ local checkconf
+
+ checkconf="${command%/named}/named-checkconf"
+ if ! checkyesno named_chroot_autoupdate && [ -n "$named_chrootdir" ]; then
+ checkconf="$checkconf -t $named_chrootdir"
+ fi
+
# Create a forwarder configuration based on /etc/resolv.conf
if checkyesno named_auto_forward; then
if [ ! -s /etc/resolv.conf ]; then
@@ -201,7 +208,7 @@ named_prestart()
[ -s "${named_confdir}/auto_forward.conf" ] &&
create_file ${named_confdir}/auto_forward.conf
- ${command%/named}/named-checkconf $named_conf ||
+ $checkconf $named_conf ||
err 3 'named-checkconf for $named_conf failed'
return
fi
@@ -263,8 +270,7 @@ named_prestart()
create_file ${named_confdir}/auto_forward.conf
fi
- ${command%/named}/named-checkconf $named_conf ||
- err 3 'named-checkconf for $named_conf failed'
+ $checkconf $named_conf || err 3 'named-checkconf for $named_conf failed'
}
load_rc_config $name
@@ -272,7 +278,7 @@ load_rc_config $name
# Updating the following variables requires that rc.conf be loaded first
#
required_dirs="$named_chrootdir" # if it is set, it must exist
-required_files="${named_conf:=/etc/namedb/named.conf}"
+
pidfile="${named_pidfile:-/var/run/named/pid}"
named_confdir="${named_chrootdir}${named_conf%/*}"
diff --git a/gnu/usr.bin/groff/tmac/mdoc.local b/gnu/usr.bin/groff/tmac/mdoc.local
index 4c83635..a3073ff 100644
--- a/gnu/usr.bin/groff/tmac/mdoc.local
+++ b/gnu/usr.bin/groff/tmac/mdoc.local
@@ -75,6 +75,7 @@
.ds doc-operating-system-FreeBSD-7.2 7.2
.ds doc-operating-system-FreeBSD-7.3 7.3
.ds doc-operating-system-FreeBSD-8.0 8.0
+.ds doc-operating-system-FreeBSD-8.1 8.1
.ds doc-operating-system-FreeBSD-9.0 9.0
.
.\" Definitions not (yet) in doc-syms
diff --git a/lib/libc/sys/getrusage.2 b/lib/libc/sys/getrusage.2
index bdf5d45..423503f 100644
--- a/lib/libc/sys/getrusage.2
+++ b/lib/libc/sys/getrusage.2
@@ -28,7 +28,7 @@
.\" @(#)getrusage.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd June 4, 1993
+.Dd May 1, 2010
.Dt GETRUSAGE 2
.Os
.Sh NAME
@@ -42,6 +42,7 @@
.In sys/resource.h
.Fd "#define RUSAGE_SELF 0"
.Fd "#define RUSAGE_CHILDREN -1"
+.Fd "#define RUSAGE_THREAD 1"
.Ft int
.Fn getrusage "int who" "struct rusage *rusage"
.Sh DESCRIPTION
@@ -49,11 +50,12 @@ The
.Fn getrusage
system call
returns information describing the resources utilized by the current
-process, or all its terminated child processes.
+thread, the current process, or all its terminated child processes.
The
.Fa who
argument is either
-.Dv RUSAGE_SELF
+.Dv RUSAGE_THREAD ,
+.Dv RUSAGE_SELF ,
or
.Dv RUSAGE_CHILDREN .
The buffer to which
@@ -175,6 +177,10 @@ The
.Fn getrusage
system call appeared in
.Bx 4.2 .
+The
+.Dv RUSAGE_THREAD
+facility first appeared in
+.Fx 8.1 .
.Sh BUGS
There is no way to obtain information about a child process
that has not yet terminated.
diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.8 b/lib/libpam/modules/pam_krb5/pam_krb5.8
index 3e0db91..bd7ac5b 100644
--- a/lib/libpam/modules/pam_krb5/pam_krb5.8
+++ b/lib/libpam/modules/pam_krb5/pam_krb5.8
@@ -1,7 +1,7 @@
.\"
.\" $Id: pam_krb5.5,v 1.5 2000/01/05 00:59:56 fcusack Exp $
.\" $FreeBSD$
-.Dd January 15, 1999
+.Dd May 3, 2010
.Dt PAM_KRB5 8
.Os
.Sh NAME
@@ -108,6 +108,10 @@ and
.Ql %p ,
to designate the current process ID; can be used in
.Ar name .
+.It Cm no_user_check
+Do not verify if a user exists on the local system. This option implies the
+.Cm no_ccache
+option because there is no secure local uid/gid for the cache file.
.El
.Ss Kerberos 5 Account Management Module
The Kerberos 5 account management component
diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.c b/lib/libpam/modules/pam_krb5/pam_krb5.c
index b56e0a3..439fcf9 100644
--- a/lib/libpam/modules/pam_krb5/pam_krb5.c
+++ b/lib/libpam/modules/pam_krb5/pam_krb5.c
@@ -89,6 +89,7 @@ static void compat_free_data_contents(krb5_context, krb5_data *);
#define PAM_OPT_DEBUG "debug"
#define PAM_OPT_FORWARDABLE "forwardable"
#define PAM_OPT_NO_CCACHE "no_ccache"
+#define PAM_OPT_NO_USER_CHECK "no_user_check"
#define PAM_OPT_REUSE_CCACHE "reuse_ccache"
/*
@@ -194,34 +195,39 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
PAM_LOG("Got password");
- /* Verify the local user exists (AFTER getting the password) */
- if (strchr(user, '@')) {
- /* get a local account name for this principal */
- krbret = krb5_aname_to_localname(pam_context, princ,
- sizeof(luser), luser);
- if (krbret != 0) {
- PAM_VERBOSE_ERROR("Kerberos 5 error");
- PAM_LOG("Error krb5_aname_to_localname(): %s",
- krb5_get_err_text(pam_context, krbret));
- retval = PAM_USER_UNKNOWN;
- goto cleanup2;
+ if (openpam_get_option(pamh, PAM_OPT_NO_USER_CHECK))
+ PAM_LOG("Skipping local user check");
+ else {
+
+ /* Verify the local user exists (AFTER getting the password) */
+ if (strchr(user, '@')) {
+ /* get a local account name for this principal */
+ krbret = krb5_aname_to_localname(pam_context, princ,
+ sizeof(luser), luser);
+ if (krbret != 0) {
+ PAM_VERBOSE_ERROR("Kerberos 5 error");
+ PAM_LOG("Error krb5_aname_to_localname(): %s",
+ krb5_get_err_text(pam_context, krbret));
+ retval = PAM_USER_UNKNOWN;
+ goto cleanup2;
+ }
+
+ retval = pam_set_item(pamh, PAM_USER, luser);
+ if (retval != PAM_SUCCESS)
+ goto cleanup2;
+
+ PAM_LOG("PAM_USER Redone");
}
- retval = pam_set_item(pamh, PAM_USER, luser);
- if (retval != PAM_SUCCESS)
+ pwd = getpwnam(user);
+ if (pwd == NULL) {
+ retval = PAM_USER_UNKNOWN;
goto cleanup2;
+ }
- PAM_LOG("PAM_USER Redone");
- }
-
- pwd = getpwnam(user);
- if (pwd == NULL) {
- retval = PAM_USER_UNKNOWN;
- goto cleanup2;
+ PAM_LOG("Done getpwnam()");
}
- PAM_LOG("Done getpwnam()");
-
/* Get a TGT */
memset(&creds, 0, sizeof(krb5_creds));
krbret = krb5_get_init_creds_password(pam_context, &creds, princ,
@@ -366,7 +372,8 @@ pam_sm_setcred(pam_handle_t *pamh, int flags,
return (PAM_SERVICE_ERR);
/* If a persistent cache isn't desired, stop now. */
- if (openpam_get_option(pamh, PAM_OPT_NO_CCACHE))
+ if (openpam_get_option(pamh, PAM_OPT_NO_CCACHE) ||
+ openpam_get_option(pamh, PAM_OPT_NO_USER_CHECK))
return (PAM_SUCCESS);
PAM_LOG("Establishing credentials");
diff --git a/lib/libpmc/libpmc.c b/lib/libpmc/libpmc.c
index c440aa8..8922dd8 100644
--- a/lib/libpmc/libpmc.c
+++ b/lib/libpmc/libpmc.c
@@ -737,9 +737,16 @@ iap_allocate_pmc(enum pmc_event pe, char *ctrspec,
case PMC_EV_IAP_EVENT_40H: /* Core */
case PMC_EV_IAP_EVENT_41H: /* Core */
case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */
- case PMC_EV_IAP_EVENT_77H: /* Core */
if (cachestate == 0)
cachestate = (0xF << 8);
+ break;
+ case PMC_EV_IAP_EVENT_77H: /* Atom */
+ /* IAP_EVENT_77H only accepts a cachestate qualifier on the
+ * Atom processor
+ */
+ if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0)
+ cachestate = (0xF << 8);
+ break;
default:
break;
}
diff --git a/lib/libufs/cgroup.c b/lib/libufs/cgroup.c
index b0cb4a7..8ab33f7 100644
--- a/lib/libufs/cgroup.c
+++ b/lib/libufs/cgroup.c
@@ -145,7 +145,7 @@ cgialloc(struct uufsd *disk)
fs = &disk->d_fs;
cgp = &disk->d_cg;
inosused = cg_inosused(cgp);
- for (ino = 0; ino < fs->fs_ipg / NBBY; ino++)
+ for (ino = 0; ino < fs->fs_ipg; ino++)
if (isclr(inosused, ino))
goto gotit;
return (0);
diff --git a/libexec/tftpd/Makefile b/libexec/tftpd/Makefile
index 6c29243..b9db2a9 100644
--- a/libexec/tftpd/Makefile
+++ b/libexec/tftpd/Makefile
@@ -2,15 +2,14 @@
# $FreeBSD$
PROG= tftpd
-SRCS= tftpd.c tftpsubs.c
-DPADD= ${LIBUTIL}
-LDADD= -lutil
-
-WARNS?= 1
+SRCS= tftpd.c tftp-io.c tftp-utils.c tftp-file.c tftp-transfer.c tftp-options.c
+WARNS= 3
WFORMAT=0
-
MAN= tftpd.8
-CFLAGS+=-I${.CURDIR}/../../usr.bin/tftp
+CFLAGS=-g -Wall
+CFLAGS+=-I${.CURDIR}/../../usr.bin/tftp -I${.CURDIR}/../../libexec/tftpd
.PATH: ${.CURDIR}/../../usr.bin/tftp
+COPTFLAGS = -O
+LDFLAGS= -lwrap
.include <bsd.prog.mk>
diff --git a/libexec/tftpd/tftp-file.c b/libexec/tftpd/tftp-file.c
new file mode 100644
index 0000000..e0f8e78
--- /dev/null
+++ b/libexec/tftpd/tftp-file.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2008 Edwin Groothuis. 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 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/types.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/tftp.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "tftp-file.h"
+#include "tftp-utils.h"
+
+static FILE *file;
+static int convert;
+
+static char convbuffer[66000];
+static int gotcr = 0;
+
+static size_t
+convert_from_net(char *buffer, size_t count)
+{
+ size_t i, n;
+
+ /*
+ * Convert all CR/LF to LF and all CR,NUL to CR
+ */
+
+ n = 0;
+ for (i = 0; i < count; i++) {
+
+ if (gotcr == 0) {
+ convbuffer[n++] = buffer[i];
+ gotcr = (buffer[i] == '\r');
+ continue;
+ }
+
+ /* CR, NULL -> CR */
+ if (buffer[i] == '\0') {
+ gotcr = 0;
+ continue;
+ }
+
+ /* CR, LF -> LF */
+ if (buffer[i] == '\n') {
+ if (n == 0) {
+ if (ftell(file) != 0) {
+ fseek(file, -1, SEEK_END);
+ convbuffer[n++] = '\n';
+ } else {
+ /* This shouldn't happen */
+ tftp_log(LOG_ERR,
+ "Received LF as first character");
+ abort();
+ }
+ } else
+ convbuffer[n-1] = '\n';
+ gotcr = 0;
+ continue;
+ }
+
+ /* Everything else just accept as is */
+ convbuffer[n++] = buffer[i];
+ gotcr = (buffer[i] == '\r');
+ continue;
+ }
+
+ return fwrite(convbuffer, 1, n, file);
+}
+
+static size_t
+convert_to_net(char *buffer, size_t count, int init)
+{
+ size_t i;
+ static size_t n = 0, read = 0;
+ static int newline = 0;
+
+ if (init) {
+ newline = 0;
+ n = 0;
+ read = 0;
+ return 0 ;
+ }
+
+ /*
+ * Convert all LF to CR,LF and all CR to CR,NUL
+ */
+ i = 0;
+
+ if (newline) {
+ buffer[i++] = newline;
+ newline = 0;
+ }
+
+ while (i < count) {
+ if (n == read) {
+ /* When done we're done */
+ if (feof(file)) break;
+
+ /* Otherwise read another bunch */
+ read = fread(convbuffer, 1, count, file);
+ if (read == 0) break;
+ n = 0;
+ }
+
+ /* CR -> CR,NULL */
+ if (convbuffer[n] == '\r') {
+ buffer[i++] = '\r';
+ buffer[i++] = '\0';
+ n++;
+ continue;
+ }
+
+ /* LF -> CR,LF */
+ if (convbuffer[n] == '\n') {
+ buffer[i++] = '\r';
+ buffer[i++] = '\n';
+ n++;
+ continue;
+ }
+
+ buffer[i++] = convbuffer[n++];
+ }
+
+ if (i > count) {
+ /*
+ * Whoops... that isn't alllowed (but it will happen
+ * when there is a CR or LF at the end of the buffer)
+ */
+ newline = buffer[i-1];
+ }
+
+ if (i < count) {
+ /* We are done! */
+ return i;
+ } else
+ return count;
+
+}
+
+int
+write_init(int fd, FILE *f, const char *mode)
+{
+
+ if (f == NULL) {
+ file = fdopen(fd, "w");
+ if (file == NULL) {
+ int en = errno;
+ tftp_log(LOG_ERR, "fdopen() failed: %s",
+ strerror(errno));
+ return en;
+ }
+ } else
+ file = f;
+ convert = !strcmp(mode, "netascii");
+ return 0;
+}
+
+size_t
+write_file(char *buffer, int count)
+{
+
+ if (convert == 0)
+ return fwrite(buffer, 1, count, file);
+
+ return convert_from_net(buffer, count);
+}
+
+int
+write_close(void)
+{
+
+ if (fclose(file) != 0) {
+ tftp_log(LOG_ERR, "fclose() failed: %s", strerror(errno));
+ return 1;
+ }
+ return 0;
+}
+
+int
+read_init(int fd, FILE *f, const char *mode)
+{
+
+ convert_to_net(NULL, 0, 1);
+ if (f == NULL) {
+ file = fdopen(fd, "r");
+ if (file == NULL) {
+ int en = errno;
+ tftp_log(LOG_ERR, "fdopen() failed: %s",
+ strerror(errno));
+ return en;
+ }
+ } else
+ file = f;
+ convert = !strcmp(mode, "netascii");
+ return 0;
+}
+
+size_t
+read_file(char *buffer, int count)
+{
+
+ if (convert == 0)
+ return fread(buffer, 1, count, file);
+
+ return convert_to_net(buffer, count, 0);
+}
+
+int
+read_close(void)
+{
+
+ if (fclose(file) != 0) {
+ tftp_log(LOG_ERR, "fclose() failed: %s", strerror(errno));
+ return 1;
+ }
+ return 0;
+}
+
+
+int
+synchnet(int peer)
+{
+
+ return 0;
+}
diff --git a/libexec/tftpd/tftp-file.h b/libexec/tftpd/tftp-file.h
new file mode 100644
index 0000000..fcc4d0d
--- /dev/null
+++ b/libexec/tftpd/tftp-file.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 Edwin Groothuis. 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 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$");
+
+int write_init(int fd, FILE *f, const char *mode);
+size_t write_file(char *buffer, int count);
+int write_close(void);
+
+int read_init(int fd, FILE *f, const char *mode);
+size_t read_file(char *buffer, int count);
+int read_close(void);
+
+int synchnet(int peer);
diff --git a/libexec/tftpd/tftp-io.c b/libexec/tftpd/tftp-io.c
new file mode 100644
index 0000000..28628ba
--- /dev/null
+++ b/libexec/tftpd/tftp-io.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2008 Edwin Groothuis. 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 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/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/tftp.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "tftp-file.h"
+#include "tftp-io.h"
+#include "tftp-utils.h"
+#include "tftp-options.h"
+
+struct sockaddr_storage peer_sock;
+struct sockaddr_storage me_sock;
+
+static int send_packet(int peer, uint16_t block, char *pkt, int size);
+
+struct errmsg {
+ int e_code;
+ const char *e_msg;
+} errmsgs[] = {
+ { EUNDEF, "Undefined error code" },
+ { ENOTFOUND, "File not found" },
+ { EACCESS, "Access violation" },
+ { ENOSPACE, "Disk full or allocation exceeded" },
+ { EBADOP, "Illegal TFTP operation" },
+ { EBADID, "Unknown transfer ID" },
+ { EEXISTS, "File already exists" },
+ { ENOUSER, "No such user" },
+ { EOPTNEG, "Option negotiation" },
+ { -1, NULL }
+};
+
+#define DROPPACKET(s) \
+ if (packetdroppercentage != 0 && \
+ random()%100 < packetdroppercentage) { \
+ tftp_log(LOG_DEBUG, "Artifical packet drop in %s", s); \
+ return; \
+ }
+#define DROPPACKETn(s,n) \
+ if (packetdroppercentage != 0 && \
+ random()%100 < packetdroppercentage) { \
+ tftp_log(LOG_DEBUG, "Artifical packet drop in %s", s); \
+ return (n); \
+ }
+
+const char *
+errtomsg(int error)
+{
+ static char ebuf[40];
+ struct errmsg *pe;
+ char buf[MAXPKTSIZE];
+
+ if (error == 0)
+ return ("success");
+ for (pe = errmsgs; pe->e_code >= 0; pe++)
+ if (pe->e_code == error)
+ return (pe->e_msg);
+ snprintf(ebuf, sizeof(buf), "error %d", error);
+ return (ebuf);
+}
+
+static int
+send_packet(int peer, uint16_t block, char *pkt, int size)
+{
+ int i;
+ int t = 1;
+
+ for (i = 0; i < 12 ; i++) {
+ DROPPACKETn("send_packet", 0);
+
+ if (sendto(peer, pkt, size, 0,
+ (struct sockaddr *)&peer_sock, peer_sock.ss_len)
+ == size) {
+ if (i)
+ tftp_log(LOG_ERR,
+ "%s block %d, attempt %d successful",
+ block, i);
+ return (0);
+ }
+ tftp_log(LOG_ERR,
+ "%s block %d, attempt %d failed (Error %d: %s)",
+ packettype(ntohs(((struct tftphdr *)(pkt))->th_opcode)),
+ block, i, errno, strerror(errno));
+ sleep(t);
+ if (t < 32)
+ t <<= 1;
+ }
+ tftp_log(LOG_ERR, "send_packet: %s", strerror(errno));
+ return (1);
+}
+
+/*
+ * Send an ERROR packet (error message).
+ * Error code passed in is one of the
+ * standard TFTP codes, or a UNIX errno
+ * offset by 100.
+ */
+void
+send_error(int peer, int error)
+{
+ struct tftphdr *tp;
+ int length;
+ struct errmsg *pe;
+ char buf[MAXPKTSIZE];
+
+ if (debug&DEBUG_PACKETS)
+ tftp_log(LOG_DEBUG, "Sending ERROR %d: %s", error);
+
+ DROPPACKET("send_error");
+
+ tp = (struct tftphdr *)buf;
+ tp->th_opcode = htons((u_short)ERROR);
+ tp->th_code = htons((u_short)error);
+ for (pe = errmsgs; pe->e_code >= 0; pe++)
+ if (pe->e_code == error)
+ break;
+ if (pe->e_code < 0) {
+ pe->e_msg = strerror(error - 100);
+ tp->th_code = EUNDEF; /* set 'undef' errorcode */
+ }
+ strcpy(tp->th_msg, pe->e_msg);
+ length = strlen(pe->e_msg);
+ tp->th_msg[length] = '\0';
+ length += 5;
+
+ if (debug&DEBUG_PACKETS)
+ tftp_log(LOG_DEBUG, "Sending ERROR %d: %s", error, tp->th_msg);
+
+ if (sendto(peer, buf, length, 0,
+ (struct sockaddr *)&peer_sock, peer_sock.ss_len) != length)
+ tftp_log(LOG_ERR, "send_error: %s", strerror(errno));
+}
+
+/*
+ * Send an WRQ packet (write request).
+ */
+int
+send_wrq(int peer, char *filename, char *mode)
+{
+ int n;
+ struct tftphdr *tp;
+ char *bp;
+ char buf[MAXPKTSIZE];
+ int size;
+
+ if (debug&DEBUG_PACKETS)
+ tftp_log(LOG_DEBUG, "Sending WRQ: filename: '%s', mode '%s'",
+ filename, mode
+ );
+
+ DROPPACKETn("send_wrq", 1);
+
+ tp = (struct tftphdr *)buf;
+ tp->th_opcode = htons((u_short)WRQ);
+ size = 2;
+
+ bp = tp->th_stuff;
+ strcpy(bp, filename);
+ bp += strlen(filename);
+ *bp = 0;
+ bp++;
+ size += strlen(filename) + 1;
+
+ strcpy(bp, mode);
+ bp += strlen(mode);
+ *bp = 0;
+ bp++;
+ size += strlen(mode) + 1;
+
+ if (options_rfc_enabled)
+ size += make_options(peer, bp, sizeof(buf) - size);
+
+ n = sendto(peer, buf, size, 0,
+ (struct sockaddr *)&peer_sock, peer_sock.ss_len);
+ if (n != size) {
+ tftp_log(LOG_ERR, "send_wrq: %s", strerror(errno));
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Send an RRQ packet (write request).
+ */
+int
+send_rrq(int peer, char *filename, char *mode)
+{
+ int n;
+ struct tftphdr *tp;
+ char *bp;
+ char buf[MAXPKTSIZE];
+ int size;
+
+ if (debug&DEBUG_PACKETS)
+ tftp_log(LOG_DEBUG, "Sending RRQ: filename: '%s', mode '%s'",
+ filename, mode
+ );
+
+ DROPPACKETn("send_rrq", 1);
+
+ tp = (struct tftphdr *)buf;
+ tp->th_opcode = htons((u_short)RRQ);
+ size = 2;
+
+ bp = tp->th_stuff;
+ strcpy(bp, filename);
+ bp += strlen(filename);
+ *bp = 0;
+ bp++;
+ size += strlen(filename) + 1;
+
+ strcpy(bp, mode);
+ bp += strlen(mode);
+ *bp = 0;
+ bp++;
+ size += strlen(mode) + 1;
+
+ if (options_rfc_enabled) {
+ options[OPT_TSIZE].o_request = strdup("0");
+ size += make_options(peer, bp, sizeof(buf) - size);
+ }
+
+ n = sendto(peer, buf, size, 0,
+ (struct sockaddr *)&peer_sock, peer_sock.ss_len);
+ if (n != size) {
+ tftp_log(LOG_ERR, "send_rrq: %s", n, strerror(errno));
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Send an OACK packet (option acknowledgement).
+ */
+int
+send_oack(int peer)
+{
+ struct tftphdr *tp;
+ int size, i, n;
+ char *bp;
+ char buf[MAXPKTSIZE];
+
+ if (debug&DEBUG_PACKETS)
+ tftp_log(LOG_DEBUG, "Sending OACK");
+
+ DROPPACKETn("send_oack", 0);
+
+ /*
+ * Send back an options acknowledgement (only the ones with
+ * a reply for)
+ */
+ tp = (struct tftphdr *)buf;
+ bp = buf + 2;
+ size = sizeof(buf) - 2;
+ tp->th_opcode = htons((u_short)OACK);
+ for (i = 0; options[i].o_type != NULL; i++) {
+ if (options[i].o_reply != NULL) {
+ n = snprintf(bp, size, "%s%c%s", options[i].o_type,
+ 0, options[i].o_reply);
+ bp += n+1;
+ size -= n+1;
+ if (size < 0) {
+ tftp_log(LOG_ERR, "oack: buffer overflow");
+ exit(1);
+ }
+ }
+ }
+ size = bp - buf;
+
+ if (sendto(peer, buf, size, 0,
+ (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) {
+ tftp_log(LOG_INFO, "send_oack: %s", strerror(errno));
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * Send an ACK packet (acknowledgement).
+ */
+int
+send_ack(int fp, uint16_t block)
+{
+ struct tftphdr *tp;
+ int size;
+ char *bp;
+ char buf[MAXPKTSIZE];
+
+ if (debug&DEBUG_PACKETS)
+ tftp_log(LOG_DEBUG, "Sending ACK for block %d", block);
+
+ DROPPACKETn("send_ack", 0);
+
+ tp = (struct tftphdr *)buf;
+ bp = buf + 2;
+ size = sizeof(buf) - 2;
+ tp->th_opcode = htons((u_short)ACK);
+ tp->th_block = htons((u_short)block);
+ size = 4;
+
+ if (sendto(fp, buf, size, 0,
+ (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) {
+ tftp_log(LOG_INFO, "send_ack: %s", strerror(errno));
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * Send a DATA packet
+ */
+int
+send_data(int peer, uint16_t block, char *data, int size)
+{
+ char buf[MAXPKTSIZE];
+ struct tftphdr *pkt;
+ int n;
+
+ if (debug&DEBUG_PACKETS)
+ tftp_log(LOG_DEBUG, "Sending DATA packet %d of %d bytes",
+ block, size);
+
+ DROPPACKETn("send_data", 0);
+
+ pkt = (struct tftphdr *)buf;
+
+ pkt->th_opcode = htons((u_short)DATA);
+ pkt->th_block = htons((u_short)block);
+ memcpy(pkt->th_data, data, size);
+
+ n = send_packet(peer, block, (char *)pkt, size + 4);
+ return (n);
+}
+
+
+/*
+ * Receive a packet
+ */
+jmp_buf timeoutbuf;
+
+static void
+timeout(int sig __unused)
+{
+
+ /* tftp_log(LOG_DEBUG, "Timeout\n"); Inside a signal handler... */
+ longjmp(timeoutbuf, 1);
+}
+
+int
+receive_packet(int peer, char *data, int size, struct sockaddr_storage *from,
+ int thistimeout)
+{
+ struct tftphdr *pkt;
+ struct sockaddr_storage from_local;
+ struct sockaddr_storage *pfrom;
+ socklen_t fromlen;
+ int n;
+ static int waiting;
+
+ pfrom = (from == NULL) ? &from_local : from;
+
+ if (debug&DEBUG_PACKETS)
+ tftp_log(LOG_DEBUG,
+ "Waiting %d seconds for packet", timeoutpacket);
+
+ pkt = (struct tftphdr *)data;
+
+ waiting = 0;
+ signal(SIGALRM, timeout);
+ setjmp(timeoutbuf);
+ alarm(thistimeout);
+
+ if (waiting > 0) {
+ alarm(0);
+ return (RP_TIMEOUT);
+ }
+
+ if (waiting > 0) {
+ tftp_log(LOG_ERR, "receive_packet: timeout");
+ alarm(0);
+ return (RP_TIMEOUT);
+ }
+
+ waiting++;
+ fromlen = sizeof(*pfrom);
+ n = recvfrom(peer, data, size, 0, (struct sockaddr *)pfrom, &fromlen);
+
+ alarm(0);
+
+ DROPPACKETn("receive_packet", RP_TIMEOUT);
+
+ if (n < 0) {
+ tftp_log(LOG_ERR, "receive_packet: timeout");
+ return (RP_TIMEOUT);
+ }
+
+ alarm(0);
+
+ if (n < 0) {
+ /* No idea what could have happened if it isn't a timeout */
+ tftp_log(LOG_ERR, "receive_packet: %s", strerror(errno));
+ return (RP_RECVFROM);
+ }
+ if (n < 4) {
+ tftp_log(LOG_ERR,
+ "receive_packet: packet too small (%d bytes)", n);
+ return (RP_TOOSMALL);
+ }
+
+ pkt->th_opcode = ntohs((u_short)pkt->th_opcode);
+ if (pkt->th_opcode == DATA ||
+ pkt->th_opcode == ACK)
+ pkt->th_block = ntohs((u_short)pkt->th_block);
+
+ if (pkt->th_opcode == DATA && n > pktsize) {
+ tftp_log(LOG_ERR, "receive_packet: packet too big");
+ return (RP_TOOBIG);
+ }
+
+ if (((struct sockaddr_in *)(pfrom))->sin_addr.s_addr !=
+ ((struct sockaddr_in *)(&peer_sock))->sin_addr.s_addr) {
+ tftp_log(LOG_ERR,
+ "receive_packet: received packet from wrong source");
+ return (RP_WRONGSOURCE);
+ }
+
+ if (pkt->th_opcode == ERROR) {
+ tftp_log(LOG_ERR, "Got ERROR packet: %s", pkt->th_msg);
+ return (RP_ERROR);
+ }
+
+ if (debug&DEBUG_PACKETS)
+ tftp_log(LOG_DEBUG, "Received %d bytes in a %s packet",
+ n, packettype(pkt->th_opcode));
+
+ return n - 4;
+}
diff --git a/libexec/tftpd/tftp-io.h b/libexec/tftpd/tftp-io.h
new file mode 100644
index 0000000..70558bc
--- /dev/null
+++ b/libexec/tftpd/tftp-io.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008 Edwin Groothuis. 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 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$");
+
+#define RP_NONE 0
+#define RP_RECVFROM -1
+#define RP_TOOSMALL -2
+#define RP_ERROR -3
+#define RP_WRONGSOURCE -4
+#define RP_TIMEOUT -5
+#define RP_TOOBIG -6
+
+const char *errtomsg(int);
+void send_error(int peer, int);
+int send_wrq(int peer, char *, char *);
+int send_rrq(int peer, char *, char *);
+int send_oack(int peer);
+int send_ack(int peer, unsigned short);
+int send_data(int peer, uint16_t, char *, int);
+int receive_packet(int peer, char *, int, struct sockaddr_storage *, int);
+
+extern struct sockaddr_storage peer_sock;
+extern struct sockaddr_storage me_sock;
diff --git a/libexec/tftpd/tftp-options.c b/libexec/tftpd/tftp-options.c
new file mode 100644
index 0000000..0b97aaf
--- /dev/null
+++ b/libexec/tftpd/tftp-options.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2008 Edwin Groothuis. 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 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/socket.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/tftp.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "tftp-utils.h"
+#include "tftp-io.h"
+#include "tftp-options.h"
+
+/*
+ * Option handlers
+ */
+
+struct options options[] = {
+ { "tsize", NULL, NULL, NULL /* option_tsize */, 1 },
+ { "timeout", NULL, NULL, option_timeout, 1 },
+ { "blksize", NULL, NULL, option_blksize, 1 },
+ { "blksize2", NULL, NULL, option_blksize2, 0 },
+ { "rollover", NULL, NULL, option_rollover, 0 },
+ { NULL, NULL, NULL, NULL, 0 }
+};
+
+/* By default allow them */
+int options_rfc_enabled = 1;
+int options_extra_enabled = 1;
+
+/*
+ * Rules for the option handlers:
+ * - If there is no o_request, there will be no processing.
+ *
+ * For servers
+ * - Logging is done as warnings.
+ * - The handler exit()s if there is a serious problem with the
+ * values submitted in the option.
+ *
+ * For clients
+ * - Logging is done as errors. After all, the server shouldn't
+ * return rubbish.
+ * - The handler returns if there is a serious problem with the
+ * values submitted in the option.
+ * - Sending the EBADOP packets is done by the handler.
+ */
+
+int
+option_tsize(int peer, struct tftphdr *tp, int mode, struct stat *stbuf)
+{
+
+ if (options[OPT_TSIZE].o_request == NULL)
+ return (0);
+
+ if (mode == RRQ)
+ asprintf(&options[OPT_TSIZE].o_reply,
+ "%ju", stbuf->st_size);
+ else
+ /* XXX Allows writes of all sizes. */
+ options[OPT_TSIZE].o_reply =
+ strdup(options[OPT_TSIZE].o_request);
+ return (0);
+}
+
+int
+option_timeout(int peer)
+{
+
+ if (options[OPT_TIMEOUT].o_request == NULL)
+ return (0);
+
+ int to = atoi(options[OPT_TIMEOUT].o_request);
+ if (to < TIMEOUT_MIN || to > TIMEOUT_MAX) {
+ tftp_log(acting_as_client ? LOG_ERR : LOG_WARNING,
+ "Received bad value for timeout. "
+ "Should be between %d and %d, received %s",
+ TIMEOUT_MIN, TIMEOUT_MAX);
+ send_error(peer, EBADOP);
+ if (acting_as_client)
+ return (1);
+ exit(1);
+ } else {
+ timeoutpacket = to;
+ options[OPT_TIMEOUT].o_reply =
+ strdup(options[OPT_TIMEOUT].o_request);
+ }
+ settimeouts(timeoutpacket, timeoutnetwork, maxtimeouts);
+
+ if (debug&DEBUG_OPTIONS)
+ tftp_log(LOG_DEBUG, "Setting timeout to '%s'",
+ options[OPT_TIMEOUT].o_reply);
+
+ return (0);
+}
+
+int
+option_rollover(int peer)
+{
+
+ if (options[OPT_ROLLOVER].o_request == NULL)
+ return (0);
+
+ if (strcmp(options[OPT_ROLLOVER].o_request, "0") != 0
+ && strcmp(options[OPT_ROLLOVER].o_request, "1") != 0) {
+ tftp_log(acting_as_client ? LOG_ERR : LOG_WARNING,
+ "Bad value for rollover, "
+ "should be either 0 or 1, received '%s', "
+ "ignoring request",
+ options[OPT_ROLLOVER].o_request);
+ if (acting_as_client) {
+ send_error(peer, EBADOP);
+ return (1);
+ }
+ return (0);
+ }
+ options[OPT_ROLLOVER].o_reply =
+ strdup(options[OPT_ROLLOVER].o_request);
+
+ if (debug&DEBUG_OPTIONS)
+ tftp_log(LOG_DEBUG, "Setting rollover to '%s'",
+ options[OPT_ROLLOVER].o_reply);
+
+ return (0);
+}
+
+int
+option_blksize(int peer)
+{
+ int *maxdgram;
+ char maxbuffer[100];
+ size_t len;
+
+ if (options[OPT_BLKSIZE].o_request == NULL)
+ return (0);
+
+ /* maximum size of an UDP packet according to the system */
+ len = sizeof(maxbuffer);
+ if (sysctlbyname("net.inet.udp.maxdgram",
+ maxbuffer, &len, NULL, 0) < 0) {
+ tftp_log(LOG_ERR, "sysctl: net.inet.udp.maxdgram");
+ return (acting_as_client ? 1 : 0);
+ }
+ maxdgram = (int *)maxbuffer;
+
+ int size = atoi(options[OPT_BLKSIZE].o_request);
+ if (size < BLKSIZE_MIN || size > BLKSIZE_MAX) {
+ if (acting_as_client) {
+ tftp_log(LOG_ERR,
+ "Invalid blocksize (%d bytes), aborting",
+ size);
+ send_error(peer, EBADOP);
+ return (1);
+ } else {
+ tftp_log(LOG_WARNING,
+ "Invalid blocksize (%d bytes), ignoring request",
+ size);
+ return (0);
+ }
+ }
+
+ if (size > *maxdgram) {
+ if (acting_as_client) {
+ tftp_log(LOG_ERR,
+ "Invalid blocksize (%d bytes), "
+ "net.inet.udp.maxdgram sysctl limits it to "
+ "%d bytes.\n", size, *maxdgram);
+ send_error(peer, EBADOP);
+ return (1);
+ } else {
+ tftp_log(LOG_WARNING,
+ "Invalid blocksize (%d bytes), "
+ "net.inet.udp.maxdgram sysctl limits it to "
+ "%d bytes.\n", size, *maxdgram);
+ size = *maxdgram;
+ /* No reason to return */
+ }
+ }
+
+ asprintf(&options[OPT_BLKSIZE].o_reply, "%d", size);
+ segsize = size;
+ pktsize = size + 4;
+ if (debug&DEBUG_OPTIONS)
+ tftp_log(LOG_DEBUG, "Setting blksize to '%s'",
+ options[OPT_BLKSIZE].o_reply);
+
+ return (0);
+}
+
+int
+option_blksize2(int peer)
+{
+ int *maxdgram;
+ char maxbuffer[100];
+ int size, i;
+ size_t len;
+
+ int sizes[] = {
+ 8, 16, 32, 64, 128, 256, 512, 1024,
+ 2048, 4096, 8192, 16384, 32768, 0
+ };
+
+ if (options[OPT_BLKSIZE2].o_request == NULL)
+ return (0);
+
+ /* maximum size of an UDP packet according to the system */
+ len = sizeof(maxbuffer);
+ if (sysctlbyname("net.inet.udp.maxdgram",
+ maxbuffer, &len, NULL, 0) < 0) {
+ tftp_log(LOG_ERR, "sysctl: net.inet.udp.maxdgram");
+ return (acting_as_client ? 1 : 0);
+ }
+ maxdgram = (int *)maxbuffer;
+
+ size = atoi(options[OPT_BLKSIZE2].o_request);
+ for (i = 0; sizes[i] != 0; i++) {
+ if (size == sizes[i]) break;
+ }
+ if (sizes[i] == 0) {
+ tftp_log(LOG_INFO,
+ "Invalid blocksize2 (%d bytes), ignoring request", size);
+ return (acting_as_client ? 1 : 0);
+ }
+
+ if (size > *maxdgram) {
+ for (i = 0; sizes[i+1] != 0; i++) {
+ if (*maxdgram < sizes[i+1]) break;
+ }
+ tftp_log(LOG_INFO,
+ "Invalid blocksize2 (%d bytes), net.inet.udp.maxdgram "
+ "sysctl limits it to %d bytes.\n", size, *maxdgram);
+ size = sizes[i];
+ /* No need to return */
+ }
+
+ asprintf(&options[OPT_BLKSIZE2].o_reply, "%d", size);
+ segsize = size;
+ pktsize = size + 4;
+ if (debug&DEBUG_OPTIONS)
+ tftp_log(LOG_DEBUG, "Setting blksize2 to '%s'",
+ options[OPT_BLKSIZE2].o_reply);
+
+ return (0);
+}
+
+/*
+ * Append the available options to the header
+ */
+uint16_t
+make_options(int peer, char *buffer, uint16_t size) {
+ int i;
+ char *value;
+ const char *option;
+ uint16_t length;
+ uint16_t returnsize = 0;
+
+ if (!options_rfc_enabled) return (0);
+
+ for (i = 0; options[i].o_type != NULL; i++) {
+ if (options[i].rfc == 0 && !options_extra_enabled)
+ continue;
+
+ option = options[i].o_type;
+ if (acting_as_client)
+ value = options[i].o_request;
+ else
+ value = options[i].o_reply;
+ if (value == NULL)
+ continue;
+
+ length = strlen(value) + strlen(option) + 2;
+ if (size <= length) {
+ tftp_log(LOG_ERR,
+ "Running out of option space for "
+ "option '%s' with value '%s': "
+ "needed %d bytes, got %d bytes",
+ option, value, size, length);
+ continue;
+ }
+
+ sprintf(buffer, "%s%c%s%c", option, '\000', value, '\000');
+ size -= length;
+ buffer += length;
+ returnsize += length;
+ }
+
+ return (returnsize);
+}
+
+/*
+ * Parse the received options in the header
+ */
+int
+parse_options(int peer, char *buffer, uint16_t size)
+{
+ int i, options_failed;
+ char *c, *cp, *option, *value;
+
+ if (!options_rfc_enabled) return (0);
+
+ /* Parse the options */
+ cp = buffer;
+ options_failed = 0;
+ while (size > 0) {
+ option = cp;
+ i = get_field(peer, cp, size);
+ cp += i;
+
+ value = cp;
+ i = get_field(peer, cp, size);
+ cp += i;
+
+ /* We are at the end */
+ if (*option == '\0') break;
+
+ if (debug&DEBUG_OPTIONS)
+ tftp_log(LOG_DEBUG,
+ "option: '%s' value: '%s'", option, value);
+
+ for (c = option; *c; c++)
+ if (isupper(*c))
+ *c = tolower(*c);
+ for (i = 0; options[i].o_type != NULL; i++) {
+ if (strcmp(option, options[i].o_type) == 0) {
+ if (!acting_as_client)
+ options[i].o_request = value;
+ if (!options_extra_enabled && !options[i].rfc) {
+ tftp_log(LOG_INFO,
+ "Option '%s' with value '%s' found "
+ "but it is not an RFC option",
+ option, value);
+ continue;
+ }
+ if (options[i].o_handler)
+ options_failed +=
+ (options[i].o_handler)(peer);
+ break;
+ }
+ }
+ if (options[i].o_type == NULL)
+ tftp_log(LOG_WARNING,
+ "Unknown option: '%s'", option);
+
+ size -= strlen(option) + strlen(value) + 2;
+ }
+
+ return (options_failed);
+}
+
+/*
+ * Set some default values in the options
+ */
+void
+init_options(void)
+{
+
+ options[OPT_ROLLOVER].o_request = strdup("0");
+}
diff --git a/libexec/tftpd/tftp-options.h b/libexec/tftpd/tftp-options.h
new file mode 100644
index 0000000..d8bd2fc
--- /dev/null
+++ b/libexec/tftpd/tftp-options.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2008 Edwin Groothuis. 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 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$");
+
+/*
+ * Options
+ */
+
+void init_options(void);
+uint16_t make_options(int peer, char *buffer, uint16_t size);
+int parse_options(int peer, char *buffer, uint16_t size);
+
+/* Call back functions */
+int option_tsize(int peer, struct tftphdr *, int, struct stat *);
+int option_timeout(int peer);
+int option_blksize(int peer);
+int option_blksize2(int peer);
+int option_rollover(int peer);
+
+extern int options_extra_enabled;
+extern int options_rfc_enabled;
+
+struct options {
+ const char *o_type;
+ char *o_request;
+ char *o_reply;
+ int (*o_handler)(int peer);
+ int rfc;
+};
+
+extern struct options options[];
+enum opt_enum {
+ OPT_TSIZE = 0,
+ OPT_TIMEOUT,
+ OPT_BLKSIZE,
+ OPT_BLKSIZE2,
+ OPT_ROLLOVER,
+};
diff --git a/libexec/tftpd/tftp-transfer.c b/libexec/tftpd/tftp-transfer.c
new file mode 100644
index 0000000..fd0e00d
--- /dev/null
+++ b/libexec/tftpd/tftp-transfer.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2008 Edwin Groothuis. 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 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/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/tftp.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+#include "tftp-file.h"
+#include "tftp-io.h"
+#include "tftp-utils.h"
+#include "tftp-options.h"
+#include "tftp-transfer.h"
+
+/*
+ * Send a file via the TFTP data session.
+ */
+void
+tftp_send(int peer, uint16_t *block, struct tftp_stats *ts)
+{
+ struct tftphdr *rp;
+ int size, n_data, n_ack, try;
+ uint16_t oldblock;
+ char sendbuffer[MAXPKTSIZE];
+ char recvbuffer[MAXPKTSIZE];
+
+ rp = (struct tftphdr *)recvbuffer;
+ *block = 1;
+ ts->amount = 0;
+ do {
+ if (debug&DEBUG_SIMPLE)
+ tftp_log(LOG_DEBUG, "Sending block %d", *block);
+
+ size = read_file(sendbuffer, segsize);
+ if (size < 0) {
+ tftp_log(LOG_ERR, "read_file returned %d", size);
+ send_error(peer, errno + 100);
+ goto abort;
+ }
+
+ for (try = 0; ; try++) {
+ n_data = send_data(peer, *block, sendbuffer, size);
+ if (n_data > 0) {
+ if (try == maxtimeouts) {
+ tftp_log(LOG_ERR,
+ "Cannot send DATA packet #%d, "
+ "giving up", *block);
+ return;
+ }
+ tftp_log(LOG_ERR,
+ "Cannot send DATA packet #%d, trying again",
+ *block);
+ continue;
+ }
+
+ n_ack = receive_packet(peer, recvbuffer,
+ MAXPKTSIZE, NULL, timeoutpacket);
+ if (n_ack < 0) {
+ if (n_ack == RP_TIMEOUT) {
+ if (try == maxtimeouts) {
+ tftp_log(LOG_ERR,
+ "Timeout #%d send ACK %d "
+ "giving up", try, *block);
+ return;
+ }
+ tftp_log(LOG_WARNING,
+ "Timeout #%d on ACK %d",
+ try, *block);
+ continue;
+ }
+
+ /* Either read failure or ERROR packet */
+ if (debug&DEBUG_SIMPLE)
+ tftp_log(LOG_ERR, "Aborting: %s",
+ rp_strerror(n_ack));
+ goto abort;
+ }
+ if (rp->th_opcode == ACK) {
+ ts->blocks++;
+ if (rp->th_block == *block) {
+ ts->amount += size;
+ break;
+ }
+
+ /* Re-synchronize with the other side */
+ (void) synchnet(peer);
+ if (rp->th_block == (*block - 1)) {
+ ts->retries++;
+ continue;
+ }
+ }
+
+ }
+ oldblock = *block;
+ (*block)++;
+ if (oldblock > *block) {
+ if (options[OPT_ROLLOVER].o_request == NULL) {
+ tftp_log(LOG_ERR,
+ "Block rollover but not allowed.");
+ send_error(peer, EBADOP);
+ gettimeofday(&(ts->tstop), NULL);
+ return;
+ }
+
+ *block = atoi(options[OPT_ROLLOVER].o_request);
+ ts->rollovers++;
+ }
+ gettimeofday(&(ts->tstop), NULL);
+ } while (size == segsize);
+abort:
+ return;
+}
+
+/*
+ * Receive a file via the TFTP data session.
+ *
+ * - It could be that the first block has already arrived while
+ * trying to figure out if we were receiving options or not. In
+ * that case it is passed to this function.
+ */
+void
+tftp_receive(int peer, uint16_t *block, struct tftp_stats *ts,
+ struct tftphdr *firstblock, size_t fb_size)
+{
+ struct tftphdr *rp;
+ uint16_t oldblock;
+ int n_data, n_ack, writesize, i, retry;
+ char recvbuffer[MAXPKTSIZE];
+
+ ts->amount = 0;
+
+ if (firstblock != NULL) {
+ writesize = write_file(firstblock->th_data, fb_size);
+ ts->amount += writesize;
+ for (i = 0; ; i++) {
+ n_ack = send_ack(peer, *block);
+ if (n_ack > 0) {
+ if (i == maxtimeouts) {
+ tftp_log(LOG_ERR,
+ "Cannot send ACK packet #%d, "
+ "giving up", *block);
+ return;
+ }
+ tftp_log(LOG_ERR,
+ "Cannot send ACK packet #%d, trying again",
+ *block);
+ continue;
+ }
+
+ break;
+ }
+
+ if (fb_size != segsize) {
+ gettimeofday(&(ts->tstop), NULL);
+ return;
+ }
+ }
+
+ rp = (struct tftphdr *)recvbuffer;
+ do {
+ oldblock = *block;
+ (*block)++;
+ if (oldblock > *block) {
+ if (options[OPT_ROLLOVER].o_request == NULL) {
+ tftp_log(LOG_ERR,
+ "Block rollover but not allowed.");
+ send_error(peer, EBADOP);
+ gettimeofday(&(ts->tstop), NULL);
+ return;
+ }
+
+ *block = atoi(options[OPT_ROLLOVER].o_request);
+ ts->rollovers++;
+ }
+
+ for (retry = 0; ; retry++) {
+ if (debug&DEBUG_SIMPLE)
+ tftp_log(LOG_DEBUG,
+ "Receiving DATA block %d", *block);
+
+ n_data = receive_packet(peer, recvbuffer,
+ MAXPKTSIZE, NULL, timeoutpacket);
+ if (n_data < 0) {
+ if (retry == maxtimeouts) {
+ tftp_log(LOG_ERR,
+ "Timeout #%d on DATA block %d, "
+ "giving up", retry, *block);
+ return;
+ }
+ if (n_data == RP_TIMEOUT) {
+ tftp_log(LOG_WARNING,
+ "Timeout #%d on DATA block %d",
+ retry, *block);
+ send_ack(peer, oldblock);
+ continue;
+ }
+
+ /* Either read failure or ERROR packet */
+ if (debug&DEBUG_SIMPLE)
+ tftp_log(LOG_DEBUG, "Aborting: %s",
+ rp_strerror(n_data));
+ goto abort;
+ }
+ if (rp->th_opcode == DATA) {
+ ts->blocks++;
+
+ if (rp->th_block == *block)
+ break;
+
+ tftp_log(LOG_WARNING,
+ "Expected DATA block %d, got block %d",
+ *block, rp->th_block);
+
+ /* Re-synchronize with the other side */
+ (void) synchnet(peer);
+ if (rp->th_block == (*block-1)) {
+ tftp_log(LOG_INFO, "Trying to sync");
+ *block = oldblock;
+ ts->retries++;
+ goto send_ack; /* rexmit */
+ }
+
+ } else {
+ tftp_log(LOG_WARNING,
+ "Expected DATA block, got %s block",
+ packettype(rp->th_opcode));
+ }
+ }
+
+ if (n_data > 0) {
+ writesize = write_file(rp->th_data, n_data);
+ ts->amount += writesize;
+ if (writesize <= 0) {
+ tftp_log(LOG_ERR,
+ "write_file returned %d", writesize);
+ if (writesize < 0)
+ send_error(peer, errno + 100);
+ else
+ send_error(peer, ENOSPACE);
+ goto abort;
+ }
+ }
+
+send_ack:
+ for (i = 0; ; i++) {
+ n_ack = send_ack(peer, *block);
+ if (n_ack > 0) {
+
+ if (i == maxtimeouts) {
+ tftp_log(LOG_ERR,
+ "Cannot send ACK packet #%d, "
+ "giving up", *block);
+ return;
+ }
+
+ tftp_log(LOG_ERR,
+ "Cannot send ACK packet #%d, trying again",
+ *block);
+ continue;
+ }
+
+ break;
+ }
+ gettimeofday(&(ts->tstop), NULL);
+ } while (n_data == segsize);
+
+ /* Don't do late packet management for the client implementation */
+ if (acting_as_client)
+ return;
+
+ for (i = 0; ; i++) {
+ n_data = receive_packet(peer, (char *)rp, pktsize,
+ NULL, timeoutpacket);
+ if (n_data <= 0)
+ break;
+ if (n_data > 0 &&
+ rp->th_opcode == DATA && /* and got a data block */
+ *block == rp->th_block) /* then my last ack was lost */
+ send_ack(peer, *block); /* resend final ack */
+ }
+
+abort:
+ return;
+}
diff --git a/libexec/tftpd/tftp-transfer.h b/libexec/tftpd/tftp-transfer.h
new file mode 100644
index 0000000..2cfa2df
--- /dev/null
+++ b/libexec/tftpd/tftp-transfer.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008 Edwin Groothuis. 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 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$");
+
+void tftp_send(int peer, uint16_t *block, struct tftp_stats *tp);
+void tftp_receive(int peer, uint16_t *block, struct tftp_stats *tp,
+ struct tftphdr *firstblock, size_t fb_size);
diff --git a/libexec/tftpd/tftp-utils.c b/libexec/tftpd/tftp-utils.c
new file mode 100644
index 0000000..da58064
--- /dev/null
+++ b/libexec/tftpd/tftp-utils.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2008 Edwin Groothuis. 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 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/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/tftp.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "tftp-utils.h"
+#include "tftp-io.h"
+
+/*
+ * Default values, can be changed later via the TFTP Options
+ */
+int timeoutpacket = TIMEOUT;
+int timeoutnetwork = MAX_TIMEOUTS * TIMEOUT;
+int maxtimeouts = MAX_TIMEOUTS;
+uint16_t segsize = SEGSIZE;
+uint16_t pktsize = SEGSIZE + 4;
+
+int acting_as_client;
+
+
+/*
+ * Set timeout values for packet reception. The idea is that you
+ * get 'maxtimeouts' of 5 seconds between 'timeoutpacket' (i.e. the
+ * first timeout) to 'timeoutnetwork' (i.e. the last timeout)
+ */
+int
+settimeouts(int _timeoutpacket, int _timeoutnetwork, int _maxtimeouts)
+{
+ int i;
+
+ /* We cannot do impossible things */
+ if (_timeoutpacket >= _timeoutnetwork)
+ return (0);
+
+ maxtimeouts = 0;
+ i = _timeoutpacket;
+ while (i < _timeoutnetwork || maxtimeouts < MIN_TIMEOUTS) {
+ maxtimeouts++;
+ i += 5;
+ }
+
+ timeoutpacket = _timeoutpacket;
+ timeoutnetwork = i;
+ return (1);
+}
+
+/* translate IPv4 mapped IPv6 address to IPv4 address */
+void
+unmappedaddr(struct sockaddr_in6 *sin6)
+{
+ struct sockaddr_in *sin4;
+ u_int32_t addr;
+ int port;
+
+ if (sin6->sin6_family != AF_INET6 ||
+ !IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
+ return;
+ sin4 = (struct sockaddr_in *)sin6;
+ addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12];
+ port = sin6->sin6_port;
+ memset(sin4, 0, sizeof(struct sockaddr_in));
+ sin4->sin_addr.s_addr = addr;
+ sin4->sin_port = port;
+ sin4->sin_family = AF_INET;
+ sin4->sin_len = sizeof(struct sockaddr_in);
+}
+
+/* Get a field from a \0 seperated string */
+ssize_t
+get_field(int peer, char *buffer, ssize_t size)
+{
+ char *cp = buffer;
+
+ while (cp < buffer + size) {
+ if (*cp == '\0') break;
+ cp++;
+ }
+ if (*cp != '\0') {
+ tftp_log(LOG_ERR, "Bad option - no trailing \\0 found");
+ send_error(peer, EBADOP);
+ exit(1);
+ }
+ return (cp - buffer + 1);
+}
+
+/*
+ * Logging functions
+ */
+int _tftp_logtostdout = 1;
+
+void
+tftp_openlog(const char *ident, int logopt, int facility)
+{
+
+ _tftp_logtostdout = (ident == NULL);
+ if (_tftp_logtostdout == 0)
+ openlog(ident, logopt, facility);
+}
+
+void
+tftp_closelog(void)
+{
+
+ if (_tftp_logtostdout == 0)
+ closelog();
+}
+
+void
+tftp_log(int priority, const char *message, ...)
+{
+ va_list ap;
+ char *s;
+
+ va_start(ap, message);
+ if (_tftp_logtostdout == 0) {
+ vasprintf(&s, message, ap);
+ syslog(priority, "%s", s);
+ } else {
+ vprintf(message, ap);
+ printf("\n");
+ }
+ va_end(ap);
+}
+
+/*
+ * Packet types
+ */
+struct packettypes packettypes[] = {
+ { RRQ, "RRQ" },
+ { WRQ, "WRQ" },
+ { DATA, "DATA" },
+ { ACK, "ACK" },
+ { ERROR, "ERROR" },
+ { OACK, "OACK" },
+ { 0, NULL },
+};
+
+char *
+packettype(int type)
+{
+ static char failed[100];
+ int i = 0;
+
+ while (packettypes[i].name != NULL) {
+ if (packettypes[i].value == type)
+ break;
+ i++;
+ }
+ if (packettypes[i].name != NULL)
+ return packettypes[i].name;
+ sprintf(failed, "unknown (type: %d)", type);
+ return (failed);
+}
+
+/*
+ * Debugs
+ */
+int debug = DEBUG_NONE;
+struct debugs debugs[] = {
+ { DEBUG_PACKETS, "packet", "Packet debugging" },
+ { DEBUG_SIMPLE, "simple", "Simple debugging" },
+ { DEBUG_OPTIONS, "options", "Options debugging" },
+ { DEBUG_ACCESS, "access", "TCPd access debugging" },
+ { DEBUG_NONE, NULL, "No debugging" },
+};
+int packetdroppercentage = 0;
+
+int
+debug_find(char *s)
+{
+ int i = 0;
+
+ while (debugs[i].name != NULL) {
+ if (strcasecmp(debugs[i].name, s) == 0)
+ break;
+ i++;
+ }
+ return (debugs[i].value);
+}
+
+int
+debug_finds(char *s)
+{
+ int i = 0;
+ char *ps = s;
+
+ while (s != NULL) {
+ ps = strchr(s, ' ');
+ if (ps != NULL)
+ *ps = '\0';
+ i += debug_find(s);
+ if (ps != NULL)
+ *ps = ' ';
+ s = ps;
+ }
+ return (i);
+}
+
+char *
+debug_show(int d)
+{
+ static char s[100];
+ int i = 0;
+
+ s[0] = '\0';
+ while (debugs[i].name != NULL) {
+ if (d&debugs[i].value) {
+ if (s[0] != '\0')
+ strcat(s, " ");
+ strcat(s, debugs[i].name);
+ }
+ i++;
+ }
+ if (s[0] != '\0')
+ return (s);
+ return ("none");
+}
+
+/*
+ * RP_
+ */
+struct rp_errors rp_errors[] = {
+ { RP_TIMEOUT, "Network timeout" },
+ { RP_TOOSMALL, "Not enough data bytes" },
+ { RP_WRONGSOURCE, "Invalid IP address of UDP port" },
+ { RP_ERROR, "Error packet" },
+ { RP_RECVFROM, "recvfrom() complained" },
+ { RP_TOOBIG, "Too many data bytes" },
+ { RP_NONE, NULL }
+};
+
+char *
+rp_strerror(int error)
+{
+ static char s[100];
+ int i = 0;
+
+ while (rp_errors[i].desc != NULL) {
+ if (rp_errors[i].error == error) {
+ strcpy(s, rp_errors[i].desc);
+ }
+ i++;
+ }
+ if (s[0] == '\0')
+ sprintf(s, "unknown (error=%d)", error);
+ return (s);
+}
+
+/*
+ * Performance figures
+ */
+
+void
+stats_init(struct tftp_stats *ts)
+{
+
+ ts->amount = 0;
+ ts->rollovers = 0;
+ ts->retries = 0;
+ ts->blocks = 0;
+ ts->amount = 0;
+ gettimeofday(&(ts->tstart), NULL);
+}
+
+void
+printstats(const char *direction, int verbose, struct tftp_stats *ts)
+{
+ double delta; /* compute delta in 1/10's second units */
+
+ delta = ((ts->tstop.tv_sec*10.)+(ts->tstop.tv_usec/100000)) -
+ ((ts->tstart.tv_sec*10.)+(ts->tstart.tv_usec/100000));
+ delta = delta/10.; /* back to seconds */
+
+ printf("%s %zu bytes during %.1f seconds in %u blocks",
+ direction, ts->amount, delta, ts->blocks);
+
+ if (ts->rollovers != 0)
+ printf(" with %d rollover%s",
+ ts->rollovers, ts->rollovers != 1 ? "s" : "");
+
+ if (verbose)
+ printf(" [%.0f bits/sec]", (ts->amount*8.)/delta);
+ putchar('\n');
+}
+
diff --git a/libexec/tftpd/tftp-utils.h b/libexec/tftpd/tftp-utils.h
new file mode 100644
index 0000000..d072479
--- /dev/null
+++ b/libexec/tftpd/tftp-utils.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2008 Edwin Groothuis. 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 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$");
+
+/*
+ */
+#define TIMEOUT 5
+#define MAX_TIMEOUTS 5
+
+/* Generic values */
+#define MAXSEGSIZE 65464 /* Maximum size of the data segment */
+#define MAXPKTSIZE (MAXSEGSIZE + 4) /* Maximum size of the packet */
+
+/* For the blksize option */
+#define BLKSIZE_MIN 8 /* Minumum size of the data segment */
+#define BLKSIZE_MAX MAXSEGSIZE /* Maximum size of the data segment */
+
+/* For the timeout option */
+#define TIMEOUT_MIN 0 /* Minumum timeout value */
+#define TIMEOUT_MAX 255 /* Maximum timeout value */
+#define MIN_TIMEOUTS 3
+
+extern int timeoutpacket;
+extern int timeoutnetwork;
+extern int maxtimeouts;
+int settimeouts(int timeoutpacket, int timeoutnetwork, int maxtimeouts);
+
+extern uint16_t segsize;
+extern uint16_t pktsize;
+
+extern int acting_as_client;
+
+/*
+ */
+void unmappedaddr(struct sockaddr_in6 *sin6);
+ssize_t get_field(int peer, char *buffer, ssize_t size);
+
+/*
+ * Packet types
+ */
+struct packettypes {
+ int value;
+ char *name;
+};
+extern struct packettypes packettypes[];
+char *packettype(int);
+
+/*
+ * RP_
+ */
+struct rp_errors {
+ int error;
+ char *desc;
+};
+extern struct rp_errors rp_errors[];
+char *rp_strerror(int error);
+
+/*
+ * Debug features
+ */
+#define DEBUG_NONE 0x0000
+#define DEBUG_PACKETS 0x0001
+#define DEBUG_SIMPLE 0x0002
+#define DEBUG_OPTIONS 0x0004
+#define DEBUG_ACCESS 0x0008
+struct debugs {
+ int value;
+ char *name;
+ char *desc;
+};
+extern int debug;
+extern struct debugs debugs[];
+extern int packetdroppercentage;
+int debug_find(char *s);
+int debug_finds(char *s);
+char *debug_show(int d);
+
+/*
+ * Log routines
+ */
+#define DEBUG(s) tftp_log(LOG_DEBUG, "%s", s)
+extern int tftp_logtostdout;
+void tftp_openlog(const char *ident, int logopt, int facility);
+void tftp_closelog(void);
+void tftp_log(int priority, const char *message, ...);
+
+/*
+ * Performance figures
+ */
+struct tftp_stats {
+ size_t amount;
+ int rollovers;
+ uint32_t blocks;
+ int retries;
+ struct timeval tstart;
+ struct timeval tstop;
+};
+
+void stats_init(struct tftp_stats *ts);
+void printstats(const char *direction, int verbose, struct tftp_stats *ts);
diff --git a/libexec/tftpd/tftpd.8 b/libexec/tftpd/tftpd.8
index f9d7aec..08f40f3 100644
--- a/libexec/tftpd/tftpd.8
+++ b/libexec/tftpd/tftpd.8
@@ -40,7 +40,7 @@
.Nd Internet Trivial File Transfer Protocol server
.Sh SYNOPSIS
.Nm tftpd
-.Op Fl cClnwW
+.Op Fl cdClnow
.Op Fl F Ar strftime-format
.Op Fl s Ar directory
.Op Fl u Ar user
@@ -150,6 +150,9 @@ compatible format string for the creation of the suffix if
.Fl W
is specified.
By default the string "%Y%m%d" is used.
+.It Fl d
+Enables debug output.
+If specified twice, it will log DATA and ACK packets too.
.It Fl l
Log all requests using
.Xr syslog 3
@@ -164,6 +167,8 @@ must also be enabled in the syslog configuration file,
.It Fl n
Suppress negative acknowledgement of requests for nonexistent
relative filenames.
+.It Fl o
+Disable support for RFC2347 style TFTP Options.
.It Fl s Ar directory
Cause
.Nm
@@ -240,10 +245,16 @@ and the
and
.Fl W
options were introduced in
-.Fx 8.0 .
+.Fx 7 .
.Pp
+Support for Timeout Interval and Transfer Size Options (RFC2349)
+was introduced in
+.Fx 5.0 ,
+support for the TFTP Blocksize Option (RFC2348) and the blksize2 option
+was introduced in
+.Fx 7 .
.Sh BUGS
Files larger than 33488896 octets (65535 blocks) cannot be transferred
-without client and server supporting blocksize negotiation (RFC1783).
+without client and server supporting blocksize negotiation (RFC2348).
.Pp
Many tftp clients will not transfer files over 16744448 octets (32767 blocks).
diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c
index 027e4bc..93943f5 100644
--- a/libexec/tftpd/tftpd.c
+++ b/libexec/tftpd/tftpd.c
@@ -41,9 +41,9 @@ static const char copyright[] =
#if 0
static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93";
#endif
-static const char rcsid[] =
- "$FreeBSD$";
#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
/*
* Trivial file transfer protocol server.
@@ -56,43 +56,30 @@ static const char rcsid[] =
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/tftp.h>
-#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
-#include <libutil.h>
#include <netdb.h>
#include <pwd.h>
-#include <setjmp.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <tcpd.h>
#include <unistd.h>
-#include "tftpsubs.h"
+#include "tftp-file.h"
+#include "tftp-io.h"
+#include "tftp-utils.h"
+#include "tftp-transfer.h"
+#include "tftp-options.h"
-#define TIMEOUT 5
-#define MAX_TIMEOUTS 5
-
-int peer;
-int rexmtval = TIMEOUT;
-int max_rexmtval = 2*TIMEOUT;
-
-#define PKTSIZE SEGSIZE+4
-char buf[PKTSIZE];
-char ackbuf[PKTSIZE];
-struct sockaddr_storage from;
-
-void tftp(struct tftphdr *, int);
-static void unmappedaddr(struct sockaddr_in6 *);
+static void tftp_wrq(int peer, char *, ssize_t);
+static void tftp_rrq(int peer, char *, ssize_t);
/*
* Null-terminated directory prefix list for absolute pathname requests and
@@ -112,31 +99,44 @@ static int ipchroot;
static int create_new = 0;
static char *newfile_format = "%Y%m%d";
static int increase_name = 0;
-static mode_t mask = S_IWGRP|S_IWOTH;
+static mode_t mask = S_IWGRP | S_IWOTH;
-static const char *errtomsg(int);
-static void nak(int);
-static void oack(void);
+struct formats;
+static void tftp_recvfile(int peer, const char *mode);
+static void tftp_xmitfile(int peer, const char *mode);
+static int validate_access(int peer, char **, int);
+static char peername[NI_MAXHOST];
+
+FILE *file;
-static void timer(int);
-static void justquit(int);
+struct formats {
+ const char *f_mode;
+ int f_convert;
+} formats[] = {
+ { "netascii", 1 },
+ { "octet", 0 },
+ { NULL, 0 }
+};
int
main(int argc, char *argv[])
{
struct tftphdr *tp;
- socklen_t fromlen, len;
- int n;
- int ch, on;
- struct sockaddr_storage me;
- char *chroot_dir = NULL;
- struct passwd *nobody;
- const char *chuser = "nobody";
+ int peer;
+ socklen_t peerlen, len;
+ ssize_t n;
+ int ch;
+ char *chroot_dir = NULL;
+ struct passwd *nobody;
+ const char *chuser = "nobody";
+ char recvbuffer[MAXPKTSIZE];
+ int allow_ro = 1, allow_wo = 1;
tzset(); /* syslog in localtime */
+ acting_as_client = 0;
- openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
- while ((ch = getopt(argc, argv, "cCF:lns:u:U:wW")) != -1) {
+ tftp_openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
+ while ((ch = getopt(argc, argv, "cCd:F:lnoOp:s:u:U:wW")) != -1) {
switch (ch) {
case 'c':
ipchroot = 1;
@@ -144,6 +144,12 @@ main(int argc, char *argv[])
case 'C':
ipchroot = 2;
break;
+ case 'd':
+ if (atoi(optarg) != 0)
+ debug += atoi(optarg);
+ else
+ debug |= debug_finds(optarg);
+ break;
case 'F':
newfile_format = optarg;
break;
@@ -153,6 +159,18 @@ main(int argc, char *argv[])
case 'n':
suppress_naks = 1;
break;
+ case 'o':
+ options_rfc_enabled = 0;
+ break;
+ case 'O':
+ options_extra_enabled = 0;
+ break;
+ case 'p':
+ packetdroppercentage = atoi(optarg);
+ tftp_log(LOG_INFO,
+ "Randomly dropping %d out of 100 packets",
+ packetdroppercentage);
+ break;
case 's':
chroot_dir = optarg;
break;
@@ -170,7 +188,8 @@ main(int argc, char *argv[])
increase_name = 1;
break;
default:
- syslog(LOG_WARNING, "ignoring unknown option -%c", ch);
+ tftp_log(LOG_WARNING,
+ "ignoring unknown option -%c", ch);
}
}
if (optind < argc) {
@@ -191,24 +210,31 @@ main(int argc, char *argv[])
dirs->len = 1;
}
if (ipchroot > 0 && chroot_dir == NULL) {
- syslog(LOG_ERR, "-c requires -s");
+ tftp_log(LOG_ERR, "-c requires -s");
exit(1);
}
umask(mask);
- on = 1;
- if (ioctl(0, FIONBIO, &on) < 0) {
- syslog(LOG_ERR, "ioctl(FIONBIO): %m");
- exit(1);
+ {
+ int on = 1;
+ if (ioctl(0, FIONBIO, &on) < 0) {
+ tftp_log(LOG_ERR, "ioctl(FIONBIO): %s", strerror(errno));
+ exit(1);
+ }
}
- fromlen = sizeof (from);
- n = recvfrom(0, buf, sizeof (buf), 0,
- (struct sockaddr *)&from, &fromlen);
+
+ /* Find out who we are talking to and what we are going to do */
+ peerlen = sizeof(peer_sock);
+ n = recvfrom(0, recvbuffer, MAXPKTSIZE, 0,
+ (struct sockaddr *)&peer_sock, &peerlen);
if (n < 0) {
- syslog(LOG_ERR, "recvfrom: %m");
+ tftp_log(LOG_ERR, "recvfrom: %s", strerror(errno));
exit(1);
}
+ getnameinfo((struct sockaddr *)&peer_sock, peer_sock.ss_len,
+ peername, sizeof(peername), NULL, 0, NI_NUMERICHOST);
+
/*
* Now that we have read the message out of the UDP
* socket, we fork and exit. Thus, inetd will go back
@@ -240,9 +266,9 @@ main(int argc, char *argv[])
* than one tftpd being started up to service
* a single request from a single client.
*/
- fromlen = sizeof from;
- i = recvfrom(0, buf, sizeof (buf), 0,
- (struct sockaddr *)&from, &fromlen);
+ peerlen = sizeof peer_sock;
+ i = recvfrom(0, recvbuffer, MAXPKTSIZE, 0,
+ (struct sockaddr *)&peer_sock, &peerlen);
if (i > 0) {
n = i;
}
@@ -251,7 +277,7 @@ main(int argc, char *argv[])
}
}
if (pid < 0) {
- syslog(LOG_ERR, "fork: %m");
+ tftp_log(LOG_ERR, "fork: %s", strerror(errno));
exit(1);
} else if (pid != 0) {
exit(0);
@@ -259,6 +285,55 @@ main(int argc, char *argv[])
}
/*
+ * See if the client is allowed to talk to me.
+ * (This needs to be done before the chroot())
+ */
+ {
+ struct request_info req;
+
+ request_init(&req, RQ_CLIENT_ADDR, peername, 0);
+ request_set(&req, RQ_DAEMON, "tftpd", 0);
+
+ if (hosts_access(&req) == 0) {
+ if (debug&DEBUG_ACCESS)
+ tftp_log(LOG_WARNING,
+ "Access denied by 'tftpd' entry "
+ "in /etc/hosts.allow");
+
+ /*
+ * Full access might be disabled, but maybe the
+ * client is allowed to do read-only access.
+ */
+ request_set(&req, RQ_DAEMON, "tftpd-ro", 0);
+ allow_ro = hosts_access(&req);
+
+ request_set(&req, RQ_DAEMON, "tftpd-wo", 0);
+ allow_wo = hosts_access(&req);
+
+ if (allow_ro == 0 && allow_wo == 0) {
+ tftp_log(LOG_WARNING,
+ "Unauthorized access from %s", peername);
+ exit(1);
+ }
+
+ if (debug&DEBUG_ACCESS) {
+ if (allow_ro)
+ tftp_log(LOG_WARNING,
+ "But allowed readonly access "
+ "via 'tftpd-ro' entry");
+ if (allow_wo)
+ tftp_log(LOG_WARNING,
+ "But allowed writeonly access "
+ "via 'tftpd-wo' entry");
+ }
+ } else
+ if (debug&DEBUG_ACCESS)
+ tftp_log(LOG_WARNING,
+ "Full access allowed"
+ "in /etc/hosts.allow");
+ }
+
+ /*
* Since we exit here, we should do that only after the above
* recvfrom to keep inetd from constantly forking should there
* be a problem. See the above comment about system clogging.
@@ -271,7 +346,8 @@ main(int argc, char *argv[])
struct sockaddr_storage ss;
char hbuf[NI_MAXHOST];
- memcpy(&ss, &from, from.ss_len);
+ statret = -1;
+ memcpy(&ss, &peer_sock, peer_sock.ss_len);
unmappedaddr((struct sockaddr_in6 *)&ss);
getnameinfo((struct sockaddr *)&ss, ss.ss_len,
hbuf, sizeof(hbuf), NULL, 0,
@@ -285,11 +361,12 @@ main(int argc, char *argv[])
}
/* Must get this before chroot because /etc might go away */
if ((nobody = getpwnam(chuser)) == NULL) {
- syslog(LOG_ERR, "%s: no such user", chuser);
+ tftp_log(LOG_ERR, "%s: no such user", chuser);
exit(1);
}
if (chroot(chroot_dir)) {
- syslog(LOG_ERR, "chroot: %s: %m", chroot_dir);
+ tftp_log(LOG_ERR, "chroot: %s: %s",
+ chroot_dir, strerror(errno));
exit(1);
}
chdir("/");
@@ -297,44 +374,56 @@ main(int argc, char *argv[])
setuid(nobody->pw_uid);
}
- len = sizeof(me);
- if (getsockname(0, (struct sockaddr *)&me, &len) == 0) {
- switch (me.ss_family) {
+ len = sizeof(me_sock);
+ if (getsockname(0, (struct sockaddr *)&me_sock, &len) == 0) {
+ switch (me_sock.ss_family) {
case AF_INET:
- ((struct sockaddr_in *)&me)->sin_port = 0;
+ ((struct sockaddr_in *)&me_sock)->sin_port = 0;
break;
case AF_INET6:
- ((struct sockaddr_in6 *)&me)->sin6_port = 0;
+ ((struct sockaddr_in6 *)&me_sock)->sin6_port = 0;
break;
default:
/* unsupported */
break;
}
} else {
- memset(&me, 0, sizeof(me));
- me.ss_family = from.ss_family;
- me.ss_len = from.ss_len;
+ memset(&me_sock, 0, sizeof(me_sock));
+ me_sock.ss_family = peer_sock.ss_family;
+ me_sock.ss_len = peer_sock.ss_len;
}
- alarm(0);
close(0);
close(1);
- peer = socket(from.ss_family, SOCK_DGRAM, 0);
+ peer = socket(peer_sock.ss_family, SOCK_DGRAM, 0);
if (peer < 0) {
- syslog(LOG_ERR, "socket: %m");
- exit(1);
- }
- if (bind(peer, (struct sockaddr *)&me, me.ss_len) < 0) {
- syslog(LOG_ERR, "bind: %m");
+ tftp_log(LOG_ERR, "socket: %s", strerror(errno));
exit(1);
}
- if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) {
- syslog(LOG_ERR, "connect: %m");
+ if (bind(peer, (struct sockaddr *)&me_sock, me_sock.ss_len) < 0) {
+ tftp_log(LOG_ERR, "bind: %s", strerror(errno));
exit(1);
}
- tp = (struct tftphdr *)buf;
+
+ tp = (struct tftphdr *)recvbuffer;
tp->th_opcode = ntohs(tp->th_opcode);
- if (tp->th_opcode == RRQ || tp->th_opcode == WRQ)
- tftp(tp, n);
+ if (tp->th_opcode == RRQ) {
+ if (allow_ro)
+ tftp_rrq(peer, tp->th_stuff, n - 1);
+ else {
+ tftp_log(LOG_WARNING,
+ "%s read access denied", peername);
+ exit(1);
+ }
+ }
+ if (tp->th_opcode == WRQ) {
+ if (allow_wo)
+ tftp_wrq(peer, tp->th_stuff, n - 1);
+ else {
+ tftp_log(LOG_WARNING,
+ "%s write access denied", peername);
+ exit(1);
+ }
+ }
exit(1);
}
@@ -369,138 +458,145 @@ reduce_path(char *fn)
}
}
-struct formats;
-int validate_access(char **, int);
-void xmitfile(struct formats *);
-void recvfile(struct formats *);
+static char *
+parse_header(int peer, char *recvbuffer, ssize_t size,
+ char **filename, char **mode)
+{
+ char *cp;
+ int i;
+ struct formats *pf;
-struct formats {
- const char *f_mode;
- int (*f_validate)(char **, int);
- void (*f_send)(struct formats *);
- void (*f_recv)(struct formats *);
- int f_convert;
-} formats[] = {
- { "netascii", validate_access, xmitfile, recvfile, 1 },
- { "octet", validate_access, xmitfile, recvfile, 0 },
-#ifdef notdef
- { "mail", validate_user, sendmail, recvmail, 1 },
-#endif
- { 0, NULL, NULL, NULL, 0 }
-};
+ *mode = NULL;
+ cp = recvbuffer;
-struct options {
- const char *o_type;
- char *o_request;
- int o_reply; /* turn into union if need be */
-} options[] = {
- { "tsize", NULL, 0 }, /* OPT_TSIZE */
- { "timeout", NULL, 0 }, /* OPT_TIMEOUT */
- { NULL, NULL, 0 }
-};
+ i = get_field(peer, recvbuffer, size);
+ if (i >= PATH_MAX) {
+ tftp_log(LOG_ERR, "Bad option - filename too long");
+ send_error(peer, EBADOP);
+ exit(1);
+ }
+ *filename = recvbuffer;
+ tftp_log(LOG_INFO, "Filename: '%s'", *filename);
+ cp += i;
-enum opt_enum {
- OPT_TSIZE = 0,
- OPT_TIMEOUT,
-};
+ i = get_field(peer, cp, size);
+ *mode = cp;
+ cp += i;
+
+ /* Find the file transfer mode */
+ for (cp = *mode; *cp; cp++)
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+ for (pf = formats; pf->f_mode; pf++)
+ if (strcmp(pf->f_mode, *mode) == 0)
+ break;
+ if (pf->f_mode == NULL) {
+ tftp_log(LOG_ERR,
+ "Bad option - Unknown transfer mode (%s)", *mode);
+ send_error(peer, EBADOP);
+ exit(1);
+ }
+ tftp_log(LOG_INFO, "Mode: '%s'", *mode);
+
+ return (cp + 1);
+}
/*
- * Handle initial connection protocol.
+ * WRQ - receive a file from the client
*/
void
-tftp(struct tftphdr *tp, int size)
+tftp_wrq(int peer, char *recvbuffer, ssize_t size)
{
char *cp;
- int i, first = 1, has_options = 0, ecode;
- struct formats *pf;
- char *filename, *mode, *option, *ccp;
+ int has_options = 0, ecode;
+ char *filename, *mode;
char fnbuf[PATH_MAX];
- cp = tp->th_stuff;
-again:
- while (cp < buf + size) {
- if (*cp == '\0')
- break;
- cp++;
- }
- if (*cp != '\0') {
- nak(EBADOP);
- exit(1);
- }
- i = cp - tp->th_stuff;
- if (i >= sizeof(fnbuf)) {
- nak(EBADOP);
- exit(1);
- }
- memcpy(fnbuf, tp->th_stuff, i);
- fnbuf[i] = '\0';
+ cp = parse_header(peer, recvbuffer, size, &filename, &mode);
+ size -= (cp - recvbuffer) + 1;
+
+ strcpy(fnbuf, filename);
reduce_path(fnbuf);
filename = fnbuf;
- if (first) {
- mode = ++cp;
- first = 0;
- goto again;
+
+ if (size > 0) {
+ if (options_rfc_enabled)
+ has_options = !parse_options(peer, cp, size);
+ else
+ tftp_log(LOG_INFO, "Options found but not enabled");
}
- for (cp = mode; *cp; cp++)
- if (isupper(*cp))
- *cp = tolower(*cp);
- for (pf = formats; pf->f_mode; pf++)
- if (strcmp(pf->f_mode, mode) == 0)
- break;
- if (pf->f_mode == 0) {
- nak(EBADOP);
- exit(1);
+
+ ecode = validate_access(peer, &filename, WRQ);
+ if (ecode == 0) {
+ if (has_options)
+ send_oack(peer);
+ else
+ send_ack(peer, 0);
}
- while (++cp < buf + size) {
- for (i = 2, ccp = cp; i > 0; ccp++) {
- if (ccp >= buf + size) {
- /*
- * Don't reject the request, just stop trying
- * to parse the option and get on with it.
- * Some Apple Open Firmware versions have
- * trailing garbage on the end of otherwise
- * valid requests.
- */
- goto option_fail;
- } else if (*ccp == '\0')
- i--;
- }
- for (option = cp; *cp; cp++)
- if (isupper(*cp))
- *cp = tolower(*cp);
- for (i = 0; options[i].o_type != NULL; i++)
- if (strcmp(option, options[i].o_type) == 0) {
- options[i].o_request = ++cp;
- has_options = 1;
- }
- cp = ccp-1;
+ if (logging) {
+ tftp_log(LOG_INFO, "%s: write request for %s: %s", peername,
+ filename, errtomsg(ecode));
}
-option_fail:
- if (options[OPT_TIMEOUT].o_request) {
- int to = atoi(options[OPT_TIMEOUT].o_request);
- if (to < 1 || to > 255) {
- nak(EBADOP);
- exit(1);
- }
- else if (to <= max_rexmtval)
- options[OPT_TIMEOUT].o_reply = rexmtval = to;
+ tftp_recvfile(peer, mode);
+ exit(0);
+}
+
+/*
+ * RRQ - send a file to the client
+ */
+void
+tftp_rrq(int peer, char *recvbuffer, ssize_t size)
+{
+ char *cp;
+ int has_options = 0, ecode;
+ char *filename, *mode;
+ char fnbuf[PATH_MAX];
+
+ cp = parse_header(peer, recvbuffer, size, &filename, &mode);
+ size -= (cp - recvbuffer) + 1;
+
+ strcpy(fnbuf, filename);
+ reduce_path(fnbuf);
+ filename = fnbuf;
+
+ if (size > 0) {
+ if (options_rfc_enabled)
+ has_options = !parse_options(peer, cp, size);
else
- options[OPT_TIMEOUT].o_request = NULL;
+ tftp_log(LOG_INFO, "Options found but not enabled");
}
- ecode = (*pf->f_validate)(&filename, tp->th_opcode);
- if (has_options && ecode == 0)
- oack();
- if (logging) {
- char hbuf[NI_MAXHOST];
+ ecode = validate_access(peer, &filename, RRQ);
+ if (ecode == 0) {
+ if (has_options) {
+ int n;
+ char lrecvbuffer[MAXPKTSIZE];
+ struct tftphdr *rp = (struct tftphdr *)lrecvbuffer;
- getnameinfo((struct sockaddr *)&from, from.ss_len,
- hbuf, sizeof(hbuf), NULL, 0, 0);
- syslog(LOG_INFO, "%s: %s request for %s: %s", hbuf,
- tp->th_opcode == WRQ ? "write" : "read",
- filename, errtomsg(ecode));
+ send_oack(peer);
+ n = receive_packet(peer, lrecvbuffer, MAXPKTSIZE,
+ NULL, timeoutpacket);
+ if (n < 0) {
+ if (debug&DEBUG_SIMPLE)
+ tftp_log(LOG_DEBUG, "Aborting: %s",
+ rp_strerror(n));
+ return;
+ }
+ if (rp->th_opcode != ACK) {
+ if (debug&DEBUG_SIMPLE)
+ tftp_log(LOG_DEBUG,
+ "Expected ACK, got %s on OACK",
+ packettype(rp->th_opcode));
+ return;
+ }
+ }
}
+
+ if (logging)
+ tftp_log(LOG_INFO, "%s: read request for %s: %s", peername,
+ filename, errtomsg(ecode));
+
if (ecode) {
/*
* Avoid storms of naks to a RRQ broadcast for a relative
@@ -508,19 +604,13 @@ option_fail:
*/
if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
exit(0);
- nak(ecode);
+ tftp_log(LOG_ERR, "Prevent NAK storm");
+ send_error(peer, ecode);
exit(1);
}
- if (tp->th_opcode == WRQ)
- (*pf->f_recv)(pf);
- else
- (*pf->f_send)(pf);
- exit(0);
+ tftp_xmitfile(peer, mode);
}
-
-FILE *file;
-
/*
* Find the next value for YYYYMMDD.nn when the file to be written should
* be unique. Due to the limitations of nn, we will fail if nn reaches 100.
@@ -536,8 +626,6 @@ find_next_name(char *filename, int *fd)
struct tm lt;
char yyyymmdd[MAXPATHLEN];
char newname[MAXPATHLEN];
- struct stat sb;
- int ret;
/* Create the YYYYMMDD part of the filename */
time(&tval);
@@ -553,7 +641,7 @@ find_next_name(char *filename, int *fd)
/* Make sure the new filename is not too long */
if (strlen(filename) > MAXPATHLEN - len - 5) {
syslog(LOG_WARNING,
- "Filename too long (%d characters, %d maximum)",
+ "Filename too long (%zd characters, %zd maximum)",
strlen(filename), MAXPATHLEN - len - 5);
return (EACCESS);
}
@@ -584,7 +672,7 @@ find_next_name(char *filename, int *fd)
* given as we have no login directory.
*/
int
-validate_access(char **filep, int mode)
+validate_access(int peer, char **filep, int mode)
{
struct stat stbuf;
int fd;
@@ -660,14 +748,13 @@ validate_access(char **filep, int mode)
else if (mode == RRQ)
return (err);
}
- if (options[OPT_TSIZE].o_request) {
- if (mode == RRQ)
- options[OPT_TSIZE].o_reply = stbuf.st_size;
- else
- /* XXX Allows writes of all sizes. */
- options[OPT_TSIZE].o_reply =
- atoi(options[OPT_TSIZE].o_request);
- }
+
+ /*
+ * This option is handled here because it (might) require(s) the
+ * size of the file.
+ */
+ option_tsize(peer, NULL, mode, &stbuf);
+
if (mode == RRQ)
fd = open(filename, O_RDONLY);
else {
@@ -694,305 +781,60 @@ validate_access(char **filep, int mode)
return (0);
}
-int timeouts;
-jmp_buf timeoutbuf;
-
-void
-timer(int sig __unused)
+static void
+tftp_xmitfile(int peer, const char *mode)
{
- if (++timeouts > MAX_TIMEOUTS)
- exit(1);
- longjmp(timeoutbuf, 1);
-}
+ uint16_t block;
+ uint32_t amount;
+ time_t now;
+ struct tftp_stats ts;
-/*
- * Send the requested file.
- */
-void
-xmitfile(struct formats *pf)
-{
- struct tftphdr *dp;
- struct tftphdr *ap; /* ack packet */
- int size, n;
- volatile unsigned short block;
-
- signal(SIGALRM, timer);
- dp = r_init();
- ap = (struct tftphdr *)ackbuf;
- block = 1;
- do {
- size = readit(file, &dp, pf->f_convert);
- if (size < 0) {
- nak(errno + 100);
- goto abort;
- }
- dp->th_opcode = htons((u_short)DATA);
- dp->th_block = htons((u_short)block);
- timeouts = 0;
- (void)setjmp(timeoutbuf);
-
-send_data:
- {
- int i, t = 1;
- for (i = 0; ; i++){
- if (send(peer, dp, size + 4, 0) != size + 4) {
- sleep(t);
- t = (t < 32) ? t<< 1 : t;
- if (i >= 12) {
- syslog(LOG_ERR, "write: %m");
- goto abort;
- }
- }
- break;
- }
- }
- read_ahead(file, pf->f_convert);
- for ( ; ; ) {
- alarm(rexmtval); /* read the ack */
- n = recv(peer, ackbuf, sizeof (ackbuf), 0);
- alarm(0);
- if (n < 0) {
- syslog(LOG_ERR, "read: %m");
- goto abort;
- }
- ap->th_opcode = ntohs((u_short)ap->th_opcode);
- ap->th_block = ntohs((u_short)ap->th_block);
+ now = time(NULL);
+ if (debug&DEBUG_SIMPLE)
+ tftp_log(LOG_DEBUG, "Transmitting file");
- if (ap->th_opcode == ERROR)
- goto abort;
-
- if (ap->th_opcode == ACK) {
- if (ap->th_block == block)
- break;
- /* Re-synchronize with the other side */
- (void) synchnet(peer);
- if (ap->th_block == (block -1))
- goto send_data;
- }
-
- }
- block++;
- } while (size == SEGSIZE);
-abort:
- (void) fclose(file);
+ read_init(0, file, mode);
+ block = 1;
+ tftp_send(peer, &block, &ts);
+ read_close();
+ if (debug&DEBUG_SIMPLE)
+ tftp_log(LOG_INFO, "Sent %d bytes in %d seconds",
+ amount, time(NULL) - now);
}
-void
-justquit(int sig __unused)
+static void
+tftp_recvfile(int peer, const char *mode)
{
- exit(0);
-}
+ uint32_t filesize;
+ uint16_t block;
+ struct timeval now1, now2;
+ struct tftp_stats ts;
+ gettimeofday(&now1, NULL);
+ if (debug&DEBUG_SIMPLE)
+ tftp_log(LOG_DEBUG, "Receiving file");
+
+ write_init(0, file, mode);
-/*
- * Receive a file.
- */
-void
-recvfile(struct formats *pf)
-{
- struct tftphdr *dp;
- struct tftphdr *ap; /* ack buffer */
- int n, size;
- volatile unsigned short block;
-
- signal(SIGALRM, timer);
- dp = w_init();
- ap = (struct tftphdr *)ackbuf;
block = 0;
- do {
- timeouts = 0;
- ap->th_opcode = htons((u_short)ACK);
- ap->th_block = htons((u_short)block);
- block++;
- (void) setjmp(timeoutbuf);
-send_ack:
- if (send(peer, ackbuf, 4, 0) != 4) {
- syslog(LOG_ERR, "write: %m");
- goto abort;
- }
- write_behind(file, pf->f_convert);
- for ( ; ; ) {
- alarm(rexmtval);
- n = recv(peer, dp, PKTSIZE, 0);
- alarm(0);
- if (n < 0) { /* really? */
- syslog(LOG_ERR, "read: %m");
- goto abort;
- }
- dp->th_opcode = ntohs((u_short)dp->th_opcode);
- dp->th_block = ntohs((u_short)dp->th_block);
- if (dp->th_opcode == ERROR)
- goto abort;
- if (dp->th_opcode == DATA) {
- if (dp->th_block == block) {
- break; /* normal */
- }
- /* Re-synchronize with the other side */
- (void) synchnet(peer);
- if (dp->th_block == (block-1))
- goto send_ack; /* rexmit */
- }
- }
- /* size = write(file, dp->th_data, n - 4); */
- size = writeit(file, &dp, n - 4, pf->f_convert);
- if (size != (n-4)) { /* ahem */
- if (size < 0) nak(errno + 100);
- else nak(ENOSPACE);
- goto abort;
- }
- } while (size == SEGSIZE);
- write_behind(file, pf->f_convert);
- (void) fclose(file); /* close data file */
-
- ap->th_opcode = htons((u_short)ACK); /* send the "final" ack */
- ap->th_block = htons((u_short)(block));
- (void) send(peer, ackbuf, 4, 0);
-
- signal(SIGALRM, justquit); /* just quit on timeout */
- alarm(rexmtval);
- n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */
- alarm(0);
- if (n >= 4 && /* if read some data */
- dp->th_opcode == DATA && /* and got a data block */
- block == dp->th_block) { /* then my last ack was lost */
- (void) send(peer, ackbuf, 4, 0); /* resend final ack */
- }
-abort:
- return;
-}
+ tftp_receive(peer, &block, &ts, NULL, 0);
-struct errmsg {
- int e_code;
- const char *e_msg;
-} errmsgs[] = {
- { EUNDEF, "Undefined error code" },
- { ENOTFOUND, "File not found" },
- { EACCESS, "Access violation" },
- { ENOSPACE, "Disk full or allocation exceeded" },
- { EBADOP, "Illegal TFTP operation" },
- { EBADID, "Unknown transfer ID" },
- { EEXISTS, "File already exists" },
- { ENOUSER, "No such user" },
- { EOPTNEG, "Option negotiation" },
- { -1, 0 }
-};
+ write_close();
-static const char *
-errtomsg(int error)
-{
- static char ebuf[20];
- struct errmsg *pe;
- if (error == 0)
- return "success";
- for (pe = errmsgs; pe->e_code >= 0; pe++)
- if (pe->e_code == error)
- return pe->e_msg;
- snprintf(ebuf, sizeof(buf), "error %d", error);
- return ebuf;
-}
+ if (debug&DEBUG_SIMPLE) {
+ double f;
+ if (now1.tv_usec > now2.tv_usec) {
+ now2.tv_usec += 1000000;
+ now2.tv_sec--;
+ }
-/*
- * Send a nak packet (error message).
- * Error code passed in is one of the
- * standard TFTP codes, or a UNIX errno
- * offset by 100.
- */
-static void
-nak(int error)
-{
- struct tftphdr *tp;
- int length;
- struct errmsg *pe;
-
- tp = (struct tftphdr *)buf;
- tp->th_opcode = htons((u_short)ERROR);
- tp->th_code = htons((u_short)error);
- for (pe = errmsgs; pe->e_code >= 0; pe++)
- if (pe->e_code == error)
- break;
- if (pe->e_code < 0) {
- pe->e_msg = strerror(error - 100);
- tp->th_code = EUNDEF; /* set 'undef' errorcode */
+ f = now2.tv_sec - now1.tv_sec +
+ (now2.tv_usec - now1.tv_usec) / 100000.0;
+ tftp_log(LOG_INFO,
+ "Download of %d bytes in %d blocks completed after %0.1f seconds\n",
+ filesize, block, f);
}
- strcpy(tp->th_msg, pe->e_msg);
- length = strlen(pe->e_msg);
- tp->th_msg[length] = '\0';
- length += 5;
- if (send(peer, buf, length, 0) != length)
- syslog(LOG_ERR, "nak: %m");
-}
-/* translate IPv4 mapped IPv6 address to IPv4 address */
-static void
-unmappedaddr(struct sockaddr_in6 *sin6)
-{
- struct sockaddr_in *sin4;
- u_int32_t addr;
- int port;
-
- if (sin6->sin6_family != AF_INET6 ||
- !IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
- return;
- sin4 = (struct sockaddr_in *)sin6;
- addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12];
- port = sin6->sin6_port;
- memset(sin4, 0, sizeof(struct sockaddr_in));
- sin4->sin_addr.s_addr = addr;
- sin4->sin_port = port;
- sin4->sin_family = AF_INET;
- sin4->sin_len = sizeof(struct sockaddr_in);
+ return;
}
-/*
- * Send an oack packet (option acknowledgement).
- */
-static void
-oack(void)
-{
- struct tftphdr *tp, *ap;
- int size, i, n;
- char *bp;
-
- tp = (struct tftphdr *)buf;
- bp = buf + 2;
- size = sizeof(buf) - 2;
- tp->th_opcode = htons((u_short)OACK);
- for (i = 0; options[i].o_type != NULL; i++) {
- if (options[i].o_request) {
- n = snprintf(bp, size, "%s%c%d", options[i].o_type,
- 0, options[i].o_reply);
- bp += n+1;
- size -= n+1;
- if (size < 0) {
- syslog(LOG_ERR, "oack: buffer overflow");
- exit(1);
- }
- }
- }
- size = bp - buf;
- ap = (struct tftphdr *)ackbuf;
- signal(SIGALRM, timer);
- timeouts = 0;
-
- (void)setjmp(timeoutbuf);
- if (send(peer, buf, size, 0) != size) {
- syslog(LOG_INFO, "oack: %m");
- exit(1);
- }
-
- for (;;) {
- alarm(rexmtval);
- n = recv(peer, ackbuf, sizeof (ackbuf), 0);
- alarm(0);
- if (n < 0) {
- syslog(LOG_ERR, "recv: %m");
- exit(1);
- }
- ap->th_opcode = ntohs((u_short)ap->th_opcode);
- ap->th_block = ntohs((u_short)ap->th_block);
- if (ap->th_opcode == ERROR)
- exit(1);
- if (ap->th_opcode == ACK && ap->th_block == 0)
- break;
- }
-}
diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8
index d1e9587..1a075b3 100644
--- a/sbin/camcontrol/camcontrol.8
+++ b/sbin/camcontrol/camcontrol.8
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 20, 2010
+.Dd May 2, 2010
.Dt CAMCONTROL 8
.Os
.Sh NAME
@@ -123,6 +123,8 @@
.Op generic args
.Aq Fl a Ar cmd Op args
.Aq Fl c Ar cmd Op args
+.Op Fl d
+.Op Fl f
.Op Fl i Ar len Ar fmt
.Bk -words
.Op Fl o Ar len Ar fmt Op args
@@ -530,6 +532,10 @@ lba_high_exp, features_exp, sector_count, sector_count_exp).
.It Fl c Ar cmd Op args
This specifies the SCSI CDB.
SCSI CDBs may be 6, 10, 12 or 16 bytes.
+.It Fl d
+Specifies DMA protocol to be used for ATA command.
+.It Fl f
+Specifies FPDMA (NCQ) protocol to be used for ATA command.
.It Fl i Ar len Ar fmt
This specifies the amount of data to read, and how it should be displayed.
If the format is
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
index 8e0605f..c39d7ba 100644
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -123,7 +123,7 @@ struct camcontrol_opts {
};
#ifndef MINIMALISTIC
-static const char scsicmd_opts[] = "a:c:i:o:r";
+static const char scsicmd_opts[] = "a:c:dfi:o:r";
static const char readdefect_opts[] = "f:GP";
static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
#endif
@@ -2184,6 +2184,8 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
int c, data_bytes = 0;
int cdb_len = 0;
int atacmd_len = 0;
+ int dmacmd = 0;
+ int fpdmacmd = 0;
int need_res = 0;
char *datastr = NULL, *tstr, *resstr = NULL;
int error = 0;
@@ -2246,6 +2248,12 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
*/
optind += hook.got;
break;
+ case 'd':
+ dmacmd = 1;
+ break;
+ case 'f':
+ fpdmacmd = 1;
+ break;
case 'i':
if (arglist & CAM_ARG_CMD_OUT) {
warnx("command must either be "
@@ -2422,6 +2430,10 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
if (need_res)
ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
+ if (dmacmd)
+ ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
+ if (fpdmacmd)
+ ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
cam_fill_ataio(&ccb->ataio,
/*retries*/ retry_count,
@@ -2843,6 +2855,10 @@ cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
sata->tags);
}
+ if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
+ fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
+ sata->caps);
+ }
}
if (cts->protocol == PROTO_SCSI) {
struct ccb_trans_settings_scsi *scsi=
@@ -4353,7 +4369,7 @@ usage(int verbose)
" [-P pagectl][-e | -b][-d]\n"
" camcontrol cmd [dev_id][generic args]\n"
" <-a cmd [args] | -c cmd [args]>\n"
-" [-i len fmt|-o len fmt [args]] [-r fmt]\n"
+" [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n"
" camcontrol debug [-I][-P][-T][-S][-X][-c]\n"
" <all|bus[:target[:lun]]|off>\n"
" camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n"
diff --git a/sbin/hastd/hast.conf.5 b/sbin/hastd/hast.conf.5
index 5734ee8..1ccd479 100644
--- a/sbin/hastd/hast.conf.5
+++ b/sbin/hastd/hast.conf.5
@@ -58,6 +58,7 @@ file is following:
control <addr>
listen <addr>
replication <mode>
+timeout <seconds>
on <node> {
# Node section
@@ -76,6 +77,7 @@ resource <name> {
replication <mode>
name <name>
local <path>
+ timeout <seconds>
on <node> {
# Resource-node section
@@ -194,6 +196,11 @@ The
.Ic async
replication mode is currently not implemented.
.El
+.It Ic timeout Aq seconds
+.Pp
+Connection timeout in seconds.
+The default value is
+.Va 5 .
.It Ic name Aq name
.Pp
GEOM provider name that will appear as
diff --git a/sbin/hastd/hast.h b/sbin/hastd/hast.h
index c5220b5..2230afb 100644
--- a/sbin/hastd/hast.h
+++ b/sbin/hastd/hast.h
@@ -75,6 +75,7 @@
#define HIO_DELETE 3
#define HIO_FLUSH 4
+#define HAST_TIMEOUT 5
#define HAST_CONFIG "/etc/hast.conf"
#define HAST_CONTROL "/var/run/hastctl"
#define HASTD_PORT 8457
@@ -148,6 +149,8 @@ struct hast_resource {
/* Token to verify both in and out connection are coming from
the same node (not necessarily from the same address). */
unsigned char hr_token[HAST_TOKEN_SIZE];
+ /* Connection timeout. */
+ int hr_timeout;
/* Resource unique identifier. */
uint64_t hr_resuid;
diff --git a/sbin/hastd/hastd.c b/sbin/hastd/hastd.c
index 957885d..27b9bba 100644
--- a/sbin/hastd/hastd.c
+++ b/sbin/hastd/hastd.c
@@ -108,6 +108,22 @@ g_gate_load(void)
}
static void
+child_exit_log(unsigned int pid, int status)
+{
+
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ pjdlog_debug(1, "Worker process exited gracefully (pid=%u).",
+ pid);
+ } else if (WIFSIGNALED(status)) {
+ pjdlog_error("Worker process killed (pid=%u, signal=%d).",
+ pid, WTERMSIG(status));
+ } else {
+ pjdlog_error("Worker process exited ungracefully (pid=%u, exitcode=%d).",
+ pid, WIFEXITED(status) ? WEXITSTATUS(status) : -1);
+ }
+}
+
+static void
child_exit(void)
{
struct hast_resource *res;
@@ -129,20 +145,25 @@ child_exit(void)
}
pjdlog_prefix_set("[%s] (%s) ", res->hr_name,
role2str(res->hr_role));
- if (WEXITSTATUS(status) == 0) {
- pjdlog_debug(1,
- "Worker process exited gracefully (pid=%u).",
- (unsigned int)pid);
- } else {
- pjdlog_error("Worker process failed (pid=%u, status=%d).",
- (unsigned int)pid, WEXITSTATUS(status));
- }
+ child_exit_log(pid, status);
proto_close(res->hr_ctrl);
res->hr_workerpid = 0;
if (res->hr_role == HAST_ROLE_PRIMARY) {
- sleep(1);
- pjdlog_info("Restarting worker process.");
- hastd_primary(res);
+ /*
+ * Restart child process if it was killed by signal
+ * or exited because of temporary problem.
+ */
+ if (WIFSIGNALED(status) ||
+ (WIFEXITED(status) &&
+ WEXITSTATUS(status) == EX_TEMPFAIL)) {
+ sleep(1);
+ pjdlog_info("Restarting worker process.");
+ hastd_primary(res);
+ } else {
+ res->hr_role = HAST_ROLE_INIT;
+ pjdlog_info("Changing resource role back to %s.",
+ role2str(res->hr_role));
+ }
}
pjdlog_prefix_set("%s", "");
}
@@ -181,6 +202,10 @@ listen_accept(void)
proto_remote_address(conn, raddr, sizeof(raddr));
pjdlog_info("Connection from %s to %s.", laddr, raddr);
+ /* Error in setting timeout is not critical, but why should it fail? */
+ if (proto_timeout(conn, HAST_TIMEOUT) < 0)
+ pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
+
nvin = nvout = nverr = NULL;
/*
@@ -290,18 +315,12 @@ listen_accept(void)
/* Wait for it to exit. */
else if ((pid = waitpid(res->hr_workerpid,
&status, 0)) != res->hr_workerpid) {
+ /* We can only log the problem. */
pjdlog_errno(LOG_ERR,
"Waiting for worker process (pid=%u) failed",
(unsigned int)res->hr_workerpid);
- /* See above. */
- } else if (status != 0) {
- pjdlog_error("Worker process (pid=%u) exited ungracefully: status=%d.",
- (unsigned int)res->hr_workerpid, status);
- /* See above. */
} else {
- pjdlog_debug(1,
- "Worker process (pid=%u) exited gracefully.",
- (unsigned int)res->hr_workerpid);
+ child_exit_log(res->hr_workerpid, status);
}
res->hr_workerpid = 0;
} else if (res->hr_remotein != NULL) {
diff --git a/sbin/hastd/metadata.c b/sbin/hastd/metadata.c
index 9bca66b..7a138e8 100644
--- a/sbin/hastd/metadata.c
+++ b/sbin/hastd/metadata.c
@@ -117,7 +117,7 @@ metadata_read(struct hast_resource *res, bool openrw)
}
str = nv_get_string(nv, "resource");
- if (strcmp(str, res->hr_name) != 0) {
+ if (str != NULL && strcmp(str, res->hr_name) != 0) {
pjdlog_error("Provider %s is not part of resource %s.",
res->hr_localpath, res->hr_name);
nv_free(nv);
diff --git a/sbin/hastd/parse.y b/sbin/hastd/parse.y
index 6755320..840a844 100644
--- a/sbin/hastd/parse.y
+++ b/sbin/hastd/parse.y
@@ -58,6 +58,7 @@ static bool mynode;
static char depth0_control[HAST_ADDRSIZE];
static char depth0_listen[HAST_ADDRSIZE];
static int depth0_replication;
+static int depth0_timeout;
static char depth1_provname[PATH_MAX];
static char depth1_localpath[PATH_MAX];
@@ -115,6 +116,7 @@ yy_config_parse(const char *config)
curres = NULL;
mynode = false;
+ depth0_timeout = HAST_TIMEOUT;
depth0_replication = HAST_REPLICATION_MEMSYNC;
strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control));
strlcpy(depth0_listen, HASTD_LISTEN, sizeof(depth0_listen));
@@ -154,6 +156,13 @@ yy_config_parse(const char *config)
*/
curres->hr_replication = depth0_replication;
}
+ if (curres->hr_timeout == -1) {
+ /*
+ * Timeout is not set at resource-level.
+ * Use global or default setting.
+ */
+ curres->hr_timeout = depth0_timeout;
+ }
}
return (&lconfig);
@@ -171,7 +180,7 @@ yy_config_free(struct hastd_config *config)
}
%}
-%token CONTROL LISTEN PORT REPLICATION EXTENTSIZE RESOURCE NAME LOCAL REMOTE ON
+%token CONTROL LISTEN PORT REPLICATION TIMEOUT EXTENTSIZE RESOURCE NAME LOCAL REMOTE ON
%token FULLSYNC MEMSYNC ASYNC
%token NUM STR OB CB
@@ -200,6 +209,8 @@ statement:
|
replication_statement
|
+ timeout_statement
+ |
node_statement
|
resource_statement
@@ -281,6 +292,22 @@ replication_type:
ASYNC { $$ = HAST_REPLICATION_ASYNC; }
;
+timeout_statement: TIMEOUT NUM
+ {
+ switch (depth) {
+ case 0:
+ depth0_timeout = $2;
+ break;
+ case 1:
+ if (curres != NULL)
+ curres->hr_timeout = $2;
+ break;
+ default:
+ assert(!"timeout at wrong depth level");
+ }
+ }
+ ;
+
node_statement: ON node_start OB node_entries CB
{
mynode = false;
@@ -389,6 +416,7 @@ resource_start: STR
curres->hr_role = HAST_ROLE_INIT;
curres->hr_previous_role = HAST_ROLE_INIT;
curres->hr_replication = -1;
+ curres->hr_timeout = -1;
curres->hr_provname[0] = '\0';
curres->hr_localpath[0] = '\0';
curres->hr_localfd = -1;
@@ -405,6 +433,8 @@ resource_entries:
resource_entry:
replication_statement
|
+ timeout_statement
+ |
name_statement
|
local_statement
diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c
index 0915154..9f2b2c7 100644
--- a/sbin/hastd/primary.c
+++ b/sbin/hastd/primary.c
@@ -480,7 +480,7 @@ init_remote(struct hast_resource *res, struct proto_conn **inp,
/* Prepare outgoing connection with remote node. */
if (proto_client(res->hr_remoteaddr, &out) < 0) {
- primary_exit(EX_OSERR, "Unable to create connection to %s",
+ primary_exit(EX_TEMPFAIL, "Unable to create connection to %s",
res->hr_remoteaddr);
}
/* Try to connect, but accept failure. */
@@ -489,6 +489,9 @@ init_remote(struct hast_resource *res, struct proto_conn **inp,
res->hr_remoteaddr);
goto close;
}
+ /* Error in setting timeout is not critical, but why should it fail? */
+ if (proto_timeout(out, res->hr_timeout) < 0)
+ pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
/*
* First handshake step.
* Setup outgoing connection with remote node.
@@ -552,6 +555,9 @@ init_remote(struct hast_resource *res, struct proto_conn **inp,
res->hr_remoteaddr);
goto close;
}
+ /* Error in setting timeout is not critical, but why should it fail? */
+ if (proto_timeout(in, res->hr_timeout) < 0)
+ pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
nvout = nv_alloc();
nv_add_string(nvout, res->hr_name, "resource");
nv_add_uint8_array(nvout, res->hr_token, sizeof(res->hr_token),
@@ -739,7 +745,7 @@ hastd_primary(struct hast_resource *res)
pid = fork();
if (pid < 0) {
KEEP_ERRNO((void)pidfile_remove(pfh));
- primary_exit(EX_OSERR, "Unable to fork");
+ primary_exit(EX_TEMPFAIL, "Unable to fork");
}
if (pid > 0) {
diff --git a/sbin/hastd/proto.c b/sbin/hastd/proto.c
index 103f20c..531e7e5 100644
--- a/sbin/hastd/proto.c
+++ b/sbin/hastd/proto.c
@@ -30,7 +30,9 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/types.h>
#include <sys/queue.h>
+#include <sys/socket.h>
#include <assert.h>
#include <errno.h>
@@ -247,6 +249,30 @@ proto_remote_address(const struct proto_conn *conn, char *addr, size_t size)
conn->pc_proto->hp_remote_address(conn->pc_ctx, addr, size);
}
+int
+proto_timeout(const struct proto_conn *conn, int timeout)
+{
+ struct timeval tv;
+ int fd;
+
+ assert(conn != NULL);
+ assert(conn->pc_magic == PROTO_CONN_MAGIC);
+ assert(conn->pc_proto != NULL);
+
+ fd = proto_descriptor(conn);
+ if (fd < 0)
+ return (-1);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
+ return (-1);
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
+ return (-1);
+
+ return (0);
+}
+
void
proto_close(struct proto_conn *conn)
{
diff --git a/sbin/hastd/proto.h b/sbin/hastd/proto.h
index cb196d8..13248ba 100644
--- a/sbin/hastd/proto.h
+++ b/sbin/hastd/proto.h
@@ -49,6 +49,7 @@ void proto_local_address(const struct proto_conn *conn, char *addr,
size_t size);
void proto_remote_address(const struct proto_conn *conn, char *addr,
size_t size);
+int proto_timeout(const struct proto_conn *conn, int timeout);
void proto_close(struct proto_conn *conn);
#endif /* !_PROTO_H_ */
diff --git a/sbin/hastd/proto_common.c b/sbin/hastd/proto_common.c
index 22102d8..131d30e 100644
--- a/sbin/hastd/proto_common.c
+++ b/sbin/hastd/proto_common.c
@@ -58,7 +58,7 @@ proto_common_send(int fd, const unsigned char *data, size_t size)
if (done == 0)
return (ENOTCONN);
else if (done < 0) {
- if (errno == EAGAIN)
+ if (errno == EINTR)
continue;
return (errno);
}
@@ -76,7 +76,7 @@ proto_common_recv(int fd, unsigned char *data, size_t size)
do {
done = recv(fd, data, size, MSG_WAITALL);
- } while (done == -1 && errno == EAGAIN);
+ } while (done == -1 && errno == EINTR);
if (done == 0)
return (ENOTCONN);
else if (done < 0)
diff --git a/sbin/hastd/proto_tcp4.c b/sbin/hastd/proto_tcp4.c
index 2fba996..5af82d5 100644
--- a/sbin/hastd/proto_tcp4.c
+++ b/sbin/hastd/proto_tcp4.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#include <netdb.h>
#include <stdbool.h>
#include <stdint.h>
@@ -47,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include "hast.h"
#include "pjdlog.h"
#include "proto_impl.h"
+#include "subr.h"
#define TCP4_CTX_MAGIC 0x7c441c
struct tcp4_ctx {
@@ -222,18 +224,88 @@ static int
tcp4_connect(void *ctx)
{
struct tcp4_ctx *tctx = ctx;
+ struct timeval tv;
+ fd_set fdset;
+ socklen_t esize;
+ int error, flags, ret;
assert(tctx != NULL);
assert(tctx->tc_magic == TCP4_CTX_MAGIC);
assert(tctx->tc_side == TCP4_SIDE_CLIENT);
assert(tctx->tc_fd >= 0);
- if (connect(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sin,
- sizeof(tctx->tc_sin)) < 0) {
+ flags = fcntl(tctx->tc_fd, F_GETFL);
+ if (flags == -1) {
+ KEEP_ERRNO(pjdlog_common(LOG_DEBUG, 1, errno,
+ "fcntl(F_GETFL) failed"));
+ return (errno);
+ }
+ /*
+ * We make socket non-blocking so we have decided about connection
+ * timeout.
+ */
+ flags |= O_NONBLOCK;
+ if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) {
+ KEEP_ERRNO(pjdlog_common(LOG_DEBUG, 1, errno,
+ "fcntl(F_SETFL, O_NONBLOCK) failed"));
return (errno);
}
- return (0);
+ if (connect(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sin,
+ sizeof(tctx->tc_sin)) == 0) {
+ error = 0;
+ goto done;
+ }
+ if (errno != EINPROGRESS) {
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno, "connect() failed");
+ goto done;
+ }
+ /*
+ * Connection can't be established immediately, let's wait
+ * for HAST_TIMEOUT seconds.
+ */
+ tv.tv_sec = HAST_TIMEOUT;
+ tv.tv_usec = 0;
+again:
+ FD_ZERO(&fdset);
+ FD_SET(tctx->tc_fd, &fdset);
+ ret = select(tctx->tc_fd + 1, NULL, &fdset, NULL, &tv);
+ if (ret == 0) {
+ error = ETIMEDOUT;
+ goto done;
+ } else if (ret == -1) {
+ if (errno == EINTR)
+ goto again;
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno, "select() failed");
+ goto done;
+ }
+ assert(ret > 0);
+ assert(FD_ISSET(tctx->tc_fd, &fdset));
+ esize = sizeof(error);
+ if (getsockopt(tctx->tc_fd, SOL_SOCKET, SO_ERROR, &error,
+ &esize) == -1) {
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno,
+ "getsockopt(SO_ERROR) failed");
+ goto done;
+ }
+ if (error != 0) {
+ pjdlog_common(LOG_DEBUG, 1, error,
+ "getsockopt(SO_ERROR) returned error");
+ goto done;
+ }
+ error = 0;
+done:
+ flags &= ~O_NONBLOCK;
+ if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) {
+ if (error == 0)
+ error = errno;
+ pjdlog_common(LOG_DEBUG, 1, errno,
+ "fcntl(F_SETFL, ~O_NONBLOCK) failed");
+ }
+ return (error);
}
static int
diff --git a/sbin/hastd/secondary.c b/sbin/hastd/secondary.c
index 6af95b5..b189b7e 100644
--- a/sbin/hastd/secondary.c
+++ b/sbin/hastd/secondary.c
@@ -337,6 +337,12 @@ hastd_secondary(struct hast_resource *res, struct nv *nvin)
setproctitle("%s (secondary)", res->hr_name);
+ /* Error in setting timeout is not critical, but why should it fail? */
+ if (proto_timeout(res->hr_remotein, 0) < 0)
+ pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
+ if (proto_timeout(res->hr_remoteout, res->hr_timeout) < 0)
+ pjdlog_errno(LOG_WARNING, "Unable to set connection timeout");
+
init_local(res);
init_remote(res, nvin);
init_environment();
diff --git a/sbin/hastd/token.l b/sbin/hastd/token.l
index 7b80384..e5d4ca1 100644
--- a/sbin/hastd/token.l
+++ b/sbin/hastd/token.l
@@ -48,6 +48,7 @@ control { DP; return CONTROL; }
listen { DP; return LISTEN; }
port { DP; return PORT; }
replication { DP; return REPLICATION; }
+timeout { DP; return TIMEOUT; }
resource { DP; return RESOURCE; }
name { DP; return NAME; }
local { DP; return LOCAL; }
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index eafd5d8..65c240f 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -28,7 +28,7 @@
.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94
.\" $FreeBSD$
.\"
-.Dd February 20, 2010
+.Dd April 28, 2010
.Dt IFCONFIG 8
.Os
.Sh NAME
@@ -1163,9 +1163,9 @@ In particular the information elements included in management frames
for old devices are different.
When compatibility support is enabled both standard and compatible data
will be provided.
-Stations that associate using the compatiblity mechanisms are flagged
+Stations that associate using the compatibility mechanisms are flagged
in ``list sta''.
-To disable compatiblity support use
+To disable compatibility support use
.Fl htcompat .
.It Cm htprotmode Ar technique
For interfaces operating in 802.11n, use the specified
diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c
index 6cb4d2c..6ec45ff 100644
--- a/sbin/ifconfig/ifieee80211.c
+++ b/sbin/ifconfig/ifieee80211.c
@@ -5027,7 +5027,7 @@ DECL_CMD_FUNC(set80211clone_wlanaddr, arg, d)
ea = ether_aton(arg);
if (ea == NULL)
- errx(1, "%s: cannot parse addres", arg);
+ errx(1, "%s: cannot parse address", arg);
memcpy(params.icp_macaddr, ea->octet, IEEE80211_ADDR_LEN);
params.icp_flags |= IEEE80211_CLONE_MACADDR;
}
diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c
index a10b35d..dc2492f 100644
--- a/sbin/tunefs/tunefs.c
+++ b/sbin/tunefs/tunefs.c
@@ -280,9 +280,9 @@ main(int argc, char *argv[])
if (ufs_disk_fillout(&disk, special) == -1)
goto err;
if (disk.d_name != special) {
- special = disk.d_name;
- if (statfs(special, &stfs) == 0 &&
- strcmp(special, stfs.f_mntonname) == 0)
+ if (statfs(special, &stfs) != 0)
+ warn("Can't stat %s", special);
+ if (strcmp(special, stfs.f_mntonname) == 0)
active = 1;
}
@@ -546,7 +546,7 @@ journal_balloc(void)
* Try to minimize fragmentation by requiring a minimum
* number of blocks present.
*/
- if (cgp->cg_cs.cs_nbfree > blocks / 8)
+ if (cgp->cg_cs.cs_nbfree > 128 * 1024 * 1024)
break;
if (contig == 0 && cgp->cg_cs.cs_nbfree)
break;
@@ -1007,10 +1007,11 @@ out:
void
usage(void)
{
- fprintf(stderr, "%s\n%s\n%s\n%s\n",
+ fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
"usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]",
-" [-J enable | disable ] [-L volname] [-l enable | disable]",
-" [-m minfree] [-N enable | disable] [-n enable | disable]",
+" [-J enable | disable] [-j enable | disable]",
+" [-L volname] [-l enable | disable] [-m minfree]",
+" [-N enable | disable] [-n enable | disable]",
" [-o space | time] [-p] [-s avgfpdir] special | filesystem");
exit(2);
}
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index c71a097..b1282da 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -220,6 +220,7 @@ MAN= aac.4 \
msk.4 \
mtio.4 \
multicast.4 \
+ mvs.4 \
mwl.4 \
mwlfw.4 \
mxge.4 \
diff --git a/share/man/man4/bwn.4 b/share/man/man4/bwn.4
index 1293c36..b75f9d0 100644
--- a/share/man/man4/bwn.4
+++ b/share/man/man4/bwn.4
@@ -123,7 +123,7 @@ ifconfig wlan create wlandev bwn0 ssid my_net \e
The
.Nm
driver first appeared in
-.Fx 8.0 .
+.Fx 8.1 .
.Sh AUTHORS
.An -nosplit
The
diff --git a/share/man/man4/cas.4 b/share/man/man4/cas.4
index 7851a99..cc050c9 100644
--- a/share/man/man4/cas.4
+++ b/share/man/man4/cas.4
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 15, 2009
+.Dd May 3, 2010
.Dt CAS 4
.Os
.Sh NAME
@@ -91,6 +91,9 @@ driver at this time:
.Pp
.Bl -bullet -compact
.It
+Sun GigaSwift Ethernet 1.0 MMF (Cassini Kuheen)
+(part no.\& 501-5524)
+.It
Sun GigaSwift Ethernet 1.0 UTP (Cassini)
(part no.\& 501-5902)
.It
diff --git a/share/man/man4/msk.4 b/share/man/man4/msk.4
index 7a842f5..7ea12dd 100644
--- a/share/man/man4/msk.4
+++ b/share/man/man4/msk.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 1, 2010
+.Dd April 30, 2010
.Dt MSK 4
.Os
.Sh NAME
@@ -208,6 +208,8 @@ Marvell Yukon 88E8057 Gigabit Ethernet
.It
Marvell Yukon 88E8058 Gigabit Ethernet
.It
+Marvell Yukon 88E8059 Gigabit Ethernet
+.It
Marvell Yukon 88E8070 Gigabit Ethernet
.It
Marvell Yukon 88E8071 Gigabit Ethernet
diff --git a/share/man/man4/mvs.4 b/share/man/man4/mvs.4
new file mode 100644
index 0000000..5999335
--- /dev/null
+++ b/share/man/man4/mvs.4
@@ -0,0 +1,176 @@
+.\" Copyright (c) 2009 Alexander Motin <mav@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.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 27, 2010
+.Dt MVS 4
+.Os
+.Sh NAME
+.Nm mvs
+.Nd Marvell Serial ATA Host Controller driver
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device pci"
+.Cd "device scbus"
+.Cd "device mvs"
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+mvs_load="YES"
+.Ed
+.Pp
+The following tunables are settable from the
+.Xr loader 8 :
+.Bl -ohang
+.It Va hint.mvs. Ns Ar X Ns Va .msi
+controls Message Signaled Interrupts (MSI) usage by the specified controller.
+.It Va hint.mvs. Ns Ar X Ns Va .ccc
+controls Command Completion Coalescing (CCC) usage by the specified controller.
+Non-zero value enables CCC and defines maximum time (in us), request can wait
+for interrupt.
+CCC reduces number of context switches on systems with many parallel requests,
+but it can decrease disk performance on some workloads due to additional
+command latency.
+.It Va hint.mvs. Ns Ar X Ns Va .cccc
+defines number of completed commands for CCC, which trigger interrupt without
+waiting for specified coalescing timeout.
+.It Va hint.mvs. Ns Ar X Ns Va .pm_level
+controls SATA interface Power Management for the specified channel,
+allowing some power to be saved at the cost of additional command
+latency.
+Possible values:
+.Bl -tag -compact
+.It 0
+interface Power Management is disabled (default);
+.It 1
+device is allowed to initiate PM state change, host is passive;
+.It 4
+driver initiates PARTIAL PM state transition 1ms after port becomes idle;
+.It 5
+driver initiates SLUMBER PM state transition 125ms after port becomes idle.
+.El
+.Pp
+Note that interface Power Management is not compatible with
+device presence detection.
+A manual bus reset is needed on device hot-plug.
+.It Va hint.mvs. Ns Ar X Ns Va .sata_rev
+setting to nonzero value limits maximum SATA revision (speed).
+Values 1, 2 and 3 are respectively 1.5, 3 and 6Gbps.
+.El
+.Sh DESCRIPTION
+This driver provides the
+.Xr CAM 4
+subsystem with native access to the
+.Tn SATA
+ports of several generations (Gen-I/II/IIe) of Marvell SATA controllers.
+Each SATA port found is represented to CAM as a separate bus with one
+target, or, if HBA supports Port Multipliers (Gen-II/IIe), 16 targets.
+Most of the bus-management details are handled by the SATA-specific
+transport of CAM.
+Connected ATA disks are handled by the ATA protocol disk peripheral driver
+.Xr ada 4 .
+ATAPI devices are handled by the SCSI protocol peripheral drivers
+.Xr cd 4 ,
+.Xr da 4 ,
+.Xr sa 4 ,
+etc.
+.Pp
+Driver features include support for Serial ATA and ATAPI devices,
+Port Multipliers (including FIS-based switching, when supported),
+hardware command queues (up to 31 command per port),
+Native Command Queuing, SATA interface Power Management, device hot-plug
+and Message Signaled Interrupts.
+.Pp
+Same hardware is also supported by atamarvell and ataadaptec drivers from
+.Xr ata 4
+subsystem.
+If both drivers are loaded at the same time, this one will be
+given precedence as the more functional of the two.
+.Sh HARDWARE
+The
+.Nm
+driver supports the following controllers:
+.Bl -tag -compact
+.It Gen-I (SATA 1.5Gbps):
+.Bl -bullet -compact
+.It
+88SX5040
+.It
+88SX5041
+.It
+88SX5080
+.It
+88SX5081
+.El
+.It Gen-II (SATA 3Gbps, NCQ, PMP):
+.Bl -bullet -compact
+.It
+88SX6040
+.It
+88SX6041 (including Adaptec 1420SA)
+.It
+88SX6080
+.It
+88SX6081
+.El
+.It Gen-IIe (SATA 3Gbps, NCQ, PMP with FBS):
+.Bl -bullet -compact
+.It
+88SX6042
+.It
+88SX7042 (including Adaptec 1430SA)
+.It
+88F5182 SoC
+.It
+88F6281 SoC
+.It
+MV78100 SoC
+.El
+.El
+Note, that this hardware supports command queueing and FIS-based switching
+only for ATA DMA commands. ATAPI and non-DMA ATA commands executed one by one
+for each port.
+.Pp
+.Sh SEE ALSO
+.Xr ada 4 ,
+.Xr ata 4 ,
+.Xr cam 4 ,
+.Xr cd 4 ,
+.Xr da 4 ,
+.Xr sa 4
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+.An Alexander Motin Aq mav@FreeBSD.org .
diff --git a/share/man/man4/ng_bridge.4 b/share/man/man4/ng_bridge.4
index 3b1dd71..8884e33 100644
--- a/share/man/man4/ng_bridge.4
+++ b/share/man/man4/ng_bridge.4
@@ -34,7 +34,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 31, 2000
+.Dd May 5, 2010
.Dt NG_BRIDGE 4
.Os
.Sh NAME
@@ -181,11 +181,17 @@ but also atomically clears the statistics as well.
.It Dv NGM_BRIDGE_GET_TABLE
Returns the current host mapping table used to direct packets, in a
.Dv "struct ng_bridge_host_ary" .
+.It Dv NGM_BRIDGE_SET_PERSISTENT
+This command sets the persistent flag on the node, and takes no arguments.
.El
.Sh SHUTDOWN
This node shuts down upon receipt of a
.Dv NGM_SHUTDOWN
-control message, or when all hooks have been disconnected.
+control message, or when all hooks have been disconnected. Setting the
+persistent flag via a
+.Dv NGM_BRIDGE_SET_PERSISTENT
+control message disables automatic node shutdown when the last hook gets
+disconnected.
.Sh FILES
.Bl -tag -width XXXXXXXX -compact
.It Pa /usr/share/examples/netgraph/ether.bridge
diff --git a/share/man/man4/ng_hub.4 b/share/man/man4/ng_hub.4
index a1ad068..c52aba0 100644
--- a/share/man/man4/ng_hub.4
+++ b/share/man/man4/ng_hub.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 17, 2004
+.Dd May 5, 2010
.Dt NG_HUB 4
.Os
.Sh NAME
@@ -45,11 +45,20 @@ A
node accepts any request to connect, regardless of the hook name,
as long as the name is unique.
.Sh CONTROL MESSAGES
-This node type supports only the generic control messages.
+This node type supports the generic control messages, plus the
+following:
+.Bl -tag -width foo
+.It Dv NGM_HUB_SET_PERSISTENT
+This command sets the persistent flag on the node, and takes no arguments.
+.El
.Sh SHUTDOWN
This node shuts down upon receipt of a
.Dv NGM_SHUTDOWN
-control message, or when all hooks have been disconnected.
+control message, or when all hooks have been disconnected. Setting the
+persistent flag via a
+.Dv NGM_HUB_SET_PERSISTENT
+control message disables automatic node shutdown when the last hook gets
+disconnected.
.Sh SEE ALSO
.Xr netgraph 4 ,
.Xr ng_bridge 4 ,
diff --git a/share/man/man4/sge.4 b/share/man/man4/sge.4
index a3d057d..9ef179c 100644
--- a/share/man/man4/sge.4
+++ b/share/man/man4/sge.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 14, 2010
+.Dd April 29, 2010
.Dt SGE 4
.Os
.Sh NAME
@@ -53,11 +53,11 @@ controllers and SiS191 Fast/Gigabit Ethernet controllers.
.Pp
All LOMs supported by the
.Nm
-driver have TCP/UDP/IP checksum offload for transmit and receive.
+driver have TCP/UDP/IP checksum offload for transmit and receive,
+hardware VLAN tag stripping/insertion features.
Due to lack of documentation more offloading features like TCP
-segmentation offload (TSO), hardware VLAN tag stripping/insertion
-features, Wake On Lan (WOL), Jumbo frame and an interrupt moderation
-mechanism are not supported yet.
+segmentation offload (TSO), Wake On Lan (WOL), Jumbo frame and an
+interrupt moderation mechanism are not supported yet.
.Pp
The
.Nm
diff --git a/share/man/man4/vlan.4 b/share/man/man4/vlan.4
index f7f7807..17fff6a 100644
--- a/share/man/man4/vlan.4
+++ b/share/man/man4/vlan.4
@@ -134,6 +134,7 @@ in the hardware is limited to the following devices:
.Xr msk 4 ,
.Xr nge 4 ,
.Xr re 4 ,
+.Xr sge 4 ,
.Xr stge 4 ,
.Xr ti 4 ,
.Xr txp 4 ,
@@ -172,7 +173,6 @@ natively:
.Xr nve 4 ,
.Xr rl 4 ,
.Xr sf 4 ,
-.Xr sge 4 ,
.Xr sis 4 ,
.Xr sk 4 ,
.Xr ste 4 ,
diff --git a/share/man/man9/ieee80211.9 b/share/man/man9/ieee80211.9
index ae92d5e..8fd6e0d 100644
--- a/share/man/man9/ieee80211.9
+++ b/share/man/man9/ieee80211.9
@@ -25,11 +25,11 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 29, 2010
-.Dt NET80211 9
+.Dd April 28, 2010
+.Dt IEEE80211 9
.Os
.Sh NAME
-.Nm net80211
+.Nm IEEE80211
.Nd 802.11 network layer
.Sh SYNOPSIS
.In net80211/ieee80211_var.h
diff --git a/share/man/man9/ieee80211_node.9 b/share/man/man9/ieee80211_node.9
index be0b506..9389411 100644
--- a/share/man/man9/ieee80211_node.9
+++ b/share/man/man9/ieee80211_node.9
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 29, 2010
+.Dd April 28, 2010
.Dt IEEE80211_NODE 9
.Os
.Sh NAME
@@ -152,7 +152,7 @@ displays the contents of a single node while
.Fn ieee80211_dump_nodes
displays the contents of the specified node table.
Nodes may also be displayed using
-.Xr ddb 9
+.Xr ddb 4
with the
.Dq show node
directive and the station node table can be displayed with
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index 0d5a50d..7b1fed8 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -50,14 +50,14 @@
.bss
.globl dtrace_invop_jump_addr
.align 8
- .type dtrace_invop_jump_addr, @object
- .size dtrace_invop_jump_addr, 8
+ .type dtrace_invop_jump_addr,@object
+ .size dtrace_invop_jump_addr,8
dtrace_invop_jump_addr:
.zero 8
.globl dtrace_invop_calltrap_addr
.align 8
- .type dtrace_invop_calltrap_addr, @object
- .size dtrace_invop_calltrap_addr, 8
+ .type dtrace_invop_calltrap_addr,@object
+ .size dtrace_invop_calltrap_addr,8
dtrace_invop_calltrap_addr:
.zero 8
#endif
@@ -157,7 +157,6 @@ IDTVEC(align)
* kernel from userland. Reenable interrupts if they were enabled
* before the trap. This approximates SDT_SYS386TGT on the i386 port.
*/
-
SUPERALIGN_TEXT
.globl alltraps
.type alltraps,@function
@@ -211,16 +210,16 @@ alltraps_pushregs_no_rdi:
* Set our jump address for the jump back in the event that
* the breakpoint wasn't caused by DTrace at all.
*/
- movq $calltrap, dtrace_invop_calltrap_addr(%rip)
+ movq $calltrap,dtrace_invop_calltrap_addr(%rip)
/* Jump to the code hooked in by DTrace. */
- movq dtrace_invop_jump_addr, %rax
+ movq dtrace_invop_jump_addr,%rax
jmpq *dtrace_invop_jump_addr
#endif
.globl calltrap
.type calltrap,@function
calltrap:
- movq %rsp, %rdi
+ movq %rsp,%rdi
call trap
MEXITCOUNT
jmp doreti /* Handle any pending ASTs */
@@ -274,9 +273,11 @@ IDTVEC(dblfault)
testb $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
jz 1f /* already running with kernel GS.base */
swapgs
-1: movq %rsp, %rdi
+1:
+ movq %rsp,%rdi
call dblfault_handler
-2: hlt
+2:
+ hlt
jmp 2b
IDTVEC(page)
@@ -369,7 +370,7 @@ IDTVEC(fast_syscall)
movq %r15,TF_R15(%rsp) /* C preserved */
movl $TF_HASSEGS,TF_FLAGS(%rsp)
FAKE_MCOUNT(TF_RIP(%rsp))
- movq %rsp, %rdi
+ movq %rsp,%rdi
call syscall
movq PCPU(CURPCB),%rax
andq $~PCB_FULLCTX,PCB_FLAGS(%rax)
@@ -456,7 +457,7 @@ nmi_fromuserspace:
/* Note: this label is also used by ddb and gdb: */
nmi_calltrap:
FAKE_MCOUNT(TF_RIP(%rsp))
- movq %rsp, %rdi
+ movq %rsp,%rdi
call trap
MEXITCOUNT
#ifdef HWPMC_HOOKS
@@ -555,9 +556,9 @@ nmi_restoreregs:
iretq
ENTRY(fork_trampoline)
- movq %r12, %rdi /* function */
- movq %rbx, %rsi /* arg1 */
- movq %rsp, %rdx /* trapframe pointer */
+ movq %r12,%rdi /* function */
+ movq %rbx,%rsi /* arg1 */
+ movq %rsp,%rdx /* trapframe pointer */
call fork_exit
MEXITCOUNT
jmp doreti /* Handle any ASTs */
@@ -628,7 +629,7 @@ doreti_ast:
testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
je doreti_exit
sti
- movq %rsp, %rdi /* pass a pointer to the trapframe */
+ movq %rsp,%rdi /* pass a pointer to the trapframe */
call ast
jmp doreti_ast
@@ -648,8 +649,8 @@ doreti_exit:
* Do not reload segment registers for kernel.
* Since we do not reload segments registers with sane
* values on kernel entry, descriptors referenced by
- * segments registers may be not valid. This is fatal
- * for the usermode, but is innocent for the kernel.
+ * segments registers might be not valid. This is fatal
+ * for user mode, but is not a problem for the kernel.
*/
testb $SEL_RPL_MASK,TF_CS(%rsp)
jz ld_regs
@@ -662,14 +663,16 @@ do_segs:
/* Restore %fs and fsbase */
movw TF_FS(%rsp),%ax
.globl ld_fs
-ld_fs: movw %ax,%fs
+ld_fs:
+ movw %ax,%fs
cmpw $KUF32SEL,%ax
jne 1f
movl $MSR_FSBASE,%ecx
movl PCB_FSBASE(%r8),%eax
movl PCB_FSBASE+4(%r8),%edx
.globl ld_fsbase
-ld_fsbase: wrmsr
+ld_fsbase:
+ wrmsr
1:
/* Restore %gs and gsbase */
movw TF_GS(%rsp),%si
@@ -678,7 +681,8 @@ ld_fsbase: wrmsr
movl $MSR_GSBASE,%ecx
rdmsr
.globl ld_gs
-ld_gs: movw %si,%gs
+ld_gs:
+ movw %si,%gs
wrmsr
popfq
cmpw $KUG32SEL,%si
@@ -687,12 +691,17 @@ ld_gs: movw %si,%gs
movl PCB_GSBASE(%r8),%eax
movl PCB_GSBASE+4(%r8),%edx
.globl ld_gsbase
-ld_gsbase: wrmsr
-1: .globl ld_es
-ld_es: movw TF_ES(%rsp),%es
+ld_gsbase:
+ wrmsr
+1:
+ .globl ld_es
+ld_es:
+ movw TF_ES(%rsp),%es
.globl ld_ds
-ld_ds: movw TF_DS(%rsp),%ds
-ld_regs:movq TF_RDI(%rsp),%rdi
+ld_ds:
+ movw TF_DS(%rsp),%ds
+ld_regs:
+ movq TF_RDI(%rsp),%rdi
movq TF_RSI(%rsp),%rsi
movq TF_RDX(%rsp),%rdx
movq TF_RCX(%rsp),%rcx
@@ -711,7 +720,8 @@ ld_regs:movq TF_RDI(%rsp),%rdi
jz 1f /* keep running with kernel GS.base */
cli
swapgs
-1: addq $TF_RIP,%rsp /* skip over tf_err, tf_trapno */
+1:
+ addq $TF_RIP,%rsp /* skip over tf_err, tf_trapno */
.globl doreti_iret
doreti_iret:
iretq
@@ -738,7 +748,8 @@ doreti_iret_fault:
testl $PSL_I,TF_RFLAGS(%rsp)
jz 1f
sti
-1: movw %fs,TF_FS(%rsp)
+1:
+ movw %fs,TF_FS(%rsp)
movw %gs,TF_GS(%rsp)
movw %es,TF_ES(%rsp)
movw %ds,TF_DS(%rsp)
@@ -768,7 +779,7 @@ doreti_iret_fault:
.globl ds_load_fault
ds_load_fault:
movl $T_PROTFLT,TF_TRAPNO(%rsp)
- movq %rsp, %rdi
+ movq %rsp,%rdi
call trap
movw $KUDSEL,TF_DS(%rsp)
jmp doreti
@@ -777,7 +788,7 @@ ds_load_fault:
.globl es_load_fault
es_load_fault:
movl $T_PROTFLT,TF_TRAPNO(%rsp)
- movq %rsp, %rdi
+ movq %rsp,%rdi
call trap
movw $KUDSEL,TF_ES(%rsp)
jmp doreti
@@ -786,7 +797,7 @@ es_load_fault:
.globl fs_load_fault
fs_load_fault:
movl $T_PROTFLT,TF_TRAPNO(%rsp)
- movq %rsp, %rdi
+ movq %rsp,%rdi
call trap
movw $KUF32SEL,TF_FS(%rsp)
jmp doreti
@@ -796,7 +807,7 @@ fs_load_fault:
gs_load_fault:
popfq
movl $T_PROTFLT,TF_TRAPNO(%rsp)
- movq %rsp, %rdi
+ movq %rsp,%rdi
call trap
movw $KUG32SEL,TF_GS(%rsp)
jmp doreti
@@ -805,7 +816,7 @@ gs_load_fault:
.globl fsbase_load_fault
fsbase_load_fault:
movl $T_PROTFLT,TF_TRAPNO(%rsp)
- movq %rsp, %rdi
+ movq %rsp,%rdi
call trap
movq PCPU(CURTHREAD),%r8
movq TD_PCB(%r8),%r8
@@ -816,7 +827,7 @@ fsbase_load_fault:
.globl gsbase_load_fault
gsbase_load_fault:
movl $T_PROTFLT,TF_TRAPNO(%rsp)
- movq %rsp, %rdi
+ movq %rsp,%rdi
call trap
movq PCPU(CURTHREAD),%r8
movq TD_PCB(%r8),%r8
diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c
index c23102a..52e7568 100644
--- a/sys/amd64/amd64/identcpu.c
+++ b/sys/amd64/amd64/identcpu.c
@@ -240,7 +240,7 @@ printcpuinfo(void)
printf("\n Features2=0x%b", cpu_feature2,
"\020"
"\001SSE3" /* SSE3 */
- "\002<b1>"
+ "\002PCLMULQDQ" /* Carry-Less Mul Quadword */
"\003DTES64" /* 64-bit Debug Trace */
"\004MON" /* MONITOR/MWAIT Instructions */
"\005DS_CPL" /* CPL Qualified Debug Store */
@@ -264,7 +264,7 @@ printcpuinfo(void)
"\027MOVBE"
"\030POPCNT"
"\031<b24>"
- "\032<b25>"
+ "\032AESNI" /* AES Crypto*/
"\033XSAVE"
"\034OSXSAVE"
"\035<b28>"
diff --git a/sys/amd64/amd64/io.c b/sys/amd64/amd64/io.c
index 09d6e89..c2d0d51 100644
--- a/sys/amd64/amd64/io.c
+++ b/sys/amd64/amd64/io.c
@@ -28,60 +28,32 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/fcntl.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mutex.h>
-#include <sys/priv.h>
#include <sys/proc.h>
-#include <sys/signalvar.h>
-#include <sys/systm.h>
-#include <machine/db_machdep.h>
#include <machine/frame.h>
-#include <machine/psl.h>
-#include <machine/specialreg.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
#include <machine/iodev.h>
+#include <machine/psl.h>
-/* ARGSUSED */
int
-ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused,
- struct thread *td)
+iodev_open(struct thread *td)
{
- int error;
-
- error = priv_check(td, PRIV_IO);
- if (error != 0)
- return (error);
- error = securelevel_gt(td->td_ucred, 0);
- if (error != 0)
- return (error);
td->td_frame->tf_rflags |= PSL_IOPL;
-
return (0);
}
-/* ARGSUSED */
int
-ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused,
- struct thread *td)
+iodev_close(struct thread *td)
{
- td->td_frame->tf_rflags &= ~PSL_IOPL;
+ td->td_frame->tf_rflags &= ~PSL_IOPL;
return (0);
}
/* ARGSUSED */
int
-ioioctl(struct cdev *dev __unused, u_long cmd __unused, caddr_t data __unused,
- int fflag __unused, struct thread *td __unused)
+iodev_ioctl(u_long cmd __unused, caddr_t data __unused)
{
- return (ENXIO);
+ return (ENOIOCTL);
}
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index d07292d..045b634 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -793,7 +793,6 @@ static u_long pmap_pdpe_demotions;
SYSCTL_ULONG(_vm_pmap_pdpe, OID_AUTO, demotions, CTLFLAG_RD,
&pmap_pdpe_demotions, 0, "1GB page demotions");
-
/***************************************************
* Low level helper routines.....
***************************************************/
@@ -1200,15 +1199,20 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
{
pd_entry_t pde, *pdep;
pt_entry_t pte;
+ vm_paddr_t pa;
vm_page_t m;
+ pa = 0;
m = NULL;
- vm_page_lock_queues();
PMAP_LOCK(pmap);
+retry:
pdep = pmap_pde(pmap, va);
if (pdep != NULL && (pde = *pdep)) {
if (pde & PG_PS) {
if ((pde & PG_RW) || (prot & VM_PROT_WRITE) == 0) {
+ if (vm_page_pa_tryrelock(pmap, (pde & PG_PS_FRAME) |
+ (va & PDRMASK), &pa))
+ goto retry;
m = PHYS_TO_VM_PAGE((pde & PG_PS_FRAME) |
(va & PDRMASK));
vm_page_hold(m);
@@ -1217,12 +1221,14 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
pte = *pmap_pde_to_pte(pdep, va);
if ((pte & PG_V) &&
((pte & PG_RW) || (prot & VM_PROT_WRITE) == 0)) {
+ if (vm_page_pa_tryrelock(pmap, pte & PG_FRAME, &pa))
+ goto retry;
m = PHYS_TO_VM_PAGE(pte & PG_FRAME);
vm_page_hold(m);
}
}
}
- vm_page_unlock_queues();
+ PA_UNLOCK_COND(pa);
PMAP_UNLOCK(pmap);
return (m);
}
@@ -3143,9 +3149,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
* In the case that a page table page is not
* resident, we are creating it here.
*/
- if (va < VM_MAXUSER_ADDRESS) {
+ if (va < VM_MAXUSER_ADDRESS)
mpte = pmap_allocpte(pmap, va, M_WAITOK);
- }
pde = pmap_pde(pmap, va);
if (pde != NULL && (*pde & PG_V) != 0) {
@@ -3393,7 +3398,7 @@ pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
mpte);
m = TAILQ_NEXT(m, listq);
}
- PMAP_UNLOCK(pmap);
+ PMAP_UNLOCK(pmap);
}
/*
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 8acde03..f3dba94 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -172,52 +172,6 @@ SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW,
extern char *syscallnames[];
-/* #define DEBUG 1 */
-#ifdef DEBUG
-static void
-report_seg_fault(const char *segn, struct trapframe *frame)
-{
- struct proc_ldt *pldt;
- struct trapframe *pf;
-
- pldt = curproc->p_md.md_ldt;
- printf("%d: %s load fault %lx %p %d\n",
- curproc->p_pid, segn, frame->tf_err,
- pldt != NULL ? pldt->ldt_base : NULL,
- pldt != NULL ? pldt->ldt_refcnt : 0);
- kdb_backtrace();
- pf = (struct trapframe *)frame->tf_rsp;
- printf("rdi %lx\n", pf->tf_rdi);
- printf("rsi %lx\n", pf->tf_rsi);
- printf("rdx %lx\n", pf->tf_rdx);
- printf("rcx %lx\n", pf->tf_rcx);
- printf("r8 %lx\n", pf->tf_r8);
- printf("r9 %lx\n", pf->tf_r9);
- printf("rax %lx\n", pf->tf_rax);
- printf("rbx %lx\n", pf->tf_rbx);
- printf("rbp %lx\n", pf->tf_rbp);
- printf("r10 %lx\n", pf->tf_r10);
- printf("r11 %lx\n", pf->tf_r11);
- printf("r12 %lx\n", pf->tf_r12);
- printf("r13 %lx\n", pf->tf_r13);
- printf("r14 %lx\n", pf->tf_r14);
- printf("r15 %lx\n", pf->tf_r15);
- printf("fs %x\n", pf->tf_fs);
- printf("gs %x\n", pf->tf_gs);
- printf("es %x\n", pf->tf_es);
- printf("ds %x\n", pf->tf_ds);
- printf("tno %x\n", pf->tf_trapno);
- printf("adr %lx\n", pf->tf_addr);
- printf("flg %x\n", pf->tf_flags);
- printf("err %lx\n", pf->tf_err);
- printf("rip %lx\n", pf->tf_rip);
- printf("cs %lx\n", pf->tf_cs);
- printf("rfl %lx\n", pf->tf_rflags);
- printf("rsp %lx\n", pf->tf_rsp);
- printf("ss %lx\n", pf->tf_ss);
-}
-#endif
-
/*
* Exception, fault, and trap interface to the FreeBSD kernel.
* This common code is called from assembly language IDT gate entry
@@ -314,9 +268,7 @@ trap(struct trapframe *frame)
*/
printf("kernel trap %d with interrupts disabled\n",
type);
-#ifdef DEBUG
- report_seg_fault("hlt", frame);
-#endif
+
/*
* We shouldn't enable interrupts while holding a
* spin lock or servicing an NMI.
@@ -535,33 +487,21 @@ trap(struct trapframe *frame)
goto out;
}
if (frame->tf_rip == (long)ld_ds) {
-#ifdef DEBUG
- report_seg_fault("ds", frame);
-#endif
frame->tf_rip = (long)ds_load_fault;
frame->tf_ds = _udatasel;
goto out;
}
if (frame->tf_rip == (long)ld_es) {
-#ifdef DEBUG
- report_seg_fault("es", frame);
-#endif
frame->tf_rip = (long)es_load_fault;
frame->tf_es = _udatasel;
goto out;
}
if (frame->tf_rip == (long)ld_fs) {
-#ifdef DEBUG
- report_seg_fault("fs", frame);
-#endif
frame->tf_rip = (long)fs_load_fault;
frame->tf_fs = _ufssel;
goto out;
}
if (frame->tf_rip == (long)ld_gs) {
-#ifdef DEBUG
- report_seg_fault("gs", frame);
-#endif
frame->tf_rip = (long)gs_load_fault;
frame->tf_gs = _ugssel;
goto out;
@@ -667,30 +607,6 @@ trap(struct trapframe *frame)
ksi.ksi_addr = (void *)addr;
trapsignal(td, &ksi);
-#ifdef DEBUG
-{
- register_t rg,rgk, rf;
-
- if (type <= MAX_TRAP_MSG) {
- uprintf("fatal process exception: %s",
- trap_msg[type]);
- if ((type == T_PAGEFLT) || (type == T_PROTFLT))
- uprintf(", fault VA = 0x%lx", frame->tf_addr);
- uprintf("\n");
- }
- rf = rdmsr(0xc0000100);
- rg = rdmsr(0xc0000101);
- rgk = rdmsr(0xc0000102);
- uprintf("pid %d TRAP %d rip %lx err %lx addr %lx cs %lx ss %lx ds %x "
- "es %x fs %x fsbase %lx %lx gs %x gsbase %lx %lx %lx\n",
- curproc->p_pid, type, frame->tf_rip, frame->tf_err,
- frame->tf_addr,
- frame->tf_cs, frame->tf_ss, frame->tf_ds, frame->tf_es,
- frame->tf_fs, td->td_pcb->pcb_fsbase, rf,
- frame->tf_gs, td->td_pcb->pcb_gsbase, rg, rgk);
-}
-#endif
-
user:
userret(td, frame);
mtx_assert(&Giant, MA_NOTOWNED);
diff --git a/sys/amd64/include/iodev.h b/sys/amd64/include/iodev.h
index 1a0a17a..9f53cac 100644
--- a/sys/amd64/include/iodev.h
+++ b/sys/amd64/include/iodev.h
@@ -25,7 +25,22 @@
*
* $FreeBSD$
*/
+#ifndef _MACHINE_IODEV_H_
+#define _MACHINE_IODEV_H_
-d_open_t ioopen;
-d_close_t ioclose;
-d_ioctl_t ioioctl;
+#ifdef _KERNEL
+#include <machine/cpufunc.h>
+
+#define iodev_read_1 inb
+#define iodev_read_2 inw
+#define iodev_read_4 inl
+#define iodev_write_1 outb
+#define iodev_write_2 outw
+#define iodev_write_4 outl
+
+int iodev_open(struct thread *td);
+int iodev_close(struct thread *td);
+int iodev_ioctl(u_long cmd, caddr_t data);
+
+#endif /* _KERNEL */
+#endif /* _MACHINE_IODEV_H_ */
diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h
index 11a5628..6f0b188 100644
--- a/sys/amd64/include/pmap.h
+++ b/sys/amd64/include/pmap.h
@@ -245,6 +245,8 @@ struct pmap {
pml4_entry_t *pm_pml4; /* KVA of level 4 page table */
TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */
u_int pm_active; /* active on cpus */
+ uint32_t pm_gen_count; /* generation count (pmap lock dropped) */
+ u_int pm_retries;
/* spare u_int here due to padding */
struct pmap_statistics pm_stats; /* pmap statistics */
vm_page_t pm_root; /* spare page table pages */
diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h
index 126412c..acea4c0 100644
--- a/sys/amd64/include/proc.h
+++ b/sys/amd64/include/proc.h
@@ -53,8 +53,8 @@ struct mdproc {
struct system_segment_descriptor md_ldt_sd;
};
-#define KINFO_PROC_SIZE 1088
-#define KINFO_PROC32_SIZE 768
+#define KINFO_PROC_SIZE 1088
+#define KINFO_PROC32_SIZE 768
#ifdef _KERNEL
diff --git a/sys/amd64/include/specialreg.h b/sys/amd64/include/specialreg.h
index 86a08ce..895619c 100644
--- a/sys/amd64/include/specialreg.h
+++ b/sys/amd64/include/specialreg.h
@@ -113,6 +113,7 @@
#define CPUID_PBE 0x80000000
#define CPUID2_SSE3 0x00000001
+#define CPUID2_PCLMULQDQ 0x00000002
#define CPUID2_DTES64 0x00000004
#define CPUID2_MON 0x00000008
#define CPUID2_DS_CPL 0x00000010
@@ -131,6 +132,7 @@
#define CPUID2_X2APIC 0x00200000
#define CPUID2_MOVBE 0x00400000
#define CPUID2_POPCNT 0x00800000
+#define CPUID2_AESNI 0x02000000
/*
* Important bits in the AMD extended cpuid flags
diff --git a/sys/amd64/include/vmparam.h b/sys/amd64/include/vmparam.h
index 0b5004c..6dbe371 100644
--- a/sys/amd64/include/vmparam.h
+++ b/sys/amd64/include/vmparam.h
@@ -145,6 +145,10 @@
#define VM_LEVEL_0_ORDER 9
#endif
+#ifdef SMP
+#define PA_LOCK_COUNT 256
+#endif
+
/*
* Virtual addresses of things. Derived from the page directory and
* page table indexes from pmap.h for precision.
diff --git a/sys/amd64/include/xen/xenfunc.h b/sys/amd64/include/xen/xenfunc.h
index b3a6672..d03d4f6 100644
--- a/sys/amd64/include/xen/xenfunc.h
+++ b/sys/amd64/include/xen/xenfunc.h
@@ -1,6 +1,5 @@
-/*
- *
- * Copyright (c) 2004,2005 Kip Macy
+/*-
+ * Copyright (c) 2004, 2005 Kip Macy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,22 +10,22 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 4. 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.
+ * 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 _XEN_XENFUNC_H_
#define _XEN_XENFUNC_H_
diff --git a/sys/amd64/include/xen/xenvar.h b/sys/amd64/include/xen/xenvar.h
index 1433b76..d9dbc5d 100644
--- a/sys/amd64/include/xen/xenvar.h
+++ b/sys/amd64/include/xen/xenvar.h
@@ -1,29 +1,27 @@
-/*
+/*-
* Copyright (c) 2008 Kip Macy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- *
+ * 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$
*/
diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c
index 2f4c3a1..09c2026 100644
--- a/sys/arm/arm/cpufunc.c
+++ b/sys/arm/arm/cpufunc.c
@@ -783,69 +783,66 @@ struct cpu_functions xscalec3_cpufuncs = {
#endif /* CPU_XSCALE_81342 */
-#if defined(CPU_FA526)
+#if defined(CPU_FA526) || defined(CPU_FA626TE)
struct cpu_functions fa526_cpufuncs = {
/* CPU functions */
- .cf_id = cpufunc_id,
- .cf_cpwait = cpufunc_nullop,
+ cpufunc_id, /* id */
+ cpufunc_nullop, /* cpwait */
/* MMU functions */
- .cf_control = cpufunc_control,
- .cf_domains = cpufunc_domains,
- .cf_setttb = fa526_setttb,
- .cf_faultstatus = cpufunc_faultstatus,
- .cf_faultaddress = cpufunc_faultaddress,
+ cpufunc_control, /* control */
+ cpufunc_domains, /* domain */
+ fa526_setttb, /* setttb */
+ cpufunc_faultstatus, /* faultstatus */
+ cpufunc_faultaddress, /* faultaddress */
/* TLB functions */
- .cf_tlb_flushID = armv4_tlb_flushID,
- .cf_tlb_flushID_SE = fa526_tlb_flushID_SE,
- .cf_tlb_flushI = armv4_tlb_flushI,
- .cf_tlb_flushI_SE = fa526_tlb_flushI_SE,
- .cf_tlb_flushD = armv4_tlb_flushD,
- .cf_tlb_flushD_SE = armv4_tlb_flushD_SE,
+ armv4_tlb_flushID, /* tlb_flushID */
+ fa526_tlb_flushID_SE, /* tlb_flushID_SE */
+ armv4_tlb_flushI, /* tlb_flushI */
+ fa526_tlb_flushI_SE, /* tlb_flushI_SE */
+ armv4_tlb_flushD, /* tlb_flushD */
+ armv4_tlb_flushD_SE, /* tlb_flushD_SE */
/* Cache operations */
- .cf_icache_sync_all = fa526_icache_sync_all,
- .cf_icache_sync_range = fa526_icache_sync_range,
-
- .cf_dcache_wbinv_all = fa526_dcache_wbinv_all,
- .cf_dcache_wbinv_range = fa526_dcache_wbinv_range,
- .cf_dcache_inv_range = fa526_dcache_inv_range,
- .cf_dcache_wb_range = fa526_dcache_wb_range,
-
- .cf_idcache_wbinv_all = fa526_idcache_wbinv_all,
- .cf_idcache_wbinv_range = fa526_idcache_wbinv_range,
-
+ fa526_icache_sync_all, /* icache_sync_all */
+ fa526_icache_sync_range, /* icache_sync_range */
- .cf_l2cache_wbinv_all = cpufunc_nullop,
- .cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
- .cf_l2cache_inv_range = (void *)cpufunc_nullop,
- .cf_l2cache_wb_range = (void *)cpufunc_nullop,
+ fa526_dcache_wbinv_all, /* dcache_wbinv_all */
+ fa526_dcache_wbinv_range, /* dcache_wbinv_range */
+ fa526_dcache_inv_range, /* dcache_inv_range */
+ fa526_dcache_wb_range, /* dcache_wb_range */
+ fa526_idcache_wbinv_all, /* idcache_wbinv_all */
+ fa526_idcache_wbinv_range, /* idcache_wbinv_range */
+ cpufunc_nullop, /* l2cache_wbinv_all */
+ (void *)cpufunc_nullop, /* l2cache_wbinv_range */
+ (void *)cpufunc_nullop, /* l2cache_inv_range */
+ (void *)cpufunc_nullop, /* l2cache_wb_range */
/* Other functions */
- .cf_flush_prefetchbuf = fa526_flush_prefetchbuf,
- .cf_drain_writebuf = armv4_drain_writebuf,
- .cf_flush_brnchtgt_C = cpufunc_nullop,
- .cf_flush_brnchtgt_E = fa526_flush_brnchtgt_E,
+ fa526_flush_prefetchbuf, /* flush_prefetchbuf */
+ armv4_drain_writebuf, /* drain_writebuf */
+ cpufunc_nullop, /* flush_brnchtgt_C */
+ fa526_flush_brnchtgt_E, /* flush_brnchtgt_E */
- .cf_sleep = fa526_cpu_sleep,
+ fa526_cpu_sleep, /* sleep */
/* Soft functions */
- .cf_dataabt_fixup = cpufunc_null_fixup,
- .cf_prefetchabt_fixup = cpufunc_null_fixup,
+ cpufunc_null_fixup, /* dataabt_fixup */
+ cpufunc_null_fixup, /* prefetchabt_fixup */
- .cf_context_switch = fa526_context_switch,
+ fa526_context_switch, /* context_switch */
- .cf_setup = fa526_setup
-};
-#endif /* CPU_FA526 */
+ fa526_setup /* cpu setup */
+};
+#endif /* CPU_FA526 || CPU_FA626TE */
/*
@@ -856,11 +853,11 @@ struct cpu_functions cpufuncs;
u_int cputype;
u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */
-#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) || \
- defined (CPU_ARM9E) || defined (CPU_ARM10) || \
- defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
- defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
- defined(CPU_FA526) || \
+#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) || \
+ defined (CPU_ARM9E) || defined (CPU_ARM10) || \
+ defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+ defined(CPU_FA526) || defined(CPU_FA626TE) || \
defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
static void get_cachetype_cp15(void);
@@ -1141,8 +1138,8 @@ set_cpufuncs()
goto out;
}
#endif /* CPU_SA1110 */
-#ifdef CPU_FA526
- if (cputype == CPU_ID_FA526) {
+#if defined(CPU_FA526) || defined(CPU_FA626TE)
+ if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) {
cpufuncs = fa526_cpufuncs;
cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */
get_cachetype_cp15();
@@ -1153,7 +1150,7 @@ set_cpufuncs()
goto out;
}
-#endif /* CPU_FA526 */
+#endif /* CPU_FA526 || CPU_FA626TE */
#ifdef CPU_IXP12X0
if (cputype == CPU_ID_IXP1200) {
cpufuncs = ixp12x0_cpufuncs;
@@ -1629,7 +1626,7 @@ late_abort_fixup(arg)
defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
defined(CPU_ARM10) || defined(CPU_ARM11) || \
- defined(CPU_FA526)
+ defined(CPU_FA526) || defined(CPU_FA626TE)
#define IGN 0
#define OR 1
@@ -2095,7 +2092,7 @@ sa11x0_setup(args)
}
#endif /* CPU_SA1100 || CPU_SA1110 */
-#if defined(CPU_FA526)
+#if defined(CPU_FA526) || defined(CPU_FA626TE)
struct cpu_option fa526_options[] = {
#ifdef COMPAT_12
{ "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE |
@@ -2149,7 +2146,7 @@ fa526_setup(char *args)
ctrl = cpuctrl;
cpu_control(0xffffffff, cpuctrl);
}
-#endif /* CPU_FA526 */
+#endif /* CPU_FA526 || CPU_FA626TE */
#if defined(CPU_IXP12X0)
diff --git a/sys/arm/arm/cpufunc_asm_fa526.S b/sys/arm/arm/cpufunc_asm_fa526.S
index d68d7a6..d53d29a 100644
--- a/sys/arm/arm/cpufunc_asm_fa526.S
+++ b/sys/arm/arm/cpufunc_asm_fa526.S
@@ -32,7 +32,11 @@
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
+#ifdef CPU_FA526
#define CACHELINE_SIZE 16
+#else
+#define CACHELINE_SIZE 32
+#endif
ENTRY(fa526_setttb)
mov r1, #0
diff --git a/sys/arm/arm/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c
index 6addbc3..0f725c8 100644
--- a/sys/arm/arm/elf_trampoline.c
+++ b/sys/arm/arm/elf_trampoline.c
@@ -57,7 +57,7 @@ void __startC(void);
#define cpu_idcache_wbinv_all arm8_cache_purgeID
#elif defined(CPU_ARM9)
#define cpu_idcache_wbinv_all arm9_idcache_wbinv_all
-#elif defined(CPU_FA526)
+#elif defined(CPU_FA526) || defined(CPU_FA626TE)
#define cpu_idcache_wbinv_all fa526_idcache_wbinv_all
#elif defined(CPU_ARM9E)
#define cpu_idcache_wbinv_all armv5_ec_idcache_wbinv_all
diff --git a/sys/arm/arm/identcpu.c b/sys/arm/arm/identcpu.c
index 6d2a0f0..1a9c996 100644
--- a/sys/arm/arm/identcpu.c
+++ b/sys/arm/arm/identcpu.c
@@ -220,7 +220,9 @@ const struct cpuidtab cpuids[] = {
generic_steppings },
{ CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S",
generic_steppings },
- { CPU_ID_FA526, CPU_CLASS_ARM9, "FA526",
+ { CPU_ID_FA526, CPU_CLASS_ARM9, "FA526",
+ generic_steppings },
+ { CPU_ID_FA626TE, CPU_CLASS_ARM9ES, "FA626TE",
generic_steppings },
{ CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T",
diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c
index 366b43f..8fe6424 100644
--- a/sys/arm/arm/pmap.c
+++ b/sys/arm/arm/pmap.c
@@ -3740,13 +3740,14 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
struct l2_dtable *l2;
pd_entry_t l1pd;
pt_entry_t *ptep, pte;
- vm_paddr_t pa;
+ vm_paddr_t pa, paddr;
vm_page_t m = NULL;
u_int l1idx;
l1idx = L1_IDX(va);
+ paddr = 0;
- vm_page_lock_queues();
PMAP_LOCK(pmap);
+retry:
l1pd = pmap->pm_l1->l1_kva[l1idx];
if (l1pte_section_p(l1pd)) {
/*
@@ -3758,6 +3759,8 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
else
pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET);
+ if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr))
+ goto retry;
if (l1pd & L1_S_PROT_W || (prot & VM_PROT_WRITE) == 0) {
m = PHYS_TO_VM_PAGE(pa);
vm_page_hold(m);
@@ -3774,7 +3777,6 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
if (l2 == NULL ||
(ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) {
PMAP_UNLOCK(pmap);
- vm_page_unlock_queues();
return (NULL);
}
@@ -3783,7 +3785,6 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
if (pte == 0) {
PMAP_UNLOCK(pmap);
- vm_page_unlock_queues();
return (NULL);
}
if (pte & L2_S_PROT_W || (prot & VM_PROT_WRITE) == 0) {
@@ -3796,13 +3797,15 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
break;
}
+ if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr))
+ goto retry;
m = PHYS_TO_VM_PAGE(pa);
vm_page_hold(m);
}
}
PMAP_UNLOCK(pmap);
- vm_page_unlock_queues();
+ PA_UNLOCK_COND(paddr);
return (m);
}
diff --git a/sys/arm/at91/if_ate.c b/sys/arm/at91/if_ate.c
index 2f6b741..b065482 100644
--- a/sys/arm/at91/if_ate.c
+++ b/sys/arm/at91/if_ate.c
@@ -272,8 +272,8 @@ ate_attach(device_t dev)
ifp->if_ioctl = ateioctl;
ifp->if_init = ateinit;
ifp->if_baudrate = 10000000;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ifp->if_linkmib = &sc->mibdata;
ifp->if_linkmiblen = sizeof(sc->mibdata);
diff --git a/sys/arm/include/cpuconf.h b/sys/arm/include/cpuconf.h
index 942b591..c8a9b6e 100644
--- a/sys/arm/include/cpuconf.h
+++ b/sys/arm/include/cpuconf.h
@@ -62,6 +62,7 @@
defined(CPU_XSCALE_80321) + \
defined(CPU_XSCALE_PXA2X0) + \
defined(CPU_FA526) + \
+ defined(CPU_FA626TE) + \
defined(CPU_XSCALE_IXP425))
/*
@@ -78,7 +79,7 @@
#if (defined(CPU_ARM9E) || defined(CPU_ARM10) || \
defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \
- defined(CPU_XSCALE_PXA2X0))
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_FA626TE))
#define ARM_ARCH_5 1
#else
#define ARM_ARCH_5 0
@@ -126,7 +127,8 @@
#if (defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) || \
defined(CPU_ARM8) || defined(CPU_ARM9) || defined(CPU_ARM9E) || \
- defined(CPU_ARM10) || defined(CPU_ARM11) || defined(CPU_FA526))
+ defined(CPU_ARM10) || defined(CPU_ARM11) || defined(CPU_FA526) || \
+ defined(CPU_FA626TE))
#define ARM_MMU_GENERIC 1
#else
#define ARM_MMU_GENERIC 0
diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h
index 8494966..4ab63fb 100644
--- a/sys/arm/include/cpufunc.h
+++ b/sys/arm/include/cpufunc.h
@@ -284,7 +284,7 @@ u_int arm8_clock_config (u_int, u_int);
#endif
-#ifdef CPU_FA526
+#if defined(CPU_FA526) || defined(CPU_FA626TE)
void fa526_setup (char *arg);
void fa526_setttb (u_int ttb);
void fa526_context_switch (void);
@@ -464,11 +464,11 @@ extern unsigned armv5_dcache_index_max;
extern unsigned armv5_dcache_index_inc;
#endif
-#if defined(CPU_ARM9) || defined(CPU_ARM9E) || defined(CPU_ARM10) || \
- defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \
- defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
- defined(CPU_FA526) || \
- defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
+#if defined(CPU_ARM9) || defined(CPU_ARM9E) || defined(CPU_ARM10) || \
+ defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \
+ defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
+ defined(CPU_FA526) || defined(CPU_FA626TE) || \
+ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \
defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342)
void armv4_tlb_flushID (void);
diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h
index 8ee7bac..287c4c1 100644
--- a/sys/arm/include/pmap.h
+++ b/sys/arm/include/pmap.h
@@ -134,6 +134,8 @@ struct pmap {
struct l1_ttable *pm_l1;
struct l2_dtable *pm_l2[L2_SIZE];
pd_entry_t *pm_pdir; /* KVA of page directory */
+ uint32_t pm_gen_count; /* generation count (pmap lock dropped) */
+ u_int pm_retries;
int pm_active; /* active on cpus */
struct pmap_statistics pm_stats; /* pmap statictics */
TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */
diff --git a/sys/arm/include/proc.h b/sys/arm/include/proc.h
index 37051bf..0885744 100644
--- a/sys/arm/include/proc.h
+++ b/sys/arm/include/proc.h
@@ -60,6 +60,6 @@ struct mdproc {
void *md_sigtramp;
};
-#define KINFO_PROC_SIZE 792
+#define KINFO_PROC_SIZE 792
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/arm/mv/files.mv b/sys/arm/mv/files.mv
index 36be745..d7352b7 100644
--- a/sys/arm/mv/files.mv
+++ b/sys/arm/mv/files.mv
@@ -30,6 +30,7 @@ arm/mv/timer.c standard
arm/mv/twsi.c optional iicbus
dev/mge/if_mge.c optional mge
+dev/mvs/mvs_soc.c optional mvs
dev/uart/uart_bus_mbus.c optional uart
dev/uart/uart_cpu_mv.c optional uart
dev/uart/uart_dev_ns8250.c optional uart
diff --git a/sys/arm/xscale/ixp425/if_npe.c b/sys/arm/xscale/ixp425/if_npe.c
index 5b605ae..3d8d670 100644
--- a/sys/arm/xscale/ixp425/if_npe.c
+++ b/sys/arm/xscale/ixp425/if_npe.c
@@ -360,7 +360,7 @@ npe_attach(device_t dev)
ifp->if_ioctl = npeioctl;
ifp->if_init = npeinit;
IFQ_SET_MAXLEN(&ifp->if_snd, sc->txdma.nbuf - 1);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ifp->if_linkmib = &sc->mibdata;
ifp->if_linkmiblen = sizeof(sc->mibdata);
diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
index e0e4409..d48d8c4 100644
--- a/sys/boot/forth/loader.conf
+++ b/sys/boot/forth/loader.conf
@@ -197,8 +197,6 @@ if_epair_load="NO" # Virtual b-t-b Ethernet-like interface pair
if_faith_load="NO" # IPv6-to-IPv4 TCP relay capturing interface
if_gif_load="NO" # generic tunnel interface
if_gre_load="NO" # encapsulating network device
-if_ppp_load="NO" # Kernel ppp
-if_sl_load="NO" # SLIP
if_stf_load="NO" # 6to4 tunnel interface
if_tap_load="NO" # Ethernet tunnel software network interface
if_tun_load="NO" # Tunnel driver (user process ppp)
@@ -217,7 +215,6 @@ if_age_load="NO" # Attansic/Atheros L1 Gigabit Ethernet
if_alc_load="NO" # Atheros AR8131/AR8132 Ethernet
if_ale_load="NO" # Atheros AR8121/AR8113/AR8114 Ethernet
if_an_load="NO" # Aironet 4500/4800 802.11 wireless NICs
-if_ar_load="NO" # Digi SYNC/570i
if_ath_load="NO" # Atheros IEEE 802.11 wireless NICs
if_aue_load="NO" # ADMtek AN986 Pegasus USB Ethernet
if_awi_load="NO" # AMD PCnetMobile IEEE 802.11 wireless NICs
@@ -237,6 +234,7 @@ if_ed_load="NO" # National Semiconductor DS8390/WD83C690
if_em_load="NO" # Intel(R) PRO/1000 Gigabit Ethernet
if_en_load="NO" # Midway-based ATM interfaces
if_ep_load="NO" # 3Com Etherlink III (3c5x9)
+if_et_load="NO" # Agere ET1310 10/100/Gigabit Ethernet
if_ex_load="NO" # Intel EtherExpress Pro/10 Ethernet
if_fe_load="NO" # Fujitsu MB86960A/MB86965A based Ethernet
# adapters
@@ -265,17 +263,15 @@ if_nve_load="NO" # NVIDIA nForce MCP Networking Adapter
if_nxge_load="NO" # Neterion Xframe 10Gb Ethernet
if_pcn_load="NO" # AMD PCnet PCI
if_ral_load="NO" # Ralink Technology wireless
-if_ray_load="NO" # Raytheon Raylink/Webgear Aviator PCCard
if_re_load="NO" # RealTek 8139C+/8169/8169S/8110S
if_rl_load="NO" # RealTek 8129/8139
if_rue_load="NO" # RealTek RTL8150 USB to Fast Ethernet
if_sbni_load="NO" # Granch SBNI12 leased line adapters
if_sf_load="NO" # Adaptec Duralink PCI (AIC-6915 "starfire")
-if_sge_load="NO" # Silicon Integrated Systems SiS190/191
+if_sge_load="NO" # Silicon Integrated Systems SiS 190/191
if_sis_load="NO" # Silicon Integrated Systems SiS 900/7016
if_sk_load="NO" # SysKonnect SK-984x series PCI Gigabit Ethernet
if_sn_load="NO" # SMC 91Cxx
-if_sr_load="NO" # synchronous RISCom/N2 / WANic 400/405
if_ste_load="NO" # Sundance Technologies ST201 Fast Ethernet
if_stge_load="NO" # Sundance/Tamarack TC9021 Gigabit Ethernet
if_ti_load="NO" # Alteon Networks Tigon 1 and Tigon 2
diff --git a/sys/boot/sparc64/loader/main.c b/sys/boot/sparc64/loader/main.c
index 2afbfee..b3e7908 100644
--- a/sys/boot/sparc64/loader/main.c
+++ b/sys/boot/sparc64/loader/main.c
@@ -451,7 +451,8 @@ dtlb_va_to_pa_sun4u(vm_offset_t va)
reg = dtlb_get_data_sun4u(i);
wrpr(pstate, pstate, 0);
reg >>= TD_PA_SHIFT;
- if (cpu_impl >= CPU_IMPL_ULTRASPARCIII)
+ if (cpu_impl == CPU_IMPL_SPARC64V ||
+ cpu_impl >= CPU_IMPL_ULTRASPARCIII)
return (reg & TD_PA_CH_MASK);
return (reg & TD_PA_SF_MASK);
}
@@ -474,7 +475,8 @@ itlb_va_to_pa_sun4u(vm_offset_t va)
reg = itlb_get_data_sun4u(i);
wrpr(pstate, pstate, 0);
reg >>= TD_PA_SHIFT;
- if (cpu_impl >= CPU_IMPL_ULTRASPARCIII)
+ if (cpu_impl == CPU_IMPL_SPARC64V ||
+ cpu_impl >= CPU_IMPL_ULTRASPARCIII)
return (reg & TD_PA_CH_MASK);
return (reg & TD_PA_SF_MASK);
}
@@ -696,6 +698,7 @@ cpu_cpuid_prop_sun4u(void)
switch (cpu_impl) {
case CPU_IMPL_SPARC64:
+ case CPU_IMPL_SPARC64V:
case CPU_IMPL_ULTRASPARCI:
case CPU_IMPL_ULTRASPARCII:
case CPU_IMPL_ULTRASPARCIIi:
@@ -720,6 +723,7 @@ cpu_get_mid_sun4u(void)
switch (cpu_impl) {
case CPU_IMPL_SPARC64:
+ case CPU_IMPL_SPARC64V:
case CPU_IMPL_ULTRASPARCI:
case CPU_IMPL_ULTRASPARCII:
case CPU_IMPL_ULTRASPARCIIi:
diff --git a/sys/cam/ata/ata_pmp.c b/sys/cam/ata/ata_pmp.c
index b60a4a7..0835a2b 100644
--- a/sys/cam/ata/ata_pmp.c
+++ b/sys/cam/ata/ata_pmp.c
@@ -101,6 +101,7 @@ struct pmp_softc {
int events;
#define PMP_EV_RESET 1
#define PMP_EV_RESCAN 2
+ u_int caps;
struct task sysctl_task;
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
@@ -457,6 +458,14 @@ pmpstart(struct cam_periph *periph, union ccb *start_ccb)
ata_pm_read_cmd(ataio, 2, 15);
break;
case PMP_STATE_PRECONFIG:
+ /* Get/update host SATA capabilities. */
+ bzero(&cts, sizeof(cts));
+ xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
+ cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+ cts.type = CTS_TYPE_CURRENT_SETTINGS;
+ xpt_action((union ccb *)&cts);
+ if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
+ softc->caps = cts.xport_specific.sata.caps;
cam_fill_ataio(ataio,
pmp_retry_count,
pmpdone,
@@ -644,14 +653,16 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
(done_ccb->ataio.res.lba_mid << 16) +
(done_ccb->ataio.res.lba_low << 8) +
done_ccb->ataio.res.sector_count;
- if ((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) {
+ if (((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) ||
+ (res & 0x600) != 0) {
if (bootverbose) {
printf("%s%d: port %d status: %08x\n",
periph->periph_name, periph->unit_number,
softc->pm_step, res);
}
- /* Report device speed. */
- if (xpt_create_path(&dpath, periph,
+ /* Report device speed if it is online. */
+ if ((res & 0xf0f) == 0x103 &&
+ xpt_create_path(&dpath, periph,
xpt_path_path_id(periph->path),
softc->pm_step, 0) == CAM_REQ_CMP) {
bzero(&cts, sizeof(cts));
@@ -660,6 +671,9 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.xport_specific.sata.revision = (res & 0x0f0) >> 4;
cts.xport_specific.sata.valid = CTS_SATA_VALID_REVISION;
+ cts.xport_specific.sata.caps = softc->caps &
+ (CTS_SATA_CAPS_H_PMREQ | CTS_SATA_CAPS_H_DMAAA);
+ cts.xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
xpt_action((union ccb *)&cts);
xpt_free_path(dpath);
}
diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c
index 3bf9c1e..478b006 100644
--- a/sys/cam/ata/ata_xpt.c
+++ b/sys/cam/ata/ata_xpt.c
@@ -88,6 +88,9 @@ typedef enum {
PROBE_IDENTIFY,
PROBE_SPINUP,
PROBE_SETMODE,
+ PROBE_SETPM,
+ PROBE_SETAPST,
+ PROBE_SETDMAAA,
PROBE_SET_MULTI,
PROBE_INQUIRY,
PROBE_FULL_INQUIRY,
@@ -101,6 +104,9 @@ static char *probe_action_text[] = {
"PROBE_IDENTIFY",
"PROBE_SPINUP",
"PROBE_SETMODE",
+ "PROBE_SETPM",
+ "PROBE_SETAPST",
+ "PROBE_SETDMAAA",
"PROBE_SET_MULTI",
"PROBE_INQUIRY",
"PROBE_FULL_INQUIRY",
@@ -132,6 +138,7 @@ typedef struct {
uint32_t pm_prv;
int restart;
int spinup;
+ u_int caps;
struct cam_periph *periph;
} probe_softc;
@@ -393,6 +400,45 @@ negotiate:
ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
break;
}
+ case PROBE_SETPM:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ CAM_DIR_NONE,
+ 0,
+ NULL,
+ 0,
+ 30*1000);
+ ata_28bit_cmd(ataio, ATA_SETFEATURES,
+ (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90,
+ 0, 0x03);
+ break;
+ case PROBE_SETAPST:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ CAM_DIR_NONE,
+ 0,
+ NULL,
+ 0,
+ 30*1000);
+ ata_28bit_cmd(ataio, ATA_SETFEATURES,
+ (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90,
+ 0, 0x07);
+ break;
+ case PROBE_SETDMAAA:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ CAM_DIR_NONE,
+ 0,
+ NULL,
+ 0,
+ 30*1000);
+ ata_28bit_cmd(ataio, ATA_SETFEATURES,
+ (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90,
+ 0, 0x02);
+ break;
case PROBE_SET_MULTI:
{
u_int sectors, bytecount;
@@ -685,6 +731,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
probe_softc *softc;
struct cam_path *path;
u_int32_t priority;
+ u_int caps;
int found = 1;
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n"));
@@ -768,6 +815,7 @@ noerror:
{
struct ccb_pathinq cpi;
int16_t *ptr;
+ int changed = 1;
ident_buf = &softc->ident_data;
for (ptr = (int16_t *)ident_buf;
@@ -809,9 +857,12 @@ noerror:
sizeof(ident_buf->serial))) {
/* Device changed. */
xpt_async(AC_LOST_DEVICE, path, NULL);
- } else
+ } else {
bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params));
- } else {
+ changed = 0;
+ }
+ }
+ if (changed) {
bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params));
/* Clean up from previous instance of this device */
if (path->device->serial_num != NULL) {
@@ -875,6 +926,67 @@ noerror:
xpt_schedule(periph, priority);
return;
case PROBE_SETMODE:
+ if (path->device->transport != XPORT_SATA)
+ goto notsata;
+ /* Set supported bits. */
+ bzero(&cts, sizeof(cts));
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
+ cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+ cts.type = CTS_TYPE_CURRENT_SETTINGS;
+ xpt_action((union ccb *)&cts);
+ if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
+ caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H;
+ else
+ caps = 0;
+ if (ident_buf->satacapabilities != 0xffff) {
+ if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV)
+ caps |= CTS_SATA_CAPS_D_PMREQ;
+ if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST)
+ caps |= CTS_SATA_CAPS_D_APST;
+ }
+ /* Mask unwanted bits. */
+ bzero(&cts, sizeof(cts));
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
+ cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+ cts.type = CTS_TYPE_USER_SETTINGS;
+ xpt_action((union ccb *)&cts);
+ if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
+ caps &= cts.xport_specific.sata.caps;
+ /* Store result to SIM. */
+ bzero(&cts, sizeof(cts));
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
+ cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
+ cts.type = CTS_TYPE_CURRENT_SETTINGS;
+ cts.xport_specific.sata.caps = caps;
+ cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS;
+ xpt_action((union ccb *)&cts);
+ softc->caps = caps;
+ if (ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) {
+ PROBE_SET_ACTION(softc, PROBE_SETPM);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ }
+ /* FALLTHROUGH */
+ case PROBE_SETPM:
+ if (ident_buf->satacapabilities != 0xffff &&
+ ident_buf->satacapabilities & ATA_SUPPORT_DAPST) {
+ PROBE_SET_ACTION(softc, PROBE_SETAPST);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ }
+ /* FALLTHROUGH */
+ case PROBE_SETAPST:
+ if (ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) {
+ PROBE_SET_ACTION(softc, PROBE_SETDMAAA);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ }
+ /* FALLTHROUGH */
+ case PROBE_SETDMAAA:
+notsata:
if (path->device->protocol == PROTO_ATA) {
PROBE_SET_ACTION(softc, PROBE_SET_MULTI);
} else {
@@ -960,6 +1072,35 @@ noerror:
snprintf(ident_buf->revision, sizeof(ident_buf->revision),
"%04x", softc->pm_prv);
path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
+ /* Set supported bits. */
+ bzero(&cts, sizeof(cts));
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
+ cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+ cts.type = CTS_TYPE_CURRENT_SETTINGS;
+ xpt_action((union ccb *)&cts);
+ if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
+ caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H;
+ else
+ caps = 0;
+ /* All PMPs must support PM requests. */
+ caps |= CTS_SATA_CAPS_D_PMREQ;
+ /* Mask unwanted bits. */
+ bzero(&cts, sizeof(cts));
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
+ cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+ cts.type = CTS_TYPE_USER_SETTINGS;
+ xpt_action((union ccb *)&cts);
+ if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
+ caps &= cts.xport_specific.sata.caps;
+ /* Store result to SIM. */
+ bzero(&cts, sizeof(cts));
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
+ cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
+ cts.type = CTS_TYPE_CURRENT_SETTINGS;
+ cts.xport_specific.sata.caps = caps;
+ cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS;
+ xpt_action((union ccb *)&cts);
+ softc->caps = caps;
if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
path->device->flags &= ~CAM_DEV_UNCONFIGURED;
xpt_acquire_device(path->device);
@@ -1114,13 +1255,13 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
work_ccb = request_ccb;
/* Reuse the same CCB to query if a device was really found */
scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0;
- /* Free the current request path- we're done with it. */
- xpt_free_path(work_ccb->ccb_h.path);
/* If there is PMP... */
if ((scan_info->cpi->hba_inquiry & PI_SATAPM) &&
(scan_info->counter == scan_info->cpi->max_target)) {
if (work_ccb->ccb_h.status == CAM_REQ_CMP) {
- /* everything else willbe probed by it */
+ /* everything else will be probed by it */
+ /* Free the current request path- we're done with it. */
+ xpt_free_path(work_ccb->ccb_h.path);
goto done;
} else {
struct ccb_trans_settings cts;
@@ -1128,7 +1269,7 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
/* Report SIM that PM is absent. */
bzero(&cts, sizeof(cts));
xpt_setup_ccb(&cts.ccb_h,
- scan_info->request_ccb->ccb_h.path, 1);
+ work_ccb->ccb_h.path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.xport_specific.sata.pm_present = 0;
@@ -1136,6 +1277,8 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
xpt_action((union ccb *)&cts);
}
}
+ /* Free the current request path- we're done with it. */
+ xpt_free_path(work_ccb->ccb_h.path);
if (scan_info->counter ==
((scan_info->cpi->hba_inquiry & PI_SATAPM) ?
0 : scan_info->cpi->max_target)) {
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 2810c54..c5ac35e 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -837,12 +837,21 @@ struct ccb_trans_settings_sata {
#define CTS_SATA_VALID_PM 0x08
#define CTS_SATA_VALID_TAGS 0x10
#define CTS_SATA_VALID_ATAPI 0x20
+#define CTS_SATA_VALID_CAPS 0x40
int mode; /* Legacy PATA mode */
u_int bytecount; /* Length of PIO transaction */
int revision; /* SATA revision */
u_int pm_present; /* PM is present (XPT->SIM) */
u_int tags; /* Number of allowed tags */
u_int atapi; /* Length of ATAPI CDB */
+ u_int caps; /* Device and host SATA caps. */
+#define CTS_SATA_CAPS_H 0x0000ffff
+#define CTS_SATA_CAPS_H_PMREQ 0x00000001
+#define CTS_SATA_CAPS_H_APST 0x00000002
+#define CTS_SATA_CAPS_H_DMAAA 0x00000010 /* Auto-activation */
+#define CTS_SATA_CAPS_D 0xffff0000
+#define CTS_SATA_CAPS_D_PMREQ 0x00010000
+#define CTS_SATA_CAPS_D_APST 0x00020000
};
/* Get/Set transfer rate/width/disconnection/tag queueing settings */
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 1812edb..5d83539 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -467,34 +467,7 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
ccb = xpt_alloc_ccb();
CAM_SIM_LOCK(bus->sim);
- /* Ensure passed in target/lun supported on this bus. */
- if ((inccb->ccb_h.target_id != CAM_TARGET_WILDCARD) ||
- (inccb->ccb_h.target_lun != CAM_LUN_WILDCARD)) {
- if (xpt_create_path(&ccb->ccb_h.path,
- xpt_periph,
- inccb->ccb_h.path_id,
- CAM_TARGET_WILDCARD,
- CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- error = EINVAL;
- CAM_SIM_UNLOCK(bus->sim);
- xpt_free_ccb(ccb);
- break;
- }
- xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path,
- inccb->ccb_h.pinfo.priority);
- ccb->ccb_h.func_code = XPT_PATH_INQ;
- xpt_action(ccb);
- xpt_free_path(ccb->ccb_h.path);
- if ((inccb->ccb_h.target_id != CAM_TARGET_WILDCARD &&
- inccb->ccb_h.target_id > ccb->cpi.max_target) ||
- (inccb->ccb_h.target_lun != CAM_LUN_WILDCARD &&
- inccb->ccb_h.target_lun > ccb->cpi.max_lun)) {
- error = EINVAL;
- CAM_SIM_UNLOCK(bus->sim);
- xpt_free_ccb(ccb);
- break;
- }
- }
+
/*
* Create a path using the bus, target, and lun the
* user passed in.
@@ -4901,6 +4874,8 @@ camisr_runqueue(void *V_queue)
if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
&& (--dev->tag_delay_count == 0))
xpt_start_tags(ccb_h->path);
+ if (!device_is_send_queued(dev))
+ xpt_schedule_dev_sendq(ccb_h->path->bus, dev);
}
if (ccb_h->status & CAM_RELEASE_SIMQ) {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
index 3bf0939..053c1e1 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
@@ -464,15 +464,15 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags)
ASSERT(db->db_buf == NULL);
if (db->db_blkid == DB_BONUS_BLKID) {
- int bonuslen = dn->dn_bonuslen;
+ int bonuslen = MIN(dn->dn_bonuslen, dn->dn_phys->dn_bonuslen);
ASSERT3U(bonuslen, <=, db->db.db_size);
db->db.db_data = zio_buf_alloc(DN_MAX_BONUSLEN);
arc_space_consume(DN_MAX_BONUSLEN);
if (bonuslen < DN_MAX_BONUSLEN)
bzero(db->db.db_data, DN_MAX_BONUSLEN);
- bcopy(DN_BONUS(dn->dn_phys), db->db.db_data,
- bonuslen);
+ if (bonuslen)
+ bcopy(DN_BONUS(dn->dn_phys), db->db.db_data, bonuslen);
dbuf_update_data(db);
db->db_state = DB_CACHED;
mutex_exit(&db->db_mtx);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
index 25dfafd..1f91fc1 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
@@ -128,15 +128,6 @@ dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot,
return (0);
}
- tx = dmu_tx_create(os);
- dmu_tx_hold_bonus(tx, object);
- err = dmu_tx_assign(tx, TXG_WAIT);
- if (err) {
- dmu_tx_abort(tx);
- dnode_rele(dn, FTAG);
- return (err);
- }
-
nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
/*
@@ -144,16 +135,27 @@ dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot,
* be a new file instance. We must clear out the previous file
* contents before we can change this type of metadata in the dnode.
*/
- if (dn->dn_nblkptr > nblkptr || dn->dn_datablksz != blocksize)
- dmu_free_long_range(os, object, 0, DMU_OBJECT_END);
+ if (dn->dn_nblkptr > nblkptr || dn->dn_datablksz != blocksize) {
+ err = dmu_free_long_range(os, object, 0, DMU_OBJECT_END);
+ if (err)
+ goto out;
+ }
+
+ tx = dmu_tx_create(os);
+ dmu_tx_hold_bonus(tx, object);
+ err = dmu_tx_assign(tx, TXG_WAIT);
+ if (err) {
+ dmu_tx_abort(tx);
+ goto out;
+ }
dnode_reallocate(dn, ot, blocksize, bonustype, bonuslen, tx);
dmu_tx_commit(tx);
-
+out:
dnode_rele(dn, FTAG);
- return (0);
+ return (err);
}
int
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 7981e06..c9e00d5 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
@@ -1213,6 +1213,39 @@ dmu_objset_find_spa(spa_t *spa, const char *name,
return (err);
}
+/* ARGSUSED */
+int
+dmu_objset_prefetch(char *name, void *arg)
+{
+ dsl_dataset_t *ds;
+
+ if (dsl_dataset_hold(name, FTAG, &ds))
+ return (0);
+
+ if (!BP_IS_HOLE(&ds->ds_phys->ds_bp)) {
+ mutex_enter(&ds->ds_opening_lock);
+ if (!dsl_dataset_get_user_ptr(ds)) {
+ uint32_t aflags = ARC_NOWAIT | ARC_PREFETCH;
+ zbookmark_t zb;
+
+ zb.zb_objset = ds->ds_object;
+ zb.zb_object = 0;
+ zb.zb_level = -1;
+ zb.zb_blkid = 0;
+
+ (void) arc_read_nolock(NULL, dsl_dataset_get_spa(ds),
+ &ds->ds_phys->ds_bp, NULL, NULL,
+ ZIO_PRIORITY_ASYNC_READ,
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE,
+ &aflags, &zb);
+ }
+ mutex_exit(&ds->ds_opening_lock);
+ }
+
+ dsl_dataset_rele(ds, FTAG);
+ return (0);
+}
+
void
dmu_objset_set_user(objset_t *os, void *user_ptr)
{
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
index 03af3d1..58a79ca 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
@@ -300,6 +300,7 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
tx = dmu_tx_create_assigned(dp, txg);
dp->dp_read_overhead = 0;
+ start = gethrtime();
zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED);
while (ds = txg_list_remove(&dp->dp_dirty_datasets, txg)) {
if (!list_link_active(&ds->ds_synced_link))
@@ -310,7 +311,6 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
}
DTRACE_PROBE(pool_sync__1setup);
- start = gethrtime();
err = zio_wait(zio);
write_time = gethrtime() - start;
ASSERT(err == 0);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
index 90861ba..888b882 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
@@ -2564,11 +2564,12 @@ spa_tryimport(nvlist_t *tryconfig)
* The act of destroying or exporting a pool is very simple. We make sure there
* is no more pending I/O and any references to the pool are gone. Then, we
* update the pool state and sync all the labels to disk, removing the
- * configuration from the cache afterwards.
+ * configuration from the cache afterwards. If the 'hardforce' flag is set, then
+ * we don't sync the labels or remove the configuration cache.
*/
static int
spa_export_common(char *pool, int new_state, nvlist_t **oldconfig,
- boolean_t force)
+ boolean_t force, boolean_t hardforce)
{
spa_t *spa;
@@ -2636,7 +2637,7 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig,
* so mark them all dirty. spa_unload() will do the
* final sync that pushes these changes out.
*/
- if (new_state != POOL_STATE_UNINITIALIZED) {
+ if (new_state != POOL_STATE_UNINITIALIZED && !hardforce) {
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
spa->spa_state = new_state;
spa->spa_final_txg = spa_last_synced_txg(spa) + 1;
@@ -2656,7 +2657,8 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig,
VERIFY(nvlist_dup(spa->spa_config, oldconfig, 0) == 0);
if (new_state != POOL_STATE_UNINITIALIZED) {
- spa_config_sync(spa, B_TRUE, B_TRUE);
+ if (!hardforce)
+ spa_config_sync(spa, B_TRUE, B_TRUE);
spa_remove(spa);
}
mutex_exit(&spa_namespace_lock);
@@ -2670,16 +2672,19 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig,
int
spa_destroy(char *pool)
{
- return (spa_export_common(pool, POOL_STATE_DESTROYED, NULL, B_FALSE));
+ return (spa_export_common(pool, POOL_STATE_DESTROYED, NULL,
+ B_FALSE, B_FALSE));
}
/*
* Export a storage pool.
*/
int
-spa_export(char *pool, nvlist_t **oldconfig, boolean_t force)
+spa_export(char *pool, nvlist_t **oldconfig, boolean_t force,
+ boolean_t hardforce)
{
- return (spa_export_common(pool, POOL_STATE_EXPORTED, oldconfig, force));
+ return (spa_export_common(pool, POOL_STATE_EXPORTED, oldconfig,
+ force, hardforce));
}
/*
@@ -2690,7 +2695,7 @@ int
spa_reset(char *pool)
{
return (spa_export_common(pool, POOL_STATE_UNINITIALIZED, NULL,
- B_FALSE));
+ B_FALSE, B_FALSE));
}
/*
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h
index 15df29a..1d65727 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h
@@ -26,8 +26,6 @@
#ifndef _SYS_DMU_OBJSET_H
#define _SYS_DMU_OBJSET_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/spa.h>
#include <sys/arc.h>
#include <sys/txg.h>
@@ -118,6 +116,7 @@ int dmu_objset_find(char *name, int func(char *, void *), void *arg,
int flags);
int dmu_objset_find_spa(spa_t *spa, const char *name,
int func(spa_t *, uint64_t, const char *, void *), void *arg, int flags);
+int dmu_objset_prefetch(char *name, void *arg);
void dmu_objset_byteswap(void *buf, size_t size);
int dmu_objset_evict_dbufs(objset_t *os);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
index 99bcb91..b0b758b 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
@@ -333,7 +333,8 @@ extern int spa_import(const char *pool, nvlist_t *config, nvlist_t *props);
extern int spa_import_faulted(const char *, nvlist_t *, nvlist_t *);
extern nvlist_t *spa_tryimport(nvlist_t *tryconfig);
extern int spa_destroy(char *pool);
-extern int spa_export(char *pool, nvlist_t **oldconfig, boolean_t force);
+extern int spa_export(char *pool, nvlist_t **oldconfig, boolean_t force,
+ boolean_t hardforce);
extern int spa_reset(char *pool);
extern void spa_async_request(spa_t *spa, int flag);
extern void spa_async_unrequest(spa_t *spa, int flag);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
index 040e4d7..8650fa1 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
@@ -38,15 +38,22 @@ static void txg_quiesce_thread(void *arg);
int zfs_txg_timeout = 30; /* max seconds worth of delta per txg */
extern int zfs_txg_synctime;
+extern uint64_t zfs_write_limit_override;
SYSCTL_DECL(_vfs_zfs);
-SYSCTL_NODE(_vfs_zfs, OID_AUTO, txg, CTLFLAG_RW, 0, "ZFS TXG");
+SYSCTL_NODE(_vfs_zfs, OID_AUTO, txg, CTLFLAG_RW, 0,
+ "ZFS transaction groups (TXG)");
TUNABLE_INT("vfs.zfs.txg.timeout", &zfs_txg_timeout);
SYSCTL_INT(_vfs_zfs_txg, OID_AUTO, timeout, CTLFLAG_RDTUN, &zfs_txg_timeout, 0,
"Maximum seconds worth of delta per txg");
TUNABLE_INT("vfs.zfs.txg.synctime", &zfs_txg_synctime);
SYSCTL_INT(_vfs_zfs_txg, OID_AUTO, synctime, CTLFLAG_RDTUN, &zfs_txg_synctime,
0, "Target seconds to sync a txg");
+TUNABLE_QUAD("vfs.zfs.txg.write_limit_override", &zfs_write_limit_override);
+SYSCTL_QUAD(_vfs_zfs_txg, OID_AUTO, write_limit_override, CTLFLAG_RW,
+ &zfs_write_limit_override, 0,
+ "Override maximum size of a txg to this size in bytes, "
+ "value of 0 means don't override");
/*
* Prepare the txg subsystem.
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_byteswap.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_byteswap.c
index b6c43f4..cd36696 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_byteswap.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_byteswap.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/zfs_context.h>
#include <sys/vfs.h>
#include <sys/fs/zfs.h>
@@ -50,7 +48,6 @@ zfs_oldace_byteswap(ace_t *ace, int ace_cnt)
void
zfs_ace_byteswap(void *buf, size_t size, boolean_t zfs_layout)
{
-#ifdef TODO
caddr_t end;
caddr_t ptr;
zfs_ace_t *zacep;
@@ -64,6 +61,20 @@ zfs_ace_byteswap(void *buf, size_t size, boolean_t zfs_layout)
while (ptr < end) {
if (zfs_layout) {
+ /*
+ * Avoid overrun. Embedded aces can have one
+ * of several sizes. We don't know exactly
+ * how many our present, only the size of the
+ * buffer containing them. That size may be
+ * larger than needed to hold the aces
+ * present. As long as we do not do any
+ * swapping beyond the end of our block we are
+ * okay. It it safe to swap any non-ace data
+ * within the block since it is just zeros.
+ */
+ if (ptr + sizeof (zfs_ace_hdr_t) > end) {
+ break;
+ }
zacep = (zfs_ace_t *)ptr;
zacep->z_hdr.z_access_mask =
BSWAP_32(zacep->z_hdr.z_access_mask);
@@ -72,6 +83,10 @@ zfs_ace_byteswap(void *buf, size_t size, boolean_t zfs_layout)
BSWAP_16(zacep->z_hdr.z_type);
entry_type = zacep->z_hdr.z_flags & ACE_TYPE_FLAGS;
} else {
+ /* Overrun avoidance */
+ if (ptr + sizeof (ace_t) > end) {
+ break;
+ }
acep = (ace_t *)ptr;
acep->a_access_mask = BSWAP_32(acep->a_access_mask);
acep->a_flags = BSWAP_16(acep->a_flags);
@@ -88,8 +103,14 @@ zfs_ace_byteswap(void *buf, size_t size, boolean_t zfs_layout)
break;
case ACE_IDENTIFIER_GROUP:
default:
+ /* Overrun avoidance */
if (zfs_layout) {
- zacep->z_fuid = BSWAP_64(zacep->z_fuid);
+ if (ptr + sizeof (zfs_ace_t) <= end) {
+ zacep->z_fuid = BSWAP_64(zacep->z_fuid);
+ } else {
+ entry_size = sizeof (zfs_ace_t);
+ break;
+ }
}
switch (ace_type) {
case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
@@ -108,9 +129,6 @@ zfs_ace_byteswap(void *buf, size_t size, boolean_t zfs_layout)
}
ptr = ptr + entry_size;
}
-#else /* TODO */
- panic("%s:%u: TODO", __func__, __LINE__);
-#endif /* TODO */
}
/* ARGSUSED */
@@ -173,7 +191,8 @@ zfs_znode_byteswap(void *buf, size_t size)
if (zp->zp_acl.z_acl_version == ZFS_ACL_VERSION) {
zfs_acl_byteswap((void *)&zp->zp_acl.z_ace_data[0],
ZFS_ACE_SPACE);
- } else
+ } else {
zfs_oldace_byteswap((ace_t *)&zp->zp_acl.z_ace_data[0],
ACE_SLOT_CNT);
+ }
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
index 00e446b..c7bd8ad 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -882,9 +882,10 @@ zfs_ioc_pool_export(zfs_cmd_t *zc)
{
int error;
boolean_t force = (boolean_t)zc->zc_cookie;
+ boolean_t hardforce = (boolean_t)zc->zc_guid;
zfs_log_history(zc);
- error = spa_export(zc->zc_name, NULL, force);
+ error = spa_export(zc->zc_name, NULL, force, hardforce);
return (error);
}
@@ -1349,6 +1350,14 @@ zfs_ioc_dataset_list_next(zfs_cmd_t *zc)
(void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name));
p = zc->zc_name + strlen(zc->zc_name);
+ if (zc->zc_cookie == 0) {
+ uint64_t cookie = 0;
+ int len = sizeof (zc->zc_name) - (p - zc->zc_name);
+
+ while (dmu_dir_list_next(os, len, p, NULL, &cookie) == 0)
+ dmu_objset_prefetch(p, NULL);
+ }
+
do {
error = dmu_dir_list_next(os,
sizeof (zc->zc_name) - (p - zc->zc_name), p,
@@ -1387,6 +1396,9 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
objset_t *os;
int error;
+ if (zc->zc_cookie == 0)
+ dmu_objset_find(zc->zc_name, dmu_objset_prefetch,
+ NULL, DS_FIND_SNAPSHOTS);
error = dmu_objset_open(zc->zc_name,
DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os);
if (error)
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
index 900087b..947f9dd 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
@@ -704,6 +704,8 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
DMU_OT_ZNODE, sizeof (znode_phys_t) + bonuslen, tx);
}
}
+
+ ZFS_OBJ_HOLD_ENTER(zfsvfs, obj);
VERIFY(0 == dmu_bonus_hold(zfsvfs->z_os, obj, NULL, &db));
dmu_buf_will_dirty(db, tx);
@@ -765,9 +767,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
pzp->zp_mode = MAKEIMODE(vap->va_type, vap->va_mode);
if (!(flag & IS_ROOT_NODE)) {
- ZFS_OBJ_HOLD_ENTER(zfsvfs, obj);
*zpp = zfs_znode_alloc(zfsvfs, db, 0);
- ZFS_OBJ_HOLD_EXIT(zfsvfs, obj);
} else {
/*
* If we are creating the root node, the "parent" we
@@ -776,6 +776,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
*zpp = dzp;
}
zfs_perm_init(*zpp, dzp, flag, vap, tx, cr, setaclp, fuidp);
+ ZFS_OBJ_HOLD_EXIT(zfsvfs, obj);
if (!(flag & IS_ROOT_NODE)) {
vnode_t *vp;
@@ -939,19 +940,31 @@ again:
/*
* Not found create new znode/vnode
+ * but only if file exists.
+ *
+ * There is a small window where zfs_vget() could
+ * find this object while a file create is still in
+ * progress. Since a gen number can never be zero
+ * we will check that to determine if its an allocated
+ * file.
*/
- zp = zfs_znode_alloc(zfsvfs, db, doi.doi_data_block_size);
-
- vp = ZTOV(zp);
- vp->v_vflag |= VV_FORCEINSMQ;
- err = insmntque(vp, zfsvfs->z_vfs);
- vp->v_vflag &= ~VV_FORCEINSMQ;
- KASSERT(err == 0, ("insmntque() failed: error %d", err));
- VOP_UNLOCK(vp, 0);
+ if (((znode_phys_t *)db->db_data)->zp_gen != 0) {
+ zp = zfs_znode_alloc(zfsvfs, db, doi.doi_data_block_size);
+ *zpp = zp;
+ vp = ZTOV(zp);
+ vp->v_vflag |= VV_FORCEINSMQ;
+ err = insmntque(vp, zfsvfs->z_vfs);
+ vp->v_vflag &= ~VV_FORCEINSMQ;
+ KASSERT(err == 0, ("insmntque() failed: error %d", err));
+ VOP_UNLOCK(vp, 0);
+ err = 0;
+ } else {
+ dmu_buf_rele(db, NULL);
+ err = ENOENT;
+ }
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
- *zpp = zp;
- return (0);
+ return (err);
}
int
@@ -1440,6 +1453,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
uint64_t norm = 0;
nvpair_t *elem;
int error;
+ int i;
znode_t *rootzp = NULL;
vnode_t vnode;
vattr_t vattr;
@@ -1537,6 +1551,9 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
list_create(&zfsvfs.z_all_znodes, sizeof (znode_t),
offsetof(znode_t, z_link_node));
+ for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
+ mutex_init(&zfsvfs.z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL);
+
ASSERT(!POINTER_IS_VALID(rootzp->z_zfsvfs));
rootzp->z_zfsvfs = &zfsvfs;
zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, 0, NULL, NULL);
@@ -1547,6 +1564,8 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
dmu_buf_rele(rootzp->z_dbuf, NULL);
rootzp->z_dbuf = NULL;
+ for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
+ mutex_destroy(&zfsvfs.z_hold_mtx[i]);
mutex_destroy(&zfsvfs.z_znodes_lock);
rootzp->z_vnode = NULL;
kmem_cache_free(znode_cache, rootzp);
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index 6600976..261126b 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -2628,6 +2628,7 @@ bsd_to_linux_v4l_tuner(struct video_tuner *vt, struct l_video_tuner *lvt)
return (0);
}
+#ifdef COMPAT_LINUX_V4L_CLIPLIST
static int
linux_to_bsd_v4l_clip(struct l_video_clip *lvc, struct video_clip *vc)
{
@@ -2638,6 +2639,7 @@ linux_to_bsd_v4l_clip(struct l_video_clip *lvc, struct video_clip *vc)
vc->next = PTRIN(lvc->next); /* possible pointer size conversion */
return (0);
}
+#endif
static int
linux_to_bsd_v4l_window(struct l_video_window *lvw, struct video_window *vw)
@@ -2698,6 +2700,7 @@ linux_to_bsd_v4l_code(struct l_video_code *lvc, struct video_code *vc)
return (0);
}
+#ifdef COMPAT_LINUX_V4L_CLIPLIST
static int
linux_v4l_clip_copy(void *lvc, struct video_clip **ppvc)
{
@@ -2772,15 +2775,18 @@ linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw)
* example of cliplist use.
*/
plvc = PTRIN(lvw->clips);
+ vw->clips = NULL;
ppvc = &(vw->clips);
while (clipcount-- > 0) {
- if (plvc == 0)
+ if (plvc == 0) {
error = EFAULT;
- if (!error)
- error = linux_v4l_clip_copy(plvc, ppvc);
- if (error) {
- linux_v4l_cliplist_free(vw);
break;
+ } else {
+ error = linux_v4l_clip_copy(plvc, ppvc);
+ if (error) {
+ linux_v4l_cliplist_free(vw);
+ break;
+ }
}
ppvc = &((*ppvc)->next);
plvc = PTRIN(((struct l_video_clip *) plvc)->next);
@@ -2795,6 +2801,7 @@ linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw)
}
return (error);
}
+#endif
static int
linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
@@ -2818,6 +2825,12 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
case LINUX_VIDIOCGTUNER:
if ((error = fget(td, args->fd, &fp)) != 0)
return (error);
+ error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
+ if (error) {
+ fdrop(fp, td);
+ return (error);
+ }
+ linux_to_bsd_v4l_tuner(&l_vtun, &vtun);
error = fo_ioctl(fp, VIDIOCGTUNER, &vtun, td->td_ucred, td);
if (!error) {
bsd_to_linux_v4l_tuner(&vtun, &l_vtun);
@@ -2836,7 +2849,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
return (error);
}
linux_to_bsd_v4l_tuner(&l_vtun, &vtun);
- error = fo_ioctl(fp, VIDIOCSMICROCODE, &vtun, td->td_ucred, td);
+ error = fo_ioctl(fp, VIDIOCSTUNER, &vtun, td->td_ucred, td);
fdrop(fp, td);
return (error);
@@ -2865,14 +2878,18 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
return (error);
}
linux_to_bsd_v4l_window(&l_vwin, &vwin);
+#ifdef COMPAT_LINUX_V4L_CLIPLIST
error = linux_v4l_cliplist_copy(&l_vwin, &vwin);
if (error) {
fdrop(fp, td);
return (error);
}
+#endif
error = fo_ioctl(fp, VIDIOCSWIN, &vwin, td->td_ucred, td);
fdrop(fp, td);
+#ifdef COMPAT_LINUX_V4L_CLIPLIST
linux_v4l_cliplist_free(&vwin);
+#endif
return (error);
case LINUX_VIDIOCGFBUF:
@@ -2924,7 +2941,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
return (error);
}
linux_to_bsd_v4l_code(&l_vcode, &vcode);
- error = fo_ioctl(fp, VIDIOCSTUNER, &vcode, td->td_ucred, td);
+ error = fo_ioctl(fp, VIDIOCSMICROCODE, &vcode, td->td_ucred, td);
fdrop(fp, td);
return (error);
diff --git a/sys/compat/x86bios/x86bios.c b/sys/compat/x86bios/x86bios.c
index d5512fc..cb8b85e 100644
--- a/sys/compat/x86bios/x86bios.c
+++ b/sys/compat/x86bios/x86bios.c
@@ -47,11 +47,15 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#include <machine/cpufunc.h>
+#include <machine/iodev.h>
#include <vm/vm.h>
#include <vm/pmap.h>
+#if defined(__amd64__) || defined(__i386__)
+#define X86BIOS_NATIVE_ARCH
+#endif
+
#define X86BIOS_PAGE_SIZE 0x00001000 /* 4K */
#define X86BIOS_IVT_SIZE 0x00000500 /* 1K + 256 (BDA) */
@@ -236,27 +240,49 @@ x86bios_emu_inb(struct x86emu *emu, uint16_t port)
if (port >= 0x80 && port < 0x88) /* POST status register */
return (0);
- return (inb(port));
+ return (iodev_read_1(port));
}
static uint16_t
x86bios_emu_inw(struct x86emu *emu, uint16_t port)
{
+ uint16_t val;
if (port >= 0x80 && port < 0x88) /* POST status register */
return (0);
- return (inw(port));
+#ifndef X86BIOS_NATIVE_ARCH
+ if ((port & 1) != 0) {
+ val = iodev_read_1(port);
+ val |= iodev_read_1(port + 1) << 8;
+ } else
+#endif
+ val = iodev_read_2(port);
+
+ return (val);
}
static uint32_t
x86bios_emu_inl(struct x86emu *emu, uint16_t port)
{
+ uint32_t val;
if (port >= 0x80 && port < 0x88) /* POST status register */
return (0);
- return (inl(port));
+#ifndef X86BIOS_NATIVE_ARCH
+ if ((port & 1) != 0) {
+ val = iodev_read_1(port);
+ val |= iodev_read_2(port + 1) << 8;
+ val |= iodev_read_1(port + 3) << 24;
+ } else if ((port & 2) != 0) {
+ val = iodev_read_2(port);
+ val |= iodev_read_2(port + 2) << 16;
+ } else
+#endif
+ val = iodev_read_4(port);
+
+ return (val);
}
static void
@@ -268,7 +294,7 @@ x86bios_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val)
if (port >= 0x80 && port < 0x88) /* POST status register */
return;
- outb(port, val);
+ iodev_write_1(port, val);
}
static void
@@ -278,7 +304,13 @@ x86bios_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val)
if (port >= 0x80 && port < 0x88) /* POST status register */
return;
- outw(port, val);
+#ifndef X86BIOS_NATIVE_ARCH
+ if ((port & 1) != 0) {
+ iodev_write_1(port, val);
+ iodev_write_1(port + 1, val >> 8);
+ } else
+#endif
+ iodev_write_2(port, val);
}
static void
@@ -288,7 +320,17 @@ x86bios_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val)
if (port >= 0x80 && port < 0x88) /* POST status register */
return;
- outl(port, val);
+#ifndef X86BIOS_NATIVE_ARCH
+ if ((port & 1) != 0) {
+ iodev_write_1(port, val);
+ iodev_write_2(port + 1, val >> 8);
+ iodev_write_1(port + 3, val >> 24);
+ } else if ((port & 2) != 0) {
+ iodev_write_2(port, val);
+ iodev_write_2(port + 2, val >> 16);
+ } else
+#endif
+ iodev_write_4(port, val);
}
static void
@@ -484,45 +526,53 @@ x86bios_match_device(uint32_t offset, device_t dev)
return (1);
}
-#if defined(__amd64__) || (defined(__i386__) && !defined(PC98))
-#define PROBE_EBDA 1
+static __inline void
+x86bios_unmap_mem(void)
+{
+
+ if (x86bios_ivt != NULL)
+#ifdef X86BIOS_NATIVE_ARCH
+ pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE);
#else
-#define PROBE_EBDA 0
+ free(x86bios_ivt, M_DEVBUF);
#endif
+ if (x86bios_rom != NULL)
+ pmap_unmapdev((vm_offset_t)x86bios_rom, X86BIOS_ROM_SIZE);
+ if (x86bios_seg != NULL)
+ contigfree(x86bios_seg, X86BIOS_SEG_SIZE, M_DEVBUF);
+}
static __inline int
x86bios_map_mem(void)
{
+#ifdef X86BIOS_NATIVE_ARCH
x86bios_ivt = pmap_mapbios(X86BIOS_IVT_BASE, X86BIOS_IVT_SIZE);
- if (x86bios_ivt == NULL)
- return (1);
-#if PROBE_EBDA
+#ifndef PC98
/* Probe EBDA via BDA. */
- x86bios_rom_phys = *(uint16_t *)((vm_offset_t)x86bios_ivt + 0x40e);
- x86bios_rom_phys = le16toh(x86bios_rom_phys) << 4;
+ x86bios_rom_phys = *(uint16_t *)((caddr_t)x86bios_ivt + 0x40e);
+ x86bios_rom_phys = x86bios_rom_phys << 4;
if (x86bios_rom_phys != 0 && x86bios_rom_phys < X86BIOS_ROM_BASE &&
X86BIOS_ROM_BASE - x86bios_rom_phys <= 128 * 1024)
x86bios_rom_phys =
rounddown(x86bios_rom_phys, X86BIOS_PAGE_SIZE);
else
#endif
+#else
+ x86bios_ivt = malloc(X86BIOS_IVT_SIZE, M_DEVBUF, M_ZERO | M_WAITOK);
+#endif
+
x86bios_rom_phys = X86BIOS_ROM_BASE;
x86bios_rom = pmap_mapdev(x86bios_rom_phys, X86BIOS_ROM_SIZE);
- if (x86bios_rom == NULL) {
- pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE);
- return (1);
- }
-#if PROBE_EBDA
+ if (x86bios_rom == NULL)
+ goto fail;
+#if defined(X86BIOS_NATIVE_ARCH) && !defined(PC98)
/* Change attribute for EBDA. */
if (x86bios_rom_phys < X86BIOS_ROM_BASE &&
pmap_change_attr((vm_offset_t)x86bios_rom,
- X86BIOS_ROM_BASE - x86bios_rom_phys, PAT_WRITE_BACK) != 0) {
- pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE);
- pmap_unmapdev((vm_offset_t)x86bios_rom, X86BIOS_ROM_SIZE);
- return (1);
- }
+ X86BIOS_ROM_BASE - x86bios_rom_phys, PAT_WRITE_BACK) != 0)
+ goto fail;
#endif
x86bios_seg = contigmalloc(X86BIOS_SEG_SIZE, M_DEVBUF, M_WAITOK,
@@ -537,12 +587,10 @@ x86bios_map_mem(void)
(uint32_t)x86bios_seg_phys,
X86BIOS_SEG_SIZE + (uint32_t)x86bios_seg_phys - 1,
x86bios_seg);
-#if PROBE_EBDA
if (x86bios_rom_phys < X86BIOS_ROM_BASE)
printf("x86bios: EBDA 0x%06x-0x%06x at %p\n",
(uint32_t)x86bios_rom_phys, X86BIOS_ROM_BASE - 1,
x86bios_rom);
-#endif
printf("x86bios: ROM 0x%06x-0x%06x at %p\n",
X86BIOS_ROM_BASE, X86BIOS_MEM_SIZE - X86BIOS_SEG_SIZE - 1,
(void *)((vm_offset_t)x86bios_rom + X86BIOS_ROM_BASE -
@@ -550,28 +598,22 @@ x86bios_map_mem(void)
}
return (0);
-}
-
-#undef PROBE_EBDA
-static __inline void
-x86bios_unmap_mem(void)
-{
+fail:
+ x86bios_unmap_mem();
- pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE);
- pmap_unmapdev((vm_offset_t)x86bios_rom, X86BIOS_ROM_SIZE);
- contigfree(x86bios_seg, X86BIOS_SEG_SIZE, M_DEVBUF);
+ return (1);
}
-static void
-x86bios_init(void *arg __unused)
+static int
+x86bios_init(void)
{
int i;
- mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_SPIN);
-
if (x86bios_map_mem() != 0)
- return;
+ return (ENOMEM);
+
+ mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_SPIN);
x86bios_map = malloc(sizeof(*x86bios_map) * X86BIOS_PAGES, M_DEVBUF,
M_WAITOK | M_ZERO);
@@ -600,10 +642,12 @@ x86bios_init(void *arg __unused)
for (i = 0; i < 256; i++)
x86bios_emu._x86emu_intrTab[i] = x86bios_emu_get_intr;
+
+ return (0);
}
-static void
-x86bios_uninit(void *arg __unused)
+static int
+x86bios_uninit(void)
{
vm_offset_t *map = x86bios_map;
@@ -618,6 +662,8 @@ x86bios_uninit(void *arg __unused)
x86bios_unmap_mem();
mtx_destroy(&x86bios_lock);
+
+ return (0);
}
static int
@@ -626,16 +672,12 @@ x86bios_modevent(module_t mod __unused, int type, void *data __unused)
switch (type) {
case MOD_LOAD:
- x86bios_init(NULL);
- break;
+ return (x86bios_init());
case MOD_UNLOAD:
- x86bios_uninit(NULL);
- break;
+ return (x86bios_uninit());
default:
return (ENOTSUP);
}
-
- return (0);
}
static moduledata_t x86bios_mod = {
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index f0cc9a0..1ec82a9 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1660,12 +1660,14 @@ device twe # 3ware ATA RAID
# Serial ATA host controllers:
#
# ahci: Advanced Host Controller Interface (AHCI) compatible
+# mvs: Marvell 88SX50XX/88SX60XX/88SX70XX/SoC controllers
# siis: SiliconImage SiI3124/SiI3132/SiI3531 controllers
#
# These drivers are part of cam(4) subsystem. They supersede less featured
# ata(4) subsystem drivers, supporting same hardware.
device ahci
+device mvs
device siis
#
@@ -2091,6 +2093,15 @@ device ath_hal # pci/cardbus chip support
#device ath_rf5413
#device ath_ar5416 # AR5416 chips
options AH_SUPPORT_AR5416 # enable AR5416 tx/rx descriptors
+# All of the AR5212 parts have a problem when paired with the AR71xx
+# CPUS. These parts have a bug that triggers a fatal bus error on the AR71xx
+# only. Details of the exact nature of the bug are sketchy, but some can be
+# found at https://forum.openwrt.org/viewtopic.php?pid=70060 on pages 4, 5 and
+# 6. This option enables this workaround. There is a performance penalty
+# for this work around, but without it things don't work at all. The DMA
+# from the card usually bursts 128 bytes, but on the affected CPUs, only
+# 4 are safe.
+options AH_RXCFG_SDMAMW_4BYTES
#device ath_ar9160 # AR9160 chips
#device ath_ar9280 # AR9280 chips
#device ath_ar9285 # AR9285 chips
diff --git a/sys/conf/files b/sys/conf/files
index 6bb1355..a485f2f 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -174,6 +174,8 @@ contrib/dev/acpica/dispatcher/dswstate.c optional acpi
contrib/dev/acpica/events/evevent.c optional acpi
contrib/dev/acpica/events/evgpe.c optional acpi
contrib/dev/acpica/events/evgpeblk.c optional acpi
+contrib/dev/acpica/events/evgpeinit.c optional acpi
+contrib/dev/acpica/events/evgpeutil.c optional acpi
contrib/dev/acpica/events/evmisc.c optional acpi
contrib/dev/acpica/events/evregion.c optional acpi
contrib/dev/acpica/events/evrgnini.c optional acpi
@@ -1291,6 +1293,9 @@ dev/mpt/mpt_pci.c optional mpt pci
dev/mpt/mpt_raid.c optional mpt
dev/mpt/mpt_user.c optional mpt
dev/msk/if_msk.c optional msk inet
+dev/mvs/mvs.c optional mvs
+dev/mvs/mvs_if.m standard
+dev/mvs/mvs_pci.c optional mvs pci
dev/mwl/if_mwl.c optional mwl
dev/mwl/if_mwl_pci.c optional mwl pci
dev/mwl/mwlhal.c optional mwl
diff --git a/sys/conf/files.sparc64 b/sys/conf/files.sparc64
index 63ee2c5..3a0620a 100644
--- a/sys/conf/files.sparc64
+++ b/sys/conf/files.sparc64
@@ -138,3 +138,4 @@ sparc64/sparc64/tsb.c standard
sparc64/sparc64/uio_machdep.c standard
sparc64/sparc64/upa.c optional creator
sparc64/sparc64/vm_machdep.c standard
+sparc64/sparc64/zeus.c standard
diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk
index 18bfbb1..c6413d7 100644
--- a/sys/conf/kmod.mk
+++ b/sys/conf/kmod.mk
@@ -342,7 +342,7 @@ MFILES?= dev/acpica/acpi_if.m dev/acpi_support/acpi_wmi_if.m \
dev/agp/agp_if.m dev/ata/ata_if.m dev/eisa/eisa_if.m \
dev/iicbus/iicbb_if.m dev/iicbus/iicbus_if.m \
dev/mmc/mmcbr_if.m dev/mmc/mmcbus_if.m \
- dev/mii/miibus_if.m dev/ofw/ofw_bus_if.m \
+ dev/mii/miibus_if.m dev/mvs/mvs_if.m dev/ofw/ofw_bus_if.m \
dev/pccard/card_if.m dev/pccard/power_if.m dev/pci/pci_if.m \
dev/pci/pcib_if.m dev/ppbus/ppbus_if.m dev/smbus/smbus_if.m \
dev/sound/pcm/ac97_if.m dev/sound/pcm/channel_if.m \
diff --git a/sys/conf/options b/sys/conf/options
index fabc0bf..8f1dcaa 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -771,6 +771,7 @@ AH_PRIVATE_DIAG opt_ah.h
AH_NEED_DESC_SWAP opt_ah.h
AH_USE_INIPDGAIN opt_ah.h
AH_MAXCHAN opt_ah.h
+AH_RXCFG_SDMAMW_4BYTES opt_ah.h
# options for the Broadcom BCM43xx driver (bwi)
BWI_DEBUG opt_bwi.h
diff --git a/sys/conf/options.arm b/sys/conf/options.arm
index 922d38f..6b19281 100644
--- a/sys/conf/options.arm
+++ b/sys/conf/options.arm
@@ -37,3 +37,4 @@ AT91_BWCT opt_at91.h
AT91_TSC opt_at91.h
AT91_KWIKBYTE opt_at91.h
CPU_FA526 opt_global.h
+CPU_FA626TE opt_global.h
diff --git a/sys/contrib/dev/acpica/acpica_prep.sh b/sys/contrib/dev/acpica/acpica_prep.sh
index 3a17041..ebbf8cf 100755
--- a/sys/contrib/dev/acpica/acpica_prep.sh
+++ b/sys/contrib/dev/acpica/acpica_prep.sh
@@ -19,7 +19,7 @@ fulldirs="common compiler debugger disassembler dispatcher events \
tools utilities"
# files to remove
-stripdirs="acpisrc acpixtract examples generate os_specific"
+stripdirs="acpisrc acpixtract examples generate os_specific tests"
stripfiles="Makefile README acintel.h aclinux.h acmsvc.h acnetbsd.h \
acos2.h accygwin.h acefi.h acwin.h acwin64.h aeexec.c \
aehandlers.c aemain.c aetables.c osunixdir.c readme.txt \
diff --git a/sys/contrib/dev/acpica/changes.txt b/sys/contrib/dev/acpica/changes.txt
index d2c8c0e..fed0395 100644
--- a/sys/contrib/dev/acpica/changes.txt
+++ b/sys/contrib/dev/acpica/changes.txt
@@ -1,4 +1,70 @@
----------------------------------------
+28 April 2010. Summary of changes for version 20100428:
+
+1) ACPI CA Core Subsystem:
+
+Implemented GPE support for dynamically loaded ACPI tables. For all GPEs,
+including FADT-based and GPE Block Devices, execute any _PRW methods in the
+new table, and process any _Lxx/_Exx GPE methods in the new table. Any
+runtime GPE that is referenced by an _Lxx/_Exx method in the new table is
+immediately enabled. Handles the FADT-defined GPEs as well as GPE Block
+Devices. Provides compatibility with other ACPI implementations. Two new
+files added, evgpeinit.c and evgpeutil.c. ACPICA BZ 833. Lin Ming, Bob Moore.
+
+Fixed a regression introduced in version 20100331 within the table manager
+where initial table loading could fail. This was introduced in the fix for
+AcpiReallocateRootTable. Also, renamed some of fields in the table manager
+data structures to clarify their meaning and use.
+
+Fixed a possible allocation overrun during internal object copy in
+AcpiUtCopySimpleObject. The original code did not correctly handle the case
+where the object to be copied was a namespace node. Lin Ming. ACPICA BZ 847.
+
+Updated the allocation dump routine, AcpiUtDumpAllocation and fixed a
+possible access beyond end-of-allocation. Also, now fully validate descriptor
+(size and type) before output. Lin Ming, Bob Moore. ACPICA BZ 847
+
+Example Code and Data Size: These are the sizes for the OS-independent
+acpica.lib produced by the Microsoft Visual C++ 6.0 32-bit compiler. The
+debug version of the code includes the debug output trace mechanism and has a
+much larger code and data size.
+
+ Previous Release:
+ Non-Debug Version: 87.9K Code, 18.6K Data, 106.5K Total
+ Debug Version: 163.5K Code, 51.3K Data, 214.8K Total
+ Current Release:
+ Non-Debug Version: 88.4K Code, 18.8K Data, 107.2K Total
+ Debug Version: 164.2K Code, 51.5K Data, 215.7K Total
+
+2) iASL Compiler/Disassembler and Tools:
+
+iASL: Implemented Min/Max/Len/Gran validation for address resource
+descriptors. This change implements validation for the address fields that
+are common to all address-type resource descriptors. These checks are
+implemented: Checks for valid Min/Max, length within the Min/Max window,
+valid granularity, Min/Max a multiple of granularity, and _MIF/_MAF as per
+table 6-40 in the ACPI 4.0a specification. Also split the large aslrestype1.c
+and aslrestype2.c files into five new files. ACPICA BZ 840.
+
+iASL: Added support for the _Wxx predefined names. This support was missing
+and these names were not recognized by the compiler as valid predefined
+names. ACPICA BZ 851.
+
+iASL: Added an error for all predefined names that are defined to return no
+value and thus must be implemented as Control Methods. These include all of
+the _Lxx, _Exx, _Wxx, and _Qxx names, as well as some other miscellaneous
+names such as _DIS, _INI, _IRC, _OFF, _ON, and _PSx. ACPICA BZ 850, 856.
+
+iASL: Implemented the -ts option to emit hex AML data in ASL format, as an
+ASL Buffer. Allows ACPI tables to be easily included within ASL files, to be
+dynamically loaded via the Load() operator. Also cleaned up output for the -
+ta and -tc options. ACPICA BZ 853.
+
+Tests: Added a new file with examples of extended iASL error checking.
+Demonstrates the advanced error checking ability of the iASL compiler.
+Available at tests/misc/badcode.asl.
+
+----------------------------------------
31 March 2010. Summary of changes for version 20100331:
1) ACPI CA Core Subsystem:
diff --git a/sys/contrib/dev/acpica/common/adisasm.c b/sys/contrib/dev/acpica/common/adisasm.c
index fe5ae35..91559c2 100644
--- a/sys/contrib/dev/acpica/common/adisasm.c
+++ b/sys/contrib/dev/acpica/common/adisasm.c
@@ -282,8 +282,8 @@ AdInitialize (
/* Setup the Table Manager (cheat - there is no RSDT) */
- AcpiGbl_RootTableList.Size = 1;
- AcpiGbl_RootTableList.Count = 0;
+ AcpiGbl_RootTableList.MaxTableCount = 1;
+ AcpiGbl_RootTableList.CurrentTableCount = 0;
AcpiGbl_RootTableList.Tables = LocalTables;
return (Status);
@@ -1156,7 +1156,7 @@ AdParseTable (
/* If LoadTable is FALSE, we are parsing the last loaded table */
- TableIndex = AcpiGbl_RootTableList.Count - 1;
+ TableIndex = AcpiGbl_RootTableList.CurrentTableCount - 1;
/* Pass 2 */
diff --git a/sys/contrib/dev/acpica/compiler/aslcompile.c b/sys/contrib/dev/acpica/compiler/aslcompile.c
index 443273c..439c21a 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompile.c
+++ b/sys/contrib/dev/acpica/compiler/aslcompile.c
@@ -177,7 +177,8 @@ AslCompilerSignon (
{
Prefix = "; ";
}
- else if (Gbl_HexOutputFlag == HEX_OUTPUT_C)
+ else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) ||
+ (Gbl_HexOutputFlag == HEX_OUTPUT_ASL))
{
FlPrintFile (ASL_FILE_HEX_OUTPUT, "/*\n");
Prefix = " * ";
@@ -265,7 +266,8 @@ AslCompilerFileHeader (
{
Prefix = "; ";
}
- else if (Gbl_HexOutputFlag == HEX_OUTPUT_C)
+ else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) ||
+ (Gbl_HexOutputFlag == HEX_OUTPUT_ASL))
{
Prefix = " * ";
}
diff --git a/sys/contrib/dev/acpica/compiler/aslcompiler.h b/sys/contrib/dev/acpica/compiler/aslcompiler.h
index dbc2709..a277c67 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompiler.h
+++ b/sys/contrib/dev/acpica/compiler/aslcompiler.h
@@ -592,6 +592,10 @@ FlFileError (
UINT32 FileId,
UINT8 ErrorId);
+UINT32
+FlGetFileSize (
+ UINT32 FileId);
+
ACPI_STATUS
FlReadFile (
UINT32 FileId,
@@ -750,6 +754,34 @@ UtDoConstant (
/*
* aslresource - Resource template generation utilities
*/
+void
+RsSmallAddressCheck (
+ UINT8 Type,
+ UINT32 Minimum,
+ UINT32 Maximum,
+ UINT32 Length,
+ UINT32 Alignment,
+ ACPI_PARSE_OBJECT *MinOp,
+ ACPI_PARSE_OBJECT *MaxOp,
+ ACPI_PARSE_OBJECT *LengthOp,
+ ACPI_PARSE_OBJECT *AlignOp);
+
+void
+RsLargeAddressCheck (
+ UINT64 Minimum,
+ UINT64 Maximum,
+ UINT64 Length,
+ UINT64 Granularity,
+ UINT8 Flags,
+ ACPI_PARSE_OBJECT *MinOp,
+ ACPI_PARSE_OBJECT *MaxOp,
+ ACPI_PARSE_OBJECT *LengthOp,
+ ACPI_PARSE_OBJECT *GranOp);
+
+UINT16
+RsGetStringDataLength (
+ ACPI_PARSE_OBJECT *InitializerOp);
+
ASL_RESOURCE_NODE *
RsAllocateResourceNode (
UINT32 Size);
@@ -805,7 +837,7 @@ RsDoResourceTemplate (
/*
- * aslrestype1 - generate Small descriptors
+ * aslrestype1 - Miscellaneous Small descriptors
*/
ASL_RESOURCE_NODE *
RsDoEndTagDescriptor (
@@ -813,68 +845,72 @@ RsDoEndTagDescriptor (
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
-RsDoDmaDescriptor (
+RsDoEndDependentDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
-RsDoEndDependentDescriptor (
+RsDoMemory24Descriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
-RsDoFixedIoDescriptor (
+RsDoMemory32Descriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
-RsDoIoDescriptor (
+RsDoMemory32FixedDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
-RsDoIrqDescriptor (
+RsDoStartDependentDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
-RsDoIrqNoFlagsDescriptor (
+RsDoStartDependentNoPriDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
-RsDoMemory24Descriptor (
+RsDoVendorSmallDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
+
+/*
+ * aslrestype1i - I/O-related Small descriptors
+ */
ASL_RESOURCE_NODE *
-RsDoMemory32Descriptor (
+RsDoDmaDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
-RsDoMemory32FixedDescriptor (
+RsDoFixedIoDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
-RsDoStartDependentDescriptor (
+RsDoIoDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
-RsDoStartDependentNoPriDescriptor (
+RsDoIrqDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
-RsDoVendorSmallDescriptor (
+RsDoIrqNoFlagsDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
/*
- * aslrestype2 - generate Large descriptors
+ * aslrestype2 - Large resource descriptors
*/
ASL_RESOURCE_NODE *
RsDoInterruptDescriptor (
@@ -882,6 +918,20 @@ RsDoInterruptDescriptor (
UINT32 CurrentByteOffset);
ASL_RESOURCE_NODE *
+RsDoVendorLargeDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset);
+
+ASL_RESOURCE_NODE *
+RsDoGeneralRegisterDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset);
+
+
+/*
+ * aslrestype2d - DWord address descriptors
+ */
+ASL_RESOURCE_NODE *
RsDoDwordIoDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
@@ -896,6 +946,10 @@ RsDoDwordSpaceDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
+
+/*
+ * aslrestype2e - Extended address descriptors
+ */
ASL_RESOURCE_NODE *
RsDoExtendedIoDescriptor (
ACPI_PARSE_OBJECT *Op,
@@ -911,6 +965,10 @@ RsDoExtendedSpaceDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
+
+/*
+ * aslrestype2q - QWord address descriptors
+ */
ASL_RESOURCE_NODE *
RsDoQwordIoDescriptor (
ACPI_PARSE_OBJECT *Op,
@@ -926,6 +984,10 @@ RsDoQwordSpaceDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
+
+/*
+ * aslrestype2w - Word address descriptors
+ */
ASL_RESOURCE_NODE *
RsDoWordIoDescriptor (
ACPI_PARSE_OBJECT *Op,
@@ -941,15 +1003,5 @@ RsDoWordBusNumberDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset);
-ASL_RESOURCE_NODE *
-RsDoVendorLargeDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset);
-
-ASL_RESOURCE_NODE *
-RsDoGeneralRegisterDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset);
-
#endif /* __ASLCOMPILER_H */
diff --git a/sys/contrib/dev/acpica/compiler/asldefine.h b/sys/contrib/dev/acpica/compiler/asldefine.h
index 75345a5..cff4ecf 100644
--- a/sys/contrib/dev/acpica/compiler/asldefine.h
+++ b/sys/contrib/dev/acpica/compiler/asldefine.h
@@ -128,7 +128,7 @@
#define CompilerId "ASL Optimizing Compiler"
#define DisassemblerId "AML Disassembler"
#define CompilerCopyright "Copyright (c) 2000 - 2010 Intel Corporation"
-#define CompilerCompliance "Supports ACPI Specification Revision 4.0"
+#define CompilerCompliance "Supports ACPI Specification Revision 4.0a"
#define CompilerName "iasl"
#define CompilerCreatorId "INTL"
diff --git a/sys/contrib/dev/acpica/compiler/aslfiles.c b/sys/contrib/dev/acpica/compiler/aslfiles.c
index f2e2dca..ca23834 100644
--- a/sys/contrib/dev/acpica/compiler/aslfiles.c
+++ b/sys/contrib/dev/acpica/compiler/aslfiles.c
@@ -236,6 +236,36 @@ FlOpenFile (
/*******************************************************************************
*
+ * FUNCTION: FlGetFileSize
+ *
+ * PARAMETERS: FileId - Index into file info array
+ *
+ * RETURN: File Size
+ *
+ * DESCRIPTION: Get current file size. Uses seek-to-EOF. File must be open.
+ *
+ ******************************************************************************/
+
+UINT32
+FlGetFileSize (
+ UINT32 FileId)
+{
+ FILE *fp;
+ UINT32 FileSize;
+
+
+ fp = Gbl_Files[FileId].Handle;
+
+ fseek (fp, 0, SEEK_END);
+ FileSize = (UINT32) ftell (fp);
+ fseek (fp, 0, SEEK_SET);
+
+ return (FileSize);
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: FlReadFile
*
* PARAMETERS: FileId - Index into file info array
diff --git a/sys/contrib/dev/acpica/compiler/aslglobal.h b/sys/contrib/dev/acpica/compiler/aslglobal.h
index 01ab931..85bb3e2 100644
--- a/sys/contrib/dev/acpica/compiler/aslglobal.h
+++ b/sys/contrib/dev/acpica/compiler/aslglobal.h
@@ -188,6 +188,7 @@ ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_CompileTimesFlag, FALSE
ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_FoldConstants, TRUE);
ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_VerboseErrors, TRUE);
ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_NoErrors, FALSE);
+ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_NoResourceChecking, FALSE);
ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_DisasmFlag, FALSE);
ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_GetAllTables, FALSE);
ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_IntegerOptimizationFlag, TRUE);
@@ -200,6 +201,8 @@ ASL_EXTERN UINT8 ASL_INIT_GLOBAL (Gbl_WarningLevel, ASL_WARNI
#define HEX_OUTPUT_NONE 0
#define HEX_OUTPUT_C 1
#define HEX_OUTPUT_ASM 2
+#define HEX_OUTPUT_ASL 3
+
ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_HexOutputFlag, HEX_OUTPUT_NONE);
diff --git a/sys/contrib/dev/acpica/compiler/asllisting.c b/sys/contrib/dev/acpica/compiler/asllisting.c
index ebac9ca..9458b92 100644
--- a/sys/contrib/dev/acpica/compiler/asllisting.c
+++ b/sys/contrib/dev/acpica/compiler/asllisting.c
@@ -198,6 +198,10 @@ static void
LsDoHexOutputAsm (
void);
+static void
+LsDoHexOutputAsl (
+ void);
+
ACPI_STATUS
LsTreeWriteWalk (
ACPI_PARSE_OBJECT *Op,
@@ -1337,6 +1341,11 @@ LsDoHexOutput (
LsDoHexOutputAsm ();
break;
+ case HEX_OUTPUT_ASL:
+
+ LsDoHexOutputAsl ();
+ break;
+
default:
/* No other output types supported */
break;
@@ -1362,60 +1371,160 @@ static void
LsDoHexOutputC (
void)
{
- UINT32 j;
- UINT8 FileByte[HEX_TABLE_LINE_SIZE];
- UINT8 Buffer[4];
+ UINT8 FileData[HEX_TABLE_LINE_SIZE];
+ UINT32 LineLength;
UINT32 Offset = 0;
+ UINT32 AmlFileSize;
+ UINT32 i;
+
+
+ /* Get AML size, seek back to start */
+ AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " * C source code output\n *\n */\n");
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " * C source code output\n");
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n",
+ AmlFileSize);
FlPrintFile (ASL_FILE_HEX_OUTPUT, "unsigned char AmlCode[] =\n{\n");
- /* Start at the beginning of the AML file */
+ while (Offset < AmlFileSize)
+ {
+ /* Read enough bytes needed for one output line */
- FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
+ LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE,
+ Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
+ if (!LineLength)
+ {
+ break;
+ }
- /* Process all AML bytes in the AML file */
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
- j = 0;
- while (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte[j], 1) == AE_OK)
- {
- if (j == 0)
+ for (i = 0; i < LineLength; i++)
{
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
+ /*
+ * Print each hex byte.
+ * Add a comma until the very last byte of the AML file
+ * (Some C compilers complain about a trailing comma)
+ */
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]);
+ if ((Offset + i + 1) < AmlFileSize)
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
+ }
+ else
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
+ }
}
- /* Convert each AML byte to hex */
+ /* Add fill spaces if needed for last line */
- UtConvertByteToHex (FileByte[j], Buffer);
- FlWriteFile (ASL_FILE_HEX_OUTPUT, Buffer, 4);
- FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
+ if (LineLength < HEX_TABLE_LINE_SIZE)
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
+ 5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
+ }
- /* An occasional linefeed improves readability */
+ /* Emit the offset and ascii dump for the entire line */
- Offset++;
- j++;
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset);
+ LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n",
+ HEX_TABLE_LINE_SIZE - LineLength + 1, " ");
- if (j >= HEX_TABLE_LINE_SIZE)
- {
- /* End of line, emit the ascii dump of the entire line */
+ Offset += LineLength;
+ }
- FlPrintFile (ASL_FILE_HEX_OUTPUT,
- " /* %8.8X", Offset - HEX_TABLE_LINE_SIZE);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "};\n");
+ FlCloseFile (ASL_FILE_HEX_OUTPUT);
+}
- /* Write the ASCII character associated with each of the bytes */
- LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT,
- HEX_TABLE_LINE_SIZE, FileByte);
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " */\n");
+/*******************************************************************************
+ *
+ * FUNCTION: LsDoHexOutputAsl
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Create the hex output file. This is the same data as the AML
+ * output file, but formatted into hex/ascii bytes suitable for
+ * inclusion into a C source file.
+ *
+ ******************************************************************************/
- /* Start new line */
+static void
+LsDoHexOutputAsl (
+ void)
+{
+ UINT8 FileData[HEX_TABLE_LINE_SIZE];
+ UINT32 LineLength;
+ UINT32 Offset = 0;
+ UINT32 AmlFileSize;
+ UINT32 i;
- j = 0;
+
+ /* Get AML size, seek back to start */
+
+ AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " * ASL source code output\n");
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n",
+ AmlFileSize);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " Name (BUF1, Buffer()\n {\n");
+
+ while (Offset < AmlFileSize)
+ {
+ /* Read enough bytes needed for one output line */
+
+ LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE,
+ Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
+ if (!LineLength)
+ {
+ break;
+ }
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
+
+ for (i = 0; i < LineLength; i++)
+ {
+ /*
+ * Print each hex byte.
+ * Add a comma until the very last byte of the AML file
+ * (Some C compilers complain about a trailing comma)
+ */
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]);
+ if ((Offset + i + 1) < AmlFileSize)
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
+ }
+ else
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
+ }
+ }
+
+ /* Add fill spaces if needed for last line */
+
+ if (LineLength < HEX_TABLE_LINE_SIZE)
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
+ 5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
}
+
+ /* Emit the offset and ascii dump for the entire line */
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset);
+ LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n",
+ HEX_TABLE_LINE_SIZE - LineLength + 1, " ");
+
+ Offset += LineLength;
}
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n};\n");
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " })\n");
FlCloseFile (ASL_FILE_HEX_OUTPUT);
}
@@ -1438,58 +1547,64 @@ static void
LsDoHexOutputAsm (
void)
{
- UINT32 j;
- UINT8 FileByte[HEX_TABLE_LINE_SIZE];
- UINT8 Buffer[4];
+ UINT8 FileData[HEX_TABLE_LINE_SIZE];
+ UINT32 LineLength;
UINT32 Offset = 0;
- BOOLEAN DoComma = FALSE;
+ UINT32 AmlFileSize;
+ UINT32 i;
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "; Assembly code source output\n;\n");
+ /* Get AML size, seek back to start */
- /* Start at the beginning of the AML file */
+ AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
- FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "; Assembly code source output\n");
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "; AML code block contains 0x%X bytes\n;\n",
+ AmlFileSize);
- /* Process all AML bytes in the AML file */
-
- j = 0;
- while (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte[j], 1) == AE_OK)
+ while (Offset < AmlFileSize)
{
- if (j == 0)
+ /* Read enough bytes needed for one output line */
+
+ LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE,
+ Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
+ if (!LineLength)
{
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " db ");
+ break;
}
- else if (DoComma)
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " db ");
+
+ for (i = 0; i < LineLength; i++)
{
- FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
- DoComma = FALSE;
+ /*
+ * Print each hex byte.
+ * Add a comma until the last byte of the line
+ */
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "0%2.2Xh", FileData[i]);
+ if ((i + 1) < LineLength)
+ {
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
+ }
}
- /* Convert each AML byte to hex */
-
- UtConvertByteToAsmHex (FileByte[j], Buffer);
- FlWriteFile (ASL_FILE_HEX_OUTPUT, Buffer, 4);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
- /* An occasional linefeed improves readability */
+ /* Add fill spaces if needed for last line */
- Offset++;
- j++;
- if (j >= HEX_TABLE_LINE_SIZE)
+ if (LineLength < HEX_TABLE_LINE_SIZE)
{
- FlPrintFile (ASL_FILE_HEX_OUTPUT,
- " ;%8.8X", Offset - HEX_TABLE_LINE_SIZE);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
+ 5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
+ }
- /* Write the ASCII character associated with each of the bytes */
+ /* Emit the offset and ascii dump for the entire line */
- LsDumpAscii (ASL_FILE_HEX_OUTPUT, HEX_TABLE_LINE_SIZE, FileByte);
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
- j = 0;
- }
- else
- {
- DoComma = TRUE;
- }
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " ; %8.8X", Offset);
+ LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
+
+ Offset += LineLength;
}
FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
diff --git a/sys/contrib/dev/acpica/compiler/aslmain.c b/sys/contrib/dev/acpica/compiler/aslmain.c
index e8b0c45..76be1af 100644
--- a/sys/contrib/dev/acpica/compiler/aslmain.c
+++ b/sys/contrib/dev/acpica/compiler/aslmain.c
@@ -167,7 +167,7 @@ AslDoResponseFile (
#define ASL_TOKEN_SEPARATORS " \t\n"
-#define ASL_SUPPORTED_OPTIONS "@:2b:cd^e:fgh^i^I:l^o:p:r:s:t:v:w:x:"
+#define ASL_SUPPORTED_OPTIONS "@:2b:c:d^e:fgh^i^I:l^no:p:r:s:t:v:w:x:"
/*******************************************************************************
@@ -203,13 +203,14 @@ Options (
printf ("\nAML Output Files:\n");
printf (" -s<a|c> Create AML in assembler or C source file (*.asm or *.c)\n");
printf (" -i<a|c> Create assembler or C include file (*.inc or *.h)\n");
- printf (" -t<a|c> Create AML in assembler or C hex table (*.hex)\n");
+ printf (" -t<a|c|s> Create AML in assembler, C, or ASL hex table (*.hex)\n");
printf ("\nAML Code Generation:\n");
printf (" -oa Disable all optimizations (compatibility mode)\n");
printf (" -of Disable constant folding\n");
printf (" -oi Disable integer optimization to Zero/One/Ones\n");
printf (" -on Disable named reference string optimization\n");
+ printf (" -cr Disable Resource Descriptor error checking\n");
printf (" -r<Revision> Override table header Revision (1-255)\n");
printf ("\nListings:\n");
@@ -264,7 +265,7 @@ HelpMessage (
printf (" -b<p|t|b> Create compiler debug/trace file (*.txt)\n");
printf (" Types: Parse/Tree/Both\n");
printf (" -f Ignore errors, force creation of AML output file(s)\n");
- printf (" -c Parse only, no output generation\n");
+ printf (" -n Parse only, no output generation\n");
printf (" -ot Display compile times\n");
printf (" -x<level> Set debug level for trace output\n");
}
@@ -507,10 +508,16 @@ AslDoOptions (
case 'c':
+ switch (AcpiGbl_Optarg[0])
+ {
+ case 'r':
+ Gbl_NoResourceChecking = TRUE;
+ break;
- /* Parse only */
-
- Gbl_ParseOnlyFlag = TRUE;
+ default:
+ printf ("Unknown option: -c%s\n", AcpiGbl_Optarg);
+ return (-1);
+ }
break;
@@ -688,6 +695,14 @@ AslDoOptions (
break;
+ case 'n':
+
+ /* Parse only */
+
+ Gbl_ParseOnlyFlag = TRUE;
+ break;
+
+
case 'p':
/* Override default AML output filename */
@@ -741,6 +756,10 @@ AslDoOptions (
Gbl_HexOutputFlag = HEX_OUTPUT_C;
break;
+ case 's':
+ Gbl_HexOutputFlag = HEX_OUTPUT_ASL;
+ break;
+
default:
printf ("Unknown option: -t%s\n", AcpiGbl_Optarg);
return (-1);
diff --git a/sys/contrib/dev/acpica/compiler/aslpredef.c b/sys/contrib/dev/acpica/compiler/aslpredef.c
index b9632f9..c3e49cd 100644
--- a/sys/contrib/dev/acpica/compiler/aslpredef.c
+++ b/sys/contrib/dev/acpica/compiler/aslpredef.c
@@ -243,11 +243,11 @@ ApCheckForPredefinedMethod (
break;
- case ACPI_EVENT_RESERVED_NAME: /* _Lxx, _Exx, and _Qxx methods */
+ case ACPI_EVENT_RESERVED_NAME: /* _Lxx/_Exx/_Wxx/_Qxx methods */
Gbl_ReservedMethods++;
- /* NumArguments must be zero for all _Lxx, _Exx, and _Qxx methods */
+ /* NumArguments must be zero for all _Lxx/_Exx/_Wxx/_Qxx methods */
if (MethodInfo->NumArguments != 0)
{
@@ -346,12 +346,12 @@ ApCheckPredefinedReturnValue (
case ACPI_NOT_RESERVED_NAME: /* No underscore or _Txx or _xxx name not matched */
case ACPI_PREDEFINED_NAME: /* Resource Name or reserved scope name */
case ACPI_COMPILER_RESERVED_NAME: /* A _Txx that was not emitted by compiler */
- case ACPI_EVENT_RESERVED_NAME: /* _Lxx, _Exx, and _Qxx methods */
+ case ACPI_EVENT_RESERVED_NAME: /* _Lxx/_Exx/_Wxx/_Qxx methods */
/* Just return, nothing to do */
return;
- default: /* a real predefined ACPI name */
+ default: /* A standard predefined ACPI name */
/* Exit if no return value expected */
@@ -425,29 +425,59 @@ ApCheckForPredefinedObject (
* or a predefined scope name
*/
Index = ApCheckForPredefinedName (Op, Name);
- if (Index > ACPI_VALID_RESERVED_NAME_MAX)
+
+ switch (Index)
{
+ case ACPI_NOT_RESERVED_NAME: /* No underscore or _Txx or _xxx name not matched */
+ case ACPI_PREDEFINED_NAME: /* Resource Name or reserved scope name */
+ case ACPI_COMPILER_RESERVED_NAME: /* A _Txx that was not emitted by compiler */
+
+ /* Nothing to do */
return;
- }
- /*
- * We found a matching predefind name.
- * Check if this predefined name requires input arguments
- */
- if (PredefinedNames[Index].Info.ParamCount > 0)
- {
+ case ACPI_EVENT_RESERVED_NAME: /* _Lxx/_Exx/_Wxx/_Qxx methods */
+
/*
- * This predefined name must always be defined as a control
- * method because it is required to have input arguments.
+ * These names must be control methods, by definition in ACPI spec.
+ * Also because they are defined to return no value. None of them
+ * require any arguments.
*/
AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op,
- "with arguments");
- }
+ "with zero arguments");
+ return;
- /* Typecheck the actual object, it is the next argument */
+ default: /* A standard predefined ACPI name */
- ApCheckObjectType (Op->Asl.Child->Asl.Next,
- PredefinedNames[Index].Info.ExpectedBtypes);
+ /*
+ * If this predefined name requires input arguments, then
+ * it must be implemented as a control method
+ */
+ if (PredefinedNames[Index].Info.ParamCount > 0)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op,
+ "with arguments");
+ return;
+ }
+
+ /*
+ * If no return value is expected from this predefined name, then
+ * it follows that it must be implemented as a control method
+ * (with zero args, because the args > 0 case was handled above)
+ * Examples are: _DIS, _INI, _IRC, _OFF, _ON, _PSx
+ */
+ if (!PredefinedNames[Index].Info.ExpectedBtypes)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op,
+ "with zero arguments");
+ return;
+ }
+
+ /* Typecheck the actual object, it is the next argument */
+
+ ApCheckObjectType (Op->Asl.Child->Asl.Next,
+ PredefinedNames[Index].Info.ExpectedBtypes);
+ return;
+ }
}
@@ -514,7 +544,7 @@ ApCheckForPredefinedName (
}
}
- /* Check for _Lxx, _Exx, _Qxx, _T_x. Warning if unknown predefined name */
+ /* Check for _Lxx/_Exx/_Wxx/_Qxx/_T_x. Warning if unknown predefined name */
return (ApCheckForSpecialName (Op, Name));
}
@@ -530,7 +560,7 @@ ApCheckForPredefinedName (
* RETURN: None
*
* DESCRIPTION: Check for the "special" predefined names -
- * _Lxx, _Exx, _Qxx, and _T_x
+ * _Lxx, _Exx, _Qxx, _Wxx, and _T_x
*
******************************************************************************/
@@ -541,14 +571,16 @@ ApCheckForSpecialName (
{
/*
- * Check for the "special" predefined names. We know the first char is an
- * underscore already.
+ * Check for the "special" predefined names. We already know that the
+ * first character is an underscore.
* GPE: _Lxx
* GPE: _Exx
+ * GPE: _Wxx
* EC: _Qxx
*/
if ((Name[1] == 'L') ||
(Name[1] == 'E') ||
+ (Name[1] == 'W') ||
(Name[1] == 'Q'))
{
/* The next two characters must be hex digits */
diff --git a/sys/contrib/dev/acpica/compiler/aslresource.c b/sys/contrib/dev/acpica/compiler/aslresource.c
index 3242ba7..25289f5 100644
--- a/sys/contrib/dev/acpica/compiler/aslresource.c
+++ b/sys/contrib/dev/acpica/compiler/aslresource.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Module Name: aslresource - Resource templates and descriptors
+ * Module Name: aslresource - Resource template/descriptor utilities
*
*****************************************************************************/
@@ -126,6 +126,298 @@
/*******************************************************************************
*
+ * FUNCTION: RsSmallAddressCheck
+ *
+ * PARAMETERS: Minimum - Address Min value
+ * Maximum - Address Max value
+ * Length - Address range value
+ * Alignment - Address alignment value
+ * MinOp - Original Op for Address Min
+ * MaxOp - Original Op for Address Max
+ * LengthOp - Original Op for address range
+ * AlignOp - Original Op for address alignment. If
+ * NULL, means "zero value for alignment is
+ * OK, and means 64K alignment" (for
+ * Memory24 descriptor)
+ *
+ * RETURN: None. Adds error messages to error log if necessary
+ *
+ * DESCRIPTION: Perform common value checks for "small" address descriptors.
+ * Currently:
+ * Io, Memory24, Memory32
+ *
+ ******************************************************************************/
+
+void
+RsSmallAddressCheck (
+ UINT8 Type,
+ UINT32 Minimum,
+ UINT32 Maximum,
+ UINT32 Length,
+ UINT32 Alignment,
+ ACPI_PARSE_OBJECT *MinOp,
+ ACPI_PARSE_OBJECT *MaxOp,
+ ACPI_PARSE_OBJECT *LengthOp,
+ ACPI_PARSE_OBJECT *AlignOp)
+{
+
+ if (Gbl_NoResourceChecking)
+ {
+ return;
+ }
+
+ /* Special case for Memory24, values are compressed */
+
+ if (Type == ACPI_RESOURCE_NAME_MEMORY24)
+ {
+ if (!Alignment) /* Alignment==0 means 64K - no invalid alignment */
+ {
+ Alignment = ACPI_UINT16_MAX + 1;
+ }
+
+ Minimum <<= 8;
+ Maximum <<= 8;
+ Length *= 256;
+ }
+
+ /* IO descriptor has different definition of min/max, don't check */
+
+ if (Type != ACPI_RESOURCE_NAME_IO)
+ {
+ /* Basic checks on Min/Max/Length */
+
+ if (Minimum > Maximum)
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
+ }
+ else if (Length > (Maximum - Minimum + 1))
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
+ }
+ }
+
+ /* Alignment of zero is not in ACPI spec, but is used to mean byte acc */
+
+ if (!Alignment)
+ {
+ Alignment = 1;
+ }
+
+ /* Addresses must be an exact multiple of the alignment value */
+
+ if (Minimum % Alignment)
+ {
+ AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
+ }
+ if (Maximum % Alignment)
+ {
+ AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, NULL);
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsLargeAddressCheck
+ *
+ * PARAMETERS: Minimum - Address Min value
+ * Maximum - Address Max value
+ * Length - Address range value
+ * Granularity - Address granularity value
+ * Flags - General flags for address descriptors:
+ * _MIF, _MAF, _DEC
+ * MinOp - Original Op for Address Min
+ * MaxOp - Original Op for Address Max
+ * LengthOp - Original Op for address range
+ * GranOp - Original Op for address granularity
+ *
+ * RETURN: None. Adds error messages to error log if necessary
+ *
+ * DESCRIPTION: Perform common value checks for "large" address descriptors.
+ * Currently:
+ * WordIo, WordBusNumber, WordSpace
+ * DWordIo, DWordMemory, DWordSpace
+ * QWordIo, QWordMemory, QWordSpace
+ * ExtendedIo, ExtendedMemory, ExtendedSpace
+ *
+ * _MIF flag set means that the minimum address is fixed and is not relocatable
+ * _MAF flag set means that the maximum address is fixed and is not relocatable
+ * Length of zero means that the record size is variable
+ *
+ * This function implements the LEN/MIF/MAF/MIN/MAX/GRA rules within Table 6-40
+ * of the ACPI 4.0a specification. Added 04/2010.
+ *
+ ******************************************************************************/
+
+void
+RsLargeAddressCheck (
+ UINT64 Minimum,
+ UINT64 Maximum,
+ UINT64 Length,
+ UINT64 Granularity,
+ UINT8 Flags,
+ ACPI_PARSE_OBJECT *MinOp,
+ ACPI_PARSE_OBJECT *MaxOp,
+ ACPI_PARSE_OBJECT *LengthOp,
+ ACPI_PARSE_OBJECT *GranOp)
+{
+
+ if (Gbl_NoResourceChecking)
+ {
+ return;
+ }
+
+ /* Basic checks on Min/Max/Length */
+
+ if (Minimum > Maximum)
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL);
+ return;
+ }
+ else if (Length > (Maximum - Minimum + 1))
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL);
+ return;
+ }
+
+ /* If specified (non-zero), ensure granularity is a power-of-two minus one */
+
+ if (Granularity)
+ {
+ if ((Granularity + 1) &
+ Granularity)
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_GRANULARITY, GranOp, NULL);
+ return;
+ }
+ }
+
+ /*
+ * Check the various combinations of Length, MinFixed, and MaxFixed
+ */
+ if (Length)
+ {
+ /* Fixed non-zero length */
+
+ switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
+ {
+ case 0:
+ /*
+ * Fixed length, variable locations (both _MIN and _MAX).
+ * Length must be a multiple of granularity
+ */
+ if (Granularity & Length)
+ {
+ AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, LengthOp, NULL);
+ }
+ break;
+
+ case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
+
+ /* Fixed length, fixed location. Granularity must be zero */
+
+ if (Granularity != 0)
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_GRAN_FIXED, GranOp, NULL);
+ }
+
+ /* Length must be exactly the size of the min/max window */
+
+ if (Length != (Maximum - Minimum + 1))
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH_FIXED, LengthOp, NULL);
+ }
+ break;
+
+ /* All other combinations are invalid */
+
+ case ACPI_RESOURCE_FLAG_MIF:
+ case ACPI_RESOURCE_FLAG_MAF:
+ default:
+ AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
+ }
+ }
+ else
+ {
+ /* Variable length (length==0) */
+
+ switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF))
+ {
+ case 0:
+ /*
+ * Both _MIN and _MAX are variable.
+ * No additional requirements, just exit
+ */
+ break;
+
+ case ACPI_RESOURCE_FLAG_MIF:
+
+ /* _MIN is fixed. _MIN must be multiple of _GRA */
+
+ /*
+ * The granularity is defined by the ACPI specification to be a
+ * power-of-two minus one, therefore the granularity is a
+ * bitmask which can be used to easily validate the addresses.
+ */
+ if (Granularity & Minimum)
+ {
+ AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL);
+ }
+ break;
+
+ case ACPI_RESOURCE_FLAG_MAF:
+
+ /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */
+
+ if (Granularity & (Maximum + 1))
+ {
+ AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1");
+ }
+ break;
+
+ /* Both MIF/MAF set is invalid if length is zero */
+
+ case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF):
+ default:
+ AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL);
+ }
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsGetStringDataLength
+ *
+ * PARAMETERS: InitializerOp - Start of a subtree of init nodes
+ *
+ * RETURN: Valid string length if a string node is found (otherwise 0)
+ *
+ * DESCRIPTION: In a list of peer nodes, find the first one that contains a
+ * string and return the length of the string.
+ *
+ ******************************************************************************/
+
+UINT16
+RsGetStringDataLength (
+ ACPI_PARSE_OBJECT *InitializerOp)
+{
+
+ while (InitializerOp)
+ {
+ if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
+ {
+ return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1));
+ }
+ InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
+ }
+
+ return 0;
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: RsAllocateResourceNode
*
* PARAMETERS: Size - Size of node in bytes
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype1.c b/sys/contrib/dev/acpica/compiler/aslrestype1.c
index 036abdf..32f2cfc 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype1.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype1.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Module Name: aslrestype1 - Short (type1) resource templates and descriptors
+ * Module Name: aslrestype1 - Miscellaneous small resource descriptors
*
*****************************************************************************/
@@ -121,6 +121,18 @@
#define _COMPONENT ACPI_COMPILER
ACPI_MODULE_NAME ("aslrestype1")
+/*
+ * This module contains miscellaneous small resource descriptors:
+ *
+ * EndTag
+ * EndDependentFn
+ * Memory24
+ * Memory32
+ * Memory32Fixed
+ * StartDependentFn
+ * StartDependentFnNoPri
+ * VendorShort
+ */
/*******************************************************************************
*
@@ -158,127 +170,6 @@ RsDoEndTagDescriptor (
/*******************************************************************************
*
- * FUNCTION: RsDoDmaDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a short "DMA" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoDmaDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT32 i;
- UINT8 DmaChannelMask = 0;
- UINT8 DmaChannels = 0;
-
-
- InitializerOp = Op->Asl.Child;
- Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_DMA));
-
- Descriptor = Rnode->Buffer;
- Descriptor->Dma.DescriptorType = ACPI_RESOURCE_NAME_DMA |
- ASL_RDESC_DMA_SIZE;
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* DMA type */
-
- RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 5, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DMATYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 5);
- break;
-
- case 1: /* Bus Master */
-
- RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_BUSMASTER,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 2);
- break;
-
- case 2: /* Xfer Type (transfer width) */
-
- RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 0, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_XFERTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 0);
- break;
-
- case 3: /* Name */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- default:
-
- /* All DMA channel bytes are handled here, after flags and name */
-
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- /* Up to 8 channels can be specified in the list */
-
- DmaChannels++;
- if (DmaChannels > 8)
- {
- AslError (ASL_ERROR, ASL_MSG_DMA_LIST,
- InitializerOp, NULL);
- return (Rnode);
- }
-
- /* Only DMA channels 0-7 are allowed (mask is 8 bits) */
-
- if (InitializerOp->Asl.Value.Integer > 7)
- {
- AslError (ASL_ERROR, ASL_MSG_DMA_CHANNEL,
- InitializerOp, NULL);
- }
-
- /* Build the mask */
-
- DmaChannelMask |=
- (1 << ((UINT8) InitializerOp->Asl.Value.Integer));
- }
-
- if (i == 4) /* case 4: First DMA byte */
- {
- /* Check now for duplicates in list */
-
- RsCheckListForDuplicates (InitializerOp);
-
- /* Create a named field at the start of the list */
-
- RsCreateByteField (InitializerOp, ACPI_RESTAG_DMA,
- CurrentByteOffset +
- ASL_RESDESC_OFFSET (Dma.DmaChannelMask));
- }
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- /* Now we can set the channel mask */
-
- Descriptor->Dma.DmaChannelMask = DmaChannelMask;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: RsDoEndDependentDescriptor
*
* PARAMETERS: Op - Parent resource descriptor parse node
@@ -311,396 +202,6 @@ RsDoEndDependentDescriptor (
/*******************************************************************************
*
- * FUNCTION: RsDoFixedIoDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a short "FixedIO" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoFixedIoDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT32 i;
-
-
- InitializerOp = Op->Asl.Child;
- Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_IO));
-
- Descriptor = Rnode->Buffer;
- Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_FIXED_IO |
- ASL_RDESC_FIXED_IO_SIZE;
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Base Address */
-
- Descriptor->FixedIo.Address =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_BASEADDRESS,
- CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.Address));
- break;
-
- case 1: /* Length */
-
- Descriptor->FixedIo.AddressLength =
- (UINT8) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.AddressLength));
- break;
-
- case 2: /* Name */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoIoDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a short "IO" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoIoDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT32 i;
-
-
- InitializerOp = Op->Asl.Child;
- Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IO));
-
- Descriptor = Rnode->Buffer;
- Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_IO |
- ASL_RDESC_IO_SIZE;
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Decode size */
-
- RsSetFlagBits (&Descriptor->Io.Flags, InitializerOp, 0, 1);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Flags), 0);
- break;
-
- case 1: /* Min Address */
-
- Descriptor->Io.Minimum =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Minimum));
- break;
-
- case 2: /* Max Address */
-
- Descriptor->Io.Maximum =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Maximum));
- break;
-
- case 3: /* Alignment */
-
- Descriptor->Io.Alignment =
- (UINT8) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Alignment));
- break;
-
- case 4: /* Length */
-
- Descriptor->Io.AddressLength =
- (UINT8) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Io.AddressLength));
- break;
-
- case 5: /* Name */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoIrqDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a short "IRQ" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoIrqDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT32 Interrupts = 0;
- UINT16 IrqMask = 0;
- UINT32 i;
-
-
- InitializerOp = Op->Asl.Child;
- Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ));
-
- /* Length = 3 (with flag byte) */
-
- Descriptor = Rnode->Buffer;
- Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ |
- (ASL_RDESC_IRQ_SIZE + 0x01);
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Interrupt Type (or Mode - edge/level) */
-
- RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 0, 1);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 0);
- break;
-
- case 1: /* Interrupt Level (or Polarity - Active high/low) */
-
- RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 3);
- break;
-
- case 2: /* Share Type - Default: exclusive (0) */
-
- RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 4, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 4);
- break;
-
- case 3: /* Name */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- default:
-
- /* All IRQ bytes are handled here, after the flags and name */
-
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- /* Up to 16 interrupts can be specified in the list */
-
- Interrupts++;
- if (Interrupts > 16)
- {
- AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST,
- InitializerOp, NULL);
- return (Rnode);
- }
-
- /* Only interrupts 0-15 are allowed (mask is 16 bits) */
-
- if (InitializerOp->Asl.Value.Integer > 15)
- {
- AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER,
- InitializerOp, NULL);
- }
- else
- {
- IrqMask |= (1 << (UINT8) InitializerOp->Asl.Value.Integer);
- }
- }
-
- /* Case 4: First IRQ value in list */
-
- if (i == 4)
- {
- /* Check now for duplicates in list */
-
- RsCheckListForDuplicates (InitializerOp);
-
- /* Create a named field at the start of the list */
-
- RsCreateByteField (InitializerOp, ACPI_RESTAG_INTERRUPT,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask));
- }
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- /* Now we can set the channel mask */
-
- Descriptor->Irq.IrqMask = IrqMask;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoIrqNoFlagsDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a short "IRQNoFlags" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoIrqNoFlagsDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT16 IrqMask = 0;
- UINT32 Interrupts = 0;
- UINT32 i;
-
-
- InitializerOp = Op->Asl.Child;
- Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ_NOFLAGS));
-
- Descriptor = Rnode->Buffer;
- Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ |
- ASL_RDESC_IRQ_SIZE;
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Name */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- default:
-
- /* IRQ bytes are handled here, after the flags and name */
-
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- /* Up to 16 interrupts can be specified in the list */
-
- Interrupts++;
- if (Interrupts > 16)
- {
- AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST,
- InitializerOp, NULL);
- return (Rnode);
- }
-
- /* Only interrupts 0-15 are allowed (mask is 16 bits) */
-
- if (InitializerOp->Asl.Value.Integer > 15)
- {
- AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER,
- InitializerOp, NULL);
- }
- else
- {
- IrqMask |= (1 << ((UINT8) InitializerOp->Asl.Value.Integer));
- }
- }
-
- /* Case 1: First IRQ value in list */
-
- if (i == 1)
- {
- /* Check now for duplicates in list */
-
- RsCheckListForDuplicates (InitializerOp);
-
- /* Create a named field at the start of the list */
-
- RsCreateByteField (InitializerOp, ACPI_RESTAG_INTERRUPT,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask));
- }
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- /* Now we can set the interrupt mask */
-
- Descriptor->Irq.IrqMask = IrqMask;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: RsDoMemory24Descriptor
*
* PARAMETERS: Op - Parent resource descriptor parse node
@@ -720,6 +221,10 @@ RsDoMemory24Descriptor (
{
AML_RESOURCE *Descriptor;
ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *AlignOp = NULL;
ASL_RESOURCE_NODE *Rnode;
UINT32 i;
@@ -749,6 +254,7 @@ RsDoMemory24Descriptor (
Descriptor->Memory24.Minimum = (UINT16) InitializerOp->Asl.Value.Integer;
RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.Minimum));
+ MinOp = InitializerOp;
break;
case 2: /* Max Address */
@@ -756,6 +262,7 @@ RsDoMemory24Descriptor (
Descriptor->Memory24.Maximum = (UINT16) InitializerOp->Asl.Value.Integer;
RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.Maximum));
+ MaxOp = InitializerOp;
break;
case 3: /* Alignment */
@@ -763,6 +270,7 @@ RsDoMemory24Descriptor (
Descriptor->Memory24.Alignment = (UINT16) InitializerOp->Asl.Value.Integer;
RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT,
CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.Alignment));
+ AlignOp = InitializerOp;
break;
case 4: /* Length */
@@ -770,6 +278,7 @@ RsDoMemory24Descriptor (
Descriptor->Memory24.AddressLength = (UINT16) InitializerOp->Asl.Value.Integer;
RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.AddressLength));
+ LengthOp = InitializerOp;
break;
case 5: /* Name */
@@ -786,6 +295,15 @@ RsDoMemory24Descriptor (
InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
}
+ /* Validate the Min/Max/Len/Align values (Alignment==0 means 64K) */
+
+ RsSmallAddressCheck (ACPI_RESOURCE_NAME_MEMORY24,
+ Descriptor->Memory24.Minimum,
+ Descriptor->Memory24.Maximum,
+ Descriptor->Memory24.AddressLength,
+ Descriptor->Memory24.Alignment,
+ MinOp, MaxOp, LengthOp, NULL);
+
return (Rnode);
}
@@ -811,6 +329,10 @@ RsDoMemory32Descriptor (
{
AML_RESOURCE *Descriptor;
ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *AlignOp = NULL;
ASL_RESOURCE_NODE *Rnode;
UINT32 i;
@@ -840,6 +362,7 @@ RsDoMemory32Descriptor (
Descriptor->Memory32.Minimum = (UINT32) InitializerOp->Asl.Value.Integer;
RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.Minimum));
+ MinOp = InitializerOp;
break;
case 2: /* Max Address */
@@ -847,6 +370,7 @@ RsDoMemory32Descriptor (
Descriptor->Memory32.Maximum = (UINT32) InitializerOp->Asl.Value.Integer;
RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.Maximum));
+ MaxOp = InitializerOp;
break;
case 3: /* Alignment */
@@ -854,6 +378,7 @@ RsDoMemory32Descriptor (
Descriptor->Memory32.Alignment = (UINT32) InitializerOp->Asl.Value.Integer;
RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT,
CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.Alignment));
+ AlignOp = InitializerOp;
break;
case 4: /* Length */
@@ -861,6 +386,7 @@ RsDoMemory32Descriptor (
Descriptor->Memory32.AddressLength = (UINT32) InitializerOp->Asl.Value.Integer;
RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.AddressLength));
+ LengthOp = InitializerOp;
break;
case 5: /* Name */
@@ -877,6 +403,15 @@ RsDoMemory32Descriptor (
InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
}
+ /* Validate the Min/Max/Len/Align values */
+
+ RsSmallAddressCheck (ACPI_RESOURCE_NAME_MEMORY32,
+ Descriptor->Memory32.Minimum,
+ Descriptor->Memory32.Maximum,
+ Descriptor->Memory32.AddressLength,
+ Descriptor->Memory32.Alignment,
+ MinOp, MaxOp, LengthOp, AlignOp);
+
return (Rnode);
}
@@ -1027,6 +562,7 @@ RsDoStartDependentDescriptor (
break;
default:
+
NextRnode = RsDoOneResourceDescriptor (InitializerOp,
CurrentByteOffset, &State);
@@ -1036,7 +572,6 @@ RsDoStartDependentDescriptor (
* must keep track of the offset of not only each descriptor, but each
* element (field) within each descriptor as well.
*/
-
CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode,
NextRnode);
break;
@@ -1182,4 +717,3 @@ RsDoVendorSmallDescriptor (
return (Rnode);
}
-
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype1i.c b/sys/contrib/dev/acpica/compiler/aslrestype1i.c
new file mode 100644
index 0000000..a2b80cb
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslrestype1i.c
@@ -0,0 +1,668 @@
+
+/******************************************************************************
+ *
+ * Module Name: aslrestype1i - Small I/O-related resource descriptors
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * 1. Copyright Notice
+ *
+ * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * 2. License
+ *
+ * 2.1. This is your license from Intel Corp. under its intellectual property
+ * rights. You may have additional license terms from the party that provided
+ * you this software, covering your right to use that party's intellectual
+ * property rights.
+ *
+ * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
+ * copy of the source code appearing in this file ("Covered Code") an
+ * irrevocable, perpetual, worldwide license under Intel's copyrights in the
+ * base code distributed originally by Intel ("Original Intel Code") to copy,
+ * make derivatives, distribute, use and display any portion of the Covered
+ * Code in any form, with the right to sublicense such rights; and
+ *
+ * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
+ * license (with the right to sublicense), under only those claims of Intel
+ * patents that are infringed by the Original Intel Code, to make, use, sell,
+ * offer to sell, and import the Covered Code and derivative works thereof
+ * solely to the minimum extent necessary to exercise the above copyright
+ * license, and in no event shall the patent license extend to any additions
+ * to or modifications of the Original Intel Code. No other license or right
+ * is granted directly or by implication, estoppel or otherwise;
+ *
+ * The above copyright and patent license is granted only if the following
+ * conditions are met:
+ *
+ * 3. Conditions
+ *
+ * 3.1. Redistribution of Source with Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification with rights to further distribute source must include
+ * the above Copyright Notice, the above License, this list of Conditions,
+ * and the following Disclaimer and Export Compliance provision. In addition,
+ * Licensee must cause all Covered Code to which Licensee contributes to
+ * contain a file documenting the changes Licensee made to create that Covered
+ * Code and the date of any change. Licensee must include in that file the
+ * documentation of any changes made by any predecessor Licensee. Licensee
+ * must include a prominent statement that the modification is derived,
+ * directly or indirectly, from Original Intel Code.
+ *
+ * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification without rights to further distribute source must
+ * include the following Disclaimer and Export Compliance provision in the
+ * documentation and/or other materials provided with distribution. In
+ * addition, Licensee may not authorize further sublicense of source of any
+ * portion of the Covered Code, and must include terms to the effect that the
+ * license from Licensee to its licensee is limited to the intellectual
+ * property embodied in the software Licensee provides to its licensee, and
+ * not to intellectual property embodied in modifications its licensee may
+ * make.
+ *
+ * 3.3. Redistribution of Executable. Redistribution in executable form of any
+ * substantial portion of the Covered Code or modification must reproduce the
+ * above Copyright Notice, and the following Disclaimer and Export Compliance
+ * provision in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3.4. Intel retains all right, title, and interest in and to the Original
+ * Intel Code.
+ *
+ * 3.5. Neither the name Intel nor any other trademark owned or controlled by
+ * Intel shall be used in advertising or otherwise to promote the sale, use or
+ * other dealings in products derived from or relating to the Covered Code
+ * without prior written authorization from Intel.
+ *
+ * 4. Disclaimer and Export Compliance
+ *
+ * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
+ * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
+ * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
+ * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
+ * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
+ * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
+ * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
+ * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
+ * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
+ * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
+ * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
+ * LIMITED REMEDY.
+ *
+ * 4.3. Licensee shall not export, either directly or indirectly, any of this
+ * software or system incorporating such software without first obtaining any
+ * required license or other approval from the U. S. Department of Commerce or
+ * any other agency or department of the United States Government. In the
+ * event Licensee exports any such software from the United States or
+ * re-exports any such software from a foreign destination, Licensee shall
+ * ensure that the distribution and export/re-export of the software is in
+ * compliance with all laws, regulations, orders, or other restrictions of the
+ * U.S. Export Administration Regulations. Licensee agrees that neither it nor
+ * any of its subsidiaries will export/re-export any technical data, process,
+ * software, or service, directly or indirectly, to any country for which the
+ * United States government or any agency thereof requires an export license,
+ * other governmental approval, or letter of assurance, without first obtaining
+ * such license, approval or letter.
+ *
+ *****************************************************************************/
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslrestype1i")
+
+/*
+ * This module contains the I/O-related small resource descriptors:
+ *
+ * DMA
+ * FixedIO
+ * IO
+ * IRQ
+ * IRQNoFlags
+ */
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoDmaDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a short "DMA" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoDmaDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT32 i;
+ UINT8 DmaChannelMask = 0;
+ UINT8 DmaChannels = 0;
+
+
+ InitializerOp = Op->Asl.Child;
+ Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_DMA));
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Dma.DescriptorType = ACPI_RESOURCE_NAME_DMA |
+ ASL_RDESC_DMA_SIZE;
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* DMA type */
+
+ RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 5, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DMATYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 5);
+ break;
+
+ case 1: /* Bus Master */
+
+ RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_BUSMASTER,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 2);
+ break;
+
+ case 2: /* Xfer Type (transfer width) */
+
+ RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 0, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_XFERTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 0);
+ break;
+
+ case 3: /* Name */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ default:
+
+ /* All DMA channel bytes are handled here, after flags and name */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ /* Up to 8 channels can be specified in the list */
+
+ DmaChannels++;
+ if (DmaChannels > 8)
+ {
+ AslError (ASL_ERROR, ASL_MSG_DMA_LIST,
+ InitializerOp, NULL);
+ return (Rnode);
+ }
+
+ /* Only DMA channels 0-7 are allowed (mask is 8 bits) */
+
+ if (InitializerOp->Asl.Value.Integer > 7)
+ {
+ AslError (ASL_ERROR, ASL_MSG_DMA_CHANNEL,
+ InitializerOp, NULL);
+ }
+
+ /* Build the mask */
+
+ DmaChannelMask |=
+ (1 << ((UINT8) InitializerOp->Asl.Value.Integer));
+ }
+
+ if (i == 4) /* case 4: First DMA byte */
+ {
+ /* Check now for duplicates in list */
+
+ RsCheckListForDuplicates (InitializerOp);
+
+ /* Create a named field at the start of the list */
+
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_DMA,
+ CurrentByteOffset +
+ ASL_RESDESC_OFFSET (Dma.DmaChannelMask));
+ }
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Now we can set the channel mask */
+
+ Descriptor->Dma.DmaChannelMask = DmaChannelMask;
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoFixedIoDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a short "FixedIO" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoFixedIoDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *AddressOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT32 i;
+
+
+ InitializerOp = Op->Asl.Child;
+ Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_IO));
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_FIXED_IO |
+ ASL_RDESC_FIXED_IO_SIZE;
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Base Address */
+
+ Descriptor->FixedIo.Address =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_BASEADDRESS,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.Address));
+ AddressOp = InitializerOp;
+ break;
+
+ case 1: /* Length */
+
+ Descriptor->FixedIo.AddressLength =
+ (UINT8) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.AddressLength));
+ break;
+
+ case 2: /* Name */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Error checks */
+
+ if (Descriptor->FixedIo.Address > 0x03FF)
+ {
+ AslError (ASL_WARNING, ASL_MSG_ISA_ADDRESS, AddressOp, NULL);
+ }
+
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoIoDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a short "IO" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoIoDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *AlignOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT32 i;
+
+
+ InitializerOp = Op->Asl.Child;
+ Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IO));
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_IO |
+ ASL_RDESC_IO_SIZE;
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Decode size */
+
+ RsSetFlagBits (&Descriptor->Io.Flags, InitializerOp, 0, 1);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Flags), 0);
+ break;
+
+ case 1: /* Min Address */
+
+ Descriptor->Io.Minimum =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 2: /* Max Address */
+
+ Descriptor->Io.Maximum =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 3: /* Alignment */
+
+ Descriptor->Io.Alignment =
+ (UINT8) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Alignment));
+ AlignOp = InitializerOp;
+ break;
+
+ case 4: /* Length */
+
+ Descriptor->Io.AddressLength =
+ (UINT8) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Io.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 5: /* Name */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Align values */
+
+ RsSmallAddressCheck (ACPI_RESOURCE_NAME_IO,
+ Descriptor->Io.Minimum,
+ Descriptor->Io.Maximum,
+ Descriptor->Io.AddressLength,
+ Descriptor->Io.Alignment,
+ MinOp, MaxOp, LengthOp, AlignOp);
+
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoIrqDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a short "IRQ" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoIrqDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT32 Interrupts = 0;
+ UINT16 IrqMask = 0;
+ UINT32 i;
+
+
+ InitializerOp = Op->Asl.Child;
+ Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ));
+
+ /* Length = 3 (with flag byte) */
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ |
+ (ASL_RDESC_IRQ_SIZE + 0x01);
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Interrupt Type (or Mode - edge/level) */
+
+ RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 0, 1);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 0);
+ break;
+
+ case 1: /* Interrupt Level (or Polarity - Active high/low) */
+
+ RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 3);
+ break;
+
+ case 2: /* Share Type - Default: exclusive (0) */
+
+ RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 4, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 4);
+ break;
+
+ case 3: /* Name */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ default:
+
+ /* All IRQ bytes are handled here, after the flags and name */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ /* Up to 16 interrupts can be specified in the list */
+
+ Interrupts++;
+ if (Interrupts > 16)
+ {
+ AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST,
+ InitializerOp, NULL);
+ return (Rnode);
+ }
+
+ /* Only interrupts 0-15 are allowed (mask is 16 bits) */
+
+ if (InitializerOp->Asl.Value.Integer > 15)
+ {
+ AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER,
+ InitializerOp, NULL);
+ }
+ else
+ {
+ IrqMask |= (1 << (UINT8) InitializerOp->Asl.Value.Integer);
+ }
+ }
+
+ /* Case 4: First IRQ value in list */
+
+ if (i == 4)
+ {
+ /* Check now for duplicates in list */
+
+ RsCheckListForDuplicates (InitializerOp);
+
+ /* Create a named field at the start of the list */
+
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_INTERRUPT,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask));
+ }
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Now we can set the channel mask */
+
+ Descriptor->Irq.IrqMask = IrqMask;
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoIrqNoFlagsDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a short "IRQNoFlags" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoIrqNoFlagsDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT16 IrqMask = 0;
+ UINT32 Interrupts = 0;
+ UINT32 i;
+
+
+ InitializerOp = Op->Asl.Child;
+ Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ_NOFLAGS));
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ |
+ ASL_RDESC_IRQ_SIZE;
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Name */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ default:
+
+ /* IRQ bytes are handled here, after the flags and name */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ /* Up to 16 interrupts can be specified in the list */
+
+ Interrupts++;
+ if (Interrupts > 16)
+ {
+ AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST,
+ InitializerOp, NULL);
+ return (Rnode);
+ }
+
+ /* Only interrupts 0-15 are allowed (mask is 16 bits) */
+
+ if (InitializerOp->Asl.Value.Integer > 15)
+ {
+ AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER,
+ InitializerOp, NULL);
+ }
+ else
+ {
+ IrqMask |= (1 << ((UINT8) InitializerOp->Asl.Value.Integer));
+ }
+ }
+
+ /* Case 1: First IRQ value in list */
+
+ if (i == 1)
+ {
+ /* Check now for duplicates in list */
+
+ RsCheckListForDuplicates (InitializerOp);
+
+ /* Create a named field at the start of the list */
+
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_INTERRUPT,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask));
+ }
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Now we can set the interrupt mask */
+
+ Descriptor->Irq.IrqMask = IrqMask;
+ return (Rnode);
+}
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2.c b/sys/contrib/dev/acpica/compiler/aslrestype2.c
index 48be853..e153701 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
- * Module Name: aslrestype2 - Long (type2) resource templates and descriptors
+ * Module Name: aslrestype2 - Miscellaneous Large resource descriptors
*
*****************************************************************************/
@@ -117,1145 +117,22 @@
#include <contrib/dev/acpica/compiler/aslcompiler.h>
#include "aslcompiler.y.h"
+#include <contrib/dev/acpica/include/amlcode.h>
#define _COMPONENT ACPI_COMPILER
ACPI_MODULE_NAME ("aslrestype2")
-/* Local prototypes */
-
-static UINT16
-RsGetStringDataLength (
- ACPI_PARSE_OBJECT *InitializerOp);
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsGetStringDataLength
- *
- * PARAMETERS: InitializerOp - Start of a subtree of init nodes
- *
- * RETURN: Valid string length if a string node is found (otherwise 0)
- *
- * DESCRIPTION: In a list of peer nodes, find the first one that contains a
- * string and return the length of the string.
- *
- ******************************************************************************/
-
-static UINT16
-RsGetStringDataLength (
- ACPI_PARSE_OBJECT *InitializerOp)
-{
-
- while (InitializerOp)
- {
- if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
- {
- return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1));
- }
- InitializerOp = ASL_GET_PEER_NODE (InitializerOp);
- }
-
- return 0;
-}
-
-
-/*******************************************************************************
+/*
+ * This module contains miscellaneous large resource descriptors:
*
- * FUNCTION: RsDoDwordIoDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "DwordIO" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoDwordIoDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT16 StringLength = 0;
- UINT32 OptionIndex = 0;
- UINT8 *OptionalFields;
- UINT32 i;
- BOOLEAN ResSourceIndex = FALSE;
-
-
- InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength);
-
- Descriptor = Rnode->Buffer;
- Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32;
- Descriptor->Address32.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE;
-
- /*
- * Initial descriptor length -- may be enlarged if there are
- * optional fields present
- */
- OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32);
- Descriptor->Address32.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_ADDRESS32) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1);
- break;
-
- case 1: /* MinType */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2);
- break;
-
- case 2: /* MaxType */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3);
- break;
-
- case 3: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1);
- break;
-
- case 4: /* Range Type */
-
- RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 0, 3);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 0);
- break;
-
- case 5: /* Address Granularity */
-
- Descriptor->Address32.Granularity =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity));
- break;
-
- case 6: /* Address Min */
-
- Descriptor->Address32.Minimum =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum));
- break;
-
- case 7: /* Address Max */
-
- Descriptor->Address32.Maximum =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum));
- break;
-
- case 8: /* Translation Offset */
-
- Descriptor->Address32.TranslationOffset =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset));
- break;
-
- case 9: /* Address Length */
-
- Descriptor->Address32.AddressLength =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength));
- break;
-
- case 10: /* ResSourceIndex [Optional Field - BYTE] */
-
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- /* Found a valid ResourceSourceIndex */
-
- OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
- OptionIndex++;
- Descriptor->Address32.ResourceLength++;
- ResSourceIndex = TRUE;
- }
- break;
-
- case 11: /* ResSource [Optional Field - STRING] */
-
- if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
- (InitializerOp->Asl.Value.String))
- {
- if (StringLength)
- {
- /* Found a valid ResourceSource */
-
- Descriptor->Address32.ResourceLength = (UINT16)
- (Descriptor->Address32.ResourceLength + StringLength);
-
- strcpy ((char *)
- &OptionalFields[OptionIndex],
- InitializerOp->Asl.Value.String);
-
- /* ResourceSourceIndex must also be valid */
-
- if (!ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
- InitializerOp, NULL);
- }
- }
- }
-
-#if 0
- /*
- * Not a valid ResourceSource, ResourceSourceIndex must also
- * be invalid
- */
- else if (ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
- InitializerOp, NULL);
- }
-#endif
- break;
-
- case 12: /* ResourceTag */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- case 13: /* Type */
-
- RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 4, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 4);
- break;
-
- case 14: /* Translation Type */
-
- RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 5, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 5);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) +
- OptionIndex + StringLength;
- return (Rnode);
-}
-
+ * Register
+ * Interrupt
+ * VendorLong
+ */
/*******************************************************************************
*
- * FUNCTION: RsDoDwordMemoryDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "DwordMemory" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoDwordMemoryDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT8 *OptionalFields;
- UINT16 StringLength = 0;
- UINT32 OptionIndex = 0;
- UINT32 i;
- BOOLEAN ResSourceIndex = FALSE;
-
-
- InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength);
-
- Descriptor = Rnode->Buffer;
- Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32;
- Descriptor->Address32.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE;
-
- /*
- * Initial descriptor length -- may be enlarged if there are
- * optional fields present
- */
- OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32);
- Descriptor->Address32.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_ADDRESS32) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
-
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1);
- break;
-
- case 1: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1);
- break;
-
- case 2: /* MinType */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2);
- break;
-
- case 3: /* MaxType */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3);
- break;
-
- case 4: /* Memory Type */
-
- RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 1);
- break;
-
- case 5: /* Read/Write Type */
-
- RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 0, 1);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 0);
- break;
-
- case 6: /* Address Granularity */
-
- Descriptor->Address32.Granularity =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity));
- break;
-
- case 7: /* Min Address */
-
- Descriptor->Address32.Minimum =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum));
- break;
-
- case 8: /* Max Address */
-
- Descriptor->Address32.Maximum =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum));
- break;
-
- case 9: /* Translation Offset */
-
- Descriptor->Address32.TranslationOffset =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset));
- break;
-
- case 10: /* Address Length */
-
- Descriptor->Address32.AddressLength =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength));
- break;
-
- case 11: /* ResSourceIndex [Optional Field - BYTE] */
-
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
- OptionIndex++;
- Descriptor->Address32.ResourceLength++;
- ResSourceIndex = TRUE;
- }
- break;
-
- case 12: /* ResSource [Optional Field - STRING] */
-
- if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
- (InitializerOp->Asl.Value.String))
- {
- if (StringLength)
- {
- Descriptor->Address32.ResourceLength = (UINT16)
- (Descriptor->Address32.ResourceLength + StringLength);
-
- strcpy ((char *)
- &OptionalFields[OptionIndex],
- InitializerOp->Asl.Value.String);
-
- /* ResourceSourceIndex must also be valid */
-
- if (!ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
- InitializerOp, NULL);
- }
- }
- }
-
-#if 0
- /*
- * Not a valid ResourceSource, ResourceSourceIndex must also
- * be invalid
- */
- else if (ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
- InitializerOp, NULL);
- }
-#endif
- break;
-
- case 13: /* ResourceTag */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
-
- case 14: /* Address Range */
-
- RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 3);
- break;
-
- case 15: /* Type */
-
- RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 5, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 5);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) +
- OptionIndex + StringLength;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoDwordSpaceDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "DwordSpace" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoDwordSpaceDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT8 *OptionalFields;
- UINT16 StringLength = 0;
- UINT32 OptionIndex = 0;
- UINT32 i;
- BOOLEAN ResSourceIndex = FALSE;
-
-
- InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength);
-
- Descriptor = Rnode->Buffer;
- Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32;
-
- /*
- * Initial descriptor length -- may be enlarged if there are
- * optional fields present
- */
- OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32);
- Descriptor->Address32.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_ADDRESS32) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Resource Type */
-
- Descriptor->Address32.ResourceType =
- (UINT8) InitializerOp->Asl.Value.Integer;
- break;
-
- case 1: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1);
- break;
-
- case 2: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1);
- break;
-
- case 3: /* MinType */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2);
- break;
-
- case 4: /* MaxType */
-
- RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3);
- break;
-
- case 5: /* Type-Specific flags */
-
- Descriptor->Address32.SpecificFlags =
- (UINT8) InitializerOp->Asl.Value.Integer;
- break;
-
- case 6: /* Address Granularity */
-
- Descriptor->Address32.Granularity =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity));
- break;
-
- case 7: /* Min Address */
-
- Descriptor->Address32.Minimum =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum));
- break;
-
- case 8: /* Max Address */
-
- Descriptor->Address32.Maximum =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum));
- break;
-
- case 9: /* Translation Offset */
-
- Descriptor->Address32.TranslationOffset =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset));
- break;
-
- case 10: /* Address Length */
-
- Descriptor->Address32.AddressLength =
- (UINT32) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength));
- break;
-
- case 11: /* ResSourceIndex [Optional Field - BYTE] */
-
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
- OptionIndex++;
- Descriptor->Address32.ResourceLength++;
- ResSourceIndex = TRUE;
- }
- break;
-
- case 12: /* ResSource [Optional Field - STRING] */
-
- if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
- (InitializerOp->Asl.Value.String))
- {
- if (StringLength)
- {
- Descriptor->Address32.ResourceLength = (UINT16)
- (Descriptor->Address32.ResourceLength + StringLength);
-
- strcpy ((char *)
- &OptionalFields[OptionIndex],
- InitializerOp->Asl.Value.String);
-
- /* ResourceSourceIndex must also be valid */
-
- if (!ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
- InitializerOp, NULL);
- }
- }
- }
-
-#if 0
- /*
- * Not a valid ResourceSource, ResourceSourceIndex must also
- * be invalid
- */
- else if (ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
- InitializerOp, NULL);
- }
-#endif
- break;
-
- case 13: /* ResourceTag */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST,
- InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) +
- OptionIndex + StringLength;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoExtendedIoDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "ExtendedIO" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoExtendedIoDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT16 StringLength = 0;
- UINT32 i;
-
-
- InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength);
-
- Descriptor = Rnode->Buffer;
- Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64;
- Descriptor->ExtAddress64.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE;
- Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION;
-
- Descriptor->ExtAddress64.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1);
- break;
-
- case 1: /* MinType */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2);
- break;
-
- case 2: /* MaxType */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3);
- break;
-
- case 3: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1);
- break;
-
- case 4: /* Range Type */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 0, 3);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 0);
- break;
-
- case 5: /* Address Granularity */
-
- Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity));
- break;
-
- case 6: /* Address Min */
-
- Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum));
- break;
-
- case 7: /* Address Max */
-
- Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum));
- break;
-
- case 8: /* Translation Offset */
-
- Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset));
- break;
-
- case 9: /* Address Length */
-
- Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength));
- break;
-
- case 10: /* Type-Specific Attributes */
-
- Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific));
- break;
-
- case 11: /* ResourceTag */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- case 12: /* Type */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 4, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 4);
- break;
-
- case 13: /* Translation Type */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 5, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 5);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoExtendedMemoryDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "ExtendedMemory" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoExtendedMemoryDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT16 StringLength = 0;
- UINT32 i;
-
-
- InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength);
-
- Descriptor = Rnode->Buffer;
- Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64;
- Descriptor->ExtAddress64.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE;
- Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION;
-
- Descriptor->ExtAddress64.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1);
- break;
-
- case 1: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1);
- break;
-
- case 2: /* MinType */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2);
- break;
-
- case 3: /* MaxType */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3);
- break;
-
- case 4: /* Memory Type */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 1);
- break;
-
- case 5: /* Read/Write Type */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 0, 1);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 0);
- break;
-
- case 6: /* Address Granularity */
-
- Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity));
- break;
-
- case 7: /* Min Address */
-
- Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum));
- break;
-
- case 8: /* Max Address */
-
- Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum));
- break;
-
- case 9: /* Translation Offset */
-
- Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset));
- break;
-
- case 10: /* Address Length */
-
- Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength));
- break;
-
- case 11: /* Type-Specific Attributes */
-
- Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific));
- break;
-
- case 12: /* ResourceTag */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
-
- case 13: /* Address Range */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 3);
- break;
-
- case 14: /* Type */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 5, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 5);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoExtendedSpaceDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "ExtendedSpace" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoExtendedSpaceDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT16 StringLength = 0;
- UINT32 i;
-
-
- InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength);
-
- Descriptor = Rnode->Buffer;
- Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64;
- Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION;
-
- Descriptor->ExtAddress64.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Resource Type */
-
- Descriptor->ExtAddress64.ResourceType =
- (UINT8) InitializerOp->Asl.Value.Integer;
- break;
-
- case 1: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1);
- break;
-
- case 2: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1);
- break;
-
- case 3: /* MinType */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2);
- break;
-
- case 4: /* MaxType */
-
- RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3);
- break;
-
- case 5: /* Type-Specific flags */
-
- Descriptor->ExtAddress64.SpecificFlags =
- (UINT8) InitializerOp->Asl.Value.Integer;
- break;
-
- case 6: /* Address Granularity */
-
- Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity));
- break;
-
- case 7: /* Min Address */
-
- Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum));
- break;
-
- case 8: /* Max Address */
-
- Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum));
- break;
-
- case 9: /* Translation Offset */
-
- Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset));
- break;
-
- case 10: /* Address Length */
-
- Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength));
- break;
-
- case 11: /* Type-Specific Attributes */
-
- Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES,
- CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific));
- break;
-
- case 12: /* ResourceTag */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoQwordIoDescriptor
+ * FUNCTION: RsDoGeneralRegisterDescriptor
*
* PARAMETERS: Op - Parent resource descriptor parse node
* CurrentByteOffset - Offset into the resource template AML
@@ -1263,43 +140,27 @@ RsDoExtendedSpaceDescriptor (
*
* RETURN: Completed resource node
*
- * DESCRIPTION: Construct a long "QwordIO" descriptor
+ * DESCRIPTION: Construct a long "Register" descriptor
*
******************************************************************************/
ASL_RESOURCE_NODE *
-RsDoQwordIoDescriptor (
+RsDoGeneralRegisterDescriptor (
ACPI_PARSE_OBJECT *Op,
UINT32 CurrentByteOffset)
{
AML_RESOURCE *Descriptor;
ACPI_PARSE_OBJECT *InitializerOp;
ASL_RESOURCE_NODE *Rnode;
- UINT8 *OptionalFields;
- UINT16 StringLength = 0;
- UINT32 OptionIndex = 0;
UINT32 i;
- BOOLEAN ResSourceIndex = FALSE;
InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength);
+ Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_GENERIC_REGISTER));
Descriptor = Rnode->Buffer;
- Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64;
- Descriptor->Address64.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE;
-
- /*
- * Initial descriptor length -- may be enlarged if there are
- * optional fields present
- */
- OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64);
- Descriptor->Address64.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_ADDRESS64) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
+ Descriptor->GenericReg.DescriptorType = ACPI_RESOURCE_NAME_GENERIC_REGISTER;
+ Descriptor->GenericReg.ResourceLength = 12;
/* Process all child initialization nodes */
@@ -1307,1134 +168,48 @@ RsDoQwordIoDescriptor (
{
switch (i)
{
- case 0: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1);
- break;
-
- case 1: /* MinType */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2);
- break;
-
- case 2: /* MaxType */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3);
- break;
-
- case 3: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1);
- break;
-
- case 4: /* Range Type */
-
- RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 0, 3);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 0);
- break;
-
- case 5: /* Address Granularity */
+ case 0: /* Address space */
- Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity));
+ Descriptor->GenericReg.AddressSpaceId = (UINT8) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESSSPACE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AddressSpaceId));
break;
- case 6: /* Address Min */
-
- Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum));
- break;
-
- case 7: /* Address Max */
-
- Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum));
- break;
-
- case 8: /* Translation Offset */
-
- Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset));
- break;
-
- case 9: /* Address Length */
-
- Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength));
- break;
-
- case 10: /* ResSourceIndex [Optional Field - BYTE] */
-
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
- OptionIndex++;
- Descriptor->Address64.ResourceLength++;
- ResSourceIndex = TRUE;
- }
- break;
-
- case 11: /* ResSource [Optional Field - STRING] */
-
- if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
- (InitializerOp->Asl.Value.String))
- {
- if (StringLength)
- {
- Descriptor->Address64.ResourceLength = (UINT16)
- (Descriptor->Address64.ResourceLength + StringLength);
-
- strcpy ((char *)
- &OptionalFields[OptionIndex],
- InitializerOp->Asl.Value.String);
-
- /* ResourceSourceIndex must also be valid */
-
- if (!ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
- InitializerOp, NULL);
- }
- }
- }
-
-#if 0
- /*
- * Not a valid ResourceSource, ResourceSourceIndex must also
- * be invalid
- */
- else if (ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
- InitializerOp, NULL);
- }
-#endif
- break;
-
- case 12: /* ResourceTag */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- case 13: /* Type */
-
- RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 4, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 4);
- break;
-
- case 14: /* Translation Type */
-
- RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 5, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 5);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) +
- OptionIndex + StringLength;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoQwordMemoryDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "QwordMemory" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoQwordMemoryDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT8 *OptionalFields;
- UINT16 StringLength = 0;
- UINT32 OptionIndex = 0;
- UINT32 i;
- BOOLEAN ResSourceIndex = FALSE;
-
-
- InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength);
-
- Descriptor = Rnode->Buffer;
- Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64;
- Descriptor->Address64.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE;
-
- /*
- * Initial descriptor length -- may be enlarged if there are
- * optional fields present
- */
- OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64);
- Descriptor->Address64.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_ADDRESS64) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1);
- break;
-
- case 1: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1);
- break;
-
- case 2: /* MinType */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2);
- break;
-
- case 3: /* MaxType */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3);
- break;
-
- case 4: /* Memory Type */
-
- RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 1);
- break;
-
- case 5: /* Read/Write Type */
-
- RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 0, 1);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 0);
- break;
-
- case 6: /* Address Granularity */
-
- Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity));
- break;
-
- case 7: /* Min Address */
-
- Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum));
- break;
-
- case 8: /* Max Address */
-
- Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum));
- break;
-
- case 9: /* Translation Offset */
-
- Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset));
- break;
-
- case 10: /* Address Length */
-
- Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength));
- break;
-
- case 11: /* ResSourceIndex [Optional Field - BYTE] */
-
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
- OptionIndex++;
- Descriptor->Address64.ResourceLength++;
- ResSourceIndex = TRUE;
- }
- break;
-
- case 12: /* ResSource [Optional Field - STRING] */
-
- if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
- (InitializerOp->Asl.Value.String))
- {
- if (StringLength)
- {
- Descriptor->Address64.ResourceLength = (UINT16)
- (Descriptor->Address64.ResourceLength + StringLength);
-
- strcpy ((char *)
- &OptionalFields[OptionIndex],
- InitializerOp->Asl.Value.String);
-
- /* ResourceSourceIndex must also be valid */
-
- if (!ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
- InitializerOp, NULL);
- }
- }
- }
-
-#if 0
- /*
- * Not a valid ResourceSource, ResourceSourceIndex must also
- * be invalid
- */
- else if (ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
- InitializerOp, NULL);
- }
-#endif
- break;
-
- case 13: /* ResourceTag */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
-
- case 14: /* Address Range */
-
- RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 3);
- break;
-
- case 15: /* Type */
-
- RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 5, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 5);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) +
- OptionIndex + StringLength;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoQwordSpaceDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "QwordSpace" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoQwordSpaceDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT8 *OptionalFields;
- UINT16 StringLength = 0;
- UINT32 OptionIndex = 0;
- UINT32 i;
- BOOLEAN ResSourceIndex = FALSE;
-
-
- InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength);
-
- Descriptor = Rnode->Buffer;
- Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64;
-
- /*
- * Initial descriptor length -- may be enlarged if there are
- * optional fields present
- */
- OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64);
- Descriptor->Address64.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_ADDRESS64) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Resource Type */
-
- Descriptor->Address64.ResourceType =
- (UINT8) InitializerOp->Asl.Value.Integer;
- break;
-
- case 1: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1);
- break;
-
- case 2: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1);
- break;
-
- case 3: /* MinType */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2);
- break;
-
- case 4: /* MaxType */
-
- RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3);
- break;
-
- case 5: /* Type-Specific flags */
-
- Descriptor->Address64.SpecificFlags =
- (UINT8) InitializerOp->Asl.Value.Integer;
- break;
-
- case 6: /* Address Granularity */
-
- Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity));
- break;
-
- case 7: /* Min Address */
-
- Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum));
- break;
-
- case 8: /* Max Address */
-
- Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum));
- break;
-
- case 9: /* Translation Offset */
-
- Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset));
- break;
-
- case 10: /* Address Length */
-
- Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength));
- break;
-
- case 11: /* ResSourceIndex [Optional Field - BYTE] */
-
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
- OptionIndex++;
- Descriptor->Address64.ResourceLength++;
- ResSourceIndex = TRUE;
- }
- break;
-
- case 12: /* ResSource [Optional Field - STRING] */
-
- if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
- (InitializerOp->Asl.Value.String))
- {
- if (StringLength)
- {
- Descriptor->Address64.ResourceLength = (UINT16)
- (Descriptor->Address64.ResourceLength + StringLength);
-
- strcpy ((char *)
- &OptionalFields[OptionIndex],
- InitializerOp->Asl.Value.String);
-
- /* ResourceSourceIndex must also be valid */
-
- if (!ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
- InitializerOp, NULL);
- }
- }
- }
-
-#if 0
- /*
- * Not a valid ResourceSource, ResourceSourceIndex must also
- * be invalid
- */
- else if (ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
- InitializerOp, NULL);
- }
-#endif
- break;
-
- case 13: /* ResourceTag */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) +
- OptionIndex + StringLength;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoWordIoDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "WordIO" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoWordIoDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT8 *OptionalFields;
- UINT16 StringLength = 0;
- UINT32 OptionIndex = 0;
- UINT32 i;
- BOOLEAN ResSourceIndex = FALSE;
-
-
- InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength);
-
- Descriptor = Rnode->Buffer;
- Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16;
- Descriptor->Address16.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE;
-
- /*
- * Initial descriptor length -- may be enlarged if there are
- * optional fields present
- */
- OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16);
- Descriptor->Address16.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_ADDRESS16) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1);
- break;
-
- case 1: /* MinType */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2);
- break;
-
- case 2: /* MaxType */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3);
- break;
-
- case 3: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1);
- break;
-
- case 4: /* Range Type */
-
- RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 0, 3);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 0);
- break;
-
- case 5: /* Address Granularity */
-
- Descriptor->Address16.Granularity = (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity));
- break;
-
- case 6: /* Address Min */
-
- Descriptor->Address16.Minimum = (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum));
- break;
-
- case 7: /* Address Max */
-
- Descriptor->Address16.Maximum = (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum));
- break;
-
- case 8: /* Translation Offset */
-
- Descriptor->Address16.TranslationOffset = (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset));
- break;
-
- case 9: /* Address Length */
-
- Descriptor->Address16.AddressLength = (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength));
- break;
-
- case 10: /* ResSourceIndex [Optional Field - BYTE] */
-
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
- OptionIndex++;
- Descriptor->Address16.ResourceLength++;
- ResSourceIndex = TRUE;
- }
- break;
-
- case 11: /* ResSource [Optional Field - STRING] */
-
- if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
- (InitializerOp->Asl.Value.String))
- {
- if (StringLength)
- {
- Descriptor->Address16.ResourceLength = (UINT16)
- (Descriptor->Address16.ResourceLength + StringLength);
-
- strcpy ((char *)
- &OptionalFields[OptionIndex],
- InitializerOp->Asl.Value.String);
-
- /* ResourceSourceIndex must also be valid */
-
- if (!ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
- InitializerOp, NULL);
- }
- }
- }
-
-#if 0
- /*
- * Not a valid ResourceSource, ResourceSourceIndex must also
- * be invalid
- */
- else if (ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
- InitializerOp, NULL);
- }
-#endif
- break;
-
- case 12: /* ResourceTag */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- case 13: /* Type */
-
- RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 4, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 4);
- break;
-
- case 14: /* Translation Type */
-
- RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 5, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 5);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) +
- OptionIndex + StringLength;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoWordBusNumberDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "WordBusNumber" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoWordBusNumberDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT8 *OptionalFields;
- UINT16 StringLength = 0;
- UINT32 OptionIndex = 0;
- UINT32 i;
- BOOLEAN ResSourceIndex = FALSE;
-
-
- InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength);
-
- Descriptor = Rnode->Buffer;
- Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16;
- Descriptor->Address16.ResourceType = ACPI_ADDRESS_TYPE_BUS_NUMBER_RANGE;
-
- /*
- * Initial descriptor length -- may be enlarged if there are
- * optional fields present
- */
- OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16);
- Descriptor->Address16.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_ADDRESS16) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1);
- break;
-
- case 1: /* MinType */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2);
- break;
-
- case 2: /* MaxType */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3);
- break;
-
- case 3: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1);
- break;
-
- case 4: /* Address Granularity */
-
- Descriptor->Address16.Granularity =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity));
- break;
-
- case 5: /* Min Address */
-
- Descriptor->Address16.Minimum =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum));
- break;
-
- case 6: /* Max Address */
-
- Descriptor->Address16.Maximum =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum));
- break;
-
- case 7: /* Translation Offset */
-
- Descriptor->Address16.TranslationOffset =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset));
- break;
-
- case 8: /* Address Length */
-
- Descriptor->Address16.AddressLength =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength));
- break;
-
- case 9: /* ResSourceIndex [Optional Field - BYTE] */
-
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
- OptionIndex++;
- Descriptor->Address16.ResourceLength++;
- ResSourceIndex = TRUE;
- }
- break;
-
- case 10: /* ResSource [Optional Field - STRING] */
-
- if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
- (InitializerOp->Asl.Value.String))
- {
- if (StringLength)
- {
- Descriptor->Address16.ResourceLength = (UINT16)
- (Descriptor->Address16.ResourceLength + StringLength);
-
- strcpy ((char *)
- &OptionalFields[OptionIndex],
- InitializerOp->Asl.Value.String);
-
- /* ResourceSourceIndex must also be valid */
-
- if (!ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
- InitializerOp, NULL);
- }
- }
- }
-
-#if 0
- /*
- * Not a valid ResourceSource, ResourceSourceIndex must also
- * be invalid
- */
- else if (ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
- InitializerOp, NULL);
- }
-#endif
- break;
-
- case 11: /* ResourceTag */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) +
- OptionIndex + StringLength;
- return (Rnode);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoWordSpaceDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "WordSpace" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoWordSpaceDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT8 *OptionalFields;
- UINT16 StringLength = 0;
- UINT32 OptionIndex = 0;
- UINT32 i;
- BOOLEAN ResSourceIndex = FALSE;
-
-
- InitializerOp = Op->Asl.Child;
- StringLength = RsGetStringDataLength (InitializerOp);
-
- Rnode = RsAllocateResourceNode (
- sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength);
-
- Descriptor = Rnode->Buffer;
- Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16;
-
- /*
- * Initial descriptor length -- may be enlarged if there are
- * optional fields present
- */
- OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16);
- Descriptor->Address16.ResourceLength = (UINT16)
- (sizeof (AML_RESOURCE_ADDRESS16) -
- sizeof (AML_RESOURCE_LARGE_HEADER));
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Resource Type */
-
- Descriptor->Address16.ResourceType =
- (UINT8) InitializerOp->Asl.Value.Integer;
- break;
-
- case 1: /* Resource Usage */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1);
- break;
-
- case 2: /* DecodeType */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1);
- break;
-
- case 3: /* MinType */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2);
- break;
-
- case 4: /* MaxType */
-
- RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0);
- RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3);
- break;
-
- case 5: /* Type-Specific flags */
-
- Descriptor->Address16.SpecificFlags =
- (UINT8) InitializerOp->Asl.Value.Integer;
- break;
-
- case 6: /* Address Granularity */
-
- Descriptor->Address16.Granularity =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity));
- break;
-
- case 7: /* Min Address */
-
- Descriptor->Address16.Minimum =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum));
- break;
-
- case 8: /* Max Address */
-
- Descriptor->Address16.Maximum =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum));
- break;
-
- case 9: /* Translation Offset */
+ case 1: /* Register Bit Width */
- Descriptor->Address16.TranslationOffset =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset));
+ Descriptor->GenericReg.BitWidth = (UINT8) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITWIDTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitWidth));
break;
- case 10: /* Address Length */
+ case 2: /* Register Bit Offset */
- Descriptor->Address16.AddressLength =
- (UINT16) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength));
+ Descriptor->GenericReg.BitOffset = (UINT8) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITOFFSET,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitOffset));
break;
- case 11: /* ResSourceIndex [Optional Field - BYTE] */
+ case 3: /* Register Address */
- if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
- {
- OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
- OptionIndex++;
- Descriptor->Address16.ResourceLength++;
- ResSourceIndex = TRUE;
- }
+ Descriptor->GenericReg.Address = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESS,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.Address));
break;
- case 12: /* ResSource [Optional Field - STRING] */
-
- if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
- (InitializerOp->Asl.Value.String))
- {
- if (StringLength)
- {
- Descriptor->Address16.ResourceLength = (UINT16)
- (Descriptor->Address16.ResourceLength + StringLength);
-
- strcpy ((char *)
- &OptionalFields[OptionIndex],
- InitializerOp->Asl.Value.String);
-
- /* ResourceSourceIndex must also be valid */
+ case 4: /* Access Size (ACPI 3.0) */
- if (!ResSourceIndex)
- {
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
- InitializerOp, NULL);
- }
- }
- }
+ Descriptor->GenericReg.AccessSize = (UINT8) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_ACCESSSIZE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AccessSize));
-#if 0
- /*
- * Not a valid ResourceSource, ResourceSourceIndex must also
- * be invalid
- */
- else if (ResSourceIndex)
+ if (Descriptor->GenericReg.AccessSize > AML_FIELD_ACCESS_QWORD)
{
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
+ AslError (ASL_ERROR, ASL_MSG_INVALID_ACCESS_SIZE,
InitializerOp, NULL);
}
-#endif
break;
- case 13: /* ResourceTag */
+ case 5: /* ResourceTag (ACPI 3.0b) */
UtAttachNamepathToOwner (Op, InitializerOp);
break;
@@ -2447,9 +222,6 @@ RsDoWordSpaceDescriptor (
InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
}
-
- Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) +
- OptionIndex + StringLength;
return (Rnode);
}
@@ -2760,95 +532,3 @@ RsDoVendorLargeDescriptor (
return (Rnode);
}
-
-
-/*******************************************************************************
- *
- * FUNCTION: RsDoGeneralRegisterDescriptor
- *
- * PARAMETERS: Op - Parent resource descriptor parse node
- * CurrentByteOffset - Offset into the resource template AML
- * buffer (to track references to the desc)
- *
- * RETURN: Completed resource node
- *
- * DESCRIPTION: Construct a long "Register" descriptor
- *
- ******************************************************************************/
-
-ASL_RESOURCE_NODE *
-RsDoGeneralRegisterDescriptor (
- ACPI_PARSE_OBJECT *Op,
- UINT32 CurrentByteOffset)
-{
- AML_RESOURCE *Descriptor;
- ACPI_PARSE_OBJECT *InitializerOp;
- ASL_RESOURCE_NODE *Rnode;
- UINT32 i;
-
-
- InitializerOp = Op->Asl.Child;
- Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_GENERIC_REGISTER));
-
- Descriptor = Rnode->Buffer;
- Descriptor->GenericReg.DescriptorType = ACPI_RESOURCE_NAME_GENERIC_REGISTER;
- Descriptor->GenericReg.ResourceLength = 12;
-
- /* Process all child initialization nodes */
-
- for (i = 0; InitializerOp; i++)
- {
- switch (i)
- {
- case 0: /* Address space */
-
- Descriptor->GenericReg.AddressSpaceId = (UINT8) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESSSPACE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AddressSpaceId));
- break;
-
- case 1: /* Register Bit Width */
-
- Descriptor->GenericReg.BitWidth = (UINT8) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITWIDTH,
- CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitWidth));
- break;
-
- case 2: /* Register Bit Offset */
-
- Descriptor->GenericReg.BitOffset = (UINT8) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITOFFSET,
- CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitOffset));
- break;
-
- case 3: /* Register Address */
-
- Descriptor->GenericReg.Address = InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESS,
- CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.Address));
- break;
-
- case 4: /* Access Size (ACPI 3.0) */
-
- Descriptor->GenericReg.AccessSize = (UINT8) InitializerOp->Asl.Value.Integer;
- RsCreateByteField (InitializerOp, ACPI_RESTAG_ACCESSSIZE,
- CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AccessSize));
- break;
-
- case 5: /* ResourceTag (ACPI 3.0b) */
-
- UtAttachNamepathToOwner (Op, InitializerOp);
- break;
-
- default:
-
- AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
- break;
- }
-
- InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
- }
- return (Rnode);
-}
-
-
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2d.c b/sys/contrib/dev/acpica/compiler/aslrestype2d.c
new file mode 100644
index 0000000..db0a2a7
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2d.c
@@ -0,0 +1,814 @@
+
+/******************************************************************************
+ *
+ * Module Name: aslrestype2d - Large DWord address resource descriptors
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * 1. Copyright Notice
+ *
+ * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * 2. License
+ *
+ * 2.1. This is your license from Intel Corp. under its intellectual property
+ * rights. You may have additional license terms from the party that provided
+ * you this software, covering your right to use that party's intellectual
+ * property rights.
+ *
+ * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
+ * copy of the source code appearing in this file ("Covered Code") an
+ * irrevocable, perpetual, worldwide license under Intel's copyrights in the
+ * base code distributed originally by Intel ("Original Intel Code") to copy,
+ * make derivatives, distribute, use and display any portion of the Covered
+ * Code in any form, with the right to sublicense such rights; and
+ *
+ * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
+ * license (with the right to sublicense), under only those claims of Intel
+ * patents that are infringed by the Original Intel Code, to make, use, sell,
+ * offer to sell, and import the Covered Code and derivative works thereof
+ * solely to the minimum extent necessary to exercise the above copyright
+ * license, and in no event shall the patent license extend to any additions
+ * to or modifications of the Original Intel Code. No other license or right
+ * is granted directly or by implication, estoppel or otherwise;
+ *
+ * The above copyright and patent license is granted only if the following
+ * conditions are met:
+ *
+ * 3. Conditions
+ *
+ * 3.1. Redistribution of Source with Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification with rights to further distribute source must include
+ * the above Copyright Notice, the above License, this list of Conditions,
+ * and the following Disclaimer and Export Compliance provision. In addition,
+ * Licensee must cause all Covered Code to which Licensee contributes to
+ * contain a file documenting the changes Licensee made to create that Covered
+ * Code and the date of any change. Licensee must include in that file the
+ * documentation of any changes made by any predecessor Licensee. Licensee
+ * must include a prominent statement that the modification is derived,
+ * directly or indirectly, from Original Intel Code.
+ *
+ * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification without rights to further distribute source must
+ * include the following Disclaimer and Export Compliance provision in the
+ * documentation and/or other materials provided with distribution. In
+ * addition, Licensee may not authorize further sublicense of source of any
+ * portion of the Covered Code, and must include terms to the effect that the
+ * license from Licensee to its licensee is limited to the intellectual
+ * property embodied in the software Licensee provides to its licensee, and
+ * not to intellectual property embodied in modifications its licensee may
+ * make.
+ *
+ * 3.3. Redistribution of Executable. Redistribution in executable form of any
+ * substantial portion of the Covered Code or modification must reproduce the
+ * above Copyright Notice, and the following Disclaimer and Export Compliance
+ * provision in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3.4. Intel retains all right, title, and interest in and to the Original
+ * Intel Code.
+ *
+ * 3.5. Neither the name Intel nor any other trademark owned or controlled by
+ * Intel shall be used in advertising or otherwise to promote the sale, use or
+ * other dealings in products derived from or relating to the Covered Code
+ * without prior written authorization from Intel.
+ *
+ * 4. Disclaimer and Export Compliance
+ *
+ * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
+ * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
+ * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
+ * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
+ * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
+ * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
+ * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
+ * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
+ * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
+ * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
+ * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
+ * LIMITED REMEDY.
+ *
+ * 4.3. Licensee shall not export, either directly or indirectly, any of this
+ * software or system incorporating such software without first obtaining any
+ * required license or other approval from the U. S. Department of Commerce or
+ * any other agency or department of the United States Government. In the
+ * event Licensee exports any such software from the United States or
+ * re-exports any such software from a foreign destination, Licensee shall
+ * ensure that the distribution and export/re-export of the software is in
+ * compliance with all laws, regulations, orders, or other restrictions of the
+ * U.S. Export Administration Regulations. Licensee agrees that neither it nor
+ * any of its subsidiaries will export/re-export any technical data, process,
+ * software, or service, directly or indirectly, to any country for which the
+ * United States government or any agency thereof requires an export license,
+ * other governmental approval, or letter of assurance, without first obtaining
+ * such license, approval or letter.
+ *
+ *****************************************************************************/
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslrestype2d")
+
+/*
+ * This module contains the Dword (32-bit) address space descriptors:
+ *
+ * DwordIO
+ * DwordMemory
+ * DwordSpace
+ */
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoDwordIoDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "DwordIO" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoDwordIoDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT16 StringLength = 0;
+ UINT32 OptionIndex = 0;
+ UINT8 *OptionalFields;
+ UINT32 i;
+ BOOLEAN ResSourceIndex = FALSE;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32;
+ Descriptor->Address32.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE;
+
+ /*
+ * Initial descriptor length -- may be enlarged if there are
+ * optional fields present
+ */
+ OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32);
+ Descriptor->Address32.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_ADDRESS32) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 1: /* MinType */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2);
+ break;
+
+ case 2: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3);
+ break;
+
+ case 3: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1);
+ break;
+
+ case 4: /* Range Type */
+
+ RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 0, 3);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 0);
+ break;
+
+ case 5: /* Address Granularity */
+
+ Descriptor->Address32.Granularity =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 6: /* Address Min */
+
+ Descriptor->Address32.Minimum =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 7: /* Address Max */
+
+ Descriptor->Address32.Maximum =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 8: /* Translation Offset */
+
+ Descriptor->Address32.TranslationOffset =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset));
+ break;
+
+ case 9: /* Address Length */
+
+ Descriptor->Address32.AddressLength =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 10: /* ResSourceIndex [Optional Field - BYTE] */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ /* Found a valid ResourceSourceIndex */
+
+ OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
+ OptionIndex++;
+ Descriptor->Address32.ResourceLength++;
+ ResSourceIndex = TRUE;
+ }
+ break;
+
+ case 11: /* ResSource [Optional Field - STRING] */
+
+ if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
+ (InitializerOp->Asl.Value.String))
+ {
+ if (StringLength)
+ {
+ /* Found a valid ResourceSource */
+
+ Descriptor->Address32.ResourceLength = (UINT16)
+ (Descriptor->Address32.ResourceLength + StringLength);
+
+ strcpy ((char *)
+ &OptionalFields[OptionIndex],
+ InitializerOp->Asl.Value.String);
+
+ /* ResourceSourceIndex must also be valid */
+
+ if (!ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
+ InitializerOp, NULL);
+ }
+ }
+ }
+
+#if 0
+ /*
+ * Not a valid ResourceSource, ResourceSourceIndex must also
+ * be invalid
+ */
+ else if (ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
+ InitializerOp, NULL);
+ }
+#endif
+ break;
+
+ case 12: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ case 13: /* Type */
+
+ RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 4, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 4);
+ break;
+
+ case 14: /* Translation Type */
+
+ RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 5, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 5);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->Address32.Minimum,
+ Descriptor->Address32.Maximum,
+ Descriptor->Address32.AddressLength,
+ Descriptor->Address32.Granularity,
+ Descriptor->Address32.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) +
+ OptionIndex + StringLength;
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoDwordMemoryDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "DwordMemory" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoDwordMemoryDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT8 *OptionalFields;
+ UINT16 StringLength = 0;
+ UINT32 OptionIndex = 0;
+ UINT32 i;
+ BOOLEAN ResSourceIndex = FALSE;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32;
+ Descriptor->Address32.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE;
+
+ /*
+ * Initial descriptor length -- may be enlarged if there are
+ * optional fields present
+ */
+ OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32);
+ Descriptor->Address32.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_ADDRESS32) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 1: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1);
+ break;
+
+ case 2: /* MinType */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2);
+ break;
+
+ case 3: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3);
+ break;
+
+ case 4: /* Memory Type */
+
+ RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 1);
+ break;
+
+ case 5: /* Read/Write Type */
+
+ RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 0, 1);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 0);
+ break;
+
+ case 6: /* Address Granularity */
+
+ Descriptor->Address32.Granularity =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 7: /* Min Address */
+
+ Descriptor->Address32.Minimum =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 8: /* Max Address */
+
+ Descriptor->Address32.Maximum =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 9: /* Translation Offset */
+
+ Descriptor->Address32.TranslationOffset =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset));
+ break;
+
+ case 10: /* Address Length */
+
+ Descriptor->Address32.AddressLength =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 11: /* ResSourceIndex [Optional Field - BYTE] */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
+ OptionIndex++;
+ Descriptor->Address32.ResourceLength++;
+ ResSourceIndex = TRUE;
+ }
+ break;
+
+ case 12: /* ResSource [Optional Field - STRING] */
+
+ if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
+ (InitializerOp->Asl.Value.String))
+ {
+ if (StringLength)
+ {
+ Descriptor->Address32.ResourceLength = (UINT16)
+ (Descriptor->Address32.ResourceLength + StringLength);
+
+ strcpy ((char *)
+ &OptionalFields[OptionIndex],
+ InitializerOp->Asl.Value.String);
+
+ /* ResourceSourceIndex must also be valid */
+
+ if (!ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
+ InitializerOp, NULL);
+ }
+ }
+ }
+
+#if 0
+ /*
+ * Not a valid ResourceSource, ResourceSourceIndex must also
+ * be invalid
+ */
+ else if (ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
+ InitializerOp, NULL);
+ }
+#endif
+ break;
+
+ case 13: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+
+ case 14: /* Address Range */
+
+ RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 3);
+ break;
+
+ case 15: /* Type */
+
+ RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 5, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 5);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->Address32.Minimum,
+ Descriptor->Address32.Maximum,
+ Descriptor->Address32.AddressLength,
+ Descriptor->Address32.Granularity,
+ Descriptor->Address32.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) +
+ OptionIndex + StringLength;
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoDwordSpaceDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "DwordSpace" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoDwordSpaceDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT8 *OptionalFields;
+ UINT16 StringLength = 0;
+ UINT32 OptionIndex = 0;
+ UINT32 i;
+ BOOLEAN ResSourceIndex = FALSE;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32;
+
+ /*
+ * Initial descriptor length -- may be enlarged if there are
+ * optional fields present
+ */
+ OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32);
+ Descriptor->Address32.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_ADDRESS32) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Type */
+
+ Descriptor->Address32.ResourceType =
+ (UINT8) InitializerOp->Asl.Value.Integer;
+ break;
+
+ case 1: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 2: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1);
+ break;
+
+ case 3: /* MinType */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2);
+ break;
+
+ case 4: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3);
+ break;
+
+ case 5: /* Type-Specific flags */
+
+ Descriptor->Address32.SpecificFlags =
+ (UINT8) InitializerOp->Asl.Value.Integer;
+ break;
+
+ case 6: /* Address Granularity */
+
+ Descriptor->Address32.Granularity =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 7: /* Min Address */
+
+ Descriptor->Address32.Minimum =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 8: /* Max Address */
+
+ Descriptor->Address32.Maximum =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 9: /* Translation Offset */
+
+ Descriptor->Address32.TranslationOffset =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset));
+ break;
+
+ case 10: /* Address Length */
+
+ Descriptor->Address32.AddressLength =
+ (UINT32) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 11: /* ResSourceIndex [Optional Field - BYTE] */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
+ OptionIndex++;
+ Descriptor->Address32.ResourceLength++;
+ ResSourceIndex = TRUE;
+ }
+ break;
+
+ case 12: /* ResSource [Optional Field - STRING] */
+
+ if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
+ (InitializerOp->Asl.Value.String))
+ {
+ if (StringLength)
+ {
+ Descriptor->Address32.ResourceLength = (UINT16)
+ (Descriptor->Address32.ResourceLength + StringLength);
+
+ strcpy ((char *)
+ &OptionalFields[OptionIndex],
+ InitializerOp->Asl.Value.String);
+
+ /* ResourceSourceIndex must also be valid */
+
+ if (!ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
+ InitializerOp, NULL);
+ }
+ }
+ }
+
+#if 0
+ /*
+ * Not a valid ResourceSource, ResourceSourceIndex must also
+ * be invalid
+ */
+ else if (ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
+ InitializerOp, NULL);
+ }
+#endif
+ break;
+
+ case 13: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST,
+ InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->Address32.Minimum,
+ Descriptor->Address32.Maximum,
+ Descriptor->Address32.AddressLength,
+ Descriptor->Address32.Granularity,
+ Descriptor->Address32.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) +
+ OptionIndex + StringLength;
+ return (Rnode);
+}
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2e.c b/sys/contrib/dev/acpica/compiler/aslrestype2e.c
new file mode 100644
index 0000000..b75d174
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2e.c
@@ -0,0 +1,646 @@
+
+/******************************************************************************
+ *
+ * Module Name: aslrestype2e - Large Extended address resource descriptors
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * 1. Copyright Notice
+ *
+ * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * 2. License
+ *
+ * 2.1. This is your license from Intel Corp. under its intellectual property
+ * rights. You may have additional license terms from the party that provided
+ * you this software, covering your right to use that party's intellectual
+ * property rights.
+ *
+ * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
+ * copy of the source code appearing in this file ("Covered Code") an
+ * irrevocable, perpetual, worldwide license under Intel's copyrights in the
+ * base code distributed originally by Intel ("Original Intel Code") to copy,
+ * make derivatives, distribute, use and display any portion of the Covered
+ * Code in any form, with the right to sublicense such rights; and
+ *
+ * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
+ * license (with the right to sublicense), under only those claims of Intel
+ * patents that are infringed by the Original Intel Code, to make, use, sell,
+ * offer to sell, and import the Covered Code and derivative works thereof
+ * solely to the minimum extent necessary to exercise the above copyright
+ * license, and in no event shall the patent license extend to any additions
+ * to or modifications of the Original Intel Code. No other license or right
+ * is granted directly or by implication, estoppel or otherwise;
+ *
+ * The above copyright and patent license is granted only if the following
+ * conditions are met:
+ *
+ * 3. Conditions
+ *
+ * 3.1. Redistribution of Source with Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification with rights to further distribute source must include
+ * the above Copyright Notice, the above License, this list of Conditions,
+ * and the following Disclaimer and Export Compliance provision. In addition,
+ * Licensee must cause all Covered Code to which Licensee contributes to
+ * contain a file documenting the changes Licensee made to create that Covered
+ * Code and the date of any change. Licensee must include in that file the
+ * documentation of any changes made by any predecessor Licensee. Licensee
+ * must include a prominent statement that the modification is derived,
+ * directly or indirectly, from Original Intel Code.
+ *
+ * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification without rights to further distribute source must
+ * include the following Disclaimer and Export Compliance provision in the
+ * documentation and/or other materials provided with distribution. In
+ * addition, Licensee may not authorize further sublicense of source of any
+ * portion of the Covered Code, and must include terms to the effect that the
+ * license from Licensee to its licensee is limited to the intellectual
+ * property embodied in the software Licensee provides to its licensee, and
+ * not to intellectual property embodied in modifications its licensee may
+ * make.
+ *
+ * 3.3. Redistribution of Executable. Redistribution in executable form of any
+ * substantial portion of the Covered Code or modification must reproduce the
+ * above Copyright Notice, and the following Disclaimer and Export Compliance
+ * provision in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3.4. Intel retains all right, title, and interest in and to the Original
+ * Intel Code.
+ *
+ * 3.5. Neither the name Intel nor any other trademark owned or controlled by
+ * Intel shall be used in advertising or otherwise to promote the sale, use or
+ * other dealings in products derived from or relating to the Covered Code
+ * without prior written authorization from Intel.
+ *
+ * 4. Disclaimer and Export Compliance
+ *
+ * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
+ * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
+ * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
+ * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
+ * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
+ * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
+ * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
+ * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
+ * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
+ * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
+ * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
+ * LIMITED REMEDY.
+ *
+ * 4.3. Licensee shall not export, either directly or indirectly, any of this
+ * software or system incorporating such software without first obtaining any
+ * required license or other approval from the U. S. Department of Commerce or
+ * any other agency or department of the United States Government. In the
+ * event Licensee exports any such software from the United States or
+ * re-exports any such software from a foreign destination, Licensee shall
+ * ensure that the distribution and export/re-export of the software is in
+ * compliance with all laws, regulations, orders, or other restrictions of the
+ * U.S. Export Administration Regulations. Licensee agrees that neither it nor
+ * any of its subsidiaries will export/re-export any technical data, process,
+ * software, or service, directly or indirectly, to any country for which the
+ * United States government or any agency thereof requires an export license,
+ * other governmental approval, or letter of assurance, without first obtaining
+ * such license, approval or letter.
+ *
+ *****************************************************************************/
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslrestype2e")
+
+/*
+ * This module contains the Extended (64-bit) address space descriptors:
+ *
+ * ExtendedIO
+ * ExtendedMemory
+ * ExtendedSpace
+ */
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoExtendedIoDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "ExtendedIO" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoExtendedIoDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT16 StringLength = 0;
+ UINT32 i;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64;
+ Descriptor->ExtAddress64.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE;
+ Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION;
+
+ Descriptor->ExtAddress64.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 1: /* MinType */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2);
+ break;
+
+ case 2: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3);
+ break;
+
+ case 3: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1);
+ break;
+
+ case 4: /* Range Type */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 0, 3);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 0);
+ break;
+
+ case 5: /* Address Granularity */
+
+ Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 6: /* Address Min */
+
+ Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 7: /* Address Max */
+
+ Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 8: /* Translation Offset */
+
+ Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset));
+ break;
+
+ case 9: /* Address Length */
+
+ Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 10: /* Type-Specific Attributes */
+
+ Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific));
+ break;
+
+ case 11: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ case 12: /* Type */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 4, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 4);
+ break;
+
+ case 13: /* Translation Type */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 5, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 5);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->ExtAddress64.Minimum,
+ Descriptor->ExtAddress64.Maximum,
+ Descriptor->ExtAddress64.AddressLength,
+ Descriptor->ExtAddress64.Granularity,
+ Descriptor->ExtAddress64.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength;
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoExtendedMemoryDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "ExtendedMemory" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoExtendedMemoryDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT16 StringLength = 0;
+ UINT32 i;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64;
+ Descriptor->ExtAddress64.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE;
+ Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION;
+
+ Descriptor->ExtAddress64.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 1: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1);
+ break;
+
+ case 2: /* MinType */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2);
+ break;
+
+ case 3: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3);
+ break;
+
+ case 4: /* Memory Type */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 1);
+ break;
+
+ case 5: /* Read/Write Type */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 0, 1);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 0);
+ break;
+
+ case 6: /* Address Granularity */
+
+ Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 7: /* Min Address */
+
+ Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 8: /* Max Address */
+
+ Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 9: /* Translation Offset */
+
+ Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset));
+ break;
+
+ case 10: /* Address Length */
+
+ Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 11: /* Type-Specific Attributes */
+
+ Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific));
+ break;
+
+ case 12: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+
+ case 13: /* Address Range */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 3);
+ break;
+
+ case 14: /* Type */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 5, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 5);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->ExtAddress64.Minimum,
+ Descriptor->ExtAddress64.Maximum,
+ Descriptor->ExtAddress64.AddressLength,
+ Descriptor->ExtAddress64.Granularity,
+ Descriptor->ExtAddress64.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength;
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoExtendedSpaceDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "ExtendedSpace" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoExtendedSpaceDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT16 StringLength = 0;
+ UINT32 i;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64;
+ Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION;
+
+ Descriptor->ExtAddress64.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Type */
+
+ Descriptor->ExtAddress64.ResourceType =
+ (UINT8) InitializerOp->Asl.Value.Integer;
+ break;
+
+ case 1: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 2: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1);
+ break;
+
+ case 3: /* MinType */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2);
+ break;
+
+ case 4: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3);
+ break;
+
+ case 5: /* Type-Specific flags */
+
+ Descriptor->ExtAddress64.SpecificFlags =
+ (UINT8) InitializerOp->Asl.Value.Integer;
+ break;
+
+ case 6: /* Address Granularity */
+
+ Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 7: /* Min Address */
+
+ Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 8: /* Max Address */
+
+ Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 9: /* Translation Offset */
+
+ Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset));
+ break;
+
+ case 10: /* Address Length */
+
+ Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 11: /* Type-Specific Attributes */
+
+ Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific));
+ break;
+
+ case 12: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->ExtAddress64.Minimum,
+ Descriptor->ExtAddress64.Maximum,
+ Descriptor->ExtAddress64.AddressLength,
+ Descriptor->ExtAddress64.Granularity,
+ Descriptor->ExtAddress64.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength;
+ return (Rnode);
+}
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2q.c b/sys/contrib/dev/acpica/compiler/aslrestype2q.c
new file mode 100644
index 0000000..cea12aa
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2q.c
@@ -0,0 +1,793 @@
+
+/******************************************************************************
+ *
+ * Module Name: aslrestype2q - Large QWord address resource descriptors
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * 1. Copyright Notice
+ *
+ * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * 2. License
+ *
+ * 2.1. This is your license from Intel Corp. under its intellectual property
+ * rights. You may have additional license terms from the party that provided
+ * you this software, covering your right to use that party's intellectual
+ * property rights.
+ *
+ * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
+ * copy of the source code appearing in this file ("Covered Code") an
+ * irrevocable, perpetual, worldwide license under Intel's copyrights in the
+ * base code distributed originally by Intel ("Original Intel Code") to copy,
+ * make derivatives, distribute, use and display any portion of the Covered
+ * Code in any form, with the right to sublicense such rights; and
+ *
+ * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
+ * license (with the right to sublicense), under only those claims of Intel
+ * patents that are infringed by the Original Intel Code, to make, use, sell,
+ * offer to sell, and import the Covered Code and derivative works thereof
+ * solely to the minimum extent necessary to exercise the above copyright
+ * license, and in no event shall the patent license extend to any additions
+ * to or modifications of the Original Intel Code. No other license or right
+ * is granted directly or by implication, estoppel or otherwise;
+ *
+ * The above copyright and patent license is granted only if the following
+ * conditions are met:
+ *
+ * 3. Conditions
+ *
+ * 3.1. Redistribution of Source with Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification with rights to further distribute source must include
+ * the above Copyright Notice, the above License, this list of Conditions,
+ * and the following Disclaimer and Export Compliance provision. In addition,
+ * Licensee must cause all Covered Code to which Licensee contributes to
+ * contain a file documenting the changes Licensee made to create that Covered
+ * Code and the date of any change. Licensee must include in that file the
+ * documentation of any changes made by any predecessor Licensee. Licensee
+ * must include a prominent statement that the modification is derived,
+ * directly or indirectly, from Original Intel Code.
+ *
+ * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification without rights to further distribute source must
+ * include the following Disclaimer and Export Compliance provision in the
+ * documentation and/or other materials provided with distribution. In
+ * addition, Licensee may not authorize further sublicense of source of any
+ * portion of the Covered Code, and must include terms to the effect that the
+ * license from Licensee to its licensee is limited to the intellectual
+ * property embodied in the software Licensee provides to its licensee, and
+ * not to intellectual property embodied in modifications its licensee may
+ * make.
+ *
+ * 3.3. Redistribution of Executable. Redistribution in executable form of any
+ * substantial portion of the Covered Code or modification must reproduce the
+ * above Copyright Notice, and the following Disclaimer and Export Compliance
+ * provision in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3.4. Intel retains all right, title, and interest in and to the Original
+ * Intel Code.
+ *
+ * 3.5. Neither the name Intel nor any other trademark owned or controlled by
+ * Intel shall be used in advertising or otherwise to promote the sale, use or
+ * other dealings in products derived from or relating to the Covered Code
+ * without prior written authorization from Intel.
+ *
+ * 4. Disclaimer and Export Compliance
+ *
+ * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
+ * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
+ * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
+ * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
+ * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
+ * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
+ * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
+ * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
+ * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
+ * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
+ * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
+ * LIMITED REMEDY.
+ *
+ * 4.3. Licensee shall not export, either directly or indirectly, any of this
+ * software or system incorporating such software without first obtaining any
+ * required license or other approval from the U. S. Department of Commerce or
+ * any other agency or department of the United States Government. In the
+ * event Licensee exports any such software from the United States or
+ * re-exports any such software from a foreign destination, Licensee shall
+ * ensure that the distribution and export/re-export of the software is in
+ * compliance with all laws, regulations, orders, or other restrictions of the
+ * U.S. Export Administration Regulations. Licensee agrees that neither it nor
+ * any of its subsidiaries will export/re-export any technical data, process,
+ * software, or service, directly or indirectly, to any country for which the
+ * United States government or any agency thereof requires an export license,
+ * other governmental approval, or letter of assurance, without first obtaining
+ * such license, approval or letter.
+ *
+ *****************************************************************************/
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslrestype2q")
+
+/*
+ * This module contains the QWord (64-bit) address space descriptors:
+ *
+ * QWordIO
+ * QWordMemory
+ * QWordSpace
+ */
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoQwordIoDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "QwordIO" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoQwordIoDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT8 *OptionalFields;
+ UINT16 StringLength = 0;
+ UINT32 OptionIndex = 0;
+ UINT32 i;
+ BOOLEAN ResSourceIndex = FALSE;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64;
+ Descriptor->Address64.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE;
+
+ /*
+ * Initial descriptor length -- may be enlarged if there are
+ * optional fields present
+ */
+ OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64);
+ Descriptor->Address64.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_ADDRESS64) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 1: /* MinType */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2);
+ break;
+
+ case 2: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3);
+ break;
+
+ case 3: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1);
+ break;
+
+ case 4: /* Range Type */
+
+ RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 0, 3);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 0);
+ break;
+
+ case 5: /* Address Granularity */
+
+ Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 6: /* Address Min */
+
+ Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 7: /* Address Max */
+
+ Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 8: /* Translation Offset */
+
+ Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset));
+ break;
+
+ case 9: /* Address Length */
+
+ Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 10: /* ResSourceIndex [Optional Field - BYTE] */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
+ OptionIndex++;
+ Descriptor->Address64.ResourceLength++;
+ ResSourceIndex = TRUE;
+ }
+ break;
+
+ case 11: /* ResSource [Optional Field - STRING] */
+
+ if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
+ (InitializerOp->Asl.Value.String))
+ {
+ if (StringLength)
+ {
+ Descriptor->Address64.ResourceLength = (UINT16)
+ (Descriptor->Address64.ResourceLength + StringLength);
+
+ strcpy ((char *)
+ &OptionalFields[OptionIndex],
+ InitializerOp->Asl.Value.String);
+
+ /* ResourceSourceIndex must also be valid */
+
+ if (!ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
+ InitializerOp, NULL);
+ }
+ }
+ }
+
+#if 0
+ /*
+ * Not a valid ResourceSource, ResourceSourceIndex must also
+ * be invalid
+ */
+ else if (ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
+ InitializerOp, NULL);
+ }
+#endif
+ break;
+
+ case 12: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ case 13: /* Type */
+
+ RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 4, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 4);
+ break;
+
+ case 14: /* Translation Type */
+
+ RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 5, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 5);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->Address64.Minimum,
+ Descriptor->Address64.Maximum,
+ Descriptor->Address64.AddressLength,
+ Descriptor->Address64.Granularity,
+ Descriptor->Address64.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) +
+ OptionIndex + StringLength;
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoQwordMemoryDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "QwordMemory" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoQwordMemoryDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT8 *OptionalFields;
+ UINT16 StringLength = 0;
+ UINT32 OptionIndex = 0;
+ UINT32 i;
+ BOOLEAN ResSourceIndex = FALSE;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64;
+ Descriptor->Address64.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE;
+
+ /*
+ * Initial descriptor length -- may be enlarged if there are
+ * optional fields present
+ */
+ OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64);
+ Descriptor->Address64.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_ADDRESS64) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 1: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1);
+ break;
+
+ case 2: /* MinType */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2);
+ break;
+
+ case 3: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3);
+ break;
+
+ case 4: /* Memory Type */
+
+ RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 1);
+ break;
+
+ case 5: /* Read/Write Type */
+
+ RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 0, 1);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 0);
+ break;
+
+ case 6: /* Address Granularity */
+
+ Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 7: /* Min Address */
+
+ Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 8: /* Max Address */
+
+ Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 9: /* Translation Offset */
+
+ Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset));
+ break;
+
+ case 10: /* Address Length */
+
+ Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 11: /* ResSourceIndex [Optional Field - BYTE] */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
+ OptionIndex++;
+ Descriptor->Address64.ResourceLength++;
+ ResSourceIndex = TRUE;
+ }
+ break;
+
+ case 12: /* ResSource [Optional Field - STRING] */
+
+ if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
+ (InitializerOp->Asl.Value.String))
+ {
+ if (StringLength)
+ {
+ Descriptor->Address64.ResourceLength = (UINT16)
+ (Descriptor->Address64.ResourceLength + StringLength);
+
+ strcpy ((char *)
+ &OptionalFields[OptionIndex],
+ InitializerOp->Asl.Value.String);
+
+ /* ResourceSourceIndex must also be valid */
+
+ if (!ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
+ InitializerOp, NULL);
+ }
+ }
+ }
+
+#if 0
+ /*
+ * Not a valid ResourceSource, ResourceSourceIndex must also
+ * be invalid
+ */
+ else if (ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
+ InitializerOp, NULL);
+ }
+#endif
+ break;
+
+ case 13: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+
+ case 14: /* Address Range */
+
+ RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 3);
+ break;
+
+ case 15: /* Type */
+
+ RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 5, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 5);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->Address64.Minimum,
+ Descriptor->Address64.Maximum,
+ Descriptor->Address64.AddressLength,
+ Descriptor->Address64.Granularity,
+ Descriptor->Address64.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) +
+ OptionIndex + StringLength;
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoQwordSpaceDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "QwordSpace" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoQwordSpaceDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT8 *OptionalFields;
+ UINT16 StringLength = 0;
+ UINT32 OptionIndex = 0;
+ UINT32 i;
+ BOOLEAN ResSourceIndex = FALSE;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64;
+
+ /*
+ * Initial descriptor length -- may be enlarged if there are
+ * optional fields present
+ */
+ OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64);
+ Descriptor->Address64.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_ADDRESS64) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Type */
+
+ Descriptor->Address64.ResourceType =
+ (UINT8) InitializerOp->Asl.Value.Integer;
+ break;
+
+ case 1: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 2: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1);
+ break;
+
+ case 3: /* MinType */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2);
+ break;
+
+ case 4: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3);
+ break;
+
+ case 5: /* Type-Specific flags */
+
+ Descriptor->Address64.SpecificFlags =
+ (UINT8) InitializerOp->Asl.Value.Integer;
+ break;
+
+ case 6: /* Address Granularity */
+
+ Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 7: /* Min Address */
+
+ Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 8: /* Max Address */
+
+ Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 9: /* Translation Offset */
+
+ Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset));
+ break;
+
+ case 10: /* Address Length */
+
+ Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 11: /* ResSourceIndex [Optional Field - BYTE] */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
+ OptionIndex++;
+ Descriptor->Address64.ResourceLength++;
+ ResSourceIndex = TRUE;
+ }
+ break;
+
+ case 12: /* ResSource [Optional Field - STRING] */
+
+ if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
+ (InitializerOp->Asl.Value.String))
+ {
+ if (StringLength)
+ {
+ Descriptor->Address64.ResourceLength = (UINT16)
+ (Descriptor->Address64.ResourceLength + StringLength);
+
+ strcpy ((char *)
+ &OptionalFields[OptionIndex],
+ InitializerOp->Asl.Value.String);
+
+ /* ResourceSourceIndex must also be valid */
+
+ if (!ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
+ InitializerOp, NULL);
+ }
+ }
+ }
+
+#if 0
+ /*
+ * Not a valid ResourceSource, ResourceSourceIndex must also
+ * be invalid
+ */
+ else if (ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
+ InitializerOp, NULL);
+ }
+#endif
+ break;
+
+ case 13: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->Address64.Minimum,
+ Descriptor->Address64.Maximum,
+ Descriptor->Address64.AddressLength,
+ Descriptor->Address64.Granularity,
+ Descriptor->Address64.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) +
+ OptionIndex + StringLength;
+ return (Rnode);
+}
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2w.c b/sys/contrib/dev/acpica/compiler/aslrestype2w.c
new file mode 100644
index 0000000..fa0bb22
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2w.c
@@ -0,0 +1,774 @@
+
+/******************************************************************************
+ *
+ * Module Name: aslrestype2w - Large Word address resource descriptors
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * 1. Copyright Notice
+ *
+ * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * 2. License
+ *
+ * 2.1. This is your license from Intel Corp. under its intellectual property
+ * rights. You may have additional license terms from the party that provided
+ * you this software, covering your right to use that party's intellectual
+ * property rights.
+ *
+ * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
+ * copy of the source code appearing in this file ("Covered Code") an
+ * irrevocable, perpetual, worldwide license under Intel's copyrights in the
+ * base code distributed originally by Intel ("Original Intel Code") to copy,
+ * make derivatives, distribute, use and display any portion of the Covered
+ * Code in any form, with the right to sublicense such rights; and
+ *
+ * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
+ * license (with the right to sublicense), under only those claims of Intel
+ * patents that are infringed by the Original Intel Code, to make, use, sell,
+ * offer to sell, and import the Covered Code and derivative works thereof
+ * solely to the minimum extent necessary to exercise the above copyright
+ * license, and in no event shall the patent license extend to any additions
+ * to or modifications of the Original Intel Code. No other license or right
+ * is granted directly or by implication, estoppel or otherwise;
+ *
+ * The above copyright and patent license is granted only if the following
+ * conditions are met:
+ *
+ * 3. Conditions
+ *
+ * 3.1. Redistribution of Source with Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification with rights to further distribute source must include
+ * the above Copyright Notice, the above License, this list of Conditions,
+ * and the following Disclaimer and Export Compliance provision. In addition,
+ * Licensee must cause all Covered Code to which Licensee contributes to
+ * contain a file documenting the changes Licensee made to create that Covered
+ * Code and the date of any change. Licensee must include in that file the
+ * documentation of any changes made by any predecessor Licensee. Licensee
+ * must include a prominent statement that the modification is derived,
+ * directly or indirectly, from Original Intel Code.
+ *
+ * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification without rights to further distribute source must
+ * include the following Disclaimer and Export Compliance provision in the
+ * documentation and/or other materials provided with distribution. In
+ * addition, Licensee may not authorize further sublicense of source of any
+ * portion of the Covered Code, and must include terms to the effect that the
+ * license from Licensee to its licensee is limited to the intellectual
+ * property embodied in the software Licensee provides to its licensee, and
+ * not to intellectual property embodied in modifications its licensee may
+ * make.
+ *
+ * 3.3. Redistribution of Executable. Redistribution in executable form of any
+ * substantial portion of the Covered Code or modification must reproduce the
+ * above Copyright Notice, and the following Disclaimer and Export Compliance
+ * provision in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3.4. Intel retains all right, title, and interest in and to the Original
+ * Intel Code.
+ *
+ * 3.5. Neither the name Intel nor any other trademark owned or controlled by
+ * Intel shall be used in advertising or otherwise to promote the sale, use or
+ * other dealings in products derived from or relating to the Covered Code
+ * without prior written authorization from Intel.
+ *
+ * 4. Disclaimer and Export Compliance
+ *
+ * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
+ * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
+ * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
+ * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
+ * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
+ * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
+ * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
+ * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
+ * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
+ * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
+ * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
+ * LIMITED REMEDY.
+ *
+ * 4.3. Licensee shall not export, either directly or indirectly, any of this
+ * software or system incorporating such software without first obtaining any
+ * required license or other approval from the U. S. Department of Commerce or
+ * any other agency or department of the United States Government. In the
+ * event Licensee exports any such software from the United States or
+ * re-exports any such software from a foreign destination, Licensee shall
+ * ensure that the distribution and export/re-export of the software is in
+ * compliance with all laws, regulations, orders, or other restrictions of the
+ * U.S. Export Administration Regulations. Licensee agrees that neither it nor
+ * any of its subsidiaries will export/re-export any technical data, process,
+ * software, or service, directly or indirectly, to any country for which the
+ * United States government or any agency thereof requires an export license,
+ * other governmental approval, or letter of assurance, without first obtaining
+ * such license, approval or letter.
+ *
+ *****************************************************************************/
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslrestype2w")
+
+/*
+ * This module contains the Word (16-bit) address space descriptors:
+ *
+ * WordIO
+ * WordMemory
+ * WordSpace
+ */
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoWordIoDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "WordIO" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoWordIoDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT8 *OptionalFields;
+ UINT16 StringLength = 0;
+ UINT32 OptionIndex = 0;
+ UINT32 i;
+ BOOLEAN ResSourceIndex = FALSE;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16;
+ Descriptor->Address16.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE;
+
+ /*
+ * Initial descriptor length -- may be enlarged if there are
+ * optional fields present
+ */
+ OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16);
+ Descriptor->Address16.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_ADDRESS16) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 1: /* MinType */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2);
+ break;
+
+ case 2: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3);
+ break;
+
+ case 3: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1);
+ break;
+
+ case 4: /* Range Type */
+
+ RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 0, 3);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 0);
+ break;
+
+ case 5: /* Address Granularity */
+
+ Descriptor->Address16.Granularity = (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 6: /* Address Min */
+
+ Descriptor->Address16.Minimum = (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 7: /* Address Max */
+
+ Descriptor->Address16.Maximum = (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 8: /* Translation Offset */
+
+ Descriptor->Address16.TranslationOffset = (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset));
+ break;
+
+ case 9: /* Address Length */
+
+ Descriptor->Address16.AddressLength = (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 10: /* ResSourceIndex [Optional Field - BYTE] */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
+ OptionIndex++;
+ Descriptor->Address16.ResourceLength++;
+ ResSourceIndex = TRUE;
+ }
+ break;
+
+ case 11: /* ResSource [Optional Field - STRING] */
+
+ if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
+ (InitializerOp->Asl.Value.String))
+ {
+ if (StringLength)
+ {
+ Descriptor->Address16.ResourceLength = (UINT16)
+ (Descriptor->Address16.ResourceLength + StringLength);
+
+ strcpy ((char *)
+ &OptionalFields[OptionIndex],
+ InitializerOp->Asl.Value.String);
+
+ /* ResourceSourceIndex must also be valid */
+
+ if (!ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
+ InitializerOp, NULL);
+ }
+ }
+ }
+
+#if 0
+ /*
+ * Not a valid ResourceSource, ResourceSourceIndex must also
+ * be invalid
+ */
+ else if (ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
+ InitializerOp, NULL);
+ }
+#endif
+ break;
+
+ case 12: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ case 13: /* Type */
+
+ RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 4, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 4);
+ break;
+
+ case 14: /* Translation Type */
+
+ RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 5, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 5);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->Address16.Minimum,
+ Descriptor->Address16.Maximum,
+ Descriptor->Address16.AddressLength,
+ Descriptor->Address16.Granularity,
+ Descriptor->Address16.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) +
+ OptionIndex + StringLength;
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoWordBusNumberDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "WordBusNumber" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoWordBusNumberDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT8 *OptionalFields;
+ UINT16 StringLength = 0;
+ UINT32 OptionIndex = 0;
+ UINT32 i;
+ BOOLEAN ResSourceIndex = FALSE;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16;
+ Descriptor->Address16.ResourceType = ACPI_ADDRESS_TYPE_BUS_NUMBER_RANGE;
+
+ /*
+ * Initial descriptor length -- may be enlarged if there are
+ * optional fields present
+ */
+ OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16);
+ Descriptor->Address16.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_ADDRESS16) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 1: /* MinType */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2);
+ break;
+
+ case 2: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3);
+ break;
+
+ case 3: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1);
+ break;
+
+ case 4: /* Address Granularity */
+
+ Descriptor->Address16.Granularity =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 5: /* Min Address */
+
+ Descriptor->Address16.Minimum =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 6: /* Max Address */
+
+ Descriptor->Address16.Maximum =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 7: /* Translation Offset */
+
+ Descriptor->Address16.TranslationOffset =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset));
+ break;
+
+ case 8: /* Address Length */
+
+ Descriptor->Address16.AddressLength =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 9: /* ResSourceIndex [Optional Field - BYTE] */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
+ OptionIndex++;
+ Descriptor->Address16.ResourceLength++;
+ ResSourceIndex = TRUE;
+ }
+ break;
+
+ case 10: /* ResSource [Optional Field - STRING] */
+
+ if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
+ (InitializerOp->Asl.Value.String))
+ {
+ if (StringLength)
+ {
+ Descriptor->Address16.ResourceLength = (UINT16)
+ (Descriptor->Address16.ResourceLength + StringLength);
+
+ strcpy ((char *)
+ &OptionalFields[OptionIndex],
+ InitializerOp->Asl.Value.String);
+
+ /* ResourceSourceIndex must also be valid */
+
+ if (!ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
+ InitializerOp, NULL);
+ }
+ }
+ }
+
+#if 0
+ /*
+ * Not a valid ResourceSource, ResourceSourceIndex must also
+ * be invalid
+ */
+ else if (ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
+ InitializerOp, NULL);
+ }
+#endif
+ break;
+
+ case 11: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->Address16.Minimum,
+ Descriptor->Address16.Maximum,
+ Descriptor->Address16.AddressLength,
+ Descriptor->Address16.Granularity,
+ Descriptor->Address16.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) +
+ OptionIndex + StringLength;
+ return (Rnode);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: RsDoWordSpaceDescriptor
+ *
+ * PARAMETERS: Op - Parent resource descriptor parse node
+ * CurrentByteOffset - Offset into the resource template AML
+ * buffer (to track references to the desc)
+ *
+ * RETURN: Completed resource node
+ *
+ * DESCRIPTION: Construct a long "WordSpace" descriptor
+ *
+ ******************************************************************************/
+
+ASL_RESOURCE_NODE *
+RsDoWordSpaceDescriptor (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 CurrentByteOffset)
+{
+ AML_RESOURCE *Descriptor;
+ ACPI_PARSE_OBJECT *InitializerOp;
+ ACPI_PARSE_OBJECT *MinOp = NULL;
+ ACPI_PARSE_OBJECT *MaxOp = NULL;
+ ACPI_PARSE_OBJECT *LengthOp = NULL;
+ ACPI_PARSE_OBJECT *GranOp = NULL;
+ ASL_RESOURCE_NODE *Rnode;
+ UINT8 *OptionalFields;
+ UINT16 StringLength = 0;
+ UINT32 OptionIndex = 0;
+ UINT32 i;
+ BOOLEAN ResSourceIndex = FALSE;
+
+
+ InitializerOp = Op->Asl.Child;
+ StringLength = RsGetStringDataLength (InitializerOp);
+
+ Rnode = RsAllocateResourceNode (
+ sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength);
+
+ Descriptor = Rnode->Buffer;
+ Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16;
+
+ /*
+ * Initial descriptor length -- may be enlarged if there are
+ * optional fields present
+ */
+ OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16);
+ Descriptor->Address16.ResourceLength = (UINT16)
+ (sizeof (AML_RESOURCE_ADDRESS16) -
+ sizeof (AML_RESOURCE_LARGE_HEADER));
+
+ /* Process all child initialization nodes */
+
+ for (i = 0; InitializerOp; i++)
+ {
+ switch (i)
+ {
+ case 0: /* Resource Type */
+
+ Descriptor->Address16.ResourceType =
+ (UINT8) InitializerOp->Asl.Value.Integer;
+ break;
+
+ case 1: /* Resource Usage */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1);
+ break;
+
+ case 2: /* DecodeType */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1);
+ break;
+
+ case 3: /* MinType */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2);
+ break;
+
+ case 4: /* MaxType */
+
+ RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0);
+ RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3);
+ break;
+
+ case 5: /* Type-Specific flags */
+
+ Descriptor->Address16.SpecificFlags =
+ (UINT8) InitializerOp->Asl.Value.Integer;
+ break;
+
+ case 6: /* Address Granularity */
+
+ Descriptor->Address16.Granularity =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity));
+ GranOp = InitializerOp;
+ break;
+
+ case 7: /* Min Address */
+
+ Descriptor->Address16.Minimum =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum));
+ MinOp = InitializerOp;
+ break;
+
+ case 8: /* Max Address */
+
+ Descriptor->Address16.Maximum =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum));
+ MaxOp = InitializerOp;
+ break;
+
+ case 9: /* Translation Offset */
+
+ Descriptor->Address16.TranslationOffset =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset));
+ break;
+
+ case 10: /* Address Length */
+
+ Descriptor->Address16.AddressLength =
+ (UINT16) InitializerOp->Asl.Value.Integer;
+ RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH,
+ CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength));
+ LengthOp = InitializerOp;
+ break;
+
+ case 11: /* ResSourceIndex [Optional Field - BYTE] */
+
+ if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
+ {
+ OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer;
+ OptionIndex++;
+ Descriptor->Address16.ResourceLength++;
+ ResSourceIndex = TRUE;
+ }
+ break;
+
+ case 12: /* ResSource [Optional Field - STRING] */
+
+ if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
+ (InitializerOp->Asl.Value.String))
+ {
+ if (StringLength)
+ {
+ Descriptor->Address16.ResourceLength = (UINT16)
+ (Descriptor->Address16.ResourceLength + StringLength);
+
+ strcpy ((char *)
+ &OptionalFields[OptionIndex],
+ InitializerOp->Asl.Value.String);
+
+ /* ResourceSourceIndex must also be valid */
+
+ if (!ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX,
+ InitializerOp, NULL);
+ }
+ }
+ }
+
+#if 0
+ /*
+ * Not a valid ResourceSource, ResourceSourceIndex must also
+ * be invalid
+ */
+ else if (ResSourceIndex)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE,
+ InitializerOp, NULL);
+ }
+#endif
+ break;
+
+ case 13: /* ResourceTag */
+
+ UtAttachNamepathToOwner (Op, InitializerOp);
+ break;
+
+ default:
+
+ AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL);
+ break;
+ }
+
+ InitializerOp = RsCompleteNodeAndGetNext (InitializerOp);
+ }
+
+ /* Validate the Min/Max/Len/Gran values */
+
+ RsLargeAddressCheck (
+ Descriptor->Address16.Minimum,
+ Descriptor->Address16.Maximum,
+ Descriptor->Address16.AddressLength,
+ Descriptor->Address16.Granularity,
+ Descriptor->Address16.Flags,
+ MinOp, MaxOp, LengthOp, GranOp);
+
+ Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) +
+ OptionIndex + StringLength;
+ return (Rnode);
+}
diff --git a/sys/contrib/dev/acpica/compiler/asltypes.h b/sys/contrib/dev/acpica/compiler/asltypes.h
index 30b8fdf..8157634 100644
--- a/sys/contrib/dev/acpica/compiler/asltypes.h
+++ b/sys/contrib/dev/acpica/compiler/asltypes.h
@@ -420,7 +420,16 @@ typedef enum
ASL_MSG_SERIALIZED,
ASL_MSG_COMPILER_RESERVED,
ASL_MSG_NAMED_OBJECT_IN_WHILE,
- ASL_MSG_LOCAL_OUTSIDE_METHOD
+ ASL_MSG_LOCAL_OUTSIDE_METHOD,
+ ASL_MSG_ALIGNMENT,
+ ASL_MSG_ISA_ADDRESS,
+ ASL_MSG_INVALID_MIN_MAX,
+ ASL_MSG_INVALID_LENGTH,
+ ASL_MSG_INVALID_LENGTH_FIXED,
+ ASL_MSG_INVALID_GRANULARITY,
+ ASL_MSG_INVALID_GRAN_FIXED,
+ ASL_MSG_INVALID_ACCESS_SIZE,
+ ASL_MSG_INVALID_ADDR_FLAGS
} ASL_MESSAGE_IDS;
@@ -540,7 +549,16 @@ char *AslMessages [] = {
/* ASL_MSG_SERIALIZED */ "Control Method marked Serialized",
/* ASL_MSG_COMPILER_RESERVED */ "Use of compiler reserved name",
/* ASL_MSG_NAMED_OBJECT_IN_WHILE */ "Creating a named object in a While loop",
-/* ASL_MSG_LOCAL_OUTSIDE_METHOD */ "Local or Arg used outside a control method"
+/* ASL_MSG_LOCAL_OUTSIDE_METHOD */ "Local or Arg used outside a control method",
+/* ASL_MSG_ALIGNMENT */ "Must be a multiple of alignment/granularity value",
+/* ASL_MSG_ISA_ADDRESS */ "Maximum 10-bit ISA address (0x3FF)",
+/* ASL_MSG_INVALID_MIN_MAX */ "Address Min is greater than Address Max",
+/* ASL_MSG_INVALID_LENGTH */ "Length is larger than Min/Max window",
+/* ASL_MSG_INVALID_LENGTH_FIXED */ "Length is not equal to fixed Min/Max window",
+/* ASL_MSG_INVALID_GRANULARITY */ "Granularity must be zero or a power of two minus one",
+/* ASL_MSG_INVALID_GRAN_FIXED */ "Granularity must be zero for fixed Min/Max",
+/* ASL_MSG_INVALID_ACCESS_SIZE */ "Invalid AccessSize (Maximum is 4 - QWord access)",
+/* ASL_MSG_INVALID_ADDR_FLAGS */ "Invalid combination of Length and Min/Max fixed flags"
};
diff --git a/sys/contrib/dev/acpica/debugger/dbcmds.c b/sys/contrib/dev/acpica/debugger/dbcmds.c
index 0c704e7..a5f5941 100644
--- a/sys/contrib/dev/acpica/debugger/dbcmds.c
+++ b/sys/contrib/dev/acpica/debugger/dbcmds.c
@@ -675,7 +675,7 @@ AcpiDbDisplayTableInfo (
/* Walk the entire root table list */
- for (i = 0; i < AcpiGbl_RootTableList.Count; i++)
+ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
{
TableDesc = &AcpiGbl_RootTableList.Tables[i];
AcpiOsPrintf ("%d ", i);
diff --git a/sys/contrib/dev/acpica/debugger/dbdisply.c b/sys/contrib/dev/acpica/debugger/dbdisply.c
index 4109489..9c85200 100644
--- a/sys/contrib/dev/acpica/debugger/dbdisply.c
+++ b/sys/contrib/dev/acpica/debugger/dbdisply.c
@@ -816,6 +816,7 @@ AcpiDbDisplayGpes (
ACPI_GPE_XRUPT_INFO *GpeXruptInfo;
ACPI_GPE_EVENT_INFO *GpeEventInfo;
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
+ char *GpeType;
UINT32 GpeIndex;
UINT32 Block = 0;
UINT32 i;
@@ -844,8 +845,17 @@ AcpiDbDisplayGpes (
AcpiOsPrintf ("Could not convert name to pathname\n");
}
- AcpiOsPrintf ("\nBlock %d - Info %p DeviceNode %p [%s]\n",
- Block, GpeBlock, GpeBlock->Node, Buffer);
+ if (GpeBlock->Node == AcpiGbl_FadtGpeDevice)
+ {
+ GpeType = "FADT-defined GPE block";
+ }
+ else
+ {
+ GpeType = "GPE Block Device";
+ }
+
+ AcpiOsPrintf ("\nBlock %d - Info %p DeviceNode %p [%s] - %s\n",
+ Block, GpeBlock, GpeBlock->Node, Buffer, GpeType);
AcpiOsPrintf (" Registers: %u (%u GPEs)\n",
GpeBlock->RegisterCount, GpeBlock->GpeCount);
diff --git a/sys/contrib/dev/acpica/events/evgpe.c b/sys/contrib/dev/acpica/events/evgpe.c
index 0ece12c..892b2c3 100644
--- a/sys/contrib/dev/acpica/events/evgpe.c
+++ b/sys/contrib/dev/acpica/events/evgpe.c
@@ -370,7 +370,7 @@ AcpiEvGetGpeEventInfo (
ACPI_FUNCTION_ENTRY ();
- /* A NULL GpeBlock means use the FADT-defined GPE block(s) */
+ /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
if (!GpeDevice)
{
diff --git a/sys/contrib/dev/acpica/events/evgpeblk.c b/sys/contrib/dev/acpica/events/evgpeblk.c
index 29b0e71..4c115fb 100644
--- a/sys/contrib/dev/acpica/events/evgpeblk.c
+++ b/sys/contrib/dev/acpica/events/evgpeblk.c
@@ -124,28 +124,6 @@
/* Local prototypes */
static ACPI_STATUS
-AcpiEvMatchGpeMethod (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *ObjDesc,
- void **ReturnValue);
-
-static ACPI_STATUS
-AcpiEvMatchPrwAndGpe (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Info,
- void **ReturnValue);
-
-static ACPI_GPE_XRUPT_INFO *
-AcpiEvGetGpeXruptBlock (
- UINT32 InterruptNumber);
-
-static ACPI_STATUS
-AcpiEvDeleteGpeXrupt (
- ACPI_GPE_XRUPT_INFO *GpeXrupt);
-
-static ACPI_STATUS
AcpiEvInstallGpeBlock (
ACPI_GPE_BLOCK_INFO *GpeBlock,
UINT32 InterruptNumber);
@@ -157,581 +135,6 @@ AcpiEvCreateGpeInfoBlocks (
/*******************************************************************************
*
- * FUNCTION: AcpiEvValidGpeEvent
- *
- * PARAMETERS: GpeEventInfo - Info for this GPE
- *
- * RETURN: TRUE if the GpeEvent is valid
- *
- * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
- * Should be called only when the GPE lists are semaphore locked
- * and not subject to change.
- *
- ******************************************************************************/
-
-BOOLEAN
-AcpiEvValidGpeEvent (
- ACPI_GPE_EVENT_INFO *GpeEventInfo)
-{
- ACPI_GPE_XRUPT_INFO *GpeXruptBlock;
- ACPI_GPE_BLOCK_INFO *GpeBlock;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- /* No need for spin lock since we are not changing any list elements */
-
- /* Walk the GPE interrupt levels */
-
- GpeXruptBlock = AcpiGbl_GpeXruptListHead;
- while (GpeXruptBlock)
- {
- GpeBlock = GpeXruptBlock->GpeBlockListHead;
-
- /* Walk the GPE blocks on this interrupt level */
-
- while (GpeBlock)
- {
- if ((&GpeBlock->EventInfo[0] <= GpeEventInfo) &&
- (&GpeBlock->EventInfo[GpeBlock->GpeCount] > GpeEventInfo))
- {
- return (TRUE);
- }
-
- GpeBlock = GpeBlock->Next;
- }
-
- GpeXruptBlock = GpeXruptBlock->Next;
- }
-
- return (FALSE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvWalkGpeList
- *
- * PARAMETERS: GpeWalkCallback - Routine called for each GPE block
- * Context - Value passed to callback
- *
- * RETURN: Status
- *
- * DESCRIPTION: Walk the GPE lists.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiEvWalkGpeList (
- ACPI_GPE_CALLBACK GpeWalkCallback,
- void *Context)
-{
- ACPI_GPE_BLOCK_INFO *GpeBlock;
- ACPI_GPE_XRUPT_INFO *GpeXruptInfo;
- ACPI_STATUS Status = AE_OK;
- ACPI_CPU_FLAGS Flags;
-
-
- ACPI_FUNCTION_TRACE (EvWalkGpeList);
-
-
- Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
-
- /* Walk the interrupt level descriptor list */
-
- GpeXruptInfo = AcpiGbl_GpeXruptListHead;
- while (GpeXruptInfo)
- {
- /* Walk all Gpe Blocks attached to this interrupt level */
-
- GpeBlock = GpeXruptInfo->GpeBlockListHead;
- while (GpeBlock)
- {
- /* One callback per GPE block */
-
- Status = GpeWalkCallback (GpeXruptInfo, GpeBlock, Context);
- if (ACPI_FAILURE (Status))
- {
- if (Status == AE_CTRL_END) /* Callback abort */
- {
- Status = AE_OK;
- }
- goto UnlockAndExit;
- }
-
- GpeBlock = GpeBlock->Next;
- }
-
- GpeXruptInfo = GpeXruptInfo->Next;
- }
-
-UnlockAndExit:
- AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
- return_ACPI_STATUS (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvDeleteGpeHandlers
- *
- * PARAMETERS: GpeXruptInfo - GPE Interrupt info
- * GpeBlock - Gpe Block info
- *
- * RETURN: Status
- *
- * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
- * Used only prior to termination.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiEvDeleteGpeHandlers (
- ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
- ACPI_GPE_BLOCK_INFO *GpeBlock,
- void *Context)
-{
- ACPI_GPE_EVENT_INFO *GpeEventInfo;
- UINT32 i;
- UINT32 j;
-
-
- ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers);
-
-
- /* Examine each GPE Register within the block */
-
- for (i = 0; i < GpeBlock->RegisterCount; i++)
- {
- /* Now look at the individual GPEs in this byte register */
-
- for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
- {
- GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
- ACPI_GPE_REGISTER_WIDTH) + j];
-
- if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
- ACPI_GPE_DISPATCH_HANDLER)
- {
- ACPI_FREE (GpeEventInfo->Dispatch.Handler);
- GpeEventInfo->Dispatch.Handler = NULL;
- GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
- }
- }
- }
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvMatchGpeMethod
- *
- * PARAMETERS: Callback from WalkNamespace
- *
- * RETURN: Status
- *
- * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
- * control method under the _GPE portion of the namespace.
- * Extract the name and GPE type from the object, saving this
- * information for quick lookup during GPE dispatch
- *
- * The name of each GPE control method is of the form:
- * "_Lxx" or "_Exx", where:
- * L - means that the GPE is level triggered
- * E - means that the GPE is edge triggered
- * xx - is the GPE number [in HEX]
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiEvMatchGpeMethod (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *ObjDesc,
- void **ReturnValue)
-{
- ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
- ACPI_GPE_BLOCK_INFO *GpeBlock = (void *) ObjDesc;
- ACPI_GPE_EVENT_INFO *GpeEventInfo;
- UINT32 GpeNumber;
- char Name[ACPI_NAME_SIZE + 1];
- UINT8 Type;
-
-
- ACPI_FUNCTION_TRACE (EvMatchGpeMethod);
-
-
- /*
- * Match and decode the _Lxx and _Exx GPE method names
- *
- * 1) Extract the method name and null terminate it
- */
- ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer);
- Name[ACPI_NAME_SIZE] = 0;
-
- /* 2) Name must begin with an underscore */
-
- if (Name[0] != '_')
- {
- return_ACPI_STATUS (AE_OK); /* Ignore this method */
- }
-
- /*
- * 3) Edge/Level determination is based on the 2nd character
- * of the method name
- *
- * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is
- * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set.
- */
- switch (Name[1])
- {
- case 'L':
- Type = ACPI_GPE_LEVEL_TRIGGERED;
- break;
-
- case 'E':
- Type = ACPI_GPE_EDGE_TRIGGERED;
- break;
-
- default:
- /* Unknown method type, just ignore it */
-
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
- "Ignoring unknown GPE method type: %s "
- "(name not of form _Lxx or _Exx)", Name));
- return_ACPI_STATUS (AE_OK);
- }
-
- /* 4) The last two characters of the name are the hex GPE Number */
-
- GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16);
- if (GpeNumber == ACPI_UINT32_MAX)
- {
- /* Conversion failed; invalid method, just ignore it */
-
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
- "Could not extract GPE number from name: %s "
- "(name is not of form _Lxx or _Exx)", Name));
- return_ACPI_STATUS (AE_OK);
- }
-
- /* Ensure that we have a valid GPE number for this GPE block */
-
- GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock);
- if (!GpeEventInfo)
- {
- /*
- * This GpeNumber is not valid for this GPE block, just ignore it.
- * However, it may be valid for a different GPE block, since GPE0
- * and GPE1 methods both appear under \_GPE.
- */
- return_ACPI_STATUS (AE_OK);
- }
-
- /*
- * Add the GPE information from above to the GpeEventInfo block for
- * use during dispatch of this GPE.
- */
- GpeEventInfo->Flags = (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD);
- GpeEventInfo->Dispatch.MethodNode = MethodNode;
-
- ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
- "Registered GPE method %s as GPE number 0x%.2X\n",
- Name, GpeNumber));
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvMatchPrwAndGpe
- *
- * PARAMETERS: Callback from WalkNamespace
- *
- * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is
- * not aborted on a single _PRW failure.
- *
- * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
- * Device. Run the _PRW method. If present, extract the GPE
- * number and mark the GPE as a CAN_WAKE GPE.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiEvMatchPrwAndGpe (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Info,
- void **ReturnValue)
-{
- ACPI_GPE_WALK_INFO *GpeInfo = (void *) Info;
- ACPI_NAMESPACE_NODE *GpeDevice;
- ACPI_GPE_BLOCK_INFO *GpeBlock;
- ACPI_NAMESPACE_NODE *TargetGpeDevice;
- ACPI_GPE_EVENT_INFO *GpeEventInfo;
- ACPI_OPERAND_OBJECT *PkgDesc;
- ACPI_OPERAND_OBJECT *ObjDesc;
- UINT32 GpeNumber;
- ACPI_STATUS Status;
-
-
- ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe);
-
-
- /* Check for a _PRW method under this device */
-
- Status = AcpiUtEvaluateObject (ObjHandle, METHOD_NAME__PRW,
- ACPI_BTYPE_PACKAGE, &PkgDesc);
- if (ACPI_FAILURE (Status))
- {
- /* Ignore all errors from _PRW, we don't want to abort the walk */
-
- return_ACPI_STATUS (AE_OK);
- }
-
- /* The returned _PRW package must have at least two elements */
-
- if (PkgDesc->Package.Count < 2)
- {
- goto Cleanup;
- }
-
- /* Extract pointers from the input context */
-
- GpeDevice = GpeInfo->GpeDevice;
- GpeBlock = GpeInfo->GpeBlock;
-
- /*
- * The _PRW object must return a package, we are only interested in the
- * first element
- */
- ObjDesc = PkgDesc->Package.Elements[0];
-
- if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
- {
- /* Use FADT-defined GPE device (from definition of _PRW) */
-
- TargetGpeDevice = AcpiGbl_FadtGpeDevice;
-
- /* Integer is the GPE number in the FADT described GPE blocks */
-
- GpeNumber = (UINT32) ObjDesc->Integer.Value;
- }
- else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
- {
- /* Package contains a GPE reference and GPE number within a GPE block */
-
- if ((ObjDesc->Package.Count < 2) ||
- ((ObjDesc->Package.Elements[0])->Common.Type !=
- ACPI_TYPE_LOCAL_REFERENCE) ||
- ((ObjDesc->Package.Elements[1])->Common.Type !=
- ACPI_TYPE_INTEGER))
- {
- goto Cleanup;
- }
-
- /* Get GPE block reference and decode */
-
- TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node;
- GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value;
- }
- else
- {
- /* Unknown type, just ignore it */
-
- goto Cleanup;
- }
-
- /*
- * Is this GPE within this block?
- *
- * TRUE if and only if these conditions are true:
- * 1) The GPE devices match.
- * 2) The GPE index(number) is within the range of the Gpe Block
- * associated with the GPE device.
- */
- if (GpeDevice != TargetGpeDevice)
- {
- goto Cleanup;
- }
-
- GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock);
- if (GpeEventInfo)
- {
- /* This GPE can wake the system */
-
- GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
- }
-
-Cleanup:
- AcpiUtRemoveReference (PkgDesc);
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvGetGpeXruptBlock
- *
- * PARAMETERS: InterruptNumber - Interrupt for a GPE block
- *
- * RETURN: A GPE interrupt block
- *
- * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
- * block per unique interrupt level used for GPEs. Should be
- * called only when the GPE lists are semaphore locked and not
- * subject to change.
- *
- ******************************************************************************/
-
-static ACPI_GPE_XRUPT_INFO *
-AcpiEvGetGpeXruptBlock (
- UINT32 InterruptNumber)
-{
- ACPI_GPE_XRUPT_INFO *NextGpeXrupt;
- ACPI_GPE_XRUPT_INFO *GpeXrupt;
- ACPI_STATUS Status;
- ACPI_CPU_FLAGS Flags;
-
-
- ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock);
-
-
- /* No need for lock since we are not changing any list elements here */
-
- NextGpeXrupt = AcpiGbl_GpeXruptListHead;
- while (NextGpeXrupt)
- {
- if (NextGpeXrupt->InterruptNumber == InterruptNumber)
- {
- return_PTR (NextGpeXrupt);
- }
-
- NextGpeXrupt = NextGpeXrupt->Next;
- }
-
- /* Not found, must allocate a new xrupt descriptor */
-
- GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO));
- if (!GpeXrupt)
- {
- return_PTR (NULL);
- }
-
- GpeXrupt->InterruptNumber = InterruptNumber;
-
- /* Install new interrupt descriptor with spin lock */
-
- Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
- if (AcpiGbl_GpeXruptListHead)
- {
- NextGpeXrupt = AcpiGbl_GpeXruptListHead;
- while (NextGpeXrupt->Next)
- {
- NextGpeXrupt = NextGpeXrupt->Next;
- }
-
- NextGpeXrupt->Next = GpeXrupt;
- GpeXrupt->Previous = NextGpeXrupt;
- }
- else
- {
- AcpiGbl_GpeXruptListHead = GpeXrupt;
- }
- AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
-
- /* Install new interrupt handler if not SCI_INT */
-
- if (InterruptNumber != AcpiGbl_FADT.SciInterrupt)
- {
- Status = AcpiOsInstallInterruptHandler (InterruptNumber,
- AcpiEvGpeXruptHandler, GpeXrupt);
- if (ACPI_FAILURE (Status))
- {
- ACPI_ERROR ((AE_INFO,
- "Could not install GPE interrupt handler at level 0x%X",
- InterruptNumber));
- return_PTR (NULL);
- }
- }
-
- return_PTR (GpeXrupt);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvDeleteGpeXrupt
- *
- * PARAMETERS: GpeXrupt - A GPE interrupt info block
- *
- * RETURN: Status
- *
- * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated
- * interrupt handler if not the SCI interrupt.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiEvDeleteGpeXrupt (
- ACPI_GPE_XRUPT_INFO *GpeXrupt)
-{
- ACPI_STATUS Status;
- ACPI_CPU_FLAGS Flags;
-
-
- ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt);
-
-
- /* We never want to remove the SCI interrupt handler */
-
- if (GpeXrupt->InterruptNumber == AcpiGbl_FADT.SciInterrupt)
- {
- GpeXrupt->GpeBlockListHead = NULL;
- return_ACPI_STATUS (AE_OK);
- }
-
- /* Disable this interrupt */
-
- Status = AcpiOsRemoveInterruptHandler (
- GpeXrupt->InterruptNumber, AcpiEvGpeXruptHandler);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- /* Unlink the interrupt block with lock */
-
- Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
- if (GpeXrupt->Previous)
- {
- GpeXrupt->Previous->Next = GpeXrupt->Next;
- }
- else
- {
- /* No previous, update list head */
-
- AcpiGbl_GpeXruptListHead = GpeXrupt->Next;
- }
-
- if (GpeXrupt->Next)
- {
- GpeXrupt->Next->Previous = GpeXrupt->Previous;
- }
- AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
-
- /* Free the block */
-
- ACPI_FREE (GpeXrupt);
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiEvInstallGpeBlock
*
* PARAMETERS: GpeBlock - New GPE block
@@ -1041,6 +444,7 @@ AcpiEvCreateGpeBlock (
{
ACPI_STATUS Status;
ACPI_GPE_BLOCK_INFO *GpeBlock;
+ ACPI_GPE_WALK_INFO WalkInfo;
ACPI_FUNCTION_TRACE (EvCreateGpeBlock);
@@ -1089,11 +493,16 @@ AcpiEvCreateGpeBlock (
return_ACPI_STATUS (Status);
}
- /* Find all GPE methods (_Lxx, _Exx) for this block */
+ /* Find all GPE methods (_Lxx or_Exx) for this block */
+
+ WalkInfo.GpeBlock = GpeBlock;
+ WalkInfo.GpeDevice = GpeDevice;
+ WalkInfo.EnableThisGpe = FALSE;
+ WalkInfo.ExecuteByOwnerId = FALSE;
Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice,
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
- AcpiEvMatchGpeMethod, NULL, GpeBlock, NULL);
+ AcpiEvMatchGpeMethod, NULL, &WalkInfo, NULL);
/* Return the new block */
@@ -1139,7 +548,7 @@ AcpiEvInitializeGpeBlock (
{
ACPI_STATUS Status;
ACPI_GPE_EVENT_INFO *GpeEventInfo;
- ACPI_GPE_WALK_INFO GpeInfo;
+ ACPI_GPE_WALK_INFO WalkInfo;
UINT32 WakeGpeCount;
UINT32 GpeEnabledCount;
UINT32 GpeIndex;
@@ -1170,12 +579,13 @@ AcpiEvInitializeGpeBlock (
* definition a wake GPE and will not be enabled while the machine
* is running.
*/
- GpeInfo.GpeBlock = GpeBlock;
- GpeInfo.GpeDevice = GpeDevice;
+ WalkInfo.GpeBlock = GpeBlock;
+ WalkInfo.GpeDevice = GpeDevice;
+ WalkInfo.ExecuteByOwnerId = FALSE;
Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
- AcpiEvMatchPrwAndGpe, NULL, &GpeInfo, NULL);
+ AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL);
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status, "While executing _PRW methods"));
@@ -1238,165 +648,13 @@ AcpiEvInitializeGpeBlock (
}
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
- WakeGpeCount, GpeEnabledCount));
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvGpeInitialize
- *
- * PARAMETERS: None
- *
- * RETURN: Status
- *
- * DESCRIPTION: Initialize the GPE data structures
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiEvGpeInitialize (
- void)
-{
- UINT32 RegisterCount0 = 0;
- UINT32 RegisterCount1 = 0;
- UINT32 GpeNumberMax = 0;
- ACPI_STATUS Status;
-
-
- ACPI_FUNCTION_TRACE (EvGpeInitialize);
-
-
- Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- /*
- * Initialize the GPE Block(s) defined in the FADT
- *
- * Why the GPE register block lengths are divided by 2: From the ACPI
- * Spec, section "General-Purpose Event Registers", we have:
- *
- * "Each register block contains two registers of equal length
- * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
- * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
- * The length of the GPE1_STS and GPE1_EN registers is equal to
- * half the GPE1_LEN. If a generic register block is not supported
- * then its respective block pointer and block length values in the
- * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
- * to be the same size."
- */
-
- /*
- * Determine the maximum GPE number for this machine.
- *
- * Note: both GPE0 and GPE1 are optional, and either can exist without
- * the other.
- *
- * If EITHER the register length OR the block address are zero, then that
- * particular block is not supported.
- */
- if (AcpiGbl_FADT.Gpe0BlockLength &&
- AcpiGbl_FADT.XGpe0Block.Address)
- {
- /* GPE block 0 exists (has both length and address > 0) */
-
- RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2);
-
- GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1;
-
- /* Install GPE Block 0 */
-
- Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
- &AcpiGbl_FADT.XGpe0Block, RegisterCount0, 0,
- AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]);
-
- if (ACPI_FAILURE (Status))
- {
- ACPI_EXCEPTION ((AE_INFO, Status,
- "Could not create GPE Block 0"));
- }
- }
-
- if (AcpiGbl_FADT.Gpe1BlockLength &&
- AcpiGbl_FADT.XGpe1Block.Address)
- {
- /* GPE block 1 exists (has both length and address > 0) */
-
- RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2);
-
- /* Check for GPE0/GPE1 overlap (if both banks exist) */
-
- if ((RegisterCount0) &&
- (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base))
- {
- ACPI_ERROR ((AE_INFO,
- "GPE0 block (GPE 0 to %u) overlaps the GPE1 block "
- "(GPE %u to %u) - Ignoring GPE1",
- GpeNumberMax, AcpiGbl_FADT.Gpe1Base,
- AcpiGbl_FADT.Gpe1Base +
- ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
-
- /* Ignore GPE1 block by setting the register count to zero */
-
- RegisterCount1 = 0;
- }
- else
- {
- /* Install GPE Block 1 */
-
- Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
- &AcpiGbl_FADT.XGpe1Block, RegisterCount1,
- AcpiGbl_FADT.Gpe1Base,
- AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]);
-
- if (ACPI_FAILURE (Status))
- {
- ACPI_EXCEPTION ((AE_INFO, Status,
- "Could not create GPE Block 1"));
- }
-
- /*
- * GPE0 and GPE1 do not have to be contiguous in the GPE number
- * space. However, GPE0 always starts at GPE number zero.
- */
- GpeNumberMax = AcpiGbl_FADT.Gpe1Base +
- ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1);
- }
- }
-
- /* Exit if there are no GPE registers */
-
- if ((RegisterCount0 + RegisterCount1) == 0)
+ if (GpeEnabledCount || WakeGpeCount)
{
- /* GPEs are not required by ACPI, this is OK */
-
ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "There are no GPE blocks defined in the FADT\n"));
- Status = AE_OK;
- goto Cleanup;
+ "Enabled %u Runtime GPEs, added %u Wake GPEs in this block\n",
+ GpeEnabledCount, WakeGpeCount));
}
- /* Check for Max GPE number out-of-range */
-
- if (GpeNumberMax > ACPI_GPE_MAX)
- {
- ACPI_ERROR ((AE_INFO,
- "Maximum GPE number from FADT is too large: 0x%X",
- GpeNumberMax));
- Status = AE_BAD_VALUE;
- goto Cleanup;
- }
-
-Cleanup:
- (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
return_ACPI_STATUS (AE_OK);
}
-
diff --git a/sys/contrib/dev/acpica/events/evgpeinit.c b/sys/contrib/dev/acpica/events/evgpeinit.c
new file mode 100644
index 0000000..7f41eb7
--- /dev/null
+++ b/sys/contrib/dev/acpica/events/evgpeinit.c
@@ -0,0 +1,763 @@
+/******************************************************************************
+ *
+ * Module Name: evgpeinit - System GPE initialization and update
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * 1. Copyright Notice
+ *
+ * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * 2. License
+ *
+ * 2.1. This is your license from Intel Corp. under its intellectual property
+ * rights. You may have additional license terms from the party that provided
+ * you this software, covering your right to use that party's intellectual
+ * property rights.
+ *
+ * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
+ * copy of the source code appearing in this file ("Covered Code") an
+ * irrevocable, perpetual, worldwide license under Intel's copyrights in the
+ * base code distributed originally by Intel ("Original Intel Code") to copy,
+ * make derivatives, distribute, use and display any portion of the Covered
+ * Code in any form, with the right to sublicense such rights; and
+ *
+ * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
+ * license (with the right to sublicense), under only those claims of Intel
+ * patents that are infringed by the Original Intel Code, to make, use, sell,
+ * offer to sell, and import the Covered Code and derivative works thereof
+ * solely to the minimum extent necessary to exercise the above copyright
+ * license, and in no event shall the patent license extend to any additions
+ * to or modifications of the Original Intel Code. No other license or right
+ * is granted directly or by implication, estoppel or otherwise;
+ *
+ * The above copyright and patent license is granted only if the following
+ * conditions are met:
+ *
+ * 3. Conditions
+ *
+ * 3.1. Redistribution of Source with Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification with rights to further distribute source must include
+ * the above Copyright Notice, the above License, this list of Conditions,
+ * and the following Disclaimer and Export Compliance provision. In addition,
+ * Licensee must cause all Covered Code to which Licensee contributes to
+ * contain a file documenting the changes Licensee made to create that Covered
+ * Code and the date of any change. Licensee must include in that file the
+ * documentation of any changes made by any predecessor Licensee. Licensee
+ * must include a prominent statement that the modification is derived,
+ * directly or indirectly, from Original Intel Code.
+ *
+ * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification without rights to further distribute source must
+ * include the following Disclaimer and Export Compliance provision in the
+ * documentation and/or other materials provided with distribution. In
+ * addition, Licensee may not authorize further sublicense of source of any
+ * portion of the Covered Code, and must include terms to the effect that the
+ * license from Licensee to its licensee is limited to the intellectual
+ * property embodied in the software Licensee provides to its licensee, and
+ * not to intellectual property embodied in modifications its licensee may
+ * make.
+ *
+ * 3.3. Redistribution of Executable. Redistribution in executable form of any
+ * substantial portion of the Covered Code or modification must reproduce the
+ * above Copyright Notice, and the following Disclaimer and Export Compliance
+ * provision in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3.4. Intel retains all right, title, and interest in and to the Original
+ * Intel Code.
+ *
+ * 3.5. Neither the name Intel nor any other trademark owned or controlled by
+ * Intel shall be used in advertising or otherwise to promote the sale, use or
+ * other dealings in products derived from or relating to the Covered Code
+ * without prior written authorization from Intel.
+ *
+ * 4. Disclaimer and Export Compliance
+ *
+ * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
+ * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
+ * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
+ * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
+ * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
+ * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
+ * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
+ * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
+ * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
+ * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
+ * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
+ * LIMITED REMEDY.
+ *
+ * 4.3. Licensee shall not export, either directly or indirectly, any of this
+ * software or system incorporating such software without first obtaining any
+ * required license or other approval from the U. S. Department of Commerce or
+ * any other agency or department of the United States Government. In the
+ * event Licensee exports any such software from the United States or
+ * re-exports any such software from a foreign destination, Licensee shall
+ * ensure that the distribution and export/re-export of the software is in
+ * compliance with all laws, regulations, orders, or other restrictions of the
+ * U.S. Export Administration Regulations. Licensee agrees that neither it nor
+ * any of its subsidiaries will export/re-export any technical data, process,
+ * software, or service, directly or indirectly, to any country for which the
+ * United States government or any agency thereof requires an export license,
+ * other governmental approval, or letter of assurance, without first obtaining
+ * such license, approval or letter.
+ *
+ *****************************************************************************/
+
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acevents.h>
+#include <contrib/dev/acpica/include/acnamesp.h>
+#include <contrib/dev/acpica/include/acinterp.h>
+
+#define _COMPONENT ACPI_EVENTS
+ ACPI_MODULE_NAME ("evgpeinit")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvGpeInitialize
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Initialize the GPE data structures and the FADT GPE 0/1 blocks
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvGpeInitialize (
+ void)
+{
+ UINT32 RegisterCount0 = 0;
+ UINT32 RegisterCount1 = 0;
+ UINT32 GpeNumberMax = 0;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (EvGpeInitialize);
+
+
+ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /*
+ * Initialize the GPE Block(s) defined in the FADT
+ *
+ * Why the GPE register block lengths are divided by 2: From the ACPI
+ * Spec, section "General-Purpose Event Registers", we have:
+ *
+ * "Each register block contains two registers of equal length
+ * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
+ * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
+ * The length of the GPE1_STS and GPE1_EN registers is equal to
+ * half the GPE1_LEN. If a generic register block is not supported
+ * then its respective block pointer and block length values in the
+ * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
+ * to be the same size."
+ */
+
+ /*
+ * Determine the maximum GPE number for this machine.
+ *
+ * Note: both GPE0 and GPE1 are optional, and either can exist without
+ * the other.
+ *
+ * If EITHER the register length OR the block address are zero, then that
+ * particular block is not supported.
+ */
+ if (AcpiGbl_FADT.Gpe0BlockLength &&
+ AcpiGbl_FADT.XGpe0Block.Address)
+ {
+ /* GPE block 0 exists (has both length and address > 0) */
+
+ RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2);
+
+ GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1;
+
+ /* Install GPE Block 0 */
+
+ Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
+ &AcpiGbl_FADT.XGpe0Block, RegisterCount0, 0,
+ AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]);
+
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status,
+ "Could not create GPE Block 0"));
+ }
+ }
+
+ if (AcpiGbl_FADT.Gpe1BlockLength &&
+ AcpiGbl_FADT.XGpe1Block.Address)
+ {
+ /* GPE block 1 exists (has both length and address > 0) */
+
+ RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2);
+
+ /* Check for GPE0/GPE1 overlap (if both banks exist) */
+
+ if ((RegisterCount0) &&
+ (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base))
+ {
+ ACPI_ERROR ((AE_INFO,
+ "GPE0 block (GPE 0 to %u) overlaps the GPE1 block "
+ "(GPE %u to %u) - Ignoring GPE1",
+ GpeNumberMax, AcpiGbl_FADT.Gpe1Base,
+ AcpiGbl_FADT.Gpe1Base +
+ ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1)));
+
+ /* Ignore GPE1 block by setting the register count to zero */
+
+ RegisterCount1 = 0;
+ }
+ else
+ {
+ /* Install GPE Block 1 */
+
+ Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice,
+ &AcpiGbl_FADT.XGpe1Block, RegisterCount1,
+ AcpiGbl_FADT.Gpe1Base,
+ AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]);
+
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status,
+ "Could not create GPE Block 1"));
+ }
+
+ /*
+ * GPE0 and GPE1 do not have to be contiguous in the GPE number
+ * space. However, GPE0 always starts at GPE number zero.
+ */
+ GpeNumberMax = AcpiGbl_FADT.Gpe1Base +
+ ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1);
+ }
+ }
+
+ /* Exit if there are no GPE registers */
+
+ if ((RegisterCount0 + RegisterCount1) == 0)
+ {
+ /* GPEs are not required by ACPI, this is OK */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+ "There are no GPE blocks defined in the FADT\n"));
+ Status = AE_OK;
+ goto Cleanup;
+ }
+
+ /* Check for Max GPE number out-of-range */
+
+ if (GpeNumberMax > ACPI_GPE_MAX)
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Maximum GPE number from FADT is too large: 0x%X",
+ GpeNumberMax));
+ Status = AE_BAD_VALUE;
+ goto Cleanup;
+ }
+
+Cleanup:
+ (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvUpdateGpes
+ *
+ * PARAMETERS: TableOwnerId - ID of the newly-loaded ACPI table
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
+ * result of a Load() or LoadTable() operation. If new GPE
+ * methods have been installed, register the new methods and
+ * enable and runtime GPEs that are associated with them. Also,
+ * run any newly loaded _PRW methods in order to discover any
+ * new CAN_WAKE GPEs.
+ *
+ ******************************************************************************/
+
+void
+AcpiEvUpdateGpes (
+ ACPI_OWNER_ID TableOwnerId)
+{
+ ACPI_GPE_XRUPT_INFO *GpeXruptInfo;
+ ACPI_GPE_BLOCK_INFO *GpeBlock;
+ ACPI_GPE_WALK_INFO WalkInfo;
+ ACPI_STATUS Status = AE_OK;
+ UINT32 NewWakeGpeCount = 0;
+
+
+ /* We will examine only _PRW/_Lxx/_Exx methods owned by this table */
+
+ WalkInfo.OwnerId = TableOwnerId;
+ WalkInfo.ExecuteByOwnerId = TRUE;
+ WalkInfo.Count = 0;
+
+ if (AcpiGbl_LeaveWakeGpesDisabled)
+ {
+ /*
+ * 1) Run any newly-loaded _PRW methods to find any GPEs that
+ * can now be marked as CAN_WAKE GPEs. Note: We must run the
+ * _PRW methods before we process the _Lxx/_Exx methods because
+ * we will enable all runtime GPEs associated with the new
+ * _Lxx/_Exx methods at the time we process those methods.
+ *
+ * Unlock interpreter so that we can run the _PRW methods.
+ */
+ WalkInfo.GpeBlock = NULL;
+ WalkInfo.GpeDevice = NULL;
+
+ AcpiExExitInterpreter ();
+
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
+ AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status,
+ "While executing _PRW methods"));
+ }
+
+ AcpiExEnterInterpreter ();
+ NewWakeGpeCount = WalkInfo.Count;
+ }
+
+ /*
+ * 2) Find any _Lxx/_Exx GPE methods that have just been loaded.
+ *
+ * Any GPEs that correspond to new _Lxx/_Exx methods and are not
+ * marked as CAN_WAKE are immediately enabled.
+ *
+ * Examine the namespace underneath each GpeDevice within the
+ * GpeBlock lists.
+ */
+ Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE (Status))
+ {
+ return;
+ }
+
+ WalkInfo.Count = 0;
+ WalkInfo.EnableThisGpe = TRUE;
+
+ /* Walk the interrupt level descriptor list */
+
+ GpeXruptInfo = AcpiGbl_GpeXruptListHead;
+ while (GpeXruptInfo)
+ {
+ /* Walk all Gpe Blocks attached to this interrupt level */
+
+ GpeBlock = GpeXruptInfo->GpeBlockListHead;
+ while (GpeBlock)
+ {
+ WalkInfo.GpeBlock = GpeBlock;
+ WalkInfo.GpeDevice = GpeBlock->Node;
+
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD,
+ WalkInfo.GpeDevice, ACPI_UINT32_MAX,
+ ACPI_NS_WALK_NO_UNLOCK, AcpiEvMatchGpeMethod,
+ NULL, &WalkInfo, NULL);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status,
+ "While decoding _Lxx/_Exx methods"));
+ }
+
+ GpeBlock = GpeBlock->Next;
+ }
+
+ GpeXruptInfo = GpeXruptInfo->Next;
+ }
+
+ if (WalkInfo.Count || NewWakeGpeCount)
+ {
+ ACPI_INFO ((AE_INFO,
+ "Enabled %u new runtime GPEs, added %u new wakeup GPEs",
+ WalkInfo.Count, NewWakeGpeCount));
+ }
+
+ (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
+ return;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvMatchGpeMethod
+ *
+ * PARAMETERS: Callback from WalkNamespace
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
+ * control method under the _GPE portion of the namespace.
+ * Extract the name and GPE type from the object, saving this
+ * information for quick lookup during GPE dispatch. Allows a
+ * per-OwnerId evaluation if ExecuteByOwnerId is TRUE in the
+ * WalkInfo parameter block.
+ *
+ * The name of each GPE control method is of the form:
+ * "_Lxx" or "_Exx", where:
+ * L - means that the GPE is level triggered
+ * E - means that the GPE is edge triggered
+ * xx - is the GPE number [in HEX]
+ *
+ * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods
+ * with that owner.
+ * If WalkInfo->EnableThisGpe is TRUE, the GPE that is referred to by a GPE
+ * method is immediately enabled (Used for Load/LoadTable operators)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvMatchGpeMethod (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue)
+{
+ ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
+ ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context);
+ ACPI_GPE_EVENT_INFO *GpeEventInfo;
+ ACPI_NAMESPACE_NODE *GpeDevice;
+ ACPI_STATUS Status;
+ UINT32 GpeNumber;
+ char Name[ACPI_NAME_SIZE + 1];
+ UINT8 Type;
+
+
+ ACPI_FUNCTION_TRACE (EvMatchGpeMethod);
+
+
+ /* Check if requested OwnerId matches this OwnerId */
+
+ if ((WalkInfo->ExecuteByOwnerId) &&
+ (MethodNode->OwnerId != WalkInfo->OwnerId))
+ {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /*
+ * Match and decode the _Lxx and _Exx GPE method names
+ *
+ * 1) Extract the method name and null terminate it
+ */
+ ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer);
+ Name[ACPI_NAME_SIZE] = 0;
+
+ /* 2) Name must begin with an underscore */
+
+ if (Name[0] != '_')
+ {
+ return_ACPI_STATUS (AE_OK); /* Ignore this method */
+ }
+
+ /*
+ * 3) Edge/Level determination is based on the 2nd character
+ * of the method name
+ *
+ * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is
+ * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set.
+ */
+ switch (Name[1])
+ {
+ case 'L':
+ Type = ACPI_GPE_LEVEL_TRIGGERED;
+ break;
+
+ case 'E':
+ Type = ACPI_GPE_EDGE_TRIGGERED;
+ break;
+
+ default:
+ /* Unknown method type, just ignore it */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
+ "Ignoring unknown GPE method type: %s "
+ "(name not of form _Lxx or _Exx)", Name));
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* 4) The last two characters of the name are the hex GPE Number */
+
+ GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16);
+ if (GpeNumber == ACPI_UINT32_MAX)
+ {
+ /* Conversion failed; invalid method, just ignore it */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
+ "Could not extract GPE number from name: %s "
+ "(name is not of form _Lxx or _Exx)", Name));
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Ensure that we have a valid GPE number for this GPE block */
+
+ GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, WalkInfo->GpeBlock);
+ if (!GpeEventInfo)
+ {
+ /*
+ * This GpeNumber is not valid for this GPE block, just ignore it.
+ * However, it may be valid for a different GPE block, since GPE0
+ * and GPE1 methods both appear under \_GPE.
+ */
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
+ ACPI_GPE_DISPATCH_HANDLER)
+ {
+ /* If there is already a handler, ignore this GPE method */
+
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
+ ACPI_GPE_DISPATCH_METHOD)
+ {
+ /*
+ * If there is already a method, ignore this method. But check
+ * for a type mismatch (if both the _Lxx AND _Exx exist)
+ */
+ if (Type != (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
+ {
+ ACPI_ERROR ((AE_INFO,
+ "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods",
+ GpeNumber, GpeNumber, GpeNumber));
+ }
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /*
+ * Add the GPE information from above to the GpeEventInfo block for
+ * use during dispatch of this GPE.
+ */
+ GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD);
+ GpeEventInfo->Dispatch.MethodNode = MethodNode;
+
+ /*
+ * Enable this GPE if requested. This only happens when during the
+ * execution of a Load or LoadTable operator. We have found a new
+ * GPE method and want to immediately enable the GPE if it is a
+ * runtime GPE.
+ */
+ if (WalkInfo->EnableThisGpe)
+ {
+ /* Ignore GPEs that can wake the system */
+
+ if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) ||
+ !AcpiGbl_LeaveWakeGpesDisabled)
+ {
+ WalkInfo->Count++;
+ GpeDevice = WalkInfo->GpeDevice;
+
+ if (GpeDevice == AcpiGbl_FadtGpeDevice)
+ {
+ GpeDevice = NULL;
+ }
+
+ Status = AcpiEnableGpe (GpeDevice, GpeNumber,
+ ACPI_GPE_TYPE_RUNTIME);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status,
+ "Could not enable GPE 0x%02X", GpeNumber));
+ }
+ }
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
+ "Registered GPE method %s as GPE number 0x%.2X\n",
+ Name, GpeNumber));
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvMatchPrwAndGpe
+ *
+ * PARAMETERS: Callback from WalkNamespace
+ *
+ * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is
+ * not aborted on a single _PRW failure.
+ *
+ * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a
+ * Device. Run the _PRW method. If present, extract the GPE
+ * number and mark the GPE as a CAN_WAKE GPE. Allows a
+ * per-OwnerId execution if ExecuteByOwnerId is TRUE in the
+ * WalkInfo parameter block.
+ *
+ * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute _PRWs with that
+ * owner.
+ * If WalkInfo->GpeDevice is NULL, we execute every _PRW found. Otherwise,
+ * we only execute _PRWs that refer to the input GpeDevice.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvMatchPrwAndGpe (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue)
+{
+ ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context);
+ ACPI_NAMESPACE_NODE *GpeDevice;
+ ACPI_GPE_BLOCK_INFO *GpeBlock;
+ ACPI_NAMESPACE_NODE *TargetGpeDevice;
+ ACPI_NAMESPACE_NODE *PrwNode;
+ ACPI_GPE_EVENT_INFO *GpeEventInfo;
+ ACPI_OPERAND_OBJECT *PkgDesc;
+ ACPI_OPERAND_OBJECT *ObjDesc;
+ UINT32 GpeNumber;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe);
+
+
+ /* Check for a _PRW method under this device */
+
+ Status = AcpiNsGetNode (ObjHandle, METHOD_NAME__PRW,
+ ACPI_NS_NO_UPSEARCH, &PrwNode);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Check if requested OwnerId matches this OwnerId */
+
+ if ((WalkInfo->ExecuteByOwnerId) &&
+ (PrwNode->OwnerId != WalkInfo->OwnerId))
+ {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Execute the _PRW */
+
+ Status = AcpiUtEvaluateObject (PrwNode, NULL,
+ ACPI_BTYPE_PACKAGE, &PkgDesc);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* The returned _PRW package must have at least two elements */
+
+ if (PkgDesc->Package.Count < 2)
+ {
+ goto Cleanup;
+ }
+
+ /* Extract pointers from the input context */
+
+ GpeDevice = WalkInfo->GpeDevice;
+ GpeBlock = WalkInfo->GpeBlock;
+
+ /*
+ * The _PRW object must return a package, we are only interested
+ * in the first element
+ */
+ ObjDesc = PkgDesc->Package.Elements[0];
+
+ if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
+ {
+ /* Use FADT-defined GPE device (from definition of _PRW) */
+
+ TargetGpeDevice = NULL;
+ if (GpeDevice)
+ {
+ TargetGpeDevice = AcpiGbl_FadtGpeDevice;
+ }
+
+ /* Integer is the GPE number in the FADT described GPE blocks */
+
+ GpeNumber = (UINT32) ObjDesc->Integer.Value;
+ }
+ else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
+ {
+ /* Package contains a GPE reference and GPE number within a GPE block */
+
+ if ((ObjDesc->Package.Count < 2) ||
+ ((ObjDesc->Package.Elements[0])->Common.Type !=
+ ACPI_TYPE_LOCAL_REFERENCE) ||
+ ((ObjDesc->Package.Elements[1])->Common.Type !=
+ ACPI_TYPE_INTEGER))
+ {
+ goto Cleanup;
+ }
+
+ /* Get GPE block reference and decode */
+
+ TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node;
+ GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value;
+ }
+ else
+ {
+ /* Unknown type, just ignore it */
+
+ goto Cleanup;
+ }
+
+ /* Get the GpeEventInfo for this GPE */
+
+ if (GpeDevice)
+ {
+ /*
+ * Is this GPE within this block?
+ *
+ * TRUE if and only if these conditions are true:
+ * 1) The GPE devices match.
+ * 2) The GPE index(number) is within the range of the Gpe Block
+ * associated with the GPE device.
+ */
+ if (GpeDevice != TargetGpeDevice)
+ {
+ goto Cleanup;
+ }
+
+ GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock);
+ }
+ else
+ {
+ /* GpeDevice is NULL, just match the TargetDevice and GpeNumber */
+
+ GpeEventInfo = AcpiEvGetGpeEventInfo (TargetGpeDevice, GpeNumber);
+ }
+
+ if (GpeEventInfo)
+ {
+ if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
+ {
+ /* This GPE can wake the system */
+
+ GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
+ WalkInfo->Count++;
+ }
+ }
+
+Cleanup:
+ AcpiUtRemoveReference (PkgDesc);
+ return_ACPI_STATUS (AE_OK);
+}
+
diff --git a/sys/contrib/dev/acpica/events/evgpeutil.c b/sys/contrib/dev/acpica/events/evgpeutil.c
new file mode 100644
index 0000000..d67f77e
--- /dev/null
+++ b/sys/contrib/dev/acpica/events/evgpeutil.c
@@ -0,0 +1,452 @@
+/******************************************************************************
+ *
+ * Module Name: evgpeutil - GPE utilities
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ *
+ * 1. Copyright Notice
+ *
+ * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * 2. License
+ *
+ * 2.1. This is your license from Intel Corp. under its intellectual property
+ * rights. You may have additional license terms from the party that provided
+ * you this software, covering your right to use that party's intellectual
+ * property rights.
+ *
+ * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
+ * copy of the source code appearing in this file ("Covered Code") an
+ * irrevocable, perpetual, worldwide license under Intel's copyrights in the
+ * base code distributed originally by Intel ("Original Intel Code") to copy,
+ * make derivatives, distribute, use and display any portion of the Covered
+ * Code in any form, with the right to sublicense such rights; and
+ *
+ * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
+ * license (with the right to sublicense), under only those claims of Intel
+ * patents that are infringed by the Original Intel Code, to make, use, sell,
+ * offer to sell, and import the Covered Code and derivative works thereof
+ * solely to the minimum extent necessary to exercise the above copyright
+ * license, and in no event shall the patent license extend to any additions
+ * to or modifications of the Original Intel Code. No other license or right
+ * is granted directly or by implication, estoppel or otherwise;
+ *
+ * The above copyright and patent license is granted only if the following
+ * conditions are met:
+ *
+ * 3. Conditions
+ *
+ * 3.1. Redistribution of Source with Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification with rights to further distribute source must include
+ * the above Copyright Notice, the above License, this list of Conditions,
+ * and the following Disclaimer and Export Compliance provision. In addition,
+ * Licensee must cause all Covered Code to which Licensee contributes to
+ * contain a file documenting the changes Licensee made to create that Covered
+ * Code and the date of any change. Licensee must include in that file the
+ * documentation of any changes made by any predecessor Licensee. Licensee
+ * must include a prominent statement that the modification is derived,
+ * directly or indirectly, from Original Intel Code.
+ *
+ * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
+ * Redistribution of source code of any substantial portion of the Covered
+ * Code or modification without rights to further distribute source must
+ * include the following Disclaimer and Export Compliance provision in the
+ * documentation and/or other materials provided with distribution. In
+ * addition, Licensee may not authorize further sublicense of source of any
+ * portion of the Covered Code, and must include terms to the effect that the
+ * license from Licensee to its licensee is limited to the intellectual
+ * property embodied in the software Licensee provides to its licensee, and
+ * not to intellectual property embodied in modifications its licensee may
+ * make.
+ *
+ * 3.3. Redistribution of Executable. Redistribution in executable form of any
+ * substantial portion of the Covered Code or modification must reproduce the
+ * above Copyright Notice, and the following Disclaimer and Export Compliance
+ * provision in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3.4. Intel retains all right, title, and interest in and to the Original
+ * Intel Code.
+ *
+ * 3.5. Neither the name Intel nor any other trademark owned or controlled by
+ * Intel shall be used in advertising or otherwise to promote the sale, use or
+ * other dealings in products derived from or relating to the Covered Code
+ * without prior written authorization from Intel.
+ *
+ * 4. Disclaimer and Export Compliance
+ *
+ * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
+ * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
+ * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
+ * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
+ * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ *
+ * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
+ * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
+ * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
+ * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
+ * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
+ * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
+ * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
+ * LIMITED REMEDY.
+ *
+ * 4.3. Licensee shall not export, either directly or indirectly, any of this
+ * software or system incorporating such software without first obtaining any
+ * required license or other approval from the U. S. Department of Commerce or
+ * any other agency or department of the United States Government. In the
+ * event Licensee exports any such software from the United States or
+ * re-exports any such software from a foreign destination, Licensee shall
+ * ensure that the distribution and export/re-export of the software is in
+ * compliance with all laws, regulations, orders, or other restrictions of the
+ * U.S. Export Administration Regulations. Licensee agrees that neither it nor
+ * any of its subsidiaries will export/re-export any technical data, process,
+ * software, or service, directly or indirectly, to any country for which the
+ * United States government or any agency thereof requires an export license,
+ * other governmental approval, or letter of assurance, without first obtaining
+ * such license, approval or letter.
+ *
+ *****************************************************************************/
+
+
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acevents.h>
+
+#define _COMPONENT ACPI_EVENTS
+ ACPI_MODULE_NAME ("evgpeutil")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvWalkGpeList
+ *
+ * PARAMETERS: GpeWalkCallback - Routine called for each GPE block
+ * Context - Value passed to callback
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Walk the GPE lists.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvWalkGpeList (
+ ACPI_GPE_CALLBACK GpeWalkCallback,
+ void *Context)
+{
+ ACPI_GPE_BLOCK_INFO *GpeBlock;
+ ACPI_GPE_XRUPT_INFO *GpeXruptInfo;
+ ACPI_STATUS Status = AE_OK;
+ ACPI_CPU_FLAGS Flags;
+
+
+ ACPI_FUNCTION_TRACE (EvWalkGpeList);
+
+
+ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
+
+ /* Walk the interrupt level descriptor list */
+
+ GpeXruptInfo = AcpiGbl_GpeXruptListHead;
+ while (GpeXruptInfo)
+ {
+ /* Walk all Gpe Blocks attached to this interrupt level */
+
+ GpeBlock = GpeXruptInfo->GpeBlockListHead;
+ while (GpeBlock)
+ {
+ /* One callback per GPE block */
+
+ Status = GpeWalkCallback (GpeXruptInfo, GpeBlock, Context);
+ if (ACPI_FAILURE (Status))
+ {
+ if (Status == AE_CTRL_END) /* Callback abort */
+ {
+ Status = AE_OK;
+ }
+ goto UnlockAndExit;
+ }
+
+ GpeBlock = GpeBlock->Next;
+ }
+
+ GpeXruptInfo = GpeXruptInfo->Next;
+ }
+
+UnlockAndExit:
+ AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvValidGpeEvent
+ *
+ * PARAMETERS: GpeEventInfo - Info for this GPE
+ *
+ * RETURN: TRUE if the GpeEvent is valid
+ *
+ * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
+ * Should be called only when the GPE lists are semaphore locked
+ * and not subject to change.
+ *
+ ******************************************************************************/
+
+BOOLEAN
+AcpiEvValidGpeEvent (
+ ACPI_GPE_EVENT_INFO *GpeEventInfo)
+{
+ ACPI_GPE_XRUPT_INFO *GpeXruptBlock;
+ ACPI_GPE_BLOCK_INFO *GpeBlock;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ /* No need for spin lock since we are not changing any list elements */
+
+ /* Walk the GPE interrupt levels */
+
+ GpeXruptBlock = AcpiGbl_GpeXruptListHead;
+ while (GpeXruptBlock)
+ {
+ GpeBlock = GpeXruptBlock->GpeBlockListHead;
+
+ /* Walk the GPE blocks on this interrupt level */
+
+ while (GpeBlock)
+ {
+ if ((&GpeBlock->EventInfo[0] <= GpeEventInfo) &&
+ (&GpeBlock->EventInfo[GpeBlock->GpeCount] > GpeEventInfo))
+ {
+ return (TRUE);
+ }
+
+ GpeBlock = GpeBlock->Next;
+ }
+
+ GpeXruptBlock = GpeXruptBlock->Next;
+ }
+
+ return (FALSE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvGetGpeXruptBlock
+ *
+ * PARAMETERS: InterruptNumber - Interrupt for a GPE block
+ *
+ * RETURN: A GPE interrupt block
+ *
+ * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
+ * block per unique interrupt level used for GPEs. Should be
+ * called only when the GPE lists are semaphore locked and not
+ * subject to change.
+ *
+ ******************************************************************************/
+
+ACPI_GPE_XRUPT_INFO *
+AcpiEvGetGpeXruptBlock (
+ UINT32 InterruptNumber)
+{
+ ACPI_GPE_XRUPT_INFO *NextGpeXrupt;
+ ACPI_GPE_XRUPT_INFO *GpeXrupt;
+ ACPI_STATUS Status;
+ ACPI_CPU_FLAGS Flags;
+
+
+ ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock);
+
+
+ /* No need for lock since we are not changing any list elements here */
+
+ NextGpeXrupt = AcpiGbl_GpeXruptListHead;
+ while (NextGpeXrupt)
+ {
+ if (NextGpeXrupt->InterruptNumber == InterruptNumber)
+ {
+ return_PTR (NextGpeXrupt);
+ }
+
+ NextGpeXrupt = NextGpeXrupt->Next;
+ }
+
+ /* Not found, must allocate a new xrupt descriptor */
+
+ GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO));
+ if (!GpeXrupt)
+ {
+ return_PTR (NULL);
+ }
+
+ GpeXrupt->InterruptNumber = InterruptNumber;
+
+ /* Install new interrupt descriptor with spin lock */
+
+ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
+ if (AcpiGbl_GpeXruptListHead)
+ {
+ NextGpeXrupt = AcpiGbl_GpeXruptListHead;
+ while (NextGpeXrupt->Next)
+ {
+ NextGpeXrupt = NextGpeXrupt->Next;
+ }
+
+ NextGpeXrupt->Next = GpeXrupt;
+ GpeXrupt->Previous = NextGpeXrupt;
+ }
+ else
+ {
+ AcpiGbl_GpeXruptListHead = GpeXrupt;
+ }
+ AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
+
+ /* Install new interrupt handler if not SCI_INT */
+
+ if (InterruptNumber != AcpiGbl_FADT.SciInterrupt)
+ {
+ Status = AcpiOsInstallInterruptHandler (InterruptNumber,
+ AcpiEvGpeXruptHandler, GpeXrupt);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Could not install GPE interrupt handler at level 0x%X",
+ InterruptNumber));
+ return_PTR (NULL);
+ }
+ }
+
+ return_PTR (GpeXrupt);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvDeleteGpeXrupt
+ *
+ * PARAMETERS: GpeXrupt - A GPE interrupt info block
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated
+ * interrupt handler if not the SCI interrupt.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvDeleteGpeXrupt (
+ ACPI_GPE_XRUPT_INFO *GpeXrupt)
+{
+ ACPI_STATUS Status;
+ ACPI_CPU_FLAGS Flags;
+
+
+ ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt);
+
+
+ /* We never want to remove the SCI interrupt handler */
+
+ if (GpeXrupt->InterruptNumber == AcpiGbl_FADT.SciInterrupt)
+ {
+ GpeXrupt->GpeBlockListHead = NULL;
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Disable this interrupt */
+
+ Status = AcpiOsRemoveInterruptHandler (
+ GpeXrupt->InterruptNumber, AcpiEvGpeXruptHandler);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /* Unlink the interrupt block with lock */
+
+ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
+ if (GpeXrupt->Previous)
+ {
+ GpeXrupt->Previous->Next = GpeXrupt->Next;
+ }
+ else
+ {
+ /* No previous, update list head */
+
+ AcpiGbl_GpeXruptListHead = GpeXrupt->Next;
+ }
+
+ if (GpeXrupt->Next)
+ {
+ GpeXrupt->Next->Previous = GpeXrupt->Previous;
+ }
+ AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
+
+ /* Free the block */
+
+ ACPI_FREE (GpeXrupt);
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvDeleteGpeHandlers
+ *
+ * PARAMETERS: GpeXruptInfo - GPE Interrupt info
+ * GpeBlock - Gpe Block info
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
+ * Used only prior to termination.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvDeleteGpeHandlers (
+ ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
+ ACPI_GPE_BLOCK_INFO *GpeBlock,
+ void *Context)
+{
+ ACPI_GPE_EVENT_INFO *GpeEventInfo;
+ UINT32 i;
+ UINT32 j;
+
+
+ ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers);
+
+
+ /* Examine each GPE Register within the block */
+
+ for (i = 0; i < GpeBlock->RegisterCount; i++)
+ {
+ /* Now look at the individual GPEs in this byte register */
+
+ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
+ {
+ GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
+ ACPI_GPE_REGISTER_WIDTH) + j];
+
+ if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
+ ACPI_GPE_DISPATCH_HANDLER)
+ {
+ ACPI_FREE (GpeEventInfo->Dispatch.Handler);
+ GpeEventInfo->Dispatch.Handler = NULL;
+ GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
+ }
+ }
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
diff --git a/sys/contrib/dev/acpica/executer/exconfig.c b/sys/contrib/dev/acpica/executer/exconfig.c
index 95b78ed..918fc1c 100644
--- a/sys/contrib/dev/acpica/executer/exconfig.c
+++ b/sys/contrib/dev/acpica/executer/exconfig.c
@@ -164,8 +164,9 @@ AcpiExAddTable (
ACPI_NAMESPACE_NODE *ParentNode,
ACPI_OPERAND_OBJECT **DdbHandle)
{
- ACPI_STATUS Status;
ACPI_OPERAND_OBJECT *ObjDesc;
+ ACPI_STATUS Status;
+ ACPI_OWNER_ID OwnerId;
ACPI_FUNCTION_TRACE (ExAddTable);
@@ -205,7 +206,15 @@ AcpiExAddTable (
AcpiNsExecModuleCodeList ();
AcpiExEnterInterpreter ();
- return_ACPI_STATUS (Status);
+ /* Update GPEs for any new _PRW or _Lxx/_Exx methods. Ignore errors */
+
+ Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
+ if (ACPI_SUCCESS (Status))
+ {
+ AcpiEvUpdateGpes (OwnerId);
+ }
+
+ return_ACPI_STATUS (AE_OK);
}
@@ -347,9 +356,8 @@ AcpiExLoadTableOp (
Status = AcpiGetTableByIndex (TableIndex, &Table);
if (ACPI_SUCCESS (Status))
{
- ACPI_INFO ((AE_INFO,
- "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]",
- Table->Signature, Table->OemId, Table->OemTableId));
+ ACPI_INFO ((AE_INFO, "Dynamic OEM Table Load:"));
+ AcpiTbPrintTableHeader (0, Table);
}
/* Invoke table handler if present */
@@ -644,6 +652,9 @@ AcpiExLoadOp (
return_ACPI_STATUS (Status);
}
+ ACPI_INFO ((AE_INFO, "Dynamic OEM Table Load:"));
+ AcpiTbPrintTableHeader (0, TableDesc.Pointer);
+
/* Remove the reference by added by AcpiExStore above */
AcpiUtRemoveReference (DdbHandle);
diff --git a/sys/contrib/dev/acpica/executer/exoparg1.c b/sys/contrib/dev/acpica/executer/exoparg1.c
index 550980f..f12b14f 100644
--- a/sys/contrib/dev/acpica/executer/exoparg1.c
+++ b/sys/contrib/dev/acpica/executer/exoparg1.c
@@ -268,7 +268,7 @@ AcpiExOpcode_1A_0T_0R (
case AML_SLEEP_OP: /* Sleep (MsecTime) */
- Status = AcpiExSystemDoSuspend (Operand[0]->Integer.Value);
+ Status = AcpiExSystemDoSleep (Operand[0]->Integer.Value);
break;
diff --git a/sys/contrib/dev/acpica/executer/exsystem.c b/sys/contrib/dev/acpica/executer/exsystem.c
index 96e3063..2bc96fc 100644
--- a/sys/contrib/dev/acpica/executer/exsystem.c
+++ b/sys/contrib/dev/acpica/executer/exsystem.c
@@ -280,19 +280,19 @@ AcpiExSystemDoStall (
/*******************************************************************************
*
- * FUNCTION: AcpiExSystemDoSuspend
+ * FUNCTION: AcpiExSystemDoSleep
*
- * PARAMETERS: HowLong - The amount of time to suspend,
+ * PARAMETERS: HowLong - The amount of time to sleep,
* in milliseconds
*
* RETURN: None
*
- * DESCRIPTION: Suspend running thread for specified amount of time.
+ * DESCRIPTION: Sleep the running thread for specified amount of time.
*
******************************************************************************/
ACPI_STATUS
-AcpiExSystemDoSuspend (
+AcpiExSystemDoSleep (
UINT64 HowLong)
{
ACPI_FUNCTION_ENTRY ();
diff --git a/sys/contrib/dev/acpica/include/acevents.h b/sys/contrib/dev/acpica/include/acevents.h
index 4d945ef..4051557 100644
--- a/sys/contrib/dev/acpica/include/acevents.h
+++ b/sys/contrib/dev/acpica/include/acevents.h
@@ -167,8 +167,12 @@ AcpiEvQueueNotifyRequest (
/*
- * evgpe - GPE handling and dispatch
+ * evgpe - Low-level GPE support
*/
+UINT32
+AcpiEvGpeDetect (
+ ACPI_GPE_XRUPT_INFO *GpeXruptList);
+
ACPI_STATUS
AcpiEvUpdateGpeEnableMasks (
ACPI_GPE_EVENT_INFO *GpeEventInfo);
@@ -193,23 +197,8 @@ AcpiEvLowGetGpeInfo (
/*
- * evgpeblk
+ * evgpeblk - Upper-level GPE block support
*/
-BOOLEAN
-AcpiEvValidGpeEvent (
- ACPI_GPE_EVENT_INFO *GpeEventInfo);
-
-ACPI_STATUS
-AcpiEvWalkGpeList (
- ACPI_GPE_CALLBACK GpeWalkCallback,
- void *Context);
-
-ACPI_STATUS
-AcpiEvDeleteGpeHandlers (
- ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
- ACPI_GPE_BLOCK_INFO *GpeBlock,
- void *Context);
-
ACPI_STATUS
AcpiEvCreateGpeBlock (
ACPI_NAMESPACE_NODE *GpeDevice,
@@ -233,14 +222,57 @@ AcpiEvGpeDispatch (
ACPI_GPE_EVENT_INFO *GpeEventInfo,
UINT32 GpeNumber);
-UINT32
-AcpiEvGpeDetect (
- ACPI_GPE_XRUPT_INFO *GpeXruptList);
-
+/*
+ * evgpeinit - GPE initialization and update
+ */
ACPI_STATUS
AcpiEvGpeInitialize (
void);
+void
+AcpiEvUpdateGpes (
+ ACPI_OWNER_ID TableOwnerId);
+
+ACPI_STATUS
+AcpiEvMatchGpeMethod (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue);
+
+ACPI_STATUS
+AcpiEvMatchPrwAndGpe (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue);
+
+/*
+ * evgpeutil - GPE utilities
+ */
+ACPI_STATUS
+AcpiEvWalkGpeList (
+ ACPI_GPE_CALLBACK GpeWalkCallback,
+ void *Context);
+
+BOOLEAN
+AcpiEvValidGpeEvent (
+ ACPI_GPE_EVENT_INFO *GpeEventInfo);
+
+ACPI_GPE_XRUPT_INFO *
+AcpiEvGetGpeXruptBlock (
+ UINT32 InterruptNumber);
+
+ACPI_STATUS
+AcpiEvDeleteGpeXrupt (
+ ACPI_GPE_XRUPT_INFO *GpeXrupt);
+
+ACPI_STATUS
+AcpiEvDeleteGpeHandlers (
+ ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
+ ACPI_GPE_BLOCK_INFO *GpeBlock,
+ void *Context);
+
/*
* evregion - Address Space handling
diff --git a/sys/contrib/dev/acpica/include/acglobal.h b/sys/contrib/dev/acpica/include/acglobal.h
index 4f0769e..e0f8871 100644
--- a/sys/contrib/dev/acpica/include/acglobal.h
+++ b/sys/contrib/dev/acpica/include/acglobal.h
@@ -216,11 +216,10 @@ ACPI_NAME AcpiGbl_TraceMethodName;
****************************************************************************/
/*
- * AcpiGbl_RootTableList is the master list of ACPI tables found in the
- * RSDT/XSDT.
- *
+ * AcpiGbl_RootTableList is the master list of ACPI tables that were
+ * found in the RSDT/XSDT.
*/
-ACPI_EXTERN ACPI_INTERNAL_RSDT AcpiGbl_RootTableList;
+ACPI_EXTERN ACPI_TABLE_LIST AcpiGbl_RootTableList;
ACPI_EXTERN ACPI_TABLE_FACS *AcpiGbl_FACS;
/* These addresses are calculated from the FADT Event Block addresses */
diff --git a/sys/contrib/dev/acpica/include/acinterp.h b/sys/contrib/dev/acpica/include/acinterp.h
index 67142c8..e3fa940 100644
--- a/sys/contrib/dev/acpica/include/acinterp.h
+++ b/sys/contrib/dev/acpica/include/acinterp.h
@@ -434,7 +434,7 @@ AcpiExSystemDoNotifyOp (
ACPI_OPERAND_OBJECT *ObjDesc);
ACPI_STATUS
-AcpiExSystemDoSuspend(
+AcpiExSystemDoSleep(
UINT64 Time);
ACPI_STATUS
diff --git a/sys/contrib/dev/acpica/include/aclocal.h b/sys/contrib/dev/acpica/include/aclocal.h
index 8818a6e..1deced0 100644
--- a/sys/contrib/dev/acpica/include/aclocal.h
+++ b/sys/contrib/dev/acpica/include/aclocal.h
@@ -307,16 +307,16 @@ typedef struct acpi_namespace_node
#define ANOBJ_IS_REFERENCED 0x80 /* iASL only: Object was referenced */
-/* One internal RSDT for table management */
+/* Internal ACPI table management - master table list */
-typedef struct acpi_internal_rsdt
+typedef struct acpi_table_list
{
- ACPI_TABLE_DESC *Tables;
- UINT32 Count;
- UINT32 Size;
+ ACPI_TABLE_DESC *Tables; /* Table descriptor array */
+ UINT32 CurrentTableCount; /* Tables currently in the array */
+ UINT32 MaxTableCount; /* Max tables array will hold */
UINT8 Flags;
-} ACPI_INTERNAL_RSDT;
+} ACPI_TABLE_LIST;
/* Flags for above */
@@ -612,6 +612,10 @@ typedef struct acpi_gpe_walk_info
{
ACPI_NAMESPACE_NODE *GpeDevice;
ACPI_GPE_BLOCK_INFO *GpeBlock;
+ UINT16 Count;
+ ACPI_OWNER_ID OwnerId;
+ BOOLEAN EnableThisGpe;
+ BOOLEAN ExecuteByOwnerId;
} ACPI_GPE_WALK_INFO;
diff --git a/sys/contrib/dev/acpica/include/acpiosxf.h b/sys/contrib/dev/acpica/include/acpiosxf.h
index 13570b4..9924d4d 100644
--- a/sys/contrib/dev/acpica/include/acpiosxf.h
+++ b/sys/contrib/dev/acpica/include/acpiosxf.h
@@ -410,8 +410,8 @@ AcpiOsWritePciConfiguration (
*/
void
AcpiOsDerivePciId(
- ACPI_HANDLE Rhandle,
- ACPI_HANDLE Chandle,
+ ACPI_HANDLE Device,
+ ACPI_HANDLE Region,
ACPI_PCI_ID **PciId);
diff --git a/sys/contrib/dev/acpica/include/acpixf.h b/sys/contrib/dev/acpica/include/acpixf.h
index 5562fa0..48d824f 100644
--- a/sys/contrib/dev/acpica/include/acpixf.h
+++ b/sys/contrib/dev/acpica/include/acpixf.h
@@ -120,7 +120,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20100331
+#define ACPI_CA_VERSION 0x20100428
#include <contrib/dev/acpica/include/actypes.h>
#include <contrib/dev/acpica/include/actbl.h>
@@ -283,7 +283,7 @@ AcpiGetDevices (
ACPI_STATUS
AcpiGetName (
- ACPI_HANDLE Handle,
+ ACPI_HANDLE Object,
UINT32 NameType,
ACPI_BUFFER *RetPathPtr);
@@ -295,18 +295,18 @@ AcpiGetHandle (
ACPI_STATUS
AcpiAttachData (
- ACPI_HANDLE ObjHandle,
+ ACPI_HANDLE Object,
ACPI_OBJECT_HANDLER Handler,
void *Data);
ACPI_STATUS
AcpiDetachData (
- ACPI_HANDLE ObjHandle,
+ ACPI_HANDLE Object,
ACPI_OBJECT_HANDLER Handler);
ACPI_STATUS
AcpiGetData (
- ACPI_HANDLE ObjHandle,
+ ACPI_HANDLE Object,
ACPI_OBJECT_HANDLER Handler,
void **Data);
@@ -338,7 +338,7 @@ AcpiEvaluateObjectTyped (
ACPI_STATUS
AcpiGetObjectInfo (
- ACPI_HANDLE Handle,
+ ACPI_HANDLE Object,
ACPI_DEVICE_INFO **ReturnBuffer);
ACPI_STATUS
@@ -527,36 +527,36 @@ ACPI_STATUS (*ACPI_WALK_RESOURCE_CALLBACK) (
ACPI_STATUS
AcpiGetVendorResource (
- ACPI_HANDLE DeviceHandle,
+ ACPI_HANDLE Device,
char *Name,
ACPI_VENDOR_UUID *Uuid,
ACPI_BUFFER *RetBuffer);
ACPI_STATUS
-AcpiGetCurrentResources(
- ACPI_HANDLE DeviceHandle,
+AcpiGetCurrentResources (
+ ACPI_HANDLE Device,
ACPI_BUFFER *RetBuffer);
ACPI_STATUS
-AcpiGetPossibleResources(
- ACPI_HANDLE DeviceHandle,
+AcpiGetPossibleResources (
+ ACPI_HANDLE Device,
ACPI_BUFFER *RetBuffer);
ACPI_STATUS
AcpiWalkResources (
- ACPI_HANDLE DeviceHandle,
+ ACPI_HANDLE Device,
char *Name,
ACPI_WALK_RESOURCE_CALLBACK UserFunction,
void *Context);
ACPI_STATUS
AcpiSetCurrentResources (
- ACPI_HANDLE DeviceHandle,
+ ACPI_HANDLE Device,
ACPI_BUFFER *InBuffer);
ACPI_STATUS
-AcpiGetIrqRoutingTable (
- ACPI_HANDLE BusDeviceHandle,
+AcpiGetIrqRoutingTable (
+ ACPI_HANDLE Device,
ACPI_BUFFER *RetBuffer);
ACPI_STATUS
diff --git a/sys/contrib/dev/acpica/include/actypes.h b/sys/contrib/dev/acpica/include/actypes.h
index 3c0626a..601e87e 100644
--- a/sys/contrib/dev/acpica/include/actypes.h
+++ b/sys/contrib/dev/acpica/include/actypes.h
@@ -1099,7 +1099,7 @@ ACPI_STATUS (*ACPI_ADR_SPACE_SETUP) (
typedef
ACPI_STATUS (*ACPI_WALK_CALLBACK) (
- ACPI_HANDLE ObjHandle,
+ ACPI_HANDLE Object,
UINT32 NestingLevel,
void *Context,
void **ReturnValue);
diff --git a/sys/contrib/dev/acpica/include/amlresrc.h b/sys/contrib/dev/acpica/include/amlresrc.h
index 9084e44..4cd2617 100644
--- a/sys/contrib/dev/acpica/include/amlresrc.h
+++ b/sys/contrib/dev/acpica/include/amlresrc.h
@@ -300,6 +300,12 @@ typedef struct aml_resource_large_header
} AML_RESOURCE_LARGE_HEADER;
+/* General Flags for address space resource descriptors */
+
+#define ACPI_RESOURCE_FLAG_DEC 2
+#define ACPI_RESOURCE_FLAG_MIF 4
+#define ACPI_RESOURCE_FLAG_MAF 8
+
typedef struct aml_resource_memory24
{
AML_RESOURCE_LARGE_HEADER_COMMON
diff --git a/sys/contrib/dev/acpica/osunixxf.c b/sys/contrib/dev/acpica/osunixxf.c
index a0e38e4..456fd19 100644
--- a/sys/contrib/dev/acpica/osunixxf.c
+++ b/sys/contrib/dev/acpica/osunixxf.c
@@ -986,8 +986,8 @@ AcpiOsWritePciConfiguration (
/* TEMPORARY STUB FUNCTION */
void
AcpiOsDerivePciId(
- ACPI_HANDLE rhandle,
- ACPI_HANDLE chandle,
+ ACPI_HANDLE Device,
+ ACPI_HANDLE Region,
ACPI_PCI_ID **PciId)
{
diff --git a/sys/contrib/dev/acpica/tables/tbfind.c b/sys/contrib/dev/acpica/tables/tbfind.c
index d6cee63..f9b28ba 100644
--- a/sys/contrib/dev/acpica/tables/tbfind.c
+++ b/sys/contrib/dev/acpica/tables/tbfind.c
@@ -164,7 +164,7 @@ AcpiTbFindTable (
/* Search for the table */
- for (i = 0; i < AcpiGbl_RootTableList.Count; ++i)
+ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
{
if (ACPI_MEMCMP (&(AcpiGbl_RootTableList.Tables[i].Signature),
Header.Signature, ACPI_NAME_SIZE))
diff --git a/sys/contrib/dev/acpica/tables/tbinstal.c b/sys/contrib/dev/acpica/tables/tbinstal.c
index be55612..d573eb9 100644
--- a/sys/contrib/dev/acpica/tables/tbinstal.c
+++ b/sys/contrib/dev/acpica/tables/tbinstal.c
@@ -227,7 +227,7 @@ AcpiTbAddTable (
/* Check if table is already registered */
- for (i = 0; i < AcpiGbl_RootTableList.Count; ++i)
+ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
{
if (!AcpiGbl_RootTableList.Tables[i].Pointer)
{
@@ -370,7 +370,7 @@ AcpiTbResizeRootTableList (
/* Increase the Table Array size */
Tables = ACPI_ALLOCATE_ZEROED (
- ((ACPI_SIZE) AcpiGbl_RootTableList.Size +
+ ((ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount +
ACPI_ROOT_TABLE_SIZE_INCREMENT) *
sizeof (ACPI_TABLE_DESC));
if (!Tables)
@@ -384,7 +384,7 @@ AcpiTbResizeRootTableList (
if (AcpiGbl_RootTableList.Tables)
{
ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables,
- (ACPI_SIZE) AcpiGbl_RootTableList.Size * sizeof (ACPI_TABLE_DESC));
+ (ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount * sizeof (ACPI_TABLE_DESC));
if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
{
@@ -393,7 +393,7 @@ AcpiTbResizeRootTableList (
}
AcpiGbl_RootTableList.Tables = Tables;
- AcpiGbl_RootTableList.Size += ACPI_ROOT_TABLE_SIZE_INCREMENT;
+ AcpiGbl_RootTableList.MaxTableCount += ACPI_ROOT_TABLE_SIZE_INCREMENT;
AcpiGbl_RootTableList.Flags |= (UINT8) ACPI_ROOT_ORIGIN_ALLOCATED;
return_ACPI_STATUS (AE_OK);
@@ -423,12 +423,14 @@ AcpiTbStoreTable (
UINT8 Flags,
UINT32 *TableIndex)
{
- ACPI_STATUS Status = AE_OK;
+ ACPI_STATUS Status;
+ ACPI_TABLE_DESC *NewTable;
/* Ensure that there is room for the table in the Root Table List */
- if (AcpiGbl_RootTableList.Count >= AcpiGbl_RootTableList.Size)
+ if (AcpiGbl_RootTableList.CurrentTableCount >=
+ AcpiGbl_RootTableList.MaxTableCount)
{
Status = AcpiTbResizeRootTableList();
if (ACPI_FAILURE (Status))
@@ -437,21 +439,21 @@ AcpiTbStoreTable (
}
}
+ NewTable = &AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount];
+
/* Initialize added table */
- AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Address = Address;
- AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Pointer = Table;
- AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Length = Length;
- AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].OwnerId = 0;
- AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Flags = Flags;
+ NewTable->Address = Address;
+ NewTable->Pointer = Table;
+ NewTable->Length = Length;
+ NewTable->OwnerId = 0;
+ NewTable->Flags = Flags;
- ACPI_MOVE_32_TO_32 (
- &(AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Signature),
- Table->Signature);
+ ACPI_MOVE_32_TO_32 (&NewTable->Signature, Table->Signature);
- *TableIndex = AcpiGbl_RootTableList.Count;
- AcpiGbl_RootTableList.Count++;
- return (Status);
+ *TableIndex = AcpiGbl_RootTableList.CurrentTableCount;
+ AcpiGbl_RootTableList.CurrentTableCount++;
+ return (AE_OK);
}
@@ -523,7 +525,7 @@ AcpiTbTerminate (
/* Delete the individual tables */
- for (i = 0; i < AcpiGbl_RootTableList.Count; i++)
+ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
{
AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]);
}
@@ -539,7 +541,7 @@ AcpiTbTerminate (
AcpiGbl_RootTableList.Tables = NULL;
AcpiGbl_RootTableList.Flags = 0;
- AcpiGbl_RootTableList.Count = 0;
+ AcpiGbl_RootTableList.CurrentTableCount = 0;
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
(void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
@@ -575,7 +577,7 @@ AcpiTbDeleteNamespaceByOwner (
return_ACPI_STATUS (Status);
}
- if (TableIndex >= AcpiGbl_RootTableList.Count)
+ if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
{
/* The table index does not exist */
@@ -634,7 +636,7 @@ AcpiTbAllocateOwnerId (
(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- if (TableIndex < AcpiGbl_RootTableList.Count)
+ if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
{
Status = AcpiUtAllocateOwnerId
(&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
@@ -668,7 +670,7 @@ AcpiTbReleaseOwnerId (
(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- if (TableIndex < AcpiGbl_RootTableList.Count)
+ if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
{
AcpiUtReleaseOwnerId (
&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
@@ -705,7 +707,7 @@ AcpiTbGetOwnerId (
(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- if (TableIndex < AcpiGbl_RootTableList.Count)
+ if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
{
*OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
Status = AE_OK;
@@ -734,7 +736,7 @@ AcpiTbIsTableLoaded (
(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- if (TableIndex < AcpiGbl_RootTableList.Count)
+ if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
{
IsLoaded = (BOOLEAN)
(AcpiGbl_RootTableList.Tables[TableIndex].Flags &
@@ -766,7 +768,7 @@ AcpiTbSetTableLoadedFlag (
{
(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- if (TableIndex < AcpiGbl_RootTableList.Count)
+ if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
{
if (IsLoaded)
{
diff --git a/sys/contrib/dev/acpica/tables/tbutils.c b/sys/contrib/dev/acpica/tables/tbutils.c
index 916c04e..f6acc3c 100644
--- a/sys/contrib/dev/acpica/tables/tbutils.c
+++ b/sys/contrib/dev/acpica/tables/tbutils.c
@@ -184,7 +184,7 @@ AcpiTbTablesLoaded (
void)
{
- if (AcpiGbl_RootTableList.Count >= 3)
+ if (AcpiGbl_RootTableList.CurrentTableCount >= 3)
{
return (TRUE);
}
@@ -780,14 +780,15 @@ AcpiTbParseRootTable (
* come from the FADT
*/
TableEntry = ACPI_CAST_PTR (UINT8, Table) + sizeof (ACPI_TABLE_HEADER);
- AcpiGbl_RootTableList.Count = 2;
+ AcpiGbl_RootTableList.CurrentTableCount = 2;
/*
* Initialize the root table array from the RSDT/XSDT
*/
for (i = 0; i < TableCount; i++)
{
- if (AcpiGbl_RootTableList.Count >= AcpiGbl_RootTableList.Size)
+ if (AcpiGbl_RootTableList.CurrentTableCount >=
+ AcpiGbl_RootTableList.MaxTableCount)
{
/* There is no more room in the root table array, attempt resize */
@@ -796,18 +797,18 @@ AcpiTbParseRootTable (
{
ACPI_WARNING ((AE_INFO, "Truncating %u table entries!",
(unsigned) (TableCount -
- (AcpiGbl_RootTableList.Count - 2))));
+ (AcpiGbl_RootTableList.CurrentTableCount - 2))));
break;
}
}
/* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
- AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Address =
+ AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount].Address =
AcpiTbGetRootTableEntry (TableEntry, TableEntrySize);
TableEntry += TableEntrySize;
- AcpiGbl_RootTableList.Count++;
+ AcpiGbl_RootTableList.CurrentTableCount++;
}
/*
@@ -820,7 +821,7 @@ AcpiTbParseRootTable (
* Complete the initialization of the root table array by examining
* the header of each table
*/
- for (i = 2; i < AcpiGbl_RootTableList.Count; i++)
+ for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
{
AcpiTbInstallTable (AcpiGbl_RootTableList.Tables[i].Address,
NULL, i);
diff --git a/sys/contrib/dev/acpica/tables/tbxface.c b/sys/contrib/dev/acpica/tables/tbxface.c
index e2eeb2e..366a525 100644
--- a/sys/contrib/dev/acpica/tables/tbxface.c
+++ b/sys/contrib/dev/acpica/tables/tbxface.c
@@ -150,7 +150,7 @@ AcpiAllocateRootTable (
UINT32 InitialTableCount)
{
- AcpiGbl_RootTableList.Size = InitialTableCount;
+ AcpiGbl_RootTableList.MaxTableCount = InitialTableCount;
AcpiGbl_RootTableList.Flags = ACPI_ROOT_ALLOW_RESIZE;
return (AcpiTbResizeRootTableList ());
@@ -216,7 +216,7 @@ AcpiInitializeTables (
(ACPI_SIZE) InitialTableCount * sizeof (ACPI_TABLE_DESC));
AcpiGbl_RootTableList.Tables = InitialTableArray;
- AcpiGbl_RootTableList.Size = InitialTableCount;
+ AcpiGbl_RootTableList.MaxTableCount = InitialTableCount;
AcpiGbl_RootTableList.Flags = ACPI_ROOT_ORIGIN_UNKNOWN;
if (AllowResize)
{
@@ -285,7 +285,7 @@ AcpiReallocateRootTable (
* increment to create the new table size.
*/
CurrentSize = (ACPI_SIZE)
- AcpiGbl_RootTableList.Count * sizeof (ACPI_TABLE_DESC);
+ AcpiGbl_RootTableList.CurrentTableCount * sizeof (ACPI_TABLE_DESC);
NewSize = CurrentSize +
(ACPI_ROOT_TABLE_SIZE_INCREMENT * sizeof (ACPI_TABLE_DESC));
@@ -306,8 +306,8 @@ AcpiReallocateRootTable (
* size of the original table list.
*/
AcpiGbl_RootTableList.Tables = Tables;
- AcpiGbl_RootTableList.Size =
- AcpiGbl_RootTableList.Count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
+ AcpiGbl_RootTableList.MaxTableCount =
+ AcpiGbl_RootTableList.CurrentTableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT;
AcpiGbl_RootTableList.Flags =
ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE;
@@ -354,7 +354,7 @@ AcpiGetTableHeader (
/* Walk the root table list */
- for (i = 0, j = 0; i < AcpiGbl_RootTableList.Count; i++)
+ for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
{
if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature),
Signature))
@@ -439,7 +439,7 @@ AcpiGetTable (
/* Walk the root table list */
- for (i = 0, j = 0; i < AcpiGbl_RootTableList.Count; i++)
+ for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
{
if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature),
Signature))
@@ -502,7 +502,7 @@ AcpiGetTableByIndex (
/* Validate index */
- if (TableIndex >= AcpiGbl_RootTableList.Count)
+ if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
{
(void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
return_ACPI_STATUS (AE_BAD_PARAMETER);
@@ -559,7 +559,7 @@ AcpiTbLoadNamespace (
* Load the namespace. The DSDT is required, but any SSDT and
* PSDT tables are optional. Verify the DSDT.
*/
- if (!AcpiGbl_RootTableList.Count ||
+ if (!AcpiGbl_RootTableList.CurrentTableCount ||
!ACPI_COMPARE_NAME (
&(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature),
ACPI_SIG_DSDT) ||
@@ -613,7 +613,7 @@ AcpiTbLoadNamespace (
/* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */
(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- for (i = 2; i < AcpiGbl_RootTableList.Count; ++i)
+ for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
{
if ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature),
ACPI_SIG_SSDT) &&
diff --git a/sys/contrib/dev/acpica/utilities/utcopy.c b/sys/contrib/dev/acpica/utilities/utcopy.c
index b16e14c..f6bfba0 100644
--- a/sys/contrib/dev/acpica/utilities/utcopy.c
+++ b/sys/contrib/dev/acpica/utilities/utcopy.c
@@ -797,6 +797,7 @@ AcpiUtCopySimpleObject (
UINT16 ReferenceCount;
ACPI_OPERAND_OBJECT *NextObject;
ACPI_STATUS Status;
+ ACPI_SIZE CopySize;
/* Save fields from destination that we don't want to overwrite */
@@ -804,10 +805,18 @@ AcpiUtCopySimpleObject (
ReferenceCount = DestDesc->Common.ReferenceCount;
NextObject = DestDesc->Common.NextObject;
- /* Copy the entire source object over the destination object*/
+ /*
+ * Copy the entire source object over the destination object.
+ * Note: Source can be either an operand object or namespace node.
+ */
+ CopySize = sizeof (ACPI_OPERAND_OBJECT);
+ if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED)
+ {
+ CopySize = sizeof (ACPI_NAMESPACE_NODE);
+ }
- ACPI_MEMCPY ((char *) DestDesc, (char *) SourceDesc,
- sizeof (ACPI_OPERAND_OBJECT));
+ ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc),
+ ACPI_CAST_PTR (char, SourceDesc), CopySize);
/* Restore the saved fields */
@@ -841,8 +850,7 @@ AcpiUtCopySimpleObject (
/* Copy the actual buffer data */
ACPI_MEMCPY (DestDesc->Buffer.Pointer,
- SourceDesc->Buffer.Pointer,
- SourceDesc->Buffer.Length);
+ SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length);
}
break;
@@ -864,7 +872,7 @@ AcpiUtCopySimpleObject (
/* Copy the actual string data */
ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer,
- (ACPI_SIZE) SourceDesc->String.Length + 1);
+ (ACPI_SIZE) SourceDesc->String.Length + 1);
}
break;
diff --git a/sys/contrib/dev/acpica/utilities/utglobal.c b/sys/contrib/dev/acpica/utilities/utglobal.c
index 85a93fe..0483be9 100644
--- a/sys/contrib/dev/acpica/utilities/utglobal.c
+++ b/sys/contrib/dev/acpica/utilities/utglobal.c
@@ -625,7 +625,7 @@ AcpiUtGetNodeName (
static const char *AcpiGbl_DescTypeNames[] =
{
- /* 00 */ "Invalid",
+ /* 00 */ "Not a Descriptor",
/* 01 */ "Cached",
/* 02 */ "State-Generic",
/* 03 */ "State-Update",
@@ -656,7 +656,7 @@ AcpiUtGetDescriptorName (
if (ACPI_GET_DESCRIPTOR_TYPE (Object) > ACPI_DESC_TYPE_MAX)
{
- return (ACPI_CAST_PTR (char, AcpiGbl_BadType));
+ return ("Not a Descriptor");
}
return (ACPI_CAST_PTR (char,
diff --git a/sys/contrib/dev/acpica/utilities/uttrack.c b/sys/contrib/dev/acpica/utilities/uttrack.c
index ddb35ef..fc5a472 100644
--- a/sys/contrib/dev/acpica/utilities/uttrack.c
+++ b/sys/contrib/dev/acpica/utilities/uttrack.c
@@ -644,6 +644,7 @@ AcpiUtDumpAllocations (
ACPI_DEBUG_MEM_BLOCK *Element;
ACPI_DESCRIPTOR *Descriptor;
UINT32 NumOutstanding = 0;
+ UINT8 DescriptorType;
ACPI_FUNCTION_TRACE (UtDumpAllocations);
@@ -663,43 +664,86 @@ AcpiUtDumpAllocations (
if ((Element->Component & Component) &&
((Module == NULL) || (0 == ACPI_STRCMP (Module, Element->Module))))
{
- /* Ignore allocated objects that are in a cache */
-
Descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &Element->UserSpace);
- if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED)
+
+ if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR))
{
- AcpiOsPrintf ("%p Len %04X %9.9s-%d [%s] ",
+ AcpiOsPrintf ("%p Length 0x%04X %9.9s-%d "
+ "[Not a Descriptor - too small]\n",
Descriptor, Element->Size, Element->Module,
- Element->Line, AcpiUtGetDescriptorName (Descriptor));
-
- /* Most of the elements will be Operand objects. */
+ Element->Line);
+ }
+ else
+ {
+ /* Ignore allocated objects that are in a cache */
- switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
+ if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED)
{
- case ACPI_DESC_TYPE_OPERAND:
- AcpiOsPrintf ("%12.12s R%hd",
- AcpiUtGetTypeName (Descriptor->Object.Common.Type),
- Descriptor->Object.Common.ReferenceCount);
- break;
-
- case ACPI_DESC_TYPE_PARSER:
- AcpiOsPrintf ("AmlOpcode %04hX",
- Descriptor->Op.Asl.AmlOpcode);
- break;
-
- case ACPI_DESC_TYPE_NAMED:
- AcpiOsPrintf ("%4.4s",
- AcpiUtGetNodeName (&Descriptor->Node));
- break;
-
- default:
- break;
+ AcpiOsPrintf ("%p Length 0x%04X %9.9s-%d [%s] ",
+ Descriptor, Element->Size, Element->Module,
+ Element->Line, AcpiUtGetDescriptorName (Descriptor));
+
+ /* Validate the descriptor type using Type field and length */
+
+ DescriptorType = 0; /* Not a valid descriptor type */
+
+ switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
+ {
+ case ACPI_DESC_TYPE_OPERAND:
+ if (Element->Size == sizeof (ACPI_DESC_TYPE_OPERAND))
+ {
+ DescriptorType = ACPI_DESC_TYPE_OPERAND;
+ }
+ break;
+
+ case ACPI_DESC_TYPE_PARSER:
+ if (Element->Size == sizeof (ACPI_DESC_TYPE_PARSER))
+ {
+ DescriptorType = ACPI_DESC_TYPE_PARSER;
+ }
+ break;
+
+ case ACPI_DESC_TYPE_NAMED:
+ if (Element->Size == sizeof (ACPI_DESC_TYPE_NAMED))
+ {
+ DescriptorType = ACPI_DESC_TYPE_NAMED;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Display additional info for the major descriptor types */
+
+ switch (DescriptorType)
+ {
+ case ACPI_DESC_TYPE_OPERAND:
+ AcpiOsPrintf ("%12.12s RefCount 0x%04X\n",
+ AcpiUtGetTypeName (Descriptor->Object.Common.Type),
+ Descriptor->Object.Common.ReferenceCount);
+ break;
+
+ case ACPI_DESC_TYPE_PARSER:
+ AcpiOsPrintf ("AmlOpcode 0x%04hX\n",
+ Descriptor->Op.Asl.AmlOpcode);
+ break;
+
+ case ACPI_DESC_TYPE_NAMED:
+ AcpiOsPrintf ("%4.4s\n",
+ AcpiUtGetNodeName (&Descriptor->Node));
+ break;
+
+ default:
+ AcpiOsPrintf ( "\n");
+ break;
+ }
}
-
- AcpiOsPrintf ( "\n");
- NumOutstanding++;
}
+
+ NumOutstanding++;
}
+
Element = Element->Next;
}
@@ -709,13 +753,11 @@ AcpiUtDumpAllocations (
if (!NumOutstanding)
{
- ACPI_INFO ((AE_INFO,
- "No outstanding allocations"));
+ ACPI_INFO ((AE_INFO, "No outstanding allocations"));
}
else
{
- ACPI_ERROR ((AE_INFO,
- "%d(0x%X) Outstanding allocations",
+ ACPI_ERROR ((AE_INFO, "%d(0x%X) Outstanding allocations",
NumOutstanding, NumOutstanding));
}
diff --git a/sys/contrib/ipfilter/netinet/ip_auth.c b/sys/contrib/ipfilter/netinet/ip_auth.c
index 19a12f4..42d29d4 100644
--- a/sys/contrib/ipfilter/netinet/ip_auth.c
+++ b/sys/contrib/ipfilter/netinet/ip_auth.c
@@ -70,11 +70,6 @@ struct file;
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
-#if !defined(_KERNEL) && defined(__FreeBSD_version) && \
- __FreeBSD_version >= 800049
-# define V_ip_do_randomid ip_do_randomid
-# define V_ip_id ip_id
-#endif
#if !defined(_KERNEL) && !defined(__osf__) && !defined(__sgi)
# define KERNEL
# define _KERNEL
diff --git a/sys/dev/acpica/Osd/OsdHardware.c b/sys/dev/acpica/Osd/OsdHardware.c
index 822bf78..0638802 100644
--- a/sys/dev/acpica/Osd/OsdHardware.c
+++ b/sys/dev/acpica/Osd/OsdHardware.c
@@ -216,12 +216,12 @@ acpi_bus_number(ACPI_HANDLE root, ACPI_HANDLE curr, ACPI_PCI_ID *PciId)
/*
* Find the bus number for a device
*
- * rhandle: handle for the root bus
- * chandle: handle for the device
+ * Device: handle for the PCI root bridge device
+ * Region: handle for the PCI configuration space operation region
* PciId: pointer to device slot and function, we fill out bus
*/
void
-AcpiOsDerivePciId(ACPI_HANDLE rhandle, ACPI_HANDLE chandle, ACPI_PCI_ID **PciId)
+AcpiOsDerivePciId(ACPI_HANDLE Device, ACPI_HANDLE Region, ACPI_PCI_ID **PciId)
{
ACPI_HANDLE parent;
ACPI_STATUS status;
@@ -230,26 +230,21 @@ AcpiOsDerivePciId(ACPI_HANDLE rhandle, ACPI_HANDLE chandle, ACPI_PCI_ID **PciId)
if (pci_cfgregopen() == 0)
panic("AcpiOsDerivePciId unable to initialize pci bus");
- /* Try to read _BBN for bus number if we're at the root */
+ /* Try to read _BBN for bus number if we're at the root. */
bus = 0;
- if (rhandle == chandle) {
- status = acpi_GetInteger(rhandle, "_BBN", &bus);
+ if (Device == Region) {
+ status = acpi_GetInteger(Device, "_BBN", &bus);
if (ACPI_FAILURE(status) && bootverbose)
printf("AcpiOsDerivePciId: root bus has no _BBN, assuming 0\n");
}
- /*
- * Get the parent handle and call the recursive case. It is not
- * clear why we seem to be getting a chandle that points to a child
- * of the desired slot/function but passing in the parent handle
- * here works.
- */
- if (ACPI_SUCCESS(AcpiGetParent(chandle, &parent)))
- bus = acpi_bus_number(rhandle, parent, *PciId);
+ /* Get the parent handle and call the recursive case. */
+ if (ACPI_SUCCESS(AcpiGetParent(Region, &parent)))
+ bus = acpi_bus_number(Device, parent, *PciId);
(*PciId)->Bus = bus;
if (bootverbose) {
printf("AcpiOsDerivePciId: %s -> bus %d dev %d func %d\n",
- acpi_name(chandle), (*PciId)->Bus, (*PciId)->Device,
+ acpi_name(Region), (*PciId)->Bus, (*PciId)->Device,
(*PciId)->Function);
}
}
diff --git a/sys/dev/ae/if_ae.c b/sys/dev/ae/if_ae.c
index 68181f4..d2812a4 100644
--- a/sys/dev/ae/if_ae.c
+++ b/sys/dev/ae/if_ae.c
@@ -378,7 +378,7 @@ ae_attach(device_t dev)
ifp->if_init = ae_init;
ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
ifp->if_hwassist = 0;
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
IFQ_SET_READY(&ifp->if_snd);
if (pci_find_extcap(dev, PCIY_PMG, &pmc) == 0) {
diff --git a/sys/dev/agp/agp.c b/sys/dev/agp/agp.c
index c992c93..577a7e9 100644
--- a/sys/dev/agp/agp.c
+++ b/sys/dev/agp/agp.c
@@ -623,9 +623,9 @@ bad:
m = vm_page_lookup(mem->am_obj, OFF_TO_IDX(k));
if (k >= i)
vm_page_wakeup(m);
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_unwire(m, 0);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
}
VM_OBJECT_UNLOCK(mem->am_obj);
@@ -657,9 +657,9 @@ agp_generic_unbind_memory(device_t dev, struct agp_memory *mem)
VM_OBJECT_LOCK(mem->am_obj);
for (i = 0; i < mem->am_size; i += PAGE_SIZE) {
m = vm_page_lookup(mem->am_obj, atop(i));
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_unwire(m, 0);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
}
VM_OBJECT_UNLOCK(mem->am_obj);
diff --git a/sys/dev/agp/agp_i810.c b/sys/dev/agp/agp_i810.c
index 95a9cc4..ff3ad1c 100644
--- a/sys/dev/agp/agp_i810.c
+++ b/sys/dev/agp/agp_i810.c
@@ -1010,10 +1010,10 @@ agp_i810_free_memory(device_t dev, struct agp_memory *mem)
VM_OBJECT_LOCK(mem->am_obj);
m = vm_page_lookup(mem->am_obj, 0);
- VM_OBJECT_UNLOCK(mem->am_obj);
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_unwire(m, 0);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
+ VM_OBJECT_UNLOCK(mem->am_obj);
} else {
contigfree(sc->argb_cursor, mem->am_size, M_AGP);
sc->argb_cursor = NULL;
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 5d39968..1aa719e 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -111,6 +111,7 @@ static struct {
#define AHCI_Q_EDGEIS 64
#define AHCI_Q_SATA2 128
#define AHCI_Q_NOBSYRES 256
+#define AHCI_Q_NOAA 512
} ahci_ids[] = {
{0x43801002, 0x00, "ATI IXP600", 0},
{0x43901002, 0x00, "ATI IXP700", 0},
@@ -167,75 +168,75 @@ static struct {
{0x614511ab, 0x00, "Marvell 88SX6145", AHCI_Q_NOFORCE|AHCI_Q_4CH|AHCI_Q_EDGEIS},
{0x91231b4b, 0x11, "Marvell 88SE912x", AHCI_Q_NOBSYRES},
{0x91231b4b, 0x00, "Marvell 88SE912x", AHCI_Q_EDGEIS|AHCI_Q_SATA2|AHCI_Q_NOBSYRES},
- {0x044c10de, 0x00, "NVIDIA MCP65", 0},
- {0x044d10de, 0x00, "NVIDIA MCP65", 0},
- {0x044e10de, 0x00, "NVIDIA MCP65", 0},
- {0x044f10de, 0x00, "NVIDIA MCP65", 0},
- {0x045c10de, 0x00, "NVIDIA MCP65", 0},
- {0x045d10de, 0x00, "NVIDIA MCP65", 0},
- {0x045e10de, 0x00, "NVIDIA MCP65", 0},
- {0x045f10de, 0x00, "NVIDIA MCP65", 0},
- {0x055010de, 0x00, "NVIDIA MCP67", 0},
- {0x055110de, 0x00, "NVIDIA MCP67", 0},
- {0x055210de, 0x00, "NVIDIA MCP67", 0},
- {0x055310de, 0x00, "NVIDIA MCP67", 0},
- {0x055410de, 0x00, "NVIDIA MCP67", 0},
- {0x055510de, 0x00, "NVIDIA MCP67", 0},
- {0x055610de, 0x00, "NVIDIA MCP67", 0},
- {0x055710de, 0x00, "NVIDIA MCP67", 0},
- {0x055810de, 0x00, "NVIDIA MCP67", 0},
- {0x055910de, 0x00, "NVIDIA MCP67", 0},
- {0x055A10de, 0x00, "NVIDIA MCP67", 0},
- {0x055B10de, 0x00, "NVIDIA MCP67", 0},
- {0x058410de, 0x00, "NVIDIA MCP67", 0},
- {0x07f010de, 0x00, "NVIDIA MCP73", 0},
- {0x07f110de, 0x00, "NVIDIA MCP73", 0},
- {0x07f210de, 0x00, "NVIDIA MCP73", 0},
- {0x07f310de, 0x00, "NVIDIA MCP73", 0},
- {0x07f410de, 0x00, "NVIDIA MCP73", 0},
- {0x07f510de, 0x00, "NVIDIA MCP73", 0},
- {0x07f610de, 0x00, "NVIDIA MCP73", 0},
- {0x07f710de, 0x00, "NVIDIA MCP73", 0},
- {0x07f810de, 0x00, "NVIDIA MCP73", 0},
- {0x07f910de, 0x00, "NVIDIA MCP73", 0},
- {0x07fa10de, 0x00, "NVIDIA MCP73", 0},
- {0x07fb10de, 0x00, "NVIDIA MCP73", 0},
- {0x0ad010de, 0x00, "NVIDIA MCP77", 0},
- {0x0ad110de, 0x00, "NVIDIA MCP77", 0},
- {0x0ad210de, 0x00, "NVIDIA MCP77", 0},
- {0x0ad310de, 0x00, "NVIDIA MCP77", 0},
- {0x0ad410de, 0x00, "NVIDIA MCP77", 0},
- {0x0ad510de, 0x00, "NVIDIA MCP77", 0},
- {0x0ad610de, 0x00, "NVIDIA MCP77", 0},
- {0x0ad710de, 0x00, "NVIDIA MCP77", 0},
- {0x0ad810de, 0x00, "NVIDIA MCP77", 0},
- {0x0ad910de, 0x00, "NVIDIA MCP77", 0},
- {0x0ada10de, 0x00, "NVIDIA MCP77", 0},
- {0x0adb10de, 0x00, "NVIDIA MCP77", 0},
- {0x0ab410de, 0x00, "NVIDIA MCP79", 0},
- {0x0ab510de, 0x00, "NVIDIA MCP79", 0},
- {0x0ab610de, 0x00, "NVIDIA MCP79", 0},
- {0x0ab710de, 0x00, "NVIDIA MCP79", 0},
- {0x0ab810de, 0x00, "NVIDIA MCP79", 0},
- {0x0ab910de, 0x00, "NVIDIA MCP79", 0},
- {0x0aba10de, 0x00, "NVIDIA MCP79", 0},
- {0x0abb10de, 0x00, "NVIDIA MCP79", 0},
- {0x0abc10de, 0x00, "NVIDIA MCP79", 0},
- {0x0abd10de, 0x00, "NVIDIA MCP79", 0},
- {0x0abe10de, 0x00, "NVIDIA MCP79", 0},
- {0x0abf10de, 0x00, "NVIDIA MCP79", 0},
- {0x0d8410de, 0x00, "NVIDIA MCP89", 0},
- {0x0d8510de, 0x00, "NVIDIA MCP89", 0},
- {0x0d8610de, 0x00, "NVIDIA MCP89", 0},
- {0x0d8710de, 0x00, "NVIDIA MCP89", 0},
- {0x0d8810de, 0x00, "NVIDIA MCP89", 0},
- {0x0d8910de, 0x00, "NVIDIA MCP89", 0},
- {0x0d8a10de, 0x00, "NVIDIA MCP89", 0},
- {0x0d8b10de, 0x00, "NVIDIA MCP89", 0},
- {0x0d8c10de, 0x00, "NVIDIA MCP89", 0},
- {0x0d8d10de, 0x00, "NVIDIA MCP89", 0},
- {0x0d8e10de, 0x00, "NVIDIA MCP89", 0},
- {0x0d8f10de, 0x00, "NVIDIA MCP89", 0},
+ {0x044c10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
+ {0x044d10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
+ {0x044e10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
+ {0x044f10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
+ {0x045c10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
+ {0x045d10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
+ {0x045e10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
+ {0x045f10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
+ {0x055010de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x055110de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x055210de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x055310de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x055410de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x055510de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x055610de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x055710de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x055810de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x055910de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x055A10de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x055B10de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x058410de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
+ {0x07f010de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x07f110de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x07f210de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x07f310de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x07f410de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x07f510de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x07f610de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x07f710de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x07f810de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x07f910de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x07fa10de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x07fb10de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
+ {0x0ad010de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0ad110de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0ad210de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0ad310de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0ad410de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0ad510de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0ad610de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0ad710de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0ad810de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0ad910de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0ada10de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0adb10de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
+ {0x0ab410de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0ab510de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0ab610de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0ab710de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0ab810de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0ab910de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0aba10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0abb10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0abc10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0abd10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0abe10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0abf10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
+ {0x0d8410de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8510de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8610de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8710de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8810de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8910de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8a10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8b10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8c10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8d10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8e10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8f10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x33491106, 0x00, "VIA VT8251", 0},
{0x62871106, 0x00, "VIA VT8251", 0},
{0x11841039, 0x00, "SiS 966", 0},
@@ -339,6 +340,7 @@ ahci_attach(device_t dev)
rman_fini(&ctlr->sc_iomem);
return (error);
}
+ pci_enable_busmaster(dev);
/* Reset controller */
if ((error = ahci_ctlr_reset(dev)) != 0) {
bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
@@ -860,7 +862,14 @@ ahci_ch_attach(device_t dev)
ch->user[i].mode = 0;
ch->user[i].bytecount = 8192;
ch->user[i].tags = ch->numslots;
+ ch->user[i].caps = 0;
ch->curr[i] = ch->user[i];
+ if (ch->pm_level) {
+ ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ |
+ CTS_SATA_CAPS_H_APST |
+ CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST;
+ }
+ ch->user[i].caps |= CTS_SATA_CAPS_H_DMAAA;
}
rid = ch->unit;
if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -1960,7 +1969,8 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
et != AHCI_ERR_TIMEOUT)
ahci_rearm_timeout(dev);
/* Start PM timer. */
- if (ch->numrslots == 0 && ch->pm_level > 3) {
+ if (ch->numrslots == 0 && ch->pm_level > 3 &&
+ (ch->curr[ch->pm_present ? 15 : 0].caps & CTS_SATA_CAPS_D_PMREQ)) {
callout_schedule(&ch->pm_timer,
(ch->pm_level == 4) ? hz / 1000 : hz / 8);
}
@@ -2083,6 +2093,7 @@ ahci_start(device_t dev, int fbs)
}
/* Start operations on this channel */
cmd = ATA_INL(ch->r_mem, AHCI_P_CMD);
+ cmd &= ~AHCI_P_CMD_PMA;
ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd | AHCI_P_CMD_ST |
(ch->pm_present ? AHCI_P_CMD_PMA : 0));
}
@@ -2381,6 +2392,24 @@ ahci_sata_phy_reset(device_t dev)
return (1);
}
+static int
+ahci_check_ids(device_t dev, union ccb *ccb)
+{
+ struct ahci_channel *ch = device_get_softc(dev);
+
+ if (ccb->ccb_h.target_id > ((ch->caps & AHCI_CAP_SPM) ? 15 : 0)) {
+ ccb->ccb_h.status = CAM_TID_INVALID;
+ xpt_done(ccb);
+ return (-1);
+ }
+ if (ccb->ccb_h.target_lun != 0) {
+ ccb->ccb_h.status = CAM_LUN_INVALID;
+ xpt_done(ccb);
+ return (-1);
+ }
+ return (0);
+}
+
static void
ahciaction(struct cam_sim *sim, union ccb *ccb)
{
@@ -2396,9 +2425,12 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
/* Common cases first */
case XPT_ATA_IO: /* Execute the requested I/O operation */
case XPT_SCSI_IO:
- if (ch->devices == 0) {
+ if (ahci_check_ids(dev, ccb))
+ return;
+ if (ch->devices == 0 ||
+ (ch->pm_present == 0 &&
+ ccb->ccb_h.target_id > 0 && ccb->ccb_h.target_id < 15)) {
ccb->ccb_h.status = CAM_SEL_TIMEOUT;
- xpt_done(ccb);
break;
}
/* Check for command collision. */
@@ -2410,7 +2442,7 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
return;
}
ahci_begin_transaction(dev, ccb);
- break;
+ return;
case XPT_EN_LUN: /* Enable LUN as a target */
case XPT_TARGET_IO: /* Execute target I/O request */
case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
@@ -2418,13 +2450,14 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
case XPT_ABORT: /* Abort the specified CCB */
/* XXX Implement */
ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
break;
case XPT_SET_TRAN_SETTINGS:
{
struct ccb_trans_settings *cts = &ccb->cts;
struct ahci_device *d;
+ if (ahci_check_ids(dev, ccb))
+ return;
if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
d = &ch->curr[ccb->ccb_h.target_id];
else
@@ -2441,8 +2474,9 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
ch->pm_present = cts->xport_specific.sata.pm_present;
if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI)
d->atapi = cts->xport_specific.sata.atapi;
+ if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
+ d->caps = cts->xport_specific.sata.caps;
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
}
case XPT_GET_TRAN_SETTINGS:
@@ -2452,6 +2486,8 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
struct ahci_device *d;
uint32_t status;
+ if (ahci_check_ids(dev, ccb))
+ return;
if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
d = &ch->curr[ccb->ccb_h.target_id];
else
@@ -2472,9 +2508,24 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
cts->xport_specific.sata.valid |=
CTS_SATA_VALID_REVISION;
}
+ cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
+ if (ch->pm_level) {
+ if (ch->caps & (AHCI_CAP_PSC | AHCI_CAP_SSC))
+ cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
+ if (ch->caps2 & AHCI_CAP2_APST)
+ cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_APST;
+ }
+ if ((ch->caps & AHCI_CAP_SNCQ) &&
+ (ch->quirks & AHCI_Q_NOAA) == 0)
+ cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_DMAAA;
+ cts->xport_specific.sata.caps &=
+ ch->user[ccb->ccb_h.target_id].caps;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
} else {
cts->xport_specific.sata.revision = d->revision;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
+ cts->xport_specific.sata.caps = d->caps;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
}
cts->xport_specific.sata.mode = d->mode;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE;
@@ -2487,48 +2538,16 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
cts->xport_specific.sata.atapi = d->atapi;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI;
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
}
-#if 0
- case XPT_CALC_GEOMETRY:
- {
- struct ccb_calc_geometry *ccg;
- uint32_t size_mb;
- uint32_t secs_per_cylinder;
-
- ccg = &ccb->ccg;
- size_mb = ccg->volume_size
- / ((1024L * 1024L) / ccg->block_size);
- if (size_mb >= 1024 && (aha->extended_trans != 0)) {
- if (size_mb >= 2048) {
- ccg->heads = 255;
- ccg->secs_per_track = 63;
- } else {
- ccg->heads = 128;
- ccg->secs_per_track = 32;
- }
- } else {
- ccg->heads = 64;
- ccg->secs_per_track = 32;
- }
- secs_per_cylinder = ccg->heads * ccg->secs_per_track;
- ccg->cylinders = ccg->volume_size / secs_per_cylinder;
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
- }
-#endif
case XPT_RESET_BUS: /* Reset the specified SCSI bus */
case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
ahci_reset(dev);
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
case XPT_TERM_IO: /* Terminate the I/O process */
/* XXX Implement */
ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
break;
case XPT_PATH_INQ: /* Path routing inquiry */
{
@@ -2564,14 +2583,13 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
if (pci_get_devid(device_get_parent(dev)) == 0x43801002)
cpi->maxio = min(cpi->maxio, 128 * 512);
cpi->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
}
default:
ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
break;
}
+ xpt_done(ccb);
}
static void
diff --git a/sys/dev/ahci/ahci.h b/sys/dev/ahci/ahci.h
index d4c73c9..1473962 100644
--- a/sys/dev/ahci/ahci.h
+++ b/sys/dev/ahci/ahci.h
@@ -372,6 +372,7 @@ struct ahci_device {
u_int bytecount;
u_int atapi;
u_int tags;
+ u_int caps;
};
/* structure describing an ATA channel */
diff --git a/sys/dev/ale/if_ale.c b/sys/dev/ale/if_ale.c
index b3e7187..ea6b53b 100644
--- a/sys/dev/ale/if_ale.c
+++ b/sys/dev/ale/if_ale.c
@@ -1585,7 +1585,7 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head)
struct tcphdr *tcp;
bus_dma_segment_t txsegs[ALE_MAXTXSEGS];
bus_dmamap_t map;
- uint32_t cflags, ip_off, poff, vtag;
+ uint32_t cflags, hdrlen, ip_off, poff, vtag;
int error, i, nsegs, prod, si;
ALE_LOCK_ASSERT(sc);
@@ -1678,6 +1678,11 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head)
return (ENOBUFS);
}
tcp = (struct tcphdr *)(mtod(m, char *) + poff);
+ m = m_pullup(m, poff + (tcp->th_off << 2));
+ if (m == NULL) {
+ *m_head = NULL;
+ return (ENOBUFS);
+ }
/*
* AR81xx requires IP/TCP header size and offset as
* well as TCP pseudo checksum which complicates
@@ -1730,7 +1735,7 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head)
}
/* Check descriptor overrun. */
- if (sc->ale_cdata.ale_tx_cnt + nsegs >= ALE_TX_RING_CNT - 2) {
+ if (sc->ale_cdata.ale_tx_cnt + nsegs >= ALE_TX_RING_CNT - 3) {
bus_dmamap_unload(sc->ale_cdata.ale_tx_tag, map);
return (ENOBUFS);
}
@@ -1782,8 +1787,32 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head)
cflags |= ALE_TD_INSERT_VLAN_TAG;
}
- desc = NULL;
- for (i = 0; i < nsegs; i++) {
+ i = 0;
+ if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
+ /*
+ * Make sure the first fragment contains
+ * only ethernet and IP/TCP header with options.
+ */
+ hdrlen = poff + (tcp->th_off << 2);
+ desc = &sc->ale_cdata.ale_tx_ring[prod];
+ desc->addr = htole64(txsegs[i].ds_addr);
+ desc->len = htole32(ALE_TX_BYTES(hdrlen) | vtag);
+ desc->flags = htole32(cflags);
+ sc->ale_cdata.ale_tx_cnt++;
+ ALE_DESC_INC(prod, ALE_TX_RING_CNT);
+ if (m->m_len - hdrlen > 0) {
+ /* Handle remaining payload of the first fragment. */
+ desc = &sc->ale_cdata.ale_tx_ring[prod];
+ desc->addr = htole64(txsegs[i].ds_addr + hdrlen);
+ desc->len = htole32(ALE_TX_BYTES(m->m_len - hdrlen) |
+ vtag);
+ desc->flags = htole32(cflags);
+ sc->ale_cdata.ale_tx_cnt++;
+ ALE_DESC_INC(prod, ALE_TX_RING_CNT);
+ }
+ i = 1;
+ }
+ for (; i < nsegs; i++) {
desc = &sc->ale_cdata.ale_tx_ring[prod];
desc->addr = htole64(txsegs[i].ds_addr);
desc->len = htole32(ALE_TX_BYTES(txsegs[i].ds_len) | vtag);
diff --git a/sys/dev/an/if_an.c b/sys/dev/an/if_an.c
index 6d9ef96..645fe41 100644
--- a/sys/dev/an/if_an.c
+++ b/sys/dev/an/if_an.c
@@ -767,8 +767,8 @@ an_attach(struct an_softc *sc, int flags)
ifp->if_start = an_start;
ifp->if_init = an_init;
ifp->if_baudrate = 10000000;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename));
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 73dfa94..5c6f0db 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -1430,6 +1430,24 @@ ata_cam_end_transaction(device_t dev, struct ata_request *request)
ata_reinit(dev);
}
+static int
+ata_check_ids(device_t dev, union ccb *ccb)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+
+ if (ccb->ccb_h.target_id > ((ch->flags & ATA_NO_SLAVE) ? 0 : 1)) {
+ ccb->ccb_h.status = CAM_TID_INVALID;
+ xpt_done(ccb);
+ return (-1);
+ }
+ if (ccb->ccb_h.target_lun != 0) {
+ ccb->ccb_h.status = CAM_LUN_INVALID;
+ xpt_done(ccb);
+ return (-1);
+ }
+ return (0);
+}
+
static void
ataaction(struct cam_sim *sim, union ccb *ccb)
{
@@ -1445,10 +1463,11 @@ ataaction(struct cam_sim *sim, union ccb *ccb)
/* Common cases first */
case XPT_ATA_IO: /* Execute the requested I/O operation */
case XPT_SCSI_IO:
+ if (ata_check_ids(dev, ccb))
+ return;
if ((ch->devices & ((ATA_ATA_MASTER | ATA_ATAPI_MASTER)
<< ccb->ccb_h.target_id)) == 0) {
ccb->ccb_h.status = CAM_SEL_TIMEOUT;
- xpt_done(ccb);
break;
}
if (ch->running)
@@ -1467,11 +1486,10 @@ ataaction(struct cam_sim *sim, union ccb *ccb)
res->lba_mid = 0x14;
}
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
}
ata_cam_begin_transaction(dev, ccb);
- break;
+ return;
case XPT_EN_LUN: /* Enable LUN as a target */
case XPT_TARGET_IO: /* Execute target I/O request */
case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
@@ -1479,13 +1497,14 @@ ataaction(struct cam_sim *sim, union ccb *ccb)
case XPT_ABORT: /* Abort the specified CCB */
/* XXX Implement */
ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
break;
case XPT_SET_TRAN_SETTINGS:
{
struct ccb_trans_settings *cts = &ccb->cts;
struct ata_cam_device *d;
+ if (ata_check_ids(dev, ccb))
+ return;
if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
d = &ch->curr[ccb->ccb_h.target_id];
else
@@ -1520,7 +1539,6 @@ ataaction(struct cam_sim *sim, union ccb *ccb)
d->atapi = cts->xport_specific.ata.atapi;
}
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
}
case XPT_GET_TRAN_SETTINGS:
@@ -1528,6 +1546,8 @@ ataaction(struct cam_sim *sim, union ccb *ccb)
struct ccb_trans_settings *cts = &ccb->cts;
struct ata_cam_device *d;
+ if (ata_check_ids(dev, ccb))
+ return;
if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
d = &ch->curr[ccb->ccb_h.target_id];
else
@@ -1567,48 +1587,16 @@ ataaction(struct cam_sim *sim, union ccb *ccb)
cts->xport_specific.ata.valid |= CTS_ATA_VALID_ATAPI;
}
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
}
-#if 0
- case XPT_CALC_GEOMETRY:
- {
- struct ccb_calc_geometry *ccg;
- uint32_t size_mb;
- uint32_t secs_per_cylinder;
-
- ccg = &ccb->ccg;
- size_mb = ccg->volume_size
- / ((1024L * 1024L) / ccg->block_size);
- if (size_mb >= 1024 && (aha->extended_trans != 0)) {
- if (size_mb >= 2048) {
- ccg->heads = 255;
- ccg->secs_per_track = 63;
- } else {
- ccg->heads = 128;
- ccg->secs_per_track = 32;
- }
- } else {
- ccg->heads = 64;
- ccg->secs_per_track = 32;
- }
- secs_per_cylinder = ccg->heads * ccg->secs_per_track;
- ccg->cylinders = ccg->volume_size / secs_per_cylinder;
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
- }
-#endif
case XPT_RESET_BUS: /* Reset the specified SCSI bus */
case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
ata_reinit(dev);
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
case XPT_TERM_IO: /* Terminate the I/O process */
/* XXX Implement */
ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
break;
case XPT_PATH_INQ: /* Path routing inquiry */
{
@@ -1643,14 +1631,13 @@ ataaction(struct cam_sim *sim, union ccb *ccb)
cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
cpi->maxio = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
cpi->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
}
default:
ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
break;
}
+ xpt_done(ccb);
}
static void
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c b/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c
index fc937ea..8e6341a 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c
@@ -283,6 +283,14 @@ ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode,
regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0);
regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange,
regWrites);
+#ifdef AH_RXCFG_SDMAMW_4BYTES
+ /*
+ * Nala doesn't work with 128 byte bursts on pb42(hydra) (ar71xx),
+ * use 4 instead. Enabling it on all platforms would hurt performance,
+ * so we only enable it on the ones that are affected by it.
+ */
+ OS_REG_WRITE(ah, AR_RXCFG, 0);
+#endif
ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);
OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 5847489..15765f2 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -562,8 +562,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
ifp->if_start = ath_start;
ifp->if_ioctl = ath_ioctl;
ifp->if_init = ath_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
diff --git a/sys/dev/atkbdc/atkbdc.c b/sys/dev/atkbdc/atkbdc.c
index df1f28e..f8e856a 100644
--- a/sys/dev/atkbdc/atkbdc.c
+++ b/sys/dev/atkbdc/atkbdc.c
@@ -44,6 +44,10 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <sys/rman.h>
+#if defined(__amd64__)
+#include <machine/clock.h>
+#endif
+
#include <dev/atkbdc/atkbdcreg.h>
#ifdef __sparc64__
@@ -153,7 +157,7 @@ atkbdc_configure(void)
bus_space_tag_t tag;
bus_space_handle_t h0;
bus_space_handle_t h1;
-#if defined(__i386__)
+#if defined(__i386__) || defined(__amd64__)
volatile int i;
register_t flags;
#endif
@@ -222,7 +226,7 @@ atkbdc_configure(void)
#endif
#endif
-#if defined(__i386__)
+#if defined(__i386__) || defined(__amd64__)
/*
* Check if we really have AT keyboard controller. Poll status
* register until we get "all clear" indication. If no such
@@ -248,6 +252,11 @@ static int
atkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag, bus_space_handle_t h0,
bus_space_handle_t h1)
{
+#if defined(__amd64__)
+ u_int64_t tscval[3], read_delay;
+ register_t flags;
+#endif
+
if (sc->ioh0 == 0) { /* XXX */
sc->command_byte = -1;
sc->command_mask = 0;
@@ -264,6 +273,33 @@ atkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag, bus_space_handle_t h0,
sc->iot = tag;
sc->ioh0 = h0;
sc->ioh1 = h1;
+
+#if defined(__amd64__)
+ /*
+ * On certain chipsets AT keyboard controller isn't present and is
+ * emulated by BIOS using SMI interrupt. On those chipsets reading
+ * from the status port may be thousand times slower than usually.
+ * Sometimes this emilation is not working properly resulting in
+ * commands timing our and since we assume that inb() operation
+ * takes very little time to complete we need to adjust number of
+ * retries to keep waiting time within a designed limits (100ms).
+ * Measure time it takes to make read_status() call and adjust
+ * number of retries accordingly.
+ */
+ flags = intr_disable();
+ tscval[0] = rdtsc();
+ read_status(sc);
+ tscval[1] = rdtsc();
+ DELAY(1000);
+ tscval[2] = rdtsc();
+ intr_restore(flags);
+ read_delay = tscval[1] - tscval[0];
+ read_delay /= (tscval[2] - tscval[1]) / 1000;
+ sc->retry = 100000 / ((KBDD_DELAYTIME * 2) + read_delay);
+#else
+ sc->retry = 5000;
+#endif
+
return 0;
}
@@ -380,10 +416,12 @@ removeq(kqueue *q)
static int
wait_while_controller_busy(struct atkbdc_softc *kbdc)
{
- /* CPU will stay inside the loop for 100msec at most */
- int retry = 5000;
+ int retry;
int f;
+ /* CPU will stay inside the loop for 100msec at most */
+ retry = kbdc->retry;
+
while ((f = read_status(kbdc)) & KBDS_INPUT_BUFFER_FULL) {
if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
DELAY(KBDD_DELAYTIME);
@@ -406,10 +444,12 @@ wait_while_controller_busy(struct atkbdc_softc *kbdc)
static int
wait_for_data(struct atkbdc_softc *kbdc)
{
- /* CPU will stay inside the loop for 200msec at most */
- int retry = 10000;
+ int retry;
int f;
+ /* CPU will stay inside the loop for 200msec at most */
+ retry = kbdc->retry * 2;
+
while ((f = read_status(kbdc) & KBDS_ANY_BUFFER_FULL) == 0) {
DELAY(KBDC_DELAYTIME);
if (--retry < 0)
@@ -423,10 +463,12 @@ wait_for_data(struct atkbdc_softc *kbdc)
static int
wait_for_kbd_data(struct atkbdc_softc *kbdc)
{
- /* CPU will stay inside the loop for 200msec at most */
- int retry = 10000;
+ int retry;
int f;
+ /* CPU will stay inside the loop for 200msec at most */
+ retry = kbdc->retry * 2;
+
while ((f = read_status(kbdc) & KBDS_BUFFER_FULL)
!= KBDS_KBD_BUFFER_FULL) {
if (f == KBDS_AUX_BUFFER_FULL) {
@@ -448,11 +490,13 @@ wait_for_kbd_data(struct atkbdc_softc *kbdc)
static int
wait_for_kbd_ack(struct atkbdc_softc *kbdc)
{
- /* CPU will stay inside the loop for 200msec at most */
- int retry = 10000;
+ int retry;
int f;
int b;
+ /* CPU will stay inside the loop for 200msec at most */
+ retry = kbdc->retry * 2;
+
while (retry-- > 0) {
if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) {
DELAY(KBDD_DELAYTIME);
@@ -475,10 +519,12 @@ wait_for_kbd_ack(struct atkbdc_softc *kbdc)
static int
wait_for_aux_data(struct atkbdc_softc *kbdc)
{
- /* CPU will stay inside the loop for 200msec at most */
- int retry = 10000;
+ int retry;
int f;
+ /* CPU will stay inside the loop for 200msec at most */
+ retry = kbdc->retry * 2;
+
while ((f = read_status(kbdc) & KBDS_BUFFER_FULL)
!= KBDS_AUX_BUFFER_FULL) {
if (f == KBDS_KBD_BUFFER_FULL) {
@@ -500,11 +546,13 @@ wait_for_aux_data(struct atkbdc_softc *kbdc)
static int
wait_for_aux_ack(struct atkbdc_softc *kbdc)
{
- /* CPU will stay inside the loop for 200msec at most */
- int retry = 10000;
+ int retry;
int f;
int b;
+ /* CPU will stay inside the loop for 200msec at most */
+ retry = kbdc->retry * 2;
+
while (retry-- > 0) {
if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) {
DELAY(KBDD_DELAYTIME);
diff --git a/sys/dev/atkbdc/atkbdc_ebus.c b/sys/dev/atkbdc/atkbdc_ebus.c
index 639203d..0dcb0a7 100644
--- a/sys/dev/atkbdc/atkbdc_ebus.c
+++ b/sys/dev/atkbdc/atkbdc_ebus.c
@@ -202,6 +202,7 @@ atkbdc_ebus_attach(device_t dev)
"cannot determine command/data port resource\n");
return (ENXIO);
}
+ sc->retry = 5000;
sc->port0 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start,
1, RF_ACTIVE);
if (sc->port0 == NULL) {
diff --git a/sys/dev/atkbdc/atkbdc_isa.c b/sys/dev/atkbdc/atkbdc_isa.c
index 975d299..10e172f 100644
--- a/sys/dev/atkbdc/atkbdc_isa.c
+++ b/sys/dev/atkbdc/atkbdc_isa.c
@@ -94,7 +94,7 @@ atkbdc_isa_probe(device_t dev)
u_long count;
int error;
int rid;
-#if defined(__i386__)
+#if defined(__i386__) || defined(__amd64__)
bus_space_tag_t tag;
bus_space_handle_t ioh1;
volatile int i;
@@ -141,7 +141,7 @@ atkbdc_isa_probe(device_t dev)
return ENXIO;
}
-#if defined(__i386__)
+#if defined(__i386__) || defined(__amd64__)
/*
* Check if we really have AT keyboard controller. Poll status
* register until we get "all clear" indication. If no such
@@ -161,6 +161,8 @@ atkbdc_isa_probe(device_t dev)
if (i == 65535) {
bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);
+ if (bootverbose)
+ device_printf(dev, "AT keyboard controller not found\n");
return ENXIO;
}
#endif
@@ -201,6 +203,7 @@ atkbdc_isa_attach(device_t dev)
}
rid = 0;
+ sc->retry = 5000;
sc->port0 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
RF_ACTIVE);
if (sc->port0 == NULL)
diff --git a/sys/dev/atkbdc/atkbdcreg.h b/sys/dev/atkbdc/atkbdcreg.h
index 0715d9e..7ea26a6 100644
--- a/sys/dev/atkbdc/atkbdcreg.h
+++ b/sys/dev/atkbdc/atkbdcreg.h
@@ -200,6 +200,7 @@ typedef struct atkbdc_softc {
int lock; /* FIXME: XXX not quite a semaphore... */
kqueue kbd; /* keyboard data queue */
kqueue aux; /* auxiliary data queue */
+ int retry;
} atkbdc_softc_t;
enum kbdc_device_ivar {
diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c
index 2ad5ab2..6608dbd 100644
--- a/sys/dev/bce/if_bce.c
+++ b/sys/dev/bce/if_bce.c
@@ -303,7 +303,7 @@ static void bce_dump_txbd (struct bce_softc *,
static void bce_dump_rxbd (struct bce_softc *,
int, struct rx_bd *);
#ifdef BCE_JUMBO_HDRSPLIT
-static void bce_dump_pgbd (struct bce_softc *,
+static void bce_dump_pgbd (struct bce_softc *,
int, struct rx_bd *);
#endif
static void bce_dump_l2fhdr (struct bce_softc *,
@@ -368,7 +368,7 @@ static int bce_nvram_write (struct bce_softc *, u32, u8 *, int);
/****************************************************************************/
static void bce_get_media (struct bce_softc *);
static void bce_init_media (struct bce_softc *);
-static void bce_dma_map_addr (void *,
+static void bce_dma_map_addr (void *,
bus_dma_segment_t *, int, int);
static int bce_dma_alloc (device_t);
static void bce_dma_free (struct bce_softc *);
@@ -379,7 +379,7 @@ static void bce_release_resources (struct bce_softc *);
/****************************************************************************/
static int bce_fw_sync (struct bce_softc *, u32);
static void bce_load_rv2p_fw (struct bce_softc *, u32 *, u32, u32);
-static void bce_load_cpu_fw (struct bce_softc *,
+static void bce_load_cpu_fw (struct bce_softc *,
struct cpu_reg *, struct fw_info *);
static void bce_start_cpu (struct bce_softc *, struct cpu_reg *);
static void bce_halt_cpu (struct bce_softc *, struct cpu_reg *);
@@ -401,21 +401,21 @@ static int bce_blockinit (struct bce_softc *);
static int bce_init_tx_chain (struct bce_softc *);
static void bce_free_tx_chain (struct bce_softc *);
-static int bce_get_rx_buf (struct bce_softc *,
+static int bce_get_rx_buf (struct bce_softc *,
struct mbuf *, u16 *, u16 *, u32 *);
static int bce_init_rx_chain (struct bce_softc *);
static void bce_fill_rx_chain (struct bce_softc *);
static void bce_free_rx_chain (struct bce_softc *);
#ifdef BCE_JUMBO_HDRSPLIT
-static int bce_get_pg_buf (struct bce_softc *,
+static int bce_get_pg_buf (struct bce_softc *,
struct mbuf *, u16 *, u16 *);
static int bce_init_pg_chain (struct bce_softc *);
static void bce_fill_pg_chain (struct bce_softc *);
static void bce_free_pg_chain (struct bce_softc *);
#endif
-static struct mbuf *bce_tso_setup (struct bce_softc *,
+static struct mbuf *bce_tso_setup (struct bce_softc *,
struct mbuf **, u16 *);
static int bce_tx_encap (struct bce_softc *, struct mbuf **);
static void bce_start_locked (struct ifnet *);
@@ -566,7 +566,7 @@ bce_probe(device_t dev)
/* Print out the device identity. */
snprintf(descbuf, BCE_DEVDESC_MAX, "%s (%c%d)",
- t->bce_name, (((pci_read_config(dev,
+ t->bce_name, (((pci_read_config(dev,
PCIR_REVID, 4) & 0xf0) >> 4) + 'A'),
(pci_read_config(dev, PCIR_REVID, 4) & 0xf));
@@ -593,57 +593,60 @@ bce_probe(device_t dev)
static void
bce_print_adapter_info(struct bce_softc *sc)
{
- int i = 0;
+ int i = 0;
DBENTER(BCE_VERBOSE_LOAD);
- BCE_PRINTF("ASIC (0x%08X); ", sc->bce_chipid);
- printf("Rev (%c%d); ", ((BCE_CHIP_ID(sc) & 0xf000) >> 12) + 'A',
- ((BCE_CHIP_ID(sc) & 0x0ff0) >> 4));
+ if (bootverbose) {
+ BCE_PRINTF("ASIC (0x%08X); ", sc->bce_chipid);
+ printf("Rev (%c%d); ", ((BCE_CHIP_ID(sc) & 0xf000) >>
+ 12) + 'A', ((BCE_CHIP_ID(sc) & 0x0ff0) >> 4));
+
- /* Bus info. */
- if (sc->bce_flags & BCE_PCIE_FLAG) {
- printf("Bus (PCIe x%d, ", sc->link_width);
- switch (sc->link_speed) {
- case 1: printf("2.5Gbps); "); break;
- case 2: printf("5Gbps); "); break;
- default: printf("Unknown link speed); ");
+ /* Bus info. */
+ if (sc->bce_flags & BCE_PCIE_FLAG) {
+ printf("Bus (PCIe x%d, ", sc->link_width);
+ switch (sc->link_speed) {
+ case 1: printf("2.5Gbps); "); break;
+ case 2: printf("5Gbps); "); break;
+ default: printf("Unknown link speed); ");
+ }
+ } else {
+ printf("Bus (PCI%s, %s, %dMHz); ",
+ ((sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : ""),
+ ((sc->bce_flags & BCE_PCI_32BIT_FLAG) ?
+ "32-bit" : "64-bit"), sc->bus_speed_mhz);
}
- } else {
- printf("Bus (PCI%s, %s, %dMHz); ",
- ((sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : ""),
- ((sc->bce_flags & BCE_PCI_32BIT_FLAG) ?
- "32-bit" : "64-bit"), sc->bus_speed_mhz);
- }
- /* Firmware version and device features. */
- printf("B/C (%s); Flags (", sc->bce_bc_ver);
+ /* Firmware version and device features. */
+ printf("B/C (%s); Flags (", sc->bce_bc_ver);
-#ifdef BCE_JUMBO_HDRSPLIT
- printf("SPLT");
- i++;
-#endif
+ #ifdef BCE_JUMBO_HDRSPLIT
+ printf("SPLT");
+ i++;
+ #endif
- if (sc->bce_flags & BCE_USING_MSI_FLAG) {
- if (i > 0) printf("|");
- printf("MSI"); i++;
- }
+ if (sc->bce_flags & BCE_USING_MSI_FLAG) {
+ if (i > 0) printf("|");
+ printf("MSI"); i++;
+ }
- if (sc->bce_flags & BCE_USING_MSIX_FLAG) {
- if (i > 0) printf("|");
- printf("MSI-X"); i++;
- }
+ if (sc->bce_flags & BCE_USING_MSIX_FLAG) {
+ if (i > 0) printf("|");
+ printf("MSI-X"); i++;
+ }
- if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) {
- if (i > 0) printf("|");
- printf("2.5G"); i++;
- }
+ if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) {
+ if (i > 0) printf("|");
+ printf("2.5G"); i++;
+ }
- if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) {
- if (i > 0) printf("|");
- printf("MFW); MFW (%s)\n", sc->bce_mfw_ver);
- } else {
- printf(")\n");
+ if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) {
+ if (i > 0) printf("|");
+ printf("MFW); MFW (%s)\n", sc->bce_mfw_ver);
+ } else {
+ printf(")\n");
+ }
}
DBEXIT(BCE_VERBOSE_LOAD);
@@ -785,13 +788,13 @@ bce_attach(device_t dev)
(bce_msi_enable >= 1) && (sc->bce_msi_count == 0)) {
sc->bce_msi_count = 1;
if ((error = pci_alloc_msi(dev, &sc->bce_msi_count)) != 0) {
- BCE_PRINTF("%s(%d): MSI allocation failed! error = %d\n",
- __FILE__, __LINE__, error);
+ BCE_PRINTF("%s(%d): MSI allocation failed! "
+ "error = %d\n", __FILE__, __LINE__, error);
sc->bce_msi_count = 0;
pci_release_msi(dev);
} else {
- DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI interrupt.\n",
- __FUNCTION__);
+ DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI "
+ "interrupt.\n", __FUNCTION__);
sc->bce_flags |= BCE_USING_MSI_FLAG;
if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716))
@@ -848,10 +851,11 @@ bce_attach(device_t dev)
case BCE_CHIP_ID_5709_B0:
case BCE_CHIP_ID_5709_B1:
case BCE_CHIP_ID_5709_B2:
- BCE_PRINTF("%s(%d): Unsupported controller revision (%c%d)!\n",
- __FILE__, __LINE__,
- (((pci_read_config(dev, PCIR_REVID, 4) & 0xf0) >> 4) + 'A'),
- (pci_read_config(dev, PCIR_REVID, 4) & 0xf));
+ BCE_PRINTF("%s(%d): Unsupported controller "
+ "revision (%c%d)!\n", __FILE__, __LINE__,
+ (((pci_read_config(dev, PCIR_REVID, 4) &
+ 0xf0) >> 4) + 'A'), (pci_read_config(dev,
+ PCIR_REVID, 4) & 0xf));
rc = ENODEV;
goto bce_attach_fail;
}
@@ -1072,19 +1076,19 @@ bce_attach(device_t dev)
ifp = sc->bce_ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
BCE_PRINTF("%s(%d): Interface allocation failed!\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
rc = ENXIO;
goto bce_attach_fail;
}
/* Initialize the ifnet interface. */
- ifp->if_softc = sc;
+ ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = bce_ioctl;
- ifp->if_start = bce_start;
- ifp->if_init = bce_init;
- ifp->if_mtu = ETHERMTU;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_ioctl = bce_ioctl;
+ ifp->if_start = bce_start;
+ ifp->if_init = bce_init;
+ ifp->if_mtu = ETHERMTU;
if (bce_tso_enable) {
ifp->if_hwassist = BCE_IF_HWASSIST | CSUM_TSO;
@@ -1095,7 +1099,7 @@ bce_attach(device_t dev)
ifp->if_capabilities = BCE_IF_CAPABILITIES;
}
- ifp->if_capenable = ifp->if_capabilities;
+ ifp->if_capenable = ifp->if_capabilities;
/*
* Assume standard mbuf sizes for buffer allocation.
@@ -1105,16 +1109,17 @@ bce_attach(device_t dev)
#ifdef BCE_JUMBO_HDRSPLIT
sc->rx_bd_mbuf_alloc_size = MHLEN;
/* Make sure offset is 16 byte aligned for hardware. */
- sc->rx_bd_mbuf_align_pad = roundup2((MSIZE - MHLEN), 16) -
- (MSIZE - MHLEN);
- sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size -
- sc->rx_bd_mbuf_align_pad;
+ sc->rx_bd_mbuf_align_pad =
+ roundup2((MSIZE - MHLEN), 16) - (MSIZE - MHLEN);
+ sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size -
+ sc->rx_bd_mbuf_align_pad;
sc->pg_bd_mbuf_alloc_size = MCLBYTES;
#else
sc->rx_bd_mbuf_alloc_size = MCLBYTES;
- sc->rx_bd_mbuf_align_pad = roundup2(MCLBYTES, 16) - MCLBYTES;
- sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size -
- sc->rx_bd_mbuf_align_pad;
+ sc->rx_bd_mbuf_align_pad =
+ roundup2(MCLBYTES, 16) - MCLBYTES;
+ sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size -
+ sc->rx_bd_mbuf_align_pad;
#endif
ifp->if_snd.ifq_drv_maxlen = USABLE_TX_BD;
@@ -1126,14 +1131,14 @@ bce_attach(device_t dev)
else
ifp->if_baudrate = IF_Mbps(1000);
- /* Handle any special PHY initialization for SerDes PHYs. */
- bce_init_media(sc);
+ /* Handle any special PHY initialization for SerDes PHYs. */
+ bce_init_media(sc);
/* MII child bus by probing the PHY. */
if (mii_phy_probe(dev, &sc->bce_miibus, bce_ifmedia_upd,
bce_ifmedia_sts)) {
BCE_PRINTF("%s(%d): No PHY found on child MII bus!\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
rc = ENXIO;
goto bce_attach_fail;
}
@@ -1155,7 +1160,7 @@ bce_attach(device_t dev)
if (rc) {
BCE_PRINTF("%s(%d): Failed to setup IRQ!\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
bce_detach(dev);
goto bce_attach_exit;
}
@@ -1396,6 +1401,9 @@ bce_reg_wr_ind(struct bce_softc *sc, u32 offset, u32 val)
static void
bce_shmem_wr(struct bce_softc *sc, u32 offset, u32 val)
{
+ DBPRINT(sc, BCE_VERBOSE_FIRMWARE, "%s(): Writing 0x%08X to "
+ "0x%08X\n", __FUNCTION__, val, offset);
+
bce_reg_wr_ind(sc, sc->bce_shmem_base + offset, val);
}
@@ -1411,7 +1419,12 @@ bce_shmem_wr(struct bce_softc *sc, u32 offset, u32 val)
static u32
bce_shmem_rd(struct bce_softc *sc, u32 offset)
{
- return (bce_reg_rd_ind(sc, sc->bce_shmem_base + offset));
+ u32 val = bce_reg_rd_ind(sc, sc->bce_shmem_base + offset);
+
+ DBPRINT(sc, BCE_VERBOSE_FIRMWARE, "%s(): Reading 0x%08X from "
+ "0x%08X\n", __FUNCTION__, val, offset);
+
+ return val;
}
@@ -1430,9 +1443,9 @@ bce_ctx_rd(struct bce_softc *sc, u32 cid_addr, u32 ctx_offset)
{
u32 idx, offset, retry_cnt = 5, val;
- DBRUNIF((cid_addr > MAX_CID_ADDR || ctx_offset & 0x3 || cid_addr & CTX_MASK),
- BCE_PRINTF("%s(): Invalid CID address: 0x%08X.\n",
- __FUNCTION__, cid_addr));
+ DBRUNIF((cid_addr > MAX_CID_ADDR || ctx_offset & 0x3 ||
+ cid_addr & CTX_MASK), BCE_PRINTF("%s(): Invalid CID "
+ "address: 0x%08X.\n", __FUNCTION__, cid_addr));
offset = ctx_offset + cid_addr;
@@ -1450,8 +1463,8 @@ bce_ctx_rd(struct bce_softc *sc, u32 cid_addr, u32 ctx_offset)
if (val & BCE_CTX_CTX_CTRL_READ_REQ)
BCE_PRINTF("%s(%d); Unable to read CTX memory: "
- "cid_addr = 0x%08X, offset = 0x%08X!\n",
- __FILE__, __LINE__, cid_addr, ctx_offset);
+ "cid_addr = 0x%08X, offset = 0x%08X!\n",
+ __FILE__, __LINE__, cid_addr, ctx_offset);
val = REG_RD(sc, BCE_CTX_CTX_DATA);
} else {
@@ -1487,7 +1500,7 @@ bce_ctx_wr(struct bce_softc *sc, u32 cid_addr, u32 ctx_offset, u32 ctx_val)
DBRUNIF((cid_addr > MAX_CID_ADDR || ctx_offset & 0x3 || cid_addr & CTX_MASK),
BCE_PRINTF("%s(): Invalid CID address: 0x%08X.\n",
- __FUNCTION__, cid_addr));
+ __FUNCTION__, cid_addr));
if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
@@ -1504,8 +1517,8 @@ bce_ctx_wr(struct bce_softc *sc, u32 cid_addr, u32 ctx_offset, u32 ctx_val)
if (val & BCE_CTX_CTX_CTRL_WRITE_REQ)
BCE_PRINTF("%s(%d); Unable to write CTX memory: "
- "cid_addr = 0x%08X, offset = 0x%08X!\n",
- __FILE__, __LINE__, cid_addr, ctx_offset);
+ "cid_addr = 0x%08X, offset = 0x%08X!\n",
+ __FILE__, __LINE__, cid_addr, ctx_offset);
} else {
REG_WR(sc, BCE_CTX_DATA_ADR, offset);
@@ -1706,54 +1719,73 @@ bce_miibus_statchg(device_t dev)
val = REG_RD(sc, BCE_EMAC_MODE);
val &= ~(BCE_EMAC_MODE_PORT | BCE_EMAC_MODE_HALF_DUPLEX |
- BCE_EMAC_MODE_MAC_LOOP | BCE_EMAC_MODE_FORCE_LINK |
- BCE_EMAC_MODE_25G);
+ BCE_EMAC_MODE_MAC_LOOP | BCE_EMAC_MODE_FORCE_LINK |
+ BCE_EMAC_MODE_25G);
- /* Set MII or GMII interface based on the speed negotiated by the PHY. */
+ /* Set MII or GMII interface based on the PHY speed. */
switch (IFM_SUBTYPE(mii->mii_media_active)) {
case IFM_10_T:
if (BCE_CHIP_NUM(sc) != BCE_CHIP_NUM_5706) {
- DBPRINT(sc, BCE_INFO, "Enabling 10Mb interface.\n");
+ DBPRINT(sc, BCE_INFO_PHY,
+ "Enabling 10Mb interface.\n");
val |= BCE_EMAC_MODE_PORT_MII_10;
break;
}
/* fall-through */
case IFM_100_TX:
- DBPRINT(sc, BCE_INFO, "Enabling MII interface.\n");
+ DBPRINT(sc, BCE_INFO_PHY, "Enabling MII interface.\n");
val |= BCE_EMAC_MODE_PORT_MII;
break;
case IFM_2500_SX:
- DBPRINT(sc, BCE_INFO, "Enabling 2.5G MAC mode.\n");
+ DBPRINT(sc, BCE_INFO_PHY, "Enabling 2.5G MAC mode.\n");
val |= BCE_EMAC_MODE_25G;
/* fall-through */
case IFM_1000_T:
case IFM_1000_SX:
- DBPRINT(sc, BCE_INFO, "Enabling GMII interface.\n");
+ DBPRINT(sc, BCE_INFO_PHY, "Enabling GMII interface.\n");
val |= BCE_EMAC_MODE_PORT_GMII;
break;
default:
- DBPRINT(sc, BCE_INFO, "Unknown speed, enabling default GMII "
- "interface.\n");
+ DBPRINT(sc, BCE_INFO_PHY, "Unknown link speed, enabling "
+ "default GMII interface.\n");
val |= BCE_EMAC_MODE_PORT_GMII;
}
- /* Set half or full duplex based on the duplicity negotiated by the PHY. */
+ /* Set half or full duplex based on PHY settings. */
if ((mii->mii_media_active & IFM_GMASK) == IFM_HDX) {
- DBPRINT(sc, BCE_INFO, "Setting Half-Duplex interface.\n");
+ DBPRINT(sc, BCE_INFO_PHY,
+ "Setting Half-Duplex interface.\n");
val |= BCE_EMAC_MODE_HALF_DUPLEX;
} else
- DBPRINT(sc, BCE_INFO, "Setting Full-Duplex interface.\n");
+ DBPRINT(sc, BCE_INFO_PHY,
+ "Setting Full-Duplex interface.\n");
REG_WR(sc, BCE_EMAC_MODE, val);
-#if 0
- /* ToDo: Enable flow control support in brgphy and bge. */
/* FLAG0 is set if RX is enabled and FLAG1 if TX is enabled */
- if (mii->mii_media_active & IFM_FLAG0)
+ if (mii->mii_media_active & IFM_FLAG0) {
+ DBPRINT(sc, BCE_INFO_PHY,
+ "%s(): Enabling RX flow control.\n", __FUNCTION__);
BCE_SETBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_RX_MODE_FLOW_EN);
- if (mii->mii_media_active & IFM_FLAG1)
- BCE_SETBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_TX_MODE_FLOW_EN);
-#endif
+ } else {
+ DBPRINT(sc, BCE_INFO_PHY,
+ "%s(): Disabling RX flow control.\n", __FUNCTION__);
+ BCE_CLRBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_RX_MODE_FLOW_EN);
+ }
+
+ if (mii->mii_media_active & IFM_FLAG1) {
+ DBPRINT(sc, BCE_INFO_PHY,
+ "%s(): Enabling TX flow control.\n", __FUNCTION__);
+ BCE_SETBIT(sc, BCE_EMAC_TX_MODE, BCE_EMAC_TX_MODE_FLOW_EN);
+ sc->bce_flags |= BCE_USING_TX_FLOW_CONTROL;
+ } else {
+ DBPRINT(sc, BCE_INFO_PHY,
+ "%s(): Disabling TX flow control.\n", __FUNCTION__);
+ BCE_CLRBIT(sc, BCE_EMAC_TX_MODE, BCE_EMAC_TX_MODE_FLOW_EN);
+ sc->bce_flags &= ~BCE_USING_TX_FLOW_CONTROL;
+ }
+
+ /* ToDo: Update watermarks in bce_init_rx_context(). */
DBEXIT(BCE_VERBOSE_PHY);
}
@@ -1926,8 +1958,8 @@ bce_enable_nvram_access(struct bce_softc *sc)
val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE);
/* Enable both bits, even on read. */
- REG_WR(sc, BCE_NVM_ACCESS_ENABLE,
- val | BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN);
+ REG_WR(sc, BCE_NVM_ACCESS_ENABLE, val |
+ BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN);
DBEXIT(BCE_VERBOSE_NVRAM);
}
@@ -1951,9 +1983,8 @@ bce_disable_nvram_access(struct bce_softc *sc)
val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE);
/* Disable both bits, even after read. */
- REG_WR(sc, BCE_NVM_ACCESS_ENABLE,
- val & ~(BCE_NVM_ACCESS_ENABLE_EN |
- BCE_NVM_ACCESS_ENABLE_WR_EN));
+ REG_WR(sc, BCE_NVM_ACCESS_ENABLE, val &
+ ~(BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN));
DBEXIT(BCE_VERBOSE_NVRAM);
}
@@ -1983,7 +2014,7 @@ bce_nvram_erase_page(struct bce_softc *sc, u32 offset)
/* Build an erase command. */
cmd = BCE_NVM_COMMAND_ERASE | BCE_NVM_COMMAND_WR |
- BCE_NVM_COMMAND_DOIT;
+ BCE_NVM_COMMAND_DOIT;
/*
* Clear the DONE bit separately, set the NVRAM adress to erase,
@@ -2026,8 +2057,8 @@ bce_nvram_erase_page_exit:
/* 0 on success and the 32 bit value read, positive value on failure. */
/****************************************************************************/
static int
-bce_nvram_read_dword(struct bce_softc *sc, u32 offset, u8 *ret_val,
- u32 cmd_flags)
+bce_nvram_read_dword(struct bce_softc *sc,
+ u32 offset, u8 *ret_val, u32 cmd_flags)
{
u32 cmd;
int i, rc = 0;
@@ -2040,8 +2071,8 @@ bce_nvram_read_dword(struct bce_softc *sc, u32 offset, u8 *ret_val,
/* Calculate the offset for buffered flash if translation is used. */
if (sc->bce_flash_info->flags & BCE_NV_TRANSLATE) {
offset = ((offset / sc->bce_flash_info->page_size) <<
- sc->bce_flash_info->page_bits) +
- (offset % sc->bce_flash_info->page_size);
+ sc->bce_flash_info->page_bits) +
+ (offset % sc->bce_flash_info->page_size);
}
/*
@@ -2070,8 +2101,8 @@ bce_nvram_read_dword(struct bce_softc *sc, u32 offset, u8 *ret_val,
/* Check for errors. */
if (i >= NVRAM_TIMEOUT_COUNT) {
- BCE_PRINTF("%s(%d): Timeout error reading NVRAM at offset 0x%08X!\n",
- __FILE__, __LINE__, offset);
+ BCE_PRINTF("%s(%d): Timeout error reading NVRAM at "
+ "offset 0x%08X!\n", __FILE__, __LINE__, offset);
rc = EBUSY;
}
@@ -2106,8 +2137,8 @@ bce_nvram_write_dword(struct bce_softc *sc, u32 offset, u8 *val,
/* Calculate the offset for buffered flash if translation is used. */
if (sc->bce_flash_info->flags & BCE_NV_TRANSLATE) {
offset = ((offset / sc->bce_flash_info->page_size) <<
- sc->bce_flash_info->page_bits) +
- (offset % sc->bce_flash_info->page_size);
+ sc->bce_flash_info->page_bits) +
+ (offset % sc->bce_flash_info->page_size);
}
/*
@@ -2129,8 +2160,8 @@ bce_nvram_write_dword(struct bce_softc *sc, u32 offset, u8 *val,
break;
}
if (j >= NVRAM_TIMEOUT_COUNT) {
- BCE_PRINTF("%s(%d): Timeout error writing NVRAM at offset 0x%08X\n",
- __FILE__, __LINE__, offset);
+ BCE_PRINTF("%s(%d): Timeout error writing NVRAM at "
+ "offset 0x%08X\n", __FILE__, __LINE__, offset);
rc = EBUSY;
}
@@ -2232,7 +2263,7 @@ bce_init_nvram(struct bce_softc *sc)
if (j == entry_count) {
sc->bce_flash_info = NULL;
BCE_PRINTF("%s(%d): Unknown Flash NVRAM found!\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
rc = ENODEV;
}
@@ -2246,8 +2277,8 @@ bce_init_nvram_get_flash_size:
sc->bce_flash_size = sc->bce_flash_info->total_size;
DBPRINT(sc, BCE_INFO_LOAD, "%s(): Found %s, size = 0x%08X\n",
- __FUNCTION__, sc->bce_flash_info->name,
- sc->bce_flash_info->total_size);
+ __FUNCTION__, sc->bce_flash_info->name,
+ sc->bce_flash_info->total_size);
DBEXIT(BCE_VERBOSE_NVRAM);
return rc;
@@ -2604,7 +2635,8 @@ bce_nvram_test(struct bce_softc *sc)
* the magic value at offset 0.
*/
if ((rc = bce_nvram_read(sc, 0, data, 4)) != 0) {
- BCE_PRINTF("%s(%d): Unable to read NVRAM!\n", __FILE__, __LINE__);
+ BCE_PRINTF("%s(%d): Unable to read NVRAM!\n",
+ __FILE__, __LINE__);
goto bce_nvram_test_exit;
}
@@ -2615,9 +2647,9 @@ bce_nvram_test(struct bce_softc *sc)
magic = bce_be32toh(buf[0]);
if (magic != BCE_NVRAM_MAGIC) {
rc = ENODEV;
- BCE_PRINTF("%s(%d): Invalid NVRAM magic value! Expected: 0x%08X, "
- "Found: 0x%08X\n",
- __FILE__, __LINE__, BCE_NVRAM_MAGIC, magic);
+ BCE_PRINTF("%s(%d): Invalid NVRAM magic value! "
+ "Expected: 0x%08X, Found: 0x%08X\n",
+ __FILE__, __LINE__, BCE_NVRAM_MAGIC, magic);
goto bce_nvram_test_exit;
}
@@ -2626,26 +2658,27 @@ bce_nvram_test(struct bce_softc *sc)
* configuration data.
*/
if ((rc = bce_nvram_read(sc, 0x100, data, BCE_NVRAM_SIZE)) != 0) {
- BCE_PRINTF("%s(%d): Unable to read Manufacturing Information from "
- "NVRAM!\n", __FILE__, __LINE__);
+ BCE_PRINTF("%s(%d): Unable to read manufacturing "
+ "Information from NVRAM!\n", __FILE__, __LINE__);
goto bce_nvram_test_exit;
}
csum = ether_crc32_le(data, 0x100);
if (csum != BCE_CRC32_RESIDUAL) {
rc = ENODEV;
- BCE_PRINTF("%s(%d): Invalid Manufacturing Information NVRAM CRC! "
- "Expected: 0x%08X, Found: 0x%08X\n",
- __FILE__, __LINE__, BCE_CRC32_RESIDUAL, csum);
+ BCE_PRINTF("%s(%d): Invalid manufacturing information "
+ "NVRAM CRC! Expected: 0x%08X, Found: 0x%08X\n",
+ __FILE__, __LINE__, BCE_CRC32_RESIDUAL, csum);
goto bce_nvram_test_exit;
}
csum = ether_crc32_le(data + 0x100, 0x100);
if (csum != BCE_CRC32_RESIDUAL) {
rc = ENODEV;
- BCE_PRINTF("%s(%d): Invalid Feature Configuration Information "
- "NVRAM CRC! Expected: 0x%08X, Found: 08%08X\n",
- __FILE__, __LINE__, BCE_CRC32_RESIDUAL, csum);
+ BCE_PRINTF("%s(%d): Invalid feature configuration "
+ "information NVRAM CRC! Expected: 0x%08X, "
+ "Found: 08%08X\n", __FILE__, __LINE__,
+ BCE_CRC32_RESIDUAL, csum);
}
bce_nvram_test_exit:
@@ -2666,7 +2699,7 @@ bce_get_media(struct bce_softc *sc)
{
u32 val;
- DBENTER(BCE_VERBOSE);
+ DBENTER(BCE_VERBOSE_PHY);
/* Assume PHY address for copper controllers. */
sc->bce_phy_addr = 1;
@@ -2692,10 +2725,10 @@ bce_get_media(struct bce_softc *sc)
}
if (val & BCE_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE)
- strap = (val &
+ strap = (val &
BCE_MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21;
else
- strap = (val &
+ strap = (val &
BCE_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8;
if (pci_get_function(sc->bce_dev) == 0) {
@@ -2744,7 +2777,7 @@ bce_get_media(struct bce_softc *sc)
val = bce_shmem_rd(sc, BCE_SHARED_HW_CFG_CONFIG);
if (val & BCE_SHARED_HW_CFG_PHY_2_5G) {
- sc->bce_phy_flags |=
+ sc->bce_phy_flags |=
BCE_PHY_2_5G_CAPABLE_FLAG;
DBPRINT(sc, BCE_INFO_LOAD, "Found 2.5Gb "
"capable adapter\n");
@@ -2758,7 +2791,7 @@ bce_get_media_exit:
DBPRINT(sc, (BCE_INFO_LOAD | BCE_INFO_PHY),
"Using PHY address %d.\n", sc->bce_phy_addr);
- DBEXIT(BCE_VERBOSE);
+ DBEXIT(BCE_VERBOSE_PHY);
}
@@ -3056,7 +3089,9 @@ bce_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
/* Simulate a mapping failure. */
DBRUNIF(DB_RANDOMTRUE(dma_map_addr_failed_sim_control),
- error = ENOMEM);
+ error = ENOMEM);
+
+ /* ToDo: How to increment debug sim_count variable here? */
/* Check for an error and signal the caller that an error occurred. */
if (error) {
@@ -3154,7 +3189,7 @@ bce_dma_alloc(device_t dev)
goto bce_dma_alloc_exit;
}
- DBPRINT(sc, BCE_INFO, "%s(): status_block_paddr = 0x%jX\n",
+ DBPRINT(sc, BCE_INFO_LOAD, "%s(): status_block_paddr = 0x%jX\n",
__FUNCTION__, (uintmax_t) sc->status_block_paddr);
/*
@@ -3193,7 +3228,7 @@ bce_dma_alloc(device_t dev)
goto bce_dma_alloc_exit;
}
- DBPRINT(sc, BCE_INFO, "%s(): stats_block_paddr = 0x%jX\n",
+ DBPRINT(sc, BCE_INFO_LOAD, "%s(): stats_block_paddr = 0x%jX\n",
__FUNCTION__, (uintmax_t) sc->stats_block_paddr);
/* BCM5709 uses host memory as cache for context memory. */
@@ -3217,8 +3252,8 @@ bce_dma_alloc(device_t dev)
BCE_DMA_BOUNDARY, sc->max_bus_addr, BUS_SPACE_MAXADDR,
NULL, NULL, BCM_PAGE_SIZE, 1, BCM_PAGE_SIZE,
0, NULL, NULL, &sc->ctx_tag)) {
- BCE_PRINTF("%s(%d): Could not allocate CTX DMA tag!\n",
- __FILE__, __LINE__);
+ BCE_PRINTF("%s(%d): Could not allocate CTX "
+ "DMA tag!\n", __FILE__, __LINE__);
rc = ENOMEM;
goto bce_dma_alloc_exit;
}
@@ -3248,8 +3283,9 @@ bce_dma_alloc(device_t dev)
goto bce_dma_alloc_exit;
}
- DBPRINT(sc, BCE_INFO, "%s(): ctx_paddr[%d] = 0x%jX\n",
- __FUNCTION__, i, (uintmax_t) sc->ctx_paddr[i]);
+ DBPRINT(sc, BCE_INFO_LOAD, "%s(): ctx_paddr[%d] "
+ "= 0x%jX\n", __FUNCTION__, i,
+ (uintmax_t) sc->ctx_paddr[i]);
}
}
@@ -3262,15 +3298,15 @@ bce_dma_alloc(device_t dev)
sc->max_bus_addr, BUS_SPACE_MAXADDR, NULL, NULL,
BCE_TX_CHAIN_PAGE_SZ, 1, BCE_TX_CHAIN_PAGE_SZ, 0,
NULL, NULL, &sc->tx_bd_chain_tag)) {
- BCE_PRINTF("%s(%d): Could not allocate TX descriptor chain "
- "DMA tag!\n", __FILE__, __LINE__);
+ BCE_PRINTF("%s(%d): Could not allocate TX descriptor "
+ "chain DMA tag!\n", __FILE__, __LINE__);
rc = ENOMEM;
goto bce_dma_alloc_exit;
}
for (i = 0; i < TX_PAGES; i++) {
- if(bus_dmamem_alloc(sc->tx_bd_chain_tag,
+ if(bus_dmamem_alloc(sc->tx_bd_chain_tag,
(void **)&sc->tx_bd_chain[i], BUS_DMA_NOWAIT,
&sc->tx_bd_chain_map[i])) {
BCE_PRINTF("%s(%d): Could not allocate TX descriptor "
@@ -3291,8 +3327,9 @@ bce_dma_alloc(device_t dev)
goto bce_dma_alloc_exit;
}
- DBPRINT(sc, BCE_INFO, "%s(): tx_bd_chain_paddr[%d] = 0x%jX\n",
- __FUNCTION__, i, (uintmax_t) sc->tx_bd_chain_paddr[i]);
+ DBPRINT(sc, BCE_INFO_LOAD, "%s(): tx_bd_chain_paddr[%d] = "
+ "0x%jX\n", __FUNCTION__, i,
+ (uintmax_t) sc->tx_bd_chain_paddr[i]);
}
/* Check the required size before mapping to conserve resources. */
@@ -3368,8 +3405,9 @@ bce_dma_alloc(device_t dev)
goto bce_dma_alloc_exit;
}
- DBPRINT(sc, BCE_INFO, "%s(): rx_bd_chain_paddr[%d] = 0x%jX\n",
- __FUNCTION__, i, (uintmax_t) sc->rx_bd_chain_paddr[i]);
+ DBPRINT(sc, BCE_INFO_LOAD, "%s(): rx_bd_chain_paddr[%d] = "
+ "0x%jX\n", __FUNCTION__, i,
+ (uintmax_t) sc->rx_bd_chain_paddr[i]);
}
/*
@@ -3383,9 +3421,10 @@ bce_dma_alloc(device_t dev)
#endif
max_segments = 1;
- DBPRINT(sc, BCE_INFO, "%s(): Creating rx_mbuf_tag (max size = 0x%jX "
- "max segments = %d, max segment size = 0x%jX)\n", __FUNCTION__,
- (uintmax_t) max_size, max_segments, (uintmax_t) max_seg_size);
+ DBPRINT(sc, BCE_INFO_LOAD, "%s(): Creating rx_mbuf_tag "
+ "(max size = 0x%jX max segments = %d, max segment "
+ "size = 0x%jX)\n", __FUNCTION__, (uintmax_t) max_size,
+ max_segments, (uintmax_t) max_seg_size);
if (bus_dma_tag_create(sc->parent_tag, 1, BCE_DMA_BOUNDARY,
sc->max_bus_addr, BUS_SPACE_MAXADDR, NULL, NULL, max_size,
@@ -3429,7 +3468,7 @@ bce_dma_alloc(device_t dev)
(void **)&sc->pg_bd_chain[i], BUS_DMA_NOWAIT,
&sc->pg_bd_chain_map[i])) {
BCE_PRINTF("%s(%d): Could not allocate page "
- "descriptor chain DMA memory!\n",
+ "descriptor chain DMA memory!\n",
__FILE__, __LINE__);
rc = ENOMEM;
goto bce_dma_alloc_exit;
@@ -3437,7 +3476,7 @@ bce_dma_alloc(device_t dev)
bzero((char *)sc->pg_bd_chain[i], BCE_PG_CHAIN_PAGE_SZ);
- error = bus_dmamap_load(sc->pg_bd_chain_tag,
+ error = bus_dmamap_load(sc->pg_bd_chain_tag,
sc->pg_bd_chain_map[i], sc->pg_bd_chain[i],
BCE_PG_CHAIN_PAGE_SZ, bce_dma_map_addr,
&sc->pg_bd_chain_paddr[i], BUS_DMA_NOWAIT);
@@ -3449,8 +3488,9 @@ bce_dma_alloc(device_t dev)
goto bce_dma_alloc_exit;
}
- DBPRINT(sc, BCE_INFO, "%s(): pg_bd_chain_paddr[%d] = 0x%jX\n",
- __FUNCTION__, i, (uintmax_t) sc->pg_bd_chain_paddr[i]);
+ DBPRINT(sc, BCE_INFO_LOAD, "%s(): pg_bd_chain_paddr[%d] = "
+ "0x%jX\n", __FUNCTION__, i,
+ (uintmax_t) sc->pg_bd_chain_paddr[i]);
}
/*
@@ -3524,7 +3564,7 @@ bce_release_resources(struct bce_softc *sc)
if (sc->bce_res_mem != NULL) {
DBPRINT(sc, BCE_INFO_RESET, "Releasing PCI memory.\n");
- bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0),
+ bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0),
sc->bce_res_mem);
}
@@ -3582,7 +3622,7 @@ bce_fw_sync(struct bce_softc *sc, u32 msg_data)
DELAY(1000);
}
- /* If we've timed out, tell the bootcode that we've stopped waiting. */
+ /* If we've timed out, tell bootcode that we've stopped waiting. */
if (((val & BCE_FW_MSG_ACK) != (msg_data & BCE_DRV_MSG_SEQ)) &&
((msg_data & BCE_DRV_MSG_DATA) != BCE_DRV_MSG_DATA_WAIT0)) {
@@ -4319,22 +4359,22 @@ bce_init_cpus(struct bce_softc *sc)
(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
if ((BCE_CHIP_REV(sc) == BCE_CHIP_REV_Ax)) {
- bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc1,
- sizeof(bce_xi90_rv2p_proc1), RV2P_PROC1);
- bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc2,
- sizeof(bce_xi90_rv2p_proc2), RV2P_PROC2);
+ bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc1,
+ sizeof(bce_xi90_rv2p_proc1), RV2P_PROC1);
+ bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc2,
+ sizeof(bce_xi90_rv2p_proc2), RV2P_PROC2);
} else {
- bce_load_rv2p_fw(sc, bce_xi_rv2p_proc1,
- sizeof(bce_xi_rv2p_proc1), RV2P_PROC1);
- bce_load_rv2p_fw(sc, bce_xi_rv2p_proc2,
- sizeof(bce_xi_rv2p_proc2), RV2P_PROC2);
+ bce_load_rv2p_fw(sc, bce_xi_rv2p_proc1,
+ sizeof(bce_xi_rv2p_proc1), RV2P_PROC1);
+ bce_load_rv2p_fw(sc, bce_xi_rv2p_proc2,
+ sizeof(bce_xi_rv2p_proc2), RV2P_PROC2);
}
} else {
- bce_load_rv2p_fw(sc, bce_rv2p_proc1,
- sizeof(bce_rv2p_proc1), RV2P_PROC1);
+ bce_load_rv2p_fw(sc, bce_rv2p_proc1,
+ sizeof(bce_rv2p_proc1), RV2P_PROC1);
bce_load_rv2p_fw(sc, bce_rv2p_proc2,
- sizeof(bce_rv2p_proc2), RV2P_PROC2);
+ sizeof(bce_rv2p_proc2), RV2P_PROC2);
}
bce_init_rxp_cpu(sc);
@@ -4373,7 +4413,7 @@ bce_init_ctx(struct bce_softc *sc)
* in host memory so prepare the host memory
* for access.
*/
- val = BCE_CTX_COMMAND_ENABLED |
+ val = BCE_CTX_COMMAND_ENABLED |
BCE_CTX_COMMAND_MEM_INIT | (1 << 12);
val |= (BCM_PAGE_BITS - 8) << 16;
REG_WR(sc, BCE_CTX_COMMAND, val);
@@ -4406,7 +4446,7 @@ bce_init_ctx(struct bce_softc *sc)
/* Verify the context memory write was successful. */
for (j = 0; j < retry_cnt; j++) {
val = REG_RD(sc, BCE_CTX_HOST_PAGE_TBL_CTRL);
- if ((val &
+ if ((val &
BCE_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ) == 0)
break;
DELAY(5);
@@ -4461,6 +4501,7 @@ bce_get_mac_addr(struct bce_softc *sc)
u32 mac_lo = 0, mac_hi = 0;
DBENTER(BCE_VERBOSE_RESET);
+
/*
* The NetXtreme II bootcode populates various NIC
* power-on and runtime configuration items in a
@@ -4475,7 +4516,7 @@ bce_get_mac_addr(struct bce_softc *sc)
if ((mac_lo == 0) && (mac_hi == 0)) {
BCE_PRINTF("%s(%d): Invalid Ethernet address!\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
} else {
sc->eaddr[0] = (u_char)(mac_hi >> 8);
sc->eaddr[1] = (u_char)(mac_hi >> 0);
@@ -4485,7 +4526,8 @@ bce_get_mac_addr(struct bce_softc *sc)
sc->eaddr[5] = (u_char)(mac_lo >> 0);
}
- DBPRINT(sc, BCE_INFO_MISC, "Permanent Ethernet address = %6D\n", sc->eaddr, ":");
+ DBPRINT(sc, BCE_INFO_MISC, "Permanent Ethernet "
+ "address = %6D\n", sc->eaddr, ":");
DBEXIT(BCE_VERBOSE_RESET);
}
@@ -4505,14 +4547,15 @@ bce_set_mac_addr(struct bce_softc *sc)
/* ToDo: Add support for setting multiple MAC addresses. */
DBENTER(BCE_VERBOSE_RESET);
- DBPRINT(sc, BCE_INFO_MISC, "Setting Ethernet address = %6D\n", sc->eaddr, ":");
+ DBPRINT(sc, BCE_INFO_MISC, "Setting Ethernet address = "
+ "%6D\n", sc->eaddr, ":");
val = (mac_addr[0] << 8) | mac_addr[1];
REG_WR(sc, BCE_EMAC_MAC_MATCH0, val);
val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
- (mac_addr[4] << 8) | mac_addr[5];
+ (mac_addr[4] << 8) | mac_addr[5];
REG_WR(sc, BCE_EMAC_MAC_MATCH1, val);
@@ -4598,20 +4641,20 @@ bce_reset(struct bce_softc *sc, u32 reset_code)
DBENTER(BCE_VERBOSE_RESET);
DBPRINT(sc, BCE_VERBOSE_RESET, "%s(): reset_code = 0x%08X\n",
- __FUNCTION__, reset_code);
+ __FUNCTION__, reset_code);
/* Wait for pending PCI transactions to complete. */
REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS,
- BCE_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
- BCE_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
- BCE_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
- BCE_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
+ BCE_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
+ BCE_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
+ BCE_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
+ BCE_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
val = REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS);
DELAY(5);
/* Disable DMA */
if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
val = REG_RD(sc, BCE_MISC_NEW_CORE_CTL);
val &= ~BCE_MISC_NEW_CORE_CTL_DMA_ENABLE;
REG_WR(sc, BCE_MISC_NEW_CORE_CTL, val);
@@ -4634,26 +4677,26 @@ bce_reset(struct bce_softc *sc, u32 reset_code)
/* Chip reset. */
if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
REG_WR(sc, BCE_MISC_COMMAND, BCE_MISC_COMMAND_SW_RESET);
REG_RD(sc, BCE_MISC_COMMAND);
DELAY(5);
val = BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
- BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
+ BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
pci_write_config(sc->bce_dev, BCE_PCICFG_MISC_CONFIG, val, 4);
} else {
val = BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
- BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
- BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
+ BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+ BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
REG_WR(sc, BCE_PCICFG_MISC_CONFIG, val);
/* Allow up to 30us for reset to complete. */
for (i = 0; i < 10; i++) {
val = REG_RD(sc, BCE_PCICFG_MISC_CONFIG);
if ((val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
- BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) {
+ BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) {
break;
}
DELAY(10);
@@ -4661,9 +4704,9 @@ bce_reset(struct bce_softc *sc, u32 reset_code)
/* Check that reset completed successfully. */
if (val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
- BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
+ BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
BCE_PRINTF("%s(%d): Reset failed!\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
rc = EBUSY;
goto bce_reset_exit;
}
@@ -4673,7 +4716,7 @@ bce_reset(struct bce_softc *sc, u32 reset_code)
val = REG_RD(sc, BCE_PCI_SWAP_DIAG0);
if (val != 0x01020304) {
BCE_PRINTF("%s(%d): Byte swap is incorrect!\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
rc = ENODEV;
goto bce_reset_exit;
}
@@ -4685,8 +4728,8 @@ bce_reset(struct bce_softc *sc, u32 reset_code)
/* Wait for the firmware to finish its initialization. */
rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT1 | reset_code);
if (rc)
- BCE_PRINTF("%s(%d): Firmware did not complete initialization!\n",
- __FILE__, __LINE__);
+ BCE_PRINTF("%s(%d): Firmware did not complete "
+ "initialization!\n", __FILE__, __LINE__);
bce_reset_exit:
DBEXIT(BCE_VERBOSE_RESET);
@@ -4709,13 +4752,13 @@ bce_chipinit(struct bce_softc *sc)
* channels and PCI clock compensation delay.
*/
val = BCE_DMA_CONFIG_DATA_BYTE_SWAP |
- BCE_DMA_CONFIG_DATA_WORD_SWAP |
+ BCE_DMA_CONFIG_DATA_WORD_SWAP |
#if BYTE_ORDER == BIG_ENDIAN
- BCE_DMA_CONFIG_CNTL_BYTE_SWAP |
+ BCE_DMA_CONFIG_CNTL_BYTE_SWAP |
#endif
- BCE_DMA_CONFIG_CNTL_WORD_SWAP |
- DMA_READ_CHANS << 12 |
- DMA_WRITE_CHANS << 16;
+ BCE_DMA_CONFIG_CNTL_WORD_SWAP |
+ DMA_READ_CHANS << 12 |
+ DMA_WRITE_CHANS << 16;
val |= (0x2 << 20) | BCE_DMA_CONFIG_CNTL_PCI_COMP_DLY;
@@ -4765,7 +4808,7 @@ bce_chipinit(struct bce_softc *sc)
/* Enable bins used on the 5709. */
if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
- (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
+ (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
val |= BCE_MQ_CONFIG_BIN_MQ_MODE;
if (BCE_CHIP_ID(sc) == BCE_CHIP_ID_5709_A1)
val |= BCE_MQ_CONFIG_HALT_DIS;
@@ -4927,7 +4970,7 @@ bce_blockinit(struct bce_softc *sc)
}
/* Allow bootcode to apply additional fixes before enabling MAC. */
- rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT2 |
+ rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT2 |
BCE_DRV_MSG_CODE_RESET);
/* Enable link state change interrupt generation. */
@@ -4938,7 +4981,7 @@ bce_blockinit(struct bce_softc *sc)
/* Disable management frames (NC-SI) from flowing to the MCP. */
if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) {
- val = REG_RD(sc, BCE_RPM_MGMT_PKT_CTRL) &
+ val = REG_RD(sc, BCE_RPM_MGMT_PKT_CTRL) &
~BCE_RPM_MGMT_PKT_CTRL_MGMT_EN;
REG_WR(sc, BCE_RPM_MGMT_PKT_CTRL, val);
}
@@ -4946,10 +4989,10 @@ bce_blockinit(struct bce_softc *sc)
/* Enable all remaining blocks in the MAC. */
if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716))
- REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
+ REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
BCE_MISC_ENABLE_DEFAULT_XI);
else
- REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
+ REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
BCE_MISC_ENABLE_DEFAULT);
REG_RD(sc, BCE_MISC_ENABLE_SET_BITS);
@@ -4988,8 +5031,9 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod,
/* Make sure the inputs are valid. */
DBRUNIF((*chain_prod > MAX_RX_BD),
- BCE_PRINTF("%s(%d): RX producer out of range: 0x%04X > 0x%04X\n",
- __FILE__, __LINE__, *chain_prod, (u16) MAX_RX_BD));
+ BCE_PRINTF("%s(%d): RX producer out of range: "
+ "0x%04X > 0x%04X\n", __FILE__, __LINE__,
+ *chain_prod, (u16) MAX_RX_BD));
DBPRINT(sc, BCE_EXTREME_RECV, "%s(enter): prod = 0x%04X, "
"chain_prod = 0x%04X, prod_bseq = 0x%08X\n", __FUNCTION__,
@@ -4997,8 +5041,9 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod,
/* Update some debug statistic counters */
DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
- sc->rx_low_watermark = sc->free_rx_bd);
- DBRUNIF((sc->free_rx_bd == sc->max_rx_bd), sc->rx_empty_count++);
+ sc->rx_low_watermark = sc->free_rx_bd);
+ DBRUNIF((sc->free_rx_bd == sc->max_rx_bd),
+ sc->rx_empty_count++);
/* Check whether this is a new mbuf allocation. */
if (m == NULL) {
@@ -5017,7 +5062,7 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod,
if (sc->rx_bd_mbuf_alloc_size <= MCLBYTES)
m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
else
- m_new = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR,
+ m_new = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR,
sc->rx_bd_mbuf_alloc_size);
#endif
@@ -5049,8 +5094,8 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod,
/* Handle any mapping errors. */
if (error) {
- BCE_PRINTF("%s(%d): Error mapping mbuf into RX chain (%d)!\n",
- __FILE__, __LINE__, error);
+ BCE_PRINTF("%s(%d): Error mapping mbuf into RX "
+ "chain (%d)!\n", __FILE__, __LINE__, error);
sc->dma_map_addr_rx_failed_count++;
m_freem(m_new);
@@ -5078,11 +5123,11 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod,
sc->rx_mbuf_ptr[*chain_prod] = m_new;
sc->free_rx_bd -= nsegs;
- DBRUNMSG(BCE_INSANE_RECV,
+ DBRUNMSG(BCE_INSANE_RECV,
bce_dump_rx_mbuf_chain(sc, debug_chain_prod, nsegs));
DBPRINT(sc, BCE_EXTREME_RECV, "%s(exit): prod = 0x%04X, "
- "chain_prod = 0x%04X, prod_bseq = 0x%08X\n",
+ "chain_prod = 0x%04X, prod_bseq = 0x%08X\n",
__FUNCTION__, *prod, *chain_prod, *prod_bseq);
bce_get_rx_buf_exit:
@@ -5116,8 +5161,9 @@ bce_get_pg_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod,
/* Make sure the inputs are valid. */
DBRUNIF((*prod_idx > MAX_PG_BD),
- BCE_PRINTF("%s(%d): page producer out of range: 0x%04X > 0x%04X\n",
- __FILE__, __LINE__, *prod_idx, (u16) MAX_PG_BD));
+ BCE_PRINTF("%s(%d): page producer out of range: "
+ "0x%04X > 0x%04X\n", __FILE__, __LINE__,
+ *prod_idx, (u16) MAX_PG_BD));
DBPRINT(sc, BCE_EXTREME_RECV, "%s(enter): prod = 0x%04X, "
"chain_prod = 0x%04X\n", __FUNCTION__, *prod, *prod_idx);
@@ -5159,7 +5205,7 @@ bce_get_pg_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod,
/* Map the mbuf cluster into device memory. */
map = sc->pg_mbuf_map[*prod_idx];
error = bus_dmamap_load(sc->pg_mbuf_tag, map, mtod(m_new, void *),
- sc->pg_bd_mbuf_alloc_size, bce_dma_map_addr,
+ sc->pg_bd_mbuf_alloc_size, bce_dma_map_addr,
&busaddr, BUS_DMA_NOWAIT);
/* Handle any mapping errors. */
@@ -5191,7 +5237,7 @@ bce_get_pg_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod,
sc->pg_mbuf_ptr[*prod_idx] = m_new;
sc->free_pg_bd--;
- DBRUNMSG(BCE_INSANE_RECV,
+ DBRUNMSG(BCE_INSANE_RECV,
bce_dump_pg_mbuf_chain(sc, debug_prod_idx, 1));
DBPRINT(sc, BCE_EXTREME_RECV, "%s(exit): prod = 0x%04X, "
@@ -5222,19 +5268,19 @@ bce_init_tx_context(struct bce_softc *sc)
if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
/* Set the CID type to support an L2 connection. */
- val = BCE_L2CTX_TX_TYPE_TYPE_L2_XI |
+ val = BCE_L2CTX_TX_TYPE_TYPE_L2_XI |
BCE_L2CTX_TX_TYPE_SIZE_L2_XI;
CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_TYPE_XI, val);
val = BCE_L2CTX_TX_CMD_TYPE_TYPE_L2_XI | (8 << 16);
- CTX_WR(sc, GET_CID_ADDR(TX_CID),
+ CTX_WR(sc, GET_CID_ADDR(TX_CID),
BCE_L2CTX_TX_CMD_TYPE_XI, val);
/* Point the hardware to the first page in the chain. */
val = BCE_ADDR_HI(sc->tx_bd_chain_paddr[0]);
- CTX_WR(sc, GET_CID_ADDR(TX_CID),
+ CTX_WR(sc, GET_CID_ADDR(TX_CID),
BCE_L2CTX_TX_TBDR_BHADDR_HI_XI, val);
val = BCE_ADDR_LO(sc->tx_bd_chain_paddr[0]);
- CTX_WR(sc, GET_CID_ADDR(TX_CID),
+ CTX_WR(sc, GET_CID_ADDR(TX_CID),
BCE_L2CTX_TX_TBDR_BHADDR_LO_XI, val);
} else {
/* Set the CID type to support an L2 connection. */
@@ -5245,10 +5291,10 @@ bce_init_tx_context(struct bce_softc *sc)
/* Point the hardware to the first page in the chain. */
val = BCE_ADDR_HI(sc->tx_bd_chain_paddr[0]);
- CTX_WR(sc, GET_CID_ADDR(TX_CID),
+ CTX_WR(sc, GET_CID_ADDR(TX_CID),
BCE_L2CTX_TX_TBDR_BHADDR_HI, val);
val = BCE_ADDR_LO(sc->tx_bd_chain_paddr[0]);
- CTX_WR(sc, GET_CID_ADDR(TX_CID),
+ CTX_WR(sc, GET_CID_ADDR(TX_CID),
BCE_L2CTX_TX_TBDR_BHADDR_LO, val);
}
@@ -5331,7 +5377,7 @@ bce_free_tx_chain(struct bce_softc *sc)
for (i = 0; i < TOTAL_TX_BD; i++) {
if (sc->tx_mbuf_ptr[i] != NULL) {
if (sc->tx_mbuf_map[i] != NULL)
- bus_dmamap_sync(sc->tx_mbuf_tag,
+ bus_dmamap_sync(sc->tx_mbuf_tag,
sc->tx_mbuf_map[i],
BUS_DMASYNC_POSTWRITE);
m_freem(sc->tx_mbuf_ptr[i]);
@@ -5349,7 +5395,7 @@ bce_free_tx_chain(struct bce_softc *sc)
/* Check if we lost any mbufs in the process. */
DBRUNIF((sc->debug_tx_mbuf_alloc),
BCE_PRINTF("%s(%d): Memory leak! Lost %d mbufs "
- "from tx chain!\n", __FILE__, __LINE__,
+ "from tx chain!\n", __FILE__, __LINE__,
sc->debug_tx_mbuf_alloc));
DBEXIT(BCE_VERBOSE_RESET | BCE_VERBOSE_SEND | BCE_VERBOSE_UNLOAD);
@@ -5385,9 +5431,22 @@ bce_init_rx_context(struct bce_softc *sc)
(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
u32 lo_water, hi_water;
- lo_water = BCE_L2CTX_RX_LO_WATER_MARK_DEFAULT;
+ if (sc->bce_flags && BCE_USING_TX_FLOW_CONTROL) {
+ lo_water = BCE_L2CTX_RX_LO_WATER_MARK_DEFAULT;
+ } else {
+ lo_water = 0;
+ }
+
+ if (lo_water >= USABLE_RX_BD) {
+ lo_water = 0;
+ }
+
hi_water = USABLE_RX_BD / 4;
+ if (hi_water <= lo_water) {
+ lo_water = 0;
+ }
+
lo_water /= BCE_L2CTX_RX_LO_WATER_MARK_SCALE;
hi_water /= BCE_L2CTX_RX_HI_WATER_MARK_SCALE;
@@ -5395,11 +5454,12 @@ bce_init_rx_context(struct bce_softc *sc)
hi_water = 0xf;
else if (hi_water == 0)
lo_water = 0;
+
val |= (lo_water << BCE_L2CTX_RX_LO_WATER_MARK_SHIFT) |
- (hi_water << BCE_L2CTX_RX_HI_WATER_MARK_SHIFT);
+ (hi_water << BCE_L2CTX_RX_HI_WATER_MARK_SHIFT);
}
- CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_CTX_TYPE, val);
+ CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_CTX_TYPE, val);
/* Setup the MQ BIN mapping for l2_ctx_host_bseq. */
if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
@@ -5453,9 +5513,9 @@ bce_init_rx_chain(struct bce_softc *sc)
j = i + 1;
/* Setup the chain page pointers. */
- rxbd->rx_bd_haddr_hi =
+ rxbd->rx_bd_haddr_hi =
htole32(BCE_ADDR_HI(sc->rx_bd_chain_paddr[j]));
- rxbd->rx_bd_haddr_lo =
+ rxbd->rx_bd_haddr_lo =
htole32(BCE_ADDR_LO(sc->rx_bd_chain_paddr[j]));
}
@@ -5517,14 +5577,14 @@ bce_fill_rx_chain(struct bce_softc *sc)
/* We should never end up pointing to a next page pointer. */
DBRUNIF(((prod & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE),
- BCE_PRINTF("%s(): Invalid rx_prod value: 0x%04X\n",
- __FUNCTION__, sc->rx_prod));
+ BCE_PRINTF("%s(): Invalid rx_prod value: 0x%04X\n",
+ __FUNCTION__, sc->rx_prod));
/* Write the mailbox and tell the chip about the waiting rx_bd's. */
- REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BDIDX,
- sc->rx_prod);
- REG_WR(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BSEQ,
- sc->rx_prod_bseq);
+ REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) +
+ BCE_L2MQ_RX_HOST_BDIDX, sc->rx_prod);
+ REG_WR(sc, MB_GET_CID_ADDR(RX_CID) +
+ BCE_L2MQ_RX_HOST_BSEQ, sc->rx_prod_bseq);
DBEXIT(BCE_VERBOSE_RESET | BCE_EXTREME_RECV | BCE_VERBOSE_LOAD |
BCE_VERBOSE_CTX);
@@ -5548,7 +5608,7 @@ bce_free_rx_chain(struct bce_softc *sc)
for (i = 0; i < TOTAL_RX_BD; i++) {
if (sc->rx_mbuf_ptr[i] != NULL) {
if (sc->rx_mbuf_map[i] != NULL)
- bus_dmamap_sync(sc->rx_mbuf_tag,
+ bus_dmamap_sync(sc->rx_mbuf_tag,
sc->rx_mbuf_map[i],
BUS_DMASYNC_POSTREAD);
m_freem(sc->rx_mbuf_ptr[i]);
@@ -5560,7 +5620,7 @@ bce_free_rx_chain(struct bce_softc *sc)
/* Clear each RX chain page. */
for (i = 0; i < RX_PAGES; i++)
if (sc->rx_bd_chain[i] != NULL) {
- bzero((char *)sc->rx_bd_chain[i],
+ bzero((char *)sc->rx_bd_chain[i],
BCE_RX_CHAIN_PAGE_SZ);
}
@@ -5667,7 +5727,7 @@ bce_fill_pg_chain(struct bce_softc *sc)
u16 prod, prod_idx;
DBENTER(BCE_VERBOSE_RESET | BCE_EXTREME_RECV | BCE_VERBOSE_LOAD |
- BCE_VERBOSE_CTX);
+ BCE_VERBOSE_CTX);
/* Get the page chain prodcuer index. */
prod = sc->pg_prod;
@@ -5686,18 +5746,18 @@ bce_fill_pg_chain(struct bce_softc *sc)
sc->pg_prod = prod;
DBRUNIF(((prod & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE),
- BCE_PRINTF("%s(): Invalid pg_prod value: 0x%04X\n",
- __FUNCTION__, sc->pg_prod));
+ BCE_PRINTF("%s(): Invalid pg_prod value: 0x%04X\n",
+ __FUNCTION__, sc->pg_prod));
/*
* Write the mailbox and tell the chip about
* the new rx_bd's in the page chain.
*/
- REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_PG_BDIDX,
- sc->pg_prod);
+ REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) +
+ BCE_L2MQ_RX_HOST_PG_BDIDX, sc->pg_prod);
DBEXIT(BCE_VERBOSE_RESET | BCE_EXTREME_RECV | BCE_VERBOSE_LOAD |
- BCE_VERBOSE_CTX);
+ BCE_VERBOSE_CTX);
}
@@ -5718,8 +5778,9 @@ bce_free_pg_chain(struct bce_softc *sc)
for (i = 0; i < TOTAL_PG_BD; i++) {
if (sc->pg_mbuf_ptr[i] != NULL) {
if (sc->pg_mbuf_map[i] != NULL)
- bus_dmamap_sync(sc->pg_mbuf_tag, sc->pg_mbuf_map[i],
- BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(sc->pg_mbuf_tag,
+ sc->pg_mbuf_map[i],
+ BUS_DMASYNC_POSTREAD);
m_freem(sc->pg_mbuf_ptr[i]);
sc->pg_mbuf_ptr[i] = NULL;
DBRUN(sc->debug_pg_mbuf_alloc--);
@@ -5734,8 +5795,8 @@ bce_free_pg_chain(struct bce_softc *sc)
/* Check if we lost any mbufs in the process. */
DBRUNIF((sc->debug_pg_mbuf_alloc),
- BCE_PRINTF("%s(): Memory leak! Lost %d mbufs from page chain!\n",
- __FUNCTION__, sc->debug_pg_mbuf_alloc));
+ BCE_PRINTF("%s(): Memory leak! Lost %d mbufs from page chain!\n",
+ __FUNCTION__, sc->debug_pg_mbuf_alloc));
DBEXIT(BCE_VERBOSE_RESET | BCE_VERBOSE_RECV | BCE_VERBOSE_UNLOAD);
}
@@ -5776,7 +5837,7 @@ bce_ifmedia_upd_locked(struct ifnet *ifp)
struct bce_softc *sc = ifp->if_softc;
struct mii_data *mii;
- DBENTER(BCE_VERBOSE);
+ DBENTER(BCE_VERBOSE_PHY);
BCE_LOCK_ASSERT(sc);
@@ -5794,7 +5855,7 @@ bce_ifmedia_upd_locked(struct ifnet *ifp)
mii_mediachg(mii);
}
- DBEXIT(BCE_VERBOSE);
+ DBEXIT(BCE_VERBOSE_PHY);
}
@@ -5810,7 +5871,7 @@ bce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
struct bce_softc *sc = ifp->if_softc;
struct mii_data *mii;
- DBENTER(BCE_VERBOSE);
+ DBENTER(BCE_VERBOSE_PHY);
BCE_LOCK(sc);
@@ -5822,7 +5883,7 @@ bce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
BCE_UNLOCK(sc);
- DBEXIT(BCE_VERBOSE);
+ DBEXIT(BCE_VERBOSE_PHY);
}
@@ -5921,7 +5982,7 @@ bce_rx_intr(struct bce_softc *sc)
#endif
DBENTER(BCE_VERBOSE_RECV | BCE_VERBOSE_INTR);
- DBRUN(sc->rx_interrupts++);
+ DBRUN(sc->interrupts_rx++);
DBPRINT(sc, BCE_EXTREME_RECV, "%s(enter): rx_prod = 0x%04X, "
"rx_cons = 0x%04X, rx_prod_bseq = 0x%08X\n",
__FUNCTION__, sc->rx_prod, sc->rx_cons, sc->rx_prod_bseq);
@@ -5943,14 +6004,16 @@ bce_rx_intr(struct bce_softc *sc)
/* Get working copies of the driver's view of the consumer indices. */
sw_rx_cons = sc->rx_cons;
+
#ifdef BCE_JUMBO_HDRSPLIT
sw_pg_cons = sc->pg_cons;
#endif
/* Update some debug statistics counters */
DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
- sc->rx_low_watermark = sc->free_rx_bd);
- DBRUNIF((sc->free_rx_bd == sc->max_rx_bd), sc->rx_empty_count++);
+ sc->rx_low_watermark = sc->free_rx_bd);
+ DBRUNIF((sc->free_rx_bd == sc->max_rx_bd),
+ sc->rx_empty_count++);
/* Scan through the receive chain as long as there is work to do */
/* ToDo: Consider setting a limit on the number of packets processed. */
@@ -5962,7 +6025,7 @@ bce_rx_intr(struct bce_softc *sc)
sw_rx_cons_idx = RX_CHAIN_IDX(sw_rx_cons);
/* Unmap the mbuf from DMA space. */
- bus_dmamap_sync(sc->rx_mbuf_tag,
+ bus_dmamap_sync(sc->rx_mbuf_tag,
sc->rx_mbuf_map[sw_rx_cons_idx],
BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->rx_mbuf_tag,
@@ -5975,7 +6038,7 @@ bce_rx_intr(struct bce_softc *sc)
sc->free_rx_bd++;
if(m0 == NULL) {
- DBPRINT(sc, BCE_EXTREME_RECV,
+ DBPRINT(sc, BCE_EXTREME_RECV,
"%s(): Oops! Empty mbuf pointer "
"found in sc->rx_mbuf_ptr[0x%04X]!\n",
__FUNCTION__, sw_rx_cons_idx);
@@ -5983,20 +6046,23 @@ bce_rx_intr(struct bce_softc *sc)
}
/*
- * Frames received on the NetXteme II are prepended with an
- * l2_fhdr structure which provides status information about
- * the received frame (including VLAN tags and checksum info).
- * The frames are also automatically adjusted to align the IP
- * header (i.e. two null bytes are inserted before the Ethernet
- * header). As a result the data DMA'd by the controller into
- * the mbuf is as follows:
- *
+ * Frames received on the NetXteme II are prepended
+ * with an l2_fhdr structure which provides status
+ * information about the received frame (including
+ * VLAN tags and checksum info). The frames are
+ * also automatically adjusted to align the IP
+ * header (i.e. two null bytes are inserted before
+ * the Ethernet header). As a result the data
+ * DMA'd by the controller into the mbuf looks
+ * like this:
+ *
* +---------+-----+---------------------+-----+
* | l2_fhdr | pad | packet data | FCS |
* +---------+-----+---------------------+-----+
- *
- * The l2_fhdr needs to be checked and skipped and the FCS needs
- * to be stripped before sending the packet up the stack.
+ *
+ * The l2_fhdr needs to be checked and skipped and
+ * the FCS needs to be stripped before sending the
+ * packet up the stack.
*/
l2fhdr = mtod(m0, struct l2_fhdr *);
@@ -6100,7 +6166,7 @@ bce_rx_intr(struct bce_softc *sc)
m0->m_pkthdr.len = m0->m_len = pkt_len;
}
#else
- /* Set the total packet length. */
+ /* Set the total packet length. */
m0->m_pkthdr.len = m0->m_len = pkt_len;
#endif
@@ -6115,12 +6181,11 @@ bce_rx_intr(struct bce_softc *sc)
m_print(m0, 128));
DBRUNIF(DB_RANDOMTRUE(l2fhdr_error_sim_control),
- BCE_PRINTF("Simulating l2_fhdr status error.\n");
sc->l2fhdr_error_sim_count++;
status = status | L2_FHDR_ERRORS_PHY_DECODE);
/* Check the received frame for errors. */
- if (status & (L2_FHDR_ERRORS_BAD_CRC |
+ if (status & (L2_FHDR_ERRORS_BAD_CRC |
L2_FHDR_ERRORS_PHY_DECODE | L2_FHDR_ERRORS_ALIGNMENT |
L2_FHDR_ERRORS_TOO_SHORT | L2_FHDR_ERRORS_GIANT_FRAME)) {
@@ -6144,12 +6209,12 @@ bce_rx_intr(struct bce_softc *sc)
/* Check for an IP datagram. */
if (!(status & L2_FHDR_STATUS_SPLIT) &&
- (status & L2_FHDR_STATUS_IP_DATAGRAM)) {
+ (status & L2_FHDR_STATUS_IP_DATAGRAM)) {
m0->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
-
+ DBRUN(sc->csum_offload_ip++);
/* Check if the IP checksum is valid. */
if ((l2fhdr->l2_fhdr_ip_xsum ^ 0xffff) == 0)
- m0->m_pkthdr.csum_flags |=
+ m0->m_pkthdr.csum_flags |=
CSUM_IP_VALID;
}
@@ -6160,9 +6225,10 @@ bce_rx_intr(struct bce_softc *sc)
/* Check for a good TCP/UDP checksum. */
if ((status & (L2_FHDR_ERRORS_TCP_XSUM |
L2_FHDR_ERRORS_UDP_XSUM)) == 0) {
+ DBRUN(sc->csum_offload_tcp_udp++);
m0->m_pkthdr.csum_data =
l2fhdr->l2_fhdr_tcp_udp_xsum;
- m0->m_pkthdr.csum_flags |=
+ m0->m_pkthdr.csum_flags |=
(CSUM_DATA_VALID
| CSUM_PSEUDO_HDR);
}
@@ -6234,12 +6300,13 @@ bce_rx_int_next_rx:
hw_rx_cons = sc->hw_rx_cons = bce_get_hw_rx_cons(sc);
}
- /* No new packets to process. Refill the RX and page chains and exit. */
#ifdef BCE_JUMBO_HDRSPLIT
+ /* No new packets. Refill the page chain. */
sc->pg_cons = sw_pg_cons;
bce_fill_pg_chain(sc);
#endif
+ /* No new packets. Refill the RX chain. */
sc->rx_cons = sw_rx_cons;
bce_fill_rx_chain(sc);
@@ -6295,7 +6362,7 @@ bce_tx_intr(struct bce_softc *sc)
u16 hw_tx_cons, sw_tx_cons, sw_tx_chain_cons;
DBENTER(BCE_VERBOSE_SEND | BCE_VERBOSE_INTR);
- DBRUN(sc->tx_interrupts++);
+ DBRUN(sc->interrupts_tx++);
DBPRINT(sc, BCE_EXTREME_SEND, "%s(enter): tx_prod = 0x%04X, "
"tx_cons = 0x%04X, tx_prod_bseq = 0x%08X\n",
__FUNCTION__, sc->tx_prod, sc->tx_cons, sc->tx_prod_bseq);
@@ -6306,7 +6373,7 @@ bce_tx_intr(struct bce_softc *sc)
hw_tx_cons = sc->hw_tx_cons = bce_get_hw_tx_cons(sc);
sw_tx_cons = sc->tx_cons;
- /* Prevent speculative reads from getting ahead of the status block. */
+ /* Prevent speculative reads of the status block. */
bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
BUS_SPACE_BARRIER_READ);
@@ -6354,7 +6421,7 @@ bce_tx_intr(struct bce_softc *sc)
DBRUNMSG(BCE_INFO_SEND,
BCE_PRINTF("%s(): Unloading map/freeing mbuf "
- "from tx_bd[0x%04X]\n", __FUNCTION__,
+ "from tx_bd[0x%04X]\n", __FUNCTION__,
sw_tx_chain_cons));
/* Unmap the mbuf. */
@@ -6496,9 +6563,9 @@ bce_init_locked(struct bce_softc *sc)
* size. Be generous on the receive if we have room.
*/
#ifdef BCE_JUMBO_HDRSPLIT
- if (ifp->if_mtu <= (sc->rx_bd_mbuf_data_len +
+ if (ifp->if_mtu <= (sc->rx_bd_mbuf_data_len +
sc->pg_bd_mbuf_alloc_size))
- ether_mtu = sc->rx_bd_mbuf_data_len +
+ ether_mtu = sc->rx_bd_mbuf_data_len +
sc->pg_bd_mbuf_alloc_size;
#else
if (ifp->if_mtu <= sc->rx_bd_mbuf_data_len)
@@ -6509,7 +6576,7 @@ bce_init_locked(struct bce_softc *sc)
ether_mtu += ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETHER_CRC_LEN;
- DBPRINT(sc, BCE_INFO_MISC, "%s(): setting h/w mtu = %d\n",
+ DBPRINT(sc, BCE_INFO_MISC, "%s(): setting h/w mtu = %d\n",
__FUNCTION__, ether_mtu);
/* Program the mtu, enabling jumbo frame support if necessary. */
@@ -6522,7 +6589,7 @@ bce_init_locked(struct bce_softc *sc)
DBPRINT(sc, BCE_INFO_LOAD,
"%s(): rx_bd_mbuf_alloc_size = %d, rx_bce_mbuf_data_len = %d, "
- "rx_bd_mbuf_align_pad = %d\n", __FUNCTION__,
+ "rx_bd_mbuf_align_pad = %d\n", __FUNCTION__,
sc->rx_bd_mbuf_alloc_size, sc->rx_bd_mbuf_data_len,
sc->rx_bd_mbuf_align_pad);
@@ -6617,6 +6684,12 @@ bce_init(void *xsc)
}
+/****************************************************************************/
+/* Modifies an mbuf for TSO on the hardware. */
+/* */
+/* Returns: */
+/* Pointer to a modified mbuf. */
+/****************************************************************************/
static struct mbuf *
bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags)
{
@@ -6627,8 +6700,9 @@ bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags)
u16 etype;
int hdr_len, ip_hlen = 0, tcp_hlen = 0, ip_len = 0;
- DBRUN(sc->requested_tso_frames++);
- /* Controller requires to monify mbuf chains. */
+ DBRUN(sc->tso_frames_requested++);
+
+ /* Controller may modify mbuf chains. */
if (M_WRITABLE(*m_head) == 0) {
m = m_dup(*m_head, M_DONTWAIT);
m_freem(*m_head);
@@ -6639,6 +6713,7 @@ bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags)
}
*m_head = m;
}
+
/*
* For TSO the controller needs two pieces of info,
* the MSS and the IP+TCP options length.
@@ -6714,9 +6789,12 @@ bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags)
/* Set the LSO flag in the TX BD */
*flags |= TX_BD_FLAGS_SW_LSO;
+
/* Set the length of IP + TCP options (in 32 bit words) */
*flags |= (((ip_hlen + tcp_hlen - sizeof(struct ip) -
sizeof(struct tcphdr)) >> 2) << 8);
+
+ DBRUN(sc->tso_frames_completed++);
return (*m_head);
}
@@ -6743,22 +6821,24 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head)
#ifdef BCE_DEBUG
u16 debug_prod;
#endif
+
int i, error, nsegs, rc = 0;
DBENTER(BCE_VERBOSE_SEND);
- DBPRINT(sc, BCE_INFO_SEND,
- "%s(enter): tx_prod = 0x%04X, tx_chain_prod = %04X, "
- "tx_prod_bseq = 0x%08X\n",
- __FUNCTION__, sc->tx_prod, (u16) TX_CHAIN_IDX(sc->tx_prod),
- sc->tx_prod_bseq);
+
+ /* Make sure we have room in the TX chain. */
+ if (sc->used_tx_bd >= sc->max_tx_bd)
+ goto bce_tx_encap_exit;
/* Transfer any checksum offload flags to the bd. */
m0 = *m_head;
if (m0->m_pkthdr.csum_flags) {
if (m0->m_pkthdr.csum_flags & CSUM_TSO) {
m0 = bce_tso_setup(sc, m_head, &flags);
- if (m0 == NULL)
+ if (m0 == NULL) {
+ DBRUN(sc->tso_frames_failed++);
goto bce_tx_encap_exit;
+ }
mss = htole16(m0->m_pkthdr.tso_segsz);
} else {
if (m0->m_pkthdr.csum_flags & CSUM_IP)
@@ -6785,8 +6865,7 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head)
/* Check if the DMA mapping was successful */
if (error == EFBIG) {
-
- sc->fragmented_mbuf_count++;
+ sc->mbuf_frag_count++;
/* Try to defrag the mbuf. */
m0 = m_collapse(*m_head, M_DONTWAIT, BCE_MAX_SEGMENTS);
@@ -6801,8 +6880,8 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head)
/* Defrag was successful, try mapping again */
*m_head = m0;
- error = bus_dmamap_load_mbuf_sg(sc->tx_mbuf_tag, map, m0,
- segs, &nsegs, BUS_DMA_NOWAIT);
+ error = bus_dmamap_load_mbuf_sg(sc->tx_mbuf_tag,
+ map, m0, segs, &nsegs, BUS_DMA_NOWAIT);
/* Still getting an error after a defrag. */
if (error == ENOMEM) {
@@ -6864,9 +6943,11 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head)
txbd= &sc->tx_bd_chain[TX_PAGE(chain_prod)]
[TX_IDX(chain_prod)];
- txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr));
- txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr));
- txbd->tx_bd_mss_nbytes = htole32(mss << 16) |
+ txbd->tx_bd_haddr_lo =
+ htole32(BCE_ADDR_LO(segs[i].ds_addr));
+ txbd->tx_bd_haddr_hi =
+ htole32(BCE_ADDR_HI(segs[i].ds_addr));
+ txbd->tx_bd_mss_nbytes = htole32(mss << 16) |
htole16(segs[i].ds_len);
txbd->tx_bd_vlan_tag = htole16(vlan_tag);
txbd->tx_bd_flags = htole16(flags);
@@ -6879,12 +6960,8 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head)
/* Set the END flag on the last TX buffer descriptor. */
txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_END);
- DBRUNMSG(BCE_EXTREME_SEND, bce_dump_tx_chain(sc, debug_prod, nsegs));
-
- DBPRINT(sc, BCE_INFO_SEND,
- "%s( end ): prod = 0x%04X, chain_prod = 0x%04X, "
- "prod_bseq = 0x%08X\n",
- __FUNCTION__, prod, chain_prod, prod_bseq);
+ DBRUNMSG(BCE_EXTREME_SEND,
+ bce_dump_tx_chain(sc, debug_prod, nsegs));
/*
* Ensure that the mbuf pointer for this transmission
@@ -6910,11 +6987,11 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head)
sc->tx_prod = prod;
sc->tx_prod_bseq = prod_bseq;
- DBPRINT(sc, BCE_INFO_SEND,
- "%s(exit): prod = 0x%04X, chain_prod = %04X, "
- "prod_bseq = 0x%08X\n", __FUNCTION__,
- sc->tx_prod, (u16) TX_CHAIN_IDX(sc->tx_prod),
- sc->tx_prod_bseq);
+ /* Tell the chip about the waiting TX frames. */
+ REG_WR16(sc, MB_GET_CID_ADDR(TX_CID) +
+ BCE_L2MQ_TX_HOST_BIDX, sc->tx_prod);
+ REG_WR(sc, MB_GET_CID_ADDR(TX_CID) +
+ BCE_L2MQ_TX_HOST_BSEQ, sc->tx_prod_bseq);
bce_tx_encap_exit:
DBEXIT(BCE_VERBOSE_SEND);
@@ -7006,23 +7083,6 @@ bce_start_locked(struct ifnet *ifp)
DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): Inserted %d frames into "
"send queue.\n", __FUNCTION__, count);
- REG_WR(sc, BCE_MQ_COMMAND, REG_RD(sc, BCE_MQ_COMMAND) |
- BCE_MQ_COMMAND_NO_MAP_ERROR);
-
- /* Write the mailbox and tell the chip about the waiting tx_bd's. */
- DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): MB_GET_CID_ADDR(TX_CID) = "
- "0x%08X; BCE_L2MQ_TX_HOST_BIDX = 0x%08X, sc->tx_prod = 0x%04X\n",
- __FUNCTION__, MB_GET_CID_ADDR(TX_CID),
- BCE_L2MQ_TX_HOST_BIDX, sc->tx_prod);
- REG_WR16(sc, MB_GET_CID_ADDR(TX_CID) +
- BCE_L2MQ_TX_HOST_BIDX, sc->tx_prod);
-
- DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): MB_GET_CID_ADDR(TX_CID) = "
- "0x%08X; BCE_L2MQ_TX_HOST_BSEQ = 0x%08X, sc->tx_prod_bseq = "
- "0x%04X\n", __FUNCTION__, MB_GET_CID_ADDR(TX_CID),
- BCE_L2MQ_TX_HOST_BSEQ, sc->tx_prod_bseq);
- REG_WR(sc, MB_GET_CID_ADDR(TX_CID) + BCE_L2MQ_TX_HOST_BSEQ, sc->tx_prod_bseq);
-
/* Set the tx timeout. */
sc->watchdog_timer = BCE_TX_TIMEOUT;
@@ -7103,19 +7163,19 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
/* No buffer allocation size changes are necessary. */
#else
/* Recalculate our buffer allocation sizes. */
- if ((ifp->if_mtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN +
+ if ((ifp->if_mtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN +
ETHER_CRC_LEN) > MCLBYTES) {
sc->rx_bd_mbuf_alloc_size = MJUM9BYTES;
- sc->rx_bd_mbuf_align_pad =
+ sc->rx_bd_mbuf_align_pad =
roundup2(MJUM9BYTES, 16) - MJUM9BYTES;
- sc->rx_bd_mbuf_data_len =
+ sc->rx_bd_mbuf_data_len =
sc->rx_bd_mbuf_alloc_size -
sc->rx_bd_mbuf_align_pad;
} else {
sc->rx_bd_mbuf_alloc_size = MCLBYTES;
- sc->rx_bd_mbuf_align_pad =
+ sc->rx_bd_mbuf_align_pad =
roundup2(MCLBYTES, 16) - MCLBYTES;
- sc->rx_bd_mbuf_data_len =
+ sc->rx_bd_mbuf_data_len =
sc->rx_bd_mbuf_alloc_size -
sc->rx_bd_mbuf_align_pad;
}
@@ -7161,7 +7221,7 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
/* Add/Delete multicast address */
case SIOCADDMULTI:
case SIOCDELMULTI:
- DBPRINT(sc, BCE_VERBOSE_MISC,
+ DBPRINT(sc, BCE_VERBOSE_MISC,
"Received SIOCADDMULTI/SIOCDELMULTI\n");
BCE_LOCK(sc);
@@ -7174,7 +7234,7 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
/* Set/Get Interface media */
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
- DBPRINT(sc, BCE_VERBOSE_MISC,
+ DBPRINT(sc, BCE_VERBOSE_MISC,
"Received SIOCSIFMEDIA/SIOCGIFMEDIA\n");
mii = device_get_softc(sc->bce_miibus);
@@ -7185,7 +7245,7 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
/* Set interface capability */
case SIOCSIFCAP:
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
- DBPRINT(sc, BCE_INFO_MISC,
+ DBPRINT(sc, BCE_INFO_MISC,
"Received SIOCSIFCAP = 0x%08X\n", (u32) mask);
/* Toggle the TX checksum capabilities enable flag. */
@@ -7270,7 +7330,7 @@ bce_watchdog(struct bce_softc *sc)
goto bce_watchdog_exit;
BCE_PRINTF("%s(%d): Watchdog timeout occurred, resetting!\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
DBRUNMSG(BCE_INFO,
bce_dump_driver_state(sc);
@@ -7336,7 +7396,7 @@ bce_intr(void *xsc)
* interrupt then there's nothing to do.
*/
if ((sc->status_block->status_idx == sc->last_status_idx) &&
- (REG_RD(sc, BCE_PCICFG_MISC_STATUS) &
+ (REG_RD(sc, BCE_PCICFG_MISC_STATUS) &
BCE_PCICFG_MISC_STATUS_INTA_VALUE)) {
DBPRINT(sc, BCE_VERBOSE_INTR, "%s(): Spurious interrupt.\n",
__FUNCTION__);
@@ -7361,17 +7421,17 @@ bce_intr(void *xsc)
BCE_PRINTF("Simulating unexpected status attention "
"bit set.");
sc->unexpected_attention_sim_count++;
- status_attn_bits = status_attn_bits |
+ status_attn_bits = status_attn_bits |
STATUS_ATTN_BITS_PARITY_ERROR);
/* Was it a link change interrupt? */
if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) !=
- (sc->status_block->status_attn_bits_ack &
+ (sc->status_block->status_attn_bits_ack &
STATUS_ATTN_BITS_LINK_STATE)) {
bce_phy_intr(sc);
/* Clear transient updates during link state change. */
- REG_WR(sc, BCE_HC_COMMAND, sc->hc_command |
+ REG_WR(sc, BCE_HC_COMMAND, sc->hc_command |
BCE_HC_COMMAND_COAL_NOW_WO_INT);
REG_RD(sc, BCE_HC_COMMAND);
}
@@ -7384,7 +7444,7 @@ bce_intr(void *xsc)
sc->unexpected_attention_count++;
BCE_PRINTF("%s(%d): Fatal attention detected: "
- "0x%08X\n", __FILE__, __LINE__,
+ "0x%08X\n", __FILE__, __LINE__,
sc->status_block->status_attn_bits);
DBRUNMSG(BCE_FATAL,
@@ -7420,7 +7480,7 @@ bce_intr(void *xsc)
hw_rx_cons = bce_get_hw_rx_cons(sc);
hw_tx_cons = bce_get_hw_tx_cons(sc);
- if ((hw_rx_cons == sc->hw_rx_cons) &&
+ if ((hw_rx_cons == sc->hw_rx_cons) &&
(hw_tx_cons == sc->hw_tx_cons))
break;
@@ -7433,7 +7493,7 @@ bce_intr(void *xsc)
bce_enable_intr(sc, 0);
/* Handle any frames that arrived while handling the interrupt. */
- if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
bce_start_locked(ifp);
@@ -7560,7 +7620,7 @@ bce_stats_update(struct bce_softc *sc)
*/
if (!(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) &&
!(BCE_CHIP_ID(sc) == BCE_CHIP_ID_5708_A0))
- ifp->if_oerrors +=
+ ifp->if_oerrors +=
(u_long) stats->stat_Dot3StatsCarrierSenseErrors;
/*
@@ -7799,25 +7859,28 @@ bce_pulse(void *xsc)
sc->bc_state = bce_shmem_rd(sc, BCE_BC_STATE_CONDITION);
/* Report whether the bootcode still knows the driver is running. */
- if (sc->bce_drv_cardiac_arrest == FALSE) {
- if (!(sc->bc_state & BCE_CONDITION_DRV_PRESENT)) {
- sc->bce_drv_cardiac_arrest = TRUE;
- BCE_PRINTF("%s(): Bootcode lost the driver pulse! "
- "(bc_state = 0x%08X)\n", __FUNCTION__,
- sc->bc_state);
- }
- } else {
- /*
- * Not supported by all bootcode versions.
- * (v5.0.11+ and v5.2.1+) Older bootcode
- * will require the driver to reset the
- * controller to clear this condition.
- */
- if (sc->bc_state & BCE_CONDITION_DRV_PRESENT) {
- sc->bce_drv_cardiac_arrest = FALSE;
- BCE_PRINTF("%s(): Bootcode found the driver pulse! "
- "(bc_state = 0x%08X)\n", __FUNCTION__,
- sc->bc_state);
+ if (bootverbose) {
+ if (sc->bce_drv_cardiac_arrest == FALSE) {
+ if (!(sc->bc_state & BCE_CONDITION_DRV_PRESENT)) {
+ sc->bce_drv_cardiac_arrest = TRUE;
+ BCE_PRINTF("%s(): Warning: bootcode "
+ "thinks driver is absent! "
+ "(bc_state = 0x%08X)\n",
+ __FUNCTION__, sc->bc_state);
+ }
+ } else {
+ /*
+ * Not supported by all bootcode versions.
+ * (v5.0.11+ and v5.2.1+) Older bootcode
+ * will require the driver to reset the
+ * controller to clear this condition.
+ */
+ if (sc->bc_state & BCE_CONDITION_DRV_PRESENT) {
+ sc->bce_drv_cardiac_arrest = FALSE;
+ BCE_PRINTF("%s(): Bootcode found the "
+ "driver pulse! (bc_state = 0x%08X)\n",
+ __FUNCTION__, sc->bc_state);
+ }
}
}
@@ -7874,7 +7937,7 @@ bce_tick(void *xsc)
/* Check if the link has come up. */
if ((mii->mii_media_status & IFM_ACTIVE) &&
(IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)) {
- DBPRINT(sc, BCE_VERBOSE_MISC,
+ DBPRINT(sc, BCE_VERBOSE_MISC,
"%s(): Link up!\n", __FUNCTION__);
sc->bce_link_up = TRUE;
if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T ||
@@ -8011,6 +8074,62 @@ bce_sysctl_stats_block(SYSCTL_HANDLER_ARGS)
/****************************************************************************/
+/* Allows the stat counters to be cleared without unloading/reloading the */
+/* driver. */
+/* */
+/* Returns: */
+/* 0 for success, positive value for failure. */
+/****************************************************************************/
+static int
+bce_sysctl_stats_clear(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ int result;
+ struct bce_softc *sc;
+
+ result = -1;
+ error = sysctl_handle_int(oidp, &result, 0, req);
+
+ if (error || !req->newptr)
+ return (error);
+
+ if (result == 1) {
+ sc = (struct bce_softc *)arg1;
+
+ /* Clear the internal H/W statistics counters. */
+ REG_WR(sc, BCE_HC_COMMAND, BCE_HC_COMMAND_CLR_STAT_NOW);
+
+ /* Reset the driver maintained statistics. */
+ sc->interrupts_rx =
+ sc->interrupts_tx = 0;
+ sc->tso_frames_requested =
+ sc->tso_frames_completed =
+ sc->tso_frames_failed = 0;
+ sc->rx_empty_count =
+ sc->tx_full_count = 0;
+ sc->rx_low_watermark = USABLE_RX_BD;
+ sc->tx_hi_watermark = 0;
+ sc->l2fhdr_error_count =
+ sc->l2fhdr_error_sim_count = 0;
+ sc->mbuf_alloc_failed_count =
+ sc->mbuf_alloc_failed_sim_count = 0;
+ sc->dma_map_addr_rx_failed_count =
+ sc->dma_map_addr_tx_failed_count = 0;
+ sc->mbuf_frag_count = 0;
+ sc->csum_offload_tcp_udp =
+ sc->csum_offload_ip = 0;
+ sc->vlan_tagged_frames_rcvd =
+ sc->vlan_tagged_frames_stripped = 0;
+
+ /* Clear firmware maintained statistics. */
+ REG_WR_IND(sc, 0x120084, 0);
+ }
+
+ return error;
+}
+
+
+/****************************************************************************/
/* Allows the bootcode state to be dumped through the sysctl interface. */
/* */
/* Returns: */
@@ -8252,8 +8371,7 @@ static int
bce_sysctl_dump_ctx(SYSCTL_HANDLER_ARGS)
{
struct bce_softc *sc;
- int error;
- u16 result;
+ int error, result;
result = -1;
error = sysctl_handle_int(oidp, &result, 0, req);
@@ -8352,8 +8470,8 @@ bce_add_sysctls(struct bce_softc *sc)
0, "Number of mbuf allocation failures");
SYSCTL_ADD_INT(ctx, children, OID_AUTO,
- "fragmented_mbuf_count",
- CTLFLAG_RD, &sc->fragmented_mbuf_count,
+ "mbuf_frag_count",
+ CTLFLAG_RD, &sc->mbuf_frag_count,
0, "Number of fragmented mbufs");
#ifdef BCE_DEBUG
@@ -8367,7 +8485,7 @@ bce_add_sysctls(struct bce_softc *sc)
"dma_map_addr_failed_sim_count",
CTLFLAG_RD, &sc->dma_map_addr_failed_sim_count,
0, "Number of simulated DMA mapping failures");
-
+
#endif
SYSCTL_ADD_INT(ctx, children, OID_AUTO,
@@ -8424,18 +8542,48 @@ bce_add_sysctls(struct bce_softc *sc)
0, "Number of times the TX chain was full");
SYSCTL_ADD_INT(ctx, children, OID_AUTO,
- "requested_tso_frames",
- CTLFLAG_RD, &sc->requested_tso_frames,
- 0, "Number of TSO frames received");
+ "tso_frames_requested",
+ CTLFLAG_RD, &sc->tso_frames_requested,
+ 0, "Number of TSO frames requested");
+
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "tso_frames_completed",
+ CTLFLAG_RD, &sc->tso_frames_completed,
+ 0, "Number of TSO frames completed");
+
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "tso_frames_failed",
+ CTLFLAG_RD, &sc->tso_frames_failed,
+ 0, "Number of TSO frames failed");
+
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "csum_offload_ip",
+ CTLFLAG_RD, &sc->csum_offload_ip,
+ 0, "Number of IP checksum offload frames");
+
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "csum_offload_tcp_udp",
+ CTLFLAG_RD, &sc->csum_offload_tcp_udp,
+ 0, "Number of TCP/UDP checksum offload frames");
+
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "vlan_tagged_frames_rcvd",
+ CTLFLAG_RD, &sc->vlan_tagged_frames_rcvd,
+ 0, "Number of VLAN tagged frames received");
+
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "vlan_tagged_frames_stripped",
+ CTLFLAG_RD, &sc->vlan_tagged_frames_stripped,
+ 0, "Number of VLAN tagged frames stripped");
SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
- "rx_interrupts",
- CTLFLAG_RD, &sc->rx_interrupts,
+ "interrupts_rx",
+ CTLFLAG_RD, &sc->interrupts_rx,
0, "Number of RX interrupts");
SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
- "tx_interrupts",
- CTLFLAG_RD, &sc->tx_interrupts,
+ "interrupts_tx",
+ CTLFLAG_RD, &sc->interrupts_tx,
0, "Number of TX interrupts");
#endif
@@ -8730,12 +8878,17 @@ bce_add_sysctls(struct bce_softc *sc)
SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"status_block", CTLTYPE_INT | CTLFLAG_RW,
(void *)sc, 0,
- bce_sysctl_status_block, "I", "Status block");
+ bce_sysctl_status_block, "I", "Dump status block");
SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"stats_block", CTLTYPE_INT | CTLFLAG_RW,
(void *)sc, 0,
- bce_sysctl_stats_block, "I", "Stats block");
+ bce_sysctl_stats_block, "I", "Dump statistics block");
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ "stats_clear", CTLTYPE_INT | CTLFLAG_RW,
+ (void *)sc, 0,
+ bce_sysctl_stats_clear, "I", "Clear statistics block");
SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"bc_state", CTLTYPE_INT | CTLFLAG_RW,
@@ -8882,18 +9035,18 @@ bce_dump_enet(struct bce_softc *sc, struct mbuf *m)
switch (ip->ip_p) {
case IPPROTO_TCP:
th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));
- BCE_PRINTF("-tcp: dest = %d, src = %d, hlen = %d bytes, "
- "flags = 0x%b, csum = 0x%04X\n",
- ntohs(th->th_dport), ntohs(th->th_sport),
- (th->th_off << 2), th->th_flags,
+ BCE_PRINTF("-tcp: dest = %d, src = %d, hlen = "
+ "%d bytes, flags = 0x%b, csum = 0x%04X\n",
+ ntohs(th->th_dport), ntohs(th->th_sport),
+ (th->th_off << 2), th->th_flags,
"\20\10CWR\07ECE\06URG\05ACK\04PSH\03RST"
"\02SYN\01FIN", ntohs(th->th_sum));
break;
case IPPROTO_UDP:
uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
BCE_PRINTF("-udp: dest = %d, src = %d, len = %d "
- "bytes, csum = 0x%04X\n", ntohs(uh->uh_dport),
- ntohs(uh->uh_sport), ntohs(uh->uh_ulen),
+ "bytes, csum = 0x%04X\n", ntohs(uh->uh_dport),
+ ntohs(uh->uh_sport), ntohs(uh->uh_ulen),
ntohs(uh->uh_sum));
break;
case IPPROTO_ICMP:
@@ -8960,10 +9113,10 @@ bce_dump_mbuf(struct bce_softc *sc, struct mbuf *m)
if (mp->m_flags & M_PKTHDR) {
BCE_PRINTF("- m_pkthdr: len = %d, flags = 0x%b, "
- "csum_flags = %b\n", mp->m_pkthdr.len,
+ "csum_flags = %b\n", mp->m_pkthdr.len,
mp->m_flags, "\20\12M_BCAST\13M_MCAST\14M_FRAG"
"\15M_FIRSTFRAG\16M_LASTFRAG\21M_VLANTAG"
- "\22M_PROMISC\23M_NOFREE",
+ "\22M_PROMISC\23M_NOFREE",
mp->m_pkthdr.csum_flags,
"\20\1CSUM_IP\2CSUM_TCP\3CSUM_UDP\4CSUM_IP_FRAGS"
"\5CSUM_FRAGMENT\6CSUM_TSO\11CSUM_IP_CHECKED"
@@ -8995,7 +9148,7 @@ bce_dump_mbuf(struct bce_softc *sc, struct mbuf *m)
printf("EXT_DISPOSABLE\n"); break;
case EXT_EXTREF:
printf("EXT_EXTREF\n"); break;
- default:
+ default:
printf("UNKNOWN\n");
}
}
@@ -9116,96 +9269,96 @@ bce_dump_txbd(struct bce_softc *sc, int idx, struct tx_bd *txbd)
else if ((idx & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE)
/* TX Chain page pointer. */
BCE_PRINTF("tx_bd[0x%04X]: haddr = 0x%08X:%08X, chain page "
- "pointer\n", idx, txbd->tx_bd_haddr_hi,
+ "pointer\n", idx, txbd->tx_bd_haddr_hi,
txbd->tx_bd_haddr_lo);
else {
/* Normal tx_bd entry. */
BCE_PRINTF("tx_bd[0x%04X]: haddr = 0x%08X:%08X, "
"mss_nbytes = 0x%08X, vlan tag = 0x%04X, flags = "
- "0x%04X (", idx, txbd->tx_bd_haddr_hi,
- txbd->tx_bd_haddr_lo, txbd->tx_bd_mss_nbytes,
+ "0x%04X (", idx, txbd->tx_bd_haddr_hi,
+ txbd->tx_bd_haddr_lo, txbd->tx_bd_mss_nbytes,
txbd->tx_bd_vlan_tag, txbd->tx_bd_flags);
if (txbd->tx_bd_flags & TX_BD_FLAGS_CONN_FAULT) {
- if (i>0)
- printf("|");
- printf("CONN_FAULT");
+ if (i>0)
+ printf("|");
+ printf("CONN_FAULT");
i++;
}
if (txbd->tx_bd_flags & TX_BD_FLAGS_TCP_UDP_CKSUM) {
- if (i>0)
- printf("|");
- printf("TCP_UDP_CKSUM");
+ if (i>0)
+ printf("|");
+ printf("TCP_UDP_CKSUM");
i++;
}
if (txbd->tx_bd_flags & TX_BD_FLAGS_IP_CKSUM) {
- if (i>0)
- printf("|");
- printf("IP_CKSUM");
+ if (i>0)
+ printf("|");
+ printf("IP_CKSUM");
i++;
}
if (txbd->tx_bd_flags & TX_BD_FLAGS_VLAN_TAG) {
- if (i>0)
- printf("|");
- printf("VLAN");
+ if (i>0)
+ printf("|");
+ printf("VLAN");
i++;
}
if (txbd->tx_bd_flags & TX_BD_FLAGS_COAL_NOW) {
- if (i>0)
- printf("|");
- printf("COAL_NOW");
+ if (i>0)
+ printf("|");
+ printf("COAL_NOW");
i++;
}
if (txbd->tx_bd_flags & TX_BD_FLAGS_DONT_GEN_CRC) {
- if (i>0)
- printf("|");
- printf("DONT_GEN_CRC");
+ if (i>0)
+ printf("|");
+ printf("DONT_GEN_CRC");
i++;
}
if (txbd->tx_bd_flags & TX_BD_FLAGS_START) {
- if (i>0)
- printf("|");
- printf("START");
+ if (i>0)
+ printf("|");
+ printf("START");
i++;
}
if (txbd->tx_bd_flags & TX_BD_FLAGS_END) {
- if (i>0)
- printf("|");
- printf("END");
+ if (i>0)
+ printf("|");
+ printf("END");
i++;
}
if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_LSO) {
- if (i>0)
- printf("|");
- printf("LSO");
+ if (i>0)
+ printf("|");
+ printf("LSO");
i++;
}
if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_OPTION_WORD) {
- if (i>0)
- printf("|");
- printf("SW_OPTION=%d", ((txbd->tx_bd_flags &
+ if (i>0)
+ printf("|");
+ printf("SW_OPTION=%d", ((txbd->tx_bd_flags &
TX_BD_FLAGS_SW_OPTION_WORD) >> 8)); i++;
}
if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_FLAGS) {
- if (i>0)
- printf("|");
- printf("SW_FLAGS");
+ if (i>0)
+ printf("|");
+ printf("SW_FLAGS");
i++;
}
if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_SNAP) {
- if (i>0)
- printf("|");
+ if (i>0)
+ printf("|");
printf("SNAP)");
} else {
printf(")\n");
@@ -9229,13 +9382,13 @@ bce_dump_rxbd(struct bce_softc *sc, int idx, struct rx_bd *rxbd)
else if ((idx & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE)
/* RX Chain page pointer. */
BCE_PRINTF("rx_bd[0x%04X]: haddr = 0x%08X:%08X, chain page "
- "pointer\n", idx, rxbd->rx_bd_haddr_hi,
+ "pointer\n", idx, rxbd->rx_bd_haddr_hi,
rxbd->rx_bd_haddr_lo);
else
/* Normal rx_bd entry. */
BCE_PRINTF("rx_bd[0x%04X]: haddr = 0x%08X:%08X, nbytes = "
- "0x%08X, flags = 0x%08X\n", idx, rxbd->rx_bd_haddr_hi,
- rxbd->rx_bd_haddr_lo, rxbd->rx_bd_len,
+ "0x%08X, flags = 0x%08X\n", idx, rxbd->rx_bd_haddr_hi,
+ rxbd->rx_bd_haddr_lo, rxbd->rx_bd_len,
rxbd->rx_bd_flags);
}
@@ -9325,57 +9478,57 @@ bce_dump_ctx(struct bce_softc *sc, u16 cid)
"index\n", CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_RX_NX_BDIDX));
BCE_PRINTF(" 0x%08X - (L2CTX_RX_HOST_PG_BDIDX) host page "
- "producer index\n", CTX_RD(sc, GET_CID_ADDR(cid),
+ "producer index\n", CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_RX_HOST_PG_BDIDX));
BCE_PRINTF(" 0x%08X - (L2CTX_RX_PG_BUF_SIZE) host rx_bd/page "
- "buffer size\n", CTX_RD(sc, GET_CID_ADDR(cid),
+ "buffer size\n", CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_RX_PG_BUF_SIZE));
BCE_PRINTF(" 0x%08X - (L2CTX_RX_NX_PG_BDHADDR_HI) h/w page "
- "chain address\n", CTX_RD(sc, GET_CID_ADDR(cid),
+ "chain address\n", CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_RX_NX_PG_BDHADDR_HI));
BCE_PRINTF(" 0x%08X - (L2CTX_RX_NX_PG_BDHADDR_LO) h/w page "
- "chain address\n", CTX_RD(sc, GET_CID_ADDR(cid),
+ "chain address\n", CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_RX_NX_PG_BDHADDR_LO));
BCE_PRINTF(" 0x%08X - (L2CTX_RX_NX_PG_BDIDX) h/w page "
- "consumer index\n", CTX_RD(sc, GET_CID_ADDR(cid),
+ "consumer index\n", CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_RX_NX_PG_BDIDX));
} else if (cid == TX_CID) {
if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) {
BCE_PRINTF(" 0x%08X - (L2CTX_TX_TYPE_XI) ctx type\n",
- CTX_RD(sc, GET_CID_ADDR(cid),
+ CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_TX_TYPE_XI));
BCE_PRINTF(" 0x%08X - (L2CTX_CMD_TX_TYPE_XI) ctx "
- "cmd\n", CTX_RD(sc, GET_CID_ADDR(cid),
+ "cmd\n", CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_TX_CMD_TYPE_XI));
BCE_PRINTF(" 0x%08X - (L2CTX_TX_TBDR_BDHADDR_HI_XI) "
- "h/w buffer descriptor address\n",
- CTX_RD(sc, GET_CID_ADDR(cid),
+ "h/w buffer descriptor address\n",
+ CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_TX_TBDR_BHADDR_HI_XI));
BCE_PRINTF(" 0x%08X - (L2CTX_TX_TBDR_BHADDR_LO_XI) "
- "h/w buffer descriptor address\n",
+ "h/w buffer descriptor address\n",
CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_TX_TBDR_BHADDR_LO_XI));
BCE_PRINTF(" 0x%08X - (L2CTX_TX_HOST_BIDX_XI) "
- "host producer index\n",
+ "host producer index\n",
CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_TX_HOST_BIDX_XI));
BCE_PRINTF(" 0x%08X - (L2CTX_TX_HOST_BSEQ_XI) "
- "host byte sequence\n",
+ "host byte sequence\n",
CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_TX_HOST_BSEQ_XI));
} else {
BCE_PRINTF(" 0x%08X - (L2CTX_TX_TYPE) ctx type\n",
CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_TX_TYPE));
BCE_PRINTF(" 0x%08X - (L2CTX_TX_CMD_TYPE) ctx cmd\n",
- CTX_RD(sc, GET_CID_ADDR(cid),
+ CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_TX_CMD_TYPE));
BCE_PRINTF(" 0x%08X - (L2CTX_TX_TBDR_BDHADDR_HI) "
- "h/w buffer descriptor address\n",
+ "h/w buffer descriptor address\n",
CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_TX_TBDR_BHADDR_HI));
BCE_PRINTF(" 0x%08X - (L2CTX_TX_TBDR_BHADDR_LO) "
- "h/w buffer descriptor address\n",
+ "h/w buffer descriptor address\n",
CTX_RD(sc, GET_CID_ADDR(cid),
BCE_L2CTX_TX_TBDR_BHADDR_LO));
BCE_PRINTF(" 0x%08X - (L2CTX_TX_HOST_BIDX) host "
@@ -9605,8 +9758,8 @@ bce_dump_ftqs(struct bce_softc *sc)
if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) ||
(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716))
- val = val |
- (BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCSQ_VALID_CNT_XI <<
+ val = val |
+ (BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCSQ_VALID_CNT_XI <<
24);
REG_WR(sc, BCE_HC_STAT_GEN_SEL_0, val);
@@ -10020,11 +10173,11 @@ bce_dump_driver_state(struct bce_softc *sc)
BCE_PRINTF(" 0x%08X - (sc->interrupts_generated) "
"h/w intrs\n", sc->interrupts_generated);
- BCE_PRINTF(" 0x%08X - (sc->rx_interrupts) "
- "rx interrupts handled\n", sc->rx_interrupts);
+ BCE_PRINTF(" 0x%08X - (sc->interrupts_rx) "
+ "rx interrupts handled\n", sc->interrupts_rx);
- BCE_PRINTF(" 0x%08X - (sc->tx_interrupts) "
- "tx interrupts handled\n", sc->tx_interrupts);
+ BCE_PRINTF(" 0x%08X - (sc->interrupts_tx) "
+ "tx interrupts handled\n", sc->interrupts_tx);
BCE_PRINTF(" 0x%08X - (sc->phy_interrupts) "
"phy interrupts handled\n", sc->phy_interrupts);
@@ -10122,15 +10275,15 @@ bce_dump_hw_state(struct bce_softc *sc)
val, BCE_MISC_ENABLE_STATUS_BITS);
val = REG_RD(sc, BCE_DMA_STATUS);
- BCE_PRINTF("0x%08X - (0x%06X) dma_status\n",
+ BCE_PRINTF("0x%08X - (0x%06X) dma_status\n",
val, BCE_DMA_STATUS);
val = REG_RD(sc, BCE_CTX_STATUS);
- BCE_PRINTF("0x%08X - (0x%06X) ctx_status\n",
+ BCE_PRINTF("0x%08X - (0x%06X) ctx_status\n",
val, BCE_CTX_STATUS);
val = REG_RD(sc, BCE_EMAC_STATUS);
- BCE_PRINTF("0x%08X - (0x%06X) emac_status\n",
+ BCE_PRINTF("0x%08X - (0x%06X) emac_status\n",
val, BCE_EMAC_STATUS);
val = REG_RD(sc, BCE_RPM_STATUS);
@@ -10139,16 +10292,16 @@ bce_dump_hw_state(struct bce_softc *sc)
/* ToDo: Create a #define for this constant. */
val = REG_RD(sc, 0x2004);
- BCE_PRINTF("0x%08X - (0x%06X) rlup_status\n",
+ BCE_PRINTF("0x%08X - (0x%06X) rlup_status\n",
val, 0x2004);
val = REG_RD(sc, BCE_RV2P_STATUS);
- BCE_PRINTF("0x%08X - (0x%06X) rv2p_status\n",
+ BCE_PRINTF("0x%08X - (0x%06X) rv2p_status\n",
val, BCE_RV2P_STATUS);
/* ToDo: Create a #define for this constant. */
val = REG_RD(sc, 0x2c04);
- BCE_PRINTF("0x%08X - (0x%06X) rdma_status\n",
+ BCE_PRINTF("0x%08X - (0x%06X) rdma_status\n",
val, 0x2c04);
val = REG_RD(sc, BCE_TBDR_STATUS);
@@ -10156,7 +10309,7 @@ bce_dump_hw_state(struct bce_softc *sc)
val, BCE_TBDR_STATUS);
val = REG_RD(sc, BCE_TDMA_STATUS);
- BCE_PRINTF("0x%08X - (0x%06X) tdma_status\n",
+ BCE_PRINTF("0x%08X - (0x%06X) tdma_status\n",
val, BCE_TDMA_STATUS);
val = REG_RD(sc, BCE_HC_STATUS);
@@ -10164,27 +10317,27 @@ bce_dump_hw_state(struct bce_softc *sc)
val, BCE_HC_STATUS);
val = REG_RD_IND(sc, BCE_TXP_CPU_STATE);
- BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_state\n",
+ BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_state\n",
val, BCE_TXP_CPU_STATE);
val = REG_RD_IND(sc, BCE_TPAT_CPU_STATE);
- BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_state\n",
+ BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_state\n",
val, BCE_TPAT_CPU_STATE);
val = REG_RD_IND(sc, BCE_RXP_CPU_STATE);
- BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_state\n",
+ BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_state\n",
val, BCE_RXP_CPU_STATE);
val = REG_RD_IND(sc, BCE_COM_CPU_STATE);
- BCE_PRINTF("0x%08X - (0x%06X) com_cpu_state\n",
+ BCE_PRINTF("0x%08X - (0x%06X) com_cpu_state\n",
val, BCE_COM_CPU_STATE);
val = REG_RD_IND(sc, BCE_MCP_CPU_STATE);
- BCE_PRINTF("0x%08X - (0x%06X) mcp_cpu_state\n",
+ BCE_PRINTF("0x%08X - (0x%06X) mcp_cpu_state\n",
val, BCE_MCP_CPU_STATE);
val = REG_RD_IND(sc, BCE_CP_CPU_STATE);
- BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_state\n",
+ BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_state\n",
val, BCE_CP_CPU_STATE);
BCE_PRINTF(
@@ -10306,15 +10459,15 @@ bce_dump_txp_state(struct bce_softc *sc, int regs)
BCE_PRINTF("Firmware version - %s\n", (char *) fw_version);
val = REG_RD_IND(sc, BCE_TXP_CPU_MODE);
- BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_mode\n",
+ BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_mode\n",
val, BCE_TXP_CPU_MODE);
val = REG_RD_IND(sc, BCE_TXP_CPU_STATE);
- BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_state\n",
+ BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_state\n",
val, BCE_TXP_CPU_STATE);
val = REG_RD_IND(sc, BCE_TXP_CPU_EVENT_MASK);
- BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_event_mask\n",
+ BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_event_mask\n",
val, BCE_TXP_CPU_EVENT_MASK);
if (regs) {
@@ -10327,8 +10480,8 @@ bce_dump_txp_state(struct bce_softc *sc, int regs)
/* Skip the big blank spaces */
if (i < 0x454000 && i > 0x5ffff)
BCE_PRINTF("0x%04X: 0x%08X 0x%08X "
- "0x%08X 0x%08X\n", i,
- REG_RD_IND(sc, i),
+ "0x%08X 0x%08X\n", i,
+ REG_RD_IND(sc, i),
REG_RD_IND(sc, i + 0x4),
REG_RD_IND(sc, i + 0x8),
REG_RD_IND(sc, i + 0xC));
@@ -10366,15 +10519,15 @@ bce_dump_rxp_state(struct bce_softc *sc, int regs)
BCE_PRINTF("Firmware version - %s\n", (char *) fw_version);
val = REG_RD_IND(sc, BCE_RXP_CPU_MODE);
- BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_mode\n",
+ BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_mode\n",
val, BCE_RXP_CPU_MODE);
val = REG_RD_IND(sc, BCE_RXP_CPU_STATE);
- BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_state\n",
+ BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_state\n",
val, BCE_RXP_CPU_STATE);
val = REG_RD_IND(sc, BCE_RXP_CPU_EVENT_MASK);
- BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_event_mask\n",
+ BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_event_mask\n",
val, BCE_RXP_CPU_EVENT_MASK);
if (regs) {
@@ -10387,10 +10540,10 @@ bce_dump_rxp_state(struct bce_softc *sc, int regs)
/* Skip the big blank sapces */
if (i < 0xc5400 && i > 0xdffff)
BCE_PRINTF("0x%04X: 0x%08X 0x%08X "
- "0x%08X 0x%08X\n", i,
- REG_RD_IND(sc, i),
+ "0x%08X 0x%08X\n", i,
+ REG_RD_IND(sc, i),
REG_RD_IND(sc, i + 0x4),
- REG_RD_IND(sc, i + 0x8),
+ REG_RD_IND(sc, i + 0x8),
REG_RD_IND(sc, i + 0xC));
}
}
@@ -10426,15 +10579,15 @@ bce_dump_tpat_state(struct bce_softc *sc, int regs)
BCE_PRINTF("Firmware version - %s\n", (char *) fw_version);
val = REG_RD_IND(sc, BCE_TPAT_CPU_MODE);
- BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_mode\n",
+ BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_mode\n",
val, BCE_TPAT_CPU_MODE);
val = REG_RD_IND(sc, BCE_TPAT_CPU_STATE);
- BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_state\n",
+ BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_state\n",
val, BCE_TPAT_CPU_STATE);
val = REG_RD_IND(sc, BCE_TPAT_CPU_EVENT_MASK);
- BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_event_mask\n",
+ BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_event_mask\n",
val, BCE_TPAT_CPU_EVENT_MASK);
if (regs) {
@@ -10448,9 +10601,9 @@ bce_dump_tpat_state(struct bce_softc *sc, int regs)
if (i < 0x854000 && i > 0x9ffff)
BCE_PRINTF("0x%04X: 0x%08X 0x%08X "
"0x%08X 0x%08X\n", i,
- REG_RD_IND(sc, i),
+ REG_RD_IND(sc, i),
REG_RD_IND(sc, i + 0x4),
- REG_RD_IND(sc, i + 0x8),
+ REG_RD_IND(sc, i + 0x8),
REG_RD_IND(sc, i + 0xC));
}
}
@@ -10486,11 +10639,11 @@ bce_dump_cp_state(struct bce_softc *sc, int regs)
BCE_PRINTF("Firmware version - %s\n", (char *) fw_version);
val = REG_RD_IND(sc, BCE_CP_CPU_MODE);
- BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_mode\n",
+ BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_mode\n",
val, BCE_CP_CPU_MODE);
val = REG_RD_IND(sc, BCE_CP_CPU_STATE);
- BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_state\n",
+ BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_state\n",
val, BCE_CP_CPU_STATE);
val = REG_RD_IND(sc, BCE_CP_CPU_EVENT_MASK);
@@ -10507,10 +10660,10 @@ bce_dump_cp_state(struct bce_softc *sc, int regs)
/* Skip the big blank spaces */
if (i < 0x185400 && i > 0x19ffff)
BCE_PRINTF("0x%04X: 0x%08X 0x%08X "
- "0x%08X 0x%08X\n", i,
- REG_RD_IND(sc, i),
+ "0x%08X 0x%08X\n", i,
+ REG_RD_IND(sc, i),
REG_RD_IND(sc, i + 0x4),
- REG_RD_IND(sc, i + 0x8),
+ REG_RD_IND(sc, i + 0x8),
REG_RD_IND(sc, i + 0xC));
}
}
@@ -10546,11 +10699,11 @@ bce_dump_com_state(struct bce_softc *sc, int regs)
BCE_PRINTF("Firmware version - %s\n", (char *) fw_version);
val = REG_RD_IND(sc, BCE_COM_CPU_MODE);
- BCE_PRINTF("0x%08X - (0x%06X) com_cpu_mode\n",
+ BCE_PRINTF("0x%08X - (0x%06X) com_cpu_mode\n",
val, BCE_COM_CPU_MODE);
val = REG_RD_IND(sc, BCE_COM_CPU_STATE);
- BCE_PRINTF("0x%08X - (0x%06X) com_cpu_state\n",
+ BCE_PRINTF("0x%08X - (0x%06X) com_cpu_state\n",
val, BCE_COM_CPU_STATE);
val = REG_RD_IND(sc, BCE_COM_CPU_EVENT_MASK);
@@ -10565,8 +10718,8 @@ bce_dump_com_state(struct bce_softc *sc, int regs)
for (int i = BCE_COM_CPU_MODE; i < 0x1053e8; i += 0x10) {
BCE_PRINTF("0x%04X: 0x%08X 0x%08X "
- "0x%08X 0x%08X\n", i,
- REG_RD_IND(sc, i),
+ "0x%08X 0x%08X\n", i,
+ REG_RD_IND(sc, i),
REG_RD_IND(sc, i + 0x4),
REG_RD_IND(sc, i + 0x8),
REG_RD_IND(sc, i + 0xC));
@@ -10605,17 +10758,17 @@ bce_dump_rv2p_state(struct bce_softc *sc)
val = 0x00000001;
REG_WR_IND(sc, BCE_RV2P_PROC1_ADDR_CMD, val);
fw_ver_low = REG_RD_IND(sc, BCE_RV2P_INSTR_LOW);
- fw_ver_high = REG_RD_IND(sc, BCE_RV2P_INSTR_HIGH) &
+ fw_ver_high = REG_RD_IND(sc, BCE_RV2P_INSTR_HIGH) &
BCE_RV2P_INSTR_HIGH_HIGH;
- BCE_PRINTF("RV2P1 Firmware version - 0x%08X:0x%08X\n",
+ BCE_PRINTF("RV2P1 Firmware version - 0x%08X:0x%08X\n",
fw_ver_high, fw_ver_low);
val = 0x00000001;
REG_WR_IND(sc, BCE_RV2P_PROC2_ADDR_CMD, val);
fw_ver_low = REG_RD_IND(sc, BCE_RV2P_INSTR_LOW);
- fw_ver_high = REG_RD_IND(sc, BCE_RV2P_INSTR_HIGH) &
+ fw_ver_high = REG_RD_IND(sc, BCE_RV2P_INSTR_HIGH) &
BCE_RV2P_INSTR_HIGH_HIGH;
- BCE_PRINTF("RV2P2 Firmware version - 0x%08X:0x%08X\n",
+ BCE_PRINTF("RV2P2 Firmware version - 0x%08X:0x%08X\n",
fw_ver_high, fw_ver_low);
/* Resume the RV2P processors. */
diff --git a/sys/dev/bce/if_bcereg.h b/sys/dev/bce/if_bcereg.h
index 49bba63..d6e7c24 100644
--- a/sys/dev/bce/if_bcereg.h
+++ b/sys/dev/bce/if_bcereg.h
@@ -284,8 +284,8 @@
"\02EnaPauseRcv" \
"\01EnaPausXmit"
-/*
- * Remove before release:
+/*
+ * Remove before release:
*
* #define BCE_DEBUG
* #define BCE_NVRAM_WRITE_SUPPORT
@@ -439,7 +439,7 @@
}
/* Runs a particular command based on the code path. */
-#define DBRUNCP(cp, args...) \
+#define DBRUNCP(cp, args...) \
if (BCE_CODE_PATH(cp)) { \
args; \
}
@@ -4116,7 +4116,7 @@ struct l2_fhdr {
#define BCE_RDMA_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
-
+
/*
* timer_reg definition
* offset: 0x4400
@@ -4476,107 +4476,107 @@ struct l2_fhdr {
* csch_reg definition
* offset: 0x4000
*/
-#define BCE_CSCH_COMMAND 0x00004000
-#define BCE_CSCH_CH_FTQ_CMD 0x000043f8
-#define BCE_CSCH_CH_FTQ_CTL 0x000043fc
-#define BCE_CSCH_CH_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
-#define BCE_CSCH_CH_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+#define BCE_CSCH_COMMAND 0x00004000
+#define BCE_CSCH_CH_FTQ_CMD 0x000043f8
+#define BCE_CSCH_CH_FTQ_CTL 0x000043fc
+#define BCE_CSCH_CH_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BCE_CSCH_CH_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
/*
* tbdr_reg definition
* offset: 0x5000
*/
-#define BCE_TBDR_COMMAND 0x00005000
-#define BCE_TBDR_COMMAND_ENABLE (1L<<0)
-#define BCE_TBDR_COMMAND_SOFT_RST (1L<<1)
-#define BCE_TBDR_COMMAND_MSTR_ABORT (1L<<4)
-
-#define BCE_TBDR_STATUS 0x00005004
-#define BCE_TBDR_STATUS_DMA_WAIT (1L<<0)
-#define BCE_TBDR_STATUS_FTQ_WAIT (1L<<1)
-#define BCE_TBDR_STATUS_FIFO_OVERFLOW (1L<<2)
-#define BCE_TBDR_STATUS_FIFO_UNDERFLOW (1L<<3)
-#define BCE_TBDR_STATUS_SEARCHMISS_ERROR (1L<<4)
-#define BCE_TBDR_STATUS_FTQ_ENTRY_CNT (1L<<5)
-#define BCE_TBDR_STATUS_BURST_CNT (1L<<6)
-
-#define BCE_TBDR_CONFIG 0x00005008
-#define BCE_TBDR_CONFIG_MAX_BDS (0xffL<<0)
-#define BCE_TBDR_CONFIG_SWAP_MODE (1L<<8)
-#define BCE_TBDR_CONFIG_PRIORITY (1L<<9)
+#define BCE_TBDR_COMMAND 0x00005000
+#define BCE_TBDR_COMMAND_ENABLE (1L<<0)
+#define BCE_TBDR_COMMAND_SOFT_RST (1L<<1)
+#define BCE_TBDR_COMMAND_MSTR_ABORT (1L<<4)
+
+#define BCE_TBDR_STATUS 0x00005004
+#define BCE_TBDR_STATUS_DMA_WAIT (1L<<0)
+#define BCE_TBDR_STATUS_FTQ_WAIT (1L<<1)
+#define BCE_TBDR_STATUS_FIFO_OVERFLOW (1L<<2)
+#define BCE_TBDR_STATUS_FIFO_UNDERFLOW (1L<<3)
+#define BCE_TBDR_STATUS_SEARCHMISS_ERROR (1L<<4)
+#define BCE_TBDR_STATUS_FTQ_ENTRY_CNT (1L<<5)
+#define BCE_TBDR_STATUS_BURST_CNT (1L<<6)
+
+#define BCE_TBDR_CONFIG 0x00005008
+#define BCE_TBDR_CONFIG_MAX_BDS (0xffL<<0)
+#define BCE_TBDR_CONFIG_SWAP_MODE (1L<<8)
+#define BCE_TBDR_CONFIG_PRIORITY (1L<<9)
#define BCE_TBDR_CONFIG_CACHE_NEXT_PAGE_PTRS (1L<<10)
-#define BCE_TBDR_CONFIG_PAGE_SIZE (0xfL<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_256 (0L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_512 (1L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_1K (2L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_2K (3L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_4K (4L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_8K (5L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_16K (6L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_32K (7L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_64K (8L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_128K (9L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_256K (10L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_512K (11L<<24)
-#define BCE_TBDR_CONFIG_PAGE_SIZE_1M (12L<<24)
-
-#define BCE_TBDR_DEBUG_VECT_PEEK 0x0000500c
-#define BCE_TBDR_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
-#define BCE_TBDR_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
-#define BCE_TBDR_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
-#define BCE_TBDR_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
-#define BCE_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
-#define BCE_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
-
-#define BCE_TBDR_FTQ_DATA 0x000053c0
-#define BCE_TBDR_FTQ_CMD 0x000053f8
-#define BCE_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0)
-#define BCE_TBDR_FTQ_CMD_WR_TOP (1L<<10)
-#define BCE_TBDR_FTQ_CMD_WR_TOP_0 (0L<<10)
-#define BCE_TBDR_FTQ_CMD_WR_TOP_1 (1L<<10)
-#define BCE_TBDR_FTQ_CMD_SFT_RESET (1L<<25)
-#define BCE_TBDR_FTQ_CMD_RD_DATA (1L<<26)
-#define BCE_TBDR_FTQ_CMD_ADD_INTERVEN (1L<<27)
-#define BCE_TBDR_FTQ_CMD_ADD_DATA (1L<<28)
-#define BCE_TBDR_FTQ_CMD_INTERVENE_CLR (1L<<29)
-#define BCE_TBDR_FTQ_CMD_POP (1L<<30)
-#define BCE_TBDR_FTQ_CMD_BUSY (1L<<31)
-
-#define BCE_TBDR_FTQ_CTL 0x000053fc
-#define BCE_TBDR_FTQ_CTL_INTERVENE (1L<<0)
-#define BCE_TBDR_FTQ_CTL_OVERFLOW (1L<<1)
-#define BCE_TBDR_FTQ_CTL_FORCE_INTERVENE (1L<<2)
-#define BCE_TBDR_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
-#define BCE_TBDR_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+#define BCE_TBDR_CONFIG_PAGE_SIZE (0xfL<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_256 (0L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_512 (1L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_1K (2L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_2K (3L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_4K (4L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_8K (5L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_16K (6L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_32K (7L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_64K (8L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_128K (9L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_256K (10L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_512K (11L<<24)
+#define BCE_TBDR_CONFIG_PAGE_SIZE_1M (12L<<24)
+
+#define BCE_TBDR_DEBUG_VECT_PEEK 0x0000500c
+#define BCE_TBDR_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BCE_TBDR_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BCE_TBDR_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BCE_TBDR_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BCE_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BCE_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BCE_TBDR_FTQ_DATA 0x000053c0
+#define BCE_TBDR_FTQ_CMD 0x000053f8
+#define BCE_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BCE_TBDR_FTQ_CMD_WR_TOP (1L<<10)
+#define BCE_TBDR_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BCE_TBDR_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BCE_TBDR_FTQ_CMD_SFT_RESET (1L<<25)
+#define BCE_TBDR_FTQ_CMD_RD_DATA (1L<<26)
+#define BCE_TBDR_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BCE_TBDR_FTQ_CMD_ADD_DATA (1L<<28)
+#define BCE_TBDR_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BCE_TBDR_FTQ_CMD_POP (1L<<30)
+#define BCE_TBDR_FTQ_CMD_BUSY (1L<<31)
+
+#define BCE_TBDR_FTQ_CTL 0x000053fc
+#define BCE_TBDR_FTQ_CTL_INTERVENE (1L<<0)
+#define BCE_TBDR_FTQ_CTL_OVERFLOW (1L<<1)
+#define BCE_TBDR_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BCE_TBDR_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BCE_TBDR_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
/*
* tdma_reg definition
* offset: 0x5c00
*/
-#define BCE_TDMA_COMMAND 0x00005c00
-#define BCE_TDMA_COMMAND_ENABLED (1L<<0)
-#define BCE_TDMA_COMMAND_MASTER_ABORT (1L<<4)
-#define BCE_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7)
-
-#define BCE_TDMA_STATUS 0x00005c04
-#define BCE_TDMA_STATUS_DMA_WAIT (1L<<0)
-#define BCE_TDMA_STATUS_PAYLOAD_WAIT (1L<<1)
-#define BCE_TDMA_STATUS_PATCH_FTQ_WAIT (1L<<2)
+#define BCE_TDMA_COMMAND 0x00005c00
+#define BCE_TDMA_COMMAND_ENABLED (1L<<0)
+#define BCE_TDMA_COMMAND_MASTER_ABORT (1L<<4)
+#define BCE_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7)
+
+#define BCE_TDMA_STATUS 0x00005c04
+#define BCE_TDMA_STATUS_DMA_WAIT (1L<<0)
+#define BCE_TDMA_STATUS_PAYLOAD_WAIT (1L<<1)
+#define BCE_TDMA_STATUS_PATCH_FTQ_WAIT (1L<<2)
#define BCE_TDMA_STATUS_LOCK_WAIT (1L<<3)
#define BCE_TDMA_STATUS_FTQ_ENTRY_CNT (1L<<16)
#define BCE_TDMA_STATUS_BURST_CNT (1L<<17)
-#define BCE_TDMA_CONFIG 0x00005c08
-#define BCE_TDMA_CONFIG_ONE_DMA (1L<<0)
+#define BCE_TDMA_CONFIG 0x00005c08
+#define BCE_TDMA_CONFIG_ONE_DMA (1L<<0)
#define BCE_TDMA_CONFIG_ONE_RECORD (1L<<1)
#define BCE_TDMA_CONFIG_LIMIT_SZ (0xfL<<4)
#define BCE_TDMA_CONFIG_LIMIT_SZ_64 (0L<<4)
#define BCE_TDMA_CONFIG_LIMIT_SZ_128 (0x4L<<4)
#define BCE_TDMA_CONFIG_LIMIT_SZ_256 (0x6L<<4)
#define BCE_TDMA_CONFIG_LIMIT_SZ_512 (0x8L<<4)
-#define BCE_TDMA_CONFIG_LINE_SZ (0xfL<<8)
+#define BCE_TDMA_CONFIG_LINE_SZ (0xfL<<8)
#define BCE_TDMA_CONFIG_LINE_SZ_64 (0L<<8)
#define BCE_TDMA_CONFIG_LINE_SZ_128 (4L<<8)
#define BCE_TDMA_CONFIG_LINE_SZ_256 (6L<<8)
@@ -4612,7 +4612,7 @@ struct l2_fhdr {
#define BCE_TDMA_DR_INTF_FSM_DR_BUF (0x7L<<12)
#define BCE_TDMA_DR_INTF_FSM_DMAD (0x7L<<16)
-#define BCE_TDMA_DR_INTF_STATUS 0x00005c8c
+#define BCE_TDMA_DR_INTF_STATUS 0x00005c8c
#define BCE_TDMA_DR_INTF_STATUS_HOLE_PHASE (0x7L<<0)
#define BCE_TDMA_DR_INTF_STATUS_DATA_AVAIL (0x3L<<4)
#define BCE_TDMA_DR_INTF_STATUS_SHIFT_ADDR (0x7L<<8)
@@ -4621,8 +4621,8 @@ struct l2_fhdr {
#define BCE_TDMA_FTQ_DATA 0x00005fc0
#define BCE_TDMA_FTQ_CMD 0x00005ff8
-#define BCE_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0)
-#define BCE_TDMA_FTQ_CMD_WR_TOP (1L<<10)
+#define BCE_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BCE_TDMA_FTQ_CMD_WR_TOP (1L<<10)
#define BCE_TDMA_FTQ_CMD_WR_TOP_0 (0L<<10)
#define BCE_TDMA_FTQ_CMD_WR_TOP_1 (1L<<10)
#define BCE_TDMA_FTQ_CMD_SFT_RESET (1L<<25)
@@ -4645,7 +4645,7 @@ struct l2_fhdr {
* nvm_reg definition
* offset: 0x6400
*/
-#define BCE_NVM_COMMAND 0x00006400
+#define BCE_NVM_COMMAND 0x00006400
#define BCE_NVM_COMMAND_RST (1L<<0)
#define BCE_NVM_COMMAND_DONE (1L<<3)
#define BCE_NVM_COMMAND_DOIT (1L<<4)
@@ -4694,23 +4694,23 @@ struct l2_fhdr {
#define BCE_NVM_READ_NVM_READ_VALUE_SI (32L<<0)
#define BCE_NVM_CFG1 0x00006414
-#define BCE_NVM_CFG1_FLASH_MODE (1L<<0)
+#define BCE_NVM_CFG1_FLASH_MODE (1L<<0)
#define BCE_NVM_CFG1_BUFFER_MODE (1L<<1)
#define BCE_NVM_CFG1_PASS_MODE (1L<<2)
#define BCE_NVM_CFG1_BITBANG_MODE (1L<<3)
-#define BCE_NVM_CFG1_STATUS_BIT (0x7L<<4)
+#define BCE_NVM_CFG1_STATUS_BIT (0x7L<<4)
#define BCE_NVM_CFG1_STATUS_BIT_FLASH_RDY (0L<<4)
#define BCE_NVM_CFG1_STATUS_BIT_BUFFER_RDY (7L<<4)
#define BCE_NVM_CFG1_SPI_CLK_DIV (0xfL<<7)
#define BCE_NVM_CFG1_SEE_CLK_DIV (0x7ffL<<11)
#define BCE_NVM_CFG1_PROTECT_MODE (1L<<24)
-#define BCE_NVM_CFG1_FLASH_SIZE (1L<<25)
+#define BCE_NVM_CFG1_FLASH_SIZE (1L<<25)
#define BCE_NVM_CFG1_COMPAT_BYPASSS (1L<<31)
#define BCE_NVM_CFG2 0x00006418
#define BCE_NVM_CFG2_ERASE_CMD (0xffL<<0)
#define BCE_NVM_CFG2_DUMMY (0xffL<<8)
-#define BCE_NVM_CFG2_STATUS_CMD (0xffL<<16)
+#define BCE_NVM_CFG2_STATUS_CMD (0xffL<<16)
#define BCE_NVM_CFG3 0x0000641c
#define BCE_NVM_CFG3_BUFFER_RD_CMD (0xffL<<0)
@@ -4727,10 +4727,10 @@ struct l2_fhdr {
#define BCE_NVM_SW_ARB_ARB_REQ_CLR1 (1L<<5)
#define BCE_NVM_SW_ARB_ARB_REQ_CLR2 (1L<<6)
#define BCE_NVM_SW_ARB_ARB_REQ_CLR3 (1L<<7)
-#define BCE_NVM_SW_ARB_ARB_ARB0 (1L<<8)
-#define BCE_NVM_SW_ARB_ARB_ARB1 (1L<<9)
-#define BCE_NVM_SW_ARB_ARB_ARB2 (1L<<10)
-#define BCE_NVM_SW_ARB_ARB_ARB3 (1L<<11)
+#define BCE_NVM_SW_ARB_ARB_ARB0 (1L<<8)
+#define BCE_NVM_SW_ARB_ARB_ARB1 (1L<<9)
+#define BCE_NVM_SW_ARB_ARB_ARB2 (1L<<10)
+#define BCE_NVM_SW_ARB_ARB_ARB3 (1L<<11)
#define BCE_NVM_SW_ARB_REQ0 (1L<<12)
#define BCE_NVM_SW_ARB_REQ1 (1L<<13)
#define BCE_NVM_SW_ARB_REQ2 (1L<<14)
@@ -4741,8 +4741,8 @@ struct l2_fhdr {
#define BCE_NVM_ACCESS_ENABLE_WR_EN (1L<<1)
#define BCE_NVM_WRITE1 0x00006428
-#define BCE_NVM_WRITE1_WREN_CMD (0xffL<<0)
-#define BCE_NVM_WRITE1_WRDI_CMD (0xffL<<8)
+#define BCE_NVM_WRITE1_WREN_CMD (0xffL<<0)
+#define BCE_NVM_WRITE1_WRDI_CMD (0xffL<<8)
#define BCE_NVM_WRITE1_SR_DATA (0xffL<<16)
@@ -4753,7 +4753,7 @@ struct l2_fhdr {
#define BCE_HC_COMMAND 0x00006800
#define BCE_HC_COMMAND_ENABLE (1L<<0)
#define BCE_HC_COMMAND_SKIP_ABORT (1L<<4)
-#define BCE_HC_COMMAND_COAL_NOW (1L<<16)
+#define BCE_HC_COMMAND_COAL_NOW (1L<<16)
#define BCE_HC_COMMAND_COAL_NOW_WO_INT (1L<<17)
#define BCE_HC_COMMAND_STATS_NOW (1L<<18)
#define BCE_HC_COMMAND_FORCE_INT (0x3L<<19)
@@ -4769,7 +4769,7 @@ struct l2_fhdr {
#define BCE_HC_STATUS_MASTER_ABORT (1L<<0)
#define BCE_HC_STATUS_PARITY_ERROR_STATE (1L<<1)
#define BCE_HC_STATUS_PCI_CLK_CNT_STAT (1L<<16)
-#define BCE_HC_STATUS_CORE_CLK_CNT_STAT (1L<<17)
+#define BCE_HC_STATUS_CORE_CLK_CNT_STAT (1L<<17)
#define BCE_HC_STATUS_NUM_STATUS_BLOCKS_STAT (1L<<18)
#define BCE_HC_STATUS_NUM_INT_GEN_STAT (1L<<19)
#define BCE_HC_STATUS_NUM_INT_MBOX_WR_STAT (1L<<20)
@@ -4790,27 +4790,27 @@ struct l2_fhdr {
#define BCE_HC_CONFIG_ONE_SHOT (1L<<17)
#define BCE_HC_CONFIG_USE_INT_PARAM (1L<<18)
#define BCE_HC_CONFIG_SET_MASK_AT_RD (1L<<19)
-#define BCE_HC_CONFIG_PER_COLLECT_LIMIT (0xfL<<20)
+#define BCE_HC_CONFIG_PER_COLLECT_LIMIT (0xfL<<20)
#define BCE_HC_CONFIG_SB_ADDR_INC (0x7L<<24)
#define BCE_HC_CONFIG_SB_ADDR_INC_64B (0L<<24)
#define BCE_HC_CONFIG_SB_ADDR_INC_128B (1L<<24)
#define BCE_HC_CONFIG_SB_ADDR_INC_256B (2L<<24)
#define BCE_HC_CONFIG_SB_ADDR_INC_512B (3L<<24)
-#define BCE_HC_CONFIG_SB_ADDR_INC_1024B (4L<<24)
-#define BCE_HC_CONFIG_SB_ADDR_INC_2048B (5L<<24)
-#define BCE_HC_CONFIG_SB_ADDR_INC_4096B (6L<<24)
-#define BCE_HC_CONFIG_SB_ADDR_INC_8192B (7L<<24)
-#define BCE_HC_CONFIG_GEN_STAT_AVG_INTR (1L<<29)
+#define BCE_HC_CONFIG_SB_ADDR_INC_1024B (4L<<24)
+#define BCE_HC_CONFIG_SB_ADDR_INC_2048B (5L<<24)
+#define BCE_HC_CONFIG_SB_ADDR_INC_4096B (6L<<24)
+#define BCE_HC_CONFIG_SB_ADDR_INC_8192B (7L<<24)
+#define BCE_HC_CONFIG_GEN_STAT_AVG_INTR (1L<<29)
#define BCE_HC_CONFIG_UNMASK_ALL (1L<<30)
#define BCE_HC_CONFIG_TX_SEL (1L<<31)
-#define BCE_HC_ATTN_BITS_ENABLE 0x0000680c
+#define BCE_HC_ATTN_BITS_ENABLE 0x0000680c
#define BCE_HC_STATUS_ADDR_L 0x00006810
#define BCE_HC_STATUS_ADDR_H 0x00006814
#define BCE_HC_STATISTICS_ADDR_L 0x00006818
#define BCE_HC_STATISTICS_ADDR_H 0x0000681c
#define BCE_HC_TX_QUICK_CONS_TRIP 0x00006820
-#define BCE_HC_TX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
+#define BCE_HC_TX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
#define BCE_HC_TX_QUICK_CONS_TRIP_INT (0xffL<<16)
#define BCE_HC_COMP_PROD_TRIP 0x00006824
@@ -4818,14 +4818,14 @@ struct l2_fhdr {
#define BCE_HC_COMP_PROD_TRIP_INT (0xffL<<16)
#define BCE_HC_RX_QUICK_CONS_TRIP 0x00006828
-#define BCE_HC_RX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
+#define BCE_HC_RX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
#define BCE_HC_RX_QUICK_CONS_TRIP_INT (0xffL<<16)
-#define BCE_HC_RX_TICKS 0x0000682c
+#define BCE_HC_RX_TICKS 0x0000682c
#define BCE_HC_RX_TICKS_VALUE (0x3ffL<<0)
#define BCE_HC_RX_TICKS_INT (0x3ffL<<16)
-#define BCE_HC_TX_TICKS 0x00006830
+#define BCE_HC_TX_TICKS 0x00006830
#define BCE_HC_TX_TICKS_VALUE (0x3ffL<<0)
#define BCE_HC_TX_TICKS_INT (0x3ffL<<16)
@@ -4838,7 +4838,7 @@ struct l2_fhdr {
#define BCE_HC_CMD_TICKS_INT (0x3ffL<<16)
#define BCE_HC_PERIODIC_TICKS 0x0000683c
-#define BCE_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0)
+#define BCE_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0)
#define BCE_HC_PERIODIC_TICKS_HC_INT_PERIODIC_TICKS (0xffffL<<16)
#define BCE_HC_STAT_COLLECT_TICKS 0x00006840
@@ -4848,12 +4848,12 @@ struct l2_fhdr {
#define BCE_HC_STATS_TICKS_HC_STAT_TICKS (0xffffL<<8)
#define BCE_HC_STATS_INTERRUPT_STATUS 0x00006848
-#define BCE_HC_STATS_INTERRUPT_STATUS_SB_STATUS (0x1ffL<<0)
+#define BCE_HC_STATS_INTERRUPT_STATUS_SB_STATUS (0x1ffL<<0)
#define BCE_HC_STATS_INTERRUPT_STATUS_INT_STATUS (0x1ffL<<16)
#define BCE_HC_STAT_MEM_DATA 0x0000684c
#define BCE_HC_STAT_GEN_SEL_0 0x00006850
-#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0)
+#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0)
#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT0 (0L<<0)
#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT1 (1L<<0)
#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT2 (2L<<0)
@@ -4921,9 +4921,9 @@ struct l2_fhdr {
#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUPQ_VALID_CNT (66L<<0)
#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPQ_VALID_CNT (67L<<0)
#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPCQ_VALID_CNT (68L<<0)
-#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PPQ_VALID_CNT (69L<<0)
-#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PMQ_VALID_CNT (70L<<0)
-#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PTQ_VALID_CNT (71L<<0)
+#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PPQ_VALID_CNT (69L<<0)
+#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PMQ_VALID_CNT (70L<<0)
+#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PTQ_VALID_CNT (71L<<0)
#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMAQ_VALID_CNT (72L<<0)
#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCHQ_VALID_CNT (73L<<0)
#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDRQ_VALID_CNT (74L<<0)
@@ -6006,7 +6006,7 @@ struct l2_fhdr {
#define BCE_TAS_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
#define BCE_TAS_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
-
+
/*
* mcp_reg definition
* offset: 0x140000
@@ -6372,7 +6372,7 @@ struct fw_info {
struct bce_softc
{
- /* Interface info */
+ /* Interface info. Must be first!! */
struct ifnet *bce_ifp;
/* Parent device handle */
@@ -6403,167 +6403,168 @@ struct bce_softc
/* Interrupt handler. */
driver_intr_t *bce_intr;
- void *bce_intrhand;
- int bce_irq_rid;
- int bce_msi_count;
+ void *bce_intrhand;
+ int bce_irq_rid;
+ int bce_msi_count;
/* ASIC Chip ID. */
- u32 bce_chipid;
+ u32 bce_chipid;
/* General controller flags. */
- u32 bce_flags;
-#define BCE_PCIX_FLAG 0x00000001
-#define BCE_PCI_32BIT_FLAG 0x00000002
-#define BCE_RESERVED_FLAG 0x00000004
-#define BCE_NO_WOL_FLAG 0x00000008
-#define BCE_USING_DAC_FLAG 0x00000010
-#define BCE_USING_MSI_FLAG 0x00000020
-#define BCE_MFW_ENABLE_FLAG 0x00000040
-#define BCE_ONE_SHOT_MSI_FLAG 0x00000080
-#define BCE_USING_MSIX_FLAG 0x00000100
-#define BCE_PCIE_FLAG 0x00000200
+ u32 bce_flags;
+#define BCE_PCIX_FLAG 0x00000001
+#define BCE_PCI_32BIT_FLAG 0x00000002
+#define BCE_RESERVED_FLAG 0x00000004
+#define BCE_NO_WOL_FLAG 0x00000008
+#define BCE_USING_DAC_FLAG 0x00000010
+#define BCE_USING_MSI_FLAG 0x00000020
+#define BCE_MFW_ENABLE_FLAG 0x00000040
+#define BCE_ONE_SHOT_MSI_FLAG 0x00000080
+#define BCE_USING_MSIX_FLAG 0x00000100
+#define BCE_PCIE_FLAG 0x00000200
+#define BCE_USING_TX_FLOW_CONTROL 0x00000400
/* Controller capability flags. */
- u32 bce_cap_flags;
-#define BCE_MSI_CAPABLE_FLAG 0x00000001
-#define BCE_MSIX_CAPABLE_FLAG 0x00000002
-#define BCE_PCIE_CAPABLE_FLAG 0x00000004
-#define BCE_PCIX_CAPABLE_FLAG 0x00000008
+ u32 bce_cap_flags;
+#define BCE_MSI_CAPABLE_FLAG 0x00000001
+#define BCE_MSIX_CAPABLE_FLAG 0x00000002
+#define BCE_PCIE_CAPABLE_FLAG 0x00000004
+#define BCE_PCIX_CAPABLE_FLAG 0x00000008
/* PHY specific flags. */
- u32 bce_phy_flags;
-#define BCE_PHY_SERDES_FLAG 0x00000001
-#define BCE_PHY_CRC_FIX_FLAG 0x00000002
-#define BCE_PHY_PARALLEL_DETECT_FLAG 0x00000004
-#define BCE_PHY_2_5G_CAPABLE_FLAG 0x00000008
-#define BCE_PHY_INT_MODE_MASK_FLAG 0x00000300
-#define BCE_PHY_INT_MODE_AUTO_POLLING_FLAG 0x00000100
-#define BCE_PHY_INT_MODE_LINK_READY_FLAG 0x00000200
-#define BCE_PHY_IEEE_CLAUSE_45_FLAG 0x00000400
+ u32 bce_phy_flags;
+#define BCE_PHY_SERDES_FLAG 0x00000001
+#define BCE_PHY_CRC_FIX_FLAG 0x00000002
+#define BCE_PHY_PARALLEL_DETECT_FLAG 0x00000004
+#define BCE_PHY_2_5G_CAPABLE_FLAG 0x00000008
+#define BCE_PHY_INT_MODE_MASK_FLAG 0x00000300
+#define BCE_PHY_INT_MODE_AUTO_POLLING_FLAG 0x00000100
+#define BCE_PHY_INT_MODE_LINK_READY_FLAG 0x00000200
+#define BCE_PHY_IEEE_CLAUSE_45_FLAG 0x00000400
/* Values that need to be shared with the PHY driver. */
- u32 bce_shared_hw_cfg;
- u32 bce_port_hw_cfg;
+ u32 bce_shared_hw_cfg;
+ u32 bce_port_hw_cfg;
- bus_addr_t max_bus_addr;
+ bus_addr_t max_bus_addr;
/* PCI bus speed */
- u16 bus_speed_mhz;
+ u16 bus_speed_mhz;
/* PCIe link width */
- u16 link_width;
+ u16 link_width;
/* PCIe link speed */
- u16 link_speed;
+ u16 link_speed;
/* Flash NVRAM settings */
- struct flash_spec *bce_flash_info;
+ struct flash_spec *bce_flash_info;
/* Flash NVRAM size */
- u32 bce_flash_size;
+ u32 bce_flash_size;
/* Shared Memory base address */
- u32 bce_shmem_base;
+ u32 bce_shmem_base;
/* Name string */
- char * bce_name;
+ char *bce_name;
/* Tracks the version of bootcode firmware. */
- char bce_bc_ver[32];
+ char bce_bc_ver[32];
/* Tracks the version of management firmware. */
- char bce_mfw_ver[32];
+ char bce_mfw_ver[32];
- /*
+ /*
* Tracks the state of the firmware. 0 = Running while any
* other value indicates that the firmware is not responding.
*/
- u16 bce_fw_timed_out;
+ u16 bce_fw_timed_out;
- /*
+ /*
* An incrementing sequence used to coordinate messages passed
* from the driver to the firmware.
- */
- u16 bce_fw_wr_seq;
+ */
+ u16 bce_fw_wr_seq;
- /*
+ /*
* An incrementing sequence used to let the firmware know that
* the driver is still operating. Without the pulse, management
* firmware such as IPMI or UMP will operate in OS absent state.
- */
- u16 bce_fw_drv_pulse_wr_seq;
+ */
+ u16 bce_fw_drv_pulse_wr_seq;
/* Tracks whether firmware has lost the driver's pulse. */
- u16 bce_drv_cardiac_arrest;
+ u16 bce_drv_cardiac_arrest;
/* Ethernet MAC address. */
- u_char eaddr[6];
+ u_char eaddr[6];
- /*
+ /*
* These setting are used by the host coalescing (HC) block to
* to control how often the status block, statistics block and
* interrupts are generated.
- */
- u16 bce_tx_quick_cons_trip_int;
- u16 bce_tx_quick_cons_trip;
- u16 bce_rx_quick_cons_trip_int;
- u16 bce_rx_quick_cons_trip;
- u16 bce_tx_ticks_int;
- u16 bce_tx_ticks;
- u16 bce_rx_ticks_int;
- u16 bce_rx_ticks;
- u32 bce_stats_ticks;
+ */
+ u16 bce_tx_quick_cons_trip_int;
+ u16 bce_tx_quick_cons_trip;
+ u16 bce_rx_quick_cons_trip_int;
+ u16 bce_rx_quick_cons_trip;
+ u16 bce_tx_ticks_int;
+ u16 bce_tx_ticks;
+ u16 bce_rx_ticks_int;
+ u16 bce_rx_ticks;
+ u32 bce_stats_ticks;
/* ToDo: Can these be removed? */
- u16 bce_comp_prod_trip_int;
- u16 bce_comp_prod_trip;
- u16 bce_com_ticks_int;
- u16 bce_com_ticks;
- u16 bce_cmd_ticks_int;
- u16 bce_cmd_ticks;
+ u16 bce_comp_prod_trip_int;
+ u16 bce_comp_prod_trip;
+ u16 bce_com_ticks_int;
+ u16 bce_com_ticks;
+ u16 bce_cmd_ticks_int;
+ u16 bce_cmd_ticks;
/* The address of the integrated PHY on the MII bus. */
- int bce_phy_addr;
+ int bce_phy_addr;
/* The device handle for the MII bus child device. */
- device_t bce_miibus;
+ device_t bce_miibus;
/* Driver maintained TX chain pointers and byte counter. */
- u16 rx_prod;
- u16 rx_cons;
+ u16 rx_prod;
+ u16 rx_cons;
/* Counts the bytes used in the RX chain. */
- u32 rx_prod_bseq;
- u16 tx_prod;
- u16 tx_cons;
+ u32 rx_prod_bseq;
+ u16 tx_prod;
+ u16 tx_cons;
/* Counts the bytes used in the TX chain. */
- u32 tx_prod_bseq;
+ u32 tx_prod_bseq;
#ifdef BCE_JUMBO_HDRSPLIT
- u16 pg_prod;
- u16 pg_cons;
+ u16 pg_prod;
+ u16 pg_cons;
#endif
- int bce_link_up;
- struct callout bce_tick_callout;
- struct callout bce_pulse_callout;
+ int bce_link_up;
+ struct callout bce_tick_callout;
+ struct callout bce_pulse_callout;
/* Ticks until chip reset */
- int watchdog_timer;
+ int watchdog_timer;
/* Frame size and mbuf allocation size for RX frames. */
- u32 max_frame_size;
- int rx_bd_mbuf_alloc_size;
- int rx_bd_mbuf_data_len;
- int rx_bd_mbuf_align_pad;
+ u32 max_frame_size;
+ int rx_bd_mbuf_alloc_size;
+ int rx_bd_mbuf_data_len;
+ int rx_bd_mbuf_align_pad;
#ifdef BCE_JUMBO_HDRSPLIT
- int pg_bd_mbuf_alloc_size;
+ int pg_bd_mbuf_alloc_size;
#endif
/* Receive mode settings (i.e promiscuous, multicast, etc.). */
- u32 rx_mode;
+ u32 rx_mode;
/* Bus tag for the bce controller. */
bus_dma_tag_t parent_tag;
@@ -6595,9 +6596,9 @@ struct bce_softc
bus_addr_t status_block_paddr;
/* Driver maintained status block values. */
- u16 last_status_idx;
- u16 hw_rx_cons;
- u16 hw_tx_cons;
+ u16 last_status_idx;
+ u16 hw_rx_cons;
+ u16 hw_tx_cons;
/* H/W maintained statistics block. */
bus_dma_tag_t stats_tag;
@@ -6606,7 +6607,7 @@ struct bce_softc
bus_addr_t stats_block_paddr;
/* H/W maintained context block. */
- int ctx_pages;
+ int ctx_pages;
bus_dma_tag_t ctx_tag;
/* BCM5709/16 use host memory for context. */
@@ -6637,139 +6638,156 @@ struct bce_softc
#endif
/* Track the number of buffer descriptors in use. */
- u16 free_rx_bd;
- u16 max_rx_bd;
- u16 used_tx_bd;
- u16 max_tx_bd;
+ u16 free_rx_bd;
+ u16 max_rx_bd;
+ u16 used_tx_bd;
+ u16 max_tx_bd;
#ifdef BCE_JUMBO_HDRSPLIT
- u16 free_pg_bd;
- u16 max_pg_bd;
+ u16 free_pg_bd;
+ u16 max_pg_bd;
#endif
/* Provides access to hardware statistics through sysctl. */
- u64 stat_IfHCInOctets;
- u64 stat_IfHCInBadOctets;
- u64 stat_IfHCOutOctets;
- u64 stat_IfHCOutBadOctets;
- u64 stat_IfHCInUcastPkts;
- u64 stat_IfHCInMulticastPkts;
- u64 stat_IfHCInBroadcastPkts;
- u64 stat_IfHCOutUcastPkts;
- u64 stat_IfHCOutMulticastPkts;
- u64 stat_IfHCOutBroadcastPkts;
-
- u32 stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
- u32 stat_Dot3StatsCarrierSenseErrors;
- u32 stat_Dot3StatsFCSErrors;
- u32 stat_Dot3StatsAlignmentErrors;
- u32 stat_Dot3StatsSingleCollisionFrames;
- u32 stat_Dot3StatsMultipleCollisionFrames;
- u32 stat_Dot3StatsDeferredTransmissions;
- u32 stat_Dot3StatsExcessiveCollisions;
- u32 stat_Dot3StatsLateCollisions;
- u32 stat_EtherStatsCollisions;
- u32 stat_EtherStatsFragments;
- u32 stat_EtherStatsJabbers;
- u32 stat_EtherStatsUndersizePkts;
- u32 stat_EtherStatsOversizePkts;
- u32 stat_EtherStatsPktsRx64Octets;
- u32 stat_EtherStatsPktsRx65Octetsto127Octets;
- u32 stat_EtherStatsPktsRx128Octetsto255Octets;
- u32 stat_EtherStatsPktsRx256Octetsto511Octets;
- u32 stat_EtherStatsPktsRx512Octetsto1023Octets;
- u32 stat_EtherStatsPktsRx1024Octetsto1522Octets;
- u32 stat_EtherStatsPktsRx1523Octetsto9022Octets;
- u32 stat_EtherStatsPktsTx64Octets;
- u32 stat_EtherStatsPktsTx65Octetsto127Octets;
- u32 stat_EtherStatsPktsTx128Octetsto255Octets;
- u32 stat_EtherStatsPktsTx256Octetsto511Octets;
- u32 stat_EtherStatsPktsTx512Octetsto1023Octets;
- u32 stat_EtherStatsPktsTx1024Octetsto1522Octets;
- u32 stat_EtherStatsPktsTx1523Octetsto9022Octets;
- u32 stat_XonPauseFramesReceived;
- u32 stat_XoffPauseFramesReceived;
- u32 stat_OutXonSent;
- u32 stat_OutXoffSent;
- u32 stat_FlowControlDone;
- u32 stat_MacControlFramesReceived;
- u32 stat_XoffStateEntered;
- u32 stat_IfInFramesL2FilterDiscards;
- u32 stat_IfInRuleCheckerDiscards;
- u32 stat_IfInFTQDiscards;
- u32 stat_IfInMBUFDiscards;
- u32 stat_IfInRuleCheckerP4Hit;
- u32 stat_CatchupInRuleCheckerDiscards;
- u32 stat_CatchupInFTQDiscards;
- u32 stat_CatchupInMBUFDiscards;
- u32 stat_CatchupInRuleCheckerP4Hit;
+ u64 stat_IfHCInOctets;
+ u64 stat_IfHCInBadOctets;
+ u64 stat_IfHCOutOctets;
+ u64 stat_IfHCOutBadOctets;
+ u64 stat_IfHCInUcastPkts;
+ u64 stat_IfHCInMulticastPkts;
+ u64 stat_IfHCInBroadcastPkts;
+ u64 stat_IfHCOutUcastPkts;
+ u64 stat_IfHCOutMulticastPkts;
+ u64 stat_IfHCOutBroadcastPkts;
+
+ u32 stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
+ u32 stat_Dot3StatsCarrierSenseErrors;
+ u32 stat_Dot3StatsFCSErrors;
+ u32 stat_Dot3StatsAlignmentErrors;
+ u32 stat_Dot3StatsSingleCollisionFrames;
+ u32 stat_Dot3StatsMultipleCollisionFrames;
+ u32 stat_Dot3StatsDeferredTransmissions;
+ u32 stat_Dot3StatsExcessiveCollisions;
+ u32 stat_Dot3StatsLateCollisions;
+ u32 stat_EtherStatsCollisions;
+ u32 stat_EtherStatsFragments;
+ u32 stat_EtherStatsJabbers;
+ u32 stat_EtherStatsUndersizePkts;
+ u32 stat_EtherStatsOversizePkts;
+ u32 stat_EtherStatsPktsRx64Octets;
+ u32 stat_EtherStatsPktsRx65Octetsto127Octets;
+ u32 stat_EtherStatsPktsRx128Octetsto255Octets;
+ u32 stat_EtherStatsPktsRx256Octetsto511Octets;
+ u32 stat_EtherStatsPktsRx512Octetsto1023Octets;
+ u32 stat_EtherStatsPktsRx1024Octetsto1522Octets;
+ u32 stat_EtherStatsPktsRx1523Octetsto9022Octets;
+ u32 stat_EtherStatsPktsTx64Octets;
+ u32 stat_EtherStatsPktsTx65Octetsto127Octets;
+ u32 stat_EtherStatsPktsTx128Octetsto255Octets;
+ u32 stat_EtherStatsPktsTx256Octetsto511Octets;
+ u32 stat_EtherStatsPktsTx512Octetsto1023Octets;
+ u32 stat_EtherStatsPktsTx1024Octetsto1522Octets;
+ u32 stat_EtherStatsPktsTx1523Octetsto9022Octets;
+ u32 stat_XonPauseFramesReceived;
+ u32 stat_XoffPauseFramesReceived;
+ u32 stat_OutXonSent;
+ u32 stat_OutXoffSent;
+ u32 stat_FlowControlDone;
+ u32 stat_MacControlFramesReceived;
+ u32 stat_XoffStateEntered;
+ u32 stat_IfInFramesL2FilterDiscards;
+ u32 stat_IfInRuleCheckerDiscards;
+ u32 stat_IfInFTQDiscards;
+ u32 stat_IfInMBUFDiscards;
+ u32 stat_IfInRuleCheckerP4Hit;
+ u32 stat_CatchupInRuleCheckerDiscards;
+ u32 stat_CatchupInFTQDiscards;
+ u32 stat_CatchupInMBUFDiscards;
+ u32 stat_CatchupInRuleCheckerP4Hit;
/* Provides access to certain firmware statistics. */
- u32 com_no_buffers;
+ u32 com_no_buffers;
/* Recoverable failure counters. */
- u32 mbuf_alloc_failed_count;
- u32 fragmented_mbuf_count;
- u32 unexpected_attention_count;
- u32 l2fhdr_error_count;
- u32 dma_map_addr_tx_failed_count;
- u32 dma_map_addr_rx_failed_count;
+ u32 mbuf_alloc_failed_count;
+ u32 mbuf_frag_count;
+ u32 unexpected_attention_count;
+ u32 l2fhdr_error_count;
+ u32 dma_map_addr_tx_failed_count;
+ u32 dma_map_addr_rx_failed_count;
/* Host coalescing block command register */
- u32 hc_command;
+ u32 hc_command;
/* Bootcode state */
- u32 bc_state;
+ u32 bc_state;
#ifdef BCE_DEBUG
/* Simulated recoverable failure counters. */
- u32 mbuf_alloc_failed_sim_count;
- u32 unexpected_attention_sim_count;
- u32 l2fhdr_error_sim_count;
- u32 dma_map_addr_failed_sim_count;
+ u32 mbuf_alloc_failed_sim_count;
+ u32 unexpected_attention_sim_count;
+ u32 l2fhdr_error_sim_count;
+ u32 dma_map_addr_failed_sim_count;
/* Track the number of enqueued mbufs. */
- int debug_tx_mbuf_alloc;
- int debug_rx_mbuf_alloc;
+ int debug_tx_mbuf_alloc;
+ int debug_rx_mbuf_alloc;
#ifdef BCE_JUMBO_HDRSPLIT
- int debug_pg_mbuf_alloc;
+ int debug_pg_mbuf_alloc;
#endif
/* Track how many and what type of interrupts are generated. */
- u32 interrupts_generated;
- u32 interrupts_handled;
- u32 rx_interrupts;
- u32 tx_interrupts;
- u32 phy_interrupts;
+ u32 interrupts_generated;
+ u32 interrupts_handled;
+ u32 interrupts_rx;
+ u32 interrupts_tx;
+ u32 phy_interrupts;
/* Track interrupt time (25MHz clock). */
- u64 rx_intr_time;
- u64 tx_intr_time;
+ u64 rx_intr_time;
+ u64 tx_intr_time;
/* Lowest number of rx_bd's free. */
- u32 rx_low_watermark;
+ u32 rx_low_watermark;
/* Number of times the RX chain was empty. */
- u32 rx_empty_count;
+ u32 rx_empty_count;
#ifdef BCE_JUMBO_HDRSPLIT
-
/* Lowest number of pages free. */
- u32 pg_low_watermark;
+ u32 pg_low_watermark;
/* Number of times the page chain was empty. */
- u32 pg_empty_count;
+ u32 pg_empty_count;
#endif
/* Greatest number of tx_bd's used. */
- u32 tx_hi_watermark;
+ u32 tx_hi_watermark;
/* Number of times the TX chain was full. */
- u32 tx_full_count;
+ u32 tx_full_count;
+
+ /* Number of TSO frames requested. */
+ u32 tso_frames_requested;
+
+ /* Number of TSO frames completed. */
+ u32 tso_frames_completed;
+
+ /* Number of TSO frames failed. */
+ u32 tso_frames_failed;
+
+ /* Number of IP checksum offload frames.*/
+ u32 csum_offload_ip;
+
+ /* Number of TCP/UDP checksum offload frames.*/
+ u32 csum_offload_tcp_udp;
+
+ /* Number of VLAN tagged frames received. */
+ u32 vlan_tagged_frames_rcvd;
- /* Number of TSO frames enqueued. */
- u32 requested_tso_frames;
+ /* Number of VLAN tagged frames stripped. */
+ u32 vlan_tagged_frames_stripped;
#endif
};
diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c
index 96c5cc6..724778d 100644
--- a/sys/dev/bwi/if_bwi.c
+++ b/sys/dev/bwi/if_bwi.c
@@ -461,8 +461,8 @@ bwi_attach(struct bwi_softc *sc)
ifp->if_init = bwi_init;
ifp->if_ioctl = bwi_ioctl;
ifp->if_start = bwi_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
callout_init_mtx(&sc->sc_watchdog_timer, &sc->sc_mtx, 0);
diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c
index 5ca5098..fd36403 100644
--- a/sys/dev/bwn/if_bwn.c
+++ b/sys/dev/bwn/if_bwn.c
@@ -1193,8 +1193,8 @@ bwn_attach_pre(struct bwn_softc *sc)
ifp->if_init = bwn_init;
ifp->if_ioctl = bwn_ioctl;
ifp->if_start = bwn_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
return (0);
diff --git a/sys/dev/cas/if_cas.c b/sys/dev/cas/if_cas.c
index edcfec4..3522f7c 100644
--- a/sys/dev/cas/if_cas.c
+++ b/sys/dev/cas/if_cas.c
@@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#if defined(__powerpc__) || defined(__sparc64__)
+#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/openfirm.h>
#include <machine/ofw_machdep.h>
#endif
@@ -321,55 +322,82 @@ cas_attach(struct cas_softc *sc)
}
}
- CAS_WRITE_4(sc, CAS_PCS_DATAPATH, CAS_PCS_DATAPATH_MII);
-
- cas_mifinit(sc);
-
- /*
- * Look for an external PHY.
- */
- error = ENXIO;
- v = CAS_READ_4(sc, CAS_MIF_CONF);
- if ((v & CAS_MIF_CONF_MDI1) != 0) {
- v |= CAS_MIF_CONF_PHY_SELECT;
- CAS_WRITE_4(sc, CAS_MIF_CONF, v);
- switch (sc->sc_variant) {
- default:
- sc->sc_phyad = -1;
- break;
+ if ((sc->sc_flags & CAS_SERDES) == 0) {
+ CAS_WRITE_4(sc, CAS_PCS_DATAPATH, CAS_PCS_DATAPATH_MII);
+ CAS_BARRIER(sc, CAS_PCS_DATAPATH, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+ cas_mifinit(sc);
+ /*
+ * Look for an external PHY.
+ */
+ error = ENXIO;
+ v = CAS_READ_4(sc, CAS_MIF_CONF);
+ if ((v & CAS_MIF_CONF_MDI1) != 0) {
+ v |= CAS_MIF_CONF_PHY_SELECT;
+ CAS_WRITE_4(sc, CAS_MIF_CONF, v);
+ CAS_BARRIER(sc, CAS_MIF_CONF, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+ /* Enable/unfreeze the GMII pins of Saturn. */
+ if (sc->sc_variant == CAS_SATURN) {
+ CAS_WRITE_4(sc, CAS_SATURN_PCFG, 0);
+ CAS_BARRIER(sc, CAS_SATURN_PCFG, 4,
+ BUS_SPACE_BARRIER_READ |
+ BUS_SPACE_BARRIER_WRITE);
+ }
+ switch (sc->sc_variant) {
+ default:
+ sc->sc_phyad = -1;
+ break;
+ }
+ error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus,
+ cas_mediachange, cas_mediastatus);
}
- error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus,
- cas_mediachange, cas_mediastatus);
- }
-
- /*
- * Fall back on an internal PHY if no external PHY was found.
- */
- if (error != 0 && (v & CAS_MIF_CONF_MDI0) != 0) {
- v &= ~CAS_MIF_CONF_PHY_SELECT;
- CAS_WRITE_4(sc, CAS_MIF_CONF, v);
- switch (sc->sc_variant) {
- default:
- sc->sc_phyad = -1;
- break;
+ /*
+ * Fall back on an internal PHY if no external PHY was found.
+ */
+ if (error != 0 && (v & CAS_MIF_CONF_MDI0) != 0) {
+ v &= ~CAS_MIF_CONF_PHY_SELECT;
+ CAS_WRITE_4(sc, CAS_MIF_CONF, v);
+ CAS_BARRIER(sc, CAS_MIF_CONF, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+ /* Freeze the GMII pins of Saturn for saving power. */
+ if (sc->sc_variant == CAS_SATURN) {
+ CAS_WRITE_4(sc, CAS_SATURN_PCFG,
+ CAS_SATURN_PCFG_FSI);
+ CAS_BARRIER(sc, CAS_SATURN_PCFG, 4,
+ BUS_SPACE_BARRIER_READ |
+ BUS_SPACE_BARRIER_WRITE);
+ }
+ switch (sc->sc_variant) {
+ default:
+ sc->sc_phyad = -1;
+ break;
+ }
+ error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus,
+ cas_mediachange, cas_mediastatus);
}
- error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus,
- cas_mediachange, cas_mediastatus);
- }
-
- /*
- * Try the external PCS SERDES if we didn't find any PHYs.
- */
- if (error != 0) {
+ } else {
+ /*
+ * Use the external PCS SERDES.
+ */
CAS_WRITE_4(sc, CAS_PCS_DATAPATH, CAS_PCS_DATAPATH_SERDES);
+ CAS_BARRIER(sc, CAS_PCS_DATAPATH, 4, BUS_SPACE_BARRIER_WRITE);
+ /* Enable/unfreeze the SERDES pins of Saturn. */
+ if (sc->sc_variant == CAS_SATURN) {
+ CAS_WRITE_4(sc, CAS_SATURN_PCFG, 0);
+ CAS_BARRIER(sc, CAS_SATURN_PCFG, 4,
+ BUS_SPACE_BARRIER_WRITE);
+ }
CAS_WRITE_4(sc, CAS_PCS_SERDES_CTRL, CAS_PCS_SERDES_CTRL_ESD);
- CAS_WRITE_4(sc, CAS_PCS_CONF_EN, CAS_PCS_CONF_EN);
- sc->sc_flags |= CAS_SERDES;
+ CAS_BARRIER(sc, CAS_PCS_SERDES_CTRL, 4,
+ BUS_SPACE_BARRIER_WRITE);
+ CAS_WRITE_4(sc, CAS_PCS_CONF, CAS_PCS_CONF_EN);
+ CAS_BARRIER(sc, CAS_PCS_CONF, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
sc->sc_phyad = CAS_PHYAD_EXTERNAL;
error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus,
cas_mediachange, cas_mediastatus);
}
-
if (error != 0) {
device_printf(sc->sc_dev, "PHY probe failed: %d\n", error);
goto fail_rxmap;
@@ -956,8 +984,9 @@ cas_init_locked(struct cas_softc *sc)
__func__);
#endif
- /* Re-initialize the MIF. */
- cas_mifinit(sc);
+ if ((sc->sc_flags & CAS_SERDES) == 0)
+ /* Re-initialize the MIF. */
+ cas_mifinit(sc);
/* step 3. Setup data structures in host memory. */
cas_meminit(sc);
@@ -2105,6 +2134,8 @@ cas_mifinit(struct cas_softc *sc)
/* Configure the MIF in frame mode. */
CAS_WRITE_4(sc, CAS_MIF_CONF,
CAS_READ_4(sc, CAS_MIF_CONF) & ~CAS_MIF_CONF_BB_MODE);
+ CAS_BARRIER(sc, CAS_MIF_CONF, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
/*
@@ -2219,10 +2250,16 @@ cas_mii_writereg(device_t dev, int phy, int reg, int val)
CAS_BARRIER(sc, CAS_PCS_CONF, 4,
BUS_SPACE_BARRIER_WRITE);
CAS_WRITE_4(sc, CAS_PCS_ANAR, val);
+ CAS_BARRIER(sc, CAS_PCS_ANAR, 4,
+ BUS_SPACE_BARRIER_WRITE);
CAS_WRITE_4(sc, CAS_PCS_SERDES_CTRL,
CAS_PCS_SERDES_CTRL_ESD);
+ CAS_BARRIER(sc, CAS_PCS_CONF, 4,
+ BUS_SPACE_BARRIER_WRITE);
CAS_WRITE_4(sc, CAS_PCS_CONF,
CAS_PCS_CONF_EN);
+ CAS_BARRIER(sc, CAS_PCS_CONF, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
return (0);
case MII_ANLPAR:
reg = CAS_PCS_ANLPAR;
@@ -2233,6 +2270,8 @@ cas_mii_writereg(device_t dev, int phy, int reg, int val)
return (0);
}
CAS_WRITE_4(sc, reg, val);
+ CAS_BARRIER(sc, reg, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
return (0);
}
@@ -2630,15 +2669,20 @@ static struct resource_spec cas_pci_res_spec[] = {
{ -1, 0 }
};
+#define CAS_LOCAL_MAC_ADDRESS "local-mac-address"
+#define CAS_PHY_INTERFACE "phy-interface"
+#define CAS_PHY_TYPE "phy-type"
+#define CAS_PHY_TYPE_PCS "pcs"
+
static int
cas_pci_attach(device_t dev)
{
+ char buf[sizeof(CAS_LOCAL_MAC_ADDRESS)];
struct cas_softc *sc;
int i;
#if !(defined(__powerpc__) || defined(__sparc64__))
u_char enaddr[4][ETHER_ADDR_LEN];
- char lma[sizeof("local-mac-address")];
- int found, j;
+ u_int j, k, lma, pcs[4], phy;
#endif
sc = device_get_softc(dev);
@@ -2679,13 +2723,20 @@ cas_pci_attach(device_t dev)
#if defined(__powerpc__) || defined(__sparc64__)
OF_getetheraddr(dev, sc->sc_enaddr);
+ if (OF_getprop(ofw_bus_get_node(dev), CAS_PHY_INTERFACE, buf,
+ sizeof(buf)) > 0 || OF_getprop(ofw_bus_get_node(dev),
+ CAS_PHY_TYPE, buf, sizeof(buf)) > 0) {
+ buf[sizeof(buf) - 1] = '\0';
+ if (strcmp(buf, CAS_PHY_TYPE_PCS) == 0)
+ sc->sc_flags |= CAS_SERDES;
+ }
#else
/*
- * Dig out VPD (vital product data) and read the MAX address.
- * The VPD resides in the PCI Expansion ROM (PCI FCode) and
- * can't be accessed via the PCI capability pointer.
- * SUNW,pci-ce and SUNW,pci-qge use the Enhanced VPD format
- * described in US Patent 7149820.
+ * Dig out VPD (vital product data) and read the MAC address as well
+ * as the PHY type. The VPD resides in the PCI Expansion ROM (PCI
+ * FCode) and can't be accessed via the PCI capability pointer.
+ * SUNW,pci-ce and SUNW,pci-qge use the Enhanced VPD format described
+ * in the free US Patent 7149820.
*/
#define PCI_ROMHDR_SIZE 0x1c
@@ -2719,7 +2770,10 @@ cas_pci_attach(device_t dev)
#define CAS_ROM_READ_4(sc, offs) \
CAS_READ_4((sc), CAS_PCI_ROM_OFFSET + (offs))
- found = 0;
+ lma = phy = 0;
+ memset(enaddr, 0, sizeof(enaddr));
+ memset(pcs, 0, sizeof(pcs));
+
/* Enable PCI Expansion ROM access. */
CAS_WRITE_4(sc, CAS_BIM_LDEV_OEN,
CAS_BIM_LDEV_OEN_PAD | CAS_BIM_LDEV_OEN_PROM);
@@ -2768,23 +2822,51 @@ cas_pci_attach(device_t dev)
if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE) != 'I')
/* no instance property */
continue;
- if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 3) != 'B')
- /* no byte array */
- continue;
- if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 4) !=
- ETHER_ADDR_LEN)
- continue;
- bus_read_region_1(sc->sc_res[CAS_RES_MEM],
- CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5,
- lma, sizeof(lma));
- if (strcmp(lma, "local-mac-address") != 0)
- continue;
- bus_read_region_1(sc->sc_res[CAS_RES_MEM],
- CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5 +
- sizeof(lma), enaddr[found],
- sizeof(enaddr[found]));
- if (found++ == 4)
- break;
+ if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 3) == 'B') {
+ /* byte array */
+ if (CAS_ROM_READ_1(sc,
+ j + PCI_VPD_SIZE + 4) != ETHER_ADDR_LEN)
+ continue;
+ bus_read_region_1(sc->sc_res[CAS_RES_MEM],
+ CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5,
+ buf, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ if (strcmp(buf, CAS_LOCAL_MAC_ADDRESS) != 0)
+ continue;
+ bus_read_region_1(sc->sc_res[CAS_RES_MEM],
+ CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE +
+ 5 + sizeof(CAS_LOCAL_MAC_ADDRESS),
+ enaddr[lma], sizeof(enaddr[lma]));
+ lma++;
+ if (lma == 4 && phy == 4)
+ break;
+ } else if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 3) ==
+ 'S') {
+ /* string */
+ if (CAS_ROM_READ_1(sc,
+ j + PCI_VPD_SIZE + 4) !=
+ sizeof(CAS_PHY_TYPE_PCS))
+ continue;
+ bus_read_region_1(sc->sc_res[CAS_RES_MEM],
+ CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5,
+ buf, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ if (strcmp(buf, CAS_PHY_INTERFACE) == 0)
+ k = sizeof(CAS_PHY_INTERFACE);
+ else if (strcmp(buf, CAS_PHY_TYPE) == 0)
+ k = sizeof(CAS_PHY_TYPE);
+ else
+ continue;
+ bus_read_region_1(sc->sc_res[CAS_RES_MEM],
+ CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE +
+ 5 + k, buf, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ if (strcmp(buf, CAS_PHY_TYPE_PCS) == 0)
+ pcs[phy] = 1;
+ phy++;
+ if (lma == 4 && phy == 4)
+ break;
+ }
}
break;
default:
@@ -2795,14 +2877,24 @@ cas_pci_attach(device_t dev)
fail_prom:
CAS_WRITE_4(sc, CAS_BIM_LDEV_OEN, 0);
- if (found == 0) {
+ if (lma == 0) {
device_printf(dev, "could not determine Ethernet address\n");
goto fail;
}
i = 0;
- if (found > 1 && pci_get_slot(dev) < sizeof(enaddr) / sizeof(*enaddr))
+ if (lma > 1 && pci_get_slot(dev) < sizeof(enaddr) / sizeof(*enaddr))
i = pci_get_slot(dev);
memcpy(sc->sc_enaddr, enaddr[i], ETHER_ADDR_LEN);
+
+ if (phy == 0) {
+ device_printf(dev, "could not determine PHY type\n");
+ goto fail;
+ }
+ i = 0;
+ if (phy > 1 && pci_get_slot(dev) < sizeof(pcs) / sizeof(*pcs))
+ i = pci_get_slot(dev);
+ if (pcs[i] != 0)
+ sc->sc_flags |= CAS_SERDES;
#endif
if (cas_attach(sc) != 0) {
diff --git a/sys/dev/cas/if_casreg.h b/sys/dev/cas/if_casreg.h
index 97250e0..0d1c1d8 100644
--- a/sys/dev/cas/if_casreg.h
+++ b/sys/dev/cas/if_casreg.h
@@ -68,6 +68,7 @@
#define CAS_STATUS4 0x105c /* interrupt status 4 for INTD */
#define CAS_CLEAR_ALIAS4 0x1060 /* clear mask alias 4 for INTD */
#define CAS_STATUS_ALIAS4 0x1064 /* interrupt status alias 4 for INTD */
+#define CAS_SATURN_PCFG 0x106c /* internal MACPHY pin configuration */
#define CAS_CAW_RX_WGHT_MASK 0x00000003 /* RX DMA factor for... */
#define CAS_CAW_RX_WGHT_SHFT 0 /* ...weighted round robin */
@@ -171,6 +172,17 @@
/* INTn enable bit for CAS_INTMASK[2-4] */
#define CAS_INTMASKN_EN 0x00000080 /* INT[B-D] enable */
+#define CAS_SATURN_PCFG_TLA 0x00000001 /* PHY activity LED */
+#define CAS_SATURN_PCFG_FLA 0x00000002 /* PHY 10MBit/sec LED */
+#define CAS_SATURN_PCFG_CLA 0x00000004 /* PHY 100MBit/sec LED */
+#define CAS_SATURN_PCFG_LLA 0x00000008 /* PHY 1000MBit/sec LED */
+#define CAS_SATURN_PCFG_RLA 0x00000010 /* PHY full-duplex LED */
+#define CAS_SATURN_PCFG_PDS 0x00000020 /* PHY debug mode */
+#define CAS_SATURN_PCFG_MTP 0x00000080 /* test point select */
+#define CAS_SATURN_PCFG_GMO 0x00000100 /* GMII observe */
+#define CAS_SATURN_PCFG_FSI 0x00000200 /* freeze GMII/SERDES */
+#define CAS_SATURN_PCFG_LAD 0x00000800 /* MAC LED control active low */
+
/* TX DMA registers */
#define CAS_TX_CONF 0x2004 /* TX configuration */
#define CAS_TX_FIFO_WR 0x2014 /* FIFO write pointer */
diff --git a/sys/dev/ce/if_ce.c b/sys/dev/ce/if_ce.c
index f04fd09..d151b42 100644
--- a/sys/dev/ce/if_ce.c
+++ b/sys/dev/ce/if_ce.c
@@ -701,9 +701,9 @@ static int ce_attach (device_t dev)
#endif
continue;
}
- d->queue.ifq_maxlen = IFQ_MAXLEN;
- d->hi_queue.ifq_maxlen = IFQ_MAXLEN;
- d->rqueue.ifq_maxlen = IFQ_MAXLEN;
+ d->queue.ifq_maxlen = ifqmaxlen;
+ d->hi_queue.ifq_maxlen = ifqmaxlen;
+ d->rqueue.ifq_maxlen = ifqmaxlen;
#if __FreeBSD_version >= 500000
mtx_init (&d->queue.ifq_mtx, "ce_queue", NULL, MTX_DEF);
mtx_init (&d->hi_queue.ifq_mtx, "ce_queue_hi", NULL, MTX_DEF);
@@ -732,7 +732,7 @@ static int ce_attach (device_t dev)
d->ifp->if_ioctl = ce_sioctl;
d->ifp->if_start = ce_ifstart;
d->ifp->if_init = ce_initialize;
- d->rqueue.ifq_maxlen = IFQ_MAXLEN;
+ d->rqueue.ifq_maxlen = ifqmaxlen;
#if __FreeBSD_version >= 500000
mtx_init (&d->rqueue.ifq_mtx, "ce_rqueue", NULL, MTX_DEF);
#endif
diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c
index 7293bb1..2a4fb27 100644
--- a/sys/dev/ciss/ciss.c
+++ b/sys/dev/ciss/ciss.c
@@ -417,6 +417,7 @@ ciss_attach(device_t dev)
sc = device_get_softc(dev);
sc->ciss_dev = dev;
mtx_init(&sc->ciss_mtx, "cissmtx", NULL, MTX_DEF);
+ callout_init_mtx(&sc->ciss_periodic, &sc->ciss_mtx, 0);
/*
* Do PCI-specific init.
@@ -429,7 +430,6 @@ ciss_attach(device_t dev)
*/
ciss_initq_free(sc);
ciss_initq_notify(sc);
- callout_init_mtx(&sc->ciss_periodic, &sc->ciss_mtx, 0);
/*
* Initalize device sysctls.
diff --git a/sys/dev/cm/smc90cx6.c b/sys/dev/cm/smc90cx6.c
index 0e9015e..719e468 100644
--- a/sys/dev/cm/smc90cx6.c
+++ b/sys/dev/cm/smc90cx6.c
@@ -189,7 +189,7 @@ cm_attach(dev)
ifp->if_ioctl = cm_ioctl;
ifp->if_init = cm_init;
/* XXX IFQ_SET_READY(&ifp->if_snd); */
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
arc_ifattach(ifp, linkaddress);
diff --git a/sys/dev/cp/if_cp.c b/sys/dev/cp/if_cp.c
index f6eeed5..e640230 100644
--- a/sys/dev/cp/if_cp.c
+++ b/sys/dev/cp/if_cp.c
@@ -505,8 +505,8 @@ static int cp_attach (device_t dev)
NG_NODE_UNREF (d->node);
continue;
}
- d->queue.ifq_maxlen = IFQ_MAXLEN;
- d->hi_queue.ifq_maxlen = IFQ_MAXLEN;
+ d->queue.ifq_maxlen = ifqmaxlen;
+ d->hi_queue.ifq_maxlen = ifqmaxlen;
mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF);
mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF);
#else /*NETGRAPH*/
diff --git a/sys/dev/cs/if_cs.c b/sys/dev/cs/if_cs.c
index b32a03d..476b9dd 100644
--- a/sys/dev/cs/if_cs.c
+++ b/sys/dev/cs/if_cs.c
@@ -500,7 +500,7 @@ cs_attach(device_t dev)
ifp->if_start=cs_start;
ifp->if_ioctl=cs_ioctl;
ifp->if_init=cs_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_flags=(IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
diff --git a/sys/dev/ctau/if_ct.c b/sys/dev/ctau/if_ct.c
index 125dfa5..dbdca97 100644
--- a/sys/dev/ctau/if_ct.c
+++ b/sys/dev/ctau/if_ct.c
@@ -722,8 +722,8 @@ static int ct_attach (device_t dev)
ct_bus_dma_mem_free (&d->dmamem);
continue;
}
- d->queue.ifq_maxlen = IFQ_MAXLEN;
- d->hi_queue.ifq_maxlen = IFQ_MAXLEN;
+ d->queue.ifq_maxlen = ifqmaxlen;
+ d->hi_queue.ifq_maxlen = ifqmaxlen;
mtx_init (&d->queue.ifq_mtx, "ct_queue", NULL, MTX_DEF);
mtx_init (&d->hi_queue.ifq_mtx, "ct_queue_hi", NULL, MTX_DEF);
#else /*NETGRAPH*/
diff --git a/sys/dev/cx/if_cx.c b/sys/dev/cx/if_cx.c
index 4e9750e..c8f53a0 100644
--- a/sys/dev/cx/if_cx.c
+++ b/sys/dev/cx/if_cx.c
@@ -831,8 +831,8 @@ static int cx_attach (device_t dev)
cx_bus_dma_mem_free (&d->dmamem);
continue;
}
- d->lo_queue.ifq_maxlen = IFQ_MAXLEN;
- d->hi_queue.ifq_maxlen = IFQ_MAXLEN;
+ d->lo_queue.ifq_maxlen = ifqmaxlen;
+ d->hi_queue.ifq_maxlen = ifqmaxlen;
mtx_init (&d->lo_queue.ifq_mtx, "cx_queue_lo", NULL, MTX_DEF);
mtx_init (&d->hi_queue.ifq_mtx, "cx_queue_hi", NULL, MTX_DEF);
#else /*NETGRAPH*/
diff --git a/sys/dev/cxgb/cxgb_ioctl.h b/sys/dev/cxgb/cxgb_ioctl.h
index e4b4875..3f3ac5a 100644
--- a/sys/dev/cxgb/cxgb_ioctl.h
+++ b/sys/dev/cxgb/cxgb_ioctl.h
@@ -59,6 +59,9 @@ enum {
CH_CLEAR_STATS,
CH_GET_UP_LA,
CH_GET_UP_IOQS,
+ CH_SET_FILTER,
+ CH_DEL_FILTER,
+ CH_GET_FILTER,
};
/* statistics categories */
@@ -215,6 +218,29 @@ struct ch_up_ioqs {
struct t3_ioq_entry *data;
};
+struct ch_filter_tuple {
+ uint32_t sip;
+ uint32_t dip;
+ uint16_t sport;
+ uint16_t dport;
+ uint16_t vlan:12;
+ uint16_t vlan_prio:3;
+};
+
+struct ch_filter {
+ uint32_t filter_id;
+ struct ch_filter_tuple val;
+ struct ch_filter_tuple mask;
+ uint16_t mac_addr_idx;
+ uint8_t mac_hit:1;
+ uint8_t proto:2;
+
+ uint8_t want_filter_id:1;
+ uint8_t pass:1;
+ uint8_t rss:1;
+ uint8_t qset;
+};
+
#define CHELSIO_SETREG _IOW('f', CH_SETREG, struct ch_reg)
#define CHELSIO_GETREG _IOWR('f', CH_GETREG, struct ch_reg)
#define CHELSIO_GETMTUTAB _IOR('f', CH_GETMTUTAB, struct ch_mtus)
@@ -239,4 +265,7 @@ struct ch_up_ioqs {
#define CHELSIO_GET_EEPROM _IOWR('f', CH_GET_EEPROM, struct ch_eeprom)
#define CHELSIO_GET_UP_LA _IOWR('f', CH_GET_UP_LA, struct ch_up_la)
#define CHELSIO_GET_UP_IOQS _IOWR('f', CH_GET_UP_IOQS, struct ch_up_ioqs)
+#define CHELSIO_SET_FILTER _IOW('f', CH_SET_FILTER, struct ch_filter)
+#define CHELSIO_DEL_FILTER _IOW('f', CH_DEL_FILTER, struct ch_filter)
+#define CHELSIO_GET_FILTER _IOWR('f', CH_GET_FILTER, struct ch_filter)
#endif
diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c
index a47284f..13fed44 100644
--- a/sys/dev/cxgb/cxgb_main.c
+++ b/sys/dev/cxgb/cxgb_main.c
@@ -99,6 +99,13 @@ static void cxgb_ext_intr_handler(void *, int);
static void cxgb_tick_handler(void *, int);
static void cxgb_tick(void *);
static void setup_rss(adapter_t *sc);
+static int alloc_filters(struct adapter *);
+static int setup_hw_filters(struct adapter *);
+static int set_filter(struct adapter *, int, const struct filter_info *);
+static inline void mk_set_tcb_field(struct cpl_set_tcb_field *, unsigned int,
+ unsigned int, u64, u64);
+static inline void set_tcb_field_ulp(struct cpl_set_tcb_field *, unsigned int,
+ unsigned int, u64, u64);
/* Attachment glue for the PCI controller end of the device. Each port of
* the device is attached separately, as defined later.
@@ -981,7 +988,7 @@ cxgb_makedev(struct port_info *pi)
#define CXGB_CAP (IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | \
IFCAP_VLAN_HWCSUM | IFCAP_TSO | IFCAP_JUMBO_MTU | IFCAP_LRO | \
- IFCAP_VLAN_HWTSO)
+ IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE)
#define CXGB_CAP_ENABLE (CXGB_CAP & ~IFCAP_TSO6)
static int
@@ -1012,7 +1019,7 @@ cxgb_port_attach(device_t dev)
ifp->if_ioctl = cxgb_ioctl;
ifp->if_start = cxgb_start;
- ifp->if_snd.ifq_drv_maxlen = cxgb_snd_queue_len;
+ ifp->if_snd.ifq_drv_maxlen = max(cxgb_snd_queue_len, ifqmaxlen);
IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
IFQ_SET_READY(&ifp->if_snd);
@@ -1661,6 +1668,13 @@ cxgb_up(struct adapter *sc)
if ((err = update_tpsram(sc)))
goto out;
+ if (is_offload(sc)) {
+ sc->params.mc5.nservers = 0;
+ sc->params.mc5.nroutes = 0;
+ sc->params.mc5.nfilters = t3_mc5_size(&sc->mc5) -
+ MC5_MIN_TIDS;
+ }
+
err = t3_init_hw(sc, 0);
if (err)
goto out;
@@ -1672,6 +1686,7 @@ cxgb_up(struct adapter *sc)
if (err)
goto out;
+ alloc_filters(sc);
setup_rss(sc);
t3_intr_clear(sc);
@@ -1698,6 +1713,7 @@ cxgb_up(struct adapter *sc)
if (!(sc->flags & QUEUES_BOUND)) {
bind_qsets(sc);
+ setup_hw_filters(sc);
sc->flags |= QUEUES_BOUND;
}
@@ -3076,6 +3092,139 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
free(buf, M_DEVBUF);
break;
}
+ case CHELSIO_SET_FILTER: {
+ struct ch_filter *f = (struct ch_filter *)data;;
+ struct filter_info *p;
+ unsigned int nfilters = sc->params.mc5.nfilters;
+
+ if (!is_offload(sc))
+ return (EOPNOTSUPP); /* No TCAM */
+ if (!(sc->flags & FULL_INIT_DONE))
+ return (EAGAIN); /* mc5 not setup yet */
+ if (nfilters == 0)
+ return (EBUSY); /* TOE will use TCAM */
+
+ /* sanity checks */
+ if (f->filter_id >= nfilters ||
+ (f->val.dip && f->mask.dip != 0xffffffff) ||
+ (f->val.sport && f->mask.sport != 0xffff) ||
+ (f->val.dport && f->mask.dport != 0xffff) ||
+ (f->val.vlan && f->mask.vlan != 0xfff) ||
+ (f->val.vlan_prio &&
+ f->mask.vlan_prio != FILTER_NO_VLAN_PRI) ||
+ (f->mac_addr_idx != 0xffff && f->mac_addr_idx > 15) ||
+ f->qset >= SGE_QSETS ||
+ sc->rrss_map[f->qset] >= RSS_TABLE_SIZE)
+ return (EINVAL);
+
+ /* Was allocated with M_WAITOK */
+ KASSERT(sc->filters, ("filter table NULL\n"));
+
+ p = &sc->filters[f->filter_id];
+ if (p->locked)
+ return (EPERM);
+
+ bzero(p, sizeof(*p));
+ p->sip = f->val.sip;
+ p->sip_mask = f->mask.sip;
+ p->dip = f->val.dip;
+ p->sport = f->val.sport;
+ p->dport = f->val.dport;
+ p->vlan = f->mask.vlan ? f->val.vlan : 0xfff;
+ p->vlan_prio = f->mask.vlan_prio ? (f->val.vlan_prio & 6) :
+ FILTER_NO_VLAN_PRI;
+ p->mac_hit = f->mac_hit;
+ p->mac_vld = f->mac_addr_idx != 0xffff;
+ p->mac_idx = f->mac_addr_idx;
+ p->pkt_type = f->proto;
+ p->report_filter_id = f->want_filter_id;
+ p->pass = f->pass;
+ p->rss = f->rss;
+ p->qset = f->qset;
+
+ error = set_filter(sc, f->filter_id, p);
+ if (error == 0)
+ p->valid = 1;
+ break;
+ }
+ case CHELSIO_DEL_FILTER: {
+ struct ch_filter *f = (struct ch_filter *)data;
+ struct filter_info *p;
+ unsigned int nfilters = sc->params.mc5.nfilters;
+
+ if (!is_offload(sc))
+ return (EOPNOTSUPP);
+ if (!(sc->flags & FULL_INIT_DONE))
+ return (EAGAIN);
+ if (nfilters == 0 || sc->filters == NULL)
+ return (EINVAL);
+ if (f->filter_id >= nfilters)
+ return (EINVAL);
+
+ p = &sc->filters[f->filter_id];
+ if (p->locked)
+ return (EPERM);
+ if (!p->valid)
+ return (EFAULT); /* Read "Bad address" as "Bad index" */
+
+ bzero(p, sizeof(*p));
+ p->sip = p->sip_mask = 0xffffffff;
+ p->vlan = 0xfff;
+ p->vlan_prio = FILTER_NO_VLAN_PRI;
+ p->pkt_type = 1;
+ error = set_filter(sc, f->filter_id, p);
+ break;
+ }
+ case CHELSIO_GET_FILTER: {
+ struct ch_filter *f = (struct ch_filter *)data;
+ struct filter_info *p;
+ unsigned int i, nfilters = sc->params.mc5.nfilters;
+
+ if (!is_offload(sc))
+ return (EOPNOTSUPP);
+ if (!(sc->flags & FULL_INIT_DONE))
+ return (EAGAIN);
+ if (nfilters == 0 || sc->filters == NULL)
+ return (EINVAL);
+
+ i = f->filter_id == 0xffffffff ? 0 : f->filter_id + 1;
+ for (; i < nfilters; i++) {
+ p = &sc->filters[i];
+ if (!p->valid)
+ continue;
+
+ bzero(f, sizeof(*f));
+
+ f->filter_id = i;
+ f->val.sip = p->sip;
+ f->mask.sip = p->sip_mask;
+ f->val.dip = p->dip;
+ f->mask.dip = p->dip ? 0xffffffff : 0;
+ f->val.sport = p->sport;
+ f->mask.sport = p->sport ? 0xffff : 0;
+ f->val.dport = p->dport;
+ f->mask.dport = p->dport ? 0xffff : 0;
+ f->val.vlan = p->vlan == 0xfff ? 0 : p->vlan;
+ f->mask.vlan = p->vlan == 0xfff ? 0 : 0xfff;
+ f->val.vlan_prio = p->vlan_prio == FILTER_NO_VLAN_PRI ?
+ 0 : p->vlan_prio;
+ f->mask.vlan_prio = p->vlan_prio == FILTER_NO_VLAN_PRI ?
+ 0 : FILTER_NO_VLAN_PRI;
+ f->mac_hit = p->mac_hit;
+ f->mac_addr_idx = p->mac_vld ? p->mac_idx : 0xffff;
+ f->proto = p->pkt_type;
+ f->want_filter_id = p->report_filter_id;
+ f->pass = p->pass;
+ f->rss = p->rss;
+ f->qset = p->qset;
+
+ break;
+ }
+
+ if (i == nfilters)
+ f->filter_id = 0xffffffff;
+ break;
+ }
default:
return (EOPNOTSUPP);
break;
@@ -3130,5 +3279,127 @@ cxgb_get_regs(adapter_t *sc, struct ch_ifconf_regs *regs, uint8_t *buf)
XGM_REG(A_XGM_RX_SPI4_SOP_EOP_CNT, 1));
}
+static int
+alloc_filters(struct adapter *sc)
+{
+ struct filter_info *p;
+ unsigned int nfilters = sc->params.mc5.nfilters;
+
+ if (nfilters == 0)
+ return (0);
-MODULE_DEPEND(if_cxgb, cxgb_t3fw, 1, 1, 1);
+ p = malloc(sizeof(*p) * nfilters, M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->filters = p;
+
+ p = &sc->filters[nfilters - 1];
+ p->vlan = 0xfff;
+ p->vlan_prio = FILTER_NO_VLAN_PRI;
+ p->pass = p->rss = p->valid = p->locked = 1;
+
+ return (0);
+}
+
+static int
+setup_hw_filters(struct adapter *sc)
+{
+ int i, rc;
+ unsigned int nfilters = sc->params.mc5.nfilters;
+
+ if (!sc->filters)
+ return (0);
+
+ t3_enable_filters(sc);
+
+ for (i = rc = 0; i < nfilters && !rc; i++) {
+ if (sc->filters[i].locked)
+ rc = set_filter(sc, i, &sc->filters[i]);
+ }
+
+ return (rc);
+}
+
+static int
+set_filter(struct adapter *sc, int id, const struct filter_info *f)
+{
+ int len;
+ struct mbuf *m;
+ struct ulp_txpkt *txpkt;
+ struct work_request_hdr *wr;
+ struct cpl_pass_open_req *oreq;
+ struct cpl_set_tcb_field *sreq;
+
+ len = sizeof(*wr) + sizeof(*oreq) + 2 * sizeof(*sreq);
+ KASSERT(len <= MHLEN, ("filter request too big for an mbuf"));
+
+ id += t3_mc5_size(&sc->mc5) - sc->params.mc5.nroutes -
+ sc->params.mc5.nfilters;
+
+ m = m_gethdr(M_WAITOK, MT_DATA);
+ m->m_len = m->m_pkthdr.len = len;
+ bzero(mtod(m, char *), len);
+
+ wr = mtod(m, struct work_request_hdr *);
+ wr->wrh_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS) | F_WR_ATOMIC);
+
+ oreq = (struct cpl_pass_open_req *)(wr + 1);
+ txpkt = (struct ulp_txpkt *)oreq;
+ txpkt->cmd_dest = htonl(V_ULPTX_CMD(ULP_TXPKT));
+ txpkt->len = htonl(V_ULPTX_NFLITS(sizeof(*oreq) / 8));
+ OPCODE_TID(oreq) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, id));
+ oreq->local_port = htons(f->dport);
+ oreq->peer_port = htons(f->sport);
+ oreq->local_ip = htonl(f->dip);
+ oreq->peer_ip = htonl(f->sip);
+ oreq->peer_netmask = htonl(f->sip_mask);
+ oreq->opt0h = 0;
+ oreq->opt0l = htonl(F_NO_OFFLOAD);
+ oreq->opt1 = htonl(V_MAC_MATCH_VALID(f->mac_vld) |
+ V_CONN_POLICY(CPL_CONN_POLICY_FILTER) |
+ V_VLAN_PRI(f->vlan_prio >> 1) |
+ V_VLAN_PRI_VALID(f->vlan_prio != FILTER_NO_VLAN_PRI) |
+ V_PKT_TYPE(f->pkt_type) | V_OPT1_VLAN(f->vlan) |
+ V_MAC_MATCH(f->mac_idx | (f->mac_hit << 4)));
+
+ sreq = (struct cpl_set_tcb_field *)(oreq + 1);
+ set_tcb_field_ulp(sreq, id, 1, 0x1800808000ULL,
+ (f->report_filter_id << 15) | (1 << 23) |
+ ((u64)f->pass << 35) | ((u64)!f->rss << 36));
+ set_tcb_field_ulp(sreq + 1, id, 0, 0xffffffff, (2 << 19) | 1);
+ t3_mgmt_tx(sc, m);
+
+ if (f->pass && !f->rss) {
+ len = sizeof(*sreq);
+ m = m_gethdr(M_WAITOK, MT_DATA);
+ m->m_len = m->m_pkthdr.len = len;
+ bzero(mtod(m, char *), len);
+ sreq = mtod(m, struct cpl_set_tcb_field *);
+ sreq->wr.wrh_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
+ mk_set_tcb_field(sreq, id, 25, 0x3f80000,
+ (u64)sc->rrss_map[f->qset] << 19);
+ t3_mgmt_tx(sc, m);
+ }
+ return 0;
+}
+
+static inline void
+mk_set_tcb_field(struct cpl_set_tcb_field *req, unsigned int tid,
+ unsigned int word, u64 mask, u64 val)
+{
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+ req->reply = V_NO_REPLY(1);
+ req->cpu_idx = 0;
+ req->word = htons(word);
+ req->mask = htobe64(mask);
+ req->val = htobe64(val);
+}
+
+static inline void
+set_tcb_field_ulp(struct cpl_set_tcb_field *req, unsigned int tid,
+ unsigned int word, u64 mask, u64 val)
+{
+ struct ulp_txpkt *txpkt = (struct ulp_txpkt *)req;
+
+ txpkt->cmd_dest = htonl(V_ULPTX_CMD(ULP_TXPKT));
+ txpkt->len = htonl(V_ULPTX_NFLITS(sizeof(*req) / 8));
+ mk_set_tcb_field(req, tid, word, mask, val);
+}
diff --git a/sys/dev/cxgb/sys/mvec.h b/sys/dev/cxgb/sys/mvec.h
index ed38dca..9db27dd 100644
--- a/sys/dev/cxgb/sys/mvec.h
+++ b/sys/dev/cxgb/sys/mvec.h
@@ -1,33 +1,31 @@
-/**************************************************************************
- *
- * Copyright (c) 2007,2009 Kip Macy kmacy@freebsd.org
+/*-
+ * Copyright (c) 2007, 2009 Kip Macy <kmacy@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. The name of Kip Macy nor the names of other
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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 _MVEC_H_
#define _MVEC_H_
diff --git a/sys/dev/cxgb/sys/uipc_mvec.c b/sys/dev/cxgb/sys/uipc_mvec.c
index 4e494eb..f52daa6 100644
--- a/sys/dev/cxgb/sys/uipc_mvec.c
+++ b/sys/dev/cxgb/sys/uipc_mvec.c
@@ -1,32 +1,28 @@
-/**************************************************************************
- *
- * Copyright (c) 2007-2008, Kip Macy kmacy@freebsd.org
+/*-
+ * Copyright (c) 2007-2008 Kip Macy <kmacy@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. The name of Kip Macy nor the names of other
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- *
- ***************************************************************************/
+ * 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$");
diff --git a/sys/dev/drm/via_dmablit.c b/sys/dev/drm/via_dmablit.c
index ea449f1..9be42ff 100644
--- a/sys/dev/drm/via_dmablit.c
+++ b/sys/dev/drm/via_dmablit.c
@@ -178,9 +178,9 @@ via_free_sg_info(drm_via_sg_info_t *vsg)
case dr_via_pages_locked:
for (i=0; i < vsg->num_pages; ++i) {
if ( NULL != (page = vsg->pages[i])) {
- vm_page_lock_queues();
+ vm_page_lock(page);
vm_page_unwire(page, 0);
- vm_page_unlock_queues();
+ vm_page_unlock(page);
}
}
case dr_via_pages_alloc:
@@ -248,10 +248,10 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
(vm_offset_t)xfer->mem_addr + IDX_TO_OFF(i), VM_PROT_RW);
if (m == NULL)
break;
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_wire(m);
vm_page_unhold(m);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
vsg->pages[i] = m;
}
vsg->state = dr_via_pages_locked;
diff --git a/sys/dev/drm/via_video.c b/sys/dev/drm/via_video.c
index f903cf5..3bd9605 100644
--- a/sys/dev/drm/via_video.c
+++ b/sys/dev/drm/via_video.c
@@ -78,7 +78,7 @@ int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_
DRM_DEBUG("\n");
- if (fx->lock > VIA_NR_XVMC_LOCKS)
+ if (fx->lock >= VIA_NR_XVMC_LOCKS)
return -EFAULT;
lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx->lock);
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 1db9012..2fb4f17 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -347,8 +347,13 @@ static int em_debug_sbp = FALSE;
TUNABLE_INT("hw.em.sbp", &em_debug_sbp);
/* Local controls for MSI/MSIX */
+#ifdef EM_MULTIQUEUE
static int em_enable_msix = TRUE;
static int em_msix_queues = 2; /* for 82574, can be 1 or 2 */
+#else
+static int em_enable_msix = FALSE;
+static int em_msix_queues = 0; /* disable */
+#endif
TUNABLE_INT("hw.em.enable_msix", &em_enable_msix);
TUNABLE_INT("hw.em.msix_queues", &em_msix_queues);
@@ -1371,9 +1376,7 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
}
EM_CORE_UNLOCK(adapter);
- EM_RX_LOCK(rxr);
rx_done = em_rxeof(rxr, count);
- EM_RX_UNLOCK(rxr);
EM_TX_LOCK(txr);
em_txeof(txr);
@@ -1449,9 +1452,7 @@ em_handle_que(void *context, int pending)
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- EM_RX_LOCK(rxr);
more_rx = em_rxeof(rxr, adapter->rx_process_limit);
- EM_RX_UNLOCK(rxr);
EM_TX_LOCK(txr);
em_txeof(txr);
@@ -1511,10 +1512,8 @@ em_msix_rx(void *arg)
struct adapter *adapter = rxr->adapter;
bool more;
- EM_RX_LOCK(rxr);
++rxr->rx_irq;
more = em_rxeof(rxr, adapter->rx_process_limit);
- EM_RX_UNLOCK(rxr);
if (more)
taskqueue_enqueue(rxr->tq, &rxr->rx_task);
else
@@ -1553,9 +1552,7 @@ em_handle_rx(void *context, int pending)
struct adapter *adapter = rxr->adapter;
bool more;
- EM_RX_LOCK(rxr);
more = em_rxeof(rxr, adapter->rx_process_limit);
- EM_RX_UNLOCK(rxr);
if (more)
taskqueue_enqueue(rxr->tq, &rxr->rx_task);
else
@@ -2707,10 +2704,10 @@ em_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_capabilities |= IFCAP_POLLING;
#endif
- /* Enable All WOL methods by default */
+ /* Enable only WOL MAGIC by default */
if (adapter->wol) {
ifp->if_capabilities |= IFCAP_WOL;
- ifp->if_capenable |= IFCAP_WOL;
+ ifp->if_capenable |= IFCAP_WOL_MAGIC;
}
/*
@@ -4100,7 +4097,7 @@ em_rxeof(struct rx_ring *rxr, int count)
bool eop;
struct e1000_rx_desc *cur;
- EM_RX_LOCK_ASSERT(rxr);
+ EM_RX_LOCK(rxr);
for (i = rxr->next_to_check, processed = 0; count != 0;) {
@@ -4194,8 +4191,13 @@ skip:
i = 0;
/* Send to the stack */
- if (sendmp != NULL)
+ if (sendmp != NULL) {
+ rxr->next_to_check = i;
+ EM_RX_UNLOCK(rxr);
(*ifp->if_input)(ifp, sendmp);
+ EM_RX_LOCK(rxr);
+ i = rxr->next_to_check;
+ }
/* Only refresh mbufs every 8 descriptors */
if (processed == 8) {
@@ -4211,6 +4213,7 @@ skip:
}
rxr->next_to_check = i;
+ EM_RX_UNLOCK(rxr);
#ifdef DEVICE_POLLING
return (rxdone);
diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c
index e065a67..839e2a5 100644
--- a/sys/dev/ed/if_ed.c
+++ b/sys/dev/ed/if_ed.c
@@ -283,8 +283,8 @@ ed_attach(device_t dev)
ifp->if_start = ed_start;
ifp->if_ioctl = ed_ioctl;
ifp->if_init = ed_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ifp->if_linkmib = &sc->mibdata;
ifp->if_linkmiblen = sizeof sc->mibdata;
diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c
index 59dd1c4..2436255 100644
--- a/sys/dev/ep/if_ep.c
+++ b/sys/dev/ep/if_ep.c
@@ -306,8 +306,8 @@ ep_attach(struct ep_softc *sc)
ifp->if_start = epstart;
ifp->if_ioctl = epioctl;
ifp->if_init = epinit;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
callout_init_mtx(&sc->watchdog_timer, &sc->sc_mtx, 0);
diff --git a/sys/dev/esp/esp_sbus.c b/sys/dev/esp/esp_sbus.c
index 2033cc6..3ba0d46 100644
--- a/sys/dev/esp/esp_sbus.c
+++ b/sys/dev/esp/esp_sbus.c
@@ -466,9 +466,7 @@ espattach(struct esp_softc *esc, const struct ncr53c9x_glue *gluep)
goto fail_lock;
}
- if (OF_getprop(ofw_bus_get_node(esc->sc_dev), "scsi-initiator-id",
- &sc->sc_id, sizeof(sc->sc_id)) == -1)
- sc->sc_id = 7;
+ sc->sc_id = OF_getscsinitid(esc->sc_dev);
#ifdef ESP_SBUS_DEBUG
device_printf(esc->sc_dev, "%s: sc_id %d, freq %d\n",
diff --git a/sys/dev/ex/if_ex.c b/sys/dev/ex/if_ex.c
index d9e0c98..efd54bc 100644
--- a/sys/dev/ex/if_ex.c
+++ b/sys/dev/ex/if_ex.c
@@ -237,7 +237,7 @@ ex_attach(device_t dev)
ifp->if_start = ex_start;
ifp->if_ioctl = ex_ioctl;
ifp->if_init = ex_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifmedia_init(&sc->ifmedia, 0, ex_ifmedia_upd, ex_ifmedia_sts);
mtx_init(&sc->lock, device_get_nameunit(dev), MTX_NETWORK_LOCK,
diff --git a/sys/dev/fe/if_fe.c b/sys/dev/fe/if_fe.c
index eff92b7..9fe1f2c 100644
--- a/sys/dev/fe/if_fe.c
+++ b/sys/dev/fe/if_fe.c
@@ -766,7 +766,7 @@ fe_attach (device_t dev)
* Set fixed interface flags.
*/
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
#if FE_SINGLE_TRANSMISSION
/* Override txb config to allocate minimum. */
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index e33b431..a19c85e 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -2675,16 +2675,16 @@ pmc_start(struct pmc *pm)
PMCDBG(PMC,OPS,1, "po=%p in global list", po);
}
po->po_sscount++;
- }
- /*
- * Log mapping information for all existing processes in the
- * system. Subsequent mappings are logged as they happen;
- * see pmc_process_mmap().
- */
- if (po->po_logprocmaps == 0) {
- pmc_log_all_process_mappings(po);
- po->po_logprocmaps = 1;
+ /*
+ * Log mapping information for all existing processes in the
+ * system. Subsequent mappings are logged as they happen;
+ * see pmc_process_mmap().
+ */
+ if (po->po_logprocmaps == 0) {
+ pmc_log_all_process_mappings(po);
+ po->po_logprocmaps = 1;
+ }
}
/*
diff --git a/sys/dev/ie/if_ie.c b/sys/dev/ie/if_ie.c
index 34c658e..172bf9e 100644
--- a/sys/dev/ie/if_ie.c
+++ b/sys/dev/ie/if_ie.c
@@ -318,7 +318,7 @@ ie_attach(device_t dev)
ifp->if_start = iestart;
ifp->if_ioctl = ieioctl;
ifp->if_init = ieinit;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ether_ifattach(ifp, sc->enaddr);
diff --git a/sys/dev/iicbus/if_ic.c b/sys/dev/iicbus/if_ic.c
index bb5186c..4a05b16 100644
--- a/sys/dev/iicbus/if_ic.c
+++ b/sys/dev/iicbus/if_ic.c
@@ -181,7 +181,7 @@ icattach(device_t dev)
ifp->if_output = icoutput;
ifp->if_hdrlen = 0;
ifp->if_addrlen = 0;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
ic_alloc_buffers(sc, ICMTU);
diff --git a/sys/dev/io/iodev.c b/sys/dev/io/iodev.c
index b142a39..eae69f4 100644
--- a/sys/dev/io/iodev.c
+++ b/sys/dev/io/iodev.c
@@ -30,22 +30,27 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/conf.h>
-#include <sys/fcntl.h>
#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
+#include <sys/ioccom.h>
#include <sys/module.h>
-#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
-#include <sys/signalvar.h>
#include <sys/systm.h>
-#include <sys/uio.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
#include <machine/iodev.h>
+#include <dev/io/iodev.h>
+
+static int ioopen(struct cdev *dev, int flags, int fmt,
+ struct thread *td);
+static int ioclose(struct cdev *dev, int flags, int fmt,
+ struct thread *td);
+static int ioioctl(struct cdev *dev, u_long cmd, caddr_t data,
+ int fflag, struct thread *td);
+
+static int iopio_read(struct iodev_pio_req *req);
+static int iopio_write(struct iodev_pio_req *req);
+
static struct cdev *iodev;
static struct cdevsw io_cdevsw = {
@@ -58,6 +63,129 @@ static struct cdevsw io_cdevsw = {
/* ARGSUSED */
static int
+ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused,
+ struct thread *td)
+{
+ int error;
+
+ error = priv_check(td, PRIV_IO);
+ if (error != 0)
+ return (error);
+ error = securelevel_gt(td->td_ucred, 0);
+ if (error != 0)
+ return (error);
+ error = iodev_open(td);
+
+ return (error);
+}
+
+/* ARGSUSED */
+static int
+ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused,
+ struct thread *td)
+{
+
+ return (iodev_close(td));
+}
+
+/* ARGSUSED */
+static int
+ioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
+ int fflag __unused, struct thread *td __unused)
+{
+ struct iodev_pio_req *pio_req;
+ int error;
+
+ switch (cmd) {
+ case IODEV_PIO:
+ pio_req = (struct iodev_pio_req *)data;
+ switch (pio_req->access) {
+ case IODEV_PIO_READ:
+ error = iopio_read(pio_req);
+ break;
+ case IODEV_PIO_WRITE:
+ error = iopio_write(pio_req);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+ default:
+ error = iodev_ioctl(cmd, data);
+ }
+
+ return (error);
+}
+
+static int
+iopio_read(struct iodev_pio_req *req)
+{
+
+ switch (req->width) {
+ case 1:
+ req->val = iodev_read_1(req->port);
+ break;
+ case 2:
+ if (req->port & 1) {
+ req->val = iodev_read_1(req->port);
+ req->val |= iodev_read_1(req->port + 1) << 8;
+ } else
+ req->val = iodev_read_2(req->port);
+ break;
+ case 4:
+ if (req->port & 1) {
+ req->val = iodev_read_1(req->port);
+ req->val |= iodev_read_2(req->port + 1) << 8;
+ req->val |= iodev_read_1(req->port + 3) << 24;
+ } else if (req->port & 2) {
+ req->val = iodev_read_2(req->port);
+ req->val |= iodev_read_2(req->port + 2) << 16;
+ } else
+ req->val = iodev_read_4(req->port);
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static int
+iopio_write(struct iodev_pio_req *req)
+{
+
+ switch (req->width) {
+ case 1:
+ iodev_write_1(req->port, req->val);
+ break;
+ case 2:
+ if (req->port & 1) {
+ iodev_write_1(req->port, req->val);
+ iodev_write_1(req->port + 1, req->val >> 8);
+ } else
+ iodev_write_2(req->port, req->val);
+ break;
+ case 4:
+ if (req->port & 1) {
+ iodev_write_1(req->port, req->val);
+ iodev_write_2(req->port + 1, req->val >> 8);
+ iodev_write_1(req->port + 3, req->val >> 24);
+ } else if (req->port & 2) {
+ iodev_write_2(req->port, req->val);
+ iodev_write_2(req->port + 2, req->val >> 16);
+ } else
+ iodev_write_4(req->port, req->val);
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+/* ARGSUSED */
+static int
io_modevent(module_t mod __unused, int type, void *data __unused)
{
switch(type) {
diff --git a/sys/dev/io/iodev.h b/sys/dev/io/iodev.h
new file mode 100644
index 0000000..d040fccc
--- /dev/null
+++ b/sys/dev/io/iodev.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2010 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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_IODEV_H_
+#define _DEV_IODEV_H_
+
+#define IODEV_PIO_READ 0
+#define IODEV_PIO_WRITE 1
+
+struct iodev_pio_req {
+ u_int access;
+ u_int port;
+ u_int width;
+ u_int val;
+};
+
+#define IODEV_PIO _IOWR('I', 0, struct iodev_pio_req)
+
+#endif /* _DEV_IODEV_H_ */
diff --git a/sys/dev/ipw/if_ipw.c b/sys/dev/ipw/if_ipw.c
index 3315d65..2329c33 100644
--- a/sys/dev/ipw/if_ipw.c
+++ b/sys/dev/ipw/if_ipw.c
@@ -289,8 +289,8 @@ ipw_attach(device_t dev)
ifp->if_init = ipw_init;
ifp->if_ioctl = ipw_ioctl;
ifp->if_start = ipw_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 8410ea6..e152e99 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -46,6 +46,11 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/uio.h>
+#ifdef __sparc64__
+#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
+#endif
+
#include <dev/isp/isp_freebsd.h>
static uint32_t isp_pci_rd_reg(ispsoftc_t *, int);
@@ -517,7 +522,11 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
if (IS_FC(isp)) {
ISP_FC_PC(isp, chan)->default_id = 109 - chan;
} else {
+#ifdef __sparc64__
+ ISP_SPI_PC(isp, chan)->iid = OF_getscsinitid(dev);
+#else
ISP_SPI_PC(isp, chan)->iid = 7;
+#endif
}
} else {
if (IS_FC(isp)) {
diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c
index 895645a..34dcc09 100644
--- a/sys/dev/isp/isp_sbus.c
+++ b/sys/dev/isp/isp_sbus.c
@@ -41,8 +41,10 @@ __FBSDID("$FreeBSD$");
#include <sys/resource.h>
#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
+#include <machine/ofw_machdep.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <sparc64/sbus/sbusvar.h>
@@ -264,11 +266,7 @@ isp_sbus_attach(device_t dev)
isp->isp_confopts |= ISP_CFG_OWNLOOPID;
}
if (default_id == -1) {
- /*
- * XXX: should be a way to get properties w/o having
- * XXX: to call OF_xxx functions
- */
- default_id = 7;
+ default_id = OF_getscsinitid(dev);
}
ISP_SPI_PC(isp, 0)->iid = default_id;
diff --git a/sys/dev/iwi/if_iwi.c b/sys/dev/iwi/if_iwi.c
index 1105425..4b765ef 100644
--- a/sys/dev/iwi/if_iwi.c
+++ b/sys/dev/iwi/if_iwi.c
@@ -363,8 +363,8 @@ iwi_attach(device_t dev)
ifp->if_init = iwi_init;
ifp->if_ioctl = iwi_ioctl;
ifp->if_start = iwi_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index 09c1efd..5a17d1e 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -627,8 +627,8 @@ iwn_attach(device_t dev)
ifp->if_init = iwn_init;
ifp->if_ioctl = iwn_ioctl;
ifp->if_start = iwn_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ieee80211_ifattach(ic, macaddr);
diff --git a/sys/dev/le/lance.c b/sys/dev/le/lance.c
index db20099..8700aa2 100644
--- a/sys/dev/le/lance.c
+++ b/sys/dev/le/lance.c
@@ -133,8 +133,8 @@ lance_config(struct lance_softc *sc, const char* name, int unit)
ifp->if_flags &= ~IFF_MULTICAST;
#endif
ifp->if_baudrate = IF_Mbps(10);
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
/* Initialize ifmedia structures. */
diff --git a/sys/dev/malo/if_malo.c b/sys/dev/malo/if_malo.c
index 57e0d3d..ae6ef88 100644
--- a/sys/dev/malo/if_malo.c
+++ b/sys/dev/malo/if_malo.c
@@ -275,8 +275,8 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
ifp->if_start = malo_start;
ifp->if_ioctl = malo_ioctl;
ifp->if_init = malo_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index 78f2af3..edd687f 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -665,11 +665,13 @@ mdstart_swap(struct md_s *sc, struct bio *bp)
sf_buf_free(sf);
sched_unpin();
vm_page_wakeup(m);
+ vm_page_lock(m);
vm_page_lock_queues();
vm_page_activate(m);
if (bp->bio_cmd == BIO_WRITE)
vm_page_dirty(m);
vm_page_unlock_queues();
+ vm_page_unlock(m);
/* Actions on further pages start at offset 0 */
p += PAGE_SIZE - offs;
diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c
index 97a423c..a733597 100644
--- a/sys/dev/mii/brgphy.c
+++ b/sys/dev/mii/brgphy.c
@@ -685,16 +685,15 @@ brgphy_status(struct mii_softc *sc)
}
-#if 0
- /* Todo: Change bge/bce to use these settings. */
+ /* Todo: Change bge to use these settings. */
- /* Fetch flow control settings from the PHY */
+ /* Fetch flow control settings from the copper PHY. */
if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
- /* Set FLAG0 is RX is enabled and FLAG1 if TX is enabled */
+ /* Set FLAG0 if RX is enabled and FLAG1 if TX is enabled */
if ((anar & BRGPHY_ANAR_PC) && (anlpar & BRGPHY_ANLPAR_PC)) {
mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1;
} else if (!(anar & BRGPHY_ANAR_PC) && (anlpar & BRGPHY_ANAR_ASP) &&
- (anlpar & BRPHY_ANLPAR_PC) && (anlpar & BRGPHY_ANLPAR_ASP)) {
+ (anlpar & BRGPHY_ANLPAR_PC) && (anlpar & BRGPHY_ANLPAR_ASP)) {
mii->mii_media_active |= IFM_FLAG1;
} else if ((anar & BRGPHY_ANAR_PC) && (anar & BRGPHY_ANAR_ASP) &&
!(anlpar & BRGPHY_ANLPAR_PC) && (anlpar & BRGPHY_ANLPAR_ASP)) {
@@ -703,7 +702,6 @@ brgphy_status(struct mii_softc *sc)
}
/* Todo: Add support for fiber settings too. */
-#endif
brgphy_status_exit:
diff --git a/sys/dev/mii/e1000phy.c b/sys/dev/mii/e1000phy.c
index b50eb07..f30f91c 100644
--- a/sys/dev/mii/e1000phy.c
+++ b/sys/dev/mii/e1000phy.c
@@ -112,6 +112,7 @@ static const struct mii_phydesc e1000phys[] = {
MII_PHY_DESC(MARVELL, E1116R),
MII_PHY_DESC(MARVELL, E1118),
MII_PHY_DESC(MARVELL, E3016),
+ MII_PHY_DESC(MARVELL, PHYG65G),
MII_PHY_DESC(xxMARVELL, E1000),
MII_PHY_DESC(xxMARVELL, E1011),
MII_PHY_DESC(xxMARVELL, E1000_3),
@@ -230,6 +231,7 @@ e1000phy_reset(struct mii_softc *sc)
case MII_MODEL_MARVELL_E1116:
case MII_MODEL_MARVELL_E1118:
case MII_MODEL_MARVELL_E1149:
+ case MII_MODEL_MARVELL_PHYG65G:
/* Disable energy detect mode. */
reg &= ~E1000_SCR_EN_DETECT_MASK;
reg |= E1000_SCR_AUTO_X_MODE;
diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs
index 30cd09c..bbf668b 100644
--- a/sys/dev/mii/miidevs
+++ b/sys/dev/mii/miidevs
@@ -247,6 +247,7 @@ model MARVELL E1116 0x0021 Marvell 88E1116 Gigabit PHY
model MARVELL E1116R 0x0024 Marvell 88E1116R Gigabit PHY
model MARVELL E1118 0x0022 Marvell 88E1118 Gigabit PHY
model MARVELL E3016 0x0026 Marvell 88E3016 10/100 Fast Ethernet PHY
+model MARVELL PHYG65G 0x0027 Marvell PHYG65G Gigabit PHY
model xxMARVELL E1000 0x0005 Marvell 88E1000 Gigabit PHY
model xxMARVELL E1011 0x0002 Marvell 88E1011 Gigabit PHY
model xxMARVELL E1000_3 0x0003 Marvell 88E1000 Gigabit PHY
diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c
index 6a74dc3..40c581c 100644
--- a/sys/dev/mpt/mpt.c
+++ b/sys/dev/mpt/mpt.c
@@ -2667,6 +2667,8 @@ mpt_configure_ioc(struct mpt_softc *mpt, int tn, int needreset)
mpt->is_fc = 0;
mpt->is_sas = 0;
mpt->is_spi = 1;
+ if (mpt->mpt_ini_id == MPT_INI_ID_NONE)
+ mpt->mpt_ini_id = pfp->PortSCSIID;
} else if (pfp->PortType == MPI_PORTFACTS_PORTTYPE_ISCSI) {
mpt_prt(mpt, "iSCSI not supported yet\n");
return (ENXIO);
diff --git a/sys/dev/mpt/mpt.h b/sys/dev/mpt/mpt.h
index 1fa2d1aa..ab4cfa6 100644
--- a/sys/dev/mpt/mpt.h
+++ b/sys/dev/mpt/mpt.h
@@ -130,6 +130,11 @@
#include <machine/clock.h>
#endif
+#ifdef __sparc64__
+#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
+#endif
+
#include <sys/rman.h>
#if __FreeBSD_version < 500000
@@ -172,6 +177,8 @@
#define MPT_ROLE_BOTH 3
#define MPT_ROLE_DEFAULT MPT_ROLE_INITIATOR
+#define MPT_INI_ID_NONE -1
+
/**************************** Forward Declarations ****************************/
struct mpt_softc;
struct mpt_personality;
@@ -637,7 +644,6 @@ struct mpt_softc {
* Port Facts
*/
MSG_PORT_FACTS_REPLY * port_facts;
-#define mpt_ini_id port_facts[0].PortSCSIID
#define mpt_max_tgtcmds port_facts[0].MaxPostedCmdBuffers
/*
@@ -650,6 +656,7 @@ struct mpt_softc {
CONFIG_PAGE_SCSI_PORT_2 _port_page2;
CONFIG_PAGE_SCSI_DEVICE_0 _dev_page0[16];
CONFIG_PAGE_SCSI_DEVICE_1 _dev_page1[16];
+ int _ini_id;
uint16_t _tag_enable;
uint16_t _disc_enable;
} spi;
@@ -658,6 +665,7 @@ struct mpt_softc {
#define mpt_port_page2 cfg.spi._port_page2
#define mpt_dev_page0 cfg.spi._dev_page0
#define mpt_dev_page1 cfg.spi._dev_page1
+#define mpt_ini_id cfg.spi._ini_id
#define mpt_tag_enable cfg.spi._tag_enable
#define mpt_disc_enable cfg.spi._disc_enable
struct mpi_fc_cfg {
diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c
index 5e63ef9..39b57de 100644
--- a/sys/dev/mpt/mpt_cam.c
+++ b/sys/dev/mpt/mpt_cam.c
@@ -1058,12 +1058,13 @@ mpt_read_config_info_spi(struct mpt_softc *mpt)
static int
mpt_set_initial_config_spi(struct mpt_softc *mpt)
{
- int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id;
- int error;
+ int error, i, pp1val;
mpt->mpt_disc_enable = 0xff;
mpt->mpt_tag_enable = 0;
+ pp1val = ((1 << mpt->mpt_ini_id) <<
+ MPI_SCSIPORTPAGE1_CFG_SHIFT_PORT_RESPONSE_ID) | mpt->mpt_ini_id;
if (mpt->mpt_port_page1.Configuration != pp1val) {
CONFIG_PAGE_SCSI_PORT_1 tmp;
@@ -2574,6 +2575,10 @@ mpt_cam_event(struct mpt_softc *mpt, request_t *req,
CAMLOCK_2_MPTLOCK(mpt);
break;
}
+ case MPI_EVENT_IR_RESYNC_UPDATE:
+ mpt_prt(mpt, "IR resync update %d completed\n",
+ (data0 >> 16) & 0xff);
+ break;
case MPI_EVENT_EVENT_CHANGE:
case MPI_EVENT_INTEGRATED_RAID:
case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
diff --git a/sys/dev/mpt/mpt_pci.c b/sys/dev/mpt/mpt_pci.c
index 1e9dc92..e3b0ea3 100644
--- a/sys/dev/mpt/mpt_pci.c
+++ b/sys/dev/mpt/mpt_pci.c
@@ -460,6 +460,11 @@ mpt_pci_attach(device_t dev)
mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT;
mpt->verbose = MPT_PRT_NONE;
mpt->role = MPT_ROLE_NONE;
+ mpt->mpt_ini_id = MPT_INI_ID_NONE;
+#ifdef __sparc64__
+ if (mpt->is_spi)
+ mpt->mpt_ini_id = OF_getscsinitid(dev);
+#endif
mpt_set_options(mpt);
if (mpt->verbose == MPT_PRT_NONE) {
mpt->verbose = MPT_PRT_WARN;
diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c
index c083e1e..3f97c3a 100644
--- a/sys/dev/msk/if_msk.c
+++ b/sys/dev/msk/if_msk.c
@@ -223,6 +223,8 @@ static struct msk_product {
"Marvell Yukon 88E8072 Gigabit Ethernet" },
{ VENDORID_MARVELL, DEVICEID_MRVL_4380,
"Marvell Yukon 88E8057 Gigabit Ethernet" },
+ { VENDORID_MARVELL, DEVICEID_MRVL_4381,
+ "Marvell Yukon 88E8059 Gigabit Ethernet" },
{ VENDORID_DLINK, DEVICEID_DLINK_DGE550SX,
"D-Link 550SX Gigabit Ethernet" },
{ VENDORID_DLINK, DEVICEID_DLINK_DGE560SX,
@@ -239,7 +241,9 @@ static const char *model_name[] = {
"Yukon FE",
"Yukon FE+",
"Yukon Supreme",
- "Yukon Ultra 2"
+ "Yukon Ultra 2",
+ "Yukon Unknown",
+ "Yukon Optima",
};
static int mskc_probe(device_t);
@@ -1097,7 +1101,8 @@ msk_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
(IFCAP_VLAN_HWTAGGING & ifp->if_capabilities) != 0) {
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
if ((IFCAP_VLAN_HWTAGGING & ifp->if_capenable) == 0)
- ifp->if_capenable &= ~IFCAP_VLAN_HWTSO;
+ ifp->if_capenable &=
+ ~(IFCAP_VLAN_HWTSO | IFCAP_VLAN_HWCSUM);
msk_setvlan(sc_if, ifp);
}
if (ifp->if_mtu > ETHERMTU &&
@@ -1229,6 +1234,7 @@ msk_phy_power(struct msk_softc *sc, int mode)
case CHIP_ID_YUKON_EX:
case CHIP_ID_YUKON_FE_P:
case CHIP_ID_YUKON_UL_2:
+ case CHIP_ID_YUKON_OPT:
CSR_WRITE_2(sc, B0_CTST, Y2_HW_WOL_OFF);
/* Enable all clocks. */
@@ -1372,6 +1378,10 @@ mskc_reset(struct msk_softc *sc)
GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON |
GMC_BYP_RETR_ON);
}
+ if (sc->msk_hw_id == CHIP_ID_YUKON_OPT && sc->msk_hw_rev == 0) {
+ /* Disable PCIe PHY powerdown(reg 0x80, bit7). */
+ CSR_WRITE_4(sc, Y2_PEX_PHY_DATA, (0x0080 << 16) | 0x0080);
+ }
CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
/* LED On. */
@@ -1705,8 +1715,9 @@ mskc_attach(device_t dev)
sc->msk_hw_rev = (CSR_READ_1(sc, B2_MAC_CFG) >> 4) & 0x0f;
/* Bail out if chip is not recognized. */
if (sc->msk_hw_id < CHIP_ID_YUKON_XL ||
- sc->msk_hw_id > CHIP_ID_YUKON_UL_2 ||
- sc->msk_hw_id == CHIP_ID_YUKON_SUPR) {
+ sc->msk_hw_id > CHIP_ID_YUKON_OPT ||
+ sc->msk_hw_id == CHIP_ID_YUKON_SUPR ||
+ sc->msk_hw_id == CHIP_ID_YUKON_UNKNOWN) {
device_printf(dev, "unknown device: id=0x%02x, rev=0x%02x\n",
sc->msk_hw_id, sc->msk_hw_rev);
mtx_destroy(&sc->msk_mtx);
@@ -1819,6 +1830,10 @@ mskc_attach(device_t dev)
sc->msk_clock = 125; /* 125 MHz */
sc->msk_pflags |= MSK_FLAG_JUMBO;
break;
+ case CHIP_ID_YUKON_OPT:
+ sc->msk_clock = 125; /* 125 MHz */
+ sc->msk_pflags |= MSK_FLAG_JUMBO | MSK_FLAG_DESCV2;
+ break;
default:
sc->msk_clock = 156; /* 156 MHz */
break;
@@ -2890,20 +2905,15 @@ mskc_shutdown(device_t dev)
sc = device_get_softc(dev);
MSK_LOCK(sc);
for (i = 0; i < sc->msk_num_port; i++) {
- if (sc->msk_if[i] != NULL)
+ if (sc->msk_if[i] != NULL && sc->msk_if[i]->msk_ifp != NULL &&
+ ((sc->msk_if[i]->msk_ifp->if_drv_flags &
+ IFF_DRV_RUNNING) != 0))
msk_stop(sc->msk_if[i]);
}
-
- /* Disable all interrupts. */
- CSR_WRITE_4(sc, B0_IMSK, 0);
- CSR_READ_4(sc, B0_IMSK);
- CSR_WRITE_4(sc, B0_HWE_IMSK, 0);
- CSR_READ_4(sc, B0_HWE_IMSK);
+ MSK_UNLOCK(sc);
/* Put hardware reset. */
CSR_WRITE_2(sc, B0_CTST, CS_RST_SET);
-
- MSK_UNLOCK(sc);
return (0);
}
@@ -3511,6 +3521,8 @@ msk_handle_events(struct msk_softc *sc)
sc_if->msk_csum = status;
break;
case OP_RXSTAT:
+ if (!(sc_if->msk_ifp->if_drv_flags & IFF_DRV_RUNNING))
+ break;
if (sc_if->msk_framesize >
(MCLBYTES - MSK_RX_BUF_ALIGN))
msk_jumbo_rxeof(sc_if, status, control, len);
@@ -3580,6 +3592,7 @@ msk_intr(void *xsc)
(sc->msk_pflags & MSK_FLAG_SUSPEND) != 0 ||
(status & sc->msk_intrmask) == 0) {
CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2);
+ MSK_UNLOCK(sc);
return;
}
@@ -3822,9 +3835,9 @@ msk_init_locked(struct msk_if_softc *sc_if)
if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0) {
/* Set Rx Pause threshould. */
- CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, RX_GMF_LP_THR),
+ CSR_WRITE_2(sc, MR_ADDR(sc_if->msk_port, RX_GMF_LP_THR),
MSK_ECU_LLPP);
- CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, RX_GMF_UP_THR),
+ CSR_WRITE_2(sc, MR_ADDR(sc_if->msk_port, RX_GMF_UP_THR),
MSK_ECU_ULPP);
/* Configure store-and-forward for Tx. */
msk_set_tx_stfwd(sc_if);
@@ -3917,6 +3930,11 @@ msk_init_locked(struct msk_if_softc *sc_if)
msk_stop(sc_if);
return;
}
+ if (sc->msk_hw_id == CHIP_ID_YUKON_EX) {
+ /* Disable flushing of non-ASF packets. */
+ CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T),
+ GMF_RX_MACSEC_FLUSH_OFF);
+ }
/* Configure interrupt handling. */
if (sc_if->msk_port == MSK_PORT_A) {
diff --git a/sys/dev/msk/if_mskreg.h b/sys/dev/msk/if_mskreg.h
index 34cac67..3b05b9b 100644
--- a/sys/dev/msk/if_mskreg.h
+++ b/sys/dev/msk/if_mskreg.h
@@ -145,6 +145,7 @@
#define DEVICEID_MRVL_436B 0x436B
#define DEVICEID_MRVL_436C 0x436C
#define DEVICEID_MRVL_4380 0x4380
+#define DEVICEID_MRVL_4381 0x4381
/*
* D-Link gigabit ethernet device ID
@@ -621,8 +622,8 @@
#define RX_GMF_FL_MSK 0x0c4c /* 32 bit Rx GMAC FIFO Flush Mask */
#define RX_GMF_FL_THR 0x0c50 /* 32 bit Rx GMAC FIFO Flush Threshold */
#define RX_GMF_TR_THR 0x0c54 /* 32 bit Rx Truncation Threshold (Yukon-2) */
-#define RX_GMF_UP_THR 0x0c58 /* 8 bit Rx Upper Pause Thr (Yukon-EC_U) */
-#define RX_GMF_LP_THR 0x0c5a /* 8 bit Rx Lower Pause Thr (Yukon-EC_U) */
+#define RX_GMF_UP_THR 0x0c58 /* 16 bit Rx Upper Pause Thr (Yukon-EC_U) */
+#define RX_GMF_LP_THR 0x0c5a /* 16 bit Rx Lower Pause Thr (Yukon-EC_U) */
#define RX_GMF_VLAN 0x0c5c /* 32 bit Rx VLAN Type Register (Yukon-2) */
#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */
#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */
@@ -828,6 +829,9 @@
#define Y2_IS_CHK_RX2 BIT_10 /* Descriptor error Rx 2 */
#define Y2_IS_CHK_TXS2 BIT_9 /* Descriptor error TXS 2 */
#define Y2_IS_CHK_TXA2 BIT_8 /* Descriptor error TXA 2 */
+#define Y2_IS_PSM_ACK BIT_7 /* PSM Ack (Yukon Optima) */
+#define Y2_IS_PTP_TIST BIT_6 /* PTP TIme Stamp (Yukon Optima) */
+#define Y2_IS_PHY_QLNK BIT_5 /* PHY Quick Link (Yukon Optima) */
#define Y2_IS_IRQ_PHY1 BIT_4 /* Interrupt from PHY 1 */
#define Y2_IS_IRQ_MAC1 BIT_3 /* Interrupt from MAC 1 */
#define Y2_IS_CHK_RX1 BIT_2 /* Descriptor error Rx 1 */
@@ -894,6 +898,8 @@
#define CHIP_ID_YUKON_FE_P 0xb8 /* Chip ID for YUKON-2 FE+ */
#define CHIP_ID_YUKON_SUPR 0xb9 /* Chip ID for YUKON-2 Supreme */
#define CHIP_ID_YUKON_UL_2 0xba /* Chip ID for YUKON-2 Ultra 2 */
+#define CHIP_ID_YUKON_UNKNOWN 0xbb
+#define CHIP_ID_YUKON_OPT 0xbc /* Chip ID for YUKON-2 Optima */
#define CHIP_REV_YU_XL_A0 0 /* Chip Rev. for Yukon-2 A0 */
#define CHIP_REV_YU_XL_A1 1 /* Chip Rev. for Yukon-2 A1 */
@@ -1941,6 +1947,8 @@
#define RX_TRUNC_OFF BIT_26 /* disable packet truncation */
#define RX_VLAN_STRIP_ON BIT_25 /* enable VLAN stripping */
#define RX_VLAN_STRIP_OFF BIT_24 /* disable VLAN stripping */
+#define GMF_RX_MACSEC_FLUSH_ON BIT_23
+#define GMF_RX_MACSEC_FLUSH_OFF BIT_22
#define GMF_RX_OVER_ON BIT_19 /* enable flushing on receive overrun */
#define GMF_RX_OVER_OFF BIT_18 /* disable flushing on receive overrun */
#define GMF_ASF_RX_OVER_ON BIT_17 /* enable flushing of ASF when overrun */
diff --git a/sys/dev/mvs/mvs.c b/sys/dev/mvs/mvs.c
new file mode 100644
index 0000000..038e9f21
--- /dev/null
+++ b/sys/dev/mvs/mvs.c
@@ -0,0 +1,2173 @@
+/*-
+ * Copyright (c) 2010 Alexander Motin <mav@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,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must 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/module.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/ata.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <vm/uma.h>
+#include <machine/stdarg.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include "mvs.h"
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt_sim.h>
+#include <cam/cam_debug.h>
+
+/* local prototypes */
+static int mvs_ch_suspend(device_t dev);
+static int mvs_ch_resume(device_t dev);
+static void mvs_dmainit(device_t dev);
+static void mvs_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
+static void mvs_dmafini(device_t dev);
+static void mvs_slotsalloc(device_t dev);
+static void mvs_slotsfree(device_t dev);
+static void mvs_setup_edma_queues(device_t dev);
+static void mvs_set_edma_mode(device_t dev, enum mvs_edma_mode mode);
+static void mvs_ch_pm(void *arg);
+static void mvs_ch_intr_locked(void *data);
+static void mvs_ch_intr(void *data);
+static void mvs_reset(device_t dev);
+static void mvs_softreset(device_t dev, union ccb *ccb);
+
+static int mvs_sata_connect(struct mvs_channel *ch);
+static int mvs_sata_phy_reset(device_t dev);
+static int mvs_wait(device_t dev, u_int s, u_int c, int t);
+static void mvs_tfd_read(device_t dev, union ccb *ccb);
+static void mvs_tfd_write(device_t dev, union ccb *ccb);
+static void mvs_legacy_intr(device_t dev);
+static void mvs_crbq_intr(device_t dev);
+static void mvs_begin_transaction(device_t dev, union ccb *ccb);
+static void mvs_legacy_execute_transaction(struct mvs_slot *slot);
+static void mvs_timeout(struct mvs_slot *slot);
+static void mvs_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error);
+static void mvs_requeue_frozen(device_t dev);
+static void mvs_execute_transaction(struct mvs_slot *slot);
+static void mvs_end_transaction(struct mvs_slot *slot, enum mvs_err_type et);
+
+static void mvs_issue_read_log(device_t dev);
+static void mvs_process_read_log(device_t dev, union ccb *ccb);
+
+static void mvsaction(struct cam_sim *sim, union ccb *ccb);
+static void mvspoll(struct cam_sim *sim);
+
+MALLOC_DEFINE(M_MVS, "MVS driver", "MVS driver data buffers");
+
+static int
+mvs_ch_probe(device_t dev)
+{
+
+ device_set_desc_copy(dev, "Marvell SATA channel");
+ return (0);
+}
+
+static int
+mvs_ch_attach(device_t dev)
+{
+ struct mvs_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct mvs_channel *ch = device_get_softc(dev);
+ struct cam_devq *devq;
+ int rid, error, i, sata_rev = 0;
+
+ ch->dev = dev;
+ ch->unit = (intptr_t)device_get_ivars(dev);
+ ch->quirks = ctlr->quirks;
+ mtx_init(&ch->mtx, "MVS channel lock", NULL, MTX_DEF);
+ resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "pm_level", &ch->pm_level);
+ if (ch->pm_level > 3)
+ callout_init_mtx(&ch->pm_timer, &ch->mtx, 0);
+ resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "sata_rev", &sata_rev);
+ for (i = 0; i < 16; i++) {
+ ch->user[i].revision = sata_rev;
+ ch->user[i].mode = 0;
+ ch->user[i].bytecount = (ch->quirks & MVS_Q_GENIIE) ? 8192 : 2048;
+ ch->user[i].tags = MVS_MAX_SLOTS;
+ ch->curr[i] = ch->user[i];
+ if (ch->pm_level) {
+ ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ |
+ CTS_SATA_CAPS_H_APST |
+ CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST;
+ }
+ }
+ rid = ch->unit;
+ if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &rid, RF_ACTIVE)))
+ return (ENXIO);
+ mvs_dmainit(dev);
+ mvs_slotsalloc(dev);
+ mvs_ch_resume(dev);
+ mtx_lock(&ch->mtx);
+ rid = ATA_IRQ_RID;
+ if (!(ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &rid, RF_SHAREABLE | RF_ACTIVE))) {
+ device_printf(dev, "Unable to map interrupt\n");
+ error = ENXIO;
+ goto err0;
+ }
+ if ((bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL,
+ mvs_ch_intr_locked, dev, &ch->ih))) {
+ device_printf(dev, "Unable to setup interrupt\n");
+ error = ENXIO;
+ goto err1;
+ }
+ /* Create the device queue for our SIM. */
+ devq = cam_simq_alloc(MVS_MAX_SLOTS - 1);
+ if (devq == NULL) {
+ device_printf(dev, "Unable to allocate simq\n");
+ error = ENOMEM;
+ goto err1;
+ }
+ /* Construct SIM entry */
+ ch->sim = cam_sim_alloc(mvsaction, mvspoll, "mvsch", ch,
+ device_get_unit(dev), &ch->mtx,
+ 2, (ch->quirks & MVS_Q_GENI) ? 0 : MVS_MAX_SLOTS - 1,
+ devq);
+ if (ch->sim == NULL) {
+ cam_simq_free(devq);
+ device_printf(dev, "unable to allocate sim\n");
+ error = ENOMEM;
+ goto err1;
+ }
+ if (xpt_bus_register(ch->sim, dev, 0) != CAM_SUCCESS) {
+ device_printf(dev, "unable to register xpt bus\n");
+ error = ENXIO;
+ goto err2;
+ }
+ if (xpt_create_path(&ch->path, /*periph*/NULL, cam_sim_path(ch->sim),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ device_printf(dev, "unable to create path\n");
+ error = ENXIO;
+ goto err3;
+ }
+ if (ch->pm_level > 3) {
+ callout_reset(&ch->pm_timer,
+ (ch->pm_level == 4) ? hz / 1000 : hz / 8,
+ mvs_ch_pm, dev);
+ }
+ mtx_unlock(&ch->mtx);
+ return (0);
+
+err3:
+ xpt_bus_deregister(cam_sim_path(ch->sim));
+err2:
+ cam_sim_free(ch->sim, /*free_devq*/TRUE);
+err1:
+ bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
+err0:
+ bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem);
+ mtx_unlock(&ch->mtx);
+ mtx_destroy(&ch->mtx);
+ return (error);
+}
+
+static int
+mvs_ch_detach(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+
+ mtx_lock(&ch->mtx);
+ xpt_async(AC_LOST_DEVICE, ch->path, NULL);
+ xpt_free_path(ch->path);
+ xpt_bus_deregister(cam_sim_path(ch->sim));
+ cam_sim_free(ch->sim, /*free_devq*/TRUE);
+ mtx_unlock(&ch->mtx);
+
+ if (ch->pm_level > 3)
+ callout_drain(&ch->pm_timer);
+ bus_teardown_intr(dev, ch->r_irq, ch->ih);
+ bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
+
+ mvs_ch_suspend(dev);
+ mvs_slotsfree(dev);
+ mvs_dmafini(dev);
+
+ bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem);
+ mtx_destroy(&ch->mtx);
+ return (0);
+}
+
+static int
+mvs_ch_suspend(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+
+ /* Stop EDMA */
+ mvs_set_edma_mode(dev, MVS_EDMA_OFF);
+ /* Disable port interrupts. */
+ ATA_OUTL(ch->r_mem, EDMA_IEM, 0);
+ return (0);
+}
+
+static int
+mvs_ch_resume(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ uint32_t reg;
+
+ /* Disable port interrupts */
+ ATA_OUTL(ch->r_mem, EDMA_IEM, 0);
+ /* Stop EDMA */
+ ch->curr_mode = MVS_EDMA_UNKNOWN;
+ mvs_set_edma_mode(dev, MVS_EDMA_OFF);
+ /* Clear and configure FIS interrupts. */
+ ATA_OUTL(ch->r_mem, SATA_FISIC, 0);
+ reg = ATA_INL(ch->r_mem, SATA_FISC);
+ reg |= SATA_FISC_FISWAIT4HOSTRDYEN_B1;
+ ATA_OUTL(ch->r_mem, SATA_FISC, reg);
+ reg = ATA_INL(ch->r_mem, SATA_FISIM);
+ reg |= SATA_FISC_FISWAIT4HOSTRDYEN_B1;
+ ATA_OUTL(ch->r_mem, SATA_FISC, reg);
+ /* Clear SATA error register. */
+ ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff);
+ /* Clear any outstanding error interrupts. */
+ ATA_OUTL(ch->r_mem, EDMA_IEC, 0);
+ /* Unmask all error interrupts */
+ ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT);
+ return (0);
+}
+
+struct mvs_dc_cb_args {
+ bus_addr_t maddr;
+ int error;
+};
+
+static void
+mvs_dmainit(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ struct mvs_dc_cb_args dcba;
+
+ /* EDMA command request area. */
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), 1024, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
+ NULL, NULL, MVS_WORKRQ_SIZE, 1, MVS_WORKRQ_SIZE,
+ 0, NULL, NULL, &ch->dma.workrq_tag))
+ goto error;
+ if (bus_dmamem_alloc(ch->dma.workrq_tag, (void **)&ch->dma.workrq, 0,
+ &ch->dma.workrq_map))
+ goto error;
+ if (bus_dmamap_load(ch->dma.workrq_tag, ch->dma.workrq_map, ch->dma.workrq,
+ MVS_WORKRQ_SIZE, mvs_dmasetupc_cb, &dcba, 0) || dcba.error) {
+ bus_dmamem_free(ch->dma.workrq_tag, ch->dma.workrq, ch->dma.workrq_map);
+ goto error;
+ }
+ ch->dma.workrq_bus = dcba.maddr;
+ /* EDMA command response area. */
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), 256, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
+ NULL, NULL, MVS_WORKRP_SIZE, 1, MVS_WORKRP_SIZE,
+ 0, NULL, NULL, &ch->dma.workrp_tag))
+ goto error;
+ if (bus_dmamem_alloc(ch->dma.workrp_tag, (void **)&ch->dma.workrp, 0,
+ &ch->dma.workrp_map))
+ goto error;
+ if (bus_dmamap_load(ch->dma.workrp_tag, ch->dma.workrp_map, ch->dma.workrp,
+ MVS_WORKRP_SIZE, mvs_dmasetupc_cb, &dcba, 0) || dcba.error) {
+ bus_dmamem_free(ch->dma.workrp_tag, ch->dma.workrp, ch->dma.workrp_map);
+ goto error;
+ }
+ ch->dma.workrp_bus = dcba.maddr;
+ /* Data area. */
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), 2, MVS_EPRD_MAX,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
+ NULL, NULL,
+ MVS_SG_ENTRIES * PAGE_SIZE * MVS_MAX_SLOTS,
+ MVS_SG_ENTRIES, MVS_EPRD_MAX,
+ 0, busdma_lock_mutex, &ch->mtx, &ch->dma.data_tag)) {
+ goto error;
+ }
+ return;
+
+error:
+ device_printf(dev, "WARNING - DMA initialization failed\n");
+ mvs_dmafini(dev);
+}
+
+static void
+mvs_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct mvs_dc_cb_args *dcba = (struct mvs_dc_cb_args *)xsc;
+
+ if (!(dcba->error = error))
+ dcba->maddr = segs[0].ds_addr;
+}
+
+static void
+mvs_dmafini(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+
+ if (ch->dma.data_tag) {
+ bus_dma_tag_destroy(ch->dma.data_tag);
+ ch->dma.data_tag = NULL;
+ }
+ if (ch->dma.workrp_bus) {
+ bus_dmamap_unload(ch->dma.workrp_tag, ch->dma.workrp_map);
+ bus_dmamem_free(ch->dma.workrp_tag, ch->dma.workrp, ch->dma.workrp_map);
+ ch->dma.workrp_bus = 0;
+ ch->dma.workrp_map = NULL;
+ ch->dma.workrp = NULL;
+ }
+ if (ch->dma.workrp_tag) {
+ bus_dma_tag_destroy(ch->dma.workrp_tag);
+ ch->dma.workrp_tag = NULL;
+ }
+ if (ch->dma.workrq_bus) {
+ bus_dmamap_unload(ch->dma.workrq_tag, ch->dma.workrq_map);
+ bus_dmamem_free(ch->dma.workrq_tag, ch->dma.workrq, ch->dma.workrq_map);
+ ch->dma.workrq_bus = 0;
+ ch->dma.workrq_map = NULL;
+ ch->dma.workrq = NULL;
+ }
+ if (ch->dma.workrq_tag) {
+ bus_dma_tag_destroy(ch->dma.workrq_tag);
+ ch->dma.workrq_tag = NULL;
+ }
+}
+
+static void
+mvs_slotsalloc(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ int i;
+
+ /* Alloc and setup command/dma slots */
+ bzero(ch->slot, sizeof(ch->slot));
+ for (i = 0; i < MVS_MAX_SLOTS; i++) {
+ struct mvs_slot *slot = &ch->slot[i];
+
+ slot->dev = dev;
+ slot->slot = i;
+ slot->state = MVS_SLOT_EMPTY;
+ slot->ccb = NULL;
+ callout_init_mtx(&slot->timeout, &ch->mtx, 0);
+
+ if (bus_dmamap_create(ch->dma.data_tag, 0, &slot->dma.data_map))
+ device_printf(ch->dev, "FAILURE - create data_map\n");
+ }
+}
+
+static void
+mvs_slotsfree(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ int i;
+
+ /* Free all dma slots */
+ for (i = 0; i < MVS_MAX_SLOTS; i++) {
+ struct mvs_slot *slot = &ch->slot[i];
+
+ callout_drain(&slot->timeout);
+ if (slot->dma.data_map) {
+ bus_dmamap_destroy(ch->dma.data_tag, slot->dma.data_map);
+ slot->dma.data_map = NULL;
+ }
+ }
+}
+
+static void
+mvs_setup_edma_queues(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ uint64_t work;
+
+ /* Requests queue. */
+ work = ch->dma.workrq_bus;
+ ATA_OUTL(ch->r_mem, EDMA_REQQBAH, work >> 32);
+ ATA_OUTL(ch->r_mem, EDMA_REQQIP, work & 0xffffffff);
+ ATA_OUTL(ch->r_mem, EDMA_REQQOP, work & 0xffffffff);
+ bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map, BUS_DMASYNC_PREWRITE);
+ /* Reponses queue. */
+ bzero(ch->dma.workrp, 256);
+ work = ch->dma.workrp_bus;
+ ATA_OUTL(ch->r_mem, EDMA_RESQBAH, work >> 32);
+ ATA_OUTL(ch->r_mem, EDMA_RESQIP, work & 0xffffffff);
+ ATA_OUTL(ch->r_mem, EDMA_RESQOP, work & 0xffffffff);
+ bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, BUS_DMASYNC_PREREAD);
+ ch->out_idx = 0;
+ ch->in_idx = 0;
+}
+
+static void
+mvs_set_edma_mode(device_t dev, enum mvs_edma_mode mode)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ int timeout;
+ uint32_t ecfg, fcfg, hc, ltm, unkn;
+
+ if (mode == ch->curr_mode)
+ return;
+ /* If we are running, we should stop first. */
+ if (ch->curr_mode != MVS_EDMA_OFF) {
+ ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EDSEDMA);
+ timeout = 0;
+ while (ATA_INL(ch->r_mem, EDMA_CMD) & EDMA_CMD_EENEDMA) {
+ DELAY(1000);
+ if (timeout++ > 1000) {
+ device_printf(dev, "stopping EDMA engine failed\n");
+ break;
+ }
+ };
+ }
+ ch->curr_mode = mode;
+ ch->fbs_enabled = 0;
+ ch->fake_busy = 0;
+ /* Report mode to controller. Needed for correct CCC operation. */
+ MVS_EDMA(device_get_parent(dev), dev, mode);
+ /* Configure new mode. */
+ ecfg = EDMA_CFG_RESERVED | EDMA_CFG_RESERVED2 | EDMA_CFG_EHOSTQUEUECACHEEN;
+ if (ch->pm_present) {
+ ecfg |= EDMA_CFG_EMASKRXPM;
+ if (ch->quirks & MVS_Q_GENIIE) {
+ ecfg |= EDMA_CFG_EEDMAFBS;
+ ch->fbs_enabled = 1;
+ }
+ }
+ if (ch->quirks & MVS_Q_GENI)
+ ecfg |= EDMA_CFG_ERDBSZ;
+ else if (ch->quirks & MVS_Q_GENII)
+ ecfg |= EDMA_CFG_ERDBSZEXT | EDMA_CFG_EWRBUFFERLEN;
+ if (ch->quirks & MVS_Q_CT)
+ ecfg |= EDMA_CFG_ECUTTHROUGHEN;
+ if (mode != MVS_EDMA_OFF)
+ ecfg |= EDMA_CFG_EEARLYCOMPLETIONEN;
+ if (mode == MVS_EDMA_QUEUED)
+ ecfg |= EDMA_CFG_EQUE;
+ else if (mode == MVS_EDMA_NCQ)
+ ecfg |= EDMA_CFG_ESATANATVCMDQUE;
+ ATA_OUTL(ch->r_mem, EDMA_CFG, ecfg);
+ mvs_setup_edma_queues(dev);
+ if (ch->quirks & MVS_Q_GENIIE) {
+ /* Configure FBS-related registers */
+ fcfg = ATA_INL(ch->r_mem, SATA_FISC);
+ ltm = ATA_INL(ch->r_mem, SATA_LTM);
+ hc = ATA_INL(ch->r_mem, EDMA_HC);
+ if (ch->fbs_enabled) {
+ fcfg |= SATA_FISC_FISDMAACTIVATESYNCRESP;
+ if (mode == MVS_EDMA_NCQ) {
+ fcfg &= ~SATA_FISC_FISWAIT4HOSTRDYEN_B0;
+ hc &= ~EDMA_IE_EDEVERR;
+ } else {
+ fcfg |= SATA_FISC_FISWAIT4HOSTRDYEN_B0;
+ hc |= EDMA_IE_EDEVERR;
+ }
+ ltm |= (1 << 8);
+ } else {
+ fcfg &= ~SATA_FISC_FISDMAACTIVATESYNCRESP;
+ fcfg &= ~SATA_FISC_FISWAIT4HOSTRDYEN_B0;
+ hc |= EDMA_IE_EDEVERR;
+ ltm &= ~(1 << 8);
+ }
+ ATA_OUTL(ch->r_mem, SATA_FISC, fcfg);
+ ATA_OUTL(ch->r_mem, SATA_LTM, ltm);
+ ATA_OUTL(ch->r_mem, EDMA_HC, hc);
+ /* This is some magic, required to handle several DRQs
+ * with basic DMA. */
+ unkn = ATA_INL(ch->r_mem, EDMA_UNKN_RESD);
+ if (mode == MVS_EDMA_OFF)
+ unkn |= 1;
+ else
+ unkn &= ~1;
+ ATA_OUTL(ch->r_mem, EDMA_UNKN_RESD, unkn);
+ }
+ /* Run EDMA. */
+ if (mode != MVS_EDMA_OFF)
+ ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EENEDMA);
+}
+
+devclass_t mvs_devclass;
+devclass_t mvsch_devclass;
+static device_method_t mvsch_methods[] = {
+ DEVMETHOD(device_probe, mvs_ch_probe),
+ DEVMETHOD(device_attach, mvs_ch_attach),
+ DEVMETHOD(device_detach, mvs_ch_detach),
+ DEVMETHOD(device_suspend, mvs_ch_suspend),
+ DEVMETHOD(device_resume, mvs_ch_resume),
+ { 0, 0 }
+};
+static driver_t mvsch_driver = {
+ "mvsch",
+ mvsch_methods,
+ sizeof(struct mvs_channel)
+};
+DRIVER_MODULE(mvsch, mvs, mvsch_driver, mvsch_devclass, 0, 0);
+DRIVER_MODULE(mvsch, sata, mvsch_driver, mvsch_devclass, 0, 0);
+
+static void
+mvs_phy_check_events(device_t dev, u_int32_t serr)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+
+ if (ch->pm_level == 0) {
+ u_int32_t status = ATA_INL(ch->r_mem, SATA_SS);
+ union ccb *ccb;
+
+ if (bootverbose) {
+ if (((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_ONLINE) &&
+ ((status & SATA_SS_SPD_MASK) != SATA_SS_SPD_NO_SPEED) &&
+ ((status & SATA_SS_IPM_MASK) == SATA_SS_IPM_ACTIVE)) {
+ device_printf(dev, "CONNECT requested\n");
+ } else
+ device_printf(dev, "DISCONNECT requested\n");
+ }
+ mvs_reset(dev);
+ if ((ccb = xpt_alloc_ccb_nowait()) == NULL)
+ return;
+ if (xpt_create_path(&ccb->ccb_h.path, NULL,
+ cam_sim_path(ch->sim),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb);
+ return;
+ }
+ xpt_rescan(ccb);
+ }
+}
+
+static void
+mvs_notify_events(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ struct cam_path *dpath;
+ uint32_t fis;
+ int d;
+
+ /* Try to read PMP field from SDB FIS. Present only for Gen-IIe. */
+ fis = ATA_INL(ch->r_mem, SATA_FISDW0);
+ if ((fis & 0x80ff) == 0x80a1)
+ d = (fis & 0x0f00) >> 8;
+ else
+ d = ch->pm_present ? 15 : 0;
+ if (bootverbose)
+ device_printf(dev, "SNTF %d\n", d);
+ if (xpt_create_path(&dpath, NULL,
+ xpt_path_path_id(ch->path), d, 0) == CAM_REQ_CMP) {
+ xpt_async(AC_SCSI_AEN, dpath, NULL);
+ xpt_free_path(dpath);
+ }
+}
+
+static void
+mvs_ch_intr_locked(void *data)
+{
+ struct mvs_intr_arg *arg = (struct mvs_intr_arg *)data;
+ device_t dev = (device_t)arg->arg;
+ struct mvs_channel *ch = device_get_softc(dev);
+
+ mtx_lock(&ch->mtx);
+ mvs_ch_intr(data);
+ mtx_unlock(&ch->mtx);
+}
+
+static void
+mvs_ch_pm(void *arg)
+{
+ device_t dev = (device_t)arg;
+ struct mvs_channel *ch = device_get_softc(dev);
+ uint32_t work;
+
+ if (ch->numrslots != 0)
+ return;
+ /* If we are idle - request power state transition. */
+ work = ATA_INL(ch->r_mem, SATA_SC);
+ work &= ~SATA_SC_SPM_MASK;
+ if (ch->pm_level == 4)
+ work |= SATA_SC_SPM_PARTIAL;
+ else
+ work |= SATA_SC_SPM_SLUMBER;
+ ATA_OUTL(ch->r_mem, SATA_SC, work);
+}
+
+static void
+mvs_ch_pm_wake(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ uint32_t work;
+ int timeout = 0;
+
+ work = ATA_INL(ch->r_mem, SATA_SS);
+ if (work & SATA_SS_IPM_ACTIVE)
+ return;
+ /* If we are not in active state - request power state transition. */
+ work = ATA_INL(ch->r_mem, SATA_SC);
+ work &= ~SATA_SC_SPM_MASK;
+ work |= SATA_SC_SPM_ACTIVE;
+ ATA_OUTL(ch->r_mem, SATA_SC, work);
+ /* Wait for transition to happen. */
+ while ((ATA_INL(ch->r_mem, SATA_SS) & SATA_SS_IPM_ACTIVE) == 0 &&
+ timeout++ < 100) {
+ DELAY(100);
+ }
+}
+
+static void
+mvs_ch_intr(void *data)
+{
+ struct mvs_intr_arg *arg = (struct mvs_intr_arg *)data;
+ device_t dev = (device_t)arg->arg;
+ struct mvs_channel *ch = device_get_softc(dev);
+ uint32_t iec, serr = 0, fisic = 0;
+ enum mvs_err_type et;
+ int i, ccs, port = -1, selfdis = 0;
+ int edma = (ch->numtslots != 0 || ch->numdslots != 0);
+
+//device_printf(dev, "irq cause %02x EDMA %d IEC %08x\n",
+// arg->cause, edma, ATA_INL(ch->r_mem, EDMA_IEC));
+ /* New item in response queue. */
+ if ((arg->cause & 2) && edma)
+ mvs_crbq_intr(dev);
+ /* Some error or special event. */
+ if (arg->cause & 1) {
+ iec = ATA_INL(ch->r_mem, EDMA_IEC);
+//device_printf(dev, "irq cause %02x EDMA %d IEC %08x\n",
+// arg->cause, edma, iec);
+ if (iec & EDMA_IE_SERRINT) {
+ serr = ATA_INL(ch->r_mem, SATA_SE);
+ ATA_OUTL(ch->r_mem, SATA_SE, serr);
+//device_printf(dev, "SERR %08x\n", serr);
+ }
+ /* EDMA self-disabled due to error. */
+ if (iec & EDMA_IE_ESELFDIS)
+ selfdis = 1;
+ /* Transport interrupt. */
+ if (iec & EDMA_IE_ETRANSINT) {
+ /* For Gen-I this bit means self-disable. */
+ if (ch->quirks & MVS_Q_GENI)
+ selfdis = 1;
+ /* For Gen-II this bit means SDB-N. */
+ else if (ch->quirks & MVS_Q_GENII)
+ fisic = SATA_FISC_FISWAIT4HOSTRDYEN_B1;
+ else /* For Gen-IIe - read FIS interrupt cause. */
+ fisic = ATA_INL(ch->r_mem, SATA_FISIC);
+//device_printf(dev, "FISIC %08x\n", fisic);
+ }
+ if (selfdis)
+ ch->curr_mode = MVS_EDMA_UNKNOWN;
+ ATA_OUTL(ch->r_mem, EDMA_IEC, ~iec);
+ /* Interface errors or Device error. */
+ if (iec & (0xfc1e9000 | EDMA_IE_EDEVERR)) {
+ port = -1;
+ if (ch->numpslots != 0) {
+ ccs = 0;
+ } else {
+ if (ch->quirks & MVS_Q_GENIIE)
+ ccs = EDMA_S_EIOID(ATA_INL(ch->r_mem, EDMA_S));
+ else
+ ccs = EDMA_S_EDEVQUETAG(ATA_INL(ch->r_mem, EDMA_S));
+ /* Check if error is one-PMP-port-specific, */
+ if (ch->fbs_enabled) {
+ /* Which ports were active. */
+ for (i = 0; i < 16; i++) {
+ if (ch->numrslotspd[i] == 0)
+ continue;
+ if (port == -1)
+ port = i;
+ else if (port != i) {
+ port = -2;
+ break;
+ }
+ }
+ /* If several ports were active and EDMA still enabled -
+ * other ports are probably unaffected and may continue.
+ */
+ if (port == -2 && !selfdis) {
+ uint16_t p = ATA_INL(ch->r_mem, SATA_SATAITC) >> 16;
+ port = ffs(p) - 1;
+ if (port != (fls(p) - 1))
+ port = -2;
+ }
+ }
+ }
+//device_printf(dev, "err slot %d port %d\n", ccs, port);
+ mvs_requeue_frozen(dev);
+ for (i = 0; i < MVS_MAX_SLOTS; i++) {
+ /* XXX: reqests in loading state. */
+ if (((ch->rslots >> i) & 1) == 0)
+ continue;
+ if (port >= 0 &&
+ ch->slot[i].ccb->ccb_h.target_id != port)
+ continue;
+ if (iec & EDMA_IE_EDEVERR) { /* Device error. */
+ if (port != -2) {
+ if (ch->numtslots == 0) {
+ /* Untagged operation. */
+ if (i == ccs)
+ et = MVS_ERR_TFE;
+ else
+ et = MVS_ERR_INNOCENT;
+ } else {
+ /* Tagged operation. */
+ et = MVS_ERR_NCQ;
+ }
+ } else {
+ et = MVS_ERR_TFE;
+ ch->fatalerr = 1;
+ }
+ } else if (iec & 0xfc1e9000) {
+ if (ch->numtslots == 0 && i != ccs && port != -2)
+ et = MVS_ERR_INNOCENT;
+ else
+ et = MVS_ERR_SATA;
+ } else
+ et = MVS_ERR_INVALID;
+ mvs_end_transaction(&ch->slot[i], et);
+ }
+ }
+ /* Process SDB-N. */
+ if (fisic & SATA_FISC_FISWAIT4HOSTRDYEN_B1)
+ mvs_notify_events(dev);
+ if (fisic)
+ ATA_OUTL(ch->r_mem, SATA_FISIC, ~fisic);
+ /* Process hot-plug. */
+ if ((iec & (EDMA_IE_EDEVDIS | EDMA_IE_EDEVCON)) ||
+ (serr & SATA_SE_PHY_CHANGED))
+ mvs_phy_check_events(dev, serr);
+ }
+ /* Legacy mode device interrupt. */
+ if ((arg->cause & 2) && !edma)
+ mvs_legacy_intr(dev);
+}
+
+static uint8_t
+mvs_getstatus(device_t dev, int clear)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ uint8_t status = ATA_INB(ch->r_mem, clear ? ATA_STATUS : ATA_ALTSTAT);
+
+ if (ch->fake_busy) {
+ if (status & (ATA_S_BUSY | ATA_S_DRQ | ATA_S_ERROR))
+ ch->fake_busy = 0;
+ else
+ status |= ATA_S_BUSY;
+ }
+ return (status);
+}
+
+static void
+mvs_legacy_intr(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ struct mvs_slot *slot = &ch->slot[0]; /* PIO is always in slot 0. */
+ union ccb *ccb = slot->ccb;
+ enum mvs_err_type et = MVS_ERR_NONE;
+ int port;
+ u_int length;
+ uint8_t status, ireason;
+
+ /* Clear interrupt and get status. */
+ status = mvs_getstatus(dev, 1);
+// device_printf(dev, "Legacy intr status %02x\n",
+// status);
+ if (slot->state < MVS_SLOT_RUNNING)
+ return;
+ port = ccb->ccb_h.target_id & 0x0f;
+ /* Wait a bit for late !BUSY status update. */
+ if (status & ATA_S_BUSY) {
+ DELAY(100);
+ if ((status = mvs_getstatus(dev, 1)) & ATA_S_BUSY) {
+ DELAY(1000);
+ if ((status = mvs_getstatus(dev, 1)) & ATA_S_BUSY)
+ return;
+ }
+ }
+ /* If we got an error, we are done. */
+ if (status & ATA_S_ERROR) {
+ et = MVS_ERR_TFE;
+ goto end_finished;
+ }
+ if (ccb->ccb_h.func_code == XPT_ATA_IO) { /* ATA PIO */
+ ccb->ataio.res.status = status;
+ /* Are we moving data? */
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
+ /* If data read command - get them. */
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) {
+ device_printf(dev, "timeout waiting for read DRQ\n");
+ et = MVS_ERR_TIMEOUT;
+ goto end_finished;
+ }
+ ATA_INSW_STRM(ch->r_mem, ATA_DATA,
+ (uint16_t *)(ccb->ataio.data_ptr + ch->donecount),
+ ch->transfersize / 2);
+ }
+ /* Update how far we've gotten. */
+ ch->donecount += ch->transfersize;
+ /* Do we need more? */
+ if (ccb->ataio.dxfer_len > ch->donecount) {
+ /* Set this transfer size according to HW capabilities */
+ ch->transfersize = min(ccb->ataio.dxfer_len - ch->donecount,
+ ch->curr[ccb->ccb_h.target_id].bytecount);
+ /* If data write command - put them */
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
+ if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) {
+ device_printf(dev, "timeout waiting for write DRQ\n");
+ et = MVS_ERR_TIMEOUT;
+ goto end_finished;
+ }
+ ATA_OUTSW_STRM(ch->r_mem, ATA_DATA,
+ (uint16_t *)(ccb->ataio.data_ptr + ch->donecount),
+ ch->transfersize / 2);
+ return;
+ }
+ /* If data read command, return & wait for interrupt */
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
+ return;
+ }
+ }
+ } else if (ch->basic_dma) { /* ATAPI DMA */
+ if (status & ATA_S_DWF)
+ et = MVS_ERR_TFE;
+ else if (ATA_INL(ch->r_mem, DMA_S) & DMA_S_ERR)
+ et = MVS_ERR_TFE;
+ /* Stop basic DMA. */
+ ATA_OUTL(ch->r_mem, DMA_C, 0);
+ goto end_finished;
+ } else { /* ATAPI PIO */
+ length = ATA_INB(ch->r_mem,ATA_CYL_LSB) | (ATA_INB(ch->r_mem,ATA_CYL_MSB) << 8);
+ ireason = ATA_INB(ch->r_mem,ATA_IREASON);
+//device_printf(dev, "status %02x, ireason %02x, length %d\n", status, ireason, length);
+ switch ((ireason & (ATA_I_CMD | ATA_I_IN)) |
+ (status & ATA_S_DRQ)) {
+
+ case ATAPI_P_CMDOUT:
+device_printf(dev, "ATAPI CMDOUT\n");
+ /* Return wait for interrupt */
+ return;
+
+ case ATAPI_P_WRITE:
+//device_printf(dev, "ATAPI WRITE\n");
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ device_printf(dev, "trying to write on read buffer\n");
+ et = MVS_ERR_TFE;
+ goto end_finished;
+ break;
+ }
+ ATA_OUTSW_STRM(ch->r_mem, ATA_DATA,
+ (uint16_t *)(ccb->csio.data_ptr + ch->donecount),
+ length / 2);
+ ch->donecount += length;
+ /* Set next transfer size according to HW capabilities */
+ ch->transfersize = min(ccb->csio.dxfer_len - ch->donecount,
+ ch->curr[ccb->ccb_h.target_id].bytecount);
+ /* Return wait for interrupt */
+ return;
+
+ case ATAPI_P_READ:
+//device_printf(dev, "ATAPI READ\n");
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
+ device_printf(dev, "trying to read on write buffer\n");
+ et = MVS_ERR_TFE;
+ goto end_finished;
+ }
+ ATA_INSW_STRM(ch->r_mem, ATA_DATA,
+ (uint16_t *)(ccb->csio.data_ptr + ch->donecount),
+ length / 2);
+ ch->donecount += length;
+ /* Set next transfer size according to HW capabilities */
+ ch->transfersize = min(ccb->csio.dxfer_len - ch->donecount,
+ ch->curr[ccb->ccb_h.target_id].bytecount);
+ /* Return wait for interrupt */
+ return;
+
+ case ATAPI_P_DONEDRQ:
+device_printf(dev, "ATAPI DONEDRQ\n");
+ device_printf(dev,
+ "WARNING - DONEDRQ non conformant device\n");
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ ATA_INSW_STRM(ch->r_mem, ATA_DATA,
+ (uint16_t *)(ccb->csio.data_ptr + ch->donecount),
+ length / 2);
+ ch->donecount += length;
+ }
+ else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
+ ATA_OUTSW_STRM(ch->r_mem, ATA_DATA,
+ (uint16_t *)(ccb->csio.data_ptr + ch->donecount),
+ length / 2);
+ ch->donecount += length;
+ }
+ else
+ et = MVS_ERR_TFE;
+ /* FALLTHROUGH */
+
+ case ATAPI_P_ABORT:
+ case ATAPI_P_DONE:
+//device_printf(dev, "ATAPI ABORT/DONE\n");
+ if (status & (ATA_S_ERROR | ATA_S_DWF))
+ et = MVS_ERR_TFE;
+ goto end_finished;
+
+ default:
+ device_printf(dev, "unknown transfer phase (status %02x, ireason %02x)\n",
+ status, ireason);
+ et = MVS_ERR_TFE;
+ }
+ }
+
+end_finished:
+ mvs_end_transaction(slot, et);
+}
+
+static void
+mvs_crbq_intr(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ struct mvs_crpb *crpb;
+ union ccb *ccb;
+ int in_idx, cin_idx, slot;
+ uint16_t flags;
+
+ in_idx = (ATA_INL(ch->r_mem, EDMA_RESQIP) & EDMA_RESQP_ERPQP_MASK) >>
+ EDMA_RESQP_ERPQP_SHIFT;
+ bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map,
+ BUS_DMASYNC_POSTREAD);
+ cin_idx = ch->in_idx;
+ ch->in_idx = in_idx;
+ while (in_idx != cin_idx) {
+ crpb = (struct mvs_crpb *)
+ (ch->dma.workrp + MVS_CRPB_OFFSET + (MVS_CRPB_SIZE * cin_idx));
+ slot = le16toh(crpb->id) & MVS_CRPB_TAG_MASK;
+ flags = le16toh(crpb->rspflg);
+//device_printf(dev, "CRPB %d %d %04x\n", cin_idx, slot, flags);
+ /*
+ * Handle only successfull completions here.
+ * Errors will be handled by main intr handler.
+ */
+ if (ch->numtslots != 0 || (flags & EDMA_IE_EDEVERR) == 0) {
+if ((flags >> 8) & ATA_S_ERROR)
+device_printf(dev, "ERROR STATUS CRPB %d %d %04x\n", cin_idx, slot, flags);
+ if (ch->slot[slot].state >= MVS_SLOT_RUNNING) {
+ ccb = ch->slot[slot].ccb;
+ ccb->ataio.res.status = (flags & MVS_CRPB_ATASTS_MASK) >>
+ MVS_CRPB_ATASTS_SHIFT;
+ mvs_end_transaction(&ch->slot[slot], MVS_ERR_NONE);
+ } else
+device_printf(dev, "EMPTY CRPB %d (->%d) %d %04x\n", cin_idx, in_idx, slot, flags);
+ } else
+device_printf(dev, "ERROR FLAGS CRPB %d %d %04x\n", cin_idx, slot, flags);
+
+ cin_idx = (cin_idx + 1) & (MVS_MAX_SLOTS - 1);
+ }
+ bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map,
+ BUS_DMASYNC_PREREAD);
+ if (cin_idx == ch->in_idx) {
+ ATA_OUTL(ch->r_mem, EDMA_RESQOP,
+ ch->dma.workrp_bus | (cin_idx << EDMA_RESQP_ERPQP_SHIFT));
+ }
+}
+
+/* Must be called with channel locked. */
+static int
+mvs_check_collision(device_t dev, union ccb *ccb)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+
+ if (ccb->ccb_h.func_code == XPT_ATA_IO) {
+ /* NCQ DMA */
+ if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) {
+ /* Can't mix NCQ and non-NCQ DMA commands. */
+ if (ch->numdslots != 0)
+ return (1);
+ /* Can't mix NCQ and PIO commands. */
+ if (ch->numpslots != 0)
+ return (1);
+ /* If we have no FBS */
+ if (!ch->fbs_enabled) {
+ /* Tagged command while tagged to other target is active. */
+ if (ch->numtslots != 0 &&
+ ch->taggedtarget != ccb->ccb_h.target_id)
+ return (1);
+ }
+ /* Non-NCQ DMA */
+ } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) {
+ /* Can't mix non-NCQ DMA and NCQ commands. */
+ if (ch->numtslots != 0)
+ return (1);
+ /* Can't mix non-NCQ DMA and PIO commands. */
+ if (ch->numpslots != 0)
+ return (1);
+ /* PIO */
+ } else {
+ /* Can't mix PIO with anything. */
+ if (ch->numrslots != 0)
+ return (1);
+ }
+ if (ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)) {
+ /* Atomic command while anything active. */
+ if (ch->numrslots != 0)
+ return (1);
+ }
+ } else { /* ATAPI */
+ /* ATAPI goes without EDMA, so can't mix it with anything. */
+ if (ch->numrslots != 0)
+ return (1);
+ }
+ /* We have some atomic command running. */
+ if (ch->aslots != 0)
+ return (1);
+ return (0);
+}
+
+static void
+mvs_tfd_read(device_t dev, union ccb *ccb)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ struct ata_res *res = &ccb->ataio.res;
+
+ res->status = ATA_INB(ch->r_mem, ATA_ALTSTAT);
+ res->error = ATA_INB(ch->r_mem, ATA_ERROR);
+ res->device = ATA_INB(ch->r_mem, ATA_DRIVE);
+ ATA_OUTB(ch->r_mem, ATA_CONTROL, ATA_A_HOB);
+ res->sector_count_exp = ATA_INB(ch->r_mem, ATA_COUNT);
+ res->lba_low_exp = ATA_INB(ch->r_mem, ATA_SECTOR);
+ res->lba_mid_exp = ATA_INB(ch->r_mem, ATA_CYL_LSB);
+ res->lba_high_exp = ATA_INB(ch->r_mem, ATA_CYL_MSB);
+ ATA_OUTB(ch->r_mem, ATA_CONTROL, 0);
+ res->sector_count = ATA_INB(ch->r_mem, ATA_COUNT);
+ res->lba_low = ATA_INB(ch->r_mem, ATA_SECTOR);
+ res->lba_mid = ATA_INB(ch->r_mem, ATA_CYL_LSB);
+ res->lba_high = ATA_INB(ch->r_mem, ATA_CYL_MSB);
+}
+
+static void
+mvs_tfd_write(device_t dev, union ccb *ccb)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ struct ata_cmd *cmd = &ccb->ataio.cmd;
+
+ ATA_OUTB(ch->r_mem, ATA_DRIVE, cmd->device);
+ ATA_OUTB(ch->r_mem, ATA_CONTROL, cmd->control);
+ ATA_OUTB(ch->r_mem, ATA_FEATURE, cmd->features_exp);
+ ATA_OUTB(ch->r_mem, ATA_FEATURE, cmd->features);
+ ATA_OUTB(ch->r_mem, ATA_COUNT, cmd->sector_count_exp);
+ ATA_OUTB(ch->r_mem, ATA_COUNT, cmd->sector_count);
+ ATA_OUTB(ch->r_mem, ATA_SECTOR, cmd->lba_low_exp);
+ ATA_OUTB(ch->r_mem, ATA_SECTOR, cmd->lba_low);
+ ATA_OUTB(ch->r_mem, ATA_CYL_LSB, cmd->lba_mid_exp);
+ ATA_OUTB(ch->r_mem, ATA_CYL_LSB, cmd->lba_mid);
+ ATA_OUTB(ch->r_mem, ATA_CYL_MSB, cmd->lba_high_exp);
+ ATA_OUTB(ch->r_mem, ATA_CYL_MSB, cmd->lba_high);
+ ATA_OUTB(ch->r_mem, ATA_COMMAND, cmd->command);
+}
+
+
+/* Must be called with channel locked. */
+static void
+mvs_begin_transaction(device_t dev, union ccb *ccb)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ struct mvs_slot *slot;
+ int slotn, tag;
+
+ if (ch->pm_level > 0)
+ mvs_ch_pm_wake(dev);
+ /* Softreset is a special case. */
+ if (ccb->ccb_h.func_code == XPT_ATA_IO &&
+ (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL)) {
+ mvs_softreset(dev, ccb);
+ return;
+ }
+ /* Choose empty slot. */
+ slotn = ffs(~ch->oslots) - 1;
+ if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
+ (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
+ if (ch->quirks & MVS_Q_GENIIE)
+ tag = ffs(~ch->otagspd[ccb->ccb_h.target_id]) - 1;
+ else
+ tag = slotn;
+ } else
+ tag = 0;
+ /* Occupy chosen slot. */
+ slot = &ch->slot[slotn];
+ slot->ccb = ccb;
+ slot->tag = tag;
+ /* Stop PM timer. */
+ if (ch->numrslots == 0 && ch->pm_level > 3)
+ callout_stop(&ch->pm_timer);
+ /* Update channel stats. */
+ ch->oslots |= (1 << slot->slot);
+ ch->numrslots++;
+ ch->numrslotspd[ccb->ccb_h.target_id]++;
+ if (ccb->ccb_h.func_code == XPT_ATA_IO) {
+ if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) {
+ ch->otagspd[ccb->ccb_h.target_id] |= (1 << slot->tag);
+ ch->numtslots++;
+ ch->numtslotspd[ccb->ccb_h.target_id]++;
+ ch->taggedtarget = ccb->ccb_h.target_id;
+ mvs_set_edma_mode(dev, MVS_EDMA_NCQ);
+ } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) {
+ ch->numdslots++;
+ mvs_set_edma_mode(dev, MVS_EDMA_ON);
+ } else {
+ ch->numpslots++;
+ mvs_set_edma_mode(dev, MVS_EDMA_OFF);
+ }
+ if (ccb->ataio.cmd.flags &
+ (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)) {
+ ch->aslots |= (1 << slot->slot);
+ }
+ } else {
+ uint8_t *cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+ ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes;
+ ch->numpslots++;
+ /* Use ATAPI DMA only for commands without under-/overruns. */
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE &&
+ ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA &&
+ (ch->quirks & MVS_Q_SOC) == 0 &&
+ (cdb[0] == 0x08 ||
+ cdb[0] == 0x0a ||
+ cdb[0] == 0x28 ||
+ cdb[0] == 0x2a ||
+ cdb[0] == 0x88 ||
+ cdb[0] == 0x8a ||
+ cdb[0] == 0xa8 ||
+ cdb[0] == 0xaa ||
+ cdb[0] == 0xbe)) {
+ ch->basic_dma = 1;
+ }
+ mvs_set_edma_mode(dev, MVS_EDMA_OFF);
+ }
+ if (ch->numpslots == 0 || ch->basic_dma) {
+ void *buf;
+ bus_size_t size;
+
+ slot->state = MVS_SLOT_LOADING;
+ if (ccb->ccb_h.func_code == XPT_ATA_IO) {
+ buf = ccb->ataio.data_ptr;
+ size = ccb->ataio.dxfer_len;
+ } else {
+ buf = ccb->csio.data_ptr;
+ size = ccb->csio.dxfer_len;
+ }
+ bus_dmamap_load(ch->dma.data_tag, slot->dma.data_map,
+ buf, size, mvs_dmasetprd, slot, 0);
+ } else
+ mvs_legacy_execute_transaction(slot);
+}
+
+/* Locked by busdma engine. */
+static void
+mvs_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct mvs_slot *slot = arg;
+ struct mvs_channel *ch = device_get_softc(slot->dev);
+ struct mvs_eprd *eprd;
+ int i;
+
+ if (error) {
+ device_printf(slot->dev, "DMA load error\n");
+ mvs_end_transaction(slot, MVS_ERR_INVALID);
+ return;
+ }
+ KASSERT(nsegs <= MVS_SG_ENTRIES, ("too many DMA segment entries\n"));
+ /* If there is only one segment - no need to use S/G table on Gen-IIe. */
+ if (nsegs == 1 && ch->basic_dma == 0 && (ch->quirks & MVS_Q_GENIIE)) {
+ slot->dma.addr = segs[0].ds_addr;
+ slot->dma.len = segs[0].ds_len;
+ } else {
+ slot->dma.addr = 0;
+ /* Get a piece of the workspace for this EPRD */
+ eprd = (struct mvs_eprd *)
+ (ch->dma.workrq + MVS_EPRD_OFFSET + (MVS_EPRD_SIZE * slot->slot));
+ /* Fill S/G table */
+ for (i = 0; i < nsegs; i++) {
+ eprd[i].prdbal = htole32(segs[i].ds_addr);
+ eprd[i].bytecount = htole32(segs[i].ds_len & MVS_EPRD_MASK);
+ eprd[i].prdbah = htole32((segs[i].ds_addr >> 16) >> 16);
+ }
+ eprd[i - 1].bytecount |= htole32(MVS_EPRD_EOF);
+ }
+ bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map,
+ ((slot->ccb->ccb_h.flags & CAM_DIR_IN) ?
+ BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE));
+ if (ch->basic_dma)
+ mvs_legacy_execute_transaction(slot);
+ else
+ mvs_execute_transaction(slot);
+}
+
+static void
+mvs_legacy_execute_transaction(struct mvs_slot *slot)
+{
+ device_t dev = slot->dev;
+ struct mvs_channel *ch = device_get_softc(dev);
+ bus_addr_t eprd;
+ union ccb *ccb = slot->ccb;
+ int port = ccb->ccb_h.target_id & 0x0f;
+ int timeout;
+
+ slot->state = MVS_SLOT_RUNNING;
+ ch->rslots |= (1 << slot->slot);
+ ATA_OUTB(ch->r_mem, SATA_SATAICTL, port << SATA_SATAICTL_PMPTX_SHIFT);
+ if (ccb->ccb_h.func_code == XPT_ATA_IO) {
+// device_printf(dev, "%d Legacy command %02x size %d\n",
+// port, ccb->ataio.cmd.command, ccb->ataio.dxfer_len);
+ mvs_tfd_write(dev, ccb);
+ /* Device reset doesn't interrupt. */
+ if (ccb->ataio.cmd.command == ATA_DEVICE_RESET) {
+ int timeout = 1000000;
+ do {
+ DELAY(10);
+ ccb->ataio.res.status = ATA_INB(ch->r_mem, ATA_STATUS);
+ } while (ccb->ataio.res.status & ATA_S_BUSY && timeout--);
+ mvs_legacy_intr(dev);
+ return;
+ }
+ ch->donecount = 0;
+ ch->transfersize = min(ccb->ataio.dxfer_len,
+ ch->curr[port].bytecount);
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
+ ch->fake_busy = 1;
+ /* If data write command - output the data */
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
+ if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) {
+ device_printf(dev, "timeout waiting for write DRQ\n");
+ mvs_end_transaction(slot, MVS_ERR_TIMEOUT);
+ return;
+ }
+ ATA_OUTSW_STRM(ch->r_mem, ATA_DATA,
+ (uint16_t *)(ccb->ataio.data_ptr + ch->donecount),
+ ch->transfersize / 2);
+ }
+ } else {
+// device_printf(dev, "%d ATAPI command %02x size %d dma %d\n",
+// port, ccb->csio.cdb_io.cdb_bytes[0], ccb->csio.dxfer_len,
+// ch->basic_dma);
+ ch->donecount = 0;
+ ch->transfersize = min(ccb->csio.dxfer_len,
+ ch->curr[port].bytecount);
+ /* Write ATA PACKET command. */
+ if (ch->basic_dma) {
+ ATA_OUTB(ch->r_mem, ATA_FEATURE, ATA_F_DMA);
+ ATA_OUTB(ch->r_mem, ATA_CYL_LSB, 0);
+ ATA_OUTB(ch->r_mem, ATA_CYL_MSB, 0);
+ } else {
+ ATA_OUTB(ch->r_mem, ATA_FEATURE, 0);
+ ATA_OUTB(ch->r_mem, ATA_CYL_LSB, ch->transfersize);
+ ATA_OUTB(ch->r_mem, ATA_CYL_MSB, ch->transfersize >> 8);
+ }
+ ATA_OUTB(ch->r_mem, ATA_COMMAND, ATA_PACKET_CMD);
+ ch->fake_busy = 1;
+ /* Wait for ready to write ATAPI command block */
+ if (mvs_wait(dev, 0, ATA_S_BUSY, 1000) < 0) {
+ device_printf(dev, "timeout waiting for ATAPI !BUSY\n");
+ mvs_end_transaction(slot, MVS_ERR_TIMEOUT);
+ return;
+ }
+ timeout = 5000;
+ while (timeout--) {
+ int reason = ATA_INB(ch->r_mem, ATA_IREASON);
+ int status = ATA_INB(ch->r_mem, ATA_STATUS);
+
+ if (((reason & (ATA_I_CMD | ATA_I_IN)) |
+ (status & (ATA_S_DRQ | ATA_S_BUSY))) == ATAPI_P_CMDOUT)
+ break;
+ DELAY(20);
+ }
+ if (timeout <= 0) {
+ device_printf(dev, "timeout waiting for ATAPI command ready\n");
+ mvs_end_transaction(slot, MVS_ERR_TIMEOUT);
+ return;
+ }
+ /* Write ATAPI command. */
+ ATA_OUTSW_STRM(ch->r_mem, ATA_DATA,
+ (uint16_t *)((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+ ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes),
+ ch->curr[port].atapi / 2);
+ DELAY(10);
+ if (ch->basic_dma) {
+ /* Start basic DMA. */
+ eprd = ch->dma.workrq_bus + MVS_EPRD_OFFSET +
+ (MVS_EPRD_SIZE * slot->slot);
+ ATA_OUTL(ch->r_mem, DMA_DTLBA, eprd);
+ ATA_OUTL(ch->r_mem, DMA_DTHBA, (eprd >> 16) >> 16);
+ ATA_OUTL(ch->r_mem, DMA_C, DMA_C_START |
+ (((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) ?
+ DMA_C_READ : 0));
+ } else if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
+ ch->fake_busy = 1;
+ }
+ /* Start command execution timeout */
+ callout_reset(&slot->timeout, (int)ccb->ccb_h.timeout * hz / 1000,
+ (timeout_t*)mvs_timeout, slot);
+}
+
+/* Must be called with channel locked. */
+static void
+mvs_execute_transaction(struct mvs_slot *slot)
+{
+ device_t dev = slot->dev;
+ struct mvs_channel *ch = device_get_softc(dev);
+ bus_addr_t eprd;
+ struct mvs_crqb *crqb;
+ struct mvs_crqb_gen2e *crqb2e;
+ union ccb *ccb = slot->ccb;
+ int port = ccb->ccb_h.target_id & 0x0f;
+ int i;
+
+// device_printf(dev, "%d EDMA command %02x size %d slot %d tag %d\n",
+// port, ccb->ataio.cmd.command, ccb->ataio.dxfer_len, slot->slot, slot->tag);
+ /* Get address of the prepared EPRD */
+ eprd = ch->dma.workrq_bus + MVS_EPRD_OFFSET + (MVS_EPRD_SIZE * slot->slot);
+ /* Prepare CRQB. Gen IIe uses different CRQB format. */
+ if (ch->quirks & MVS_Q_GENIIE) {
+ crqb2e = (struct mvs_crqb_gen2e *)
+ (ch->dma.workrq + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx));
+ crqb2e->ctrlflg = htole32(
+ ((ccb->ccb_h.flags & CAM_DIR_IN) ? MVS_CRQB2E_READ : 0) |
+ (slot->tag << MVS_CRQB2E_DTAG_SHIFT) |
+ (port << MVS_CRQB2E_PMP_SHIFT) |
+ (slot->slot << MVS_CRQB2E_HTAG_SHIFT));
+ /* If there is only one segment - no need to use S/G table. */
+ if (slot->dma.addr != 0) {
+ eprd = slot->dma.addr;
+ crqb2e->ctrlflg |= htole32(MVS_CRQB2E_CPRD);
+ crqb2e->drbc = slot->dma.len;
+ }
+ crqb2e->cprdbl = htole32(eprd);
+ crqb2e->cprdbh = htole32((eprd >> 16) >> 16);
+ crqb2e->cmd[0] = 0;
+ crqb2e->cmd[1] = 0;
+ crqb2e->cmd[2] = ccb->ataio.cmd.command;
+ crqb2e->cmd[3] = ccb->ataio.cmd.features;
+ crqb2e->cmd[4] = ccb->ataio.cmd.lba_low;
+ crqb2e->cmd[5] = ccb->ataio.cmd.lba_mid;
+ crqb2e->cmd[6] = ccb->ataio.cmd.lba_high;
+ crqb2e->cmd[7] = ccb->ataio.cmd.device;
+ crqb2e->cmd[8] = ccb->ataio.cmd.lba_low_exp;
+ crqb2e->cmd[9] = ccb->ataio.cmd.lba_mid_exp;
+ crqb2e->cmd[10] = ccb->ataio.cmd.lba_high_exp;
+ crqb2e->cmd[11] = ccb->ataio.cmd.features_exp;
+ if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) {
+ crqb2e->cmd[12] = slot->tag << 3;
+ crqb2e->cmd[13] = 0;
+ } else {
+ crqb2e->cmd[12] = ccb->ataio.cmd.sector_count;
+ crqb2e->cmd[13] = ccb->ataio.cmd.sector_count_exp;
+ }
+ crqb2e->cmd[14] = 0;
+ crqb2e->cmd[15] = 0;
+ } else {
+ crqb = (struct mvs_crqb *)
+ (ch->dma.workrq + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx));
+ crqb->cprdbl = htole32(eprd);
+ crqb->cprdbh = htole32((eprd >> 16) >> 16);
+ crqb->ctrlflg = htole16(
+ ((ccb->ccb_h.flags & CAM_DIR_IN) ? MVS_CRQB_READ : 0) |
+ (slot->slot << MVS_CRQB_TAG_SHIFT) |
+ (port << MVS_CRQB_PMP_SHIFT));
+ i = 0;
+ /*
+ * Controller can handle only 11 of 12 ATA registers,
+ * so we have to choose which one to skip.
+ */
+ if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) {
+ crqb->cmd[i++] = ccb->ataio.cmd.features_exp;
+ crqb->cmd[i++] = 0x11;
+ }
+ crqb->cmd[i++] = ccb->ataio.cmd.features;
+ crqb->cmd[i++] = 0x11;
+ if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) {
+ crqb->cmd[i++] = slot->tag << 3;
+ crqb->cmd[i++] = 0x12;
+ } else {
+ crqb->cmd[i++] = ccb->ataio.cmd.sector_count_exp;
+ crqb->cmd[i++] = 0x12;
+ crqb->cmd[i++] = ccb->ataio.cmd.sector_count;
+ crqb->cmd[i++] = 0x12;
+ }
+ crqb->cmd[i++] = ccb->ataio.cmd.lba_low_exp;
+ crqb->cmd[i++] = 0x13;
+ crqb->cmd[i++] = ccb->ataio.cmd.lba_low;
+ crqb->cmd[i++] = 0x13;
+ crqb->cmd[i++] = ccb->ataio.cmd.lba_mid_exp;
+ crqb->cmd[i++] = 0x14;
+ crqb->cmd[i++] = ccb->ataio.cmd.lba_mid;
+ crqb->cmd[i++] = 0x14;
+ crqb->cmd[i++] = ccb->ataio.cmd.lba_high_exp;
+ crqb->cmd[i++] = 0x15;
+ crqb->cmd[i++] = ccb->ataio.cmd.lba_high;
+ crqb->cmd[i++] = 0x15;
+ crqb->cmd[i++] = ccb->ataio.cmd.device;
+ crqb->cmd[i++] = 0x16;
+ crqb->cmd[i++] = ccb->ataio.cmd.command;
+ crqb->cmd[i++] = 0x97;
+ }
+ bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map,
+ BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map,
+ BUS_DMASYNC_PREREAD);
+ slot->state = MVS_SLOT_RUNNING;
+ ch->rslots |= (1 << slot->slot);
+ /* Issue command to the controller. */
+ ch->out_idx = (ch->out_idx + 1) & (MVS_MAX_SLOTS - 1);
+ ATA_OUTL(ch->r_mem, EDMA_REQQIP,
+ ch->dma.workrq_bus + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx));
+ /* Start command execution timeout */
+ callout_reset(&slot->timeout, (int)ccb->ccb_h.timeout * hz / 1000,
+ (timeout_t*)mvs_timeout, slot);
+ return;
+}
+
+/* Must be called with channel locked. */
+static void
+mvs_process_timeout(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ int i;
+
+ mtx_assert(&ch->mtx, MA_OWNED);
+ /* Handle the rest of commands. */
+ for (i = 0; i < MVS_MAX_SLOTS; i++) {
+ /* Do we have a running request on slot? */
+ if (ch->slot[i].state < MVS_SLOT_RUNNING)
+ continue;
+ mvs_end_transaction(&ch->slot[i], MVS_ERR_TIMEOUT);
+ }
+}
+
+/* Must be called with channel locked. */
+static void
+mvs_rearm_timeout(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ int i;
+
+ mtx_assert(&ch->mtx, MA_OWNED);
+ for (i = 0; i < MVS_MAX_SLOTS; i++) {
+ struct mvs_slot *slot = &ch->slot[i];
+
+ /* Do we have a running request on slot? */
+ if (slot->state < MVS_SLOT_RUNNING)
+ continue;
+ if ((ch->toslots & (1 << i)) == 0)
+ continue;
+ callout_reset(&slot->timeout,
+ (int)slot->ccb->ccb_h.timeout * hz / 2000,
+ (timeout_t*)mvs_timeout, slot);
+ }
+}
+
+/* Locked by callout mechanism. */
+static void
+mvs_timeout(struct mvs_slot *slot)
+{
+ device_t dev = slot->dev;
+ struct mvs_channel *ch = device_get_softc(dev);
+
+ /* Check for stale timeout. */
+ if (slot->state < MVS_SLOT_RUNNING)
+ return;
+ device_printf(dev, "Timeout on slot %d\n", slot->slot);
+ device_printf(dev, "iec %08x sstat %08x serr %08x edma_s %08x "
+ "dma_c %08x dma_s %08x rs %08x status %02x\n",
+ ATA_INL(ch->r_mem, EDMA_IEC),
+ ATA_INL(ch->r_mem, SATA_SS), ATA_INL(ch->r_mem, SATA_SE),
+ ATA_INL(ch->r_mem, EDMA_S), ATA_INL(ch->r_mem, DMA_C),
+ ATA_INL(ch->r_mem, DMA_S), ch->rslots,
+ ATA_INB(ch->r_mem, ATA_ALTSTAT));
+ /* Handle frozen command. */
+ mvs_requeue_frozen(dev);
+ /* We wait for other commands timeout and pray. */
+ if (ch->toslots == 0)
+ xpt_freeze_simq(ch->sim, 1);
+ ch->toslots |= (1 << slot->slot);
+ if ((ch->rslots & ~ch->toslots) == 0)
+ mvs_process_timeout(dev);
+ else
+ device_printf(dev, " ... waiting for slots %08x\n",
+ ch->rslots & ~ch->toslots);
+}
+
+/* Must be called with channel locked. */
+static void
+mvs_end_transaction(struct mvs_slot *slot, enum mvs_err_type et)
+{
+ device_t dev = slot->dev;
+ struct mvs_channel *ch = device_get_softc(dev);
+ union ccb *ccb = slot->ccb;
+
+//device_printf(dev, "cmd done status %d\n", et);
+ bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map,
+ BUS_DMASYNC_POSTWRITE);
+ /* Read result registers to the result struct
+ * May be incorrect if several commands finished same time,
+ * so read only when sure or have to.
+ */
+ if (ccb->ccb_h.func_code == XPT_ATA_IO) {
+ struct ata_res *res = &ccb->ataio.res;
+
+ if ((et == MVS_ERR_TFE) ||
+ (ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT)) {
+ mvs_tfd_read(dev, ccb);
+ } else
+ bzero(res, sizeof(*res));
+ }
+ if (ch->numpslots == 0 || ch->basic_dma) {
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
+ bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map,
+ (ccb->ccb_h.flags & CAM_DIR_IN) ?
+ BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(ch->dma.data_tag, slot->dma.data_map);
+ }
+ }
+ if (et != MVS_ERR_NONE)
+ ch->eslots |= (1 << slot->slot);
+ /* In case of error, freeze device for proper recovery. */
+ if ((et != MVS_ERR_NONE) && (!ch->readlog) &&
+ !(ccb->ccb_h.status & CAM_DEV_QFRZN)) {
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status |= CAM_DEV_QFRZN;
+ }
+ /* Set proper result status. */
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ switch (et) {
+ case MVS_ERR_NONE:
+ ccb->ccb_h.status |= CAM_REQ_CMP;
+ if (ccb->ccb_h.func_code == XPT_SCSI_IO)
+ ccb->csio.scsi_status = SCSI_STATUS_OK;
+ break;
+ case MVS_ERR_INVALID:
+ ch->fatalerr = 1;
+ ccb->ccb_h.status |= CAM_REQ_INVALID;
+ break;
+ case MVS_ERR_INNOCENT:
+ ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+ break;
+ case MVS_ERR_TFE:
+ case MVS_ERR_NCQ:
+ if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
+ ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
+ ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+ } else {
+ ccb->ccb_h.status |= CAM_ATA_STATUS_ERROR;
+ }
+ break;
+ case MVS_ERR_SATA:
+ ch->fatalerr = 1;
+ if (!ch->readlog) {
+ xpt_freeze_simq(ch->sim, 1);
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
+ }
+ ccb->ccb_h.status |= CAM_UNCOR_PARITY;
+ break;
+ case MVS_ERR_TIMEOUT:
+ if (!ch->readlog) {
+ xpt_freeze_simq(ch->sim, 1);
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
+ }
+ ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
+ break;
+ default:
+ ch->fatalerr = 1;
+ ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
+ }
+ /* Free slot. */
+ ch->oslots &= ~(1 << slot->slot);
+ ch->rslots &= ~(1 << slot->slot);
+ ch->aslots &= ~(1 << slot->slot);
+ if (et != MVS_ERR_TIMEOUT) {
+ if (ch->toslots == (1 << slot->slot))
+ xpt_release_simq(ch->sim, TRUE);
+ ch->toslots &= ~(1 << slot->slot);
+ }
+ slot->state = MVS_SLOT_EMPTY;
+ slot->ccb = NULL;
+ /* Update channel stats. */
+ ch->numrslots--;
+ ch->numrslotspd[ccb->ccb_h.target_id]--;
+ if (ccb->ccb_h.func_code == XPT_ATA_IO) {
+ if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) {
+ ch->otagspd[ccb->ccb_h.target_id] &= ~(1 << slot->tag);
+ ch->numtslots--;
+ ch->numtslotspd[ccb->ccb_h.target_id]--;
+ } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) {
+ ch->numdslots--;
+ } else {
+ ch->numpslots--;
+ }
+ } else {
+ ch->numpslots--;
+ ch->basic_dma = 0;
+ }
+ /* If it was our READ LOG command - process it. */
+ if (ch->readlog) {
+ mvs_process_read_log(dev, ccb);
+ /* If it was NCQ command error, put result on hold. */
+ } else if (et == MVS_ERR_NCQ) {
+ ch->hold[slot->slot] = ccb;
+ ch->holdtag[slot->slot] = slot->tag;
+ ch->numhslots++;
+ } else
+ xpt_done(ccb);
+ /* Unfreeze frozen command. */
+ if (ch->frozen && !mvs_check_collision(dev, ch->frozen)) {
+ union ccb *fccb = ch->frozen;
+ ch->frozen = NULL;
+ mvs_begin_transaction(dev, fccb);
+ xpt_release_simq(ch->sim, TRUE);
+ }
+ /* If we have no other active commands, ... */
+ if (ch->rslots == 0) {
+ /* if there was fatal error - reset port. */
+ if (ch->toslots != 0 || ch->fatalerr) {
+ mvs_reset(dev);
+ } else {
+ /* if we have slots in error, we can reinit port. */
+ if (ch->eslots != 0) {
+ mvs_set_edma_mode(dev, MVS_EDMA_OFF);
+ ch->eslots = 0;
+ }
+ /* if there commands on hold, we can do READ LOG. */
+ if (!ch->readlog && ch->numhslots)
+ mvs_issue_read_log(dev);
+ }
+ /* If all the rest of commands are in timeout - give them chance. */
+ } else if ((ch->rslots & ~ch->toslots) == 0 &&
+ et != MVS_ERR_TIMEOUT)
+ mvs_rearm_timeout(dev);
+ /* Start PM timer. */
+ if (ch->numrslots == 0 && ch->pm_level > 3 &&
+ (ch->curr[ch->pm_present ? 15 : 0].caps & CTS_SATA_CAPS_D_PMREQ)) {
+ callout_schedule(&ch->pm_timer,
+ (ch->pm_level == 4) ? hz / 1000 : hz / 8);
+ }
+}
+
+static void
+mvs_issue_read_log(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ union ccb *ccb;
+ struct ccb_ataio *ataio;
+ int i;
+
+ ch->readlog = 1;
+ /* Find some holden command. */
+ for (i = 0; i < MVS_MAX_SLOTS; i++) {
+ if (ch->hold[i])
+ break;
+ }
+ ccb = xpt_alloc_ccb_nowait();
+ if (ccb == NULL) {
+ device_printf(dev, "Unable allocate READ LOG command");
+ return; /* XXX */
+ }
+ ccb->ccb_h = ch->hold[i]->ccb_h; /* Reuse old header. */
+ ccb->ccb_h.func_code = XPT_ATA_IO;
+ ccb->ccb_h.flags = CAM_DIR_IN;
+ ccb->ccb_h.timeout = 1000; /* 1s should be enough. */
+ ataio = &ccb->ataio;
+ ataio->data_ptr = malloc(512, M_MVS, M_NOWAIT);
+ if (ataio->data_ptr == NULL) {
+ device_printf(dev, "Unable allocate memory for READ LOG command");
+ return; /* XXX */
+ }
+ ataio->dxfer_len = 512;
+ bzero(&ataio->cmd, sizeof(ataio->cmd));
+ ataio->cmd.flags = CAM_ATAIO_48BIT;
+ ataio->cmd.command = 0x2F; /* READ LOG EXT */
+ ataio->cmd.sector_count = 1;
+ ataio->cmd.sector_count_exp = 0;
+ ataio->cmd.lba_low = 0x10;
+ ataio->cmd.lba_mid = 0;
+ ataio->cmd.lba_mid_exp = 0;
+ /* Freeze SIM while doing READ LOG EXT. */
+ xpt_freeze_simq(ch->sim, 1);
+ mvs_begin_transaction(dev, ccb);
+}
+
+static void
+mvs_process_read_log(device_t dev, union ccb *ccb)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ uint8_t *data;
+ struct ata_res *res;
+ int i;
+
+ ch->readlog = 0;
+
+ data = ccb->ataio.data_ptr;
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
+ (data[0] & 0x80) == 0) {
+ for (i = 0; i < MVS_MAX_SLOTS; i++) {
+ if (!ch->hold[i])
+ continue;
+ if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id)
+ continue;
+ if ((data[0] & 0x1F) == ch->holdtag[i]) {
+ res = &ch->hold[i]->ataio.res;
+ res->status = data[2];
+ res->error = data[3];
+ res->lba_low = data[4];
+ res->lba_mid = data[5];
+ res->lba_high = data[6];
+ res->device = data[7];
+ res->lba_low_exp = data[8];
+ res->lba_mid_exp = data[9];
+ res->lba_high_exp = data[10];
+ res->sector_count = data[12];
+ res->sector_count_exp = data[13];
+ } else {
+ ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK;
+ ch->hold[i]->ccb_h.status |= CAM_REQUEUE_REQ;
+ }
+ xpt_done(ch->hold[i]);
+ ch->hold[i] = NULL;
+ ch->numhslots--;
+ }
+ } else {
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
+ device_printf(dev, "Error while READ LOG EXT\n");
+ else if ((data[0] & 0x80) == 0) {
+ device_printf(dev, "Non-queued command error in READ LOG EXT\n");
+ }
+ for (i = 0; i < MVS_MAX_SLOTS; i++) {
+ if (!ch->hold[i])
+ continue;
+ if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id)
+ continue;
+ xpt_done(ch->hold[i]);
+ ch->hold[i] = NULL;
+ ch->numhslots--;
+ }
+ }
+ free(ccb->ataio.data_ptr, M_MVS);
+ xpt_free_ccb(ccb);
+ xpt_release_simq(ch->sim, TRUE);
+}
+
+static int
+mvs_wait(device_t dev, u_int s, u_int c, int t)
+{
+ int timeout = 0;
+ uint8_t st;
+
+ while (((st = mvs_getstatus(dev, 0)) & (s | c)) != s) {
+ DELAY(1000);
+ if (timeout++ > t) {
+ device_printf(dev, "Wait status %02x\n", st);
+ return (-1);
+ }
+ }
+ return (timeout);
+}
+
+static void
+mvs_requeue_frozen(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ union ccb *fccb = ch->frozen;
+
+ if (fccb) {
+ ch->frozen = NULL;
+ fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
+ if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) {
+ xpt_freeze_devq(fccb->ccb_h.path, 1);
+ fccb->ccb_h.status |= CAM_DEV_QFRZN;
+ }
+ xpt_done(fccb);
+ }
+}
+
+static void
+mvs_reset(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ int i;
+
+ xpt_freeze_simq(ch->sim, 1);
+ if (bootverbose)
+ device_printf(dev, "MVS reset...\n");
+ /* Requeue freezed command. */
+ mvs_requeue_frozen(dev);
+ /* Kill the engine and requeue all running commands. */
+ mvs_set_edma_mode(dev, MVS_EDMA_OFF);
+ ATA_OUTL(ch->r_mem, DMA_C, 0);
+ for (i = 0; i < MVS_MAX_SLOTS; i++) {
+ /* Do we have a running request on slot? */
+ if (ch->slot[i].state < MVS_SLOT_RUNNING)
+ continue;
+ /* XXX; Commands in loading state. */
+ mvs_end_transaction(&ch->slot[i], MVS_ERR_INNOCENT);
+ }
+ for (i = 0; i < MVS_MAX_SLOTS; i++) {
+ if (!ch->hold[i])
+ continue;
+ xpt_done(ch->hold[i]);
+ ch->hold[i] = NULL;
+ ch->numhslots--;
+ }
+ if (ch->toslots != 0)
+ xpt_release_simq(ch->sim, TRUE);
+ ch->eslots = 0;
+ ch->toslots = 0;
+ ch->fatalerr = 0;
+ /* Tell the XPT about the event */
+ xpt_async(AC_BUS_RESET, ch->path, NULL);
+ ATA_OUTL(ch->r_mem, EDMA_IEM, 0);
+ ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EATARST);
+ DELAY(25);
+ ATA_OUTL(ch->r_mem, EDMA_CMD, 0);
+ /* Reset and reconnect PHY, */
+ if (!mvs_sata_phy_reset(dev)) {
+ if (bootverbose)
+ device_printf(dev,
+ "MVS reset done: phy reset found no device\n");
+ ch->devices = 0;
+ ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff);
+ ATA_OUTL(ch->r_mem, EDMA_IEC, 0);
+ ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT);
+ xpt_release_simq(ch->sim, TRUE);
+ return;
+ }
+ /* Wait for clearing busy status. */
+ if ((i = mvs_wait(dev, 0, ATA_S_BUSY | ATA_S_DRQ, 15000)) < 0)
+ device_printf(dev, "device is not ready\n");
+ else if (bootverbose)
+ device_printf(dev, "ready wait time=%dms\n", i);
+ ch->devices = 1;
+ ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff);
+ ATA_OUTL(ch->r_mem, EDMA_IEC, 0);
+ ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT);
+ if (bootverbose)
+ device_printf(dev, "MVS reset done: device found\n");
+ xpt_release_simq(ch->sim, TRUE);
+}
+
+static void
+mvs_softreset(device_t dev, union ccb *ccb)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ int port = ccb->ccb_h.target_id & 0x0f;
+ int i;
+
+ mvs_set_edma_mode(dev, MVS_EDMA_OFF);
+ ATA_OUTB(ch->r_mem, SATA_SATAICTL, port << SATA_SATAICTL_PMPTX_SHIFT);
+ ATA_OUTB(ch->r_mem, ATA_CONTROL, ATA_A_RESET);
+ DELAY(10000);
+ ATA_OUTB(ch->r_mem, ATA_CONTROL, 0);
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ /* Wait for clearing busy status. */
+ if ((i = mvs_wait(dev, 0, ATA_S_BUSY | ATA_S_DRQ, ccb->ccb_h.timeout)) < 0) {
+ ccb->ccb_h.status |= CAM_CMD_TIMEOUT;
+ } else {
+ ccb->ccb_h.status |= CAM_REQ_CMP;
+ }
+ mvs_tfd_read(dev, ccb);
+ xpt_done(ccb);
+}
+
+static int
+mvs_sata_connect(struct mvs_channel *ch)
+{
+ u_int32_t status;
+ int timeout;
+
+ /* Wait up to 100ms for "connect well" */
+ for (timeout = 0; timeout < 100 ; timeout++) {
+ status = ATA_INL(ch->r_mem, SATA_SS);
+ if (((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_ONLINE) &&
+ ((status & SATA_SS_SPD_MASK) != SATA_SS_SPD_NO_SPEED) &&
+ ((status & SATA_SS_IPM_MASK) == SATA_SS_IPM_ACTIVE))
+ break;
+ if ((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_OFFLINE) {
+ if (bootverbose) {
+ device_printf(ch->dev, "SATA offline status=%08x\n",
+ status);
+ }
+ return (0);
+ }
+ DELAY(1000);
+ }
+ if (timeout >= 100) {
+ if (bootverbose) {
+ device_printf(ch->dev, "SATA connect timeout status=%08x\n",
+ status);
+ }
+ return (0);
+ }
+ if (bootverbose) {
+ device_printf(ch->dev, "SATA connect time=%dms status=%08x\n",
+ timeout, status);
+ }
+ /* Clear SATA error register */
+ ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff);
+ return (1);
+}
+
+static int
+mvs_sata_phy_reset(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ int sata_rev;
+ uint32_t val;
+
+ sata_rev = ch->user[ch->pm_present ? 15 : 0].revision;
+ if (sata_rev == 1)
+ val = SATA_SC_SPD_SPEED_GEN1;
+ else if (sata_rev == 2)
+ val = SATA_SC_SPD_SPEED_GEN2;
+ else if (sata_rev == 3)
+ val = SATA_SC_SPD_SPEED_GEN3;
+ else
+ val = 0;
+ ATA_OUTL(ch->r_mem, SATA_SC,
+ SATA_SC_DET_RESET | val |
+ SATA_SC_IPM_DIS_PARTIAL | SATA_SC_IPM_DIS_SLUMBER);
+ DELAY(5000);
+ ATA_OUTL(ch->r_mem, SATA_SC,
+ SATA_SC_DET_IDLE | val | ((ch->pm_level > 0) ? 0 :
+ (SATA_SC_IPM_DIS_PARTIAL | SATA_SC_IPM_DIS_SLUMBER)));
+ DELAY(5000);
+ if (!mvs_sata_connect(ch)) {
+ if (ch->pm_level > 0)
+ ATA_OUTL(ch->r_mem, SATA_SC, SATA_SC_DET_DISABLE);
+ return (0);
+ }
+ return (1);
+}
+
+static int
+mvs_check_ids(device_t dev, union ccb *ccb)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+
+ if (ccb->ccb_h.target_id > ((ch->quirks & MVS_Q_GENI) ? 0 : 15)) {
+ ccb->ccb_h.status = CAM_TID_INVALID;
+ xpt_done(ccb);
+ return (-1);
+ }
+ if (ccb->ccb_h.target_lun != 0) {
+ ccb->ccb_h.status = CAM_LUN_INVALID;
+ xpt_done(ccb);
+ return (-1);
+ }
+ return (0);
+}
+
+static void
+mvsaction(struct cam_sim *sim, union ccb *ccb)
+{
+ device_t dev;
+ struct mvs_channel *ch;
+
+ CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mvsaction func_code=%x\n",
+ ccb->ccb_h.func_code));
+
+ ch = (struct mvs_channel *)cam_sim_softc(sim);
+ dev = ch->dev;
+ switch (ccb->ccb_h.func_code) {
+ /* Common cases first */
+ case XPT_ATA_IO: /* Execute the requested I/O operation */
+ case XPT_SCSI_IO:
+ if (mvs_check_ids(dev, ccb))
+ return;
+ if (ch->devices == 0 ||
+ (ch->pm_present == 0 &&
+ ccb->ccb_h.target_id > 0 && ccb->ccb_h.target_id < 15)) {
+ ccb->ccb_h.status = CAM_SEL_TIMEOUT;
+ break;
+ }
+ /* Check for command collision. */
+ if (mvs_check_collision(dev, ccb)) {
+ /* Freeze command. */
+ ch->frozen = ccb;
+ /* We have only one frozen slot, so freeze simq also. */
+ xpt_freeze_simq(ch->sim, 1);
+ return;
+ }
+ mvs_begin_transaction(dev, ccb);
+ return;
+ case XPT_EN_LUN: /* Enable LUN as a target */
+ case XPT_TARGET_IO: /* Execute target I/O request */
+ case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
+ case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/
+ case XPT_ABORT: /* Abort the specified CCB */
+ /* XXX Implement */
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ break;
+ case XPT_SET_TRAN_SETTINGS:
+ {
+ struct ccb_trans_settings *cts = &ccb->cts;
+ struct mvs_device *d;
+
+ if (mvs_check_ids(dev, ccb))
+ return;
+ if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
+ d = &ch->curr[ccb->ccb_h.target_id];
+ else
+ d = &ch->user[ccb->ccb_h.target_id];
+ if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
+ d->revision = cts->xport_specific.sata.revision;
+ if (cts->xport_specific.sata.valid & CTS_SATA_VALID_MODE)
+ d->mode = cts->xport_specific.sata.mode;
+ if (cts->xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) {
+ d->bytecount = min((ch->quirks & MVS_Q_GENIIE) ? 8192 : 2048,
+ cts->xport_specific.sata.bytecount);
+ }
+ if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS)
+ d->tags = min(MVS_MAX_SLOTS, cts->xport_specific.sata.tags);
+ if (cts->xport_specific.sata.valid & CTS_SATA_VALID_PM)
+ ch->pm_present = cts->xport_specific.sata.pm_present;
+ if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI)
+ d->atapi = cts->xport_specific.sata.atapi;
+ if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
+ d->caps = cts->xport_specific.sata.caps;
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ break;
+ }
+ case XPT_GET_TRAN_SETTINGS:
+ /* Get default/user set transfer settings for the target */
+ {
+ struct ccb_trans_settings *cts = &ccb->cts;
+ struct mvs_device *d;
+ uint32_t status;
+
+ if (mvs_check_ids(dev, ccb))
+ return;
+ if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
+ d = &ch->curr[ccb->ccb_h.target_id];
+ else
+ d = &ch->user[ccb->ccb_h.target_id];
+ cts->protocol = PROTO_ATA;
+ cts->protocol_version = PROTO_VERSION_UNSPECIFIED;
+ cts->transport = XPORT_SATA;
+ cts->transport_version = XPORT_VERSION_UNSPECIFIED;
+ cts->proto_specific.valid = 0;
+ cts->xport_specific.sata.valid = 0;
+ if (cts->type == CTS_TYPE_CURRENT_SETTINGS &&
+ (ccb->ccb_h.target_id == 15 ||
+ (ccb->ccb_h.target_id == 0 && !ch->pm_present))) {
+ status = ATA_INL(ch->r_mem, SATA_SS) & SATA_SS_SPD_MASK;
+ if (status & 0x0f0) {
+ cts->xport_specific.sata.revision =
+ (status & 0x0f0) >> 4;
+ cts->xport_specific.sata.valid |=
+ CTS_SATA_VALID_REVISION;
+ }
+ cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
+// if (ch->pm_level)
+// cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
+ cts->xport_specific.sata.caps &=
+ ch->user[ccb->ccb_h.target_id].caps;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
+ } else {
+ cts->xport_specific.sata.revision = d->revision;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
+ cts->xport_specific.sata.caps = d->caps;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
+ }
+ cts->xport_specific.sata.mode = d->mode;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE;
+ cts->xport_specific.sata.bytecount = d->bytecount;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_BYTECOUNT;
+ cts->xport_specific.sata.pm_present = ch->pm_present;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_PM;
+ cts->xport_specific.sata.tags = d->tags;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_TAGS;
+ cts->xport_specific.sata.atapi = d->atapi;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI;
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ break;
+ }
+ case XPT_RESET_BUS: /* Reset the specified SCSI bus */
+ case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
+ mvs_reset(dev);
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ break;
+ case XPT_TERM_IO: /* Terminate the I/O process */
+ /* XXX Implement */
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ break;
+ case XPT_PATH_INQ: /* Path routing inquiry */
+ {
+ struct ccb_pathinq *cpi = &ccb->cpi;
+
+ cpi->version_num = 1; /* XXX??? */
+ cpi->hba_inquiry = PI_SDTR_ABLE;
+ if (!(ch->quirks & MVS_Q_GENI)) {
+ cpi->hba_inquiry |= PI_SATAPM;
+ /* Gen-II is extremely slow with NCQ on PMP. */
+ if ((ch->quirks & MVS_Q_GENIIE) || ch->pm_present == 0)
+ cpi->hba_inquiry |= PI_TAG_ABLE;
+ }
+ cpi->target_sprt = 0;
+ cpi->hba_misc = PIM_SEQSCAN;
+ cpi->hba_eng_cnt = 0;
+ if (!(ch->quirks & MVS_Q_GENI))
+ cpi->max_target = 15;
+ else
+ cpi->max_target = 0;
+ cpi->max_lun = 0;
+ cpi->initiator_id = 0;
+ cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 150000;
+ strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+ strncpy(cpi->hba_vid, "Marvell", HBA_IDLEN);
+ strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+ cpi->unit_number = cam_sim_unit(sim);
+ cpi->transport = XPORT_SATA;
+ cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
+ cpi->protocol = PROTO_ATA;
+ cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
+ cpi->maxio = MAXPHYS;
+ cpi->ccb_h.status = CAM_REQ_CMP;
+ break;
+ }
+ default:
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ break;
+ }
+ xpt_done(ccb);
+}
+
+static void
+mvspoll(struct cam_sim *sim)
+{
+ struct mvs_channel *ch = (struct mvs_channel *)cam_sim_softc(sim);
+ struct mvs_intr_arg arg;
+
+ arg.arg = ch->dev;
+ arg.cause = 2; /* XXX */
+ mvs_ch_intr(arg.arg);
+}
+
diff --git a/sys/dev/mvs/mvs.h b/sys/dev/mvs/mvs.h
new file mode 100644
index 0000000..9ec4e3d
--- /dev/null
+++ b/sys/dev/mvs/mvs.h
@@ -0,0 +1,650 @@
+/*-
+ * Copyright (c) 2010 Alexander Motin <mav@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,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "mvs_if.h"
+
+/* Chip registers */
+#define CHIP_PCIEIC 0x1900 /* PCIe Interrupt Cause */
+#define CHIP_PCIEIM 0x1910 /* PCIe Interrupt Mask */
+#define CHIP_PCIIC 0x1d58 /* PCI Interrupt Cause */
+#define CHIP_PCIIM 0x1d5c /* PCI Interrupt Mask */
+#define CHIP_MIC 0x1d60 /* Main Interrupt Cause */
+#define CHIP_MIM 0x1d64 /* Main Interrupt Mask */
+#define CHIP_SOC_MIC 0x20 /* SoC Main Interrupt Cause */
+#define CHIP_SOC_MIM 0x24 /* SoC Main Interrupt Mask */
+#define IC_ERR_IRQ (1 << 0) /* shift by (2 * port #) */
+#define IC_DONE_IRQ (1 << 1) /* shift by (2 * port #) */
+#define IC_HC0 0x000001ff /* bits 0-8 = HC0 */
+#define IC_HC_SHIFT 9 /* HC1 shift */
+#define IC_HC1 (IC_HC0 << IC_HC_SHIFT) /* 9-17 = HC1 */
+#define IC_ERR_HC0 0x00000055 /* HC0 ERR_IRQ */
+#define IC_DONE_HC0 0x000000aa /* HC0 DONE_IRQ */
+#define IC_ERR_HC1 (IC_ERR_HC0 << IC_HC_SHIFT) /* HC1 ERR_IRQ */
+#define IC_DONE_HC1 (IC_DONE_HC0 << IC_HC_SHIFT) /* HC1 DONE_IRQ */
+#define IC_HC0_COAL_DONE (1 << 8) /* HC0 IRQ coalescing */
+#define IC_HC1_COAL_DONE (1 << 17) /* HC1 IRQ coalescing */
+#define IC_PCI_ERR (1 << 18)
+#define IC_TRAN_COAL_LO_DONE (1 << 19) /* transaction coalescing */
+#define IC_TRAN_COAL_HI_DONE (1 << 20) /* transaction coalescing */
+#define IC_ALL_PORTS_COAL_DONE (1 << 21) /* GEN_II(E) IRQ coalescing */
+#define IC_GPIO_INT (1 << 22)
+#define IC_SELF_INT (1 << 23)
+#define IC_TWSI_INT (1 << 24)
+#define IC_MAIN_RSVD (0xfe000000) /* bits 31-25 */
+#define IC_MAIN_RSVD_5 (0xfff10000) /* bits 31-19 */
+#define IC_MAIN_RSVD_SOC (0xfffffec0) /* bits 31-9, 7-6 */
+
+#define CHIP_SOC_LED 0x2C /* SoC LED Configuration */
+
+/* Chip CCC registers */
+#define CHIP_ICC 0x18008
+#define CHIP_ICC_ALL_PORTS (1 << 4) /* all ports irq event */
+#define CHIP_ICT 0x180cc
+#define CHIP_ITT 0x180d0
+#define CHIP_TRAN_COAL_CAUSE_LO 0x18088
+#define CHIP_TRAN_COAL_CAUSE_HI 0x1808c
+
+/* Host Controller registers */
+#define HC_SIZE 0x10000
+#define HC_OFFSET 0x20000
+#define HC_BASE(hc) ((hc) * HC_SIZE + HC_OFFSET)
+
+#define HC_CFG 0x0 /* Configuration */
+#define HC_CFG_TIMEOUT_MASK (0xff << 0)
+#define HC_CFG_NODMABS (1 << 8)
+#define HC_CFG_NOEDMABS (1 << 9)
+#define HC_CFG_NOPRDBS (1 << 10)
+#define HC_CFG_TIMEOUTEN (1 << 16) /* Timer Enable */
+#define HC_CFG_COALDIS(p) (1 << ((p) + 24))/* Coalescing Disable*/
+#define HC_RQOP 0x4 /* Request Queue Out-Pointer */
+#define HC_RQIP 0x8 /* Response Queue In-Pointer */
+#define HC_ICT 0xc /* Interrupt Coalescing Threshold */
+#define HC_ICT_SAICOALT_MASK 0x000000ff
+#define HC_ITT 0x10 /* Interrupt Time Threshold */
+#define HC_ITT_SAITMTH_MASK 0x00ffffff
+#define HC_IC 0x14 /* Interrupt Cause */
+#define HC_IC_DONE(p) (1 << (p)) /* SaCrpb/DMA Done */
+#define HC_IC_COAL (1 << 4) /* Intr Coalescing */
+#define HC_IC_DEV(p) (1 << ((p) + 8)) /* Device Intr */
+
+/* Port registers */
+#define PORT_SIZE 0x2000
+#define PORT_OFFSET 0x2000
+#define PORT_BASE(hc) ((hc) * PORT_SIZE + PORT_OFFSET)
+
+#define EDMA_CFG 0x0 /* Configuration */
+#define EDMA_CFG_RESERVED (0x1f << 0) /* Queue len ? */
+#define EDMA_CFG_ESATANATVCMDQUE (1 << 5)
+#define EDMA_CFG_ERDBSZ (1 << 8)
+#define EDMA_CFG_EQUE (1 << 9)
+#define EDMA_CFG_ERDBSZEXT (1 << 11)
+#define EDMA_CFG_RESERVED2 (1 << 12)
+#define EDMA_CFG_EWRBUFFERLEN (1 << 13)
+#define EDMA_CFG_EDEVERR (1 << 14)
+#define EDMA_CFG_EEDMAFBS (1 << 16)
+#define EDMA_CFG_ECUTTHROUGHEN (1 << 17)
+#define EDMA_CFG_EEARLYCOMPLETIONEN (1 << 18)
+#define EDMA_CFG_EEDMAQUELEN (1 << 19)
+#define EDMA_CFG_EHOSTQUEUECACHEEN (1 << 22)
+#define EDMA_CFG_EMASKRXPM (1 << 23)
+#define EDMA_CFG_RESUMEDIS (1 << 24)
+#define EDMA_CFG_EDMAFBS (1 << 26)
+#define EDMA_T 0x4 /* Timer */
+#define EDMA_IEC 0x8 /* Interrupt Error Cause */
+#define EDMA_IEM 0xc /* Interrupt Error Mask */
+#define EDMA_IE_EDEVERR (1 << 2) /* EDMA Device Error */
+#define EDMA_IE_EDEVDIS (1 << 3) /* EDMA Dev Disconn */
+#define EDMA_IE_EDEVCON (1 << 4) /* EDMA Dev Conn */
+#define EDMA_IE_SERRINT (1 << 5)
+#define EDMA_IE_ESELFDIS (1 << 7) /* EDMA Self Disable */
+#define EDMA_IE_ETRANSINT (1 << 8) /* Transport Layer */
+#define EDMA_IE_EIORDYERR (1 << 12) /* EDMA IORdy Error */
+#define EDMA_IE_LINKXERR_SATACRC (1 << 0) /* SATA CRC error */
+#define EDMA_IE_LINKXERR_INTERNALFIFO (1 << 1) /* internal FIFO err */
+#define EDMA_IE_LINKXERR_LINKLAYERRESET (1 << 2)
+ /* Link Layer is reset by the reception of SYNC primitive from device */
+#define EDMA_IE_LINKXERR_OTHERERRORS (1 << 3)
+ /*
+ * Link state errors, coding errors, or running disparity errors occur
+ * during FIS reception.
+ */
+#define EDMA_IE_LINKTXERR_FISTXABORTED (1 << 4) /* FIS Tx is aborted */
+#define EDMA_IE_LINKCTLRXERR(x) ((x) << 13) /* Link Ctrl Recv Err */
+#define EDMA_IE_LINKDATARXERR(x) ((x) << 17) /* Link Data Recv Err */
+#define EDMA_IE_LINKCTLTXERR(x) ((x) << 21) /* Link Ctrl Tx Error */
+#define EDMA_IE_LINKDATATXERR(x) ((x) << 26) /* Link Data Tx Error */
+#define EDMA_IE_TRANSPROTERR (1 << 31) /* Transport Proto E */
+#define EDMA_IE_TRANSIENT (EDMA_IE_LINKCTLRXERR(0x0b) | \
+ EDMA_IE_LINKCTLTXERR(0x1f))
+ /* Non-fatal Errors */
+#define EDMA_REQQBAH 0x10 /* Request Queue Base Address High */
+#define EDMA_REQQIP 0x14 /* Request Queue In-Pointer */
+#define EDMA_REQQOP 0x18 /* Request Queue Out-Pointer */
+#define EDMA_REQQP_ERQQP_SHIFT 5
+#define EDMA_REQQP_ERQQP_MASK 0x000003e0
+#define EDMA_REQQP_ERQQBAP_MASK 0x00000c00
+#define EDMA_REQQP_ERQQBA_MASK 0xfffff000
+#define EDMA_RESQBAH 0x1c /* Response Queue Base Address High */
+#define EDMA_RESQIP 0x20 /* Response Queue In-Pointer */
+#define EDMA_RESQOP 0x24 /* Response Queue Out-Pointer */
+#define EDMA_RESQP_ERPQP_SHIFT 3
+#define EDMA_RESQP_ERPQP_MASK 0x000000f8
+#define EDMA_RESQP_ERPQBAP_MASK 0x00000300
+#define EDMA_RESQP_ERPQBA_MASK 0xfffffc00
+#define EDMA_CMD 0x28 /* Command */
+#define EDMA_CMD_EENEDMA (1 << 0) /* Enable EDMA */
+#define EDMA_CMD_EDSEDMA (1 << 1) /* Disable EDMA */
+#define EDMA_CMD_EATARST (1 << 2) /* ATA Device Reset */
+#define EDMA_CMD_EEDMAFRZ (1 << 4) /* EDMA Freeze */
+#define EDMA_TC 0x2c /* Test Control */
+#define EDMA_S 0x30 /* Status */
+#define EDMA_S_EDEVQUETAG(s) ((s) & 0x0000001f)
+#define EDMA_S_EDEVDIR_WRITE (0 << 5)
+#define EDMA_S_EDEVDIR_READ (1 << 5)
+#define EDMA_S_ECACHEEMPTY (1 << 6)
+#define EDMA_S_EDMAIDLE (1 << 7)
+#define EDMA_S_ESTATE(s) (((s) & 0x0000ff00) >> 8)
+#define EDMA_S_EIOID(s) (((s) & 0x003f0000) >> 16)
+#define EDMA_IORT 0x34 /* IORdy Timeout */
+#define EDMA_CDT 0x40 /* Command Delay Threshold */
+#define EDMA_HC 0x60 /* Halt Condition */
+#define EDMA_UNKN_RESD 0x6C /* Unknown register */
+#define EDMA_CQDCQOS(x) (0x90 + ((x) << 2)
+ /* NCQ Done/TCQ Outstanding Status */
+
+/* ATA register defines */
+#define ATA_DATA 0x100 /* (RW) data */
+#define ATA_FEATURE 0x104 /* (W) feature */
+#define ATA_F_DMA 0x01 /* enable DMA */
+#define ATA_F_OVL 0x02 /* enable overlap */
+#define ATA_ERROR 0x104 /* (R) error */
+#define ATA_E_ILI 0x01 /* illegal length */
+#define ATA_E_NM 0x02 /* no media */
+#define ATA_E_ABORT 0x04 /* command aborted */
+#define ATA_E_MCR 0x08 /* media change request */
+#define ATA_E_IDNF 0x10 /* ID not found */
+#define ATA_E_MC 0x20 /* media changed */
+#define ATA_E_UNC 0x40 /* uncorrectable data */
+#define ATA_E_ICRC 0x80 /* UDMA crc error */
+#define ATA_E_ATAPI_SENSE_MASK 0xf0 /* ATAPI sense key mask */
+#define ATA_COUNT 0x108 /* (W) sector count */
+#define ATA_IREASON 0x108 /* (R) interrupt reason */
+#define ATA_I_CMD 0x01 /* cmd (1) | data (0) */
+#define ATA_I_IN 0x02 /* read (1) | write (0) */
+#define ATA_I_RELEASE 0x04 /* released bus (1) */
+#define ATA_I_TAGMASK 0xf8 /* tag mask */
+#define ATA_SECTOR 0x10c /* (RW) sector # */
+#define ATA_CYL_LSB 0x110 /* (RW) cylinder# LSB */
+#define ATA_CYL_MSB 0x114 /* (RW) cylinder# MSB */
+#define ATA_DRIVE 0x118 /* (W) Sector/Drive/Head */
+#define ATA_D_LBA 0x40 /* use LBA addressing */
+#define ATA_D_IBM 0xa0 /* 512 byte sectors, ECC */
+#define ATA_COMMAND 0x11c /* (W) command */
+#define ATA_STATUS 0x11c /* (R) status */
+#define ATA_S_ERROR 0x01 /* error */
+#define ATA_S_INDEX 0x02 /* index */
+#define ATA_S_CORR 0x04 /* data corrected */
+#define ATA_S_DRQ 0x08 /* data request */
+#define ATA_S_DSC 0x10 /* drive seek completed */
+#define ATA_S_SERVICE 0x10 /* drive needs service */
+#define ATA_S_DWF 0x20 /* drive write fault */
+#define ATA_S_DMA 0x20 /* DMA ready */
+#define ATA_S_READY 0x40 /* drive ready */
+#define ATA_S_BUSY 0x80 /* busy */
+#define ATA_CONTROL 0x120 /* (W) control */
+#define ATA_A_IDS 0x02 /* disable interrupts */
+#define ATA_A_RESET 0x04 /* RESET controller */
+#define ATA_A_4BIT 0x08 /* 4 head bits */
+#define ATA_A_HOB 0x80 /* High Order Byte enable */
+#define ATA_ALTSTAT 0x120 /* (R) alternate status */
+#define ATAPI_P_READ (ATA_S_DRQ | ATA_I_IN)
+#define ATAPI_P_WRITE (ATA_S_DRQ)
+#define ATAPI_P_CMDOUT (ATA_S_DRQ | ATA_I_CMD)
+#define ATAPI_P_DONEDRQ (ATA_S_DRQ | ATA_I_CMD | ATA_I_IN)
+#define ATAPI_P_DONE (ATA_I_CMD | ATA_I_IN)
+#define ATAPI_P_ABORT 0
+
+/* Basic DMA Registers */
+#define DMA_C 0x224 /* Basic DMA Command */
+#define DMA_C_START (1 << 0)
+#define DMA_C_READ (1 << 3)
+#define DMA_C_DREGIONVALID (1 << 8)
+#define DMA_C_DREGIONLAST (1 << 9)
+#define DMA_C_CONTFROMPREV (1 << 10)
+#define DMA_C_DRBC(n) (((n) & 0xffff) << 16)
+#define DMA_S 0x228 /* Basic DMA Status */
+#define DMA_S_ACT (1 << 0) /* Active */
+#define DMA_S_ERR (1 << 1) /* Error */
+#define DMA_S_PAUSED (1 << 2) /* Paused */
+#define DMA_S_LAST (1 << 3) /* Last */
+#define DMA_DTLBA 0x22c /* Descriptor Table Low Base Address */
+#define DMA_DTLBA_MASK 0xfffffff0
+#define DMA_DTHBA 0x230 /* Descriptor Table High Base Address */
+#define DMA_DRLA 0x234 /* Data Region Low Address */
+#define DMA_DRHA 0x238 /* Data Region High Address */
+
+/* Serial-ATA Registers */
+#define SATA_SS 0x300 /* SStatus */
+#define SATA_SS_DET_MASK 0x0000000f
+#define SATA_SS_DET_NO_DEVICE 0x00000000
+#define SATA_SS_DET_DEV_PRESENT 0x00000001
+#define SATA_SS_DET_PHY_ONLINE 0x00000003
+#define SATA_SS_DET_PHY_OFFLINE 0x00000004
+
+#define SATA_SS_SPD_MASK 0x000000f0
+#define SATA_SS_SPD_NO_SPEED 0x00000000
+#define SATA_SS_SPD_GEN1 0x00000010
+#define SATA_SS_SPD_GEN2 0x00000020
+#define SATA_SS_SPD_GEN3 0x00000040
+
+#define SATA_SS_IPM_MASK 0x00000f00
+#define SATA_SS_IPM_NO_DEVICE 0x00000000
+#define SATA_SS_IPM_ACTIVE 0x00000100
+#define SATA_SS_IPM_PARTIAL 0x00000200
+#define SATA_SS_IPM_SLUMBER 0x00000600
+#define SATA_SE 0x304 /* SError */
+#define SATA_SEIM 0x340 /* SError Interrupt Mask */
+#define SATA_SE_DATA_CORRECTED 0x00000001
+#define SATA_SE_COMM_CORRECTED 0x00000002
+#define SATA_SE_DATA_ERR 0x00000100
+#define SATA_SE_COMM_ERR 0x00000200
+#define SATA_SE_PROT_ERR 0x00000400
+#define SATA_SE_HOST_ERR 0x00000800
+#define SATA_SE_PHY_CHANGED 0x00010000
+#define SATA_SE_PHY_IERROR 0x00020000
+#define SATA_SE_COMM_WAKE 0x00040000
+#define SATA_SE_DECODE_ERR 0x00080000
+#define SATA_SE_PARITY_ERR 0x00100000
+#define SATA_SE_CRC_ERR 0x00200000
+#define SATA_SE_HANDSHAKE_ERR 0x00400000
+#define SATA_SE_LINKSEQ_ERR 0x00800000
+#define SATA_SE_TRANSPORT_ERR 0x01000000
+#define SATA_SE_UNKNOWN_FIS 0x02000000
+#define SATA_SC 0x308 /* SControl */
+#define SATA_SC_DET_MASK 0x0000000f
+#define SATA_SC_DET_IDLE 0x00000000
+#define SATA_SC_DET_RESET 0x00000001
+#define SATA_SC_DET_DISABLE 0x00000004
+
+#define SATA_SC_SPD_MASK 0x000000f0
+#define SATA_SC_SPD_NO_SPEED 0x00000000
+#define SATA_SC_SPD_SPEED_GEN1 0x00000010
+#define SATA_SC_SPD_SPEED_GEN2 0x00000020
+#define SATA_SC_SPD_SPEED_GEN3 0x00000040
+
+#define SATA_SC_IPM_MASK 0x00000f00
+#define SATA_SC_IPM_NONE 0x00000000
+#define SATA_SC_IPM_DIS_PARTIAL 0x00000100
+#define SATA_SC_IPM_DIS_SLUMBER 0x00000200
+
+#define SATA_SC_SPM_MASK 0x0000f000
+#define SATA_SC_SPM_NONE 0x00000000
+#define SATA_SC_SPM_PARTIAL 0x00001000
+#define SATA_SC_SPM_SLUMBER 0x00002000
+#define SATA_SC_SPM_ACTIVE 0x00004000
+#define SATA_LTM 0x30c /* LTMode */
+#define SATA_PHYM3 0x310 /* PHY Mode 3 */
+#define SATA_PHYM4 0x314 /* PHY Mode 4 */
+#define SATA_PHYM1 0x32c /* PHY Mode 1 */
+#define SATA_PHYM2 0x330 /* PHY Mode 2 */
+#define SATA_BISTC 0x334 /* BIST Control */
+#define SATA_BISTDW1 0x338 /* BIST DW1 */
+#define SATA_BISTDW2 0x33c /* BIST DW2 */
+#define SATA_SATAICFG 0x050 /* Serial-ATA Interface Configuration */
+#define SATA_SATAICFG_REFCLKCNF_20MHZ (0 << 0)
+#define SATA_SATAICFG_REFCLKCNF_25MHZ (1 << 0)
+#define SATA_SATAICFG_REFCLKCNF_30MHZ (2 << 0)
+#define SATA_SATAICFG_REFCLKCNF_40MHZ (3 << 0)
+#define SATA_SATAICFG_REFCLKCNF_MASK (3 << 0)
+#define SATA_SATAICFG_REFCLKDIV_1 (0 << 2)
+#define SATA_SATAICFG_REFCLKDIV_2 (1 << 2) /* Used 20 or 25MHz */
+#define SATA_SATAICFG_REFCLKDIV_4 (2 << 2) /* Used 40MHz */
+#define SATA_SATAICFG_REFCLKDIV_3 (3 << 2) /* Used 30MHz */
+#define SATA_SATAICFG_REFCLKDIV_MASK (3 << 2)
+#define SATA_SATAICFG_REFCLKFEEDDIV_50 (0 << 4) /* or 100, when Gen2En is 1 */
+#define SATA_SATAICFG_REFCLKFEEDDIV_60 (1 << 4) /* or 120. Used 25MHz */
+#define SATA_SATAICFG_REFCLKFEEDDIV_75 (2 << 4) /* or 150. Used 20MHz */
+#define SATA_SATAICFG_REFCLKFEEDDIV_90 (3 << 4) /* or 180 */
+#define SATA_SATAICFG_REFCLKFEEDDIV_MASK (3 << 4)
+#define SATA_SATAICFG_PHYSSCEN (1 << 6)
+#define SATA_SATAICFG_GEN2EN (1 << 7)
+#define SATA_SATAICFG_COMMEN (1 << 8)
+#define SATA_SATAICFG_PHYSHUTDOWN (1 << 9)
+#define SATA_SATAICFG_TARGETMODE (1 << 10) /* 1 = Initiator */
+#define SATA_SATAICFG_COMCHANNEL (1 << 11)
+#define SATA_SATAICFG_IGNOREBSY (1 << 24)
+#define SATA_SATAICFG_LINKRSTEN (1 << 25)
+#define SATA_SATAICFG_CMDRETXDS (1 << 26)
+#define SATA_SATAICTL 0x344 /* Serial-ATA Interface Control */
+#define SATA_SATAICTL_PMPTX_MASK 0x0000000f
+#define SATA_SATAICTL_PMPTX_SHIFT 0
+#define SATA_SATAICTL_VUM (1 << 8)
+#define SATA_SATAICTL_VUS (1 << 9)
+#define SATA_SATAICTL_EDMAACT (1 << 16)
+#define SATA_SATAICTL_CLEARSTAT (1 << 24)
+#define SATA_SATAICTL_SRST (1 << 25)
+#define SATA_SATAITC 0x348 /* Serial-ATA Interface Test Control */
+#define SATA_SATAIS 0x34c /* Serial-ATA Interface Status */
+#define SATA_VU 0x35c /* Vendor Unique */
+#define SATA_FISC 0x360 /* FIS Configuration */
+#define SATA_FISC_FISWAIT4RDYEN_B0 (1 << 0) /* Device to Host FIS */
+#define SATA_FISC_FISWAIT4RDYEN_B1 (1 << 1) /* SDB FIS rcv with <N>bit 0 */
+#define SATA_FISC_FISWAIT4RDYEN_B2 (1 << 2) /* DMA Activate FIS */
+#define SATA_FISC_FISWAIT4RDYEN_B3 (1 << 3) /* DMA Setup FIS */
+#define SATA_FISC_FISWAIT4RDYEN_B4 (1 << 4) /* Data FIS first DW */
+#define SATA_FISC_FISWAIT4RDYEN_B5 (1 << 5) /* Data FIS entire FIS */
+#define SATA_FISC_FISWAIT4HOSTRDYEN_B0 (1 << 8)
+ /* Device to Host FIS with <ERR> or <DF> */
+#define SATA_FISC_FISWAIT4HOSTRDYEN_B1 (1 << 9) /* SDB FIS rcv with <N>bit */
+#define SATA_FISC_FISWAIT4HOSTRDYEN_B2 (1 << 10) /* SDB FIS rcv with <ERR> */
+#define SATA_FISC_FISWAIT4HOSTRDYEN_B3 (1 << 11) /* BIST Acivate FIS */
+#define SATA_FISC_FISWAIT4HOSTRDYEN_B4 (1 << 12) /* PIO Setup FIS */
+#define SATA_FISC_FISWAIT4HOSTRDYEN_B5 (1 << 13) /* Data FIS with Link error */
+#define SATA_FISC_FISWAIT4HOSTRDYEN_B6 (1 << 14) /* Unrecognized FIS type */
+#define SATA_FISC_FISWAIT4HOSTRDYEN_B7 (1 << 15) /* Any FIS */
+#define SATA_FISC_FISDMAACTIVATESYNCRESP (1 << 16)
+#define SATA_FISC_FISUNRECTYPECONT (1 << 17)
+#define SATA_FISIC 0x364 /* FIS Interrupt Cause */
+#define SATA_FISIM 0x368 /* FIS Interrupt Mask */
+#define SATA_FISDW0 0x370 /* FIS DW0 */
+#define SATA_FISDW1 0x374 /* FIS DW1 */
+#define SATA_FISDW2 0x378 /* FIS DW2 */
+#define SATA_FISDW3 0x37c /* FIS DW3 */
+#define SATA_FISDW4 0x380 /* FIS DW4 */
+#define SATA_FISDW5 0x384 /* FIS DW5 */
+#define SATA_FISDW6 0x388 /* FIS DW6 */
+
+#define MVS_MAX_PORTS 8
+#define MVS_MAX_SLOTS 32
+
+/* Pessimistic prognosis on number of required S/G entries */
+#define MVS_SG_ENTRIES (btoc(MAXPHYS) + 1)
+
+/* EDMA Command Request Block (CRQB) Data */
+struct mvs_crqb {
+ uint32_t cprdbl; /* cPRD Desriptor Table Base Low Address */
+ uint32_t cprdbh; /* cPRD Desriptor Table Base High Address */
+ uint16_t ctrlflg; /* Control Flags */
+#define MVS_CRQB_READ 0x0001
+#define MVS_CRQB_TAG_MASK 0x003e
+#define MVS_CRQB_TAG_SHIFT 1
+#define MVS_CRQB_PMP_MASK 0xf000
+#define MVS_CRQB_PMP_SHIFT 12
+ uint8_t cmd[22];
+} __packed;
+
+struct mvs_crqb_gen2e {
+ uint32_t cprdbl; /* cPRD Desriptor Table Base Low Address */
+ uint32_t cprdbh; /* cPRD Desriptor Table Base High Address */
+ uint32_t ctrlflg; /* Control Flags */
+#define MVS_CRQB2E_READ 0x00000001
+#define MVS_CRQB2E_DTAG_MASK 0x0000003e
+#define MVS_CRQB2E_DTAG_SHIFT 1
+#define MVS_CRQB2E_PMP_MASK 0x0000f000
+#define MVS_CRQB2E_PMP_SHIFT 12
+#define MVS_CRQB2E_CPRD 0x00010000
+#define MVS_CRQB2E_HTAG_MASK 0x003e0000
+#define MVS_CRQB2E_HTAG_SHIFT 17
+ uint32_t drbc; /* Data Region Byte Count */
+ uint8_t cmd[16];
+} __packed;
+
+/* EDMA Phisical Region Descriptors (ePRD) Table Data Structure */
+struct mvs_eprd {
+ uint32_t prdbal; /* Address bits[31:1] */
+ uint32_t bytecount; /* Byte Count */
+#define MVS_EPRD_MASK 0x0000ffff /* max 64KB */
+#define MVS_EPRD_MAX (MVS_EPRD_MASK + 1)
+#define MVS_EPRD_EOF 0x80000000
+ uint32_t prdbah; /* Address bits[63:32] */
+ uint32_t resv;
+} __packed;
+
+/* Command request blocks. 32 commands. First 1Kbyte aligned. */
+#define MVS_CRQB_OFFSET 0
+#define MVS_CRQB_SIZE 32 /* sizeof(struct mvs_crqb) */
+#define MVS_CRQB_MASK 0x000003e0
+#define MVS_CRQB_SHIFT 5
+#define MVS_CRQB_TO_ADDR(slot) ((slot) << MVS_CRQB_SHIFT)
+#define MVS_ADDR_TO_CRQB(addr) (((addr) & MVS_CRQB_MASK) >> MVS_CRQB_SHIFT)
+/* ePRD blocks. Up to 32 commands, Each 16byte aligned. */
+#define MVS_EPRD_OFFSET (MVS_CRQB_OFFSET + MVS_CRQB_SIZE * MVS_MAX_SLOTS)
+#define MVS_EPRD_SIZE (MVS_SG_ENTRIES * 16) /* sizeof(struct mvs_eprd) */
+/* Request work area. */
+#define MVS_WORKRQ_SIZE (MVS_EPRD_OFFSET + MVS_EPRD_SIZE * MVS_MAX_SLOTS)
+
+/* EDMA Command Response Block (CRPB) Data */
+struct mvs_crpb {
+ uint16_t id; /* CRPB ID */
+#define MVS_CRPB_TAG_MASK 0x001F
+#define MVS_CRPB_TAG_SHIFT 0
+ uint16_t rspflg; /* CPRB Response Flags */
+#define MVS_CRPB_EDMASTS_MASK 0x007F
+#define MVS_CRPB_EDMASTS_SHIFT 0
+#define MVS_CRPB_ATASTS_MASK 0xFF00
+#define MVS_CRPB_ATASTS_SHIFT 8
+ uint32_t ts; /* CPRB Time Stamp */
+} __packed;
+
+/* Command response blocks. 32 commands. First 256byte aligned. */
+#define MVS_CRPB_OFFSET 0
+#define MVS_CRPB_SIZE sizeof(struct mvs_crpb)
+#define MVS_CRPB_MASK 0x000000f8
+#define MVS_CRPB_SHIFT 3
+#define MVS_CRPB_TO_ADDR(slot) ((slot) << MVS_CRPB_SHIFT)
+#define MVS_ADDR_TO_CRPB(addr) (((addr) & MVS_CRPB_MASK) >> MVS_CRPB_SHIFT)
+/* Request work area. */
+#define MVS_WORKRP_SIZE (MVS_CRPB_OFFSET + MVS_CRPB_SIZE * MVS_MAX_SLOTS)
+
+/* misc defines */
+#define ATA_IRQ_RID 0
+#define ATA_INTR_FLAGS (INTR_MPSAFE|INTR_TYPE_BIO|INTR_ENTROPY)
+
+struct ata_dmaslot {
+ bus_dmamap_t data_map; /* Data DMA map */
+ bus_addr_t addr; /* Data address */
+ uint16_t len; /* Data size */
+};
+
+/* structure holding DMA related information */
+struct mvs_dma {
+ bus_dma_tag_t workrq_tag; /* Request workspace DMA tag */
+ bus_dmamap_t workrq_map; /* Request workspace DMA map */
+ uint8_t *workrq; /* Request workspace */
+ bus_addr_t workrq_bus; /* Request bus address */
+ bus_dma_tag_t workrp_tag; /* Reply workspace DMA tag */
+ bus_dmamap_t workrp_map; /* Reply workspace DMA map */
+ uint8_t *workrp; /* Reply workspace */
+ bus_addr_t workrp_bus; /* Reply bus address */
+ bus_dma_tag_t data_tag; /* Data DMA tag */
+};
+
+enum mvs_slot_states {
+ MVS_SLOT_EMPTY,
+ MVS_SLOT_LOADING,
+ MVS_SLOT_RUNNING,
+ MVS_SLOT_EXECUTING
+};
+
+struct mvs_slot {
+ device_t dev; /* Device handle */
+ int slot; /* Number of this slot */
+ int tag; /* Used command tag */
+ enum mvs_slot_states state; /* Slot state */
+ union ccb *ccb; /* CCB occupying slot */
+ struct ata_dmaslot dma; /* DMA data of this slot */
+ struct callout timeout; /* Execution timeout */
+};
+
+struct mvs_device {
+ int revision;
+ int mode;
+ u_int bytecount;
+ u_int atapi;
+ u_int tags;
+ u_int caps;
+};
+
+enum mvs_edma_mode {
+ MVS_EDMA_UNKNOWN,
+ MVS_EDMA_OFF,
+ MVS_EDMA_ON,
+ MVS_EDMA_QUEUED,
+ MVS_EDMA_NCQ,
+};
+
+/* structure describing an ATA channel */
+struct mvs_channel {
+ device_t dev; /* Device handle */
+ int unit; /* Physical channel */
+ struct resource *r_mem; /* Memory of this channel */
+ struct resource *r_irq; /* Interrupt of this channel */
+ void *ih; /* Interrupt handle */
+ struct mvs_dma dma; /* DMA data */
+ struct cam_sim *sim;
+ struct cam_path *path;
+ int quirks;
+#define MVS_Q_GENI 1
+#define MVS_Q_GENII 2
+#define MVS_Q_GENIIE 4
+#define MVS_Q_SOC 8
+#define MVS_Q_CT 16
+ int pm_level; /* power management level */
+
+ struct mvs_slot slot[MVS_MAX_SLOTS];
+ union ccb *hold[MVS_MAX_SLOTS];
+ int holdtag[MVS_MAX_SLOTS]; /* Tags used for holden commands. */
+ struct mtx mtx; /* state lock */
+ int devices; /* What is present */
+ int pm_present; /* PM presence reported */
+ enum mvs_edma_mode curr_mode; /* Current EDMA mode */
+ int fbs_enabled; /* FIS-based switching enabled */
+ uint32_t oslots; /* Occupied slots */
+ uint32_t otagspd[16]; /* Occupied device tags */
+ uint32_t rslots; /* Running slots */
+ uint32_t aslots; /* Slots with atomic commands */
+ uint32_t eslots; /* Slots in error */
+ uint32_t toslots; /* Slots in timeout */
+ int numrslots; /* Number of running slots */
+ int numrslotspd[16];/* Number of running slots per dev */
+ int numpslots; /* Number of PIO slots */
+ int numdslots; /* Number of DMA slots */
+ int numtslots; /* Number of NCQ slots */
+ int numtslotspd[16];/* Number of NCQ slots per dev */
+ int numhslots; /* Number of holden slots */
+ int readlog; /* Our READ LOG active */
+ int fatalerr; /* Fatal error happend */
+ int lastslot; /* Last used slot */
+ int taggedtarget; /* Last tagged target */
+ int out_idx; /* Next written CRQB */
+ int in_idx; /* Next read CRPB */
+ u_int transfersize; /* PIO transfer size */
+ u_int donecount; /* PIO bytes sent/received */
+ u_int basic_dma; /* Basic DMA used for ATAPI */
+ u_int fake_busy; /* Fake busy bit after command submission */
+ union ccb *frozen; /* Frozen command */
+ struct callout pm_timer; /* Power management events */
+
+ struct mvs_device user[16]; /* User-specified settings */
+ struct mvs_device curr[16]; /* Current settings */
+};
+
+/* structure describing a MVS controller */
+struct mvs_controller {
+ device_t dev;
+ int r_rid;
+ struct resource *r_mem;
+ struct rman sc_iomem;
+ struct mvs_controller_irq {
+ struct resource *r_irq;
+ void *handle;
+ int r_irq_rid;
+ } irq;
+ int quirks;
+ int channels;
+ int ccc; /* CCC timeout */
+ int cccc; /* CCC commands */
+ struct mtx mtx; /* MIM access lock */
+ int gmim; /* Globally wanted MIM bits */
+ int pmim; /* Port wanted MIM bits */
+ int mim; /* Current MIM bits */
+ int msi; /* MSI enabled */
+ int msia; /* MSI active */
+ struct {
+ void (*function)(void *);
+ void *argument;
+ } interrupt[MVS_MAX_PORTS];
+};
+
+enum mvs_err_type {
+ MVS_ERR_NONE, /* No error */
+ MVS_ERR_INVALID, /* Error detected by us before submitting. */
+ MVS_ERR_INNOCENT, /* Innocent victim. */
+ MVS_ERR_TFE, /* Task File Error. */
+ MVS_ERR_SATA, /* SATA error. */
+ MVS_ERR_TIMEOUT, /* Command execution timeout. */
+ MVS_ERR_NCQ, /* NCQ command error. CCB should be put on hold
+ * until READ LOG executed to reveal error. */
+};
+
+struct mvs_intr_arg {
+ void *arg;
+ u_int cause;
+};
+
+extern devclass_t mvs_devclass;
+
+/* macros to hide busspace uglyness */
+#define ATA_INB(res, offset) \
+ bus_read_1((res), (offset))
+#define ATA_INW(res, offset) \
+ bus_read_2((res), (offset))
+#define ATA_INL(res, offset) \
+ bus_read_4((res), (offset))
+#define ATA_INSW(res, offset, addr, count) \
+ bus_read_multi_2((res), (offset), (addr), (count))
+#define ATA_INSW_STRM(res, offset, addr, count) \
+ bus_read_multi_stream_2((res), (offset), (addr), (count))
+#define ATA_INSL(res, offset, addr, count) \
+ bus_read_multi_4((res), (offset), (addr), (count))
+#define ATA_INSL_STRM(res, offset, addr, count) \
+ bus_read_multi_stream_4((res), (offset), (addr), (count))
+#define ATA_OUTB(res, offset, value) \
+ bus_write_1((res), (offset), (value))
+#define ATA_OUTW(res, offset, value) \
+ bus_write_2((res), (offset), (value))
+#define ATA_OUTL(res, offset, value) \
+ bus_write_4((res), (offset), (value));
+#define ATA_OUTSW(res, offset, addr, count) \
+ bus_write_multi_2((res), (offset), (addr), (count))
+#define ATA_OUTSW_STRM(res, offset, addr, count) \
+ bus_write_multi_stream_2((res), (offset), (addr), (count))
+#define ATA_OUTSL(res, offset, addr, count) \
+ bus_write_multi_4((res), (offset), (addr), (count))
+#define ATA_OUTSL_STRM(res, offset, addr, count) \
+ bus_write_multi_stream_4((res), (offset), (addr), (count))
diff --git a/sys/dev/mvs/mvs_if.m b/sys/dev/mvs/mvs_if.m
new file mode 100644
index 0000000..e744219
--- /dev/null
+++ b/sys/dev/mvs/mvs_if.m
@@ -0,0 +1,34 @@
+# Copyright (c) 2010 Alexander Motin <mav@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,
+# without modification, immediately at the beginning of the file.
+# 2. Redistributions in binary form must 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$
+
+INTERFACE mvs;
+
+METHOD void edma {
+ device_t dev;
+ device_t child;
+ int mode;
+};
+
diff --git a/sys/dev/mvs/mvs_pci.c b/sys/dev/mvs/mvs_pci.c
new file mode 100644
index 0000000..4fae627
--- /dev/null
+++ b/sys/dev/mvs/mvs_pci.c
@@ -0,0 +1,507 @@
+/*-
+ * Copyright (c) 2010 Alexander Motin <mav@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,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must 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/module.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <vm/uma.h>
+#include <machine/stdarg.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include "mvs.h"
+
+/* local prototypes */
+static int mvs_setup_interrupt(device_t dev);
+static void mvs_intr(void *data);
+static int mvs_suspend(device_t dev);
+static int mvs_resume(device_t dev);
+static int mvs_ctlr_setup(device_t dev);
+
+static struct {
+ uint32_t id;
+ uint8_t rev;
+ const char *name;
+ int ports;
+ int quirks;
+} mvs_ids[] = {
+ {0x504011ab, 0x00, "Marvell 88SX5040", 4, MVS_Q_GENI},
+ {0x504111ab, 0x00, "Marvell 88SX5041", 4, MVS_Q_GENI},
+ {0x508011ab, 0x00, "Marvell 88SX5080", 8, MVS_Q_GENI},
+ {0x508111ab, 0x00, "Marvell 88SX5081", 8, MVS_Q_GENI},
+ {0x604011ab, 0x00, "Marvell 88SX6040", 4, MVS_Q_GENII},
+ {0x604111ab, 0x00, "Marvell 88SX6041", 4, MVS_Q_GENII},
+ {0x604211ab, 0x00, "Marvell 88SX6042", 4, MVS_Q_GENIIE},
+ {0x608011ab, 0x00, "Marvell 88SX6080", 8, MVS_Q_GENII},
+ {0x608111ab, 0x00, "Marvell 88SX6081", 8, MVS_Q_GENII},
+ {0x704211ab, 0x00, "Marvell 88SX7042", 4, MVS_Q_GENIIE|MVS_Q_CT},
+ {0x02419005, 0x00, "Adaptec 1420SA", 4, MVS_Q_GENII},
+ {0x02439005, 0x00, "Adaptec 1430SA", 4, MVS_Q_GENIIE|MVS_Q_CT},
+ {0x00000000, 0x00, NULL, 0, 0}
+};
+
+static int
+mvs_probe(device_t dev)
+{
+ char buf[64];
+ int i;
+ uint32_t devid = pci_get_devid(dev);
+ uint8_t revid = pci_get_revid(dev);
+
+ for (i = 0; mvs_ids[i].id != 0; i++) {
+ if (mvs_ids[i].id == devid &&
+ mvs_ids[i].rev <= revid) {
+ snprintf(buf, sizeof(buf), "%s SATA controller",
+ mvs_ids[i].name);
+ device_set_desc_copy(dev, buf);
+ return (BUS_PROBE_VENDOR);
+ }
+ }
+ return (ENXIO);
+}
+
+static int
+mvs_attach(device_t dev)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ device_t child;
+ int error, unit, i;
+ uint32_t devid = pci_get_devid(dev);
+ uint8_t revid = pci_get_revid(dev);
+
+ ctlr->dev = dev;
+ i = 0;
+ while (mvs_ids[i].id != 0 &&
+ (mvs_ids[i].id != devid ||
+ mvs_ids[i].rev > revid))
+ i++;
+ ctlr->channels = mvs_ids[i].ports;
+ ctlr->quirks = mvs_ids[i].quirks;
+ resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "ccc", &ctlr->ccc);
+ ctlr->cccc = 8;
+ resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "cccc", &ctlr->cccc);
+ if (ctlr->ccc == 0 || ctlr->cccc == 0) {
+ ctlr->ccc = 0;
+ ctlr->cccc = 0;
+ }
+ if (ctlr->ccc > 100000)
+ ctlr->ccc = 100000;
+ device_printf(dev,
+ "Gen-%s, %d %sGbps ports, Port Multiplier %s%s\n",
+ ((ctlr->quirks & MVS_Q_GENI) ? "I" :
+ ((ctlr->quirks & MVS_Q_GENII) ? "II" : "IIe")),
+ ctlr->channels,
+ ((ctlr->quirks & MVS_Q_GENI) ? "1.5" : "3"),
+ ((ctlr->quirks & MVS_Q_GENI) ?
+ "not supported" : "supported"),
+ ((ctlr->quirks & MVS_Q_GENIIE) ?
+ " with FBS" : ""));
+ mtx_init(&ctlr->mtx, "MVS controller lock", NULL, MTX_DEF);
+ /* We should have a memory BAR(0). */
+ ctlr->r_rid = PCIR_BAR(0);
+ if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &ctlr->r_rid, RF_ACTIVE)))
+ return ENXIO;
+ /* Setup our own memory management for channels. */
+ ctlr->sc_iomem.rm_type = RMAN_ARRAY;
+ ctlr->sc_iomem.rm_descr = "I/O memory addresses";
+ if ((error = rman_init(&ctlr->sc_iomem)) != 0) {
+ bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ return (error);
+ }
+ if ((error = rman_manage_region(&ctlr->sc_iomem,
+ rman_get_start(ctlr->r_mem), rman_get_end(ctlr->r_mem))) != 0) {
+ bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ rman_fini(&ctlr->sc_iomem);
+ return (error);
+ }
+ pci_enable_busmaster(dev);
+ mvs_ctlr_setup(dev);
+ /* Setup interrupts. */
+ if (mvs_setup_interrupt(dev)) {
+ bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ rman_fini(&ctlr->sc_iomem);
+ return ENXIO;
+ }
+ /* Attach all channels on this controller */
+ for (unit = 0; unit < ctlr->channels; unit++) {
+ child = device_add_child(dev, "mvsch", -1);
+ if (child == NULL)
+ device_printf(dev, "failed to add channel device\n");
+ else
+ device_set_ivars(child, (void *)(intptr_t)unit);
+ }
+ bus_generic_attach(dev);
+ return 0;
+}
+
+static int
+mvs_detach(device_t dev)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ device_t *children;
+ int nchildren, i;
+
+ /* Detach & delete all children */
+ if (!device_get_children(dev, &children, &nchildren)) {
+ for (i = 0; i < nchildren; i++)
+ device_delete_child(dev, children[i]);
+ free(children, M_TEMP);
+ }
+ /* Free interrupt. */
+ if (ctlr->irq.r_irq) {
+ bus_teardown_intr(dev, ctlr->irq.r_irq,
+ ctlr->irq.handle);
+ bus_release_resource(dev, SYS_RES_IRQ,
+ ctlr->irq.r_irq_rid, ctlr->irq.r_irq);
+ }
+ pci_release_msi(dev);
+ /* Free memory. */
+ rman_fini(&ctlr->sc_iomem);
+ if (ctlr->r_mem)
+ bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ mtx_destroy(&ctlr->mtx);
+ return (0);
+}
+
+static int
+mvs_ctlr_setup(device_t dev)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int i, ccc = ctlr->ccc, cccc = ctlr->cccc, ccim = 0;
+
+ /* Mask chip interrupts */
+ ATA_OUTL(ctlr->r_mem, CHIP_MIM, 0x00000000);
+ /* Mask PCI interrupts */
+ ATA_OUTL(ctlr->r_mem, CHIP_PCIIM, 0x00000000);
+ /* Clear PCI interrupts */
+ ATA_OUTL(ctlr->r_mem, CHIP_PCIIC, 0x00000000);
+ if (ccc && bootverbose) {
+ device_printf(dev,
+ "CCC with %dus/%dcmd enabled\n",
+ ctlr->ccc, ctlr->cccc);
+ }
+ ccc *= 150;
+ /* Configure chip-global CCC */
+ if (ctlr->channels > 4 && (ctlr->quirks & MVS_Q_GENI) == 0) {
+ ATA_OUTL(ctlr->r_mem, CHIP_ICT, cccc);
+ ATA_OUTL(ctlr->r_mem, CHIP_ITT, ccc);
+ ATA_OUTL(ctlr->r_mem, CHIP_ICC, ~CHIP_ICC_ALL_PORTS);
+ if (ccc)
+ ccim |= IC_ALL_PORTS_COAL_DONE;
+ ccc = 0;
+ cccc = 0;
+ }
+ for (i = 0; i < ctlr->channels / 4; i++) {
+ /* Configure per-HC CCC */
+ ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_ICT, cccc);
+ ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_ITT, ccc);
+ if (ccc)
+ ccim |= (IC_HC0_COAL_DONE << (i * IC_HC_SHIFT));
+ /* Clear HC interrupts */
+ ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_IC, 0x00000000);
+ }
+ /* Enable chip interrupts */
+ ctlr->gmim = (ccim ? ccim : (IC_DONE_HC0 | IC_DONE_HC1)) |
+ IC_ERR_HC0 | IC_ERR_HC1;
+ ctlr->mim = ctlr->gmim | ctlr->pmim;
+ ATA_OUTL(ctlr->r_mem, CHIP_MIM, ctlr->mim);
+ /* Enable PCI interrupts */
+ ATA_OUTL(ctlr->r_mem, CHIP_PCIIM, 0x007fffff);
+ return (0);
+}
+
+static void
+mvs_edma(device_t dev, device_t child, int mode)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int unit = ((struct mvs_channel *)device_get_softc(child))->unit;
+ int bit = IC_DONE_IRQ << (unit * 2 + unit / 4) ;
+
+ if (ctlr->ccc == 0)
+ return;
+ /* CCC is not working for non-EDMA mode. Unmask device interrupts. */
+ mtx_lock(&ctlr->mtx);
+ if (mode == MVS_EDMA_OFF)
+ ctlr->pmim |= bit;
+ else
+ ctlr->pmim &= ~bit;
+ ctlr->mim = ctlr->gmim | ctlr->pmim;
+ if (!ctlr->msia)
+ ATA_OUTL(ctlr->r_mem, CHIP_MIM, ctlr->mim);
+ mtx_unlock(&ctlr->mtx);
+}
+
+static int
+mvs_suspend(device_t dev)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+
+ bus_generic_suspend(dev);
+ /* Mask chip interrupts */
+ ATA_OUTL(ctlr->r_mem, CHIP_MIM, 0x00000000);
+ /* Mask PCI interrupts */
+ ATA_OUTL(ctlr->r_mem, CHIP_PCIIM, 0x00000000);
+ return 0;
+}
+
+static int
+mvs_resume(device_t dev)
+{
+
+ mvs_ctlr_setup(dev);
+ return (bus_generic_resume(dev));
+}
+
+static int
+mvs_setup_interrupt(device_t dev)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int msi = 0;
+
+ /* Process hints. */
+ resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "msi", &msi);
+ if (msi < 0)
+ msi = 0;
+ else if (msi > 0)
+ msi = min(1, pci_msi_count(dev));
+ /* Allocate MSI if needed/present. */
+ if (msi && pci_alloc_msi(dev, &msi) != 0)
+ msi = 0;
+ ctlr->msi = msi;
+ /* Allocate all IRQs. */
+ ctlr->irq.r_irq_rid = msi ? 1 : 0;
+ if (!(ctlr->irq.r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &ctlr->irq.r_irq_rid, RF_SHAREABLE | RF_ACTIVE))) {
+ device_printf(dev, "unable to map interrupt\n");
+ return (ENXIO);
+ }
+ if ((bus_setup_intr(dev, ctlr->irq.r_irq, ATA_INTR_FLAGS, NULL,
+ mvs_intr, ctlr, &ctlr->irq.handle))) {
+ device_printf(dev, "unable to setup interrupt\n");
+ bus_release_resource(dev, SYS_RES_IRQ,
+ ctlr->irq.r_irq_rid, ctlr->irq.r_irq);
+ ctlr->irq.r_irq = 0;
+ return (ENXIO);
+ }
+ return (0);
+}
+
+/*
+ * Common case interrupt handler.
+ */
+static void
+mvs_intr(void *data)
+{
+ struct mvs_controller *ctlr = data;
+ struct mvs_intr_arg arg;
+ void (*function)(void *);
+ int p;
+ u_int32_t ic, aic;
+
+ ic = ATA_INL(ctlr->r_mem, CHIP_MIC);
+//device_printf(ctlr->dev, "irq MIC:%08x\n", ic);
+ if (ctlr->msi) {
+ /* We have to to mask MSI during processing. */
+ mtx_lock(&ctlr->mtx);
+ ATA_OUTL(ctlr->r_mem, CHIP_MIM, 0);
+ ctlr->msia = 1; /* Deny MIM update during processing. */
+ mtx_unlock(&ctlr->mtx);
+ } else if (ic == 0)
+ return;
+ /* Acknowledge all-ports CCC interrupt. */
+ if (ic & IC_ALL_PORTS_COAL_DONE)
+ ATA_OUTL(ctlr->r_mem, CHIP_ICC, ~CHIP_ICC_ALL_PORTS);
+ for (p = 0; p < ctlr->channels; p++) {
+ if ((p & 3) == 0) {
+ if (p != 0)
+ ic >>= 1;
+ if ((ic & IC_HC0) == 0) {
+ p += 3;
+ ic >>= 8;
+ continue;
+ }
+ /* Acknowledge interrupts of this HC. */
+ aic = 0;
+ if (ic & (IC_DONE_IRQ << 0))
+ aic |= HC_IC_DONE(0) | HC_IC_DEV(0);
+ if (ic & (IC_DONE_IRQ << 2))
+ aic |= HC_IC_DONE(1) | HC_IC_DEV(1);
+ if (ic & (IC_DONE_IRQ << 4))
+ aic |= HC_IC_DONE(2) | HC_IC_DEV(2);
+ if (ic & (IC_DONE_IRQ << 6))
+ aic |= HC_IC_DONE(3) | HC_IC_DEV(3);
+ if (ic & IC_HC0_COAL_DONE)
+ aic |= HC_IC_COAL;
+ ATA_OUTL(ctlr->r_mem, HC_BASE(p == 4) + HC_IC, ~aic);
+ }
+ /* Call per-port interrupt handler. */
+ arg.cause = ic & (IC_ERR_IRQ|IC_DONE_IRQ);
+ if ((arg.cause != 0) &&
+ (function = ctlr->interrupt[p].function)) {
+ arg.arg = ctlr->interrupt[p].argument;
+ function(&arg);
+ }
+ ic >>= 2;
+ }
+ if (ctlr->msi) {
+ /* Unmasking MSI triggers next interrupt, if needed. */
+ mtx_lock(&ctlr->mtx);
+ ctlr->msia = 0; /* Allow MIM update. */
+ ATA_OUTL(ctlr->r_mem, CHIP_MIM, ctlr->mim);
+ mtx_unlock(&ctlr->mtx);
+ }
+}
+
+static struct resource *
+mvs_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int unit = ((struct mvs_channel *)device_get_softc(child))->unit;
+ struct resource *res = NULL;
+ int offset = HC_BASE(unit >> 2) + PORT_BASE(unit & 0x03);
+ long st;
+
+ switch (type) {
+ case SYS_RES_MEMORY:
+ st = rman_get_start(ctlr->r_mem);
+ res = rman_reserve_resource(&ctlr->sc_iomem, st + offset,
+ st + offset + PORT_SIZE - 1, PORT_SIZE, RF_ACTIVE, child);
+ if (res) {
+ bus_space_handle_t bsh;
+ bus_space_tag_t bst;
+ bsh = rman_get_bushandle(ctlr->r_mem);
+ bst = rman_get_bustag(ctlr->r_mem);
+ bus_space_subregion(bst, bsh, offset, PORT_SIZE, &bsh);
+ rman_set_bushandle(res, bsh);
+ rman_set_bustag(res, bst);
+ }
+ break;
+ case SYS_RES_IRQ:
+ if (*rid == ATA_IRQ_RID)
+ res = ctlr->irq.r_irq;
+ break;
+ }
+ return (res);
+}
+
+static int
+mvs_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+
+ switch (type) {
+ case SYS_RES_MEMORY:
+ rman_release_resource(r);
+ return (0);
+ case SYS_RES_IRQ:
+ if (rid != ATA_IRQ_RID)
+ return ENOENT;
+ return (0);
+ }
+ return (EINVAL);
+}
+
+static int
+mvs_setup_intr(device_t dev, device_t child, struct resource *irq,
+ int flags, driver_filter_t *filter, driver_intr_t *function,
+ void *argument, void **cookiep)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int unit = (intptr_t)device_get_ivars(child);
+
+ if (filter != NULL) {
+ printf("mvs.c: we cannot use a filter here\n");
+ return (EINVAL);
+ }
+ ctlr->interrupt[unit].function = function;
+ ctlr->interrupt[unit].argument = argument;
+ return (0);
+}
+
+static int
+mvs_teardown_intr(device_t dev, device_t child, struct resource *irq,
+ void *cookie)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int unit = (intptr_t)device_get_ivars(child);
+
+ ctlr->interrupt[unit].function = NULL;
+ ctlr->interrupt[unit].argument = NULL;
+ return (0);
+}
+
+static int
+mvs_print_child(device_t dev, device_t child)
+{
+ int retval;
+
+ retval = bus_print_child_header(dev, child);
+ retval += printf(" at channel %d",
+ (int)(intptr_t)device_get_ivars(child));
+ retval += bus_print_child_footer(dev, child);
+
+ return (retval);
+}
+
+static device_method_t mvs_methods[] = {
+ DEVMETHOD(device_probe, mvs_probe),
+ DEVMETHOD(device_attach, mvs_attach),
+ DEVMETHOD(device_detach, mvs_detach),
+ DEVMETHOD(device_suspend, mvs_suspend),
+ DEVMETHOD(device_resume, mvs_resume),
+ DEVMETHOD(bus_print_child, mvs_print_child),
+ DEVMETHOD(bus_alloc_resource, mvs_alloc_resource),
+ DEVMETHOD(bus_release_resource, mvs_release_resource),
+ DEVMETHOD(bus_setup_intr, mvs_setup_intr),
+ DEVMETHOD(bus_teardown_intr,mvs_teardown_intr),
+ DEVMETHOD(mvs_edma, mvs_edma),
+ { 0, 0 }
+};
+static driver_t mvs_driver = {
+ "mvs",
+ mvs_methods,
+ sizeof(struct mvs_controller)
+};
+DRIVER_MODULE(mvs, pci, mvs_driver, mvs_devclass, 0, 0);
+MODULE_VERSION(mvs, 1);
+MODULE_DEPEND(mvs, cam, 1, 1, 1);
+
diff --git a/sys/dev/mvs/mvs_soc.c b/sys/dev/mvs/mvs_soc.c
new file mode 100644
index 0000000..298a873
--- /dev/null
+++ b/sys/dev/mvs/mvs_soc.c
@@ -0,0 +1,437 @@
+/*-
+ * Copyright (c) 2010 Alexander Motin <mav@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,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must 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/module.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <vm/uma.h>
+#include <machine/stdarg.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+#include "mvs.h"
+
+/* local prototypes */
+static int mvs_setup_interrupt(device_t dev);
+static void mvs_intr(void *data);
+static int mvs_suspend(device_t dev);
+static int mvs_resume(device_t dev);
+static int mvs_ctlr_setup(device_t dev);
+
+static struct {
+ uint32_t id;
+ uint8_t rev;
+ const char *name;
+ int ports;
+ int quirks;
+} mvs_ids[] = {
+ {MV_DEV_88F5182, 0x00, "Marvell 88F5182", 2, MVS_Q_GENIIE|MVS_Q_SOC},
+ {MV_DEV_88F6281, 0x00, "Marvell 88F6281", 2, MVS_Q_GENIIE|MVS_Q_SOC},
+ {MV_DEV_MV78100, 0x00, "Marvell MV78100", 2, MVS_Q_GENIIE|MVS_Q_SOC},
+ {MV_DEV_MV78100_Z0, 0x00,"Marvell MV78100", 2, MVS_Q_GENIIE|MVS_Q_SOC},
+ {0, 0x00, NULL, 0, 0}
+};
+
+static int
+mvs_probe(device_t dev)
+{
+ char buf[64];
+ int i;
+ uint32_t devid, revid;
+
+ soc_id(&devid, &revid);
+ for (i = 0; mvs_ids[i].id != 0; i++) {
+ if (mvs_ids[i].id == devid &&
+ mvs_ids[i].rev <= revid) {
+ snprintf(buf, sizeof(buf), "%s SATA controller",
+ mvs_ids[i].name);
+ device_set_desc_copy(dev, buf);
+ return (BUS_PROBE_VENDOR);
+ }
+ }
+ return (ENXIO);
+}
+
+static int
+mvs_attach(device_t dev)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ device_t child;
+ int error, unit, i;
+ uint32_t devid, revid;
+
+ soc_id(&devid, &revid);
+ ctlr->dev = dev;
+ i = 0;
+ while (mvs_ids[i].id != 0 &&
+ (mvs_ids[i].id != devid ||
+ mvs_ids[i].rev > revid))
+ i++;
+ ctlr->channels = mvs_ids[i].ports;
+ ctlr->quirks = mvs_ids[i].quirks;
+ resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "ccc", &ctlr->ccc);
+ ctlr->cccc = 8;
+ resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "cccc", &ctlr->cccc);
+ if (ctlr->ccc == 0 || ctlr->cccc == 0) {
+ ctlr->ccc = 0;
+ ctlr->cccc = 0;
+ }
+ if (ctlr->ccc > 100000)
+ ctlr->ccc = 100000;
+ device_printf(dev,
+ "Gen-%s, %d %sGbps ports, Port Multiplier %s%s\n",
+ ((ctlr->quirks & MVS_Q_GENI) ? "I" :
+ ((ctlr->quirks & MVS_Q_GENII) ? "II" : "IIe")),
+ ctlr->channels,
+ ((ctlr->quirks & MVS_Q_GENI) ? "1.5" : "3"),
+ ((ctlr->quirks & MVS_Q_GENI) ?
+ "not supported" : "supported"),
+ ((ctlr->quirks & MVS_Q_GENIIE) ?
+ " with FBS" : ""));
+ mtx_init(&ctlr->mtx, "MVS controller lock", NULL, MTX_DEF);
+ /* We should have a memory BAR(0). */
+ ctlr->r_rid = 0;
+ if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &ctlr->r_rid, RF_ACTIVE)))
+ return ENXIO;
+ /* Setup our own memory management for channels. */
+ ctlr->sc_iomem.rm_type = RMAN_ARRAY;
+ ctlr->sc_iomem.rm_descr = "I/O memory addresses";
+ if ((error = rman_init(&ctlr->sc_iomem)) != 0) {
+ bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ return (error);
+ }
+ if ((error = rman_manage_region(&ctlr->sc_iomem,
+ rman_get_start(ctlr->r_mem), rman_get_end(ctlr->r_mem))) != 0) {
+ bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ rman_fini(&ctlr->sc_iomem);
+ return (error);
+ }
+ mvs_ctlr_setup(dev);
+ /* Setup interrupts. */
+ if (mvs_setup_interrupt(dev)) {
+ bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ rman_fini(&ctlr->sc_iomem);
+ return ENXIO;
+ }
+ /* Attach all channels on this controller */
+ for (unit = 0; unit < ctlr->channels; unit++) {
+ child = device_add_child(dev, "mvsch", -1);
+ if (child == NULL)
+ device_printf(dev, "failed to add channel device\n");
+ else
+ device_set_ivars(child, (void *)(intptr_t)unit);
+ }
+ bus_generic_attach(dev);
+ return 0;
+}
+
+static int
+mvs_detach(device_t dev)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ device_t *children;
+ int nchildren, i;
+
+ /* Detach & delete all children */
+ if (!device_get_children(dev, &children, &nchildren)) {
+ for (i = 0; i < nchildren; i++)
+ device_delete_child(dev, children[i]);
+ free(children, M_TEMP);
+ }
+ /* Free interrupt. */
+ if (ctlr->irq.r_irq) {
+ bus_teardown_intr(dev, ctlr->irq.r_irq,
+ ctlr->irq.handle);
+ bus_release_resource(dev, SYS_RES_IRQ,
+ ctlr->irq.r_irq_rid, ctlr->irq.r_irq);
+ }
+ /* Free memory. */
+ rman_fini(&ctlr->sc_iomem);
+ if (ctlr->r_mem)
+ bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ mtx_destroy(&ctlr->mtx);
+ return (0);
+}
+
+static int
+mvs_ctlr_setup(device_t dev)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int ccc = ctlr->ccc, cccc = ctlr->cccc, ccim = 0;
+
+ /* Mask chip interrupts */
+ ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, 0x00000000);
+ /* Clear HC interrupts */
+ ATA_OUTL(ctlr->r_mem, HC_IC, 0x00000000);
+ /* Clear chip interrupts */
+ ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIC, 0);
+ /* Configure per-HC CCC */
+ if (ccc && bootverbose) {
+ device_printf(dev,
+ "CCC with %dus/%dcmd enabled\n",
+ ctlr->ccc, ctlr->cccc);
+ }
+ ccc *= 150;
+ ATA_OUTL(ctlr->r_mem, HC_ICT, cccc);
+ ATA_OUTL(ctlr->r_mem, HC_ITT, ccc);
+ if (ccc)
+ ccim |= IC_HC0_COAL_DONE;
+ /* Enable chip interrupts */
+ ctlr->gmim = (ccc ? IC_HC0_COAL_DONE : IC_DONE_HC0) | IC_ERR_HC0;
+ ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, ctlr->gmim | ctlr->pmim);
+ return (0);
+}
+
+static void
+mvs_edma(device_t dev, device_t child, int mode)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int unit = ((struct mvs_channel *)device_get_softc(child))->unit;
+ int bit = IC_DONE_IRQ << (unit * 2);
+
+ if (ctlr->ccc == 0)
+ return;
+ /* CCC is not working for non-EDMA mode. Unmask device interrupts. */
+ mtx_lock(&ctlr->mtx);
+ if (mode == MVS_EDMA_OFF)
+ ctlr->pmim |= bit;
+ else
+ ctlr->pmim &= ~bit;
+ ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, ctlr->gmim | ctlr->pmim);
+ mtx_unlock(&ctlr->mtx);
+}
+
+static int
+mvs_suspend(device_t dev)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+
+ bus_generic_suspend(dev);
+ /* Mask chip interrupts */
+ ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, 0x00000000);
+ return 0;
+}
+
+static int
+mvs_resume(device_t dev)
+{
+
+ mvs_ctlr_setup(dev);
+ return (bus_generic_resume(dev));
+}
+
+static int
+mvs_setup_interrupt(device_t dev)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+
+ /* Allocate all IRQs. */
+ ctlr->irq.r_irq_rid = 0;
+ if (!(ctlr->irq.r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &ctlr->irq.r_irq_rid, RF_SHAREABLE | RF_ACTIVE))) {
+ device_printf(dev, "unable to map interrupt\n");
+ return (ENXIO);
+ }
+ if ((bus_setup_intr(dev, ctlr->irq.r_irq, ATA_INTR_FLAGS, NULL,
+ mvs_intr, ctlr, &ctlr->irq.handle))) {
+ device_printf(dev, "unable to setup interrupt\n");
+ bus_release_resource(dev, SYS_RES_IRQ,
+ ctlr->irq.r_irq_rid, ctlr->irq.r_irq);
+ ctlr->irq.r_irq = 0;
+ return (ENXIO);
+ }
+ return (0);
+}
+
+/*
+ * Common case interrupt handler.
+ */
+static void
+mvs_intr(void *data)
+{
+ struct mvs_controller *ctlr = data;
+ struct mvs_intr_arg arg;
+ void (*function)(void *);
+ int p;
+ u_int32_t ic, aic;
+
+ ic = ATA_INL(ctlr->r_mem, CHIP_SOC_MIC);
+//device_printf(ctlr->dev, "irq MIC:%08x\n", ic);
+ if ((ic & IC_HC0) == 0)
+ return;
+ /* Acknowledge interrupts of this HC. */
+ aic = 0;
+ if (ic & (IC_DONE_IRQ << 0))
+ aic |= HC_IC_DONE(0) | HC_IC_DEV(0);
+ if (ic & (IC_DONE_IRQ << 2))
+ aic |= HC_IC_DONE(1) | HC_IC_DEV(1);
+ if (ic & (IC_DONE_IRQ << 4))
+ aic |= HC_IC_DONE(2) | HC_IC_DEV(2);
+ if (ic & (IC_DONE_IRQ << 6))
+ aic |= HC_IC_DONE(3) | HC_IC_DEV(3);
+ if (ic & IC_HC0_COAL_DONE)
+ aic |= HC_IC_COAL;
+ ATA_OUTL(ctlr->r_mem, HC_IC, ~aic);
+ /* Call per-port interrupt handler. */
+ for (p = 0; p < ctlr->channels; p++) {
+ arg.cause = ic & (IC_ERR_IRQ|IC_DONE_IRQ);
+ if ((arg.cause != 0) &&
+ (function = ctlr->interrupt[p].function)) {
+ arg.arg = ctlr->interrupt[p].argument;
+ function(&arg);
+ }
+ ic >>= 2;
+ }
+}
+
+static struct resource *
+mvs_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int unit = ((struct mvs_channel *)device_get_softc(child))->unit;
+ struct resource *res = NULL;
+ int offset = PORT_BASE(unit & 0x03);
+ long st;
+
+ switch (type) {
+ case SYS_RES_MEMORY:
+ st = rman_get_start(ctlr->r_mem);
+ res = rman_reserve_resource(&ctlr->sc_iomem, st + offset,
+ st + offset + PORT_SIZE - 1, PORT_SIZE, RF_ACTIVE, child);
+ if (res) {
+ bus_space_handle_t bsh;
+ bus_space_tag_t bst;
+ bsh = rman_get_bushandle(ctlr->r_mem);
+ bst = rman_get_bustag(ctlr->r_mem);
+ bus_space_subregion(bst, bsh, offset, PORT_SIZE, &bsh);
+ rman_set_bushandle(res, bsh);
+ rman_set_bustag(res, bst);
+ }
+ break;
+ case SYS_RES_IRQ:
+ if (*rid == ATA_IRQ_RID)
+ res = ctlr->irq.r_irq;
+ break;
+ }
+ return (res);
+}
+
+static int
+mvs_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *r)
+{
+
+ switch (type) {
+ case SYS_RES_MEMORY:
+ rman_release_resource(r);
+ return (0);
+ case SYS_RES_IRQ:
+ if (rid != ATA_IRQ_RID)
+ return ENOENT;
+ return (0);
+ }
+ return (EINVAL);
+}
+
+static int
+mvs_setup_intr(device_t dev, device_t child, struct resource *irq,
+ int flags, driver_filter_t *filter, driver_intr_t *function,
+ void *argument, void **cookiep)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int unit = (intptr_t)device_get_ivars(child);
+
+ if (filter != NULL) {
+ printf("mvs.c: we cannot use a filter here\n");
+ return (EINVAL);
+ }
+ ctlr->interrupt[unit].function = function;
+ ctlr->interrupt[unit].argument = argument;
+ return (0);
+}
+
+static int
+mvs_teardown_intr(device_t dev, device_t child, struct resource *irq,
+ void *cookie)
+{
+ struct mvs_controller *ctlr = device_get_softc(dev);
+ int unit = (intptr_t)device_get_ivars(child);
+
+ ctlr->interrupt[unit].function = NULL;
+ ctlr->interrupt[unit].argument = NULL;
+ return (0);
+}
+
+static int
+mvs_print_child(device_t dev, device_t child)
+{
+ int retval;
+
+ retval = bus_print_child_header(dev, child);
+ retval += printf(" at channel %d",
+ (int)(intptr_t)device_get_ivars(child));
+ retval += bus_print_child_footer(dev, child);
+
+ return (retval);
+}
+
+static device_method_t mvs_methods[] = {
+ DEVMETHOD(device_probe, mvs_probe),
+ DEVMETHOD(device_attach, mvs_attach),
+ DEVMETHOD(device_detach, mvs_detach),
+ DEVMETHOD(device_suspend, mvs_suspend),
+ DEVMETHOD(device_resume, mvs_resume),
+ DEVMETHOD(bus_print_child, mvs_print_child),
+ DEVMETHOD(bus_alloc_resource, mvs_alloc_resource),
+ DEVMETHOD(bus_release_resource, mvs_release_resource),
+ DEVMETHOD(bus_setup_intr, mvs_setup_intr),
+ DEVMETHOD(bus_teardown_intr,mvs_teardown_intr),
+ DEVMETHOD(mvs_edma, mvs_edma),
+ { 0, 0 }
+};
+static driver_t mvs_driver = {
+ "sata",
+ mvs_methods,
+ sizeof(struct mvs_controller)
+};
+DRIVER_MODULE(sata, mbus, mvs_driver, mvs_devclass, 0, 0);
+MODULE_VERSION(sata, 1);
+
diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c
index e4e469b..662f201 100644
--- a/sys/dev/mwl/if_mwl.c
+++ b/sys/dev/mwl/if_mwl.c
@@ -404,8 +404,8 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc)
ifp->if_start = mwl_start;
ifp->if_ioctl = mwl_ioctl;
ifp->if_init = mwl_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
diff --git a/sys/dev/my/if_my.c b/sys/dev/my/if_my.c
index 99f6071..951473a 100644
--- a/sys/dev/my/if_my.c
+++ b/sys/dev/my/if_my.c
@@ -902,8 +902,8 @@ my_attach(device_t dev)
ifp->if_start = my_start;
ifp->if_init = my_init;
ifp->if_baudrate = 10000000;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
if (sc->my_info->my_did == MTD803ID)
diff --git a/sys/dev/nxge/if_nxge.c b/sys/dev/nxge/if_nxge.c
index c86d7b6..0e67413 100644
--- a/sys/dev/nxge/if_nxge.c
+++ b/sys/dev/nxge/if_nxge.c
@@ -1190,7 +1190,7 @@ xge_interface_setup(device_t dev)
ifnetp->if_start = xge_send;
/* TODO: Check and assign optimal value */
- ifnetp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifnetp->if_snd.ifq_maxlen = ifqmaxlen;
ifnetp->if_capabilities = IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU |
IFCAP_HWCSUM;
diff --git a/sys/dev/pdq/pdq_ifsubr.c b/sys/dev/pdq/pdq_ifsubr.c
index ec14150..4df0082 100644
--- a/sys/dev/pdq/pdq_ifsubr.c
+++ b/sys/dev/pdq/pdq_ifsubr.c
@@ -471,7 +471,7 @@ pdq_ifattach(pdq_softc_t *sc, const pdq_uint8_t *llc, pdq_type_t type)
if_initname(ifp, device_get_name(sc->dev), device_get_unit(sc->dev));
ifp->if_softc = sc;
ifp->if_init = pdq_ifinit;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
ifp->if_ioctl = pdq_ifioctl;
diff --git a/sys/dev/ppbus/if_plip.c b/sys/dev/ppbus/if_plip.c
index 3e4c1ca..fc81aec 100644
--- a/sys/dev/ppbus/if_plip.c
+++ b/sys/dev/ppbus/if_plip.c
@@ -262,7 +262,7 @@ lp_attach(device_t dev)
ifp->if_output = lpoutput;
ifp->if_hdrlen = 0;
ifp->if_addrlen = 0;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
if_attach(ifp);
bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
diff --git a/sys/dev/quicc/quicc_bfe.h b/sys/dev/quicc/quicc_bfe.h
index 9ba622c..5c58914 100644
--- a/sys/dev/quicc/quicc_bfe.h
+++ b/sys/dev/quicc/quicc_bfe.h
@@ -50,7 +50,6 @@ struct quicc_softc {
u_int sc_clock;
int sc_fastintr:1;
- int sc_leaving:1;
int sc_polled:1;
};
diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c
index 9549107..8589768 100644
--- a/sys/dev/ral/rt2560.c
+++ b/sys/dev/ral/rt2560.c
@@ -267,8 +267,8 @@ rt2560_attach(device_t dev, int id)
ifp->if_init = rt2560_init;
ifp->if_ioctl = rt2560_ioctl;
ifp->if_start = rt2560_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c
index 9bc8838..9b77c23 100644
--- a/sys/dev/ral/rt2661.c
+++ b/sys/dev/ral/rt2661.c
@@ -269,8 +269,8 @@ rt2661_attach(device_t dev, int id)
ifp->if_init = rt2661_init;
ifp->if_ioctl = rt2661_ioctl;
ifp->if_start = rt2661_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
diff --git a/sys/dev/sbni/if_sbni.c b/sys/dev/sbni/if_sbni.c
index 8c8687c..7ca46d3 100644
--- a/sys/dev/sbni/if_sbni.c
+++ b/sys/dev/sbni/if_sbni.c
@@ -235,7 +235,7 @@ sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
ifp->if_init = sbni_init;
ifp->if_start = sbni_start;
ifp->if_ioctl = sbni_ioctl;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
/* report real baud rate */
csr0 = sbni_inb(sc, CSR0);
diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c
index 6c737bd..ee88cb6 100644
--- a/sys/dev/sge/if_sge.c
+++ b/sys/dev/sge/if_sge.c
@@ -137,6 +137,7 @@ static int sge_get_mac_addr_eeprom(struct sge_softc *, uint8_t *);
static uint16_t sge_read_eeprom(struct sge_softc *, int);
static void sge_rxfilter(struct sge_softc *);
+static void sge_setvlan(struct sge_softc *);
static void sge_reset(struct sge_softc *);
static int sge_list_rx_init(struct sge_softc *);
static int sge_list_rx_free(struct sge_softc *);
@@ -453,8 +454,9 @@ sge_rxfilter(struct sge_softc *sc)
SGE_LOCK_ASSERT(sc);
ifp = sc->sge_ifp;
- hashes[0] = hashes[1] = 0;
- rxfilt = AcceptMyPhys;
+ rxfilt = CSR_READ_2(sc, RxMacControl);
+ rxfilt &= ~(AcceptBroadcast | AcceptAllPhys | AcceptMulticast);
+ rxfilt |= AcceptMyPhys;
if ((ifp->if_flags & IFF_BROADCAST) != 0)
rxfilt |= AcceptBroadcast;
if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) {
@@ -463,26 +465,45 @@ sge_rxfilter(struct sge_softc *sc)
rxfilt |= AcceptMulticast;
hashes[0] = 0xFFFFFFFF;
hashes[1] = 0xFFFFFFFF;
- goto done;
- }
- rxfilt |= AcceptMulticast;
- /* Now program new ones. */
- if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr), ETHER_ADDR_LEN);
- hashes[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
+ } else {
+ rxfilt |= AcceptMulticast;
+ hashes[0] = hashes[1] = 0;
+ /* Now program new ones. */
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
+ ifma->ifma_addr), ETHER_ADDR_LEN);
+ hashes[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
+ }
+ if_maddr_runlock(ifp);
}
- if_maddr_runlock(ifp);
-done:
CSR_WRITE_2(sc, RxMacControl, rxfilt | 0x02);
CSR_WRITE_4(sc, RxHashTable, hashes[0]);
CSR_WRITE_4(sc, RxHashTable2, hashes[1]);
}
static void
+sge_setvlan(struct sge_softc *sc)
+{
+ struct ifnet *ifp;
+ uint16_t rxfilt;
+
+ SGE_LOCK_ASSERT(sc);
+
+ ifp = sc->sge_ifp;
+ if ((ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0)
+ return;
+ rxfilt = CSR_READ_2(sc, RxMacControl);
+ if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0)
+ rxfilt |= RXMAC_STRIP_VLAN;
+ else
+ rxfilt &= ~RXMAC_STRIP_VLAN;
+ CSR_WRITE_2(sc, RxMacControl, rxfilt);
+}
+
+static void
sge_reset(struct sge_softc *sc)
{
@@ -571,7 +592,7 @@ sge_attach(device_t dev)
}
sc->sge_rev = pci_get_revid(dev);
if (pci_get_device(dev) == SIS_DEVICEID_190)
- sc->sge_flags |= SGE_FLAG_FASTETHER;
+ sc->sge_flags |= SGE_FLAG_FASTETHER | SGE_FLAG_SIS190;
/* Reset the adapter. */
sge_reset(sc);
@@ -618,6 +639,9 @@ sge_attach(device_t dev)
ether_ifattach(ifp, eaddr);
/* VLAN setup. */
+ if ((sc->sge_flags & SGE_FLAG_SIS190) == 0)
+ ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING |
+ IFCAP_VLAN_HWCSUM;
ifp->if_capabilities |= IFCAP_VLAN_MTU;
ifp->if_capenable = ifp->if_capabilities;
/* Tell the upper layer(s) we support long frames. */
@@ -732,6 +756,8 @@ sge_dma_alloc(struct sge_softc *sc)
{
struct sge_chain_data *cd;
struct sge_list_data *ld;
+ struct sge_rxdesc *rxd;
+ struct sge_txdesc *txd;
int error, i;
cd = &sc->sge_cdata;
@@ -845,8 +871,12 @@ sge_dma_alloc(struct sge_softc *sc)
/* Create DMA maps for Tx buffers. */
for (i = 0; i < SGE_TX_RING_CNT; i++) {
+ txd = &cd->sge_txdesc[i];
+ txd->tx_m = NULL;
+ txd->tx_dmamap = NULL;
+ txd->tx_ndesc = 0;
error = bus_dmamap_create(cd->sge_txmbuf_tag, 0,
- &cd->sge_tx_map[i]);
+ &txd->tx_dmamap);
if (error != 0) {
device_printf(sc->sge_dev,
"could not create Tx DMA map.\n");
@@ -862,8 +892,11 @@ sge_dma_alloc(struct sge_softc *sc)
}
/* Create DMA maps for Rx buffers. */
for (i = 0; i < SGE_RX_RING_CNT; i++) {
+ rxd = &cd->sge_rxdesc[i];
+ rxd->rx_m = NULL;
+ rxd->rx_dmamap = NULL;
error = bus_dmamap_create(cd->sge_rxmbuf_tag, 0,
- &cd->sge_rx_map[i]);
+ &rxd->rx_dmamap);
if (error) {
device_printf(sc->sge_dev,
"could not create Rx DMA map.\n");
@@ -879,6 +912,8 @@ sge_dma_free(struct sge_softc *sc)
{
struct sge_chain_data *cd;
struct sge_list_data *ld;
+ struct sge_rxdesc *rxd;
+ struct sge_txdesc *txd;
int i;
cd = &sc->sge_cdata;
@@ -910,10 +945,11 @@ sge_dma_free(struct sge_softc *sc)
/* Rx buffers. */
if (cd->sge_rxmbuf_tag != NULL) {
for (i = 0; i < SGE_RX_RING_CNT; i++) {
- if (cd->sge_rx_map[i] != NULL) {
+ rxd = &cd->sge_rxdesc[i];
+ if (rxd->rx_dmamap != NULL) {
bus_dmamap_destroy(cd->sge_rxmbuf_tag,
- cd->sge_rx_map[i]);
- cd->sge_rx_map[i] = NULL;
+ rxd->rx_dmamap);
+ rxd->rx_dmamap = NULL;
}
}
if (cd->sge_rx_spare_map != NULL) {
@@ -927,10 +963,11 @@ sge_dma_free(struct sge_softc *sc)
/* Tx buffers. */
if (cd->sge_txmbuf_tag != NULL) {
for (i = 0; i < SGE_TX_RING_CNT; i++) {
- if (cd->sge_tx_map[i] != NULL) {
+ txd = &cd->sge_txdesc[i];
+ if (txd->tx_dmamap != NULL) {
bus_dmamap_destroy(cd->sge_txmbuf_tag,
- cd->sge_tx_map[i]);
- cd->sge_tx_map[i] = NULL;
+ txd->tx_dmamap);
+ txd->tx_dmamap = NULL;
}
}
bus_dma_tag_destroy(cd->sge_txmbuf_tag);
@@ -967,18 +1004,20 @@ static int
sge_list_tx_free(struct sge_softc *sc)
{
struct sge_chain_data *cd;
+ struct sge_txdesc *txd;
int i;
SGE_LOCK_ASSERT(sc);
cd = &sc->sge_cdata;
for (i = 0; i < SGE_TX_RING_CNT; i++) {
- if (cd->sge_tx_mbuf[i] != NULL) {
- bus_dmamap_sync(cd->sge_txmbuf_tag,
- cd->sge_tx_map[i], BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(cd->sge_txmbuf_tag,
- cd->sge_tx_map[i]);
- m_free(cd->sge_tx_mbuf[i]);
- cd->sge_tx_mbuf[i] = NULL;
+ txd = &cd->sge_txdesc[i];
+ if (txd->tx_m != NULL) {
+ bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap);
+ m_freem(txd->tx_m);
+ txd->tx_m = NULL;
+ txd->tx_ndesc = 0;
}
}
@@ -1013,18 +1052,20 @@ static int
sge_list_rx_free(struct sge_softc *sc)
{
struct sge_chain_data *cd;
+ struct sge_rxdesc *rxd;
int i;
SGE_LOCK_ASSERT(sc);
cd = &sc->sge_cdata;
for (i = 0; i < SGE_RX_RING_CNT; i++) {
- if (cd->sge_rx_mbuf[i] != NULL) {
- bus_dmamap_sync(cd->sge_rxmbuf_tag, cd->sge_rx_map[i],
+ rxd = &cd->sge_rxdesc[i];
+ if (rxd->rx_m != NULL) {
+ bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap,
BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(cd->sge_rxmbuf_tag,
- cd->sge_rx_map[i]);
- m_free(cd->sge_rx_mbuf[i]);
- cd->sge_rx_mbuf[i] = NULL;
+ rxd->rx_dmamap);
+ m_freem(rxd->rx_m);
+ rxd->rx_m = NULL;
}
}
return (0);
@@ -1039,6 +1080,7 @@ sge_newbuf(struct sge_softc *sc, int prod)
struct mbuf *m;
struct sge_desc *desc;
struct sge_chain_data *cd;
+ struct sge_rxdesc *rxd;
bus_dma_segment_t segs[1];
bus_dmamap_t map;
int error, nsegs;
@@ -1058,17 +1100,18 @@ sge_newbuf(struct sge_softc *sc, int prod)
return (error);
}
KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
- if (cd->sge_rx_mbuf[prod] != NULL) {
- bus_dmamap_sync(cd->sge_rxmbuf_tag, cd->sge_rx_map[prod],
+ rxd = &cd->sge_rxdesc[prod];
+ if (rxd->rx_m != NULL) {
+ bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap,
BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(cd->sge_rxmbuf_tag, cd->sge_rx_map[prod]);
+ bus_dmamap_unload(cd->sge_rxmbuf_tag, rxd->rx_dmamap);
}
- map = cd->sge_rx_map[prod];
- cd->sge_rx_map[prod] = cd->sge_rx_spare_map;
+ map = rxd->rx_dmamap;
+ rxd->rx_dmamap = cd->sge_rx_spare_map;
cd->sge_rx_spare_map = map;
- bus_dmamap_sync(cd->sge_rxmbuf_tag, cd->sge_rx_map[prod],
+ bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap,
BUS_DMASYNC_PREREAD);
- cd->sge_rx_mbuf[prod] = m;
+ rxd->rx_m = m;
desc = &sc->sge_ldata.sge_rx_ring[prod];
desc->sge_sts_size = 0;
@@ -1143,7 +1186,8 @@ sge_rxeof(struct sge_softc *sc)
if ((rxinfo & RDC_OWN) != 0)
break;
rxstat = le32toh(cur_rx->sge_sts_size);
- if (SGE_RX_ERROR(rxstat) != 0 || SGE_RX_NSEGS(rxstat) != 1) {
+ if ((rxstat & RDS_CRCOK) == 0 || SGE_RX_ERROR(rxstat) != 0 ||
+ SGE_RX_NSEGS(rxstat) != 1) {
/* XXX We don't support multi-segment frames yet. */
#ifdef SGE_SHOW_ERRORS
device_printf(sc->sge_dev, "Rx error : 0x%b\n", rxstat,
@@ -1153,7 +1197,7 @@ sge_rxeof(struct sge_softc *sc)
ifp->if_ierrors++;
continue;
}
- m = cd->sge_rx_mbuf[cons];
+ m = cd->sge_rxdesc[cons].rx_m;
if (sge_newbuf(sc, cons) != 0) {
sge_discard_rxbuf(sc, cons);
ifp->if_iqdrops++;
@@ -1173,14 +1217,29 @@ sge_rxeof(struct sge_softc *sc)
m->m_pkthdr.csum_data = 0xffff;
}
}
- /*
- * TODO : VLAN hardware tag stripping.
- */
- m->m_pkthdr.len = m->m_len =
- SGE_RX_BYTES(rxstat) - ETHER_CRC_LEN;
+ /* Check for VLAN tagged frame. */
+ if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 &&
+ (rxstat & RDS_VLAN) != 0) {
+ m->m_pkthdr.ether_vtag = rxinfo & RDC_VLAN_MASK;
+ m->m_flags |= M_VLANTAG;
+ }
+ if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) {
+ /*
+ * Account for 10bytes auto padding which is used
+ * to align IP header on 32bit boundary. Also note,
+ * CRC bytes is automatically removed by the
+ * hardware.
+ */
+ m->m_data += SGE_RX_PAD_BYTES;
+ m->m_pkthdr.len = m->m_len = SGE_RX_BYTES(rxstat) -
+ SGE_RX_PAD_BYTES;
+ } else {
+ m->m_pkthdr.len = m->m_len = SGE_RX_BYTES(rxstat) -
+ ETHER_CRC_LEN;
#ifndef __NO_STRICT_ALIGNMENT
- sge_fixup_rx(m);
+ sge_fixup_rx(m);
#endif
+ }
m->m_pkthdr.rcvif = ifp;
ifp->if_ipackets++;
SGE_UNLOCK(sc);
@@ -1205,8 +1264,9 @@ sge_txeof(struct sge_softc *sc)
struct ifnet *ifp;
struct sge_list_data *ld;
struct sge_chain_data *cd;
+ struct sge_txdesc *txd;
uint32_t txstat;
- int cons, prod;
+ int cons, nsegs, prod;
SGE_LOCK_ASSERT(sc);
@@ -1220,33 +1280,47 @@ sge_txeof(struct sge_softc *sc)
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
cons = cd->sge_tx_cons;
prod = cd->sge_tx_prod;
- for (; cons != prod; SGE_INC(cons, SGE_TX_RING_CNT)) {
+ for (; cons != prod;) {
txstat = le32toh(ld->sge_tx_ring[cons].sge_cmdsts);
if ((txstat & TDC_OWN) != 0)
break;
- cd->sge_tx_cnt--;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- if (cd->sge_tx_mbuf[cons] != NULL) {
- bus_dmamap_sync(cd->sge_txmbuf_tag,
- cd->sge_tx_map[cons], BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(cd->sge_txmbuf_tag,
- cd->sge_tx_map[cons]);
- m_freem(cd->sge_tx_mbuf[cons]);
- cd->sge_tx_mbuf[cons] = NULL;
- if (SGE_TX_ERROR(txstat) != 0) {
+ /*
+ * Only the first descriptor of multi-descriptor transmission
+ * is updated by controller. Driver should skip entire
+ * chained buffers for the transmitted frame. In other words
+ * TDC_OWN bit is valid only at the first descriptor of a
+ * multi-descriptor transmission.
+ */
+ if (SGE_TX_ERROR(txstat) != 0) {
#ifdef SGE_SHOW_ERRORS
- device_printf(sc->sge_dev, "Tx error : 0x%b\n",
- txstat, TX_ERR_BITS);
+ device_printf(sc->sge_dev, "Tx error : 0x%b\n",
+ txstat, TX_ERR_BITS);
#endif
- ifp->if_oerrors++;
- } else {
+ ifp->if_oerrors++;
+ } else {
#ifdef notyet
- ifp->if_collisions += (txstat & 0xFFFF) - 1;
+ ifp->if_collisions += (txstat & 0xFFFF) - 1;
#endif
- ifp->if_opackets++;
- }
+ ifp->if_opackets++;
}
-
+ txd = &cd->sge_txdesc[cons];
+ for (nsegs = 0; nsegs < txd->tx_ndesc; nsegs++) {
+ ld->sge_tx_ring[cons].sge_cmdsts = 0;
+ SGE_INC(cons, SGE_TX_RING_CNT);
+ }
+ /* Reclaim transmitted mbuf. */
+ KASSERT(txd->tx_m != NULL,
+ ("%s: freeing NULL mbuf\n", __func__));
+ bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap);
+ m_freem(txd->tx_m);
+ txd->tx_m = NULL;
+ cd->sge_tx_cnt -= txd->tx_ndesc;
+ KASSERT(cd->sge_tx_cnt >= 0,
+ ("%s: Active Tx desc counter was garbled\n", __func__));
+ txd->tx_ndesc = 0;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
cd->sge_tx_cons = cons;
if (cd->sge_tx_cnt == 0)
@@ -1348,67 +1422,78 @@ sge_encap(struct sge_softc *sc, struct mbuf **m_head)
{
struct mbuf *m;
struct sge_desc *desc;
+ struct sge_txdesc *txd;
bus_dma_segment_t txsegs[SGE_MAXTXSEGS];
- bus_dmamap_t map;
uint32_t cflags;
- int error, nsegs, prod;
+ int error, i, nsegs, prod, si;
SGE_LOCK_ASSERT(sc);
- prod = sc->sge_cdata.sge_tx_prod;
- map = sc->sge_cdata.sge_tx_map[prod];
- /*
- * Reading Windows inf file indicates SiS controller supports
- * TSO, VLAN hardware tag insertion/stripping, interrupt
- * moderation and Tx/Rx checksum offloading. Unfortunately
- * vendor didn't release these information so we're guessing
- * descriptor usage with trial and errors.
- *
- * Controller seems to support multi-fragmented buffers but
- * don't know how to enable that feature so limit number of
- * fragmented Tx buffers to single buffer until we understand
- * the controller internals.
- * I assume the controller can pad zero bytes if frame length
- * is less than 60 bytes and I also think the controller has
- * no Tx buffer alignment limitation. - Need testing!
- */
- if ((*m_head)->m_next != NULL) {
- m = m_defrag(*m_head, M_DONTWAIT);
+ si = prod = sc->sge_cdata.sge_tx_prod;
+ txd = &sc->sge_cdata.sge_txdesc[prod];
+ error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag,
+ txd->tx_dmamap, *m_head, txsegs, &nsegs, 0);
+ if (error == EFBIG) {
+ m = m_collapse(*m_head, M_DONTWAIT, SGE_MAXTXSEGS);
if (m == NULL) {
m_freem(*m_head);
*m_head = NULL;
return (ENOBUFS);
}
*m_head = m;
- }
- error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_tx_tag, map,
- *m_head, txsegs, &nsegs, 0);
- if (error != 0) {
- m_freem(*m_head);
- *m_head = NULL;
+ error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag,
+ txd->tx_dmamap, *m_head, txsegs, &nsegs, 0);
+ if (error != 0) {
+ m_freem(*m_head);
+ *m_head = NULL;
+ return (error);
+ }
+ } else if (error != 0)
return (error);
- }
+
+ KASSERT(nsegs != 0, ("zero segment returned"));
/* Check descriptor overrun. */
if (sc->sge_cdata.sge_tx_cnt + nsegs >= SGE_TX_RING_CNT) {
- bus_dmamap_unload(sc->sge_cdata.sge_tx_tag, map);
+ bus_dmamap_unload(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap);
return (ENOBUFS);
}
- bus_dmamap_sync(sc->sge_cdata.sge_tx_tag, map, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap,
+ BUS_DMASYNC_PREWRITE);
+ m = *m_head;
cflags = 0;
- if ((*m_head)->m_pkthdr.csum_flags & CSUM_IP)
+ if (m->m_pkthdr.csum_flags & CSUM_IP)
cflags |= TDC_IP_CSUM;
- if ((*m_head)->m_pkthdr.csum_flags & CSUM_TCP)
+ if (m->m_pkthdr.csum_flags & CSUM_TCP)
cflags |= TDC_TCP_CSUM;
- if ((*m_head)->m_pkthdr.csum_flags & CSUM_UDP)
+ if (m->m_pkthdr.csum_flags & CSUM_UDP)
cflags |= TDC_UDP_CSUM;
- desc = &sc->sge_ldata.sge_tx_ring[prod];
- desc->sge_sts_size = htole32((*m_head)->m_pkthdr.len);
- desc->sge_ptr = htole32(SGE_ADDR_LO(txsegs[0].ds_addr));
- desc->sge_flags = htole32(txsegs[0].ds_len);
- if (prod == SGE_TX_RING_CNT - 1)
- desc->sge_flags |= htole32(RING_END);
- desc->sge_cmdsts = htole32(TDC_DEF | TDC_CRC | TDC_PAD | cflags);
+ for (i = 0; i < nsegs; i++) {
+ desc = &sc->sge_ldata.sge_tx_ring[prod];
+ if (i == 0) {
+ desc->sge_sts_size = htole32(m->m_pkthdr.len);
+ desc->sge_cmdsts = 0;
+ } else {
+ desc->sge_sts_size = 0;
+ desc->sge_cmdsts = htole32(TDC_OWN);
+ }
+ desc->sge_ptr = htole32(SGE_ADDR_LO(txsegs[i].ds_addr));
+ desc->sge_flags = htole32(txsegs[i].ds_len);
+ if (prod == SGE_TX_RING_CNT - 1)
+ desc->sge_flags |= htole32(RING_END);
+ sc->sge_cdata.sge_tx_cnt++;
+ SGE_INC(prod, SGE_TX_RING_CNT);
+ }
+ /* Update producer index. */
+ sc->sge_cdata.sge_tx_prod = prod;
+
+ desc = &sc->sge_ldata.sge_tx_ring[si];
+ /* Configure VLAN. */
+ if((m->m_flags & M_VLANTAG) != 0) {
+ cflags |= m->m_pkthdr.ether_vtag;
+ desc->sge_sts_size |= htole32(TDS_INS_VLAN);
+ }
+ desc->sge_cmdsts |= htole32(TDC_DEF | TDC_CRC | TDC_PAD | cflags);
#if 1
if ((sc->sge_flags & SGE_FLAG_SPEED_1000) != 0)
desc->sge_cmdsts |= htole32(TDC_BST);
@@ -1420,13 +1505,9 @@ sge_encap(struct sge_softc *sc, struct mbuf **m_head)
}
#endif
/* Request interrupt and give ownership to controller. */
- if ((prod % SGE_TX_INTR_FRAMES) == 0)
- desc->sge_cmdsts |= htole32(TDC_OWN | TDC_INTR);
- else
- desc->sge_cmdsts |= htole32(TDC_OWN);
- sc->sge_cdata.sge_tx_mbuf[prod] = *m_head;
- sc->sge_cdata.sge_tx_cnt++;
- SGE_INC(sc->sge_cdata.sge_tx_prod, SGE_TX_RING_CNT);
+ desc->sge_cmdsts |= htole32(TDC_OWN | TDC_INTR);
+ txd->tx_m = m;
+ txd->tx_ndesc = nsegs;
return (0);
}
@@ -1457,7 +1538,8 @@ sge_start_locked(struct ifnet *ifp)
return;
for (queued = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) {
- if (sc->sge_cdata.sge_tx_cnt == SGE_TX_RING_CNT - 1) {
+ if (sc->sge_cdata.sge_tx_cnt > (SGE_TX_RING_CNT -
+ SGE_MAXTXSEGS)) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
@@ -1502,6 +1584,7 @@ sge_init_locked(struct sge_softc *sc)
{
struct ifnet *ifp;
struct mii_data *mii;
+ uint16_t rxfilt;
int i;
SGE_LOCK_ASSERT(sc);
@@ -1530,15 +1613,24 @@ sge_init_locked(struct sge_softc *sc)
CSR_WRITE_4(sc, RX_DESC, SGE_ADDR_LO(sc->sge_ldata.sge_rx_paddr));
CSR_WRITE_4(sc, TxMacControl, 0x60);
- CSR_WRITE_4(sc, 0x6c, 0);
CSR_WRITE_4(sc, RxWakeOnLan, 0);
CSR_WRITE_4(sc, RxWakeOnLanData, 0);
/* Allow receiving VLAN frames. */
- CSR_WRITE_2(sc, RxMPSControl, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
+ if ((sc->sge_flags & SGE_FLAG_SIS190) == 0)
+ CSR_WRITE_2(sc, RxMPSControl,
+ ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN + SGE_RX_PAD_BYTES);
+ else
+ CSR_WRITE_2(sc, RxMPSControl, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
for (i = 0; i < ETHER_ADDR_LEN; i++)
CSR_WRITE_1(sc, RxMacAddr + i, IF_LLADDR(ifp)[i]);
+ /* Configure RX MAC. */
+ rxfilt = 0;
+ if ((sc->sge_flags & SGE_FLAG_SIS190) == 0)
+ rxfilt |= RXMAC_STRIP_FCS | RXMAC_PAD_ENB;
+ CSR_WRITE_2(sc, RxMacControl, rxfilt);
sge_rxfilter(sc);
+ sge_setvlan(sc);
/* Initialize default speed/duplex information. */
if ((sc->sge_flags & SGE_FLAG_FASTETHER) == 0)
@@ -1590,7 +1682,6 @@ sge_ifmedia_upd(struct ifnet *ifp)
sc = ifp->if_softc;
SGE_LOCK(sc);
mii = device_get_softc(sc->sge_miibus);
- sc->sge_flags &= ~SGE_FLAG_LINK;
if (mii->mii_instance) {
struct mii_softc *miisc;
LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
@@ -1630,7 +1721,7 @@ sge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct sge_softc *sc;
struct ifreq *ifr;
struct mii_data *mii;
- int error = 0, mask;
+ int error = 0, mask, reinit;
sc = ifp->if_softc;
ifr = (struct ifreq *)data;
@@ -1652,6 +1743,7 @@ sge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
break;
case SIOCSIFCAP:
SGE_LOCK(sc);
+ reinit = 0;
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
if ((mask & IFCAP_TXCSUM) != 0 &&
(ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
@@ -1664,7 +1756,24 @@ sge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if ((mask & IFCAP_RXCSUM) != 0 &&
(ifp->if_capabilities & IFCAP_RXCSUM) != 0)
ifp->if_capenable ^= IFCAP_RXCSUM;
+ if ((mask & IFCAP_VLAN_HWCSUM) != 0 &&
+ (ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0)
+ ifp->if_capenable ^= IFCAP_VLAN_HWCSUM;
+ if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
+ (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) {
+ /*
+ * Due to unknown reason, toggling VLAN hardware
+ * tagging require interface reinitialization.
+ */
+ ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
+ reinit = 1;
+ }
+ if (reinit > 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ sge_init_locked(sc);
+ }
SGE_UNLOCK(sc);
+ VLAN_CAPABILITIES(ifp);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
diff --git a/sys/dev/sge/if_sgereg.h b/sys/dev/sge/if_sgereg.h
index 29253e0..c06072c 100644
--- a/sys/dev/sge/if_sgereg.h
+++ b/sys/dev/sge/if_sgereg.h
@@ -137,6 +137,11 @@
#define AcceptAllPhys 0x0100
#define AcceptErr 0x0020
#define AcceptRunt 0x0010
+#define RXMAC_STRIP_VLAN 0x0020
+#define RXMAC_STRIP_FCS 0x0010
+#define RXMAC_PAD_ENB 0x0004
+
+#define SGE_RX_PAD_BYTES 10
/* Station control register. */
#define SC_LOOPBACK 0x80000000
@@ -183,12 +188,14 @@
#define TDC_COL 0x00040000
#define TDC_CRC 0x00020000
#define TDC_PAD 0x00010000
+#define TDC_VLAN_MASK 0x0000FFFF
#define SGE_TX_INTR_FRAMES 32
/*
* TX descriptor status bits.
*/
+#define TDS_INS_VLAN 0x80000000
#define TDS_OWC 0x00080000
#define TDS_ABT 0x00040000
#define TDS_FIFO 0x00020000
@@ -215,11 +222,12 @@
#define RDC_UCAST 0x00040000
#define RDC_CRCOFF 0x00020000
#define RDC_PREADD 0x00010000
+#define RDC_VLAN_MASK 0x0000FFFF
/*
* RX descriptor status bits
*/
-#define RDS_TAGON 0x80000000
+#define RDS_VLAN 0x80000000
#define RDS_DESCS 0x3f000000
#define RDS_ABORT 0x00800000
#define RDS_SHORT 0x00400000
@@ -236,7 +244,7 @@
#define RX_ERR_BITS "\20" \
"\21CRCOK\22COLON\23NIBON\24OVRUN" \
"\25MIIER\26LIMIT\27SHORT\30ABORT" \
- "\40TAGON"
+ "\40VLAN"
#define RING_END 0x80000000
#define SGE_RX_BYTES(x) ((x) & 0xFFFF)
@@ -275,7 +283,7 @@ struct sge_desc {
#define SGE_RX_RING_CNT 256 /* [8, 1024] */
#define SGE_TX_RING_CNT 256 /* [8, 8192] */
#define SGE_DESC_ALIGN 16
-#define SGE_MAXTXSEGS 1
+#define SGE_MAXTXSEGS 16
#define SGE_RX_BUF_ALIGN sizeof(uint64_t)
#define SGE_RX_RING_SZ (SGE_RX_RING_CNT * sizeof(struct sge_desc))
@@ -290,6 +298,17 @@ struct sge_list_data {
bus_addr_t sge_tx_paddr;
};
+struct sge_txdesc {
+ struct mbuf *tx_m;
+ bus_dmamap_t tx_dmamap;
+ int tx_ndesc;
+};
+
+struct sge_rxdesc {
+ struct mbuf *rx_m;
+ bus_dmamap_t rx_dmamap;
+};
+
struct sge_chain_data {
bus_dma_tag_t sge_tag;
bus_dma_tag_t sge_rx_tag;
@@ -298,11 +317,9 @@ struct sge_chain_data {
bus_dmamap_t sge_tx_dmamap;
bus_dma_tag_t sge_txmbuf_tag;
bus_dma_tag_t sge_rxmbuf_tag;
- struct mbuf *sge_rx_mbuf[SGE_RX_RING_CNT];
- struct mbuf *sge_tx_mbuf[SGE_TX_RING_CNT];
- bus_dmamap_t sge_rx_map[SGE_RX_RING_CNT];
+ struct sge_txdesc sge_txdesc[SGE_TX_RING_CNT];
+ struct sge_rxdesc sge_rxdesc[SGE_RX_RING_CNT];
bus_dmamap_t sge_rx_spare_map;
- bus_dmamap_t sge_tx_map[SGE_TX_RING_CNT];
int sge_rx_cons;
int sge_tx_prod;
int sge_tx_cons;
@@ -331,6 +348,7 @@ struct sge_softc {
int sge_timer;
int sge_flags;
#define SGE_FLAG_FASTETHER 0x0001
+#define SGE_FLAG_SIS190 0x0002
#define SGE_FLAG_RGMII 0x0010
#define SGE_FLAG_SPEED_1000 0x2000
#define SGE_FLAG_FDX 0x4000
diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c
index c9c1572..937d04c 100644
--- a/sys/dev/siis/siis.c
+++ b/sys/dev/siis/siis.c
@@ -448,6 +448,8 @@ siis_ch_attach(device_t dev)
ch->user[i].bytecount = 8192;
ch->user[i].tags = SIIS_MAX_SLOTS;
ch->curr[i] = ch->user[i];
+ if (ch->pm_level)
+ ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ;
}
mtx_init(&ch->mtx, "SIIS channel lock", NULL, MTX_DEF);
rid = ch->unit;
@@ -1610,6 +1612,23 @@ siis_sata_connect(struct siis_channel *ch)
return (1);
}
+static int
+siis_check_ids(device_t dev, union ccb *ccb)
+{
+
+ if (ccb->ccb_h.target_id > 15) {
+ ccb->ccb_h.status = CAM_TID_INVALID;
+ xpt_done(ccb);
+ return (-1);
+ }
+ if (ccb->ccb_h.target_lun != 0) {
+ ccb->ccb_h.status = CAM_LUN_INVALID;
+ xpt_done(ccb);
+ return (-1);
+ }
+ return (0);
+}
+
static void
siisaction(struct cam_sim *sim, union ccb *ccb)
{
@@ -1626,9 +1645,12 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
/* Common cases first */
case XPT_ATA_IO: /* Execute the requested I/O operation */
case XPT_SCSI_IO:
- if (ch->devices == 0) {
+ if (siis_check_ids(dev, ccb))
+ return;
+ if (ch->devices == 0 ||
+ (ch->pm_present == 0 &&
+ ccb->ccb_h.target_id > 0 && ccb->ccb_h.target_id < 15)) {
ccb->ccb_h.status = CAM_SEL_TIMEOUT;
- xpt_done(ccb);
break;
}
/* Check for command collision. */
@@ -1640,7 +1662,7 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
return;
}
siis_begin_transaction(dev, ccb);
- break;
+ return;
case XPT_EN_LUN: /* Enable LUN as a target */
case XPT_TARGET_IO: /* Execute target I/O request */
case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
@@ -1648,13 +1670,14 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
case XPT_ABORT: /* Abort the specified CCB */
/* XXX Implement */
ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
break;
case XPT_SET_TRAN_SETTINGS:
{
struct ccb_trans_settings *cts = &ccb->cts;
struct siis_device *d;
+ if (siis_check_ids(dev, ccb))
+ return;
if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
d = &ch->curr[ccb->ccb_h.target_id];
else
@@ -1676,8 +1699,9 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
}
if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS)
d->atapi = cts->xport_specific.sata.atapi;
+ if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
+ d->caps = cts->xport_specific.sata.caps;
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
}
case XPT_GET_TRAN_SETTINGS:
@@ -1687,6 +1711,8 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
struct siis_device *d;
uint32_t status;
+ if (siis_check_ids(dev, ccb))
+ return;
if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
d = &ch->curr[ccb->ccb_h.target_id];
else
@@ -1707,9 +1733,17 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
cts->xport_specific.sata.valid |=
CTS_SATA_VALID_REVISION;
}
+ cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
+ if (ch->pm_level)
+ cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
+ cts->xport_specific.sata.caps &=
+ ch->user[ccb->ccb_h.target_id].caps;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
} else {
cts->xport_specific.sata.revision = d->revision;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
+ cts->xport_specific.sata.caps = d->caps;
+ cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
}
cts->xport_specific.sata.mode = d->mode;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE;
@@ -1722,48 +1756,16 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
cts->xport_specific.sata.atapi = d->atapi;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI;
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
}
-#if 0
- case XPT_CALC_GEOMETRY:
- {
- struct ccb_calc_geometry *ccg;
- uint32_t size_mb;
- uint32_t secs_per_cylinder;
-
- ccg = &ccb->ccg;
- size_mb = ccg->volume_size
- / ((1024L * 1024L) / ccg->block_size);
- if (size_mb >= 1024 && (aha->extended_trans != 0)) {
- if (size_mb >= 2048) {
- ccg->heads = 255;
- ccg->secs_per_track = 63;
- } else {
- ccg->heads = 128;
- ccg->secs_per_track = 32;
- }
- } else {
- ccg->heads = 64;
- ccg->secs_per_track = 32;
- }
- secs_per_cylinder = ccg->heads * ccg->secs_per_track;
- ccg->cylinders = ccg->volume_size / secs_per_cylinder;
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
- }
-#endif
case XPT_RESET_BUS: /* Reset the specified SCSI bus */
case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
siis_reset(dev);
ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
break;
case XPT_TERM_IO: /* Terminate the I/O process */
/* XXX Implement */
ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
break;
case XPT_PATH_INQ: /* Path routing inquiry */
{
@@ -1790,14 +1792,13 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
cpi->ccb_h.status = CAM_REQ_CMP;
cpi->maxio = MAXPHYS;
- xpt_done(ccb);
break;
}
default:
ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
break;
}
+ xpt_done(ccb);
}
static void
diff --git a/sys/dev/siis/siis.h b/sys/dev/siis/siis.h
index 92b4e26..5317628 100644
--- a/sys/dev/siis/siis.h
+++ b/sys/dev/siis/siis.h
@@ -358,6 +358,7 @@ struct siis_device {
u_int bytecount;
u_int atapi;
u_int tags;
+ u_int caps;
};
/* structure describing an ATA channel */
diff --git a/sys/dev/smc/if_smc.c b/sys/dev/smc/if_smc.c
index f7f5407..6d9ba59 100644
--- a/sys/dev/smc/if_smc.c
+++ b/sys/dev/smc/if_smc.c
@@ -347,7 +347,7 @@ smc_attach(device_t dev)
ifp->if_init = smc_init;
ifp->if_ioctl = smc_ioctl;
ifp->if_start = smc_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
IFQ_SET_READY(&ifp->if_snd);
ifp->if_capabilities = ifp->if_capenable = 0;
diff --git a/sys/dev/sn/if_sn.c b/sys/dev/sn/if_sn.c
index 217d811..0f86f92 100644
--- a/sys/dev/sn/if_sn.c
+++ b/sys/dev/sn/if_sn.c
@@ -207,8 +207,8 @@ sn_attach(device_t dev)
ifp->if_ioctl = snioctl;
ifp->if_init = sninit;
ifp->if_baudrate = 10000000;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ether_ifattach(ifp, eaddr);
diff --git a/sys/dev/snc/dp83932.c b/sys/dev/snc/dp83932.c
index c659c82..0b62053 100644
--- a/sys/dev/snc/dp83932.c
+++ b/sys/dev/snc/dp83932.c
@@ -177,7 +177,7 @@ sncconfig(sc, media, nmedia, defmedia, myea)
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = sncinit;
ifp->if_mtu = ETHERMTU;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
/* Initialize media goo. */
ifmedia_init(&sc->sc_media, 0, snc_mediachange,
diff --git a/sys/dev/sound/pcm/buffer.c b/sys/dev/sound/pcm/buffer.c
index 6e82592..687542e 100644
--- a/sys/dev/sound/pcm/buffer.c
+++ b/sys/dev/sound/pcm/buffer.c
@@ -566,30 +566,6 @@ sndbuf_updateprevtotal(struct snd_dbuf *b)
}
unsigned int
-snd_xbytes(unsigned int v, unsigned int from, unsigned int to)
-{
- unsigned int w, x, y;
-
- if (from == to)
- return v;
-
- if (from == 0 || to == 0 || v == 0)
- return 0;
-
- x = from;
- y = to;
- while (y != 0) {
- w = x % y;
- x = y;
- y = w;
- }
- from /= x;
- to /= x;
-
- return (unsigned int)(((u_int64_t)v * to) / from);
-}
-
-unsigned int
sndbuf_xbytes(unsigned int v, struct snd_dbuf *from, struct snd_dbuf *to)
{
if (from == NULL || to == NULL || v == 0)
diff --git a/sys/dev/sound/pcm/buffer.h b/sys/dev/sound/pcm/buffer.h
index 91a63af..d079cdb 100644
--- a/sys/dev/sound/pcm/buffer.h
+++ b/sys/dev/sound/pcm/buffer.h
@@ -111,7 +111,6 @@ u_int64_t sndbuf_getblocks(struct snd_dbuf *b);
u_int64_t sndbuf_getprevblocks(struct snd_dbuf *b);
u_int64_t sndbuf_gettotal(struct snd_dbuf *b);
u_int64_t sndbuf_getprevtotal(struct snd_dbuf *b);
-unsigned int snd_xbytes(unsigned int v, unsigned int from, unsigned int to);
unsigned int sndbuf_xbytes(unsigned int v, struct snd_dbuf *from, struct snd_dbuf *to);
u_int8_t sndbuf_zerodata(u_int32_t fmt);
void sndbuf_updateprevtotal(struct snd_dbuf *b);
@@ -132,3 +131,14 @@ void sndbuf_dmabounce(struct snd_dbuf *b);
#ifdef OSSV4_EXPERIMENT
void sndbuf_getpeaks(struct snd_dbuf *b, int *lp, int *rp);
#endif
+
+static inline u_int32_t
+snd_xbytes(u_int32_t v, u_int32_t from, u_int32_t to)
+{
+
+ if (from == to)
+ return (v);
+ if (from == 0)
+ return (0);
+ return ((u_int64_t)v * to / from);
+}
diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c
index a43c816..5050a5f 100644
--- a/sys/dev/sym/sym_hipd.c
+++ b/sys/dev/sym/sym_hipd.c
@@ -87,6 +87,12 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
+
+#ifdef __sparc64__
+#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
+#endif
+
#include <sys/rman.h>
#include <cam/cam.h>
@@ -98,10 +104,6 @@ __FBSDID("$FreeBSD$");
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
/* Short and quite clear integer types */
typedef int8_t s8;
typedef int16_t s16;
@@ -2682,6 +2684,9 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
*/
np->myaddr = 255;
sym_nvram_setup_host (np, nvram);
+#ifdef __sparc64__
+ np->myaddr = OF_getscsinitid(np->device);
+#endif
/*
* Get SCSI addr of host adapter (set by bios?).
diff --git a/sys/dev/ti/if_ti.c b/sys/dev/ti/if_ti.c
index 20130bc..7eeee36 100644
--- a/sys/dev/ti/if_ti.c
+++ b/sys/dev/ti/if_ti.c
@@ -1488,10 +1488,8 @@ ti_newbuf_jumbo(sc, idx, m_old)
}
sf[i] = sf_buf_alloc(frame, SFB_NOWAIT);
if (sf[i] == NULL) {
- vm_page_lock_queues();
vm_page_unwire(frame, 0);
vm_page_free(frame);
- vm_page_unlock_queues();
device_printf(sc->ti_dev, "buffer allocation "
"failed -- packet dropped!\n");
printf(" index %d page %d\n", idx, i);
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index c01fd61..b93e254 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -604,7 +604,7 @@ ns8250_bus_ipend(struct uart_softc *sc)
if (ipend == 0)
ns8250_clrint(bas);
uart_unlock(sc->sc_hwmtx);
- return ((sc->sc_leaving) ? 0 : ipend);
+ return (ipend);
}
static int
diff --git a/sys/dev/usb/net/uhso.c b/sys/dev/usb/net/uhso.c
index a810ec4..21a23c9 100644
--- a/sys/dev/usb/net/uhso.c
+++ b/sys/dev/usb/net/uhso.c
@@ -1471,8 +1471,8 @@ static int uhso_attach_ifnet(struct uhso_softc *sc, struct usb_interface *iface,
ifp->if_output = uhso_if_output;
ifp->if_flags = 0;
ifp->if_softc = sc;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
if_attach(ifp);
diff --git a/sys/dev/usb/net/usb_ethernet.c b/sys/dev/usb/net/usb_ethernet.c
index 6cf4460..bd75cef 100644
--- a/sys/dev/usb/net/usb_ethernet.c
+++ b/sys/dev/usb/net/usb_ethernet.c
@@ -214,8 +214,8 @@ ue_attach_post_task(struct usb_proc_msg *_task)
ifp->if_ioctl = uether_ioctl;
ifp->if_start = ue_start;
ifp->if_init = ue_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ue->ue_ifp = ifp;
diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c
index 4a5fbae..155b767 100644
--- a/sys/dev/usb/wlan/if_rum.c
+++ b/sys/dev/usb/wlan/if_rum.c
@@ -478,8 +478,8 @@ rum_attach(device_t self)
ifp->if_init = rum_init;
ifp->if_ioctl = rum_ioctl;
ifp->if_start = rum_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c
index 3ab607f..c798c32 100644
--- a/sys/dev/usb/wlan/if_run.c
+++ b/sys/dev/usb/wlan/if_run.c
@@ -609,8 +609,8 @@ run_attach(device_t self)
ifp->if_init = run_init;
ifp->if_ioctl = run_ioctl;
ifp->if_start = run_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c
index 7838d5a..40b7c83 100644
--- a/sys/dev/usb/wlan/if_uath.c
+++ b/sys/dev/usb/wlan/if_uath.c
@@ -438,8 +438,8 @@ uath_attach(device_t dev)
ifp->if_ioctl = uath_ioctl;
ifp->if_start = uath_start;
/* XXX UATH_TX_DATA_LIST_COUNT */
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic = ifp->if_l2com;
diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c
index 20f06c6..091b9df 100644
--- a/sys/dev/usb/wlan/if_upgt.c
+++ b/sys/dev/usb/wlan/if_upgt.c
@@ -331,7 +331,7 @@ upgt_attach(device_t dev)
ifp->if_init = upgt_init;
ifp->if_ioctl = upgt_ioctl;
ifp->if_start = upgt_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
IFQ_SET_READY(&ifp->if_snd);
ic = ifp->if_l2com;
diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c
index 4a4378b..6839bcf 100644
--- a/sys/dev/usb/wlan/if_ural.c
+++ b/sys/dev/usb/wlan/if_ural.c
@@ -467,8 +467,8 @@ ural_attach(device_t self)
ifp->if_init = ural_init;
ifp->if_ioctl = ural_ioctl;
ifp->if_start = ural_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c
index 6604268..9ff16f3 100644
--- a/sys/dev/usb/wlan/if_urtw.c
+++ b/sys/dev/usb/wlan/if_urtw.c
@@ -867,8 +867,8 @@ urtw_attach(device_t dev)
ifp->if_ioctl = urtw_ioctl;
ifp->if_start = urtw_start;
/* XXX URTW_TX_DATA_LIST_COUNT */
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic = ifp->if_l2com;
diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c
index a0b8179..1a298f8 100644
--- a/sys/dev/usb/wlan/if_zyd.c
+++ b/sys/dev/usb/wlan/if_zyd.c
@@ -381,7 +381,7 @@ zyd_attach(device_t dev)
ifp->if_init = zyd_init;
ifp->if_ioctl = zyd_ioctl;
ifp->if_start = zyd_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
IFQ_SET_READY(&ifp->if_snd);
ic = ifp->if_l2com;
diff --git a/sys/dev/vx/if_vx.c b/sys/dev/vx/if_vx.c
index 0dea9bf..1ea0faf 100644
--- a/sys/dev/vx/if_vx.c
+++ b/sys/dev/vx/if_vx.c
@@ -189,7 +189,7 @@ vx_attach(device_t dev)
}
ifp->if_mtu = ETHERMTU;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_start = vx_start;
ifp->if_ioctl = vx_ioctl;
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index 616c5d7..fe0d903 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -333,8 +333,8 @@ wi_attach(device_t dev)
ifp->if_ioctl = wi_ioctl;
ifp->if_start = wi_start;
ifp->if_init = wi_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
diff --git a/sys/dev/wl/if_wl.c b/sys/dev/wl/if_wl.c
index ed291ed..a95997e 100644
--- a/sys/dev/wl/if_wl.c
+++ b/sys/dev/wl/if_wl.c
@@ -559,7 +559,7 @@ wlattach(device_t device)
ifp->if_init = wlinit;
ifp->if_start = wlstart;
ifp->if_ioctl = wlioctl;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
/* no entries
ifp->if_done
ifp->if_reset
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c
index 9bf9342..f6edc91 100644
--- a/sys/dev/wpi/if_wpi.c
+++ b/sys/dev/wpi/if_wpi.c
@@ -661,8 +661,8 @@ wpi_attach(device_t dev)
ifp->if_init = wpi_init;
ifp->if_ioctl = wpi_ioctl;
ifp->if_start = wpi_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ieee80211_ifattach(ic, macaddr);
diff --git a/sys/dev/xe/if_xe.c b/sys/dev/xe/if_xe.c
index f18fd98..77b953a 100644
--- a/sys/dev/xe/if_xe.c
+++ b/sys/dev/xe/if_xe.c
@@ -254,7 +254,7 @@ xe_attach(device_t dev)
scp->ifp->if_ioctl = xe_ioctl;
scp->ifp->if_init = xe_init;
scp->ifp->if_baudrate = 100000000;
- IFQ_SET_MAXLEN(&scp->ifp->if_snd, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&scp->ifp->if_snd, ifqmaxlen);
/* Initialise the ifmedia structure */
ifmedia_init(scp->ifm, 0, xe_media_change, xe_media_status);
diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index d67d354..15cf455 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -1,19 +1,27 @@
-/*
- *
+/*-
* Copyright (c) 2004-2006 Kip Macy
* All rights reserved.
*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
+ * 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.
*/
diff --git a/sys/fs/ext2fs/ext2_readwrite.c b/sys/fs/ext2fs/ext2_readwrite.c
index 9c9749a..1a713ca 100644
--- a/sys/fs/ext2fs/ext2_readwrite.c
+++ b/sys/fs/ext2fs/ext2_readwrite.c
@@ -168,7 +168,6 @@ WRITE(ap)
struct inode *ip;
FS *fs;
struct buf *bp;
- struct thread *td;
daddr_t lbn;
off_t osize;
int blkoffset, error, flags, ioflag, resid, size, seqcount, xfersize;
@@ -213,17 +212,8 @@ WRITE(ap)
* Maybe this should be above the vnode op call, but so long as
* file servers have no limits, I don't think it matters.
*/
- td = uio->uio_td;
- if (vp->v_type == VREG && td != NULL) {
- PROC_LOCK(td->td_proc);
- if (uio->uio_offset + uio->uio_resid >
- lim_cur(td->td_proc, RLIMIT_FSIZE)) {
- psignal(td->td_proc, SIGXFSZ);
- PROC_UNLOCK(td->td_proc);
- return (EFBIG);
- }
- PROC_UNLOCK(td->td_proc);
- }
+ if (vn_rlimit_fsize(vp, uio, uio->uio_td))
+ return (EFBIG);
resid = uio->uio_resid;
osize = ip->i_size;
diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c
index 2b2f8c5..2d302c5 100644
--- a/sys/fs/ext2fs/ext2_vnops.c
+++ b/sys/fs/ext2fs/ext2_vnops.c
@@ -46,7 +46,6 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/resourcevar.h>
#include <sys/kernel.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
@@ -54,7 +53,6 @@
#include <sys/buf.h>
#include <sys/endian.h>
#include <sys/priv.h>
-#include <sys/proc.h>
#include <sys/mount.h>
#include <sys/unistd.h>
#include <sys/time.h>
@@ -71,7 +69,6 @@
#include <fs/fifofs/fifo.h>
-#include <sys/signalvar.h>
#include <ufs/ufs/dir.h>
#include <fs/ext2fs/inode.h>
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index e9c593b..f38c72b 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -61,9 +61,6 @@
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/priv.h>
-#include <sys/proc.h>
-#include <sys/resourcevar.h>
-#include <sys/signalvar.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
@@ -699,16 +696,8 @@ msdosfs_write(ap)
/*
* If they've exceeded their filesize limit, tell them about it.
*/
- if (td != NULL) {
- PROC_LOCK(td->td_proc);
- if ((uoff_t)uio->uio_offset + uio->uio_resid >
- lim_cur(td->td_proc, RLIMIT_FSIZE)) {
- psignal(td->td_proc, SIGXFSZ);
- PROC_UNLOCK(td->td_proc);
- return (EFBIG);
- }
- PROC_UNLOCK(td->td_proc);
- }
+ if (vn_rlimit_fsize(vp, uio, td))
+ return (EFBIG);
/*
* If the offset we are starting the write at is beyond the end of
diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c
index 2401c88..df027ac 100644
--- a/sys/fs/nfsclient/nfs_clbio.c
+++ b/sys/fs/nfsclient/nfs_clbio.c
@@ -41,9 +41,6 @@ __FBSDID("$FreeBSD$");
#include <sys/buf.h>
#include <sys/kernel.h>
#include <sys/mount.h>
-#include <sys/proc.h>
-#include <sys/resourcevar.h>
-#include <sys/signalvar.h>
#include <sys/vmmeter.h>
#include <sys/vnode.h>
@@ -134,12 +131,15 @@ ncl_getpages(struct vop_getpages_args *ap)
*/
VM_OBJECT_LOCK(object);
if (pages[ap->a_reqpage]->valid != 0) {
- vm_page_lock_queues();
for (i = 0; i < npages; ++i) {
- if (i != ap->a_reqpage)
+ if (i != ap->a_reqpage) {
+ vm_page_lock(pages[i]);
+ vm_page_lock_queues();
vm_page_free(pages[i]);
+ vm_page_unlock_queues();
+ vm_page_unlock(pages[i]);
+ }
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
return (0);
}
@@ -174,12 +174,15 @@ ncl_getpages(struct vop_getpages_args *ap)
if (error && (uio.uio_resid == count)) {
ncl_printf("nfs_getpages: error %d\n", error);
VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
for (i = 0; i < npages; ++i) {
- if (i != ap->a_reqpage)
+ if (i != ap->a_reqpage) {
+ vm_page_lock(pages[i]);
+ vm_page_lock_queues();
vm_page_free(pages[i]);
+ vm_page_unlock_queues();
+ vm_page_unlock(pages[i]);
+ }
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
return (VM_PAGER_ERROR);
}
@@ -192,12 +195,14 @@ ncl_getpages(struct vop_getpages_args *ap)
size = count - uio.uio_resid;
VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
vm_page_t m;
nextoff = toff + PAGE_SIZE;
m = pages[i];
+ vm_page_lock(m);
+ vm_page_lock_queues();
+
if (nextoff <= size) {
/*
* Read operation filled an entire page
@@ -244,8 +249,10 @@ ncl_getpages(struct vop_getpages_args *ap)
vm_page_free(m);
}
}
+
+ vm_page_unlock_queues();
+ vm_page_unlock(m);
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
return (0);
}
@@ -876,7 +883,6 @@ ncl_write(struct vop_write_args *ap)
daddr_t lbn;
int bcount;
int n, on, error = 0;
- struct proc *p = td?td->td_proc:NULL;
#ifdef DIAGNOSTIC
if (uio->uio_rw != UIO_WRITE)
@@ -958,16 +964,8 @@ flush_and_restart:
* Maybe this should be above the vnode op call, but so long as
* file servers have no limits, i don't think it matters
*/
- if (p != NULL) {
- PROC_LOCK(p);
- if (uio->uio_offset + uio->uio_resid >
- lim_cur(p, RLIMIT_FSIZE)) {
- psignal(p, SIGXFSZ);
- PROC_UNLOCK(p);
- return (EFBIG);
- }
- PROC_UNLOCK(p);
- }
+ if (vn_rlimit_fsize(vp, uio, td))
+ return (EFBIG);
biosize = vp->v_mount->mnt_stat.f_iosize;
/*
diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c
index c133742..e36431f 100644
--- a/sys/fs/nfsclient/nfs_clnode.c
+++ b/sys/fs/nfsclient/nfs_clnode.c
@@ -198,8 +198,7 @@ ncl_inactive(struct vop_inactive_args *ap)
* must be flushed before the close, so that the stateid is
* available for the writes.
*/
- if (nfscl_mustflush(vp))
- (void) ncl_flush(vp, MNT_WAIT, NULL, ap->a_td, 1, 0);
+ (void) ncl_flush(vp, MNT_WAIT, NULL, ap->a_td, 1, 0);
(void) nfsrpc_close(vp, 1, ap->a_td);
}
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index a84a301..5d00102 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -1399,10 +1399,6 @@ nfsrpc_write(vnode_t vp, struct uio *uiop, int *iomode, u_char *verfp,
else
error = nfsrpc_writerpc(vp, uiop, iomode, verfp,
newcred, &stateid, p, nap, attrflagp, stuff);
-if (error == NFSERR_BADSTATEID) {
-printf("st=0x%x 0x%x 0x%x\n",stateid.other[0],stateid.other[1],stateid.other[2]);
-nfscl_dumpstate(nmp, 1, 1, 0, 0);
-}
if (error == NFSERR_STALESTATEID)
nfscl_initiate_recovery(nmp->nm_clp);
if (lckp != NULL)
diff --git a/sys/fs/nwfs/nwfs_io.c b/sys/fs/nwfs/nwfs_io.c
index 75b1c18..0bb996f 100644
--- a/sys/fs/nwfs/nwfs_io.c
+++ b/sys/fs/nwfs/nwfs_io.c
@@ -28,16 +28,13 @@
*/
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/resourcevar.h> /* defines plimit structure in proc struct */
#include <sys/kernel.h>
#include <sys/bio.h>
#include <sys/buf.h>
-#include <sys/proc.h>
#include <sys/mount.h>
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/dirent.h>
-#include <sys/signalvar.h>
#include <sys/sysctl.h>
#include <vm/vm.h>
@@ -229,16 +226,10 @@ nwfs_writevnode(vp, uiop, cred, ioflag)
}
}
if (uiop->uio_resid == 0) return 0;
- if (td != NULL) {
- PROC_LOCK(td->td_proc);
- if (uiop->uio_offset + uiop->uio_resid >
- lim_cur(td->td_proc, RLIMIT_FSIZE)) {
- psignal(td->td_proc, SIGXFSZ);
- PROC_UNLOCK(td->td_proc);
- return (EFBIG);
- }
- PROC_UNLOCK(td->td_proc);
- }
+
+ if (vn_rlimit_fsize(vp, uiop, td))
+ return (EFBIG);
+
error = ncp_write(NWFSTOCONN(nmp), &np->n_fh, uiop, cred);
NCPVNDEBUG("after: ofs=%d,resid=%d\n",(int)uiop->uio_offset, uiop->uio_resid);
if (!error) {
@@ -437,24 +428,29 @@ nwfs_getpages(ap)
VM_OBJECT_LOCK(object);
if (error && (uio.uio_resid == count)) {
printf("nwfs_getpages: error %d\n",error);
- vm_page_lock_queues();
for (i = 0; i < npages; i++) {
- if (ap->a_reqpage != i)
+ if (ap->a_reqpage != i) {
+ vm_page_lock(pages[i]);
+ vm_page_lock_queues();
vm_page_free(pages[i]);
+ vm_page_unlock_queues();
+ vm_page_unlock(pages[i]);
+ }
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
return VM_PAGER_ERROR;
}
size = count - uio.uio_resid;
- vm_page_lock_queues();
for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
vm_page_t m;
nextoff = toff + PAGE_SIZE;
m = pages[i];
+ vm_page_lock(m);
+ vm_page_lock_queues();
+
if (nextoff <= size) {
m->valid = VM_PAGE_BITS_ALL;
KASSERT(m->dirty == 0,
@@ -489,8 +485,10 @@ nwfs_getpages(ap)
vm_page_free(m);
}
}
+
+ vm_page_unlock_queues();
+ vm_page_unlock(m);
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
return 0;
#endif /* NWFS_RWCACHE */
diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c
index df779a6..c47fb1b 100644
--- a/sys/fs/smbfs/smbfs_io.c
+++ b/sys/fs/smbfs/smbfs_io.c
@@ -28,9 +28,7 @@
*/
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/resourcevar.h> /* defines plimit structure in proc struct */
#include <sys/kernel.h>
-#include <sys/proc.h>
#include <sys/fcntl.h>
#include <sys/bio.h>
#include <sys/buf.h>
@@ -235,7 +233,6 @@ smbfs_writevnode(struct vnode *vp, struct uio *uiop,
struct smbmount *smp = VTOSMBFS(vp);
struct smbnode *np = VTOSMB(vp);
struct smb_cred scred;
- struct proc *p;
struct thread *td;
int error = 0;
@@ -249,7 +246,6 @@ smbfs_writevnode(struct vnode *vp, struct uio *uiop,
/* if (uiop->uio_offset + uiop->uio_resid > smp->nm_maxfilesize)
return (EFBIG);*/
td = uiop->uio_td;
- p = td->td_proc;
if (ioflag & (IO_APPEND | IO_SYNC)) {
if (np->n_flag & NMODIFIED) {
smbfs_attr_cacheremove(vp);
@@ -271,16 +267,10 @@ smbfs_writevnode(struct vnode *vp, struct uio *uiop,
}
if (uiop->uio_resid == 0)
return 0;
- if (p != NULL) {
- PROC_LOCK(p);
- if (uiop->uio_offset + uiop->uio_resid >
- lim_cur(p, RLIMIT_FSIZE)) {
- psignal(p, SIGXFSZ);
- PROC_UNLOCK(p);
- return EFBIG;
- }
- PROC_UNLOCK(p);
- }
+
+ if (vn_rlimit_fsize(vp, uiop, td))
+ return (EFBIG);
+
smb_makescred(&scred, td, cred);
error = smb_write(smp->sm_share, np->n_fid, uiop, &scred);
SMBVDEBUG("after: ofs=%d,resid=%d\n",(int)uiop->uio_offset, uiop->uio_resid);
@@ -450,12 +440,15 @@ smbfs_getpages(ap)
VM_OBJECT_LOCK(object);
if (m->valid != 0) {
- vm_page_lock_queues();
for (i = 0; i < npages; ++i) {
- if (i != reqpage)
+ if (i != reqpage) {
+ vm_page_lock(pages[i]);
+ vm_page_lock_queues();
vm_page_free(pages[i]);
+ vm_page_unlock_queues();
+ vm_page_unlock(pages[i]);
+ }
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
return 0;
}
@@ -488,24 +481,29 @@ smbfs_getpages(ap)
VM_OBJECT_LOCK(object);
if (error && (uio.uio_resid == count)) {
printf("smbfs_getpages: error %d\n",error);
- vm_page_lock_queues();
for (i = 0; i < npages; i++) {
- if (reqpage != i)
+ if (reqpage != i) {
+ vm_page_lock(pages[i]);
+ vm_page_lock_queues();
vm_page_free(pages[i]);
+ vm_page_unlock_queues();
+ vm_page_unlock(pages[i]);
+ }
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
return VM_PAGER_ERROR;
}
size = count - uio.uio_resid;
- vm_page_lock_queues();
for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
vm_page_t m;
nextoff = toff + PAGE_SIZE;
m = pages[i];
+ vm_page_lock(m);
+ vm_page_lock_queues();
+
if (nextoff <= size) {
/*
* Read operation filled an entire page
@@ -553,8 +551,10 @@ smbfs_getpages(ap)
vm_page_free(m);
}
}
+
+ vm_page_unlock_queues();
+ vm_page_unlock(m);
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
return 0;
#endif /* SMBFS_RWGENERIC */
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index c17efff..3ffef6b 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <sys/namei.h>
#include <sys/priv.h>
#include <sys/proc.h>
-#include <sys/resourcevar.h>
#include <sys/sched.h>
#include <sys/sf_buf.h>
#include <sys/stat.h>
@@ -460,9 +459,9 @@ tmpfs_nocacheread(vm_object_t tobj, vm_pindex_t idx,
error = uiomove_fromphys(&m, offset, tlen, uio);
VM_OBJECT_LOCK(tobj);
out:
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_unwire(m, TRUE);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
vm_page_wakeup(m);
vm_object_pip_subtract(tobj, 1);
VM_OBJECT_UNLOCK(tobj);
@@ -516,8 +515,16 @@ tmpfs_mappedread(vm_object_t vobj, vm_object_t tobj, size_t len, struct uio *uio
lookupvpg:
if (((m = vm_page_lookup(vobj, idx)) != NULL) &&
vm_page_is_valid(m, offset, tlen)) {
- if (vm_page_sleep_if_busy(m, FALSE, "tmfsmr"))
+ if ((m->oflags & VPO_BUSY) != 0) {
+ /*
+ * Reference the page before unlocking and sleeping so
+ * that the page daemon is less likely to reclaim it.
+ */
+ vm_page_lock_queues();
+ vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_sleep(m, "tmfsmr");
goto lookupvpg;
+ }
vm_page_busy(m);
VM_OBJECT_UNLOCK(vobj);
error = uiomove_fromphys(&m, offset, tlen, uio);
@@ -526,8 +533,16 @@ lookupvpg:
VM_OBJECT_UNLOCK(vobj);
return (error);
} else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) {
- if (vm_page_sleep_if_busy(m, FALSE, "tmfsmr"))
+ if ((m->oflags & VPO_BUSY) != 0) {
+ /*
+ * Reference the page before unlocking and sleeping so
+ * that the page daemon is less likely to reclaim it.
+ */
+ vm_page_lock_queues();
+ vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_sleep(m, "tmfsmr");
goto lookupvpg;
+ }
vm_page_busy(m);
VM_OBJECT_UNLOCK(vobj);
sched_pin();
@@ -627,8 +642,16 @@ tmpfs_mappedwrite(vm_object_t vobj, vm_object_t tobj, size_t len, struct uio *ui
lookupvpg:
if (((vpg = vm_page_lookup(vobj, idx)) != NULL) &&
vm_page_is_valid(vpg, offset, tlen)) {
- if (vm_page_sleep_if_busy(vpg, FALSE, "tmfsmw"))
+ if ((vpg->oflags & VPO_BUSY) != 0) {
+ /*
+ * Reference the page before unlocking and sleeping so
+ * that the page daemon is less likely to reclaim it.
+ */
+ vm_page_lock_queues();
+ vm_page_flag_set(vpg, PG_REFERENCED);
+ vm_page_sleep(vpg, "tmfsmw");
goto lookupvpg;
+ }
vm_page_busy(vpg);
vm_page_lock_queues();
vm_page_undirty(vpg);
@@ -667,6 +690,7 @@ nocache:
out:
if (vobj != NULL)
VM_OBJECT_LOCK(vobj);
+ vm_page_lock(tpg);
vm_page_lock_queues();
if (error == 0) {
KASSERT(tpg->valid == VM_PAGE_BITS_ALL,
@@ -675,6 +699,7 @@ out:
}
vm_page_unwire(tpg, TRUE);
vm_page_unlock_queues();
+ vm_page_unlock(tpg);
vm_page_wakeup(tpg);
if (vpg != NULL)
vm_page_wakeup(vpg);
@@ -722,16 +747,8 @@ tmpfs_write(struct vop_write_args *v)
VFS_TO_TMPFS(vp->v_mount)->tm_maxfilesize)
return (EFBIG);
- if (vp->v_type == VREG && td != NULL) {
- PROC_LOCK(td->td_proc);
- if (uio->uio_offset + uio->uio_resid >
- lim_cur(td->td_proc, RLIMIT_FSIZE)) {
- psignal(td->td_proc, SIGXFSZ);
- PROC_UNLOCK(td->td_proc);
- return (EFBIG);
- }
- PROC_UNLOCK(td->td_proc);
- }
+ if (vn_rlimit_fsize(vp, uio, td))
+ return (EFBIG);
extended = uio->uio_offset + uio->uio_resid > node->tn_size;
if (extended) {
diff --git a/sys/geom/geom.h b/sys/geom/geom.h
index 82d0456..fe18a15 100644
--- a/sys/geom/geom.h
+++ b/sys/geom/geom.h
@@ -353,6 +353,9 @@ g_free(void *ptr)
sx_assert(&topology_lock, SX_UNLOCKED); \
} while (0)
+#define g_topology_sleep(chan, timo) \
+ sx_sleep(chan, &topology_lock, 0, "gtopol", timo)
+
#define DECLARE_GEOM_CLASS(class, name) \
static moduledata_t name##_mod = { \
#name, g_modevent, &class \
diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c
index 772277e..b001c5f 100644
--- a/sys/geom/geom_subr.c
+++ b/sys/geom/geom_subr.c
@@ -134,65 +134,73 @@ g_load_class(void *arg, int flag)
}
}
-static void
-g_unload_class(void *arg, int flag)
+static int
+g_unload_class(struct g_class *mp)
{
- struct g_hh00 *hh;
- struct g_class *mp;
struct g_geom *gp;
struct g_provider *pp;
struct g_consumer *cp;
int error;
- g_topology_assert();
- hh = arg;
- mp = hh->mp;
- G_VALID_CLASS(mp);
+ g_topology_lock();
g_trace(G_T_TOPOLOGY, "g_unload_class(%s)", mp->name);
-
- /*
- * We allow unloading if we have no geoms, or a class
- * method we can use to get rid of them.
- */
- if (!LIST_EMPTY(&mp->geom) && mp->destroy_geom == NULL) {
- hh->error = EOPNOTSUPP;
- return;
- }
-
- /* We refuse to unload if anything is open */
+retry:
+ G_VALID_CLASS(mp);
LIST_FOREACH(gp, &mp->geom, geom) {
+ /* We refuse to unload if anything is open */
LIST_FOREACH(pp, &gp->provider, provider)
if (pp->acr || pp->acw || pp->ace) {
- hh->error = EBUSY;
- return;
+ g_topology_unlock();
+ return (EBUSY);
}
LIST_FOREACH(cp, &gp->consumer, consumer)
if (cp->acr || cp->acw || cp->ace) {
- hh->error = EBUSY;
- return;
+ g_topology_unlock();
+ return (EBUSY);
}
+ /* If the geom is withering, wait for it to finish. */
+ if (gp->flags & G_GEOM_WITHER) {
+ g_topology_sleep(mp, 1);
+ goto retry;
+ }
+ }
+
+ /*
+ * We allow unloading if we have no geoms, or a class
+ * method we can use to get rid of them.
+ */
+ if (!LIST_EMPTY(&mp->geom) && mp->destroy_geom == NULL) {
+ g_topology_unlock();
+ return (EOPNOTSUPP);
}
/* Bar new entries */
mp->taste = NULL;
mp->config = NULL;
- error = 0;
+ LIST_FOREACH(gp, &mp->geom, geom) {
+ error = mp->destroy_geom(NULL, mp, gp);
+ if (error != 0) {
+ g_topology_unlock();
+ return (error);
+ }
+ }
+ /* Wait for withering to finish. */
for (;;) {
gp = LIST_FIRST(&mp->geom);
if (gp == NULL)
break;
- error = mp->destroy_geom(NULL, mp, gp);
- if (error != 0)
- break;
+ KASSERT(gp->flags & G_GEOM_WITHER,
+ ("Non-withering geom in class %s", mp->name));
+ g_topology_sleep(mp, 1);
}
- if (error == 0) {
- if (mp->fini != NULL)
- mp->fini(mp);
- LIST_REMOVE(mp, class);
- }
- hh->error = error;
- return;
+ G_VALID_CLASS(mp);
+ if (mp->fini != NULL)
+ mp->fini(mp);
+ LIST_REMOVE(mp, class);
+ g_topology_unlock();
+
+ return (0);
}
int
@@ -213,12 +221,12 @@ g_modevent(module_t mod, int type, void *data)
g_ignition++;
g_init();
}
- hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO);
- hh->mp = data;
error = EOPNOTSUPP;
switch (type) {
case MOD_LOAD:
- g_trace(G_T_TOPOLOGY, "g_modevent(%s, LOAD)", hh->mp->name);
+ g_trace(G_T_TOPOLOGY, "g_modevent(%s, LOAD)", mp->name);
+ hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO);
+ hh->mp = mp;
/*
* Once the system is not cold, MOD_LOAD calls will be
* from the userland and the g_event thread will be able
@@ -236,18 +244,14 @@ g_modevent(module_t mod, int type, void *data)
}
break;
case MOD_UNLOAD:
- g_trace(G_T_TOPOLOGY, "g_modevent(%s, UNLOAD)", hh->mp->name);
- error = g_waitfor_event(g_unload_class, hh, M_WAITOK, NULL);
- if (error == 0)
- error = hh->error;
+ g_trace(G_T_TOPOLOGY, "g_modevent(%s, UNLOAD)", mp->name);
+ DROP_GIANT();
+ error = g_unload_class(mp);
+ PICKUP_GIANT();
if (error == 0) {
- KASSERT(LIST_EMPTY(&hh->mp->geom),
- ("Unloaded class (%s) still has geom", hh->mp->name));
+ KASSERT(LIST_EMPTY(&mp->geom),
+ ("Unloaded class (%s) still has geom", mp->name));
}
- g_free(hh);
- break;
- default:
- g_free(hh);
break;
}
return (error);
diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c b/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
index 20be557..b935b64 100644
--- a/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
+++ b/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
@@ -598,16 +598,8 @@ xfs_write_file(xfs_inode_t *xip, struct uio *uio, int ioflag)
*/
#if 0
td = uio->uio_td;
- if (vp->v_type == VREG && td != NULL) {
- PROC_LOCK(td->td_proc);
- if (uio->uio_offset + uio->uio_resid >
- lim_cur(td->td_proc, RLIMIT_FSIZE)) {
- psignal(td->td_proc, SIGXFSZ);
- PROC_UNLOCK(td->td_proc);
- return (EFBIG);
- }
- PROC_UNLOCK(td->td_proc);
- }
+ if (vn_rlimit_fsize(vp, uio, uio->uio_td))
+ return (EFBIG);
#endif
resid = uio->uio_resid;
diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c
index 931bfaf..6f2e4a4 100644
--- a/sys/i386/i386/identcpu.c
+++ b/sys/i386/i386/identcpu.c
@@ -727,7 +727,7 @@ printcpuinfo(void)
printf("\n Features2=0x%b", cpu_feature2,
"\020"
"\001SSE3" /* SSE3 */
- "\002<b1>"
+ "\002PCLMULQDQ" /* Carry-Less Mul Quadword */
"\003DTES64" /* 64-bit Debug Trace */
"\004MON" /* MONITOR/MWAIT Instructions */
"\005DS_CPL" /* CPL Qualified Debug Store */
@@ -751,7 +751,7 @@ printcpuinfo(void)
"\027MOVBE"
"\030POPCNT"
"\031<b24>"
- "\032<b25>"
+ "\032AESNI" /* AES Crypto*/
"\033XSAVE"
"\034OSXSAVE"
"\035<b28>"
diff --git a/sys/i386/i386/io.c b/sys/i386/i386/io.c
index c392af5..152f6b1 100644
--- a/sys/i386/i386/io.c
+++ b/sys/i386/i386/io.c
@@ -28,60 +28,32 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/fcntl.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mutex.h>
-#include <sys/priv.h>
#include <sys/proc.h>
-#include <sys/signalvar.h>
-#include <sys/systm.h>
-#include <machine/db_machdep.h>
#include <machine/frame.h>
-#include <machine/psl.h>
-#include <machine/specialreg.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
#include <machine/iodev.h>
+#include <machine/psl.h>
-/* ARGSUSED */
int
-ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused,
- struct thread *td)
+iodev_open(struct thread *td)
{
- int error;
-
- error = priv_check(td, PRIV_IO);
- if (error != 0)
- return (error);
- error = securelevel_gt(td->td_ucred, 0);
- if (error != 0)
- return (error);
td->td_frame->tf_eflags |= PSL_IOPL;
-
return (0);
}
-/* ARGSUSED */
int
-ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused,
- struct thread *td)
+iodev_close(struct thread *td)
{
- td->td_frame->tf_eflags &= ~PSL_IOPL;
+ td->td_frame->tf_eflags &= ~PSL_IOPL;
return (0);
}
/* ARGSUSED */
int
-ioioctl(struct cdev *dev __unused, u_long cmd __unused, caddr_t data __unused,
- int fflag __unused, struct thread *td __unused)
+iodev_ioctl(u_long cmd __unused, caddr_t data __unused)
{
- return (ENXIO);
+ return (ENOIOCTL);
}
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index d8b9686..661fade 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -1346,14 +1346,19 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
pd_entry_t pde;
pt_entry_t pte;
vm_page_t m;
+ vm_paddr_t pa;
+ pa = 0;
m = NULL;
- vm_page_lock_queues();
PMAP_LOCK(pmap);
+retry:
pde = *pmap_pde(pmap, va);
if (pde != 0) {
if (pde & PG_PS) {
if ((pde & PG_RW) || (prot & VM_PROT_WRITE) == 0) {
+ if (vm_page_pa_tryrelock(pmap, (pde & PG_PS_FRAME) |
+ (va & PDRMASK), &pa))
+ goto retry;
m = PHYS_TO_VM_PAGE((pde & PG_PS_FRAME) |
(va & PDRMASK));
vm_page_hold(m);
@@ -1363,13 +1368,15 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
pte = *pmap_pte_quick(pmap, va);
if (pte != 0 &&
((pte & PG_RW) || (prot & VM_PROT_WRITE) == 0)) {
+ if (vm_page_pa_tryrelock(pmap, pte & PG_FRAME, &pa))
+ goto retry;
m = PHYS_TO_VM_PAGE(pte & PG_FRAME);
vm_page_hold(m);
}
sched_unpin();
}
}
- vm_page_unlock_queues();
+ PA_UNLOCK_COND(pa);
PMAP_UNLOCK(pmap);
return (m);
}
diff --git a/sys/i386/include/iodev.h b/sys/i386/include/iodev.h
index 1a0a17a..9f53cac 100644
--- a/sys/i386/include/iodev.h
+++ b/sys/i386/include/iodev.h
@@ -25,7 +25,22 @@
*
* $FreeBSD$
*/
+#ifndef _MACHINE_IODEV_H_
+#define _MACHINE_IODEV_H_
-d_open_t ioopen;
-d_close_t ioclose;
-d_ioctl_t ioioctl;
+#ifdef _KERNEL
+#include <machine/cpufunc.h>
+
+#define iodev_read_1 inb
+#define iodev_read_2 inw
+#define iodev_read_4 inl
+#define iodev_write_1 outb
+#define iodev_write_2 outw
+#define iodev_write_4 outl
+
+int iodev_open(struct thread *td);
+int iodev_close(struct thread *td);
+int iodev_ioctl(u_long cmd, caddr_t data);
+
+#endif /* _KERNEL */
+#endif /* _MACHINE_IODEV_H_ */
diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h
index ae7d79d..f45a9df 100644
--- a/sys/i386/include/pmap.h
+++ b/sys/i386/include/pmap.h
@@ -420,11 +420,14 @@ struct pmap {
u_int pm_active; /* active on cpus */
struct pmap_statistics pm_stats; /* pmap statistics */
LIST_ENTRY(pmap) pm_list; /* List of all pmaps */
+ uint32_t pm_gen_count; /* generation count (pmap lock dropped) */
+ u_int pm_retries;
#ifdef PAE
pdpt_entry_t *pm_pdpt; /* KVA of page director pointer
table */
#endif
vm_page_t pm_root; /* spare page table pages */
+
};
typedef struct pmap *pmap_t;
diff --git a/sys/i386/include/proc.h b/sys/i386/include/proc.h
index 0b9fca2..86be8c8 100644
--- a/sys/i386/include/proc.h
+++ b/sys/i386/include/proc.h
@@ -57,7 +57,7 @@ struct mdproc {
struct proc_ldt *md_ldt; /* (t) per-process ldt */
};
-#define KINFO_PROC_SIZE 768
+#define KINFO_PROC_SIZE 768
#ifdef _KERNEL
diff --git a/sys/i386/include/specialreg.h b/sys/i386/include/specialreg.h
index d2494c7..efcf924 100644
--- a/sys/i386/include/specialreg.h
+++ b/sys/i386/include/specialreg.h
@@ -110,6 +110,7 @@
#define CPUID_PBE 0x80000000
#define CPUID2_SSE3 0x00000001
+#define CPUID2_PCLMULQDQ 0x00000002
#define CPUID2_DTES64 0x00000004
#define CPUID2_MON 0x00000008
#define CPUID2_DS_CPL 0x00000010
@@ -128,6 +129,7 @@
#define CPUID2_X2APIC 0x00200000
#define CPUID2_MOVBE 0x00400000
#define CPUID2_POPCNT 0x00800000
+#define CPUID2_AESNI 0x02000000
/*
* Important bits in the AMD extended cpuid flags
diff --git a/sys/i386/include/xen/xenfunc.h b/sys/i386/include/xen/xenfunc.h
index 2851709..47f0405 100644
--- a/sys/i386/include/xen/xenfunc.h
+++ b/sys/i386/include/xen/xenfunc.h
@@ -1,6 +1,5 @@
-/*
- *
- * Copyright (c) 2004,2005 Kip Macy
+/*-
+ * Copyright (c) 2004, 2005 Kip Macy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,24 +10,22 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 4. 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.
+ * 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 _XEN_XENFUNC_H_
#define _XEN_XENFUNC_H_
diff --git a/sys/i386/include/xen/xenvar.h b/sys/i386/include/xen/xenvar.h
index cefbb05..1110f85 100644
--- a/sys/i386/include/xen/xenvar.h
+++ b/sys/i386/include/xen/xenvar.h
@@ -1,32 +1,31 @@
-/*
+/*-
* Copyright (c) 2008 Kip Macy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
- *
+ * 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 XENVAR_H_
#define XENVAR_H_
#define XBOOTUP 0x1
diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
index 40e36be..1bd081f 100644
--- a/sys/i386/xen/pmap.c
+++ b/sys/i386/xen/pmap.c
@@ -289,6 +289,12 @@ SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_max, CTLFLAG_RD, &pv_entry_max, 0,
"Max number of PV entries");
SYSCTL_INT(_vm_pmap, OID_AUTO, shpgperproc, CTLFLAG_RD, &shpgperproc, 0,
"Page share factor per proc");
+SYSCTL_NODE(_vm_pmap, OID_AUTO, pde, CTLFLAG_RD, 0,
+ "2/4MB page mapping counters");
+
+static u_long pmap_pde_mappings;
+SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, mappings, CTLFLAG_RD,
+ &pmap_pde_mappings, 0, "2/4MB page mappings");
static void free_pv_entry(pmap_t pmap, pv_entry_t pv);
static pv_entry_t get_pv_entry(pmap_t locked_pmap, int try);
@@ -1219,14 +1225,19 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
pd_entry_t pde;
pt_entry_t pte;
vm_page_t m;
+ vm_paddr_t pa;
+ pa = 0;
m = NULL;
- vm_page_lock_queues();
PMAP_LOCK(pmap);
+retry:
pde = PT_GET(pmap_pde(pmap, va));
if (pde != 0) {
if (pde & PG_PS) {
if ((pde & PG_RW) || (prot & VM_PROT_WRITE) == 0) {
+ if (vm_page_pa_tryrelock(pmap, (pde & PG_PS_FRAME) |
+ (va & PDRMASK), &pa))
+ goto retry;
m = PHYS_TO_VM_PAGE((pde & PG_PS_FRAME) |
(va & PDRMASK));
vm_page_hold(m);
@@ -1238,13 +1249,15 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
PT_SET_MA(PADDR1, 0);
if ((pte & PG_V) &&
((pte & PG_RW) || (prot & VM_PROT_WRITE) == 0)) {
+ if (vm_page_pa_tryrelock(pmap, pte & PG_FRAME, &pa))
+ goto retry;
m = PHYS_TO_VM_PAGE(pte & PG_FRAME);
vm_page_hold(m);
}
sched_unpin();
}
}
- vm_page_unlock_queues();
+ PA_UNLOCK_COND(pa);
PMAP_UNLOCK(pmap);
return (m);
}
@@ -2600,22 +2613,16 @@ retry:
obits = pbits = *pte;
if ((pbits & PG_V) == 0)
continue;
- if (pbits & PG_MANAGED) {
- m = NULL;
- if (pbits & PG_A) {
- m = PHYS_TO_VM_PAGE(xpmap_mtop(pbits) & PG_FRAME);
- vm_page_flag_set(m, PG_REFERENCED);
- pbits &= ~PG_A;
- }
- if ((pbits & PG_M) != 0) {
- if (m == NULL)
- m = PHYS_TO_VM_PAGE(xpmap_mtop(pbits) & PG_FRAME);
+
+ if ((prot & VM_PROT_WRITE) == 0) {
+ if ((pbits & (PG_MANAGED | PG_M | PG_RW)) ==
+ (PG_MANAGED | PG_M | PG_RW)) {
+ m = PHYS_TO_VM_PAGE(xpmap_mtop(pbits) &
+ PG_FRAME);
vm_page_dirty(m);
}
- }
-
- if ((prot & VM_PROT_WRITE) == 0)
pbits &= ~(PG_RW | PG_M);
+ }
#ifdef PAE
if ((prot & VM_PROT_EXECUTE) == 0)
pbits |= pg_nx;
@@ -3129,64 +3136,59 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr,
vm_object_t object, vm_pindex_t pindex,
vm_size_t size)
{
+ pd_entry_t *pde;
+ vm_paddr_t pa, ptepa;
vm_page_t p;
+ int pat_mode;
VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG,
("pmap_object_init_pt: non-device object"));
if (pseflag &&
- ((addr & (NBPDR - 1)) == 0) && ((size & (NBPDR - 1)) == 0)) {
- int i;
- vm_page_t m[1];
- unsigned int ptepindex;
- int npdes;
- pd_entry_t ptepa;
-
- PMAP_LOCK(pmap);
- if (pmap->pm_pdir[ptepindex = (addr >> PDRSHIFT)])
- goto out;
- PMAP_UNLOCK(pmap);
-retry:
+ (addr & (NBPDR - 1)) == 0 && (size & (NBPDR - 1)) == 0) {
+ if (!vm_object_populate(object, pindex, pindex + atop(size)))
+ return;
p = vm_page_lookup(object, pindex);
- if (p != NULL) {
- if (vm_page_sleep_if_busy(p, FALSE, "init4p"))
- goto retry;
- } else {
- p = vm_page_alloc(object, pindex, VM_ALLOC_NORMAL);
- if (p == NULL)
- return;
- m[0] = p;
-
- if (vm_pager_get_pages(object, m, 1, 0) != VM_PAGER_OK) {
- vm_page_lock_queues();
- vm_page_free(p);
- vm_page_unlock_queues();
- return;
- }
-
- p = vm_page_lookup(object, pindex);
- vm_page_wakeup(p);
- }
-
+ KASSERT(p->valid == VM_PAGE_BITS_ALL,
+ ("pmap_object_init_pt: invalid page %p", p));
+ pat_mode = p->md.pat_mode;
+ /*
+ * Abort the mapping if the first page is not physically
+ * aligned to a 2/4MB page boundary.
+ */
ptepa = VM_PAGE_TO_PHYS(p);
if (ptepa & (NBPDR - 1))
return;
-
- p->valid = VM_PAGE_BITS_ALL;
-
+ /*
+ * Skip the first page. Abort the mapping if the rest of
+ * the pages are not physically contiguous or have differing
+ * memory attributes.
+ */
+ p = TAILQ_NEXT(p, listq);
+ for (pa = ptepa + PAGE_SIZE; pa < ptepa + size;
+ pa += PAGE_SIZE) {
+ KASSERT(p->valid == VM_PAGE_BITS_ALL,
+ ("pmap_object_init_pt: invalid page %p", p));
+ if (pa != VM_PAGE_TO_PHYS(p) ||
+ pat_mode != p->md.pat_mode)
+ return;
+ p = TAILQ_NEXT(p, listq);
+ }
+ /* Map using 2/4MB pages. */
PMAP_LOCK(pmap);
- pmap->pm_stats.resident_count += size >> PAGE_SHIFT;
- npdes = size >> PDRSHIFT;
- critical_enter();
- for(i = 0; i < npdes; i++) {
- PD_SET_VA(pmap, ptepindex,
- ptepa | PG_U | PG_M | PG_RW | PG_V | PG_PS, FALSE);
- ptepa += NBPDR;
- ptepindex += 1;
+ for (pa = ptepa | pmap_cache_bits(pat_mode, 1); pa < ptepa +
+ size; pa += NBPDR) {
+ pde = pmap_pde(pmap, addr);
+ if (*pde == 0) {
+ pde_store(pde, pa | PG_PS | PG_M | PG_A |
+ PG_U | PG_RW | PG_V);
+ pmap->pm_stats.resident_count += NBPDR /
+ PAGE_SIZE;
+ pmap_pde_mappings++;
+ }
+ /* Else continue on if the PDE is already valid. */
+ addr += NBPDR;
}
- pmap_invalidate_all(pmap);
- critical_exit();
-out:
PMAP_UNLOCK(pmap);
}
}
diff --git a/sys/ia64/ia64/iodev_machdep.c b/sys/ia64/ia64/iodev_machdep.c
index d255aae..9d9057d 100644
--- a/sys/ia64/ia64/iodev_machdep.c
+++ b/sys/ia64/ia64/iodev_machdep.c
@@ -40,61 +40,33 @@ __FBSDID("$FreeBSD$");
#include <machine/efi.h>
#include <machine/iodev.h>
-static int iodev_pio_read(struct iodev_pio_req *req);
-static int iodev_pio_write(struct iodev_pio_req *req);
-
static int iodev_efivar_getvar(struct iodev_efivar_req *req);
static int iodev_efivar_nextname(struct iodev_efivar_req *req);
static int iodev_efivar_setvar(struct iodev_efivar_req *req);
/* ARGSUSED */
int
-ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused,
- struct thread *td)
+iodev_open(struct thread *td __unused)
{
- int error;
-
- error = priv_check(td, PRIV_IO);
- if (error == 0)
- error = securelevel_gt(td->td_ucred, 0);
- return (error);
+ return (0);
}
/* ARGSUSED */
int
-ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused,
- struct thread *td __unused)
+iodev_close(struct thread *td __unused)
{
return (0);
}
-/* ARGSUSED */
int
-ioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
- int fflag __unused, struct thread *td __unused)
+iodev_ioctl(u_long cmd, caddr_t data)
{
struct iodev_efivar_req *efivar_req;
- struct iodev_pio_req *pio_req;
int error;
- error = ENOIOCTL;
switch (cmd) {
- case IODEV_PIO:
- pio_req = (struct iodev_pio_req *)data;
- switch (pio_req->access) {
- case IODEV_PIO_READ:
- error = iodev_pio_read(pio_req);
- break;
- case IODEV_PIO_WRITE:
- error = iodev_pio_write(pio_req);
- break;
- default:
- error = EINVAL;
- break;
- }
- break;
case IODEV_EFIVAR:
efivar_req = (struct iodev_efivar_req *)data;
efivar_req->result = 0; /* So it's well-defined */
@@ -113,75 +85,11 @@ ioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
break;
}
break;
- }
-
- return (error);
-}
-
-static int
-iodev_pio_read(struct iodev_pio_req *req)
-{
-
- switch (req->width) {
- case 1:
- req->val = bus_space_read_io_1(req->port);
- break;
- case 2:
- if (req->port & 1) {
- req->val = bus_space_read_io_1(req->port);
- req->val |= bus_space_read_io_1(req->port + 1) << 8;
- } else
- req->val = bus_space_read_io_2(req->port);
- break;
- case 4:
- if (req->port & 1) {
- req->val = bus_space_read_io_1(req->port);
- req->val |= bus_space_read_io_2(req->port + 1) << 8;
- req->val |= bus_space_read_io_1(req->port + 3) << 24;
- } else if (req->port & 2) {
- req->val = bus_space_read_io_2(req->port);
- req->val |= bus_space_read_io_2(req->port + 2) << 16;
- } else
- req->val = bus_space_read_io_4(req->port);
- break;
- default:
- return (EINVAL);
- }
-
- return (0);
-}
-
-static int
-iodev_pio_write(struct iodev_pio_req *req)
-{
-
- switch (req->width) {
- case 1:
- bus_space_write_io_1(req->port, req->val);
- break;
- case 2:
- if (req->port & 1) {
- bus_space_write_io_1(req->port, req->val);
- bus_space_write_io_1(req->port + 1, req->val >> 8);
- } else
- bus_space_write_io_2(req->port, req->val);
- break;
- case 4:
- if (req->port & 1) {
- bus_space_write_io_1(req->port, req->val);
- bus_space_write_io_2(req->port + 1, req->val >> 8);
- bus_space_write_io_1(req->port + 3, req->val >> 24);
- } else if (req->port & 2) {
- bus_space_write_io_2(req->port, req->val);
- bus_space_write_io_2(req->port + 2, req->val >> 16);
- } else
- bus_space_write_io_4(req->port, req->val);
- break;
default:
- return (EINVAL);
+ error = ENOIOCTL;
}
- return (0);
+ return (error);
}
static int
diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c
index a7c47ef..7cc18c1 100644
--- a/sys/ia64/ia64/pmap.c
+++ b/sys/ia64/ia64/pmap.c
@@ -1028,18 +1028,22 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
struct ia64_lpte *pte;
pmap_t oldpmap;
vm_page_t m;
+ vm_paddr_t pa;
+ pa = 0;
m = NULL;
- vm_page_lock_queues();
PMAP_LOCK(pmap);
oldpmap = pmap_switch(pmap);
+retry:
pte = pmap_find_vhpt(va);
if (pte != NULL && pmap_present(pte) &&
(pmap_prot(pte) & prot) == prot) {
m = PHYS_TO_VM_PAGE(pmap_ppn(pte));
+ if (vm_page_pa_tryrelock(pmap, pmap_ppn(pte), &pa))
+ goto retry;
vm_page_hold(m);
}
- vm_page_unlock_queues();
+ PA_UNLOCK_COND(pa);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
return (m);
@@ -1450,19 +1454,13 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
if (pmap_prot(pte) == prot)
continue;
- if (pmap_managed(pte)) {
- vm_offset_t pa = pmap_ppn(pte);
+ if ((prot & VM_PROT_WRITE) == 0 &&
+ pmap_managed(pte) && pmap_dirty(pte)) {
+ vm_paddr_t pa = pmap_ppn(pte);
vm_page_t m = PHYS_TO_VM_PAGE(pa);
- if (pmap_dirty(pte)) {
- vm_page_dirty(m);
- pmap_clear_dirty(pte);
- }
-
- if (pmap_accessed(pte)) {
- vm_page_flag_set(m, PG_REFERENCED);
- pmap_clear_accessed(pte);
- }
+ vm_page_dirty(m);
+ pmap_clear_dirty(pte);
}
if (prot & VM_PROT_EXECUTE)
diff --git a/sys/ia64/include/iodev.h b/sys/ia64/include/iodev.h
index 6d2ae19..cf349d9 100644
--- a/sys/ia64/include/iodev.h
+++ b/sys/ia64/include/iodev.h
@@ -31,22 +31,16 @@
#include <sys/uuid.h>
-struct iodev_pio_req {
- u_int access;
-#define IODEV_PIO_READ 0
-#define IODEV_PIO_WRITE 1
- u_int port;
- u_int width;
- u_int val;
-};
-
-#define IODEV_PIO _IOWR('I', 0, struct iodev_pio_req)
+#ifdef _KERNEL
+#include <machine/bus.h>
+#endif
-struct iodev_efivar_req {
- u_int access;
#define IODEV_EFIVAR_GETVAR 0
#define IODEV_EFIVAR_NEXTNAME 1
#define IODEV_EFIVAR_SETVAR 2
+
+struct iodev_efivar_req {
+ u_int access;
u_int result; /* errno value */
size_t namesize;
u_short *name; /* UCS-2 */
@@ -59,11 +53,16 @@ struct iodev_efivar_req {
#define IODEV_EFIVAR _IOWR('I', 1, struct iodev_efivar_req)
#ifdef _KERNEL
+#define iodev_read_1 bus_space_read_io_1
+#define iodev_read_2 bus_space_read_io_2
+#define iodev_read_4 bus_space_read_io_4
+#define iodev_write_1 bus_space_write_io_1
+#define iodev_write_2 bus_space_write_io_2
+#define iodev_write_4 bus_space_write_io_4
-d_open_t ioopen;
-d_close_t ioclose;
-d_ioctl_t ioioctl;
-
-#endif
+int iodev_open(struct thread *td);
+int iodev_close(struct thread *td);
+int iodev_ioctl(u_long, caddr_t data);
+#endif /* _KERNEL */
#endif /* _MACHINE_IODEV_H_ */
diff --git a/sys/ia64/include/pmap.h b/sys/ia64/include/pmap.h
index 44079c8..ff059fd 100644
--- a/sys/ia64/include/pmap.h
+++ b/sys/ia64/include/pmap.h
@@ -77,6 +77,8 @@ struct pmap {
TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */
u_int32_t pm_rid[5]; /* base RID for pmap */
struct pmap_statistics pm_stats; /* pmap statistics */
+ uint32_t pm_gen_count; /* generation count (pmap lock dropped) */
+ u_int pm_retries;
};
typedef struct pmap *pmap_t;
diff --git a/sys/ia64/include/proc.h b/sys/ia64/include/proc.h
index 81e2e4f..e9f337c 100644
--- a/sys/ia64/include/proc.h
+++ b/sys/ia64/include/proc.h
@@ -38,7 +38,7 @@ struct mdproc {
int __dummy; /* Avoid having an empty struct. */
};
-#define KINFO_PROC_SIZE 1088
-#define KINFO_PROC32_SIZE 768
+#define KINFO_PROC_SIZE 1088
+#define KINFO_PROC32_SIZE 768
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 236894f..c48e0f5 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1088,8 +1088,10 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
hdrsize = 0;
__elfN(puthdr)(td, (void *)NULL, &hdrsize, seginfo.count);
- if (hdrsize + seginfo.size >= limit)
- return (EFAULT);
+ if (hdrsize + seginfo.size >= limit) {
+ error = EFAULT;
+ goto done;
+ }
/*
* Allocate memory for building the header, fill it up,
@@ -1097,7 +1099,8 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
*/
hdr = malloc(hdrsize, M_TEMP, M_WAITOK);
if (hdr == NULL) {
- return (EINVAL);
+ error = EINVAL;
+ goto done;
}
error = __elfN(corehdr)(td, vp, cred, seginfo.count, hdr, hdrsize,
gzfile);
@@ -1125,8 +1128,8 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
curproc->p_comm, error);
}
-#ifdef COMPRESS_USER_CORES
done:
+#ifdef COMPRESS_USER_CORES
if (core_buf)
free(core_buf, M_TEMP);
if (gzfile)
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index ed22519..0ec9817 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -949,17 +949,19 @@ exec_map_first_page(imgp)
ma[0] = vm_page_lookup(object, 0);
if ((rv != VM_PAGER_OK) || (ma[0] == NULL)) {
if (ma[0]) {
+ vm_page_lock(ma[0]);
vm_page_lock_queues();
vm_page_free(ma[0]);
vm_page_unlock_queues();
+ vm_page_unlock(ma[0]);
}
VM_OBJECT_UNLOCK(object);
return (EIO);
}
}
- vm_page_lock_queues();
+ vm_page_lock(ma[0]);
vm_page_hold(ma[0]);
- vm_page_unlock_queues();
+ vm_page_unlock(ma[0]);
vm_page_wakeup(ma[0]);
VM_OBJECT_UNLOCK(object);
@@ -979,9 +981,9 @@ exec_unmap_first_page(imgp)
m = sf_buf_page(imgp->firstpage);
sf_buf_free(imgp->firstpage);
imgp->firstpage = NULL;
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_unhold(m);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
}
}
diff --git a/sys/kern/kern_gzio.c b/sys/kern/kern_gzio.c
index 1f9c387..c1b2b3f 100644
--- a/sys/kern/kern_gzio.c
+++ b/sys/kern/kern_gzio.c
@@ -166,7 +166,7 @@ gzFile gz_open (path, mode, vp)
0 /*xflags*/, OS_CODE);
if ((error = vn_rdwr(UIO_WRITE, s->file, buf, GZ_HEADER_LEN, s->outoff,
- UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, curproc->p_ucred,
+ UIO_SYSSPACE, IO_UNIT, curproc->p_ucred,
NOCRED, &resid, curthread))) {
s->outoff += GZ_HEADER_LEN - resid;
return destroy(s), (gzFile)Z_NULL;
@@ -234,7 +234,7 @@ int ZEXPORT gzwrite (file, buf, len)
s->stream.next_out = s->outbuf;
vfslocked = VFS_LOCK_GIANT(s->file->v_mount);
error = vn_rdwr_inchunks(UIO_WRITE, s->file, s->outbuf, Z_BUFSIZE,
- curoff, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT,
+ curoff, UIO_SYSSPACE, IO_UNIT,
curproc->p_ucred, NOCRED, &resid, curthread);
VFS_UNLOCK_GIANT(vfslocked);
if (error) {
@@ -291,7 +291,7 @@ local int do_flush (file, flush)
if (len != 0) {
vfslocked = VFS_LOCK_GIANT(s->file->v_mount);
error = vn_rdwr_inchunks(UIO_WRITE, s->file, s->outbuf, len, curoff,
- UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, curproc->p_ucred,
+ UIO_SYSSPACE, IO_UNIT, curproc->p_ucred,
NOCRED, &resid, curthread);
VFS_UNLOCK_GIANT(vfslocked);
if (error) {
@@ -350,7 +350,7 @@ local void putU32 (s, x)
xx = x;
#endif
vn_rdwr(UIO_WRITE, s->file, (caddr_t)&xx, sizeof(xx), curoff,
- UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, curproc->p_ucred,
+ UIO_SYSSPACE, IO_UNIT, curproc->p_ucred,
NOCRED, &resid, curthread);
s->outoff += sizeof(xx) - resid;
}
diff --git a/sys/kern/kern_ntptime.c b/sys/kern/kern_ntptime.c
index 2d87740..c427ac4 100644
--- a/sys/kern/kern_ntptime.c
+++ b/sys/kern/kern_ntptime.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
+#include <sys/eventhandler.h>
#include <sys/kernel.h>
#include <sys/priv.h>
#include <sys/proc.h>
@@ -198,22 +199,11 @@ static long pps_errcnt; /* calibration errors */
static void ntp_init(void);
static void hardupdate(long offset);
static void ntp_gettime1(struct ntptimeval *ntvp);
+static int ntp_is_time_error(void);
-static void
-ntp_gettime1(struct ntptimeval *ntvp)
+static int
+ntp_is_time_error(void)
{
- struct timespec atv; /* nanosecond time */
-
- GIANT_REQUIRED;
-
- nanotime(&atv);
- ntvp->time.tv_sec = atv.tv_sec;
- ntvp->time.tv_nsec = atv.tv_nsec;
- ntvp->maxerror = time_maxerror;
- ntvp->esterror = time_esterror;
- ntvp->tai = time_tai;
- ntvp->time_state = time_state;
-
/*
* Status word error decode. If any of these conditions occur,
* an error is returned, instead of the status word. Most
@@ -243,6 +233,27 @@ ntp_gettime1(struct ntptimeval *ntvp)
*/
(time_status & STA_PPSFREQ &&
time_status & (STA_PPSWANDER | STA_PPSERROR)))
+ return (1);
+
+ return (0);
+}
+
+static void
+ntp_gettime1(struct ntptimeval *ntvp)
+{
+ struct timespec atv; /* nanosecond time */
+
+ GIANT_REQUIRED;
+
+ nanotime(&atv);
+ ntvp->time.tv_sec = atv.tv_sec;
+ ntvp->time.tv_nsec = atv.tv_nsec;
+ ntvp->maxerror = time_maxerror;
+ ntvp->esterror = time_esterror;
+ ntvp->tai = time_tai;
+ ntvp->time_state = time_state;
+
+ if (ntp_is_time_error())
ntvp->time_state = TIME_ERROR;
}
@@ -442,21 +453,11 @@ ntp_adjtime(struct thread *td, struct ntp_adjtime_args *uap)
if (error)
goto done2;
- /*
- * Status word error decode. See comments in
- * ntp_gettime() routine.
- */
- if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) ||
- (time_status & (STA_PPSFREQ | STA_PPSTIME) &&
- !(time_status & STA_PPSSIGNAL)) ||
- (time_status & STA_PPSTIME &&
- time_status & STA_PPSJITTER) ||
- (time_status & STA_PPSFREQ &&
- time_status & (STA_PPSWANDER | STA_PPSERROR))) {
+ if (ntp_is_time_error())
td->td_retval[0] = TIME_ERROR;
- } else {
+ else
td->td_retval[0] = time_state;
- }
+
done2:
mtx_unlock(&Giant);
return (error);
@@ -972,3 +973,67 @@ kern_adjtime(struct thread *td, struct timeval *delta, struct timeval *olddelta)
return (0);
}
+static struct callout resettodr_callout;
+static int resettodr_period = 1800;
+
+static void
+periodic_resettodr(void *arg __unused)
+{
+
+ if (!ntp_is_time_error()) {
+ mtx_lock(&Giant);
+ resettodr();
+ mtx_unlock(&Giant);
+ }
+ if (resettodr_period > 0)
+ callout_schedule(&resettodr_callout, resettodr_period * hz);
+}
+
+static void
+shutdown_resettodr(void *arg __unused, int howto __unused)
+{
+
+ callout_drain(&resettodr_callout);
+ if (resettodr_period > 0 && !ntp_is_time_error()) {
+ mtx_lock(&Giant);
+ resettodr();
+ mtx_unlock(&Giant);
+ }
+}
+
+static int
+sysctl_resettodr_period(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+
+ error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+ if (error || !req->newptr)
+ return (error);
+ if (resettodr_period == 0)
+ callout_stop(&resettodr_callout);
+ else
+ callout_reset(&resettodr_callout, resettodr_period * hz,
+ periodic_resettodr, NULL);
+ return (0);
+}
+
+SYSCTL_PROC(_machdep, OID_AUTO, rtc_save_period, CTLTYPE_INT|CTLFLAG_RW,
+ &resettodr_period, 1800, sysctl_resettodr_period, "I",
+ "Save system time to RTC with this period (in seconds)");
+TUNABLE_INT("machdep.rtc_save_period", &resettodr_period);
+
+static void
+start_periodic_resettodr(void *arg __unused)
+{
+
+ EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_resettodr, NULL,
+ SHUTDOWN_PRI_FIRST);
+ callout_init(&resettodr_callout, 1);
+ if (resettodr_period == 0)
+ return;
+ callout_reset(&resettodr_callout, resettodr_period * hz,
+ periodic_resettodr, NULL);
+}
+
+SYSINIT(periodic_resettodr, SI_SUB_RUN_SCHEDULER, SI_ORDER_ANY - 1,
+ start_periodic_resettodr, NULL);
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 5601ecf..055c844 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -901,7 +901,7 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread)
kp->ki_pri.pri_user = td->td_user_pri;
if (preferthread) {
- kp->ki_runtime = cputick2usec(td->td_runtime);
+ kp->ki_runtime = cputick2usec(td->td_rux.rux_runtime);
kp->ki_pctcpu = sched_pctcpu(td);
kp->ki_estcpu = td->td_estcpu;
}
@@ -1084,11 +1084,9 @@ sysctl_out_proc_copyout(struct kinfo_proc *ki, struct sysctl_req *req)
if (req->flags & SCTL_MASK32) {
freebsd32_kinfo_proc_out(ki, &ki32);
- error = SYSCTL_OUT(req, (caddr_t)&ki32,
- sizeof(struct kinfo_proc32));
+ error = SYSCTL_OUT(req, &ki32, sizeof(struct kinfo_proc32));
} else
- error = SYSCTL_OUT(req, (caddr_t)ki,
- sizeof(struct kinfo_proc));
+ error = SYSCTL_OUT(req, ki, sizeof(struct kinfo_proc));
return (error);
}
#else
@@ -1096,7 +1094,7 @@ static int
sysctl_out_proc_copyout(struct kinfo_proc *ki, struct sysctl_req *req)
{
- return (SYSCTL_OUT(req, (caddr_t)ki, sizeof(struct kinfo_proc)));
+ return (SYSCTL_OUT(req, ki, sizeof(struct kinfo_proc)));
}
#endif
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index f867839..0bc78d0 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -76,6 +76,7 @@ static void calcru1(struct proc *p, struct rusage_ext *ruxp,
struct timeval *up, struct timeval *sp);
static int donice(struct thread *td, struct proc *chgp, int n);
static struct uidinfo *uilookup(uid_t uid);
+static void ruxagg(struct proc *p, struct thread *td);
/*
* Resource controls and accounting.
@@ -629,9 +630,7 @@ lim_cb(void *arg)
return;
PROC_SLOCK(p);
FOREACH_THREAD_IN_PROC(p, td) {
- thread_lock(td);
- ruxagg(&p->p_rux, td);
- thread_unlock(td);
+ ruxagg(p, td);
}
PROC_SUNLOCK(p);
if (p->p_rux.rux_runtime > p->p_cpulimit * cpu_tickrate()) {
@@ -842,9 +841,7 @@ calcru(struct proc *p, struct timeval *up, struct timeval *sp)
FOREACH_THREAD_IN_PROC(p, td) {
if (td->td_incruntime == 0)
continue;
- thread_lock(td);
- ruxagg(&p->p_rux, td);
- thread_unlock(td);
+ ruxagg(p, td);
}
calcru1(p, &p->p_rux, up, sp);
}
@@ -945,10 +942,7 @@ getrusage(td, uap)
}
int
-kern_getrusage(td, who, rup)
- struct thread *td;
- int who;
- struct rusage *rup;
+kern_getrusage(struct thread *td, int who, struct rusage *rup)
{
struct proc *p;
int error;
@@ -967,6 +961,16 @@ kern_getrusage(td, who, rup)
calccru(p, &rup->ru_utime, &rup->ru_stime);
break;
+ case RUSAGE_THREAD:
+ PROC_SLOCK(p);
+ ruxagg(p, td);
+ PROC_SUNLOCK(p);
+ thread_lock(td);
+ *rup = td->td_ru;
+ calcru1(p, &td->td_rux, &rup->ru_utime, &rup->ru_stime);
+ thread_unlock(td);
+ break;
+
default:
error = EINVAL;
}
@@ -1007,7 +1011,7 @@ ruadd(struct rusage *ru, struct rusage_ext *rux, struct rusage *ru2,
* Aggregate tick counts into the proc's rusage_ext.
*/
void
-ruxagg(struct rusage_ext *rux, struct thread *td)
+ruxagg_locked(struct rusage_ext *rux, struct thread *td)
{
THREAD_LOCK_ASSERT(td, MA_OWNED);
@@ -1016,10 +1020,20 @@ ruxagg(struct rusage_ext *rux, struct thread *td)
rux->rux_uticks += td->td_uticks;
rux->rux_sticks += td->td_sticks;
rux->rux_iticks += td->td_iticks;
+}
+
+static void
+ruxagg(struct proc *p, struct thread *td)
+{
+
+ thread_lock(td);
+ ruxagg_locked(&p->p_rux, td);
+ ruxagg_locked(&td->td_rux, td);
td->td_incruntime = 0;
td->td_uticks = 0;
td->td_iticks = 0;
td->td_sticks = 0;
+ thread_unlock(td);
}
/*
@@ -1036,9 +1050,7 @@ rufetch(struct proc *p, struct rusage *ru)
*ru = p->p_ru;
if (p->p_numthreads > 0) {
FOREACH_THREAD_IN_PROC(p, td) {
- thread_lock(td);
- ruxagg(&p->p_rux, td);
- thread_unlock(td);
+ ruxagg(p, td);
rucollect(ru, &td->td_ru);
}
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 706433d..789bb61 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -3004,8 +3004,9 @@ expand_name(const char *name, uid_t uid, pid_t pid, struct thread *td,
char *temp;
size_t i;
int indexpos;
- char hostname[MAXHOSTNAMELEN];
+ char *hostname;
+ hostname = NULL;
format = corefilename;
temp = malloc(MAXPATHLEN, M_TEMP, M_NOWAIT | M_ZERO);
if (temp == NULL)
@@ -3021,8 +3022,21 @@ expand_name(const char *name, uid_t uid, pid_t pid, struct thread *td,
sbuf_putc(&sb, '%');
break;
case 'H': /* hostname */
+ if (hostname == NULL) {
+ hostname = malloc(MAXHOSTNAMELEN,
+ M_TEMP, M_NOWAIT);
+ if (hostname == NULL) {
+ log(LOG_ERR,
+ "pid %ld (%s), uid (%lu): "
+ "unable to alloc memory "
+ "for corefile hostname\n",
+ (long)pid, name,
+ (u_long)uid);
+ goto nomem;
+ }
+ }
getcredhostname(td->td_ucred, hostname,
- sizeof(hostname));
+ MAXHOSTNAMELEN);
sbuf_printf(&sb, "%s", hostname);
break;
case 'I': /* autoincrementing index */
@@ -3048,15 +3062,17 @@ expand_name(const char *name, uid_t uid, pid_t pid, struct thread *td,
sbuf_putc(&sb, format[i]);
}
}
+ free(hostname, M_TEMP);
#ifdef COMPRESS_USER_CORES
if (compress) {
sbuf_printf(&sb, GZ_SUFFIX);
}
#endif
if (sbuf_overflowed(&sb)) {
- sbuf_delete(&sb);
log(LOG_ERR, "pid %ld (%s), uid (%lu): corename is too "
"long\n", (long)pid, name, (u_long)uid);
+nomem:
+ sbuf_delete(&sb);
free(temp, M_TEMP);
return (NULL);
}
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index 9be4c2f3e..d7a9199 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -398,7 +398,7 @@ thread_exit(void)
/*
* The test below is NOT true if we are the
- * sole exiting thread. P_STOPPED_SNGL is unset
+ * sole exiting thread. P_STOPPED_SINGLE is unset
* in exit1() after it is the only survivor.
*/
if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) {
@@ -431,8 +431,7 @@ thread_exit(void)
#endif
PROC_UNLOCK(p);
thread_lock(td);
- /* Save our tick information with both the thread and proc locked */
- ruxagg(&p->p_rux, td);
+ ruxagg_locked(&p->p_rux, td);
PROC_SUNLOCK(p);
td->td_state = TDS_INACTIVE;
#ifdef WITNESS
diff --git a/sys/kern/subr_bufring.c b/sys/kern/subr_bufring.c
index 63938ea..4cd3929 100644
--- a/sys/kern/subr_bufring.c
+++ b/sys/kern/subr_bufring.c
@@ -1,32 +1,29 @@
-/**************************************************************************
- *
- * Copyright (c) 2007,2008 Kip Macy kmacy@freebsd.org
+/*-
+ * Copyright (c) 2007, 2008 Kip Macy <kmacy@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. The name of Kip Macy nor the names of other
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- *
- ***************************************************************************/
+ * 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$");
diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c
index 8405b3d..3b18269 100644
--- a/sys/kern/subr_taskqueue.c
+++ b/sys/kern/subr_taskqueue.c
@@ -51,7 +51,6 @@ struct taskqueue {
const char *tq_name;
taskqueue_enqueue_fn tq_enqueue;
void *tq_context;
- struct task *tq_running;
struct mtx tq_mutex;
struct thread **tq_threads;
int tq_tcount;
@@ -233,13 +232,13 @@ taskqueue_run(struct taskqueue *queue)
STAILQ_REMOVE_HEAD(&queue->tq_queue, ta_link);
pending = task->ta_pending;
task->ta_pending = 0;
- queue->tq_running = task;
+ task->ta_flags |= TA_FLAGS_RUNNING;
TQ_UNLOCK(queue);
task->ta_func(task->ta_context, pending);
TQ_LOCK(queue);
- queue->tq_running = NULL;
+ task->ta_flags &= ~TA_FLAGS_RUNNING;
wakeup(task);
}
@@ -256,14 +255,16 @@ taskqueue_drain(struct taskqueue *queue, struct task *task)
{
if (queue->tq_spin) { /* XXX */
mtx_lock_spin(&queue->tq_mutex);
- while (task->ta_pending != 0 || task == queue->tq_running)
+ while (task->ta_pending != 0 ||
+ (task->ta_flags & TA_FLAGS_RUNNING) != 0)
msleep_spin(task, &queue->tq_mutex, "-", 0);
mtx_unlock_spin(&queue->tq_mutex);
} else {
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, __func__);
mtx_lock(&queue->tq_mutex);
- while (task->ta_pending != 0 || task == queue->tq_running)
+ while (task->ta_pending != 0 ||
+ (task->ta_flags & TA_FLAGS_RUNNING) != 0)
msleep(task, &queue->tq_mutex, PWAIT, "-", 0);
mtx_unlock(&queue->tq_mutex);
}
diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c
index 725b1a8..783a8d6 100644
--- a/sys/kern/subr_uio.c
+++ b/sys/kern/subr_uio.c
@@ -104,9 +104,11 @@ retry:
if ((user_pg = vm_page_lookup(uobject, upindex)) != NULL) {
if (vm_page_sleep_if_busy(user_pg, TRUE, "vm_pgmoveco"))
goto retry;
+ vm_page_lock(user_pg);
vm_page_lock_queues();
pmap_remove_all(user_pg);
vm_page_free(user_pg);
+ vm_page_unlock(user_pg);
} else {
/*
* Even if a physical page does not exist in the
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 5b7d565..ef1bc39 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -597,6 +597,15 @@ static struct witness_order_list_entry order_lists[] = {
{ "cdev", &lock_class_mtx_sleep },
{ NULL, NULL },
/*
+ * VM
+ *
+ */
+ { "vm object", &lock_class_mtx_sleep },
+ { "page lock", &lock_class_mtx_sleep },
+ { "vm page queue mutex", &lock_class_mtx_sleep },
+ { "pmap", &lock_class_mtx_sleep },
+ { NULL, NULL },
+ /*
* kqueue/VFS interaction
*/
{ "kqueue", &lock_class_mtx_sleep },
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index e098648..7130c26 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -773,10 +773,12 @@ pipe_build_write_buffer(wpipe, uio)
*/
race:
if (vm_fault_quick((caddr_t)addr, VM_PROT_READ) < 0) {
- vm_page_lock_queues();
- for (j = 0; j < i; j++)
+
+ for (j = 0; j < i; j++) {
+ vm_page_lock(wpipe->pipe_map.ms[j]);
vm_page_unhold(wpipe->pipe_map.ms[j]);
- vm_page_unlock_queues();
+ vm_page_unlock(wpipe->pipe_map.ms[j]);
+ }
return (EFAULT);
}
wpipe->pipe_map.ms[i] = pmap_extract_and_hold(pmap, addr,
@@ -816,11 +818,11 @@ pipe_destroy_write_buffer(wpipe)
int i;
PIPE_LOCK_ASSERT(wpipe, MA_OWNED);
- vm_page_lock_queues();
for (i = 0; i < wpipe->pipe_map.npages; i++) {
+ vm_page_lock(wpipe->pipe_map.ms[i]);
vm_page_unhold(wpipe->pipe_map.ms[i]);
+ vm_page_unlock(wpipe->pipe_map.ms[i]);
}
- vm_page_unlock_queues();
wpipe->pipe_map.npages = 0;
}
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index f5671d9..d8cc4f0 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -328,9 +328,9 @@ proc_rwmem(struct proc *p, struct uio *uio)
/*
* Hold the page in memory.
*/
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_hold(m);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
/*
* We're done with tmap now.
@@ -349,9 +349,9 @@ proc_rwmem(struct proc *p, struct uio *uio)
/*
* Release the page.
*/
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_unhold(m);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
} while (error == 0 && uio->uio_resid > 0);
diff --git a/sys/kern/uipc_cow.c b/sys/kern/uipc_cow.c
index 52988dd..bc9a56a 100644
--- a/sys/kern/uipc_cow.c
+++ b/sys/kern/uipc_cow.c
@@ -80,6 +80,7 @@ socow_iodone(void *addr, void *args)
pp = sf_buf_page(sf);
sf_buf_free(sf);
/* remove COW mapping */
+ vm_page_lock(pp);
vm_page_lock_queues();
vm_page_cowclear(pp);
vm_page_unwire(pp, 0);
@@ -91,6 +92,7 @@ socow_iodone(void *addr, void *args)
if (pp->wire_count == 0 && pp->object == NULL)
vm_page_free(pp);
vm_page_unlock_queues();
+ vm_page_unlock(pp);
socow_stats.iodone++;
}
@@ -128,10 +130,10 @@ socow_setup(struct mbuf *m0, struct uio *uio)
/*
* set up COW
*/
- vm_page_lock_queues();
+ vm_page_lock(pp);
if (vm_page_cowsetup(pp) != 0) {
vm_page_unhold(pp);
- vm_page_unlock_queues();
+ vm_page_unlock(pp);
return (0);
}
@@ -140,13 +142,13 @@ socow_setup(struct mbuf *m0, struct uio *uio)
*/
vm_page_wire(pp);
vm_page_unhold(pp);
- vm_page_unlock_queues();
-
+ vm_page_unlock(pp);
/*
* Allocate an sf buf
*/
sf = sf_buf_alloc(pp, SFB_CATCH);
if (!sf) {
+ vm_page_lock(pp);
vm_page_lock_queues();
vm_page_cowclear(pp);
vm_page_unwire(pp, 0);
@@ -158,6 +160,7 @@ socow_setup(struct mbuf *m0, struct uio *uio)
if (pp->wire_count == 0 && pp->object == NULL)
vm_page_free(pp);
vm_page_unlock_queues();
+ vm_page_unlock(pp);
socow_stats.fail_sf_buf++;
return(0);
}
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index bc0e88d..85e0e39 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -948,9 +948,8 @@ m_adj(struct mbuf *mp, int req_len)
len = 0;
}
}
- m = mp;
if (mp->m_flags & M_PKTHDR)
- m->m_pkthdr.len -= (req_len - len);
+ mp->m_pkthdr.len -= (req_len - len);
} else {
/*
* Trim from tail. Scan the mbuf chain,
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index a14be72..a137875 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -1715,6 +1715,7 @@ sf_buf_mext(void *addr, void *args)
m = sf_buf_page(args);
sf_buf_free(args);
+ vm_page_lock(m);
vm_page_lock_queues();
vm_page_unwire(m, 0);
/*
@@ -1725,6 +1726,7 @@ sf_buf_mext(void *addr, void *args)
if (m->wire_count == 0 && m->object == NULL)
vm_page_free(m);
vm_page_unlock_queues();
+ vm_page_unlock(m);
if (addr == NULL)
return;
sfs = addr;
@@ -2108,6 +2110,7 @@ retry_space:
mbstat.sf_iocnt++;
}
if (error) {
+ vm_page_lock(pg);
vm_page_lock_queues();
vm_page_unwire(pg, 0);
/*
@@ -2121,6 +2124,7 @@ retry_space:
vm_page_free(pg);
}
vm_page_unlock_queues();
+ vm_page_unlock(pg);
VM_OBJECT_UNLOCK(obj);
if (error == EAGAIN)
error = 0; /* not a real error */
@@ -2134,6 +2138,7 @@ retry_space:
if ((sf = sf_buf_alloc(pg,
(mnw ? SFB_NOWAIT : SFB_CATCH))) == NULL) {
mbstat.sf_allocfail++;
+ vm_page_lock(pg);
vm_page_lock_queues();
vm_page_unwire(pg, 0);
/*
@@ -2142,6 +2147,7 @@ retry_space:
if (pg->wire_count == 0 && pg->object == NULL)
vm_page_free(pg);
vm_page_unlock_queues();
+ vm_page_unlock(pg);
error = (mnw ? EAGAIN : EINTR);
break;
}
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 156b676..ec8ad67 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -1563,7 +1563,6 @@ vfs_vmio_release(struct buf *bp)
vm_page_t m;
VM_OBJECT_LOCK(bp->b_bufobj->bo_object);
- vm_page_lock_queues();
for (i = 0; i < bp->b_npages; i++) {
m = bp->b_pages[i];
bp->b_pages[i] = NULL;
@@ -1571,16 +1570,16 @@ vfs_vmio_release(struct buf *bp)
* In order to keep page LRU ordering consistent, put
* everything on the inactive queue.
*/
+ vm_page_lock(m);
vm_page_unwire(m, 0);
/*
* We don't mess with busy pages, it is
* the responsibility of the process that
* busied the pages to deal with them.
*/
- if ((m->oflags & VPO_BUSY) || (m->busy != 0))
- continue;
-
- if (m->wire_count == 0) {
+ if ((m->oflags & VPO_BUSY) == 0 && m->busy == 0 &&
+ m->wire_count == 0) {
+ vm_page_lock_queues();
/*
* Might as well free the page if we can and it has
* no valid data. We also free the page if the
@@ -1594,9 +1593,10 @@ vfs_vmio_release(struct buf *bp)
} else if (buf_vm_page_count_severe()) {
vm_page_try_to_cache(m);
}
+ vm_page_unlock_queues();
}
+ vm_page_unlock(m);
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(bp->b_bufobj->bo_object);
pmap_qremove(trunc_page((vm_offset_t) bp->b_data), bp->b_npages);
@@ -2942,7 +2942,6 @@ allocbuf(struct buf *bp, int size)
vm_page_t m;
VM_OBJECT_LOCK(bp->b_bufobj->bo_object);
- vm_page_lock_queues();
for (i = desiredpages; i < bp->b_npages; i++) {
/*
* the page is not freed here -- it
@@ -2952,13 +2951,15 @@ allocbuf(struct buf *bp, int size)
m = bp->b_pages[i];
KASSERT(m != bogus_page,
("allocbuf: bogus page found"));
- while (vm_page_sleep_if_busy(m, TRUE, "biodep"))
- vm_page_lock_queues();
+ while (vm_page_sleep_if_busy(m, TRUE,
+ "biodep"))
+ continue;
bp->b_pages[i] = NULL;
+ vm_page_lock(m);
vm_page_unwire(m, 0);
+ vm_page_unlock(m);
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(bp->b_bufobj->bo_object);
pmap_qremove((vm_offset_t) trunc_page((vm_offset_t)bp->b_data) +
(desiredpages << PAGE_SHIFT), (bp->b_npages - desiredpages));
@@ -3024,15 +3025,24 @@ allocbuf(struct buf *bp, int size)
* vm_fault->getpages->cluster_read->allocbuf
*
*/
- if (vm_page_sleep_if_busy(m, FALSE, "pgtblk"))
+ if ((m->oflags & VPO_BUSY) != 0) {
+ /*
+ * Reference the page before unlocking
+ * and sleeping so that the page daemon
+ * is less likely to reclaim it.
+ */
+ vm_page_lock_queues();
+ vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_sleep(m, "pgtblk");
continue;
+ }
/*
* We have a good page.
*/
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_wire(m);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
bp->b_pages[bp->b_npages] = m;
++bp->b_npages;
}
@@ -3860,12 +3870,12 @@ vmapbuf(struct buf *bp)
retry:
if (vm_fault_quick(addr >= bp->b_data ? addr : bp->b_data,
prot) < 0) {
- vm_page_lock_queues();
for (i = 0; i < pidx; ++i) {
+ vm_page_lock(bp->b_pages[i]);
vm_page_unhold(bp->b_pages[i]);
+ vm_page_unlock(bp->b_pages[i]);
bp->b_pages[i] = NULL;
}
- vm_page_unlock_queues();
return(-1);
}
m = pmap_extract_and_hold(pmap, (vm_offset_t)addr, prot);
@@ -3896,11 +3906,12 @@ vunmapbuf(struct buf *bp)
npages = bp->b_npages;
pmap_qremove(trunc_page((vm_offset_t)bp->b_data), npages);
- vm_page_lock_queues();
- for (pidx = 0; pidx < npages; pidx++)
+ for (pidx = 0; pidx < npages; pidx++) {
+ vm_page_lock(bp->b_pages[pidx]);
vm_page_unhold(bp->b_pages[pidx]);
- vm_page_unlock_queues();
-
+ vm_page_unlock(bp->b_pages[pidx]);
+ }
+
bp->b_data = bp->b_saveaddr;
}
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 838f8f7..edc7ea8 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/filio.h>
+#include <sys/resourcevar.h>
#include <sys/sx.h>
#include <sys/ttycom.h>
#include <sys/conf.h>
@@ -1338,3 +1339,21 @@ vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags, struct vnode **rvp)
}
return (error);
}
+
+int
+vn_rlimit_fsize(const struct vnode *vp, const struct uio *uio, const struct thread *td)
+{
+ if (vp->v_type != VREG || td == NULL)
+ return (0);
+
+ PROC_LOCK(td->td_proc);
+ if (uio->uio_offset + uio->uio_resid >
+ lim_cur(td->td_proc, RLIMIT_FSIZE)) {
+ psignal(td->td_proc, SIGXFSZ);
+ PROC_UNLOCK(td->td_proc);
+ return (EFBIG);
+ }
+ PROC_UNLOCK(td->td_proc);
+
+ return (0);
+}
diff --git a/sys/mips/adm5120/if_admsw.c b/sys/mips/adm5120/if_admsw.c
index 164e840..472a804 100644
--- a/sys/mips/adm5120/if_admsw.c
+++ b/sys/mips/adm5120/if_admsw.c
@@ -540,8 +540,8 @@ admsw_attach(device_t dev)
ifp->if_init = admsw_init;
ifp->if_mtu = ETHERMTU;
ifp->if_baudrate = IF_Mbps(100);
- IFQ_SET_MAXLEN(&ifp->if_snd, max(ADMSW_NTXLDESC, IFQ_MAXLEN));
- ifp->if_snd.ifq_drv_maxlen = max(ADMSW_NTXLDESC, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&ifp->if_snd, max(ADMSW_NTXLDESC, ifqmaxlen));
+ ifp->if_snd.ifq_drv_maxlen = max(ADMSW_NTXLDESC, ifqmaxlen);
IFQ_SET_READY(&ifp->if_snd);
ifp->if_capabilities |= IFCAP_VLAN_MTU;
diff --git a/sys/mips/atheros/if_arge.c b/sys/mips/atheros/if_arge.c
index 4367bfb..eef1dcf 100644
--- a/sys/mips/atheros/if_arge.c
+++ b/sys/mips/atheros/if_arge.c
@@ -312,8 +312,8 @@ arge_attach(device_t dev)
sc->arge_if_flags = ifp->if_flags;
/* XXX: add real size */
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ifp->if_capenable = ifp->if_capabilities;
diff --git a/sys/mips/cavium/uart_dev_oct16550.c b/sys/mips/cavium/uart_dev_oct16550.c
index 3e6d7c7..5c6e11e 100644
--- a/sys/mips/cavium/uart_dev_oct16550.c
+++ b/sys/mips/cavium/uart_dev_oct16550.c
@@ -644,12 +644,9 @@ oct16550_bus_ipend(struct uart_softc *sc)
if (ipend) octeon_led_run_wheel(&where1, 6 + device_get_unit(sc->sc_dev));
#endif
- return ((sc->sc_leaving) ? 0 : ipend);
+ return (ipend);
}
-
-
-
static int
oct16550_bus_param (struct uart_softc *sc, int baudrate, int databits,
int stopbits, int parity)
diff --git a/sys/mips/conf/AR71XX b/sys/mips/conf/AR71XX
index 4ee6aab..12c73da 100644
--- a/sys/mips/conf/AR71XX
+++ b/sys/mips/conf/AR71XX
@@ -29,11 +29,11 @@ options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
# options NFS_LEGACYRPC
# Debugging for use in -current
-# options DEADLKRES
-# options INVARIANTS
-# options INVARIANT_SUPPORT
-# options WITNESS
-# options WITNESS_SKIPSPIN
+options DEADLKRES
+options INVARIANTS
+options INVARIANT_SUPPORT
+options WITNESS
+options WITNESS_SKIPSPIN
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options UFS_ACL #Support for access control lists
@@ -62,6 +62,7 @@ device ath # Atheros pci/cardbus NIC's
options ATH_DEBUG
device ath_hal
option AH_SUPPORT_AR5416
+option AH_RXCFG_SDMAMW_4BYTES # See NOTES for details of this WAR
device ath_rate_sample
device mii
diff --git a/sys/mips/include/pmap.h b/sys/mips/include/pmap.h
index 80772d9..f4df6ca 100644
--- a/sys/mips/include/pmap.h
+++ b/sys/mips/include/pmap.h
@@ -88,6 +88,8 @@ struct pmap {
pd_entry_t *pm_segtab; /* KVA of segment table */
TAILQ_HEAD(, pv_entry) pm_pvlist; /* list of mappings in
* pmap */
+ uint32_t pm_gen_count; /* generation count (pmap lock dropped) */
+ u_int pm_retries;
int pm_active; /* active on cpus */
struct {
u_int32_t asid:ASID_BITS; /* TLB address space tag */
diff --git a/sys/mips/include/proc.h b/sys/mips/include/proc.h
index 1479eda..e71c858 100644
--- a/sys/mips/include/proc.h
+++ b/sys/mips/include/proc.h
@@ -69,9 +69,9 @@ void mips_cpu_switch(struct thread *, struct thread *, struct mtx *);
void mips_cpu_throw(struct thread *, struct thread *);
#ifdef __mips_n64
-#define KINFO_PROC_SIZE 1088
+#define KINFO_PROC_SIZE 1088
#else
-#define KINFO_PROC_SIZE 816
+#define KINFO_PROC_SIZE 816
#endif
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/mips/mips/db_trace.c b/sys/mips/mips/db_trace.c
index 9417bcc..116470c 100644
--- a/sys/mips/mips/db_trace.c
+++ b/sys/mips/mips/db_trace.c
@@ -181,7 +181,7 @@ loop:
}
/* check for bad PC */
/*XXX MIPS64 bad: These hard coded constants are lame */
- if (pc & 3 || pc < (uintptr_t)0x80000000 || pc >= (uintptr_t)edata) {
+ if (pc & 3 || pc < (uintptr_t)0x80000000) {
(*printfn) ("PC 0x%x: not in kernel\n", pc);
ra = 0;
goto done;
diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c
index 3634a27..af9ef43 100644
--- a/sys/mips/mips/pmap.c
+++ b/sys/mips/mips/pmap.c
@@ -147,7 +147,6 @@ unsigned pmap_max_asid; /* max ASID supported by the system */
#define PMAP_ASID_RESERVED 0
-
vm_offset_t kernel_vm_end;
static struct tlb tlbstash[MAXCPU][MIPS_MAX_TLB_ENTRIES];
@@ -237,7 +236,7 @@ caddr_t virtual_sys_start = (caddr_t)0;
sched_pin(); \
va1 = sysm->base; \
va2 = sysm->base + PAGE_SIZE; \
- npte = mips_paddr_to_tlbpfn(phys2) | \
+ npte = mips_paddr_to_tlbpfn(phys1) | \
PTE_RW | PTE_V | PTE_G | PTE_W | PTE_CACHE; \
pte = pmap_pte(kernel_pmap, va1); \
*pte = npte; \
@@ -710,18 +709,22 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
{
pt_entry_t pte;
vm_page_t m;
+ vm_paddr_t pa;
m = NULL;
- vm_page_lock_queues();
+ pa = 0;
PMAP_LOCK(pmap);
-
+retry:
pte = *pmap_pte(pmap, va);
if (pte != 0 && pmap_pte_v(&pte) &&
((pte & PTE_RW) || (prot & VM_PROT_WRITE) == 0)) {
+ if (vm_page_pa_tryrelock(pmap, mips_tlbpfn_to_paddr(pte), &pa))
+ goto retry;
+
m = PHYS_TO_VM_PAGE(mips_tlbpfn_to_paddr(pte));
vm_page_hold(m);
}
- vm_page_unlock_queues();
+ PA_UNLOCK_COND(pa);
PMAP_UNLOCK(pmap);
return (m);
}
@@ -1690,16 +1693,10 @@ retry:
obits = pbits = *pte;
pa = mips_tlbpfn_to_paddr(pbits);
- if (page_is_managed(pa)) {
+ if (page_is_managed(pa) && (pbits & PTE_M) != 0) {
m = PHYS_TO_VM_PAGE(pa);
- if (m->md.pv_flags & PV_TABLE_REF) {
- vm_page_flag_set(m, PG_REFERENCED);
- m->md.pv_flags &= ~PV_TABLE_REF;
- }
- if (pbits & PTE_M) {
- vm_page_dirty(m);
- m->md.pv_flags &= ~PV_TABLE_MOD;
- }
+ vm_page_dirty(m);
+ m->md.pv_flags &= ~PV_TABLE_MOD;
}
pbits = (pbits & ~PTE_M) | PTE_RO;
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 83c7757..601b73b 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -188,6 +188,7 @@ SUBDIR= ${_3dfx} \
msdosfs_iconv \
${_mse} \
msk \
+ mvs \
mwl \
mxge \
my \
diff --git a/sys/modules/acpi/acpi/Makefile b/sys/modules/acpi/acpi/Makefile
index 6fa36ff..2606023 100644
--- a/sys/modules/acpi/acpi/Makefile
+++ b/sys/modules/acpi/acpi/Makefile
@@ -33,8 +33,8 @@ SRCS+= dmbuffer.c dmnames.c dmopcode.c dmobject.c dmresrc.c dmresrcl.c
SRCS+= dmresrcs.c dmutils.c dmwalk.c
SRCS+= dsfield.c dsinit.c dsmethod.c dsmthdat.c dsobject.c dsopcode.c
SRCS+= dsutils.c dswexec.c dswload.c dswscope.c dswstate.c
-SRCS+= evevent.c evgpe.c evgpeblk.c evmisc.c evregion.c evrgnini.c evsci.c
-SRCS+= evxface.c evxfevnt.c evxfregn.c
+SRCS+= evevent.c evgpe.c evgpeblk.c evgpeinit.c evgpeutil.c evmisc.c
+SRCS+= evregion.c evrgnini.c evsci.c evxface.c evxfevnt.c evxfregn.c
SRCS+= exconfig.c exconvrt.c excreate.c exdebug.c exdump.c exfield.c
SRCS+= exfldio.c exmisc.c exmutex.c exnames.c exoparg1.c exoparg2.c
SRCS+= exoparg3.c exoparg6.c exprep.c exregion.c exresnte.c exresolv.c
diff --git a/sys/modules/mvs/Makefile b/sys/modules/mvs/Makefile
new file mode 100644
index 0000000..f33a092
--- /dev/null
+++ b/sys/modules/mvs/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/mvs
+
+KMOD= mvs
+SRCS= mvs.c mvs_pci.c mvs.h mvs_if.h device_if.h bus_if.h pci_if.h opt_cam.h
+
+MFILES= kern/bus_if.m kern/device_if.m dev/pci/pci_if.m dev/mvs/mvs_if.m
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/usb/usb/Makefile b/sys/modules/usb/usb/Makefile
index 5b0104e..32a2107 100644
--- a/sys/modules/usb/usb/Makefile
+++ b/sys/modules/usb/usb/Makefile
@@ -31,7 +31,7 @@ S= ${.CURDIR}/../../..
KMOD= usb
SRCS= bus_if.h device_if.h usb_if.h usb_if.c vnode_if.h \
- opt_usb.h opt_bus.h \
+ opt_usb.h opt_bus.h opt_ddb.h \
usbdevs.h usbdevs_data.h \
usb_busdma.c usb_controller.c usb_compat_linux.c usb_core.c usb_debug.c \
usb_dev.c usb_device.c usb_dynamic.c usb_error.c usb_generic.c \
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 1755ec7..16245c9 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -1454,6 +1454,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
/* FALLSTHROUGH */
default:
+ CURVNET_RESTORE();
return (EINVAL);
}
@@ -1461,6 +1462,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
if (d->bd_sbuf != NULL || d->bd_hbuf != NULL ||
d->bd_fbuf != NULL || d->bd_bif != NULL) {
BPFD_UNLOCK(d);
+ CURVNET_RESTORE();
return (EBUSY);
}
d->bd_bufmode = *(u_int *)addr;
@@ -1468,13 +1470,16 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
break;
case BIOCGETZMAX:
- return (bpf_ioctl_getzmax(td, d, (size_t *)addr));
+ error = bpf_ioctl_getzmax(td, d, (size_t *)addr);
+ break;
case BIOCSETZBUF:
- return (bpf_ioctl_setzbuf(td, d, (struct bpf_zbuf *)addr));
+ error = bpf_ioctl_setzbuf(td, d, (struct bpf_zbuf *)addr);
+ break;
case BIOCROTZBUF:
- return (bpf_ioctl_rotzbuf(td, d, (struct bpf_zbuf *)addr));
+ error = bpf_ioctl_rotzbuf(td, d, (struct bpf_zbuf *)addr);
+ break;
}
CURVNET_RESTORE();
return (error);
diff --git a/sys/net/bpf_zerocopy.c b/sys/net/bpf_zerocopy.c
index a1dd923..5629093 100644
--- a/sys/net/bpf_zerocopy.c
+++ b/sys/net/bpf_zerocopy.c
@@ -112,11 +112,13 @@ static void
zbuf_page_free(vm_page_t pp)
{
+ vm_page_lock(pp);
vm_page_lock_queues();
vm_page_unwire(pp, 0);
if (pp->wire_count == 0 && pp->object == NULL)
vm_page_free(pp);
vm_page_unlock_queues();
+ vm_page_unlock(pp);
}
/*
@@ -168,10 +170,10 @@ zbuf_sfbuf_get(struct vm_map *map, vm_offset_t uaddr)
VM_PROT_WRITE);
if (pp == NULL)
return (NULL);
- vm_page_lock_queues();
+ vm_page_lock(pp);
vm_page_wire(pp);
vm_page_unhold(pp);
- vm_page_unlock_queues();
+ vm_page_unlock(pp);
sf = sf_buf_alloc(pp, SFB_NOWAIT);
if (sf == NULL) {
zbuf_page_free(pp);
diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c
index 39b6b40..0e4beb4 100644
--- a/sys/net/flowtable.c
+++ b/sys/net/flowtable.c
@@ -1626,7 +1626,7 @@ flowtable_init(const void *unused __unused)
EVENTHANDLER_PRI_ANY);
flowclean_freq = 20*hz;
}
-SYSINIT(flowtable_init, SI_SUB_SMP, SI_ORDER_MIDDLE,
+SYSINIT(flowtable_init, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST,
flowtable_init, NULL);
diff --git a/sys/net/if.c b/sys/net/if.c
index 98c8afa..780f2c2 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -104,6 +104,10 @@ struct ifindex_entry {
SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
+TUNABLE_INT("net.link.ifqmaxlen", &ifqmaxlen);
+SYSCTL_UINT(_net_link, OID_AUTO, ifqmaxlen, CTLFLAG_RDTUN,
+ &ifqmaxlen, 0, "max send queue size");
+
/* Log link state change events */
static int log_link_state_change = 1;
@@ -163,9 +167,11 @@ static void if_detach_internal(struct ifnet *, int);
extern void nd6_setmtu(struct ifnet *);
#endif
+VNET_DEFINE(int, if_index);
+int ifqmaxlen = IFQ_MAXLEN;
VNET_DEFINE(struct ifnethead, ifnet); /* depend on static init XXX */
VNET_DEFINE(struct ifgrouphead, ifg_head);
-VNET_DEFINE(int, if_index);
+
static VNET_DEFINE(int, if_indexlim) = 8;
/* Table of ifnet by index. */
@@ -174,8 +180,6 @@ static VNET_DEFINE(struct ifindex_entry *, ifindex_table);
#define V_if_indexlim VNET(if_indexlim)
#define V_ifindex_table VNET(ifindex_table)
-int ifqmaxlen = IFQ_MAXLEN;
-
/*
* The global network interface list (V_ifnet) and related state (such as
* if_index, if_indexlim, and ifindex_table) are protected by an sxlock and
diff --git a/sys/net/if_ef.c b/sys/net/if_ef.c
index 94fb03d..61f7cb7 100644
--- a/sys/net/if_ef.c
+++ b/sys/net/if_ef.c
@@ -129,7 +129,7 @@ ef_attach(struct efnet *sc)
ifp->if_start = ef_start;
ifp->if_init = ef_init;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
/*
* Attach the interface
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index 22ef6ab..7683839 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -94,20 +94,9 @@
*/
static struct mtx gif_mtx;
static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
-
static VNET_DEFINE(LIST_HEAD(, gif_softc), gif_softc_list);
-
#define V_gif_softc_list VNET(gif_softc_list)
-#ifdef INET
-VNET_DEFINE(int, ip_gif_ttl) = GIF_TTL;
-#define V_ip_gif_ttl VNET(ip_gif_ttl)
-#endif
-#ifdef INET6
-VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM;
-#define V_ip6_gif_hlim VNET(ip6_gif_hlim)
-#endif
-
void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af);
void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
void (*ng_gif_attach_p)(struct ifnet *ifp);
@@ -135,19 +124,11 @@ SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0,
*/
#define MAX_GIF_NEST 1
#endif
-
static VNET_DEFINE(int, max_gif_nesting) = MAX_GIF_NEST;
#define V_max_gif_nesting VNET(max_gif_nesting)
-
SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW,
&VNET_NAME(max_gif_nesting), 0, "Max nested tunnels");
-#ifdef INET6
-SYSCTL_DECL(_net_inet6_ip6);
-SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_RW,
- &VNET_NAME(ip6_gif_hlim), 0, "");
-#endif
-
/*
* By default, we disallow creation of multiple tunnels between the same
* pair of addresses. Some applications require this functionality so
@@ -159,7 +140,6 @@ static VNET_DEFINE(int, parallel_tunnels) = 1;
static VNET_DEFINE(int, parallel_tunnels) = 0;
#endif
#define V_parallel_tunnels VNET(parallel_tunnels)
-
SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW,
&VNET_NAME(parallel_tunnels), 0, "Allow parallel tunnels?");
@@ -205,7 +185,7 @@ gif_clone_create(ifc, unit, params)
GIF2IFP(sc)->if_ioctl = gif_ioctl;
GIF2IFP(sc)->if_start = gif_start;
GIF2IFP(sc)->if_output = gif_output;
- GIF2IFP(sc)->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ GIF2IFP(sc)->if_snd.ifq_maxlen = ifqmaxlen;
if_attach(GIF2IFP(sc));
bpfattach(GIF2IFP(sc), DLT_NULL, sizeof(u_int32_t));
if (ng_gif_attach_p != NULL)
diff --git a/sys/net/if_gif.h b/sys/net/if_gif.h
index 18b7831..5d0db6d 100644
--- a/sys/net/if_gif.h
+++ b/sys/net/if_gif.h
@@ -118,10 +118,6 @@ int gif_ioctl(struct ifnet *, u_long, caddr_t);
int gif_set_tunnel(struct ifnet *, struct sockaddr *, struct sockaddr *);
void gif_delete_tunnel(struct ifnet *);
int gif_encapcheck(const struct mbuf *, int, int, void *);
-
-VNET_DECLARE(int, ip_gif_ttl);
-#define V_ip_gif_ttl VNET(ip_gif_ttl)
-
#endif /* _KERNEL */
#define GIFGOPTS _IOWR('i', 150, struct ifreq)
diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c
index bac3d795..1f1e108 100644
--- a/sys/net/if_gre.c
+++ b/sys/net/if_gre.c
@@ -184,7 +184,7 @@ gre_clone_create(ifc, unit, params)
GRE2IFP(sc)->if_softc = sc;
if_initname(GRE2IFP(sc), ifc->ifc_name, unit);
- GRE2IFP(sc)->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ GRE2IFP(sc)->if_snd.ifq_maxlen = ifqmaxlen;
GRE2IFP(sc)->if_addrlen = 0;
GRE2IFP(sc)->if_hdrlen = 24; /* IP + GRE */
GRE2IFP(sc)->if_mtu = GREMTU;
diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c
index 5c082c4..1ef5581 100644
--- a/sys/net/if_stf.c
+++ b/sys/net/if_stf.c
@@ -252,7 +252,7 @@ stf_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
ifp->if_mtu = IPV6_MMTU;
ifp->if_ioctl = stf_ioctl;
ifp->if_output = stf_output;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
if_attach(ifp);
bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
return (0);
diff --git a/sys/net/route.c b/sys/net/route.c
index e500ed1..b45361e 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -88,15 +88,14 @@ SYSCTL_INT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RW,
&rt_add_addr_allfibs, 0, "");
TUNABLE_INT("net.add_addr_allfibs", &rt_add_addr_allfibs);
-VNET_DEFINE(struct radix_node_head *, rt_tables);
-static VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */
-VNET_DEFINE(int, rttrash); /* routes not in table but not freed */
VNET_DEFINE(struct rtstat, rtstat);
+#define V_rtstat VNET(rtstat)
+VNET_DEFINE(struct radix_node_head *, rt_tables);
#define V_rt_tables VNET(rt_tables)
-#define V_rtzone VNET(rtzone)
+
+VNET_DEFINE(int, rttrash); /* routes not in table but not freed */
#define V_rttrash VNET(rttrash)
-#define V_rtstat VNET(rtstat)
/* compare two sockaddr structures */
@@ -114,6 +113,9 @@ VNET_DEFINE(struct rtstat, rtstat);
*/
#define RNTORT(p) ((struct rtentry *)(p))
+static VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */
+#define V_rtzone VNET(rtzone)
+
#if 0
/* default fib for tunnels to use */
u_int tunnel_fib = 0;
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
index 3d5669c..97ff7c2 100644
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -394,8 +394,8 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
ifp->if_ioctl = ieee80211_ioctl;
ifp->if_init = ieee80211_init;
/* NB: input+output filled in by ether_ifattach */
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
vap->iv_ifp = ifp;
diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c
index 6111058..7902545 100644
--- a/sys/net80211/ieee80211_amrr.c
+++ b/sys/net80211/ieee80211_amrr.c
@@ -136,16 +136,16 @@ amrr_node_init(struct ieee80211_node *ni)
struct ieee80211_amrr *amrr = vap->iv_rs;
struct ieee80211_amrr_node *amn;
- KASSERT(ni->ni_rctls == NULL, ("%s: ni_rctls already initialized",
- __func__));
-
- ni->ni_rctls = amn = malloc(sizeof(struct ieee80211_amrr_node),
- M_80211_RATECTL, M_NOWAIT|M_ZERO);
- if (amn == NULL) {
- if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl "
- "structure\n");
- return;
- }
+ if (ni->ni_rctls == NULL) {
+ ni->ni_rctls = amn = malloc(sizeof(struct ieee80211_amrr_node),
+ M_80211_RATECTL, M_NOWAIT|M_ZERO);
+ if (amn == NULL) {
+ if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl "
+ "structure\n");
+ return;
+ }
+ } else
+ amn = ni->ni_rctls;
amn->amn_amrr = amrr;
amn->amn_success = 0;
amn->amn_recovery = 0;
diff --git a/sys/net80211/ieee80211_ht.h b/sys/net80211/ieee80211_ht.h
index 7b0eab7..9cdc1ea 100644
--- a/sys/net80211/ieee80211_ht.h
+++ b/sys/net80211/ieee80211_ht.h
@@ -142,7 +142,8 @@ struct ieee80211_rx_ampdu {
int rxa_age; /* age of oldest frame in window */
int rxa_nframes; /* frames since ADDBA */
struct mbuf *rxa_m[IEEE80211_AGGR_BAWMAX];
- uint64_t rxa_pad[4];
+ void *rxa_private;
+ uint64_t rxa_pad[3];
};
void ieee80211_ht_attach(struct ieee80211com *);
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index b17f42f..992ea0f 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -432,7 +432,7 @@ ieee80211_reset_bss(struct ieee80211vap *vap)
ieee80211_reset_erp(ic);
ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr);
- KASSERT(ni != NULL, ("unable to setup inital BSS node"));
+ KASSERT(ni != NULL, ("unable to setup initial BSS node"));
obss = vap->iv_bss;
vap->iv_bss = ieee80211_ref_node(ni);
if (obss != NULL) {
diff --git a/sys/net80211/ieee80211_rssadapt.c b/sys/net80211/ieee80211_rssadapt.c
index ad329e0..f82c01e 100644
--- a/sys/net80211/ieee80211_rssadapt.c
+++ b/sys/net80211/ieee80211_rssadapt.c
@@ -169,13 +169,17 @@ rssadapt_node_init(struct ieee80211_node *ni)
struct ieee80211_rssadapt *rsa = vap->iv_rs;
const struct ieee80211_rateset *rs = &ni->ni_rates;
- ni->ni_rctls = ra = malloc(sizeof(struct ieee80211_rssadapt_node),
- M_80211_RATECTL, M_NOWAIT|M_ZERO);
- if (ra == NULL) {
- if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl "
- "structure\n");
- return;
- }
+ if (ni->ni_rctls == NULL) {
+ ni->ni_rctls = ra =
+ malloc(sizeof(struct ieee80211_rssadapt_node),
+ M_80211_RATECTL, M_NOWAIT|M_ZERO);
+ if (ra == NULL) {
+ if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl "
+ "structure\n");
+ return;
+ }
+ } else
+ ra = ni->ni_rctls;
ra->ra_rs = rsa;
ra->ra_rates = *rs;
rssadapt_updatestats(ra);
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index ff3694f..eea8dbe 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -213,6 +213,8 @@ struct ieee80211com {
enum ieee80211_protmode ic_htprotmode; /* HT protection mode */
int ic_lastnonerp; /* last time non-ERP sta noted*/
int ic_lastnonht; /* last time non-HT sta noted */
+ uint8_t ic_rxstream; /* # RX streams */
+ uint8_t ic_txstream; /* # TX streams */
/* optional state for Atheros SuperG protocol extensions */
struct ieee80211_superg *ic_superg;
@@ -315,7 +317,6 @@ struct ieee80211com {
void (*ic_ampdu_rx_stop)(struct ieee80211_node *,
struct ieee80211_rx_ampdu *);
uint64_t ic_spare[7];
- uint32_t ic_spare2;
};
struct ieee80211_aclator;
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index fdfe878..2a93e58 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -3067,28 +3067,42 @@ ng_mod_event(module_t mod, int event, void *data)
static void
vnet_netgraph_uninit(const void *unused __unused)
{
-#if 0
- node_p node, last_killed = NULL;
-
- /* XXXRW: utterly bogus. */
- while ((node = LIST_FIRST(&V_ng_allnodes)) != NULL) {
- if (node == last_killed) {
- /* This should never happen */
- node->nd_flags |= NGF_REALLY_DIE;
- printf("netgraph node %s needs NGF_REALLY_DIE\n",
- node->nd_name);
+ node_p node = NULL, last_killed = NULL;
+ int i;
+
+ do {
+ /* Find a node to kill */
+ mtx_lock(&ng_namehash_mtx);
+ for (i = 0; i < NG_NAME_HASH_SIZE; i++) {
+ LIST_FOREACH(node, &V_ng_name_hash[i], nd_nodes) {
+ if (node != &ng_deadnode) {
+ NG_NODE_REF(node);
+ break;
+ }
+ }
+ if (node != NULL)
+ break;
+ }
+ mtx_unlock(&ng_namehash_mtx);
+
+ /* Attempt to kill it only if it is a regular node */
+ if (node != NULL) {
+ if (node == last_killed) {
+ /* This should never happen */
+ printf("ng node %s needs"
+ "NGF_REALLY_DIE\n", node->nd_name);
+ if (node->nd_flags & NGF_REALLY_DIE)
+ panic("ng node %s won't die",
+ node->nd_name);
+ node->nd_flags |= NGF_REALLY_DIE;
+ }
ng_rmnode(node, NULL, NULL, 0);
- /* This must never happen */
- if (node == LIST_FIRST(&V_ng_allnodes))
- panic("netgraph node %s won't die",
- node->nd_name);
+ NG_NODE_UNREF(node);
+ last_killed = node;
}
- ng_rmnode(node, NULL, NULL, 0);
- last_killed = node;
- }
-#endif
+ } while (node != NULL);
}
-VNET_SYSUNINIT(vnet_netgraph_uninit, SI_SUB_NETGRAPH, SI_ORDER_ANY,
+VNET_SYSUNINIT(vnet_netgraph_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
vnet_netgraph_uninit, NULL);
#endif /* VIMAGE */
diff --git a/sys/netgraph/ng_bridge.c b/sys/netgraph/ng_bridge.c
index 35e1392..0bf0866 100644
--- a/sys/netgraph/ng_bridge.c
+++ b/sys/netgraph/ng_bridge.c
@@ -84,7 +84,7 @@
#include <netgraph/ng_bridge.h>
#ifdef NG_SEPARATE_MALLOC
-MALLOC_DEFINE(M_NETGRAPH_BRIDGE, "netgraph_bridge", "netgraph bridge node ");
+MALLOC_DEFINE(M_NETGRAPH_BRIDGE, "netgraph_bridge", "netgraph bridge node");
#else
#define M_NETGRAPH_BRIDGE M_NETGRAPH
#endif
@@ -106,6 +106,7 @@ struct ng_bridge_private {
u_int numBuckets; /* num buckets in table */
u_int hashMask; /* numBuckets - 1 */
int numLinks; /* num connected links */
+ int persistent; /* can exist w/o hooks */
struct callout timer; /* one second periodic timer */
};
typedef struct ng_bridge_private *priv_p;
@@ -271,6 +272,13 @@ static const struct ng_cmdlist ng_bridge_cmdlist[] = {
NULL,
&ng_bridge_host_ary_type
},
+ {
+ NGM_BRIDGE_COOKIE,
+ NGM_BRIDGE_SET_PERSISTENT,
+ "setpersistent",
+ NULL,
+ NULL
+ },
{ 0 }
};
@@ -495,6 +503,11 @@ ng_bridge_rcvmsg(node_p node, item_p item, hook_p lasthook)
}
break;
}
+ case NGM_BRIDGE_SET_PERSISTENT:
+ {
+ priv->persistent = 1;
+ break;
+ }
default:
error = EINVAL;
break;
@@ -800,7 +813,8 @@ ng_bridge_disconnect(hook_p hook)
/* If no more hooks, go away */
if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
- && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
+ && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))
+ && !priv->persistent) {
ng_rmnode_self(NG_HOOK_NODE(hook));
}
return (0);
diff --git a/sys/netgraph/ng_bridge.h b/sys/netgraph/ng_bridge.h
index 0524a96..c34d27d 100644
--- a/sys/netgraph/ng_bridge.h
+++ b/sys/netgraph/ng_bridge.h
@@ -149,6 +149,7 @@ enum {
NGM_BRIDGE_CLR_STATS, /* clear link stats */
NGM_BRIDGE_GETCLR_STATS, /* atomically get & clear link stats */
NGM_BRIDGE_GET_TABLE, /* get link table */
+ NGM_BRIDGE_SET_PERSISTENT, /* set persistent mode */
};
#endif /* _NETGRAPH_NG_BRIDGE_H_ */
diff --git a/sys/netgraph/ng_eiface.c b/sys/netgraph/ng_eiface.c
index 72cc55c..4239328 100644
--- a/sys/netgraph/ng_eiface.c
+++ b/sys/netgraph/ng_eiface.c
@@ -369,7 +369,7 @@ ng_eiface_constructor(node_p node)
ifp->if_output = ether_output;
ifp->if_start = ng_eiface_start;
ifp->if_ioctl = ng_eiface_ioctl;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_flags = (IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST);
/* Give this node the same name as the interface (if possible) */
diff --git a/sys/netgraph/ng_fec.c b/sys/netgraph/ng_fec.c
index 919947a..ce5a2d5 100644
--- a/sys/netgraph/ng_fec.c
+++ b/sys/netgraph/ng_fec.c
@@ -1227,7 +1227,7 @@ ng_fec_constructor(node_p node)
ifp->if_start = ng_fec_start;
ifp->if_ioctl = ng_fec_ioctl;
ifp->if_init = ng_fec_init;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_mtu = NG_FEC_MTU_DEFAULT;
ifp->if_flags = (IFF_SIMPLEX|IFF_BROADCAST|IFF_MULTICAST);
ifp->if_addrlen = 0; /* XXX */
diff --git a/sys/netgraph/ng_hub.c b/sys/netgraph/ng_hub.c
index ba298e5..0770745 100644
--- a/sys/netgraph/ng_hub.c
+++ b/sys/netgraph/ng_hub.c
@@ -36,16 +36,46 @@
#include <netgraph/ng_hub.h>
#include <netgraph/netgraph.h>
+#ifdef NG_SEPARATE_MALLOC
+MALLOC_DEFINE(M_NETGRAPH_HUB, "netgraph_hub", "netgraph hub node");
+#else
+#define M_NETGRAPH_HUB M_NETGRAPH
+#endif
+
+/* Per-node private data */
+struct ng_hub_private {
+ int persistent; /* can exist w/o hooks */
+};
+typedef struct ng_hub_private *priv_p;
+
+/* Netgraph node methods */
static ng_constructor_t ng_hub_constructor;
+static ng_rcvmsg_t ng_hub_rcvmsg;
+static ng_shutdown_t ng_hub_shutdown;
static ng_rcvdata_t ng_hub_rcvdata;
static ng_disconnect_t ng_hub_disconnect;
+/* List of commands and how to convert arguments to/from ASCII */
+static const struct ng_cmdlist ng_hub_cmdlist[] = {
+ {
+ NGM_HUB_COOKIE,
+ NGM_HUB_SET_PERSISTENT,
+ "setpersistent",
+ NULL,
+ NULL
+ },
+ { 0 }
+};
+
static struct ng_type ng_hub_typestruct = {
.version = NG_ABI_VERSION,
.name = NG_HUB_NODE_TYPE,
.constructor = ng_hub_constructor,
+ .rcvmsg = ng_hub_rcvmsg,
+ .shutdown = ng_hub_shutdown,
.rcvdata = ng_hub_rcvdata,
.disconnect = ng_hub_disconnect,
+ .cmdlist = ng_hub_cmdlist,
};
NETGRAPH_INIT(hub, &ng_hub_typestruct);
@@ -53,10 +83,39 @@ NETGRAPH_INIT(hub, &ng_hub_typestruct);
static int
ng_hub_constructor(node_p node)
{
+ priv_p priv;
+
+ /* Allocate and initialize private info */
+ priv = malloc(sizeof(*priv), M_NETGRAPH_HUB, M_NOWAIT | M_ZERO);
+ if (priv == NULL)
+ return (ENOMEM);
+ NG_NODE_SET_PRIVATE(node, priv);
return (0);
}
+/*
+ * Receive a control message
+ */
+static int
+ng_hub_rcvmsg(node_p node, item_p item, hook_p lasthook)
+{
+ const priv_p priv = NG_NODE_PRIVATE(node);
+ int error = 0;
+ struct ng_mesg *msg;
+
+ NGI_GET_MSG(item, msg);
+ if (msg->header.typecookie == NGM_HUB_COOKIE &&
+ msg->header.cmd == NGM_HUB_SET_PERSISTENT) {
+ priv->persistent = 1;
+ } else {
+ error = EINVAL;
+ }
+
+ NG_FREE_MSG(msg);
+ return (error);
+}
+
static int
ng_hub_rcvdata(hook_p hook, item_p item)
{
@@ -89,12 +148,25 @@ ng_hub_rcvdata(hook_p hook, item_p item)
return (error);
}
+/*
+ * Shutdown node
+ */
+static int
+ng_hub_shutdown(node_p node)
+{
+ const priv_p priv = NG_NODE_PRIVATE(node);
+
+ free(priv, M_NETGRAPH_HUB);
+ return (0);
+}
+
static int
ng_hub_disconnect(hook_p hook)
{
+ const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 &&
- NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))
+ NG_NODE_IS_VALID(NG_HOOK_NODE(hook)) && !priv->persistent)
ng_rmnode_self(NG_HOOK_NODE(hook));
return (0);
}
diff --git a/sys/netgraph/ng_hub.h b/sys/netgraph/ng_hub.h
index a735d7b..d6b16e0 100644
--- a/sys/netgraph/ng_hub.h
+++ b/sys/netgraph/ng_hub.h
@@ -33,4 +33,9 @@
#define NG_HUB_NODE_TYPE "hub"
#define NGM_HUB_COOKIE 1082189597
+/* Netgraph control messages */
+enum {
+ NGM_HUB_SET_PERSISTENT = 1, /* set persistent mode */
+};
+
#endif /* _NETGRAPH_NG_HUB_H_ */
diff --git a/sys/netgraph/ng_iface.c b/sys/netgraph/ng_iface.c
index d53bf76..f94fd14 100644
--- a/sys/netgraph/ng_iface.c
+++ b/sys/netgraph/ng_iface.c
@@ -564,8 +564,8 @@ ng_iface_constructor(node_p node)
ifp->if_addrlen = 0; /* XXX */
ifp->if_hdrlen = 0; /* XXX */
ifp->if_baudrate = 64000; /* XXX */
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
/* Give this node the same name as the interface (if possible) */
diff --git a/sys/netgraph/ng_pipe.c b/sys/netgraph/ng_pipe.c
index a094646..a454624 100644
--- a/sys/netgraph/ng_pipe.c
+++ b/sys/netgraph/ng_pipe.c
@@ -816,14 +816,17 @@ pipe_dequeue(struct hookinfo *hinfo, struct timeval *now) {
}
/* Randomly discard the frame, according to BER setting */
- if (hinfo->cfg.ber &&
- ((oldrand = rand) ^ (rand = random())<<17) >=
- hinfo->ber_p[priv->overhead + m->m_pkthdr.len] ) {
- hinfo->stats.out_disc_frames++;
- hinfo->stats.out_disc_octets += m->m_pkthdr.len;
- uma_zfree(ngp_zone, ngp_h);
- m_freem(m);
- continue;
+ if (hinfo->cfg.ber) {
+ oldrand = rand;
+ rand = random();
+ if (((oldrand ^ rand) << 17) >=
+ hinfo->ber_p[priv->overhead + m->m_pkthdr.len]) {
+ hinfo->stats.out_disc_frames++;
+ hinfo->stats.out_disc_octets += m->m_pkthdr.len;
+ uma_zfree(ngp_zone, ngp_h);
+ m_freem(m);
+ continue;
+ }
}
/* Discard frame if outbound queue size limit exceeded */
diff --git a/sys/netgraph/ng_tty.c b/sys/netgraph/ng_tty.c
index 2fa33fc..8408317 100644
--- a/sys/netgraph/ng_tty.c
+++ b/sys/netgraph/ng_tty.c
@@ -164,7 +164,7 @@ ngt_constructor(node_p node)
sc->node = node;
mtx_init(&sc->outq.ifq_mtx, "ng_tty node+queue", NULL, MTX_DEF);
- IFQ_SET_MAXLEN(&sc->outq, IFQ_MAXLEN);
+ IFQ_SET_MAXLEN(&sc->outq, ifqmaxlen);
return (0);
}
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h
index c3a8ac7..5faae7c 100644
--- a/sys/netinet/icmp6.h
+++ b/sys/netinet/icmp6.h
@@ -652,7 +652,6 @@ struct rtentry;
struct rttimer;
struct in6_multi;
# endif
-void icmp6_init(void);
void icmp6_paramerror(struct mbuf *, int);
void icmp6_error(struct mbuf *, int, int, int);
void icmp6_error2(struct mbuf *, int, int, int, struct ifnet *);
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 25fba9f..08a162f 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -82,16 +82,15 @@ SYSCTL_DECL(_net_link_ether);
SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, "");
SYSCTL_NODE(_net_link_ether, PF_ARP, arp, CTLFLAG_RW, 0, "");
-VNET_DEFINE(int, useloopback) = 1; /* use loopback interface for
- * local traffic */
-
/* timer values */
static VNET_DEFINE(int, arpt_keep) = (20*60); /* once resolved, good for 20
* minutes */
+static VNET_DEFINE(int, arp_maxtries) = 5;
+VNET_DEFINE(int, useloopback) = 1; /* use loopback interface for
+ * local traffic */
+static VNET_DEFINE(int, arp_proxyall) = 0;
static VNET_DEFINE(int, arpt_down) = 20; /* keep incomplete entries for
* 20 seconds */
-static VNET_DEFINE(int, arp_maxtries) = 5;
-static VNET_DEFINE(int, arp_proxyall);
static VNET_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */
#define V_arpt_keep VNET(arpt_keep)
@@ -103,7 +102,6 @@ static VNET_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */
SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW,
&VNET_NAME(arpt_keep), 0,
"ARP entry lifetime in seconds");
-
SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW,
&VNET_NAME(arp_maxtries), 0,
"ARP resolution attempts before returning error");
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c
index f9f6381..d4c8e99 100644
--- a/sys/netinet/igmp.c
+++ b/sys/netinet/igmp.c
@@ -1468,12 +1468,6 @@ igmp_input(struct mbuf *m, int off)
}
ip = mtod(m, struct ip *);
- if (ip->ip_ttl != 1) {
- IGMPSTAT_INC(igps_rcv_badttl);
- m_freem(m);
- return;
- }
-
/*
* Validate checksum.
*/
@@ -1488,6 +1482,17 @@ igmp_input(struct mbuf *m, int off)
m->m_data -= iphlen;
m->m_len += iphlen;
+ /*
+ * IGMP control traffic is link-scope, and must have a TTL of 1.
+ * DVMRP traffic (e.g. mrinfo, mtrace) is an exception;
+ * probe packets may come from beyond the LAN.
+ */
+ if (igmp->igmp_type != IGMP_DVMRP && ip->ip_ttl != 1) {
+ IGMPSTAT_INC(igps_rcv_badttl);
+ m_freem(m);
+ return;
+ }
+
switch (igmp->igmp_type) {
case IGMP_HOST_MEMBERSHIP_QUERY:
if (igmplen == IGMP_MINLEN) {
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 0a0fe47..96bfa0e 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -77,20 +77,19 @@ static int in_ifinit(struct ifnet *,
static void in_purgemaddrs(struct ifnet *);
static VNET_DEFINE(int, subnetsarelocal);
-static VNET_DEFINE(int, sameprefixcarponly);
-VNET_DECLARE(struct inpcbinfo, ripcbinfo);
-
#define V_subnetsarelocal VNET(subnetsarelocal)
-#define V_sameprefixcarponly VNET(sameprefixcarponly)
-#define V_ripcbinfo VNET(ripcbinfo)
-
SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
&VNET_NAME(subnetsarelocal), 0,
"Treat all subnets as directly connected");
+static VNET_DEFINE(int, sameprefixcarponly);
+#define V_sameprefixcarponly VNET(sameprefixcarponly)
SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, same_prefix_carp_only, CTLFLAG_RW,
&VNET_NAME(sameprefixcarponly), 0,
"Refuse to create same prefixes on different interfaces");
+VNET_DECLARE(struct inpcbinfo, ripcbinfo);
+#define V_ripcbinfo VNET(ripcbinfo)
+
/*
* Return 1 if an internet address is for a ``local'' host
* (one to which we have a connection). If subnetsarelocal
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
index 44b9961..6c60390 100644
--- a/sys/netinet/in_gif.c
+++ b/sys/netinet/in_gif.c
@@ -85,6 +85,8 @@ struct protosw in_gif_protosw = {
.pr_usrreqs = &rip_usrreqs
};
+VNET_DEFINE(int, ip_gif_ttl) = GIF_TTL;
+#define V_ip_gif_ttl VNET(ip_gif_ttl)
SYSCTL_VNET_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW,
&VNET_NAME(ip_gif_ttl), 0, "");
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index d9cab84..6d72fbe 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -208,7 +208,6 @@ struct protosw inetsw[] = {
.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
.pr_input = icmp_input,
.pr_ctloutput = rip_ctloutput,
- .pr_init = icmp_init,
.pr_usrreqs = &rip_usrreqs
},
{
diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c
index 6516277..5b8e0f6 100644
--- a/sys/netinet/in_rmx.c
+++ b/sys/netinet/in_rmx.c
@@ -131,22 +131,22 @@ in_matroute(void *v_arg, struct radix_node_head *head)
return rn;
}
-static VNET_DEFINE(int, rtq_reallyold);
-static VNET_DEFINE(int, rtq_minreallyold);
-static VNET_DEFINE(int, rtq_toomany);
-
+static VNET_DEFINE(int, rtq_reallyold) = 60*60; /* one hour is "really old" */
#define V_rtq_reallyold VNET(rtq_reallyold)
-#define V_rtq_minreallyold VNET(rtq_minreallyold)
-#define V_rtq_toomany VNET(rtq_toomany)
-
SYSCTL_VNET_INT(_net_inet_ip, IPCTL_RTEXPIRE, rtexpire, CTLFLAG_RW,
&VNET_NAME(rtq_reallyold), 0,
"Default expiration time on dynamically learned routes");
+/* never automatically crank down to less */
+static VNET_DEFINE(int, rtq_minreallyold) = 10;
+#define V_rtq_minreallyold VNET(rtq_minreallyold)
SYSCTL_VNET_INT(_net_inet_ip, IPCTL_RTMINEXPIRE, rtminexpire, CTLFLAG_RW,
&VNET_NAME(rtq_minreallyold), 0,
"Minimum time to attempt to hold onto dynamically learned routes");
+/* 128 cached routes is "too many" */
+static VNET_DEFINE(int, rtq_toomany) = 128;
+#define V_rtq_toomany VNET(rtq_toomany)
SYSCTL_VNET_INT(_net_inet_ip, IPCTL_RTMAXCACHE, rtmaxcache, CTLFLAG_RW,
&VNET_NAME(rtq_toomany), 0,
"Upper limit on dynamically learned routes");
@@ -239,7 +239,7 @@ in_rtqkill(struct radix_node *rn, void *rock)
}
#define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */
-static VNET_DEFINE(int, rtq_timeout);
+static VNET_DEFINE(int, rtq_timeout) = RTQ_TIMEOUT;
static VNET_DEFINE(struct callout, rtq_timer);
#define V_rtq_timeout VNET(rtq_timeout)
@@ -362,11 +362,6 @@ in_inithead(void **head, int off)
if (off == 0) /* XXX MRT see above */
return 1; /* only do the rest for a real routing table */
- V_rtq_reallyold = 60*60; /* one hour is "really old" */
- V_rtq_minreallyold = 10; /* never automatically crank down to less */
- V_rtq_toomany = 128; /* 128 cached routes is "too many" */
- V_rtq_timeout = RTQ_TIMEOUT;
-
rnh = *head;
rnh->rnh_addaddr = in_addroute;
rnh->rnh_matchaddr = in_matroute;
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index b13bc7c..8dc08d9 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -75,65 +75,60 @@ __FBSDID("$FreeBSD$");
* routines to turnaround packets back to the originator, and
* host table maintenance routines.
*/
-
VNET_DEFINE(struct icmpstat, icmpstat);
-static VNET_DEFINE(int, icmpmaskrepl);
-static VNET_DEFINE(u_int, icmpmaskfake);
-static VNET_DEFINE(int, drop_redirect);
-static VNET_DEFINE(int, log_redirect);
-static VNET_DEFINE(int, icmplim);
-static VNET_DEFINE(int, icmplim_output);
-static VNET_DEFINE(char, reply_src[IFNAMSIZ]);
-static VNET_DEFINE(int, icmp_rfi);
-static VNET_DEFINE(int, icmp_quotelen);
-static VNET_DEFINE(int, icmpbmcastecho);
-
-#define V_icmpmaskrepl VNET(icmpmaskrepl)
-#define V_icmpmaskfake VNET(icmpmaskfake)
-#define V_drop_redirect VNET(drop_redirect)
-#define V_log_redirect VNET(log_redirect)
-#define V_icmplim VNET(icmplim)
-#define V_icmplim_output VNET(icmplim_output)
-#define V_reply_src VNET(reply_src)
-#define V_icmp_rfi VNET(icmp_rfi)
-#define V_icmp_quotelen VNET(icmp_quotelen)
-#define V_icmpbmcastecho VNET(icmpbmcastecho)
-
SYSCTL_VNET_STRUCT(_net_inet_icmp, ICMPCTL_STATS, stats, CTLFLAG_RW,
&VNET_NAME(icmpstat), icmpstat, "");
+static VNET_DEFINE(int, icmpmaskrepl) = 0;
+#define V_icmpmaskrepl VNET(icmpmaskrepl)
SYSCTL_VNET_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW,
&VNET_NAME(icmpmaskrepl), 0,
"Reply to ICMP Address Mask Request packets.");
+static VNET_DEFINE(u_int, icmpmaskfake) = 0;
+#define V_icmpmaskfake VNET(icmpmaskfake)
SYSCTL_VNET_UINT(_net_inet_icmp, OID_AUTO, maskfake, CTLFLAG_RW,
&VNET_NAME(icmpmaskfake), 0,
"Fake reply to ICMP Address Mask Request packets.");
+static VNET_DEFINE(int, drop_redirect) = 0;
+#define V_drop_redirect VNET(drop_redirect)
SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, drop_redirect, CTLFLAG_RW,
&VNET_NAME(drop_redirect), 0,
"Ignore ICMP redirects");
+static VNET_DEFINE(int, log_redirect) = 0;
+#define V_log_redirect VNET(log_redirect)
SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, log_redirect, CTLFLAG_RW,
&VNET_NAME(log_redirect), 0,
"Log ICMP redirects to the console");
+static VNET_DEFINE(int, icmplim) = 200;
+#define V_icmplim VNET(icmplim)
SYSCTL_VNET_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW,
&VNET_NAME(icmplim), 0,
"Maximum number of ICMP responses per second");
+static VNET_DEFINE(int, icmplim_output) = 1;
+#define V_icmplim_output VNET(icmplim_output)
SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, icmplim_output, CTLFLAG_RW,
&VNET_NAME(icmplim_output), 0,
"Enable rate limiting of ICMP responses");
+static VNET_DEFINE(char, reply_src[IFNAMSIZ]);
+#define V_reply_src VNET(reply_src)
SYSCTL_VNET_STRING(_net_inet_icmp, OID_AUTO, reply_src, CTLFLAG_RW,
&VNET_NAME(reply_src), IFNAMSIZ,
"icmp reply source for non-local packets.");
+static VNET_DEFINE(int, icmp_rfi) = 0;
+#define V_icmp_rfi VNET(icmp_rfi)
SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, reply_from_interface, CTLFLAG_RW,
&VNET_NAME(icmp_rfi), 0,
"ICMP reply from incoming interface for non-local packets");
+static VNET_DEFINE(int, icmp_quotelen) = 8;
+#define V_icmp_quotelen VNET(icmp_quotelen)
SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, quotelen, CTLFLAG_RW,
&VNET_NAME(icmp_quotelen), 0,
"Number of bytes from original packet to quote in ICMP reply");
@@ -141,7 +136,8 @@ SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, quotelen, CTLFLAG_RW,
/*
* ICMP broadcast echo sysctl
*/
-
+static VNET_DEFINE(int, icmpbmcastecho) = 0;
+#define V_icmpbmcastecho VNET(icmpbmcastecho)
SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW,
&VNET_NAME(icmpbmcastecho), 0,
"");
@@ -156,21 +152,6 @@ static void icmp_send(struct mbuf *, struct mbuf *);
extern struct protosw inetsw[];
-void
-icmp_init(void)
-{
-
- V_icmpmaskrepl = 0;
- V_icmpmaskfake = 0;
- V_drop_redirect = 0;
- V_log_redirect = 0;
- V_icmplim = 200;
- V_icmplim_output = 1;
- V_icmp_rfi = 0;
- V_icmp_quotelen = 8;
- V_icmpbmcastecho = 0;
-}
-
/*
* Kernel module interface for updating icmpstat. The argument is an index
* into icmpstat treated as an array of u_long. While this encodes the
diff --git a/sys/netinet/ip_icmp.h b/sys/netinet/ip_icmp.h
index e4ee7f7..9cabdb5 100644
--- a/sys/netinet/ip_icmp.h
+++ b/sys/netinet/ip_icmp.h
@@ -208,7 +208,6 @@ struct icmp {
#ifdef _KERNEL
void icmp_error(struct mbuf *, int, int, uint32_t, int);
void icmp_input(struct mbuf *, int);
-void icmp_init(void);
int ip_next_mtu(int, int);
#endif
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index fdef645..a17907c 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -89,66 +89,40 @@ __FBSDID("$FreeBSD$");
CTASSERT(sizeof(struct ip) == 20);
#endif
-static VNET_DEFINE(int, ipsendredirects) = 1; /* XXX */
-static VNET_DEFINE(int, ip_checkinterface);
-static VNET_DEFINE(int, ip_keepfaith);
-static VNET_DEFINE(int, ip_sendsourcequench);
-
-#define V_ipsendredirects VNET(ipsendredirects)
-#define V_ip_checkinterface VNET(ip_checkinterface)
-#define V_ip_keepfaith VNET(ip_keepfaith)
-#define V_ip_sendsourcequench VNET(ip_sendsourcequench)
-
-VNET_DEFINE(int, ip_defttl) = IPDEFTTL;
-VNET_DEFINE(int, ip_do_randomid);
-VNET_DEFINE(int, ipforwarding);
-
-VNET_DEFINE(struct in_ifaddrhead, in_ifaddrhead); /* first inet address */
-VNET_DEFINE(struct in_ifaddrhashhead *, in_ifaddrhashtbl); /* inet addr hash table */
-VNET_DEFINE(u_long, in_ifaddrhmask); /* mask for hash table */
-VNET_DEFINE(struct ipstat, ipstat);
-
-static VNET_DEFINE(int, ip_rsvp_on);
-VNET_DEFINE(struct socket *, ip_rsvpd);
-VNET_DEFINE(int, rsvp_on);
-
-#define V_ip_rsvp_on VNET(ip_rsvp_on)
-
-static VNET_DEFINE(TAILQ_HEAD(ipqhead, ipq), ipq[IPREASS_NHASH]);
-static VNET_DEFINE(int, maxnipq); /* Administrative limit on # reass queues. */
-static VNET_DEFINE(int, maxfragsperpacket);
-static VNET_DEFINE(int, nipq); /* Total # of reass queues */
-
-#define V_ipq VNET(ipq)
-#define V_maxnipq VNET(maxnipq)
-#define V_maxfragsperpacket VNET(maxfragsperpacket)
-#define V_nipq VNET(nipq)
-
-VNET_DEFINE(int, ipstealth);
-
struct rwlock in_ifaddr_lock;
RW_SYSINIT(in_ifaddr_lock, &in_ifaddr_lock, "in_ifaddr_lock");
+VNET_DEFINE(int, rsvp_on);
+
+VNET_DEFINE(int, ipforwarding);
SYSCTL_VNET_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW,
&VNET_NAME(ipforwarding), 0,
"Enable IP forwarding between interfaces");
+static VNET_DEFINE(int, ipsendredirects) = 1; /* XXX */
+#define V_ipsendredirects VNET(ipsendredirects)
SYSCTL_VNET_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_RW,
&VNET_NAME(ipsendredirects), 0,
"Enable sending IP redirects");
+VNET_DEFINE(int, ip_defttl) = IPDEFTTL;
SYSCTL_VNET_INT(_net_inet_ip, IPCTL_DEFTTL, ttl, CTLFLAG_RW,
&VNET_NAME(ip_defttl), 0,
"Maximum TTL on IP packets");
+static VNET_DEFINE(int, ip_keepfaith);
+#define V_ip_keepfaith VNET(ip_keepfaith)
SYSCTL_VNET_INT(_net_inet_ip, IPCTL_KEEPFAITH, keepfaith, CTLFLAG_RW,
&VNET_NAME(ip_keepfaith), 0,
"Enable packet capture for FAITH IPv4->IPv6 translater daemon");
+static VNET_DEFINE(int, ip_sendsourcequench);
+#define V_ip_sendsourcequench VNET(ip_sendsourcequench)
SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, sendsourcequench, CTLFLAG_RW,
&VNET_NAME(ip_sendsourcequench), 0,
"Enable the transmission of source quench packets");
+VNET_DEFINE(int, ip_do_randomid);
SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, random_id, CTLFLAG_RW,
&VNET_NAME(ip_do_randomid), 0,
"Assign random ip_id values");
@@ -166,6 +140,8 @@ SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, random_id, CTLFLAG_RW,
* to the loopback interface instead of the interface where the
* packets for those addresses are received.
*/
+static VNET_DEFINE(int, ip_checkinterface);
+#define V_ip_checkinterface VNET(ip_checkinterface)
SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, check_interface, CTLFLAG_RW,
&VNET_NAME(ip_checkinterface), 0,
"Verify packet arrives on correct interface");
@@ -182,16 +158,22 @@ static struct netisr_handler ip_nh = {
extern struct domain inetdomain;
extern struct protosw inetsw[];
u_char ip_protox[IPPROTO_MAX];
+VNET_DEFINE(struct in_ifaddrhead, in_ifaddrhead); /* first inet address */
+VNET_DEFINE(struct in_ifaddrhashhead *, in_ifaddrhashtbl); /* inet addr hash table */
+VNET_DEFINE(u_long, in_ifaddrhmask); /* mask for hash table */
+VNET_DEFINE(struct ipstat, ipstat);
SYSCTL_VNET_STRUCT(_net_inet_ip, IPCTL_STATS, stats, CTLFLAG_RW,
&VNET_NAME(ipstat), ipstat,
"IP statistics (struct ipstat, netinet/ip_var.h)");
static VNET_DEFINE(uma_zone_t, ipq_zone);
-#define V_ipq_zone VNET(ipq_zone)
-
+static VNET_DEFINE(TAILQ_HEAD(ipqhead, ipq), ipq[IPREASS_NHASH]);
static struct mtx ipqlock;
+#define V_ipq_zone VNET(ipq_zone)
+#define V_ipq VNET(ipq)
+
#define IPQ_LOCK() mtx_lock(&ipqlock)
#define IPQ_UNLOCK() mtx_unlock(&ipqlock)
#define IPQ_LOCK_INIT() mtx_init(&ipqlock, "ipqlock", NULL, MTX_DEF)
@@ -201,10 +183,16 @@ static void maxnipq_update(void);
static void ipq_zone_change(void *);
static void ip_drain_locked(void);
+static VNET_DEFINE(int, maxnipq); /* Administrative limit on # reass queues. */
+static VNET_DEFINE(int, nipq); /* Total # of reass queues */
+#define V_maxnipq VNET(maxnipq)
+#define V_nipq VNET(nipq)
SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, fragpackets, CTLFLAG_RD,
&VNET_NAME(nipq), 0,
"Current number of IPv4 fragment reassembly queue entries");
+static VNET_DEFINE(int, maxfragsperpacket);
+#define V_maxfragsperpacket VNET(maxfragsperpacket)
SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, maxfragsperpacket, CTLFLAG_RW,
&VNET_NAME(maxfragsperpacket), 0,
"Maximum number of IPv4 fragments allowed per packet");
@@ -217,6 +205,7 @@ SYSCTL_INT(_net_inet_ip, IPCTL_DEFMTU, mtu, CTLFLAG_RW,
#endif
#ifdef IPSTEALTH
+VNET_DEFINE(int, ipstealth);
SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, stealth, CTLFLAG_RW,
&VNET_NAME(ipstealth), 0,
"IP stealth mode, no TTL decrementation on forwarding");
@@ -1740,6 +1729,11 @@ makedummy:
* locking. This code remains in ip_input.c as ip_mroute.c is optionally
* compiled.
*/
+static VNET_DEFINE(int, ip_rsvp_on);
+VNET_DEFINE(struct socket *, ip_rsvpd);
+
+#define V_ip_rsvp_on VNET(ip_rsvp_on)
+
int
ip_rsvp_init(struct socket *so)
{
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 389ad6e..4415001 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -181,9 +181,13 @@ VNET_DECLARE(int, ipforwarding); /* ip forwarding */
#ifdef IPSTEALTH
VNET_DECLARE(int, ipstealth); /* stealth forwarding */
#endif
-VNET_DECLARE(int, rsvp_on);
+extern u_char ip_protox[];
VNET_DECLARE(struct socket *, ip_rsvpd); /* reservation protocol daemon*/
VNET_DECLARE(struct socket *, ip_mrouter); /* multicast routing daemon */
+extern int (*legal_vif_num)(int);
+extern u_long (*ip_mcast_src)(int);
+VNET_DECLARE(int, rsvp_on);
+extern struct pr_usrreqs rip_usrreqs;
#define V_ipstat VNET(ipstat)
#define V_ip_id VNET(ip_id)
@@ -192,14 +196,9 @@ VNET_DECLARE(struct socket *, ip_mrouter); /* multicast routing daemon */
#ifdef IPSTEALTH
#define V_ipstealth VNET(ipstealth)
#endif
-#define V_rsvp_on VNET(rsvp_on)
#define V_ip_rsvpd VNET(ip_rsvpd)
#define V_ip_mrouter VNET(ip_mrouter)
-
-extern u_char ip_protox[];
-extern int (*legal_vif_num)(int);
-extern u_long (*ip_mcast_src)(int);
-extern struct pr_usrreqs rip_usrreqs;
+#define V_rsvp_on VNET(rsvp_on)
void inp_freemoptions(struct ip_moptions *);
int inp_getmoptions(struct inpcb *, struct sockopt *);
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 1db3774..0b77b5b 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -427,11 +427,24 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst)
ip->ip_p = inp->inp_ip_p;
ip->ip_len = m->m_pkthdr.len;
ip->ip_src = inp->inp_laddr;
- error = prison_get_ip4(inp->inp_cred, &ip->ip_src);
- if (error != 0) {
- INP_RUNLOCK(inp);
- m_freem(m);
- return (error);
+ if (jailed(inp->inp_cred)) {
+ /*
+ * prison_local_ip4() would be good enough but would
+ * let a source of INADDR_ANY pass, which we do not
+ * want to see from jails. We do not go through the
+ * pain of in_pcbladdr() for raw sockets.
+ */
+ if (ip->ip_src.s_addr == INADDR_ANY)
+ error = prison_get_ip4(inp->inp_cred,
+ &ip->ip_src);
+ else
+ error = prison_local_ip4(inp->inp_cred,
+ &ip->ip_src);
+ if (error != 0) {
+ INP_RUNLOCK(inp);
+ m_freem(m);
+ return (error);
+ }
}
ip->ip_dst.s_addr = dst;
ip->ip_ttl = inp->inp_ip_ttl;
diff --git a/sys/netinet/tcp_hostcache.c b/sys/netinet/tcp_hostcache.c
index a0c4012..d20adb7 100644
--- a/sys/netinet/tcp_hostcache.c
+++ b/sys/netinet/tcp_hostcache.c
@@ -107,9 +107,9 @@ __FBSDID("$FreeBSD$");
#define TCP_HOSTCACHE_PRUNE 5*60 /* every 5 minutes */
static VNET_DEFINE(struct tcp_hostcache, tcp_hostcache);
-static VNET_DEFINE(struct callout, tcp_hc_callout);
-
#define V_tcp_hostcache VNET(tcp_hostcache)
+
+static VNET_DEFINE(struct callout, tcp_hc_callout);
#define V_tcp_hc_callout VNET(tcp_hc_callout)
static struct hc_metrics *tcp_hc_lookup(struct in_conninfo *);
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 0254cff..cbba9cd 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -99,20 +99,6 @@ __FBSDID("$FreeBSD$");
static const int tcprexmtthresh = 3;
VNET_DEFINE(struct tcpstat, tcpstat);
-VNET_DEFINE(int, blackhole);
-VNET_DEFINE(int, tcp_delack_enabled);
-VNET_DEFINE(int, drop_synfin);
-VNET_DEFINE(int, tcp_do_rfc3042);
-VNET_DEFINE(int, tcp_do_rfc3390);
-VNET_DEFINE(int, tcp_do_ecn);
-VNET_DEFINE(int, tcp_ecn_maxretries);
-VNET_DEFINE(int, tcp_insecure_rst);
-VNET_DEFINE(int, tcp_do_autorcvbuf);
-VNET_DEFINE(int, tcp_autorcvbuf_inc);
-VNET_DEFINE(int, tcp_autorcvbuf_max);
-VNET_DEFINE(int, tcp_do_rfc3465);
-VNET_DEFINE(int, tcp_abc_l_var);
-
SYSCTL_VNET_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats, CTLFLAG_RW,
&VNET_NAME(tcpstat), tcpstat,
"TCP statistics (struct tcpstat, netinet/tcp_var.h)");
@@ -122,56 +108,79 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_in_vain, CTLFLAG_RW,
&tcp_log_in_vain, 0,
"Log all incoming TCP segments to closed ports");
+VNET_DEFINE(int, blackhole) = 0;
+#define V_blackhole VNET(blackhole)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, blackhole, CTLFLAG_RW,
&VNET_NAME(blackhole), 0,
"Do not send RST on segments to closed ports");
+VNET_DEFINE(int, tcp_delack_enabled) = 1;
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, delayed_ack, CTLFLAG_RW,
&VNET_NAME(tcp_delack_enabled), 0,
"Delay ACK to try and piggyback it onto a data packet");
+VNET_DEFINE(int, drop_synfin) = 0;
+#define V_drop_synfin VNET(drop_synfin)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, drop_synfin, CTLFLAG_RW,
&VNET_NAME(drop_synfin), 0,
"Drop TCP packets with SYN+FIN set");
+VNET_DEFINE(int, tcp_do_rfc3042) = 1;
+#define V_tcp_do_rfc3042 VNET(tcp_do_rfc3042)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3042, CTLFLAG_RW,
&VNET_NAME(tcp_do_rfc3042), 0,
"Enable RFC 3042 (Limited Transmit)");
+VNET_DEFINE(int, tcp_do_rfc3390) = 1;
+#define V_tcp_do_rfc3390 VNET(tcp_do_rfc3390)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3390, CTLFLAG_RW,
&VNET_NAME(tcp_do_rfc3390), 0,
"Enable RFC 3390 (Increasing TCP's Initial Congestion Window)");
+VNET_DEFINE(int, tcp_do_rfc3465) = 1;
+#define V_tcp_do_rfc3465 VNET(tcp_do_rfc3465)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3465, CTLFLAG_RW,
&VNET_NAME(tcp_do_rfc3465), 0,
"Enable RFC 3465 (Appropriate Byte Counting)");
+VNET_DEFINE(int, tcp_abc_l_var) = 2;
+#define V_tcp_abc_l_var VNET(tcp_abc_l_var)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, abc_l_var, CTLFLAG_RW,
&VNET_NAME(tcp_abc_l_var), 2,
"Cap the max cwnd increment during slow-start to this number of segments");
SYSCTL_NODE(_net_inet_tcp, OID_AUTO, ecn, CTLFLAG_RW, 0, "TCP ECN");
+VNET_DEFINE(int, tcp_do_ecn) = 0;
SYSCTL_VNET_INT(_net_inet_tcp_ecn, OID_AUTO, enable, CTLFLAG_RW,
&VNET_NAME(tcp_do_ecn), 0,
"TCP ECN support");
+VNET_DEFINE(int, tcp_ecn_maxretries) = 1;
SYSCTL_VNET_INT(_net_inet_tcp_ecn, OID_AUTO, maxretries, CTLFLAG_RW,
&VNET_NAME(tcp_ecn_maxretries), 0,
"Max retries before giving up on ECN");
+VNET_DEFINE(int, tcp_insecure_rst) = 0;
+#define V_tcp_insecure_rst VNET(tcp_insecure_rst)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, insecure_rst, CTLFLAG_RW,
&VNET_NAME(tcp_insecure_rst), 0,
"Follow the old (insecure) criteria for accepting RST packets");
+VNET_DEFINE(int, tcp_do_autorcvbuf) = 1;
+#define V_tcp_do_autorcvbuf VNET(tcp_do_autorcvbuf)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, recvbuf_auto, CTLFLAG_RW,
&VNET_NAME(tcp_do_autorcvbuf), 0,
"Enable automatic receive buffer sizing");
+VNET_DEFINE(int, tcp_autorcvbuf_inc) = 16*1024;
+#define V_tcp_autorcvbuf_inc VNET(tcp_autorcvbuf_inc)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, recvbuf_inc, CTLFLAG_RW,
&VNET_NAME(tcp_autorcvbuf_inc), 0,
"Incrementor step size of automatic receive buffer");
+VNET_DEFINE(int, tcp_autorcvbuf_max) = 256*1024;
+#define V_tcp_autorcvbuf_max VNET(tcp_autorcvbuf_max)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, recvbuf_max, CTLFLAG_RW,
&VNET_NAME(tcp_autorcvbuf_max), 0,
"Max size of automatic receive buffer");
@@ -181,8 +190,8 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, read_locking, CTLFLAG_RW,
&tcp_read_locking, 0, "Enable read locking strategy");
VNET_DEFINE(struct inpcbhead, tcb);
-VNET_DEFINE(struct inpcbinfo, tcbinfo);
#define tcb6 tcb /* for KAME src sync over BSD*'s */
+VNET_DEFINE(struct inpcbinfo, tcbinfo);
static void tcp_dooptions(struct tcpopt *, u_char *, int, int);
static void tcp_do_segment(struct mbuf *, struct tcphdr *,
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index f9d1b63..50973c4 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -87,43 +87,46 @@ __FBSDID("$FreeBSD$");
extern struct mbuf *m_copypack();
#endif
-VNET_DEFINE(int, path_mtu_discovery);
-VNET_DEFINE(int, ss_fltsz);
-VNET_DEFINE(int, ss_fltsz_local);
-VNET_DEFINE(int, tcp_do_newreno);
-VNET_DEFINE(int, tcp_do_tso);
-VNET_DEFINE(int, tcp_do_autosndbuf);
-VNET_DEFINE(int, tcp_autosndbuf_inc);
-VNET_DEFINE(int, tcp_autosndbuf_max);
-
+VNET_DEFINE(int, path_mtu_discovery) = 1;
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, path_mtu_discovery, CTLFLAG_RW,
&VNET_NAME(path_mtu_discovery), 1,
"Enable Path MTU Discovery");
+VNET_DEFINE(int, ss_fltsz) = 1;
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, slowstart_flightsize, CTLFLAG_RW,
&VNET_NAME(ss_fltsz), 1,
"Slow start flight size");
+VNET_DEFINE(int, ss_fltsz_local) = 4;
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, local_slowstart_flightsize,
CTLFLAG_RW, &VNET_NAME(ss_fltsz_local), 1,
"Slow start flight size for local networks");
+VNET_DEFINE(int, tcp_do_newreno) = 1;
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, newreno, CTLFLAG_RW,
&VNET_NAME(tcp_do_newreno), 0,
"Enable NewReno Algorithms");
+VNET_DEFINE(int, tcp_do_tso) = 1;
+#define V_tcp_do_tso VNET(tcp_do_tso)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, tso, CTLFLAG_RW,
&VNET_NAME(tcp_do_tso), 0,
"Enable TCP Segmentation Offload");
+VNET_DEFINE(int, tcp_do_autosndbuf) = 1;
+#define V_tcp_do_autosndbuf VNET(tcp_do_autosndbuf)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, sendbuf_auto, CTLFLAG_RW,
&VNET_NAME(tcp_do_autosndbuf), 0,
"Enable automatic send buffer sizing");
+VNET_DEFINE(int, tcp_autosndbuf_inc) = 8*1024;
+#define V_tcp_autosndbuf_inc VNET(tcp_autosndbuf_inc)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, sendbuf_inc, CTLFLAG_RW,
&VNET_NAME(tcp_autosndbuf_inc), 0,
"Incrementor step size of automatic send buffer");
+VNET_DEFINE(int, tcp_autosndbuf_max) = 256*1024;
+#define V_tcp_autosndbuf_max VNET(tcp_autosndbuf_max)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, sendbuf_max, CTLFLAG_RW,
&VNET_NAME(tcp_autosndbuf_max), 0,
"Max size of automatic send buffer");
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index cd7eb1c..bfb53d3 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -74,30 +74,28 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp_debug.h>
#endif /* TCPDEBUG */
-static VNET_DEFINE(int, tcp_reass_maxseg);
-VNET_DEFINE(int, tcp_reass_qsize);
-static VNET_DEFINE(int, tcp_reass_maxqlen);
-static VNET_DEFINE(int, tcp_reass_overflows);
-
-#define V_tcp_reass_maxseg VNET(tcp_reass_maxseg)
-#define V_tcp_reass_maxqlen VNET(tcp_reass_maxqlen)
-#define V_tcp_reass_overflows VNET(tcp_reass_overflows)
-
SYSCTL_NODE(_net_inet_tcp, OID_AUTO, reass, CTLFLAG_RW, 0,
"TCP Segment Reassembly Queue");
+static VNET_DEFINE(int, tcp_reass_maxseg) = 0;
+#define V_tcp_reass_maxseg VNET(tcp_reass_maxseg)
SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, maxsegments, CTLFLAG_RDTUN,
&VNET_NAME(tcp_reass_maxseg), 0,
"Global maximum number of TCP Segments in Reassembly Queue");
+VNET_DEFINE(int, tcp_reass_qsize) = 0;
SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, cursegments, CTLFLAG_RD,
&VNET_NAME(tcp_reass_qsize), 0,
"Global number of TCP Segments currently in Reassembly Queue");
+static VNET_DEFINE(int, tcp_reass_maxqlen) = 48;
+#define V_tcp_reass_maxqlen VNET(tcp_reass_maxqlen)
SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, maxqlen, CTLFLAG_RW,
&VNET_NAME(tcp_reass_maxqlen), 0,
"Maximum number of TCP Segments per individual Reassembly Queue");
+static VNET_DEFINE(int, tcp_reass_overflows) = 0;
+#define V_tcp_reass_overflows VNET(tcp_reass_overflows)
SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, overflows, CTLFLAG_RD,
&VNET_NAME(tcp_reass_overflows), 0,
"Global number of TCP Segment Reassembly Queue Overflows");
@@ -117,11 +115,6 @@ void
tcp_reass_init(void)
{
- V_tcp_reass_maxseg = 0;
- V_tcp_reass_qsize = 0;
- V_tcp_reass_maxqlen = 48;
- V_tcp_reass_overflows = 0;
-
V_tcp_reass_maxseg = nmbclusters / 16;
TUNABLE_INT_FETCH("net.inet.tcp.reass.maxsegments",
&V_tcp_reass_maxseg);
diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c
index 06fb502..737c2b2 100644
--- a/sys/netinet/tcp_sack.c
+++ b/sys/netinet/tcp_sack.c
@@ -123,29 +123,28 @@ __FBSDID("$FreeBSD$");
#include <machine/in_cksum.h>
VNET_DECLARE(struct uma_zone *, sack_hole_zone);
-VNET_DEFINE(int, tcp_do_sack);
-VNET_DEFINE(int, tcp_sack_maxholes);
-VNET_DEFINE(int, tcp_sack_globalmaxholes);
-VNET_DEFINE(int, tcp_sack_globalholes);
-
#define V_sack_hole_zone VNET(sack_hole_zone)
-#define V_tcp_do_sack VNET(tcp_do_sack)
-#define V_tcp_sack_maxholes VNET(tcp_sack_maxholes)
-#define V_tcp_sack_globalmaxholes VNET(tcp_sack_globalmaxholes)
-#define V_tcp_sack_globalholes VNET(tcp_sack_globalholes)
SYSCTL_NODE(_net_inet_tcp, OID_AUTO, sack, CTLFLAG_RW, 0, "TCP SACK");
+VNET_DEFINE(int, tcp_do_sack) = 1;
+#define V_tcp_do_sack VNET(tcp_do_sack)
SYSCTL_VNET_INT(_net_inet_tcp_sack, OID_AUTO, enable, CTLFLAG_RW,
&VNET_NAME(tcp_do_sack), 0, "Enable/Disable TCP SACK support");
+VNET_DEFINE(int, tcp_sack_maxholes) = 128;
+#define V_tcp_sack_maxholes VNET(tcp_sack_maxholes)
SYSCTL_VNET_INT(_net_inet_tcp_sack, OID_AUTO, maxholes, CTLFLAG_RW,
&VNET_NAME(tcp_sack_maxholes), 0,
"Maximum number of TCP SACK holes allowed per connection");
+VNET_DEFINE(int, tcp_sack_globalmaxholes) = 65536;
+#define V_tcp_sack_globalmaxholes VNET(tcp_sack_globalmaxholes)
SYSCTL_VNET_INT(_net_inet_tcp_sack, OID_AUTO, globalmaxholes, CTLFLAG_RW,
&VNET_NAME(tcp_sack_globalmaxholes), 0,
"Global maximum number of TCP SACK holes");
+VNET_DEFINE(int, tcp_sack_globalholes) = 0;
+#define V_tcp_sack_globalholes VNET(tcp_sack_globalholes)
SYSCTL_VNET_INT(_net_inet_tcp_sack, OID_AUTO, globalholes, CTLFLAG_RD,
&VNET_NAME(tcp_sack_globalholes), 0,
"Global number of TCP SACK holes currently allocated");
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 9ec434c..43ed1e4 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -111,28 +111,10 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
-VNET_DEFINE(int, tcp_mssdflt);
+VNET_DEFINE(int, tcp_mssdflt) = TCP_MSS;
#ifdef INET6
-VNET_DEFINE(int, tcp_v6mssdflt);
+VNET_DEFINE(int, tcp_v6mssdflt) = TCP6_MSS;
#endif
-VNET_DEFINE(int, tcp_minmss);
-VNET_DEFINE(int, tcp_do_rfc1323);
-
-static VNET_DEFINE(int, icmp_may_rst);
-static VNET_DEFINE(int, tcp_isn_reseed_interval);
-static VNET_DEFINE(int, tcp_inflight_enable);
-static VNET_DEFINE(int, tcp_inflight_rttthresh);
-static VNET_DEFINE(int, tcp_inflight_min);
-static VNET_DEFINE(int, tcp_inflight_max);
-static VNET_DEFINE(int, tcp_inflight_stab);
-
-#define V_icmp_may_rst VNET(icmp_may_rst)
-#define V_tcp_isn_reseed_interval VNET(tcp_isn_reseed_interval)
-#define V_tcp_inflight_enable VNET(tcp_inflight_enable)
-#define V_tcp_inflight_rttthresh VNET(tcp_inflight_rttthresh)
-#define V_tcp_inflight_min VNET(tcp_inflight_min)
-#define V_tcp_inflight_max VNET(tcp_inflight_max)
-#define V_tcp_inflight_stab VNET(tcp_inflight_stab)
static int
sysctl_net_inet_tcp_mss_check(SYSCTL_HANDLER_ARGS)
@@ -194,10 +176,12 @@ vnet_sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS)
* with packet generation and sending. Set to zero to disable MINMSS
* checking. This setting prevents us from sending too small packets.
*/
+VNET_DEFINE(int, tcp_minmss) = TCP_MINMSS;
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, minmss, CTLFLAG_RW,
&VNET_NAME(tcp_minmss), 0,
"Minmum TCP Maximum Segment Size");
+VNET_DEFINE(int, tcp_do_rfc1323) = 1;
SYSCTL_VNET_INT(_net_inet_tcp, TCPCTL_DO_RFC1323, rfc1323, CTLFLAG_RW,
&VNET_NAME(tcp_do_rfc1323), 0,
"Enable rfc1323 (high performance TCP) extensions");
@@ -217,10 +201,14 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_tcpdrain, CTLFLAG_RW, &do_tcpdrain, 0,
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_RD,
&VNET_NAME(tcbinfo.ipi_count), 0, "Number of active PCBs");
+static VNET_DEFINE(int, icmp_may_rst) = 1;
+#define V_icmp_may_rst VNET(icmp_may_rst)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, icmp_may_rst, CTLFLAG_RW,
&VNET_NAME(icmp_may_rst), 0,
"Certain ICMP unreachable messages may abort connections in SYN_SENT");
+static VNET_DEFINE(int, tcp_isn_reseed_interval) = 0;
+#define V_tcp_isn_reseed_interval VNET(tcp_isn_reseed_interval)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_RW,
&VNET_NAME(tcp_isn_reseed_interval), 0,
"Seconds between reseeding of ISN secret");
@@ -233,6 +221,8 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_RW,
SYSCTL_NODE(_net_inet_tcp, OID_AUTO, inflight, CTLFLAG_RW, 0,
"TCP inflight data limiting");
+static VNET_DEFINE(int, tcp_inflight_enable) = 1;
+#define V_tcp_inflight_enable VNET(tcp_inflight_enable)
SYSCTL_VNET_INT(_net_inet_tcp_inflight, OID_AUTO, enable, CTLFLAG_RW,
&VNET_NAME(tcp_inflight_enable), 0,
"Enable automatic TCP inflight data limiting");
@@ -242,19 +232,27 @@ SYSCTL_INT(_net_inet_tcp_inflight, OID_AUTO, debug, CTLFLAG_RW,
&tcp_inflight_debug, 0,
"Debug TCP inflight calculations");
+static VNET_DEFINE(int, tcp_inflight_rttthresh);
+#define V_tcp_inflight_rttthresh VNET(tcp_inflight_rttthresh)
SYSCTL_VNET_PROC(_net_inet_tcp_inflight, OID_AUTO, rttthresh,
CTLTYPE_INT|CTLFLAG_RW, &VNET_NAME(tcp_inflight_rttthresh), 0,
vnet_sysctl_msec_to_ticks, "I",
"RTT threshold below which inflight will deactivate itself");
+static VNET_DEFINE(int, tcp_inflight_min) = 6144;
+#define V_tcp_inflight_min VNET(tcp_inflight_min)
SYSCTL_VNET_INT(_net_inet_tcp_inflight, OID_AUTO, min, CTLFLAG_RW,
&VNET_NAME(tcp_inflight_min), 0,
"Lower-bound for TCP inflight window");
+static VNET_DEFINE(int, tcp_inflight_max) = TCP_MAXWIN << TCP_MAX_WINSHIFT;
+#define V_tcp_inflight_max VNET(tcp_inflight_max)
SYSCTL_VNET_INT(_net_inet_tcp_inflight, OID_AUTO, max, CTLFLAG_RW,
&VNET_NAME(tcp_inflight_max), 0,
"Upper-bound for TCP inflight window");
+static VNET_DEFINE(int, tcp_inflight_stab) = 20;
+#define V_tcp_inflight_stab VNET(tcp_inflight_stab)
SYSCTL_VNET_INT(_net_inet_tcp_inflight, OID_AUTO, stab, CTLFLAG_RW,
&VNET_NAME(tcp_inflight_stab), 0,
"Inflight Algorithm Stabilization 20 = 2 packets");
@@ -329,53 +327,6 @@ tcp_init(void)
{
int hashsize;
- V_blackhole = 0;
- V_tcp_delack_enabled = 1;
- V_drop_synfin = 0;
- V_tcp_do_rfc3042 = 1;
- V_tcp_do_rfc3390 = 1;
- V_tcp_do_ecn = 0;
- V_tcp_ecn_maxretries = 1;
- V_tcp_insecure_rst = 0;
- V_tcp_do_autorcvbuf = 1;
- V_tcp_autorcvbuf_inc = 16*1024;
- V_tcp_autorcvbuf_max = 256*1024;
- V_tcp_do_rfc3465 = 1;
- V_tcp_abc_l_var = 2;
-
- V_tcp_mssdflt = TCP_MSS;
-#ifdef INET6
- V_tcp_v6mssdflt = TCP6_MSS;
-#endif
- V_tcp_minmss = TCP_MINMSS;
- V_tcp_do_rfc1323 = 1;
- V_icmp_may_rst = 1;
- V_tcp_isn_reseed_interval = 0;
- V_tcp_inflight_enable = 1;
- V_tcp_inflight_min = 6144;
- V_tcp_inflight_max = TCP_MAXWIN << TCP_MAX_WINSHIFT;
- V_tcp_inflight_stab = 20;
-
- V_path_mtu_discovery = 1;
- V_ss_fltsz = 1;
- V_ss_fltsz_local = 4;
- V_tcp_do_newreno = 1;
- V_tcp_do_tso = 1;
- V_tcp_do_autosndbuf = 1;
- V_tcp_autosndbuf_inc = 8*1024;
- V_tcp_autosndbuf_max = 256*1024;
-
- V_nolocaltimewait = 0;
-
- V_tcp_do_sack = 1;
- V_tcp_sack_maxholes = 128;
- V_tcp_sack_globalmaxholes = 65536;
- V_tcp_sack_globalholes = 0;
-
- V_tcp_inflight_rttthresh = TCPTV_INFLIGHT_RTTTHRESH;
-
- TUNABLE_INT_FETCH("net.inet.tcp.sack.enable", &V_tcp_do_sack);
-
hashsize = TCBHASHSIZE;
TUNABLE_INT_FETCH("net.inet.tcp.tcbhashsize", &hashsize);
if (!powerof2(hashsize)) {
@@ -385,16 +336,21 @@ tcp_init(void)
in_pcbinfo_init(&V_tcbinfo, "tcp", &V_tcb, hashsize, hashsize,
"tcp_inpcb", tcp_inpcb_init, NULL, UMA_ZONE_NOFREE);
+ V_tcp_inflight_rttthresh = TCPTV_INFLIGHT_RTTTHRESH;
+
/*
* These have to be type stable for the benefit of the timers.
*/
V_tcpcb_zone = uma_zcreate("tcpcb", sizeof(struct tcpcb_mem),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
uma_zone_set_max(V_tcpcb_zone, maxsockets);
+
tcp_tw_init();
syncache_init();
tcp_hc_init();
tcp_reass_init();
+
+ TUNABLE_INT_FETCH("net.inet.tcp.sack.enable", &V_tcp_do_sack);
V_sack_hole_zone = uma_zcreate("sackhole", sizeof(struct sackhole),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 4d9d487..c47493c 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -97,19 +97,14 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
-static VNET_DEFINE(struct tcp_syncache, tcp_syncache);
-static VNET_DEFINE(int, tcp_syncookies);
-static VNET_DEFINE(int, tcp_syncookiesonly);
-VNET_DEFINE(int, tcp_sc_rst_sock_fail);
-
-#define V_tcp_syncache VNET(tcp_syncache)
+static VNET_DEFINE(int, tcp_syncookies) = 1;
#define V_tcp_syncookies VNET(tcp_syncookies)
-#define V_tcp_syncookiesonly VNET(tcp_syncookiesonly)
-
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, syncookies, CTLFLAG_RW,
&VNET_NAME(tcp_syncookies), 0,
"Use TCP SYN cookies if the syncache overflows");
+static VNET_DEFINE(int, tcp_syncookiesonly) = 0;
+#define V_tcp_syncookiesonly VNET(tcp_syncookiesonly)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, syncookies_only, CTLFLAG_RW,
&VNET_NAME(tcp_syncookiesonly), 0,
"Use only TCP SYN cookies");
@@ -148,6 +143,9 @@ static struct syncache
#define TCP_SYNCACHE_HASHSIZE 512
#define TCP_SYNCACHE_BUCKETLIMIT 30
+static VNET_DEFINE(struct tcp_syncache, tcp_syncache);
+#define V_tcp_syncache VNET(tcp_syncache)
+
SYSCTL_NODE(_net_inet_tcp, OID_AUTO, syncache, CTLFLAG_RW, 0, "TCP SYN cache");
SYSCTL_VNET_INT(_net_inet_tcp_syncache, OID_AUTO, bucketlimit, CTLFLAG_RDTUN,
@@ -170,6 +168,7 @@ SYSCTL_VNET_INT(_net_inet_tcp_syncache, OID_AUTO, rexmtlimit, CTLFLAG_RW,
&VNET_NAME(tcp_syncache.rexmt_limit), 0,
"Limit on SYN/ACK retransmissions");
+VNET_DEFINE(int, tcp_sc_rst_sock_fail) = 1;
SYSCTL_VNET_INT(_net_inet_tcp_syncache, OID_AUTO, rst_on_sock_fail,
CTLFLAG_RW, &VNET_NAME(tcp_sc_rst_sock_fail), 0,
"Send reset on socket allocation failure");
@@ -224,10 +223,6 @@ syncache_init(void)
{
int i;
- V_tcp_syncookies = 1;
- V_tcp_syncookiesonly = 0;
- V_tcp_sc_rst_sock_fail = 1;
-
V_tcp_syncache.cache_count = 0;
V_tcp_syncache.hashsize = TCP_SYNCACHE_HASHSIZE;
V_tcp_syncache.bucket_limit = TCP_SYNCACHE_BUCKETLIMIT;
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 6e5b013..42df4fe 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -92,6 +92,8 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
+static VNET_DEFINE(uma_zone_t, tcptw_zone);
+#define V_tcptw_zone VNET(tcptw_zone)
static int maxtcptw;
/*
@@ -100,11 +102,7 @@ static int maxtcptw;
* queue pointers in each tcptw structure, are protected using the global
* tcbinfo lock, which must be held over queue iteration and modification.
*/
-static VNET_DEFINE(uma_zone_t, tcptw_zone);
static VNET_DEFINE(TAILQ_HEAD(, tcptw), twq_2msl);
-VNET_DEFINE(int, nolocaltimewait);
-
-#define V_tcptw_zone VNET(tcptw_zone)
#define V_twq_2msl VNET(twq_2msl)
static void tcp_tw_2msl_reset(struct tcptw *, int);
@@ -149,6 +147,8 @@ SYSCTL_PROC(_net_inet_tcp, OID_AUTO, maxtcptw, CTLTYPE_INT|CTLFLAG_RW,
&maxtcptw, 0, sysctl_maxtcptw, "IU",
"Maximum number of compressed TCP TIME_WAIT entries");
+VNET_DEFINE(int, nolocaltimewait) = 0;
+#define V_nolocaltimewait VNET(nolocaltimewait)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, nolocaltimewait, CTLFLAG_RW,
&VNET_NAME(nolocaltimewait), 0,
"Do not create compressed TCP TIME_WAIT entries for local connections");
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 3a59eee..5811439 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -42,12 +42,12 @@
* Kernel variables for tcp.
*/
VNET_DECLARE(int, tcp_do_rfc1323);
+#define V_tcp_do_rfc1323 VNET(tcp_do_rfc1323)
+
VNET_DECLARE(int, tcp_reass_qsize);
VNET_DECLARE(struct uma_zone *, tcp_reass_zone);
-#define V_tcp_do_rfc1323 VNET(tcp_do_rfc1323)
#define V_tcp_reass_qsize VNET(tcp_reass_qsize)
#define V_tcp_reass_zone VNET(tcp_reass_zone)
-
#endif /* _KERNEL */
/* TCP segment queue entry */
@@ -558,11 +558,10 @@ SYSCTL_DECL(_net_inet_tcp_sack);
MALLOC_DECLARE(M_TCPLOG);
#endif
-extern int tcp_log_in_vain;
-
VNET_DECLARE(struct inpcbhead, tcb); /* queue of active tcpcb's */
VNET_DECLARE(struct inpcbinfo, tcbinfo);
VNET_DECLARE(struct tcpstat, tcpstat); /* tcp statistics */
+extern int tcp_log_in_vain;
VNET_DECLARE(int, tcp_mssdflt); /* XXX */
VNET_DECLARE(int, tcp_minmss);
VNET_DECLARE(int, tcp_delack_enabled);
@@ -570,7 +569,6 @@ VNET_DECLARE(int, tcp_do_newreno);
VNET_DECLARE(int, path_mtu_discovery);
VNET_DECLARE(int, ss_fltsz);
VNET_DECLARE(int, ss_fltsz_local);
-
#define V_tcb VNET(tcb)
#define V_tcbinfo VNET(tcbinfo)
#define V_tcpstat VNET(tcpstat)
@@ -582,55 +580,13 @@ VNET_DECLARE(int, ss_fltsz_local);
#define V_ss_fltsz VNET(ss_fltsz)
#define V_ss_fltsz_local VNET(ss_fltsz_local)
-VNET_DECLARE(int, blackhole);
-VNET_DECLARE(int, drop_synfin);
-VNET_DECLARE(int, tcp_do_rfc3042);
-VNET_DECLARE(int, tcp_do_rfc3390);
-VNET_DECLARE(int, tcp_insecure_rst);
-VNET_DECLARE(int, tcp_do_autorcvbuf);
-VNET_DECLARE(int, tcp_autorcvbuf_inc);
-VNET_DECLARE(int, tcp_autorcvbuf_max);
-VNET_DECLARE(int, tcp_do_rfc3465);
-VNET_DECLARE(int, tcp_abc_l_var);
-
-#define V_blackhole VNET(blackhole)
-#define V_drop_synfin VNET(drop_synfin)
-#define V_tcp_do_rfc3042 VNET(tcp_do_rfc3042)
-#define V_tcp_do_rfc3390 VNET(tcp_do_rfc3390)
-#define V_tcp_insecure_rst VNET(tcp_insecure_rst)
-#define V_tcp_do_autorcvbuf VNET(tcp_do_autorcvbuf)
-#define V_tcp_autorcvbuf_inc VNET(tcp_autorcvbuf_inc)
-#define V_tcp_autorcvbuf_max VNET(tcp_autorcvbuf_max)
-#define V_tcp_do_rfc3465 VNET(tcp_do_rfc3465)
-#define V_tcp_abc_l_var VNET(tcp_abc_l_var)
-
-VNET_DECLARE(int, tcp_do_tso);
-VNET_DECLARE(int, tcp_do_autosndbuf);
-VNET_DECLARE(int, tcp_autosndbuf_inc);
-VNET_DECLARE(int, tcp_autosndbuf_max);
-
-#define V_tcp_do_tso VNET(tcp_do_tso)
-#define V_tcp_do_autosndbuf VNET(tcp_do_autosndbuf)
-#define V_tcp_autosndbuf_inc VNET(tcp_autosndbuf_inc)
-#define V_tcp_autosndbuf_max VNET(tcp_autosndbuf_max)
-
-VNET_DECLARE(int, nolocaltimewait);
-
-#define V_nolocaltimewait VNET(nolocaltimewait)
-
VNET_DECLARE(int, tcp_do_sack); /* SACK enabled/disabled */
-VNET_DECLARE(int, tcp_sack_maxholes);
-VNET_DECLARE(int, tcp_sack_globalmaxholes);
-VNET_DECLARE(int, tcp_sack_globalholes);
VNET_DECLARE(int, tcp_sc_rst_sock_fail); /* RST on sock alloc failure */
-VNET_DECLARE(int, tcp_do_ecn); /* TCP ECN enabled/disabled */
-VNET_DECLARE(int, tcp_ecn_maxretries);
-
#define V_tcp_do_sack VNET(tcp_do_sack)
-#define V_tcp_sack_maxholes VNET(tcp_sack_maxholes)
-#define V_tcp_sack_globalmaxholes VNET(tcp_sack_globalmaxholes)
-#define V_tcp_sack_globalholes VNET(tcp_sack_globalholes)
#define V_tcp_sc_rst_sock_fail VNET(tcp_sc_rst_sock_fail)
+
+VNET_DECLARE(int, tcp_do_ecn); /* TCP ECN enabled/disabled */
+VNET_DECLARE(int, tcp_ecn_maxretries);
#define V_tcp_do_ecn VNET(tcp_do_ecn)
#define V_tcp_ecn_maxretries VNET(tcp_ecn_maxretries)
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 0d8e04d..4541038 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -94,8 +94,6 @@ __FBSDID("$FreeBSD$");
* Per RFC 768, August, 1980.
*/
-VNET_DEFINE(int, udp_blackhole);
-
/*
* BSD 4.2 defaulted the udp checksum to be off. Turning off udp checksums
* removes the only data integrity mechanism for packets and malformed
@@ -110,6 +108,7 @@ int udp_log_in_vain = 0;
SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW,
&udp_log_in_vain, 0, "Log all incoming UDP packets");
+VNET_DEFINE(int, udp_blackhole) = 0;
SYSCTL_VNET_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW,
&VNET_NAME(udp_blackhole), 0,
"Do not send port unreachables for refused connects");
@@ -133,14 +132,13 @@ SYSCTL_ULONG(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
VNET_DEFINE(struct inpcbhead, udb); /* from udp_var.h */
VNET_DEFINE(struct inpcbinfo, udbinfo);
static VNET_DEFINE(uma_zone_t, udpcb_zone);
-VNET_DEFINE(struct udpstat, udpstat); /* from udp_var.h */
-
#define V_udpcb_zone VNET(udpcb_zone)
#ifndef UDBHASHSIZE
#define UDBHASHSIZE 128
#endif
+VNET_DEFINE(struct udpstat, udpstat); /* from udp_var.h */
SYSCTL_VNET_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RW,
&VNET_NAME(udpstat), udpstat,
"UDP statistics (struct udpstat, netinet/udp_var.h)");
@@ -179,7 +177,6 @@ void
udp_init(void)
{
- V_udp_blackhole = 0;
in_pcbinfo_init(&V_udbinfo, "udp", &V_udb, UDBHASHSIZE, UDBHASHSIZE,
"udp_inpcb", udp_inpcb_init, NULL, UMA_ZONE_NOFREE);
V_udpcb_zone = uma_zcreate("udpcb", sizeof(struct udpcb),
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index b8d994c..aa7ee47 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -129,19 +129,17 @@ void kmod_udpstat_inc(int statnum);
SYSCTL_DECL(_net_inet_udp);
extern struct pr_usrreqs udp_usrreqs;
-
VNET_DECLARE(struct inpcbhead, udb);
VNET_DECLARE(struct inpcbinfo, udbinfo);
-VNET_DECLARE(struct udpstat, udpstat);
-VNET_DECLARE(int, udp_blackhole);
-
#define V_udb VNET(udb)
#define V_udbinfo VNET(udbinfo)
-#define V_udpstat VNET(udpstat)
-#define V_udp_blackhole VNET(udp_blackhole)
extern u_long udp_sendspace;
extern u_long udp_recvspace;
+VNET_DECLARE(struct udpstat, udpstat);
+VNET_DECLARE(int, udp_blackhole);
+#define V_udpstat VNET(udpstat)
+#define V_udp_blackhole VNET(udp_blackhole)
extern int udp_log_in_vain;
int udp_newudpcb(struct inpcb *);
diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c
index 8900f7d..1523133 100644
--- a/sys/netinet6/frag6.c
+++ b/sys/netinet6/frag6.c
@@ -106,16 +106,17 @@ void
frag6_init(void)
{
- V_ip6q.ip6q_next = V_ip6q.ip6q_prev = &V_ip6q;
V_ip6_maxfragpackets = nmbclusters / 4;
V_ip6_maxfrags = nmbclusters / 4;
+ V_ip6q.ip6q_next = V_ip6q.ip6q_prev = &V_ip6q;
if (!IS_DEFAULT_VNET(curvnet))
return;
- IP6Q_LOCK_INIT();
EVENTHANDLER_REGISTER(nmbclusters_change,
frag6_change, NULL, EVENTHANDLER_PRI_ANY);
+
+ IP6Q_LOCK_INIT();
}
/*
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 57f8d32..87df9c3 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -113,23 +113,22 @@ __FBSDID("$FreeBSD$");
extern struct domain inet6domain;
+VNET_DEFINE(struct icmp6stat, icmp6stat);
+
VNET_DECLARE(struct inpcbinfo, ripcbinfo);
VNET_DECLARE(struct inpcbhead, ripcb);
VNET_DECLARE(int, icmp6errppslim);
+static VNET_DEFINE(int, icmp6errpps_count) = 0;
+static VNET_DEFINE(struct timeval, icmp6errppslim_last);
VNET_DECLARE(int, icmp6_nodeinfo);
#define V_ripcbinfo VNET(ripcbinfo)
#define V_ripcb VNET(ripcb)
#define V_icmp6errppslim VNET(icmp6errppslim)
+#define V_icmp6errpps_count VNET(icmp6errpps_count)
+#define V_icmp6errppslim_last VNET(icmp6errppslim_last)
#define V_icmp6_nodeinfo VNET(icmp6_nodeinfo)
-VNET_DEFINE(struct icmp6stat, icmp6stat);
-static VNET_DEFINE(int, icmp6errpps_count);
-static VNET_DEFINE(struct timeval, icmp6errppslim_last);
-
-#define V_icmp6errpps_count VNET(icmp6errpps_count)
-#define V_icmp6errppslim_last VNET(icmp6errppslim_last)
-
static void icmp6_errcount(struct icmp6errstat *, int, int);
static int icmp6_rip6_input(struct mbuf **, int);
static int icmp6_ratelimit(const struct in6_addr *, const int, const int);
@@ -144,14 +143,6 @@ static int ni6_store_addrs __P((struct icmp6_nodeinfo *, struct icmp6_nodeinfo *
struct ifnet *, int));
static int icmp6_notify_error(struct mbuf **, int, int, int);
-
-void
-icmp6_init(void)
-{
-
- V_icmp6errpps_count = 0;
-}
-
/*
* Kernel module interface for updating icmp6stat. The argument is an index
* into icmp6stat treated as an array of u_quad_t. While this encodes the
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 74c15d5..15ff6b2 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -63,6 +63,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_compat.h"
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -176,6 +177,14 @@ in6_mask2len(struct in6_addr *mask, u_char *lim0)
#define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa))
#define ia62ifa(ia6) (&((ia6)->ia_ifa))
+#ifdef COMPAT_FREEBSD32
+struct in6_ndifreq32 {
+ char ifname[IFNAMSIZ];
+ uint32_t ifindex;
+};
+#define SIOCGDEFIFACE32_IN6 _IOWR('i', 86, struct in6_ndifreq32)
+#endif
+
int
in6_control(struct socket *so, u_long cmd, caddr_t data,
struct ifnet *ifp, struct thread *td)
@@ -226,6 +235,22 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
case SIOCGNBRINFO_IN6:
case SIOCGDEFIFACE_IN6:
return (nd6_ioctl(cmd, data, ifp));
+
+#ifdef COMPAT_FREEBSD32
+ case SIOCGDEFIFACE32_IN6:
+ {
+ struct in6_ndifreq ndif;
+ struct in6_ndifreq32 *ndif32;
+
+ error = nd6_ioctl(SIOCGDEFIFACE_IN6, (caddr_t)&ndif,
+ ifp);
+ if (error)
+ return (error);
+ ndif32 = (struct in6_ndifreq32 *)data;
+ ndif32->ifindex = ndif.ifindex;
+ return (0);
+ }
+#endif
}
switch (cmd) {
diff --git a/sys/netinet6/in6_gif.c b/sys/netinet6/in6_gif.c
index a481706..e786836 100644
--- a/sys/netinet6/in6_gif.c
+++ b/sys/netinet6/in6_gif.c
@@ -41,8 +41,10 @@ __FBSDID("$FreeBSD$");
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/errno.h>
+#include <sys/kernel.h>
#include <sys/queue.h>
#include <sys/syslog.h>
+#include <sys/sysctl.h>
#include <sys/protosw.h>
#include <sys/malloc.h>
@@ -69,6 +71,13 @@ __FBSDID("$FreeBSD$");
#include <net/if_gif.h>
+VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM;
+#define V_ip6_gif_hlim VNET(ip6_gif_hlim)
+
+SYSCTL_DECL(_net_inet6_ip6);
+SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_RW,
+ &VNET_NAME(ip6_gif_hlim), 0, "");
+
static int gif_validate6(const struct ip6_hdr *, struct gif_softc *,
struct ifnet *);
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 5041ee2..363d7be 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -67,10 +67,15 @@ __FBSDID("$FreeBSD$");
#include <netinet6/mld6_var.h>
#include <netinet6/scope6_var.h>
-VNET_DEFINE(unsigned long, in6_maxmtu);
-VNET_DEFINE(int, ip6_auto_linklocal);
-VNET_DEFINE(struct callout, in6_tmpaddrtimer_ch);
+VNET_DEFINE(unsigned long, in6_maxmtu) = 0;
+
+#ifdef IP6_AUTO_LINKLOCAL
+VNET_DEFINE(int, ip6_auto_linklocal) = IP6_AUTO_LINKLOCAL;
+#else
+VNET_DEFINE(int, ip6_auto_linklocal) = 1; /* enabled by default */
+#endif
+VNET_DEFINE(struct callout, in6_tmpaddrtimer_ch);
#define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch)
VNET_DECLARE(struct inpcbinfo, ripcbinfo);
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
index 3289e57..51f5187 100644
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -234,7 +234,6 @@ struct ip6protosw inet6sw[] = {
.pr_output = rip6_output,
.pr_ctlinput = rip6_ctlinput,
.pr_ctloutput = rip6_ctloutput,
- .pr_init = icmp6_init,
.pr_fasttimo = icmp6_fasttimo,
.pr_slowtimo = icmp6_slowtimo,
.pr_usrreqs = &rip6_usrreqs
@@ -378,25 +377,44 @@ VNET_DOMAIN_SET(inet6);
/*
* Internet configuration info
*/
-VNET_DEFINE(int, ip6_forwarding);
-VNET_DEFINE(int, ip6_sendredirects);
-VNET_DEFINE(int, ip6_defhlim);
-VNET_DEFINE(int, ip6_defmcasthlim);
-VNET_DEFINE(int, ip6_accept_rtadv);
-VNET_DEFINE(int, ip6_maxfragpackets);
-VNET_DEFINE(int, ip6_maxfrags);
-VNET_DEFINE(int, ip6_log_interval);
-VNET_DEFINE(int, ip6_hdrnestlimit);
-VNET_DEFINE(int, ip6_dad_count);
-VNET_DEFINE(int, ip6_auto_flowlabel);
-VNET_DEFINE(int, ip6_use_deprecated);
-VNET_DEFINE(int, ip6_rr_prune);
-VNET_DEFINE(int, ip6_mcast_pmtu);
-VNET_DEFINE(int, ip6_v6only);
-VNET_DEFINE(int, ip6_keepfaith);
-VNET_DEFINE(time_t, ip6_log_time);
-VNET_DEFINE(int, ip6stealth);
-VNET_DEFINE(int, nd6_onlink_ns_rfc4861);
+#ifndef IPV6FORWARDING
+#ifdef GATEWAY6
+#define IPV6FORWARDING 1 /* forward IP6 packets not for us */
+#else
+#define IPV6FORWARDING 0 /* don't forward IP6 packets not for us */
+#endif /* GATEWAY6 */
+#endif /* !IPV6FORWARDING */
+
+#ifndef IPV6_SENDREDIRECTS
+#define IPV6_SENDREDIRECTS 1
+#endif
+
+VNET_DEFINE(int, ip6_forwarding) = IPV6FORWARDING; /* act as router? */
+VNET_DEFINE(int, ip6_sendredirects) = IPV6_SENDREDIRECTS;
+VNET_DEFINE(int, ip6_defhlim) = IPV6_DEFHLIM;
+VNET_DEFINE(int, ip6_defmcasthlim) = IPV6_DEFAULT_MULTICAST_HOPS;
+VNET_DEFINE(int, ip6_accept_rtadv) = 0;
+VNET_DEFINE(int, ip6_maxfragpackets); /* initialized in frag6.c:frag6_init() */
+VNET_DEFINE(int, ip6_maxfrags); /* initialized in frag6.c:frag6_init() */
+VNET_DEFINE(int, ip6_log_interval) = 5;
+VNET_DEFINE(int, ip6_hdrnestlimit) = 15;/* How many header options will we
+ * process? */
+VNET_DEFINE(int, ip6_dad_count) = 1; /* DupAddrDetectionTransmits */
+VNET_DEFINE(int, ip6_auto_flowlabel) = 1;
+VNET_DEFINE(int, ip6_use_deprecated) = 1;/* allow deprecated addr
+ * (RFC2462 5.5.4) */
+VNET_DEFINE(int, ip6_rr_prune) = 5; /* router renumbering prefix
+ * walk list every 5 sec. */
+VNET_DEFINE(int, ip6_mcast_pmtu) = 0; /* enable pMTU discovery for multicast? */
+VNET_DEFINE(int, ip6_v6only) = 1;
+
+VNET_DEFINE(int, ip6_keepfaith) = 0;
+VNET_DEFINE(time_t, ip6_log_time) = (time_t)0L;
+#ifdef IPSTEALTH
+VNET_DEFINE(int, ip6stealth) = 0;
+#endif
+VNET_DEFINE(int, nd6_onlink_ns_rfc4861) = 0;/* allow 'on-link' nd6 NS
+ * (RFC 4861) */
/* icmp6 */
/*
@@ -404,26 +422,31 @@ VNET_DEFINE(int, nd6_onlink_ns_rfc4861);
* XXX: what if we don't define INET? Should we define pmtu6_expire
* or so? (jinmei@kame.net 19990310)
*/
-VNET_DEFINE(int, pmtu_expire);
-VNET_DEFINE(int, pmtu_probe);
+VNET_DEFINE(int, pmtu_expire) = 60*10;
+VNET_DEFINE(int, pmtu_probe) = 60*2;
/* raw IP6 parameters */
/*
* Nominal space allocated to a raw ip socket.
*/
-VNET_DEFINE(u_long, rip6_sendspace);
-VNET_DEFINE(u_long, rip6_recvspace);
+#define RIPV6SNDQ 8192
+#define RIPV6RCVQ 8192
+
+VNET_DEFINE(u_long, rip6_sendspace) = RIPV6SNDQ;
+VNET_DEFINE(u_long, rip6_recvspace) = RIPV6RCVQ;
/* ICMPV6 parameters */
-VNET_DEFINE(int, icmp6_rediraccept);
-VNET_DEFINE(int, icmp6_redirtimeout);
-VNET_DEFINE(int, icmp6errppslim);
+VNET_DEFINE(int, icmp6_rediraccept) = 1;/* accept and process redirects */
+VNET_DEFINE(int, icmp6_redirtimeout) = 10 * 60; /* 10 minutes */
+VNET_DEFINE(int, icmp6errppslim) = 100; /* 100pps */
/* control how to respond to NI queries */
-VNET_DEFINE(int, icmp6_nodeinfo);
+VNET_DEFINE(int, icmp6_nodeinfo) =
+ (ICMP6_NODEINFO_FQDNOK|ICMP6_NODEINFO_NODEADDROK);
/* UDP on IP6 parameters */
-VNET_DEFINE(int, udp6_sendspace);
-VNET_DEFINE(int, udp6_recvspace);
+VNET_DEFINE(int, udp6_sendspace) = 9216;/* really max datagram size */
+VNET_DEFINE(int, udp6_recvspace) = 40 * (1024 + sizeof(struct sockaddr_in6));
+ /* 40 1K datagrams */
/*
* sysctl related items.
@@ -571,7 +594,6 @@ SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXNUDHINT, nd6_maxnudhint,
CTLFLAG_RW, &VNET_NAME(nd6_maxnudhint), 0, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_DEBUG, nd6_debug, CTLFLAG_RW,
&VNET_NAME(nd6_debug), 0, "");
-
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_ONLINKNSRFC4861,
nd6_onlink_ns_rfc4861, CTLFLAG_RW, &VNET_NAME(nd6_onlink_ns_rfc4861),
0, "Accept 'on-link' nd6 NS in compliance with RFC 4861.");
diff --git a/sys/netinet6/in6_rmx.c b/sys/netinet6/in6_rmx.c
index 1ae04c3..8927a17 100644
--- a/sys/netinet6/in6_rmx.c
+++ b/sys/netinet6/in6_rmx.c
@@ -204,20 +204,21 @@ in6_matroute(void *v_arg, struct radix_node_head *head)
SYSCTL_DECL(_net_inet6_ip6);
-static VNET_DEFINE(int, rtq_reallyold6);
-static VNET_DEFINE(int, rtq_minreallyold6);
-static VNET_DEFINE(int, rtq_toomany6);
-
+static VNET_DEFINE(int, rtq_reallyold6) = 60*60;
+ /* one hour is ``really old'' */
#define V_rtq_reallyold6 VNET(rtq_reallyold6)
-#define V_rtq_minreallyold6 VNET(rtq_minreallyold6)
-#define V_rtq_toomany6 VNET(rtq_toomany6)
-
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTEXPIRE, rtexpire, CTLFLAG_RW,
&VNET_NAME(rtq_reallyold6) , 0, "");
+static VNET_DEFINE(int, rtq_minreallyold6) = 10;
+ /* never automatically crank down to less */
+#define V_rtq_minreallyold6 VNET(rtq_minreallyold6)
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTMINEXPIRE, rtminexpire, CTLFLAG_RW,
&VNET_NAME(rtq_minreallyold6) , 0, "");
+static VNET_DEFINE(int, rtq_toomany6) = 128;
+ /* 128 cached routes is ``too many'' */
+#define V_rtq_toomany6 VNET(rtq_toomany6)
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTMAXCACHE, rtmaxcache, CTLFLAG_RW,
&VNET_NAME(rtq_toomany6) , 0, "");
@@ -277,7 +278,7 @@ in6_rtqkill(struct radix_node *rn, void *rock)
}
#define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */
-static VNET_DEFINE(int, rtq_timeout6);
+static VNET_DEFINE(int, rtq_timeout6) = RTQ_TIMEOUT;
static VNET_DEFINE(struct callout, rtq_timer6);
#define V_rtq_timeout6 VNET(rtq_timeout6)
@@ -346,7 +347,6 @@ struct mtuex_arg {
struct radix_node_head *rnh;
time_t nextstop;
};
-
static VNET_DEFINE(struct callout, rtq_mtutimer);
#define V_rtq_mtutimer VNET(rtq_mtutimer)
@@ -422,11 +422,6 @@ in6_inithead(void **head, int off)
if (off == 0) /* See above */
return 1; /* only do the rest for the real thing */
- V_rtq_reallyold6 = 60*60; /* one hour is ``really old'' */
- V_rtq_minreallyold6 = 10; /* never automatically crank down to less */
- V_rtq_toomany6 = 128; /* 128 cached routes is ``too many'' */
- V_rtq_timeout6 = RTQ_TIMEOUT;
-
rnh = *head;
KASSERT(rnh == rt_tables_get_rnh(0, AF_INET6), ("rnh?"));
rnh->rnh_addaddr = in6_addroute;
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index ea302a5..49bc715 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -122,12 +122,11 @@ static struct sx addrsel_sxlock;
#define ADDRSEL_XUNLOCK() sx_xunlock(&addrsel_sxlock)
#define ADDR_LABEL_NOTAPP (-1)
-
static VNET_DEFINE(struct in6_addrpolicy, defaultaddrpolicy);
-VNET_DEFINE(int, ip6_prefer_tempaddr);
-
#define V_defaultaddrpolicy VNET(defaultaddrpolicy)
+VNET_DEFINE(int, ip6_prefer_tempaddr) = 0;
+
static int selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
struct rtentry **, int));
@@ -182,7 +181,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct inpcb *inp, struct route_in6 *ro, struct ucred *cred,
struct ifnet **ifpp, struct in6_addr *srcp)
{
- struct in6_addr dst;
+ struct in6_addr dst, tmp;
struct ifnet *ifp = NULL;
struct in6_ifaddr *ia = NULL, *ia_best = NULL;
struct in6_pktinfo *pi = NULL;
@@ -326,10 +325,9 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
if (!V_ip6_use_deprecated && IFA6_IS_DEPRECATED(ia))
continue;
+ /* If jailed only take addresses of the jail into account. */
if (cred != NULL &&
- prison_local_ip6(cred, &ia->ia_addr.sin6_addr,
- (inp != NULL &&
- (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0)
+ prison_check_ip6(cred, &ia->ia_addr.sin6_addr) != 0)
continue;
/* Rule 1: Prefer same address */
@@ -476,10 +474,26 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
return (EADDRNOTAVAIL);
}
+ /*
+ * At this point at least one of the addresses belonged to the jail
+ * but it could still be, that we want to further restrict it, e.g.
+ * theoratically IN6_IS_ADDR_LOOPBACK.
+ * It must not be IN6_IS_ADDR_UNSPECIFIED anymore.
+ * prison_local_ip6() will fix an IN6_IS_ADDR_LOOPBACK but should
+ * let all others previously selected pass.
+ * Use tmp to not change ::1 on lo0 to the primary jail address.
+ */
+ tmp = ia->ia_addr.sin6_addr;
+ if (cred != NULL && prison_local_ip6(cred, &tmp, (inp != NULL &&
+ (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) {
+ IN6_IFADDR_RUNLOCK();
+ return (EADDRNOTAVAIL);
+ }
+
if (ifpp)
*ifpp = ifp;
- bcopy(&ia->ia_addr.sin6_addr, srcp, sizeof(*srcp));
+ bcopy(&tmp, srcp, sizeof(*srcp));
IN6_IFADDR_RUNLOCK();
return (0);
}
@@ -937,8 +951,6 @@ void
addrsel_policy_init(void)
{
- V_ip6_prefer_tempaddr = 0;
-
init_policy_queue();
/* initialize the "last resort" policy */
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index d0a54e0..00342fd 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -487,12 +487,7 @@ struct in6_rrenumreq {
#ifdef _KERNEL
VNET_DECLARE(struct in6_ifaddrhead, in6_ifaddrhead);
-VNET_DECLARE(struct icmp6stat, icmp6stat);
-VNET_DECLARE(unsigned long, in6_maxmtu);
-
#define V_in6_ifaddrhead VNET(in6_ifaddrhead)
-#define V_icmp6stat VNET(icmp6stat)
-#define V_in6_maxmtu VNET(in6_maxmtu)
extern struct rwlock in6_ifaddr_lock;
#define IN6_IFADDR_LOCK_ASSERT( ) rw_assert(&in6_ifaddr_lock, RA_LOCKED)
@@ -503,6 +498,8 @@ extern struct rwlock in6_ifaddr_lock;
#define IN6_IFADDR_WLOCK_ASSERT() rw_assert(&in6_ifaddr_lock, RA_WLOCKED)
#define IN6_IFADDR_WUNLOCK() rw_wunlock(&in6_ifaddr_lock)
+VNET_DECLARE(struct icmp6stat, icmp6stat);
+#define V_icmp6stat VNET(icmp6stat)
#define in6_ifstat_inc(ifp, tag) \
do { \
if (ifp) \
@@ -511,6 +508,8 @@ do { \
extern struct in6_addr zeroin6_addr;
extern u_char inet6ctlerrmap[];
+VNET_DECLARE(unsigned long, in6_maxmtu);
+#define V_in6_maxmtu VNET(in6_maxmtu)
#endif /* _KERNEL */
/*
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index c244f37..42f9351 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -116,6 +116,7 @@ __FBSDID("$FreeBSD$");
extern struct domain inet6domain;
u_char ip6_protox[IPPROTO_MAX];
+VNET_DEFINE(struct in6_ifaddrhead, in6_ifaddrhead);
static struct netisr_handler ip6_nh = {
.nh_name = "ip6",
@@ -124,36 +125,16 @@ static struct netisr_handler ip6_nh = {
.nh_policy = NETISR_POLICY_FLOW,
};
-VNET_DEFINE(struct in6_ifaddrhead, in6_ifaddrhead);
-VNET_DEFINE(struct ip6stat, ip6stat);
-
VNET_DECLARE(struct callout, in6_tmpaddrtimer_ch);
-VNET_DECLARE(int, dad_init);
-VNET_DECLARE(int, pmtu_expire);
-VNET_DECLARE(int, pmtu_probe);
-VNET_DECLARE(u_long, rip6_sendspace);
-VNET_DECLARE(u_long, rip6_recvspace);
-VNET_DECLARE(int, icmp6errppslim);
-VNET_DECLARE(int, icmp6_nodeinfo);
-VNET_DECLARE(int, udp6_sendspace);
-VNET_DECLARE(int, udp6_recvspace);
-
#define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch)
-#define V_dad_init VNET(dad_init)
-#define V_pmtu_expire VNET(pmtu_expire)
-#define V_pmtu_probe VNET(pmtu_probe)
-#define V_rip6_sendspace VNET(rip6_sendspace)
-#define V_rip6_recvspace VNET(rip6_recvspace)
-#define V_icmp6errppslim VNET(icmp6errppslim)
-#define V_icmp6_nodeinfo VNET(icmp6_nodeinfo)
-#define V_udp6_sendspace VNET(udp6_sendspace)
-#define V_udp6_recvspace VNET(udp6_recvspace)
+
+VNET_DEFINE(struct pfil_head, inet6_pfil_hook);
+
+VNET_DEFINE(struct ip6stat, ip6stat);
struct rwlock in6_ifaddr_lock;
RW_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock");
-VNET_DEFINE (struct pfil_head, inet6_pfil_hook);
-
static void ip6_init2(void *);
static struct ip6aux *ip6_setdstifaddr(struct mbuf *, struct in6_ifaddr *);
static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
@@ -171,82 +152,11 @@ ip6_init(void)
struct ip6protosw *pr;
int i;
- V_in6_maxmtu = 0;
-#ifdef IP6_AUTO_LINKLOCAL
- V_ip6_auto_linklocal = IP6_AUTO_LINKLOCAL;
-#else
- V_ip6_auto_linklocal = 1; /* enabled by default */
-#endif
TUNABLE_INT_FETCH("net.inet6.ip6.auto_linklocal",
&V_ip6_auto_linklocal);
-#ifndef IPV6FORWARDING
-#ifdef GATEWAY6
-#define IPV6FORWARDING 1 /* forward IP6 packets not for us */
-#else
-#define IPV6FORWARDING 0 /* don't forward IP6 packets not for us */
-#endif /* GATEWAY6 */
-#endif /* !IPV6FORWARDING */
-
-#ifndef IPV6_SENDREDIRECTS
-#define IPV6_SENDREDIRECTS 1
-#endif
-
- V_ip6_forwarding = IPV6FORWARDING; /* act as router? */
- V_ip6_sendredirects = IPV6_SENDREDIRECTS;
- V_ip6_defhlim = IPV6_DEFHLIM;
- V_ip6_defmcasthlim = IPV6_DEFAULT_MULTICAST_HOPS;
- V_ip6_accept_rtadv = 0;
- V_ip6_log_interval = 5;
- V_ip6_hdrnestlimit = 15; /* How many header options will we process? */
- V_ip6_dad_count = 1; /* DupAddrDetectionTransmits */
- V_ip6_auto_flowlabel = 1;
- V_ip6_use_deprecated = 1;/* allow deprecated addr (RFC2462 5.5.4) */
- V_ip6_rr_prune = 5; /* router renumbering prefix
- * walk list every 5 sec. */
- V_ip6_mcast_pmtu = 0; /* enable pMTU discovery for multicast? */
- V_ip6_v6only = 1;
- V_ip6_keepfaith = 0;
- V_ip6_log_time = (time_t)0L;
-#ifdef IPSTEALTH
- V_ip6stealth = 0;
-#endif
- V_nd6_onlink_ns_rfc4861 = 0; /* allow 'on-link' nd6 NS (RFC 4861) */
-
- V_pmtu_expire = 60*10;
- V_pmtu_probe = 60*2;
-
- /* raw IP6 parameters */
- /*
- * Nominal space allocated to a raw ip socket.
- */
-#define RIPV6SNDQ 8192
-#define RIPV6RCVQ 8192
- V_rip6_sendspace = RIPV6SNDQ;
- V_rip6_recvspace = RIPV6RCVQ;
-
- /* ICMPV6 parameters */
- V_icmp6_rediraccept = 1; /* accept and process redirects */
- V_icmp6_redirtimeout = 10 * 60; /* 10 minutes */
- V_icmp6errppslim = 100; /* 100pps */
- /* control how to respond to NI queries */
- V_icmp6_nodeinfo = (ICMP6_NODEINFO_FQDNOK|ICMP6_NODEINFO_NODEADDROK);
-
- /* UDP on IP6 parameters */
- V_udp6_sendspace = 9216; /* really max datagram size */
- V_udp6_recvspace = 40 * (1024 + sizeof(struct sockaddr_in6));
- /* 40 1K datagrams */
- V_dad_init = 0;
-
TAILQ_INIT(&V_in6_ifaddrhead);
- scope6_init();
- addrsel_policy_init();
- nd6_init();
- frag6_init();
-
- V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
-
/* Initialize packet filter hooks. */
V_inet6_pfil_hook.ph_type = PFIL_TYPE_AF;
V_inet6_pfil_hook.ph_af = AF_INET6;
@@ -254,6 +164,13 @@ ip6_init(void)
printf("%s: WARNING: unable to register pfil hook, "
"error %d\n", __func__, i);
+ scope6_init();
+ addrsel_policy_init();
+ nd6_init();
+ frag6_init();
+
+ V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
+
/* Skip global initialization stuff for non-default instances. */
if (!IS_DEFAULT_VNET(curvnet))
return;
diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c
index 5496062..0c1ff78 100644
--- a/sys/netinet6/ip6_mroute.c
+++ b/sys/netinet6/ip6_mroute.c
@@ -130,7 +130,6 @@ static MALLOC_DEFINE(M_MRTABLE6, "mf6c", "multicast forwarding cache entry");
static int ip6_mdq(struct mbuf *, struct ifnet *, struct mf6c *);
static void phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
-static void pim6_init(void);
static int register_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
static int set_pim6(int *);
static int socket_send(struct socket *, struct mbuf *,
@@ -148,12 +147,11 @@ static const struct ip6protosw in6_pim_protosw = {
.pr_input = pim6_input,
.pr_output = rip6_output,
.pr_ctloutput = rip6_ctloutput,
- .pr_init = pim6_init,
.pr_usrreqs = &rip6_usrreqs
};
static int pim6_encapcheck(const struct mbuf *, int, int, void *);
-static VNET_DEFINE(int, ip6_mrouter_ver);
+static VNET_DEFINE(int, ip6_mrouter_ver) = 0;
#define V_ip6_mrouter_ver VNET(ip6_mrouter_ver)
SYSCTL_DECL(_net_inet6);
@@ -212,7 +210,7 @@ static struct mtx mif6_mtx;
#define MIF6_LOCK_DESTROY() mtx_destroy(&mif6_mtx)
#ifdef MRT6DEBUG
-static VNET_DEFINE(u_int, mrt6debug); /* debug level */
+static VNET_DEFINE(u_int, mrt6debug) = 0; /* debug level */
#define V_mrt6debug VNET(mrt6debug)
#define DEBUG_MFC 0x02
#define DEBUG_FORWARD 0x04
@@ -338,15 +336,6 @@ int X_ip6_mrouter_set(struct socket *, struct sockopt *);
int X_ip6_mrouter_get(struct socket *, struct sockopt *);
int X_mrt6_ioctl(u_long, caddr_t);
-static void
-pim6_init(void)
-{
-
-#ifdef MRT6DEBUG
- V_mrt6debug = 0; /* debug level */
-#endif
-}
-
/*
* Handle MRT setsockopt commands to modify the multicast routing tables.
*/
@@ -533,11 +522,7 @@ static int
ip6_mrouter_init(struct socket *so, int v, int cmd)
{
- V_ip6_mrouter_ver = 0;
-
#ifdef MRT6DEBUG
- V_mrt6debug = 0;
-
if (V_mrt6debug)
log(LOG_DEBUG,
"ip6_mrouter_init: so_type = %d, pr_protocol = %d\n",
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index a0a0f3a..3e91a79 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -295,12 +295,20 @@ VNET_DECLARE(struct ip6stat, ip6stat); /* statistics */
VNET_DECLARE(int, ip6_defhlim); /* default hop limit */
VNET_DECLARE(int, ip6_defmcasthlim); /* default multicast hop limit */
VNET_DECLARE(int, ip6_forwarding); /* act as router? */
-VNET_DECLARE(int, ip6_gif_hlim); /* Hop limit for gif encap packet */
VNET_DECLARE(int, ip6_use_deprecated); /* allow deprecated addr as source */
VNET_DECLARE(int, ip6_rr_prune); /* router renumbering prefix
* walk list every 5 sec. */
VNET_DECLARE(int, ip6_mcast_pmtu); /* enable pMTU discovery for multicast? */
VNET_DECLARE(int, ip6_v6only);
+#define V_ip6stat VNET(ip6stat)
+#define V_ip6_defhlim VNET(ip6_defhlim)
+#define V_ip6_defmcasthlim VNET(ip6_defmcasthlim)
+#define V_ip6_forwarding VNET(ip6_forwarding)
+#define V_ip6_use_deprecated VNET(ip6_use_deprecated)
+#define V_ip6_rr_prune VNET(ip6_rr_prune)
+#define V_ip6_mcast_pmtu VNET(ip6_mcast_pmtu)
+#define V_ip6_v6only VNET(ip6_v6only)
+
VNET_DECLARE(struct socket *, ip6_mrouter); /* multicast routing daemon */
VNET_DECLARE(int, ip6_sendredirects); /* send IP redirects when forwarding? */
VNET_DECLARE(int, ip6_maxfragpackets); /* Maximum packets in reassembly
@@ -314,31 +322,6 @@ VNET_DECLARE(time_t, ip6_log_time);
VNET_DECLARE(int, ip6_hdrnestlimit); /* upper limit of # of extension
* headers */
VNET_DECLARE(int, ip6_dad_count); /* DupAddrDetectionTransmits */
-
-VNET_DECLARE(int, ip6_auto_flowlabel);
-VNET_DECLARE(int, ip6_auto_linklocal);
-
-VNET_DECLARE(int, ip6_use_tempaddr); /* Whether to use temporary addresses */
-VNET_DECLARE(int, ip6_prefer_tempaddr); /* Whether to prefer temporary
- * addresses in the source address
- * selection */
-
-#ifdef IPSTEALTH
-VNET_DECLARE(int, ip6stealth);
-#endif
-
-VNET_DECLARE(int, ip6_use_defzone); /* Whether to use the default scope
- * zone when unspecified */
-
-#define V_ip6stat VNET(ip6stat)
-#define V_ip6_defhlim VNET(ip6_defhlim)
-#define V_ip6_defmcasthlim VNET(ip6_defmcasthlim)
-#define V_ip6_forwarding VNET(ip6_forwarding)
-#define V_ip6_gif_hlim VNET(ip6_gif_hlim)
-#define V_ip6_use_deprecated VNET(ip6_use_deprecated)
-#define V_ip6_rr_prune VNET(ip6_rr_prune)
-#define V_ip6_mcast_pmtu VNET(ip6_mcast_pmtu)
-#define V_ip6_v6only VNET(ip6_v6only)
#define V_ip6_mrouter VNET(ip6_mrouter)
#define V_ip6_sendredirects VNET(ip6_sendredirects)
#define V_ip6_maxfragpackets VNET(ip6_maxfragpackets)
@@ -349,17 +332,29 @@ VNET_DECLARE(int, ip6_use_defzone); /* Whether to use the default scope
#define V_ip6_log_time VNET(ip6_log_time)
#define V_ip6_hdrnestlimit VNET(ip6_hdrnestlimit)
#define V_ip6_dad_count VNET(ip6_dad_count)
+
+VNET_DECLARE(int, ip6_auto_flowlabel);
+VNET_DECLARE(int, ip6_auto_linklocal);
#define V_ip6_auto_flowlabel VNET(ip6_auto_flowlabel)
#define V_ip6_auto_linklocal VNET(ip6_auto_linklocal)
+
+VNET_DECLARE(int, ip6_use_tempaddr); /* Whether to use temporary addresses */
+VNET_DECLARE(int, ip6_prefer_tempaddr); /* Whether to prefer temporary
+ * addresses in the source address
+ * selection */
#define V_ip6_use_tempaddr VNET(ip6_use_tempaddr)
#define V_ip6_prefer_tempaddr VNET(ip6_prefer_tempaddr)
-#ifdef IPSTEALTH
-#define V_ip6stealth VNET(ip6stealth)
-#endif
+
+VNET_DECLARE(int, ip6_use_defzone); /* Whether to use the default scope
+ * zone when unspecified */
#define V_ip6_use_defzone VNET(ip6_use_defzone)
VNET_DECLARE (struct pfil_head, inet6_pfil_hook); /* packet filter hooks */
#define V_inet6_pfil_hook VNET(inet6_pfil_hook)
+#ifdef IPSTEALTH
+VNET_DECLARE(int, ip6stealth);
+#define V_ip6stealth VNET(ip6stealth)
+#endif
extern struct pr_usrreqs rip6_usrreqs;
struct sockopt;
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index a0ef204..7a54226 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -82,21 +82,31 @@ __FBSDID("$FreeBSD$");
#define SIN6(s) ((struct sockaddr_in6 *)s)
-VNET_DEFINE(int, nd6_prune);
-VNET_DEFINE(int, nd6_delay);
-VNET_DEFINE(int, nd6_umaxtries);
-VNET_DEFINE(int, nd6_mmaxtries);
-VNET_DEFINE(int, nd6_useloopback);
-VNET_DEFINE(int, nd6_gctimer);
+/* timer values */
+VNET_DEFINE(int, nd6_prune) = 1; /* walk list every 1 seconds */
+VNET_DEFINE(int, nd6_delay) = 5; /* delay first probe time 5 second */
+VNET_DEFINE(int, nd6_umaxtries) = 3; /* maximum unicast query */
+VNET_DEFINE(int, nd6_mmaxtries) = 3; /* maximum multicast query */
+VNET_DEFINE(int, nd6_useloopback) = 1; /* use loopback interface for
+ * local traffic */
+VNET_DEFINE(int, nd6_gctimer) = (60 * 60 * 24); /* 1 day: garbage
+ * collection timer */
/* preventing too many loops in ND option parsing */
-static VNET_DEFINE(int, nd6_maxndopt);
-VNET_DEFINE(int, nd6_maxnudhint);
-static VNET_DEFINE(int, nd6_maxqueuelen);
+static VNET_DEFINE(int, nd6_maxndopt) = 10; /* max # of ND options allowed */
+
+VNET_DEFINE(int, nd6_maxnudhint) = 0; /* max # of subsequent upper
+ * layer hints */
+static VNET_DEFINE(int, nd6_maxqueuelen) = 1; /* max pkts cached in unresolved
+ * ND entries */
#define V_nd6_maxndopt VNET(nd6_maxndopt)
#define V_nd6_maxqueuelen VNET(nd6_maxqueuelen)
-VNET_DEFINE(int, nd6_debug);
+#ifdef ND6_DEBUG
+VNET_DEFINE(int, nd6_debug) = 1;
+#else
+VNET_DEFINE(int, nd6_debug) = 0;
+#endif
/* for debugging? */
#if 0
@@ -106,7 +116,7 @@ static int nd6_inuse, nd6_allocated;
VNET_DEFINE(struct nd_drhead, nd_defrouter);
VNET_DEFINE(struct nd_prhead, nd_prefix);
-VNET_DEFINE(int, nd6_recalc_reachtm_interval);
+VNET_DEFINE(int, nd6_recalc_reachtm_interval) = ND6_RECALC_REACHTM_INTERVAL;
#define V_nd6_recalc_reachtm_interval VNET(nd6_recalc_reachtm_interval)
static struct sockaddr_in6 all1_sa;
@@ -125,56 +135,13 @@ static VNET_DEFINE(struct callout, nd6_slowtimo_ch);
VNET_DEFINE(struct callout, nd6_timer_ch);
-VNET_DECLARE(int, dad_ignore_ns);
-VNET_DECLARE(int, dad_maxtry);
-#define V_dad_ignore_ns VNET(dad_ignore_ns)
-#define V_dad_maxtry VNET(dad_maxtry)
-
void
nd6_init(void)
{
int i;
- V_nd6_prune = 1; /* walk list every 1 seconds */
- V_nd6_delay = 5; /* delay first probe time 5 second */
- V_nd6_umaxtries = 3; /* maximum unicast query */
- V_nd6_mmaxtries = 3; /* maximum multicast query */
- V_nd6_useloopback = 1; /* use loopback interface for local traffic */
- V_nd6_gctimer = (60 * 60 * 24); /* 1 day: garbage collection timer */
-
- /* preventing too many loops in ND option parsing */
- V_nd6_maxndopt = 10; /* max # of ND options allowed */
-
- V_nd6_maxnudhint = 0; /* max # of subsequent upper layer hints */
- V_nd6_maxqueuelen = 1; /* max pkts cached in unresolved ND entries */
-
-#ifdef ND6_DEBUG
- V_nd6_debug = 1;
-#else
- V_nd6_debug = 0;
-#endif
-
- V_nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL;
-
- V_dad_ignore_ns = 0; /* ignore NS in DAD - specwise incorrect*/
- V_dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */
-
- /*
- * XXX just to get this to compile KMM
- */
-#ifdef notyet
- V_llinfo_nd6.ln_next = &V_llinfo_nd6;
- V_llinfo_nd6.ln_prev = &V_llinfo_nd6;
-#endif
LIST_INIT(&V_nd_prefix);
- V_ip6_use_tempaddr = 0;
- V_ip6_temp_preferred_lifetime = DEF_TEMP_PREFERRED_LIFETIME;
- V_ip6_temp_valid_lifetime = DEF_TEMP_VALID_LIFETIME;
- V_ip6_temp_regen_advance = TEMPADDR_REGEN_ADVANCE;
-
- V_ip6_desync_factor = 0;
-
all1_sa.sin6_family = AF_INET6;
all1_sa.sin6_len = sizeof(struct sockaddr_in6);
for (i = 0; i < sizeof(all1_sa.sin6_addr); i++)
@@ -182,13 +149,13 @@ nd6_init(void)
/* initialization of the default router list */
TAILQ_INIT(&V_nd_defrouter);
+
/* start timer */
callout_init(&V_nd6_slowtimo_ch, 0);
callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
nd6_slowtimo, curvnet);
}
-
#ifdef VIMAGE
void
nd6_destroy()
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index ff8faa2..abcfcb7 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -330,8 +330,6 @@ VNET_DECLARE(struct nd_drhead, nd_defrouter);
VNET_DECLARE(struct nd_prhead, nd_prefix);
VNET_DECLARE(int, nd6_debug);
VNET_DECLARE(int, nd6_onlink_ns_rfc4861);
-VNET_DECLARE(struct callout, nd6_timer_ch);
-
#define V_nd6_prune VNET(nd6_prune)
#define V_nd6_delay VNET(nd6_delay)
#define V_nd6_umaxtries VNET(nd6_umaxtries)
@@ -343,6 +341,10 @@ VNET_DECLARE(struct callout, nd6_timer_ch);
#define V_nd_prefix VNET(nd_prefix)
#define V_nd6_debug VNET(nd6_debug)
#define V_nd6_onlink_ns_rfc4861 VNET(nd6_onlink_ns_rfc4861)
+
+#define nd6log(x) do { if (V_nd6_debug) log x; } while (/*CONSTCOND*/ 0)
+
+VNET_DECLARE(struct callout, nd6_timer_ch);
#define V_nd6_timer_ch VNET(nd6_timer_ch)
/* nd6_rtr.c */
@@ -351,15 +353,12 @@ VNET_DECLARE(int, ip6_desync_factor); /* seconds */
VNET_DECLARE(u_int32_t, ip6_temp_preferred_lifetime); /* seconds */
VNET_DECLARE(u_int32_t, ip6_temp_valid_lifetime); /* seconds */
VNET_DECLARE(int, ip6_temp_regen_advance); /* seconds */
-
#define V_nd6_defifindex VNET(nd6_defifindex)
#define V_ip6_desync_factor VNET(ip6_desync_factor)
#define V_ip6_temp_preferred_lifetime VNET(ip6_temp_preferred_lifetime)
#define V_ip6_temp_valid_lifetime VNET(ip6_temp_valid_lifetime)
#define V_ip6_temp_regen_advance VNET(ip6_temp_regen_advance)
-#define nd6log(x) do { if (V_nd6_debug) log x; } while (/*CONSTCOND*/ 0)
-
union nd_opts {
struct nd_opt_hdr *nd_opt_array[8]; /* max = target address list */
struct {
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index f9061d3..a50925b 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -89,9 +89,8 @@ static void nd6_dad_ns_output(struct dadq *, struct ifaddr *);
static void nd6_dad_ns_input(struct ifaddr *);
static void nd6_dad_na_input(struct ifaddr *);
-VNET_DEFINE(int, dad_ignore_ns);
-VNET_DEFINE(int, dad_maxtry);
-
+VNET_DEFINE(int, dad_ignore_ns) = 0; /* ignore NS in DAD - specwise incorrect*/
+VNET_DEFINE(int, dad_maxtry) = 15; /* max # of *tries* to transmit DAD packet */
#define V_dad_ignore_ns VNET(dad_ignore_ns)
#define V_dad_maxtry VNET(dad_maxtry)
@@ -1124,9 +1123,8 @@ struct dadq {
};
static VNET_DEFINE(TAILQ_HEAD(, dadq), dadq);
+VNET_DEFINE(int, dad_init) = 0;
#define V_dadq VNET(dadq)
-
-VNET_DEFINE(int, dad_init);
#define V_dad_init VNET(dad_init)
static struct dadq *
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index 74f4954..19ec989 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -90,14 +90,16 @@ VNET_DECLARE(int, nd6_recalc_reachtm_interval);
#define V_nd6_recalc_reachtm_interval VNET(nd6_recalc_reachtm_interval)
static VNET_DEFINE(struct ifnet *, nd6_defifp);
+VNET_DEFINE(int, nd6_defifindex);
#define V_nd6_defifp VNET(nd6_defifp)
-VNET_DEFINE(int, nd6_defifindex);
-VNET_DEFINE(int, ip6_use_tempaddr);
+VNET_DEFINE(int, ip6_use_tempaddr) = 0;
+
VNET_DEFINE(int, ip6_desync_factor);
-VNET_DEFINE(u_int32_t, ip6_temp_preferred_lifetime);
-VNET_DEFINE(u_int32_t, ip6_temp_valid_lifetime);
-VNET_DEFINE(int, ip6_temp_regen_advance);
+VNET_DEFINE(u_int32_t, ip6_temp_preferred_lifetime) = DEF_TEMP_PREFERRED_LIFETIME;
+VNET_DEFINE(u_int32_t, ip6_temp_valid_lifetime) = DEF_TEMP_VALID_LIFETIME;
+
+VNET_DEFINE(int, ip6_temp_regen_advance) = TEMPADDR_REGEN_ADVANCE;
/* RTPREF_MEDIUM has to be 0! */
#define RTPREF_HIGH 1
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index 9f1236a..939aa6a 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -119,11 +119,11 @@ VNET_DECLARE(struct inpcbinfo, ripcbinfo);
#define V_ripcb VNET(ripcb)
#define V_ripcbinfo VNET(ripcbinfo)
-VNET_DEFINE(struct rip6stat, rip6stat);
-
extern u_long rip_sendspace;
extern u_long rip_recvspace;
+VNET_DEFINE(struct rip6stat, rip6stat);
+
/*
* Hooks for multicast routing. They all default to NULL, so leave them not
* initialized and rely on BSS being set to 0.
@@ -465,7 +465,7 @@ rip6_output(m, va_alist)
&oifp, &in6a);
if (error)
goto bad;
- error = prison_get_ip6(in6p->inp_cred, &in6a);
+ error = prison_check_ip6(in6p->inp_cred, &in6a);
if (error != 0)
goto bad;
ip6->ip6_src = in6a;
diff --git a/sys/netinet6/scope6.c b/sys/netinet6/scope6.c
index cced5e30..8189d87 100644
--- a/sys/netinet6/scope6.c
+++ b/sys/netinet6/scope6.c
@@ -50,6 +50,11 @@ __FBSDID("$FreeBSD$");
#include <netinet6/ip6_var.h>
#include <netinet6/scope6_var.h>
+#ifdef ENABLE_DEFAULT_SCOPE
+VNET_DEFINE(int, ip6_use_defzone) = 1;
+#else
+VNET_DEFINE(int, ip6_use_defzone) = 0;
+#endif
/*
* The scope6_lock protects the global sid default stored in
@@ -62,8 +67,6 @@ static struct mtx scope6_lock;
#define SCOPE6_LOCK_ASSERT() mtx_assert(&scope6_lock, MA_OWNED)
static VNET_DEFINE(struct scope6_id, sid_default);
-VNET_DEFINE(int, ip6_use_defzone);
-
#define V_sid_default VNET(sid_default)
#define SID(ifp) \
@@ -73,11 +76,6 @@ void
scope6_init(void)
{
-#ifdef ENABLE_DEFAULT_SCOPE
- V_ip6_use_defzone = 1;
-#else
- V_ip6_use_defzone = 0;
-#endif
bzero(&V_sid_default, sizeof(V_sid_default));
if (!IS_DEFAULT_VNET(curvnet))
diff --git a/sys/netipsec/ah_var.h b/sys/netipsec/ah_var.h
index b031a98..6145dba 100644
--- a/sys/netipsec/ah_var.h
+++ b/sys/netipsec/ah_var.h
@@ -72,10 +72,11 @@ struct ahstat {
#ifdef _KERNEL
VNET_DECLARE(int, ah_enable);
-#define V_ah_enable VNET(ah_enable)
VNET_DECLARE(int, ah_cleartos);
-#define V_ah_cleartos VNET(ah_cleartos)
VNET_DECLARE(struct ahstat, ahstat);
+
+#define V_ah_enable VNET(ah_enable)
+#define V_ah_cleartos VNET(ah_cleartos)
#define V_ahstat VNET(ahstat)
#endif /* _KERNEL */
#endif /*_NETIPSEC_AH_VAR_H_*/
diff --git a/sys/netipsec/esp_var.h b/sys/netipsec/esp_var.h
index dc1aad4..477dcbf 100644
--- a/sys/netipsec/esp_var.h
+++ b/sys/netipsec/esp_var.h
@@ -73,8 +73,9 @@ struct espstat {
#ifdef _KERNEL
VNET_DECLARE(int, esp_enable);
-#define V_esp_enable VNET(esp_enable)
VNET_DECLARE(struct espstat, espstat);
+
+#define V_esp_enable VNET(esp_enable)
#define V_espstat VNET(espstat)
#endif /* _KERNEL */
#endif /*_NETIPSEC_ESP_VAR_H_*/
diff --git a/sys/netipsec/ipcomp_var.h b/sys/netipsec/ipcomp_var.h
index 78f1848..c99a3be 100644
--- a/sys/netipsec/ipcomp_var.h
+++ b/sys/netipsec/ipcomp_var.h
@@ -66,8 +66,9 @@ struct ipcompstat {
#ifdef _KERNEL
VNET_DECLARE(int, ipcomp_enable);
-#define V_ipcomp_enable VNET(ipcomp_enable)
VNET_DECLARE(struct ipcompstat, ipcompstat);
+
+#define V_ipcomp_enable VNET(ipcomp_enable)
#define V_ipcompstat VNET(ipcompstat)
#endif /* _KERNEL */
#endif /*_NETIPSEC_IPCOMP_VAR_H_*/
diff --git a/sys/netipsec/ipip_var.h b/sys/netipsec/ipip_var.h
index a6e33e8..3c8c397 100644
--- a/sys/netipsec/ipip_var.h
+++ b/sys/netipsec/ipip_var.h
@@ -60,8 +60,9 @@ struct ipipstat
#ifdef _KERNEL
VNET_DECLARE(int, ipip_allow);
-#define V_ipip_allow VNET(ipip_allow)
VNET_DECLARE(struct ipipstat, ipipstat);
+
+#define V_ipip_allow VNET(ipip_allow)
#define V_ipipstat VNET(ipipstat)
#endif /* _KERNEL */
#endif /* _NETINET_IPIP_H_ */
diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c
index 5ee4bbb..1f48dd6 100644
--- a/sys/netipsec/ipsec.c
+++ b/sys/netipsec/ipsec.c
@@ -102,6 +102,7 @@ VNET_DEFINE(int, ipsec_debug) = 1;
#else
VNET_DEFINE(int, ipsec_debug) = 0;
#endif
+
/* NB: name changed so netstat doesn't use it. */
VNET_DEFINE(struct ipsecstat, ipsec4stat);
VNET_DEFINE(int, ip4_ah_offsetmask) = 0; /* maybe IP_DF? */
diff --git a/sys/netipsec/ipsec.h b/sys/netipsec/ipsec.h
index 92539b9..090255a 100644
--- a/sys/netipsec/ipsec.h
+++ b/sys/netipsec/ipsec.h
@@ -334,39 +334,39 @@ struct ipsec_history {
VNET_DECLARE(int, ipsec_debug);
#define V_ipsec_debug VNET(ipsec_debug)
+
+#ifdef REGRESSION
+VNET_DECLARE(int, ipsec_replay);
+VNET_DECLARE(int, ipsec_integrity);
+
+#define V_ipsec_replay VNET(ipsec_replay)
+#define V_ipsec_integrity VNET(ipsec_integrity)
+#endif
+
VNET_DECLARE(struct ipsecstat, ipsec4stat);
-#define V_ipsec4stat VNET(ipsec4stat)
+VNET_DECLARE(struct secpolicy, ip4_def_policy);
+VNET_DECLARE(int, ip4_esp_trans_deflev);
+VNET_DECLARE(int, ip4_esp_net_deflev);
+VNET_DECLARE(int, ip4_ah_trans_deflev);
+VNET_DECLARE(int, ip4_ah_net_deflev);
VNET_DECLARE(int, ip4_ah_offsetmask);
-#define V_ip4_ah_offsetmask VNET(ip4_ah_offsetmask)
VNET_DECLARE(int, ip4_ipsec_dfbit);
-#define V_ip4_ipsec_dfbit VNET(ip4_ipsec_dfbit)
-VNET_DECLARE(int, ip4_esp_trans_deflev);
+VNET_DECLARE(int, ip4_ipsec_ecn);
+VNET_DECLARE(int, ip4_esp_randpad);
+VNET_DECLARE(int, crypto_support);
+
+#define V_ipsec4stat VNET(ipsec4stat)
+#define V_ip4_def_policy VNET(ip4_def_policy)
#define V_ip4_esp_trans_deflev VNET(ip4_esp_trans_deflev)
-VNET_DECLARE(int, ip4_esp_net_deflev);
#define V_ip4_esp_net_deflev VNET(ip4_esp_net_deflev)
-VNET_DECLARE(int, ip4_ah_trans_deflev);
#define V_ip4_ah_trans_deflev VNET(ip4_ah_trans_deflev)
-VNET_DECLARE(int, ip4_ah_net_deflev);
#define V_ip4_ah_net_deflev VNET(ip4_ah_net_deflev)
-VNET_DECLARE(struct secpolicy, ip4_def_policy);
-#define V_ip4_def_policy VNET(ip4_def_policy)
-VNET_DECLARE(int, ip4_ipsec_ecn);
+#define V_ip4_ah_offsetmask VNET(ip4_ah_offsetmask)
+#define V_ip4_ipsec_dfbit VNET(ip4_ipsec_dfbit)
#define V_ip4_ipsec_ecn VNET(ip4_ipsec_ecn)
-VNET_DECLARE(int, ip4_esp_randpad);
#define V_ip4_esp_randpad VNET(ip4_esp_randpad)
-
-VNET_DECLARE(int, crypto_support);
#define V_crypto_support VNET(crypto_support)
-extern int ip4_ah_cleartos;
-
-#ifdef REGRESSION
-VNET_DECLARE(int, ipsec_replay);
-#define V_ipsec_replay VNET(ipsec_replay)
-VNET_DECLARE(int, ipsec_integrity);
-#define V_ipsec_integrity VNET(ipsec_integrity)
-#endif
-
#define ipseclog(x) do { if (V_ipsec_debug) log x; } while (0)
/* for openbsd compatibility */
#define DPRINTF(x) do { if (V_ipsec_debug) printf x; } while (0)
diff --git a/sys/netipsec/ipsec6.h b/sys/netipsec/ipsec6.h
index 030113f..c004220 100644
--- a/sys/netipsec/ipsec6.h
+++ b/sys/netipsec/ipsec6.h
@@ -42,16 +42,17 @@
#ifdef _KERNEL
VNET_DECLARE(struct ipsecstat, ipsec6stat);
-#define V_ipsec6stat VNET(ipsec6stat)
VNET_DECLARE(int, ip6_esp_trans_deflev);
-#define V_ip6_esp_trans_deflev VNET(ip6_esp_trans_deflev)
VNET_DECLARE(int, ip6_esp_net_deflev);
-#define V_ip6_esp_net_deflev VNET(ip6_esp_net_deflev)
VNET_DECLARE(int, ip6_ah_trans_deflev);
-#define V_ip6_ah_trans_deflev VNET(ip6_ah_trans_deflev)
VNET_DECLARE(int, ip6_ah_net_deflev);
-#define V_ip6_ah_net_deflev VNET(ip6_ah_net_deflev)
VNET_DECLARE(int, ip6_ipsec_ecn);
+
+#define V_ipsec6stat VNET(ipsec6stat)
+#define V_ip6_esp_trans_deflev VNET(ip6_esp_trans_deflev)
+#define V_ip6_esp_net_deflev VNET(ip6_esp_net_deflev)
+#define V_ip6_ah_trans_deflev VNET(ip6_ah_trans_deflev)
+#define V_ip6_ah_net_deflev VNET(ip6_ah_net_deflev)
#define V_ip6_ipsec_ecn VNET(ip6_ipsec_ecn)
struct inpcb;
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index 2b17fb0..d00489d 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -114,27 +114,27 @@
VNET_DEFINE(u_int32_t, key_debug_level) = 0;
static VNET_DEFINE(u_int, key_spi_trycnt) = 1000;
-#define V_key_spi_trycnt VNET(key_spi_trycnt)
static VNET_DEFINE(u_int32_t, key_spi_minval) = 0x100;
-#define V_key_spi_minval VNET(key_spi_minval)
static VNET_DEFINE(u_int32_t, key_spi_maxval) = 0x0fffffff; /* XXX */
-#define V_key_spi_maxval VNET(key_spi_maxval)
static VNET_DEFINE(u_int32_t, policy_id) = 0;
-#define V_policy_id VNET(policy_id)
/*interval to initialize randseed,1(m)*/
static VNET_DEFINE(u_int, key_int_random) = 60;
-#define V_key_int_random VNET(key_int_random)
/* interval to expire acquiring, 30(s)*/
static VNET_DEFINE(u_int, key_larval_lifetime) = 30;
-#define V_key_larval_lifetime VNET(key_larval_lifetime)
/* counter for blocking SADB_ACQUIRE.*/
static VNET_DEFINE(int, key_blockacq_count) = 10;
-#define V_key_blockacq_count VNET(key_blockacq_count)
/* lifetime for blocking SADB_ACQUIRE.*/
static VNET_DEFINE(int, key_blockacq_lifetime) = 20;
-#define V_key_blockacq_lifetime VNET(key_blockacq_lifetime)
/* preferred old sa rather than new sa.*/
static VNET_DEFINE(int, key_preferred_oldsa) = 1;
+#define V_key_spi_trycnt VNET(key_spi_trycnt)
+#define V_key_spi_minval VNET(key_spi_minval)
+#define V_key_spi_maxval VNET(key_spi_maxval)
+#define V_policy_id VNET(policy_id)
+#define V_key_int_random VNET(key_int_random)
+#define V_key_larval_lifetime VNET(key_larval_lifetime)
+#define V_key_blockacq_count VNET(key_blockacq_count)
+#define V_key_blockacq_lifetime VNET(key_blockacq_lifetime)
#define V_key_preferred_oldsa VNET(key_preferred_oldsa)
static VNET_DEFINE(u_int32_t, acq_seq) = 0;
@@ -270,10 +270,11 @@ static const int maxsize[] = {
};
static VNET_DEFINE(int, ipsec_esp_keymin) = 256;
-#define V_ipsec_esp_keymin VNET(ipsec_esp_keymin)
static VNET_DEFINE(int, ipsec_esp_auth) = 0;
-#define V_ipsec_esp_auth VNET(ipsec_esp_auth)
static VNET_DEFINE(int, ipsec_ah_keymin) = 128;
+
+#define V_ipsec_esp_keymin VNET(ipsec_esp_keymin)
+#define V_ipsec_esp_auth VNET(ipsec_esp_auth)
#define V_ipsec_ah_keymin VNET(ipsec_ah_keymin)
#ifdef SYSCTL_DECL
@@ -5155,12 +5156,6 @@ key_update(so, m, mhp)
return key_senderror(so, m, error);
}
- /* check SA values to be mature. */
- if ((mhp->msg->sadb_msg_errno = key_mature(sav)) != 0) {
- KEY_FREESAV(&sav);
- return key_senderror(so, m, 0);
- }
-
#ifdef IPSEC_NAT_T
/*
* Handle more NAT-T info if present,
@@ -5187,6 +5182,12 @@ key_update(so, m, mhp)
#endif
#endif
+ /* check SA values to be mature. */
+ if ((mhp->msg->sadb_msg_errno = key_mature(sav)) != 0) {
+ KEY_FREESAV(&sav);
+ return key_senderror(so, m, 0);
+ }
+
{
struct mbuf *n;
@@ -5421,12 +5422,6 @@ key_add(so, m, mhp)
return key_senderror(so, m, error);
}
- /* check SA values to be mature. */
- if ((error = key_mature(newsav)) != 0) {
- KEY_FREESAV(&newsav);
- return key_senderror(so, m, error);
- }
-
#ifdef IPSEC_NAT_T
/*
* Handle more NAT-T info if present,
@@ -5446,6 +5441,12 @@ key_add(so, m, mhp)
#endif
#endif
+ /* check SA values to be mature. */
+ if ((error = key_mature(newsav)) != 0) {
+ KEY_FREESAV(&newsav);
+ return key_senderror(so, m, error);
+ }
+
/*
* don't call key_freesav() here, as we would like to keep the SA
* in the database on success.
diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c
index dbacd77..6186b59 100644
--- a/sys/netipsec/xform_esp.c
+++ b/sys/netipsec/xform_esp.c
@@ -85,8 +85,7 @@ SYSCTL_VNET_INT(_net_inet_esp, OID_AUTO,
SYSCTL_VNET_STRUCT(_net_inet_esp, IPSECCTL_STATS,
stats, CTLFLAG_RD, &VNET_NAME(espstat), espstat, "");
-/* max iv length over all algorithms */
-static VNET_DEFINE(int, esp_max_ivlen) = 0;
+static VNET_DEFINE(int, esp_max_ivlen); /* max iv length over all algorithms */
#define V_esp_max_ivlen VNET(esp_max_ivlen)
static int esp_input_cb(struct cryptop *op);
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index cec0220..c93d677 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -45,8 +45,6 @@ __FBSDID("$FreeBSD$");
#include <sys/mbuf.h>
#include <sys/mount.h>
#include <sys/proc.h>
-#include <sys/resourcevar.h>
-#include <sys/signalvar.h>
#include <sys/vmmeter.h>
#include <sys/vnode.h>
@@ -131,12 +129,15 @@ nfs_getpages(struct vop_getpages_args *ap)
*/
VM_OBJECT_LOCK(object);
if (pages[ap->a_reqpage]->valid != 0) {
- vm_page_lock_queues();
for (i = 0; i < npages; ++i) {
- if (i != ap->a_reqpage)
+ if (i != ap->a_reqpage) {
+ vm_page_lock(pages[i]);
+ vm_page_lock_queues();
vm_page_free(pages[i]);
+ vm_page_unlock_queues();
+ vm_page_unlock(pages[i]);
+ }
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
return (0);
}
@@ -171,12 +172,15 @@ nfs_getpages(struct vop_getpages_args *ap)
if (error && (uio.uio_resid == count)) {
nfs_printf("nfs_getpages: error %d\n", error);
VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
for (i = 0; i < npages; ++i) {
- if (i != ap->a_reqpage)
+ if (i != ap->a_reqpage) {
+ vm_page_lock(pages[i]);
+ vm_page_lock_queues();
vm_page_free(pages[i]);
+ vm_page_unlock_queues();
+ vm_page_unlock(pages[i]);
+ }
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
return (VM_PAGER_ERROR);
}
@@ -189,12 +193,14 @@ nfs_getpages(struct vop_getpages_args *ap)
size = count - uio.uio_resid;
VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
vm_page_t m;
nextoff = toff + PAGE_SIZE;
m = pages[i];
+ vm_page_lock(m);
+ vm_page_lock_queues();
+
if (nextoff <= size) {
/*
* Read operation filled an entire page
@@ -241,8 +247,10 @@ nfs_getpages(struct vop_getpages_args *ap)
vm_page_free(m);
}
}
+
+ vm_page_unlock_queues();
+ vm_page_unlock(m);
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
return (0);
}
@@ -869,7 +877,6 @@ nfs_write(struct vop_write_args *ap)
daddr_t lbn;
int bcount;
int n, on, error = 0;
- struct proc *p = td?td->td_proc:NULL;
#ifdef DIAGNOSTIC
if (uio->uio_rw != UIO_WRITE)
@@ -950,16 +957,8 @@ flush_and_restart:
* Maybe this should be above the vnode op call, but so long as
* file servers have no limits, i don't think it matters
*/
- if (p != NULL) {
- PROC_LOCK(p);
- if (uio->uio_offset + uio->uio_resid >
- lim_cur(p, RLIMIT_FSIZE)) {
- psignal(p, SIGXFSZ);
- PROC_UNLOCK(p);
- return (EFBIG);
- }
- PROC_UNLOCK(p);
- }
+ if (vn_rlimit_fsize(vp, uio, td))
+ return (EFBIG);
biosize = vp->v_mount->mnt_stat.f_iosize;
/*
diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
index f470b5e..e0482e2 100644
--- a/sys/pc98/pc98/machdep.c
+++ b/sys/pc98/pc98/machdep.c
@@ -874,7 +874,8 @@ freebsd4_sigreturn(td, uap)
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
- printf("freebsd4_sigreturn: eflags = 0x%x\n", eflags);
+ uprintf("pid %d (%s): freebsd4_sigreturn eflags = 0x%x\n",
+ td->td_proc->p_pid, td->td_name, eflags);
return (EINVAL);
}
@@ -885,7 +886,8 @@ freebsd4_sigreturn(td, uap)
*/
cs = ucp->uc_mcontext.mc_cs;
if (!CS_SECURE(cs)) {
- printf("freebsd4_sigreturn: cs = 0x%x\n", cs);
+ uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n",
+ td->td_proc->p_pid, td->td_name, cs);
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_OBJERR;
@@ -986,7 +988,8 @@ sigreturn(td, uap)
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
- printf("sigreturn: eflags = 0x%x\n", eflags);
+ uprintf("pid %d (%s): sigreturn eflags = 0x%x\n",
+ td->td_proc->p_pid, td->td_name, eflags);
return (EINVAL);
}
@@ -997,7 +1000,8 @@ sigreturn(td, uap)
*/
cs = ucp->uc_mcontext.mc_cs;
if (!CS_SECURE(cs)) {
- printf("sigreturn: cs = 0x%x\n", cs);
+ uprintf("pid %d (%s): sigreturn cs = 0x%x\n",
+ td->td_proc->p_pid, td->td_name, cs);
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_OBJERR;
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c
index 8b22516..cd7609d 100644
--- a/sys/pci/if_rl.c
+++ b/sys/pci/if_rl.c
@@ -942,8 +942,8 @@ rl_attach(device_t dev)
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
#endif
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
/*
diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
index 24e7b4e..95936ed 100644
--- a/sys/powerpc/aim/mmu_oea.c
+++ b/sys/powerpc/aim/mmu_oea.c
@@ -1241,18 +1241,22 @@ moea_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot)
{
struct pvo_entry *pvo;
vm_page_t m;
-
+ vm_paddr_t pa;
+
m = NULL;
- vm_page_lock_queues();
+ pa = 0;
PMAP_LOCK(pmap);
+retry:
pvo = moea_pvo_find_va(pmap, va & ~ADDR_POFF, NULL);
if (pvo != NULL && (pvo->pvo_pte.pte.pte_hi & PTE_VALID) &&
((pvo->pvo_pte.pte.pte_lo & PTE_PP) == PTE_RW ||
(prot & VM_PROT_WRITE) == 0)) {
+ if (vm_page_pa_tryrelock(pmap, pvo->pvo_pte.pte.pte_lo & PTE_RPGN, &pa))
+ goto retry;
m = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte.pte_lo & PTE_RPGN);
vm_page_hold(m);
}
- vm_page_unlock_queues();
+ PA_UNLOCK_COND(pa);
PMAP_UNLOCK(pmap);
return (m);
}
diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
index 2571587..0483b41 100644
--- a/sys/powerpc/aim/mmu_oea64.c
+++ b/sys/powerpc/aim/mmu_oea64.c
@@ -1374,18 +1374,23 @@ moea64_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot)
{
struct pvo_entry *pvo;
vm_page_t m;
+ vm_paddr_t pa;
m = NULL;
- vm_page_lock_queues();
+ pa = 0;
PMAP_LOCK(pmap);
+retry:
pvo = moea64_pvo_find_va(pmap, va & ~ADDR_POFF, NULL);
if (pvo != NULL && (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) &&
((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) == LPTE_RW ||
(prot & VM_PROT_WRITE) == 0)) {
+ if (vm_page_pa_tryrelock(pmap,
+ pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN, &pa))
+ goto retry;
m = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
vm_page_hold(m);
}
- vm_page_unlock_queues();
+ PA_UNLOCK_COND(pa);
PMAP_UNLOCK(pmap);
return (m);
}
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index 549eaaa..78e9afb 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -1915,16 +1915,11 @@ mmu_booke_protect(mmu_t mmu, pmap_t pmap, vm_offset_t sva, vm_offset_t eva,
tlb_miss_lock();
/* Handle modified pages. */
- if (PTE_ISMODIFIED(pte))
+ if (PTE_ISMODIFIED(pte) && PTE_ISMANAGED(pte))
vm_page_dirty(m);
- /* Referenced pages. */
- if (PTE_ISREFERENCED(pte))
- vm_page_flag_set(m, PG_REFERENCED);
-
tlb0_flush_entry(va);
- pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED |
- PTE_REFERENCED);
+ pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED);
tlb_miss_unlock();
mtx_unlock_spin(&tlbivax_mutex);
@@ -1962,13 +1957,8 @@ mmu_booke_remove_write(mmu_t mmu, vm_page_t m)
if (PTE_ISMODIFIED(pte))
vm_page_dirty(m);
- /* Referenced pages. */
- if (PTE_ISREFERENCED(pte))
- vm_page_flag_set(m, PG_REFERENCED);
-
/* Flush mapping from TLB0. */
- pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED |
- PTE_REFERENCED);
+ pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED);
tlb_miss_unlock();
mtx_unlock_spin(&tlbivax_mutex);
@@ -2034,11 +2024,12 @@ mmu_booke_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va,
pte_t *pte;
vm_page_t m;
uint32_t pte_wbit;
-
+ vm_paddr_t pa;
+
m = NULL;
- vm_page_lock_queues();
+ pa = 0;
PMAP_LOCK(pmap);
-
+retry:
pte = pte_find(mmu, pmap, va);
if ((pte != NULL) && PTE_ISVALID(pte)) {
if (pmap == kernel_pmap)
@@ -2047,12 +2038,14 @@ mmu_booke_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va,
pte_wbit = PTE_UW;
if ((pte->flags & pte_wbit) || ((prot & VM_PROT_WRITE) == 0)) {
+ if (vm_page_pa_tryrelock(pmap, PTE_PA(pte), &pa))
+ goto retry;
m = PHYS_TO_VM_PAGE(PTE_PA(pte));
vm_page_hold(m);
}
}
- vm_page_unlock_queues();
+ PA_UNLOCK_COND(pa);
PMAP_UNLOCK(pmap);
return (m);
}
diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h
index a23052e..a49bd6c 100644
--- a/sys/powerpc/include/pmap.h
+++ b/sys/powerpc/include/pmap.h
@@ -88,6 +88,8 @@ struct pmap {
struct mtx pm_mtx;
u_int pm_sr[16];
u_int pm_active;
+ uint32_t pm_gen_count; /* generation count (pmap lock dropped) */
+ u_int pm_retries;
u_int pm_context;
struct pmap *pmap_phys;
diff --git a/sys/powerpc/include/proc.h b/sys/powerpc/include/proc.h
index cbe6da9..d51116b 100644
--- a/sys/powerpc/include/proc.h
+++ b/sys/powerpc/include/proc.h
@@ -46,6 +46,6 @@ struct mdthread {
struct mdproc {
};
-#define KINFO_PROC_SIZE 768
+#define KINFO_PROC_SIZE 768
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c
index faa4583..b4713cc 100644
--- a/sys/security/audit/audit_bsm.c
+++ b/sys/security/audit/audit_bsm.c
@@ -740,6 +740,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
case AUE_LUTIMES:
case AUE_NFS_GETFH:
case AUE_LSTAT:
+ case AUE_LPATHCONF:
case AUE_PATHCONF:
case AUE_READLINK:
case AUE_REVOKE:
diff --git a/sys/sparc64/include/asi.h b/sys/sparc64/include/asi.h
index 90dc3f3..e5769c1 100644
--- a/sys/sparc64/include/asi.h
+++ b/sys/sparc64/include/asi.h
@@ -82,7 +82,10 @@
#define ASI_DCACHE_SNOOP_TAG 0x44 /* US-III Cu */
/* Named ASI_DCUCR on US-III, but is mostly identical except for added bits. */
-#define ASI_LSU_CTL_REG 0x45
+#define ASI_LSU_CTL_REG 0x45 /* US only */
+
+#define ASI_MCNTL 0x45 /* SPARC64 only */
+#define AA_MCNTL 0x08
#define ASI_DCACHE_DATA 0x46
#define ASI_DCACHE_TAG 0x47
@@ -167,6 +170,8 @@
#define ASI_ICACHE_PRE_DECODE 0x6e /* US-I, II */
#define ASI_ICACHE_PRE_NEXT_FIELD 0x6f /* US-I, II */
+#define ASI_FLUSH_L1I 0x67 /* SPARC64 only */
+
#define ASI_BLK_AUIP 0x70
#define ASI_BLK_AIUS 0x71
diff --git a/sys/sparc64/include/cache.h b/sys/sparc64/include/cache.h
index 9c4804b..29bff69 100644
--- a/sys/sparc64/include/cache.h
+++ b/sys/sparc64/include/cache.h
@@ -113,6 +113,10 @@ extern cache_flush_t *cache_flush;
extern dcache_page_inval_t *dcache_page_inval;
extern icache_page_inval_t *icache_page_inval;
+cache_flush_t zeus_cache_flush;
+dcache_page_inval_t zeus_dcache_page_inval;
+icache_page_inval_t zeus_icache_page_inval;
+
#endif /* KERNEL */
#endif /* !LOCORE */
diff --git a/sys/sparc64/include/mcntl.h b/sys/sparc64/include/mcntl.h
new file mode 100644
index 0000000..e9483c0
--- /dev/null
+++ b/sys/sparc64/include/mcntl.h
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2010 Marius Strobl <marius@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_MCNTL_H
+#define _MACHINE_MCNTL_H
+
+/*
+ * Definitions for the SPARC64 V, VI, VII and VIIIfx Memory Control Register
+ */
+#define MCNTL_JPS1_TSBP (1UL << 8)
+
+#define MCNTL_RMD_SHIFT 12
+#define MCNTL_RMD_BITS 2
+#define MCNTL_RMD_MASK \
+ (((1UL << MCNTL_RMD_BITS) - 1) << MCNTL_RMD_SHIFT)
+#define MCNTL_RMD_FULL (0UL << MCNTL_RMD_SHIFT)
+#define MCNTL_RMD_1024 (2UL << MCNTL_RMD_SHIFT)
+#define MCNTL_RMD_512 (3UL << MCNTL_RMD_SHIFT)
+
+#define MCNTL_FW_FDTLB (1UL << 14)
+#define MCNTL_FW_FITLB (1UL << 15)
+#define MCNTL_NC_CACHE (1UL << 16)
+
+/* The following bits are valid for the SPARC64 VI, VII and VIIIfx only. */
+#define MCNTL_MPG_SDTLB (1UL << 6)
+#define MCNTL_MPG_SITLB (1UL << 7)
+
+/* The following bits are valid for the SPARC64 VIIIfx only. */
+#define MCNTL_HPF_SHIFT 18
+#define MCNTL_HPF_BITS 2
+#define MCNTL_HPF_MASK \
+ (((1UL << MCNTL_HPF_BITS) - 1) << MCNTL_HPF_SHIFT)
+#define MCNTL_HPF_STRONG (0UL << MCNTL_HPF_SHIFT)
+#define MCNTL_HPF_NOT (1UL << MCNTL_HPF_SHIFT)
+#define MCNTL_HPF_WEAK (2UL << MCNTL_HPF_SHIFT)
+
+#endif /* _MACHINE_MCNTL_H */
diff --git a/sys/sparc64/include/pmap.h b/sys/sparc64/include/pmap.h
index 83c8190..388f751 100644
--- a/sys/sparc64/include/pmap.h
+++ b/sys/sparc64/include/pmap.h
@@ -62,6 +62,8 @@ struct pmap {
struct tte *pm_tsb;
vm_object_t pm_tsb_obj;
u_int pm_active;
+ uint32_t pm_gen_count; /* generation count (pmap lock dropped) */
+ u_int pm_retries;
u_int pm_context[MAXCPU];
struct pmap_statistics pm_stats;
};
diff --git a/sys/sparc64/include/proc.h b/sys/sparc64/include/proc.h
index 84eaed5..3c23663 100644
--- a/sys/sparc64/include/proc.h
+++ b/sys/sparc64/include/proc.h
@@ -51,6 +51,6 @@ struct mdproc {
void *md_sigtramp;
};
-#define KINFO_PROC_SIZE 1088
+#define KINFO_PROC_SIZE 1088
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/sparc64/sparc64/cache.c b/sys/sparc64/sparc64/cache.c
index 8cb8dee..a3c6119 100644
--- a/sys/sparc64/sparc64/cache.c
+++ b/sys/sparc64/sparc64/cache.c
@@ -141,7 +141,12 @@ cache_init(struct pcpu *pcpu)
if ((pcpu->pc_cache.dc_size &
~(1UL << (ffs(pcpu->pc_cache.dc_size) - 1))) != 0)
panic("cache_init: D$ size not a power of 2");
- if (((pcpu->pc_cache.dc_size / pcpu->pc_cache.dc_assoc) /
+ /*
+ * For CPUs which don't support unaliasing in hardware ensure that
+ * the data cache doesn't have too many virtual colors.
+ */
+ if (pcpu->pc_impl != CPU_IMPL_SPARC64V &&
+ ((pcpu->pc_cache.dc_size / pcpu->pc_cache.dc_assoc) /
PAGE_SIZE) != DCACHE_COLORS)
panic("cache_init: too many D$ colors");
set = pcpu->pc_cache.ec_size / pcpu->pc_cache.ec_assoc;
@@ -155,12 +160,21 @@ cache_init(struct pcpu *pcpu)
icache_page_inval = cheetah_icache_page_inval;
tlb_flush_nonlocked = cheetah_tlb_flush_nonlocked;
tlb_flush_user = cheetah_tlb_flush_user;
- } else {
+ } else if (pcpu->pc_impl == CPU_IMPL_SPARC64V) {
+ cache_enable = cheetah_cache_enable;
+ cache_flush = zeus_cache_flush;
+ dcache_page_inval = zeus_dcache_page_inval;
+ icache_page_inval = zeus_icache_page_inval;
+ tlb_flush_nonlocked = cheetah_tlb_flush_nonlocked;
+ tlb_flush_user = cheetah_tlb_flush_user;
+ } else if (pcpu->pc_impl >= CPU_IMPL_ULTRASPARCI &&
+ pcpu->pc_impl < CPU_IMPL_ULTRASPARCIII) {
cache_enable = spitfire_cache_enable;
cache_flush = spitfire_cache_flush;
dcache_page_inval = spitfire_dcache_page_inval;
icache_page_inval = spitfire_icache_page_inval;
tlb_flush_nonlocked = spitfire_tlb_flush_nonlocked;
tlb_flush_user = spitfire_tlb_flush_user;
- }
+ } else
+ panic("cache_init: unknown CPU");
}
diff --git a/sys/sparc64/sparc64/cheetah.c b/sys/sparc64/sparc64/cheetah.c
index 8366187..99d38c9 100644
--- a/sys/sparc64/sparc64/cheetah.c
+++ b/sys/sparc64/sparc64/cheetah.c
@@ -39,11 +39,13 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/asi.h>
#include <machine/cache.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/dcr.h>
#include <machine/lsu.h>
+#include <machine/mcntl.h>
#include <machine/smp.h>
#include <machine/tlb.h>
#include <machine/ver.h>
@@ -52,7 +54,8 @@ __FBSDID("$FreeBSD$");
#define CHEETAH_ICACHE_TAG_LOWER 0x30
/*
- * CPU-specific initialization
+ * CPU-specific initialization - this is used for both the Sun Cheetah and
+ * later as well as the Fujitsu Zeus and later CPUs.
*/
void
cheetah_init(u_int cpu_impl)
@@ -75,6 +78,14 @@ cheetah_init(u_int cpu_impl)
stxa(AA_IMMU_TSB_NEXT_REG, ASI_IMMU, 0);
membar(Sync);
+ if (cpu_impl == CPU_IMPL_SPARC64V) {
+ /* Ensure MCNTL_JPS1_TSBP is 0. */
+ val = ldxa(AA_MCNTL, ASI_MCNTL);
+ val &= ~MCNTL_JPS1_TSBP;
+ stxa(AA_MCNTL, ASI_MCNTL, val);
+ return;
+ }
+
/*
* Configure the first large dTLB to hold 4MB pages (e.g. for direct
* mappings) for all three contexts and ensure the second one is set
@@ -207,7 +218,7 @@ cheetah_dcache_page_inval(vm_paddr_t spa)
* consistency is maintained by hardware.
*/
void
-cheetah_icache_page_inval(vm_paddr_t pa)
+cheetah_icache_page_inval(vm_paddr_t pa __unused)
{
}
diff --git a/sys/sparc64/sparc64/identcpu.c b/sys/sparc64/sparc64/identcpu.c
index 0b73151..455aa67 100644
--- a/sys/sparc64/sparc64/identcpu.c
+++ b/sys/sparc64/sparc64/identcpu.c
@@ -41,7 +41,7 @@ cpu_identify(u_long vers, u_int freq, u_int id)
switch (VER_MANUF(vers)) {
case 0x04:
- manus = "HAL";
+ manus = "HAL/Fujitsu";
break;
case 0x13:
case 0x17:
@@ -57,6 +57,27 @@ cpu_identify(u_long vers, u_int freq, u_int id)
case CPU_IMPL_SPARC64:
impls = "SPARC64";
break;
+ case CPU_IMPL_SPARC64II:
+ impls = "SPARC64-II";
+ break;
+ case CPU_IMPL_SPARC64III:
+ impls = "SPARC64-III";
+ break;
+ case CPU_IMPL_SPARC64IV:
+ impls = "SPARC64-IV";
+ break;
+ case CPU_IMPL_SPARC64V:
+ impls = "SPARC64-V";
+ break;
+ case CPU_IMPL_SPARC64VI:
+ impls = "SPARC64-VI";
+ break;
+ case CPU_IMPL_SPARC64VII:
+ impls = "SPARC64-VII";
+ break;
+ case CPU_IMPL_SPARC64VIIIfx:
+ impls = "SPARC64-VIIIfx";
+ break;
case CPU_IMPL_ULTRASPARCI:
impls = "UltraSparc-I";
break;
@@ -67,7 +88,6 @@ cpu_identify(u_long vers, u_int freq, u_int id)
impls = "UltraSparc-IIi";
break;
case CPU_IMPL_ULTRASPARCIIe:
- /* V9 Manual says `UltraSparc-e'. I assume this is wrong. */
impls = "UltraSparc-IIe";
break;
case CPU_IMPL_ULTRASPARCIII:
diff --git a/sys/sparc64/sparc64/interrupt.S b/sys/sparc64/sparc64/interrupt.S
index 75a9727..b71a05d 100644
--- a/sys/sparc64/sparc64/interrupt.S
+++ b/sys/sparc64/sparc64/interrupt.S
@@ -83,8 +83,11 @@ ENTRY(intr_vector)
* The 2nd word points to code to execute and the 3rd is an argument
* to pass. Jump to it.
*/
- brnz,a,pt %g3, 1f
- nop
+ brnz,pt %g3, 1f
+ /*
+ * NB: Zeus CPUs set some undocumented bits in the first data word.
+ */
+ and %g3, IV_MAX - 1, %g3
jmpl %g4, %g0
nop
/* NOTREACHED */
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index c904060..eda2e01 100644
--- a/sys/sparc64/sparc64/machdep.c
+++ b/sys/sparc64/sparc64/machdep.c
@@ -276,6 +276,7 @@ cpu_cpuid_prop(u_int cpu_impl)
switch (cpu_impl) {
case CPU_IMPL_SPARC64:
+ case CPU_IMPL_SPARC64V:
case CPU_IMPL_ULTRASPARCI:
case CPU_IMPL_ULTRASPARCII:
case CPU_IMPL_ULTRASPARCIIi:
@@ -300,6 +301,7 @@ cpu_get_mid(u_int cpu_impl)
switch (cpu_impl) {
case CPU_IMPL_SPARC64:
+ case CPU_IMPL_SPARC64V:
case CPU_IMPL_ULTRASPARCI:
case CPU_IMPL_ULTRASPARCII:
case CPU_IMPL_ULTRASPARCIIi:
@@ -343,7 +345,8 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
/*
* Do CPU-specific initialization.
*/
- if (cpu_impl >= CPU_IMPL_ULTRASPARCIII)
+ if (cpu_impl == CPU_IMPL_SPARC64V ||
+ cpu_impl >= CPU_IMPL_ULTRASPARCIII)
cheetah_init(cpu_impl);
/*
@@ -491,6 +494,7 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
if (cpu_use_vis) {
switch (cpu_impl) {
case CPU_IMPL_SPARC64:
+ case CPU_IMPL_SPARC64V:
case CPU_IMPL_ULTRASPARCI:
case CPU_IMPL_ULTRASPARCII:
case CPU_IMPL_ULTRASPARCIIi:
diff --git a/sys/sparc64/sparc64/mp_locore.S b/sys/sparc64/sparc64/mp_locore.S
index bd4fd13..e78b4b9 100644
--- a/sys/sparc64/sparc64/mp_locore.S
+++ b/sys/sparc64/sparc64/mp_locore.S
@@ -200,19 +200,25 @@ ENTRY(mp_startup)
srlx %l1, VER_IMPL_SHIFT, %l1
sll %l1, VER_IMPL_SIZE, %l1
srl %l1, VER_IMPL_SIZE, %l1
+ cmp %l1, CPU_IMPL_SPARC64V
+ bl %icc, 4f
+ nop
+ cmp %l1, CPU_IMPL_ULTRASPARCI
+ bl %icc, 2f
+ nop
cmp %l1, CPU_IMPL_ULTRASPARCIII
bl %icc, 3f
nop
- mov CPU_STICKSYNC, %l2
+2: mov CPU_STICKSYNC, %l2
membar #StoreLoad
stw %l2, [%l0 + CSA_STATE]
-2: ldx [%l0 + CSA_STICK], %l2
- brz %l2, 2b
+3: ldx [%l0 + CSA_STICK], %l2
+ brz %l2, 3b
nop
wr %l2, 0, %asr24
-3: call cpu_get_mid
+4: call cpu_get_mid
mov %l1, %o0
/*
@@ -225,9 +231,9 @@ ENTRY(mp_startup)
/*
* Wait till its our turn to bootstrap.
*/
-4: lduw [%l0 + CSA_MID], %l1
+5: lduw [%l0 + CSA_MID], %l1
cmp %l1, %o0
- bne %xcc, 4b
+ bne %xcc, 5b
nop
add %l0, CSA_TTES, %l1
@@ -236,7 +242,7 @@ ENTRY(mp_startup)
/*
* Map the per-CPU pages.
*/
-5: sllx %l2, TTE_SHIFT, %l3
+6: sllx %l2, TTE_SHIFT, %l3
add %l1, %l3, %l3
ldx [%l3 + TTE_VPN], %l4
@@ -251,7 +257,7 @@ ENTRY(mp_startup)
add %l2, 1, %l2
cmp %l2, PCPU_PAGES
- bne %xcc, 5b
+ bne %xcc, 6b
nop
/*
diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c
index ce66a4b..4281204 100644
--- a/sys/sparc64/sparc64/mp_machdep.c
+++ b/sys/sparc64/sparc64/mp_machdep.c
@@ -164,7 +164,8 @@ mp_init(u_int cpu_impl)
if (cpu_impl == CPU_IMPL_ULTRASPARCIIIi ||
cpu_impl == CPU_IMPL_ULTRASPARCIIIip)
isjbus = 1;
- if (cpu_impl >= CPU_IMPL_ULTRASPARCIII)
+ if (cpu_impl == CPU_IMPL_SPARC64V ||
+ cpu_impl >= CPU_IMPL_ULTRASPARCIII)
cpu_ipi_selected = cheetah_ipi_selected;
else
cpu_ipi_selected = spitfire_ipi_selected;
@@ -315,7 +316,8 @@ ap_start(phandle_t node, u_int mid, u_int cpu_impl)
;
membar(StoreLoad);
csa->csa_tick = rd(tick);
- if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) {
+ if (cpu_impl == CPU_IMPL_SPARC64V ||
+ cpu_impl >= CPU_IMPL_ULTRASPARCIII) {
while (csa->csa_state != CPU_STICKSYNC)
;
membar(StoreLoad);
@@ -411,7 +413,8 @@ cpu_mp_bootstrap(struct pcpu *pc)
csa = &cpu_start_args;
/* Do CPU-specific initialization. */
- if (pc->pc_impl >= CPU_IMPL_ULTRASPARCIII)
+ if (pc->pc_impl == CPU_IMPL_SPARC64V ||
+ pc->pc_impl >= CPU_IMPL_ULTRASPARCIII)
cheetah_init(pc->pc_impl);
/*
* Enable the caches. Note that his may include applying workarounds.
diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c
index d97900c..daba4b7 100644
--- a/sys/sparc64/sparc64/pmap.c
+++ b/sys/sparc64/sparc64/pmap.c
@@ -528,7 +528,8 @@ pmap_bootstrap(u_int cpu_impl)
tp->tte_data =
((translations[i].om_tte &
~((TD_SOFT2_MASK << TD_SOFT2_SHIFT) |
- (cpu_impl < CPU_IMPL_ULTRASPARCIII ?
+ (cpu_impl >= CPU_IMPL_ULTRASPARCI &&
+ cpu_impl < CPU_IMPL_ULTRASPARCIII ?
(TD_DIAG_SF_MASK << TD_DIAG_SF_SHIFT) :
(TD_RSVD_CH_MASK << TD_RSVD_CH_SHIFT)) |
(TD_SOFT_MASK << TD_SOFT_SHIFT))) | TD_EXEC) +
@@ -694,31 +695,35 @@ pmap_extract_and_hold(pmap_t pm, vm_offset_t va, vm_prot_t prot)
{
struct tte *tp;
vm_page_t m;
+ vm_paddr_t pa;
m = NULL;
- vm_page_lock_queues();
+ pa = 0;
+ PMAP_LOCK(pm);
+retry:
if (pm == kernel_pmap) {
if (va >= VM_MIN_DIRECT_ADDRESS) {
tp = NULL;
m = PHYS_TO_VM_PAGE(TLB_DIRECT_TO_PHYS(va));
+ (void)vm_page_pa_tryrelock(pm, TLB_DIRECT_TO_PHYS(va),
+ &pa);
vm_page_hold(m);
} else {
tp = tsb_kvtotte(va);
if ((tp->tte_data & TD_V) == 0)
tp = NULL;
}
- } else {
- PMAP_LOCK(pm);
+ } else
tp = tsb_tte_lookup(pm, va);
- }
if (tp != NULL && ((tp->tte_data & TD_SW) ||
(prot & VM_PROT_WRITE) == 0)) {
+ if (vm_page_pa_tryrelock(pm, TTE_GET_PA(tp), &pa))
+ goto retry;
m = PHYS_TO_VM_PAGE(TTE_GET_PA(tp));
vm_page_hold(m);
}
- vm_page_unlock_queues();
- if (pm != kernel_pmap)
- PMAP_UNLOCK(pm);
+ PA_UNLOCK_COND(pa);
+ PMAP_UNLOCK(pm);
return (m);
}
@@ -1086,7 +1091,7 @@ pmap_pinit(pmap_t pm)
* Allocate an object for it.
*/
if (pm->pm_tsb_obj == NULL)
- pm->pm_tsb_obj = vm_object_allocate(OBJT_DEFAULT, TSB_PAGES);
+ pm->pm_tsb_obj = vm_object_allocate(OBJT_PHYS, TSB_PAGES);
VM_OBJECT_LOCK(pm->pm_tsb_obj);
for (i = 0; i < TSB_PAGES; i++) {
@@ -1147,16 +1152,10 @@ pmap_release(pmap_t pm)
KASSERT(obj->ref_count == 1, ("pmap_release: tsbobj ref count != 1"));
while (!TAILQ_EMPTY(&obj->memq)) {
m = TAILQ_FIRST(&obj->memq);
- vm_page_lock_queues();
- if (vm_page_sleep_if_busy(m, FALSE, "pmaprl"))
- continue;
- KASSERT(m->hold_count == 0,
- ("pmap_release: freeing held tsb page"));
m->md.pmap = NULL;
m->wire_count--;
atomic_subtract_int(&cnt.v_wire_count, 1);
vm_page_free_zero(m);
- vm_page_unlock_queues();
}
VM_OBJECT_UNLOCK(obj);
pmap_qremove((vm_offset_t)pm->pm_tsb, TSB_PAGES);
@@ -1273,13 +1272,10 @@ pmap_protect_tte(struct pmap *pm, struct pmap *pm2, struct tte *tp,
u_long data;
vm_page_t m;
- data = atomic_clear_long(&tp->tte_data, TD_REF | TD_SW | TD_W);
- if ((data & TD_PV) != 0) {
+ data = atomic_clear_long(&tp->tte_data, TD_SW | TD_W);
+ if ((data & (TD_PV | TD_W)) == (TD_PV | TD_W)) {
m = PHYS_TO_VM_PAGE(TD_PA(data));
- if ((data & TD_REF) != 0)
- vm_page_flag_set(m, PG_REFERENCED);
- if ((data & TD_W) != 0)
- vm_page_dirty(m);
+ vm_page_dirty(m);
}
return (1);
}
diff --git a/sys/sparc64/sparc64/tick.c b/sys/sparc64/sparc64/tick.c
index 1a38013..041faa0 100644
--- a/sys/sparc64/sparc64/tick.c
+++ b/sys/sparc64/sparc64/tick.c
@@ -120,7 +120,8 @@ cpu_initclocks(void)
*/
} else {
clock = PCPU_GET(clock);
- intr_setup(PIL_TICK, PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII ?
+ intr_setup(PIL_TICK, PCPU_GET(impl) >= CPU_IMPL_ULTRASPARCI &&
+ PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII ?
tick_hardclock_bbwar : tick_hardclock, -1, NULL, NULL);
set_cputicker(tick_cputicks, clock, 0);
}
@@ -325,7 +326,8 @@ void
tick_clear(u_int cpu_impl)
{
- if (cpu_impl >= CPU_IMPL_ULTRASPARCIII)
+ if (cpu_impl == CPU_IMPL_SPARC64V ||
+ cpu_impl >= CPU_IMPL_ULTRASPARCIII)
wrstick(0, 0);
wrpr(tick, 0, 0);
}
@@ -334,7 +336,8 @@ void
tick_stop(u_int cpu_impl)
{
- if (cpu_impl >= CPU_IMPL_ULTRASPARCIII)
+ if (cpu_impl == CPU_IMPL_SPARC64V ||
+ cpu_impl >= CPU_IMPL_ULTRASPARCIII)
wrstickcmpr(1L << 63, 0);
wrtickcmpr(1L << 63, 0);
}
diff --git a/sys/sparc64/sparc64/zeus.c b/sys/sparc64/sparc64/zeus.c
new file mode 100644
index 0000000..a3dc4e5
--- /dev/null
+++ b/sys/sparc64/sparc64/zeus.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2010 Marius Strobl <marius@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/asi.h>
+#include <machine/cache.h>
+#include <machine/cpufunc.h>
+
+/*
+ * Flush all lines from the level 1 caches.
+ */
+void
+zeus_cache_flush(void)
+{
+
+ stxa_sync(0, ASI_FLUSH_L1I, 0);
+}
+
+/*
+ * Flush a physical page from the data cache. Data cache consistency is
+ * maintained by hardware.
+ */
+void
+zeus_dcache_page_inval(vm_paddr_t spa __unused)
+{
+
+}
+
+/*
+ * Flush a physical page from the intsruction cache. Instruction cache
+ * consistency is maintained by hardware.
+ */
+void
+zeus_icache_page_inval(vm_paddr_t pa __unused)
+{
+
+}
diff --git a/sys/sun4v/include/pmap.h b/sys/sun4v/include/pmap.h
index 90ae4c4..6acebb4 100644
--- a/sys/sun4v/include/pmap.h
+++ b/sys/sun4v/include/pmap.h
@@ -75,6 +75,8 @@ struct pmap {
struct tte_hash *pm_hash;
TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */
struct hv_tsb_info pm_tsb;
+ uint32_t pm_gen_count; /* generation count (pmap lock dropped) */
+ u_int pm_retries;
pmap_cpumask_t pm_active; /* mask of cpus currently using pmap */
pmap_cpumask_t pm_tlbactive; /* mask of cpus that have used this pmap */
struct pmap_statistics pm_stats;
diff --git a/sys/sun4v/include/proc.h b/sys/sun4v/include/proc.h
index 84eaed5..3c23663 100644
--- a/sys/sun4v/include/proc.h
+++ b/sys/sun4v/include/proc.h
@@ -51,6 +51,6 @@ struct mdproc {
void *md_sigtramp;
};
-#define KINFO_PROC_SIZE 1088
+#define KINFO_PROC_SIZE 1088
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/sun4v/sun4v/pmap.c b/sys/sun4v/sun4v/pmap.c
index 2633b8e..0c84421 100644
--- a/sys/sun4v/sun4v/pmap.c
+++ b/sys/sun4v/sun4v/pmap.c
@@ -1275,17 +1275,21 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
{
tte_t tte_data;
vm_page_t m;
+ vm_paddr_t pa;
m = NULL;
- vm_page_lock_queues();
+ pa = 0;
PMAP_LOCK(pmap);
+retry:
tte_data = tte_hash_lookup(pmap->pm_hash, va);
if (tte_data != 0 &&
((tte_data & VTD_SW_W) || (prot & VM_PROT_WRITE) == 0)) {
+ if (vm_page_pa_tryrelock(pmap, TTE_GET_PA(tte_data), &pa))
+ goto retry;
m = PHYS_TO_VM_PAGE(TTE_GET_PA(tte_data));
vm_page_hold(m);
}
- vm_page_unlock_queues();
+ PA_UNLOCK_COND(pa);
PMAP_UNLOCK(pmap);
return (m);
@@ -1824,17 +1828,10 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
if (!anychanged && (otte_data & VTD_W))
anychanged = 1;
- if (otte_data & VTD_MANAGED) {
- m = NULL;
-
- if (otte_data & VTD_REF) {
- m = PHYS_TO_VM_PAGE(TTE_GET_PA(otte_data));
- vm_page_flag_set(m, PG_REFERENCED);
- }
- if (otte_data & VTD_W) {
- m = PHYS_TO_VM_PAGE(TTE_GET_PA(otte_data));
- vm_page_dirty(m);
- }
+ if ((otte_data & (VTD_MANAGED | VTD_W)) == (VTD_MANAGED |
+ VTD_W)) {
+ m = PHYS_TO_VM_PAGE(TTE_GET_PA(otte_data));
+ vm_page_dirty(m);
}
}
diff --git a/sys/sys/_task.h b/sys/sys/_task.h
index 2a51e1b..781cd48 100644
--- a/sys/sys/_task.h
+++ b/sys/sys/_task.h
@@ -36,15 +36,21 @@
* taskqueue_run(). The first argument is taken from the 'ta_context'
* field of struct task and the second argument is a count of how many
* times the task was enqueued before the call to taskqueue_run().
+ *
+ * List of locks
+ * (c) const after init
+ * (q) taskqueue lock
*/
typedef void task_fn_t(void *context, int pending);
struct task {
- STAILQ_ENTRY(task) ta_link; /* link for queue */
- u_short ta_pending; /* count times queued */
- u_short ta_priority; /* Priority */
- task_fn_t *ta_func; /* task handler */
- void *ta_context; /* argument for handler */
+ STAILQ_ENTRY(task) ta_link; /* (q) link for queue */
+ u_int ta_flags; /* (q) state of this task */
+#define TA_FLAGS_RUNNING 0x01
+ u_short ta_pending; /* (q) count times queued */
+ u_short ta_priority; /* (c) Priority */
+ task_fn_t *ta_func; /* (c) task handler */
+ void *ta_context; /* (c) argument for handler */
};
#endif /* !_SYS__TASK_H_ */
diff --git a/sys/sys/buf_ring.h b/sys/sys/buf_ring.h
index efa667d..57e42e5 100644
--- a/sys/sys/buf_ring.h
+++ b/sys/sys/buf_ring.h
@@ -1,33 +1,31 @@
-/**************************************************************************
- *
- * Copyright (c) 2007-2009 Kip Macy kmacy@freebsd.org
+/*-
+ * Copyright (c) 2007-2009 Kip Macy <kmacy@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.
+ * 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.
*
- * 2. The name of Kip Macy nor the names of other
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*
* $FreeBSD$
*
- ***************************************************************************/
+ */
#ifndef _SYS_BUF_RING_H_
#define _SYS_BUF_RING_H_
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 9f87ee2..11c15ab 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 900010 /* Master, propagated to newvers */
+#define __FreeBSD_version 900011 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index fb31cfc..e32e494 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -173,6 +173,27 @@ struct kdtrace_thread;
struct cpuset;
/*
+ * XXX: Does this belong in resource.h or resourcevar.h instead?
+ * Resource usage extension. The times in rusage structs in the kernel are
+ * never up to date. The actual times are kept as runtimes and tick counts
+ * (with control info in the "previous" times), and are converted when
+ * userland asks for rusage info. Backwards compatibility prevents putting
+ * this directly in the user-visible rusage struct.
+ *
+ * Locking for p_rux: (cj) means (j) for p_rux and (c) for p_crux.
+ * Locking for td_rux: (t) for all fields.
+ */
+struct rusage_ext {
+ u_int64_t rux_runtime; /* (cj) Real time. */
+ u_int64_t rux_uticks; /* (cj) Statclock hits in user mode. */
+ u_int64_t rux_sticks; /* (cj) Statclock hits in sys mode. */
+ u_int64_t rux_iticks; /* (cj) Statclock hits in intr mode. */
+ u_int64_t rux_uu; /* (c) Previous user time in usec. */
+ u_int64_t rux_su; /* (c) Previous sys time in usec. */
+ u_int64_t rux_tu; /* (c) Previous total time in usec. */
+};
+
+/*
* Kernel runnable context (thread).
* This is what is put to sleep and reactivated.
* Thread context. Processes may have multiple threads.
@@ -219,7 +240,8 @@ struct thread {
u_int td_estcpu; /* (t) estimated cpu utilization */
int td_slptick; /* (t) Time at sleep. */
int td_blktick; /* (t) Time spent blocked. */
- struct rusage td_ru; /* (t) rusage information */
+ struct rusage td_ru; /* (t) rusage information. */
+ struct rusage_ext td_rux; /* (t) Internal rusage information. */
uint64_t td_incruntime; /* (t) Cpu ticks to transfer to proc. */
uint64_t td_runtime; /* (t) How many cpu ticks we've run. */
u_int td_pticks; /* (t) Statclock hits for profiling */
@@ -426,26 +448,6 @@ do { \
#define TD_SET_CAN_RUN(td) (td)->td_state = TDS_CAN_RUN
/*
- * XXX: Does this belong in resource.h or resourcevar.h instead?
- * Resource usage extension. The times in rusage structs in the kernel are
- * never up to date. The actual times are kept as runtimes and tick counts
- * (with control info in the "previous" times), and are converted when
- * userland asks for rusage info. Backwards compatibility prevents putting
- * this directly in the user-visible rusage struct.
- *
- * Locking: (cj) means (j) for p_rux and (c) for p_crux.
- */
-struct rusage_ext {
- u_int64_t rux_runtime; /* (cj) Real time. */
- u_int64_t rux_uticks; /* (cj) Statclock hits in user mode. */
- u_int64_t rux_sticks; /* (cj) Statclock hits in sys mode. */
- u_int64_t rux_iticks; /* (cj) Statclock hits in intr mode. */
- u_int64_t rux_uu; /* (c) Previous user time in usec. */
- u_int64_t rux_su; /* (c) Previous sys time in usec. */
- u_int64_t rux_tu; /* (c) Previous total time in usec. */
-};
-
-/*
* Process structure.
*/
struct proc {
diff --git a/sys/sys/resource.h b/sys/sys/resource.h
index 9af96af..e703744 100644
--- a/sys/sys/resource.h
+++ b/sys/sys/resource.h
@@ -56,6 +56,7 @@
#define RUSAGE_SELF 0
#define RUSAGE_CHILDREN -1
+#define RUSAGE_THREAD 1
struct rusage {
struct timeval ru_utime; /* user time used */
diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h
index 21728aa..95a9b49 100644
--- a/sys/sys/resourcevar.h
+++ b/sys/sys/resourcevar.h
@@ -131,7 +131,7 @@ void rucollect(struct rusage *ru, struct rusage *ru2);
void rufetch(struct proc *p, struct rusage *ru);
void rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up,
struct timeval *sp);
-void ruxagg(struct rusage_ext *rux, struct thread *td);
+void ruxagg_locked(struct rusage_ext *rux, struct thread *td);
int suswintr(void *base, int word);
struct uidinfo
*uifind(uid_t uid);
diff --git a/sys/sys/taskqueue.h b/sys/sys/taskqueue.h
index bf2e4ee..fa8897d 100644
--- a/sys/sys/taskqueue.h
+++ b/sys/sys/taskqueue.h
@@ -75,6 +75,7 @@ void taskqueue_thread_enqueue(void *context);
(task)->ta_priority = (priority); \
(task)->ta_func = (func); \
(task)->ta_context = (context); \
+ (task)->ta_flags = 0; \
} while (0)
/*
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index b5784e4..7c4ae32 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -780,6 +780,7 @@ struct dirent;
int vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off);
int vfs_unixify_accmode(accmode_t *accmode);
+int vn_rlimit_fsize(const struct vnode *vn, const struct uio *uio, const struct thread *td);
#endif /* _KERNEL */
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 4a659f9..b05339b 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -123,6 +123,21 @@ softdep_uninitialize()
}
void
+softdep_unmount(mp)
+ struct mount *mp;
+{
+
+}
+
+void
+softdep_setup_sbupdate(ump, fs, bp)
+ struct ufsmount *ump;
+ struct fs *fs;
+ struct buf *bp;
+{
+}
+
+void
softdep_setup_inomapdep(bp, ip, newinum)
struct buf *bp;
struct inode *ip;
@@ -267,6 +282,162 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir)
panic("softdep_setup_directory_change called");
}
+void *
+softdep_setup_trunc(vp, length, flags)
+ struct vnode *vp;
+ off_t length;
+ int flags;
+{
+
+ panic("%s called", __FUNCTION__);
+
+ return (NULL);
+}
+
+int
+softdep_complete_trunc(vp, cookie)
+ struct vnode *vp;
+ void *cookie;
+{
+
+ panic("%s called", __FUNCTION__);
+
+ return (0);
+}
+
+void
+softdep_setup_blkfree(mp, bp, blkno, frags, wkhd)
+ struct mount *mp;
+ struct buf *bp;
+ ufs2_daddr_t blkno;
+ int frags;
+ struct workhead *wkhd;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+void
+softdep_setup_inofree(mp, bp, ino, wkhd)
+ struct mount *mp;
+ struct buf *bp;
+ ino_t ino;
+ struct workhead *wkhd;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+void
+softdep_setup_unlink(dp, ip)
+ struct inode *dp;
+ struct inode *ip;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+void
+softdep_setup_link(dp, ip)
+ struct inode *dp;
+ struct inode *ip;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+void
+softdep_revert_link(dp, ip)
+ struct inode *dp;
+ struct inode *ip;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+void
+softdep_setup_rmdir(dp, ip)
+ struct inode *dp;
+ struct inode *ip;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+void
+softdep_revert_rmdir(dp, ip)
+ struct inode *dp;
+ struct inode *ip;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+void
+softdep_setup_create(dp, ip)
+ struct inode *dp;
+ struct inode *ip;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+void
+softdep_revert_create(dp, ip)
+ struct inode *dp;
+ struct inode *ip;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+void
+softdep_setup_mkdir(dp, ip)
+ struct inode *dp;
+ struct inode *ip;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+void
+softdep_revert_mkdir(dp, ip)
+ struct inode *dp;
+ struct inode *ip;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+void
+softdep_setup_dotdot_link(dp, ip)
+ struct inode *dp;
+ struct inode *ip;
+{
+
+ panic("%s called", __FUNCTION__);
+}
+
+int
+softdep_prealloc(vp, waitok)
+ struct vnode *vp;
+ int waitok;
+{
+
+ panic("%s called", __FUNCTION__);
+
+ return (0);
+}
+
+int
+softdep_journal_lookup(mp, vpp)
+ struct mount *mp;
+ struct vnode **vpp;
+{
+
+ return (ENOENT);
+}
+
void
softdep_change_linkcnt(ip)
struct inode *ip;
@@ -3333,7 +3504,8 @@ cancel_jaddref(jaddref, inodedep, wkhd)
WORKLIST_INSERT(wkhd, &jsegdep->jd_list);
} else {
free_jsegdep(jsegdep);
- remove_from_journal(&jaddref->ja_list);
+ if (jaddref->ja_state & DEPCOMPLETE)
+ remove_from_journal(&jaddref->ja_list);
}
/*
* Leave NEWBLOCK jaddrefs on the inodedep so handle_workitem_remove
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index e403368..2963514 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -126,8 +126,8 @@ static struct buf_ops ffs_ops = {
static const char *ffs_opts[] = { "acls", "async", "noatime", "noclusterr",
"noclusterw", "noexec", "export", "force", "from", "multilabel",
- "snapshot", "nosuid", "suiddir", "nosymfollow", "sync",
- "union", "nfsv4acls", NULL };
+ "nfsv4acls", "snapshot", "nosuid", "suiddir", "nosymfollow", "sync",
+ "union", NULL };
static int
ffs_mount(struct mount *mp)
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index e6617cb..a2fee4e 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -75,9 +75,6 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/priv.h>
-#include <sys/proc.h>
-#include <sys/resourcevar.h>
-#include <sys/signalvar.h>
#include <sys/stat.h>
#include <sys/vmmeter.h>
#include <sys/vnode.h>
@@ -652,7 +649,6 @@ ffs_write(ap)
struct inode *ip;
struct fs *fs;
struct buf *bp;
- struct thread *td;
ufs_lbn_t lbn;
off_t osize;
int seqcount;
@@ -704,17 +700,8 @@ ffs_write(ap)
* Maybe this should be above the vnode op call, but so long as
* file servers have no limits, I don't think it matters.
*/
- td = uio->uio_td;
- if (vp->v_type == VREG && td != NULL) {
- PROC_LOCK(td->td_proc);
- if (uio->uio_offset + uio->uio_resid >
- lim_cur(td->td_proc, RLIMIT_FSIZE)) {
- psignal(td->td_proc, SIGXFSZ);
- PROC_UNLOCK(td->td_proc);
- return (EFBIG);
- }
- PROC_UNLOCK(td->td_proc);
- }
+ if (vn_rlimit_fsize(vp, uio, uio->uio_td))
+ return (EFBIG);
resid = uio->uio_resid;
osize = ip->i_size;
@@ -860,13 +847,15 @@ ffs_getpages(ap)
if (mreq->valid) {
if (mreq->valid != VM_PAGE_BITS_ALL)
vm_page_zero_invalid(mreq, TRUE);
- vm_page_lock_queues();
for (i = 0; i < pcount; i++) {
if (i != ap->a_reqpage) {
+ vm_page_lock(ap->a_m[i]);
+ vm_page_lock_queues();
vm_page_free(ap->a_m[i]);
+ vm_page_unlock_queues();
+ vm_page_unlock(ap->a_m[i]);
}
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(mreq->object);
return VM_PAGER_OK;
}
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index 9002e77..996f740 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -251,12 +251,16 @@ dev_pager_getpages(object, m, count, reqpage)
VM_OBJECT_LOCK(object);
dev_pager_updatefake(page, paddr, memattr);
if (count > 1) {
- vm_page_lock_queues();
+
for (i = 0; i < count; i++) {
- if (i != reqpage)
+ if (i != reqpage) {
+ vm_page_lock(m[i]);
+ vm_page_lock_queues();
vm_page_free(m[i]);
+ vm_page_unlock_queues();
+ vm_page_unlock(m[i]);
+ }
}
- vm_page_unlock_queues();
}
} else {
/*
@@ -266,10 +270,13 @@ dev_pager_getpages(object, m, count, reqpage)
page = dev_pager_getfake(paddr, memattr);
VM_OBJECT_LOCK(object);
TAILQ_INSERT_TAIL(&object->un_pager.devp.devp_pglist, page, pageq);
- vm_page_lock_queues();
- for (i = 0; i < count; i++)
+ for (i = 0; i < count; i++) {
+ vm_page_lock(m[i]);
+ vm_page_lock_queues();
vm_page_free(m[i]);
- vm_page_unlock_queues();
+ vm_page_unlock_queues();
+ vm_page_unlock(m[i]);
+ }
vm_page_insert(page, object, offset);
m[reqpage] = page;
}
diff --git a/sys/vm/phys_pager.c b/sys/vm/phys_pager.c
index 42cdab3..97674e3 100644
--- a/sys/vm/phys_pager.c
+++ b/sys/vm/phys_pager.c
@@ -152,10 +152,10 @@ phys_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
KASSERT(m[i]->dirty == 0,
("phys_pager_getpages: dirty page %p", m[i]));
/* The requested page must remain busy, the others not. */
- if (reqpage != i) {
- m[i]->oflags &= ~VPO_BUSY;
- m[i]->busy = 0;
- }
+ if (i == reqpage)
+ vm_page_flash(m[i]);
+ else
+ vm_page_wakeup(m[i]);
}
return (VM_PAGER_OK);
}
diff --git a/sys/vm/sg_pager.c b/sys/vm/sg_pager.c
index a17fe82..845401a 100644
--- a/sys/vm/sg_pager.c
+++ b/sys/vm/sg_pager.c
@@ -198,10 +198,13 @@ sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
TAILQ_INSERT_TAIL(&object->un_pager.sgp.sgp_pglist, page, pageq);
/* Free the original pages and insert this fake page into the object. */
- vm_page_lock_queues();
- for (i = 0; i < count; i++)
+ for (i = 0; i < count; i++) {
+ vm_page_lock(m[i]);
+ vm_page_lock_queues();
vm_page_free(m[i]);
- vm_page_unlock_queues();
+ vm_page_unlock_queues();
+ vm_page_unlock(m[i]);
+ }
vm_page_insert(page, object, offset);
m[reqpage] = page;
page->valid = VM_PAGE_BITS_ALL;
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index f1d89d5..6017a52 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -378,6 +378,14 @@ static void swp_pager_meta_free(vm_object_t, vm_pindex_t, daddr_t);
static void swp_pager_meta_free_all(vm_object_t);
static daddr_t swp_pager_meta_ctl(vm_object_t, vm_pindex_t, int);
+static void
+swp_pager_free_nrpage(vm_page_t m)
+{
+
+ if (m->wire_count == 0)
+ vm_page_free(m);
+}
+
/*
* SWP_SIZECHECK() - update swap_pager_full indication
*
@@ -1129,12 +1137,21 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage)
if (0 < i || j < count) {
int k;
- vm_page_lock_queues();
- for (k = 0; k < i; ++k)
- vm_page_free(m[k]);
- for (k = j; k < count; ++k)
- vm_page_free(m[k]);
- vm_page_unlock_queues();
+
+ for (k = 0; k < i; ++k) {
+ vm_page_lock(m[k]);
+ vm_page_lock_queues();
+ swp_pager_free_nrpage(m[k]);
+ vm_page_unlock_queues();
+ vm_page_unlock(m[k]);
+ }
+ for (k = j; k < count; ++k) {
+ vm_page_lock(m[k]);
+ vm_page_lock_queues();
+ swp_pager_free_nrpage(m[k]);
+ vm_page_unlock_queues();
+ vm_page_unlock(m[k]);
+ }
}
/*
@@ -1489,7 +1506,7 @@ swp_pager_async_iodone(struct buf *bp)
object = bp->b_pages[0]->object;
VM_OBJECT_LOCK(object);
}
- vm_page_lock_queues();
+
/*
* cleanup pages. If an error occurs writing to swap, we are in
* very serious trouble. If it happens to be a disk error, though,
@@ -1501,6 +1518,8 @@ swp_pager_async_iodone(struct buf *bp)
for (i = 0; i < bp->b_npages; ++i) {
vm_page_t m = bp->b_pages[i];
+ vm_page_lock(m);
+ vm_page_lock_queues();
m->oflags &= ~VPO_SWAPINPROG;
if (bp->b_ioflags & BIO_ERROR) {
@@ -1529,7 +1548,7 @@ swp_pager_async_iodone(struct buf *bp)
*/
m->valid = 0;
if (i != bp->b_pager.pg_reqpage)
- vm_page_free(m);
+ swp_pager_free_nrpage(m);
else
vm_page_flash(m);
/*
@@ -1597,8 +1616,9 @@ swp_pager_async_iodone(struct buf *bp)
if (vm_page_count_severe())
vm_page_try_to_cache(m);
}
+ vm_page_unlock_queues();
+ vm_page_unlock(m);
}
- vm_page_unlock_queues();
/*
* adjust pip. NOTE: the original parent may still have its own
@@ -1694,10 +1714,12 @@ swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex)
m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL|VM_ALLOC_RETRY);
if (m->valid == VM_PAGE_BITS_ALL) {
vm_object_pip_subtract(object, 1);
+ vm_page_lock(m);
vm_page_lock_queues();
vm_page_activate(m);
vm_page_dirty(m);
vm_page_unlock_queues();
+ vm_page_unlock(m);
vm_page_wakeup(m);
vm_pager_page_unswapped(m);
return;
@@ -1706,10 +1728,12 @@ swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex)
if (swap_pager_getpages(object, &m, 1, 0) != VM_PAGER_OK)
panic("swap_pager_force_pagein: read from swap failed");/*XXX*/
vm_object_pip_subtract(object, 1);
+ vm_page_lock(m);
vm_page_lock_queues();
vm_page_dirty(m);
vm_page_dontneed(m);
vm_page_unlock_queues();
+ vm_page_unlock(m);
vm_page_wakeup(m);
vm_pager_page_unswapped(m);
}
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index a2d5633..e1b9a08 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -1022,10 +1022,8 @@ obj_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
while (pages != startpages) {
pages--;
p = TAILQ_LAST(&object->memq, pglist);
- vm_page_lock_queues();
vm_page_unwire(p, 0);
vm_page_free(p);
- vm_page_unlock_queues();
}
retkva = 0;
goto done;
@@ -2891,13 +2889,11 @@ uma_zone_set_obj(uma_zone_t zone, struct vm_object *obj, int count)
if (kva == 0)
return (0);
- if (obj == NULL) {
- obj = vm_object_allocate(OBJT_DEFAULT,
- pages);
- } else {
+ if (obj == NULL)
+ obj = vm_object_allocate(OBJT_PHYS, pages);
+ else {
VM_OBJECT_LOCK_INIT(obj, "uma object");
- _vm_object_allocate(OBJT_DEFAULT,
- pages, obj);
+ _vm_object_allocate(OBJT_PHYS, pages, obj);
}
ZONE_LOCK(zone);
keg->uk_kva = kva;
diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c
index 78d7e28..c1c8618 100644
--- a/sys/vm/vm_contig.c
+++ b/sys/vm/vm_contig.c
@@ -99,9 +99,11 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next)
int vfslocked;
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(m, MA_OWNED);
object = m->object;
if (!VM_OBJECT_TRYLOCK(object) &&
!vm_pageout_fallback_object_lock(m, next)) {
+ vm_page_unlock(m);
VM_OBJECT_UNLOCK(object);
return (EAGAIN);
}
@@ -113,7 +115,8 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next)
vm_page_test_dirty(m);
if (m->dirty == 0 && m->hold_count == 0)
pmap_remove_all(m);
- if (m->dirty) {
+ if (m->dirty != 0) {
+ vm_page_unlock(m);
if ((object->flags & OBJ_DEAD) != 0) {
VM_OBJECT_UNLOCK(object);
return (EAGAIN);
@@ -137,13 +140,18 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next)
return (0);
} else if (object->type == OBJT_SWAP ||
object->type == OBJT_DEFAULT) {
+ vm_page_unlock_queues();
m_tmp = m;
vm_pageout_flush(&m_tmp, 1, VM_PAGER_PUT_SYNC);
VM_OBJECT_UNLOCK(object);
+ vm_page_lock_queues();
return (0);
}
- } else if (m->hold_count == 0)
- vm_page_cache(m);
+ } else {
+ if (m->hold_count == 0)
+ vm_page_cache(m);
+ vm_page_unlock(m);
+ }
VM_OBJECT_UNLOCK(object);
return (0);
}
@@ -160,9 +168,12 @@ vm_contig_launder(int queue)
if ((m->flags & PG_MARKER) != 0)
continue;
+ if (!vm_page_trylock(m))
+ continue;
KASSERT(VM_PAGE_INQUEUE2(m, queue),
("vm_contig_launder: page %p's queue is not %d", m, queue));
error = vm_contig_launder_page(m, &next);
+ vm_page_lock_assert(m, MA_NOTOWNED);
if (error == 0)
return (TRUE);
if (error == EBUSY)
@@ -257,9 +268,7 @@ retry:
i -= PAGE_SIZE;
m = vm_page_lookup(object, OFF_TO_IDX(offset +
i));
- vm_page_lock_queues();
vm_page_free(m);
- vm_page_unlock_queues();
}
VM_OBJECT_UNLOCK(object);
vm_map_delete(map, addr, addr + size);
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index f409856..2978f7f 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -137,9 +137,11 @@ release_page(struct faultstate *fs)
{
vm_page_wakeup(fs->m);
+ vm_page_lock(fs->m);
vm_page_lock_queues();
vm_page_deactivate(fs->m);
vm_page_unlock_queues();
+ vm_page_unlock(fs->m);
fs->m = NULL;
}
@@ -161,9 +163,11 @@ unlock_and_deallocate(struct faultstate *fs)
VM_OBJECT_UNLOCK(fs->object);
if (fs->object != fs->first_object) {
VM_OBJECT_LOCK(fs->first_object);
+ vm_page_lock(fs->first_m);
vm_page_lock_queues();
vm_page_free(fs->first_m);
vm_page_unlock_queues();
+ vm_page_unlock(fs->first_m);
vm_object_pip_wakeup(fs->first_object);
VM_OBJECT_UNLOCK(fs->first_object);
fs->first_m = NULL;
@@ -211,7 +215,7 @@ vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type,
{
vm_prot_t prot;
int is_first_object_locked, result;
- boolean_t are_queues_locked, growstack, wired;
+ boolean_t growstack, wired;
int map_generation;
vm_object_t next_object;
vm_page_t marray[VM_FAULT_READ];
@@ -305,12 +309,12 @@ RetryFault:;
* removes the page from the backing object,
* which is not what we want.
*/
+ vm_page_lock(fs.m);
vm_page_lock_queues();
if ((fs.m->cow) &&
(fault_type & VM_PROT_WRITE) &&
(fs.object == fs.first_object)) {
vm_page_cowfault(fs.m);
- vm_page_unlock_queues();
unlock_and_deallocate(&fs);
goto RetryFault;
}
@@ -332,13 +336,22 @@ RetryFault:;
* to pmap it.
*/
if ((fs.m->oflags & VPO_BUSY) || fs.m->busy) {
+ /*
+ * Reference the page before unlocking and
+ * sleeping so that the page daemon is less
+ * likely to reclaim it.
+ */
+ vm_page_flag_set(fs.m, PG_REFERENCED);
vm_page_unlock_queues();
+ vm_page_unlock(fs.m);
VM_OBJECT_UNLOCK(fs.object);
if (fs.object != fs.first_object) {
VM_OBJECT_LOCK(fs.first_object);
+ vm_page_lock(fs.first_m);
vm_page_lock_queues();
vm_page_free(fs.first_m);
vm_page_unlock_queues();
+ vm_page_unlock(fs.first_m);
vm_object_pip_wakeup(fs.first_object);
VM_OBJECT_UNLOCK(fs.first_object);
fs.first_m = NULL;
@@ -358,6 +371,7 @@ RetryFault:;
}
vm_pageq_remove(fs.m);
vm_page_unlock_queues();
+ vm_page_unlock(fs.m);
/*
* Mark page busy for other processes, and the
@@ -462,7 +476,6 @@ readrest:
else
firstpindex = fs.first_pindex - 2 * VM_FAULT_READ;
- are_queues_locked = FALSE;
/*
* note: partially valid pages cannot be
* included in the lookahead - NFS piecemeal
@@ -479,22 +492,23 @@ readrest:
if (mt->busy ||
(mt->oflags & VPO_BUSY))
continue;
- if (!are_queues_locked) {
- are_queues_locked = TRUE;
- vm_page_lock_queues();
- }
+ vm_page_lock(mt);
+ vm_page_lock_queues();
if (mt->hold_count ||
- mt->wire_count)
+ mt->wire_count) {
+ vm_page_unlock_queues();
+ vm_page_unlock(mt);
continue;
+ }
pmap_remove_all(mt);
if (mt->dirty) {
vm_page_deactivate(mt);
} else {
vm_page_cache(mt);
}
- }
- if (are_queues_locked)
vm_page_unlock_queues();
+ vm_page_unlock(mt);
+ }
ahead += behind;
behind = 0;
}
@@ -623,17 +637,21 @@ vnode_locked:
*/
if (((fs.map != kernel_map) && (rv == VM_PAGER_ERROR)) ||
(rv == VM_PAGER_BAD)) {
+ vm_page_lock(fs.m);
vm_page_lock_queues();
vm_page_free(fs.m);
vm_page_unlock_queues();
+ vm_page_unlock(fs.m);
fs.m = NULL;
unlock_and_deallocate(&fs);
return ((rv == VM_PAGER_ERROR) ? KERN_FAILURE : KERN_PROTECTION_FAILURE);
}
if (fs.object != fs.first_object) {
+ vm_page_lock(fs.m);
vm_page_lock_queues();
vm_page_free(fs.m);
vm_page_unlock_queues();
+ vm_page_unlock(fs.m);
fs.m = NULL;
/*
* XXX - we cannot just fall out at this
@@ -746,18 +764,22 @@ vnode_locked:
* We don't chase down the shadow chain
*/
fs.object == fs.first_object->backing_object) {
+ vm_page_lock(fs.first_m);
vm_page_lock_queues();
/*
* get rid of the unnecessary page
*/
vm_page_free(fs.first_m);
+ vm_page_unlock_queues();
+ vm_page_unlock(fs.first_m);
/*
* grab the page and put it into the
* process'es object. The page is
* automatically made dirty.
*/
+ vm_page_lock(fs.m);
vm_page_rename(fs.m, fs.first_object, fs.first_pindex);
- vm_page_unlock_queues();
+ vm_page_unlock(fs.m);
vm_page_busy(fs.m);
fs.first_m = fs.m;
fs.m = NULL;
@@ -770,10 +792,13 @@ vnode_locked:
fs.first_m->valid = VM_PAGE_BITS_ALL;
if (wired && (fault_flags &
VM_FAULT_CHANGE_WIRING) == 0) {
- vm_page_lock_queues();
+ vm_page_lock(fs.first_m);
vm_page_wire(fs.first_m);
+ vm_page_unlock(fs.first_m);
+
+ vm_page_lock(fs.m);
vm_page_unwire(fs.m, FALSE);
- vm_page_unlock_queues();
+ vm_page_unlock(fs.m);
}
/*
* We no longer need the old page or object.
@@ -923,8 +948,8 @@ vnode_locked:
if ((fault_flags & VM_FAULT_CHANGE_WIRING) == 0 && wired == 0)
vm_fault_prefault(fs.map->pmap, vaddr, fs.entry);
VM_OBJECT_LOCK(fs.object);
+ vm_page_lock(fs.m);
vm_page_lock_queues();
- vm_page_flag_set(fs.m, PG_REFERENCED);
/*
* If the page is not wired down, then put it where the pageout daemon
@@ -939,6 +964,7 @@ vnode_locked:
vm_page_activate(fs.m);
}
vm_page_unlock_queues();
+ vm_page_unlock(fs.m);
vm_page_wakeup(fs.m);
/*
@@ -1015,9 +1041,11 @@ vm_fault_prefault(pmap_t pmap, vm_offset_t addra, vm_map_entry_t entry)
}
if (m->valid == VM_PAGE_BITS_ALL &&
(m->flags & PG_FICTITIOUS) == 0) {
+ vm_page_lock(m);
vm_page_lock_queues();
pmap_enter_quick(pmap, addr, m, entry->protection);
vm_page_unlock_queues();
+ vm_page_unlock(m);
}
VM_OBJECT_UNLOCK(lobject);
}
@@ -1080,6 +1108,7 @@ vm_fault_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end,
{
vm_paddr_t pa;
vm_offset_t va;
+ vm_page_t m;
pmap_t pmap;
pmap = vm_map_pmap(map);
@@ -1093,9 +1122,10 @@ vm_fault_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end,
if (pa != 0) {
pmap_change_wiring(pmap, va, FALSE);
if (!fictitious) {
- vm_page_lock_queues();
- vm_page_unwire(PHYS_TO_VM_PAGE(pa), 1);
- vm_page_unlock_queues();
+ m = PHYS_TO_VM_PAGE(pa);
+ vm_page_lock(m);
+ vm_page_unwire(m, TRUE);
+ vm_page_unlock(m);
}
}
}
@@ -1238,13 +1268,22 @@ vm_fault_copy_entry(vm_map_t dst_map, vm_map_t src_map,
* Mark it no longer busy, and put it on the active list.
*/
VM_OBJECT_LOCK(dst_object);
- vm_page_lock_queues();
+
if (upgrade) {
+ vm_page_lock(src_m);
vm_page_unwire(src_m, 0);
+ vm_page_unlock(src_m);
+
+ vm_page_lock(dst_m);
vm_page_wire(dst_m);
- } else
+ vm_page_unlock(dst_m);
+ } else {
+ vm_page_lock(dst_m);
+ vm_page_lock_queues();
vm_page_activate(dst_m);
- vm_page_unlock_queues();
+ vm_page_unlock_queues();
+ vm_page_unlock(dst_m);
+ }
vm_page_wakeup(dst_m);
}
VM_OBJECT_UNLOCK(dst_object);
diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c
index dbd5065d8..f86212f 100644
--- a/sys/vm/vm_glue.c
+++ b/sys/vm/vm_glue.c
@@ -257,16 +257,18 @@ vm_imgact_hold_page(vm_object_t object, vm_ooffset_t offset)
if (m == NULL)
goto out;
if (rv != VM_PAGER_OK) {
+ vm_page_lock(m);
vm_page_lock_queues();
vm_page_free(m);
vm_page_unlock_queues();
+ vm_page_unlock(m);
m = NULL;
goto out;
}
}
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_hold(m);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
vm_page_wakeup(m);
out:
VM_OBJECT_UNLOCK(object);
@@ -300,9 +302,9 @@ vm_imgact_unmap_page(struct sf_buf *sf)
m = sf_buf_page(sf);
sf_buf_free(sf);
sched_unpin();
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_unhold(m);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
}
void
@@ -434,10 +436,12 @@ vm_thread_stack_dispose(vm_object_t ksobj, vm_offset_t ks, int pages)
m = vm_page_lookup(ksobj, i);
if (m == NULL)
panic("vm_thread_dispose: kstack already missing?");
+ vm_page_lock(m);
vm_page_lock_queues();
vm_page_unwire(m, 0);
vm_page_free(m);
vm_page_unlock_queues();
+ vm_page_unlock(m);
}
VM_OBJECT_UNLOCK(ksobj);
vm_object_deallocate(ksobj);
@@ -524,9 +528,9 @@ vm_thread_swapout(struct thread *td)
if (m == NULL)
panic("vm_thread_swapout: kstack already missing?");
vm_page_dirty(m);
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_unwire(m, 0);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
}
VM_OBJECT_UNLOCK(ksobj);
}
@@ -538,23 +542,37 @@ static void
vm_thread_swapin(struct thread *td)
{
vm_object_t ksobj;
- vm_page_t m, ma[KSTACK_MAX_PAGES];
- int i, pages, rv;
+ vm_page_t ma[KSTACK_MAX_PAGES];
+ int i, j, k, pages, rv;
pages = td->td_kstack_pages;
ksobj = td->td_kstack_obj;
VM_OBJECT_LOCK(ksobj);
- for (i = 0; i < pages; i++) {
- m = vm_page_grab(ksobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY |
+ for (i = 0; i < pages; i++)
+ ma[i] = vm_page_grab(ksobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY |
VM_ALLOC_WIRED);
- if (m->valid != VM_PAGE_BITS_ALL) {
- rv = vm_pager_get_pages(ksobj, &m, 1, 0);
+ for (i = 0; i < pages; i++) {
+ if (ma[i]->valid != VM_PAGE_BITS_ALL) {
+ KASSERT(ma[i]->oflags & VPO_BUSY,
+ ("lost busy 1"));
+ vm_object_pip_add(ksobj, 1);
+ for (j = i + 1; j < pages; j++) {
+ KASSERT(ma[j]->valid == VM_PAGE_BITS_ALL ||
+ (ma[j]->oflags & VPO_BUSY),
+ ("lost busy 2"));
+ if (ma[j]->valid == VM_PAGE_BITS_ALL)
+ break;
+ }
+ rv = vm_pager_get_pages(ksobj, ma + i, j - i, 0);
if (rv != VM_PAGER_OK)
- panic("vm_thread_swapin: cannot get kstack for proc: %d", td->td_proc->p_pid);
- m = vm_page_lookup(ksobj, i);
- }
- ma[i] = m;
- vm_page_wakeup(m);
+ panic("vm_thread_swapin: cannot get kstack for proc: %d",
+ td->td_proc->p_pid);
+ vm_object_pip_wakeup(ksobj);
+ for (k = i; k < j; k++)
+ ma[k] = vm_page_lookup(ksobj, k);
+ vm_page_wakeup(ma[i]);
+ } else if (ma[i]->oflags & VPO_BUSY)
+ vm_page_wakeup(ma[i]);
}
VM_OBJECT_UNLOCK(ksobj);
pmap_qenter(td->td_kstack, ma, pages);
diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c
index 739d289..95a4e9d 100644
--- a/sys/vm/vm_kern.c
+++ b/sys/vm/vm_kern.c
@@ -380,10 +380,8 @@ retry:
i -= PAGE_SIZE;
m = vm_page_lookup(kmem_object,
OFF_TO_IDX(offset + i));
- vm_page_lock_queues();
vm_page_unwire(m, 0);
vm_page_free(m);
- vm_page_unlock_queues();
}
VM_OBJECT_UNLOCK(kmem_object);
vm_map_delete(map, addr, addr + size);
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 1d22fa6..2a57e33 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -1412,7 +1412,11 @@ vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
}
result = vm_map_insert(map, object, offset, start, start +
length, prot, max, cow);
- } while (result == KERN_NO_SPACE && find_space == VMFS_ALIGNED_SPACE);
+ } while (result == KERN_NO_SPACE && (find_space == VMFS_ALIGNED_SPACE
+#ifdef VMFS_TLB_ALIGNED_SPACE
+ || find_space == VMFS_TLB_ALIGNED_SPACE
+#endif
+ ));
vm_map_unlock(map);
return (result);
}
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index 88ed3d5..f9b3db3 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -866,6 +866,7 @@ RestartScan:
*/
if (m != NULL && m->valid != 0) {
mincoreinfo = MINCORE_INCORE;
+ vm_page_lock(m);
vm_page_lock_queues();
if (m->dirty ||
pmap_is_modified(m))
@@ -874,6 +875,7 @@ RestartScan:
pmap_is_referenced(m))
mincoreinfo |= MINCORE_REFERENCED_OTHER;
vm_page_unlock_queues();
+ vm_page_unlock(m);
}
VM_OBJECT_UNLOCK(current->object.vm_object);
}
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 7e4dbc8..f8c50bc 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -717,19 +717,21 @@ vm_object_terminate(vm_object_t object)
* removes them from paging queues. Don't free wired pages, just
* remove them from the object.
*/
- vm_page_lock_queues();
while ((p = TAILQ_FIRST(&object->memq)) != NULL) {
KASSERT(!p->busy && (p->oflags & VPO_BUSY) == 0,
("vm_object_terminate: freeing busy page %p "
"p->busy = %d, p->oflags %x\n", p, p->busy, p->oflags));
+ vm_page_lock(p);
+ vm_page_lock_queues();
if (p->wire_count == 0) {
vm_page_free(p);
cnt.v_pfree++;
} else {
vm_page_remove(p);
}
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
}
- vm_page_unlock_queues();
#if VM_NRESERVLEVEL > 0
if (__predict_false(!LIST_EMPTY(&object->rvq)))
@@ -772,6 +774,7 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int
int pagerflags;
int curgeneration;
+ mtx_assert(&vm_page_queue_mtx, MA_NOTOWNED);
VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
if ((object->flags & OBJ_MIGHTBEDIRTY) == 0)
return;
@@ -789,7 +792,6 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int
tend = end;
}
- vm_page_lock_queues();
/*
* If the caller is smart and only msync()s a range he knows is
* dirty, we may be able to avoid an object scan. This results in
@@ -818,13 +820,19 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int
++tscan;
continue;
}
+ vm_page_lock(p);
+ vm_page_lock_queues();
vm_page_test_dirty(p);
if (p->dirty == 0) {
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
if (--scanlimit == 0)
break;
++tscan;
continue;
}
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
/*
* If we have been asked to skip nosync pages and
* this is a nosync page, we can't continue.
@@ -842,6 +850,7 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int
* page (i.e. had to sleep).
*/
tscan += vm_object_page_collect_flush(object, p, curgeneration, pagerflags);
+
}
/*
@@ -851,7 +860,6 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int
* return immediately.
*/
if (tscan >= tend && (tstart || tend < object->size)) {
- vm_page_unlock_queues();
vm_object_clear_flag(object, OBJ_CLEANING);
return;
}
@@ -871,8 +879,13 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int
p->oflags |= VPO_CLEANCHK;
if ((flags & OBJPC_NOSYNC) && (p->oflags & VPO_NOSYNC))
clearobjflags = 0;
- else
+ else {
+ vm_page_lock(p);
+ vm_page_lock_queues();
pmap_remove_write(p);
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
+ }
}
if (clearobjflags && (tstart == 0) && (tend == object->size))
@@ -895,12 +908,17 @@ again:
continue;
}
+ vm_page_lock(p);
+ vm_page_lock_queues();
vm_page_test_dirty(p);
if (p->dirty == 0) {
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
p->oflags &= ~VPO_CLEANCHK;
continue;
}
-
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
/*
* If we have been asked to skip nosync pages and this is a
* nosync page, skip it. Note that the object flags were
@@ -923,12 +941,10 @@ again:
* Try to optimize the next page. If we can't we pick up
* our (random) scan where we left off.
*/
- if (msync_flush_flags & MSYNC_FLUSH_SOFTSEQ) {
+ if (msync_flush_flags & MSYNC_FLUSH_SOFTSEQ)
if ((p = vm_page_lookup(object, pi + n)) != NULL)
goto again;
- }
}
- vm_page_unlock_queues();
#if 0
VOP_FSYNC(vp, (pagerflags & VM_PAGER_PUT_SYNC)?MNT_WAIT:0, curproc);
#endif
@@ -950,10 +966,11 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration,
vm_page_t mab[vm_pageout_page_count];
vm_page_t ma[vm_pageout_page_count];
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ mtx_assert(&vm_page_queue_mtx, MA_NOTOWNED);
+ vm_page_lock_assert(p, MA_NOTOWNED);
+ VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
pi = p->pindex;
while (vm_page_sleep_if_busy(p, TRUE, "vpcwai")) {
- vm_page_lock_queues();
if (object->generation != curgeneration) {
return(0);
}
@@ -968,11 +985,17 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration,
(tp->oflags & VPO_CLEANCHK) == 0) ||
(tp->busy != 0))
break;
+ vm_page_lock(tp);
+ vm_page_lock_queues();
vm_page_test_dirty(tp);
if (tp->dirty == 0) {
+ vm_page_unlock(tp);
+ vm_page_unlock_queues();
tp->oflags &= ~VPO_CLEANCHK;
break;
}
+ vm_page_unlock(tp);
+ vm_page_unlock_queues();
maf[ i - 1 ] = tp;
maxf++;
continue;
@@ -992,11 +1015,17 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration,
(tp->oflags & VPO_CLEANCHK) == 0) ||
(tp->busy != 0))
break;
+ vm_page_lock(tp);
+ vm_page_lock_queues();
vm_page_test_dirty(tp);
if (tp->dirty == 0) {
+ vm_page_unlock_queues();
+ vm_page_unlock(tp);
tp->oflags &= ~VPO_CLEANCHK;
break;
}
+ vm_page_unlock_queues();
+ vm_page_unlock(tp);
mab[ i - 1 ] = tp;
maxb++;
continue;
@@ -1022,7 +1051,11 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration,
vm_pageout_flush(ma, runlen, pagerflags);
for (i = 0; i < runlen; i++) {
if (ma[i]->dirty) {
+ vm_page_lock(ma[i]);
+ vm_page_lock_queues();
pmap_remove_write(ma[i]);
+ vm_page_unlock_queues();
+ vm_page_unlock(ma[i]);
ma[i]->oflags |= VPO_CLEANCHK;
/*
@@ -1162,7 +1195,8 @@ shadowlookup:
(tobject->flags & OBJ_ONEMAPPING) == 0) {
goto unlock_tobject;
}
- }
+ } else if (tobject->type == OBJT_PHYS)
+ goto unlock_tobject;
m = vm_page_lookup(tobject, tpindex);
if (m == NULL && advise == MADV_WILLNEED) {
/*
@@ -1189,19 +1223,16 @@ shadowlookup:
VM_OBJECT_UNLOCK(tobject);
tobject = backing_object;
goto shadowlookup;
- }
+ } else if (m->valid != VM_PAGE_BITS_ALL)
+ goto unlock_tobject;
/*
- * If the page is busy or not in a normal active state,
- * we skip it. If the page is not managed there are no
- * page queues to mess with. Things can break if we mess
- * with pages in any of the below states.
+ * If the page is not in a normal state, skip it.
*/
+ vm_page_lock(m);
vm_page_lock_queues();
- if (m->hold_count ||
- m->wire_count ||
- (m->flags & PG_UNMANAGED) ||
- m->valid != VM_PAGE_BITS_ALL) {
+ if (m->hold_count != 0 || m->wire_count != 0) {
vm_page_unlock_queues();
+ vm_page_unlock(m);
goto unlock_tobject;
}
if ((m->oflags & VPO_BUSY) || m->busy) {
@@ -1213,6 +1244,7 @@ shadowlookup:
*/
vm_page_flag_set(m, PG_REFERENCED);
vm_page_unlock_queues();
+ vm_page_unlock(m);
if (object != tobject)
VM_OBJECT_UNLOCK(object);
m->oflags |= VPO_WANTED;
@@ -1247,6 +1279,7 @@ shadowlookup:
vm_page_dontneed(m);
}
vm_page_unlock_queues();
+ vm_page_unlock(m);
if (advise == MADV_FREE && tobject->type == OBJT_SWAP)
swap_pager_freespace(tobject, tpindex, 1);
unlock_tobject:
@@ -1409,7 +1442,6 @@ retry:
m = TAILQ_NEXT(m, listq);
}
}
- vm_page_lock_queues();
for (; m != NULL && (idx = m->pindex - offidxstart) < size;
m = m_next) {
m_next = TAILQ_NEXT(m, listq);
@@ -1422,18 +1454,18 @@ retry:
* not be changed by this operation.
*/
if ((m->oflags & VPO_BUSY) || m->busy) {
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(new_object);
m->oflags |= VPO_WANTED;
msleep(m, VM_OBJECT_MTX(orig_object), PVM, "spltwt", 0);
VM_OBJECT_LOCK(new_object);
goto retry;
}
+ vm_page_lock(m);
vm_page_rename(m, new_object, idx);
+ vm_page_unlock(m);
/* page automatically made dirty by rename and cache handled */
vm_page_busy(m);
}
- vm_page_unlock_queues();
if (orig_object->type == OBJT_SWAP) {
/*
* swap_pager_copy() can sleep, in which case the orig_object's
@@ -1601,6 +1633,7 @@ vm_object_backing_scan(vm_object_t object, int op)
* Page is out of the parent object's range, we
* can simply destroy it.
*/
+ vm_page_lock(p);
vm_page_lock_queues();
KASSERT(!pmap_page_is_mapped(p),
("freeing mapped page %p", p));
@@ -1609,6 +1642,7 @@ vm_object_backing_scan(vm_object_t object, int op)
else
vm_page_remove(p);
vm_page_unlock_queues();
+ vm_page_unlock(p);
p = next;
continue;
}
@@ -1625,6 +1659,7 @@ vm_object_backing_scan(vm_object_t object, int op)
*
* Leave the parent's page alone
*/
+ vm_page_lock(p);
vm_page_lock_queues();
KASSERT(!pmap_page_is_mapped(p),
("freeing mapped page %p", p));
@@ -1633,6 +1668,7 @@ vm_object_backing_scan(vm_object_t object, int op)
else
vm_page_remove(p);
vm_page_unlock_queues();
+ vm_page_unlock(p);
p = next;
continue;
}
@@ -1652,9 +1688,9 @@ vm_object_backing_scan(vm_object_t object, int op)
* If the page was mapped to a process, it can remain
* mapped through the rename.
*/
- vm_page_lock_queues();
+ vm_page_lock(p);
vm_page_rename(p, object, new_pindex);
- vm_page_unlock_queues();
+ vm_page_unlock(p);
/* page automatically made dirty by rename */
}
p = next;
@@ -1919,7 +1955,7 @@ again:
p = TAILQ_NEXT(p, listq);
}
}
- vm_page_lock_queues();
+
/*
* Assert: the variable p is either (1) the page with the
* least pindex greater than or equal to the parameter pindex
@@ -1938,6 +1974,8 @@ again:
* cannot be freed. They can, however, be invalidated
* if "clean_only" is FALSE.
*/
+ vm_page_lock(p);
+ vm_page_lock_queues();
if ((wirings = p->wire_count) != 0 &&
(wirings = pmap_page_wired_mappings(p)) != p->wire_count) {
/* Fictitious pages do not have managed mappings. */
@@ -1949,6 +1987,8 @@ again:
p->valid = 0;
vm_page_undirty(p);
}
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
continue;
}
if (vm_page_sleep_if_busy(p, TRUE, "vmopar"))
@@ -1957,16 +1997,20 @@ again:
("vm_object_page_remove: page %p is fictitious", p));
if (clean_only && p->valid) {
pmap_remove_write(p);
- if (p->dirty)
+ if (p->dirty) {
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
continue;
+ }
}
pmap_remove_all(p);
/* Account for removal of managed, wired mappings. */
if (wirings != 0)
p->wire_count -= wirings;
vm_page_free(p);
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
}
- vm_page_unlock_queues();
vm_object_pip_wakeup(object);
skipmemq:
if (__predict_false(object->cache != NULL))
@@ -2001,9 +2045,11 @@ vm_object_populate(vm_object_t object, vm_pindex_t start, vm_pindex_t end)
if (m == NULL)
break;
if (rv != VM_PAGER_OK) {
+ vm_page_lock(m);
vm_page_lock_queues();
vm_page_free(m);
vm_page_unlock_queues();
+ vm_page_unlock(m);
break;
}
}
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 7c149c9..cc34c1b 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$");
#include <sys/vnode.h>
#include <vm/vm.h>
+#include <vm/pmap.h>
#include <vm/vm_param.h>
#include <vm/vm_kern.h>
#include <vm/vm_object.h>
@@ -129,6 +130,24 @@ __FBSDID("$FreeBSD$");
#include <machine/md_var.h>
+#if defined(__amd64__) || defined (__i386__)
+extern struct sysctl_oid_list sysctl__vm_pmap_children;
+#else
+SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
+#endif
+
+static uint64_t pmap_tryrelock_calls;
+SYSCTL_QUAD(_vm_pmap, OID_AUTO, tryrelock_calls, CTLFLAG_RD,
+ &pmap_tryrelock_calls, 0, "Number of tryrelock calls");
+
+static int pmap_tryrelock_restart;
+SYSCTL_INT(_vm_pmap, OID_AUTO, tryrelock_restart, CTLFLAG_RD,
+ &pmap_tryrelock_restart, 0, "Number of tryrelock restarts");
+
+static int pmap_tryrelock_race;
+SYSCTL_INT(_vm_pmap, OID_AUTO, tryrelock_race, CTLFLAG_RD,
+ &pmap_tryrelock_race, 0, "Number of tryrelock pmap race cases");
+
/*
* Associated with page of user-allocatable memory is a
* page structure.
@@ -138,6 +157,8 @@ struct vpgqueues vm_page_queues[PQ_COUNT];
struct vpglocks vm_page_queue_lock;
struct vpglocks vm_page_queue_free_lock;
+struct vpglocks pa_lock[PA_LOCK_COUNT] __aligned(CACHE_LINE_SIZE);
+
vm_page_t vm_page_array = 0;
int vm_page_array_size = 0;
long first_page = 0;
@@ -158,6 +179,43 @@ CTASSERT(sizeof(u_long) >= 8);
#endif
/*
+ * Try to acquire a physical address lock while a pmap is locked. If we
+ * fail to trylock we unlock and lock the pmap directly and cache the
+ * locked pa in *locked. The caller should then restart their loop in case
+ * the virtual to physical mapping has changed.
+ */
+int
+vm_page_pa_tryrelock(pmap_t pmap, vm_paddr_t pa, vm_paddr_t *locked)
+{
+ vm_paddr_t lockpa;
+ uint32_t gen_count;
+
+ gen_count = pmap->pm_gen_count;
+ atomic_add_long((volatile long *)&pmap_tryrelock_calls, 1);
+ lockpa = *locked;
+ *locked = pa;
+ if (lockpa) {
+ PA_LOCK_ASSERT(lockpa, MA_OWNED);
+ if (PA_LOCKPTR(pa) == PA_LOCKPTR(lockpa))
+ return (0);
+ PA_UNLOCK(lockpa);
+ }
+ if (PA_TRYLOCK(pa))
+ return (0);
+ PMAP_UNLOCK(pmap);
+ atomic_add_int((volatile int *)&pmap_tryrelock_restart, 1);
+ PA_LOCK(pa);
+ PMAP_LOCK(pmap);
+
+ if (pmap->pm_gen_count != gen_count + 1) {
+ pmap->pm_retries++;
+ atomic_add_int((volatile int *)&pmap_tryrelock_race, 1);
+ return (EAGAIN);
+ }
+ return (0);
+}
+
+/*
* vm_set_page_size:
*
* Sets the page size, perhaps based upon the memory
@@ -271,6 +329,11 @@ vm_page_startup(vm_offset_t vaddr)
mtx_init(&vm_page_queue_free_mtx, "vm page queue free mutex", NULL,
MTX_DEF);
+ /* Setup page locks. */
+ for (i = 0; i < PA_LOCK_COUNT; i++)
+ mtx_init(&pa_lock[i].data, "page lock", NULL,
+ MTX_DEF | MTX_RECURSE | MTX_DUPOK);
+
/*
* Initialize the queue headers for the hold queue, the active queue,
* and the inactive queue.
@@ -489,7 +552,7 @@ void
vm_page_hold(vm_page_t mem)
{
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(mem, MA_OWNED);
mem->hold_count++;
}
@@ -497,11 +560,14 @@ void
vm_page_unhold(vm_page_t mem)
{
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(mem, MA_OWNED);
--mem->hold_count;
KASSERT(mem->hold_count >= 0, ("vm_page_unhold: hold count < 0!!!"));
- if (mem->hold_count == 0 && VM_PAGE_INQUEUE2(mem, PQ_HOLD))
+ if (mem->hold_count == 0 && VM_PAGE_INQUEUE2(mem, PQ_HOLD)) {
+ vm_page_lock_queues();
vm_page_free_toq(mem);
+ vm_page_unlock_queues();
+ }
}
/*
@@ -533,7 +599,7 @@ vm_page_free_zero(vm_page_t m)
/*
* vm_page_sleep:
*
- * Sleep and release the page queues lock.
+ * Sleep and release the page and page queues locks.
*
* The object containing the given page must be locked.
*/
@@ -542,10 +608,10 @@ vm_page_sleep(vm_page_t m, const char *msg)
{
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
- if (!mtx_owned(&vm_page_queue_mtx))
- vm_page_lock_queues();
- vm_page_flag_set(m, PG_REFERENCED);
- vm_page_unlock_queues();
+ if (mtx_owned(&vm_page_queue_mtx))
+ vm_page_unlock_queues();
+ if (mtx_owned(vm_page_lockptr(m)))
+ vm_page_unlock(m);
/*
* It's possible that while we sleep, the page will get
@@ -724,6 +790,8 @@ vm_page_remove(vm_page_t m)
vm_object_t object;
vm_page_t root;
+ if ((m->flags & PG_UNMANAGED) == 0)
+ vm_page_lock_assert(m, MA_OWNED);
if ((object = m->object) == NULL)
return;
VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
@@ -731,7 +799,6 @@ vm_page_remove(vm_page_t m)
m->oflags &= ~VPO_BUSY;
vm_page_flash(m);
}
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
/*
* Now remove from the object's list of backed pages.
@@ -1318,6 +1385,7 @@ vm_page_activate(vm_page_t m)
{
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(m, MA_OWNED);
if (VM_PAGE_GETKNOWNQUEUE2(m) != PQ_ACTIVE) {
vm_pageq_remove(m);
if (m->wire_count == 0 && (m->flags & PG_UNMANAGED) == 0) {
@@ -1425,6 +1493,7 @@ vm_page_free_toq(vm_page_t m)
panic("vm_page_free: freeing wired page");
}
if (m->hold_count != 0) {
+ vm_page_lock_assert(m, MA_OWNED);
m->flags &= ~PG_ZERO;
vm_page_enqueue(PQ_HOLD, m);
} else {
@@ -1463,7 +1532,7 @@ vm_page_free_toq(vm_page_t m)
* another map, removing it from paging queues
* as necessary.
*
- * The page queues must be locked.
+ * The page must be locked.
* This routine may not block.
*/
void
@@ -1475,12 +1544,15 @@ vm_page_wire(vm_page_t m)
* and only unqueue the page if it is on some queue (if it is unmanaged
* it is already off the queues).
*/
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(m, MA_OWNED);
if (m->flags & PG_FICTITIOUS)
return;
if (m->wire_count == 0) {
- if ((m->flags & PG_UNMANAGED) == 0)
+ if ((m->flags & PG_UNMANAGED) == 0) {
+ vm_page_lock_queues();
vm_pageq_remove(m);
+ vm_page_unlock_queues();
+ }
atomic_add_int(&cnt.v_wire_count, 1);
}
m->wire_count++;
@@ -1512,28 +1584,31 @@ vm_page_wire(vm_page_t m)
* be placed in the cache - for example, just after dirtying a page.
* dirty pages in the cache are not allowed.
*
- * The page queues must be locked.
+ * The page must be locked.
* This routine may not block.
*/
void
vm_page_unwire(vm_page_t m, int activate)
{
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ if ((m->flags & PG_UNMANAGED) == 0)
+ vm_page_lock_assert(m, MA_OWNED);
if (m->flags & PG_FICTITIOUS)
return;
if (m->wire_count > 0) {
m->wire_count--;
if (m->wire_count == 0) {
atomic_subtract_int(&cnt.v_wire_count, 1);
- if (m->flags & PG_UNMANAGED) {
- ;
- } else if (activate)
+ if ((m->flags & PG_UNMANAGED) != 0)
+ return;
+ vm_page_lock_queues();
+ if (activate)
vm_page_enqueue(PQ_ACTIVE, m);
else {
vm_page_flag_clear(m, PG_WINATCFLS);
vm_page_enqueue(PQ_INACTIVE, m);
}
+ vm_page_unlock_queues();
}
} else {
panic("vm_page_unwire: invalid wire count: %d", m->wire_count);
@@ -1556,6 +1631,7 @@ _vm_page_deactivate(vm_page_t m, int athead)
{
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(m, MA_OWNED);
/*
* Ignore if already inactive.
@@ -1590,6 +1666,7 @@ vm_page_try_to_cache(vm_page_t m)
{
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(m, MA_OWNED);
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if (m->dirty || m->hold_count || m->busy || m->wire_count ||
(m->oflags & VPO_BUSY) || (m->flags & PG_UNMANAGED)) {
@@ -1613,6 +1690,7 @@ vm_page_try_to_free(vm_page_t m)
{
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(m, MA_OWNED);
if (m->object != NULL)
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if (m->dirty || m->hold_count || m->busy || m->wire_count ||
@@ -1640,6 +1718,7 @@ vm_page_cache(vm_page_t m)
vm_page_t root;
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(m, MA_OWNED);
object = m->object;
VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
if ((m->flags & PG_UNMANAGED) || (m->oflags & VPO_BUSY) || m->busy ||
@@ -1772,6 +1851,8 @@ vm_page_dontneed(vm_page_t m)
int head;
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(m, MA_OWNED);
+ VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
dnw = ++dnweight;
/*
@@ -1826,15 +1907,25 @@ vm_page_grab(vm_object_t object, vm_pindex_t pindex, int allocflags)
VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
retrylookup:
if ((m = vm_page_lookup(object, pindex)) != NULL) {
- if (vm_page_sleep_if_busy(m, TRUE, "pgrbwt")) {
+ if ((m->oflags & VPO_BUSY) != 0 || m->busy != 0) {
+ if ((allocflags & VM_ALLOC_RETRY) != 0) {
+ /*
+ * Reference the page before unlocking and
+ * sleeping so that the page daemon is less
+ * likely to reclaim it.
+ */
+ vm_page_lock_queues();
+ vm_page_flag_set(m, PG_REFERENCED);
+ }
+ vm_page_sleep(m, "pgrbwt");
if ((allocflags & VM_ALLOC_RETRY) == 0)
return (NULL);
goto retrylookup;
} else {
if ((allocflags & VM_ALLOC_WIRED) != 0) {
- vm_page_lock_queues();
+ vm_page_lock(m);
vm_page_wire(m);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
}
if ((allocflags & VM_ALLOC_NOBUSY) == 0)
vm_page_busy(m);
@@ -2133,6 +2224,7 @@ vm_page_cowfault(vm_page_t m)
vm_object_t object;
vm_pindex_t pindex;
+ vm_page_lock_assert(m, MA_OWNED);
object = m->object;
VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
KASSERT(object->paging_in_progress != 0,
@@ -2142,22 +2234,23 @@ vm_page_cowfault(vm_page_t m)
retry_alloc:
pmap_remove_all(m);
+ vm_page_unlock_queues();
vm_page_remove(m);
mnew = vm_page_alloc(object, pindex, VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY);
if (mnew == NULL) {
vm_page_insert(m, object, pindex);
- vm_page_unlock_queues();
+ vm_page_unlock(m);
VM_OBJECT_UNLOCK(object);
VM_WAIT;
VM_OBJECT_LOCK(object);
if (m == vm_page_lookup(object, pindex)) {
+ vm_page_lock(m);
vm_page_lock_queues();
goto retry_alloc;
} else {
/*
* Page disappeared during the wait.
*/
- vm_page_lock_queues();
return;
}
}
@@ -2168,7 +2261,12 @@ vm_page_cowfault(vm_page_t m)
* waiting to allocate a page. If so, put things back
* the way they were
*/
+ vm_page_unlock(m);
+ vm_page_lock(mnew);
+ vm_page_lock_queues();
vm_page_free(mnew);
+ vm_page_unlock_queues();
+ vm_page_unlock(mnew);
vm_page_insert(m, object, pindex);
} else { /* clear COW & copy page */
if (!so_zerocp_fullpage)
@@ -2177,6 +2275,7 @@ vm_page_cowfault(vm_page_t m)
vm_page_dirty(mnew);
mnew->wire_count = m->wire_count - m->cow;
m->wire_count = m->cow;
+ vm_page_unlock(m);
}
}
@@ -2184,7 +2283,7 @@ void
vm_page_cowclear(vm_page_t m)
{
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(m, MA_OWNED);
if (m->cow) {
m->cow--;
/*
@@ -2200,11 +2299,13 @@ int
vm_page_cowsetup(vm_page_t m)
{
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(m, MA_OWNED);
if (m->cow == USHRT_MAX - 1)
return (EBUSY);
m->cow++;
+ vm_page_lock_queues();
pmap_remove_write(m);
+ vm_page_unlock_queues();
return (0);
}
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index 662af98..da4d42a 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -90,20 +90,21 @@
* and sundry status bits.
*
* Fields in this structure are locked either by the lock on the
- * object that the page belongs to (O) or by the lock on the page
- * queues (P).
+ * object that the page belongs to (O), its corresponding page lock (P),
+ * or by the lock on the page queues (Q).
+ *
*/
TAILQ_HEAD(pglist, vm_page);
struct vm_page {
- TAILQ_ENTRY(vm_page) pageq; /* queue info for FIFO queue or free list (P) */
+ TAILQ_ENTRY(vm_page) pageq; /* queue info for FIFO queue or free list (Q) */
TAILQ_ENTRY(vm_page) listq; /* pages in same object (O) */
struct vm_page *left; /* splay tree link (O) */
struct vm_page *right; /* splay tree link (O) */
vm_object_t object; /* which object am I in (O,P)*/
- vm_pindex_t pindex; /* offset into object (O,P) */
+ vm_pindex_t pindex; /* offset into object (O,Q) */
vm_paddr_t phys_addr; /* physical address of page */
struct md_page md; /* machine dependant stuff */
uint8_t queue; /* page queue index */
@@ -111,11 +112,11 @@ struct vm_page {
u_short flags; /* see below */
uint8_t order; /* index of the buddy queue */
uint8_t pool;
- u_short cow; /* page cow mapping count */
- u_int wire_count; /* wired down maps refs (P) */
- short hold_count; /* page hold count */
+ u_short cow; /* page cow mapping count (Q) */
+ u_int wire_count; /* wired down maps refs (Q) */
+ short hold_count; /* page hold count (P) */
u_short oflags; /* page flags (O) */
- u_char act_count; /* page usage count */
+ u_char act_count; /* page usage count (Q) */
u_char busy; /* page busy count (O) */
/* NOTE that these must support one bit per DEV_BSIZE in a page!!! */
/* so, on normal X86 kernels, they must be at least 8 bits wide */
@@ -177,9 +178,35 @@ struct vpglocks {
} __aligned(CACHE_LINE_SIZE);
extern struct vpglocks vm_page_queue_free_lock;
+extern struct vpglocks pa_lock[];
-#define vm_page_queue_free_mtx vm_page_queue_free_lock.data
+#if defined(__arm__)
+#define PDRSHIFT PDR_SHIFT
+#elif !defined(PDRSHIFT)
+#define PDRSHIFT 21
+#endif
+#define pa_index(pa) ((pa) >> PDRSHIFT)
+#define PA_LOCKPTR(pa) &pa_lock[pa_index((pa)) % PA_LOCK_COUNT].data
+#define PA_LOCKOBJPTR(pa) ((struct lock_object *)PA_LOCKPTR((pa)))
+#define PA_LOCK(pa) mtx_lock(PA_LOCKPTR(pa))
+#define PA_TRYLOCK(pa) mtx_trylock(PA_LOCKPTR(pa))
+#define PA_UNLOCK(pa) mtx_unlock(PA_LOCKPTR(pa))
+#define PA_UNLOCK_COND(pa) \
+ do { \
+ if (pa) \
+ PA_UNLOCK(pa); \
+ } while (0)
+
+#define PA_LOCK_ASSERT(pa, a) mtx_assert(PA_LOCKPTR(pa), (a))
+
+#define vm_page_lockptr(m) (PA_LOCKPTR(VM_PAGE_TO_PHYS((m))))
+#define vm_page_lock(m) mtx_lock(vm_page_lockptr((m)))
+#define vm_page_unlock(m) mtx_unlock(vm_page_lockptr((m)))
+#define vm_page_trylock(m) mtx_trylock(vm_page_lockptr((m)))
+#define vm_page_lock_assert(m, a) mtx_assert(vm_page_lockptr((m)), (a))
+
+#define vm_page_queue_free_mtx vm_page_queue_free_lock.data
/*
* These are the flags defined for vm_page.
*
@@ -324,6 +351,7 @@ void vm_page_dontneed(vm_page_t);
void vm_page_deactivate (vm_page_t);
void vm_page_insert (vm_page_t, vm_object_t, vm_pindex_t);
vm_page_t vm_page_lookup (vm_object_t, vm_pindex_t);
+int vm_page_pa_tryrelock(pmap_t, vm_paddr_t, vm_paddr_t *);
void vm_page_remove (vm_page_t);
void vm_page_rename (vm_page_t, vm_object_t, vm_pindex_t);
void vm_page_requeue(vm_page_t m);
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 735beee..9921a84 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -252,7 +252,9 @@ vm_pageout_fallback_object_lock(vm_page_t m, vm_page_t *next)
TAILQ_INSERT_AFTER(&vm_page_queues[queue].pl,
m, &marker, pageq);
vm_page_unlock_queues();
+ vm_page_unlock(m);
VM_OBJECT_LOCK(object);
+ vm_page_lock(m);
vm_page_lock_queues();
/* Page queue might have changed. */
@@ -275,8 +277,7 @@ vm_pageout_fallback_object_lock(vm_page_t m, vm_page_t *next)
* late and we cannot do anything that will mess with the page.
*/
static int
-vm_pageout_clean(m)
- vm_page_t m;
+vm_pageout_clean(vm_page_t m)
{
vm_object_t object;
vm_page_t mc[2*vm_pageout_page_count];
@@ -284,7 +285,8 @@ vm_pageout_clean(m)
int ib, is, page_base;
vm_pindex_t pindex = m->pindex;
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ vm_page_lock_assert(m, MA_NOTOWNED);
+ vm_page_lock(m);
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
/*
@@ -301,6 +303,7 @@ vm_pageout_clean(m)
*/
if ((m->hold_count != 0) ||
((m->busy != 0) || (m->oflags & VPO_BUSY))) {
+ vm_page_unlock(m);
return 0;
}
@@ -347,13 +350,19 @@ more:
ib = 0;
break;
}
+ vm_page_lock(p);
+ vm_page_lock_queues();
vm_page_test_dirty(p);
if (p->dirty == 0 ||
p->queue != PQ_INACTIVE ||
p->hold_count != 0) { /* may be undergoing I/O */
+ vm_page_unlock(p);
+ vm_page_unlock_queues();
ib = 0;
break;
}
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
mc[--page_base] = p;
++pageout_count;
++ib;
@@ -374,12 +383,18 @@ more:
if ((p->oflags & VPO_BUSY) || p->busy) {
break;
}
+ vm_page_lock(p);
+ vm_page_lock_queues();
vm_page_test_dirty(p);
if (p->dirty == 0 ||
p->queue != PQ_INACTIVE ||
p->hold_count != 0) { /* may be undergoing I/O */
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
break;
}
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
mc[page_base + pageout_count] = p;
++pageout_count;
++is;
@@ -393,6 +408,7 @@ more:
if (ib && pageout_count < vm_pageout_page_count)
goto more;
+ vm_page_unlock(m);
/*
* we allow reads during pageouts...
*/
@@ -416,8 +432,9 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags)
int numpagedout = 0;
int i;
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
+ mtx_assert(&vm_page_queue_mtx, MA_NOTOWNED);
+
/*
* Initiate I/O. Bump the vm_page_t->busy counter and
* mark the pages read-only.
@@ -433,17 +450,21 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags)
("vm_pageout_flush: partially invalid page %p index %d/%d",
mc[i], i, count));
vm_page_io_start(mc[i]);
+ vm_page_lock(mc[i]);
+ vm_page_lock_queues();
pmap_remove_write(mc[i]);
+ vm_page_unlock(mc[i]);
+ vm_page_unlock_queues();
}
- vm_page_unlock_queues();
vm_object_pip_add(object, count);
vm_pager_put_pages(object, mc, count, flags, pageout_status);
- vm_page_lock_queues();
for (i = 0; i < count; i++) {
vm_page_t mt = mc[i];
+ vm_page_lock(mt);
+ vm_page_lock_queues();
KASSERT(pageout_status[i] == VM_PAGER_PEND ||
(mt->flags & PG_WRITEABLE) == 0,
("vm_pageout_flush: page %p is not write protected", mt));
@@ -485,6 +506,8 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags)
if (vm_page_count_severe())
vm_page_try_to_cache(mt);
}
+ vm_page_unlock_queues();
+ vm_page_unlock(mt);
}
return numpagedout;
}
@@ -508,17 +531,17 @@ vm_pageout_object_deactivate_pages(pmap, first_object, desired)
{
vm_object_t backing_object, object;
vm_page_t p, next;
- int actcount, rcount, remove_mode;
+ int actcount, remove_mode;
VM_OBJECT_LOCK_ASSERT(first_object, MA_OWNED);
if (first_object->type == OBJT_DEVICE ||
- first_object->type == OBJT_SG ||
- first_object->type == OBJT_PHYS)
+ first_object->type == OBJT_SG)
return;
for (object = first_object;; object = backing_object) {
if (pmap_resident_count(pmap) <= desired)
goto unlock_return;
- if (object->paging_in_progress)
+ VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
+ if (object->type == OBJT_PHYS || object->paging_in_progress)
goto unlock_return;
remove_mode = 0;
@@ -527,22 +550,23 @@ vm_pageout_object_deactivate_pages(pmap, first_object, desired)
/*
* scan the objects entire memory queue
*/
- rcount = object->resident_page_count;
p = TAILQ_FIRST(&object->memq);
- vm_page_lock_queues();
- while (p && (rcount-- > 0)) {
- if (pmap_resident_count(pmap) <= desired) {
- vm_page_unlock_queues();
+ while (p != NULL) {
+ if (pmap_resident_count(pmap) <= desired)
goto unlock_return;
- }
next = TAILQ_NEXT(p, listq);
+ if ((p->oflags & VPO_BUSY) != 0 || p->busy != 0) {
+ p = next;
+ continue;
+ }
+ vm_page_lock(p);
+ vm_page_lock_queues();
cnt.v_pdpages++;
if (p->wire_count != 0 ||
p->hold_count != 0 ||
- p->busy != 0 ||
- (p->oflags & VPO_BUSY) ||
- (p->flags & PG_UNMANAGED) ||
!pmap_page_exists_quick(pmap, p)) {
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
p = next;
continue;
}
@@ -576,9 +600,10 @@ vm_pageout_object_deactivate_pages(pmap, first_object, desired)
} else if (p->queue == PQ_INACTIVE) {
pmap_remove_all(p);
}
+ vm_page_unlock_queues();
+ vm_page_unlock(p);
p = next;
}
- vm_page_unlock_queues();
if ((backing_object = object->backing_object) == NULL)
goto unlock_return;
VM_OBJECT_LOCK(backing_object);
@@ -745,7 +770,6 @@ rescan0:
}
next = TAILQ_NEXT(m, pageq);
- object = m->object;
/*
* skip marker pages
@@ -753,26 +777,35 @@ rescan0:
if (m->flags & PG_MARKER)
continue;
+ if (!vm_page_trylock(m)) {
+ addl_page_shortage++;
+ continue;
+ }
+
/*
* A held page may be undergoing I/O, so skip it.
*/
- if (m->hold_count) {
+ if (m->hold_count || (object = m->object) == NULL) {
+ vm_page_unlock(m);
vm_page_requeue(m);
addl_page_shortage++;
continue;
}
+
/*
* Don't mess with busy pages, keep in the front of the
* queue, most likely are being paged out.
*/
if (!VM_OBJECT_TRYLOCK(object) &&
(!vm_pageout_fallback_object_lock(m, &next) ||
- m->hold_count != 0)) {
+ m->hold_count != 0)) {
VM_OBJECT_UNLOCK(object);
+ vm_page_unlock(m);
addl_page_shortage++;
continue;
}
if (m->busy || (m->oflags & VPO_BUSY)) {
+ vm_page_unlock(m);
VM_OBJECT_UNLOCK(object);
addl_page_shortage++;
continue;
@@ -801,6 +834,7 @@ rescan0:
vm_page_activate(m);
VM_OBJECT_UNLOCK(object);
m->act_count += (actcount + ACT_ADVANCE);
+ vm_page_unlock(m);
continue;
}
@@ -816,6 +850,7 @@ rescan0:
vm_page_activate(m);
VM_OBJECT_UNLOCK(object);
m->act_count += (actcount + ACT_ADVANCE + 1);
+ vm_page_unlock(m);
continue;
}
@@ -901,6 +936,7 @@ rescan0:
* Those objects are in a "rundown" state.
*/
if (!swap_pageouts_ok || (object->flags & OBJ_DEAD)) {
+ vm_page_unlock(m);
VM_OBJECT_UNLOCK(object);
vm_page_requeue(m);
continue;
@@ -940,6 +976,8 @@ rescan0:
* of time.
*/
if (object->type == OBJT_VNODE) {
+ vm_page_unlock_queues();
+ vm_page_unlock(m);
vp = object->handle;
if (vp->v_type == VREG &&
vn_start_write(vp, &mp, V_NOWAIT) != 0) {
@@ -947,11 +985,11 @@ rescan0:
++pageout_lock_miss;
if (object->flags & OBJ_MIGHTBEDIRTY)
vnodes_skipped++;
+ vm_page_lock_queues();
goto unlock_and_continue;
}
KASSERT(mp != NULL,
("vp %p with NULL v_mount", vp));
- vm_page_unlock_queues();
vm_object_reference_locked(object);
VM_OBJECT_UNLOCK(object);
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
@@ -966,6 +1004,7 @@ rescan0:
goto unlock_and_continue;
}
VM_OBJECT_LOCK(object);
+ vm_page_lock(m);
vm_page_lock_queues();
/*
* The page might have been moved to another
@@ -976,6 +1015,7 @@ rescan0:
if (VM_PAGE_GETQUEUE(m) != PQ_INACTIVE ||
m->object != object ||
TAILQ_NEXT(m, pageq) != &marker) {
+ vm_page_unlock(m);
if (object->flags & OBJ_MIGHTBEDIRTY)
vnodes_skipped++;
goto unlock_and_continue;
@@ -988,6 +1028,7 @@ rescan0:
* statistics are more correct if we don't.
*/
if (m->busy || (m->oflags & VPO_BUSY)) {
+ vm_page_unlock(m);
goto unlock_and_continue;
}
@@ -996,12 +1037,14 @@ rescan0:
* be undergoing I/O, so skip it
*/
if (m->hold_count) {
+ vm_page_unlock(m);
vm_page_requeue(m);
if (object->flags & OBJ_MIGHTBEDIRTY)
vnodes_skipped++;
goto unlock_and_continue;
}
}
+ vm_page_unlock(m);
/*
* If a page is dirty, then it is either being washed
@@ -1013,11 +1056,14 @@ rescan0:
* the (future) cleaned page. Otherwise we could wind
* up laundering or cleaning too many pages.
*/
+ vm_page_unlock_queues();
if (vm_pageout_clean(m) != 0) {
--page_shortage;
--maxlaunder;
}
+ vm_page_lock_queues();
unlock_and_continue:
+ vm_page_lock_assert(m, MA_NOTOWNED);
VM_OBJECT_UNLOCK(object);
if (mp != NULL) {
vm_page_unlock_queues();
@@ -1031,8 +1077,10 @@ unlock_and_continue:
next = TAILQ_NEXT(&marker, pageq);
TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl,
&marker, pageq);
+ vm_page_lock_assert(m, MA_NOTOWNED);
continue;
}
+ vm_page_unlock(m);
VM_OBJECT_UNLOCK(object);
}
@@ -1051,6 +1099,7 @@ unlock_and_continue:
*/
pcount = cnt.v_active_count;
m = TAILQ_FIRST(&vm_page_queues[PQ_ACTIVE].pl);
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
while ((m != NULL) && (pcount-- > 0) && (page_shortage > 0)) {
@@ -1063,9 +1112,14 @@ unlock_and_continue:
m = next;
continue;
}
+ if (!vm_page_trylock(m) || (object = m->object) == NULL) {
+ m = next;
+ continue;
+ }
if (!VM_OBJECT_TRYLOCK(object) &&
!vm_pageout_fallback_object_lock(m, &next)) {
VM_OBJECT_UNLOCK(object);
+ vm_page_unlock(m);
m = next;
continue;
}
@@ -1076,6 +1130,7 @@ unlock_and_continue:
if ((m->busy != 0) ||
(m->oflags & VPO_BUSY) ||
(m->hold_count != 0)) {
+ vm_page_unlock(m);
VM_OBJECT_UNLOCK(object);
vm_page_requeue(m);
m = next;
@@ -1135,6 +1190,7 @@ unlock_and_continue:
vm_page_requeue(m);
}
}
+ vm_page_unlock(m);
VM_OBJECT_UNLOCK(object);
m = next;
}
@@ -1314,15 +1370,19 @@ vm_pageout_page_stats()
("vm_pageout_page_stats: page %p isn't active", m));
next = TAILQ_NEXT(m, pageq);
- object = m->object;
-
if ((m->flags & PG_MARKER) != 0) {
m = next;
continue;
}
+ vm_page_lock_assert(m, MA_NOTOWNED);
+ if (vm_page_trylock(m) == 0 || (object = m->object) == NULL) {
+ m = next;
+ continue;
+ }
if (!VM_OBJECT_TRYLOCK(object) &&
!vm_pageout_fallback_object_lock(m, &next)) {
VM_OBJECT_UNLOCK(object);
+ vm_page_unlock(m);
m = next;
continue;
}
@@ -1333,6 +1393,7 @@ vm_pageout_page_stats()
if ((m->busy != 0) ||
(m->oflags & VPO_BUSY) ||
(m->hold_count != 0)) {
+ vm_page_unlock(m);
VM_OBJECT_UNLOCK(object);
vm_page_requeue(m);
m = next;
@@ -1369,6 +1430,7 @@ vm_pageout_page_stats()
vm_page_requeue(m);
}
}
+ vm_page_unlock(m);
VM_OBJECT_UNLOCK(object);
m = next;
}
diff --git a/sys/vm/vm_param.h b/sys/vm/vm_param.h
index 2ff2603..c404989 100644
--- a/sys/vm/vm_param.h
+++ b/sys/vm/vm_param.h
@@ -126,6 +126,14 @@ struct xswdev {
#define KERN_NOT_RECEIVER 7
#define KERN_NO_ACCESS 8
+#ifndef PA_LOCK_COUNT
+#ifdef SMP
+#define PA_LOCK_COUNT 32
+#else
+#define PA_LOCK_COUNT 1
+#endif /* !SMP */
+#endif /* !PA_LOCK_COUNT */
+
#ifndef ASSEMBLER
#ifdef _KERNEL
#define num_pages(x) \
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index aedc794..eb21c60 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -429,9 +429,11 @@ vnode_pager_setsize(vp, nsize)
* bits. This would prevent bogus_page
* replacement from working properly.
*/
+ vm_page_lock(m);
vm_page_lock_queues();
vm_page_clear_dirty(m, base, PAGE_SIZE - base);
vm_page_unlock_queues();
+ vm_page_unlock(m);
} else if ((nsize & PAGE_MASK) &&
__predict_false(object->cache != NULL)) {
vm_page_cache_free(object, OFF_TO_IDX(nsize),
@@ -719,11 +721,15 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
error = VOP_BMAP(vp, foff / bsize, &bo, &reqblock, NULL, NULL);
if (error == EOPNOTSUPP) {
VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
+
for (i = 0; i < count; i++)
- if (i != reqpage)
+ if (i != reqpage) {
+ vm_page_lock(m[i]);
+ vm_page_lock_queues();
vm_page_free(m[i]);
- vm_page_unlock_queues();
+ vm_page_unlock_queues();
+ vm_page_unlock(m[i]);
+ }
PCPU_INC(cnt.v_vnodein);
PCPU_INC(cnt.v_vnodepgsin);
error = vnode_pager_input_old(object, m[reqpage]);
@@ -731,11 +737,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
return (error);
} else if (error != 0) {
VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
for (i = 0; i < count; i++)
- if (i != reqpage)
+ if (i != reqpage) {
+ vm_page_lock(m[i]);
+ vm_page_lock_queues();
vm_page_free(m[i]);
- vm_page_unlock_queues();
+ vm_page_unlock_queues();
+ vm_page_unlock(m[i]);
+ }
VM_OBJECT_UNLOCK(object);
return (VM_PAGER_ERROR);
@@ -747,11 +756,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
} else if ((PAGE_SIZE / bsize) > 1 &&
(vp->v_mount->mnt_stat.f_type != nfs_mount_type)) {
VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
for (i = 0; i < count; i++)
- if (i != reqpage)
+ if (i != reqpage) {
+ vm_page_lock(m[i]);
+ vm_page_lock_queues();
vm_page_free(m[i]);
- vm_page_unlock_queues();
+ vm_page_unlock_queues();
+ vm_page_unlock(m[i]);
+ }
VM_OBJECT_UNLOCK(object);
PCPU_INC(cnt.v_vnodein);
PCPU_INC(cnt.v_vnodepgsin);
@@ -765,11 +777,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
*/
VM_OBJECT_LOCK(object);
if (m[reqpage]->valid == VM_PAGE_BITS_ALL) {
- vm_page_lock_queues();
for (i = 0; i < count; i++)
- if (i != reqpage)
+ if (i != reqpage) {
+ vm_page_lock(m[i]);
+ vm_page_lock_queues();
vm_page_free(m[i]);
- vm_page_unlock_queues();
+ vm_page_unlock_queues();
+ vm_page_unlock(m[i]);
+ }
VM_OBJECT_UNLOCK(object);
return VM_PAGER_OK;
} else if (reqblock == -1) {
@@ -777,11 +792,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
KASSERT(m[reqpage]->dirty == 0,
("vnode_pager_generic_getpages: page %p is dirty", m));
m[reqpage]->valid = VM_PAGE_BITS_ALL;
- vm_page_lock_queues();
for (i = 0; i < count; i++)
- if (i != reqpage)
+ if (i != reqpage) {
+ vm_page_lock(m[i]);
+ vm_page_lock_queues();
vm_page_free(m[i]);
- vm_page_unlock_queues();
+ vm_page_unlock_queues();
+ vm_page_unlock(m[i]);
+ }
VM_OBJECT_UNLOCK(object);
return (VM_PAGER_OK);
}
@@ -800,11 +818,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
if (vnode_pager_addr(vp, IDX_TO_OFF(m[i]->pindex), &firstaddr,
&runpg) != 0) {
VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
for (; i < count; i++)
- if (i != reqpage)
+ if (i != reqpage) {
+ vm_page_lock(m[i]);
+ vm_page_lock_queues();
vm_page_free(m[i]);
- vm_page_unlock_queues();
+ vm_page_unlock_queues();
+ vm_page_unlock(m[i]);
+ }
VM_OBJECT_UNLOCK(object);
return (VM_PAGER_ERROR);
}
@@ -818,9 +839,11 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
(object->un_pager.vnp.vnp_size >> 32),
(uintmax_t)object->un_pager.vnp.vnp_size);
}
+ vm_page_lock(m[i]);
vm_page_lock_queues();
vm_page_free(m[i]);
vm_page_unlock_queues();
+ vm_page_unlock(m[i]);
VM_OBJECT_UNLOCK(object);
runend = i + 1;
first = runend;
@@ -829,18 +852,24 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
runend = i + runpg;
if (runend <= reqpage) {
VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
- for (j = i; j < runend; j++)
+ for (j = i; j < runend; j++) {
+ vm_page_lock(m[j]);
+ vm_page_lock_queues();
vm_page_free(m[j]);
- vm_page_unlock_queues();
+ vm_page_unlock_queues();
+ vm_page_unlock(m[j]);
+ }
VM_OBJECT_UNLOCK(object);
} else {
if (runpg < (count - first)) {
VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
- for (i = first + runpg; i < count; i++)
+ for (i = first + runpg; i < count; i++) {
+ vm_page_lock(m[i]);
+ vm_page_lock_queues();
vm_page_free(m[i]);
- vm_page_unlock_queues();
+ vm_page_unlock_queues();
+ vm_page_unlock(m[i]);
+ }
VM_OBJECT_UNLOCK(object);
count = first + runpg;
}
@@ -931,13 +960,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
relpbuf(bp, &vnode_pbuf_freecnt);
VM_OBJECT_LOCK(object);
- vm_page_lock_queues();
for (i = 0, tfoff = foff; i < count; i++, tfoff = nextoff) {
vm_page_t mt;
nextoff = tfoff + PAGE_SIZE;
mt = m[i];
+ vm_page_lock(mt);
+ vm_page_lock_queues();
if (nextoff <= object->un_pager.vnp.vnp_size) {
/*
* Read filled up entire page.
@@ -989,8 +1019,9 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
vm_page_free(mt);
}
}
+ vm_page_unlock_queues();
+ vm_page_unlock(mt);
}
- vm_page_unlock_queues();
VM_OBJECT_UNLOCK(object);
if (error) {
printf("vnode_pager_getpages: I/O read error\n");
@@ -1113,10 +1144,12 @@ vnode_pager_generic_putpages(vp, m, bytecount, flags, rtvals)
maxsize = object->un_pager.vnp.vnp_size - poffset;
ncount = btoc(maxsize);
if ((pgoff = (int)maxsize & PAGE_MASK) != 0) {
+ vm_page_lock(m[ncount - 1]);
vm_page_lock_queues();
vm_page_clear_dirty(m[ncount - 1], pgoff,
PAGE_SIZE - pgoff);
vm_page_unlock_queues();
+ vm_page_unlock(m[ncount - 1]);
}
} else {
maxsize = 0;
diff --git a/tools/regression/bin/sh/builtins/locale1.0 b/tools/regression/bin/sh/builtins/locale1.0
new file mode 100644
index 0000000..93a37df
--- /dev/null
+++ b/tools/regression/bin/sh/builtins/locale1.0
@@ -0,0 +1,133 @@
+# $FreeBSD$
+# Note: this test depends on strerror() using locale.
+
+failures=0
+
+check() {
+ if ! eval "[ $1 ]"; then
+ echo "Failed: $1 at $2"
+ : $((failures += 1))
+ fi
+}
+
+unset LANG LC_ALL LC_COLLATE LC_CTYPE LC_MONETARY LC_NUMERIC LC_TIME LC_MESSAGES
+
+msgeng="No such file or directory"
+msgdut="Bestand of map niet gevonden"
+
+# Verify C locale error message.
+case $(command . /var/empty/foo 2>&1) in
+ *"$msgeng"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+# Various locale variables that should not affect the message.
+case $(LC_ALL=C command . /var/empty/foo 2>&1) in
+ *"$msgeng"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(LC_ALL=C LANG=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in
+ *"$msgeng"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(LC_ALL=C LC_MESSAGES=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in
+ *"$msgeng"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(LC_CTYPE=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in
+ *"$msgeng"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+# Verify Dutch message.
+case $(export LANG=nl_NL.ISO8859-1; command . /var/empty/foo 2>&1) in
+ *"$msgdut"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(export LC_MESSAGES=nl_NL.ISO8859-1; command . /var/empty/foo 2>&1) in
+ *"$msgdut"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(export LC_ALL=nl_NL.ISO8859-1; command . /var/empty/foo 2>&1) in
+ *"$msgdut"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(LANG=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in
+ *"$msgdut"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(LC_MESSAGES=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in
+ *"$msgdut"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(LC_ALL=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in
+ *"$msgdut"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+# Verify that command assignments do not set the locale persistently.
+case $(command . /var/empty/foo 2>&1) in
+ *"$msgeng"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(LANG=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1; command . /var/empty/foo 2>&1) in
+ *"$msgdut"*"$msgeng"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(LC_MESSAGES=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1; command . /var/empty/foo 2>&1) in
+ *"$msgdut"*"$msgeng"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(LC_ALL=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1; command . /var/empty/foo 2>&1) in
+ *"$msgdut"*"$msgeng"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+# Check special builtin; add colon invocation to avoid depending on certain fix.
+case $(LC_ALL=nl_NL.ISO8859-1 . /var/empty/foo 2>&1; :) in
+ *"$msgdut"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+# Assignments on special builtins are exported to that builtin; the export
+# is not persistent.
+case $(LC_ALL=nl_NL.ISO8859-1 . /dev/null; . /var/empty/foo 2>&1) in
+ *"$msgeng"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+case $(export LC_ALL; LC_ALL=nl_NL.ISO8859-1 . /dev/null; . /var/empty/foo 2>&1) in
+ *"$msgdut"*) ok=1 ;;
+ *) ok=0 ;;
+esac
+check '$ok -eq 1' $LINENO
+
+exit $((failures > 0))
diff --git a/tools/tools/nanobsd/nanobsd.sh b/tools/tools/nanobsd/nanobsd.sh
index ce518a5..7afb047 100644
--- a/tools/tools/nanobsd/nanobsd.sh
+++ b/tools/tools/nanobsd/nanobsd.sh
@@ -682,12 +682,12 @@ pprint() {
usage () {
(
- echo "Usage: $0 [-bikqvw] [-c config_file]"
+ echo "Usage: $0 [-biknqvw] [-c config_file]"
echo " -b suppress builds (both kernel and world)"
echo " -i suppress disk image build"
echo " -k suppress buildkernel"
echo " -n add -DNO_CLEAN to buildworld, buildkernel, etc"
- echo " -q make output more quite"
+ echo " -q make output more quiet"
echo " -v make output more verbose"
echo " -w suppress buildworld"
echo " -c specify config file"
diff --git a/usr.bin/chpass/Makefile b/usr.bin/chpass/Makefile
index a5571d7..566173e 100644
--- a/usr.bin/chpass/Makefile
+++ b/usr.bin/chpass/Makefile
@@ -38,7 +38,9 @@ MLINKS+= chpass.1 ypchpass.1 chpass.1 ypchfn.1 chpass.1 ypchsh.1
beforeinstall:
.for i in chpass chfn chsh ypchpass ypchfn ypchsh
+.if exists(${DESTDIR}${BINDIR}/$i)
-chflags noschg ${DESTDIR}${BINDIR}/$i
+.endif
.endfor
.if !defined(NO_FSCHG)
diff --git a/usr.bin/find/find.c b/usr.bin/find/find.c
index cc2d797..35ef5b2 100644
--- a/usr.bin/find/find.c
+++ b/usr.bin/find/find.c
@@ -32,15 +32,10 @@
* 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.
+ *
+ * @(#)find.c 8.5 (Berkeley) 8/5/94
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)find.c 8.5 (Berkeley) 8/5/94";
-#else
-#endif
-#endif /* not lint */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c
index 1714627..4329887 100644
--- a/usr.bin/find/function.c
+++ b/usr.bin/find/function.c
@@ -32,14 +32,10 @@
* 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.
+ *
+ * @(#)function.c 8.10 (Berkeley) 5/4/95
*/
-#ifndef lint
-#if 0
-static const char sccsid[] = "@(#)function.c 8.10 (Berkeley) 5/4/95";
-#endif
-#endif /* not lint */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
diff --git a/usr.bin/find/ls.c b/usr.bin/find/ls.c
index 88e4593..e96994b 100644
--- a/usr.bin/find/ls.c
+++ b/usr.bin/find/ls.c
@@ -29,14 +29,10 @@
* 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.
+ *
+ * @(#)ls.c 8.1 (Berkeley) 6/6/93
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)ls.c 8.1 (Berkeley) 6/6/93";
-#endif
-#endif /* not lint */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
diff --git a/usr.bin/find/main.c b/usr.bin/find/main.c
index 8e2b42c..7d4c24a 100644
--- a/usr.bin/find/main.c
+++ b/usr.bin/find/main.c
@@ -32,6 +32,8 @@
* 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.
+ *
+ * @(#)main.c 8.4 (Berkeley) 5/4/95
*/
#ifndef lint
@@ -40,12 +42,6 @@ char copyright[] =
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 5/4/95";
-#endif
-#endif /* not lint */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
diff --git a/usr.bin/find/misc.c b/usr.bin/find/misc.c
index 1532906..3696c13 100644
--- a/usr.bin/find/misc.c
+++ b/usr.bin/find/misc.c
@@ -32,15 +32,10 @@
* 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.
+ *
+ * @(#)misc.c 8.2 (Berkeley) 4/1/94
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)misc.c 8.2 (Berkeley) 4/1/94";
-#else
-#endif
-#endif /* not lint */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
diff --git a/usr.bin/find/operator.c b/usr.bin/find/operator.c
index c774efa..d1a7ea8 100644
--- a/usr.bin/find/operator.c
+++ b/usr.bin/find/operator.c
@@ -32,14 +32,10 @@
* 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.
+ *
+ * @(#)operator.c 8.1 (Berkeley) 6/6/93
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)operator.c 8.1 (Berkeley) 6/6/93";
-#endif
-#endif /* not lint */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
diff --git a/usr.bin/find/option.c b/usr.bin/find/option.c
index 7d06c91..6ae3958 100644
--- a/usr.bin/find/option.c
+++ b/usr.bin/find/option.c
@@ -32,14 +32,10 @@
* 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.
+ *
+ * @(#)option.c 8.2 (Berkeley) 4/16/94
*/
-#ifndef lint
-/*
-static char sccsid[] = "@(#)option.c 8.2 (Berkeley) 4/16/94";
-*/
-#endif /* not lint */
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
diff --git a/usr.bin/gzip/gzip.1 b/usr.bin/gzip/gzip.1
index bb1fadd..848a4b3 100644
--- a/usr.bin/gzip/gzip.1
+++ b/usr.bin/gzip/gzip.1
@@ -25,7 +25,7 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
-.Dd April 7, 2010
+.Dd April 27, 2010
.Dt GZIP 1
.Os
.Sh NAME
@@ -218,8 +218,8 @@ with unpack support written by
.An Xin LI Aq delphij@FreeBSD.org .
.Sh BUGS
According to RFC 1952, the recorded file size is stored in a 32-bit
-integer and therefore it can not represent files that is bigger than
-4GB in size. This limitation also applies to
+integer, therefore, it can not represent files larger than 4GB.
+This limitation also applies to
.Fl l
option of
.Nm
diff --git a/usr.bin/gzip/gzip.c b/usr.bin/gzip/gzip.c
index 9503762..de9fe80 100644
--- a/usr.bin/gzip/gzip.c
+++ b/usr.bin/gzip/gzip.c
@@ -1178,7 +1178,7 @@ sigint_handler(int signo __unused)
if (remove_file != NULL)
unlink(remove_file);
- exit(2);
+ _exit(2);
}
#endif
diff --git a/usr.bin/pathchk/pathchk.1 b/usr.bin/pathchk/pathchk.1
index e863955..931f82f 100644
--- a/usr.bin/pathchk/pathchk.1
+++ b/usr.bin/pathchk/pathchk.1
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 21, 2002
+.Dd May 1, 2010
.Dt PATHCHK 1
.Os
.Sh NAME
@@ -35,7 +35,7 @@
.Nd check pathnames
.Sh SYNOPSIS
.Nm
-.Op Fl p
+.Op Fl pP
.Ar pathname ...
.Sh DESCRIPTION
The
@@ -95,6 +95,16 @@ No component may start with the hyphen
.Pq Ql \&-
character.
.El
+.It Fl P
+In addition to the default or
+.Fl p
+checks, write a diagnostic for each argument that:
+.Bl -bullet
+.It
+Is empty.
+.It
+Contains a component that starts with a hyphen.
+.El
.El
.Sh EXIT STATUS
.Ex -std
@@ -104,7 +114,7 @@ other
.Tn POSIX
systems:
.Pp
-.Dl "find . -print | xargs pathchk -p"
+.Dl "find . -exec pathchk -p -- {} +"
.Sh SEE ALSO
.Xr getconf 1 ,
.Xr pathconf 2 ,
diff --git a/usr.bin/pathchk/pathchk.c b/usr.bin/pathchk/pathchk.c
index dd9768a..2d8fa59 100644
--- a/usr.bin/pathchk/pathchk.c
+++ b/usr.bin/pathchk/pathchk.c
@@ -51,6 +51,7 @@ static int portable(const char *);
static void usage(void);
static int pflag; /* Perform portability checks */
+static int Pflag; /* Check for empty paths, leading '-' */
int
main(int argc, char *argv[])
@@ -58,11 +59,14 @@ main(int argc, char *argv[])
int ch, rval;
const char *arg;
- while ((ch = getopt(argc, argv, "p")) > 0) {
+ while ((ch = getopt(argc, argv, "pP")) > 0) {
switch (ch) {
case 'p':
pflag = 1;
break;
+ case 'P':
+ Pflag = 1;
+ break;
default:
usage();
/*NOTREACHED*/
@@ -102,6 +106,15 @@ check(const char *path)
p = pathd;
+ if (Pflag && *p == '\0') {
+ warnx("%s: empty pathname", path);
+ goto bad;
+ }
+ if ((Pflag || pflag) && (*p == '-' || strstr(p, "/-") != NULL)) {
+ warnx("%s: contains a component starting with '-'", path);
+ goto bad;
+ }
+
if (!pflag) {
errno = 0;
namemax = pathconf(*p == '/' ? "/" : ".", _PC_NAME_MAX);
@@ -182,9 +195,6 @@ portable(const char *path)
"0123456789._-";
long s;
- if (*path == '-')
- return (*path);
-
s = strspn(path, charset);
if (path[s] != '\0')
return (path[s]);
diff --git a/usr.bin/script/script.c b/usr.bin/script/script.c
index 6c4e0ee..a21785a 100644
--- a/usr.bin/script/script.c
+++ b/usr.bin/script/script.c
@@ -219,23 +219,17 @@ usage(void)
void
finish(void)
{
- pid_t pid;
- int die, e, status;
+ int e, status;
- die = e = 0;
- while ((pid = wait3(&status, WNOHANG, 0)) > 0)
- if (pid == child) {
- die = 1;
- if (WIFEXITED(status))
- e = WEXITSTATUS(status);
- else if (WIFSIGNALED(status))
- e = WTERMSIG(status);
- else /* can't happen */
- e = 1;
- }
-
- if (die)
+ if (waitpid(child, &status, 0) == child) {
+ if (WIFEXITED(status))
+ e = WEXITSTATUS(status);
+ else if (WIFSIGNALED(status))
+ e = WTERMSIG(status);
+ else /* can't happen */
+ e = 1;
done(e);
+ }
}
void
diff --git a/usr.bin/tftp/Makefile b/usr.bin/tftp/Makefile
index a51afed..9be599a 100644
--- a/usr.bin/tftp/Makefile
+++ b/usr.bin/tftp/Makefile
@@ -1,9 +1,13 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
+CFLAGS=-g -Wall
+WARNS= 3
PROG= tftp
-SRCS= main.c tftp.c tftpsubs.c
+SRCS= main.c tftp.c tftp-utils.c tftp-io.c tftp-file.c tftp-transfer.c tftp-options.c
DPADD= ${LIBEDIT} ${LIBTERMCAP}
LDADD= -ledit -ltermcap
+CFLAGS+=-I${.CURDIR}/../../libexec/tftpd -I${.CURDIR}/../../usr.bin/tftp
+.PATH: ${.CURDIR}/../../libexec/tftpd
.include <bsd.prog.mk>
diff --git a/usr.bin/tftp/main.c b/usr.bin/tftp/main.c
index f01d3d8..26ca0244 100644
--- a/usr.bin/tftp/main.c
+++ b/usr.bin/tftp/main.c
@@ -54,12 +54,14 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/sysctl.h>
#include <sys/file.h>
#include <sys/param.h>
+#include <sys/stat.h>
#include <netinet/in.h>
-
#include <arpa/inet.h>
+#include <arpa/tftp.h>
#include <ctype.h>
#include <err.h>
@@ -72,119 +74,212 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
-#include "extern.h"
+#include "tftp-utils.h"
+#include "tftp-io.h"
+#include "tftp-options.h"
+#include "tftp.h"
#define MAXLINE 200
#define TIMEOUT 5 /* secs between rexmt's */
-struct sockaddr_storage peeraddr;
-int f;
-int trace;
-int verbose;
-int connected;
-char mode[32];
-char line[MAXLINE];
-int margc;
+static struct sockaddr_storage peeraddr;
+static int connected;
+static char mode[32];
+jmp_buf toplevel;
+volatile int txrx_error;
+static int peer;
+
#define MAX_MARGV 20
-char *margv[MAX_MARGV];
-jmp_buf toplevel;
-volatile int txrx_error;
-
-void get(int, char **);
-void help(int, char **);
-void intr(int);
-void modecmd(int, char **);
-void put(int, char **);
-void quit(int, char **);
-void setascii(int, char **);
-void setbinary(int, char **);
-void setpeer0(char *, const char *);
-void setpeer(int, char **);
-void setrexmt(int, char **);
-void settimeout(int, char **);
-void settrace(int, char **);
-void setverbose(int, char **);
-void status(int, char **);
+static int margc;
+static char *margv[MAX_MARGV];
+
+int verbose;
+char *port = NULL;
+
+static void get(int, char **);
+static void help(int, char **);
+static void intr(int);
+static void modecmd(int, char **);
+static void put(int, char **);
+static void quit(int, char **);
+static void setascii(int, char **);
+static void setbinary(int, char **);
+static void setpeer0(char *, const char *);
+static void setpeer(int, char **);
+static void settimeoutpacket(int, char **);
+static void settimeoutnetwork(int, char **);
+static void setdebug(int, char **);
+static void setverbose(int, char **);
+static void showstatus(int, char **);
+static void setblocksize(int, char **);
+static void setblocksize2(int, char **);
+static void setoptions(int, char **);
+static void setrollover(int, char **);
+static void setpacketdrop(int, char **);
static void command(void) __dead2;
static const char *command_prompt(void);
-static void getusage(const char *);
-static void makeargv(void);
-static void putusage(const char *);
+static void urihandling(char *URI);
+static void getusage(char *);
+static void makeargv(char *line);
+static void putusage(char *);
static void settftpmode(const char *);
-char *tail(char *);
-struct cmd *getcmd(char *);
+static char *tail(char *);
+static struct cmd *getcmd(char *);
#define HELPINDENT (sizeof("connect"))
struct cmd {
const char *name;
- char *help;
void (*handler)(int, char **);
+ const char *help;
};
-char vhelp[] = "toggle verbose mode";
-char thelp[] = "toggle packet tracing";
-char chelp[] = "connect to remote tftp";
-char qhelp[] = "exit tftp";
-char hhelp[] = "print help information";
-char shelp[] = "send file";
-char rhelp[] = "receive file";
-char mhelp[] = "set file transfer mode";
-char sthelp[] = "show current status";
-char xhelp[] = "set per-packet retransmission timeout";
-char ihelp[] = "set total retransmission timeout";
-char ashelp[] = "set mode to netascii";
-char bnhelp[] = "set mode to octet";
-
-struct cmd cmdtab[] = {
- { "connect", chelp, setpeer },
- { "mode", mhelp, modecmd },
- { "put", shelp, put },
- { "get", rhelp, get },
- { "quit", qhelp, quit },
- { "verbose", vhelp, setverbose },
- { "trace", thelp, settrace },
- { "status", sthelp, status },
- { "binary", bnhelp, setbinary },
- { "ascii", ashelp, setascii },
- { "rexmt", xhelp, setrexmt },
- { "timeout", ihelp, settimeout },
- { "?", hhelp, help },
- { NULL, NULL, NULL }
+static struct cmd cmdtab[] = {
+ { "connect", setpeer, "connect to remote tftp" },
+ { "mode", modecmd, "set file transfer mode" },
+ { "put", put, "send file" },
+ { "get", get, "receive file" },
+ { "quit", quit, "exit tftp" },
+ { "verbose", setverbose, "toggle verbose mode" },
+ { "status", showstatus, "show current status" },
+ { "binary", setbinary, "set mode to octet" },
+ { "ascii", setascii, "set mode to netascii" },
+ { "rexmt", settimeoutpacket,
+ "set per-packet retransmission timeout[-]" },
+ { "timeout", settimeoutnetwork,
+ "set total retransmission timeout" },
+ { "trace", setdebug, "enable 'debug packet'[-]" },
+ { "debug", setdebug, "enable verbose output" },
+ { "blocksize", setblocksize, "set blocksize[*]" },
+ { "blocksize2", setblocksize2, "set blocksize as a power of 2[**]" },
+ { "rollover", setrollover, "rollover after 64K packets[**]" },
+ { "options", setoptions,
+ "enable or disable RFC2347 style options" },
+ { "help", help, "print help information" },
+ { "packetdrop", setpacketdrop, "artifical packetloss feature" },
+ { "?", help, "print help information" },
+ { NULL, NULL, NULL }
+};
+
+static struct modes {
+ const char *m_name;
+ const char *m_mode;
+} modes[] = {
+ { "ascii", "netascii" },
+ { "netascii", "netascii" },
+ { "binary", "octet" },
+ { "image", "octet" },
+ { "octet", "octet" },
+ { NULL, NULL }
};
int
main(int argc, char *argv[])
{
- f = -1;
+
+ acting_as_client = 1;
+ peer = -1;
strcpy(mode, "netascii");
signal(SIGINT, intr);
if (argc > 1) {
if (setjmp(toplevel) != 0)
exit(txrx_error);
+
+ if (strncmp(argv[1], "tftp://", 7) == 0) {
+ urihandling(argv[1]);
+ exit(txrx_error);
+ }
+
setpeer(argc, argv);
}
if (setjmp(toplevel) != 0)
(void)putchar('\n');
+
+ init_options();
command();
}
-char hostname[MAXHOSTNAMELEN];
+/*
+ * RFC3617 handling of TFTP URIs:
+ *
+ * tftpURI = "tftp://" host "/" file [ mode ]
+ * mode = ";" "mode=" ( "netascii" / "octet" )
+ * file = *( unreserved / escaped )
+ * host = <as specified by RFC 2732>
+ * unreserved = <as specified in RFC 2396>
+ * escaped = <as specified in RFC 2396>
+ *
+ * We are cheating a little bit by allowing any mode as specified in the
+ * modes table defined earlier on in this file and mapping it on the real
+ * mode.
+ */
+static void
+urihandling(char *URI)
+{
+ char uri[ARG_MAX];
+ char *host = NULL;
+ char *path = NULL;
+ char *options = NULL;
+ char *mode = "octet";
+ char *s;
+ char line[MAXLINE];
+ int i;
+
+ strncpy(uri, URI, ARG_MAX);
+ host = uri + 7;
+
+ if ((s = strchr(host, '/')) == NULL) {
+ fprintf(stderr,
+ "Invalid URI: Couldn't find / after hostname\n");
+ exit(1);
+ }
+ *s = '\0';
+ path = s + 1;
+
+ if ((s = strchr(path, ';')) != NULL) {
+ *s = '\0';
+ options = s + 1;
-void
-setpeer0(char *host, const char *port)
+ if (strncmp(options, "mode=", 5) == 0) {
+ mode = options;
+ mode += 5;
+
+ for (i = 0; modes[i].m_name != NULL; i++) {
+ if (strcmp(modes[i].m_name, mode) == 0)
+ break;
+ }
+ if (modes[i].m_name == NULL) {
+ fprintf(stderr, "Invalid mode: '%s'\n", mode);
+ exit(1);
+ }
+ settftpmode(modes[i].m_mode);
+ }
+ } else {
+ settftpmode("octet");
+ }
+
+ setpeer0(host, NULL);
+
+ sprintf(line, "get %s", path);
+ makeargv(line);
+ get(margc, margv);
+}
+
+static char hostname[MAXHOSTNAMELEN];
+
+static void
+setpeer0(char *host, const char *lport)
{
struct addrinfo hints, *res0, *res;
int error;
- struct sockaddr_storage ss;
const char *cause = "unknown";
if (connected) {
- close(f);
- f = -1;
+ close(peer);
+ peer = -1;
}
connected = 0;
@@ -193,9 +288,9 @@ setpeer0(char *host, const char *port)
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_CANONNAME;
- if (!port)
- port = "tftp";
- error = getaddrinfo(host, port, &hints, &res0);
+ if (!lport)
+ lport = "tftp";
+ error = getaddrinfo(host, lport, &hints, &res0);
if (error) {
warnx("%s", gai_strerror(error));
return;
@@ -204,50 +299,53 @@ setpeer0(char *host, const char *port)
for (res = res0; res; res = res->ai_next) {
if (res->ai_addrlen > sizeof(peeraddr))
continue;
- f = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (f < 0) {
+ peer = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if (peer < 0) {
cause = "socket";
continue;
}
- memset(&ss, 0, sizeof(ss));
- ss.ss_family = res->ai_family;
- ss.ss_len = res->ai_addrlen;
- if (bind(f, (struct sockaddr *)&ss, ss.ss_len) < 0) {
+ memset(&peer_sock, 0, sizeof(peer_sock));
+ peer_sock.ss_family = res->ai_family;
+ peer_sock.ss_len = res->ai_addrlen;
+ if (bind(peer, (struct sockaddr *)&peer_sock, peer_sock.ss_len) < 0) {
cause = "bind";
- close(f);
- f = -1;
+ close(peer);
+ peer = -1;
continue;
}
break;
}
- if (f < 0)
+ if (peer < 0)
warn("%s", cause);
else {
/* res->ai_addr <= sizeof(peeraddr) is guaranteed */
- memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
+ memcpy(&peer_sock, res->ai_addr, res->ai_addrlen);
if (res->ai_canonname) {
- (void) strlcpy(hostname, res->ai_canonname,
+ (void) strncpy(hostname, res->ai_canonname,
sizeof(hostname));
} else
- (void) strlcpy(hostname, host, sizeof(hostname));
+ (void) strncpy(hostname, host, sizeof(hostname));
+ hostname[sizeof(hostname)-1] = 0;
connected = 1;
}
freeaddrinfo(res0);
}
-void
+static void
setpeer(int argc, char *argv[])
{
+ char line[MAXLINE];
if (argc < 2) {
strcpy(line, "Connect ");
printf("(to) ");
fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
- makeargv();
+ makeargv(line);
argc = margc;
argv = margv;
}
@@ -255,26 +353,14 @@ setpeer(int argc, char *argv[])
printf("usage: %s [host [port]]\n", argv[0]);
return;
}
- if (argc == 3)
+ if (argc == 3) {
+ port = argv[2];
setpeer0(argv[1], argv[2]);
- else
+ } else
setpeer0(argv[1], NULL);
}
-struct modes {
- const char *m_name;
- const char *m_mode;
-} modes[] = {
- { "ascii", "netascii" },
- { "netascii", "netascii" },
- { "binary", "octet" },
- { "image", "octet" },
- { "octet", "octet" },
-/* { "mail", "mail" }, */
- { 0, 0 }
-};
-
-void
+static void
modecmd(int argc, char *argv[])
{
struct modes *p;
@@ -298,7 +384,7 @@ modecmd(int argc, char *argv[])
printf("usage: %s [", argv[0]);
sep = " ";
- for (p = modes; p->m_name; p++) {
+ for (p = modes; p->m_name != NULL; p++) {
printf("%s%s", sep, p->m_name);
if (*sep == ' ')
sep = " | ";
@@ -307,14 +393,14 @@ modecmd(int argc, char *argv[])
return;
}
-void
+static void
setbinary(int argc __unused, char *argv[] __unused)
{
settftpmode("octet");
}
-void
+static void
setascii(int argc __unused, char *argv[] __unused)
{
@@ -324,6 +410,7 @@ setascii(int argc __unused, char *argv[] __unused)
static void
settftpmode(const char *newmode)
{
+
strcpy(mode, newmode);
if (verbose)
printf("mode set to %s\n", mode);
@@ -333,18 +420,20 @@ settftpmode(const char *newmode)
/*
* Send file(s).
*/
-void
+static void
put(int argc, char *argv[])
{
- int fd;
- int n;
- char *cp, *targ;
+ int fd;
+ int n;
+ char *cp, *targ;
+ char line[MAXLINE];
+ struct stat sb;
if (argc < 2) {
strcpy(line, "send ");
printf("(file) ");
fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
- makeargv();
+ makeargv(line);
argc = margc;
argv = margv;
}
@@ -381,10 +470,14 @@ put(int argc, char *argv[])
warn("%s", cp);
return;
}
+
+ stat(cp, &sb);
+ asprintf(&options[OPT_TSIZE].o_request, "%ju", sb.st_size);
+
if (verbose)
printf("putting %s to %s:%s [%s]\n",
- cp, hostname, targ, mode);
- xmitfile(fd, targ, mode);
+ cp, hostname, targ, mode);
+ xmitfile(peer, port, fd, targ, mode);
return;
}
/* this assumes the target is a directory */
@@ -398,36 +491,43 @@ put(int argc, char *argv[])
warn("%s", argv[n]);
continue;
}
+
+ stat(cp, &sb);
+ asprintf(&options[OPT_TSIZE].o_request, "%ju", sb.st_size);
+
if (verbose)
printf("putting %s to %s:%s [%s]\n",
- argv[n], hostname, targ, mode);
- xmitfile(fd, targ, mode);
+ argv[n], hostname, targ, mode);
+ xmitfile(peer, port, fd, targ, mode);
}
}
static void
-putusage(const char *s)
+putusage(char *s)
{
- printf("usage: %s file [[host:]remotename]\n", s);
+
+ printf("usage: %s file [remotename]\n", s);
+ printf(" %s file host:remotename\n", s);
printf(" %s file1 file2 ... fileN [[host:]remote-directory]\n", s);
}
/*
* Receive file(s).
*/
-void
+static void
get(int argc, char *argv[])
{
int fd;
int n;
char *cp;
char *src;
+ char line[MAXLINE];
if (argc < 2) {
strcpy(line, "get ");
printf("(files) ");
fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
- makeargv();
+ makeargv(line);
argc = margc;
argv = margv;
}
@@ -438,6 +538,8 @@ get(int argc, char *argv[])
if (!connected) {
for (n = 1; n < argc ; n++)
if (rindex(argv[n], ':') == 0) {
+ printf("No remote host specified and "
+ "no host given for file '%s'\n", argv[n]);
getusage(argv[0]);
return;
}
@@ -468,8 +570,8 @@ get(int argc, char *argv[])
}
if (verbose)
printf("getting from %s:%s to %s [%s]\n",
- hostname, src, cp, mode);
- recvfile(fd, src, mode);
+ hostname, src, cp, mode);
+ recvfile(peer, port, fd, src, mode);
break;
}
cp = tail(src); /* new .. jdg */
@@ -480,30 +582,31 @@ get(int argc, char *argv[])
}
if (verbose)
printf("getting from %s:%s to %s [%s]\n",
- hostname, src, cp, mode);
- recvfile(fd, src, mode);
+ hostname, src, cp, mode);
+ recvfile(peer, port, fd, src, mode);
}
}
static void
-getusage(const char *s)
+getusage(char *s)
{
- printf("usage: %s [host:]file [localname]\n", s);
+
+ printf("usage: %s file [localname]\n", s);
+ printf(" %s [host:]file [localname]\n", s);
printf(" %s [host1:]file1 [host2:]file2 ... [hostN:]fileN\n", s);
}
-int rexmtval = TIMEOUT;
-
-void
-setrexmt(int argc, char *argv[])
+static void
+settimeoutpacket(int argc, char *argv[])
{
int t;
+ char line[MAXLINE];
if (argc < 2) {
- strcpy(line, "Rexmt-timeout ");
+ strcpy(line, "Packet timeout ");
printf("(value) ");
fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
- makeargv();
+ makeargv(line);
argc = margc;
argv = margv;
}
@@ -512,24 +615,25 @@ setrexmt(int argc, char *argv[])
return;
}
t = atoi(argv[1]);
- if (t < 0)
+ if (t < 0) {
printf("%s: bad value\n", argv[1]);
- else
- rexmtval = t;
-}
+ return;
+ }
-int maxtimeout = 5 * TIMEOUT;
+ settimeouts(t, timeoutnetwork, maxtimeouts);
+}
-void
-settimeout(int argc, char *argv[])
+static void
+settimeoutnetwork(int argc, char *argv[])
{
int t;
+ char line[MAXLINE];
if (argc < 2) {
- strcpy(line, "Maximum-timeout ");
+ strcpy(line, "Network timeout ");
printf("(value) ");
fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
- makeargv();
+ makeargv(line);
argc = margc;
argv = margv;
}
@@ -538,26 +642,36 @@ settimeout(int argc, char *argv[])
return;
}
t = atoi(argv[1]);
- if (t < 0)
+ if (t < 0) {
printf("%s: bad value\n", argv[1]);
- else
- maxtimeout = t;
+ return;
+ }
+
+ settimeouts(timeoutpacket, t, maxtimeouts);
}
-void
-status(int argc __unused, char *argv[] __unused)
+static void
+showstatus(int argc __unused, char *argv[] __unused)
{
- if (connected)
- printf("Connected to %s.\n", hostname);
- else
- printf("Not connected.\n");
- printf("Mode: %s Verbose: %s Tracing: %s\n", mode,
- verbose ? "on" : "off", trace ? "on" : "off");
- printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
- rexmtval, maxtimeout);
+
+ printf("Remote host: %s\n",
+ connected ? hostname : "none specified yet");
+ printf("RFC2347 Options support: %s\n",
+ options_rfc_enabled ? "enabled" : "disabled");
+ printf("Non-RFC defined options support: %s\n",
+ options_extra_enabled ? "enabled" : "disabled");
+ printf("Mode: %s\n", mode);
+ printf("Verbose: %s\n", verbose ? "on" : "off");
+ printf("Debug: %s\n", debug_show(debug));
+ printf("Artificial packetloss: %d in 100 packets\n",
+ packetdroppercentage);
+ printf("Segment size: %d bytes\n", segsize);
+ printf("Network timeout: %d seconds\n", timeoutpacket);
+ printf("Maximum network timeout: %d seconds\n", timeoutnetwork);
+ printf("Maximum timeouts: %d \n", maxtimeouts);
}
-void
+static void
intr(int dummy __unused)
{
@@ -566,7 +680,7 @@ intr(int dummy __unused)
longjmp(toplevel, -1);
}
-char *
+static char *
tail(char *filename)
{
char *s;
@@ -583,7 +697,7 @@ tail(char *filename)
}
static const char *
-command_prompt(void)
+command_prompt()
{
return ("tftp> ");
@@ -602,6 +716,7 @@ command(void)
const char *bp;
char *cp;
int len, num, vrbose;
+ char line[MAXLINE];
vrbose = isatty(0);
if (vrbose) {
@@ -623,6 +738,7 @@ command(void)
line[len] = '\0';
history(hist, &he, H_ENTER, bp);
} else {
+ line[0] = 0;
if (fgets(line, sizeof line , stdin) == 0) {
if (feof(stdin)) {
exit(txrx_error);
@@ -635,7 +751,7 @@ command(void)
*cp = '\0';
if (line[0] == 0)
continue;
- makeargv();
+ makeargv(line);
if (margc == 0)
continue;
c = getcmd(margv[0]);
@@ -651,7 +767,7 @@ command(void)
}
}
-struct cmd *
+static struct cmd *
getcmd(char *name)
{
const char *p, *q;
@@ -683,15 +799,15 @@ getcmd(char *name)
* Slice a string up into argc/argv.
*/
static void
-makeargv(void)
+makeargv(char *line)
{
char *cp;
char **argp = margv;
margc = 0;
- if ((cp = strchr(line, '\n')))
+ if ((cp = strchr(line, '\n')) != NULL)
*cp = '\0';
- for (cp = line; margc < MAX_MARGV - 1 && *cp;) {
+ for (cp = line; margc < MAX_MARGV - 1 && *cp != '\0';) {
while (isspace(*cp))
cp++;
if (*cp == '\0')
@@ -707,16 +823,17 @@ makeargv(void)
*argp++ = 0;
}
-void
+static void
quit(int argc __unused, char *argv[] __unused)
{
+
exit(txrx_error);
}
/*
* Help command.
*/
-void
+static void
help(int argc, char *argv[])
{
struct cmd *c;
@@ -725,6 +842,10 @@ help(int argc, char *argv[])
printf("Commands may be abbreviated. Commands are:\n\n");
for (c = cmdtab; c->name; c++)
printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help);
+
+ printf("\n[-] : You shouldn't use these ones anymore.\n");
+ printf("[*] : RFC2834 options support required.\n");
+ printf("[**] : Non-standard RFC2834 option.\n");
return;
}
while (--argc > 0) {
@@ -732,24 +853,211 @@ help(int argc, char *argv[])
arg = *++argv;
c = getcmd(arg);
if (c == (struct cmd *)-1)
- printf("?Ambiguous help command %s\n", arg);
+ printf("?Ambiguous help command: %s\n", arg);
else if (c == (struct cmd *)0)
- printf("?Invalid help command %s\n", arg);
+ printf("?Invalid help command: %s\n", arg);
else
printf("%s\n", c->help);
}
}
-void
-settrace(int argc __unused, char **argv __unused)
+static void
+setverbose(int argc __unused, char *argv[] __unused)
{
- trace = !trace;
- printf("Packet tracing %s.\n", trace ? "on" : "off");
-}
-void
-setverbose(int argc __unused, char **argv __unused)
-{
verbose = !verbose;
printf("Verbose mode %s.\n", verbose ? "on" : "off");
}
+
+static void
+setoptions(int argc, char *argv[])
+{
+
+ if (argc == 2) {
+ if (strcasecmp(argv[1], "enable") == 0 ||
+ strcasecmp(argv[1], "on") == 0) {
+ options_extra_enabled = 1;
+ options_rfc_enabled = 1;
+ }
+ if (strcasecmp(argv[1], "disable") == 0 ||
+ strcasecmp(argv[1], "off") == 0) {
+ options_extra_enabled = 0;
+ options_rfc_enabled = 0;
+ }
+ if (strcasecmp(argv[1], "extra") == 0)
+ options_extra_enabled = !options_extra_enabled;
+ }
+ printf("Support for RFC2347 style options are now %s.\n",
+ options_rfc_enabled ? "enabled" : "disabled");
+ printf("Support for non-RFC defined options are now %s.\n",
+ options_extra_enabled ? "enabled" : "disabled");
+
+ printf("\nThe following options are available:\n"
+ "\toptions on : enable support for RFC2347 style options\n"
+ "\toptions off : disable support for RFC2347 style options\n"
+ "\toptions extra : toggle support for non-RFC defined options\n"
+ );
+}
+
+static void
+setrollover(int argc, char *argv[])
+{
+
+ if (argc == 2) {
+ if (strcasecmp(argv[1], "never") == 0 ||
+ strcasecmp(argv[1], "none") == 0) {
+ free(options[OPT_ROLLOVER].o_request);
+ options[OPT_ROLLOVER].o_request = NULL;
+ }
+ if (strcasecmp(argv[1], "1") == 0) {
+ free(options[OPT_ROLLOVER].o_request);
+ options[OPT_ROLLOVER].o_request = strdup("1");
+ }
+ if (strcasecmp(argv[1], "0") == 0) {
+ free(options[OPT_ROLLOVER].o_request);
+ options[OPT_ROLLOVER].o_request = strdup("0");
+ }
+ }
+ printf("Support for the rollover options is %s.\n",
+ options[OPT_ROLLOVER].o_request != NULL ? "enabled" : "disabled");
+ if (options[OPT_ROLLOVER].o_request != NULL)
+ printf("Block rollover will be to block %s.\n",
+ options[OPT_ROLLOVER].o_request);
+
+
+ printf("\nThe following rollover options are available:\n"
+ "\trollover 0 : rollover to block zero (default)\n"
+ "\trollover 1 : rollover to block one\n"
+ "\trollover never : do not support the rollover option\n"
+ "\trollover none : do not support the rollover option\n"
+ );
+}
+
+static void
+setdebug(int argc, char *argv[])
+{
+ int i;
+
+ if (argc != 1) {
+ i = 1;
+ while (i < argc)
+ debug ^= debug_find(argv[i++]);
+ }
+ printf("The following debugging is enabled: %s\n", debug_show(debug));
+
+ printf("\nThe following debugs are available:\n");
+ i = 0;
+ while (debugs[i].name != NULL) {
+ printf("\t%s\t%s\n", debugs[i].name, debugs[i].desc);
+ i++;
+ }
+}
+
+static void
+setblocksize(int argc, char *argv[])
+{
+
+ if (!options_rfc_enabled)
+ printf("RFC2347 style options are not enabled "
+ "(but proceding anyway)\n");
+
+ if (argc != 1) {
+ int size = atoi(argv[1]);
+ size_t max;
+ char maxbuffer[100];
+ int *maxdgram;
+
+ max = sizeof(maxbuffer);
+ if (sysctlbyname("net.inet.udp.maxdgram",
+ maxbuffer, &max, NULL, 0) < 0) {
+ perror("sysctl: net.inet.udp.maxdgram");
+ return;
+ }
+ maxdgram = (int *)maxbuffer;
+
+ if (size < BLKSIZE_MIN || size > BLKSIZE_MAX) {
+ printf("Blocksize should be between %d and %d bytes.\n",
+ BLKSIZE_MIN, BLKSIZE_MAX);
+ return;
+ } else if (size > *maxdgram - 4) {
+ printf("Blocksize can't be bigger than %d bytes due "
+ "to the net.inet.udp.maxdgram sysctl limitation.\n",
+ *maxdgram - 4);
+ asprintf(&options[OPT_BLKSIZE].o_request,
+ "%d", *maxdgram - 4);
+ } else {
+ asprintf(&options[OPT_BLKSIZE].o_request, "%d", size);
+ }
+ }
+ printf("Blocksize is now %s bytes.\n", options[OPT_BLKSIZE].o_request);
+}
+
+static void
+setblocksize2(int argc, char *argv[])
+{
+
+ if (!options_rfc_enabled || !options_extra_enabled)
+ printf(
+ "RFC2347 style or non-RFC defined options are not enabled "
+ "(but proceding anyway)\n");
+
+ if (argc != 1) {
+ int size = atoi(argv[1]);
+ int i;
+ size_t max;
+ char maxbuffer[100];
+ int *maxdgram;
+
+ int sizes[] = {
+ 8, 16, 32, 64, 128, 256, 512, 1024,
+ 2048, 4096, 8192, 16384, 32768, 0
+ };
+
+ max = sizeof(maxbuffer);
+ if (sysctlbyname("net.inet.udp.maxdgram",
+ maxbuffer, &max, NULL, 0) < 0) {
+ perror("sysctl: net.inet.udp.maxdgram");
+ return;
+ }
+ maxdgram = (int *)maxbuffer;
+
+ for (i = 0; sizes[i] != 0; i++) {
+ if (sizes[i] == size) break;
+ }
+ if (sizes[i] == 0) {
+ printf("Blocksize2 should be a power of two between "
+ "8 and 32768.\n");
+ return;
+ }
+
+ if (size < BLKSIZE_MIN || size > BLKSIZE_MAX) {
+ printf("Blocksize2 should be between "
+ "%d and %d bytes.\n", BLKSIZE_MIN, BLKSIZE_MAX);
+ return;
+ } else if (size > *maxdgram - 4) {
+ printf("Blocksize2 can't be bigger than %d bytes due "
+ "to the net.inet.udp.maxdgram sysctl limitation.\n",
+ *maxdgram - 4);
+ for (i = 0; sizes[i+1] != 0; i++) {
+ if (*maxdgram < sizes[i+1]) break;
+ }
+ asprintf(&options[OPT_BLKSIZE2].o_request,
+ "%d", sizes[i]);
+ } else {
+ asprintf(&options[OPT_BLKSIZE2].o_request, "%d", size);
+ }
+ }
+ printf("Blocksize2 is now %s bytes.\n",
+ options[OPT_BLKSIZE2].o_request);
+}
+
+static void
+setpacketdrop(int argc, char *argv[])
+{
+
+ if (argc != 1)
+ packetdroppercentage = atoi(argv[1]);
+
+ printf("Randomly %d in 100 packets will be dropped\n",
+ packetdroppercentage);
+}
diff --git a/usr.bin/tftp/tftp.1 b/usr.bin/tftp/tftp.1
index 8924eb5..04daa87 100644
--- a/usr.bin/tftp/tftp.1
+++ b/usr.bin/tftp/tftp.1
@@ -37,7 +37,7 @@
.Os
.Sh NAME
.Nm tftp
-.Nd "trivial file transfer program"
+.Nd trivial file transfer program
.Sh SYNOPSIS
.Nm
.Op Ar host Op Ar port
@@ -55,28 +55,26 @@ may be specified on the command line, in which case
uses
.Ar host
as the default host for future transfers (see the
-.Ic connect
+.Cm connect
command below).
.Sh COMMANDS
Once
.Nm
is running, it issues the prompt
-.Dq Li "tftp> "
+.Dq Li tftp>
and recognizes the following commands:
.Pp
-.Bl -tag -width ".Ic verbose" -compact
-.It Ic \&? Ar command-name ...
+.Bl -tag -width verbose -compact
+.It Cm \&? Ar command-name ...
Print help information.
.Pp
-.It Ic ascii
-Shorthand for
-.Ic mode Cm ascii .
+.It Cm ascii
+Shorthand for "mode ascii"
.Pp
-.It Ic binary
-Shorthand for
-.Ic mode Cm binary .
+.It Cm binary
+Shorthand for "mode binary"
.Pp
-.It Ic connect Ar host Op Ar port
+.It Cm connect Ar host Op Ar port
Set the
.Ar host
(and optionally
@@ -88,19 +86,19 @@ protocol, unlike the
.Tn FTP
protocol,
does not maintain connections between transfers; thus, the
-.Ic connect
+.Cm connect
command does not actually create a connection,
but merely remembers what host is to be used for transfers.
You do not have to use the
-.Ic connect
+.Cm connect
command; the remote host can be specified as part of the
-.Ic get
+.Cm get
or
-.Ic put
+.Cm put
commands.
.Pp
-.It Ic get Oo Ar host : Oc Ns Ar file Op Ar localname
-.It Ic get Xo
+.It Cm get Oo Ar host : Oc Ns Ar file Op Ar localname
+.It Cm get Xo
.Oo Ar host1 : Oc Ns Ar file1
.Oo Ar host2 : Oc Ns Ar file2 ...
.Oo Ar hostN : Oc Ns Ar fileN
@@ -126,18 +124,18 @@ to disambiguate the
colons used in the IPv6 address from the colon separating the host and
the filename.
.Pp
-.It Ic mode Ar transfer-mode
+.It Cm mode Ar transfer-mode
Set the mode for transfers;
.Ar transfer-mode
may be one of
-.Cm ascii
+.Em ascii
or
-.Cm binary .
+.Em binary .
The default is
-.Cm ascii .
+.Em ascii .
.Pp
-.It Ic put Ar file Op Oo Ar host : Oc Ns Ar remotename
-.It Ic put Ar file1 file2 ... fileN Op Oo Ar host : Oc Ns Ar remote-directory
+.It Cm put Ar file Op Oo Ar host : Oc Ns Ar remotename
+.It Cm put Ar file1 file2 ... fileN Op Oo Ar host : Oc Ns Ar remote-directory
Put a file or set of files to the remote host.
When
.Ar remotename
@@ -152,27 +150,27 @@ machine.
To specify an IPv6 numeric address for a
.Ar host ,
see the example under the
-.Ic get
+.Cm get
command.
.Pp
-.It Ic quit
+.It Cm quit
Exit
.Nm .
An end of file also exits.
.Pp
-.It Ic rexmt Ar retransmission-timeout
+.It Cm rexmt Ar retransmission-timeout
Set the per-packet retransmission timeout, in seconds.
.Pp
-.It Ic status
+.It Cm status
Show current status.
.Pp
-.It Ic timeout Ar total-transmission-timeout
+.It Cm timeout Ar total-transmission-timeout
Set the total transmission timeout, in seconds.
.Pp
-.It Ic trace
+.It Cm trace
Toggle packet tracing.
.Pp
-.It Ic verbose
+.It Cm verbose
Toggle verbose mode.
.El
.Sh HISTORY
diff --git a/usr.bin/tftp/tftp.c b/usr.bin/tftp/tftp.c
index 4300902..29ba2b2 100644
--- a/usr.bin/tftp/tftp.c
+++ b/usr.bin/tftp/tftp.c
@@ -45,446 +45,230 @@ __FBSDID("$FreeBSD$");
/*
* TFTP User Program -- Protocol Machines
*/
-#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/time.h>
+#include <sys/stat.h>
#include <netinet/in.h>
-#include <arpa/inet.h>
#include <arpa/tftp.h>
#include <err.h>
-#include <errno.h>
-#include <setjmp.h>
-#include <signal.h>
+#include <netdb.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#include <netdb.h>
+#include <syslog.h>
-#include "extern.h"
-#include "tftpsubs.h"
-
-extern struct sockaddr_storage peeraddr; /* filled in by main */
-extern int f; /* the opened socket */
-extern int trace;
-extern int verbose;
-extern int rexmtval;
-extern int maxtimeout;
-extern volatile int txrx_error;
-
-#define PKTSIZE SEGSIZE+4
-char ackbuf[PKTSIZE];
-int timeout;
-jmp_buf toplevel;
-jmp_buf timeoutbuf;
-
-static void nak(int, const struct sockaddr *);
-static int makerequest(int, const char *, struct tftphdr *, const char *);
-static void printstats(const char *, unsigned long);
-static void startclock(void);
-static void stopclock(void);
-static void timer(int);
-static void tpacket(const char *, struct tftphdr *, int);
-static int cmpport(const struct sockaddr *, const struct sockaddr *);
+#include "tftp.h"
+#include "tftp-file.h"
+#include "tftp-utils.h"
+#include "tftp-io.h"
+#include "tftp-transfer.h"
+#include "tftp-options.h"
/*
* Send the requested file.
*/
void
-xmitfile(int fd, const char *name, const char *mode)
+xmitfile(int peer, char *port, int fd, char *name, char *mode)
{
- struct tftphdr *ap; /* data and ack packets */
- struct tftphdr *dp;
- int n;
- volatile unsigned short block;
- volatile int size, convert;
- volatile unsigned long amount;
- struct sockaddr_storage from;
- socklen_t fromlen;
- FILE *file;
- struct sockaddr_storage peer;
+ struct tftphdr *rp;
+ int n, i;
+ uint16_t block;
+ uint32_t amount;
struct sockaddr_storage serv; /* valid server port number */
+ char recvbuffer[MAXPKTSIZE];
+ struct tftp_stats tftp_stats;
+
+ stats_init(&tftp_stats);
- startclock(); /* start stat's clock */
- dp = r_init(); /* reset fillbuf/read-ahead code */
- ap = (struct tftphdr *)ackbuf;
- file = fdopen(fd, "r");
- convert = !strcmp(mode, "netascii");
- block = 0;
- amount = 0;
- memcpy(&peer, &peeraddr, peeraddr.ss_len);
memset(&serv, 0, sizeof(serv));
+ rp = (struct tftphdr *)recvbuffer;
+
+ if (port == NULL) {
+ struct servent *se;
+ se = getservbyname("tftp", "udp");
+ ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port;
+ } else
+ ((struct sockaddr_in *)&peer_sock)->sin_port =
+ htons(atoi(port));
+
+ for (i = 0; i < 12; i++) {
+ struct sockaddr_storage from;
+
+ /* Tell the other side what we want to do */
+ if (debug&DEBUG_SIMPLE)
+ printf("Sending %s\n", name);
+
+ n = send_wrq(peer, name, mode);
+ if (n > 0) {
+ printf("Cannot send WRQ packet\n");
+ return;
+ }
- signal(SIGALRM, timer);
- do {
- if (block == 0)
- size = makerequest(WRQ, name, dp, mode) - 4;
- else {
- /* size = read(fd, dp->th_data, SEGSIZE); */
- size = readit(file, &dp, convert);
- if (size < 0) {
- nak(errno + 100, (struct sockaddr *)&peer);
- break;
- }
- dp->th_opcode = htons((u_short)DATA);
- dp->th_block = htons((u_short)block);
+ /*
+ * The first packet we receive has the new destination port
+ * we have to send the next packets to.
+ */
+ n = receive_packet(peer, recvbuffer,
+ MAXPKTSIZE, &from, timeoutpacket);
+
+ /* We got some data! */
+ if (n >= 0) {
+ ((struct sockaddr_in *)&peer_sock)->sin_port =
+ ((struct sockaddr_in *)&from)->sin_port;
+ break;
}
- timeout = 0;
- (void) setjmp(timeoutbuf);
-send_data:
- if (trace)
- tpacket("sent", dp, size + 4);
- n = sendto(f, dp, size + 4, 0,
- (struct sockaddr *)&peer, peer.ss_len);
- if (n != size + 4) {
- warn("sendto");
- txrx_error = 1;
- goto abort;
+
+ /* This should be retried */
+ if (n == RP_TIMEOUT) {
+ printf("Try %d, didn't receive answer from remote.\n",
+ i + 1);
+ continue;
}
- read_ahead(file, convert);
- for ( ; ; ) {
- alarm(rexmtval);
- do {
- fromlen = sizeof(from);
- n = recvfrom(f, ackbuf, sizeof(ackbuf), 0,
- (struct sockaddr *)&from, &fromlen);
- } while (n <= 0);
- alarm(0);
- if (n < 0) {
- warn("recvfrom");
- txrx_error = 1;
- goto abort;
- }
- if (!serv.ss_family)
- serv = from;
- else if (!cmpport((struct sockaddr *)&serv,
- (struct sockaddr *)&from)) {
- warn("server port mismatch");
- txrx_error = 1;
- goto abort;
- }
- peer = from;
- if (trace)
- tpacket("received", ap, n);
- /* should verify packet came from server */
- ap->th_opcode = ntohs(ap->th_opcode);
- ap->th_block = ntohs(ap->th_block);
- if (ap->th_opcode == ERROR) {
- printf("Error code %d: %s\n", ap->th_code,
- ap->th_msg);
- txrx_error = 1;
- goto abort;
- }
- if (ap->th_opcode == ACK) {
- int j;
-
- if (ap->th_block == block) {
- break;
- }
- /* On an error, try to synchronize
- * both sides.
- */
- j = synchnet(f);
- if (j && trace) {
- printf("discarded %d packets\n",
- j);
- }
- if (ap->th_block == (block-1)) {
- goto send_data;
- }
- }
+
+ /* Everything else is fatal */
+ break;
+ }
+ if (i == 12) {
+ printf("Transfer timed out.\n");
+ return;
+ }
+ if (rp->th_opcode == ERROR) {
+ printf("Got ERROR, aborted\n");
+ return;
+ }
+
+ /*
+ * If the first packet is an OACK instead of an ACK packet,
+ * handle it different.
+ */
+ if (rp->th_opcode == OACK) {
+ if (!options_rfc_enabled) {
+ printf("Got OACK while options are not enabled!\n");
+ send_error(peer, EBADOP);
+ return;
}
- if (block > 0)
- amount += size;
- block++;
- } while (size == SEGSIZE || block == 1);
-abort:
- fclose(file);
- stopclock();
- if (amount > 0)
- printstats("Sent", amount);
-}
-/*
- * Receive a file.
- */
-void
-recvfile(int fd, const char *name, const char *mode)
-{
- struct tftphdr *ap;
- struct tftphdr *dp;
- int n;
- volatile unsigned short block;
- volatile int size, firsttrip;
- volatile unsigned long amount;
- struct sockaddr_storage from;
- socklen_t fromlen;
- FILE *file;
- volatile int convert; /* true if converting crlf -> lf */
- struct sockaddr_storage peer;
- struct sockaddr_storage serv; /* valid server port number */
+ parse_options(peer, rp->th_stuff, n + 2);
+ }
+
+ if (read_init(fd, NULL, mode) < 0) {
+ warn("read_init()");
+ return;
+ }
- startclock();
- dp = w_init();
- ap = (struct tftphdr *)ackbuf;
- file = fdopen(fd, "w");
- convert = !strcmp(mode, "netascii");
block = 1;
- firsttrip = 1;
- amount = 0;
- memcpy(&peer, &peeraddr, peeraddr.ss_len);
- memset(&serv, 0, sizeof(serv));
+ tftp_send(peer, &block, &tftp_stats);
- signal(SIGALRM, timer);
- do {
- if (firsttrip) {
- size = makerequest(RRQ, name, ap, mode);
- firsttrip = 0;
- } else {
- ap->th_opcode = htons((u_short)ACK);
- ap->th_block = htons((u_short)(block));
- size = 4;
- block++;
- }
- timeout = 0;
- (void) setjmp(timeoutbuf);
-send_ack:
- if (trace)
- tpacket("sent", ap, size);
- if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&peer,
- peer.ss_len) != size) {
- alarm(0);
- warn("sendto");
- txrx_error = 1;
- goto abort;
- }
- write_behind(file, convert);
- for ( ; ; ) {
- alarm(rexmtval);
- do {
- fromlen = sizeof(from);
- n = recvfrom(f, dp, PKTSIZE, 0,
- (struct sockaddr *)&from, &fromlen);
- } while (n <= 0);
- alarm(0);
- if (n < 0) {
- warn("recvfrom");
- txrx_error = 1;
- goto abort;
- }
- if (!serv.ss_family)
- serv = from;
- else if (!cmpport((struct sockaddr *)&serv,
- (struct sockaddr *)&from)) {
- warn("server port mismatch");
- txrx_error = 1;
- goto abort;
- }
- peer = from;
- if (trace)
- tpacket("received", dp, n);
- /* should verify client address */
- dp->th_opcode = ntohs(dp->th_opcode);
- dp->th_block = ntohs(dp->th_block);
- if (dp->th_opcode == ERROR) {
- printf("Error code %d: %s\n", dp->th_code,
- dp->th_msg);
- txrx_error = 1;
- goto abort;
- }
- if (dp->th_opcode == DATA) {
- int j;
-
- if (dp->th_block == block) {
- break; /* have next packet */
- }
- /* On an error, try to synchronize
- * both sides.
- */
- j = synchnet(f);
- if (j && trace) {
- printf("discarded %d packets\n", j);
- }
- if (dp->th_block == (block-1)) {
- goto send_ack; /* resend ack */
- }
- }
- }
- /* size = write(fd, dp->th_data, n - 4); */
- size = writeit(file, &dp, n - 4, convert);
- if (size < 0) {
- nak(errno + 100, (struct sockaddr *)&peer);
- break;
- }
- amount += size;
- } while (size == SEGSIZE);
-abort: /* ok to ack, since user */
- ap->th_opcode = htons((u_short)ACK); /* has seen err msg */
- ap->th_block = htons((u_short)block);
- (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peer,
- peer.ss_len);
- write_behind(file, convert); /* flush last buffer */
- fclose(file);
- stopclock();
+ read_close();
if (amount > 0)
- printstats("Received", amount);
-}
+ printstats("Sent", verbose, &tftp_stats);
-static int
-makerequest(int request, const char *name, struct tftphdr *tp, const char *mode)
-{
- char *cp;
-
- tp->th_opcode = htons((u_short)request);
- cp = tp->th_stuff;
- strcpy(cp, name);
- cp += strlen(name);
- *cp++ = '\0';
- strcpy(cp, mode);
- cp += strlen(mode);
- *cp++ = '\0';
- return (cp - (char *)tp);
+ txrx_error = 1;
}
-struct errmsg {
- int e_code;
- const char *e_msg;
-} errmsgs[] = {
- { EUNDEF, "Undefined error code" },
- { ENOTFOUND, "File not found" },
- { EACCESS, "Access violation" },
- { ENOSPACE, "Disk full or allocation exceeded" },
- { EBADOP, "Illegal TFTP operation" },
- { EBADID, "Unknown transfer ID" },
- { EEXISTS, "File already exists" },
- { ENOUSER, "No such user" },
- { -1, 0 }
-};
-
/*
- * Send a nak packet (error message).
- * Error code passed in is one of the
- * standard TFTP codes, or a UNIX errno
- * offset by 100.
+ * Receive a file.
*/
-static void
-nak(int error, const struct sockaddr *peer)
-{
- struct errmsg *pe;
- struct tftphdr *tp;
- int length;
-
- tp = (struct tftphdr *)ackbuf;
- tp->th_opcode = htons((u_short)ERROR);
- tp->th_code = htons((u_short)error);
- for (pe = errmsgs; pe->e_code >= 0; pe++)
- if (pe->e_code == error)
- break;
- if (pe->e_code < 0) {
- pe->e_msg = strerror(error - 100);
- tp->th_code = EUNDEF;
- }
- strcpy(tp->th_msg, pe->e_msg);
- length = strlen(pe->e_msg) + 4;
- if (trace)
- tpacket("sent", tp, length);
- if (sendto(f, ackbuf, length, 0, peer, peer->sa_len) != length)
- warn("nak");
-}
-
-static void
-tpacket(const char *s, struct tftphdr *tp, int n)
+void
+recvfile(int peer, char *port, int fd, char *name, char *mode)
{
- static const char *opcodes[] =
- { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR" };
- char *cp, *file;
- u_short op = ntohs(tp->th_opcode);
-
- if (op < RRQ || op > ERROR)
- printf("%s opcode=%x ", s, op);
- else
- printf("%s %s ", s, opcodes[op]);
- switch (op) {
-
- case RRQ:
- case WRQ:
- n -= 2;
- file = cp = tp->th_stuff;
- cp = index(cp, '\0');
- printf("<file=%s, mode=%s>\n", file, cp + 1);
- break;
+ struct tftphdr *rp;
+ uint16_t block;
+ char recvbuffer[MAXPKTSIZE];
+ int n, i;
+ struct tftp_stats tftp_stats;
+
+ stats_init(&tftp_stats);
+
+ rp = (struct tftphdr *)recvbuffer;
+
+ if (port == NULL) {
+ struct servent *se;
+ se = getservbyname("tftp", "udp");
+ ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port;
+ } else
+ ((struct sockaddr_in *)&peer_sock)->sin_port =
+ htons(atoi(port));
+
+ for (i = 0; i < 12; i++) {
+ struct sockaddr_storage from;
+
+ /* Tell the other side what we want to do */
+ if (debug&DEBUG_SIMPLE)
+ printf("Requesting %s\n", name);
+
+ n = send_rrq(peer, name, mode);
+ if (n > 0) {
+ printf("Cannot send RRQ packet\n");
+ return;
+ }
- case DATA:
- printf("<block=%d, %d bytes>\n", ntohs(tp->th_block), n - 4);
- break;
+ /*
+ * The first packet we receive has the new destination port
+ * we have to send the next packets to.
+ */
+ n = receive_packet(peer, recvbuffer,
+ MAXPKTSIZE, &from, timeoutpacket);
+
+ /* We got something useful! */
+ if (n >= 0) {
+ ((struct sockaddr_in *)&peer_sock)->sin_port =
+ ((struct sockaddr_in *)&from)->sin_port;
+ break;
+ }
- case ACK:
- printf("<block=%d>\n", ntohs(tp->th_block));
- break;
+ /* We should retry if this happens */
+ if (n == RP_TIMEOUT) {
+ printf("Try %d, didn't receive answer from remote.\n",
+ i + 1);
+ continue;
+ }
- case ERROR:
- printf("<code=%d, msg=%s>\n", ntohs(tp->th_code), tp->th_msg);
+ /* Otherwise it is a fatal error */
break;
}
-}
-
-struct timeval tstart;
-struct timeval tstop;
-
-static void
-startclock(void)
-{
- (void)gettimeofday(&tstart, NULL);
-}
-
-static void
-stopclock(void)
-{
+ if (rp->th_opcode == ERROR) {
+ tftp_log(LOG_ERR, "Error code %d: %s", rp->th_code, rp->th_msg);
+ return;
+ }
- (void)gettimeofday(&tstop, NULL);
-}
+ if (write_init(fd, NULL, mode) < 0) {
+ warn("write_init");
+ return;
+ }
-static void
-printstats(const char *direction, unsigned long amount)
-{
- double delta;
- /* compute delta in 1/10's second units */
- delta = ((tstop.tv_sec*10.)+(tstop.tv_usec/100000)) -
- ((tstart.tv_sec*10.)+(tstart.tv_usec/100000));
- delta = delta/10.; /* back to seconds */
- printf("%s %ld bytes in %.1f seconds", direction, amount, delta);
- if (verbose)
- printf(" [%.0f bits/sec]", (amount*8.)/delta);
- putchar('\n');
-}
+ stats_init(&tftp_stats);
+
+ /*
+ * If the first packet is an OACK packet instead of an DATA packet,
+ * handle it different.
+ */
+ if (rp->th_opcode == OACK) {
+ if (!options_rfc_enabled) {
+ printf("Got OACK while options are not enabled!\n");
+ send_error(peer, EBADOP);
+ return;
+ }
-static void
-timer(int sig __unused)
-{
+ parse_options(peer, rp->th_stuff, n + 2);
- timeout += rexmtval;
- if (timeout >= maxtimeout) {
- printf("Transfer timed out.\n");
- longjmp(toplevel, -1);
+ n = send_ack(peer, 0);
+ if (n > 0) {
+ printf("Cannot send ACK on OACK.\n");
+ return;
+ }
+ block = 0;
+ tftp_receive(peer, &block, &tftp_stats, NULL, 0);
+ } else {
+ block = 1;
+ tftp_receive(peer, &block, &tftp_stats, rp, n);
}
- txrx_error = 1;
- longjmp(timeoutbuf, 1);
-}
-
-static int
-cmpport(const struct sockaddr *sa, const struct sockaddr *sb)
-{
- char a[NI_MAXSERV], b[NI_MAXSERV];
-
- if (getnameinfo(sa, sa->sa_len, NULL, 0, a, sizeof(a), NI_NUMERICSERV))
- return 0;
- if (getnameinfo(sb, sb->sa_len, NULL, 0, b, sizeof(b), NI_NUMERICSERV))
- return 0;
- if (strcmp(a, b) != 0)
- return 0;
- return 1;
+ write_close();
+ if (tftp_stats.amount > 0)
+ printstats("Received", verbose, &tftp_stats);
+ return;
}
diff --git a/usr.bin/tftp/tftp.h b/usr.bin/tftp/tftp.h
new file mode 100644
index 0000000..5928dea
--- /dev/null
+++ b/usr.bin/tftp/tftp.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.1 (Berkeley) 6/6/93
+ * $FreeBSD$
+ */
+
+void recvfile(int peer, char *port, int fd, char *name, char *mode);
+void xmitfile(int peer, char *port, int fd, char *name, char *mode);
+
+extern int verbose;
+extern int maxtimeout;
+extern volatile int txrx_error;
diff --git a/usr.sbin/acpi/acpidb/Makefile b/usr.sbin/acpi/acpidb/Makefile
index c2fe844..eed57f3 100644
--- a/usr.sbin/acpi/acpidb/Makefile
+++ b/usr.sbin/acpi/acpidb/Makefile
@@ -13,8 +13,9 @@ SRCS+= dmbuffer.c dmnames.c dmobject.c dmopcode.c dmresrc.c \
dmresrcl.c dmresrcs.c dmutils.c dmwalk.c
# events
-SRCS+= evevent.c evgpe.c evgpeblk.c evmisc.c evregion.c \
- evrgnini.c evsci.c evxface.c evxfevnt.c evxfregn.c
+SRCS+= evevent.c evgpe.c evgpeblk.c evgpeinit.c evgpeutil.c \
+ evmisc.c evregion.c evrgnini.c evsci.c evxface.c \
+ evxfevnt.c evxfregn.c
# hardware
SRCS+= hwacpi.c hwgpe.c hwregs.c hwsleep.c hwvalid.c hwxface.c
diff --git a/usr.sbin/acpi/iasl/Makefile b/usr.sbin/acpi/iasl/Makefile
index ea7a325..3e17cc9 100644
--- a/usr.sbin/acpi/iasl/Makefile
+++ b/usr.sbin/acpi/iasl/Makefile
@@ -14,8 +14,10 @@ SRCS+= aslanalyze.c aslcodegen.c aslcompile.c aslcompiler.y.h \
aslfiles.c aslfold.c asllength.c asllisting.c \
aslload.c asllookup.c aslmain.c aslmap.c aslopcodes.c \
asloperands.c aslopt.c aslpredef.c aslresource.c \
- aslrestype1.c aslrestype2.c aslstartup.c aslstubs.c \
- asltransform.c asltree.c aslutils.c
+ aslrestype1.c aslrestype1i.c aslrestype2.c \
+ aslrestype2d.c aslrestype2e.c aslrestype2q.c \
+ aslrestype2w.c aslstartup.c aslstubs.c asltransform.c \
+ asltree.c aslutils.c
# debugger
SRCS+= dbfileio.c
diff --git a/usr.sbin/config/config.h b/usr.sbin/config/config.h
index ec19986..4abb567 100644
--- a/usr.sbin/config/config.h
+++ b/usr.sbin/config/config.h
@@ -179,6 +179,7 @@ void makehints(void);
void headers(void);
void cfgfile_add(const char *);
void cfgfile_removeall(void);
+FILE *open_makefile_template(void);
extern STAILQ_HEAD(device_head, device) dtab;
diff --git a/usr.sbin/config/configvers.h b/usr.sbin/config/configvers.h
index 73310bd..2d43329 100644
--- a/usr.sbin/config/configvers.h
+++ b/usr.sbin/config/configvers.h
@@ -49,5 +49,5 @@
*
* $FreeBSD$
*/
-#define CONFIGVERS 600008
+#define CONFIGVERS 600009
#define MAJOR_VERS(x) ((x) / 100000)
diff --git a/usr.sbin/config/main.c b/usr.sbin/config/main.c
index 2b5e055..e63e6ab 100644
--- a/usr.sbin/config/main.c
+++ b/usr.sbin/config/main.c
@@ -90,6 +90,7 @@ static void get_srcdir(void);
static void usage(void);
static void cleanheaders(char *);
static void kernconfdump(const char *);
+static void checkversion(void);
struct hdr_list {
char *h_name;
@@ -204,6 +205,7 @@ main(int argc, char **argv)
printf("cpu type must be specified\n");
exit(1);
}
+ checkversion();
/*
* make symbolic links in compilation directory
@@ -668,7 +670,7 @@ kernconfdump(const char *file)
struct stat st;
FILE *fp, *pp;
int error, len, osz, r;
- unsigned int i, off, size;
+ unsigned int i, off, size, t1, t2, align;
char *cmd, *o;
r = open(file, O_RDONLY);
@@ -687,8 +689,8 @@ kernconfdump(const char *file)
if (o == NULL)
err(EXIT_FAILURE, "Couldn't allocate memory");
/* ELF note section header. */
- asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 5 kern_conf"
- "| tail -2 | cut -d ' ' -f 2 | paste - - -", file);
+ asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 8 kern_conf"
+ "| tail -5 | cut -d ' ' -f 2 | paste - - - - -", file);
if (cmd == NULL)
errx(EXIT_FAILURE, "asprintf() failed");
pp = popen(cmd, "r");
@@ -697,27 +699,69 @@ kernconfdump(const char *file)
free(cmd);
len = fread(o, osz, 1, pp);
pclose(pp);
- r = sscanf(o, "%d\t%d", &off, &size);
+ r = sscanf(o, "%d%d%d%d%d", &off, &size, &t1, &t2, &align);
free(o);
- if (r != 2)
+ if (r != 5)
errx(EXIT_FAILURE, "File %s doesn't contain configuration "
"file. Either unsupported, or not compiled with "
"INCLUDE_CONFIG_FILE", file);
r = fseek(fp, off, SEEK_CUR);
if (r != 0)
err(EXIT_FAILURE, "fseek() failed");
- for (i = 0; i < size - 1; i++) {
+ for (i = 0; i < size; i++) {
r = fgetc(fp);
if (r == EOF)
break;
/*
* If '\0' is present in the middle of the configuration
* string, this means something very weird is happening.
- * Make such case very visible.
+ * Make such case very visible. However, some architectures
+ * pad the length of the section with NULs to a multiple of
+ * sh_addralign, allow a NUL in that part of the section.
*/
+ if (r == '\0' && (size - i) < align)
+ break;
assert(r != '\0' && ("Char present in the configuration "
"string mustn't be equal to 0"));
fputc(r, stdout);
}
fclose(fp);
}
+
+static void
+badversion(int versreq)
+{
+ fprintf(stderr, "ERROR: version of config(8) does not match kernel!\n");
+ fprintf(stderr, "config version = %d, ", CONFIGVERS);
+ fprintf(stderr, "version required = %d\n\n", versreq);
+ fprintf(stderr, "Make sure that /usr/src/usr.sbin/config is in sync\n");
+ fprintf(stderr, "with your /usr/src/sys and install a new config binary\n");
+ fprintf(stderr, "before trying this again.\n\n");
+ fprintf(stderr, "If running the new config fails check your config\n");
+ fprintf(stderr, "file against the GENERIC or LINT config files for\n");
+ fprintf(stderr, "changes in config syntax, or option/device naming\n");
+ fprintf(stderr, "conventions\n\n");
+ exit(1);
+}
+
+static void
+checkversion(void)
+{
+ FILE *ifp;
+ char line[BUFSIZ];
+ int versreq;
+
+ ifp = open_makefile_template();
+ while (fgets(line, BUFSIZ, ifp) != 0) {
+ if (*line != '%')
+ continue;
+ if (strncmp(line, "%VERSREQ=", 9) != 0)
+ continue;
+ versreq = atoi(line + 9);
+ if (MAJOR_VERS(versreq) == MAJOR_VERS(CONFIGVERS) &&
+ versreq <= CONFIGVERS)
+ continue;
+ badversion(versreq);
+ }
+ fclose(ifp);
+}
diff --git a/usr.sbin/config/mkmakefile.c b/usr.sbin/config/mkmakefile.c
index 7845089..b5a0e35 100644
--- a/usr.sbin/config/mkmakefile.c
+++ b/usr.sbin/config/mkmakefile.c
@@ -105,17 +105,14 @@ new_fent(void)
}
/*
- * Build the makefile from the skeleton
+ * Open the correct Makefile and return it, or error out.
*/
-void
-makefile(void)
+FILE *
+open_makefile_template(void)
{
- FILE *ifp, *ofp;
+ FILE *ifp;
char line[BUFSIZ];
- struct opt *op, *t;
- int versreq;
- read_files();
snprintf(line, sizeof(line), "../../conf/Makefile.%s", machinename);
ifp = fopen(line, "r");
if (ifp == 0) {
@@ -124,7 +121,21 @@ makefile(void)
}
if (ifp == 0)
err(1, "%s", line);
+ return (ifp);
+}
+/*
+ * Build the makefile from the skeleton
+ */
+void
+makefile(void)
+{
+ FILE *ifp, *ofp;
+ char line[BUFSIZ];
+ struct opt *op, *t;
+
+ read_files();
+ ifp = open_makefile_template();
ofp = fopen(path("Makefile.new"), "w");
if (ofp == 0)
err(1, "%s", path("Makefile.new"));
@@ -156,23 +167,9 @@ makefile(void)
do_rules(ofp);
else if (eq(line, "%CLEAN\n"))
do_clean(ofp);
- else if (strncmp(line, "%VERSREQ=", sizeof("%VERSREQ=") - 1) == 0) {
- versreq = atoi(line + sizeof("%VERSREQ=") - 1);
- if (MAJOR_VERS(versreq) != MAJOR_VERS(CONFIGVERS) ||
- versreq > CONFIGVERS) {
- fprintf(stderr, "ERROR: version of config(8) does not match kernel!\n");
- fprintf(stderr, "config version = %d, ", CONFIGVERS);
- fprintf(stderr, "version required = %d\n\n", versreq);
- fprintf(stderr, "Make sure that /usr/src/usr.sbin/config is in sync\n");
- fprintf(stderr, "with your /usr/src/sys and install a new config binary\n");
- fprintf(stderr, "before trying this again.\n\n");
- fprintf(stderr, "If running the new config fails check your config\n");
- fprintf(stderr, "file against the GENERIC or LINT config files for\n");
- fprintf(stderr, "changes in config syntax, or option/device naming\n");
- fprintf(stderr, "conventions\n\n");
- exit(1);
- }
- } else
+ else if (strncmp(line, "%VERSREQ=", 9) == 0)
+ line[0] = '\0'; /* handled elsewhere */
+ else
fprintf(stderr,
"Unknown %% construct in generic makefile: %s",
line);
diff --git a/usr.sbin/config/mkoptions.c b/usr.sbin/config/mkoptions.c
index 1a6ccc8..044b669 100644
--- a/usr.sbin/config/mkoptions.c
+++ b/usr.sbin/config/mkoptions.c
@@ -166,7 +166,7 @@ do_option(char *name)
fprintf(outf, "#define %s %s\n", name, value);
} /* else empty file */
- (void) fclose(outf);
+ (void)fclose(outf);
return;
}
basefile = "";
@@ -225,7 +225,7 @@ do_option(char *name)
if (cp == (char *)EOF)
break;
}
- (void) fclose(inf);
+ (void)fclose(inf);
if (!tidy && ((value == NULL && oldvalue == NULL) ||
(value && oldvalue && eq(value, oldvalue)))) {
while (!SLIST_EMPTY(&op_head)) {
@@ -263,7 +263,7 @@ do_option(char *name)
free(op->op_value);
free(op);
}
- (void) fclose(outf);
+ (void)fclose(outf);
}
/*
@@ -277,7 +277,7 @@ tooption(char *name)
struct opt_list *po;
/* "cannot happen"? the otab list should be complete.. */
- (void) strlcpy(nbuf, "options.h", sizeof(nbuf));
+ (void)strlcpy(nbuf, "options.h", sizeof(nbuf));
SLIST_FOREACH(po, &otab, o_next) {
if (eq(po->o_name, name)) {
@@ -286,78 +286,15 @@ tooption(char *name)
}
}
- (void) strlcpy(hbuf, path(nbuf), sizeof(hbuf));
+ (void)strlcpy(hbuf, path(nbuf), sizeof(hbuf));
return (hbuf);
}
-/*
- * read the options and options.<machine> files
- */
+
static void
-read_options(void)
+check_duplicate(const char *fname, const char *this)
{
- FILE *fp;
- char fname[MAXPATHLEN];
- char *wd, *this, *val;
struct opt_list *po;
- int first = 1;
- char genopt[MAXPATHLEN];
- int flags = 0;
-
- SLIST_INIT(&otab);
- (void) snprintf(fname, sizeof(fname), "../../conf/options");
-openit:
- fp = fopen(fname, "r");
- if (fp == 0) {
- return;
- }
-next:
- flags = 0;
- wd = get_word(fp);
- if (wd == (char *)EOF) {
- (void) fclose(fp);
- if (first == 1) {
- first++;
- (void) snprintf(fname, sizeof fname, "../../conf/options.%s", machinename);
- fp = fopen(fname, "r");
- if (fp != 0)
- goto next;
- (void) snprintf(fname, sizeof fname, "options.%s", machinename);
- goto openit;
- }
- return;
- }
- if (wd == 0)
- goto next;
- if (wd[0] == '#')
- {
- while (((wd = get_word(fp)) != (char *)EOF) && wd)
- ;
- goto next;
- }
- this = ns(wd);
- val = get_word(fp);
- if (val == (char *)EOF)
- return;
- if (val == 0) {
- char *s = ns(this);
- (void) snprintf(genopt, sizeof(genopt), "opt_%s.h", lower(s));
- val = genopt;
- free(s);
- } else if (eq(val, "=")) {
- val = get_word(fp);
- if (val == (char *)EOF) {
- printf("%s: unexpected end of file\n", fname);
- exit(1);
- }
- if (val == 0) {
- printf("%s: Expected a right hand side at %s\n", fname,
- this);
- exit(1);
- }
- flags |= OL_ALIAS;
- }
- val = ns(val);
SLIST_FOREACH(po, &otab, o_next) {
if (eq(po->o_name, this)) {
@@ -366,16 +303,101 @@ next:
exit(1);
}
}
-
+}
+
+static void
+insert_option(const char *fname, char *this, char *val)
+{
+ struct opt_list *po;
+
+ check_duplicate(fname, this);
po = (struct opt_list *) calloc(1, sizeof *po);
if (po == NULL)
err(EXIT_FAILURE, "calloc");
po->o_name = this;
po->o_file = val;
- po->o_flags = flags;
+ po->o_flags = 0;
SLIST_INSERT_HEAD(&otab, po, o_next);
+}
- goto next;
+static void
+update_option(const char *this, char *val, int flags)
+{
+ struct opt_list *po;
+
+ SLIST_FOREACH(po, &otab, o_next) {
+ if (eq(po->o_name, this)) {
+ free(po->o_file);
+ po->o_file = val;
+ po->o_flags = flags;
+ return;
+ }
+ }
+ printf("Compat option %s not listed in options file.\n", this);
+ exit(1);
+}
+
+static int
+read_option_file(const char *fname, int flags)
+{
+ FILE *fp;
+ char *wd, *this, *val;
+ char genopt[MAXPATHLEN];
+
+ fp = fopen(fname, "r");
+ if (fp == 0)
+ return (0);
+ while ((wd = get_word(fp)) != (char *)EOF) {
+ if (wd == 0)
+ continue;
+ if (wd[0] == '#') {
+ while (((wd = get_word(fp)) != (char *)EOF) && wd)
+ continue;
+ continue;
+ }
+ this = ns(wd);
+ val = get_word(fp);
+ if (val == (char *)EOF)
+ return (1);
+ if (val == 0) {
+ if (flags) {
+ printf("%s: compat file requires two words "
+ "per line at %s\n", fname, this);
+ exit(1);
+ }
+ char *s = ns(this);
+ (void)snprintf(genopt, sizeof(genopt), "opt_%s.h",
+ lower(s));
+ val = genopt;
+ free(s);
+ }
+ val = ns(val);
+ if (flags == 0)
+ insert_option(fname, this, val);
+ else
+ update_option(this, val, flags);
+ }
+ (void)fclose(fp);
+ return (1);
+}
+
+/*
+ * read the options and options.<machine> files
+ */
+static void
+read_options(void)
+{
+ char fname[MAXPATHLEN];
+
+ SLIST_INIT(&otab);
+ read_option_file("../../conf/options", 0);
+ (void)snprintf(fname, sizeof fname, "../../conf/options.%s",
+ machinename);
+ if (!read_option_file(fname, 0)) {
+ (void)snprintf(fname, sizeof fname, "options.%s", machinename);
+ read_option_file(fname, 0);
+ }
+ read_option_file("../../conf/options-compat", OL_ALIAS);
}
static char *
diff --git a/usr.sbin/cxgbtool/cxgbtool.c b/usr.sbin/cxgbtool/cxgbtool.c
index 28d91f9..b705ff8 100644
--- a/usr.sbin/cxgbtool/cxgbtool.c
+++ b/usr.sbin/cxgbtool/cxgbtool.c
@@ -1,6 +1,6 @@
/**************************************************************************
-Copyright (c) 2007-2009, Chelsio Inc.
+Copyright (c) 2007-2010, Chelsio Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -93,6 +93,9 @@ usage(FILE *fp)
"\tclearstats clear MAC statistics\n"
"\tcontext <type> <id> show an SGE context\n"
"\tdesc <qset> <queue> <idx> [<cnt>] dump SGE descriptors\n"
+ "\tfilter <idx> [<param> <val>] ... set a filter\n"
+ "\tfilter <idx> delete|clear delete a filter\n"
+ "\tfilter list list all filters\n"
"\tioqs dump uP IOQs\n"
"\tla dump uP logic analyzer info\n"
"\tloadboot <boot image> download boot image\n"
@@ -1177,24 +1180,25 @@ parse_ipaddr(const char *s, uint32_t *addr, uint32_t *mask)
* Parse a string containing a value and an optional colon separated mask.
*/
static int
-parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask)
+parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask,
+ uint32_t default_mask)
{
char *p;
- *mask = 0xffffffffU;
+ *mask = default_mask;
*val = strtoul(s, &p, 0);
- if (p == s)
+ if (p == s || *val > default_mask)
return -1;
if (*p == ':' && p[1])
*mask = strtoul(p + 1, &p, 0);
- return *p ? -1 : 0;
+ return *p || *mask > default_mask ? -1 : 0;
}
static int
parse_trace_param(const char *s, uint32_t *val, uint32_t *mask)
{
return strchr(s, '.') ? parse_ipaddr(s, val, mask) :
- parse_val_mask_param(s, val, mask);
+ parse_val_mask_param(s, val, mask, 0xffffffffU);
}
static int
@@ -1273,6 +1277,174 @@ trace_config(int argc, char *argv[], int start_arg, const char *iff_name)
return 0;
}
+static void
+show_filters(const char *iff_name)
+{
+ static const char *pkt_type[] = { "*", "tcp", "udp", "frag" };
+ struct ch_filter op;
+ union {
+ uint32_t nip;
+ uint8_t octet[4];
+ } nsip, ndip;
+ char sip[20], dip[20];
+ int header = 0;
+
+ bzero(&op, sizeof(op));
+ op.filter_id = 0xffffffff;
+
+ do {
+ if (doit(iff_name, CHELSIO_GET_FILTER, &op) < 0)
+ err(1, "list filters");
+
+ if (op.filter_id == 0xffffffff)
+ break;
+
+ if (!header) {
+ printf("index SIP DIP sport "
+ "dport VLAN PRI P/MAC type Q\n");
+ header = 1;
+ }
+
+ nsip.nip = htonl(op.val.sip);
+ ndip.nip = htonl(op.val.dip);
+
+ sprintf(sip, "%u.%u.%u.%u/%-2u", nsip.octet[0], nsip.octet[1],
+ nsip.octet[2], nsip.octet[3],
+ op.mask.sip ? 33 - ffs(op.mask.sip) : 0);
+ sprintf(dip, "%u.%u.%u.%u", ndip.octet[0], ndip.octet[1],
+ ndip.octet[2], ndip.octet[3]);
+ printf("%5zu %18s %15s ", (size_t)op.filter_id, sip, dip);
+ printf(op.val.sport ? "%5u " : " * ", op.val.sport);
+ printf(op.val.dport ? "%5u " : " * ", op.val.dport);
+ printf(op.val.vlan != 0xfff ? "%4u " : " * ", op.val.vlan);
+ printf(op.val.vlan_prio == 7 ? " * " :
+ "%1u/%1u ", op.val.vlan_prio, op.val.vlan_prio | 1);
+ if (op.mac_addr_idx == 0xffff)
+ printf("*/* ");
+ else if (op.mac_hit)
+ printf("%1u/%3u ", (op.mac_addr_idx >> 3) & 0x1,
+ (op.mac_addr_idx) & 0x7);
+ else
+ printf("%1u/ * ", (op.mac_addr_idx >> 3) & 0x1);
+ printf("%4s ", pkt_type[op.proto]);
+ if (!op.pass)
+ printf("-\n");
+ else if (op.rss)
+ printf("*\n");
+ else
+ printf("%1u\n", op.qset);
+ } while (1);
+}
+
+static int
+filter_config(int argc, char *argv[], int start_arg, const char *iff_name)
+{
+ int ret = 0;
+ uint32_t val, mask;
+ struct ch_filter op;
+
+ if (argc < start_arg + 1)
+ return -1;
+
+ memset(&op, 0, sizeof(op));
+ op.mac_addr_idx = 0xffff;
+ op.rss = 1;
+
+ if (argc == start_arg + 1 && !strcmp(argv[start_arg], "list")) {
+ show_filters(iff_name);
+ return 0;
+ }
+
+ if (get_int_arg(argv[start_arg++], &op.filter_id))
+ return -1;
+ if (argc == start_arg + 1 && (!strcmp(argv[start_arg], "delete") ||
+ !strcmp(argv[start_arg], "clear"))) {
+ if (doit(iff_name, CHELSIO_DEL_FILTER, &op) < 0) {
+ if (errno == EBUSY)
+ err(1, "no filter support when offload in use");
+ err(1, "delete filter");
+ }
+ return 0;
+ }
+
+ while (start_arg + 2 <= argc) {
+ if (!strcmp(argv[start_arg], "sip")) {
+ ret = parse_ipaddr(argv[start_arg + 1], &op.val.sip,
+ &op.mask.sip);
+ } else if (!strcmp(argv[start_arg], "dip")) {
+ ret = parse_ipaddr(argv[start_arg + 1], &op.val.dip,
+ &op.mask.dip);
+ } else if (!strcmp(argv[start_arg], "sport")) {
+ ret = parse_val_mask_param(argv[start_arg + 1],
+ &val, &mask, 0xffff);
+ op.val.sport = val;
+ op.mask.sport = mask;
+ } else if (!strcmp(argv[start_arg], "dport")) {
+ ret = parse_val_mask_param(argv[start_arg + 1],
+ &val, &mask, 0xffff);
+ op.val.dport = val;
+ op.mask.dport = mask;
+ } else if (!strcmp(argv[start_arg], "vlan")) {
+ ret = parse_val_mask_param(argv[start_arg + 1],
+ &val, &mask, 0xfff);
+ op.val.vlan = val;
+ op.mask.vlan = mask;
+ } else if (!strcmp(argv[start_arg], "prio")) {
+ ret = parse_val_mask_param(argv[start_arg + 1],
+ &val, &mask, 7);
+ op.val.vlan_prio = val;
+ op.mask.vlan_prio = mask;
+ } else if (!strcmp(argv[start_arg], "mac")) {
+ if (!strcmp(argv[start_arg + 1], "none"))
+ val = -1;
+ else
+ ret = get_int_arg(argv[start_arg + 1], &val);
+ op.mac_hit = val != (uint32_t)-1;
+ op.mac_addr_idx = op.mac_hit ? val : 0;
+ } else if (!strcmp(argv[start_arg], "type")) {
+ if (!strcmp(argv[start_arg + 1], "tcp"))
+ op.proto = 1;
+ else if (!strcmp(argv[start_arg + 1], "udp"))
+ op.proto = 2;
+ else if (!strcmp(argv[start_arg + 1], "frag"))
+ op.proto = 3;
+ else
+ errx(1, "unknown type \"%s\"; must be one of "
+ "\"tcp\", \"udp\", or \"frag\"",
+ argv[start_arg + 1]);
+ } else if (!strcmp(argv[start_arg], "queue")) {
+ ret = get_int_arg(argv[start_arg + 1], &val);
+ op.qset = val;
+ op.rss = 0;
+ } else if (!strcmp(argv[start_arg], "action")) {
+ if (!strcmp(argv[start_arg + 1], "pass"))
+ op.pass = 1;
+ else if (strcmp(argv[start_arg + 1], "drop"))
+ errx(1, "unknown action \"%s\"; must be one of "
+ "\"pass\" or \"drop\"",
+ argv[start_arg + 1]);
+ } else
+ errx(1, "unknown filter parameter \"%s\"\n"
+ "known parameters are \"mac\", \"sip\", "
+ "\"dip\", \"sport\", \"dport\", \"vlan\", "
+ "\"prio\", \"type\", \"queue\", and \"action\"",
+ argv[start_arg]);
+ if (ret < 0)
+ errx(1, "bad value \"%s\" for parameter \"%s\"",
+ argv[start_arg + 1], argv[start_arg]);
+ start_arg += 2;
+ }
+ if (start_arg != argc)
+ errx(1, "no value for \"%s\"", argv[start_arg]);
+
+ if (doit(iff_name, CHELSIO_SET_FILTER, &op) < 0) {
+ if (errno == EBUSY)
+ err(1, "no filter support when offload in use");
+ err(1, "set filter");
+ }
+
+ return 0;
+}
static int
get_sched_param(int argc, char *argv[], int pos, unsigned int *valp)
{
@@ -1501,6 +1673,8 @@ run_cmd(int argc, char *argv[], const char *iff_name)
r = pktsched(argc, argv, 3, iff_name);
else if (!strcmp(argv[2], "tcb"))
r = get_tcb2(argc, argv, 3, iff_name);
+ else if (!strcmp(argv[2], "filter"))
+ r = filter_config(argc, argv, 3, iff_name);
else if (!strcmp(argv[2], "clearstats"))
r = clear_stats(argc, argv, 3, iff_name);
else if (!strcmp(argv[2], "la"))
diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8
index 85fe988..8e49b07 100644
--- a/usr.sbin/jail/jail.8
+++ b/usr.sbin/jail/jail.8
@@ -239,7 +239,7 @@ The
.Xr jexec 8 .
.It Va ip4.addr
A comma-separated list of IPv4 addresses assigned to the prison.
-If this is set, the jail is restricted to using only these address.
+If this is set, the jail is restricted to using only these addresses.
Any attempts to use other addresses fail, and attempts to use wildcard
addresses silently use the jailed address instead.
For IPv4 the first address given will be kept used as the source address
diff --git a/usr.sbin/mergemaster/mergemaster.sh b/usr.sbin/mergemaster/mergemaster.sh
index 7f06968..84ee455 100755
--- a/usr.sbin/mergemaster/mergemaster.sh
+++ b/usr.sbin/mergemaster/mergemaster.sh
@@ -849,6 +849,9 @@ mm_install () {
/etc/login.conf)
NEED_CAP_MKDB=yes
;;
+ /etc/services)
+ NEED_SERVICES_MKDB=yes
+ ;;
/etc/master.passwd)
do_install_and_rm 600 "${1}" "${DESTDIR}${INSTALL_DIR}"
NEED_PWD_MKDB=yes
@@ -1278,6 +1281,17 @@ case "${NEED_CAP_MKDB}" in
;;
esac
+case "${NEED_SERVICES_MKDB}" in
+'') ;;
+*)
+ echo ''
+ echo "*** You installed a services file, so make sure that you run"
+ echo " '/usr/sbin/services_mkdb -q -o ${DESTDIR}/var/db/services.db ${DESTDIR}/etc/services'"
+ echo " to rebuild your services database"
+ run_it_now "/usr/sbin/services_mkdb -q -o ${DESTDIR}/var/db/services.db ${DESTDIR}/etc/services"
+ ;;
+esac
+
case "${NEED_PWD_MKDB}" in
'') ;;
*)
OpenPOWER on IntegriCloud