summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2013-02-03 20:13:33 +0000
committerattilio <attilio@FreeBSD.org>2013-02-03 20:13:33 +0000
commit0d3b58aee00948d85d75a9d3d222deb454afc98e (patch)
tree865d112b57519913a8de64b2d9ca8787633c95a2 /sys
parent561dd1163dbb481d204da7a526739ac6e43d08f2 (diff)
parent2d2c37fb592dfc24f15e4bf14c2f109b5d4b5a83 (diff)
downloadFreeBSD-src-0d3b58aee00948d85d75a9d3d222deb454afc98e.zip
FreeBSD-src-0d3b58aee00948d85d75a9d3d222deb454afc98e.tar.gz
MFC
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/mp_machdep.c4
-rw-r--r--sys/amd64/amd64/pmap.c12
-rw-r--r--sys/amd64/conf/GENERIC9
-rw-r--r--sys/amd64/conf/NOTES9
-rw-r--r--sys/amd64/include/intr_machdep.h2
-rw-r--r--sys/amd64/include/vmm.h293
-rw-r--r--sys/amd64/include/vmm_dev.h215
-rw-r--r--sys/amd64/include/vmm_instruction_emul.h114
-rw-r--r--sys/amd64/linux32/linux.h153
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c1
-rw-r--r--sys/amd64/vmm/amd/amdv.c265
-rw-r--r--sys/amd64/vmm/intel/ept.c392
-rw-r--r--sys/amd64/vmm/intel/ept.h43
-rw-r--r--sys/amd64/vmm/intel/vmcs.c551
-rw-r--r--sys/amd64/vmm/intel/vmcs.h338
-rw-r--r--sys/amd64/vmm/intel/vmx.c1852
-rw-r--r--sys/amd64/vmm/intel/vmx.h120
-rw-r--r--sys/amd64/vmm/intel/vmx_controls.h92
-rw-r--r--sys/amd64/vmm/intel/vmx_cpufunc.h218
-rw-r--r--sys/amd64/vmm/intel/vmx_genassym.c89
-rw-r--r--sys/amd64/vmm/intel/vmx_msr.c172
-rw-r--r--sys/amd64/vmm/intel/vmx_msr.h78
-rw-r--r--sys/amd64/vmm/intel/vmx_support.S246
-rw-r--r--sys/amd64/vmm/intel/vtd.c677
-rw-r--r--sys/amd64/vmm/io/iommu.c277
-rw-r--r--sys/amd64/vmm/io/iommu.h75
-rw-r--r--sys/amd64/vmm/io/ppt.c619
-rw-r--r--sys/amd64/vmm/io/ppt.h41
-rw-r--r--sys/amd64/vmm/io/vdev.c270
-rw-r--r--sys/amd64/vmm/io/vdev.h84
-rw-r--r--sys/amd64/vmm/io/vlapic.c901
-rw-r--r--sys/amd64/vmm/io/vlapic.h111
-rw-r--r--sys/amd64/vmm/vmm.c1038
-rw-r--r--sys/amd64/vmm/vmm_dev.c538
-rw-r--r--sys/amd64/vmm/vmm_host.c124
-rw-r--r--sys/amd64/vmm/vmm_host.h75
-rw-r--r--sys/amd64/vmm/vmm_instruction_emul.c868
-rw-r--r--sys/amd64/vmm/vmm_ipi.c93
-rw-r--r--sys/amd64/vmm/vmm_ipi.h39
-rw-r--r--sys/amd64/vmm/vmm_ktr.h51
-rw-r--r--sys/amd64/vmm/vmm_lapic.c201
-rw-r--r--sys/amd64/vmm/vmm_lapic.h71
-rw-r--r--sys/amd64/vmm/vmm_mem.c135
-rw-r--r--sys/amd64/vmm/vmm_mem.h37
-rw-r--r--sys/amd64/vmm/vmm_msr.c254
-rw-r--r--sys/amd64/vmm/vmm_msr.h43
-rw-r--r--sys/amd64/vmm/vmm_stat.c104
-rw-r--r--sys/amd64/vmm/vmm_stat.h71
-rw-r--r--sys/amd64/vmm/vmm_support.S42
-rw-r--r--sys/amd64/vmm/vmm_util.c111
-rw-r--r--sys/amd64/vmm/vmm_util.h40
-rw-r--r--sys/amd64/vmm/x86.c202
-rw-r--r--sys/amd64/vmm/x86.h64
-rw-r--r--sys/arm/allwinner/a10_clk.c171
-rw-r--r--sys/arm/allwinner/a10_clk.h114
-rw-r--r--sys/arm/allwinner/a10_ehci.c279
-rw-r--r--sys/arm/allwinner/a10_machdep.c122
-rw-r--r--sys/arm/allwinner/aintc.c211
-rw-r--r--sys/arm/allwinner/bus_space.c113
-rw-r--r--sys/arm/allwinner/common.c63
-rw-r--r--sys/arm/allwinner/console.c142
-rw-r--r--sys/arm/allwinner/files.a1019
-rw-r--r--sys/arm/allwinner/std.a1021
-rw-r--r--sys/arm/allwinner/timer.c379
-rw-r--r--sys/arm/arm/busdma_machdep.c30
-rw-r--r--sys/arm/arm/cpufunc.c4
-rw-r--r--sys/arm/arm/cpufunc_asm_arm10.S26
-rw-r--r--sys/arm/arm/cpufunc_asm_arm9.S26
-rw-r--r--sys/arm/arm/db_trace.c416
-rw-r--r--sys/arm/arm/intr.c35
-rw-r--r--sys/arm/arm/locore.S19
-rw-r--r--sys/arm/arm/machdep.c1
-rw-r--r--sys/arm/arm/swtch.S3
-rw-r--r--sys/arm/arm/trap.c8
-rw-r--r--sys/arm/arm/vm_machdep.c6
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_fb.c25
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_machdep.c5
-rw-r--r--sys/arm/conf/BEAGLEBONE6
-rw-r--r--sys/arm/conf/CUBIEBOARD134
-rw-r--r--sys/arm/conf/DOCKSTAR2
-rw-r--r--sys/arm/conf/DREAMPLUG-1001183
-rw-r--r--sys/arm/conf/NOTES1
-rw-r--r--sys/arm/conf/SHEEVAPLUG2
-rw-r--r--sys/arm/include/atomic.h25
-rw-r--r--sys/arm/include/intr.h1
-rw-r--r--sys/arm/include/proc.h6
-rw-r--r--sys/arm/include/vmparam.h7
-rw-r--r--sys/arm/mv/kirkwood/files.sheevaplug4
-rw-r--r--sys/arm/mv/kirkwood/std.sheevaplug5
-rw-r--r--sys/arm/mv/mv_machdep.c19
-rw-r--r--sys/arm/ti/am335x/am335x_scm_padconf.c248
-rw-r--r--sys/arm/ti/cpsw/if_cpsw.c2324
-rw-r--r--sys/arm/ti/cpsw/if_cpswreg.h24
-rw-r--r--sys/arm/ti/cpsw/if_cpswvar.h139
-rw-r--r--sys/arm/ti/ti_scm.c13
-rw-r--r--sys/boot/arm/uboot/Makefile4
-rw-r--r--sys/boot/fdt/dts/beaglebone.dts57
-rw-r--r--sys/boot/fdt/dts/cubieboard.dts111
-rw-r--r--sys/boot/fdt/dts/dreamplug-1001.dts319
-rw-r--r--sys/boot/fdt/dts/dreamplug-1001N.dts340
-rw-r--r--sys/boot/i386/efi/Makefile2
-rw-r--r--sys/boot/i386/libi386/bootinfo64.c3
-rw-r--r--sys/boot/i386/libi386/comconsole.c25
-rw-r--r--sys/boot/i386/libi386/devicename.c2
-rw-r--r--sys/boot/i386/libi386/pxe.c6
-rw-r--r--sys/boot/sparc64/loader/main.c20
-rw-r--r--sys/boot/uboot/common/metadata.c15
-rw-r--r--sys/boot/usb/Makefile150
-rw-r--r--sys/boot/usb/Makefile.test61
-rw-r--r--sys/boot/usb/bsd_busspace.c207
-rw-r--r--sys/boot/usb/bsd_global.h63
-rw-r--r--sys/boot/usb/bsd_kernel.c1269
-rw-r--r--sys/boot/usb/bsd_kernel.h458
-rw-r--r--sys/boot/usb/bsd_usbloader_test.c80
-rw-r--r--sys/boot/usb/tools/sysinit.c331
-rw-r--r--sys/boot/usb/tools/sysinit.h57
-rw-r--r--sys/boot/usb/usb_busdma_loader.c619
-rw-r--r--sys/cam/ctl/ctl.c24
-rw-r--r--sys/cam/ctl/scsi_ctl.c247
-rw-r--r--sys/cam/scsi/scsi_all.c21
-rw-r--r--sys/cam/scsi/scsi_cd.c13
-rw-r--r--sys/cam/scsi/scsi_da.c83
-rw-r--r--sys/cam/scsi/scsi_enc_ses.c12
-rw-r--r--sys/cddl/compat/opensolaris/sys/kmem.h1
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c26
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c9
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c5
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h6
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c73
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c1
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c143
-rw-r--r--sys/cddl/dev/dtrace/powerpc/dtrace_asm.S44
-rw-r--r--sys/cddl/dev/dtrace/powerpc/dtrace_isa.c83
-rw-r--r--sys/compat/linprocfs/linprocfs.c6
-rw-r--r--sys/compat/linux/linux_emul.c1
-rw-r--r--sys/compat/linux/linux_file.c1
-rw-r--r--sys/compat/linux/linux_file.h19
-rw-r--r--sys/compat/linux/linux_fork.c1
-rw-r--r--sys/compat/linux/linux_futex.c4
-rw-r--r--sys/compat/linux/linux_ioctl.h16
-rw-r--r--sys/compat/linux/linux_ipc.h44
-rw-r--r--sys/compat/linux/linux_mib.c1
-rw-r--r--sys/compat/linux/linux_misc.h48
-rw-r--r--sys/compat/linux/linux_signal.h3
-rw-r--r--sys/compat/linux/linux_socket.c28
-rw-r--r--sys/compat/linux/linux_socket.h40
-rw-r--r--sys/compat/linux/linux_sysctl.c1
-rw-r--r--sys/compat/linux/linux_time.c1
-rw-r--r--sys/conf/Makefile.arm4
-rw-r--r--sys/conf/NOTES5
-rw-r--r--sys/conf/files21
-rw-r--r--sys/conf/files.amd6417
-rw-r--r--sys/conf/files.arm2
-rw-r--r--sys/conf/files.i38612
-rw-r--r--sys/conf/files.mips1
-rw-r--r--sys/conf/ldscript.arm12
-rw-r--r--sys/conf/newvers.sh2
-rw-r--r--sys/conf/options5
-rw-r--r--sys/contrib/dev/acpica/changes.txt152
-rw-r--r--sys/contrib/dev/acpica/common/adfile.c2
-rw-r--r--sys/contrib/dev/acpica/common/adisasm.c18
-rw-r--r--sys/contrib/dev/acpica/common/adwalk.c2
-rw-r--r--sys/contrib/dev/acpica/common/ahpredef.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmextern.c2
-rw-r--r--sys/contrib/dev/acpica/common/dmrestag.c8
-rw-r--r--sys/contrib/dev/acpica/common/dmtable.c5
-rw-r--r--sys/contrib/dev/acpica/common/dmtbdump.c27
-rw-r--r--sys/contrib/dev/acpica/common/dmtbinfo.c53
-rw-r--r--sys/contrib/dev/acpica/common/getopt.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslanalyze.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslbtypes.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcodegen.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompile.c18
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompiler.h49
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompiler.l4
-rw-r--r--sys/contrib/dev/acpica/compiler/aslcompiler.y17
-rw-r--r--sys/contrib/dev/acpica/compiler/asldefine.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslerror.c3
-rw-r--r--sys/contrib/dev/acpica/compiler/aslfileio.c393
-rw-r--r--sys/contrib/dev/acpica/compiler/aslfiles.c350
-rw-r--r--sys/contrib/dev/acpica/compiler/aslfold.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslglobal.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslhex.c401
-rw-r--r--sys/contrib/dev/acpica/compiler/asllength.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asllisting.c486
-rw-r--r--sys/contrib/dev/acpica/compiler/aslload.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asllookup.c1238
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmain.c11
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmap.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmessages.h6
-rw-r--r--sys/contrib/dev/acpica/compiler/aslmethod.c619
-rw-r--r--sys/contrib/dev/acpica/compiler/aslnamesp.c422
-rw-r--r--sys/contrib/dev/acpica/compiler/aslopcodes.c10
-rw-r--r--sys/contrib/dev/acpica/compiler/asloperands.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslopt.c8
-rw-r--r--sys/contrib/dev/acpica/compiler/aslpredef.c17
-rw-r--r--sys/contrib/dev/acpica/compiler/aslresource.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype1.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype1i.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2d.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2e.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2q.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2s.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslrestype2w.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslstartup.c4
-rw-r--r--sys/contrib/dev/acpica/compiler/aslstubs.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslsupport.l2
-rw-r--r--sys/contrib/dev/acpica/compiler/asltransform.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asltree.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/asltypes.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslutils.c5
-rw-r--r--sys/contrib/dev/acpica/compiler/asluuid.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/aslwalks.c573
-rw-r--r--sys/contrib/dev/acpica/compiler/aslxref.c874
-rw-r--r--sys/contrib/dev/acpica/compiler/dtcompile.c12
-rw-r--r--sys/contrib/dev/acpica/compiler/dtcompiler.h17
-rw-r--r--sys/contrib/dev/acpica/compiler/dtexpress.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtfield.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtio.c155
-rw-r--r--sys/contrib/dev/acpica/compiler/dtparser.l2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtparser.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/dtsubtable.c3
-rw-r--r--sys/contrib/dev/acpica/compiler/dttable.c90
-rw-r--r--sys/contrib/dev/acpica/compiler/dttemplate.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/dttemplate.h59
-rw-r--r--sys/contrib/dev/acpica/compiler/dtutils.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/preprocess.h2
-rw-r--r--sys/contrib/dev/acpica/compiler/prexpress.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/prmacros.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/prparser.l2
-rw-r--r--sys/contrib/dev/acpica/compiler/prparser.y2
-rw-r--r--sys/contrib/dev/acpica/compiler/prscan.c2
-rw-r--r--sys/contrib/dev/acpica/compiler/prutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbcmds.c259
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbconvert.c525
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbdisply.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbexec.c510
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbfileio.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbhistry.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbinput.c8
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbmethod.c4
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbnames.c4
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbstats.c2
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbutils.c4
-rw-r--r--sys/contrib/dev/acpica/components/debugger/dbxface.c6
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmbuffer.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmdeferred.c4
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmnames.c8
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmobject.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmopcode.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrc.c5
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrcl.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmresrcs.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/disassembler/dmwalk.c27
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsargs.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dscontrol.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsfield.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsinit.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsmethod.c3
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsobject.c17
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsopcode.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dsutils.c12
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswexec.c6
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswload.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswload2.c4
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswscope.c2
-rw-r--r--sys/contrib/dev/acpica/components/dispatcher/dswstate.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evevent.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evglock.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpe.c8
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpeblk.c12
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpeinit.c5
-rw-r--r--sys/contrib/dev/acpica/components/events/evgpeutil.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evhandler.c578
-rw-r--r--sys/contrib/dev/acpica/components/events/evmisc.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evregion.c634
-rw-r--r--sys/contrib/dev/acpica/components/events/evrgnini.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evsci.c6
-rw-r--r--sys/contrib/dev/acpica/components/events/evxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evxfevnt.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evxfgpe.c2
-rw-r--r--sys/contrib/dev/acpica/components/events/evxfregn.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exconfig.c18
-rw-r--r--sys/contrib/dev/acpica/components/executer/exconvrt.c4
-rw-r--r--sys/contrib/dev/acpica/components/executer/excreate.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exdebug.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exdump.c14
-rw-r--r--sys/contrib/dev/acpica/components/executer/exfield.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exfldio.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exmisc.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exmutex.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exnames.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg1.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg2.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg3.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exoparg6.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exprep.c6
-rw-r--r--sys/contrib/dev/acpica/components/executer/exregion.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exresnte.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exresolv.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exresop.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exstore.c27
-rw-r--r--sys/contrib/dev/acpica/components/executer/exstoren.c4
-rw-r--r--sys/contrib/dev/acpica/components/executer/exstorob.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exsystem.c2
-rw-r--r--sys/contrib/dev/acpica/components/executer/exutils.c22
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwacpi.c14
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwesleep.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwgpe.c4
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwpci.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwregs.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwsleep.c4
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwtimer.c9
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwvalid.c2
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwxface.c132
-rw-r--r--sys/contrib/dev/acpica/components/hardware/hwxfsleep.c4
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsaccess.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsalloc.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsdump.c9
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsdumpdv.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nseval.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsinit.c25
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsload.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsnames.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsobject.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsparse.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nspredef.c601
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsprepkg.c639
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsrepair.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsrepair2.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nssearch.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsutils.c88
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nswalk.c2
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsxfeval.c4
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsxfname.c4
-rw-r--r--sys/contrib/dev/acpica/components/namespace/nsxfobj.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psargs.c10
-rw-r--r--sys/contrib/dev/acpica/components/parser/psloop.c665
-rw-r--r--sys/contrib/dev/acpica/components/parser/psobject.c683
-rw-r--r--sys/contrib/dev/acpica/components/parser/psopcode.c184
-rw-r--r--sys/contrib/dev/acpica/components/parser/psopinfo.c238
-rw-r--r--sys/contrib/dev/acpica/components/parser/psparse.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psscope.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/pstree.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psutils.c13
-rw-r--r--sys/contrib/dev/acpica/components/parser/pswalk.c2
-rw-r--r--sys/contrib/dev/acpica/components/parser/psxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsaddr.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rscalc.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rscreate.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsdump.c315
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsdumpinfo.c357
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsinfo.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsio.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsirq.c34
-rw-r--r--sys/contrib/dev/acpica/components/resources/rslist.c4
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsmemory.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsmisc.c2
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsserial.c10
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsutils.c5
-rw-r--r--sys/contrib/dev/acpica/components/resources/rsxface.c110
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbfadt.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbfind.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbinstal.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbutils.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbxfload.c4
-rw-r--r--sys/contrib/dev/acpica/components/tables/tbxfroot.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utaddress.c6
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utalloc.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utcache.c14
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utcopy.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utdebug.c123
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utdecode.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utdelete.c4
-rw-r--r--sys/contrib/dev/acpica/components/utilities/uteval.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utexcep.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utglobal.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utids.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utinit.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utlock.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utmath.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utmisc.c958
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utmutex.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utobject.c4
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utosi.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utownerid.c241
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utresrc.c8
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utstate.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utstring.c674
-rw-r--r--sys/contrib/dev/acpica/components/utilities/uttrack.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxface.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxferror.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxfinit.c2
-rw-r--r--sys/contrib/dev/acpica/components/utilities/utxfmutex.c2
-rw-r--r--sys/contrib/dev/acpica/include/acapps.h4
-rw-r--r--sys/contrib/dev/acpica/include/acbuffer.h2
-rw-r--r--sys/contrib/dev/acpica/include/accommon.h2
-rw-r--r--sys/contrib/dev/acpica/include/acconfig.h3
-rw-r--r--sys/contrib/dev/acpica/include/acdebug.h35
-rw-r--r--sys/contrib/dev/acpica/include/acdisasm.h4
-rw-r--r--sys/contrib/dev/acpica/include/acdispat.h2
-rw-r--r--sys/contrib/dev/acpica/include/acevents.h31
-rw-r--r--sys/contrib/dev/acpica/include/acexcep.h2
-rw-r--r--sys/contrib/dev/acpica/include/acglobal.h7
-rw-r--r--sys/contrib/dev/acpica/include/achware.h2
-rw-r--r--sys/contrib/dev/acpica/include/acinterp.h4
-rw-r--r--sys/contrib/dev/acpica/include/aclocal.h2
-rw-r--r--sys/contrib/dev/acpica/include/acmacros.h147
-rw-r--r--sys/contrib/dev/acpica/include/acnames.h2
-rw-r--r--sys/contrib/dev/acpica/include/acnamesp.h22
-rw-r--r--sys/contrib/dev/acpica/include/acobject.h2
-rw-r--r--sys/contrib/dev/acpica/include/acopcode.h2
-rw-r--r--sys/contrib/dev/acpica/include/acoutput.h183
-rw-r--r--sys/contrib/dev/acpica/include/acparser.h37
-rw-r--r--sys/contrib/dev/acpica/include/acpi.h2
-rw-r--r--sys/contrib/dev/acpica/include/acpiosxf.h2
-rw-r--r--sys/contrib/dev/acpica/include/acpixf.h10
-rw-r--r--sys/contrib/dev/acpica/include/acpredef.h6
-rw-r--r--sys/contrib/dev/acpica/include/acresrc.h10
-rw-r--r--sys/contrib/dev/acpica/include/acrestyp.h12
-rw-r--r--sys/contrib/dev/acpica/include/acstruct.h2
-rw-r--r--sys/contrib/dev/acpica/include/actables.h2
-rw-r--r--sys/contrib/dev/acpica/include/actbl.h2
-rw-r--r--sys/contrib/dev/acpica/include/actbl1.h2
-rw-r--r--sys/contrib/dev/acpica/include/actbl2.h28
-rw-r--r--sys/contrib/dev/acpica/include/actbl3.h39
-rw-r--r--sys/contrib/dev/acpica/include/actypes.h29
-rw-r--r--sys/contrib/dev/acpica/include/acutils.h111
-rw-r--r--sys/contrib/dev/acpica/include/amlcode.h2
-rw-r--r--sys/contrib/dev/acpica/include/amlresrc.h2
-rw-r--r--sys/contrib/dev/acpica/include/platform/acenv.h4
-rw-r--r--sys/contrib/dev/acpica/include/platform/acfreebsd.h2
-rw-r--r--sys/contrib/dev/acpica/include/platform/acgcc.h4
-rw-r--r--sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c140
-rw-r--r--sys/contrib/octeon-sdk/cvmx-helper-board.c15
-rw-r--r--sys/dev/acpi_support/acpi_asus_wmi.c3
-rw-r--r--sys/dev/acpi_support/acpi_fujitsu.c3
-rw-r--r--sys/dev/acpi_support/acpi_hp.c3
-rw-r--r--sys/dev/acpi_support/acpi_ibm.c2
-rw-r--r--sys/dev/acpi_support/acpi_panasonic.c2
-rw-r--r--sys/dev/acpi_support/acpi_sony.c2
-rw-r--r--sys/dev/acpi_support/acpi_toshiba.c4
-rw-r--r--sys/dev/acpica/Osd/OsdSchedule.c8
-rw-r--r--sys/dev/acpica/acpi.c44
-rw-r--r--sys/dev/acpica/acpi_acad.c2
-rw-r--r--sys/dev/acpica/acpi_button.c3
-rw-r--r--sys/dev/acpica/acpi_cmbat.c2
-rw-r--r--sys/dev/acpica/acpi_dock.c2
-rw-r--r--sys/dev/acpica/acpi_ec.c2
-rw-r--r--sys/dev/acpica/acpi_hpet.c2
-rw-r--r--sys/dev/acpica/acpi_lid.c2
-rw-r--r--sys/dev/acpica/acpi_pci.c2
-rw-r--r--sys/dev/acpica/acpi_pci_link.c2
-rw-r--r--sys/dev/acpica/acpi_pcib.c9
-rw-r--r--sys/dev/acpica/acpi_pcib_pci.c2
-rw-r--r--sys/dev/acpica/acpi_perf.c3
-rw-r--r--sys/dev/acpica/acpi_resource.c2
-rw-r--r--sys/dev/acpica/acpi_smbat.c2
-rw-r--r--sys/dev/acpica/acpi_thermal.c11
-rw-r--r--sys/dev/acpica/acpi_throttle.c2
-rw-r--r--sys/dev/acpica/acpi_timer.c2
-rw-r--r--sys/dev/adlink/adlink.c3
-rw-r--r--sys/dev/agp/agp_i810.c2
-rw-r--r--sys/dev/ahci/ahci.c5
-rw-r--r--sys/dev/altera/avgen/altera_avgen.c96
-rw-r--r--sys/dev/altera/avgen/altera_avgen.h6
-rw-r--r--sys/dev/altera/avgen/altera_avgen_fdt.c154
-rw-r--r--sys/dev/altera/avgen/altera_avgen_nexus.c141
-rw-r--r--sys/dev/altera/jtag_uart/altera_jtag_uart.h2
-rw-r--r--sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c3
-rw-r--r--sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c147
-rw-r--r--sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c2
-rw-r--r--sys/dev/altera/sdcard/altera_sdcard.c1
-rw-r--r--sys/dev/altera/sdcard/altera_sdcard.h4
-rw-r--r--sys/dev/altera/sdcard/altera_sdcard_fdt.c120
-rw-r--r--sys/dev/altera/sdcard/altera_sdcard_io.c7
-rw-r--r--sys/dev/altera/sdcard/altera_sdcard_nexus.c2
-rw-r--r--sys/dev/amdsbwd/amdsbwd.c2
-rw-r--r--sys/dev/amdtemp/amdtemp.c2
-rw-r--r--sys/dev/ata/ata-all.h10
-rw-r--r--sys/dev/ata/ata-lowlevel.c49
-rw-r--r--sys/dev/ata/ata-raid.c3
-rw-r--r--sys/dev/ath/ath_hal/ah.h2
-rw-r--r--[-rwxr-xr-x]sys/dev/ath/ath_hal/ar5211/boss.ini0
-rw-r--r--sys/dev/ath/if_ath.c588
-rw-r--r--sys/dev/ath/if_ath_beacon.c10
-rw-r--r--sys/dev/ath/if_ath_misc.h5
-rw-r--r--sys/dev/ath/if_ath_rx.c16
-rw-r--r--sys/dev/ath/if_ath_sysctl.c31
-rw-r--r--sys/dev/ath/if_ath_tx.c50
-rw-r--r--sys/dev/ath/if_ath_tx_edma.c2
-rw-r--r--sys/dev/ath/if_athvar.h13
-rw-r--r--sys/dev/atkbdc/atkbd.c174
-rw-r--r--sys/dev/atkbdc/atkbd_atkbdc.c8
-rw-r--r--sys/dev/atkbdc/atkbdreg.h5
-rw-r--r--sys/dev/auxio/auxio.c6
-rw-r--r--sys/dev/bge/if_bge.c161
-rw-r--r--[-rwxr-xr-x]sys/dev/bktr/CHANGELOG.TXT0
-rw-r--r--sys/dev/bvm/bvm_console.c240
-rw-r--r--sys/dev/bvm/bvm_dbg.c100
-rw-r--r--sys/dev/cas/if_cas.c17
-rw-r--r--sys/dev/ce/if_ce.c2
-rw-r--r--sys/dev/cfi/cfi_bus_fdt.c2
-rw-r--r--sys/dev/cfi/cfi_bus_ixp4xx.c2
-rw-r--r--sys/dev/ciss/ciss.c46
-rw-r--r--sys/dev/ciss/cissreg.h9
-rw-r--r--sys/dev/ciss/cissvar.h5
-rw-r--r--sys/dev/coretemp/coretemp.c2
-rw-r--r--sys/dev/cp/if_cp.c2
-rw-r--r--sys/dev/cpufreq/ichss.c2
-rw-r--r--sys/dev/ctau/if_ct.c3
-rw-r--r--sys/dev/cx/if_cx.c3
-rw-r--r--sys/dev/cxgbe/adapter.h60
-rw-r--r--sys/dev/cxgbe/common/jhash.h140
-rw-r--r--sys/dev/cxgbe/common/t4_msg.h2
-rw-r--r--sys/dev/cxgbe/firmware/t4fw_cfg.txt8
-rw-r--r--sys/dev/cxgbe/offload.h58
-rw-r--r--sys/dev/cxgbe/t4_l2t.c44
-rw-r--r--sys/dev/cxgbe/t4_l2t.h6
-rw-r--r--sys/dev/cxgbe/t4_main.c664
-rw-r--r--sys/dev/cxgbe/t4_sge.c2
-rw-r--r--sys/dev/cxgbe/tom/t4_connect.c127
-rw-r--r--sys/dev/cxgbe/tom/t4_cpl_io.c3
-rw-r--r--sys/dev/cxgbe/tom/t4_listen.c409
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.c240
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.h24
-rw-r--r--sys/dev/cxgbe/tom/t4_tom_l2t.c124
-rw-r--r--sys/dev/digi/digi_isa.c3
-rw-r--r--sys/dev/digi/digi_pci.c3
-rw-r--r--sys/dev/e1000/if_em.c2
-rw-r--r--sys/dev/e1000/if_igb.c6
-rw-r--r--sys/dev/e1000/if_lem.c2
-rw-r--r--sys/dev/ep/if_ep_eisa.c2
-rw-r--r--sys/dev/ep/if_ep_isa.c2
-rw-r--r--sys/dev/ep/if_ep_mca.c2
-rw-r--r--sys/dev/ep/if_ep_pccard.c2
-rw-r--r--sys/dev/fdc/fdc_acpi.c2
-rw-r--r--sys/dev/fdt/fdt_mips.c22
-rw-r--r--sys/dev/hpt27xx/hpt27xx_config.c6
-rw-r--r--sys/dev/hpt27xx/os_bsd.h6
-rw-r--r--sys/dev/hpt27xx/osm_bsd.c7
-rw-r--r--sys/dev/hwpmc/hwpmc_core.c409
-rw-r--r--sys/dev/hwpmc/hwpmc_intel.c6
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c2
-rw-r--r--sys/dev/hwpmc/hwpmc_soft.c2
-rw-r--r--sys/dev/hwpmc/pmc_events.h204
-rw-r--r--sys/dev/iicbus/ad7418.c2
-rw-r--r--sys/dev/iicbus/ds133x.c2
-rw-r--r--sys/dev/iicbus/ds1672.c2
-rw-r--r--sys/dev/iicbus/icee.c2
-rw-r--r--sys/dev/isf/isf.c1
-rw-r--r--sys/dev/isf/isf.h2
-rw-r--r--sys/dev/isf/isf_fdt.c124
-rw-r--r--sys/dev/isf/isf_nexus.c2
-rw-r--r--sys/dev/ixgb/if_ixgb.c3
-rw-r--r--sys/dev/ixgbe/ixgbe.c3
-rw-r--r--[-rwxr-xr-x]sys/dev/ixgbe/ixgbe_82598.h0
-rw-r--r--[-rwxr-xr-x]sys/dev/ixgbe/ixgbe_82599.h0
-rw-r--r--[-rwxr-xr-x]sys/dev/ixgbe/ixgbe_x540.c0
-rw-r--r--[-rwxr-xr-x]sys/dev/ixgbe/ixgbe_x540.h0
-rw-r--r--sys/dev/ixgbe/ixv.c3
-rw-r--r--sys/dev/mfi/mfi_cam.c3
-rw-r--r--sys/dev/mmc/mmc.c3
-rw-r--r--sys/dev/mmc/mmcreg.h2
-rw-r--r--sys/dev/mn/if_mn.c2
-rw-r--r--sys/dev/mxge/if_mxge.c3
-rw-r--r--sys/dev/my/if_my.c2
-rw-r--r--sys/dev/nand/nand_id.c2
-rw-r--r--sys/dev/netmap/if_em_netmap.h3
-rw-r--r--sys/dev/netmap/if_igb_netmap.h3
-rw-r--r--sys/dev/netmap/if_lem_netmap.h3
-rw-r--r--sys/dev/netmap/if_re_netmap.h3
-rw-r--r--sys/dev/netmap/ixgbe_netmap.h13
-rw-r--r--sys/dev/netmap/netmap.c338
-rw-r--r--sys/dev/netmap/netmap_kern.h8
-rw-r--r--sys/dev/netmap/netmap_mem1.c521
-rw-r--r--sys/dev/netmap/netmap_mem2.c45
-rw-r--r--sys/dev/nvram2env/nvram2env.c3
-rw-r--r--sys/dev/nxge/if_nxge.c3
-rw-r--r--sys/dev/oce/oce_if.c3
-rw-r--r--sys/dev/puc/puc.c2
-rw-r--r--sys/dev/sdhci/sdhci_pci.c2
-rw-r--r--sys/dev/sound/pci/emu10kx-midi.c2
-rw-r--r--sys/dev/sound/pci/emu10kx-pcm.c3
-rw-r--r--sys/dev/sound/pci/emu10kx.c2
-rw-r--r--sys/dev/sound/sbus/cs4231.c6
-rw-r--r--sys/dev/sound/usb/uaudio_pcm.c2
-rw-r--r--sys/dev/sym/sym_hipd.c4
-rw-r--r--sys/dev/terasic/de4led/terasic_de4led.c2
-rw-r--r--sys/dev/terasic/de4led/terasic_de4led.h2
-rw-r--r--sys/dev/terasic/de4led/terasic_de4led_fdt.c118
-rw-r--r--sys/dev/terasic/de4led/terasic_de4led_nexus.c2
-rw-r--r--sys/dev/terasic/mtl/terasic_mtl.c3
-rw-r--r--sys/dev/terasic/mtl/terasic_mtl.h2
-rw-r--r--sys/dev/terasic/mtl/terasic_mtl_fdt.c200
-rw-r--r--sys/dev/terasic/mtl/terasic_mtl_nexus.c2
-rw-r--r--sys/dev/uart/uart_bus.h1
-rw-r--r--sys/dev/uart/uart_bus_acpi.c1
-rw-r--r--sys/dev/uart/uart_bus_isa.c1
-rw-r--r--sys/dev/uart/uart_bus_pci.c1
-rw-r--r--sys/dev/uart/uart_core.c9
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c14
-rw-r--r--sys/dev/usb/controller/at91dci.c23
-rw-r--r--sys/dev/usb/controller/atmegadci.c23
-rw-r--r--sys/dev/usb/controller/avr32dci.c24
-rw-r--r--sys/dev/usb/controller/dwc_otg.c22
-rw-r--r--sys/dev/usb/controller/ehci.c9
-rw-r--r--sys/dev/usb/controller/musb_otg.c20
-rw-r--r--sys/dev/usb/controller/ohci.c9
-rw-r--r--sys/dev/usb/controller/uhci.c9
-rw-r--r--sys/dev/usb/controller/usb_controller.c22
-rw-r--r--sys/dev/usb/controller/uss820dci.c19
-rw-r--r--sys/dev/usb/controller/xhci.c15
-rw-r--r--sys/dev/usb/input/uhid.c3
-rw-r--r--sys/dev/usb/input/ukbd.c39
-rw-r--r--sys/dev/usb/input/ums.c50
-rw-r--r--sys/dev/usb/misc/udbp.c3
-rw-r--r--sys/dev/usb/misc/ufm.c3
-rw-r--r--sys/dev/usb/net/if_axe.c1
-rw-r--r--sys/dev/usb/net/if_cdce.c6
-rw-r--r--sys/dev/usb/net/if_cue.c2
-rw-r--r--sys/dev/usb/net/if_ipheth.c2
-rw-r--r--sys/dev/usb/net/if_kue.c2
-rw-r--r--sys/dev/usb/net/if_smsc.c10
-rw-r--r--sys/dev/usb/quirk/usb_quirk.c7
-rw-r--r--sys/dev/usb/serial/u3g.c1
-rw-r--r--sys/dev/usb/storage/umass.c46
-rw-r--r--sys/dev/usb/storage/urio.c3
-rw-r--r--sys/dev/usb/storage/ustorage_fs.c6
-rw-r--r--sys/dev/usb/template/usb_template.c4
-rw-r--r--sys/dev/usb/template/usb_template_audio.c30
-rw-r--r--sys/dev/usb/template/usb_template_cdce.c61
-rw-r--r--sys/dev/usb/template/usb_template_kbd.c24
-rw-r--r--sys/dev/usb/template/usb_template_modem.c24
-rw-r--r--sys/dev/usb/template/usb_template_mouse.c24
-rw-r--r--sys/dev/usb/template/usb_template_msc.c46
-rw-r--r--sys/dev/usb/template/usb_template_mtp.c42
-rw-r--r--sys/dev/usb/ufm_ioctl.h6
-rw-r--r--sys/dev/usb/usb.h20
-rw-r--r--sys/dev/usb/usb_busdma.c9
-rw-r--r--sys/dev/usb/usb_busdma.h2
-rw-r--r--sys/dev/usb/usb_compat_linux.c6
-rw-r--r--sys/dev/usb/usb_core.c9
-rw-r--r--sys/dev/usb/usb_core.h2
-rw-r--r--sys/dev/usb/usb_debug.c4
-rw-r--r--sys/dev/usb/usb_dev.c4
-rw-r--r--sys/dev/usb/usb_dev.h2
-rw-r--r--sys/dev/usb/usb_device.c4
-rw-r--r--sys/dev/usb/usb_dynamic.c4
-rw-r--r--sys/dev/usb/usb_endian.h2
-rw-r--r--sys/dev/usb/usb_error.c4
-rw-r--r--sys/dev/usb/usb_freebsd.h2
-rw-r--r--sys/dev/usb/usb_freebsd_loader.h84
-rw-r--r--sys/dev/usb/usb_generic.c4
-rw-r--r--sys/dev/usb/usb_handle_request.c4
-rw-r--r--sys/dev/usb/usb_hid.c85
-rw-r--r--sys/dev/usb/usb_hub.c4
-rw-r--r--sys/dev/usb/usb_ioctl.h2
-rw-r--r--sys/dev/usb/usb_lookup.c6
-rw-r--r--sys/dev/usb/usb_mbuf.c4
-rw-r--r--sys/dev/usb/usb_msctest.c4
-rw-r--r--sys/dev/usb/usb_parse.c5
-rw-r--r--sys/dev/usb/usb_pci.h2
-rw-r--r--sys/dev/usb/usb_pf.c7
-rw-r--r--sys/dev/usb/usb_process.c4
-rw-r--r--sys/dev/usb/usb_process.h2
-rw-r--r--sys/dev/usb/usb_request.c4
-rw-r--r--sys/dev/usb/usb_transfer.c4
-rw-r--r--sys/dev/usb/usb_util.c4
-rw-r--r--sys/dev/usb/usbdevs5
-rw-r--r--sys/dev/usb/usbdi.h11
-rw-r--r--sys/dev/usb/usbhid.h4
-rw-r--r--sys/dev/vx/if_vx_eisa.c2
-rw-r--r--sys/dev/vx/if_vx_pci.c2
-rw-r--r--sys/dev/vxge/vxge.c3
-rw-r--r--sys/dev/wbwd/wbwd.c19
-rw-r--r--sys/dev/xen/console/console.c3
-rw-r--r--sys/fs/ext2fs/ext2_alloc.c15
-rw-r--r--sys/fs/ext2fs/ext2_balloc.c2
-rw-r--r--[-rwxr-xr-x]sys/fs/ext2fs/ext2_dinode.h0
-rw-r--r--[-rwxr-xr-x]sys/fs/ext2fs/ext2_dir.h4
-rw-r--r--sys/fs/ext2fs/ext2_inode.c23
-rw-r--r--sys/fs/ext2fs/ext2_lookup.c2
-rw-r--r--sys/fs/ext2fs/ext2_vfsops.c13
-rw-r--r--[-rwxr-xr-x]sys/fs/ext2fs/ext2fs.h45
-rw-r--r--sys/fs/ext2fs/fs.h3
-rw-r--r--sys/fs/ext2fs/inode.h10
-rw-r--r--sys/fs/msdosfs/msdosfs_fat.c19
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c3
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c18
-rw-r--r--sys/fs/nfs/nfs.h1
-rw-r--r--sys/fs/nfs/nfs_commonkrpc.c20
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c8
-rw-r--r--sys/fs/nfs/nfsport.h6
-rw-r--r--sys/fs/nfsclient/nfs_clport.c6
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c2
-rw-r--r--sys/fs/nfsclient/nfs_clstate.c10
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c6
-rw-r--r--sys/fs/nfsserver/nfs_nfsdkrpc.c1
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c20
-rw-r--r--sys/fs/nfsserver/nfs_nfsdserv.c13
-rw-r--r--sys/fs/nfsserver/nfs_nfsdstate.c18
-rw-r--r--sys/fs/nullfs/null_subr.c16
-rw-r--r--sys/fs/nullfs/null_vfsops.c11
-rw-r--r--sys/fs/nullfs/null_vnops.c8
-rw-r--r--sys/geom/journal/g_journal.c2
-rw-r--r--sys/geom/mirror/g_mirror.c25
-rw-r--r--sys/geom/raid/g_raid.c6
-rw-r--r--sys/geom/raid/g_raid.h11
-rw-r--r--sys/geom/raid/md_intel.c271
-rw-r--r--sys/geom/raid/md_promise.c149
-rw-r--r--sys/geom/raid/tr_concat.c3
-rw-r--r--sys/geom/raid3/g_raid3.c21
-rw-r--r--sys/geom/raid3/g_raid3_ctl.c45
-rw-r--r--sys/i386/conf/GENERIC9
-rw-r--r--sys/i386/conf/NOTES9
-rw-r--r--sys/i386/i386/mp_machdep.c4
-rw-r--r--sys/i386/i386/pmap.c16
-rw-r--r--sys/i386/include/intr_machdep.h2
-rw-r--r--sys/i386/include/vmparam.h5
-rw-r--r--sys/i386/linux/linux.h153
-rw-r--r--sys/i386/linux/linux_ptrace.c1
-rw-r--r--sys/i386/linux/linux_sysvec.c1
-rw-r--r--sys/kern/init_main.c1
-rw-r--r--sys/kern/kern_clock.c4
-rw-r--r--sys/kern/kern_clocksource.c18
-rw-r--r--sys/kern/kern_descrip.c7
-rw-r--r--sys/kern/kern_exit.c14
-rw-r--r--sys/kern/kern_ktr.c30
-rw-r--r--sys/kern/kern_mbuf.c27
-rw-r--r--sys/kern/kern_mib.c3
-rw-r--r--sys/kern/kern_tc.c4
-rw-r--r--sys/kern/subr_bus.c2
-rw-r--r--sys/kern/subr_param.c21
-rw-r--r--sys/kern/uipc_mbuf.c73
-rw-r--r--sys/kern/vfs_hash.c19
-rw-r--r--sys/kern/vfs_subr.c14
-rw-r--r--sys/kern/vfs_syscalls.c103
-rw-r--r--sys/kern/vfs_vnops.c15
-rw-r--r--sys/libkern/arm/divsi3.S8
-rw-r--r--sys/libkern/arm/ldivmod.S67
-rw-r--r--sys/libkern/arm/ldivmod_helper.c (renamed from sys/arm/mv/kirkwood/sheevaplug.c)35
-rw-r--r--sys/libkern/quad.h5
-rw-r--r--sys/libkern/ucmpdi2.c12
-rw-r--r--sys/mips/beri/beri_machdep.c44
-rw-r--r--sys/mips/beri/files.beri3
-rw-r--r--sys/mips/include/bus.h2
-rw-r--r--sys/mips/include/fdt.h2
-rw-r--r--sys/mips/include/metadata.h1
-rw-r--r--sys/mips/include/vmparam.h5
-rw-r--r--sys/mips/mips/bus_space_fdt.c212
-rw-r--r--sys/mips/nlm/dev/net/mdio.c23
-rw-r--r--sys/mips/nlm/dev/net/nae.c26
-rw-r--r--sys/mips/nlm/dev/net/sgmii.c7
-rw-r--r--sys/mips/nlm/dev/net/xlpge.c32
-rw-r--r--sys/mips/nlm/hal/fmn.c4
-rw-r--r--sys/mips/nlm/hal/mdio.h1
-rw-r--r--sys/mips/nlm/hal/sys.h13
-rw-r--r--sys/mips/nlm/hal/ucore_loader.h2
-rw-r--r--sys/mips/nlm/xlp_machdep.c21
-rw-r--r--sys/mips/nlm/xlp_pci.c7
-rw-r--r--[-rwxr-xr-x]sys/mips/rmi/msgring_xls.cfg0
-rw-r--r--sys/modules/Makefile2
-rw-r--r--sys/modules/cxgbe/tom/Makefile11
-rw-r--r--[-rwxr-xr-x]sys/modules/digi/Makefile0
-rw-r--r--[-rwxr-xr-x]sys/modules/digi/Makefile.inc0
-rw-r--r--sys/modules/hpt27xx/Makefile3
-rw-r--r--[-rwxr-xr-x]sys/modules/isci/Makefile0
-rw-r--r--[-rwxr-xr-x]sys/modules/sound/driver/ich/Makefile0
-rw-r--r--sys/modules/usb/Makefile2
-rw-r--r--sys/modules/usb/smsc/Makefile2
-rw-r--r--sys/modules/vmm/Makefile62
-rw-r--r--sys/modules/wlan/Makefile2
-rw-r--r--sys/net/bpf.c23
-rw-r--r--sys/net/if_lagg.c4
-rw-r--r--sys/net/if_llatbl.c40
-rw-r--r--sys/net/if_llatbl.h11
-rw-r--r--sys/net/netmap.h49
-rw-r--r--sys/net80211/ieee80211_adhoc.c18
-rw-r--r--sys/net80211/ieee80211_node.c62
-rw-r--r--sys/net80211/ieee80211_power.c40
-rw-r--r--sys/net80211/ieee80211_scan_sta.c24
-rw-r--r--sys/net80211/ieee80211_superg.c4
-rw-r--r--sys/netgraph/ng_ether.c60
-rw-r--r--sys/netinet/if_ether.h14
-rw-r--r--sys/netinet/in.c10
-rw-r--r--sys/netinet/in_pcb.c3
-rw-r--r--sys/netinet/libalias/alias.c16
-rw-r--r--sys/netinet/libalias/libalias.368
-rw-r--r--sys/netinet/tcp.h29
-rw-r--r--sys/netinet/tcp_input.c2
-rw-r--r--sys/netinet/tcp_reass.c8
-rw-r--r--sys/netinet/tcp_syncache.c13
-rw-r--r--sys/netinet/tcp_timer.c8
-rw-r--r--sys/netinet/tcp_usrreq.c10
-rw-r--r--sys/netinet/toecore.c81
-rw-r--r--sys/netinet/udp.h4
-rw-r--r--sys/netinet6/in6_src.c10
-rw-r--r--sys/netinet6/nd6.c6
-rw-r--r--sys/netinet6/nd6.h1
-rw-r--r--sys/netinet6/nd6_nbr.c3
-rw-r--r--sys/netinet6/scope6.c70
-rw-r--r--sys/nfs/nfs_common.c9
-rw-r--r--sys/nfs/nfs_common.h1
-rw-r--r--sys/nfsclient/nfs_krpc.c29
-rw-r--r--sys/nfsclient/nfs_subs.c4
-rw-r--r--sys/nfsclient/nfs_vnops.c6
-rw-r--r--sys/nfsserver/nfs_srvsubs.c4
-rw-r--r--sys/pc98/cbus/pckbd.c16
-rw-r--r--sys/pc98/conf/GENERIC1
-rw-r--r--sys/pci/if_rl.c2
-rw-r--r--sys/pci/if_rlreg.h5
-rw-r--r--sys/pci/ncr.c2
-rw-r--r--sys/security/audit/audit.c13
-rw-r--r--sys/security/audit/audit_bsm.c13
-rw-r--r--sys/security/audit/audit_private.h1
-rw-r--r--sys/sparc64/conf/GENERIC1
-rw-r--r--sys/sparc64/include/smp.h20
-rw-r--r--sys/sparc64/sparc64/tick.c4
-rw-r--r--sys/sys/bufobj.h10
-rw-r--r--sys/sys/kernel.h2
-rw-r--r--sys/sys/mbuf.h123
-rw-r--r--sys/sys/mount.h5
-rw-r--r--sys/sys/param.h10
-rw-r--r--sys/sys/pmc.h1
-rw-r--r--sys/sys/socket.h9
-rw-r--r--sys/sys/systm.h1
-rw-r--r--sys/sys/time.h4
-rw-r--r--sys/sys/un.h9
-rw-r--r--sys/sys/vdso.h6
-rw-r--r--sys/sys/vmmeter.h1
-rw-r--r--sys/sys/vnode.h38
-rw-r--r--sys/ufs/ffs/ffs_inode.c6
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c2
-rw-r--r--sys/ufs/ffs/ffs_softdep.c2
-rw-r--r--sys/ufs/ffs/ffs_suspend.c2
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c18
-rw-r--r--sys/vm/device_pager.c3
-rw-r--r--sys/vm/uma_core.c2
-rw-r--r--sys/vm/vm_fault.c5
-rw-r--r--sys/vm/vm_map.c16
-rw-r--r--sys/vm/vm_map.h1
-rw-r--r--sys/vm/vm_meter.c1
-rw-r--r--sys/vm/vm_mmap.c17
-rw-r--r--sys/vm/vm_object.h1
-rw-r--r--sys/vm/vm_pageout.c45
-rw-r--r--sys/vm/vm_unix.c44
-rw-r--r--sys/x86/x86/intr_machdep.c12
-rw-r--r--sys/x86/x86/local_apic.c13
-rw-r--r--sys/x86/x86/tsc.c72
856 files changed, 37700 insertions, 12532 deletions
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index d2e4aad..31dbb3f 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -1431,11 +1431,11 @@ cpususpend_handler(void)
while (!CPU_ISSET(cpu, &started_cpus))
ia32_pause();
- CPU_CLR_ATOMIC(cpu, &started_cpus);
-
/* Resume MCA and local APIC */
mca_resume();
lapic_setup(0);
+
+ CPU_CLR_ATOMIC(cpu, &started_cpus);
}
/*
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index a7b1e2b..5436b6f 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -102,6 +102,7 @@ __FBSDID("$FreeBSD$");
#include "opt_vm.h"
#include <sys/param.h>
+#include <sys/bus.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
@@ -133,6 +134,8 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_reserv.h>
#include <vm/uma.h>
+#include <machine/intr_machdep.h>
+#include <machine/apicvar.h>
#include <machine/cpu.h>
#include <machine/cputypes.h>
#include <machine/md_var.h>
@@ -1151,6 +1154,15 @@ pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva)
eva - sva < PMAP_CLFLUSH_THRESHOLD) {
/*
+ * XXX: Some CPUs fault, hang, or trash the local APIC
+ * registers if we use CLFLUSH on the local APIC
+ * range. The local APIC is always uncached, so we
+ * don't need to flush for that range anyway.
+ */
+ if (pmap_kextract(sva) == lapic_paddr)
+ return;
+
+ /*
* Otherwise, do per-cache line flush. Use the mfence
* instruction to insure that previous stores are
* included in the write-back. The processor
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 48f41b3..5819a0d 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -197,7 +197,6 @@ device uart # Generic UART driver
device ppc
device ppbus # Parallel port bus (required)
device lpt # Printer
-device plip # TCP/IP over parallel
device ppi # Parallel port interface device
#device vpo # Requires scbus and da
@@ -332,3 +331,11 @@ device snd_via8233 # VIA VT8233x Audio
device mmc # MMC/SD bus
device mmcsd # MMC/SD memory card
device sdhci # Generic PCI SD Host Controller
+
+# VirtIO support
+device virtio # Generic VirtIO bus (required)
+device virtio_pci # VirtIO PCI device
+device vtnet # VirtIO Ethernet device
+device virtio_blk # VirtIO Block device
+device virtio_scsi # VirtIO SCSI device
+device virtio_balloon # VirtIO Memory Balloon device
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index 6562981..a4371f7 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -440,6 +440,15 @@ device safe # SafeNet 1141
options SAFE_DEBUG # enable debugging support: hw.safe.debug
options SAFE_RNDTEST # enable rndtest support
+#
+# VirtIO support
+device virtio # Generic VirtIO bus (required)
+device virtio_pci # VirtIO PCI Interface
+device vtnet # VirtIO Ethernet device
+device virtio_blk # VirtIO Block device
+device virtio_scsi # VirtIO SCSI device
+device virtio_balloon # VirtIO Memory Balloon device
+
#####################################################################
#
diff --git a/sys/amd64/include/intr_machdep.h b/sys/amd64/include/intr_machdep.h
index 700e35f..8671605 100644
--- a/sys/amd64/include/intr_machdep.h
+++ b/sys/amd64/include/intr_machdep.h
@@ -94,7 +94,7 @@ struct pic {
int (*pic_config_intr)(struct intsrc *, enum intr_trigger,
enum intr_polarity);
int (*pic_assign_cpu)(struct intsrc *, u_int apic_id);
- STAILQ_ENTRY(pic) pics;
+ TAILQ_ENTRY(pic) pics;
};
/* Flags for pic_disable_source() */
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
new file mode 100644
index 0000000..ec94083
--- /dev/null
+++ b/sys/amd64/include/vmm.h
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMM_H_
+#define _VMM_H_
+
+#ifdef _KERNEL
+
+#define VM_MAX_NAMELEN 32
+
+struct vm;
+struct vm_memory_segment;
+struct seg_desc;
+struct vm_exit;
+struct vm_run;
+struct vlapic;
+
+enum x2apic_state;
+
+typedef int (*vmm_init_func_t)(void);
+typedef int (*vmm_cleanup_func_t)(void);
+typedef void * (*vmi_init_func_t)(struct vm *vm); /* instance specific apis */
+typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip);
+typedef void (*vmi_cleanup_func_t)(void *vmi);
+typedef int (*vmi_mmap_set_func_t)(void *vmi, vm_paddr_t gpa,
+ vm_paddr_t hpa, size_t length,
+ vm_memattr_t attr, int prot,
+ boolean_t superpages_ok);
+typedef vm_paddr_t (*vmi_mmap_get_func_t)(void *vmi, vm_paddr_t gpa);
+typedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num,
+ uint64_t *retval);
+typedef int (*vmi_set_register_t)(void *vmi, int vcpu, int num,
+ uint64_t val);
+typedef int (*vmi_get_desc_t)(void *vmi, int vcpu, int num,
+ struct seg_desc *desc);
+typedef int (*vmi_set_desc_t)(void *vmi, int vcpu, int num,
+ struct seg_desc *desc);
+typedef int (*vmi_inject_event_t)(void *vmi, int vcpu,
+ int type, int vector,
+ uint32_t code, int code_valid);
+typedef int (*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval);
+typedef int (*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val);
+
+struct vmm_ops {
+ vmm_init_func_t init; /* module wide initialization */
+ vmm_cleanup_func_t cleanup;
+
+ vmi_init_func_t vminit; /* vm-specific initialization */
+ vmi_run_func_t vmrun;
+ vmi_cleanup_func_t vmcleanup;
+ vmi_mmap_set_func_t vmmmap_set;
+ vmi_mmap_get_func_t vmmmap_get;
+ vmi_get_register_t vmgetreg;
+ vmi_set_register_t vmsetreg;
+ vmi_get_desc_t vmgetdesc;
+ vmi_set_desc_t vmsetdesc;
+ vmi_inject_event_t vminject;
+ vmi_get_cap_t vmgetcap;
+ vmi_set_cap_t vmsetcap;
+};
+
+extern struct vmm_ops vmm_ops_intel;
+extern struct vmm_ops vmm_ops_amd;
+
+struct vm *vm_create(const char *name);
+void vm_destroy(struct vm *vm);
+const char *vm_name(struct vm *vm);
+int vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len);
+int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa);
+int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len);
+vm_paddr_t vm_gpa2hpa(struct vm *vm, vm_paddr_t gpa, size_t size);
+int vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase,
+ struct vm_memory_segment *seg);
+int vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval);
+int vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val);
+int vm_get_seg_desc(struct vm *vm, int vcpu, int reg,
+ struct seg_desc *ret_desc);
+int vm_set_seg_desc(struct vm *vm, int vcpu, int reg,
+ struct seg_desc *desc);
+int vm_get_pinning(struct vm *vm, int vcpu, int *cpuid);
+int vm_set_pinning(struct vm *vm, int vcpu, int cpuid);
+int vm_run(struct vm *vm, struct vm_run *vmrun);
+int vm_inject_event(struct vm *vm, int vcpu, int type,
+ int vector, uint32_t error_code, int error_code_valid);
+int vm_inject_nmi(struct vm *vm, int vcpu);
+int vm_nmi_pending(struct vm *vm, int vcpuid);
+void vm_nmi_clear(struct vm *vm, int vcpuid);
+uint64_t *vm_guest_msrs(struct vm *vm, int cpu);
+struct vlapic *vm_lapic(struct vm *vm, int cpu);
+int vm_get_capability(struct vm *vm, int vcpu, int type, int *val);
+int vm_set_capability(struct vm *vm, int vcpu, int type, int val);
+int vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state);
+int vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state);
+void vm_activate_cpu(struct vm *vm, int vcpu);
+cpuset_t vm_active_cpus(struct vm *vm);
+struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);
+
+/*
+ * Return 1 if device indicated by bus/slot/func is supposed to be a
+ * pci passthrough device.
+ *
+ * Return 0 otherwise.
+ */
+int vmm_is_pptdev(int bus, int slot, int func);
+
+void *vm_iommu_domain(struct vm *vm);
+
+enum vcpu_state {
+ VCPU_IDLE,
+ VCPU_RUNNING,
+ VCPU_CANNOT_RUN,
+};
+
+int vcpu_set_state(struct vm *vm, int vcpu, enum vcpu_state state);
+enum vcpu_state vcpu_get_state(struct vm *vm, int vcpu);
+
+static int __inline
+vcpu_is_running(struct vm *vm, int vcpu)
+{
+ return (vcpu_get_state(vm, vcpu) == VCPU_RUNNING);
+}
+
+void *vcpu_stats(struct vm *vm, int vcpu);
+void vm_interrupt_hostcpu(struct vm *vm, int vcpu);
+
+#endif /* KERNEL */
+
+#include <machine/vmm_instruction_emul.h>
+
+#define VM_MAXCPU 8 /* maximum virtual cpus */
+
+/*
+ * Identifiers for events that can be injected into the VM
+ */
+enum vm_event_type {
+ VM_EVENT_NONE,
+ VM_HW_INTR,
+ VM_NMI,
+ VM_HW_EXCEPTION,
+ VM_SW_INTR,
+ VM_PRIV_SW_EXCEPTION,
+ VM_SW_EXCEPTION,
+ VM_EVENT_MAX
+};
+
+/*
+ * Identifiers for architecturally defined registers.
+ */
+enum vm_reg_name {
+ VM_REG_GUEST_RAX,
+ VM_REG_GUEST_RBX,
+ VM_REG_GUEST_RCX,
+ VM_REG_GUEST_RDX,
+ VM_REG_GUEST_RSI,
+ VM_REG_GUEST_RDI,
+ VM_REG_GUEST_RBP,
+ VM_REG_GUEST_R8,
+ VM_REG_GUEST_R9,
+ VM_REG_GUEST_R10,
+ VM_REG_GUEST_R11,
+ VM_REG_GUEST_R12,
+ VM_REG_GUEST_R13,
+ VM_REG_GUEST_R14,
+ VM_REG_GUEST_R15,
+ VM_REG_GUEST_CR0,
+ VM_REG_GUEST_CR3,
+ VM_REG_GUEST_CR4,
+ VM_REG_GUEST_DR7,
+ VM_REG_GUEST_RSP,
+ VM_REG_GUEST_RIP,
+ VM_REG_GUEST_RFLAGS,
+ VM_REG_GUEST_ES,
+ VM_REG_GUEST_CS,
+ VM_REG_GUEST_SS,
+ VM_REG_GUEST_DS,
+ VM_REG_GUEST_FS,
+ VM_REG_GUEST_GS,
+ VM_REG_GUEST_LDTR,
+ VM_REG_GUEST_TR,
+ VM_REG_GUEST_IDTR,
+ VM_REG_GUEST_GDTR,
+ VM_REG_GUEST_EFER,
+ VM_REG_LAST
+};
+
+/*
+ * Identifiers for optional vmm capabilities
+ */
+enum vm_cap_type {
+ VM_CAP_HALT_EXIT,
+ VM_CAP_MTRAP_EXIT,
+ VM_CAP_PAUSE_EXIT,
+ VM_CAP_UNRESTRICTED_GUEST,
+ VM_CAP_MAX
+};
+
+enum x2apic_state {
+ X2APIC_ENABLED,
+ X2APIC_AVAILABLE,
+ X2APIC_DISABLED,
+ X2APIC_STATE_LAST
+};
+
+/*
+ * The 'access' field has the format specified in Table 21-2 of the Intel
+ * Architecture Manual vol 3b.
+ *
+ * XXX The contents of the 'access' field are architecturally defined except
+ * bit 16 - Segment Unusable.
+ */
+struct seg_desc {
+ uint64_t base;
+ uint32_t limit;
+ uint32_t access;
+};
+
+enum vm_exitcode {
+ VM_EXITCODE_INOUT,
+ VM_EXITCODE_VMX,
+ VM_EXITCODE_BOGUS,
+ VM_EXITCODE_RDMSR,
+ VM_EXITCODE_WRMSR,
+ VM_EXITCODE_HLT,
+ VM_EXITCODE_MTRAP,
+ VM_EXITCODE_PAUSE,
+ VM_EXITCODE_PAGING,
+ VM_EXITCODE_SPINUP_AP,
+ VM_EXITCODE_MAX
+};
+
+struct vm_exit {
+ enum vm_exitcode exitcode;
+ int inst_length; /* 0 means unknown */
+ uint64_t rip;
+ union {
+ struct {
+ uint16_t bytes:3; /* 1 or 2 or 4 */
+ uint16_t in:1; /* out is 0, in is 1 */
+ uint16_t string:1;
+ uint16_t rep:1;
+ uint16_t port;
+ uint32_t eax; /* valid for out */
+ } inout;
+ struct {
+ uint64_t gpa;
+ struct vie vie;
+ } paging;
+ /*
+ * VMX specific payload. Used when there is no "better"
+ * exitcode to represent the VM-exit.
+ */
+ struct {
+ int error; /* vmx inst error */
+ uint32_t exit_reason;
+ uint64_t exit_qualification;
+ } vmx;
+ struct {
+ uint32_t code; /* ecx value */
+ uint64_t wval;
+ } msr;
+ struct {
+ int vcpu;
+ uint64_t rip;
+ } spinup_ap;
+ } u;
+};
+
+#endif /* _VMM_H_ */
diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h
new file mode 100644
index 0000000..2311673
--- /dev/null
+++ b/sys/amd64/include/vmm_dev.h
@@ -0,0 +1,215 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMM_DEV_H_
+#define _VMM_DEV_H_
+
+#ifdef _KERNEL
+void vmmdev_init(void);
+int vmmdev_cleanup(void);
+#endif
+
+struct vm_memory_segment {
+ vm_paddr_t gpa; /* in */
+ size_t len; /* in */
+};
+
+struct vm_register {
+ int cpuid;
+ int regnum; /* enum vm_reg_name */
+ uint64_t regval;
+};
+
+struct vm_seg_desc { /* data or code segment */
+ int cpuid;
+ int regnum; /* enum vm_reg_name */
+ struct seg_desc desc;
+};
+
+struct vm_pin {
+ int vm_cpuid;
+ int host_cpuid; /* -1 to unpin */
+};
+
+struct vm_run {
+ int cpuid;
+ uint64_t rip; /* start running here */
+ struct vm_exit vm_exit;
+};
+
+struct vm_event {
+ int cpuid;
+ enum vm_event_type type;
+ int vector;
+ uint32_t error_code;
+ int error_code_valid;
+};
+
+struct vm_lapic_irq {
+ int cpuid;
+ int vector;
+};
+
+struct vm_capability {
+ int cpuid;
+ enum vm_cap_type captype;
+ int capval;
+ int allcpus;
+};
+
+struct vm_pptdev {
+ int bus;
+ int slot;
+ int func;
+};
+
+struct vm_pptdev_mmio {
+ int bus;
+ int slot;
+ int func;
+ vm_paddr_t gpa;
+ vm_paddr_t hpa;
+ size_t len;
+};
+
+struct vm_pptdev_msi {
+ int vcpu;
+ int bus;
+ int slot;
+ int func;
+ int numvec; /* 0 means disabled */
+ int vector;
+ int destcpu;
+};
+
+struct vm_pptdev_msix {
+ int vcpu;
+ int bus;
+ int slot;
+ int func;
+ int idx;
+ uint32_t msg;
+ uint32_t vector_control;
+ uint64_t addr;
+};
+
+struct vm_nmi {
+ int cpuid;
+};
+
+#define MAX_VM_STATS 64
+struct vm_stats {
+ int cpuid; /* in */
+ int num_entries; /* out */
+ struct timeval tv;
+ uint64_t statbuf[MAX_VM_STATS];
+};
+
+struct vm_stat_desc {
+ int index; /* in */
+ char desc[128]; /* out */
+};
+
+struct vm_x2apic {
+ int cpuid;
+ enum x2apic_state state;
+};
+
+enum {
+ IOCNUM_RUN,
+ IOCNUM_SET_PINNING,
+ IOCNUM_GET_PINNING,
+ IOCNUM_MAP_MEMORY,
+ IOCNUM_GET_MEMORY_SEG,
+ IOCNUM_SET_REGISTER,
+ IOCNUM_GET_REGISTER,
+ IOCNUM_SET_SEGMENT_DESCRIPTOR,
+ IOCNUM_GET_SEGMENT_DESCRIPTOR,
+ IOCNUM_INJECT_EVENT,
+ IOCNUM_LAPIC_IRQ,
+ IOCNUM_SET_CAPABILITY,
+ IOCNUM_GET_CAPABILITY,
+ IOCNUM_BIND_PPTDEV,
+ IOCNUM_UNBIND_PPTDEV,
+ IOCNUM_MAP_PPTDEV_MMIO,
+ IOCNUM_PPTDEV_MSI,
+ IOCNUM_PPTDEV_MSIX,
+ IOCNUM_INJECT_NMI,
+ IOCNUM_VM_STATS,
+ IOCNUM_VM_STAT_DESC,
+ IOCNUM_SET_X2APIC_STATE,
+ IOCNUM_GET_X2APIC_STATE,
+};
+
+#define VM_RUN \
+ _IOWR('v', IOCNUM_RUN, struct vm_run)
+#define VM_SET_PINNING \
+ _IOW('v', IOCNUM_SET_PINNING, struct vm_pin)
+#define VM_GET_PINNING \
+ _IOWR('v', IOCNUM_GET_PINNING, struct vm_pin)
+#define VM_MAP_MEMORY \
+ _IOWR('v', IOCNUM_MAP_MEMORY, struct vm_memory_segment)
+#define VM_GET_MEMORY_SEG \
+ _IOWR('v', IOCNUM_GET_MEMORY_SEG, struct vm_memory_segment)
+#define VM_SET_REGISTER \
+ _IOW('v', IOCNUM_SET_REGISTER, struct vm_register)
+#define VM_GET_REGISTER \
+ _IOWR('v', IOCNUM_GET_REGISTER, struct vm_register)
+#define VM_SET_SEGMENT_DESCRIPTOR \
+ _IOW('v', IOCNUM_SET_SEGMENT_DESCRIPTOR, struct vm_seg_desc)
+#define VM_GET_SEGMENT_DESCRIPTOR \
+ _IOWR('v', IOCNUM_GET_SEGMENT_DESCRIPTOR, struct vm_seg_desc)
+#define VM_INJECT_EVENT \
+ _IOW('v', IOCNUM_INJECT_EVENT, struct vm_event)
+#define VM_LAPIC_IRQ \
+ _IOW('v', IOCNUM_LAPIC_IRQ, struct vm_lapic_irq)
+#define VM_SET_CAPABILITY \
+ _IOW('v', IOCNUM_SET_CAPABILITY, struct vm_capability)
+#define VM_GET_CAPABILITY \
+ _IOWR('v', IOCNUM_GET_CAPABILITY, struct vm_capability)
+#define VM_BIND_PPTDEV \
+ _IOW('v', IOCNUM_BIND_PPTDEV, struct vm_pptdev)
+#define VM_UNBIND_PPTDEV \
+ _IOW('v', IOCNUM_UNBIND_PPTDEV, struct vm_pptdev)
+#define VM_MAP_PPTDEV_MMIO \
+ _IOW('v', IOCNUM_MAP_PPTDEV_MMIO, struct vm_pptdev_mmio)
+#define VM_PPTDEV_MSI \
+ _IOW('v', IOCNUM_PPTDEV_MSI, struct vm_pptdev_msi)
+#define VM_PPTDEV_MSIX \
+ _IOW('v', IOCNUM_PPTDEV_MSIX, struct vm_pptdev_msix)
+#define VM_INJECT_NMI \
+ _IOW('v', IOCNUM_INJECT_NMI, struct vm_nmi)
+#define VM_STATS \
+ _IOWR('v', IOCNUM_VM_STATS, struct vm_stats)
+#define VM_STAT_DESC \
+ _IOWR('v', IOCNUM_VM_STAT_DESC, struct vm_stat_desc)
+#define VM_SET_X2APIC_STATE \
+ _IOW('v', IOCNUM_SET_X2APIC_STATE, struct vm_x2apic)
+#define VM_GET_X2APIC_STATE \
+ _IOWR('v', IOCNUM_GET_X2APIC_STATE, struct vm_x2apic)
+#endif
diff --git a/sys/amd64/include/vmm_instruction_emul.h b/sys/amd64/include/vmm_instruction_emul.h
new file mode 100644
index 0000000..4c7a346
--- /dev/null
+++ b/sys/amd64/include/vmm_instruction_emul.h
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMM_INSTRUCTION_EMUL_H_
+#define _VMM_INSTRUCTION_EMUL_H_
+
+/*
+ * The data structures 'vie' and 'vie_op' are meant to be opaque to the
+ * consumers of instruction decoding. The only reason why their contents
+ * need to be exposed is because they are part of the 'vm_exit' structure.
+ */
+struct vie_op {
+ uint8_t op_byte; /* actual opcode byte */
+ uint8_t op_type; /* type of operation (e.g. MOV) */
+ uint16_t op_flags;
+};
+
+#define VIE_INST_SIZE 15
+struct vie {
+ uint8_t inst[VIE_INST_SIZE]; /* instruction bytes */
+ uint8_t num_valid; /* size of the instruction */
+ uint8_t num_processed;
+
+ uint8_t rex_w:1, /* REX prefix */
+ rex_r:1,
+ rex_x:1,
+ rex_b:1,
+ rex_present:1;
+
+ uint8_t mod:2, /* ModRM byte */
+ reg:4,
+ rm:4;
+
+ uint8_t ss:2, /* SIB byte */
+ index:4,
+ base:4;
+
+ uint8_t disp_bytes;
+ uint8_t imm_bytes;
+
+ uint8_t scale;
+ int base_register; /* VM_REG_GUEST_xyz */
+ int index_register; /* VM_REG_GUEST_xyz */
+
+ int64_t displacement; /* optional addr displacement */
+ int64_t immediate; /* optional immediate operand */
+
+ uint8_t decoded; /* set to 1 if successfully decoded */
+
+ struct vie_op op; /* opcode description */
+};
+
+/*
+ * Callback functions to read and write memory regions.
+ */
+typedef int (*mem_region_read_t)(void *vm, int cpuid, uint64_t gpa,
+ uint64_t *rval, int rsize, void *arg);
+
+typedef int (*mem_region_write_t)(void *vm, int cpuid, uint64_t gpa,
+ uint64_t wval, int wsize, void *arg);
+
+/*
+ * Emulate the decoded 'vie' instruction.
+ *
+ * The callbacks 'mrr' and 'mrw' emulate reads and writes to the memory region
+ * containing 'gpa'. 'mrarg' is an opaque argument that is passed into the
+ * callback functions.
+ *
+ * 'void *vm' should be 'struct vm *' when called from kernel context and
+ * 'struct vmctx *' when called from user context.
+ * s
+ */
+int vmm_emulate_instruction(void *vm, int cpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t mrr, mem_region_write_t mrw,
+ void *mrarg);
+
+#ifdef _KERNEL
+/*
+ * APIs to fetch and decode the instruction from nested page fault handler.
+ */
+int vmm_fetch_instruction(struct vm *vm, int cpuid,
+ uint64_t rip, int inst_length, uint64_t cr3,
+ struct vie *vie);
+
+int vmm_decode_instruction(struct vm *vm, int cpuid,
+ uint64_t gla, struct vie *vie);
+#endif /* _KERNEL */
+
+#endif /* _VMM_INSTRUCTION_EMUL_H_ */
diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h
index 2c269d3..7b52a64 100644
--- a/sys/amd64/linux32/linux.h
+++ b/sys/amd64/linux32/linux.h
@@ -107,11 +107,6 @@ typedef struct {
/*
* Miscellaneous
*/
-#define LINUX_NAME_MAX 255
-#define LINUX_MAX_UTSNAME 65
-
-#define LINUX_CTL_MAXNAME 10
-
#define LINUX_AT_COUNT 16 /* Count of used aux entry types.
* Keep this synchronized with
* elf_linux_fixup() code.
@@ -127,11 +122,6 @@ struct l___sysctl_args
l_ulong __spare[4];
} __packed;
-/* Scheduling policies */
-#define LINUX_SCHED_OTHER 0
-#define LINUX_SCHED_FIFO 1
-#define LINUX_SCHED_RR 2
-
/* Resource limits */
#define LINUX_RLIMIT_CPU 0
#define LINUX_RLIMIT_FSIZE 1
@@ -265,15 +255,6 @@ struct l_statfs64 {
l_int f_spare[6];
} __packed;
-struct l_new_utsname {
- char sysname[LINUX_MAX_UTSNAME];
- char nodename[LINUX_MAX_UTSNAME];
- char release[LINUX_MAX_UTSNAME];
- char version[LINUX_MAX_UTSNAME];
- char machine[LINUX_MAX_UTSNAME];
- char domainname[LINUX_MAX_UTSNAME];
-} __packed;
-
/*
* Signalling
*/
@@ -535,27 +516,9 @@ struct l_rt_sigframe {
l_handler_t sf_handler;
} __packed;
-extern int bsd_to_linux_signal[];
-extern int linux_to_bsd_signal[];
extern struct sysentvec elf_linux_sysvec;
/*
- * Pluggable ioctl handlers
- */
-struct linux_ioctl_args;
-struct thread;
-
-typedef int linux_ioctl_function_t(struct thread *, struct linux_ioctl_args *);
-
-struct linux_ioctl_handler {
- linux_ioctl_function_t *func;
- int low, high;
-};
-
-int linux_ioctl_register_handler(struct linux_ioctl_handler *h);
-int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
-
-/*
* open/fcntl flags
*/
#define LINUX_O_RDONLY 00000000
@@ -597,65 +560,6 @@ int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
#define LINUX_F_WRLCK 1
#define LINUX_F_UNLCK 2
-/*
- * posix_fadvise advice
- */
-#define LINUX_POSIX_FADV_NORMAL 0
-#define LINUX_POSIX_FADV_RANDOM 1
-#define LINUX_POSIX_FADV_SEQUENTIAL 2
-#define LINUX_POSIX_FADV_WILLNEED 3
-#define LINUX_POSIX_FADV_DONTNEED 4
-#define LINUX_POSIX_FADV_NOREUSE 5
-
-/*
- * mount flags
- */
-#define LINUX_MS_RDONLY 0x0001
-#define LINUX_MS_NOSUID 0x0002
-#define LINUX_MS_NODEV 0x0004
-#define LINUX_MS_NOEXEC 0x0008
-#define LINUX_MS_REMOUNT 0x0020
-
-/*
- * SystemV IPC defines
- */
-#define LINUX_SEMOP 1
-#define LINUX_SEMGET 2
-#define LINUX_SEMCTL 3
-#define LINUX_MSGSND 11
-#define LINUX_MSGRCV 12
-#define LINUX_MSGGET 13
-#define LINUX_MSGCTL 14
-#define LINUX_SHMAT 21
-#define LINUX_SHMDT 22
-#define LINUX_SHMGET 23
-#define LINUX_SHMCTL 24
-
-#define LINUX_IPC_RMID 0
-#define LINUX_IPC_SET 1
-#define LINUX_IPC_STAT 2
-#define LINUX_IPC_INFO 3
-
-#define LINUX_SHM_LOCK 11
-#define LINUX_SHM_UNLOCK 12
-#define LINUX_SHM_STAT 13
-#define LINUX_SHM_INFO 14
-
-#define LINUX_SHM_RDONLY 0x1000
-#define LINUX_SHM_RND 0x2000
-#define LINUX_SHM_REMAP 0x4000
-
-/* semctl commands */
-#define LINUX_GETPID 11
-#define LINUX_GETVAL 12
-#define LINUX_GETALL 13
-#define LINUX_GETNCNT 14
-#define LINUX_GETZCNT 15
-#define LINUX_SETVAL 16
-#define LINUX_SETALL 17
-#define LINUX_SEM_STAT 18
-#define LINUX_SEM_INFO 19
-
union l_semun {
l_int val;
l_uintptr_t buf;
@@ -667,25 +571,6 @@ union l_semun {
/*
* Socket defines
*/
-#define LINUX_SOCKET 1
-#define LINUX_BIND 2
-#define LINUX_CONNECT 3
-#define LINUX_LISTEN 4
-#define LINUX_ACCEPT 5
-#define LINUX_GETSOCKNAME 6
-#define LINUX_GETPEERNAME 7
-#define LINUX_SOCKETPAIR 8
-#define LINUX_SEND 9
-#define LINUX_RECV 10
-#define LINUX_SENDTO 11
-#define LINUX_RECVFROM 12
-#define LINUX_SHUTDOWN 13
-#define LINUX_SETSOCKOPT 14
-#define LINUX_GETSOCKOPT 15
-#define LINUX_SENDMSG 16
-#define LINUX_RECVMSG 17
-#define LINUX_ACCEPT4 18
-
#define LINUX_SOL_SOCKET 1
#define LINUX_SOL_IP 0
#define LINUX_SOL_IPX 256
@@ -714,17 +599,6 @@ union l_semun {
#define LINUX_SO_TIMESTAMP 29
#define LINUX_SO_ACCEPTCONN 30
-#define LINUX_IP_TOS 1
-#define LINUX_IP_TTL 2
-#define LINUX_IP_HDRINCL 3
-#define LINUX_IP_OPTIONS 4
-
-#define LINUX_IP_MULTICAST_IF 32
-#define LINUX_IP_MULTICAST_TTL 33
-#define LINUX_IP_MULTICAST_LOOP 34
-#define LINUX_IP_ADD_MEMBERSHIP 35
-#define LINUX_IP_DROP_MEMBERSHIP 36
-
struct l_sockaddr {
l_ushort sa_family;
char sa_data[14];
@@ -890,30 +764,6 @@ struct l_user_desc {
#define LINUX_GET_USEABLE(desc) \
(((desc)->b >> LINUX_ENTRY_B_USEABLE) & 1)
-#define LINUX_CLOCK_REALTIME 0
-#define LINUX_CLOCK_MONOTONIC 1
-#define LINUX_CLOCK_PROCESS_CPUTIME_ID 2
-#define LINUX_CLOCK_THREAD_CPUTIME_ID 3
-#define LINUX_CLOCK_REALTIME_HR 4
-#define LINUX_CLOCK_MONOTONIC_HR 5
-
-#define LINUX_CLONE_VM 0x00000100
-#define LINUX_CLONE_FS 0x00000200
-#define LINUX_CLONE_FILES 0x00000400
-#define LINUX_CLONE_SIGHAND 0x00000800
-#define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */
-#define LINUX_CLONE_VFORK 0x00004000
-#define LINUX_CLONE_PARENT 0x00008000
-#define LINUX_CLONE_THREAD 0x00010000
-#define LINUX_CLONE_SETTLS 0x00080000
-#define LINUX_CLONE_PARENT_SETTID 0x00100000
-#define LINUX_CLONE_CHILD_CLEARTID 0x00200000
-#define LINUX_CLONE_CHILD_SETTID 0x01000000
-
-#define LINUX_THREADING_FLAGS \
- (LINUX_CLONE_VM | LINUX_CLONE_FS | LINUX_CLONE_FILES | \
- LINUX_CLONE_SIGHAND | LINUX_CLONE_THREAD)
-
struct iovec;
struct l_iovec32 {
@@ -935,7 +785,4 @@ struct linux_robust_list_head {
l_uintptr_t pending_list;
};
-int linux_set_upcall_kse(struct thread *td, register_t stack);
-int linux_set_cloned_tls(struct thread *td, void *desc);
-
#endif /* !_AMD64_LINUX_H_ */
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 5afc9ce..42500da 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <amd64/linux32/linux32_proto.h>
#include <compat/linux/linux_emul.h>
#include <compat/linux/linux_futex.h>
+#include <compat/linux/linux_ioctl.h>
#include <compat/linux/linux_mib.h>
#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_signal.h>
diff --git a/sys/amd64/vmm/amd/amdv.c b/sys/amd64/vmm/amd/amdv.c
new file mode 100644
index 0000000..dc071d3
--- /dev/null
+++ b/sys/amd64/vmm/amd/amdv.c
@@ -0,0 +1,265 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/smp.h>
+
+#include <machine/vmm.h>
+#include "io/iommu.h"
+
+static int
+amdv_init(void)
+{
+
+ printf("amdv_init: not implemented\n");
+ return (ENXIO);
+}
+
+static int
+amdv_cleanup(void)
+{
+
+ printf("amdv_cleanup: not implemented\n");
+ return (ENXIO);
+}
+
+static void *
+amdv_vminit(struct vm *vm)
+{
+
+ printf("amdv_vminit: not implemented\n");
+ return (NULL);
+}
+
+static int
+amdv_vmrun(void *arg, int vcpu, register_t rip)
+{
+
+ printf("amdv_vmrun: not implemented\n");
+ return (ENXIO);
+}
+
+static void
+amdv_vmcleanup(void *arg)
+{
+
+ printf("amdv_vmcleanup: not implemented\n");
+ return;
+}
+
+static int
+amdv_vmmmap_set(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t length,
+ vm_memattr_t attr, int prot, boolean_t spok)
+{
+
+ printf("amdv_vmmmap_set: not implemented\n");
+ return (EINVAL);
+}
+
+static vm_paddr_t
+amdv_vmmmap_get(void *arg, vm_paddr_t gpa)
+{
+
+ printf("amdv_vmmmap_get: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_getreg(void *arg, int vcpu, int regnum, uint64_t *retval)
+{
+
+ printf("amdv_getreg: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_setreg(void *arg, int vcpu, int regnum, uint64_t val)
+{
+
+ printf("amdv_setreg: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_getdesc(void *vmi, int vcpu, int num, struct seg_desc *desc)
+{
+
+ printf("amdv_get_desc: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_setdesc(void *vmi, int vcpu, int num, struct seg_desc *desc)
+{
+
+ printf("amdv_get_desc: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_inject_event(void *vmi, int vcpu, int type, int vector,
+ uint32_t error_code, int error_code_valid)
+{
+
+ printf("amdv_inject_event: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_getcap(void *arg, int vcpu, int type, int *retval)
+{
+
+ printf("amdv_getcap: not implemented\n");
+ return (EINVAL);
+}
+
+static int
+amdv_setcap(void *arg, int vcpu, int type, int val)
+{
+
+ printf("amdv_setcap: not implemented\n");
+ return (EINVAL);
+}
+
+struct vmm_ops vmm_ops_amd = {
+ amdv_init,
+ amdv_cleanup,
+ amdv_vminit,
+ amdv_vmrun,
+ amdv_vmcleanup,
+ amdv_vmmmap_set,
+ amdv_vmmmap_get,
+ amdv_getreg,
+ amdv_setreg,
+ amdv_getdesc,
+ amdv_setdesc,
+ amdv_inject_event,
+ amdv_getcap,
+ amdv_setcap
+};
+
+static int
+amd_iommu_init(void)
+{
+
+ printf("amd_iommu_init: not implemented\n");
+ return (ENXIO);
+}
+
+static void
+amd_iommu_cleanup(void)
+{
+
+ printf("amd_iommu_cleanup: not implemented\n");
+}
+
+static void
+amd_iommu_enable(void)
+{
+
+ printf("amd_iommu_enable: not implemented\n");
+}
+
+static void
+amd_iommu_disable(void)
+{
+
+ printf("amd_iommu_disable: not implemented\n");
+}
+
+static void *
+amd_iommu_create_domain(vm_paddr_t maxaddr)
+{
+
+ printf("amd_iommu_create_domain: not implemented\n");
+ return (NULL);
+}
+
+static void
+amd_iommu_destroy_domain(void *domain)
+{
+
+ printf("amd_iommu_destroy_domain: not implemented\n");
+}
+
+static uint64_t
+amd_iommu_create_mapping(void *domain, vm_paddr_t gpa, vm_paddr_t hpa,
+ uint64_t len)
+{
+
+ printf("amd_iommu_create_mapping: not implemented\n");
+ return (0);
+}
+
+static uint64_t
+amd_iommu_remove_mapping(void *domain, vm_paddr_t gpa, uint64_t len)
+{
+
+ printf("amd_iommu_remove_mapping: not implemented\n");
+ return (0);
+}
+
+static void
+amd_iommu_add_device(void *domain, int bus, int slot, int func)
+{
+
+ printf("amd_iommu_add_device: not implemented\n");
+}
+
+static void
+amd_iommu_remove_device(void *domain, int bus, int slot, int func)
+{
+
+ printf("amd_iommu_remove_device: not implemented\n");
+}
+
+static void
+amd_iommu_invalidate_tlb(void *domain)
+{
+
+ printf("amd_iommu_invalidate_tlb: not implemented\n");
+}
+
+struct iommu_ops iommu_ops_amd = {
+ amd_iommu_init,
+ amd_iommu_cleanup,
+ amd_iommu_enable,
+ amd_iommu_disable,
+ amd_iommu_create_domain,
+ amd_iommu_destroy_domain,
+ amd_iommu_create_mapping,
+ amd_iommu_remove_mapping,
+ amd_iommu_add_device,
+ amd_iommu_remove_device,
+ amd_iommu_invalidate_tlb,
+};
diff --git a/sys/amd64/vmm/intel/ept.c b/sys/amd64/vmm/intel/ept.c
new file mode 100644
index 0000000..4f91601
--- /dev/null
+++ b/sys/amd64/vmm/intel/ept.c
@@ -0,0 +1,392 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/param.h>
+#include <machine/cpufunc.h>
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+
+#include <machine/vmm.h>
+#include "vmx_cpufunc.h"
+#include "vmx_msr.h"
+#include "vmx.h"
+#include "ept.h"
+
+#define EPT_PWL4(cap) ((cap) & (1UL << 6))
+#define EPT_MEMORY_TYPE_WB(cap) ((cap) & (1UL << 14))
+#define EPT_PDE_SUPERPAGE(cap) ((cap) & (1UL << 16)) /* 2MB pages */
+#define EPT_PDPTE_SUPERPAGE(cap) ((cap) & (1UL << 17)) /* 1GB pages */
+#define INVVPID_SUPPORTED(cap) ((cap) & (1UL << 32))
+#define INVEPT_SUPPORTED(cap) ((cap) & (1UL << 20))
+
+#define INVVPID_ALL_TYPES_MASK 0xF0000000000UL
+#define INVVPID_ALL_TYPES_SUPPORTED(cap) \
+ (((cap) & INVVPID_ALL_TYPES_MASK) == INVVPID_ALL_TYPES_MASK)
+
+#define INVEPT_ALL_TYPES_MASK 0x6000000UL
+#define INVEPT_ALL_TYPES_SUPPORTED(cap) \
+ (((cap) & INVEPT_ALL_TYPES_MASK) == INVEPT_ALL_TYPES_MASK)
+
+#define EPT_PG_RD (1 << 0)
+#define EPT_PG_WR (1 << 1)
+#define EPT_PG_EX (1 << 2)
+#define EPT_PG_MEMORY_TYPE(x) ((x) << 3)
+#define EPT_PG_IGNORE_PAT (1 << 6)
+#define EPT_PG_SUPERPAGE (1 << 7)
+
+#define EPT_ADDR_MASK ((uint64_t)-1 << 12)
+
+MALLOC_DECLARE(M_VMX);
+
+static uint64_t page_sizes_mask;
+
+int
+ept_init(void)
+{
+ int page_shift;
+ uint64_t cap;
+
+ cap = rdmsr(MSR_VMX_EPT_VPID_CAP);
+
+ /*
+ * Verify that:
+ * - page walk length is 4 steps
+ * - extended page tables can be laid out in write-back memory
+ * - invvpid instruction with all possible types is supported
+ * - invept instruction with all possible types is supported
+ */
+ if (!EPT_PWL4(cap) ||
+ !EPT_MEMORY_TYPE_WB(cap) ||
+ !INVVPID_SUPPORTED(cap) ||
+ !INVVPID_ALL_TYPES_SUPPORTED(cap) ||
+ !INVEPT_SUPPORTED(cap) ||
+ !INVEPT_ALL_TYPES_SUPPORTED(cap))
+ return (EINVAL);
+
+ /* Set bits in 'page_sizes_mask' for each valid page size */
+ page_shift = PAGE_SHIFT;
+ page_sizes_mask = 1UL << page_shift; /* 4KB page */
+
+ page_shift += 9;
+ if (EPT_PDE_SUPERPAGE(cap))
+ page_sizes_mask |= 1UL << page_shift; /* 2MB superpage */
+
+ page_shift += 9;
+ if (EPT_PDPTE_SUPERPAGE(cap))
+ page_sizes_mask |= 1UL << page_shift; /* 1GB superpage */
+
+ return (0);
+}
+
+#if 0
+static void
+ept_dump(uint64_t *ptp, int nlevels)
+{
+ int i, t, tabs;
+ uint64_t *ptpnext, ptpval;
+
+ if (--nlevels < 0)
+ return;
+
+ tabs = 3 - nlevels;
+ for (t = 0; t < tabs; t++)
+ printf("\t");
+ printf("PTP = %p\n", ptp);
+
+ for (i = 0; i < 512; i++) {
+ ptpval = ptp[i];
+
+ if (ptpval == 0)
+ continue;
+
+ for (t = 0; t < tabs; t++)
+ printf("\t");
+ printf("%3d 0x%016lx\n", i, ptpval);
+
+ if (nlevels != 0 && (ptpval & EPT_PG_SUPERPAGE) == 0) {
+ ptpnext = (uint64_t *)
+ PHYS_TO_DMAP(ptpval & EPT_ADDR_MASK);
+ ept_dump(ptpnext, nlevels);
+ }
+ }
+}
+#endif
+
+static size_t
+ept_create_mapping(uint64_t *ptp, vm_paddr_t gpa, vm_paddr_t hpa, size_t length,
+ vm_memattr_t attr, vm_prot_t prot, boolean_t spok)
+{
+ int spshift, ptpshift, ptpindex, nlevels;
+
+ /*
+ * Compute the size of the mapping that we can accomodate.
+ *
+ * This is based on three factors:
+ * - super page sizes supported by the processor
+ * - alignment of the region starting at 'gpa' and 'hpa'
+ * - length of the region 'len'
+ */
+ spshift = PAGE_SHIFT;
+ if (spok)
+ spshift += (EPT_PWLEVELS - 1) * 9;
+ while (spshift >= PAGE_SHIFT) {
+ uint64_t spsize = 1UL << spshift;
+ if ((page_sizes_mask & spsize) != 0 &&
+ (gpa & (spsize - 1)) == 0 &&
+ (hpa & (spsize - 1)) == 0 &&
+ length >= spsize) {
+ break;
+ }
+ spshift -= 9;
+ }
+
+ if (spshift < PAGE_SHIFT) {
+ panic("Invalid spshift for gpa 0x%016lx, hpa 0x%016lx, "
+ "length 0x%016lx, page_sizes_mask 0x%016lx",
+ gpa, hpa, length, page_sizes_mask);
+ }
+
+ nlevels = EPT_PWLEVELS;
+ while (--nlevels >= 0) {
+ ptpshift = PAGE_SHIFT + nlevels * 9;
+ ptpindex = (gpa >> ptpshift) & 0x1FF;
+
+ /* We have reached the leaf mapping */
+ if (spshift >= ptpshift)
+ break;
+
+ /*
+ * We are working on a non-leaf page table page.
+ *
+ * Create the next level page table page if necessary and point
+ * to it from the current page table.
+ */
+ if (ptp[ptpindex] == 0) {
+ void *nlp = malloc(PAGE_SIZE, M_VMX, M_WAITOK | M_ZERO);
+ ptp[ptpindex] = vtophys(nlp);
+ ptp[ptpindex] |= EPT_PG_RD | EPT_PG_WR | EPT_PG_EX;
+ }
+
+ /* Work our way down to the next level page table page */
+ ptp = (uint64_t *)PHYS_TO_DMAP(ptp[ptpindex] & EPT_ADDR_MASK);
+ }
+
+ if ((gpa & ((1UL << ptpshift) - 1)) != 0) {
+ panic("ept_create_mapping: gpa 0x%016lx and ptpshift %d "
+ "mismatch\n", gpa, ptpshift);
+ }
+
+ if (prot != VM_PROT_NONE) {
+ /* Do the mapping */
+ ptp[ptpindex] = hpa;
+
+ /* Apply the access controls */
+ if (prot & VM_PROT_READ)
+ ptp[ptpindex] |= EPT_PG_RD;
+ if (prot & VM_PROT_WRITE)
+ ptp[ptpindex] |= EPT_PG_WR;
+ if (prot & VM_PROT_EXECUTE)
+ ptp[ptpindex] |= EPT_PG_EX;
+
+ /*
+ * XXX should we enforce this memory type by setting the
+ * ignore PAT bit to 1.
+ */
+ ptp[ptpindex] |= EPT_PG_MEMORY_TYPE(attr);
+
+ if (nlevels > 0)
+ ptp[ptpindex] |= EPT_PG_SUPERPAGE;
+ } else {
+ /* Remove the mapping */
+ ptp[ptpindex] = 0;
+ }
+
+ return (1UL << ptpshift);
+}
+
+static vm_paddr_t
+ept_lookup_mapping(uint64_t *ptp, vm_paddr_t gpa)
+{
+ int nlevels, ptpshift, ptpindex;
+ uint64_t ptpval, hpabase, pgmask;
+
+ nlevels = EPT_PWLEVELS;
+ while (--nlevels >= 0) {
+ ptpshift = PAGE_SHIFT + nlevels * 9;
+ ptpindex = (gpa >> ptpshift) & 0x1FF;
+
+ ptpval = ptp[ptpindex];
+
+ /* Cannot make progress beyond this point */
+ if ((ptpval & (EPT_PG_RD | EPT_PG_WR | EPT_PG_EX)) == 0)
+ break;
+
+ if (nlevels == 0 || (ptpval & EPT_PG_SUPERPAGE)) {
+ pgmask = (1UL << ptpshift) - 1;
+ hpabase = ptpval & ~pgmask;
+ return (hpabase | (gpa & pgmask));
+ }
+
+ /* Work our way down to the next level page table page */
+ ptp = (uint64_t *)PHYS_TO_DMAP(ptpval & EPT_ADDR_MASK);
+ }
+
+ return ((vm_paddr_t)-1);
+}
+
+static void
+ept_free_pt_entry(pt_entry_t pte)
+{
+ if (pte == 0)
+ return;
+
+ /* sanity check */
+ if ((pte & EPT_PG_SUPERPAGE) != 0)
+ panic("ept_free_pt_entry: pte cannot have superpage bit");
+
+ return;
+}
+
+static void
+ept_free_pd_entry(pd_entry_t pde)
+{
+ pt_entry_t *pt;
+ int i;
+
+ if (pde == 0)
+ return;
+
+ if ((pde & EPT_PG_SUPERPAGE) == 0) {
+ pt = (pt_entry_t *)PHYS_TO_DMAP(pde & EPT_ADDR_MASK);
+ for (i = 0; i < NPTEPG; i++)
+ ept_free_pt_entry(pt[i]);
+ free(pt, M_VMX); /* free the page table page */
+ }
+}
+
+static void
+ept_free_pdp_entry(pdp_entry_t pdpe)
+{
+ pd_entry_t *pd;
+ int i;
+
+ if (pdpe == 0)
+ return;
+
+ if ((pdpe & EPT_PG_SUPERPAGE) == 0) {
+ pd = (pd_entry_t *)PHYS_TO_DMAP(pdpe & EPT_ADDR_MASK);
+ for (i = 0; i < NPDEPG; i++)
+ ept_free_pd_entry(pd[i]);
+ free(pd, M_VMX); /* free the page directory page */
+ }
+}
+
+static void
+ept_free_pml4_entry(pml4_entry_t pml4e)
+{
+ pdp_entry_t *pdp;
+ int i;
+
+ if (pml4e == 0)
+ return;
+
+ if ((pml4e & EPT_PG_SUPERPAGE) == 0) {
+ pdp = (pdp_entry_t *)PHYS_TO_DMAP(pml4e & EPT_ADDR_MASK);
+ for (i = 0; i < NPDPEPG; i++)
+ ept_free_pdp_entry(pdp[i]);
+ free(pdp, M_VMX); /* free the page directory ptr page */
+ }
+}
+
+void
+ept_vmcleanup(struct vmx *vmx)
+{
+ int i;
+
+ for (i = 0; i < NPML4EPG; i++)
+ ept_free_pml4_entry(vmx->pml4ept[i]);
+}
+
+int
+ept_vmmmap_set(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t len,
+ vm_memattr_t attr, int prot, boolean_t spok)
+{
+ size_t n;
+ struct vmx *vmx = arg;
+
+ while (len > 0) {
+ n = ept_create_mapping(vmx->pml4ept, gpa, hpa, len, attr,
+ prot, spok);
+ len -= n;
+ gpa += n;
+ hpa += n;
+ }
+
+ return (0);
+}
+
+vm_paddr_t
+ept_vmmmap_get(void *arg, vm_paddr_t gpa)
+{
+ vm_paddr_t hpa;
+ struct vmx *vmx;
+
+ vmx = arg;
+ hpa = ept_lookup_mapping(vmx->pml4ept, gpa);
+ return (hpa);
+}
+
+static void
+invept_single_context(void *arg)
+{
+ struct invept_desc desc = *(struct invept_desc *)arg;
+
+ invept(INVEPT_TYPE_SINGLE_CONTEXT, desc);
+}
+
+void
+ept_invalidate_mappings(u_long pml4ept)
+{
+ struct invept_desc invept_desc = { 0 };
+
+ invept_desc.eptp = EPTP(pml4ept);
+
+ smp_rendezvous(NULL, invept_single_context, NULL, &invept_desc);
+}
diff --git a/sys/amd64/vmm/intel/ept.h b/sys/amd64/vmm/intel/ept.h
new file mode 100644
index 0000000..2d7258d
--- /dev/null
+++ b/sys/amd64/vmm/intel/ept.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _EPT_H_
+#define _EPT_H_
+
+struct vmx;
+
+#define EPT_PWLEVELS 4 /* page walk levels */
+#define EPTP(pml4) ((pml4) | (EPT_PWLEVELS - 1) << 3 | PAT_WRITE_BACK)
+
+int ept_init(void);
+int ept_vmmmap_set(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, size_t length,
+ vm_memattr_t attr, int prot, boolean_t allow_superpage_mappings);
+vm_paddr_t ept_vmmmap_get(void *arg, vm_paddr_t gpa);
+void ept_invalidate_mappings(u_long ept_pml4);
+void ept_vmcleanup(struct vmx *vmx);
+#endif
diff --git a/sys/amd64/vmm/intel/vmcs.c b/sys/amd64/vmm/intel/vmcs.c
new file mode 100644
index 0000000..a5784dd
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmcs.c
@@ -0,0 +1,551 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_ddb.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/pcpu.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/segments.h>
+#include <machine/pmap.h>
+
+#include <machine/vmm.h>
+#include "vmm_host.h"
+#include "vmcs.h"
+#include "vmx_cpufunc.h"
+#include "ept.h"
+#include "vmx.h"
+
+#ifdef DDB
+#include <ddb/ddb.h>
+#endif
+
+static uint64_t
+vmcs_fix_regval(uint32_t encoding, uint64_t val)
+{
+
+ switch (encoding) {
+ case VMCS_GUEST_CR0:
+ val = vmx_fix_cr0(val);
+ break;
+ case VMCS_GUEST_CR4:
+ val = vmx_fix_cr4(val);
+ break;
+ default:
+ break;
+ }
+ return (val);
+}
+
+static uint32_t
+vmcs_field_encoding(int ident)
+{
+ switch (ident) {
+ case VM_REG_GUEST_CR0:
+ return (VMCS_GUEST_CR0);
+ case VM_REG_GUEST_CR3:
+ return (VMCS_GUEST_CR3);
+ case VM_REG_GUEST_CR4:
+ return (VMCS_GUEST_CR4);
+ case VM_REG_GUEST_DR7:
+ return (VMCS_GUEST_DR7);
+ case VM_REG_GUEST_RSP:
+ return (VMCS_GUEST_RSP);
+ case VM_REG_GUEST_RIP:
+ return (VMCS_GUEST_RIP);
+ case VM_REG_GUEST_RFLAGS:
+ return (VMCS_GUEST_RFLAGS);
+ case VM_REG_GUEST_ES:
+ return (VMCS_GUEST_ES_SELECTOR);
+ case VM_REG_GUEST_CS:
+ return (VMCS_GUEST_CS_SELECTOR);
+ case VM_REG_GUEST_SS:
+ return (VMCS_GUEST_SS_SELECTOR);
+ case VM_REG_GUEST_DS:
+ return (VMCS_GUEST_DS_SELECTOR);
+ case VM_REG_GUEST_FS:
+ return (VMCS_GUEST_FS_SELECTOR);
+ case VM_REG_GUEST_GS:
+ return (VMCS_GUEST_GS_SELECTOR);
+ case VM_REG_GUEST_TR:
+ return (VMCS_GUEST_TR_SELECTOR);
+ case VM_REG_GUEST_LDTR:
+ return (VMCS_GUEST_LDTR_SELECTOR);
+ case VM_REG_GUEST_EFER:
+ return (VMCS_GUEST_IA32_EFER);
+ default:
+ return (-1);
+ }
+
+}
+
+static int
+vmcs_seg_desc_encoding(int seg, uint32_t *base, uint32_t *lim, uint32_t *acc)
+{
+
+ switch (seg) {
+ case VM_REG_GUEST_ES:
+ *base = VMCS_GUEST_ES_BASE;
+ *lim = VMCS_GUEST_ES_LIMIT;
+ *acc = VMCS_GUEST_ES_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_CS:
+ *base = VMCS_GUEST_CS_BASE;
+ *lim = VMCS_GUEST_CS_LIMIT;
+ *acc = VMCS_GUEST_CS_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_SS:
+ *base = VMCS_GUEST_SS_BASE;
+ *lim = VMCS_GUEST_SS_LIMIT;
+ *acc = VMCS_GUEST_SS_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_DS:
+ *base = VMCS_GUEST_DS_BASE;
+ *lim = VMCS_GUEST_DS_LIMIT;
+ *acc = VMCS_GUEST_DS_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_FS:
+ *base = VMCS_GUEST_FS_BASE;
+ *lim = VMCS_GUEST_FS_LIMIT;
+ *acc = VMCS_GUEST_FS_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_GS:
+ *base = VMCS_GUEST_GS_BASE;
+ *lim = VMCS_GUEST_GS_LIMIT;
+ *acc = VMCS_GUEST_GS_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_TR:
+ *base = VMCS_GUEST_TR_BASE;
+ *lim = VMCS_GUEST_TR_LIMIT;
+ *acc = VMCS_GUEST_TR_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_LDTR:
+ *base = VMCS_GUEST_LDTR_BASE;
+ *lim = VMCS_GUEST_LDTR_LIMIT;
+ *acc = VMCS_GUEST_LDTR_ACCESS_RIGHTS;
+ break;
+ case VM_REG_GUEST_IDTR:
+ *base = VMCS_GUEST_IDTR_BASE;
+ *lim = VMCS_GUEST_IDTR_LIMIT;
+ *acc = VMCS_INVALID_ENCODING;
+ break;
+ case VM_REG_GUEST_GDTR:
+ *base = VMCS_GUEST_GDTR_BASE;
+ *lim = VMCS_GUEST_GDTR_LIMIT;
+ *acc = VMCS_INVALID_ENCODING;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+int
+vmcs_getreg(struct vmcs *vmcs, int ident, uint64_t *retval)
+{
+ int error;
+ uint32_t encoding;
+
+ /*
+ * If we need to get at vmx-specific state in the VMCS we can bypass
+ * the translation of 'ident' to 'encoding' by simply setting the
+ * sign bit. As it so happens the upper 16 bits are reserved (i.e
+ * set to 0) in the encodings for the VMCS so we are free to use the
+ * sign bit.
+ */
+ if (ident < 0)
+ encoding = ident & 0x7fffffff;
+ else
+ encoding = vmcs_field_encoding(ident);
+
+ if (encoding == (uint32_t)-1)
+ return (EINVAL);
+
+ VMPTRLD(vmcs);
+ error = vmread(encoding, retval);
+ VMCLEAR(vmcs);
+ return (error);
+}
+
+int
+vmcs_setreg(struct vmcs *vmcs, int ident, uint64_t val)
+{
+ int error;
+ uint32_t encoding;
+
+ if (ident < 0)
+ encoding = ident & 0x7fffffff;
+ else
+ encoding = vmcs_field_encoding(ident);
+
+ if (encoding == (uint32_t)-1)
+ return (EINVAL);
+
+ val = vmcs_fix_regval(encoding, val);
+
+ VMPTRLD(vmcs);
+ error = vmwrite(encoding, val);
+ VMCLEAR(vmcs);
+ return (error);
+}
+
+int
+vmcs_setdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc)
+{
+ int error;
+ uint32_t base, limit, access;
+
+ error = vmcs_seg_desc_encoding(seg, &base, &limit, &access);
+ if (error != 0)
+ panic("vmcs_setdesc: invalid segment register %d", seg);
+
+ VMPTRLD(vmcs);
+ if ((error = vmwrite(base, desc->base)) != 0)
+ goto done;
+
+ if ((error = vmwrite(limit, desc->limit)) != 0)
+ goto done;
+
+ if (access != VMCS_INVALID_ENCODING) {
+ if ((error = vmwrite(access, desc->access)) != 0)
+ goto done;
+ }
+done:
+ VMCLEAR(vmcs);
+ return (error);
+}
+
+int
+vmcs_getdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc)
+{
+ int error;
+ uint32_t base, limit, access;
+ uint64_t u64;
+
+ error = vmcs_seg_desc_encoding(seg, &base, &limit, &access);
+ if (error != 0)
+ panic("vmcs_getdesc: invalid segment register %d", seg);
+
+ VMPTRLD(vmcs);
+ if ((error = vmread(base, &u64)) != 0)
+ goto done;
+ desc->base = u64;
+
+ if ((error = vmread(limit, &u64)) != 0)
+ goto done;
+ desc->limit = u64;
+
+ if (access != VMCS_INVALID_ENCODING) {
+ if ((error = vmread(access, &u64)) != 0)
+ goto done;
+ desc->access = u64;
+ }
+done:
+ VMCLEAR(vmcs);
+ return (error);
+}
+
+int
+vmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count)
+{
+ int error;
+
+ VMPTRLD(vmcs);
+
+ /*
+ * Guest MSRs are saved in the VM-exit MSR-store area.
+ * Guest MSRs are loaded from the VM-entry MSR-load area.
+ * Both areas point to the same location in memory.
+ */
+ if ((error = vmwrite(VMCS_EXIT_MSR_STORE, g_area)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_EXIT_MSR_STORE_COUNT, g_count)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD, g_area)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD_COUNT, g_count)) != 0)
+ goto done;
+
+ error = 0;
+done:
+ VMCLEAR(vmcs);
+ return (error);
+}
+
+int
+vmcs_set_defaults(struct vmcs *vmcs,
+ u_long host_rip, u_long host_rsp, u_long ept_pml4,
+ uint32_t pinbased_ctls, uint32_t procbased_ctls,
+ uint32_t procbased_ctls2, uint32_t exit_ctls,
+ uint32_t entry_ctls, u_long msr_bitmap, uint16_t vpid)
+{
+ int error, codesel, datasel, tsssel;
+ u_long cr0, cr4, efer;
+ uint64_t eptp, pat, fsbase, idtrbase;
+ uint32_t exc_bitmap;
+
+ codesel = vmm_get_host_codesel();
+ datasel = vmm_get_host_datasel();
+ tsssel = vmm_get_host_tsssel();
+
+ /*
+ * Make sure we have a "current" VMCS to work with.
+ */
+ VMPTRLD(vmcs);
+
+ /*
+ * Load the VMX controls
+ */
+ if ((error = vmwrite(VMCS_PIN_BASED_CTLS, pinbased_ctls)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, procbased_ctls)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_SEC_PROC_BASED_CTLS, procbased_ctls2)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_EXIT_CTLS, exit_ctls)) != 0)
+ goto done;
+ if ((error = vmwrite(VMCS_ENTRY_CTLS, entry_ctls)) != 0)
+ goto done;
+
+ /* Guest state */
+
+ /* Initialize guest IA32_PAT MSR with the default value */
+ pat = PAT_VALUE(0, PAT_WRITE_BACK) |
+ PAT_VALUE(1, PAT_WRITE_THROUGH) |
+ PAT_VALUE(2, PAT_UNCACHED) |
+ PAT_VALUE(3, PAT_UNCACHEABLE) |
+ PAT_VALUE(4, PAT_WRITE_BACK) |
+ PAT_VALUE(5, PAT_WRITE_THROUGH) |
+ PAT_VALUE(6, PAT_UNCACHED) |
+ PAT_VALUE(7, PAT_UNCACHEABLE);
+ if ((error = vmwrite(VMCS_GUEST_IA32_PAT, pat)) != 0)
+ goto done;
+
+ /* Host state */
+
+ /* Initialize host IA32_PAT MSR */
+ pat = vmm_get_host_pat();
+ if ((error = vmwrite(VMCS_HOST_IA32_PAT, pat)) != 0)
+ goto done;
+
+ /* Load the IA32_EFER MSR */
+ efer = vmm_get_host_efer();
+ if ((error = vmwrite(VMCS_HOST_IA32_EFER, efer)) != 0)
+ goto done;
+
+ /* Load the control registers */
+
+ cr0 = vmm_get_host_cr0();
+ if ((error = vmwrite(VMCS_HOST_CR0, cr0)) != 0)
+ goto done;
+
+ cr4 = vmm_get_host_cr4() | CR4_VMXE;
+ if ((error = vmwrite(VMCS_HOST_CR4, cr4)) != 0)
+ goto done;
+
+ /* Load the segment selectors */
+ if ((error = vmwrite(VMCS_HOST_ES_SELECTOR, datasel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_CS_SELECTOR, codesel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_SS_SELECTOR, datasel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_DS_SELECTOR, datasel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_FS_SELECTOR, datasel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_GS_SELECTOR, datasel)) != 0)
+ goto done;
+
+ if ((error = vmwrite(VMCS_HOST_TR_SELECTOR, tsssel)) != 0)
+ goto done;
+
+ /*
+ * Load the Base-Address for %fs and idtr.
+ *
+ * Note that we exclude %gs, tss and gdtr here because their base
+ * address is pcpu specific.
+ */
+ fsbase = vmm_get_host_fsbase();
+ if ((error = vmwrite(VMCS_HOST_FS_BASE, fsbase)) != 0)
+ goto done;
+
+ idtrbase = vmm_get_host_idtrbase();
+ if ((error = vmwrite(VMCS_HOST_IDTR_BASE, idtrbase)) != 0)
+ goto done;
+
+ /* instruction pointer */
+ if ((error = vmwrite(VMCS_HOST_RIP, host_rip)) != 0)
+ goto done;
+
+ /* stack pointer */
+ if ((error = vmwrite(VMCS_HOST_RSP, host_rsp)) != 0)
+ goto done;
+
+ /* eptp */
+ eptp = EPTP(ept_pml4);
+ if ((error = vmwrite(VMCS_EPTP, eptp)) != 0)
+ goto done;
+
+ /* vpid */
+ if ((error = vmwrite(VMCS_VPID, vpid)) != 0)
+ goto done;
+
+ /* msr bitmap */
+ if ((error = vmwrite(VMCS_MSR_BITMAP, msr_bitmap)) != 0)
+ goto done;
+
+ /* exception bitmap */
+ exc_bitmap = 1 << IDT_MC;
+ if ((error = vmwrite(VMCS_EXCEPTION_BITMAP, exc_bitmap)) != 0)
+ goto done;
+
+ /* link pointer */
+ if ((error = vmwrite(VMCS_LINK_POINTER, ~0)) != 0)
+ goto done;
+done:
+ VMCLEAR(vmcs);
+ return (error);
+}
+
+uint64_t
+vmcs_read(uint32_t encoding)
+{
+ int error;
+ uint64_t val;
+
+ error = vmread(encoding, &val);
+ if (error != 0)
+ panic("vmcs_read(%u) error %d", encoding, error);
+
+ return (val);
+}
+
+#ifdef DDB
+extern int vmxon_enabled[];
+
+DB_SHOW_COMMAND(vmcs, db_show_vmcs)
+{
+ uint64_t cur_vmcs, val;
+ uint32_t exit;
+
+ if (!vmxon_enabled[curcpu]) {
+ db_printf("VMX not enabled\n");
+ return;
+ }
+
+ if (have_addr) {
+ db_printf("Only current VMCS supported\n");
+ return;
+ }
+
+ vmptrst(&cur_vmcs);
+ if (cur_vmcs == VMCS_INITIAL) {
+ db_printf("No current VM context\n");
+ return;
+ }
+ db_printf("VMCS: %jx\n", cur_vmcs);
+ db_printf("VPID: %lu\n", vmcs_read(VMCS_VPID));
+ db_printf("Activity: ");
+ val = vmcs_read(VMCS_GUEST_ACTIVITY);
+ switch (val) {
+ case 0:
+ db_printf("Active");
+ break;
+ case 1:
+ db_printf("HLT");
+ break;
+ case 2:
+ db_printf("Shutdown");
+ break;
+ case 3:
+ db_printf("Wait for SIPI");
+ break;
+ default:
+ db_printf("Unknown: %#lx", val);
+ }
+ db_printf("\n");
+ exit = vmcs_read(VMCS_EXIT_REASON);
+ if (exit & 0x80000000)
+ db_printf("Entry Failure Reason: %u\n", exit & 0xffff);
+ else
+ db_printf("Exit Reason: %u\n", exit & 0xffff);
+ db_printf("Qualification: %#lx\n", vmcs_exit_qualification());
+ db_printf("Guest Linear Address: %#lx\n",
+ vmcs_read(VMCS_GUEST_LINEAR_ADDRESS));
+ switch (exit & 0x8000ffff) {
+ case EXIT_REASON_EXCEPTION:
+ case EXIT_REASON_EXT_INTR:
+ val = vmcs_read(VMCS_EXIT_INTERRUPTION_INFO);
+ db_printf("Interrupt Type: ");
+ switch (val >> 8 & 0x7) {
+ case 0:
+ db_printf("external");
+ break;
+ case 2:
+ db_printf("NMI");
+ break;
+ case 3:
+ db_printf("HW exception");
+ break;
+ case 4:
+ db_printf("SW exception");
+ break;
+ default:
+ db_printf("?? %lu", val >> 8 & 0x7);
+ break;
+ }
+ db_printf(" Vector: %lu", val & 0xff);
+ if (val & 0x800)
+ db_printf(" Error Code: %lx",
+ vmcs_read(VMCS_EXIT_INTERRUPTION_ERROR));
+ db_printf("\n");
+ break;
+ case EXIT_REASON_EPT_FAULT:
+ case EXIT_REASON_EPT_MISCONFIG:
+ db_printf("Guest Physical Address: %#lx\n",
+ vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS));
+ break;
+ }
+ db_printf("VM-instruction error: %#lx\n", vmcs_instruction_error());
+}
+#endif
diff --git a/sys/amd64/vmm/intel/vmcs.h b/sys/amd64/vmm/intel/vmcs.h
new file mode 100644
index 0000000..f39eed2
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmcs.h
@@ -0,0 +1,338 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMCS_H_
+#define _VMCS_H_
+
+#ifdef _KERNEL
+struct vmcs {
+ uint32_t identifier;
+ uint32_t abort_code;
+ char _impl_specific[PAGE_SIZE - sizeof(uint32_t) * 2];
+};
+CTASSERT(sizeof(struct vmcs) == PAGE_SIZE);
+
+/* MSR save region is composed of an array of 'struct msr_entry' */
+struct msr_entry {
+ uint32_t index;
+ uint32_t reserved;
+ uint64_t val;
+
+};
+
+int vmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count);
+int vmcs_set_defaults(struct vmcs *vmcs, u_long host_rip, u_long host_rsp,
+ u_long ept_pml4,
+ uint32_t pinbased_ctls, uint32_t procbased_ctls,
+ uint32_t procbased_ctls2, uint32_t exit_ctls,
+ uint32_t entry_ctls, u_long msr_bitmap,
+ uint16_t vpid);
+int vmcs_getreg(struct vmcs *vmcs, int ident, uint64_t *retval);
+int vmcs_setreg(struct vmcs *vmcs, int ident, uint64_t val);
+int vmcs_getdesc(struct vmcs *vmcs, int ident,
+ struct seg_desc *desc);
+int vmcs_setdesc(struct vmcs *vmcs, int ident,
+ struct seg_desc *desc);
+uint64_t vmcs_read(uint32_t encoding);
+
+#define vmexit_instruction_length() vmcs_read(VMCS_EXIT_INSTRUCTION_LENGTH)
+#define vmcs_guest_rip() vmcs_read(VMCS_GUEST_RIP)
+#define vmcs_instruction_error() vmcs_read(VMCS_INSTRUCTION_ERROR)
+#define vmcs_exit_reason() (vmcs_read(VMCS_EXIT_REASON) & 0xffff)
+#define vmcs_exit_qualification() vmcs_read(VMCS_EXIT_QUALIFICATION)
+#define vmcs_guest_cr3() vmcs_read(VMCS_GUEST_CR3)
+#define vmcs_gpa() vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS)
+#define vmcs_gla() vmcs_read(VMCS_GUEST_LINEAR_ADDRESS)
+
+#endif /* _KERNEL */
+
+#define VMCS_INITIAL 0xffffffffffffffff
+
+#define VMCS_IDENT(encoding) ((encoding) | 0x80000000)
+/*
+ * VMCS field encodings from Appendix H, Intel Architecture Manual Vol3B.
+ */
+#define VMCS_INVALID_ENCODING 0xffffffff
+
+/* 16-bit control fields */
+#define VMCS_VPID 0x00000000
+
+/* 16-bit guest-state fields */
+#define VMCS_GUEST_ES_SELECTOR 0x00000800
+#define VMCS_GUEST_CS_SELECTOR 0x00000802
+#define VMCS_GUEST_SS_SELECTOR 0x00000804
+#define VMCS_GUEST_DS_SELECTOR 0x00000806
+#define VMCS_GUEST_FS_SELECTOR 0x00000808
+#define VMCS_GUEST_GS_SELECTOR 0x0000080A
+#define VMCS_GUEST_LDTR_SELECTOR 0x0000080C
+#define VMCS_GUEST_TR_SELECTOR 0x0000080E
+
+/* 16-bit host-state fields */
+#define VMCS_HOST_ES_SELECTOR 0x00000C00
+#define VMCS_HOST_CS_SELECTOR 0x00000C02
+#define VMCS_HOST_SS_SELECTOR 0x00000C04
+#define VMCS_HOST_DS_SELECTOR 0x00000C06
+#define VMCS_HOST_FS_SELECTOR 0x00000C08
+#define VMCS_HOST_GS_SELECTOR 0x00000C0A
+#define VMCS_HOST_TR_SELECTOR 0x00000C0C
+
+/* 64-bit control fields */
+#define VMCS_IO_BITMAP_A 0x00002000
+#define VMCS_IO_BITMAP_B 0x00002002
+#define VMCS_MSR_BITMAP 0x00002004
+#define VMCS_EXIT_MSR_STORE 0x00002006
+#define VMCS_EXIT_MSR_LOAD 0x00002008
+#define VMCS_ENTRY_MSR_LOAD 0x0000200A
+#define VMCS_EXECUTIVE_VMCS 0x0000200C
+#define VMCS_TSC_OFFSET 0x00002010
+#define VMCS_VIRTUAL_APIC 0x00002012
+#define VMCS_APIC_ACCESS 0x00002014
+#define VMCS_EPTP 0x0000201A
+
+/* 64-bit read-only fields */
+#define VMCS_GUEST_PHYSICAL_ADDRESS 0x00002400
+
+/* 64-bit guest-state fields */
+#define VMCS_LINK_POINTER 0x00002800
+#define VMCS_GUEST_IA32_DEBUGCTL 0x00002802
+#define VMCS_GUEST_IA32_PAT 0x00002804
+#define VMCS_GUEST_IA32_EFER 0x00002806
+#define VMCS_GUEST_IA32_PERF_GLOBAL_CTRL 0x00002808
+#define VMCS_GUEST_PDPTE0 0x0000280A
+#define VMCS_GUEST_PDPTE1 0x0000280C
+#define VMCS_GUEST_PDPTE2 0x0000280E
+#define VMCS_GUEST_PDPTE3 0x00002810
+
+/* 64-bit host-state fields */
+#define VMCS_HOST_IA32_PAT 0x00002C00
+#define VMCS_HOST_IA32_EFER 0x00002C02
+#define VMCS_HOST_IA32_PERF_GLOBAL_CTRL 0x00002C04
+
+/* 32-bit control fields */
+#define VMCS_PIN_BASED_CTLS 0x00004000
+#define VMCS_PRI_PROC_BASED_CTLS 0x00004002
+#define VMCS_EXCEPTION_BITMAP 0x00004004
+#define VMCS_PF_ERROR_MASK 0x00004006
+#define VMCS_PF_ERROR_MATCH 0x00004008
+#define VMCS_CR3_TARGET_COUNT 0x0000400A
+#define VMCS_EXIT_CTLS 0x0000400C
+#define VMCS_EXIT_MSR_STORE_COUNT 0x0000400E
+#define VMCS_EXIT_MSR_LOAD_COUNT 0x00004010
+#define VMCS_ENTRY_CTLS 0x00004012
+#define VMCS_ENTRY_MSR_LOAD_COUNT 0x00004014
+#define VMCS_ENTRY_INTR_INFO 0x00004016
+#define VMCS_ENTRY_EXCEPTION_ERROR 0x00004018
+#define VMCS_ENTRY_INST_LENGTH 0x0000401A
+#define VMCS_TPR_THRESHOLD 0x0000401C
+#define VMCS_SEC_PROC_BASED_CTLS 0x0000401E
+#define VMCS_PLE_GAP 0x00004020
+#define VMCS_PLE_WINDOW 0x00004022
+
+/* 32-bit read-only data fields */
+#define VMCS_INSTRUCTION_ERROR 0x00004400
+#define VMCS_EXIT_REASON 0x00004402
+#define VMCS_EXIT_INTERRUPTION_INFO 0x00004404
+#define VMCS_EXIT_INTERRUPTION_ERROR 0x00004406
+#define VMCS_IDT_VECTORING_INFO 0x00004408
+#define VMCS_IDT_VECTORING_ERROR 0x0000440A
+#define VMCS_EXIT_INSTRUCTION_LENGTH 0x0000440C
+#define VMCS_EXIT_INSTRUCTION_INFO 0x0000440E
+
+/* 32-bit guest-state fields */
+#define VMCS_GUEST_ES_LIMIT 0x00004800
+#define VMCS_GUEST_CS_LIMIT 0x00004802
+#define VMCS_GUEST_SS_LIMIT 0x00004804
+#define VMCS_GUEST_DS_LIMIT 0x00004806
+#define VMCS_GUEST_FS_LIMIT 0x00004808
+#define VMCS_GUEST_GS_LIMIT 0x0000480A
+#define VMCS_GUEST_LDTR_LIMIT 0x0000480C
+#define VMCS_GUEST_TR_LIMIT 0x0000480E
+#define VMCS_GUEST_GDTR_LIMIT 0x00004810
+#define VMCS_GUEST_IDTR_LIMIT 0x00004812
+#define VMCS_GUEST_ES_ACCESS_RIGHTS 0x00004814
+#define VMCS_GUEST_CS_ACCESS_RIGHTS 0x00004816
+#define VMCS_GUEST_SS_ACCESS_RIGHTS 0x00004818
+#define VMCS_GUEST_DS_ACCESS_RIGHTS 0x0000481A
+#define VMCS_GUEST_FS_ACCESS_RIGHTS 0x0000481C
+#define VMCS_GUEST_GS_ACCESS_RIGHTS 0x0000481E
+#define VMCS_GUEST_LDTR_ACCESS_RIGHTS 0x00004820
+#define VMCS_GUEST_TR_ACCESS_RIGHTS 0x00004822
+#define VMCS_GUEST_INTERRUPTIBILITY 0x00004824
+#define VMCS_GUEST_ACTIVITY 0x00004826
+#define VMCS_GUEST_SMBASE 0x00004828
+#define VMCS_GUEST_IA32_SYSENTER_CS 0x0000482A
+#define VMCS_PREEMPTION_TIMER_VALUE 0x0000482E
+
+/* 32-bit host state fields */
+#define VMCS_HOST_IA32_SYSENTER_CS 0x00004C00
+
+/* Natural Width control fields */
+#define VMCS_CR0_MASK 0x00006000
+#define VMCS_CR4_MASK 0x00006002
+#define VMCS_CR0_SHADOW 0x00006004
+#define VMCS_CR4_SHADOW 0x00006006
+#define VMCS_CR3_TARGET0 0x00006008
+#define VMCS_CR3_TARGET1 0x0000600A
+#define VMCS_CR3_TARGET2 0x0000600C
+#define VMCS_CR3_TARGET3 0x0000600E
+
+/* Natural Width read-only fields */
+#define VMCS_EXIT_QUALIFICATION 0x00006400
+#define VMCS_IO_RCX 0x00006402
+#define VMCS_IO_RSI 0x00006404
+#define VMCS_IO_RDI 0x00006406
+#define VMCS_IO_RIP 0x00006408
+#define VMCS_GUEST_LINEAR_ADDRESS 0x0000640A
+
+/* Natural Width guest-state fields */
+#define VMCS_GUEST_CR0 0x00006800
+#define VMCS_GUEST_CR3 0x00006802
+#define VMCS_GUEST_CR4 0x00006804
+#define VMCS_GUEST_ES_BASE 0x00006806
+#define VMCS_GUEST_CS_BASE 0x00006808
+#define VMCS_GUEST_SS_BASE 0x0000680A
+#define VMCS_GUEST_DS_BASE 0x0000680C
+#define VMCS_GUEST_FS_BASE 0x0000680E
+#define VMCS_GUEST_GS_BASE 0x00006810
+#define VMCS_GUEST_LDTR_BASE 0x00006812
+#define VMCS_GUEST_TR_BASE 0x00006814
+#define VMCS_GUEST_GDTR_BASE 0x00006816
+#define VMCS_GUEST_IDTR_BASE 0x00006818
+#define VMCS_GUEST_DR7 0x0000681A
+#define VMCS_GUEST_RSP 0x0000681C
+#define VMCS_GUEST_RIP 0x0000681E
+#define VMCS_GUEST_RFLAGS 0x00006820
+#define VMCS_GUEST_PENDING_DBG_EXCEPTIONS 0x00006822
+#define VMCS_GUEST_IA32_SYSENTER_ESP 0x00006824
+#define VMCS_GUEST_IA32_SYSENTER_EIP 0x00006826
+
+/* Natural Width host-state fields */
+#define VMCS_HOST_CR0 0x00006C00
+#define VMCS_HOST_CR3 0x00006C02
+#define VMCS_HOST_CR4 0x00006C04
+#define VMCS_HOST_FS_BASE 0x00006C06
+#define VMCS_HOST_GS_BASE 0x00006C08
+#define VMCS_HOST_TR_BASE 0x00006C0A
+#define VMCS_HOST_GDTR_BASE 0x00006C0C
+#define VMCS_HOST_IDTR_BASE 0x00006C0E
+#define VMCS_HOST_IA32_SYSENTER_ESP 0x00006C10
+#define VMCS_HOST_IA32_SYSENTER_EIP 0x00006C12
+#define VMCS_HOST_RSP 0x00006C14
+#define VMCS_HOST_RIP 0x00006c16
+
+/*
+ * VM instruction error numbers
+ */
+#define VMRESUME_WITH_NON_LAUNCHED_VMCS 5
+
+/*
+ * VMCS exit reasons
+ */
+#define EXIT_REASON_EXCEPTION 0
+#define EXIT_REASON_EXT_INTR 1
+#define EXIT_REASON_TRIPLE_FAULT 2
+#define EXIT_REASON_INIT 3
+#define EXIT_REASON_SIPI 4
+#define EXIT_REASON_IO_SMI 5
+#define EXIT_REASON_SMI 6
+#define EXIT_REASON_INTR_WINDOW 7
+#define EXIT_REASON_NMI_WINDOW 8
+#define EXIT_REASON_TASK_SWITCH 9
+#define EXIT_REASON_CPUID 10
+#define EXIT_REASON_GETSEC 11
+#define EXIT_REASON_HLT 12
+#define EXIT_REASON_INVD 13
+#define EXIT_REASON_INVLPG 14
+#define EXIT_REASON_RDPMC 15
+#define EXIT_REASON_RDTSC 16
+#define EXIT_REASON_RSM 17
+#define EXIT_REASON_VMCALL 18
+#define EXIT_REASON_VMCLEAR 19
+#define EXIT_REASON_VMLAUNCH 20
+#define EXIT_REASON_VMPTRLD 21
+#define EXIT_REASON_VMPTRST 22
+#define EXIT_REASON_VMREAD 23
+#define EXIT_REASON_VMRESUME 24
+#define EXIT_REASON_VMWRITE 25
+#define EXIT_REASON_VMXOFF 26
+#define EXIT_REASON_VMXON 27
+#define EXIT_REASON_CR_ACCESS 28
+#define EXIT_REASON_DR_ACCESS 29
+#define EXIT_REASON_INOUT 30
+#define EXIT_REASON_RDMSR 31
+#define EXIT_REASON_WRMSR 32
+#define EXIT_REASON_INVAL_VMCS 33
+#define EXIT_REASON_INVAL_MSR 34
+#define EXIT_REASON_MWAIT 36
+#define EXIT_REASON_MTF 37
+#define EXIT_REASON_MONITOR 39
+#define EXIT_REASON_PAUSE 40
+#define EXIT_REASON_MCE 41
+#define EXIT_REASON_TPR 43
+#define EXIT_REASON_APIC 44
+#define EXIT_REASON_GDTR_IDTR 46
+#define EXIT_REASON_LDTR_TR 47
+#define EXIT_REASON_EPT_FAULT 48
+#define EXIT_REASON_EPT_MISCONFIG 49
+#define EXIT_REASON_INVEPT 50
+#define EXIT_REASON_RDTSCP 51
+#define EXIT_REASON_VMX_PREEMPT 52
+#define EXIT_REASON_INVVPID 53
+#define EXIT_REASON_WBINVD 54
+#define EXIT_REASON_XSETBV 55
+
+/*
+ * VMCS interrupt information fields
+ */
+#define VMCS_INTERRUPTION_INFO_VALID (1U << 31)
+#define VMCS_INTERRUPTION_INFO_HW_INTR (0 << 8)
+#define VMCS_INTERRUPTION_INFO_NMI (2 << 8)
+
+/*
+ * VMCS Guest interruptibility field
+ */
+#define VMCS_INTERRUPTIBILITY_STI_BLOCKING (1 << 0)
+#define VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING (1 << 1)
+#define VMCS_INTERRUPTIBILITY_SMI_BLOCKING (1 << 2)
+#define VMCS_INTERRUPTIBILITY_NMI_BLOCKING (1 << 3)
+
+/*
+ * Exit qualification for EXIT_REASON_INVAL_VMCS
+ */
+#define EXIT_QUAL_NMI_WHILE_STI_BLOCKING 3
+
+/*
+ * Exit qualification for EPT violation
+ */
+#define EPT_VIOLATION_DATA_READ (1UL << 0)
+#define EPT_VIOLATION_DATA_WRITE (1UL << 1)
+#define EPT_VIOLATION_INST_FETCH (1UL << 2)
+#define EPT_VIOLATION_GLA_VALID (1UL << 7)
+#define EPT_VIOLATION_XLAT_VALID (1UL << 8)
+
+#endif
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
new file mode 100644
index 0000000..287ac8c
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -0,0 +1,1852 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/psl.h>
+#include <machine/cpufunc.h>
+#include <machine/md_var.h>
+#include <machine/pmap.h>
+#include <machine/segments.h>
+#include <machine/specialreg.h>
+#include <machine/vmparam.h>
+
+#include <x86/apicreg.h>
+
+#include <machine/vmm.h>
+#include "vmm_host.h"
+#include "vmm_lapic.h"
+#include "vmm_msr.h"
+#include "vmm_ktr.h"
+#include "vmm_stat.h"
+
+#include "vmx_msr.h"
+#include "ept.h"
+#include "vmx_cpufunc.h"
+#include "vmx.h"
+#include "x86.h"
+#include "vmx_controls.h"
+
+#define PINBASED_CTLS_ONE_SETTING \
+ (PINBASED_EXTINT_EXITING | \
+ PINBASED_NMI_EXITING | \
+ PINBASED_VIRTUAL_NMI)
+#define PINBASED_CTLS_ZERO_SETTING 0
+
+#define PROCBASED_CTLS_WINDOW_SETTING \
+ (PROCBASED_INT_WINDOW_EXITING | \
+ PROCBASED_NMI_WINDOW_EXITING)
+
+#define PROCBASED_CTLS_ONE_SETTING \
+ (PROCBASED_SECONDARY_CONTROLS | \
+ PROCBASED_IO_EXITING | \
+ PROCBASED_MSR_BITMAPS | \
+ PROCBASED_CTLS_WINDOW_SETTING)
+#define PROCBASED_CTLS_ZERO_SETTING \
+ (PROCBASED_CR3_LOAD_EXITING | \
+ PROCBASED_CR3_STORE_EXITING | \
+ PROCBASED_IO_BITMAPS)
+
+#define PROCBASED_CTLS2_ONE_SETTING PROCBASED2_ENABLE_EPT
+#define PROCBASED_CTLS2_ZERO_SETTING 0
+
+#define VM_EXIT_CTLS_ONE_SETTING_NO_PAT \
+ (VM_EXIT_HOST_LMA | \
+ VM_EXIT_SAVE_EFER | \
+ VM_EXIT_LOAD_EFER)
+
+#define VM_EXIT_CTLS_ONE_SETTING \
+ (VM_EXIT_CTLS_ONE_SETTING_NO_PAT | \
+ VM_EXIT_SAVE_PAT | \
+ VM_EXIT_LOAD_PAT)
+#define VM_EXIT_CTLS_ZERO_SETTING VM_EXIT_SAVE_DEBUG_CONTROLS
+
+#define VM_ENTRY_CTLS_ONE_SETTING_NO_PAT VM_ENTRY_LOAD_EFER
+
+#define VM_ENTRY_CTLS_ONE_SETTING \
+ (VM_ENTRY_CTLS_ONE_SETTING_NO_PAT | \
+ VM_ENTRY_LOAD_PAT)
+#define VM_ENTRY_CTLS_ZERO_SETTING \
+ (VM_ENTRY_LOAD_DEBUG_CONTROLS | \
+ VM_ENTRY_INTO_SMM | \
+ VM_ENTRY_DEACTIVATE_DUAL_MONITOR)
+
+#define guest_msr_rw(vmx, msr) \
+ msr_bitmap_change_access((vmx)->msr_bitmap, (msr), MSR_BITMAP_ACCESS_RW)
+
+#define HANDLED 1
+#define UNHANDLED 0
+
+MALLOC_DEFINE(M_VMX, "vmx", "vmx");
+
+int vmxon_enabled[MAXCPU];
+static char vmxon_region[MAXCPU][PAGE_SIZE] __aligned(PAGE_SIZE);
+
+static uint32_t pinbased_ctls, procbased_ctls, procbased_ctls2;
+static uint32_t exit_ctls, entry_ctls;
+
+static uint64_t cr0_ones_mask, cr0_zeros_mask;
+static uint64_t cr4_ones_mask, cr4_zeros_mask;
+
+static volatile u_int nextvpid;
+
+static int vmx_no_patmsr;
+
+/*
+ * Virtual NMI blocking conditions.
+ *
+ * Some processor implementations also require NMI to be blocked if
+ * the STI_BLOCKING bit is set. It is possible to detect this at runtime
+ * based on the (exit_reason,exit_qual) tuple being set to
+ * (EXIT_REASON_INVAL_VMCS, EXIT_QUAL_NMI_WHILE_STI_BLOCKING).
+ *
+ * We take the easy way out and also include STI_BLOCKING as one of the
+ * gating items for vNMI injection.
+ */
+static uint64_t nmi_blocking_bits = VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING |
+ VMCS_INTERRUPTIBILITY_NMI_BLOCKING |
+ VMCS_INTERRUPTIBILITY_STI_BLOCKING;
+
+/*
+ * Optional capabilities
+ */
+static int cap_halt_exit;
+static int cap_pause_exit;
+static int cap_unrestricted_guest;
+static int cap_monitor_trap;
+
+/* statistics */
+static VMM_STAT_DEFINE(VCPU_MIGRATIONS, "vcpu migration across host cpus");
+static VMM_STAT_DEFINE(VMEXIT_EXTINT, "vm exits due to external interrupt");
+static VMM_STAT_DEFINE(VMEXIT_HLT_IGNORED, "number of times hlt was ignored");
+static VMM_STAT_DEFINE(VMEXIT_HLT, "number of times hlt was intercepted");
+
+#ifdef KTR
+static const char *
+exit_reason_to_str(int reason)
+{
+ static char reasonbuf[32];
+
+ switch (reason) {
+ case EXIT_REASON_EXCEPTION:
+ return "exception";
+ case EXIT_REASON_EXT_INTR:
+ return "extint";
+ case EXIT_REASON_TRIPLE_FAULT:
+ return "triplefault";
+ case EXIT_REASON_INIT:
+ return "init";
+ case EXIT_REASON_SIPI:
+ return "sipi";
+ case EXIT_REASON_IO_SMI:
+ return "iosmi";
+ case EXIT_REASON_SMI:
+ return "smi";
+ case EXIT_REASON_INTR_WINDOW:
+ return "intrwindow";
+ case EXIT_REASON_NMI_WINDOW:
+ return "nmiwindow";
+ case EXIT_REASON_TASK_SWITCH:
+ return "taskswitch";
+ case EXIT_REASON_CPUID:
+ return "cpuid";
+ case EXIT_REASON_GETSEC:
+ return "getsec";
+ case EXIT_REASON_HLT:
+ return "hlt";
+ case EXIT_REASON_INVD:
+ return "invd";
+ case EXIT_REASON_INVLPG:
+ return "invlpg";
+ case EXIT_REASON_RDPMC:
+ return "rdpmc";
+ case EXIT_REASON_RDTSC:
+ return "rdtsc";
+ case EXIT_REASON_RSM:
+ return "rsm";
+ case EXIT_REASON_VMCALL:
+ return "vmcall";
+ case EXIT_REASON_VMCLEAR:
+ return "vmclear";
+ case EXIT_REASON_VMLAUNCH:
+ return "vmlaunch";
+ case EXIT_REASON_VMPTRLD:
+ return "vmptrld";
+ case EXIT_REASON_VMPTRST:
+ return "vmptrst";
+ case EXIT_REASON_VMREAD:
+ return "vmread";
+ case EXIT_REASON_VMRESUME:
+ return "vmresume";
+ case EXIT_REASON_VMWRITE:
+ return "vmwrite";
+ case EXIT_REASON_VMXOFF:
+ return "vmxoff";
+ case EXIT_REASON_VMXON:
+ return "vmxon";
+ case EXIT_REASON_CR_ACCESS:
+ return "craccess";
+ case EXIT_REASON_DR_ACCESS:
+ return "draccess";
+ case EXIT_REASON_INOUT:
+ return "inout";
+ case EXIT_REASON_RDMSR:
+ return "rdmsr";
+ case EXIT_REASON_WRMSR:
+ return "wrmsr";
+ case EXIT_REASON_INVAL_VMCS:
+ return "invalvmcs";
+ case EXIT_REASON_INVAL_MSR:
+ return "invalmsr";
+ case EXIT_REASON_MWAIT:
+ return "mwait";
+ case EXIT_REASON_MTF:
+ return "mtf";
+ case EXIT_REASON_MONITOR:
+ return "monitor";
+ case EXIT_REASON_PAUSE:
+ return "pause";
+ case EXIT_REASON_MCE:
+ return "mce";
+ case EXIT_REASON_TPR:
+ return "tpr";
+ case EXIT_REASON_APIC:
+ return "apic";
+ case EXIT_REASON_GDTR_IDTR:
+ return "gdtridtr";
+ case EXIT_REASON_LDTR_TR:
+ return "ldtrtr";
+ case EXIT_REASON_EPT_FAULT:
+ return "eptfault";
+ case EXIT_REASON_EPT_MISCONFIG:
+ return "eptmisconfig";
+ case EXIT_REASON_INVEPT:
+ return "invept";
+ case EXIT_REASON_RDTSCP:
+ return "rdtscp";
+ case EXIT_REASON_VMX_PREEMPT:
+ return "vmxpreempt";
+ case EXIT_REASON_INVVPID:
+ return "invvpid";
+ case EXIT_REASON_WBINVD:
+ return "wbinvd";
+ case EXIT_REASON_XSETBV:
+ return "xsetbv";
+ default:
+ snprintf(reasonbuf, sizeof(reasonbuf), "%d", reason);
+ return (reasonbuf);
+ }
+}
+
+#ifdef SETJMP_TRACE
+static const char *
+vmx_setjmp_rc2str(int rc)
+{
+ switch (rc) {
+ case VMX_RETURN_DIRECT:
+ return "direct";
+ case VMX_RETURN_LONGJMP:
+ return "longjmp";
+ case VMX_RETURN_VMRESUME:
+ return "vmresume";
+ case VMX_RETURN_VMLAUNCH:
+ return "vmlaunch";
+ case VMX_RETURN_AST:
+ return "ast";
+ default:
+ return "unknown";
+ }
+}
+
+#define SETJMP_TRACE(vmx, vcpu, vmxctx, regname) \
+ VMM_CTR1((vmx)->vm, (vcpu), "setjmp trace " #regname " 0x%016lx", \
+ (vmxctx)->regname)
+
+static void
+vmx_setjmp_trace(struct vmx *vmx, int vcpu, struct vmxctx *vmxctx, int rc)
+{
+ uint64_t host_rip, host_rsp;
+
+ if (vmxctx != &vmx->ctx[vcpu])
+ panic("vmx_setjmp_trace: invalid vmxctx %p; should be %p",
+ vmxctx, &vmx->ctx[vcpu]);
+
+ VMM_CTR1((vmx)->vm, (vcpu), "vmxctx = %p", vmxctx);
+ VMM_CTR2((vmx)->vm, (vcpu), "setjmp return code %s(%d)",
+ vmx_setjmp_rc2str(rc), rc);
+
+ host_rsp = host_rip = ~0;
+ vmread(VMCS_HOST_RIP, &host_rip);
+ vmread(VMCS_HOST_RSP, &host_rsp);
+ VMM_CTR2((vmx)->vm, (vcpu), "vmcs host_rip 0x%016lx, host_rsp 0x%016lx",
+ host_rip, host_rsp);
+
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_r15);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_r14);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_r13);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_r12);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_rbp);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_rsp);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_rbx);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, host_rip);
+
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rdi);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rsi);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rdx);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rcx);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r8);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r9);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rax);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rbx);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_rbp);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r10);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r11);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r12);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r13);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r14);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_r15);
+ SETJMP_TRACE(vmx, vcpu, vmxctx, guest_cr2);
+}
+#endif
+#else
+static void __inline
+vmx_setjmp_trace(struct vmx *vmx, int vcpu, struct vmxctx *vmxctx, int rc)
+{
+ return;
+}
+#endif /* KTR */
+
+u_long
+vmx_fix_cr0(u_long cr0)
+{
+
+ return ((cr0 | cr0_ones_mask) & ~cr0_zeros_mask);
+}
+
+u_long
+vmx_fix_cr4(u_long cr4)
+{
+
+ return ((cr4 | cr4_ones_mask) & ~cr4_zeros_mask);
+}
+
+static void
+msr_save_area_init(struct msr_entry *g_area, int *g_count)
+{
+ int cnt;
+
+ static struct msr_entry guest_msrs[] = {
+ { MSR_KGSBASE, 0, 0 },
+ };
+
+ cnt = sizeof(guest_msrs) / sizeof(guest_msrs[0]);
+ if (cnt > GUEST_MSR_MAX_ENTRIES)
+ panic("guest msr save area overrun");
+ bcopy(guest_msrs, g_area, sizeof(guest_msrs));
+ *g_count = cnt;
+}
+
+static void
+vmx_disable(void *arg __unused)
+{
+ struct invvpid_desc invvpid_desc = { 0 };
+ struct invept_desc invept_desc = { 0 };
+
+ if (vmxon_enabled[curcpu]) {
+ /*
+ * See sections 25.3.3.3 and 25.3.3.4 in Intel Vol 3b.
+ *
+ * VMXON or VMXOFF are not required to invalidate any TLB
+ * caching structures. This prevents potential retention of
+ * cached information in the TLB between distinct VMX episodes.
+ */
+ invvpid(INVVPID_TYPE_ALL_CONTEXTS, invvpid_desc);
+ invept(INVEPT_TYPE_ALL_CONTEXTS, invept_desc);
+ vmxoff();
+ }
+ load_cr4(rcr4() & ~CR4_VMXE);
+}
+
+static int
+vmx_cleanup(void)
+{
+
+ smp_rendezvous(NULL, vmx_disable, NULL, NULL);
+
+ return (0);
+}
+
+static void
+vmx_enable(void *arg __unused)
+{
+ int error;
+
+ load_cr4(rcr4() | CR4_VMXE);
+
+ *(uint32_t *)vmxon_region[curcpu] = vmx_revision();
+ error = vmxon(vmxon_region[curcpu]);
+ if (error == 0)
+ vmxon_enabled[curcpu] = 1;
+}
+
+static int
+vmx_init(void)
+{
+ int error;
+ uint64_t fixed0, fixed1, feature_control;
+ uint32_t tmp;
+
+ /* CPUID.1:ECX[bit 5] must be 1 for processor to support VMX */
+ if (!(cpu_feature2 & CPUID2_VMX)) {
+ printf("vmx_init: processor does not support VMX operation\n");
+ return (ENXIO);
+ }
+
+ /*
+ * Verify that MSR_IA32_FEATURE_CONTROL lock and VMXON enable bits
+ * are set (bits 0 and 2 respectively).
+ */
+ feature_control = rdmsr(MSR_IA32_FEATURE_CONTROL);
+ if ((feature_control & 0x5) != 0x5) {
+ printf("vmx_init: VMX operation disabled by BIOS\n");
+ return (ENXIO);
+ }
+
+ /* Check support for primary processor-based VM-execution controls */
+ error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS,
+ MSR_VMX_TRUE_PROCBASED_CTLS,
+ PROCBASED_CTLS_ONE_SETTING,
+ PROCBASED_CTLS_ZERO_SETTING, &procbased_ctls);
+ if (error) {
+ printf("vmx_init: processor does not support desired primary "
+ "processor-based controls\n");
+ return (error);
+ }
+
+ /* Clear the processor-based ctl bits that are set on demand */
+ procbased_ctls &= ~PROCBASED_CTLS_WINDOW_SETTING;
+
+ /* Check support for secondary processor-based VM-execution controls */
+ error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2,
+ MSR_VMX_PROCBASED_CTLS2,
+ PROCBASED_CTLS2_ONE_SETTING,
+ PROCBASED_CTLS2_ZERO_SETTING, &procbased_ctls2);
+ if (error) {
+ printf("vmx_init: processor does not support desired secondary "
+ "processor-based controls\n");
+ return (error);
+ }
+
+ /* Check support for VPID */
+ error = vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2, MSR_VMX_PROCBASED_CTLS2,
+ PROCBASED2_ENABLE_VPID, 0, &tmp);
+ if (error == 0)
+ procbased_ctls2 |= PROCBASED2_ENABLE_VPID;
+
+ /* Check support for pin-based VM-execution controls */
+ error = vmx_set_ctlreg(MSR_VMX_PINBASED_CTLS,
+ MSR_VMX_TRUE_PINBASED_CTLS,
+ PINBASED_CTLS_ONE_SETTING,
+ PINBASED_CTLS_ZERO_SETTING, &pinbased_ctls);
+ if (error) {
+ printf("vmx_init: processor does not support desired "
+ "pin-based controls\n");
+ return (error);
+ }
+
+ /* Check support for VM-exit controls */
+ error = vmx_set_ctlreg(MSR_VMX_EXIT_CTLS, MSR_VMX_TRUE_EXIT_CTLS,
+ VM_EXIT_CTLS_ONE_SETTING,
+ VM_EXIT_CTLS_ZERO_SETTING,
+ &exit_ctls);
+ if (error) {
+ /* Try again without the PAT MSR bits */
+ error = vmx_set_ctlreg(MSR_VMX_EXIT_CTLS,
+ MSR_VMX_TRUE_EXIT_CTLS,
+ VM_EXIT_CTLS_ONE_SETTING_NO_PAT,
+ VM_EXIT_CTLS_ZERO_SETTING,
+ &exit_ctls);
+ if (error) {
+ printf("vmx_init: processor does not support desired "
+ "exit controls\n");
+ return (error);
+ } else {
+ if (bootverbose)
+ printf("vmm: PAT MSR access not supported\n");
+ guest_msr_valid(MSR_PAT);
+ vmx_no_patmsr = 1;
+ }
+ }
+
+ /* Check support for VM-entry controls */
+ if (!vmx_no_patmsr) {
+ error = vmx_set_ctlreg(MSR_VMX_ENTRY_CTLS,
+ MSR_VMX_TRUE_ENTRY_CTLS,
+ VM_ENTRY_CTLS_ONE_SETTING,
+ VM_ENTRY_CTLS_ZERO_SETTING,
+ &entry_ctls);
+ } else {
+ error = vmx_set_ctlreg(MSR_VMX_ENTRY_CTLS,
+ MSR_VMX_TRUE_ENTRY_CTLS,
+ VM_ENTRY_CTLS_ONE_SETTING_NO_PAT,
+ VM_ENTRY_CTLS_ZERO_SETTING,
+ &entry_ctls);
+ }
+
+ if (error) {
+ printf("vmx_init: processor does not support desired "
+ "entry controls\n");
+ return (error);
+ }
+
+ /*
+ * Check support for optional features by testing them
+ * as individual bits
+ */
+ cap_halt_exit = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS,
+ MSR_VMX_TRUE_PROCBASED_CTLS,
+ PROCBASED_HLT_EXITING, 0,
+ &tmp) == 0);
+
+ cap_monitor_trap = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS,
+ MSR_VMX_PROCBASED_CTLS,
+ PROCBASED_MTF, 0,
+ &tmp) == 0);
+
+ cap_pause_exit = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS,
+ MSR_VMX_TRUE_PROCBASED_CTLS,
+ PROCBASED_PAUSE_EXITING, 0,
+ &tmp) == 0);
+
+ cap_unrestricted_guest = (vmx_set_ctlreg(MSR_VMX_PROCBASED_CTLS2,
+ MSR_VMX_PROCBASED_CTLS2,
+ PROCBASED2_UNRESTRICTED_GUEST, 0,
+ &tmp) == 0);
+
+ /* Initialize EPT */
+ error = ept_init();
+ if (error) {
+ printf("vmx_init: ept initialization failed (%d)\n", error);
+ return (error);
+ }
+
+ /*
+ * Stash the cr0 and cr4 bits that must be fixed to 0 or 1
+ */
+ fixed0 = rdmsr(MSR_VMX_CR0_FIXED0);
+ fixed1 = rdmsr(MSR_VMX_CR0_FIXED1);
+ cr0_ones_mask = fixed0 & fixed1;
+ cr0_zeros_mask = ~fixed0 & ~fixed1;
+
+ /*
+ * CR0_PE and CR0_PG can be set to zero in VMX non-root operation
+ * if unrestricted guest execution is allowed.
+ */
+ if (cap_unrestricted_guest)
+ cr0_ones_mask &= ~(CR0_PG | CR0_PE);
+
+ /*
+ * Do not allow the guest to set CR0_NW or CR0_CD.
+ */
+ cr0_zeros_mask |= (CR0_NW | CR0_CD);
+
+ fixed0 = rdmsr(MSR_VMX_CR4_FIXED0);
+ fixed1 = rdmsr(MSR_VMX_CR4_FIXED1);
+ cr4_ones_mask = fixed0 & fixed1;
+ cr4_zeros_mask = ~fixed0 & ~fixed1;
+
+ /* enable VMX operation */
+ smp_rendezvous(NULL, vmx_enable, NULL, NULL);
+
+ return (0);
+}
+
+/*
+ * If this processor does not support VPIDs then simply return 0.
+ *
+ * Otherwise generate the next value of VPID to use. Any value is alright
+ * as long as it is non-zero.
+ *
+ * We always execute in VMX non-root context with EPT enabled. Thus all
+ * combined mappings are tagged with the (EP4TA, VPID, PCID) tuple. This
+ * in turn means that multiple VMs can share the same VPID as long as
+ * they have distinct EPT page tables.
+ *
+ * XXX
+ * We should optimize this so that it returns VPIDs that are not in
+ * use. Then we will not unnecessarily invalidate mappings in
+ * vmx_set_pcpu_defaults() just because two or more vcpus happen to
+ * use the same 'vpid'.
+ */
+static uint16_t
+vmx_vpid(void)
+{
+ uint16_t vpid = 0;
+
+ if ((procbased_ctls2 & PROCBASED2_ENABLE_VPID) != 0) {
+ do {
+ vpid = atomic_fetchadd_int(&nextvpid, 1);
+ } while (vpid == 0);
+ }
+
+ return (vpid);
+}
+
+static int
+vmx_setup_cr_shadow(int which, struct vmcs *vmcs)
+{
+ int error, mask_ident, shadow_ident;
+ uint64_t mask_value, shadow_value;
+
+ if (which != 0 && which != 4)
+ panic("vmx_setup_cr_shadow: unknown cr%d", which);
+
+ if (which == 0) {
+ mask_ident = VMCS_CR0_MASK;
+ mask_value = cr0_ones_mask | cr0_zeros_mask;
+ shadow_ident = VMCS_CR0_SHADOW;
+ shadow_value = cr0_ones_mask;
+ } else {
+ mask_ident = VMCS_CR4_MASK;
+ mask_value = cr4_ones_mask | cr4_zeros_mask;
+ shadow_ident = VMCS_CR4_SHADOW;
+ shadow_value = cr4_ones_mask;
+ }
+
+ error = vmcs_setreg(vmcs, VMCS_IDENT(mask_ident), mask_value);
+ if (error)
+ return (error);
+
+ error = vmcs_setreg(vmcs, VMCS_IDENT(shadow_ident), shadow_value);
+ if (error)
+ return (error);
+
+ return (0);
+}
+#define vmx_setup_cr0_shadow(vmcs) vmx_setup_cr_shadow(0, (vmcs))
+#define vmx_setup_cr4_shadow(vmcs) vmx_setup_cr_shadow(4, (vmcs))
+
+static void *
+vmx_vminit(struct vm *vm)
+{
+ uint16_t vpid;
+ int i, error, guest_msr_count;
+ struct vmx *vmx;
+
+ vmx = malloc(sizeof(struct vmx), M_VMX, M_WAITOK | M_ZERO);
+ if ((uintptr_t)vmx & PAGE_MASK) {
+ panic("malloc of struct vmx not aligned on %d byte boundary",
+ PAGE_SIZE);
+ }
+ vmx->vm = vm;
+
+ /*
+ * Clean up EPTP-tagged guest physical and combined mappings
+ *
+ * VMX transitions are not required to invalidate any guest physical
+ * mappings. So, it may be possible for stale guest physical mappings
+ * to be present in the processor TLBs.
+ *
+ * Combined mappings for this EP4TA are also invalidated for all VPIDs.
+ */
+ ept_invalidate_mappings(vtophys(vmx->pml4ept));
+
+ msr_bitmap_initialize(vmx->msr_bitmap);
+
+ /*
+ * It is safe to allow direct access to MSR_GSBASE and MSR_FSBASE.
+ * The guest FSBASE and GSBASE are saved and restored during
+ * vm-exit and vm-entry respectively. The host FSBASE and GSBASE are
+ * always restored from the vmcs host state area on vm-exit.
+ *
+ * The SYSENTER_CS/ESP/EIP MSRs are identical to FS/GSBASE in
+ * how they are saved/restored so can be directly accessed by the
+ * guest.
+ *
+ * Guest KGSBASE is saved and restored in the guest MSR save area.
+ * Host KGSBASE is restored before returning to userland from the pcb.
+ * There will be a window of time when we are executing in the host
+ * kernel context with a value of KGSBASE from the guest. This is ok
+ * because the value of KGSBASE is inconsequential in kernel context.
+ *
+ * MSR_EFER is saved and restored in the guest VMCS area on a
+ * VM exit and entry respectively. It is also restored from the
+ * host VMCS area on a VM exit.
+ */
+ if (guest_msr_rw(vmx, MSR_GSBASE) ||
+ guest_msr_rw(vmx, MSR_FSBASE) ||
+ guest_msr_rw(vmx, MSR_SYSENTER_CS_MSR) ||
+ guest_msr_rw(vmx, MSR_SYSENTER_ESP_MSR) ||
+ guest_msr_rw(vmx, MSR_SYSENTER_EIP_MSR) ||
+ guest_msr_rw(vmx, MSR_KGSBASE) ||
+ guest_msr_rw(vmx, MSR_EFER))
+ panic("vmx_vminit: error setting guest msr access");
+
+ /*
+ * MSR_PAT is saved and restored in the guest VMCS are on a VM exit
+ * and entry respectively. It is also restored from the host VMCS
+ * area on a VM exit. However, if running on a system with no
+ * MSR_PAT save/restore support, leave access disabled so accesses
+ * will be trapped.
+ */
+ if (!vmx_no_patmsr && guest_msr_rw(vmx, MSR_PAT))
+ panic("vmx_vminit: error setting guest pat msr access");
+
+ for (i = 0; i < VM_MAXCPU; i++) {
+ vmx->vmcs[i].identifier = vmx_revision();
+ error = vmclear(&vmx->vmcs[i]);
+ if (error != 0) {
+ panic("vmx_vminit: vmclear error %d on vcpu %d\n",
+ error, i);
+ }
+
+ vpid = vmx_vpid();
+
+ error = vmcs_set_defaults(&vmx->vmcs[i],
+ (u_long)vmx_longjmp,
+ (u_long)&vmx->ctx[i],
+ vtophys(vmx->pml4ept),
+ pinbased_ctls,
+ procbased_ctls,
+ procbased_ctls2,
+ exit_ctls, entry_ctls,
+ vtophys(vmx->msr_bitmap),
+ vpid);
+
+ if (error != 0)
+ panic("vmx_vminit: vmcs_set_defaults error %d", error);
+
+ vmx->cap[i].set = 0;
+ vmx->cap[i].proc_ctls = procbased_ctls;
+
+ vmx->state[i].lastcpu = -1;
+ vmx->state[i].vpid = vpid;
+
+ msr_save_area_init(vmx->guest_msrs[i], &guest_msr_count);
+
+ error = vmcs_set_msr_save(&vmx->vmcs[i],
+ vtophys(vmx->guest_msrs[i]),
+ guest_msr_count);
+ if (error != 0)
+ panic("vmcs_set_msr_save error %d", error);
+
+ error = vmx_setup_cr0_shadow(&vmx->vmcs[i]);
+ if (error != 0)
+ panic("vmx_setup_cr0_shadow %d", error);
+
+ error = vmx_setup_cr4_shadow(&vmx->vmcs[i]);
+ if (error != 0)
+ panic("vmx_setup_cr4_shadow %d", error);
+ }
+
+ return (vmx);
+}
+
+static int
+vmx_handle_cpuid(struct vm *vm, int vcpu, struct vmxctx *vmxctx)
+{
+ int handled, func;
+
+ func = vmxctx->guest_rax;
+
+ handled = x86_emulate_cpuid(vm, vcpu,
+ (uint32_t*)(&vmxctx->guest_rax),
+ (uint32_t*)(&vmxctx->guest_rbx),
+ (uint32_t*)(&vmxctx->guest_rcx),
+ (uint32_t*)(&vmxctx->guest_rdx));
+ return (handled);
+}
+
+static __inline void
+vmx_run_trace(struct vmx *vmx, int vcpu)
+{
+#ifdef KTR
+ VMM_CTR1(vmx->vm, vcpu, "Resume execution at 0x%0lx", vmcs_guest_rip());
+#endif
+}
+
+static __inline void
+vmx_exit_trace(struct vmx *vmx, int vcpu, uint64_t rip, uint32_t exit_reason,
+ int handled)
+{
+#ifdef KTR
+ VMM_CTR3(vmx->vm, vcpu, "%s %s vmexit at 0x%0lx",
+ handled ? "handled" : "unhandled",
+ exit_reason_to_str(exit_reason), rip);
+#endif
+}
+
+static __inline void
+vmx_astpending_trace(struct vmx *vmx, int vcpu, uint64_t rip)
+{
+#ifdef KTR
+ VMM_CTR1(vmx->vm, vcpu, "astpending vmexit at 0x%0lx", rip);
+#endif
+}
+
+static int
+vmx_set_pcpu_defaults(struct vmx *vmx, int vcpu)
+{
+ int error, lastcpu;
+ struct vmxstate *vmxstate;
+ struct invvpid_desc invvpid_desc = { 0 };
+
+ vmxstate = &vmx->state[vcpu];
+ lastcpu = vmxstate->lastcpu;
+ vmxstate->lastcpu = curcpu;
+
+ if (lastcpu == curcpu) {
+ error = 0;
+ goto done;
+ }
+
+ vmm_stat_incr(vmx->vm, vcpu, VCPU_MIGRATIONS, 1);
+
+ error = vmwrite(VMCS_HOST_TR_BASE, vmm_get_host_trbase());
+ if (error != 0)
+ goto done;
+
+ error = vmwrite(VMCS_HOST_GDTR_BASE, vmm_get_host_gdtrbase());
+ if (error != 0)
+ goto done;
+
+ error = vmwrite(VMCS_HOST_GS_BASE, vmm_get_host_gsbase());
+ if (error != 0)
+ goto done;
+
+ /*
+ * If we are using VPIDs then invalidate all mappings tagged with 'vpid'
+ *
+ * We do this because this vcpu was executing on a different host
+ * cpu when it last ran. We do not track whether it invalidated
+ * mappings associated with its 'vpid' during that run. So we must
+ * assume that the mappings associated with 'vpid' on 'curcpu' are
+ * stale and invalidate them.
+ *
+ * Note that we incur this penalty only when the scheduler chooses to
+ * move the thread associated with this vcpu between host cpus.
+ *
+ * Note also that this will invalidate mappings tagged with 'vpid'
+ * for "all" EP4TAs.
+ */
+ if (vmxstate->vpid != 0) {
+ invvpid_desc.vpid = vmxstate->vpid;
+ invvpid(INVVPID_TYPE_SINGLE_CONTEXT, invvpid_desc);
+ }
+done:
+ return (error);
+}
+
+static void
+vm_exit_update_rip(struct vm_exit *vmexit)
+{
+ int error;
+
+ error = vmwrite(VMCS_GUEST_RIP, vmexit->rip + vmexit->inst_length);
+ if (error)
+ panic("vmx_run: error %d writing to VMCS_GUEST_RIP", error);
+}
+
+/*
+ * We depend on 'procbased_ctls' to have the Interrupt Window Exiting bit set.
+ */
+CTASSERT((PROCBASED_CTLS_ONE_SETTING & PROCBASED_INT_WINDOW_EXITING) != 0);
+
+static void __inline
+vmx_set_int_window_exiting(struct vmx *vmx, int vcpu)
+{
+ int error;
+
+ vmx->cap[vcpu].proc_ctls |= PROCBASED_INT_WINDOW_EXITING;
+
+ error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls);
+ if (error)
+ panic("vmx_set_int_window_exiting: vmwrite error %d", error);
+}
+
+static void __inline
+vmx_clear_int_window_exiting(struct vmx *vmx, int vcpu)
+{
+ int error;
+
+ vmx->cap[vcpu].proc_ctls &= ~PROCBASED_INT_WINDOW_EXITING;
+
+ error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls);
+ if (error)
+ panic("vmx_clear_int_window_exiting: vmwrite error %d", error);
+}
+
+static void __inline
+vmx_set_nmi_window_exiting(struct vmx *vmx, int vcpu)
+{
+ int error;
+
+ vmx->cap[vcpu].proc_ctls |= PROCBASED_NMI_WINDOW_EXITING;
+
+ error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls);
+ if (error)
+ panic("vmx_set_nmi_window_exiting: vmwrite error %d", error);
+}
+
+static void __inline
+vmx_clear_nmi_window_exiting(struct vmx *vmx, int vcpu)
+{
+ int error;
+
+ vmx->cap[vcpu].proc_ctls &= ~PROCBASED_NMI_WINDOW_EXITING;
+
+ error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, vmx->cap[vcpu].proc_ctls);
+ if (error)
+ panic("vmx_clear_nmi_window_exiting: vmwrite error %d", error);
+}
+
+static int
+vmx_inject_nmi(struct vmx *vmx, int vcpu)
+{
+ int error;
+ uint64_t info, interruptibility;
+
+ /* Bail out if no NMI requested */
+ if (!vm_nmi_pending(vmx->vm, vcpu))
+ return (0);
+
+ error = vmread(VMCS_GUEST_INTERRUPTIBILITY, &interruptibility);
+ if (error) {
+ panic("vmx_inject_nmi: vmread(interruptibility) %d",
+ error);
+ }
+ if (interruptibility & nmi_blocking_bits)
+ goto nmiblocked;
+
+ /*
+ * Inject the virtual NMI. The vector must be the NMI IDT entry
+ * or the VMCS entry check will fail.
+ */
+ info = VMCS_INTERRUPTION_INFO_NMI | VMCS_INTERRUPTION_INFO_VALID;
+ info |= IDT_NMI;
+
+ error = vmwrite(VMCS_ENTRY_INTR_INFO, info);
+ if (error)
+ panic("vmx_inject_nmi: vmwrite(intrinfo) %d", error);
+
+ VMM_CTR0(vmx->vm, vcpu, "Injecting vNMI");
+
+ /* Clear the request */
+ vm_nmi_clear(vmx->vm, vcpu);
+ return (1);
+
+nmiblocked:
+ /*
+ * Set the NMI Window Exiting execution control so we can inject
+ * the virtual NMI as soon as blocking condition goes away.
+ */
+ vmx_set_nmi_window_exiting(vmx, vcpu);
+
+ VMM_CTR0(vmx->vm, vcpu, "Enabling NMI window exiting");
+ return (1);
+}
+
+static void
+vmx_inject_interrupts(struct vmx *vmx, int vcpu)
+{
+ int error, vector;
+ uint64_t info, rflags, interruptibility;
+
+ const int HWINTR_BLOCKED = VMCS_INTERRUPTIBILITY_STI_BLOCKING |
+ VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING;
+
+ /*
+ * If there is already an interrupt pending then just return.
+ *
+ * This could happen if an interrupt was injected on a prior
+ * VM entry but the actual entry into guest mode was aborted
+ * because of a pending AST.
+ */
+ error = vmread(VMCS_ENTRY_INTR_INFO, &info);
+ if (error)
+ panic("vmx_inject_interrupts: vmread(intrinfo) %d", error);
+ if (info & VMCS_INTERRUPTION_INFO_VALID)
+ return;
+
+ /*
+ * NMI injection has priority so deal with those first
+ */
+ if (vmx_inject_nmi(vmx, vcpu))
+ return;
+
+ /* Ask the local apic for a vector to inject */
+ vector = lapic_pending_intr(vmx->vm, vcpu);
+ if (vector < 0)
+ return;
+
+ if (vector < 32 || vector > 255)
+ panic("vmx_inject_interrupts: invalid vector %d\n", vector);
+
+ /* Check RFLAGS.IF and the interruptibility state of the guest */
+ error = vmread(VMCS_GUEST_RFLAGS, &rflags);
+ if (error)
+ panic("vmx_inject_interrupts: vmread(rflags) %d", error);
+
+ if ((rflags & PSL_I) == 0)
+ goto cantinject;
+
+ error = vmread(VMCS_GUEST_INTERRUPTIBILITY, &interruptibility);
+ if (error) {
+ panic("vmx_inject_interrupts: vmread(interruptibility) %d",
+ error);
+ }
+ if (interruptibility & HWINTR_BLOCKED)
+ goto cantinject;
+
+ /* Inject the interrupt */
+ info = VMCS_INTERRUPTION_INFO_HW_INTR | VMCS_INTERRUPTION_INFO_VALID;
+ info |= vector;
+ error = vmwrite(VMCS_ENTRY_INTR_INFO, info);
+ if (error)
+ panic("vmx_inject_interrupts: vmwrite(intrinfo) %d", error);
+
+ /* Update the Local APIC ISR */
+ lapic_intr_accepted(vmx->vm, vcpu, vector);
+
+ VMM_CTR1(vmx->vm, vcpu, "Injecting hwintr at vector %d", vector);
+
+ return;
+
+cantinject:
+ /*
+ * Set the Interrupt Window Exiting execution control so we can inject
+ * the interrupt as soon as blocking condition goes away.
+ */
+ vmx_set_int_window_exiting(vmx, vcpu);
+
+ VMM_CTR0(vmx->vm, vcpu, "Enabling interrupt window exiting");
+}
+
+static int
+vmx_emulate_cr_access(struct vmx *vmx, int vcpu, uint64_t exitqual)
+{
+ int error, cr, vmcs_guest_cr;
+ uint64_t regval, ones_mask, zeros_mask;
+ const struct vmxctx *vmxctx;
+
+ /* We only handle mov to %cr0 or %cr4 at this time */
+ if ((exitqual & 0xf0) != 0x00)
+ return (UNHANDLED);
+
+ cr = exitqual & 0xf;
+ if (cr != 0 && cr != 4)
+ return (UNHANDLED);
+
+ vmxctx = &vmx->ctx[vcpu];
+
+ /*
+ * We must use vmwrite() directly here because vmcs_setreg() will
+ * call vmclear(vmcs) as a side-effect which we certainly don't want.
+ */
+ switch ((exitqual >> 8) & 0xf) {
+ case 0:
+ regval = vmxctx->guest_rax;
+ break;
+ case 1:
+ regval = vmxctx->guest_rcx;
+ break;
+ case 2:
+ regval = vmxctx->guest_rdx;
+ break;
+ case 3:
+ regval = vmxctx->guest_rbx;
+ break;
+ case 4:
+ error = vmread(VMCS_GUEST_RSP, &regval);
+ if (error) {
+ panic("vmx_emulate_cr_access: "
+ "error %d reading guest rsp", error);
+ }
+ break;
+ case 5:
+ regval = vmxctx->guest_rbp;
+ break;
+ case 6:
+ regval = vmxctx->guest_rsi;
+ break;
+ case 7:
+ regval = vmxctx->guest_rdi;
+ break;
+ case 8:
+ regval = vmxctx->guest_r8;
+ break;
+ case 9:
+ regval = vmxctx->guest_r9;
+ break;
+ case 10:
+ regval = vmxctx->guest_r10;
+ break;
+ case 11:
+ regval = vmxctx->guest_r11;
+ break;
+ case 12:
+ regval = vmxctx->guest_r12;
+ break;
+ case 13:
+ regval = vmxctx->guest_r13;
+ break;
+ case 14:
+ regval = vmxctx->guest_r14;
+ break;
+ case 15:
+ regval = vmxctx->guest_r15;
+ break;
+ }
+
+ if (cr == 0) {
+ ones_mask = cr0_ones_mask;
+ zeros_mask = cr0_zeros_mask;
+ vmcs_guest_cr = VMCS_GUEST_CR0;
+ } else {
+ ones_mask = cr4_ones_mask;
+ zeros_mask = cr4_zeros_mask;
+ vmcs_guest_cr = VMCS_GUEST_CR4;
+ }
+ regval |= ones_mask;
+ regval &= ~zeros_mask;
+ error = vmwrite(vmcs_guest_cr, regval);
+ if (error) {
+ panic("vmx_emulate_cr_access: error %d writing cr%d",
+ error, cr);
+ }
+
+ return (HANDLED);
+}
+
+static int
+vmx_ept_fault(struct vm *vm, int cpu,
+ uint64_t gla, uint64_t gpa, uint64_t rip, int inst_length,
+ uint64_t cr3, uint64_t ept_qual, struct vie *vie)
+{
+ int read, write, error;
+
+ /* EPT violation on an instruction fetch doesn't make sense here */
+ if (ept_qual & EPT_VIOLATION_INST_FETCH)
+ return (UNHANDLED);
+
+ /* EPT violation must be a read fault or a write fault */
+ read = ept_qual & EPT_VIOLATION_DATA_READ ? 1 : 0;
+ write = ept_qual & EPT_VIOLATION_DATA_WRITE ? 1 : 0;
+ if ((read | write) == 0)
+ return (UNHANDLED);
+
+ /*
+ * The EPT violation must have been caused by accessing a
+ * guest-physical address that is a translation of a guest-linear
+ * address.
+ */
+ if ((ept_qual & EPT_VIOLATION_GLA_VALID) == 0 ||
+ (ept_qual & EPT_VIOLATION_XLAT_VALID) == 0) {
+ return (UNHANDLED);
+ }
+
+ /* Fetch, decode and emulate the faulting instruction */
+ if (vmm_fetch_instruction(vm, cpu, rip, inst_length, cr3, vie) != 0)
+ return (UNHANDLED);
+
+ if (vmm_decode_instruction(vm, cpu, gla, vie) != 0)
+ return (UNHANDLED);
+
+ /*
+ * Check if this is a local apic access
+ */
+ if (gpa < DEFAULT_APIC_BASE || gpa >= DEFAULT_APIC_BASE + PAGE_SIZE)
+ return (UNHANDLED);
+
+ error = vmm_emulate_instruction(vm, cpu, gpa, vie,
+ lapic_mmio_read, lapic_mmio_write, 0);
+
+ return (error ? UNHANDLED : HANDLED);
+}
+
+static int
+vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit)
+{
+ int error, handled;
+ struct vmcs *vmcs;
+ struct vmxctx *vmxctx;
+ uint32_t eax, ecx, edx;
+ uint64_t qual, gla, gpa, cr3, intr_info;
+
+ handled = 0;
+ vmcs = &vmx->vmcs[vcpu];
+ vmxctx = &vmx->ctx[vcpu];
+ qual = vmexit->u.vmx.exit_qualification;
+ vmexit->exitcode = VM_EXITCODE_BOGUS;
+
+ switch (vmexit->u.vmx.exit_reason) {
+ case EXIT_REASON_CR_ACCESS:
+ handled = vmx_emulate_cr_access(vmx, vcpu, qual);
+ break;
+ case EXIT_REASON_RDMSR:
+ ecx = vmxctx->guest_rcx;
+ error = emulate_rdmsr(vmx->vm, vcpu, ecx);
+ if (error) {
+ vmexit->exitcode = VM_EXITCODE_RDMSR;
+ vmexit->u.msr.code = ecx;
+ } else
+ handled = 1;
+ break;
+ case EXIT_REASON_WRMSR:
+ eax = vmxctx->guest_rax;
+ ecx = vmxctx->guest_rcx;
+ edx = vmxctx->guest_rdx;
+ error = emulate_wrmsr(vmx->vm, vcpu, ecx,
+ (uint64_t)edx << 32 | eax);
+ if (error) {
+ vmexit->exitcode = VM_EXITCODE_WRMSR;
+ vmexit->u.msr.code = ecx;
+ vmexit->u.msr.wval = (uint64_t)edx << 32 | eax;
+ } else
+ handled = 1;
+ break;
+ case EXIT_REASON_HLT:
+ vmm_stat_incr(vmx->vm, vcpu, VMEXIT_HLT, 1);
+ /*
+ * If there is an event waiting to be injected then there is
+ * no need to 'hlt'.
+ */
+ error = vmread(VMCS_ENTRY_INTR_INFO, &intr_info);
+ if (error)
+ panic("vmx_exit_process: vmread(intrinfo) %d", error);
+
+ if (intr_info & VMCS_INTERRUPTION_INFO_VALID) {
+ handled = 1;
+ vmm_stat_incr(vmx->vm, vcpu, VMEXIT_HLT_IGNORED, 1);
+ } else
+ vmexit->exitcode = VM_EXITCODE_HLT;
+ break;
+ case EXIT_REASON_MTF:
+ vmexit->exitcode = VM_EXITCODE_MTRAP;
+ break;
+ case EXIT_REASON_PAUSE:
+ vmexit->exitcode = VM_EXITCODE_PAUSE;
+ break;
+ case EXIT_REASON_INTR_WINDOW:
+ vmx_clear_int_window_exiting(vmx, vcpu);
+ VMM_CTR0(vmx->vm, vcpu, "Disabling interrupt window exiting");
+ /* FALLTHRU */
+ case EXIT_REASON_EXT_INTR:
+ /*
+ * External interrupts serve only to cause VM exits and allow
+ * the host interrupt handler to run.
+ *
+ * If this external interrupt triggers a virtual interrupt
+ * to a VM, then that state will be recorded by the
+ * host interrupt handler in the VM's softc. We will inject
+ * this virtual interrupt during the subsequent VM enter.
+ */
+
+ /*
+ * This is special. We want to treat this as an 'handled'
+ * VM-exit but not increment the instruction pointer.
+ */
+ vmm_stat_incr(vmx->vm, vcpu, VMEXIT_EXTINT, 1);
+ return (1);
+ case EXIT_REASON_NMI_WINDOW:
+ /* Exit to allow the pending virtual NMI to be injected */
+ vmx_clear_nmi_window_exiting(vmx, vcpu);
+ VMM_CTR0(vmx->vm, vcpu, "Disabling NMI window exiting");
+ return (1);
+ case EXIT_REASON_INOUT:
+ vmexit->exitcode = VM_EXITCODE_INOUT;
+ vmexit->u.inout.bytes = (qual & 0x7) + 1;
+ vmexit->u.inout.in = (qual & 0x8) ? 1 : 0;
+ vmexit->u.inout.string = (qual & 0x10) ? 1 : 0;
+ vmexit->u.inout.rep = (qual & 0x20) ? 1 : 0;
+ vmexit->u.inout.port = (uint16_t)(qual >> 16);
+ vmexit->u.inout.eax = (uint32_t)(vmxctx->guest_rax);
+ break;
+ case EXIT_REASON_CPUID:
+ handled = vmx_handle_cpuid(vmx->vm, vcpu, vmxctx);
+ break;
+ case EXIT_REASON_EPT_FAULT:
+ gla = vmcs_gla();
+ gpa = vmcs_gpa();
+ cr3 = vmcs_guest_cr3();
+ handled = vmx_ept_fault(vmx->vm, vcpu, gla, gpa,
+ vmexit->rip, vmexit->inst_length,
+ cr3, qual, &vmexit->u.paging.vie);
+ if (!handled) {
+ vmexit->exitcode = VM_EXITCODE_PAGING;
+ vmexit->u.paging.gpa = gpa;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (handled) {
+ /*
+ * It is possible that control is returned to userland
+ * even though we were able to handle the VM exit in the
+ * kernel.
+ *
+ * In such a case we want to make sure that the userland
+ * restarts guest execution at the instruction *after*
+ * the one we just processed. Therefore we update the
+ * guest rip in the VMCS and in 'vmexit'.
+ */
+ vm_exit_update_rip(vmexit);
+ vmexit->rip += vmexit->inst_length;
+ vmexit->inst_length = 0;
+
+ /*
+ * Special case for spinning up an AP - exit to userspace to
+ * give the controlling process a chance to intercept and
+ * spin up a thread for the AP.
+ */
+ if (vmexit->exitcode == VM_EXITCODE_SPINUP_AP)
+ handled = 0;
+ } else {
+ if (vmexit->exitcode == VM_EXITCODE_BOGUS) {
+ /*
+ * If this VM exit was not claimed by anybody then
+ * treat it as a generic VMX exit.
+ */
+ vmexit->exitcode = VM_EXITCODE_VMX;
+ vmexit->u.vmx.error = 0;
+ } else {
+ /*
+ * The exitcode and collateral have been populated.
+ * The VM exit will be processed further in userland.
+ */
+ }
+ }
+ return (handled);
+}
+
+static int
+vmx_run(void *arg, int vcpu, register_t rip)
+{
+ int error, vie, rc, handled, astpending;
+ uint32_t exit_reason;
+ struct vmx *vmx;
+ struct vmxctx *vmxctx;
+ struct vmcs *vmcs;
+ struct vm_exit *vmexit;
+
+ vmx = arg;
+ vmcs = &vmx->vmcs[vcpu];
+ vmxctx = &vmx->ctx[vcpu];
+ vmxctx->launched = 0;
+
+ astpending = 0;
+ vmexit = vm_exitinfo(vmx->vm, vcpu);
+
+ /*
+ * XXX Can we avoid doing this every time we do a vm run?
+ */
+ VMPTRLD(vmcs);
+
+ /*
+ * XXX
+ * We do this every time because we may setup the virtual machine
+ * from a different process than the one that actually runs it.
+ *
+ * If the life of a virtual machine was spent entirely in the context
+ * of a single process we could do this once in vmcs_set_defaults().
+ */
+ if ((error = vmwrite(VMCS_HOST_CR3, rcr3())) != 0)
+ panic("vmx_run: error %d writing to VMCS_HOST_CR3", error);
+
+ if ((error = vmwrite(VMCS_GUEST_RIP, rip)) != 0)
+ panic("vmx_run: error %d writing to VMCS_GUEST_RIP", error);
+
+ if ((error = vmx_set_pcpu_defaults(vmx, vcpu)) != 0)
+ panic("vmx_run: error %d setting up pcpu defaults", error);
+
+ do {
+ lapic_timer_tick(vmx->vm, vcpu);
+ vmx_inject_interrupts(vmx, vcpu);
+ vmx_run_trace(vmx, vcpu);
+ rc = vmx_setjmp(vmxctx);
+#ifdef SETJMP_TRACE
+ vmx_setjmp_trace(vmx, vcpu, vmxctx, rc);
+#endif
+ switch (rc) {
+ case VMX_RETURN_DIRECT:
+ if (vmxctx->launched == 0) {
+ vmxctx->launched = 1;
+ vmx_launch(vmxctx);
+ } else
+ vmx_resume(vmxctx);
+ panic("vmx_launch/resume should not return");
+ break;
+ case VMX_RETURN_LONGJMP:
+ break; /* vm exit */
+ case VMX_RETURN_AST:
+ astpending = 1;
+ break;
+ case VMX_RETURN_VMRESUME:
+ vie = vmcs_instruction_error();
+ if (vmxctx->launch_error == VM_FAIL_INVALID ||
+ vie != VMRESUME_WITH_NON_LAUNCHED_VMCS) {
+ printf("vmresume error %d vmcs inst error %d\n",
+ vmxctx->launch_error, vie);
+ goto err_exit;
+ }
+ vmx_launch(vmxctx); /* try to launch the guest */
+ panic("vmx_launch should not return");
+ break;
+ case VMX_RETURN_VMLAUNCH:
+ vie = vmcs_instruction_error();
+#if 1
+ printf("vmlaunch error %d vmcs inst error %d\n",
+ vmxctx->launch_error, vie);
+#endif
+ goto err_exit;
+ default:
+ panic("vmx_setjmp returned %d", rc);
+ }
+
+ /* enable interrupts */
+ enable_intr();
+
+ /* collect some basic information for VM exit processing */
+ vmexit->rip = rip = vmcs_guest_rip();
+ vmexit->inst_length = vmexit_instruction_length();
+ vmexit->u.vmx.exit_reason = exit_reason = vmcs_exit_reason();
+ vmexit->u.vmx.exit_qualification = vmcs_exit_qualification();
+
+ if (astpending) {
+ handled = 1;
+ vmexit->inst_length = 0;
+ vmexit->exitcode = VM_EXITCODE_BOGUS;
+ vmx_astpending_trace(vmx, vcpu, rip);
+ break;
+ }
+
+ handled = vmx_exit_process(vmx, vcpu, vmexit);
+ vmx_exit_trace(vmx, vcpu, rip, exit_reason, handled);
+
+ } while (handled);
+
+ /*
+ * If a VM exit has been handled then the exitcode must be BOGUS
+ * If a VM exit is not handled then the exitcode must not be BOGUS
+ */
+ if ((handled && vmexit->exitcode != VM_EXITCODE_BOGUS) ||
+ (!handled && vmexit->exitcode == VM_EXITCODE_BOGUS)) {
+ panic("Mismatch between handled (%d) and exitcode (%d)",
+ handled, vmexit->exitcode);
+ }
+
+ VMM_CTR1(vmx->vm, vcpu, "goto userland: exitcode %d",vmexit->exitcode);
+
+ /*
+ * XXX
+ * We need to do this to ensure that any VMCS state cached by the
+ * processor is flushed to memory. We need to do this in case the
+ * VM moves to a different cpu the next time it runs.
+ *
+ * Can we avoid doing this?
+ */
+ VMCLEAR(vmcs);
+ return (0);
+
+err_exit:
+ vmexit->exitcode = VM_EXITCODE_VMX;
+ vmexit->u.vmx.exit_reason = (uint32_t)-1;
+ vmexit->u.vmx.exit_qualification = (uint32_t)-1;
+ vmexit->u.vmx.error = vie;
+ VMCLEAR(vmcs);
+ return (ENOEXEC);
+}
+
+static void
+vmx_vmcleanup(void *arg)
+{
+ int error;
+ struct vmx *vmx = arg;
+
+ /*
+ * XXXSMP we also need to clear the VMCS active on the other vcpus.
+ */
+ error = vmclear(&vmx->vmcs[0]);
+ if (error != 0)
+ panic("vmx_vmcleanup: vmclear error %d on vcpu 0", error);
+
+ ept_vmcleanup(vmx);
+ free(vmx, M_VMX);
+
+ return;
+}
+
+static register_t *
+vmxctx_regptr(struct vmxctx *vmxctx, int reg)
+{
+
+ switch (reg) {
+ case VM_REG_GUEST_RAX:
+ return (&vmxctx->guest_rax);
+ case VM_REG_GUEST_RBX:
+ return (&vmxctx->guest_rbx);
+ case VM_REG_GUEST_RCX:
+ return (&vmxctx->guest_rcx);
+ case VM_REG_GUEST_RDX:
+ return (&vmxctx->guest_rdx);
+ case VM_REG_GUEST_RSI:
+ return (&vmxctx->guest_rsi);
+ case VM_REG_GUEST_RDI:
+ return (&vmxctx->guest_rdi);
+ case VM_REG_GUEST_RBP:
+ return (&vmxctx->guest_rbp);
+ case VM_REG_GUEST_R8:
+ return (&vmxctx->guest_r8);
+ case VM_REG_GUEST_R9:
+ return (&vmxctx->guest_r9);
+ case VM_REG_GUEST_R10:
+ return (&vmxctx->guest_r10);
+ case VM_REG_GUEST_R11:
+ return (&vmxctx->guest_r11);
+ case VM_REG_GUEST_R12:
+ return (&vmxctx->guest_r12);
+ case VM_REG_GUEST_R13:
+ return (&vmxctx->guest_r13);
+ case VM_REG_GUEST_R14:
+ return (&vmxctx->guest_r14);
+ case VM_REG_GUEST_R15:
+ return (&vmxctx->guest_r15);
+ default:
+ break;
+ }
+ return (NULL);
+}
+
+static int
+vmxctx_getreg(struct vmxctx *vmxctx, int reg, uint64_t *retval)
+{
+ register_t *regp;
+
+ if ((regp = vmxctx_regptr(vmxctx, reg)) != NULL) {
+ *retval = *regp;
+ return (0);
+ } else
+ return (EINVAL);
+}
+
+static int
+vmxctx_setreg(struct vmxctx *vmxctx, int reg, uint64_t val)
+{
+ register_t *regp;
+
+ if ((regp = vmxctx_regptr(vmxctx, reg)) != NULL) {
+ *regp = val;
+ return (0);
+ } else
+ return (EINVAL);
+}
+
+static int
+vmx_getreg(void *arg, int vcpu, int reg, uint64_t *retval)
+{
+ struct vmx *vmx = arg;
+
+ if (vmxctx_getreg(&vmx->ctx[vcpu], reg, retval) == 0)
+ return (0);
+
+ /*
+ * If the vcpu is running then don't mess with the VMCS.
+ *
+ * vmcs_getreg will VMCLEAR the vmcs when it is done which will cause
+ * the subsequent vmlaunch/vmresume to fail.
+ */
+ if (vcpu_is_running(vmx->vm, vcpu))
+ panic("vmx_getreg: %s%d is running", vm_name(vmx->vm), vcpu);
+
+ return (vmcs_getreg(&vmx->vmcs[vcpu], reg, retval));
+}
+
+static int
+vmx_setreg(void *arg, int vcpu, int reg, uint64_t val)
+{
+ int error;
+ uint64_t ctls;
+ struct vmx *vmx = arg;
+
+ /*
+ * XXX Allow caller to set contents of the guest registers saved in
+ * the 'vmxctx' even though the vcpu might be running. We need this
+ * specifically to support the rdmsr emulation that will set the
+ * %eax and %edx registers during vm exit processing.
+ */
+ if (vmxctx_setreg(&vmx->ctx[vcpu], reg, val) == 0)
+ return (0);
+
+ /*
+ * If the vcpu is running then don't mess with the VMCS.
+ *
+ * vmcs_setreg will VMCLEAR the vmcs when it is done which will cause
+ * the subsequent vmlaunch/vmresume to fail.
+ */
+ if (vcpu_is_running(vmx->vm, vcpu))
+ panic("vmx_setreg: %s%d is running", vm_name(vmx->vm), vcpu);
+
+ error = vmcs_setreg(&vmx->vmcs[vcpu], reg, val);
+
+ if (error == 0) {
+ /*
+ * If the "load EFER" VM-entry control is 1 then the
+ * value of EFER.LMA must be identical to "IA-32e mode guest"
+ * bit in the VM-entry control.
+ */
+ if ((entry_ctls & VM_ENTRY_LOAD_EFER) != 0 &&
+ (reg == VM_REG_GUEST_EFER)) {
+ vmcs_getreg(&vmx->vmcs[vcpu],
+ VMCS_IDENT(VMCS_ENTRY_CTLS), &ctls);
+ if (val & EFER_LMA)
+ ctls |= VM_ENTRY_GUEST_LMA;
+ else
+ ctls &= ~VM_ENTRY_GUEST_LMA;
+ vmcs_setreg(&vmx->vmcs[vcpu],
+ VMCS_IDENT(VMCS_ENTRY_CTLS), ctls);
+ }
+ }
+
+ return (error);
+}
+
+static int
+vmx_getdesc(void *arg, int vcpu, int reg, struct seg_desc *desc)
+{
+ struct vmx *vmx = arg;
+
+ return (vmcs_getdesc(&vmx->vmcs[vcpu], reg, desc));
+}
+
+static int
+vmx_setdesc(void *arg, int vcpu, int reg, struct seg_desc *desc)
+{
+ struct vmx *vmx = arg;
+
+ return (vmcs_setdesc(&vmx->vmcs[vcpu], reg, desc));
+}
+
+static int
+vmx_inject(void *arg, int vcpu, int type, int vector, uint32_t code,
+ int code_valid)
+{
+ int error;
+ uint64_t info;
+ struct vmx *vmx = arg;
+ struct vmcs *vmcs = &vmx->vmcs[vcpu];
+
+ static uint32_t type_map[VM_EVENT_MAX] = {
+ 0x1, /* VM_EVENT_NONE */
+ 0x0, /* VM_HW_INTR */
+ 0x2, /* VM_NMI */
+ 0x3, /* VM_HW_EXCEPTION */
+ 0x4, /* VM_SW_INTR */
+ 0x5, /* VM_PRIV_SW_EXCEPTION */
+ 0x6, /* VM_SW_EXCEPTION */
+ };
+
+ /*
+ * If there is already an exception pending to be delivered to the
+ * vcpu then just return.
+ */
+ error = vmcs_getreg(vmcs, VMCS_IDENT(VMCS_ENTRY_INTR_INFO), &info);
+ if (error)
+ return (error);
+
+ if (info & VMCS_INTERRUPTION_INFO_VALID)
+ return (EAGAIN);
+
+ info = vector | (type_map[type] << 8) | (code_valid ? 1 << 11 : 0);
+ info |= VMCS_INTERRUPTION_INFO_VALID;
+ error = vmcs_setreg(vmcs, VMCS_IDENT(VMCS_ENTRY_INTR_INFO), info);
+ if (error != 0)
+ return (error);
+
+ if (code_valid) {
+ error = vmcs_setreg(vmcs,
+ VMCS_IDENT(VMCS_ENTRY_EXCEPTION_ERROR),
+ code);
+ }
+ return (error);
+}
+
+static int
+vmx_getcap(void *arg, int vcpu, int type, int *retval)
+{
+ struct vmx *vmx = arg;
+ int vcap;
+ int ret;
+
+ ret = ENOENT;
+
+ vcap = vmx->cap[vcpu].set;
+
+ switch (type) {
+ case VM_CAP_HALT_EXIT:
+ if (cap_halt_exit)
+ ret = 0;
+ break;
+ case VM_CAP_PAUSE_EXIT:
+ if (cap_pause_exit)
+ ret = 0;
+ break;
+ case VM_CAP_MTRAP_EXIT:
+ if (cap_monitor_trap)
+ ret = 0;
+ break;
+ case VM_CAP_UNRESTRICTED_GUEST:
+ if (cap_unrestricted_guest)
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+
+ if (ret == 0)
+ *retval = (vcap & (1 << type)) ? 1 : 0;
+
+ return (ret);
+}
+
+static int
+vmx_setcap(void *arg, int vcpu, int type, int val)
+{
+ struct vmx *vmx = arg;
+ struct vmcs *vmcs = &vmx->vmcs[vcpu];
+ uint32_t baseval;
+ uint32_t *pptr;
+ int error;
+ int flag;
+ int reg;
+ int retval;
+
+ retval = ENOENT;
+ pptr = NULL;
+
+ switch (type) {
+ case VM_CAP_HALT_EXIT:
+ if (cap_halt_exit) {
+ retval = 0;
+ pptr = &vmx->cap[vcpu].proc_ctls;
+ baseval = *pptr;
+ flag = PROCBASED_HLT_EXITING;
+ reg = VMCS_PRI_PROC_BASED_CTLS;
+ }
+ break;
+ case VM_CAP_MTRAP_EXIT:
+ if (cap_monitor_trap) {
+ retval = 0;
+ pptr = &vmx->cap[vcpu].proc_ctls;
+ baseval = *pptr;
+ flag = PROCBASED_MTF;
+ reg = VMCS_PRI_PROC_BASED_CTLS;
+ }
+ break;
+ case VM_CAP_PAUSE_EXIT:
+ if (cap_pause_exit) {
+ retval = 0;
+ pptr = &vmx->cap[vcpu].proc_ctls;
+ baseval = *pptr;
+ flag = PROCBASED_PAUSE_EXITING;
+ reg = VMCS_PRI_PROC_BASED_CTLS;
+ }
+ break;
+ case VM_CAP_UNRESTRICTED_GUEST:
+ if (cap_unrestricted_guest) {
+ retval = 0;
+ baseval = procbased_ctls2;
+ flag = PROCBASED2_UNRESTRICTED_GUEST;
+ reg = VMCS_SEC_PROC_BASED_CTLS;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (retval == 0) {
+ if (val) {
+ baseval |= flag;
+ } else {
+ baseval &= ~flag;
+ }
+ VMPTRLD(vmcs);
+ error = vmwrite(reg, baseval);
+ VMCLEAR(vmcs);
+
+ if (error) {
+ retval = error;
+ } else {
+ /*
+ * Update optional stored flags, and record
+ * setting
+ */
+ if (pptr != NULL) {
+ *pptr = baseval;
+ }
+
+ if (val) {
+ vmx->cap[vcpu].set |= (1 << type);
+ } else {
+ vmx->cap[vcpu].set &= ~(1 << type);
+ }
+ }
+ }
+
+ return (retval);
+}
+
+struct vmm_ops vmm_ops_intel = {
+ vmx_init,
+ vmx_cleanup,
+ vmx_vminit,
+ vmx_run,
+ vmx_vmcleanup,
+ ept_vmmmap_set,
+ ept_vmmmap_get,
+ vmx_getreg,
+ vmx_setreg,
+ vmx_getdesc,
+ vmx_setdesc,
+ vmx_inject,
+ vmx_getcap,
+ vmx_setcap
+};
diff --git a/sys/amd64/vmm/intel/vmx.h b/sys/amd64/vmm/intel/vmx.h
new file mode 100644
index 0000000..c7cd567
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx.h
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMX_H_
+#define _VMX_H_
+
+#include "vmcs.h"
+
+#define GUEST_MSR_MAX_ENTRIES 64 /* arbitrary */
+
+struct vmxctx {
+ register_t tmpstk[32]; /* vmx_return() stack */
+ register_t tmpstktop;
+
+ register_t guest_rdi; /* Guest state */
+ register_t guest_rsi;
+ register_t guest_rdx;
+ register_t guest_rcx;
+ register_t guest_r8;
+ register_t guest_r9;
+ register_t guest_rax;
+ register_t guest_rbx;
+ register_t guest_rbp;
+ register_t guest_r10;
+ register_t guest_r11;
+ register_t guest_r12;
+ register_t guest_r13;
+ register_t guest_r14;
+ register_t guest_r15;
+ register_t guest_cr2;
+
+ register_t host_r15; /* Host state */
+ register_t host_r14;
+ register_t host_r13;
+ register_t host_r12;
+ register_t host_rbp;
+ register_t host_rsp;
+ register_t host_rbx;
+ register_t host_rip;
+ /*
+ * XXX todo debug registers and fpu state
+ */
+
+ int launched; /* vmcs launch state */
+ int launch_error;
+};
+
+struct vmxcap {
+ int set;
+ uint32_t proc_ctls;
+};
+
+struct vmxstate {
+ int lastcpu; /* host cpu that this 'vcpu' last ran on */
+ uint16_t vpid;
+};
+
+/* virtual machine softc */
+struct vmx {
+ pml4_entry_t pml4ept[NPML4EPG];
+ struct vmcs vmcs[VM_MAXCPU]; /* one vmcs per virtual cpu */
+ char msr_bitmap[PAGE_SIZE];
+ struct msr_entry guest_msrs[VM_MAXCPU][GUEST_MSR_MAX_ENTRIES];
+ struct vmxctx ctx[VM_MAXCPU];
+ struct vmxcap cap[VM_MAXCPU];
+ struct vmxstate state[VM_MAXCPU];
+ struct vm *vm;
+};
+CTASSERT((offsetof(struct vmx, pml4ept) & PAGE_MASK) == 0);
+CTASSERT((offsetof(struct vmx, vmcs) & PAGE_MASK) == 0);
+CTASSERT((offsetof(struct vmx, msr_bitmap) & PAGE_MASK) == 0);
+CTASSERT((offsetof(struct vmx, guest_msrs) & 15) == 0);
+
+#define VMX_RETURN_DIRECT 0
+#define VMX_RETURN_LONGJMP 1
+#define VMX_RETURN_VMRESUME 2
+#define VMX_RETURN_VMLAUNCH 3
+#define VMX_RETURN_AST 4
+/*
+ * vmx_setjmp() returns:
+ * - 0 when it returns directly
+ * - 1 when it returns from vmx_longjmp
+ * - 2 when it returns from vmx_resume (which would only be in the error case)
+ * - 3 when it returns from vmx_launch (which would only be in the error case)
+ * - 4 when it returns from vmx_resume or vmx_launch because of AST pending
+ */
+int vmx_setjmp(struct vmxctx *ctx);
+void vmx_longjmp(void); /* returns via vmx_setjmp */
+void vmx_launch(struct vmxctx *ctx) __dead2; /* may return via vmx_setjmp */
+void vmx_resume(struct vmxctx *ctx) __dead2; /* may return via vmx_setjmp */
+
+u_long vmx_fix_cr0(u_long cr0);
+u_long vmx_fix_cr4(u_long cr4);
+
+#endif
diff --git a/sys/amd64/vmm/intel/vmx_controls.h b/sys/amd64/vmm/intel/vmx_controls.h
new file mode 100644
index 0000000..31f29f8
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_controls.h
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMX_CONTROLS_H_
+#define _VMX_CONTROLS_H_
+
+/* Pin-Based VM-Execution Controls */
+#define PINBASED_EXTINT_EXITING (1 << 0)
+#define PINBASED_NMI_EXITING (1 << 3)
+#define PINBASED_VIRTUAL_NMI (1 << 5)
+#define PINBASED_PREMPTION_TIMER (1 << 6)
+
+/* Primary Processor-Based VM-Execution Controls */
+#define PROCBASED_INT_WINDOW_EXITING (1 << 2)
+#define PROCBASED_TSC_OFFSET (1 << 3)
+#define PROCBASED_HLT_EXITING (1 << 7)
+#define PROCBASED_INVLPG_EXITING (1 << 9)
+#define PROCBASED_MWAIT_EXITING (1 << 10)
+#define PROCBASED_RDPMC_EXITING (1 << 11)
+#define PROCBASED_RDTSC_EXITING (1 << 12)
+#define PROCBASED_CR3_LOAD_EXITING (1 << 15)
+#define PROCBASED_CR3_STORE_EXITING (1 << 16)
+#define PROCBASED_CR8_LOAD_EXITING (1 << 19)
+#define PROCBASED_CR8_STORE_EXITING (1 << 20)
+#define PROCBASED_USE_TPR_SHADOW (1 << 21)
+#define PROCBASED_NMI_WINDOW_EXITING (1 << 22)
+#define PROCBASED_MOV_DR_EXITING (1 << 23)
+#define PROCBASED_IO_EXITING (1 << 24)
+#define PROCBASED_IO_BITMAPS (1 << 25)
+#define PROCBASED_MTF (1 << 27)
+#define PROCBASED_MSR_BITMAPS (1 << 28)
+#define PROCBASED_MONITOR_EXITING (1 << 29)
+#define PROCBASED_PAUSE_EXITING (1 << 30)
+#define PROCBASED_SECONDARY_CONTROLS (1 << 31)
+
+/* Secondary Processor-Based VM-Execution Controls */
+#define PROCBASED2_VIRTUALIZE_APIC (1 << 0)
+#define PROCBASED2_ENABLE_EPT (1 << 1)
+#define PROCBASED2_DESC_TABLE_EXITING (1 << 2)
+#define PROCBASED2_ENABLE_RDTSCP (1 << 3)
+#define PROCBASED2_VIRTUALIZE_X2APIC (1 << 4)
+#define PROCBASED2_ENABLE_VPID (1 << 5)
+#define PROCBASED2_WBINVD_EXITING (1 << 6)
+#define PROCBASED2_UNRESTRICTED_GUEST (1 << 7)
+#define PROCBASED2_PAUSE_LOOP_EXITING (1 << 10)
+
+/* VM Exit Controls */
+#define VM_EXIT_SAVE_DEBUG_CONTROLS (1 << 2)
+#define VM_EXIT_HOST_LMA (1 << 9)
+#define VM_EXIT_LOAD_PERF_GLOBAL_CTRL (1 << 12)
+#define VM_EXIT_ACKNOWLEDGE_INTERRUPT (1 << 15)
+#define VM_EXIT_SAVE_PAT (1 << 18)
+#define VM_EXIT_LOAD_PAT (1 << 19)
+#define VM_EXIT_SAVE_EFER (1 << 20)
+#define VM_EXIT_LOAD_EFER (1 << 21)
+#define VM_EXIT_SAVE_PREEMPTION_TIMER (1 << 22)
+
+/* VM Entry Controls */
+#define VM_ENTRY_LOAD_DEBUG_CONTROLS (1 << 2)
+#define VM_ENTRY_GUEST_LMA (1 << 9)
+#define VM_ENTRY_INTO_SMM (1 << 10)
+#define VM_ENTRY_DEACTIVATE_DUAL_MONITOR (1 << 11)
+#define VM_ENTRY_LOAD_PERF_GLOBAL_CTRL (1 << 13)
+#define VM_ENTRY_LOAD_PAT (1 << 14)
+#define VM_ENTRY_LOAD_EFER (1 << 15)
+
+#endif
diff --git a/sys/amd64/vmm/intel/vmx_cpufunc.h b/sys/amd64/vmm/intel/vmx_cpufunc.h
new file mode 100644
index 0000000..2e66443
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_cpufunc.h
@@ -0,0 +1,218 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMX_CPUFUNC_H_
+#define _VMX_CPUFUNC_H_
+
+struct vmcs;
+
+/*
+ * Section 5.2 "Conventions" from Intel Architecture Manual 2B.
+ *
+ * error
+ * VMsucceed 0
+ * VMFailInvalid 1
+ * VMFailValid 2 see also VMCS VM-Instruction Error Field
+ */
+#define VM_SUCCESS 0
+#define VM_FAIL_INVALID 1
+#define VM_FAIL_VALID 2
+#define VMX_SET_ERROR_CODE \
+ " jnc 1f;" \
+ " mov $1, %[error];" /* CF: error = 1 */ \
+ " jmp 3f;" \
+ "1: jnz 2f;" \
+ " mov $2, %[error];" /* ZF: error = 2 */ \
+ " jmp 3f;" \
+ "2: mov $0, %[error];" \
+ "3:"
+
+/* returns 0 on success and non-zero on failure */
+static __inline int
+vmxon(char *region)
+{
+ int error;
+ uint64_t addr;
+
+ addr = vtophys(region);
+ __asm __volatile("vmxon %[addr];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [addr] "m" (*(uint64_t *)&addr)
+ : "memory");
+
+ return (error);
+}
+
+/* returns 0 on success and non-zero on failure */
+static __inline int
+vmclear(struct vmcs *vmcs)
+{
+ int error;
+ uint64_t addr;
+
+ addr = vtophys(vmcs);
+ __asm __volatile("vmclear %[addr];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [addr] "m" (*(uint64_t *)&addr)
+ : "memory");
+ return (error);
+}
+
+static __inline void
+vmxoff(void)
+{
+
+ __asm __volatile("vmxoff");
+}
+
+static __inline void
+vmptrst(uint64_t *addr)
+{
+
+ __asm __volatile("vmptrst %[addr]" :: [addr]"m" (*addr) : "memory");
+}
+
+static __inline int
+vmptrld(struct vmcs *vmcs)
+{
+ int error;
+ uint64_t addr;
+
+ addr = vtophys(vmcs);
+ __asm __volatile("vmptrld %[addr];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [addr] "m" (*(uint64_t *)&addr)
+ : "memory");
+ return (error);
+}
+
+static __inline int
+vmwrite(uint64_t reg, uint64_t val)
+{
+ int error;
+
+ __asm __volatile("vmwrite %[val], %[reg];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [val] "r" (val), [reg] "r" (reg)
+ : "memory");
+
+ return (error);
+}
+
+static __inline int
+vmread(uint64_t r, uint64_t *addr)
+{
+ int error;
+
+ __asm __volatile("vmread %[r], %[addr];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [r] "r" (r), [addr] "m" (*addr)
+ : "memory");
+
+ return (error);
+}
+
+static void __inline
+VMCLEAR(struct vmcs *vmcs)
+{
+ int err;
+
+ err = vmclear(vmcs);
+ if (err != 0)
+ panic("%s: vmclear(%p) error %d", __func__, vmcs, err);
+
+ critical_exit();
+}
+
+static void __inline
+VMPTRLD(struct vmcs *vmcs)
+{
+ int err;
+
+ critical_enter();
+
+ err = vmptrld(vmcs);
+ if (err != 0)
+ panic("%s: vmptrld(%p) error %d", __func__, vmcs, err);
+}
+
+#define INVVPID_TYPE_ADDRESS 0UL
+#define INVVPID_TYPE_SINGLE_CONTEXT 1UL
+#define INVVPID_TYPE_ALL_CONTEXTS 2UL
+
+struct invvpid_desc {
+ uint16_t vpid;
+ uint16_t _res1;
+ uint32_t _res2;
+ uint64_t linear_addr;
+};
+CTASSERT(sizeof(struct invvpid_desc) == 16);
+
+static void __inline
+invvpid(uint64_t type, struct invvpid_desc desc)
+{
+ int error;
+
+ __asm __volatile("invvpid %[desc], %[type];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [desc] "m" (desc), [type] "r" (type)
+ : "memory");
+
+ if (error)
+ panic("invvpid error %d", error);
+}
+
+#define INVEPT_TYPE_SINGLE_CONTEXT 1UL
+#define INVEPT_TYPE_ALL_CONTEXTS 2UL
+struct invept_desc {
+ uint64_t eptp;
+ uint64_t _res;
+};
+CTASSERT(sizeof(struct invept_desc) == 16);
+
+static void __inline
+invept(uint64_t type, struct invept_desc desc)
+{
+ int error;
+
+ __asm __volatile("invept %[desc], %[type];"
+ VMX_SET_ERROR_CODE
+ : [error] "=r" (error)
+ : [desc] "m" (desc), [type] "r" (type)
+ : "memory");
+
+ if (error)
+ panic("invept error %d", error);
+}
+#endif
diff --git a/sys/amd64/vmm/intel/vmx_genassym.c b/sys/amd64/vmm/intel/vmx_genassym.c
new file mode 100644
index 0000000..823a05d
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_genassym.c
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/assym.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pmap.h>
+
+#include <machine/vmm.h>
+#include "vmx.h"
+#include "vmx_cpufunc.h"
+
+ASSYM(VMXCTX_TMPSTKTOP, offsetof(struct vmxctx, tmpstktop));
+ASSYM(VMXCTX_GUEST_RDI, offsetof(struct vmxctx, guest_rdi));
+ASSYM(VMXCTX_GUEST_RSI, offsetof(struct vmxctx, guest_rsi));
+ASSYM(VMXCTX_GUEST_RDX, offsetof(struct vmxctx, guest_rdx));
+ASSYM(VMXCTX_GUEST_RCX, offsetof(struct vmxctx, guest_rcx));
+ASSYM(VMXCTX_GUEST_R8, offsetof(struct vmxctx, guest_r8));
+ASSYM(VMXCTX_GUEST_R9, offsetof(struct vmxctx, guest_r9));
+ASSYM(VMXCTX_GUEST_RAX, offsetof(struct vmxctx, guest_rax));
+ASSYM(VMXCTX_GUEST_RBX, offsetof(struct vmxctx, guest_rbx));
+ASSYM(VMXCTX_GUEST_RBP, offsetof(struct vmxctx, guest_rbp));
+ASSYM(VMXCTX_GUEST_R10, offsetof(struct vmxctx, guest_r10));
+ASSYM(VMXCTX_GUEST_R11, offsetof(struct vmxctx, guest_r11));
+ASSYM(VMXCTX_GUEST_R12, offsetof(struct vmxctx, guest_r12));
+ASSYM(VMXCTX_GUEST_R13, offsetof(struct vmxctx, guest_r13));
+ASSYM(VMXCTX_GUEST_R14, offsetof(struct vmxctx, guest_r14));
+ASSYM(VMXCTX_GUEST_R15, offsetof(struct vmxctx, guest_r15));
+ASSYM(VMXCTX_GUEST_CR2, offsetof(struct vmxctx, guest_cr2));
+
+ASSYM(VMXCTX_HOST_R15, offsetof(struct vmxctx, host_r15));
+ASSYM(VMXCTX_HOST_R14, offsetof(struct vmxctx, host_r14));
+ASSYM(VMXCTX_HOST_R13, offsetof(struct vmxctx, host_r13));
+ASSYM(VMXCTX_HOST_R12, offsetof(struct vmxctx, host_r12));
+ASSYM(VMXCTX_HOST_RBP, offsetof(struct vmxctx, host_rbp));
+ASSYM(VMXCTX_HOST_RSP, offsetof(struct vmxctx, host_rsp));
+ASSYM(VMXCTX_HOST_RBX, offsetof(struct vmxctx, host_rbx));
+ASSYM(VMXCTX_HOST_RIP, offsetof(struct vmxctx, host_rip));
+
+ASSYM(VMXCTX_LAUNCH_ERROR, offsetof(struct vmxctx, launch_error));
+
+ASSYM(VM_SUCCESS, VM_SUCCESS);
+ASSYM(VM_FAIL_INVALID, VM_FAIL_INVALID);
+ASSYM(VM_FAIL_VALID, VM_FAIL_VALID);
+
+ASSYM(VMX_RETURN_DIRECT, VMX_RETURN_DIRECT);
+ASSYM(VMX_RETURN_LONGJMP, VMX_RETURN_LONGJMP);
+ASSYM(VMX_RETURN_VMRESUME, VMX_RETURN_VMRESUME);
+ASSYM(VMX_RETURN_VMLAUNCH, VMX_RETURN_VMLAUNCH);
+ASSYM(VMX_RETURN_AST, VMX_RETURN_AST);
+
+ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
+ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
+ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
+ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
diff --git a/sys/amd64/vmm/intel/vmx_msr.c b/sys/amd64/vmm/intel/vmx_msr.c
new file mode 100644
index 0000000..2aba63c
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_msr.c
@@ -0,0 +1,172 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/cpufunc.h>
+
+#include "vmx_msr.h"
+
+static boolean_t
+vmx_ctl_allows_one_setting(uint64_t msr_val, int bitpos)
+{
+
+ if (msr_val & (1UL << (bitpos + 32)))
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+static boolean_t
+vmx_ctl_allows_zero_setting(uint64_t msr_val, int bitpos)
+{
+
+ if ((msr_val & (1UL << bitpos)) == 0)
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+uint32_t
+vmx_revision(void)
+{
+
+ return (rdmsr(MSR_VMX_BASIC) & 0xffffffff);
+}
+
+/*
+ * Generate a bitmask to be used for the VMCS execution control fields.
+ *
+ * The caller specifies what bits should be set to one in 'ones_mask'
+ * and what bits should be set to zero in 'zeros_mask'. The don't-care
+ * bits are set to the default value. The default values are obtained
+ * based on "Algorithm 3" in Section 27.5.1 "Algorithms for Determining
+ * VMX Capabilities".
+ *
+ * Returns zero on success and non-zero on error.
+ */
+int
+vmx_set_ctlreg(int ctl_reg, int true_ctl_reg, uint32_t ones_mask,
+ uint32_t zeros_mask, uint32_t *retval)
+{
+ int i;
+ uint64_t val, trueval;
+ boolean_t true_ctls_avail, one_allowed, zero_allowed;
+
+ /* We cannot ask the same bit to be set to both '1' and '0' */
+ if ((ones_mask ^ zeros_mask) != (ones_mask | zeros_mask))
+ return (EINVAL);
+
+ if (rdmsr(MSR_VMX_BASIC) & (1UL << 55))
+ true_ctls_avail = TRUE;
+ else
+ true_ctls_avail = FALSE;
+
+ val = rdmsr(ctl_reg);
+ if (true_ctls_avail)
+ trueval = rdmsr(true_ctl_reg); /* step c */
+ else
+ trueval = val; /* step a */
+
+ for (i = 0; i < 32; i++) {
+ one_allowed = vmx_ctl_allows_one_setting(trueval, i);
+ zero_allowed = vmx_ctl_allows_zero_setting(trueval, i);
+
+ KASSERT(one_allowed || zero_allowed,
+ ("invalid zero/one setting for bit %d of ctl 0x%0x, "
+ "truectl 0x%0x\n", i, ctl_reg, true_ctl_reg));
+
+ if (zero_allowed && !one_allowed) { /* b(i),c(i) */
+ if (ones_mask & (1 << i))
+ return (EINVAL);
+ *retval &= ~(1 << i);
+ } else if (one_allowed && !zero_allowed) { /* b(i),c(i) */
+ if (zeros_mask & (1 << i))
+ return (EINVAL);
+ *retval |= 1 << i;
+ } else {
+ if (zeros_mask & (1 << i)) /* b(ii),c(ii) */
+ *retval &= ~(1 << i);
+ else if (ones_mask & (1 << i)) /* b(ii), c(ii) */
+ *retval |= 1 << i;
+ else if (!true_ctls_avail)
+ *retval &= ~(1 << i); /* b(iii) */
+ else if (vmx_ctl_allows_zero_setting(val, i))/* c(iii)*/
+ *retval &= ~(1 << i);
+ else if (vmx_ctl_allows_one_setting(val, i)) /* c(iv) */
+ *retval |= 1 << i;
+ else {
+ panic("vmx_set_ctlreg: unable to determine "
+ "correct value of ctl bit %d for msr "
+ "0x%0x and true msr 0x%0x", i, ctl_reg,
+ true_ctl_reg);
+ }
+ }
+ }
+
+ return (0);
+}
+
+void
+msr_bitmap_initialize(char *bitmap)
+{
+
+ memset(bitmap, 0xff, PAGE_SIZE);
+}
+
+int
+msr_bitmap_change_access(char *bitmap, u_int msr, int access)
+{
+ int byte, bit;
+
+ if (msr <= 0x00001FFF)
+ byte = msr / 8;
+ else if (msr >= 0xC0000000 && msr <= 0xC0001FFF)
+ byte = 1024 + (msr - 0xC0000000) / 8;
+ else
+ return (EINVAL);
+
+ bit = msr & 0x7;
+
+ if (access & MSR_BITMAP_ACCESS_READ)
+ bitmap[byte] &= ~(1 << bit);
+ else
+ bitmap[byte] |= 1 << bit;
+
+ byte += 2048;
+ if (access & MSR_BITMAP_ACCESS_WRITE)
+ bitmap[byte] &= ~(1 << bit);
+ else
+ bitmap[byte] |= 1 << bit;
+
+ return (0);
+}
diff --git a/sys/amd64/vmm/intel/vmx_msr.h b/sys/amd64/vmm/intel/vmx_msr.h
new file mode 100644
index 0000000..e6379a9
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_msr.h
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMX_MSR_H_
+#define _VMX_MSR_H_
+
+#define MSR_VMX_BASIC 0x480
+#define MSR_VMX_EPT_VPID_CAP 0x48C
+
+#define MSR_VMX_PROCBASED_CTLS 0x482
+#define MSR_VMX_TRUE_PROCBASED_CTLS 0x48E
+
+#define MSR_VMX_PINBASED_CTLS 0x481
+#define MSR_VMX_TRUE_PINBASED_CTLS 0x48D
+
+#define MSR_VMX_PROCBASED_CTLS2 0x48B
+
+#define MSR_VMX_EXIT_CTLS 0x483
+#define MSR_VMX_TRUE_EXIT_CTLS 0x48f
+
+#define MSR_VMX_ENTRY_CTLS 0x484
+#define MSR_VMX_TRUE_ENTRY_CTLS 0x490
+
+#define MSR_VMX_CR0_FIXED0 0x486
+#define MSR_VMX_CR0_FIXED1 0x487
+
+#define MSR_VMX_CR4_FIXED0 0x488
+#define MSR_VMX_CR4_FIXED1 0x489
+
+uint32_t vmx_revision(void);
+
+int vmx_set_ctlreg(int ctl_reg, int true_ctl_reg, uint32_t ones_mask,
+ uint32_t zeros_mask, uint32_t *retval);
+
+/*
+ * According to Section 21.10.4 "Software Access to Related Structures",
+ * changes to data structures pointed to by the VMCS must be made only when
+ * there is no logical processor with a current VMCS that points to the
+ * data structure.
+ *
+ * This pretty much limits us to configuring the MSR bitmap before VMCS
+ * initialization for SMP VMs. Unless of course we do it the hard way - which
+ * would involve some form of synchronization between the vcpus to vmclear
+ * all VMCSs' that point to the bitmap.
+ */
+#define MSR_BITMAP_ACCESS_NONE 0x0
+#define MSR_BITMAP_ACCESS_READ 0x1
+#define MSR_BITMAP_ACCESS_WRITE 0x2
+#define MSR_BITMAP_ACCESS_RW (MSR_BITMAP_ACCESS_READ|MSR_BITMAP_ACCESS_WRITE)
+void msr_bitmap_initialize(char *bitmap);
+int msr_bitmap_change_access(char *bitmap, u_int msr, int access);
+
+#endif
diff --git a/sys/amd64/vmm/intel/vmx_support.S b/sys/amd64/vmm/intel/vmx_support.S
new file mode 100644
index 0000000..4ba582a
--- /dev/null
+++ b/sys/amd64/vmm/intel/vmx_support.S
@@ -0,0 +1,246 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asmacros.h>
+
+#include "vmx_assym.s"
+
+/*
+ * Disable interrupts before updating %rsp in VMX_CHECK_AST or
+ * VMX_GUEST_RESTORE.
+ *
+ * The location that %rsp points to is a 'vmxctx' and not a
+ * real stack so we don't want an interrupt handler to trash it
+ */
+#define VMX_DISABLE_INTERRUPTS cli
+
+/*
+ * If the thread hosting the vcpu has an ast pending then take care of it
+ * by returning from vmx_setjmp() with a return value of VMX_RETURN_AST.
+ *
+ * Assumes that %rdi holds a pointer to the 'vmxctx' and that interrupts
+ * are disabled.
+ */
+#define VMX_CHECK_AST \
+ movq PCPU(CURTHREAD),%rax; \
+ testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax); \
+ je 9f; \
+ movq $VMX_RETURN_AST,%rsi; \
+ movq %rdi,%rsp; \
+ addq $VMXCTX_TMPSTKTOP,%rsp; \
+ callq vmx_return; \
+9:
+
+/*
+ * Assumes that %rdi holds a pointer to the 'vmxctx'.
+ *
+ * On "return" all registers are updated to reflect guest state. The two
+ * exceptions are %rip and %rsp. These registers are atomically switched
+ * by hardware from the guest area of the vmcs.
+ *
+ * We modify %rsp to point to the 'vmxctx' so we can use it to restore
+ * host context in case of an error with 'vmlaunch' or 'vmresume'.
+ */
+#define VMX_GUEST_RESTORE \
+ movq %rdi,%rsp; \
+ movq VMXCTX_GUEST_CR2(%rdi),%rsi; \
+ movq %rsi,%cr2; \
+ movq VMXCTX_GUEST_RSI(%rdi),%rsi; \
+ movq VMXCTX_GUEST_RDX(%rdi),%rdx; \
+ movq VMXCTX_GUEST_RCX(%rdi),%rcx; \
+ movq VMXCTX_GUEST_R8(%rdi),%r8; \
+ movq VMXCTX_GUEST_R9(%rdi),%r9; \
+ movq VMXCTX_GUEST_RAX(%rdi),%rax; \
+ movq VMXCTX_GUEST_RBX(%rdi),%rbx; \
+ movq VMXCTX_GUEST_RBP(%rdi),%rbp; \
+ movq VMXCTX_GUEST_R10(%rdi),%r10; \
+ movq VMXCTX_GUEST_R11(%rdi),%r11; \
+ movq VMXCTX_GUEST_R12(%rdi),%r12; \
+ movq VMXCTX_GUEST_R13(%rdi),%r13; \
+ movq VMXCTX_GUEST_R14(%rdi),%r14; \
+ movq VMXCTX_GUEST_R15(%rdi),%r15; \
+ movq VMXCTX_GUEST_RDI(%rdi),%rdi; /* restore rdi the last */
+
+#define VM_INSTRUCTION_ERROR(reg) \
+ jnc 1f; \
+ movl $VM_FAIL_INVALID,reg; /* CF is set */ \
+ jmp 3f; \
+1: jnz 2f; \
+ movl $VM_FAIL_VALID,reg; /* ZF is set */ \
+ jmp 3f; \
+2: movl $VM_SUCCESS,reg; \
+3: movl reg,VMXCTX_LAUNCH_ERROR(%rsp)
+
+ .text
+/*
+ * int vmx_setjmp(ctxp)
+ * %rdi = ctxp
+ *
+ * Return value is '0' when it returns directly from here.
+ * Return value is '1' when it returns after a vm exit through vmx_longjmp.
+ */
+ENTRY(vmx_setjmp)
+ movq (%rsp),%rax /* return address */
+ movq %r15,VMXCTX_HOST_R15(%rdi)
+ movq %r14,VMXCTX_HOST_R14(%rdi)
+ movq %r13,VMXCTX_HOST_R13(%rdi)
+ movq %r12,VMXCTX_HOST_R12(%rdi)
+ movq %rbp,VMXCTX_HOST_RBP(%rdi)
+ movq %rsp,VMXCTX_HOST_RSP(%rdi)
+ movq %rbx,VMXCTX_HOST_RBX(%rdi)
+ movq %rax,VMXCTX_HOST_RIP(%rdi)
+
+ /*
+ * XXX save host debug registers
+ */
+ movl $VMX_RETURN_DIRECT,%eax
+ ret
+END(vmx_setjmp)
+
+/*
+ * void vmx_return(struct vmxctx *ctxp, int retval)
+ * %rdi = ctxp
+ * %rsi = retval
+ * Return to vmm context through vmx_setjmp() with a value of 'retval'.
+ */
+ENTRY(vmx_return)
+ /* Restore host context. */
+ movq VMXCTX_HOST_R15(%rdi),%r15
+ movq VMXCTX_HOST_R14(%rdi),%r14
+ movq VMXCTX_HOST_R13(%rdi),%r13
+ movq VMXCTX_HOST_R12(%rdi),%r12
+ movq VMXCTX_HOST_RBP(%rdi),%rbp
+ movq VMXCTX_HOST_RSP(%rdi),%rsp
+ movq VMXCTX_HOST_RBX(%rdi),%rbx
+ movq VMXCTX_HOST_RIP(%rdi),%rax
+ movq %rax,(%rsp) /* return address */
+
+ /*
+ * XXX restore host debug registers
+ */
+ movl %esi,%eax
+ ret
+END(vmx_return)
+
+/*
+ * void vmx_longjmp(void)
+ * %rsp points to the struct vmxctx
+ */
+ENTRY(vmx_longjmp)
+ /*
+ * Save guest state that is not automatically saved in the vmcs.
+ */
+ movq %rdi,VMXCTX_GUEST_RDI(%rsp)
+ movq %rsi,VMXCTX_GUEST_RSI(%rsp)
+ movq %rdx,VMXCTX_GUEST_RDX(%rsp)
+ movq %rcx,VMXCTX_GUEST_RCX(%rsp)
+ movq %r8,VMXCTX_GUEST_R8(%rsp)
+ movq %r9,VMXCTX_GUEST_R9(%rsp)
+ movq %rax,VMXCTX_GUEST_RAX(%rsp)
+ movq %rbx,VMXCTX_GUEST_RBX(%rsp)
+ movq %rbp,VMXCTX_GUEST_RBP(%rsp)
+ movq %r10,VMXCTX_GUEST_R10(%rsp)
+ movq %r11,VMXCTX_GUEST_R11(%rsp)
+ movq %r12,VMXCTX_GUEST_R12(%rsp)
+ movq %r13,VMXCTX_GUEST_R13(%rsp)
+ movq %r14,VMXCTX_GUEST_R14(%rsp)
+ movq %r15,VMXCTX_GUEST_R15(%rsp)
+
+ movq %cr2,%rdi
+ movq %rdi,VMXCTX_GUEST_CR2(%rsp)
+
+ movq %rsp,%rdi
+ movq $VMX_RETURN_LONGJMP,%rsi
+
+ addq $VMXCTX_TMPSTKTOP,%rsp
+ callq vmx_return
+END(vmx_longjmp)
+
+/*
+ * void vmx_resume(struct vmxctx *ctxp)
+ * %rdi = ctxp
+ *
+ * Although the return type is a 'void' this function may return indirectly
+ * through vmx_setjmp() with a return value of 2.
+ */
+ENTRY(vmx_resume)
+ VMX_DISABLE_INTERRUPTS
+
+ VMX_CHECK_AST
+
+ /*
+ * Restore guest state that is not automatically loaded from the vmcs.
+ */
+ VMX_GUEST_RESTORE
+
+ vmresume
+
+ /*
+ * Capture the reason why vmresume failed.
+ */
+ VM_INSTRUCTION_ERROR(%eax)
+
+ /* Return via vmx_setjmp with return value of VMX_RETURN_VMRESUME */
+ movq %rsp,%rdi
+ movq $VMX_RETURN_VMRESUME,%rsi
+
+ addq $VMXCTX_TMPSTKTOP,%rsp
+ callq vmx_return
+END(vmx_resume)
+
+/*
+ * void vmx_launch(struct vmxctx *ctxp)
+ * %rdi = ctxp
+ *
+ * Although the return type is a 'void' this function may return indirectly
+ * through vmx_setjmp() with a return value of 3.
+ */
+ENTRY(vmx_launch)
+ VMX_DISABLE_INTERRUPTS
+
+ VMX_CHECK_AST
+
+ /*
+ * Restore guest state that is not automatically loaded from the vmcs.
+ */
+ VMX_GUEST_RESTORE
+
+ vmlaunch
+
+ /*
+ * Capture the reason why vmlaunch failed.
+ */
+ VM_INSTRUCTION_ERROR(%eax)
+
+ /* Return via vmx_setjmp with return value of VMX_RETURN_VMLAUNCH */
+ movq %rsp,%rdi
+ movq $VMX_RETURN_VMLAUNCH,%rsi
+
+ addq $VMXCTX_TMPSTKTOP,%rsp
+ callq vmx_return
+END(vmx_launch)
diff --git a/sys/amd64/vmm/intel/vtd.c b/sys/amd64/vmm/intel/vtd.c
new file mode 100644
index 0000000..ef0e9bc
--- /dev/null
+++ b/sys/amd64/vmm/intel/vtd.c
@@ -0,0 +1,677 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/pci/pcireg.h>
+
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+#include <machine/pci_cfgreg.h>
+
+#include "io/iommu.h"
+
+/*
+ * Documented in the "Intel Virtualization Technology for Directed I/O",
+ * Architecture Spec, September 2008.
+ */
+
+/* Section 10.4 "Register Descriptions" */
+struct vtdmap {
+ volatile uint32_t version;
+ volatile uint32_t res0;
+ volatile uint64_t cap;
+ volatile uint64_t ext_cap;
+ volatile uint32_t gcr;
+ volatile uint32_t gsr;
+ volatile uint64_t rta;
+ volatile uint64_t ccr;
+};
+
+#define VTD_CAP_SAGAW(cap) (((cap) >> 8) & 0x1F)
+#define VTD_CAP_ND(cap) ((cap) & 0x7)
+#define VTD_CAP_CM(cap) (((cap) >> 7) & 0x1)
+#define VTD_CAP_SPS(cap) (((cap) >> 34) & 0xF)
+#define VTD_CAP_RWBF(cap) (((cap) >> 4) & 0x1)
+
+#define VTD_ECAP_DI(ecap) (((ecap) >> 2) & 0x1)
+#define VTD_ECAP_COHERENCY(ecap) ((ecap) & 0x1)
+#define VTD_ECAP_IRO(ecap) (((ecap) >> 8) & 0x3FF)
+
+#define VTD_GCR_WBF (1 << 27)
+#define VTD_GCR_SRTP (1 << 30)
+#define VTD_GCR_TE (1 << 31)
+
+#define VTD_GSR_WBFS (1 << 27)
+#define VTD_GSR_RTPS (1 << 30)
+#define VTD_GSR_TES (1 << 31)
+
+#define VTD_CCR_ICC (1UL << 63) /* invalidate context cache */
+#define VTD_CCR_CIRG_GLOBAL (1UL << 61) /* global invalidation */
+
+#define VTD_IIR_IVT (1UL << 63) /* invalidation IOTLB */
+#define VTD_IIR_IIRG_GLOBAL (1ULL << 60) /* global IOTLB invalidation */
+#define VTD_IIR_IIRG_DOMAIN (2ULL << 60) /* domain IOTLB invalidation */
+#define VTD_IIR_IIRG_PAGE (3ULL << 60) /* page IOTLB invalidation */
+#define VTD_IIR_DRAIN_READS (1ULL << 49) /* drain pending DMA reads */
+#define VTD_IIR_DRAIN_WRITES (1ULL << 48) /* drain pending DMA writes */
+#define VTD_IIR_DOMAIN_P 32
+
+#define VTD_ROOT_PRESENT 0x1
+#define VTD_CTX_PRESENT 0x1
+#define VTD_CTX_TT_ALL (1UL << 2)
+
+#define VTD_PTE_RD (1UL << 0)
+#define VTD_PTE_WR (1UL << 1)
+#define VTD_PTE_SUPERPAGE (1UL << 7)
+#define VTD_PTE_ADDR_M (0x000FFFFFFFFFF000UL)
+
+struct domain {
+ uint64_t *ptp; /* first level page table page */
+ int pt_levels; /* number of page table levels */
+ int addrwidth; /* 'AW' field in context entry */
+ int spsmask; /* supported super page sizes */
+ u_int id; /* domain id */
+ vm_paddr_t maxaddr; /* highest address to be mapped */
+ SLIST_ENTRY(domain) next;
+};
+
+static SLIST_HEAD(, domain) domhead;
+
+#define DRHD_MAX_UNITS 8
+static int drhd_num;
+static struct vtdmap *vtdmaps[DRHD_MAX_UNITS];
+static int max_domains;
+typedef int (*drhd_ident_func_t)(void);
+
+static uint64_t root_table[PAGE_SIZE / sizeof(uint64_t)] __aligned(4096);
+static uint64_t ctx_tables[256][PAGE_SIZE / sizeof(uint64_t)] __aligned(4096);
+
+static MALLOC_DEFINE(M_VTD, "vtd", "vtd");
+
+/*
+ * Config space register definitions from the "Intel 5520 and 5500" datasheet.
+ */
+static int
+tylersburg_vtd_ident(void)
+{
+ int units, nlbus;
+ uint16_t did, vid;
+ uint32_t miscsts, vtbar;
+
+ const int bus = 0;
+ const int slot = 20;
+ const int func = 0;
+
+ units = 0;
+
+ vid = pci_cfgregread(bus, slot, func, PCIR_VENDOR, 2);
+ did = pci_cfgregread(bus, slot, func, PCIR_DEVICE, 2);
+ if (vid != 0x8086 || did != 0x342E)
+ goto done;
+
+ /*
+ * Check if this is a dual IOH configuration.
+ */
+ miscsts = pci_cfgregread(bus, slot, func, 0x9C, 4);
+ if (miscsts & (1 << 25))
+ nlbus = pci_cfgregread(bus, slot, func, 0x160, 1);
+ else
+ nlbus = -1;
+
+ vtbar = pci_cfgregread(bus, slot, func, 0x180, 4);
+ if (vtbar & 0x1) {
+ vtdmaps[units++] = (struct vtdmap *)
+ PHYS_TO_DMAP(vtbar & 0xffffe000);
+ } else if (bootverbose)
+ printf("VT-d unit in legacy IOH is disabled!\n");
+
+ if (nlbus != -1) {
+ vtbar = pci_cfgregread(nlbus, slot, func, 0x180, 4);
+ if (vtbar & 0x1) {
+ vtdmaps[units++] = (struct vtdmap *)
+ PHYS_TO_DMAP(vtbar & 0xffffe000);
+ } else if (bootverbose)
+ printf("VT-d unit in non-legacy IOH is disabled!\n");
+ }
+done:
+ return (units);
+}
+
+static drhd_ident_func_t drhd_ident_funcs[] = {
+ tylersburg_vtd_ident,
+ NULL
+};
+
+static int
+vtd_max_domains(struct vtdmap *vtdmap)
+{
+ int nd;
+
+ nd = VTD_CAP_ND(vtdmap->cap);
+
+ switch (nd) {
+ case 0:
+ return (16);
+ case 1:
+ return (64);
+ case 2:
+ return (256);
+ case 3:
+ return (1024);
+ case 4:
+ return (4 * 1024);
+ case 5:
+ return (16 * 1024);
+ case 6:
+ return (64 * 1024);
+ default:
+ panic("vtd_max_domains: invalid value of nd (0x%0x)", nd);
+ }
+}
+
+static u_int
+domain_id(void)
+{
+ u_int id;
+ struct domain *dom;
+
+ /* Skip domain id 0 - it is reserved when Caching Mode field is set */
+ for (id = 1; id < max_domains; id++) {
+ SLIST_FOREACH(dom, &domhead, next) {
+ if (dom->id == id)
+ break;
+ }
+ if (dom == NULL)
+ break; /* found it */
+ }
+
+ if (id >= max_domains)
+ panic("domain ids exhausted");
+
+ return (id);
+}
+
+static void
+vtd_wbflush(struct vtdmap *vtdmap)
+{
+
+ if (VTD_ECAP_COHERENCY(vtdmap->ext_cap) == 0)
+ pmap_invalidate_cache();
+
+ if (VTD_CAP_RWBF(vtdmap->cap)) {
+ vtdmap->gcr = VTD_GCR_WBF;
+ while ((vtdmap->gsr & VTD_GSR_WBFS) != 0)
+ ;
+ }
+}
+
+static void
+vtd_ctx_global_invalidate(struct vtdmap *vtdmap)
+{
+
+ vtdmap->ccr = VTD_CCR_ICC | VTD_CCR_CIRG_GLOBAL;
+ while ((vtdmap->ccr & VTD_CCR_ICC) != 0)
+ ;
+}
+
+static void
+vtd_iotlb_global_invalidate(struct vtdmap *vtdmap)
+{
+ int offset;
+ volatile uint64_t *iotlb_reg, val;
+
+ vtd_wbflush(vtdmap);
+
+ offset = VTD_ECAP_IRO(vtdmap->ext_cap) * 16;
+ iotlb_reg = (volatile uint64_t *)((caddr_t)vtdmap + offset + 8);
+
+ *iotlb_reg = VTD_IIR_IVT | VTD_IIR_IIRG_GLOBAL |
+ VTD_IIR_DRAIN_READS | VTD_IIR_DRAIN_WRITES;
+
+ while (1) {
+ val = *iotlb_reg;
+ if ((val & VTD_IIR_IVT) == 0)
+ break;
+ }
+}
+
+static void
+vtd_translation_enable(struct vtdmap *vtdmap)
+{
+
+ vtdmap->gcr = VTD_GCR_TE;
+ while ((vtdmap->gsr & VTD_GSR_TES) == 0)
+ ;
+}
+
+static void
+vtd_translation_disable(struct vtdmap *vtdmap)
+{
+
+ vtdmap->gcr = 0;
+ while ((vtdmap->gsr & VTD_GSR_TES) != 0)
+ ;
+}
+
+static int
+vtd_init(void)
+{
+ int i, units;
+ struct vtdmap *vtdmap;
+ vm_paddr_t ctx_paddr;
+
+ for (i = 0; drhd_ident_funcs[i] != NULL; i++) {
+ units = (*drhd_ident_funcs[i])();
+ if (units > 0)
+ break;
+ }
+
+ if (units <= 0)
+ return (ENXIO);
+
+ drhd_num = units;
+ vtdmap = vtdmaps[0];
+
+ if (VTD_CAP_CM(vtdmap->cap) != 0)
+ panic("vtd_init: invalid caching mode");
+
+ max_domains = vtd_max_domains(vtdmap);
+
+ /*
+ * Set up the root-table to point to the context-entry tables
+ */
+ for (i = 0; i < 256; i++) {
+ ctx_paddr = vtophys(ctx_tables[i]);
+ if (ctx_paddr & PAGE_MASK)
+ panic("ctx table (0x%0lx) not page aligned", ctx_paddr);
+
+ root_table[i * 2] = ctx_paddr | VTD_ROOT_PRESENT;
+ }
+
+ return (0);
+}
+
+static void
+vtd_cleanup(void)
+{
+}
+
+static void
+vtd_enable(void)
+{
+ int i;
+ struct vtdmap *vtdmap;
+
+ for (i = 0; i < drhd_num; i++) {
+ vtdmap = vtdmaps[i];
+ vtd_wbflush(vtdmap);
+
+ /* Update the root table address */
+ vtdmap->rta = vtophys(root_table);
+ vtdmap->gcr = VTD_GCR_SRTP;
+ while ((vtdmap->gsr & VTD_GSR_RTPS) == 0)
+ ;
+
+ vtd_ctx_global_invalidate(vtdmap);
+ vtd_iotlb_global_invalidate(vtdmap);
+
+ vtd_translation_enable(vtdmap);
+ }
+}
+
+static void
+vtd_disable(void)
+{
+ int i;
+ struct vtdmap *vtdmap;
+
+ for (i = 0; i < drhd_num; i++) {
+ vtdmap = vtdmaps[i];
+ vtd_translation_disable(vtdmap);
+ }
+}
+
+static void
+vtd_add_device(void *arg, int bus, int slot, int func)
+{
+ int idx;
+ uint64_t *ctxp;
+ struct domain *dom = arg;
+ vm_paddr_t pt_paddr;
+ struct vtdmap *vtdmap;
+
+ if (bus < 0 || bus > PCI_BUSMAX ||
+ slot < 0 || slot > PCI_SLOTMAX ||
+ func < 0 || func > PCI_FUNCMAX)
+ panic("vtd_add_device: invalid bsf %d/%d/%d", bus, slot, func);
+
+ vtdmap = vtdmaps[0];
+ ctxp = ctx_tables[bus];
+ pt_paddr = vtophys(dom->ptp);
+ idx = (slot << 3 | func) * 2;
+
+ if (ctxp[idx] & VTD_CTX_PRESENT) {
+ panic("vtd_add_device: device %d/%d/%d is already owned by "
+ "domain %d", bus, slot, func,
+ (uint16_t)(ctxp[idx + 1] >> 8));
+ }
+
+ /*
+ * Order is important. The 'present' bit is set only after all fields
+ * of the context pointer are initialized.
+ */
+ ctxp[idx + 1] = dom->addrwidth | (dom->id << 8);
+
+ if (VTD_ECAP_DI(vtdmap->ext_cap))
+ ctxp[idx] = VTD_CTX_TT_ALL;
+ else
+ ctxp[idx] = 0;
+
+ ctxp[idx] |= pt_paddr | VTD_CTX_PRESENT;
+
+ /*
+ * 'Not Present' entries are not cached in either the Context Cache
+ * or in the IOTLB, so there is no need to invalidate either of them.
+ */
+}
+
+static void
+vtd_remove_device(void *arg, int bus, int slot, int func)
+{
+ int i, idx;
+ uint64_t *ctxp;
+ struct vtdmap *vtdmap;
+
+ if (bus < 0 || bus > PCI_BUSMAX ||
+ slot < 0 || slot > PCI_SLOTMAX ||
+ func < 0 || func > PCI_FUNCMAX)
+ panic("vtd_add_device: invalid bsf %d/%d/%d", bus, slot, func);
+
+ ctxp = ctx_tables[bus];
+ idx = (slot << 3 | func) * 2;
+
+ /*
+ * Order is important. The 'present' bit is must be cleared first.
+ */
+ ctxp[idx] = 0;
+ ctxp[idx + 1] = 0;
+
+ /*
+ * Invalidate the Context Cache and the IOTLB.
+ *
+ * XXX use device-selective invalidation for Context Cache
+ * XXX use domain-selective invalidation for IOTLB
+ */
+ for (i = 0; i < drhd_num; i++) {
+ vtdmap = vtdmaps[i];
+ vtd_ctx_global_invalidate(vtdmap);
+ vtd_iotlb_global_invalidate(vtdmap);
+ }
+}
+
+#define CREATE_MAPPING 0
+#define REMOVE_MAPPING 1
+
+static uint64_t
+vtd_update_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len,
+ int remove)
+{
+ struct domain *dom;
+ int i, spshift, ptpshift, ptpindex, nlevels;
+ uint64_t spsize, *ptp;
+
+ dom = arg;
+ ptpindex = 0;
+ ptpshift = 0;
+
+ if (gpa & PAGE_MASK)
+ panic("vtd_create_mapping: unaligned gpa 0x%0lx", gpa);
+
+ if (hpa & PAGE_MASK)
+ panic("vtd_create_mapping: unaligned hpa 0x%0lx", hpa);
+
+ if (len & PAGE_MASK)
+ panic("vtd_create_mapping: unaligned len 0x%0lx", len);
+
+ /*
+ * Compute the size of the mapping that we can accomodate.
+ *
+ * This is based on three factors:
+ * - supported super page size
+ * - alignment of the region starting at 'gpa' and 'hpa'
+ * - length of the region 'len'
+ */
+ spshift = 48;
+ for (i = 3; i >= 0; i--) {
+ spsize = 1UL << spshift;
+ if ((dom->spsmask & (1 << i)) != 0 &&
+ (gpa & (spsize - 1)) == 0 &&
+ (hpa & (spsize - 1)) == 0 &&
+ (len >= spsize)) {
+ break;
+ }
+ spshift -= 9;
+ }
+
+ ptp = dom->ptp;
+ nlevels = dom->pt_levels;
+ while (--nlevels >= 0) {
+ ptpshift = 12 + nlevels * 9;
+ ptpindex = (gpa >> ptpshift) & 0x1FF;
+
+ /* We have reached the leaf mapping */
+ if (spshift >= ptpshift) {
+ break;
+ }
+
+ /*
+ * We are working on a non-leaf page table page.
+ *
+ * Create a downstream page table page if necessary and point
+ * to it from the current page table.
+ */
+ if (ptp[ptpindex] == 0) {
+ void *nlp = malloc(PAGE_SIZE, M_VTD, M_WAITOK | M_ZERO);
+ ptp[ptpindex] = vtophys(nlp)| VTD_PTE_RD | VTD_PTE_WR;
+ }
+
+ ptp = (uint64_t *)PHYS_TO_DMAP(ptp[ptpindex] & VTD_PTE_ADDR_M);
+ }
+
+ if ((gpa & ((1UL << ptpshift) - 1)) != 0)
+ panic("gpa 0x%lx and ptpshift %d mismatch", gpa, ptpshift);
+
+ /*
+ * Update the 'gpa' -> 'hpa' mapping
+ */
+ if (remove) {
+ ptp[ptpindex] = 0;
+ } else {
+ ptp[ptpindex] = hpa | VTD_PTE_RD | VTD_PTE_WR;
+
+ if (nlevels > 0)
+ ptp[ptpindex] |= VTD_PTE_SUPERPAGE;
+ }
+
+ return (1UL << ptpshift);
+}
+
+static uint64_t
+vtd_create_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len)
+{
+
+ return (vtd_update_mapping(arg, gpa, hpa, len, CREATE_MAPPING));
+}
+
+static uint64_t
+vtd_remove_mapping(void *arg, vm_paddr_t gpa, uint64_t len)
+{
+
+ return (vtd_update_mapping(arg, gpa, 0, len, REMOVE_MAPPING));
+}
+
+static void
+vtd_invalidate_tlb(void *dom)
+{
+ int i;
+ struct vtdmap *vtdmap;
+
+ /*
+ * Invalidate the IOTLB.
+ * XXX use domain-selective invalidation for IOTLB
+ */
+ for (i = 0; i < drhd_num; i++) {
+ vtdmap = vtdmaps[i];
+ vtd_iotlb_global_invalidate(vtdmap);
+ }
+}
+
+static void *
+vtd_create_domain(vm_paddr_t maxaddr)
+{
+ struct domain *dom;
+ vm_paddr_t addr;
+ int tmp, i, gaw, agaw, sagaw, res, pt_levels, addrwidth;
+ struct vtdmap *vtdmap;
+
+ if (drhd_num <= 0)
+ panic("vtd_create_domain: no dma remapping hardware available");
+
+ vtdmap = vtdmaps[0];
+
+ /*
+ * Calculate AGAW.
+ * Section 3.4.2 "Adjusted Guest Address Width", Architecture Spec.
+ */
+ addr = 0;
+ for (gaw = 0; addr < maxaddr; gaw++)
+ addr = 1ULL << gaw;
+
+ res = (gaw - 12) % 9;
+ if (res == 0)
+ agaw = gaw;
+ else
+ agaw = gaw + 9 - res;
+
+ if (agaw > 64)
+ agaw = 64;
+
+ /*
+ * Select the smallest Supported AGAW and the corresponding number
+ * of page table levels.
+ */
+ pt_levels = 2;
+ sagaw = 30;
+ addrwidth = 0;
+ tmp = VTD_CAP_SAGAW(vtdmap->cap);
+ for (i = 0; i < 5; i++) {
+ if ((tmp & (1 << i)) != 0 && sagaw >= agaw)
+ break;
+ pt_levels++;
+ addrwidth++;
+ sagaw += 9;
+ if (sagaw > 64)
+ sagaw = 64;
+ }
+
+ if (i >= 5) {
+ panic("vtd_create_domain: SAGAW 0x%lx does not support AGAW %d",
+ VTD_CAP_SAGAW(vtdmap->cap), agaw);
+ }
+
+ dom = malloc(sizeof(struct domain), M_VTD, M_ZERO | M_WAITOK);
+ dom->pt_levels = pt_levels;
+ dom->addrwidth = addrwidth;
+ dom->spsmask = VTD_CAP_SPS(vtdmap->cap);
+ dom->id = domain_id();
+ dom->maxaddr = maxaddr;
+ dom->ptp = malloc(PAGE_SIZE, M_VTD, M_ZERO | M_WAITOK);
+ if ((uintptr_t)dom->ptp & PAGE_MASK)
+ panic("vtd_create_domain: ptp (%p) not page aligned", dom->ptp);
+
+ SLIST_INSERT_HEAD(&domhead, dom, next);
+
+ return (dom);
+}
+
+static void
+vtd_free_ptp(uint64_t *ptp, int level)
+{
+ int i;
+ uint64_t *nlp;
+
+ if (level > 1) {
+ for (i = 0; i < 512; i++) {
+ if ((ptp[i] & (VTD_PTE_RD | VTD_PTE_WR)) == 0)
+ continue;
+ if ((ptp[i] & VTD_PTE_SUPERPAGE) != 0)
+ continue;
+ nlp = (uint64_t *)PHYS_TO_DMAP(ptp[i] & VTD_PTE_ADDR_M);
+ vtd_free_ptp(nlp, level - 1);
+ }
+ }
+
+ bzero(ptp, PAGE_SIZE);
+ free(ptp, M_VTD);
+}
+
+static void
+vtd_destroy_domain(void *arg)
+{
+ struct domain *dom;
+
+ dom = arg;
+
+ SLIST_REMOVE(&domhead, dom, domain, next);
+ vtd_free_ptp(dom->ptp, dom->pt_levels);
+ free(dom, M_VTD);
+}
+
+struct iommu_ops iommu_ops_intel = {
+ vtd_init,
+ vtd_cleanup,
+ vtd_enable,
+ vtd_disable,
+ vtd_create_domain,
+ vtd_destroy_domain,
+ vtd_create_mapping,
+ vtd_remove_mapping,
+ vtd_add_device,
+ vtd_remove_device,
+ vtd_invalidate_tlb,
+};
diff --git a/sys/amd64/vmm/io/iommu.c b/sys/amd64/vmm/io/iommu.c
new file mode 100644
index 0000000..c8447cc
--- /dev/null
+++ b/sys/amd64/vmm/io/iommu.c
@@ -0,0 +1,277 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/md_var.h>
+
+#include "vmm_util.h"
+#include "vmm_mem.h"
+#include "iommu.h"
+
+static boolean_t iommu_avail;
+static struct iommu_ops *ops;
+static void *host_domain;
+
+static __inline int
+IOMMU_INIT(void)
+{
+ if (ops != NULL)
+ return ((*ops->init)());
+ else
+ return (ENXIO);
+}
+
+static __inline void
+IOMMU_CLEANUP(void)
+{
+ if (ops != NULL && iommu_avail)
+ (*ops->cleanup)();
+}
+
+static __inline void *
+IOMMU_CREATE_DOMAIN(vm_paddr_t maxaddr)
+{
+
+ if (ops != NULL && iommu_avail)
+ return ((*ops->create_domain)(maxaddr));
+ else
+ return (NULL);
+}
+
+static __inline void
+IOMMU_DESTROY_DOMAIN(void *dom)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->destroy_domain)(dom);
+}
+
+static __inline uint64_t
+IOMMU_CREATE_MAPPING(void *domain, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len)
+{
+
+ if (ops != NULL && iommu_avail)
+ return ((*ops->create_mapping)(domain, gpa, hpa, len));
+ else
+ return (len); /* XXX */
+}
+
+static __inline uint64_t
+IOMMU_REMOVE_MAPPING(void *domain, vm_paddr_t gpa, uint64_t len)
+{
+
+ if (ops != NULL && iommu_avail)
+ return ((*ops->remove_mapping)(domain, gpa, len));
+ else
+ return (len); /* XXX */
+}
+
+static __inline void
+IOMMU_ADD_DEVICE(void *domain, int bus, int slot, int func)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->add_device)(domain, bus, slot, func);
+}
+
+static __inline void
+IOMMU_REMOVE_DEVICE(void *domain, int bus, int slot, int func)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->remove_device)(domain, bus, slot, func);
+}
+
+static __inline void
+IOMMU_INVALIDATE_TLB(void *domain)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->invalidate_tlb)(domain);
+}
+
+static __inline void
+IOMMU_ENABLE(void)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->enable)();
+}
+
+static __inline void
+IOMMU_DISABLE(void)
+{
+
+ if (ops != NULL && iommu_avail)
+ (*ops->disable)();
+}
+
+void
+iommu_init(void)
+{
+ int error, bus, slot, func;
+ vm_paddr_t maxaddr;
+ const char *name;
+ device_t dev;
+
+ if (vmm_is_intel())
+ ops = &iommu_ops_intel;
+ else if (vmm_is_amd())
+ ops = &iommu_ops_amd;
+ else
+ ops = NULL;
+
+ error = IOMMU_INIT();
+ if (error)
+ return;
+
+ iommu_avail = TRUE;
+
+ /*
+ * Create a domain for the devices owned by the host
+ */
+ maxaddr = vmm_mem_maxaddr();
+ host_domain = IOMMU_CREATE_DOMAIN(maxaddr);
+ if (host_domain == NULL)
+ panic("iommu_init: unable to create a host domain");
+
+ /*
+ * Create 1:1 mappings from '0' to 'maxaddr' for devices assigned to
+ * the host
+ */
+ iommu_create_mapping(host_domain, 0, 0, maxaddr);
+
+ for (bus = 0; bus <= PCI_BUSMAX; bus++) {
+ for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
+ for (func = 0; func <= PCI_FUNCMAX; func++) {
+ dev = pci_find_dbsf(0, bus, slot, func);
+ if (dev == NULL)
+ continue;
+
+ /* skip passthrough devices */
+ name = device_get_name(dev);
+ if (name != NULL && strcmp(name, "ppt") == 0)
+ continue;
+
+ /* everything else belongs to the host domain */
+ iommu_add_device(host_domain, bus, slot, func);
+ }
+ }
+ }
+ IOMMU_ENABLE();
+
+}
+
+void
+iommu_cleanup(void)
+{
+ IOMMU_DISABLE();
+ IOMMU_DESTROY_DOMAIN(host_domain);
+ IOMMU_CLEANUP();
+}
+
+void *
+iommu_create_domain(vm_paddr_t maxaddr)
+{
+
+ return (IOMMU_CREATE_DOMAIN(maxaddr));
+}
+
+void
+iommu_destroy_domain(void *dom)
+{
+
+ IOMMU_DESTROY_DOMAIN(dom);
+}
+
+void
+iommu_create_mapping(void *dom, vm_paddr_t gpa, vm_paddr_t hpa, size_t len)
+{
+ uint64_t mapped, remaining;
+
+ remaining = len;
+
+ while (remaining > 0) {
+ mapped = IOMMU_CREATE_MAPPING(dom, gpa, hpa, remaining);
+ gpa += mapped;
+ hpa += mapped;
+ remaining -= mapped;
+ }
+}
+
+void
+iommu_remove_mapping(void *dom, vm_paddr_t gpa, size_t len)
+{
+ uint64_t unmapped, remaining;
+
+ remaining = len;
+
+ while (remaining > 0) {
+ unmapped = IOMMU_REMOVE_MAPPING(dom, gpa, remaining);
+ gpa += unmapped;
+ remaining -= unmapped;
+ }
+}
+
+void *
+iommu_host_domain(void)
+{
+
+ return (host_domain);
+}
+
+void
+iommu_add_device(void *dom, int bus, int slot, int func)
+{
+
+ IOMMU_ADD_DEVICE(dom, bus, slot, func);
+}
+
+void
+iommu_remove_device(void *dom, int bus, int slot, int func)
+{
+
+ IOMMU_REMOVE_DEVICE(dom, bus, slot, func);
+}
+
+void
+iommu_invalidate_tlb(void *domain)
+{
+
+ IOMMU_INVALIDATE_TLB(domain);
+}
diff --git a/sys/amd64/vmm/io/iommu.h b/sys/amd64/vmm/io/iommu.h
new file mode 100644
index 0000000..d5c1d6e
--- /dev/null
+++ b/sys/amd64/vmm/io/iommu.h
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _IO_IOMMU_H_
+#define _IO_IOMMU_H_
+
+typedef int (*iommu_init_func_t)(void);
+typedef void (*iommu_cleanup_func_t)(void);
+typedef void (*iommu_enable_func_t)(void);
+typedef void (*iommu_disable_func_t)(void);
+typedef void *(*iommu_create_domain_t)(vm_paddr_t maxaddr);
+typedef void (*iommu_destroy_domain_t)(void *domain);
+typedef uint64_t (*iommu_create_mapping_t)(void *domain, vm_paddr_t gpa,
+ vm_paddr_t hpa, uint64_t len);
+typedef uint64_t (*iommu_remove_mapping_t)(void *domain, vm_paddr_t gpa,
+ uint64_t len);
+typedef void (*iommu_add_device_t)(void *domain, int bus, int slot, int func);
+typedef void (*iommu_remove_device_t)(void *dom, int bus, int slot, int func);
+typedef void (*iommu_invalidate_tlb_t)(void *dom);
+
+struct iommu_ops {
+ iommu_init_func_t init; /* module wide */
+ iommu_cleanup_func_t cleanup;
+ iommu_enable_func_t enable;
+ iommu_disable_func_t disable;
+
+ iommu_create_domain_t create_domain; /* domain-specific */
+ iommu_destroy_domain_t destroy_domain;
+ iommu_create_mapping_t create_mapping;
+ iommu_remove_mapping_t remove_mapping;
+ iommu_add_device_t add_device;
+ iommu_remove_device_t remove_device;
+ iommu_invalidate_tlb_t invalidate_tlb;
+};
+
+extern struct iommu_ops iommu_ops_intel;
+extern struct iommu_ops iommu_ops_amd;
+
+void iommu_init(void);
+void iommu_cleanup(void);
+void *iommu_host_domain(void);
+void *iommu_create_domain(vm_paddr_t maxaddr);
+void iommu_destroy_domain(void *dom);
+void iommu_create_mapping(void *dom, vm_paddr_t gpa, vm_paddr_t hpa,
+ size_t len);
+void iommu_remove_mapping(void *dom, vm_paddr_t gpa, size_t len);
+void iommu_add_device(void *dom, int bus, int slot, int func);
+void iommu_remove_device(void *dom, int bus, int slot, int func);
+void iommu_invalidate_tlb(void *domain);
+#endif
diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c
new file mode 100644
index 0000000..4a05985
--- /dev/null
+++ b/sys/amd64/vmm/io/ppt.c
@@ -0,0 +1,619 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/pciio.h>
+#include <sys/rman.h>
+#include <sys/smp.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/resource.h>
+
+#include <machine/vmm.h>
+#include <machine/vmm_dev.h>
+
+#include "vmm_lapic.h"
+#include "vmm_ktr.h"
+
+#include "iommu.h"
+#include "ppt.h"
+
+/* XXX locking */
+
+#define MAX_PPTDEVS (sizeof(pptdevs) / sizeof(pptdevs[0]))
+#define MAX_MSIMSGS 32
+
+/*
+ * If the MSI-X table is located in the middle of a BAR then that MMIO
+ * region gets split into two segments - one segment above the MSI-X table
+ * and the other segment below the MSI-X table - with a hole in place of
+ * the MSI-X table so accesses to it can be trapped and emulated.
+ *
+ * So, allocate a MMIO segment for each BAR register + 1 additional segment.
+ */
+#define MAX_MMIOSEGS ((PCIR_MAX_BAR_0 + 1) + 1)
+
+MALLOC_DEFINE(M_PPTMSIX, "pptmsix", "Passthru MSI-X resources");
+
+struct pptintr_arg { /* pptintr(pptintr_arg) */
+ struct pptdev *pptdev;
+ int vec;
+ int vcpu;
+};
+
+static struct pptdev {
+ device_t dev;
+ struct vm *vm; /* owner of this device */
+ struct vm_memory_segment mmio[MAX_MMIOSEGS];
+ struct {
+ int num_msgs; /* guest state */
+
+ int startrid; /* host state */
+ struct resource *res[MAX_MSIMSGS];
+ void *cookie[MAX_MSIMSGS];
+ struct pptintr_arg arg[MAX_MSIMSGS];
+ } msi;
+
+ struct {
+ int num_msgs;
+ int startrid;
+ int msix_table_rid;
+ struct resource *msix_table_res;
+ struct resource **res;
+ void **cookie;
+ struct pptintr_arg *arg;
+ } msix;
+} pptdevs[64];
+
+static int num_pptdevs;
+
+static int
+ppt_probe(device_t dev)
+{
+ int bus, slot, func;
+ struct pci_devinfo *dinfo;
+
+ dinfo = (struct pci_devinfo *)device_get_ivars(dev);
+
+ bus = pci_get_bus(dev);
+ slot = pci_get_slot(dev);
+ func = pci_get_function(dev);
+
+ /*
+ * To qualify as a pci passthrough device a device must:
+ * - be allowed by administrator to be used in this role
+ * - be an endpoint device
+ */
+ if (vmm_is_pptdev(bus, slot, func) &&
+ (dinfo->cfg.hdrtype & PCIM_HDRTYPE) == PCIM_HDRTYPE_NORMAL)
+ return (0);
+ else
+ return (ENXIO);
+}
+
+static int
+ppt_attach(device_t dev)
+{
+ int n;
+
+ if (num_pptdevs >= MAX_PPTDEVS) {
+ printf("ppt_attach: maximum number of pci passthrough devices "
+ "exceeded\n");
+ return (ENXIO);
+ }
+
+ n = num_pptdevs++;
+ pptdevs[n].dev = dev;
+
+ if (bootverbose)
+ device_printf(dev, "attached\n");
+
+ return (0);
+}
+
+static int
+ppt_detach(device_t dev)
+{
+ /*
+ * XXX check whether there are any pci passthrough devices assigned
+ * to guests before we allow this driver to detach.
+ */
+
+ return (0);
+}
+
+static device_method_t ppt_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ppt_probe),
+ DEVMETHOD(device_attach, ppt_attach),
+ DEVMETHOD(device_detach, ppt_detach),
+ {0, 0}
+};
+
+static devclass_t ppt_devclass;
+DEFINE_CLASS_0(ppt, ppt_driver, ppt_methods, 0);
+DRIVER_MODULE(ppt, pci, ppt_driver, ppt_devclass, NULL, NULL);
+
+static struct pptdev *
+ppt_find(int bus, int slot, int func)
+{
+ device_t dev;
+ int i, b, s, f;
+
+ for (i = 0; i < num_pptdevs; i++) {
+ dev = pptdevs[i].dev;
+ b = pci_get_bus(dev);
+ s = pci_get_slot(dev);
+ f = pci_get_function(dev);
+ if (bus == b && slot == s && func == f)
+ return (&pptdevs[i]);
+ }
+ return (NULL);
+}
+
+static void
+ppt_unmap_mmio(struct vm *vm, struct pptdev *ppt)
+{
+ int i;
+ struct vm_memory_segment *seg;
+
+ for (i = 0; i < MAX_MMIOSEGS; i++) {
+ seg = &ppt->mmio[i];
+ if (seg->len == 0)
+ continue;
+ (void)vm_unmap_mmio(vm, seg->gpa, seg->len);
+ bzero(seg, sizeof(struct vm_memory_segment));
+ }
+}
+
+static void
+ppt_teardown_msi(struct pptdev *ppt)
+{
+ int i, rid;
+ void *cookie;
+ struct resource *res;
+
+ if (ppt->msi.num_msgs == 0)
+ return;
+
+ for (i = 0; i < ppt->msi.num_msgs; i++) {
+ rid = ppt->msi.startrid + i;
+ res = ppt->msi.res[i];
+ cookie = ppt->msi.cookie[i];
+
+ if (cookie != NULL)
+ bus_teardown_intr(ppt->dev, res, cookie);
+
+ if (res != NULL)
+ bus_release_resource(ppt->dev, SYS_RES_IRQ, rid, res);
+
+ ppt->msi.res[i] = NULL;
+ ppt->msi.cookie[i] = NULL;
+ }
+
+ if (ppt->msi.startrid == 1)
+ pci_release_msi(ppt->dev);
+
+ ppt->msi.num_msgs = 0;
+}
+
+static void
+ppt_teardown_msix_intr(struct pptdev *ppt, int idx)
+{
+ int rid;
+ struct resource *res;
+ void *cookie;
+
+ rid = ppt->msix.startrid + idx;
+ res = ppt->msix.res[idx];
+ cookie = ppt->msix.cookie[idx];
+
+ if (cookie != NULL)
+ bus_teardown_intr(ppt->dev, res, cookie);
+
+ if (res != NULL)
+ bus_release_resource(ppt->dev, SYS_RES_IRQ, rid, res);
+
+ ppt->msix.res[idx] = NULL;
+ ppt->msix.cookie[idx] = NULL;
+}
+
+static void
+ppt_teardown_msix(struct pptdev *ppt)
+{
+ int i;
+
+ if (ppt->msix.num_msgs == 0)
+ return;
+
+ for (i = 0; i < ppt->msix.num_msgs; i++)
+ ppt_teardown_msix_intr(ppt, i);
+
+ if (ppt->msix.msix_table_res) {
+ bus_release_resource(ppt->dev, SYS_RES_MEMORY,
+ ppt->msix.msix_table_rid,
+ ppt->msix.msix_table_res);
+ ppt->msix.msix_table_res = NULL;
+ ppt->msix.msix_table_rid = 0;
+ }
+
+ free(ppt->msix.res, M_PPTMSIX);
+ free(ppt->msix.cookie, M_PPTMSIX);
+ free(ppt->msix.arg, M_PPTMSIX);
+
+ pci_release_msi(ppt->dev);
+
+ ppt->msix.num_msgs = 0;
+}
+
+int
+ppt_assign_device(struct vm *vm, int bus, int slot, int func)
+{
+ struct pptdev *ppt;
+
+ ppt = ppt_find(bus, slot, func);
+ if (ppt != NULL) {
+ /*
+ * If this device is owned by a different VM then we
+ * cannot change its owner.
+ */
+ if (ppt->vm != NULL && ppt->vm != vm)
+ return (EBUSY);
+
+ ppt->vm = vm;
+ iommu_add_device(vm_iommu_domain(vm), bus, slot, func);
+ return (0);
+ }
+ return (ENOENT);
+}
+
+int
+ppt_unassign_device(struct vm *vm, int bus, int slot, int func)
+{
+ struct pptdev *ppt;
+
+ ppt = ppt_find(bus, slot, func);
+ if (ppt != NULL) {
+ /*
+ * If this device is not owned by this 'vm' then bail out.
+ */
+ if (ppt->vm != vm)
+ return (EBUSY);
+ ppt_unmap_mmio(vm, ppt);
+ ppt_teardown_msi(ppt);
+ ppt_teardown_msix(ppt);
+ iommu_remove_device(vm_iommu_domain(vm), bus, slot, func);
+ ppt->vm = NULL;
+ return (0);
+ }
+ return (ENOENT);
+}
+
+int
+ppt_unassign_all(struct vm *vm)
+{
+ int i, bus, slot, func;
+ device_t dev;
+
+ for (i = 0; i < num_pptdevs; i++) {
+ if (pptdevs[i].vm == vm) {
+ dev = pptdevs[i].dev;
+ bus = pci_get_bus(dev);
+ slot = pci_get_slot(dev);
+ func = pci_get_function(dev);
+ ppt_unassign_device(vm, bus, slot, func);
+ }
+ }
+
+ return (0);
+}
+
+int
+ppt_map_mmio(struct vm *vm, int bus, int slot, int func,
+ vm_paddr_t gpa, size_t len, vm_paddr_t hpa)
+{
+ int i, error;
+ struct vm_memory_segment *seg;
+ struct pptdev *ppt;
+
+ ppt = ppt_find(bus, slot, func);
+ if (ppt != NULL) {
+ if (ppt->vm != vm)
+ return (EBUSY);
+
+ for (i = 0; i < MAX_MMIOSEGS; i++) {
+ seg = &ppt->mmio[i];
+ if (seg->len == 0) {
+ error = vm_map_mmio(vm, gpa, len, hpa);
+ if (error == 0) {
+ seg->gpa = gpa;
+ seg->len = len;
+ }
+ return (error);
+ }
+ }
+ return (ENOSPC);
+ }
+ return (ENOENT);
+}
+
+static int
+pptintr(void *arg)
+{
+ int vec;
+ struct pptdev *ppt;
+ struct pptintr_arg *pptarg;
+
+ pptarg = arg;
+ ppt = pptarg->pptdev;
+ vec = pptarg->vec;
+
+ if (ppt->vm != NULL)
+ (void) lapic_set_intr(ppt->vm, pptarg->vcpu, vec);
+ else {
+ /*
+ * XXX
+ * This is not expected to happen - panic?
+ */
+ }
+
+ /*
+ * For legacy interrupts give other filters a chance in case
+ * the interrupt was not generated by the passthrough device.
+ */
+ if (ppt->msi.startrid == 0)
+ return (FILTER_STRAY);
+ else
+ return (FILTER_HANDLED);
+}
+
+/*
+ * XXX
+ * When we try to free the MSI resource the kernel will bind the thread to
+ * the host cpu was originally handling the MSI. The function freeing the
+ * MSI vector (apic_free_vector()) will panic the kernel if the thread
+ * is already bound to a cpu.
+ *
+ * So, we temporarily unbind the vcpu thread before freeing the MSI resource.
+ */
+static void
+PPT_TEARDOWN_MSI(struct vm *vm, int vcpu, struct pptdev *ppt)
+{
+ int pincpu = -1;
+
+ vm_get_pinning(vm, vcpu, &pincpu);
+
+ if (pincpu >= 0)
+ vm_set_pinning(vm, vcpu, -1);
+
+ ppt_teardown_msi(ppt);
+
+ if (pincpu >= 0)
+ vm_set_pinning(vm, vcpu, pincpu);
+}
+
+int
+ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func,
+ int destcpu, int vector, int numvec)
+{
+ int i, rid, flags;
+ int msi_count, startrid, error, tmp;
+ struct pptdev *ppt;
+
+ if ((destcpu >= VM_MAXCPU || destcpu < 0) ||
+ (vector < 0 || vector > 255) ||
+ (numvec < 0 || numvec > MAX_MSIMSGS))
+ return (EINVAL);
+
+ ppt = ppt_find(bus, slot, func);
+ if (ppt == NULL)
+ return (ENOENT);
+ if (ppt->vm != vm) /* Make sure we own this device */
+ return (EBUSY);
+
+ /* Free any allocated resources */
+ PPT_TEARDOWN_MSI(vm, vcpu, ppt);
+
+ if (numvec == 0) /* nothing more to do */
+ return (0);
+
+ flags = RF_ACTIVE;
+ msi_count = pci_msi_count(ppt->dev);
+ if (msi_count == 0) {
+ startrid = 0; /* legacy interrupt */
+ msi_count = 1;
+ flags |= RF_SHAREABLE;
+ } else
+ startrid = 1; /* MSI */
+
+ /*
+ * The device must be capable of supporting the number of vectors
+ * the guest wants to allocate.
+ */
+ if (numvec > msi_count)
+ return (EINVAL);
+
+ /*
+ * Make sure that we can allocate all the MSI vectors that are needed
+ * by the guest.
+ */
+ if (startrid == 1) {
+ tmp = numvec;
+ error = pci_alloc_msi(ppt->dev, &tmp);
+ if (error)
+ return (error);
+ else if (tmp != numvec) {
+ pci_release_msi(ppt->dev);
+ return (ENOSPC);
+ } else {
+ /* success */
+ }
+ }
+
+ ppt->msi.startrid = startrid;
+
+ /*
+ * Allocate the irq resource and attach it to the interrupt handler.
+ */
+ for (i = 0; i < numvec; i++) {
+ ppt->msi.num_msgs = i + 1;
+ ppt->msi.cookie[i] = NULL;
+
+ rid = startrid + i;
+ ppt->msi.res[i] = bus_alloc_resource_any(ppt->dev, SYS_RES_IRQ,
+ &rid, flags);
+ if (ppt->msi.res[i] == NULL)
+ break;
+
+ ppt->msi.arg[i].pptdev = ppt;
+ ppt->msi.arg[i].vec = vector + i;
+ ppt->msi.arg[i].vcpu = destcpu;
+
+ error = bus_setup_intr(ppt->dev, ppt->msi.res[i],
+ INTR_TYPE_NET | INTR_MPSAFE,
+ pptintr, NULL, &ppt->msi.arg[i],
+ &ppt->msi.cookie[i]);
+ if (error != 0)
+ break;
+ }
+
+ if (i < numvec) {
+ PPT_TEARDOWN_MSI(vm, vcpu, ppt);
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+int
+ppt_setup_msix(struct vm *vm, int vcpu, int bus, int slot, int func,
+ int idx, uint32_t msg, uint32_t vector_control, uint64_t addr)
+{
+ struct pptdev *ppt;
+ struct pci_devinfo *dinfo;
+ int numvec, alloced, rid, error;
+ size_t res_size, cookie_size, arg_size;
+
+ ppt = ppt_find(bus, slot, func);
+ if (ppt == NULL)
+ return (ENOENT);
+ if (ppt->vm != vm) /* Make sure we own this device */
+ return (EBUSY);
+
+ dinfo = device_get_ivars(ppt->dev);
+ if (!dinfo)
+ return (ENXIO);
+
+ /*
+ * First-time configuration:
+ * Allocate the MSI-X table
+ * Allocate the IRQ resources
+ * Set up some variables in ppt->msix
+ */
+ if (ppt->msix.num_msgs == 0) {
+ numvec = pci_msix_count(ppt->dev);
+ if (numvec <= 0)
+ return (EINVAL);
+
+ ppt->msix.startrid = 1;
+ ppt->msix.num_msgs = numvec;
+
+ res_size = numvec * sizeof(ppt->msix.res[0]);
+ cookie_size = numvec * sizeof(ppt->msix.cookie[0]);
+ arg_size = numvec * sizeof(ppt->msix.arg[0]);
+
+ ppt->msix.res = malloc(res_size, M_PPTMSIX, M_WAITOK | M_ZERO);
+ ppt->msix.cookie = malloc(cookie_size, M_PPTMSIX,
+ M_WAITOK | M_ZERO);
+ ppt->msix.arg = malloc(arg_size, M_PPTMSIX, M_WAITOK | M_ZERO);
+
+ rid = dinfo->cfg.msix.msix_table_bar;
+ ppt->msix.msix_table_res = bus_alloc_resource_any(ppt->dev,
+ SYS_RES_MEMORY, &rid, RF_ACTIVE);
+
+ if (ppt->msix.msix_table_res == NULL) {
+ ppt_teardown_msix(ppt);
+ return (ENOSPC);
+ }
+ ppt->msix.msix_table_rid = rid;
+
+ alloced = numvec;
+ error = pci_alloc_msix(ppt->dev, &alloced);
+ if (error || alloced != numvec) {
+ ppt_teardown_msix(ppt);
+ return (error == 0 ? ENOSPC: error);
+ }
+ }
+
+ if ((vector_control & PCIM_MSIX_VCTRL_MASK) == 0) {
+ /* Tear down the IRQ if it's already set up */
+ ppt_teardown_msix_intr(ppt, idx);
+
+ /* Allocate the IRQ resource */
+ ppt->msix.cookie[idx] = NULL;
+ rid = ppt->msix.startrid + idx;
+ ppt->msix.res[idx] = bus_alloc_resource_any(ppt->dev, SYS_RES_IRQ,
+ &rid, RF_ACTIVE);
+ if (ppt->msix.res[idx] == NULL)
+ return (ENXIO);
+
+ ppt->msix.arg[idx].pptdev = ppt;
+ ppt->msix.arg[idx].vec = msg;
+ ppt->msix.arg[idx].vcpu = (addr >> 12) & 0xFF;
+
+ /* Setup the MSI-X interrupt */
+ error = bus_setup_intr(ppt->dev, ppt->msix.res[idx],
+ INTR_TYPE_NET | INTR_MPSAFE,
+ pptintr, NULL, &ppt->msix.arg[idx],
+ &ppt->msix.cookie[idx]);
+
+ if (error != 0) {
+ bus_teardown_intr(ppt->dev, ppt->msix.res[idx], ppt->msix.cookie[idx]);
+ bus_release_resource(ppt->dev, SYS_RES_IRQ, rid, ppt->msix.res[idx]);
+ ppt->msix.cookie[idx] = NULL;
+ ppt->msix.res[idx] = NULL;
+ return (ENXIO);
+ }
+ } else {
+ /* Masked, tear it down if it's already been set up */
+ ppt_teardown_msix_intr(ppt, idx);
+ }
+
+ return (0);
+}
+
diff --git a/sys/amd64/vmm/io/ppt.h b/sys/amd64/vmm/io/ppt.h
new file mode 100644
index 0000000..63c8228
--- /dev/null
+++ b/sys/amd64/vmm/io/ppt.h
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _IO_PPT_H_
+#define _IO_PPT_H_
+
+int ppt_assign_device(struct vm *vm, int bus, int slot, int func);
+int ppt_unassign_device(struct vm *vm, int bus, int slot, int func);
+int ppt_unassign_all(struct vm *vm);
+int ppt_map_mmio(struct vm *vm, int bus, int slot, int func,
+ vm_paddr_t gpa, size_t len, vm_paddr_t hpa);
+int ppt_setup_msi(struct vm *vm, int vcpu, int bus, int slot, int func,
+ int destcpu, int vector, int numvec);
+int ppt_setup_msix(struct vm *vm, int vcpu, int bus, int slot, int func,
+ int idx, uint32_t msg, uint32_t vector_control, uint64_t addr);
+#endif
diff --git a/sys/amd64/vmm/io/vdev.c b/sys/amd64/vmm/io/vdev.c
new file mode 100644
index 0000000..cd6c5d1
--- /dev/null
+++ b/sys/amd64/vmm/io/vdev.c
@@ -0,0 +1,270 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include "vdev.h"
+
+struct vdev {
+ SLIST_ENTRY(vdev) entry;
+ struct vdev_ops *ops;
+ void *dev;
+};
+static SLIST_HEAD(, vdev) vdev_head;
+static int vdev_count;
+
+struct vdev_region {
+ SLIST_ENTRY(vdev_region) entry;
+ struct vdev_ops *ops;
+ void *dev;
+ struct io_region *io;
+};
+static SLIST_HEAD(, vdev_region) region_head;
+static int region_count;
+
+static MALLOC_DEFINE(M_VDEV, "vdev", "vdev");
+
+#define VDEV_INIT (0)
+#define VDEV_RESET (1)
+#define VDEV_HALT (2)
+
+// static const char* vdev_event_str[] = {"VDEV_INIT", "VDEV_RESET", "VDEV_HALT"};
+
+static int
+vdev_system_event(int event)
+{
+ struct vdev *vd;
+ int rc;
+
+ // TODO: locking
+ SLIST_FOREACH(vd, &vdev_head, entry) {
+ // printf("%s : %s Device %s\n", __func__, vdev_event_str[event], vd->ops->name);
+ switch (event) {
+ case VDEV_INIT:
+ rc = vd->ops->init(vd->dev);
+ break;
+ case VDEV_RESET:
+ rc = vd->ops->reset(vd->dev);
+ break;
+ case VDEV_HALT:
+ rc = vd->ops->halt(vd->dev);
+ break;
+ default:
+ break;
+ }
+ if (rc) {
+ printf("vdev %s init failed rc=%d\n",
+ vd->ops->name, rc);
+ return rc;
+ }
+ }
+ return 0;
+}
+
+int
+vdev_init(void)
+{
+ return vdev_system_event(VDEV_INIT);
+}
+
+int
+vdev_reset(void)
+{
+ return vdev_system_event(VDEV_RESET);
+}
+
+int
+vdev_halt(void)
+{
+ return vdev_system_event(VDEV_HALT);
+}
+
+void
+vdev_vm_init(void)
+{
+ SLIST_INIT(&vdev_head);
+ vdev_count = 0;
+
+ SLIST_INIT(&region_head);
+ region_count = 0;
+}
+void
+vdev_vm_cleanup(void)
+{
+ struct vdev *vd;
+
+ // TODO: locking
+ while (!SLIST_EMPTY(&vdev_head)) {
+ vd = SLIST_FIRST(&vdev_head);
+ SLIST_REMOVE_HEAD(&vdev_head, entry);
+ free(vd, M_VDEV);
+ vdev_count--;
+ }
+}
+
+int
+vdev_register(struct vdev_ops *ops, void *dev)
+{
+ struct vdev *vd;
+ vd = malloc(sizeof(*vd), M_VDEV, M_WAITOK | M_ZERO);
+ vd->ops = ops;
+ vd->dev = dev;
+
+ // TODO: locking
+ SLIST_INSERT_HEAD(&vdev_head, vd, entry);
+ vdev_count++;
+ return 0;
+}
+
+void
+vdev_unregister(void *dev)
+{
+ struct vdev *vd, *found;
+
+ found = NULL;
+ // TODO: locking
+ SLIST_FOREACH(vd, &vdev_head, entry) {
+ if (vd->dev == dev) {
+ found = vd;
+ }
+ }
+
+ if (found) {
+ SLIST_REMOVE(&vdev_head, found, vdev, entry);
+ free(found, M_VDEV);
+ }
+}
+
+#define IN_RANGE(val, start, end) \
+ (((val) >= (start)) && ((val) < (end)))
+
+static struct vdev_region*
+vdev_find_region(struct io_region *io, void *dev)
+{
+ struct vdev_region *region, *found;
+ uint64_t region_base;
+ uint64_t region_end;
+
+ found = NULL;
+
+ // TODO: locking
+ // FIXME: we should verify we are in the context the current
+ // vcpu here as well.
+ SLIST_FOREACH(region, &region_head, entry) {
+ region_base = region->io->base;
+ region_end = region_base + region->io->len;
+ if (IN_RANGE(io->base, region_base, region_end) &&
+ IN_RANGE(io->base+io->len, region_base, region_end+1) &&
+ (dev && dev == region->dev)) {
+ found = region;
+ break;
+ }
+ }
+ return found;
+}
+
+int
+vdev_register_region(struct vdev_ops *ops, void *dev, struct io_region *io)
+{
+ struct vdev_region *region;
+
+ region = vdev_find_region(io, dev);
+ if (region) {
+ return -EEXIST;
+ }
+
+ region = malloc(sizeof(*region), M_VDEV, M_WAITOK | M_ZERO);
+ region->io = io;
+ region->ops = ops;
+ region->dev = dev;
+
+ // TODO: locking
+ SLIST_INSERT_HEAD(&region_head, region, entry);
+ region_count++;
+
+ return 0;
+}
+
+void
+vdev_unregister_region(void *dev, struct io_region *io)
+{
+ struct vdev_region *region;
+
+ region = vdev_find_region(io, dev);
+
+ if (region) {
+ SLIST_REMOVE(&region_head, region, vdev_region, entry);
+ free(region, M_VDEV);
+ region_count--;
+ }
+}
+
+static int
+vdev_memrw(uint64_t gpa, opsize_t size, uint64_t *data, int read)
+{
+ struct vdev_region *region;
+ struct io_region io;
+ region_attr_t attr;
+ int rc;
+
+ io.base = gpa;
+ io.len = size;
+
+ region = vdev_find_region(&io, NULL);
+ if (!region)
+ return -EINVAL;
+
+ attr = (read) ? MMIO_READ : MMIO_WRITE;
+ if (!(region->io->attr & attr))
+ return -EPERM;
+
+ if (read)
+ rc = region->ops->memread(region->dev, gpa, size, data);
+ else
+ rc = region->ops->memwrite(region->dev, gpa, size, *data);
+
+ return rc;
+}
+
+int
+vdev_memread(uint64_t gpa, opsize_t size, uint64_t *data)
+{
+ return vdev_memrw(gpa, size, data, 1);
+}
+
+int
+vdev_memwrite(uint64_t gpa, opsize_t size, uint64_t data)
+{
+ return vdev_memrw(gpa, size, &data, 0);
+}
diff --git a/sys/amd64/vmm/io/vdev.h b/sys/amd64/vmm/io/vdev.h
new file mode 100644
index 0000000..6feeba8
--- /dev/null
+++ b/sys/amd64/vmm/io/vdev.h
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VDEV_H_
+#define _VDEV_H_
+
+typedef enum {
+ BYTE = 1,
+ WORD = 2,
+ DWORD = 4,
+ QWORD = 8,
+} opsize_t;
+
+typedef enum {
+ MMIO_READ = 1,
+ MMIO_WRITE = 2,
+} region_attr_t;
+
+struct io_region {
+ uint64_t base;
+ uint64_t len;
+ region_attr_t attr;
+ int vcpu;
+};
+
+typedef int (*vdev_init_t)(void* dev);
+typedef int (*vdev_reset_t)(void* dev);
+typedef int (*vdev_halt_t)(void* dev);
+typedef int (*vdev_memread_t)(void* dev, uint64_t gpa, opsize_t size, uint64_t *data);
+typedef int (*vdev_memwrite_t)(void* dev, uint64_t gpa, opsize_t size, uint64_t data);
+
+
+struct vdev_ops {
+ const char *name;
+ vdev_init_t init;
+ vdev_reset_t reset;
+ vdev_halt_t halt;
+ vdev_memread_t memread;
+ vdev_memwrite_t memwrite;
+};
+
+
+void vdev_vm_init(void);
+void vdev_vm_cleanup(void);
+
+int vdev_register(struct vdev_ops *ops, void *dev);
+void vdev_unregister(void *dev);
+
+int vdev_register_region(struct vdev_ops *ops, void *dev, struct io_region *io);
+void vdev_unregister_region(void *dev, struct io_region *io);
+
+int vdev_init(void);
+int vdev_reset(void);
+int vdev_halt(void);
+int vdev_memread(uint64_t gpa, opsize_t size, uint64_t *data);
+int vdev_memwrite(uint64_t gpa, opsize_t size, uint64_t data);
+
+#endif /* _VDEV_H_ */
+
diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c
new file mode 100644
index 0000000..15fc6c2
--- /dev/null
+++ b/sys/amd64/vmm/io/vlapic.c
@@ -0,0 +1,901 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+
+#include <machine/clock.h>
+#include <x86/specialreg.h>
+#include <x86/apicreg.h>
+
+#include <machine/vmm.h>
+
+#include "vmm_lapic.h"
+#include "vmm_ktr.h"
+#include "vdev.h"
+#include "vlapic.h"
+
+#define VLAPIC_CTR0(vlapic, format) \
+ VMM_CTR0((vlapic)->vm, (vlapic)->vcpuid, format)
+
+#define VLAPIC_CTR1(vlapic, format, p1) \
+ VMM_CTR1((vlapic)->vm, (vlapic)->vcpuid, format, p1)
+
+#define VLAPIC_CTR_IRR(vlapic, msg) \
+do { \
+ uint32_t *irrptr = &(vlapic)->apic.irr0; \
+ irrptr[0] = irrptr[0]; /* silence compiler */ \
+ VLAPIC_CTR1((vlapic), msg " irr0 0x%08x", irrptr[0 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr1 0x%08x", irrptr[1 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr2 0x%08x", irrptr[2 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr3 0x%08x", irrptr[3 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr4 0x%08x", irrptr[4 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr5 0x%08x", irrptr[5 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr6 0x%08x", irrptr[6 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " irr7 0x%08x", irrptr[7 << 2]); \
+} while (0)
+
+#define VLAPIC_CTR_ISR(vlapic, msg) \
+do { \
+ uint32_t *isrptr = &(vlapic)->apic.isr0; \
+ isrptr[0] = isrptr[0]; /* silence compiler */ \
+ VLAPIC_CTR1((vlapic), msg " isr0 0x%08x", isrptr[0 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr1 0x%08x", isrptr[1 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr2 0x%08x", isrptr[2 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr3 0x%08x", isrptr[3 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr4 0x%08x", isrptr[4 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr5 0x%08x", isrptr[5 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr6 0x%08x", isrptr[6 << 2]); \
+ VLAPIC_CTR1((vlapic), msg " isr7 0x%08x", isrptr[7 << 2]); \
+} while (0)
+
+static MALLOC_DEFINE(M_VLAPIC, "vlapic", "vlapic");
+
+#define PRIO(x) ((x) >> 4)
+
+#define VLAPIC_VERSION (16)
+#define VLAPIC_MAXLVT_ENTRIES (5)
+
+#define x2apic(vlapic) (((vlapic)->msr_apicbase & APICBASE_X2APIC) ? 1 : 0)
+
+enum boot_state {
+ BS_INIT,
+ BS_SIPI,
+ BS_RUNNING
+};
+
+struct vlapic {
+ struct vm *vm;
+ int vcpuid;
+
+ struct io_region *mmio;
+ struct vdev_ops *ops;
+ struct LAPIC apic;
+
+ int esr_update;
+
+ int divisor;
+ int ccr_ticks;
+
+ /*
+ * The 'isrvec_stk' is a stack of vectors injected by the local apic.
+ * A vector is popped from the stack when the processor does an EOI.
+ * The vector on the top of the stack is used to compute the
+ * Processor Priority in conjunction with the TPR.
+ */
+ uint8_t isrvec_stk[ISRVEC_STK_SIZE];
+ int isrvec_stk_top;
+
+ uint64_t msr_apicbase;
+ enum boot_state boot_state;
+};
+
+#define VLAPIC_BUS_FREQ tsc_freq
+
+static int
+vlapic_timer_divisor(uint32_t dcr)
+{
+ switch (dcr & 0xB) {
+ case APIC_TDCR_2:
+ return (2);
+ case APIC_TDCR_4:
+ return (4);
+ case APIC_TDCR_8:
+ return (8);
+ case APIC_TDCR_16:
+ return (16);
+ case APIC_TDCR_32:
+ return (32);
+ case APIC_TDCR_64:
+ return (64);
+ case APIC_TDCR_128:
+ return (128);
+ default:
+ panic("vlapic_timer_divisor: invalid dcr 0x%08x", dcr);
+ }
+}
+
+static void
+vlapic_mask_lvts(uint32_t *lvts, int num_lvt)
+{
+ int i;
+ for (i = 0; i < num_lvt; i++) {
+ *lvts |= APIC_LVT_M;
+ lvts += 4;
+ }
+}
+
+#if 0
+static inline void
+vlapic_dump_lvt(uint32_t offset, uint32_t *lvt)
+{
+ printf("Offset %x: lvt %08x (V:%02x DS:%x M:%x)\n", offset,
+ *lvt, *lvt & APIC_LVTT_VECTOR, *lvt & APIC_LVTT_DS,
+ *lvt & APIC_LVTT_M);
+}
+#endif
+
+static uint64_t
+vlapic_get_ccr(struct vlapic *vlapic)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ return lapic->ccr_timer;
+}
+
+static void
+vlapic_update_errors(struct vlapic *vlapic)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ lapic->esr = 0; // XXX
+}
+
+static void
+vlapic_init_ipi(struct vlapic *vlapic)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ lapic->version = VLAPIC_VERSION;
+ lapic->version |= (VLAPIC_MAXLVT_ENTRIES < MAXLVTSHIFT);
+ lapic->dfr = 0xffffffff;
+ lapic->svr = APIC_SVR_VECTOR;
+ vlapic_mask_lvts(&lapic->lvt_timer, VLAPIC_MAXLVT_ENTRIES+1);
+}
+
+static int
+vlapic_op_reset(void* dev)
+{
+ struct vlapic *vlapic = (struct vlapic*)dev;
+ struct LAPIC *lapic = &vlapic->apic;
+
+ memset(lapic, 0, sizeof(*lapic));
+ lapic->apr = vlapic->vcpuid;
+ vlapic_init_ipi(vlapic);
+ vlapic->divisor = vlapic_timer_divisor(lapic->dcr_timer);
+
+ if (vlapic->vcpuid == 0)
+ vlapic->boot_state = BS_RUNNING; /* BSP */
+ else
+ vlapic->boot_state = BS_INIT; /* AP */
+
+ return 0;
+
+}
+
+static int
+vlapic_op_init(void* dev)
+{
+ struct vlapic *vlapic = (struct vlapic*)dev;
+ vdev_register_region(vlapic->ops, vlapic, vlapic->mmio);
+ return vlapic_op_reset(dev);
+}
+
+static int
+vlapic_op_halt(void* dev)
+{
+ struct vlapic *vlapic = (struct vlapic*)dev;
+ vdev_unregister_region(vlapic, vlapic->mmio);
+ return 0;
+
+}
+
+void
+vlapic_set_intr_ready(struct vlapic *vlapic, int vector)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ uint32_t *irrptr;
+ int idx;
+
+ if (vector < 0 || vector >= 256)
+ panic("vlapic_set_intr_ready: invalid vector %d\n", vector);
+
+ idx = (vector / 32) * 4;
+ irrptr = &lapic->irr0;
+ atomic_set_int(&irrptr[idx], 1 << (vector % 32));
+ VLAPIC_CTR_IRR(vlapic, "vlapic_set_intr_ready");
+}
+
+static void
+vlapic_start_timer(struct vlapic *vlapic, uint32_t elapsed)
+{
+ uint32_t icr_timer;
+
+ icr_timer = vlapic->apic.icr_timer;
+
+ vlapic->ccr_ticks = ticks;
+ if (elapsed < icr_timer)
+ vlapic->apic.ccr_timer = icr_timer - elapsed;
+ else {
+ /*
+ * This can happen when the guest is trying to run its local
+ * apic timer higher that the setting of 'hz' in the host.
+ *
+ * We deal with this by running the guest local apic timer
+ * at the rate of the host's 'hz' setting.
+ */
+ vlapic->apic.ccr_timer = 0;
+ }
+}
+
+static __inline uint32_t *
+vlapic_get_lvt(struct vlapic *vlapic, uint32_t offset)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ int i;
+
+ if (offset < APIC_OFFSET_TIMER_LVT || offset > APIC_OFFSET_ERROR_LVT) {
+ panic("vlapic_get_lvt: invalid LVT\n");
+ }
+ i = (offset - APIC_OFFSET_TIMER_LVT) >> 2;
+ return ((&lapic->lvt_timer) + i);;
+}
+
+#if 1
+static void
+dump_isrvec_stk(struct vlapic *vlapic)
+{
+ int i;
+ uint32_t *isrptr;
+
+ isrptr = &vlapic->apic.isr0;
+ for (i = 0; i < 8; i++)
+ printf("ISR%d 0x%08x\n", i, isrptr[i * 4]);
+
+ for (i = 0; i <= vlapic->isrvec_stk_top; i++)
+ printf("isrvec_stk[%d] = %d\n", i, vlapic->isrvec_stk[i]);
+}
+#endif
+
+/*
+ * Algorithm adopted from section "Interrupt, Task and Processor Priority"
+ * in Intel Architecture Manual Vol 3a.
+ */
+static void
+vlapic_update_ppr(struct vlapic *vlapic)
+{
+ int isrvec, tpr, ppr;
+
+ /*
+ * Note that the value on the stack at index 0 is always 0.
+ *
+ * This is a placeholder for the value of ISRV when none of the
+ * bits is set in the ISRx registers.
+ */
+ isrvec = vlapic->isrvec_stk[vlapic->isrvec_stk_top];
+ tpr = vlapic->apic.tpr;
+
+#if 1
+ {
+ int i, lastprio, curprio, vector, idx;
+ uint32_t *isrptr;
+
+ if (vlapic->isrvec_stk_top == 0 && isrvec != 0)
+ panic("isrvec_stk is corrupted: %d", isrvec);
+
+ /*
+ * Make sure that the priority of the nested interrupts is
+ * always increasing.
+ */
+ lastprio = -1;
+ for (i = 1; i <= vlapic->isrvec_stk_top; i++) {
+ curprio = PRIO(vlapic->isrvec_stk[i]);
+ if (curprio <= lastprio) {
+ dump_isrvec_stk(vlapic);
+ panic("isrvec_stk does not satisfy invariant");
+ }
+ lastprio = curprio;
+ }
+
+ /*
+ * Make sure that each bit set in the ISRx registers has a
+ * corresponding entry on the isrvec stack.
+ */
+ i = 1;
+ isrptr = &vlapic->apic.isr0;
+ for (vector = 0; vector < 256; vector++) {
+ idx = (vector / 32) * 4;
+ if (isrptr[idx] & (1 << (vector % 32))) {
+ if (i > vlapic->isrvec_stk_top ||
+ vlapic->isrvec_stk[i] != vector) {
+ dump_isrvec_stk(vlapic);
+ panic("ISR and isrvec_stk out of sync");
+ }
+ i++;
+ }
+ }
+ }
+#endif
+
+ if (PRIO(tpr) >= PRIO(isrvec))
+ ppr = tpr;
+ else
+ ppr = isrvec & 0xf0;
+
+ vlapic->apic.ppr = ppr;
+ VLAPIC_CTR1(vlapic, "vlapic_update_ppr 0x%02x", ppr);
+}
+
+static void
+vlapic_process_eoi(struct vlapic *vlapic)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ uint32_t *isrptr;
+ int i, idx, bitpos;
+
+ isrptr = &lapic->isr0;
+
+ /*
+ * The x86 architecture reserves the the first 32 vectors for use
+ * by the processor.
+ */
+ for (i = 7; i > 0; i--) {
+ idx = i * 4;
+ bitpos = fls(isrptr[idx]);
+ if (bitpos != 0) {
+ if (vlapic->isrvec_stk_top <= 0) {
+ panic("invalid vlapic isrvec_stk_top %d",
+ vlapic->isrvec_stk_top);
+ }
+ isrptr[idx] &= ~(1 << (bitpos - 1));
+ VLAPIC_CTR_ISR(vlapic, "vlapic_process_eoi");
+ vlapic->isrvec_stk_top--;
+ vlapic_update_ppr(vlapic);
+ return;
+ }
+ }
+}
+
+static __inline int
+vlapic_get_lvt_field(uint32_t *lvt, uint32_t mask)
+{
+ return (*lvt & mask);
+}
+
+static __inline int
+vlapic_periodic_timer(struct vlapic *vlapic)
+{
+ uint32_t *lvt;
+
+ lvt = vlapic_get_lvt(vlapic, APIC_OFFSET_TIMER_LVT);
+
+ return (vlapic_get_lvt_field(lvt, APIC_LVTT_TM_PERIODIC));
+}
+
+static void
+vlapic_fire_timer(struct vlapic *vlapic)
+{
+ int vector;
+ uint32_t *lvt;
+
+ lvt = vlapic_get_lvt(vlapic, APIC_OFFSET_TIMER_LVT);
+
+ if (!vlapic_get_lvt_field(lvt, APIC_LVTT_M)) {
+ vector = vlapic_get_lvt_field(lvt,APIC_LVTT_VECTOR);
+ vlapic_set_intr_ready(vlapic, vector);
+ }
+}
+
+static int
+lapic_process_icr(struct vlapic *vlapic, uint64_t icrval)
+{
+ int i;
+ cpuset_t dmask;
+ uint32_t dest, vec, mode;
+ struct vlapic *vlapic2;
+ struct vm_exit *vmexit;
+
+ if (x2apic(vlapic))
+ dest = icrval >> 32;
+ else
+ dest = icrval >> (32 + 24);
+ vec = icrval & APIC_VECTOR_MASK;
+ mode = icrval & APIC_DELMODE_MASK;
+
+ if (mode == APIC_DELMODE_FIXED || mode == APIC_DELMODE_NMI) {
+ switch (icrval & APIC_DEST_MASK) {
+ case APIC_DEST_DESTFLD:
+ CPU_SETOF(dest, &dmask);
+ break;
+ case APIC_DEST_SELF:
+ CPU_SETOF(vlapic->vcpuid, &dmask);
+ break;
+ case APIC_DEST_ALLISELF:
+ dmask = vm_active_cpus(vlapic->vm);
+ break;
+ case APIC_DEST_ALLESELF:
+ dmask = vm_active_cpus(vlapic->vm);
+ CPU_CLR(vlapic->vcpuid, &dmask);
+ break;
+ }
+
+ while ((i = cpusetobj_ffs(&dmask)) != 0) {
+ i--;
+ CPU_CLR(i, &dmask);
+ if (mode == APIC_DELMODE_FIXED)
+ lapic_set_intr(vlapic->vm, i, vec);
+ else
+ vm_inject_nmi(vlapic->vm, i);
+ }
+
+ return (0); /* handled completely in the kernel */
+ }
+
+ if (mode == APIC_DELMODE_INIT) {
+ if ((icrval & APIC_LEVEL_MASK) == APIC_LEVEL_DEASSERT)
+ return (0);
+
+ if (vlapic->vcpuid == 0 && dest != 0 && dest < VM_MAXCPU) {
+ vlapic2 = vm_lapic(vlapic->vm, dest);
+
+ /* move from INIT to waiting-for-SIPI state */
+ if (vlapic2->boot_state == BS_INIT) {
+ vlapic2->boot_state = BS_SIPI;
+ }
+
+ return (0);
+ }
+ }
+
+ if (mode == APIC_DELMODE_STARTUP) {
+ if (vlapic->vcpuid == 0 && dest != 0 && dest < VM_MAXCPU) {
+ vlapic2 = vm_lapic(vlapic->vm, dest);
+
+ /*
+ * Ignore SIPIs in any state other than wait-for-SIPI
+ */
+ if (vlapic2->boot_state != BS_SIPI)
+ return (0);
+
+ vmexit = vm_exitinfo(vlapic->vm, vlapic->vcpuid);
+ vmexit->exitcode = VM_EXITCODE_SPINUP_AP;
+ vmexit->u.spinup_ap.vcpu = dest;
+ vmexit->u.spinup_ap.rip = vec << PAGE_SHIFT;
+
+ /*
+ * XXX this assumes that the startup IPI always succeeds
+ */
+ vlapic2->boot_state = BS_RUNNING;
+ vm_activate_cpu(vlapic2->vm, dest);
+
+ return (0);
+ }
+ }
+
+ /*
+ * This will cause a return to userland.
+ */
+ return (1);
+}
+
+int
+vlapic_pending_intr(struct vlapic *vlapic)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ int idx, i, bitpos, vector;
+ uint32_t *irrptr, val;
+
+ irrptr = &lapic->irr0;
+
+ /*
+ * The x86 architecture reserves the the first 32 vectors for use
+ * by the processor.
+ */
+ for (i = 7; i > 0; i--) {
+ idx = i * 4;
+ val = atomic_load_acq_int(&irrptr[idx]);
+ bitpos = fls(val);
+ if (bitpos != 0) {
+ vector = i * 32 + (bitpos - 1);
+ if (PRIO(vector) > PRIO(lapic->ppr)) {
+ VLAPIC_CTR1(vlapic, "pending intr %d", vector);
+ return (vector);
+ } else
+ break;
+ }
+ }
+ VLAPIC_CTR0(vlapic, "no pending intr");
+ return (-1);
+}
+
+void
+vlapic_intr_accepted(struct vlapic *vlapic, int vector)
+{
+ struct LAPIC *lapic = &vlapic->apic;
+ uint32_t *irrptr, *isrptr;
+ int idx, stk_top;
+
+ /*
+ * clear the ready bit for vector being accepted in irr
+ * and set the vector as in service in isr.
+ */
+ idx = (vector / 32) * 4;
+
+ irrptr = &lapic->irr0;
+ atomic_clear_int(&irrptr[idx], 1 << (vector % 32));
+ VLAPIC_CTR_IRR(vlapic, "vlapic_intr_accepted");
+
+ isrptr = &lapic->isr0;
+ isrptr[idx] |= 1 << (vector % 32);
+ VLAPIC_CTR_ISR(vlapic, "vlapic_intr_accepted");
+
+ /*
+ * Update the PPR
+ */
+ vlapic->isrvec_stk_top++;
+
+ stk_top = vlapic->isrvec_stk_top;
+ if (stk_top >= ISRVEC_STK_SIZE)
+ panic("isrvec_stk_top overflow %d", stk_top);
+
+ vlapic->isrvec_stk[stk_top] = vector;
+ vlapic_update_ppr(vlapic);
+}
+
+int
+vlapic_op_mem_read(void* dev, uint64_t gpa, opsize_t size, uint64_t *data)
+{
+ struct vlapic *vlapic = (struct vlapic*)dev;
+ struct LAPIC *lapic = &vlapic->apic;
+ uint64_t offset = gpa & ~(PAGE_SIZE);
+ uint32_t *reg;
+ int i;
+
+ if (offset > sizeof(*lapic)) {
+ *data = 0;
+ return 0;
+ }
+
+ offset &= ~3;
+ switch(offset)
+ {
+ case APIC_OFFSET_ID:
+ if (x2apic(vlapic))
+ *data = vlapic->vcpuid;
+ else
+ *data = vlapic->vcpuid << 24;
+ break;
+ case APIC_OFFSET_VER:
+ *data = lapic->version;
+ break;
+ case APIC_OFFSET_TPR:
+ *data = lapic->tpr;
+ break;
+ case APIC_OFFSET_APR:
+ *data = lapic->apr;
+ break;
+ case APIC_OFFSET_PPR:
+ *data = lapic->ppr;
+ break;
+ case APIC_OFFSET_EOI:
+ *data = lapic->eoi;
+ break;
+ case APIC_OFFSET_LDR:
+ *data = lapic->ldr;
+ break;
+ case APIC_OFFSET_DFR:
+ *data = lapic->dfr;
+ break;
+ case APIC_OFFSET_SVR:
+ *data = lapic->svr;
+ break;
+ case APIC_OFFSET_ISR0 ... APIC_OFFSET_ISR7:
+ i = (offset - APIC_OFFSET_ISR0) >> 2;
+ reg = &lapic->isr0;
+ *data = *(reg + i);
+ break;
+ case APIC_OFFSET_TMR0 ... APIC_OFFSET_TMR7:
+ i = (offset - APIC_OFFSET_TMR0) >> 2;
+ reg = &lapic->tmr0;
+ *data = *(reg + i);
+ break;
+ case APIC_OFFSET_IRR0 ... APIC_OFFSET_IRR7:
+ i = (offset - APIC_OFFSET_IRR0) >> 2;
+ reg = &lapic->irr0;
+ *data = atomic_load_acq_int(reg + i);
+ break;
+ case APIC_OFFSET_ESR:
+ *data = lapic->esr;
+ break;
+ case APIC_OFFSET_ICR_LOW:
+ *data = lapic->icr_lo;
+ break;
+ case APIC_OFFSET_ICR_HI:
+ *data = lapic->icr_hi;
+ break;
+ case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
+ reg = vlapic_get_lvt(vlapic, offset);
+ *data = *(reg);
+ break;
+ case APIC_OFFSET_ICR:
+ *data = lapic->icr_timer;
+ break;
+ case APIC_OFFSET_CCR:
+ *data = vlapic_get_ccr(vlapic);
+ break;
+ case APIC_OFFSET_DCR:
+ *data = lapic->dcr_timer;
+ break;
+ case APIC_OFFSET_RRR:
+ default:
+ *data = 0;
+ break;
+ }
+ return 0;
+}
+
+int
+vlapic_op_mem_write(void* dev, uint64_t gpa, opsize_t size, uint64_t data)
+{
+ struct vlapic *vlapic = (struct vlapic*)dev;
+ struct LAPIC *lapic = &vlapic->apic;
+ uint64_t offset = gpa & ~(PAGE_SIZE);
+ uint32_t *reg;
+ int retval;
+
+ if (offset > sizeof(*lapic)) {
+ return 0;
+ }
+
+ retval = 0;
+ offset &= ~3;
+ switch(offset)
+ {
+ case APIC_OFFSET_ID:
+ break;
+ case APIC_OFFSET_TPR:
+ lapic->tpr = data & 0xff;
+ vlapic_update_ppr(vlapic);
+ break;
+ case APIC_OFFSET_EOI:
+ vlapic_process_eoi(vlapic);
+ break;
+ case APIC_OFFSET_LDR:
+ break;
+ case APIC_OFFSET_DFR:
+ break;
+ case APIC_OFFSET_SVR:
+ lapic->svr = data;
+ break;
+ case APIC_OFFSET_ICR_LOW:
+ if (!x2apic(vlapic)) {
+ data &= 0xffffffff;
+ data |= (uint64_t)lapic->icr_hi << 32;
+ }
+ retval = lapic_process_icr(vlapic, data);
+ break;
+ case APIC_OFFSET_ICR_HI:
+ if (!x2apic(vlapic)) {
+ retval = 0;
+ lapic->icr_hi = data;
+ }
+ break;
+ case APIC_OFFSET_TIMER_LVT ... APIC_OFFSET_ERROR_LVT:
+ reg = vlapic_get_lvt(vlapic, offset);
+ if (!(lapic->svr & APIC_SVR_ENABLE)) {
+ data |= APIC_LVT_M;
+ }
+ *reg = data;
+ // vlapic_dump_lvt(offset, reg);
+ break;
+ case APIC_OFFSET_ICR:
+ lapic->icr_timer = data;
+ vlapic_start_timer(vlapic, 0);
+ break;
+
+ case APIC_OFFSET_DCR:
+ lapic->dcr_timer = data;
+ vlapic->divisor = vlapic_timer_divisor(data);
+ break;
+
+ case APIC_OFFSET_ESR:
+ vlapic_update_errors(vlapic);
+ break;
+ case APIC_OFFSET_VER:
+ case APIC_OFFSET_APR:
+ case APIC_OFFSET_PPR:
+ case APIC_OFFSET_RRR:
+ case APIC_OFFSET_ISR0 ... APIC_OFFSET_ISR7:
+ case APIC_OFFSET_TMR0 ... APIC_OFFSET_TMR7:
+ case APIC_OFFSET_IRR0 ... APIC_OFFSET_IRR7:
+ case APIC_OFFSET_CCR:
+ default:
+ // Read only.
+ break;
+ }
+
+ return (retval);
+}
+
+int
+vlapic_timer_tick(struct vlapic *vlapic)
+{
+ int curticks, delta, periodic, fired;
+ uint32_t ccr;
+ uint32_t decrement, leftover;
+
+restart:
+ curticks = ticks;
+ delta = curticks - vlapic->ccr_ticks;
+
+ /* Local APIC timer is disabled */
+ if (vlapic->apic.icr_timer == 0)
+ return (-1);
+
+ /* One-shot mode and timer has already counted down to zero */
+ periodic = vlapic_periodic_timer(vlapic);
+ if (!periodic && vlapic->apic.ccr_timer == 0)
+ return (-1);
+ /*
+ * The 'curticks' and 'ccr_ticks' are out of sync by more than
+ * 2^31 ticks. We deal with this by restarting the timer.
+ */
+ if (delta < 0) {
+ vlapic_start_timer(vlapic, 0);
+ goto restart;
+ }
+
+ fired = 0;
+ decrement = (VLAPIC_BUS_FREQ / vlapic->divisor) / hz;
+
+ vlapic->ccr_ticks = curticks;
+ ccr = vlapic->apic.ccr_timer;
+
+ while (delta-- > 0) {
+ if (ccr > decrement) {
+ ccr -= decrement;
+ continue;
+ }
+
+ /* Trigger the local apic timer interrupt */
+ vlapic_fire_timer(vlapic);
+ if (periodic) {
+ leftover = decrement - ccr;
+ vlapic_start_timer(vlapic, leftover);
+ ccr = vlapic->apic.ccr_timer;
+ } else {
+ /*
+ * One-shot timer has counted down to zero.
+ */
+ ccr = 0;
+ }
+ fired = 1;
+ break;
+ }
+
+ vlapic->apic.ccr_timer = ccr;
+
+ if (!fired)
+ return ((ccr / decrement) + 1);
+ else
+ return (0);
+}
+
+struct vdev_ops vlapic_dev_ops = {
+ .name = "vlapic",
+ .init = vlapic_op_init,
+ .reset = vlapic_op_reset,
+ .halt = vlapic_op_halt,
+ .memread = vlapic_op_mem_read,
+ .memwrite = vlapic_op_mem_write,
+};
+static struct io_region vlapic_mmio[VM_MAXCPU];
+
+struct vlapic *
+vlapic_init(struct vm *vm, int vcpuid)
+{
+ struct vlapic *vlapic;
+
+ vlapic = malloc(sizeof(struct vlapic), M_VLAPIC, M_WAITOK | M_ZERO);
+ vlapic->vm = vm;
+ vlapic->vcpuid = vcpuid;
+
+ vlapic->msr_apicbase = DEFAULT_APIC_BASE | APICBASE_ENABLED;
+
+ if (vcpuid == 0)
+ vlapic->msr_apicbase |= APICBASE_BSP;
+
+ vlapic->ops = &vlapic_dev_ops;
+
+ vlapic->mmio = vlapic_mmio + vcpuid;
+ vlapic->mmio->base = DEFAULT_APIC_BASE;
+ vlapic->mmio->len = PAGE_SIZE;
+ vlapic->mmio->attr = MMIO_READ|MMIO_WRITE;
+ vlapic->mmio->vcpu = vcpuid;
+
+ vdev_register(&vlapic_dev_ops, vlapic);
+
+ vlapic_op_init(vlapic);
+
+ return (vlapic);
+}
+
+void
+vlapic_cleanup(struct vlapic *vlapic)
+{
+ vlapic_op_halt(vlapic);
+ vdev_unregister(vlapic);
+ free(vlapic, M_VLAPIC);
+}
+
+uint64_t
+vlapic_get_apicbase(struct vlapic *vlapic)
+{
+
+ return (vlapic->msr_apicbase);
+}
+
+void
+vlapic_set_apicbase(struct vlapic *vlapic, uint64_t val)
+{
+ int err;
+ enum x2apic_state state;
+
+ err = vm_get_x2apic_state(vlapic->vm, vlapic->vcpuid, &state);
+ if (err)
+ panic("vlapic_set_apicbase: err %d fetching x2apic state", err);
+
+ if (state == X2APIC_DISABLED)
+ val &= ~APICBASE_X2APIC;
+
+ vlapic->msr_apicbase = val;
+}
+
+void
+vlapic_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state)
+{
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, vcpuid);
+
+ if (state == X2APIC_DISABLED)
+ vlapic->msr_apicbase &= ~APICBASE_X2APIC;
+}
diff --git a/sys/amd64/vmm/io/vlapic.h b/sys/amd64/vmm/io/vlapic.h
new file mode 100644
index 0000000..00de019
--- /dev/null
+++ b/sys/amd64/vmm/io/vlapic.h
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VLAPIC_H_
+#define _VLAPIC_H_
+
+#include "vdev.h"
+
+struct vm;
+
+/*
+ * Map of APIC Registers: Offset Description Access
+ */
+#define APIC_OFFSET_ID 0x20 // Local APIC ID R/W
+#define APIC_OFFSET_VER 0x30 // Local APIC Version R
+#define APIC_OFFSET_TPR 0x80 // Task Priority Register R/W
+#define APIC_OFFSET_APR 0x90 // Arbitration Priority Register R
+#define APIC_OFFSET_PPR 0xA0 // Processor Priority Register R
+#define APIC_OFFSET_EOI 0xB0 // EOI Register W
+#define APIC_OFFSET_RRR 0xC0 // Remote read R
+#define APIC_OFFSET_LDR 0xD0 // Logical Destination R/W
+#define APIC_OFFSET_DFR 0xE0 // Destination Format Register 0..27 R; 28..31 R/W
+#define APIC_OFFSET_SVR 0xF0 // Spurious Interrupt Vector Reg. 0..3 R; 4..9 R/W
+#define APIC_OFFSET_ISR0 0x100 // ISR 000-031 R
+#define APIC_OFFSET_ISR1 0x110 // ISR 032-063 R
+#define APIC_OFFSET_ISR2 0x120 // ISR 064-095 R
+#define APIC_OFFSET_ISR3 0x130 // ISR 095-128 R
+#define APIC_OFFSET_ISR4 0x140 // ISR 128-159 R
+#define APIC_OFFSET_ISR5 0x150 // ISR 160-191 R
+#define APIC_OFFSET_ISR6 0x160 // ISR 192-223 R
+#define APIC_OFFSET_ISR7 0x170 // ISR 224-255 R
+#define APIC_OFFSET_TMR0 0x180 // TMR 000-031 R
+#define APIC_OFFSET_TMR1 0x190 // TMR 032-063 R
+#define APIC_OFFSET_TMR2 0x1A0 // TMR 064-095 R
+#define APIC_OFFSET_TMR3 0x1B0 // TMR 095-128 R
+#define APIC_OFFSET_TMR4 0x1C0 // TMR 128-159 R
+#define APIC_OFFSET_TMR5 0x1D0 // TMR 160-191 R
+#define APIC_OFFSET_TMR6 0x1E0 // TMR 192-223 R
+#define APIC_OFFSET_TMR7 0x1F0 // TMR 224-255 R
+#define APIC_OFFSET_IRR0 0x200 // IRR 000-031 R
+#define APIC_OFFSET_IRR1 0x210 // IRR 032-063 R
+#define APIC_OFFSET_IRR2 0x220 // IRR 064-095 R
+#define APIC_OFFSET_IRR3 0x230 // IRR 095-128 R
+#define APIC_OFFSET_IRR4 0x240 // IRR 128-159 R
+#define APIC_OFFSET_IRR5 0x250 // IRR 160-191 R
+#define APIC_OFFSET_IRR6 0x260 // IRR 192-223 R
+#define APIC_OFFSET_IRR7 0x270 // IRR 224-255 R
+#define APIC_OFFSET_ESR 0x280 // Error Status Register R
+#define APIC_OFFSET_ICR_LOW 0x300 // Interrupt Command Reg. (0-31) R/W
+#define APIC_OFFSET_ICR_HI 0x310 // Interrupt Command Reg. (32-63) R/W
+#define APIC_OFFSET_TIMER_LVT 0x320 // Local Vector Table (Timer) R/W
+#define APIC_OFFSET_THERM_LVT 0x330 // Local Vector Table (Thermal) R/W (PIV+)
+#define APIC_OFFSET_PERF_LVT 0x340 // Local Vector Table (Performance) R/W (P6+)
+#define APIC_OFFSET_LINT0_LVT 0x350 // Local Vector Table (LINT0) R/W
+#define APIC_OFFSET_LINT1_LVT 0x360 // Local Vector Table (LINT1) R/W
+#define APIC_OFFSET_ERROR_LVT 0x370 // Local Vector Table (ERROR) R/W
+#define APIC_OFFSET_ICR 0x380 // Initial Count Reg. for Timer R/W
+#define APIC_OFFSET_CCR 0x390 // Current Count of Timer R
+#define APIC_OFFSET_DCR 0x3E0 // Timer Divide Configuration Reg. R/W
+
+/*
+ * 16 priority levels with at most one vector injected per level.
+ */
+#define ISRVEC_STK_SIZE (16 + 1)
+
+enum x2apic_state;
+
+struct vlapic *vlapic_init(struct vm *vm, int vcpuid);
+void vlapic_cleanup(struct vlapic *vlapic);
+
+int vlapic_op_mem_write(void* dev, uint64_t gpa,
+ opsize_t size, uint64_t data);
+
+int vlapic_op_mem_read(void* dev, uint64_t gpa,
+ opsize_t size, uint64_t *data);
+
+int vlapic_pending_intr(struct vlapic *vlapic);
+void vlapic_intr_accepted(struct vlapic *vlapic, int vector);
+void vlapic_set_intr_ready(struct vlapic *vlapic, int vector);
+int vlapic_timer_tick(struct vlapic *vlapic);
+
+uint64_t vlapic_get_apicbase(struct vlapic *vlapic);
+void vlapic_set_apicbase(struct vlapic *vlapic, uint64_t val);
+void vlapic_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state s);
+
+#endif /* _VLAPIC_H_ */
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
new file mode 100644
index 0000000..82d4baa
--- /dev/null
+++ b/sys/amd64/vmm/vmm.c
@@ -0,0 +1,1038 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+#include <sys/pcpu.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
+#include <sys/smp.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+
+#include <machine/vm.h>
+#include <machine/pcb.h>
+#include <machine/smp.h>
+#include <x86/apicreg.h>
+
+#include <machine/vmm.h>
+#include "vmm_host.h"
+#include "vmm_mem.h"
+#include "vmm_util.h"
+#include <machine/vmm_dev.h>
+#include "vlapic.h"
+#include "vmm_msr.h"
+#include "vmm_ipi.h"
+#include "vmm_stat.h"
+#include "vmm_lapic.h"
+
+#include "io/ppt.h"
+#include "io/iommu.h"
+
+struct vlapic;
+
+struct vcpu {
+ int flags;
+ enum vcpu_state state;
+ struct mtx mtx;
+ int pincpu; /* host cpuid this vcpu is bound to */
+ int hostcpu; /* host cpuid this vcpu last ran on */
+ uint64_t guest_msrs[VMM_MSR_NUM];
+ struct vlapic *vlapic;
+ int vcpuid;
+ struct savefpu *guestfpu; /* guest fpu state */
+ void *stats;
+ struct vm_exit exitinfo;
+ enum x2apic_state x2apic_state;
+ int nmi_pending;
+};
+#define VCPU_F_PINNED 0x0001
+
+#define VCPU_PINCPU(vm, vcpuid) \
+ ((vm->vcpu[vcpuid].flags & VCPU_F_PINNED) ? vm->vcpu[vcpuid].pincpu : -1)
+
+#define VCPU_UNPIN(vm, vcpuid) (vm->vcpu[vcpuid].flags &= ~VCPU_F_PINNED)
+
+#define VCPU_PIN(vm, vcpuid, host_cpuid) \
+do { \
+ vm->vcpu[vcpuid].flags |= VCPU_F_PINNED; \
+ vm->vcpu[vcpuid].pincpu = host_cpuid; \
+} while(0)
+
+#define vcpu_lock_init(v) mtx_init(&((v)->mtx), "vcpu lock", 0, MTX_SPIN)
+#define vcpu_lock(v) mtx_lock_spin(&((v)->mtx))
+#define vcpu_unlock(v) mtx_unlock_spin(&((v)->mtx))
+
+#define VM_MAX_MEMORY_SEGMENTS 2
+
+struct vm {
+ void *cookie; /* processor-specific data */
+ void *iommu; /* iommu-specific data */
+ struct vcpu vcpu[VM_MAXCPU];
+ int num_mem_segs;
+ struct vm_memory_segment mem_segs[VM_MAX_MEMORY_SEGMENTS];
+ char name[VM_MAX_NAMELEN];
+
+ /*
+ * Set of active vcpus.
+ * An active vcpu is one that has been started implicitly (BSP) or
+ * explicitly (AP) by sending it a startup ipi.
+ */
+ cpuset_t active_cpus;
+};
+
+static struct vmm_ops *ops;
+#define VMM_INIT() (ops != NULL ? (*ops->init)() : 0)
+#define VMM_CLEANUP() (ops != NULL ? (*ops->cleanup)() : 0)
+
+#define VMINIT(vm) (ops != NULL ? (*ops->vminit)(vm): NULL)
+#define VMRUN(vmi, vcpu, rip) \
+ (ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip) : ENXIO)
+#define VMCLEANUP(vmi) (ops != NULL ? (*ops->vmcleanup)(vmi) : NULL)
+#define VMMMAP_SET(vmi, gpa, hpa, len, attr, prot, spm) \
+ (ops != NULL ? \
+ (*ops->vmmmap_set)(vmi, gpa, hpa, len, attr, prot, spm) : \
+ ENXIO)
+#define VMMMAP_GET(vmi, gpa) \
+ (ops != NULL ? (*ops->vmmmap_get)(vmi, gpa) : ENXIO)
+#define VMGETREG(vmi, vcpu, num, retval) \
+ (ops != NULL ? (*ops->vmgetreg)(vmi, vcpu, num, retval) : ENXIO)
+#define VMSETREG(vmi, vcpu, num, val) \
+ (ops != NULL ? (*ops->vmsetreg)(vmi, vcpu, num, val) : ENXIO)
+#define VMGETDESC(vmi, vcpu, num, desc) \
+ (ops != NULL ? (*ops->vmgetdesc)(vmi, vcpu, num, desc) : ENXIO)
+#define VMSETDESC(vmi, vcpu, num, desc) \
+ (ops != NULL ? (*ops->vmsetdesc)(vmi, vcpu, num, desc) : ENXIO)
+#define VMINJECT(vmi, vcpu, type, vec, ec, ecv) \
+ (ops != NULL ? (*ops->vminject)(vmi, vcpu, type, vec, ec, ecv) : ENXIO)
+#define VMGETCAP(vmi, vcpu, num, retval) \
+ (ops != NULL ? (*ops->vmgetcap)(vmi, vcpu, num, retval) : ENXIO)
+#define VMSETCAP(vmi, vcpu, num, val) \
+ (ops != NULL ? (*ops->vmsetcap)(vmi, vcpu, num, val) : ENXIO)
+
+#define fpu_start_emulating() load_cr0(rcr0() | CR0_TS)
+#define fpu_stop_emulating() clts()
+
+static MALLOC_DEFINE(M_VM, "vm", "vm");
+CTASSERT(VMM_MSR_NUM <= 64); /* msr_mask can keep track of up to 64 msrs */
+
+/* statistics */
+static VMM_STAT_DEFINE(VCPU_TOTAL_RUNTIME, "vcpu total runtime");
+
+static void
+vcpu_cleanup(struct vcpu *vcpu)
+{
+ vlapic_cleanup(vcpu->vlapic);
+ vmm_stat_free(vcpu->stats);
+ fpu_save_area_free(vcpu->guestfpu);
+}
+
+static void
+vcpu_init(struct vm *vm, uint32_t vcpu_id)
+{
+ struct vcpu *vcpu;
+
+ vcpu = &vm->vcpu[vcpu_id];
+
+ vcpu_lock_init(vcpu);
+ vcpu->hostcpu = NOCPU;
+ vcpu->vcpuid = vcpu_id;
+ vcpu->vlapic = vlapic_init(vm, vcpu_id);
+ vm_set_x2apic_state(vm, vcpu_id, X2APIC_ENABLED);
+ vcpu->guestfpu = fpu_save_area_alloc();
+ fpu_save_area_reset(vcpu->guestfpu);
+ vcpu->stats = vmm_stat_alloc();
+}
+
+struct vm_exit *
+vm_exitinfo(struct vm *vm, int cpuid)
+{
+ struct vcpu *vcpu;
+
+ if (cpuid < 0 || cpuid >= VM_MAXCPU)
+ panic("vm_exitinfo: invalid cpuid %d", cpuid);
+
+ vcpu = &vm->vcpu[cpuid];
+
+ return (&vcpu->exitinfo);
+}
+
+static int
+vmm_init(void)
+{
+ int error;
+
+ vmm_host_state_init();
+ vmm_ipi_init();
+
+ error = vmm_mem_init();
+ if (error)
+ return (error);
+
+ if (vmm_is_intel())
+ ops = &vmm_ops_intel;
+ else if (vmm_is_amd())
+ ops = &vmm_ops_amd;
+ else
+ return (ENXIO);
+
+ vmm_msr_init();
+
+ return (VMM_INIT());
+}
+
+static int
+vmm_handler(module_t mod, int what, void *arg)
+{
+ int error;
+
+ switch (what) {
+ case MOD_LOAD:
+ vmmdev_init();
+ iommu_init();
+ error = vmm_init();
+ break;
+ case MOD_UNLOAD:
+ error = vmmdev_cleanup();
+ if (error == 0) {
+ iommu_cleanup();
+ vmm_ipi_cleanup();
+ error = VMM_CLEANUP();
+ }
+ break;
+ default:
+ error = 0;
+ break;
+ }
+ return (error);
+}
+
+static moduledata_t vmm_kmod = {
+ "vmm",
+ vmm_handler,
+ NULL
+};
+
+/*
+ * vmm initialization has the following dependencies:
+ *
+ * - iommu initialization must happen after the pci passthru driver has had
+ * a chance to attach to any passthru devices (after SI_SUB_CONFIGURE).
+ *
+ * - VT-x initialization requires smp_rendezvous() and therefore must happen
+ * after SMP is fully functional (after SI_SUB_SMP).
+ */
+DECLARE_MODULE(vmm, vmm_kmod, SI_SUB_SMP + 1, SI_ORDER_ANY);
+MODULE_VERSION(vmm, 1);
+
+SYSCTL_NODE(_hw, OID_AUTO, vmm, CTLFLAG_RW, NULL, NULL);
+
+struct vm *
+vm_create(const char *name)
+{
+ int i;
+ struct vm *vm;
+ vm_paddr_t maxaddr;
+
+ const int BSP = 0;
+
+ if (name == NULL || strlen(name) >= VM_MAX_NAMELEN)
+ return (NULL);
+
+ vm = malloc(sizeof(struct vm), M_VM, M_WAITOK | M_ZERO);
+ strcpy(vm->name, name);
+ vm->cookie = VMINIT(vm);
+
+ for (i = 0; i < VM_MAXCPU; i++) {
+ vcpu_init(vm, i);
+ guest_msrs_init(vm, i);
+ }
+
+ maxaddr = vmm_mem_maxaddr();
+ vm->iommu = iommu_create_domain(maxaddr);
+ vm_activate_cpu(vm, BSP);
+
+ return (vm);
+}
+
+static void
+vm_free_mem_seg(struct vm *vm, struct vm_memory_segment *seg)
+{
+ size_t len;
+ vm_paddr_t hpa;
+ void *host_domain;
+
+ host_domain = iommu_host_domain();
+
+ len = 0;
+ while (len < seg->len) {
+ hpa = vm_gpa2hpa(vm, seg->gpa + len, PAGE_SIZE);
+ if (hpa == (vm_paddr_t)-1) {
+ panic("vm_free_mem_segs: cannot free hpa "
+ "associated with gpa 0x%016lx", seg->gpa + len);
+ }
+
+ /*
+ * Remove the 'gpa' to 'hpa' mapping in VMs domain.
+ * And resurrect the 1:1 mapping for 'hpa' in 'host_domain'.
+ */
+ iommu_remove_mapping(vm->iommu, seg->gpa + len, PAGE_SIZE);
+ iommu_create_mapping(host_domain, hpa, hpa, PAGE_SIZE);
+
+ vmm_mem_free(hpa, PAGE_SIZE);
+
+ len += PAGE_SIZE;
+ }
+
+ /*
+ * Invalidate cached translations associated with 'vm->iommu' since
+ * we have now moved some pages from it.
+ */
+ iommu_invalidate_tlb(vm->iommu);
+
+ bzero(seg, sizeof(struct vm_memory_segment));
+}
+
+void
+vm_destroy(struct vm *vm)
+{
+ int i;
+
+ ppt_unassign_all(vm);
+
+ for (i = 0; i < vm->num_mem_segs; i++)
+ vm_free_mem_seg(vm, &vm->mem_segs[i]);
+
+ vm->num_mem_segs = 0;
+
+ for (i = 0; i < VM_MAXCPU; i++)
+ vcpu_cleanup(&vm->vcpu[i]);
+
+ iommu_destroy_domain(vm->iommu);
+
+ VMCLEANUP(vm->cookie);
+
+ free(vm, M_VM);
+}
+
+const char *
+vm_name(struct vm *vm)
+{
+ return (vm->name);
+}
+
+int
+vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa)
+{
+ const boolean_t spok = TRUE; /* superpage mappings are ok */
+
+ return (VMMMAP_SET(vm->cookie, gpa, hpa, len, VM_MEMATTR_UNCACHEABLE,
+ VM_PROT_RW, spok));
+}
+
+int
+vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len)
+{
+ const boolean_t spok = TRUE; /* superpage mappings are ok */
+
+ return (VMMMAP_SET(vm->cookie, gpa, 0, len, 0,
+ VM_PROT_NONE, spok));
+}
+
+/*
+ * Returns TRUE if 'gpa' is available for allocation and FALSE otherwise
+ */
+static boolean_t
+vm_gpa_available(struct vm *vm, vm_paddr_t gpa)
+{
+ int i;
+ vm_paddr_t gpabase, gpalimit;
+
+ if (gpa & PAGE_MASK)
+ panic("vm_gpa_available: gpa (0x%016lx) not page aligned", gpa);
+
+ for (i = 0; i < vm->num_mem_segs; i++) {
+ gpabase = vm->mem_segs[i].gpa;
+ gpalimit = gpabase + vm->mem_segs[i].len;
+ if (gpa >= gpabase && gpa < gpalimit)
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+int
+vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len)
+{
+ int error, available, allocated;
+ struct vm_memory_segment *seg;
+ vm_paddr_t g, hpa;
+ void *host_domain;
+
+ const boolean_t spok = TRUE; /* superpage mappings are ok */
+
+ if ((gpa & PAGE_MASK) || (len & PAGE_MASK) || len == 0)
+ return (EINVAL);
+
+ available = allocated = 0;
+ g = gpa;
+ while (g < gpa + len) {
+ if (vm_gpa_available(vm, g))
+ available++;
+ else
+ allocated++;
+
+ g += PAGE_SIZE;
+ }
+
+ /*
+ * If there are some allocated and some available pages in the address
+ * range then it is an error.
+ */
+ if (allocated && available)
+ return (EINVAL);
+
+ /*
+ * If the entire address range being requested has already been
+ * allocated then there isn't anything more to do.
+ */
+ if (allocated && available == 0)
+ return (0);
+
+ if (vm->num_mem_segs >= VM_MAX_MEMORY_SEGMENTS)
+ return (E2BIG);
+
+ host_domain = iommu_host_domain();
+
+ seg = &vm->mem_segs[vm->num_mem_segs];
+
+ error = 0;
+ seg->gpa = gpa;
+ seg->len = 0;
+ while (seg->len < len) {
+ hpa = vmm_mem_alloc(PAGE_SIZE);
+ if (hpa == 0) {
+ error = ENOMEM;
+ break;
+ }
+
+ error = VMMMAP_SET(vm->cookie, gpa + seg->len, hpa, PAGE_SIZE,
+ VM_MEMATTR_WRITE_BACK, VM_PROT_ALL, spok);
+ if (error)
+ break;
+
+ /*
+ * Remove the 1:1 mapping for 'hpa' from the 'host_domain'.
+ * Add mapping for 'gpa + seg->len' to 'hpa' in the VMs domain.
+ */
+ iommu_remove_mapping(host_domain, hpa, PAGE_SIZE);
+ iommu_create_mapping(vm->iommu, gpa + seg->len, hpa, PAGE_SIZE);
+
+ seg->len += PAGE_SIZE;
+ }
+
+ if (error) {
+ vm_free_mem_seg(vm, seg);
+ return (error);
+ }
+
+ /*
+ * Invalidate cached translations associated with 'host_domain' since
+ * we have now moved some pages from it.
+ */
+ iommu_invalidate_tlb(host_domain);
+
+ vm->num_mem_segs++;
+
+ return (0);
+}
+
+vm_paddr_t
+vm_gpa2hpa(struct vm *vm, vm_paddr_t gpa, size_t len)
+{
+ vm_paddr_t nextpage;
+
+ nextpage = rounddown(gpa + PAGE_SIZE, PAGE_SIZE);
+ if (len > nextpage - gpa)
+ panic("vm_gpa2hpa: invalid gpa/len: 0x%016lx/%lu", gpa, len);
+
+ return (VMMMAP_GET(vm->cookie, gpa));
+}
+
+int
+vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase,
+ struct vm_memory_segment *seg)
+{
+ int i;
+
+ for (i = 0; i < vm->num_mem_segs; i++) {
+ if (gpabase == vm->mem_segs[i].gpa) {
+ *seg = vm->mem_segs[i];
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+int
+vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval)
+{
+
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (reg >= VM_REG_LAST)
+ return (EINVAL);
+
+ return (VMGETREG(vm->cookie, vcpu, reg, retval));
+}
+
+int
+vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val)
+{
+
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (reg >= VM_REG_LAST)
+ return (EINVAL);
+
+ return (VMSETREG(vm->cookie, vcpu, reg, val));
+}
+
+static boolean_t
+is_descriptor_table(int reg)
+{
+
+ switch (reg) {
+ case VM_REG_GUEST_IDTR:
+ case VM_REG_GUEST_GDTR:
+ return (TRUE);
+ default:
+ return (FALSE);
+ }
+}
+
+static boolean_t
+is_segment_register(int reg)
+{
+
+ switch (reg) {
+ case VM_REG_GUEST_ES:
+ case VM_REG_GUEST_CS:
+ case VM_REG_GUEST_SS:
+ case VM_REG_GUEST_DS:
+ case VM_REG_GUEST_FS:
+ case VM_REG_GUEST_GS:
+ case VM_REG_GUEST_TR:
+ case VM_REG_GUEST_LDTR:
+ return (TRUE);
+ default:
+ return (FALSE);
+ }
+}
+
+int
+vm_get_seg_desc(struct vm *vm, int vcpu, int reg,
+ struct seg_desc *desc)
+{
+
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (!is_segment_register(reg) && !is_descriptor_table(reg))
+ return (EINVAL);
+
+ return (VMGETDESC(vm->cookie, vcpu, reg, desc));
+}
+
+int
+vm_set_seg_desc(struct vm *vm, int vcpu, int reg,
+ struct seg_desc *desc)
+{
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (!is_segment_register(reg) && !is_descriptor_table(reg))
+ return (EINVAL);
+
+ return (VMSETDESC(vm->cookie, vcpu, reg, desc));
+}
+
+int
+vm_get_pinning(struct vm *vm, int vcpuid, int *cpuid)
+{
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ *cpuid = VCPU_PINCPU(vm, vcpuid);
+
+ return (0);
+}
+
+int
+vm_set_pinning(struct vm *vm, int vcpuid, int host_cpuid)
+{
+ struct thread *td;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ td = curthread; /* XXXSMP only safe when muxing vcpus */
+
+ /* unpin */
+ if (host_cpuid < 0) {
+ VCPU_UNPIN(vm, vcpuid);
+ thread_lock(td);
+ sched_unbind(td);
+ thread_unlock(td);
+ return (0);
+ }
+
+ if (CPU_ABSENT(host_cpuid))
+ return (EINVAL);
+
+ /*
+ * XXX we should check that 'host_cpuid' has not already been pinned
+ * by another vm.
+ */
+ thread_lock(td);
+ sched_bind(td, host_cpuid);
+ thread_unlock(td);
+ VCPU_PIN(vm, vcpuid, host_cpuid);
+
+ return (0);
+}
+
+static void
+restore_guest_fpustate(struct vcpu *vcpu)
+{
+
+ /* flush host state to the pcb */
+ fpuexit(curthread);
+
+ /* restore guest FPU state */
+ fpu_stop_emulating();
+ fpurestore(vcpu->guestfpu);
+
+ /*
+ * The FPU is now "dirty" with the guest's state so turn on emulation
+ * to trap any access to the FPU by the host.
+ */
+ fpu_start_emulating();
+}
+
+static void
+save_guest_fpustate(struct vcpu *vcpu)
+{
+
+ if ((rcr0() & CR0_TS) == 0)
+ panic("fpu emulation not enabled in host!");
+
+ /* save guest FPU state */
+ fpu_stop_emulating();
+ fpusave(vcpu->guestfpu);
+ fpu_start_emulating();
+}
+
+static VMM_STAT_DEFINE(VCPU_IDLE_TICKS, "number of ticks vcpu was idle");
+
+int
+vm_run(struct vm *vm, struct vm_run *vmrun)
+{
+ int error, vcpuid, sleepticks, t;
+ struct vcpu *vcpu;
+ struct pcb *pcb;
+ uint64_t tscval, rip;
+ struct vm_exit *vme;
+
+ vcpuid = vmrun->cpuid;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ vcpu = &vm->vcpu[vcpuid];
+ vme = &vmrun->vm_exit;
+ rip = vmrun->rip;
+restart:
+ critical_enter();
+
+ tscval = rdtsc();
+
+ pcb = PCPU_GET(curpcb);
+ set_pcb_flags(pcb, PCB_FULL_IRET);
+
+ restore_guest_msrs(vm, vcpuid);
+ restore_guest_fpustate(vcpu);
+
+ vcpu->hostcpu = curcpu;
+ error = VMRUN(vm->cookie, vcpuid, rip);
+ vcpu->hostcpu = NOCPU;
+
+ save_guest_fpustate(vcpu);
+ restore_host_msrs(vm, vcpuid);
+
+ vmm_stat_incr(vm, vcpuid, VCPU_TOTAL_RUNTIME, rdtsc() - tscval);
+
+ /* copy the exit information */
+ bcopy(&vcpu->exitinfo, vme, sizeof(struct vm_exit));
+
+ critical_exit();
+
+ /*
+ * Oblige the guest's desire to 'hlt' by sleeping until the vcpu
+ * is ready to run.
+ */
+ if (error == 0 && vme->exitcode == VM_EXITCODE_HLT) {
+ vcpu_lock(vcpu);
+
+ /*
+ * Figure out the number of host ticks until the next apic
+ * timer interrupt in the guest.
+ */
+ sleepticks = lapic_timer_tick(vm, vcpuid);
+
+ /*
+ * If the guest local apic timer is disabled then sleep for
+ * a long time but not forever.
+ */
+ if (sleepticks < 0)
+ sleepticks = hz;
+
+ /*
+ * Do a final check for pending NMI or interrupts before
+ * really putting this thread to sleep.
+ *
+ * These interrupts could have happened any time after we
+ * returned from VMRUN() and before we grabbed the vcpu lock.
+ */
+ if (!vm_nmi_pending(vm, vcpuid) &&
+ lapic_pending_intr(vm, vcpuid) < 0) {
+ if (sleepticks <= 0)
+ panic("invalid sleepticks %d", sleepticks);
+ t = ticks;
+ msleep_spin(vcpu, &vcpu->mtx, "vmidle", sleepticks);
+ vmm_stat_incr(vm, vcpuid, VCPU_IDLE_TICKS, ticks - t);
+ }
+
+ vcpu_unlock(vcpu);
+
+ rip = vme->rip + vme->inst_length;
+ goto restart;
+ }
+
+ return (error);
+}
+
+int
+vm_inject_event(struct vm *vm, int vcpuid, int type,
+ int vector, uint32_t code, int code_valid)
+{
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ if ((type > VM_EVENT_NONE && type < VM_EVENT_MAX) == 0)
+ return (EINVAL);
+
+ if (vector < 0 || vector > 255)
+ return (EINVAL);
+
+ return (VMINJECT(vm->cookie, vcpuid, type, vector, code, code_valid));
+}
+
+static VMM_STAT_DEFINE(VCPU_NMI_COUNT, "number of NMIs delivered to vcpu");
+
+int
+vm_inject_nmi(struct vm *vm, int vcpuid)
+{
+ struct vcpu *vcpu;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ vcpu->nmi_pending = 1;
+ vm_interrupt_hostcpu(vm, vcpuid);
+ return (0);
+}
+
+int
+vm_nmi_pending(struct vm *vm, int vcpuid)
+{
+ struct vcpu *vcpu;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ panic("vm_nmi_pending: invalid vcpuid %d", vcpuid);
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ return (vcpu->nmi_pending);
+}
+
+void
+vm_nmi_clear(struct vm *vm, int vcpuid)
+{
+ struct vcpu *vcpu;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ panic("vm_nmi_pending: invalid vcpuid %d", vcpuid);
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ if (vcpu->nmi_pending == 0)
+ panic("vm_nmi_clear: inconsistent nmi_pending state");
+
+ vcpu->nmi_pending = 0;
+ vmm_stat_incr(vm, vcpuid, VCPU_NMI_COUNT, 1);
+}
+
+int
+vm_get_capability(struct vm *vm, int vcpu, int type, int *retval)
+{
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (type < 0 || type >= VM_CAP_MAX)
+ return (EINVAL);
+
+ return (VMGETCAP(vm->cookie, vcpu, type, retval));
+}
+
+int
+vm_set_capability(struct vm *vm, int vcpu, int type, int val)
+{
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (type < 0 || type >= VM_CAP_MAX)
+ return (EINVAL);
+
+ return (VMSETCAP(vm->cookie, vcpu, type, val));
+}
+
+uint64_t *
+vm_guest_msrs(struct vm *vm, int cpu)
+{
+ return (vm->vcpu[cpu].guest_msrs);
+}
+
+struct vlapic *
+vm_lapic(struct vm *vm, int cpu)
+{
+ return (vm->vcpu[cpu].vlapic);
+}
+
+boolean_t
+vmm_is_pptdev(int bus, int slot, int func)
+{
+ int found, i, n;
+ int b, s, f;
+ char *val, *cp, *cp2;
+
+ /*
+ * XXX
+ * The length of an environment variable is limited to 128 bytes which
+ * puts an upper limit on the number of passthru devices that may be
+ * specified using a single environment variable.
+ *
+ * Work around this by scanning multiple environment variable
+ * names instead of a single one - yuck!
+ */
+ const char *names[] = { "pptdevs", "pptdevs2", "pptdevs3", NULL };
+
+ /* set pptdevs="1/2/3 4/5/6 7/8/9 10/11/12" */
+ found = 0;
+ for (i = 0; names[i] != NULL && !found; i++) {
+ cp = val = getenv(names[i]);
+ while (cp != NULL && *cp != '\0') {
+ if ((cp2 = strchr(cp, ' ')) != NULL)
+ *cp2 = '\0';
+
+ n = sscanf(cp, "%d/%d/%d", &b, &s, &f);
+ if (n == 3 && bus == b && slot == s && func == f) {
+ found = 1;
+ break;
+ }
+
+ if (cp2 != NULL)
+ *cp2++ = ' ';
+
+ cp = cp2;
+ }
+ freeenv(val);
+ }
+ return (found);
+}
+
+void *
+vm_iommu_domain(struct vm *vm)
+{
+
+ return (vm->iommu);
+}
+
+int
+vcpu_set_state(struct vm *vm, int vcpuid, enum vcpu_state state)
+{
+ int error;
+ struct vcpu *vcpu;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ panic("vm_set_run_state: invalid vcpuid %d", vcpuid);
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ vcpu_lock(vcpu);
+
+ /*
+ * The following state transitions are allowed:
+ * IDLE -> RUNNING -> IDLE
+ * IDLE -> CANNOT_RUN -> IDLE
+ */
+ if ((vcpu->state == VCPU_IDLE && state != VCPU_IDLE) ||
+ (vcpu->state != VCPU_IDLE && state == VCPU_IDLE)) {
+ error = 0;
+ vcpu->state = state;
+ } else {
+ error = EBUSY;
+ }
+
+ vcpu_unlock(vcpu);
+
+ return (error);
+}
+
+enum vcpu_state
+vcpu_get_state(struct vm *vm, int vcpuid)
+{
+ struct vcpu *vcpu;
+ enum vcpu_state state;
+
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ panic("vm_get_run_state: invalid vcpuid %d", vcpuid);
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ vcpu_lock(vcpu);
+ state = vcpu->state;
+ vcpu_unlock(vcpu);
+
+ return (state);
+}
+
+void
+vm_activate_cpu(struct vm *vm, int vcpuid)
+{
+
+ if (vcpuid >= 0 && vcpuid < VM_MAXCPU)
+ CPU_SET(vcpuid, &vm->active_cpus);
+}
+
+cpuset_t
+vm_active_cpus(struct vm *vm)
+{
+
+ return (vm->active_cpus);
+}
+
+void *
+vcpu_stats(struct vm *vm, int vcpuid)
+{
+
+ return (vm->vcpu[vcpuid].stats);
+}
+
+int
+vm_get_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state *state)
+{
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ *state = vm->vcpu[vcpuid].x2apic_state;
+
+ return (0);
+}
+
+int
+vm_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state)
+{
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (state < 0 || state >= X2APIC_STATE_LAST)
+ return (EINVAL);
+
+ vm->vcpu[vcpuid].x2apic_state = state;
+
+ vlapic_set_x2apic_state(vm, vcpuid, state);
+
+ return (0);
+}
+
+void
+vm_interrupt_hostcpu(struct vm *vm, int vcpuid)
+{
+ int hostcpu;
+ struct vcpu *vcpu;
+
+ vcpu = &vm->vcpu[vcpuid];
+
+ vcpu_lock(vcpu);
+ hostcpu = vcpu->hostcpu;
+ if (hostcpu == NOCPU) {
+ /*
+ * If the vcpu is 'RUNNING' but without a valid 'hostcpu' then
+ * the host thread must be sleeping waiting for an event to
+ * kick the vcpu out of 'hlt'.
+ *
+ * XXX this is racy because the condition exists right before
+ * and after calling VMRUN() in vm_run(). The wakeup() is
+ * benign in this case.
+ */
+ if (vcpu->state == VCPU_RUNNING)
+ wakeup_one(vcpu);
+ } else {
+ if (vcpu->state != VCPU_RUNNING)
+ panic("invalid vcpu state %d", vcpu->state);
+ if (hostcpu != curcpu)
+ ipi_cpu(hostcpu, vmm_ipinum);
+ }
+ vcpu_unlock(vcpu);
+}
diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c
new file mode 100644
index 0000000..0150ebd
--- /dev/null
+++ b/sys/amd64/vmm/vmm_dev.c
@@ -0,0 +1,538 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/malloc.h>
+#include <sys/conf.h>
+#include <sys/sysctl.h>
+#include <sys/libkern.h>
+#include <sys/ioccom.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+
+#include <machine/vmm.h>
+#include "vmm_lapic.h"
+#include "vmm_stat.h"
+#include "vmm_mem.h"
+#include "io/ppt.h"
+#include <machine/vmm_dev.h>
+
+struct vmmdev_softc {
+ struct vm *vm; /* vm instance cookie */
+ struct cdev *cdev;
+ SLIST_ENTRY(vmmdev_softc) link;
+};
+static SLIST_HEAD(, vmmdev_softc) head;
+
+static struct mtx vmmdev_mtx;
+
+static MALLOC_DEFINE(M_VMMDEV, "vmmdev", "vmmdev");
+
+SYSCTL_DECL(_hw_vmm);
+
+static struct vmmdev_softc *
+vmmdev_lookup(const char *name)
+{
+ struct vmmdev_softc *sc;
+
+#ifdef notyet /* XXX kernel is not compiled with invariants */
+ mtx_assert(&vmmdev_mtx, MA_OWNED);
+#endif
+
+ SLIST_FOREACH(sc, &head, link) {
+ if (strcmp(name, vm_name(sc->vm)) == 0)
+ break;
+ }
+
+ return (sc);
+}
+
+static struct vmmdev_softc *
+vmmdev_lookup2(struct cdev *cdev)
+{
+
+ return (cdev->si_drv1);
+}
+
+static int
+vmmdev_rw(struct cdev *cdev, struct uio *uio, int flags)
+{
+ int error, off, c;
+ vm_paddr_t hpa, gpa;
+ struct vmmdev_softc *sc;
+
+ static char zerobuf[PAGE_SIZE];
+
+ error = 0;
+ mtx_lock(&vmmdev_mtx);
+ sc = vmmdev_lookup2(cdev);
+ if (sc == NULL)
+ error = ENXIO;
+
+ while (uio->uio_resid > 0 && error == 0) {
+ gpa = uio->uio_offset;
+ off = gpa & PAGE_MASK;
+ c = min(uio->uio_resid, PAGE_SIZE - off);
+
+ /*
+ * The VM has a hole in its physical memory map. If we want to
+ * use 'dd' to inspect memory beyond the hole we need to
+ * provide bogus data for memory that lies in the hole.
+ *
+ * Since this device does not support lseek(2), dd(1) will
+ * read(2) blocks of data to simulate the lseek(2).
+ */
+ hpa = vm_gpa2hpa(sc->vm, gpa, c);
+ if (hpa == (vm_paddr_t)-1) {
+ if (uio->uio_rw == UIO_READ)
+ error = uiomove(zerobuf, c, uio);
+ else
+ error = EFAULT;
+ } else
+ error = uiomove((void *)PHYS_TO_DMAP(hpa), c, uio);
+ }
+
+ mtx_unlock(&vmmdev_mtx);
+ return (error);
+}
+
+static int
+vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
+ struct thread *td)
+{
+ int error, vcpu, state_changed;
+ enum vcpu_state new_state;
+ struct vmmdev_softc *sc;
+ struct vm_memory_segment *seg;
+ struct vm_register *vmreg;
+ struct vm_seg_desc* vmsegdesc;
+ struct vm_pin *vmpin;
+ struct vm_run *vmrun;
+ struct vm_event *vmevent;
+ struct vm_lapic_irq *vmirq;
+ struct vm_capability *vmcap;
+ struct vm_pptdev *pptdev;
+ struct vm_pptdev_mmio *pptmmio;
+ struct vm_pptdev_msi *pptmsi;
+ struct vm_pptdev_msix *pptmsix;
+ struct vm_nmi *vmnmi;
+ struct vm_stats *vmstats;
+ struct vm_stat_desc *statdesc;
+ struct vm_x2apic *x2apic;
+
+ sc = vmmdev_lookup2(cdev);
+ if (sc == NULL)
+ return (ENXIO);
+
+ vcpu = -1;
+ state_changed = 0;
+
+ /*
+ * Some VMM ioctls can operate only on vcpus that are not running.
+ */
+ switch (cmd) {
+ case VM_RUN:
+ case VM_SET_PINNING:
+ case VM_GET_REGISTER:
+ case VM_SET_REGISTER:
+ case VM_GET_SEGMENT_DESCRIPTOR:
+ case VM_SET_SEGMENT_DESCRIPTOR:
+ case VM_INJECT_EVENT:
+ case VM_GET_CAPABILITY:
+ case VM_SET_CAPABILITY:
+ case VM_PPTDEV_MSI:
+ case VM_PPTDEV_MSIX:
+ case VM_SET_X2APIC_STATE:
+ /*
+ * XXX fragile, handle with care
+ * Assumes that the first field of the ioctl data is the vcpu.
+ */
+ vcpu = *(int *)data;
+ if (vcpu < 0 || vcpu >= VM_MAXCPU) {
+ error = EINVAL;
+ goto done;
+ }
+
+ if (cmd == VM_RUN)
+ new_state = VCPU_RUNNING;
+ else
+ new_state = VCPU_CANNOT_RUN;
+
+ error = vcpu_set_state(sc->vm, vcpu, new_state);
+ if (error)
+ goto done;
+
+ state_changed = 1;
+ break;
+
+ case VM_MAP_PPTDEV_MMIO:
+ case VM_BIND_PPTDEV:
+ case VM_UNBIND_PPTDEV:
+ case VM_MAP_MEMORY:
+ /*
+ * ioctls that operate on the entire virtual machine must
+ * prevent all vcpus from running.
+ */
+ error = 0;
+ for (vcpu = 0; vcpu < VM_MAXCPU; vcpu++) {
+ error = vcpu_set_state(sc->vm, vcpu, VCPU_CANNOT_RUN);
+ if (error)
+ break;
+ }
+
+ if (error) {
+ while (--vcpu >= 0)
+ vcpu_set_state(sc->vm, vcpu, VCPU_IDLE);
+ goto done;
+ }
+
+ state_changed = 2;
+ break;
+
+ default:
+ break;
+ }
+
+ switch(cmd) {
+ case VM_RUN:
+ vmrun = (struct vm_run *)data;
+ error = vm_run(sc->vm, vmrun);
+ break;
+ case VM_STAT_DESC: {
+ const char *desc;
+ statdesc = (struct vm_stat_desc *)data;
+ desc = vmm_stat_desc(statdesc->index);
+ if (desc != NULL) {
+ error = 0;
+ strlcpy(statdesc->desc, desc, sizeof(statdesc->desc));
+ } else
+ error = EINVAL;
+ break;
+ }
+ case VM_STATS: {
+ CTASSERT(MAX_VM_STATS >= MAX_VMM_STAT_TYPES);
+ vmstats = (struct vm_stats *)data;
+ getmicrotime(&vmstats->tv);
+ error = vmm_stat_copy(sc->vm, vmstats->cpuid,
+ &vmstats->num_entries, vmstats->statbuf);
+ break;
+ }
+ case VM_PPTDEV_MSI:
+ pptmsi = (struct vm_pptdev_msi *)data;
+ error = ppt_setup_msi(sc->vm, pptmsi->vcpu,
+ pptmsi->bus, pptmsi->slot, pptmsi->func,
+ pptmsi->destcpu, pptmsi->vector,
+ pptmsi->numvec);
+ break;
+ case VM_PPTDEV_MSIX:
+ pptmsix = (struct vm_pptdev_msix *)data;
+ error = ppt_setup_msix(sc->vm, pptmsix->vcpu,
+ pptmsix->bus, pptmsix->slot,
+ pptmsix->func, pptmsix->idx,
+ pptmsix->msg, pptmsix->vector_control,
+ pptmsix->addr);
+ break;
+ case VM_MAP_PPTDEV_MMIO:
+ pptmmio = (struct vm_pptdev_mmio *)data;
+ error = ppt_map_mmio(sc->vm, pptmmio->bus, pptmmio->slot,
+ pptmmio->func, pptmmio->gpa, pptmmio->len,
+ pptmmio->hpa);
+ break;
+ case VM_BIND_PPTDEV:
+ pptdev = (struct vm_pptdev *)data;
+ error = ppt_assign_device(sc->vm, pptdev->bus, pptdev->slot,
+ pptdev->func);
+ break;
+ case VM_UNBIND_PPTDEV:
+ pptdev = (struct vm_pptdev *)data;
+ error = ppt_unassign_device(sc->vm, pptdev->bus, pptdev->slot,
+ pptdev->func);
+ break;
+ case VM_INJECT_EVENT:
+ vmevent = (struct vm_event *)data;
+ error = vm_inject_event(sc->vm, vmevent->cpuid, vmevent->type,
+ vmevent->vector,
+ vmevent->error_code,
+ vmevent->error_code_valid);
+ break;
+ case VM_INJECT_NMI:
+ vmnmi = (struct vm_nmi *)data;
+ error = vm_inject_nmi(sc->vm, vmnmi->cpuid);
+ break;
+ case VM_LAPIC_IRQ:
+ vmirq = (struct vm_lapic_irq *)data;
+ error = lapic_set_intr(sc->vm, vmirq->cpuid, vmirq->vector);
+ break;
+ case VM_SET_PINNING:
+ vmpin = (struct vm_pin *)data;
+ error = vm_set_pinning(sc->vm, vmpin->vm_cpuid,
+ vmpin->host_cpuid);
+ break;
+ case VM_GET_PINNING:
+ vmpin = (struct vm_pin *)data;
+ error = vm_get_pinning(sc->vm, vmpin->vm_cpuid,
+ &vmpin->host_cpuid);
+ break;
+ case VM_MAP_MEMORY:
+ seg = (struct vm_memory_segment *)data;
+ error = vm_malloc(sc->vm, seg->gpa, seg->len);
+ break;
+ case VM_GET_MEMORY_SEG:
+ seg = (struct vm_memory_segment *)data;
+ seg->len = 0;
+ (void)vm_gpabase2memseg(sc->vm, seg->gpa, seg);
+ error = 0;
+ break;
+ case VM_GET_REGISTER:
+ vmreg = (struct vm_register *)data;
+ error = vm_get_register(sc->vm, vmreg->cpuid, vmreg->regnum,
+ &vmreg->regval);
+ break;
+ case VM_SET_REGISTER:
+ vmreg = (struct vm_register *)data;
+ error = vm_set_register(sc->vm, vmreg->cpuid, vmreg->regnum,
+ vmreg->regval);
+ break;
+ case VM_SET_SEGMENT_DESCRIPTOR:
+ vmsegdesc = (struct vm_seg_desc *)data;
+ error = vm_set_seg_desc(sc->vm, vmsegdesc->cpuid,
+ vmsegdesc->regnum,
+ &vmsegdesc->desc);
+ break;
+ case VM_GET_SEGMENT_DESCRIPTOR:
+ vmsegdesc = (struct vm_seg_desc *)data;
+ error = vm_get_seg_desc(sc->vm, vmsegdesc->cpuid,
+ vmsegdesc->regnum,
+ &vmsegdesc->desc);
+ break;
+ case VM_GET_CAPABILITY:
+ vmcap = (struct vm_capability *)data;
+ error = vm_get_capability(sc->vm, vmcap->cpuid,
+ vmcap->captype,
+ &vmcap->capval);
+ break;
+ case VM_SET_CAPABILITY:
+ vmcap = (struct vm_capability *)data;
+ error = vm_set_capability(sc->vm, vmcap->cpuid,
+ vmcap->captype,
+ vmcap->capval);
+ break;
+ case VM_SET_X2APIC_STATE:
+ x2apic = (struct vm_x2apic *)data;
+ error = vm_set_x2apic_state(sc->vm,
+ x2apic->cpuid, x2apic->state);
+ break;
+ case VM_GET_X2APIC_STATE:
+ x2apic = (struct vm_x2apic *)data;
+ error = vm_get_x2apic_state(sc->vm,
+ x2apic->cpuid, &x2apic->state);
+ break;
+ default:
+ error = ENOTTY;
+ break;
+ }
+
+ if (state_changed == 1) {
+ vcpu_set_state(sc->vm, vcpu, VCPU_IDLE);
+ } else if (state_changed == 2) {
+ for (vcpu = 0; vcpu < VM_MAXCPU; vcpu++)
+ vcpu_set_state(sc->vm, vcpu, VCPU_IDLE);
+ }
+
+done:
+ return (error);
+}
+
+static int
+vmmdev_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr,
+ int nprot, vm_memattr_t *memattr)
+{
+ int error;
+ struct vmmdev_softc *sc;
+
+ error = -1;
+ mtx_lock(&vmmdev_mtx);
+
+ sc = vmmdev_lookup2(cdev);
+ if (sc != NULL && (nprot & PROT_EXEC) == 0) {
+ *paddr = vm_gpa2hpa(sc->vm, (vm_paddr_t)offset, PAGE_SIZE);
+ if (*paddr != (vm_paddr_t)-1)
+ error = 0;
+ }
+
+ mtx_unlock(&vmmdev_mtx);
+
+ return (error);
+}
+
+static void
+vmmdev_destroy(struct vmmdev_softc *sc, boolean_t unlink)
+{
+
+ /*
+ * XXX must stop virtual machine instances that may be still
+ * running and cleanup their state.
+ */
+ if (sc->cdev)
+ destroy_dev(sc->cdev);
+
+ if (sc->vm)
+ vm_destroy(sc->vm);
+
+ if (unlink) {
+ mtx_lock(&vmmdev_mtx);
+ SLIST_REMOVE(&head, sc, vmmdev_softc, link);
+ mtx_unlock(&vmmdev_mtx);
+ }
+
+ free(sc, M_VMMDEV);
+}
+
+static int
+sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ char buf[VM_MAX_NAMELEN];
+ struct vmmdev_softc *sc;
+
+ strlcpy(buf, "beavis", sizeof(buf));
+ error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ /*
+ * XXX TODO if any process has this device open then fail
+ */
+
+ mtx_lock(&vmmdev_mtx);
+ sc = vmmdev_lookup(buf);
+ if (sc == NULL) {
+ mtx_unlock(&vmmdev_mtx);
+ return (EINVAL);
+ }
+
+ sc->cdev->si_drv1 = NULL;
+ mtx_unlock(&vmmdev_mtx);
+
+ vmmdev_destroy(sc, TRUE);
+
+ return (0);
+}
+SYSCTL_PROC(_hw_vmm, OID_AUTO, destroy, CTLTYPE_STRING | CTLFLAG_RW,
+ NULL, 0, sysctl_vmm_destroy, "A", NULL);
+
+static struct cdevsw vmmdevsw = {
+ .d_name = "vmmdev",
+ .d_version = D_VERSION,
+ .d_ioctl = vmmdev_ioctl,
+ .d_mmap = vmmdev_mmap,
+ .d_read = vmmdev_rw,
+ .d_write = vmmdev_rw,
+};
+
+static int
+sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ struct vm *vm;
+ struct vmmdev_softc *sc, *sc2;
+ char buf[VM_MAX_NAMELEN];
+
+ strlcpy(buf, "beavis", sizeof(buf));
+ error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ mtx_lock(&vmmdev_mtx);
+ sc = vmmdev_lookup(buf);
+ mtx_unlock(&vmmdev_mtx);
+ if (sc != NULL)
+ return (EEXIST);
+
+ vm = vm_create(buf);
+ if (vm == NULL)
+ return (EINVAL);
+
+ sc = malloc(sizeof(struct vmmdev_softc), M_VMMDEV, M_WAITOK | M_ZERO);
+ sc->vm = vm;
+
+ /*
+ * Lookup the name again just in case somebody sneaked in when we
+ * dropped the lock.
+ */
+ mtx_lock(&vmmdev_mtx);
+ sc2 = vmmdev_lookup(buf);
+ if (sc2 == NULL)
+ SLIST_INSERT_HEAD(&head, sc, link);
+ mtx_unlock(&vmmdev_mtx);
+
+ if (sc2 != NULL) {
+ vmmdev_destroy(sc, FALSE);
+ return (EEXIST);
+ }
+
+ sc->cdev = make_dev(&vmmdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
+ "vmm/%s", buf);
+ sc->cdev->si_drv1 = sc;
+
+ return (0);
+}
+SYSCTL_PROC(_hw_vmm, OID_AUTO, create, CTLTYPE_STRING | CTLFLAG_RW,
+ NULL, 0, sysctl_vmm_create, "A", NULL);
+
+void
+vmmdev_init(void)
+{
+ mtx_init(&vmmdev_mtx, "vmm device mutex", NULL, MTX_DEF);
+}
+
+int
+vmmdev_cleanup(void)
+{
+ int error;
+
+ if (SLIST_EMPTY(&head))
+ error = 0;
+ else
+ error = EBUSY;
+
+ return (error);
+}
diff --git a/sys/amd64/vmm/vmm_host.c b/sys/amd64/vmm/vmm_host.c
new file mode 100644
index 0000000..8dfef73
--- /dev/null
+++ b/sys/amd64/vmm/vmm_host.c
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/pcpu.h>
+
+#include <machine/cpufunc.h>
+#include <machine/segments.h>
+#include <machine/specialreg.h>
+
+#include "vmm_host.h"
+
+static uint64_t vmm_host_efer, vmm_host_pat, vmm_host_cr0, vmm_host_cr4;
+
+void
+vmm_host_state_init(void)
+{
+
+ vmm_host_efer = rdmsr(MSR_EFER);
+ vmm_host_pat = rdmsr(MSR_PAT);
+
+ /*
+ * We always want CR0.TS to be set when the processor does a VM exit.
+ *
+ * With emulation turned on unconditionally after a VM exit, we are
+ * able to trap inadvertent use of the FPU until the guest FPU state
+ * has been safely squirreled away.
+ */
+ vmm_host_cr0 = rcr0() | CR0_TS;
+
+ vmm_host_cr4 = rcr4();
+}
+
+uint64_t
+vmm_get_host_pat(void)
+{
+
+ return (vmm_host_pat);
+}
+
+uint64_t
+vmm_get_host_efer(void)
+{
+
+ return (vmm_host_efer);
+}
+
+uint64_t
+vmm_get_host_cr0(void)
+{
+
+ return (vmm_host_cr0);
+}
+
+uint64_t
+vmm_get_host_cr4(void)
+{
+
+ return (vmm_host_cr4);
+}
+
+uint64_t
+vmm_get_host_datasel(void)
+{
+
+ return (GSEL(GDATA_SEL, SEL_KPL));
+
+}
+
+uint64_t
+vmm_get_host_codesel(void)
+{
+
+ return (GSEL(GCODE_SEL, SEL_KPL));
+}
+
+uint64_t
+vmm_get_host_tsssel(void)
+{
+
+ return (GSEL(GPROC0_SEL, SEL_KPL));
+}
+
+uint64_t
+vmm_get_host_fsbase(void)
+{
+
+ return (0);
+}
+
+uint64_t
+vmm_get_host_idtrbase(void)
+{
+
+ return (r_idt.rd_base);
+}
diff --git a/sys/amd64/vmm/vmm_host.h b/sys/amd64/vmm/vmm_host.h
new file mode 100644
index 0000000..839f54a
--- /dev/null
+++ b/sys/amd64/vmm/vmm_host.h
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMM_HOST_H_
+#define _VMM_HOST_H_
+
+#ifndef _KERNEL
+#error "no user-servicable parts inside"
+#endif
+
+void vmm_host_state_init(void);
+
+uint64_t vmm_get_host_pat(void);
+uint64_t vmm_get_host_efer(void);
+uint64_t vmm_get_host_cr0(void);
+uint64_t vmm_get_host_cr4(void);
+uint64_t vmm_get_host_datasel(void);
+uint64_t vmm_get_host_codesel(void);
+uint64_t vmm_get_host_tsssel(void);
+uint64_t vmm_get_host_fsbase(void);
+uint64_t vmm_get_host_idtrbase(void);
+
+/*
+ * Inline access to host state that is used on every VM entry
+ */
+static __inline uint64_t
+vmm_get_host_trbase(void)
+{
+
+ return ((uint64_t)PCPU_GET(tssp));
+}
+
+static __inline uint64_t
+vmm_get_host_gdtrbase(void)
+{
+
+ return ((uint64_t)&gdt[NGDT * curcpu]);
+}
+
+struct pcpu;
+extern struct pcpu __pcpu[];
+
+static __inline uint64_t
+vmm_get_host_gsbase(void)
+{
+
+ return ((uint64_t)&__pcpu[curcpu]);
+}
+
+#endif
diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c
new file mode 100644
index 0000000..40748ea
--- /dev/null
+++ b/sys/amd64/vmm/vmm_instruction_emul.c
@@ -0,0 +1,868 @@
+/*-
+ * Copyright (c) 2012 Sandvine, Inc.
+ * Copyright (c) 2012 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef _KERNEL
+#include <sys/param.h>
+#include <sys/pcpu.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+#include <machine/vmm.h>
+#else /* !_KERNEL */
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <machine/vmm.h>
+
+#include <vmmapi.h>
+#endif /* _KERNEL */
+
+
+
+/* struct vie_op.op_type */
+enum {
+ VIE_OP_TYPE_NONE = 0,
+ VIE_OP_TYPE_MOV,
+ VIE_OP_TYPE_AND,
+ VIE_OP_TYPE_LAST
+};
+
+/* struct vie_op.op_flags */
+#define VIE_OP_F_IMM (1 << 0) /* immediate operand present */
+#define VIE_OP_F_IMM8 (1 << 1) /* 8-bit immediate operand */
+
+static const struct vie_op one_byte_opcodes[256] = {
+ [0x88] = {
+ .op_byte = 0x88,
+ .op_type = VIE_OP_TYPE_MOV,
+ },
+ [0x89] = {
+ .op_byte = 0x89,
+ .op_type = VIE_OP_TYPE_MOV,
+ },
+ [0x8B] = {
+ .op_byte = 0x8B,
+ .op_type = VIE_OP_TYPE_MOV,
+ },
+ [0xC7] = {
+ .op_byte = 0xC7,
+ .op_type = VIE_OP_TYPE_MOV,
+ .op_flags = VIE_OP_F_IMM,
+ },
+ [0x23] = {
+ .op_byte = 0x23,
+ .op_type = VIE_OP_TYPE_AND,
+ },
+ [0x81] = {
+ /* XXX Group 1 extended opcode - not just AND */
+ .op_byte = 0x81,
+ .op_type = VIE_OP_TYPE_AND,
+ .op_flags = VIE_OP_F_IMM,
+ }
+};
+
+/* struct vie.mod */
+#define VIE_MOD_INDIRECT 0
+#define VIE_MOD_INDIRECT_DISP8 1
+#define VIE_MOD_INDIRECT_DISP32 2
+#define VIE_MOD_DIRECT 3
+
+/* struct vie.rm */
+#define VIE_RM_SIB 4
+#define VIE_RM_DISP32 5
+
+#define GB (1024 * 1024 * 1024)
+
+static enum vm_reg_name gpr_map[16] = {
+ VM_REG_GUEST_RAX,
+ VM_REG_GUEST_RCX,
+ VM_REG_GUEST_RDX,
+ VM_REG_GUEST_RBX,
+ VM_REG_GUEST_RSP,
+ VM_REG_GUEST_RBP,
+ VM_REG_GUEST_RSI,
+ VM_REG_GUEST_RDI,
+ VM_REG_GUEST_R8,
+ VM_REG_GUEST_R9,
+ VM_REG_GUEST_R10,
+ VM_REG_GUEST_R11,
+ VM_REG_GUEST_R12,
+ VM_REG_GUEST_R13,
+ VM_REG_GUEST_R14,
+ VM_REG_GUEST_R15
+};
+
+static uint64_t size2mask[] = {
+ [1] = 0xff,
+ [2] = 0xffff,
+ [4] = 0xffffffff,
+ [8] = 0xffffffffffffffff,
+};
+
+static int
+vie_valid_register(enum vm_reg_name reg)
+{
+#ifdef _KERNEL
+ /*
+ * XXX
+ * The operand register in which we store the result of the
+ * read must be a GPR that we can modify even if the vcpu
+ * is "running". All the GPRs qualify except for %rsp.
+ *
+ * This is a limitation of the vm_set_register() API
+ * and can be fixed if necessary.
+ */
+ if (reg == VM_REG_GUEST_RSP)
+ return (0);
+#endif
+ return (1);
+}
+
+static int
+vie_read_register(void *vm, int vcpuid, enum vm_reg_name reg, uint64_t *rval)
+{
+ int error;
+
+ if (!vie_valid_register(reg))
+ return (EINVAL);
+
+ error = vm_get_register(vm, vcpuid, reg, rval);
+
+ return (error);
+}
+
+static int
+vie_read_bytereg(void *vm, int vcpuid, struct vie *vie, uint8_t *rval)
+{
+ uint64_t val;
+ int error, rshift;
+ enum vm_reg_name reg;
+
+ rshift = 0;
+ reg = gpr_map[vie->reg];
+
+ /*
+ * 64-bit mode imposes limitations on accessing legacy byte registers.
+ *
+ * The legacy high-byte registers cannot be addressed if the REX
+ * prefix is present. In this case the values 4, 5, 6 and 7 of the
+ * 'ModRM:reg' field address %spl, %bpl, %sil and %dil respectively.
+ *
+ * If the REX prefix is not present then the values 4, 5, 6 and 7
+ * of the 'ModRM:reg' field address the legacy high-byte registers,
+ * %ah, %ch, %dh and %bh respectively.
+ */
+ if (!vie->rex_present) {
+ if (vie->reg & 0x4) {
+ /*
+ * Obtain the value of %ah by reading %rax and shifting
+ * right by 8 bits (same for %bh, %ch and %dh).
+ */
+ rshift = 8;
+ reg = gpr_map[vie->reg & 0x3];
+ }
+ }
+
+ if (!vie_valid_register(reg))
+ return (EINVAL);
+
+ error = vm_get_register(vm, vcpuid, reg, &val);
+ *rval = val >> rshift;
+ return (error);
+}
+
+static int
+vie_update_register(void *vm, int vcpuid, enum vm_reg_name reg,
+ uint64_t val, int size)
+{
+ int error;
+ uint64_t origval;
+
+ if (!vie_valid_register(reg))
+ return (EINVAL);
+
+ switch (size) {
+ case 1:
+ case 2:
+ error = vie_read_register(vm, vcpuid, reg, &origval);
+ if (error)
+ return (error);
+ val &= size2mask[size];
+ val |= origval & ~size2mask[size];
+ break;
+ case 4:
+ val &= 0xffffffffUL;
+ break;
+ case 8:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ error = vm_set_register(vm, vcpuid, reg, val);
+ return (error);
+}
+
+/*
+ * The following simplifying assumptions are made during emulation:
+ *
+ * - guest is in 64-bit mode
+ * - default address size is 64-bits
+ * - default operand size is 32-bits
+ *
+ * - operand size override is not supported
+ *
+ * - address size override is not supported
+ */
+static int
+emulate_mov(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
+{
+ int error, size;
+ enum vm_reg_name reg;
+ uint8_t byte;
+ uint64_t val;
+
+ size = 4;
+ error = EINVAL;
+
+ switch (vie->op.op_byte) {
+ case 0x88:
+ /*
+ * MOV byte from reg (ModRM:reg) to mem (ModRM:r/m)
+ * 88/r: mov r/m8, r8
+ * REX + 88/r: mov r/m8, r8 (%ah, %ch, %dh, %bh not available)
+ */
+ size = 1;
+ error = vie_read_bytereg(vm, vcpuid, vie, &byte);
+ if (error == 0)
+ error = memwrite(vm, vcpuid, gpa, byte, size, arg);
+ break;
+ case 0x89:
+ /*
+ * MOV from reg (ModRM:reg) to mem (ModRM:r/m)
+ * 89/r: mov r/m32, r32
+ * REX.W + 89/r mov r/m64, r64
+ */
+ if (vie->rex_w)
+ size = 8;
+ reg = gpr_map[vie->reg];
+ error = vie_read_register(vm, vcpuid, reg, &val);
+ if (error == 0) {
+ val &= size2mask[size];
+ error = memwrite(vm, vcpuid, gpa, val, size, arg);
+ }
+ break;
+ case 0x8B:
+ /*
+ * MOV from mem (ModRM:r/m) to reg (ModRM:reg)
+ * 8B/r: mov r32, r/m32
+ * REX.W 8B/r: mov r64, r/m64
+ */
+ if (vie->rex_w)
+ size = 8;
+ error = memread(vm, vcpuid, gpa, &val, size, arg);
+ if (error == 0) {
+ reg = gpr_map[vie->reg];
+ error = vie_update_register(vm, vcpuid, reg, val, size);
+ }
+ break;
+ case 0xC7:
+ /*
+ * MOV from imm32 to mem (ModRM:r/m)
+ * C7/0 mov r/m32, imm32
+ * REX.W + C7/0 mov r/m64, imm32 (sign-extended to 64-bits)
+ */
+ val = vie->immediate; /* already sign-extended */
+
+ if (vie->rex_w)
+ size = 8;
+
+ if (size != 8)
+ val &= size2mask[size];
+
+ error = memwrite(vm, vcpuid, gpa, val, size, arg);
+ break;
+ default:
+ break;
+ }
+
+ return (error);
+}
+
+static int
+emulate_and(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
+{
+ int error, size;
+ enum vm_reg_name reg;
+ uint64_t val1, val2;
+
+ size = 4;
+ error = EINVAL;
+
+ switch (vie->op.op_byte) {
+ case 0x23:
+ /*
+ * AND reg (ModRM:reg) and mem (ModRM:r/m) and store the
+ * result in reg.
+ *
+ * 23/r and r32, r/m32
+ * REX.W + 23/r and r64, r/m64
+ */
+ if (vie->rex_w)
+ size = 8;
+
+ /* get the first operand */
+ reg = gpr_map[vie->reg];
+ error = vie_read_register(vm, vcpuid, reg, &val1);
+ if (error)
+ break;
+
+ /* get the second operand */
+ error = memread(vm, vcpuid, gpa, &val2, size, arg);
+ if (error)
+ break;
+
+ /* perform the operation and write the result */
+ val1 &= val2;
+ error = vie_update_register(vm, vcpuid, reg, val1, size);
+ break;
+ case 0x81:
+ /*
+ * AND reg (ModRM:reg) with immediate and store the
+ * result in reg
+ *
+ * 81/ and r/m32, imm32
+ * REX.W + 81/ and r/m64, imm32 sign-extended to 64
+ *
+ * Currently, only the AND operation of the 0x81 opcode
+ * is implemented (ModRM:reg = b100).
+ */
+ if ((vie->reg & 7) != 4)
+ break;
+
+ if (vie->rex_w)
+ size = 8;
+
+ /* get the first operand */
+ error = memread(vm, vcpuid, gpa, &val1, size, arg);
+ if (error)
+ break;
+
+ /*
+ * perform the operation with the pre-fetched immediate
+ * operand and write the result
+ */
+ val1 &= vie->immediate;
+ error = memwrite(vm, vcpuid, gpa, val1, size, arg);
+ break;
+ default:
+ break;
+ }
+ return (error);
+}
+
+int
+vmm_emulate_instruction(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
+ mem_region_read_t memread, mem_region_write_t memwrite,
+ void *memarg)
+{
+ int error;
+
+ if (!vie->decoded)
+ return (EINVAL);
+
+ switch (vie->op.op_type) {
+ case VIE_OP_TYPE_MOV:
+ error = emulate_mov(vm, vcpuid, gpa, vie,
+ memread, memwrite, memarg);
+ break;
+ case VIE_OP_TYPE_AND:
+ error = emulate_and(vm, vcpuid, gpa, vie,
+ memread, memwrite, memarg);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+
+#ifdef _KERNEL
+static void
+vie_init(struct vie *vie)
+{
+
+ bzero(vie, sizeof(struct vie));
+
+ vie->base_register = VM_REG_LAST;
+ vie->index_register = VM_REG_LAST;
+}
+
+static int
+gla2gpa(struct vm *vm, uint64_t gla, uint64_t ptpphys,
+ uint64_t *gpa, uint64_t *gpaend)
+{
+ vm_paddr_t hpa;
+ int nlevels, ptpshift, ptpindex;
+ uint64_t *ptpbase, pte, pgsize;
+
+ /*
+ * XXX assumes 64-bit guest with 4 page walk levels
+ */
+ nlevels = 4;
+ while (--nlevels >= 0) {
+ /* Zero out the lower 12 bits and the upper 12 bits */
+ ptpphys >>= 12; ptpphys <<= 24; ptpphys >>= 12;
+
+ hpa = vm_gpa2hpa(vm, ptpphys, PAGE_SIZE);
+ if (hpa == -1)
+ goto error;
+
+ ptpbase = (uint64_t *)PHYS_TO_DMAP(hpa);
+
+ ptpshift = PAGE_SHIFT + nlevels * 9;
+ ptpindex = (gla >> ptpshift) & 0x1FF;
+ pgsize = 1UL << ptpshift;
+
+ pte = ptpbase[ptpindex];
+
+ if ((pte & PG_V) == 0)
+ goto error;
+
+ if (pte & PG_PS) {
+ if (pgsize > 1 * GB)
+ goto error;
+ else
+ break;
+ }
+
+ ptpphys = pte;
+ }
+
+ /* Zero out the lower 'ptpshift' bits and the upper 12 bits */
+ pte >>= ptpshift; pte <<= (ptpshift + 12); pte >>= 12;
+ *gpa = pte | (gla & (pgsize - 1));
+ *gpaend = pte + pgsize;
+ return (0);
+
+error:
+ return (-1);
+}
+
+int
+vmm_fetch_instruction(struct vm *vm, int cpuid, uint64_t rip, int inst_length,
+ uint64_t cr3, struct vie *vie)
+{
+ int n, err;
+ uint64_t hpa, gpa, gpaend, off;
+
+ /*
+ * XXX cache previously fetched instructions using 'rip' as the tag
+ */
+
+ if (inst_length > VIE_INST_SIZE)
+ panic("vmm_fetch_instruction: invalid length %d", inst_length);
+
+ vie_init(vie);
+
+ /* Copy the instruction into 'vie' */
+ while (vie->num_valid < inst_length) {
+ err = gla2gpa(vm, rip, cr3, &gpa, &gpaend);
+ if (err)
+ break;
+
+ off = gpa & PAGE_MASK;
+ n = min(inst_length - vie->num_valid, PAGE_SIZE - off);
+
+ hpa = vm_gpa2hpa(vm, gpa, n);
+ if (hpa == -1)
+ break;
+
+ bcopy((void *)PHYS_TO_DMAP(hpa), &vie->inst[vie->num_valid], n);
+
+ rip += n;
+ vie->num_valid += n;
+ }
+
+ if (vie->num_valid == inst_length)
+ return (0);
+ else
+ return (-1);
+}
+
+static int
+vie_peek(struct vie *vie, uint8_t *x)
+{
+
+ if (vie->num_processed < vie->num_valid) {
+ *x = vie->inst[vie->num_processed];
+ return (0);
+ } else
+ return (-1);
+}
+
+static void
+vie_advance(struct vie *vie)
+{
+
+ vie->num_processed++;
+}
+
+static int
+decode_rex(struct vie *vie)
+{
+ uint8_t x;
+
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ if (x >= 0x40 && x <= 0x4F) {
+ vie->rex_present = 1;
+
+ vie->rex_w = x & 0x8 ? 1 : 0;
+ vie->rex_r = x & 0x4 ? 1 : 0;
+ vie->rex_x = x & 0x2 ? 1 : 0;
+ vie->rex_b = x & 0x1 ? 1 : 0;
+
+ vie_advance(vie);
+ }
+
+ return (0);
+}
+
+static int
+decode_opcode(struct vie *vie)
+{
+ uint8_t x;
+
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ vie->op = one_byte_opcodes[x];
+
+ if (vie->op.op_type == VIE_OP_TYPE_NONE)
+ return (-1);
+
+ vie_advance(vie);
+ return (0);
+}
+
+/*
+ * XXX assuming 32-bit or 64-bit guest
+ */
+static int
+decode_modrm(struct vie *vie)
+{
+ uint8_t x;
+
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ vie->mod = (x >> 6) & 0x3;
+ vie->rm = (x >> 0) & 0x7;
+ vie->reg = (x >> 3) & 0x7;
+
+ /*
+ * A direct addressing mode makes no sense in the context of an EPT
+ * fault. There has to be a memory access involved to cause the
+ * EPT fault.
+ */
+ if (vie->mod == VIE_MOD_DIRECT)
+ return (-1);
+
+ if ((vie->mod == VIE_MOD_INDIRECT && vie->rm == VIE_RM_DISP32) ||
+ (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB)) {
+ /*
+ * Table 2-5: Special Cases of REX Encodings
+ *
+ * mod=0, r/m=5 is used in the compatibility mode to
+ * indicate a disp32 without a base register.
+ *
+ * mod!=3, r/m=4 is used in the compatibility mode to
+ * indicate that the SIB byte is present.
+ *
+ * The 'b' bit in the REX prefix is don't care in
+ * this case.
+ */
+ } else {
+ vie->rm |= (vie->rex_b << 3);
+ }
+
+ vie->reg |= (vie->rex_r << 3);
+
+ /* SIB */
+ if (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB)
+ goto done;
+
+ vie->base_register = gpr_map[vie->rm];
+
+ switch (vie->mod) {
+ case VIE_MOD_INDIRECT_DISP8:
+ vie->disp_bytes = 1;
+ break;
+ case VIE_MOD_INDIRECT_DISP32:
+ vie->disp_bytes = 4;
+ break;
+ case VIE_MOD_INDIRECT:
+ if (vie->rm == VIE_RM_DISP32) {
+ vie->disp_bytes = 4;
+ vie->base_register = VM_REG_LAST; /* no base */
+ }
+ break;
+ }
+
+ /* Figure out immediate operand size (if any) */
+ if (vie->op.op_flags & VIE_OP_F_IMM)
+ vie->imm_bytes = 4;
+ else if (vie->op.op_flags & VIE_OP_F_IMM8)
+ vie->imm_bytes = 1;
+
+done:
+ vie_advance(vie);
+
+ return (0);
+}
+
+static int
+decode_sib(struct vie *vie)
+{
+ uint8_t x;
+
+ /* Proceed only if SIB byte is present */
+ if (vie->mod == VIE_MOD_DIRECT || vie->rm != VIE_RM_SIB)
+ return (0);
+
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ /* De-construct the SIB byte */
+ vie->ss = (x >> 6) & 0x3;
+ vie->index = (x >> 3) & 0x7;
+ vie->base = (x >> 0) & 0x7;
+
+ /* Apply the REX prefix modifiers */
+ vie->index |= vie->rex_x << 3;
+ vie->base |= vie->rex_b << 3;
+
+ switch (vie->mod) {
+ case VIE_MOD_INDIRECT_DISP8:
+ vie->disp_bytes = 1;
+ break;
+ case VIE_MOD_INDIRECT_DISP32:
+ vie->disp_bytes = 4;
+ break;
+ }
+
+ if (vie->mod == VIE_MOD_INDIRECT &&
+ (vie->base == 5 || vie->base == 13)) {
+ /*
+ * Special case when base register is unused if mod = 0
+ * and base = %rbp or %r13.
+ *
+ * Documented in:
+ * Table 2-3: 32-bit Addressing Forms with the SIB Byte
+ * Table 2-5: Special Cases of REX Encodings
+ */
+ vie->disp_bytes = 4;
+ } else {
+ vie->base_register = gpr_map[vie->base];
+ }
+
+ /*
+ * All encodings of 'index' are valid except for %rsp (4).
+ *
+ * Documented in:
+ * Table 2-3: 32-bit Addressing Forms with the SIB Byte
+ * Table 2-5: Special Cases of REX Encodings
+ */
+ if (vie->index != 4)
+ vie->index_register = gpr_map[vie->index];
+
+ /* 'scale' makes sense only in the context of an index register */
+ if (vie->index_register < VM_REG_LAST)
+ vie->scale = 1 << vie->ss;
+
+ vie_advance(vie);
+
+ return (0);
+}
+
+static int
+decode_displacement(struct vie *vie)
+{
+ int n, i;
+ uint8_t x;
+
+ union {
+ char buf[4];
+ int8_t signed8;
+ int32_t signed32;
+ } u;
+
+ if ((n = vie->disp_bytes) == 0)
+ return (0);
+
+ if (n != 1 && n != 4)
+ panic("decode_displacement: invalid disp_bytes %d", n);
+
+ for (i = 0; i < n; i++) {
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ u.buf[i] = x;
+ vie_advance(vie);
+ }
+
+ if (n == 1)
+ vie->displacement = u.signed8; /* sign-extended */
+ else
+ vie->displacement = u.signed32; /* sign-extended */
+
+ return (0);
+}
+
+static int
+decode_immediate(struct vie *vie)
+{
+ int i, n;
+ uint8_t x;
+ union {
+ char buf[4];
+ int8_t signed8;
+ int32_t signed32;
+ } u;
+
+ if ((n = vie->imm_bytes) == 0)
+ return (0);
+
+ if (n != 1 && n != 4)
+ panic("decode_immediate: invalid imm_bytes %d", n);
+
+ for (i = 0; i < n; i++) {
+ if (vie_peek(vie, &x))
+ return (-1);
+
+ u.buf[i] = x;
+ vie_advance(vie);
+ }
+
+ if (n == 1)
+ vie->immediate = u.signed8; /* sign-extended */
+ else
+ vie->immediate = u.signed32; /* sign-extended */
+
+ return (0);
+}
+
+#define VERIFY_GLA
+/*
+ * Verify that the 'guest linear address' provided as collateral of the nested
+ * page table fault matches with our instruction decoding.
+ */
+#ifdef VERIFY_GLA
+static int
+verify_gla(struct vm *vm, int cpuid, uint64_t gla, struct vie *vie)
+{
+ int error;
+ uint64_t base, idx;
+
+ base = 0;
+ if (vie->base_register != VM_REG_LAST) {
+ error = vm_get_register(vm, cpuid, vie->base_register, &base);
+ if (error) {
+ printf("verify_gla: error %d getting base reg %d\n",
+ error, vie->base_register);
+ return (-1);
+ }
+ }
+
+ idx = 0;
+ if (vie->index_register != VM_REG_LAST) {
+ error = vm_get_register(vm, cpuid, vie->index_register, &idx);
+ if (error) {
+ printf("verify_gla: error %d getting index reg %d\n",
+ error, vie->index_register);
+ return (-1);
+ }
+ }
+
+ if (base + vie->scale * idx + vie->displacement != gla) {
+ printf("verify_gla mismatch: "
+ "base(0x%0lx), scale(%d), index(0x%0lx), "
+ "disp(0x%0lx), gla(0x%0lx)\n",
+ base, vie->scale, idx, vie->displacement, gla);
+ return (-1);
+ }
+
+ return (0);
+}
+#endif /* VERIFY_GLA */
+
+int
+vmm_decode_instruction(struct vm *vm, int cpuid, uint64_t gla, struct vie *vie)
+{
+
+ if (decode_rex(vie))
+ return (-1);
+
+ if (decode_opcode(vie))
+ return (-1);
+
+ if (decode_modrm(vie))
+ return (-1);
+
+ if (decode_sib(vie))
+ return (-1);
+
+ if (decode_displacement(vie))
+ return (-1);
+
+ if (decode_immediate(vie))
+ return (-1);
+
+#ifdef VERIFY_GLA
+ if (verify_gla(vm, cpuid, gla, vie))
+ return (-1);
+#endif
+
+ vie->decoded = 1; /* success */
+
+ return (0);
+}
+#endif /* _KERNEL */
diff --git a/sys/amd64/vmm/vmm_ipi.c b/sys/amd64/vmm/vmm_ipi.c
new file mode 100644
index 0000000..643d326
--- /dev/null
+++ b/sys/amd64/vmm/vmm_ipi.c
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/bus.h>
+
+#include <machine/intr_machdep.h>
+#include <machine/apicvar.h>
+#include <machine/segments.h>
+#include <machine/md_var.h>
+
+#include <machine/vmm.h>
+#include "vmm_ipi.h"
+
+extern inthand_t IDTVEC(rsvd), IDTVEC(justreturn);
+
+/*
+ * The default is to use the IPI_AST to interrupt a vcpu.
+ */
+int vmm_ipinum = IPI_AST;
+
+CTASSERT(APIC_SPURIOUS_INT == 255);
+
+void
+vmm_ipi_init(void)
+{
+ int idx;
+ uintptr_t func;
+ struct gate_descriptor *ip;
+
+ /*
+ * Search backwards from the highest IDT vector available for use
+ * as our IPI vector. We install the 'justreturn' handler at that
+ * vector and use it to interrupt the vcpus.
+ *
+ * We do this because the IPI_AST is heavyweight and saves all
+ * registers in the trapframe. This is overkill for our use case
+ * which is simply to EOI the interrupt and return.
+ */
+ idx = APIC_SPURIOUS_INT;
+ while (--idx >= APIC_IPI_INTS) {
+ ip = &idt[idx];
+ func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
+ if (func == (uintptr_t)&IDTVEC(rsvd)) {
+ vmm_ipinum = idx;
+ setidt(vmm_ipinum, IDTVEC(justreturn), SDT_SYSIGT,
+ SEL_KPL, 0);
+ break;
+ }
+ }
+
+ if (vmm_ipinum != IPI_AST && bootverbose) {
+ printf("vmm_ipi_init: installing ipi handler to interrupt "
+ "vcpus at vector %d\n", vmm_ipinum);
+ }
+}
+
+void
+vmm_ipi_cleanup(void)
+{
+ if (vmm_ipinum != IPI_AST)
+ setidt(vmm_ipinum, IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
+}
diff --git a/sys/amd64/vmm/vmm_ipi.h b/sys/amd64/vmm/vmm_ipi.h
new file mode 100644
index 0000000..91552e3
--- /dev/null
+++ b/sys/amd64/vmm/vmm_ipi.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMM_IPI_H_
+#define _VMM_IPI_H_
+
+struct vm;
+
+extern int vmm_ipinum;
+
+void vmm_ipi_init(void);
+void vmm_ipi_cleanup(void);
+
+#endif
diff --git a/sys/amd64/vmm/vmm_ktr.h b/sys/amd64/vmm/vmm_ktr.h
new file mode 100644
index 0000000..e691c61
--- /dev/null
+++ b/sys/amd64/vmm/vmm_ktr.h
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMM_KTR_H_
+#define _VMM_KTR_H_
+
+#include <sys/ktr.h>
+#include <sys/pcpu.h>
+
+#define KTR_VMM KTR_GEN
+
+#define VMM_CTR0(vm, vcpuid, format) \
+CTR3(KTR_VMM, "vm %s-%d(%d): " format, vm_name((vm)), (vcpuid), curcpu)
+
+#define VMM_CTR1(vm, vcpuid, format, p1) \
+CTR4(KTR_VMM, "vm %s-%d(%d): " format, vm_name((vm)), (vcpuid), curcpu, \
+ (p1))
+
+#define VMM_CTR2(vm, vcpuid, format, p1, p2) \
+CTR5(KTR_VMM, "vm %s-%d(%d): " format, vm_name((vm)), (vcpuid), curcpu, \
+ (p1), (p2))
+
+#define VMM_CTR3(vm, vcpuid, format, p1, p2, p3) \
+CTR6(KTR_VMM, "vm %s-%d(%d): " format, vm_name((vm)), (vcpuid), curcpu, \
+ (p1), (p2), (p3))
+#endif
diff --git a/sys/amd64/vmm/vmm_lapic.c b/sys/amd64/vmm/vmm_lapic.c
new file mode 100644
index 0000000..d024b71
--- /dev/null
+++ b/sys/amd64/vmm/vmm_lapic.c
@@ -0,0 +1,201 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+
+#include <x86/specialreg.h>
+#include <x86/apicreg.h>
+
+#include <machine/vmm.h>
+#include "vmm_ipi.h"
+#include "vmm_lapic.h"
+#include "vlapic.h"
+
+int
+lapic_pending_intr(struct vm *vm, int cpu)
+{
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, cpu);
+
+ return (vlapic_pending_intr(vlapic));
+}
+
+void
+lapic_intr_accepted(struct vm *vm, int cpu, int vector)
+{
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, cpu);
+
+ vlapic_intr_accepted(vlapic, vector);
+}
+
+int
+lapic_set_intr(struct vm *vm, int cpu, int vector)
+{
+ struct vlapic *vlapic;
+
+ if (cpu < 0 || cpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (vector < 32 || vector > 255)
+ return (EINVAL);
+
+ vlapic = vm_lapic(vm, cpu);
+ vlapic_set_intr_ready(vlapic, vector);
+
+ vm_interrupt_hostcpu(vm, cpu);
+
+ return (0);
+}
+
+int
+lapic_timer_tick(struct vm *vm, int cpu)
+{
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, cpu);
+
+ return (vlapic_timer_tick(vlapic));
+}
+
+static boolean_t
+x2apic_msr(u_int msr)
+{
+ if (msr >= 0x800 && msr <= 0xBFF)
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+static u_int
+x2apic_msr_to_regoff(u_int msr)
+{
+
+ return ((msr - 0x800) << 4);
+}
+
+boolean_t
+lapic_msr(u_int msr)
+{
+
+ if (x2apic_msr(msr) || (msr == MSR_APICBASE))
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+int
+lapic_rdmsr(struct vm *vm, int cpu, u_int msr, uint64_t *rval)
+{
+ int error;
+ u_int offset;
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, cpu);
+
+ if (msr == MSR_APICBASE) {
+ *rval = vlapic_get_apicbase(vlapic);
+ error = 0;
+ } else {
+ offset = x2apic_msr_to_regoff(msr);
+ error = vlapic_op_mem_read(vlapic, offset, DWORD, rval);
+ }
+
+ return (error);
+}
+
+int
+lapic_wrmsr(struct vm *vm, int cpu, u_int msr, uint64_t val)
+{
+ int error;
+ u_int offset;
+ struct vlapic *vlapic;
+
+ vlapic = vm_lapic(vm, cpu);
+
+ if (msr == MSR_APICBASE) {
+ vlapic_set_apicbase(vlapic, val);
+ error = 0;
+ } else {
+ offset = x2apic_msr_to_regoff(msr);
+ error = vlapic_op_mem_write(vlapic, offset, DWORD, val);
+ }
+
+ return (error);
+}
+
+int
+lapic_mmio_write(void *vm, int cpu, uint64_t gpa, uint64_t wval, int size,
+ void *arg)
+{
+ int error;
+ uint64_t off;
+ struct vlapic *vlapic;
+
+ off = gpa - DEFAULT_APIC_BASE;
+
+ /*
+ * Memory mapped local apic accesses must be 4 bytes wide and
+ * aligned on a 16-byte boundary.
+ */
+ if (size != 4 || off & 0xf)
+ return (EINVAL);
+
+ vlapic = vm_lapic(vm, cpu);
+ error = vlapic_op_mem_write(vlapic, off, DWORD, wval);
+ return (error);
+}
+
+int
+lapic_mmio_read(void *vm, int cpu, uint64_t gpa, uint64_t *rval, int size,
+ void *arg)
+{
+ int error;
+ uint64_t off;
+ struct vlapic *vlapic;
+
+ off = gpa - DEFAULT_APIC_BASE;
+
+ /*
+ * Memory mapped local apic accesses must be 4 bytes wide and
+ * aligned on a 16-byte boundary.
+ */
+ if (size != 4 || off & 0xf)
+ return (EINVAL);
+
+ vlapic = vm_lapic(vm, cpu);
+ error = vlapic_op_mem_read(vlapic, off, DWORD, rval);
+ return (error);
+}
diff --git a/sys/amd64/vmm/vmm_lapic.h b/sys/amd64/vmm/vmm_lapic.h
new file mode 100644
index 0000000..a79912e
--- /dev/null
+++ b/sys/amd64/vmm/vmm_lapic.h
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMM_LAPIC_H_
+#define _VMM_LAPIC_H_
+
+struct vm;
+
+boolean_t lapic_msr(u_int num);
+int lapic_rdmsr(struct vm *vm, int cpu, u_int msr, uint64_t *rval);
+int lapic_wrmsr(struct vm *vm, int cpu, u_int msr, uint64_t wval);
+
+int lapic_mmio_read(void *vm, int cpu, uint64_t gpa,
+ uint64_t *rval, int size, void *arg);
+int lapic_mmio_write(void *vm, int cpu, uint64_t gpa,
+ uint64_t wval, int size, void *arg);
+
+int lapic_timer_tick(struct vm *vm, int cpu);
+
+/*
+ * Returns a vector between 32 and 255 if an interrupt is pending in the
+ * IRR that can be delivered based on the current state of ISR and TPR.
+ *
+ * Note that the vector does not automatically transition to the ISR as a
+ * result of calling this function.
+ *
+ * Returns -1 if there is no eligible vector that can be delivered to the
+ * guest at this time.
+ */
+int lapic_pending_intr(struct vm *vm, int cpu);
+
+/*
+ * Transition 'vector' from IRR to ISR. This function is called with the
+ * vector returned by 'lapic_pending_intr()' when the guest is able to
+ * accept this interrupt (i.e. RFLAGS.IF = 1 and no conditions exist that
+ * block interrupt delivery).
+ */
+void lapic_intr_accepted(struct vm *vm, int cpu, int vector);
+
+/*
+ * Signals to the LAPIC that an interrupt at 'vector' needs to be generated
+ * to the 'cpu', the state is recorded in IRR.
+ */
+int lapic_set_intr(struct vm *vm, int cpu, int vector);
+
+#endif
diff --git a/sys/amd64/vmm/vmm_mem.c b/sys/amd64/vmm/vmm_mem.c
new file mode 100644
index 0000000..04f99b1
--- /dev/null
+++ b/sys/amd64/vmm/vmm_mem.c
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/linker.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+
+#include <machine/md_var.h>
+#include <machine/metadata.h>
+#include <machine/pc/bios.h>
+#include <machine/vmparam.h>
+#include <machine/pmap.h>
+
+#include "vmm_util.h"
+#include "vmm_mem.h"
+
+SYSCTL_DECL(_hw_vmm);
+
+static u_long pages_allocated;
+SYSCTL_ULONG(_hw_vmm, OID_AUTO, pages_allocated, CTLFLAG_RD,
+ &pages_allocated, 0, "4KB pages allocated");
+
+static void
+update_pages_allocated(int howmany)
+{
+ pages_allocated += howmany; /* XXX locking? */
+}
+
+int
+vmm_mem_init(void)
+{
+
+ return (0);
+}
+
+vm_paddr_t
+vmm_mem_alloc(size_t size)
+{
+ int flags;
+ vm_page_t m;
+ vm_paddr_t pa;
+
+ if (size != PAGE_SIZE)
+ panic("vmm_mem_alloc: invalid allocation size %lu", size);
+
+ flags = VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED |
+ VM_ALLOC_ZERO;
+
+ while (1) {
+ /*
+ * XXX need policy to determine when to back off the allocation
+ */
+ m = vm_page_alloc(NULL, 0, flags);
+ if (m == NULL)
+ VM_WAIT;
+ else
+ break;
+ }
+
+ pa = VM_PAGE_TO_PHYS(m);
+
+ if ((m->flags & PG_ZERO) == 0)
+ pagezero((void *)PHYS_TO_DMAP(pa));
+ m->valid = VM_PAGE_BITS_ALL;
+
+ update_pages_allocated(1);
+
+ return (pa);
+}
+
+void
+vmm_mem_free(vm_paddr_t base, size_t length)
+{
+ vm_page_t m;
+
+ if (base & PAGE_MASK) {
+ panic("vmm_mem_free: base 0x%0lx must be aligned on a "
+ "0x%0x boundary\n", base, PAGE_SIZE);
+ }
+
+ if (length != PAGE_SIZE)
+ panic("vmm_mem_free: invalid length %lu", length);
+
+ m = PHYS_TO_VM_PAGE(base);
+ m->wire_count--;
+ vm_page_free(m);
+ atomic_subtract_int(&cnt.v_wire_count, 1);
+
+ update_pages_allocated(-1);
+}
+
+vm_paddr_t
+vmm_mem_maxaddr(void)
+{
+
+ return (ptoa(Maxmem));
+}
diff --git a/sys/amd64/vmm/vmm_mem.h b/sys/amd64/vmm/vmm_mem.h
new file mode 100644
index 0000000..7d45c74
--- /dev/null
+++ b/sys/amd64/vmm/vmm_mem.h
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMM_MEM_H_
+#define _VMM_MEM_H_
+
+int vmm_mem_init(void);
+vm_paddr_t vmm_mem_alloc(size_t size);
+void vmm_mem_free(vm_paddr_t start, size_t size);
+vm_paddr_t vmm_mem_maxaddr(void);
+
+#endif
diff --git a/sys/amd64/vmm/vmm_msr.c b/sys/amd64/vmm/vmm_msr.c
new file mode 100644
index 0000000..d97c819
--- /dev/null
+++ b/sys/amd64/vmm/vmm_msr.c
@@ -0,0 +1,254 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+
+#include <machine/specialreg.h>
+
+#include <machine/vmm.h>
+#include "vmm_lapic.h"
+#include "vmm_msr.h"
+
+#define VMM_MSR_F_EMULATE 0x01
+#define VMM_MSR_F_READONLY 0x02
+#define VMM_MSR_F_INVALID 0x04 /* guest_msr_valid() can override this */
+
+struct vmm_msr {
+ int num;
+ int flags;
+ uint64_t hostval;
+};
+
+static struct vmm_msr vmm_msr[] = {
+ { MSR_LSTAR, 0 },
+ { MSR_CSTAR, 0 },
+ { MSR_STAR, 0 },
+ { MSR_SF_MASK, 0 },
+ { MSR_PAT, VMM_MSR_F_EMULATE | VMM_MSR_F_INVALID },
+ { MSR_BIOS_SIGN,VMM_MSR_F_EMULATE },
+ { MSR_MCG_CAP, VMM_MSR_F_EMULATE | VMM_MSR_F_READONLY },
+};
+
+#define vmm_msr_num (sizeof(vmm_msr) / sizeof(vmm_msr[0]))
+CTASSERT(VMM_MSR_NUM >= vmm_msr_num);
+
+#define readonly_msr(idx) \
+ ((vmm_msr[(idx)].flags & VMM_MSR_F_READONLY) != 0)
+
+#define emulated_msr(idx) \
+ ((vmm_msr[(idx)].flags & VMM_MSR_F_EMULATE) != 0)
+
+#define invalid_msr(idx) \
+ ((vmm_msr[(idx)].flags & VMM_MSR_F_INVALID) != 0)
+
+void
+vmm_msr_init(void)
+{
+ int i;
+
+ for (i = 0; i < vmm_msr_num; i++) {
+ if (emulated_msr(i))
+ continue;
+ /*
+ * XXX this assumes that the value of the host msr does not
+ * change after we have cached it.
+ */
+ vmm_msr[i].hostval = rdmsr(vmm_msr[i].num);
+ }
+}
+
+void
+guest_msrs_init(struct vm *vm, int cpu)
+{
+ int i;
+ uint64_t *guest_msrs;
+
+ guest_msrs = vm_guest_msrs(vm, cpu);
+
+ for (i = 0; i < vmm_msr_num; i++) {
+ switch (vmm_msr[i].num) {
+ case MSR_LSTAR:
+ case MSR_CSTAR:
+ case MSR_STAR:
+ case MSR_SF_MASK:
+ case MSR_BIOS_SIGN:
+ case MSR_MCG_CAP:
+ guest_msrs[i] = 0;
+ break;
+ case MSR_PAT:
+ guest_msrs[i] = PAT_VALUE(0, PAT_WRITE_BACK) |
+ PAT_VALUE(1, PAT_WRITE_THROUGH) |
+ PAT_VALUE(2, PAT_UNCACHED) |
+ PAT_VALUE(3, PAT_UNCACHEABLE) |
+ PAT_VALUE(4, PAT_WRITE_BACK) |
+ PAT_VALUE(5, PAT_WRITE_THROUGH) |
+ PAT_VALUE(6, PAT_UNCACHED) |
+ PAT_VALUE(7, PAT_UNCACHEABLE);
+ break;
+ default:
+ panic("guest_msrs_init: missing initialization for msr "
+ "0x%0x", vmm_msr[i].num);
+ }
+ }
+}
+
+static int
+msr_num_to_idx(u_int num)
+{
+ int i;
+
+ for (i = 0; i < vmm_msr_num; i++)
+ if (vmm_msr[i].num == num)
+ return (i);
+
+ return (-1);
+}
+
+int
+emulate_wrmsr(struct vm *vm, int cpu, u_int num, uint64_t val)
+{
+ int idx;
+ uint64_t *guest_msrs;
+
+ if (lapic_msr(num))
+ return (lapic_wrmsr(vm, cpu, num, val));
+
+ idx = msr_num_to_idx(num);
+ if (idx < 0 || invalid_msr(idx))
+ return (EINVAL);
+
+ if (!readonly_msr(idx)) {
+ guest_msrs = vm_guest_msrs(vm, cpu);
+
+ /* Stash the value */
+ guest_msrs[idx] = val;
+
+ /* Update processor state for non-emulated MSRs */
+ if (!emulated_msr(idx))
+ wrmsr(vmm_msr[idx].num, val);
+ }
+
+ return (0);
+}
+
+int
+emulate_rdmsr(struct vm *vm, int cpu, u_int num)
+{
+ int error, idx;
+ uint32_t eax, edx;
+ uint64_t result, *guest_msrs;
+
+ if (lapic_msr(num)) {
+ error = lapic_rdmsr(vm, cpu, num, &result);
+ goto done;
+ }
+
+ idx = msr_num_to_idx(num);
+ if (idx < 0 || invalid_msr(idx)) {
+ error = EINVAL;
+ goto done;
+ }
+
+ guest_msrs = vm_guest_msrs(vm, cpu);
+ result = guest_msrs[idx];
+
+ /*
+ * If this is not an emulated msr register make sure that the processor
+ * state matches our cached state.
+ */
+ if (!emulated_msr(idx) && (rdmsr(num) != result)) {
+ panic("emulate_rdmsr: msr 0x%0x has inconsistent cached "
+ "(0x%016lx) and actual (0x%016lx) values", num,
+ result, rdmsr(num));
+ }
+
+ error = 0;
+
+done:
+ if (error == 0) {
+ eax = result;
+ edx = result >> 32;
+ error = vm_set_register(vm, cpu, VM_REG_GUEST_RAX, eax);
+ if (error)
+ panic("vm_set_register(rax) error %d", error);
+ error = vm_set_register(vm, cpu, VM_REG_GUEST_RDX, edx);
+ if (error)
+ panic("vm_set_register(rdx) error %d", error);
+ }
+ return (error);
+}
+
+void
+restore_guest_msrs(struct vm *vm, int cpu)
+{
+ int i;
+ uint64_t *guest_msrs;
+
+ guest_msrs = vm_guest_msrs(vm, cpu);
+
+ for (i = 0; i < vmm_msr_num; i++) {
+ if (emulated_msr(i))
+ continue;
+ else
+ wrmsr(vmm_msr[i].num, guest_msrs[i]);
+ }
+}
+
+void
+restore_host_msrs(struct vm *vm, int cpu)
+{
+ int i;
+
+ for (i = 0; i < vmm_msr_num; i++) {
+ if (emulated_msr(i))
+ continue;
+ else
+ wrmsr(vmm_msr[i].num, vmm_msr[i].hostval);
+ }
+}
+
+/*
+ * Must be called by the CPU-specific code before any guests are
+ * created
+ */
+void
+guest_msr_valid(int msr)
+{
+ int i;
+
+ for (i = 0; i < vmm_msr_num; i++) {
+ if (vmm_msr[i].num == msr && invalid_msr(i)) {
+ vmm_msr[i].flags &= ~VMM_MSR_F_INVALID;
+ }
+ }
+}
diff --git a/sys/amd64/vmm/vmm_msr.h b/sys/amd64/vmm/vmm_msr.h
new file mode 100644
index 0000000..8a1fda3
--- /dev/null
+++ b/sys/amd64/vmm/vmm_msr.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMM_MSR_H_
+#define _VMM_MSR_H_
+
+#define VMM_MSR_NUM 16
+struct vm;
+
+void vmm_msr_init(void);
+int emulate_wrmsr(struct vm *vm, int vcpu, u_int msr, uint64_t val);
+int emulate_rdmsr(struct vm *vm, int vcpu, u_int msr);
+void guest_msrs_init(struct vm *vm, int cpu);
+void guest_msr_valid(int msr);
+void restore_host_msrs(struct vm *vm, int cpu);
+void restore_guest_msrs(struct vm *vm, int cpu);
+
+#endif
diff --git a/sys/amd64/vmm/vmm_stat.c b/sys/amd64/vmm/vmm_stat.c
new file mode 100644
index 0000000..ae60979
--- /dev/null
+++ b/sys/amd64/vmm/vmm_stat.c
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/smp.h>
+
+#include <machine/vmm.h>
+#include "vmm_stat.h"
+
+static int vstnum;
+static struct vmm_stat_type *vsttab[MAX_VMM_STAT_TYPES];
+
+static MALLOC_DEFINE(M_VMM_STAT, "vmm stat", "vmm stat");
+
+void
+vmm_stat_init(void *arg)
+{
+ struct vmm_stat_type *vst = arg;
+
+ /* We require all stats to identify themselves with a description */
+ if (vst->desc == NULL)
+ return;
+
+ if (vstnum >= MAX_VMM_STAT_TYPES) {
+ printf("Cannot accomodate vmm stat type \"%s\"!\n", vst->desc);
+ return;
+ }
+
+ vst->index = vstnum;
+ vsttab[vstnum++] = vst;
+}
+
+int
+vmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf)
+{
+ int i;
+ uint64_t *stats;
+
+ if (vcpu < 0 || vcpu >= VM_MAXCPU)
+ return (EINVAL);
+
+ stats = vcpu_stats(vm, vcpu);
+ for (i = 0; i < vstnum; i++)
+ buf[i] = stats[i];
+ *num_stats = vstnum;
+ return (0);
+}
+
+void *
+vmm_stat_alloc(void)
+{
+ u_long size;
+
+ size = vstnum * sizeof(uint64_t);
+
+ return (malloc(size, M_VMM_STAT, M_ZERO | M_WAITOK));
+}
+
+void
+vmm_stat_free(void *vp)
+{
+ free(vp, M_VMM_STAT);
+}
+
+const char *
+vmm_stat_desc(int index)
+{
+
+ if (index >= 0 && index < vstnum)
+ return (vsttab[index]->desc);
+ else
+ return (NULL);
+}
diff --git a/sys/amd64/vmm/vmm_stat.h b/sys/amd64/vmm/vmm_stat.h
new file mode 100644
index 0000000..7c075a6
--- /dev/null
+++ b/sys/amd64/vmm/vmm_stat.h
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VMM_STAT_H_
+#define _VMM_STAT_H_
+
+struct vm;
+
+#define MAX_VMM_STAT_TYPES 64 /* arbitrary */
+
+struct vmm_stat_type {
+ const char *desc; /* description of statistic */
+ int index; /* position in the stats buffer */
+};
+
+void vmm_stat_init(void *arg);
+
+#define VMM_STAT_DEFINE(type, desc) \
+ struct vmm_stat_type type[1] = { \
+ { desc, -1 } \
+ }; \
+ SYSINIT(type##_stat, SI_SUB_KLD, SI_ORDER_ANY, vmm_stat_init, type)
+
+void *vmm_stat_alloc(void);
+void vmm_stat_free(void *vp);
+
+/*
+ * 'buf' should be at least fit 'MAX_VMM_STAT_TYPES' entries
+ */
+int vmm_stat_copy(struct vm *vm, int vcpu, int *num_stats, uint64_t *buf);
+const char *vmm_stat_desc(int index);
+
+static void __inline
+vmm_stat_incr(struct vm *vm, int vcpu, struct vmm_stat_type *vst, uint64_t x)
+{
+#ifdef VMM_KEEP_STATS
+ uint64_t *stats = vcpu_stats(vm, vcpu);
+ if (vst->index >= 0)
+ stats[vst->index] += x;
+#endif
+}
+
+#endif
diff --git a/sys/amd64/vmm/vmm_support.S b/sys/amd64/vmm/vmm_support.S
new file mode 100644
index 0000000..2afc608
--- /dev/null
+++ b/sys/amd64/vmm/vmm_support.S
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define LOCORE
+
+#include <machine/asmacros.h>
+
+#define LA_EOI 0xB0
+
+ .text
+ SUPERALIGN_TEXT
+IDTVEC(justreturn)
+ pushq %rax
+ movq lapic, %rax
+ movl $0, LA_EOI(%rax)
+ popq %rax
+ iretq
diff --git a/sys/amd64/vmm/vmm_util.c b/sys/amd64/vmm/vmm_util.c
new file mode 100644
index 0000000..f245f92
--- /dev/null
+++ b/sys/amd64/vmm/vmm_util.c
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/libkern.h>
+
+#include <machine/md_var.h>
+
+#include "vmm_util.h"
+
+boolean_t
+vmm_is_intel(void)
+{
+
+ if (strcmp(cpu_vendor, "GenuineIntel") == 0)
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+boolean_t
+vmm_is_amd(void)
+{
+ if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+boolean_t
+vmm_supports_1G_pages(void)
+{
+ unsigned int regs[4];
+
+ /*
+ * CPUID.80000001:EDX[bit 26] = 1 indicates support for 1GB pages
+ *
+ * Both Intel and AMD support this bit.
+ */
+ if (cpu_exthigh >= 0x80000001) {
+ do_cpuid(0x80000001, regs);
+ if (regs[3] & (1 << 26))
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+#include <sys/proc.h>
+#include <machine/frame.h>
+#define DUMP_REG(x) printf(#x "\t\t0x%016lx\n", (long)(tf->tf_ ## x))
+#define DUMP_SEG(x) printf(#x "\t\t0x%04x\n", (unsigned)(tf->tf_ ## x))
+void
+dump_trapframe(struct trapframe *tf)
+{
+ DUMP_REG(rdi);
+ DUMP_REG(rsi);
+ DUMP_REG(rdx);
+ DUMP_REG(rcx);
+ DUMP_REG(r8);
+ DUMP_REG(r9);
+ DUMP_REG(rax);
+ DUMP_REG(rbx);
+ DUMP_REG(rbp);
+ DUMP_REG(r10);
+ DUMP_REG(r11);
+ DUMP_REG(r12);
+ DUMP_REG(r13);
+ DUMP_REG(r14);
+ DUMP_REG(r15);
+ DUMP_REG(trapno);
+ DUMP_REG(addr);
+ DUMP_REG(flags);
+ DUMP_REG(err);
+ DUMP_REG(rip);
+ DUMP_REG(rflags);
+ DUMP_REG(rsp);
+ DUMP_SEG(cs);
+ DUMP_SEG(ss);
+ DUMP_SEG(fs);
+ DUMP_SEG(gs);
+ DUMP_SEG(es);
+ DUMP_SEG(ds);
+}
diff --git a/sys/amd64/vmm/vmm_util.h b/sys/amd64/vmm/vmm_util.h
new file mode 100644
index 0000000..7f82332
--- /dev/null
+++ b/sys/amd64/vmm/vmm_util.h
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _VMM_UTIL_H_
+#define _VMM_UTIL_H_
+
+struct trapframe;
+
+boolean_t vmm_is_intel(void);
+boolean_t vmm_is_amd(void);
+boolean_t vmm_supports_1G_pages(void);
+
+void dump_trapframe(struct trapframe *tf);
+
+#endif
diff --git a/sys/amd64/vmm/x86.c b/sys/amd64/vmm/x86.c
new file mode 100644
index 0000000..94abe09
--- /dev/null
+++ b/sys/amd64/vmm/x86.c
@@ -0,0 +1,202 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/cpuset.h>
+
+#include <machine/cpufunc.h>
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+
+#include <machine/vmm.h>
+
+#include "x86.h"
+
+#define CPUID_VM_HIGH 0x40000000
+
+static const char bhyve_id[12] = "BHyVE BHyVE ";
+
+int
+x86_emulate_cpuid(struct vm *vm, int vcpu_id,
+ uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+{
+ int error;
+ unsigned int func, regs[4];
+ enum x2apic_state x2apic_state;
+
+ func = *eax;
+
+ /*
+ * Requests for invalid CPUID levels should map to the highest
+ * available level instead.
+ */
+ if (cpu_exthigh != 0 && *eax >= 0x80000000) {
+ if (*eax > cpu_exthigh)
+ *eax = cpu_exthigh;
+ } else if (*eax >= 0x40000000) {
+ if (*eax > CPUID_VM_HIGH)
+ *eax = CPUID_VM_HIGH;
+ } else if (*eax > cpu_high) {
+ *eax = cpu_high;
+ }
+
+ /*
+ * In general the approach used for CPU topology is to
+ * advertise a flat topology where all CPUs are packages with
+ * no multi-core or SMT.
+ */
+ switch (func) {
+ case CPUID_0000_0000:
+ case CPUID_0000_0002:
+ case CPUID_0000_0003:
+ case CPUID_0000_000A:
+ cpuid_count(*eax, *ecx, regs);
+ break;
+
+ case CPUID_8000_0000:
+ case CPUID_8000_0001:
+ case CPUID_8000_0002:
+ case CPUID_8000_0003:
+ case CPUID_8000_0004:
+ case CPUID_8000_0006:
+ case CPUID_8000_0007:
+ case CPUID_8000_0008:
+ cpuid_count(*eax, *ecx, regs);
+ break;
+
+ case CPUID_0000_0001:
+ do_cpuid(1, regs);
+
+ error = vm_get_x2apic_state(vm, vcpu_id, &x2apic_state);
+ if (error) {
+ panic("x86_emulate_cpuid: error %d "
+ "fetching x2apic state", error);
+ }
+
+ /*
+ * Override the APIC ID only in ebx
+ */
+ regs[1] &= ~(CPUID_LOCAL_APIC_ID);
+ regs[1] |= (vcpu_id << CPUID_0000_0001_APICID_SHIFT);
+
+ /*
+ * Don't expose VMX, SpeedStep or TME capability.
+ * Advertise x2APIC capability and Hypervisor guest.
+ */
+ regs[2] &= ~(CPUID2_VMX | CPUID2_EST | CPUID2_TM2);
+
+ regs[2] |= CPUID2_HV;
+
+ if (x2apic_state != X2APIC_DISABLED)
+ regs[2] |= CPUID2_X2APIC;
+
+ /*
+ * Hide xsave/osxsave/avx until the FPU save/restore
+ * issues are resolved
+ */
+ regs[2] &= ~(CPUID2_XSAVE | CPUID2_OSXSAVE |
+ CPUID2_AVX);
+
+ /*
+ * Hide monitor/mwait until we know how to deal with
+ * these instructions.
+ */
+ regs[2] &= ~CPUID2_MON;
+
+ /*
+ * Hide thermal monitoring
+ */
+ regs[3] &= ~(CPUID_ACPI | CPUID_TM);
+
+ /*
+ * Machine check handling is done in the host.
+ * Hide MTRR capability.
+ */
+ regs[3] &= ~(CPUID_MCA | CPUID_MCE | CPUID_MTRR);
+
+ /*
+ * Disable multi-core.
+ */
+ regs[1] &= ~CPUID_HTT_CORES;
+ regs[3] &= ~CPUID_HTT;
+ break;
+
+ case CPUID_0000_0004:
+ do_cpuid(4, regs);
+
+ /*
+ * Do not expose topology.
+ */
+ regs[0] &= 0xffff8000;
+ regs[0] |= 0x04008000;
+ break;
+
+ case CPUID_0000_0006:
+ case CPUID_0000_0007:
+ /*
+ * Handle the access, but report 0 for
+ * all options
+ */
+ regs[0] = 0;
+ regs[1] = 0;
+ regs[2] = 0;
+ regs[3] = 0;
+ break;
+
+ case CPUID_0000_000B:
+ /*
+ * Processor topology enumeration
+ */
+ regs[0] = 0;
+ regs[1] = 0;
+ regs[2] = *ecx & 0xff;
+ regs[3] = vcpu_id;
+ break;
+
+ case 0x40000000:
+ regs[0] = CPUID_VM_HIGH;
+ bcopy(bhyve_id, &regs[1], 4);
+ bcopy(bhyve_id, &regs[2], 4);
+ bcopy(bhyve_id, &regs[3], 4);
+ break;
+ default:
+ /* XXX: Leaf 5? */
+ return (0);
+ }
+
+ *eax = regs[0];
+ *ebx = regs[1];
+ *ecx = regs[2];
+ *edx = regs[3];
+ return (1);
+}
diff --git a/sys/amd64/vmm/x86.h b/sys/amd64/vmm/x86.h
new file mode 100644
index 0000000..368e967
--- /dev/null
+++ b/sys/amd64/vmm/x86.h
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC 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 _X86_H_
+#define _X86_H_
+
+#define CPUID_0000_0000 (0x0)
+#define CPUID_0000_0001 (0x1)
+#define CPUID_0000_0002 (0x2)
+#define CPUID_0000_0003 (0x3)
+#define CPUID_0000_0004 (0x4)
+#define CPUID_0000_0006 (0x6)
+#define CPUID_0000_0007 (0x7)
+#define CPUID_0000_000A (0xA)
+#define CPUID_0000_000B (0xB)
+#define CPUID_8000_0000 (0x80000000)
+#define CPUID_8000_0001 (0x80000001)
+#define CPUID_8000_0002 (0x80000002)
+#define CPUID_8000_0003 (0x80000003)
+#define CPUID_8000_0004 (0x80000004)
+#define CPUID_8000_0006 (0x80000006)
+#define CPUID_8000_0007 (0x80000007)
+#define CPUID_8000_0008 (0x80000008)
+
+/*
+ * CPUID instruction Fn0000_0001:
+ */
+#define CPUID_0000_0001_APICID_MASK (0xff<<24)
+#define CPUID_0000_0001_APICID_SHIFT 24
+
+/*
+ * CPUID instruction Fn0000_0001 ECX
+ */
+#define CPUID_0000_0001_FEAT0_VMX (1<<5)
+
+int x86_emulate_cpuid(struct vm *vm, int vcpu_id, uint32_t *eax, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx);
+
+#endif
diff --git a/sys/arm/allwinner/a10_clk.c b/sys/arm/allwinner/a10_clk.c
new file mode 100644
index 0000000..2d7699e
--- /dev/null
+++ b/sys/arm/allwinner/a10_clk.c
@@ -0,0 +1,171 @@
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Simple clock driver for Allwinner A10 */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include "a10_clk.h"
+
+struct a10_ccm_softc {
+ struct resource *res;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+};
+
+static struct a10_ccm_softc *a10_ccm_sc = NULL;
+
+#define ccm_read_4(reg) \
+ bus_space_read_4(a10_ccm_sc->bst, a10_ccm_sc->bsh, reg)
+#define ccm_write_4(reg, val) \
+ bus_space_write_4(a10_ccm_sc->bst, a10_ccm_sc->bsh, reg, val)
+
+static int
+a10_ccm_probe(device_t dev)
+{
+ if (ofw_bus_is_compatible(dev, "allwinner,sun4i-ccm")) {
+ device_set_desc(dev, "Allwinner Clock Control Module");
+ return(BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+a10_ccm_attach(device_t dev)
+{
+ struct a10_ccm_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ if (a10_ccm_sc)
+ return (ENXIO);
+
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->res) {
+ device_printf(dev, "could not allocate resource\n");
+ return (ENXIO);
+ }
+
+ sc->bst = rman_get_bustag(sc->res);
+ sc->bsh = rman_get_bushandle(sc->res);
+
+ a10_ccm_sc = sc;
+
+ return (0);
+}
+
+static device_method_t a10_ccm_methods[] = {
+ DEVMETHOD(device_probe, a10_ccm_probe),
+ DEVMETHOD(device_attach, a10_ccm_attach),
+ { 0, 0 }
+};
+
+static driver_t a10_ccm_driver = {
+ "a10_ccm",
+ a10_ccm_methods,
+ sizeof(struct a10_ccm_softc),
+};
+
+static devclass_t a10_ccm_devclass;
+
+DRIVER_MODULE(a10_ccm, simplebus, a10_ccm_driver, a10_ccm_devclass, 0, 0);
+
+int
+a10_clk_usb_activate(void)
+{
+ struct a10_ccm_softc *sc = a10_ccm_sc;
+ uint32_t reg_value = 0;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ /* Gating AHB clock for USB */
+ reg_value = ccm_read_4(CCM_AHB_GATING0);
+ reg_value |= CCM_AHB_GATING_USB0; /* AHB clock gate usb0 */
+ reg_value |= CCM_AHB_GATING_EHCI1; /* AHB clock gate ehci1 */
+ ccm_write_4(CCM_AHB_GATING0, reg_value);
+
+ /* Enable clock for USB */
+ reg_value = ccm_read_4(CCM_USB_CLK);
+ reg_value |= CCM_USB_PHY; /* USBPHY */
+ reg_value |= CCM_USB0_RESET; /* disable reset for USB0 */
+ reg_value |= CCM_USB1_RESET; /* disable reset for USB1 */
+ reg_value |= CCM_USB2_RESET; /* disable reset for USB2 */
+ ccm_write_4(CCM_USB_CLK, reg_value);
+
+ return (0);
+}
+
+int
+a10_clk_usb_deactivate(void)
+{
+ struct a10_ccm_softc *sc = a10_ccm_sc;
+ uint32_t reg_value = 0;
+
+ if (sc == NULL)
+ return ENXIO;
+
+ /* Disable clock for USB */
+ reg_value = ccm_read_4(CCM_USB_CLK);
+ reg_value &= ~CCM_USB_PHY; /* USBPHY */
+ reg_value &= ~CCM_USB0_RESET; /* reset for USB0 */
+ reg_value &= ~CCM_USB1_RESET; /* reset for USB1 */
+ reg_value &= ~CCM_USB2_RESET; /* reset for USB2 */
+ ccm_write_4(CCM_USB_CLK, reg_value);
+
+ /* Disable gating AHB clock for USB */
+ reg_value = ccm_read_4(CCM_AHB_GATING0);
+ reg_value &= ~CCM_AHB_GATING_USB0; /* disable AHB clock gate usb0 */
+ reg_value &= ~CCM_AHB_GATING_EHCI1; /* disable AHB clock gate ehci1 */
+ ccm_write_4(CCM_AHB_GATING0, reg_value);
+
+ return (0);
+}
+
diff --git a/sys/arm/allwinner/a10_clk.h b/sys/arm/allwinner/a10_clk.h
new file mode 100644
index 0000000..7316a22
--- /dev/null
+++ b/sys/arm/allwinner/a10_clk.h
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _A10_CLK_H_
+#define _A10_CLK_H_
+
+#define CCMU_BASE 0xe1c20000
+
+#define CCM_PLL1_CFG 0x0000
+#define CCM_PLL1_TUN 0x0004
+#define CCM_PLL2_CFG 0x0008
+#define CCM_PLL2_TUN 0x000c
+#define CCM_PLL3_CFG 0x0010
+#define CCM_PLL3_TUN 0x0014
+#define CCM_PLL4_CFG 0x0018
+#define CCM_PLL4_TUN 0x001c
+#define CCM_PLL5_CFG 0x0020
+#define CCM_PLL5_TUN 0x0024
+#define CCM_PLL6_CFG 0x0028
+#define CCM_PLL6_TUN 0x002c
+#define CCM_PLL7_CFG 0x0030
+#define CCM_PLL7_TUN 0x0034
+#define CCM_PLL1_TUN2 0x0038
+#define CCM_PLL5_TUN2 0x003c
+#define CCM_PLL_LOCK_DBG 0x004c
+#define CCM_OSC24M_CFG 0x0050
+#define CCM_CPU_AHB_APB0_CFG 0x0054
+#define CCM_APB1_CLK_DIV 0x0058
+#define CCM_AXI_GATING 0x005c
+#define CCM_AHB_GATING0 0x0060
+#define CCM_AHB_GATING1 0x0064
+#define CCM_APB0_GATING 0x0068
+#define CCM_APB1_GATING 0x006c
+#define CCM_NAND_SCLK_CFG 0x0080
+#define CCM_MS_SCLK_CFG 0x0084
+#define CCM_MMC0_SCLK_CFG 0x0088
+#define CCM_MMC1_SCLK_CFG 0x008c
+#define CCM_MMC2_SCLK_CFG 0x0090
+#define CCM_MMC3_SCLK_CFG 0x0094
+#define CCM_TS_CLK 0x0098
+#define CCM_SS_CLK 0x009c
+#define CCM_SPI0_CLK 0x00a0
+#define CCM_SPI1_CLK 0x00a4
+#define CCM_SPI2_CLK 0x00a8
+#define CCM_PATA_CLK 0x00ac
+#define CCM_IR0_CLK 0x00b0
+#define CCM_IR1_CLK 0x00b4
+#define CCM_IIS_CLK 0x00b8
+#define CCM_AC97_CLK 0x00bc
+#define CCM_SPDIF_CLK 0x00c0
+#define CCM_KEYPAD_CLK 0x00c4
+#define CCM_SATA_CLK 0x00c8
+#define CCM_USB_CLK 0x00cc
+#define CCM_GPS_CLK 0x00d0
+#define CCM_SPI3_CLK 0x00d4
+#define CCM_DRAM_CLK 0x0100
+#define CCM_BE0_SCLK 0x0104
+#define CCM_BE1_SCLK 0x0108
+#define CCM_FE0_CLK 0x010c
+#define CCM_FE1_CLK 0x0110
+#define CCM_MP_CLK 0x0114
+#define CCM_LCD0_CH0_CLK 0x0118
+#define CCM_LCD1_CH0_CLK 0x011c
+#define CCM_CSI_ISP_CLK 0x0120
+#define CCM_TVD_CLK 0x0128
+#define CCM_LCD0_CH1_CLK 0x012c
+#define CCM_LCD1_CH1_CLK 0x0130
+#define CCM_CS0_CLK 0x0134
+#define CCM_CS1_CLK 0x0138
+#define CCM_VE_CLK 0x013c
+#define CCM_AUDIO_CODEC_CLK 0x0140
+#define CCM_AVS_CLK 0x0144
+#define CCM_ACE_CLK 0x0148
+#define CCM_LVDS_CLK 0x014c
+#define CCM_HDMI_CLK 0x0150
+#define CCM_MALI400_CLK 0x0154
+
+#define CCM_AHB_GATING_USB0 (1 << 0)
+#define CCM_AHB_GATING_EHCI1 (1 << 3)
+
+#define CCM_USB_PHY (1 << 8)
+#define CCM_USB0_RESET (1 << 0)
+#define CCM_USB1_RESET (1 << 1)
+#define CCM_USB2_RESET (1 << 2)
+
+int a10_clk_usb_activate(void);
+int a10_clk_usb_deactivate(void);
+
+#endif /* _A10_CLK_H_ */
diff --git a/sys/arm/allwinner/a10_ehci.c b/sys/arm/allwinner/a10_ehci.c
new file mode 100644
index 0000000..d3a90d0
--- /dev/null
+++ b/sys/arm/allwinner/a10_ehci.c
@@ -0,0 +1,279 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Allwinner A10 attachment driver for the USB Enhanced Host Controller.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_bus.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/condvar.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+
+#include "a10_clk.h"
+
+#define EHCI_HC_DEVSTR "Allwinner Integrated USB 2.0 controller"
+
+#define SW_USB_PMU_IRQ_ENABLE 0x800
+
+#define SW_SDRAM_REG_HPCR_USB1 (0x250 + ((1 << 2) * 4))
+#define SW_SDRAM_REG_HPCR_USB2 (0x250 + ((1 << 2) * 5))
+#define SW_SDRAM_BP_HPCR_ACCESS (1 << 0)
+
+#define SW_ULPI_BYPASS (1 << 0)
+#define SW_AHB_INCRX_ALIGN (1 << 8)
+#define SW_AHB_INCR4 (1 << 9)
+#define SW_AHB_INCR8 (1 << 10)
+
+#define A10_READ_4(sc, reg) \
+ bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
+
+#define A10_WRITE_4(sc, reg, data) \
+ bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data)
+
+static device_attach_t a10_ehci_attach;
+static device_detach_t a10_ehci_detach;
+
+bs_r_1_proto(reversed);
+bs_w_1_proto(reversed);
+
+static int
+a10_ehci_probe(device_t self)
+{
+ if (!ofw_bus_is_compatible(self, "allwinner,usb-ehci"))
+ return (ENXIO);
+
+ device_set_desc(self, EHCI_HC_DEVSTR);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10_ehci_attach(device_t self)
+{
+ ehci_softc_t *sc = device_get_softc(self);
+ bus_space_handle_t bsh;
+ int err;
+ int rid;
+ uint32_t reg_value = 0;
+
+ /* initialise some bus fields */
+ sc->sc_bus.parent = self;
+ sc->sc_bus.devices = sc->sc_devices;
+ sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+
+ /* get all DMA memory */
+ if (usb_bus_mem_alloc_all(&sc->sc_bus,
+ USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
+ return (ENOMEM);
+ }
+
+ sc->sc_bus.usbrev = USB_REV_2_0;
+
+ rid = 0;
+ sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->sc_io_res) {
+ device_printf(self, "Could not map memory\n");
+ goto error;
+ }
+
+ sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
+ sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
+ bsh = rman_get_bushandle(sc->sc_io_res);
+
+ sc->sc_io_size = rman_get_size(sc->sc_io_res);
+
+ if (bus_space_subregion(sc->sc_io_tag, bsh, 0x00,
+ sc->sc_io_size, &sc->sc_io_hdl) != 0)
+ panic("%s: unable to subregion USB host registers",
+ device_get_name(self));
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(self, "Could not allocate irq\n");
+ goto error;
+ }
+ sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
+ if (!sc->sc_bus.bdev) {
+ device_printf(self, "Could not add USB device\n");
+ goto error;
+ }
+ device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+ device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);
+
+ sprintf(sc->sc_vendor, "Allwinner");
+
+ err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+ if (err) {
+ device_printf(self, "Could not setup irq, %d\n", err);
+ sc->sc_intr_hdl = NULL;
+ goto error;
+ }
+
+ sc->sc_flags |= EHCI_SCFLG_DONTRESET;
+
+ /* Enable clock for USB */
+ a10_clk_usb_activate();
+
+ /* Enable passby */
+ reg_value = A10_READ_4(sc, SW_USB_PMU_IRQ_ENABLE);
+ reg_value |= SW_AHB_INCR8; /* AHB INCR8 enable */
+ reg_value |= SW_AHB_INCR4; /* AHB burst type INCR4 enable */
+ reg_value |= SW_AHB_INCRX_ALIGN; /* AHB INCRX align enable */
+ reg_value |= SW_ULPI_BYPASS; /* ULPI bypass enable */
+ A10_WRITE_4(sc, SW_USB_PMU_IRQ_ENABLE, reg_value);
+
+ /* Configure port */
+ reg_value = A10_READ_4(sc, SW_SDRAM_REG_HPCR_USB2);
+ reg_value |= SW_SDRAM_BP_HPCR_ACCESS;
+ A10_WRITE_4(sc, SW_SDRAM_REG_HPCR_USB2, reg_value);
+
+ err = ehci_init(sc);
+ if (!err) {
+ err = device_probe_and_attach(sc->sc_bus.bdev);
+ }
+ if (err) {
+ device_printf(self, "USB init failed err=%d\n", err);
+ goto error;
+ }
+ return (0);
+
+error:
+ a10_ehci_detach(self);
+ return (ENXIO);
+}
+
+static int
+a10_ehci_detach(device_t self)
+{
+ ehci_softc_t *sc = device_get_softc(self);
+ device_t bdev;
+ int err;
+ uint32_t reg_value = 0;
+
+ if (sc->sc_bus.bdev) {
+ bdev = sc->sc_bus.bdev;
+ device_detach(bdev);
+ device_delete_child(self, bdev);
+ }
+ /* during module unload there are lots of children leftover */
+ device_delete_children(self);
+
+ if (sc->sc_irq_res && sc->sc_intr_hdl) {
+ /*
+ * only call ehci_detach() after ehci_init()
+ */
+ ehci_detach(sc);
+
+ err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
+
+ if (err)
+ /* XXX or should we panic? */
+ device_printf(self, "Could not tear down irq, %d\n",
+ err);
+ sc->sc_intr_hdl = NULL;
+ }
+
+ if (sc->sc_irq_res) {
+ bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ sc->sc_irq_res = NULL;
+ }
+ if (sc->sc_io_res) {
+ bus_release_resource(self, SYS_RES_MEMORY, 0,
+ sc->sc_io_res);
+ sc->sc_io_res = NULL;
+ }
+ usb_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
+
+ /* Disable configure port */
+ reg_value = A10_READ_4(sc, SW_SDRAM_REG_HPCR_USB2);
+ reg_value &= ~SW_SDRAM_BP_HPCR_ACCESS;
+ A10_WRITE_4(sc, SW_SDRAM_REG_HPCR_USB2, reg_value);
+
+ /* Disable passby */
+ reg_value = A10_READ_4(sc, SW_USB_PMU_IRQ_ENABLE);
+ reg_value &= ~SW_AHB_INCR8; /* AHB INCR8 disable */
+ reg_value &= ~SW_AHB_INCR4; /* AHB burst type INCR4 disable */
+ reg_value &= ~SW_AHB_INCRX_ALIGN; /* AHB INCRX align disable */
+ reg_value &= ~SW_ULPI_BYPASS; /* ULPI bypass disable */
+ A10_WRITE_4(sc, SW_USB_PMU_IRQ_ENABLE, reg_value);
+
+ /* Disable clock for USB */
+ a10_clk_usb_deactivate();
+
+ return (0);
+}
+
+static device_method_t ehci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, a10_ehci_probe),
+ DEVMETHOD(device_attach, a10_ehci_attach),
+ DEVMETHOD(device_detach, a10_ehci_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ DEVMETHOD_END
+};
+
+static driver_t ehci_driver = {
+ .name = "ehci",
+ .methods = ehci_methods,
+ .size = sizeof(ehci_softc_t),
+};
+
+static devclass_t ehci_devclass;
+
+DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0);
+MODULE_DEPEND(ehci, usb, 1, 1, 1);
diff --git a/sys/arm/allwinner/a10_machdep.c b/sys/arm/allwinner/a10_machdep.c
new file mode 100644
index 0000000..1ad9ea1
--- /dev/null
+++ b/sys/arm/allwinner/a10_machdep.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * All rights reserved.
+ *
+ * This code is derived from software written for Brini by Mark Brinicombe
+ *
+ * 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.
+ *
+ * from: FreeBSD: //depot/projects/arm/src/sys/arm/ti/ti_machdep.c
+ */
+
+#include "opt_ddb.h"
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/frame.h> /* For trapframe_t, used in <machine/machdep.h> */
+#include <machine/machdep.h>
+#include <machine/pmap.h>
+
+#include <dev/fdt/fdt_common.h>
+
+/* Start of address space used for bootstrap map */
+#define DEVMAP_BOOTSTRAP_MAP_START 0xE0000000
+
+void (*a10_cpu_reset)(void);
+
+vm_offset_t
+initarm_lastaddr(void)
+{
+
+ a10_cpu_reset = NULL;
+ return (DEVMAP_BOOTSTRAP_MAP_START - ARM_NOCACHE_KVA_SIZE);
+}
+
+void
+initarm_gpio_init(void)
+{
+}
+
+void
+initarm_late_init(void)
+{
+}
+
+#define FDT_DEVMAP_MAX (1 + 2 + 1 + 1)
+static struct pmap_devmap fdt_devmap[FDT_DEVMAP_MAX] = {
+ { 0, 0, 0, 0, 0, }
+};
+
+/*
+ * Construct pmap_devmap[] with DT-derived config data.
+ */
+int
+platform_devmap_init(void)
+{
+ int i = 0;
+
+ fdt_devmap[i].pd_va = 0xE1C00000;
+ fdt_devmap[i].pd_pa = 0x01C00000;
+ fdt_devmap[i].pd_size = 0x00400000; /* 4 MB */
+ fdt_devmap[i].pd_prot = VM_PROT_READ | VM_PROT_WRITE;
+ fdt_devmap[i].pd_cache = PTE_DEVICE;
+
+ i++;
+
+ pmap_devmap_bootstrap_table = &fdt_devmap[0];
+
+ return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+ return (0);
+}
+
+void
+cpu_reset()
+{
+ if (a10_cpu_reset)
+ (*a10_cpu_reset)();
+ else
+ printf("no cpu_reset implementation\n");
+ printf("Reset failed!\n");
+ while (1);
+}
diff --git a/sys/arm/allwinner/aintc.c b/sys/arm/allwinner/aintc.c
new file mode 100644
index 0000000..bfa35f5
--- /dev/null
+++ b/sys/arm/allwinner/aintc.c
@@ -0,0 +1,211 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/**
+ * Interrupt controller registers
+ *
+ */
+#define SW_INT_VECTOR_REG 0x00
+#define SW_INT_BASE_ADR_REG 0x04
+#define SW_INT_PROTECTION_REG 0x08
+#define SW_INT_NMI_CTRL_REG 0x0c
+
+#define SW_INT_IRQ_PENDING_REG0 0x10
+#define SW_INT_IRQ_PENDING_REG1 0x14
+#define SW_INT_IRQ_PENDING_REG2 0x18
+
+#define SW_INT_FIQ_PENDING_REG0 0x20
+#define SW_INT_FIQ_PENDING_REG1 0x24
+#define SW_INT_FIQ_PENDING_REG2 0x28
+
+#define SW_INT_SELECT_REG0 0x30
+#define SW_INT_SELECT_REG1 0x34
+#define SW_INT_SELECT_REG2 0x38
+
+#define SW_INT_ENABLE_REG0 0x40
+#define SW_INT_ENABLE_REG1 0x44
+#define SW_INT_ENABLE_REG2 0x48
+
+#define SW_INT_MASK_REG0 0x50
+#define SW_INT_MASK_REG1 0x54
+#define SW_INT_MASK_REG2 0x58
+
+#define SW_INT_IRQNO_ENMI 0
+
+#define SW_INT_IRQ_PENDING_REG(_b) (0x10 + ((_b) * 4))
+#define SW_INT_FIQ_PENDING_REG(_b) (0x20 + ((_b) * 4))
+#define SW_INT_SELECT_REG(_b) (0x30 + ((_b) * 4))
+#define SW_INT_ENABLE_REG(_b) (0x40 + ((_b) * 4))
+#define SW_INT_MASK_REG(_b) (0x50 + ((_b) * 4))
+
+struct a10_aintc_softc {
+ device_t sc_dev;
+ struct resource * aintc_res;
+ bus_space_tag_t aintc_bst;
+ bus_space_handle_t aintc_bsh;
+ uint8_t ver;
+};
+
+static struct a10_aintc_softc *a10_aintc_sc = NULL;
+
+#define aintc_read_4(reg) \
+ bus_space_read_4(a10_aintc_sc->aintc_bst, a10_aintc_sc->aintc_bsh, reg)
+#define aintc_write_4(reg, val) \
+ bus_space_write_4(a10_aintc_sc->aintc_bst, a10_aintc_sc->aintc_bsh, reg, val)
+
+static int
+a10_aintc_probe(device_t dev)
+{
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-ic"))
+ return (ENXIO);
+ device_set_desc(dev, "A10 AINTC Interrupt Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10_aintc_attach(device_t dev)
+{
+ struct a10_aintc_softc *sc = device_get_softc(dev);
+ int rid = 0;
+ int i;
+
+ sc->sc_dev = dev;
+
+ if (a10_aintc_sc)
+ return (ENXIO);
+
+ sc->aintc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->aintc_res) {
+ device_printf(dev, "could not allocate resource\n");
+ return (ENXIO);
+ }
+
+ sc->aintc_bst = rman_get_bustag(sc->aintc_res);
+ sc->aintc_bsh = rman_get_bushandle(sc->aintc_res);
+
+ a10_aintc_sc = sc;
+
+ /* Disable & clear all interrupts */
+ for (i = 0; i < 3; i++) {
+ aintc_write_4(SW_INT_ENABLE_REG(i), 0);
+ aintc_write_4(SW_INT_MASK_REG(i), 0xffffffff);
+ }
+ /* enable protection mode*/
+ aintc_write_4(SW_INT_PROTECTION_REG, 0x01);
+
+ /* config the external interrupt source type*/
+ aintc_write_4(SW_INT_NMI_CTRL_REG, 0x00);
+
+ return (0);
+}
+
+static device_method_t a10_aintc_methods[] = {
+ DEVMETHOD(device_probe, a10_aintc_probe),
+ DEVMETHOD(device_attach, a10_aintc_attach),
+ { 0, 0 }
+};
+
+static driver_t a10_aintc_driver = {
+ "aintc",
+ a10_aintc_methods,
+ sizeof(struct a10_aintc_softc),
+};
+
+static devclass_t a10_aintc_devclass;
+
+DRIVER_MODULE(aintc, simplebus, a10_aintc_driver, a10_aintc_devclass, 0, 0);
+
+int
+arm_get_next_irq(int last_irq)
+{
+ uint32_t value;
+ int i, b;
+
+ for (i = 0; i < 3; i++) {
+ value = aintc_read_4(SW_INT_IRQ_PENDING_REG(i));
+ for (b = 0; b < 32; b++)
+ if (value & (1 << b)) {
+ return (i * 32 + b);
+ }
+ }
+
+ return (-1);
+}
+
+void
+arm_mask_irq(uintptr_t nb)
+{
+ uint32_t bit, block, value;
+
+ bit = (nb % 32);
+ block = (nb / 32);
+
+ value = aintc_read_4(SW_INT_ENABLE_REG(block));
+ value &= ~(1 << bit);
+ aintc_write_4(SW_INT_ENABLE_REG(block), value);
+
+ value = aintc_read_4(SW_INT_MASK_REG(block));
+ value |= (1 << bit);
+ aintc_write_4(SW_INT_MASK_REG(block), value);
+}
+
+void
+arm_unmask_irq(uintptr_t nb)
+{
+ uint32_t bit, block, value;
+
+ bit = (nb % 32);
+ block = (nb / 32);
+
+ value = aintc_read_4(SW_INT_ENABLE_REG(block));
+ value |= (1 << bit);
+ aintc_write_4(SW_INT_ENABLE_REG(block), value);
+
+ value = aintc_read_4(SW_INT_MASK_REG(block));
+ value &= ~(1 << bit);
+ aintc_write_4(SW_INT_MASK_REG(block), value);
+
+ if(nb == SW_INT_IRQNO_ENMI) /* must clear pending bit when enabled */
+ aintc_write_4(SW_INT_IRQ_PENDING_REG(0), (1 << SW_INT_IRQNO_ENMI));
+}
diff --git a/sys/arm/allwinner/bus_space.c b/sys/arm/allwinner/bus_space.c
new file mode 100644
index 0000000..4cce820
--- /dev/null
+++ b/sys/arm/allwinner/bus_space.c
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (C) 2012 FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY 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/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+
+/* Prototypes for all the bus_space structure functions */
+bs_protos(generic);
+bs_protos(generic_armv4);
+
+struct bus_space _base_tag = {
+ /* cookie */
+ .bs_cookie = (void *) 0,
+
+ /* mapping/unmapping */
+ .bs_map = generic_bs_map,
+ .bs_unmap = generic_bs_unmap,
+ .bs_subregion = generic_bs_subregion,
+
+ /* allocation/deallocation */
+ .bs_alloc = generic_bs_alloc,
+ .bs_free = generic_bs_free,
+
+ /* barrier */
+ .bs_barrier = generic_bs_barrier,
+
+ /* read (single) */
+ .bs_r_1 = generic_bs_r_1,
+ .bs_r_2 = generic_armv4_bs_r_2,
+ .bs_r_4 = generic_bs_r_4,
+ .bs_r_8 = NULL,
+
+ /* read multiple */
+ .bs_rm_1 = generic_bs_rm_1,
+ .bs_rm_2 = generic_armv4_bs_rm_2,
+ .bs_rm_4 = generic_bs_rm_4,
+ .bs_rm_8 = NULL,
+
+ /* read region */
+ .bs_rr_1 = generic_bs_rr_1,
+ .bs_rr_2 = generic_armv4_bs_rr_2,
+ .bs_rr_4 = generic_bs_rr_4,
+ .bs_rr_8 = NULL,
+
+ /* write (single) */
+ .bs_w_1 = generic_bs_w_1,
+ .bs_w_2 = generic_armv4_bs_w_2,
+ .bs_w_4 = generic_bs_w_4,
+ .bs_w_8 = NULL,
+
+ /* write multiple */
+ .bs_wm_1 = generic_bs_wm_1,
+ .bs_wm_2 = generic_armv4_bs_wm_2,
+ .bs_wm_4 = generic_bs_wm_4,
+ .bs_wm_8 = NULL,
+
+ /* write region */
+ .bs_wr_1 = generic_bs_wr_1,
+ .bs_wr_2 = generic_armv4_bs_wr_2,
+ .bs_wr_4 = generic_bs_wr_4,
+ .bs_wr_8 = NULL,
+
+ /* set multiple */
+ /* XXX not implemented */
+
+ /* set region */
+ .bs_sr_1 = NULL,
+ .bs_sr_2 = generic_armv4_bs_sr_2,
+ .bs_sr_4 = generic_bs_sr_4,
+ .bs_sr_8 = NULL,
+
+ /* copy */
+ .bs_c_1 = NULL,
+ .bs_c_2 = generic_armv4_bs_c_2,
+ .bs_c_4 = NULL,
+ .bs_c_8 = NULL,
+};
+
+bus_space_tag_t fdtbus_bs_tag = &_base_tag;
diff --git a/sys/arm/allwinner/common.c b/sys/arm/allwinner/common.c
new file mode 100644
index 0000000..eb49479
--- /dev/null
+++ b/sys/arm/allwinner/common.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/vmparam.h>
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+static int
+fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
+ int *pol)
+{
+ if (!fdt_is_compatible(node, "allwinner,sun4i-ic"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+ &fdt_aintc_decode_ic,
+ NULL
+};
diff --git a/sys/arm/allwinner/console.c b/sys/arm/allwinner/console.c
new file mode 100644
index 0000000..52d7376
--- /dev/null
+++ b/sys/arm/allwinner/console.c
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Simple UART console driver for Allwinner A10 */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/cons.h>
+#include <sys/consio.h>
+#include <sys/kernel.h>
+
+#ifndef A10_UART_BASE
+#define A10_UART_BASE 0xe1c28000 /* UART0 */
+#endif
+
+#define REG_SHIFT 2
+
+#define UART_DLL 0 /* Out: Divisor Latch Low */
+#define UART_DLM 1 /* Out: Divisor Latch High */
+#define UART_FCR 2 /* Out: FIFO Control Register */
+#define UART_LCR 3 /* Out: Line Control Register */
+#define UART_MCR 4 /* Out: Modem Control Register */
+#define UART_LSR 5 /* In: Line Status Register */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_DR 0x01 /* Receiver data ready */
+#define UART_MSR 6 /* In: Modem Status Register */
+#define UART_SCR 7 /* I/O: Scratch Register */
+
+static uint32_t
+uart_getreg(uint32_t *bas)
+{
+ return *((volatile uint32_t *)(bas)) & 0xff;
+}
+
+static void
+uart_setreg(uint32_t *bas, uint32_t val)
+{
+ *((volatile uint32_t *)(bas)) = val;
+}
+
+static int
+ub_getc(void)
+{
+ while ((uart_getreg((uint32_t *)(A10_UART_BASE +
+ (UART_LSR << REG_SHIFT))) & UART_LSR_DR) == 0);
+ __asm __volatile("nop");
+
+ return (uart_getreg((uint32_t *)A10_UART_BASE) & 0xff);
+}
+
+static void
+ub_putc(unsigned char c)
+{
+ if (c == '\n')
+ ub_putc('\r');
+
+ while ((uart_getreg((uint32_t *)(A10_UART_BASE +
+ (UART_LSR << REG_SHIFT))) & UART_LSR_THRE) == 0)
+ __asm __volatile("nop");
+
+ uart_setreg((uint32_t *)A10_UART_BASE, c);
+}
+
+static cn_probe_t uart_cnprobe;
+static cn_init_t uart_cninit;
+static cn_term_t uart_cnterm;
+static cn_getc_t uart_cngetc;
+static cn_putc_t uart_cnputc;
+static cn_grab_t uart_cngrab;
+static cn_ungrab_t uart_cnungrab;
+
+static void
+uart_cngrab(struct consdev *cp)
+{
+}
+
+static void
+uart_cnungrab(struct consdev *cp)
+{
+}
+
+
+static void
+uart_cnprobe(struct consdev *cp)
+{
+ sprintf(cp->cn_name, "uart");
+ cp->cn_pri = CN_NORMAL;
+}
+
+static void
+uart_cninit(struct consdev *cp)
+{
+ uart_setreg((uint32_t *)(A10_UART_BASE +
+ (UART_FCR << REG_SHIFT)), 0x06);
+}
+
+void
+uart_cnputc(struct consdev *cp, int c)
+{
+ ub_putc(c);
+}
+
+int
+uart_cngetc(struct consdev * cp)
+{
+ return ub_getc();
+}
+
+static void
+uart_cnterm(struct consdev * cp)
+{
+}
+
+CONSOLE_DRIVER(uart);
+
diff --git a/sys/arm/allwinner/files.a10 b/sys/arm/allwinner/files.a10
new file mode 100644
index 0000000..9d056fc
--- /dev/null
+++ b/sys/arm/allwinner/files.a10
@@ -0,0 +1,19 @@
+# $FreeBSD$
+kern/kern_clocksource.c standard
+
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_armv5.S standard
+arm/arm/cpufunc_asm_arm10.S standard
+arm/arm/cpufunc_asm_arm11.S standard
+arm/arm/cpufunc_asm_armv7.S standard
+arm/arm/irq_dispatch.S standard
+
+arm/allwinner/a10_clk.c standard
+arm/allwinner/a10_ehci.c optional ehci
+arm/allwinner/timer.c standard
+arm/allwinner/aintc.c standard
+arm/allwinner/bus_space.c standard
+arm/allwinner/common.c standard
+arm/allwinner/console.c standard
+arm/allwinner/a10_machdep.c standard
diff --git a/sys/arm/allwinner/std.a10 b/sys/arm/allwinner/std.a10
new file mode 100644
index 0000000..f698b34
--- /dev/null
+++ b/sys/arm/allwinner/std.a10
@@ -0,0 +1,21 @@
+# Allwinner A10 common options
+#$FreeBSD$
+
+cpu CPU_CORTEXA
+machine arm armv6
+makeoption ARM_LITTLE_ENDIAN
+
+# Physical memory starts at 0x40200000. We assume images are loaded at
+# 0x40200000, e.g. from u-boot with 'fatload mmc 0 0x40200000 kernel'
+#
+#
+options PHYSADDR=0x40000000
+
+makeoptions KERNPHYSADDR=0x40200000
+options KERNPHYSADDR=0x40200000
+makeoptions KERNVIRTADDR=0xc0200000
+options KERNVIRTADDR=0xc0200000
+
+options STARTUP_PAGETABLE_ADDR=0x48000000
+
+files "../allwinner/files.a10"
diff --git a/sys/arm/allwinner/timer.c b/sys/arm/allwinner/timer.c
new file mode 100644
index 0000000..4da3517
--- /dev/null
+++ b/sys/arm/allwinner/timer.c
@@ -0,0 +1,379 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/watchdog.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <sys/kdb.h>
+
+/**
+ * Timer registers addr
+ *
+ */
+#define SW_TIMER_IRQ_EN_REG 0x00
+#define SW_TIMER_IRQ_STA_REG 0x04
+#define SW_TIMER0_CTRL_REG 0x10
+#define SW_TIMER0_INT_VALUE_REG 0x14
+#define SW_TIMER0_CUR_VALUE_REG 0x18
+
+#define SW_COUNTER64LO_REG 0xa4
+#define SW_COUNTER64HI_REG 0xa8
+#define CNT64_CTRL_REG 0xa0
+
+#define CNT64_RL_EN 0x02 /* read latch enable */
+
+#define TIMER_ENABLE (1<<0)
+#define TIMER_AUTORELOAD (1<<1)
+#define TIMER_OSC24M (1<<2) /* oscillator = 24mhz */
+#define TIMER_PRESCALAR (4<<4) /* prescalar = 16 */
+
+#define SYS_TIMER_CLKSRC 24000000 /* clock source */
+
+struct a10_timer_softc {
+ device_t sc_dev;
+ struct resource *res[2];
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ void *sc_ih; /* interrupt handler */
+ uint32_t sc_period;
+ uint32_t timer0_freq;
+ struct eventtimer et;
+};
+
+int a10_timer_get_timerfreq(struct a10_timer_softc *);
+
+#define timer_read_4(sc, reg) \
+ bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg)
+#define timer_write_4(sc, reg, val) \
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, val)
+
+static u_int a10_timer_get_timecount(struct timecounter *);
+static int a10_timer_timer_start(struct eventtimer *,
+ struct bintime *, struct bintime *);
+static int a10_timer_timer_stop(struct eventtimer *);
+
+static uint64_t timer_read_counter64(void);
+
+static int a10_timer_initialized = 0;
+static int a10_timer_hardclock(void *);
+static int a10_timer_probe(device_t);
+static int a10_timer_attach(device_t);
+
+static struct timecounter a10_timer_timecounter = {
+ .tc_name = "a10_timer timer0",
+ .tc_get_timecount = a10_timer_get_timecount,
+ .tc_counter_mask = ~0u,
+ .tc_frequency = 0,
+ .tc_quality = 1000,
+};
+
+struct a10_timer_softc *a10_timer_sc = NULL;
+
+static struct resource_spec a10_timer_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static uint64_t
+timer_read_counter64(void)
+{
+ uint32_t lo, hi;
+
+ /* Latch counter, wait for it to be ready to read. */
+ timer_write_4(a10_timer_sc, CNT64_CTRL_REG, CNT64_RL_EN);
+ while (timer_read_4(a10_timer_sc, CNT64_CTRL_REG) & CNT64_RL_EN)
+ continue;
+
+ hi = timer_read_4(a10_timer_sc, SW_COUNTER64HI_REG);
+ lo = timer_read_4(a10_timer_sc, SW_COUNTER64LO_REG);
+
+ return (((uint64_t)hi << 32) | lo);
+}
+
+static int
+a10_timer_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-timer"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Allwinner A10 timer");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10_timer_attach(device_t dev)
+{
+ struct a10_timer_softc *sc;
+ int err;
+ uint32_t val;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, a10_timer_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->sc_dev = dev;
+ sc->sc_bst = rman_get_bustag(sc->res[0]);
+ sc->sc_bsh = rman_get_bushandle(sc->res[0]);
+
+ /* Setup and enable the timer interrupt */
+ err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_CLK, a10_timer_hardclock,
+ NULL, sc, &sc->sc_ih);
+ if (err != 0) {
+ bus_release_resources(dev, a10_timer_spec, sc->res);
+ device_printf(dev, "Unable to setup the clock irq handler, "
+ "err = %d\n", err);
+ return (ENXIO);
+ }
+
+ /* Set clock source to OSC24M, 16 pre-division */
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ val |= TIMER_PRESCALAR | TIMER_OSC24M;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+
+ /* Enable timer0 */
+ val = timer_read_4(sc, SW_TIMER_IRQ_EN_REG);
+ val |= TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER_IRQ_EN_REG, val);
+
+ sc->timer0_freq = SYS_TIMER_CLKSRC;
+
+ /* Set desired frequency in event timer and timecounter */
+ sc->et.et_frequency = sc->timer0_freq;
+ sc->et.et_name = "a10_timer Eventtimer";
+ sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC;
+ sc->et.et_quality = 1000;
+ sc->et.et_min_period.sec = 0;
+ sc->et.et_min_period.frac =
+ ((0x00000005LLU << 32) / sc->et.et_frequency) << 32;
+ sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
+ sc->et.et_max_period.frac =
+ ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
+ sc->et.et_start = a10_timer_timer_start;
+ sc->et.et_stop = a10_timer_timer_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+
+ if (device_get_unit(dev) == 0)
+ a10_timer_sc = sc;
+
+ a10_timer_timecounter.tc_frequency = sc->timer0_freq;
+ tc_init(&a10_timer_timecounter);
+
+ if (bootverbose) {
+ device_printf(sc->sc_dev, "clock: hz=%d stathz = %d\n", hz, stathz);
+
+ device_printf(sc->sc_dev, "event timer clock frequency %u\n",
+ sc->timer0_freq);
+ device_printf(sc->sc_dev, "timecounter clock frequency %lld\n",
+ a10_timer_timecounter.tc_frequency);
+ }
+
+ a10_timer_initialized = 1;
+
+ return (0);
+}
+
+static int
+a10_timer_timer_start(struct eventtimer *et, struct bintime *first,
+ struct bintime *period)
+{
+ struct a10_timer_softc *sc;
+ uint32_t count;
+ uint32_t val;
+
+ sc = (struct a10_timer_softc *)et->et_priv;
+
+ sc->sc_period = 0;
+
+ if (period != NULL) {
+ sc->sc_period = (sc->et.et_frequency * (period->frac >> 32)) >> 32;
+ sc->sc_period += sc->et.et_frequency * period->sec;
+ }
+ if (first == NULL)
+ count = sc->sc_period;
+ else {
+ count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
+ if (first->sec != 0)
+ count += sc->et.et_frequency * first->sec;
+ }
+
+ /* Update timer values */
+ timer_write_4(sc, SW_TIMER0_INT_VALUE_REG, sc->sc_period);
+ timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, count);
+
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ if (first == NULL) {
+ /* periodic */
+ val |= TIMER_AUTORELOAD;
+ } else {
+ /* oneshot */
+ val &= ~TIMER_AUTORELOAD;
+ }
+ /* Enable timer0 */
+ val |= TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+
+ return (0);
+}
+
+static int
+a10_timer_timer_stop(struct eventtimer *et)
+{
+ struct a10_timer_softc *sc;
+ uint32_t val;
+
+ sc = (struct a10_timer_softc *)et->et_priv;
+
+ /* Disable timer0 */
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ val &= ~TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+
+ sc->sc_period = 0;
+
+ return (0);
+}
+
+int
+a10_timer_get_timerfreq(struct a10_timer_softc *sc)
+{
+ return (sc->timer0_freq);
+}
+
+void
+cpu_initclocks(void)
+{
+ cpu_initclocks_bsp();
+}
+
+static int
+a10_timer_hardclock(void *arg)
+{
+ struct a10_timer_softc *sc;
+ uint32_t val;
+
+ sc = (struct a10_timer_softc *)arg;
+
+ /* Clear interrupt pending bit. */
+ timer_write_4(sc, SW_TIMER_IRQ_STA_REG, 0x1);
+
+ val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
+ /*
+ * Disabled autoreload and sc_period > 0 means
+ * timer_start was called with non NULL first value.
+ * Now we will set periodic timer with the given period
+ * value.
+ */
+ if ((val & (1<<1)) == 0 && sc->sc_period > 0) {
+ /* Update timer */
+ timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, sc->sc_period);
+
+ /* Make periodic and enable */
+ val |= TIMER_AUTORELOAD | TIMER_ENABLE;
+ timer_write_4(sc, SW_TIMER0_CTRL_REG, val);
+ }
+
+ if (sc->et.et_active)
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
+
+ return (FILTER_HANDLED);
+}
+
+u_int
+a10_timer_get_timecount(struct timecounter *tc)
+{
+
+ if (a10_timer_sc == NULL)
+ return (0);
+
+ return ((u_int)timer_read_counter64());
+}
+
+static device_method_t a10_timer_methods[] = {
+ DEVMETHOD(device_probe, a10_timer_probe),
+ DEVMETHOD(device_attach, a10_timer_attach),
+
+ DEVMETHOD_END
+};
+
+static driver_t a10_timer_driver = {
+ "a10_timer",
+ a10_timer_methods,
+ sizeof(struct a10_timer_softc),
+};
+
+static devclass_t a10_timer_devclass;
+
+DRIVER_MODULE(a10_timer, simplebus, a10_timer_driver, a10_timer_devclass, 0, 0);
+
+void
+DELAY(int usec)
+{
+ uint32_t counter;
+ uint64_t end, now;
+
+ if (!a10_timer_initialized) {
+ for (; usec > 0; usec--)
+ for (counter = 50; counter > 0; counter--)
+ cpufunc_nullop();
+ return;
+ }
+
+ now = timer_read_counter64();
+ end = now + (a10_timer_sc->timer0_freq / 1000000) * (usec + 1);
+
+ while (now < end)
+ now = timer_read_counter64();
+}
+
diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c
index 42566e8..fa7afd4 100644
--- a/sys/arm/arm/busdma_machdep.c
+++ b/sys/arm/arm/busdma_machdep.c
@@ -849,9 +849,6 @@ bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t *segs,
vm_offset_t vaddr = (vm_offset_t)buf;
int seg;
int error = 0;
- pd_entry_t *pde;
- pt_entry_t pte;
- pt_entry_t *ptep;
lastaddr = *lastaddrp;
bmask = ~(dmat->boundary - 1);
@@ -868,34 +865,9 @@ bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t *segs,
for (seg = *segp; buflen > 0 ; ) {
/*
* Get the physical address for this segment.
- *
- * XXX Don't support checking for coherent mappings
- * XXX in user address space.
*/
if (__predict_true(pmap == pmap_kernel())) {
- if (pmap_get_pde_pte(pmap, vaddr, &pde, &ptep) == FALSE)
- return (EFAULT);
-
- if (__predict_false(pmap_pde_section(pde))) {
- if (*pde & L1_S_SUPERSEC)
- curaddr = (*pde & L1_SUP_FRAME) |
- (vaddr & L1_SUP_OFFSET);
- else
- curaddr = (*pde & L1_S_FRAME) |
- (vaddr & L1_S_OFFSET);
- } else {
- pte = *ptep;
- KASSERT((pte & L2_TYPE_MASK) != L2_TYPE_INV,
- ("INV type"));
- if (__predict_false((pte & L2_TYPE_MASK)
- == L2_TYPE_L)) {
- curaddr = (pte & L2_L_FRAME) |
- (vaddr & L2_L_OFFSET);
- } else {
- curaddr = (pte & L2_S_FRAME) |
- (vaddr & L2_S_OFFSET);
- }
- }
+ curaddr = pmap_kextract(vaddr);
} else {
curaddr = pmap_extract(pmap, vaddr);
map->flags &= ~DMAMAP_COHERENT;
diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c
index 5dc2679..1d15e27 100644
--- a/sys/arm/arm/cpufunc.c
+++ b/sys/arm/arm/cpufunc.c
@@ -1146,7 +1146,7 @@ struct cpu_functions cortexa_cpufuncs = {
/* Other functions */
cpufunc_nullop, /* flush_prefetchbuf */
- arm11_drain_writebuf, /* drain_writebuf */
+ armv7_drain_writebuf, /* drain_writebuf */
cpufunc_nullop, /* flush_brnchtgt_C */
(void *)cpufunc_nullop, /* flush_brnchtgt_E */
@@ -1157,7 +1157,7 @@ struct cpu_functions cortexa_cpufuncs = {
cpufunc_null_fixup, /* dataabt_fixup */
cpufunc_null_fixup, /* prefetchabt_fixup */
- arm11_context_switch, /* context_switch */
+ armv7_context_switch, /* context_switch */
cortexa_setup /* cpu setup */
};
diff --git a/sys/arm/arm/cpufunc_asm_arm10.S b/sys/arm/arm/cpufunc_asm_arm10.S
index 22da6aa..2ef999c 100644
--- a/sys/arm/arm/cpufunc_asm_arm10.S
+++ b/sys/arm/arm/cpufunc_asm_arm10.S
@@ -87,7 +87,7 @@ ENTRY_NP(arm10_icache_sync_range)
mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm10_sync_next
+ bhi .Larm10_sync_next
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -108,12 +108,10 @@ ENTRY_NP(arm10_icache_sync_all)
orr ip, s_max, i_max
.Lnext_index:
mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
- sub ip, ip, i_inc
- tst ip, i_max /* Index 0 is last one */
- bne .Lnext_index /* Next index */
- mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index /* Next index */
subs s_max, s_max, s_inc
- bpl .Lnext_set /* Next set */
+ bhs .Lnext_set /* Next set */
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -133,7 +131,7 @@ ENTRY(arm10_dcache_wb_range)
mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm10_wb_next
+ bhi .Larm10_wb_next
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -150,7 +148,7 @@ ENTRY(arm10_dcache_wbinv_range)
mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm10_wbinv_next
+ bhi .Larm10_wbinv_next
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -171,7 +169,7 @@ ENTRY(arm10_dcache_inv_range)
mcr p15, 0, r0, c7, c6, 1 /* Invalidate D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm10_inv_next
+ bhi .Larm10_inv_next
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -189,7 +187,7 @@ ENTRY(arm10_idcache_wbinv_range)
mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm10_id_wbinv_next
+ bhi .Larm10_id_wbinv_next
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
@@ -211,12 +209,10 @@ ENTRY(arm10_dcache_wbinv_all)
orr ip, s_max, i_max
.Lnext_index_inv:
mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
- sub ip, ip, i_inc
- tst ip, i_max /* Index 0 is last one */
- bne .Lnext_index_inv /* Next index */
- mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index_inv /* Next index */
subs s_max, s_max, s_inc
- bpl .Lnext_set_inv /* Next set */
+ bhs .Lnext_set_inv /* Next set */
mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */
bx lr
diff --git a/sys/arm/arm/cpufunc_asm_arm9.S b/sys/arm/arm/cpufunc_asm_arm9.S
index 291d3f7..ae9fe00 100644
--- a/sys/arm/arm/cpufunc_asm_arm9.S
+++ b/sys/arm/arm/cpufunc_asm_arm9.S
@@ -81,7 +81,7 @@ ENTRY_NP(arm9_icache_sync_range)
mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm9_sync_next
+ bhi .Larm9_sync_next
mov pc, lr
ENTRY_NP(arm9_icache_sync_all)
@@ -101,12 +101,10 @@ ENTRY_NP(arm9_icache_sync_all)
orr ip, s_max, i_max
.Lnext_index:
mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
- sub ip, ip, i_inc
- tst ip, i_max /* Index 0 is last one */
- bne .Lnext_index /* Next index */
- mcr p15, 0, ip, c7, c10, 2 /* Clean D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index /* Next index */
subs s_max, s_max, s_inc
- bpl .Lnext_set /* Next set */
+ bhs .Lnext_set /* Next set */
mov pc, lr
.Larm9_line_size:
@@ -125,7 +123,7 @@ ENTRY(arm9_dcache_wb_range)
mcr p15, 0, r0, c7, c10, 1 /* Clean D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm9_wb_next
+ bhi .Larm9_wb_next
mov pc, lr
ENTRY(arm9_dcache_wbinv_range)
@@ -141,7 +139,7 @@ ENTRY(arm9_dcache_wbinv_range)
mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm9_wbinv_next
+ bhi .Larm9_wbinv_next
mov pc, lr
/*
@@ -161,7 +159,7 @@ ENTRY(arm9_dcache_inv_range)
mcr p15, 0, r0, c7, c6, 1 /* Invalidate D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm9_inv_next
+ bhi .Larm9_inv_next
mov pc, lr
ENTRY(arm9_idcache_wbinv_range)
@@ -178,7 +176,7 @@ ENTRY(arm9_idcache_wbinv_range)
mcr p15, 0, r0, c7, c14, 1 /* Purge D cache SE with VA */
add r0, r0, ip
subs r1, r1, ip
- bpl .Larm9_id_wbinv_next
+ bhi .Larm9_id_wbinv_next
mov pc, lr
ENTRY_NP(arm9_idcache_wbinv_all)
@@ -199,12 +197,10 @@ ENTRY(arm9_dcache_wbinv_all)
orr ip, s_max, i_max
.Lnext_index_inv:
mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
- sub ip, ip, i_inc
- tst ip, i_max /* Index 0 is last one */
- bne .Lnext_index_inv /* Next index */
- mcr p15, 0, ip, c7, c14, 2 /* Purge D cache SE with Set/Index */
+ subs ip, ip, i_inc
+ bhs .Lnext_index_inv /* Next index */
subs s_max, s_max, s_inc
- bpl .Lnext_set_inv /* Next set */
+ bhs .Lnext_set_inv /* Next set */
mov pc, lr
.Larm9_cache_data:
diff --git a/sys/arm/arm/db_trace.c b/sys/arm/arm/db_trace.c
index d6e1c3a..89ec507 100644
--- a/sys/arm/arm/db_trace.c
+++ b/sys/arm/arm/db_trace.c
@@ -50,6 +50,395 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_sym.h>
#include <ddb/db_output.h>
+#ifdef __ARM_EABI__
+/*
+ * Definitions for the instruction interpreter.
+ *
+ * The ARM EABI specifies how to perform the frame unwinding in the
+ * Exception Handling ABI for the ARM Architecture document. To perform
+ * the unwind we need to know the initial frame pointer, stack pointer,
+ * link register and program counter. We then find the entry within the
+ * index table that points to the function the program counter is within.
+ * This gives us either a list of three instructions to process, a 31-bit
+ * relative offset to a table of instructions, or a value telling us
+ * we can't unwind any further.
+ *
+ * When we have the instructions to process we need to decode them
+ * following table 4 in section 9.3. This describes a collection of bit
+ * patterns to encode that steps to take to update the stack pointer and
+ * link register to the correct values at the start of the function.
+ */
+
+/* A special case when we are unable to unwind past this function */
+#define EXIDX_CANTUNWIND 1
+
+/* The register names */
+#define FP 11
+#define SP 13
+#define LR 14
+#define PC 15
+
+/*
+ * These are set in the linker script. Their addresses will be
+ * either the start or end of the exception table or index.
+ */
+extern int extab_start, extab_end, exidx_start, exidx_end;
+
+/*
+ * Entry types.
+ * These are the only entry types that have been seen in the kernel.
+ */
+#define ENTRY_MASK 0xff000000
+#define ENTRY_ARM_SU16 0x80000000
+#define ENTRY_ARM_LU16 0x81000000
+
+/* Instruction masks. */
+#define INSN_VSP_MASK 0xc0
+#define INSN_VSP_SIZE_MASK 0x3f
+#define INSN_STD_MASK 0xf0
+#define INSN_STD_DATA_MASK 0x0f
+#define INSN_POP_TYPE_MASK 0x08
+#define INSN_POP_COUNT_MASK 0x07
+#define INSN_VSP_LARGE_INC_MASK 0xff
+
+/* Instruction definitions */
+#define INSN_VSP_INC 0x00
+#define INSN_VSP_DEC 0x40
+#define INSN_POP_MASKED 0x80
+#define INSN_VSP_REG 0x90
+#define INSN_POP_COUNT 0xa0
+#define INSN_FINISH 0xb0
+#define INSN_VSP_LARGE_INC 0xb2
+
+/* An item in the exception index table */
+struct unwind_idx {
+ uint32_t offset;
+ uint32_t insn;
+};
+
+/* The state of the unwind process */
+struct unwind_state {
+ uint32_t registers[16];
+ uint32_t start_pc;
+ uint32_t *insn;
+ u_int entries;
+ u_int byte;
+ uint16_t update_mask;
+};
+
+/* We need to provide these but never use them */
+void __aeabi_unwind_cpp_pr0(void);
+void __aeabi_unwind_cpp_pr1(void);
+void __aeabi_unwind_cpp_pr2(void);
+
+void
+__aeabi_unwind_cpp_pr0(void)
+{
+ panic("__aeabi_unwind_cpp_pr0");
+}
+
+void
+__aeabi_unwind_cpp_pr1(void)
+{
+ panic("__aeabi_unwind_cpp_pr1");
+}
+
+void
+__aeabi_unwind_cpp_pr2(void)
+{
+ panic("__aeabi_unwind_cpp_pr2");
+}
+
+/* Expand a 31-bit signed value to a 32-bit signed value */
+static __inline int32_t
+db_expand_prel31(uint32_t prel31)
+{
+
+ return ((int32_t)(prel31 & 0x7fffffffu) << 1) / 2;
+}
+
+/*
+ * Perform a binary search of the index table to find the function
+ * with the largest address that doesn't exceed addr.
+ */
+static struct unwind_idx *
+db_find_index(uint32_t addr)
+{
+ unsigned int min, mid, max;
+ struct unwind_idx *start;
+ struct unwind_idx *item;
+ int32_t prel31_addr;
+ uint32_t func_addr;
+
+ start = (struct unwind_idx *)&exidx_start;
+
+ min = 0;
+ max = (&exidx_end - &exidx_start) / 2;
+
+ while (min != max) {
+ mid = min + (max - min + 1) / 2;
+
+ item = &start[mid];
+
+ prel31_addr = db_expand_prel31(item->offset);
+ func_addr = (uint32_t)&item->offset + prel31_addr;
+
+ if (func_addr <= addr) {
+ min = mid;
+ } else {
+ max = mid - 1;
+ }
+ }
+
+ return &start[min];
+}
+
+/* Reads the next byte from the instruction list */
+static uint8_t
+db_unwind_exec_read_byte(struct unwind_state *state)
+{
+ uint8_t insn;
+
+ /* Read the unwind instruction */
+ insn = (*state->insn) >> (state->byte * 8);
+
+ /* Update the location of the next instruction */
+ if (state->byte == 0) {
+ state->byte = 3;
+ state->insn++;
+ state->entries--;
+ } else
+ state->byte--;
+
+ return insn;
+}
+
+/* Executes the next instruction on the list */
+static int
+db_unwind_exec_insn(struct unwind_state *state)
+{
+ unsigned int insn;
+ uint32_t *vsp = (uint32_t *)state->registers[SP];
+ int update_vsp = 0;
+
+ /* This should never happen */
+ if (state->entries == 0)
+ return 1;
+
+ /* Read the next instruction */
+ insn = db_unwind_exec_read_byte(state);
+
+ if ((insn & INSN_VSP_MASK) == INSN_VSP_INC) {
+ state->registers[SP] += ((insn & INSN_VSP_SIZE_MASK) << 2) + 4;
+
+ } else if ((insn & INSN_VSP_MASK) == INSN_VSP_DEC) {
+ state->registers[SP] -= ((insn & INSN_VSP_SIZE_MASK) << 2) + 4;
+
+ } else if ((insn & INSN_STD_MASK) == INSN_POP_MASKED) {
+ unsigned int mask, reg;
+
+ /* Load the mask */
+ mask = db_unwind_exec_read_byte(state);
+ mask |= (insn & INSN_STD_DATA_MASK) << 8;
+
+ /* We have a refuse to unwind instruction */
+ if (mask == 0)
+ return 1;
+
+ /* Update SP */
+ update_vsp = 1;
+
+ /* Load the registers */
+ for (reg = 4; mask && reg < 16; mask >>= 1, reg++) {
+ if (mask & 1) {
+ state->registers[reg] = *vsp++;
+ state->update_mask |= 1 << reg;
+
+ /* If we have updated SP kep its value */
+ if (reg == SP)
+ update_vsp = 0;
+ }
+ }
+
+ } else if ((insn & INSN_STD_MASK) == INSN_VSP_REG &&
+ ((insn & INSN_STD_DATA_MASK) != 13) &&
+ ((insn & INSN_STD_DATA_MASK) != 15)) {
+ /* sp = register */
+ state->registers[SP] =
+ state->registers[insn & INSN_STD_DATA_MASK];
+
+ } else if ((insn & INSN_STD_MASK) == INSN_POP_COUNT) {
+ unsigned int count, reg;
+
+ /* Read how many registers to load */
+ count = insn & INSN_POP_COUNT_MASK;
+
+ /* Update sp */
+ update_vsp = 1;
+
+ /* Pop the registers */
+ for (reg = 4; reg <= 4 + count; reg++) {
+ state->registers[reg] = *vsp++;
+ state->update_mask |= 1 << reg;
+ }
+
+ /* Check if we are in the pop r14 version */
+ if ((insn & INSN_POP_TYPE_MASK) != 0) {
+ state->registers[14] = *vsp++;
+ }
+
+ } else if (insn == INSN_FINISH) {
+ /* Stop processing */
+ state->entries = 0;
+
+ } else if ((insn & INSN_VSP_LARGE_INC_MASK) == INSN_VSP_LARGE_INC) {
+ unsigned int uleb128;
+
+ /* Read the increment value */
+ uleb128 = db_unwind_exec_read_byte(state);
+
+ state->registers[SP] += 0x204 + (uleb128 << 2);
+
+ } else {
+ /* We hit a new instruction that needs to be implemented */
+ db_printf("Unhandled instruction %.2x\n", insn);
+ return 1;
+ }
+
+ if (update_vsp) {
+ state->registers[SP] = (uint32_t)vsp;
+ }
+
+#if 0
+ db_printf("fp = %08x, sp = %08x, lr = %08x, pc = %08x\n",
+ state->registers[FP], state->registers[SP], state->registers[LR],
+ state->registers[PC]);
+#endif
+
+ return 0;
+}
+
+/* Performs the unwind of a function */
+static int
+db_unwind_tab(struct unwind_state *state)
+{
+ uint32_t entry;
+
+ /* Set PC to a known value */
+ state->registers[PC] = 0;
+
+ /* Read the personality */
+ entry = *state->insn & ENTRY_MASK;
+
+ if (entry == ENTRY_ARM_SU16) {
+ state->byte = 2;
+ state->entries = 1;
+ } else if (entry == ENTRY_ARM_LU16) {
+ state->byte = 1;
+ state->entries = ((*state->insn >> 16) & 0xFF) + 1;
+ } else {
+ db_printf("Unknown entry: %x\n", entry);
+ return 1;
+ }
+
+ while (state->entries > 0) {
+ if (db_unwind_exec_insn(state) != 0)
+ return 1;
+ }
+
+ /*
+ * The program counter was not updated, load it from the link register.
+ */
+ if (state->registers[PC] == 0)
+ state->registers[PC] = state->registers[LR];
+
+ return 0;
+}
+
+static void
+db_stack_trace_cmd(struct unwind_state *state)
+{
+ struct unwind_idx *index;
+ const char *name;
+ db_expr_t value;
+ db_expr_t offset;
+ c_db_sym_t sym;
+ u_int reg, i;
+ char *sep;
+
+ while (1) {
+ /* Reset the mask of updated registers */
+ state->update_mask = 0;
+
+ /* The pc value is correct and will be overwritten, save it */
+ state->start_pc = state->registers[PC];
+
+ /* Find the item to run */
+ index = db_find_index(state->start_pc);
+
+ if (index->insn == EXIDX_CANTUNWIND) {
+ printf("Unable to unwind\n");
+ break;
+ } else if (index->insn & (1 << 31)) {
+ /* The data is within the instruction */
+ state->insn = &index->insn;
+ } else {
+ /* We have a prel31 offset to the unwind table */
+ uint32_t prel31_tbl = db_expand_prel31(index->insn);
+
+ state->insn = (uint32_t *)((uintptr_t)&index->insn +
+ prel31_tbl);
+ }
+
+ /* Run the unwind function */
+ if (db_unwind_tab(state) != 0)
+ break;
+
+ /* This is not a kernel address, stop processing */
+ if (state->registers[PC] < VM_MIN_KERNEL_ADDRESS)
+ break;
+
+ /* Print the frame details */
+ sym = db_search_symbol(state->start_pc, DB_STGY_ANY, &offset);
+ if (sym == C_DB_SYM_NULL) {
+ value = 0;
+ name = "(null)";
+ } else
+ db_symbol_values(sym, &name, &value);
+ db_printf("%s() at ", name);
+ db_printsym(state->start_pc, DB_STGY_PROC);
+ db_printf("\n");
+ db_printf("\t pc = 0x%08x lr = 0x%08x (", state->start_pc,
+ state->registers[LR]);
+ db_printsym(state->registers[LR], DB_STGY_PROC);
+ db_printf(")\n");
+ db_printf("\t sp = 0x%08x fp = 0x%08x",
+ state->registers[SP], state->registers[FP]);
+
+ /* Don't print the registers we have already printed */
+ state->update_mask &= ~((1 << SP) | (1 << FP) | (1 << LR) |
+ (1 << PC));
+ sep = "\n\t";
+ for (i = 0, reg = 0; state->update_mask != 0;
+ state->update_mask >>= 1, reg++) {
+ if ((state->update_mask & 1) != 0) {
+ db_printf("%s%sr%d = 0x%08x", sep,
+ (reg < 10) ? " " : "", reg,
+ state->registers[reg]);
+ i++;
+ if (i == 2) {
+ sep = "\n\t";
+ i = 0;
+ } else
+ sep = " ";
+
+ }
+ }
+ db_printf("\n");
+ }
+}
+#endif
+
/*
* APCS stack frames are awkward beasts, so I don't think even trying to use
* a structure to represent them is a good idea.
@@ -78,6 +467,7 @@ __FBSDID("$FreeBSD$");
* fields are actually present.
*/
+#ifndef __ARM_EABI__ /* The frame format is differend in AAPCS */
static void
db_stack_trace_cmd(db_expr_t addr, db_expr_t count, boolean_t kernel_only)
{
@@ -171,6 +561,7 @@ db_stack_trace_cmd(db_expr_t addr, db_expr_t count, boolean_t kernel_only)
}
}
}
+#endif
/* XXX stubs */
void
@@ -193,11 +584,24 @@ db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
int
db_trace_thread(struct thread *thr, int count)
{
+#ifdef __ARM_EABI__
+ struct unwind_state state;
+#endif
struct pcb *ctx;
if (thr != curthread) {
ctx = kdb_thr_ctx(thr);
+
+#ifdef __ARM_EABI__
+ state.registers[FP] = ctx->un_32.pcb32_r11;
+ state.registers[SP] = ctx->un_32.pcb32_sp;
+ state.registers[LR] = ctx->un_32.pcb32_lr;
+ state.registers[PC] = ctx->un_32.pcb32_pc;
+
+ db_stack_trace_cmd(&state);
+#else
db_stack_trace_cmd(ctx->un_32.pcb32_r11, -1, TRUE);
+#endif
} else
db_trace_self();
return (0);
@@ -206,8 +610,20 @@ db_trace_thread(struct thread *thr, int count)
void
db_trace_self(void)
{
+#ifdef __ARM_EABI__
+ struct unwind_state state;
+ register uint32_t sp __asm__ ("sp");
+
+ state.registers[FP] = (uint32_t)__builtin_frame_address(0);
+ state.registers[SP] = (uint32_t)sp;
+ state.registers[LR] = (uint32_t)__builtin_return_address(0);
+ state.registers[PC] = (uint32_t)db_trace_self;
+
+ db_stack_trace_cmd(&state);
+#else
db_addr_t addr;
addr = (db_addr_t)__builtin_frame_address(0);
db_stack_trace_cmd(addr, -1, FALSE);
+#endif
}
diff --git a/sys/arm/arm/intr.c b/sys/arm/arm/intr.c
index e79e44c..062b10a 100644
--- a/sys/arm/arm/intr.c
+++ b/sys/arm/arm/intr.c
@@ -50,17 +50,34 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/cpu.h>
+#define INTRNAME_LEN (MAXCOMLEN + 1)
+
typedef void (*mask_fn)(void *);
static struct intr_event *intr_events[NIRQ];
-static int intrcnt_tab[NIRQ];
-static int intrcnt_index = 0;
-static int last_printed = 0;
void arm_handler_execute(struct trapframe *, int);
void (*arm_post_filter)(void *) = NULL;
+/*
+ * Pre-format intrnames into an array of fixed-size strings containing spaces.
+ * This allows us to avoid the need for an intermediate table of indices into
+ * the names and counts arrays, while still meeting the requirements and
+ * assumptions of vmstat(8) and the kdb "show intrcnt" command, the two
+ * consumers of this data.
+ */
+void
+arm_intrnames_init(void)
+{
+ int i;
+
+ for (i = 0; i < NIRQ; ++i) {
+ snprintf(&intrnames[i * INTRNAME_LEN], INTRNAME_LEN, "%-*s",
+ INTRNAME_LEN - 1, "");
+ }
+}
+
void
arm_setup_irqhandler(const char *name, driver_filter_t *filt,
void (*hand)(void*), void *arg, int irq, int flags, void **cookiep)
@@ -78,14 +95,8 @@ arm_setup_irqhandler(const char *name, driver_filter_t *filt,
if (error)
return;
intr_events[irq] = event;
- last_printed +=
- snprintf(intrnames + last_printed,
- MAXCOMLEN + 1,
- "irq%d: %s", irq, name);
- last_printed++;
- intrcnt_tab[irq] = intrcnt_index;
- intrcnt_index++;
-
+ snprintf(&intrnames[irq * INTRNAME_LEN], INTRNAME_LEN,
+ "irq%d: %-*s", irq, INTRNAME_LEN - 1, name);
}
intr_event_add_handler(event, name, filt, hand, arg,
intr_priority(flags), flags, cookiep);
@@ -122,7 +133,7 @@ arm_handler_execute(struct trapframe *frame, int irqnb)
PCPU_INC(cnt.v_intr);
i = -1;
while ((i = arm_get_next_irq(i)) != -1) {
- intrcnt[intrcnt_tab[i]]++;
+ intrcnt[i]++;
event = intr_events[i];
if (intr_event_handle(event, frame) != 0) {
/* XXX: Log stray IRQs */
diff --git a/sys/arm/arm/locore.S b/sys/arm/arm/locore.S
index ed7af25..00a61e7 100644
--- a/sys/arm/arm/locore.S
+++ b/sys/arm/arm/locore.S
@@ -484,12 +484,29 @@ ENTRY_NP(abort)
ENTRY_NP(sigcode)
mov r0, sp
+
+ /*
+ * Call the sigreturn system call.
+ *
+ * We have to load r7 manually rather than using
+ * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
+ * correct. Using the alternative places esigcode at the address
+ * of the data rather than the address one past the data.
+ */
+
+ ldr r7, [pc, #12] /* Load SYS_sigreturn */
swi SYS_sigreturn
/* Well if that failed we better exit quick ! */
+ ldr r7, [pc, #8] /* Load SYS_exit */
swi SYS_exit
- b . - 8
+
+ /* Branch back to retry SYS_sigreturn */
+ b . - 16
+
+ .word SYS_sigreturn
+ .word SYS_exit
.align 0
.global _C_LABEL(esigcode)
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index a1b5a8f..5c4d92c 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -1474,6 +1474,7 @@ initarm(struct arm_boot_params *abp)
init_proc0(kernelstack.pv_va);
+ arm_intrnames_init();
arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
arm_dump_avail_init(memsize, sizeof(dump_avail) / sizeof(dump_avail[0]));
pmap_bootstrap(freemempos, pmap_bootstrap_lastaddr, &kernel_l1pt);
diff --git a/sys/arm/arm/swtch.S b/sys/arm/arm/swtch.S
index e93b948..4c422e8 100644
--- a/sys/arm/arm/swtch.S
+++ b/sys/arm/arm/swtch.S
@@ -79,6 +79,7 @@
*/
#include "assym.s"
+#include "opt_sched.h"
#include <machine/asm.h>
#include <machine/asmacros.h>
@@ -428,6 +429,7 @@ ENTRY(cpu_switch)
/* Release the old thread */
str r6, [r4, #TD_LOCK]
+#if defined(SCHED_ULE) && defined(SMP)
ldr r6, .Lblocked_lock
GET_CURTHREAD_PTR(r3)
@@ -435,6 +437,7 @@ ENTRY(cpu_switch)
ldr r4, [r3, #TD_LOCK]
cmp r4, r6
beq 1b
+#endif
/* XXXSCW: Safe to re-enable FIQs here */
diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c
index e737dc8..bdc4ccc 100644
--- a/sys/arm/arm/trap.c
+++ b/sys/arm/arm/trap.c
@@ -866,7 +866,11 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
register_t *ap;
int error;
+#ifdef __ARM_EABI__
+ sa->code = td->td_frame->tf_r7;
+#else
sa->code = sa->insn & 0x000fffff;
+#endif
ap = &td->td_frame->tf_r0;
if (sa->code == SYS_syscall) {
sa->code = *ap++;
@@ -905,16 +909,18 @@ syscall(struct thread *td, trapframe_t *frame)
struct syscall_args sa;
int error;
+#ifndef __ARM_EABI__
sa.insn = *(uint32_t *)(frame->tf_pc - INSN_SIZE);
switch (sa.insn & SWI_OS_MASK) {
case 0: /* XXX: we need our own one. */
- sa.nap = 4;
break;
default:
call_trapsignal(td, SIGILL, 0);
userret(td, frame);
return;
}
+#endif
+ sa.nap = 4;
error = syscallenter(td, &sa);
KASSERT(error != 0 || td->td_ar == NULL,
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
index cc87bbe..22a209b 100644
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -398,6 +398,12 @@ cpu_thread_alloc(struct thread *td)
PAGE_SIZE) - 1;
td->td_frame = (struct trapframe *)
((u_int)td->td_kstack + USPACE_SVC_STACK_TOP - sizeof(struct pcb)) - 1;
+ /*
+ * Ensure td_frame is aligned to an 8 byte boundary as it will be
+ * placed into the stack pointer which must be 8 byte aligned in
+ * the ARM EABI.
+ */
+ td->td_frame = (struct trapframe *)((u_int)td->td_frame & ~7);
#ifdef __XSCALE__
#ifndef CPU_XSCALE_CORE3
pmap_use_minicache(td->td_kstack, td->td_kstack_pages * PAGE_SIZE);
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fb.c b/sys/arm/broadcom/bcm2835/bcm2835_fb.c
index 35343c8..0f1e81c 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_fb.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_fb.c
@@ -136,6 +136,7 @@ struct video_adapter_softc {
int console;
intptr_t fb_addr;
+ intptr_t fb_paddr;
unsigned int fb_size;
unsigned int height;
@@ -222,6 +223,7 @@ bcm_fb_init(void *arg)
fb_config->screen_size);
va_sc->fb_addr = (intptr_t)pmap_mapdev(fb_config->base, fb_config->screen_size);
+ va_sc->fb_paddr = fb_config->base;
va_sc->fb_size = fb_config->screen_size;
va_sc->depth = fb_config->bpp;
va_sc->stride = fb_config->pitch;
@@ -795,7 +797,7 @@ bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
* framebuffer, since it shouldn't be touched
*/
if (offset < sc->stride*sc->height) {
- *paddr = sc->fb_addr + offset;
+ *paddr = sc->fb_paddr + offset;
return (0);
}
@@ -805,6 +807,27 @@ bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
static int
bcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
{
+ struct video_adapter_softc *sc;
+ struct fbtype *fb;
+
+ sc = (struct video_adapter_softc *)adp;
+
+ switch (cmd) {
+ case FBIOGTYPE:
+ fb = (struct fbtype *)data;
+ fb->fb_type = FBTYPE_PCIMISC;
+ fb->fb_height = sc->height;
+ fb->fb_width = sc->width;
+ fb->fb_depth = sc->depth;
+ if (sc->depth <= 1 || sc->depth > 8)
+ fb->fb_cmsize = 0;
+ else
+ fb->fb_cmsize = 1 << sc->depth;
+ fb->fb_size = sc->fb_size;
+ break;
+ default:
+ return (fb_commonioctl(adp, cmd, data));
+ }
return (0);
}
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
index 7308c0f..7eff61c 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
@@ -82,11 +82,6 @@ initarm_late_init(void)
pcell_t cells[2];
int len;
- /*
- * It seems there is no way to let syscons framework know
- * that framebuffer resolution has changed. So just try
- * to fetch data from FDT and go with defaults if failed
- */
system = OF_finddevice("/system");
if (system != 0) {
len = OF_getprop(system, "linux,serial", &cells, sizeof(cells));
diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE
index 1481d92..6336c0c 100644
--- a/sys/arm/conf/BEAGLEBONE
+++ b/sys/arm/conf/BEAGLEBONE
@@ -37,6 +37,7 @@ options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
options PROCFS #Process filesystem (requires PSEUDOFS)
options PSEUDOFS #Pseudo-filesystem framework
+options TMPFS #Efficient memory filesystem
options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI
options KTRACE #ktrace(1) support
@@ -61,9 +62,9 @@ options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
#options DIAGNOSTIC
# NFS support
-#options NFSCL
+options NFSCL
#options NFSD
-#options NFSLOCKD
+options NFSLOCKD
# Uncomment this for NFS root
#options NFS_ROOT #NFS usable as /, requires NFSCL
@@ -124,4 +125,3 @@ device axe # ASIX Electronics USB Ethernet
options FDT
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=beaglebone.dts
-
diff --git a/sys/arm/conf/CUBIEBOARD b/sys/arm/conf/CUBIEBOARD
new file mode 100644
index 0000000..82f484b
--- /dev/null
+++ b/sys/arm/conf/CUBIEBOARD
@@ -0,0 +1,134 @@
+# CUBIEBOARD -- Custom configuration for the CUBIEBOARD ARM development
+# platform, check out http://www.cubieboard.org
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+
+ident CUBIEBOARD
+
+include "../allwinner/std.a10"
+
+makeoptions MODULES_OVERRIDE=""
+makeoptions WITHOUT_MODULES="ahc"
+
+options HZ=100
+options SCHED_4BSD #4BSD scheduler
+options INET #InterNETworking
+options INET6 #IPv6 communications protocols
+options FFS #Berkeley Fast Filesystem
+options SOFTUPDATES #Enable FFS soft updates support
+options UFS_ACL #Support for access control lists
+options UFS_DIRHASH #Improve performance on big directories
+options MSDOSFS #MSDOS Filesystem
+options CD9660 #ISO 9660 Filesystem
+options PROCFS #Process filesystem (requires PSEUDOFS)
+options PSEUDOFS #Pseudo-filesystem framework
+options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!]
+options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI
+options KTRACE #ktrace(1) support
+options SYSVSHM #SYSV-style shared memory
+options SYSVMSG #SYSV-style message queues
+options SYSVSEM #SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options PREEMPTION
+options FREEBSD_BOOT_LOADER
+
+# Debugging
+makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
+options BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT #Enable verbose sysinit messages
+options KDB
+options DDB #Enable the kernel debugger
+options INVARIANTS #Enable calls of extra sanity checking
+options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS
+options WITNESS #Enable checks to detect deadlocks and cycles
+options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS support
+#options NFSCL
+#options NFSSERVER #Network Filesystem Server
+#options NFSCLIENT #Network Filesystem Client
+
+# Uncomment this for NFS root
+#options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=cpsw0
+
+# MMC/SD/SDIO card slot support
+#device mmc # mmc/sd bus
+#device mmcsd # mmc/sd flash cards
+
+# Boot device is 2nd slice on MMC/SD card
+options ROOTDEVNAME=\"ufs:/dev/da0s2\"
+
+# ATA controllers
+#device ahci # AHCI-compatible SATA controllers
+#device ata # Legacy ATA/SATA controllers
+#options ATA_CAM # Handle legacy controllers with CAM
+#options ATA_STATIC_ID # Static device numbering
+
+# Console and misc
+#device uart
+#device uart_ns8250
+device pty
+device snp
+device md
+device random # Entropy device
+
+# I2C support
+#device iicbus
+#device iic
+
+# GPIO
+#device gpio
+
+device scbus # SCSI bus (required for SCSI)
+device da # Direct Access (disks)
+device pass
+
+# USB support
+device usb
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+#device uhci
+#device ohci
+device ehci
+
+device umass
+
+# Ethernet
+device loop
+device ether
+device mii
+device smscphy
+#device cpsw
+device bpf
+
+# USB ethernet support, requires miibus
+device miibus
+
+# Flattened Device Tree
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=cubieboard.dts
+
diff --git a/sys/arm/conf/DOCKSTAR b/sys/arm/conf/DOCKSTAR
index 3dd83fc..25c0121 100644
--- a/sys/arm/conf/DOCKSTAR
+++ b/sys/arm/conf/DOCKSTAR
@@ -5,7 +5,7 @@
#
ident DOCKSTAR
-include "../mv/kirkwood/std.sheevaplug"
+include "../mv/kirkwood/std.db88f6xxx"
options SOC_MV_KIRKWOOD
makeoptions MODULES_OVERRIDE=""
diff --git a/sys/arm/conf/DREAMPLUG-1001 b/sys/arm/conf/DREAMPLUG-1001
new file mode 100644
index 0000000..442cde0
--- /dev/null
+++ b/sys/arm/conf/DREAMPLUG-1001
@@ -0,0 +1,183 @@
+# Kernel config for GlobalScale Technologies DreamPlug version 1001.
+#
+# This is for units that are version 10, revision 01, with NOR SPI flash.
+# These units are identified with the number "1001" on the S/N label.
+#
+# For more information on this file, please read the handbook section on
+# Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+#
+
+ident DREAMPLUG-1001
+
+include "../mv/kirkwood/std.db88f6xxx"
+
+makeoptions FDT_DTS_FILE=dreamplug-1001.dts
+
+makeoptions MODULES_OVERRIDE=""
+
+options SOC_MV_KIRKWOOD
+
+options SCHED_4BSD #4BSD scheduler
+options INET #InterNETworking
+options INET6 #IPv6 communications protocols
+options SOFTUPDATES
+options CD9660 #ISO 9660 filesystem
+options FFS #Berkeley Fast Filesystem
+options MSDOSFS #MS DOS File System (FAT, FAT32)
+options NULLFS #NULL filesystem
+options TMPFS #Efficient memory filesystem
+options SYSVSHM #SYSV-style shared memory
+options SYSVMSG #SYSV-style message queues
+options SYSVSEM #SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+options GEOM_ELI # Disk encryption.
+options GEOM_LABEL # Providers labelization.
+options GEOM_PART_GPT # GPT partitioning
+
+# Flattened Device Tree
+device fdt
+options FDT
+options FDT_DTB_STATIC
+
+# Misc pseudo devices
+device bpf #Required for DHCP
+device faith #IPv6-to-IPv4 relaying (translation)
+device firmware #firmware(9) required for USB wlan
+device gif #IPv6 and IPv4 tunneling
+device loop #Network loopback
+device md #Memory/malloc disk
+device pty #BSD-style compatibility pseudo ttys
+device random #Entropy device
+device tun #Packet tunnel.
+device ether #Required for all ethernet devices
+device vlan #802.1Q VLAN support
+device wlan #802.11 WLAN support
+
+# cam support for umass and ahci
+device scbus
+device pass
+device da
+device cd
+
+# Serial ports
+device uart
+
+# Networking
+device mge # Marvell Gigabit Ethernet controller
+device mii
+device e1000phy
+
+# USB
+options USB_HOST_ALIGN=32 # Align DMA to cacheline
+#options USB_DEBUG # Compile in USB debug support
+device usb # Basic usb support
+device ehci # USB host controller
+device umass # Mass storage
+device uhid # Human-interface devices
+device rum # Ralink Technology RT2501USB wireless NICs
+device uath # Atheros AR5523 wireless NICs
+device ural # Ralink Technology RT2500USB wireless NICs
+device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device urtw # Realtek RTL8187B/L USB
+device upgt # Conexant/Intersil PrismGT SoftMAC USB
+device u3g # USB-based 3G modems (Option, Huawei, Sierra)
+
+# I2C (TWSI)
+device iic
+device iicbus
+
+# SATA
+device mvs
+device ahci
+
+# Sound
+device sound
+device snd_uaudio
+
+#crypto
+device cesa # Marvell security engine
+device crypto
+device cryptodev
+
+# IPSec
+device enc
+options IPSEC
+options IPSEC_NAT_T
+options TCP_SIGNATURE #include support for RFC 2385
+
+# IPFW
+options IPFIREWALL
+options IPFIREWALL_DEFAULT_TO_ACCEPT
+options IPFIREWALL_VERBOSE
+options IPFIREWALL_VERBOSE_LIMIT=100
+options IPFIREWALL_NAT
+options LIBALIAS
+options DUMMYNET
+options IPDIVERT
+
+#PF
+device pf
+device pflog
+device pfsync
+
+# ALTQ, required for PF
+options ALTQ # Basic ALTQ support
+options ALTQ_CBQ # Class Based Queueing
+options ALTQ_RED # Random Early Detection
+options ALTQ_RIO # RED In/Out
+options ALTQ_HFSC # Hierarchical Packet Scheduler
+options ALTQ_CDNR # Traffic conditioner
+options ALTQ_PRIQ # Priority Queueing
+options ALTQ_NOPCC # Required if the TSC is unusable
+#options ALTQ_DEBUG
+
+# Debugging
+makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
+options BREAK_TO_DEBUGGER
+options ALT_BREAK_TO_DEBUGGER
+options DDB
+options KDB
+options DIAGNOSTIC
+options INVARIANTS #Enable calls of extra sanity checking
+options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS #Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
+#options WITNESS_KDB
+
+# Enable these options for nfs root configured via BOOTP.
+options NFSCL #Network Filesystem Client
+options NFSLOCKD #Network Lock Manager
+#options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=mge0
+
+# If not using BOOTP, use something like one of these...
+#options ROOTDEVNAME=\"ufs:/dev/da1a\"
+options ROOTDEVNAME=\"ufs:/dev/da1s1a\"
+#options ROOTDEVNAME=\"ufs:/dev/da1p10\"
+#options ROOTDEVNAME=\"nfs:192.168.0.254/dreamplug\"
+
+# To use this configuration with the (rare) model 1001N (nand flash),
+# create a kernel config file that looks like this:
+#
+# include DREAMPLUG-1001
+# nomakeoptions FDT_DTS_FILE
+# makeoptions FDT_DTS_FILE=dreamplug-1001N.dts
+# device nand
+
diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES
index 1d4f897..fa36275 100644
--- a/sys/arm/conf/NOTES
+++ b/sys/arm/conf/NOTES
@@ -19,7 +19,6 @@ files "../econa/files.econa"
files "../mv/files.mv"
files "../mv/discovery/files.db78xxx"
files "../mv/kirkwood/files.kirkwood"
-files "../mv/kirkwood/files.sheevaplug"
files "../mv/orion/files.db88f5xxx"
files "../mv/orion/files.ts7800"
files "../s3c2xx0/files.s3c2xx0"
diff --git a/sys/arm/conf/SHEEVAPLUG b/sys/arm/conf/SHEEVAPLUG
index b7de8f6..c6bd901 100644
--- a/sys/arm/conf/SHEEVAPLUG
+++ b/sys/arm/conf/SHEEVAPLUG
@@ -5,7 +5,7 @@
#
ident SHEEVAPLUG
-include "../mv/kirkwood/std.sheevaplug"
+include "../mv/kirkwood/std.db88f6xxx"
options SOC_MV_KIRKWOOD
makeoptions MODULES_OVERRIDE=""
diff --git a/sys/arm/include/atomic.h b/sys/arm/include/atomic.h
index 4862453..82b7d1b 100644
--- a/sys/arm/include/atomic.h
+++ b/sys/arm/include/atomic.h
@@ -677,6 +677,17 @@ atomic_readandclear_32(volatile u_int32_t *p)
#define atomic_store_rel_long atomic_store_long
#define atomic_load_acq_32 atomic_load_32
#define atomic_load_acq_long atomic_load_long
+#define atomic_add_acq_long atomic_add_long
+#define atomic_add_rel_long atomic_add_long
+#define atomic_subtract_acq_long atomic_subtract_long
+#define atomic_subtract_rel_long atomic_subtract_long
+#define atomic_clear_acq_long atomic_clear_long
+#define atomic_clear_rel_long atomic_clear_long
+#define atomic_set_acq_long atomic_set_long
+#define atomic_set_rel_long atomic_set_long
+#define atomic_cmpset_acq_long atomic_cmpset_long
+#define atomic_cmpset_rel_long atomic_cmpset_long
+#define atomic_load_acq_long atomic_load_long
#undef __with_interrupts_disabled
static __inline void
@@ -758,25 +769,13 @@ atomic_store_long(volatile u_long *dst, u_long src)
*dst = src;
}
-#define atomic_add_acq_long atomic_add_long
-#define atomic_add_rel_long atomic_add_long
-#define atomic_subtract_acq_long atomic_subtract_long
-#define atomic_subtract_rel_long atomic_subtract_long
-#define atomic_clear_acq_long atomic_clear_long
-#define atomic_clear_rel_long atomic_clear_long
-#define atomic_set_acq_long atomic_set_long
-#define atomic_set_rel_long atomic_set_long
-#define atomic_cmpset_acq_long atomic_cmpset_long
-#define atomic_cmpset_rel_long atomic_cmpset_long
-#define atomic_load_acq_long atomic_load_long
-
#define atomic_clear_ptr atomic_clear_32
#define atomic_set_ptr atomic_set_32
#define atomic_cmpset_ptr atomic_cmpset_32
#define atomic_cmpset_rel_ptr atomic_cmpset_rel_32
#define atomic_cmpset_acq_ptr atomic_cmpset_acq_32
#define atomic_store_ptr atomic_store_32
-#define atomic_store_rel_ptr atomic_store_ptr
+#define atomic_store_rel_ptr atomic_store_rel_32
#define atomic_add_int atomic_add_32
#define atomic_add_acq_int atomic_add_acq_32
diff --git a/sys/arm/include/intr.h b/sys/arm/include/intr.h
index 45e36e9..9392969 100644
--- a/sys/arm/include/intr.h
+++ b/sys/arm/include/intr.h
@@ -70,6 +70,7 @@
int arm_get_next_irq(int);
void arm_mask_irq(uintptr_t);
void arm_unmask_irq(uintptr_t);
+void arm_intrnames_init(void);
void arm_setup_irqhandler(const char *, int (*)(void*), void (*)(void*),
void *, int, int, void **);
int arm_remove_irqhandler(int, void *);
diff --git a/sys/arm/include/proc.h b/sys/arm/include/proc.h
index c1bce00..597a5ad 100644
--- a/sys/arm/include/proc.h
+++ b/sys/arm/include/proc.h
@@ -60,7 +60,11 @@ struct mdproc {
void *md_sigtramp;
};
+#ifdef __ARM_EABI__
+#define KINFO_PROC_SIZE 816
+#else
#define KINFO_PROC_SIZE 792
+#endif
#define MAXARGS 8
struct syscall_args {
@@ -69,7 +73,9 @@ struct syscall_args {
register_t args[MAXARGS];
int narg;
u_int nap;
+#ifndef __ARM_EABI__
u_int32_t insn;
+#endif
};
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h
index eac46cc..267ba6e 100644
--- a/sys/arm/include/vmparam.h
+++ b/sys/arm/include/vmparam.h
@@ -134,12 +134,15 @@
#endif
#define VM_MAX_KERNEL_ADDRESS 0xffffffff
+
/*
* Virtual size (bytes) for various kernel submaps.
*/
-
#ifndef VM_KMEM_SIZE
-#define VM_KMEM_SIZE (12*1024*1024)
+#define VM_KMEM_SIZE (12*1024*1024)
+#endif
+#ifndef VM_KMEM_SIZE_SCALE
+#define VM_KMEM_SIZE_SCALE (2)
#endif
#define MAXTSIZ (16*1024*1024)
diff --git a/sys/arm/mv/kirkwood/files.sheevaplug b/sys/arm/mv/kirkwood/files.sheevaplug
deleted file mode 100644
index f56c2ab..0000000
--- a/sys/arm/mv/kirkwood/files.sheevaplug
+++ /dev/null
@@ -1,4 +0,0 @@
-# $FreeBSD$
-
-include "arm/mv/kirkwood/files.kirkwood"
-arm/mv/kirkwood/sheevaplug.c standard
diff --git a/sys/arm/mv/kirkwood/std.sheevaplug b/sys/arm/mv/kirkwood/std.sheevaplug
deleted file mode 100644
index 44c977e..0000000
--- a/sys/arm/mv/kirkwood/std.sheevaplug
+++ /dev/null
@@ -1,5 +0,0 @@
-# $FreeBSD$
-
-include "../mv/std.mv"
-include "../mv/kirkwood/std.kirkwood"
-files "../mv/kirkwood/files.sheevaplug"
diff --git a/sys/arm/mv/mv_machdep.c b/sys/arm/mv/mv_machdep.c
index ae74fa3..fba222d 100644
--- a/sys/arm/mv/mv_machdep.c
+++ b/sys/arm/mv/mv_machdep.c
@@ -279,6 +279,25 @@ out:
}
/*
+ * Supply a default do-nothing implementation of fdt_pci_devmap() via a weak
+ * alias. Many Marvell platforms don't support a PCI interface, but to support
+ * those that do, we end up with a reference to this function below, in
+ * platform_devmap_init(). If "device pci" appears in the kernel config, the
+ * real implementation of this function in dev/fdt/fdt_pci.c overrides the weak
+ * alias defined here.
+ */
+int mv_default_fdt_pci_devmap(phandle_t node, struct pmap_devmap *devmap,
+ vm_offset_t io_va, vm_offset_t mem_va);
+int
+mv_default_fdt_pci_devmap(phandle_t node, struct pmap_devmap *devmap,
+ vm_offset_t io_va, vm_offset_t mem_va)
+{
+
+ return (0);
+}
+__weak_reference(mv_default_fdt_pci_devmap, fdt_pci_devmap);
+
+/*
* XXX: When device entry in devmap has pd_size smaller than section size,
* system will freeze during initialization
*/
diff --git a/sys/arm/ti/am335x/am335x_scm_padconf.c b/sys/arm/ti/am335x/am335x_scm_padconf.c
index 4ed63a3..6bb89f5 100644
--- a/sys/arm/ti/am335x/am335x_scm_padconf.c
+++ b/sys/arm/ti/am335x/am335x_scm_padconf.c
@@ -86,127 +86,117 @@ const struct ti_scm_padstate ti_padstate_devmap[] = {
};
const struct ti_scm_padconf ti_padconf_devmap[] = {
- _PIN(0x800, "GPMC_AD0", 32, 7,"gpmc_ad0", "mmc1_dat0", NULL, NULL, NULL, NULL, NULL, "gpio1_0"),
- _PIN(0x804, "GPMC_AD1", 33, 7,"gpmc_ad1", "mmc1_dat1", NULL, NULL, NULL, NULL, NULL, "gpio1_1"),
- _PIN(0x808, "GPMC_AD2", 34, 7,"gpmc_ad2", "mmc1_dat2", NULL, NULL, NULL, NULL, NULL, "gpio1_2"),
- _PIN(0x80C, "GPMC_AD3", 35, 7,"gpmc_ad3", "mmc1_dat3", NULL, NULL, NULL, NULL, NULL, "gpio1_3"),
- _PIN(0x810, "GPMC_AD4", 36, 7,"gpmc_ad4", "mmc1_dat4", NULL, NULL, NULL, NULL, NULL, "gpio1_4"),
- _PIN(0x814, "GPMC_AD5", 37, 7,"gpmc_ad5", "mmc1_dat5", NULL, NULL, NULL, NULL, NULL, "gpio1_5"),
- _PIN(0x818, "GPMC_AD6", 38, 7,"gpmc_ad6", "mmc1_dat6", NULL, NULL, NULL, NULL, NULL, "gpio1_6"),
- _PIN(0x81C, "GPMC_AD7", 39, 7,"gpmc_ad7", "mmc1_dat7", NULL, NULL, NULL, NULL, NULL, "gpio1_7"),
-#if 0 /* Incomplete Entries - fill with data from table 2-7 in datasheet */
- _PIN(0x820, "gpmc_ad8", 0, 0, "gpmc_ad8", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x824, "gpmc_ad9", 0, 0, "gpmc_ad9", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x828, "gpmc_ad10", 0, 0, "gpmc_ad10", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x82C, "gpmc_ad11", 0, 0, "gpmc_ad11", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x830, "gpmc_ad12", 0, 0, "gpmc_ad12", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x834, "gpmc_ad13", 0, 0, "gpmc_ad13", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x838, "gpmc_ad14", 0, 0, "gpmc_ad14", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x83C, "gpmc_ad15", 0, 0, "gpmc_ad15", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x840, "gpmc_a0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x844, "gpmc_a1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x848, "gpmc_a2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x84C, "gpmc_a3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x850, "gpmc_a4", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-#endif
- _PIN(0x854, "GPMC_A5", 53, 7, "gpmc_a5", "gmii2_txd0", "rgmii2_td0", "rmii2_txd0", "gpmc_a21", "pr1_mii1_rxd3", "eQEP1B_in", "gpio1_21"),
- _PIN(0x858, "GPMC_A6", 54, 7, "gpmc_a6", "gmii2_txclk", "rgmii2_tclk", "mmc2_dat4", "gpmc_a22", "pr1_mii1_rxd2", "eQEP1_index", "gpio1_22"),
- _PIN(0x85C, "GPMC_A7", 55, 7, "gpmc_a7", "gmii2_rxclk", "rgmii2_rclk", "mmc2_dat5", "gpmc_a23", "pr1_mii1_rxd1", "eQEP1_strobe", "gpio1_23"),
- _PIN(0x860, "GPMC_A8", 56, 7, "gpmc_a8", "gmii2_rxd3", "rgmii2_rd3", "mmc2_dat6", "gpmc_a24", "pr1_mii1_rxd0", "mcasp0_aclkx", "gpio1_24"),
-#if 0
- _PIN(0x864, "gpmc_a9", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x868, "gpmc_a10", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x86C, "gpmc_a11", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x870, "gpmc_wait0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x874, "gpmc_wpn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x878, "gpmc_be1n", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x87c, "gpmc_csn0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x880, "gpmc_csn1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x884, "gpmc_csn2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x888, "gpmc_csn3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x88c, "gpmc_clk", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x890, "gpmc_advn_ale", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x894, "gpmc_oen_ren", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x898, "gpmc_wen", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x89c, "gpmc_be0n_cle", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8a0, "lcd_data0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8a4, "lcd_data1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8a8, "lcd_data2", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8ac, "lcd_data3", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8b0, "lcd_data4", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8b4, "lcd_data5", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8b8, "lcd_data6", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8bc, "lcd_data7", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8c0, "lcd_data8", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8c4, "lcd_data9", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8c8, "lcd_data10", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8cc, "lcd_data11", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8d0, "lcd_data12", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8d4, "lcd_data13", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8d8, "lcd_data14", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8dc, "lcd_data15", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8e0, "lcd_vsync", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8e4, "lcd_hsync", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8e8, "lcd_pclk", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x8ec, "lcd_ac_bias_en", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-#endif
- _PIN(0x8f0, "MMC0_DAT3", 90, 7, "mmc0_dat3", "gpmc_a20", "uart4_ctsn", "timer5", "uart1_dcdn", "pr1_pru0_pru_r30_8", "pr1_pru0_pru_r31_8", "gpio2_26"),
- _PIN(0x8f4, "MMC0_DAT2", 91, 7, "mmc0_dat2", "gpmc_a21", "uart4_rtsn", "timer6", "uart1_dsrn", "pr1_pru0_pru_r30_9", "pr1_pru0_pru_r31_9", "gpio2_27"),
- _PIN(0x8f8, "MMC0_DAT1", 92, 7, "mmc0_dat1", "gpmc_a22", "uart5_ctsn", "uart3_rxd", "uart1_dtrn", "pr1_pru0_pru_r30_10", "pr1_pru0_pru_r31_10", "gpio2_28"),
- _PIN(0x8fc, "MMC0_DAT0", 93, 7, "mmc0_dat0", "gpmc_a23", "uart5_rtsn", "uart3_txd", "uart1_rin", "pr1_pru0_pru_r30_11", "pr1_pru0_pru_r31_11", "gpio2_29"),
- _PIN(0x900, "MMC0_CLK", 94, 7, "mmc0_clk", "gpmc_a24", "uart3_ctsn", "uart2_rxd", "dcan1_tx", "pr1_pru0_pru_r30_12", "pr1_pru0_pru_r31_12", "gpio2_30"),
- _PIN(0x904, "MMC0_CMD", 95, 7, "mmc0_cmd", "gpmc_a25", "uart3_rtsn", "uart2_txd", "dcan1_rx", "pr1_pru0_pru_r30_13", "pr1_pru0_pru_r31_13", "gpio2_31"),
- _PIN(0x908, "MII1_COL", 96, 7, "gmii1_col", "rmii2_refclk", "spi1_sclk", "uart5_rxd", "mcasp1_axr2", "mmc2_dat3", "mcasp0_axr2", "gpio3_0"),
- _PIN(0x90c, "MII1_CRS", 97, 7, "gmii1_crs", "rmii1_crs_dv", "spi1_d0", "I2C1_SDA", "mcasp1_aclkx", "uart5_ctsn", "uart2_rxd", "gpio3_1"),
- _PIN(0x910, "MII1_RX_ER", 98, 7, "gmii1_rxerr", "rmii1_rxerr", "spi1_d1", "I2C1_SCL", "mcasp1_fsx", "uart5_rtsn", "uart2_txd", "gpio3_2"),
- _PIN(0x914, "MII1_TX_EN", 99, 7, "gmii1_txen", "rmii1_txen", "rgmii1_tctl", "timer4", "mcasp1_axr0", "eQEP0_index", "mmc2_cmd", "gpio3_3"),
+ _PIN(0x800, "GPMC_AD0", 32, 7,"gpmc_ad0", "mmc1_dat0", NULL, NULL, NULL, NULL, NULL, "gpio1_0"),
+ _PIN(0x804, "GPMC_AD1", 33, 7,"gpmc_ad1", "mmc1_dat1", NULL, NULL, NULL, NULL, NULL, "gpio1_1"),
+ _PIN(0x808, "GPMC_AD2", 34, 7,"gpmc_ad2", "mmc1_dat2", NULL, NULL, NULL, NULL, NULL, "gpio1_2"),
+ _PIN(0x80C, "GPMC_AD3", 35, 7,"gpmc_ad3", "mmc1_dat3", NULL, NULL, NULL, NULL, NULL, "gpio1_3"),
+ _PIN(0x810, "GPMC_AD4", 36, 7,"gpmc_ad4", "mmc1_dat4", NULL, NULL, NULL, NULL, NULL, "gpio1_4"),
+ _PIN(0x814, "GPMC_AD5", 37, 7,"gpmc_ad5", "mmc1_dat5", NULL, NULL, NULL, NULL, NULL, "gpio1_5"),
+ _PIN(0x818, "GPMC_AD6", 38, 7,"gpmc_ad6", "mmc1_dat6", NULL, NULL, NULL, NULL, NULL, "gpio1_6"),
+ _PIN(0x81C, "GPMC_AD7", 39, 7,"gpmc_ad7", "mmc1_dat7", NULL, NULL, NULL, NULL, NULL, "gpio1_7"),
+ _PIN(0x820, "GPMC_AD8", 22, 7, "gpmc_ad8", "lcd_data23", "mmc1_dat0", "mmc2_dat4", "ehrpwm2A", NULL, NULL, "gpio0_22"),
+ _PIN(0x824, "GPMC_AD9", 23, 7, "gpmc_ad9", "lcd_data22", "mmc1_dat1", "mmc2_dat5", "ehrpwm2B", NULL, NULL, "gpio0_23"),
+ _PIN(0x828, "GPMC_AD10", 26, 7, "gpmc_ad10", "lcd_data21", "mmc1_dat2", "mmc2_dat6", "ehrpwm2_tripzone_in", NULL, NULL, "gpio0_26"),
+ _PIN(0x82C, "GPMC_AD11", 27, 7, "gpmc_ad11", "lcd_data20", "mmc1_dat3", "mmc2_dat7", "ehrpwm0_synco", NULL, NULL, "gpio0_27"),
+ _PIN(0x830, "GPMC_AD12", 44, 7, "gpmc_ad12", "lcd_data19", "mmc1_dat4", "mmc2_dat0", "eQEP2A_in", "pr1_mii0_txd2", "pr1_pru0_pru_r30_14", "gpio1_12"),
+ _PIN(0x834, "GPMC_AD13", 45, 7, "gpmc_ad13", "lcd_data18", "mmc1_dat5", "mmc2_dat1", "eQEP2B_in", "pr1_mii0_txd1", "pr1_pru0_pru_r30_15", "gpio1_13"),
+ _PIN(0x838, "GPMC_AD14", 46, 7, "gpmc_ad14", "lcd_data17", "mmc1_dat6", "mmc2_dat2", "eQEP2_index", "pr1_mii0_txd0", "pr1_pru0_pru_r31_14", "gpio1_14"),
+ _PIN(0x83C, "GPMC_AD15", 47, 7, "gpmc_ad15", "lcd_data16", "mmc1_dat7", "mmc2_dat3", "eQEP2_strobe", "pr1_ecap0_ecap_capin_apwm_o", "pr1_pru0_pru_r31_15", "gpio1_15"),
+ _PIN(0x840, "GPMC_A0", 48, 7, "gpmc_a0", "gmii2_txen", "rgmii2_tctl", "rmii2_txen", "gpmc_a16", "pr1_mii_mt1_clk", "ehrpwm1_tripzone_input", "gpio1_16"),
+ _PIN(0x844, "GPMC_A1", 49, 7, "gpmc_a1", "gmii2_rxdv", "rgmii2_rctl", "mmc2_dat0", "gpmc_a17", "pr1_mii1_txd3", "ehrpwm0_synco", "gpio1_17"),
+ _PIN(0x848, "GPMC_A2", 50, 7, "gpmc_a2", "gmii2_txd3", "rgmii2_td3", "mmc2_dat1", "gpmc_a18", "pr1_mii1_txd2", "ehrpwm1A", "gpio1_18"),
+ _PIN(0x84C, "GPMC_A3", 51, 7, "gpmc_a3", "gmii2_txd2", "rgmii2_td2", "mmc2_dat2", "gpmc_a19", "pr1_mii1_txd1", "ehrpwm1B", "gpio1_19"),
+ _PIN(0x850, "GPMC_A4", 52, 7, "gpmc_a4", "gmii2_txd1", "rgmii2_td1", "rmii2_tdx1", "gpmc_a20", "pr1_mii1_txd0", "eQEP1A_in", "gpio1_20"),
+ _PIN(0x854, "GPMC_A5", 53, 7, "gpmc_a5", "gmii2_txd0", "rgmii2_td0", "rmii2_txd0", "gpmc_a21", "pr1_mii1_rxd3", "eQEP1B_in", "gpio1_21"),
+ _PIN(0x858, "GPMC_A6", 54, 7, "gpmc_a6", "gmii2_txclk", "rgmii2_tclk", "mmc2_dat4", "gpmc_a22", "pr1_mii1_rxd2", "eQEP1_index", "gpio1_22"),
+ _PIN(0x85C, "GPMC_A7", 55, 7, "gpmc_a7", "gmii2_rxclk", "rgmii2_rclk", "mmc2_dat5", "gpmc_a23", "pr1_mii1_rxd1", "eQEP1_strobe", "gpio1_23"),
+ _PIN(0x860, "GPMC_A8", 56, 7, "gpmc_a8", "gmii2_rxd3", "rgmii2_rd3", "mmc2_dat6", "gpmc_a24", "pr1_mii1_rxd0", "mcasp0_aclkx", "gpio1_24"),
+ _PIN(0x864, "GPMC_A9", 57, 7, "gmpc_a9", "gmii2_rxd2", "rgmii2_rd2", "mmc2_dat7 / rmii2_crs_dv", "gpmc_a25", "pr1_mii_mr1_clk", "mcasp0_fsx", "gpio1_25"),
+ _PIN(0x868, "GPMC_A10", 58, 7, "gmpc_a10", "gmii2_rxd1", "rgmii2_rd1", "rmii2_rxd1", "gpmc_a26", "pr1_mii1_rxdv", "mcasp0_arx0", "gpio1_26"),
+ _PIN(0x86C, "GPMC_A11", 59, 7, "gmpc_a11", "gmii2_rxd0", "rgmii2_rd0", "rmii2_rxd0", "gpmc_a27", "pr1_mii1_rxer", "mcasp0_axr1", "gpio1_27"),
+ _PIN(0x870, "GPMC_WAIT0", 30, 7, "gpmc_wait0", "gmii2_crs", "gpmc_csn4", "rmii2_crs_dv", "mmc1_sdcd", "pr1_mii1_col", "uart4_rxd", "gpio0_30"),
+ _PIN(0x874, "GPMC_WPn", 31, 7, "gpmc_wpn", "gmii2_rxerr", "gpmc_csn5", "rmii2_rxerr", "mmc2_sdcd", "pr1_mii1_txen", "uart4_txd", "gpio0_31"),
+ _PIN(0x878, "GPMC_BEn1", 60, 7, "gpmc_be1n", "gmii2_col", "gmpc_csn6","mmc2_dat3", "gpmc_dir", "pr1_mii1_rxlink", "mcasp0_aclkr", "gpio1_28"),
+ _PIN(0x87c, "GPMC_CSn0", 61, 7, "gpmc_csn0", NULL, NULL, NULL, NULL, NULL, NULL, "gpio1_29"),
+ _PIN(0x880, "GPMC_CSn1", 62, 7, "gpmc_csn1", "gpmc_clk", "mmc1_clk", "pr1_edio_data_in6", "pr1_edio_data_out6", "pr1_pru1_pru_r30_12", "pr1_pru1_pru_r31_12", "gpio1_30"),
+ _PIN(0x884, "GPMC_CSn2", 63, 7, "gpmc_csn2", "gpmc_be1n", "mmc1_cmd", "pr1_edio_data_in7", "pr1_edio_data_out7", "pr1_pru1_pru_r30_13", "pr1_pru1_pru_r31_13", "gpio1_31"),
+ _PIN(0x888, "GPMC_CSn3", 64, 7, "gpmc_csn3", "gpmc_a3", "rmii2_crs_dv", "mmc2_cmd", "pr1_mii0_crs", "pr1_mdio_data", "EMU4", "gpio2_0"),
+ _PIN(0x88c, "GPMC_CLK", 65, 7, "gpmc_clk", "lcd_memory_clk", "gpmc_wait1", "mmc2_clk", "pr1_mii1_crs", "pr1_mdio_mdclk", "mcasp0_fsr", "gpio2_1"),
+ _PIN(0x890, "GPMC_ADVn_ALE", 66, 7, "gpmc_advn_ale", NULL, "timer4", NULL, NULL, NULL, NULL, "gpio2_2"),
+ _PIN(0x894, "GPMC_OEn_REn", 67, 7, "gpmc_oen_ren", NULL, "timer7", NULL, NULL, NULL, NULL, "gpio2_3"),
+ _PIN(0x898, "GPMC_WEn", 68, 7, "gpmc_wen", NULL, "timer6", NULL, NULL, NULL, NULL, "gpio2_4"),
+ _PIN(0x89c, "GPMC_BEn0_CLE", 67, 7, "gpmc_ben0_cle", NULL, "timer5", NULL, NULL, NULL, NULL, "gpio2_5"),
+ _PIN(0x8a0, "LCD_DATA0", 68, 7, "lcd_data0", "gpmc_a0", "pr1_mii_mt0_clk", "ehrpwm2A", NULL, "pr1_pru1_pru_r30_0", "pr1_pru1_pru_r31_0", "gpio2_6"),
+ _PIN(0x8a4, "LCD_DATA1", 69, 7, "lcd_data1", "gpmc_a1", "pr1_mii0_txen", "ehrpwm2B", NULL, "pr1_pru1_pru_r30_1", "pr1_pru1_pru_r31_1", "gpio2_7"),
+ _PIN(0x8a8, "LCD_DATA2", 70, 7, "lcd_data2", "gpmc_a2", "pr1_mii0_txd3", "ehrpwm2_tripzone_input", NULL, "pr1_pru1_pru_r30_2", "pr1_pru1_pru_r31_2", "gpio2_8"),
+ _PIN(0x8ac, "LCD_DATA3", 71, 7, "lcd_data3", "gpmc_a3", "pr1_mii0_txd2", "ehrpwm0_synco", NULL, "pr1_pru1_pru_r30_3", "pr1_pru1_pru_r31_3", "gpio2_9"),
+ _PIN(0x8b0, "LCD_DATA4", 72, 7, "lcd_data4", "gpmc_a4", "pr1_mii0_txd1", "eQEP2A_in", NULL, "pr1_pru1_pru_r30_4", "pr1_pru1_pru_r31_4", "gpio2_10"),
+ _PIN(0x8b4, "LCD_DATA5", 73, 7, "lcd_data5", "gpmc_a5", "pr1_mii0_txd0", "eQEP2B_in", NULL, "pr1_pru1_pru_r30_5", "pr1_pru1_pru_r31_5", "gpio2_11"),
+ _PIN(0x8b8, "LCD_DATA6", 74, 7, "lcd_data6", "gpmc_a6", "pr1_edio_data_in6", "eQEP2_index", "pr1_edio_data_out6", "pr1_pru1_pru_r30_6", "pr1_pru1_pru_r31_6", "gpio2_12"),
+ _PIN(0x8bc, "LCD_DATA7", 75, 7, "lcd_data7", "gpmc_a7", "pr1_edio_data_in7", "eQEP2_strobe", "pr1_edio_data_out7", "pr1_pru1_pru_r30_7", "pr1_pru1_pru_r31_7", "gpio2_13"),
+ _PIN(0x8c0, "LCD_DATA8", 76, 7, "lcd_data8", "gpmc_a12", "ehrpwm1_tripzone_input", "mcasp0_aclkx", "uart5_txd", "pr1_mii0_rxd3", "uart2_ctsn", "gpio2_14"),
+ _PIN(0x8c4, "LCD_DATA9", 76, 7, "lcd_data9", "gpmc_a13", "ehrpwm0_synco", "mcasp0_fsx", "uart5_rxd", "pr1_mii0_rxd2", "uart2_rtsn", "gpio2_15"),
+ _PIN(0x8c8, "LCD_DATA10", 77, 7, "lcd_data10", "gpmc_a14", "ehrpwm1A", "mcasp0_axr0", NULL, "pr1_mii0_rxd1", "uart3_ctsn", "gpio2_16"),
+ _PIN(0x8cc, "LCD_DATA11", 78, 7, "lcd_data11", "gpmc_a15", "ehrpwm1B", "mcasp0_ahclkr", "mcasp0_axr2", "pr1_mii0_rxd0", "uart3_rtsn", "gpio2_17"),
+ _PIN(0x8d0, "LCD_DATA12", 8, 7, "lcd_data12", "gpmc_a16", "eQEP1A_in", "mcasp0_aclkr", "mcasp0_axr2", "pr1_mii0_rxlink", "uart4_ctsn", "gpio0_8"),
+ _PIN(0x8d4, "LCD_DATA13", 9, 7, "lcd_data13", "gpmc_a17", "eQEP1B_in", "mcasp0_fsr", "mcasp0_axr3", "pr1_mii0_rxer", "uart4_rtsn", "gpio0_9"),
+ _PIN(0x8d8, "LCD_DATA14", 10, 7, "lcd_data14", "gpmc_a18", "eQEP1_index", "mcasp0_axr1", "uart5_rxd", "pr1_mii_mr0_clk", "uart5_ctsn", "gpio0_10"),
+ _PIN(0x8dc, "LCD_DATA15", 11, 7, "lcd_data15", "gpmc_a19", "eQEP1_strobe", "mcasp0_ahclkx", "mcasp0_axr3", "pr1_mii0_rxdv", "uart5_rtsn", "gpio0_11"),
+ _PIN(0x8e0, "LCD_VSYNC", 86, 7, "lcd_vsync", "gpmc_a8", "gpmc_a1", "pr1_edio_data_in2", "pr1_edio_data_out2", "pr1_pru1_pru_r30_8", "pr1_pru1_pru_r31_8", "gpio2_22"),
+ _PIN(0x8e4, "LCD_HSYNC", 87, 7, "lcd_hsync", "gmpc_a9", "gpmc_a2", "pr1_edio_data_in3", "pr1_edio_data_out3", "pr1_pru1_pru_r30_9", "pr1_pru1_pru_r31_9", "gpio2_23"),
+ _PIN(0x8e8, "LCD_PCLK", 88, 7, "lcd_pclk", "gpmc_a10", "pr1_mii0_crs", "pr1_edio_data_in4", "pr1_edio_data_out4", "pr1_pru1_pru_r30_10", "pr1_pru1_pru_r31_10", "gpio2_24"),
+ _PIN(0x8ec, "LCD_AC_BIAS_EN", 89, 7, "lcd_ac_bias_en", "gpmc_a11", "pr1_mii1_crs", "pr1_edio_data_in5", "pr1_edio_data_out5", "pr1_pru1_pru_r30_11", "pr1_pru1_pru_r31_11", "gpio2_25"),
+ _PIN(0x8f0, "MMC0_DAT3", 90, 7, "mmc0_dat3", "gpmc_a20", "uart4_ctsn", "timer5", "uart1_dcdn", "pr1_pru0_pru_r30_8", "pr1_pru0_pru_r31_8", "gpio2_26"),
+ _PIN(0x8f4, "MMC0_DAT2", 91, 7, "mmc0_dat2", "gpmc_a21", "uart4_rtsn", "timer6", "uart1_dsrn", "pr1_pru0_pru_r30_9", "pr1_pru0_pru_r31_9", "gpio2_27"),
+ _PIN(0x8f8, "MMC0_DAT1", 92, 7, "mmc0_dat1", "gpmc_a22", "uart5_ctsn", "uart3_rxd", "uart1_dtrn", "pr1_pru0_pru_r30_10", "pr1_pru0_pru_r31_10", "gpio2_28"),
+ _PIN(0x8fc, "MMC0_DAT0", 93, 7, "mmc0_dat0", "gpmc_a23", "uart5_rtsn", "uart3_txd", "uart1_rin", "pr1_pru0_pru_r30_11", "pr1_pru0_pru_r31_11", "gpio2_29"),
+ _PIN(0x900, "MMC0_CLK", 94, 7, "mmc0_clk", "gpmc_a24", "uart3_ctsn", "uart2_rxd", "dcan1_tx", "pr1_pru0_pru_r30_12", "pr1_pru0_pru_r31_12", "gpio2_30"),
+ _PIN(0x904, "MMC0_CMD", 95, 7, "mmc0_cmd", "gpmc_a25", "uart3_rtsn", "uart2_txd", "dcan1_rx", "pr1_pru0_pru_r30_13", "pr1_pru0_pru_r31_13", "gpio2_31"),
+ _PIN(0x908, "MII1_COL", 96, 7, "gmii1_col", "rmii2_refclk", "spi1_sclk", "uart5_rxd", "mcasp1_axr2", "mmc2_dat3", "mcasp0_axr2", "gpio3_0"),
+ _PIN(0x90c, "MII1_CRS", 97, 7, "gmii1_crs", "rmii1_crs_dv", "spi1_d0", "I2C1_SDA", "mcasp1_aclkx", "uart5_ctsn", "uart2_rxd", "gpio3_1"),
+ _PIN(0x910, "MII1_RX_ER", 98, 7, "gmii1_rxerr", "rmii1_rxerr", "spi1_d1", "I2C1_SCL", "mcasp1_fsx", "uart5_rtsn", "uart2_txd", "gpio3_2"),
+ _PIN(0x914, "MII1_TX_EN", 99, 7, "gmii1_txen", "rmii1_txen", "rgmii1_tctl", "timer4", "mcasp1_axr0", "eQEP0_index", "mmc2_cmd", "gpio3_3"),
_PIN(0x918, "MII1_RX_DV", 100, 7, "gmii1_rxdv", "cd_memory_clk", "rgmii1_rctl", "uart5_txd", "mcasp1_aclkx", "mmc2_dat0", "mcasp0_aclkr", "gpio3_4"),
- _PIN(0x91c, "MII1_TXD3", 16, 7, "gmii1_txd3", "dcan0_tx", "rgmii1_td3", "uart4_rxd", "mcasp1_fsx", "mmc2_dat1", "mcasp0_fsr", "gpio0_16"),
- _PIN(0x920, "MII1_TXD2", 17, 7, "gmii1_txd2", "dcan0_rx", "rgmii1_td2", "uart4_txd", "mcasp1_axr0", "mmc2_dat2", "mcasp0_ahclkx", "gpio0_17"),
- _PIN(0x924, "MII1_TXD1", 21, 7, "gmii1_txd1", "rmii1_txd1", "rgmii1_td1", "mcasp1_fsr", "mcasp1_axr1", "eQEP0A_in", "mmc1_cmd", "gpio0_21"),
- _PIN(0x928, "MII1_TXD0", 28, 7, "gmii1_txd0", "rmii1_txd0", "rgmii1_td0", "mcasp1_axr2", "mcasp1_aclkr", "eQEP0B_in", "mmc1_clk", "gpio0_28"),
+ _PIN(0x91c, "MII1_TXD3", 16, 7, "gmii1_txd3", "dcan0_tx", "rgmii1_td3", "uart4_rxd", "mcasp1_fsx", "mmc2_dat1", "mcasp0_fsr", "gpio0_16"),
+ _PIN(0x920, "MII1_TXD2", 17, 7, "gmii1_txd2", "dcan0_rx", "rgmii1_td2", "uart4_txd", "mcasp1_axr0", "mmc2_dat2", "mcasp0_ahclkx", "gpio0_17"),
+ _PIN(0x924, "MII1_TXD1", 21, 7, "gmii1_txd1", "rmii1_txd1", "rgmii1_td1", "mcasp1_fsr", "mcasp1_axr1", "eQEP0A_in", "mmc1_cmd", "gpio0_21"),
+ _PIN(0x928, "MII1_TXD0", 28, 7, "gmii1_txd0", "rmii1_txd0", "rgmii1_td0", "mcasp1_axr2", "mcasp1_aclkr", "eQEP0B_in", "mmc1_clk", "gpio0_28"),
_PIN(0x92c, "MII1_TX_CLK", 105, 7, "gmii1_txclk", "uart2_rxd", "rgmii1_tclk", "mmc0_dat7", "mmc1_dat0", "uart1_dcdn", "mcasp0_aclkx", "gpio3_9"),
_PIN(0x930, "MII1_RX_CLK", 106, 7, "gmii1_rxclk", "uart2_txd", "rgmii1_rclk", "mmc0_dat6", "mmc1_dat1", "uart1_dsrn", "mcasp0_fsx", "gpio3_10"),
- _PIN(0x934, "MII1_RXD3", 82, 7, "gmii1_rxd3", "uart3_rxd", "rgmii1_rd3", "mmc0_dat5", "mmc1_dat2", "uart1_dtrn", "mcasp0_axr0", "gpio2_18"),
- _PIN(0x938, "MII1_RXD2", 83, 7, "gmii1_rxd2", "uart3_txd", "rgmii1_rd2", "mmc0_dat4", "mmc1_dat3", "uart1_rin", "mcasp0_axr1", "gpio2_19"),
- _PIN(0x93c, "MII1_RXD1", 84, 7, "gmii1_rxd1", "rmii1_rxd1", "rgmii1_rd1", "mcasp1_axr3", "mcasp1_fsr", "eQEP0_strobe", "mmc2_clk", "gpio2_20"),
- _PIN(0x940, "MII1_RXD0", 85, 7, "gmii1_rxd0", "rmii1_rxd0", "rgmii1_rd0", "mcasp1_ahclkx", "mcasp1_ahclkr", "mcasp1_aclkr", "mcasp0_axr3", "gpio2_21"),
- _PIN(0x944, "RMII1_REF_CLK", 29, 7, "rmii1_refclk", "xdma_event_intr2", "spi1_cs0", "uart5_txd", "mcasp1_axr3", "mmc0_pow", "mcasp1_ahclkx", "gpio0_29"),
- _PIN(0x948, "MDIO", 0, 7, "mdio_data", "timer6", "uart5_rxd", "uart3_ctsn", "mmc0_sdcd","mmc1_cmd", "mmc2_cmd","gpio0_0"),
- _PIN(0x94c, "MDC", 1, 7, "mdio_clk", "timer5", "uart5_txd", "uart3_rtsn", "mmc0_sdwp", "mmc1_clk", "mmc2_clk", "gpio0_1"),
-#if 0 /* Incomplete Entries - fill with data from table 2-7 in datasheet */
- _PIN(0x950, "spi0_sclk", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x954, "spi0_d0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-#endif
- _PIN(0x958, "spi0_d1", 4, 7, "spi0_d1", "mmc1_sdwp", "I2C1_SDA", "ehrpwm0_tripzone_input", "pr1_uart0_rxd", "pr1_edio_data_in0", "pr1_edio_data_out0", "gpio0_4"),
- _PIN(0x95c, "spi0_cs0", 5, 7, "spi0_cs0", "mmc2_sdwp", "I2C1_SCL", "ehrpwm0_synci", "pr1_uart0_txd", "pr1_edio_data_in1", "pr1_edio_data_out1", "gpio0_5"),
-#if 0
- _PIN(0x960, "spi0_cs1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x964, "ecap0_in_pwm0_out",0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x968, "uart0_ctsn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x96c, "uart0_rtsn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x970, "uart0_rxd", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x974, "uart0_txd", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-#endif
- _PIN(0x978, "uart1_ctsn", 12, 7, "uart1_ctsn", "timer6_mux1", "dcan0_tx", "I2C2_SDA", "spi1_cs0", "pr1_uart0_cts_n", "pr1_edc_latch0_in", "gpio0_12"),
- _PIN(0x97c, "uart1_rtsn", 13, 7, "uart1_rtsn", "timer5_mux1", "dcan0_rx", "I2C2_SCL", "spi1_cs1", "pr1_uart0_rts_n ", "pr1_edc_latch1_in", "gpio0_13"),
-#if 0
- _PIN(0x980, "uart1_rxd", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x984, "uart1_txd", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
-#endif
+ _PIN(0x934, "MII1_RXD3", 82, 7, "gmii1_rxd3", "uart3_rxd", "rgmii1_rd3", "mmc0_dat5", "mmc1_dat2", "uart1_dtrn", "mcasp0_axr0", "gpio2_18"),
+ _PIN(0x938, "MII1_RXD2", 83, 7, "gmii1_rxd2", "uart3_txd", "rgmii1_rd2", "mmc0_dat4", "mmc1_dat3", "uart1_rin", "mcasp0_axr1", "gpio2_19"),
+ _PIN(0x93c, "MII1_RXD1", 84, 7, "gmii1_rxd1", "rmii1_rxd1", "rgmii1_rd1", "mcasp1_axr3", "mcasp1_fsr", "eQEP0_strobe", "mmc2_clk", "gpio2_20"),
+ _PIN(0x940, "MII1_RXD0", 85, 7, "gmii1_rxd0", "rmii1_rxd0", "rgmii1_rd0", "mcasp1_ahclkx", "mcasp1_ahclkr", "mcasp1_aclkr", "mcasp0_axr3", "gpio2_21"),
+ _PIN(0x944, "RMII1_REF_CLK", 29, 7, "rmii1_refclk", "xdma_event_intr2", "spi1_cs0", "uart5_txd", "mcasp1_axr3", "mmc0_pow", "mcasp1_ahclkx", "gpio0_29"),
+ _PIN(0x948, "MDIO", 0, 7, "mdio_data", "timer6", "uart5_rxd", "uart3_ctsn", "mmc0_sdcd","mmc1_cmd", "mmc2_cmd","gpio0_0"),
+ _PIN(0x94c, "MDC", 1, 7, "mdio_clk", "timer5", "uart5_txd", "uart3_rtsn", "mmc0_sdwp", "mmc1_clk", "mmc2_clk", "gpio0_1"),
+ _PIN(0x950, "SPI0_SCLK", 2, 7, "spi0_sclk", "uart2_rxd", "I2C2_SDA", "ehrpwm0A", "pr1_uart0_cts_n", "pr1_edio_sof", "EMU2", "gpio0_2"),
+ _PIN(0x954, "SPI0_D0", 3, 7, "spi0_d0", "uart2_txd", "i2C2_SCL", "ehrpwm0B", "pr1_uart0_rts_n", "pr1_edio_latch_in", "EMU3", "gpio0_3"),
+ _PIN(0x958, "SPIO_D1", 4, 7, "spi0_d1", "mmc1_sdwp", "I2C1_SDA", "ehrpwm0_tripzone_input", "pr1_uart0_rxd", "pr1_edio_data_in0", "pr1_edio_data_out0", "gpio0_4"),
+ _PIN(0x95c, "SPI0_CS0", 5, 7, "spi0_cs0", "mmc2_sdwp", "I2C1_SCL", "ehrpwm0_synci", "pr1_uart0_txd", "pr1_edio_data_in1", "pr1_edio_data_out1", "gpio0_5"),
+ _PIN(0x960, "SPI0_CS1", 6, 7, "spi0_cs1", "uart3_rxd", "eCAP1_in_PWM1_out", "mcc0_pow", "xdm_event_intr2", "mmc0_sdcd", "EMU4", "gpio0_6"),
+ _PIN(0x964, "ECAP0_IN_PWM0_OUT",7, 7, "eCAP0_in_PWM0_out", "uart3_txd", "spi1_cs1", "pr1_ecap0_ecap_capin_apwm_o", "spi1_sclk", "mmc0_sdwp", "xdma_event_intr2", "gpio0_7"),
+ _PIN(0x968, "UART0_CTSn", 40, 7, "uart0_ctsn", "uart4_rxd", "dcan1_tx", "I2C1_SDA", "spi1_d0", "timer7", "pr1_edc_sync0_out", "gpio1_8"),
+ _PIN(0x96c, "UART0_RTSn", 41, 7, "uart0_rtsn", "uart4_txd", "dcan1_rx", "I2C1_SCL", "spi1_d1", "spi1_cs0", "pr1_edc_sync1_out", "gpio1_9"),
+ _PIN(0x970, "UART0_rxd", 42, 7, "uart0_rxd", "spi1_cs0", "dcan0_tx", "I2C2_SDA", "eCAP2_in_PWM2_out", "pr1_pru1_pru_r30_14", "pr1_pru1_pru_r31_14", "gpio1_10"),
+ _PIN(0x974, "UART0_txd", 43, 7, "uart0_txd", "spi1_cs1", "dcan0_rx", "I2C2_SCL", "eCAP1_in_PWM1_out", "pr1_pru1_pru_r30_15", "pr1_pru1_pru_r31_15", "gpio1_11"),
+ _PIN(0x978, "UART1_CTSn", 12, 7, "uart1_ctsn", "timer6_mux1", "dcan0_tx", "I2C2_SDA", "spi1_cs0", "pr1_uart0_cts_n", "pr1_edc_latch0_in", "gpio0_12"),
+ _PIN(0x97c, "UART1_RTSn", 13, 7, "uart1_rtsn", "timer5_mux1", "dcan0_rx", "I2C2_SCL", "spi1_cs1", "pr1_uart0_rts_n ", "pr1_edc_latch1_in", "gpio0_13"),
+ _PIN(0x980, "UART1_RXD", 14, 7, "uart1_rxd", "mmc1_sdwp", "dcan1_tx", "I2C1_SDA", NULL, "pr1_uart0_rxd", "pr1_pru1_pru_r31_16", "gpio0_14"),
+ _PIN(0x984, "UART1_TXD", 15, 7, "uart1_txd", "mmc2_sdwp", "dcan1_rx", "I2C1_SCL", NULL, "pr1_uart0_txd", "pr1_pru0_pru_r31_16", "gpio0_15"),
_PIN(0x988, "I2C0_SDA", 101, 7, "I2C0_SDA", "timer4", "uart2_ctsn", "eCAP2_in_PWM2_out", NULL, NULL, NULL, "gpio3_5"),
_PIN(0x98c, "I2C0_SCL", 102, 7, "I2C0_SCL", "timer7", "uart2_rtsn", "eCAP1_in_PWM1_out", NULL, NULL, NULL, "gpio3_6"),
+ _PIN(0x990, "MCASP0_ACLKX", 110, 7, "mcasp0_aclkx", "ehrpwm0A", NULL, "spi1_sclk", "mmc0_sdcd", "pr1_pru0_pru_r30_0", "pr1_pru0_pru_r31_0", "gpio3_14"),
+ _PIN(0x994, "MCASP0_FSX", 111, 7, "mcasp0_fsx", "ehrpwm0B", NULL, "spi1_d0", "mmc1_sdcd", "pr1_pru0_pru_r30_1", "pr1_pru0_pru_r31_1", "gpio3_15"),
+ _PIN(0x998, "MCASP0_AXR0", 112, 7, "mcasp0_axr0", "ehrpwm0_tripzone_input", NULL, "spi1_d1", "mmc2_sdcd", "pr1_pru0_pru_r30_2", "pr1_pru0_pru_r31_2", "gpio3_16"),
+ _PIN(0x99c, "MCASP0_AHCLKR", 113, 7, "mcasp0_ahclkr", "ehrpwm0_synci", "mcasp0_axr2", "spi1_cs0", "eCAP2_in_PWM2_out", "pr1_pru0_pru_r30_3", "pr1_pru0_pru_r31_3", "gpio3_17"),
+ _PIN(0x9a0, "MCASP0_ACLKR", 114, 7, "mcasp0_aclkr", "eQEP0A_in", "mcasp0_axr2", "mcasp1_aclkx", "mmc0_sdwp", "pr1_pru0_pru_r30_4", "pr1_pru0_pru_r31_4", "gpio3_18"),
+ _PIN(0x9a4, "MCASP0_FSR", 115, 7, "mcasp0_fsr", "eQEP0B_in", "mcasp0_axr3", "mcasp1_fsx", "EMU2", "pr1_pru0_pru_r30_5", "pr1_pru0_pru_r31_5", "gpio3_19"),
+ _PIN(0x9a8, "MCASP0_AXR1", 116, 7, "mcasp0_axr1", "eQEP0_index", NULL, "mcasp1_axr0", "EMU3", "pr1_pru0_pru_r30_6", "pr1_pru0_pru_r31_6", "gpio3_20"),
+ _PIN(0x9ac, "MCASP0_AHCLKX", 117, 7, "mcasp0_ahclkx", "eQEP0_strobe", "mcasp0_axr3", "mcasp1_axr1", "EMU4", "pr1_pru0_pru_r30_7", "pr1_pru0_pru_r31_7", "gpio3_21"),
+ _PIN(0x9b0, "XDMA_EVENT_INTR0", 19, 7, "xdma_event_intr0", NULL, "timer4", "clkout1", "spi1_cs1", "pr1_pru1_pru_r31_16", "EMU2", "gpio0_19"),
+ _PIN(0x9b4, "XDMA_EVENT_INTR1", 20, 7, "xdma_event_intr1", NULL, "tclkin", "clkout2", "timer7", "pr1_pru0_pru_r31_16", "EMU3", "gpio0_20"),
#if 0
- _PIN(0x990, "mcasp0_aclkx", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x994, "mcasp0_fsx", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x998, "mcasp0_axr0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x99c, "mcasp0_ahclkr", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9a0, "mcasp0_aclkr", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9a4, "mcasp0_fsr", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9a8, "mcasp0_axr1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9ac, "mcasp0_ahclkx", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9b0, "xdma_event_intr0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9b4, "xdma_event_intr1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9b8, "nresetin_out", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9bc, "porz", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9c0, "nnmi", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
@@ -218,8 +208,10 @@ const struct ti_scm_padconf ti_padconf_devmap[] = {
_PIN(0x9d8, "tdo", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9dc, "tck", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9e0, "ntrst", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9e4, "emu0", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0x9e8, "emu1", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+#endif
+ _PIN(0x9e4, "EMU0", 103, 7, "EMU0", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_7"),
+ _PIN(0x9e8, "EMU1", 104, 0, "EMU1", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_8"),
+#if 0
_PIN(0x9ec, "osc1_in", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9f0, "osc1_out", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0x9f4, "osc1_vss", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
@@ -228,17 +220,17 @@ const struct ti_scm_padconf ti_padconf_devmap[] = {
_PIN(0xa00, "ext_wakeup", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0xa04, "enz_kaldo_1p8v", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
#endif
- _PIN(0xa08, "USB0_DM", 0, 0, "USB0_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa0c, "USB0_DP", 0, 0, "USB0_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa10, "USB0_CE", 0, 0, "USB0_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa14, "USB0_ID", 0, 0, "USB0_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa18, "USB0_VBUS", 0, 0, "USB0_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa1c, "USB0_DRVVBUS", 18, 7, "USB0_DRVVBUS", NULL, NULL, NULL, NULL, NULL, NULL, "gpio0_18"),
- _PIN(0xa20, "USB1_DM", 0, 0, "USB1_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa24, "USB1_DP", 0, 0, "USB1_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa28, "USB1_CE", 0, 0, "USB1_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa2c, "USB1_ID", 0, 0, "USB1_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
- _PIN(0xa30, "USB1_VBUS", 0, 0, "USB1_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa08, "USB0_DM", 0, 0, "USB0_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa0c, "USB0_DP", 0, 0, "USB0_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa10, "USB0_CE", 0, 0, "USB0_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa14, "USB0_ID", 0, 0, "USB0_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa18, "USB0_VBUS", 0, 0, "USB0_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa1c, "USB0_DRVVBUS", 18, 7, "USB0_DRVVBUS", NULL, NULL, NULL, NULL, NULL, NULL, "gpio0_18"),
+ _PIN(0xa20, "USB1_DM", 0, 0, "USB1_DM", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa24, "USB1_DP", 0, 0, "USB1_DP", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa28, "USB1_CE", 0, 0, "USB1_CE", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa2c, "USB1_ID", 0, 0, "USB1_ID", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+ _PIN(0xa30, "USB1_VBUS", 0, 0, "USB1_VBUS", NULL, NULL, NULL, NULL, NULL, NULL, NULL),
_PIN(0xa34, "USB1_DRVVBUS", 109, 7, "USB1_DRVVBUS", NULL, NULL, NULL, NULL, NULL, NULL, "gpio3_13"),
#if 0
_PIN(0xa38, "ddr_resetn", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
diff --git a/sys/arm/ti/cpsw/if_cpsw.c b/sys/arm/ti/cpsw/if_cpsw.c
index a47c131..93702df 100644
--- a/sys/arm/ti/cpsw/if_cpsw.c
+++ b/sys/arm/ti/cpsw/if_cpsw.c
@@ -25,8 +25,22 @@
*/
/*
- * TI 3 Port Switch Ethernet (CPSW) Driver
- * Found in TI8148, AM335x SoCs
+ * TI Common Platform Ethernet Switch (CPSW) Driver
+ * Found in TI8148 "DaVinci" and AM335x "Sitara" SoCs.
+ *
+ * This controller is documented in the AM335x Technical Reference
+ * Manual, in the TMS320DM814x DaVinci Digital Video Processors TRM
+ * and in the TMS320C6452 3 Port Switch Ethernet Subsystem TRM.
+ *
+ * It is basically a single Ethernet port (port 0) wired internally to
+ * a 3-port store-and-forward switch connected to two independent
+ * "sliver" controllers (port 1 and port 2). You can operate the
+ * controller in a variety of different ways by suitably configuring
+ * the slivers and the Address Lookup Engine (ALE) that routes packets
+ * between the ports.
+ *
+ * This code was developed and tested on a BeagleBone with
+ * an AM335x SoC.
*/
#include <sys/cdefs.h>
@@ -76,44 +90,82 @@ __FBSDID("$FreeBSD$");
#include "miibus_if.h"
-static int cpsw_probe(device_t dev);
-static int cpsw_attach(device_t dev);
-static int cpsw_detach(device_t dev);
-static int cpsw_shutdown(device_t dev);
-static int cpsw_suspend(device_t dev);
-static int cpsw_resume(device_t dev);
-
-static int cpsw_miibus_readreg(device_t dev, int phy, int reg);
-static int cpsw_miibus_writereg(device_t dev, int phy, int reg, int value);
-
-static int cpsw_ifmedia_upd(struct ifnet *ifp);
-static void cpsw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
-
-static void cpsw_init(void *arg);
-static void cpsw_init_locked(void *arg);
-static void cpsw_start(struct ifnet *ifp);
-static void cpsw_start_locked(struct ifnet *ifp);
-static void cpsw_stop_locked(struct cpsw_softc *sc);
-static int cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data);
-static int cpsw_init_slot_lists(struct cpsw_softc *sc);
-static void cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot);
-static void cpsw_fill_rx_queue_locked(struct cpsw_softc *sc);
-static void cpsw_tx_watchdog(struct cpsw_softc *sc);
-
-static void cpsw_intr_rx_thresh(void *arg);
+/* Device probe/attach/detach. */
+static int cpsw_probe(device_t);
+static void cpsw_init_slots(struct cpsw_softc *);
+static int cpsw_attach(device_t);
+static void cpsw_free_slot(struct cpsw_softc *, struct cpsw_slot *);
+static int cpsw_detach(device_t);
+
+/* Device Init/shutdown. */
+static void cpsw_init(void *);
+static void cpsw_init_locked(void *);
+static int cpsw_shutdown(device_t);
+static void cpsw_shutdown_locked(struct cpsw_softc *);
+
+/* Device Suspend/Resume. */
+static int cpsw_suspend(device_t);
+static int cpsw_resume(device_t);
+
+/* Ioctl. */
+static int cpsw_ioctl(struct ifnet *, u_long command, caddr_t data);
+
+static int cpsw_miibus_readreg(device_t, int phy, int reg);
+static int cpsw_miibus_writereg(device_t, int phy, int reg, int value);
+
+/* Send/Receive packets. */
static void cpsw_intr_rx(void *arg);
-static void cpsw_intr_rx_locked(void *arg);
-static void cpsw_intr_tx(void *arg);
-static void cpsw_intr_tx_locked(void *arg);
-static void cpsw_intr_misc(void *arg);
-
-static void cpsw_ale_read_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry);
-static void cpsw_ale_write_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry);
-static int cpsw_ale_uc_entry_set(struct cpsw_softc *sc, uint8_t port, uint8_t *mac);
-static int cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac);
-#ifdef CPSW_DEBUG
-static void cpsw_ale_dump_table(struct cpsw_softc *sc);
-#endif
+static struct mbuf *cpsw_rx_dequeue(struct cpsw_softc *);
+static void cpsw_rx_enqueue(struct cpsw_softc *);
+static void cpsw_start(struct ifnet *);
+static void cpsw_tx_enqueue(struct cpsw_softc *);
+static int cpsw_tx_dequeue(struct cpsw_softc *);
+
+/* Misc interrupts and watchdog. */
+static void cpsw_intr_rx_thresh(void *);
+static void cpsw_intr_misc(void *);
+static void cpsw_tick(void *);
+static void cpsw_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int cpsw_ifmedia_upd(struct ifnet *);
+static void cpsw_tx_watchdog(struct cpsw_softc *);
+
+/* ALE support */
+static void cpsw_ale_read_entry(struct cpsw_softc *, uint16_t idx, uint32_t *ale_entry);
+static void cpsw_ale_write_entry(struct cpsw_softc *, uint16_t idx, uint32_t *ale_entry);
+static int cpsw_ale_mc_entry_set(struct cpsw_softc *, uint8_t portmap, uint8_t *mac);
+static int cpsw_ale_update_addresses(struct cpsw_softc *, int purge);
+static void cpsw_ale_dump_table(struct cpsw_softc *);
+
+/* Statistics and sysctls. */
+static void cpsw_add_sysctls(struct cpsw_softc *);
+static void cpsw_stats_collect(struct cpsw_softc *);
+static int cpsw_stats_sysctl(SYSCTL_HANDLER_ARGS);
+
+/*
+ * Arbitrary limit on number of segments in an mbuf to be transmitted.
+ * Packets with more segments than this will be defragmented before
+ * they are queued.
+ */
+#define CPSW_TXFRAGS 8
+
+
+/*
+ * TODO: The CPSW subsystem (CPSW_SS) can drive two independent PHYs
+ * as separate Ethernet ports. To properly support this, we should
+ * break this into two separate devices: a CPSW_SS device that owns
+ * the interrupts and actually talks to the CPSW hardware, and a
+ * separate CPSW Ethernet child device for each Ethernet port. The RX
+ * interrupt, for example, would be part of CPSW_SS; it would receive
+ * a packet, note the input port, and then dispatch it to the child
+ * device's interface queue. Similarly for transmit.
+ *
+ * It's not clear to me whether the device tree should be restructured
+ * with a cpsw_ss node and two child nodes. That would allow specifying
+ * MAC addresses for each port, for example, but might be overkill.
+ *
+ * Unfortunately, I don't have hardware right now that supports two
+ * Ethernet ports via CPSW.
+ */
static device_method_t cpsw_methods[] = {
/* Device interface */
@@ -137,7 +189,6 @@ static driver_t cpsw_driver = {
static devclass_t cpsw_devclass;
-
DRIVER_MODULE(cpsw, simplebus, cpsw_driver, cpsw_devclass, 0, 0);
DRIVER_MODULE(miibus, cpsw, miibus_driver, miibus_devclass, 0, 0);
MODULE_DEPEND(cpsw, ether, 1, 1, 1);
@@ -152,40 +203,109 @@ static struct resource_spec res_spec[] = {
{ -1, 0 }
};
-static struct {
- driver_intr_t *handler;
- char * description;
-} cpsw_intrs[CPSW_INTR_COUNT + 1] = {
- { cpsw_intr_rx_thresh, "CPSW RX threshold interrupt" },
- { cpsw_intr_rx, "CPSW RX interrupt" },
- { cpsw_intr_tx, "CPSW TX interrupt" },
- { cpsw_intr_misc, "CPSW misc interrupt" },
+/* Number of entries here must match size of stats
+ * array in struct cpsw_softc. */
+static struct cpsw_stat {
+ int reg;
+ char *oid;
+} cpsw_stat_sysctls[CPSW_SYSCTL_COUNT] = {
+ {0x00, "GoodRxFrames"},
+ {0x04, "BroadcastRxFrames"},
+ {0x08, "MulticastRxFrames"},
+ {0x0C, "PauseRxFrames"},
+ {0x10, "RxCrcErrors"},
+ {0x14, "RxAlignErrors"},
+ {0x18, "OversizeRxFrames"},
+ {0x1c, "RxJabbers"},
+ {0x20, "ShortRxFrames"},
+ {0x24, "RxFragments"},
+ {0x30, "RxOctets"},
+ {0x34, "GoodTxFrames"},
+ {0x38, "BroadcastTxFrames"},
+ {0x3c, "MulticastTxFrames"},
+ {0x40, "PauseTxFrames"},
+ {0x44, "DeferredTxFrames"},
+ {0x48, "CollisionsTxFrames"},
+ {0x4c, "SingleCollisionTxFrames"},
+ {0x50, "MultipleCollisionTxFrames"},
+ {0x54, "ExcessiveCollisions"},
+ {0x58, "LateCollisions"},
+ {0x5c, "TxUnderrun"},
+ {0x60, "CarrierSenseErrors"},
+ {0x64, "TxOctets"},
+ {0x68, "RxTx64OctetFrames"},
+ {0x6c, "RxTx65to127OctetFrames"},
+ {0x70, "RxTx128to255OctetFrames"},
+ {0x74, "RxTx256to511OctetFrames"},
+ {0x78, "RxTx512to1024OctetFrames"},
+ {0x7c, "RxTx1024upOctetFrames"},
+ {0x80, "NetOctets"},
+ {0x84, "RxStartOfFrameOverruns"},
+ {0x88, "RxMiddleOfFrameOverruns"},
+ {0x8c, "RxDmaOverruns"}
};
-/* Locking macros */
+/*
+ * Basic debug support.
+ */
+
+#define IF_DEBUG(sc) if (sc->cpsw_if_flags & IFF_DEBUG)
+
+static void
+cpsw_debugf_head(const char *funcname)
+{
+ int t = (int)(time_second % (24 * 60 * 60));
+
+ printf("%02d:%02d:%02d %s ", t / (60 * 60), (t / 60) % 60, t % 60, funcname);
+}
+
+#include <machine/stdarg.h>
+static void
+cpsw_debugf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ printf("\n");
+
+}
+
+#define CPSW_DEBUGF(a) do { \
+ IF_DEBUG(sc) { \
+ cpsw_debugf_head(__func__); \
+ cpsw_debugf a; \
+ } \
+} while (0)
+
+
+/*
+ * Locking macros
+ */
#define CPSW_TX_LOCK(sc) do { \
- mtx_assert(&(sc)->rx_lock, MA_NOTOWNED); \
- mtx_lock(&(sc)->tx_lock); \
+ mtx_assert(&(sc)->rx.lock, MA_NOTOWNED); \
+ mtx_lock(&(sc)->tx.lock); \
} while (0)
-#define CPSW_TX_UNLOCK(sc) mtx_unlock(&(sc)->tx_lock)
-#define CPSW_TX_LOCK_ASSERT(sc) mtx_assert(&(sc)->tx_lock, MA_OWNED)
+#define CPSW_TX_UNLOCK(sc) mtx_unlock(&(sc)->tx.lock)
+#define CPSW_TX_LOCK_ASSERT(sc) mtx_assert(&(sc)->tx.lock, MA_OWNED)
#define CPSW_RX_LOCK(sc) do { \
- mtx_assert(&(sc)->tx_lock, MA_NOTOWNED); \
- mtx_lock(&(sc)->rx_lock); \
+ mtx_assert(&(sc)->tx.lock, MA_NOTOWNED); \
+ mtx_lock(&(sc)->rx.lock); \
} while (0)
-#define CPSW_RX_UNLOCK(sc) mtx_unlock(&(sc)->rx_lock)
-#define CPSW_RX_LOCK_ASSERT(sc) mtx_assert(&(sc)->rx_lock, MA_OWNED)
+#define CPSW_RX_UNLOCK(sc) mtx_unlock(&(sc)->rx.lock)
+#define CPSW_RX_LOCK_ASSERT(sc) mtx_assert(&(sc)->rx.lock, MA_OWNED)
#define CPSW_GLOBAL_LOCK(sc) do { \
- if ((mtx_owned(&(sc)->tx_lock) ? 1 : 0) != \
- (mtx_owned(&(sc)->rx_lock) ? 1 : 0)) { \
+ if ((mtx_owned(&(sc)->tx.lock) ? 1 : 0) != \
+ (mtx_owned(&(sc)->rx.lock) ? 1 : 0)) { \
panic("cpsw deadlock possibility detection!"); \
} \
- mtx_lock(&(sc)->tx_lock); \
- mtx_lock(&(sc)->rx_lock); \
+ mtx_lock(&(sc)->tx.lock); \
+ mtx_lock(&(sc)->rx.lock); \
} while (0)
#define CPSW_GLOBAL_UNLOCK(sc) do { \
@@ -198,35 +318,128 @@ static struct {
CPSW_RX_LOCK_ASSERT(sc); \
} while (0)
-
-#include <machine/stdarg.h>
+/*
+ * Read/Write macros
+ */
+#define cpsw_read_4(sc, reg) bus_read_4(sc->res[0], reg)
+#define cpsw_write_4(sc, reg, val) bus_write_4(sc->res[0], reg, val)
+
+#define cpsw_cpdma_bd_offset(i) (CPSW_CPPI_RAM_OFFSET + ((i)*16))
+
+#define cpsw_cpdma_bd_paddr(sc, slot) \
+ (slot->bd_offset + vtophys(rman_get_start(sc->res[0])))
+#define cpsw_cpdma_read_bd(sc, slot, val) \
+ bus_read_region_4(sc->res[0], slot->bd_offset, (uint32_t *) val, 4)
+#define cpsw_cpdma_write_bd(sc, slot, val) \
+ bus_write_region_4(sc->res[0], slot->bd_offset, (uint32_t *) val, 4)
+#define cpsw_cpdma_write_bd_next(sc, slot, next_slot) \
+ cpsw_write_4(sc, slot->bd_offset, cpsw_cpdma_bd_paddr(sc, next_slot))
+#define cpsw_cpdma_read_bd_flags(sc, slot) \
+ bus_read_2(sc->res[0], slot->bd_offset + 14)
+#define cpsw_write_hdp_slot(sc, queue, slot) \
+ cpsw_write_4(sc, (queue)->hdp_offset, cpsw_cpdma_bd_paddr(sc, slot))
+#define CP_OFFSET (CPSW_CPDMA_TX_CP(0) - CPSW_CPDMA_TX_HDP(0))
+#define cpsw_read_cp(sc, queue) \
+ cpsw_read_4(sc, (queue)->hdp_offset + CP_OFFSET)
+#define cpsw_write_cp(sc, queue, val) \
+ cpsw_write_4(sc, (queue)->hdp_offset + CP_OFFSET, (val))
+#define cpsw_write_cp_slot(sc, queue, slot) \
+ cpsw_write_cp(sc, queue, cpsw_cpdma_bd_paddr(sc, slot))
+
+#if 0
+/* XXX temporary function versions for debugging. */
static void
-cpsw_debugf_head(const char *funcname)
+cpsw_write_hdp_slotX(struct cpsw_softc *sc, struct cpsw_queue *queue, struct cpsw_slot *slot)
{
- int t = (int)(time_second % (24 * 60 * 60));
+ uint32_t reg = queue->hdp_offset;
+ uint32_t v = cpsw_cpdma_bd_paddr(sc, slot);
+ CPSW_DEBUGF(("HDP <=== 0x%08x (was 0x%08x)", v, cpsw_read_4(sc, reg)));
+ cpsw_write_4(sc, reg, v);
+}
- printf("%02d:%02d:%02d %s ", t / (60 * 60), (t / 60) % 60, t % 60, funcname);
+static void
+cpsw_write_cp_slotX(struct cpsw_softc *sc, struct cpsw_queue *queue, struct cpsw_slot *slot)
+{
+ uint32_t v = cpsw_cpdma_bd_paddr(sc, slot);
+ CPSW_DEBUGF(("CP <=== 0x%08x (expecting 0x%08x)", v, cpsw_read_cp(sc, queue)));
+ cpsw_write_cp(sc, queue, v);
}
+#endif
+/*
+ * Expanded dump routines for verbose debugging.
+ */
static void
-cpsw_debugf(const char *fmt, ...)
+cpsw_dump_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
{
- va_list ap;
+ static const char *flags[] = {"SOP", "EOP", "Owner", "EOQ",
+ "TDownCmplt", "PassCRC", "Long", "Short", "MacCtl", "Overrun",
+ "PktErr1", "PortEn/PktErr0", "RxVlanEncap", "Port2", "Port1",
+ "Port0"};
+ struct cpsw_cpdma_bd bd;
+ const char *sep;
+ int i;
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
+ cpsw_cpdma_read_bd(sc, slot, &bd);
+ printf("BD Addr: 0x%08x Next: 0x%08x\n", cpsw_cpdma_bd_paddr(sc, slot), bd.next);
+ printf(" BufPtr: 0x%08x BufLen: 0x%08x\n", bd.bufptr, bd.buflen);
+ printf(" BufOff: 0x%08x PktLen: 0x%08x\n", bd.bufoff, bd.pktlen);
+ printf(" Flags: ");
+ sep = "";
+ for (i = 0; i < 16; ++i) {
+ if (bd.flags & (1 << (15 - i))) {
+ printf("%s%s", sep, flags[i]);
+ sep = ",";
+ }
+ }
printf("\n");
+ if (slot->mbuf) {
+ printf(" Ether: %14D\n",
+ (char *)(slot->mbuf->m_hdr.mh_data), " ");
+ printf(" Packet: %16D\n",
+ (char *)(slot->mbuf->m_hdr.mh_data) + 14, " ");
+ }
+}
+#define CPSW_DUMP_SLOT(cs, slot) do { \
+ IF_DEBUG(sc) { \
+ cpsw_dump_slot(sc, slot); \
+ } \
+} while (0)
+
+
+static void
+cpsw_dump_queue(struct cpsw_softc *sc, struct cpsw_slots *q)
+{
+ struct cpsw_slot *slot;
+ int i = 0;
+ int others = 0;
+
+ STAILQ_FOREACH(slot, q, next) {
+ if (i > 4)
+ ++others;
+ else
+ cpsw_dump_slot(sc, slot);
+ ++i;
+ }
+ if (others)
+ printf(" ... and %d more.\n", others);
+ printf("\n");
}
-#define CPSW_DEBUGF(a) do { \
- if (sc->cpsw_if_flags & IFF_DEBUG) { \
- cpsw_debugf_head(__func__); \
- cpsw_debugf a; \
- } \
+#define CPSW_DUMP_QUEUE(sc, q) do { \
+ IF_DEBUG(sc) { \
+ cpsw_dump_queue(sc, q); \
+ } \
} while (0)
+
+/*
+ *
+ * Device Probe, Attach, Detach.
+ *
+ */
+
static int
cpsw_probe(device_t dev)
{
@@ -238,18 +451,107 @@ cpsw_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
+
+static void
+cpsw_init_slots(struct cpsw_softc *sc)
+{
+ struct cpsw_slot *slot;
+ int i;
+
+ STAILQ_INIT(&sc->avail);
+
+ /* Put the slot descriptors onto the global avail list. */
+ for (i = 0; i < sizeof(sc->_slots) / sizeof(sc->_slots[0]); i++) {
+ slot = &sc->_slots[i];
+ slot->bd_offset = cpsw_cpdma_bd_offset(i);
+ STAILQ_INSERT_TAIL(&sc->avail, slot, next);
+ }
+}
+
+/*
+ * bind an interrupt, add the relevant info to sc->interrupts
+ */
+static int
+cpsw_attach_interrupt(struct cpsw_softc *sc, struct resource *res, driver_intr_t *handler, const char *description)
+{
+ void **pcookie;
+ int error;
+
+ sc->interrupts[sc->interrupt_count].res = res;
+ sc->interrupts[sc->interrupt_count].description = description;
+ pcookie = &sc->interrupts[sc->interrupt_count].ih_cookie;
+
+ error = bus_setup_intr(sc->dev, res, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, *handler, sc, pcookie);
+ if (error)
+ device_printf(sc->dev,
+ "could not setup %s\n", description);
+ else
+ ++sc->interrupt_count;
+ return (error);
+}
+
+/*
+ * teardown everything in sc->interrupts.
+ */
+static void
+cpsw_detach_interrupts(struct cpsw_softc *sc)
+{
+ int error;
+ int i;
+
+ for (i = 0; i < sizeof(sc->interrupts) / sizeof(sc->interrupts[0]); ++i) {
+ if (!sc->interrupts[i].ih_cookie)
+ continue;
+ error = bus_teardown_intr(sc->dev,
+ sc->interrupts[i].res, sc->interrupts[i].ih_cookie);
+ if (error)
+ device_printf(sc->dev, "could not release %s\n",
+ sc->interrupts[i].description);
+ sc->interrupts[i].ih_cookie = NULL;
+ }
+}
+
+static int
+cpsw_add_slots(struct cpsw_softc *sc, struct cpsw_queue *queue, int requested)
+{
+ const int max_slots = sizeof(sc->_slots) / sizeof(sc->_slots[0]);
+ struct cpsw_slot *slot;
+ int i;
+
+ if (requested < 0)
+ requested = max_slots;
+
+ for (i = 0; i < requested; ++i) {
+ slot = STAILQ_FIRST(&sc->avail);
+ if (slot == NULL)
+ return (0);
+ if (bus_dmamap_create(sc->mbuf_dtag, 0, &slot->dmamap)) {
+ if_printf(sc->ifp, "failed to create dmamap\n");
+ return (ENOMEM);
+ }
+ STAILQ_REMOVE_HEAD(&sc->avail, next);
+ STAILQ_INSERT_TAIL(&queue->avail, slot, next);
+ ++queue->avail_queue_len;
+ ++queue->queue_slots;
+ }
+ return (0);
+}
+
static int
cpsw_attach(device_t dev)
{
+ bus_dma_segment_t segs[1];
struct cpsw_softc *sc = device_get_softc(dev);
struct mii_softc *miisc;
struct ifnet *ifp;
void *phy_sc;
- int i, error, phy;
+ int error, phy, nsegs;
uint32_t reg;
CPSW_DEBUGF((""));
+ getbinuptime(&sc->attach_uptime);
sc->dev = dev;
sc->node = ofw_bus_get_node(dev);
@@ -259,10 +561,10 @@ cpsw_attach(device_t dev)
return (ENXIO);
}
/* Initialize mutexes */
- mtx_init(&sc->tx_lock, device_get_nameunit(dev),
- "cpsw TX lock", MTX_DEF);
- mtx_init(&sc->rx_lock, device_get_nameunit(dev),
- "cpsw RX lock", MTX_DEF);
+ mtx_init(&sc->tx.lock, device_get_nameunit(dev),
+ "cpsw TX lock", MTX_DEF);
+ mtx_init(&sc->rx.lock, device_get_nameunit(dev),
+ "cpsw RX lock", MTX_DEF);
/* Allocate IO and IRQ resources */
error = bus_alloc_resources(dev, res_spec, sc->res);
@@ -272,11 +574,11 @@ cpsw_attach(device_t dev)
return (ENXIO);
}
- reg = cpsw_read_4(CPSW_SS_IDVER);
- device_printf(dev, "Version %d.%d (%d)\n", (reg >> 8 & 0x7),
+ reg = cpsw_read_4(sc, CPSW_SS_IDVER);
+ device_printf(dev, "CPSW SS Version %d.%d (%d)\n", (reg >> 8 & 0x7),
reg & 0xFF, (reg >> 11) & 0x1F);
- //cpsw_add_sysctls(sc); TODO
+ cpsw_add_sysctls(sc);
/* Allocate a busdma tag and DMA safe memory for mbufs. */
error = bus_dma_tag_create(
@@ -285,22 +587,14 @@ cpsw_attach(device_t dev)
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filtfunc, filtfuncarg */
- MCLBYTES, 1, /* maxsize, nsegments */
+ MCLBYTES, CPSW_TXFRAGS, /* maxsize, nsegments */
MCLBYTES, 0, /* maxsegsz, flags */
NULL, NULL, /* lockfunc, lockfuncarg */
&sc->mbuf_dtag); /* dmatag */
if (error) {
device_printf(dev, "bus_dma_tag_create failed\n");
cpsw_detach(dev);
- return (ENOMEM);
- }
-
- /* Initialize the tx_avail and rx_avail lists. */
- error = cpsw_init_slot_lists(sc);
- if (error) {
- device_printf(dev, "failed to allocate dmamaps\n");
- cpsw_detach(dev);
- return (ENOMEM);
+ return (error);
}
/* Allocate network interface */
@@ -311,6 +605,16 @@ cpsw_attach(device_t dev)
return (ENOMEM);
}
+ /* Allocate the null mbuf and pre-sync it. */
+ sc->null_mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ memset(sc->null_mbuf->m_hdr.mh_data, 0, sc->null_mbuf->m_ext.ext_size);
+ bus_dmamap_create(sc->mbuf_dtag, 0, &sc->null_mbuf_dmamap);
+ bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, sc->null_mbuf_dmamap,
+ sc->null_mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
+ bus_dmamap_sync(sc->mbuf_dtag, sc->null_mbuf_dmamap,
+ BUS_DMASYNC_PREWRITE);
+ sc->null_mbuf_paddr = segs[0].ds_addr;
+
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_softc = sc;
ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST;
@@ -321,11 +625,32 @@ cpsw_attach(device_t dev)
ifp->if_start = cpsw_start;
ifp->if_ioctl = cpsw_ioctl;
- ifp->if_snd.ifq_drv_maxlen = CPSW_MAX_TX_BUFFERS - 1;
+ cpsw_init_slots(sc);
+
+ /* Allocate slots to TX and RX queues. */
+ STAILQ_INIT(&sc->rx.avail);
+ STAILQ_INIT(&sc->rx.active);
+ STAILQ_INIT(&sc->tx.avail);
+ STAILQ_INIT(&sc->tx.active);
+ // For now: 128 slots to TX, rest to RX.
+ // XXX TODO: start with 32/64 and grow dynamically based on demand.
+ if (cpsw_add_slots(sc, &sc->tx, 128) || cpsw_add_slots(sc, &sc->rx, -1)) {
+ device_printf(dev, "failed to allocate dmamaps\n");
+ cpsw_detach(dev);
+ return (ENOMEM);
+ }
+ device_printf(dev, "Initial queue size TX=%d RX=%d\n",
+ sc->tx.queue_slots, sc->rx.queue_slots);
+
+ ifp->if_snd.ifq_drv_maxlen = sc->tx.queue_slots;
IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
IFQ_SET_READY(&ifp->if_snd);
+ sc->tx.hdp_offset = CPSW_CPDMA_TX_HDP(0);
+ sc->rx.hdp_offset = CPSW_CPDMA_RX_HDP(0);
+
/* Get high part of MAC address from control module (mac_id0_hi) */
+ /* TODO: Get MAC ID1 as well as MAC ID0. */
ti_scm_reg_read_4(0x634, &reg);
sc->mac_addr[0] = reg & 0xFF;
sc->mac_addr[1] = (reg >> 8) & 0xFF;
@@ -338,11 +663,14 @@ cpsw_attach(device_t dev)
sc->mac_addr[5] = (reg >> 8) & 0xFF;
ether_ifattach(ifp, sc->mac_addr);
- callout_init(&sc->wd_callout, 0);
+ callout_init(&sc->watchdog.callout, 0);
/* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
/* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
- cpsw_write_4(MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
+ cpsw_write_4(sc, MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
+
+ /* Clear ALE */
+ cpsw_write_4(sc, CPSW_ALE_CONTROL, 1 << 30);
/* Attach PHY(s) */
error = mii_attach(dev, &sc->miibus, ifp, cpsw_ifmedia_upd,
@@ -358,25 +686,38 @@ cpsw_attach(device_t dev)
miisc = LIST_FIRST(&sc->mii->mii_phys);
/* Select PHY and enable interrupts */
- cpsw_write_4(MDIOUSERPHYSEL0, 1 << 6 | (miisc->mii_phy & 0x1F));
-
- /* Attach interrupt handlers */
- for (i = 1; i <= CPSW_INTR_COUNT; ++i) {
- error = bus_setup_intr(dev, sc->res[i],
- INTR_TYPE_NET | INTR_MPSAFE,
- NULL, *cpsw_intrs[i - 1].handler,
- sc, &sc->ih_cookie[i - 1]);
- if (error) {
- device_printf(dev, "could not setup %s\n",
- cpsw_intrs[i].description);
- cpsw_detach(dev);
- return (error);
- }
+ cpsw_write_4(sc, MDIOUSERPHYSEL0, 1 << 6 | (miisc->mii_phy & 0x1F));
+
+ /* Note: We don't use sc->res[3] (TX interrupt) */
+ if (cpsw_attach_interrupt(sc, sc->res[1],
+ cpsw_intr_rx_thresh, "CPSW RX threshold interrupt") ||
+ cpsw_attach_interrupt(sc, sc->res[2],
+ cpsw_intr_rx, "CPSW RX interrupt") ||
+ cpsw_attach_interrupt(sc, sc->res[4],
+ cpsw_intr_misc, "CPSW misc interrupt")) {
+ cpsw_detach(dev);
+ return (ENXIO);
}
return (0);
}
+static void
+cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
+{
+ int error;
+
+ if (slot->dmamap) {
+ error = bus_dmamap_destroy(sc->mbuf_dtag, slot->dmamap);
+ KASSERT(error == 0, ("Mapping still active"));
+ slot->dmamap = NULL;
+ }
+ if (slot->mbuf) {
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+ }
+}
+
static int
cpsw_detach(device_t dev)
{
@@ -389,31 +730,20 @@ cpsw_detach(device_t dev)
if (device_is_attached(dev)) {
ether_ifdetach(sc->ifp);
CPSW_GLOBAL_LOCK(sc);
- cpsw_stop_locked(sc);
+ cpsw_shutdown_locked(sc);
CPSW_GLOBAL_UNLOCK(sc);
- callout_drain(&sc->wd_callout);
+ callout_drain(&sc->watchdog.callout);
}
bus_generic_detach(dev);
device_delete_child(dev, sc->miibus);
/* Stop and release all interrupts */
- for (i = 0; i < CPSW_INTR_COUNT; ++i) {
- if (!sc->ih_cookie[i])
- continue;
-
- error = bus_teardown_intr(dev, sc->res[1 + i], sc->ih_cookie[i]);
- if (error)
- device_printf(dev, "could not release %s\n",
- cpsw_intrs[i + 1].description);
- }
+ cpsw_detach_interrupts(sc);
/* Free dmamaps and mbufs */
- for (i = 0; i < CPSW_MAX_TX_BUFFERS; i++) {
- cpsw_free_slot(sc, &sc->_tx_slots[i]);
- }
- for (i = 0; i < CPSW_MAX_RX_BUFFERS; i++) {
- cpsw_free_slot(sc, &sc->_rx_slots[i]);
+ for (i = 0; i < sizeof(sc->_slots) / sizeof(sc->_slots[0]); ++i) {
+ cpsw_free_slot(sc, &sc->_slots[i]);
}
/* Free DMA tag */
@@ -424,409 +754,323 @@ cpsw_detach(device_t dev)
bus_release_resources(dev, res_spec, sc->res);
/* Destroy mutexes */
- mtx_destroy(&sc->rx_lock);
- mtx_destroy(&sc->tx_lock);
+ mtx_destroy(&sc->rx.lock);
+ mtx_destroy(&sc->tx.lock);
return (0);
}
-static int
-cpsw_suspend(device_t dev)
+/*
+ *
+ * Init/Shutdown.
+ *
+ */
+
+static void
+cpsw_reset(struct cpsw_softc *sc)
{
- struct cpsw_softc *sc = device_get_softc(dev);
+ int i;
- CPSW_DEBUGF((""));
- CPSW_GLOBAL_LOCK(sc);
- cpsw_stop_locked(sc);
- CPSW_GLOBAL_UNLOCK(sc);
- return (0);
-}
+ /* Reset RMII/RGMII wrapper. */
+ cpsw_write_4(sc, CPSW_WR_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_WR_SOFT_RESET) & 1)
+ ;
-static int
-cpsw_resume(device_t dev)
-{
- /* XXX TODO XXX */
- device_printf(dev, "%s\n", __FUNCTION__);
- return (0);
+ /* Disable TX and RX interrupts for all cores. */
+ for (i = 0; i < 3; ++i) {
+ cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_TX_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_RX_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_MISC_EN(i), 0x00);
+ }
+
+ /* Reset CPSW subsystem. */
+ cpsw_write_4(sc, CPSW_SS_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_SS_SOFT_RESET) & 1)
+ ;
+
+ /* Reset Sliver port 1 and 2 */
+ for (i = 0; i < 2; i++) {
+ /* Reset */
+ cpsw_write_4(sc, CPSW_SL_SOFT_RESET(i), 1);
+ while (cpsw_read_4(sc, CPSW_SL_SOFT_RESET(i)) & 1)
+ ;
+ }
+
+ /* Reset DMA controller. */
+ cpsw_write_4(sc, CPSW_CPDMA_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_CPDMA_SOFT_RESET) & 1)
+ ;
+
+ /* Disable TX & RX DMA */
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 0);
+
+ /* Clear all queues. */
+ for (i = 0; i < 8; i++) {
+ cpsw_write_4(sc, CPSW_CPDMA_TX_HDP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_HDP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CP(i), 0);
+ }
+
+ /* Clear all interrupt Masks */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
+ cpsw_write_4(sc, CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
}
-static int
-cpsw_shutdown(device_t dev)
+static void
+cpsw_init(void *arg)
{
- struct cpsw_softc *sc = device_get_softc(dev);
+ struct cpsw_softc *sc = arg;
CPSW_DEBUGF((""));
CPSW_GLOBAL_LOCK(sc);
- cpsw_stop_locked(sc);
+ cpsw_init_locked(arg);
CPSW_GLOBAL_UNLOCK(sc);
- return (0);
}
-static int
-cpsw_miibus_ready(struct cpsw_softc *sc)
+static void
+cpsw_init_locked(void *arg)
{
- uint32_t r, retries = CPSW_MIIBUS_RETRIES;
+ struct ifnet *ifp;
+ struct cpsw_softc *sc = arg;
+ struct cpsw_slot *slot;
+ uint32_t i;
- while (--retries) {
- r = cpsw_read_4(MDIOUSERACCESS0);
- if ((r & 1 << 31) == 0)
- return 1;
- DELAY(CPSW_MIIBUS_DELAY);
- }
- return 0;
-}
+ CPSW_DEBUGF((""));
+ ifp = sc->ifp;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
-static int
-cpsw_miibus_readreg(device_t dev, int phy, int reg)
-{
- struct cpsw_softc *sc = device_get_softc(dev);
- uint32_t cmd, r;
+ getbinuptime(&sc->init_uptime);
- if (!cpsw_miibus_ready(sc)) {
- device_printf(dev, "MDIO not ready to read\n");
- return 0;
- }
+ /* Reset the controller. */
+ cpsw_reset(sc);
- /* Set GO, reg, phy */
- cmd = 1 << 31 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16;
- cpsw_write_4(MDIOUSERACCESS0, cmd);
+ /* Enable ALE */
+ cpsw_write_4(sc, CPSW_ALE_CONTROL, 1 << 31 | 1 << 4);
- if (!cpsw_miibus_ready(sc)) {
- device_printf(dev, "MDIO timed out during read\n");
- return 0;
- }
-
- r = cpsw_read_4(MDIOUSERACCESS0);
- if((r & 1 << 29) == 0) {
- device_printf(dev, "Failed to read from PHY.\n");
- r = 0;
+ /* Init Sliver port 1 and 2 */
+ for (i = 0; i < 2; i++) {
+ /* Set Slave Mapping */
+ cpsw_write_4(sc, CPSW_SL_RX_PRI_MAP(i), 0x76543210);
+ cpsw_write_4(sc, CPSW_PORT_P_TX_PRI_MAP(i + 1), 0x33221100);
+ cpsw_write_4(sc, CPSW_SL_RX_MAXLEN(i), 0x5f2);
+ /* Set MACCONTROL for ports 0,1: IFCTL_B(16), IFCTL_A(15),
+ GMII_EN(5), FULLDUPLEX(1) */
+ /* TODO: Docs claim that IFCTL_B and IFCTL_A do the same thing? */
+ /* Huh? Docs call bit 0 "Loopback" some places, "FullDuplex" others. */
+ cpsw_write_4(sc, CPSW_SL_MACCONTROL(i), 1 << 15 | 1 << 5 | 1);
}
- return (r & 0xFFFF);
-}
-
-static int
-cpsw_miibus_writereg(device_t dev, int phy, int reg, int value)
-{
- struct cpsw_softc *sc = device_get_softc(dev);
- uint32_t cmd;
- if (!cpsw_miibus_ready(sc)) {
- device_printf(dev, "MDIO not ready to write\n");
- return 0;
- }
+ /* Set Host Port Mapping */
+ cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210);
+ cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0);
- /* Set GO, WRITE, reg, phy, and value */
- cmd = 3 << 30 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16
- | (value & 0xFFFF);
- cpsw_write_4(MDIOUSERACCESS0, cmd);
+ /* Initialize ALE: all ports set to forwarding(3), initialize addrs */
+ for (i = 0; i < 3; i++)
+ cpsw_write_4(sc, CPSW_ALE_PORTCTL(i), 3);
+ cpsw_ale_update_addresses(sc, 1);
- if (!cpsw_miibus_ready(sc)) {
- device_printf(dev, "MDIO timed out during write\n");
- return 0;
- }
+ cpsw_write_4(sc, CPSW_SS_PTYPE, 0);
- if((cpsw_read_4(MDIOUSERACCESS0) & (1 << 29)) == 0)
- device_printf(dev, "Failed to write to PHY.\n");
+ /* Enable statistics for ports 0, 1 and 2 */
+ cpsw_write_4(sc, CPSW_SS_STAT_PORT_EN, 7);
- return 0;
-}
+ /* Experiment: Turn off flow control */
+ /* This seems to fix the watchdog resets that have plagued
+ earlier versions of this driver; I'm not yet sure if there
+ are negative effects yet. */
+ cpsw_write_4(sc, CPSW_SS_FLOW_CONTROL, 0);
-static int
-cpsw_init_slot_lists(struct cpsw_softc *sc)
-{
- int i;
+ /* Make IP hdr aligned with 4 */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_BUFFER_OFFSET, 2);
- STAILQ_INIT(&sc->rx_active);
- STAILQ_INIT(&sc->rx_avail);
- STAILQ_INIT(&sc->tx_active);
- STAILQ_INIT(&sc->tx_avail);
-
- /* Put the slot descriptors onto the avail lists. */
- for (i = 0; i < CPSW_MAX_TX_BUFFERS; i++) {
- struct cpsw_slot *slot = &sc->_tx_slots[i];
- slot->index = i;
- /* XXX TODO: Remove this from here; allocate dmamaps lazily
- in the encap routine to reduce memory usage. */
- if (bus_dmamap_create(sc->mbuf_dtag, 0, &slot->dmamap)) {
- if_printf(sc->ifp, "failed to create dmamap for tx mbuf\n");
- return (ENOMEM);
- }
- STAILQ_INSERT_TAIL(&sc->tx_avail, slot, next);
- }
+ /* Initialize RX Buffer Descriptors */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_FREEBUFFER(0), 0);
- for (i = 0; i < CPSW_MAX_RX_BUFFERS; i++) {
- struct cpsw_slot *slot = &sc->_rx_slots[i];
- slot->index = i;
- if (bus_dmamap_create(sc->mbuf_dtag, 0, &slot->dmamap)) {
- if_printf(sc->ifp, "failed to create dmamap for rx mbuf\n");
- return (ENOMEM);
- }
- STAILQ_INSERT_TAIL(&sc->rx_avail, slot, next);
- }
+ /* Enable TX & RX DMA */
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 1);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 1);
- return (0);
-}
+ /* Enable Interrupts for core 0 */
+ cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(0), 0xFF);
+ cpsw_write_4(sc, CPSW_WR_C_RX_EN(0), 0xFF);
+ cpsw_write_4(sc, CPSW_WR_C_MISC_EN(0), 0x3F);
-static void
-cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
-{
- int error;
+ /* Enable host Error Interrupt */
+ cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_SET, 3);
- if (slot->dmamap) {
- error = bus_dmamap_destroy(sc->mbuf_dtag, slot->dmamap);
- KASSERT(error == 0, ("Mapping still active"));
- slot->dmamap = NULL;
- }
- if (slot->mbuf) {
- m_freem(slot->mbuf);
- slot->mbuf = NULL;
- }
-}
+ /* Enable interrupts for RX Channel 0 */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_SET, 1);
-/*
- * Pad the packet to the minimum length for Ethernet.
- * (CPSW hardware doesn't do this for us.)
- */
-static int
-cpsw_pad(struct mbuf *m)
-{
- int padlen = ETHER_MIN_LEN - m->m_pkthdr.len;
- struct mbuf *last, *n;
+ /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
+ /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
+ cpsw_write_4(sc, MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
- if (padlen <= 0)
- return (0);
+ /* Select MII in GMII_SEL, Internal Delay mode */
+ //ti_scm_reg_write_4(0x650, 0);
- /* If there's only the packet-header and we can pad there, use it. */
- if (m->m_pkthdr.len == m->m_len && M_WRITABLE(m) &&
- M_TRAILINGSPACE(m) >= padlen) {
- last = m;
- } else {
- /*
- * Walk packet chain to find last mbuf. We will either
- * pad there, or append a new mbuf and pad it.
- */
- for (last = m; last->m_next != NULL; last = last->m_next)
- ;
- if (!(M_WRITABLE(last) && M_TRAILINGSPACE(last) >= padlen)) {
- /* Allocate new empty mbuf, pad it. Compact later. */
- MGET(n, M_NOWAIT, MT_DATA);
- if (n == NULL)
- return (ENOBUFS);
- n->m_len = 0;
- last->m_next = n;
- last = n;
- }
- }
+ /* Initialize active queues. */
+ slot = STAILQ_FIRST(&sc->tx.active);
+ if (slot != NULL)
+ cpsw_write_hdp_slot(sc, &sc->tx, slot);
+ slot = STAILQ_FIRST(&sc->rx.active);
+ if (slot != NULL)
+ cpsw_write_hdp_slot(sc, &sc->rx, slot);
+ cpsw_rx_enqueue(sc);
- /* Now zero the pad area. */
- memset(mtod(last, caddr_t) + last->m_len, 0, padlen);
- last->m_len += padlen;
- m->m_pkthdr.len += padlen;
+ /* Activate network interface */
+ sc->rx.running = 1;
+ sc->tx.running = 1;
+ sc->watchdog.timer = 0;
+ callout_reset(&sc->watchdog.callout, hz, cpsw_tick, sc);
+ sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- return (0);
}
-static void
-cpsw_start(struct ifnet *ifp)
+static int
+cpsw_shutdown(device_t dev)
{
- struct cpsw_softc *sc = ifp->if_softc;
+ struct cpsw_softc *sc = device_get_softc(dev);
- CPSW_TX_LOCK(sc);
- cpsw_start_locked(ifp);
- CPSW_TX_UNLOCK(sc);
+ CPSW_DEBUGF((""));
+ CPSW_GLOBAL_LOCK(sc);
+ cpsw_shutdown_locked(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ return (0);
}
static void
-cpsw_start_locked(struct ifnet *ifp)
+cpsw_rx_teardown_locked(struct cpsw_softc *sc)
{
- bus_dma_segment_t seg[1];
- struct cpsw_cpdma_bd bd;
- struct cpsw_softc *sc = ifp->if_softc;
- struct cpsw_queue newslots = STAILQ_HEAD_INITIALIZER(newslots);
- struct cpsw_slot *slot, *prev_slot = NULL, *first_new_slot;
- struct mbuf *m0, *mtmp;
- int error, nsegs, enqueued = 0;
-
- CPSW_TX_LOCK_ASSERT(sc);
-
- if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
- IFF_DRV_RUNNING)
- return;
+ struct mbuf *received, *next;
+ int i = 0;
- /* Pull pending packets from IF queue and prep them for DMA. */
+ CPSW_DEBUGF(("starting RX teardown"));
+ cpsw_write_4(sc, CPSW_CPDMA_RX_TEARDOWN, 0);
for (;;) {
- slot = STAILQ_FIRST(&sc->tx_avail);
- if (slot == NULL) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
+ received = cpsw_rx_dequeue(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ while (received != NULL) {
+ next = received->m_nextpkt;
+ received->m_nextpkt = NULL;
+ (*sc->ifp->if_input)(sc->ifp, received);
+ received = next;
}
-
- IF_DEQUEUE(&ifp->if_snd, m0);
- if (m0 == NULL)
- break;
-
- if ((error = cpsw_pad(m0))) {
- if_printf(ifp,
- "%s: Dropping packet; could not pad\n", __func__);
- m_freem(m0);
- continue;
+ CPSW_GLOBAL_LOCK(sc);
+ if (!sc->rx.running) {
+ CPSW_DEBUGF(("finished RX teardown (%d retries)", i));
+ return;
}
-
- /* TODO: don't defragment here, queue each
- packet fragment as a separate entry. */
- mtmp = m_defrag(m0, M_NOWAIT);
- if (mtmp)
- m0 = mtmp;
-
- slot->mbuf = m0;
- /* Create mapping in DMA memory */
- error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, slot->dmamap,
- m0, seg, &nsegs, BUS_DMA_NOWAIT);
- KASSERT(nsegs == 1, ("More than one segment (nsegs=%d)", nsegs));
- KASSERT(error == 0, ("DMA error (error=%d)", error));
- if (error != 0 || nsegs != 1) {
- if_printf(ifp,
- "%s: Can't load packet for DMA (nsegs=%d, error=%d), dropping packet\n",
- __func__, nsegs, error);
- bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
- m_freem(m0);
- break;
+ if (++i > 10) {
+ if_printf(sc->ifp, "Unable to cleanly shutdown receiver\n");
+ return;
}
- bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap,
- BUS_DMASYNC_PREWRITE);
-
- if (prev_slot != NULL)
- cpsw_cpdma_write_txbd_next(prev_slot->index,
- cpsw_cpdma_txbd_paddr(slot->index));
- bd.next = 0;
- bd.bufptr = seg->ds_addr;
- bd.bufoff = 0;
- bd.buflen = seg->ds_len;
- bd.pktlen = seg->ds_len;
- bd.flags = 7 << 13; /* Set OWNERSHIP, SOP, EOP */
- cpsw_cpdma_write_txbd(slot->index, &bd);
- ++enqueued;
-
- prev_slot = slot;
- STAILQ_REMOVE_HEAD(&sc->tx_avail, next);
- STAILQ_INSERT_TAIL(&newslots, slot, next);
- BPF_MTAP(ifp, m0);
+ DELAY(10);
}
+}
- if (STAILQ_EMPTY(&newslots))
- return;
+static void
+cpsw_tx_teardown_locked(struct cpsw_softc *sc)
+{
+ int i = 0;
- /* Attach the list of new buffers to the hardware TX queue. */
- prev_slot = STAILQ_LAST(&sc->tx_active, cpsw_slot, next);
- first_new_slot = STAILQ_FIRST(&newslots);
- STAILQ_CONCAT(&sc->tx_active, &newslots);
- if (prev_slot == NULL) {
- /* Start the TX queue fresh. */
- cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
- cpsw_cpdma_txbd_paddr(first_new_slot->index));
- } else {
- /* Add buffers to end of current queue. */
- cpsw_cpdma_write_txbd_next(prev_slot->index,
- cpsw_cpdma_txbd_paddr(first_new_slot->index));
- /* If underrun, restart queue. */
- if (cpsw_cpdma_read_txbd_flags(prev_slot->index) & CPDMA_BD_EOQ)
- cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
- cpsw_cpdma_txbd_paddr(first_new_slot->index));
- }
- sc->tx_enqueues += enqueued;
- sc->tx_queued += enqueued;
- if (sc->tx_queued > sc->tx_max_queued) {
- sc->tx_max_queued = sc->tx_queued;
- CPSW_DEBUGF(("New TX high water mark %d", sc->tx_queued));
+ CPSW_DEBUGF(("starting TX teardown"));
+ cpsw_write_4(sc, CPSW_CPDMA_TX_TEARDOWN, 0);
+ cpsw_tx_dequeue(sc);
+ while (sc->tx.running && ++i < 10) {
+ DELAY(10);
+ cpsw_tx_dequeue(sc);
}
+ if (sc->tx.running)
+ if_printf(sc->ifp, "Unable to cleanly shutdown transmitter\n");
+ CPSW_DEBUGF(("finished TX teardown (%d retries, %d idle buffers)",
+ i, sc->tx.active_queue_len));
}
static void
-cpsw_stop_locked(struct cpsw_softc *sc)
+cpsw_shutdown_locked(struct cpsw_softc *sc)
{
struct ifnet *ifp;
- int i;
CPSW_DEBUGF((""));
-
CPSW_GLOBAL_LOCK_ASSERT(sc);
-
ifp = sc->ifp;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
/* Disable interface */
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-
- /* Stop tick engine */
- callout_stop(&sc->wd_callout);
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- /* Wait for hardware to clear pending ops. */
- CPSW_GLOBAL_UNLOCK(sc);
- CPSW_DEBUGF(("starting RX and TX teardown"));
- cpsw_write_4(CPSW_CPDMA_RX_TEARDOWN, 0);
- cpsw_write_4(CPSW_CPDMA_TX_TEARDOWN, 0);
- i = 0;
- cpsw_intr_rx(sc); // Try clearing without delay.
- cpsw_intr_tx(sc);
- while (sc->rx_running || sc->tx_running) {
- DELAY(10);
- cpsw_intr_rx(sc);
- cpsw_intr_tx(sc);
- ++i;
- }
- CPSW_DEBUGF(("finished RX and TX teardown (%d tries)", i));
- CPSW_GLOBAL_LOCK(sc);
+ /* Stop ticker */
+ callout_stop(&sc->watchdog.callout);
- /* All slots are now available */
- STAILQ_CONCAT(&sc->rx_avail, &sc->rx_active);
- STAILQ_CONCAT(&sc->tx_avail, &sc->tx_active);
- CPSW_DEBUGF(("%d buffers dropped at TX reset", sc->tx_queued));
- sc->tx_queued = 0;
+ /* Tear down the RX/TX queues. */
+ cpsw_rx_teardown_locked(sc);
+ cpsw_tx_teardown_locked(sc);
- /* Reset writer */
- cpsw_write_4(CPSW_WR_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_WR_SOFT_RESET) & 1)
- ;
+ /* Capture stats before we reset controller. */
+ cpsw_stats_collect(sc);
- /* Reset SS */
- cpsw_write_4(CPSW_SS_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_SS_SOFT_RESET) & 1)
- ;
+ cpsw_reset(sc);
+}
- /* Reset Sliver port 1 and 2 */
- for (i = 0; i < 2; i++) {
- /* Reset */
- cpsw_write_4(CPSW_SL_SOFT_RESET(i), 1);
- while (cpsw_read_4(CPSW_SL_SOFT_RESET(i)) & 1)
- ;
- }
+/*
+ * Suspend/Resume.
+ */
- /* Reset CPDMA */
- cpsw_write_4(CPSW_CPDMA_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_CPDMA_SOFT_RESET) & 1)
- ;
+static int
+cpsw_suspend(device_t dev)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
- /* Disable TX & RX DMA */
- cpsw_write_4(CPSW_CPDMA_TX_CONTROL, 0);
- cpsw_write_4(CPSW_CPDMA_RX_CONTROL, 0);
+ CPSW_DEBUGF((""));
+ CPSW_GLOBAL_LOCK(sc);
+ cpsw_shutdown_locked(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ return (0);
+}
- /* Disable TX and RX interrupts for all cores. */
- for (i = 0; i < 3; ++i) {
- cpsw_write_4(CPSW_WR_C_TX_EN(i), 0x00);
- cpsw_write_4(CPSW_WR_C_RX_EN(i), 0x00);
- cpsw_write_4(CPSW_WR_C_MISC_EN(i), 0x00);
- }
+static int
+cpsw_resume(device_t dev)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
- /* Clear all interrupt Masks */
- cpsw_write_4(CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
- cpsw_write_4(CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
+ CPSW_DEBUGF(("UNIMPLEMENTED"));
+ return (0);
}
+/*
+ *
+ * IOCTL
+ *
+ */
+
static void
cpsw_set_promisc(struct cpsw_softc *sc, int set)
{
+ /*
+ * Enabling promiscuous mode requires two bits of work: First,
+ * ALE_BYPASS needs to be enabled. That disables the ALE
+ * forwarding logic and causes every packet to be sent to the
+ * host port. That makes us promiscuous wrt received packets.
+ *
+ * With ALE forwarding disabled, the transmitter needs to set
+ * an explicit output port on every packet to route it to the
+ * correct egress. This should be doable for systems such as
+ * BeagleBone where only one egress port is actually wired to
+ * a PHY. If you have both egress ports wired up, life gets a
+ * lot more interesting.
+ *
+ * Hmmm.... NetBSD driver uses ALE_BYPASS always and doesn't
+ * seem to set explicit egress ports. Does that mean they
+ * are always promiscuous?
+ */
if (set) {
printf("Promiscuous mode unimplemented\n");
}
@@ -848,7 +1092,6 @@ cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
int error;
uint32_t changed;
- CPSW_DEBUGF(("command=0x%lx", command));
error = 0;
switch (command) {
@@ -865,118 +1108,175 @@ cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
cpsw_set_allmulti(sc,
ifp->if_flags & IFF_ALLMULTI);
} else {
- CPSW_DEBUGF(("SIOCSIFFLAGS: UP but not RUNNING"));
+ CPSW_DEBUGF(("SIOCSIFFLAGS: UP but not RUNNING; starting up"));
cpsw_init_locked(sc);
}
} else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- CPSW_DEBUGF(("SIOCSIFFLAGS: not UP but RUNNING"));
- cpsw_stop_locked(sc);
+ CPSW_DEBUGF(("SIOCSIFFLAGS: not UP but RUNNING; shutting down"));
+ cpsw_shutdown_locked(sc);
}
sc->cpsw_if_flags = ifp->if_flags;
CPSW_GLOBAL_UNLOCK(sc);
break;
case SIOCADDMULTI:
- CPSW_DEBUGF(("SIOCADDMULTI unimplemented"));
+ cpsw_ale_update_addresses(sc, 0);
break;
case SIOCDELMULTI:
- CPSW_DEBUGF(("SIOCDELMULTI unimplemented"));
+ /* Ugh. DELMULTI doesn't provide the specific address
+ being removed, so the best we can do is remove
+ everything and rebuild it all. */
+ cpsw_ale_update_addresses(sc, 1);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, command);
break;
default:
- CPSW_DEBUGF(("ether ioctl"));
error = ether_ioctl(ifp, command, data);
}
return (error);
}
-static void
-cpsw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+/*
+ *
+ * MIIBUS
+ *
+ */
+static int
+cpsw_miibus_ready(struct cpsw_softc *sc)
{
- struct cpsw_softc *sc = ifp->if_softc;
- struct mii_data *mii;
+ uint32_t r, retries = CPSW_MIIBUS_RETRIES;
- CPSW_DEBUGF((""));
- CPSW_TX_LOCK(sc);
+ while (--retries) {
+ r = cpsw_read_4(sc, MDIOUSERACCESS0);
+ if ((r & 1 << 31) == 0)
+ return 1;
+ DELAY(CPSW_MIIBUS_DELAY);
+ }
+ return 0;
+}
- mii = sc->mii;
- mii_pollstat(mii);
+static int
+cpsw_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct cpsw_softc *sc = device_get_softc(dev);
+ uint32_t cmd, r;
- ifmr->ifm_active = mii->mii_media_active;
- ifmr->ifm_status = mii->mii_media_status;
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO not ready to read\n");
+ return 0;
+ }
- CPSW_TX_UNLOCK(sc);
-}
+ /* Set GO, reg, phy */
+ cmd = 1 << 31 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16;
+ cpsw_write_4(sc, MDIOUSERACCESS0, cmd);
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO timed out during read\n");
+ return 0;
+ }
+
+ r = cpsw_read_4(sc, MDIOUSERACCESS0);
+ if((r & 1 << 29) == 0) {
+ device_printf(dev, "Failed to read from PHY.\n");
+ r = 0;
+ }
+ return (r & 0xFFFF);
+}
static int
-cpsw_ifmedia_upd(struct ifnet *ifp)
+cpsw_miibus_writereg(device_t dev, int phy, int reg, int value)
{
- struct cpsw_softc *sc = ifp->if_softc;
+ struct cpsw_softc *sc = device_get_softc(dev);
+ uint32_t cmd;
- CPSW_DEBUGF((""));
- if (ifp->if_flags & IFF_UP) {
- CPSW_GLOBAL_LOCK(sc);
- sc->cpsw_media_status = sc->mii->mii_media.ifm_media;
- mii_mediachg(sc->mii);
- cpsw_init_locked(sc);
- CPSW_GLOBAL_UNLOCK(sc);
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO not ready to write\n");
+ return 0;
}
- return (0);
-}
+ /* Set GO, WRITE, reg, phy, and value */
+ cmd = 3 << 30 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16
+ | (value & 0xFFFF);
+ cpsw_write_4(sc, MDIOUSERACCESS0, cmd);
-static void
-cpsw_intr_rx_thresh(void *arg)
-{
- struct cpsw_softc *sc = arg;
- CPSW_DEBUGF((""));
+ if (!cpsw_miibus_ready(sc)) {
+ device_printf(dev, "MDIO timed out during write\n");
+ return 0;
+ }
+
+ if((cpsw_read_4(sc, MDIOUSERACCESS0) & (1 << 29)) == 0)
+ device_printf(dev, "Failed to write to PHY.\n");
+
+ return 0;
}
+/*
+ *
+ * Transmit/Receive Packets.
+ *
+ */
+
+
static void
cpsw_intr_rx(void *arg)
{
struct cpsw_softc *sc = arg;
+ struct mbuf *received, *next;
CPSW_RX_LOCK(sc);
- cpsw_intr_rx_locked(arg);
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 1);
+ received = cpsw_rx_dequeue(sc);
+ cpsw_rx_enqueue(sc);
+ cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 1);
CPSW_RX_UNLOCK(sc);
+
+ while (received != NULL) {
+ next = received->m_nextpkt;
+ received->m_nextpkt = NULL;
+ (*sc->ifp->if_input)(sc->ifp, received);
+ received = next;
+ }
}
-static void
-cpsw_intr_rx_locked(void *arg)
+static struct mbuf *
+cpsw_rx_dequeue(struct cpsw_softc *sc)
{
- struct cpsw_softc *sc = arg;
struct cpsw_cpdma_bd bd;
- struct cpsw_slot *slot, *last_slot = NULL;
+ struct cpsw_slot *slot;
struct ifnet *ifp;
+ struct mbuf *mb_head, *mb_tail;
+ int removed = 0;
ifp = sc->ifp;
- if (!sc->rx_running)
- return;
+ mb_head = mb_tail = NULL;
/* Pull completed packets off hardware RX queue. */
- slot = STAILQ_FIRST(&sc->rx_active);
- while (slot != NULL) {
- cpsw_cpdma_read_rxbd(slot->index, &bd);
+ while ((slot = STAILQ_FIRST(&sc->rx.active)) != NULL) {
+ cpsw_cpdma_read_bd(sc, slot, &bd);
if (bd.flags & CPDMA_BD_OWNER)
break; /* Still in use by hardware */
+ CPSW_DEBUGF(("Removing received packet from RX queue"));
+ ++removed;
+ STAILQ_REMOVE_HEAD(&sc->rx.active, next);
+ STAILQ_INSERT_TAIL(&sc->rx.avail, slot, next);
+
+ bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+
if (bd.flags & CPDMA_BD_TDOWNCMPLT) {
CPSW_DEBUGF(("RX teardown in progress"));
- cpsw_write_4(CPSW_CPDMA_RX_CP(0), 0xfffffffc);
- sc->rx_running = 0;
- return;
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+ cpsw_write_cp(sc, &sc->rx, 0xfffffffc);
+ sc->rx.running = 0;
+ break;
}
- bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ cpsw_write_cp_slot(sc, &sc->rx, slot);
- /* Fill mbuf */
+ /* Set up mbuf */
/* TODO: track SOP/EOP bits to assemble a full mbuf
out of received fragments. */
slot->mbuf->m_hdr.mh_data += bd.bufoff;
@@ -984,6 +1284,7 @@ cpsw_intr_rx_locked(void *arg)
slot->mbuf->m_pkthdr.len = bd.pktlen - 4;
slot->mbuf->m_flags |= M_PKTHDR;
slot->mbuf->m_pkthdr.rcvif = ifp;
+ slot->mbuf->m_nextpkt = NULL;
if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
/* check for valid CRC by looking into pkt_err[5:4] */
@@ -994,64 +1295,60 @@ cpsw_intr_rx_locked(void *arg)
}
}
- /* Handover packet */
- CPSW_RX_UNLOCK(sc);
- (*ifp->if_input)(ifp, slot->mbuf);
+ /* Add mbuf to packet list to be returned. */
+ if (mb_tail) {
+ mb_tail->m_nextpkt = slot->mbuf;
+ } else {
+ mb_head = slot->mbuf;
+ }
+ mb_tail = slot->mbuf;
slot->mbuf = NULL;
- CPSW_RX_LOCK(sc);
-
- last_slot = slot;
- STAILQ_REMOVE_HEAD(&sc->rx_active, next);
- STAILQ_INSERT_TAIL(&sc->rx_avail, slot, next);
- slot = STAILQ_FIRST(&sc->rx_active);
}
- /* Tell hardware last slot we processed. */
- if (last_slot)
- cpsw_write_4(CPSW_CPDMA_RX_CP(0),
- cpsw_cpdma_rxbd_paddr(last_slot->index));
-
- /* Repopulate hardware RX queue. */
- cpsw_fill_rx_queue_locked(sc);
+ if (removed != 0) {
+ sc->rx.queue_removes += removed;
+ sc->rx.active_queue_len -= removed;
+ sc->rx.avail_queue_len += removed;
+ if (sc->rx.avail_queue_len > sc->rx.max_avail_queue_len)
+ sc->rx.max_avail_queue_len = sc->rx.avail_queue_len;
+ }
+ return (mb_head);
}
static void
-cpsw_fill_rx_queue_locked(struct cpsw_softc *sc)
+cpsw_rx_enqueue(struct cpsw_softc *sc)
{
bus_dma_segment_t seg[1];
- struct cpsw_queue tmpqueue = STAILQ_HEAD_INITIALIZER(tmpqueue);
struct cpsw_cpdma_bd bd;
- struct cpsw_slot *slot, *prev_slot, *next_slot;
- int error, nsegs;
+ struct ifnet *ifp = sc->ifp;
+ struct cpsw_slots tmpqueue = STAILQ_HEAD_INITIALIZER(tmpqueue);
+ struct cpsw_slot *slot, *prev_slot = NULL;
+ struct cpsw_slot *last_old_slot, *first_new_slot;
+ int error, nsegs, added = 0;
- /* Try to allocate new mbufs. */
- STAILQ_FOREACH(slot, &sc->rx_avail, next) {
- if (slot->mbuf != NULL)
- continue;
- slot->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ /* Register new mbufs with hardware. */
+ while ((slot = STAILQ_FIRST(&sc->rx.avail)) != NULL) {
if (slot->mbuf == NULL) {
- if_printf(sc->ifp, "Unable to fill RX queue\n");
- break;
+ slot->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (slot->mbuf == NULL) {
+ if_printf(sc->ifp, "Unable to fill RX queue\n");
+ break;
+ }
+ slot->mbuf->m_len =
+ slot->mbuf->m_pkthdr.len =
+ slot->mbuf->m_ext.ext_size;
}
- slot->mbuf->m_len = slot->mbuf->m_pkthdr.len = slot->mbuf->m_ext.ext_size;
- }
-
- /* Register new mbufs with hardware. */
- prev_slot = NULL;
- while (!STAILQ_EMPTY(&sc->rx_avail)) {
- slot = STAILQ_FIRST(&sc->rx_avail);
- if (slot->mbuf == NULL)
- break;
error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, slot->dmamap,
slot->mbuf, seg, &nsegs, BUS_DMA_NOWAIT);
KASSERT(nsegs == 1, ("More than one segment (nsegs=%d)", nsegs));
KASSERT(error == 0, ("DMA error (error=%d)", error));
- if (nsegs != 1 || error) {
- if_printf(sc->ifp,
+ if (error != 0 || nsegs != 1) {
+ if_printf(ifp,
"%s: Can't prep RX buf for DMA (nsegs=%d, error=%d)\n",
__func__, nsegs, error);
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
m_freem(slot->mbuf);
slot->mbuf = NULL;
break;
@@ -1062,410 +1359,563 @@ cpsw_fill_rx_queue_locked(struct cpsw_softc *sc)
/* Create and submit new rx descriptor*/
bd.next = 0;
bd.bufptr = seg->ds_addr;
- bd.buflen = MCLBYTES-1;
- bd.bufoff = 2; /* make IP hdr aligned with 4 */
- bd.pktlen = 0;
+ bd.bufoff = 0;
+ bd.buflen = MCLBYTES - 1;
+ bd.pktlen = bd.buflen;
bd.flags = CPDMA_BD_OWNER;
- cpsw_cpdma_write_rxbd(slot->index, &bd);
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ ++added;
- if (prev_slot) {
- cpsw_cpdma_write_rxbd_next(prev_slot->index,
- cpsw_cpdma_rxbd_paddr(slot->index));
- }
+ if (prev_slot != NULL)
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
prev_slot = slot;
- STAILQ_REMOVE_HEAD(&sc->rx_avail, next);
+ STAILQ_REMOVE_HEAD(&sc->rx.avail, next);
+ sc->rx.avail_queue_len--;
STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
}
+ if (added == 0)
+ return;
+
+ CPSW_DEBUGF(("Adding %d buffers to RX queue", added));
+
/* Link new entries to hardware RX queue. */
- prev_slot = STAILQ_LAST(&sc->rx_active, cpsw_slot, next);
- next_slot = STAILQ_FIRST(&tmpqueue);
- if (next_slot == NULL) {
+ last_old_slot = STAILQ_LAST(&sc->rx.active, cpsw_slot, next);
+ first_new_slot = STAILQ_FIRST(&tmpqueue);
+ STAILQ_CONCAT(&sc->rx.active, &tmpqueue);
+ if (first_new_slot == NULL) {
return;
- } else if (prev_slot == NULL) {
- /* Start a fresh RX queue. */
- cpsw_write_4(CPSW_CPDMA_RX_HDP(0),
- cpsw_cpdma_rxbd_paddr(next_slot->index));
+ } else if (last_old_slot == NULL) {
+ /* Start a fresh queue. */
+ cpsw_write_hdp_slot(sc, &sc->rx, first_new_slot);
} else {
/* Add buffers to end of current queue. */
- cpsw_cpdma_write_rxbd_next(prev_slot->index,
- cpsw_cpdma_rxbd_paddr(next_slot->index));
+ cpsw_cpdma_write_bd_next(sc, last_old_slot, first_new_slot);
/* If underrun, restart queue. */
- if (cpsw_cpdma_read_rxbd_flags(prev_slot->index) & CPDMA_BD_EOQ) {
- cpsw_write_4(CPSW_CPDMA_RX_HDP(0),
- cpsw_cpdma_rxbd_paddr(next_slot->index));
+ if (cpsw_cpdma_read_bd_flags(sc, last_old_slot) & CPDMA_BD_EOQ) {
+ cpsw_write_hdp_slot(sc, &sc->rx, first_new_slot);
}
}
- STAILQ_CONCAT(&sc->rx_active, &tmpqueue);
+ sc->rx.queue_adds += added;
+ sc->rx.active_queue_len += added;
+ if (sc->rx.active_queue_len > sc->rx.max_active_queue_len) {
+ sc->rx.max_active_queue_len = sc->rx.active_queue_len;
+ }
}
static void
-cpsw_intr_tx(void *arg)
+cpsw_start(struct ifnet *ifp)
{
- struct cpsw_softc *sc = arg;
+ struct cpsw_softc *sc = ifp->if_softc;
+
CPSW_TX_LOCK(sc);
- cpsw_intr_tx_locked(arg);
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 2);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && sc->tx.running) {
+ cpsw_tx_enqueue(sc);
+ cpsw_tx_dequeue(sc);
+ }
CPSW_TX_UNLOCK(sc);
}
static void
-cpsw_intr_tx_locked(void *arg)
+cpsw_tx_enqueue(struct cpsw_softc *sc)
{
- struct cpsw_softc *sc = arg;
- struct cpsw_slot *slot, *last_slot = NULL;
- uint32_t flags, last_flags = 0, retires = 0;
+ bus_dma_segment_t segs[CPSW_TXFRAGS];
+ struct cpsw_cpdma_bd bd;
+ struct cpsw_slots tmpqueue = STAILQ_HEAD_INITIALIZER(tmpqueue);
+ struct cpsw_slot *slot, *prev_slot = NULL;
+ struct cpsw_slot *last_old_slot, *first_new_slot;
+ struct mbuf *m0;
+ int error, nsegs, seg, added = 0, padlen;
+
+ /* Pull pending packets from IF queue and prep them for DMA. */
+ while ((slot = STAILQ_FIRST(&sc->tx.avail)) != NULL) {
+ IF_DEQUEUE(&sc->ifp->if_snd, m0);
+ if (m0 == NULL)
+ break;
+
+ slot->mbuf = m0;
+ padlen = ETHER_MIN_LEN - slot->mbuf->m_pkthdr.len;
+ if (padlen < 0)
+ padlen = 0;
+
+ /* Create mapping in DMA memory */
+ error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, slot->dmamap,
+ slot->mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
+ /* If the packet is too fragmented, try to simplify. */
+ if (error == EFBIG ||
+ (error == 0 &&
+ nsegs + (padlen > 0 ? 1 : 0) > sc->tx.avail_queue_len)) {
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ if (padlen > 0) /* May as well add padding. */
+ m_append(slot->mbuf, padlen,
+ sc->null_mbuf->m_hdr.mh_data);
+ m0 = m_defrag(slot->mbuf, M_NOWAIT);
+ if (m0 == NULL) {
+ if_printf(sc->ifp,
+ "Can't defragment packet; dropping\n");
+ m_freem(slot->mbuf);
+ } else {
+ CPSW_DEBUGF(("Requeueing defragmented packet"));
+ IF_PREPEND(&sc->ifp->if_snd, m0);
+ }
+ slot->mbuf = NULL;
+ continue;
+ }
+ if (error != 0) {
+ if_printf(sc->ifp,
+ "%s: Can't setup DMA (error=%d), dropping packet\n",
+ __func__, error);
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+ break;
+ }
+
+ bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap,
+ BUS_DMASYNC_PREWRITE);
+
+
+ CPSW_DEBUGF(("Queueing TX packet: %d segments + %d pad bytes",
+ nsegs, padlen));
+
+ /* If there is only one segment, the for() loop
+ * gets skipped and the single buffer gets set up
+ * as both SOP and EOP. */
+ /* Start by setting up the first buffer */
+ bd.next = 0;
+ bd.bufptr = segs[0].ds_addr;
+ bd.bufoff = 0;
+ bd.buflen = segs[0].ds_len;
+ bd.pktlen = m_length(slot->mbuf, NULL) + padlen;
+ bd.flags = CPDMA_BD_SOP | CPDMA_BD_OWNER;
+ for (seg = 1; seg < nsegs; ++seg) {
+ /* Save the previous buffer (which isn't EOP) */
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ if (prev_slot != NULL)
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ prev_slot = slot;
+ STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
+ sc->tx.avail_queue_len--;
+ STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
+ ++added;
+ slot = STAILQ_FIRST(&sc->tx.avail);
+
+ /* Setup next buffer (which isn't SOP) */
+ bd.next = 0;
+ bd.bufptr = segs[seg].ds_addr;
+ bd.bufoff = 0;
+ bd.buflen = segs[seg].ds_len;
+ bd.pktlen = 0;
+ bd.flags = CPDMA_BD_OWNER;
+ }
+ /* Save the final buffer. */
+ if (padlen <= 0)
+ bd.flags |= CPDMA_BD_EOP;
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ if (prev_slot != NULL)
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ prev_slot = slot;
+ STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
+ sc->tx.avail_queue_len--;
+ STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
+ ++added;
+
+ if (padlen > 0) {
+ slot = STAILQ_FIRST(&sc->tx.avail);
+ STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
+ sc->tx.avail_queue_len--;
+ STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
+ ++added;
+
+ /* Setup buffer of null pad bytes (definitely EOP) */
+ cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ prev_slot = slot;
+ bd.next = 0;
+ bd.bufptr = sc->null_mbuf_paddr;
+ bd.bufoff = 0;
+ bd.buflen = padlen;
+ bd.pktlen = 0;
+ bd.flags = CPDMA_BD_EOP | CPDMA_BD_OWNER;
+ cpsw_cpdma_write_bd(sc, slot, &bd);
+ ++nsegs;
+ }
- if (!sc->tx_running)
+ if (nsegs > sc->tx.longest_chain)
+ sc->tx.longest_chain = nsegs;
+
+ // TODO: Should we defer the BPF tap until
+ // after all packets are queued?
+ BPF_MTAP(sc->ifp, m0);
+ }
+
+ /* Attach the list of new buffers to the hardware TX queue. */
+ last_old_slot = STAILQ_LAST(&sc->tx.active, cpsw_slot, next);
+ first_new_slot = STAILQ_FIRST(&tmpqueue);
+ STAILQ_CONCAT(&sc->tx.active, &tmpqueue);
+ if (first_new_slot == NULL) {
return;
+ } else if (last_old_slot == NULL) {
+ /* Start a fresh queue. */
+ cpsw_write_hdp_slot(sc, &sc->tx, first_new_slot);
+ } else {
+ /* Add buffers to end of current queue. */
+ cpsw_cpdma_write_bd_next(sc, last_old_slot, first_new_slot);
+ /* If underrun, restart queue. */
+ if (cpsw_cpdma_read_bd_flags(sc, last_old_slot) & CPDMA_BD_EOQ) {
+ cpsw_write_hdp_slot(sc, &sc->tx, first_new_slot);
+ }
+ }
+ sc->tx.queue_adds += added;
+ sc->tx.active_queue_len += added;
+ if (sc->tx.active_queue_len > sc->tx.max_active_queue_len) {
+ sc->tx.max_active_queue_len = sc->tx.active_queue_len;
+ }
+}
+
+static int
+cpsw_tx_dequeue(struct cpsw_softc *sc)
+{
+ struct cpsw_slot *slot, *last_removed_slot = NULL;
+ uint32_t flags, removed = 0;
- slot = STAILQ_FIRST(&sc->tx_active);
- if (slot == NULL &&
- cpsw_read_4(CPSW_CPDMA_TX_CP(0)) == 0xfffffffc) {
+ slot = STAILQ_FIRST(&sc->tx.active);
+ if (slot == NULL && cpsw_read_cp(sc, &sc->tx) == 0xfffffffc) {
CPSW_DEBUGF(("TX teardown of an empty queue"));
- cpsw_write_4(CPSW_CPDMA_TX_CP(0), 0xfffffffc);
- sc->tx_running = 0;
- return;
+ cpsw_write_cp(sc, &sc->tx, 0xfffffffc);
+ sc->tx.running = 0;
+ return (0);
}
- /* Pull completed segments off the hardware TX queue. */
+ /* Pull completed buffers off the hardware TX queue. */
while (slot != NULL) {
- flags = cpsw_cpdma_read_txbd_flags(slot->index);
+ flags = cpsw_cpdma_read_bd_flags(sc, slot);
if (flags & CPDMA_BD_OWNER)
- break; /* Hardware is still using this. */
-
- if (flags & CPDMA_BD_TDOWNCMPLT) {
- CPSW_DEBUGF(("TX teardown in progress"));
- cpsw_write_4(CPSW_CPDMA_TX_CP(0), 0xfffffffc);
- sc->tx_running = 0;
- return;
- }
+ break; /* Hardware is still using this packet. */
- /* Release dmamap, free mbuf. */
- bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap,
- BUS_DMASYNC_POSTWRITE);
+ CPSW_DEBUGF(("TX removing completed packet"));
+ bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
m_freem(slot->mbuf);
slot->mbuf = NULL;
- STAILQ_REMOVE_HEAD(&sc->tx_active, next);
- STAILQ_INSERT_TAIL(&sc->tx_avail, slot, next);
- sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ /* Dequeue any additional buffers used by this packet. */
+ while (slot != NULL && slot->mbuf == NULL) {
+ STAILQ_REMOVE_HEAD(&sc->tx.active, next);
+ STAILQ_INSERT_TAIL(&sc->tx.avail, slot, next);
+ ++removed;
+ last_removed_slot = slot;
+ slot = STAILQ_FIRST(&sc->tx.active);
+ }
- last_slot = slot;
- last_flags = flags;
- ++retires;
- slot = STAILQ_FIRST(&sc->tx_active);
+ /* TearDown complete is only marked on the SOP for the packet. */
+ if (flags & CPDMA_BD_TDOWNCMPLT) {
+ CPSW_DEBUGF(("TX teardown in progress"));
+ cpsw_write_cp(sc, &sc->tx, 0xfffffffc);
+ // TODO: Increment a count of dropped TX packets
+ sc->tx.running = 0;
+ break;
+ }
}
- if (retires != 0) {
- /* Tell hardware the last item we dequeued. */
- cpsw_write_4(CPSW_CPDMA_TX_CP(0),
- cpsw_cpdma_txbd_paddr(last_slot->index));
- sc->tx_retires += retires;
- sc->tx_queued -= retires;
+ if (removed != 0) {
+ cpsw_write_cp_slot(sc, &sc->tx, last_removed_slot);
+ sc->tx.queue_removes += removed;
+ sc->tx.active_queue_len -= removed;
+ sc->tx.avail_queue_len += removed;
+ if (sc->tx.avail_queue_len > sc->tx.max_avail_queue_len)
+ sc->tx.max_avail_queue_len = sc->tx.avail_queue_len;
}
+ return (removed);
}
+/*
+ *
+ * Miscellaneous interrupts.
+ *
+ */
+
static void
-cpsw_intr_misc(void *arg)
+cpsw_intr_rx_thresh(void *arg)
{
struct cpsw_softc *sc = arg;
- uint32_t stat = cpsw_read_4(CPSW_WR_C_MISC_STAT(0));
+ uint32_t stat = cpsw_read_4(sc, CPSW_WR_C_RX_THRESH_STAT(0));
CPSW_DEBUGF(("stat=%x", stat));
- /* EOI_RX_PULSE */
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 3);
+ cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 0);
}
static void
-cpsw_tick(void *msc)
+cpsw_intr_misc_host_error(struct cpsw_softc *sc)
{
- struct cpsw_softc *sc = msc;
+ uint32_t intstat;
+ uint32_t dmastat;
+ int txerr, rxerr, txchan, rxchan;
+
+ printf("\n\n");
+ device_printf(sc->dev,
+ "HOST ERROR: PROGRAMMING ERROR DETECTED BY HARDWARE\n");
+ printf("\n\n");
+ intstat = cpsw_read_4(sc, CPSW_CPDMA_DMA_INTSTAT_MASKED);
+ device_printf(sc->dev, "CPSW_CPDMA_DMA_INTSTAT_MASKED=0x%x\n", intstat);
+ dmastat = cpsw_read_4(sc, CPSW_CPDMA_DMASTATUS);
+ device_printf(sc->dev, "CPSW_CPDMA_DMASTATUS=0x%x\n", dmastat);
+
+ txerr = (dmastat >> 20) & 15;
+ txchan = (dmastat >> 16) & 7;
+ rxerr = (dmastat >> 12) & 15;
+ rxchan = (dmastat >> 8) & 7;
+
+ switch (txerr) {
+ case 0: break;
+ case 1: printf("SOP error on TX channel %d\n", txchan);
+ break;
+ case 2: printf("Ownership bit not set on SOP buffer on TX channel %d\n", txchan);
+ break;
+ case 3: printf("Zero Next Buffer but not EOP on TX channel %d\n", txchan);
+ break;
+ case 4: printf("Zero Buffer Pointer on TX channel %d\n", txchan);
+ break;
+ case 5: printf("Zero Buffer Length on TX channel %d\n", txchan);
+ break;
+ case 6: printf("Packet length error on TX channel %d\n", txchan);
+ break;
+ default: printf("Unknown error on TX channel %d\n", txchan);
+ break;
+ }
- /* Check for TX timeout */
- cpsw_tx_watchdog(sc);
+ if (txerr != 0) {
+ printf("CPSW_CPDMA_TX%d_HDP=0x%x\n",
+ txchan, cpsw_read_4(sc, CPSW_CPDMA_TX_HDP(txchan)));
+ printf("CPSW_CPDMA_TX%d_CP=0x%x\n",
+ txchan, cpsw_read_4(sc, CPSW_CPDMA_TX_CP(txchan)));
+ cpsw_dump_queue(sc, &sc->tx.active);
+ }
- mii_tick(sc->mii);
+ switch (rxerr) {
+ case 0: break;
+ case 2: printf("Ownership bit not set on RX channel %d\n", rxchan);
+ break;
+ case 4: printf("Zero Buffer Pointer on RX channel %d\n", rxchan);
+ break;
+ case 5: printf("Zero Buffer Length on RX channel %d\n", rxchan);
+ break;
+ case 6: printf("Buffer offset too big on RX channel %d\n", rxchan);
+ break;
+ default: printf("Unknown RX error on RX channel %d\n", rxchan);
+ break;
+ }
- /* Check for media type change */
- if(sc->cpsw_media_status != sc->mii->mii_media.ifm_media) {
- printf("%s: media type changed (ifm_media=%x)\n", __func__,
- sc->mii->mii_media.ifm_media);
- cpsw_ifmedia_upd(sc->ifp);
+ if (rxerr != 0) {
+ printf("CPSW_CPDMA_RX%d_HDP=0x%x\n",
+ rxchan, cpsw_read_4(sc,CPSW_CPDMA_RX_HDP(rxchan)));
+ printf("CPSW_CPDMA_RX%d_CP=0x%x\n",
+ rxchan, cpsw_read_4(sc, CPSW_CPDMA_RX_CP(rxchan)));
+ cpsw_dump_queue(sc, &sc->rx.active);
}
- /* Schedule another timeout one second from now */
- callout_reset(&sc->wd_callout, hz, cpsw_tick, sc);
-}
+ printf("\nALE Table\n");
+ cpsw_ale_dump_table(sc);
-static void
-cpsw_tx_watchdog(struct cpsw_softc *sc)
-{
- struct ifnet *ifp = sc->ifp;
+ // XXX do something useful here??
+ panic("CPSW HOST ERROR INTERRUPT");
- CPSW_GLOBAL_LOCK(sc);
- if (sc->tx_retires > sc->tx_retires_at_last_tick) {
- sc->tx_wd_timer = 0; /* Stuff got sent. */
- } else if (sc->tx_queued == 0) {
- sc->tx_wd_timer = 0; /* Nothing to send. */
- } else {
- /* There was something to send but we didn't. */
- ++sc->tx_wd_timer;
- if (sc->tx_wd_timer > 3) {
- sc->tx_wd_timer = 0;
- ifp->if_oerrors++;
- if_printf(ifp, "watchdog timeout\n");
- cpsw_stop_locked(sc);
- cpsw_init_locked(sc);
- CPSW_DEBUGF(("watchdog reset completed\n"));
- }
- }
- sc->tx_retires_at_last_tick = sc->tx_retires;
- CPSW_GLOBAL_UNLOCK(sc);
+ // Suppress this interrupt in the future.
+ cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_CLEAR, intstat);
+ printf("XXX HOST ERROR INTERRUPT SUPPRESSED\n");
+ // The watchdog will probably reset the controller
+ // in a little while. It will probably fail again.
}
static void
-cpsw_init(void *arg)
+cpsw_intr_misc(void *arg)
{
struct cpsw_softc *sc = arg;
-
- CPSW_DEBUGF((""));
- CPSW_GLOBAL_LOCK(sc);
- cpsw_init_locked(arg);
- CPSW_GLOBAL_UNLOCK(sc);
+ uint32_t stat = cpsw_read_4(sc, CPSW_WR_C_MISC_STAT(0));
+
+ if (stat & 16)
+ CPSW_DEBUGF(("Time sync event interrupt unimplemented"));
+ if (stat & 8)
+ cpsw_stats_collect(sc);
+ if (stat & 4)
+ cpsw_intr_misc_host_error(sc);
+ if (stat & 2)
+ CPSW_DEBUGF(("MDIO link change interrupt unimplemented"));
+ if (stat & 1)
+ CPSW_DEBUGF(("MDIO operation completed interrupt unimplemented"));
+ cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 3);
}
-int once = 1;
+/*
+ *
+ * Periodic Checks and Watchdog.
+ *
+ */
static void
-cpsw_init_locked(void *arg)
+cpsw_tick(void *msc)
{
- struct ifnet *ifp;
- struct cpsw_softc *sc = arg;
- uint8_t broadcast_address[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- uint32_t i;
-
- CPSW_DEBUGF((""));
- ifp = sc->ifp;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
- return;
-
- /* Reset writer */
- cpsw_write_4(CPSW_WR_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_WR_SOFT_RESET) & 1)
- ;
-
- /* Reset SS */
- cpsw_write_4(CPSW_SS_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_SS_SOFT_RESET) & 1)
- ;
+ struct cpsw_softc *sc = msc;
- /* Clear table (30) and enable ALE(31) */
- if (once)
- cpsw_write_4(CPSW_ALE_CONTROL, 3 << 30);
- else
- cpsw_write_4(CPSW_ALE_CONTROL, 1 << 31);
- once = 0; // FIXME
+ /* Check for TX timeout */
+ cpsw_tx_watchdog(sc);
- /* Reset and init Sliver port 1 and 2 */
- for (i = 0; i < 2; i++) {
- /* Reset */
- cpsw_write_4(CPSW_SL_SOFT_RESET(i), 1);
- while (cpsw_read_4(CPSW_SL_SOFT_RESET(i)) & 1)
- ;
- /* Set Slave Mapping */
- cpsw_write_4(CPSW_SL_RX_PRI_MAP(i), 0x76543210);
- cpsw_write_4(CPSW_PORT_P_TX_PRI_MAP(i + 1), 0x33221100);
- cpsw_write_4(CPSW_SL_RX_MAXLEN(i), 0x5f2);
- /* Set MAC Address */
- cpsw_write_4(CPSW_PORT_P_SA_HI(i + 1),
- sc->mac_addr[3] << 24 |
- sc->mac_addr[2] << 16 |
- sc->mac_addr[1] << 8 |
- sc->mac_addr[0]);
- cpsw_write_4(CPSW_PORT_P_SA_LO(i+1),
- sc->mac_addr[5] << 8 |
- sc->mac_addr[4]);
-
- /* Set MACCONTROL for ports 0,1: FULLDUPLEX(1), GMII_EN(5),
- IFCTL_A(15), IFCTL_B(16) FIXME */
- cpsw_write_4(CPSW_SL_MACCONTROL(i), 1 << 15 | 1 << 5 | 1);
-
- /* Set ALE port to forwarding(3) */
- cpsw_write_4(CPSW_ALE_PORTCTL(i + 1), 3);
+ /* Check for media type change */
+ mii_tick(sc->mii);
+ if(sc->cpsw_media_status != sc->mii->mii_media.ifm_media) {
+ printf("%s: media type changed (ifm_media=%x)\n", __func__,
+ sc->mii->mii_media.ifm_media);
+ cpsw_ifmedia_upd(sc->ifp);
}
- /* Set Host Port Mapping */
- cpsw_write_4(CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210);
- cpsw_write_4(CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0);
-
- /* Set ALE port to forwarding(3)*/
- cpsw_write_4(CPSW_ALE_PORTCTL(0), 3);
-
- /* Add own MAC address and broadcast to ALE */
- cpsw_ale_uc_entry_set(sc, 0, sc->mac_addr);
- cpsw_ale_mc_entry_set(sc, 7, broadcast_address);
-
- cpsw_write_4(CPSW_SS_PTYPE, 0);
- /* Enable statistics for ports 0, 1 and 2 */
- cpsw_write_4(CPSW_SS_STAT_PORT_EN, 7);
-
- /* Reset CPDMA */
- cpsw_write_4(CPSW_CPDMA_SOFT_RESET, 1);
- while (cpsw_read_4(CPSW_CPDMA_SOFT_RESET) & 1)
- ;
-
- /* Make IP hdr aligned with 4 */
- cpsw_write_4(CPSW_CPDMA_RX_BUFFER_OFFSET, 2);
+ /* Schedule another timeout one second from now */
+ callout_reset(&sc->watchdog.callout, hz, cpsw_tick, sc);
+}
- for (i = 0; i < 8; i++) {
- cpsw_write_4(CPSW_CPDMA_TX_HDP(i), 0);
- cpsw_write_4(CPSW_CPDMA_RX_HDP(i), 0);
- cpsw_write_4(CPSW_CPDMA_TX_CP(i), 0);
- cpsw_write_4(CPSW_CPDMA_RX_CP(i), 0);
- }
+static void
+cpsw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct cpsw_softc *sc = ifp->if_softc;
+ struct mii_data *mii;
- /* Initialize RX Buffer Descriptors */
- cpsw_write_4(CPSW_CPDMA_RX_FREEBUFFER(0), 0);
- cpsw_fill_rx_queue_locked(sc);
+ CPSW_DEBUGF((""));
+ CPSW_TX_LOCK(sc);
- /* Clear all interrupt Masks */
- cpsw_write_4(CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
- cpsw_write_4(CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
+ mii = sc->mii;
+ mii_pollstat(mii);
- /* Enable TX & RX DMA */
- cpsw_write_4(CPSW_CPDMA_TX_CONTROL, 1);
- cpsw_write_4(CPSW_CPDMA_RX_CONTROL, 1);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
- /* Enable TX and RX interrupt receive for core 0 */
- cpsw_write_4(CPSW_WR_C_TX_EN(0), 0xFF);
- cpsw_write_4(CPSW_WR_C_RX_EN(0), 0xFF);
- //cpsw_write_4(CPSW_WR_C_MISC_EN(0), 0x3F);
+ CPSW_TX_UNLOCK(sc);
+}
- /* Enable host Error Interrupt */
- cpsw_write_4(CPSW_CPDMA_DMA_INTMASK_SET, 1);
+static int
+cpsw_ifmedia_upd(struct ifnet *ifp)
+{
+ struct cpsw_softc *sc = ifp->if_softc;
- /* Enable interrupts for TX and RX Channel 0 */
- cpsw_write_4(CPSW_CPDMA_TX_INTMASK_SET, 1);
- cpsw_write_4(CPSW_CPDMA_RX_INTMASK_SET, 1);
+ CPSW_DEBUGF((""));
+ if (ifp->if_flags & IFF_UP) {
+ CPSW_GLOBAL_LOCK(sc);
+ sc->cpsw_media_status = sc->mii->mii_media.ifm_media;
+ mii_mediachg(sc->mii);
+ cpsw_init_locked(sc);
+ CPSW_GLOBAL_UNLOCK(sc);
+ }
- /* Ack stalled irqs */
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 0);
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 1);
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 2);
- cpsw_write_4(CPSW_CPDMA_CPDMA_EOI_VECTOR, 3);
+ return (0);
+}
- /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
- /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
- cpsw_write_4(MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
+static void
+cpsw_tx_watchdog_full_reset(struct cpsw_softc *sc)
+{
+ cpsw_debugf_head("CPSW watchdog");
+ if_printf(sc->ifp, "watchdog timeout\n");
+ cpsw_shutdown_locked(sc);
+ cpsw_init_locked(sc);
+}
- /* Select MII in GMII_SEL, Internal Delay mode */
- //ti_scm_reg_write_4(0x650, 0);
+static void
+cpsw_tx_watchdog(struct cpsw_softc *sc)
+{
+ struct ifnet *ifp = sc->ifp;
- /* Activate network interface */
- sc->rx_running = 1;
- sc->tx_running = 1;
- sc->tx_wd_timer = 0;
- callout_reset(&sc->wd_callout, hz, cpsw_tick, sc);
- sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
- sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ CPSW_GLOBAL_LOCK(sc);
+ if (sc->tx.active_queue_len == 0 || (ifp->if_flags & IFF_UP) == 0 ||
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || !sc->tx.running) {
+ sc->watchdog.timer = 0; /* Nothing to do. */
+ } else if (sc->tx.queue_removes > sc->tx.queue_removes_at_last_tick) {
+ sc->watchdog.timer = 0; /* Stuff done while we weren't looking. */
+ } else if (cpsw_tx_dequeue(sc) > 0) {
+ sc->watchdog.timer = 0; /* We just did something. */
+ } else {
+ /* There was something to do but it didn't get done. */
+ ++sc->watchdog.timer;
+ if (sc->watchdog.timer > 2) {
+ sc->watchdog.timer = 0;
+ ++ifp->if_oerrors;
+ ++sc->watchdog.resets;
+ cpsw_tx_watchdog_full_reset(sc);
+ }
+ }
+ sc->tx.queue_removes_at_last_tick = sc->tx.queue_removes;
+ CPSW_GLOBAL_UNLOCK(sc);
}
+/*
+ *
+ * ALE support routines.
+ *
+ */
+
static void
cpsw_ale_read_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry)
{
- cpsw_write_4(CPSW_ALE_TBLCTL, idx & 1023);
- ale_entry[0] = cpsw_read_4(CPSW_ALE_TBLW0);
- ale_entry[1] = cpsw_read_4(CPSW_ALE_TBLW1);
- ale_entry[2] = cpsw_read_4(CPSW_ALE_TBLW2);
+ cpsw_write_4(sc, CPSW_ALE_TBLCTL, idx & 1023);
+ ale_entry[0] = cpsw_read_4(sc, CPSW_ALE_TBLW0);
+ ale_entry[1] = cpsw_read_4(sc, CPSW_ALE_TBLW1);
+ ale_entry[2] = cpsw_read_4(sc, CPSW_ALE_TBLW2);
}
static void
cpsw_ale_write_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry)
{
- cpsw_write_4(CPSW_ALE_TBLW0, ale_entry[0]);
- cpsw_write_4(CPSW_ALE_TBLW1, ale_entry[1]);
- cpsw_write_4(CPSW_ALE_TBLW2, ale_entry[2]);
- cpsw_write_4(CPSW_ALE_TBLCTL, 1 << 31 | (idx & 1023));
+ cpsw_write_4(sc, CPSW_ALE_TBLW0, ale_entry[0]);
+ cpsw_write_4(sc, CPSW_ALE_TBLW1, ale_entry[1]);
+ cpsw_write_4(sc, CPSW_ALE_TBLW2, ale_entry[2]);
+ cpsw_write_4(sc, CPSW_ALE_TBLCTL, 1 << 31 | (idx & 1023));
}
static int
-cpsw_ale_find_entry_by_mac(struct cpsw_softc *sc, uint8_t *mac)
+cpsw_ale_remove_all_mc_entries(struct cpsw_softc *sc)
{
int i;
uint32_t ale_entry[3];
- for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
+
+ /* First two entries are link address and broadcast. */
+ for (i = 2; i < CPSW_MAX_ALE_ENTRIES; i++) {
cpsw_ale_read_entry(sc, i, ale_entry);
- if ((((ale_entry[1] >> 8) & 0xFF) == mac[0]) &&
- (((ale_entry[1] >> 0) & 0xFF) == mac[1]) &&
- (((ale_entry[0] >>24) & 0xFF) == mac[2]) &&
- (((ale_entry[0] >>16) & 0xFF) == mac[3]) &&
- (((ale_entry[0] >> 8) & 0xFF) == mac[4]) &&
- (((ale_entry[0] >> 0) & 0xFF) == mac[5])) {
- return (i);
+ if (((ale_entry[1] >> 28) & 3) == 1 && /* Address entry */
+ ((ale_entry[1] >> 8) & 1) == 1) { /* MCast link addr */
+ ale_entry[0] = ale_entry[1] = ale_entry[2] = 0;
+ cpsw_ale_write_entry(sc, i, ale_entry);
}
}
return CPSW_MAX_ALE_ENTRIES;
}
static int
-cpsw_ale_find_free_entry(struct cpsw_softc *sc)
+cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac)
{
- int i;
+ int free_index = -1, matching_index = -1, i;
uint32_t ale_entry[3];
+
+ /* Find a matching entry or a free entry. */
for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
cpsw_ale_read_entry(sc, i, ale_entry);
+
/* Entry Type[61:60] is 0 for free entry */
- if (((ale_entry[1] >> 28) & 3) == 0) {
- return i;
+ if (free_index < 0 && ((ale_entry[1] >> 28) & 3) == 0) {
+ free_index = i;
}
- }
- return CPSW_MAX_ALE_ENTRIES;
-}
-
-
-static int
-cpsw_ale_uc_entry_set(struct cpsw_softc *sc, uint8_t port, uint8_t *mac)
-{
- int i;
- uint32_t ale_entry[3];
- if ((i = cpsw_ale_find_entry_by_mac(sc, mac)) == CPSW_MAX_ALE_ENTRIES) {
- i = cpsw_ale_find_free_entry(sc);
+ if ((((ale_entry[1] >> 8) & 0xFF) == mac[0]) &&
+ (((ale_entry[1] >> 0) & 0xFF) == mac[1]) &&
+ (((ale_entry[0] >>24) & 0xFF) == mac[2]) &&
+ (((ale_entry[0] >>16) & 0xFF) == mac[3]) &&
+ (((ale_entry[0] >> 8) & 0xFF) == mac[4]) &&
+ (((ale_entry[0] >> 0) & 0xFF) == mac[5])) {
+ matching_index = i;
+ break;
+ }
}
- if (i == CPSW_MAX_ALE_ENTRIES)
- return (ENOMEM);
-
- /* Set MAC address */
- ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
- ale_entry[1] = mac[0] << 8 | mac[1];
-
- /* Entry type[61:60] is addr entry(1) */
- ale_entry[1] |= 0x10 << 24;
-
- /* Set portmask [67:66] */
- ale_entry[2] = (port & 3) << 2;
-
- cpsw_ale_write_entry(sc, i, ale_entry);
-
- return 0;
-}
-
-static int
-cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac)
-{
- int i;
- uint32_t ale_entry[3];
-
- if ((i = cpsw_ale_find_entry_by_mac(sc, mac)) == CPSW_MAX_ALE_ENTRIES) {
- i = cpsw_ale_find_free_entry(sc);
+ if (matching_index < 0) {
+ if (free_index < 0)
+ return (ENOMEM);
+ i = free_index;
}
- if (i == CPSW_MAX_ALE_ENTRIES)
- return (ENOMEM);
-
/* Set MAC address */
ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
ale_entry[1] = mac[0] << 8 | mac[1];
@@ -1481,7 +1931,6 @@ cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac)
return 0;
}
-#ifdef CPSW_DEBUG
static void
cpsw_ale_dump_table(struct cpsw_softc *sc) {
int i;
@@ -1504,5 +1953,232 @@ cpsw_ale_dump_table(struct cpsw_softc *sc) {
printf("\n");
}
}
+ printf("\n");
+}
+
+static int
+cpsw_ale_update_addresses(struct cpsw_softc *sc, int purge)
+{
+ uint8_t *mac;
+ uint32_t ale_entry[3];
+ struct ifnet *ifp = sc->ifp;
+ struct ifmultiaddr *ifma;
+ int i;
+
+ /* Route incoming packets for our MAC address to Port 0 (host). */
+ /* For simplicity, keep this entry at table index 0 in the ALE. */
+ if_addr_rlock(ifp);
+ mac = LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr);
+ ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
+ ale_entry[1] = 0x10 << 24 | mac[0] << 8 | mac[1]; /* addr entry + mac */
+ ale_entry[2] = 0; /* port = 0 */
+ cpsw_ale_write_entry(sc, 0, ale_entry);
+
+ /* Set outgoing MAC Address for Ports 1 and 2. */
+ for (i = 1; i < 3; ++i) {
+ cpsw_write_4(sc, CPSW_PORT_P_SA_HI(i),
+ mac[3] << 24 | mac[2] << 16 | mac[1] << 8 | mac[0]);
+ cpsw_write_4(sc, CPSW_PORT_P_SA_LO(i),
+ mac[5] << 8 | mac[4]);
+ }
+ if_addr_runlock(ifp);
+
+ /* Keep the broadcast address at table entry 1. */
+ ale_entry[0] = 0xffffffff; /* Lower 32 bits of MAC */
+ ale_entry[1] = 0xd000ffff; /* FW (3 << 30), Addr entry (1 << 24), upper 16 bits of Mac */
+ ale_entry[2] = 0x0000001c; /* Forward to all ports */
+ cpsw_ale_write_entry(sc, 1, ale_entry);
+
+ /* SIOCDELMULTI doesn't specify the particular address
+ being removed, so we have to remove all and rebuild. */
+ if (purge)
+ cpsw_ale_remove_all_mc_entries(sc);
+
+ /* Set other multicast addrs desired. */
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ cpsw_ale_mc_entry_set(sc, 7,
+ LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ }
+ if_maddr_runlock(ifp);
+
+ return (0);
+}
+
+/*
+ *
+ * Statistics and Sysctls.
+ *
+ */
+
+#if 0
+static void
+cpsw_stats_dump(struct cpsw_softc *sc)
+{
+ int i;
+ uint32_t r;
+
+ for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
+ r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
+ cpsw_stat_sysctls[i].reg);
+ CPSW_DEBUGF(("%s: %ju + %u = %ju", cpsw_stat_sysctls[i].oid,
+ (intmax_t)sc->shadow_stats[i], r,
+ (intmax_t)sc->shadow_stats[i] + r));
+ }
}
#endif
+
+static void
+cpsw_stats_collect(struct cpsw_softc *sc)
+{
+ int i;
+ uint32_t r;
+
+ CPSW_DEBUGF(("Controller shadow statistics updated."));
+
+ for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
+ r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
+ cpsw_stat_sysctls[i].reg);
+ sc->shadow_stats[i] += r;
+ cpsw_write_4(sc, CPSW_STATS_OFFSET + cpsw_stat_sysctls[i].reg, r);
+ }
+}
+
+static int
+cpsw_stats_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct cpsw_softc *sc;
+ struct cpsw_stat *stat;
+ uint64_t result;
+
+ sc = (struct cpsw_softc *)arg1;
+ stat = &cpsw_stat_sysctls[oidp->oid_number];
+ result = sc->shadow_stats[oidp->oid_number];
+ result += cpsw_read_4(sc, CPSW_STATS_OFFSET + stat->reg);
+ return (sysctl_handle_64(oidp, &result, 0, req));
+}
+
+static int
+cpsw_stat_attached(SYSCTL_HANDLER_ARGS)
+{
+ struct cpsw_softc *sc;
+ struct bintime t;
+ unsigned result;
+
+ sc = (struct cpsw_softc *)arg1;
+ getbinuptime(&t);
+ bintime_sub(&t, &sc->attach_uptime);
+ result = t.sec;
+ return (sysctl_handle_int(oidp, &result, 0, req));
+}
+
+static int
+cpsw_stat_uptime(SYSCTL_HANDLER_ARGS)
+{
+ struct cpsw_softc *sc;
+ struct bintime t;
+ unsigned result;
+
+ sc = (struct cpsw_softc *)arg1;
+ if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ getbinuptime(&t);
+ bintime_sub(&t, &sc->init_uptime);
+ result = t.sec;
+ } else
+ result = 0;
+ return (sysctl_handle_int(oidp, &result, 0, req));
+}
+
+static void
+cpsw_add_queue_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node, struct cpsw_queue *queue)
+{
+ struct sysctl_oid_list *parent;
+
+ parent = SYSCTL_CHILDREN(node);
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "totalBuffers",
+ CTLFLAG_RD, &queue->queue_slots, 0,
+ "Total buffers currently assigned to this queue");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "activeBuffers",
+ CTLFLAG_RD, &queue->active_queue_len, 0,
+ "Buffers currently registered with hardware controller");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "maxActiveBuffers",
+ CTLFLAG_RD, &queue->max_active_queue_len, 0,
+ "Max value of activeBuffers since last driver reset");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "availBuffers",
+ CTLFLAG_RD, &queue->avail_queue_len, 0,
+ "Buffers allocated to this queue but not currently "
+ "registered with hardware controller");
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "maxAvailBuffers",
+ CTLFLAG_RD, &queue->max_avail_queue_len, 0,
+ "Max value of availBuffers since last driver reset");
+ SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "totalEnqueued",
+ CTLFLAG_RD, &queue->queue_adds, 0,
+ "Total buffers added to queue");
+ SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "totalDequeued",
+ CTLFLAG_RD, &queue->queue_removes, 0,
+ "Total buffers removed from queue");
+ SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "longestChain",
+ CTLFLAG_RD, &queue->longest_chain, 0,
+ "Max buffers used for a single packet");
+}
+
+static void
+cpsw_add_watchdog_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node, struct cpsw_softc *sc)
+{
+ struct sysctl_oid_list *parent;
+
+ parent = SYSCTL_CHILDREN(node);
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "resets",
+ CTLFLAG_RD, &sc->watchdog.resets, 0,
+ "Total number of watchdog resets");
+}
+
+static void
+cpsw_add_sysctls(struct cpsw_softc *sc)
+{
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *stats_node, *queue_node, *node;
+ struct sysctl_oid_list *parent, *stats_parent, *queue_parent;
+ int i;
+
+ ctx = device_get_sysctl_ctx(sc->dev);
+ parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
+
+ SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "attachedSecs",
+ CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_attached, "IU",
+ "Time since driver attach");
+
+ SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "uptime",
+ CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_uptime, "IU",
+ "Seconds since driver init");
+
+ stats_node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "stats",
+ CTLFLAG_RD, NULL, "CPSW Statistics");
+ stats_parent = SYSCTL_CHILDREN(stats_node);
+ for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
+ SYSCTL_ADD_PROC(ctx, stats_parent, i,
+ cpsw_stat_sysctls[i].oid,
+ CTLTYPE_U64 | CTLFLAG_RD, sc, 0,
+ cpsw_stats_sysctl, "IU",
+ cpsw_stat_sysctls[i].oid);
+ }
+
+ queue_node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "queue",
+ CTLFLAG_RD, NULL, "CPSW Queue Statistics");
+ queue_parent = SYSCTL_CHILDREN(queue_node);
+
+ node = SYSCTL_ADD_NODE(ctx, queue_parent, OID_AUTO, "tx",
+ CTLFLAG_RD, NULL, "TX Queue Statistics");
+ cpsw_add_queue_sysctls(ctx, node, &sc->tx);
+
+ node = SYSCTL_ADD_NODE(ctx, queue_parent, OID_AUTO, "rx",
+ CTLFLAG_RD, NULL, "RX Queue Statistics");
+ cpsw_add_queue_sysctls(ctx, node, &sc->rx);
+
+ node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "watchdog",
+ CTLFLAG_RD, NULL, "Watchdog Statistics");
+ cpsw_add_watchdog_sysctls(ctx, node, sc);
+}
+
diff --git a/sys/arm/ti/cpsw/if_cpswreg.h b/sys/arm/ti/cpsw/if_cpswreg.h
index dab4f36..46f8417 100644
--- a/sys/arm/ti/cpsw/if_cpswreg.h
+++ b/sys/arm/ti/cpsw/if_cpswreg.h
@@ -34,8 +34,11 @@
#define CPSW_SS_SOFT_RESET (CPSW_SS_OFFSET + 0x08)
#define CPSW_SS_STAT_PORT_EN (CPSW_SS_OFFSET + 0x0C)
#define CPSW_SS_PTYPE (CPSW_SS_OFFSET + 0x10)
+#define CPSW_SS_FLOW_CONTROL (CPSW_SS_OFFSET + 0x24)
#define CPSW_PORT_OFFSET 0x0100
+#define CPSW_PORT_P_MAX_BLKS(p) (CPSW_PORT_OFFSET + 0x08 + ((p) * 0x100))
+#define CPSW_PORT_P_BLK_CNT(p) (CPSW_PORT_OFFSET + 0x0C + ((p) * 0x100))
#define CPSW_PORT_P_TX_PRI_MAP(p) (CPSW_PORT_OFFSET + 0x118 + ((p-1) * 0x100))
#define CPSW_PORT_P0_CPDMA_TX_PRI_MAP (CPSW_PORT_OFFSET + 0x01C)
#define CPSW_PORT_P0_CPDMA_RX_CH_MAP (CPSW_PORT_OFFSET + 0x020)
@@ -84,10 +87,14 @@
#define CPSW_ALE_TBLW0 (CPSW_ALE_OFFSET + 0x3C)
#define CPSW_ALE_PORTCTL(p) (CPSW_ALE_OFFSET + 0x40 + ((p) * 0x04))
+/* SL1 is at 0x0D80, SL2 is at 0x0DC0 */
#define CPSW_SL_OFFSET 0x0D80
#define CPSW_SL_MACCONTROL(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x04)
+#define CPSW_SL_MACSTATUS(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x08)
#define CPSW_SL_SOFT_RESET(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x0C)
#define CPSW_SL_RX_MAXLEN(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x10)
+#define CPSW_SL_RX_PAUSE(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x18)
+#define CPSW_SL_TX_PAUSE(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x1C)
#define CPSW_SL_RX_PRI_MAP(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x24)
#define MDIO_OFFSET 0x1000
@@ -109,5 +116,22 @@
#define CPSW_WR_C_MISC_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x4C)
#define CPSW_CPPI_RAM_OFFSET 0x2000
+#define CPSW_CPPI_RAM_SIZE 0x2000
+
+#define CPDMA_BD_SOP (1<<15)
+#define CPDMA_BD_EOP (1<<14)
+#define CPDMA_BD_OWNER (1<<13)
+#define CPDMA_BD_EOQ (1<<12)
+#define CPDMA_BD_TDOWNCMPLT (1<<11)
+#define CPDMA_BD_PKT_ERR_MASK (3<< 4)
+
+struct cpsw_cpdma_bd {
+ volatile uint32_t next;
+ volatile uint32_t bufptr;
+ volatile uint16_t buflen;
+ volatile uint16_t bufoff;
+ volatile uint16_t pktlen;
+ volatile uint16_t flags;
+};
#endif /*_IF_CPSWREG_H */
diff --git a/sys/arm/ti/cpsw/if_cpswvar.h b/sys/arm/ti/cpsw/if_cpswvar.h
index 35024c6..2aebb0f 100644
--- a/sys/arm/ti/cpsw/if_cpswvar.h
+++ b/sys/arm/ti/cpsw/if_cpswvar.h
@@ -35,105 +35,90 @@
#define CPSW_MIIBUS_RETRIES 5
#define CPSW_MIIBUS_DELAY 1000
-#define CPSW_MAX_TX_BUFFERS 128
-#define CPSW_MAX_RX_BUFFERS 128
#define CPSW_MAX_ALE_ENTRIES 1024
+#define CPSW_SYSCTL_COUNT 34
+
struct cpsw_slot {
+ uint32_t bd_offset; /* Offset of corresponding BD within CPPI RAM. */
bus_dmamap_t dmamap;
struct mbuf *mbuf;
- int index;
STAILQ_ENTRY(cpsw_slot) next;
};
-STAILQ_HEAD(cpsw_queue, cpsw_slot);
+STAILQ_HEAD(cpsw_slots, cpsw_slot);
+
+struct cpsw_queue {
+ struct mtx lock;
+ int running;
+ struct cpsw_slots active;
+ struct cpsw_slots avail;
+ uint32_t queue_adds; /* total bufs added */
+ uint32_t queue_removes; /* total bufs removed */
+ uint32_t queue_removes_at_last_tick; /* Used by watchdog */
+ int queue_slots;
+ int active_queue_len;
+ int max_active_queue_len;
+ int avail_queue_len;
+ int max_avail_queue_len;
+ int longest_chain; /* Largest # segments in a single packet. */
+ int hdp_offset;
+};
struct cpsw_softc {
struct ifnet *ifp;
phandle_t node;
device_t dev;
+ struct bintime attach_uptime; /* system uptime when attach happened. */
+ struct bintime init_uptime; /* system uptime when init happened. */
+
+ /* TODO: We should set up a child structure for each port;
+ store mac, phy information, etc, in that structure. */
uint8_t mac_addr[ETHER_ADDR_LEN];
+
device_t miibus;
struct mii_data *mii;
- struct mtx tx_lock; /* transmitter lock */
- struct mtx rx_lock; /* receiver lock */
- struct resource *res[1 + CPSW_INTR_COUNT]; /* resources */
- void *ih_cookie[CPSW_INTR_COUNT]; /* interrupt handlers cookies */
+ /* We expect 1 memory resource and 4 interrupts from the device tree. */
+ struct resource *res[1 + CPSW_INTR_COUNT];
+
+ /* Interrupts get recorded here as we initialize them. */
+ /* Interrupt teardown just walks this list. */
+ struct {
+ struct resource *res;
+ void *ih_cookie;
+ const char *description;
+ } interrupts[CPSW_INTR_COUNT];
+ int interrupt_count;
uint32_t cpsw_if_flags;
int cpsw_media_status;
- struct callout wd_callout;
- int tx_wd_timer;
+ struct {
+ int resets;
+ int timer;
+ struct callout callout;
+ } watchdog;
bus_dma_tag_t mbuf_dtag;
- /* RX buffer tracking */
- int rx_running;
- struct cpsw_queue rx_active;
- struct cpsw_queue rx_avail;
- struct cpsw_slot _rx_slots[CPSW_MAX_RX_BUFFERS];
-
- /* TX buffer tracking. */
- int tx_running;
- struct cpsw_queue tx_active;
- struct cpsw_queue tx_avail;
- struct cpsw_slot _tx_slots[CPSW_MAX_TX_BUFFERS];
-
- /* Statistics */
- uint32_t tx_enqueues; /* total TX bufs added to queue */
- uint32_t tx_retires; /* total TX bufs removed from queue */
- uint32_t tx_retires_at_last_tick; /* used for watchdog */
- /* Note: tx_queued != tx_enqueues - tx_retires
- At driver reset, packets can be discarded
- from TX queue without being retired. */
- int tx_queued; /* Current bufs in TX queue */
- int tx_max_queued;
+ /* An mbuf full of nulls for TX padding. */
+ bus_dmamap_t null_mbuf_dmamap;
+ struct mbuf *null_mbuf;
+ bus_addr_t null_mbuf_paddr;
+
+ /* RX and TX buffer tracking */
+ struct cpsw_queue rx, tx;
+
+ /* 64-bit versions of 32-bit hardware statistics counters */
+ uint64_t shadow_stats[CPSW_SYSCTL_COUNT];
+
+ /* CPPI STATERAM has 512 slots for building TX/RX queues. */
+ /* TODO: Size here supposedly varies with different versions
+ of the controller. Check DaVinci specs and find a good
+ way to adjust this. One option is to have a separate
+ Device Tree parameter for number slots; another option
+ is to calculate it from the memory size in the device tree. */
+ struct cpsw_slot _slots[CPSW_CPPI_RAM_SIZE / sizeof(struct cpsw_cpdma_bd)];
+ struct cpsw_slots avail;
};
-#define CPDMA_BD_SOP (1<<15)
-#define CPDMA_BD_EOP (1<<14)
-#define CPDMA_BD_OWNER (1<<13)
-#define CPDMA_BD_EOQ (1<<12)
-#define CPDMA_BD_TDOWNCMPLT (1<<11)
-#define CPDMA_BD_PKT_ERR_MASK (3<< 4)
-
-struct cpsw_cpdma_bd {
- volatile uint32_t next;
- volatile uint32_t bufptr;
- volatile uint16_t buflen;
- volatile uint16_t bufoff;
- volatile uint16_t pktlen;
- volatile uint16_t flags;
-};
-
-/* Read/Write macros */
-#define cpsw_read_4(reg) bus_read_4(sc->res[0], reg)
-#define cpsw_write_4(reg, val) bus_write_4(sc->res[0], reg, val)
-
-#define cpsw_cpdma_txbd_offset(i) \
- (CPSW_CPPI_RAM_OFFSET + ((i)*16))
-#define cpsw_cpdma_txbd_paddr(i) (cpsw_cpdma_txbd_offset(i) + \
- vtophys(rman_get_start(sc->res[0])))
-#define cpsw_cpdma_read_txbd(i, val) \
- bus_read_region_4(sc->res[0], cpsw_cpdma_txbd_offset(i), (uint32_t *) val, 4)
-#define cpsw_cpdma_write_txbd(i, val) \
- bus_write_region_4(sc->res[0], cpsw_cpdma_txbd_offset(i), (uint32_t *) val, 4)
-#define cpsw_cpdma_write_txbd_next(i, val) \
- bus_write_4(sc->res[0], cpsw_cpdma_txbd_offset(i), val)
-#define cpsw_cpdma_read_txbd_flags(i) \
- bus_read_2(sc->res[0], cpsw_cpdma_txbd_offset(i)+14)
-
-#define cpsw_cpdma_rxbd_offset(i) \
- (CPSW_CPPI_RAM_OFFSET + ((CPSW_MAX_TX_BUFFERS + (i))*16))
-#define cpsw_cpdma_rxbd_paddr(i) (cpsw_cpdma_rxbd_offset(i) + \
- vtophys(rman_get_start(sc->res[0])))
-#define cpsw_cpdma_read_rxbd(i, val) \
- bus_read_region_4(sc->res[0], cpsw_cpdma_rxbd_offset(i), (uint32_t *) val, 4)
-#define cpsw_cpdma_write_rxbd(i, val) \
- bus_write_region_4(sc->res[0], cpsw_cpdma_rxbd_offset(i), (uint32_t *) val, 4)
-#define cpsw_cpdma_write_rxbd_next(i, val) \
- bus_write_4(sc->res[0], cpsw_cpdma_rxbd_offset(i), val)
-#define cpsw_cpdma_read_rxbd_flags(i) \
- bus_read_2(sc->res[0], cpsw_cpdma_rxbd_offset(i)+14)
-
#endif /*_IF_CPSWVAR_H */
diff --git a/sys/arm/ti/ti_scm.c b/sys/arm/ti/ti_scm.c
index ce31f6e..58849c2 100644
--- a/sys/arm/ti/ti_scm.c
+++ b/sys/arm/ti/ti_scm.c
@@ -155,8 +155,10 @@ ti_scm_padconf_set_internal(struct ti_scm_softc *sc,
}
/* couldn't find the mux mode */
- if (mode >= 8)
+ if (mode >= 8) {
+ printf("Invalid mode \"%s\"\n", muxmode);
return (EINVAL);
+ }
/* set the mux mode */
reg_val |= (uint16_t)(mode & ti_scm_dev.padconf_muxmode_mask);
@@ -391,13 +393,16 @@ ti_scm_padconf_init_from_fdt(struct ti_scm_softc *sc)
while (padstates->state != NULL) {
if (strcmp(padstates->state, padstate) == 0) {
err = ti_scm_padconf_set_internal(sc,
- padconf, muxname, padstates->reg);
+ padconf, muxname, padstates->reg);
}
padstates++;
}
if (err)
- device_printf(sc->sc_dev, "err: failed to configure"
- "pin \"%s\"\n", padconf->ballname);
+ device_printf(sc->sc_dev,
+ "err: failed to configure "
+ "pin \"%s\" as \"%s\"\n",
+ padconf->ballname,
+ muxname);
}
padconf++;
}
diff --git a/sys/boot/arm/uboot/Makefile b/sys/boot/arm/uboot/Makefile
index 1974218..c3c4bd8 100644
--- a/sys/boot/arm/uboot/Makefile
+++ b/sys/boot/arm/uboot/Makefile
@@ -112,8 +112,8 @@ CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
# clang doesn't understand %D as a specifier to printf
NO_WERROR.clang=
-DPADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBSTAND}
-LDADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} -lstand
+DPADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBSTAND} ${LIBGCC}
+LDADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} -lstand -lgcc
vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
diff --git a/sys/boot/fdt/dts/beaglebone.dts b/sys/boot/fdt/dts/beaglebone.dts
index 2c68021..3e2dc80 100644
--- a/sys/boot/fdt/dts/beaglebone.dts
+++ b/sys/boot/fdt/dts/beaglebone.dts
@@ -91,7 +91,58 @@
"MMC0_DAT0", "mmc0_dat0", "input_pullup",
"MMC0_DAT1", "mmc0_dat1", "input_pullup",
"MMC0_DAT2", "mmc0_dat2", "input_pullup",
- "MMC0_DAT3", "mmc0_dat3", "input_pullup";
+ "MMC0_DAT3", "mmc0_dat3", "input_pullup",
+ /* GPIO */
+ "ECAP0_IN_PWM0_OUT", "gpio0_7", "input_pulldown",
+ "GPMC_AD10", "gpio0_26", "input_pulldown",
+ "GPMC_AD11", "gpio0_27", "input_pulldown",
+ "GPMC_AD0", "gpio1_0", "input_pulldown",
+ "GPMC_AD1", "gpio1_1", "input_pulldown",
+ "GPMC_AD2", "gpio1_2", "input_pulldown",
+ "GPMC_AD3", "gpio1_3", "input_pulldown",
+ "GPMC_AD4", "gpio1_4", "input_pulldown",
+ "GPMC_AD5", "gpio1_5", "input_pulldown",
+ "GPMC_AD6", "gpio1_6", "input_pulldown",
+ "GPMC_AD7", "gpio1_7", "input_pulldown",
+ "GPMC_AD12", "gpio1_12", "input_pulldown",
+ "GPMC_AD13", "gpio1_13", "input_pulldown",
+ "GPMC_AD14", "gpio1_14", "input_pulldown",
+ "GPMC_AD15", "gpio1_15", "input_pulldown",
+ "GPMC_A0", "gpio1_16", "input_pulldown",
+ "GPMC_A1", "gpio1_17", "input_pulldown",
+ "GPMC_A5", "gpio1_21", "output", /* User LED 1 */
+ "GPMC_A6", "gpio1_22", "output", /* User LED 2 */
+ "GPMC_A7", "gpio1_23", "output", /* User LED 3 */
+ "GPMC_A8", "gpio1_24", "output", /* User LED 4 */
+ "GPMC_BEn1", "gpio1_28", "input_pulldown",
+ "GPMC_CSn0", "gpio1_29", "input_pulldown",
+ "GPMC_CSn1", "gpio1_30", "input_pulldown",
+ "GPMC_CSn2", "gpio1_31", "input_pulldown",
+ "GPMC_CLK", "gpio2_1", "input_pulldown",
+ "LCD_DATA0", "gpio2_6", "input_pulldown",
+ "LCD_DATA1", "gpio2_7", "input_pulldown",
+ "LCD_DATA2", "gpio2_8", "input_pulldown",
+ "LCD_DATA3", "gpio2_9", "input_pulldown",
+ "LCD_DATA4", "gpio2_10", "input_pulldown",
+ "LCD_DATA5", "gpio2_11", "input_pulldown",
+ "LCD_DATA6", "gpio2_12", "input_pulldown",
+ "LCD_DATA7", "gpio2_13", "input_pulldown",
+ "LCD_VSYNC", "gpio2_22", "input_pulldown",
+ "LCD_HSYNC", "gpio2_23", "input_pulldown",
+ "LCD_PCLK", "gpio2_24", "input_pulldown",
+ "LCD_AC_BIAS_EN", "gpio2_25", "input_pulldown",
+ "MCASP0_FSR", "gpio3_19", "input_pulldown",
+ "MCASP0_AHCLKX", "gpio3_21", "input_pulldown",
+ /* TIMERs */
+ "GPMC_ADVn_ALE", "timer4", "output",
+ "GPMC_BEn0_CLE", "timer5", "output",
+ "GPMC_WEn", "timer6", "output",
+ "GPMC_OEn_REn", "timer7", "output",
+ /* PWM */
+ "GPMC_A2", "ehrpwm1A", "output",
+ "GPMC_A3", "ehrpwm1B", "output",
+ "GPMC_AD8", "ehrpwm2A", "output",
+ "GPMC_AD9", "ehrpwm2B", "output";
};
prcm@44E00000 {
@@ -125,7 +176,7 @@
0x4804C000 0x1000
0x481AC000 0x1000
0x481AE000 0x1000 >;
- interrupts = < 17 19 21 23 >;
+ interrupts = < 96 97 98 99 32 33 62 63 >;
interrupt-parent = <&AINTC>;
};
@@ -161,7 +212,7 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "ti,cpsw";
- reg = <0x4A100000 0x3000>;
+ reg = <0x4A100000 0x4000>;
interrupts = <40 41 42 43>;
interrupt-parent = <&AINTC>;
phy-handle = <&phy0>;
diff --git a/sys/boot/fdt/dts/cubieboard.dts b/sys/boot/fdt/dts/cubieboard.dts
new file mode 100644
index 0000000..c4dd2a8
--- /dev/null
+++ b/sys/boot/fdt/dts/cubieboard.dts
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2012 Ganbold Tsagaankhuu <ganbold@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/dts-v1/;
+
+/ {
+ model = "Cubietech Cubieboard";
+ compatible = "cubietech,a10-cubieboard", "allwinner,sun4i-a10";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-parent = <&AINTC>;
+
+ memory {
+ device_type = "memory";
+ reg = < 0x40000000 0x20000000 >; /* 512MB RAM */
+ };
+
+ aliases {
+ soc = &SOC;
+ UART0 = &UART0;
+ };
+
+ SOC: a10 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+ bus-frequency = <0>;
+
+ AINTC: interrupt-controller@01c20400 {
+ compatible = "allwinner,sun4i-ic";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = < 0x01c20400 0x400 >;
+ };
+
+ ccm@01c20000 {
+ compatible = "allwinner,sun4i-ccm";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = < 0x01c20000 0x400 >;
+ };
+
+ timer@01c20c00 {
+ compatible = "allwinner,sun4i-timer";
+ reg = <0x01c20c00 0x90>;
+ interrupts = < 22 >;
+ interrupt-parent = <&AINTC>;
+ clock-frequency = < 24000000 >;
+ };
+
+ usb1: usb@01c1c000 {
+ compatible = "allwinner,usb-ehci", "usb-ehci";
+ reg = <0x01c1c000 0x1000>;
+ interrupts = < 40 >;
+ interrupt-parent = <&AINTC>;
+ };
+
+ sata@01c18000 {
+ compatible = "allwinner,ahci";
+ reg = <0x01c18000 0x1000>;
+ interrupts = <56>;
+ interrupt-parent = <&AINTC>;
+ };
+
+ UART0: serial@01c28000 {
+ status = "okay";
+ compatible = "ns16550";
+ reg = <0x01c28000 0x400>;
+ reg-shift = <2>;
+ interrupts = <1>;
+ interrupt-parent = <&AINTC>;
+ current-speed = <115200>;
+ clock-frequency = < 24000000 >;
+ };
+ };
+
+ chosen {
+ bootargs = "-v";
+ stdin = "UART0";
+ stdout = "UART0";
+ };
+};
+
diff --git a/sys/boot/fdt/dts/dreamplug-1001.dts b/sys/boot/fdt/dts/dreamplug-1001.dts
new file mode 100644
index 0000000..92ca1b0
--- /dev/null
+++ b/sys/boot/fdt/dts/dreamplug-1001.dts
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2013 Ian Lepore
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software substantially based on work developed by Semihalf
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * GlobalScale Technologies DreamPlug Device Tree Source.
+ *
+ * This source is for version 10 revision 01 units with NOR SPI flash.
+ * These units are marked "1001" on the serial number label.
+ *
+ * $FreeBSD$
+ */
+
+/dts-v1/;
+
+/ {
+ model = "GlobalScale Technologies Dreamplug v1001";
+ compatible = "globalscale,dreamplug-003-ds2001", "globalscale,dreamplug", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ mpp = &MPP;
+ serial0 = &serial0;
+ serial1 = &serial1;
+ soc = &SOC;
+ sram = &SRAM;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "ARM,88FR131";
+ reg = <0x0>;
+ d-cache-line-size = <32>; // 32 bytes
+ i-cache-line-size = <32>; // 32 bytes
+ d-cache-size = <0x4000>; // L1, 16K
+ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+ };
+
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x20000000>; // 512M at 0x0
+ };
+
+ localbus@0 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "mrvl,lbc";
+ bank-count = <1>;
+
+ /* This reflects CPU decode windows setup. */
+ ranges = <0x0 0x1e 0xfa000000 0x00100000>;
+
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x00100000>;
+ bank-width = <2>;
+ device-width = <1>;
+ };
+ };
+
+ SOC: soc88f6281@f1000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0xf1000000 0x00100000>;
+ bus-frequency = <0>;
+
+ PIC: pic@20200 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = <0x20200 0x3c>;
+ compatible = "mrvl,pic";
+ };
+
+ timer@20300 {
+ compatible = "mrvl,timer";
+ reg = <0x20300 0x30>;
+ interrupts = <1>;
+ interrupt-parent = <&PIC>;
+ mrvl,has-wdt;
+ };
+
+ MPP: mpp@10000 {
+ #pin-cells = <2>;
+ compatible = "mrvl,mpp";
+ reg = <0x10000 0x34>;
+ pin-count = <50>;
+ pin-map = <
+ 0 2 /* MPP[ 0]: SPI_SCn */
+ 1 2 /* MPP[ 1]: SPI_MOSI */
+ 2 2 /* MPP[ 2]: SPI_SCK */
+ 3 2 /* MPP[ 3]: SPI_MISO */
+ 4 1 /* MPP[ 4]: NF_IO[6] */
+ 5 1 /* MPP[ 5]: NF_IO[7] */
+ 6 1 /* MPP[ 6]: SYSRST_OUTn */
+ 7 0 /* MPP[ 7]: GPO[7] */
+ 8 1 /* MPP[ 8]: TW_SDA */
+ 9 1 /* MPP[ 9]: TW_SCK */
+ 10 3 /* MPP[10]: UA0_TXD */
+ 11 3 /* MPP[11]: US0_RXD */
+ 12 1 /* MPP[12]: SD_CLK */
+ 13 1 /* MPP[13]: SD_CMD */
+ 14 1 /* MPP[14]: SD_D[0] */
+ 15 1 /* MPP[15]: SD_D[1] */
+ 16 1 /* MPP[16]: SD_D[2] */
+ 17 1 /* MPP[17]: SD_D[3] */
+ 18 1 /* MPP[18]: NF_IO[0] */
+ 19 1 /* MPP[19]: NF_IO[1] */
+ 20 3 /* MPP[20]: GE1[ 0] */
+ 21 3 /* MPP[21]: GE1[ 1] */
+ 22 3 /* MPP[22]: GE1[ 2] */
+ 23 3 /* MPP[23]: GE1[ 3] */
+ 24 3 /* MPP[24]: GE1[ 4] */
+ 25 3 /* MPP[25]: GE1[ 5] */
+ 26 3 /* MPP[26]: GE1[ 6] */
+ 27 3 /* MPP[27]: GE1[ 7] */
+ 28 3 /* MPP[28]: GE1[ 8] */
+ 29 3 /* MPP[29]: GE1[ 9] */
+ 30 3 /* MPP[30]: GE1[10] */
+ 31 3 /* MPP[31]: GE1[11] */
+ 32 3 /* MPP[32]: GE1[12] */
+ 33 3 /* MPP[33]: GE1[13] */
+ 34 3 /* MPP[34]: GE1[14] */
+ 35 3 /* MPP[35]: GE1[15] */
+ 36 0 /* MPP[36]: GPIO[36] */
+ 37 0 /* MPP[37]: GPIO[37] */
+ 38 0 /* MPP[38]: GPIO[38] */
+ 39 0 /* MPP[39]: GPIO[39] */
+ 40 2 /* MPP[40]: TDM_SPI_SCK */
+ 41 2 /* MPP[41]: TDM_SPI_MISO */
+ 42 2 /* MPP[42]: TDM_SPI_MOSI */
+ 43 0 /* MPP[43]: GPIO[43] */
+ 44 0 /* MPP[44]: GPIO[44] */
+ 45 0 /* MPP[45]: GPIO[45] */
+ 46 0 /* MPP[46]: GPIO[46] */
+ 47 0 /* MPP[47]: GPIO[47] */
+ 48 0 /* MPP[48]: GPIO[48] */
+ 49 0 /* MPP[49]: GPIO[49] */
+ >;
+ };
+
+ GPIO: gpio@10100 {
+ #gpio-cells = <3>;
+ compatible = "mrvl,gpio";
+ reg = <0x10100 0x20>;
+ gpio-controller;
+ interrupts = <35 36 37 38 39 40 41>;
+ interrupt-parent = <&PIC>;
+ pin-count = <50>;
+ };
+
+ gpioled@0 {
+ compatible = "mrvl,gpioled";
+
+ gpios = <&GPIO 47 2 0 /* GPIO[47] BT LED: OUT */
+ &GPIO 48 2 0 /* GPIO[48] WLAN LED: OUT */
+ &GPIO 49 2 0>; /* GPIO[49] WLAN AP LED: OUT */
+ };
+
+ rtc@10300 {
+ compatible = "mrvl,rtc";
+ reg = <0x10300 0x08>;
+ };
+
+ twsi@11000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,twsi";
+ reg = <0x11000 0x20>;
+ interrupts = <43>;
+ interrupt-parent = <&PIC>;
+ };
+
+ enet0: ethernet@72000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "V2";
+ compatible = "mrvl,ge";
+ reg = <0x72000 0x2000>;
+ ranges = <0x0 0x72000 0x2000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <12 13 14 11 46>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&phy0>;
+
+ mdio@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,mdio";
+
+ phy0: ethernet-phy@0 {
+ reg = <0x0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <0x1>;
+ };
+ };
+ };
+
+ enet1: ethernet@76000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "V2";
+ compatible = "mrvl,ge";
+ reg = <0x76000 0x02000>;
+ ranges = <0x0 0x76000 0x2000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <16 17 18 15 47>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&phy1>;
+ };
+
+ serial0: serial@12000 {
+ compatible = "ns16550";
+ reg = <0x12000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <0>;
+ interrupts = <33>;
+ interrupt-parent = <&PIC>;
+ };
+
+ serial1: serial@12100 {
+ compatible = "ns16550";
+ reg = <0x12100 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <0>;
+ interrupts = <34>;
+ interrupt-parent = <&PIC>;
+ };
+
+ crypto@30000 {
+ compatible = "mrvl,cesa";
+ reg = <0x30000 0x10000>;
+ interrupts = <22>;
+ interrupt-parent = <&PIC>;
+
+ sram-handle = <&SRAM>;
+ };
+
+ usb@50000 {
+ compatible = "mrvl,usb-ehci", "usb-ehci";
+ reg = <0x50000 0x1000>;
+ interrupts = <48 19>;
+ interrupt-parent = <&PIC>;
+ };
+
+ xor@60000 {
+ compatible = "mrvl,xor";
+ reg = <0x60000 0x1000>;
+ interrupts = <5 6 7 8>;
+ interrupt-parent = <&PIC>;
+ };
+
+ sata@80000 {
+ compatible = "mrvl,sata";
+ reg = <0x80000 0x6000>;
+ interrupts = <21>;
+ interrupt-parent = <&PIC>;
+ };
+
+ sdio@90000 {
+ compatible = "mrvl,sdio";
+ reg = <0x90000 0x134>;
+ interrupts = <28>;
+ interrupt-parent = <&PIC>;
+ };
+ };
+
+ SRAM: sram@fd000000 {
+ compatible = "mrvl,cesa-sram";
+ reg = <0xfd000000 0x00100000>;
+ };
+
+ chosen {
+ stdin = "serial0";
+ stdout = "serial0";
+ };
+
+};
diff --git a/sys/boot/fdt/dts/dreamplug-1001N.dts b/sys/boot/fdt/dts/dreamplug-1001N.dts
new file mode 100644
index 0000000..230a65f
--- /dev/null
+++ b/sys/boot/fdt/dts/dreamplug-1001N.dts
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2013 Ian Lepore
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software substantially based on work developed by Semihalf
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * GlobalScale Technologies DreamPlug Device Tree Source.
+ *
+ * This source is for version 10 revision 01 units with NAND flash.
+ * These units are marked "1001N" on the serial number label.
+ *
+ * $FreeBSD$
+ */
+
+/dts-v1/;
+
+/ {
+ model = "GlobalScale Technologies Dreamplug v1001N";
+ compatible = "globalscale,dreamplug-003-ds2001", "globalscale,dreamplug", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ mpp = &MPP;
+ serial0 = &serial0;
+ serial1 = &serial1;
+ soc = &SOC;
+ sram = &SRAM;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "ARM,88FR131";
+ reg = <0x0>;
+ d-cache-line-size = <32>; // 32 bytes
+ i-cache-line-size = <32>; // 32 bytes
+ d-cache-size = <0x4000>; // L1, 16K
+ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+ };
+
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x20000000>; // 512M at 0x0
+ };
+
+ localbus@0 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "mrvl,lbc";
+ bank-count = <1>;
+
+ /* This reflects CPU decode windows setup. */
+ ranges = <0x0 0x2f 0xf9300000 0x00100000>;
+
+ nand@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "mrvl,nfc";
+ reg = <0x0 0x0 0x00100000>;
+ bank-width = <2>;
+ device-width = <1>;
+
+ // Slice info reported by builtin linux when it boots...
+ //[ 11.161328] 0x00000000-0x00100000 : "u-boot"
+ //[ 11.167431] 0x00100000-0x00500000 : "uImage"
+ //[ 11.173471] 0x00500000-0x20000000 : "root"
+
+ slice@0 {
+ reg = <0x0 0x100000>;
+ label = "u-boot";
+ read-only;
+ };
+
+ slice@200000 {
+ reg = <0x100000 0x40000>;
+ label = "uImage";
+ };
+
+ slice@500000 {
+ reg = <0x500000 0x1FB00000>;
+ label = "root";
+ };
+ };
+ };
+
+ SOC: soc88f6281@f1000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0xf1000000 0x00100000>;
+ bus-frequency = <0>;
+
+ PIC: pic@20200 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = <0x20200 0x3c>;
+ compatible = "mrvl,pic";
+ };
+
+ timer@20300 {
+ compatible = "mrvl,timer";
+ reg = <0x20300 0x30>;
+ interrupts = <1>;
+ interrupt-parent = <&PIC>;
+ mrvl,has-wdt;
+ };
+
+ MPP: mpp@10000 {
+ #pin-cells = <2>;
+ compatible = "mrvl,mpp";
+ reg = <0x10000 0x34>;
+ pin-count = <50>;
+ pin-map = <
+ 0 1 /* MPP[ 0]: NF_IO[2] */
+ 1 1 /* MPP[ 1]: NF_IO[3] */
+ 2 1 /* MPP[ 2]: NF_IO[4] */
+ 3 1 /* MPP[ 3]: NF_IO[5] */
+ 4 1 /* MPP[ 4]: NF_IO[6] */
+ 5 1 /* MPP[ 5]: NF_IO[7] */
+ 6 1 /* MPP[ 6]: SYSRST_OUTn */
+ 7 0 /* MPP[ 7]: GPO[7] */
+ 8 1 /* MPP[ 8]: TW_SDA */
+ 9 1 /* MPP[ 9]: TW_SCK */
+ 10 3 /* MPP[10]: UA0_TXD */
+ 11 3 /* MPP[11]: US0_RXD */
+ 12 1 /* MPP[12]: SD_CLK */
+ 13 1 /* MPP[13]: SD_CMD */
+ 14 1 /* MPP[14]: SD_D[0] */
+ 15 1 /* MPP[15]: SD_D[1] */
+ 16 1 /* MPP[16]: SD_D[2] */
+ 17 1 /* MPP[17]: SD_D[3] */
+ 18 1 /* MPP[18]: NF_IO[0] */
+ 19 1 /* MPP[19]: NF_IO[1] */
+ 20 3 /* MPP[20]: GE1[ 0] */
+ 21 3 /* MPP[21]: GE1[ 1] */
+ 22 3 /* MPP[22]: GE1[ 2] */
+ 23 3 /* MPP[23]: GE1[ 3] */
+ 24 3 /* MPP[24]: GE1[ 4] */
+ 25 3 /* MPP[25]: GE1[ 5] */
+ 26 3 /* MPP[26]: GE1[ 6] */
+ 27 3 /* MPP[27]: GE1[ 7] */
+ 28 3 /* MPP[28]: GE1[ 8] */
+ 29 3 /* MPP[29]: GE1[ 9] */
+ 30 3 /* MPP[30]: GE1[10] */
+ 31 3 /* MPP[31]: GE1[11] */
+ 32 3 /* MPP[32]: GE1[12] */
+ 33 3 /* MPP[33]: GE1[13] */
+ 34 3 /* MPP[34]: GE1[14] */
+ 35 3 /* MPP[35]: GE1[15] */
+ 36 0 /* MPP[36]: GPIO[36] */
+ 37 0 /* MPP[37]: GPIO[37] */
+ 38 0 /* MPP[38]: GPIO[38] */
+ 39 0 /* MPP[39]: GPIO[39] */
+ 40 2 /* MPP[40]: TDM_SPI_SCK */
+ 41 2 /* MPP[41]: TDM_SPI_MISO */
+ 42 2 /* MPP[42]: TDM_SPI_MOSI */
+ 43 0 /* MPP[43]: GPIO[43] */
+ 44 0 /* MPP[44]: GPIO[44] */
+ 45 0 /* MPP[45]: GPIO[45] */
+ 46 0 /* MPP[46]: GPIO[46] */
+ 47 0 /* MPP[47]: GPIO[47] */
+ 48 0 /* MPP[48]: GPIO[48] */
+ 49 0 /* MPP[49]: GPIO[49] */
+ >;
+ };
+
+ GPIO: gpio@10100 {
+ #gpio-cells = <3>;
+ compatible = "mrvl,gpio";
+ reg = <0x10100 0x20>;
+ gpio-controller;
+ interrupts = <35 36 37 38 39 40 41>;
+ interrupt-parent = <&PIC>;
+ pin-count = <50>;
+ };
+
+ gpioled@0 {
+ compatible = "mrvl,gpioled";
+
+ gpios = <&GPIO 47 2 0 /* GPIO[47] BT LED: OUT */
+ &GPIO 48 2 0 /* GPIO[48] WLAN LED: OUT */
+ &GPIO 49 2 0>; /* GPIO[49] WLAN AP LED: OUT */
+ };
+
+ rtc@10300 {
+ compatible = "mrvl,rtc";
+ reg = <0x10300 0x08>;
+ };
+
+ twsi@11000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,twsi";
+ reg = <0x11000 0x20>;
+ interrupts = <43>;
+ interrupt-parent = <&PIC>;
+ };
+
+ enet0: ethernet@72000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "V2";
+ compatible = "mrvl,ge";
+ reg = <0x72000 0x2000>;
+ ranges = <0x0 0x72000 0x2000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <12 13 14 11 46>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&phy0>;
+
+ mdio@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,mdio";
+
+ phy0: ethernet-phy@0 {
+ reg = <0x0>;
+ };
+
+ phy1: ethernet-phy@1 {
+ reg = <0x1>;
+ };
+ };
+ };
+
+ enet1: ethernet@76000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "V2";
+ compatible = "mrvl,ge";
+ reg = <0x76000 0x02000>;
+ ranges = <0x0 0x76000 0x2000>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <16 17 18 15 47>;
+ interrupt-parent = <&PIC>;
+ phy-handle = <&phy1>;
+ };
+
+ serial0: serial@12000 {
+ compatible = "ns16550";
+ reg = <0x12000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <0>;
+ interrupts = <33>;
+ interrupt-parent = <&PIC>;
+ };
+
+ serial1: serial@12100 {
+ compatible = "ns16550";
+ reg = <0x12100 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <0>;
+ interrupts = <34>;
+ interrupt-parent = <&PIC>;
+ };
+
+ crypto@30000 {
+ compatible = "mrvl,cesa";
+ reg = <0x30000 0x10000>;
+ interrupts = <22>;
+ interrupt-parent = <&PIC>;
+
+ sram-handle = <&SRAM>;
+ };
+
+ usb@50000 {
+ compatible = "mrvl,usb-ehci", "usb-ehci";
+ reg = <0x50000 0x1000>;
+ interrupts = <48 19>;
+ interrupt-parent = <&PIC>;
+ };
+
+ xor@60000 {
+ compatible = "mrvl,xor";
+ reg = <0x60000 0x1000>;
+ interrupts = <5 6 7 8>;
+ interrupt-parent = <&PIC>;
+ };
+
+ sata@80000 {
+ compatible = "mrvl,sata";
+ reg = <0x80000 0x6000>;
+ interrupts = <21>;
+ interrupt-parent = <&PIC>;
+ };
+
+ sdio@90000 {
+ compatible = "mrvl,sdio";
+ reg = <0x90000 0x134>;
+ interrupts = <28>;
+ interrupt-parent = <&PIC>;
+ };
+ };
+
+ SRAM: sram@fd000000 {
+ compatible = "mrvl,cesa-sram";
+ reg = <0xfd000000 0x00100000>;
+ };
+
+ chosen {
+ stdin = "serial0";
+ stdout = "serial0";
+ };
+
+};
diff --git a/sys/boot/i386/efi/Makefile b/sys/boot/i386/efi/Makefile
index 95c219d..25df59b 100644
--- a/sys/boot/i386/efi/Makefile
+++ b/sys/boot/i386/efi/Makefile
@@ -36,7 +36,7 @@ FILES= loader.efi
FILESMODE_loader.efi= ${BINMODE}
LDSCRIPT= ${.CURDIR}/ldscript.i386
-LDFLAGS= -Wl,-T${LDSCRIPT} -shared -symbolic
+LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared
${PROG}: ${LDSCRIPT}
diff --git a/sys/boot/i386/libi386/bootinfo64.c b/sys/boot/i386/libi386/bootinfo64.c
index 0c6d077..617414e 100644
--- a/sys/boot/i386/libi386/bootinfo64.c
+++ b/sys/boot/i386/libi386/bootinfo64.c
@@ -134,7 +134,8 @@ bi_checkcpu(void)
{
char *cpu_vendor;
int vendor[3];
- int eflags, regs[4];
+ int eflags;
+ unsigned int regs[4];
/* Check for presence of "cpuid". */
eflags = read_eflags();
diff --git a/sys/boot/i386/libi386/comconsole.c b/sys/boot/i386/libi386/comconsole.c
index 3822597..e2710c1 100644
--- a/sys/boot/i386/libi386/comconsole.c
+++ b/sys/boot/i386/libi386/comconsole.c
@@ -50,7 +50,6 @@ static int comc_init(int arg);
static void comc_putchar(int c);
static int comc_getchar(void);
static int comc_getspeed(void);
-static void set_hw_console_hint(void);
static int comc_ischar(void);
static int comc_parseint(const char *string);
static uint32_t comc_parse_pcidev(const char *string);
@@ -202,27 +201,14 @@ comc_port_set(struct env_var *ev, int flags, const void *value)
}
if ((comconsole.c_flags & (C_ACTIVEIN | C_ACTIVEOUT)) != 0 &&
- comc_port != port) {
+ comc_port != port)
comc_setup(comc_curspeed, port);
- set_hw_console_hint();
- }
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
return (CMD_OK);
}
-static void
-set_hw_console_hint(void)
-{
- char intbuf[64];
-
- unsetenv("hw.uart.console");
- sprintf(intbuf, "io:%d,br:%d", comc_port, comc_curspeed);
- env_setenv("hw.uart.console", EV_VOLATILE, intbuf,
- env_noset, env_nounset);
-}
-
/*
* Input: bus:dev:func[:bar]. If bar is not specified, it is 0x10.
* Output: bar[24:16] bus[15:8] dev[7:3] func[2:0]
@@ -288,7 +274,6 @@ comc_pcidev_handle(uint32_t locator)
comc_port_set, env_nounset);
comc_setup(comc_curspeed, port);
- set_hw_console_hint();
comc_locator = locator;
return (CMD_OK);
@@ -318,8 +303,10 @@ static void
comc_setup(int speed, int port)
{
static int TRY_COUNT = 1000000;
+ char intbuf[64];
int tries;
+ unsetenv("hw.uart.console");
comc_curspeed = speed;
comc_port = port;
@@ -334,9 +321,11 @@ comc_setup(int speed, int port)
inb(comc_port + com_data);
while (inb(comc_port + com_lsr) & LSR_RXRDY && ++tries < TRY_COUNT);
- if (tries < TRY_COUNT)
+ if (tries < TRY_COUNT) {
comconsole.c_flags |= (C_PRESENTIN | C_PRESENTOUT);
- else
+ sprintf(intbuf, "io:%d,br:%d", comc_port, comc_curspeed);
+ env_setenv("hw.uart.console", EV_VOLATILE, intbuf, NULL, NULL);
+ } else
comconsole.c_flags &= ~(C_PRESENTIN | C_PRESENTOUT);
}
diff --git a/sys/boot/i386/libi386/devicename.c b/sys/boot/i386/libi386/devicename.c
index 15889d3..c7705d7 100644
--- a/sys/boot/i386/libi386/devicename.c
+++ b/sys/boot/i386/libi386/devicename.c
@@ -128,7 +128,7 @@ i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path)
goto fail;
}
} else {
- cp = np;
+ cp = (char *)np;
}
if (*cp && (*cp != ':')) {
err = EINVAL;
diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c
index e4ec5c0..49814dd 100644
--- a/sys/boot/i386/libi386/pxe.c
+++ b/sys/boot/i386/libi386/pxe.c
@@ -88,6 +88,12 @@ static int pxe_netif_get(struct iodesc *desc, void *pkt, size_t len,
static int pxe_netif_put(struct iodesc *desc, void *pkt, size_t len);
static void pxe_netif_end(struct netif *nif);
+#ifdef OLD_NFSV2
+int nfs_getrootfh(struct iodesc*, char*, u_char*);
+#else
+int nfs_getrootfh(struct iodesc*, char*, uint32_t*, u_char*);
+#endif
+
extern struct netif_stats pxe_st[];
extern u_int16_t __bangpxeseg;
extern u_int16_t __bangpxeoff;
diff --git a/sys/boot/sparc64/loader/main.c b/sys/boot/sparc64/loader/main.c
index fa9d068..5a0badf 100644
--- a/sys/boot/sparc64/loader/main.c
+++ b/sys/boot/sparc64/loader/main.c
@@ -142,6 +142,10 @@ static vm_offset_t heapva;
static char bootpath[64];
static phandle_t root;
+#ifdef LOADER_ZFS_SUPPORT
+static struct zfs_devdesc zfs_currdev;
+#endif
+
/*
* Machine dependent structures that the machine independent
* loader part uses.
@@ -732,7 +736,6 @@ static void
sparc64_zfs_probe(void)
{
struct vtoc8 vtoc;
- struct zfs_devdesc zfs_currdev;
char alias[64], devname[sizeof(alias) + sizeof(":x") - 1];
char type[sizeof("device_type")];
char *bdev, *dev, *odev;
@@ -805,9 +808,6 @@ sparc64_zfs_probe(void)
zfs_currdev.root_guid = 0;
zfs_currdev.d_dev = &zfs_dev;
zfs_currdev.d_type = zfs_currdev.d_dev->dv_type;
- (void)strncpy(bootpath, zfs_fmtdev(&zfs_currdev),
- sizeof(bootpath) - 1);
- bootpath[sizeof(bootpath) - 1] = '\0';
}
}
#endif /* LOADER_ZFS_SUPPORT */
@@ -878,10 +878,14 @@ main(int (*openfirm)(void *))
if ((*dp)->dv_init != 0)
(*dp)->dv_init();
- /*
- * Now that sparc64_zfs_probe() might have altered bootpath,
- * export it.
- */
+#ifdef LOADER_ZFS_SUPPORT
+ if (zfs_currdev.pool_guid != 0) {
+ (void)strncpy(bootpath, zfs_fmtdev(&zfs_currdev),
+ sizeof(bootpath) - 1);
+ bootpath[sizeof(bootpath) - 1] = '\0';
+ }
+#endif
+
env_setenv("currdev", EV_VOLATILE, bootpath,
ofw_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, bootpath,
diff --git a/sys/boot/uboot/common/metadata.c b/sys/boot/uboot/common/metadata.c
index 74497a9..bbc1893 100644
--- a/sys/boot/uboot/common/metadata.c
+++ b/sys/boot/uboot/common/metadata.c
@@ -369,12 +369,15 @@ md_load(char *args, vm_offset_t *modulep)
/* Convert addresses to the final VA */
*modulep -= __elfN(relocation_offset);
- for (i = 0; i < sizeof mdt / sizeof mdt[0]; i++) {
- md = file_findmetadata(kfp, mdt[i]);
- if (md) {
- bcopy(md->md_data, &vaddr, sizeof vaddr);
- vaddr -= __elfN(relocation_offset);
- bcopy(&vaddr, md->md_data, sizeof vaddr);
+ /* Do relocation fixup on metadata of each module. */
+ for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
+ for (i = 0; i < sizeof mdt / sizeof mdt[0]; i++) {
+ md = file_findmetadata(xp, mdt[i]);
+ if (md) {
+ bcopy(md->md_data, &vaddr, sizeof vaddr);
+ vaddr -= __elfN(relocation_offset);
+ bcopy(&vaddr, md->md_data, sizeof vaddr);
+ }
}
}
diff --git a/sys/boot/usb/Makefile b/sys/boot/usb/Makefile
new file mode 100644
index 0000000..b71b10d
--- /dev/null
+++ b/sys/boot/usb/Makefile
@@ -0,0 +1,150 @@
+#
+# $FreeBSD$
+#
+# Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# 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.
+#
+
+T=${.CURDIR}/tools
+S=${.CURDIR}/../..
+
+.PATH: \
+ ${.CURDIR} \
+ ${S}/dev/usb \
+ ${S}/dev/usb/controller \
+ ${S}/dev/usb/serial \
+ ${S}/dev/usb/storage \
+ ${S}/dev/usb/template
+
+LIB= usbboot
+INTERNALLIB=
+OBJCOPY?= objcopy
+SYSCC?= cc
+
+CFLAGS+= -DBOOTPROG=\"usbloader\"
+CFLAGS+= -DUSB_GLOBAL_INCLUDE_FILE="\"bsd_global.h\""
+CFLAGS+= -ffunction-sections -fdata-sections
+CFLAGS+= -ffreestanding
+CFLAGS+= -Wformat -Wall
+CFLAGS+= -I ${S}
+CFLAGS+= -I ${T}
+CFLAGS+= -I ${.CURDIR}
+CFLAGS+= -g
+
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -march=i386
+CFLAGS+= -mpreferred-stack-boundary=2
+.endif
+.if ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -m32
+.endif
+
+#
+# Single threaded BSD kernel
+#
+SRCS+= bsd_kernel.c
+
+#
+# BUSSPACE implementation
+#
+SRCS+= bsd_busspace.c
+
+#
+# BUSDMA implementation
+#
+SRCS+= usb_busdma_loader.c
+
+#
+# USB controller drivers
+#
+SRCS+= at91dci.c
+SRCS+= atmegadci.c
+SRCS+= avr32dci.c
+SRCS+= dwc_otg.c
+SRCS+= ehci.c
+SRCS+= musb_otg.c
+SRCS+= ohci.c
+SRCS+= uhci.c
+SRCS+= uss820dci.c
+SRCS+= xhci.c
+SRCS+= usb_controller.c
+
+CFLAGS += -DUSB_PROBE_LIST="\"xhci\", \"ehci\", \"uhci\", \"ohci\""
+
+#
+# USB core and templates
+#
+SRCS+= usb_core.c
+SRCS+= usb_debug.c
+SRCS+= usb_device.c
+SRCS+= usb_dynamic.c
+SRCS+= usb_error.c
+SRCS+= usb_handle_request.c
+SRCS+= usb_hid.c
+SRCS+= usb_hub.c
+SRCS+= usb_lookup.c
+SRCS+= usb_msctest.c
+SRCS+= usb_parse.c
+SRCS+= usb_request.c
+SRCS+= usb_transfer.c
+SRCS+= usb_util.c
+SRCS+= usb_template.c
+SRCS+= usb_template_cdce.c
+SRCS+= usb_template_msc.c
+SRCS+= usb_template_mtp.c
+SRCS+= usb_template_modem.c
+SRCS+= usb_template_mouse.c
+SRCS+= usb_template_kbd.c
+SRCS+= usb_template_audio.c
+SRCS+= sysinit_data.c
+SRCS+= sysuninit_data.c
+
+CLEANFILES+= sysinit
+CLEANFILES+= sysinit.bin
+CLEANFILES+= sysinit_data.c
+CLEANFILES+= sysuninit_data.c
+
+CLEANFILES+= ${SRCS:C/\.c/.osys/g}
+
+.include <bsd.lib.mk>
+
+#
+# SYSINIT() and SYSUNINIT() handling
+#
+sysinit: ${T}/sysinit.c
+ ${SYSCC} -Wall -o ${.TARGET} ${.ALLSRC}
+
+sysinit_data.c: sysinit.bin sysinit
+ ${.OBJDIR}/sysinit -i sysinit.bin -o ${.TARGET} -k sysinit -s sysinit_data
+
+sysuninit_data.c: sysinit.bin sysinit
+ ${.OBJDIR}/sysinit -i sysinit.bin -o ${.TARGET} -R -k sysuninit -s sysuninit_data
+
+.for F in ${OBJS}
+${F}sys: ${F}
+ ${OBJCOPY} -j ".debug.sysinit" -O binary ${F} ${.TARGET}
+ [ -f ${.TARGET} ] || touch ${.TARGET}
+.endfor
+
+sysinit.bin: ${OBJS:C/\.o/.osys/g:C/sysinit_data.osys//g:C/sysuninit_data.osys//g}
+ cat ${.ALLSRC} > sysinit.bin
diff --git a/sys/boot/usb/Makefile.test b/sys/boot/usb/Makefile.test
new file mode 100644
index 0000000..a366d36
--- /dev/null
+++ b/sys/boot/usb/Makefile.test
@@ -0,0 +1,61 @@
+#
+# $FreeBSD$
+#
+# Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# 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.
+#
+
+#
+# USB test application
+#
+
+.PATH: ${.CURDIR}
+
+PROG= usbloader
+MAN=
+SRCS=
+
+CFLAGS+= -Wall
+CFLAGS+= -g
+
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -march=i386
+CFLAGS+= -mpreferred-stack-boundary=2
+.endif
+.if ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -m32
+.endif
+
+LDFLAGS+= -Wl,--gc-sections
+
+SRCS+= bsd_usbloader_test.c
+
+LDADD+= libusbboot.a
+DPADD+= libusbboot.a
+
+all: libusbboot.a
+
+.include <bsd.prog.mk>
+
+libusbboot.a:
+ make -f Makefile
diff --git a/sys/boot/usb/bsd_busspace.c b/sys/boot/usb/bsd_busspace.c
new file mode 100644
index 0000000..c9ba09f
--- /dev/null
+++ b/sys/boot/usb/bsd_busspace.c
@@ -0,0 +1,207 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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 <bsd_kernel.h>
+
+struct burst {
+ uint32_t dw0;
+ uint32_t dw1;
+ uint32_t dw2;
+ uint32_t dw3;
+ uint32_t dw4;
+ uint32_t dw5;
+ uint32_t dw6;
+ uint32_t dw7;
+};
+
+void
+bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint8_t *datap, bus_size_t count)
+{
+ while (count--) {
+ *datap++ = bus_space_read_1(t, h, offset);
+ }
+}
+
+void
+bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint16_t *datap, bus_size_t count)
+{
+ while (count--) {
+ *datap++ = bus_space_read_2(t, h, offset);
+ }
+}
+
+void
+bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint32_t *datap, bus_size_t count)
+{
+ h += offset;
+
+ while (count--) {
+ *datap++ = *((volatile uint32_t *)h);
+ }
+}
+
+void
+bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint8_t *datap, bus_size_t count)
+{
+ while (count--) {
+ uint8_t temp = *datap++;
+
+ bus_space_write_1(t, h, offset, temp);
+ }
+}
+
+void
+bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint16_t *datap, bus_size_t count)
+{
+ while (count--) {
+ uint16_t temp = *datap++;
+
+ bus_space_write_2(t, h, offset, temp);
+ }
+}
+
+void
+bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint32_t *datap, bus_size_t count)
+{
+ h += offset;
+
+ while (count--) {
+ *((volatile uint32_t *)h) = *datap++;
+ }
+}
+
+void
+bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint8_t data)
+{
+ *((volatile uint8_t *)(h + offset)) = data;
+}
+
+void
+bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint16_t data)
+{
+ *((volatile uint16_t *)(h + offset)) = data;
+}
+
+void
+bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint32_t data)
+{
+ *((volatile uint32_t *)(h + offset)) = data;
+}
+
+uint8_t
+bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset)
+{
+ return (*((volatile uint8_t *)(h + offset)));
+}
+
+uint16_t
+bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset)
+{
+ return (*((volatile uint16_t *)(h + offset)));
+}
+
+uint32_t
+bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset)
+{
+ return (*((volatile uint32_t *)(h + offset)));
+}
+
+void
+bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint8_t *datap, bus_size_t count)
+{
+ h += offset;
+
+ while (count--) {
+ *datap++ = *((volatile uint8_t *)h);
+ h += 1;
+ }
+}
+
+void
+bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint8_t *datap, bus_size_t count)
+{
+ h += offset;
+
+ while (count--) {
+ *((volatile uint8_t *)h) = *datap++;
+ h += 1;
+ }
+}
+
+void
+bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint32_t *datap, bus_size_t count)
+{
+ enum { BURST = sizeof(struct burst) / 4 };
+
+ h += offset;
+
+ while (count >= BURST) {
+ *(struct burst *)datap = *((/* volatile */ struct burst *)h);
+
+ h += BURST * 4;
+ datap += BURST;
+ count -= BURST;
+ }
+
+ while (count--) {
+ *datap++ = *((volatile uint32_t *)h);
+ h += 4;
+ }
+}
+
+void
+bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h,
+ bus_size_t offset, uint32_t *datap, bus_size_t count)
+{
+ enum { BURST = sizeof(struct burst) / 4 };
+
+ h += offset;
+
+ while (count >= BURST) {
+ *((/* volatile */ struct burst *)h) = *(struct burst *)datap;
+
+ h += BURST * 4;
+ datap += BURST;
+ count -= BURST;
+ }
+
+ while (count--) {
+ *((volatile uint32_t *)h) = *datap++;
+ h += 4;
+ }
+}
diff --git a/sys/boot/usb/bsd_global.h b/sys/boot/usb/bsd_global.h
new file mode 100644
index 0000000..9fe1c8c
--- /dev/null
+++ b/sys/boot/usb/bsd_global.h
@@ -0,0 +1,63 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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.
+ */
+
+#ifndef _BSD_GLOBAL_H_
+#define _BSD_GLOBAL_H_
+
+#include <bsd_kernel.h>
+
+#define USB_DEBUG_VAR usb_debug
+#include <dev/usb/usb_freebsd_loader.h>
+#include <dev/usb/usb_endian.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_dynamic.h>
+#include <dev/usb/usb_device.h>
+#include <dev/usb/usb_hub.h>
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usb_cdc.h>
+#include <dev/usb/usb_dev.h>
+#include <dev/usb/usb_mbuf.h>
+#include <dev/usb/usb_msctest.h>
+#include <dev/usb/usb_pci.h>
+#include <dev/usb/usb_pf.h>
+#include <dev/usb/usb_request.h>
+#include <dev/usb/usb_util.h>
+#include <dev/usb/usb_transfer.h>
+#include <dev/usb/usb_compat_linux.h>
+#include <dev/usb/usbhid.h>
+#include <dev/usb/usb_ioctl.h>
+#include <dev/usb/usb_generic.h>
+#include <dev/usb/quirk/usb_quirk.h>
+#include <dev/usb/template/usb_template.h>
+
+#endif /* _BSD_GLOBAL_H_ */
diff --git a/sys/boot/usb/bsd_kernel.c b/sys/boot/usb/bsd_kernel.c
new file mode 100644
index 0000000..5f24c2d
--- /dev/null
+++ b/sys/boot/usb/bsd_kernel.c
@@ -0,0 +1,1269 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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 <bsd_global.h>
+
+static struct usb_process usb_process[USB_PROC_MAX];
+static device_t usb_pci_root;
+
+/*------------------------------------------------------------------------*
+ * Implementation of mutex API
+ *------------------------------------------------------------------------*/
+
+struct mtx Giant;
+
+static void
+mtx_system_init(void *arg)
+{
+ mtx_init(&Giant, "Giant", NULL, MTX_DEF | MTX_RECURSE);
+}
+SYSINIT(mtx_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, mtx_system_init, NULL);
+
+void
+mtx_init(struct mtx *mtx, const char *name, const char *type, int opt)
+{
+ mtx->owned = 0;
+ mtx->parent = mtx;
+}
+
+void
+mtx_lock(struct mtx *mtx)
+{
+ mtx = mtx->parent;
+ mtx->owned++;
+}
+
+void
+mtx_unlock(struct mtx *mtx)
+{
+ mtx = mtx->parent;
+ mtx->owned--;
+}
+
+int
+mtx_owned(struct mtx *mtx)
+{
+ mtx = mtx->parent;
+ return (mtx->owned != 0);
+}
+
+void
+mtx_destroy(struct mtx *mtx)
+{
+ /* NOP */
+}
+
+/*------------------------------------------------------------------------*
+ * Implementation of shared/exclusive mutex API
+ *------------------------------------------------------------------------*/
+
+void
+sx_init_flags(struct sx *sx, const char *name, int flags)
+{
+ sx->owned = 0;
+}
+
+void
+sx_destroy(struct sx *sx)
+{
+ /* NOP */
+}
+
+void
+sx_xlock(struct sx *sx)
+{
+ sx->owned++;
+}
+
+void
+sx_xunlock(struct sx *sx)
+{
+ sx->owned--;
+}
+
+int
+sx_xlocked(struct sx *sx)
+{
+ return (sx->owned != 0);
+}
+
+/*------------------------------------------------------------------------*
+ * Implementaiton of condition variable API
+ *------------------------------------------------------------------------*/
+
+void
+cv_init(struct cv *cv, const char *desc)
+{
+ cv->sleeping = 0;
+}
+
+void
+cv_destroy(struct cv *cv)
+{
+ /* NOP */
+}
+
+void
+cv_wait(struct cv *cv, struct mtx *mtx)
+{
+ cv_timedwait(cv, mtx, -1);
+}
+
+int
+cv_timedwait(struct cv *cv, struct mtx *mtx, int timo)
+{
+ int start = ticks;
+ int delta;
+
+ if (cv->sleeping)
+ return (EWOULDBLOCK); /* not allowed */
+
+ cv->sleeping = 1;
+
+ while (cv->sleeping) {
+ if (timo >= 0) {
+ delta = ticks - start;
+ if (delta >= timo || delta < 0)
+ break;
+ }
+ mtx_unlock(mtx);
+
+ usb_idle();
+
+ mtx_lock(mtx);
+ }
+
+ if (cv->sleeping) {
+ cv->sleeping = 0;
+ return (EWOULDBLOCK); /* not allowed */
+ }
+ return (0);
+}
+
+void
+cv_signal(struct cv *cv)
+{
+ cv->sleeping = 0;
+}
+
+void
+cv_broadcast(struct cv *cv)
+{
+ cv->sleeping = 0;
+}
+
+/*------------------------------------------------------------------------*
+ * Implementation of callout API
+ *------------------------------------------------------------------------*/
+
+static void callout_proc_msg(struct usb_proc_msg *);
+
+volatile int ticks = 0;
+
+static LIST_HEAD(, callout) head_callout = LIST_HEAD_INITIALIZER(&head_callout);
+
+static struct mtx mtx_callout;
+static struct usb_proc_msg callout_msg[2];
+
+static void
+callout_system_init(void *arg)
+{
+ mtx_init(&mtx_callout, "callout-mtx", NULL, MTX_DEF | MTX_RECURSE);
+
+ callout_msg[0].pm_callback = &callout_proc_msg;
+ callout_msg[1].pm_callback = &callout_proc_msg;
+}
+SYSINIT(callout_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, callout_system_init, NULL);
+
+static void
+callout_callback(struct callout *c)
+{
+ mtx_lock(c->mtx);
+
+ mtx_lock(&mtx_callout);
+ if (c->entry.le_prev != NULL) {
+ LIST_REMOVE(c, entry);
+ c->entry.le_prev = NULL;
+ }
+ mtx_unlock(&mtx_callout);
+
+ if (c->func)
+ (c->func) (c->arg);
+
+ if (!(c->flags & CALLOUT_RETURNUNLOCKED))
+ mtx_unlock(c->mtx);
+}
+
+void
+callout_process(int timeout)
+{
+ ticks += timeout;
+ usb_proc_msignal(usb_process + 2, &callout_msg[0], &callout_msg[1]);
+}
+
+static void
+callout_proc_msg(struct usb_proc_msg *pmsg)
+{
+ struct callout *c;
+ int delta;
+
+repeat:
+ mtx_lock(&mtx_callout);
+
+ LIST_FOREACH(c, &head_callout, entry) {
+
+ delta = c->timeout - ticks;
+ if (delta < 0) {
+ mtx_unlock(&mtx_callout);
+
+ callout_callback(c);
+
+ goto repeat;
+ }
+ }
+ mtx_unlock(&mtx_callout);
+}
+
+void
+callout_init_mtx(struct callout *c, struct mtx *mtx, int flags)
+{
+ memset(c, 0, sizeof(*c));
+
+ if (mtx == NULL)
+ mtx = &Giant;
+
+ c->mtx = mtx;
+ c->flags = (flags & CALLOUT_RETURNUNLOCKED);
+}
+
+void
+callout_reset(struct callout *c, int to_ticks,
+ void (*func) (void *), void *arg)
+{
+ callout_stop(c);
+
+ c->func = func;
+ c->arg = arg;
+ c->timeout = ticks + to_ticks;
+
+ mtx_lock(&mtx_callout);
+ LIST_INSERT_HEAD(&head_callout, c, entry);
+ mtx_unlock(&mtx_callout);
+}
+
+void
+callout_stop(struct callout *c)
+{
+ mtx_lock(&mtx_callout);
+
+ if (c->entry.le_prev != NULL) {
+ LIST_REMOVE(c, entry);
+ c->entry.le_prev = NULL;
+ }
+ mtx_unlock(&mtx_callout);
+
+ c->func = NULL;
+ c->arg = NULL;
+}
+
+void
+callout_drain(struct callout *c)
+{
+ if (c->mtx == NULL)
+ return; /* not initialised */
+
+ mtx_lock(c->mtx);
+ callout_stop(c);
+ mtx_unlock(c->mtx);
+}
+
+int
+callout_pending(struct callout *c)
+{
+ int retval;
+
+ mtx_lock(&mtx_callout);
+ retval = (c->entry.le_prev != NULL);
+ mtx_unlock(&mtx_callout);
+
+ return (retval);
+}
+
+/*------------------------------------------------------------------------*
+ * Implementation of device API
+ *------------------------------------------------------------------------*/
+
+static const char unknown_string[] = { "unknown" };
+
+static TAILQ_HEAD(, module_data) module_head =
+ TAILQ_HEAD_INITIALIZER(module_head);
+
+static uint8_t
+devclass_equal(const char *a, const char *b)
+{
+ char ta, tb;
+
+ if (a == b)
+ return (1);
+
+ while (1) {
+ ta = *a;
+ tb = *b;
+ if (ta != tb)
+ return (0);
+ if (ta == 0)
+ break;
+ a++;
+ b++;
+ }
+ return (1);
+}
+
+int
+bus_generic_resume(device_t dev)
+{
+ return (0);
+}
+
+int
+bus_generic_shutdown(device_t dev)
+{
+ return (0);
+}
+
+int
+bus_generic_suspend(device_t dev)
+{
+ return (0);
+}
+
+int
+bus_generic_print_child(device_t dev, device_t child)
+{
+ return (0);
+}
+
+void
+bus_generic_driver_added(device_t dev, driver_t *driver)
+{
+ return;
+}
+
+device_t
+device_get_parent(device_t dev)
+{
+ return (dev ? dev->dev_parent : NULL);
+}
+
+void
+device_set_interrupt(device_t dev, intr_fn_t *fn, void *arg)
+{
+ dev->dev_irq_fn = fn;
+ dev->dev_irq_arg = arg;
+}
+
+void
+device_run_interrupts(device_t parent)
+{
+ device_t child;
+
+ if (parent == NULL)
+ return;
+
+ TAILQ_FOREACH(child, &parent->dev_children, dev_link) {
+ if (child->dev_irq_fn != NULL)
+ (child->dev_irq_fn) (child->dev_irq_arg);
+ }
+}
+
+void
+device_set_ivars(device_t dev, void *ivars)
+{
+ dev->dev_aux = ivars;
+}
+
+void *
+device_get_ivars(device_t dev)
+{
+ return (dev ? dev->dev_aux : NULL);
+}
+
+int
+device_get_unit(device_t dev)
+{
+ return (dev ? dev->dev_unit : 0);
+}
+
+int
+bus_generic_detach(device_t dev)
+{
+ device_t child;
+ int error;
+
+ if (!dev->dev_attached)
+ return (EBUSY);
+
+ TAILQ_FOREACH(child, &dev->dev_children, dev_link) {
+ if ((error = device_detach(child)) != 0)
+ return (error);
+ }
+ return (0);
+}
+
+const char *
+device_get_nameunit(device_t dev)
+{
+ if (dev && dev->dev_nameunit[0])
+ return (dev->dev_nameunit);
+
+ return (unknown_string);
+}
+
+static uint8_t
+devclass_create(devclass_t *dc_pp)
+{
+ if (dc_pp == NULL) {
+ return (1);
+ }
+ if (dc_pp[0] == NULL) {
+ dc_pp[0] = malloc(sizeof(**(dc_pp)),
+ M_DEVBUF, M_WAITOK | M_ZERO);
+
+ if (dc_pp[0] == NULL) {
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static const struct module_data *
+devclass_find_create(const char *classname)
+{
+ const struct module_data *mod;
+
+ TAILQ_FOREACH(mod, &module_head, entry) {
+ if (devclass_equal(mod->mod_name, classname)) {
+ if (devclass_create(mod->devclass_pp)) {
+ continue;
+ }
+ return (mod);
+ }
+ }
+ return (NULL);
+}
+
+static uint8_t
+devclass_add_device(const struct module_data *mod, device_t dev)
+{
+ device_t *pp_dev;
+ device_t *end;
+ uint8_t unit;
+
+ pp_dev = mod->devclass_pp[0]->dev_list;
+ end = pp_dev + DEVCLASS_MAXUNIT;
+ unit = 0;
+
+ while (pp_dev != end) {
+ if (*pp_dev == NULL) {
+ *pp_dev = dev;
+ dev->dev_unit = unit;
+ dev->dev_module = mod;
+ snprintf(dev->dev_nameunit,
+ sizeof(dev->dev_nameunit),
+ "%s%d", device_get_name(dev), unit);
+ return (0);
+ }
+ pp_dev++;
+ unit++;
+ }
+ DPRINTF("Could not add device to devclass.\n");
+ return (1);
+}
+
+static void
+devclass_delete_device(const struct module_data *mod, device_t dev)
+{
+ if (mod == NULL) {
+ return;
+ }
+ mod->devclass_pp[0]->dev_list[dev->dev_unit] = NULL;
+ dev->dev_module = NULL;
+}
+
+static device_t
+make_device(device_t parent, const char *name)
+{
+ device_t dev = NULL;
+ const struct module_data *mod = NULL;
+
+ if (name) {
+
+ mod = devclass_find_create(name);
+
+ if (!mod) {
+
+ DPRINTF("%s:%d:%s: can't find device "
+ "class %s\n", __FILE__, __LINE__,
+ __FUNCTION__, name);
+
+ goto done;
+ }
+ }
+ dev = malloc(sizeof(*dev),
+ M_DEVBUF, M_WAITOK | M_ZERO);
+
+ if (dev == NULL)
+ goto done;
+
+ dev->dev_parent = parent;
+ TAILQ_INIT(&dev->dev_children);
+
+ if (name) {
+ dev->dev_fixed_class = 1;
+ if (devclass_add_device(mod, dev)) {
+ goto error;
+ }
+ }
+done:
+ return (dev);
+
+error:
+ if (dev) {
+ free(dev, M_DEVBUF);
+ }
+ return (NULL);
+}
+
+device_t
+device_add_child(device_t dev, const char *name, int unit)
+{
+ device_t child;
+
+ if (unit != -1) {
+ device_printf(dev, "Unit is not -1\n");
+ }
+ child = make_device(dev, name);
+ if (child == NULL) {
+ device_printf(dev, "Could not add child '%s'\n", name);
+ goto done;
+ }
+ if (dev == NULL) {
+ /* no parent */
+ goto done;
+ }
+ TAILQ_INSERT_TAIL(&dev->dev_children, child, dev_link);
+done:
+ return (child);
+}
+
+int
+device_delete_child(device_t dev, device_t child)
+{
+ int error = 0;
+ device_t grandchild;
+
+ /* remove children first */
+
+ while ((grandchild = TAILQ_FIRST(&child->dev_children))) {
+ error = device_delete_child(child, grandchild);
+ if (error) {
+ device_printf(dev, "Error deleting child!\n");
+ goto done;
+ }
+ }
+
+ error = device_detach(child);
+
+ if (error)
+ goto done;
+
+ devclass_delete_device(child->dev_module, child);
+
+ if (dev != NULL) {
+ /* remove child from parent */
+ TAILQ_REMOVE(&dev->dev_children, child, dev_link);
+ }
+ free(child, M_DEVBUF);
+
+done:
+ return (error);
+}
+
+int
+device_delete_children(device_t dev)
+{
+ device_t child;
+ int error = 0;
+
+ while ((child = TAILQ_FIRST(&dev->dev_children))) {
+ error = device_delete_child(dev, child);
+ if (error) {
+ device_printf(dev, "Error deleting child!\n");
+ break;
+ }
+ }
+ return (error);
+}
+
+void
+device_quiet(device_t dev)
+{
+ dev->dev_quiet = 1;
+}
+
+const char *
+device_get_desc(device_t dev)
+{
+ if (dev)
+ return &(dev->dev_desc[0]);
+ return (unknown_string);
+}
+
+static int
+default_method(void)
+{
+ /* do nothing */
+ DPRINTF("Default method called\n");
+ return (0);
+}
+
+void *
+device_get_method(device_t dev, const char *what)
+{
+ const struct device_method *mtod;
+
+ mtod = dev->dev_module->driver->methods;
+ while (mtod->func != NULL) {
+ if (devclass_equal(mtod->desc, what)) {
+ return (mtod->func);
+ }
+ mtod++;
+ }
+ return ((void *)&default_method);
+}
+
+const char *
+device_get_name(device_t dev)
+{
+ if (dev == NULL)
+ return (unknown_string);
+
+ return (dev->dev_module->driver->name);
+}
+
+static int
+device_allocate_softc(device_t dev)
+{
+ const struct module_data *mod;
+
+ mod = dev->dev_module;
+
+ if ((dev->dev_softc_alloc == 0) &&
+ (mod->driver->size != 0)) {
+ dev->dev_sc = malloc(mod->driver->size,
+ M_DEVBUF, M_WAITOK | M_ZERO);
+
+ if (dev->dev_sc == NULL)
+ return (ENOMEM);
+
+ dev->dev_softc_alloc = 1;
+ }
+ return (0);
+}
+
+int
+device_probe_and_attach(device_t dev)
+{
+ const struct module_data *mod;
+ const char *bus_name_parent;
+
+ bus_name_parent = device_get_name(device_get_parent(dev));
+
+ if (dev->dev_attached)
+ return (0); /* fail-safe */
+
+ if (dev->dev_fixed_class) {
+
+ mod = dev->dev_module;
+
+ if (DEVICE_PROBE(dev) <= 0) {
+
+ if (device_allocate_softc(dev) == 0) {
+
+ if (DEVICE_ATTACH(dev) == 0) {
+ /* success */
+ dev->dev_attached = 1;
+ return (0);
+ }
+ }
+ }
+ device_detach(dev);
+
+ goto error;
+ }
+ /*
+ * Else find a module for our device, if any
+ */
+
+ TAILQ_FOREACH(mod, &module_head, entry) {
+ if (devclass_equal(mod->bus_name, bus_name_parent)) {
+ if (devclass_create(mod->devclass_pp)) {
+ continue;
+ }
+ if (devclass_add_device(mod, dev)) {
+ continue;
+ }
+ if (DEVICE_PROBE(dev) <= 0) {
+
+ if (device_allocate_softc(dev) == 0) {
+
+ if (DEVICE_ATTACH(dev) == 0) {
+ /* success */
+ dev->dev_attached = 1;
+ return (0);
+ }
+ }
+ }
+ /* else try next driver */
+
+ device_detach(dev);
+ }
+ }
+
+error:
+ return (ENODEV);
+}
+
+int
+device_detach(device_t dev)
+{
+ const struct module_data *mod = dev->dev_module;
+ int error;
+
+ if (dev->dev_attached) {
+
+ error = DEVICE_DETACH(dev);
+ if (error) {
+ return error;
+ }
+ dev->dev_attached = 0;
+ }
+ device_set_softc(dev, NULL);
+
+ if (dev->dev_fixed_class == 0)
+ devclass_delete_device(mod, dev);
+
+ return (0);
+}
+
+void
+device_set_softc(device_t dev, void *softc)
+{
+ if (dev->dev_softc_alloc) {
+ free(dev->dev_sc, M_DEVBUF);
+ dev->dev_sc = NULL;
+ }
+ dev->dev_sc = softc;
+ dev->dev_softc_alloc = 0;
+}
+
+void *
+device_get_softc(device_t dev)
+{
+ if (dev == NULL)
+ return (NULL);
+
+ return (dev->dev_sc);
+}
+
+int
+device_is_attached(device_t dev)
+{
+ return (dev->dev_attached);
+}
+
+void
+device_set_desc(device_t dev, const char *desc)
+{
+ snprintf(dev->dev_desc, sizeof(dev->dev_desc), "%s", desc);
+}
+
+void
+device_set_desc_copy(device_t dev, const char *desc)
+{
+ device_set_desc(dev, desc);
+}
+
+void *
+devclass_get_softc(devclass_t dc, int unit)
+{
+ return (device_get_softc(devclass_get_device(dc, unit)));
+}
+
+int
+devclass_get_maxunit(devclass_t dc)
+{
+ int max_unit = 0;
+
+ if (dc) {
+ max_unit = DEVCLASS_MAXUNIT;
+ while (max_unit--) {
+ if (dc->dev_list[max_unit]) {
+ break;
+ }
+ }
+ max_unit++;
+ }
+ return (max_unit);
+}
+
+device_t
+devclass_get_device(devclass_t dc, int unit)
+{
+ return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ?
+ NULL : dc->dev_list[unit]);
+}
+
+devclass_t
+devclass_find(const char *classname)
+{
+ const struct module_data *mod;
+
+ TAILQ_FOREACH(mod, &module_head, entry) {
+ if (devclass_equal(mod->mod_name, classname))
+ return (mod->devclass_pp[0]);
+ }
+ return (NULL);
+}
+
+void
+module_register(void *data)
+{
+ struct module_data *mdata = data;
+
+ TAILQ_INSERT_TAIL(&module_head, mdata, entry);
+}
+
+/*------------------------------------------------------------------------*
+ * System startup
+ *------------------------------------------------------------------------*/
+
+static void
+sysinit_run(const void **ppdata)
+{
+ const struct sysinit *psys;
+
+ while ((psys = *ppdata) != NULL) {
+ (psys->func) (psys->data);
+ ppdata++;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * USB process API
+ *------------------------------------------------------------------------*/
+
+static int usb_do_process(struct usb_process *);
+static int usb_proc_level = -1;
+static struct mtx usb_proc_mtx;
+
+void
+usb_idle(void)
+{
+ int old_level = usb_proc_level;
+ int old_giant = Giant.owned;
+ int worked;
+
+ device_run_interrupts(usb_pci_root);
+
+ do {
+ worked = 0;
+ Giant.owned = 0;
+
+ while (++usb_proc_level < USB_PROC_MAX)
+ worked |= usb_do_process(usb_process + usb_proc_level);
+
+ usb_proc_level = old_level;
+ Giant.owned = old_giant;
+
+ } while (worked);
+}
+
+void
+usb_init(void)
+{
+ sysinit_run(sysinit_data);
+}
+
+void
+usb_uninit(void)
+{
+ sysinit_run(sysuninit_data);
+}
+
+static void
+usb_process_init_sub(struct usb_process *up)
+{
+ TAILQ_INIT(&up->up_qhead);
+
+ cv_init(&up->up_cv, "-");
+ cv_init(&up->up_drain, "usbdrain");
+
+ up->up_mtx = &usb_proc_mtx;
+}
+
+static void
+usb_process_init(void *arg)
+{
+ uint8_t x;
+
+ mtx_init(&usb_proc_mtx, "usb-proc-mtx", NULL, MTX_DEF | MTX_RECURSE);
+
+ for (x = 0; x != USB_PROC_MAX; x++)
+ usb_process_init_sub(&usb_process[x]);
+
+}
+SYSINIT(usb_process_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, usb_process_init, NULL);
+
+static int
+usb_do_process(struct usb_process *up)
+{
+ struct usb_proc_msg *pm;
+ int worked = 0;
+
+ mtx_lock(&usb_proc_mtx);
+
+repeat:
+ pm = TAILQ_FIRST(&up->up_qhead);
+
+ if (pm != NULL) {
+
+ worked = 1;
+
+ (pm->pm_callback) (pm);
+
+ if (pm == TAILQ_FIRST(&up->up_qhead)) {
+ /* nothing changed */
+ TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry);
+ pm->pm_qentry.tqe_prev = NULL;
+ }
+ goto repeat;
+ }
+ mtx_unlock(&usb_proc_mtx);
+
+ return (worked);
+}
+
+int
+usb_proc_create(struct usb_process *up, struct mtx *p_mtx,
+ const char *pmesg, uint8_t prio)
+{
+#define USB_PROC_OFFSET(a,b) \
+ ((int)(((long)&((struct usb_bus *)0)->a) - \
+ ((long)&((struct usb_bus *)0)->b)))
+
+ /* figure out which process we are creating */
+ switch ((int)((long)up - (long)p_mtx)) {
+ case USB_PROC_OFFSET(giant_callback_proc, bus_mtx):
+ up->up_ptr = (void *)(usb_process + 2);
+ break;
+ case USB_PROC_OFFSET(non_giant_callback_proc, bus_mtx):
+ up->up_ptr = (void *)(usb_process + 2);
+ break;
+ case USB_PROC_OFFSET(explore_proc, bus_mtx):
+ up->up_ptr = (void *)(usb_process + 0);
+ break;
+ case USB_PROC_OFFSET(control_xfer_proc, bus_mtx):
+ up->up_ptr = (void *)(usb_process + 1);
+ break;
+ default:
+ up->up_ptr = (void *)(usb_process + 1);
+ break;
+ }
+ return (0); /* success */
+}
+
+void
+usb_proc_free(struct usb_process *up)
+{
+ /* NOP */
+}
+
+void *
+usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1)
+{
+ struct usb_proc_msg *pm0 = _pm0;
+ struct usb_proc_msg *pm1 = _pm1;
+ struct usb_proc_msg *pm2;
+ usb_size_t d;
+ uint8_t t;
+
+ /* find the correct parent */
+ while (up->up_ptr != NULL)
+ up = (struct usb_process *)up->up_ptr;
+
+ t = 0;
+
+ if (pm0->pm_qentry.tqe_prev) {
+ t |= 1;
+ }
+ if (pm1->pm_qentry.tqe_prev) {
+ t |= 2;
+ }
+ if (t == 0) {
+ /*
+ * No entries are queued. Queue "pm0" and use the existing
+ * message number.
+ */
+ pm2 = pm0;
+ } else if (t == 1) {
+ /* Check if we need to increment the message number. */
+ if (pm0->pm_num == up->up_msg_num) {
+ up->up_msg_num++;
+ }
+ pm2 = pm1;
+ } else if (t == 2) {
+ /* Check if we need to increment the message number. */
+ if (pm1->pm_num == up->up_msg_num) {
+ up->up_msg_num++;
+ }
+ pm2 = pm0;
+ } else if (t == 3) {
+ /*
+ * Both entries are queued. Re-queue the entry closest to
+ * the end.
+ */
+ d = (pm1->pm_num - pm0->pm_num);
+
+ /* Check sign after subtraction */
+ if (d & 0x80000000) {
+ pm2 = pm0;
+ } else {
+ pm2 = pm1;
+ }
+
+ TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry);
+ } else {
+ pm2 = NULL; /* panic - should not happen */
+ }
+
+ /* Put message last on queue */
+
+ pm2->pm_num = up->up_msg_num;
+ TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry);
+
+ return (pm2);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_proc_is_gone
+ *
+ * Return values:
+ * 0: USB process is running
+ * Else: USB process is tearing down
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_proc_is_gone(struct usb_process *up)
+{
+ return (0);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_proc_mwait
+ *
+ * This function will return when the USB process message pointed to
+ * by "pm" is no longer on a queue. This function must be called
+ * having "usb_proc_mtx" locked.
+ *------------------------------------------------------------------------*/
+void
+usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1)
+{
+ struct usb_proc_msg *pm0 = _pm0;
+ struct usb_proc_msg *pm1 = _pm1;
+
+ /* find the correct parent */
+ while (up->up_ptr != NULL)
+ up = (struct usb_process *)up->up_ptr;
+
+ /* Just remove the messages from the queue. */
+ if (pm0->pm_qentry.tqe_prev) {
+ TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry);
+ pm0->pm_qentry.tqe_prev = NULL;
+ }
+ if (pm1->pm_qentry.tqe_prev) {
+ TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry);
+ pm1->pm_qentry.tqe_prev = NULL;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * SYSTEM attach
+ *------------------------------------------------------------------------*/
+
+static device_method_t pci_methods[] = {
+ DEVMETHOD_END
+};
+
+static driver_t pci_driver = {
+ .name = "pci",
+ .methods = pci_methods,
+};
+
+static devclass_t pci_devclass;
+
+DRIVER_MODULE(pci, pci, pci_driver, pci_devclass, 0, 0);
+
+static const char *usb_pci_devices[] = {
+#ifdef USB_PROBE_LIST
+ USB_PROBE_LIST
+#endif
+};
+
+#define USB_PCI_USB_MAX (sizeof(usb_pci_devices) / sizeof(void *))
+
+static device_t usb_pci_dev[USB_PCI_USB_MAX];
+
+static void
+usb_pci_mod_load(void *arg)
+{
+ uint32_t x;
+
+ usb_pci_root = device_add_child(NULL, "pci", -1);
+ if (usb_pci_root == NULL)
+ return;
+
+ for (x = 0; x != USB_PCI_USB_MAX; x++) {
+ usb_pci_dev[x] = device_add_child(usb_pci_root, usb_pci_devices[x], -1);
+ if (usb_pci_dev[x] == NULL)
+ continue;
+ if (device_probe_and_attach(usb_pci_dev[x])) {
+ device_printf(usb_pci_dev[x],
+ "WARNING: Probe and attach failed!\n");
+ }
+ }
+}
+SYSINIT(usb_pci_mod_load, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_load, 0);
+
+static void
+usb_pci_mod_unload(void *arg)
+{
+ uint32_t x;
+
+ for (x = 0; x != USB_PCI_USB_MAX; x++) {
+ if (usb_pci_dev[x]) {
+ device_detach(usb_pci_dev[x]);
+ device_delete_child(usb_pci_root, usb_pci_dev[x]);
+ }
+ }
+ if (usb_pci_root)
+ device_delete_child(NULL, usb_pci_root);
+}
+SYSUNINIT(usb_pci_mod_unload, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_unload, 0);
+
+/*------------------------------------------------------------------------*
+ * MALLOC API
+ *------------------------------------------------------------------------*/
+
+#define USB_POOL_ALIGN 8
+
+static uint8_t usb_pool[USB_POOL_SIZE] __aligned(USB_POOL_ALIGN);
+static uint32_t usb_pool_rem = USB_POOL_SIZE;
+static uint32_t usb_pool_entries;
+
+struct malloc_hdr {
+ TAILQ_ENTRY(malloc_hdr) entry;
+ uint32_t size;
+} __aligned(USB_POOL_ALIGN);
+
+static TAILQ_HEAD(, malloc_hdr) malloc_head =
+ TAILQ_HEAD_INITIALIZER(malloc_head);
+
+void *
+usb_malloc(unsigned long size)
+{
+ struct malloc_hdr *hdr;
+
+ size = (size + USB_POOL_ALIGN - 1) & ~(USB_POOL_ALIGN - 1);
+ size += sizeof(struct malloc_hdr);
+
+ TAILQ_FOREACH(hdr, &malloc_head, entry) {
+ if (hdr->size == size)
+ break;
+ }
+
+ if (hdr) {
+ printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
+ (int)usb_pool_entries, (int)usb_pool_rem, (int)size);
+
+ TAILQ_REMOVE(&malloc_head, hdr, entry);
+ memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
+ return (hdr + 1);
+ }
+ if (usb_pool_rem >= size) {
+ hdr = (void *)(usb_pool + USB_POOL_SIZE - usb_pool_rem);
+ hdr->size = size;
+
+ usb_pool_rem -= size;
+ usb_pool_entries++;
+
+ printf("MALLOC: Entries = %d; Remainder = %d; Size = %d\n",
+ (int)usb_pool_entries, (int)usb_pool_rem, (int)size);
+
+ memset(hdr + 1, 0, hdr->size - sizeof(*hdr));
+ return (hdr + 1);
+ }
+ return (NULL);
+}
+
+void
+usb_free(void *arg)
+{
+ struct malloc_hdr *hdr;
+
+ if (arg == NULL)
+ return;
+
+ hdr = arg;
+ hdr--;
+
+ TAILQ_INSERT_TAIL(&malloc_head, hdr, entry);
+}
+
+char *
+usb_strdup(const char *str)
+{
+ char *tmp;
+ int len;
+
+ len = 1 + strlen(str);
+
+ tmp = usb_malloc(len);
+ if (tmp == NULL)
+ return (NULL);
+
+ memcpy(tmp, str, len);
+ return (tmp);
+}
diff --git a/sys/boot/usb/bsd_kernel.h b/sys/boot/usb/bsd_kernel.h
new file mode 100644
index 0000000..4c94721
--- /dev/null
+++ b/sys/boot/usb/bsd_kernel.h
@@ -0,0 +1,458 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2011 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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.
+ */
+
+#ifndef _BSD_KERNEL_H_
+#define _BSD_KERNEL_H_
+
+#define _KERNEL
+#define __FreeBSD_version 1000000
+
+#include <sys/cdefs.h>
+#include <sys/queue.h>
+#include <sys/errno.h>
+
+#define isalpha(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z'))
+#define isdigit(x) ((x) >= '0' && (x) <= '9')
+#define panic(...) do { printf("USB PANIC: " __VA_ARGS__); while (1) ; } while (0)
+#define M_USB 0
+#define M_USBDEV 0
+#define USB_PROC_MAX 3
+#define SYSCTL_DECL(...)
+#define SYSCTL_NODE(name,...) struct { } name __used
+#define SYSCTL_INT(...)
+#define TUNABLE_INT(...)
+#define MALLOC_DECLARE(...)
+#define MALLOC_DEFINE(...)
+#define EVENTHANDLER_DECLARE(...)
+#define EVENTHANDLER_INVOKE(...)
+#define KASSERT(...)
+#define SCHEDULER_STOPPED(x) (0)
+#define PI_SWI(...) (0)
+#define UNIQ_NAME(x) x
+#define UNIQ_NAME_STR(x) #x
+#define DEVCLASS_MAXUNIT 32
+#define MOD_LOAD 1
+#define MOD_UNLOAD 2
+#define DEVMETHOD(what,func) { #what, (void *)&func }
+#define DEVMETHOD_END {0,0}
+#define DRIVER_MODULE(name, busname, driver, devclass, evh, arg) \
+ static struct module_data bsd_##name##_##busname##_driver_mod = { \
+ evh, arg, #busname, #name, #busname "/" #name, \
+ &driver, &devclass, { 0, 0 } }; \
+SYSINIT(bsd_##name##_##busname##_driver_mod, SI_SUB_DRIVERS, \
+ SI_ORDER_MIDDLE, module_register, \
+ &bsd_##name##_##busname##_driver_mod)
+#define SYSINIT(uniq, subs, order, _func, _data) \
+const struct sysinit UNIQ_NAME(sysinit_##uniq) = { \
+ .func = (_func), \
+ .data = __DECONST(void *, _data) \
+}; \
+SYSINIT_ENTRY(uniq##_entry, "sysinit", (subs), \
+ (order), "const struct sysinit", \
+ UNIQ_NAME_STR(sysinit_##uniq), "SYSINIT")
+
+#define SYSUNINIT(uniq, subs, order, _func, _data) \
+const struct sysinit UNIQ_NAME(sysuninit_##uniq) = { \
+ .func = (_func), \
+ .data = __DECONST(void *, _data) \
+}; \
+SYSINIT_ENTRY(uniq##_entry, "sysuninit", (subs), \
+ (order), "const struct sysuninit", \
+ UNIQ_NAME_STR(sysuninit_##uniq), "SYSUNINIT")
+#define MODULE_DEPEND(...)
+#define MODULE_VERSION(...)
+#define NULL ((void *)0)
+#define BUS_SPACE_BARRIER_READ 0x01
+#define BUS_SPACE_BARRIER_WRITE 0x02
+#define hz 1000
+#define PAGE_SIZE 4096
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define MTX_DEF 0
+#define MTX_RECURSE 0
+#define SX_DUPOK 0
+#define SX_NOWITNESS 0
+#define WITNESS_WARN(...)
+#define cold 0
+#define BUS_PROBE_GENERIC 0
+#define CALLOUT_RETURNUNLOCKED 0x1
+#define va_list __builtin_va_list
+#define va_size(type) __builtin_va_size(type)
+#define va_start(ap, last) __builtin_va_start(ap, last)
+#define va_end(ap) __builtin_va_end(ap)
+#define va_arg(ap, type) __builtin_va_arg((ap), type)
+#define DEVICE_ATTACH(dev, ...) \
+ (((device_attach_t *)(device_get_method(dev, "device_attach")))(dev,## __VA_ARGS__))
+#define DEVICE_DETACH(dev, ...) \
+ (((device_detach_t *)(device_get_method(dev, "device_detach")))(dev,## __VA_ARGS__))
+#define DEVICE_PROBE(dev, ...) \
+ (((device_probe_t *)(device_get_method(dev, "device_probe")))(dev,## __VA_ARGS__))
+#define DEVICE_RESUME(dev, ...) \
+ (((device_resume_t *)(device_get_method(dev, "device_resume")))(dev,## __VA_ARGS__))
+#define DEVICE_SHUTDOWN(dev, ...) \
+ (((device_shutdown_t *)(device_get_method(dev, "device_shutdown")))(dev,## __VA_ARGS__))
+#define DEVICE_SUSPEND(dev, ...) \
+ (((device_suspend_t *)(device_get_method(dev, "device_suspend")))(dev,## __VA_ARGS__))
+#define USB_HANDLE_REQUEST(dev, ...) \
+ (((usb_handle_request_t *)(device_get_method(dev, "usb_handle_request")))(dev,## __VA_ARGS__))
+#define USB_TAKE_CONTROLLER(dev, ...) \
+ (((usb_take_controller_t *)(device_get_method(dev, "usb_take_controller")))(dev,## __VA_ARGS__))
+
+enum {
+ SI_SUB_DUMMY = 0x0000000,
+ SI_SUB_LOCK = 0x1B00000,
+ SI_SUB_KLD = 0x2000000,
+ SI_SUB_DRIVERS = 0x3100000,
+ SI_SUB_PSEUDO = 0x7000000,
+ SI_SUB_KICK_SCHEDULER = 0xa000000,
+ SI_SUB_RUN_SCHEDULER = 0xfffffff
+};
+
+enum {
+ SI_ORDER_FIRST = 0x0000000,
+ SI_ORDER_SECOND = 0x0000001,
+ SI_ORDER_THIRD = 0x0000002,
+ SI_ORDER_FOURTH = 0x0000003,
+ SI_ORDER_MIDDLE = 0x1000000,
+ SI_ORDER_ANY = 0xfffffff /* last */
+};
+
+struct uio;
+struct thread;
+struct malloc_type;
+struct usb_process;
+
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+
+typedef unsigned int uint32_t;
+typedef signed int int32_t;
+
+typedef unsigned long long uint64_t;
+typedef signed long long int64_t;
+
+typedef unsigned long bus_addr_t;
+typedef unsigned long bus_size_t;
+
+typedef unsigned long size_t;
+typedef unsigned long u_long;
+
+typedef void *bus_dmamap_t;
+typedef void *bus_dma_tag_t;
+
+typedef void *bus_space_tag_t;
+typedef uint8_t *bus_space_handle_t;
+
+typedef uint16_t uid_t;
+typedef uint16_t gid_t;
+typedef uint16_t mode_t;
+
+typedef uint8_t *caddr_t;
+typedef unsigned long __uintptr_t;
+typedef unsigned long uintptr_t;
+
+/* SYSINIT API */
+
+#include <sysinit.h>
+
+struct sysinit {
+ void (*func) (void *arg);
+ void *data;
+};
+
+/* MUTEX API */
+
+struct mtx {
+ int owned;
+ struct mtx *parent;
+};
+
+#define mtx_assert(...) do { } while (0)
+void mtx_init(struct mtx *, const char *, const char *, int);
+void mtx_lock(struct mtx *);
+void mtx_unlock(struct mtx *);
+int mtx_owned(struct mtx *);
+void mtx_destroy(struct mtx *);
+
+extern struct mtx Giant;
+
+/* SX API */
+
+struct sx {
+ int owned;
+};
+
+#define sx_assert(...) do { } while (0)
+#define sx_init(...) sx_init_flags(__VA_ARGS__, 0)
+void sx_init_flags(struct sx *, const char *, int);
+void sx_destroy(struct sx *);
+void sx_xlock(struct sx *);
+void sx_xunlock(struct sx *);
+int sx_xlocked(struct sx *);
+
+/* CONDVAR API */
+
+struct cv {
+ int sleeping;
+};
+
+void cv_init(struct cv *, const char *desc);
+void cv_destroy(struct cv *);
+void cv_wait(struct cv *, struct mtx *);
+int cv_timedwait(struct cv *, struct mtx *, int);
+void cv_signal(struct cv *);
+void cv_broadcast(struct cv *);
+
+/* CALLOUT API */
+
+typedef void callout_fn_t (void *);
+
+extern volatile int ticks;
+
+struct callout {
+ LIST_ENTRY(callout) entry;
+ callout_fn_t *func;
+ void *arg;
+ struct mtx *mtx;
+ int flags;
+ int timeout;
+};
+
+void callout_init_mtx(struct callout *, struct mtx *, int);
+void callout_reset(struct callout *, int, callout_fn_t *, void *);
+void callout_stop(struct callout *);
+void callout_drain(struct callout *);
+int callout_pending(struct callout *);
+void callout_process(int timeout);
+
+/* DEVICE API */
+
+struct driver;
+struct devclass;
+struct device;
+struct module;
+struct module_data;
+
+typedef struct driver driver_t;
+typedef struct devclass *devclass_t;
+typedef struct device *device_t;
+typedef void (intr_fn_t)(void *arg);
+
+typedef int device_attach_t (device_t dev);
+typedef int device_detach_t (device_t dev);
+typedef int device_resume_t (device_t dev);
+typedef int device_shutdown_t (device_t dev);
+typedef int device_probe_t (device_t dev);
+typedef int device_suspend_t (device_t dev);
+
+typedef int bus_child_location_str_t (device_t parent, device_t child, char *buf, size_t buflen);
+typedef int bus_child_pnpinfo_str_t (device_t parent, device_t child, char *buf, size_t buflen);
+typedef void bus_driver_added_t (device_t dev, driver_t *driver);
+
+struct device_method {
+ const char *desc;
+ void *const func;
+};
+
+typedef struct device_method device_method_t;
+
+struct device {
+ TAILQ_HEAD(device_list, device) dev_children;
+ TAILQ_ENTRY(device) dev_link;
+
+ struct device *dev_parent;
+ const struct module_data *dev_module;
+ void *dev_sc;
+ void *dev_aux;
+ intr_fn_t *dev_irq_fn;
+ void *dev_irq_arg;
+
+ uint16_t dev_unit;
+
+ char dev_nameunit[64];
+ char dev_desc[64];
+
+ uint8_t dev_res_alloc:1;
+ uint8_t dev_quiet:1;
+ uint8_t dev_softc_set:1;
+ uint8_t dev_softc_alloc:1;
+ uint8_t dev_attached:1;
+ uint8_t dev_fixed_class:1;
+ uint8_t dev_unit_manual:1;
+};
+
+struct devclass {
+ device_t dev_list[DEVCLASS_MAXUNIT];
+};
+
+struct driver {
+ const char *name;
+ const struct device_method *methods;
+ uint32_t size;
+};
+
+struct module_data {
+ int (*callback) (struct module *, int, void *arg);
+ void *arg;
+ const char *bus_name;
+ const char *mod_name;
+ const char *long_name;
+ const struct driver *driver;
+ struct devclass **devclass_pp;
+ TAILQ_ENTRY(module_data) entry;
+};
+
+device_t device_get_parent(device_t dev);
+void *device_get_method(device_t dev, const char *what);
+const char *device_get_name(device_t dev);
+const char *device_get_nameunit(device_t dev);
+
+#define device_printf(dev, fmt,...) \
+ printf("%s: " fmt, device_get_nameunit(dev),## __VA_ARGS__)
+device_t device_add_child(device_t dev, const char *name, int unit);
+void device_quiet(device_t dev);
+void device_set_interrupt(device_t dev, intr_fn_t *fn, void *arg);
+void device_run_interrupts(device_t parent);
+void device_set_ivars(device_t dev, void *ivars);
+void *device_get_ivars(device_t dev);
+const char *device_get_desc(device_t dev);
+int device_probe_and_attach(device_t dev);
+int device_detach(device_t dev);
+void *device_get_softc(device_t dev);
+void device_set_softc(device_t dev, void *softc);
+int device_delete_child(device_t dev, device_t child);
+int device_delete_children(device_t dev);
+int device_is_attached(device_t dev);
+void device_set_desc(device_t dev, const char *desc);
+void device_set_desc_copy(device_t dev, const char *desc);
+int device_get_unit(device_t dev);
+void *devclass_get_softc(devclass_t dc, int unit);
+int devclass_get_maxunit(devclass_t dc);
+device_t devclass_get_device(devclass_t dc, int unit);
+devclass_t devclass_find(const char *classname);
+
+#define bus_get_dma_tag(...) (NULL)
+int bus_generic_detach(device_t dev);
+int bus_generic_resume(device_t dev);
+int bus_generic_shutdown(device_t dev);
+int bus_generic_suspend(device_t dev);
+int bus_generic_print_child(device_t dev, device_t child);
+void bus_generic_driver_added(device_t dev, driver_t *driver);
+
+/* BUS SPACE API */
+
+void bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint8_t data);
+void bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint16_t data);
+void bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint32_t data);
+
+uint8_t bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset);
+uint16_t bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset);
+uint32_t bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset);
+
+void bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint8_t *datap, bus_size_t count);
+void bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint16_t *datap, bus_size_t count);
+void bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint32_t *datap, bus_size_t count);
+
+void bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint8_t *datap, bus_size_t count);
+void bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint16_t *datap, bus_size_t count);
+void bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint32_t *datap, bus_size_t count);
+
+void bus_space_read_region_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint8_t *datap, bus_size_t count);
+void bus_space_write_region_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint8_t *datap, bus_size_t count);
+void bus_space_read_region_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint32_t *datap, bus_size_t count);
+void bus_space_write_region_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint32_t *datap, bus_size_t count);
+
+void bus_space_barrier(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, bus_size_t length, int flags);
+
+void module_register(void *);
+
+/* LIB-C */
+
+void *memset(void *, int, size_t len);
+void *memcpy(void *, const void *, size_t len);
+int printf(const char *,...) __printflike(1, 2);
+int snprintf(char *restrict str, size_t size, const char *restrict format,...) __printflike(3, 4);
+size_t strlen(const char *s);
+
+/* MALLOC API */
+
+#define malloc(s,x,f) usb_malloc(s)
+void *usb_malloc(size_t);
+
+#define free(p,x) usb_free(p)
+void usb_free(void *);
+
+#define strdup(p,x) usb_strdup(p)
+char *usb_strdup(const char *str);
+
+/* ENDIANNESS */
+
+/* Assume little endian */
+
+#define htole64(x) ((uint64_t)(x))
+#define le64toh(x) ((uint64_t)(x))
+
+#define htole32(x) ((uint32_t)(x))
+#define le32toh(x) ((uint32_t)(x))
+
+#define htole16(x) ((uint16_t)(x))
+#define le16toh(x) ((uint16_t)(x))
+
+#define be32toh(x) ((uint32_t)(x))
+#define htobe32(x) ((uint32_t)(x))
+
+/* USB */
+
+typedef int usb_handle_request_t (device_t dev, const void *req, void **pptr, uint16_t *plen, uint16_t offset, uint8_t *pstate);
+typedef int usb_take_controller_t (device_t dev);
+
+void usb_idle(void);
+void usb_init(void);
+void usb_uninit(void);
+
+/* set some defaults */
+
+#ifndef USB_POOL_SIZE
+#define USB_POOL_SIZE (1024*1024) /* 1 MByte */
+#endif
+
+int pause(const char *, int);
+void DELAY(unsigned int);
+
+/* OTHER */
+
+struct selinfo {
+};
+
+/* SYSTEM STARTUP API */
+
+extern const void *sysinit_data[];
+extern const void *sysuninit_data[];
+
+#endif /* _BSD_KERNEL_H_ */
diff --git a/sys/boot/usb/bsd_usbloader_test.c b/sys/boot/usb/bsd_usbloader_test.c
new file mode 100644
index 0000000..929e2e9
--- /dev/null
+++ b/sys/boot/usb/bsd_usbloader_test.c
@@ -0,0 +1,80 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <time.h>
+
+extern int usleep(int);
+extern void callout_process(int);
+extern void usb_idle(void);
+extern void usb_init(void);
+extern void usb_uninit(void);
+
+#define hz 1000
+
+void
+DELAY(unsigned int delay)
+{
+ usleep(delay);
+}
+
+int
+pause(const char *what, int timeout)
+{
+ if (timeout == 0)
+ timeout = 1;
+
+ usleep((1000000 / hz) * timeout);
+
+ return (0);
+}
+
+int
+main(int argc, char **argv)
+{
+ uint32_t time;
+
+ usb_init();
+
+ time = 0;
+
+ while (1) {
+
+ usb_idle();
+
+ usleep(1000);
+
+ if (++time >= (1000 / hz)) {
+ time = 0;
+ callout_process(1);
+ }
+ }
+
+ usb_uninit();
+
+ return (0);
+}
diff --git a/sys/boot/usb/tools/sysinit.c b/sys/boot/usb/tools/sysinit.c
new file mode 100644
index 0000000..b968fe0
--- /dev/null
+++ b/sys/boot/usb/tools/sysinit.c
@@ -0,0 +1,331 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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.
+ */
+
+/*
+ * This utility sorts sysinit structure entries in binary format and
+ * prints out the result in C-format.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <err.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sysexits.h>
+#include "sysinit.h"
+
+static int opt_R;
+static const char *input_f;
+static const char *output_f;
+static const char *struct_name;
+static const char *keyword;
+static struct sysinit_data **start;
+static struct sysinit_data **stop;
+
+static int input_file = -1;
+static int output_file = -1;
+
+static uint8_t *input_ptr;
+static uint32_t input_len;
+
+static uint32_t endian32;
+
+static char scratch_buf[4096];
+
+static int success;
+
+static void do_sysinit(void);
+
+/* the following function converts the numbers into host endian format */
+
+static uint32_t
+read32(uint32_t val)
+{
+ uint32_t temp;
+ uint32_t endian;
+
+ endian = endian32;
+ temp = 0;
+
+ while (val) {
+ temp |= (val & 0xF) << ((endian & 0xF) * 4);
+ endian >>= 4;
+ val >>= 4;
+ }
+ return (temp);
+}
+
+static void
+do_write(int fd, const char *buf)
+{
+ int len = strlen(buf);
+
+ if (write(fd, buf, len) != len)
+ err(EX_SOFTWARE, "Could not write to output file");
+}
+
+static void *
+do_malloc(int size)
+{
+ void *ptr;
+
+ ptr = malloc(size);
+ if (ptr == NULL)
+ errx(EX_SOFTWARE, "Could not allocate memory");
+ return (ptr);
+}
+
+static void
+usage(void)
+{
+ errx(EX_USAGE, "sysinit -i sysinit.bin -o sysinit_data.c \\\n"
+ "\t" "-k sysinit -s sysinit_data [ -R (reverse)]");
+}
+
+static void
+cleanup(void)
+{
+ if (output_file >= 0)
+ close(output_file);
+ if (input_file >= 0)
+ close(input_file);
+ if (success == 0) {
+ if (output_f)
+ unlink(output_f);
+ }
+}
+
+static int
+compare(const void *_pa, const void *_pb)
+{
+ const struct sysinit_data * const *pa = _pa;
+ const struct sysinit_data * const *pb = _pb;
+
+ if ((*pa)->dw_msb_value > (*pb)->dw_msb_value)
+ return (1);
+
+ if ((*pa)->dw_msb_value < (*pb)->dw_msb_value)
+ return (-1);
+
+ if ((*pa)->dw_lsb_value > (*pb)->dw_lsb_value)
+ return (1);
+
+ if ((*pa)->dw_lsb_value < (*pb)->dw_lsb_value)
+ return (-1);
+
+ return (0); /* equal */
+}
+
+static int
+compare_R(const void *_pa, const void *_pb)
+{
+ const struct sysinit_data * const *pa = _pa;
+ const struct sysinit_data * const *pb = _pb;
+
+ if ((*pa)->dw_msb_value > (*pb)->dw_msb_value)
+ return (-1);
+
+ if ((*pa)->dw_msb_value < (*pb)->dw_msb_value)
+ return (1);
+
+ if ((*pa)->dw_lsb_value > (*pb)->dw_lsb_value)
+ return (-1);
+
+ if ((*pa)->dw_lsb_value < (*pb)->dw_lsb_value)
+ return (1);
+
+ return (0); /* equal */
+}
+
+int
+main(int argc, char **argv)
+{
+ struct sysinit_data **sipp;
+ int c;
+ int entries;
+ off_t off;
+
+ while ((c = getopt(argc, argv, "k:s:i:o:Rh")) != -1) {
+ switch (c) {
+ case 'i':
+ input_f = optarg;
+ break;
+ case 'o':
+ output_f = optarg;
+ break;
+ case 'R':
+ opt_R = 1;
+ break;
+ case 'k':
+ keyword = optarg;
+ break;
+ case 's':
+ struct_name = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (input_f == NULL || output_f == NULL ||
+ struct_name == NULL || keyword == NULL)
+ usage();
+
+ atexit(&cleanup);
+
+ cleanup();
+
+ input_file = open(input_f, O_RDONLY);
+ if (input_file < 0)
+ err(EX_SOFTWARE, "Could not open input file: %s", input_f);
+
+ output_file = open(output_f, O_TRUNC | O_CREAT | O_RDWR, 0600);
+ if (output_file < 0)
+ err(EX_SOFTWARE, "Could not open output file: %s", output_f);
+
+ off = lseek(input_file, 0, SEEK_END);
+
+ input_ptr = do_malloc(off);
+ input_len = off;
+
+ if (input_len % (uint32_t)sizeof(struct sysinit_data)) {
+ errx(EX_SOFTWARE, "Input file size is not divisible by %u",
+ (unsigned int)sizeof(struct sysinit_data));
+ }
+ off = lseek(input_file, 0, SEEK_SET);
+ if (off < 0)
+ err(EX_SOFTWARE, "Could not seek to start of input file");
+
+ if (read(input_file, input_ptr, input_len) != input_len)
+ err(EX_SOFTWARE, "Could not read input file");
+
+ entries = input_len / (uint32_t)sizeof(struct sysinit_data);
+
+ start = do_malloc(sizeof(void *) * entries);
+ stop = start + entries;
+
+ for (c = 0; c != entries; c++)
+ start[c] = &((struct sysinit_data *)input_ptr)[c];
+
+ if (start != stop)
+ endian32 = (*start)->dw_endian32;
+
+ /* switch all fields to host endian order */
+ for (sipp = start; sipp < stop; sipp++) {
+ (*sipp)->dw_lsb_value = read32((*sipp)->dw_lsb_value);
+ (*sipp)->dw_msb_value = read32((*sipp)->dw_msb_value);
+ (*sipp)->dw_file_line = read32((*sipp)->dw_file_line);
+ }
+
+ if (opt_R == 0) {
+ /* sort entries, rising numerical order */
+ qsort(start, entries, sizeof(void *), &compare);
+ } else {
+ /* sort entries, falling numerical order */
+ qsort(start, entries, sizeof(void *), &compare_R);
+ }
+
+ /* safe all strings */
+ for (sipp = start; sipp < stop; sipp++) {
+ (*sipp)->b_keyword_name[sizeof((*sipp)->b_keyword_name) - 1] = 0;
+ (*sipp)->b_global_type[sizeof((*sipp)->b_global_type) - 1] = 0;
+ (*sipp)->b_global_name[sizeof((*sipp)->b_global_name) - 1] = 0;
+ (*sipp)->b_file_name[sizeof((*sipp)->b_file_name) - 1] = 0;
+ (*sipp)->b_debug_info[sizeof((*sipp)->b_debug_info) - 1] = 0;
+ }
+
+ if (strcmp(keyword, "sysinit") == 0)
+ do_sysinit();
+ else if (strcmp(keyword, "sysuninit") == 0)
+ do_sysinit();
+ else
+ errx(EX_USAGE, "Unknown keyword '%s'", keyword);
+
+ success = 1;
+
+ return (0);
+}
+
+static void
+do_sysinit(void)
+{
+ struct sysinit_data **sipp;
+ int c;
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "/*\n"
+ " * This file was automatically generated.\n"
+ " * Please do not edit.\n"
+ " */\n\n");
+
+ /* write out externals */
+ for (c = 0, sipp = start; sipp < stop; c++, sipp++) {
+ if (strcmp((const char *)(*sipp)->b_keyword_name, keyword))
+ continue;
+ if ((*sipp)->dw_msb_value == 0)
+ continue;
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "/* #%04u: %s entry at %s:%u */\n",
+ c, (*sipp)->b_debug_info, (*sipp)->b_file_name,
+ (unsigned int)(*sipp)->dw_file_line);
+
+ do_write(output_file, scratch_buf);
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "extern %s %s;\n\n", (*sipp)->b_global_type,
+ (*sipp)->b_global_name);
+
+ do_write(output_file, scratch_buf);
+ }
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "const void *%s[] = {\n", struct_name);
+
+ do_write(output_file, scratch_buf);
+
+ /* write out actual table */
+ for (c = 0, sipp = start; sipp < stop; c++, sipp++) {
+ if (strcmp((const char *)(*sipp)->b_keyword_name, keyword))
+ continue;
+ if ((*sipp)->dw_msb_value == 0)
+ continue;
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "\t&%s, /* #%04u */\n",
+ (*sipp)->b_global_name, (unsigned int)c);
+
+ do_write(output_file, scratch_buf);
+ }
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "\t(const void *)0\n"
+ "};\n");
+
+ do_write(output_file, scratch_buf);
+}
diff --git a/sys/boot/usb/tools/sysinit.h b/sys/boot/usb/tools/sysinit.h
new file mode 100644
index 0000000..a7a450e
--- /dev/null
+++ b/sys/boot/usb/tools/sysinit.h
@@ -0,0 +1,57 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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.
+ */
+
+#ifndef _SYSINIT_H_
+#define _SYSINIT_H_
+
+struct sysinit_data {
+ uint8_t b_keyword_name[64];
+ uint8_t b_debug_info[128];
+ uint8_t b_global_type[128];
+ uint8_t b_global_name[128];
+ uint8_t b_file_name[256];
+ uint32_t dw_endian32;
+ uint32_t dw_msb_value; /* must be non-zero, else entry is skipped */
+ uint32_t dw_lsb_value;
+ uint32_t dw_file_line;
+} __attribute__((__packed__));
+
+#define SYSINIT_ENTRY(uniq, keyword, msb, lsb, g_type, g_name, debug) \
+ static const struct sysinit_data sysinit_##uniq \
+ __attribute__((__section__(".debug.sysinit"), \
+ __used__, __aligned__(1))) = { \
+ .b_keyword_name = { keyword }, \
+ .b_debug_info = { debug }, \
+ .b_global_type = { g_type }, \
+ .b_global_name = { g_name }, \
+ .b_file_name = { __FILE__ }, \
+ .dw_endian32 = 0x76543210U, \
+ .dw_msb_value = (msb), \
+ .dw_lsb_value = (lsb), \
+ .dw_file_line = __LINE__ \
+}
+
+#endif /* _SYSINIT_H_ */
diff --git a/sys/boot/usb/usb_busdma_loader.c b/sys/boot/usb/usb_busdma_loader.c
new file mode 100644
index 0000000..c7d1ecb
--- /dev/null
+++ b/sys/boot/usb/usb_busdma_loader.c
@@ -0,0 +1,619 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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 <bsd_global.h>
+
+#if USB_HAVE_BUSDMA
+static void usb_pc_common_mem_cb(struct usb_page_cache *pc,
+ void *vaddr, uint32_t length);
+#endif
+
+/*------------------------------------------------------------------------*
+ * usbd_get_page - lookup DMA-able memory for the given offset
+ *
+ * NOTE: Only call this function when the "page_cache" structure has
+ * been properly initialized !
+ *------------------------------------------------------------------------*/
+void
+usbd_get_page(struct usb_page_cache *pc, usb_frlength_t offset,
+ struct usb_page_search *res)
+{
+#if USB_HAVE_BUSDMA
+ struct usb_page *page;
+
+ if (pc->page_start) {
+
+ /* Case 1 - something has been loaded into DMA */
+
+ if (pc->buffer) {
+
+ /* Case 1a - Kernel Virtual Address */
+
+ res->buffer = USB_ADD_BYTES(pc->buffer, offset);
+ }
+ offset += pc->page_offset_buf;
+
+ /* compute destination page */
+
+ page = pc->page_start;
+
+ if (pc->ismultiseg) {
+
+ page += (offset / USB_PAGE_SIZE);
+
+ offset %= USB_PAGE_SIZE;
+
+ res->length = USB_PAGE_SIZE - offset;
+ res->physaddr = page->physaddr + offset;
+ } else {
+ res->length = (usb_size_t)-1;
+ res->physaddr = page->physaddr + offset;
+ }
+ if (!pc->buffer) {
+
+ /* Case 1b - Non Kernel Virtual Address */
+
+ res->buffer = USB_ADD_BYTES(page->buffer, offset);
+ }
+ return;
+ }
+#endif
+ /* Case 2 - Plain PIO */
+
+ res->buffer = USB_ADD_BYTES(pc->buffer, offset);
+ res->length = (usb_size_t)-1;
+#if USB_HAVE_BUSDMA
+ res->physaddr = 0;
+#endif
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_copy_in - copy directly to DMA-able memory
+ *------------------------------------------------------------------------*/
+void
+usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
+ const void *ptr, usb_frlength_t len)
+{
+ struct usb_page_search buf_res;
+
+ while (len != 0) {
+
+ usbd_get_page(cache, offset, &buf_res);
+
+ if (buf_res.length > len) {
+ buf_res.length = len;
+ }
+ memcpy(buf_res.buffer, ptr, buf_res.length);
+
+ offset += buf_res.length;
+ len -= buf_res.length;
+ ptr = USB_ADD_BYTES(ptr, buf_res.length);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_copy_out - copy directly from DMA-able memory
+ *------------------------------------------------------------------------*/
+void
+usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset,
+ void *ptr, usb_frlength_t len)
+{
+ struct usb_page_search res;
+
+ while (len != 0) {
+
+ usbd_get_page(cache, offset, &res);
+
+ if (res.length > len) {
+ res.length = len;
+ }
+ memcpy(ptr, res.buffer, res.length);
+
+ offset += res.length;
+ len -= res.length;
+ ptr = USB_ADD_BYTES(ptr, res.length);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_frame_zero - zero DMA-able memory
+ *------------------------------------------------------------------------*/
+void
+usbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset,
+ usb_frlength_t len)
+{
+ struct usb_page_search res;
+
+ while (len != 0) {
+
+ usbd_get_page(cache, offset, &res);
+
+ if (res.length > len) {
+ res.length = len;
+ }
+ memset(res.buffer, 0, res.length);
+
+ offset += res.length;
+ len -= res.length;
+ }
+}
+
+#if USB_HAVE_BUSDMA
+
+/*------------------------------------------------------------------------*
+ * usb_pc_common_mem_cb - BUS-DMA callback function
+ *------------------------------------------------------------------------*/
+static void
+usb_pc_common_mem_cb(struct usb_page_cache *pc,
+ void *vaddr, uint32_t length)
+{
+ struct usb_page *pg;
+ usb_size_t rem;
+ bus_size_t off;
+ bus_addr_t phys = (uintptr_t)vaddr; /* XXX */
+ uint32_t nseg;
+
+ if (length == 0)
+ nseg = 1;
+ else
+ nseg = ((length + USB_PAGE_SIZE - 1) / USB_PAGE_SIZE);
+
+ pg = pc->page_start;
+ pg->physaddr = phys & ~(USB_PAGE_SIZE - 1);
+ rem = phys & (USB_PAGE_SIZE - 1);
+ pc->page_offset_buf = rem;
+ pc->page_offset_end += rem;
+ length += rem;
+
+ for (off = USB_PAGE_SIZE; off < length; off += USB_PAGE_SIZE) {
+ pg++;
+ pg->physaddr = (phys + off) & ~(USB_PAGE_SIZE - 1);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_alloc_mem - allocate DMA'able memory
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg,
+ usb_size_t size, usb_size_t align)
+{
+ void *ptr;
+ uint32_t rem;
+
+ /* allocate zeroed memory */
+
+ if (align != 1) {
+ ptr = usb_malloc(size + align);
+ if (ptr == NULL)
+ goto error;
+
+ rem = (-((uintptr_t)ptr)) & (align - 1);
+ } else {
+ ptr = usb_malloc(size);
+ if (ptr == NULL)
+ goto error;
+ rem = 0;
+ }
+
+ /* setup page cache */
+ pc->buffer = ((uint8_t *)ptr) + rem;
+ pc->page_start = pg;
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = size;
+ pc->map = NULL;
+ pc->tag = ptr;
+ pc->ismultiseg = (align == 1);
+
+ /* compute physical address */
+ usb_pc_common_mem_cb(pc, ptr, size);
+
+ usb_pc_cpu_flush(pc);
+ return (0);
+
+error:
+ /* reset most of the page cache */
+ pc->buffer = NULL;
+ pc->page_start = NULL;
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = 0;
+ pc->map = NULL;
+ pc->tag = NULL;
+ return (1);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_free_mem - free DMA memory
+ *
+ * This function is NULL safe.
+ *------------------------------------------------------------------------*/
+void
+usb_pc_free_mem(struct usb_page_cache *pc)
+{
+ if (pc != NULL && pc->buffer != NULL) {
+ usb_free(pc->tag);
+ pc->buffer = NULL;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_load_mem - load virtual memory into DMA
+ *
+ * Return values:
+ * 0: Success
+ * Else: Error
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size, uint8_t sync)
+{
+ /* setup page cache */
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = size;
+ pc->ismultiseg = 1;
+
+ mtx_assert(pc->tag_parent->mtx, MA_OWNED);
+
+ if (size > 0) {
+ /* compute physical address */
+ usb_pc_common_mem_cb(pc, pc->buffer, size);
+ }
+ if (sync == 0) {
+ /*
+ * Call callback so that refcount is decremented
+ * properly:
+ */
+ pc->tag_parent->dma_error = 0;
+ (pc->tag_parent->func) (pc->tag_parent);
+ }
+ return (0);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_cpu_invalidate - invalidate CPU cache
+ *------------------------------------------------------------------------*/
+void
+usb_pc_cpu_invalidate(struct usb_page_cache *pc)
+{
+ if (pc->page_offset_end == pc->page_offset_buf) {
+ /* nothing has been loaded into this page cache! */
+ return;
+ }
+ /* NOP */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_cpu_flush - flush CPU cache
+ *------------------------------------------------------------------------*/
+void
+usb_pc_cpu_flush(struct usb_page_cache *pc)
+{
+ if (pc->page_offset_end == pc->page_offset_buf) {
+ /* nothing has been loaded into this page cache! */
+ return;
+ }
+ /* NOP */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_dmamap_create - create a DMA map
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_pc_dmamap_create(struct usb_page_cache *pc, usb_size_t size)
+{
+ return (0); /* NOP, success */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_dmamap_destroy
+ *
+ * This function is NULL safe.
+ *------------------------------------------------------------------------*/
+void
+usb_pc_dmamap_destroy(struct usb_page_cache *pc)
+{
+ /* NOP */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_dma_tag_setup - initialise USB DMA tags
+ *------------------------------------------------------------------------*/
+void
+usb_dma_tag_setup(struct usb_dma_parent_tag *udpt,
+ struct usb_dma_tag *udt, bus_dma_tag_t dmat,
+ struct mtx *mtx, usb_dma_callback_t *func,
+ uint8_t ndmabits, uint8_t nudt)
+{
+ memset(udpt, 0, sizeof(*udpt));
+
+ /* sanity checking */
+ if ((nudt == 0) ||
+ (ndmabits == 0) ||
+ (mtx == NULL)) {
+ /* something is corrupt */
+ return;
+ }
+ /* initialise condition variable */
+ cv_init(udpt->cv, "USB DMA CV");
+
+ /* store some information */
+ udpt->mtx = mtx;
+ udpt->func = func;
+ udpt->tag = dmat;
+ udpt->utag_first = udt;
+ udpt->utag_max = nudt;
+ udpt->dma_bits = ndmabits;
+
+ while (nudt--) {
+ memset(udt, 0, sizeof(*udt));
+ udt->tag_parent = udpt;
+ udt++;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bus_tag_unsetup - factored out code
+ *------------------------------------------------------------------------*/
+void
+usb_dma_tag_unsetup(struct usb_dma_parent_tag *udpt)
+{
+ struct usb_dma_tag *udt;
+ uint8_t nudt;
+
+ udt = udpt->utag_first;
+ nudt = udpt->utag_max;
+
+ while (nudt--) {
+ udt->align = 0;
+ udt++;
+ }
+
+ if (udpt->utag_max) {
+ /* destroy the condition variable */
+ cv_destroy(udpt->cv);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_work_loop
+ *
+ * This function handles loading of virtual buffers into DMA and is
+ * only called when "dma_refcount" is zero.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_work_loop(struct usb_xfer_queue *pq)
+{
+ struct usb_xfer_root *info;
+ struct usb_xfer *xfer;
+ usb_frcount_t nframes;
+
+ xfer = pq->curr;
+ info = xfer->xroot;
+
+ mtx_assert(info->xfer_mtx, MA_OWNED);
+
+ if (xfer->error) {
+ /* some error happened */
+ USB_BUS_LOCK(info->bus);
+ usbd_transfer_done(xfer, 0);
+ USB_BUS_UNLOCK(info->bus);
+ return;
+ }
+ if (!xfer->flags_int.bdma_setup) {
+ struct usb_page *pg;
+ usb_frlength_t frlength_0;
+ uint8_t isread;
+
+ xfer->flags_int.bdma_setup = 1;
+
+ /* reset BUS-DMA load state */
+
+ info->dma_error = 0;
+
+ if (xfer->flags_int.isochronous_xfr) {
+ /* only one frame buffer */
+ nframes = 1;
+ frlength_0 = xfer->sumlen;
+ } else {
+ /* can be multiple frame buffers */
+ nframes = xfer->nframes;
+ frlength_0 = xfer->frlengths[0];
+ }
+
+ /*
+ * Set DMA direction first. This is needed to
+ * select the correct cache invalidate and cache
+ * flush operations.
+ */
+ isread = USB_GET_DATA_ISREAD(xfer);
+ pg = xfer->dma_page_ptr;
+
+ if (xfer->flags_int.control_xfr &&
+ xfer->flags_int.control_hdr) {
+ /* special case */
+ if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
+ /* The device controller writes to memory */
+ xfer->frbuffers[0].isread = 1;
+ } else {
+ /* The host controller reads from memory */
+ xfer->frbuffers[0].isread = 0;
+ }
+ } else {
+ /* default case */
+ xfer->frbuffers[0].isread = isread;
+ }
+
+ /*
+ * Setup the "page_start" pointer which points to an array of
+ * USB pages where information about the physical address of a
+ * page will be stored. Also initialise the "isread" field of
+ * the USB page caches.
+ */
+ xfer->frbuffers[0].page_start = pg;
+
+ info->dma_nframes = nframes;
+ info->dma_currframe = 0;
+ info->dma_frlength_0 = frlength_0;
+
+ pg += (frlength_0 / USB_PAGE_SIZE);
+ pg += 2;
+
+ while (--nframes > 0) {
+ xfer->frbuffers[nframes].isread = isread;
+ xfer->frbuffers[nframes].page_start = pg;
+
+ pg += (xfer->frlengths[nframes] / USB_PAGE_SIZE);
+ pg += 2;
+ }
+
+ }
+ if (info->dma_error) {
+ USB_BUS_LOCK(info->bus);
+ usbd_transfer_done(xfer, USB_ERR_DMA_LOAD_FAILED);
+ USB_BUS_UNLOCK(info->bus);
+ return;
+ }
+ if (info->dma_currframe != info->dma_nframes) {
+
+ if (info->dma_currframe == 0) {
+ /* special case */
+ usb_pc_load_mem(xfer->frbuffers,
+ info->dma_frlength_0, 0);
+ } else {
+ /* default case */
+ nframes = info->dma_currframe;
+ usb_pc_load_mem(xfer->frbuffers + nframes,
+ xfer->frlengths[nframes], 0);
+ }
+
+ /* advance frame index */
+ info->dma_currframe++;
+
+ return;
+ }
+ /* go ahead */
+ usb_bdma_pre_sync(xfer);
+
+ /* start loading next USB transfer, if any */
+ usb_command_wrapper(pq, NULL);
+
+ /* finally start the hardware */
+ usbd_pipe_enter(xfer);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_done_event
+ *
+ * This function is called when the BUS-DMA has loaded virtual memory
+ * into DMA, if any.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_done_event(struct usb_dma_parent_tag *udpt)
+{
+ struct usb_xfer_root *info;
+
+ info = USB_DMATAG_TO_XROOT(udpt);
+
+ mtx_assert(info->xfer_mtx, MA_OWNED);
+
+ /* copy error */
+ info->dma_error = udpt->dma_error;
+
+ /* enter workloop again */
+ usb_command_wrapper(&info->dma_q,
+ info->dma_q.curr);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_pre_sync
+ *
+ * This function handles DMA synchronisation that must be done before
+ * an USB transfer is started.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_pre_sync(struct usb_xfer *xfer)
+{
+ struct usb_page_cache *pc;
+ usb_frcount_t nframes;
+
+ if (xfer->flags_int.isochronous_xfr) {
+ /* only one frame buffer */
+ nframes = 1;
+ } else {
+ /* can be multiple frame buffers */
+ nframes = xfer->nframes;
+ }
+
+ pc = xfer->frbuffers;
+
+ while (nframes--) {
+
+ if (pc->isread) {
+ usb_pc_cpu_invalidate(pc);
+ } else {
+ usb_pc_cpu_flush(pc);
+ }
+ pc++;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_post_sync
+ *
+ * This function handles DMA synchronisation that must be done after
+ * an USB transfer is complete.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_post_sync(struct usb_xfer *xfer)
+{
+ struct usb_page_cache *pc;
+ usb_frcount_t nframes;
+
+ if (xfer->flags_int.isochronous_xfr) {
+ /* only one frame buffer */
+ nframes = 1;
+ } else {
+ /* can be multiple frame buffers */
+ nframes = xfer->nframes;
+ }
+
+ pc = xfer->frbuffers;
+
+ while (nframes--) {
+ if (pc->isread) {
+ usb_pc_cpu_invalidate(pc);
+ }
+ pc++;
+ }
+}
+#endif
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index ac5eba7..768332e 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -2257,11 +2257,31 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
*/
mtx_unlock(&softc->ctl_lock);
- if (cmd == CTL_ENABLE_PORT)
+ if (cmd == CTL_ENABLE_PORT) {
+ struct ctl_lun *lun;
+
+ STAILQ_FOREACH(lun, &softc->lun_list,
+ links) {
+ fe->lun_enable(fe->targ_lun_arg,
+ lun->target,
+ lun->lun);
+ }
+
ctl_frontend_online(fe);
- else if (cmd == CTL_DISABLE_PORT)
+ } else if (cmd == CTL_DISABLE_PORT) {
+ struct ctl_lun *lun;
+
ctl_frontend_offline(fe);
+ STAILQ_FOREACH(lun, &softc->lun_list,
+ links) {
+ fe->lun_disable(
+ fe->targ_lun_arg,
+ lun->target,
+ lun->lun);
+ }
+ }
+
mtx_lock(&softc->ctl_lock);
if (cmd == CTL_SET_PORT_WWNS)
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index 59357123..5dc20e5 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <cam/ctl/ctl_error.h>
typedef enum {
+ CTLFE_CCB_DEFAULT = 0x00,
CTLFE_CCB_WAITING = 0x01
} ctlfe_ccb_types;
@@ -304,10 +305,7 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
case AC_PATH_REGISTERED: {
struct ctl_frontend *fe;
struct ctlfe_softc *bus_softc;
- struct ctlfe_lun_softc *lun_softc;
- struct cam_path *path;
struct ccb_pathinq *cpi;
- cam_status status;
int retval;
cpi = (struct ccb_pathinq *)arg;
@@ -330,7 +328,6 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
M_NOWAIT | M_ZERO);
if (ccb == NULL) {
printf("%s: unable to malloc CCB!\n", __func__);
- xpt_free_path(path);
return;
}
xpt_setup_ccb(&ccb->ccb_h, cpi->ccb_h.path,
@@ -448,44 +445,31 @@ ctlfeasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
mtx_unlock(&ctlfe_list_mtx);
}
- status = xpt_create_path(&path, /*periph*/ NULL,
- bus_softc->path_id,CAM_TARGET_WILDCARD,
- CAM_LUN_WILDCARD);
- if (status != CAM_REQ_CMP) {
- printf("%s: unable to create path for wildcard "
- "periph\n", __func__);
- break;
- }
- lun_softc = malloc(sizeof(*lun_softc), M_CTLFE,
- M_NOWAIT | M_ZERO);
- if (lun_softc == NULL) {
- xpt_print(path, "%s: unable to allocate softc for "
- "wildcard periph\n", __func__);
- xpt_free_path(path);
- break;
+ break;
+ }
+ case AC_PATH_DEREGISTERED: {
+ struct ctlfe_softc *softc = NULL;
+
+ mtx_lock(&ctlfe_list_mtx);
+ STAILQ_FOREACH(softc, &ctlfe_softc_list, links) {
+ if (softc->path_id == xpt_path_path_id(path)) {
+ STAILQ_REMOVE(&ctlfe_softc_list, softc,
+ ctlfe_softc, links);
+ break;
+ }
}
+ mtx_unlock(&ctlfe_list_mtx);
- lun_softc->parent_softc = bus_softc;
- lun_softc->flags |= CTLFE_LUN_WILDCARD;
-
- status = cam_periph_alloc(ctlferegister,
- ctlfeoninvalidate,
- ctlfecleanup,
- ctlfestart,
- "ctl",
- CAM_PERIPH_BIO,
- path,
- ctlfeasync,
- 0,
- lun_softc);
-
- xpt_free_path(path);
-
+ if (softc != NULL) {
+ /*
+ * XXX KDM are we certain at this point that there
+ * are no outstanding commands for this frontend?
+ */
+ ctl_frontend_deregister(&softc->fe);
+ free(softc, M_CTLFE);
+ }
break;
}
- case AC_PATH_DEREGISTERED:
- /* ctl_frontend_deregister() */
- break;
case AC_CONTRACT: {
struct ac_contract *ac;
@@ -699,11 +683,14 @@ ctlfecleanup(struct cam_periph *periph)
softc = (struct ctlfe_lun_softc *)periph->softc;
bus_softc = softc->parent_softc;
- STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc,links);
+ STAILQ_REMOVE(&bus_softc->lun_softc_list, softc, ctlfe_lun_softc, links);
/*
* XXX KDM is there anything else that needs to be done here?
*/
+
+ callout_stop(&softc->dma_callout);
+
free(softc, M_CTLFE);
}
@@ -717,6 +704,8 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
softc->ccbs_alloced++;
+ start_ccb->ccb_h.ccb_type = CTLFE_CCB_DEFAULT;
+
ccb_h = TAILQ_FIRST(&softc->work_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
panic("shouldn't get to the CCB waiting case!");
@@ -857,8 +846,6 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
/*
* Datamove call, we need to setup the S/G list.
- * If we pass in a S/G list, the isp(4) driver at
- * least expects physical/bus addresses.
*/
cmd_info = (struct ctlfe_lun_cmd_info *)
@@ -933,12 +920,13 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
int *ti;
/*
- * XXX KDM this is a temporary hack. The
- * isp(4) driver can't deal with S/G lists
- * with virtual pointers, so we need to
- * go through and send down one virtual
- * pointer at a time.
+ * If we have more S/G list pointers than
+ * will fit in the available storage in the
+ * cmd_info structure inside the ctl_io header,
+ * then we need to send down the pointers
+ * one element at a time.
*/
+
sglist = (struct ctl_sg_entry *)
io->scsiio.kern_data_ptr;
ti = &cmd_info->cur_transfer_index;
@@ -1405,13 +1393,15 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
break;
default:
/*
- * XXX KDM the isp(4) driver doesn't really
- * seem to send errors back for data
- * transfers that I can tell. There is one
- * case where it'll send CAM_REQ_CMP_ERR,
- * but probably not that many more cases.
- * So set a generic data phase error here,
- * like the SXP driver sets.
+ * XXX KDM we probably need to figure out a
+ * standard set of errors that the SIM
+ * drivers should return in the event of a
+ * data transfer failure. A data phase
+ * error will at least point the user to a
+ * data transfer error of some sort.
+ * Hopefully the SIM printed out some
+ * additional information to give the user
+ * a clue what happened.
*/
io->io_hdr.port_status = 0xbad1;
ctl_set_data_phase_error(&io->scsiio);
@@ -1689,20 +1679,22 @@ ctlfe_onoffline(void *arg, int online)
sim = bus_softc->sim;
- CAM_SIM_LOCK(sim);
+ mtx_assert(sim->mtx, MA_OWNED);
+
status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP) {
printf("%s: unable to create path!\n", __func__);
- CAM_SIM_UNLOCK(sim);
return;
}
- CAM_SIM_UNLOCK(sim);
-
- ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP, M_WAITOK | M_ZERO);
+ ccb = (union ccb *)malloc(sizeof(*ccb), M_TEMP, M_NOWAIT | M_ZERO);
+ if (ccb == NULL) {
+ printf("%s: unable to malloc CCB!\n", __func__);
+ xpt_free_path(path);
+ return;
+ }
xpt_setup_ccb(&ccb->ccb_h, path, CAM_PRIORITY_NONE);
-
/*
* Copan WWN format:
*
@@ -1720,11 +1712,9 @@ ctlfe_onoffline(void *arg, int online)
ccb->ccb_h.func_code = XPT_GET_SIM_KNOB;
- CAM_SIM_LOCK(sim);
xpt_action(ccb);
- CAM_SIM_UNLOCK(sim);
if ((ccb->knob.xport_specific.valid & KNOB_VALID_ADDRESS) != 0){
#ifdef RANDOM_WWNN
@@ -1822,9 +1812,6 @@ ctlfe_onoffline(void *arg, int online)
else
ccb->knob.xport_specific.fc.role = KNOB_ROLE_NONE;
-
- CAM_SIM_LOCK(sim);
-
xpt_action(ccb);
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
@@ -1841,8 +1828,6 @@ ctlfe_onoffline(void *arg, int online)
xpt_free_path(path);
- CAM_SIM_UNLOCK(sim);
-
free(ccb, M_TEMP);
return;
@@ -1851,13 +1836,111 @@ ctlfe_onoffline(void *arg, int online)
static void
ctlfe_online(void *arg)
{
+ struct ctlfe_softc *bus_softc;
+ struct cam_path *path;
+ cam_status status;
+ struct ctlfe_lun_softc *lun_softc;
+ struct cam_sim *sim;
+
+ bus_softc = (struct ctlfe_softc *)arg;
+ sim = bus_softc->sim;
+
+ CAM_SIM_LOCK(sim);
+
+ /*
+ * Create the wildcard LUN before bringing the port online.
+ */
+ status = xpt_create_path(&path, /*periph*/ NULL,
+ bus_softc->path_id, CAM_TARGET_WILDCARD,
+ CAM_LUN_WILDCARD);
+ if (status != CAM_REQ_CMP) {
+ printf("%s: unable to create path for wildcard periph\n",
+ __func__);
+ CAM_SIM_UNLOCK(sim);
+ return;
+ }
+
+ lun_softc = malloc(sizeof(*lun_softc), M_CTLFE,
+ M_NOWAIT | M_ZERO);
+ if (lun_softc == NULL) {
+ xpt_print(path, "%s: unable to allocate softc for "
+ "wildcard periph\n", __func__);
+ xpt_free_path(path);
+ CAM_SIM_UNLOCK(sim);
+ return;
+ }
+
+ lun_softc->parent_softc = bus_softc;
+ lun_softc->flags |= CTLFE_LUN_WILDCARD;
+
+ STAILQ_INSERT_TAIL(&bus_softc->lun_softc_list, lun_softc, links);
+
+
+ status = cam_periph_alloc(ctlferegister,
+ ctlfeoninvalidate,
+ ctlfecleanup,
+ ctlfestart,
+ "ctl",
+ CAM_PERIPH_BIO,
+ path,
+ ctlfeasync,
+ 0,
+ lun_softc);
+
+ if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ const struct cam_status_entry *entry;
+
+ entry = cam_fetch_status_entry(status);
+
+ printf("%s: CAM error %s (%#x) returned from "
+ "cam_periph_alloc()\n", __func__, (entry != NULL) ?
+ entry->status_text : "Unknown", status);
+ }
+
+ xpt_free_path(path);
+
ctlfe_onoffline(arg, /*online*/ 1);
+
+ CAM_SIM_UNLOCK(sim);
}
static void
ctlfe_offline(void *arg)
{
+ struct ctlfe_softc *bus_softc;
+ struct cam_path *path;
+ cam_status status;
+ struct cam_periph *periph;
+ struct cam_sim *sim;
+
+ bus_softc = (struct ctlfe_softc *)arg;
+ sim = bus_softc->sim;
+
+ CAM_SIM_LOCK(sim);
+
ctlfe_onoffline(arg, /*online*/ 0);
+
+ /*
+ * Disable the wildcard LUN for this port now that we have taken
+ * the port offline.
+ */
+ status = xpt_create_path(&path, /*periph*/ NULL,
+ bus_softc->path_id, CAM_TARGET_WILDCARD,
+ CAM_LUN_WILDCARD);
+ if (status != CAM_REQ_CMP) {
+ CAM_SIM_UNLOCK(sim);
+ printf("%s: unable to create path for wildcard periph\n",
+ __func__);
+ return;
+ }
+
+
+ if ((periph = cam_periph_find(path, "ctl")) != NULL)
+ cam_periph_invalidate(periph);
+
+ xpt_free_path(path);
+
+ CAM_SIM_UNLOCK(sim);
}
static int
@@ -1890,21 +1973,17 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
bus_softc = (struct ctlfe_softc *)arg;
sim = bus_softc->sim;
- CAM_SIM_LOCK(sim);
-
- status = xpt_create_path(&path, /*periph*/ NULL, bus_softc->path_id,
- targ_id.id, lun_id);
+ status = xpt_create_path_unlocked(&path, /*periph*/ NULL,
+ bus_softc->path_id,
+ targ_id.id, lun_id);
/* XXX KDM need some way to return status to CTL here? */
if (status != CAM_REQ_CMP) {
printf("%s: could not create path, status %#x\n", __func__,
status);
- CAM_SIM_UNLOCK(sim);
return (1);
}
- CAM_SIM_UNLOCK(sim);
softc = malloc(sizeof(*softc), M_CTLFE, M_WAITOK | M_ZERO);
-
CAM_SIM_LOCK(sim);
periph = cam_periph_find(path, "ctl");
if (periph != NULL) {
@@ -1937,23 +2016,20 @@ ctlfe_lun_enable(void *arg, struct ctl_id targ_id, int lun_id)
}
/*
- * XXX KDM we disable LUN removal here. The problem is that the isp(4)
- * driver doesn't currently handle LUN removal properly. We need to keep
- * enough state here at the peripheral level even after LUNs have been
- * removed inside CTL.
- *
- * Once the isp(4) driver is fixed, this can be re-enabled.
+ * This will get called when the user removes a LUN to disable that LUN
+ * on every bus that is attached to CTL.
*/
static int
ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
{
-#ifdef NOTYET
struct ctlfe_softc *softc;
struct ctlfe_lun_softc *lun_softc;
+ struct cam_sim *sim;
softc = (struct ctlfe_softc *)arg;
+ sim = softc->sim;
- mtx_lock(softc->sim->mtx);
+ CAM_SIM_LOCK(sim);
STAILQ_FOREACH(lun_softc, &softc->lun_softc_list, links) {
struct cam_path *path;
@@ -1965,7 +2041,7 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
}
}
if (lun_softc == NULL) {
- mtx_unlock(softc->sim->mtx);
+ CAM_SIM_UNLOCK(sim);
printf("%s: can't find target %d lun %d\n", __func__,
targ_id.id, lun_id);
return (1);
@@ -1973,8 +2049,7 @@ ctlfe_lun_disable(void *arg, struct ctl_id targ_id, int lun_id)
cam_periph_invalidate(lun_softc->periph);
- mtx_unlock(softc->sim->mtx);
-#endif
+ CAM_SIM_UNLOCK(sim);
return (0);
}
@@ -2139,7 +2214,7 @@ ctlfe_datamove_done(union ctl_io *io)
sim = xpt_path_sim(ccb->ccb_h.path);
- mtx_lock(sim->mtx);
+ CAM_SIM_LOCK(sim);
periph = xpt_path_periph(ccb->ccb_h.path);
@@ -2186,7 +2261,7 @@ ctlfe_datamove_done(union ctl_io *io)
xpt_schedule(periph, /*priority*/ 1);
}
- mtx_unlock(sim->mtx);
+ CAM_SIM_UNLOCK(sim);
}
static void
diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c
index a37ae19..9dac9c0 100644
--- a/sys/cam/scsi/scsi_all.c
+++ b/sys/cam/scsi/scsi_all.c
@@ -3071,16 +3071,15 @@ scsi_error_action(struct ccb_scsiio *csio, struct scsi_inquiry_data *inq_data,
SSQ_PRINT_SENSE;
}
}
- if ((action & SS_MASK) >= SS_START &&
- (sense_flags & SF_NO_RECOVERY)) {
- action &= ~SS_MASK;
- action |= SS_FAIL;
- } else if ((action & SS_MASK) == SS_RETRY &&
- (sense_flags & SF_NO_RETRY)) {
- action &= ~SS_MASK;
- action |= SS_FAIL;
- }
-
+ }
+ if ((action & SS_MASK) >= SS_START &&
+ (sense_flags & SF_NO_RECOVERY)) {
+ action &= ~SS_MASK;
+ action |= SS_FAIL;
+ } else if ((action & SS_MASK) == SS_RETRY &&
+ (sense_flags & SF_NO_RETRY)) {
+ action &= ~SS_MASK;
+ action |= SS_FAIL;
}
if ((sense_flags & SF_PRINT_ALWAYS) != 0)
action |= SSQ_PRINT_SENSE;
@@ -3140,7 +3139,7 @@ scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string, size_t len)
*cdb_string = '\0';
for (i = 0; i < cdb_len; i++)
snprintf(cdb_string + strlen(cdb_string),
- len - strlen(cdb_string), "%x ", cdb_ptr[i]);
+ len - strlen(cdb_string), "%02hhx ", cdb_ptr[i]);
return(cdb_string);
}
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
index d5d7156..a7c4c5b 100644
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -581,7 +581,7 @@ cdasync(void *callback_arg, u_int32_t code,
if (softc->state == CD_STATE_NORMAL && !softc->tur) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
softc->tur = 1;
- xpt_schedule(periph, CAM_PRIORITY_DEV);
+ xpt_schedule(periph, CAM_PRIORITY_NORMAL);
}
}
/* FALLTHROUGH */
@@ -1612,9 +1612,11 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
xpt_action(start_ccb);
}
- if (bp != NULL || softc->tur) {
+ if (bp != NULL || softc->tur ||
+ periph->immediate_priority != CAM_PRIORITY_NONE) {
/* Have more work to do, so ensure we stay scheduled */
- xpt_schedule(periph, CAM_PRIORITY_NORMAL);
+ xpt_schedule(periph, min(CAM_PRIORITY_NORMAL,
+ periph->immediate_priority));
}
break;
}
@@ -3293,10 +3295,11 @@ cdmediapoll(void *arg)
if (softc->flags & CD_FLAG_CHANGER)
return;
- if (softc->state == CD_STATE_NORMAL && !softc->tur) {
+ if (softc->state == CD_STATE_NORMAL && !softc->tur &&
+ softc->outstanding_cmds == 0) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
softc->tur = 1;
- xpt_schedule(periph, CAM_PRIORITY_DEV);
+ xpt_schedule(periph, CAM_PRIORITY_NORMAL);
}
}
/* Queue us up again */
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index adda9c9..7854215 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -863,6 +863,8 @@ static void daasync(void *callback_arg, u_int32_t code,
static void dasysctlinit(void *context, int pending);
static int dacmdsizesysctl(SYSCTL_HANDLER_ARGS);
static int dadeletemethodsysctl(SYSCTL_HANDLER_ARGS);
+static int dadeletemethodset(struct da_softc *softc,
+ da_delete_methods delete_method);
static periph_ctor_t daregister;
static periph_dtor_t dacleanup;
static periph_start_t dastart;
@@ -1079,6 +1081,9 @@ daschedule(struct cam_periph *periph)
struct da_softc *softc = (struct da_softc *)periph->softc;
uint32_t prio;
+ if (softc->state != DA_STATE_NORMAL)
+ return;
+
/* Check if cam_periph_getccb() was called. */
prio = periph->immediate_priority;
@@ -1423,10 +1428,10 @@ daasync(void *callback_arg, u_int32_t code,
}
case AC_SCSI_AEN:
softc = (struct da_softc *)periph->softc;
- if (softc->state == DA_STATE_NORMAL && !softc->tur) {
+ if (!softc->tur) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
softc->tur = 1;
- xpt_schedule(periph, CAM_PRIORITY_DEV);
+ daschedule(periph);
}
}
/* FALLTHROUGH */
@@ -1489,7 +1494,7 @@ dasysctlinit(void *context, int pending)
*/
SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
OID_AUTO, "delete_method", CTLTYPE_STRING | CTLFLAG_RW,
- &softc->delete_method, 0, dadeletemethodsysctl, "A",
+ softc, 0, dadeletemethodsysctl, "A",
"BIO_DELETE execution method");
SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
@@ -1566,14 +1571,33 @@ dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
}
static int
+dadeletemethodset(struct da_softc *softc, da_delete_methods delete_method)
+{
+
+ if (delete_method < 0 || delete_method > DA_DELETE_MAX)
+ return (EINVAL);
+
+ softc->delete_method = delete_method;
+
+ if (softc->delete_method > DA_DELETE_DISABLE)
+ softc->disk->d_flags |= DISKFLAG_CANDELETE;
+ else
+ softc->disk->d_flags &= ~DISKFLAG_CANDELETE;
+
+ return (0);
+}
+
+static int
dadeletemethodsysctl(SYSCTL_HANDLER_ARGS)
{
char buf[16];
- int error;
const char *p;
- int i, value;
+ struct da_softc *softc;
+ int i, error, value;
- value = *(int *)arg1;
+ softc = (struct da_softc *)arg1;
+
+ value = softc->delete_method;
if (value < 0 || value > DA_DELETE_MAX)
p = "UNKNOWN";
else
@@ -1585,8 +1609,7 @@ dadeletemethodsysctl(SYSCTL_HANDLER_ARGS)
for (i = 0; i <= DA_DELETE_MAX; i++) {
if (strcmp(buf, da_delete_method_names[i]) != 0)
continue;
- *(int *)arg1 = i;
- return (0);
+ return dadeletemethodset(softc, i);
}
return (EINVAL);
}
@@ -2014,7 +2037,6 @@ out:
}
case DA_STATE_PROBE:
{
- struct ccb_scsiio *csio;
struct scsi_read_capacity_data *rcap;
rcap = (struct scsi_read_capacity_data *)
@@ -2024,9 +2046,8 @@ out:
/* da_free_periph??? */
break;
}
- csio = &start_ccb->csio;
- scsi_read_capacity(csio,
- /*retries*/4,
+ scsi_read_capacity(&start_ccb->csio,
+ /*retries*/da_retry_count,
dadone,
MSG_SIMPLE_Q_TAG,
rcap,
@@ -2039,7 +2060,6 @@ out:
}
case DA_STATE_PROBE2:
{
- struct ccb_scsiio *csio;
struct scsi_read_capacity_data_long *rcaplong;
rcaplong = (struct scsi_read_capacity_data_long *)
@@ -2049,9 +2069,8 @@ out:
/* da_free_periph??? */
break;
}
- csio = &start_ccb->csio;
- scsi_read_capacity_16(csio,
- /*retries*/ 4,
+ scsi_read_capacity_16(&start_ccb->csio,
+ /*retries*/ da_retry_count,
/*cbfcnp*/ dadone,
/*tag_action*/ MSG_SIMPLE_Q_TAG,
/*lba*/ 0,
@@ -2060,7 +2079,7 @@ out:
/*rcap_buf*/ (uint8_t *)rcaplong,
/*rcap_buf_len*/ sizeof(*rcaplong),
/*sense_len*/ SSD_FULL_SIZE,
- /*timeout*/ 60000);
+ /*timeout*/ da_default_timeout * 1000);
start_ccb->ccb_h.ccb_bp = NULL;
start_ccb->ccb_h.ccb_state = DA_CCB_PROBE2;
xpt_action(start_ccb);
@@ -2086,24 +2105,24 @@ cmd6workaround(union ccb *ccb)
if (softc->delete_method == DA_DELETE_UNMAP) {
xpt_print(ccb->ccb_h.path, "UNMAP is not supported, "
"switching to WRITE SAME(16) with UNMAP.\n");
- softc->delete_method = DA_DELETE_WS16;
+ dadeletemethodset(softc, DA_DELETE_WS16);
} else if (softc->delete_method == DA_DELETE_WS16) {
xpt_print(ccb->ccb_h.path,
"WRITE SAME(16) with UNMAP is not supported, "
"disabling BIO_DELETE.\n");
- softc->delete_method = DA_DELETE_DISABLE;
+ dadeletemethodset(softc, DA_DELETE_DISABLE);
} else if (softc->delete_method == DA_DELETE_WS10) {
xpt_print(ccb->ccb_h.path,
"WRITE SAME(10) with UNMAP is not supported, "
"disabling BIO_DELETE.\n");
- softc->delete_method = DA_DELETE_DISABLE;
+ dadeletemethodset(softc, DA_DELETE_DISABLE);
} else if (softc->delete_method == DA_DELETE_ZERO) {
xpt_print(ccb->ccb_h.path,
"WRITE SAME(10) is not supported, "
"disabling BIO_DELETE.\n");
- softc->delete_method = DA_DELETE_DISABLE;
+ dadeletemethodset(softc, DA_DELETE_DISABLE);
} else
- softc->delete_method = DA_DELETE_DISABLE;
+ dadeletemethodset(softc, DA_DELETE_DISABLE);
while ((bp = bioq_takefirst(&softc->delete_run_queue))
!= NULL)
bioq_disksort(&softc->delete_queue, bp);
@@ -2152,6 +2171,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
struct da_softc *softc;
struct ccb_scsiio *csio;
u_int32_t priority;
+ da_ccb_state state;
softc = (struct da_softc *)periph->softc;
priority = done_ccb->ccb_h.pinfo.priority;
@@ -2159,7 +2179,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n"));
csio = &done_ccb->csio;
- switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
+ state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK;
+ switch (state) {
case DA_CCB_BUFFER_IO:
case DA_CCB_DELETE:
{
@@ -2257,8 +2278,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
softc->outstanding_cmds);
}
- if ((csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) ==
- DA_CCB_DELETE) {
+ if (state == DA_CCB_DELETE) {
while ((bp1 = bioq_takefirst(&softc->delete_run_queue))
!= NULL) {
bp1->bio_resid = bp->bio_resid;
@@ -2284,7 +2304,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
rdcap = NULL;
rcaplong = NULL;
- if (softc->state == DA_STATE_PROBE)
+ if (state == DA_CCB_PROBE)
rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
else
rcaplong = (struct scsi_read_capacity_data_long *)
@@ -2297,7 +2317,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
u_int lbppbe; /* LB per physical block exponent. */
u_int lalba; /* Lowest aligned LBA. */
- if (softc->state == DA_STATE_PROBE) {
+ if (state == DA_CCB_PROBE) {
block_size = scsi_4btoul(rdcap->length);
maxsector = scsi_4btoul(rdcap->addr);
lbppbe = 0;
@@ -2349,7 +2369,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
rcaplong, sizeof(*rcaplong));
if ((lalba & SRC16_LBPME_A)
&& softc->delete_method == DA_DELETE_NONE)
- softc->delete_method = DA_DELETE_UNMAP;
+ dadeletemethodset(softc, DA_DELETE_UNMAP);
dp = &softc->params;
snprintf(announce_buf, sizeof(announce_buf),
"%juMB (%ju %u byte sectors: %dH %dS/T "
@@ -2410,7 +2430,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* If we tried READ CAPACITY(16) and failed,
* fallback to READ CAPACITY(10).
*/
- if ((softc->state == DA_STATE_PROBE2) &&
+ if ((state == DA_CCB_PROBE2) &&
(softc->flags & DA_FLAG_CAN_RC16) &&
(((csio->ccb_h.status & CAM_STATUS_MASK) ==
CAM_REQ_INVALID) ||
@@ -2490,7 +2510,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* operation.
*/
xpt_release_ccb(done_ccb);
- softc->state = DA_STATE_NORMAL;
+ softc->state = DA_STATE_NORMAL;
+ daschedule(periph);
wakeup(&softc->disk->d_mediasize);
if ((softc->flags & DA_FLAG_PROBED) == 0) {
softc->flags |= DA_FLAG_PROBED;
@@ -2615,7 +2636,7 @@ damediapoll(void *arg)
struct cam_periph *periph = arg;
struct da_softc *softc = periph->softc;
- if (softc->state == DA_STATE_NORMAL && !softc->tur) {
+ if (!softc->tur && softc->outstanding_cmds == 0) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
softc->tur = 1;
daschedule(periph);
diff --git a/sys/cam/scsi/scsi_enc_ses.c b/sys/cam/scsi/scsi_enc_ses.c
index 79e96db..c4a8c49 100644
--- a/sys/cam/scsi/scsi_enc_ses.c
+++ b/sys/cam/scsi/scsi_enc_ses.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/ctype.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/lock.h>
@@ -1053,10 +1054,11 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
{
struct ccb_dev_advinfo cdai;
ses_setphyspath_callback_args_t args;
- int ret;
+ int i, ret;
struct sbuf sb;
uint8_t *devid, *elmaddr;
ses_element_t *elmpriv;
+ const char *c;
ret = EIO;
devid = NULL;
@@ -1099,7 +1101,13 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
elmpriv = elm->elm_private;
if (elmpriv->descr != NULL && elmpriv->descr_len > 0) {
sbuf_cat(&sb, "/elmdesc@");
- sbuf_bcat(&sb, elmpriv->descr, elmpriv->descr_len);
+ for (i = 0, c = elmpriv->descr; i < elmpriv->descr_len;
+ i++, c++) {
+ if (!isprint(*c) || isspace(*c) || *c == '/')
+ sbuf_putc(&sb, '_');
+ else
+ sbuf_putc(&sb, *c);
+ }
}
sbuf_finish(&sb);
diff --git a/sys/cddl/compat/opensolaris/sys/kmem.h b/sys/cddl/compat/opensolaris/sys/kmem.h
index 428badf..ba8b42d 100644
--- a/sys/cddl/compat/opensolaris/sys/kmem.h
+++ b/sys/cddl/compat/opensolaris/sys/kmem.h
@@ -45,7 +45,6 @@ MALLOC_DECLARE(M_SOLARIS);
#define KM_SLEEP M_WAITOK
#define KM_PUSHPAGE M_WAITOK
#define KM_NOSLEEP M_NOWAIT
-#define KM_ZERO M_ZERO
#define KM_NODEBUG M_NODUMP
#define KMC_NODEBUG UMA_ZONE_NODUMP
#define KMC_NOTOUCH 0
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
index ef3d0f4..885af95 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
@@ -89,12 +89,13 @@ ddt_object_destroy(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
spa_t *spa = ddt->ddt_spa;
objset_t *os = ddt->ddt_os;
uint64_t *objectp = &ddt->ddt_object[type][class];
+ uint64_t count;
char name[DDT_NAMELEN];
ddt_object_name(ddt, type, class, name);
ASSERT(*objectp != 0);
- ASSERT(ddt_object_count(ddt, type, class) == 0);
+ VERIFY(ddt_object_count(ddt, type, class, &count) == 0 && count == 0);
ASSERT(ddt_histogram_empty(&ddt->ddt_histogram[type][class]));
VERIFY(zap_remove(os, DMU_POOL_DIRECTORY_OBJECT, name, tx) == 0);
VERIFY(zap_remove(os, spa->spa_ddt_stat_object, name, tx) == 0);
@@ -109,6 +110,7 @@ ddt_object_load(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
{
ddt_object_t *ddo = &ddt->ddt_object_stats[type][class];
dmu_object_info_t doi;
+ uint64_t count;
char name[DDT_NAMELEN];
int error;
@@ -129,7 +131,11 @@ ddt_object_load(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
*/
VERIFY(ddt_object_info(ddt, type, class, &doi) == 0);
- ddo->ddo_count = ddt_object_count(ddt, type, class);
+ error = ddt_object_count(ddt, type, class, &count);
+ if (error)
+ return error;
+
+ ddo->ddo_count = count;
ddo->ddo_dspace = doi.doi_physical_blocks_512 << 9;
ddo->ddo_mspace = doi.doi_fill_count * doi.doi_data_block_size;
@@ -143,6 +149,7 @@ ddt_object_sync(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
{
ddt_object_t *ddo = &ddt->ddt_object_stats[type][class];
dmu_object_info_t doi;
+ uint64_t count;
char name[DDT_NAMELEN];
ddt_object_name(ddt, type, class, name);
@@ -155,8 +162,9 @@ ddt_object_sync(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
* Cache DDT statistics; this is the only time they'll change.
*/
VERIFY(ddt_object_info(ddt, type, class, &doi) == 0);
+ VERIFY(ddt_object_count(ddt, type, class, &count) == 0);
- ddo->ddo_count = ddt_object_count(ddt, type, class);
+ ddo->ddo_count = count;
ddo->ddo_dspace = doi.doi_physical_blocks_512 << 9;
ddo->ddo_mspace = doi.doi_fill_count * doi.doi_data_block_size;
}
@@ -213,13 +221,13 @@ ddt_object_walk(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
ddt->ddt_object[type][class], dde, walk));
}
-uint64_t
-ddt_object_count(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
+int
+ddt_object_count(ddt_t *ddt, enum ddt_type type, enum ddt_class class, uint64_t *count)
{
ASSERT(ddt_object_exists(ddt, type, class));
return (ddt_ops[type]->ddt_op_count(ddt->ddt_os,
- ddt->ddt_object[type][class]));
+ ddt->ddt_object[type][class], count));
}
int
@@ -1079,11 +1087,13 @@ ddt_sync_table(ddt_t *ddt, dmu_tx_t *tx, uint64_t txg)
}
for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
- uint64_t count = 0;
+ uint64_t add, count = 0;
for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
if (ddt_object_exists(ddt, type, class)) {
ddt_object_sync(ddt, type, class, tx);
- count += ddt_object_count(ddt, type, class);
+ VERIFY(ddt_object_count(ddt, type, class,
+ &add) == 0);
+ count += add;
}
}
for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c
index 6812aa3..f42b4dd 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c
@@ -133,14 +133,11 @@ ddt_zap_walk(objset_t *os, uint64_t object, ddt_entry_t *dde, uint64_t *walk)
return (error);
}
-static uint64_t
-ddt_zap_count(objset_t *os, uint64_t object)
+static int
+ddt_zap_count(objset_t *os, uint64_t object, uint64_t *count)
{
- uint64_t count = 0;
-
- VERIFY(zap_count(os, object, &count) == 0);
- return (count);
+ return (zap_count(os, object, count));
}
const ddt_ops_t ddt_zap_ops = {
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 4392ea8..8da3f0e 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
@@ -3792,9 +3792,8 @@ spa_generate_rootconf(const char *name)
/*
* Multi-vdev root pool configuration discovery is not supported yet.
*/
- nchildren = 0;
- VERIFY(nvlist_lookup_uint64(best_cfg, ZPOOL_CONFIG_VDEV_CHILDREN,
- &nchildren) == 0);
+ nchildren = 1;
+ nvlist_lookup_uint64(best_cfg, ZPOOL_CONFIG_VDEV_CHILDREN, &nchildren);
holes = NULL;
nvlist_lookup_uint64_array(best_cfg, ZPOOL_CONFIG_HOLE_ARRAY,
&holes, &nholes);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h
index 405622b..5d9747b 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h
@@ -163,7 +163,7 @@ typedef struct ddt_ops {
dmu_tx_t *tx);
int (*ddt_op_walk)(objset_t *os, uint64_t object, ddt_entry_t *dde,
uint64_t *walk);
- uint64_t (*ddt_op_count)(objset_t *os, uint64_t object);
+ int (*ddt_op_count)(objset_t *os, uint64_t object, uint64_t *count);
} ddt_ops_t;
#define DDT_NAMELEN 80
@@ -172,8 +172,8 @@ extern void ddt_object_name(ddt_t *ddt, enum ddt_type type,
enum ddt_class cls, char *name);
extern int ddt_object_walk(ddt_t *ddt, enum ddt_type type,
enum ddt_class cls, uint64_t *walk, ddt_entry_t *dde);
-extern uint64_t ddt_object_count(ddt_t *ddt, enum ddt_type type,
- enum ddt_class cls);
+extern int ddt_object_count(ddt_t *ddt, enum ddt_type type,
+ enum ddt_class class, uint64_t *count);
extern int ddt_object_info(ddt_t *ddt, enum ddt_type type,
enum ddt_class cls, dmu_object_info_t *);
extern boolean_t ddt_object_exists(ddt_t *ddt, enum ddt_type type,
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 dac619b..ce0579c 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org>
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <sys/zfs_context.h>
@@ -33,7 +33,76 @@
#include <sys/callb.h>
/*
- * Pool-wide transaction groups.
+ * ZFS Transaction Groups
+ * ----------------------
+ *
+ * ZFS transaction groups are, as the name implies, groups of transactions
+ * that act on persistent state. ZFS asserts consistency at the granularity of
+ * these transaction groups. Each successive transaction group (txg) is
+ * assigned a 64-bit consecutive identifier. There are three active
+ * transaction group states: open, quiescing, or syncing. At any given time,
+ * there may be an active txg associated with each state; each active txg may
+ * either be processing, or blocked waiting to enter the next state. There may
+ * be up to three active txgs, and there is always a txg in the open state
+ * (though it may be blocked waiting to enter the quiescing state). In broad
+ * strokes, transactions — operations that change in-memory structures — are
+ * accepted into the txg in the open state, and are completed while the txg is
+ * in the open or quiescing states. The accumulated changes are written to
+ * disk in the syncing state.
+ *
+ * Open
+ *
+ * When a new txg becomes active, it first enters the open state. New
+ * transactions — updates to in-memory structures — are assigned to the
+ * currently open txg. There is always a txg in the open state so that ZFS can
+ * accept new changes (though the txg may refuse new changes if it has hit
+ * some limit). ZFS advances the open txg to the next state for a variety of
+ * reasons such as it hitting a time or size threshold, or the execution of an
+ * administrative action that must be completed in the syncing state.
+ *
+ * Quiescing
+ *
+ * After a txg exits the open state, it enters the quiescing state. The
+ * quiescing state is intended to provide a buffer between accepting new
+ * transactions in the open state and writing them out to stable storage in
+ * the syncing state. While quiescing, transactions can continue their
+ * operation without delaying either of the other states. Typically, a txg is
+ * in the quiescing state very briefly since the operations are bounded by
+ * software latencies rather than, say, slower I/O latencies. After all
+ * transactions complete, the txg is ready to enter the next state.
+ *
+ * Syncing
+ *
+ * In the syncing state, the in-memory state built up during the open and (to
+ * a lesser degree) the quiescing states is written to stable storage. The
+ * process of writing out modified data can, in turn modify more data. For
+ * example when we write new blocks, we need to allocate space for them; those
+ * allocations modify metadata (space maps)... which themselves must be
+ * written to stable storage. During the sync state, ZFS iterates, writing out
+ * data until it converges and all in-memory changes have been written out.
+ * The first such pass is the largest as it encompasses all the modified user
+ * data (as opposed to filesystem metadata). Subsequent passes typically have
+ * far less data to write as they consist exclusively of filesystem metadata.
+ *
+ * To ensure convergence, after a certain number of passes ZFS begins
+ * overwriting locations on stable storage that had been allocated earlier in
+ * the syncing state (and subsequently freed). ZFS usually allocates new
+ * blocks to optimize for large, continuous, writes. For the syncing state to
+ * converge however it must complete a pass where no new blocks are allocated
+ * since each allocation requires a modification of persistent metadata.
+ * Further, to hasten convergence, after a prescribed number of passes, ZFS
+ * also defers frees, and stops compressing.
+ *
+ * In addition to writing out user data, we must also execute synctasks during
+ * the syncing context. A synctask is the mechanism by which some
+ * administrative activities work such as creating and destroying snapshots or
+ * datasets. Note that when a synctask is initiated it enters the open txg,
+ * and ZFS then pushes that txg as quickly as possible to completion of the
+ * syncing state in order to reduce the latency of the administrative
+ * activity. To complete the syncing state, ZFS writes out a new uberblock,
+ * the root of the tree of blocks that comprise all state stored on the ZFS
+ * pool. Finally, if there is a quiesced txg waiting, we signal that it can
+ * now transition to the syncing state.
*/
static void txg_sync_thread(void *arg);
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 e4157df..6fa9cea 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
@@ -5536,6 +5536,7 @@ static moduledata_t zfs_mod = {
0
};
DECLARE_MODULE(zfsctrl, zfs_mod, SI_SUB_VFS, SI_ORDER_ANY);
+MODULE_VERSION(zfsctrl, 1);
MODULE_DEPEND(zfsctrl, opensolaris, 1, 1, 1);
MODULE_DEPEND(zfsctrl, krpc, 1, 1, 1);
MODULE_DEPEND(zfsctrl, acl_nfs4, 1, 1, 1);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
index 72c22dc..7f3f7a1 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
@@ -2025,6 +2025,8 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int flags, vnode_t **vpp)
err = zfs_vnode_lock(*vpp, flags);
if (err != 0)
*vpp = NULL;
+ else
+ (*vpp)->v_hash = ino;
return (err);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
index 354deaa..9438266 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -323,7 +323,7 @@ zfs_ioctl(vnode_t *vp, u_long com, intptr_t data, int flag, cred_t *cred,
}
static vm_page_t
-page_lookup(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
+page_busy(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
{
vm_object_t obj;
vm_page_t pp;
@@ -332,32 +332,30 @@ page_lookup(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
VM_OBJECT_LOCK_ASSERT(obj, MA_OWNED);
for (;;) {
- pp = vm_radix_lookup(&obj->rtree, OFF_TO_IDX(start),
- VM_RADIX_ANY);
- if (pp != NULL) {
- if (vm_page_is_valid(pp, (vm_offset_t)off, nbytes)) {
- if ((pp->oflags & VPO_BUSY) != 0) {
- /*
- * Reference the page before unlocking
- * and sleeping so that the page
- * daemon is less likely to reclaim it.
- */
- vm_page_reference(pp);
- vm_page_sleep(pp, "zfsmwb");
- continue;
- }
- vm_page_busy(pp);
- vm_page_undirty(pp);
- } else {
- if (obj->cached_page_count != 0 &&
- (pp->flags & PG_CACHED) != 0) {
- mtx_lock(&vm_page_queue_free_mtx);
- if (pp->object == obj)
- vm_page_cache_free(pp);
- mtx_unlock(&vm_page_queue_free_mtx);
- }
- pp = NULL;
+ if ((pp = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
+ pp->valid) {
+ if ((pp->oflags & VPO_BUSY) != 0) {
+ /*
+ * Reference the page before unlocking and
+ * sleeping so that the page daemon is less
+ * likely to reclaim it.
+ */
+ vm_page_reference(pp);
+ vm_page_sleep(pp, "zfsmwb");
+ continue;
}
+ } else {
+ pp = vm_page_alloc(obj, OFF_TO_IDX(start),
+ VM_ALLOC_SYSTEM | VM_ALLOC_IFCACHED |
+ VM_ALLOC_NOBUSY);
+ }
+
+ if (pp != NULL) {
+ ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL);
+ vm_object_pip_add(obj, 1);
+ vm_page_io_start(pp);
+ pmap_remove_write(pp);
+ vm_page_clear_dirty(pp, off, nbytes);
}
break;
}
@@ -365,10 +363,55 @@ page_lookup(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
}
static void
-page_unlock(vm_page_t pp)
+page_unbusy(vm_page_t pp)
{
- vm_page_wakeup(pp);
+ vm_page_io_finish(pp);
+ vm_object_pip_subtract(pp->object, 1);
+}
+
+static vm_page_t
+page_hold(vnode_t *vp, int64_t start)
+{
+ vm_object_t obj;
+ vm_page_t pp;
+
+ obj = vp->v_object;
+ VM_OBJECT_LOCK_ASSERT(obj, MA_OWNED);
+
+ for (;;) {
+ if ((pp = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
+ pp->valid) {
+ if ((pp->oflags & VPO_BUSY) != 0) {
+ /*
+ * Reference the page before unlocking and
+ * sleeping so that the page daemon is less
+ * likely to reclaim it.
+ */
+ vm_page_reference(pp);
+ vm_page_sleep(pp, "zfsmwb");
+ continue;
+ }
+
+ ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL);
+ vm_page_lock(pp);
+ vm_page_hold(pp);
+ vm_page_unlock(pp);
+
+ } else
+ pp = NULL;
+ break;
+ }
+ return (pp);
+}
+
+static void
+page_unhold(vm_page_t pp)
+{
+
+ vm_page_lock(pp);
+ vm_page_unhold(pp);
+ vm_page_unlock(pp);
}
static caddr_t
@@ -399,6 +442,7 @@ update_pages(vnode_t *vp, int64_t start, int len, objset_t *os, uint64_t oid,
{
vm_object_t obj;
struct sf_buf *sf;
+ caddr_t va;
int off;
ASSERT(vp->v_mount != NULL);
@@ -409,27 +453,44 @@ update_pages(vnode_t *vp, int64_t start, int len, objset_t *os, uint64_t oid,
VM_OBJECT_LOCK(obj);
for (start &= PAGEMASK; len > 0; start += PAGESIZE) {
vm_page_t pp;
- int nbytes = MIN(PAGESIZE - off, len);
+ int nbytes = imin(PAGESIZE - off, len);
+
+ if (segflg == UIO_NOCOPY) {
+ pp = vm_page_lookup(obj, OFF_TO_IDX(start));
+ KASSERT(pp != NULL,
+ ("zfs update_pages: NULL page in putpages case"));
+ KASSERT(off == 0,
+ ("zfs update_pages: unaligned data in putpages case"));
+ KASSERT(pp->valid == VM_PAGE_BITS_ALL,
+ ("zfs update_pages: invalid page in putpages case"));
+ KASSERT(pp->busy > 0,
+ ("zfs update_pages: unbusy page in putpages case"));
+ KASSERT(!pmap_page_is_write_mapped(pp),
+ ("zfs update_pages: writable page in putpages case"));
+ VM_OBJECT_UNLOCK(obj);
- if ((pp = page_lookup(vp, start, off, nbytes)) != NULL) {
- caddr_t va;
+ va = zfs_map_page(pp, &sf);
+ (void) dmu_write(os, oid, start, nbytes, va, tx);
+ zfs_unmap_page(sf);
+ VM_OBJECT_LOCK(obj);
+ vm_page_undirty(pp);
+ } else if ((pp = page_busy(vp, start, off, nbytes)) != NULL) {
VM_OBJECT_UNLOCK(obj);
+
va = zfs_map_page(pp, &sf);
- if (segflg == UIO_NOCOPY) {
- (void) dmu_write(os, oid, start+off, nbytes,
- va+off, tx);
- } else {
- (void) dmu_read(os, oid, start+off, nbytes,
- va+off, DMU_READ_PREFETCH);
- }
+ (void) dmu_read(os, oid, start+off, nbytes,
+ va+off, DMU_READ_PREFETCH);;
zfs_unmap_page(sf);
+
VM_OBJECT_LOCK(obj);
- page_unlock(pp);
+ page_unbusy(pp);
}
len -= nbytes;
off = 0;
}
+ if (segflg != UIO_NOCOPY)
+ vm_object_pip_wakeupn(obj, 0);
VM_OBJECT_UNLOCK(obj);
}
@@ -531,7 +592,7 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio)
vm_page_t pp;
uint64_t bytes = MIN(PAGESIZE - off, len);
- if (pp = page_lookup(vp, start, off, bytes)) {
+ if (pp = page_hold(vp, start)) {
struct sf_buf *sf;
caddr_t va;
@@ -540,7 +601,7 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio)
error = uiomove(va + off, bytes, UIO_READ, uio);
zfs_unmap_page(sf);
VM_OBJECT_LOCK(obj);
- page_unlock(pp);
+ page_unhold(pp);
} else {
VM_OBJECT_UNLOCK(obj);
error = dmu_read_uio(os, zp->z_id, uio, bytes);
diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S b/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
index 9ff83db..8537e3c 100644
--- a/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
+++ b/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
@@ -19,6 +19,8 @@
*
* CDDL HEADER END
*
+ * Portions Copyright 2012,2013 Justin Hibbits <jhibbits@freebsd.org>
+ *
* $FreeBSD$
*/
/*
@@ -114,48 +116,6 @@ ASENTRY_NOPROF(dtrace_fulword)
END(dtrace_fulword)
/*
-uint8_t
-dtrace_fuword8_nocheck(void *addr)
-*/
-ASENTRY_NOPROF(dtrace_fuword8_nocheck)
- lbz %r3,0(%r3)
- blr
-END(dtrace_fuword8_nocheck)
-
-/*
-uint16_t
-dtrace_fuword16_nocheck(void *addr)
-*/
-ASENTRY_NOPROF(dtrace_fuword16_nocheck)
- lhz %r3,0(%r3)
- blr
-END(dtrace_fuword16_nocheck)
-
-/*
-uint32_t
-dtrace_fuword32_nocheck(void *addr)
-*/
-ASENTRY_NOPROF(dtrace_fuword32_nocheck)
- lwz %r3,0(%r3)
- blr
-END(dtrace_fuword32_nocheck)
-
-/*
-uint64_t
-dtrace_fuword64_nocheck(void *addr)
-*/
-ASENTRY_NOPROF(dtrace_fuword64_nocheck)
-#if defined(__powerpc64__)
- ld %r3,0(%r3)
-#else
- lwz %r5,0(%r3)
- lwz %r4,4(%r3)
- mr %r3,%r5
-#endif
- blr
-END(dtrace_fuword64_nocheck)
-
-/*
XXX: unoptimized
void
dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
index a697816..efbca6f 100644
--- a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
+++ b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
@@ -19,6 +19,8 @@
*
* CDDL HEADER END
*
+ * Portions Copyright 2012,2013 Justin Hibbits <jhibbits@freebsd.org>
+ *
* $FreeBSD$
*/
/*
@@ -45,11 +47,6 @@
#include "regset.h"
-uint8_t dtrace_fuword8_nocheck(void *);
-uint16_t dtrace_fuword16_nocheck(void *);
-uint32_t dtrace_fuword32_nocheck(void *);
-uint64_t dtrace_fuword64_nocheck(void *);
-
/* Offset to the LR Save word (ppc32) */
#define RETURN_OFFSET 4
#define RETURN_OFFSET64 8
@@ -462,31 +459,63 @@ dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
volatile uint16_t *flags)
{
if (dtrace_copycheck(uaddr, kaddr, size))
- dtrace_copy(uaddr, kaddr, size);
+ if (copyin((const void *)uaddr, (void *)kaddr, size)) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
}
void
dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
volatile uint16_t *flags)
{
- if (dtrace_copycheck(uaddr, kaddr, size))
- dtrace_copy(kaddr, uaddr, size);
+ if (dtrace_copycheck(uaddr, kaddr, size)) {
+ if (copyout((const void *)kaddr, (void *)uaddr, size)) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
+ }
}
void
dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
volatile uint16_t *flags)
{
- if (dtrace_copycheck(uaddr, kaddr, size))
- dtrace_copystr(uaddr, kaddr, size, flags);
+ size_t actual;
+ int error;
+
+ if (dtrace_copycheck(uaddr, kaddr, size)) {
+ error = copyinstr((const void *)uaddr, (void *)kaddr,
+ size, &actual);
+
+ /* ENAMETOOLONG is not a fault condition. */
+ if (error && error != ENAMETOOLONG) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
+ }
}
+/*
+ * The bulk of this function could be replaced to match dtrace_copyinstr()
+ * if we ever implement a copyoutstr().
+ */
void
dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
volatile uint16_t *flags)
{
- if (dtrace_copycheck(uaddr, kaddr, size))
- dtrace_copystr(kaddr, uaddr, size, flags);
+ size_t len;
+
+ if (dtrace_copycheck(uaddr, kaddr, size)) {
+ len = strlen((const char *)kaddr);
+ if (len > size)
+ len = size;
+
+ if (copyout((const void *)kaddr, (void *)uaddr, len)) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
+ }
}
uint8_t
@@ -497,18 +526,21 @@ dtrace_fuword8(void *uaddr)
cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
return (0);
}
- return (dtrace_fuword8_nocheck(uaddr));
+ return (fubyte(uaddr));
}
uint16_t
dtrace_fuword16(void *uaddr)
{
- if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
- DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
- cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
- return (0);
+ uint16_t ret = 0;
+
+ if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) {
+ if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
}
- return (dtrace_fuword16_nocheck(uaddr));
+ return ret;
}
uint32_t
@@ -519,16 +551,19 @@ dtrace_fuword32(void *uaddr)
cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
return (0);
}
- return (dtrace_fuword32_nocheck(uaddr));
+ return (fuword32(uaddr));
}
uint64_t
dtrace_fuword64(void *uaddr)
{
- if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
- DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
- cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
- return (0);
+ uint64_t ret = 0;
+
+ if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) {
+ if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+ }
}
- return (dtrace_fuword64_nocheck(uaddr));
+ return ret;
}
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 31cda7d..d86da04 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -101,13 +101,9 @@ __FBSDID("$FreeBSD$");
#include <compat/freebsd32/freebsd32_util.h>
#endif
-#ifdef COMPAT_LINUX32 /* XXX */
-#include <machine/../linux32/linux.h>
-#else
-#include <machine/../linux/linux.h>
-#endif
#include <compat/linux/linux_ioctl.h>
#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_util.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/procfs/procfs.h>
diff --git a/sys/compat/linux/linux_emul.c b/sys/compat/linux/linux_emul.c
index 6a1098d..61156ba 100644
--- a/sys/compat/linux/linux_emul.c
+++ b/sys/compat/linux/linux_emul.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include <compat/linux/linux_dtrace.h>
#include <compat/linux/linux_emul.h>
#include <compat/linux/linux_futex.h>
+#include <compat/linux/linux_misc.h>
/**
* Special DTrace provider for the linuxulator.
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index df13277..0318a5c 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
#include <machine/../linux/linux.h>
#include <machine/../linux/linux_proto.h>
#endif
+#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_util.h>
#include <compat/linux/linux_file.h>
diff --git a/sys/compat/linux/linux_file.h b/sys/compat/linux/linux_file.h
index d0d95ac..2d3106f 100644
--- a/sys/compat/linux/linux_file.h
+++ b/sys/compat/linux/linux_file.h
@@ -35,4 +35,23 @@
#define LINUX_AT_REMOVEDIR 0x200
#define LINUX_AT_SYMLINK_FOLLOW 0x400
+/*
+ * posix_fadvise advice
+ */
+#define LINUX_POSIX_FADV_NORMAL 0
+#define LINUX_POSIX_FADV_RANDOM 1
+#define LINUX_POSIX_FADV_SEQUENTIAL 2
+#define LINUX_POSIX_FADV_WILLNEED 3
+#define LINUX_POSIX_FADV_DONTNEED 4
+#define LINUX_POSIX_FADV_NOREUSE 5
+
+/*
+ * mount flags
+ */
+#define LINUX_MS_RDONLY 0x0001
+#define LINUX_MS_NOSUID 0x0002
+#define LINUX_MS_NODEV 0x0004
+#define LINUX_MS_NOEXEC 0x0008
+#define LINUX_MS_REMOUNT 0x0020
+
#endif /* !_LINUX_FILE_H_ */
diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c
index f71063c..2103636 100644
--- a/sys/compat/linux/linux_fork.c
+++ b/sys/compat/linux/linux_fork.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <compat/linux/linux_dtrace.h>
#include <compat/linux/linux_signal.h>
#include <compat/linux/linux_emul.h>
+#include <compat/linux/linux_misc.h>
/* DTrace init */
LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
diff --git a/sys/compat/linux/linux_futex.c b/sys/compat/linux/linux_futex.c
index c87fd00..c1531d0 100644
--- a/sys/compat/linux/linux_futex.c
+++ b/sys/compat/linux/linux_futex.c
@@ -1203,7 +1203,7 @@ release_futexes(struct proc *p)
if (entry != pending)
if (handle_futex_death(p,
- (uint32_t *)entry + futex_offset, pi)) {
+ (uint32_t *)((caddr_t)entry + futex_offset), pi)) {
LIN_SDT_PROBE0(futex, release_futexes, return);
return;
}
@@ -1222,7 +1222,7 @@ release_futexes(struct proc *p)
}
if (pending)
- handle_futex_death(p, (uint32_t *)pending + futex_offset, pip);
+ handle_futex_death(p, (uint32_t *)((caddr_t)pending + futex_offset), pip);
LIN_SDT_PROBE0(futex, release_futexes, return);
}
diff --git a/sys/compat/linux/linux_ioctl.h b/sys/compat/linux/linux_ioctl.h
index c075231..aa7650b 100644
--- a/sys/compat/linux/linux_ioctl.h
+++ b/sys/compat/linux/linux_ioctl.h
@@ -748,4 +748,20 @@ int linux_ifname(struct ifnet *, char *, size_t);
#define FBSD_LUSB_MAX 0xffff
#define FBSD_LUSB_MIN 0xffe0
+/*
+ * Pluggable ioctl handlers
+ */
+struct linux_ioctl_args;
+struct thread;
+
+typedef int linux_ioctl_function_t(struct thread *, struct linux_ioctl_args *);
+
+struct linux_ioctl_handler {
+ linux_ioctl_function_t *func;
+ int low, high;
+};
+
+int linux_ioctl_register_handler(struct linux_ioctl_handler *h);
+int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
+
#endif /* !_LINUX_IOCTL_H_ */
diff --git a/sys/compat/linux/linux_ipc.h b/sys/compat/linux/linux_ipc.h
index 4c01342..f1531ba 100644
--- a/sys/compat/linux/linux_ipc.h
+++ b/sys/compat/linux/linux_ipc.h
@@ -32,6 +32,48 @@
#define _LINUX_IPC_H_
/*
+ * SystemV IPC defines
+ */
+#define LINUX_SEMOP 1
+#define LINUX_SEMGET 2
+#define LINUX_SEMCTL 3
+#define LINUX_MSGSND 11
+#define LINUX_MSGRCV 12
+#define LINUX_MSGGET 13
+#define LINUX_MSGCTL 14
+#define LINUX_SHMAT 21
+#define LINUX_SHMDT 22
+#define LINUX_SHMGET 23
+#define LINUX_SHMCTL 24
+
+#define LINUX_IPC_RMID 0
+#define LINUX_IPC_SET 1
+#define LINUX_IPC_STAT 2
+#define LINUX_IPC_INFO 3
+
+#define LINUX_MSG_INFO 12
+
+#define LINUX_SHM_LOCK 11
+#define LINUX_SHM_UNLOCK 12
+#define LINUX_SHM_STAT 13
+#define LINUX_SHM_INFO 14
+
+#define LINUX_SHM_RDONLY 0x1000
+#define LINUX_SHM_RND 0x2000
+#define LINUX_SHM_REMAP 0x4000
+
+/* semctl commands */
+#define LINUX_GETPID 11
+#define LINUX_GETVAL 12
+#define LINUX_GETALL 13
+#define LINUX_GETNCNT 14
+#define LINUX_GETZCNT 15
+#define LINUX_SETVAL 16
+#define LINUX_SETALL 17
+#define LINUX_SEM_STAT 18
+#define LINUX_SEM_INFO 19
+
+/*
* Version flags for semctl, msgctl, and shmctl commands
* These are passed as bitflags or-ed with the actual command
*/
@@ -135,8 +177,6 @@ int linux_shmctl(struct thread *, struct linux_shmctl_args *);
int linux_shmdt(struct thread *, struct linux_shmdt_args *);
int linux_shmget(struct thread *, struct linux_shmget_args *);
-#define LINUX_MSG_INFO 12
-
#endif /* __i386__ || __amd64__ */
#endif /* _LINUX_IPC_H_ */
diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c
index 0856662..323a38f 100644
--- a/sys/compat/linux/linux_mib.c
+++ b/sys/compat/linux/linux_mib.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <compat/linux/linux_dtrace.h>
#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_misc.h>
/* DTrace init */
LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h
index b771825..154d78f 100644
--- a/sys/compat/linux/linux_misc.h
+++ b/sys/compat/linux/linux_misc.h
@@ -31,6 +31,14 @@
#ifndef _LINUX_MISC_H_
#define _LINUX_MISC_H_
+/*
+ * Miscellaneous
+ */
+#define LINUX_NAME_MAX 255
+#define LINUX_MAX_UTSNAME 65
+
+#define LINUX_CTL_MAXNAME 10
+
/* defines for prctl */
#define LINUX_PR_SET_PDEATHSIG 1 /* Second arg is a signal. */
#define LINUX_PR_GET_PDEATHSIG 2 /*
@@ -67,11 +75,51 @@ extern const char *linux_platform;
#define __LINUX_NPXCW__ 0x37f
#endif
+#define LINUX_CLONE_VM 0x00000100
+#define LINUX_CLONE_FS 0x00000200
+#define LINUX_CLONE_FILES 0x00000400
+#define LINUX_CLONE_SIGHAND 0x00000800
+#define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */
+#define LINUX_CLONE_VFORK 0x00004000
+#define LINUX_CLONE_PARENT 0x00008000
+#define LINUX_CLONE_THREAD 0x00010000
+#define LINUX_CLONE_SETTLS 0x00080000
+#define LINUX_CLONE_PARENT_SETTID 0x00100000
+#define LINUX_CLONE_CHILD_CLEARTID 0x00200000
+#define LINUX_CLONE_CHILD_SETTID 0x01000000
+
+#define LINUX_THREADING_FLAGS \
+ (LINUX_CLONE_VM | LINUX_CLONE_FS | LINUX_CLONE_FILES | \
+ LINUX_CLONE_SIGHAND | LINUX_CLONE_THREAD)
+
+/* Scheduling policies */
+#define LINUX_SCHED_OTHER 0
+#define LINUX_SCHED_FIFO 1
+#define LINUX_SCHED_RR 2
+
+struct l_new_utsname {
+ char sysname[LINUX_MAX_UTSNAME];
+ char nodename[LINUX_MAX_UTSNAME];
+ char release[LINUX_MAX_UTSNAME];
+ char version[LINUX_MAX_UTSNAME];
+ char machine[LINUX_MAX_UTSNAME];
+ char domainname[LINUX_MAX_UTSNAME];
+};
+
+#define LINUX_CLOCK_REALTIME 0
+#define LINUX_CLOCK_MONOTONIC 1
+#define LINUX_CLOCK_PROCESS_CPUTIME_ID 2
+#define LINUX_CLOCK_THREAD_CPUTIME_ID 3
+#define LINUX_CLOCK_REALTIME_HR 4
+#define LINUX_CLOCK_MONOTONIC_HR 5
+
extern int stclohz;
#define __WCLONE 0x80000000
int linux_common_wait(struct thread *td, int pid, int *status,
int options, struct rusage *ru);
+int linux_set_upcall_kse(struct thread *td, register_t stack);
+int linux_set_cloned_tls(struct thread *td, void *desc);
#endif /* _LINUX_MISC_H_ */
diff --git a/sys/compat/linux/linux_signal.h b/sys/compat/linux/linux_signal.h
index 939009f..426cf43 100644
--- a/sys/compat/linux/linux_signal.h
+++ b/sys/compat/linux/linux_signal.h
@@ -33,6 +33,9 @@
#define LINUX_SI_TKILL -6;
+extern int bsd_to_linux_signal[];
+extern int linux_to_bsd_signal[];
+
void linux_to_bsd_sigset(l_sigset_t *, sigset_t *);
void bsd_to_linux_sigset(sigset_t *, l_sigset_t *);
int linux_do_sigaction(struct thread *, int, l_sigaction_t *, l_sigaction_t *);
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 7271a18..cd288f8 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#include <netinet/tcp.h>
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
@@ -326,6 +327,27 @@ linux_to_bsd_so_sockopt(int opt)
}
static int
+linux_to_bsd_tcp_sockopt(int opt)
+{
+
+ switch (opt) {
+ case LINUX_TCP_NODELAY:
+ return (TCP_NODELAY);
+ case LINUX_TCP_MAXSEG:
+ return (TCP_MAXSEG);
+ case LINUX_TCP_KEEPIDLE:
+ return (TCP_KEEPIDLE);
+ case LINUX_TCP_KEEPINTVL:
+ return (TCP_KEEPINTVL);
+ case LINUX_TCP_KEEPCNT:
+ return (TCP_KEEPCNT);
+ case LINUX_TCP_MD5SIG:
+ return (TCP_MD5SIG);
+ }
+ return (-1);
+}
+
+static int
linux_to_bsd_msg_flags(int flags)
{
int ret_flags = 0;
@@ -1496,8 +1518,7 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
name = linux_to_bsd_ip_sockopt(args->optname);
break;
case IPPROTO_TCP:
- /* Linux TCP option values match BSD's */
- name = args->optname;
+ name = linux_to_bsd_tcp_sockopt(args->optname);
break;
default:
name = -1;
@@ -1591,8 +1612,7 @@ linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args)
name = linux_to_bsd_ip_sockopt(args->optname);
break;
case IPPROTO_TCP:
- /* Linux TCP option values match BSD's */
- name = args->optname;
+ name = linux_to_bsd_tcp_sockopt(args->optname);
break;
default:
name = -1;
diff --git a/sys/compat/linux/linux_socket.h b/sys/compat/linux/linux_socket.h
index 1fe53ed..e6efadb 100644
--- a/sys/compat/linux/linux_socket.h
+++ b/sys/compat/linux/linux_socket.h
@@ -116,4 +116,44 @@ struct l_ucred {
uint32_t gid;
};
+/* Operations for socketcall */
+
+#define LINUX_SOCKET 1
+#define LINUX_BIND 2
+#define LINUX_CONNECT 3
+#define LINUX_LISTEN 4
+#define LINUX_ACCEPT 5
+#define LINUX_GETSOCKNAME 6
+#define LINUX_GETPEERNAME 7
+#define LINUX_SOCKETPAIR 8
+#define LINUX_SEND 9
+#define LINUX_RECV 10
+#define LINUX_SENDTO 11
+#define LINUX_RECVFROM 12
+#define LINUX_SHUTDOWN 13
+#define LINUX_SETSOCKOPT 14
+#define LINUX_GETSOCKOPT 15
+#define LINUX_SENDMSG 16
+#define LINUX_RECVMSG 17
+#define LINUX_ACCEPT4 18
+
+/* Socket options */
+#define LINUX_IP_TOS 1
+#define LINUX_IP_TTL 2
+#define LINUX_IP_HDRINCL 3
+#define LINUX_IP_OPTIONS 4
+
+#define LINUX_IP_MULTICAST_IF 32
+#define LINUX_IP_MULTICAST_TTL 33
+#define LINUX_IP_MULTICAST_LOOP 34
+#define LINUX_IP_ADD_MEMBERSHIP 35
+#define LINUX_IP_DROP_MEMBERSHIP 36
+
+#define LINUX_TCP_NODELAY 1
+#define LINUX_TCP_MAXSEG 2
+#define LINUX_TCP_KEEPIDLE 4
+#define LINUX_TCP_KEEPINTVL 5
+#define LINUX_TCP_KEEPCNT 6
+#define LINUX_TCP_MD5SIG 14
+
#endif /* _LINUX_SOCKET_H_ */
diff --git a/sys/compat/linux/linux_sysctl.c b/sys/compat/linux/linux_sysctl.c
index b2c10e1..decd8f8 100644
--- a/sys/compat/linux/linux_sysctl.c
+++ b/sys/compat/linux/linux_sysctl.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_util.h>
#define LINUX_CTL_KERN 1
diff --git a/sys/compat/linux/linux_time.c b/sys/compat/linux/linux_time.c
index 1359025..e03af00 100644
--- a/sys/compat/linux/linux_time.c
+++ b/sys/compat/linux/linux_time.c
@@ -60,6 +60,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp
#endif
#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_misc.h>
/* DTrace init */
LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
diff --git a/sys/conf/Makefile.arm b/sys/conf/Makefile.arm
index 4145d60..63b451d 100644
--- a/sys/conf/Makefile.arm
+++ b/sys/conf/Makefile.arm
@@ -39,8 +39,12 @@ SYSTEM_DEP:= ${SYSTEM_DEP:$S/conf/ldscript.$M=ldscript.$M}
STRIP_FLAGS = -S
.endif
+CFLAGS += -mno-thumb-interwork
+
.if empty(DDB_ENABLED)
CFLAGS += -mno-apcs-frame
+.elif defined(WITH_ARM_EABI)
+CFLAGS += -funwind-tables
.endif
SYSTEM_LD_ = ${LD} -Bdynamic -T ldscript.$M.noheader ${LDFLAGS} \
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 216d2f5..ff245ed 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -446,6 +446,8 @@ options KTRACE_REQUEST_POOL=101
# KTR is a kernel tracing facility imported from BSD/OS. It is
# enabled with the KTR option. KTR_ENTRIES defines the number of
# entries in the circular trace buffer; it may be an arbitrary number.
+# KTR_BOOT_ENTRIES defines the number of entries during the early boot,
+# before malloc(9) is functional.
# KTR_COMPILE defines the mask of events to compile into the kernel as
# defined by the KTR_* constants in <sys/ktr.h>. KTR_MASK defines the
# initial value of the ktr_mask variable which determines at runtime
@@ -459,7 +461,8 @@ options KTRACE_REQUEST_POOL=101
# if KTR_VERBOSE is not defined. See ktr(4) and ktrdump(8) for details.
#
options KTR
-options KTR_ENTRIES=1024
+options KTR_BOOT_ENTRIES=1024
+options KTR_ENTRIES=(128 * 1024)
options KTR_COMPILE=(KTR_INTR|KTR_PROC)
options KTR_MASK=KTR_INTR
options KTR_CPUMASK=0x3
diff --git a/sys/conf/files b/sys/conf/files
index 04718e8..2a3db4f 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -283,6 +283,7 @@ contrib/altq/altq/altq_rio.c optional altq
contrib/altq/altq/altq_rmclass.c optional altq
contrib/altq/altq/altq_subr.c optional altq
contrib/dev/acpica/components/debugger/dbcmds.c optional acpi acpi_debug
+contrib/dev/acpica/components/debugger/dbconvert.c optional acpi acpi_debug
contrib/dev/acpica/components/debugger/dbdisply.c optional acpi acpi_debug
contrib/dev/acpica/components/debugger/dbexec.c optional acpi acpi_debug
contrib/dev/acpica/components/debugger/dbfileio.c optional acpi acpi_debug
@@ -324,6 +325,7 @@ contrib/dev/acpica/components/events/evgpe.c optional acpi
contrib/dev/acpica/components/events/evgpeblk.c optional acpi
contrib/dev/acpica/components/events/evgpeinit.c optional acpi
contrib/dev/acpica/components/events/evgpeutil.c optional acpi
+contrib/dev/acpica/components/events/evhandler.c optional acpi
contrib/dev/acpica/components/events/evmisc.c optional acpi
contrib/dev/acpica/components/events/evregion.c optional acpi
contrib/dev/acpica/components/events/evrgnini.c optional acpi
@@ -376,6 +378,7 @@ contrib/dev/acpica/components/namespace/nsnames.c optional acpi
contrib/dev/acpica/components/namespace/nsobject.c optional acpi
contrib/dev/acpica/components/namespace/nsparse.c optional acpi
contrib/dev/acpica/components/namespace/nspredef.c optional acpi
+contrib/dev/acpica/components/namespace/nsprepkg.c optional acpi
contrib/dev/acpica/components/namespace/nsrepair.c optional acpi
contrib/dev/acpica/components/namespace/nsrepair2.c optional acpi
contrib/dev/acpica/components/namespace/nssearch.c optional acpi
@@ -386,7 +389,9 @@ contrib/dev/acpica/components/namespace/nsxfname.c optional acpi
contrib/dev/acpica/components/namespace/nsxfobj.c optional acpi
contrib/dev/acpica/components/parser/psargs.c optional acpi
contrib/dev/acpica/components/parser/psloop.c optional acpi
+contrib/dev/acpica/components/parser/psobject.c optional acpi
contrib/dev/acpica/components/parser/psopcode.c optional acpi
+contrib/dev/acpica/components/parser/psopinfo.c optional acpi
contrib/dev/acpica/components/parser/psparse.c optional acpi
contrib/dev/acpica/components/parser/psscope.c optional acpi
contrib/dev/acpica/components/parser/pstree.c optional acpi
@@ -397,6 +402,7 @@ contrib/dev/acpica/components/resources/rsaddr.c optional acpi
contrib/dev/acpica/components/resources/rscalc.c optional acpi
contrib/dev/acpica/components/resources/rscreate.c optional acpi
contrib/dev/acpica/components/resources/rsdump.c optional acpi
+contrib/dev/acpica/components/resources/rsdumpinfo.c optional acpi
contrib/dev/acpica/components/resources/rsinfo.c optional acpi
contrib/dev/acpica/components/resources/rsio.c optional acpi
contrib/dev/acpica/components/resources/rsirq.c optional acpi
@@ -431,8 +437,10 @@ contrib/dev/acpica/components/utilities/utmisc.c optional acpi
contrib/dev/acpica/components/utilities/utmutex.c optional acpi
contrib/dev/acpica/components/utilities/utobject.c optional acpi
contrib/dev/acpica/components/utilities/utosi.c optional acpi
+contrib/dev/acpica/components/utilities/utownerid.c optional acpi
contrib/dev/acpica/components/utilities/utresrc.c optional acpi
contrib/dev/acpica/components/utilities/utstate.c optional acpi
+contrib/dev/acpica/components/utilities/utstring.c optional acpi
contrib/dev/acpica/components/utilities/utxface.c optional acpi
contrib/dev/acpica/components/utilities/utxferror.c optional acpi
contrib/dev/acpica/components/utilities/utxfinit.c optional acpi
@@ -638,9 +646,12 @@ dev/aic7xxx/aic7xxx_pci.c optional ahc pci
dev/alc/if_alc.c optional alc pci
dev/ale/if_ale.c optional ale pci
dev/altera/avgen/altera_avgen.c optional altera_avgen
+dev/altera/avgen/altera_avgen_fdt.c optional altera_avgen fdt
+dev/altera/avgen/altera_avgen_nexus.c optional altera_avgen
dev/altera/sdcard/altera_sdcard.c optional altera_sdcard
dev/altera/sdcard/altera_sdcard_disk.c optional altera_sdcard
dev/altera/sdcard/altera_sdcard_io.c optional altera_sdcard
+dev/altera/sdcard/altera_sdcard_fdt.c optional altera_sdcard fdt
dev/altera/sdcard/altera_sdcard_nexus.c optional altera_sdcard
dev/amr/amr.c optional amr
dev/amr/amr_cam.c optional amrp amr
@@ -1415,6 +1426,7 @@ dev/iscsi/initiator/isc_soc.c optional iscsi_initiator scbus
dev/iscsi/initiator/isc_sm.c optional iscsi_initiator scbus
dev/iscsi/initiator/isc_subr.c optional iscsi_initiator scbus
dev/isf/isf.c optional isf
+dev/isf/isf_fdt.c optional isf fdt
dev/isf/isf_nexus.c optional isf
dev/isp/isp.c optional isp
dev/isp/isp_freebsd.c optional isp
@@ -2276,15 +2288,6 @@ dev/utopia/idtphy.c optional utopia
dev/utopia/suni.c optional utopia
dev/utopia/utopia.c optional utopia
dev/vge/if_vge.c optional vge
-#
-# virtio support
-#
-dev/virtio/pci/virtio_pci.c optional vtnet
-dev/virtio/virtio.c optional vtnet
-dev/virtio/virtqueue.c optional vtnet
-dev/virtio/network/if_vtnet.c optional vtnet
-dev/virtio/virtio_bus_if.m optional vtnet
-dev/virtio/virtio_if.m optional vtnet
dev/vkbd/vkbd.c optional vkbd
dev/vr/if_vr.c optional vr pci
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index b6a474e..131a1e7 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -190,8 +190,7 @@ dev/fdc/fdc_acpi.c optional fdc
dev/fdc/fdc_isa.c optional fdc isa
dev/fdc/fdc_pccard.c optional fdc pccard
dev/hpt27xx/os_bsd.c optional hpt27xx
-dev/hpt27xx/osm_bsd.c optional hpt27xx \
- compile-with "${NORMAL_C} ${NO_WFORMAT_SECURITY}"
+dev/hpt27xx/osm_bsd.c optional hpt27xx
dev/hpt27xx/hpt27xx_config.c optional hpt27xx
dev/hptmv/entry.c optional hptmv
dev/hptmv/mv.c optional hptmv
@@ -390,6 +389,15 @@ dev/isci/scil/scif_sas_task_request.c optional isci
dev/isci/scil/scif_sas_task_request_state_handlers.c optional isci
dev/isci/scil/scif_sas_task_request_states.c optional isci
dev/isci/scil/scif_sas_timer.c optional isci
+dev/virtio/virtio.c optional virtio
+dev/virtio/virtqueue.c optional virtio
+dev/virtio/virtio_bus_if.m optional virtio
+dev/virtio/virtio_if.m optional virtio
+dev/virtio/pci/virtio_pci.c optional virtio_pci virtio pci
+dev/virtio/network/if_vtnet.c optional vtnet virtio
+dev/virtio/block/virtio_blk.c optional virtio_blk virtio
+dev/virtio/balloon/virtio_balloon.c optional virtio_balloon virtio
+dev/virtio/scsi/virtio_scsi.c optional virtio_scsi virtio scbus
isa/syscons_isa.c optional sc
isa/vga_isa.c optional vga
kern/kern_clocksource.c standard
@@ -455,6 +463,11 @@ libkern/memset.c standard
compat/x86bios/x86bios.c optional x86bios | atkbd | dpms | vesa
contrib/x86emu/x86emu.c optional x86bios | atkbd | dpms | vesa
#
+# bvm console
+#
+dev/bvm/bvm_console.c optional bvmconsole
+dev/bvm/bvm_dbg.c optional bvmdebug
+#
# x86 shared code between IA32, AMD64 and PC98 architectures
#
x86/acpica/OsdEnvironment.c optional acpi
diff --git a/sys/conf/files.arm b/sys/conf/files.arm
index 428757a..14d6c4b 100644
--- a/sys/conf/files.arm
+++ b/sys/conf/files.arm
@@ -74,6 +74,8 @@ kern/subr_busdma_bufalloc.c standard
kern/subr_dummy_vdso_tc.c standard
libkern/arm/divsi3.S standard
libkern/arm/ffs.S standard
+libkern/arm/ldivmod.S standard
+libkern/arm/ldivmod_helper.c standard
libkern/arm/muldi3.c standard
libkern/ashldi3.c standard
libkern/ashrdi3.c standard
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index d4df01d..fd536af 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -181,8 +181,7 @@ dev/glxiic/glxiic.c optional glxiic
dev/glxsb/glxsb.c optional glxsb
dev/glxsb/glxsb_hash.c optional glxsb
dev/hpt27xx/os_bsd.c optional hpt27xx
-dev/hpt27xx/osm_bsd.c optional hpt27xx \
- compile-with "${NORMAL_C} ${NO_WFORMAT_SECURITY}"
+dev/hpt27xx/osm_bsd.c optional hpt27xx
dev/hpt27xx/hpt27xx_config.c optional hpt27xx
dev/hptmv/entry.c optional hptmv
dev/hptmv/mv.c optional hptmv
@@ -371,6 +370,15 @@ dev/isci/scil/scif_sas_task_request.c optional isci
dev/isci/scil/scif_sas_task_request_state_handlers.c optional isci
dev/isci/scil/scif_sas_task_request_states.c optional isci
dev/isci/scil/scif_sas_timer.c optional isci
+dev/virtio/virtio.c optional virtio
+dev/virtio/virtqueue.c optional virtio
+dev/virtio/virtio_bus_if.m optional virtio
+dev/virtio/virtio_if.m optional virtio
+dev/virtio/pci/virtio_pci.c optional virtio_pci virtio pci
+dev/virtio/network/if_vtnet.c optional vtnet virtio
+dev/virtio/block/virtio_blk.c optional virtio_blk virtio
+dev/virtio/balloon/virtio_balloon.c optional virtio_balloon virtio
+dev/virtio/scsi/virtio_scsi.c optional virtio_scsi virtio scbus
i386/acpica/acpi_machdep.c optional acpi
acpi_wakecode.o optional acpi \
dependency "$S/i386/acpica/acpi_wakecode.S assym.s" \
diff --git a/sys/conf/files.mips b/sys/conf/files.mips
index 8c7a530..2dfc5dd 100644
--- a/sys/conf/files.mips
+++ b/sys/conf/files.mips
@@ -7,6 +7,7 @@
# Arch dependent files
mips/mips/autoconf.c standard
mips/mips/bus_space_generic.c standard
+mips/mips/bus_space_fdt.c optional fdt
mips/mips/busdma_machdep.c standard
mips/mips/cache.c standard
mips/mips/cache_mipsNN.c standard
diff --git a/sys/conf/ldscript.arm b/sys/conf/ldscript.arm
index 3b8422c..d681c87 100644
--- a/sys/conf/ldscript.arm
+++ b/sys/conf/ldscript.arm
@@ -56,6 +56,18 @@ SECTIONS
.init : { *(.init) } =0x9090
.plt : { *(.plt) }
+ _extab_start = .;
+ PROVIDE(extab_start = .);
+ .ARM.extab : { *(.ARM.extab) }
+ _extab.end = .;
+ PROVIDE(extab_end = .);
+
+ _exidx_start = .;
+ PROVIDE(exidx_start = .);
+ .ARM.exidx : { *(.ARM.exidx) }
+ _exidx_end = .;
+ PROVIDE(exidx_end = .);
+
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN(0x1000) + (. & (0x1000 - 1)) ;
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index 3cb211b..1e5e24b 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -86,6 +86,7 @@ fi
touch version
v=`cat version` u=${USER:-root} d=`pwd` h=${HOSTNAME:-`hostname`} t=`date`
i=`${MAKE:-make} -V KERN_IDENT`
+compiler_v=$($(${MAKE:-make} -V CC) -v 2>&1 | grep 'version')
for dir in /bin /usr/bin /usr/local/bin; do
if [ -x "${dir}/svnversion" ] && [ -z ${svnversion} ] ; then
@@ -159,6 +160,7 @@ $COPYRIGHT
char sccs[sizeof(SCCSSTR) > 128 ? sizeof(SCCSSTR) : 128] = SCCSSTR;
char version[sizeof(VERSTR) > 256 ? sizeof(VERSTR) : 256] = VERSTR;
+char compiler_version[] = "${compiler_v}";
char ostype[] = "${TYPE}";
char osrelease[sizeof(RELSTR) > 32 ? sizeof(RELSTR) : 32] = RELSTR;
int osreldate = ${RELDATE};
diff --git a/sys/conf/options b/sys/conf/options
index 1fb3a2a..5722ac4 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -669,6 +669,7 @@ KTR_ALQ opt_ktr.h
KTR_MASK opt_ktr.h
KTR_CPUMASK opt_ktr.h
KTR_COMPILE opt_global.h
+KTR_BOOT_ENTRIES opt_global.h
KTR_ENTRIES opt_global.h
KTR_VERBOSE opt_ktr.h
WITNESS opt_global.h
@@ -775,6 +776,8 @@ ATH_ENABLE_11N opt_ath.h
ATH_ENABLE_DFS opt_ath.h
ATH_EEPROM_FIRMWARE opt_ath.h
ATH_ENABLE_RADIOTAP_VENDOR_EXT opt_ath.h
+ATH_DEBUG_ALQ opt_ath.h
+ATH_KTR_INTR_DEBUG opt_ath.h
# options for the Atheros hal
AH_SUPPORT_AR5416 opt_ah.h
@@ -794,7 +797,7 @@ 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
-
+AH_INTERRUPT_DEBUGGING opt_ah.h
# AR5416 and later interrupt mitigation
# XXX do not use this for AR9130
AH_AR5416_INTERRUPT_MITIGATION opt_ah.h
diff --git a/sys/contrib/dev/acpica/changes.txt b/sys/contrib/dev/acpica/changes.txt
index 6374788..5848335 100644
--- a/sys/contrib/dev/acpica/changes.txt
+++ b/sys/contrib/dev/acpica/changes.txt
@@ -1,8 +1,154 @@
----------------------------------------
-14 November 2012. Summary of changes for version 20121114:
+17 January 2013. Summary of changes for version 20130117:
+
+
+1) ACPICA Kernel-resident Subsystem:
+
+Updated the AcpiGetSleepTypeData interface: Allow the \_Sx methods to
+return either 1 or 2 integers. Although the ACPI spec defines the \_Sx
+objects to return a package containing one integer, most BIOS code returns
+two integers and the previous code reflects that. However, we also need to
+support BIOS code that actually implements to the ACPI spec, and this
+change reflects this.
+
+Fixed two issues with the ACPI_DEBUG_PRINT macros:
+1) Added the ACPI_DO_WHILE macro to the main DEBUG_PRINT helper macro for
+C compilers that require this support.
+2) Renamed the internal ACPI_DEBUG macro to ACPI_DO_DEBUG_PRINT since
+ACPI_DEBUG is already used by many of the various hosts.
+
+Updated all ACPICA copyrights and signons to 2013. Added the 2013
+copyright to all module headers and signons, including the standard Linux
+header. This affects virtually every file in the ACPICA core subsystem,
+iASL compiler, all ACPICA utilities, and the test suites.
-This release is available at https://www.acpica.org/downloads
-The ACPI 5.0 specification is available at www.acpi.info
+Example Code and Data Size: These are the sizes for the OS-independent
+acpica.lib produced by the Microsoft Visual C++ 9.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: 94.5K Code, 25.5K Data, 120.0K Total
+ Debug Version: 182.2K Code, 74.9K Data, 257.1K Total
+ Current Release:
+ Non-Debug Version: 94.5K Code, 25.4K Data, 119.9K Total
+ Debug Version: 182.3K Code, 75.0K Data, 257.3K Total
+
+
+2) iASL Compiler/Disassembler and Tools:
+
+Generic Unix OSL: Use a buffer to eliminate multiple vfprintf()s and
+prevent a possible fault on some hosts. Some C libraries modify the arg
+pointer parameter to vfprintf making it difficult to call it twice in the
+AcpiOsVprintf function. Use a local buffer to workaround this issue. This
+does not affect the Windows OSL since the Win C library does not modify
+the arg pointer. Chao Guan, Bob Moore.
+
+iASL: Fixed a possible infinite loop when the maximum error count is
+reached. If an output file other than the .AML file is specified (such as
+a listing file), and the maximum number of errors is reached, do not
+attempt to flush data to the output file(s) as the compiler is aborting.
+This can cause an infinite loop as the max error count code essentially
+keeps calling itself.
+
+iASL/Disassembler: Added an option (-in) to ignore NOOP opcodes/operators.
+Implemented for both the compiler and the disassembler. Often, the NOOP
+opcode is used as padding for packages that are changed dynamically by the
+BIOS. When disassembled and recompiled, these NOOPs will cause syntax
+errors. This option causes the disassembler to ignore all NOOP opcodes
+(0xA3), and it also causes the compiler to ignore all ASL source code NOOP
+statements as well.
+
+Debugger: Enhanced the Sleep command to execute all sleep states. This
+change allows Sleep to be invoked with no arguments and causes the
+debugger to execute all of the sleep states, 0-5, automatically.
+
+----------------------------------------
+20 December 2012. Summary of changes for version 20121220:
+
+1) ACPICA Kernel-resident Subsystem:
+
+Implemented a new interface, AcpiWalkResourceBuffer. This interface is an
+alternate entry point for AcpiWalkResources and improves the usability of
+the resource manager by accepting as input a buffer containing the output
+of either a _CRS, _PRS, or _AEI method. The key functionality is that the
+input buffer is not deleted by this interface so that it can be used by
+the host later. See the ACPICA reference for details.
+
+Interpreter: Add a warning if a 64-bit constant appears in a 32-bit table
+(DSDT version < 2). The constant will be truncated and this warning
+reflects that behavior.
+
+Resource Manager: Add support for the new ACPI 5.0 wake bit in the IRQ,
+ExtendedInterrupt, and GpioInt descriptors. This change adds support to
+both get and set the new wake bit in these descriptors, separately from
+the existing share bit. Reported by Aaron Lu.
+
+Interpreter: Fix Store() when an implicit conversion is not possible. For
+example, in the cases such as a store of a string to an existing package
+object, implement the store as a CopyObject(). This is a small departure
+from the ACPI specification which states that the control method should be
+aborted in this case. However, the ASLTS suite depends on this behavior.
+
+Performance improvement for the various FUNCTION_TRACE and DEBUG_PRINT
+macros: check if debug output is currently enabled as soon as possible to
+minimize performance impact if debug is in fact not enabled.
+
+Source code restructuring: Cleanup to improve modularity. The following
+new files have been added: dbconvert.c, evhandler.c, nsprepkg.c,
+psopinfo.c, psobject.c, rsdumpinfo.c, utstring.c, and utownerid.c.
+Associated makefiles and project files have been updated.
+
+Changed an exception code for LoadTable operator. For the case where one
+of the input strings is too long, change the returned exception code from
+AE_BAD_PARAMETER to AE_AML_STRING_LIMIT.
+
+Fixed a possible memory leak in dispatcher error path. On error, delete
+the mutex object created during method mutex creation. Reported by
+tim.gardner@canonical.com.
+
+Example Code and Data Size: These are the sizes for the OS-independent
+acpica.lib produced by the Microsoft Visual C++ 9.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: 94.3K Code, 25.3K Data, 119.6K Total
+ Debug Version: 175.5K Code, 74.5K Data, 250.0K Total
+ Current Release:
+ Non-Debug Version: 94.5K Code, 25.5K Data, 120.0K Total
+ Debug Version: 182.2K Code, 74.9K Data, 257.1K Total
+
+
+2) iASL Compiler/Disassembler and Tools:
+
+iASL: Disallow a method call as argument to the ObjectType ASL operator.
+This change tracks an errata to the ACPI 5.0 document. The AML grammar
+will not allow the interpreter to differentiate between a method and a
+method invocation when these are used as an argument to the ObjectType
+operator. The ACPI specification change is to disallow a method invocation
+(UserTerm) for the ObjectType operator.
+
+Finish support for the TPM2 and CSRT tables in the headers, table
+compiler, and disassembler.
+
+Unix user-space OSL: Fix a problem with WaitSemaphore where the timeout
+always expires immediately if the semaphore is not available. The original
+code was using a relative-time timeout, but sem_timedwait requires the use
+of an absolute time.
+
+iASL: Added a remark if the Timer() operator is used within a 32-bit
+table. This operator returns a 64-bit time value that will be truncated
+within a 32-bit table.
+
+iASL Source code restructuring: Cleanup to improve modularity. The
+following new files have been added: aslhex.c, aslxref.c, aslnamesp.c,
+aslmethod.c, and aslfileio.c. Associated makefiles and project files have
+been updated.
+
+
+----------------------------------------
+14 November 2012. Summary of changes for version 20121114:
1) ACPICA Kernel-resident Subsystem:
diff --git a/sys/contrib/dev/acpica/common/adfile.c b/sys/contrib/dev/acpica/common/adfile.c
index 67d7b79..5cde806 100644
--- a/sys/contrib/dev/acpica/common/adfile.c
+++ b/sys/contrib/dev/acpica/common/adfile.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/common/adisasm.c b/sys/contrib/dev/acpica/common/adisasm.c
index c63d9b5..42befa8 100644
--- a/sys/contrib/dev/acpica/common/adisasm.c
+++ b/sys/contrib/dev/acpica/common/adisasm.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -69,11 +69,11 @@ extern int AslCompilerdebug;
#endif
ACPI_STATUS
-LsDisplayNamespace (
+NsDisplayNamespace (
void);
void
-LsSetupNsList (
+NsSetupNamespaceListing (
void *Handle);
@@ -429,8 +429,8 @@ AdAmlDisassemble (
{
AcpiOsPrintf ("/**** Before second load\n");
- LsSetupNsList (File);
- LsDisplayNamespace ();
+ NsSetupNamespaceListing (File);
+ NsDisplayNamespace ();
AcpiOsPrintf ("*****/\n");
}
@@ -498,8 +498,8 @@ AdAmlDisassemble (
if (AslCompilerdebug)
{
AcpiOsPrintf ("/**** After second load and resource conversion\n");
- LsSetupNsList (File);
- LsDisplayNamespace ();
+ NsSetupNamespaceListing (File);
+ NsDisplayNamespace ();
AcpiOsPrintf ("*****/\n");
AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
@@ -549,8 +549,8 @@ Cleanup:
{
if (AslCompilerdebug) /* Display final namespace, with transforms */
{
- LsSetupNsList (File);
- LsDisplayNamespace ();
+ NsSetupNamespaceListing (File);
+ NsDisplayNamespace ();
}
fclose (File);
diff --git a/sys/contrib/dev/acpica/common/adwalk.c b/sys/contrib/dev/acpica/common/adwalk.c
index af86c91..f801f10 100644
--- a/sys/contrib/dev/acpica/common/adwalk.c
+++ b/sys/contrib/dev/acpica/common/adwalk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/common/ahpredef.c b/sys/contrib/dev/acpica/common/ahpredef.c
index 858a714..4583b58 100644
--- a/sys/contrib/dev/acpica/common/ahpredef.c
+++ b/sys/contrib/dev/acpica/common/ahpredef.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/common/dmextern.c b/sys/contrib/dev/acpica/common/dmextern.c
index f5d676d..67f13f7 100644
--- a/sys/contrib/dev/acpica/common/dmextern.c
+++ b/sys/contrib/dev/acpica/common/dmextern.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/common/dmrestag.c b/sys/contrib/dev/acpica/common/dmrestag.c
index 1e9bd88..54f4282 100644
--- a/sys/contrib/dev/acpica/common/dmrestag.c
+++ b/sys/contrib/dev/acpica/common/dmrestag.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -89,7 +89,7 @@ AcpiDmAddResourceToNamespace (
UINT32 Length,
UINT32 Offset,
UINT8 ResourceIndex,
- void *Context);
+ void **Context);
static void
AcpiDmAddResourcesToNamespace (
@@ -993,7 +993,7 @@ AcpiDmAddResourcesToNamespace (
*/
AcpiUtWalkAmlResources (NULL, (UINT8 *) NextOp->Named.Data,
(ACPI_SIZE) NextOp->Common.Value.Integer,
- AcpiDmAddResourceToNamespace, BufferNode);
+ AcpiDmAddResourceToNamespace, (void **) BufferNode);
}
@@ -1019,7 +1019,7 @@ AcpiDmAddResourceToNamespace (
UINT32 Length,
UINT32 Offset,
UINT8 ResourceIndex,
- void *Context)
+ void **Context)
{
ACPI_STATUS Status;
ACPI_GENERIC_STATE ScopeInfo;
diff --git a/sys/contrib/dev/acpica/common/dmtable.c b/sys/contrib/dev/acpica/common/dmtable.c
index 5d2717c..e569b63 100644
--- a/sys/contrib/dev/acpica/common/dmtable.c
+++ b/sys/contrib/dev/acpica/common/dmtable.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -281,7 +281,7 @@ ACPI_DMTABLE_DATA AcpiDmTableData[] =
{ACPI_SIG_BGRT, AcpiDmTableInfoBgrt, NULL, NULL, TemplateBgrt, "Boot Graphics Resource Table"},
{ACPI_SIG_BOOT, AcpiDmTableInfoBoot, NULL, NULL, TemplateBoot, "Simple Boot Flag Table"},
{ACPI_SIG_CPEP, NULL, AcpiDmDumpCpep, DtCompileCpep, TemplateCpep, "Corrected Platform Error Polling table"},
- {ACPI_SIG_CSRT, NULL, AcpiDmDumpCsrt, NULL, NULL, "Core System Resource Table"},
+ {ACPI_SIG_CSRT, NULL, AcpiDmDumpCsrt, DtCompileCsrt, TemplateCsrt, "Core System Resource Table"},
{ACPI_SIG_DBG2, NULL, AcpiDmDumpDbg2, NULL, NULL, "Debug Port table type 2"},
{ACPI_SIG_DBGP, AcpiDmTableInfoDbgp, NULL, NULL, TemplateDbgp, "Debug Port table"},
{ACPI_SIG_DMAR, NULL, AcpiDmDumpDmar, DtCompileDmar, TemplateDmar, "DMA Remapping table"},
@@ -310,6 +310,7 @@ ACPI_DMTABLE_DATA AcpiDmTableData[] =
{ACPI_SIG_SPMI, AcpiDmTableInfoSpmi, NULL, NULL, TemplateSpmi, "Server Platform Management Interface table"},
{ACPI_SIG_SRAT, NULL, AcpiDmDumpSrat, DtCompileSrat, TemplateSrat, "System Resource Affinity Table"},
{ACPI_SIG_TCPA, AcpiDmTableInfoTcpa, NULL, NULL, TemplateTcpa, "Trusted Computing Platform Alliance table"},
+ {ACPI_SIG_TPM2, AcpiDmTableInfoTpm2, NULL, NULL, TemplateTpm2, "Trusted Platform Module hardware interface table"},
{ACPI_SIG_UEFI, AcpiDmTableInfoUefi, NULL, DtCompileUefi, TemplateUefi, "UEFI Boot Optimization Table"},
{ACPI_SIG_WAET, AcpiDmTableInfoWaet, NULL, NULL, TemplateWaet, "Windows ACPI Emulated Devices Table"},
{ACPI_SIG_WDAT, NULL, AcpiDmDumpWdat, DtCompileWdat, TemplateWdat, "Watchdog Action Table"},
diff --git a/sys/contrib/dev/acpica/common/dmtbdump.c b/sys/contrib/dev/acpica/common/dmtbdump.c
index 2a79b25..ac5ee90 100644
--- a/sys/contrib/dev/acpica/common/dmtbdump.c
+++ b/sys/contrib/dev/acpica/common/dmtbdump.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -614,6 +614,7 @@ AcpiDmDumpCsrt (
{
ACPI_STATUS Status;
ACPI_CSRT_GROUP *SubTable;
+ ACPI_CSRT_SHARED_INFO *SharedInfoTable;
ACPI_CSRT_DESCRIPTOR *SubSubTable;
UINT32 Length = Table->Length;
UINT32 Offset = sizeof (ACPI_TABLE_CSRT);
@@ -629,6 +630,8 @@ AcpiDmDumpCsrt (
SubTable = ACPI_ADD_PTR (ACPI_CSRT_GROUP, Table, Offset);
while (Offset < Table->Length)
{
+ /* Resource group subtable */
+
AcpiOsPrintf ("\n");
Status = AcpiDmDumpTable (Length, Offset, SubTable,
SubTable->Length, AcpiDmTableInfoCsrt0);
@@ -637,15 +640,23 @@ AcpiDmDumpCsrt (
return;
}
+ /* Shared info subtable (One per resource group) */
+
SubOffset = sizeof (ACPI_CSRT_GROUP);
+ SharedInfoTable = ACPI_ADD_PTR (ACPI_CSRT_SHARED_INFO, Table,
+ Offset + SubOffset);
- /* Shared resource group info buffer */
+ AcpiOsPrintf ("\n");
+ Status = AcpiDmDumpTable (Length, Offset + SubOffset, SharedInfoTable,
+ sizeof (ACPI_CSRT_SHARED_INFO), AcpiDmTableInfoCsrt1);
+ if (ACPI_FAILURE (Status))
+ {
+ return;
+ }
- AcpiDmDumpBuffer (SubTable, SubOffset, SubTable->InfoLength,
- Offset+SubOffset, "Shared Data");
- SubOffset += SubTable->InfoLength;
+ SubOffset += SubTable->SharedInfoLength;
- /* Sub-Sub-tables (Resource Descriptors) */
+ /* Sub-Subtables (Resource Descriptors) */
SubSubTable = ACPI_ADD_PTR (ACPI_CSRT_DESCRIPTOR, Table,
Offset + SubOffset);
@@ -655,7 +666,7 @@ AcpiDmDumpCsrt (
{
AcpiOsPrintf ("\n");
Status = AcpiDmDumpTable (Length, Offset + SubOffset, SubSubTable,
- SubSubTable->Length, AcpiDmTableInfoCsrt1);
+ SubSubTable->Length, AcpiDmTableInfoCsrt2);
if (ACPI_FAILURE (Status))
{
return;
@@ -671,7 +682,7 @@ AcpiDmDumpCsrt (
Offset + SubOffset + SubSubOffset, "ResourceInfo");
SubSubOffset += InfoLength;
- /* Point to next sub-sub-table */
+ /* Point to next sub-subtable */
SubOffset += SubSubTable->Length;
SubSubTable = ACPI_ADD_PTR (ACPI_CSRT_DESCRIPTOR, SubSubTable,
diff --git a/sys/contrib/dev/acpica/common/dmtbinfo.c b/sys/contrib/dev/acpica/common/dmtbinfo.c
index 21fddec..54bd5c2 100644
--- a/sys/contrib/dev/acpica/common/dmtbinfo.c
+++ b/sys/contrib/dev/acpica/common/dmtbinfo.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -111,6 +111,7 @@
#define ACPI_SPMI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SPMI,f)
#define ACPI_SRAT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SRAT,f)
#define ACPI_TCPA_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA,f)
+#define ACPI_TPM2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TPM2,f)
#define ACPI_UEFI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_UEFI,f)
#define ACPI_WAET_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WAET,f)
#define ACPI_WDAT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WDAT,f)
@@ -128,7 +129,8 @@
#define ACPI_ASF4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASF_ADDRESS,f)
#define ACPI_CPEP0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CPEP_POLLING,f)
#define ACPI_CSRT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CSRT_GROUP,f)
-#define ACPI_CSRT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CSRT_DESCRIPTOR,f)
+#define ACPI_CSRT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CSRT_SHARED_INFO,f)
+#define ACPI_CSRT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CSRT_DESCRIPTOR,f)
#define ACPI_DBG20_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DBG2_DEVICE,f)
#define ACPI_DMARS_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_DEVICE_SCOPE,f)
#define ACPI_DMAR0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_HARDWARE_UNIT,f)
@@ -662,18 +664,38 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt0[] =
{ACPI_DMT_UINT16, ACPI_CSRT0_OFFSET (SubdeviceId), "Subdevice ID", 0},
{ACPI_DMT_UINT16, ACPI_CSRT0_OFFSET (Revision), "Revision", 0},
{ACPI_DMT_UINT16, ACPI_CSRT0_OFFSET (Reserved), "Reserved", 0},
- {ACPI_DMT_UINT32, ACPI_CSRT0_OFFSET (InfoLength), "InfoLength", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT0_OFFSET (SharedInfoLength), "Shared Info Length", 0},
ACPI_DMT_TERMINATOR
};
-/* Resource Descriptor subtable */
+/* Shared Info subtable */
ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt1[] =
{
- {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (Length), "Length", 0},
- {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (Type), "Type", 0},
- {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (Subtype), "Subtype", 0},
- {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (Uid), "UID", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (MajorVersion), "Major Version", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (MinorVersion), "Minor Version", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (MmioBaseLow), "MMIO Base Address Low", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (MmioBaseHigh), "MMIO Base Address High", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (GsiInterrupt), "GSI Interrupt", 0},
+ {ACPI_DMT_UINT8, ACPI_CSRT1_OFFSET (InterruptPolarity), "Interrupt Polarity", 0},
+ {ACPI_DMT_UINT8, ACPI_CSRT1_OFFSET (InterruptMode), "Interrupt Mode", 0},
+ {ACPI_DMT_UINT8, ACPI_CSRT1_OFFSET (NumChannels), "Num Channels", 0},
+ {ACPI_DMT_UINT8, ACPI_CSRT1_OFFSET (DmaAddressWidth), "DMA Address Width", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (BaseRequestLine), "Base Request Line", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT1_OFFSET (NumHandshakeSignals), "Num Handshake Signals", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT1_OFFSET (MaxBlockSize), "Max Block Size", 0},
+ ACPI_DMT_TERMINATOR
+};
+
+
+/* Resource Descriptor subtable */
+
+ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt2[] =
+{
+ {ACPI_DMT_UINT32, ACPI_CSRT2_OFFSET (Length), "Length", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT2_OFFSET (Type), "Type", 0},
+ {ACPI_DMT_UINT16, ACPI_CSRT2_OFFSET (Subtype), "Subtype", 0},
+ {ACPI_DMT_UINT32, ACPI_CSRT2_OFFSET (Uid), "UID", 0},
ACPI_DMT_TERMINATOR
};
@@ -1984,6 +2006,21 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoTcpa[] =
/*******************************************************************************
*
+ * TPM2 - Trusted Platform Module (TPM) 2.0 Hardware Interface Table
+ *
+ ******************************************************************************/
+
+ACPI_DMTABLE_INFO AcpiDmTableInfoTpm2[] =
+{
+ {ACPI_DMT_UINT32, ACPI_TPM2_OFFSET (Flags), "Flags", 0},
+ {ACPI_DMT_UINT64, ACPI_TPM2_OFFSET (ControlAddress), "Control Address", 0},
+ {ACPI_DMT_UINT32, ACPI_TPM2_OFFSET (StartMethod), "Start Method", 0},
+ ACPI_DMT_TERMINATOR
+};
+
+
+/*******************************************************************************
+ *
* UEFI - UEFI Boot optimization Table
*
******************************************************************************/
diff --git a/sys/contrib/dev/acpica/common/getopt.c b/sys/contrib/dev/acpica/common/getopt.c
index 3855fa5..6bedff6 100644
--- a/sys/contrib/dev/acpica/common/getopt.c
+++ b/sys/contrib/dev/acpica/common/getopt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslanalyze.c b/sys/contrib/dev/acpica/compiler/aslanalyze.c
index ea4ee35..a42526c 100644
--- a/sys/contrib/dev/acpica/compiler/aslanalyze.c
+++ b/sys/contrib/dev/acpica/compiler/aslanalyze.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslbtypes.c b/sys/contrib/dev/acpica/compiler/aslbtypes.c
index d7140d2..aac3870 100644
--- a/sys/contrib/dev/acpica/compiler/aslbtypes.c
+++ b/sys/contrib/dev/acpica/compiler/aslbtypes.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslcodegen.c b/sys/contrib/dev/acpica/compiler/aslcodegen.c
index 571e5dd..13ba665 100644
--- a/sys/contrib/dev/acpica/compiler/aslcodegen.c
+++ b/sys/contrib/dev/acpica/compiler/aslcodegen.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslcompile.c b/sys/contrib/dev/acpica/compiler/aslcompile.c
index 4ca98f6..6d4c466 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompile.c
+++ b/sys/contrib/dev/acpica/compiler/aslcompile.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -617,7 +617,7 @@ CmDoCompile (
/* Namespace cross-reference */
AslGbl_NamespaceEvent = UtBeginEvent ("Cross reference parse tree and Namespace");
- Status = LkCrossReferenceNamespace ();
+ Status = XfCrossReferenceNamespace ();
if (ACPI_FAILURE (Status))
{
goto ErrorExit;
@@ -639,8 +639,8 @@ CmDoCompile (
DbgPrint (ASL_DEBUG_OUTPUT, "\nSemantic analysis - Method analysis\n\n");
TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE,
- AnMethodAnalysisWalkBegin,
- AnMethodAnalysisWalkEnd, &AnalysisWalkInfo);
+ MtMethodAnalysisWalkBegin,
+ MtMethodAnalysisWalkEnd, &AnalysisWalkInfo);
UtEndEvent (Event);
/* Semantic error checking part two - typing of method returns */
@@ -719,11 +719,11 @@ CmDoOutputFiles (
/* Create listings and hex files */
LsDoListings ();
- LsDoHexOutput ();
+ HxDoHexOutput ();
/* Dump the namespace to the .nsp file if requested */
- (void) LsDisplayNamespace ();
+ (void) NsDisplayNamespace ();
}
@@ -766,12 +766,12 @@ CmDumpAllEvents (
Delta = (UINT32) (Event->EndTime - Event->StartTime);
- USec = Delta / 10;
- MSec = Delta / 10000;
+ USec = Delta / ACPI_100NSEC_PER_USEC;
+ MSec = Delta / ACPI_100NSEC_PER_MSEC;
/* Round milliseconds up */
- if ((USec - (MSec * 1000)) >= 500)
+ if ((USec - (MSec * ACPI_USEC_PER_MSEC)) >= 500)
{
MSec++;
}
diff --git a/sys/contrib/dev/acpica/compiler/aslcompiler.h b/sys/contrib/dev/acpica/compiler/aslcompiler.h
index 72c21ab..d772e8f 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompiler.h
+++ b/sys/contrib/dev/acpica/compiler/aslcompiler.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -188,19 +188,23 @@ AnOperandTypecheckWalkEnd (
void *Context);
ACPI_STATUS
-AnMethodAnalysisWalkBegin (
+AnMethodTypingWalkEnd (
ACPI_PARSE_OBJECT *Op,
UINT32 Level,
void *Context);
+
+/*
+ * aslmethod - Control method analysis walk
+ */
ACPI_STATUS
-AnMethodAnalysisWalkEnd (
+MtMethodAnalysisWalkBegin (
ACPI_PARSE_OBJECT *Op,
UINT32 Level,
void *Context);
ACPI_STATUS
-AnMethodTypingWalkEnd (
+MtMethodAnalysisWalkEnd (
ACPI_PARSE_OBJECT *Op,
UINT32 Level,
void *Context);
@@ -342,6 +346,12 @@ LsDoListings (
void);
void
+LsDumpAsciiInComment (
+ UINT32 FileId,
+ UINT32 Count,
+ UINT8 *Buffer);
+
+void
LsWriteNodeToAsmListing (
ACPI_PARSE_OBJECT *Op);
@@ -351,13 +361,18 @@ LsWriteNode (
UINT32 FileId);
void
-LsDoHexOutput (
+LsDumpParseTree (
void);
+
+/*
+ * aslhex - generate all "hex" output files (C, ASM, ASL)
+ */
void
-LsDumpParseTree (
+HxDoHexOutput (
void);
+
/*
* aslfold - constant folding
*/
@@ -689,26 +704,34 @@ LdLoadNamespace (
/*
- * asllookup - namespace cross reference
+ * asllookup - namespace lookup functions
*/
-ACPI_STATUS
-LkCrossReferenceNamespace (
- void);
-
void
LkFindUnreferencedObjects (
void);
+
+/*
+ * aslnamesp - namespace output file generation
+ */
ACPI_STATUS
-LsDisplayNamespace (
+NsDisplayNamespace (
void);
void
-LsSetupNsList (
+NsSetupNamespaceListing (
void *Handle);
/*
+ * aslxref - namespace cross reference
+ */
+ACPI_STATUS
+XfCrossReferenceNamespace (
+ void);
+
+
+/*
* aslutils - common compiler utilites
*/
void
diff --git a/sys/contrib/dev/acpica/compiler/aslcompiler.l b/sys/contrib/dev/acpica/compiler/aslcompiler.l
index 5b9ff12..5b2d9ce 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompiler.l
+++ b/sys/contrib/dev/acpica/compiler/aslcompiler.l
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -201,7 +201,7 @@ NamePathTail [.]{NameSeg}
"Mutex" { count (2); return (PARSEOP_MUTEX); }
"Name" { count (2); return (PARSEOP_NAME); }
"NAnd" { count (3); return (PARSEOP_NAND); }
-"Noop" { count (3); return (PARSEOP_NOOP); }
+"Noop" { if (!AcpiGbl_IgnoreNoopOperator) {count (3); return (PARSEOP_NOOP);} }
"NOr" { count (3); return (PARSEOP_NOR); }
"Not" { count (3); return (PARSEOP_NOT); }
"Notify" { count (3); return (PARSEOP_NOTIFY); }
diff --git a/sys/contrib/dev/acpica/compiler/aslcompiler.y b/sys/contrib/dev/acpica/compiler/aslcompiler.y
index b6453ac..42ff850 100644
--- a/sys/contrib/dev/acpica/compiler/aslcompiler.y
+++ b/sys/contrib/dev/acpica/compiler/aslcompiler.y
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -661,6 +661,7 @@ void * AslLocalAllocate (unsigned int Size);
/* Types */
%type <n> SuperName
+%type <n> ObjectTypeName
%type <n> ArgTerm
%type <n> LocalTerm
%type <n> DebugTerm
@@ -1991,7 +1992,7 @@ NotTerm
ObjectTypeTerm
: PARSEOP_OBJECTTYPE '(' {$<n>$ = TrCreateLeafNode (PARSEOP_OBJECTTYPE);}
- SuperName
+ ObjectTypeName
')' {$$ = TrLinkChildren ($<n>3,1,$4);}
| PARSEOP_OBJECTTYPE '('
error ')' {$$ = AslDoError(); yyclearin;}
@@ -2439,6 +2440,18 @@ SuperName
| LocalTerm {}
| DebugTerm {}
| Type6Opcode {}
+
+/* For ObjectType: SuperName except for UserTerm (method invocation) */
+
+ObjectTypeName
+ : NameString {}
+ | ArgTerm {}
+ | LocalTerm {}
+ | DebugTerm {}
+ | RefOfTerm {}
+ | DerefOfTerm {}
+ | IndexTerm {}
+
/* | UserTerm {} */ /* Caused reduce/reduce with Type6Opcode->UserTerm */
;
diff --git a/sys/contrib/dev/acpica/compiler/asldefine.h b/sys/contrib/dev/acpica/compiler/asldefine.h
index 0ee3c69..7c8bd66 100644
--- a/sys/contrib/dev/acpica/compiler/asldefine.h
+++ b/sys/contrib/dev/acpica/compiler/asldefine.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslerror.c b/sys/contrib/dev/acpica/compiler/aslerror.c
index 41ae967..f362589 100644
--- a/sys/contrib/dev/acpica/compiler/aslerror.c
+++ b/sys/contrib/dev/acpica/compiler/aslerror.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -660,7 +660,6 @@ AslCommonError (
Gbl_SourceLine = 0;
Gbl_NextError = Gbl_ErrorLog;
- CmDoOutputFiles ();
CmCleanupAndExit ();
exit(1);
}
diff --git a/sys/contrib/dev/acpica/compiler/aslfileio.c b/sys/contrib/dev/acpica/compiler/aslfileio.c
new file mode 100644
index 0000000..660b82f
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslfileio.c
@@ -0,0 +1,393 @@
+/******************************************************************************
+ *
+ * Module Name: aslfileio - File I/O support
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslfileio")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AslAbort
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
+ * I/O errors.
+ *
+ ******************************************************************************/
+
+void
+AslAbort (
+ void)
+{
+
+ AePrintErrorLog (ASL_FILE_STDERR);
+ if (Gbl_DebugFlag)
+ {
+ /* Print error summary to stdout also */
+
+ AePrintErrorLog (ASL_FILE_STDOUT);
+ }
+
+ exit (1);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlFileError
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * ErrorId - Index into error message array
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Decode errno to an error message and add the entire error
+ * to the error log.
+ *
+ ******************************************************************************/
+
+void
+FlFileError (
+ UINT32 FileId,
+ UINT8 ErrorId)
+{
+
+ sprintf (MsgBuffer, "\"%s\" (%s)", Gbl_Files[FileId].Filename,
+ strerror (errno));
+ AslCommonError (ASL_ERROR, ErrorId, 0, 0, 0, 0, NULL, MsgBuffer);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlOpenFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * Filename - file pathname to open
+ * Mode - Open mode for fopen
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Open a file.
+ * NOTE: Aborts compiler on any error.
+ *
+ ******************************************************************************/
+
+void
+FlOpenFile (
+ UINT32 FileId,
+ char *Filename,
+ char *Mode)
+{
+ FILE *File;
+
+
+ File = fopen (Filename, Mode);
+ if (!File)
+ {
+ FlFileError (FileId, ASL_MSG_OPEN);
+ AslAbort ();
+ }
+
+ Gbl_Files[FileId].Filename = Filename;
+ Gbl_Files[FileId].Handle = File;
+}
+
+
+/*******************************************************************************
+ *
+ * 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;
+ long Offset;
+
+
+ fp = Gbl_Files[FileId].Handle;
+ Offset = ftell (fp);
+
+ fseek (fp, 0, SEEK_END);
+ FileSize = (UINT32) ftell (fp);
+
+ /* Restore file pointer */
+
+ fseek (fp, Offset, SEEK_SET);
+ return (FileSize);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlReadFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * Buffer - Where to place the data
+ * Length - Amount to read
+ *
+ * RETURN: Status. AE_ERROR indicates EOF.
+ *
+ * DESCRIPTION: Read data from an open file.
+ * NOTE: Aborts compiler on any error.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+FlReadFile (
+ UINT32 FileId,
+ void *Buffer,
+ UINT32 Length)
+{
+ UINT32 Actual;
+
+
+ /* Read and check for error */
+
+ Actual = fread (Buffer, 1, Length, Gbl_Files[FileId].Handle);
+ if (Actual < Length)
+ {
+ if (feof (Gbl_Files[FileId].Handle))
+ {
+ /* End-of-file, just return error */
+
+ return (AE_ERROR);
+ }
+
+ FlFileError (FileId, ASL_MSG_READ);
+ AslAbort ();
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlWriteFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * Buffer - Data to write
+ * Length - Amount of data to write
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Write data to an open file.
+ * NOTE: Aborts compiler on any error.
+ *
+ ******************************************************************************/
+
+void
+FlWriteFile (
+ UINT32 FileId,
+ void *Buffer,
+ UINT32 Length)
+{
+ UINT32 Actual;
+
+
+ /* Write and check for error */
+
+ Actual = fwrite ((char *) Buffer, 1, Length, Gbl_Files[FileId].Handle);
+ if (Actual != Length)
+ {
+ FlFileError (FileId, ASL_MSG_WRITE);
+ AslAbort ();
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlPrintFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * Format - Printf format string
+ * ... - Printf arguments
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Formatted write to an open file.
+ * NOTE: Aborts compiler on any error.
+ *
+ ******************************************************************************/
+
+void
+FlPrintFile (
+ UINT32 FileId,
+ char *Format,
+ ...)
+{
+ INT32 Actual;
+ va_list Args;
+
+
+ va_start (Args, Format);
+
+ Actual = vfprintf (Gbl_Files[FileId].Handle, Format, Args);
+ va_end (Args);
+
+ if (Actual == -1)
+ {
+ FlFileError (FileId, ASL_MSG_WRITE);
+ AslAbort ();
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlSeekFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ * Offset - Absolute byte offset in file
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Seek to absolute offset.
+ * NOTE: Aborts compiler on any error.
+ *
+ ******************************************************************************/
+
+void
+FlSeekFile (
+ UINT32 FileId,
+ long Offset)
+{
+ int Error;
+
+
+ Error = fseek (Gbl_Files[FileId].Handle, Offset, SEEK_SET);
+ if (Error)
+ {
+ FlFileError (FileId, ASL_MSG_SEEK);
+ AslAbort ();
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlCloseFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Close an open file. Aborts compiler on error
+ *
+ ******************************************************************************/
+
+void
+FlCloseFile (
+ UINT32 FileId)
+{
+ int Error;
+
+
+ if (!Gbl_Files[FileId].Handle)
+ {
+ return;
+ }
+
+ Error = fclose (Gbl_Files[FileId].Handle);
+ if (Error)
+ {
+ FlFileError (FileId, ASL_MSG_CLOSE);
+ AslAbort ();
+ }
+
+ Gbl_Files[FileId].Handle = NULL;
+ return;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: FlDeleteFile
+ *
+ * PARAMETERS: FileId - Index into file info array
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Delete a file.
+ *
+ ******************************************************************************/
+
+void
+FlDeleteFile (
+ UINT32 FileId)
+{
+ ASL_FILE_INFO *Info = &Gbl_Files[FileId];
+
+
+ if (!Info->Filename)
+ {
+ return;
+ }
+
+ if (remove (Info->Filename))
+ {
+ printf ("%s (%s file) ",
+ Info->Filename, Info->Description);
+ perror ("Could not delete");
+ }
+
+ Info->Filename = NULL;
+ return;
+}
diff --git a/sys/contrib/dev/acpica/compiler/aslfiles.c b/sys/contrib/dev/acpica/compiler/aslfiles.c
index 39f64b7..a525fc2 100644
--- a/sys/contrib/dev/acpica/compiler/aslfiles.c
+++ b/sys/contrib/dev/acpica/compiler/aslfiles.c
@@ -1,11 +1,11 @@
/******************************************************************************
*
- * Module Name: aslfiles - file I/O suppoert
+ * Module Name: aslfiles - File support functions
*
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -64,352 +64,6 @@ FlParseInputPathname (
/*******************************************************************************
*
- * FUNCTION: AslAbort
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Dump the error log and abort the compiler. Used for serious
- * I/O errors
- *
- ******************************************************************************/
-
-void
-AslAbort (
- void)
-{
-
- AePrintErrorLog (ASL_FILE_STDERR);
- if (Gbl_DebugFlag)
- {
- /* Print error summary to stdout also */
-
- AePrintErrorLog (ASL_FILE_STDOUT);
- }
-
- exit (1);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlFileError
- *
- * PARAMETERS: FileId - Index into file info array
- * ErrorId - Index into error message array
- *
- * RETURN: None
- *
- * DESCRIPTION: Decode errno to an error message and add the entire error
- * to the error log.
- *
- ******************************************************************************/
-
-void
-FlFileError (
- UINT32 FileId,
- UINT8 ErrorId)
-{
-
- sprintf (MsgBuffer, "\"%s\" (%s)", Gbl_Files[FileId].Filename,
- strerror (errno));
- AslCommonError (ASL_ERROR, ErrorId, 0, 0, 0, 0, NULL, MsgBuffer);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlOpenFile
- *
- * PARAMETERS: FileId - Index into file info array
- * Filename - file pathname to open
- * Mode - Open mode for fopen
- *
- * RETURN: None
- *
- * DESCRIPTION: Open a file.
- * NOTE: Aborts compiler on any error.
- *
- ******************************************************************************/
-
-void
-FlOpenFile (
- UINT32 FileId,
- char *Filename,
- char *Mode)
-{
- FILE *File;
-
-
- File = fopen (Filename, Mode);
- if (!File)
- {
- FlFileError (FileId, ASL_MSG_OPEN);
- AslAbort ();
- }
-
- Gbl_Files[FileId].Filename = Filename;
- Gbl_Files[FileId].Handle = File;
-}
-
-
-/*******************************************************************************
- *
- * 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;
- long Offset;
-
-
- fp = Gbl_Files[FileId].Handle;
- Offset = ftell (fp);
-
- fseek (fp, 0, SEEK_END);
- FileSize = (UINT32) ftell (fp);
-
- /* Restore file pointer */
-
- fseek (fp, Offset, SEEK_SET);
- return (FileSize);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlReadFile
- *
- * PARAMETERS: FileId - Index into file info array
- * Buffer - Where to place the data
- * Length - Amount to read
- *
- * RETURN: Status. AE_ERROR indicates EOF.
- *
- * DESCRIPTION: Read data from an open file.
- * NOTE: Aborts compiler on any error.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-FlReadFile (
- UINT32 FileId,
- void *Buffer,
- UINT32 Length)
-{
- UINT32 Actual;
-
-
- /* Read and check for error */
-
- Actual = fread (Buffer, 1, Length, Gbl_Files[FileId].Handle);
- if (Actual < Length)
- {
- if (feof (Gbl_Files[FileId].Handle))
- {
- /* End-of-file, just return error */
-
- return (AE_ERROR);
- }
-
- FlFileError (FileId, ASL_MSG_READ);
- AslAbort ();
- }
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlWriteFile
- *
- * PARAMETERS: FileId - Index into file info array
- * Buffer - Data to write
- * Length - Amount of data to write
- *
- * RETURN: None
- *
- * DESCRIPTION: Write data to an open file.
- * NOTE: Aborts compiler on any error.
- *
- ******************************************************************************/
-
-void
-FlWriteFile (
- UINT32 FileId,
- void *Buffer,
- UINT32 Length)
-{
- UINT32 Actual;
-
-
- /* Write and check for error */
-
- Actual = fwrite ((char *) Buffer, 1, Length, Gbl_Files[FileId].Handle);
- if (Actual != Length)
- {
- FlFileError (FileId, ASL_MSG_WRITE);
- AslAbort ();
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlPrintFile
- *
- * PARAMETERS: FileId - Index into file info array
- * Format - Printf format string
- * ... - Printf arguments
- *
- * RETURN: None
- *
- * DESCRIPTION: Formatted write to an open file.
- * NOTE: Aborts compiler on any error.
- *
- ******************************************************************************/
-
-void
-FlPrintFile (
- UINT32 FileId,
- char *Format,
- ...)
-{
- INT32 Actual;
- va_list Args;
-
-
- va_start (Args, Format);
-
- Actual = vfprintf (Gbl_Files[FileId].Handle, Format, Args);
- va_end (Args);
-
- if (Actual == -1)
- {
- FlFileError (FileId, ASL_MSG_WRITE);
- AslAbort ();
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlSeekFile
- *
- * PARAMETERS: FileId - Index into file info array
- * Offset - Absolute byte offset in file
- *
- * RETURN: None
- *
- * DESCRIPTION: Seek to absolute offset
- * NOTE: Aborts compiler on any error.
- *
- ******************************************************************************/
-
-void
-FlSeekFile (
- UINT32 FileId,
- long Offset)
-{
- int Error;
-
-
- Error = fseek (Gbl_Files[FileId].Handle, Offset, SEEK_SET);
- if (Error)
- {
- FlFileError (FileId, ASL_MSG_SEEK);
- AslAbort ();
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlCloseFile
- *
- * PARAMETERS: FileId - Index into file info array
- *
- * RETURN: None
- *
- * DESCRIPTION: Close an open file. Aborts compiler on error
- *
- ******************************************************************************/
-
-void
-FlCloseFile (
- UINT32 FileId)
-{
- int Error;
-
-
- if (!Gbl_Files[FileId].Handle)
- {
- return;
- }
-
- Error = fclose (Gbl_Files[FileId].Handle);
- if (Error)
- {
- FlFileError (FileId, ASL_MSG_CLOSE);
- AslAbort ();
- }
-
- Gbl_Files[FileId].Handle = NULL;
- return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: FlDeleteFile
- *
- * PARAMETERS: FileId - Index into file info array
- *
- * RETURN: None
- *
- * DESCRIPTION: Delete a file.
- *
- ******************************************************************************/
-
-void
-FlDeleteFile (
- UINT32 FileId)
-{
- ASL_FILE_INFO *Info = &Gbl_Files[FileId];
-
-
- if (!Info->Filename)
- {
- return;
- }
-
- if (remove (Info->Filename))
- {
- printf ("%s (%s file) ",
- Info->Filename, Info->Description);
- perror ("Could not delete");
- }
-
- Info->Filename = NULL;
- return;
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: FlSetLineNumber
*
* PARAMETERS: Op - Parse node for the LINE asl statement
diff --git a/sys/contrib/dev/acpica/compiler/aslfold.c b/sys/contrib/dev/acpica/compiler/aslfold.c
index e5b6520..c01bce4 100644
--- a/sys/contrib/dev/acpica/compiler/aslfold.c
+++ b/sys/contrib/dev/acpica/compiler/aslfold.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslglobal.h b/sys/contrib/dev/acpica/compiler/aslglobal.h
index 101b23d..1b1f67c 100644
--- a/sys/contrib/dev/acpica/compiler/aslglobal.h
+++ b/sys/contrib/dev/acpica/compiler/aslglobal.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslhex.c b/sys/contrib/dev/acpica/compiler/aslhex.c
new file mode 100644
index 0000000..c6b310e
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslhex.c
@@ -0,0 +1,401 @@
+/******************************************************************************
+ *
+ * Module Name: aslhex - ASCII hex output file generation (C, ASM, and ASL)
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("ashex")
+
+/*
+ * This module emits ASCII hex output files in either C, ASM, or ASL format
+ */
+
+
+/* Local prototypes */
+
+static void
+HxDoHexOutputC (
+ void);
+
+static void
+HxDoHexOutputAsl (
+ void);
+
+static void
+HxDoHexOutputAsm (
+ void);
+
+static UINT32
+HxReadAmlOutputFile (
+ UINT8 *Buffer);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: HxDoHexOutput
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Create the hex output file. Note: data is obtained by reading
+ * the entire AML output file that was previously generated.
+ *
+ ******************************************************************************/
+
+void
+HxDoHexOutput (
+ void)
+{
+
+ switch (Gbl_HexOutputFlag)
+ {
+ case HEX_OUTPUT_C:
+
+ HxDoHexOutputC ();
+ break;
+
+ case HEX_OUTPUT_ASM:
+
+ HxDoHexOutputAsm ();
+ break;
+
+ case HEX_OUTPUT_ASL:
+
+ HxDoHexOutputAsl ();
+ break;
+
+ default:
+ /* No other output types supported */
+ break;
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: HxReadAmlOutputFile
+ *
+ * PARAMETERS: Buffer - Where to return data
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Read a line of the AML output prior to formatting the data
+ *
+ ******************************************************************************/
+
+static UINT32
+HxReadAmlOutputFile (
+ UINT8 *Buffer)
+{
+ UINT32 Actual;
+
+
+ Actual = fread (Buffer, 1, HEX_TABLE_LINE_SIZE,
+ Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
+
+ if (ferror (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle))
+ {
+ FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
+ AslAbort ();
+ }
+
+ return (Actual);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: HxDoHexOutputC
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+static void
+HxDoHexOutputC (
+ void)
+{
+ 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);
+ FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
+
+ 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");
+
+ while (Offset < AmlFileSize)
+ {
+ /* Read enough bytes needed for one output line */
+
+ LineLength = HxReadAmlOutputFile (FileData);
+ 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");
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: HxDoHexOutputAsl
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+static void
+HxDoHexOutputAsl (
+ void)
+{
+ 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);
+ FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
+
+ 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 = HxReadAmlOutputFile (FileData);
+ 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");
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: HxDoHexOutputAsm
+ *
+ * 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 ASM source file.
+ *
+ ******************************************************************************/
+
+static void
+HxDoHexOutputAsm (
+ void)
+{
+ 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);
+ 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);
+
+ while (Offset < AmlFileSize)
+ {
+ /* Read enough bytes needed for one output line */
+
+ LineLength = HxReadAmlOutputFile (FileData);
+ if (!LineLength)
+ {
+ break;
+ }
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, " db ");
+
+ for (i = 0; i < LineLength; i++)
+ {
+ /*
+ * 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, ",");
+ }
+ }
+
+ 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, "\n");
+
+ Offset += LineLength;
+ }
+
+ FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
+}
diff --git a/sys/contrib/dev/acpica/compiler/asllength.c b/sys/contrib/dev/acpica/compiler/asllength.c
index ef113f9..57835a6 100644
--- a/sys/contrib/dev/acpica/compiler/asllength.c
+++ b/sys/contrib/dev/acpica/compiler/asllength.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/asllisting.c b/sys/contrib/dev/acpica/compiler/asllisting.c
index 9a85fd7..49c43fb 100644
--- a/sys/contrib/dev/acpica/compiler/asllisting.c
+++ b/sys/contrib/dev/acpica/compiler/asllisting.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,12 +59,6 @@ LsDumpAscii (
UINT32 Count,
UINT8 *Buffer);
-static void
-LsDumpAsciiInComment (
- UINT32 FileId,
- UINT32 Count,
- UINT8 *Buffer);
-
static ACPI_STATUS
LsAmlListingWalk (
ACPI_PARSE_OBJECT *Op,
@@ -117,27 +111,57 @@ LsWriteNodeToListing (
ACPI_PARSE_OBJECT *Op,
UINT32 FileId);
-static void
-LsDoHexOutputC (
- void);
-
-static void
-LsDoHexOutputAsm (
- void);
-
-static void
-LsDoHexOutputAsl (
- void);
-
static ACPI_STATUS
LsTreeWriteWalk (
ACPI_PARSE_OBJECT *Op,
UINT32 Level,
void *Context);
-static UINT32
-LsReadAmlOutputFile (
- UINT8 *Buffer);
+#define ASL_LISTING_LINE_PREFIX ": "
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: LsDoListings
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Generate all requested listing files.
+ *
+ ******************************************************************************/
+
+void
+LsDoListings (
+ void)
+{
+
+ if (Gbl_C_OutputFlag)
+ {
+ LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT);
+ }
+
+ if (Gbl_ListingFlag)
+ {
+ LsGenerateListing (ASL_FILE_LISTING_OUTPUT);
+ }
+
+ if (Gbl_AsmOutputFlag)
+ {
+ LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT);
+ }
+
+ if (Gbl_C_IncludeOutputFlag)
+ {
+ LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT);
+ }
+
+ if (Gbl_AsmIncludeOutputFlag)
+ {
+ LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT);
+ }
+}
/*******************************************************************************
@@ -147,7 +171,7 @@ LsReadAmlOutputFile (
* PARAMETERS: ASL_WALK_CALLBACK
*
*
- * RETURN: None.
+ * RETURN: None
*
* DESCRIPTION: Dump entire parse tree, for compiler debug only
*
@@ -196,7 +220,7 @@ LsDumpParseTree (
* Count - Number of bytes to convert
* Buffer - Buffer of bytes to convert
*
- * RETURN: None.
+ * RETURN: None
*
* DESCRIPTION: Convert hex bytes to ascii
*
@@ -239,13 +263,13 @@ LsDumpAscii (
* Count - Number of bytes to convert
* Buffer - Buffer of bytes to convert
*
- * RETURN: None.
+ * RETURN: None
*
* DESCRIPTION: Convert hex bytes to ascii
*
******************************************************************************/
-static void
+void
LsDumpAsciiInComment (
UINT32 FileId,
UINT32 Count,
@@ -374,50 +398,6 @@ LsGenerateListing (
/*******************************************************************************
*
- * FUNCTION: LsDoListings
- *
- * PARAMETERS: None.
- *
- * RETURN: None
- *
- * DESCRIPTION: Generate all requested listing files.
- *
- ******************************************************************************/
-
-void
-LsDoListings (
- void)
-{
-
- if (Gbl_C_OutputFlag)
- {
- LsGenerateListing (ASL_FILE_C_SOURCE_OUTPUT);
- }
-
- if (Gbl_ListingFlag)
- {
- LsGenerateListing (ASL_FILE_LISTING_OUTPUT);
- }
-
- if (Gbl_AsmOutputFlag)
- {
- LsGenerateListing (ASL_FILE_ASM_SOURCE_OUTPUT);
- }
-
- if (Gbl_C_IncludeOutputFlag)
- {
- LsGenerateListing (ASL_FILE_C_INCLUDE_OUTPUT);
- }
-
- if (Gbl_AsmIncludeOutputFlag)
- {
- LsGenerateListing (ASL_FILE_ASM_INCLUDE_OUTPUT);
- }
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: LsPushNode
*
* PARAMETERS: Filename - Pointer to the include filename
@@ -687,7 +667,8 @@ LsWriteListingHexBytes (
{
case ASL_FILE_LISTING_OUTPUT:
- FlPrintFile (FileId, "%8.8X....", Gbl_CurrentAmlOffset);
+ FlPrintFile (FileId, "%8.8X%s", Gbl_CurrentAmlOffset,
+ ASL_LISTING_LINE_PREFIX);
break;
case ASL_FILE_ASM_SOURCE_OUTPUT:
@@ -747,6 +728,24 @@ LsWriteOneSourceLine (
Gbl_SourceLine++;
Gbl_ListingNode->LineNumber++;
+ /* Ignore lines that are completely blank (but count the line above) */
+
+ if (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) != AE_OK)
+ {
+ return (0);
+ }
+ if (FileByte == '\n')
+ {
+ return (1);
+ }
+
+ /*
+ * This is a non-empty line, we will print the entire line with
+ * the line number and possibly other prefixes and transforms.
+ */
+
+ /* Line prefixes for special files, C and ASM output */
+
if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
{
FlPrintFile (FileId, " *");
@@ -762,19 +761,21 @@ LsWriteOneSourceLine (
* This file contains "include" statements, print the current
* filename and line number within the current file
*/
- FlPrintFile (FileId, "%12s %5d....",
- Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber);
+ FlPrintFile (FileId, "%12s %5d%s",
+ Gbl_ListingNode->Filename, Gbl_ListingNode->LineNumber,
+ ASL_LISTING_LINE_PREFIX);
}
else
{
/* No include files, just print the line number */
- FlPrintFile (FileId, "%8d....", Gbl_SourceLine);
+ FlPrintFile (FileId, "%8u%s", Gbl_SourceLine,
+ ASL_LISTING_LINE_PREFIX);
}
- /* Read one line (up to a newline or EOF) */
+ /* Read the rest of this line (up to a newline or EOF) */
- while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK)
+ do
{
if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
{
@@ -788,13 +789,15 @@ LsWriteOneSourceLine (
if (FileByte == '\n')
{
/*
+ * This line has been completed.
* Check if an error occurred on this source line during the compile.
* If so, we print the error message after the source line.
*/
LsCheckException (Gbl_SourceLine, FileId);
return (1);
}
- }
+
+ } while (FlReadFile (ASL_FILE_SOURCE_OUTPUT, &FileByte, 1) == AE_OK);
/* EOF on the input file was reached */
@@ -1241,332 +1244,3 @@ LsWriteNodeToListing (
break;
}
}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsDoHexOutput
- *
- * PARAMETERS: None
- *
- * RETURN: None.
- *
- * DESCRIPTION: Create the hex output file.
- *
- ******************************************************************************/
-
-void
-LsDoHexOutput (
- void)
-{
-
- switch (Gbl_HexOutputFlag)
- {
- case HEX_OUTPUT_C:
-
- LsDoHexOutputC ();
- break;
-
- case HEX_OUTPUT_ASM:
-
- LsDoHexOutputAsm ();
- break;
-
- case HEX_OUTPUT_ASL:
-
- LsDoHexOutputAsl ();
- break;
-
- default:
- /* No other output types supported */
- break;
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsReadAmlOutputFile
- *
- * PARAMETERS: Buffer - Where to return data
- *
- * RETURN: None.
- *
- * DESCRIPTION: Read a line of the AML output prior to formatting the data
- *
- ******************************************************************************/
-
-static UINT32
-LsReadAmlOutputFile (
- UINT8 *Buffer)
-{
- UINT32 Actual;
-
-
- Actual = fread (Buffer, 1, HEX_TABLE_LINE_SIZE,
- Gbl_Files[ASL_FILE_AML_OUTPUT].Handle);
-
- if (ferror (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle))
- {
- FlFileError (ASL_FILE_AML_OUTPUT, ASL_MSG_READ);
- AslAbort ();
- }
-
- return (Actual);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsDoHexOutputC
- *
- * 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.
- *
- ******************************************************************************/
-
-static void
-LsDoHexOutputC (
- void)
-{
- 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);
- FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
-
- 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");
-
- while (Offset < AmlFileSize)
- {
- /* Read enough bytes needed for one output line */
-
- LineLength = LsReadAmlOutputFile (FileData);
- 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");
-}
-
-
-/*******************************************************************************
- *
- * 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.
- *
- ******************************************************************************/
-
-static void
-LsDoHexOutputAsl (
- void)
-{
- 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);
- FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
-
- 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 = LsReadAmlOutputFile (FileData);
- 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");
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsDoHexOutputAsm
- *
- * 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 ASM source file.
- *
- ******************************************************************************/
-
-static void
-LsDoHexOutputAsm (
- void)
-{
- 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);
- 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);
-
- while (Offset < AmlFileSize)
- {
- /* Read enough bytes needed for one output line */
-
- LineLength = LsReadAmlOutputFile (FileData);
- if (!LineLength)
- {
- break;
- }
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, " db ");
-
- for (i = 0; i < LineLength; i++)
- {
- /*
- * 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, ",");
- }
- }
-
- 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, "\n");
-
- Offset += LineLength;
- }
-
- FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
-}
diff --git a/sys/contrib/dev/acpica/compiler/aslload.c b/sys/contrib/dev/acpica/compiler/aslload.c
index 907dc14..813e603 100644
--- a/sys/contrib/dev/acpica/compiler/aslload.c
+++ b/sys/contrib/dev/acpica/compiler/aslload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/asllookup.c b/sys/contrib/dev/acpica/compiler/asllookup.c
index 9af193b..67952a6 100644
--- a/sys/contrib/dev/acpica/compiler/asllookup.c
+++ b/sys/contrib/dev/acpica/compiler/asllookup.c
@@ -1,11 +1,11 @@
/******************************************************************************
*
- * Module Name: asllookup- Namespace lookup
+ * Module Name: asllookup- Namespace lookup functions
*
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,6 @@
#include <contrib/dev/acpica/compiler/aslcompiler.h>
#include "aslcompiler.y.h"
-
#include <contrib/dev/acpica/include/acparser.h>
#include <contrib/dev/acpica/include/amlcode.h>
#include <contrib/dev/acpica/include/acnamesp.h>
@@ -57,57 +56,12 @@
/* Local prototypes */
static ACPI_STATUS
-LsCompareOneNamespaceObject (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue);
-
-static ACPI_STATUS
-LsDoOneNamespaceObject (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue);
-
-static BOOLEAN
-LkObjectExists (
- char *Name);
-
-static void
-LkCheckFieldRange (
- ACPI_PARSE_OBJECT *Op,
- UINT32 RegionBitLength,
- UINT32 FieldBitOffset,
- UINT32 FieldBitLength,
- UINT32 AccessBitWidth);
-
-static ACPI_STATUS
-LkNamespaceLocateBegin (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context);
-
-static ACPI_STATUS
-LkNamespaceLocateEnd (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context);
-
-static ACPI_STATUS
LkIsObjectUsed (
ACPI_HANDLE ObjHandle,
UINT32 Level,
void *Context,
void **ReturnValue);
-static ACPI_STATUS
-LsDoOnePathname (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue);
-
static ACPI_PARSE_OBJECT *
LkGetNameOp (
ACPI_PARSE_OBJECT *Op);
@@ -115,480 +69,28 @@ LkGetNameOp (
/*******************************************************************************
*
- * FUNCTION: LsDoOneNamespaceObject
- *
- * PARAMETERS: ACPI_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Dump a namespace object to the namespace output file.
- * Called during the walk of the namespace to dump all objects.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-LsDoOneNamespaceObject (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue)
-{
- ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
- ACPI_OPERAND_OBJECT *ObjDesc;
- ACPI_PARSE_OBJECT *Op;
-
-
- Gbl_NumNamespaceObjects++;
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%5u [%u] %*s %4.4s - %s",
- Gbl_NumNamespaceObjects, Level, (Level * 3), " ",
- &Node->Name,
- AcpiUtGetTypeName (Node->Type));
-
- Op = Node->Op;
- ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Node->Object);
-
- if (!Op)
- {
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n");
- return (AE_OK);
- }
-
-
- if ((ObjDesc) &&
- (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND))
- {
- switch (Node->Type)
- {
- case ACPI_TYPE_INTEGER:
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Value 0x%8.8X%8.8X]",
- ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
- break;
-
-
- case ACPI_TYPE_STRING:
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Value \"%s\"]",
- ObjDesc->String.Pointer);
- break;
-
- default:
- /* Nothing to do for other types */
- break;
- }
-
- }
- else
- {
- switch (Node->Type)
- {
- case ACPI_TYPE_INTEGER:
-
- if (Op->Asl.ParseOpcode == PARSEOP_NAME)
- {
- Op = Op->Asl.Child;
- }
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
- {
- Op = Op->Asl.Next;
- }
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Value 0x%8.8X%8.8X]",
- ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
- break;
-
-
- case ACPI_TYPE_STRING:
-
- if (Op->Asl.ParseOpcode == PARSEOP_NAME)
- {
- Op = Op->Asl.Child;
- }
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
- {
- Op = Op->Asl.Next;
- }
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Value \"%s\"]",
- Op->Asl.Value.String);
- break;
-
-
- case ACPI_TYPE_LOCAL_REGION_FIELD:
-
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
- {
- Op = Op->Asl.Child;
- }
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Offset 0x%04X Length 0x%04X bits]",
- Op->Asl.Parent->Asl.ExtraValue, (UINT32) Op->Asl.Value.Integer);
- break;
-
-
- case ACPI_TYPE_BUFFER_FIELD:
-
- switch (Op->Asl.ParseOpcode)
- {
- case PARSEOP_CREATEBYTEFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BYTE ( 8 bit)]");
- break;
-
- case PARSEOP_CREATEDWORDFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [DWORD (32 bit)]");
- break;
-
- case PARSEOP_CREATEQWORDFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [QWORD (64 bit)]");
- break;
-
- case PARSEOP_CREATEWORDFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [WORD (16 bit)]");
- break;
-
- case PARSEOP_CREATEBITFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BIT ( 1 bit)]");
- break;
-
- case PARSEOP_CREATEFIELD:
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [Arbitrary Bit Field]");
- break;
-
- default:
- break;
-
- }
- break;
-
-
- case ACPI_TYPE_PACKAGE:
-
- if (Op->Asl.ParseOpcode == PARSEOP_NAME)
- {
- Op = Op->Asl.Child;
- }
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
- {
- Op = Op->Asl.Next;
- }
- Op = Op->Asl.Child;
-
- if ((Op->Asl.ParseOpcode == PARSEOP_BYTECONST) ||
- (Op->Asl.ParseOpcode == PARSEOP_RAW_DATA))
- {
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Length 0x%.2X elements]",
- Op->Asl.Value.Integer);
- }
- break;
-
-
- case ACPI_TYPE_BUFFER:
-
- if (Op->Asl.ParseOpcode == PARSEOP_NAME)
- {
- Op = Op->Asl.Child;
- }
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
- {
- Op = Op->Asl.Next;
- }
- Op = Op->Asl.Child;
-
- if (Op && (Op->Asl.ParseOpcode == PARSEOP_INTEGER))
- {
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Initial Length 0x%.2X bytes]",
- Op->Asl.Value.Integer);
- }
- break;
-
-
- case ACPI_TYPE_METHOD:
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Code Length 0x%.4X bytes]",
- Op->Asl.AmlSubtreeLength);
- break;
-
-
- case ACPI_TYPE_LOCAL_RESOURCE:
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Desc Offset 0x%.4X Bytes]", Node->Value);
- break;
-
-
- case ACPI_TYPE_LOCAL_RESOURCE_FIELD:
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- " [Field Offset 0x%.4X Bits 0x%.4X Bytes] ",
- Node->Value, Node->Value / 8);
-
- if (Node->Flags & ANOBJ_IS_REFERENCED)
- {
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- "Referenced");
- }
- else
- {
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
- "Name not referenced");
- }
- break;
-
-
- default:
- /* Nothing to do for other types */
- break;
- }
- }
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n");
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsSetupNsList
+ * FUNCTION: LkFindUnreferencedObjects
*
- * PARAMETERS: Handle - local file handle
+ * PARAMETERS: None
*
* RETURN: None
*
- * DESCRIPTION: Set the namespace output file to the input handle
+ * DESCRIPTION: Namespace walk to find objects that are not referenced in any
+ * way. Must be called after the namespace has been cross
+ * referenced.
*
******************************************************************************/
void
-LsSetupNsList (
- void *Handle)
-{
-
- Gbl_NsOutputFlag = TRUE;
- Gbl_Files[ASL_FILE_NAMESPACE_OUTPUT].Handle = Handle;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsDoOnePathname
- *
- * PARAMETERS: ACPI_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Print the full pathname for a namespace node.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-LsDoOnePathname (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue)
-{
- ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
- ACPI_STATUS Status;
- ACPI_BUFFER TargetPath;
-
-
- TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- Status = AcpiNsHandleToPathname (Node, &TargetPath);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%s\n", TargetPath.Pointer);
- ACPI_FREE (TargetPath.Pointer);
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsDisplayNamespace
- *
- * PARAMETERS: None
- *
- * RETURN: Status
- *
- * DESCRIPTION: Walk the namespace an display information about each node
- * in the tree. Information is written to the optional
- * namespace output file.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-LsDisplayNamespace (
+LkFindUnreferencedObjects (
void)
{
- ACPI_STATUS Status;
-
-
- if (!Gbl_NsOutputFlag)
- {
- return (AE_OK);
- }
-
- Gbl_NumNamespaceObjects = 0;
-
- /* File header */
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Contents of ACPI Namespace\n\n");
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Count Depth Name - Type\n\n");
-
- /* Walk entire namespace from the root */
-
- Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, FALSE, LsDoOneNamespaceObject, NULL,
- NULL, NULL);
-
- /* Print the full pathname for each namespace node */
-
- FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\nNamespace pathnames\n\n");
-
- Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, FALSE, LsDoOnePathname, NULL,
- NULL, NULL);
-
- return (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LsCompareOneNamespaceObject
- *
- * PARAMETERS: ACPI_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Compare name of one object.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-LsCompareOneNamespaceObject (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue)
-{
- ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
-
-
- /* Simply check the name */
-
- if (*((UINT32 *) (Context)) == Node->Name.Integer)
- {
- /* Abort walk if we found one instance */
-
- return (AE_CTRL_TRUE);
- }
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LkObjectExists
- *
- * PARAMETERS: Name - 4 char ACPI name
- *
- * RETURN: TRUE if name exists in namespace
- *
- * DESCRIPTION: Walk the namespace to find an object
- *
- ******************************************************************************/
-
-static BOOLEAN
-LkObjectExists (
- char *Name)
-{
- ACPI_STATUS Status;
-
/* Walk entire namespace from the supplied root */
- Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, FALSE, LsCompareOneNamespaceObject, NULL,
- Name, NULL);
- if (Status == AE_CTRL_TRUE)
- {
- /* At least one instance of the name was found */
-
- return (TRUE);
- }
-
- return (FALSE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LkGetNameOp
- *
- * PARAMETERS: Op - Current Op
- *
- * RETURN: NameOp associated with the input op
- *
- * DESCRIPTION: Find the name declaration op associated with the operator
- *
- ******************************************************************************/
-
-static ACPI_PARSE_OBJECT *
-LkGetNameOp (
- ACPI_PARSE_OBJECT *Op)
-{
- const ACPI_OPCODE_INFO *OpInfo;
- ACPI_PARSE_OBJECT *NameOp = Op;
-
-
- OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
-
-
- /* Get the NamePath from the appropriate place */
-
- if (OpInfo->Flags & AML_NAMED)
- {
- /* For nearly all NAMED operators, the name reference is the first child */
-
- NameOp = Op->Asl.Child;
- if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
- {
- /*
- * ALIAS is the only oddball opcode, the name declaration
- * (alias name) is the second operand
- */
- NameOp = Op->Asl.Child->Asl.Next;
- }
- }
- else if (OpInfo->Flags & AML_CREATE)
- {
- /* Name must appear as the last parameter */
-
- NameOp = Op->Asl.Child;
- while (!(NameOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
- {
- NameOp = NameOp->Asl.Next;
- }
- }
-
- return (NameOp);
+ (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE, LkIsObjectUsed, NULL,
+ NULL, NULL);
}
@@ -660,232 +162,26 @@ LkIsObjectUsed (
/*******************************************************************************
*
- * FUNCTION: LkFindUnreferencedObjects
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Namespace walk to find objects that are not referenced in any
- * way. Must be called after the namespace has been cross
- * referenced.
- *
- ******************************************************************************/
-
-void
-LkFindUnreferencedObjects (
- void)
-{
-
- /* Walk entire namespace from the supplied root */
-
- (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, FALSE, LkIsObjectUsed, NULL,
- NULL, NULL);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LkCrossReferenceNamespace
- *
- * PARAMETERS: None
- *
- * RETURN: Status
- *
- * DESCRIPTION: Perform a cross reference check of the parse tree against the
- * namespace. Every named referenced within the parse tree
- * should be get resolved with a namespace lookup. If not, the
- * original reference in the ASL code is invalid -- i.e., refers
- * to a non-existent object.
- *
- * NOTE: The ASL "External" operator causes the name to be inserted into the
- * namespace so that references to the external name will be resolved
- * correctly here.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-LkCrossReferenceNamespace (
- void)
-{
- ACPI_WALK_STATE *WalkState;
-
-
- DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n");
-
- /*
- * Create a new walk state for use when looking up names
- * within the namespace (Passed as context to the callbacks)
- */
- WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
- if (!WalkState)
- {
- return (AE_NO_MEMORY);
- }
-
- /* Walk the entire parse tree */
-
- TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, LkNamespaceLocateBegin,
- LkNamespaceLocateEnd, WalkState);
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LkCheckFieldRange
- *
- * PARAMETERS: RegionBitLength - Length of entire parent region
- * FieldBitOffset - Start of the field unit (within region)
- * FieldBitLength - Entire length of field unit
- * AccessBitWidth - Access width of the field unit
- *
- * RETURN: None
- *
- * DESCRIPTION: Check one field unit to make sure it fits in the parent
- * op region.
- *
- * Note: AccessBitWidth must be either 8,16,32, or 64
- *
- ******************************************************************************/
-
-static void
-LkCheckFieldRange (
- ACPI_PARSE_OBJECT *Op,
- UINT32 RegionBitLength,
- UINT32 FieldBitOffset,
- UINT32 FieldBitLength,
- UINT32 AccessBitWidth)
-{
- UINT32 FieldEndBitOffset;
-
-
- /*
- * Check each field unit against the region size. The entire
- * field unit (start offset plus length) must fit within the
- * region.
- */
- FieldEndBitOffset = FieldBitOffset + FieldBitLength;
-
- if (FieldEndBitOffset > RegionBitLength)
- {
- /* Field definition itself is beyond the end-of-region */
-
- AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL);
- return;
- }
-
- /*
- * Now check that the field plus AccessWidth doesn't go beyond
- * the end-of-region. Assumes AccessBitWidth is a power of 2
- */
- FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth);
-
- if (FieldEndBitOffset > RegionBitLength)
- {
- /* Field definition combined with the access is beyond EOR */
-
- AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL);
- }
-}
-
-/*******************************************************************************
- *
- * FUNCTION: LkNamespaceLocateBegin
- *
- * PARAMETERS: ASL_WALK_CALLBACK
+ * FUNCTION: LkGetNameOp
*
- * RETURN: Status
+ * PARAMETERS: Op - Current Op
*
- * DESCRIPTION: Descending callback used during cross-reference. For named
- * object references, attempt to locate the name in the
- * namespace.
+ * RETURN: NameOp associated with the input op
*
- * NOTE: ASL references to named fields within resource descriptors are
- * resolved to integer values here. Therefore, this step is an
- * important part of the code generation. We don't know that the
- * name refers to a resource descriptor until now.
+ * DESCRIPTION: Find the name declaration op associated with the operator
*
******************************************************************************/
-static ACPI_STATUS
-LkNamespaceLocateBegin (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context)
+static ACPI_PARSE_OBJECT *
+LkGetNameOp (
+ ACPI_PARSE_OBJECT *Op)
{
- ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context;
- ACPI_NAMESPACE_NODE *Node;
- ACPI_STATUS Status;
- ACPI_OBJECT_TYPE ObjectType;
- char *Path;
- UINT8 PassedArgs;
- ACPI_PARSE_OBJECT *NextOp;
- ACPI_PARSE_OBJECT *OwningOp;
- ACPI_PARSE_OBJECT *SpaceIdOp;
- UINT32 MinimumLength;
- UINT32 Offset;
- UINT32 FieldBitLength;
- UINT32 TagBitLength;
- UINT8 Message = 0;
const ACPI_OPCODE_INFO *OpInfo;
- UINT32 Flags;
-
-
- ACPI_FUNCTION_TRACE_PTR (LkNamespaceLocateBegin, Op);
-
- /*
- * If this node is the actual declaration of a name
- * [such as the XXXX name in "Method (XXXX)"],
- * we are not interested in it here. We only care about names that are
- * references to other objects within the namespace and the parent objects
- * of name declarations
- */
- if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
- {
- return (AE_OK);
- }
+ ACPI_PARSE_OBJECT *NameOp = Op;
- /* We are only interested in opcodes that have an associated name */
OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
- if ((!(OpInfo->Flags & AML_NAMED)) &&
- (!(OpInfo->Flags & AML_CREATE)) &&
- (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
- (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) &&
- (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
- {
- return (AE_OK);
- }
-
- /*
- * One special case: CondRefOf operator - we don't care if the name exists
- * or not at this point, just ignore it, the point of the operator is to
- * determine if the name exists at runtime.
- */
- if ((Op->Asl.Parent) &&
- (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
- {
- return (AE_OK);
- }
-
- /*
- * We must enable the "search-to-root" for single NameSegs, but
- * we have to be very careful about opening up scopes
- */
- Flags = ACPI_NS_SEARCH_PARENT;
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
- {
- /*
- * These are name references, do not push the scope stack
- * for them.
- */
- Flags |= ACPI_NS_DONT_OPEN_SCOPE;
- }
/* Get the NamePath from the appropriate place */
@@ -893,510 +189,26 @@ LkNamespaceLocateBegin (
{
/* For nearly all NAMED operators, the name reference is the first child */
- Path = Op->Asl.Child->Asl.Value.String;
+ NameOp = Op->Asl.Child;
if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
{
/*
* ALIAS is the only oddball opcode, the name declaration
* (alias name) is the second operand
*/
- Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
+ NameOp = Op->Asl.Child->Asl.Next;
}
}
else if (OpInfo->Flags & AML_CREATE)
{
/* Name must appear as the last parameter */
- NextOp = Op->Asl.Child;
- while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
- {
- NextOp = NextOp->Asl.Next;
- }
- Path = NextOp->Asl.Value.String;
- }
- else
- {
- Path = Op->Asl.Value.String;
- }
-
- ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Type=%s\n", AcpiUtGetTypeName (ObjectType)));
-
- /*
- * Lookup the name in the namespace. Name must exist at this point, or it
- * is an invalid reference.
- *
- * The namespace is also used as a lookup table for references to resource
- * descriptors and the fields within them.
- */
- Gbl_NsLookupCount++;
-
- Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
- ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node));
- if (ACPI_FAILURE (Status))
- {
- if (Status == AE_NOT_FOUND)
- {
- /*
- * We didn't find the name reference by path -- we can qualify this
- * a little better before we print an error message
- */
- if (strlen (Path) == ACPI_NAME_SIZE)
- {
- /* A simple, one-segment ACPI name */
-
- if (LkObjectExists (Path))
- {
- /*
- * There exists such a name, but we couldn't get to it
- * from this scope
- */
- AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
- Op->Asl.ExternalName);
- }
- else
- {
- /* The name doesn't exist, period */
-
- AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
- Op, Op->Asl.ExternalName);
- }
- }
- else
- {
- /* Check for a fully qualified path */
-
- if (Path[0] == AML_ROOT_PREFIX)
- {
- /* Gave full path, the object does not exist */
-
- AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
- Op->Asl.ExternalName);
- }
- else
- {
- /*
- * We can't tell whether it doesn't exist or just
- * can't be reached.
- */
- AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
- Op->Asl.ExternalName);
- }
- }
-
- Status = AE_OK;
- }
- return (Status);
- }
-
- /* Check for a reference vs. name declaration */
-
- if (!(OpInfo->Flags & AML_NAMED) &&
- !(OpInfo->Flags & AML_CREATE))
- {
- /* This node has been referenced, mark it for reference check */
-
- Node->Flags |= ANOBJ_IS_REFERENCED;
- }
-
- /* Attempt to optimize the NamePath */
-
- OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);
-
- /*
- * 1) Dereference an alias (A name reference that is an alias)
- * Aliases are not nested, the alias always points to the final object
- */
- if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
- (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
- {
- /* This node points back to the original PARSEOP_ALIAS */
-
- NextOp = Node->Op;
-
- /* The first child is the alias target op */
-
- NextOp = NextOp->Asl.Child;
-
- /* That in turn points back to original target alias node */
-
- if (NextOp->Asl.Node)
- {
- Node = NextOp->Asl.Node;
- }
-
- /* Else - forward reference to alias, will be resolved later */
- }
-
- /* 2) Check for a reference to a resource descriptor */
-
- if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
- (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
- {
- /*
- * This was a reference to a field within a resource descriptor.
- * Extract the associated field offset (either a bit or byte
- * offset depending on the field type) and change the named
- * reference into an integer for AML code generation
- */
- Offset = Node->Value;
- TagBitLength = Node->Length;
-
- /*
- * If a field is being created, generate the length (in bits) of
- * the field. Note: Opcodes other than CreateXxxField and Index
- * can come through here. For other opcodes, we just need to
- * convert the resource tag reference to an integer offset.
- */
- switch (Op->Asl.Parent->Asl.AmlOpcode)
- {
- case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
- /*
- * We know the length operand is an integer constant because
- * we know that it contains a reference to a resource
- * descriptor tag.
- */
- FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
- break;
-
- case AML_CREATE_BIT_FIELD_OP:
- FieldBitLength = 1;
- break;
-
- case AML_CREATE_BYTE_FIELD_OP:
- case AML_INDEX_OP:
- FieldBitLength = 8;
- break;
-
- case AML_CREATE_WORD_FIELD_OP:
- FieldBitLength = 16;
- break;
-
- case AML_CREATE_DWORD_FIELD_OP:
- FieldBitLength = 32;
- break;
-
- case AML_CREATE_QWORD_FIELD_OP:
- FieldBitLength = 64;
- break;
-
- default:
- FieldBitLength = 0;
- break;
- }
-
- /* Check the field length against the length of the resource tag */
-
- if (FieldBitLength)
- {
- if (TagBitLength < FieldBitLength)
- {
- Message = ASL_MSG_TAG_SMALLER;
- }
- else if (TagBitLength > FieldBitLength)
- {
- Message = ASL_MSG_TAG_LARGER;
- }
-
- if (Message)
- {
- sprintf (MsgBuffer, "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
- TagBitLength, (TagBitLength > 1) ? "s" : "",
- FieldBitLength, (FieldBitLength > 1) ? "s" : "");
-
- AslError (ASL_WARNING, Message, Op, MsgBuffer);
- }
- }
-
- /* Convert the BitOffset to a ByteOffset for certain opcodes */
-
- switch (Op->Asl.Parent->Asl.AmlOpcode)
- {
- case AML_CREATE_BYTE_FIELD_OP:
- case AML_CREATE_WORD_FIELD_OP:
- case AML_CREATE_DWORD_FIELD_OP:
- case AML_CREATE_QWORD_FIELD_OP:
- case AML_INDEX_OP:
-
- Offset = ACPI_DIV_8 (Offset);
- break;
-
- default:
- break;
- }
-
- /* Now convert this node to an integer whose value is the field offset */
-
- Op->Asl.AmlLength = 0;
- Op->Asl.ParseOpcode = PARSEOP_INTEGER;
- Op->Asl.Value.Integer = (UINT64) Offset;
- Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD;
-
- OpcGenerateAmlOpcode (Op);
- }
-
- /* 3) Check for a method invocation */
-
- else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
- (Node->Type == ACPI_TYPE_METHOD) &&
- (Op->Asl.Parent) &&
- (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) ||
-
- (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
- {
-
- /*
- * A reference to a method within one of these opcodes is not an
- * invocation of the method, it is simply a reference to the method.
- */
- if ((Op->Asl.Parent) &&
- ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) ||
- (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF) ||
- (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE)))
- {
- return (AE_OK);
- }
- /*
- * There are two types of method invocation:
- * 1) Invocation with arguments -- the parser recognizes this
- * as a METHODCALL.
- * 2) Invocation with no arguments --the parser cannot determine that
- * this is a method invocation, therefore we have to figure it out
- * here.
- */
- if (Node->Type != ACPI_TYPE_METHOD)
- {
- sprintf (MsgBuffer, "%s is a %s",
- Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
-
- AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer);
- return (AE_OK);
- }
-
- /* Save the method node in the caller's op */
-
- Op->Asl.Node = Node;
- if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
- {
- return (AE_OK);
- }
-
- /*
- * This is a method invocation, with or without arguments.
- * Count the number of arguments, each appears as a child
- * under the parent node
- */
- Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
- UtSetParseOpName (Op);
-
- PassedArgs = 0;
- NextOp = Op->Asl.Child;
-
- while (NextOp)
- {
- PassedArgs++;
- NextOp = NextOp->Asl.Next;
- }
-
- if (Node->Value != ASL_EXTERNAL_METHOD)
- {
- /*
- * Check the parsed arguments with the number expected by the
- * method declaration itself
- */
- if (PassedArgs != Node->Value)
- {
- sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName,
- Node->Value);
-
- if (PassedArgs < Node->Value)
- {
- AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer);
- }
- else
- {
- AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer);
- }
- }
- }
- }
-
- /* 4) Check for an ASL Field definition */
-
- else if ((Op->Asl.Parent) &&
- ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) ||
- (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
- {
- /*
- * Offset checking for fields. If the parent operation region has a
- * constant length (known at compile time), we can check fields
- * defined in that region against the region length. This will catch
- * fields and field units that cannot possibly fit within the region.
- *
- * Note: Index fields do not directly reference an operation region,
- * thus they are not included in this check.
- */
- if (Op == Op->Asl.Parent->Asl.Child)
- {
- /*
- * This is the first child of the field node, which is
- * the name of the region. Get the parse node for the
- * region -- which contains the length of the region.
- */
- OwningOp = Node->Op;
- Op->Asl.Parent->Asl.ExtraValue =
- ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
-
- /* Examine the field access width */
-
- switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
- {
- case AML_FIELD_ACCESS_ANY:
- case AML_FIELD_ACCESS_BYTE:
- case AML_FIELD_ACCESS_BUFFER:
- default:
- MinimumLength = 1;
- break;
-
- case AML_FIELD_ACCESS_WORD:
- MinimumLength = 2;
- break;
-
- case AML_FIELD_ACCESS_DWORD:
- MinimumLength = 4;
- break;
-
- case AML_FIELD_ACCESS_QWORD:
- MinimumLength = 8;
- break;
- }
-
- /*
- * Is the region at least as big as the access width?
- * Note: DataTableRegions have 0 length
- */
- if (((UINT32) OwningOp->Asl.Value.Integer) &&
- ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
- {
- AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
- }
-
- /*
- * Check EC/CMOS/SMBUS fields to make sure that the correct
- * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
- */
- SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
- switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
- {
- case ACPI_ADR_SPACE_EC:
- case ACPI_ADR_SPACE_CMOS:
- case ACPI_ADR_SPACE_GPIO:
-
- if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE)
- {
- AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
- }
- break;
-
- case ACPI_ADR_SPACE_SMBUS:
- case ACPI_ADR_SPACE_IPMI:
- case ACPI_ADR_SPACE_GSBUS:
-
- if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER)
- {
- AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
- }
- break;
-
- default:
-
- /* Nothing to do for other address spaces */
- break;
- }
- }
- else
+ NameOp = Op->Asl.Child;
+ while (!(NameOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
{
- /*
- * This is one element of the field list. Check to make sure
- * that it does not go beyond the end of the parent operation region.
- *
- * In the code below:
- * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits)
- * Op->Asl.ExtraValue - Field start offset (bits)
- * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits)
- * Op->Asl.Child->Asl.ExtraValue - Field access width (bits)
- */
- if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
- {
- LkCheckFieldRange (Op,
- Op->Asl.Parent->Asl.ExtraValue,
- Op->Asl.ExtraValue,
- (UINT32) Op->Asl.Child->Asl.Value.Integer,
- Op->Asl.Child->Asl.ExtraValue);
- }
+ NameOp = NameOp->Asl.Next;
}
}
- Op->Asl.Node = Node;
- return (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: LkNamespaceLocateEnd
- *
- * PARAMETERS: ASL_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Ascending callback used during cross reference. We only
- * need to worry about scope management here.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-LkNamespaceLocateEnd (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context)
-{
- ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context;
- const ACPI_OPCODE_INFO *OpInfo;
-
-
- ACPI_FUNCTION_TRACE (LkNamespaceLocateEnd);
-
-
- /* We are only interested in opcodes that have an associated name */
-
- OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
- if (!(OpInfo->Flags & AML_NAMED))
- {
- return (AE_OK);
- }
-
- /* Not interested in name references, we did not open a scope for them */
-
- if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
- (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
- (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
- {
- return (AE_OK);
- }
-
- /* Pop the scope stack if necessary */
-
- if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
- {
-
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "%s: Popping scope for Op %p\n",
- AcpiUtGetTypeName (OpInfo->ObjectType), Op));
-
- (void) AcpiDsScopeStackPop (WalkState);
- }
-
- return (AE_OK);
+ return (NameOp);
}
diff --git a/sys/contrib/dev/acpica/compiler/aslmain.c b/sys/contrib/dev/acpica/compiler/aslmain.c
index 3b6d45b..1a05b9f 100644
--- a/sys/contrib/dev/acpica/compiler/aslmain.c
+++ b/sys/contrib/dev/acpica/compiler/aslmain.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -153,6 +153,7 @@ Options (
ACPI_OPTION ("-oi", "Disable integer optimization to Zero/One/Ones");
ACPI_OPTION ("-on", "Disable named reference string optimization");
ACPI_OPTION ("-cr", "Disable Resource Descriptor error checking");
+ ACPI_OPTION ("-in", "Ignore NoOp operators");
ACPI_OPTION ("-r <revision>", "Override table header Revision (1-255)");
printf ("\nASL Listing Files:\n");
@@ -172,6 +173,7 @@ Options (
ACPI_OPTION ("", "(Obtain DSDT from current system if no input file)");
ACPI_OPTION ("-e [f1,f2]", "Include ACPI table(s) for external symbol resolution");
ACPI_OPTION ("-g", "Get ACPI tables and write to files (*.dat)");
+ ACPI_OPTION ("-in", "Ignore NoOp opcodes");
ACPI_OPTION ("-vt", "Dump binary table data in hex format within output file");
printf ("\nHelp:\n");
@@ -622,6 +624,13 @@ AslDoOptions (
Gbl_C_IncludeOutputFlag = TRUE;
break;
+ case 'n':
+
+ /* Compiler/Disassembler: Ignore the NOOP operator */
+
+ AcpiGbl_IgnoreNoopOperator = TRUE;
+ break;
+
default:
printf ("Unknown option: -i%s\n", AcpiGbl_Optarg);
return (-1);
diff --git a/sys/contrib/dev/acpica/compiler/aslmap.c b/sys/contrib/dev/acpica/compiler/aslmap.c
index d9f3325..0d2e636 100644
--- a/sys/contrib/dev/acpica/compiler/aslmap.c
+++ b/sys/contrib/dev/acpica/compiler/aslmap.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslmessages.h b/sys/contrib/dev/acpica/compiler/aslmessages.h
index 07758ef..be7a3f9 100644
--- a/sys/contrib/dev/acpica/compiler/aslmessages.h
+++ b/sys/contrib/dev/acpica/compiler/aslmessages.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -190,6 +190,7 @@ typedef enum
ASL_MSG_TAG_SMALLER,
ASL_MSG_TIMEOUT,
ASL_MSG_TOO_MANY_TEMPS,
+ ASL_MSG_TRUNCATION,
ASL_MSG_UNKNOWN_RESERVED_NAME,
ASL_MSG_UNREACHABLE_CODE,
ASL_MSG_UNSUPPORTED,
@@ -274,7 +275,7 @@ char *AslMessages [] = {
/* ASL_MSG_HID_SUFFIX */ "_HID suffix must be all hex digits",
/* ASL_MSG_INCLUDE_FILE_OPEN */ "Could not open include file",
/* ASL_MSG_INPUT_FILE_OPEN */ "Could not open input file",
-/* ASL_MSG_INTEGER_LENGTH */ "64-bit integer in 32-bit table, truncating",
+/* ASL_MSG_INTEGER_LENGTH */ "64-bit integer in 32-bit table, truncating (DSDT version < 2)",
/* ASL_MSG_INTEGER_OPTIMIZATION */ "Integer optimized to single-byte AML opcode",
/* ASL_MSG_INTERRUPT_LIST */ "Too many interrupts (16 max)",
/* ASL_MSG_INTERRUPT_NUMBER */ "Invalid interrupt number (must be 0-15)",
@@ -366,6 +367,7 @@ char *AslMessages [] = {
/* ASL_MSG_TAG_SMALLER */ "ResourceTag smaller than Field",
/* ASL_MSG_TIMEOUT */ "Result is not used, possible operator timeout will be missed",
/* ASL_MSG_TOO_MANY_TEMPS */ "Method requires too many temporary variables (_T_x)",
+/* ASL_MSG_TRUNCATION */ "64-bit return value will be truncated to 32 bits (DSDT version < 2)",
/* ASL_MSG_UNKNOWN_RESERVED_NAME */ "Unknown reserved name",
/* ASL_MSG_UNREACHABLE_CODE */ "Statement is unreachable",
/* ASL_MSG_UNSUPPORTED */ "Unsupported feature",
diff --git a/sys/contrib/dev/acpica/compiler/aslmethod.c b/sys/contrib/dev/acpica/compiler/aslmethod.c
new file mode 100644
index 0000000..f104d44
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslmethod.c
@@ -0,0 +1,619 @@
+/******************************************************************************
+ *
+ * Module Name: aslmethod.c - Control method analysis walk
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslmethod")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: MtMethodAnalysisWalkBegin
+ *
+ * PARAMETERS: ASL_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
+ * 1) Initialized local variables
+ * 2) Valid arguments
+ * 3) Return types
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+MtMethodAnalysisWalkBegin (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context)
+{
+ ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
+ ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;
+ ACPI_PARSE_OBJECT *Next;
+ UINT32 RegisterNumber;
+ UINT32 i;
+ char LocalName[] = "Local0";
+ char ArgName[] = "Arg0";
+ ACPI_PARSE_OBJECT *ArgNode;
+ ACPI_PARSE_OBJECT *NextType;
+ ACPI_PARSE_OBJECT *NextParamType;
+ UINT8 ActualArgs = 0;
+
+
+ switch (Op->Asl.ParseOpcode)
+ {
+ case PARSEOP_METHOD:
+
+ TotalMethods++;
+
+ /* Create and init method info */
+
+ MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
+ MethodInfo->Next = WalkInfo->MethodStack;
+ MethodInfo->Op = Op;
+
+ WalkInfo->MethodStack = MethodInfo;
+
+ /* Get the name node, ignored here */
+
+ Next = Op->Asl.Child;
+
+ /* Get the NumArguments node */
+
+ Next = Next->Asl.Next;
+ MethodInfo->NumArguments = (UINT8)
+ (((UINT8) Next->Asl.Value.Integer) & 0x07);
+
+ /* Get the SerializeRule and SyncLevel nodes, ignored here */
+
+ Next = Next->Asl.Next;
+ Next = Next->Asl.Next;
+ ArgNode = Next;
+
+ /* Get the ReturnType node */
+
+ Next = Next->Asl.Next;
+
+ NextType = Next->Asl.Child;
+ while (NextType)
+ {
+ /* Get and map each of the ReturnTypes */
+
+ MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
+ NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
+ NextType = NextType->Asl.Next;
+ }
+
+ /* Get the ParameterType node */
+
+ Next = Next->Asl.Next;
+
+ NextType = Next->Asl.Child;
+ while (NextType)
+ {
+ if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
+ {
+ NextParamType = NextType->Asl.Child;
+ while (NextParamType)
+ {
+ MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType);
+ NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
+ NextParamType = NextParamType->Asl.Next;
+ }
+ }
+ else
+ {
+ MethodInfo->ValidArgTypes[ActualArgs] =
+ AnMapObjTypeToBtype (NextType);
+ NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
+ ActualArgs++;
+ }
+
+ NextType = NextType->Asl.Next;
+ }
+
+ if ((MethodInfo->NumArguments) &&
+ (MethodInfo->NumArguments != ActualArgs))
+ {
+ /* error: Param list did not match number of args */
+ }
+
+ /* Allow numarguments == 0 for Function() */
+
+ if ((!MethodInfo->NumArguments) && (ActualArgs))
+ {
+ MethodInfo->NumArguments = ActualArgs;
+ ArgNode->Asl.Value.Integer |= ActualArgs;
+ }
+
+ /*
+ * Actual arguments are initialized at method entry.
+ * All other ArgX "registers" can be used as locals, so we
+ * track their initialization.
+ */
+ for (i = 0; i < MethodInfo->NumArguments; i++)
+ {
+ MethodInfo->ArgInitialized[i] = TRUE;
+ }
+ break;
+
+
+ case PARSEOP_METHODCALL:
+
+ if (MethodInfo &&
+ (Op->Asl.Node == MethodInfo->Op->Asl.Node))
+ {
+ AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
+ }
+ break;
+
+
+ case PARSEOP_LOCAL0:
+ case PARSEOP_LOCAL1:
+ case PARSEOP_LOCAL2:
+ case PARSEOP_LOCAL3:
+ case PARSEOP_LOCAL4:
+ case PARSEOP_LOCAL5:
+ case PARSEOP_LOCAL6:
+ case PARSEOP_LOCAL7:
+
+ if (!MethodInfo)
+ {
+ /*
+ * Local was used outside a control method, or there was an error
+ * in the method declaration.
+ */
+ AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
+ return (AE_ERROR);
+ }
+
+ RegisterNumber = (Op->Asl.AmlOpcode & 0x000F);
+
+ /*
+ * If the local is being used as a target, mark the local
+ * initialized
+ */
+ if (Op->Asl.CompileFlags & NODE_IS_TARGET)
+ {
+ MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
+ }
+
+ /*
+ * Otherwise, this is a reference, check if the local
+ * has been previously initialized.
+ *
+ * The only operator that accepts an uninitialized value is ObjectType()
+ */
+ else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
+ (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
+ {
+ LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
+ AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
+ }
+ break;
+
+
+ case PARSEOP_ARG0:
+ case PARSEOP_ARG1:
+ case PARSEOP_ARG2:
+ case PARSEOP_ARG3:
+ case PARSEOP_ARG4:
+ case PARSEOP_ARG5:
+ case PARSEOP_ARG6:
+
+ if (!MethodInfo)
+ {
+ /*
+ * Arg was used outside a control method, or there was an error
+ * in the method declaration.
+ */
+ AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
+ return (AE_ERROR);
+ }
+
+ RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
+ ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
+
+ /*
+ * If the Arg is being used as a target, mark the local
+ * initialized
+ */
+ if (Op->Asl.CompileFlags & NODE_IS_TARGET)
+ {
+ MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
+ }
+
+ /*
+ * Otherwise, this is a reference, check if the Arg
+ * has been previously initialized.
+ *
+ * The only operator that accepts an uninitialized value is ObjectType()
+ */
+ else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
+ (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
+ {
+ AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
+ }
+
+ /* Flag this arg if it is not a "real" argument to the method */
+
+ if (RegisterNumber >= MethodInfo->NumArguments)
+ {
+ AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
+ }
+ break;
+
+
+ case PARSEOP_RETURN:
+
+ if (!MethodInfo)
+ {
+ /*
+ * Probably was an error in the method declaration,
+ * no additional error here
+ */
+ ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
+ return (AE_ERROR);
+ }
+
+ /*
+ * A child indicates a possible return value. A simple Return or
+ * Return() is marked with NODE_IS_NULL_RETURN by the parser so
+ * that it is not counted as a "real" return-with-value, although
+ * the AML code that is actually emitted is Return(0). The AML
+ * definition of Return has a required parameter, so we are
+ * forced to convert a null return to Return(0).
+ */
+ if ((Op->Asl.Child) &&
+ (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
+ (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN)))
+ {
+ MethodInfo->NumReturnWithValue++;
+ }
+ else
+ {
+ MethodInfo->NumReturnNoValue++;
+ }
+ break;
+
+
+ case PARSEOP_BREAK:
+ case PARSEOP_CONTINUE:
+
+ Next = Op->Asl.Parent;
+ while (Next)
+ {
+ if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
+ {
+ break;
+ }
+ Next = Next->Asl.Parent;
+ }
+
+ if (!Next)
+ {
+ AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
+ }
+ break;
+
+
+ case PARSEOP_STALL:
+
+ /* We can range check if the argument is an integer */
+
+ if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
+ (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
+ {
+ AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
+ }
+ break;
+
+
+ case PARSEOP_DEVICE:
+ case PARSEOP_EVENT:
+ case PARSEOP_MUTEX:
+ case PARSEOP_OPERATIONREGION:
+ case PARSEOP_POWERRESOURCE:
+ case PARSEOP_PROCESSOR:
+ case PARSEOP_THERMALZONE:
+
+ /*
+ * The first operand is a name to be created in the namespace.
+ * Check against the reserved list.
+ */
+ i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
+ if (i < ACPI_VALID_RESERVED_NAME_MAX)
+ {
+ AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
+ }
+ break;
+
+
+ case PARSEOP_NAME:
+
+ /* Typecheck any predefined names statically defined with Name() */
+
+ ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
+
+ /* Special typechecking for _HID */
+
+ if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg))
+ {
+ Next = Op->Asl.Child->Asl.Next;
+ AnCheckId (Next, ASL_TYPE_HID);
+ }
+
+ /* Special typechecking for _CID */
+
+ else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg))
+ {
+ Next = Op->Asl.Child->Asl.Next;
+
+ if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
+ (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
+ {
+ Next = Next->Asl.Child;
+ while (Next)
+ {
+ AnCheckId (Next, ASL_TYPE_CID);
+ Next = Next->Asl.Next;
+ }
+ }
+ else
+ {
+ AnCheckId (Next, ASL_TYPE_CID);
+ }
+ }
+ break;
+
+
+ default:
+ break;
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: MtMethodAnalysisWalkEnd
+ *
+ * PARAMETERS: ASL_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Ascending callback for analysis walk. Complete method
+ * return analysis.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+MtMethodAnalysisWalkEnd (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context)
+{
+ ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
+ ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;
+
+
+ switch (Op->Asl.ParseOpcode)
+ {
+ case PARSEOP_METHOD:
+ case PARSEOP_RETURN:
+ if (!MethodInfo)
+ {
+ printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
+ AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
+ "No method info for this method");
+
+ CmCleanupAndExit ();
+ return (AE_AML_INTERNAL);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ switch (Op->Asl.ParseOpcode)
+ {
+ case PARSEOP_METHOD:
+
+ WalkInfo->MethodStack = MethodInfo->Next;
+
+ /*
+ * Check if there is no return statement at the end of the
+ * method AND we can actually get there -- i.e., the execution
+ * of the method can possibly terminate without a return statement.
+ */
+ if ((!AnLastStatementIsReturn (Op)) &&
+ (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
+ {
+ /*
+ * No return statement, and execution can possibly exit
+ * via this path. This is equivalent to Return ()
+ */
+ MethodInfo->NumReturnNoValue++;
+ }
+
+ /*
+ * Check for case where some return statements have a return value
+ * and some do not. Exit without a return statement is a return with
+ * no value
+ */
+ if (MethodInfo->NumReturnNoValue &&
+ MethodInfo->NumReturnWithValue)
+ {
+ AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
+ Op->Asl.ExternalName);
+ }
+
+ /*
+ * If there are any RETURN() statements with no value, or there is a
+ * control path that allows the method to exit without a return value,
+ * we mark the method as a method that does not return a value. This
+ * knowledge can be used to check method invocations that expect a
+ * returned value.
+ */
+ if (MethodInfo->NumReturnNoValue)
+ {
+ if (MethodInfo->NumReturnWithValue)
+ {
+ Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
+ }
+ else
+ {
+ Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
+ }
+ }
+
+ /*
+ * Check predefined method names for correct return behavior
+ * and correct number of arguments. Also, some special checks
+ * For GPE and _REG methods.
+ */
+ if (ApCheckForPredefinedMethod (Op, MethodInfo))
+ {
+ /* Special check for two names like _L01 and _E01 in same scope */
+
+ ApCheckForGpeNameConflict (Op);
+
+ /*
+ * Special check for _REG: Must have an operation region definition
+ * within the same scope!
+ */
+ ApCheckRegMethod (Op);
+ }
+
+ ACPI_FREE (MethodInfo);
+ break;
+
+
+ case PARSEOP_NAME:
+
+ /* Special check for two names like _L01 and _E01 in same scope */
+
+ ApCheckForGpeNameConflict (Op);
+ break;
+
+
+ case PARSEOP_RETURN:
+
+ /*
+ * If the parent is a predefined method name, attempt to typecheck
+ * the return value. Only static types can be validated.
+ */
+ ApCheckPredefinedReturnValue (Op, MethodInfo);
+
+ /*
+ * The parent block does not "exit" and continue execution -- the
+ * method is terminated here with the Return() statement.
+ */
+ Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
+
+ /* Used in the "typing" pass later */
+
+ Op->Asl.ParentMethod = MethodInfo->Op;
+
+ /*
+ * If there is a peer node after the return statement, then this
+ * node is unreachable code -- i.e., it won't be executed because of
+ * the preceding Return() statement.
+ */
+ if (Op->Asl.Next)
+ {
+ AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
+ }
+ break;
+
+
+ case PARSEOP_IF:
+
+ if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
+ (Op->Asl.Next) &&
+ (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
+ {
+ /*
+ * This IF has a corresponding ELSE. The IF block has no exit,
+ * (it contains an unconditional Return)
+ * mark the ELSE block to remember this fact.
+ */
+ Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
+ }
+ break;
+
+
+ case PARSEOP_ELSE:
+
+ if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
+ (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
+ {
+ /*
+ * This ELSE block has no exit and the corresponding IF block
+ * has no exit either. Therefore, the parent node has no exit.
+ */
+ Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
+ }
+ break;
+
+
+ default:
+
+ if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
+ (Op->Asl.Parent))
+ {
+ /* If this node has no exit, then the parent has no exit either */
+
+ Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
+ }
+ break;
+ }
+
+ return (AE_OK);
+}
diff --git a/sys/contrib/dev/acpica/compiler/aslnamesp.c b/sys/contrib/dev/acpica/compiler/aslnamesp.c
new file mode 100644
index 0000000..5eb3b64
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslnamesp.c
@@ -0,0 +1,422 @@
+/******************************************************************************
+ *
+ * Module Name: aslnamesp - Namespace output file generation
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+#include <contrib/dev/acpica/include/acnamesp.h>
+
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslnamesp")
+
+/* Local prototypes */
+
+static ACPI_STATUS
+NsDoOneNamespaceObject (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue);
+
+static ACPI_STATUS
+NsDoOnePathname (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: NsSetupNamespaceListing
+ *
+ * PARAMETERS: Handle - local file handle
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Set the namespace output file to the input handle
+ *
+ ******************************************************************************/
+
+void
+NsSetupNamespaceListing (
+ void *Handle)
+{
+
+ Gbl_NsOutputFlag = TRUE;
+ Gbl_Files[ASL_FILE_NAMESPACE_OUTPUT].Handle = Handle;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: NsDisplayNamespace
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Walk the namespace an display information about each node
+ * in the tree. Information is written to the optional
+ * namespace output file.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+NsDisplayNamespace (
+ void)
+{
+ ACPI_STATUS Status;
+
+
+ if (!Gbl_NsOutputFlag)
+ {
+ return (AE_OK);
+ }
+
+ Gbl_NumNamespaceObjects = 0;
+
+ /* File header */
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Contents of ACPI Namespace\n\n");
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "Count Depth Name - Type\n\n");
+
+ /* Walk entire namespace from the root */
+
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE, NsDoOneNamespaceObject, NULL,
+ NULL, NULL);
+
+ /* Print the full pathname for each namespace node */
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\nNamespace pathnames\n\n");
+
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE, NsDoOnePathname, NULL,
+ NULL, NULL);
+
+ return (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: NsDoOneNamespaceObject
+ *
+ * PARAMETERS: ACPI_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Dump a namespace object to the namespace output file.
+ * Called during the walk of the namespace to dump all objects.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+NsDoOneNamespaceObject (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue)
+{
+ ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
+ ACPI_OPERAND_OBJECT *ObjDesc;
+ ACPI_PARSE_OBJECT *Op;
+
+
+ Gbl_NumNamespaceObjects++;
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%5u [%u] %*s %4.4s - %s",
+ Gbl_NumNamespaceObjects, Level, (Level * 3), " ",
+ &Node->Name,
+ AcpiUtGetTypeName (Node->Type));
+
+ Op = Node->Op;
+ ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Node->Object);
+
+ if (!Op)
+ {
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n");
+ return (AE_OK);
+ }
+
+
+ if ((ObjDesc) &&
+ (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND))
+ {
+ switch (Node->Type)
+ {
+ case ACPI_TYPE_INTEGER:
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Value 0x%8.8X%8.8X]",
+ ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
+ break;
+
+
+ case ACPI_TYPE_STRING:
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Value \"%s\"]",
+ ObjDesc->String.Pointer);
+ break;
+
+ default:
+ /* Nothing to do for other types */
+ break;
+ }
+
+ }
+ else
+ {
+ switch (Node->Type)
+ {
+ case ACPI_TYPE_INTEGER:
+
+ if (Op->Asl.ParseOpcode == PARSEOP_NAME)
+ {
+ Op = Op->Asl.Child;
+ }
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
+ {
+ Op = Op->Asl.Next;
+ }
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Value 0x%8.8X%8.8X]",
+ ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
+ break;
+
+
+ case ACPI_TYPE_STRING:
+
+ if (Op->Asl.ParseOpcode == PARSEOP_NAME)
+ {
+ Op = Op->Asl.Child;
+ }
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
+ {
+ Op = Op->Asl.Next;
+ }
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Value \"%s\"]",
+ Op->Asl.Value.String);
+ break;
+
+
+ case ACPI_TYPE_LOCAL_REGION_FIELD:
+
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
+ {
+ Op = Op->Asl.Child;
+ }
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Offset 0x%04X Length 0x%04X bits]",
+ Op->Asl.Parent->Asl.ExtraValue, (UINT32) Op->Asl.Value.Integer);
+ break;
+
+
+ case ACPI_TYPE_BUFFER_FIELD:
+
+ switch (Op->Asl.ParseOpcode)
+ {
+ case PARSEOP_CREATEBYTEFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BYTE ( 8 bit)]");
+ break;
+
+ case PARSEOP_CREATEDWORDFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [DWORD (32 bit)]");
+ break;
+
+ case PARSEOP_CREATEQWORDFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [QWORD (64 bit)]");
+ break;
+
+ case PARSEOP_CREATEWORDFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [WORD (16 bit)]");
+ break;
+
+ case PARSEOP_CREATEBITFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [BIT ( 1 bit)]");
+ break;
+
+ case PARSEOP_CREATEFIELD:
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, " [Arbitrary Bit Field]");
+ break;
+
+ default:
+ break;
+
+ }
+ break;
+
+
+ case ACPI_TYPE_PACKAGE:
+
+ if (Op->Asl.ParseOpcode == PARSEOP_NAME)
+ {
+ Op = Op->Asl.Child;
+ }
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
+ {
+ Op = Op->Asl.Next;
+ }
+ Op = Op->Asl.Child;
+
+ if ((Op->Asl.ParseOpcode == PARSEOP_BYTECONST) ||
+ (Op->Asl.ParseOpcode == PARSEOP_RAW_DATA))
+ {
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Length 0x%.2X elements]",
+ Op->Asl.Value.Integer);
+ }
+ break;
+
+
+ case ACPI_TYPE_BUFFER:
+
+ if (Op->Asl.ParseOpcode == PARSEOP_NAME)
+ {
+ Op = Op->Asl.Child;
+ }
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING))
+ {
+ Op = Op->Asl.Next;
+ }
+ Op = Op->Asl.Child;
+
+ if (Op && (Op->Asl.ParseOpcode == PARSEOP_INTEGER))
+ {
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Initial Length 0x%.2X bytes]",
+ Op->Asl.Value.Integer);
+ }
+ break;
+
+
+ case ACPI_TYPE_METHOD:
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Code Length 0x%.4X bytes]",
+ Op->Asl.AmlSubtreeLength);
+ break;
+
+
+ case ACPI_TYPE_LOCAL_RESOURCE:
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Desc Offset 0x%.4X Bytes]", Node->Value);
+ break;
+
+
+ case ACPI_TYPE_LOCAL_RESOURCE_FIELD:
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ " [Field Offset 0x%.4X Bits 0x%.4X Bytes] ",
+ Node->Value, Node->Value / 8);
+
+ if (Node->Flags & ANOBJ_IS_REFERENCED)
+ {
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ "Referenced");
+ }
+ else
+ {
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT,
+ "Name not referenced");
+ }
+ break;
+
+
+ default:
+ /* Nothing to do for other types */
+ break;
+ }
+ }
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "\n");
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: NsDoOnePathname
+ *
+ * PARAMETERS: ACPI_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Print the full pathname for a namespace node.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+NsDoOnePathname (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue)
+{
+ ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
+ ACPI_STATUS Status;
+ ACPI_BUFFER TargetPath;
+
+
+ TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ Status = AcpiNsHandleToPathname (Node, &TargetPath);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ FlPrintFile (ASL_FILE_NAMESPACE_OUTPUT, "%s\n", TargetPath.Pointer);
+ ACPI_FREE (TargetPath.Pointer);
+
+ return (AE_OK);
+}
diff --git a/sys/contrib/dev/acpica/compiler/aslopcodes.c b/sys/contrib/dev/acpica/compiler/aslopcodes.c
index 9f4ab42..ca358dc 100644
--- a/sys/contrib/dev/acpica/compiler/aslopcodes.c
+++ b/sys/contrib/dev/acpica/compiler/aslopcodes.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -802,6 +802,14 @@ OpcGenerateAmlOpcode (
Op->Asl.Child->Asl.Next->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
break;
+ case PARSEOP_TIMER:
+
+ if (AcpiGbl_IntegerBitWidth == 32)
+ {
+ AslError (ASL_REMARK, ASL_MSG_TRUNCATION, Op, NULL);
+ }
+ break;
+
default:
/* Nothing to do for other opcodes */
break;
diff --git a/sys/contrib/dev/acpica/compiler/asloperands.c b/sys/contrib/dev/acpica/compiler/asloperands.c
index 2427265..f773f6f 100644
--- a/sys/contrib/dev/acpica/compiler/asloperands.c
+++ b/sys/contrib/dev/acpica/compiler/asloperands.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslopt.c b/sys/contrib/dev/acpica/compiler/aslopt.c
index 244e46c..3471006 100644
--- a/sys/contrib/dev/acpica/compiler/aslopt.c
+++ b/sys/contrib/dev/acpica/compiler/aslopt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -305,7 +305,7 @@ OptBuildShortestPath (
for (i = 0; i < NumCarats; i++)
{
- NewPathExternal[i] = '^';
+ NewPathExternal[i] = AML_PARENT_PREFIX;
}
/*
@@ -329,7 +329,7 @@ OptBuildShortestPath (
if (Op->Asl.AmlOpcode == AML_SCOPE_OP)
{
- NewPathExternal[i] = '^';
+ NewPathExternal[i] = AML_PARENT_PREFIX;
i++;
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)"));
}
@@ -448,7 +448,7 @@ OptOptimizeNameDeclaration (
if (((CurrentNode == AcpiGbl_RootNode) ||
(Op->Common.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK)) &&
- (AmlNameString[0] == '\\'))
+ (ACPI_IS_ROOT_PREFIX (AmlNameString[0])))
{
/*
* The current scope is the root, and the namepath has a root prefix
diff --git a/sys/contrib/dev/acpica/compiler/aslpredef.c b/sys/contrib/dev/acpica/compiler/aslpredef.c
index a5ebb83..dea0c83 100644
--- a/sys/contrib/dev/acpica/compiler/aslpredef.c
+++ b/sys/contrib/dev/acpica/compiler/aslpredef.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -66,6 +66,7 @@ ApCheckForSpecialName (
static void
ApCheckObjectType (
+ const char *PredefinedName,
ACPI_PARSE_OBJECT *Op,
UINT32 ExpectedBtypes);
@@ -383,7 +384,8 @@ ApCheckPredefinedReturnValue (
/* Static data return object - check against expected type */
- ApCheckObjectType (ReturnValueOp,
+ ApCheckObjectType (PredefinedNames[Index].Info.Name,
+ ReturnValueOp,
PredefinedNames[Index].Info.ExpectedBtypes);
break;
@@ -482,7 +484,8 @@ ApCheckForPredefinedObject (
/* Typecheck the actual object, it is the next argument */
- ApCheckObjectType (Op->Asl.Child->Asl.Next,
+ ApCheckObjectType (PredefinedNames[Index].Info.Name,
+ Op->Asl.Child->Asl.Next,
PredefinedNames[Index].Info.ExpectedBtypes);
return;
}
@@ -640,7 +643,8 @@ ApCheckForSpecialName (
*
* FUNCTION: ApCheckObjectType
*
- * PARAMETERS: Op - Current parse node
+ * PARAMETERS: PredefinedName - Name of the predefined object we are checking
+ * Op - Current parse node
* ExpectedBtypes - Bitmap of expected return type(s)
*
* RETURN: None
@@ -653,6 +657,7 @@ ApCheckForSpecialName (
static void
ApCheckObjectType (
+ const char *PredefinedName,
ACPI_PARSE_OBJECT *Op,
UINT32 ExpectedBtypes)
{
@@ -701,8 +706,8 @@ TypeErrorExit:
ApGetExpectedTypes (StringBuffer, ExpectedBtypes);
- sprintf (MsgBuffer, "found %s, requires %s",
- UtGetOpName (Op->Asl.ParseOpcode), StringBuffer);
+ sprintf (MsgBuffer, "%s: found %s, requires %s",
+ PredefinedName, UtGetOpName (Op->Asl.ParseOpcode), StringBuffer);
AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Op,
MsgBuffer);
diff --git a/sys/contrib/dev/acpica/compiler/aslresource.c b/sys/contrib/dev/acpica/compiler/aslresource.c
index e0e582a..d809b73 100644
--- a/sys/contrib/dev/acpica/compiler/aslresource.c
+++ b/sys/contrib/dev/acpica/compiler/aslresource.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype1.c b/sys/contrib/dev/acpica/compiler/aslrestype1.c
index 3de2421..21a8705 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype1.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype1.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype1i.c b/sys/contrib/dev/acpica/compiler/aslrestype1i.c
index 77bdd91..3ec92aa 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype1i.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype1i.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2.c b/sys/contrib/dev/acpica/compiler/aslrestype2.c
index 4784f86..942d45e 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2d.c b/sys/contrib/dev/acpica/compiler/aslrestype2d.c
index 7836461..035b6ec 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2d.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2d.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2e.c b/sys/contrib/dev/acpica/compiler/aslrestype2e.c
index fe2f0d8..5621762 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2e.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2e.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2q.c b/sys/contrib/dev/acpica/compiler/aslrestype2q.c
index 70cfbd5..3a002a4 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2q.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2q.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2s.c b/sys/contrib/dev/acpica/compiler/aslrestype2s.c
index fa30b58..42d51a9 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2s.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2s.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslrestype2w.c b/sys/contrib/dev/acpica/compiler/aslrestype2w.c
index 613b7b3..be388b7 100644
--- a/sys/contrib/dev/acpica/compiler/aslrestype2w.c
+++ b/sys/contrib/dev/acpica/compiler/aslrestype2w.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslstartup.c b/sys/contrib/dev/acpica/compiler/aslstartup.c
index 3d50a21..8deb894 100644
--- a/sys/contrib/dev/acpica/compiler/aslstartup.c
+++ b/sys/contrib/dev/acpica/compiler/aslstartup.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -341,7 +341,7 @@ AslDoOneFile (
/* TBD: Handle additional output files for disassembler */
Status = FlOpenMiscOutputFiles (Gbl_OutputFilenamePrefix);
- LsDisplayNamespace ();
+ NsDisplayNamespace ();
#endif
/* Shutdown compiler and ACPICA subsystem */
diff --git a/sys/contrib/dev/acpica/compiler/aslstubs.c b/sys/contrib/dev/acpica/compiler/aslstubs.c
index 8711441..9ac9698 100644
--- a/sys/contrib/dev/acpica/compiler/aslstubs.c
+++ b/sys/contrib/dev/acpica/compiler/aslstubs.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslsupport.l b/sys/contrib/dev/acpica/compiler/aslsupport.l
index daab402..90af049 100644
--- a/sys/contrib/dev/acpica/compiler/aslsupport.l
+++ b/sys/contrib/dev/acpica/compiler/aslsupport.l
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/asltransform.c b/sys/contrib/dev/acpica/compiler/asltransform.c
index 7c8bfcd..7a29446 100644
--- a/sys/contrib/dev/acpica/compiler/asltransform.c
+++ b/sys/contrib/dev/acpica/compiler/asltransform.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/asltree.c b/sys/contrib/dev/acpica/compiler/asltree.c
index 86e7f2d..8fa532b 100644
--- a/sys/contrib/dev/acpica/compiler/asltree.c
+++ b/sys/contrib/dev/acpica/compiler/asltree.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/asltypes.h b/sys/contrib/dev/acpica/compiler/asltypes.h
index 0e3b16a..538911f 100644
--- a/sys/contrib/dev/acpica/compiler/asltypes.h
+++ b/sys/contrib/dev/acpica/compiler/asltypes.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslutils.c b/sys/contrib/dev/acpica/compiler/aslutils.c
index 32ab1c9..1a4a27d 100644
--- a/sys/contrib/dev/acpica/compiler/aslutils.c
+++ b/sys/contrib/dev/acpica/compiler/aslutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -826,7 +826,8 @@ UtAttachNameseg (
/* No dots in the namepath, there is only a single nameseg. */
/* Handle prefixes */
- while ((*Name == '\\') || (*Name == '^'))
+ while (ACPI_IS_ROOT_PREFIX (*Name) ||
+ ACPI_IS_PARENT_PREFIX (*Name))
{
Name++;
}
diff --git a/sys/contrib/dev/acpica/compiler/asluuid.c b/sys/contrib/dev/acpica/compiler/asluuid.c
index 485db6b..ed884dc 100644
--- a/sys/contrib/dev/acpica/compiler/asluuid.c
+++ b/sys/contrib/dev/acpica/compiler/asluuid.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/aslwalks.c b/sys/contrib/dev/acpica/compiler/aslwalks.c
index 77bff82..6613cac 100644
--- a/sys/contrib/dev/acpica/compiler/aslwalks.c
+++ b/sys/contrib/dev/acpica/compiler/aslwalks.c
@@ -1,11 +1,11 @@
/******************************************************************************
*
- * Module Name: aslwalks.c - major analytical parse tree walks
+ * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
*
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,575 +54,6 @@
/*******************************************************************************
*
- * FUNCTION: AnMethodAnalysisWalkBegin
- *
- * PARAMETERS: ASL_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
- * 1) Initialized local variables
- * 2) Valid arguments
- * 3) Return types
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AnMethodAnalysisWalkBegin (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context)
-{
- ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
- ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;
- ACPI_PARSE_OBJECT *Next;
- UINT32 RegisterNumber;
- UINT32 i;
- char LocalName[] = "Local0";
- char ArgName[] = "Arg0";
- ACPI_PARSE_OBJECT *ArgNode;
- ACPI_PARSE_OBJECT *NextType;
- ACPI_PARSE_OBJECT *NextParamType;
- UINT8 ActualArgs = 0;
-
-
- switch (Op->Asl.ParseOpcode)
- {
- case PARSEOP_METHOD:
-
- TotalMethods++;
-
- /* Create and init method info */
-
- MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
- MethodInfo->Next = WalkInfo->MethodStack;
- MethodInfo->Op = Op;
-
- WalkInfo->MethodStack = MethodInfo;
-
- /* Get the name node, ignored here */
-
- Next = Op->Asl.Child;
-
- /* Get the NumArguments node */
-
- Next = Next->Asl.Next;
- MethodInfo->NumArguments = (UINT8)
- (((UINT8) Next->Asl.Value.Integer) & 0x07);
-
- /* Get the SerializeRule and SyncLevel nodes, ignored here */
-
- Next = Next->Asl.Next;
- Next = Next->Asl.Next;
- ArgNode = Next;
-
- /* Get the ReturnType node */
-
- Next = Next->Asl.Next;
-
- NextType = Next->Asl.Child;
- while (NextType)
- {
- /* Get and map each of the ReturnTypes */
-
- MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
- NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
- NextType = NextType->Asl.Next;
- }
-
- /* Get the ParameterType node */
-
- Next = Next->Asl.Next;
-
- NextType = Next->Asl.Child;
- while (NextType)
- {
- if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
- {
- NextParamType = NextType->Asl.Child;
- while (NextParamType)
- {
- MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType);
- NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
- NextParamType = NextParamType->Asl.Next;
- }
- }
- else
- {
- MethodInfo->ValidArgTypes[ActualArgs] =
- AnMapObjTypeToBtype (NextType);
- NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
- ActualArgs++;
- }
-
- NextType = NextType->Asl.Next;
- }
-
- if ((MethodInfo->NumArguments) &&
- (MethodInfo->NumArguments != ActualArgs))
- {
- /* error: Param list did not match number of args */
- }
-
- /* Allow numarguments == 0 for Function() */
-
- if ((!MethodInfo->NumArguments) && (ActualArgs))
- {
- MethodInfo->NumArguments = ActualArgs;
- ArgNode->Asl.Value.Integer |= ActualArgs;
- }
-
- /*
- * Actual arguments are initialized at method entry.
- * All other ArgX "registers" can be used as locals, so we
- * track their initialization.
- */
- for (i = 0; i < MethodInfo->NumArguments; i++)
- {
- MethodInfo->ArgInitialized[i] = TRUE;
- }
- break;
-
-
- case PARSEOP_METHODCALL:
-
- if (MethodInfo &&
- (Op->Asl.Node == MethodInfo->Op->Asl.Node))
- {
- AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
- }
- break;
-
-
- case PARSEOP_LOCAL0:
- case PARSEOP_LOCAL1:
- case PARSEOP_LOCAL2:
- case PARSEOP_LOCAL3:
- case PARSEOP_LOCAL4:
- case PARSEOP_LOCAL5:
- case PARSEOP_LOCAL6:
- case PARSEOP_LOCAL7:
-
- if (!MethodInfo)
- {
- /*
- * Local was used outside a control method, or there was an error
- * in the method declaration.
- */
- AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
- return (AE_ERROR);
- }
-
- RegisterNumber = (Op->Asl.AmlOpcode & 0x000F);
-
- /*
- * If the local is being used as a target, mark the local
- * initialized
- */
- if (Op->Asl.CompileFlags & NODE_IS_TARGET)
- {
- MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
- }
-
- /*
- * Otherwise, this is a reference, check if the local
- * has been previously initialized.
- *
- * The only operator that accepts an uninitialized value is ObjectType()
- */
- else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
- (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
- {
- LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
- AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
- }
- break;
-
-
- case PARSEOP_ARG0:
- case PARSEOP_ARG1:
- case PARSEOP_ARG2:
- case PARSEOP_ARG3:
- case PARSEOP_ARG4:
- case PARSEOP_ARG5:
- case PARSEOP_ARG6:
-
- if (!MethodInfo)
- {
- /*
- * Arg was used outside a control method, or there was an error
- * in the method declaration.
- */
- AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
- return (AE_ERROR);
- }
-
- RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
- ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
-
- /*
- * If the Arg is being used as a target, mark the local
- * initialized
- */
- if (Op->Asl.CompileFlags & NODE_IS_TARGET)
- {
- MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
- }
-
- /*
- * Otherwise, this is a reference, check if the Arg
- * has been previously initialized.
- *
- * The only operator that accepts an uninitialized value is ObjectType()
- */
- else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
- (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
- {
- AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
- }
-
- /* Flag this arg if it is not a "real" argument to the method */
-
- if (RegisterNumber >= MethodInfo->NumArguments)
- {
- AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
- }
- break;
-
-
- case PARSEOP_RETURN:
-
- if (!MethodInfo)
- {
- /*
- * Probably was an error in the method declaration,
- * no additional error here
- */
- ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
- return (AE_ERROR);
- }
-
- /*
- * A child indicates a possible return value. A simple Return or
- * Return() is marked with NODE_IS_NULL_RETURN by the parser so
- * that it is not counted as a "real" return-with-value, although
- * the AML code that is actually emitted is Return(0). The AML
- * definition of Return has a required parameter, so we are
- * forced to convert a null return to Return(0).
- */
- if ((Op->Asl.Child) &&
- (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
- (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN)))
- {
- MethodInfo->NumReturnWithValue++;
- }
- else
- {
- MethodInfo->NumReturnNoValue++;
- }
- break;
-
-
- case PARSEOP_BREAK:
- case PARSEOP_CONTINUE:
-
- Next = Op->Asl.Parent;
- while (Next)
- {
- if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
- {
- break;
- }
- Next = Next->Asl.Parent;
- }
-
- if (!Next)
- {
- AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
- }
- break;
-
-
- case PARSEOP_STALL:
-
- /* We can range check if the argument is an integer */
-
- if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
- (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
- {
- AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
- }
- break;
-
-
- case PARSEOP_DEVICE:
- case PARSEOP_EVENT:
- case PARSEOP_MUTEX:
- case PARSEOP_OPERATIONREGION:
- case PARSEOP_POWERRESOURCE:
- case PARSEOP_PROCESSOR:
- case PARSEOP_THERMALZONE:
-
- /*
- * The first operand is a name to be created in the namespace.
- * Check against the reserved list.
- */
- i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
- if (i < ACPI_VALID_RESERVED_NAME_MAX)
- {
- AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
- }
- break;
-
-
- case PARSEOP_NAME:
-
- /* Typecheck any predefined names statically defined with Name() */
-
- ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
-
- /* Special typechecking for _HID */
-
- if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg))
- {
- Next = Op->Asl.Child->Asl.Next;
- AnCheckId (Next, ASL_TYPE_HID);
- }
-
- /* Special typechecking for _CID */
-
- else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg))
- {
- Next = Op->Asl.Child->Asl.Next;
-
- if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
- (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
- {
- Next = Next->Asl.Child;
- while (Next)
- {
- AnCheckId (Next, ASL_TYPE_CID);
- Next = Next->Asl.Next;
- }
- }
- else
- {
- AnCheckId (Next, ASL_TYPE_CID);
- }
- }
- break;
-
-
- default:
- break;
- }
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AnMethodAnalysisWalkEnd
- *
- * PARAMETERS: ASL_WALK_CALLBACK
- *
- * RETURN: Status
- *
- * DESCRIPTION: Ascending callback for analysis walk. Complete method
- * return analysis.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AnMethodAnalysisWalkEnd (
- ACPI_PARSE_OBJECT *Op,
- UINT32 Level,
- void *Context)
-{
- ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
- ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;
-
-
- switch (Op->Asl.ParseOpcode)
- {
- case PARSEOP_METHOD:
- case PARSEOP_RETURN:
- if (!MethodInfo)
- {
- printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
- AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
- "No method info for this method");
-
- CmCleanupAndExit ();
- return (AE_AML_INTERNAL);
- }
- break;
-
- default:
- break;
- }
-
- switch (Op->Asl.ParseOpcode)
- {
- case PARSEOP_METHOD:
-
- WalkInfo->MethodStack = MethodInfo->Next;
-
- /*
- * Check if there is no return statement at the end of the
- * method AND we can actually get there -- i.e., the execution
- * of the method can possibly terminate without a return statement.
- */
- if ((!AnLastStatementIsReturn (Op)) &&
- (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
- {
- /*
- * No return statement, and execution can possibly exit
- * via this path. This is equivalent to Return ()
- */
- MethodInfo->NumReturnNoValue++;
- }
-
- /*
- * Check for case where some return statements have a return value
- * and some do not. Exit without a return statement is a return with
- * no value
- */
- if (MethodInfo->NumReturnNoValue &&
- MethodInfo->NumReturnWithValue)
- {
- AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
- Op->Asl.ExternalName);
- }
-
- /*
- * If there are any RETURN() statements with no value, or there is a
- * control path that allows the method to exit without a return value,
- * we mark the method as a method that does not return a value. This
- * knowledge can be used to check method invocations that expect a
- * returned value.
- */
- if (MethodInfo->NumReturnNoValue)
- {
- if (MethodInfo->NumReturnWithValue)
- {
- Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
- }
- else
- {
- Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
- }
- }
-
- /*
- * Check predefined method names for correct return behavior
- * and correct number of arguments. Also, some special checks
- * For GPE and _REG methods.
- */
- if (ApCheckForPredefinedMethod (Op, MethodInfo))
- {
- /* Special check for two names like _L01 and _E01 in same scope */
-
- ApCheckForGpeNameConflict (Op);
-
- /*
- * Special check for _REG: Must have an operation region definition
- * within the same scope!
- */
- ApCheckRegMethod (Op);
- }
-
- ACPI_FREE (MethodInfo);
- break;
-
-
- case PARSEOP_NAME:
-
- /* Special check for two names like _L01 and _E01 in same scope */
-
- ApCheckForGpeNameConflict (Op);
- break;
-
-
- case PARSEOP_RETURN:
-
- /*
- * If the parent is a predefined method name, attempt to typecheck
- * the return value. Only static types can be validated.
- */
- ApCheckPredefinedReturnValue (Op, MethodInfo);
-
- /*
- * The parent block does not "exit" and continue execution -- the
- * method is terminated here with the Return() statement.
- */
- Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
-
- /* Used in the "typing" pass later */
-
- Op->Asl.ParentMethod = MethodInfo->Op;
-
- /*
- * If there is a peer node after the return statement, then this
- * node is unreachable code -- i.e., it won't be executed because of
- * the preceding Return() statement.
- */
- if (Op->Asl.Next)
- {
- AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
- }
- break;
-
-
- case PARSEOP_IF:
-
- if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
- (Op->Asl.Next) &&
- (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
- {
- /*
- * This IF has a corresponding ELSE. The IF block has no exit,
- * (it contains an unconditional Return)
- * mark the ELSE block to remember this fact.
- */
- Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
- }
- break;
-
-
- case PARSEOP_ELSE:
-
- if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
- (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
- {
- /*
- * This ELSE block has no exit and the corresponding IF block
- * has no exit either. Therefore, the parent node has no exit.
- */
- Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
- }
- break;
-
-
- default:
-
- if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
- (Op->Asl.Parent))
- {
- /* If this node has no exit, then the parent has no exit either */
-
- Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
- }
- break;
- }
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AnMethodTypingWalkEnd
*
* PARAMETERS: ASL_WALK_CALLBACK
diff --git a/sys/contrib/dev/acpica/compiler/aslxref.c b/sys/contrib/dev/acpica/compiler/aslxref.c
new file mode 100644
index 0000000..188c214
--- /dev/null
+++ b/sys/contrib/dev/acpica/compiler/aslxref.c
@@ -0,0 +1,874 @@
+/******************************************************************************
+ *
+ * Module Name: aslxref - Namespace cross-reference
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/compiler/aslcompiler.h>
+#include "aslcompiler.y.h"
+#include <contrib/dev/acpica/include/acparser.h>
+#include <contrib/dev/acpica/include/amlcode.h>
+#include <contrib/dev/acpica/include/acnamesp.h>
+#include <contrib/dev/acpica/include/acdispat.h>
+
+
+#define _COMPONENT ACPI_COMPILER
+ ACPI_MODULE_NAME ("aslxref")
+
+/* Local prototypes */
+
+static ACPI_STATUS
+XfNamespaceLocateBegin (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context);
+
+static ACPI_STATUS
+XfNamespaceLocateEnd (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context);
+
+static BOOLEAN
+XfObjectExists (
+ char *Name);
+
+static ACPI_STATUS
+XfCompareOneNamespaceObject (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue);
+
+static void
+XfCheckFieldRange (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 RegionBitLength,
+ UINT32 FieldBitOffset,
+ UINT32 FieldBitLength,
+ UINT32 AccessBitWidth);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfCrossReferenceNamespace
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Perform a cross reference check of the parse tree against the
+ * namespace. Every named referenced within the parse tree
+ * should be get resolved with a namespace lookup. If not, the
+ * original reference in the ASL code is invalid -- i.e., refers
+ * to a non-existent object.
+ *
+ * NOTE: The ASL "External" operator causes the name to be inserted into the
+ * namespace so that references to the external name will be resolved
+ * correctly here.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+XfCrossReferenceNamespace (
+ void)
+{
+ ACPI_WALK_STATE *WalkState;
+
+
+ DbgPrint (ASL_DEBUG_OUTPUT, "\nCross referencing namespace\n\n");
+
+ /*
+ * Create a new walk state for use when looking up names
+ * within the namespace (Passed as context to the callbacks)
+ */
+ WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
+ if (!WalkState)
+ {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Walk the entire parse tree */
+
+ TrWalkParseTree (RootNode, ASL_WALK_VISIT_TWICE, XfNamespaceLocateBegin,
+ XfNamespaceLocateEnd, WalkState);
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfObjectExists
+ *
+ * PARAMETERS: Name - 4 char ACPI name
+ *
+ * RETURN: TRUE if name exists in namespace
+ *
+ * DESCRIPTION: Walk the namespace to find an object
+ *
+ ******************************************************************************/
+
+static BOOLEAN
+XfObjectExists (
+ char *Name)
+{
+ ACPI_STATUS Status;
+
+
+ /* Walk entire namespace from the supplied root */
+
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX, FALSE, XfCompareOneNamespaceObject, NULL,
+ Name, NULL);
+ if (Status == AE_CTRL_TRUE)
+ {
+ /* At least one instance of the name was found */
+
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfCompareOneNamespaceObject
+ *
+ * PARAMETERS: ACPI_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Compare name of one object.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+XfCompareOneNamespaceObject (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue)
+{
+ ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
+
+
+ /* Simply check the name */
+
+ if (*((UINT32 *) (Context)) == Node->Name.Integer)
+ {
+ /* Abort walk if we found one instance */
+
+ return (AE_CTRL_TRUE);
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfCheckFieldRange
+ *
+ * PARAMETERS: RegionBitLength - Length of entire parent region
+ * FieldBitOffset - Start of the field unit (within region)
+ * FieldBitLength - Entire length of field unit
+ * AccessBitWidth - Access width of the field unit
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Check one field unit to make sure it fits in the parent
+ * op region.
+ *
+ * Note: AccessBitWidth must be either 8,16,32, or 64
+ *
+ ******************************************************************************/
+
+static void
+XfCheckFieldRange (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 RegionBitLength,
+ UINT32 FieldBitOffset,
+ UINT32 FieldBitLength,
+ UINT32 AccessBitWidth)
+{
+ UINT32 FieldEndBitOffset;
+
+
+ /*
+ * Check each field unit against the region size. The entire
+ * field unit (start offset plus length) must fit within the
+ * region.
+ */
+ FieldEndBitOffset = FieldBitOffset + FieldBitLength;
+
+ if (FieldEndBitOffset > RegionBitLength)
+ {
+ /* Field definition itself is beyond the end-of-region */
+
+ AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_OFFSET, Op, NULL);
+ return;
+ }
+
+ /*
+ * Now check that the field plus AccessWidth doesn't go beyond
+ * the end-of-region. Assumes AccessBitWidth is a power of 2
+ */
+ FieldEndBitOffset = ACPI_ROUND_UP (FieldEndBitOffset, AccessBitWidth);
+
+ if (FieldEndBitOffset > RegionBitLength)
+ {
+ /* Field definition combined with the access is beyond EOR */
+
+ AslError (ASL_ERROR, ASL_MSG_FIELD_UNIT_ACCESS_WIDTH, Op, NULL);
+ }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfNamespaceLocateBegin
+ *
+ * PARAMETERS: ASL_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Descending callback used during cross-reference. For named
+ * object references, attempt to locate the name in the
+ * namespace.
+ *
+ * NOTE: ASL references to named fields within resource descriptors are
+ * resolved to integer values here. Therefore, this step is an
+ * important part of the code generation. We don't know that the
+ * name refers to a resource descriptor until now.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+XfNamespaceLocateBegin (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context)
+{
+ ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context;
+ ACPI_NAMESPACE_NODE *Node;
+ ACPI_STATUS Status;
+ ACPI_OBJECT_TYPE ObjectType;
+ char *Path;
+ UINT8 PassedArgs;
+ ACPI_PARSE_OBJECT *NextOp;
+ ACPI_PARSE_OBJECT *OwningOp;
+ ACPI_PARSE_OBJECT *SpaceIdOp;
+ UINT32 MinimumLength;
+ UINT32 Offset;
+ UINT32 FieldBitLength;
+ UINT32 TagBitLength;
+ UINT8 Message = 0;
+ const ACPI_OPCODE_INFO *OpInfo;
+ UINT32 Flags;
+
+
+ ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op);
+
+ /*
+ * If this node is the actual declaration of a name
+ * [such as the XXXX name in "Method (XXXX)"],
+ * we are not interested in it here. We only care about names that are
+ * references to other objects within the namespace and the parent objects
+ * of name declarations
+ */
+ if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
+ {
+ return (AE_OK);
+ }
+
+ /* We are only interested in opcodes that have an associated name */
+
+ OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
+
+ if ((!(OpInfo->Flags & AML_NAMED)) &&
+ (!(OpInfo->Flags & AML_CREATE)) &&
+ (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
+ (Op->Asl.ParseOpcode != PARSEOP_NAMESEG) &&
+ (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
+ {
+ return (AE_OK);
+ }
+
+ /*
+ * One special case: CondRefOf operator - we don't care if the name exists
+ * or not at this point, just ignore it, the point of the operator is to
+ * determine if the name exists at runtime.
+ */
+ if ((Op->Asl.Parent) &&
+ (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
+ {
+ return (AE_OK);
+ }
+
+ /*
+ * We must enable the "search-to-root" for single NameSegs, but
+ * we have to be very careful about opening up scopes
+ */
+ Flags = ACPI_NS_SEARCH_PARENT;
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
+ {
+ /*
+ * These are name references, do not push the scope stack
+ * for them.
+ */
+ Flags |= ACPI_NS_DONT_OPEN_SCOPE;
+ }
+
+ /* Get the NamePath from the appropriate place */
+
+ if (OpInfo->Flags & AML_NAMED)
+ {
+ /* For nearly all NAMED operators, the name reference is the first child */
+
+ Path = Op->Asl.Child->Asl.Value.String;
+ if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
+ {
+ /*
+ * ALIAS is the only oddball opcode, the name declaration
+ * (alias name) is the second operand
+ */
+ Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
+ }
+ }
+ else if (OpInfo->Flags & AML_CREATE)
+ {
+ /* Name must appear as the last parameter */
+
+ NextOp = Op->Asl.Child;
+ while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
+ {
+ NextOp = NextOp->Asl.Next;
+ }
+ Path = NextOp->Asl.Value.String;
+ }
+ else
+ {
+ Path = Op->Asl.Value.String;
+ }
+
+ ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Type=%s\n", AcpiUtGetTypeName (ObjectType)));
+
+ /*
+ * Lookup the name in the namespace. Name must exist at this point, or it
+ * is an invalid reference.
+ *
+ * The namespace is also used as a lookup table for references to resource
+ * descriptors and the fields within them.
+ */
+ Gbl_NsLookupCount++;
+
+ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
+ ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node));
+ if (ACPI_FAILURE (Status))
+ {
+ if (Status == AE_NOT_FOUND)
+ {
+ /*
+ * We didn't find the name reference by path -- we can qualify this
+ * a little better before we print an error message
+ */
+ if (strlen (Path) == ACPI_NAME_SIZE)
+ {
+ /* A simple, one-segment ACPI name */
+
+ if (XfObjectExists (Path))
+ {
+ /*
+ * There exists such a name, but we couldn't get to it
+ * from this scope
+ */
+ AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
+ Op->Asl.ExternalName);
+ }
+ else
+ {
+ /* The name doesn't exist, period */
+
+ AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
+ Op, Op->Asl.ExternalName);
+ }
+ }
+ else
+ {
+ /* Check for a fully qualified path */
+
+ if (Path[0] == AML_ROOT_PREFIX)
+ {
+ /* Gave full path, the object does not exist */
+
+ AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
+ Op->Asl.ExternalName);
+ }
+ else
+ {
+ /*
+ * We can't tell whether it doesn't exist or just
+ * can't be reached.
+ */
+ AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
+ Op->Asl.ExternalName);
+ }
+ }
+
+ Status = AE_OK;
+ }
+ return (Status);
+ }
+
+ /* Check for a reference vs. name declaration */
+
+ if (!(OpInfo->Flags & AML_NAMED) &&
+ !(OpInfo->Flags & AML_CREATE))
+ {
+ /* This node has been referenced, mark it for reference check */
+
+ Node->Flags |= ANOBJ_IS_REFERENCED;
+ }
+
+ /* Attempt to optimize the NamePath */
+
+ OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);
+
+ /*
+ * 1) Dereference an alias (A name reference that is an alias)
+ * Aliases are not nested, the alias always points to the final object
+ */
+ if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
+ (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
+ {
+ /* This node points back to the original PARSEOP_ALIAS */
+
+ NextOp = Node->Op;
+
+ /* The first child is the alias target op */
+
+ NextOp = NextOp->Asl.Child;
+
+ /* That in turn points back to original target alias node */
+
+ if (NextOp->Asl.Node)
+ {
+ Node = NextOp->Asl.Node;
+ }
+
+ /* Else - forward reference to alias, will be resolved later */
+ }
+
+ /* 2) Check for a reference to a resource descriptor */
+
+ if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
+ (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
+ {
+ /*
+ * This was a reference to a field within a resource descriptor.
+ * Extract the associated field offset (either a bit or byte
+ * offset depending on the field type) and change the named
+ * reference into an integer for AML code generation
+ */
+ Offset = Node->Value;
+ TagBitLength = Node->Length;
+
+ /*
+ * If a field is being created, generate the length (in bits) of
+ * the field. Note: Opcodes other than CreateXxxField and Index
+ * can come through here. For other opcodes, we just need to
+ * convert the resource tag reference to an integer offset.
+ */
+ switch (Op->Asl.Parent->Asl.AmlOpcode)
+ {
+ case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
+ /*
+ * We know the length operand is an integer constant because
+ * we know that it contains a reference to a resource
+ * descriptor tag.
+ */
+ FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
+ break;
+
+ case AML_CREATE_BIT_FIELD_OP:
+ FieldBitLength = 1;
+ break;
+
+ case AML_CREATE_BYTE_FIELD_OP:
+ case AML_INDEX_OP:
+ FieldBitLength = 8;
+ break;
+
+ case AML_CREATE_WORD_FIELD_OP:
+ FieldBitLength = 16;
+ break;
+
+ case AML_CREATE_DWORD_FIELD_OP:
+ FieldBitLength = 32;
+ break;
+
+ case AML_CREATE_QWORD_FIELD_OP:
+ FieldBitLength = 64;
+ break;
+
+ default:
+ FieldBitLength = 0;
+ break;
+ }
+
+ /* Check the field length against the length of the resource tag */
+
+ if (FieldBitLength)
+ {
+ if (TagBitLength < FieldBitLength)
+ {
+ Message = ASL_MSG_TAG_SMALLER;
+ }
+ else if (TagBitLength > FieldBitLength)
+ {
+ Message = ASL_MSG_TAG_LARGER;
+ }
+
+ if (Message)
+ {
+ sprintf (MsgBuffer, "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
+ TagBitLength, (TagBitLength > 1) ? "s" : "",
+ FieldBitLength, (FieldBitLength > 1) ? "s" : "");
+
+ AslError (ASL_WARNING, Message, Op, MsgBuffer);
+ }
+ }
+
+ /* Convert the BitOffset to a ByteOffset for certain opcodes */
+
+ switch (Op->Asl.Parent->Asl.AmlOpcode)
+ {
+ case AML_CREATE_BYTE_FIELD_OP:
+ case AML_CREATE_WORD_FIELD_OP:
+ case AML_CREATE_DWORD_FIELD_OP:
+ case AML_CREATE_QWORD_FIELD_OP:
+ case AML_INDEX_OP:
+
+ Offset = ACPI_DIV_8 (Offset);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Now convert this node to an integer whose value is the field offset */
+
+ Op->Asl.AmlLength = 0;
+ Op->Asl.ParseOpcode = PARSEOP_INTEGER;
+ Op->Asl.Value.Integer = (UINT64) Offset;
+ Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD;
+
+ OpcGenerateAmlOpcode (Op);
+ }
+
+ /* 3) Check for a method invocation */
+
+ else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
+ (Node->Type == ACPI_TYPE_METHOD) &&
+ (Op->Asl.Parent) &&
+ (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD)) ||
+
+ (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
+ {
+
+ /*
+ * A reference to a method within one of these opcodes is not an
+ * invocation of the method, it is simply a reference to the method.
+ */
+ if ((Op->Asl.Parent) &&
+ ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF) ||
+ (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF) ||
+ (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE)))
+ {
+ return (AE_OK);
+ }
+ /*
+ * There are two types of method invocation:
+ * 1) Invocation with arguments -- the parser recognizes this
+ * as a METHODCALL.
+ * 2) Invocation with no arguments --the parser cannot determine that
+ * this is a method invocation, therefore we have to figure it out
+ * here.
+ */
+ if (Node->Type != ACPI_TYPE_METHOD)
+ {
+ sprintf (MsgBuffer, "%s is a %s",
+ Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));
+
+ AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer);
+ return (AE_OK);
+ }
+
+ /* Save the method node in the caller's op */
+
+ Op->Asl.Node = Node;
+ if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
+ {
+ return (AE_OK);
+ }
+
+ /*
+ * This is a method invocation, with or without arguments.
+ * Count the number of arguments, each appears as a child
+ * under the parent node
+ */
+ Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
+ UtSetParseOpName (Op);
+
+ PassedArgs = 0;
+ NextOp = Op->Asl.Child;
+
+ while (NextOp)
+ {
+ PassedArgs++;
+ NextOp = NextOp->Asl.Next;
+ }
+
+ if (Node->Value != ASL_EXTERNAL_METHOD)
+ {
+ /*
+ * Check the parsed arguments with the number expected by the
+ * method declaration itself
+ */
+ if (PassedArgs != Node->Value)
+ {
+ sprintf (MsgBuffer, "%s requires %u", Op->Asl.ExternalName,
+ Node->Value);
+
+ if (PassedArgs < Node->Value)
+ {
+ AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer);
+ }
+ else
+ {
+ AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer);
+ }
+ }
+ }
+ }
+
+ /* 4) Check for an ASL Field definition */
+
+ else if ((Op->Asl.Parent) &&
+ ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD) ||
+ (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
+ {
+ /*
+ * Offset checking for fields. If the parent operation region has a
+ * constant length (known at compile time), we can check fields
+ * defined in that region against the region length. This will catch
+ * fields and field units that cannot possibly fit within the region.
+ *
+ * Note: Index fields do not directly reference an operation region,
+ * thus they are not included in this check.
+ */
+ if (Op == Op->Asl.Parent->Asl.Child)
+ {
+ /*
+ * This is the first child of the field node, which is
+ * the name of the region. Get the parse node for the
+ * region -- which contains the length of the region.
+ */
+ OwningOp = Node->Op;
+ Op->Asl.Parent->Asl.ExtraValue =
+ ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);
+
+ /* Examine the field access width */
+
+ switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
+ {
+ case AML_FIELD_ACCESS_ANY:
+ case AML_FIELD_ACCESS_BYTE:
+ case AML_FIELD_ACCESS_BUFFER:
+ default:
+ MinimumLength = 1;
+ break;
+
+ case AML_FIELD_ACCESS_WORD:
+ MinimumLength = 2;
+ break;
+
+ case AML_FIELD_ACCESS_DWORD:
+ MinimumLength = 4;
+ break;
+
+ case AML_FIELD_ACCESS_QWORD:
+ MinimumLength = 8;
+ break;
+ }
+
+ /*
+ * Is the region at least as big as the access width?
+ * Note: DataTableRegions have 0 length
+ */
+ if (((UINT32) OwningOp->Asl.Value.Integer) &&
+ ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
+ {
+ AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
+ }
+
+ /*
+ * Check EC/CMOS/SMBUS fields to make sure that the correct
+ * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
+ */
+ SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
+ switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
+ {
+ case ACPI_ADR_SPACE_EC:
+ case ACPI_ADR_SPACE_CMOS:
+ case ACPI_ADR_SPACE_GPIO:
+
+ if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE)
+ {
+ AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
+ }
+ break;
+
+ case ACPI_ADR_SPACE_SMBUS:
+ case ACPI_ADR_SPACE_IPMI:
+ case ACPI_ADR_SPACE_GSBUS:
+
+ if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER)
+ {
+ AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
+ }
+ break;
+
+ default:
+
+ /* Nothing to do for other address spaces */
+ break;
+ }
+ }
+ else
+ {
+ /*
+ * This is one element of the field list. Check to make sure
+ * that it does not go beyond the end of the parent operation region.
+ *
+ * In the code below:
+ * Op->Asl.Parent->Asl.ExtraValue - Region Length (bits)
+ * Op->Asl.ExtraValue - Field start offset (bits)
+ * Op->Asl.Child->Asl.Value.Integer32 - Field length (bits)
+ * Op->Asl.Child->Asl.ExtraValue - Field access width (bits)
+ */
+ if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
+ {
+ XfCheckFieldRange (Op,
+ Op->Asl.Parent->Asl.ExtraValue,
+ Op->Asl.ExtraValue,
+ (UINT32) Op->Asl.Child->Asl.Value.Integer,
+ Op->Asl.Child->Asl.ExtraValue);
+ }
+ }
+ }
+
+ Op->Asl.Node = Node;
+ return (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: XfNamespaceLocateEnd
+ *
+ * PARAMETERS: ASL_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Ascending callback used during cross reference. We only
+ * need to worry about scope management here.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+XfNamespaceLocateEnd (
+ ACPI_PARSE_OBJECT *Op,
+ UINT32 Level,
+ void *Context)
+{
+ ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context;
+ const ACPI_OPCODE_INFO *OpInfo;
+
+
+ ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd);
+
+
+ /* We are only interested in opcodes that have an associated name */
+
+ OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
+ if (!(OpInfo->Flags & AML_NAMED))
+ {
+ return (AE_OK);
+ }
+
+ /* Not interested in name references, we did not open a scope for them */
+
+ if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
+ (Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
+ (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
+ {
+ return (AE_OK);
+ }
+
+ /* Pop the scope stack if necessary */
+
+ if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
+ {
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "%s: Popping scope for Op %p\n",
+ AcpiUtGetTypeName (OpInfo->ObjectType), Op));
+
+ (void) AcpiDsScopeStackPop (WalkState);
+ }
+
+ return (AE_OK);
+}
diff --git a/sys/contrib/dev/acpica/compiler/dtcompile.c b/sys/contrib/dev/acpica/compiler/dtcompile.c
index 210b70c..1b24af26 100644
--- a/sys/contrib/dev/acpica/compiler/dtcompile.c
+++ b/sys/contrib/dev/acpica/compiler/dtcompile.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -165,7 +165,7 @@ DtDoCompile (
/* Write the binary, then the optional hex file */
DtOutputBinary (Gbl_RootTable);
- LsDoHexOutput ();
+ HxDoHexOutput ();
DtWriteTableToListing ();
CleanupAndExit:
@@ -284,6 +284,7 @@ DtCompileDataTable (
char *Signature;
ACPI_TABLE_HEADER *AcpiTableHeader;
ACPI_STATUS Status;
+ DT_FIELD *RootField = *FieldList;
/* Verify that we at least have a table signature and save it */
@@ -354,7 +355,7 @@ DtCompileDataTable (
if (!TableData || Gbl_CompileGeneric)
{
DtCompileGeneric ((void **) FieldList);
- goto Out;
+ goto FinishHeader;
}
/* Dispatch to per-table compile */
@@ -391,7 +392,8 @@ DtCompileDataTable (
return (AE_ERROR);
}
-Out:
+FinishHeader:
+
/* Set the final table length and then the checksum */
DtSetTableLength ();
@@ -399,6 +401,8 @@ Out:
ACPI_TABLE_HEADER, Gbl_RootTable->Buffer);
DtSetTableChecksum (&AcpiTableHeader->Checksum);
+ DtDumpFieldList (RootField);
+ DtDumpSubtableList ();
return (AE_OK);
}
diff --git a/sys/contrib/dev/acpica/compiler/dtcompiler.h b/sys/contrib/dev/acpica/compiler/dtcompiler.h
index 22d1805..e9bdf05 100644
--- a/sys/contrib/dev/acpica/compiler/dtcompiler.h
+++ b/sys/contrib/dev/acpica/compiler/dtcompiler.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -113,6 +113,7 @@ typedef struct dt_subtable
UINT32 Length;
UINT32 TotalLength;
UINT32 SizeOfLengthField;
+ UINT16 Depth;
UINT8 Flags;
} DT_SUBTABLE;
@@ -168,6 +169,14 @@ DtOutputBinary (
DT_SUBTABLE *RootTable);
void
+DtDumpSubtableList (
+ void);
+
+void
+DtDumpFieldList (
+ DT_FIELD *Field);
+
+void
DtWriteFieldToListing (
UINT8 *Buffer,
DT_FIELD *Field,
@@ -387,6 +396,10 @@ DtCompileCpep (
void **PFieldList);
ACPI_STATUS
+DtCompileCsrt (
+ void **PFieldList);
+
+ACPI_STATUS
DtCompileDmar (
void **PFieldList);
@@ -481,6 +494,7 @@ extern const unsigned char TemplateBoot[];
extern const unsigned char TemplateBert[];
extern const unsigned char TemplateBgrt[];
extern const unsigned char TemplateCpep[];
+extern const unsigned char TemplateCsrt[];
extern const unsigned char TemplateDbgp[];
extern const unsigned char TemplateDmar[];
extern const unsigned char TemplateEcdt[];
@@ -507,6 +521,7 @@ extern const unsigned char TemplateSpcr[];
extern const unsigned char TemplateSpmi[];
extern const unsigned char TemplateSrat[];
extern const unsigned char TemplateTcpa[];
+extern const unsigned char TemplateTpm2[];
extern const unsigned char TemplateUefi[];
extern const unsigned char TemplateWaet[];
extern const unsigned char TemplateWdat[];
diff --git a/sys/contrib/dev/acpica/compiler/dtexpress.c b/sys/contrib/dev/acpica/compiler/dtexpress.c
index f0a1c8e..1c6ed3f 100644
--- a/sys/contrib/dev/acpica/compiler/dtexpress.c
+++ b/sys/contrib/dev/acpica/compiler/dtexpress.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/dtfield.c b/sys/contrib/dev/acpica/compiler/dtfield.c
index 6bfa649..11e443e 100644
--- a/sys/contrib/dev/acpica/compiler/dtfield.c
+++ b/sys/contrib/dev/acpica/compiler/dtfield.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/dtio.c b/sys/contrib/dev/acpica/compiler/dtio.c
index 5f70a19..f3d5359 100644
--- a/sys/contrib/dev/acpica/compiler/dtio.c
+++ b/sys/contrib/dev/acpica/compiler/dtio.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -79,6 +79,18 @@ DtDumpBuffer (
UINT32 Offset,
UINT32 Length);
+static void
+DtDumpSubtableInfo (
+ DT_SUBTABLE *Subtable,
+ void *Context,
+ void *ReturnValue);
+
+static void
+DtDumpSubtableTree (
+ DT_SUBTABLE *Subtable,
+ void *Context,
+ void *ReturnValue);
+
/* States for DtGetNextLine */
@@ -708,7 +720,6 @@ DtScanFile (
{
ACPI_STATUS Status;
UINT32 Offset;
- DT_FIELD *Next;
ACPI_FUNCTION_NAME (DtScanFile);
@@ -738,28 +749,7 @@ DtScanFile (
/* Dump the parse tree if debug enabled */
- if (Gbl_DebugFlag)
- {
- Next = Gbl_FieldList;
- DbgPrint (ASL_DEBUG_OUTPUT, "Tree: %32s %32s %8s %8s %8s %8s %8s %8s\n\n",
- "Name", "Value", "Line", "ByteOff", "NameCol", "Column", "TableOff", "Flags");
-
- while (Next)
- {
- DbgPrint (ASL_DEBUG_OUTPUT, "Field: %32.32s %32.32s %.8X %.8X %.8X %.8X %.8X %.8X\n",
- Next->Name,
- Next->Value,
- Next->Line,
- Next->ByteOffset,
- Next->NameColumn,
- Next->Column,
- Next->TableOffset,
- Next->Flags);
-
- Next = Next->Next;
- }
- }
-
+ DtDumpFieldList (Gbl_FieldList);
return (Gbl_FieldList);
}
@@ -913,6 +903,123 @@ DtDumpBuffer (
/******************************************************************************
*
+ * FUNCTION: DtDumpFieldList
+ *
+ * PARAMETERS: Field - Root field
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump the entire field list
+ *
+ *****************************************************************************/
+
+void
+DtDumpFieldList (
+ DT_FIELD *Field)
+{
+
+ if (!Gbl_DebugFlag || !Field)
+ {
+ return;
+ }
+
+ DbgPrint (ASL_DEBUG_OUTPUT, "\nField List:\n"
+ "LineNo ByteOff NameCol Column TableOff "
+ "Flags %32s : %s\n\n", "Name", "Value");
+ while (Field)
+ {
+ DbgPrint (ASL_DEBUG_OUTPUT,
+ "%.08X %.08X %.08X %.08X %.08X %.08X %32s : %s\n",
+ Field->Line, Field->ByteOffset, Field->NameColumn,
+ Field->Column, Field->TableOffset, Field->Flags,
+ Field->Name, Field->Value);
+
+ Field = Field->Next;
+ }
+
+ DbgPrint (ASL_DEBUG_OUTPUT, "\n\n");
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: DtDumpSubtableInfo, DtDumpSubtableTree
+ *
+ * PARAMETERS: DT_WALK_CALLBACK
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Info - dump a subtable tree entry with extra information.
+ * Tree - dump a subtable tree formatted by depth indentation.
+ *
+ *****************************************************************************/
+
+static void
+DtDumpSubtableInfo (
+ DT_SUBTABLE *Subtable,
+ void *Context,
+ void *ReturnValue)
+{
+
+ DbgPrint (ASL_DEBUG_OUTPUT,
+ "[%.04X] %.08X %.08X %.08X %.08X %.08X %p %p %p\n",
+ Subtable->Depth, Subtable->Length, Subtable->TotalLength,
+ Subtable->SizeOfLengthField, Subtable->Flags, Subtable,
+ Subtable->Parent, Subtable->Child, Subtable->Peer);
+}
+
+static void
+DtDumpSubtableTree (
+ DT_SUBTABLE *Subtable,
+ void *Context,
+ void *ReturnValue)
+{
+
+ DbgPrint (ASL_DEBUG_OUTPUT,
+ "[%.04X] %*s%08X (%.02X) - (%.02X)\n",
+ Subtable->Depth, (4 * Subtable->Depth), " ",
+ Subtable, Subtable->Length, Subtable->TotalLength);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: DtDumpSubtableList
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump the raw list of subtables with information, and also
+ * dump the subtable list in formatted tree format. Assists with
+ * the development of new table code.
+ *
+ *****************************************************************************/
+
+void
+DtDumpSubtableList (
+ void)
+{
+
+ if (!Gbl_DebugFlag || !Gbl_RootTable)
+ {
+ return;
+ }
+
+ DbgPrint (ASL_DEBUG_OUTPUT,
+ "Subtable Info:\n"
+ "Depth Length TotalLen LenSize Flags "
+ "This Parent Child Peer\n\n");
+ DtWalkTableTree (Gbl_RootTable, DtDumpSubtableInfo, NULL, NULL);
+
+ DbgPrint (ASL_DEBUG_OUTPUT,
+ "\nSubtable Tree: (Depth, Subtable, Length, TotalLength)\n\n");
+ DtWalkTableTree (Gbl_RootTable, DtDumpSubtableTree, NULL, NULL);
+}
+
+
+/******************************************************************************
+ *
* FUNCTION: DtWriteFieldToListing
*
* PARAMETERS: Buffer - Contains the compiled data
diff --git a/sys/contrib/dev/acpica/compiler/dtparser.l b/sys/contrib/dev/acpica/compiler/dtparser.l
index b6fd6ff..b0f6d6c 100644
--- a/sys/contrib/dev/acpica/compiler/dtparser.l
+++ b/sys/contrib/dev/acpica/compiler/dtparser.l
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/dtparser.y b/sys/contrib/dev/acpica/compiler/dtparser.y
index cf9fb98..47e74bd 100644
--- a/sys/contrib/dev/acpica/compiler/dtparser.y
+++ b/sys/contrib/dev/acpica/compiler/dtparser.y
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/dtsubtable.c b/sys/contrib/dev/acpica/compiler/dtsubtable.c
index 9eebe83..df22710 100644
--- a/sys/contrib/dev/acpica/compiler/dtsubtable.c
+++ b/sys/contrib/dev/acpica/compiler/dtsubtable.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -112,6 +112,7 @@ DtInsertSubtable (
Subtable->Peer = NULL;
Subtable->Parent = ParentTable;
+ Subtable->Depth = ParentTable->Depth + 1;
/* Link the new entry into the child list */
diff --git a/sys/contrib/dev/acpica/compiler/dttable.c b/sys/contrib/dev/acpica/compiler/dttable.c
index 8b58b76..1a8fd81 100644
--- a/sys/contrib/dev/acpica/compiler/dttable.c
+++ b/sys/contrib/dev/acpica/compiler/dttable.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -420,6 +420,94 @@ DtCompileCpep (
/******************************************************************************
*
+ * FUNCTION: DtCompileCsrt
+ *
+ * PARAMETERS: List - Current field list pointer
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Compile CSRT.
+ *
+ *****************************************************************************/
+
+ACPI_STATUS
+DtCompileCsrt (
+ void **List)
+{
+ ACPI_STATUS Status = AE_OK;
+ DT_SUBTABLE *Subtable;
+ DT_SUBTABLE *ParentTable;
+ DT_FIELD **PFieldList = (DT_FIELD **) List;
+ UINT32 DescriptorCount;
+ UINT32 GroupLength;
+
+
+ /* Sub-tables (Resource Groups) */
+
+ while (*PFieldList)
+ {
+ /* Resource group subtable */
+
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt0,
+ &Subtable, TRUE);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Compute the number of resource descriptors */
+
+ GroupLength =
+ (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
+ Subtable->Buffer))->Length -
+ (ACPI_CAST_PTR (ACPI_CSRT_GROUP,
+ Subtable->Buffer))->SharedInfoLength -
+ sizeof (ACPI_CSRT_GROUP);
+
+ DescriptorCount = (GroupLength /
+ sizeof (ACPI_CSRT_DESCRIPTOR));
+
+ ParentTable = DtPeekSubtable ();
+ DtInsertSubtable (ParentTable, Subtable);
+ DtPushSubtable (Subtable);
+
+ /* Shared info subtable (One per resource group) */
+
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt1,
+ &Subtable, TRUE);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ ParentTable = DtPeekSubtable ();
+ DtInsertSubtable (ParentTable, Subtable);
+
+ /* Sub-Subtables (Resource Descriptors) */
+
+ while (*PFieldList && DescriptorCount)
+ {
+ Status = DtCompileTable (PFieldList, AcpiDmTableInfoCsrt2,
+ &Subtable, TRUE);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ ParentTable = DtPeekSubtable ();
+ DtInsertSubtable (ParentTable, Subtable);
+ DescriptorCount--;
+ }
+
+ DtPopSubtable ();
+ }
+
+ return (Status);
+}
+
+
+/******************************************************************************
+ *
* FUNCTION: DtCompileDmar
*
* PARAMETERS: List - Current field list pointer
diff --git a/sys/contrib/dev/acpica/compiler/dttemplate.c b/sys/contrib/dev/acpica/compiler/dttemplate.c
index fda712b..c0ff98b 100644
--- a/sys/contrib/dev/acpica/compiler/dttemplate.c
+++ b/sys/contrib/dev/acpica/compiler/dttemplate.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/dttemplate.h b/sys/contrib/dev/acpica/compiler/dttemplate.h
index 1a817cd..07d1f91 100644
--- a/sys/contrib/dev/acpica/compiler/dttemplate.h
+++ b/sys/contrib/dev/acpica/compiler/dttemplate.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -128,6 +128,52 @@ const unsigned char TemplateCpep[] =
0x00,0x00,0x00,0x00 /* 00000030 "...." */
};
+const unsigned char TemplateCsrt[] =
+{
+ 0x43,0x53,0x52,0x54,0x4C,0x01,0x00,0x00, /* 00000000 "CSRTL..." */
+ 0x01,0x0D,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 "..INTEL " */
+ 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */
+ 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
+ 0x14,0x11,0x12,0x20,0x88,0x00,0x00,0x00, /* 00000020 "... ...." */
+ 0x49,0x4E,0x54,0x4C,0x00,0x00,0x00,0x00, /* 00000028 "INTL...." */
+ 0x60,0x9C,0x00,0x00,0x02,0x00,0x00,0x00, /* 00000030 "`......." */
+ 0x1C,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 00000038 "........" */
+ 0x00,0x00,0xA0,0xB3,0x00,0x00,0x00,0x00, /* 00000040 "........" */
+ 0x2A,0x00,0x00,0x00,0x02,0x00,0x06,0x20, /* 00000048 "*...... " */
+ 0x00,0x00,0x10,0x00,0xFF,0x0F,0x00,0x00, /* 00000050 "........" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x01,0x00, /* 00000058 "........" */
+ 0x53,0x50,0x49,0x20,0x0C,0x00,0x00,0x00, /* 00000060 "SPI ...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x30, /* 00000068 "....CHA0" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 00000070 "........" */
+ 0x43,0x48,0x41,0x31,0x0C,0x00,0x00,0x00, /* 00000078 "CHA1...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x32, /* 00000080 "....CHA2" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 00000088 "........" */
+ 0x43,0x48,0x41,0x33,0x0C,0x00,0x00,0x00, /* 00000090 "CHA3...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x34, /* 00000098 "....CHA4" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 000000A0 "........" */
+ 0x43,0x48,0x41,0x35,0xA0,0x00,0x00,0x00, /* 000000A8 "CHA5...." */
+ 0x49,0x4E,0x54,0x4C,0x00,0x00,0x00,0x00, /* 000000B0 "INTL...." */
+ 0x60,0x9C,0x00,0x00,0x03,0x00,0x00,0x00, /* 000000B8 "`......." */
+ 0x1C,0x00,0x00,0x00,0x01,0x00,0x00,0x00, /* 000000C0 "........" */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000C8 "........" */
+ 0x2B,0x00,0x00,0x00,0x02,0x00,0x08,0x20, /* 000000D0 "+...... " */
+ 0x10,0x00,0x10,0x00,0xFF,0x0F,0x00,0x00, /* 000000D8 "........" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x01,0x00, /* 000000E0 "........" */
+ 0x49,0x32,0x43,0x20,0x0C,0x00,0x00,0x00, /* 000000E8 "I2C ...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x30, /* 000000F0 "....CHA0" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 000000F8 "........" */
+ 0x43,0x48,0x41,0x31,0x0C,0x00,0x00,0x00, /* 00000100 "CHA1...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x32, /* 00000108 "....CHA2" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 00000110 "........" */
+ 0x43,0x48,0x41,0x33,0x0C,0x00,0x00,0x00, /* 00000118 "CHA3...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x34, /* 00000120 "....CHA4" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 00000128 "........" */
+ 0x43,0x48,0x41,0x35,0x0C,0x00,0x00,0x00, /* 00000130 "CHA5...." */
+ 0x03,0x00,0x00,0x00,0x43,0x48,0x41,0x36, /* 00000138 "....CHA6" */
+ 0x0C,0x00,0x00,0x00,0x03,0x00,0x00,0x00, /* 00000140 "........" */
+ 0x43,0x48,0x41,0x37 /* 00000148 "CHA7" */
+};
+
const unsigned char TemplateDbgp[] =
{
0x44,0x42,0x47,0x50,0x34,0x00,0x00,0x00, /* 00000000 "DBGP4..." */
@@ -825,6 +871,17 @@ const unsigned char TemplateTcpa[] =
0x00,0x00 /* 00000030 ".." */
};
+const unsigned char TemplateTpm2[] =
+{
+ 0x54,0x50,0x4D,0x32,0x34,0x00,0x00,0x00, /* 00000000 "TPM24..." */
+ 0x03,0x42,0x49,0x4E,0x54,0x45,0x4C,0x20, /* 00000008 ".BINTEL " */
+ 0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45, /* 00000010 "TEMPLATE" */
+ 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
+ 0x14,0x11,0x12,0x20,0x00,0x00,0x00,0x00, /* 00000020 "... ...." */
+ 0x77,0x66,0x55,0x44,0x33,0x22,0x11,0x00, /* 00000028 "wfUD3".." */
+ 0x01,0x00,0x00,0x00 /* 00000030 "...." */
+};
+
const unsigned char TemplateUefi[] =
{
0x55,0x45,0x46,0x49,0x36,0x00,0x00,0x00, /* 00000000 "UEFI6..." */
diff --git a/sys/contrib/dev/acpica/compiler/dtutils.c b/sys/contrib/dev/acpica/compiler/dtutils.c
index f87fa20..80b0e44 100644
--- a/sys/contrib/dev/acpica/compiler/dtutils.c
+++ b/sys/contrib/dev/acpica/compiler/dtutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/preprocess.h b/sys/contrib/dev/acpica/compiler/preprocess.h
index f97434f..6decc00 100644
--- a/sys/contrib/dev/acpica/compiler/preprocess.h
+++ b/sys/contrib/dev/acpica/compiler/preprocess.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prexpress.c b/sys/contrib/dev/acpica/compiler/prexpress.c
index c0dccd9..c0aa565 100644
--- a/sys/contrib/dev/acpica/compiler/prexpress.c
+++ b/sys/contrib/dev/acpica/compiler/prexpress.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prmacros.c b/sys/contrib/dev/acpica/compiler/prmacros.c
index 82663a5..d76de8b 100644
--- a/sys/contrib/dev/acpica/compiler/prmacros.c
+++ b/sys/contrib/dev/acpica/compiler/prmacros.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prparser.l b/sys/contrib/dev/acpica/compiler/prparser.l
index 34daa48..b580d57 100644
--- a/sys/contrib/dev/acpica/compiler/prparser.l
+++ b/sys/contrib/dev/acpica/compiler/prparser.l
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prparser.y b/sys/contrib/dev/acpica/compiler/prparser.y
index 81cede3..391ad3f 100644
--- a/sys/contrib/dev/acpica/compiler/prparser.y
+++ b/sys/contrib/dev/acpica/compiler/prparser.y
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prscan.c b/sys/contrib/dev/acpica/compiler/prscan.c
index 233e45a..0d44d6a 100644
--- a/sys/contrib/dev/acpica/compiler/prscan.c
+++ b/sys/contrib/dev/acpica/compiler/prscan.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/compiler/prutils.c b/sys/contrib/dev/acpica/compiler/prutils.c
index c8faeb6..0dbf307 100644
--- a/sys/contrib/dev/acpica/compiler/prutils.c
+++ b/sys/contrib/dev/acpica/compiler/prutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/debugger/dbcmds.c b/sys/contrib/dev/acpica/components/debugger/dbcmds.c
index 5120fcb..64c299c 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbcmds.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbcmds.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -82,17 +82,21 @@ AcpiDbDeviceResources (
void *Context,
void **ReturnValue);
+static void
+AcpiDbDoOneSleepState (
+ UINT8 SleepState);
+
/*******************************************************************************
*
* FUNCTION: AcpiDbConvertToNode
*
- * PARAMETERS: InString - String to convert
+ * PARAMETERS: InString - String to convert
*
* RETURN: Pointer to a NS node
*
* DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or
- * alpha strings.
+ * alphanumeric strings.
*
******************************************************************************/
@@ -126,9 +130,9 @@ AcpiDbConvertToNode (
}
else
{
- /* Alpha argument */
- /* The parameter is a name string that must be resolved to a
- * Named obj
+ /*
+ * Alpha argument: The parameter is a name string that must be
+ * resolved to a Namespace object.
*/
Node = AcpiDbLocalNsLookup (InString);
if (!Node)
@@ -145,11 +149,12 @@ AcpiDbConvertToNode (
*
* FUNCTION: AcpiDbSleep
*
- * PARAMETERS: ObjectArg - Desired sleep state (0-5)
+ * PARAMETERS: ObjectArg - Desired sleep state (0-5). NULL means
+ * invoke all possible sleep states.
*
* RETURN: Status
*
- * DESCRIPTION: Simulate a sleep/wake sequence
+ * DESCRIPTION: Simulate sleep/wake sequences
*
******************************************************************************/
@@ -157,50 +162,124 @@ ACPI_STATUS
AcpiDbSleep (
char *ObjectArg)
{
- ACPI_STATUS Status;
UINT8 SleepState;
+ UINT32 i;
ACPI_FUNCTION_TRACE (AcpiDbSleep);
+ /* Null input (no arguments) means to invoke all sleep states */
+
+ if (!ObjectArg)
+ {
+ AcpiOsPrintf ("Invoking all possible sleep states, 0-%d\n",
+ ACPI_S_STATES_MAX);
+
+ for (i = 0; i <= ACPI_S_STATES_MAX; i++)
+ {
+ AcpiDbDoOneSleepState ((UINT8) i);
+ }
+
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Convert argument to binary and invoke the sleep state */
+
SleepState = (UINT8) ACPI_STRTOUL (ObjectArg, NULL, 0);
+ AcpiDbDoOneSleepState (SleepState);
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbDoOneSleepState
+ *
+ * PARAMETERS: SleepState - Desired sleep state (0-5)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Simulate a sleep/wake sequence
+ *
+ ******************************************************************************/
+
+static void
+AcpiDbDoOneSleepState (
+ UINT8 SleepState)
+{
+ ACPI_STATUS Status;
+ UINT8 SleepTypeA;
+ UINT8 SleepTypeB;
+
+
+ /* Validate parameter */
+
+ if (SleepState > ACPI_S_STATES_MAX)
+ {
+ AcpiOsPrintf ("Sleep state %d out of range (%d max)\n",
+ SleepState, ACPI_S_STATES_MAX);
+ return;
+ }
+
+ AcpiOsPrintf ("\n---- Invoking sleep state S%d (%s):\n",
+ SleepState, AcpiGbl_SleepStateNames[SleepState]);
+
+ /* Get the values for the sleep type registers (for display only) */
+
+ Status = AcpiGetSleepTypeData (SleepState, &SleepTypeA, &SleepTypeB);
+ if (ACPI_FAILURE (Status))
+ {
+ AcpiOsPrintf ("Could not evaluate [%s] method, %s\n",
+ AcpiGbl_SleepStateNames[SleepState],
+ AcpiFormatException (Status));
+ return;
+ }
- AcpiOsPrintf ("**** Prepare to sleep ****\n");
+ AcpiOsPrintf (
+ "Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n",
+ SleepState, SleepTypeA, SleepTypeB);
+
+ /* Invoke the various sleep/wake interfaces */
+
+ AcpiOsPrintf ("**** Sleep: Prepare to sleep (S%d) ****\n",
+ SleepState);
Status = AcpiEnterSleepStatePrep (SleepState);
if (ACPI_FAILURE (Status))
{
goto ErrorExit;
}
- AcpiOsPrintf ("**** Going to sleep ****\n");
+ AcpiOsPrintf ("**** Sleep: Going to sleep (S%d) ****\n",
+ SleepState);
Status = AcpiEnterSleepState (SleepState);
if (ACPI_FAILURE (Status))
{
goto ErrorExit;
}
- AcpiOsPrintf ("**** Prepare to return from sleep ****\n");
+ AcpiOsPrintf ("**** Wake: Prepare to return from sleep (S%d) ****\n",
+ SleepState);
Status = AcpiLeaveSleepStatePrep (SleepState);
if (ACPI_FAILURE (Status))
{
goto ErrorExit;
}
- AcpiOsPrintf ("**** Returning from sleep ****\n");
+ AcpiOsPrintf ("**** Wake: Return from sleep (S%d) ****\n",
+ SleepState);
Status = AcpiLeaveSleepState (SleepState);
if (ACPI_FAILURE (Status))
{
goto ErrorExit;
}
- return_ACPI_STATUS (Status);
+ return;
ErrorExit:
-
- ACPI_EXCEPTION ((AE_INFO, Status, "During sleep test"));
- return_ACPI_STATUS (Status);
+ ACPI_EXCEPTION ((AE_INFO, Status, "During invocation of sleep state S%d",
+ SleepState));
}
@@ -236,7 +315,7 @@ AcpiDbDisplayLocks (
*
* FUNCTION: AcpiDbDisplayTableInfo
*
- * PARAMETERS: TableArg - String with name of table to be displayed
+ * PARAMETERS: TableArg - Name of table to be displayed
*
* RETURN: None
*
@@ -377,8 +456,8 @@ AcpiDbUnloadAcpiTable (
*
* FUNCTION: AcpiDbSendNotify
*
- * PARAMETERS: Name - Name of ACPI object to send the notify to
- * Value - Value of the notify to send.
+ * PARAMETERS: Name - Name of ACPI object where to send notify
+ * Value - Value of the notify to send.
*
* RETURN: None
*
@@ -416,7 +495,8 @@ AcpiDbSendNotify (
}
else
{
- AcpiOsPrintf ("Named object [%4.4s] Type %s, must be Device/Thermal/Processor type\n",
+ AcpiOsPrintf (
+ "Named object [%4.4s] Type %s, must be Device/Thermal/Processor type\n",
AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type));
}
}
@@ -453,7 +533,6 @@ AcpiDbDisplayInterfaces (
ACPI_WAIT_FOREVER);
NextInterface = AcpiGbl_SupportedInterfaces;
-
while (NextInterface)
{
if (!(NextInterface->Flags & ACPI_OSI_INVALID))
@@ -518,7 +597,7 @@ AcpiDbDisplayInterfaces (
*
* FUNCTION: AcpiDbDisplayTemplate
*
- * PARAMETERS: BufferArg - Buffer name or addrss
+ * PARAMETERS: BufferArg - Buffer name or address
*
* RETURN: None
*
@@ -532,7 +611,7 @@ AcpiDbDisplayTemplate (
{
ACPI_NAMESPACE_NODE *Node;
ACPI_STATUS Status;
- ACPI_BUFFER ReturnObj;
+ ACPI_BUFFER ReturnBuffer;
/* Translate BufferArg to an Named object */
@@ -553,12 +632,12 @@ AcpiDbDisplayTemplate (
return;
}
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
/* Attempt to convert the raw buffer to a resource list */
- Status = AcpiRsCreateResourceList (Node->Object, &ReturnObj);
+ Status = AcpiRsCreateResourceList (Node->Object, &ReturnBuffer);
AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
AcpiDbgLevel |= ACPI_LV_RESOURCES;
@@ -573,7 +652,7 @@ AcpiDbDisplayTemplate (
/* Now we can dump the resource list */
AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE,
- ReturnObj.Pointer));
+ ReturnBuffer.Pointer));
DumpBuffer:
AcpiOsPrintf ("\nRaw data buffer:\n");
@@ -666,7 +745,8 @@ AcpiDmCompareAmlResources (
{
if (Aml1[i] != Aml2[i])
{
- AcpiOsPrintf ("Mismatch at byte offset %.2X: is %2.2X, should be %2.2X\n",
+ AcpiOsPrintf (
+ "Mismatch at byte offset %.2X: is %2.2X, should be %2.2X\n",
i, Aml2[i], Aml1[i]);
}
}
@@ -693,8 +773,8 @@ AcpiDmCompareAmlResources (
*
* FUNCTION: AcpiDmTestResourceConversion
*
- * PARAMETERS: Node - Parent device node
- * Name - resource method name (_CRS)
+ * PARAMETERS: Node - Parent device node
+ * Name - resource method name (_CRS)
*
* RETURN: Status
*
@@ -709,8 +789,8 @@ AcpiDmTestResourceConversion (
char *Name)
{
ACPI_STATUS Status;
- ACPI_BUFFER ReturnObj;
- ACPI_BUFFER ResourceObj;
+ ACPI_BUFFER ReturnBuffer;
+ ACPI_BUFFER ResourceBuffer;
ACPI_BUFFER NewAml;
ACPI_OBJECT *OriginalAml;
@@ -718,12 +798,12 @@ AcpiDmTestResourceConversion (
AcpiOsPrintf ("Resource Conversion Comparison:\n");
NewAml.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- ReturnObj.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- ResourceObj.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ ReturnBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ ResourceBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
/* Get the original _CRS AML resource template */
- Status = AcpiEvaluateObject (Node, Name, NULL, &ReturnObj);
+ Status = AcpiEvaluateObject (Node, Name, NULL, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("Could not obtain %s: %s\n",
@@ -733,7 +813,7 @@ AcpiDmTestResourceConversion (
/* Get the AML resource template, converted to internal resource structs */
- Status = AcpiGetCurrentResources (Node, &ResourceObj);
+ Status = AcpiGetCurrentResources (Node, &ResourceBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n",
@@ -743,7 +823,7 @@ AcpiDmTestResourceConversion (
/* Convert internal resource list to external AML resource template */
- Status = AcpiRsCreateAmlResources (ResourceObj.Pointer, &NewAml);
+ Status = AcpiRsCreateAmlResources (ResourceBuffer.Pointer, &NewAml);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiRsCreateAmlResources failed: %s\n",
@@ -753,7 +833,7 @@ AcpiDmTestResourceConversion (
/* Compare original AML to the newly created AML resource list */
- OriginalAml = ReturnObj.Pointer;
+ OriginalAml = ReturnBuffer.Pointer;
AcpiDmCompareAmlResources (
OriginalAml->Buffer.Pointer, (ACPI_RSDESC_SIZE) OriginalAml->Buffer.Length,
@@ -763,9 +843,9 @@ AcpiDmTestResourceConversion (
ACPI_FREE (NewAml.Pointer);
Exit2:
- ACPI_FREE (ResourceObj.Pointer);
+ ACPI_FREE (ResourceBuffer.Pointer);
Exit1:
- ACPI_FREE (ReturnObj.Pointer);
+ ACPI_FREE (ReturnBuffer.Pointer);
return (Status);
}
@@ -778,7 +858,8 @@ Exit1:
*
* RETURN: Status
*
- * DESCRIPTION: Simple callback to exercise AcpiWalkResources
+ * DESCRIPTION: Simple callback to exercise AcpiWalkResources and
+ * AcpiWalkResourceBuffer.
*
******************************************************************************/
@@ -817,7 +898,7 @@ AcpiDbDeviceResources (
ACPI_NAMESPACE_NODE *PrsNode = NULL;
ACPI_NAMESPACE_NODE *AeiNode = NULL;
char *ParentPath;
- ACPI_BUFFER ReturnObj;
+ ACPI_BUFFER ReturnBuffer;
ACPI_STATUS Status;
@@ -843,8 +924,8 @@ AcpiDbDeviceResources (
/* Prepare for a return object of arbitrary size */
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
/* _PRT */
@@ -853,7 +934,7 @@ AcpiDbDeviceResources (
{
AcpiOsPrintf ("Evaluating _PRT\n");
- Status = AcpiEvaluateObject (PrtNode, NULL, NULL, &ReturnObj);
+ Status = AcpiEvaluateObject (PrtNode, NULL, NULL, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("Could not evaluate _PRT: %s\n",
@@ -861,10 +942,10 @@ AcpiDbDeviceResources (
goto GetCrs;
}
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiGetIrqRoutingTable (Node, &ReturnObj);
+ Status = AcpiGetIrqRoutingTable (Node, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("GetIrqRoutingTable failed: %s\n",
@@ -883,10 +964,10 @@ GetCrs:
{
AcpiOsPrintf ("Evaluating _CRS\n");
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiEvaluateObject (CrsNode, NULL, NULL, &ReturnObj);
+ Status = AcpiEvaluateObject (CrsNode, NULL, NULL, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("Could not evaluate _CRS: %s\n",
@@ -894,7 +975,7 @@ GetCrs:
goto GetPrs;
}
- /* This code is here to exercise the AcpiWalkResources interface */
+ /* This code exercises the AcpiWalkResources interface */
Status = AcpiWalkResources (Node, METHOD_NAME__CRS,
AcpiDbResourceCallback, NULL);
@@ -905,12 +986,12 @@ GetCrs:
goto GetPrs;
}
- /* Get the _CRS resource list */
+ /* Get the _CRS resource list (test ALLOCATE buffer) */
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = NULL;
+ ReturnBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- Status = AcpiGetCurrentResources (Node, &ReturnObj);
+ Status = AcpiGetCurrentResources (Node, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n",
@@ -918,26 +999,41 @@ GetCrs:
goto GetPrs;
}
+ /* This code exercises the AcpiWalkResourceBuffer interface */
+
+ Status = AcpiWalkResourceBuffer (&ReturnBuffer,
+ AcpiDbResourceCallback, NULL);
+ if (ACPI_FAILURE (Status))
+ {
+ AcpiOsPrintf ("AcpiWalkResourceBuffer failed: %s\n",
+ AcpiFormatException (Status));
+ goto EndCrs;
+ }
+
/* Dump the _CRS resource list */
AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE,
- ReturnObj.Pointer));
+ ReturnBuffer.Pointer));
/*
- * Perform comparison of original AML to newly created AML. This tests both
- * the AML->Resource conversion and the Resource->Aml conversion.
+ * Perform comparison of original AML to newly created AML. This
+ * tests both the AML->Resource conversion and the Resource->AML
+ * conversion.
*/
- Status = AcpiDmTestResourceConversion (Node, METHOD_NAME__CRS);
+ (void) AcpiDmTestResourceConversion (Node, METHOD_NAME__CRS);
/* Execute _SRS with the resource list */
- Status = AcpiSetCurrentResources (Node, &ReturnObj);
+ Status = AcpiSetCurrentResources (Node, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiSetCurrentResources failed: %s\n",
AcpiFormatException (Status));
- goto GetPrs;
+ goto EndCrs;
}
+
+EndCrs:
+ ACPI_FREE_BUFFER (ReturnBuffer);
}
@@ -948,10 +1044,10 @@ GetPrs:
{
AcpiOsPrintf ("Evaluating _PRS\n");
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiEvaluateObject (PrsNode, NULL, NULL, &ReturnObj);
+ Status = AcpiEvaluateObject (PrsNode, NULL, NULL, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("Could not evaluate _PRS: %s\n",
@@ -959,10 +1055,10 @@ GetPrs:
goto GetAei;
}
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiGetPossibleResources (Node, &ReturnObj);
+ Status = AcpiGetPossibleResources (Node, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiGetPossibleResources failed: %s\n",
@@ -981,10 +1077,10 @@ GetAei:
{
AcpiOsPrintf ("Evaluating _AEI\n");
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiEvaluateObject (AeiNode, NULL, NULL, &ReturnObj);
+ Status = AcpiEvaluateObject (AeiNode, NULL, NULL, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("Could not evaluate _AEI: %s\n",
@@ -992,10 +1088,10 @@ GetAei:
goto Cleanup;
}
- ReturnObj.Pointer = AcpiGbl_DbBuffer;
- ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE;
+ ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
+ ReturnBuffer.Length = ACPI_DEBUG_BUFFER_SIZE;
- Status = AcpiGetEventResources (Node, &ReturnObj);
+ Status = AcpiGetEventResources (Node, &ReturnBuffer);
if (ACPI_FAILURE (Status))
{
AcpiOsPrintf ("AcpiGetEventResources failed: %s\n",
@@ -1017,8 +1113,9 @@ Cleanup:
*
* FUNCTION: AcpiDbDisplayResources
*
- * PARAMETERS: ObjectArg - String object name or object pointer.
- * "*" means "display resources for all devices"
+ * PARAMETERS: ObjectArg - String object name or object pointer.
+ * "*" means "display resources for all
+ * devices"
*
* RETURN: None
*
@@ -1071,13 +1168,13 @@ AcpiDbDisplayResources (
*
* FUNCTION: AcpiDbGenerateGpe
*
- * PARAMETERS: GpeArg - Raw GPE number, ascii string
- * BlockArg - GPE block number, ascii string
- * 0 or 1 for FADT GPE blocks
+ * PARAMETERS: GpeArg - Raw GPE number, ascii string
+ * BlockArg - GPE block number, ascii string
+ * 0 or 1 for FADT GPE blocks
*
* RETURN: None
*
- * DESCRIPTION: Generate a GPE
+ * DESCRIPTION: Simulate firing of a GPE
*
******************************************************************************/
diff --git a/sys/contrib/dev/acpica/components/debugger/dbconvert.c b/sys/contrib/dev/acpica/components/debugger/dbconvert.c
new file mode 100644
index 0000000..f781f29
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/debugger/dbconvert.c
@@ -0,0 +1,525 @@
+/*******************************************************************************
+ *
+ * Module Name: dbconvert - debugger miscellaneous conversion routines
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acdebug.h>
+
+#ifdef ACPI_DEBUGGER
+
+#define _COMPONENT ACPI_CA_DEBUGGER
+ ACPI_MODULE_NAME ("dbconvert")
+
+
+#define DB_DEFAULT_PKG_ELEMENTS 33
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbHexCharToValue
+ *
+ * PARAMETERS: HexChar - Ascii Hex digit, 0-9|a-f|A-F
+ * ReturnValue - Where the converted value is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a single hex character to a 4-bit number (0-16).
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiDbHexCharToValue (
+ int HexChar,
+ UINT8 *ReturnValue)
+{
+ UINT8 Value;
+
+
+ /* Digit must be ascii [0-9a-fA-F] */
+
+ if (!ACPI_IS_XDIGIT (HexChar))
+ {
+ return (AE_BAD_HEX_CONSTANT);
+ }
+
+ if (HexChar <= 0x39)
+ {
+ Value = (UINT8) (HexChar - 0x30);
+ }
+ else
+ {
+ Value = (UINT8) (ACPI_TOUPPER (HexChar) - 0x37);
+ }
+
+ *ReturnValue = Value;
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbHexByteToBinary
+ *
+ * PARAMETERS: HexByte - Double hex digit (0x00 - 0xFF) in format:
+ * HiByte then LoByte.
+ * ReturnValue - Where the converted value is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255).
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiDbHexByteToBinary (
+ char *HexByte,
+ UINT8 *ReturnValue)
+{
+ UINT8 Local0;
+ UINT8 Local1;
+ ACPI_STATUS Status;
+
+
+ /* High byte */
+
+ Status = AcpiDbHexCharToValue (HexByte[0], &Local0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Low byte */
+
+ Status = AcpiDbHexCharToValue (HexByte[1], &Local1);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ *ReturnValue = (UINT8) ((Local0 << 4) | Local1);
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbConvertToBuffer
+ *
+ * PARAMETERS: String - Input string to be converted
+ * Object - Where the buffer object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a string to a buffer object. String is treated a list
+ * of buffer elements, each separated by a space or comma.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiDbConvertToBuffer (
+ char *String,
+ ACPI_OBJECT *Object)
+{
+ UINT32 i;
+ UINT32 j;
+ UINT32 Length;
+ UINT8 *Buffer;
+ ACPI_STATUS Status;
+
+
+ /* Generate the final buffer length */
+
+ for (i = 0, Length = 0; String[i];)
+ {
+ i+=2;
+ Length++;
+
+ while (String[i] &&
+ ((String[i] == ',') || (String[i] == ' ')))
+ {
+ i++;
+ }
+ }
+
+ Buffer = ACPI_ALLOCATE (Length);
+ if (!Buffer)
+ {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Convert the command line bytes to the buffer */
+
+ for (i = 0, j = 0; String[i];)
+ {
+ Status = AcpiDbHexByteToBinary (&String[i], &Buffer[j]);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_FREE (Buffer);
+ return (Status);
+ }
+
+ j++;
+ i+=2;
+ while (String[i] &&
+ ((String[i] == ',') || (String[i] == ' ')))
+ {
+ i++;
+ }
+ }
+
+ Object->Type = ACPI_TYPE_BUFFER;
+ Object->Buffer.Pointer = Buffer;
+ Object->Buffer.Length = Length;
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbConvertToPackage
+ *
+ * PARAMETERS: String - Input string to be converted
+ * Object - Where the package object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a string to a package object. Handles nested packages
+ * via recursion with AcpiDbConvertToObject.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiDbConvertToPackage (
+ char *String,
+ ACPI_OBJECT *Object)
+{
+ char *This;
+ char *Next;
+ UINT32 i;
+ ACPI_OBJECT_TYPE Type;
+ ACPI_OBJECT *Elements;
+ ACPI_STATUS Status;
+
+
+ Elements = ACPI_ALLOCATE_ZEROED (
+ DB_DEFAULT_PKG_ELEMENTS * sizeof (ACPI_OBJECT));
+
+ This = String;
+ for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++)
+ {
+ This = AcpiDbGetNextToken (This, &Next, &Type);
+ if (!This)
+ {
+ break;
+ }
+
+ /* Recursive call to convert each package element */
+
+ Status = AcpiDbConvertToObject (Type, This, &Elements[i]);
+ if (ACPI_FAILURE (Status))
+ {
+ AcpiDbDeleteObjects (i + 1, Elements);
+ ACPI_FREE (Elements);
+ return (Status);
+ }
+
+ This = Next;
+ }
+
+ Object->Type = ACPI_TYPE_PACKAGE;
+ Object->Package.Count = i;
+ Object->Package.Elements = Elements;
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbConvertToObject
+ *
+ * PARAMETERS: Type - Object type as determined by parser
+ * String - Input string to be converted
+ * Object - Where the new object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a typed and tokenized string to an ACPI_OBJECT. Typing:
+ * 1) String objects were surrounded by quotes.
+ * 2) Buffer objects were surrounded by parentheses.
+ * 3) Package objects were surrounded by brackets "[]".
+ * 4) All standalone tokens are treated as integers.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiDbConvertToObject (
+ ACPI_OBJECT_TYPE Type,
+ char *String,
+ ACPI_OBJECT *Object)
+{
+ ACPI_STATUS Status = AE_OK;
+
+
+ switch (Type)
+ {
+ case ACPI_TYPE_STRING:
+ Object->Type = ACPI_TYPE_STRING;
+ Object->String.Pointer = String;
+ Object->String.Length = (UINT32) ACPI_STRLEN (String);
+ break;
+
+ case ACPI_TYPE_BUFFER:
+ Status = AcpiDbConvertToBuffer (String, Object);
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+ Status = AcpiDbConvertToPackage (String, Object);
+ break;
+
+ default:
+ Object->Type = ACPI_TYPE_INTEGER;
+ Status = AcpiUtStrtoul64 (String, 16, &Object->Integer.Value);
+ break;
+ }
+
+ return (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbEncodePldBuffer
+ *
+ * PARAMETERS: PldInfo - _PLD buffer struct (Using local struct)
+ *
+ * RETURN: Encode _PLD buffer suitable for return value from _PLD
+ *
+ * DESCRIPTION: Bit-packs a _PLD buffer struct. Used to test the _PLD macros
+ *
+ ******************************************************************************/
+
+UINT8 *
+AcpiDbEncodePldBuffer (
+ ACPI_PLD_INFO *PldInfo)
+{
+ UINT32 *Buffer;
+ UINT32 Dword;
+
+
+ Buffer = ACPI_ALLOCATE_ZEROED (ACPI_PLD_BUFFER_SIZE);
+ if (!Buffer)
+ {
+ return (NULL);
+ }
+
+ /* First 32 bits */
+
+ Dword = 0;
+ ACPI_PLD_SET_REVISION (&Dword, PldInfo->Revision);
+ ACPI_PLD_SET_IGNORE_COLOR (&Dword, PldInfo->IgnoreColor);
+ ACPI_PLD_SET_COLOR (&Dword, PldInfo->Color);
+ ACPI_MOVE_32_TO_32 (&Buffer[0], &Dword);
+
+ /* Second 32 bits */
+
+ Dword = 0;
+ ACPI_PLD_SET_WIDTH (&Dword, PldInfo->Width);
+ ACPI_PLD_SET_HEIGHT (&Dword, PldInfo->Height);
+ ACPI_MOVE_32_TO_32 (&Buffer[1], &Dword);
+
+ /* Third 32 bits */
+
+ Dword = 0;
+ ACPI_PLD_SET_USER_VISIBLE (&Dword, PldInfo->UserVisible);
+ ACPI_PLD_SET_DOCK (&Dword, PldInfo->Dock);
+ ACPI_PLD_SET_LID (&Dword, PldInfo->Lid);
+ ACPI_PLD_SET_PANEL (&Dword, PldInfo->Panel);
+ ACPI_PLD_SET_VERTICAL (&Dword, PldInfo->VerticalPosition);
+ ACPI_PLD_SET_HORIZONTAL (&Dword, PldInfo->HorizontalPosition);
+ ACPI_PLD_SET_SHAPE (&Dword, PldInfo->Shape);
+ ACPI_PLD_SET_ORIENTATION (&Dword, PldInfo->GroupOrientation);
+ ACPI_PLD_SET_TOKEN (&Dword, PldInfo->GroupToken);
+ ACPI_PLD_SET_POSITION (&Dword, PldInfo->GroupPosition);
+ ACPI_PLD_SET_BAY (&Dword, PldInfo->Bay);
+ ACPI_MOVE_32_TO_32 (&Buffer[2], &Dword);
+
+ /* Fourth 32 bits */
+
+ Dword = 0;
+ ACPI_PLD_SET_EJECTABLE (&Dword, PldInfo->Ejectable);
+ ACPI_PLD_SET_OSPM_EJECT (&Dword, PldInfo->OspmEjectRequired);
+ ACPI_PLD_SET_CABINET (&Dword, PldInfo->CabinetNumber);
+ ACPI_PLD_SET_CARD_CAGE (&Dword, PldInfo->CardCageNumber);
+ ACPI_PLD_SET_REFERENCE (&Dword, PldInfo->Reference);
+ ACPI_PLD_SET_ROTATION (&Dword, PldInfo->Rotation);
+ ACPI_PLD_SET_ORDER (&Dword, PldInfo->Order);
+ ACPI_MOVE_32_TO_32 (&Buffer[3], &Dword);
+
+ if (PldInfo->Revision >= 2)
+ {
+ /* Fifth 32 bits */
+
+ Dword = 0;
+ ACPI_PLD_SET_VERT_OFFSET (&Dword, PldInfo->VerticalOffset);
+ ACPI_PLD_SET_HORIZ_OFFSET (&Dword, PldInfo->HorizontalOffset);
+ ACPI_MOVE_32_TO_32 (&Buffer[4], &Dword);
+ }
+
+ return (ACPI_CAST_PTR (UINT8, Buffer));
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbDumpPldBuffer
+ *
+ * PARAMETERS: ObjDesc - Object returned from _PLD method
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Dumps formatted contents of a _PLD return buffer.
+ *
+ ******************************************************************************/
+
+#define ACPI_PLD_OUTPUT "%20s : %-6X\n"
+
+void
+AcpiDbDumpPldBuffer (
+ ACPI_OBJECT *ObjDesc)
+{
+ ACPI_OBJECT *BufferDesc;
+ ACPI_PLD_INFO *PldInfo;
+ UINT8 *NewBuffer;
+ ACPI_STATUS Status;
+
+
+ /* Object must be of type Package with at least one Buffer element */
+
+ if (ObjDesc->Type != ACPI_TYPE_PACKAGE)
+ {
+ return;
+ }
+
+ BufferDesc = &ObjDesc->Package.Elements[0];
+ if (BufferDesc->Type != ACPI_TYPE_BUFFER)
+ {
+ return;
+ }
+
+ /* Convert _PLD buffer to local _PLD struct */
+
+ Status = AcpiDecodePldBuffer (BufferDesc->Buffer.Pointer,
+ BufferDesc->Buffer.Length, &PldInfo);
+ if (ACPI_FAILURE (Status))
+ {
+ return;
+ }
+
+ /* Encode local _PLD struct back to a _PLD buffer */
+
+ NewBuffer = AcpiDbEncodePldBuffer (PldInfo);
+ if (!NewBuffer)
+ {
+ return;
+ }
+
+ /* The two bit-packed buffers should match */
+
+ if (ACPI_MEMCMP (NewBuffer, BufferDesc->Buffer.Pointer,
+ BufferDesc->Buffer.Length))
+ {
+ AcpiOsPrintf ("Converted _PLD buffer does not compare. New:\n");
+
+ AcpiUtDumpBuffer (NewBuffer,
+ BufferDesc->Buffer.Length, DB_BYTE_DISPLAY, 0);
+ }
+
+ /* First 32-bit dword */
+
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Revision", PldInfo->Revision);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "IgnoreColor", PldInfo->IgnoreColor);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Color", PldInfo->Color);
+
+ /* Second 32-bit dword */
+
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Width", PldInfo->Width);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Height", PldInfo->Height);
+
+ /* Third 32-bit dword */
+
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "UserVisible", PldInfo->UserVisible);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Dock", PldInfo->Dock);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Lid", PldInfo->Lid);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Panel", PldInfo->Panel);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "VerticalPosition", PldInfo->VerticalPosition);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "HorizontalPosition", PldInfo->HorizontalPosition);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Shape", PldInfo->Shape);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupOrientation", PldInfo->GroupOrientation);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupToken", PldInfo->GroupToken);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupPosition", PldInfo->GroupPosition);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Bay", PldInfo->Bay);
+
+ /* Fourth 32-bit dword */
+
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Ejectable", PldInfo->Ejectable);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "OspmEjectRequired", PldInfo->OspmEjectRequired);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "CabinetNumber", PldInfo->CabinetNumber);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "CardCageNumber", PldInfo->CardCageNumber);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Reference", PldInfo->Reference);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Rotation", PldInfo->Rotation);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "Order", PldInfo->Order);
+
+ /* Fifth 32-bit dword */
+
+ if (BufferDesc->Buffer.Length > 16)
+ {
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "VerticalOffset", PldInfo->VerticalOffset);
+ AcpiOsPrintf (ACPI_PLD_OUTPUT, "HorizontalOffset", PldInfo->HorizontalOffset);
+ }
+
+ ACPI_FREE (PldInfo);
+ ACPI_FREE (NewBuffer);
+}
+
+#endif /* ACPI_DEBUGGER */
diff --git a/sys/contrib/dev/acpica/components/debugger/dbdisply.c b/sys/contrib/dev/acpica/components/debugger/dbdisply.c
index 7776d55..6e82668 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbdisply.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbdisply.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/debugger/dbexec.c b/sys/contrib/dev/acpica/components/debugger/dbexec.c
index f1dce09..26f62b6 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbexec.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbexec.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,7 +54,6 @@
static ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo;
-#define DB_DEFAULT_PKG_ELEMENTS 33
/* Local prototypes */
@@ -82,308 +81,6 @@ AcpiDbExecutionWalk (
void *Context,
void **ReturnValue);
-static ACPI_STATUS
-AcpiDbHexCharToValue (
- int HexChar,
- UINT8 *ReturnValue);
-
-static ACPI_STATUS
-AcpiDbConvertToPackage (
- char *String,
- ACPI_OBJECT *Object);
-
-static ACPI_STATUS
-AcpiDbConvertToObject (
- ACPI_OBJECT_TYPE Type,
- char *String,
- ACPI_OBJECT *Object);
-
-static void
-AcpiDbDeleteObjects (
- UINT32 Count,
- ACPI_OBJECT *Objects);
-
-
-static UINT8 *
-AcpiDbEncodePldBuffer (
- ACPI_PLD_INFO *PldInfo);
-
-static void
-AcpiDbDumpPldBuffer (
- ACPI_OBJECT *ObjDesc);
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbHexCharToValue
- *
- * PARAMETERS: HexChar - Ascii Hex digit, 0-9|a-f|A-F
- * ReturnValue - Where the converted value is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Convert a single hex character to a 4-bit number (0-16).
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiDbHexCharToValue (
- int HexChar,
- UINT8 *ReturnValue)
-{
- UINT8 Value;
-
-
- /* Digit must be ascii [0-9a-fA-F] */
-
- if (!ACPI_IS_XDIGIT (HexChar))
- {
- return (AE_BAD_HEX_CONSTANT);
- }
-
- if (HexChar <= 0x39)
- {
- Value = (UINT8) (HexChar - 0x30);
- }
- else
- {
- Value = (UINT8) (ACPI_TOUPPER (HexChar) - 0x37);
- }
-
- *ReturnValue = Value;
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbHexByteToBinary
- *
- * PARAMETERS: HexByte - Double hex digit (0x00 - 0xFF) in format:
- * HiByte then LoByte.
- * ReturnValue - Where the converted value is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255).
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiDbHexByteToBinary (
- char *HexByte,
- UINT8 *ReturnValue)
-{
- UINT8 Local0;
- UINT8 Local1;
- ACPI_STATUS Status;
-
-
- /* High byte */
-
- Status = AcpiDbHexCharToValue (HexByte[0], &Local0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- /* Low byte */
-
- Status = AcpiDbHexCharToValue (HexByte[1], &Local1);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- *ReturnValue = (UINT8) ((Local0 << 4) | Local1);
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbConvertToBuffer
- *
- * PARAMETERS: String - Input string to be converted
- * Object - Where the buffer object is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Convert a string to a buffer object. String is treated a list
- * of buffer elements, each separated by a space or comma.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiDbConvertToBuffer (
- char *String,
- ACPI_OBJECT *Object)
-{
- UINT32 i;
- UINT32 j;
- UINT32 Length;
- UINT8 *Buffer;
- ACPI_STATUS Status;
-
-
- /* Generate the final buffer length */
-
- for (i = 0, Length = 0; String[i];)
- {
- i+=2;
- Length++;
-
- while (String[i] &&
- ((String[i] == ',') || (String[i] == ' ')))
- {
- i++;
- }
- }
-
- Buffer = ACPI_ALLOCATE (Length);
- if (!Buffer)
- {
- return (AE_NO_MEMORY);
- }
-
- /* Convert the command line bytes to the buffer */
-
- for (i = 0, j = 0; String[i];)
- {
- Status = AcpiDbHexByteToBinary (&String[i], &Buffer[j]);
- if (ACPI_FAILURE (Status))
- {
- ACPI_FREE (Buffer);
- return (Status);
- }
-
- j++;
- i+=2;
- while (String[i] &&
- ((String[i] == ',') || (String[i] == ' ')))
- {
- i++;
- }
- }
-
- Object->Type = ACPI_TYPE_BUFFER;
- Object->Buffer.Pointer = Buffer;
- Object->Buffer.Length = Length;
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbConvertToPackage
- *
- * PARAMETERS: String - Input string to be converted
- * Object - Where the package object is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Convert a string to a package object. Handles nested packages
- * via recursion with AcpiDbConvertToObject.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiDbConvertToPackage (
- char *String,
- ACPI_OBJECT *Object)
-{
- char *This;
- char *Next;
- UINT32 i;
- ACPI_OBJECT_TYPE Type;
- ACPI_OBJECT *Elements;
- ACPI_STATUS Status;
-
-
- Elements = ACPI_ALLOCATE_ZEROED (
- DB_DEFAULT_PKG_ELEMENTS * sizeof (ACPI_OBJECT));
-
- This = String;
- for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++)
- {
- This = AcpiDbGetNextToken (This, &Next, &Type);
- if (!This)
- {
- break;
- }
-
- /* Recursive call to convert each package element */
-
- Status = AcpiDbConvertToObject (Type, This, &Elements[i]);
- if (ACPI_FAILURE (Status))
- {
- AcpiDbDeleteObjects (i + 1, Elements);
- ACPI_FREE (Elements);
- return (Status);
- }
-
- This = Next;
- }
-
- Object->Type = ACPI_TYPE_PACKAGE;
- Object->Package.Count = i;
- Object->Package.Elements = Elements;
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbConvertToObject
- *
- * PARAMETERS: Type - Object type as determined by parser
- * String - Input string to be converted
- * Object - Where the new object is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Convert a typed and tokenized string to an ACPI_OBJECT. Typing:
- * 1) String objects were surrounded by quotes.
- * 2) Buffer objects were surrounded by parentheses.
- * 3) Package objects were surrounded by brackets "[]".
- * 4) All standalone tokens are treated as integers.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiDbConvertToObject (
- ACPI_OBJECT_TYPE Type,
- char *String,
- ACPI_OBJECT *Object)
-{
- ACPI_STATUS Status = AE_OK;
-
-
- switch (Type)
- {
- case ACPI_TYPE_STRING:
- Object->Type = ACPI_TYPE_STRING;
- Object->String.Pointer = String;
- Object->String.Length = (UINT32) ACPI_STRLEN (String);
- break;
-
- case ACPI_TYPE_BUFFER:
- Status = AcpiDbConvertToBuffer (String, Object);
- break;
-
- case ACPI_TYPE_PACKAGE:
- Status = AcpiDbConvertToPackage (String, Object);
- break;
-
- default:
- Object->Type = ACPI_TYPE_INTEGER;
- Status = AcpiUtStrtoul64 (String, 16, &Object->Integer.Value);
- break;
- }
-
- return (Status);
-}
-
/*******************************************************************************
*
@@ -399,7 +96,7 @@ AcpiDbConvertToObject (
*
******************************************************************************/
-static void
+void
AcpiDbDeleteObjects (
UINT32 Count,
ACPI_OBJECT *Objects)
@@ -720,202 +417,6 @@ AcpiDbExecutionWalk (
/*******************************************************************************
*
- * FUNCTION: AcpiDbEncodePldBuffer
- *
- * PARAMETERS: PldInfo - _PLD buffer struct (Using local struct)
- *
- * RETURN: Encode _PLD buffer suitable for return value from _PLD
- *
- * DESCRIPTION: Bit-packs a _PLD buffer struct. Used to test the _PLD macros
- *
- ******************************************************************************/
-
-static UINT8 *
-AcpiDbEncodePldBuffer (
- ACPI_PLD_INFO *PldInfo)
-{
- UINT32 *Buffer;
- UINT32 Dword;
-
-
- Buffer = ACPI_ALLOCATE_ZEROED (ACPI_PLD_BUFFER_SIZE);
- if (!Buffer)
- {
- return (NULL);
- }
-
- /* First 32 bits */
-
- Dword = 0;
- ACPI_PLD_SET_REVISION (&Dword, PldInfo->Revision);
- ACPI_PLD_SET_IGNORE_COLOR (&Dword, PldInfo->IgnoreColor);
- ACPI_PLD_SET_COLOR (&Dword, PldInfo->Color);
- ACPI_MOVE_32_TO_32 (&Buffer[0], &Dword);
-
- /* Second 32 bits */
-
- Dword = 0;
- ACPI_PLD_SET_WIDTH (&Dword, PldInfo->Width);
- ACPI_PLD_SET_HEIGHT (&Dword, PldInfo->Height);
- ACPI_MOVE_32_TO_32 (&Buffer[1], &Dword);
-
- /* Third 32 bits */
-
- Dword = 0;
- ACPI_PLD_SET_USER_VISIBLE (&Dword, PldInfo->UserVisible);
- ACPI_PLD_SET_DOCK (&Dword, PldInfo->Dock);
- ACPI_PLD_SET_LID (&Dword, PldInfo->Lid);
- ACPI_PLD_SET_PANEL (&Dword, PldInfo->Panel);
- ACPI_PLD_SET_VERTICAL (&Dword, PldInfo->VerticalPosition);
- ACPI_PLD_SET_HORIZONTAL (&Dword, PldInfo->HorizontalPosition);
- ACPI_PLD_SET_SHAPE (&Dword, PldInfo->Shape);
- ACPI_PLD_SET_ORIENTATION (&Dword, PldInfo->GroupOrientation);
- ACPI_PLD_SET_TOKEN (&Dword, PldInfo->GroupToken);
- ACPI_PLD_SET_POSITION (&Dword, PldInfo->GroupPosition);
- ACPI_PLD_SET_BAY (&Dword, PldInfo->Bay);
- ACPI_MOVE_32_TO_32 (&Buffer[2], &Dword);
-
- /* Fourth 32 bits */
-
- Dword = 0;
- ACPI_PLD_SET_EJECTABLE (&Dword, PldInfo->Ejectable);
- ACPI_PLD_SET_OSPM_EJECT (&Dword, PldInfo->OspmEjectRequired);
- ACPI_PLD_SET_CABINET (&Dword, PldInfo->CabinetNumber);
- ACPI_PLD_SET_CARD_CAGE (&Dword, PldInfo->CardCageNumber);
- ACPI_PLD_SET_REFERENCE (&Dword, PldInfo->Reference);
- ACPI_PLD_SET_ROTATION (&Dword, PldInfo->Rotation);
- ACPI_PLD_SET_ORDER (&Dword, PldInfo->Order);
- ACPI_MOVE_32_TO_32 (&Buffer[3], &Dword);
-
- if (PldInfo->Revision >= 2)
- {
- /* Fifth 32 bits */
-
- Dword = 0;
- ACPI_PLD_SET_VERT_OFFSET (&Dword, PldInfo->VerticalOffset);
- ACPI_PLD_SET_HORIZ_OFFSET (&Dword, PldInfo->HorizontalOffset);
- ACPI_MOVE_32_TO_32 (&Buffer[4], &Dword);
- }
-
- return (ACPI_CAST_PTR (UINT8, Buffer));
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiDbDumpPldBuffer
- *
- * PARAMETERS: ObjDesc - Object returned from _PLD method
- *
- * RETURN: None.
- *
- * DESCRIPTION: Dumps formatted contents of a _PLD return buffer.
- *
- ******************************************************************************/
-
-#define ACPI_PLD_OUTPUT "%20s : %-6X\n"
-
-static void
-AcpiDbDumpPldBuffer (
- ACPI_OBJECT *ObjDesc)
-{
- ACPI_OBJECT *BufferDesc;
- ACPI_PLD_INFO *PldInfo;
- UINT8 *NewBuffer;
- ACPI_STATUS Status;
-
-
- /* Object must be of type Package with at least one Buffer element */
-
- if (ObjDesc->Type != ACPI_TYPE_PACKAGE)
- {
- return;
- }
-
- BufferDesc = &ObjDesc->Package.Elements[0];
- if (BufferDesc->Type != ACPI_TYPE_BUFFER)
- {
- return;
- }
-
- /* Convert _PLD buffer to local _PLD struct */
-
- Status = AcpiDecodePldBuffer (BufferDesc->Buffer.Pointer,
- BufferDesc->Buffer.Length, &PldInfo);
- if (ACPI_FAILURE (Status))
- {
- return;
- }
-
- /* Encode local _PLD struct back to a _PLD buffer */
-
- NewBuffer = AcpiDbEncodePldBuffer (PldInfo);
- if (!NewBuffer)
- {
- return;
- }
-
- /* The two bit-packed buffers should match */
-
- if (ACPI_MEMCMP (NewBuffer, BufferDesc->Buffer.Pointer,
- BufferDesc->Buffer.Length))
- {
- AcpiOsPrintf ("Converted _PLD buffer does not compare. New:\n");
-
- AcpiUtDumpBuffer (NewBuffer,
- BufferDesc->Buffer.Length, DB_BYTE_DISPLAY, 0);
- }
-
- /* First 32-bit dword */
-
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Revision", PldInfo->Revision);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "IgnoreColor", PldInfo->IgnoreColor);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Color", PldInfo->Color);
-
- /* Second 32-bit dword */
-
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Width", PldInfo->Width);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Height", PldInfo->Height);
-
- /* Third 32-bit dword */
-
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "UserVisible", PldInfo->UserVisible);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Dock", PldInfo->Dock);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Lid", PldInfo->Lid);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Panel", PldInfo->Panel);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "VerticalPosition", PldInfo->VerticalPosition);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "HorizontalPosition", PldInfo->HorizontalPosition);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Shape", PldInfo->Shape);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupOrientation", PldInfo->GroupOrientation);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupToken", PldInfo->GroupToken);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupPosition", PldInfo->GroupPosition);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Bay", PldInfo->Bay);
-
- /* Fourth 32-bit dword */
-
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Ejectable", PldInfo->Ejectable);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "OspmEjectRequired", PldInfo->OspmEjectRequired);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "CabinetNumber", PldInfo->CabinetNumber);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "CardCageNumber", PldInfo->CardCageNumber);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Reference", PldInfo->Reference);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Rotation", PldInfo->Rotation);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "Order", PldInfo->Order);
-
- /* Fifth 32-bit dword */
-
- if (BufferDesc->Buffer.Length > 16)
- {
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "VerticalOffset", PldInfo->VerticalOffset);
- AcpiOsPrintf (ACPI_PLD_OUTPUT, "HorizontalOffset", PldInfo->HorizontalOffset);
- }
-
- ACPI_FREE (PldInfo);
- ACPI_FREE (NewBuffer);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiDbExecute
*
* PARAMETERS: Name - Name of method to execute
@@ -983,12 +484,10 @@ AcpiDbExecute (
Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname,
&AcpiGbl_DbMethodInfo.Method);
- if (ACPI_FAILURE (Status))
+ if (ACPI_SUCCESS (Status))
{
- return;
+ Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj);
}
-
- Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj);
ACPI_FREE (NameString);
}
@@ -998,7 +497,6 @@ AcpiDbExecute (
*/
AcpiOsSleep ((UINT64) 10);
-
#ifdef ACPI_DEBUG_OUTPUT
/* Memory allocation tracking */
diff --git a/sys/contrib/dev/acpica/components/debugger/dbfileio.c b/sys/contrib/dev/acpica/components/debugger/dbfileio.c
index 5c4b100..e03bb40 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbfileio.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbfileio.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/debugger/dbhistry.c b/sys/contrib/dev/acpica/components/debugger/dbhistry.c
index 1305451..0e05e14 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbhistry.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbhistry.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/debugger/dbinput.c b/sys/contrib/dev/acpica/components/debugger/dbinput.c
index f5db216..b5c46df 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbinput.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbinput.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -210,7 +210,7 @@ static const ACPI_DB_COMMAND_INFO AcpiGbl_DbCommands[] =
{"RESOURCES", 1},
{"RESULTS", 0},
{"SET", 3},
- {"SLEEP", 1},
+ {"SLEEP", 0},
{"STATS", 1},
{"STOP", 0},
{"TABLES", 0},
@@ -274,7 +274,7 @@ static const ACPI_DB_COMMAND_HELP AcpiGbl_DbCommandHelp[] =
{1, " References <Addr>", "Find all references to object at addr\n"},
{1, " Resources <DeviceName | *>", "Display Device resources (* = all devices)\n"},
{1, " Set N <NamedObject> <Value>", "Set value for named integer\n"},
- {1, " Sleep <SleepState>", "Simulate sleep/wake sequence\n"},
+ {1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"},
{1, " Template <Object>", "Format/dump a Buffer/ResourceTemplate\n"},
{1, " Terminate", "Delete namespace and all internal objects\n"},
{1, " Type <Object>", "Display object type\n"},
@@ -1168,6 +1168,8 @@ AcpiDbUserCommands (
ACPI_STATUS Status = AE_OK;
+ AcpiOsPrintf ("\n");
+
/* TBD: [Restructure] Need a separate command line buffer for step mode */
while (!AcpiGbl_DbTerminateThreads)
diff --git a/sys/contrib/dev/acpica/components/debugger/dbmethod.c b/sys/contrib/dev/acpica/components/debugger/dbmethod.c
index ccfb7d5..d3d86dd 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbmethod.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbmethod.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -396,7 +396,7 @@ AcpiDbDisassembleMethod (
WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
Status = AcpiPsParseAml (WalkState);
- AcpiDmParseDeferredOps (Op);
+ (void) AcpiDmParseDeferredOps (Op);
/* Now we can disassemble the method */
diff --git a/sys/contrib/dev/acpica/components/debugger/dbnames.c b/sys/contrib/dev/acpica/components/debugger/dbnames.c
index aed8dfb..8efb74d 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbnames.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbnames.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -159,7 +159,7 @@ AcpiDbSetScope (
AcpiDbPrepNamestring (Name);
- if (Name[0] == '\\')
+ if (ACPI_IS_ROOT_PREFIX (Name[0]))
{
/* Validate new scope from the root */
diff --git a/sys/contrib/dev/acpica/components/debugger/dbstats.c b/sys/contrib/dev/acpica/components/debugger/dbstats.c
index 7037c2b..6a1c0bb 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbstats.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbstats.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/debugger/dbutils.c b/sys/contrib/dev/acpica/components/debugger/dbutils.c
index 7d1c427..33b9c19 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbutils.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -286,7 +286,7 @@ AcpiDbPrepNamestring (
/* Ignore a leading backslash, this is the root prefix */
- if (*Name == '\\')
+ if (ACPI_IS_ROOT_PREFIX (*Name))
{
Name++;
}
diff --git a/sys/contrib/dev/acpica/components/debugger/dbxface.c b/sys/contrib/dev/acpica/components/debugger/dbxface.c
index f265dba..6f97582 100644
--- a/sys/contrib/dev/acpica/components/debugger/dbxface.c
+++ b/sys/contrib/dev/acpica/components/debugger/dbxface.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -421,9 +421,9 @@ AcpiDbInitialize (
AcpiGbl_DbOutputFlags = ACPI_DB_CONSOLE_OUTPUT;
AcpiGbl_DbOpt_tables = FALSE;
+ AcpiGbl_DbOpt_disasm = FALSE;
AcpiGbl_DbOpt_stats = FALSE;
#ifdef ACPI_DISASSEMBLER
- AcpiGbl_DbOpt_disasm = FALSE;
AcpiGbl_DbOpt_verbose = TRUE;
#endif
AcpiGbl_DbOpt_ini_methods = TRUE;
@@ -437,7 +437,7 @@ AcpiDbInitialize (
/* Initial scope is the root */
- AcpiGbl_DbScopeBuf [0] = '\\';
+ AcpiGbl_DbScopeBuf [0] = AML_ROOT_PREFIX;
AcpiGbl_DbScopeBuf [1] = 0;
AcpiGbl_DbScopeNode = AcpiGbl_RootNode;
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c b/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c
index 9be6a50..2f6ff72 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmbuffer.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c b/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c
index 1e8c224..9a68079 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -83,7 +83,7 @@ AcpiDmParseDeferredOps (
ACPI_STATUS Status;
- ACPI_FUNCTION_NAME (DmParseDeferredOps);
+ ACPI_FUNCTION_ENTRY ();
/* Traverse the entire parse tree */
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmnames.c b/sys/contrib/dev/acpica/components/disassembler/dmnames.c
index 0149bff..b2ef29d 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmnames.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmnames.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,6 @@
#include <contrib/dev/acpica/include/acpi.h>
#include <contrib/dev/acpica/include/accommon.h>
-#include <contrib/dev/acpica/include/acparser.h>
#include <contrib/dev/acpica/include/amlcode.h>
#include <contrib/dev/acpica/include/acnamesp.h>
#include <contrib/dev/acpica/include/acdisasm.h>
@@ -226,7 +225,8 @@ AcpiDmNamestring (
/* Handle all Scope Prefix operators */
- while (AcpiPsIsPrefixChar (ACPI_GET8 (Name)))
+ while (ACPI_IS_ROOT_PREFIX (ACPI_GET8 (Name)) ||
+ ACPI_IS_PARENT_PREFIX (ACPI_GET8 (Name)))
{
/* Append prefix character */
@@ -323,7 +323,7 @@ AcpiDmDisplayPath (
if ((NamePath) &&
(NamePath->Common.Value.String) &&
- (NamePath->Common.Value.String[0] == '\\'))
+ (ACPI_IS_ROOT_PREFIX (NamePath->Common.Value.String[0])))
{
AcpiDmNamestring (NamePath->Common.Value.String);
return;
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmobject.c b/sys/contrib/dev/acpica/components/disassembler/dmobject.c
index 6801af5..5dde74a 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmobject.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmobject.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmopcode.c b/sys/contrib/dev/acpica/components/disassembler/dmopcode.c
index 822a1a5..01672fa 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmopcode.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmopcode.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrc.c b/sys/contrib/dev/acpica/components/disassembler/dmresrc.c
index 5217084..fd391b3 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrc.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -415,7 +415,8 @@ AcpiDmIsResourceTemplate (
/* Walk the byte list, abort on any invalid descriptor type or length */
- Status = AcpiUtWalkAmlResources (WalkState, Aml, Length, NULL, &EndAml);
+ Status = AcpiUtWalkAmlResources (WalkState, Aml, Length,
+ NULL, ACPI_CAST_INDIRECT_PTR (void, &EndAml));
if (ACPI_FAILURE (Status))
{
return (AE_TYPE);
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c
index 700370f..c468bbd 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrcl.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c
index a3d046d..5da7df4 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrcl2.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c b/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c
index 7957920..778d663 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmresrcs.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmutils.c b/sys/contrib/dev/acpica/components/disassembler/dmutils.c
index 7ac56b7..5d35d83 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmutils.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/disassembler/dmwalk.c b/sys/contrib/dev/acpica/components/disassembler/dmwalk.c
index f0d65b6..67a7965 100644
--- a/sys/contrib/dev/acpica/components/disassembler/dmwalk.c
+++ b/sys/contrib/dev/acpica/components/disassembler/dmwalk.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -441,7 +441,30 @@ AcpiDmDescendingOp (
* This is a first-level element of a term list,
* indent a new line
*/
- AcpiDmIndent (Level);
+ switch (Op->Common.AmlOpcode)
+ {
+ case AML_NOOP_OP:
+ /*
+ * Optionally just ignore this opcode. Some tables use
+ * NoOp opcodes for "padding" out packages that the BIOS
+ * changes dynamically. This can leave hundreds or
+ * thousands of NoOp opcodes that if disassembled,
+ * cannot be compiled because they are syntactically
+ * incorrect.
+ */
+ if (AcpiGbl_IgnoreNoopOperator)
+ {
+ Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
+ return (AE_OK);
+ }
+
+ /* Fallthrough */
+
+ default:
+ AcpiDmIndent (Level);
+ break;
+ }
+
Info->LastLevel = Level;
Info->Count = 0;
}
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsargs.c b/sys/contrib/dev/acpica/components/dispatcher/dsargs.c
index 0602905..2c574ca1 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsargs.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsargs.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c b/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c
index 198ba0e..bcc58ca 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsfield.c b/sys/contrib/dev/acpica/components/dispatcher/dsfield.c
index 3574aa7..1ab8c3b 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsfield.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsfield.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsinit.c b/sys/contrib/dev/acpica/components/dispatcher/dsinit.c
index c3766fd..7aca0e8 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsinit.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c b/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c
index b3548e9..d2dccaf 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -163,6 +163,7 @@ AcpiDsCreateMethodMutex (
Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex);
if (ACPI_FAILURE (Status))
{
+ AcpiUtDeleteObjectDesc (MutexDesc);
return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c b/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c
index 76c82af..164e0ef 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsmthdat.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsobject.c b/sys/contrib/dev/acpica/components/dispatcher/dsobject.c
index 69985a9..d718929 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsobject.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsobject.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -541,7 +541,7 @@ AcpiDsBuildInternalPackageObj (
}
ACPI_INFO ((AE_INFO,
- "Actual Package length (%u) is larger than NumElements field (%u), truncated\n",
+ "Actual Package length (%u) is larger than NumElements field (%u), truncated",
i, ElementCount));
}
else if (i < ElementCount)
@@ -734,7 +734,7 @@ AcpiDsInitObjectFromOp (
/* Truncate value if we are executing from a 32-bit ACPI table */
#ifndef ACPI_NO_METHOD_EXECUTION
- AcpiExTruncateFor32bitTable (ObjDesc);
+ (void) AcpiExTruncateFor32bitTable (ObjDesc);
#endif
break;
@@ -756,8 +756,17 @@ AcpiDsInitObjectFromOp (
case AML_TYPE_LITERAL:
ObjDesc->Integer.Value = Op->Common.Value.Integer;
+
#ifndef ACPI_NO_METHOD_EXECUTION
- AcpiExTruncateFor32bitTable (ObjDesc);
+ if (AcpiExTruncateFor32bitTable (ObjDesc))
+ {
+ /* Warn if we found a 64-bit constant in a 32-bit table */
+
+ ACPI_WARNING ((AE_INFO,
+ "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
+ ACPI_FORMAT_UINT64 (Op->Common.Value.Integer),
+ (UINT32) ObjDesc->Integer.Value));
+ }
#endif
break;
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c b/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c
index 8c7d314..7fed5fd 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dsutils.c b/sys/contrib/dev/acpica/components/dispatcher/dsutils.c
index 13ef960..3b44c67 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dsutils.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dsutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -201,7 +201,7 @@ AcpiDsIsResultUsed (
if (!Op)
{
ACPI_ERROR ((AE_INFO, "Null Op"));
- return_UINT8 (TRUE);
+ return_VALUE (TRUE);
}
/*
@@ -231,7 +231,7 @@ AcpiDsIsResultUsed (
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
"At Method level, result of [%s] not used\n",
AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
- return_UINT8 (FALSE);
+ return_VALUE (FALSE);
}
/* Get info on the parent. The RootOp is AML_SCOPE */
@@ -241,7 +241,7 @@ AcpiDsIsResultUsed (
{
ACPI_ERROR ((AE_INFO,
"Unknown parent opcode Op=%p", Op));
- return_UINT8 (FALSE);
+ return_VALUE (FALSE);
}
/*
@@ -331,7 +331,7 @@ ResultUsed:
AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
- return_UINT8 (TRUE);
+ return_VALUE (TRUE);
ResultNotUsed:
@@ -340,7 +340,7 @@ ResultNotUsed:
AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
- return_UINT8 (FALSE);
+ return_VALUE (FALSE);
}
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswexec.c b/sys/contrib/dev/acpica/components/dispatcher/dswexec.c
index eed103d..f92f49b 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswexec.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswexec.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -164,7 +164,7 @@ AcpiDsGetPredicateValue (
/* Truncate the predicate to 32-bits if necessary */
- AcpiExTruncateFor32bitTable (LocalObjDesc);
+ (void) AcpiExTruncateFor32bitTable (LocalObjDesc);
/*
* Save the result of the predicate evaluation on
@@ -739,7 +739,7 @@ AcpiDsExecEndOp (
* ACPI 2.0 support for 64-bit integers: Truncate numeric
* result value if we are executing from a 32-bit ACPI table
*/
- AcpiExTruncateFor32bitTable (WalkState->ResultObj);
+ (void) AcpiExTruncateFor32bitTable (WalkState->ResultObj);
/*
* Check if we just completed the evaluation of a
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswload.c b/sys/contrib/dev/acpica/components/dispatcher/dswload.c
index 53257b5..f86dea2 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswload.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswload2.c b/sys/contrib/dev/acpica/components/dispatcher/dswload2.c
index c3f7bef..9114895 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswload2.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswload2.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -236,7 +236,7 @@ AcpiDsLoad2BeginOp (
*/
ACPI_WARNING ((AE_INFO,
"Type override - [%4.4s] had invalid type (%s) "
- "for Scope operator, changed to type ANY\n",
+ "for Scope operator, changed to type ANY",
AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type)));
Node->Type = ACPI_TYPE_ANY;
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswscope.c b/sys/contrib/dev/acpica/components/dispatcher/dswscope.c
index bdbd374..8530b5d 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswscope.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswscope.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/dispatcher/dswstate.c b/sys/contrib/dev/acpica/components/dispatcher/dswstate.c
index bdea4d7..8fd36bf 100644
--- a/sys/contrib/dev/acpica/components/dispatcher/dswstate.c
+++ b/sys/contrib/dev/acpica/components/dispatcher/dswstate.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evevent.c b/sys/contrib/dev/acpica/components/events/evevent.c
index 5706f8f..adad8c8 100644
--- a/sys/contrib/dev/acpica/components/events/evevent.c
+++ b/sys/contrib/dev/acpica/components/events/evevent.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evglock.c b/sys/contrib/dev/acpica/components/events/evglock.c
index 894e132..4cec447 100644
--- a/sys/contrib/dev/acpica/components/events/evglock.c
+++ b/sys/contrib/dev/acpica/components/events/evglock.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evgpe.c b/sys/contrib/dev/acpica/components/events/evgpe.c
index eb96d72..75ad956 100644
--- a/sys/contrib/dev/acpica/components/events/evgpe.c
+++ b/sys/contrib/dev/acpica/components/events/evgpe.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -770,7 +770,7 @@ AcpiEvGpeDispatch (
{
ACPI_EXCEPTION ((AE_INFO, Status,
"Unable to clear GPE%02X", GpeNumber));
- return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
+ return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
}
@@ -788,7 +788,7 @@ AcpiEvGpeDispatch (
{
ACPI_EXCEPTION ((AE_INFO, Status,
"Unable to disable GPE%02X", GpeNumber));
- return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
+ return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
/*
@@ -846,7 +846,7 @@ AcpiEvGpeDispatch (
break;
}
- return_UINT32 (ACPI_INTERRUPT_HANDLED);
+ return_VALUE (ACPI_INTERRUPT_HANDLED);
}
#endif /* !ACPI_REDUCED_HARDWARE */
diff --git a/sys/contrib/dev/acpica/components/events/evgpeblk.c b/sys/contrib/dev/acpica/components/events/evgpeblk.c
index 6a1c04a..f223b1a 100644
--- a/sys/contrib/dev/acpica/components/events/evgpeblk.c
+++ b/sys/contrib/dev/acpica/components/events/evgpeblk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -443,8 +443,8 @@ AcpiEvCreateGpeBlock (
(*ReturnGpeBlock) = GpeBlock;
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
+ " Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X\n",
(UINT32) GpeBlock->BlockBaseNumber,
(UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)),
GpeDevice->Name.Ascii, GpeBlock->RegisterCount,
@@ -539,8 +539,10 @@ AcpiEvInitializeGpeBlock (
if (GpeEnabledCount)
{
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
- "Enabled %u GPEs in this block\n", GpeEnabledCount));
+ ACPI_INFO ((AE_INFO,
+ "Enabled %u GPEs in block %02X to %02X", GpeEnabledCount,
+ (UINT32) GpeBlock->BlockBaseNumber,
+ (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1))));
}
GpeBlock->Initialized = TRUE;
diff --git a/sys/contrib/dev/acpica/components/events/evgpeinit.c b/sys/contrib/dev/acpica/components/events/evgpeinit.c
index 9266d60..9e8630d 100644
--- a/sys/contrib/dev/acpica/components/events/evgpeinit.c
+++ b/sys/contrib/dev/acpica/components/events/evgpeinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -94,6 +94,9 @@ AcpiEvGpeInitialize (
ACPI_FUNCTION_TRACE (EvGpeInitialize);
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
+ "Initializing General Purpose Events (GPEs):\n"));
+
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (Status))
{
diff --git a/sys/contrib/dev/acpica/components/events/evgpeutil.c b/sys/contrib/dev/acpica/components/events/evgpeutil.c
index 7f7bb3c..1841f9d 100644
--- a/sys/contrib/dev/acpica/components/events/evgpeutil.c
+++ b/sys/contrib/dev/acpica/components/events/evgpeutil.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evhandler.c b/sys/contrib/dev/acpica/components/events/evhandler.c
new file mode 100644
index 0000000..f32ba65
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/events/evhandler.c
@@ -0,0 +1,578 @@
+/******************************************************************************
+ *
+ * Module Name: evhandler - Support for Address Space handlers
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#define __EVHANDLER_C__
+
+#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 ("evhandler")
+
+
+/* Local prototypes */
+
+static ACPI_STATUS
+AcpiEvInstallHandler (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue);
+
+/* These are the address spaces that will get default handlers */
+
+UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
+{
+ ACPI_ADR_SPACE_SYSTEM_MEMORY,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ ACPI_ADR_SPACE_PCI_CONFIG,
+ ACPI_ADR_SPACE_DATA_TABLE
+};
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvInstallRegionHandlers
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Installs the core subsystem default address space handlers.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvInstallRegionHandlers (
+ void)
+{
+ ACPI_STATUS Status;
+ UINT32 i;
+
+
+ ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
+
+
+ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /*
+ * All address spaces (PCI Config, EC, SMBus) are scope dependent and
+ * registration must occur for a specific device.
+ *
+ * In the case of the system memory and IO address spaces there is
+ * currently no device associated with the address space. For these we
+ * use the root.
+ *
+ * We install the default PCI config space handler at the root so that
+ * this space is immediately available even though the we have not
+ * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
+ * specification which states that the PCI config space must be always
+ * available -- even though we are nowhere near ready to find the PCI root
+ * buses at this point.
+ *
+ * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
+ * has already been installed (via AcpiInstallAddressSpaceHandler).
+ * Similar for AE_SAME_HANDLER.
+ */
+ for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
+ {
+ Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
+ AcpiGbl_DefaultAddressSpaces[i],
+ ACPI_DEFAULT_HANDLER, NULL, NULL);
+ switch (Status)
+ {
+ case AE_OK:
+ case AE_SAME_HANDLER:
+ case AE_ALREADY_EXISTS:
+
+ /* These exceptions are all OK */
+
+ Status = AE_OK;
+ break;
+
+ default:
+
+ goto UnlockAndExit;
+ }
+ }
+
+UnlockAndExit:
+ (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvHasDefaultHandler
+ *
+ * PARAMETERS: Node - Namespace node for the device
+ * SpaceId - The address space ID
+ *
+ * RETURN: TRUE if default handler is installed, FALSE otherwise
+ *
+ * DESCRIPTION: Check if the default handler is installed for the requested
+ * space ID.
+ *
+ ******************************************************************************/
+
+BOOLEAN
+AcpiEvHasDefaultHandler (
+ ACPI_NAMESPACE_NODE *Node,
+ ACPI_ADR_SPACE_TYPE SpaceId)
+{
+ ACPI_OPERAND_OBJECT *ObjDesc;
+ ACPI_OPERAND_OBJECT *HandlerObj;
+
+
+ /* Must have an existing internal object */
+
+ ObjDesc = AcpiNsGetAttachedObject (Node);
+ if (ObjDesc)
+ {
+ HandlerObj = ObjDesc->Device.Handler;
+
+ /* Walk the linked list of handlers for this object */
+
+ while (HandlerObj)
+ {
+ if (HandlerObj->AddressSpace.SpaceId == SpaceId)
+ {
+ if (HandlerObj->AddressSpace.HandlerFlags &
+ ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
+ {
+ return (TRUE);
+ }
+ }
+
+ HandlerObj = HandlerObj->AddressSpace.Next;
+ }
+ }
+
+ return (FALSE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvInstallHandler
+ *
+ * PARAMETERS: WalkNamespace callback
+ *
+ * DESCRIPTION: This routine installs an address handler into objects that are
+ * of type Region or Device.
+ *
+ * If the Object is a Device, and the device has a handler of
+ * the same type then the search is terminated in that branch.
+ *
+ * This is because the existing handler is closer in proximity
+ * to any more regions than the one we are trying to install.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiEvInstallHandler (
+ ACPI_HANDLE ObjHandle,
+ UINT32 Level,
+ void *Context,
+ void **ReturnValue)
+{
+ ACPI_OPERAND_OBJECT *HandlerObj;
+ ACPI_OPERAND_OBJECT *NextHandlerObj;
+ ACPI_OPERAND_OBJECT *ObjDesc;
+ ACPI_NAMESPACE_NODE *Node;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_NAME (EvInstallHandler);
+
+
+ HandlerObj = (ACPI_OPERAND_OBJECT *) Context;
+
+ /* Parameter validation */
+
+ if (!HandlerObj)
+ {
+ return (AE_OK);
+ }
+
+ /* Convert and validate the device handle */
+
+ Node = AcpiNsValidateHandle (ObjHandle);
+ if (!Node)
+ {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * We only care about regions and objects that are allowed to have
+ * address space handlers
+ */
+ if ((Node->Type != ACPI_TYPE_DEVICE) &&
+ (Node->Type != ACPI_TYPE_REGION) &&
+ (Node != AcpiGbl_RootNode))
+ {
+ return (AE_OK);
+ }
+
+ /* Check for an existing internal object */
+
+ ObjDesc = AcpiNsGetAttachedObject (Node);
+ if (!ObjDesc)
+ {
+ /* No object, just exit */
+
+ return (AE_OK);
+ }
+
+ /* Devices are handled different than regions */
+
+ if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
+ {
+ /* Check if this Device already has a handler for this address space */
+
+ NextHandlerObj = ObjDesc->Device.Handler;
+ while (NextHandlerObj)
+ {
+ /* Found a handler, is it for the same address space? */
+
+ if (NextHandlerObj->AddressSpace.SpaceId ==
+ HandlerObj->AddressSpace.SpaceId)
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+ "Found handler for region [%s] in device %p(%p) "
+ "handler %p\n",
+ AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
+ ObjDesc, NextHandlerObj, HandlerObj));
+
+ /*
+ * Since the object we found it on was a device, then it
+ * means that someone has already installed a handler for
+ * the branch of the namespace from this device on. Just
+ * bail out telling the walk routine to not traverse this
+ * branch. This preserves the scoping rule for handlers.
+ */
+ return (AE_CTRL_DEPTH);
+ }
+
+ /* Walk the linked list of handlers attached to this device */
+
+ NextHandlerObj = NextHandlerObj->AddressSpace.Next;
+ }
+
+ /*
+ * As long as the device didn't have a handler for this space we
+ * don't care about it. We just ignore it and proceed.
+ */
+ return (AE_OK);
+ }
+
+ /* Object is a Region */
+
+ if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
+ {
+ /* This region is for a different address space, just ignore it */
+
+ return (AE_OK);
+ }
+
+ /*
+ * Now we have a region and it is for the handler's address space type.
+ *
+ * First disconnect region for any previous handler (if any)
+ */
+ AcpiEvDetachRegion (ObjDesc, FALSE);
+
+ /* Connect the region to the new handler */
+
+ Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
+ return (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvInstallSpaceHandler
+ *
+ * PARAMETERS: Node - Namespace node for the device
+ * SpaceId - The address space ID
+ * Handler - Address of the handler
+ * Setup - Address of the setup function
+ * Context - Value passed to the handler on each access
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
+ * Assumes namespace is locked
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvInstallSpaceHandler (
+ ACPI_NAMESPACE_NODE *Node,
+ ACPI_ADR_SPACE_TYPE SpaceId,
+ ACPI_ADR_SPACE_HANDLER Handler,
+ ACPI_ADR_SPACE_SETUP Setup,
+ void *Context)
+{
+ ACPI_OPERAND_OBJECT *ObjDesc;
+ ACPI_OPERAND_OBJECT *HandlerObj;
+ ACPI_STATUS Status;
+ ACPI_OBJECT_TYPE Type;
+ UINT8 Flags = 0;
+
+
+ ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
+
+
+ /*
+ * This registration is valid for only the types below and the root. This
+ * is where the default handlers get placed.
+ */
+ if ((Node->Type != ACPI_TYPE_DEVICE) &&
+ (Node->Type != ACPI_TYPE_PROCESSOR) &&
+ (Node->Type != ACPI_TYPE_THERMAL) &&
+ (Node != AcpiGbl_RootNode))
+ {
+ Status = AE_BAD_PARAMETER;
+ goto UnlockAndExit;
+ }
+
+ if (Handler == ACPI_DEFAULT_HANDLER)
+ {
+ Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
+
+ switch (SpaceId)
+ {
+ case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+ Handler = AcpiExSystemMemorySpaceHandler;
+ Setup = AcpiEvSystemMemoryRegionSetup;
+ break;
+
+ case ACPI_ADR_SPACE_SYSTEM_IO:
+ Handler = AcpiExSystemIoSpaceHandler;
+ Setup = AcpiEvIoSpaceRegionSetup;
+ break;
+
+ case ACPI_ADR_SPACE_PCI_CONFIG:
+ Handler = AcpiExPciConfigSpaceHandler;
+ Setup = AcpiEvPciConfigRegionSetup;
+ break;
+
+ case ACPI_ADR_SPACE_CMOS:
+ Handler = AcpiExCmosSpaceHandler;
+ Setup = AcpiEvCmosRegionSetup;
+ break;
+
+ case ACPI_ADR_SPACE_PCI_BAR_TARGET:
+ Handler = AcpiExPciBarSpaceHandler;
+ Setup = AcpiEvPciBarRegionSetup;
+ break;
+
+ case ACPI_ADR_SPACE_DATA_TABLE:
+ Handler = AcpiExDataTableSpaceHandler;
+ Setup = NULL;
+ break;
+
+ default:
+ Status = AE_BAD_PARAMETER;
+ goto UnlockAndExit;
+ }
+ }
+
+ /* If the caller hasn't specified a setup routine, use the default */
+
+ if (!Setup)
+ {
+ Setup = AcpiEvDefaultRegionSetup;
+ }
+
+ /* Check for an existing internal object */
+
+ ObjDesc = AcpiNsGetAttachedObject (Node);
+ if (ObjDesc)
+ {
+ /*
+ * The attached device object already exists. Make sure the handler
+ * is not already installed.
+ */
+ HandlerObj = ObjDesc->Device.Handler;
+
+ /* Walk the handler list for this device */
+
+ while (HandlerObj)
+ {
+ /* Same SpaceId indicates a handler already installed */
+
+ if (HandlerObj->AddressSpace.SpaceId == SpaceId)
+ {
+ if (HandlerObj->AddressSpace.Handler == Handler)
+ {
+ /*
+ * It is (relatively) OK to attempt to install the SAME
+ * handler twice. This can easily happen with the
+ * PCI_Config space.
+ */
+ Status = AE_SAME_HANDLER;
+ goto UnlockAndExit;
+ }
+ else
+ {
+ /* A handler is already installed */
+
+ Status = AE_ALREADY_EXISTS;
+ }
+ goto UnlockAndExit;
+ }
+
+ /* Walk the linked list of handlers */
+
+ HandlerObj = HandlerObj->AddressSpace.Next;
+ }
+ }
+ else
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+ "Creating object on Device %p while installing handler\n", Node));
+
+ /* ObjDesc does not exist, create one */
+
+ if (Node->Type == ACPI_TYPE_ANY)
+ {
+ Type = ACPI_TYPE_DEVICE;
+ }
+ else
+ {
+ Type = Node->Type;
+ }
+
+ ObjDesc = AcpiUtCreateInternalObject (Type);
+ if (!ObjDesc)
+ {
+ Status = AE_NO_MEMORY;
+ goto UnlockAndExit;
+ }
+
+ /* Init new descriptor */
+
+ ObjDesc->Common.Type = (UINT8) Type;
+
+ /* Attach the new object to the Node */
+
+ Status = AcpiNsAttachObject (Node, ObjDesc, Type);
+
+ /* Remove local reference to the object */
+
+ AcpiUtRemoveReference (ObjDesc);
+
+ if (ACPI_FAILURE (Status))
+ {
+ goto UnlockAndExit;
+ }
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+ "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
+ AcpiUtGetRegionName (SpaceId), SpaceId,
+ AcpiUtGetNodeName (Node), Node, ObjDesc));
+
+ /*
+ * Install the handler
+ *
+ * At this point there is no existing handler. Just allocate the object
+ * for the handler and link it into the list.
+ */
+ HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
+ if (!HandlerObj)
+ {
+ Status = AE_NO_MEMORY;
+ goto UnlockAndExit;
+ }
+
+ /* Init handler obj */
+
+ HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
+ HandlerObj->AddressSpace.HandlerFlags = Flags;
+ HandlerObj->AddressSpace.RegionList = NULL;
+ HandlerObj->AddressSpace.Node = Node;
+ HandlerObj->AddressSpace.Handler = Handler;
+ HandlerObj->AddressSpace.Context = Context;
+ HandlerObj->AddressSpace.Setup = Setup;
+
+ /* Install at head of Device.AddressSpace list */
+
+ HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
+
+ /*
+ * The Device object is the first reference on the HandlerObj.
+ * Each region that uses the handler adds a reference.
+ */
+ ObjDesc->Device.Handler = HandlerObj;
+
+ /*
+ * Walk the namespace finding all of the regions this
+ * handler will manage.
+ *
+ * Start at the device and search the branch toward
+ * the leaf nodes until either the leaf is encountered or
+ * a device is detected that has an address handler of the
+ * same type.
+ *
+ * In either case, back up and search down the remainder
+ * of the branch
+ */
+ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
+ ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
+ HandlerObj, NULL);
+
+UnlockAndExit:
+ return_ACPI_STATUS (Status);
+}
diff --git a/sys/contrib/dev/acpica/components/events/evmisc.c b/sys/contrib/dev/acpica/components/events/evmisc.c
index b63aafc..034b8e0 100644
--- a/sys/contrib/dev/acpica/components/events/evmisc.c
+++ b/sys/contrib/dev/acpica/components/events/evmisc.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evregion.c b/sys/contrib/dev/acpica/components/events/evregion.c
index d149181..7bfb1f5 100644
--- a/sys/contrib/dev/acpica/components/events/evregion.c
+++ b/sys/contrib/dev/acpica/components/events/evregion.c
@@ -1,11 +1,11 @@
/******************************************************************************
*
- * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
+ * Module Name: evregion - Operation Region support
*
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,12 +54,9 @@
ACPI_MODULE_NAME ("evregion")
-/* Local prototypes */
+extern UINT8 AcpiGbl_DefaultAddressSpaces[];
-static BOOLEAN
-AcpiEvHasDefaultHandler (
- ACPI_NAMESPACE_NODE *Node,
- ACPI_ADR_SPACE_TYPE SpaceId);
+/* Local prototypes */
static void
AcpiEvOrphanEcRegMethod (
@@ -72,152 +69,6 @@ AcpiEvRegRun (
void *Context,
void **ReturnValue);
-static ACPI_STATUS
-AcpiEvInstallHandler (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue);
-
-/* These are the address spaces that will get default handlers */
-
-#define ACPI_NUM_DEFAULT_SPACES 4
-
-static UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
-{
- ACPI_ADR_SPACE_SYSTEM_MEMORY,
- ACPI_ADR_SPACE_SYSTEM_IO,
- ACPI_ADR_SPACE_PCI_CONFIG,
- ACPI_ADR_SPACE_DATA_TABLE
-};
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvInstallRegionHandlers
- *
- * PARAMETERS: None
- *
- * RETURN: Status
- *
- * DESCRIPTION: Installs the core subsystem default address space handlers.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiEvInstallRegionHandlers (
- void)
-{
- ACPI_STATUS Status;
- UINT32 i;
-
-
- ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
-
-
- Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- /*
- * All address spaces (PCI Config, EC, SMBus) are scope dependent and
- * registration must occur for a specific device.
- *
- * In the case of the system memory and IO address spaces there is
- * currently no device associated with the address space. For these we
- * use the root.
- *
- * We install the default PCI config space handler at the root so that
- * this space is immediately available even though the we have not
- * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
- * specification which states that the PCI config space must be always
- * available -- even though we are nowhere near ready to find the PCI root
- * buses at this point.
- *
- * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
- * has already been installed (via AcpiInstallAddressSpaceHandler).
- * Similar for AE_SAME_HANDLER.
- */
- for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
- {
- Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
- AcpiGbl_DefaultAddressSpaces[i],
- ACPI_DEFAULT_HANDLER, NULL, NULL);
- switch (Status)
- {
- case AE_OK:
- case AE_SAME_HANDLER:
- case AE_ALREADY_EXISTS:
-
- /* These exceptions are all OK */
-
- Status = AE_OK;
- break;
-
- default:
-
- goto UnlockAndExit;
- }
- }
-
-UnlockAndExit:
- (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
- return_ACPI_STATUS (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvHasDefaultHandler
- *
- * PARAMETERS: Node - Namespace node for the device
- * SpaceId - The address space ID
- *
- * RETURN: TRUE if default handler is installed, FALSE otherwise
- *
- * DESCRIPTION: Check if the default handler is installed for the requested
- * space ID.
- *
- ******************************************************************************/
-
-static BOOLEAN
-AcpiEvHasDefaultHandler (
- ACPI_NAMESPACE_NODE *Node,
- ACPI_ADR_SPACE_TYPE SpaceId)
-{
- ACPI_OPERAND_OBJECT *ObjDesc;
- ACPI_OPERAND_OBJECT *HandlerObj;
-
-
- /* Must have an existing internal object */
-
- ObjDesc = AcpiNsGetAttachedObject (Node);
- if (ObjDesc)
- {
- HandlerObj = ObjDesc->Device.Handler;
-
- /* Walk the linked list of handlers for this object */
-
- while (HandlerObj)
- {
- if (HandlerObj->AddressSpace.SpaceId == SpaceId)
- {
- if (HandlerObj->AddressSpace.HandlerFlags &
- ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
- {
- return (TRUE);
- }
- }
-
- HandlerObj = HandlerObj->AddressSpace.Next;
- }
- }
-
- return (FALSE);
-}
-
/*******************************************************************************
*
@@ -275,100 +126,6 @@ AcpiEvInitializeOpRegions (
/*******************************************************************************
*
- * FUNCTION: AcpiEvExecuteRegMethod
- *
- * PARAMETERS: RegionObj - Region object
- * Function - Passed to _REG: On (1) or Off (0)
- *
- * RETURN: Status
- *
- * DESCRIPTION: Execute _REG method for a region
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiEvExecuteRegMethod (
- ACPI_OPERAND_OBJECT *RegionObj,
- UINT32 Function)
-{
- ACPI_EVALUATE_INFO *Info;
- ACPI_OPERAND_OBJECT *Args[3];
- ACPI_OPERAND_OBJECT *RegionObj2;
- ACPI_STATUS Status;
-
-
- ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
-
-
- RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
- if (!RegionObj2)
- {
- return_ACPI_STATUS (AE_NOT_EXIST);
- }
-
- if (RegionObj2->Extra.Method_REG == NULL)
- {
- return_ACPI_STATUS (AE_OK);
- }
-
- /* Allocate and initialize the evaluation information block */
-
- Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
- if (!Info)
- {
- return_ACPI_STATUS (AE_NO_MEMORY);
- }
-
- Info->PrefixNode = RegionObj2->Extra.Method_REG;
- Info->Pathname = NULL;
- Info->Parameters = Args;
- Info->Flags = ACPI_IGNORE_RETURN_VALUE;
-
- /*
- * The _REG method has two arguments:
- *
- * Arg0 - Integer:
- * Operation region space ID Same value as RegionObj->Region.SpaceId
- *
- * Arg1 - Integer:
- * connection status 1 for connecting the handler, 0 for disconnecting
- * the handler (Passed as a parameter)
- */
- Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
- if (!Args[0])
- {
- Status = AE_NO_MEMORY;
- goto Cleanup1;
- }
-
- Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
- if (!Args[1])
- {
- Status = AE_NO_MEMORY;
- goto Cleanup2;
- }
-
- Args[2] = NULL; /* Terminate list */
-
- /* Execute the method, no return value */
-
- ACPI_DEBUG_EXEC (
- AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
-
- Status = AcpiNsEvaluate (Info);
- AcpiUtRemoveReference (Args[1]);
-
-Cleanup2:
- AcpiUtRemoveReference (Args[0]);
-
-Cleanup1:
- ACPI_FREE (Info);
- return_ACPI_STATUS (Status);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiEvAddressSpaceDispatch
*
* PARAMETERS: RegionObj - Internal region object
@@ -762,377 +519,94 @@ AcpiEvAttachRegion (
/*******************************************************************************
*
- * FUNCTION: AcpiEvInstallHandler
- *
- * PARAMETERS: WalkNamespace callback
- *
- * DESCRIPTION: This routine installs an address handler into objects that are
- * of type Region or Device.
- *
- * If the Object is a Device, and the device has a handler of
- * the same type then the search is terminated in that branch.
- *
- * This is because the existing handler is closer in proximity
- * to any more regions than the one we are trying to install.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiEvInstallHandler (
- ACPI_HANDLE ObjHandle,
- UINT32 Level,
- void *Context,
- void **ReturnValue)
-{
- ACPI_OPERAND_OBJECT *HandlerObj;
- ACPI_OPERAND_OBJECT *NextHandlerObj;
- ACPI_OPERAND_OBJECT *ObjDesc;
- ACPI_NAMESPACE_NODE *Node;
- ACPI_STATUS Status;
-
-
- ACPI_FUNCTION_NAME (EvInstallHandler);
-
-
- HandlerObj = (ACPI_OPERAND_OBJECT *) Context;
-
- /* Parameter validation */
-
- if (!HandlerObj)
- {
- return (AE_OK);
- }
-
- /* Convert and validate the device handle */
-
- Node = AcpiNsValidateHandle (ObjHandle);
- if (!Node)
- {
- return (AE_BAD_PARAMETER);
- }
-
- /*
- * We only care about regions and objects that are allowed to have
- * address space handlers
- */
- if ((Node->Type != ACPI_TYPE_DEVICE) &&
- (Node->Type != ACPI_TYPE_REGION) &&
- (Node != AcpiGbl_RootNode))
- {
- return (AE_OK);
- }
-
- /* Check for an existing internal object */
-
- ObjDesc = AcpiNsGetAttachedObject (Node);
- if (!ObjDesc)
- {
- /* No object, just exit */
-
- return (AE_OK);
- }
-
- /* Devices are handled different than regions */
-
- if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
- {
- /* Check if this Device already has a handler for this address space */
-
- NextHandlerObj = ObjDesc->Device.Handler;
- while (NextHandlerObj)
- {
- /* Found a handler, is it for the same address space? */
-
- if (NextHandlerObj->AddressSpace.SpaceId ==
- HandlerObj->AddressSpace.SpaceId)
- {
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Found handler for region [%s] in device %p(%p) "
- "handler %p\n",
- AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
- ObjDesc, NextHandlerObj, HandlerObj));
-
- /*
- * Since the object we found it on was a device, then it
- * means that someone has already installed a handler for
- * the branch of the namespace from this device on. Just
- * bail out telling the walk routine to not traverse this
- * branch. This preserves the scoping rule for handlers.
- */
- return (AE_CTRL_DEPTH);
- }
-
- /* Walk the linked list of handlers attached to this device */
-
- NextHandlerObj = NextHandlerObj->AddressSpace.Next;
- }
-
- /*
- * As long as the device didn't have a handler for this space we
- * don't care about it. We just ignore it and proceed.
- */
- return (AE_OK);
- }
-
- /* Object is a Region */
-
- if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
- {
- /* This region is for a different address space, just ignore it */
-
- return (AE_OK);
- }
-
- /*
- * Now we have a region and it is for the handler's address space type.
- *
- * First disconnect region for any previous handler (if any)
- */
- AcpiEvDetachRegion (ObjDesc, FALSE);
-
- /* Connect the region to the new handler */
-
- Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
- return (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiEvInstallSpaceHandler
+ * FUNCTION: AcpiEvExecuteRegMethod
*
- * PARAMETERS: Node - Namespace node for the device
- * SpaceId - The address space ID
- * Handler - Address of the handler
- * Setup - Address of the setup function
- * Context - Value passed to the handler on each access
+ * PARAMETERS: RegionObj - Region object
+ * Function - Passed to _REG: On (1) or Off (0)
*
* RETURN: Status
*
- * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
- * Assumes namespace is locked
+ * DESCRIPTION: Execute _REG method for a region
*
******************************************************************************/
ACPI_STATUS
-AcpiEvInstallSpaceHandler (
- ACPI_NAMESPACE_NODE *Node,
- ACPI_ADR_SPACE_TYPE SpaceId,
- ACPI_ADR_SPACE_HANDLER Handler,
- ACPI_ADR_SPACE_SETUP Setup,
- void *Context)
+AcpiEvExecuteRegMethod (
+ ACPI_OPERAND_OBJECT *RegionObj,
+ UINT32 Function)
{
- ACPI_OPERAND_OBJECT *ObjDesc;
- ACPI_OPERAND_OBJECT *HandlerObj;
+ ACPI_EVALUATE_INFO *Info;
+ ACPI_OPERAND_OBJECT *Args[3];
+ ACPI_OPERAND_OBJECT *RegionObj2;
ACPI_STATUS Status;
- ACPI_OBJECT_TYPE Type;
- UINT8 Flags = 0;
-
- ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
+ ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
- /*
- * This registration is valid for only the types below and the root. This
- * is where the default handlers get placed.
- */
- if ((Node->Type != ACPI_TYPE_DEVICE) &&
- (Node->Type != ACPI_TYPE_PROCESSOR) &&
- (Node->Type != ACPI_TYPE_THERMAL) &&
- (Node != AcpiGbl_RootNode))
- {
- Status = AE_BAD_PARAMETER;
- goto UnlockAndExit;
- }
- if (Handler == ACPI_DEFAULT_HANDLER)
+ RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
+ if (!RegionObj2)
{
- Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
-
- switch (SpaceId)
- {
- case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- Handler = AcpiExSystemMemorySpaceHandler;
- Setup = AcpiEvSystemMemoryRegionSetup;
- break;
-
- case ACPI_ADR_SPACE_SYSTEM_IO:
- Handler = AcpiExSystemIoSpaceHandler;
- Setup = AcpiEvIoSpaceRegionSetup;
- break;
-
- case ACPI_ADR_SPACE_PCI_CONFIG:
- Handler = AcpiExPciConfigSpaceHandler;
- Setup = AcpiEvPciConfigRegionSetup;
- break;
-
- case ACPI_ADR_SPACE_CMOS:
- Handler = AcpiExCmosSpaceHandler;
- Setup = AcpiEvCmosRegionSetup;
- break;
-
- case ACPI_ADR_SPACE_PCI_BAR_TARGET:
- Handler = AcpiExPciBarSpaceHandler;
- Setup = AcpiEvPciBarRegionSetup;
- break;
-
- case ACPI_ADR_SPACE_DATA_TABLE:
- Handler = AcpiExDataTableSpaceHandler;
- Setup = NULL;
- break;
-
- default:
- Status = AE_BAD_PARAMETER;
- goto UnlockAndExit;
- }
+ return_ACPI_STATUS (AE_NOT_EXIST);
}
- /* If the caller hasn't specified a setup routine, use the default */
-
- if (!Setup)
+ if (RegionObj2->Extra.Method_REG == NULL)
{
- Setup = AcpiEvDefaultRegionSetup;
+ return_ACPI_STATUS (AE_OK);
}
- /* Check for an existing internal object */
-
- ObjDesc = AcpiNsGetAttachedObject (Node);
- if (ObjDesc)
- {
- /*
- * The attached device object already exists. Make sure the handler
- * is not already installed.
- */
- HandlerObj = ObjDesc->Device.Handler;
-
- /* Walk the handler list for this device */
-
- while (HandlerObj)
- {
- /* Same SpaceId indicates a handler already installed */
-
- if (HandlerObj->AddressSpace.SpaceId == SpaceId)
- {
- if (HandlerObj->AddressSpace.Handler == Handler)
- {
- /*
- * It is (relatively) OK to attempt to install the SAME
- * handler twice. This can easily happen with the
- * PCI_Config space.
- */
- Status = AE_SAME_HANDLER;
- goto UnlockAndExit;
- }
- else
- {
- /* A handler is already installed */
-
- Status = AE_ALREADY_EXISTS;
- }
- goto UnlockAndExit;
- }
-
- /* Walk the linked list of handlers */
+ /* Allocate and initialize the evaluation information block */
- HandlerObj = HandlerObj->AddressSpace.Next;
- }
- }
- else
+ Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
+ if (!Info)
{
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Creating object on Device %p while installing handler\n", Node));
-
- /* ObjDesc does not exist, create one */
-
- if (Node->Type == ACPI_TYPE_ANY)
- {
- Type = ACPI_TYPE_DEVICE;
- }
- else
- {
- Type = Node->Type;
- }
-
- ObjDesc = AcpiUtCreateInternalObject (Type);
- if (!ObjDesc)
- {
- Status = AE_NO_MEMORY;
- goto UnlockAndExit;
- }
-
- /* Init new descriptor */
-
- ObjDesc->Common.Type = (UINT8) Type;
-
- /* Attach the new object to the Node */
-
- Status = AcpiNsAttachObject (Node, ObjDesc, Type);
-
- /* Remove local reference to the object */
-
- AcpiUtRemoveReference (ObjDesc);
-
- if (ACPI_FAILURE (Status))
- {
- goto UnlockAndExit;
- }
+ return_ACPI_STATUS (AE_NO_MEMORY);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
- AcpiUtGetRegionName (SpaceId), SpaceId,
- AcpiUtGetNodeName (Node), Node, ObjDesc));
+ Info->PrefixNode = RegionObj2->Extra.Method_REG;
+ Info->Pathname = NULL;
+ Info->Parameters = Args;
+ Info->Flags = ACPI_IGNORE_RETURN_VALUE;
/*
- * Install the handler
+ * The _REG method has two arguments:
+ *
+ * Arg0 - Integer:
+ * Operation region space ID Same value as RegionObj->Region.SpaceId
*
- * At this point there is no existing handler. Just allocate the object
- * for the handler and link it into the list.
+ * Arg1 - Integer:
+ * connection status 1 for connecting the handler, 0 for disconnecting
+ * the handler (Passed as a parameter)
*/
- HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
- if (!HandlerObj)
+ Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
+ if (!Args[0])
{
Status = AE_NO_MEMORY;
- goto UnlockAndExit;
+ goto Cleanup1;
}
- /* Init handler obj */
+ Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
+ if (!Args[1])
+ {
+ Status = AE_NO_MEMORY;
+ goto Cleanup2;
+ }
- HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
- HandlerObj->AddressSpace.HandlerFlags = Flags;
- HandlerObj->AddressSpace.RegionList = NULL;
- HandlerObj->AddressSpace.Node = Node;
- HandlerObj->AddressSpace.Handler = Handler;
- HandlerObj->AddressSpace.Context = Context;
- HandlerObj->AddressSpace.Setup = Setup;
+ Args[2] = NULL; /* Terminate list */
- /* Install at head of Device.AddressSpace list */
+ /* Execute the method, no return value */
- HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
+ ACPI_DEBUG_EXEC (
+ AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
- /*
- * The Device object is the first reference on the HandlerObj.
- * Each region that uses the handler adds a reference.
- */
- ObjDesc->Device.Handler = HandlerObj;
+ Status = AcpiNsEvaluate (Info);
+ AcpiUtRemoveReference (Args[1]);
- /*
- * Walk the namespace finding all of the regions this
- * handler will manage.
- *
- * Start at the device and search the branch toward
- * the leaf nodes until either the leaf is encountered or
- * a device is detected that has an address handler of the
- * same type.
- *
- * In either case, back up and search down the remainder
- * of the branch
- */
- Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
- HandlerObj, NULL);
+Cleanup2:
+ AcpiUtRemoveReference (Args[0]);
-UnlockAndExit:
+Cleanup1:
+ ACPI_FREE (Info);
return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/events/evrgnini.c b/sys/contrib/dev/acpica/components/events/evrgnini.c
index 28c367f..90a6b02 100644
--- a/sys/contrib/dev/acpica/components/events/evrgnini.c
+++ b/sys/contrib/dev/acpica/components/events/evrgnini.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evsci.c b/sys/contrib/dev/acpica/components/events/evsci.c
index 0e7a65a..340c400 100644
--- a/sys/contrib/dev/acpica/components/events/evsci.c
+++ b/sys/contrib/dev/acpica/components/events/evsci.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -101,7 +101,7 @@ AcpiEvSciXruptHandler (
InterruptHandled |= AcpiEvGpeDetect (GpeXruptList);
AcpiSciCount++;
- return_UINT32 (InterruptHandled);
+ return_VALUE (InterruptHandled);
}
@@ -137,7 +137,7 @@ AcpiEvGpeXruptHandler (
InterruptHandled |= AcpiEvGpeDetect (GpeXruptList);
- return_UINT32 (InterruptHandled);
+ return_VALUE (InterruptHandled);
}
diff --git a/sys/contrib/dev/acpica/components/events/evxface.c b/sys/contrib/dev/acpica/components/events/evxface.c
index 4027dce..dfc4790 100644
--- a/sys/contrib/dev/acpica/components/events/evxface.c
+++ b/sys/contrib/dev/acpica/components/events/evxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evxfevnt.c b/sys/contrib/dev/acpica/components/events/evxfevnt.c
index 4e87cde..e0f36e2 100644
--- a/sys/contrib/dev/acpica/components/events/evxfevnt.c
+++ b/sys/contrib/dev/acpica/components/events/evxfevnt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evxfgpe.c b/sys/contrib/dev/acpica/components/events/evxfgpe.c
index a07751c..c574b79 100644
--- a/sys/contrib/dev/acpica/components/events/evxfgpe.c
+++ b/sys/contrib/dev/acpica/components/events/evxfgpe.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/events/evxfregn.c b/sys/contrib/dev/acpica/components/events/evxfregn.c
index 59238ef..95e598b 100644
--- a/sys/contrib/dev/acpica/components/events/evxfregn.c
+++ b/sys/contrib/dev/acpica/components/events/evxfregn.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exconfig.c b/sys/contrib/dev/acpica/components/executer/exconfig.c
index 99848a9..fa85344 100644
--- a/sys/contrib/dev/acpica/components/executer/exconfig.c
+++ b/sys/contrib/dev/acpica/components/executer/exconfig.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,7 @@
#include <contrib/dev/acpica/include/actables.h>
#include <contrib/dev/acpica/include/acdispat.h>
#include <contrib/dev/acpica/include/acevents.h>
+#include <contrib/dev/acpica/include/amlcode.h>
#define _COMPONENT ACPI_EXECUTER
@@ -185,14 +186,15 @@ AcpiExLoadTableOp (
(Operand[1]->String.Length > ACPI_OEM_ID_SIZE) ||
(Operand[2]->String.Length > ACPI_OEM_TABLE_ID_SIZE))
{
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS (AE_AML_STRING_LIMIT);
}
/* Find the ACPI table in the RSDT/XSDT */
- Status = AcpiTbFindTable (Operand[0]->String.Pointer,
- Operand[1]->String.Pointer,
- Operand[2]->String.Pointer, &TableIndex);
+ Status = AcpiTbFindTable (
+ Operand[0]->String.Pointer,
+ Operand[1]->String.Pointer,
+ Operand[2]->String.Pointer, &TableIndex);
if (ACPI_FAILURE (Status))
{
if (Status != AE_NOT_FOUND)
@@ -237,8 +239,8 @@ AcpiExLoadTableOp (
if (Operand[4]->String.Length > 0)
{
- if ((Operand[4]->String.Pointer[0] != '\\') &&
- (Operand[4]->String.Pointer[0] != '^'))
+ if ((Operand[4]->String.Pointer[0] != AML_ROOT_PREFIX) &&
+ (Operand[4]->String.Pointer[0] != AML_PARENT_PREFIX))
{
/*
* Path is not absolute, so it will be relative to the node
@@ -299,7 +301,7 @@ AcpiExLoadTableOp (
}
*ReturnDesc = DdbHandle;
- return_ACPI_STATUS (Status);
+ return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/executer/exconvrt.c b/sys/contrib/dev/acpica/components/executer/exconvrt.c
index c34f326..f185371 100644
--- a/sys/contrib/dev/acpica/components/executer/exconvrt.c
+++ b/sys/contrib/dev/acpica/components/executer/exconvrt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -199,7 +199,7 @@ AcpiExConvertToInteger (
/* Save the Result */
- AcpiExTruncateFor32bitTable (ReturnDesc);
+ (void) AcpiExTruncateFor32bitTable (ReturnDesc);
*ResultDesc = ReturnDesc;
return_ACPI_STATUS (AE_OK);
}
diff --git a/sys/contrib/dev/acpica/components/executer/excreate.c b/sys/contrib/dev/acpica/components/executer/excreate.c
index b409633..1851957 100644
--- a/sys/contrib/dev/acpica/components/executer/excreate.c
+++ b/sys/contrib/dev/acpica/components/executer/excreate.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exdebug.c b/sys/contrib/dev/acpica/components/executer/exdebug.c
index 600118b..926f8e2 100644
--- a/sys/contrib/dev/acpica/components/executer/exdebug.c
+++ b/sys/contrib/dev/acpica/components/executer/exdebug.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exdump.c b/sys/contrib/dev/acpica/components/executer/exdump.c
index ec648f3..5d1527b 100644
--- a/sys/contrib/dev/acpica/components/executer/exdump.c
+++ b/sys/contrib/dev/acpica/components/executer/exdump.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -483,7 +483,9 @@ AcpiExDumpOperand (
ACPI_FUNCTION_NAME (ExDumpOperand)
- if (!((ACPI_LV_EXEC & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer)))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_EXEC, _COMPONENT))
{
return;
}
@@ -873,7 +875,9 @@ AcpiExDumpNamespaceNode (
if (!Flags)
{
- if (!((ACPI_LV_OBJECTS & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer)))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_OBJECTS, _COMPONENT))
{
return;
}
@@ -1080,7 +1084,9 @@ AcpiExDumpObjectDescriptor (
if (!Flags)
{
- if (!((ACPI_LV_OBJECTS & AcpiDbgLevel) && (_COMPONENT & AcpiDbgLayer)))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_OBJECTS, _COMPONENT))
{
return_VOID;
}
diff --git a/sys/contrib/dev/acpica/components/executer/exfield.c b/sys/contrib/dev/acpica/components/executer/exfield.c
index 4a7fa24..bade0f8 100644
--- a/sys/contrib/dev/acpica/components/executer/exfield.c
+++ b/sys/contrib/dev/acpica/components/executer/exfield.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exfldio.c b/sys/contrib/dev/acpica/components/executer/exfldio.c
index c8c3a33..f735aec 100644
--- a/sys/contrib/dev/acpica/components/executer/exfldio.c
+++ b/sys/contrib/dev/acpica/components/executer/exfldio.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exmisc.c b/sys/contrib/dev/acpica/components/executer/exmisc.c
index cf32b76..93f6487 100644
--- a/sys/contrib/dev/acpica/components/executer/exmisc.c
+++ b/sys/contrib/dev/acpica/components/executer/exmisc.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exmutex.c b/sys/contrib/dev/acpica/components/executer/exmutex.c
index c291449..a6e5e14 100644
--- a/sys/contrib/dev/acpica/components/executer/exmutex.c
+++ b/sys/contrib/dev/acpica/components/executer/exmutex.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exnames.c b/sys/contrib/dev/acpica/components/executer/exnames.c
index ce7fd66..16d89e3 100644
--- a/sys/contrib/dev/acpica/components/executer/exnames.c
+++ b/sys/contrib/dev/acpica/components/executer/exnames.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg1.c b/sys/contrib/dev/acpica/components/executer/exoparg1.c
index ac0860b..8ce02de 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg1.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg1.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg2.c b/sys/contrib/dev/acpica/components/executer/exoparg2.c
index 6e6e0d9..55defdc 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg2.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg2.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg3.c b/sys/contrib/dev/acpica/components/executer/exoparg3.c
index 33aa6fa..5823675 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg3.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg3.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exoparg6.c b/sys/contrib/dev/acpica/components/executer/exoparg6.c
index 3677b80..41201f3 100644
--- a/sys/contrib/dev/acpica/components/executer/exoparg6.c
+++ b/sys/contrib/dev/acpica/components/executer/exoparg6.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exprep.c b/sys/contrib/dev/acpica/components/executer/exprep.c
index adf67dc..97fe872 100644
--- a/sys/contrib/dev/acpica/components/executer/exprep.c
+++ b/sys/contrib/dev/acpica/components/executer/exprep.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -292,7 +292,7 @@ AcpiExDecodeFieldAccess (
ACPI_ERROR ((AE_INFO,
"Unknown field access type 0x%X",
Access));
- return_UINT32 (0);
+ return_VALUE (0);
}
if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD)
@@ -306,7 +306,7 @@ AcpiExDecodeFieldAccess (
}
*ReturnByteAlignment = ByteAlignment;
- return_UINT32 (BitLength);
+ return_VALUE (BitLength);
}
diff --git a/sys/contrib/dev/acpica/components/executer/exregion.c b/sys/contrib/dev/acpica/components/executer/exregion.c
index abbbd84..bc3417a 100644
--- a/sys/contrib/dev/acpica/components/executer/exregion.c
+++ b/sys/contrib/dev/acpica/components/executer/exregion.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exresnte.c b/sys/contrib/dev/acpica/components/executer/exresnte.c
index 43819a9..c8937ec 100644
--- a/sys/contrib/dev/acpica/components/executer/exresnte.c
+++ b/sys/contrib/dev/acpica/components/executer/exresnte.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exresolv.c b/sys/contrib/dev/acpica/components/executer/exresolv.c
index bebf170..74a1b73 100644
--- a/sys/contrib/dev/acpica/components/executer/exresolv.c
+++ b/sys/contrib/dev/acpica/components/executer/exresolv.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exresop.c b/sys/contrib/dev/acpica/components/executer/exresop.c
index d46c2d4..0b7af01 100644
--- a/sys/contrib/dev/acpica/components/executer/exresop.c
+++ b/sys/contrib/dev/acpica/components/executer/exresop.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exstore.c b/sys/contrib/dev/acpica/components/executer/exstore.c
index ab07400..ae842d2 100644
--- a/sys/contrib/dev/acpica/components/executer/exstore.c
+++ b/sys/contrib/dev/acpica/components/executer/exstore.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -515,13 +515,28 @@ AcpiExStoreObjectToNode (
default:
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Storing %s (%p) directly into node (%p) with no implicit conversion\n",
- AcpiUtGetObjectTypeName (SourceDesc), SourceDesc, Node));
+ "Storing [%s] (%p) directly into node [%s] (%p)"
+ " with no implicit conversion\n",
+ AcpiUtGetObjectTypeName (SourceDesc), SourceDesc,
+ AcpiUtGetObjectTypeName (TargetDesc), Node));
- /* No conversions for all other types. Just attach the source object */
+ /*
+ * No conversions for all other types. Directly store a copy of
+ * the source object. NOTE: This is a departure from the ACPI
+ * spec, which states "If conversion is impossible, abort the
+ * running control method".
+ *
+ * This code implements "If conversion is impossible, treat the
+ * Store operation as a CopyObject".
+ */
+ Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
- Status = AcpiNsAttachObject (Node, SourceDesc,
- SourceDesc->Common.Type);
+ Status = AcpiNsAttachObject (Node, NewDesc, NewDesc->Common.Type);
+ AcpiUtRemoveReference (NewDesc);
break;
}
diff --git a/sys/contrib/dev/acpica/components/executer/exstoren.c b/sys/contrib/dev/acpica/components/executer/exstoren.c
index 0848e4d..a8ae148 100644
--- a/sys/contrib/dev/acpica/components/executer/exstoren.c
+++ b/sys/contrib/dev/acpica/components/executer/exstoren.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -269,7 +269,7 @@ AcpiExStoreObjectToObject (
/* Truncate value if we are executing from a 32-bit ACPI table */
- AcpiExTruncateFor32bitTable (DestDesc);
+ (void) AcpiExTruncateFor32bitTable (DestDesc);
break;
case ACPI_TYPE_STRING:
diff --git a/sys/contrib/dev/acpica/components/executer/exstorob.c b/sys/contrib/dev/acpica/components/executer/exstorob.c
index 8cf9de5..c68263c 100644
--- a/sys/contrib/dev/acpica/components/executer/exstorob.c
+++ b/sys/contrib/dev/acpica/components/executer/exstorob.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exsystem.c b/sys/contrib/dev/acpica/components/executer/exsystem.c
index 89fe6be..cc18d80 100644
--- a/sys/contrib/dev/acpica/components/executer/exsystem.c
+++ b/sys/contrib/dev/acpica/components/executer/exsystem.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/executer/exutils.c b/sys/contrib/dev/acpica/components/executer/exutils.c
index f1e9435..fb78123 100644
--- a/sys/contrib/dev/acpica/components/executer/exutils.c
+++ b/sys/contrib/dev/acpica/components/executer/exutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -229,14 +229,14 @@ AcpiExRelinquishInterpreter (
*
* PARAMETERS: ObjDesc - Object to be truncated
*
- * RETURN: none
+ * RETURN: TRUE if a truncation was performed, FALSE otherwise.
*
* DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is
* 32-bit, as determined by the revision of the DSDT.
*
******************************************************************************/
-void
+BOOLEAN
AcpiExTruncateFor32bitTable (
ACPI_OPERAND_OBJECT *ObjDesc)
{
@@ -246,23 +246,27 @@ AcpiExTruncateFor32bitTable (
/*
* Object must be a valid number and we must be executing
- * a control method. NS node could be there for AML_INT_NAMEPATH_OP.
+ * a control method. Object could be NS node for AML_INT_NAMEPATH_OP.
*/
if ((!ObjDesc) ||
(ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) ||
(ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
{
- return;
+ return (FALSE);
}
- if (AcpiGbl_IntegerByteWidth == 4)
+ if ((AcpiGbl_IntegerByteWidth == 4) &&
+ (ObjDesc->Integer.Value > (UINT64) ACPI_UINT32_MAX))
{
/*
- * We are running a method that exists in a 32-bit ACPI table.
+ * We are executing in a 32-bit ACPI table.
* Truncate the value to 32 bits by zeroing out the upper 32-bit field
*/
ObjDesc->Integer.Value &= (UINT64) ACPI_UINT32_MAX;
+ return (TRUE);
}
+
+ return (FALSE);
}
@@ -387,7 +391,7 @@ AcpiExDigitsNeeded (
if (Value == 0)
{
- return_UINT32 (1);
+ return_VALUE (1);
}
CurrentValue = Value;
@@ -401,7 +405,7 @@ AcpiExDigitsNeeded (
NumDigits++;
}
- return_UINT32 (NumDigits);
+ return_VALUE (NumDigits);
}
diff --git a/sys/contrib/dev/acpica/components/hardware/hwacpi.c b/sys/contrib/dev/acpica/components/hardware/hwacpi.c
index e667a47..41830c3 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwacpi.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwacpi.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -141,13 +141,13 @@ AcpiHwSetMode (
Retry = 3000;
while (Retry)
{
- if (AcpiHwGetMode() == Mode)
+ if (AcpiHwGetMode () == Mode)
{
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n",
Mode));
return_ACPI_STATUS (AE_OK);
}
- AcpiOsStall(1000);
+ AcpiOsStall (ACPI_USEC_PER_MSEC);
Retry--;
}
@@ -186,22 +186,22 @@ AcpiHwGetMode (
*/
if (!AcpiGbl_FADT.SmiCommand)
{
- return_UINT32 (ACPI_SYS_MODE_ACPI);
+ return_VALUE (ACPI_SYS_MODE_ACPI);
}
Status = AcpiReadBitRegister (ACPI_BITREG_SCI_ENABLE, &Value);
if (ACPI_FAILURE (Status))
{
- return_UINT32 (ACPI_SYS_MODE_LEGACY);
+ return_VALUE (ACPI_SYS_MODE_LEGACY);
}
if (Value)
{
- return_UINT32 (ACPI_SYS_MODE_ACPI);
+ return_VALUE (ACPI_SYS_MODE_ACPI);
}
else
{
- return_UINT32 (ACPI_SYS_MODE_LEGACY);
+ return_VALUE (ACPI_SYS_MODE_LEGACY);
}
}
diff --git a/sys/contrib/dev/acpica/components/hardware/hwesleep.c b/sys/contrib/dev/acpica/components/hardware/hwesleep.c
index 4a9b7ec..6717801 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwesleep.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwesleep.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/hardware/hwgpe.c b/sys/contrib/dev/acpica/components/hardware/hwgpe.c
index afb5f87..c08ce2e 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwgpe.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwgpe.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -150,7 +150,7 @@ AcpiHwLowSetGpe (
break;
default:
- ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u\n", Action));
+ ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u", Action));
return (AE_BAD_PARAMETER);
}
diff --git a/sys/contrib/dev/acpica/components/hardware/hwpci.c b/sys/contrib/dev/acpica/components/hardware/hwpci.c
index 2b3ef1c..a89a3dd 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwpci.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwpci.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/hardware/hwregs.c b/sys/contrib/dev/acpica/components/hardware/hwregs.c
index c1440f4..8a7775b 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwregs.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwregs.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/hardware/hwsleep.c b/sys/contrib/dev/acpica/components/hardware/hwsleep.c
index 6da9e5a..0e6691a 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwsleep.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwsleep.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -180,7 +180,7 @@ AcpiHwLegacySleep (
* to still read the right value. Ideally, this block would go
* away entirely.
*/
- AcpiOsStall (10000000);
+ AcpiOsStall (10 * ACPI_USEC_PER_SEC);
Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_CONTROL,
SleepEnableRegInfo->AccessBitMask);
diff --git a/sys/contrib/dev/acpica/components/hardware/hwtimer.c b/sys/contrib/dev/acpica/components/hardware/hwtimer.c
index ea8f954..1a13f64 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwtimer.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwtimer.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -203,10 +203,11 @@ AcpiGetTimerDuration (
/*
* Compute Duration (Requires a 64-bit multiply and divide):
*
- * TimeElapsed = (DeltaTicks * 1000000) / PM_TIMER_FREQUENCY;
+ * TimeElapsed (microseconds) =
+ * (DeltaTicks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY;
*/
- Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * 1000000,
- PM_TIMER_FREQUENCY, &Quotient, NULL);
+ Status = AcpiUtShortDivide (((UINT64) DeltaTicks) * ACPI_USEC_PER_SEC,
+ ACPI_PM_TIMER_FREQUENCY, &Quotient, NULL);
*TimeElapsed = (UINT32) Quotient;
return_ACPI_STATUS (Status);
diff --git a/sys/contrib/dev/acpica/components/hardware/hwvalid.c b/sys/contrib/dev/acpica/components/hardware/hwvalid.c
index c1487d7..85a87d1 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwvalid.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwvalid.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/hardware/hwxface.c b/sys/contrib/dev/acpica/components/hardware/hwxface.c
index d169728..25ed994 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwxface.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -377,7 +377,7 @@ ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
*
* PARAMETERS: RegisterId - ID of ACPI Bit Register to access
* Value - Value to write to the register, in bit
- * position zero. The bit is automaticallly
+ * position zero. The bit is automatically
* shifted to the correct position.
*
* RETURN: Status
@@ -492,10 +492,33 @@ ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
* *SleepTypeA - Where SLP_TYPa is returned
* *SleepTypeB - Where SLP_TYPb is returned
*
- * RETURN: Status - ACPI status
+ * RETURN: Status
+ *
+ * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested
+ * sleep state via the appropriate \_Sx object.
+ *
+ * The sleep state package returned from the corresponding \_Sx_ object
+ * must contain at least one integer.
+ *
+ * March 2005:
+ * Added support for a package that contains two integers. This
+ * goes against the ACPI specification which defines this object as a
+ * package with one encoded DWORD integer. However, existing practice
+ * by many BIOS vendors is to return a package with 2 or more integer
+ * elements, at least one per sleep type (A/B).
+ *
+ * January 2013:
+ * Therefore, we must be prepared to accept a package with either a
+ * single integer or multiple integers.
*
- * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
- * state.
+ * The single integer DWORD format is as follows:
+ * BYTE 0 - Value for the PM1A SLP_TYP register
+ * BYTE 1 - Value for the PM1B SLP_TYP register
+ * BYTE 2-3 - Reserved
+ *
+ * The dual integer format is as follows:
+ * Integer 0 - Value for the PM1A SLP_TYP register
+ * Integer 1 - Value for the PM1A SLP_TYP register
*
******************************************************************************/
@@ -505,8 +528,9 @@ AcpiGetSleepTypeData (
UINT8 *SleepTypeA,
UINT8 *SleepTypeB)
{
- ACPI_STATUS Status = AE_OK;
+ ACPI_STATUS Status;
ACPI_EVALUATE_INFO *Info;
+ ACPI_OPERAND_OBJECT **Elements;
ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
@@ -515,8 +539,7 @@ AcpiGetSleepTypeData (
/* Validate parameters */
if ((SleepState > ACPI_S_STATES_MAX) ||
- !SleepTypeA ||
- !SleepTypeB)
+ !SleepTypeA || !SleepTypeB)
{
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
@@ -529,17 +552,14 @@ AcpiGetSleepTypeData (
return_ACPI_STATUS (AE_NO_MEMORY);
}
+ /*
+ * Evaluate the \_Sx namespace object containing the register values
+ * for this state
+ */
Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
-
- /* Evaluate the namespace object containing the values for this state */
-
Status = AcpiNsEvaluate (Info);
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "%s while evaluating SleepState [%s]\n",
- AcpiFormatException (Status), Info->Pathname));
-
goto Cleanup;
}
@@ -549,66 +569,70 @@ AcpiGetSleepTypeData (
{
ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
Info->Pathname));
- Status = AE_NOT_EXIST;
+ Status = AE_AML_NO_RETURN_VALUE;
+ goto Cleanup;
}
- /* It must be of type Package */
+ /* Return object must be of type Package */
- else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
+ if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
{
ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
Status = AE_AML_OPERAND_TYPE;
+ goto Cleanup1;
}
/*
- * The package must have at least two elements. NOTE (March 2005): This
- * goes against the current ACPI spec which defines this object as a
- * package with one encoded DWORD element. However, existing practice
- * by BIOS vendors seems to be to have 2 or more elements, at least
- * one per sleep type (A/B).
+ * Any warnings about the package length or the object types have
+ * already been issued by the predefined name module -- there is no
+ * need to repeat them here.
*/
- else if (Info->ReturnObject->Package.Count < 2)
+ Elements = Info->ReturnObject->Package.Elements;
+ switch (Info->ReturnObject->Package.Count)
{
- ACPI_ERROR ((AE_INFO,
- "Sleep State return package does not have at least two elements"));
- Status = AE_AML_NO_OPERAND;
- }
+ case 0:
+ Status = AE_AML_PACKAGE_LIMIT;
+ break;
- /* The first two elements must both be of type Integer */
+ case 1:
+ if (Elements[0]->Common.Type != ACPI_TYPE_INTEGER)
+ {
+ Status = AE_AML_OPERAND_TYPE;
+ break;
+ }
- else if (((Info->ReturnObject->Package.Elements[0])->Common.Type
- != ACPI_TYPE_INTEGER) ||
- ((Info->ReturnObject->Package.Elements[1])->Common.Type
- != ACPI_TYPE_INTEGER))
- {
- ACPI_ERROR ((AE_INFO,
- "Sleep State return package elements are not both Integers "
- "(%s, %s)",
- AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
- AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
- Status = AE_AML_OPERAND_TYPE;
- }
- else
- {
- /* Valid _Sx_ package size, type, and value */
+ /* A valid _Sx_ package with one integer */
+
+ *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
+ *SleepTypeB = (UINT8) (Elements[0]->Integer.Value >> 8);
+ break;
+
+ case 2:
+ default:
+ if ((Elements[0]->Common.Type != ACPI_TYPE_INTEGER) ||
+ (Elements[1]->Common.Type != ACPI_TYPE_INTEGER))
+ {
+ Status = AE_AML_OPERAND_TYPE;
+ break;
+ }
+
+ /* A valid _Sx_ package with two integers */
- *SleepTypeA = (UINT8)
- (Info->ReturnObject->Package.Elements[0])->Integer.Value;
- *SleepTypeB = (UINT8)
- (Info->ReturnObject->Package.Elements[1])->Integer.Value;
+ *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
+ *SleepTypeB = (UINT8) Elements[1]->Integer.Value;
+ break;
}
+Cleanup1:
+ AcpiUtRemoveReference (Info->ReturnObject);
+
+Cleanup:
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status,
- "While evaluating SleepState [%s], bad Sleep object %p type %s",
- Info->Pathname, Info->ReturnObject,
- AcpiUtGetObjectTypeName (Info->ReturnObject)));
+ "While evaluating Sleep State [%s]", Info->Pathname));
}
- AcpiUtRemoveReference (Info->ReturnObject);
-
-Cleanup:
ACPI_FREE (Info);
return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c
index e467164..3643799 100644
--- a/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c
+++ b/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -227,7 +227,7 @@ AcpiEnterSleepStateS4bios (
(UINT32) AcpiGbl_FADT.S4BiosRequest, 8);
do {
- AcpiOsStall(1000);
+ AcpiOsStall (ACPI_USEC_PER_MSEC);
Status = AcpiReadBitRegister (ACPI_BITREG_WAKE_STATUS, &InValue);
if (ACPI_FAILURE (Status))
{
diff --git a/sys/contrib/dev/acpica/components/namespace/nsaccess.c b/sys/contrib/dev/acpica/components/namespace/nsaccess.c
index 246628c..8dc8b5f 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsaccess.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsaccess.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsalloc.c b/sys/contrib/dev/acpica/components/namespace/nsalloc.c
index c76f422..ecec172 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsalloc.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsalloc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsdump.c b/sys/contrib/dev/acpica/components/namespace/nsdump.c
index fd82cdb..1411534 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsdump.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsdump.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,7 @@
#include <contrib/dev/acpica/include/acpi.h>
#include <contrib/dev/acpica/include/accommon.h>
#include <contrib/dev/acpica/include/acnamesp.h>
+#include <contrib/dev/acpica/include/acoutput.h>
#define _COMPONENT ACPI_NAMESPACE
@@ -92,7 +93,9 @@ AcpiNsPrintPathname (
ACPI_FUNCTION_NAME (NsPrintPathname);
- if (!(AcpiDbgLevel & ACPI_LV_NAMES) || !(AcpiDbgLayer & ACPI_NAMESPACE))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_NAMES, ACPI_NAMESPACE))
{
return;
}
@@ -151,7 +154,7 @@ AcpiNsDumpPathname (
/* Do this only if the requested debug level and component are enabled */
- if (!(AcpiDbgLevel & Level) || !(AcpiDbgLayer & Component))
+ if (!ACPI_IS_DEBUG_ENABLED (Level, Component))
{
return_VOID;
}
diff --git a/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c b/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c
index 4b93fbe..868b104 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsdumpdv.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nseval.c b/sys/contrib/dev/acpica/components/namespace/nseval.c
index a7a3577..61e783c 100644
--- a/sys/contrib/dev/acpica/components/namespace/nseval.c
+++ b/sys/contrib/dev/acpica/components/namespace/nseval.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsinit.c b/sys/contrib/dev/acpica/components/namespace/nsinit.c
index be2c60d..e9c9781 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsinit.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -104,7 +104,7 @@ AcpiNsInitializeObjects (
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
"**** Starting initialization of namespace objects ****\n"));
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "Completing Region/Field/Buffer/Package initialization:"));
+ "Completing Region/Field/Buffer/Package initialization:\n"));
/* Set all init info to zero */
@@ -121,7 +121,7 @@ AcpiNsInitializeObjects (
}
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\nInitialized %u/%u Regions %u/%u Fields %u/%u "
+ " Initialized %u/%u Regions %u/%u Fields %u/%u "
"Buffers %u/%u Packages (%u nodes)\n",
Info.OpRegionInit, Info.OpRegionCount,
Info.FieldInit, Info.FieldCount,
@@ -172,7 +172,7 @@ AcpiNsInitializeDevices (
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
"Initializing Device/Processor/Thermal objects "
- "by executing _INI methods:"));
+ "and executing _INI/_STA methods:\n"));
/* Tree analysis: find all subtrees that contain _INI methods */
@@ -230,7 +230,7 @@ AcpiNsInitializeDevices (
}
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
- "\nExecuted %u _INI methods requiring %u _STA executions "
+ " Executed %u _INI methods requiring %u _STA executions "
"(examined %u objects)\n",
Info.Num_INI, Info.Num_STA, Info.DeviceCount));
@@ -381,15 +381,6 @@ AcpiNsInitOneObject (
}
/*
- * Print a dot for each object unless we are going to print the entire
- * pathname
- */
- if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES))
- {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
- }
-
- /*
* We ignore errors from above, and always return OK, since we don't want
* to abort the walk on any single error.
*/
@@ -627,12 +618,6 @@ AcpiNsInitOneDevice (
if (ACPI_SUCCESS (Status))
{
WalkInfo->Num_INI++;
-
- if ((AcpiDbgLevel <= ACPI_LV_ALL_EXCEPTIONS) &&
- (!(AcpiDbgLevel & ACPI_LV_INFO)))
- {
- ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
- }
}
#ifdef ACPI_DEBUG_OUTPUT
diff --git a/sys/contrib/dev/acpica/components/namespace/nsload.c b/sys/contrib/dev/acpica/components/namespace/nsload.c
index 9cfa412..d29a891 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsload.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsnames.c b/sys/contrib/dev/acpica/components/namespace/nsnames.c
index cd2fc2c..cd4d440 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsnames.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsnames.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsobject.c b/sys/contrib/dev/acpica/components/namespace/nsobject.c
index 0920db3..b1d1f01 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsobject.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsobject.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsparse.c b/sys/contrib/dev/acpica/components/namespace/nsparse.c
index 231a440..f327f26 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsparse.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsparse.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nspredef.c b/sys/contrib/dev/acpica/components/namespace/nspredef.c
index fd003fb..8c65b84 100644
--- a/sys/contrib/dev/acpica/components/namespace/nspredef.c
+++ b/sys/contrib/dev/acpica/components/namespace/nspredef.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -78,35 +78,6 @@
/* Local prototypes */
static ACPI_STATUS
-AcpiNsCheckPackage (
- ACPI_PREDEFINED_DATA *Data,
- ACPI_OPERAND_OBJECT **ReturnObjectPtr);
-
-static ACPI_STATUS
-AcpiNsCheckPackageList (
- ACPI_PREDEFINED_DATA *Data,
- const ACPI_PREDEFINED_INFO *Package,
- ACPI_OPERAND_OBJECT **Elements,
- UINT32 Count);
-
-static ACPI_STATUS
-AcpiNsCheckPackageElements (
- ACPI_PREDEFINED_DATA *Data,
- ACPI_OPERAND_OBJECT **Elements,
- UINT8 Type1,
- UINT32 Count1,
- UINT8 Type2,
- UINT32 Count2,
- UINT32 StartIndex);
-
-static ACPI_STATUS
-AcpiNsCheckObjectType (
- ACPI_PREDEFINED_DATA *Data,
- ACPI_OPERAND_OBJECT **ReturnObjectPtr,
- UINT32 ExpectedBtypes,
- UINT32 PackageIndex);
-
-static ACPI_STATUS
AcpiNsCheckReference (
ACPI_PREDEFINED_DATA *Data,
ACPI_OPERAND_OBJECT *ReturnObject);
@@ -450,574 +421,6 @@ AcpiNsCheckForPredefinedName (
/*******************************************************************************
*
- * FUNCTION: AcpiNsCheckPackage
- *
- * PARAMETERS: Data - Pointer to validation data structure
- * ReturnObjectPtr - Pointer to the object returned from the
- * evaluation of a method or object
- *
- * RETURN: Status
- *
- * DESCRIPTION: Check a returned package object for the correct count and
- * correct type of all sub-objects.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiNsCheckPackage (
- ACPI_PREDEFINED_DATA *Data,
- ACPI_OPERAND_OBJECT **ReturnObjectPtr)
-{
- ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr;
- const ACPI_PREDEFINED_INFO *Package;
- ACPI_OPERAND_OBJECT **Elements;
- ACPI_STATUS Status = AE_OK;
- UINT32 ExpectedCount;
- UINT32 Count;
- UINT32 i;
-
-
- ACPI_FUNCTION_NAME (NsCheckPackage);
-
-
- /* The package info for this name is in the next table entry */
-
- Package = Data->Predefined + 1;
-
- ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
- "%s Validating return Package of Type %X, Count %X\n",
- Data->Pathname, Package->RetInfo.Type, ReturnObject->Package.Count));
-
- /*
- * For variable-length Packages, we can safely remove all embedded
- * and trailing NULL package elements
- */
- AcpiNsRemoveNullElements (Data, Package->RetInfo.Type, ReturnObject);
-
- /* Extract package count and elements array */
-
- Elements = ReturnObject->Package.Elements;
- Count = ReturnObject->Package.Count;
-
- /* The package must have at least one element, else invalid */
-
- if (!Count)
- {
- ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
- "Return Package has no elements (empty)"));
-
- return (AE_AML_OPERAND_VALUE);
- }
-
- /*
- * Decode the type of the expected package contents
- *
- * PTYPE1 packages contain no subpackages
- * PTYPE2 packages contain sub-packages
- */
- switch (Package->RetInfo.Type)
- {
- case ACPI_PTYPE1_FIXED:
-
- /*
- * The package count is fixed and there are no sub-packages
- *
- * If package is too small, exit.
- * If package is larger than expected, issue warning but continue
- */
- ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
- if (Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
- else if (Count > ExpectedCount)
- {
- ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
- "%s: Return Package is larger than needed - "
- "found %u, expected %u\n",
- Data->Pathname, Count, ExpectedCount));
- }
-
- /* Validate all elements of the returned package */
-
- Status = AcpiNsCheckPackageElements (Data, Elements,
- Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
- Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0);
- break;
-
-
- case ACPI_PTYPE1_VAR:
-
- /*
- * The package count is variable, there are no sub-packages, and all
- * elements must be of the same type
- */
- for (i = 0; i < Count; i++)
- {
- Status = AcpiNsCheckObjectType (Data, Elements,
- Package->RetInfo.ObjectType1, i);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- Elements++;
- }
- break;
-
-
- case ACPI_PTYPE1_OPTION:
-
- /*
- * The package count is variable, there are no sub-packages. There are
- * a fixed number of required elements, and a variable number of
- * optional elements.
- *
- * Check if package is at least as large as the minimum required
- */
- ExpectedCount = Package->RetInfo3.Count;
- if (Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
-
- /* Variable number of sub-objects */
-
- for (i = 0; i < Count; i++)
- {
- if (i < Package->RetInfo3.Count)
- {
- /* These are the required package elements (0, 1, or 2) */
-
- Status = AcpiNsCheckObjectType (Data, Elements,
- Package->RetInfo3.ObjectType[i], i);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- }
- else
- {
- /* These are the optional package elements */
-
- Status = AcpiNsCheckObjectType (Data, Elements,
- Package->RetInfo3.TailObjectType, i);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- }
- Elements++;
- }
- break;
-
-
- case ACPI_PTYPE2_REV_FIXED:
-
- /* First element is the (Integer) revision */
-
- Status = AcpiNsCheckObjectType (Data, Elements,
- ACPI_RTYPE_INTEGER, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- Elements++;
- Count--;
-
- /* Examine the sub-packages */
-
- Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
- break;
-
-
- case ACPI_PTYPE2_PKG_COUNT:
-
- /* First element is the (Integer) count of sub-packages to follow */
-
- Status = AcpiNsCheckObjectType (Data, Elements,
- ACPI_RTYPE_INTEGER, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- /*
- * Count cannot be larger than the parent package length, but allow it
- * to be smaller. The >= accounts for the Integer above.
- */
- ExpectedCount = (UINT32) (*Elements)->Integer.Value;
- if (ExpectedCount >= Count)
- {
- goto PackageTooSmall;
- }
-
- Count = ExpectedCount;
- Elements++;
-
- /* Examine the sub-packages */
-
- Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
- break;
-
-
- case ACPI_PTYPE2:
- case ACPI_PTYPE2_FIXED:
- case ACPI_PTYPE2_MIN:
- case ACPI_PTYPE2_COUNT:
- case ACPI_PTYPE2_FIX_VAR:
-
- /*
- * These types all return a single Package that consists of a
- * variable number of sub-Packages.
- *
- * First, ensure that the first element is a sub-Package. If not,
- * the BIOS may have incorrectly returned the object as a single
- * package instead of a Package of Packages (a common error if
- * there is only one entry). We may be able to repair this by
- * wrapping the returned Package with a new outer Package.
- */
- if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE))
- {
- /* Create the new outer package and populate it */
-
- Status = AcpiNsWrapWithPackage (Data, ReturnObject, ReturnObjectPtr);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- /* Update locals to point to the new package (of 1 element) */
-
- ReturnObject = *ReturnObjectPtr;
- Elements = ReturnObject->Package.Elements;
- Count = 1;
- }
-
- /* Examine the sub-packages */
-
- Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
- break;
-
-
- default:
-
- /* Should not get here if predefined info table is correct */
-
- ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
- "Invalid internal return type in table entry: %X",
- Package->RetInfo.Type));
-
- return (AE_AML_INTERNAL);
- }
-
- return (Status);
-
-
-PackageTooSmall:
-
- /* Error exit for the case with an incorrect package count */
-
- ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
- "Return Package is too small - found %u elements, expected %u",
- Count, ExpectedCount));
-
- return (AE_AML_OPERAND_VALUE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiNsCheckPackageList
- *
- * PARAMETERS: Data - Pointer to validation data structure
- * Package - Pointer to package-specific info for method
- * Elements - Element list of parent package. All elements
- * of this list should be of type Package.
- * Count - Count of subpackages
- *
- * RETURN: Status
- *
- * DESCRIPTION: Examine a list of subpackages
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiNsCheckPackageList (
- ACPI_PREDEFINED_DATA *Data,
- const ACPI_PREDEFINED_INFO *Package,
- ACPI_OPERAND_OBJECT **Elements,
- UINT32 Count)
-{
- ACPI_OPERAND_OBJECT *SubPackage;
- ACPI_OPERAND_OBJECT **SubElements;
- ACPI_STATUS Status;
- UINT32 ExpectedCount;
- UINT32 i;
- UINT32 j;
-
-
- /*
- * Validate each sub-Package in the parent Package
- *
- * NOTE: assumes list of sub-packages contains no NULL elements.
- * Any NULL elements should have been removed by earlier call
- * to AcpiNsRemoveNullElements.
- */
- for (i = 0; i < Count; i++)
- {
- SubPackage = *Elements;
- SubElements = SubPackage->Package.Elements;
- Data->ParentPackage = SubPackage;
-
- /* Each sub-object must be of type Package */
-
- Status = AcpiNsCheckObjectType (Data, &SubPackage,
- ACPI_RTYPE_PACKAGE, i);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- /* Examine the different types of expected sub-packages */
-
- Data->ParentPackage = SubPackage;
- switch (Package->RetInfo.Type)
- {
- case ACPI_PTYPE2:
- case ACPI_PTYPE2_PKG_COUNT:
- case ACPI_PTYPE2_REV_FIXED:
-
- /* Each subpackage has a fixed number of elements */
-
- ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
- if (SubPackage->Package.Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
-
- Status = AcpiNsCheckPackageElements (Data, SubElements,
- Package->RetInfo.ObjectType1,
- Package->RetInfo.Count1,
- Package->RetInfo.ObjectType2,
- Package->RetInfo.Count2, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- break;
-
-
- case ACPI_PTYPE2_FIX_VAR:
- /*
- * Each subpackage has a fixed number of elements and an
- * optional element
- */
- ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
- if (SubPackage->Package.Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
-
- Status = AcpiNsCheckPackageElements (Data, SubElements,
- Package->RetInfo.ObjectType1,
- Package->RetInfo.Count1,
- Package->RetInfo.ObjectType2,
- SubPackage->Package.Count - Package->RetInfo.Count1, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- break;
-
-
- case ACPI_PTYPE2_FIXED:
-
- /* Each sub-package has a fixed length */
-
- ExpectedCount = Package->RetInfo2.Count;
- if (SubPackage->Package.Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
-
- /* Check the type of each sub-package element */
-
- for (j = 0; j < ExpectedCount; j++)
- {
- Status = AcpiNsCheckObjectType (Data, &SubElements[j],
- Package->RetInfo2.ObjectType[j], j);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- }
- break;
-
-
- case ACPI_PTYPE2_MIN:
-
- /* Each sub-package has a variable but minimum length */
-
- ExpectedCount = Package->RetInfo.Count1;
- if (SubPackage->Package.Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
-
- /* Check the type of each sub-package element */
-
- Status = AcpiNsCheckPackageElements (Data, SubElements,
- Package->RetInfo.ObjectType1,
- SubPackage->Package.Count, 0, 0, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- break;
-
-
- case ACPI_PTYPE2_COUNT:
-
- /*
- * First element is the (Integer) count of elements, including
- * the count field (the ACPI name is NumElements)
- */
- Status = AcpiNsCheckObjectType (Data, SubElements,
- ACPI_RTYPE_INTEGER, 0);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
-
- /*
- * Make sure package is large enough for the Count and is
- * is as large as the minimum size
- */
- ExpectedCount = (UINT32) (*SubElements)->Integer.Value;
- if (SubPackage->Package.Count < ExpectedCount)
- {
- goto PackageTooSmall;
- }
- if (SubPackage->Package.Count < Package->RetInfo.Count1)
- {
- ExpectedCount = Package->RetInfo.Count1;
- goto PackageTooSmall;
- }
- if (ExpectedCount == 0)
- {
- /*
- * Either the NumEntries element was originally zero or it was
- * a NULL element and repaired to an Integer of value zero.
- * In either case, repair it by setting NumEntries to be the
- * actual size of the subpackage.
- */
- ExpectedCount = SubPackage->Package.Count;
- (*SubElements)->Integer.Value = ExpectedCount;
- }
-
- /* Check the type of each sub-package element */
-
- Status = AcpiNsCheckPackageElements (Data, (SubElements + 1),
- Package->RetInfo.ObjectType1,
- (ExpectedCount - 1), 0, 0, 1);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- break;
-
-
- default: /* Should not get here, type was validated by caller */
-
- return (AE_AML_INTERNAL);
- }
-
- Elements++;
- }
-
- return (AE_OK);
-
-
-PackageTooSmall:
-
- /* The sub-package count was smaller than required */
-
- ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
- "Return Sub-Package[%u] is too small - found %u elements, expected %u",
- i, SubPackage->Package.Count, ExpectedCount));
-
- return (AE_AML_OPERAND_VALUE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiNsCheckPackageElements
- *
- * PARAMETERS: Data - Pointer to validation data structure
- * Elements - Pointer to the package elements array
- * Type1 - Object type for first group
- * Count1 - Count for first group
- * Type2 - Object type for second group
- * Count2 - Count for second group
- * StartIndex - Start of the first group of elements
- *
- * RETURN: Status
- *
- * DESCRIPTION: Check that all elements of a package are of the correct object
- * type. Supports up to two groups of different object types.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiNsCheckPackageElements (
- ACPI_PREDEFINED_DATA *Data,
- ACPI_OPERAND_OBJECT **Elements,
- UINT8 Type1,
- UINT32 Count1,
- UINT8 Type2,
- UINT32 Count2,
- UINT32 StartIndex)
-{
- ACPI_OPERAND_OBJECT **ThisElement = Elements;
- ACPI_STATUS Status;
- UINT32 i;
-
-
- /*
- * Up to two groups of package elements are supported by the data
- * structure. All elements in each group must be of the same type.
- * The second group can have a count of zero.
- */
- for (i = 0; i < Count1; i++)
- {
- Status = AcpiNsCheckObjectType (Data, ThisElement,
- Type1, i + StartIndex);
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- ThisElement++;
- }
-
- for (i = 0; i < Count2; i++)
- {
- Status = AcpiNsCheckObjectType (Data, ThisElement,
- Type2, (i + Count1 + StartIndex));
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
- ThisElement++;
- }
-
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiNsCheckObjectType
*
* PARAMETERS: Data - Pointer to validation data structure
@@ -1035,7 +438,7 @@ AcpiNsCheckPackageElements (
*
******************************************************************************/
-static ACPI_STATUS
+ACPI_STATUS
AcpiNsCheckObjectType (
ACPI_PREDEFINED_DATA *Data,
ACPI_OPERAND_OBJECT **ReturnObjectPtr,
diff --git a/sys/contrib/dev/acpica/components/namespace/nsprepkg.c b/sys/contrib/dev/acpica/components/namespace/nsprepkg.c
new file mode 100644
index 0000000..7b65b80
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/namespace/nsprepkg.c
@@ -0,0 +1,639 @@
+/******************************************************************************
+ *
+ * Module Name: nsprepkg - Validation of package objects for predefined names
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acnamesp.h>
+#include <contrib/dev/acpica/include/acpredef.h>
+
+
+#define _COMPONENT ACPI_NAMESPACE
+ ACPI_MODULE_NAME ("nsprepkg")
+
+
+/* Local prototypes */
+
+static ACPI_STATUS
+AcpiNsCheckPackageList (
+ ACPI_PREDEFINED_DATA *Data,
+ const ACPI_PREDEFINED_INFO *Package,
+ ACPI_OPERAND_OBJECT **Elements,
+ UINT32 Count);
+
+static ACPI_STATUS
+AcpiNsCheckPackageElements (
+ ACPI_PREDEFINED_DATA *Data,
+ ACPI_OPERAND_OBJECT **Elements,
+ UINT8 Type1,
+ UINT32 Count1,
+ UINT8 Type2,
+ UINT32 Count2,
+ UINT32 StartIndex);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiNsCheckPackage
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * ReturnObjectPtr - Pointer to the object returned from the
+ * evaluation of a method or object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Check a returned package object for the correct count and
+ * correct type of all sub-objects.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiNsCheckPackage (
+ ACPI_PREDEFINED_DATA *Data,
+ ACPI_OPERAND_OBJECT **ReturnObjectPtr)
+{
+ ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr;
+ const ACPI_PREDEFINED_INFO *Package;
+ ACPI_OPERAND_OBJECT **Elements;
+ ACPI_STATUS Status = AE_OK;
+ UINT32 ExpectedCount;
+ UINT32 Count;
+ UINT32 i;
+
+
+ ACPI_FUNCTION_NAME (NsCheckPackage);
+
+
+ /* The package info for this name is in the next table entry */
+
+ Package = Data->Predefined + 1;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
+ "%s Validating return Package of Type %X, Count %X\n",
+ Data->Pathname, Package->RetInfo.Type, ReturnObject->Package.Count));
+
+ /*
+ * For variable-length Packages, we can safely remove all embedded
+ * and trailing NULL package elements
+ */
+ AcpiNsRemoveNullElements (Data, Package->RetInfo.Type, ReturnObject);
+
+ /* Extract package count and elements array */
+
+ Elements = ReturnObject->Package.Elements;
+ Count = ReturnObject->Package.Count;
+
+ /* The package must have at least one element, else invalid */
+
+ if (!Count)
+ {
+ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
+ "Return Package has no elements (empty)"));
+
+ return (AE_AML_OPERAND_VALUE);
+ }
+
+ /*
+ * Decode the type of the expected package contents
+ *
+ * PTYPE1 packages contain no subpackages
+ * PTYPE2 packages contain sub-packages
+ */
+ switch (Package->RetInfo.Type)
+ {
+ case ACPI_PTYPE1_FIXED:
+
+ /*
+ * The package count is fixed and there are no sub-packages
+ *
+ * If package is too small, exit.
+ * If package is larger than expected, issue warning but continue
+ */
+ ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
+ if (Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+ else if (Count > ExpectedCount)
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR,
+ "%s: Return Package is larger than needed - "
+ "found %u, expected %u\n",
+ Data->Pathname, Count, ExpectedCount));
+ }
+
+ /* Validate all elements of the returned package */
+
+ Status = AcpiNsCheckPackageElements (Data, Elements,
+ Package->RetInfo.ObjectType1, Package->RetInfo.Count1,
+ Package->RetInfo.ObjectType2, Package->RetInfo.Count2, 0);
+ break;
+
+
+ case ACPI_PTYPE1_VAR:
+
+ /*
+ * The package count is variable, there are no sub-packages, and all
+ * elements must be of the same type
+ */
+ for (i = 0; i < Count; i++)
+ {
+ Status = AcpiNsCheckObjectType (Data, Elements,
+ Package->RetInfo.ObjectType1, i);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ Elements++;
+ }
+ break;
+
+
+ case ACPI_PTYPE1_OPTION:
+
+ /*
+ * The package count is variable, there are no sub-packages. There are
+ * a fixed number of required elements, and a variable number of
+ * optional elements.
+ *
+ * Check if package is at least as large as the minimum required
+ */
+ ExpectedCount = Package->RetInfo3.Count;
+ if (Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+
+ /* Variable number of sub-objects */
+
+ for (i = 0; i < Count; i++)
+ {
+ if (i < Package->RetInfo3.Count)
+ {
+ /* These are the required package elements (0, 1, or 2) */
+
+ Status = AcpiNsCheckObjectType (Data, Elements,
+ Package->RetInfo3.ObjectType[i], i);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+ else
+ {
+ /* These are the optional package elements */
+
+ Status = AcpiNsCheckObjectType (Data, Elements,
+ Package->RetInfo3.TailObjectType, i);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+ Elements++;
+ }
+ break;
+
+
+ case ACPI_PTYPE2_REV_FIXED:
+
+ /* First element is the (Integer) revision */
+
+ Status = AcpiNsCheckObjectType (Data, Elements,
+ ACPI_RTYPE_INTEGER, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ Elements++;
+ Count--;
+
+ /* Examine the sub-packages */
+
+ Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
+ break;
+
+
+ case ACPI_PTYPE2_PKG_COUNT:
+
+ /* First element is the (Integer) count of sub-packages to follow */
+
+ Status = AcpiNsCheckObjectType (Data, Elements,
+ ACPI_RTYPE_INTEGER, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /*
+ * Count cannot be larger than the parent package length, but allow it
+ * to be smaller. The >= accounts for the Integer above.
+ */
+ ExpectedCount = (UINT32) (*Elements)->Integer.Value;
+ if (ExpectedCount >= Count)
+ {
+ goto PackageTooSmall;
+ }
+
+ Count = ExpectedCount;
+ Elements++;
+
+ /* Examine the sub-packages */
+
+ Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
+ break;
+
+
+ case ACPI_PTYPE2:
+ case ACPI_PTYPE2_FIXED:
+ case ACPI_PTYPE2_MIN:
+ case ACPI_PTYPE2_COUNT:
+ case ACPI_PTYPE2_FIX_VAR:
+
+ /*
+ * These types all return a single Package that consists of a
+ * variable number of sub-Packages.
+ *
+ * First, ensure that the first element is a sub-Package. If not,
+ * the BIOS may have incorrectly returned the object as a single
+ * package instead of a Package of Packages (a common error if
+ * there is only one entry). We may be able to repair this by
+ * wrapping the returned Package with a new outer Package.
+ */
+ if (*Elements && ((*Elements)->Common.Type != ACPI_TYPE_PACKAGE))
+ {
+ /* Create the new outer package and populate it */
+
+ Status = AcpiNsWrapWithPackage (Data, ReturnObject, ReturnObjectPtr);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Update locals to point to the new package (of 1 element) */
+
+ ReturnObject = *ReturnObjectPtr;
+ Elements = ReturnObject->Package.Elements;
+ Count = 1;
+ }
+
+ /* Examine the sub-packages */
+
+ Status = AcpiNsCheckPackageList (Data, Package, Elements, Count);
+ break;
+
+
+ default:
+
+ /* Should not get here if predefined info table is correct */
+
+ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
+ "Invalid internal return type in table entry: %X",
+ Package->RetInfo.Type));
+
+ return (AE_AML_INTERNAL);
+ }
+
+ return (Status);
+
+
+PackageTooSmall:
+
+ /* Error exit for the case with an incorrect package count */
+
+ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
+ "Return Package is too small - found %u elements, expected %u",
+ Count, ExpectedCount));
+
+ return (AE_AML_OPERAND_VALUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiNsCheckPackageList
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * Package - Pointer to package-specific info for method
+ * Elements - Element list of parent package. All elements
+ * of this list should be of type Package.
+ * Count - Count of subpackages
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Examine a list of subpackages
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiNsCheckPackageList (
+ ACPI_PREDEFINED_DATA *Data,
+ const ACPI_PREDEFINED_INFO *Package,
+ ACPI_OPERAND_OBJECT **Elements,
+ UINT32 Count)
+{
+ ACPI_OPERAND_OBJECT *SubPackage;
+ ACPI_OPERAND_OBJECT **SubElements;
+ ACPI_STATUS Status;
+ UINT32 ExpectedCount;
+ UINT32 i;
+ UINT32 j;
+
+
+ /*
+ * Validate each sub-Package in the parent Package
+ *
+ * NOTE: assumes list of sub-packages contains no NULL elements.
+ * Any NULL elements should have been removed by earlier call
+ * to AcpiNsRemoveNullElements.
+ */
+ for (i = 0; i < Count; i++)
+ {
+ SubPackage = *Elements;
+ SubElements = SubPackage->Package.Elements;
+ Data->ParentPackage = SubPackage;
+
+ /* Each sub-object must be of type Package */
+
+ Status = AcpiNsCheckObjectType (Data, &SubPackage,
+ ACPI_RTYPE_PACKAGE, i);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Examine the different types of expected sub-packages */
+
+ Data->ParentPackage = SubPackage;
+ switch (Package->RetInfo.Type)
+ {
+ case ACPI_PTYPE2:
+ case ACPI_PTYPE2_PKG_COUNT:
+ case ACPI_PTYPE2_REV_FIXED:
+
+ /* Each subpackage has a fixed number of elements */
+
+ ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
+ if (SubPackage->Package.Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+
+ Status = AcpiNsCheckPackageElements (Data, SubElements,
+ Package->RetInfo.ObjectType1,
+ Package->RetInfo.Count1,
+ Package->RetInfo.ObjectType2,
+ Package->RetInfo.Count2, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ break;
+
+
+ case ACPI_PTYPE2_FIX_VAR:
+ /*
+ * Each subpackage has a fixed number of elements and an
+ * optional element
+ */
+ ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2;
+ if (SubPackage->Package.Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+
+ Status = AcpiNsCheckPackageElements (Data, SubElements,
+ Package->RetInfo.ObjectType1,
+ Package->RetInfo.Count1,
+ Package->RetInfo.ObjectType2,
+ SubPackage->Package.Count - Package->RetInfo.Count1, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ break;
+
+
+ case ACPI_PTYPE2_FIXED:
+
+ /* Each sub-package has a fixed length */
+
+ ExpectedCount = Package->RetInfo2.Count;
+ if (SubPackage->Package.Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+
+ /* Check the type of each sub-package element */
+
+ for (j = 0; j < ExpectedCount; j++)
+ {
+ Status = AcpiNsCheckObjectType (Data, &SubElements[j],
+ Package->RetInfo2.ObjectType[j], j);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ }
+ break;
+
+
+ case ACPI_PTYPE2_MIN:
+
+ /* Each sub-package has a variable but minimum length */
+
+ ExpectedCount = Package->RetInfo.Count1;
+ if (SubPackage->Package.Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+
+ /* Check the type of each sub-package element */
+
+ Status = AcpiNsCheckPackageElements (Data, SubElements,
+ Package->RetInfo.ObjectType1,
+ SubPackage->Package.Count, 0, 0, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ break;
+
+
+ case ACPI_PTYPE2_COUNT:
+
+ /*
+ * First element is the (Integer) count of elements, including
+ * the count field (the ACPI name is NumElements)
+ */
+ Status = AcpiNsCheckObjectType (Data, SubElements,
+ ACPI_RTYPE_INTEGER, 0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /*
+ * Make sure package is large enough for the Count and is
+ * is as large as the minimum size
+ */
+ ExpectedCount = (UINT32) (*SubElements)->Integer.Value;
+ if (SubPackage->Package.Count < ExpectedCount)
+ {
+ goto PackageTooSmall;
+ }
+ if (SubPackage->Package.Count < Package->RetInfo.Count1)
+ {
+ ExpectedCount = Package->RetInfo.Count1;
+ goto PackageTooSmall;
+ }
+ if (ExpectedCount == 0)
+ {
+ /*
+ * Either the NumEntries element was originally zero or it was
+ * a NULL element and repaired to an Integer of value zero.
+ * In either case, repair it by setting NumEntries to be the
+ * actual size of the subpackage.
+ */
+ ExpectedCount = SubPackage->Package.Count;
+ (*SubElements)->Integer.Value = ExpectedCount;
+ }
+
+ /* Check the type of each sub-package element */
+
+ Status = AcpiNsCheckPackageElements (Data, (SubElements + 1),
+ Package->RetInfo.ObjectType1,
+ (ExpectedCount - 1), 0, 0, 1);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ break;
+
+
+ default: /* Should not get here, type was validated by caller */
+
+ return (AE_AML_INTERNAL);
+ }
+
+ Elements++;
+ }
+
+ return (AE_OK);
+
+
+PackageTooSmall:
+
+ /* The sub-package count was smaller than required */
+
+ ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags,
+ "Return Sub-Package[%u] is too small - found %u elements, expected %u",
+ i, SubPackage->Package.Count, ExpectedCount));
+
+ return (AE_AML_OPERAND_VALUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiNsCheckPackageElements
+ *
+ * PARAMETERS: Data - Pointer to validation data structure
+ * Elements - Pointer to the package elements array
+ * Type1 - Object type for first group
+ * Count1 - Count for first group
+ * Type2 - Object type for second group
+ * Count2 - Count for second group
+ * StartIndex - Start of the first group of elements
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Check that all elements of a package are of the correct object
+ * type. Supports up to two groups of different object types.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiNsCheckPackageElements (
+ ACPI_PREDEFINED_DATA *Data,
+ ACPI_OPERAND_OBJECT **Elements,
+ UINT8 Type1,
+ UINT32 Count1,
+ UINT8 Type2,
+ UINT32 Count2,
+ UINT32 StartIndex)
+{
+ ACPI_OPERAND_OBJECT **ThisElement = Elements;
+ ACPI_STATUS Status;
+ UINT32 i;
+
+
+ /*
+ * Up to two groups of package elements are supported by the data
+ * structure. All elements in each group must be of the same type.
+ * The second group can have a count of zero.
+ */
+ for (i = 0; i < Count1; i++)
+ {
+ Status = AcpiNsCheckObjectType (Data, ThisElement,
+ Type1, i + StartIndex);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ ThisElement++;
+ }
+
+ for (i = 0; i < Count2; i++)
+ {
+ Status = AcpiNsCheckObjectType (Data, ThisElement,
+ Type2, (i + Count1 + StartIndex));
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+ ThisElement++;
+ }
+
+ return (AE_OK);
+}
diff --git a/sys/contrib/dev/acpica/components/namespace/nsrepair.c b/sys/contrib/dev/acpica/components/namespace/nsrepair.c
index 7a1ee9f..c5c9309 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsrepair.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsrepair.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsrepair2.c b/sys/contrib/dev/acpica/components/namespace/nsrepair2.c
index 06286f1..a6559f4 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsrepair2.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsrepair2.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nssearch.c b/sys/contrib/dev/acpica/components/namespace/nssearch.c
index 93e060c..255956f 100644
--- a/sys/contrib/dev/acpica/components/namespace/nssearch.c
+++ b/sys/contrib/dev/acpica/components/namespace/nssearch.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsutils.c b/sys/contrib/dev/acpica/components/namespace/nsutils.c
index 1003098..070ed26 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsutils.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsutils.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,10 +54,6 @@
/* Local prototypes */
-static BOOLEAN
-AcpiNsValidPathSeparator (
- char Sep);
-
#ifdef ACPI_OBSOLETE_FUNCTIONS
ACPI_NAME
AcpiNsFindParentName (
@@ -112,48 +108,6 @@ AcpiNsPrintNodePathname (
/*******************************************************************************
*
- * FUNCTION: AcpiNsValidRootPrefix
- *
- * PARAMETERS: Prefix - Character to be checked
- *
- * RETURN: TRUE if a valid prefix
- *
- * DESCRIPTION: Check if a character is a valid ACPI Root prefix
- *
- ******************************************************************************/
-
-BOOLEAN
-AcpiNsValidRootPrefix (
- char Prefix)
-{
-
- return ((BOOLEAN) (Prefix == '\\'));
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiNsValidPathSeparator
- *
- * PARAMETERS: Sep - Character to be checked
- *
- * RETURN: TRUE if a valid path separator
- *
- * DESCRIPTION: Check if a character is a valid ACPI path separator
- *
- ******************************************************************************/
-
-static BOOLEAN
-AcpiNsValidPathSeparator (
- char Sep)
-{
-
- return ((BOOLEAN) (Sep == '.'));
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiNsGetType
*
* PARAMETERS: Node - Parent Node to be examined
@@ -174,10 +128,10 @@ AcpiNsGetType (
if (!Node)
{
ACPI_WARNING ((AE_INFO, "Null Node parameter"));
- return_UINT32 (ACPI_TYPE_ANY);
+ return_VALUE (ACPI_TYPE_ANY);
}
- return_UINT32 ((ACPI_OBJECT_TYPE) Node->Type);
+ return_VALUE (Node->Type);
}
@@ -206,10 +160,10 @@ AcpiNsLocal (
/* Type code out of range */
ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type));
- return_UINT32 (ACPI_NS_NORMAL);
+ return_VALUE (ACPI_NS_NORMAL);
}
- return_UINT32 ((UINT32) AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
+ return_VALUE (AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL);
}
@@ -250,14 +204,14 @@ AcpiNsGetInternalNameLength (
*
* strlen() + 1 covers the first NameSeg, which has no path separator
*/
- if (AcpiNsValidRootPrefix (*NextExternalChar))
+ if (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
{
Info->FullyQualified = TRUE;
NextExternalChar++;
/* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */
- while (AcpiNsValidRootPrefix (*NextExternalChar))
+ while (ACPI_IS_ROOT_PREFIX (*NextExternalChar))
{
NextExternalChar++;
}
@@ -266,7 +220,7 @@ AcpiNsGetInternalNameLength (
{
/* Handle Carat prefixes */
- while (*NextExternalChar == '^')
+ while (ACPI_IS_PARENT_PREFIX (*NextExternalChar))
{
Info->NumCarats++;
NextExternalChar++;
@@ -283,7 +237,7 @@ AcpiNsGetInternalNameLength (
Info->NumSegments = 1;
for (i = 0; NextExternalChar[i]; i++)
{
- if (AcpiNsValidPathSeparator (NextExternalChar[i]))
+ if (ACPI_IS_PATH_SEPARATOR (NextExternalChar[i]))
{
Info->NumSegments++;
}
@@ -328,7 +282,7 @@ AcpiNsBuildInternalName (
if (Info->FullyQualified)
{
- InternalName[0] = '\\';
+ InternalName[0] = AML_ROOT_PREFIX;
if (NumSegments <= 1)
{
@@ -357,7 +311,7 @@ AcpiNsBuildInternalName (
{
for (i = 0; i < Info->NumCarats; i++)
{
- InternalName[i] = '^';
+ InternalName[i] = AML_PARENT_PREFIX;
}
}
@@ -384,7 +338,7 @@ AcpiNsBuildInternalName (
{
for (i = 0; i < ACPI_NAME_SIZE; i++)
{
- if (AcpiNsValidPathSeparator (*ExternalName) ||
+ if (ACPI_IS_PATH_SEPARATOR (*ExternalName) ||
(*ExternalName == 0))
{
/* Pad the segment with underscore(s) if segment is short */
@@ -402,7 +356,7 @@ AcpiNsBuildInternalName (
/* Now we must have a path separator, or the pathname is bad */
- if (!AcpiNsValidPathSeparator (*ExternalName) &&
+ if (!ACPI_IS_PATH_SEPARATOR (*ExternalName) &&
(*ExternalName != 0))
{
return_ACPI_STATUS (AE_BAD_PATHNAME);
@@ -542,14 +496,14 @@ AcpiNsExternalizeName (
switch (InternalName[0])
{
- case '\\':
+ case AML_ROOT_PREFIX:
PrefixLength = 1;
break;
- case '^':
+ case AML_PARENT_PREFIX:
for (i = 0; i < InternalNameLength; i++)
{
- if (InternalName[i] == '^')
+ if (ACPI_IS_PARENT_PREFIX (InternalName[i]))
{
PrefixLength = i + 1;
}
@@ -829,6 +783,8 @@ AcpiNsGetNode (
ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));
+ /* Simplest case is a null pathname */
+
if (!Pathname)
{
*ReturnNode = PrefixNode;
@@ -839,6 +795,14 @@ AcpiNsGetNode (
return_ACPI_STATUS (AE_OK);
}
+ /* Quick check for a reference to the root */
+
+ if (ACPI_IS_ROOT_PREFIX (Pathname[0]) && (!Pathname[1]))
+ {
+ *ReturnNode = AcpiGbl_RootNode;
+ return_ACPI_STATUS (AE_OK);
+ }
+
/* Convert path to internal representation */
Status = AcpiNsInternalizeName (Pathname, &InternalPath);
diff --git a/sys/contrib/dev/acpica/components/namespace/nswalk.c b/sys/contrib/dev/acpica/components/namespace/nswalk.c
index 008a957..3b42d91 100644
--- a/sys/contrib/dev/acpica/components/namespace/nswalk.c
+++ b/sys/contrib/dev/acpica/components/namespace/nswalk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfeval.c b/sys/contrib/dev/acpica/components/namespace/nsxfeval.c
index 5d3204d..ff580be 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsxfeval.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsxfeval.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -255,7 +255,7 @@ AcpiEvaluateObject (
* 3) Valid handle
*/
if ((Pathname) &&
- (AcpiNsValidRootPrefix (Pathname[0])))
+ (ACPI_IS_ROOT_PREFIX (Pathname[0])))
{
/* The path is fully qualified, just evaluate by name */
diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfname.c b/sys/contrib/dev/acpica/components/namespace/nsxfname.c
index a6e502b1..582ecf3 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsxfname.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsxfname.c
@@ -6,7 +6,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -120,7 +120,7 @@ AcpiGetHandle (
*
* Error for <null Parent + relative path>
*/
- if (AcpiNsValidRootPrefix (Pathname[0]))
+ if (ACPI_IS_ROOT_PREFIX (Pathname[0]))
{
/* Pathname is fully qualified (starts with '\') */
diff --git a/sys/contrib/dev/acpica/components/namespace/nsxfobj.c b/sys/contrib/dev/acpica/components/namespace/nsxfobj.c
index fb0df50..153dfaa 100644
--- a/sys/contrib/dev/acpica/components/namespace/nsxfobj.c
+++ b/sys/contrib/dev/acpica/components/namespace/nsxfobj.c
@@ -6,7 +6,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/parser/psargs.c b/sys/contrib/dev/acpica/components/parser/psargs.c
index 9bddc21..c57f485 100644
--- a/sys/contrib/dev/acpica/components/parser/psargs.c
+++ b/sys/contrib/dev/acpica/components/parser/psargs.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -118,7 +118,7 @@ AcpiPsGetNextPackageLength (
/* Byte 0 is a special case, either bits [0:3] or [0:5] are used */
PackageLength |= (Aml[0] & ByteZeroMask);
- return_UINT32 (PackageLength);
+ return_VALUE (PackageLength);
}
@@ -182,7 +182,8 @@ AcpiPsGetNextNamestring (
/* Point past any namestring prefix characters (backslash or carat) */
- while (AcpiPsIsPrefixChar (*End))
+ while (ACPI_IS_ROOT_PREFIX (*End) ||
+ ACPI_IS_PARENT_PREFIX (*End))
{
End++;
}
@@ -868,7 +869,8 @@ AcpiPsGetNextArg (
Subop = AcpiPsPeekOpcode (ParserState);
if (Subop == 0 ||
AcpiPsIsLeadingChar (Subop) ||
- AcpiPsIsPrefixChar (Subop))
+ ACPI_IS_ROOT_PREFIX (Subop) ||
+ ACPI_IS_PARENT_PREFIX (Subop))
{
/* NullName or NameString */
diff --git a/sys/contrib/dev/acpica/components/parser/psloop.c b/sys/contrib/dev/acpica/components/parser/psloop.c
index 814bd93..4472bf1 100644
--- a/sys/contrib/dev/acpica/components/parser/psloop.c
+++ b/sys/contrib/dev/acpica/components/parser/psloop.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,46 +59,15 @@
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME ("psloop")
-static UINT32 AcpiGbl_Depth = 0;
-
/* Local prototypes */
static ACPI_STATUS
-AcpiPsGetAmlOpcode (
- ACPI_WALK_STATE *WalkState);
-
-static ACPI_STATUS
-AcpiPsBuildNamedOp (
- ACPI_WALK_STATE *WalkState,
- UINT8 *AmlOpStart,
- ACPI_PARSE_OBJECT *UnnamedOp,
- ACPI_PARSE_OBJECT **Op);
-
-static ACPI_STATUS
-AcpiPsCreateOp (
- ACPI_WALK_STATE *WalkState,
- UINT8 *AmlOpStart,
- ACPI_PARSE_OBJECT **NewOp);
-
-static ACPI_STATUS
AcpiPsGetArguments (
ACPI_WALK_STATE *WalkState,
UINT8 *AmlOpStart,
ACPI_PARSE_OBJECT *Op);
-static ACPI_STATUS
-AcpiPsCompleteOp (
- ACPI_WALK_STATE *WalkState,
- ACPI_PARSE_OBJECT **Op,
- ACPI_STATUS Status);
-
-static ACPI_STATUS
-AcpiPsCompleteFinalOp (
- ACPI_WALK_STATE *WalkState,
- ACPI_PARSE_OBJECT *Op,
- ACPI_STATUS Status);
-
static void
AcpiPsLinkModuleCode (
ACPI_PARSE_OBJECT *ParentOp,
@@ -109,341 +78,6 @@ AcpiPsLinkModuleCode (
/*******************************************************************************
*
- * FUNCTION: AcpiPsGetAmlOpcode
- *
- * PARAMETERS: WalkState - Current state
- *
- * RETURN: Status
- *
- * DESCRIPTION: Extract the next AML opcode from the input stream.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiPsGetAmlOpcode (
- ACPI_WALK_STATE *WalkState)
-{
-
- ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState);
-
-
- WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
- WalkState->ParserState.AmlStart);
- WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState));
-
- /*
- * First cut to determine what we have found:
- * 1) A valid AML opcode
- * 2) A name string
- * 3) An unknown/invalid opcode
- */
- WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
-
- switch (WalkState->OpInfo->Class)
- {
- case AML_CLASS_ASCII:
- case AML_CLASS_PREFIX:
- /*
- * Starts with a valid prefix or ASCII char, this is a name
- * string. Convert the bare name string to a namepath.
- */
- WalkState->Opcode = AML_INT_NAMEPATH_OP;
- WalkState->ArgTypes = ARGP_NAMESTRING;
- break;
-
- case AML_CLASS_UNKNOWN:
-
- /* The opcode is unrecognized. Complain and skip unknown opcodes */
-
- if (WalkState->PassNumber == 2)
- {
- ACPI_ERROR ((AE_INFO,
- "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
- WalkState->Opcode,
- (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER))));
-
- ACPI_DUMP_BUFFER (WalkState->ParserState.Aml - 16, 48);
-
-#ifdef ACPI_ASL_COMPILER
- /*
- * This is executed for the disassembler only. Output goes
- * to the disassembled ASL output file.
- */
- AcpiOsPrintf (
- "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
- WalkState->Opcode,
- (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER)));
-
- /* Dump the context surrounding the invalid opcode */
-
- AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16),
- 48, DB_BYTE_DISPLAY,
- WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16);
- AcpiOsPrintf (" */\n");
-#endif
- }
-
- /* Increment past one-byte or two-byte opcode */
-
- WalkState->ParserState.Aml++;
- if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */
- {
- WalkState->ParserState.Aml++;
- }
-
- return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
-
- default:
-
- /* Found opcode info, this is a normal opcode */
-
- WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
- WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
- break;
- }
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsBuildNamedOp
- *
- * PARAMETERS: WalkState - Current state
- * AmlOpStart - Begin of named Op in AML
- * UnnamedOp - Early Op (not a named Op)
- * Op - Returned Op
- *
- * RETURN: Status
- *
- * DESCRIPTION: Parse a named Op
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiPsBuildNamedOp (
- ACPI_WALK_STATE *WalkState,
- UINT8 *AmlOpStart,
- ACPI_PARSE_OBJECT *UnnamedOp,
- ACPI_PARSE_OBJECT **Op)
-{
- ACPI_STATUS Status = AE_OK;
- ACPI_PARSE_OBJECT *Arg = NULL;
-
-
- ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState);
-
-
- UnnamedOp->Common.Value.Arg = NULL;
- UnnamedOp->Common.ArgListLength = 0;
- UnnamedOp->Common.AmlOpcode = WalkState->Opcode;
-
- /*
- * Get and append arguments until we find the node that contains
- * the name (the type ARGP_NAME).
- */
- while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
- (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
- {
- Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
- GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- AcpiPsAppendArg (UnnamedOp, Arg);
- INCREMENT_ARG_LIST (WalkState->ArgTypes);
- }
-
- /*
- * Make sure that we found a NAME and didn't run out of arguments
- */
- if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
- {
- return_ACPI_STATUS (AE_AML_NO_OPERAND);
- }
-
- /* We know that this arg is a name, move to next arg */
-
- INCREMENT_ARG_LIST (WalkState->ArgTypes);
-
- /*
- * Find the object. This will either insert the object into
- * the namespace or simply look it up
- */
- WalkState->Op = NULL;
-
- Status = WalkState->DescendingCallback (WalkState, Op);
- if (ACPI_FAILURE (Status))
- {
- ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog"));
- return_ACPI_STATUS (Status);
- }
-
- if (!*Op)
- {
- return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
- }
-
- Status = AcpiPsNextParseState (WalkState, *Op, Status);
- if (ACPI_FAILURE (Status))
- {
- if (Status == AE_CTRL_PENDING)
- {
- return_ACPI_STATUS (AE_CTRL_PARSE_PENDING);
- }
- return_ACPI_STATUS (Status);
- }
-
- AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg);
- AcpiGbl_Depth++;
-
- if ((*Op)->Common.AmlOpcode == AML_REGION_OP ||
- (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP)
- {
- /*
- * Defer final parsing of an OperationRegion body, because we don't
- * have enough info in the first pass to parse it correctly (i.e.,
- * there may be method calls within the TermArg elements of the body.)
- *
- * However, we must continue parsing because the opregion is not a
- * standalone package -- we don't know where the end is at this point.
- *
- * (Length is unknown until parse of the body complete)
- */
- (*Op)->Named.Data = AmlOpStart;
- (*Op)->Named.Length = 0;
- }
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsCreateOp
- *
- * PARAMETERS: WalkState - Current state
- * AmlOpStart - Op start in AML
- * NewOp - Returned Op
- *
- * RETURN: Status
- *
- * DESCRIPTION: Get Op from AML
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiPsCreateOp (
- ACPI_WALK_STATE *WalkState,
- UINT8 *AmlOpStart,
- ACPI_PARSE_OBJECT **NewOp)
-{
- ACPI_STATUS Status = AE_OK;
- ACPI_PARSE_OBJECT *Op;
- ACPI_PARSE_OBJECT *NamedOp = NULL;
- ACPI_PARSE_OBJECT *ParentScope;
- UINT8 ArgumentCount;
- const ACPI_OPCODE_INFO *OpInfo;
-
-
- ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);
-
-
- Status = AcpiPsGetAmlOpcode (WalkState);
- if (Status == AE_CTRL_PARSE_CONTINUE)
- {
- return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
- }
-
- /* Create Op structure and append to parent's argument list */
-
- WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
- Op = AcpiPsAllocOp (WalkState->Opcode);
- if (!Op)
- {
- return_ACPI_STATUS (AE_NO_MEMORY);
- }
-
- if (WalkState->OpInfo->Flags & AML_NAMED)
- {
- Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
- AcpiPsFreeOp (Op);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- *NewOp = NamedOp;
- return_ACPI_STATUS (AE_OK);
- }
-
- /* Not a named opcode, just allocate Op and append to parent */
-
- if (WalkState->OpInfo->Flags & AML_CREATE)
- {
- /*
- * Backup to beginning of CreateXXXfield declaration
- * BodyLength is unknown until we parse the body
- */
- Op->Named.Data = AmlOpStart;
- Op->Named.Length = 0;
- }
-
- if (WalkState->Opcode == AML_BANK_FIELD_OP)
- {
- /*
- * Backup to beginning of BankField declaration
- * BodyLength is unknown until we parse the body
- */
- Op->Named.Data = AmlOpStart;
- Op->Named.Length = 0;
- }
-
- ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
- AcpiPsAppendArg (ParentScope, Op);
-
- if (ParentScope)
- {
- OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
- if (OpInfo->Flags & AML_HAS_TARGET)
- {
- ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
- if (ParentScope->Common.ArgListLength > ArgumentCount)
- {
- Op->Common.Flags |= ACPI_PARSEOP_TARGET;
- }
- }
- else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
- {
- Op->Common.Flags |= ACPI_PARSEOP_TARGET;
- }
- }
-
- if (WalkState->DescendingCallback != NULL)
- {
- /*
- * Find the object. This will either insert the object into
- * the namespace or simply look it up
- */
- WalkState->Op = *NewOp = Op;
-
- Status = WalkState->DescendingCallback (WalkState, &Op);
- Status = AcpiPsNextParseState (WalkState, Op, Status);
- if (Status == AE_CTRL_PENDING)
- {
- Status = AE_CTRL_PARSE_PENDING;
- }
- }
-
- return_ACPI_STATUS (Status);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiPsGetArguments
*
* PARAMETERS: WalkState - Current state
@@ -746,298 +380,6 @@ AcpiPsLinkModuleCode (
}
}
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsCompleteOp
- *
- * PARAMETERS: WalkState - Current state
- * Op - Returned Op
- * Status - Parse status before complete Op
- *
- * RETURN: Status
- *
- * DESCRIPTION: Complete Op
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiPsCompleteOp (
- ACPI_WALK_STATE *WalkState,
- ACPI_PARSE_OBJECT **Op,
- ACPI_STATUS Status)
-{
- ACPI_STATUS Status2;
-
-
- ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);
-
-
- /*
- * Finished one argument of the containing scope
- */
- WalkState->ParserState.Scope->ParseScope.ArgCount--;
-
- /* Close this Op (will result in parse subtree deletion) */
-
- Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
-
- *Op = NULL;
-
- switch (Status)
- {
- case AE_OK:
- break;
-
-
- case AE_CTRL_TRANSFER:
-
- /* We are about to transfer to a called method */
-
- WalkState->PrevOp = NULL;
- WalkState->PrevArgTypes = WalkState->ArgTypes;
- return_ACPI_STATUS (Status);
-
-
- case AE_CTRL_END:
-
- AcpiPsPopScope (&(WalkState->ParserState), Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
-
- if (*Op)
- {
- WalkState->Op = *Op;
- WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
- WalkState->Opcode = (*Op)->Common.AmlOpcode;
-
- Status = WalkState->AscendingCallback (WalkState);
- Status = AcpiPsNextParseState (WalkState, *Op, Status);
-
- Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
- }
-
- Status = AE_OK;
- break;
-
-
- case AE_CTRL_BREAK:
- case AE_CTRL_CONTINUE:
-
- /* Pop off scopes until we find the While */
-
- while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
- {
- AcpiPsPopScope (&(WalkState->ParserState), Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
- }
-
- /* Close this iteration of the While loop */
-
- WalkState->Op = *Op;
- WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
- WalkState->Opcode = (*Op)->Common.AmlOpcode;
-
- Status = WalkState->AscendingCallback (WalkState);
- Status = AcpiPsNextParseState (WalkState, *Op, Status);
-
- Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
-
- Status = AE_OK;
- break;
-
-
- case AE_CTRL_TERMINATE:
-
- /* Clean up */
- do
- {
- if (*Op)
- {
- Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
-
- AcpiUtDeleteGenericState (
- AcpiUtPopGenericState (&WalkState->ControlState));
- }
-
- AcpiPsPopScope (&(WalkState->ParserState), Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
-
- } while (*Op);
-
- return_ACPI_STATUS (AE_OK);
-
-
- default: /* All other non-AE_OK status */
-
- do
- {
- if (*Op)
- {
- Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
- }
-
- AcpiPsPopScope (&(WalkState->ParserState), Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
-
- } while (*Op);
-
-
-#if 0
- /*
- * TBD: Cleanup parse ops on error
- */
- if (*Op == NULL)
- {
- AcpiPsPopScope (ParserState, Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
- }
-#endif
- WalkState->PrevOp = NULL;
- WalkState->PrevArgTypes = WalkState->ArgTypes;
- return_ACPI_STATUS (Status);
- }
-
- /* This scope complete? */
-
- if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
- {
- AcpiPsPopScope (&(WalkState->ParserState), Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
- }
- else
- {
- *Op = NULL;
- }
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsCompleteFinalOp
- *
- * PARAMETERS: WalkState - Current state
- * Op - Current Op
- * Status - Current parse status before complete last
- * Op
- *
- * RETURN: Status
- *
- * DESCRIPTION: Complete last Op.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-AcpiPsCompleteFinalOp (
- ACPI_WALK_STATE *WalkState,
- ACPI_PARSE_OBJECT *Op,
- ACPI_STATUS Status)
-{
- ACPI_STATUS Status2;
-
-
- ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
-
-
- /*
- * Complete the last Op (if not completed), and clear the scope stack.
- * It is easily possible to end an AML "package" with an unbounded number
- * of open scopes (such as when several ASL blocks are closed with
- * sequential closing braces). We want to terminate each one cleanly.
- */
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
- do
- {
- if (Op)
- {
- if (WalkState->AscendingCallback != NULL)
- {
- WalkState->Op = Op;
- WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
- WalkState->Opcode = Op->Common.AmlOpcode;
-
- Status = WalkState->AscendingCallback (WalkState);
- Status = AcpiPsNextParseState (WalkState, Op, Status);
- if (Status == AE_CTRL_PENDING)
- {
- Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
- }
-
- if (Status == AE_CTRL_TERMINATE)
- {
- Status = AE_OK;
-
- /* Clean up */
- do
- {
- if (Op)
- {
- Status2 = AcpiPsCompleteThisOp (WalkState, Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
- }
-
- AcpiPsPopScope (&(WalkState->ParserState), &Op,
- &WalkState->ArgTypes, &WalkState->ArgCount);
-
- } while (Op);
-
- return_ACPI_STATUS (Status);
- }
-
- else if (ACPI_FAILURE (Status))
- {
- /* First error is most important */
-
- (void) AcpiPsCompleteThisOp (WalkState, Op);
- return_ACPI_STATUS (Status);
- }
- }
-
- Status2 = AcpiPsCompleteThisOp (WalkState, Op);
- if (ACPI_FAILURE (Status2))
- {
- return_ACPI_STATUS (Status2);
- }
- }
-
- AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
- &WalkState->ArgCount);
-
- } while (Op);
-
- return_ACPI_STATUS (Status);
-}
-
-
/*******************************************************************************
*
* FUNCTION: AcpiPsParseLoop
@@ -1225,11 +567,6 @@ AcpiPsParseLoop (
WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
if (WalkState->OpInfo->Flags & AML_NAMED)
{
- if (AcpiGbl_Depth)
- {
- AcpiGbl_Depth--;
- }
-
if (Op->Common.AmlOpcode == AML_REGION_OP ||
Op->Common.AmlOpcode == AML_DATA_REGION_OP)
{
diff --git a/sys/contrib/dev/acpica/components/parser/psobject.c b/sys/contrib/dev/acpica/components/parser/psobject.c
new file mode 100644
index 0000000..397c6f9
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/parser/psobject.c
@@ -0,0 +1,683 @@
+/******************************************************************************
+ *
+ * Module Name: psobject - Support for parse objects
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acparser.h>
+#include <contrib/dev/acpica/include/amlcode.h>
+
+#define _COMPONENT ACPI_PARSER
+ ACPI_MODULE_NAME ("psobject")
+
+
+/* Local prototypes */
+
+static ACPI_STATUS
+AcpiPsGetAmlOpcode (
+ ACPI_WALK_STATE *WalkState);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsGetAmlOpcode
+ *
+ * PARAMETERS: WalkState - Current state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Extract the next AML opcode from the input stream.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiPsGetAmlOpcode (
+ ACPI_WALK_STATE *WalkState)
+{
+
+ ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState);
+
+
+ WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
+ WalkState->ParserState.AmlStart);
+ WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState));
+
+ /*
+ * First cut to determine what we have found:
+ * 1) A valid AML opcode
+ * 2) A name string
+ * 3) An unknown/invalid opcode
+ */
+ WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
+
+ switch (WalkState->OpInfo->Class)
+ {
+ case AML_CLASS_ASCII:
+ case AML_CLASS_PREFIX:
+ /*
+ * Starts with a valid prefix or ASCII char, this is a name
+ * string. Convert the bare name string to a namepath.
+ */
+ WalkState->Opcode = AML_INT_NAMEPATH_OP;
+ WalkState->ArgTypes = ARGP_NAMESTRING;
+ break;
+
+ case AML_CLASS_UNKNOWN:
+
+ /* The opcode is unrecognized. Complain and skip unknown opcodes */
+
+ if (WalkState->PassNumber == 2)
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
+ WalkState->Opcode,
+ (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER))));
+
+ ACPI_DUMP_BUFFER ((WalkState->ParserState.Aml - 16), 48);
+
+#ifdef ACPI_ASL_COMPILER
+ /*
+ * This is executed for the disassembler only. Output goes
+ * to the disassembled ASL output file.
+ */
+ AcpiOsPrintf (
+ "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
+ WalkState->Opcode,
+ (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER)));
+
+ /* Dump the context surrounding the invalid opcode */
+
+ AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16),
+ 48, DB_BYTE_DISPLAY,
+ (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16));
+ AcpiOsPrintf (" */\n");
+#endif
+ }
+
+ /* Increment past one-byte or two-byte opcode */
+
+ WalkState->ParserState.Aml++;
+ if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */
+ {
+ WalkState->ParserState.Aml++;
+ }
+
+ return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
+
+ default:
+
+ /* Found opcode info, this is a normal opcode */
+
+ WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
+ WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
+ break;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsBuildNamedOp
+ *
+ * PARAMETERS: WalkState - Current state
+ * AmlOpStart - Begin of named Op in AML
+ * UnnamedOp - Early Op (not a named Op)
+ * Op - Returned Op
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Parse a named Op
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiPsBuildNamedOp (
+ ACPI_WALK_STATE *WalkState,
+ UINT8 *AmlOpStart,
+ ACPI_PARSE_OBJECT *UnnamedOp,
+ ACPI_PARSE_OBJECT **Op)
+{
+ ACPI_STATUS Status = AE_OK;
+ ACPI_PARSE_OBJECT *Arg = NULL;
+
+
+ ACPI_FUNCTION_TRACE_PTR (PsBuildNamedOp, WalkState);
+
+
+ UnnamedOp->Common.Value.Arg = NULL;
+ UnnamedOp->Common.ArgListLength = 0;
+ UnnamedOp->Common.AmlOpcode = WalkState->Opcode;
+
+ /*
+ * Get and append arguments until we find the node that contains
+ * the name (the type ARGP_NAME).
+ */
+ while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) &&
+ (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) != ARGP_NAME))
+ {
+ Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
+ GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ AcpiPsAppendArg (UnnamedOp, Arg);
+ INCREMENT_ARG_LIST (WalkState->ArgTypes);
+ }
+
+ /*
+ * Make sure that we found a NAME and didn't run out of arguments
+ */
+ if (!GET_CURRENT_ARG_TYPE (WalkState->ArgTypes))
+ {
+ return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ }
+
+ /* We know that this arg is a name, move to next arg */
+
+ INCREMENT_ARG_LIST (WalkState->ArgTypes);
+
+ /*
+ * Find the object. This will either insert the object into
+ * the namespace or simply look it up
+ */
+ WalkState->Op = NULL;
+
+ Status = WalkState->DescendingCallback (WalkState, Op);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status, "During name lookup/catalog"));
+ return_ACPI_STATUS (Status);
+ }
+
+ if (!*Op)
+ {
+ return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
+ }
+
+ Status = AcpiPsNextParseState (WalkState, *Op, Status);
+ if (ACPI_FAILURE (Status))
+ {
+ if (Status == AE_CTRL_PENDING)
+ {
+ return_ACPI_STATUS (AE_CTRL_PARSE_PENDING);
+ }
+ return_ACPI_STATUS (Status);
+ }
+
+ AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg);
+
+ if ((*Op)->Common.AmlOpcode == AML_REGION_OP ||
+ (*Op)->Common.AmlOpcode == AML_DATA_REGION_OP)
+ {
+ /*
+ * Defer final parsing of an OperationRegion body, because we don't
+ * have enough info in the first pass to parse it correctly (i.e.,
+ * there may be method calls within the TermArg elements of the body.)
+ *
+ * However, we must continue parsing because the opregion is not a
+ * standalone package -- we don't know where the end is at this point.
+ *
+ * (Length is unknown until parse of the body complete)
+ */
+ (*Op)->Named.Data = AmlOpStart;
+ (*Op)->Named.Length = 0;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsCreateOp
+ *
+ * PARAMETERS: WalkState - Current state
+ * AmlOpStart - Op start in AML
+ * NewOp - Returned Op
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Get Op from AML
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiPsCreateOp (
+ ACPI_WALK_STATE *WalkState,
+ UINT8 *AmlOpStart,
+ ACPI_PARSE_OBJECT **NewOp)
+{
+ ACPI_STATUS Status = AE_OK;
+ ACPI_PARSE_OBJECT *Op;
+ ACPI_PARSE_OBJECT *NamedOp = NULL;
+ ACPI_PARSE_OBJECT *ParentScope;
+ UINT8 ArgumentCount;
+ const ACPI_OPCODE_INFO *OpInfo;
+
+
+ ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);
+
+
+ Status = AcpiPsGetAmlOpcode (WalkState);
+ if (Status == AE_CTRL_PARSE_CONTINUE)
+ {
+ return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
+ }
+
+ /* Create Op structure and append to parent's argument list */
+
+ WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
+ Op = AcpiPsAllocOp (WalkState->Opcode);
+ if (!Op)
+ {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ if (WalkState->OpInfo->Flags & AML_NAMED)
+ {
+ Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
+ AcpiPsFreeOp (Op);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ *NewOp = NamedOp;
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Not a named opcode, just allocate Op and append to parent */
+
+ if (WalkState->OpInfo->Flags & AML_CREATE)
+ {
+ /*
+ * Backup to beginning of CreateXXXfield declaration
+ * BodyLength is unknown until we parse the body
+ */
+ Op->Named.Data = AmlOpStart;
+ Op->Named.Length = 0;
+ }
+
+ if (WalkState->Opcode == AML_BANK_FIELD_OP)
+ {
+ /*
+ * Backup to beginning of BankField declaration
+ * BodyLength is unknown until we parse the body
+ */
+ Op->Named.Data = AmlOpStart;
+ Op->Named.Length = 0;
+ }
+
+ ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
+ AcpiPsAppendArg (ParentScope, Op);
+
+ if (ParentScope)
+ {
+ OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
+ if (OpInfo->Flags & AML_HAS_TARGET)
+ {
+ ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
+ if (ParentScope->Common.ArgListLength > ArgumentCount)
+ {
+ Op->Common.Flags |= ACPI_PARSEOP_TARGET;
+ }
+ }
+ else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
+ {
+ Op->Common.Flags |= ACPI_PARSEOP_TARGET;
+ }
+ }
+
+ if (WalkState->DescendingCallback != NULL)
+ {
+ /*
+ * Find the object. This will either insert the object into
+ * the namespace or simply look it up
+ */
+ WalkState->Op = *NewOp = Op;
+
+ Status = WalkState->DescendingCallback (WalkState, &Op);
+ Status = AcpiPsNextParseState (WalkState, Op, Status);
+ if (Status == AE_CTRL_PENDING)
+ {
+ Status = AE_CTRL_PARSE_PENDING;
+ }
+ }
+
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsCompleteOp
+ *
+ * PARAMETERS: WalkState - Current state
+ * Op - Returned Op
+ * Status - Parse status before complete Op
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Complete Op
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiPsCompleteOp (
+ ACPI_WALK_STATE *WalkState,
+ ACPI_PARSE_OBJECT **Op,
+ ACPI_STATUS Status)
+{
+ ACPI_STATUS Status2;
+
+
+ ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);
+
+
+ /*
+ * Finished one argument of the containing scope
+ */
+ WalkState->ParserState.Scope->ParseScope.ArgCount--;
+
+ /* Close this Op (will result in parse subtree deletion) */
+
+ Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+
+ *Op = NULL;
+
+ switch (Status)
+ {
+ case AE_OK:
+ break;
+
+
+ case AE_CTRL_TRANSFER:
+
+ /* We are about to transfer to a called method */
+
+ WalkState->PrevOp = NULL;
+ WalkState->PrevArgTypes = WalkState->ArgTypes;
+ return_ACPI_STATUS (Status);
+
+
+ case AE_CTRL_END:
+
+ AcpiPsPopScope (&(WalkState->ParserState), Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+
+ if (*Op)
+ {
+ WalkState->Op = *Op;
+ WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
+ WalkState->Opcode = (*Op)->Common.AmlOpcode;
+
+ Status = WalkState->AscendingCallback (WalkState);
+ Status = AcpiPsNextParseState (WalkState, *Op, Status);
+
+ Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+ }
+
+ Status = AE_OK;
+ break;
+
+
+ case AE_CTRL_BREAK:
+ case AE_CTRL_CONTINUE:
+
+ /* Pop off scopes until we find the While */
+
+ while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
+ {
+ AcpiPsPopScope (&(WalkState->ParserState), Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+ }
+
+ /* Close this iteration of the While loop */
+
+ WalkState->Op = *Op;
+ WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
+ WalkState->Opcode = (*Op)->Common.AmlOpcode;
+
+ Status = WalkState->AscendingCallback (WalkState);
+ Status = AcpiPsNextParseState (WalkState, *Op, Status);
+
+ Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+
+ Status = AE_OK;
+ break;
+
+
+ case AE_CTRL_TERMINATE:
+
+ /* Clean up */
+ do
+ {
+ if (*Op)
+ {
+ Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+
+ AcpiUtDeleteGenericState (
+ AcpiUtPopGenericState (&WalkState->ControlState));
+ }
+
+ AcpiPsPopScope (&(WalkState->ParserState), Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+
+ } while (*Op);
+
+ return_ACPI_STATUS (AE_OK);
+
+
+ default: /* All other non-AE_OK status */
+
+ do
+ {
+ if (*Op)
+ {
+ Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+ }
+
+ AcpiPsPopScope (&(WalkState->ParserState), Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+
+ } while (*Op);
+
+
+#if 0
+ /*
+ * TBD: Cleanup parse ops on error
+ */
+ if (*Op == NULL)
+ {
+ AcpiPsPopScope (ParserState, Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+ }
+#endif
+ WalkState->PrevOp = NULL;
+ WalkState->PrevArgTypes = WalkState->ArgTypes;
+ return_ACPI_STATUS (Status);
+ }
+
+ /* This scope complete? */
+
+ if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
+ {
+ AcpiPsPopScope (&(WalkState->ParserState), Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
+ }
+ else
+ {
+ *Op = NULL;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsCompleteFinalOp
+ *
+ * PARAMETERS: WalkState - Current state
+ * Op - Current Op
+ * Status - Current parse status before complete last
+ * Op
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Complete last Op.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiPsCompleteFinalOp (
+ ACPI_WALK_STATE *WalkState,
+ ACPI_PARSE_OBJECT *Op,
+ ACPI_STATUS Status)
+{
+ ACPI_STATUS Status2;
+
+
+ ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);
+
+
+ /*
+ * Complete the last Op (if not completed), and clear the scope stack.
+ * It is easily possible to end an AML "package" with an unbounded number
+ * of open scopes (such as when several ASL blocks are closed with
+ * sequential closing braces). We want to terminate each one cleanly.
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
+ do
+ {
+ if (Op)
+ {
+ if (WalkState->AscendingCallback != NULL)
+ {
+ WalkState->Op = Op;
+ WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
+ WalkState->Opcode = Op->Common.AmlOpcode;
+
+ Status = WalkState->AscendingCallback (WalkState);
+ Status = AcpiPsNextParseState (WalkState, Op, Status);
+ if (Status == AE_CTRL_PENDING)
+ {
+ Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+ }
+
+ if (Status == AE_CTRL_TERMINATE)
+ {
+ Status = AE_OK;
+
+ /* Clean up */
+ do
+ {
+ if (Op)
+ {
+ Status2 = AcpiPsCompleteThisOp (WalkState, Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+ }
+
+ AcpiPsPopScope (&(WalkState->ParserState), &Op,
+ &WalkState->ArgTypes, &WalkState->ArgCount);
+
+ } while (Op);
+
+ return_ACPI_STATUS (Status);
+ }
+
+ else if (ACPI_FAILURE (Status))
+ {
+ /* First error is most important */
+
+ (void) AcpiPsCompleteThisOp (WalkState, Op);
+ return_ACPI_STATUS (Status);
+ }
+ }
+
+ Status2 = AcpiPsCompleteThisOp (WalkState, Op);
+ if (ACPI_FAILURE (Status2))
+ {
+ return_ACPI_STATUS (Status2);
+ }
+ }
+
+ AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
+ &WalkState->ArgCount);
+
+ } while (Op);
+
+ return_ACPI_STATUS (Status);
+}
diff --git a/sys/contrib/dev/acpica/components/parser/psopcode.c b/sys/contrib/dev/acpica/components/parser/psopcode.c
index 85e170d..8ae0c80 100644
--- a/sys/contrib/dev/acpica/components/parser/psopcode.c
+++ b/sys/contrib/dev/acpica/components/parser/psopcode.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,6 @@
#include <contrib/dev/acpica/include/acpi.h>
#include <contrib/dev/acpica/include/accommon.h>
-#include <contrib/dev/acpica/include/acparser.h>
#include <contrib/dev/acpica/include/acopcode.h>
#include <contrib/dev/acpica/include/amlcode.h>
@@ -53,9 +52,6 @@
ACPI_MODULE_NAME ("psopcode")
-static const UINT8 AcpiGbl_ArgumentCount[] = {0,1,1,1,1,2,2,2,2,3,3,6};
-
-
/*******************************************************************************
*
* NAME: AcpiGbl_AmlOpInfo
@@ -342,181 +338,3 @@ const ACPI_OPCODE_INFO AcpiGbl_AmlOpInfo[AML_NUM_OPCODES] =
/*! [End] no source code translation !*/
};
-
-/*
- * This table is directly indexed by the opcodes, and returns an
- * index into the table above
- */
-static const UINT8 AcpiGbl_ShortOpIndex[256] =
-{
-/* 0 1 2 3 4 5 6 7 */
-/* 8 9 A B C D E F */
-/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK,
-/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK,
-/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK,
-/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
-/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
-/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
-/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC,
-/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
-/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK,
-/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
-/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
-/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30,
-/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72,
-/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
-/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
-/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
-/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK,
-/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45,
-};
-
-/*
- * This table is indexed by the second opcode of the extended opcode
- * pair. It returns an index into the opcode table (AcpiGbl_AmlOpInfo)
- */
-static const UINT8 AcpiGbl_LongOpIndex[NUM_EXTENDED_OPCODE] =
-{
-/* 0 1 2 3 4 5 6 7 */
-/* 8 9 A B C D E F */
-/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK,
-/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B,
-/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
-/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK,
-/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
-/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-/* 0x88 */ 0x7C,
-};
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsGetOpcodeInfo
- *
- * PARAMETERS: Opcode - The AML opcode
- *
- * RETURN: A pointer to the info about the opcode.
- *
- * DESCRIPTION: Find AML opcode description based on the opcode.
- * NOTE: This procedure must ALWAYS return a valid pointer!
- *
- ******************************************************************************/
-
-const ACPI_OPCODE_INFO *
-AcpiPsGetOpcodeInfo (
- UINT16 Opcode)
-{
- ACPI_FUNCTION_NAME (PsGetOpcodeInfo);
-
-
- /*
- * Detect normal 8-bit opcode or extended 16-bit opcode
- */
- if (!(Opcode & 0xFF00))
- {
- /* Simple (8-bit) opcode: 0-255, can't index beyond table */
-
- return (&AcpiGbl_AmlOpInfo [AcpiGbl_ShortOpIndex [(UINT8) Opcode]]);
- }
-
- if (((Opcode & 0xFF00) == AML_EXTENDED_OPCODE) &&
- (((UINT8) Opcode) <= MAX_EXTENDED_OPCODE))
- {
- /* Valid extended (16-bit) opcode */
-
- return (&AcpiGbl_AmlOpInfo [AcpiGbl_LongOpIndex [(UINT8) Opcode]]);
- }
-
- /* Unknown AML opcode */
-
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
- "Unknown AML opcode [%4.4X]\n", Opcode));
-
- return (&AcpiGbl_AmlOpInfo [_UNK]);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsGetOpcodeName
- *
- * PARAMETERS: Opcode - The AML opcode
- *
- * RETURN: A pointer to the name of the opcode (ASCII String)
- * Note: Never returns NULL.
- *
- * DESCRIPTION: Translate an opcode into a human-readable string
- *
- ******************************************************************************/
-
-char *
-AcpiPsGetOpcodeName (
- UINT16 Opcode)
-{
-#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
-
- const ACPI_OPCODE_INFO *Op;
-
-
- Op = AcpiPsGetOpcodeInfo (Opcode);
-
- /* Always guaranteed to return a valid pointer */
-
- return (Op->Name);
-
-#else
- return ("OpcodeName unavailable");
-
-#endif
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiPsGetArgumentCount
- *
- * PARAMETERS: OpType - Type associated with the AML opcode
- *
- * RETURN: Argument count
- *
- * DESCRIPTION: Obtain the number of expected arguments for an AML opcode
- *
- ******************************************************************************/
-
-UINT8
-AcpiPsGetArgumentCount (
- UINT32 OpType)
-{
-
- if (OpType <= AML_TYPE_EXEC_6A_0T_1R)
- {
- return (AcpiGbl_ArgumentCount[OpType]);
- }
-
- return (0);
-}
diff --git a/sys/contrib/dev/acpica/components/parser/psopinfo.c b/sys/contrib/dev/acpica/components/parser/psopinfo.c
new file mode 100644
index 0000000..3c6e4a5
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/parser/psopinfo.c
@@ -0,0 +1,238 @@
+/******************************************************************************
+ *
+ * Module Name: psopinfo - AML opcode information functions and dispatch tables
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acparser.h>
+#include <contrib/dev/acpica/include/acopcode.h>
+#include <contrib/dev/acpica/include/amlcode.h>
+
+
+#define _COMPONENT ACPI_PARSER
+ ACPI_MODULE_NAME ("psopinfo")
+
+
+extern const UINT8 AcpiGbl_ShortOpIndex[];
+extern const UINT8 AcpiGbl_LongOpIndex[];
+
+static const UINT8 AcpiGbl_ArgumentCount[] = {0,1,1,1,1,2,2,2,2,3,3,6};
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsGetOpcodeInfo
+ *
+ * PARAMETERS: Opcode - The AML opcode
+ *
+ * RETURN: A pointer to the info about the opcode.
+ *
+ * DESCRIPTION: Find AML opcode description based on the opcode.
+ * NOTE: This procedure must ALWAYS return a valid pointer!
+ *
+ ******************************************************************************/
+
+const ACPI_OPCODE_INFO *
+AcpiPsGetOpcodeInfo (
+ UINT16 Opcode)
+{
+ ACPI_FUNCTION_NAME (PsGetOpcodeInfo);
+
+
+ /*
+ * Detect normal 8-bit opcode or extended 16-bit opcode
+ */
+ if (!(Opcode & 0xFF00))
+ {
+ /* Simple (8-bit) opcode: 0-255, can't index beyond table */
+
+ return (&AcpiGbl_AmlOpInfo [AcpiGbl_ShortOpIndex [(UINT8) Opcode]]);
+ }
+
+ if (((Opcode & 0xFF00) == AML_EXTENDED_OPCODE) &&
+ (((UINT8) Opcode) <= MAX_EXTENDED_OPCODE))
+ {
+ /* Valid extended (16-bit) opcode */
+
+ return (&AcpiGbl_AmlOpInfo [AcpiGbl_LongOpIndex [(UINT8) Opcode]]);
+ }
+
+ /* Unknown AML opcode */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "Unknown AML opcode [%4.4X]\n", Opcode));
+
+ return (&AcpiGbl_AmlOpInfo [_UNK]);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsGetOpcodeName
+ *
+ * PARAMETERS: Opcode - The AML opcode
+ *
+ * RETURN: A pointer to the name of the opcode (ASCII String)
+ * Note: Never returns NULL.
+ *
+ * DESCRIPTION: Translate an opcode into a human-readable string
+ *
+ ******************************************************************************/
+
+char *
+AcpiPsGetOpcodeName (
+ UINT16 Opcode)
+{
+#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
+
+ const ACPI_OPCODE_INFO *Op;
+
+
+ Op = AcpiPsGetOpcodeInfo (Opcode);
+
+ /* Always guaranteed to return a valid pointer */
+
+ return (Op->Name);
+
+#else
+ return ("OpcodeName unavailable");
+
+#endif
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiPsGetArgumentCount
+ *
+ * PARAMETERS: OpType - Type associated with the AML opcode
+ *
+ * RETURN: Argument count
+ *
+ * DESCRIPTION: Obtain the number of expected arguments for an AML opcode
+ *
+ ******************************************************************************/
+
+UINT8
+AcpiPsGetArgumentCount (
+ UINT32 OpType)
+{
+
+ if (OpType <= AML_TYPE_EXEC_6A_0T_1R)
+ {
+ return (AcpiGbl_ArgumentCount[OpType]);
+ }
+
+ return (0);
+}
+
+
+/*
+ * This table is directly indexed by the opcodes It returns
+ * an index into the opcode table (AcpiGbl_AmlOpInfo)
+ */
+const UINT8 AcpiGbl_ShortOpIndex[256] =
+{
+/* 0 1 2 3 4 5 6 7 */
+/* 8 9 A B C D E F */
+/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK,
+/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK,
+/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK,
+/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
+/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
+/* 0x38 */ 0x7F, 0x80, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
+/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC,
+/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK,
+/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
+/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
+/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30,
+/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72,
+/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
+/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
+/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
+/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK,
+/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45,
+};
+
+/*
+ * This table is indexed by the second opcode of the extended opcode
+ * pair. It returns an index into the opcode table (AcpiGbl_AmlOpInfo)
+ */
+const UINT8 AcpiGbl_LongOpIndex[NUM_EXTENDED_OPCODE] =
+{
+/* 0 1 2 3 4 5 6 7 */
+/* 8 9 A B C D E F */
+/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK,
+/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B,
+/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51,
+/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x30 */ 0x55, 0x56, 0x57, 0x7e, _UNK, _UNK, _UNK, _UNK,
+/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+/* 0x88 */ 0x7C,
+};
diff --git a/sys/contrib/dev/acpica/components/parser/psparse.c b/sys/contrib/dev/acpica/components/parser/psparse.c
index 1193262..1dafdc1 100644
--- a/sys/contrib/dev/acpica/components/parser/psparse.c
+++ b/sys/contrib/dev/acpica/components/parser/psparse.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/parser/psscope.c b/sys/contrib/dev/acpica/components/parser/psscope.c
index 3d88272..3aa102bd 100644
--- a/sys/contrib/dev/acpica/components/parser/psscope.c
+++ b/sys/contrib/dev/acpica/components/parser/psscope.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/parser/pstree.c b/sys/contrib/dev/acpica/components/parser/pstree.c
index 9ad3412..277c702 100644
--- a/sys/contrib/dev/acpica/components/parser/pstree.c
+++ b/sys/contrib/dev/acpica/components/parser/pstree.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/parser/psutils.c b/sys/contrib/dev/acpica/components/parser/psutils.c
index ca0e1d3..4b555cc 100644
--- a/sys/contrib/dev/acpica/components/parser/psutils.c
+++ b/sys/contrib/dev/acpica/components/parser/psutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -238,17 +238,6 @@ AcpiPsIsLeadingChar (
/*
- * Is "c" a namestring prefix character?
- */
-BOOLEAN
-AcpiPsIsPrefixChar (
- UINT32 c)
-{
- return ((BOOLEAN) (c == '\\' || c == '^'));
-}
-
-
-/*
* Get op's name (4-byte name segment) or 0 if unnamed
*/
UINT32
diff --git a/sys/contrib/dev/acpica/components/parser/pswalk.c b/sys/contrib/dev/acpica/components/parser/pswalk.c
index 6dd2b0d..6b6e289 100644
--- a/sys/contrib/dev/acpica/components/parser/pswalk.c
+++ b/sys/contrib/dev/acpica/components/parser/pswalk.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/parser/psxface.c b/sys/contrib/dev/acpica/components/parser/psxface.c
index 1131e8c..6177baf 100644
--- a/sys/contrib/dev/acpica/components/parser/psxface.c
+++ b/sys/contrib/dev/acpica/components/parser/psxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsaddr.c b/sys/contrib/dev/acpica/components/resources/rsaddr.c
index 80eb57a..a8fa79d 100644
--- a/sys/contrib/dev/acpica/components/resources/rsaddr.c
+++ b/sys/contrib/dev/acpica/components/resources/rsaddr.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rscalc.c b/sys/contrib/dev/acpica/components/resources/rscalc.c
index 3820aa0..3b43775 100644
--- a/sys/contrib/dev/acpica/components/resources/rscalc.c
+++ b/sys/contrib/dev/acpica/components/resources/rscalc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rscreate.c b/sys/contrib/dev/acpica/components/resources/rscreate.c
index 87a9ecf..86c10aa 100644
--- a/sys/contrib/dev/acpica/components/resources/rscreate.c
+++ b/sys/contrib/dev/acpica/components/resources/rscreate.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsdump.c b/sys/contrib/dev/acpica/components/resources/rsdump.c
index acccad3..20c1893 100644
--- a/sys/contrib/dev/acpica/components/resources/rsdump.c
+++ b/sys/contrib/dev/acpica/components/resources/rsdump.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -119,315 +119,16 @@ AcpiRsDumpDescriptor (
ACPI_RSDUMP_INFO *Table);
-#define ACPI_RSD_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_RESOURCE_DATA,f)
-#define ACPI_PRT_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_PCI_ROUTING_TABLE,f)
-#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (ACPI_RSDUMP_INFO))
-
-
-/*******************************************************************************
- *
- * Resource Descriptor info tables
- *
- * Note: The first table entry must be a Title or Literal and must contain
- * the table length (number of table entries)
- *
- ******************************************************************************/
-
-ACPI_RSDUMP_INFO AcpiRsDumpIrq[7] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIrq), "IRQ", NULL},
- {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (Irq.DescriptorLength), "Descriptor Length", NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Irq.Triggering), "Triggering", AcpiGbl_HeDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Irq.Polarity), "Polarity", AcpiGbl_LlDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Irq.Sharable), "Sharing", AcpiGbl_ShrDecode},
- {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (Irq.InterruptCount), "Interrupt Count", NULL},
- {ACPI_RSD_SHORTLIST,ACPI_RSD_OFFSET (Irq.Interrupts[0]), "Interrupt List", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpDma[6] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpDma), "DMA", NULL},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Dma.Type), "Speed", AcpiGbl_TypDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Dma.BusMaster), "Mastering", AcpiGbl_BmDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Dma.Transfer), "Transfer Type", AcpiGbl_SizDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Dma.ChannelCount), "Channel Count", NULL},
- {ACPI_RSD_SHORTLIST,ACPI_RSD_OFFSET (Dma.Channels[0]), "Channel List", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpStartDpf[4] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpStartDpf), "Start-Dependent-Functions",NULL},
- {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (StartDpf.DescriptorLength), "Descriptor Length", NULL},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (StartDpf.CompatibilityPriority), "Compatibility Priority", AcpiGbl_ConfigDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (StartDpf.PerformanceRobustness), "Performance/Robustness", AcpiGbl_ConfigDecode}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpEndDpf[1] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpEndDpf), "End-Dependent-Functions", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpIo[6] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIo), "I/O", NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Io.IoDecode), "Address Decoding", AcpiGbl_IoDecode},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Io.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Io.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Io.Alignment), "Alignment", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Io.AddressLength), "Address Length", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpFixedIo[3] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedIo), "Fixed I/O", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedIo.Address), "Address", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (FixedIo.AddressLength), "Address Length", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpVendor[3] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpVendor), "Vendor Specific", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Vendor.ByteLength), "Length", NULL},
- {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET (Vendor.ByteData[0]), "Vendor Data", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpEndTag[1] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpEndTag), "EndTag", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpMemory24[6] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemory24), "24-Bit Memory Range", NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Memory24.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Alignment), "Alignment", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.AddressLength), "Address Length", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpMemory32[6] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemory32), "32-Bit Memory Range", NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Memory32.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Alignment), "Alignment", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.AddressLength), "Address Length", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpFixedMemory32[4] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedMemory32), "32-Bit Fixed Memory Range",NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (FixedMemory32.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (FixedMemory32.Address), "Address", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (FixedMemory32.AddressLength), "Address Length", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpAddress16[8] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress16), "16-Bit WORD Address Space",NULL},
- {ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Granularity), "Granularity", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.TranslationOffset), "Translation Offset", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.AddressLength), "Address Length", NULL},
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address16.ResourceSource), NULL, NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpAddress32[8] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress32), "32-Bit DWORD Address Space", NULL},
- {ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Granularity), "Granularity", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.TranslationOffset), "Translation Offset", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.AddressLength), "Address Length", NULL},
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address32.ResourceSource), NULL, NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpAddress64[8] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress64), "64-Bit QWORD Address Space", NULL},
- {ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Granularity), "Granularity", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.TranslationOffset), "Translation Offset", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.AddressLength), "Address Length", NULL},
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address64.ResourceSource), NULL, NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpExtAddress64[8] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpExtAddress64), "64-Bit Extended Address Space", NULL},
- {ACPI_RSD_ADDRESS, 0, NULL, NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Granularity), "Granularity", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Minimum), "Address Minimum", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Maximum), "Address Maximum", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.TranslationOffset), "Translation Offset", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.AddressLength), "Address Length", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.TypeSpecific), "Type-Specific Attribute", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpExtIrq[8] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpExtIrq), "Extended IRQ", NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.ProducerConsumer), "Type", AcpiGbl_ConsumeDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Triggering), "Triggering", AcpiGbl_HeDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Polarity), "Polarity", AcpiGbl_LlDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Sharable), "Sharing", AcpiGbl_ShrDecode},
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (ExtendedIrq.ResourceSource), NULL, NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (ExtendedIrq.InterruptCount), "Interrupt Count", NULL},
- {ACPI_RSD_DWORDLIST,ACPI_RSD_OFFSET (ExtendedIrq.Interrupts[0]), "Interrupt List", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpGenericReg[6] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGenericReg), "Generic Register", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.SpaceId), "Space ID", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.BitWidth), "Bit Width", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.BitOffset), "Bit Offset", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.AccessSize), "Access Size", NULL},
- {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (GenericReg.Address), "Address", NULL}
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpGpio[16] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGpio), "GPIO", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.RevisionId), "RevisionId", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.ConnectionType), "ConnectionType", AcpiGbl_CtDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Gpio.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.PinConfig), "PinConfig", AcpiGbl_PpcDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.Sharable), "Sharing", AcpiGbl_ShrDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.IoRestriction), "IoRestriction", AcpiGbl_IorDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Gpio.Triggering), "Triggering", AcpiGbl_HeDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.Polarity), "Polarity", AcpiGbl_LlDecode},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.DriveStrength), "DriveStrength", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.DebounceTimeout), "DebounceTimeout", NULL},
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Gpio.ResourceSource), "ResourceSource", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.PinTableLength), "PinTableLength", NULL},
- {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET (Gpio.PinTable), "PinTable", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.VendorLength), "VendorLength", NULL},
- {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (Gpio.VendorData), "VendorData", NULL},
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpFixedDma[4] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedDma), "FixedDma", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedDma.RequestLines), "RequestLines", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedDma.Channels), "Channels", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (FixedDma.Width), "TransferWidth", AcpiGbl_DtsDecode},
-};
-
-#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.RevisionId), "RevisionId", NULL}, \
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.Type), "Type", AcpiGbl_SbtDecode}, \
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (CommonSerialBus.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode}, \
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (CommonSerialBus.SlaveMode), "SlaveMode", AcpiGbl_SmDecode}, \
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.TypeRevisionId), "TypeRevisionId", NULL}, \
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (CommonSerialBus.TypeDataLength), "TypeDataLength", NULL}, \
- {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (CommonSerialBus.ResourceSource), "ResourceSource", NULL}, \
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (CommonSerialBus.VendorLength), "VendorLength", NULL}, \
- {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (CommonSerialBus.VendorData), "VendorData", NULL},
-
-ACPI_RSDUMP_INFO AcpiRsDumpCommonSerialBus[10] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpCommonSerialBus), "Common Serial Bus", NULL},
- ACPI_RS_DUMP_COMMON_SERIAL_BUS
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpI2cSerialBus[13] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpI2cSerialBus), "I2C Serial Bus", NULL},
- ACPI_RS_DUMP_COMMON_SERIAL_BUS
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (I2cSerialBus.AccessMode), "AccessMode", AcpiGbl_AmDecode},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (I2cSerialBus.ConnectionSpeed), "ConnectionSpeed", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (I2cSerialBus.SlaveAddress), "SlaveAddress", NULL},
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpSpiSerialBus[17] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpSpiSerialBus), "Spi Serial Bus", NULL},
- ACPI_RS_DUMP_COMMON_SERIAL_BUS
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (SpiSerialBus.WireMode), "WireMode", AcpiGbl_WmDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (SpiSerialBus.DevicePolarity), "DevicePolarity", AcpiGbl_DpDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.DataBitLength), "DataBitLength", NULL},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.ClockPhase), "ClockPhase", AcpiGbl_CphDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.ClockPolarity), "ClockPolarity", AcpiGbl_CpoDecode},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (SpiSerialBus.DeviceSelection), "DeviceSelection", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (SpiSerialBus.ConnectionSpeed), "ConnectionSpeed", NULL},
-};
-
-ACPI_RSDUMP_INFO AcpiRsDumpUartSerialBus[19] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpUartSerialBus), "Uart Serial Bus", NULL},
- ACPI_RS_DUMP_COMMON_SERIAL_BUS
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.FlowControl), "FlowControl", AcpiGbl_FcDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.StopBits), "StopBits", AcpiGbl_SbDecode},
- {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.DataBits), "DataBits", AcpiGbl_BpbDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.Endian), "Endian", AcpiGbl_EdDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (UartSerialBus.Parity), "Parity", AcpiGbl_PtDecode},
- {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (UartSerialBus.LinesEnabled), "LinesEnabled", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (UartSerialBus.RxFifoSize), "RxFifoSize", NULL},
- {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (UartSerialBus.TxFifoSize), "TxFifoSize", NULL},
- {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (UartSerialBus.DefaultBaudRate), "ConnectionSpeed", NULL},
-};
-
-/*
- * Tables used for common address descriptor flag fields
- */
-static ACPI_RSDUMP_INFO AcpiRsDumpGeneralFlags[5] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGeneralFlags), NULL, NULL},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.ProducerConsumer), "Consumer/Producer", AcpiGbl_ConsumeDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Decode), "Address Decode", AcpiGbl_DecDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.MinAddressFixed), "Min Relocatability", AcpiGbl_MinDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.MaxAddressFixed), "Max Relocatability", AcpiGbl_MaxDecode}
-};
-
-static ACPI_RSDUMP_INFO AcpiRsDumpMemoryFlags[5] =
-{
- {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemoryFlags), "Resource Type", (void *) "Memory Range"},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.Caching), "Caching", AcpiGbl_MemDecode},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.RangeType), "Range Type", AcpiGbl_MtpDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.Translation), "Translation", AcpiGbl_TtpDecode}
-};
-
-static ACPI_RSDUMP_INFO AcpiRsDumpIoFlags[4] =
-{
- {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIoFlags), "Resource Type", (void *) "I/O Range"},
- {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.RangeType), "Range Type", AcpiGbl_RngDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.Translation), "Translation", AcpiGbl_TtpDecode},
- {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.TranslationType), "Translation Type", AcpiGbl_TrsDecode}
-};
-
-
-/*
- * Table used to dump _PRT contents
- */
-static ACPI_RSDUMP_INFO AcpiRsDumpPrt[5] =
-{
- {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpPrt), NULL, NULL},
- {ACPI_RSD_UINT64, ACPI_PRT_OFFSET (Address), "Address", NULL},
- {ACPI_RSD_UINT32, ACPI_PRT_OFFSET (Pin), "Pin", NULL},
- {ACPI_RSD_STRING, ACPI_PRT_OFFSET (Source[0]), "Source", NULL},
- {ACPI_RSD_UINT32, ACPI_PRT_OFFSET (SourceIndex), "Source Index", NULL}
-};
-
-
/*******************************************************************************
*
* FUNCTION: AcpiRsDumpDescriptor
*
- * PARAMETERS: Resource
+ * PARAMETERS: Resource - Buffer containing the resource
+ * Table - Table entry to decode the resource
*
* RETURN: None
*
- * DESCRIPTION:
+ * DESCRIPTION: Dump a resource descriptor based on a dump table entry.
*
******************************************************************************/
@@ -712,7 +413,9 @@ AcpiRsDumpResourceList (
ACPI_FUNCTION_ENTRY ();
- if (!(AcpiDbgLevel & ACPI_LV_RESOURCES) || !( _COMPONENT & AcpiDbgLayer))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_RESOURCES, _COMPONENT))
{
return;
}
@@ -781,7 +484,9 @@ AcpiRsDumpIrqList (
ACPI_FUNCTION_ENTRY ();
- if (!(AcpiDbgLevel & ACPI_LV_RESOURCES) || !( _COMPONENT & AcpiDbgLayer))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_RESOURCES, _COMPONENT))
{
return;
}
diff --git a/sys/contrib/dev/acpica/components/resources/rsdumpinfo.c b/sys/contrib/dev/acpica/components/resources/rsdumpinfo.c
new file mode 100644
index 0000000..865209b
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/resources/rsdumpinfo.c
@@ -0,0 +1,357 @@
+/*******************************************************************************
+ *
+ * Module Name: rsdumpinfo - Tables used to display resource descriptors.
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#define __RSDUMPINFO_C__
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acresrc.h>
+
+#define _COMPONENT ACPI_RESOURCES
+ ACPI_MODULE_NAME ("rsdumpinfo")
+
+
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+
+
+#define ACPI_RSD_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_RESOURCE_DATA,f)
+#define ACPI_PRT_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_PCI_ROUTING_TABLE,f)
+#define ACPI_RSD_TABLE_SIZE(name) (sizeof(name) / sizeof (ACPI_RSDUMP_INFO))
+
+
+/*******************************************************************************
+ *
+ * Resource Descriptor info tables
+ *
+ * Note: The first table entry must be a Title or Literal and must contain
+ * the table length (number of table entries)
+ *
+ ******************************************************************************/
+
+ACPI_RSDUMP_INFO AcpiRsDumpIrq[7] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIrq), "IRQ", NULL},
+ {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (Irq.DescriptorLength), "Descriptor Length", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Irq.Triggering), "Triggering", AcpiGbl_HeDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Irq.Polarity), "Polarity", AcpiGbl_LlDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Irq.Sharable), "Sharing", AcpiGbl_ShrDecode},
+ {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (Irq.InterruptCount), "Interrupt Count", NULL},
+ {ACPI_RSD_SHORTLIST,ACPI_RSD_OFFSET (Irq.Interrupts[0]), "Interrupt List", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpDma[6] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpDma), "DMA", NULL},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Dma.Type), "Speed", AcpiGbl_TypDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Dma.BusMaster), "Mastering", AcpiGbl_BmDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Dma.Transfer), "Transfer Type", AcpiGbl_SizDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Dma.ChannelCount), "Channel Count", NULL},
+ {ACPI_RSD_SHORTLIST,ACPI_RSD_OFFSET (Dma.Channels[0]), "Channel List", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpStartDpf[4] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpStartDpf), "Start-Dependent-Functions",NULL},
+ {ACPI_RSD_UINT8 , ACPI_RSD_OFFSET (StartDpf.DescriptorLength), "Descriptor Length", NULL},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (StartDpf.CompatibilityPriority), "Compatibility Priority", AcpiGbl_ConfigDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (StartDpf.PerformanceRobustness), "Performance/Robustness", AcpiGbl_ConfigDecode}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpEndDpf[1] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpEndDpf), "End-Dependent-Functions", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpIo[6] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIo), "I/O", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Io.IoDecode), "Address Decoding", AcpiGbl_IoDecode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Io.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Io.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Io.Alignment), "Alignment", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Io.AddressLength), "Address Length", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpFixedIo[3] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedIo), "Fixed I/O", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedIo.Address), "Address", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (FixedIo.AddressLength), "Address Length", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpVendor[3] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpVendor), "Vendor Specific", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Vendor.ByteLength), "Length", NULL},
+ {ACPI_RSD_LONGLIST, ACPI_RSD_OFFSET (Vendor.ByteData[0]), "Vendor Data", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpEndTag[1] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpEndTag), "EndTag", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpMemory24[6] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemory24), "24-Bit Memory Range", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Memory24.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.Alignment), "Alignment", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Memory24.AddressLength), "Address Length", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpMemory32[6] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemory32), "32-Bit Memory Range", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Memory32.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.Alignment), "Alignment", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Memory32.AddressLength), "Address Length", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpFixedMemory32[4] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedMemory32), "32-Bit Fixed Memory Range",NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (FixedMemory32.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (FixedMemory32.Address), "Address", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (FixedMemory32.AddressLength), "Address Length", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpAddress16[8] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress16), "16-Bit WORD Address Space",NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Granularity), "Granularity", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.TranslationOffset), "Translation Offset", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.AddressLength), "Address Length", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address16.ResourceSource), NULL, NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpAddress32[8] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress32), "32-Bit DWORD Address Space", NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Granularity), "Granularity", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.TranslationOffset), "Translation Offset", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.AddressLength), "Address Length", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address32.ResourceSource), NULL, NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpAddress64[8] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpAddress64), "64-Bit QWORD Address Space", NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Granularity), "Granularity", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.TranslationOffset), "Translation Offset", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.AddressLength), "Address Length", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Address64.ResourceSource), NULL, NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpExtAddress64[8] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpExtAddress64), "64-Bit Extended Address Space", NULL},
+ {ACPI_RSD_ADDRESS, 0, NULL, NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Granularity), "Granularity", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Minimum), "Address Minimum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Maximum), "Address Maximum", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.TranslationOffset), "Translation Offset", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.AddressLength), "Address Length", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.TypeSpecific), "Type-Specific Attribute", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpExtIrq[8] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpExtIrq), "Extended IRQ", NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.ProducerConsumer), "Type", AcpiGbl_ConsumeDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Triggering), "Triggering", AcpiGbl_HeDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Polarity), "Polarity", AcpiGbl_LlDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Sharable), "Sharing", AcpiGbl_ShrDecode},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (ExtendedIrq.ResourceSource), NULL, NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (ExtendedIrq.InterruptCount), "Interrupt Count", NULL},
+ {ACPI_RSD_DWORDLIST,ACPI_RSD_OFFSET (ExtendedIrq.Interrupts[0]), "Interrupt List", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpGenericReg[6] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGenericReg), "Generic Register", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.SpaceId), "Space ID", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.BitWidth), "Bit Width", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.BitOffset), "Bit Offset", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (GenericReg.AccessSize), "Access Size", NULL},
+ {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (GenericReg.Address), "Address", NULL}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpGpio[16] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGpio), "GPIO", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.RevisionId), "RevisionId", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.ConnectionType), "ConnectionType", AcpiGbl_CtDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Gpio.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Gpio.PinConfig), "PinConfig", AcpiGbl_PpcDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.Sharable), "Sharing", AcpiGbl_ShrDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.IoRestriction), "IoRestriction", AcpiGbl_IorDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Gpio.Triggering), "Triggering", AcpiGbl_HeDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Gpio.Polarity), "Polarity", AcpiGbl_LlDecode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.DriveStrength), "DriveStrength", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.DebounceTimeout), "DebounceTimeout", NULL},
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Gpio.ResourceSource), "ResourceSource", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.PinTableLength), "PinTableLength", NULL},
+ {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET (Gpio.PinTable), "PinTable", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Gpio.VendorLength), "VendorLength", NULL},
+ {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (Gpio.VendorData), "VendorData", NULL},
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpFixedDma[4] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpFixedDma), "FixedDma", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedDma.RequestLines), "RequestLines", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (FixedDma.Channels), "Channels", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (FixedDma.Width), "TransferWidth", AcpiGbl_DtsDecode},
+};
+
+#define ACPI_RS_DUMP_COMMON_SERIAL_BUS \
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.RevisionId), "RevisionId", NULL}, \
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.Type), "Type", AcpiGbl_SbtDecode}, \
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (CommonSerialBus.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode}, \
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (CommonSerialBus.SlaveMode), "SlaveMode", AcpiGbl_SmDecode}, \
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (CommonSerialBus.TypeRevisionId), "TypeRevisionId", NULL}, \
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (CommonSerialBus.TypeDataLength), "TypeDataLength", NULL}, \
+ {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (CommonSerialBus.ResourceSource), "ResourceSource", NULL}, \
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (CommonSerialBus.VendorLength), "VendorLength", NULL}, \
+ {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (CommonSerialBus.VendorData), "VendorData", NULL},
+
+ACPI_RSDUMP_INFO AcpiRsDumpCommonSerialBus[10] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpCommonSerialBus), "Common Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpI2cSerialBus[13] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpI2cSerialBus), "I2C Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (I2cSerialBus.AccessMode), "AccessMode", AcpiGbl_AmDecode},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (I2cSerialBus.ConnectionSpeed), "ConnectionSpeed", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (I2cSerialBus.SlaveAddress), "SlaveAddress", NULL},
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpSpiSerialBus[17] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpSpiSerialBus), "Spi Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (SpiSerialBus.WireMode), "WireMode", AcpiGbl_WmDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (SpiSerialBus.DevicePolarity), "DevicePolarity", AcpiGbl_DpDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.DataBitLength), "DataBitLength", NULL},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.ClockPhase), "ClockPhase", AcpiGbl_CphDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (SpiSerialBus.ClockPolarity), "ClockPolarity", AcpiGbl_CpoDecode},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (SpiSerialBus.DeviceSelection), "DeviceSelection", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (SpiSerialBus.ConnectionSpeed), "ConnectionSpeed", NULL},
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpUartSerialBus[19] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpUartSerialBus), "Uart Serial Bus", NULL},
+ ACPI_RS_DUMP_COMMON_SERIAL_BUS
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.FlowControl), "FlowControl", AcpiGbl_FcDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.StopBits), "StopBits", AcpiGbl_SbDecode},
+ {ACPI_RSD_3BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.DataBits), "DataBits", AcpiGbl_BpbDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (UartSerialBus.Endian), "Endian", AcpiGbl_EdDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (UartSerialBus.Parity), "Parity", AcpiGbl_PtDecode},
+ {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (UartSerialBus.LinesEnabled), "LinesEnabled", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (UartSerialBus.RxFifoSize), "RxFifoSize", NULL},
+ {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (UartSerialBus.TxFifoSize), "TxFifoSize", NULL},
+ {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (UartSerialBus.DefaultBaudRate), "ConnectionSpeed", NULL},
+};
+
+/*
+ * Tables used for common address descriptor flag fields
+ */
+ACPI_RSDUMP_INFO AcpiRsDumpGeneralFlags[5] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpGeneralFlags), NULL, NULL},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.ProducerConsumer), "Consumer/Producer", AcpiGbl_ConsumeDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Decode), "Address Decode", AcpiGbl_DecDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.MinAddressFixed), "Min Relocatability", AcpiGbl_MinDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.MaxAddressFixed), "Max Relocatability", AcpiGbl_MaxDecode}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpMemoryFlags[5] =
+{
+ {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE (AcpiRsDumpMemoryFlags), "Resource Type", (void *) "Memory Range"},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.WriteProtect), "Write Protect", AcpiGbl_RwDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.Caching), "Caching", AcpiGbl_MemDecode},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.RangeType), "Range Type", AcpiGbl_MtpDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Mem.Translation), "Translation", AcpiGbl_TtpDecode}
+};
+
+ACPI_RSDUMP_INFO AcpiRsDumpIoFlags[4] =
+{
+ {ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE (AcpiRsDumpIoFlags), "Resource Type", (void *) "I/O Range"},
+ {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.RangeType), "Range Type", AcpiGbl_RngDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.Translation), "Translation", AcpiGbl_TtpDecode},
+ {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Address.Info.Io.TranslationType), "Translation Type", AcpiGbl_TrsDecode}
+};
+
+
+/*
+ * Table used to dump _PRT contents
+ */
+ACPI_RSDUMP_INFO AcpiRsDumpPrt[5] =
+{
+ {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpPrt), NULL, NULL},
+ {ACPI_RSD_UINT64, ACPI_PRT_OFFSET (Address), "Address", NULL},
+ {ACPI_RSD_UINT32, ACPI_PRT_OFFSET (Pin), "Pin", NULL},
+ {ACPI_RSD_STRING, ACPI_PRT_OFFSET (Source[0]), "Source", NULL},
+ {ACPI_RSD_UINT32, ACPI_PRT_OFFSET (SourceIndex), "Source Index", NULL}
+};
+
+#endif
diff --git a/sys/contrib/dev/acpica/components/resources/rsinfo.c b/sys/contrib/dev/acpica/components/resources/rsinfo.c
index ab2254e..cb72332 100644
--- a/sys/contrib/dev/acpica/components/resources/rsinfo.c
+++ b/sys/contrib/dev/acpica/components/resources/rsinfo.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsio.c b/sys/contrib/dev/acpica/components/resources/rsio.c
index 08119bf..1a41fb9 100644
--- a/sys/contrib/dev/acpica/components/resources/rsio.c
+++ b/sys/contrib/dev/acpica/components/resources/rsio.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsirq.c b/sys/contrib/dev/acpica/components/resources/rsirq.c
index 0179749..b3b5ee57 100644
--- a/sys/contrib/dev/acpica/components/resources/rsirq.c
+++ b/sys/contrib/dev/acpica/components/resources/rsirq.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,7 +57,7 @@
*
******************************************************************************/
-ACPI_RSCONVERT_INFO AcpiRsGetIrq[8] =
+ACPI_RSCONVERT_INFO AcpiRsGetIrq[9] =
{
{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ,
ACPI_RS_SIZE (ACPI_RESOURCE_IRQ),
@@ -85,7 +85,7 @@ ACPI_RSCONVERT_INFO AcpiRsGetIrq[8] =
{ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3},
- /* Get flags: Triggering[0], Polarity[3], Sharing[4] */
+ /* Get flags: Triggering[0], Polarity[3], Sharing[4], Wake[5] */
{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Triggering),
AML_OFFSET (Irq.Flags),
@@ -97,7 +97,11 @@ ACPI_RSCONVERT_INFO AcpiRsGetIrq[8] =
{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Sharable),
AML_OFFSET (Irq.Flags),
- 4}
+ 4},
+
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.WakeCapable),
+ AML_OFFSET (Irq.Flags),
+ 5}
};
@@ -107,7 +111,7 @@ ACPI_RSCONVERT_INFO AcpiRsGetIrq[8] =
*
******************************************************************************/
-ACPI_RSCONVERT_INFO AcpiRsSetIrq[13] =
+ACPI_RSCONVERT_INFO AcpiRsSetIrq[14] =
{
/* Start with a default descriptor of length 3 */
@@ -121,7 +125,7 @@ ACPI_RSCONVERT_INFO AcpiRsSetIrq[13] =
AML_OFFSET (Irq.IrqMask),
ACPI_RS_OFFSET (Data.Irq.InterruptCount)},
- /* Set the flags byte */
+ /* Set flags: Triggering[0], Polarity[3], Sharing[4], Wake[5] */
{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.Triggering),
AML_OFFSET (Irq.Flags),
@@ -135,6 +139,10 @@ ACPI_RSCONVERT_INFO AcpiRsSetIrq[13] =
AML_OFFSET (Irq.Flags),
4},
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.WakeCapable),
+ AML_OFFSET (Irq.Flags),
+ 5},
+
/*
* All done if the output descriptor length is required to be 3
* (i.e., optimization to 2 bytes cannot be attempted)
@@ -189,7 +197,7 @@ ACPI_RSCONVERT_INFO AcpiRsSetIrq[13] =
*
******************************************************************************/
-ACPI_RSCONVERT_INFO AcpiRsConvertExtIrq[9] =
+ACPI_RSCONVERT_INFO AcpiRsConvertExtIrq[10] =
{
{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_IRQ,
ACPI_RS_SIZE (ACPI_RESOURCE_EXTENDED_IRQ),
@@ -199,8 +207,10 @@ ACPI_RSCONVERT_INFO AcpiRsConvertExtIrq[9] =
sizeof (AML_RESOURCE_EXTENDED_IRQ),
0},
- /* Flag bits */
-
+ /*
+ * Flags: Producer/Consumer[0], Triggering[1], Polarity[2],
+ * Sharing[3], Wake[4]
+ */
{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.ExtendedIrq.ProducerConsumer),
AML_OFFSET (ExtendedIrq.Flags),
0},
@@ -217,6 +227,10 @@ ACPI_RSCONVERT_INFO AcpiRsConvertExtIrq[9] =
AML_OFFSET (ExtendedIrq.Flags),
3},
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.ExtendedIrq.WakeCapable),
+ AML_OFFSET (ExtendedIrq.Flags),
+ 4},
+
/* IRQ Table length (Byte4) */
{ACPI_RSC_COUNT, ACPI_RS_OFFSET (Data.ExtendedIrq.InterruptCount),
@@ -296,7 +310,6 @@ ACPI_RSCONVERT_INFO AcpiRsConvertFixedDma[4] =
* RequestLines
* Channels
*/
-
{ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.FixedDma.RequestLines),
AML_OFFSET (FixedDma.RequestLines),
2},
@@ -304,5 +317,4 @@ ACPI_RSCONVERT_INFO AcpiRsConvertFixedDma[4] =
{ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.FixedDma.Width),
AML_OFFSET (FixedDma.Width),
1},
-
};
diff --git a/sys/contrib/dev/acpica/components/resources/rslist.c b/sys/contrib/dev/acpica/components/resources/rslist.c
index 96b8c67..2c69c349 100644
--- a/sys/contrib/dev/acpica/components/resources/rslist.c
+++ b/sys/contrib/dev/acpica/components/resources/rslist.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -72,7 +72,7 @@ AcpiRsConvertAmlToResources (
UINT32 Length,
UINT32 Offset,
UINT8 ResourceIndex,
- void *Context)
+ void **Context)
{
ACPI_RESOURCE **ResourcePtr = ACPI_CAST_INDIRECT_PTR (
ACPI_RESOURCE, Context);
diff --git a/sys/contrib/dev/acpica/components/resources/rsmemory.c b/sys/contrib/dev/acpica/components/resources/rsmemory.c
index e4e4ae0..049a7b1 100644
--- a/sys/contrib/dev/acpica/components/resources/rsmemory.c
+++ b/sys/contrib/dev/acpica/components/resources/rsmemory.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsmisc.c b/sys/contrib/dev/acpica/components/resources/rsmisc.c
index 733ac8f..c0687ca 100644
--- a/sys/contrib/dev/acpica/components/resources/rsmisc.c
+++ b/sys/contrib/dev/acpica/components/resources/rsmisc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/resources/rsserial.c b/sys/contrib/dev/acpica/components/resources/rsserial.c
index 09cc7de..69e2259 100644
--- a/sys/contrib/dev/acpica/components/resources/rsserial.c
+++ b/sys/contrib/dev/acpica/components/resources/rsserial.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,7 +57,7 @@
*
******************************************************************************/
-ACPI_RSCONVERT_INFO AcpiRsConvertGpio[17] =
+ACPI_RSCONVERT_INFO AcpiRsConvertGpio[18] =
{
{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_GPIO,
ACPI_RS_SIZE (ACPI_RESOURCE_GPIO),
@@ -80,10 +80,14 @@ ACPI_RSCONVERT_INFO AcpiRsConvertGpio[17] =
AML_OFFSET (Gpio.Flags),
0},
- {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Gpio.Sharable),
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Gpio.Sharable),
AML_OFFSET (Gpio.IntFlags),
3},
+ {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Gpio.WakeCapable),
+ AML_OFFSET (Gpio.IntFlags),
+ 4},
+
{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Gpio.IoRestriction),
AML_OFFSET (Gpio.IntFlags),
0},
diff --git a/sys/contrib/dev/acpica/components/resources/rsutils.c b/sys/contrib/dev/acpica/components/resources/rsutils.c
index cdbb389..78f4549 100644
--- a/sys/contrib/dev/acpica/components/resources/rsutils.c
+++ b/sys/contrib/dev/acpica/components/resources/rsutils.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -746,7 +746,8 @@ AcpiRsGetMethodData (
/* Execute the method, no parameters */
- Status = AcpiUtEvaluateObject (Handle, Path, ACPI_BTYPE_BUFFER, &ObjDesc);
+ Status = AcpiUtEvaluateObject (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle),
+ Path, ACPI_BTYPE_BUFFER, &ObjDesc);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
diff --git a/sys/contrib/dev/acpica/components/resources/rsxface.c b/sys/contrib/dev/acpica/components/resources/rsxface.c
index 9251aec..f70d8f6 100644
--- a/sys/contrib/dev/acpica/components/resources/rsxface.c
+++ b/sys/contrib/dev/acpica/components/resources/rsxface.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -474,7 +474,7 @@ ACPI_EXPORT_SYMBOL (AcpiResourceToAddress64)
*
* RETURN: Status
*
- * DESCRIPTION: Walk a resource template for the specified evice to find a
+ * DESCRIPTION: Walk a resource template for the specified device to find a
* vendor-defined resource that matches the supplied UUID and
* UUID subtype. Returns a ACPI_RESOURCE of type Vendor.
*
@@ -586,63 +586,45 @@ AcpiRsMatchVendorResource (
/*******************************************************************************
*
- * FUNCTION: AcpiWalkResources
+ * FUNCTION: AcpiWalkResourceBuffer
*
- * PARAMETERS: DeviceHandle - Handle to the device object for the
- * device we are querying
- * Name - Method name of the resources we want.
- * (METHOD_NAME__CRS, METHOD_NAME__PRS, or
- * METHOD_NAME__AEI)
+ * PARAMETERS: Buffer - Formatted buffer returned by one of the
+ * various Get*Resource functions
* UserFunction - Called for each resource
* Context - Passed to UserFunction
*
* RETURN: Status
*
- * DESCRIPTION: Retrieves the current or possible resource list for the
- * specified device. The UserFunction is called once for
- * each resource in the list.
+ * DESCRIPTION: Walks the input resource template. The UserFunction is called
+ * once for each resource in the list.
*
******************************************************************************/
ACPI_STATUS
-AcpiWalkResources (
- ACPI_HANDLE DeviceHandle,
- char *Name,
+AcpiWalkResourceBuffer (
+ ACPI_BUFFER *Buffer,
ACPI_WALK_RESOURCE_CALLBACK UserFunction,
void *Context)
{
- ACPI_STATUS Status;
- ACPI_BUFFER Buffer;
+ ACPI_STATUS Status = AE_OK;
ACPI_RESOURCE *Resource;
ACPI_RESOURCE *ResourceEnd;
- ACPI_FUNCTION_TRACE (AcpiWalkResources);
+ ACPI_FUNCTION_TRACE (AcpiWalkResourceBuffer);
/* Parameter validation */
- if (!DeviceHandle || !UserFunction || !Name ||
- (!ACPI_COMPARE_NAME (Name, METHOD_NAME__CRS) &&
- !ACPI_COMPARE_NAME (Name, METHOD_NAME__PRS) &&
- !ACPI_COMPARE_NAME (Name, METHOD_NAME__AEI)))
+ if (!Buffer || !Buffer->Pointer || !UserFunction)
{
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
- /* Get the _CRS/_PRS/_AEI resource list */
-
- Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- Status = AcpiRsGetMethodData (DeviceHandle, Name, &Buffer);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- /* Buffer now contains the resource list */
+ /* Buffer contains the resource list and length */
- Resource = ACPI_CAST_PTR (ACPI_RESOURCE, Buffer.Pointer);
- ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Buffer.Pointer, Buffer.Length);
+ Resource = ACPI_CAST_PTR (ACPI_RESOURCE, Buffer->Pointer);
+ ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Buffer->Pointer, Buffer->Length);
/* Walk the resource list until the EndTag is found (or buffer end) */
@@ -682,6 +664,68 @@ AcpiWalkResources (
Resource = ACPI_NEXT_RESOURCE (Resource);
}
+ return_ACPI_STATUS (Status);
+}
+
+ACPI_EXPORT_SYMBOL (AcpiWalkResourceBuffer)
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiWalkResources
+ *
+ * PARAMETERS: DeviceHandle - Handle to the device object for the
+ * device we are querying
+ * Name - Method name of the resources we want.
+ * (METHOD_NAME__CRS, METHOD_NAME__PRS, or
+ * METHOD_NAME__AEI)
+ * UserFunction - Called for each resource
+ * Context - Passed to UserFunction
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Retrieves the current or possible resource list for the
+ * specified device. The UserFunction is called once for
+ * each resource in the list.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiWalkResources (
+ ACPI_HANDLE DeviceHandle,
+ char *Name,
+ ACPI_WALK_RESOURCE_CALLBACK UserFunction,
+ void *Context)
+{
+ ACPI_STATUS Status;
+ ACPI_BUFFER Buffer;
+
+
+ ACPI_FUNCTION_TRACE (AcpiWalkResources);
+
+
+ /* Parameter validation */
+
+ if (!DeviceHandle || !UserFunction || !Name ||
+ (!ACPI_COMPARE_NAME (Name, METHOD_NAME__CRS) &&
+ !ACPI_COMPARE_NAME (Name, METHOD_NAME__PRS) &&
+ !ACPI_COMPARE_NAME (Name, METHOD_NAME__AEI)))
+ {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /* Get the _CRS/_PRS/_AEI resource list */
+
+ Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ Status = AcpiRsGetMethodData (DeviceHandle, Name, &Buffer);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /* Walk the resource list and cleanup */
+
+ Status = AcpiWalkResourceBuffer (&Buffer, UserFunction, Context);
ACPI_FREE (Buffer.Pointer);
return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/tables/tbfadt.c b/sys/contrib/dev/acpica/components/tables/tbfadt.c
index 3a53ae0..327f3a6 100644
--- a/sys/contrib/dev/acpica/components/tables/tbfadt.c
+++ b/sys/contrib/dev/acpica/components/tables/tbfadt.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/tables/tbfind.c b/sys/contrib/dev/acpica/components/tables/tbfind.c
index ccb4029..6cd30e8 100644
--- a/sys/contrib/dev/acpica/components/tables/tbfind.c
+++ b/sys/contrib/dev/acpica/components/tables/tbfind.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/tables/tbinstal.c b/sys/contrib/dev/acpica/components/tables/tbinstal.c
index c2035aa..e6558ff 100644
--- a/sys/contrib/dev/acpica/components/tables/tbinstal.c
+++ b/sys/contrib/dev/acpica/components/tables/tbinstal.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/tables/tbutils.c b/sys/contrib/dev/acpica/components/tables/tbutils.c
index a97a1e9..500c2f1 100644
--- a/sys/contrib/dev/acpica/components/tables/tbutils.c
+++ b/sys/contrib/dev/acpica/components/tables/tbutils.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/tables/tbxface.c b/sys/contrib/dev/acpica/components/tables/tbxface.c
index 33d3591..e040944 100644
--- a/sys/contrib/dev/acpica/components/tables/tbxface.c
+++ b/sys/contrib/dev/acpica/components/tables/tbxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/tables/tbxfload.c b/sys/contrib/dev/acpica/components/tables/tbxfload.c
index d06683d..5a4906f 100644
--- a/sys/contrib/dev/acpica/components/tables/tbxfload.c
+++ b/sys/contrib/dev/acpica/components/tables/tbxfload.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -208,7 +208,7 @@ AcpiTbLoadNamespace (
(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
}
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
+ ACPI_INFO ((AE_INFO, "All ACPI Tables successfully acquired"));
UnlockAndExit:
(void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
diff --git a/sys/contrib/dev/acpica/components/tables/tbxfroot.c b/sys/contrib/dev/acpica/components/tables/tbxfroot.c
index db06a8a..1d8909b 100644
--- a/sys/contrib/dev/acpica/components/tables/tbxfroot.c
+++ b/sys/contrib/dev/acpica/components/tables/tbxfroot.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utaddress.c b/sys/contrib/dev/acpica/components/utilities/utaddress.c
index ca73b69..715c77b 100644
--- a/sys/contrib/dev/acpica/components/utilities/utaddress.c
+++ b/sys/contrib/dev/acpica/components/utilities/utaddress.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -237,7 +237,7 @@ AcpiUtCheckAddressRange (
if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
(SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
{
- return_UINT32 (0);
+ return_VALUE (0);
}
RangeInfo = AcpiGbl_AddressRangeList[SpaceId];
@@ -278,7 +278,7 @@ AcpiUtCheckAddressRange (
RangeInfo = RangeInfo->Next;
}
- return_UINT32 (OverlapCount);
+ return_VALUE (OverlapCount);
}
diff --git a/sys/contrib/dev/acpica/components/utilities/utalloc.c b/sys/contrib/dev/acpica/components/utilities/utalloc.c
index 0ea15af..0bdb2ff 100644
--- a/sys/contrib/dev/acpica/components/utilities/utalloc.c
+++ b/sys/contrib/dev/acpica/components/utilities/utalloc.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utcache.c b/sys/contrib/dev/acpica/components/utilities/utcache.c
index e21cb48..2aa3e5b 100644
--- a/sys/contrib/dev/acpica/components/utilities/utcache.c
+++ b/sys/contrib/dev/acpica/components/utilities/utcache.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -95,7 +95,6 @@ AcpiOsCreateCache (
/* Populate the cache object and return it */
ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST));
- Cache->LinkOffset = 8;
Cache->ListName = CacheName;
Cache->ObjectSize = ObjectSize;
Cache->MaxDepth = MaxDepth;
@@ -121,7 +120,7 @@ ACPI_STATUS
AcpiOsPurgeCache (
ACPI_MEMORY_LIST *Cache)
{
- char *Next;
+ void *Next;
ACPI_STATUS Status;
@@ -145,8 +144,7 @@ AcpiOsPurgeCache (
{
/* Delete and unlink one cached state object */
- Next = *(ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) Cache->ListHead)[Cache->LinkOffset])));
+ Next = ACPI_GET_DESCRIPTOR_PTR (Cache->ListHead);
ACPI_FREE (Cache->ListHead);
Cache->ListHead = Next;
@@ -251,8 +249,7 @@ AcpiOsReleaseObject (
/* Put the object at the head of the cache list */
- * (ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) Object)[Cache->LinkOffset]))) = Cache->ListHead;
+ ACPI_SET_DESCRIPTOR_PTR (Object, Cache->ListHead);
Cache->ListHead = Object;
Cache->CurrentDepth++;
@@ -307,8 +304,7 @@ AcpiOsAcquireObject (
/* There is an object available, use it */
Object = Cache->ListHead;
- Cache->ListHead = *(ACPI_CAST_INDIRECT_PTR (char,
- &(((char *) Object)[Cache->LinkOffset])));
+ Cache->ListHead = ACPI_GET_DESCRIPTOR_PTR (Object);
Cache->CurrentDepth--;
diff --git a/sys/contrib/dev/acpica/components/utilities/utcopy.c b/sys/contrib/dev/acpica/components/utilities/utcopy.c
index dd8de9e..696acf0 100644
--- a/sys/contrib/dev/acpica/components/utilities/utcopy.c
+++ b/sys/contrib/dev/acpica/components/utilities/utcopy.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utdebug.c b/sys/contrib/dev/acpica/components/utilities/utdebug.c
index 5834c0f..a299680 100644
--- a/sys/contrib/dev/acpica/components/utilities/utdebug.c
+++ b/sys/contrib/dev/acpica/components/utilities/utdebug.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -189,11 +189,9 @@ AcpiDebugPrint (
va_list args;
- /*
- * Stay silent if the debug level or component ID is disabled
- */
- if (!(RequestedDebugLevel & AcpiDbgLevel) ||
- !(ComponentId & AcpiDbgLayer))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (RequestedDebugLevel, ComponentId))
{
return;
}
@@ -268,8 +266,9 @@ AcpiDebugPrintRaw (
va_list args;
- if (!(RequestedDebugLevel & AcpiDbgLevel) ||
- !(ComponentId & AcpiDbgLayer))
+ /* Check if debug output enabled */
+
+ if (!ACPI_IS_DEBUG_ENABLED (RequestedDebugLevel, ComponentId))
{
return;
}
@@ -309,9 +308,14 @@ AcpiUtTrace (
AcpiGbl_NestingLevel++;
AcpiUtTrackStackPtr ();
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s\n", AcpiGbl_FnEntryStr);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s\n", AcpiGbl_FnEntryStr);
+ }
}
ACPI_EXPORT_SYMBOL (AcpiUtTrace)
@@ -346,9 +350,14 @@ AcpiUtTracePtr (
AcpiGbl_NestingLevel++;
AcpiUtTrackStackPtr ();
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %p\n", AcpiGbl_FnEntryStr, Pointer);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %p\n", AcpiGbl_FnEntryStr, Pointer);
+ }
}
@@ -381,9 +390,14 @@ AcpiUtTraceStr (
AcpiGbl_NestingLevel++;
AcpiUtTrackStackPtr ();
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %s\n", AcpiGbl_FnEntryStr, String);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %s\n", AcpiGbl_FnEntryStr, String);
+ }
}
@@ -416,9 +430,14 @@ AcpiUtTraceU32 (
AcpiGbl_NestingLevel++;
AcpiUtTrackStackPtr ();
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %08X\n", AcpiGbl_FnEntryStr, Integer);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %08X\n", AcpiGbl_FnEntryStr, Integer);
+ }
}
@@ -446,9 +465,14 @@ AcpiUtExit (
UINT32 ComponentId)
{
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s\n", AcpiGbl_FnExitStr);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s\n", AcpiGbl_FnExitStr);
+ }
AcpiGbl_NestingLevel--;
}
@@ -482,19 +506,24 @@ AcpiUtStatusExit (
ACPI_STATUS Status)
{
- if (ACPI_SUCCESS (Status))
- {
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %s\n", AcpiGbl_FnExitStr,
- AcpiFormatException (Status));
- }
- else
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
{
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s ****Exception****: %s\n", AcpiGbl_FnExitStr,
- AcpiFormatException (Status));
+ if (ACPI_SUCCESS (Status))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %s\n", AcpiGbl_FnExitStr,
+ AcpiFormatException (Status));
+ }
+ else
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s ****Exception****: %s\n", AcpiGbl_FnExitStr,
+ AcpiFormatException (Status));
+ }
}
AcpiGbl_NestingLevel--;
@@ -529,10 +558,15 @@ AcpiUtValueExit (
UINT64 Value)
{
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %8.8X%8.8X\n", AcpiGbl_FnExitStr,
- ACPI_FORMAT_UINT64 (Value));
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %8.8X%8.8X\n", AcpiGbl_FnExitStr,
+ ACPI_FORMAT_UINT64 (Value));
+ }
AcpiGbl_NestingLevel--;
}
@@ -566,9 +600,14 @@ AcpiUtPtrExit (
UINT8 *Ptr)
{
- AcpiDebugPrint (ACPI_LV_FUNCTIONS,
- LineNumber, FunctionName, ModuleName, ComponentId,
- "%s %p\n", AcpiGbl_FnExitStr, Ptr);
+ /* Check if enabled up-front for performance */
+
+ if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId))
+ {
+ AcpiDebugPrint (ACPI_LV_FUNCTIONS,
+ LineNumber, FunctionName, ModuleName, ComponentId,
+ "%s %p\n", AcpiGbl_FnExitStr, Ptr);
+ }
AcpiGbl_NestingLevel--;
}
diff --git a/sys/contrib/dev/acpica/components/utilities/utdecode.c b/sys/contrib/dev/acpica/components/utilities/utdecode.c
index ef423e9..3075479 100644
--- a/sys/contrib/dev/acpica/components/utilities/utdecode.c
+++ b/sys/contrib/dev/acpica/components/utilities/utdecode.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utdelete.c b/sys/contrib/dev/acpica/components/utilities/utdelete.c
index 77dbe1b..b73e2d8 100644
--- a/sys/contrib/dev/acpica/components/utilities/utdelete.c
+++ b/sys/contrib/dev/acpica/components/utilities/utdelete.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -368,7 +368,7 @@ AcpiUtDeleteInternalObjectList (
ACPI_OPERAND_OBJECT **InternalObj;
- ACPI_FUNCTION_NAME (UtDeleteInternalObjectList);
+ ACPI_FUNCTION_ENTRY ();
/* Walk the null-terminated internal list */
diff --git a/sys/contrib/dev/acpica/components/utilities/uteval.c b/sys/contrib/dev/acpica/components/utilities/uteval.c
index 57dbec0..95233f4 100644
--- a/sys/contrib/dev/acpica/components/utilities/uteval.c
+++ b/sys/contrib/dev/acpica/components/utilities/uteval.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utexcep.c b/sys/contrib/dev/acpica/components/utilities/utexcep.c
index 0f38227..2d3ae17 100644
--- a/sys/contrib/dev/acpica/components/utilities/utexcep.c
+++ b/sys/contrib/dev/acpica/components/utilities/utexcep.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utglobal.c b/sys/contrib/dev/acpica/components/utilities/utglobal.c
index 5bb5991..6d2f906 100644
--- a/sys/contrib/dev/acpica/components/utilities/utglobal.c
+++ b/sys/contrib/dev/acpica/components/utilities/utglobal.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utids.c b/sys/contrib/dev/acpica/components/utilities/utids.c
index 17ad5ed..c73c8ed 100644
--- a/sys/contrib/dev/acpica/components/utilities/utids.c
+++ b/sys/contrib/dev/acpica/components/utilities/utids.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utinit.c b/sys/contrib/dev/acpica/components/utilities/utinit.c
index 7b53c9a..760d789 100644
--- a/sys/contrib/dev/acpica/components/utilities/utinit.c
+++ b/sys/contrib/dev/acpica/components/utilities/utinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utlock.c b/sys/contrib/dev/acpica/components/utilities/utlock.c
index 40fc8f8..da933c2 100644
--- a/sys/contrib/dev/acpica/components/utilities/utlock.c
+++ b/sys/contrib/dev/acpica/components/utilities/utlock.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utmath.c b/sys/contrib/dev/acpica/components/utilities/utmath.c
index ec51855..b535ffc 100644
--- a/sys/contrib/dev/acpica/components/utilities/utmath.c
+++ b/sys/contrib/dev/acpica/components/utilities/utmath.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utmisc.c b/sys/contrib/dev/acpica/components/utilities/utmisc.c
index 70fdb50..7d013fc 100644
--- a/sys/contrib/dev/acpica/components/utilities/utmisc.c
+++ b/sys/contrib/dev/acpica/components/utilities/utmisc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,43 +53,6 @@
ACPI_MODULE_NAME ("utmisc")
-#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP
-/*******************************************************************************
- *
- * FUNCTION: UtConvertBackslashes
- *
- * PARAMETERS: Pathname - File pathname string to be converted
- *
- * RETURN: Modifies the input Pathname
- *
- * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within
- * the entire input file pathname string.
- *
- ******************************************************************************/
-
-void
-UtConvertBackslashes (
- char *Pathname)
-{
-
- if (!Pathname)
- {
- return;
- }
-
- while (*Pathname)
- {
- if (*Pathname == '\\')
- {
- *Pathname = '/';
- }
-
- Pathname++;
- }
-}
-#endif
-
-
/*******************************************************************************
*
* FUNCTION: AcpiUtIsPciRootBridge
@@ -158,411 +121,6 @@ AcpiUtIsAmlTable (
/*******************************************************************************
*
- * FUNCTION: AcpiUtAllocateOwnerId
- *
- * PARAMETERS: OwnerId - Where the new owner ID is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
- * track objects created by the table or method, to be deleted
- * when the method exits or the table is unloaded.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiUtAllocateOwnerId (
- ACPI_OWNER_ID *OwnerId)
-{
- UINT32 i;
- UINT32 j;
- UINT32 k;
- ACPI_STATUS Status;
-
-
- ACPI_FUNCTION_TRACE (UtAllocateOwnerId);
-
-
- /* Guard against multiple allocations of ID to the same location */
-
- if (*OwnerId)
- {
- ACPI_ERROR ((AE_INFO, "Owner ID [0x%2.2X] already exists", *OwnerId));
- return_ACPI_STATUS (AE_ALREADY_EXISTS);
- }
-
- /* Mutex for the global ID mask */
-
- Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
-
- /*
- * Find a free owner ID, cycle through all possible IDs on repeated
- * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have
- * to be scanned twice.
- */
- for (i = 0, j = AcpiGbl_LastOwnerIdIndex;
- i < (ACPI_NUM_OWNERID_MASKS + 1);
- i++, j++)
- {
- if (j >= ACPI_NUM_OWNERID_MASKS)
- {
- j = 0; /* Wraparound to start of mask array */
- }
-
- for (k = AcpiGbl_NextOwnerIdOffset; k < 32; k++)
- {
- if (AcpiGbl_OwnerIdMask[j] == ACPI_UINT32_MAX)
- {
- /* There are no free IDs in this mask */
-
- break;
- }
-
- if (!(AcpiGbl_OwnerIdMask[j] & (1 << k)))
- {
- /*
- * Found a free ID. The actual ID is the bit index plus one,
- * making zero an invalid Owner ID. Save this as the last ID
- * allocated and update the global ID mask.
- */
- AcpiGbl_OwnerIdMask[j] |= (1 << k);
-
- AcpiGbl_LastOwnerIdIndex = (UINT8) j;
- AcpiGbl_NextOwnerIdOffset = (UINT8) (k + 1);
-
- /*
- * Construct encoded ID from the index and bit position
- *
- * Note: Last [j].k (bit 255) is never used and is marked
- * permanently allocated (prevents +1 overflow)
- */
- *OwnerId = (ACPI_OWNER_ID) ((k + 1) + ACPI_MUL_32 (j));
-
- ACPI_DEBUG_PRINT ((ACPI_DB_VALUES,
- "Allocated OwnerId: %2.2X\n", (unsigned int) *OwnerId));
- goto Exit;
- }
- }
-
- AcpiGbl_NextOwnerIdOffset = 0;
- }
-
- /*
- * All OwnerIds have been allocated. This typically should
- * not happen since the IDs are reused after deallocation. The IDs are
- * allocated upon table load (one per table) and method execution, and
- * they are released when a table is unloaded or a method completes
- * execution.
- *
- * If this error happens, there may be very deep nesting of invoked control
- * methods, or there may be a bug where the IDs are not released.
- */
- Status = AE_OWNER_ID_LIMIT;
- ACPI_ERROR ((AE_INFO,
- "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
-
-Exit:
- (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
- return_ACPI_STATUS (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtReleaseOwnerId
- *
- * PARAMETERS: OwnerIdPtr - Pointer to a previously allocated OwnerID
- *
- * RETURN: None. No error is returned because we are either exiting a
- * control method or unloading a table. Either way, we would
- * ignore any error anyway.
- *
- * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
- *
- ******************************************************************************/
-
-void
-AcpiUtReleaseOwnerId (
- ACPI_OWNER_ID *OwnerIdPtr)
-{
- ACPI_OWNER_ID OwnerId = *OwnerIdPtr;
- ACPI_STATUS Status;
- UINT32 Index;
- UINT32 Bit;
-
-
- ACPI_FUNCTION_TRACE_U32 (UtReleaseOwnerId, OwnerId);
-
-
- /* Always clear the input OwnerId (zero is an invalid ID) */
-
- *OwnerIdPtr = 0;
-
- /* Zero is not a valid OwnerID */
-
- if (OwnerId == 0)
- {
- ACPI_ERROR ((AE_INFO, "Invalid OwnerId: 0x%2.2X", OwnerId));
- return_VOID;
- }
-
- /* Mutex for the global ID mask */
-
- Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
- if (ACPI_FAILURE (Status))
- {
- return_VOID;
- }
-
- /* Normalize the ID to zero */
-
- OwnerId--;
-
- /* Decode ID to index/offset pair */
-
- Index = ACPI_DIV_32 (OwnerId);
- Bit = 1 << ACPI_MOD_32 (OwnerId);
-
- /* Free the owner ID only if it is valid */
-
- if (AcpiGbl_OwnerIdMask[Index] & Bit)
- {
- AcpiGbl_OwnerIdMask[Index] ^= Bit;
- }
- else
- {
- ACPI_ERROR ((AE_INFO,
- "Release of non-allocated OwnerId: 0x%2.2X", OwnerId + 1));
- }
-
- (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
- return_VOID;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtStrupr (strupr)
- *
- * PARAMETERS: SrcString - The source string to convert
- *
- * RETURN: None
- *
- * DESCRIPTION: Convert string to uppercase
- *
- * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
- *
- ******************************************************************************/
-
-void
-AcpiUtStrupr (
- char *SrcString)
-{
- char *String;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- if (!SrcString)
- {
- return;
- }
-
- /* Walk entire string, uppercasing the letters */
-
- for (String = SrcString; *String; String++)
- {
- *String = (char) ACPI_TOUPPER (*String);
- }
-
- return;
-}
-
-
-#ifdef ACPI_ASL_COMPILER
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtStrlwr (strlwr)
- *
- * PARAMETERS: SrcString - The source string to convert
- *
- * RETURN: None
- *
- * DESCRIPTION: Convert string to lowercase
- *
- * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
- *
- ******************************************************************************/
-
-void
-AcpiUtStrlwr (
- char *SrcString)
-{
- char *String;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- if (!SrcString)
- {
- return;
- }
-
- /* Walk entire string, lowercasing the letters */
-
- for (String = SrcString; *String; String++)
- {
- *String = (char) ACPI_TOLOWER (*String);
- }
-
- return;
-}
-
-
-/******************************************************************************
- *
- * FUNCTION: AcpiUtStricmp
- *
- * PARAMETERS: String1 - first string to compare
- * String2 - second string to compare
- *
- * RETURN: int that signifies string relationship. Zero means strings
- * are equal.
- *
- * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare
- * strings with no case sensitivity)
- *
- ******************************************************************************/
-
-int
-AcpiUtStricmp (
- char *String1,
- char *String2)
-{
- int c1;
- int c2;
-
-
- do
- {
- c1 = tolower ((int) *String1);
- c2 = tolower ((int) *String2);
-
- String1++;
- String2++;
- }
- while ((c1 == c2) && (c1));
-
- return (c1 - c2);
-}
-#endif
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtPrintString
- *
- * PARAMETERS: String - Null terminated ASCII string
- * MaxLength - Maximum output length
- *
- * RETURN: None
- *
- * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape
- * sequences.
- *
- ******************************************************************************/
-
-void
-AcpiUtPrintString (
- char *String,
- UINT8 MaxLength)
-{
- UINT32 i;
-
-
- if (!String)
- {
- AcpiOsPrintf ("<\"NULL STRING PTR\">");
- return;
- }
-
- AcpiOsPrintf ("\"");
- for (i = 0; String[i] && (i < MaxLength); i++)
- {
- /* Escape sequences */
-
- switch (String[i])
- {
- case 0x07:
- AcpiOsPrintf ("\\a"); /* BELL */
- break;
-
- case 0x08:
- AcpiOsPrintf ("\\b"); /* BACKSPACE */
- break;
-
- case 0x0C:
- AcpiOsPrintf ("\\f"); /* FORMFEED */
- break;
-
- case 0x0A:
- AcpiOsPrintf ("\\n"); /* LINEFEED */
- break;
-
- case 0x0D:
- AcpiOsPrintf ("\\r"); /* CARRIAGE RETURN*/
- break;
-
- case 0x09:
- AcpiOsPrintf ("\\t"); /* HORIZONTAL TAB */
- break;
-
- case 0x0B:
- AcpiOsPrintf ("\\v"); /* VERTICAL TAB */
- break;
-
- case '\'': /* Single Quote */
- case '\"': /* Double Quote */
- case '\\': /* Backslash */
- AcpiOsPrintf ("\\%c", (int) String[i]);
- break;
-
- default:
-
- /* Check for printable character or hex escape */
-
- if (ACPI_IS_PRINT (String[i]))
- {
- /* This is a normal character */
-
- AcpiOsPrintf ("%c", (int) String[i]);
- }
- else
- {
- /* All others will be Hex escapes */
-
- AcpiOsPrintf ("\\x%2.2X", (INT32) String[i]);
- }
- break;
- }
- }
- AcpiOsPrintf ("\"");
-
- if (i == MaxLength && String[i])
- {
- AcpiOsPrintf ("...");
- }
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: AcpiUtDwordByteSwap
*
* PARAMETERS: Value - Value to be converted
@@ -642,444 +200,6 @@ AcpiUtSetIntegerWidth (
}
-#ifdef ACPI_DEBUG_OUTPUT
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtDisplayInitPathname
- *
- * PARAMETERS: Type - Object type of the node
- * ObjHandle - Handle whose pathname will be displayed
- * Path - Additional path string to be appended.
- * (NULL if no extra path)
- *
- * RETURN: ACPI_STATUS
- *
- * DESCRIPTION: Display full pathname of an object, DEBUG ONLY
- *
- ******************************************************************************/
-
-void
-AcpiUtDisplayInitPathname (
- UINT8 Type,
- ACPI_NAMESPACE_NODE *ObjHandle,
- char *Path)
-{
- ACPI_STATUS Status;
- ACPI_BUFFER Buffer;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- /* Only print the path if the appropriate debug level is enabled */
-
- if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES))
- {
- return;
- }
-
- /* Get the full pathname to the node */
-
- Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
- Status = AcpiNsHandleToPathname (ObjHandle, &Buffer);
- if (ACPI_FAILURE (Status))
- {
- return;
- }
-
- /* Print what we're doing */
-
- switch (Type)
- {
- case ACPI_TYPE_METHOD:
- AcpiOsPrintf ("Executing ");
- break;
-
- default:
- AcpiOsPrintf ("Initializing ");
- break;
- }
-
- /* Print the object type and pathname */
-
- AcpiOsPrintf ("%-12s %s",
- AcpiUtGetTypeName (Type), (char *) Buffer.Pointer);
-
- /* Extra path is used to append names like _STA, _INI, etc. */
-
- if (Path)
- {
- AcpiOsPrintf (".%s", Path);
- }
- AcpiOsPrintf ("\n");
-
- ACPI_FREE (Buffer.Pointer);
-}
-#endif
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtValidAcpiChar
- *
- * PARAMETERS: Char - The character to be examined
- * Position - Byte position (0-3)
- *
- * RETURN: TRUE if the character is valid, FALSE otherwise
- *
- * DESCRIPTION: Check for a valid ACPI character. Must be one of:
- * 1) Upper case alpha
- * 2) numeric
- * 3) underscore
- *
- * We allow a '!' as the last character because of the ASF! table
- *
- ******************************************************************************/
-
-BOOLEAN
-AcpiUtValidAcpiChar (
- char Character,
- UINT32 Position)
-{
-
- if (!((Character >= 'A' && Character <= 'Z') ||
- (Character >= '0' && Character <= '9') ||
- (Character == '_')))
- {
- /* Allow a '!' in the last position */
-
- if (Character == '!' && Position == 3)
- {
- return (TRUE);
- }
-
- return (FALSE);
- }
-
- return (TRUE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtValidAcpiName
- *
- * PARAMETERS: Name - The name to be examined
- *
- * RETURN: TRUE if the name is valid, FALSE otherwise
- *
- * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
- * 1) Upper case alpha
- * 2) numeric
- * 3) underscore
- *
- ******************************************************************************/
-
-BOOLEAN
-AcpiUtValidAcpiName (
- UINT32 Name)
-{
- UINT32 i;
-
-
- ACPI_FUNCTION_ENTRY ();
-
-
- for (i = 0; i < ACPI_NAME_SIZE; i++)
- {
- if (!AcpiUtValidAcpiChar ((ACPI_CAST_PTR (char, &Name))[i], i))
- {
- return (FALSE);
- }
- }
-
- return (TRUE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtRepairName
- *
- * PARAMETERS: Name - The ACPI name to be repaired
- *
- * RETURN: Repaired version of the name
- *
- * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and
- * return the new name. NOTE: the Name parameter must reside in
- * read/write memory, cannot be a const.
- *
- * An ACPI Name must consist of valid ACPI characters. We will repair the name
- * if necessary because we don't want to abort because of this, but we want
- * all namespace names to be printable. A warning message is appropriate.
- *
- * This issue came up because there are in fact machines that exhibit
- * this problem, and we want to be able to enable ACPI support for them,
- * even though there are a few bad names.
- *
- ******************************************************************************/
-
-void
-AcpiUtRepairName (
- char *Name)
-{
- UINT32 i;
- BOOLEAN FoundBadChar = FALSE;
- UINT32 OriginalName;
-
-
- ACPI_FUNCTION_NAME (UtRepairName);
-
-
- ACPI_MOVE_NAME (&OriginalName, Name);
-
- /* Check each character in the name */
-
- for (i = 0; i < ACPI_NAME_SIZE; i++)
- {
- if (AcpiUtValidAcpiChar (Name[i], i))
- {
- continue;
- }
-
- /*
- * Replace a bad character with something printable, yet technically
- * still invalid. This prevents any collisions with existing "good"
- * names in the namespace.
- */
- Name[i] = '*';
- FoundBadChar = TRUE;
- }
-
- if (FoundBadChar)
- {
- /* Report warning only if in strict mode or debug mode */
-
- if (!AcpiGbl_EnableInterpreterSlack)
- {
- ACPI_WARNING ((AE_INFO,
- "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
- OriginalName, Name));
- }
- else
- {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
- OriginalName, Name));
- }
- }
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiUtStrtoul64
- *
- * PARAMETERS: String - Null terminated string
- * Base - Radix of the string: 16 or ACPI_ANY_BASE;
- * ACPI_ANY_BASE means 'in behalf of ToInteger'
- * RetInteger - Where the converted integer is returned
- *
- * RETURN: Status and Converted value
- *
- * DESCRIPTION: Convert a string into an unsigned value. Performs either a
- * 32-bit or 64-bit conversion, depending on the current mode
- * of the interpreter.
- * NOTE: Does not support Octal strings, not needed.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiUtStrtoul64 (
- char *String,
- UINT32 Base,
- UINT64 *RetInteger)
-{
- UINT32 ThisDigit = 0;
- UINT64 ReturnValue = 0;
- UINT64 Quotient;
- UINT64 Dividend;
- UINT32 ToIntegerOp = (Base == ACPI_ANY_BASE);
- UINT32 Mode32 = (AcpiGbl_IntegerByteWidth == 4);
- UINT8 ValidDigits = 0;
- UINT8 SignOf0x = 0;
- UINT8 Term = 0;
-
-
- ACPI_FUNCTION_TRACE_STR (UtStroul64, String);
-
-
- switch (Base)
- {
- case ACPI_ANY_BASE:
- case 16:
- break;
-
- default:
- /* Invalid Base */
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
-
- if (!String)
- {
- goto ErrorExit;
- }
-
- /* Skip over any white space in the buffer */
-
- while ((*String) && (ACPI_IS_SPACE (*String) || *String == '\t'))
- {
- String++;
- }
-
- if (ToIntegerOp)
- {
- /*
- * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'.
- * We need to determine if it is decimal or hexadecimal.
- */
- if ((*String == '0') && (ACPI_TOLOWER (*(String + 1)) == 'x'))
- {
- SignOf0x = 1;
- Base = 16;
-
- /* Skip over the leading '0x' */
- String += 2;
- }
- else
- {
- Base = 10;
- }
- }
-
- /* Any string left? Check that '0x' is not followed by white space. */
-
- if (!(*String) || ACPI_IS_SPACE (*String) || *String == '\t')
- {
- if (ToIntegerOp)
- {
- goto ErrorExit;
- }
- else
- {
- goto AllDone;
- }
- }
-
- /*
- * Perform a 32-bit or 64-bit conversion, depending upon the current
- * execution mode of the interpreter
- */
- Dividend = (Mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
-
- /* Main loop: convert the string to a 32- or 64-bit integer */
-
- while (*String)
- {
- if (ACPI_IS_DIGIT (*String))
- {
- /* Convert ASCII 0-9 to Decimal value */
-
- ThisDigit = ((UINT8) *String) - '0';
- }
- else if (Base == 10)
- {
- /* Digit is out of range; possible in ToInteger case only */
-
- Term = 1;
- }
- else
- {
- ThisDigit = (UINT8) ACPI_TOUPPER (*String);
- if (ACPI_IS_XDIGIT ((char) ThisDigit))
- {
- /* Convert ASCII Hex char to value */
-
- ThisDigit = ThisDigit - 'A' + 10;
- }
- else
- {
- Term = 1;
- }
- }
-
- if (Term)
- {
- if (ToIntegerOp)
- {
- goto ErrorExit;
- }
- else
- {
- break;
- }
- }
- else if ((ValidDigits == 0) && (ThisDigit == 0) && !SignOf0x)
- {
- /* Skip zeros */
- String++;
- continue;
- }
-
- ValidDigits++;
-
- if (SignOf0x && ((ValidDigits > 16) || ((ValidDigits > 8) && Mode32)))
- {
- /*
- * This is ToInteger operation case.
- * No any restrictions for string-to-integer conversion,
- * see ACPI spec.
- */
- goto ErrorExit;
- }
-
- /* Divide the digit into the correct position */
-
- (void) AcpiUtShortDivide ((Dividend - (UINT64) ThisDigit),
- Base, &Quotient, NULL);
-
- if (ReturnValue > Quotient)
- {
- if (ToIntegerOp)
- {
- goto ErrorExit;
- }
- else
- {
- break;
- }
- }
-
- ReturnValue *= Base;
- ReturnValue += ThisDigit;
- String++;
- }
-
- /* All done, normal exit */
-
-AllDone:
-
- ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
- ACPI_FORMAT_UINT64 (ReturnValue)));
-
- *RetInteger = ReturnValue;
- return_ACPI_STATUS (AE_OK);
-
-
-ErrorExit:
- /* Base was set/validated above */
-
- if (Base == 10)
- {
- return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT);
- }
- else
- {
- return_ACPI_STATUS (AE_BAD_HEX_CONSTANT);
- }
-}
-
-
/*******************************************************************************
*
* FUNCTION: AcpiUtCreateUpdateStateAndPush
@@ -1257,3 +377,79 @@ AcpiUtWalkPackageTree (
return_ACPI_STATUS (AE_AML_INTERNAL);
}
+
+
+#ifdef ACPI_DEBUG_OUTPUT
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtDisplayInitPathname
+ *
+ * PARAMETERS: Type - Object type of the node
+ * ObjHandle - Handle whose pathname will be displayed
+ * Path - Additional path string to be appended.
+ * (NULL if no extra path)
+ *
+ * RETURN: ACPI_STATUS
+ *
+ * DESCRIPTION: Display full pathname of an object, DEBUG ONLY
+ *
+ ******************************************************************************/
+
+void
+AcpiUtDisplayInitPathname (
+ UINT8 Type,
+ ACPI_NAMESPACE_NODE *ObjHandle,
+ char *Path)
+{
+ ACPI_STATUS Status;
+ ACPI_BUFFER Buffer;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ /* Only print the path if the appropriate debug level is enabled */
+
+ if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES))
+ {
+ return;
+ }
+
+ /* Get the full pathname to the node */
+
+ Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
+ Status = AcpiNsHandleToPathname (ObjHandle, &Buffer);
+ if (ACPI_FAILURE (Status))
+ {
+ return;
+ }
+
+ /* Print what we're doing */
+
+ switch (Type)
+ {
+ case ACPI_TYPE_METHOD:
+ AcpiOsPrintf ("Executing ");
+ break;
+
+ default:
+ AcpiOsPrintf ("Initializing ");
+ break;
+ }
+
+ /* Print the object type and pathname */
+
+ AcpiOsPrintf ("%-12s %s",
+ AcpiUtGetTypeName (Type), (char *) Buffer.Pointer);
+
+ /* Extra path is used to append names like _STA, _INI, etc. */
+
+ if (Path)
+ {
+ AcpiOsPrintf (".%s", Path);
+ }
+ AcpiOsPrintf ("\n");
+
+ ACPI_FREE (Buffer.Pointer);
+}
+#endif
diff --git a/sys/contrib/dev/acpica/components/utilities/utmutex.c b/sys/contrib/dev/acpica/components/utilities/utmutex.c
index 14b9aa7..90717f1 100644
--- a/sys/contrib/dev/acpica/components/utilities/utmutex.c
+++ b/sys/contrib/dev/acpica/components/utilities/utmutex.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utobject.c b/sys/contrib/dev/acpica/components/utilities/utobject.c
index d4d211a..daa8e40 100644
--- a/sys/contrib/dev/acpica/components/utilities/utobject.c
+++ b/sys/contrib/dev/acpica/components/utilities/utobject.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -725,7 +725,7 @@ AcpiUtGetPackageObjectSize (
Info.NumPackages = 1;
Status = AcpiUtWalkPackageTree (InternalObject, NULL,
- AcpiUtGetElementLength, &Info);
+ AcpiUtGetElementLength, &Info);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
diff --git a/sys/contrib/dev/acpica/components/utilities/utosi.c b/sys/contrib/dev/acpica/components/utilities/utosi.c
index bd173b7..424cfb6 100644
--- a/sys/contrib/dev/acpica/components/utilities/utosi.c
+++ b/sys/contrib/dev/acpica/components/utilities/utosi.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utownerid.c b/sys/contrib/dev/acpica/components/utilities/utownerid.c
new file mode 100644
index 0000000..74f4d83
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/utilities/utownerid.c
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ *
+ * Module Name: utownerid - Support for Table/Method Owner IDs
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#define __UTOWNERID_C__
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acnamesp.h>
+
+
+#define _COMPONENT ACPI_UTILITIES
+ ACPI_MODULE_NAME ("utownerid")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtAllocateOwnerId
+ *
+ * PARAMETERS: OwnerId - Where the new owner ID is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
+ * track objects created by the table or method, to be deleted
+ * when the method exits or the table is unloaded.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiUtAllocateOwnerId (
+ ACPI_OWNER_ID *OwnerId)
+{
+ UINT32 i;
+ UINT32 j;
+ UINT32 k;
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE (UtAllocateOwnerId);
+
+
+ /* Guard against multiple allocations of ID to the same location */
+
+ if (*OwnerId)
+ {
+ ACPI_ERROR ((AE_INFO, "Owner ID [0x%2.2X] already exists", *OwnerId));
+ return_ACPI_STATUS (AE_ALREADY_EXISTS);
+ }
+
+ /* Mutex for the global ID mask */
+
+ Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
+ if (ACPI_FAILURE (Status))
+ {
+ return_ACPI_STATUS (Status);
+ }
+
+ /*
+ * Find a free owner ID, cycle through all possible IDs on repeated
+ * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have
+ * to be scanned twice.
+ */
+ for (i = 0, j = AcpiGbl_LastOwnerIdIndex;
+ i < (ACPI_NUM_OWNERID_MASKS + 1);
+ i++, j++)
+ {
+ if (j >= ACPI_NUM_OWNERID_MASKS)
+ {
+ j = 0; /* Wraparound to start of mask array */
+ }
+
+ for (k = AcpiGbl_NextOwnerIdOffset; k < 32; k++)
+ {
+ if (AcpiGbl_OwnerIdMask[j] == ACPI_UINT32_MAX)
+ {
+ /* There are no free IDs in this mask */
+
+ break;
+ }
+
+ if (!(AcpiGbl_OwnerIdMask[j] & (1 << k)))
+ {
+ /*
+ * Found a free ID. The actual ID is the bit index plus one,
+ * making zero an invalid Owner ID. Save this as the last ID
+ * allocated and update the global ID mask.
+ */
+ AcpiGbl_OwnerIdMask[j] |= (1 << k);
+
+ AcpiGbl_LastOwnerIdIndex = (UINT8) j;
+ AcpiGbl_NextOwnerIdOffset = (UINT8) (k + 1);
+
+ /*
+ * Construct encoded ID from the index and bit position
+ *
+ * Note: Last [j].k (bit 255) is never used and is marked
+ * permanently allocated (prevents +1 overflow)
+ */
+ *OwnerId = (ACPI_OWNER_ID) ((k + 1) + ACPI_MUL_32 (j));
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_VALUES,
+ "Allocated OwnerId: %2.2X\n", (unsigned int) *OwnerId));
+ goto Exit;
+ }
+ }
+
+ AcpiGbl_NextOwnerIdOffset = 0;
+ }
+
+ /*
+ * All OwnerIds have been allocated. This typically should
+ * not happen since the IDs are reused after deallocation. The IDs are
+ * allocated upon table load (one per table) and method execution, and
+ * they are released when a table is unloaded or a method completes
+ * execution.
+ *
+ * If this error happens, there may be very deep nesting of invoked control
+ * methods, or there may be a bug where the IDs are not released.
+ */
+ Status = AE_OWNER_ID_LIMIT;
+ ACPI_ERROR ((AE_INFO,
+ "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
+
+Exit:
+ (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtReleaseOwnerId
+ *
+ * PARAMETERS: OwnerIdPtr - Pointer to a previously allocated OwnerID
+ *
+ * RETURN: None. No error is returned because we are either exiting a
+ * control method or unloading a table. Either way, we would
+ * ignore any error anyway.
+ *
+ * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
+ *
+ ******************************************************************************/
+
+void
+AcpiUtReleaseOwnerId (
+ ACPI_OWNER_ID *OwnerIdPtr)
+{
+ ACPI_OWNER_ID OwnerId = *OwnerIdPtr;
+ ACPI_STATUS Status;
+ UINT32 Index;
+ UINT32 Bit;
+
+
+ ACPI_FUNCTION_TRACE_U32 (UtReleaseOwnerId, OwnerId);
+
+
+ /* Always clear the input OwnerId (zero is an invalid ID) */
+
+ *OwnerIdPtr = 0;
+
+ /* Zero is not a valid OwnerID */
+
+ if (OwnerId == 0)
+ {
+ ACPI_ERROR ((AE_INFO, "Invalid OwnerId: 0x%2.2X", OwnerId));
+ return_VOID;
+ }
+
+ /* Mutex for the global ID mask */
+
+ Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
+ if (ACPI_FAILURE (Status))
+ {
+ return_VOID;
+ }
+
+ /* Normalize the ID to zero */
+
+ OwnerId--;
+
+ /* Decode ID to index/offset pair */
+
+ Index = ACPI_DIV_32 (OwnerId);
+ Bit = 1 << ACPI_MOD_32 (OwnerId);
+
+ /* Free the owner ID only if it is valid */
+
+ if (AcpiGbl_OwnerIdMask[Index] & Bit)
+ {
+ AcpiGbl_OwnerIdMask[Index] ^= Bit;
+ }
+ else
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Release of non-allocated OwnerId: 0x%2.2X", OwnerId + 1));
+ }
+
+ (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
+ return_VOID;
+}
diff --git a/sys/contrib/dev/acpica/components/utilities/utresrc.c b/sys/contrib/dev/acpica/components/utilities/utresrc.c
index 08b8550..3a47a0c 100644
--- a/sys/contrib/dev/acpica/components/utilities/utresrc.c
+++ b/sys/contrib/dev/acpica/components/utilities/utresrc.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -456,7 +456,7 @@ AcpiUtWalkAmlResources (
UINT8 *Aml,
ACPI_SIZE AmlLength,
ACPI_WALK_AML_CALLBACK UserFunction,
- void *Context)
+ void **Context)
{
ACPI_STATUS Status;
UINT8 *EndAml;
@@ -528,7 +528,7 @@ AcpiUtWalkAmlResources (
if (!UserFunction)
{
- *(void **) Context = Aml;
+ *Context = Aml;
}
/* Normal exit */
@@ -919,7 +919,7 @@ AcpiUtGetResourceEndTag (
/* Validate the template and get a pointer to the EndTag */
Status = AcpiUtWalkAmlResources (NULL, ObjDesc->Buffer.Pointer,
- ObjDesc->Buffer.Length, NULL, EndTag);
+ ObjDesc->Buffer.Length, NULL, (void **) EndTag);
return_ACPI_STATUS (Status);
}
diff --git a/sys/contrib/dev/acpica/components/utilities/utstate.c b/sys/contrib/dev/acpica/components/utilities/utstate.c
index 8edb9cd..e0e5cce 100644
--- a/sys/contrib/dev/acpica/components/utilities/utstate.c
+++ b/sys/contrib/dev/acpica/components/utilities/utstate.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utstring.c b/sys/contrib/dev/acpica/components/utilities/utstring.c
new file mode 100644
index 0000000..49a47fe
--- /dev/null
+++ b/sys/contrib/dev/acpica/components/utilities/utstring.c
@@ -0,0 +1,674 @@
+/*******************************************************************************
+ *
+ * Module Name: utstring - Common functions for strings and characters
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2013, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+
+#define __UTSTRING_C__
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+#include <contrib/dev/acpica/include/acnamesp.h>
+
+
+#define _COMPONENT ACPI_UTILITIES
+ ACPI_MODULE_NAME ("utstring")
+
+
+/*
+ * Non-ANSI C library functions - strlwr, strupr, stricmp, and a 64-bit
+ * version of strtoul.
+ */
+
+#ifdef ACPI_ASL_COMPILER
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtStrlwr (strlwr)
+ *
+ * PARAMETERS: SrcString - The source string to convert
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Convert string to lowercase
+ *
+ * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
+ *
+ ******************************************************************************/
+
+void
+AcpiUtStrlwr (
+ char *SrcString)
+{
+ char *String;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ if (!SrcString)
+ {
+ return;
+ }
+
+ /* Walk entire string, lowercasing the letters */
+
+ for (String = SrcString; *String; String++)
+ {
+ *String = (char) ACPI_TOLOWER (*String);
+ }
+
+ return;
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: AcpiUtStricmp (stricmp)
+ *
+ * PARAMETERS: String1 - first string to compare
+ * String2 - second string to compare
+ *
+ * RETURN: int that signifies string relationship. Zero means strings
+ * are equal.
+ *
+ * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare
+ * strings with no case sensitivity)
+ *
+ ******************************************************************************/
+
+int
+AcpiUtStricmp (
+ char *String1,
+ char *String2)
+{
+ int c1;
+ int c2;
+
+
+ do
+ {
+ c1 = tolower ((int) *String1);
+ c2 = tolower ((int) *String2);
+
+ String1++;
+ String2++;
+ }
+ while ((c1 == c2) && (c1));
+
+ return (c1 - c2);
+}
+#endif
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtStrupr (strupr)
+ *
+ * PARAMETERS: SrcString - The source string to convert
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Convert string to uppercase
+ *
+ * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
+ *
+ ******************************************************************************/
+
+void
+AcpiUtStrupr (
+ char *SrcString)
+{
+ char *String;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ if (!SrcString)
+ {
+ return;
+ }
+
+ /* Walk entire string, uppercasing the letters */
+
+ for (String = SrcString; *String; String++)
+ {
+ *String = (char) ACPI_TOUPPER (*String);
+ }
+
+ return;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtStrtoul64
+ *
+ * PARAMETERS: String - Null terminated string
+ * Base - Radix of the string: 16 or ACPI_ANY_BASE;
+ * ACPI_ANY_BASE means 'in behalf of ToInteger'
+ * RetInteger - Where the converted integer is returned
+ *
+ * RETURN: Status and Converted value
+ *
+ * DESCRIPTION: Convert a string into an unsigned value. Performs either a
+ * 32-bit or 64-bit conversion, depending on the current mode
+ * of the interpreter.
+ * NOTE: Does not support Octal strings, not needed.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiUtStrtoul64 (
+ char *String,
+ UINT32 Base,
+ UINT64 *RetInteger)
+{
+ UINT32 ThisDigit = 0;
+ UINT64 ReturnValue = 0;
+ UINT64 Quotient;
+ UINT64 Dividend;
+ UINT32 ToIntegerOp = (Base == ACPI_ANY_BASE);
+ UINT32 Mode32 = (AcpiGbl_IntegerByteWidth == 4);
+ UINT8 ValidDigits = 0;
+ UINT8 SignOf0x = 0;
+ UINT8 Term = 0;
+
+
+ ACPI_FUNCTION_TRACE_STR (UtStroul64, String);
+
+
+ switch (Base)
+ {
+ case ACPI_ANY_BASE:
+ case 16:
+ break;
+
+ default:
+ /* Invalid Base */
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ if (!String)
+ {
+ goto ErrorExit;
+ }
+
+ /* Skip over any white space in the buffer */
+
+ while ((*String) && (ACPI_IS_SPACE (*String) || *String == '\t'))
+ {
+ String++;
+ }
+
+ if (ToIntegerOp)
+ {
+ /*
+ * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'.
+ * We need to determine if it is decimal or hexadecimal.
+ */
+ if ((*String == '0') && (ACPI_TOLOWER (*(String + 1)) == 'x'))
+ {
+ SignOf0x = 1;
+ Base = 16;
+
+ /* Skip over the leading '0x' */
+ String += 2;
+ }
+ else
+ {
+ Base = 10;
+ }
+ }
+
+ /* Any string left? Check that '0x' is not followed by white space. */
+
+ if (!(*String) || ACPI_IS_SPACE (*String) || *String == '\t')
+ {
+ if (ToIntegerOp)
+ {
+ goto ErrorExit;
+ }
+ else
+ {
+ goto AllDone;
+ }
+ }
+
+ /*
+ * Perform a 32-bit or 64-bit conversion, depending upon the current
+ * execution mode of the interpreter
+ */
+ Dividend = (Mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
+
+ /* Main loop: convert the string to a 32- or 64-bit integer */
+
+ while (*String)
+ {
+ if (ACPI_IS_DIGIT (*String))
+ {
+ /* Convert ASCII 0-9 to Decimal value */
+
+ ThisDigit = ((UINT8) *String) - '0';
+ }
+ else if (Base == 10)
+ {
+ /* Digit is out of range; possible in ToInteger case only */
+
+ Term = 1;
+ }
+ else
+ {
+ ThisDigit = (UINT8) ACPI_TOUPPER (*String);
+ if (ACPI_IS_XDIGIT ((char) ThisDigit))
+ {
+ /* Convert ASCII Hex char to value */
+
+ ThisDigit = ThisDigit - 'A' + 10;
+ }
+ else
+ {
+ Term = 1;
+ }
+ }
+
+ if (Term)
+ {
+ if (ToIntegerOp)
+ {
+ goto ErrorExit;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else if ((ValidDigits == 0) && (ThisDigit == 0) && !SignOf0x)
+ {
+ /* Skip zeros */
+ String++;
+ continue;
+ }
+
+ ValidDigits++;
+
+ if (SignOf0x && ((ValidDigits > 16) || ((ValidDigits > 8) && Mode32)))
+ {
+ /*
+ * This is ToInteger operation case.
+ * No any restrictions for string-to-integer conversion,
+ * see ACPI spec.
+ */
+ goto ErrorExit;
+ }
+
+ /* Divide the digit into the correct position */
+
+ (void) AcpiUtShortDivide ((Dividend - (UINT64) ThisDigit),
+ Base, &Quotient, NULL);
+
+ if (ReturnValue > Quotient)
+ {
+ if (ToIntegerOp)
+ {
+ goto ErrorExit;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ ReturnValue *= Base;
+ ReturnValue += ThisDigit;
+ String++;
+ }
+
+ /* All done, normal exit */
+
+AllDone:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64 (ReturnValue)));
+
+ *RetInteger = ReturnValue;
+ return_ACPI_STATUS (AE_OK);
+
+
+ErrorExit:
+ /* Base was set/validated above */
+
+ if (Base == 10)
+ {
+ return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT);
+ }
+ else
+ {
+ return_ACPI_STATUS (AE_BAD_HEX_CONSTANT);
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtPrintString
+ *
+ * PARAMETERS: String - Null terminated ASCII string
+ * MaxLength - Maximum output length
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape
+ * sequences.
+ *
+ ******************************************************************************/
+
+void
+AcpiUtPrintString (
+ char *String,
+ UINT8 MaxLength)
+{
+ UINT32 i;
+
+
+ if (!String)
+ {
+ AcpiOsPrintf ("<\"NULL STRING PTR\">");
+ return;
+ }
+
+ AcpiOsPrintf ("\"");
+ for (i = 0; String[i] && (i < MaxLength); i++)
+ {
+ /* Escape sequences */
+
+ switch (String[i])
+ {
+ case 0x07:
+ AcpiOsPrintf ("\\a"); /* BELL */
+ break;
+
+ case 0x08:
+ AcpiOsPrintf ("\\b"); /* BACKSPACE */
+ break;
+
+ case 0x0C:
+ AcpiOsPrintf ("\\f"); /* FORMFEED */
+ break;
+
+ case 0x0A:
+ AcpiOsPrintf ("\\n"); /* LINEFEED */
+ break;
+
+ case 0x0D:
+ AcpiOsPrintf ("\\r"); /* CARRIAGE RETURN*/
+ break;
+
+ case 0x09:
+ AcpiOsPrintf ("\\t"); /* HORIZONTAL TAB */
+ break;
+
+ case 0x0B:
+ AcpiOsPrintf ("\\v"); /* VERTICAL TAB */
+ break;
+
+ case '\'': /* Single Quote */
+ case '\"': /* Double Quote */
+ case '\\': /* Backslash */
+ AcpiOsPrintf ("\\%c", (int) String[i]);
+ break;
+
+ default:
+
+ /* Check for printable character or hex escape */
+
+ if (ACPI_IS_PRINT (String[i]))
+ {
+ /* This is a normal character */
+
+ AcpiOsPrintf ("%c", (int) String[i]);
+ }
+ else
+ {
+ /* All others will be Hex escapes */
+
+ AcpiOsPrintf ("\\x%2.2X", (INT32) String[i]);
+ }
+ break;
+ }
+ }
+ AcpiOsPrintf ("\"");
+
+ if (i == MaxLength && String[i])
+ {
+ AcpiOsPrintf ("...");
+ }
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtValidAcpiChar
+ *
+ * PARAMETERS: Char - The character to be examined
+ * Position - Byte position (0-3)
+ *
+ * RETURN: TRUE if the character is valid, FALSE otherwise
+ *
+ * DESCRIPTION: Check for a valid ACPI character. Must be one of:
+ * 1) Upper case alpha
+ * 2) numeric
+ * 3) underscore
+ *
+ * We allow a '!' as the last character because of the ASF! table
+ *
+ ******************************************************************************/
+
+BOOLEAN
+AcpiUtValidAcpiChar (
+ char Character,
+ UINT32 Position)
+{
+
+ if (!((Character >= 'A' && Character <= 'Z') ||
+ (Character >= '0' && Character <= '9') ||
+ (Character == '_')))
+ {
+ /* Allow a '!' in the last position */
+
+ if (Character == '!' && Position == 3)
+ {
+ return (TRUE);
+ }
+
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtValidAcpiName
+ *
+ * PARAMETERS: Name - The name to be examined
+ *
+ * RETURN: TRUE if the name is valid, FALSE otherwise
+ *
+ * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
+ * 1) Upper case alpha
+ * 2) numeric
+ * 3) underscore
+ *
+ ******************************************************************************/
+
+BOOLEAN
+AcpiUtValidAcpiName (
+ UINT32 Name)
+{
+ UINT32 i;
+
+
+ ACPI_FUNCTION_ENTRY ();
+
+
+ for (i = 0; i < ACPI_NAME_SIZE; i++)
+ {
+ if (!AcpiUtValidAcpiChar ((ACPI_CAST_PTR (char, &Name))[i], i))
+ {
+ return (FALSE);
+ }
+ }
+
+ return (TRUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiUtRepairName
+ *
+ * PARAMETERS: Name - The ACPI name to be repaired
+ *
+ * RETURN: Repaired version of the name
+ *
+ * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and
+ * return the new name. NOTE: the Name parameter must reside in
+ * read/write memory, cannot be a const.
+ *
+ * An ACPI Name must consist of valid ACPI characters. We will repair the name
+ * if necessary because we don't want to abort because of this, but we want
+ * all namespace names to be printable. A warning message is appropriate.
+ *
+ * This issue came up because there are in fact machines that exhibit
+ * this problem, and we want to be able to enable ACPI support for them,
+ * even though there are a few bad names.
+ *
+ ******************************************************************************/
+
+void
+AcpiUtRepairName (
+ char *Name)
+{
+ UINT32 i;
+ BOOLEAN FoundBadChar = FALSE;
+ UINT32 OriginalName;
+
+
+ ACPI_FUNCTION_NAME (UtRepairName);
+
+
+ ACPI_MOVE_NAME (&OriginalName, Name);
+
+ /* Check each character in the name */
+
+ for (i = 0; i < ACPI_NAME_SIZE; i++)
+ {
+ if (AcpiUtValidAcpiChar (Name[i], i))
+ {
+ continue;
+ }
+
+ /*
+ * Replace a bad character with something printable, yet technically
+ * still invalid. This prevents any collisions with existing "good"
+ * names in the namespace.
+ */
+ Name[i] = '*';
+ FoundBadChar = TRUE;
+ }
+
+ if (FoundBadChar)
+ {
+ /* Report warning only if in strict mode or debug mode */
+
+ if (!AcpiGbl_EnableInterpreterSlack)
+ {
+ ACPI_WARNING ((AE_INFO,
+ "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
+ OriginalName, Name));
+ }
+ else
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+ "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
+ OriginalName, Name));
+ }
+ }
+}
+
+
+#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP
+/*******************************************************************************
+ *
+ * FUNCTION: UtConvertBackslashes
+ *
+ * PARAMETERS: Pathname - File pathname string to be converted
+ *
+ * RETURN: Modifies the input Pathname
+ *
+ * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within
+ * the entire input file pathname string.
+ *
+ ******************************************************************************/
+
+void
+UtConvertBackslashes (
+ char *Pathname)
+{
+
+ if (!Pathname)
+ {
+ return;
+ }
+
+ while (*Pathname)
+ {
+ if (*Pathname == '\\')
+ {
+ *Pathname = '/';
+ }
+
+ Pathname++;
+ }
+}
+#endif
diff --git a/sys/contrib/dev/acpica/components/utilities/uttrack.c b/sys/contrib/dev/acpica/components/utilities/uttrack.c
index 76b5bb3..c829fb0 100644
--- a/sys/contrib/dev/acpica/components/utilities/uttrack.c
+++ b/sys/contrib/dev/acpica/components/utilities/uttrack.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utxface.c b/sys/contrib/dev/acpica/components/utilities/utxface.c
index 4abe72e..cd3e7b2 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxface.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxface.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utxferror.c b/sys/contrib/dev/acpica/components/utilities/utxferror.c
index e106c9b..3067294 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxferror.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxferror.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utxfinit.c b/sys/contrib/dev/acpica/components/utilities/utxfinit.c
index e6e0f5d..c828a71 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxfinit.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxfinit.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/components/utilities/utxfmutex.c b/sys/contrib/dev/acpica/components/utilities/utxfmutex.c
index ca07871..ae5a345 100644
--- a/sys/contrib/dev/acpica/components/utilities/utxfmutex.c
+++ b/sys/contrib/dev/acpica/components/utilities/utxfmutex.c
@@ -5,7 +5,7 @@
******************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acapps.h b/sys/contrib/dev/acpica/include/acapps.h
index 0b3d72a..acc6e4a 100644
--- a/sys/contrib/dev/acpica/include/acapps.h
+++ b/sys/contrib/dev/acpica/include/acapps.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -52,7 +52,7 @@
/* Common info for tool signons */
#define ACPICA_NAME "Intel ACPI Component Architecture"
-#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2012 Intel Corporation"
+#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2013 Intel Corporation"
#if ACPI_MACHINE_WIDTH == 64
#define ACPI_WIDTH "-64"
diff --git a/sys/contrib/dev/acpica/include/acbuffer.h b/sys/contrib/dev/acpica/include/acbuffer.h
index 4b34ccd..9651024 100644
--- a/sys/contrib/dev/acpica/include/acbuffer.h
+++ b/sys/contrib/dev/acpica/include/acbuffer.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/accommon.h b/sys/contrib/dev/acpica/include/accommon.h
index 93c9031..074b6c1 100644
--- a/sys/contrib/dev/acpica/include/accommon.h
+++ b/sys/contrib/dev/acpica/include/accommon.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acconfig.h b/sys/contrib/dev/acpica/include/acconfig.h
index b414383..452ab28 100644
--- a/sys/contrib/dev/acpica/include/acconfig.h
+++ b/sys/contrib/dev/acpica/include/acconfig.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -194,6 +194,7 @@
/* Maximum SpaceIds for Operation Regions */
#define ACPI_MAX_ADDRESS_SPACE 255
+#define ACPI_NUM_DEFAULT_SPACES 4
/* Array sizes. Used for range checking also */
diff --git a/sys/contrib/dev/acpica/include/acdebug.h b/sys/contrib/dev/acpica/include/acdebug.h
index de915b4..5fef182 100644
--- a/sys/contrib/dev/acpica/include/acdebug.h
+++ b/sys/contrib/dev/acpica/include/acdebug.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -161,6 +161,34 @@ AcpiDbGenerateGpe (
/*
+ * dbconvert - miscellaneous conversion routines
+ */
+ACPI_STATUS
+AcpiDbHexCharToValue (
+ int HexChar,
+ UINT8 *ReturnValue);
+
+ACPI_STATUS
+AcpiDbConvertToPackage (
+ char *String,
+ ACPI_OBJECT *Object);
+
+ACPI_STATUS
+AcpiDbConvertToObject (
+ ACPI_OBJECT_TYPE Type,
+ char *String,
+ ACPI_OBJECT *Object);
+
+UINT8 *
+AcpiDbEncodePldBuffer (
+ ACPI_PLD_INFO *PldInfo);
+
+void
+AcpiDbDumpPldBuffer (
+ ACPI_OBJECT *ObjDesc);
+
+
+/*
* dbmethod - control method commands
*/
void
@@ -299,6 +327,11 @@ AcpiDbCreateExecutionThreads (
char *NumLoopsArg,
char *MethodNameArg);
+void
+AcpiDbDeleteObjects (
+ UINT32 Count,
+ ACPI_OBJECT *Objects);
+
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
UINT32
AcpiDbGetCacheInfo (
diff --git a/sys/contrib/dev/acpica/include/acdisasm.h b/sys/contrib/dev/acpica/include/acdisasm.h
index 20e056a..eb6553b 100644
--- a/sys/contrib/dev/acpica/include/acdisasm.h
+++ b/sys/contrib/dev/acpica/include/acdisasm.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -237,6 +237,7 @@ extern ACPI_DMTABLE_INFO AcpiDmTableInfoCpep[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoCpep0[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt0[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt1[];
+extern ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt2[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2Device[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2Addr[];
@@ -340,6 +341,7 @@ extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat0[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat1[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat2[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoTcpa[];
+extern ACPI_DMTABLE_INFO AcpiDmTableInfoTpm2[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoUefi[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoWaet[];
extern ACPI_DMTABLE_INFO AcpiDmTableInfoWdat[];
diff --git a/sys/contrib/dev/acpica/include/acdispat.h b/sys/contrib/dev/acpica/include/acdispat.h
index 0699ee7..fc747f1 100644
--- a/sys/contrib/dev/acpica/include/acdispat.h
+++ b/sys/contrib/dev/acpica/include/acdispat.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acevents.h b/sys/contrib/dev/acpica/include/acevents.h
index 3b874f1..fc652b4 100644
--- a/sys/contrib/dev/acpica/include/acevents.h
+++ b/sys/contrib/dev/acpica/include/acevents.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -167,6 +167,7 @@ AcpiEvGpeDispatch (
ACPI_GPE_EVENT_INFO *GpeEventInfo,
UINT32 GpeNumber);
+
/*
* evgpeinit - GPE initialization and update
*/
@@ -186,6 +187,7 @@ AcpiEvMatchGpeMethod (
void *Context,
void **ReturnValue);
+
/*
* evgpeutil - GPE utilities
*/
@@ -220,13 +222,30 @@ AcpiEvDeleteGpeHandlers (
/*
- * evregion - Address Space handling
+ * evhandler - Address space handling
*/
+BOOLEAN
+AcpiEvHasDefaultHandler (
+ ACPI_NAMESPACE_NODE *Node,
+ ACPI_ADR_SPACE_TYPE SpaceId);
+
ACPI_STATUS
AcpiEvInstallRegionHandlers (
void);
ACPI_STATUS
+AcpiEvInstallSpaceHandler (
+ ACPI_NAMESPACE_NODE *Node,
+ ACPI_ADR_SPACE_TYPE SpaceId,
+ ACPI_ADR_SPACE_HANDLER Handler,
+ ACPI_ADR_SPACE_SETUP Setup,
+ void *Context);
+
+
+/*
+ * evregion - Operation region support
+ */
+ACPI_STATUS
AcpiEvInitializeOpRegions (
void);
@@ -251,14 +270,6 @@ AcpiEvDetachRegion (
BOOLEAN AcpiNsIsLocked);
ACPI_STATUS
-AcpiEvInstallSpaceHandler (
- ACPI_NAMESPACE_NODE *Node,
- ACPI_ADR_SPACE_TYPE SpaceId,
- ACPI_ADR_SPACE_HANDLER Handler,
- ACPI_ADR_SPACE_SETUP Setup,
- void *Context);
-
-ACPI_STATUS
AcpiEvExecuteRegMethods (
ACPI_NAMESPACE_NODE *Node,
ACPI_ADR_SPACE_TYPE SpaceId);
diff --git a/sys/contrib/dev/acpica/include/acexcep.h b/sys/contrib/dev/acpica/include/acexcep.h
index 072ddf9..110ef18 100644
--- a/sys/contrib/dev/acpica/include/acexcep.h
+++ b/sys/contrib/dev/acpica/include/acexcep.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acglobal.h b/sys/contrib/dev/acpica/include/acglobal.h
index 42c6234..83547e6 100644
--- a/sys/contrib/dev/acpica/include/acglobal.h
+++ b/sys/contrib/dev/acpica/include/acglobal.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -349,7 +349,6 @@ ACPI_EXTERN UINT32 AcpiGbl_DeepestNesting;
*
****************************************************************************/
-
ACPI_EXTERN ACPI_THREAD_STATE *AcpiGbl_CurrentWalkList;
/* Control method single step flag */
@@ -413,7 +412,7 @@ ACPI_EXTERN UINT32 AcpiGbl_TraceDbgLayer;
/*****************************************************************************
*
- * Debugger globals
+ * Debugger and Disassembler globals
*
****************************************************************************/
@@ -421,6 +420,8 @@ ACPI_EXTERN UINT8 AcpiGbl_DbOutputFlags;
#ifdef ACPI_DISASSEMBLER
+ACPI_EXTERN BOOLEAN ACPI_INIT_GLOBAL (AcpiGbl_IgnoreNoopOperator, FALSE);
+
ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_disasm;
ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_verbose;
ACPI_EXTERN ACPI_EXTERNAL_LIST *AcpiGbl_ExternalList;
diff --git a/sys/contrib/dev/acpica/include/achware.h b/sys/contrib/dev/acpica/include/achware.h
index 6dc1191..9577fd1 100644
--- a/sys/contrib/dev/acpica/include/achware.h
+++ b/sys/contrib/dev/acpica/include/achware.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acinterp.h b/sys/contrib/dev/acpica/include/acinterp.h
index 45e9814..ebf4c98 100644
--- a/sys/contrib/dev/acpica/include/acinterp.h
+++ b/sys/contrib/dev/acpica/include/acinterp.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -620,7 +620,7 @@ void
AcpiExRelinquishInterpreter (
void);
-void
+BOOLEAN
AcpiExTruncateFor32bitTable (
ACPI_OPERAND_OBJECT *ObjDesc);
diff --git a/sys/contrib/dev/acpica/include/aclocal.h b/sys/contrib/dev/acpica/include/aclocal.h
index d54455f..798c4cb 100644
--- a/sys/contrib/dev/acpica/include/aclocal.h
+++ b/sys/contrib/dev/acpica/include/aclocal.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acmacros.h b/sys/contrib/dev/acpica/include/acmacros.h
index 9b44671..a56dcd7 100644
--- a/sys/contrib/dev/acpica/include/acmacros.h
+++ b/sys/contrib/dev/acpica/include/acmacros.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -314,15 +314,23 @@
#define ACPI_EXTRACT_3BIT_FLAG(Field, Position) (ACPI_GET_3BIT_FLAG ((Field) >> Position))
#define ACPI_EXTRACT_4BIT_FLAG(Field, Position) (ACPI_GET_4BIT_FLAG ((Field) >> Position))
+/* ACPI Pathname helpers */
+
+#define ACPI_IS_ROOT_PREFIX(c) ((c) == (UINT8) 0x5C) /* Backslash */
+#define ACPI_IS_PARENT_PREFIX(c) ((c) == (UINT8) 0x5E) /* Carat */
+#define ACPI_IS_PATH_SEPARATOR(c) ((c) == (UINT8) 0x2E) /* Period (dot) */
+
/*
* An object of type ACPI_NAMESPACE_NODE can appear in some contexts
* where a pointer to an object of type ACPI_OPERAND_OBJECT can also
* appear. This macro is used to distinguish them.
*
- * The "Descriptor" field is the first field in both structures.
+ * The "DescriptorType" field is the second field in both structures.
*/
+#define ACPI_GET_DESCRIPTOR_PTR(d) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.CommonPointer)
+#define ACPI_SET_DESCRIPTOR_PTR(d, p) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.CommonPointer = (p))
#define ACPI_GET_DESCRIPTOR_TYPE(d) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.DescriptorType)
-#define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.DescriptorType = t)
+#define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.DescriptorType = (t))
/*
* Macros for the master AML opcode table
@@ -385,139 +393,6 @@
#endif /* ACPI_NO_ERROR_MESSAGES */
-/*
- * Debug macros that are conditionally compiled
- */
-#ifdef ACPI_DEBUG_OUTPUT
-/*
- * Function entry tracing
- */
-#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \
- AcpiUtTrace(ACPI_DEBUG_PARAMETERS)
-#define ACPI_FUNCTION_TRACE_PTR(a, b) ACPI_FUNCTION_NAME(a) \
- AcpiUtTracePtr(ACPI_DEBUG_PARAMETERS, (void *)b)
-#define ACPI_FUNCTION_TRACE_U32(a, b) ACPI_FUNCTION_NAME(a) \
- AcpiUtTraceU32(ACPI_DEBUG_PARAMETERS, (UINT32)b)
-#define ACPI_FUNCTION_TRACE_STR(a, b) ACPI_FUNCTION_NAME(a) \
- AcpiUtTraceStr(ACPI_DEBUG_PARAMETERS, (char *)b)
-
-#define ACPI_FUNCTION_ENTRY() AcpiUtTrackStackPtr()
-
-/*
- * Function exit tracing.
- * WARNING: These macros include a return statement. This is usually considered
- * bad form, but having a separate exit macro is very ugly and difficult to maintain.
- * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros
- * so that "_AcpiFunctionName" is defined.
- *
- * Note: the DO_WHILE0 macro is used to prevent some compilers from complaining
- * about these constructs.
- */
-#ifdef ACPI_USE_DO_WHILE_0
-#define ACPI_DO_WHILE0(a) do a while(0)
-#else
-#define ACPI_DO_WHILE0(a) a
-#endif
-
-#define return_VOID ACPI_DO_WHILE0 ({ \
- AcpiUtExit (ACPI_DEBUG_PARAMETERS); \
- return;})
-/*
- * There are two versions of most of the return macros. The default version is
- * safer, since it avoids side-effects by guaranteeing that the argument will
- * not be evaluated twice.
- *
- * A less-safe version of the macros is provided for optional use if the
- * compiler uses excessive CPU stack (for example, this may happen in the
- * debug case if code optimzation is disabled.)
- */
-#ifndef ACPI_SIMPLE_RETURN_MACROS
-
-#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \
- register ACPI_STATUS _s = (s); \
- AcpiUtStatusExit (ACPI_DEBUG_PARAMETERS, _s); \
- return (_s); })
-#define return_PTR(s) ACPI_DO_WHILE0 ({ \
- register void *_s = (void *) (s); \
- AcpiUtPtrExit (ACPI_DEBUG_PARAMETERS, (UINT8 *) _s); \
- return (_s); })
-#define return_VALUE(s) ACPI_DO_WHILE0 ({ \
- register UINT64 _s = (s); \
- AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, _s); \
- return (_s); })
-#define return_UINT8(s) ACPI_DO_WHILE0 ({ \
- register UINT8 _s = (UINT8) (s); \
- AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, (UINT64) _s); \
- return (_s); })
-#define return_UINT32(s) ACPI_DO_WHILE0 ({ \
- register UINT32 _s = (UINT32) (s); \
- AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, (UINT64) _s); \
- return (_s); })
-#else /* Use original less-safe macros */
-
-#define return_ACPI_STATUS(s) ACPI_DO_WHILE0 ({ \
- AcpiUtStatusExit (ACPI_DEBUG_PARAMETERS, (s)); \
- return((s)); })
-#define return_PTR(s) ACPI_DO_WHILE0 ({ \
- AcpiUtPtrExit (ACPI_DEBUG_PARAMETERS, (UINT8 *) (s)); \
- return((s)); })
-#define return_VALUE(s) ACPI_DO_WHILE0 ({ \
- AcpiUtValueExit (ACPI_DEBUG_PARAMETERS, (UINT64) (s)); \
- return((s)); })
-#define return_UINT8(s) return_VALUE(s)
-#define return_UINT32(s) return_VALUE(s)
-
-#endif /* ACPI_SIMPLE_RETURN_MACROS */
-
-/* Conditional execution */
-
-#define ACPI_DEBUG_EXEC(a) a
-#define ACPI_DEBUG_ONLY_MEMBERS(a) a;
-#define _VERBOSE_STRUCTURES
-
-
-/* Various object display routines for debug */
-
-#define ACPI_DUMP_STACK_ENTRY(a) AcpiExDumpOperand((a), 0)
-#define ACPI_DUMP_OPERANDS(a, b ,c) AcpiExDumpOperands(a, b, c)
-#define ACPI_DUMP_ENTRY(a, b) AcpiNsDumpEntry (a, b)
-#define ACPI_DUMP_PATHNAME(a, b, c, d) AcpiNsDumpPathname(a, b, c, d)
-#define ACPI_DUMP_BUFFER(a, b) AcpiUtDebugDumpBuffer((UINT8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
-
-#else
-/*
- * This is the non-debug case -- make everything go away,
- * leaving no executable debug code!
- */
-#define ACPI_DEBUG_EXEC(a)
-#define ACPI_DEBUG_ONLY_MEMBERS(a)
-#define ACPI_FUNCTION_TRACE(a)
-#define ACPI_FUNCTION_TRACE_PTR(a, b)
-#define ACPI_FUNCTION_TRACE_U32(a, b)
-#define ACPI_FUNCTION_TRACE_STR(a, b)
-#define ACPI_FUNCTION_EXIT
-#define ACPI_FUNCTION_STATUS_EXIT(s)
-#define ACPI_FUNCTION_VALUE_EXIT(s)
-#define ACPI_FUNCTION_ENTRY()
-#define ACPI_DUMP_STACK_ENTRY(a)
-#define ACPI_DUMP_OPERANDS(a, b, c)
-#define ACPI_DUMP_ENTRY(a, b)
-#define ACPI_DUMP_TABLES(a, b)
-#define ACPI_DUMP_PATHNAME(a, b, c, d)
-#define ACPI_DUMP_BUFFER(a, b)
-#define ACPI_DEBUG_PRINT(pl)
-#define ACPI_DEBUG_PRINT_RAW(pl)
-
-#define return_VOID return
-#define return_ACPI_STATUS(s) return(s)
-#define return_VALUE(s) return(s)
-#define return_UINT8(s) return(s)
-#define return_UINT32(s) return(s)
-#define return_PTR(s) return(s)
-
-#endif /* ACPI_DEBUG_OUTPUT */
-
-
#if (!ACPI_REDUCED_HARDWARE)
#define ACPI_HW_OPTIONAL_FUNCTION(addr) addr
#else
diff --git a/sys/contrib/dev/acpica/include/acnames.h b/sys/contrib/dev/acpica/include/acnames.h
index 1987b16..d6fdaa6 100644
--- a/sys/contrib/dev/acpica/include/acnames.h
+++ b/sys/contrib/dev/acpica/include/acnames.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acnamesp.h b/sys/contrib/dev/acpica/include/acnamesp.h
index 4a91108..7a92143 100644
--- a/sys/contrib/dev/acpica/include/acnamesp.h
+++ b/sys/contrib/dev/acpica/include/acnamesp.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -277,6 +277,22 @@ AcpiNsCheckParameterCount (
UINT32 UserParamCount,
const ACPI_PREDEFINED_INFO *Info);
+ACPI_STATUS
+AcpiNsCheckObjectType (
+ ACPI_PREDEFINED_DATA *Data,
+ ACPI_OPERAND_OBJECT **ReturnObjectPtr,
+ UINT32 ExpectedBtypes,
+ UINT32 PackageIndex);
+
+
+/*
+ * nsprepkg - Validation of predefined name packages
+ */
+ACPI_STATUS
+AcpiNsCheckPackage (
+ ACPI_PREDEFINED_DATA *Data,
+ ACPI_OPERAND_OBJECT **ReturnObjectPtr);
+
/*
* nsnames - Name and Scope manipulation
@@ -430,10 +446,6 @@ AcpiNsInstallNode (
/*
* nsutils - Utility functions
*/
-BOOLEAN
-AcpiNsValidRootPrefix (
- char Prefix);
-
ACPI_OBJECT_TYPE
AcpiNsGetType (
ACPI_NAMESPACE_NODE *Node);
diff --git a/sys/contrib/dev/acpica/include/acobject.h b/sys/contrib/dev/acpica/include/acobject.h
index 2f17375..e755daa 100644
--- a/sys/contrib/dev/acpica/include/acobject.h
+++ b/sys/contrib/dev/acpica/include/acobject.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acopcode.h b/sys/contrib/dev/acpica/include/acopcode.h
index edd1349..ba37842 100644
--- a/sys/contrib/dev/acpica/include/acopcode.h
+++ b/sys/contrib/dev/acpica/include/acopcode.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acoutput.h b/sys/contrib/dev/acpica/include/acoutput.h
index 193d0ac..4b5ca9c 100644
--- a/sys/contrib/dev/acpica/include/acoutput.h
+++ b/sys/contrib/dev/acpica/include/acoutput.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -267,18 +267,165 @@
* Common parameters used for debug output functions:
* line number, function name, module(file) name, component ID
*/
-#define ACPI_DEBUG_PARAMETERS __LINE__, ACPI_GET_FUNCTION_NAME, _AcpiModuleName, _COMPONENT
+#define ACPI_DEBUG_PARAMETERS \
+ __LINE__, ACPI_GET_FUNCTION_NAME, _AcpiModuleName, _COMPONENT
+
+/* Check if debug output is currently dynamically enabled */
+
+#define ACPI_IS_DEBUG_ENABLED(Level, Component) \
+ ((Level & AcpiDbgLevel) && (Component & AcpiDbgLayer))
/*
* Master debug print macros
* Print message if and only if:
* 1) Debug print for the current component is enabled
* 2) Debug error level or trace level for the print statement is enabled
+ *
+ * November 2012: Moved the runtime check for whether to actually emit the
+ * debug message outside of the print function itself. This improves overall
+ * performance at a relatively small code cost. Implementation involves the
+ * use of variadic macros supported by C99.
+ *
+ * Note: the ACPI_DO_WHILE0 macro is used to prevent some compilers from
+ * complaining about these constructs. On other compilers the do...while
+ * adds some extra code, so this feature is optional.
*/
-#define ACPI_DEBUG_PRINT(plist) AcpiDebugPrint plist
-#define ACPI_DEBUG_PRINT_RAW(plist) AcpiDebugPrintRaw plist
-
+#ifdef ACPI_USE_DO_WHILE_0
+#define ACPI_DO_WHILE0(a) do a while(0)
#else
+#define ACPI_DO_WHILE0(a) a
+#endif
+
+/* DEBUG_PRINT functions */
+
+#define ACPI_DEBUG_PRINT(plist) ACPI_ACTUAL_DEBUG plist
+#define ACPI_DEBUG_PRINT_RAW(plist) ACPI_ACTUAL_DEBUG_RAW plist
+
+/* Helper macros for DEBUG_PRINT */
+
+#define ACPI_DO_DEBUG_PRINT(Function, Level, Line, Filename, Modulename, Component, ...) \
+ ACPI_DO_WHILE0 ({ \
+ if (ACPI_IS_DEBUG_ENABLED (Level, Component)) \
+ { \
+ Function (Level, Line, Filename, Modulename, Component, __VA_ARGS__); \
+ } \
+ })
+
+#define ACPI_ACTUAL_DEBUG(Level, Line, Filename, Modulename, Component, ...) \
+ ACPI_DO_DEBUG_PRINT (AcpiDebugPrint, Level, Line, \
+ Filename, Modulename, Component, __VA_ARGS__)
+
+#define ACPI_ACTUAL_DEBUG_RAW(Level, Line, Filename, Modulename, Component, ...) \
+ ACPI_DO_DEBUG_PRINT (AcpiDebugPrintRaw, Level, Line, \
+ Filename, Modulename, Component, __VA_ARGS__)
+
+
+/*
+ * Function entry tracing
+ *
+ * The name of the function is emitted as a local variable that is
+ * intended to be used by both the entry trace and the exit trace.
+ */
+
+/* Helper macro */
+
+#define ACPI_TRACE_ENTRY(Name, Function, Type, Param) \
+ ACPI_FUNCTION_NAME (Name) \
+ Function (ACPI_DEBUG_PARAMETERS, (Type) (Param))
+
+/* The actual entry trace macros */
+
+#define ACPI_FUNCTION_TRACE(Name) \
+ ACPI_FUNCTION_NAME(Name) \
+ AcpiUtTrace (ACPI_DEBUG_PARAMETERS)
+
+#define ACPI_FUNCTION_TRACE_PTR(Name, Pointer) \
+ ACPI_TRACE_ENTRY (Name, AcpiUtTracePtr, void *, Pointer)
+
+#define ACPI_FUNCTION_TRACE_U32(Name, Value) \
+ ACPI_TRACE_ENTRY (Name, AcpiUtTraceU32, UINT32, Value)
+
+#define ACPI_FUNCTION_TRACE_STR(Name, String) \
+ ACPI_TRACE_ENTRY (Name, AcpiUtTraceStr, char *, String)
+
+#define ACPI_FUNCTION_ENTRY() \
+ AcpiUtTrackStackPtr()
+
+
+/*
+ * Function exit tracing
+ *
+ * These macros include a return statement. This is usually considered
+ * bad form, but having a separate exit macro before the actual return
+ * is very ugly and difficult to maintain.
+ *
+ * One of the FUNCTION_TRACE macros above must be used in conjunction
+ * with these macros so that "_AcpiFunctionName" is defined.
+ *
+ * There are two versions of most of the return macros. The default version is
+ * safer, since it avoids side-effects by guaranteeing that the argument will
+ * not be evaluated twice.
+ *
+ * A less-safe version of the macros is provided for optional use if the
+ * compiler uses excessive CPU stack (for example, this may happen in the
+ * debug case if code optimzation is disabled.)
+ */
+
+/* Exit trace helper macro */
+
+#ifndef ACPI_SIMPLE_RETURN_MACROS
+
+#define ACPI_TRACE_EXIT(Function, Type, Param) \
+ ACPI_DO_WHILE0 ({ \
+ register Type _Param = (Type) (Param); \
+ Function (ACPI_DEBUG_PARAMETERS, _Param); \
+ return (_Param); \
+ })
+
+#else /* Use original less-safe macros */
+
+#define ACPI_TRACE_EXIT(Function, Type, Param) \
+ ACPI_DO_WHILE0 ({ \
+ Function (ACPI_DEBUG_PARAMETERS, (Type) (Param)); \
+ return (Param); \
+ })
+
+#endif /* ACPI_SIMPLE_RETURN_MACROS */
+
+/* The actual exit macros */
+
+#define return_VOID \
+ ACPI_DO_WHILE0 ({ \
+ AcpiUtExit (ACPI_DEBUG_PARAMETERS); \
+ return; \
+ })
+
+#define return_ACPI_STATUS(Status) \
+ ACPI_TRACE_EXIT (AcpiUtStatusExit, ACPI_STATUS, Status)
+
+#define return_PTR(Pointer) \
+ ACPI_TRACE_EXIT (AcpiUtPtrExit, void *, Pointer)
+
+#define return_VALUE(Value) \
+ ACPI_TRACE_EXIT (AcpiUtValueExit, UINT64, Value)
+
+
+/* Conditional execution */
+
+#define ACPI_DEBUG_EXEC(a) a
+#define ACPI_DEBUG_ONLY_MEMBERS(a) a;
+#define _VERBOSE_STRUCTURES
+
+
+/* Various object display routines for debug */
+
+#define ACPI_DUMP_STACK_ENTRY(a) AcpiExDumpOperand((a), 0)
+#define ACPI_DUMP_OPERANDS(a, b ,c) AcpiExDumpOperands(a, b, c)
+#define ACPI_DUMP_ENTRY(a, b) AcpiNsDumpEntry (a, b)
+#define ACPI_DUMP_PATHNAME(a, b, c, d) AcpiNsDumpPathname(a, b, c, d)
+#define ACPI_DUMP_BUFFER(a, b) AcpiUtDebugDumpBuffer((UINT8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
+
+#else /* ACPI_DEBUG_OUTPUT */
/*
* This is the non-debug case -- make everything go away,
* leaving no executable debug code!
@@ -286,6 +433,32 @@
#define ACPI_FUNCTION_NAME(a)
#define ACPI_DEBUG_PRINT(pl)
#define ACPI_DEBUG_PRINT_RAW(pl)
+#define ACPI_DEBUG_EXEC(a)
+#define ACPI_DEBUG_ONLY_MEMBERS(a)
+#define ACPI_FUNCTION_TRACE(a)
+#define ACPI_FUNCTION_TRACE_PTR(a, b)
+#define ACPI_FUNCTION_TRACE_U32(a, b)
+#define ACPI_FUNCTION_TRACE_STR(a, b)
+#define ACPI_FUNCTION_EXIT
+#define ACPI_FUNCTION_STATUS_EXIT(s)
+#define ACPI_FUNCTION_VALUE_EXIT(s)
+#define ACPI_FUNCTION_ENTRY()
+#define ACPI_DUMP_STACK_ENTRY(a)
+#define ACPI_DUMP_OPERANDS(a, b, c)
+#define ACPI_DUMP_ENTRY(a, b)
+#define ACPI_DUMP_TABLES(a, b)
+#define ACPI_DUMP_PATHNAME(a, b, c, d)
+#define ACPI_DUMP_BUFFER(a, b)
+#define ACPI_DEBUG_PRINT(pl)
+#define ACPI_DEBUG_PRINT_RAW(pl)
+#define ACPI_IS_DEBUG_ENABLED(Level, Component) 0
+
+/* Return macros must have a return statement at the minimum */
+
+#define return_VOID return
+#define return_ACPI_STATUS(s) return(s)
+#define return_VALUE(s) return(s)
+#define return_PTR(s) return(s)
#endif /* ACPI_DEBUG_OUTPUT */
diff --git a/sys/contrib/dev/acpica/include/acparser.h b/sys/contrib/dev/acpica/include/acparser.h
index f46d3cb..7f236d8 100644
--- a/sys/contrib/dev/acpica/include/acparser.h
+++ b/sys/contrib/dev/acpica/include/acparser.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -129,7 +129,36 @@ AcpiPsGetParent (
/*
- * psopcode - AML Opcode information
+ * psobject - support for parse object processing
+ */
+ACPI_STATUS
+AcpiPsBuildNamedOp (
+ ACPI_WALK_STATE *WalkState,
+ UINT8 *AmlOpStart,
+ ACPI_PARSE_OBJECT *UnnamedOp,
+ ACPI_PARSE_OBJECT **Op);
+
+ACPI_STATUS
+AcpiPsCreateOp (
+ ACPI_WALK_STATE *WalkState,
+ UINT8 *AmlOpStart,
+ ACPI_PARSE_OBJECT **NewOp);
+
+ACPI_STATUS
+AcpiPsCompleteOp (
+ ACPI_WALK_STATE *WalkState,
+ ACPI_PARSE_OBJECT **Op,
+ ACPI_STATUS Status);
+
+ACPI_STATUS
+AcpiPsCompleteFinalOp (
+ ACPI_WALK_STATE *WalkState,
+ ACPI_PARSE_OBJECT *Op,
+ ACPI_STATUS Status);
+
+
+/*
+ * psopinfo - AML Opcode information
*/
const ACPI_OPCODE_INFO *
AcpiPsGetOpcodeInfo (
@@ -294,10 +323,6 @@ BOOLEAN
AcpiPsIsLeadingChar (
UINT32 c);
-BOOLEAN
-AcpiPsIsPrefixChar (
- UINT32 c);
-
UINT32
AcpiPsGetName(
ACPI_PARSE_OBJECT *op);
diff --git a/sys/contrib/dev/acpica/include/acpi.h b/sys/contrib/dev/acpica/include/acpi.h
index ad0f17b..5450ad4 100644
--- a/sys/contrib/dev/acpica/include/acpi.h
+++ b/sys/contrib/dev/acpica/include/acpi.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acpiosxf.h b/sys/contrib/dev/acpica/include/acpiosxf.h
index 462d030..ae9cf3c 100644
--- a/sys/contrib/dev/acpica/include/acpiosxf.h
+++ b/sys/contrib/dev/acpica/include/acpiosxf.h
@@ -8,7 +8,7 @@
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/acpixf.h b/sys/contrib/dev/acpica/include/acpixf.h
index 086e2d3..1cd6cb9 100644
--- a/sys/contrib/dev/acpica/include/acpixf.h
+++ b/sys/contrib/dev/acpica/include/acpixf.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20121114
+#define ACPI_CA_VERSION 0x20130117
#include <contrib/dev/acpica/include/acconfig.h>
#include <contrib/dev/acpica/include/actypes.h>
@@ -618,6 +618,12 @@ AcpiGetEventResources (
ACPI_BUFFER *RetBuffer);
ACPI_STATUS
+AcpiWalkResourceBuffer (
+ ACPI_BUFFER *Buffer,
+ ACPI_WALK_RESOURCE_CALLBACK UserFunction,
+ void *Context);
+
+ACPI_STATUS
AcpiWalkResources (
ACPI_HANDLE Device,
char *Name,
diff --git a/sys/contrib/dev/acpica/include/acpredef.h b/sys/contrib/dev/acpica/include/acpredef.h
index c5b115e..771e344 100644
--- a/sys/contrib/dev/acpica/include/acpredef.h
+++ b/sys/contrib/dev/acpica/include/acpredef.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -345,8 +345,8 @@ static const ACPI_PREDEFINED_INFO PredefinedNames[] =
{{"_MBM", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (8 Int) */
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 8,0}, 0,0}},
- {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (2 Str) */
- {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 2,0}, 0,0}},
+ {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (1 Str/1 Buf) */
+ {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 1, ACPI_RTYPE_BUFFER}, 1,0}},
{{"_MSG", 1, 0}},
{{"_MSM", 4, ACPI_RTYPE_INTEGER}},
diff --git a/sys/contrib/dev/acpica/include/acresrc.h b/sys/contrib/dev/acpica/include/acresrc.h
index e9ae052..b894e2f 100644
--- a/sys/contrib/dev/acpica/include/acresrc.h
+++ b/sys/contrib/dev/acpica/include/acresrc.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -265,7 +265,7 @@ AcpiRsConvertAmlToResources (
UINT32 Length,
UINT32 Offset,
UINT8 ResourceIndex,
- void *Context);
+ void **Context);
ACPI_STATUS
AcpiRsConvertResourcesToAml (
@@ -405,18 +405,21 @@ extern ACPI_RSDUMP_INFO *AcpiGbl_DumpResourceDispatch[];
extern ACPI_RSDUMP_INFO *AcpiGbl_DumpSerialBusDispatch[];
/*
- * rsdump
+ * rsdumpinfo
*/
extern ACPI_RSDUMP_INFO AcpiRsDumpIrq[];
+extern ACPI_RSDUMP_INFO AcpiRsDumpPrt[];
extern ACPI_RSDUMP_INFO AcpiRsDumpDma[];
extern ACPI_RSDUMP_INFO AcpiRsDumpStartDpf[];
extern ACPI_RSDUMP_INFO AcpiRsDumpEndDpf[];
extern ACPI_RSDUMP_INFO AcpiRsDumpIo[];
+extern ACPI_RSDUMP_INFO AcpiRsDumpIoFlags[];
extern ACPI_RSDUMP_INFO AcpiRsDumpFixedIo[];
extern ACPI_RSDUMP_INFO AcpiRsDumpVendor[];
extern ACPI_RSDUMP_INFO AcpiRsDumpEndTag[];
extern ACPI_RSDUMP_INFO AcpiRsDumpMemory24[];
extern ACPI_RSDUMP_INFO AcpiRsDumpMemory32[];
+extern ACPI_RSDUMP_INFO AcpiRsDumpMemoryFlags[];
extern ACPI_RSDUMP_INFO AcpiRsDumpFixedMemory32[];
extern ACPI_RSDUMP_INFO AcpiRsDumpAddress16[];
extern ACPI_RSDUMP_INFO AcpiRsDumpAddress32[];
@@ -430,6 +433,7 @@ extern ACPI_RSDUMP_INFO AcpiRsDumpCommonSerialBus[];
extern ACPI_RSDUMP_INFO AcpiRsDumpI2cSerialBus[];
extern ACPI_RSDUMP_INFO AcpiRsDumpSpiSerialBus[];
extern ACPI_RSDUMP_INFO AcpiRsDumpUartSerialBus[];
+extern ACPI_RSDUMP_INFO AcpiRsDumpGeneralFlags[];
#endif
#endif /* __ACRESRC_H__ */
diff --git a/sys/contrib/dev/acpica/include/acrestyp.h b/sys/contrib/dev/acpica/include/acrestyp.h
index 07a6076..9d69825 100644
--- a/sys/contrib/dev/acpica/include/acrestyp.h
+++ b/sys/contrib/dev/acpica/include/acrestyp.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -103,8 +103,11 @@ typedef UINT32 ACPI_RSDESC_SIZE; /* Max Resource Descr
#define ACPI_EXCLUSIVE (UINT8) 0x00
#define ACPI_SHARED (UINT8) 0x01
-#define ACPI_EXCLUSIVE_AND_WAKE (UINT8) 0x02
-#define ACPI_SHARED_AND_WAKE (UINT8) 0x03
+
+/* Wake */
+
+#define ACPI_NOT_WAKE_CAPABLE (UINT8) 0x00
+#define ACPI_WAKE_CAPABLE (UINT8) 0x01
/*
* DMA Attributes
@@ -177,6 +180,7 @@ typedef struct acpi_resource_irq
UINT8 Triggering;
UINT8 Polarity;
UINT8 Sharable;
+ UINT8 WakeCapable;
UINT8 InterruptCount;
UINT8 Interrupts[1];
@@ -402,6 +406,7 @@ typedef struct acpi_resource_extended_irq
UINT8 Triggering;
UINT8 Polarity;
UINT8 Sharable;
+ UINT8 WakeCapable;
UINT8 InterruptCount;
ACPI_RESOURCE_SOURCE ResourceSource;
UINT32 Interrupts[1];
@@ -425,6 +430,7 @@ typedef struct acpi_resource_gpio
UINT8 ProducerConsumer; /* For values, see Producer/Consumer above */
UINT8 PinConfig;
UINT8 Sharable; /* For values, see Interrupt Attributes above */
+ UINT8 WakeCapable; /* For values, see Interrupt Attributes above */
UINT8 IoRestriction;
UINT8 Triggering; /* For values, see Interrupt Attributes above */
UINT8 Polarity; /* For values, see Interrupt Attributes above */
diff --git a/sys/contrib/dev/acpica/include/acstruct.h b/sys/contrib/dev/acpica/include/acstruct.h
index ff01e86..8923d81 100644
--- a/sys/contrib/dev/acpica/include/acstruct.h
+++ b/sys/contrib/dev/acpica/include/acstruct.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/actables.h b/sys/contrib/dev/acpica/include/actables.h
index 26a7947d..b16c6e3 100644
--- a/sys/contrib/dev/acpica/include/actables.h
+++ b/sys/contrib/dev/acpica/include/actables.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/actbl.h b/sys/contrib/dev/acpica/include/actbl.h
index 90264dd..d77d6c4 100644
--- a/sys/contrib/dev/acpica/include/actbl.h
+++ b/sys/contrib/dev/acpica/include/actbl.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/actbl1.h b/sys/contrib/dev/acpica/include/actbl1.h
index d7cc59b..67579da 100644
--- a/sys/contrib/dev/acpica/include/actbl1.h
+++ b/sys/contrib/dev/acpica/include/actbl1.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/actbl2.h b/sys/contrib/dev/acpica/include/actbl2.h
index 2d2d5ca..49b9578 100644
--- a/sys/contrib/dev/acpica/include/actbl2.h
+++ b/sys/contrib/dev/acpica/include/actbl2.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -285,6 +285,7 @@ typedef struct acpi_table_csrt
} ACPI_TABLE_CSRT;
+
/* Resource Group subtable */
typedef struct acpi_csrt_group
@@ -296,12 +297,33 @@ typedef struct acpi_csrt_group
UINT16 SubdeviceId;
UINT16 Revision;
UINT16 Reserved;
- UINT32 InfoLength;
+ UINT32 SharedInfoLength;
- /* Shared data (length = InfoLength) immediately follows */
+ /* Shared data immediately follows (Length = SharedInfoLength) */
} ACPI_CSRT_GROUP;
+/* Shared Info subtable */
+
+typedef struct acpi_csrt_shared_info
+{
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 MmioBaseLow;
+ UINT32 MmioBaseHigh;
+ UINT32 GsiInterrupt;
+ UINT8 InterruptPolarity;
+ UINT8 InterruptMode;
+ UINT8 NumChannels;
+ UINT8 DmaAddressWidth;
+ UINT16 BaseRequestLine;
+ UINT16 NumHandshakeSignals;
+ UINT32 MaxBlockSize;
+
+ /* Resource descriptors immediately follow (Length = Group Length - SharedInfoLength) */
+
+} ACPI_CSRT_SHARED_INFO;
+
/* Resource Descriptor subtable */
typedef struct acpi_csrt_descriptor
diff --git a/sys/contrib/dev/acpica/include/actbl3.h b/sys/contrib/dev/acpica/include/actbl3.h
index 874e348..46c3c6d 100644
--- a/sys/contrib/dev/acpica/include/actbl3.h
+++ b/sys/contrib/dev/acpica/include/actbl3.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -70,13 +70,13 @@
#define ACPI_SIG_PCCT "PCCT" /* Platform Communications Channel Table */
#define ACPI_SIG_PMTT "PMTT" /* Platform Memory Topology Table */
#define ACPI_SIG_RASF "RASF" /* RAS Feature table */
+#define ACPI_SIG_TPM2 "TPM2" /* Trusted Platform Module 2.0 H/W interface table */
#define ACPI_SIG_S3PT "S3PT" /* S3 Performance (sub)Table */
#define ACPI_SIG_PCCS "PCC" /* PCC Shared Memory Region */
/* Reserved table signatures */
-#define ACPI_SIG_CSRT "CSRT" /* Core System Resources Table */
#define ACPI_SIG_MATR "MATR" /* Memory Address Translation Table */
#define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */
#define ACPI_SIG_WPBT "WPBT" /* Windows Platform Binary Table */
@@ -648,6 +648,41 @@ enum AcpiRasfStatus
#define ACPI_RASF_STATUS (0x1F<<3)
+/*******************************************************************************
+ *
+ * TPM2 - Trusted Platform Module (TPM) 2.0 Hardware Interface Table
+ * Version 3
+ *
+ * Conforms to "TPM 2.0 Hardware Interface Table (TPM2)" 29 November 2011
+ *
+ ******************************************************************************/
+
+typedef struct acpi_table_tpm2
+{
+ ACPI_TABLE_HEADER Header; /* Common ACPI table header */
+ UINT32 Flags;
+ UINT64 ControlAddress;
+ UINT32 StartMethod;
+
+} ACPI_TABLE_TPM2;
+
+/* Control area structure (not part of table, pointed to by ControlAddress) */
+
+typedef struct acpi_tpm2_control
+{
+ UINT32 Reserved;
+ UINT32 Error;
+ UINT32 Cancel;
+ UINT32 Start;
+ UINT64 InterruptControl;
+ UINT32 CommandSize;
+ UINT64 CommandAddress;
+ UINT32 ResponseSize;
+ UINT64 ResponseAddress;
+
+} ACPI_TPM2_CONTROL;
+
+
/* Reset to default packing */
#pragma pack()
diff --git a/sys/contrib/dev/acpica/include/actypes.h b/sys/contrib/dev/acpica/include/actypes.h
index 611c418..9c8ec7d 100644
--- a/sys/contrib/dev/acpica/include/actypes.h
+++ b/sys/contrib/dev/acpica/include/actypes.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -295,7 +295,7 @@ typedef UINT32 ACPI_PHYSICAL_ADDRESS;
/*
* Some compilers complain about unused variables. Sometimes we don't want to
* use all the variables (for example, _AcpiModuleName). This allows us
- * to to tell the compiler in a per-variable manner that a variable
+ * to tell the compiler in a per-variable manner that a variable
* is unused
*/
#ifndef ACPI_UNUSED_VAR
@@ -346,7 +346,7 @@ typedef UINT32 ACPI_PHYSICAL_ADDRESS;
/* PM Timer ticks per second (HZ) */
-#define PM_TIMER_FREQUENCY 3579545
+#define ACPI_PM_TIMER_FREQUENCY 3579545
/*******************************************************************************
@@ -381,6 +381,22 @@ typedef char * ACPI_STRING; /* Null terminated ASCII
typedef void * ACPI_HANDLE; /* Actually a ptr to a NS Node */
+/* Time constants for timer calculations */
+
+#define ACPI_MSEC_PER_SEC 1000L
+
+#define ACPI_USEC_PER_MSEC 1000L
+#define ACPI_USEC_PER_SEC 1000000L
+
+#define ACPI_100NSEC_PER_USEC 10L
+#define ACPI_100NSEC_PER_MSEC 10000L
+#define ACPI_100NSEC_PER_SEC 10000000L
+
+#define ACPI_NSEC_PER_USEC 1000L
+#define ACPI_NSEC_PER_MSEC 1000000L
+#define ACPI_NSEC_PER_SEC 1000000000L
+
+
/* Owner IDs are used to track namespace nodes for selective deletion */
typedef UINT8 ACPI_OWNER_ID;
@@ -596,7 +612,7 @@ typedef UINT32 ACPI_OBJECT_TYPE;
/*
* These are special object types that never appear in
- * a Namespace node, only in an ACPI_OPERAND_OBJECT
+ * a Namespace node, only in an object of ACPI_OPERAND_OBJECT
*/
#define ACPI_TYPE_LOCAL_EXTRA 0x1C
#define ACPI_TYPE_LOCAL_DATA 0x1D
@@ -904,6 +920,10 @@ typedef struct acpi_buffer
} ACPI_BUFFER;
+/* Free a buffer created in an ACPI_BUFFER via ACPI_ALLOCATE_LOCAL_BUFFER */
+
+#define ACPI_FREE_BUFFER(b) ACPI_FREE(b.Pointer)
+
/*
* NameType for AcpiGetName
@@ -1206,7 +1226,6 @@ typedef struct acpi_memory_list
UINT16 ObjectSize;
UINT16 MaxDepth;
UINT16 CurrentDepth;
- UINT16 LinkOffset;
#ifdef ACPI_DBG_TRACK_ALLOCATIONS
diff --git a/sys/contrib/dev/acpica/include/acutils.h b/sys/contrib/dev/acpica/include/acutils.h
index f663a1e..e75e248 100644
--- a/sys/contrib/dev/acpica/include/acutils.h
+++ b/sys/contrib/dev/acpica/include/acutils.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -101,7 +101,7 @@ ACPI_STATUS (*ACPI_WALK_AML_CALLBACK) (
UINT32 Length,
UINT32 Offset,
UINT8 ResourceIndex,
- void *Context);
+ void **Context);
typedef
ACPI_STATUS (*ACPI_PKG_CALLBACK) (
@@ -709,10 +709,6 @@ AcpiUtShortDivide (
/*
* utmisc
*/
-void
-UtConvertBackslashes (
- char *Pathname);
-
const char *
AcpiUtValidateException (
ACPI_STATUS Status);
@@ -726,56 +722,12 @@ AcpiUtIsAmlTable (
ACPI_TABLE_HEADER *Table);
ACPI_STATUS
-AcpiUtAllocateOwnerId (
- ACPI_OWNER_ID *OwnerId);
-
-void
-AcpiUtReleaseOwnerId (
- ACPI_OWNER_ID *OwnerId);
-
-ACPI_STATUS
AcpiUtWalkPackageTree (
ACPI_OPERAND_OBJECT *SourceObject,
void *TargetObject,
ACPI_PKG_CALLBACK WalkCallback,
void *Context);
-void
-AcpiUtStrupr (
- char *SrcString);
-
-void
-AcpiUtStrlwr (
- char *SrcString);
-
-int
-AcpiUtStricmp (
- char *String1,
- char *String2);
-
-void
-AcpiUtPrintString (
- char *String,
- UINT8 MaxLength);
-
-BOOLEAN
-AcpiUtValidAcpiName (
- UINT32 Name);
-
-void
-AcpiUtRepairName (
- char *Name);
-
-BOOLEAN
-AcpiUtValidAcpiChar (
- char Character,
- UINT32 Position);
-
-ACPI_STATUS
-AcpiUtStrtoul64 (
- char *String,
- UINT32 Base,
- UINT64 *RetInteger);
/* Values for Base above (16=Hex, 10=Decimal) */
@@ -799,6 +751,18 @@ AcpiUtDisplayInitPathname (
/*
+ * utownerid - Support for Table/Method Owner IDs
+ */
+ACPI_STATUS
+AcpiUtAllocateOwnerId (
+ ACPI_OWNER_ID *OwnerId);
+
+void
+AcpiUtReleaseOwnerId (
+ ACPI_OWNER_ID *OwnerId);
+
+
+/*
* utresrc
*/
ACPI_STATUS
@@ -807,7 +771,7 @@ AcpiUtWalkAmlResources (
UINT8 *Aml,
ACPI_SIZE AmlLength,
ACPI_WALK_AML_CALLBACK UserFunction,
- void *Context);
+ void **Context);
ACPI_STATUS
AcpiUtValidateResource (
@@ -838,6 +802,51 @@ AcpiUtGetResourceEndTag (
/*
+ * utstring - String and character utilities
+ */
+void
+AcpiUtStrupr (
+ char *SrcString);
+
+void
+AcpiUtStrlwr (
+ char *SrcString);
+
+int
+AcpiUtStricmp (
+ char *String1,
+ char *String2);
+
+ACPI_STATUS
+AcpiUtStrtoul64 (
+ char *String,
+ UINT32 Base,
+ UINT64 *RetInteger);
+
+void
+AcpiUtPrintString (
+ char *String,
+ UINT8 MaxLength);
+
+void
+UtConvertBackslashes (
+ char *Pathname);
+
+BOOLEAN
+AcpiUtValidAcpiName (
+ UINT32 Name);
+
+BOOLEAN
+AcpiUtValidAcpiChar (
+ char Character,
+ UINT32 Position);
+
+void
+AcpiUtRepairName (
+ char *Name);
+
+
+/*
* utmutex - mutex support
*/
ACPI_STATUS
diff --git a/sys/contrib/dev/acpica/include/amlcode.h b/sys/contrib/dev/acpica/include/amlcode.h
index f778bb0..66af4c2 100644
--- a/sys/contrib/dev/acpica/include/amlcode.h
+++ b/sys/contrib/dev/acpica/include/amlcode.h
@@ -7,7 +7,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/amlresrc.h b/sys/contrib/dev/acpica/include/amlresrc.h
index 2202bb9..8e68559 100644
--- a/sys/contrib/dev/acpica/include/amlresrc.h
+++ b/sys/contrib/dev/acpica/include/amlresrc.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/platform/acenv.h b/sys/contrib/dev/acpica/include/platform/acenv.h
index 4c23f30..dea4db2 100644
--- a/sys/contrib/dev/acpica/include/platform/acenv.h
+++ b/sys/contrib/dev/acpica/include/platform/acenv.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -300,7 +300,7 @@
*/
#ifdef ACPI_USE_SYSTEM_CLIBRARY
-/* Use the standard C library headers. We want to keep these to a minimum */
+/* Use the standard C library headers. We want to keep these to a minimum. */
#ifdef ACPI_USE_STANDARD_HEADERS
diff --git a/sys/contrib/dev/acpica/include/platform/acfreebsd.h b/sys/contrib/dev/acpica/include/platform/acfreebsd.h
index d7aa7ed..6b32ce7 100644
--- a/sys/contrib/dev/acpica/include/platform/acfreebsd.h
+++ b/sys/contrib/dev/acpica/include/platform/acfreebsd.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/sys/contrib/dev/acpica/include/platform/acgcc.h b/sys/contrib/dev/acpica/include/platform/acgcc.h
index d2eafff..1662a9b 100644
--- a/sys/contrib/dev/acpica/include/platform/acgcc.h
+++ b/sys/contrib/dev/acpica/include/platform/acgcc.h
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,7 +59,7 @@
/*
* Some compilers complain about unused variables. Sometimes we don't want to
* use all the variables (for example, _AcpiModuleName). This allows us
- * to to tell the compiler warning in a per-variable manner that a variable
+ * to tell the compiler warning in a per-variable manner that a variable
* is unused.
*/
#define ACPI_UNUSED_VAR __attribute__ ((unused))
diff --git a/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c b/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c
index cf6382b..c18d65c 100644
--- a/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c
+++ b/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c
@@ -5,7 +5,7 @@
*****************************************************************************/
/*
- * Copyright (C) 2000 - 2012, Intel Corp.
+ * Copyright (C) 2000 - 2013, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -84,6 +84,10 @@ AeTableOverride (
typedef void* (*PTHREAD_CALLBACK) (void *);
+/* Buffer used by AcpiOsVprintf */
+
+#define ACPI_VPRINTF_BUFFER_SIZE 512
+
/* Apple-specific */
#ifdef __APPLE__
@@ -268,7 +272,8 @@ AcpiOsRedirectOutput (
*
* RETURN: None
*
- * DESCRIPTION: Formatted output
+ * DESCRIPTION: Formatted output. Note: very similar to AcpiOsVprintf
+ * (performance), changes should be tracked in both functions.
*
*****************************************************************************/
@@ -278,11 +283,36 @@ AcpiOsPrintf (
...)
{
va_list Args;
+ UINT8 Flags;
+
+
+ Flags = AcpiGbl_DbOutputFlags;
+ if (Flags & ACPI_DB_REDIRECTABLE_OUTPUT)
+ {
+ /* Output is directable to either a file (if open) or the console */
+
+ if (AcpiGbl_DebugFile)
+ {
+ /* Output file is open, send the output there */
+
+ va_start (Args, Fmt);
+ vfprintf (AcpiGbl_DebugFile, Fmt, Args);
+ va_end (Args);
+ }
+ else
+ {
+ /* No redirection, send output to console (once only!) */
+ Flags |= ACPI_DB_CONSOLE_OUTPUT;
+ }
+ }
- va_start (Args, Fmt);
- AcpiOsVprintf (Fmt, Args);
- va_end (Args);
+ if (Flags & ACPI_DB_CONSOLE_OUTPUT)
+ {
+ va_start (Args, Fmt);
+ vfprintf (AcpiGbl_OutputFile, Fmt, Args);
+ va_end (Args);
+ }
}
@@ -295,7 +325,9 @@ AcpiOsPrintf (
*
* RETURN: None
*
- * DESCRIPTION: Formatted output with argument list pointer
+ * DESCRIPTION: Formatted output with argument list pointer. Note: very
+ * similar to AcpiOsPrintf, changes should be tracked in both
+ * functions.
*
*****************************************************************************/
@@ -305,7 +337,20 @@ AcpiOsVprintf (
va_list Args)
{
UINT8 Flags;
+ char Buffer[ACPI_VPRINTF_BUFFER_SIZE];
+
+ /*
+ * We build the output string in a local buffer because we may be
+ * outputting the buffer twice. Using vfprintf is problematic because
+ * some implementations modify the args pointer/structure during
+ * execution. Thus, we use the local buffer for portability.
+ *
+ * Note: Since this module is intended for use by the various ACPICA
+ * utilities/applications, we can safely declare the buffer on the stack.
+ * Also, This function is used for relatively small error messages only.
+ */
+ vsnprintf (Buffer, ACPI_VPRINTF_BUFFER_SIZE, Fmt, Args);
Flags = AcpiGbl_DbOutputFlags;
if (Flags & ACPI_DB_REDIRECTABLE_OUTPUT)
@@ -316,7 +361,7 @@ AcpiOsVprintf (
{
/* Output file is open, send the output there */
- vfprintf (AcpiGbl_DebugFile, Fmt, Args);
+ fputs (Buffer, AcpiGbl_DebugFile);
}
else
{
@@ -328,7 +373,7 @@ AcpiOsVprintf (
if (Flags & ACPI_DB_CONSOLE_OUTPUT)
{
- vfprintf (AcpiGbl_OutputFile, Fmt, Args);
+ fputs (Buffer, AcpiGbl_OutputFile);
}
}
@@ -626,7 +671,7 @@ AcpiOsDeleteSemaphore (
*
* PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore
* Units - How many units to wait for
- * Timeout - How long to wait
+ * MsecTimeout - How long to wait (milliseconds)
*
* RETURN: Status
*
@@ -638,11 +683,14 @@ ACPI_STATUS
AcpiOsWaitSemaphore (
ACPI_HANDLE Handle,
UINT32 Units,
- UINT16 Timeout)
+ UINT16 MsecTimeout)
{
ACPI_STATUS Status = AE_OK;
sem_t *Sem = (sem_t *) Handle;
- struct timespec T;
+#ifndef ACPI_USE_ALTERNATE_TIMEOUT
+ struct timespec Time;
+ int RetVal;
+#endif
if (!Sem)
@@ -650,7 +698,7 @@ AcpiOsWaitSemaphore (
return (AE_BAD_PARAMETER);
}
- switch (Timeout)
+ switch (MsecTimeout)
{
/*
* No Wait:
@@ -677,37 +725,71 @@ AcpiOsWaitSemaphore (
}
break;
- /* Wait with Timeout */
+ /* Wait with MsecTimeout */
default:
- T.tv_sec = Timeout / 1000;
- T.tv_nsec = (Timeout - (T.tv_sec * 1000)) * 1000000;
-
#ifdef ACPI_USE_ALTERNATE_TIMEOUT
/*
* Alternate timeout mechanism for environments where
* sem_timedwait is not available or does not work properly.
*/
- while (Timeout)
+ while (MsecTimeout)
{
if (sem_trywait (Sem) == 0)
{
/* Got the semaphore */
return (AE_OK);
}
- usleep (1000); /* one millisecond */
- Timeout--;
+
+ if (MsecTimeout >= 10)
+ {
+ MsecTimeout -= 10;
+ usleep (10 * ACPI_USEC_PER_MSEC); /* ten milliseconds */
+ }
+ else
+ {
+ MsecTimeout--;
+ usleep (ACPI_USEC_PER_MSEC); /* one millisecond */
+ }
}
Status = (AE_TIME);
#else
+ /*
+ * The interface to sem_timedwait is an absolute time, so we need to
+ * get the current time, then add in the millisecond Timeout value.
+ */
+ if (clock_gettime (CLOCK_REALTIME, &Time) == -1)
+ {
+ perror ("clock_gettime");
+ return (AE_TIME);
+ }
+
+ Time.tv_sec += (MsecTimeout / ACPI_MSEC_PER_SEC);
+ Time.tv_nsec += ((MsecTimeout % ACPI_MSEC_PER_SEC) * ACPI_NSEC_PER_MSEC);
+
+ /* Handle nanosecond overflow (field must be less than one second) */
+
+ if (Time.tv_nsec >= ACPI_NSEC_PER_SEC)
+ {
+ Time.tv_sec += (Time.tv_nsec / ACPI_NSEC_PER_SEC);
+ Time.tv_nsec = (Time.tv_nsec % ACPI_NSEC_PER_SEC);
+ }
+
+ while (((RetVal = sem_timedwait (Sem, &Time)) == -1) && (errno == EINTR))
+ {
+ continue;
+ }
- if (sem_timedwait (Sem, &T))
+ if (RetVal != 0)
{
+ if (errno != ETIMEDOUT)
+ {
+ perror ("sem_timedwait");
+ }
Status = (AE_TIME);
}
#endif
-
break;
}
@@ -884,12 +966,15 @@ AcpiOsSleep (
UINT64 milliseconds)
{
- sleep (milliseconds / 1000); /* Sleep for whole seconds */
+ /* Sleep for whole seconds */
+
+ sleep (milliseconds / ACPI_MSEC_PER_SEC);
/*
- * Arg to usleep() must be less than 1,000,000 (1 second)
+ * Sleep for remaining microseconds.
+ * Arg to usleep() is in usecs and must be less than 1,000,000 (1 second).
*/
- usleep ((milliseconds % 1000) * 1000); /* Sleep for remaining usecs */
+ usleep ((milliseconds % ACPI_MSEC_PER_SEC) * ACPI_USEC_PER_MSEC);
}
@@ -912,11 +997,14 @@ AcpiOsGetTimer (
struct timeval time;
+ /* This timer has sufficient resolution for user-space application code */
+
gettimeofday (&time, NULL);
- /* Seconds * 10^7 = 100ns(10^-7), Microseconds(10^-6) * 10^1 = 100ns */
+ /* (Seconds * 10^7 = 100ns(10^-7)) + (Microseconds(10^-6) * 10^1 = 100ns) */
- return (((UINT64) time.tv_sec * 10000000) + ((UINT64) time.tv_usec * 10));
+ return (((UINT64) time.tv_sec * ACPI_100NSEC_PER_SEC) +
+ ((UINT64) time.tv_usec * ACPI_100NSEC_PER_USEC));
}
diff --git a/sys/contrib/octeon-sdk/cvmx-helper-board.c b/sys/contrib/octeon-sdk/cvmx-helper-board.c
index 8d2b0bd..d97813e 100644
--- a/sys/contrib/octeon-sdk/cvmx-helper-board.c
+++ b/sys/contrib/octeon-sdk/cvmx-helper-board.c
@@ -1394,6 +1394,21 @@ int __cvmx_helper_board_hardware_enable(int interface)
}
}
}
+#if defined(OCTEON_VENDOR_UBIQUITI)
+ else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_UBIQUITI_E100)
+ {
+ /* Configure ASX cloks for all ports on interface 0. */
+ if (interface == 0)
+ {
+ int port;
+
+ for (port = 0; port < 3; port++) {
+ cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 16);
+ cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 0);
+ }
+ }
+ }
+#endif
return 0;
}
diff --git a/sys/dev/acpi_support/acpi_asus_wmi.c b/sys/dev/acpi_support/acpi_asus_wmi.c
index 9e2a498..54a2893 100644
--- a/sys/dev/acpi_support/acpi_asus_wmi.c
+++ b/sys/dev/acpi_support/acpi_asus_wmi.c
@@ -304,7 +304,8 @@ static device_method_t acpi_asus_wmi_methods[] = {
DEVMETHOD(device_probe, acpi_asus_wmi_probe),
DEVMETHOD(device_attach, acpi_asus_wmi_attach),
DEVMETHOD(device_detach, acpi_asus_wmi_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t acpi_asus_wmi_driver = {
diff --git a/sys/dev/acpi_support/acpi_fujitsu.c b/sys/dev/acpi_support/acpi_fujitsu.c
index 2455b50..6f96bc5 100644
--- a/sys/dev/acpi_support/acpi_fujitsu.c
+++ b/sys/dev/acpi_support/acpi_fujitsu.c
@@ -154,7 +154,8 @@ static device_method_t acpi_fujitsu_methods[] = {
DEVMETHOD(device_detach, acpi_fujitsu_detach),
DEVMETHOD(device_suspend, acpi_fujitsu_suspend),
DEVMETHOD(device_resume, acpi_fujitsu_resume),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t acpi_fujitsu_driver = {
diff --git a/sys/dev/acpi_support/acpi_hp.c b/sys/dev/acpi_support/acpi_hp.c
index edc04b7..c190166 100644
--- a/sys/dev/acpi_support/acpi_hp.c
+++ b/sys/dev/acpi_support/acpi_hp.c
@@ -324,7 +324,8 @@ static device_method_t acpi_hp_methods[] = {
DEVMETHOD(device_probe, acpi_hp_probe),
DEVMETHOD(device_attach, acpi_hp_attach),
DEVMETHOD(device_detach, acpi_hp_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t acpi_hp_driver = {
diff --git a/sys/dev/acpi_support/acpi_ibm.c b/sys/dev/acpi_support/acpi_ibm.c
index 46a985e..4160112 100644
--- a/sys/dev/acpi_support/acpi_ibm.c
+++ b/sys/dev/acpi_support/acpi_ibm.c
@@ -303,7 +303,7 @@ static device_method_t acpi_ibm_methods[] = {
DEVMETHOD(device_detach, acpi_ibm_detach),
DEVMETHOD(device_resume, acpi_ibm_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_ibm_driver = {
diff --git a/sys/dev/acpi_support/acpi_panasonic.c b/sys/dev/acpi_support/acpi_panasonic.c
index ad8b239..2542b0c 100644
--- a/sys/dev/acpi_support/acpi_panasonic.c
+++ b/sys/dev/acpi_support/acpi_panasonic.c
@@ -118,7 +118,7 @@ static device_method_t acpi_panasonic_methods[] = {
DEVMETHOD(device_detach, acpi_panasonic_detach),
DEVMETHOD(device_shutdown, acpi_panasonic_shutdown),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_panasonic_driver = {
diff --git a/sys/dev/acpi_support/acpi_sony.c b/sys/dev/acpi_support/acpi_sony.c
index 2a0d40e..95e7b4f 100644
--- a/sys/dev/acpi_support/acpi_sony.c
+++ b/sys/dev/acpi_support/acpi_sony.c
@@ -95,7 +95,7 @@ static device_method_t acpi_sony_methods[] = {
DEVMETHOD(device_attach, acpi_sony_attach),
DEVMETHOD(device_detach, acpi_sony_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_sony_driver = {
diff --git a/sys/dev/acpi_support/acpi_toshiba.c b/sys/dev/acpi_support/acpi_toshiba.c
index 343d3ae..9e3dc5b 100644
--- a/sys/dev/acpi_support/acpi_toshiba.c
+++ b/sys/dev/acpi_support/acpi_toshiba.c
@@ -172,7 +172,7 @@ static device_method_t acpi_toshiba_methods[] = {
DEVMETHOD(device_attach, acpi_toshiba_attach),
DEVMETHOD(device_detach, acpi_toshiba_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_toshiba_driver = {
@@ -190,7 +190,7 @@ static device_method_t acpi_toshiba_video_methods[] = {
DEVMETHOD(device_probe, acpi_toshiba_video_probe),
DEVMETHOD(device_attach, acpi_toshiba_video_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_toshiba_video_driver = {
diff --git a/sys/dev/acpica/Osd/OsdSchedule.c b/sys/dev/acpica/Osd/OsdSchedule.c
index 6d517cb..4afcec5 100644
--- a/sys/dev/acpica/Osd/OsdSchedule.c
+++ b/sys/dev/acpica/Osd/OsdSchedule.c
@@ -181,12 +181,13 @@ ACPI_STATUS
AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function,
void *Context)
{
+ ACPI_STATUS status;
int pri;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
if (Function == NULL)
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
switch (Type) {
case OSL_GPE_HANDLER:
@@ -208,10 +209,11 @@ AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function,
pri = 0;
break;
default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- return_ACPI_STATUS (acpi_task_enqueue(pri, Function, Context));
+ status = acpi_task_enqueue(pri, Function, Context);
+ return_ACPI_STATUS(status);
}
void
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index e2f8c1c..f0c750f 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -217,7 +217,7 @@ static device_method_t acpi_methods[] = {
/* ISA emulation */
DEVMETHOD(isa_pnp_probe, acpi_isa_pnp_probe),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_driver = {
@@ -613,7 +613,9 @@ acpi_attach(device_t dev)
/* Probe all supported sleep states. */
acpi_sleep_states[ACPI_STATE_S0] = TRUE;
for (state = ACPI_STATE_S1; state < ACPI_S_STATE_COUNT; state++)
- if (ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB)))
+ if (ACPI_SUCCESS(AcpiEvaluateObject(ACPI_ROOT_OBJECT,
+ __DECONST(char *, AcpiGbl_SleepStateNames[state]), NULL, NULL)) &&
+ ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB)))
acpi_sleep_states[state] = TRUE;
/*
@@ -2657,6 +2659,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
{
register_t intr;
ACPI_STATUS status;
+ ACPI_EVENT_STATUS power_button_status;
enum acpi_sleep_state slp_state;
int sleep_result;
@@ -2742,7 +2745,44 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
if (state != ACPI_STATE_S1) {
sleep_result = acpi_sleep_machdep(sc, state);
acpi_wakeup_machdep(sc, state, sleep_result, 0);
+
+ /*
+ * XXX According to ACPI specification SCI_EN bit should be restored
+ * by ACPI platform (BIOS, firmware) to its pre-sleep state.
+ * Unfortunately some BIOSes fail to do that and that leads to
+ * unexpected and serious consequences during wake up like a system
+ * getting stuck in SMI handlers.
+ * This hack is picked up from Linux, which claims that it follows
+ * Windows behavior.
+ */
+ if (sleep_result == 1 && state != ACPI_STATE_S4)
+ AcpiWriteBitRegister(ACPI_BITREG_SCI_ENABLE, ACPI_ENABLE_EVENT);
+
AcpiLeaveSleepStatePrep(state);
+
+ if (sleep_result == 1 && state == ACPI_STATE_S3) {
+ /*
+ * Prevent mis-interpretation of the wakeup by power button
+ * as a request for power off.
+ * Ideally we should post an appropriate wakeup event,
+ * perhaps using acpi_event_power_button_wake or alike.
+ *
+ * Clearing of power button status after wakeup is mandated
+ * by ACPI specification in section "Fixed Power Button".
+ *
+ * XXX As of ACPICA 20121114 AcpiGetEventStatus provides
+ * status as 0/1 corressponding to inactive/active despite
+ * its type being ACPI_EVENT_STATUS. In other words,
+ * we should not test for ACPI_EVENT_FLAG_SET for time being.
+ */
+ if (ACPI_SUCCESS(AcpiGetEventStatus(ACPI_EVENT_POWER_BUTTON,
+ &power_button_status)) && power_button_status != 0) {
+ AcpiClearEvent(ACPI_EVENT_POWER_BUTTON);
+ device_printf(sc->acpi_dev,
+ "cleared fixed power button status\n");
+ }
+ }
+
intr_restore(intr);
/* call acpi_wakeup_machdep() again with interrupt enabled */
diff --git a/sys/dev/acpica/acpi_acad.c b/sys/dev/acpica/acpi_acad.c
index 8153abc..4c9dc19 100644
--- a/sys/dev/acpica/acpi_acad.c
+++ b/sys/dev/acpica/acpi_acad.c
@@ -74,7 +74,7 @@ static device_method_t acpi_acad_methods[] = {
DEVMETHOD(device_probe, acpi_acad_probe),
DEVMETHOD(device_attach, acpi_acad_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_acad_driver = {
diff --git a/sys/dev/acpica/acpi_button.c b/sys/dev/acpica/acpi_button.c
index d1f774a..72bf5b1 100644
--- a/sys/dev/acpica/acpi_button.c
+++ b/sys/dev/acpica/acpi_button.c
@@ -79,8 +79,7 @@ static device_method_t acpi_button_methods[] = {
DEVMETHOD(device_suspend, acpi_button_suspend),
DEVMETHOD(device_shutdown, acpi_button_suspend),
DEVMETHOD(device_resume, acpi_button_resume),
-
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_button_driver = {
diff --git a/sys/dev/acpica/acpi_cmbat.c b/sys/dev/acpica/acpi_cmbat.c
index ba44da8..be57a32 100644
--- a/sys/dev/acpica/acpi_cmbat.c
+++ b/sys/dev/acpica/acpi_cmbat.c
@@ -99,7 +99,7 @@ static device_method_t acpi_cmbat_methods[] = {
DEVMETHOD(acpi_batt_get_info, acpi_cmbat_bif),
DEVMETHOD(acpi_batt_get_status, acpi_cmbat_bst),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_cmbat_driver = {
diff --git a/sys/dev/acpica/acpi_dock.c b/sys/dev/acpica/acpi_dock.c
index b184053..d27b4bd 100644
--- a/sys/dev/acpica/acpi_dock.c
+++ b/sys/dev/acpica/acpi_dock.c
@@ -521,7 +521,7 @@ static device_method_t acpi_dock_methods[] = {
DEVMETHOD(device_probe, acpi_dock_probe),
DEVMETHOD(device_attach, acpi_dock_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_dock_driver = {
diff --git a/sys/dev/acpica/acpi_ec.c b/sys/dev/acpica/acpi_ec.c
index 00a3073..6e2f0dd 100644
--- a/sys/dev/acpica/acpi_ec.c
+++ b/sys/dev/acpica/acpi_ec.c
@@ -253,7 +253,7 @@ static device_method_t acpi_ec_methods[] = {
DEVMETHOD(acpi_ec_read, acpi_ec_read_method),
DEVMETHOD(acpi_ec_write, acpi_ec_write_method),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_ec_driver = {
diff --git a/sys/dev/acpica/acpi_hpet.c b/sys/dev/acpica/acpi_hpet.c
index 4b0c356..c00bda4 100644
--- a/sys/dev/acpica/acpi_hpet.c
+++ b/sys/dev/acpica/acpi_hpet.c
@@ -849,7 +849,7 @@ static device_method_t hpet_methods[] = {
DEVMETHOD(bus_remap_intr, hpet_remap_intr),
#endif
- {0, 0}
+ DEVMETHOD_END
};
static driver_t hpet_driver = {
diff --git a/sys/dev/acpica/acpi_lid.c b/sys/dev/acpica/acpi_lid.c
index d84e3c9..dcdd2e6 100644
--- a/sys/dev/acpica/acpi_lid.c
+++ b/sys/dev/acpica/acpi_lid.c
@@ -69,7 +69,7 @@ static device_method_t acpi_lid_methods[] = {
DEVMETHOD(device_suspend, acpi_lid_suspend),
DEVMETHOD(device_resume, acpi_lid_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_lid_driver = {
diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c
index 185731a..39fba88 100644
--- a/sys/dev/acpica/acpi_pci.c
+++ b/sys/dev/acpica/acpi_pci.c
@@ -94,7 +94,7 @@ static device_method_t acpi_pci_methods[] = {
/* PCI interface */
DEVMETHOD(pci_set_powerstate, acpi_pci_set_powerstate_method),
- { 0, 0 }
+ DEVMETHOD_END
};
static devclass_t pci_devclass;
diff --git a/sys/dev/acpica/acpi_pci_link.c b/sys/dev/acpica/acpi_pci_link.c
index ba03d72..1a1ae4d 100644
--- a/sys/dev/acpica/acpi_pci_link.c
+++ b/sys/dev/acpica/acpi_pci_link.c
@@ -1097,7 +1097,7 @@ static device_method_t acpi_pci_link_methods[] = {
DEVMETHOD(device_attach, acpi_pci_link_attach),
DEVMETHOD(device_resume, acpi_pci_link_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_pci_link_driver = {
diff --git a/sys/dev/acpica/acpi_pcib.c b/sys/dev/acpica/acpi_pcib.c
index 1b26b4f..1a42d74 100644
--- a/sys/dev/acpica/acpi_pcib.c
+++ b/sys/dev/acpica/acpi_pcib.c
@@ -129,7 +129,8 @@ prt_attach_devices(ACPI_PCI_ROUTING_TABLE *entry, void *arg)
int
acpi_pcib_attach(device_t dev, ACPI_BUFFER *prt, int busno)
{
- ACPI_STATUS status;
+ ACPI_STATUS status;
+ int error;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -168,7 +169,8 @@ acpi_pcib_attach(device_t dev, ACPI_BUFFER *prt, int busno)
*/
prt_walk_table(prt, prt_attach_devices, dev);
- return_VALUE (bus_generic_attach(dev));
+ error = bus_generic_attach(dev);
+ return_VALUE(error);
}
static void
@@ -273,7 +275,7 @@ acpi_pcib_route_interrupt(device_t pcib, device_t dev, int pin,
out:
ACPI_SERIAL_END(pcib);
- return_VALUE (interrupt);
+ return_VALUE(interrupt);
}
int
@@ -285,4 +287,3 @@ acpi_pcib_power_for_sleep(device_t pcib, device_t dev, int *pstate)
acpi_device_pwr_for_sleep(acpi_dev, dev, pstate);
return (0);
}
-
diff --git a/sys/dev/acpica/acpi_pcib_pci.c b/sys/dev/acpica/acpi_pcib_pci.c
index 7dbccd6..de26a4a 100644
--- a/sys/dev/acpica/acpi_pcib_pci.c
+++ b/sys/dev/acpica/acpi_pcib_pci.c
@@ -83,7 +83,7 @@ static device_method_t acpi_pcib_pci_methods[] = {
DEVMETHOD(pcib_route_interrupt, acpi_pcib_pci_route_interrupt),
DEVMETHOD(pcib_power_for_sleep, acpi_pcib_power_for_sleep),
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/sys/dev/acpica/acpi_perf.c b/sys/dev/acpica/acpi_perf.c
index 3f047cc..d95cc79 100644
--- a/sys/dev/acpica/acpi_perf.c
+++ b/sys/dev/acpica/acpi_perf.c
@@ -122,7 +122,8 @@ static device_method_t acpi_perf_methods[] = {
DEVMETHOD(cpufreq_drv_get, acpi_px_get),
DEVMETHOD(cpufreq_drv_type, acpi_px_type),
DEVMETHOD(cpufreq_drv_settings, acpi_px_settings),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t acpi_perf_driver = {
diff --git a/sys/dev/acpica/acpi_resource.c b/sys/dev/acpica/acpi_resource.c
index ce6732f..0878d96 100644
--- a/sys/dev/acpica/acpi_resource.c
+++ b/sys/dev/acpica/acpi_resource.c
@@ -615,7 +615,7 @@ static device_method_t acpi_sysres_methods[] = {
DEVMETHOD(device_probe, acpi_sysres_probe),
DEVMETHOD(device_attach, acpi_sysres_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_sysres_driver = {
diff --git a/sys/dev/acpica/acpi_smbat.c b/sys/dev/acpica/acpi_smbat.c
index f83392f..dda5e75 100644
--- a/sys/dev/acpica/acpi_smbat.c
+++ b/sys/dev/acpica/acpi_smbat.c
@@ -89,7 +89,7 @@ static device_method_t acpi_smbat_methods[] = {
DEVMETHOD(acpi_batt_get_status, acpi_smbat_get_bst),
DEVMETHOD(acpi_batt_get_info, acpi_smbat_get_bif),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_smbat_driver = {
diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c
index baa8205..485da9e 100644
--- a/sys/dev/acpica/acpi_thermal.c
+++ b/sys/dev/acpica/acpi_thermal.c
@@ -152,7 +152,7 @@ static device_method_t acpi_tz_methods[] = {
DEVMETHOD(device_probe, acpi_tz_probe),
DEVMETHOD(device_attach, acpi_tz_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_tz_driver = {
@@ -509,15 +509,8 @@ acpi_tz_monitor(void *Context)
*/
newactive = TZ_ACTIVE_NONE;
for (i = TZ_NUMLEVELS - 1; i >= 0; i--) {
- if (sc->tz_zone.ac[i] != -1 && temp >= sc->tz_zone.ac[i]) {
+ if (sc->tz_zone.ac[i] != -1 && temp >= sc->tz_zone.ac[i])
newactive = i;
- if (sc->tz_active != newactive) {
- ACPI_VPRINT(sc->tz_dev,
- acpi_device_get_parent_softc(sc->tz_dev),
- "_AC%d: temperature %d.%d >= setpoint %d.%d\n", i,
- TZ_KELVTOC(temp), TZ_KELVTOC(sc->tz_zone.ac[i]));
- }
- }
}
/*
diff --git a/sys/dev/acpica/acpi_throttle.c b/sys/dev/acpica/acpi_throttle.c
index 40476e0..ca14215 100644
--- a/sys/dev/acpica/acpi_throttle.c
+++ b/sys/dev/acpica/acpi_throttle.c
@@ -114,7 +114,7 @@ static device_method_t acpi_throttle_methods[] = {
DEVMETHOD(cpufreq_drv_get, acpi_thr_get),
DEVMETHOD(cpufreq_drv_type, acpi_thr_type),
DEVMETHOD(cpufreq_drv_settings, acpi_thr_settings),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_throttle_driver = {
diff --git a/sys/dev/acpica/acpi_timer.c b/sys/dev/acpica/acpi_timer.c
index 9f61cd8..80e6d18 100644
--- a/sys/dev/acpica/acpi_timer.c
+++ b/sys/dev/acpica/acpi_timer.c
@@ -82,7 +82,7 @@ static device_method_t acpi_timer_methods[] = {
DEVMETHOD(device_probe, acpi_timer_probe),
DEVMETHOD(device_attach, acpi_timer_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t acpi_timer_driver = {
diff --git a/sys/dev/adlink/adlink.c b/sys/dev/adlink/adlink.c
index b625d26..4180f57 100644
--- a/sys/dev/adlink/adlink.c
+++ b/sys/dev/adlink/adlink.c
@@ -407,7 +407,8 @@ static device_method_t adlink_methods[] = {
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t adlink_driver = {
diff --git a/sys/dev/agp/agp_i810.c b/sys/dev/agp/agp_i810.c
index 21c7ce6..9ec3992 100644
--- a/sys/dev/agp/agp_i810.c
+++ b/sys/dev/agp/agp_i810.c
@@ -2228,7 +2228,7 @@ agp_i830_chipset_flush(device_t dev)
bus_write_4(sc->sc_res[0], AGP_I830_HIC, hic | (1 << 31));
for (i = 0; i < 20000 /* 1 sec */; i++) {
hic = bus_read_4(sc->sc_res[0], AGP_I830_HIC);
- if ((hic & (1 << 31)) != 0)
+ if ((hic & (1 << 31)) == 0)
break;
DELAY(50);
}
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 5882c86..b17b9f3 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -114,8 +114,9 @@ static struct {
#define AHCI_Q_NOAA 512
#define AHCI_Q_NOCOUNT 1024
#define AHCI_Q_ALTSIG 2048
+#define AHCI_Q_NOMSI 4096
} ahci_ids[] = {
- {0x43801002, 0x00, "ATI IXP600", 0},
+ {0x43801002, 0x00, "ATI IXP600", AHCI_Q_NOMSI},
{0x43901002, 0x00, "ATI IXP700", 0},
{0x43911002, 0x00, "ATI IXP700", 0},
{0x43921002, 0x00, "ATI IXP700", 0},
@@ -634,6 +635,8 @@ ahci_setup_interrupt(device_t dev)
int i, msi = 1;
/* Process hints. */
+ if (ctlr->quirks & AHCI_Q_NOMSI)
+ msi = 0;
resource_int_value(device_get_name(dev),
device_get_unit(dev), "msi", &msi);
if (msi < 0)
diff --git a/sys/dev/altera/avgen/altera_avgen.c b/sys/dev/altera/avgen/altera_avgen.c
index a90b546..5429c9d 100644
--- a/sys/dev/altera/avgen/altera_avgen.c
+++ b/sys/dev/altera/avgen/altera_avgen.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2012 Robert N. M. Watson
+ * Copyright (c) 2012-2013 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -60,6 +60,8 @@ __FBSDID("$FreeBSD$");
* system-on-chip bus environments would work fine with the same code.
*/
+devclass_t altera_avgen_devclass;
+
static d_mmap_t altera_avgen_mmap;
static d_read_t altera_avgen_read;
static d_write_t altera_avgen_write;
@@ -226,13 +228,6 @@ altera_avgen_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
return (0);
}
-static int
-altera_avgen_nexus_probe(device_t dev)
-{
-
- device_set_desc(dev, "Generic Altera Avalon device attachment");
- return (BUS_PROBE_DEFAULT);
-}
static int
altera_avgen_process_options(struct altera_avgen_softc *sc,
@@ -321,42 +316,14 @@ altera_avgen_process_options(struct altera_avgen_softc *sc,
return (0);
}
-static int
-altera_avgen_nexus_attach(device_t dev)
+int
+altera_avgen_attach(struct altera_avgen_softc *sc, const char *str_fileio,
+ const char *str_mmapio, const char *str_devname, int devunit)
{
- struct altera_avgen_softc *sc;
- const char *str_fileio, *str_mmapio;
- const char *str_devname;
+ device_t dev = sc->avg_dev;
char devname[SPECNAMELEN + 1];
- int devunit, error;
-
- sc = device_get_softc(dev);
- sc->avg_dev = dev;
- sc->avg_unit = device_get_unit(dev);
+ int error;
- /*
- * Query non-standard hints to find out what operations are permitted
- * on the device, and whether it is cached.
- */
- str_fileio = NULL;
- str_mmapio = NULL;
- str_devname = NULL;
- devunit = -1;
- sc->avg_width = 1;
- error = resource_int_value(device_get_name(dev), device_get_unit(dev),
- ALTERA_AVALON_STR_WIDTH, &sc->avg_width);
- if (error != 0 && error != ENOENT) {
- device_printf(dev, "invalid %s\n", ALTERA_AVALON_STR_WIDTH);
- return (error);
- }
- (void)resource_string_value(device_get_name(dev),
- device_get_unit(dev), ALTERA_AVALON_STR_FILEIO, &str_fileio);
- (void)resource_string_value(device_get_name(dev),
- device_get_unit(dev), ALTERA_AVALON_STR_MMAPIO, &str_mmapio);
- (void)resource_string_value(device_get_name(dev),
- device_get_unit(dev), ALTERA_AVALON_STR_DEVNAME, &str_devname);
- (void)resource_int_value(device_get_name(dev), device_get_unit(dev),
- ALTERA_AVALON_STR_DEVUNIT, &devunit);
error = altera_avgen_process_options(sc, str_fileio, str_mmapio,
str_devname, devunit);
if (error)
@@ -374,25 +341,15 @@ altera_avgen_nexus_attach(device_t dev)
snprintf(devname, sizeof(devname), "%s%d", "avgen",
sc->avg_unit);
- /* Memory allocation and checking. */
- sc->avg_rid = 0;
- sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &sc->avg_rid, RF_ACTIVE);
- if (sc->avg_res == NULL) {
- device_printf(dev, "couldn't map memory\n");
- return (ENXIO);
- }
if (rman_get_size(sc->avg_res) >= PAGE_SIZE || str_mmapio != NULL) {
if (rman_get_size(sc->avg_res) % PAGE_SIZE != 0) {
device_printf(dev,
"memory region not even multiple of page size\n");
- error = ENXIO;
- goto error;
+ return (ENXIO);
}
if (rman_get_start(sc->avg_res) % PAGE_SIZE != 0) {
device_printf(dev, "memory region not page-aligned\n");
- error = ENXIO;
- goto error;
+ return (ENXIO);
}
}
@@ -409,43 +366,16 @@ altera_avgen_nexus_attach(device_t dev)
GID_WHEEL, S_IRUSR | S_IWUSR, str_devname);
if (sc->avg_cdev == NULL) {
device_printf(sc->avg_dev, "%s: make_dev failed\n", __func__);
- error = ENXIO;
- goto error;
+ return (ENXIO);
}
/* XXXRW: Slight race between make_dev(9) and here. */
sc->avg_cdev->si_drv1 = sc;
return (0);
-
-error:
- bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
- return (error);
}
-static int
-altera_avgen_nexus_detach(device_t dev)
+void
+altera_avgen_detach(struct altera_avgen_softc *sc)
{
- struct altera_avgen_softc *sc;
- sc = device_get_softc(dev);
destroy_dev(sc->avg_cdev);
- bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
- return (0);
}
-
-static device_method_t altera_avgen_nexus_methods[] = {
- DEVMETHOD(device_probe, altera_avgen_nexus_probe),
- DEVMETHOD(device_attach, altera_avgen_nexus_attach),
- DEVMETHOD(device_detach, altera_avgen_nexus_detach),
- { 0, 0 }
-};
-
-static driver_t altera_avgen_nexus_driver = {
- "altera_avgen",
- altera_avgen_nexus_methods,
- sizeof(struct altera_avgen_softc),
-};
-
-static devclass_t altera_avgen_devclass;
-
-DRIVER_MODULE(avgen, nexus, altera_avgen_nexus_driver, altera_avgen_devclass,
- 0, 0);
diff --git a/sys/dev/altera/avgen/altera_avgen.h b/sys/dev/altera/avgen/altera_avgen.h
index c8c7947..fb25a3c 100644
--- a/sys/dev/altera/avgen/altera_avgen.h
+++ b/sys/dev/altera/avgen/altera_avgen.h
@@ -77,7 +77,11 @@ struct altera_avgen_softc {
/*
* Driver setup routines from the bus attachment/teardown.
*/
-int altera_avgen_attach(struct altera_avgen_softc *sc);
+int altera_avgen_attach(struct altera_avgen_softc *sc,
+ const char *str_fileio, const char *str_mmapio,
+ const char *str_devname, int devunit);
void altera_avgen_detach(struct altera_avgen_softc *sc);
+extern devclass_t altera_avgen_devclass;
+
#endif /* _DEV_ALTERA_AVALON_H_ */
diff --git a/sys/dev/altera/avgen/altera_avgen_fdt.c b/sys/dev/altera/avgen/altera_avgen_fdt.c
new file mode 100644
index 0000000..2762ff4
--- /dev/null
+++ b/sys/dev/altera/avgen/altera_avgen_fdt.c
@@ -0,0 +1,154 @@
+/*-
+ * Copyright (c) 2012-2013 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/stat.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/vm.h>
+
+#include <vm/vm.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/altera/avgen/altera_avgen.h>
+
+static int
+altera_avgen_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "sri-cambridge,avgen")) {
+ device_set_desc(dev, "Generic Altera Avalon device attachment");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+altera_avgen_fdt_attach(device_t dev)
+{
+ struct altera_avgen_softc *sc;
+ char *str_fileio, *str_mmapio;
+ char *str_devname;
+ phandle_t node;
+ pcell_t cell;
+ int devunit, error;
+
+ sc = device_get_softc(dev);
+ sc->avg_dev = dev;
+ sc->avg_unit = device_get_unit(dev);
+
+ /*
+ * Query driver-specific OpenFirmware properties to determine how to
+ * expose the device via /dev.
+ */
+ str_fileio = NULL;
+ str_mmapio = NULL;
+ str_devname = NULL;
+ devunit = -1;
+ sc->avg_width = 1;
+ node = ofw_bus_get_node(dev);
+ if (OF_getprop(node, "sri-cambridge,width", &cell, sizeof(cell)) > 0)
+ sc->avg_width = cell;
+ (void)OF_getprop_alloc(node, "sri-cambridge,fileio", sizeof(char),
+ (void **)&str_fileio);
+ (void)OF_getprop_alloc(node, "sri-cambridge,mmapio", sizeof(char),
+ (void **)&str_mmapio);
+ (void)OF_getprop_alloc(node, "sri-cambridge,devname", sizeof(char),
+ (void **)&str_devname);
+ if (OF_getprop(node, "sri-cambridge,devunit", &cell, sizeof(cell)) > 0)
+ devunit = cell;
+
+ /* Memory allocation and checking. */
+ sc->avg_rid = 0;
+ sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->avg_rid, RF_ACTIVE);
+ if (sc->avg_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ return (ENXIO);
+ }
+ error = altera_avgen_attach(sc, str_fileio, str_mmapio, str_devname,
+ devunit);
+ if (error != 0)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid,
+ sc->avg_res);
+ if (str_fileio != NULL)
+ free(str_fileio, M_OFWPROP);
+ if (str_mmapio != NULL)
+ free(str_mmapio, M_OFWPROP);
+ if (str_devname != NULL)
+ free(str_devname, M_OFWPROP);
+ return (error);
+}
+
+static int
+altera_avgen_fdt_detach(device_t dev)
+{
+ struct altera_avgen_softc *sc;
+
+ sc = device_get_softc(dev);
+ altera_avgen_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
+ return (0);
+}
+
+static device_method_t altera_avgen_fdt_methods[] = {
+ DEVMETHOD(device_probe, altera_avgen_fdt_probe),
+ DEVMETHOD(device_attach, altera_avgen_fdt_attach),
+ DEVMETHOD(device_detach, altera_avgen_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t altera_avgen_fdt_driver = {
+ "altera_avgen",
+ altera_avgen_fdt_methods,
+ sizeof(struct altera_avgen_softc),
+};
+
+DRIVER_MODULE(avgen, simplebus, altera_avgen_fdt_driver,
+ altera_avgen_devclass, 0, 0);
diff --git a/sys/dev/altera/avgen/altera_avgen_nexus.c b/sys/dev/altera/avgen/altera_avgen_nexus.c
new file mode 100644
index 0000000..d0e4f9b
--- /dev/null
+++ b/sys/dev/altera/avgen/altera_avgen_nexus.c
@@ -0,0 +1,141 @@
+/*-
+ * Copyright (c) 2012-2013 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/stat.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/vm.h>
+
+#include <vm/vm.h>
+
+#include <dev/altera/avgen/altera_avgen.h>
+
+static int
+altera_avgen_nexus_probe(device_t dev)
+{
+
+ device_set_desc(dev, "Generic Altera Avalon device attachment");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+altera_avgen_nexus_attach(device_t dev)
+{
+ struct altera_avgen_softc *sc;
+ const char *str_fileio, *str_mmapio;
+ const char *str_devname;
+ int devunit, error;
+
+ sc = device_get_softc(dev);
+ sc->avg_dev = dev;
+ sc->avg_unit = device_get_unit(dev);
+
+ /*
+ * Query non-standard hints to find out what operations are permitted
+ * on the device, and whether it is cached.
+ */
+ str_fileio = NULL;
+ str_mmapio = NULL;
+ str_devname = NULL;
+ devunit = -1;
+ sc->avg_width = 1;
+ error = resource_int_value(device_get_name(dev), device_get_unit(dev),
+ ALTERA_AVALON_STR_WIDTH, &sc->avg_width);
+ if (error != 0 && error != ENOENT) {
+ device_printf(dev, "invalid %s\n", ALTERA_AVALON_STR_WIDTH);
+ return (error);
+ }
+ (void)resource_string_value(device_get_name(dev),
+ device_get_unit(dev), ALTERA_AVALON_STR_FILEIO, &str_fileio);
+ (void)resource_string_value(device_get_name(dev),
+ device_get_unit(dev), ALTERA_AVALON_STR_MMAPIO, &str_mmapio);
+ (void)resource_string_value(device_get_name(dev),
+ device_get_unit(dev), ALTERA_AVALON_STR_DEVNAME, &str_devname);
+ (void)resource_int_value(device_get_name(dev), device_get_unit(dev),
+ ALTERA_AVALON_STR_DEVUNIT, &devunit);
+
+ /* Memory allocation and checking. */
+ sc->avg_rid = 0;
+ sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->avg_rid, RF_ACTIVE);
+ if (sc->avg_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ return (ENXIO);
+ }
+ error = altera_avgen_attach(sc, str_fileio, str_mmapio, str_devname,
+ devunit);
+ if (error != 0)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid,
+ sc->avg_res);
+ return (error);
+}
+
+static int
+altera_avgen_nexus_detach(device_t dev)
+{
+ struct altera_avgen_softc *sc;
+
+ sc = device_get_softc(dev);
+ altera_avgen_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
+ return (0);
+}
+
+static device_method_t altera_avgen_nexus_methods[] = {
+ DEVMETHOD(device_probe, altera_avgen_nexus_probe),
+ DEVMETHOD(device_attach, altera_avgen_nexus_attach),
+ DEVMETHOD(device_detach, altera_avgen_nexus_detach),
+ { 0, 0 }
+};
+
+static driver_t altera_avgen_nexus_driver = {
+ "altera_avgen",
+ altera_avgen_nexus_methods,
+ sizeof(struct altera_avgen_softc),
+};
+
+DRIVER_MODULE(avgen, nexus, altera_avgen_nexus_driver, altera_avgen_devclass,
+ 0, 0);
diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart.h b/sys/dev/altera/jtag_uart/altera_jtag_uart.h
index 1ff3bcb..5b5b29f 100644
--- a/sys/dev/altera/jtag_uart/altera_jtag_uart.h
+++ b/sys/dev/altera/jtag_uart/altera_jtag_uart.h
@@ -194,4 +194,6 @@ extern u_int aju_cons_jtag_missed;
int altera_jtag_uart_attach(struct altera_jtag_uart_softc *sc);
void altera_jtag_uart_detach(struct altera_jtag_uart_softc *sc);
+extern devclass_t altera_jtag_uart_devclass;
+
#endif /* _DEV_ALTERA_JTAG_UART_H_ */
diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c
index 679ebe2..ae84597 100644
--- a/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c
+++ b/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c
@@ -32,6 +32,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/endian.h>
#include <sys/kdb.h>
@@ -46,6 +47,8 @@ __FBSDID("$FreeBSD$");
#include <dev/altera/jtag_uart/altera_jtag_uart.h>
+devclass_t altera_jtag_uart_devclass;
+
/*
* One-byte buffer as we can't check whether the UART is readable without
* actually reading from it, synchronised by a spinlock; this lock also
diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c
new file mode 100644
index 0000000..47f39a4
--- /dev/null
+++ b/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c
@@ -0,0 +1,147 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/jtag_uart/altera_jtag_uart.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/*
+ * FDT bus attachment for Altera JTAG UARTs.
+ */
+static int
+altera_jtag_uart_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "altera,jtag_uart-11_0")) {
+ device_set_desc(dev, "Altera JTAG UART");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+altera_jtag_uart_fdt_attach(device_t dev)
+{
+ struct altera_jtag_uart_softc *sc;
+ int error;
+
+ error = 0;
+ sc = device_get_softc(dev);
+ sc->ajus_dev = dev;
+ sc->ajus_unit = device_get_unit(dev);
+ sc->ajus_mem_rid = 0;
+ sc->ajus_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->ajus_mem_rid, RF_ACTIVE);
+ if (sc->ajus_mem_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ error = ENXIO;
+ goto out;
+ }
+
+ /*
+ * Interrupt support is optional -- if we can't allocate an IRQ, then
+ * we fall back on polling.
+ */
+ sc->ajus_irq_rid = 0;
+ sc->ajus_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &sc->ajus_irq_rid, RF_ACTIVE | RF_SHAREABLE);
+ if (sc->ajus_irq_res == NULL)
+ device_printf(dev,
+ "IRQ unavailable; selecting polled operation\n");
+ error = altera_jtag_uart_attach(sc);
+out:
+ if (error) {
+ if (sc->ajus_irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ sc->ajus_irq_rid, sc->ajus_irq_res);
+ if (sc->ajus_mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ sc->ajus_mem_rid, sc->ajus_mem_res);
+ }
+ return (error);
+}
+
+static int
+altera_jtag_uart_fdt_detach(device_t dev)
+{
+ struct altera_jtag_uart_softc *sc;
+
+ sc = device_get_softc(dev);
+ KASSERT(sc->ajus_mem_res != NULL, ("%s: resources not allocated",
+ __func__));
+
+ altera_jtag_uart_detach(sc);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->ajus_irq_rid,
+ sc->ajus_irq_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->ajus_mem_rid,
+ sc->ajus_mem_res);
+ return (0);
+}
+
+static device_method_t altera_jtag_uart_fdt_methods[] = {
+ DEVMETHOD(device_probe, altera_jtag_uart_fdt_probe),
+ DEVMETHOD(device_attach, altera_jtag_uart_fdt_attach),
+ DEVMETHOD(device_detach, altera_jtag_uart_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t altera_jtag_uart_fdt_driver = {
+ "altera_jtag_uart",
+ altera_jtag_uart_fdt_methods,
+ sizeof(struct altera_jtag_uart_softc),
+};
+
+DRIVER_MODULE(altera_jtag_uart, simplebus, altera_jtag_uart_fdt_driver,
+ altera_jtag_uart_devclass, 0, 0);
diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c
index 2592249..2fe772a 100644
--- a/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c
+++ b/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c
@@ -137,7 +137,5 @@ static driver_t altera_jtag_uart_nexus_driver = {
sizeof(struct altera_jtag_uart_softc),
};
-static devclass_t altera_jtag_uart_devclass;
-
DRIVER_MODULE(altera_jtag_uart, nexus, altera_jtag_uart_nexus_driver,
altera_jtag_uart_devclass, 0, 0);
diff --git a/sys/dev/altera/sdcard/altera_sdcard.c b/sys/dev/altera/sdcard/altera_sdcard.c
index 4572206..f64b9c5 100644
--- a/sys/dev/altera/sdcard/altera_sdcard.c
+++ b/sys/dev/altera/sdcard/altera_sdcard.c
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
* 3. Handle read-only SD Cards.
* 4. Tune timeouts based on real-world SD Card speeds.
*/
+devclass_t altera_sdcard_devclass;
void
altera_sdcard_attach(struct altera_sdcard_softc *sc)
diff --git a/sys/dev/altera/sdcard/altera_sdcard.h b/sys/dev/altera/sdcard/altera_sdcard.h
index 4a491c4..96019b2 100644
--- a/sys/dev/altera/sdcard/altera_sdcard.h
+++ b/sys/dev/altera/sdcard/altera_sdcard.h
@@ -138,7 +138,7 @@ void altera_sdcard_io_start(struct altera_sdcard_softc *sc,
* data. Software ease of use was not a design consideration.
*/
#define ALTERA_SDCARD_CSD_C_SIZE_BYTE0 7
-#define ALTERA_SDCARD_CSD_C_SIZE_MASK0 0xc /* top 2 bits */
+#define ALTERA_SDCARD_CSD_C_SIZE_MASK0 0xc0 /* top 2 bits */
#define ALTERA_SDCARD_CSD_C_SIZE_RSHIFT0 6
#define ALTERA_SDCARD_CSD_C_SIZE_BYTE1 8
@@ -244,4 +244,6 @@ void altera_sdcard_start(struct altera_sdcard_softc *sc);
void altera_sdcard_disk_insert(struct altera_sdcard_softc *sc);
void altera_sdcard_disk_remove(struct altera_sdcard_softc *sc);
+extern devclass_t altera_sdcard_devclass;
+
#endif /* _DEV_ALTERA_SDCARD_H_ */
diff --git a/sys/dev/altera/sdcard/altera_sdcard_fdt.c b/sys/dev/altera/sdcard/altera_sdcard_fdt.c
new file mode 100644
index 0000000..027ca2d
--- /dev/null
+++ b/sys/dev/altera/sdcard/altera_sdcard_fdt.c
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/sdcard/altera_sdcard.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/*
+ * FDT bus attachment for the Altera SD Card IP core.
+ */
+static int
+altera_sdcard_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "altera,sdcard_11_2011")) {
+ device_set_desc(dev, "Altera Secure Data Card IP Core");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+altera_sdcard_fdt_attach(device_t dev)
+{
+ struct altera_sdcard_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->as_dev = dev;
+ sc->as_unit = device_get_unit(dev);
+ sc->as_rid = 0;
+ sc->as_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->as_rid, RF_ACTIVE);
+ if (sc->as_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ return (ENXIO);
+ }
+ altera_sdcard_attach(sc);
+ return (0);
+}
+
+static int
+altera_sdcard_fdt_detach(device_t dev)
+{
+ struct altera_sdcard_softc *sc;
+
+ sc = device_get_softc(dev);
+ KASSERT(sc->as_res != NULL, ("%s: resources not allocated",
+ __func__));
+ altera_sdcard_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->as_rid, sc->as_res);
+ return (0);
+}
+
+static device_method_t altera_sdcard_fdt_methods[] = {
+ DEVMETHOD(device_probe, altera_sdcard_fdt_probe),
+ DEVMETHOD(device_attach, altera_sdcard_fdt_attach),
+ DEVMETHOD(device_detach, altera_sdcard_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t altera_sdcard_fdt_driver = {
+ "altera_sdcardc",
+ altera_sdcard_fdt_methods,
+ sizeof(struct altera_sdcard_softc),
+};
+
+DRIVER_MODULE(altera_sdcard, simplebus, altera_sdcard_fdt_driver,
+ altera_sdcard_devclass, 0, 0);
diff --git a/sys/dev/altera/sdcard/altera_sdcard_io.c b/sys/dev/altera/sdcard/altera_sdcard_io.c
index adbd5d1..b256c0b 100644
--- a/sys/dev/altera/sdcard/altera_sdcard_io.c
+++ b/sys/dev/altera/sdcard/altera_sdcard_io.c
@@ -93,13 +93,6 @@ altera_sdcard_process_csd0(struct altera_sdcard_softc *sc)
read_bl_len = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_READ_BL_LEN_BYTE];
read_bl_len &= ALTERA_SDCARD_CSD_READ_BL_LEN_MASK;
- byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE0];
- byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK0;
- byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE1];
- byte1 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK1;
- c_size_mult = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_MULT_RSHIFT0) |
- (byte0 << ALTERA_SDCARD_CSD_C_SIZE_MULT_LSHIFT1);
-
byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE0];
byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MASK0;
byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE1];
diff --git a/sys/dev/altera/sdcard/altera_sdcard_nexus.c b/sys/dev/altera/sdcard/altera_sdcard_nexus.c
index e0fddcb..88abe1f 100644
--- a/sys/dev/altera/sdcard/altera_sdcard_nexus.c
+++ b/sys/dev/altera/sdcard/altera_sdcard_nexus.c
@@ -110,7 +110,5 @@ static driver_t altera_sdcard_nexus_driver = {
sizeof(struct altera_sdcard_softc),
};
-static devclass_t altera_sdcard_devclass;
-
DRIVER_MODULE(altera_sdcard, nexus, altera_sdcard_nexus_driver,
altera_sdcard_devclass, 0, 0);
diff --git a/sys/dev/amdsbwd/amdsbwd.c b/sys/dev/amdsbwd/amdsbwd.c
index 4256381..4726416 100644
--- a/sys/dev/amdsbwd/amdsbwd.c
+++ b/sys/dev/amdsbwd/amdsbwd.c
@@ -139,7 +139,7 @@ static device_method_t amdsbwd_methods[] = {
#if 0
DEVMETHOD(device_shutdown, amdsbwd_detach),
#endif
- {0, 0}
+ DEVMETHOD_END
};
static devclass_t amdsbwd_devclass;
diff --git a/sys/dev/amdtemp/amdtemp.c b/sys/dev/amdtemp/amdtemp.c
index 6d106ae..c55e680 100644
--- a/sys/dev/amdtemp/amdtemp.c
+++ b/sys/dev/amdtemp/amdtemp.c
@@ -134,7 +134,7 @@ static device_method_t amdtemp_methods[] = {
DEVMETHOD(device_attach, amdtemp_attach),
DEVMETHOD(device_detach, amdtemp_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t amdtemp_driver = {
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 3a6710c..28c93f9 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -698,6 +698,8 @@ MALLOC_DECLARE(M_ATA);
#define ATA_INW(res, offset) \
bus_read_2((res), (offset))
+#define ATA_INW_STRM(res, offset) \
+ bus_read_stream_2((res), (offset))
#define ATA_INL(res, offset) \
bus_read_4((res), (offset))
#define ATA_INSW(res, offset, addr, count) \
@@ -712,6 +714,8 @@ MALLOC_DECLARE(M_ATA);
bus_write_1((res), (offset), (value))
#define ATA_OUTW(res, offset, value) \
bus_write_2((res), (offset), (value))
+#define ATA_OUTW_STRM(res, offset, value) \
+ bus_write_stream_2((res), (offset), (value))
#define ATA_OUTL(res, offset, value) \
bus_write_4((res), (offset), (value))
#define ATA_OUTSW(res, offset, addr, count) \
@@ -729,6 +733,9 @@ MALLOC_DECLARE(M_ATA);
#define ATA_IDX_INW(ch, idx) \
ATA_INW(ch->r_io[idx].res, ch->r_io[idx].offset)
+#define ATA_IDX_INW_STRM(ch, idx) \
+ ATA_INW_STRM(ch->r_io[idx].res, ch->r_io[idx].offset)
+
#define ATA_IDX_INL(ch, idx) \
ATA_INL(ch->r_io[idx].res, ch->r_io[idx].offset)
@@ -750,6 +757,9 @@ MALLOC_DECLARE(M_ATA);
#define ATA_IDX_OUTW(ch, idx, value) \
ATA_OUTW(ch->r_io[idx].res, ch->r_io[idx].offset, value)
+#define ATA_IDX_OUTW_STRM(ch, idx, value) \
+ ATA_OUTW_STRM(ch->r_io[idx].res, ch->r_io[idx].offset, value)
+
#define ATA_IDX_OUTL(ch, idx, value) \
ATA_OUTL(ch->r_io[idx].res, ch->r_io[idx].offset, value)
diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c
index de30603..6f83db7 100644
--- a/sys/dev/ata/ata-lowlevel.c
+++ b/sys/dev/ata/ata-lowlevel.c
@@ -846,14 +846,28 @@ ata_pio_read(struct ata_request *request, int length)
uint8_t *addr;
int size = min(request->transfersize, length);
int resid;
- uint8_t buf[2];
+ uint8_t buf[2] __aligned(sizeof(int16_t));
+#ifndef __NO_STRICT_ALIGNMENT
+ int i;
+#endif
addr = (uint8_t *)request->data + request->donecount;
- if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)) ||
- ((uintptr_t)addr % sizeof(int32_t))) {
- ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int16_t));
+ if (__predict_false(ch->flags & ATA_USE_16BIT ||
+ (size % sizeof(int32_t)) || ((uintptr_t)addr % sizeof(int32_t)))) {
+#ifndef __NO_STRICT_ALIGNMENT
+ if (__predict_false((uintptr_t)addr % sizeof(int16_t))) {
+ for (i = 0, resid = size & ~1; resid > 0; resid -=
+ sizeof(int16_t)) {
+ *(uint16_t *)&buf = ATA_IDX_INW_STRM(ch, ATA_DATA);
+ addr[i++] = buf[0];
+ addr[i++] = buf[1];
+ }
+ } else
+#endif
+ ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)addr, size /
+ sizeof(int16_t));
if (size & 1) {
- ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)buf, 1);
+ *(uint16_t *)&buf = ATA_IDX_INW_STRM(ch, ATA_DATA);
(addr + (size & ~1))[0] = buf[0];
}
} else
@@ -875,15 +889,30 @@ ata_pio_write(struct ata_request *request, int length)
uint8_t *addr;
int size = min(request->transfersize, length);
int resid;
- uint8_t buf[2];
+ uint8_t buf[2] __aligned(sizeof(int16_t));
+#ifndef __NO_STRICT_ALIGNMENT
+ int i;
+#endif
+ size = min(request->transfersize, length);
addr = (uint8_t *)request->data + request->donecount;
- if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)) ||
- ((uintptr_t)addr % sizeof(int32_t))) {
- ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int16_t));
+ if (__predict_false(ch->flags & ATA_USE_16BIT ||
+ (size % sizeof(int32_t)) || ((uintptr_t)addr % sizeof(int32_t)))) {
+#ifndef __NO_STRICT_ALIGNMENT
+ if (__predict_false((uintptr_t)addr % sizeof(int16_t))) {
+ for (i = 0, resid = size & ~1; resid > 0; resid -=
+ sizeof(int16_t)) {
+ buf[0] = addr[i++];
+ buf[1] = addr[i++];
+ ATA_IDX_OUTW_STRM(ch, ATA_DATA, *(uint16_t *)&buf);
+ }
+ } else
+#endif
+ ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)addr, size /
+ sizeof(int16_t));
if (size & 1) {
buf[0] = (addr + (size & ~1))[0];
- ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)buf, 1);
+ ATA_IDX_OUTW_STRM(ch, ATA_DATA, *(uint16_t *)&buf);
}
} else
ATA_IDX_OUTSL_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int32_t));
diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c
index c96e252..5b0595c 100644
--- a/sys/dev/ata/ata-raid.c
+++ b/sys/dev/ata/ata-raid.c
@@ -1351,10 +1351,11 @@ static int
ata_raid_read_metadata(device_t subdisk)
{
devclass_t pci_devclass = devclass_find("pci");
+ devclass_t atapci_devclass = devclass_find("atapci");
devclass_t devclass=device_get_devclass(GRANDPARENT(GRANDPARENT(subdisk)));
/* prioritize vendor native metadata layout if possible */
- if (devclass == pci_devclass) {
+ if (devclass == pci_devclass || devclass == atapci_devclass) {
switch (pci_get_vendor(GRANDPARENT(device_get_parent(subdisk)))) {
case ATA_HIGHPOINT_ID:
if (ata_raid_hptv3_read_meta(subdisk, ata_raid_arrays))
diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h
index 19beffe..ddc4b6a 100644
--- a/sys/dev/ath/ath_hal/ah.h
+++ b/sys/dev/ath/ath_hal/ah.h
@@ -941,6 +941,8 @@ typedef struct {
int8_t ss_nf_cal[AH_MAX_CHAINS*2]; /* nf calibrated values for ctl+ext from eeprom */
int8_t ss_nf_pwr[AH_MAX_CHAINS*2]; /* nf pwr values for ctl+ext from eeprom */
int32_t ss_nf_temp_data; /* temperature data taken during nf scan */
+ int ss_enabled;
+ int ss_active;
} HAL_SPECTRAL_PARAM;
#define HAL_SPECTRAL_PARAM_NOVAL 0xFFFF
#define HAL_SPECTRAL_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */
diff --git a/sys/dev/ath/ath_hal/ar5211/boss.ini b/sys/dev/ath/ath_hal/ar5211/boss.ini
index e054436..e054436 100755..100644
--- a/sys/dev/ath/ath_hal/ar5211/boss.ini
+++ b/sys/dev/ath/ath_hal/ar5211/boss.ini
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index bd2580f..41019fb 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -152,7 +152,6 @@ static void ath_init(void *);
static void ath_stop_locked(struct ifnet *);
static void ath_stop(struct ifnet *);
static int ath_reset_vap(struct ieee80211vap *, u_long);
-static void ath_start_queue(struct ifnet *ifp);
static int ath_media_change(struct ifnet *);
static void ath_watchdog(void *);
static int ath_ioctl(struct ifnet *, u_long, caddr_t);
@@ -213,6 +212,14 @@ static void ath_dfs_tasklet(void *, int);
static void ath_node_powersave(struct ieee80211_node *, int);
static int ath_node_set_tim(struct ieee80211_node *, int);
+static int ath_transmit(struct ifnet *ifp, struct mbuf *m);
+static void ath_qflush(struct ifnet *ifp);
+
+static void ath_txq_qinit(struct ifnet *ifp);
+static void ath_txq_qflush(struct ifnet *ifp);
+static int ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0);
+static void ath_txq_qrun(struct ifnet *ifp);
+
#ifdef IEEE80211_SUPPORT_TDMA
#include <dev/ath/if_ath_tdma.h>
#endif
@@ -429,12 +436,30 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
"%s taskq", ifp->if_xname);
+ /*
+ * This taskqueue doesn't get any higher priority
+ * than the ath(4) taskqueue (PI_NET) so TX won't
+ * pre-empt RX and other task priorities.
+ *
+ * This may not be optimal - the previous behaviour
+ * was to direct-dispatch frames via the sending
+ * task context, rather than (always) software
+ * queuing.
+ */
+ sc->sc_tx_tq = taskqueue_create("ath_tx_taskq", M_NOWAIT,
+ taskqueue_thread_enqueue, &sc->sc_tx_tq);
+ taskqueue_start_threads(&sc->sc_tx_tq, 1, PI_NET,
+ "%s TX taskq", ifp->if_xname);
+
TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc);
TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc);
TASK_INIT(&sc->sc_bstucktask,0, ath_bstuck_proc, sc);
TASK_INIT(&sc->sc_resettask,0, ath_reset_proc, sc);
- TASK_INIT(&sc->sc_txqtask,0, ath_txq_sched_tasklet, sc);
- TASK_INIT(&sc->sc_fataltask,0, ath_fatal_proc, sc);
+ TASK_INIT(&sc->sc_txqtask, 0, ath_txq_sched_tasklet, sc);
+ TASK_INIT(&sc->sc_fataltask, 0, ath_fatal_proc, sc);
+
+ /* XXX make this a higher priority taskqueue? */
+ TASK_INIT(&sc->sc_txpkttask, 0, ath_start_task, sc);
/*
* Allocate hardware transmit queues: one queue for
@@ -554,13 +579,18 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
ifp->if_softc = sc;
ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
- ifp->if_start = ath_start_queue;
+ /* XXX net80211 uses if_start to re-start ifnet processing */
+ ifp->if_start = ath_start;
+ ifp->if_transmit = ath_transmit;
+ ifp->if_qflush = ath_qflush;
ifp->if_ioctl = ath_ioctl;
ifp->if_init = ath_init;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
+ ath_txq_qinit(ifp);
+
ic->ic_ifp = ifp;
/* XXX not right but it's not used anywhere important */
ic->ic_phytype = IEEE80211_T_OFDM;
@@ -966,16 +996,16 @@ ath_detach(struct ath_softc *sc)
ath_stop(ifp);
ieee80211_ifdetach(ifp->if_l2com);
taskqueue_free(sc->sc_tq);
+ taskqueue_free(sc->sc_tx_tq);
#ifdef ATH_TX99_DIAG
if (sc->sc_tx99 != NULL)
sc->sc_tx99->detach(sc->sc_tx99);
#endif
ath_rate_detach(sc->sc_rc);
-
#ifdef ATH_DEBUG_ALQ
if_ath_alq_tidyup(&sc->sc_alq);
#endif
-
+ ath_txq_qflush(ifp);
ath_spectral_detach(sc);
ath_dfs_detach(sc);
ath_desc_free(sc);
@@ -1863,11 +1893,19 @@ ath_bmiss_proc(void *arg, int pending)
DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending);
+ /*
+ * Do a reset upon any becaon miss event.
+ *
+ * It may be a non-recognised RX clear hang which needs a reset
+ * to clear.
+ */
if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) {
+ ath_reset(ifp, ATH_RESET_NOLOSS);
if_printf(ifp, "bb hang detected (0x%x), resetting\n", hangs);
+ } else {
ath_reset(ifp, ATH_RESET_NOLOSS);
- } else
ieee80211_beacon_miss(ifp->if_l2com);
+ }
}
/*
@@ -2107,6 +2145,7 @@ ath_txrx_start(struct ath_softc *sc)
{
taskqueue_unblock(sc->sc_tq);
+ taskqueue_unblock(sc->sc_tx_tq);
}
/*
@@ -2207,6 +2246,7 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
/* Try to (stop any further TX/RX from occuring */
taskqueue_block(sc->sc_tq);
+ taskqueue_block(sc->sc_tx_tq);
ATH_PCU_LOCK(sc);
ath_hal_intrset(ah, 0); /* disable interrupts */
@@ -2454,6 +2494,14 @@ ath_buf_clone(struct ath_softc *sc, const struct ath_buf *bf)
tbf->bf_flags = bf->bf_flags & ~ATH_BUF_BUSY;
tbf->bf_status = bf->bf_status;
tbf->bf_m = bf->bf_m;
+ /*
+ * XXX Copy the node reference, the caller is responsible
+ * for deleting the node reference before it frees its
+ * buffer.
+ *
+ * XXX It's done like this so we don't call the net80211
+ * code whilst having active TX queue locks held.
+ */
tbf->bf_node = bf->bf_node;
/* will be setup by the chain/setup function */
tbf->bf_lastds = NULL;
@@ -2498,13 +2546,70 @@ ath_getbuf(struct ath_softc *sc, ath_buf_type_t btype)
}
static void
-ath_start_queue(struct ifnet *ifp)
+ath_qflush(struct ifnet *ifp)
{
- struct ath_softc *sc = ifp->if_softc;
- ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: start");
+ /* XXX complete/suspend TX */
+ ath_txq_qflush(ifp);
+
+ /* Unsuspend TX? */
+}
+
+/*
+ * Transmit a frame from net80211.
+ */
+static int
+ath_transmit(struct ifnet *ifp, struct mbuf *m)
+{
+ struct ieee80211_node *ni;
+ struct ath_softc *sc = (struct ath_softc *) ifp->if_softc;
+
+ ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
+
+ if (ath_txq_qadd(ifp, m) < 0) {
+ /*
+ * If queuing fails, the if_transmit() API makes the
+ * callee responsible for freeing the mbuf (rather than
+ * the caller, who just assumes the mbuf has been dealt
+ * with somehow).
+ *
+ * BUT, net80211 will free node references if if_transmit()
+ * fails _on encapsulated buffers_. Since drivers
+ * only get fully encapsulated frames from net80211 (via
+ * raw or otherwise APIs), we must be absolutely careful
+ * to not free the node ref or things will get loopy
+ * down the track.
+ *
+ * For tx fragments, the TX code must free whatever
+ * new references it created, but NOT the original
+ * TX node ref that was passed in.
+ */
+ ath_freetx(m);
+ return (ENOBUFS);
+ }
+
+ /*
+ * Unconditionally kick the taskqueue.
+ *
+ * Now, there's a subtle race condition possible here if we
+ * went down the path of only kicking the taskqueue if it
+ * wasn't running. If we're not absolutely, positively
+ * careful, we could have a small race window between
+ * finishing the taskqueue and clearing the TX flag, which
+ * would be interpreted in _this_ context as "we don't need
+ * to kick the TX taskqueue, as said taskqueue is already
+ * running."
+ *
+ * It's a problem in some of the 1GE/10GE NIC drivers.
+ * So until a _correct_ method for implementing this is
+ * drafted up and written, which avoids (potentially)
+ * large amounts of locking contention per-frame, let's
+ * just do the inefficient "kick taskqueue each time"
+ * method.
+ */
ath_tx_kick(sc);
- ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: finished");
+
+ return (0);
}
void
@@ -2531,9 +2636,7 @@ ath_start_task(void *arg, int npending)
sc->sc_txstart_cnt++;
ATH_PCU_UNLOCK(sc);
- ATH_TX_LOCK(sc);
- ath_start(sc->sc_ifp);
- ATH_TX_UNLOCK(sc);
+ ath_txq_qrun(ifp);
ATH_PCU_LOCK(sc);
sc->sc_txstart_cnt--;
@@ -2541,91 +2644,298 @@ ath_start_task(void *arg, int npending)
ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_task: finished");
}
-void
-ath_start(struct ifnet *ifp)
+/*
+ * Pending TX buffer chain management routines.
+ */
+
+
+/*
+ * Initialise the TX queue!
+ */
+static void
+ath_txq_qinit(struct ifnet *ifp)
+{
+ struct ath_softc *sc = ifp->if_softc;
+
+ TAILQ_INIT(&sc->sc_txbuf_list);
+}
+
+/*
+ * Add this mbuf to the TX buffer chain.
+ *
+ * This allocates an ath_buf, links the mbuf into it, and
+ * appends it to the end of the TX buffer chain.
+ * It doesn't fill out the ath_buf in any way besides
+ * that.
+ *
+ * Since the mbuf may be a list of mbufs representing
+ * 802.11 fragments, handle allocating ath_bufs for each
+ * of the mbuf fragments.
+ *
+ * If we queued it, 0 is returned. Else, < 0 is returned.
+ *
+ * If <0 is returned, the sender is responsible for
+ * freeing the mbuf if appropriate.
+ */
+static int
+ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0)
{
struct ath_softc *sc = ifp->if_softc;
- struct ieee80211_node *ni;
struct ath_buf *bf;
- struct mbuf *m, *next;
ath_bufhead frags;
- int npkts = 0;
+ struct ieee80211_node *ni;
+ struct mbuf *m;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
- return;
+ /* XXX recursive TX completion -> TX? */
+ ATH_TX_UNLOCK_ASSERT(sc);
+
+ /*
+ * We grab the node pointer, but we don't deref
+ * the node. The caller must be responsible for
+ * freeing the node reference if it decides to
+ * free the mbuf.
+ */
+ ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
+
+ ATH_TXBUF_LOCK(sc);
+ if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) {
+ /* XXX increment counter? */
+ ATH_TXBUF_UNLOCK(sc);
+ IF_LOCK(&ifp->if_snd);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ IF_UNLOCK(&ifp->if_snd);
+ return (-1);
+ }
+ ATH_TXBUF_UNLOCK(sc);
+
+ /*
+ * Grab a TX buffer and associated resources.
+ */
+ bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL);
+ if (bf == NULL) {
+ device_printf(sc->sc_dev,
+ "%s: couldn't allocate a buffer\n",
+ __func__);
+ return (-1);
+ }
- ATH_TX_LOCK_ASSERT(sc);
+ /* Setup the initial buffer node contents */
+ bf->bf_m = m0;
+ bf->bf_node = ni;
- ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start: called");
+ /*
+ * Check for fragmentation. If this frame
+ * has been broken up verify we have enough
+ * buffers to send all the fragments so all
+ * go out or none...
+ */
+ TAILQ_INIT(&frags);
+ if (m0->m_flags & M_FRAG)
+ DPRINTF(sc, ATH_DEBUG_XMIT, "%s: txfrag\n", __func__);
+ if ((m0->m_flags & M_FRAG) &&
+ !ath_txfrag_setup(sc, &frags, m0, ni)) {
+ DPRINTF(sc, ATH_DEBUG_XMIT,
+ "%s: out of txfrag buffers\n", __func__);
+ sc->sc_stats.ast_tx_nofrag++;
+ ifp->if_oerrors++;
+ goto bad;
+ }
- for (;;) {
+ /*
+ * Don't stuff the non-fragment frame onto the fragment
+ * queue. ath_txfrag_cleanup() should only be called on fragments -
+ * ie, the _extra_ ieee80211_node references - and not the single
+ * node reference already done as part of the net08211 TX call
+ * into the driver.
+ */
+
+ ATH_TX_LOCK(sc);
+
+ /*
+ * Throw the single frame onto the queue.
+ */
+ TAILQ_INSERT_TAIL(&sc->sc_txbuf_list, bf, bf_list);
+
+ /*
+ * Update next packet duration length if it's a fragment.
+ * It's needed for accurate NAV calculations (which for
+ * fragments include the length of the NEXT fragment.)
+ */
+ if (m0->m_nextpkt != NULL)
+ bf->bf_state.bfs_nextpktlen =
+ m0->m_nextpkt->m_pkthdr.len;
+
+ /*
+ * Append the fragments. We have to populate bf and node
+ * references here as although the txfrag setup code does
+ * create buffers and increment the node ref, it doesn't
+ * populate the fields for us.
+ */
+ m = m0->m_nextpkt;
+ while ( (bf = TAILQ_FIRST(&frags)) != NULL) {
+ bf->bf_m = m;
+ bf->bf_node = ni;
+ device_printf(sc->sc_dev, "%s: adding bf=%p, m=%p, ni=%p\n",
+ __func__,
+ bf,
+ bf->bf_m,
+ bf->bf_node);
+ TAILQ_REMOVE(&frags, bf, bf_list);
+ TAILQ_INSERT_TAIL(&sc->sc_txbuf_list, bf, bf_list);
+
+ /*
+ * For duration (NAV) calculations, we need
+ * to know the next fragment size.
+ *
+ * XXX This isn't entirely accurate as it doesn't
+ * take pad bytes and such into account, but it'll do
+ * for fragment length / NAV calculations.
+ */
+ if (m->m_nextpkt != NULL)
+ bf->bf_state.bfs_nextpktlen =
+ m->m_nextpkt->m_pkthdr.len;
+
+ m = m->m_nextpkt;
+ }
+ ATH_TX_UNLOCK(sc);
+
+ return (0);
+bad:
+ device_printf(sc->sc_dev, "%s: bad?!\n", __func__);
+ bf->bf_m = NULL;
+ bf->bf_node = NULL;
+ ATH_TXBUF_LOCK(sc);
+ ath_returnbuf_head(sc, bf);
+ ath_txfrag_cleanup(sc, &frags, ni);
+ ATH_TXBUF_UNLOCK(sc);
+ return (-1);
+}
+
+/*
+ * Flush the pending TX buffer chain.
+ */
+static void
+ath_txq_qflush(struct ifnet *ifp)
+{
+ struct ath_softc *sc = ifp->if_softc;
+ ath_bufhead txlist;
+ struct ath_buf *bf;
+
+ device_printf(sc->sc_dev, "%s: called\n", __func__);
+ TAILQ_INIT(&txlist);
+
+ /* Grab lock */
+ ATH_TX_LOCK(sc);
+
+ /* Copy everything out of sc_txbuf_list into txlist */
+ TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list);
+
+ /* Unlock */
+ ATH_TX_UNLOCK(sc);
+
+ /* Now, walk the list, freeing things */
+ while ((bf = TAILQ_FIRST(&txlist)) != NULL) {
+ TAILQ_REMOVE(&txlist, bf, bf_list);
+
+ if (bf->bf_node)
+ ieee80211_free_node(bf->bf_node);
+
+ m_free(bf->bf_m);
+
+ /* XXX paranoia! */
+ bf->bf_m = NULL;
+ bf->bf_node = NULL;
+
+ /*
+ * XXX Perhaps do a second pass with the TXBUF lock
+ * held and free them all at once?
+ */
ATH_TXBUF_LOCK(sc);
- if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) {
- /* XXX increment counter? */
- ATH_TXBUF_UNLOCK(sc);
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
- break;
- }
+ ath_returnbuf_head(sc, bf);
ATH_TXBUF_UNLOCK(sc);
-
+ }
+}
+
+/*
+ * Walk the TX buffer queue and call ath_tx_start() on each
+ * of them.
+ */
+static void
+ath_txq_qrun(struct ifnet *ifp)
+{
+ struct ath_softc *sc = ifp->if_softc;
+ ath_bufhead txlist;
+ struct ath_buf *bf, *bf_next;
+ struct ieee80211_node *ni;
+ struct mbuf *m;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
+ return;
+
+ TAILQ_INIT(&txlist);
+
+ /*
+ * Grab the frames to transmit from the tx queue
+ */
+
+ /* Copy everything out of sc_txbuf_list into txlist */
+ ATH_TX_LOCK(sc);
+ TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list);
+ ATH_TX_UNLOCK(sc);
+
+ /*
+ * For now, the ath_tx_start() code sits behind the same lock;
+ * worry about serialising this in a taskqueue later.
+ */
+
+ ATH_TX_LOCK(sc);
+
+ /*
+ * Attempt to transmit each frame.
+ *
+ * In the old code path - if a TX fragment fails, subsequent
+ * fragments in that group would be aborted.
+ *
+ * It would be nice to chain together TX fragments in this
+ * way so they can be aborted together.
+ */
+ TAILQ_FOREACH_SAFE(bf, &txlist, bf_list, bf_next) {
/*
- * Grab a TX buffer and associated resources.
+ * Clear, because we're going to reuse this
+ * as a real ath_buf now
*/
- bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL);
- if (bf == NULL)
- break;
+ ni = bf->bf_node;
+ m = bf->bf_m;
+
+ bf->bf_node = NULL;
+ bf->bf_m = NULL;
- IFQ_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL) {
- ATH_TXBUF_LOCK(sc);
- ath_returnbuf_head(sc, bf);
- ATH_TXBUF_UNLOCK(sc);
- break;
- }
- ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- npkts ++;
/*
- * Check for fragmentation. If this frame
- * has been broken up verify we have enough
- * buffers to send all the fragments so all
- * go out or none...
+ * Remove it from the list.
*/
- TAILQ_INIT(&frags);
- if ((m->m_flags & M_FRAG) &&
- !ath_txfrag_setup(sc, &frags, m, ni)) {
- DPRINTF(sc, ATH_DEBUG_XMIT,
- "%s: out of txfrag buffers\n", __func__);
- sc->sc_stats.ast_tx_nofrag++;
- ifp->if_oerrors++;
- ath_freetx(m);
- goto bad;
- }
- ifp->if_opackets++;
- nextfrag:
+ TAILQ_REMOVE(&txlist, bf, bf_list);
+
/*
- * Pass the frame to the h/w for transmission.
- * Fragmented frames have each frag chained together
- * with m_nextpkt. We know there are sufficient ath_buf's
- * to send all the frags because of work done by
- * ath_txfrag_setup. We leave m_nextpkt set while
- * calling ath_tx_start so it can use it to extend the
- * the tx duration to cover the subsequent frag and
- * so it can reclaim all the mbufs in case of an error;
- * ath_tx_start clears m_nextpkt once it commits to
- * handing the frame to the hardware.
+ * If we fail, free this buffer and go to the next one;
+ * ath_tx_start() frees the mbuf but not the node
+ * reference.
*/
- next = m->m_nextpkt;
if (ath_tx_start(sc, ni, bf, m)) {
- bad:
+ /*
+ * XXX m is freed by ath_tx_start(); node reference
+ * is not!
+ */
+ DPRINTF(sc, ATH_DEBUG_XMIT,
+ "%s: failed; bf=%p, ni=%p, m=%p\n",
+ __func__,
+ bf,
+ ni,
+ m);
ifp->if_oerrors++;
- reclaim:
bf->bf_m = NULL;
bf->bf_node = NULL;
ATH_TXBUF_LOCK(sc);
ath_returnbuf_head(sc, bf);
- ath_txfrag_cleanup(sc, &frags, ni);
ATH_TXBUF_UNLOCK(sc);
/*
* XXX todo, free the node outside of
@@ -2633,37 +2943,84 @@ ath_start(struct ifnet *ifp)
*/
if (ni != NULL)
ieee80211_free_node(ni);
- continue;
+ } else {
+ /*
+ * Check here if the node is in power save state.
+ * XXX we should hold a node ref here, and release
+ * it after the TX has completed.
+ */
+ ath_tx_update_tim(sc, ni, 1);
+ ifp->if_opackets++;
}
/*
- * Check here if the node is in power save state.
+ * XXX should check for state change and flip out
+ * if needed.
*/
- ath_tx_update_tim(sc, ni, 1);
+ }
+ ATH_TX_UNLOCK(sc);
- if (next != NULL) {
- /*
- * Beware of state changing between frags.
- * XXX check sta power-save state?
- */
- if (ni->ni_vap->iv_state != IEEE80211_S_RUN) {
- DPRINTF(sc, ATH_DEBUG_XMIT,
- "%s: flush fragmented packet, state %s\n",
- __func__,
- ieee80211_state_name[ni->ni_vap->iv_state]);
- ath_freetx(next);
- goto reclaim;
- }
- m = next;
- bf = TAILQ_FIRST(&frags);
- KASSERT(bf != NULL, ("no buf for txfrag"));
- TAILQ_REMOVE(&frags, bf, bf_list);
- goto nextfrag;
+ /*
+ * If we break out early (eg a state change) we should prepend these
+ * frames onto the TX queue.
+ */
+}
+
+/*
+ * This is now primarily used by the net80211 layer to kick-start
+ * queue processing.
+ */
+void
+ath_start(struct ifnet *ifp)
+{
+ struct mbuf *m;
+ struct ath_softc *sc = ifp->if_softc;
+ struct ieee80211_node *ni;
+ int npkts = 0;
+
+ ATH_TX_UNLOCK_ASSERT(sc);
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
+ return;
+
+ /*
+ * If we're below the free buffer limit, don't dequeue anything.
+ * The original code would not dequeue anything from the queue
+ * if allocating an ath_buf failed.
+ *
+ * For if_transmit, we have to either queue or drop the frame.
+ * So we have to try and queue it _somewhere_.
+ */
+ for (;;) {
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL) {
+ break;
}
- sc->sc_wd_timer = 5;
+ /*
+ * If we do fail here, just break out for now
+ * and wait until we've transmitted something
+ * before we attempt again?
+ */
+ if (ath_txq_qadd(ifp, m) < 0) {
+ DPRINTF(sc, ATH_DEBUG_XMIT,
+ "%s: ath_txq_qadd failed\n",
+ __func__);
+ ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
+ if (ni != NULL)
+ ieee80211_free_node(ni);
+ ath_freetx(m);
+ break;
+ }
+ npkts++;
}
- ATH_KTR(sc, ATH_KTR_TX, 1, "ath_start: finished; npkts=%d", npkts);
+
+ /*
+ * Kick the taskqueue into activity, but only if we
+ * queued something.
+ */
+ if (npkts > 0)
+ ath_tx_kick(sc);
}
static int
@@ -2688,6 +3045,7 @@ ath_key_update_begin(struct ieee80211vap *vap)
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
taskqueue_block(sc->sc_tq);
+ taskqueue_block(sc->sc_tx_tq);
IF_LOCK(&ifp->if_snd); /* NB: doesn't block mgmt frames */
}
@@ -2700,6 +3058,7 @@ ath_key_update_end(struct ieee80211vap *vap)
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
IF_UNLOCK(&ifp->if_snd);
taskqueue_unblock(sc->sc_tq);
+ taskqueue_unblock(sc->sc_tx_tq);
}
static void
@@ -3873,9 +4232,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched)
/* Kick the TXQ scheduler */
if (dosched) {
- ATH_TX_LOCK(sc);
- ath_txq_sched(sc, txq);
- ATH_TX_UNLOCK(sc);
+ taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask);
}
ATH_KTR(sc, ATH_KTR_TXCOMP, 1,
@@ -4373,6 +4730,7 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
/* (Try to) stop TX/RX from occuring */
taskqueue_block(sc->sc_tq);
+ taskqueue_block(sc->sc_tx_tq);
ATH_PCU_LOCK(sc);
ath_hal_intrset(ah, 0); /* Stop new RX/TX completion */
@@ -4719,6 +5077,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
int i, error, stamode;
u_int32_t rfilt;
int csa_run_transition = 0;
+
static const HAL_LED_STATE leds[] = {
HAL_LED_INIT, /* IEEE80211_S_INIT */
HAL_LED_SCAN, /* IEEE80211_S_SCAN */
@@ -4761,6 +5120,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
sc->sc_beacons = 0;
taskqueue_unblock(sc->sc_tq);
+ taskqueue_unblock(sc->sc_tx_tq);
}
ni = ieee80211_ref_node(vap->iv_bss);
@@ -4863,10 +5223,32 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* force a beacon update so we pick up a lack of
* beacons from an AP in CAC and thus force a
* scan.
+ *
+ * And, there's also corner cases here where
+ * after a scan, the AP may have disappeared.
+ * In that case, we may not receive an actual
+ * beacon to update the beacon timer and thus we
+ * won't get notified of the missing beacons.
*/
sc->sc_syncbeacon = 1;
+#if 0
if (csa_run_transition)
+#endif
ath_beacon_config(sc, vap);
+
+ /*
+ * PR: kern/175227
+ *
+ * Reconfigure beacons during reset; as otherwise
+ * we won't get the beacon timers reprogrammed
+ * after a reset and thus we won't pick up a
+ * beacon miss interrupt.
+ *
+ * Hopefully we'll see a beacon before the BMISS
+ * timer fires (too often), leading to a STA
+ * disassociation.
+ */
+ sc->sc_beacons = 1;
break;
case IEEE80211_M_MONITOR:
/*
@@ -4904,6 +5286,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
"%s: calibration disabled\n", __func__);
}
taskqueue_unblock(sc->sc_tq);
+ taskqueue_unblock(sc->sc_tx_tq);
} else if (nstate == IEEE80211_S_INIT) {
/*
* If there are no vaps left in RUN state then
@@ -4917,6 +5300,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
/* disable interrupts */
ath_hal_intrset(ah, sc->sc_imask &~ HAL_INT_GLOBAL);
taskqueue_block(sc->sc_tq);
+ taskqueue_block(sc->sc_tx_tq);
sc->sc_beacons = 0;
}
#ifdef IEEE80211_SUPPORT_TDMA
diff --git a/sys/dev/ath/if_ath_beacon.c b/sys/dev/ath/if_ath_beacon.c
index bb1e393..51467cd 100644
--- a/sys/dev/ath/if_ath_beacon.c
+++ b/sys/dev/ath/if_ath_beacon.c
@@ -705,6 +705,16 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
if (vap == NULL)
vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */
+ /*
+ * Just ensure that we aren't being called when the last
+ * VAP is destroyed.
+ */
+ if (vap == NULL) {
+ device_printf(sc->sc_dev, "%s: called with no VAPs\n",
+ __func__);
+ return;
+ }
+
ni = ieee80211_ref_node(vap->iv_bss);
/* extract tstamp from last beacon and convert to TU */
diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h
index c3b101c..a97f897 100644
--- a/sys/dev/ath/if_ath_misc.h
+++ b/sys/dev/ath/if_ath_misc.h
@@ -124,9 +124,8 @@ static inline void
ath_tx_kick(struct ath_softc *sc)
{
- ATH_TX_LOCK(sc);
- ath_start(sc->sc_ifp);
- ATH_TX_UNLOCK(sc);
+ /* XXX eventually try sc_tx_tq? */
+ taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txpkttask);
}
#endif
diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c
index 5a39d16..c8d9536 100644
--- a/sys/dev/ath/if_ath_rx.c
+++ b/sys/dev/ath/if_ath_rx.c
@@ -431,18 +431,16 @@ ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
#ifdef AH_SUPPORT_AR5416
sc->sc_rx_th.wr_chan_flags &= ~CHAN_HT;
if (rs->rs_status & HAL_RXERR_PHY) {
- struct ieee80211com *ic = ifp->if_l2com;
-
/*
* PHY error - make sure the channel flags
* reflect the actual channel configuration,
* not the received frame.
*/
- if (IEEE80211_IS_CHAN_HT40U(ic->ic_curchan))
+ if (IEEE80211_IS_CHAN_HT40U(sc->sc_curchan))
sc->sc_rx_th.wr_chan_flags |= CHAN_HT40U;
- else if (IEEE80211_IS_CHAN_HT40D(ic->ic_curchan))
+ else if (IEEE80211_IS_CHAN_HT40D(sc->sc_curchan))
sc->sc_rx_th.wr_chan_flags |= CHAN_HT40D;
- else if (IEEE80211_IS_CHAN_HT20(ic->ic_curchan))
+ else if (IEEE80211_IS_CHAN_HT20(sc->sc_curchan))
sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
} else if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) { /* HT rate */
struct ieee80211com *ic = ifp->if_l2com;
@@ -845,6 +843,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
int16_t nf;
u_int64_t tsf;
int npkts = 0;
+ int kickpcu = 0;
/* XXX we must not hold the ATH_LOCK here */
ATH_UNLOCK_ASSERT(sc);
@@ -852,6 +851,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
ATH_PCU_LOCK(sc);
sc->sc_rxproc_cnt++;
+ kickpcu = sc->sc_kickpcu;
ATH_PCU_UNLOCK(sc);
DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: called\n", __func__);
@@ -866,7 +866,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
* latency can jump by quite a bit, causing throughput
* degredation.
*/
- if (npkts >= ATH_RX_MAX)
+ if (!kickpcu && npkts >= ATH_RX_MAX)
break;
bf = TAILQ_FIRST(&sc->sc_rxbuf);
@@ -961,6 +961,9 @@ rx_proc_next:
__func__, npkts);
/* XXX rxslink? */
+#if 0
+ ath_startrecv(sc);
+#else
/*
* XXX can we hold the PCU lock here?
* Are there any net80211 buffer calls involved?
@@ -970,6 +973,7 @@ rx_proc_next:
ath_hal_rxena(ah); /* enable recv descriptors */
ath_mode_init(sc); /* set filters, etc. */
ath_hal_startpcurecv(ah); /* re-enable PCU/DMA engine */
+#endif
ath_hal_intrset(ah, sc->sc_imask);
sc->sc_kickpcu = 0;
diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c
index 5de29af..abb180b 100644
--- a/sys/dev/ath/if_ath_sysctl.c
+++ b/sys/dev/ath/if_ath_sysctl.c
@@ -505,6 +505,33 @@ ath_sysctl_forcebstuck(SYSCTL_HANDLER_ARGS)
return 0;
}
+static int
+ath_sysctl_hangcheck(SYSCTL_HANDLER_ARGS)
+{
+ struct ath_softc *sc = arg1;
+ int val = 0;
+ int error;
+ uint32_t mask = 0xffffffff;
+ uint32_t *sp;
+ uint32_t rsize;
+ struct ath_hal *ah = sc->sc_ah;
+
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error || !req->newptr)
+ return error;
+ if (val == 0)
+ return 0;
+
+ /* Do a hang check */
+ if (!ath_hal_getdiagstate(ah, HAL_DIAG_CHECK_HANGS,
+ &mask, sizeof(mask),
+ (void *) &sp, &rsize))
+ return (0);
+ device_printf(sc->sc_dev, "%s: sp=0x%08x\n", __func__, *sp);
+
+ val = 0;
+ return 0;
+}
#ifdef ATH_DEBUG_ALQ
static int
@@ -661,6 +688,10 @@ ath_sysctlattach(struct ath_softc *sc)
"forcebstuck", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
ath_sysctl_forcebstuck, "I", "");
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "hangcheck", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ ath_sysctl_hangcheck, "I", "");
+
if (ath_hal_hasintmit(ah)) {
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"intmit", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index 263e69c..b3b6079 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -1124,7 +1124,11 @@ ath_tx_calc_duration(struct ath_softc *sc, struct ath_buf *bf)
dur = rt->info[rix].lpAckDuration;
if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) {
dur += dur; /* additional SIFS+ACK */
- KASSERT(bf->bf_m->m_nextpkt != NULL, ("no fragment"));
+ if (bf->bf_state.bfs_nextpktlen == 0) {
+ device_printf(sc->sc_dev,
+ "%s: next txfrag len=0?\n",
+ __func__);
+ }
/*
* Include the size of next fragment so NAV is
* updated properly. The last fragment uses only
@@ -1135,7 +1139,7 @@ ath_tx_calc_duration(struct ath_softc *sc, struct ath_buf *bf)
* first fragment!
*/
dur += ath_hal_computetxtime(ah, rt,
- bf->bf_m->m_nextpkt->m_pkthdr.len,
+ bf->bf_state.bfs_nextpktlen,
rix, shortPreamble);
}
if (isfrag) {
@@ -1393,12 +1397,13 @@ static void
ath_tx_update_clrdmask(struct ath_softc *sc, struct ath_tid *tid,
struct ath_buf *bf)
{
+ struct ath_node *an = ATH_NODE(bf->bf_node);
ATH_TX_LOCK_ASSERT(sc);
- if (tid->clrdmask == 1) {
+ if (an->clrdmask == 1) {
bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
- tid->clrdmask = 0;
+ an->clrdmask = 0;
}
}
@@ -2884,6 +2889,29 @@ ath_tx_swq(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_txq *txq,
}
/*
+ * Only set the clrdmask bit if none of the nodes are currently
+ * filtered.
+ *
+ * XXX TODO: go through all the callers and check to see
+ * which are being called in the context of looping over all
+ * TIDs (eg, if all tids are being paused, resumed, etc.)
+ * That'll avoid O(n^2) complexity here.
+ */
+static void
+ath_tx_set_clrdmask(struct ath_softc *sc, struct ath_node *an)
+{
+ int i;
+
+ ATH_TX_LOCK_ASSERT(sc);
+
+ for (i = 0; i < IEEE80211_TID_SIZE; i++) {
+ if (an->an_tid[i].isfiltered == 1)
+ return;
+ }
+ an->clrdmask = 1;
+}
+
+/*
* Configure the per-TID node state.
*
* This likely belongs in if_ath_node.c but I can't think of anywhere
@@ -2914,12 +2942,12 @@ ath_tx_tid_init(struct ath_softc *sc, struct ath_node *an)
atid->sched = 0;
atid->hwq_depth = 0;
atid->cleanup_inprogress = 0;
- atid->clrdmask = 1; /* Always start by setting this bit */
if (i == IEEE80211_NONQOS_TID)
atid->ac = ATH_NONQOS_TID_AC;
else
atid->ac = TID_TO_WME_AC(i);
}
+ an->clrdmask = 1; /* Always start by setting this bit */
}
/*
@@ -2945,7 +2973,6 @@ ath_tx_tid_pause(struct ath_softc *sc, struct ath_tid *tid)
static void
ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid)
{
-
ATH_TX_LOCK_ASSERT(sc);
tid->paused--;
@@ -2960,7 +2987,7 @@ ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid)
* Override the clrdmask configuration for the next frame
* from this TID, just to get the ball rolling.
*/
- tid->clrdmask = 1;
+ ath_tx_set_clrdmask(sc, tid->an);
if (tid->axq_depth == 0)
return;
@@ -2974,7 +3001,7 @@ ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid)
ath_tx_tid_sched(sc, tid);
/* Punt some frames to the hardware if needed */
//ath_txq_sched(sc, sc->sc_ac2q[tid->ac]);
- taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask);
+ taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask);
}
/*
@@ -3043,7 +3070,8 @@ ath_tx_tid_filt_comp_complete(struct ath_softc *sc, struct ath_tid *tid)
DPRINTF(sc, ATH_DEBUG_SW_TX_FILT, "%s: hwq=0, transition back\n",
__func__);
tid->isfiltered = 0;
- tid->clrdmask = 1;
+ /* XXX ath_tx_tid_resume() also calls ath_tx_set_clrdmask()! */
+ ath_tx_set_clrdmask(sc, tid->an);
/* XXX this is really quite inefficient */
while ((bf = ATH_TID_FILT_LAST(tid, ath_bufhead_s)) != NULL) {
@@ -3299,7 +3327,7 @@ ath_tx_tid_bar_tx(struct ath_softc *sc, struct ath_tid *tid)
* Override the clrdmask configuration for the next frame,
* just to get the ball rolling.
*/
- tid->clrdmask = 1;
+ ath_tx_set_clrdmask(sc, tid->an);
/*
* Calculate new BAW left edge, now that all frames have either
@@ -3480,7 +3508,7 @@ ath_tx_tid_drain(struct ath_softc *sc, struct ath_node *an,
*
* This won't hurt things if the TID is about to be freed.
*/
- tid->clrdmask = 1;
+ ath_tx_set_clrdmask(sc, tid->an);
/*
* Now that it's completed, grab the TID lock and update
diff --git a/sys/dev/ath/if_ath_tx_edma.c b/sys/dev/ath/if_ath_tx_edma.c
index 40a0378..a2eef65 100644
--- a/sys/dev/ath/if_ath_tx_edma.c
+++ b/sys/dev/ath/if_ath_tx_edma.c
@@ -655,7 +655,7 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched)
* the txq task for _one_ TXQ. This should be fixed.
*/
if (dosched)
- taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask);
+ taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txqtask);
}
static void
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 2e170a3..070fe53 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -132,7 +132,6 @@ struct ath_tid {
int bar_wait; /* waiting for BAR */
int bar_tx; /* BAR TXed */
int isfiltered; /* is this node currently filtered */
- int clrdmask; /* has clrdmask been set */
/*
* Is the TID being cleaned up after a transition
@@ -182,6 +181,7 @@ struct ath_node {
struct mtx an_mtx; /* protecting the ath_node state */
uint32_t an_swq_depth; /* how many SWQ packets for this
node */
+ int clrdmask; /* has clrdmask been set */
/* variable-length rate control state follows */
};
#define ATH_NODE(ni) ((struct ath_node *)(ni))
@@ -279,6 +279,8 @@ struct ath_buf {
int32_t bfs_keyix; /* crypto key index */
int32_t bfs_txantenna; /* TX antenna config */
+ uint16_t bfs_nextpktlen; /* length of next frag pkt */
+
/* Make this an 8 bit value? */
enum ieee80211_protmode bfs_protmode;
@@ -494,6 +496,13 @@ struct ath_softc {
struct ath_tx_methods sc_tx;
struct ath_tx_edma_fifo sc_txedma[HAL_NUM_TX_QUEUES];
+ /*
+ * This is (currently) protected by the TX queue lock;
+ * it should migrate to a separate lock later
+ * so as to minimise contention.
+ */
+ ath_bufhead sc_txbuf_list;
+
int sc_rx_statuslen;
int sc_tx_desclen;
int sc_tx_statuslen;
@@ -514,6 +523,7 @@ struct ath_softc {
struct mtx sc_tx_mtx; /* TX access mutex */
char sc_tx_mtx_name[32];
struct taskqueue *sc_tq; /* private task queue */
+ struct taskqueue *sc_tx_tq; /* private TX task queue */
struct ath_hal *sc_ah; /* Atheros HAL */
struct ath_ratectrl *sc_rc; /* tx rate control support */
struct ath_tx99 *sc_tx99; /* tx99 adjunct state */
@@ -660,6 +670,7 @@ struct ath_softc {
struct ath_txq *sc_ac2q[5]; /* WME AC -> h/w q map */
struct task sc_txtask; /* tx int processing */
struct task sc_txqtask; /* tx proc processing */
+ struct task sc_txpkttask; /* tx frame processing */
struct ath_descdma sc_txcompdma; /* TX EDMA completion */
struct mtx sc_txcomplock; /* TX EDMA completion lock */
diff --git a/sys/dev/atkbdc/atkbd.c b/sys/dev/atkbdc/atkbd.c
index e58ffc7..199fcb1 100644
--- a/sys/dev/atkbdc/atkbd.c
+++ b/sys/dev/atkbdc/atkbd.c
@@ -66,7 +66,7 @@ static timeout_t atkbd_timeout;
static void atkbd_shutdown_final(void *v);
int
-atkbd_probe_unit(int unit, int ctlr, int irq, int flags)
+atkbd_probe_unit(device_t dev, int irq, int flags)
{
keyboard_switch_t *sw;
int args[2];
@@ -76,27 +76,29 @@ atkbd_probe_unit(int unit, int ctlr, int irq, int flags)
if (sw == NULL)
return ENXIO;
- args[0] = ctlr;
+ args[0] = device_get_unit(device_get_parent(dev));
args[1] = irq;
- error = (*sw->probe)(unit, args, flags);
+ error = (*sw->probe)(device_get_unit(dev), args, flags);
if (error)
return error;
return 0;
}
int
-atkbd_attach_unit(int unit, keyboard_t **kbd, int ctlr, int irq, int flags)
+atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags)
{
keyboard_switch_t *sw;
int args[2];
int error;
+ int unit;
sw = kbd_get_switch(ATKBD_DRIVER_NAME);
if (sw == NULL)
return ENXIO;
/* reset, initialize and enable the device */
- args[0] = ctlr;
+ unit = device_get_unit(dev);
+ args[0] = device_get_unit(device_get_parent(dev));
args[1] = irq;
*kbd = NULL;
error = (*sw->probe)(unit, args, flags);
@@ -401,7 +403,7 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
bcopy(&key_map, keymap, sizeof(key_map));
bcopy(&accent_map, accmap, sizeof(accent_map));
bcopy(fkey_tab, fkeymap,
- imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
+ imin(fkeymap_size * sizeof(fkeymap[0]), sizeof(fkey_tab)));
kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
kbd->kb_data = (void *)state;
@@ -424,8 +426,8 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
if (KBD_HAS_DEVICE(kbd)
- && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
- && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) {
+ && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
+ && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) {
kbd_unregister(kbd);
error = ENXIO;
goto bad;
@@ -485,8 +487,7 @@ atkbd_intr(keyboard_t *kbd, void *arg)
* The keyboard was not detected before;
* it must have been reconnected!
*/
- init_keyboard(state->kbdc, &kbd->kb_type,
- kbd->kb_config);
+ init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config);
KBD_FOUND_DEVICE(kbd);
atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
get_typematic(kbd);
@@ -645,7 +646,7 @@ next_code:
goto next_code;
}
break;
- case 0xE0: /* 0xE0 prefix */
+ case 0xE0: /* 0xE0 prefix */
state->ks_prefix = 0;
switch (keycode) {
case 0x1C: /* right enter key */
@@ -655,57 +656,57 @@ next_code:
keycode = 0x5A;
break;
case 0x35: /* keypad divide key */
- keycode = 0x5B;
- break;
+ keycode = 0x5B;
+ break;
case 0x37: /* print scrn key */
- keycode = 0x5C;
- break;
+ keycode = 0x5C;
+ break;
case 0x38: /* right alt key (alt gr) */
- keycode = 0x5D;
- break;
+ keycode = 0x5D;
+ break;
case 0x46: /* ctrl-pause/break on AT 101 (see below) */
keycode = 0x68;
- break;
+ break;
case 0x47: /* grey home key */
- keycode = 0x5E;
- break;
+ keycode = 0x5E;
+ break;
case 0x48: /* grey up arrow key */
- keycode = 0x5F;
- break;
+ keycode = 0x5F;
+ break;
case 0x49: /* grey page up key */
- keycode = 0x60;
- break;
+ keycode = 0x60;
+ break;
case 0x4B: /* grey left arrow key */
- keycode = 0x61;
- break;
+ keycode = 0x61;
+ break;
case 0x4D: /* grey right arrow key */
- keycode = 0x62;
- break;
+ keycode = 0x62;
+ break;
case 0x4F: /* grey end key */
- keycode = 0x63;
- break;
+ keycode = 0x63;
+ break;
case 0x50: /* grey down arrow key */
- keycode = 0x64;
- break;
+ keycode = 0x64;
+ break;
case 0x51: /* grey page down key */
- keycode = 0x65;
- break;
+ keycode = 0x65;
+ break;
case 0x52: /* grey insert key */
- keycode = 0x66;
- break;
+ keycode = 0x66;
+ break;
case 0x53: /* grey delete key */
- keycode = 0x67;
- break;
- /* the following 3 are only used on the MS "Natural" keyboard */
+ keycode = 0x67;
+ break;
+ /* the following 3 are only used on the MS "Natural" keyboard */
case 0x5b: /* left Window key */
- keycode = 0x69;
- break;
+ keycode = 0x69;
+ break;
case 0x5c: /* right Window key */
- keycode = 0x6a;
- break;
+ keycode = 0x6a;
+ break;
case 0x5d: /* menu key */
- keycode = 0x6b;
- break;
+ keycode = 0x6b;
+ break;
case 0x5e: /* power key */
keycode = 0x6d;
break;
@@ -716,10 +717,10 @@ next_code:
keycode = 0x6f;
break;
default: /* ignore everything else */
- goto next_code;
+ goto next_code;
}
break;
- case 0xE1: /* 0xE1 prefix */
+ case 0xE1: /* 0xE1 prefix */
/*
* The pause/break key on the 101 keyboard produces:
* E1-1D-45 E1-9D-C5
@@ -728,10 +729,10 @@ next_code:
*/
state->ks_prefix = 0;
if (keycode == 0x1D)
- state->ks_prefix = 0x1D;
+ state->ks_prefix = 0x1D;
goto next_code;
/* NOT REACHED */
- case 0x1D: /* pause / break */
+ case 0x1D: /* pause / break */
state->ks_prefix = 0;
if (keycode != 0x45)
goto next_code;
@@ -743,7 +744,7 @@ next_code:
switch (keycode) {
case 0x37: /* *(numpad)/print screen */
if (state->ks_flags & SHIFTS)
- keycode = 0x5c; /* print screen */
+ keycode = 0x5c; /* print screen */
break;
case 0x45: /* num lock/pause */
if (state->ks_flags & CTLS)
@@ -1177,7 +1178,7 @@ get_kbd_echo(KBDC kbdc)
*/
return ENXIO;
}
-
+
return 0;
}
@@ -1275,7 +1276,7 @@ init_keyboard(KBDC kbdc, int *type, int flags)
}
if (bootverbose)
printf("atkbd: the current kbd controller command byte %04x\n",
- c);
+ c);
#if 0
/* override the keyboard lock switch */
c |= KBD_OVERRIDE_KBD_LOCK;
@@ -1415,52 +1416,49 @@ init_keyboard(KBDC kbdc, int *type, int flags)
static int
write_kbd(KBDC kbdc, int command, int data)
{
- int s;
+ int s;
- /* prevent the timeout routine from polling the keyboard */
- if (!kbdc_lock(kbdc, TRUE))
- return EBUSY;
+ /* prevent the timeout routine from polling the keyboard */
+ if (!kbdc_lock(kbdc, TRUE))
+ return EBUSY;
- /* disable the keyboard and mouse interrupt */
- s = spltty();
+ /* disable the keyboard and mouse interrupt */
+ s = spltty();
#if 0
- c = get_controller_command_byte(kbdc);
- if ((c == -1)
- || !set_controller_command_byte(kbdc,
- kbdc_get_device_mask(kbdc),
- KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
- | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
- /* CONTROLLER ERROR */
- kbdc_lock(kbdc, FALSE);
+ c = get_controller_command_byte(kbdc);
+ if ((c == -1)
+ || !set_controller_command_byte(kbdc,
+ kbdc_get_device_mask(kbdc),
+ KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
+ | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
+ /* CONTROLLER ERROR */
+ kbdc_lock(kbdc, FALSE);
+ splx(s);
+ return EIO;
+ }
+ /*
+ * Now that the keyboard controller is told not to generate
+ * the keyboard and mouse interrupts, call `splx()' to allow
+ * the other tty interrupts. The clock interrupt may also occur,
+ * but the timeout routine (`scrn_timer()') will be blocked
+ * by the lock flag set via `kbdc_lock()'
+ */
splx(s);
- return EIO;
- }
- /*
- * Now that the keyboard controller is told not to generate
- * the keyboard and mouse interrupts, call `splx()' to allow
- * the other tty interrupts. The clock interrupt may also occur,
- * but the timeout routine (`scrn_timer()') will be blocked
- * by the lock flag set via `kbdc_lock()'
- */
- splx(s);
#endif
-
- if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK)
- send_kbd_command(kbdc, KBDC_ENABLE_KBD);
-
+ if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK)
+ send_kbd_command(kbdc, KBDC_ENABLE_KBD);
#if 0
- /* restore the interrupts */
- if (!set_controller_command_byte(kbdc,
- kbdc_get_device_mask(kbdc),
+ /* restore the interrupts */
+ if (!set_controller_command_byte(kbdc, kbdc_get_device_mask(kbdc),
c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
- /* CONTROLLER ERROR */
- }
+ /* CONTROLLER ERROR */
+ }
#else
- splx(s);
+ splx(s);
#endif
- kbdc_lock(kbdc, FALSE);
+ kbdc_lock(kbdc, FALSE);
- return 0;
+ return 0;
}
static int
diff --git a/sys/dev/atkbdc/atkbd_atkbdc.c b/sys/dev/atkbdc/atkbd_atkbdc.c
index 8181820..dd0a9d6 100644
--- a/sys/dev/atkbdc/atkbd_atkbdc.c
+++ b/sys/dev/atkbdc/atkbd_atkbdc.c
@@ -104,9 +104,7 @@ atkbdprobe(device_t dev)
bus_release_resource(dev, SYS_RES_IRQ, rid, res);
/* probe the device */
- return atkbd_probe_unit(device_get_unit(dev),
- device_get_unit(device_get_parent(dev)),
- irq, flags);
+ return atkbd_probe_unit(dev, irq, flags);
}
static int
@@ -124,9 +122,7 @@ atkbdattach(device_t dev)
rid = KBDC_RID_KBD;
irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid);
flags = device_get_flags(dev);
- error = atkbd_attach_unit(device_get_unit(dev), &kbd,
- device_get_unit(device_get_parent(dev)),
- irq, flags);
+ error = atkbd_attach_unit(dev, &kbd, irq, flags);
if (error)
return error;
diff --git a/sys/dev/atkbdc/atkbdreg.h b/sys/dev/atkbdc/atkbdreg.h
index cf7ee6b..3d09e44 100644
--- a/sys/dev/atkbdc/atkbdreg.h
+++ b/sys/dev/atkbdc/atkbdreg.h
@@ -39,9 +39,8 @@
#ifdef _KERNEL
-int atkbd_probe_unit(int unit, int ctlr, int irq, int flags);
-int atkbd_attach_unit(int unit, keyboard_t **kbd,
- int ctlr, int irq, int flags);
+int atkbd_probe_unit(device_t dev, int irq, int flags);
+int atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags);
#endif
diff --git a/sys/dev/auxio/auxio.c b/sys/dev/auxio/auxio.c
index 35fd307..b104d5a 100644
--- a/sys/dev/auxio/auxio.c
+++ b/sys/dev/auxio/auxio.c
@@ -131,7 +131,8 @@ static device_method_t auxio_sbus_methods[] = {
DEVMETHOD(device_probe, auxio_bus_probe),
DEVMETHOD(device_attach, auxio_sbus_attach),
DEVMETHOD(device_detach, auxio_bus_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t auxio_sbus_driver = {
@@ -151,7 +152,8 @@ static device_method_t auxio_ebus_methods[] = {
DEVMETHOD(device_probe, auxio_bus_probe),
DEVMETHOD(device_attach, auxio_ebus_attach),
DEVMETHOD(device_detach, auxio_bus_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t auxio_ebus_driver = {
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index e7cb2f7..db86ec2 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -35,10 +35,10 @@
__FBSDID("$FreeBSD$");
/*
- * Broadcom BCM570x family gigabit ethernet driver for FreeBSD.
+ * Broadcom BCM57xx(x)/BCM590x NetXtreme and NetLink family Ethernet driver
*
* The Broadcom BCM5700 is based on technology originally developed by
- * Alteon Networks as part of the Tigon I and Tigon II gigabit ethernet
+ * Alteon Networks as part of the Tigon I and Tigon II Gigabit Ethernet
* MAC chips. The BCM5700, sometimes referred to as the Tigon III, has
* two on-board MIPS R4000 CPUs and can have as much as 16MB of external
* SSRAM. The BCM5700 supports TCP, UDP and IP checksum offload, jumbo
@@ -367,8 +367,9 @@ static const struct bge_revision bge_majorrevs[] = {
#define BGE_IS_5717_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_5717_PLUS)
#define BGE_IS_57765_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_57765_PLUS)
-const struct bge_revision * bge_lookup_rev(uint32_t);
-const struct bge_vendor * bge_lookup_vendor(uint16_t);
+static uint32_t bge_chipid(device_t);
+static const struct bge_vendor * bge_lookup_vendor(uint16_t);
+static const struct bge_revision * bge_lookup_rev(uint32_t);
typedef int (*bge_eaddr_fcn_t)(struct bge_softc *, uint8_t[]);
@@ -1916,7 +1917,7 @@ bge_chipinit(struct bge_softc *sc)
PCI_CLRBIT(sc->bge_dev, BGE_PCI_CMD,
PCIM_CMD_INTxDIS | PCIM_CMD_MWIEN, 4);
- /* Set the timer prescaler (always 66Mhz) */
+ /* Set the timer prescaler (always 66 MHz). */
CSR_WRITE_4(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ);
/* XXX: The Linux tg3 driver does this at the start of brgphy_reset. */
@@ -2586,7 +2587,7 @@ bge_blockinit(struct bge_softc *sc)
return (0);
}
-const struct bge_revision *
+static const struct bge_revision *
bge_lookup_rev(uint32_t chipid)
{
const struct bge_revision *br;
@@ -2604,7 +2605,7 @@ bge_lookup_rev(uint32_t chipid)
return (NULL);
}
-const struct bge_vendor *
+static const struct bge_vendor *
bge_lookup_vendor(uint16_t vid)
{
const struct bge_vendor *v;
@@ -2613,10 +2614,47 @@ bge_lookup_vendor(uint16_t vid)
if (v->v_id == vid)
return (v);
- panic("%s: unknown vendor %d", __func__, vid);
return (NULL);
}
+static uint32_t
+bge_chipid(device_t dev)
+{
+ uint32_t id;
+
+ id = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >>
+ BGE_PCIMISCCTL_ASICREV_SHIFT;
+ if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) {
+ /*
+ * Find the ASCI revision. Different chips use different
+ * registers.
+ */
+ switch (pci_get_device(dev)) {
+ case BCOM_DEVICEID_BCM5717:
+ case BCOM_DEVICEID_BCM5718:
+ case BCOM_DEVICEID_BCM5719:
+ case BCOM_DEVICEID_BCM5720:
+ id = pci_read_config(dev,
+ BGE_PCI_GEN2_PRODID_ASICREV, 4);
+ break;
+ case BCOM_DEVICEID_BCM57761:
+ case BCOM_DEVICEID_BCM57762:
+ case BCOM_DEVICEID_BCM57765:
+ case BCOM_DEVICEID_BCM57766:
+ case BCOM_DEVICEID_BCM57781:
+ case BCOM_DEVICEID_BCM57785:
+ case BCOM_DEVICEID_BCM57791:
+ case BCOM_DEVICEID_BCM57795:
+ id = pci_read_config(dev,
+ BGE_PCI_GEN15_PRODID_ASICREV, 4);
+ break;
+ default:
+ id = pci_read_config(dev, BGE_PCI_PRODID_ASICREV, 4);
+ }
+ }
+ return (id);
+}
+
/*
* Probe for a Broadcom chip. Check the PCI vendor and device IDs
* against our list and return its name if we find a match.
@@ -2634,61 +2672,34 @@ bge_probe(device_t dev)
char model[64];
const struct bge_revision *br;
const char *pname;
- struct bge_softc *sc = device_get_softc(dev);
+ struct bge_softc *sc;
const struct bge_type *t = bge_devs;
const struct bge_vendor *v;
uint32_t id;
uint16_t did, vid;
+ sc = device_get_softc(dev);
sc->bge_dev = dev;
vid = pci_get_vendor(dev);
did = pci_get_device(dev);
while(t->bge_vid != 0) {
if ((vid == t->bge_vid) && (did == t->bge_did)) {
- id = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >>
- BGE_PCIMISCCTL_ASICREV_SHIFT;
- if (BGE_ASICREV(id) == BGE_ASICREV_USE_PRODID_REG) {
- /*
- * Find the ASCI revision. Different chips
- * use different registers.
- */
- switch (pci_get_device(dev)) {
- case BCOM_DEVICEID_BCM5717:
- case BCOM_DEVICEID_BCM5718:
- case BCOM_DEVICEID_BCM5719:
- case BCOM_DEVICEID_BCM5720:
- id = pci_read_config(dev,
- BGE_PCI_GEN2_PRODID_ASICREV, 4);
- break;
- case BCOM_DEVICEID_BCM57761:
- case BCOM_DEVICEID_BCM57762:
- case BCOM_DEVICEID_BCM57765:
- case BCOM_DEVICEID_BCM57766:
- case BCOM_DEVICEID_BCM57781:
- case BCOM_DEVICEID_BCM57785:
- case BCOM_DEVICEID_BCM57791:
- case BCOM_DEVICEID_BCM57795:
- id = pci_read_config(dev,
- BGE_PCI_GEN15_PRODID_ASICREV, 4);
- break;
- default:
- id = pci_read_config(dev,
- BGE_PCI_PRODID_ASICREV, 4);
- }
- }
+ id = bge_chipid(dev);
br = bge_lookup_rev(id);
- v = bge_lookup_vendor(vid);
if (bge_has_eaddr(sc) &&
pci_get_vpd_ident(dev, &pname) == 0)
- snprintf(model, 64, "%s", pname);
- else
- snprintf(model, 64, "%s %s", v->v_name,
+ snprintf(model, sizeof(model), "%s", pname);
+ else {
+ v = bge_lookup_vendor(vid);
+ snprintf(model, sizeof(model), "%s %s",
+ v != NULL ? v->v_name : "Unknown",
br != NULL ? br->br_name :
- "NetXtreme Ethernet Controller");
- snprintf(buf, 96, "%s, %sASIC rev. %#08x", model,
- br != NULL ? "" : "unknown ", id);
+ "NetXtreme/NetLink Ethernet Controller");
+ }
+ snprintf(buf, sizeof(buf), "%s, %sASIC rev. %#08x",
+ model, br != NULL ? "" : "unknown ", id);
device_set_desc_copy(dev, buf);
- return (0);
+ return (BUS_PROBE_DEFAULT);
}
t++;
}
@@ -3247,38 +3258,7 @@ bge_attach(device_t dev)
/* Save various chip information. */
sc->bge_func_addr = pci_get_function(dev);
- sc->bge_chipid =
- pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >>
- BGE_PCIMISCCTL_ASICREV_SHIFT;
- if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_USE_PRODID_REG) {
- /*
- * Find the ASCI revision. Different chips use different
- * registers.
- */
- switch (pci_get_device(dev)) {
- case BCOM_DEVICEID_BCM5717:
- case BCOM_DEVICEID_BCM5718:
- case BCOM_DEVICEID_BCM5719:
- case BCOM_DEVICEID_BCM5720:
- sc->bge_chipid = pci_read_config(dev,
- BGE_PCI_GEN2_PRODID_ASICREV, 4);
- break;
- case BCOM_DEVICEID_BCM57761:
- case BCOM_DEVICEID_BCM57762:
- case BCOM_DEVICEID_BCM57765:
- case BCOM_DEVICEID_BCM57766:
- case BCOM_DEVICEID_BCM57781:
- case BCOM_DEVICEID_BCM57785:
- case BCOM_DEVICEID_BCM57791:
- case BCOM_DEVICEID_BCM57795:
- sc->bge_chipid = pci_read_config(dev,
- BGE_PCI_GEN15_PRODID_ASICREV, 4);
- break;
- default:
- sc->bge_chipid = pci_read_config(dev,
- BGE_PCI_PRODID_ASICREV, 4);
- }
- }
+ sc->bge_chipid = bge_chipid(dev);
sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid);
sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
@@ -3468,6 +3448,8 @@ bge_attach(device_t dev)
pci_get_device(dev) == BCOM_DEVICEID_BCM5753F ||
pci_get_device(dev) == BCOM_DEVICEID_BCM5787F)) ||
pci_get_device(dev) == BCOM_DEVICEID_BCM57790 ||
+ pci_get_device(dev) == BCOM_DEVICEID_BCM57791 ||
+ pci_get_device(dev) == BCOM_DEVICEID_BCM57795 ||
sc->bge_asicrev == BGE_ASICREV_BCM5906) {
/* These chips are 10/100 only. */
capmask &= ~BMSR_EXTSTAT;
@@ -3479,8 +3461,8 @@ bge_attach(device_t dev)
* TSO. But the firmware is not available to FreeBSD and Linux
* claims that the TSO performed by the firmware is slower than
* hardware based TSO. Moreover the firmware based TSO has one
- * known bug which can't handle TSO if ethernet header + IP/TCP
- * header is greater than 80 bytes. The workaround for the TSO
+ * known bug which can't handle TSO if Ethernet header + IP/TCP
+ * header is greater than 80 bytes. A workaround for the TSO
* bug exist but it seems it's too expensive than not using
* TSO at all. Some hardwares also have the TSO bug so limit
* the TSO to the controllers that are not affected TSO issues
@@ -3853,8 +3835,13 @@ again:
error = ENOMEM;
goto fail;
}
- taskqueue_start_threads(&sc->bge_tq, 1, PI_NET, "%s taskq",
- device_get_nameunit(sc->bge_dev));
+ error = taskqueue_start_threads(&sc->bge_tq, 1, PI_NET,
+ "%s taskq", device_get_nameunit(sc->bge_dev));
+ if (error != 0) {
+ device_printf(dev, "could not start threads.\n");
+ ether_ifdetach(ifp);
+ goto fail;
+ }
error = bus_setup_intr(dev, sc->bge_irq,
INTR_TYPE_NET | INTR_MPSAFE, bge_msi_intr, NULL, sc,
&sc->bge_intrhand);
@@ -3899,9 +3886,9 @@ bge_detach(device_t dev)
if (sc->bge_tq)
taskqueue_drain(sc->bge_tq, &sc->bge_intr_task);
- if (sc->bge_flags & BGE_FLAG_TBI) {
+ if (sc->bge_flags & BGE_FLAG_TBI)
ifmedia_removeall(&sc->bge_ifmedia);
- } else {
+ else if (sc->bge_miibus != NULL) {
bus_generic_detach(dev);
device_delete_child(dev, sc->bge_miibus);
}
@@ -5427,7 +5414,7 @@ bge_init_locked(struct bge_softc *sc)
* this number of frames, it will drop subsequent incoming
* frames until the MBUF High Watermark is reached.
*/
- if (sc->bge_asicrev == BGE_ASICREV_BCM57765)
+ if (BGE_IS_57765_PLUS(sc))
CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 1);
else
CSR_WRITE_4(sc, BGE_MAX_RX_FRAME_LOWAT, 2);
diff --git a/sys/dev/bktr/CHANGELOG.TXT b/sys/dev/bktr/CHANGELOG.TXT
index b885e15..b885e15 100755..100644
--- a/sys/dev/bktr/CHANGELOG.TXT
+++ b/sys/dev/bktr/CHANGELOG.TXT
diff --git a/sys/dev/bvm/bvm_console.c b/sys/dev/bvm/bvm_console.c
new file mode 100644
index 0000000..a0e70e5
--- /dev/null
+++ b/sys/dev/bvm/bvm_console.c
@@ -0,0 +1,240 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/cons.h>
+#include <sys/tty.h>
+#include <sys/reboot.h>
+#include <sys/bus.h>
+
+#include <sys/kdb.h>
+#include <ddb/ddb.h>
+
+#ifndef BVMCONS_POLL_HZ
+#define BVMCONS_POLL_HZ 4
+#endif
+#define BVMBURSTLEN 16 /* max number of bytes to write in one chunk */
+
+static tsw_open_t bvm_tty_open;
+static tsw_close_t bvm_tty_close;
+static tsw_outwakeup_t bvm_tty_outwakeup;
+
+static struct ttydevsw bvm_ttydevsw = {
+ .tsw_flags = TF_NOPREFIX,
+ .tsw_open = bvm_tty_open,
+ .tsw_close = bvm_tty_close,
+ .tsw_outwakeup = bvm_tty_outwakeup,
+};
+
+static int polltime;
+static struct callout_handle bvm_timeouthandle
+ = CALLOUT_HANDLE_INITIALIZER(&bvm_timeouthandle);
+
+#if defined(KDB)
+static int alt_break_state;
+#endif
+
+#define BVM_CONS_PORT 0x220
+static int bvm_cons_port = BVM_CONS_PORT;
+
+#define BVM_CONS_SIG ('b' << 8 | 'v')
+
+static void bvm_timeout(void *);
+
+static cn_probe_t bvm_cnprobe;
+static cn_init_t bvm_cninit;
+static cn_term_t bvm_cnterm;
+static cn_getc_t bvm_cngetc;
+static cn_putc_t bvm_cnputc;
+static cn_grab_t bvm_cngrab;
+static cn_ungrab_t bvm_cnungrab;
+
+CONSOLE_DRIVER(bvm);
+
+static int
+bvm_rcons(u_char *ch)
+{
+ int c;
+
+ c = inl(bvm_cons_port);
+ if (c != -1) {
+ *ch = (u_char)c;
+ return (0);
+ } else
+ return (-1);
+}
+
+static void
+bvm_wcons(u_char ch)
+{
+
+ outl(bvm_cons_port, ch);
+}
+
+static void
+cn_drvinit(void *unused)
+{
+ struct tty *tp;
+
+ if (bvm_consdev.cn_pri != CN_DEAD &&
+ bvm_consdev.cn_name[0] != '\0') {
+ tp = tty_alloc(&bvm_ttydevsw, NULL);
+ tty_makedev(tp, NULL, "bvmcons");
+ }
+}
+
+static int
+bvm_tty_open(struct tty *tp)
+{
+ polltime = hz / BVMCONS_POLL_HZ;
+ if (polltime < 1)
+ polltime = 1;
+ bvm_timeouthandle = timeout(bvm_timeout, tp, polltime);
+
+ return (0);
+}
+
+static void
+bvm_tty_close(struct tty *tp)
+{
+
+ /* XXX Should be replaced with callout_stop(9) */
+ untimeout(bvm_timeout, tp, bvm_timeouthandle);
+}
+
+static void
+bvm_tty_outwakeup(struct tty *tp)
+{
+ int len, written;
+ u_char buf[BVMBURSTLEN];
+
+ for (;;) {
+ len = ttydisc_getc(tp, buf, sizeof(buf));
+ if (len == 0)
+ break;
+
+ written = 0;
+ while (written < len)
+ bvm_wcons(buf[written++]);
+ }
+}
+
+static void
+bvm_timeout(void *v)
+{
+ struct tty *tp;
+ int c;
+
+ tp = (struct tty *)v;
+
+ tty_lock(tp);
+ while ((c = bvm_cngetc(NULL)) != -1)
+ ttydisc_rint(tp, c, 0);
+ ttydisc_rint_done(tp);
+ tty_unlock(tp);
+
+ bvm_timeouthandle = timeout(bvm_timeout, tp, polltime);
+}
+
+static void
+bvm_cnprobe(struct consdev *cp)
+{
+ int disabled, port;
+
+ disabled = 0;
+ cp->cn_pri = CN_DEAD;
+
+ resource_int_value("bvmconsole", 0, "disabled", &disabled);
+ if (!disabled) {
+ if (resource_int_value("bvmconsole", 0, "port", &port) == 0)
+ bvm_cons_port = port;
+
+ if (inw(bvm_cons_port) == BVM_CONS_SIG)
+ cp->cn_pri = CN_REMOTE;
+ }
+}
+
+static void
+bvm_cninit(struct consdev *cp)
+{
+ int i;
+ const char *bootmsg = "Using bvm console.\n";
+
+ if (boothowto & RB_VERBOSE) {
+ for (i = 0; i < strlen(bootmsg); i++)
+ bvm_cnputc(cp, bootmsg[i]);
+ }
+
+ strcpy(cp->cn_name, "bvmcons");
+}
+
+static void
+bvm_cnterm(struct consdev *cp)
+{
+
+}
+
+static int
+bvm_cngetc(struct consdev *cp)
+{
+ unsigned char ch;
+
+ if (bvm_rcons(&ch) == 0) {
+#if defined(KDB)
+ kdb_alt_break(ch, &alt_break_state);
+#endif
+ return (ch);
+ }
+
+ return (-1);
+}
+
+static void
+bvm_cnputc(struct consdev *cp, int c)
+{
+
+ bvm_wcons(c);
+}
+
+static void
+bvm_cngrab(struct consdev *cp)
+{
+}
+
+static void
+bvm_cnungrab(struct consdev *cp)
+{
+}
+
+SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL);
diff --git a/sys/dev/bvm/bvm_dbg.c b/sys/dev/bvm/bvm_dbg.c
new file mode 100644
index 0000000..1ba7ce0
--- /dev/null
+++ b/sys/dev/bvm/bvm_dbg.c
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2011 NetApp, Inc.
+ * 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 NETAPP, INC ``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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+
+#include <gdb/gdb.h>
+
+#include <machine/cpufunc.h>
+
+static gdb_probe_f bvm_dbg_probe;
+static gdb_init_f bvm_dbg_init;
+static gdb_term_f bvm_dbg_term;
+static gdb_getc_f bvm_dbg_getc;
+static gdb_putc_f bvm_dbg_putc;
+
+GDB_DBGPORT(bvm, bvm_dbg_probe, bvm_dbg_init, bvm_dbg_term,
+ bvm_dbg_getc, bvm_dbg_putc);
+
+#define BVM_DBG_PORT 0x224
+static int bvm_dbg_port = BVM_DBG_PORT;
+
+#define BVM_DBG_SIG ('B' << 8 | 'V')
+
+static int
+bvm_dbg_probe(void)
+{
+ int disabled, port;
+
+ disabled = 0;
+ resource_int_value("bvmdbg", 0, "disabled", &disabled);
+
+ if (!disabled) {
+ if (resource_int_value("bvmdbg", 0, "port", &port) == 0)
+ bvm_dbg_port = port;
+
+ if (inw(bvm_dbg_port) == BVM_DBG_SIG) {
+ /*
+ * Return a higher priority than 0 to override other
+ * gdb dbgport providers that may be present (e.g. uart)
+ */
+ return (1);
+ }
+ }
+
+ return (-1);
+}
+
+static void
+bvm_dbg_init(void)
+{
+}
+
+static void
+bvm_dbg_term(void)
+{
+}
+
+static void
+bvm_dbg_putc(int c)
+{
+
+ outl(bvm_dbg_port, c);
+}
+
+static int
+bvm_dbg_getc(void)
+{
+
+ return (inl(bvm_dbg_port));
+}
diff --git a/sys/dev/cas/if_cas.c b/sys/dev/cas/if_cas.c
index f846350..f98d4f0 100644
--- a/sys/dev/cas/if_cas.c
+++ b/sys/dev/cas/if_cas.c
@@ -214,8 +214,12 @@ cas_attach(struct cas_softc *sc)
error = ENXIO;
goto fail_ifnet;
}
- taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
+ error = taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
device_get_nameunit(sc->sc_dev));
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not start threads\n");
+ goto fail_taskq;
+ }
/* Make sure the chip is stopped. */
cas_reset(sc);
@@ -339,10 +343,13 @@ cas_attach(struct cas_softc *sc)
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_WRITE_4(sc, CAS_SATURN_PCFG,
+ CAS_READ_4(sc, CAS_SATURN_PCFG) &
+ ~CAS_SATURN_PCFG_FSI);
CAS_BARRIER(sc, CAS_SATURN_PCFG, 4,
BUS_SPACE_BARRIER_READ |
BUS_SPACE_BARRIER_WRITE);
+ DELAY(10000);
}
error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp,
cas_mediachange, cas_mediastatus, BMSR_DEFCAPMASK,
@@ -359,10 +366,12 @@ cas_attach(struct cas_softc *sc)
/* Freeze the GMII pins of Saturn for saving power. */
if (sc->sc_variant == CAS_SATURN) {
CAS_WRITE_4(sc, CAS_SATURN_PCFG,
+ CAS_READ_4(sc, CAS_SATURN_PCFG) |
CAS_SATURN_PCFG_FSI);
CAS_BARRIER(sc, CAS_SATURN_PCFG, 4,
BUS_SPACE_BARRIER_READ |
BUS_SPACE_BARRIER_WRITE);
+ DELAY(10000);
}
error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp,
cas_mediachange, cas_mediastatus, BMSR_DEFCAPMASK,
@@ -2865,7 +2874,7 @@ cas_pci_attach(device_t dev)
goto fail;
}
i = 0;
- if (lma > 1 && pci_get_slot(dev) < sizeof(enaddr) / sizeof(*enaddr))
+ if (lma > 1 && pci_get_slot(dev) < nitems(enaddr))
i = pci_get_slot(dev);
memcpy(sc->sc_enaddr, enaddr[i], ETHER_ADDR_LEN);
@@ -2874,7 +2883,7 @@ cas_pci_attach(device_t dev)
goto fail;
}
i = 0;
- if (phy > 1 && pci_get_slot(dev) < sizeof(pcs) / sizeof(*pcs))
+ if (phy > 1 && pci_get_slot(dev) < nitems(pcs))
i = pci_get_slot(dev);
if (pcs[i] != 0)
sc->sc_flags |= CAS_SERDES;
diff --git a/sys/dev/ce/if_ce.c b/sys/dev/ce/if_ce.c
index 700ab80a..3f1a550 100644
--- a/sys/dev/ce/if_ce.c
+++ b/sys/dev/ce/if_ce.c
@@ -145,7 +145,7 @@ static device_method_t ce_methods[] = {
DEVMETHOD(device_attach, ce_attach),
DEVMETHOD(device_detach, ce_detach),
- {0, 0}
+ DEVMETHOD_END
};
typedef struct _ce_dma_mem_t {
diff --git a/sys/dev/cfi/cfi_bus_fdt.c b/sys/dev/cfi/cfi_bus_fdt.c
index bfbd65f..f775e05 100644
--- a/sys/dev/cfi/cfi_bus_fdt.c
+++ b/sys/dev/cfi/cfi_bus_fdt.c
@@ -51,7 +51,7 @@ static device_method_t cfi_fdt_methods[] = {
DEVMETHOD(device_attach, cfi_attach),
DEVMETHOD(device_detach, cfi_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t cfi_fdt_driver = {
diff --git a/sys/dev/cfi/cfi_bus_ixp4xx.c b/sys/dev/cfi/cfi_bus_ixp4xx.c
index ef9da9ee..93d03fe 100644
--- a/sys/dev/cfi/cfi_bus_ixp4xx.c
+++ b/sys/dev/cfi/cfi_bus_ixp4xx.c
@@ -69,7 +69,7 @@ static device_method_t cfi_ixp4xx_methods[] = {
DEVMETHOD(device_attach, cfi_attach),
DEVMETHOD(device_detach, cfi_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t cfi_ixp4xx_driver = {
diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c
index 3291f03..a3f0a4a 100644
--- a/sys/dev/ciss/ciss.c
+++ b/sys/dev/ciss/ciss.c
@@ -1203,13 +1203,21 @@ ciss_identify_adapter(struct ciss_softc *sc)
/* XXX only really required for old 5300 adapters? */
sc->ciss_flags |= CISS_FLAG_BMIC_ABORT;
+ /*
+ * Earlier controller specs do not contain these config
+ * entries, so assume that a 0 means its old and assign
+ * these values to the defaults that were established
+ * when this driver was developed for them
+ */
+ if (sc->ciss_cfg->max_logical_supported == 0)
+ sc->ciss_cfg->max_logical_supported = CISS_MAX_LOGICAL;
+ if (sc->ciss_cfg->max_physical_supported == 0)
+ sc->ciss_cfg->max_physical_supported = CISS_MAX_PHYSICAL;
/* print information */
if (bootverbose) {
-#if 0 /* XXX proxy volumes??? */
ciss_printf(sc, " %d logical drive%s configured\n",
sc->ciss_id->configured_logical_drives,
(sc->ciss_id->configured_logical_drives == 1) ? "" : "s");
-#endif
ciss_printf(sc, " firmware %4.4s\n", sc->ciss_id->running_firmware_revision);
ciss_printf(sc, " %d SCSI channels\n", sc->ciss_id->scsi_bus_count);
@@ -1232,6 +1240,9 @@ ciss_identify_adapter(struct ciss_softc *sc)
"\20\1ultra2\2ultra3\10fibre1\11fibre2\n");
ciss_printf(sc, " server name '%.16s'\n", sc->ciss_cfg->server_name);
ciss_printf(sc, " heartbeat 0x%x\n", sc->ciss_cfg->heartbeat);
+ ciss_printf(sc, " max logical logical volumes: %d\n", sc->ciss_cfg->max_logical_supported);
+ ciss_printf(sc, " max physical disks supported: %d\n", sc->ciss_cfg->max_physical_supported);
+ ciss_printf(sc, " max physical disks per logical volume: %d\n", sc->ciss_cfg->max_physical_per_logical);
}
out:
@@ -1319,7 +1330,7 @@ ciss_report_luns(struct ciss_softc *sc, int opcode, int nunits)
break;
case CISS_CMD_STATUS_DATA_OVERRUN:
ciss_printf(sc, "WARNING: more units than driver limit (%d)\n",
- CISS_MAX_LOGICAL);
+ sc->ciss_cfg->max_logical_supported);
break;
default:
ciss_printf(sc, "error detecting logical drive configuration (%s)\n",
@@ -1353,7 +1364,7 @@ ciss_init_logical(struct ciss_softc *sc)
debug_called(1);
cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_LOGICAL_LUNS,
- CISS_MAX_LOGICAL);
+ sc->ciss_cfg->max_logical_supported);
if (cll == NULL) {
error = ENXIO;
goto out;
@@ -1361,9 +1372,9 @@ ciss_init_logical(struct ciss_softc *sc)
/* sanity-check reply */
ndrives = (ntohl(cll->list_size) / sizeof(union ciss_device_address));
- if ((ndrives < 0) || (ndrives > CISS_MAX_LOGICAL)) {
+ if ((ndrives < 0) || (ndrives > sc->ciss_cfg->max_logical_supported)) {
ciss_printf(sc, "adapter claims to report absurd number of logical drives (%d > %d)\n",
- ndrives, CISS_MAX_LOGICAL);
+ ndrives, sc->ciss_cfg->max_logical_supported);
error = ENXIO;
goto out;
}
@@ -1386,19 +1397,20 @@ ciss_init_logical(struct ciss_softc *sc)
for (i = 0; i <= sc->ciss_max_logical_bus; i++) {
sc->ciss_logical[i] =
- malloc(CISS_MAX_LOGICAL * sizeof(struct ciss_ldrive),
+ malloc(sc->ciss_cfg->max_logical_supported *
+ sizeof(struct ciss_ldrive),
CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO);
if (sc->ciss_logical[i] == NULL) {
error = ENXIO;
goto out;
}
- for (j = 0; j < CISS_MAX_LOGICAL; j++)
+ for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++)
sc->ciss_logical[i][j].cl_status = CISS_LD_NONEXISTENT;
}
- for (i = 0; i < CISS_MAX_LOGICAL; i++) {
+ for (i = 0; i < sc->ciss_cfg->max_logical_supported; i++) {
if (i < ndrives) {
struct ciss_ldrive *ld;
int bus, target;
@@ -1440,7 +1452,7 @@ ciss_init_physical(struct ciss_softc *sc)
target = 0;
cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_PHYSICAL_LUNS,
- CISS_MAX_PHYSICAL);
+ sc->ciss_cfg->max_physical_supported);
if (cll == NULL) {
error = ENXIO;
goto out;
@@ -1983,7 +1995,7 @@ ciss_free(struct ciss_softc *sc)
bus_dma_tag_destroy(sc->ciss_parent_dmat);
if (sc->ciss_logical) {
for (i = 0; i <= sc->ciss_max_logical_bus; i++) {
- for (j = 0; j < CISS_MAX_LOGICAL; j++) {
+ for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++) {
if (sc->ciss_logical[i][j].cl_ldrive)
free(sc->ciss_logical[i][j].cl_ldrive, CISS_MALLOC_CLASS);
if (sc->ciss_logical[i][j].cl_lstatus)
@@ -2966,9 +2978,9 @@ ciss_cam_action(struct cam_sim *sim, union ccb *ccb)
cpi->hba_inquiry = PI_TAG_ABLE; /* XXX is this correct? */
cpi->target_sprt = 0;
cpi->hba_misc = 0;
- cpi->max_target = CISS_MAX_LOGICAL;
+ cpi->max_target = sc->ciss_cfg->max_logical_supported;
cpi->max_lun = 0; /* 'logical drive' channel only */
- cpi->initiator_id = CISS_MAX_LOGICAL;
+ cpi->initiator_id = sc->ciss_cfg->max_logical_supported;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "msmith@freebsd.org", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
@@ -3879,7 +3891,7 @@ ciss_notify_rescan_logical(struct ciss_softc *sc)
* drive address.
*/
cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_LOGICAL_LUNS,
- CISS_MAX_LOGICAL);
+ sc->ciss_cfg->max_logical_supported);
if (cll == NULL)
return;
@@ -3890,7 +3902,7 @@ ciss_notify_rescan_logical(struct ciss_softc *sc)
* firmware.
*/
for (i = 0; i < sc->ciss_max_logical_bus; i++) {
- for (j = 0; j < CISS_MAX_LOGICAL; j++) {
+ for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++) {
ld = &sc->ciss_logical[i][j];
if (ld->cl_update == 0)
@@ -4059,7 +4071,7 @@ ciss_notify_hotplug(struct ciss_softc *sc, struct ciss_notify *cn)
* Rescan the physical lun list for new items
*/
cll = ciss_report_luns(sc, CISS_OPCODE_REPORT_PHYSICAL_LUNS,
- CISS_MAX_PHYSICAL);
+ sc->ciss_cfg->max_physical_supported);
if (cll == NULL) {
ciss_printf(sc, "Warning, cannot get physical lun list\n");
break;
@@ -4307,7 +4319,7 @@ ciss_print_adapter(struct ciss_softc *sc)
"\20\1notify_ok\2control_open\3aborting\4running\21fake_synch\22bmic_abort\n");
for (i = 0; i < sc->ciss_max_logical_bus; i++) {
- for (j = 0; j < CISS_MAX_LOGICAL; j++) {
+ for (j = 0; j < sc->ciss_cfg->max_logical_supported; j++) {
ciss_printf(sc, "LOGICAL DRIVE %d: ", i);
ciss_print_ldrive(sc, &sc->ciss_logical[i][j]);
}
diff --git a/sys/dev/ciss/cissreg.h b/sys/dev/ciss/cissreg.h
index feae826..4a3349f 100644
--- a/sys/dev/ciss/cissreg.h
+++ b/sys/dev/ciss/cissreg.h
@@ -425,6 +425,15 @@ struct ciss_config_table
#define CISS_DRIVER_DAUGHTER_ATTACHED (1<<8)
#define CISS_DRIVER_SCSI_PREFETCH (1<<9)
u_int32_t max_sg_length; /* 31 in older firmware */
+/*
+ * these fields appear in OpenCISS Spec 1.06
+ * http://cciss.sourceforge.net/#docs
+ */
+ u_int32_t max_logical_supported;
+ u_int32_t max_physical_supported;
+ u_int32_t max_physical_per_logical;
+ u_int32_t max_perfomant_mode_cmds;
+ u_int32_t max_block_fetch_count;
} __packed;
/*
diff --git a/sys/dev/ciss/cissvar.h b/sys/dev/ciss/cissvar.h
index d109b7a..e89e4e9 100644
--- a/sys/dev/ciss/cissvar.h
+++ b/sys/dev/ciss/cissvar.h
@@ -45,8 +45,11 @@ typedef STAILQ_HEAD(, ciss_request) cr_qhead_t;
/*
* Maximum number of logical drives we support.
+ * If the controller does not indicate a maximum
+ * value. This is a compatibiliy value to support
+ * older ciss controllers (e.g. model 6i)
*/
-#define CISS_MAX_LOGICAL 63
+#define CISS_MAX_LOGICAL 16
/*
* Maximum number of physical devices we support.
diff --git a/sys/dev/coretemp/coretemp.c b/sys/dev/coretemp/coretemp.c
index 54e5a43..55efca2 100644
--- a/sys/dev/coretemp/coretemp.c
+++ b/sys/dev/coretemp/coretemp.c
@@ -85,7 +85,7 @@ static device_method_t coretemp_methods[] = {
DEVMETHOD(device_attach, coretemp_attach),
DEVMETHOD(device_detach, coretemp_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t coretemp_driver = {
diff --git a/sys/dev/cp/if_cp.c b/sys/dev/cp/if_cp.c
index 4ff0bcc..299a51c 100644
--- a/sys/dev/cp/if_cp.c
+++ b/sys/dev/cp/if_cp.c
@@ -93,7 +93,7 @@ static device_method_t cp_methods[] = {
DEVMETHOD(device_attach, cp_attach),
DEVMETHOD(device_detach, cp_detach),
- {0, 0}
+ DEVMETHOD_END
};
typedef struct _cp_dma_mem_t {
diff --git a/sys/dev/cpufreq/ichss.c b/sys/dev/cpufreq/ichss.c
index fc7f0ac..0eae0c9 100644
--- a/sys/dev/cpufreq/ichss.c
+++ b/sys/dev/cpufreq/ichss.c
@@ -113,7 +113,7 @@ static device_method_t ichss_methods[] = {
DEVMETHOD(cpufreq_drv_get, ichss_get),
DEVMETHOD(cpufreq_drv_type, ichss_type),
DEVMETHOD(cpufreq_drv_settings, ichss_settings),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ichss_driver = {
"ichss", ichss_methods, sizeof(struct ichss_softc)
diff --git a/sys/dev/ctau/if_ct.c b/sys/dev/ctau/if_ct.c
index 7b4abc3..fc3e916 100644
--- a/sys/dev/ctau/if_ct.c
+++ b/sys/dev/ctau/if_ct.c
@@ -93,7 +93,8 @@ static device_method_t ct_isa_methods [] = {
DEVMETHOD(device_probe, ct_probe),
DEVMETHOD(device_attach, ct_attach),
DEVMETHOD(device_detach, ct_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
typedef struct _ct_dma_mem_t {
diff --git a/sys/dev/cx/if_cx.c b/sys/dev/cx/if_cx.c
index cb15486..ad8312c 100644
--- a/sys/dev/cx/if_cx.c
+++ b/sys/dev/cx/if_cx.c
@@ -113,7 +113,8 @@ static device_method_t cx_isa_methods [] = {
DEVMETHOD(device_probe, cx_probe),
DEVMETHOD(device_attach, cx_attach),
DEVMETHOD(device_detach, cx_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
typedef struct _cx_dma_mem_t {
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index c1d8a6b..55cfa52 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -158,6 +158,16 @@ enum {
};
enum {
+ /* flags understood by begin_synchronized_op */
+ HOLD_LOCK = (1 << 0),
+ SLEEP_OK = (1 << 1),
+ INTR_OK = (1 << 2),
+
+ /* flags understood by end_synchronized_op */
+ LOCK_HELD = HOLD_LOCK,
+};
+
+enum {
/* adapter flags */
FULL_INIT_DONE = (1 << 0),
FW_OK = (1 << 1),
@@ -174,11 +184,11 @@ enum {
PORT_SYSCTL_CTX = (1 << 2),
};
-#define IS_DOOMED(pi) (pi->flags & DOOMED)
-#define SET_DOOMED(pi) do {pi->flags |= DOOMED;} while (0)
-#define IS_BUSY(sc) (sc->flags & CXGBE_BUSY)
-#define SET_BUSY(sc) do {sc->flags |= CXGBE_BUSY;} while (0)
-#define CLR_BUSY(sc) do {sc->flags &= ~CXGBE_BUSY;} while (0)
+#define IS_DOOMED(pi) ((pi)->flags & DOOMED)
+#define SET_DOOMED(pi) do {(pi)->flags |= DOOMED;} while (0)
+#define IS_BUSY(sc) ((sc)->flags & CXGBE_BUSY)
+#define SET_BUSY(sc) do {(sc)->flags |= CXGBE_BUSY;} while (0)
+#define CLR_BUSY(sc) do {(sc)->flags &= ~CXGBE_BUSY;} while (0)
struct port_info {
device_t dev;
@@ -567,7 +577,8 @@ struct adapter {
int flags;
char fw_version[32];
- unsigned int cfcsum;
+ char cfg_file[32];
+ u_int cfcsum;
struct adapter_params params;
struct t4_virt_res vres;
@@ -591,6 +602,11 @@ struct adapter {
an_handler_t an_handler __aligned(CACHE_LINE_SIZE);
fw_msg_handler_t fw_msg_handler[4]; /* NUM_FW6_TYPES */
cpl_handler_t cpl_handler[0xef]; /* NUM_CPL_CMDS */
+
+#ifdef INVARIANTS
+ const char *last_op;
+ const void *last_op_thr;
+#endif
};
#define ADAPTER_LOCK(sc) mtx_lock(&(sc)->sc_lock)
@@ -598,6 +614,12 @@ struct adapter {
#define ADAPTER_LOCK_ASSERT_OWNED(sc) mtx_assert(&(sc)->sc_lock, MA_OWNED)
#define ADAPTER_LOCK_ASSERT_NOTOWNED(sc) mtx_assert(&(sc)->sc_lock, MA_NOTOWNED)
+/* XXX: not bulletproof, but much better than nothing */
+#define ASSERT_SYNCHRONIZED_OP(sc) \
+ KASSERT(IS_BUSY(sc) && \
+ (mtx_owned(&(sc)->sc_lock) || sc->last_op_thr == curthread), \
+ ("%s: operation not synchronized.", __func__))
+
#define PORT_LOCK(pi) mtx_lock(&(pi)->pi_lock)
#define PORT_UNLOCK(pi) mtx_unlock(&(pi)->pi_lock)
#define PORT_LOCK_ASSERT_OWNED(pi) mtx_assert(&(pi)->pi_lock, MA_OWNED)
@@ -626,18 +648,18 @@ struct adapter {
#define TXQ_LOCK_ASSERT_OWNED(txq) EQ_LOCK_ASSERT_OWNED(&(txq)->eq)
#define TXQ_LOCK_ASSERT_NOTOWNED(txq) EQ_LOCK_ASSERT_NOTOWNED(&(txq)->eq)
-#define for_each_txq(pi, iter, txq) \
- txq = &pi->adapter->sge.txq[pi->first_txq]; \
- for (iter = 0; iter < pi->ntxq; ++iter, ++txq)
-#define for_each_rxq(pi, iter, rxq) \
- rxq = &pi->adapter->sge.rxq[pi->first_rxq]; \
- for (iter = 0; iter < pi->nrxq; ++iter, ++rxq)
-#define for_each_ofld_txq(pi, iter, ofld_txq) \
- ofld_txq = &pi->adapter->sge.ofld_txq[pi->first_ofld_txq]; \
- for (iter = 0; iter < pi->nofldtxq; ++iter, ++ofld_txq)
-#define for_each_ofld_rxq(pi, iter, ofld_rxq) \
- ofld_rxq = &pi->adapter->sge.ofld_rxq[pi->first_ofld_rxq]; \
- for (iter = 0; iter < pi->nofldrxq; ++iter, ++ofld_rxq)
+#define for_each_txq(pi, iter, q) \
+ for (q = &pi->adapter->sge.txq[pi->first_txq], iter = 0; \
+ iter < pi->ntxq; ++iter, ++q)
+#define for_each_rxq(pi, iter, q) \
+ for (q = &pi->adapter->sge.rxq[pi->first_rxq], iter = 0; \
+ iter < pi->nrxq; ++iter, ++q)
+#define for_each_ofld_txq(pi, iter, q) \
+ for (q = &pi->adapter->sge.ofld_txq[pi->first_ofld_txq], iter = 0; \
+ iter < pi->nofldtxq; ++iter, ++q)
+#define for_each_ofld_rxq(pi, iter, q) \
+ for (q = &pi->adapter->sge.ofld_rxq[pi->first_ofld_rxq], iter = 0; \
+ iter < pi->nofldrxq; ++iter, ++q)
/* One for errors, one for firmware events */
#define T4_EXTRA_INTR 2
@@ -751,6 +773,8 @@ int t4_register_cpl_handler(struct adapter *, int, cpl_handler_t);
int t4_register_an_handler(struct adapter *, an_handler_t);
int t4_register_fw_msg_handler(struct adapter *, int, fw_msg_handler_t);
int t4_filter_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *);
+int begin_synchronized_op(struct adapter *, struct port_info *, int, char *);
+void end_synchronized_op(struct adapter *, int);
/* t4_sge.c */
void t4_sge_modload(void);
diff --git a/sys/dev/cxgbe/common/jhash.h b/sys/dev/cxgbe/common/jhash.h
deleted file mode 100644
index 4546b7b..0000000
--- a/sys/dev/cxgbe/common/jhash.h
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef _JHASH_H
-#define _JHASH_H
-
-/* jhash.h: Jenkins hash support.
- *
- * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
- *
- * http://burtleburtle.net/bob/hash/
- *
- * These are the credits from Bob's sources:
- *
- * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
- * hash(), hash2(), hash3, and mix() are externally useful functions.
- * Routines to test the hash are included if SELF_TEST is defined.
- * You can use this free for any purpose. It has no warranty.
- *
- * $FreeBSD$
- */
-
-/* NOTE: Arguments are modified. */
-#define __jhash_mix(a, b, c) \
-{ \
- a -= b; a -= c; a ^= (c>>13); \
- b -= c; b -= a; b ^= (a<<8); \
- c -= a; c -= b; c ^= (b>>13); \
- a -= b; a -= c; a ^= (c>>12); \
- b -= c; b -= a; b ^= (a<<16); \
- c -= a; c -= b; c ^= (b>>5); \
- a -= b; a -= c; a ^= (c>>3); \
- b -= c; b -= a; b ^= (a<<10); \
- c -= a; c -= b; c ^= (b>>15); \
-}
-
-/* The golden ration: an arbitrary value */
-#define JHASH_GOLDEN_RATIO 0x9e3779b9
-
-/* The most generic version, hashes an arbitrary sequence
- * of bytes. No alignment or length assumptions are made about
- * the input key.
- */
-static inline u32 jhash(const void *key, u32 length, u32 initval)
-{
- u32 a, b, c, len;
- const u8 *k = key;
-
- len = length;
- a = b = JHASH_GOLDEN_RATIO;
- c = initval;
-
- while (len >= 12) {
- a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24));
- b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24));
- c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24));
-
- __jhash_mix(a,b,c);
-
- k += 12;
- len -= 12;
- }
-
- c += length;
- switch (len) {
- case 11: c += ((u32)k[10]<<24);
- case 10: c += ((u32)k[9]<<16);
- case 9 : c += ((u32)k[8]<<8);
- case 8 : b += ((u32)k[7]<<24);
- case 7 : b += ((u32)k[6]<<16);
- case 6 : b += ((u32)k[5]<<8);
- case 5 : b += k[4];
- case 4 : a += ((u32)k[3]<<24);
- case 3 : a += ((u32)k[2]<<16);
- case 2 : a += ((u32)k[1]<<8);
- case 1 : a += k[0];
- };
-
- __jhash_mix(a,b,c);
-
- return c;
-}
-
-/* A special optimized version that handles 1 or more of u32s.
- * The length parameter here is the number of u32s in the key.
- */
-static inline u32 jhash2(u32 *k, u32 length, u32 initval)
-{
- u32 a, b, c, len;
-
- a = b = JHASH_GOLDEN_RATIO;
- c = initval;
- len = length;
-
- while (len >= 3) {
- a += k[0];
- b += k[1];
- c += k[2];
- __jhash_mix(a, b, c);
- k += 3; len -= 3;
- }
-
- c += length * 4;
-
- switch (len) {
- case 2 : b += k[1];
- case 1 : a += k[0];
- };
-
- __jhash_mix(a,b,c);
-
- return c;
-}
-
-
-/* A special ultra-optimized versions that knows they are hashing exactly
- * 3, 2 or 1 word(s).
- *
- * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
- * done at the end is not done here.
- */
-static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
-{
- a += JHASH_GOLDEN_RATIO;
- b += JHASH_GOLDEN_RATIO;
- c += initval;
-
- __jhash_mix(a, b, c);
-
- return c;
-}
-
-static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
-{
- return jhash_3words(a, b, 0, initval);
-}
-
-static inline u32 jhash_1word(u32 a, u32 initval)
-{
- return jhash_3words(a, 0, 0, initval);
-}
-
-#endif /* _JHASH_H */
diff --git a/sys/dev/cxgbe/common/t4_msg.h b/sys/dev/cxgbe/common/t4_msg.h
index 5bd3cef..92f760b 100644
--- a/sys/dev/cxgbe/common/t4_msg.h
+++ b/sys/dev/cxgbe/common/t4_msg.h
@@ -159,6 +159,8 @@ enum CPL_error {
CPL_ERR_KEEPALIVE_TIMEDOUT = 34,
CPL_ERR_RTX_NEG_ADVICE = 35,
CPL_ERR_PERSIST_NEG_ADVICE = 36,
+ CPL_ERR_KEEPALV_NEG_ADVICE = 37,
+ CPL_ERR_WAIT_ARP_RPL = 41,
CPL_ERR_ABORT_FAILED = 42,
CPL_ERR_IWARP_FLM = 50,
};
diff --git a/sys/dev/cxgbe/firmware/t4fw_cfg.txt b/sys/dev/cxgbe/firmware/t4fw_cfg.txt
index bf6a9a1..2a9db62 100644
--- a/sys/dev/cxgbe/firmware/t4fw_cfg.txt
+++ b/sys/dev/cxgbe/firmware/t4fw_cfg.txt
@@ -56,7 +56,7 @@
[function "4"]
wx_caps = all
r_caps = all
- nvi = 54
+ nvi = 32
niqflint = 256
nethctrl = 128
neq = 256
@@ -74,8 +74,8 @@
# Each entry in these categories takes 4 cells each. nhash will use the
# TCAM iff there is room left (that is, the rest don't add up to 2048).
nroute = 32
- nclip = 0 # needed only for IPv6 offload
- nfilter = 1488
+ nclip = 32
+ nfilter = 1456
nserver = 512
nhash = 16384
@@ -137,7 +137,7 @@
[fini]
version = 0x1
- checksum = 0x162df193
+ checksum = 0xfdebb6ef
#
# $FreeBSD$
#
diff --git a/sys/dev/cxgbe/offload.h b/sys/dev/cxgbe/offload.h
index ced15a6..55ac71b 100644
--- a/sys/dev/cxgbe/offload.h
+++ b/sys/dev/cxgbe/offload.h
@@ -54,16 +54,20 @@
OPCODE_TID(w) = htonl(MK_OPCODE_TID(cpl, tid)); \
} while (0)
+TAILQ_HEAD(stid_head, stid_region);
+struct listen_ctx;
+
+struct stid_region {
+ TAILQ_ENTRY(stid_region) link;
+ int used; /* # of stids used by this region */
+ int free; /* # of contiguous stids free right after this region */
+};
+
/*
* Max # of ATIDs. The absolute HW max is 16K but we keep it lower.
*/
#define MAX_ATIDS 8192U
-union serv_entry {
- void *data;
- union serv_entry *next;
-};
-
union aopen_entry {
void *data;
union aopen_entry *next;
@@ -75,34 +79,33 @@ union aopen_entry {
*/
struct tid_info {
void **tid_tab;
- unsigned int ntids;
-
- union serv_entry *stid_tab;
- unsigned int nstids;
- unsigned int stid_base;
-
+ u_int ntids;
+ u_int tids_in_use;
+
+ struct mtx stid_lock __aligned(CACHE_LINE_SIZE);
+ struct listen_ctx **stid_tab;
+ u_int nstids;
+ u_int stid_base;
+ u_int stids_in_use;
+ u_int nstids_free_head; /* # of available stids at the begining */
+ struct stid_head stids;
+
+ struct mtx atid_lock __aligned(CACHE_LINE_SIZE);
union aopen_entry *atid_tab;
- unsigned int natids;
-
- struct filter_entry *ftid_tab;
- unsigned int nftids;
- unsigned int ftid_base;
- unsigned int ftids_in_use;
-
- struct mtx atid_lock;
+ u_int natids;
union aopen_entry *afree;
- unsigned int atids_in_use;
-
- struct mtx stid_lock;
- union serv_entry *sfree;
- unsigned int stids_in_use;
+ u_int atids_in_use;
- unsigned int tids_in_use;
+ struct mtx ftid_lock __aligned(CACHE_LINE_SIZE);
+ struct filter_entry *ftid_tab;
+ u_int nftids;
+ u_int ftid_base;
+ u_int ftids_in_use;
};
struct t4_range {
- unsigned int start;
- unsigned int size;
+ u_int start;
+ u_int size;
};
struct t4_virt_res { /* virtualized HW resources */
@@ -114,6 +117,7 @@ struct t4_virt_res { /* virtualized HW resources */
struct t4_range qp;
struct t4_range cq;
struct t4_range ocq;
+ struct t4_range l2t;
};
#ifdef TCP_OFFLOAD
diff --git a/sys/dev/cxgbe/t4_l2t.c b/sys/dev/cxgbe/t4_l2t.c
index dd8748e..dcff5e8 100644
--- a/sys/dev/cxgbe/t4_l2t.c
+++ b/sys/dev/cxgbe/t4_l2t.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include "common/common.h"
-#include "common/jhash.h"
#include "common/t4_msg.h"
#include "t4_l2t.h"
@@ -78,7 +77,7 @@ t4_alloc_l2e(struct l2t_data *d)
return (NULL);
/* there's definitely a free entry */
- for (e = d->rover, end = &d->l2tab[L2T_SIZE]; e != end; ++e)
+ for (e = d->rover, end = &d->l2tab[d->l2t_size]; e != end; ++e)
if (atomic_load_acq_int(&e->refcnt) == 0)
goto found;
@@ -115,6 +114,7 @@ t4_write_l2e(struct adapter *sc, struct l2t_entry *e, int sync)
{
struct wrqe *wr;
struct cpl_l2t_write_req *req;
+ int idx = e->idx + sc->vres.l2t.start;
mtx_assert(&e->lock, MA_OWNED);
@@ -124,10 +124,10 @@ t4_write_l2e(struct adapter *sc, struct l2t_entry *e, int sync)
req = wrtod(wr);
INIT_TP_WR(req, 0);
- OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, e->idx |
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, idx |
V_SYNC_WR(sync) | V_TID_QID(sc->sge.fwq.abs_id)));
req->params = htons(V_L2T_W_PORT(e->lport) | V_L2T_W_NOREPLY(!sync));
- req->l2t_idx = htons(e->idx);
+ req->l2t_idx = htons(idx);
req->vlan = htons(e->vlan);
memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac));
@@ -183,18 +183,24 @@ t4_l2t_set_switching(struct adapter *sc, struct l2t_entry *e, uint16_t vlan,
int
t4_init_l2t(struct adapter *sc, int flags)
{
- int i;
+ int i, l2t_size;
struct l2t_data *d;
- d = malloc(sizeof(*d), M_CXGBE, M_ZERO | flags);
+ l2t_size = sc->vres.l2t.size;
+ if (l2t_size < 2) /* At least 1 bucket for IP and 1 for IPv6 */
+ return (EINVAL);
+
+ d = malloc(sizeof(*d) + l2t_size * sizeof (struct l2t_entry), M_CXGBE,
+ M_ZERO | flags);
if (!d)
return (ENOMEM);
+ d->l2t_size = l2t_size;
d->rover = d->l2tab;
- atomic_store_rel_int(&d->nfree, L2T_SIZE);
+ atomic_store_rel_int(&d->nfree, l2t_size);
rw_init(&d->lock, "L2T");
- for (i = 0; i < L2T_SIZE; i++) {
+ for (i = 0; i < l2t_size; i++) {
struct l2t_entry *e = &d->l2tab[i];
e->idx = i;
@@ -215,7 +221,7 @@ t4_free_l2t(struct l2t_data *d)
{
int i;
- for (i = 0; i < L2T_SIZE; i++)
+ for (i = 0; i < d->l2t_size; i++)
mtx_destroy(&d->l2tab[i].lock);
rw_destroy(&d->lock);
free(d, M_CXGBE);
@@ -229,11 +235,11 @@ do_l2t_write_rpl(struct sge_iq *iq, const struct rss_header *rss,
{
const struct cpl_l2t_write_rpl *rpl = (const void *)(rss + 1);
unsigned int tid = GET_TID(rpl);
- unsigned int idx = tid & (L2T_SIZE - 1);
+ unsigned int idx = tid % L2T_SIZE;
if (__predict_false(rpl->status != CPL_ERR_NONE)) {
log(LOG_ERR,
- "Unexpected L2T_WRITE_RPL status %u for entry %u\n",
+ "Unexpected L2T_WRITE_RPL (%u) for entry at hw_idx %u\n",
rpl->status, idx);
return (EINVAL);
}
@@ -269,7 +275,7 @@ sysctl_l2t(SYSCTL_HANDLER_ARGS)
struct l2t_entry *e;
struct sbuf *sb;
int rc, i, header = 0;
- char ip[60];
+ char ip[INET6_ADDRSTRLEN];
if (l2t == NULL)
return (ENXIO);
@@ -283,7 +289,7 @@ sysctl_l2t(SYSCTL_HANDLER_ARGS)
return (ENOMEM);
e = &l2t->l2tab[0];
- for (i = 0; i < L2T_SIZE; i++, e++) {
+ for (i = 0; i < l2t->l2t_size; i++, e++) {
mtx_lock(&e->lock);
if (e->state == L2T_STATE_UNUSED)
goto skip;
@@ -295,11 +301,15 @@ sysctl_l2t(SYSCTL_HANDLER_ARGS)
}
if (e->state == L2T_STATE_SWITCHING)
ip[0] = 0;
- else
- snprintf(ip, sizeof(ip), "%s",
- inet_ntoa(*(struct in_addr *)&e->addr));
+ else {
+ inet_ntop(e->ipv6 ? AF_INET6 : AF_INET, &e->addr[0],
+ &ip[0], sizeof(ip));
+ }
- /* XXX: e->ifp may not be around */
+ /*
+ * XXX: e->ifp may not be around.
+ * XXX: IPv6 addresses may not align properly in the output.
+ */
sbuf_printf(sb, "\n%4u %-15s %02x:%02x:%02x:%02x:%02x:%02x %4d"
" %u %2u %c %5u %s",
e->idx, ip, e->dmac[0], e->dmac[1], e->dmac[2],
diff --git a/sys/dev/cxgbe/t4_l2t.h b/sys/dev/cxgbe/t4_l2t.h
index 6927b81..c60eef1 100644
--- a/sys/dev/cxgbe/t4_l2t.h
+++ b/sys/dev/cxgbe/t4_l2t.h
@@ -60,7 +60,7 @@ enum {
struct l2t_entry {
uint16_t state; /* entry state */
uint16_t idx; /* entry index */
- uint32_t addr; /* next hop IP address */
+ uint32_t addr[4]; /* next hop IP or IPv6 address */
struct ifnet *ifp; /* outgoing interface */
uint16_t smt_idx; /* SMT index */
uint16_t vlan; /* VLAN TCI (id: 0-11, prio: 13-15) */
@@ -70,15 +70,17 @@ struct l2t_entry {
struct mtx lock;
volatile int refcnt; /* entry reference count */
uint16_t hash; /* hash bucket the entry is on */
+ uint8_t ipv6; /* entry is for an IPv6 address */
uint8_t lport; /* associated offload logical port */
uint8_t dmac[ETHER_ADDR_LEN]; /* next hop's MAC address */
};
struct l2t_data {
struct rwlock lock;
+ u_int l2t_size;
volatile int nfree; /* number of free entries */
struct l2t_entry *rover;/* starting point for next allocation */
- struct l2t_entry l2tab[L2T_SIZE];
+ struct l2t_entry l2tab[];
};
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index aeaa4d2..c22ec21 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -284,9 +284,7 @@ static int get_params__post_init(struct adapter *);
static void t4_set_desc(struct adapter *);
static void build_medialist(struct port_info *);
static int update_mac_settings(struct port_info *, int);
-static int cxgbe_init_locked(struct port_info *);
static int cxgbe_init_synchronized(struct port_info *);
-static int cxgbe_uninit_locked(struct port_info *);
static int cxgbe_uninit_synchronized(struct port_info *);
static int setup_intr_handlers(struct adapter *);
static int adapter_full_init(struct adapter *);
@@ -348,6 +346,7 @@ static void clear_filter(struct filter_entry *);
static int set_filter_wr(struct adapter *, int);
static int del_filter_wr(struct adapter *, int);
static int get_sge_context(struct adapter *, struct t4_sge_context *);
+static int load_fw(struct adapter *, struct t4_data *);
static int read_card_mem(struct adapter *, struct t4_mem_range *);
static int read_i2c(struct adapter *, struct t4_i2c_data *);
#ifdef TCP_OFFLOAD
@@ -820,6 +819,8 @@ t4_detach(device_t dev)
mtx_destroy(&sc->sc_lock);
}
+ if (mtx_initialized(&sc->tids.ftid_lock))
+ mtx_destroy(&sc->tids.ftid_lock);
if (mtx_initialized(&sc->sfl_lock))
mtx_destroy(&sc->sfl_lock);
@@ -874,7 +875,7 @@ cxgbe_attach(device_t dev)
ifp->if_capabilities = T4_CAP;
#ifdef TCP_OFFLOAD
if (is_offload(pi->adapter))
- ifp->if_capabilities |= IFCAP_TOE4;
+ ifp->if_capabilities |= IFCAP_TOE;
#endif
ifp->if_capenable = T4_CAP_ENABLE;
ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_IP | CSUM_TSO |
@@ -918,6 +919,10 @@ cxgbe_detach(device_t dev)
while (IS_BUSY(sc))
mtx_sleep(&sc->flags, &sc->sc_lock, 0, "t4detach", 0);
SET_BUSY(sc);
+#ifdef INVARIANTS
+ sc->last_op = "t4detach";
+ sc->last_op_thr = curthread;
+#endif
ADAPTER_UNLOCK(sc);
if (pi->vlan_c)
@@ -939,7 +944,7 @@ cxgbe_detach(device_t dev)
ADAPTER_LOCK(sc);
CLR_BUSY(sc);
- wakeup_one(&sc->flags);
+ wakeup(&sc->flags);
ADAPTER_UNLOCK(sc);
return (0);
@@ -951,9 +956,10 @@ cxgbe_init(void *arg)
struct port_info *pi = arg;
struct adapter *sc = pi->adapter;
- ADAPTER_LOCK(sc);
- cxgbe_init_locked(pi); /* releases adapter lock */
- ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
+ if (begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4init") != 0)
+ return;
+ cxgbe_init_synchronized(pi);
+ end_synchronized_op(sc, 0);
}
static int
@@ -967,81 +973,56 @@ cxgbe_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data)
switch (cmd) {
case SIOCSIFMTU:
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
- if (rc) {
-fail:
- ADAPTER_UNLOCK(sc);
- return (rc);
- }
-
mtu = ifr->ifr_mtu;
- if ((mtu < ETHERMIN) || (mtu > ETHERMTU_JUMBO)) {
- rc = EINVAL;
- } else {
- ifp->if_mtu = mtu;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- t4_update_fl_bufsize(ifp);
- PORT_LOCK(pi);
- rc = update_mac_settings(pi, XGMAC_MTU);
- PORT_UNLOCK(pi);
- }
+ if ((mtu < ETHERMIN) || (mtu > ETHERMTU_JUMBO))
+ return (EINVAL);
+
+ rc = begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4mtu");
+ if (rc)
+ return (rc);
+ ifp->if_mtu = mtu;
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ t4_update_fl_bufsize(ifp);
+ rc = update_mac_settings(pi, XGMAC_MTU);
}
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, 0);
break;
case SIOCSIFFLAGS:
- ADAPTER_LOCK(sc);
- if (IS_DOOMED(pi)) {
- rc = ENXIO;
- goto fail;
- }
+ rc = begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4flg");
+ if (rc)
+ return (rc);
+
if (ifp->if_flags & IFF_UP) {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
flags = pi->if_flags;
if ((ifp->if_flags ^ flags) &
(IFF_PROMISC | IFF_ALLMULTI)) {
- if (IS_BUSY(sc)) {
- rc = EBUSY;
- goto fail;
- }
- PORT_LOCK(pi);
rc = update_mac_settings(pi,
XGMAC_PROMISC | XGMAC_ALLMULTI);
- PORT_UNLOCK(pi);
}
- ADAPTER_UNLOCK(sc);
} else
- rc = cxgbe_init_locked(pi);
+ rc = cxgbe_init_synchronized(pi);
pi->if_flags = ifp->if_flags;
} else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- rc = cxgbe_uninit_locked(pi);
- else
- ADAPTER_UNLOCK(sc);
-
- ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
+ rc = cxgbe_uninit_synchronized(pi);
+ end_synchronized_op(sc, 0);
break;
case SIOCADDMULTI:
- case SIOCDELMULTI: /* these two can be called with a mutex held :-( */
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
+ case SIOCDELMULTI: /* these two are called with a mutex held :-( */
+ rc = begin_synchronized_op(sc, pi, HOLD_LOCK, "t4multi");
if (rc)
- goto fail;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- PORT_LOCK(pi);
+ return (rc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
rc = update_mac_settings(pi, XGMAC_MCADDRS);
- PORT_UNLOCK(pi);
- }
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, LOCK_HELD);
break;
case SIOCSIFCAP:
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
+ rc = begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4cap");
if (rc)
- goto fail;
+ return (rc);
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
if (mask & IFCAP_TXCSUM) {
@@ -1122,11 +1103,8 @@ fail:
#endif
if (mask & IFCAP_VLAN_HWTAGGING) {
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- PORT_LOCK(pi);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
rc = update_mac_settings(pi, XGMAC_VLANEX);
- PORT_UNLOCK(pi);
- }
}
if (mask & IFCAP_VLAN_MTU) {
ifp->if_capenable ^= IFCAP_VLAN_MTU;
@@ -1141,7 +1119,8 @@ fail:
#ifdef VLAN_CAPABILITIES
VLAN_CAPABILITIES(ifp);
#endif
- ADAPTER_UNLOCK(sc);
+fail:
+ end_synchronized_op(sc, 0);
break;
case SIOCSIFMEDIA:
@@ -1625,21 +1604,28 @@ prep_firmware(struct adapter *sc)
/* Partition adapter resources as specified in the config file. */
if (sc->flags & MASTER_PF) {
- if (strncmp(t4_cfg_file, "default", sizeof(t4_cfg_file))) {
+ snprintf(sc->cfg_file, sizeof(sc->cfg_file), "%s",
+ pci_get_device(sc->dev) == 0x440a ? "uwire" : t4_cfg_file);
+ if (strncmp(sc->cfg_file, "default", sizeof(sc->cfg_file))) {
char s[32];
- snprintf(s, sizeof(s), "t4fw_cfg_%s", t4_cfg_file);
+ snprintf(s, sizeof(s), "t4fw_cfg_%s", sc->cfg_file);
cfg = firmware_get(s);
if (cfg == NULL) {
device_printf(sc->dev,
"unable to locate %s module, "
"will use default config file.\n", s);
+ snprintf(sc->cfg_file, sizeof(sc->cfg_file),
+ "%s", "default");
}
}
rc = partition_resources(sc, cfg ? cfg : default_cfg);
if (rc != 0)
goto done; /* error message displayed already */
+ } else {
+ snprintf(sc->cfg_file, sizeof(sc->cfg_file), "%s", "notme");
+ sc->cfcsum = (u_int)-1;
}
sc->flags |= FW_OK;
@@ -1887,7 +1873,9 @@ get_params__post_init(struct adapter *sc)
param[1] = FW_PARAM_PFVF(EQ_START);
param[2] = FW_PARAM_PFVF(FILTER_START);
param[3] = FW_PARAM_PFVF(FILTER_END);
- rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 4, param, val);
+ param[4] = FW_PARAM_PFVF(L2T_START);
+ param[5] = FW_PARAM_PFVF(L2T_END);
+ rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 6, param, val);
if (rc != 0) {
device_printf(sc->dev,
"failed to query parameters (post_init): %d.\n", rc);
@@ -1898,6 +1886,11 @@ get_params__post_init(struct adapter *sc)
sc->sge.eq_start = val[1];
sc->tids.ftid_base = val[2];
sc->tids.nftids = val[3] - val[2] + 1;
+ sc->vres.l2t.start = val[4];
+ sc->vres.l2t.size = val[5] - val[4] + 1;
+ KASSERT(sc->vres.l2t.size <= L2T_SIZE,
+ ("%s: L2 table size (%u) larger than expected (%u)",
+ __func__, sc->vres.l2t.size, L2T_SIZE));
/* get capabilites */
bzero(&caps, sizeof(caps));
@@ -2111,7 +2104,7 @@ update_mac_settings(struct port_info *pi, int flags)
struct adapter *sc = pi->adapter;
int mtu = -1, promisc = -1, allmulti = -1, vlanex = -1;
- PORT_LOCK_ASSERT_OWNED(pi);
+ ASSERT_SYNCHRONIZED_OP(sc);
KASSERT(flags, ("%s: not told what to update.", __func__));
if (flags & XGMAC_MTU)
@@ -2213,39 +2206,74 @@ mcfail:
return (rc);
}
-static int
-cxgbe_init_locked(struct port_info *pi)
+int
+begin_synchronized_op(struct adapter *sc, struct port_info *pi, int flags,
+ char *wmesg)
{
- struct adapter *sc = pi->adapter;
- int rc = 0;
+ int rc, pri;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
+#ifdef WITNESS
+ /* the caller thinks it's ok to sleep, but is it really? */
+ if (flags & SLEEP_OK)
+ pause("t4slptst", 1);
+#endif
- while (!IS_DOOMED(pi) && IS_BUSY(sc)) {
- if (mtx_sleep(&sc->flags, &sc->sc_lock, PCATCH, "t4init", 0)) {
+ if (INTR_OK)
+ pri = PCATCH;
+ else
+ pri = 0;
+
+ ADAPTER_LOCK(sc);
+ for (;;) {
+
+ if (pi && IS_DOOMED(pi)) {
+ rc = ENXIO;
+ goto done;
+ }
+
+ if (!IS_BUSY(sc)) {
+ rc = 0;
+ break;
+ }
+
+ if (!(flags & SLEEP_OK)) {
+ rc = EBUSY;
+ goto done;
+ }
+
+ if (mtx_sleep(&sc->flags, &sc->sc_lock, pri, wmesg, 0)) {
rc = EINTR;
goto done;
}
}
- if (IS_DOOMED(pi)) {
- rc = ENXIO;
- goto done;
- }
- KASSERT(!IS_BUSY(sc), ("%s: controller busy.", __func__));
- /* Give up the adapter lock, port init code can sleep. */
+ KASSERT(!IS_BUSY(sc), ("%s: controller busy.", __func__));
SET_BUSY(sc);
- ADAPTER_UNLOCK(sc);
-
- rc = cxgbe_init_synchronized(pi);
+#ifdef INVARIANTS
+ sc->last_op = wmesg;
+ sc->last_op_thr = curthread;
+#endif
done:
- ADAPTER_LOCK(sc);
+ if (!(flags & HOLD_LOCK) || rc)
+ ADAPTER_UNLOCK(sc);
+
+ return (rc);
+}
+
+void
+end_synchronized_op(struct adapter *sc, int flags)
+{
+
+ if (flags & LOCK_HELD)
+ ADAPTER_LOCK_ASSERT_OWNED(sc);
+ else
+ ADAPTER_LOCK(sc);
+
KASSERT(IS_BUSY(sc), ("%s: controller not busy.", __func__));
CLR_BUSY(sc);
- wakeup_one(&sc->flags);
+ wakeup(&sc->flags);
ADAPTER_UNLOCK(sc);
- return (rc);
}
static int
@@ -2255,7 +2283,7 @@ cxgbe_init_synchronized(struct port_info *pi)
struct ifnet *ifp = pi->ifp;
int rc = 0;
- ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
+ ASSERT_SYNCHRONIZED_OP(sc);
if (isset(&sc->open_device_map, pi->port_id)) {
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING,
@@ -2271,9 +2299,7 @@ cxgbe_init_synchronized(struct port_info *pi)
((rc = port_full_init(pi)) != 0))
return (rc); /* error message displayed already */
- PORT_LOCK(pi);
rc = update_mac_settings(pi, XGMAC_ALL);
- PORT_UNLOCK(pi);
if (rc)
goto done; /* error message displayed already */
@@ -2291,7 +2317,9 @@ cxgbe_init_synchronized(struct port_info *pi)
/* all ok */
setbit(&sc->open_device_map, pi->port_id);
+ PORT_LOCK(pi);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ PORT_UNLOCK(pi);
callout_reset(&pi->tick, hz, cxgbe_tick, pi);
done:
@@ -2301,39 +2329,6 @@ done:
return (rc);
}
-static int
-cxgbe_uninit_locked(struct port_info *pi)
-{
- struct adapter *sc = pi->adapter;
- int rc;
-
- ADAPTER_LOCK_ASSERT_OWNED(sc);
-
- while (!IS_DOOMED(pi) && IS_BUSY(sc)) {
- if (mtx_sleep(&sc->flags, &sc->sc_lock, PCATCH, "t4uninit", 0)) {
- rc = EINTR;
- goto done;
- }
- }
- if (IS_DOOMED(pi)) {
- rc = ENXIO;
- goto done;
- }
- KASSERT(!IS_BUSY(sc), ("%s: controller busy.", __func__));
- SET_BUSY(sc);
- ADAPTER_UNLOCK(sc);
-
- rc = cxgbe_uninit_synchronized(pi);
-
- ADAPTER_LOCK(sc);
- KASSERT(IS_BUSY(sc), ("%s: controller not busy.", __func__));
- CLR_BUSY(sc);
- wakeup_one(&sc->flags);
-done:
- ADAPTER_UNLOCK(sc);
- return (rc);
-}
-
/*
* Idempotent.
*/
@@ -2344,7 +2339,7 @@ cxgbe_uninit_synchronized(struct port_info *pi)
struct ifnet *ifp = pi->ifp;
int rc;
- ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
+ ASSERT_SYNCHRONIZED_OP(sc);
/*
* Disable the VI so that all its data in either direction is discarded
@@ -2360,7 +2355,9 @@ cxgbe_uninit_synchronized(struct port_info *pi)
}
clrbit(&sc->open_device_map, pi->port_id);
+ PORT_LOCK(pi);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ PORT_UNLOCK(pi);
pi->link_cfg.link_ok = 0;
pi->link_cfg.speed = 0;
@@ -2539,7 +2536,7 @@ port_full_init(struct port_info *pi)
struct sge_rxq *rxq;
int rc, i;
- ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
+ ASSERT_SYNCHRONIZED_OP(sc);
KASSERT((pi->flags & PORT_INIT_DONE) == 0,
("%s: PORT_INIT_DONE already", __func__));
@@ -3119,7 +3116,7 @@ t4_sysctls(struct adapter *sc)
CTLFLAG_RD, &sc->fw_version, 0, "firmware version");
SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "cf",
- CTLFLAG_RD, &t4_cfg_file, 0, "configuration file");
+ CTLFLAG_RD, &sc->cfg_file, 0, "configuration file");
SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "cfcsum", CTLFLAG_RD,
&sc->cfcsum, 0, "config file checksum");
@@ -3524,6 +3521,8 @@ sysctl_holdoff_tmr_idx(SYSCTL_HANDLER_ARGS)
struct port_info *pi = arg1;
struct adapter *sc = pi->adapter;
int idx, rc, i;
+ struct sge_rxq *rxq;
+ uint8_t v;
idx = pi->tmr_idx;
@@ -3534,25 +3533,23 @@ sysctl_holdoff_tmr_idx(SYSCTL_HANDLER_ARGS)
if (idx < 0 || idx >= SGE_NTIMERS)
return (EINVAL);
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
- if (rc == 0) {
- struct sge_rxq *rxq;
- uint8_t v;
+ rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4tmr");
+ if (rc)
+ return (rc);
- v = V_QINTR_TIMER_IDX(idx) | V_QINTR_CNT_EN(pi->pktc_idx != -1);
- for_each_rxq(pi, i, rxq) {
+ v = V_QINTR_TIMER_IDX(idx) | V_QINTR_CNT_EN(pi->pktc_idx != -1);
+ for_each_rxq(pi, i, rxq) {
#ifdef atomic_store_rel_8
- atomic_store_rel_8(&rxq->iq.intr_params, v);
+ atomic_store_rel_8(&rxq->iq.intr_params, v);
#else
- rxq->iq.intr_params = v;
+ rxq->iq.intr_params = v;
#endif
- }
- pi->tmr_idx = idx;
}
+ pi->tmr_idx = idx;
- ADAPTER_UNLOCK(sc);
- return (rc);
+ end_synchronized_op(sc, LOCK_HELD);
+ return (0);
}
static int
@@ -3571,15 +3568,17 @@ sysctl_holdoff_pktc_idx(SYSCTL_HANDLER_ARGS)
if (idx < -1 || idx >= SGE_NCOUNTERS)
return (EINVAL);
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
- if (rc == 0 && pi->flags & PORT_INIT_DONE)
- rc = EBUSY; /* cannot be changed once the queues are created */
+ rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4pktc");
+ if (rc)
+ return (rc);
- if (rc == 0)
+ if (pi->flags & PORT_INIT_DONE)
+ rc = EBUSY; /* cannot be changed once the queues are created */
+ else
pi->pktc_idx = idx;
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, LOCK_HELD);
return (rc);
}
@@ -3599,15 +3598,17 @@ sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS)
if (qsize < 128 || (qsize & 7))
return (EINVAL);
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
- if (rc == 0 && pi->flags & PORT_INIT_DONE)
- rc = EBUSY; /* cannot be changed once the queues are created */
+ rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4rxqs");
+ if (rc)
+ return (rc);
- if (rc == 0)
+ if (pi->flags & PORT_INIT_DONE)
+ rc = EBUSY; /* cannot be changed once the queues are created */
+ else
pi->qsize_rxq = qsize;
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, LOCK_HELD);
return (rc);
}
@@ -3624,18 +3625,21 @@ sysctl_qsize_txq(SYSCTL_HANDLER_ARGS)
if (rc != 0 || req->newptr == NULL)
return (rc);
- if (qsize < 128)
+ /* bufring size must be powerof2 */
+ if (qsize < 128 || !powerof2(qsize))
return (EINVAL);
- ADAPTER_LOCK(sc);
- rc = IS_DOOMED(pi) ? ENXIO : (IS_BUSY(sc) ? EBUSY : 0);
- if (rc == 0 && pi->flags & PORT_INIT_DONE)
- rc = EBUSY; /* cannot be changed once the queues are created */
+ rc = begin_synchronized_op(sc, pi, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4txqs");
+ if (rc)
+ return (rc);
- if (rc == 0)
+ if (pi->flags & PORT_INIT_DONE)
+ rc = EBUSY; /* cannot be changed once the queues are created */
+ else
pi->qsize_txq = qsize;
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, LOCK_HELD);
return (rc);
}
@@ -4674,8 +4678,14 @@ fspec_to_fconf(struct t4_filter_specification *fs)
static int
get_filter_mode(struct adapter *sc, uint32_t *mode)
{
+ int rc;
uint32_t fconf;
+ rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4getfm");
+ if (rc)
+ return (rc);
+
t4_read_indirect(sc, A_TP_PIO_ADDR, A_TP_PIO_DATA, &fconf, 1,
A_TP_VLAN_PRI_MAP);
@@ -4687,6 +4697,7 @@ get_filter_mode(struct adapter *sc, uint32_t *mode)
*mode = fconf_to_mode(sc->filter_mode);
+ end_synchronized_op(sc, LOCK_HELD);
return (0);
}
@@ -4698,11 +4709,10 @@ set_filter_mode(struct adapter *sc, uint32_t mode)
fconf = mode_to_fconf(mode);
- ADAPTER_LOCK(sc);
- if (IS_BUSY(sc)) {
- rc = EAGAIN;
- goto done;
- }
+ rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4setfm");
+ if (rc)
+ return (rc);
if (sc->tids.ftids_in_use > 0) {
rc = EBUSY;
@@ -4725,7 +4735,7 @@ set_filter_mode(struct adapter *sc, uint32_t mode)
#endif
done:
- ADAPTER_UNLOCK(sc);
+ end_synchronized_op(sc, LOCK_HELD);
return (rc);
}
@@ -4746,18 +4756,18 @@ get_filter_hits(struct adapter *sc, uint32_t fid)
static int
get_filter(struct adapter *sc, struct t4_filter *t)
{
- int i, nfilters = sc->tids.nftids;
+ int i, rc, nfilters = sc->tids.nftids;
struct filter_entry *f;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
-
- if (IS_BUSY(sc))
- return (EAGAIN);
+ rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK,
+ "t4getf");
+ if (rc)
+ return (rc);
if (sc->tids.ftids_in_use == 0 || sc->tids.ftid_tab == NULL ||
t->idx >= nfilters) {
t->idx = 0xffffffff;
- return (0);
+ goto done;
}
f = &sc->tids.ftid_tab[t->idx];
@@ -4772,11 +4782,13 @@ get_filter(struct adapter *sc, struct t4_filter *t)
t->hits = UINT64_MAX;
t->fs = f->fs;
- return (0);
+ goto done;
}
}
t->idx = 0xffffffff;
+done:
+ end_synchronized_op(sc, LOCK_HELD);
return (0);
}
@@ -4785,40 +4797,58 @@ set_filter(struct adapter *sc, struct t4_filter *t)
{
unsigned int nfilters, nports;
struct filter_entry *f;
- int i;
+ int i, rc;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
+ rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4setf");
+ if (rc)
+ return (rc);
nfilters = sc->tids.nftids;
nports = sc->params.nports;
- if (nfilters == 0)
- return (ENOTSUP);
+ if (nfilters == 0) {
+ rc = ENOTSUP;
+ goto done;
+ }
- if (!(sc->flags & FULL_INIT_DONE))
- return (EAGAIN);
+ if (!(sc->flags & FULL_INIT_DONE)) {
+ rc = EAGAIN;
+ goto done;
+ }
- if (t->idx >= nfilters)
- return (EINVAL);
+ if (t->idx >= nfilters) {
+ rc = EINVAL;
+ goto done;
+ }
/* Validate against the global filter mode */
- if ((sc->filter_mode | fspec_to_fconf(&t->fs)) != sc->filter_mode)
- return (E2BIG);
+ if ((sc->filter_mode | fspec_to_fconf(&t->fs)) != sc->filter_mode) {
+ rc = E2BIG;
+ goto done;
+ }
- if (t->fs.action == FILTER_SWITCH && t->fs.eport >= nports)
- return (EINVAL);
+ if (t->fs.action == FILTER_SWITCH && t->fs.eport >= nports) {
+ rc = EINVAL;
+ goto done;
+ }
- if (t->fs.val.iport >= nports)
- return (EINVAL);
+ if (t->fs.val.iport >= nports) {
+ rc = EINVAL;
+ goto done;
+ }
/* Can't specify an iq if not steering to it */
- if (!t->fs.dirsteer && t->fs.iq)
- return (EINVAL);
+ if (!t->fs.dirsteer && t->fs.iq) {
+ rc = EINVAL;
+ goto done;
+ }
/* IPv6 filter idx must be 4 aligned */
if (t->fs.type == 1 &&
- ((t->idx & 0x3) || t->idx + 4 >= nfilters))
- return (EINVAL);
+ ((t->idx & 0x3) || t->idx + 4 >= nfilters)) {
+ rc = EINVAL;
+ goto done;
+ }
if (sc->tids.ftid_tab == NULL) {
KASSERT(sc->tids.ftids_in_use == 0,
@@ -4827,17 +4857,24 @@ set_filter(struct adapter *sc, struct t4_filter *t)
sc->tids.ftid_tab = malloc(sizeof (struct filter_entry) *
nfilters, M_CXGBE, M_NOWAIT | M_ZERO);
- if (sc->tids.ftid_tab == NULL)
- return (ENOMEM);
+ if (sc->tids.ftid_tab == NULL) {
+ rc = ENOMEM;
+ goto done;
+ }
+ mtx_init(&sc->tids.ftid_lock, "T4 filters", 0, MTX_DEF);
}
for (i = 0; i < 4; i++) {
f = &sc->tids.ftid_tab[t->idx + i];
- if (f->pending || f->valid)
- return (EBUSY);
- if (f->locked)
- return (EPERM);
+ if (f->pending || f->valid) {
+ rc = EBUSY;
+ goto done;
+ }
+ if (f->locked) {
+ rc = EPERM;
+ goto done;
+ }
if (t->fs.type == 0)
break;
@@ -4846,7 +4883,27 @@ set_filter(struct adapter *sc, struct t4_filter *t)
f = &sc->tids.ftid_tab[t->idx];
f->fs = t->fs;
- return set_filter_wr(sc, t->idx);
+ rc = set_filter_wr(sc, t->idx);
+done:
+ end_synchronized_op(sc, 0);
+
+ if (rc == 0) {
+ mtx_lock(&sc->tids.ftid_lock);
+ for (;;) {
+ if (f->pending == 0) {
+ rc = f->valid ? 0 : EIO;
+ break;
+ }
+
+ if (mtx_sleep(&sc->tids.ftid_tab, &sc->tids.ftid_lock,
+ PCATCH, "t4setfw", 0)) {
+ rc = EINPROGRESS;
+ break;
+ }
+ }
+ mtx_unlock(&sc->tids.ftid_lock);
+ }
+ return (rc);
}
static int
@@ -4854,37 +4911,67 @@ del_filter(struct adapter *sc, struct t4_filter *t)
{
unsigned int nfilters;
struct filter_entry *f;
+ int rc;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
-
- if (IS_BUSY(sc))
- return (EAGAIN);
+ rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4delf");
+ if (rc)
+ return (rc);
nfilters = sc->tids.nftids;
- if (nfilters == 0)
- return (ENOTSUP);
+ if (nfilters == 0) {
+ rc = ENOTSUP;
+ goto done;
+ }
if (sc->tids.ftid_tab == NULL || sc->tids.ftids_in_use == 0 ||
- t->idx >= nfilters)
- return (EINVAL);
+ t->idx >= nfilters) {
+ rc = EINVAL;
+ goto done;
+ }
- if (!(sc->flags & FULL_INIT_DONE))
- return (EAGAIN);
+ if (!(sc->flags & FULL_INIT_DONE)) {
+ rc = EAGAIN;
+ goto done;
+ }
f = &sc->tids.ftid_tab[t->idx];
- if (f->pending)
- return (EBUSY);
- if (f->locked)
- return (EPERM);
+ if (f->pending) {
+ rc = EBUSY;
+ goto done;
+ }
+ if (f->locked) {
+ rc = EPERM;
+ goto done;
+ }
if (f->valid) {
t->fs = f->fs; /* extra info for the caller */
- return del_filter_wr(sc, t->idx);
+ rc = del_filter_wr(sc, t->idx);
}
- return (0);
+done:
+ end_synchronized_op(sc, 0);
+
+ if (rc == 0) {
+ mtx_lock(&sc->tids.ftid_lock);
+ for (;;) {
+ if (f->pending == 0) {
+ rc = f->valid ? EIO : 0;
+ break;
+ }
+
+ if (mtx_sleep(&sc->tids.ftid_tab, &sc->tids.ftid_lock,
+ PCATCH, "t4delfw", 0)) {
+ rc = EINPROGRESS;
+ break;
+ }
+ }
+ mtx_unlock(&sc->tids.ftid_lock);
+ }
+
+ return (rc);
}
static void
@@ -4904,7 +4991,7 @@ set_filter_wr(struct adapter *sc, int fidx)
struct fw_filter_wr *fwr;
unsigned int ftid;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
+ ASSERT_SYNCHRONIZED_OP(sc);
if (f->fs.newdmac || f->fs.newvlan) {
/* This filter needs an L2T entry; allocate one. */
@@ -5007,8 +5094,6 @@ del_filter_wr(struct adapter *sc, int fidx)
struct fw_filter_wr *fwr;
unsigned int ftid;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
-
ftid = sc->tids.ftid_base + fidx;
wr = alloc_wrqe(sizeof(*fwr), &sc->sge.mgmtq);
@@ -5039,8 +5124,10 @@ t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
unsigned int rc = G_COOKIE(rpl->cookie);
struct filter_entry *f = &sc->tids.ftid_tab[idx];
- ADAPTER_LOCK(sc);
+ mtx_lock(&sc->tids.ftid_lock);
if (rc == FW_FILTER_WR_FLT_ADDED) {
+ KASSERT(f->pending, ("%s: filter[%u] isn't pending.",
+ __func__, idx));
f->smtidx = (be64toh(rpl->oldval) >> 24) & 0xff;
f->pending = 0; /* asynchronous setup completed */
f->valid = 1;
@@ -5055,7 +5142,8 @@ t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
clear_filter(f);
sc->tids.ftids_in_use--;
}
- ADAPTER_UNLOCK(sc);
+ wakeup(&sc->tids.ftid_tab);
+ mtx_unlock(&sc->tids.ftid_lock);
}
return (0);
@@ -5064,29 +5152,63 @@ t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
static int
get_sge_context(struct adapter *sc, struct t4_sge_context *cntxt)
{
- int rc = EINVAL;
+ int rc;
if (cntxt->cid > M_CTXTQID)
- return (rc);
+ return (EINVAL);
if (cntxt->mem_id != CTXT_EGRESS && cntxt->mem_id != CTXT_INGRESS &&
cntxt->mem_id != CTXT_FLM && cntxt->mem_id != CTXT_CNM)
- return (rc);
+ return (EINVAL);
if (sc->flags & FW_OK) {
- ADAPTER_LOCK(sc); /* Avoid parallel t4_wr_mbox */
- rc = -t4_sge_ctxt_rd(sc, sc->mbox, cntxt->cid, cntxt->mem_id,
- &cntxt->data[0]);
- ADAPTER_UNLOCK(sc);
+ rc = begin_synchronized_op(sc, NULL, HOLD_LOCK, "t4ctxt");
+ if (rc == 0) {
+ rc = -t4_sge_ctxt_rd(sc, sc->mbox, cntxt->cid,
+ cntxt->mem_id, &cntxt->data[0]);
+ end_synchronized_op(sc, LOCK_HELD);
+ if (rc == 0)
+ return (0);
+ }
}
- if (rc != 0) {
- /* Read via firmware failed or wasn't even attempted */
+ /*
+ * Read via firmware failed or wasn't even attempted. Read directly via
+ * the backdoor.
+ */
+ rc = -t4_sge_ctxt_rd_bd(sc, cntxt->cid, cntxt->mem_id,
+ &cntxt->data[0]);
+ return (rc);
+}
+
+static int
+load_fw(struct adapter *sc, struct t4_data *fw)
+{
+ int rc;
+ uint8_t *fw_data;
+
+ rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4ldfw");
+ if (rc)
+ return (rc);
+
+ if (sc->flags & FULL_INIT_DONE) {
+ rc = EBUSY;
+ goto done;
+ }
- rc = -t4_sge_ctxt_rd_bd(sc, cntxt->cid, cntxt->mem_id,
- &cntxt->data[0]);
+ fw_data = malloc(fw->len, M_CXGBE, M_WAITOK);
+ if (fw_data == NULL) {
+ rc = ENOMEM;
+ goto done;
}
+ rc = copyin(fw->data, fw_data, fw->len);
+ if (rc == 0)
+ rc = -t4_load_fw(sc, fw_data, fw->len);
+
+ free(fw_data, M_CXGBE);
+done:
+ end_synchronized_op(sc, 0);
return (rc);
}
@@ -5173,8 +5295,6 @@ read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd)
{
int rc;
- ADAPTER_LOCK_ASSERT_OWNED(sc); /* for mbox */
-
if (i2cd->len == 0 || i2cd->port_id >= sc->params.nports)
return (EINVAL);
@@ -5183,8 +5303,12 @@ read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd)
return (ENOTSUP);
}
+ rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4i2crd");
+ if (rc)
+ return (rc);
rc = -t4_i2c_rd(sc, sc->mbox, i2cd->port_id, i2cd->dev_addr,
i2cd->offset, &i2cd->data[0]);
+ end_synchronized_op(sc, 0);
return (rc);
}
@@ -5354,56 +5478,78 @@ t4_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag,
rc = set_filter_mode(sc, *(uint32_t *)data);
break;
case CHELSIO_T4_GET_FILTER:
- ADAPTER_LOCK(sc);
rc = get_filter(sc, (struct t4_filter *)data);
- ADAPTER_UNLOCK(sc);
break;
case CHELSIO_T4_SET_FILTER:
- ADAPTER_LOCK(sc);
rc = set_filter(sc, (struct t4_filter *)data);
- ADAPTER_UNLOCK(sc);
break;
case CHELSIO_T4_DEL_FILTER:
- ADAPTER_LOCK(sc);
rc = del_filter(sc, (struct t4_filter *)data);
- ADAPTER_UNLOCK(sc);
break;
case CHELSIO_T4_GET_SGE_CONTEXT:
rc = get_sge_context(sc, (struct t4_sge_context *)data);
break;
- case CHELSIO_T4_LOAD_FW: {
- struct t4_data *fw = (struct t4_data *)data;
- uint8_t *fw_data;
-
- if (sc->flags & FULL_INIT_DONE)
- return (EBUSY);
-
- fw_data = malloc(fw->len, M_CXGBE, M_NOWAIT);
- if (fw_data == NULL)
- return (ENOMEM);
-
- rc = copyin(fw->data, fw_data, fw->len);
- if (rc == 0)
- rc = -t4_load_fw(sc, fw_data, fw->len);
-
- free(fw_data, M_CXGBE);
+ case CHELSIO_T4_LOAD_FW:
+ rc = load_fw(sc, (struct t4_data *)data);
break;
- }
case CHELSIO_T4_GET_MEM:
rc = read_card_mem(sc, (struct t4_mem_range *)data);
break;
case CHELSIO_T4_GET_I2C:
- ADAPTER_LOCK(sc);
rc = read_i2c(sc, (struct t4_i2c_data *)data);
- ADAPTER_UNLOCK(sc);
break;
case CHELSIO_T4_CLEAR_STATS: {
+ int i;
u_int port_id = *(uint32_t *)data;
+ struct port_info *pi;
if (port_id >= sc->params.nports)
return (EINVAL);
+ /* MAC stats */
t4_clr_port_stats(sc, port_id);
+
+ pi = sc->port[port_id];
+ if (pi->flags & PORT_INIT_DONE) {
+ struct sge_rxq *rxq;
+ struct sge_txq *txq;
+ struct sge_wrq *wrq;
+
+ for_each_rxq(pi, i, rxq) {
+#if defined(INET) || defined(INET6)
+ rxq->lro.lro_queued = 0;
+ rxq->lro.lro_flushed = 0;
+#endif
+ rxq->rxcsum = 0;
+ rxq->vlan_extraction = 0;
+ }
+
+ for_each_txq(pi, i, txq) {
+ txq->txcsum = 0;
+ txq->tso_wrs = 0;
+ txq->vlan_insertion = 0;
+ txq->imm_wrs = 0;
+ txq->sgl_wrs = 0;
+ txq->txpkt_wrs = 0;
+ txq->txpkts_wrs = 0;
+ txq->txpkts_pkts = 0;
+ txq->br->br_drops = 0;
+ txq->no_dmamap = 0;
+ txq->no_desc = 0;
+ }
+
+#ifdef TCP_OFFLOAD
+ /* nothing to clear for each ofld_rxq */
+
+ for_each_ofld_txq(pi, i, wrq) {
+ wrq->tx_wrs = 0;
+ wrq->no_desc = 0;
+ }
+#endif
+ wrq = &sc->sge.ctrlq[pi->port_id];
+ wrq->tx_wrs = 0;
+ wrq->no_desc = 0;
+ }
break;
}
default:
@@ -5420,16 +5566,16 @@ toe_capability(struct port_info *pi, int enable)
int rc;
struct adapter *sc = pi->adapter;
- ADAPTER_LOCK_ASSERT_OWNED(sc);
+ ASSERT_SYNCHRONIZED_OP(sc);
if (!is_offload(sc))
return (ENODEV);
if (enable) {
if (!(sc->flags & FULL_INIT_DONE)) {
- log(LOG_WARNING,
- "You must enable a cxgbe interface first\n");
- return (EAGAIN);
+ rc = cxgbe_init_synchronized(pi);
+ if (rc)
+ return (rc);
}
if (isset(&sc->offload_map, pi->port_id))
@@ -5518,6 +5664,8 @@ t4_activate_uld(struct adapter *sc, int id)
int rc = EAGAIN;
struct uld_info *ui;
+ ASSERT_SYNCHRONIZED_OP(sc);
+
mtx_lock(&t4_uld_list_lock);
SLIST_FOREACH(ui, &t4_uld_list, link) {
@@ -5540,6 +5688,8 @@ t4_deactivate_uld(struct adapter *sc, int id)
int rc = EINVAL;
struct uld_info *ui;
+ ASSERT_SYNCHRONIZED_OP(sc);
+
mtx_lock(&t4_uld_list_lock);
SLIST_FOREACH(ui, &t4_uld_list, link) {
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index 62d9eb3..62ceec4 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -2362,6 +2362,8 @@ alloc_txq(struct port_info *pi, struct sge_txq *txq, int idx,
SYSCTL_ADD_UQUAD(&pi->ctx, children, OID_AUTO, "txpkts_pkts", CTLFLAG_RD,
&txq->txpkts_pkts, "# of frames tx'd using txpkts work requests");
+ SYSCTL_ADD_UQUAD(&pi->ctx, children, OID_AUTO, "br_drops", CTLFLAG_RD,
+ &txq->br->br_drops, "# of drops in the buf_ring for this queue");
SYSCTL_ADD_UINT(&pi->ctx, children, OID_AUTO, "no_dmamap", CTLFLAG_RD,
&txq->no_dmamap, 0, "# of times txq ran out of DMA maps");
SYSCTL_ADD_UINT(&pi->ctx, children, OID_AUTO, "no_desc", CTLFLAG_RD,
diff --git a/sys/dev/cxgbe/tom/t4_connect.c b/sys/dev/cxgbe/tom/t4_connect.c
index 8d36b1e..17ed1d3 100644
--- a/sys/dev/cxgbe/tom/t4_connect.c
+++ b/sys/dev/cxgbe/tom/t4_connect.c
@@ -29,6 +29,7 @@
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
+#include "opt_inet6.h"
#ifdef TCP_OFFLOAD
#include <sys/param.h>
@@ -195,7 +196,7 @@ do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
CTR3(KTR_CXGBE, "%s: atid %u, status %u ", __func__, atid, status);
/* Ignore negative advice */
- if (status == CPL_ERR_RTX_NEG_ADVICE)
+ if (negative_advice(status))
return (0);
free_atid(sc, atid);
@@ -220,10 +221,9 @@ do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
* Options2 for active open.
*/
static uint32_t
-calc_opt2a(struct socket *so)
+calc_opt2a(struct socket *so, struct toepcb *toep)
{
struct tcpcb *tp = so_sototcpcb(so);
- struct toepcb *toep = tp->t_toe;
struct port_info *pi = toep->port;
struct adapter *sc = pi->adapter;
uint32_t opt2 = 0;
@@ -260,6 +260,12 @@ t4_init_connect_cpl_handlers(struct adapter *sc)
t4_register_cpl_handler(sc, CPL_ACT_OPEN_RPL, do_act_open_rpl);
}
+#define DONT_OFFLOAD_ACTIVE_OPEN(x) do { \
+ reason = __LINE__; \
+ rc = (x); \
+ goto failed; \
+} while (0)
+
/*
* active open (soconnect).
*
@@ -275,20 +281,19 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
struct sockaddr *nam)
{
struct adapter *sc = tod->tod_softc;
+ struct tom_data *td = tod_td(tod);
struct toepcb *toep = NULL;
struct wrqe *wr = NULL;
- struct cpl_act_open_req *cpl;
- struct l2t_entry *e = NULL;
struct ifnet *rt_ifp = rt->rt_ifp;
struct port_info *pi;
- int atid = -1, mtu_idx, rscale, qid_atid, rc = ENOMEM;
+ int mtu_idx, rscale, qid_atid, rc, isipv6;
struct inpcb *inp = sotoinpcb(so);
struct tcpcb *tp = intotcpcb(inp);
+ int reason;
INP_WLOCK_ASSERT(inp);
-
- if (nam->sa_family != AF_INET)
- CXGBE_UNIMPLEMENTED("IPv6 connect");
+ KASSERT(nam->sa_family == AF_INET || nam->sa_family == AF_INET6,
+ ("%s: dest addr %p has family %u", __func__, nam, nam->sa_family));
if (rt_ifp->if_type == IFT_ETHER)
pi = rt_ifp->if_softc;
@@ -297,30 +302,29 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
pi = ifp->if_softc;
} else if (rt_ifp->if_type == IFT_IEEE8023ADLAG)
- return (ENOSYS); /* XXX: implement lagg support */
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOSYS); /* XXX: implement lagg+TOE */
else
- return (ENOTSUP);
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOTSUP);
toep = alloc_toepcb(pi, -1, -1, M_NOWAIT);
if (toep == NULL)
- goto failed;
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM);
- atid = alloc_atid(sc, toep);
- if (atid < 0)
- goto failed;
+ toep->tid = alloc_atid(sc, toep);
+ if (toep->tid < 0)
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM);
- e = t4_l2t_get(pi, rt_ifp,
+ toep->l2te = t4_l2t_get(pi, rt_ifp,
rt->rt_flags & RTF_GATEWAY ? rt->rt_gateway : nam);
- if (e == NULL)
- goto failed;
+ if (toep->l2te == NULL)
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM);
- wr = alloc_wrqe(sizeof(*cpl), toep->ctrlq);
+ isipv6 = nam->sa_family == AF_INET6;
+ wr = alloc_wrqe(isipv6 ? sizeof(struct cpl_act_open_req6) :
+ sizeof(struct cpl_act_open_req), toep->ctrlq);
if (wr == NULL)
- goto failed;
- cpl = wrtod(wr);
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOMEM);
- toep->tid = atid;
- toep->l2te = e;
if (sc->tt.ddp && (so->so_options & SO_NO_DDP) == 0)
set_tcpddp_ulp_mode(toep);
else
@@ -330,8 +334,6 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
toep->rx_credits = min(select_rcv_wnd(so) >> 10, M_RCV_BUFSIZ);
SOCKBUF_UNLOCK(&so->so_rcv);
- offload_socket(so, toep);
-
/*
* The kernel sets request_r_scale based on sb_max whereas we need to
* take hardware's MAX_RCV_WND into account too. This is normally a
@@ -342,39 +344,78 @@ t4_connect(struct toedev *tod, struct socket *so, struct rtentry *rt,
else
rscale = 0;
mtu_idx = find_best_mtu_idx(sc, &inp->inp_inc, 0);
- qid_atid = (toep->ofld_rxq->iq.abs_id << 14) | atid;
-
- INIT_TP_WR(cpl, 0);
- OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, qid_atid));
- inp_4tuple_get(inp, &cpl->local_ip, &cpl->local_port, &cpl->peer_ip,
- &cpl->peer_port);
- cpl->opt0 = calc_opt0(so, pi, e, mtu_idx, rscale, toep->rx_credits,
- toep->ulp_mode);
- cpl->params = select_ntuple(pi, e, sc->filter_mode);
- cpl->opt2 = calc_opt2a(so);
+ qid_atid = (toep->ofld_rxq->iq.abs_id << 14) | toep->tid;
+
+ if (isipv6) {
+ struct cpl_act_open_req6 *cpl = wrtod(wr);
+
+ if ((inp->inp_vflag & INP_IPV6) == 0) {
+ /* XXX think about this a bit more */
+ log(LOG_ERR,
+ "%s: time to think about AF_INET6 + vflag 0x%x.\n",
+ __func__, inp->inp_vflag);
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOTSUP);
+ }
+
+ toep->ce = hold_lip(td, &inp->in6p_laddr);
+ if (toep->ce == NULL)
+ DONT_OFFLOAD_ACTIVE_OPEN(ENOENT);
+
+ INIT_TP_WR(cpl, 0);
+ OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ6,
+ qid_atid));
+
+ cpl->local_port = inp->inp_lport;
+ cpl->local_ip_hi = *(uint64_t *)&inp->in6p_laddr.s6_addr[0];
+ cpl->local_ip_lo = *(uint64_t *)&inp->in6p_laddr.s6_addr[8];
+ cpl->peer_port = inp->inp_fport;
+ cpl->peer_ip_hi = *(uint64_t *)&inp->in6p_faddr.s6_addr[0];
+ cpl->peer_ip_lo = *(uint64_t *)&inp->in6p_faddr.s6_addr[8];
+ cpl->opt0 = calc_opt0(so, pi, toep->l2te, mtu_idx, rscale,
+ toep->rx_credits, toep->ulp_mode);
+ cpl->params = select_ntuple(pi, toep->l2te, sc->filter_mode);
+ cpl->opt2 = calc_opt2a(so, toep);
+ } else {
+ struct cpl_act_open_req *cpl = wrtod(wr);
+
+ INIT_TP_WR(cpl, 0);
+ OPCODE_TID(cpl) = htobe32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+ qid_atid));
+ inp_4tuple_get(inp, &cpl->local_ip, &cpl->local_port,
+ &cpl->peer_ip, &cpl->peer_port);
+ cpl->opt0 = calc_opt0(so, pi, toep->l2te, mtu_idx, rscale,
+ toep->rx_credits, toep->ulp_mode);
+ cpl->params = select_ntuple(pi, toep->l2te, sc->filter_mode);
+ cpl->opt2 = calc_opt2a(so, toep);
+ }
CTR5(KTR_CXGBE, "%s: atid %u (%s), toep %p, inp %p", __func__,
toep->tid, tcpstates[tp->t_state], toep, inp);
- rc = t4_l2t_send(sc, wr, e);
+ offload_socket(so, toep);
+ rc = t4_l2t_send(sc, wr, toep->l2te);
if (rc == 0) {
toep->flags |= TPF_CPL_PENDING;
return (0);
}
undo_offload_socket(so);
+ reason = __LINE__;
failed:
- CTR5(KTR_CXGBE, "%s: FAILED, atid %d, toep %p, l2te %p, wr %p",
- __func__, atid, toep, e, wr);
+ CTR3(KTR_CXGBE, "%s: not offloading (%d), rc %d", __func__, reason, rc);
- if (e)
- t4_l2t_release(e);
if (wr)
free_wrqe(wr);
- if (atid >= 0)
- free_atid(sc, atid);
- if (toep)
+
+ if (toep) {
+ if (toep->tid >= 0)
+ free_atid(sc, toep->tid);
+ if (toep->l2te)
+ t4_l2t_release(toep->l2te);
+ if (toep->ce)
+ release_lip(td, toep->ce);
free_toepcb(toep);
+ }
return (rc);
}
diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c
index 6ae1ec4..9aead9f 100644
--- a/sys/dev/cxgbe/tom/t4_cpl_io.c
+++ b/sys/dev/cxgbe/tom/t4_cpl_io.c
@@ -1018,8 +1018,7 @@ do_abort_req(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
- if (cpl->status == CPL_ERR_RTX_NEG_ADVICE ||
- cpl->status == CPL_ERR_PERSIST_NEG_ADVICE) {
+ if (negative_advice(cpl->status)) {
CTR4(KTR_CXGBE, "%s: negative advice %d for tid %d (0x%x)",
__func__, cpl->status, tid, toep->flags);
return (0); /* Ignore negative advice */
diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c
index 523f7f3..b80702d 100644
--- a/sys/dev/cxgbe/tom/t4_listen.c
+++ b/sys/dev/cxgbe/tom/t4_listen.c
@@ -29,6 +29,7 @@
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
+#include "opt_inet6.h"
#ifdef TCP_OFFLOAD
#include <sys/param.h>
@@ -50,6 +51,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet6/scope6_var.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#define TCPSTATES
@@ -63,9 +66,9 @@ __FBSDID("$FreeBSD$");
#include "tom/t4_tom.h"
/* stid services */
-static int alloc_stid(struct adapter *, void *);
-static void *lookup_stid(struct adapter *, int);
-static void free_stid(struct adapter *, int);
+static int alloc_stid(struct adapter *, struct listen_ctx *, int);
+static struct listen_ctx *lookup_stid(struct adapter *, int);
+static void free_stid(struct adapter *, struct listen_ctx *);
/* lctx services */
static struct listen_ctx *alloc_lctx(struct adapter *, struct inpcb *,
@@ -81,45 +84,105 @@ static inline void save_qids_in_mbuf(struct mbuf *, struct port_info *);
static inline void get_qids_from_mbuf(struct mbuf *m, int *, int *);
static void send_reset_synqe(struct toedev *, struct synq_entry *);
-/* XXX: won't work for IPv6 */
static int
-alloc_stid(struct adapter *sc, void *ctx)
+alloc_stid(struct adapter *sc, struct listen_ctx *lctx, int isipv6)
{
struct tid_info *t = &sc->tids;
- int stid = -1;
+ u_int stid, n, f, mask;
+ struct stid_region *sr = &lctx->stid_region;
+
+ /*
+ * An IPv6 server needs 2 naturally aligned stids (1 stid = 4 cells) in
+ * the TCAM. The start of the stid region is properly aligned (the chip
+ * requires each region to be 128-cell aligned).
+ */
+ n = isipv6 ? 2 : 1;
+ mask = n - 1;
+ KASSERT((t->stid_base & mask) == 0 && (t->nstids & mask) == 0,
+ ("%s: stid region (%u, %u) not properly aligned. n = %u",
+ __func__, t->stid_base, t->nstids, n));
mtx_lock(&t->stid_lock);
- if (t->sfree) {
- union serv_entry *p = t->sfree;
-
- stid = p - t->stid_tab;
- stid += t->stid_base;
- t->sfree = p->next;
- p->data = ctx;
- t->stids_in_use++;
+ if (n > t->nstids - t->stids_in_use) {
+ mtx_unlock(&t->stid_lock);
+ return (-1);
}
+
+ if (t->nstids_free_head >= n) {
+ /*
+ * This allocation will definitely succeed because the region
+ * starts at a good alignment and we just checked we have enough
+ * stids free.
+ */
+ f = t->nstids_free_head & mask;
+ t->nstids_free_head -= n + f;
+ stid = t->nstids_free_head;
+ TAILQ_INSERT_HEAD(&t->stids, sr, link);
+ } else {
+ struct stid_region *s;
+
+ stid = t->nstids_free_head;
+ TAILQ_FOREACH(s, &t->stids, link) {
+ stid += s->used + s->free;
+ f = stid & mask;
+ if (n <= s->free - f) {
+ stid -= n + f;
+ s->free -= n + f;
+ TAILQ_INSERT_AFTER(&t->stids, s, sr, link);
+ goto allocated;
+ }
+ }
+
+ if (__predict_false(stid != t->nstids)) {
+ panic("%s: stids TAILQ (%p) corrupt."
+ " At %d instead of %d at the end of the queue.",
+ __func__, &t->stids, stid, t->nstids);
+ }
+
+ mtx_unlock(&t->stid_lock);
+ return (-1);
+ }
+
+allocated:
+ sr->used = n;
+ sr->free = f;
+ t->stids_in_use += n;
+ t->stid_tab[stid] = lctx;
mtx_unlock(&t->stid_lock);
- return (stid);
+
+ KASSERT(((stid + t->stid_base) & mask) == 0,
+ ("%s: EDOOFUS.", __func__));
+ return (stid + t->stid_base);
}
-static void *
+static struct listen_ctx *
lookup_stid(struct adapter *sc, int stid)
{
struct tid_info *t = &sc->tids;
- return (t->stid_tab[stid - t->stid_base].data);
+ return (t->stid_tab[stid - t->stid_base]);
}
static void
-free_stid(struct adapter *sc, int stid)
+free_stid(struct adapter *sc, struct listen_ctx *lctx)
{
struct tid_info *t = &sc->tids;
- union serv_entry *p = &t->stid_tab[stid - t->stid_base];
+ struct stid_region *sr = &lctx->stid_region;
+ struct stid_region *s;
+
+ KASSERT(sr->used > 0, ("%s: nonsense free (%d)", __func__, sr->used));
mtx_lock(&t->stid_lock);
- p->next = t->sfree;
- t->sfree = p;
- t->stids_in_use--;
+ s = TAILQ_PREV(sr, stid_head, link);
+ if (s != NULL)
+ s->free += sr->used + sr->free;
+ else
+ t->nstids_free_head += sr->used + sr->free;
+ KASSERT(t->stids_in_use >= sr->used,
+ ("%s: stids_in_use (%u) < stids being freed (%u)", __func__,
+ t->stids_in_use, sr->used));
+ t->stids_in_use -= sr->used;
+ TAILQ_REMOVE(&t->stids, sr, link);
mtx_unlock(&t->stid_lock);
}
@@ -134,7 +197,7 @@ alloc_lctx(struct adapter *sc, struct inpcb *inp, struct port_info *pi)
if (lctx == NULL)
return (NULL);
- lctx->stid = alloc_stid(sc, lctx);
+ lctx->stid = alloc_stid(sc, lctx, inp->inp_vflag & INP_IPV6);
if (lctx->stid < 0) {
free(lctx, M_CXGBE);
return (NULL);
@@ -167,7 +230,7 @@ free_lctx(struct adapter *sc, struct listen_ctx *lctx)
CTR4(KTR_CXGBE, "%s: stid %u, lctx %p, inp %p",
__func__, lctx->stid, lctx, lctx->inp);
- free_stid(sc, lctx->stid);
+ free_stid(sc, lctx);
free(lctx, M_CXGBE);
return (in_pcbrele_wlocked(inp));
@@ -339,7 +402,7 @@ create_server(struct adapter *sc, struct listen_ctx *lctx)
{
struct wrqe *wr;
struct cpl_pass_open_req *req;
- struct in_conninfo *inc = &lctx->inp->inp_inc;
+ struct inpcb *inp = lctx->inp;
wr = alloc_wrqe(sizeof(*req), lctx->ctrlq);
if (wr == NULL) {
@@ -350,9 +413,9 @@ create_server(struct adapter *sc, struct listen_ctx *lctx)
INIT_TP_WR(req, 0);
OPCODE_TID(req) = htobe32(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, lctx->stid));
- req->local_port = inc->inc_lport;
+ req->local_port = inp->inp_lport;
req->peer_port = 0;
- req->local_ip = inc->inc_laddr.s_addr;
+ req->local_ip = inp->inp_laddr.s_addr;
req->peer_ip = 0;
req->opt0 = htobe64(V_TX_CHAN(lctx->ctrlq->eq.tx_chan));
req->opt1 = htobe64(V_CONN_POLICY(CPL_CONN_POLICY_ASK) |
@@ -363,6 +426,36 @@ create_server(struct adapter *sc, struct listen_ctx *lctx)
}
static int
+create_server6(struct adapter *sc, struct listen_ctx *lctx)
+{
+ struct wrqe *wr;
+ struct cpl_pass_open_req6 *req;
+ struct inpcb *inp = lctx->inp;
+
+ wr = alloc_wrqe(sizeof(*req), lctx->ctrlq);
+ if (wr == NULL) {
+ log(LOG_ERR, "%s: allocation failure", __func__);
+ return (ENOMEM);
+ }
+ req = wrtod(wr);
+
+ INIT_TP_WR(req, 0);
+ OPCODE_TID(req) = htobe32(MK_OPCODE_TID(CPL_PASS_OPEN_REQ6, lctx->stid));
+ req->local_port = inp->inp_lport;
+ req->peer_port = 0;
+ req->local_ip_hi = *(uint64_t *)&inp->in6p_laddr.s6_addr[0];
+ req->local_ip_lo = *(uint64_t *)&inp->in6p_laddr.s6_addr[8];
+ req->peer_ip_hi = 0;
+ req->peer_ip_lo = 0;
+ req->opt0 = htobe64(V_TX_CHAN(lctx->ctrlq->eq.tx_chan));
+ req->opt1 = htobe64(V_CONN_POLICY(CPL_CONN_POLICY_ASK) |
+ F_SYN_RSS_ENABLE | V_SYN_RSS_QUEUE(lctx->ofld_rxq->iq.abs_id));
+
+ t4_wrq_tx(sc, wr);
+ return (0);
+}
+
+static int
destroy_server(struct adapter *sc, struct listen_ctx *lctx)
{
struct wrqe *wr;
@@ -398,13 +491,10 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp)
struct port_info *pi;
struct inpcb *inp = tp->t_inpcb;
struct listen_ctx *lctx;
- int i;
+ int i, rc;
INP_WLOCK_ASSERT(inp);
- if ((inp->inp_vflag & INP_IPV4) == 0)
- return (0);
-
#if 0
ADAPTER_LOCK(sc);
if (IS_BUSY(sc)) {
@@ -421,8 +511,9 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp)
goto done; /* no port that's UP with IFCAP_TOE enabled */
/*
- * Find a running port with IFCAP_TOE4. We'll use the first such port's
- * queues to send the passive open and receive the reply to it.
+ * Find a running port with IFCAP_TOE (4 or 6). We'll use the first
+ * such port's queues to send the passive open and receive the reply to
+ * it.
*
* XXX: need a way to mark a port in use by offload. if_cxgbe should
* then reject any attempt to bring down such a port (and maybe reject
@@ -430,7 +521,7 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp)
*/
for_each_port(sc, i) {
if (isset(&sc->open_device_map, i) &&
- sc->port[i]->ifp->if_capenable & IFCAP_TOE4)
+ sc->port[i]->ifp->if_capenable & IFCAP_TOE)
break;
}
KASSERT(i < sc->params.nports,
@@ -449,12 +540,17 @@ t4_listen_start(struct toedev *tod, struct tcpcb *tp)
}
listen_hash_add(sc, lctx);
- CTR5(KTR_CXGBE, "%s: stid %u (%s), lctx %p, inp %p", __func__,
- lctx->stid, tcpstates[tp->t_state], lctx, inp);
+ CTR6(KTR_CXGBE, "%s: stid %u (%s), lctx %p, inp %p vflag 0x%x",
+ __func__, lctx->stid, tcpstates[tp->t_state], lctx, inp,
+ inp->inp_vflag);
- if (create_server(sc, lctx) != 0) {
- log(LOG_ERR, "%s: %s failed to create hw listener.\n", __func__,
- device_get_nameunit(sc->dev));
+ if (inp->inp_vflag & INP_IPV6)
+ rc = create_server6(sc, lctx);
+ else
+ rc = create_server(sc, lctx);
+ if (rc != 0) {
+ log(LOG_ERR, "%s: %s failed to create hw listener: %d.\n",
+ __func__, device_get_nameunit(sc->dev), rc);
(void) listen_hash_del(sc, inp);
inp = release_lctx(sc, lctx);
/* can't be freed, host stack has a reference */
@@ -558,7 +654,7 @@ t4_syncache_respond(struct toedev *tod, void *arg, struct mbuf *m)
struct l2t_entry *e;
struct tcpopt to;
struct ip *ip = mtod(m, struct ip *);
- struct tcphdr *th = (void *)(ip + 1);
+ struct tcphdr *th;
wr = (struct wrqe *)atomic_readandclear_ptr(&synqe->wr);
if (wr == NULL) {
@@ -566,6 +662,10 @@ t4_syncache_respond(struct toedev *tod, void *arg, struct mbuf *m)
return (EALREADY);
}
+ if (ip->ip_v == IPVERSION)
+ th = (void *)(ip + 1);
+ else
+ th = (void *)((struct ip6_hdr *)ip + 1);
bzero(&to, sizeof(to));
tcp_dooptions(&to, (void *)(th + 1), (th->th_off << 2) - sizeof(*th),
TO_SYN);
@@ -608,7 +708,7 @@ do_pass_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
lctx->flags &= ~LCTX_RPL_PENDING;
if (status != CPL_ERR_NONE)
- log(LOG_ERR, "listener with stid %u failed: %d", stid, status);
+ log(LOG_ERR, "listener (stid %u) failed: %d\n", stid, status);
#ifdef INVARIANTS
/*
@@ -678,7 +778,7 @@ do_close_server_rpl(struct sge_iq *iq, const struct rss_header *rss,
CTR3(KTR_CXGBE, "%s: stid %u, status %u", __func__, stid, status);
if (status != CPL_ERR_NONE) {
- log(LOG_ERR, "%s: failed (%u) to close listener for stid %u",
+ log(LOG_ERR, "%s: failed (%u) to close listener for stid %u\n",
__func__, status, stid);
return (status);
}
@@ -735,8 +835,7 @@ do_abort_req_synqe(struct sge_iq *iq, const struct rss_header *rss,
CTR6(KTR_CXGBE, "%s: tid %u, synqe %p (0x%x), lctx %p, status %d",
__func__, tid, synqe, synqe->flags, synqe->lctx, cpl->status);
- if (cpl->status == CPL_ERR_RTX_NEG_ADVICE ||
- cpl->status == CPL_ERR_PERSIST_NEG_ADVICE)
+ if (negative_advice(cpl->status))
return (0); /* Ignore negative advice */
INP_WLOCK(inp);
@@ -855,7 +954,7 @@ mbuf_to_synqe(struct mbuf *m)
return (NULL);
synqe->flags = TPF_SYNQE | TPF_SYNQE_NEEDFREE;
} else {
- synqe = (void *)(m->m_data + m->m_len + tspace - sizeof(*synqe));
+ synqe = (void *)(m->m_data + m->m_len + tspace - len);
synqe->flags = TPF_SYNQE;
}
@@ -936,21 +1035,29 @@ pass_accept_req_to_protohdrs(const struct mbuf *m, struct in_conninfo *inc,
const struct cpl_pass_accept_req *cpl = mtod(m, const void *);
const struct ether_header *eh;
unsigned int hlen = be32toh(cpl->hdr_len);
- const struct ip *ip;
+ uintptr_t l3hdr;
const struct tcphdr *tcp;
eh = (const void *)(cpl + 1);
- ip = (const void *)((uintptr_t)eh + G_ETH_HDR_LEN(hlen));
- tcp = (const void *)((uintptr_t)ip + G_IP_HDR_LEN(hlen));
+ l3hdr = ((uintptr_t)eh + G_ETH_HDR_LEN(hlen));
+ tcp = (const void *)(l3hdr + G_IP_HDR_LEN(hlen));
if (inc) {
bzero(inc, sizeof(*inc));
- inc->inc_faddr = ip->ip_src;
- inc->inc_laddr = ip->ip_dst;
inc->inc_fport = tcp->th_sport;
inc->inc_lport = tcp->th_dport;
- if (ip->ip_v == 6)
+ if (((struct ip *)l3hdr)->ip_v == IPVERSION) {
+ const struct ip *ip = (const void *)l3hdr;
+
+ inc->inc_faddr = ip->ip_src;
+ inc->inc_laddr = ip->ip_dst;
+ } else {
+ const struct ip6_hdr *ip6 = (const void *)l3hdr;
+
inc->inc_flags |= INC_ISIPV6;
+ inc->inc6_faddr = ip6->ip6_src;
+ inc->inc6_laddr = ip6->ip6_dst;
+ }
}
if (th) {
@@ -959,6 +1066,105 @@ pass_accept_req_to_protohdrs(const struct mbuf *m, struct in_conninfo *inc,
}
}
+static int
+ifnet_has_ip6(struct ifnet *ifp, struct in6_addr *ip6)
+{
+ struct ifaddr *ifa;
+ struct sockaddr_in6 *sin6;
+ int found = 0;
+ struct in6_addr in6 = *ip6;
+
+ /* Just as in ip6_input */
+ if (in6_clearscope(&in6) || in6_clearscope(&in6))
+ return (0);
+ in6_setscope(&in6, ifp, NULL);
+
+ if_addr_rlock(ifp);
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ sin6 = (void *)ifa->ifa_addr;
+ if (sin6->sin6_family != AF_INET6)
+ continue;
+
+ if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &in6)) {
+ found = 1;
+ break;
+ }
+ }
+ if_addr_runlock(ifp);
+
+ return (found);
+}
+
+static struct l2t_entry *
+get_l2te_for_nexthop(struct port_info *pi, struct ifnet *ifp,
+ struct in_conninfo *inc)
+{
+ struct rtentry *rt;
+ struct l2t_entry *e;
+ struct sockaddr_in6 sin6;
+ struct sockaddr *dst = (void *)&sin6;
+
+ if (inc->inc_flags & INC_ISIPV6) {
+ dst->sa_len = sizeof(struct sockaddr_in6);
+ dst->sa_family = AF_INET6;
+ ((struct sockaddr_in6 *)dst)->sin6_addr = inc->inc6_faddr;
+
+ if (IN6_IS_ADDR_LINKLOCAL(&inc->inc6_laddr)) {
+ /* no need for route lookup */
+ e = t4_l2t_get(pi, ifp, dst);
+ return (e);
+ }
+ } else {
+ dst->sa_len = sizeof(struct sockaddr_in);
+ dst->sa_family = AF_INET;
+ ((struct sockaddr_in *)dst)->sin_addr = inc->inc_faddr;
+ }
+
+ rt = rtalloc1(dst, 0, 0);
+ if (rt == NULL)
+ return (NULL);
+ else {
+ struct sockaddr *nexthop;
+
+ RT_UNLOCK(rt);
+ if (rt->rt_ifp != ifp)
+ e = NULL;
+ else {
+ if (rt->rt_flags & RTF_GATEWAY)
+ nexthop = rt->rt_gateway;
+ else
+ nexthop = dst;
+ e = t4_l2t_get(pi, ifp, nexthop);
+ }
+ RTFREE(rt);
+ }
+
+ return (e);
+}
+
+static int
+ifnet_has_ip(struct ifnet *ifp, struct in_addr in)
+{
+ struct ifaddr *ifa;
+ struct sockaddr_in *sin;
+ int found = 0;
+
+ if_addr_rlock(ifp);
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ sin = (void *)ifa->ifa_addr;
+ if (sin->sin_family != AF_INET)
+ continue;
+
+ if (sin->sin_addr.s_addr == in.s_addr) {
+ found = 1;
+ break;
+ }
+ }
+ if_addr_runlock(ifp);
+
+ return (found);
+}
+
#define REJECT_PASS_ACCEPT() do { \
reject_reason = __LINE__; \
goto reject; \
@@ -994,10 +1200,8 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
struct tcphdr th;
struct tcpopt to;
struct port_info *pi;
- struct ifnet *ifp, *ifp_vlan = NULL;
+ struct ifnet *hw_ifp, *ifp;
struct l2t_entry *e = NULL;
- struct rtentry *rt;
- struct sockaddr_in nam;
int rscale, mtu_idx, rx_credits, rxqid, ulp_mode;
struct synq_entry *synqe = NULL;
int reject_reason;
@@ -1017,31 +1221,24 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
t4opt_to_tcpopt(&cpl->tcpopt, &to);
pi = sc->port[G_SYN_INTF(be16toh(cpl->l2info))];
- ifp = pi->ifp;
- m->m_pkthdr.rcvif = ifp;
- tod = TOEDEV(ifp);
+ hw_ifp = pi->ifp; /* the cxgbeX ifnet */
+ m->m_pkthdr.rcvif = hw_ifp;
+ tod = TOEDEV(hw_ifp);
/*
- * Don't offload if the interface that received the SYN doesn't have
- * IFCAP_TOE enabled.
- */
- if ((ifp->if_capenable & IFCAP_TOE4) == 0)
- REJECT_PASS_ACCEPT();
-
- /* Don't offload IPv6 connections. XXX: add IPv6 support */
- if (inc.inc_flags & INC_ISIPV6)
- REJECT_PASS_ACCEPT();
-
- /*
- * Don't offload if the SYN had a VLAN tag and the vid doesn't match
- * anything on this interface.
+ * Figure out if there is a pseudo interface (vlan, lagg, etc.)
+ * involved. Don't offload if the SYN had a VLAN tag and the vid
+ * doesn't match anything on this interface.
+ *
+ * XXX: lagg support, lagg + vlan support.
*/
vid = EVL_VLANOFTAG(be16toh(cpl->vlan));
if (vid != 0xfff) {
- ifp_vlan = VLAN_DEVAT(ifp, vid);
- if (ifp_vlan == NULL)
+ ifp = VLAN_DEVAT(hw_ifp, vid);
+ if (ifp == NULL)
REJECT_PASS_ACCEPT();
- }
+ } else
+ ifp = hw_ifp;
/*
* Don't offload if the peer requested a TCP option that's not known to
@@ -1050,31 +1247,36 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
if (cpl->tcpopt.unknown)
REJECT_PASS_ACCEPT();
- /*
- * Don't offload if the outgoing interface for the route back to the
- * peer is not the same as the interface that received the SYN.
- * XXX: too restrictive.
- */
- nam.sin_len = sizeof(nam);
- nam.sin_family = AF_INET;
- nam.sin_addr = inc.inc_faddr;
- rt = rtalloc1((struct sockaddr *)&nam, 0, 0);
- if (rt == NULL)
- REJECT_PASS_ACCEPT();
- else {
- struct sockaddr *nexthop;
+ if (inc.inc_flags & INC_ISIPV6) {
- RT_UNLOCK(rt);
- nexthop = rt->rt_flags & RTF_GATEWAY ? rt->rt_gateway :
- (struct sockaddr *)&nam;
- if (rt->rt_ifp == ifp ||
- (ifp_vlan != NULL && rt->rt_ifp == ifp_vlan))
- e = t4_l2t_get(pi, rt->rt_ifp, nexthop);
- RTFREE(rt);
- if (e == NULL)
- REJECT_PASS_ACCEPT(); /* no l2te, or ifp mismatch */
+ /* Don't offload if the ifcap isn't enabled */
+ if ((ifp->if_capenable & IFCAP_TOE6) == 0)
+ REJECT_PASS_ACCEPT();
+
+ /*
+ * SYN must be directed to an IP6 address on this ifnet. This
+ * is more restrictive than in6_localip.
+ */
+ if (!ifnet_has_ip6(ifp, &inc.inc6_laddr))
+ REJECT_PASS_ACCEPT();
+ } else {
+
+ /* Don't offload if the ifcap isn't enabled */
+ if ((ifp->if_capenable & IFCAP_TOE4) == 0)
+ REJECT_PASS_ACCEPT();
+
+ /*
+ * SYN must be directed to an IP address on this ifnet. This
+ * is more restrictive than in_localip.
+ */
+ if (!ifnet_has_ip(ifp, inc.inc_laddr))
+ REJECT_PASS_ACCEPT();
}
+ e = get_l2te_for_nexthop(pi, ifp, &inc);
+ if (e == NULL)
+ REJECT_PASS_ACCEPT();
+
synqe = mbuf_to_synqe(m);
if (synqe == NULL)
REJECT_PASS_ACCEPT();
@@ -1133,7 +1335,7 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
synqe->lctx = lctx;
synqe->syn = m;
m = NULL;
- refcount_init(&synqe->refcnt, 0);
+ refcount_init(&synqe->refcnt, 1); /* 1 means extra hold */
synqe->l2e_idx = e->idx;
synqe->rcv_bufsize = rx_credits;
atomic_store_rel_ptr(&synqe->wr, (uintptr_t)wr);
@@ -1166,7 +1368,7 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
*/
m = m_dup(synqe->syn, M_NOWAIT);
if (m)
- m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.rcvif = hw_ifp;
remove_tid(sc, synqe->tid);
free(wr, M_CXGBE);
@@ -1179,6 +1381,7 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
if (inp)
INP_WUNLOCK(inp);
+ release_synqe(synqe); /* extra hold */
REJECT_PASS_ACCEPT();
}
@@ -1193,15 +1396,19 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
* this tid because there was no L2T entry for the tid at that
* time. Abort it now. The reply to the abort will clean up.
*/
- CTR5(KTR_CXGBE, "%s: stid %u, tid %u, lctx %p, synqe %p, ABORT",
- __func__, stid, tid, lctx, synqe);
- send_reset_synqe(tod, synqe);
+ CTR6(KTR_CXGBE,
+ "%s: stid %u, tid %u, lctx %p, synqe %p (0x%x), ABORT",
+ __func__, stid, tid, lctx, synqe, synqe->flags);
+ if (!(synqe->flags & TPF_SYNQE_EXPANDED))
+ send_reset_synqe(tod, synqe);
INP_WUNLOCK(inp);
+ release_synqe(synqe); /* extra hold */
return (__LINE__);
}
INP_WUNLOCK(inp);
+ release_synqe(synqe); /* extra hold */
return (0);
reject:
CTR4(KTR_CXGBE, "%s: stid %u, tid %u, REJECT (%d)", __func__, stid, tid,
@@ -1216,7 +1423,7 @@ reject:
m->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID |
CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
m->m_pkthdr.csum_data = 0xffff;
- ifp->if_input(ifp, m);
+ hw_ifp->if_input(hw_ifp, m);
}
return (reject_reason);
diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c
index 330172d..64e8b26 100644
--- a/sys/dev/cxgbe/tom/t4_tom.c
+++ b/sys/dev/cxgbe/tom/t4_tom.c
@@ -29,6 +29,7 @@
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
+#include "opt_inet6.h"
#include <sys/param.h>
#include <sys/types.h>
@@ -40,10 +41,14 @@ __FBSDID("$FreeBSD$");
#include <sys/domain.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
+#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/tcp_var.h>
+#include <netinet6/scope6_var.h>
#define TCPSTATES
#include <netinet/tcp_fsm.h>
#include <netinet/toecore.h>
@@ -58,6 +63,9 @@ __FBSDID("$FreeBSD$");
static struct protosw ddp_protosw;
static struct pr_usrreqs ddp_usrreqs;
+static struct protosw ddp6_protosw;
+static struct pr_usrreqs ddp6_usrreqs;
+
/* Module ops */
static int t4_tom_mod_load(void);
static int t4_tom_mod_unload(void);
@@ -77,6 +85,11 @@ static void queue_tid_release(struct adapter *, int);
static void release_offload_resources(struct toepcb *);
static int alloc_tid_tabs(struct tid_info *);
static void free_tid_tabs(struct tid_info *);
+static int add_lip(struct adapter *, struct in6_addr *);
+static int delete_lip(struct adapter *, struct in6_addr *);
+static struct clip_entry *search_lip(struct tom_data *, struct in6_addr *);
+static void init_clip_table(struct adapter *, struct tom_data *);
+static void destroy_clip_table(struct adapter *, struct tom_data *);
static void free_tom_data(struct adapter *, struct tom_data *);
struct toepcb *
@@ -170,8 +183,12 @@ offload_socket(struct socket *so, struct toepcb *toep)
sb = &so->so_rcv;
SOCKBUF_LOCK(sb);
sb->sb_flags |= SB_NOCOALESCE;
- if (toep->ulp_mode == ULP_MODE_TCPDDP)
- so->so_proto = &ddp_protosw;
+ if (toep->ulp_mode == ULP_MODE_TCPDDP) {
+ if (inp->inp_vflag & INP_IPV6)
+ so->so_proto = &ddp6_protosw;
+ else
+ so->so_proto = &ddp_protosw;
+ }
SOCKBUF_UNLOCK(sb);
/* Update TCP PCB */
@@ -237,8 +254,8 @@ release_offload_resources(struct toepcb *toep)
KASSERT(!(toep->flags & TPF_ATTACHED),
("%s: %p is still attached.", __func__, toep));
- CTR4(KTR_CXGBE, "%s: toep %p (tid %d, l2te %p)",
- __func__, toep, tid, toep->l2te);
+ CTR5(KTR_CXGBE, "%s: toep %p (tid %d, l2te %p, ce %p)",
+ __func__, toep, tid, toep->l2te, toep->ce);
if (toep->ulp_mode == ULP_MODE_TCPDDP)
release_ddp_resources(toep);
@@ -251,6 +268,9 @@ release_offload_resources(struct toepcb *toep)
release_tid(sc, tid, toep->ctrlq);
}
+ if (toep->ce)
+ release_lip(td, toep->ce);
+
mtx_lock(&td->toep_list_lock);
TAILQ_REMOVE(&td->toep_list, toep, link);
mtx_unlock(&td->toep_list_lock);
@@ -394,7 +414,7 @@ int
find_best_mtu_idx(struct adapter *sc, struct in_conninfo *inc, int pmss)
{
unsigned short *mtus = &sc->params.mtus[0];
- int i = 0, mss;
+ int i, mss, n;
KASSERT(inc != NULL || pmss > 0,
("%s: at least one of inc/pmss must be specified", __func__));
@@ -403,8 +423,13 @@ find_best_mtu_idx(struct adapter *sc, struct in_conninfo *inc, int pmss)
if (pmss > 0 && mss > pmss)
mss = pmss;
- while (i < NMTUS - 1 && mtus[i + 1] <= mss + 40)
- ++i;
+ if (inc->inc_flags & INC_ISIPV6)
+ n = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
+ else
+ n = sizeof(struct ip) + sizeof(struct tcphdr);
+
+ for (i = 0; i < NMTUS - 1 && mtus[i + 1] <= mss + n; i++)
+ continue;
return (i);
}
@@ -513,6 +538,24 @@ select_ntuple(struct port_info *pi, struct l2t_entry *e, uint32_t filter_mode)
return (htobe32(ntuple));
}
+void
+set_tcpddp_ulp_mode(struct toepcb *toep)
+{
+
+ toep->ulp_mode = ULP_MODE_TCPDDP;
+ toep->ddp_flags = DDP_OK;
+ toep->ddp_score = DDP_LOW_SCORE;
+}
+
+int
+negative_advice(int status)
+{
+
+ return (status == CPL_ERR_RTX_NEG_ADVICE ||
+ status == CPL_ERR_PERSIST_NEG_ADVICE ||
+ status == CPL_ERR_KEEPALV_NEG_ADVICE);
+}
+
static int
alloc_tid_tabs(struct tid_info *t)
{
@@ -536,12 +579,10 @@ alloc_tid_tabs(struct tid_info *t)
t->atid_tab[t->natids - 1].next = NULL;
mtx_init(&t->stid_lock, "stid lock", NULL, MTX_DEF);
- t->stid_tab = (union serv_entry *)&t->atid_tab[t->natids];
- t->sfree = t->stid_tab;
+ t->stid_tab = (struct listen_ctx **)&t->atid_tab[t->natids];
t->stids_in_use = 0;
- for (i = 1; i < t->nstids; i++)
- t->stid_tab[i - 1].next = &t->stid_tab[i];
- t->stid_tab[t->nstids - 1].next = NULL;
+ TAILQ_INIT(&t->stids);
+ t->nstids_free_head = t->nstids;
atomic_store_rel_int(&t->tids_in_use, 0);
@@ -567,9 +608,157 @@ free_tid_tabs(struct tid_info *t)
mtx_destroy(&t->stid_lock);
}
+static int
+add_lip(struct adapter *sc, struct in6_addr *lip)
+{
+ struct fw_clip_cmd c;
+
+ ASSERT_SYNCHRONIZED_OP(sc);
+ /* mtx_assert(&td->clip_table_lock, MA_OWNED); */
+
+ memset(&c, 0, sizeof(c));
+ c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST |
+ F_FW_CMD_WRITE);
+ c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_ALLOC | FW_LEN16(c));
+ c.ip_hi = *(uint64_t *)&lip->s6_addr[0];
+ c.ip_lo = *(uint64_t *)&lip->s6_addr[8];
+
+ return (t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c));
+}
+
+static int
+delete_lip(struct adapter *sc, struct in6_addr *lip)
+{
+ struct fw_clip_cmd c;
+
+ ASSERT_SYNCHRONIZED_OP(sc);
+ /* mtx_assert(&td->clip_table_lock, MA_OWNED); */
+
+ memset(&c, 0, sizeof(c));
+ c.op_to_write = htonl(V_FW_CMD_OP(FW_CLIP_CMD) | F_FW_CMD_REQUEST |
+ F_FW_CMD_READ);
+ c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_FREE | FW_LEN16(c));
+ c.ip_hi = *(uint64_t *)&lip->s6_addr[0];
+ c.ip_lo = *(uint64_t *)&lip->s6_addr[8];
+
+ return (t4_wr_mbox_ns(sc, sc->mbox, &c, sizeof(c), &c));
+}
+
+static struct clip_entry *
+search_lip(struct tom_data *td, struct in6_addr *lip)
+{
+ struct clip_entry *ce;
+
+ mtx_assert(&td->clip_table_lock, MA_OWNED);
+
+ TAILQ_FOREACH(ce, &td->clip_table, link) {
+ if (IN6_ARE_ADDR_EQUAL(&ce->lip, lip))
+ return (ce);
+ }
+
+ return (NULL);
+}
+
+struct clip_entry *
+hold_lip(struct tom_data *td, struct in6_addr *lip)
+{
+ struct clip_entry *ce;
+
+ mtx_lock(&td->clip_table_lock);
+ ce = search_lip(td, lip);
+ if (ce != NULL)
+ ce->refcount++;
+ mtx_unlock(&td->clip_table_lock);
+
+ return (ce);
+}
+
+void
+release_lip(struct tom_data *td, struct clip_entry *ce)
+{
+
+ mtx_lock(&td->clip_table_lock);
+ KASSERT(search_lip(td, &ce->lip) == ce,
+ ("%s: CLIP entry %p p not in CLIP table.", __func__, ce));
+ KASSERT(ce->refcount > 0,
+ ("%s: CLIP entry %p has refcount 0", __func__, ce));
+ --ce->refcount;
+ mtx_unlock(&td->clip_table_lock);
+}
+
+static void
+init_clip_table(struct adapter *sc, struct tom_data *td)
+{
+ struct in6_ifaddr *ia;
+ struct in6_addr *lip, tlip;
+ struct clip_entry *ce;
+
+ ASSERT_SYNCHRONIZED_OP(sc);
+
+ mtx_init(&td->clip_table_lock, "CLIP table lock", NULL, MTX_DEF);
+ TAILQ_INIT(&td->clip_table);
+
+ IN6_IFADDR_RLOCK();
+ TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
+ lip = &ia->ia_addr.sin6_addr;
+
+ KASSERT(!IN6_IS_ADDR_MULTICAST(lip),
+ ("%s: mcast address in in6_ifaddr list", __func__));
+
+ if (IN6_IS_ADDR_LOOPBACK(lip))
+ continue;
+ if (IN6_IS_SCOPE_EMBED(lip)) {
+ /* Remove the embedded scope */
+ tlip = *lip;
+ lip = &tlip;
+ in6_clearscope(lip);
+ }
+ /*
+ * XXX: how to weed out the link local address for the loopback
+ * interface? It's fe80::1 usually (always?).
+ */
+
+ mtx_lock(&td->clip_table_lock);
+ if (search_lip(td, lip) == NULL) {
+ ce = malloc(sizeof(*ce), M_CXGBE, M_NOWAIT);
+ memcpy(&ce->lip, lip, sizeof(ce->lip));
+ ce->refcount = 0;
+ if (add_lip(sc, lip) == 0)
+ TAILQ_INSERT_TAIL(&td->clip_table, ce, link);
+ else
+ free(ce, M_CXGBE);
+ }
+ mtx_unlock(&td->clip_table_lock);
+ }
+ IN6_IFADDR_RUNLOCK();
+}
+
+static void
+destroy_clip_table(struct adapter *sc, struct tom_data *td)
+{
+ struct clip_entry *ce, *ce_temp;
+
+ if (mtx_initialized(&td->clip_table_lock)) {
+ mtx_lock(&td->clip_table_lock);
+ TAILQ_FOREACH_SAFE(ce, &td->clip_table, link, ce_temp) {
+ KASSERT(ce->refcount == 0,
+ ("%s: CLIP entry %p still in use (%d)", __func__,
+ ce, ce->refcount));
+ TAILQ_REMOVE(&td->clip_table, ce, link);
+ delete_lip(sc, &ce->lip);
+ free(ce, M_CXGBE);
+ }
+ mtx_unlock(&td->clip_table_lock);
+ mtx_destroy(&td->clip_table_lock);
+ }
+}
+
static void
free_tom_data(struct adapter *sc, struct tom_data *td)
{
+
+ ASSERT_SYNCHRONIZED_OP(sc);
+
KASSERT(TAILQ_EMPTY(&td->toep_list),
("%s: TOE PCB list is not empty.", __func__));
KASSERT(td->lctx_count == 0,
@@ -578,6 +767,7 @@ free_tom_data(struct adapter *sc, struct tom_data *td)
t4_uninit_l2t_cpl_handlers(sc);
t4_uninit_cpl_io_handlers(sc);
t4_uninit_ddp(sc, td);
+ destroy_clip_table(sc, td);
if (td->listen_mask != 0)
hashdestroy(td->listen_hash, M_CXGBE, td->listen_mask);
@@ -602,7 +792,7 @@ t4_tom_activate(struct adapter *sc)
struct toedev *tod;
int i, rc;
- ADAPTER_LOCK_ASSERT_OWNED(sc); /* for sc->flags */
+ ASSERT_SYNCHRONIZED_OP(sc);
/* per-adapter softc for TOM */
td = malloc(sizeof(*td), M_CXGBE, M_ZERO | M_NOWAIT);
@@ -623,8 +813,12 @@ t4_tom_activate(struct adapter *sc)
if (rc != 0)
goto done;
+ /* DDP page pods and CPL handlers */
t4_init_ddp(sc, td);
+ /* CLIP table for IPv6 offload */
+ init_clip_table(sc, td);
+
/* CPL handlers */
t4_init_connect_cpl_handlers(sc);
t4_init_l2t_cpl_handlers(sc);
@@ -668,7 +862,7 @@ t4_tom_deactivate(struct adapter *sc)
int rc = 0;
struct tom_data *td = sc->tom_softc;
- ADAPTER_LOCK_ASSERT_OWNED(sc); /* for sc->flags */
+ ASSERT_SYNCHRONIZED_OP(sc);
if (td == NULL)
return (0); /* XXX. KASSERT? */
@@ -700,17 +894,24 @@ static int
t4_tom_mod_load(void)
{
int rc;
- struct protosw *tcp_protosw;
+ struct protosw *tcp_protosw, *tcp6_protosw;
tcp_protosw = pffindproto(PF_INET, IPPROTO_TCP, SOCK_STREAM);
if (tcp_protosw == NULL)
return (ENOPROTOOPT);
-
bcopy(tcp_protosw, &ddp_protosw, sizeof(ddp_protosw));
bcopy(tcp_protosw->pr_usrreqs, &ddp_usrreqs, sizeof(ddp_usrreqs));
ddp_usrreqs.pru_soreceive = t4_soreceive_ddp;
ddp_protosw.pr_usrreqs = &ddp_usrreqs;
+ tcp6_protosw = pffindproto(PF_INET6, IPPROTO_TCP, SOCK_STREAM);
+ if (tcp6_protosw == NULL)
+ return (ENOPROTOOPT);
+ bcopy(tcp6_protosw, &ddp6_protosw, sizeof(ddp6_protosw));
+ bcopy(tcp6_protosw->pr_usrreqs, &ddp6_usrreqs, sizeof(ddp6_usrreqs));
+ ddp6_usrreqs.pru_soreceive = t4_soreceive_ddp;
+ ddp6_protosw.pr_usrreqs = &ddp6_usrreqs;
+
rc = t4_register_uld(&tom_uld_info);
if (rc != 0)
t4_tom_mod_unload();
@@ -721,11 +922,14 @@ t4_tom_mod_load(void)
static void
tom_uninit(struct adapter *sc, void *arg __unused)
{
+ if (begin_synchronized_op(sc, NULL, HOLD_LOCK, "t4tomun"))
+ return;
+
/* Try to free resources (works only if no port has IFCAP_TOE) */
- ADAPTER_LOCK(sc);
if (sc->flags & TOM_INIT_DONE)
t4_deactivate_uld(sc, ULD_TOM);
- ADAPTER_UNLOCK(sc);
+
+ end_synchronized_op(sc, LOCK_HELD);
}
static int
diff --git a/sys/dev/cxgbe/tom/t4_tom.h b/sys/dev/cxgbe/tom/t4_tom.h
index 9549b0b..d0fbbd2 100644
--- a/sys/dev/cxgbe/tom/t4_tom.h
+++ b/sys/dev/cxgbe/tom/t4_tom.h
@@ -109,6 +109,7 @@ struct toepcb {
struct sge_ofld_rxq *ofld_rxq;
struct sge_wrq *ctrlq;
struct l2t_entry *l2te; /* L2 table entry used by this connection */
+ struct clip_entry *ce; /* CLIP table entry used by this tid */
int tid; /* Connection identifier */
unsigned int tx_credits;/* tx WR credits (in 16 byte units) remaining */
unsigned int sb_cc; /* last noted value of so_rcv->sb_cc */
@@ -140,15 +141,6 @@ struct flowc_tx_params {
#define DDP_LOW_SCORE 1
#define DDP_HIGH_SCORE 3
-static inline void
-set_tcpddp_ulp_mode(struct toepcb *toep)
-{
-
- toep->ulp_mode = ULP_MODE_TCPDDP;
- toep->ddp_flags = DDP_OK;
- toep->ddp_score = DDP_LOW_SCORE;
-}
-
/*
* Compressed state for embryonic connections for a listener. Barely fits in
* 64B, try not to grow it further.
@@ -174,6 +166,7 @@ struct listen_ctx {
LIST_ENTRY(listen_ctx) link; /* listen hash linkage */
volatile int refcount;
int stid;
+ struct stid_region stid_region;
int flags;
struct inpcb *inp; /* listening socket's inp */
struct sge_wrq *ctrlq;
@@ -183,6 +176,12 @@ struct listen_ctx {
TAILQ_HEAD(ppod_head, ppod_region);
+struct clip_entry {
+ TAILQ_ENTRY(clip_entry) link;
+ struct in6_addr lip; /* local IPv6 address */
+ u_int refcount;
+};
+
struct tom_data {
struct toedev tod;
@@ -200,6 +199,9 @@ struct tom_data {
int nppods_free; /* # of available ppods */
int nppods_free_head; /* # of available ppods at the begining */
struct ppod_head ppods;
+
+ struct mtx clip_table_lock;
+ TAILQ_HEAD(, clip_entry) clip_table;
};
static inline struct tom_data *
@@ -233,6 +235,10 @@ int select_rcv_wscale(void);
uint64_t calc_opt0(struct socket *, struct port_info *, struct l2t_entry *,
int, int, int, int);
uint32_t select_ntuple(struct port_info *, struct l2t_entry *, uint32_t);
+void set_tcpddp_ulp_mode(struct toepcb *);
+int negative_advice(int);
+struct clip_entry *hold_lip(struct tom_data *, struct in6_addr *);
+void release_lip(struct tom_data *, struct clip_entry *);
/* t4_connect.c */
void t4_init_connect_cpl_handlers(struct adapter *);
diff --git a/sys/dev/cxgbe/tom/t4_tom_l2t.c b/sys/dev/cxgbe/tom/t4_tom_l2t.c
index ffe64c5..7a75394 100644
--- a/sys/dev/cxgbe/tom/t4_tom_l2t.c
+++ b/sys/dev/cxgbe/tom/t4_tom_l2t.c
@@ -27,6 +27,7 @@
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
+#include "opt_inet6.h"
#ifdef TCP_OFFLOAD
#include <sys/param.h>
@@ -34,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
+#include <sys/fnv_hash.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/rwlock.h>
@@ -48,28 +50,89 @@ __FBSDID("$FreeBSD$");
#include <netinet/toecore.h>
#include "common/common.h"
-#include "common/jhash.h"
#include "common/t4_msg.h"
#include "tom/t4_tom_l2t.h"
#include "tom/t4_tom.h"
#define VLAN_NONE 0xfff
-#define SA(x) ((struct sockaddr *)(x))
-#define SIN(x) ((struct sockaddr_in *)(x))
-#define SINADDR(x) (SIN(x)->sin_addr.s_addr)
-
static inline void
l2t_hold(struct l2t_data *d, struct l2t_entry *e)
{
+
if (atomic_fetchadd_int(&e->refcnt, 1) == 0) /* 0 -> 1 transition */
atomic_subtract_int(&d->nfree, 1);
}
-static inline unsigned int
-arp_hash(const uint32_t key, int ifindex)
+static inline u_int
+l2_hash(struct l2t_data *d, const struct sockaddr *sa, int ifindex)
{
- return jhash_2words(key, ifindex, 0) & (L2T_SIZE - 1);
+ u_int hash, half = d->l2t_size / 2, start = 0;
+ const void *key;
+ size_t len;
+
+ KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
+ ("%s: sa %p has unexpected sa_family %d", __func__, sa,
+ sa->sa_family));
+
+ if (sa->sa_family == AF_INET) {
+ const struct sockaddr_in *sin = (const void *)sa;
+
+ key = &sin->sin_addr;
+ len = sizeof(sin->sin_addr);
+ } else {
+ const struct sockaddr_in6 *sin6 = (const void *)sa;
+
+ key = &sin6->sin6_addr;
+ len = sizeof(sin6->sin6_addr);
+ start = half;
+ }
+
+ hash = fnv_32_buf(key, len, FNV1_32_INIT);
+ hash = fnv_32_buf(&ifindex, sizeof(ifindex), hash);
+ hash %= half;
+
+ return (hash + start);
+}
+
+static inline int
+l2_cmp(const struct sockaddr *sa, struct l2t_entry *e)
+{
+
+ KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
+ ("%s: sa %p has unexpected sa_family %d", __func__, sa,
+ sa->sa_family));
+
+ if (sa->sa_family == AF_INET) {
+ const struct sockaddr_in *sin = (const void *)sa;
+
+ return (e->addr[0] != sin->sin_addr.s_addr);
+ } else {
+ const struct sockaddr_in6 *sin6 = (const void *)sa;
+
+ return (memcmp(&e->addr[0], &sin6->sin6_addr, sizeof(e->addr)));
+ }
+}
+
+static inline void
+l2_store(const struct sockaddr *sa, struct l2t_entry *e)
+{
+
+ KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
+ ("%s: sa %p has unexpected sa_family %d", __func__, sa,
+ sa->sa_family));
+
+ if (sa->sa_family == AF_INET) {
+ const struct sockaddr_in *sin = (const void *)sa;
+
+ e->addr[0] = sin->sin_addr.s_addr;
+ e->ipv6 = 0;
+ } else {
+ const struct sockaddr_in6 *sin6 = (const void *)sa;
+
+ memcpy(&e->addr[0], &sin6->sin6_addr, sizeof(e->addr));
+ e->ipv6 = 1;
+ }
}
/*
@@ -100,7 +163,7 @@ send_pending(struct adapter *sc, struct l2t_entry *e)
static void
resolution_failed_for_wr(struct wrqe *wr)
{
- log(LOG_ERR, "%s: leaked work request %p, wr_len %d", __func__, wr,
+ log(LOG_ERR, "%s: leaked work request %p, wr_len %d\n", __func__, wr,
wr->wr_len);
/* free(wr, M_CXGBE); */
@@ -175,15 +238,25 @@ resolve_entry(struct adapter *sc, struct l2t_entry *e)
struct tom_data *td = sc->tom_softc;
struct toedev *tod = &td->tod;
struct sockaddr_in sin = {0};
+ struct sockaddr_in6 sin6 = {0};
+ struct sockaddr *sa;
uint8_t dmac[ETHER_ADDR_LEN];
uint16_t vtag = VLAN_NONE;
int rc;
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof(struct sockaddr_in);
- SINADDR(&sin) = e->addr;
+ if (e->ipv6 == 0) {
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_addr.s_addr = e->addr[0];
+ sa = (void *)&sin;
+ } else {
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&sin6.sin6_addr, &e->addr[0], sizeof(e->addr));
+ sa = (void *)&sin6;
+ }
- rc = toe_l2_resolve(tod, e->ifp, SA(&sin), dmac, &vtag);
+ rc = toe_l2_resolve(tod, e->ifp, sa, dmac, &vtag);
if (rc == EWOULDBLOCK)
return (rc);
@@ -263,7 +336,7 @@ do_l2t_write_rpl2(struct sge_iq *iq, const struct rss_header *rss,
struct adapter *sc = iq->adapter;
const struct cpl_l2t_write_rpl *rpl = (const void *)(rss + 1);
unsigned int tid = GET_TID(rpl);
- unsigned int idx = tid & (L2T_SIZE - 1);
+ unsigned int idx = tid % L2T_SIZE;
int rc;
rc = do_l2t_write_rpl(iq, rss, m);
@@ -271,7 +344,7 @@ do_l2t_write_rpl2(struct sge_iq *iq, const struct rss_header *rss,
return (rc);
if (tid & F_SYNC_WR) {
- struct l2t_entry *e = &sc->l2t->l2tab[idx];
+ struct l2t_entry *e = &sc->l2t->l2tab[idx - sc->vres.l2t.start];
mtx_lock(&e->lock);
if (e->state != L2T_STATE_SWITCHING) {
@@ -310,21 +383,22 @@ t4_l2t_get(struct port_info *pi, struct ifnet *ifp, struct sockaddr *sa)
{
struct l2t_entry *e;
struct l2t_data *d = pi->adapter->l2t;
- uint32_t addr = SINADDR(sa);
- int hash = arp_hash(addr, ifp->if_index);
- unsigned int smt_idx = pi->port_id;
+ u_int hash, smt_idx = pi->port_id;
- if (sa->sa_family != AF_INET)
- return (NULL); /* XXX: no IPv6 support right now */
+ KASSERT(sa->sa_family == AF_INET || sa->sa_family == AF_INET6,
+ ("%s: sa %p has unexpected sa_family %d", __func__, sa,
+ sa->sa_family));
#ifndef VLAN_TAG
if (ifp->if_type == IFT_L2VLAN)
return (NULL);
#endif
+ hash = l2_hash(d, sa, ifp->if_index);
rw_wlock(&d->lock);
for (e = d->l2tab[hash].first; e; e = e->next) {
- if (e->addr == addr && e->ifp == ifp && e->smt_idx == smt_idx) {
+ if (l2_cmp(sa, e) == 0 && e->ifp == ifp &&
+ e->smt_idx == smt_idx) {
l2t_hold(d, e);
goto done;
}
@@ -338,7 +412,7 @@ t4_l2t_get(struct port_info *pi, struct ifnet *ifp, struct sockaddr *sa)
d->l2tab[hash].first = e;
e->state = L2T_STATE_RESOLVING;
- e->addr = addr;
+ l2_store(sa, e);
e->ifp = ifp;
e->smt_idx = smt_idx;
e->hash = hash;
@@ -368,14 +442,14 @@ t4_l2_update(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
struct adapter *sc = tod->tod_softc;
struct l2t_entry *e;
struct l2t_data *d = sc->l2t;
- uint32_t addr = SINADDR(sa);
- int hash = arp_hash(addr, ifp->if_index);
+ u_int hash;
KASSERT(d != NULL, ("%s: no L2 table", __func__));
+ hash = l2_hash(d, sa, ifp->if_index);
rw_rlock(&d->lock);
for (e = d->l2tab[hash].first; e; e = e->next) {
- if (e->addr == addr && e->ifp == ifp) {
+ if (l2_cmp(sa, e) == 0 && e->ifp == ifp) {
mtx_lock(&e->lock);
if (atomic_load_acq_int(&e->refcnt))
goto found;
diff --git a/sys/dev/digi/digi_isa.c b/sys/dev/digi/digi_isa.c
index f1f4a5f..0a0a2a0 100644
--- a/sys/dev/digi/digi_isa.c
+++ b/sys/dev/digi/digi_isa.c
@@ -462,7 +462,8 @@ static device_method_t digi_isa_methods[] = {
DEVMETHOD(device_attach, digi_isa_attach),
DEVMETHOD(device_detach, digi_detach),
DEVMETHOD(device_shutdown, digi_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t digi_isa_drv = {
diff --git a/sys/dev/digi/digi_pci.c b/sys/dev/digi/digi_pci.c
index 342858e..55814cd 100644
--- a/sys/dev/digi/digi_pci.c
+++ b/sys/dev/digi/digi_pci.c
@@ -219,7 +219,8 @@ static device_method_t digi_pci_methods[] = {
DEVMETHOD(device_attach, digi_pci_attach),
DEVMETHOD(device_detach, digi_detach),
DEVMETHOD(device_shutdown, digi_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t digi_pci_drv = {
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 8ba32e0..3344697 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -309,7 +309,7 @@ static device_method_t em_methods[] = {
DEVMETHOD(device_shutdown, em_shutdown),
DEVMETHOD(device_suspend, em_suspend),
DEVMETHOD(device_resume, em_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t em_driver = {
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 8eb3011..2921a91 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -294,7 +294,7 @@ static device_method_t igb_methods[] = {
DEVMETHOD(device_shutdown, igb_shutdown),
DEVMETHOD(device_suspend, igb_suspend),
DEVMETHOD(device_resume, igb_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t igb_driver = {
@@ -4330,8 +4330,8 @@ fail:
* the rings that completed, the failing case will have
* cleaned up for itself. 'i' is the endpoint.
*/
- for (int j = 0; j > i; ++j) {
- rxr = &adapter->rx_rings[i];
+ for (int j = 0; j < i; ++j) {
+ rxr = &adapter->rx_rings[j];
IGB_RX_LOCK(rxr);
igb_free_receive_ring(rxr);
IGB_RX_UNLOCK(rxr);
diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c
index 58e6c7e..6b2b4f7 100644
--- a/sys/dev/e1000/if_lem.c
+++ b/sys/dev/e1000/if_lem.c
@@ -262,7 +262,7 @@ static device_method_t lem_methods[] = {
DEVMETHOD(device_shutdown, lem_shutdown),
DEVMETHOD(device_suspend, lem_suspend),
DEVMETHOD(device_resume, lem_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t lem_driver = {
diff --git a/sys/dev/ep/if_ep_eisa.c b/sys/dev/ep/if_ep_eisa.c
index e25a531..bc77ec8 100644
--- a/sys/dev/ep/if_ep_eisa.c
+++ b/sys/dev/ep/if_ep_eisa.c
@@ -238,7 +238,7 @@ static device_method_t ep_eisa_methods[] = {
DEVMETHOD(device_attach, ep_eisa_attach),
DEVMETHOD(device_detach, ep_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ep_eisa_driver = {
diff --git a/sys/dev/ep/if_ep_isa.c b/sys/dev/ep/if_ep_isa.c
index 0455c40..e125daf 100644
--- a/sys/dev/ep/if_ep_isa.c
+++ b/sys/dev/ep/if_ep_isa.c
@@ -391,7 +391,7 @@ static device_method_t ep_isa_methods[] = {
DEVMETHOD(device_attach, ep_isa_attach),
DEVMETHOD(device_detach, ep_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ep_isa_driver = {
diff --git a/sys/dev/ep/if_ep_mca.c b/sys/dev/ep/if_ep_mca.c
index 3c1645c..17097ab 100644
--- a/sys/dev/ep/if_ep_mca.c
+++ b/sys/dev/ep/if_ep_mca.c
@@ -145,7 +145,7 @@ static device_method_t ep_mca_methods[] = {
DEVMETHOD(device_attach, ep_mca_attach),
DEVMETHOD(device_detach, ep_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ep_mca_driver = {
diff --git a/sys/dev/ep/if_ep_pccard.c b/sys/dev/ep/if_ep_pccard.c
index 98ebaf4..1b445f9 100644
--- a/sys/dev/ep/if_ep_pccard.c
+++ b/sys/dev/ep/if_ep_pccard.c
@@ -223,7 +223,7 @@ static device_method_t ep_pccard_methods[] = {
DEVMETHOD(device_attach, ep_pccard_attach),
DEVMETHOD(device_detach, ep_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ep_pccard_driver = {
diff --git a/sys/dev/fdc/fdc_acpi.c b/sys/dev/fdc/fdc_acpi.c
index 7769a57..fd5bf90 100644
--- a/sys/dev/fdc/fdc_acpi.c
+++ b/sys/dev/fdc/fdc_acpi.c
@@ -258,7 +258,7 @@ static device_method_t fdc_acpi_methods[] = {
DEVMETHOD(bus_read_ivar, fdc_read_ivar),
DEVMETHOD(bus_write_ivar, fdc_write_ivar),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t fdc_acpi_driver = {
diff --git a/sys/dev/fdt/fdt_mips.c b/sys/dev/fdt/fdt_mips.c
index 0e6828e..4df31d8 100644
--- a/sys/dev/fdt/fdt_mips.c
+++ b/sys/dev/fdt/fdt_mips.c
@@ -49,8 +49,26 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+/*
+ * For PIC-free boards, provide a PIC decoder to be used with mips4k CP0
+ * interrupt control directly.
+ */
+static int
+fdt_pic_decode_mips4k_cp0(phandle_t node, pcell_t *intr, int *interrupt,
+ int *trig, int *pol)
+{
+
+ if (!fdt_is_compatible(node, "mips,mips4k"))
+ return (ENXIO);
+
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+
+ return (0);
+}
+
fdt_pic_decode_t fdt_pic_table[] = {
- NULL,
- NULL,
+ &fdt_pic_decode_mips4k_cp0,
NULL
};
diff --git a/sys/dev/hpt27xx/hpt27xx_config.c b/sys/dev/hpt27xx/hpt27xx_config.c
index f87c7ee..5203f4a 100644
--- a/sys/dev/hpt27xx/hpt27xx_config.c
+++ b/sys/dev/hpt27xx/hpt27xx_config.c
@@ -58,9 +58,9 @@ int init_config(void)
return 0;
}
-char driver_name[] = "hpt27xx";
-char driver_name_long[] = "RocketRAID 27xx controller driver";
-char driver_ver[] = "v1.0 (" __DATE__ " " __TIME__ ")";
+const char driver_name[] = "hpt27xx";
+const char driver_name_long[] = "RocketRAID 27xx controller driver";
+const char driver_ver[] = "v1.0";
int osm_max_targets = 0xff;
diff --git a/sys/dev/hpt27xx/os_bsd.h b/sys/dev/hpt27xx/os_bsd.h
index 3895f40..e3f8e7d 100644
--- a/sys/dev/hpt27xx/os_bsd.h
+++ b/sys/dev/hpt27xx/os_bsd.h
@@ -135,9 +135,9 @@ INQUIRYDATA, *PINQUIRYDATA;
#include <dev/hpt27xx/ldm.h>
/* driver parameters */
-extern char driver_name[];
-extern char driver_name_long[];
-extern char driver_ver[];
+extern const char driver_name[];
+extern const char driver_name_long[];
+extern const char driver_ver[];
extern int osm_max_targets;
/*
diff --git a/sys/dev/hpt27xx/osm_bsd.c b/sys/dev/hpt27xx/osm_bsd.c
index ac7e9d8..fab1c71d 100644
--- a/sys/dev/hpt27xx/osm_bsd.c
+++ b/sys/dev/hpt27xx/osm_bsd.c
@@ -167,7 +167,8 @@ static int hpt_alloc_mem(PVBUS_EXT vbus_ext)
HPT_ASSERT((f->size & (f->alignment-1))==0);
- for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) ;
+ for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1)
+ ;
KdPrint(("%s: %d*%d=%d bytes, order %d",
f->tag, f->count, f->size, f->count*f->size, order));
@@ -1036,6 +1037,7 @@ static void hpt_final_init(void *dummy)
}
if (!i) {
+ if (bootverbose)
os_printk("no controller detected.");
return;
}
@@ -1177,7 +1179,7 @@ static void hpt_final_init(void *dummy)
}
make_dev(&hpt_cdevsw, DRIVER_MINOR, UID_ROOT, GID_OPERATOR,
- S_IRUSR | S_IWUSR, driver_name);
+ S_IRUSR | S_IWUSR, "%s", driver_name);
}
#if defined(KLD_MODULE) && (__FreeBSD_version >= 503000)
@@ -1224,6 +1226,7 @@ static void override_kernel_driver(void)
static void hpt_init(void *dummy)
{
+ if (bootverbose)
os_printk("%s %s", driver_name_long, driver_ver);
override_kernel_driver();
diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c
index 71d8d8a..77eb93b 100644
--- a/sys/dev/hwpmc/hwpmc_core.c
+++ b/sys/dev/hwpmc/hwpmc_core.c
@@ -560,7 +560,8 @@ struct iap_event_descr {
#define IAP_F_SB (1 << 6) /* CPU: Sandy Bridge */
#define IAP_F_IB (1 << 7) /* CPU: Ivy Bridge */
#define IAP_F_SBX (1 << 8) /* CPU: Sandy Bridge Xeon */
-#define IAP_F_FM (1 << 9) /* Fixed mask */
+#define IAP_F_IBX (1 << 9) /* CPU: Ivy Bridge */
+#define IAP_F_FM (1 << 10) /* Fixed mask */
#define IAP_F_ALLCPUSCORE2 \
(IAP_F_CC | IAP_F_CC2 | IAP_F_CC2E | IAP_F_CA)
@@ -603,7 +604,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(03H_01H, 0x03, 0x01, IAP_F_FM | IAP_F_I7O | IAP_F_SB |
IAP_F_SBX),
IAPDESCR(03H_02H, 0x03, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(03H_04H, 0x03, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7O),
IAPDESCR(03H_08H, 0x03, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_SB |
IAP_F_SBX),
@@ -619,9 +620,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(05H_00H, 0x05, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(05H_01H, 0x05, 0x01, IAP_F_FM | IAP_F_I7O | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(05H_02H, 0x05, 0x02, IAP_F_FM | IAP_F_I7O | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(05H_03H, 0x05, 0x03, IAP_F_FM | IAP_F_I7O),
IAPDESCR(06H_00H, 0x06, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2 |
@@ -634,7 +635,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(07H_00H, 0x07, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
IAPDESCR(07H_01H, 0x07, 0x01, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(07H_02H, 0x07, 0x02, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(07H_03H, 0x07, 0x03, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(07H_06H, 0x07, 0x06, IAP_F_FM | IAP_F_CA),
@@ -657,9 +658,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(08H_20H, 0x08, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(08H_40H, 0x08, 0x40, IAP_F_FM | IAP_F_I7O),
IAPDESCR(08H_80H, 0x08, 0x80, IAP_F_FM | IAP_F_I7),
- IAPDESCR(08H_81H, 0x08, 0x81, IAP_F_FM | IAP_F_IB),
- IAPDESCR(08H_82H, 0x08, 0x82, IAP_F_FM | IAP_F_IB),
- IAPDESCR(08H_84H, 0x08, 0x84, IAP_F_FM | IAP_F_IB),
+ IAPDESCR(08H_81H, 0x08, 0x81, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(08H_82H, 0x08, 0x82, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(08H_84H, 0x08, 0x84, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
IAPDESCR(09H_01H, 0x09, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7O),
IAPDESCR(09H_02H, 0x09, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 | IAP_F_I7O),
@@ -679,11 +680,11 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(0DH_40H, 0x0D, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(0EH_01H, 0x0E, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(0EH_02H, 0x0E, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
- IAPDESCR(0EH_10H, 0x0E, 0x10, IAP_F_FM | IAP_F_IB),
- IAPDESCR(0EH_20H, 0x0E, 0x20, IAP_F_FM | IAP_F_IB),
- IAPDESCR(0EH_40H, 0x0E, 0x40, IAP_F_FM | IAP_F_IB),
+ IAPDESCR(0EH_10H, 0x0E, 0x10, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(0EH_20H, 0x0E, 0x20, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(0EH_40H, 0x0E, 0x40, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
IAPDESCR(0FH_01H, 0x0F, 0x01, IAP_F_FM | IAP_F_I7),
IAPDESCR(0FH_02H, 0x0F, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -733,7 +734,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(14H_00H, 0x14, 0x00, IAP_F_FM | IAP_F_CC | IAP_F_CC2),
IAPDESCR(14H_01H, 0x14, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7 |
- IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(14H_02H, 0x14, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(17H_01H, 0x17, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB |
@@ -760,28 +761,28 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(24H, 0x24, IAP_M_CORE | IAP_M_PREFETCH, IAP_F_ALLCPUSCORE2),
IAPDESCR(24H_01H, 0x24, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_02H, 0x24, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(24H_03H, 0x24, 0x03, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_04H, 0x24, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_08H, 0x24, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_0CH, 0x24, 0x0C, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_10H, 0x24, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_20H, 0x24, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_30H, 0x24, 0x30, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_40H, 0x24, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_80H, 0x24, 0x80, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_C0H, 0x24, 0xC0, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(24H_AAH, 0x24, 0xAA, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(24H_FFH, 0x24, 0xFF, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -802,15 +803,15 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(27H, 0x27, IAP_M_CORE | IAP_M_PREFETCH, IAP_F_ALLCPUSCORE2),
IAPDESCR(27H_01H, 0x27, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(27H_02H, 0x27, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(27H_04H, 0x27, 0x04, IAP_F_FM | IAP_F_I7O | IAP_F_SB |
IAP_F_SBX),
IAPDESCR(27H_08H, 0x27, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(27H_0EH, 0x27, 0x0E, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(27H_0FH, 0x27, 0x0F, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(27H_10H, 0x27, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(27H_20H, 0x27, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(27H_40H, 0x27, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -819,13 +820,15 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(27H_F0H, 0x27, 0xF0, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(28H, 0x28, IAP_M_CORE | IAP_M_MESI, IAP_F_ALLCPUSCORE2),
- IAPDESCR(28H_01H, 0x28, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_IB | IAP_F_SBX),
+ IAPDESCR(28H_01H, 0x28, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(28H_02H, 0x28, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SBX),
IAPDESCR(28H_04H, 0x28, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(28H_08H, 0x28, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
- IAPDESCR(28H_0FH, 0x28, 0x0F, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(28H_0FH, 0x28, 0x0F, IAP_F_FM | IAP_F_I7 | IAP_F_WM | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(29H, 0x29, IAP_M_CORE | IAP_M_MESI, IAP_F_CC),
IAPDESCR(29H, 0x29, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH,
@@ -838,9 +841,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(2EH_01H, 0x2E, 0x01, IAP_F_FM | IAP_F_WM),
IAPDESCR(2EH_02H, 0x2E, 0x02, IAP_F_FM | IAP_F_WM),
IAPDESCR(2EH_41H, 0x2E, 0x41, IAP_F_FM | IAP_F_ALLCPUSCORE2 | IAP_F_I7 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(2EH_4FH, 0x2E, 0x4F, IAP_F_FM | IAP_F_ALLCPUSCORE2 | IAP_F_I7 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(30H, 0x30, IAP_M_CORE | IAP_M_MESI | IAP_M_PREFETCH,
IAP_F_ALLCPUSCORE2),
@@ -853,9 +856,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(3BH_C0H, 0x3B, 0xC0, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(3CH_00H, 0x3C, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(3CH_01H, 0x3C, 0x01, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(3CH_02H, 0x3C, 0x02, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(3DH_01H, 0x3D, 0x01, IAP_F_FM | IAP_F_I7O),
@@ -897,18 +900,18 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(48H_00H, 0x48, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(48H_01H, 0x48, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(48H_02H, 0x48, 0x02, IAP_F_FM | IAP_F_I7O),
IAPDESCR(49H_00H, 0x49, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(49H_01H, 0x49, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(49H_02H, 0x49, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(49H_04H, 0x49, 0x04, IAP_F_FM | IAP_F_WM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(49H_10H, 0x49, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(49H_20H, 0x49, 0x20, IAP_F_FM | IAP_F_I7),
IAPDESCR(49H_40H, 0x49, 0x40, IAP_F_FM | IAP_F_I7O),
IAPDESCR(49H_80H, 0x49, 0x80, IAP_F_FM | IAP_F_WM | IAP_F_I7),
@@ -921,9 +924,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(4CH_00H, 0x4C, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(4CH_01H, 0x4C, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(4CH_02H, 0x4C, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(4DH_01H, 0x4D, 0x01, IAP_F_FM | IAP_F_I7O),
@@ -940,7 +943,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(4FH_10H, 0x4F, 0x10, IAP_F_FM | IAP_F_WM),
IAPDESCR(51H_01H, 0x51, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(51H_02H, 0x51, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
IAP_F_SB | IAP_F_SBX),
IAPDESCR(51H_04H, 0x51, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
@@ -952,10 +955,10 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(53H_01H, 0x53, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
- IAPDESCR(58H_01H, 0x58, 0x01, IAP_F_FM | IAP_F_IB),
- IAPDESCR(58H_02H, 0x58, 0x02, IAP_F_FM | IAP_F_IB),
- IAPDESCR(58H_04H, 0x58, 0x04, IAP_F_FM | IAP_F_IB),
- IAPDESCR(58H_08H, 0x58, 0x08, IAP_F_FM | IAP_F_IB),
+ IAPDESCR(58H_01H, 0x58, 0x01, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(58H_02H, 0x58, 0x02, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(58H_04H, 0x58, 0x04, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(58H_08H, 0x58, 0x08, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
IAPDESCR(59H_20H, 0x59, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(59H_40H, 0x59, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
@@ -967,23 +970,25 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(5BH_4FH, 0x5B, 0x4F, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(5CH_01H, 0x5C, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(5CH_02H, 0x5C, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(5EH_01H, 0x5E, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(5FH_01H, 0x5F, 0x01, IAP_F_FM | IAP_F_IB),
+ IAPDESCR(5FH_04H, 0x5F, 0x04, IAP_F_IBX),
IAPDESCR(60H, 0x60, IAP_M_AGENT | IAP_M_CORE, IAP_F_ALLCPUSCORE2),
IAPDESCR(60H_01H, 0x60, 0x01, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
- IAPDESCR(60H_02H, 0x60, 0x02, IAP_F_FM | IAP_F_WM | IAP_F_I7O | IAP_F_IB),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(60H_02H, 0x60, 0x02, IAP_F_FM | IAP_F_WM | IAP_F_I7O | IAP_F_IB |
+ IAP_F_IBX),
IAPDESCR(60H_04H, 0x60, 0x04, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(60H_08H, 0x60, 0x08, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(61H, 0x61, IAP_M_AGENT, IAP_F_CA | IAP_F_CC2),
IAPDESCR(61H_00H, 0x61, 0x00, IAP_F_FM | IAP_F_CC),
@@ -995,9 +1000,9 @@ static struct iap_event_descr iap_events[] = {
IAP_F_CA | IAP_F_CC2),
IAPDESCR(63H, 0x63, IAP_M_CORE, IAP_F_CC),
IAPDESCR(63H_01H, 0x63, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(63H_02H, 0x63, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(64H, 0x64, IAP_M_CORE, IAP_F_CA | IAP_F_CC2),
IAPDESCR(64H_40H, 0x64, 0x40, IAP_F_FM | IAP_F_CC),
@@ -1039,20 +1044,20 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(78H, 0x78, IAP_M_CORE | IAP_M_SNOOPTYPE, IAP_F_CA | IAP_F_CC2),
IAPDESCR(79H_02H, 0x79, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(79H_04H, 0x79, 0x04, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(79H_08H, 0x79, 0x08, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(79H_10H, 0x79, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(79H_20H, 0x79, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(79H_30H, 0x79, 0x30, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
- IAPDESCR(79H_18H, 0x79, 0x18, IAP_F_FM | IAP_F_IB),
- IAPDESCR(79H_24H, 0x79, 0x24, IAP_F_FM | IAP_F_IB),
- IAPDESCR(79H_3CH, 0x79, 0x3C, IAP_F_FM | IAP_F_IB),
+ IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(79H_18H, 0x79, 0x18, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(79H_24H, 0x79, 0x24, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
+ IAPDESCR(79H_3CH, 0x79, 0x3C, IAP_F_FM | IAP_F_IB | IAP_F_IBX),
IAPDESCR(7AH, 0x7A, IAP_M_AGENT, IAP_F_CA | IAP_F_CC2),
@@ -1068,7 +1073,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(80H_00H, 0x80, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(80H_01H, 0x80, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(80H_02H, 0x80, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_I7 |
- IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(80H_03H, 0x80, 0x03, IAP_F_FM | IAP_F_CA | IAP_F_I7 |
IAP_F_WM),
IAPDESCR(80H_04H, 0x80, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1089,13 +1094,13 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(85H_00H, 0x85, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(85H_01H, 0x85, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(85H_02H, 0x85, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(85H_04H, 0x85, 0x04, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(85H_10H, 0x85, 0x10, IAP_F_FM | IAP_F_I7O | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(85H_20H, 0x85, 0x20, IAP_F_FM | IAP_F_I7O),
IAPDESCR(85H_40H, 0x85, 0x40, IAP_F_FM | IAP_F_I7O),
IAPDESCR(85H_80H, 0x85, 0x80, IAP_F_FM | IAP_F_WM | IAP_F_I7O),
@@ -1104,57 +1109,57 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(87H_00H, 0x87, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(87H_01H, 0x87, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(87H_02H, 0x87, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(87H_04H, 0x87, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(87H_08H, 0x87, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(87H_0FH, 0x87, 0x0F, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(88H_00H, 0x88, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(88H_01H, 0x88, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_02H, 0x88, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_04H, 0x88, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_07H, 0x88, 0x07, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(88H_08H, 0x88, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_10H, 0x88, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_20H, 0x88, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_30H, 0x88, 0x30, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(88H_40H, 0x88, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_7FH, 0x88, 0x7F, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(88H_80H, 0x88, 0x80, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(88H_FFH, 0x88, 0xFF, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_00H, 0x89, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(89H_01H, 0x89, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_02H, 0x89, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(89H_04H, 0x89, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_07H, 0x89, 0x07, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(89H_08H, 0x89, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_10H, 0x89, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_20H, 0x89, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_30H, 0x89, 0x30, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(89H_40H, 0x89, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_7FH, 0x89, 0x7F, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(89H_80H, 0x89, 0x80, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(89H_FFH, 0x89, 0xFF, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(8AH_00H, 0x8A, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(8BH_00H, 0x8B, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
@@ -1170,44 +1175,44 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(94H_00H, 0x94, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(9CH_01H, 0x9C, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(97H_00H, 0x97, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(98H_00H, 0x98, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(A0H_00H, 0xA0, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(A1H_01H, 0xA1, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_02H, 0xA1, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_04H, 0xA1, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_08H, 0xA1, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_0CH, 0xA1, 0x0C, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_10H, 0xA1, 0x10, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_20H, 0xA1, 0x20, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_30H, 0xA1, 0x30, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_40H, 0xA1, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A1H_80H, 0xA1, 0x80, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A2H_00H, 0xA2, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(A2H_01H, 0xA2, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A2H_02H, 0xA2, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
IAP_F_SB | IAP_F_SBX),
IAPDESCR(A2H_04H, 0xA2, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A2H_08H, 0xA2, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A2H_10H, 0xA2, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(A2H_20H, 0xA2, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
IAP_F_SB | IAP_F_SBX),
IAPDESCR(A2H_40H, 0xA2, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
@@ -1215,9 +1220,10 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(A2H_80H, 0xA2, 0x80, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
IAP_F_SB | IAP_F_SBX),
- IAPDESCR(A3H_01H, 0xA3, 0x01, IAP_F_FM | IAP_F_SBX),
- IAPDESCR(A3H_02H, 0xA3, 0x02, IAP_F_FM | IAP_F_SBX),
- IAPDESCR(A3H_04H, 0xA3, 0x04, IAP_F_FM | IAP_F_SBX),
+ IAPDESCR(A3H_01H, 0xA3, 0x01, IAP_F_FM | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(A3H_02H, 0xA3, 0x02, IAP_F_FM | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(A3H_04H, 0xA3, 0x04, IAP_F_FM | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(A3H_08H, 0xA3, 0x08, IAP_F_IBX),
IAPDESCR(A6H_01H, 0xA6, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(A7H_01H, 0xA7, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1229,26 +1235,27 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(AAH_08H, 0xAA, 0x08, IAP_F_FM | IAP_F_CC2),
IAPDESCR(ABH_01H, 0xAB, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(ABH_02H, 0xAB, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(ACH_02H, 0xAC, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(ACH_08H, 0xAC, 0x08, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(ACH_0AH, 0xAC, 0x0A, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(AEH_01H, 0xAE, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IB),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B0H_00H, 0xB0, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(B0H_01H, 0xB0, 0x01, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
- IAPDESCR(B0H_02H, 0xB0, 0x02, IAP_F_FM | IAP_F_WM | IAP_F_I7O | IAP_F_IB),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(B0H_02H, 0xB0, 0x02, IAP_F_FM | IAP_F_WM | IAP_F_I7O | IAP_F_IB |
+ IAP_F_IBX),
IAPDESCR(B0H_04H, 0xB0, 0x04, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B0H_08H, 0xB0, 0x08, IAP_F_FM | IAP_F_WM | IAP_F_I7O |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B0H_10H, 0xB0, 0x10, IAP_F_FM | IAP_F_WM | IAP_F_I7O),
IAPDESCR(B0H_20H, 0xB0, 0x20, IAP_F_FM | IAP_F_I7O),
IAPDESCR(B0H_40H, 0xB0, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1256,9 +1263,9 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(B1H_00H, 0xB1, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(B1H_01H, 0xB1, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B1H_02H, 0xB1, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B1H_04H, 0xB1, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(B1H_08H, 0xB1, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(B1H_10H, 0xB1, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1295,7 +1302,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(B6H_01H, 0xB6, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(B7H_01H, 0xB7, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(B8H_01H, 0xB8, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(B8H_02H, 0xB8, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1305,19 +1312,20 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(BAH_02H, 0xBA, 0x02, IAP_F_FM | IAP_F_I7O),
IAPDESCR(BBH_01H, 0xBB, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(BDH_01H, 0xBD, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(BDH_20H, 0xBD, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(BFH_05H, 0xBF, 0x05, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(C0H_00H, 0xC0, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C0H_01H, 0xC0, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C0H_02H, 0xC0, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM | IAP_F_SB),
IAPDESCR(C0H_04H, 0xC0, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
@@ -1328,18 +1336,20 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(C1H_01H, 0xC1, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(C1H_02H, 0xC1, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
IAPDESCR(C1H_08H, 0xC1, 0x08, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C1H_10H, 0xC1, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C1H_20H, 0xC1, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C1H_FEH, 0xC1, 0xFE, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(C2H_00H, 0xC2, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(C2H_01H, 0xC2, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C2H_02H, 0xC2, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C2H_04H, 0xC2, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM),
IAPDESCR(C2H_07H, 0xC2, 0x07, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
@@ -1351,44 +1361,50 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(C3H_01H, 0xC3, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM),
IAPDESCR(C3H_02H, 0xC3, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C3H_04H, 0xC3, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C3H_10H, 0xC3, 0x10, IAP_F_FM | IAP_F_I7O),
IAPDESCR(C3H_20H, 0xC3, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C4H_00H, 0xC4, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C4H_01H, 0xC4, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C4H_02H, 0xC4, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C4H_04H, 0xC4, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C4H_08H, 0xC4, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C4H_0CH, 0xC4, 0x0C, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(C4H_0FH, 0xC4, 0x0F, IAP_F_FM | IAP_F_CA),
IAPDESCR(C4H_10H, 0xC4, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C4H_20H, 0xC4, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C4H_40H, 0xC4, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C5H_00H, 0xC5, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(C5H_01H, 0xC5, 0x01, IAP_F_FM | IAP_F_WM | IAP_F_SB |
- IAP_F_IB | IAP_F_SBX),
+ IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C5H_02H, 0xC5, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C5H_04H, 0xC5, 0x04, IAP_F_FM | IAP_F_WM | IAP_F_SB |
- IAP_F_IB | IAP_F_SBX),
+ IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C5H_10H, 0xC5, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C5H_20H, 0xC5, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(C6H_00H, 0xC6, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(C6H_01H, 0xC6, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
@@ -1415,15 +1431,15 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(CAH_00H, 0xCA, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(CAH_01H, 0xCA, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(CAH_02H, 0xCA, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CAH_04H, 0xCA, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CAH_08H, 0xCA, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CAH_10H, 0xCA, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CAH_1EH, 0xCA, 0x1E, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CBH_01H, 0xCB, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM),
@@ -1445,56 +1461,59 @@ static struct iap_event_descr iap_events[] = {
IAP_F_I7 | IAP_F_WM),
IAPDESCR(CCH_03H, 0xCC, 0x03, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(CCH_20H, 0xCC, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CDH_00H, 0xCD, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(CDH_01H, 0xCD, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CDH_02H, 0xCD, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(CEH_00H, 0xCE, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(CFH_00H, 0xCF, 0x00, IAP_F_FM | IAP_F_CA | IAP_F_CC2),
IAPDESCR(D0H_00H, 0xD0, 0x00, IAP_F_FM | IAP_F_CC),
IAPDESCR(D0H_01H, 0xD0, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D0H_02H, 0xD0, 0x02, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D0H_10H, 0xD0, 0x10, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D0H_20H, 0xD0, 0x20, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D0H_40H, 0xD0, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D0H_80H, 0xD0, 0X80, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D1H_01H, 0xD1, 0x01, IAP_F_FM | IAP_F_WM | IAP_F_SB |
- IAP_F_IB | IAP_F_SBX),
+ IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D1H_02H, 0xD1, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D1H_04H, 0xD1, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D1H_08H, 0xD1, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
- IAPDESCR(D1H_20H, 0xD1, 0x20, IAP_F_FM | IAP_F_SBX),
+ IAPDESCR(D1H_20H, 0xD1, 0x20, IAP_F_FM | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D1H_40H, 0xD1, 0x40, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(D2H_01H, 0xD2, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_IBX),
IAPDESCR(D2H_02H, 0xD2, 0x02, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_IBX),
IAPDESCR(D2H_04H, 0xD2, 0x04, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_IBX),
IAPDESCR(D2H_08H, 0xD2, 0x08, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
- IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB),
+ IAP_F_I7 | IAP_F_WM | IAP_F_SB | IAP_F_IB | IAP_F_IBX),
IAPDESCR(D2H_0FH, 0xD2, 0x0F, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM),
IAPDESCR(D2H_10H, 0xD2, 0x10, IAP_F_FM | IAP_F_CC2E),
- IAPDESCR(D3H_01H, 0xD3, 0x01, IAP_F_FM | IAP_F_IB | IAP_F_SBX),
- IAPDESCR(D3H_04H, 0xD3, 0x04, IAP_F_FM | IAP_F_SBX),
+ IAPDESCR(D3H_01H, 0xD3, 0x01, IAP_F_FM | IAP_F_IB | IAP_F_SBX |
+ IAP_F_IBX),
+ IAPDESCR(D3H_04H, 0xD3, 0x04, IAP_F_FM | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(D3H_10H, 0xD3, 0x10, IAP_F_IBX),
+ IAPDESCR(D3H_20H, 0xD3, 0x20, IAP_F_IBX),
IAPDESCR(D4H_01H, 0xD4, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_CC2 |
IAP_F_I7 | IAP_F_WM),
@@ -1553,6 +1572,7 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(E6H_01H, 0xE6, 0x01, IAP_F_FM | IAP_F_CA | IAP_F_I7 |
IAP_F_WM | IAP_F_SBX),
IAPDESCR(E6H_02H, 0xE6, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
+ IAPDESCR(E6H_1FH, 0xE6, 0x1F, IAP_F_IBX),
IAPDESCR(E8H_01H, 0xE8, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(E8H_02H, 0xE8, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
@@ -1562,40 +1582,41 @@ static struct iap_event_descr iap_events[] = {
IAPDESCR(F0H_00H, 0xF0, 0x00, IAP_F_FM | IAP_F_ALLCPUSCORE2),
IAPDESCR(F0H_01H, 0xF0, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_02H, 0xF0, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_04H, 0xF0, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_08H, 0xF0, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_10H, 0xF0, 0x10, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_20H, 0xF0, 0x20, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_40H, 0xF0, 0x40, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F0H_80H, 0xF0, 0x80, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F1H_01H, 0xF1, 0x01, IAP_F_FM | IAP_F_SB | IAP_F_IB |
- IAP_F_SBX),
+ IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F1H_02H, 0xF1, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F1H_04H, 0xF1, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F1H_07H, 0xF1, 0x07, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F2H_01H, 0xF2, 0x01, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F2H_02H, 0xF2, 0x02, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F2H_04H, 0xF2, 0x04, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
IAPDESCR(F2H_08H, 0xF2, 0x08, IAP_F_FM | IAP_F_I7 | IAP_F_WM |
- IAP_F_SB | IAP_F_IB | IAP_F_SBX),
- IAPDESCR(F2H_0AH, 0xF2, 0x0A, IAP_F_FM | IAP_F_SB | IAP_F_SBX),
+ IAP_F_SB | IAP_F_IB | IAP_F_SBX | IAP_F_IBX),
+ IAPDESCR(F2H_0AH, 0xF2, 0x0A, IAP_F_FM | IAP_F_SB | IAP_F_SBX |
+ IAP_F_IBX),
IAPDESCR(F2H_0FH, 0xF2, 0x0F, IAP_F_FM | IAP_F_I7 | IAP_F_WM),
IAPDESCR(F3H_01H, 0xF3, 0x01, IAP_F_FM | IAP_F_I7O),
@@ -1782,7 +1803,7 @@ iap_event_westmere_ok_on_counter(enum pmc_event pe, int ri)
}
static int
-iap_event_sb_sbx_ib_ok_on_counter(enum pmc_event pe, int ri)
+iap_event_sb_sbx_ib_ibx_ok_on_counter(enum pmc_event pe, int ri)
{
uint32_t mask;
@@ -1801,6 +1822,7 @@ iap_event_sb_sbx_ib_ok_on_counter(enum pmc_event pe, int ri)
mask = 0x4;
break;
/* Events valid only on counter 3. */
+ case PMC_EV_IAP_EVENT_A3H_08H:
case PMC_EV_IAP_EVENT_BBH_01H:
case PMC_EV_IAP_EVENT_CDH_01H:
case PMC_EV_IAP_EVENT_CDH_02H:
@@ -1892,7 +1914,8 @@ iap_allocate_pmc(int cpu, int ri, struct pmc *pm,
case PMC_CPU_INTEL_SANDYBRIDGE:
case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
case PMC_CPU_INTEL_IVYBRIDGE:
- if (iap_event_sb_sbx_ib_ok_on_counter(ev, ri) == 0)
+ case PMC_CPU_INTEL_IVYBRIDGE_XEON:
+ if (iap_event_sb_sbx_ib_ibx_ok_on_counter(ev, ri) == 0)
return (EINVAL);
break;
case PMC_CPU_INTEL_WESTMERE:
@@ -1929,6 +1952,9 @@ iap_allocate_pmc(int cpu, int ri, struct pmc *pm,
case PMC_CPU_INTEL_IVYBRIDGE:
cpuflag = IAP_F_IB;
break;
+ case PMC_CPU_INTEL_IVYBRIDGE_XEON:
+ cpuflag = IAP_F_IBX;
+ break;
case PMC_CPU_INTEL_SANDYBRIDGE:
cpuflag = IAP_F_SB;
break;
@@ -2043,8 +2069,9 @@ iap_allocate_pmc(int cpu, int ri, struct pmc *pm,
a->pm_md.pm_iap.pm_iap_rsp & ~IA_OFFCORE_RSP_MASK_I7WM)
return (EINVAL);
else if ((core_cputype == PMC_CPU_INTEL_SANDYBRIDGE ||
- core_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON ||
- core_cputype == PMC_CPU_INTEL_IVYBRIDGE) &&
+ core_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON ||
+ core_cputype == PMC_CPU_INTEL_IVYBRIDGE ||
+ core_cputype == PMC_CPU_INTEL_IVYBRIDGE_XEON) &&
a->pm_md.pm_iap.pm_iap_rsp & ~IA_OFFCORE_RSP_MASK_SBIB)
return (EINVAL);
pm->pm_md.pm_iap.pm_iap_rsp = a->pm_md.pm_iap.pm_iap_rsp;
diff --git a/sys/dev/hwpmc/hwpmc_intel.c b/sys/dev/hwpmc/hwpmc_intel.c
index f633ac9..00ec29e 100644
--- a/sys/dev/hwpmc/hwpmc_intel.c
+++ b/sys/dev/hwpmc/hwpmc_intel.c
@@ -154,6 +154,10 @@ pmc_intel_initialize(void)
cputype = PMC_CPU_INTEL_IVYBRIDGE;
nclasses = 3;
break;
+ case 0x3E: /* Per Intel document 325462-045US 01/2013. */
+ cputype = PMC_CPU_INTEL_IVYBRIDGE_XEON;
+ nclasses = 3;
+ break;
}
break;
#if defined(__i386__) || defined(__amd64__)
@@ -196,6 +200,7 @@ pmc_intel_initialize(void)
case PMC_CPU_INTEL_SANDYBRIDGE:
case PMC_CPU_INTEL_WESTMERE:
case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
+ case PMC_CPU_INTEL_IVYBRIDGE_XEON:
error = pmc_core_initialize(pmc_mdep, ncpus);
break;
@@ -280,6 +285,7 @@ pmc_intel_finalize(struct pmc_mdep *md)
case PMC_CPU_INTEL_SANDYBRIDGE:
case PMC_CPU_INTEL_WESTMERE:
case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
+ case PMC_CPU_INTEL_IVYBRIDGE_XEON:
pmc_core_finalize(md);
break;
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 9e82a34..2f2f05a 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -3022,7 +3022,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
}
nevent = 0;
- for (ev = PMC_EV_SOFT_FIRST; ev <= PMC_EV_SOFT_LAST; ev++) {
+ for (ev = PMC_EV_SOFT_FIRST; (int)ev <= PMC_EV_SOFT_LAST; ev++) {
ps = pmc_soft_ev_acquire(ev);
if (ps == NULL)
continue;
diff --git a/sys/dev/hwpmc/hwpmc_soft.c b/sys/dev/hwpmc/hwpmc_soft.c
index c3d2dec..dac3612 100644
--- a/sys/dev/hwpmc/hwpmc_soft.c
+++ b/sys/dev/hwpmc/hwpmc_soft.c
@@ -116,7 +116,7 @@ soft_allocate_pmc(int cpu, int ri, struct pmc *pm,
return (EPERM);
ev = pm->pm_event;
- if (ev < PMC_EV_SOFT_FIRST || ev > PMC_EV_SOFT_LAST)
+ if ((int)ev < PMC_EV_SOFT_FIRST || (int)ev > PMC_EV_SOFT_LAST)
return (EINVAL);
/* Check if event is registered. */
diff --git a/sys/dev/hwpmc/pmc_events.h b/sys/dev/hwpmc/pmc_events.h
index cb22324..8f246f6 100644
--- a/sys/dev/hwpmc/pmc_events.h
+++ b/sys/dev/hwpmc/pmc_events.h
@@ -722,6 +722,7 @@ __PMC_EV(IAP, EVENT_5CH_01H) \
__PMC_EV(IAP, EVENT_5CH_02H) \
__PMC_EV(IAP, EVENT_5EH_01H) \
__PMC_EV(IAP, EVENT_5FH_01H) \
+__PMC_EV(IAP, EVENT_5FH_04H) \
__PMC_EV(IAP, EVENT_60H) \
__PMC_EV(IAP, EVENT_60H_01H) \
__PMC_EV(IAP, EVENT_60H_02H) \
@@ -861,6 +862,7 @@ __PMC_EV(IAP, EVENT_A2H_80H) \
__PMC_EV(IAP, EVENT_A3H_01H) \
__PMC_EV(IAP, EVENT_A3H_02H) \
__PMC_EV(IAP, EVENT_A3H_04H) \
+__PMC_EV(IAP, EVENT_A3H_08H) \
__PMC_EV(IAP, EVENT_A6H_01H) \
__PMC_EV(IAP, EVENT_A7H_01H) \
__PMC_EV(IAP, EVENT_A8H_01H) \
@@ -1021,6 +1023,8 @@ __PMC_EV(IAP, EVENT_D2H_0FH) \
__PMC_EV(IAP, EVENT_D2H_10H) \
__PMC_EV(IAP, EVENT_D3H_01H) \
__PMC_EV(IAP, EVENT_D3H_04H) \
+__PMC_EV(IAP, EVENT_D3H_10H) \
+__PMC_EV(IAP, EVENT_D3H_20H) \
__PMC_EV(IAP, EVENT_D4H_01H) \
__PMC_EV(IAP, EVENT_D4H_02H) \
__PMC_EV(IAP, EVENT_D4H_04H) \
@@ -1061,6 +1065,7 @@ __PMC_EV(IAP, EVENT_E5H_01H) \
__PMC_EV(IAP, EVENT_E6H_00H) \
__PMC_EV(IAP, EVENT_E6H_01H) \
__PMC_EV(IAP, EVENT_E6H_02H) \
+__PMC_EV(IAP, EVENT_E6H_1FH) \
__PMC_EV(IAP, EVENT_E8H_01H) \
__PMC_EV(IAP, EVENT_E8H_02H) \
__PMC_EV(IAP, EVENT_E8H_03H) \
@@ -2584,6 +2589,205 @@ __PMC_EV_ALIAS("L2_LINES_OUT.PF_CLEAN", IAP_EVENT_F2H_04H) \
__PMC_EV_ALIAS("L2_LINES_OUT.PF_DIRTY", IAP_EVENT_F2H_08H)
/*
+ * Aliases for Ivy Bridge Xeon PMC events (325462-045US January 2013)
+ */
+
+#define __PMC_EV_ALIAS_IVYBRIDGE_XEON() \
+__PMC_EV_ALIAS("LD_BLOCKS.STORE_FORWARD", IAP_EVENT_03H_02H) \
+__PMC_EV_ALIAS("MISALIGN_MEM_REF.LOADS", IAP_EVENT_05H_01H) \
+__PMC_EV_ALIAS("MISALIGN_MEM_REF.STORES", IAP_EVENT_05H_02H) \
+__PMC_EV_ALIAS("LD_BLOCKS_PARTIAL.ADDRESS_ALIAS", IAP_EVENT_07H_01H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.DEMAND_LD_MISS_CAUSES_A_WALK", IAP_EVENT_08H_81H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.DEMAND_LD_WALK_COMPLETED", IAP_EVENT_08H_82H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.DEMAND_LD_WALK_DURATION", IAP_EVENT_08H_84H) \
+__PMC_EV_ALIAS("UOPS_ISSUED.ANY", IAP_EVENT_0EH_01H) \
+__PMC_EV_ALIAS("UOPS_ISSUED.FLAGS_MERGE", IAP_EVENT_0EH_10H) \
+__PMC_EV_ALIAS("UOPS_ISSUED.SLOW_LEA", IAP_EVENT_0EH_20H) \
+__PMC_EV_ALIAS("UOPS_ISSUED.SINGLE_MUL", IAP_EVENT_0EH_40H) \
+__PMC_EV_ALIAS("ARITH.FPU_DIV_ACTIVE", IAP_EVENT_14H_01H) \
+__PMC_EV_ALIAS("L2_RQSTS.DEMAND_DATA_RD_HIT", IAP_EVENT_24H_01H) \
+__PMC_EV_ALIAS("L2_RQSTS.ALL_DEMAND_DATA_RD", IAP_EVENT_24H_03H) \
+__PMC_EV_ALIAS("L2_RQSTS.RFO_HITS", IAP_EVENT_24H_04H) \
+__PMC_EV_ALIAS("L2_RQSTS.RFO_MISS", IAP_EVENT_24H_08H) \
+__PMC_EV_ALIAS("L2_RQSTS.ALL_RFO", IAP_EVENT_24H_0CH) \
+__PMC_EV_ALIAS("L2_RQSTS.CODE_RD_HIT", IAP_EVENT_24H_10H) \
+__PMC_EV_ALIAS("L2_RQSTS.CODE_RD_MISS", IAP_EVENT_24H_20H) \
+__PMC_EV_ALIAS("L2_RQSTS.ALL_CODE_RD", IAP_EVENT_24H_30H) \
+__PMC_EV_ALIAS("L2_RQSTS.PF_HIT", IAP_EVENT_24H_40H) \
+__PMC_EV_ALIAS("L2_RQSTS.PF_MISS", IAP_EVENT_24H_80H) \
+__PMC_EV_ALIAS("L2_RQSTS.ALL_PF", IAP_EVENT_24H_C0H) \
+__PMC_EV_ALIAS("L2_STORE_LOCK_RQSTS.MISS", IAP_EVENT_27H_01H) \
+__PMC_EV_ALIAS("L2_STORE_LOCK_RQSTS.HIT_M", IAP_EVENT_27H_08H) \
+__PMC_EV_ALIAS("L2_STORE_LOCK_RQSTS.ALL", IAP_EVENT_27H_0FH) \
+__PMC_EV_ALIAS("L2_L1D_WB_RQSTS.MISS", IAP_EVENT_28H_01H) \
+__PMC_EV_ALIAS("L2_L1D_WB_RQSTS.HIT_E", IAP_EVENT_28H_04H) \
+__PMC_EV_ALIAS("L2_L1D_WB_RQSTS.HIT_M", IAP_EVENT_28H_08H) \
+__PMC_EV_ALIAS("L2_L1D_WB_RQSTS.ALL", IAP_EVENT_28H_0FH) \
+__PMC_EV_ALIAS("LONGEST_LAT_CACHE.REFERENCE", IAP_EVENT_2EH_4FH) \
+__PMC_EV_ALIAS("LONGEST_LAT_CACHE.MISS", IAP_EVENT_2EH_41H) \
+__PMC_EV_ALIAS("CPU_CLK_UNHALTED.THREAD_P", IAP_EVENT_3CH_00H) \
+__PMC_EV_ALIAS("CPU_CLK_THREAD_UNHALTED.REF_XCLK", IAP_EVENT_3CH_01H) \
+__PMC_EV_ALIAS("L1D_PEND_MISS.PENDING", IAP_EVENT_48H_01H) \
+__PMC_EV_ALIAS("DTLB_STORE_MISSES.MISS_CAUSES_A_WALK", IAP_EVENT_49H_01H) \
+__PMC_EV_ALIAS("DTLB_STORE_MISSES.WALK_COMPLETED", IAP_EVENT_49H_02H) \
+__PMC_EV_ALIAS("DTLB_STORE_MISSES.WALK_DURATION", IAP_EVENT_49H_04H) \
+__PMC_EV_ALIAS("DTLB_STORE_MISSES.STLB_HIT", IAP_EVENT_49H_10H) \
+__PMC_EV_ALIAS("LOAD_HIT_PRE.SW_PF", IAP_EVENT_4CH_01H) \
+__PMC_EV_ALIAS("LOAD_HIT_PRE.HW_PF", IAP_EVENT_4CH_02H) \
+__PMC_EV_ALIAS("L1D.REPLACEMENT", IAP_EVENT_51H_01H) \
+__PMC_EV_ALIAS("MOVE_ELIMINATION.INT_NOT_ELIMINATED", IAP_EVENT_58H_01H) \
+__PMC_EV_ALIAS("MOVE_ELIMINATION.SIMD_NOT_ELIMINATED", IAP_EVENT_58H_02H) \
+__PMC_EV_ALIAS("MOVE_ELIMINATION.INT_ELIMINATED", IAP_EVENT_58H_04H) \
+__PMC_EV_ALIAS("MOVE_ELIMINATION.SIMD_ELIMINATED", IAP_EVENT_58H_08H) \
+__PMC_EV_ALIAS("CPL_CYCLES.RING0", IAP_EVENT_5CH_01H) \
+__PMC_EV_ALIAS("CPL_CYCLES.RING123", IAP_EVENT_5CH_02H) \
+__PMC_EV_ALIAS("RS_EVENTS.EMPTY_CYCLES", IAP_EVENT_5EH_01H) \
+__PMC_EV_ALIAS("DTLB_LOAD_MISSES.STLB_HIT", IAP_EVENT_5FH_04H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD", IAP_EVENT_60H_01H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.DEMAND_CODE_RD", IAP_EVENT_60H_02H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.DEMAND_RFO", IAP_EVENT_60H_04H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD", IAP_EVENT_60H_08H) \
+__PMC_EV_ALIAS("LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION", IAP_EVENT_63H_01H) \
+__PMC_EV_ALIAS("LOCK_CYCLES.CACHE_LOCK_DURATION", IAP_EVENT_63H_02H) \
+__PMC_EV_ALIAS("IDQ.EMPTY", IAP_EVENT_79H_02H) \
+__PMC_EV_ALIAS("IDQ.MITE_UOPS", IAP_EVENT_79H_04H) \
+__PMC_EV_ALIAS("IDQ.DSB_UOPS", IAP_EVENT_79H_08H) \
+__PMC_EV_ALIAS("IDQ.MS_DSB_UOPS", IAP_EVENT_79H_10H) \
+__PMC_EV_ALIAS("IDQ.MS_MITE_UOPS", IAP_EVENT_79H_20H) \
+__PMC_EV_ALIAS("IDQ.MS_UOPS", IAP_EVENT_79H_30H) \
+__PMC_EV_ALIAS("IDQ.ALL_DSB_CYCLES_ANY_UOPS", IAP_EVENT_79H_18H) \
+__PMC_EV_ALIAS("IDQ.ALL_DSB_CYCLES_4_UOPS", IAP_EVENT_79H_18H) \
+__PMC_EV_ALIAS("IDQ.ALL_MITE_CYCLES_ANY_UOPS", IAP_EVENT_79H_24H) \
+__PMC_EV_ALIAS("IDQ.ALL_MITE_CYCLES_4_UOPS", IAP_EVENT_79H_24H) \
+__PMC_EV_ALIAS("IDQ.MITE_ALL_UOPS", IAP_EVENT_79H_3CH) \
+__PMC_EV_ALIAS("ICACHE.MISSES", IAP_EVENT_80H_02H) \
+__PMC_EV_ALIAS("ITLB_MISSES.MISS_CAUSES_A_WALK", IAP_EVENT_85H_01H) \
+__PMC_EV_ALIAS("ITLB_MISSES.WALK_COMPLETED", IAP_EVENT_85H_02H) \
+__PMC_EV_ALIAS("ITLB_MISSES.WALK_DURATION", IAP_EVENT_85H_04H) \
+__PMC_EV_ALIAS("ITLB_MISSES.STLB_HIT", IAP_EVENT_85H_10H) \
+__PMC_EV_ALIAS("ILD_STALL.LCP", IAP_EVENT_87H_01H) \
+__PMC_EV_ALIAS("ILD_STALL.IQ_FULL", IAP_EVENT_87H_04H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.COND", IAP_EVENT_88H_01H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.DIRECT_JMP", IAP_EVENT_88H_02H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.INDIRECT_JMP_NON_CALL_RET", IAP_EVENT_88H_04H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.RETURN_NEAR", IAP_EVENT_88H_08H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.DIRECT_NEAR_CALL", IAP_EVENT_88H_10H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.INDIRECT_NEAR_CALL", IAP_EVENT_88H_20H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.NONTAKEN", IAP_EVENT_88H_40H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.TAKEN", IAP_EVENT_88H_80H) \
+__PMC_EV_ALIAS("BR_INST_EXEC.ALL_BRANCHES", IAP_EVENT_88H_FFH) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.COND", IAP_EVENT_89H_01H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.INDIRECT_JMP_NON_CALL_RET", IAP_EVENT_89H_04H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.RETURN_NEAR", IAP_EVENT_89H_08H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.DIRECT_NEAR_CALL", IAP_EVENT_89H_10H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.INDIRECT_NEAR_CALL", IAP_EVENT_89H_20H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.NONTAKEN", IAP_EVENT_89H_40H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.TAKEN", IAP_EVENT_89H_80H) \
+__PMC_EV_ALIAS("BR_MISP_EXEC.ALL_BRANCHES", IAP_EVENT_89H_FFH) \
+__PMC_EV_ALIAS("IDQ_UOPS_NOT_DELIVERED.CORE", IAP_EVENT_9CH_01H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_0", IAP_EVENT_A1H_01H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_1", IAP_EVENT_A1H_02H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_2_LD", IAP_EVENT_A1H_04H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_2_STA", IAP_EVENT_A1H_08H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_2", IAP_EVENT_A1H_0CH) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_3_LD", IAP_EVENT_A1H_10H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_3_STA", IAP_EVENT_A1H_20H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_3", IAP_EVENT_A1H_30H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_4", IAP_EVENT_A1H_40H) \
+__PMC_EV_ALIAS("UOPS_DISPATCHED_PORT.PORT_5", IAP_EVENT_A1H_80H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.ANY", IAP_EVENT_A2H_01H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.RS", IAP_EVENT_A2H_04H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.SB", IAP_EVENT_A2H_08H) \
+__PMC_EV_ALIAS("RESOURCE_STALLS.ROB", IAP_EVENT_A2H_10H) \
+__PMC_EV_ALIAS("CYCLE_ACTIVITY.CYCLES_L2_PENDING", IAP_EVENT_A3H_01H) \
+__PMC_EV_ALIAS("CYCLE_ACTIVITY.CYCLES_LDM_PENDING", IAP_EVENT_A3H_02H) \
+__PMC_EV_ALIAS("CYCLE_ACTIVITY.CYCLES_NO_EXECUTE", IAP_EVENT_A3H_04H) \
+__PMC_EV_ALIAS("CYCLE_ACTIVITY.CYCLES_L1D_PENDING", IAP_EVENT_A3H_08H) \
+__PMC_EV_ALIAS("DSB2MITE_SWITCHES.COUNT", IAP_EVENT_ABH_01H) \
+__PMC_EV_ALIAS("DSB2MITE_SWITCHES.PENALTY_CYCLES", IAP_EVENT_ABH_02H) \
+__PMC_EV_ALIAS("DSB_FILL.EXCEED_DSB_LINES", IAP_EVENT_ACH_08H) \
+__PMC_EV_ALIAS("ITLB.ITLB_FLUSH", IAP_EVENT_AEH_01H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.DEMAND_DATA_RD", IAP_EVENT_B0H_01H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.DEMAND_CODE_RD", IAP_EVENT_B0H_02H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.DEMAND_RFO", IAP_EVENT_B0H_04H) \
+__PMC_EV_ALIAS("OFFCORE_REQUESTS.ALL_DATA_RD", IAP_EVENT_B0H_08H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.THREAD", IAP_EVENT_B1H_01H) \
+__PMC_EV_ALIAS("UOPS_EXECUTED.CORE", IAP_EVENT_B1H_02H) \
+__PMC_EV_ALIAS("OFF_CORE_RESPONSE_0", IAP_EVENT_B7H_01H) \
+__PMC_EV_ALIAS("OFF_CORE_RESPONSE_1", IAP_EVENT_BBH_01H) \
+__PMC_EV_ALIAS("TLB_FLUSH.DTLB_THREAD", IAP_EVENT_BDH_01H) \
+__PMC_EV_ALIAS("TLB_FLUSH.STLB_ANY", IAP_EVENT_BDH_20H) \
+__PMC_EV_ALIAS("INST_RETIRED.ANY_P", IAP_EVENT_C0H_00H) \
+__PMC_EV_ALIAS("INST_RETIRED.ALL", IAP_EVENT_C0H_01H) \
+__PMC_EV_ALIAS("OTHER_ASSISTS.AVX_STORE", IAP_EVENT_C1H_08H) \
+__PMC_EV_ALIAS("OTHER_ASSISTS.AVX_TO_SSE", IAP_EVENT_C1H_10H) \
+__PMC_EV_ALIAS("OTHER_ASSISTS.SSE_TO_AVX", IAP_EVENT_C1H_20H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.ALL", IAP_EVENT_C2H_01H) \
+__PMC_EV_ALIAS("UOPS_RETIRED.RETIRE_SLOTS", IAP_EVENT_C2H_02H) \
+__PMC_EV_ALIAS("MACHINE_CLEARS.MEMORY_ORDERING", IAP_EVENT_C3H_02H) \
+__PMC_EV_ALIAS("MACHINE_CLEARS.SMC", IAP_EVENT_C3H_04H) \
+__PMC_EV_ALIAS("MACHINE_CLEARS.MASKMOV", IAP_EVENT_C3H_20H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.ALL_BRANCHES", IAP_EVENT_C4H_00H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.CONDITIONAL", IAP_EVENT_C4H_01H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.NEAR_CALL", IAP_EVENT_C4H_02H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.ALL_BRANCHES", IAP_EVENT_C4H_04H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.NEAR_RETURN", IAP_EVENT_C4H_08H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.NOT_TAKEN", IAP_EVENT_C4H_10H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.NEAR_TAKEN", IAP_EVENT_C4H_20H) \
+__PMC_EV_ALIAS("BR_INST_RETIRED.FAR_BRANCH", IAP_EVENT_C4H_40H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.ALL_BRANCHES", IAP_EVENT_C5H_00H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.CONDITIONAL", IAP_EVENT_C5H_01H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.NEAR_CALL", IAP_EVENT_C5H_02H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.ALL_BRANCHES", IAP_EVENT_C5H_04H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.NOT_TAKEN", IAP_EVENT_C5H_10H) \
+__PMC_EV_ALIAS("BR_MISP_RETIRED.TAKEN", IAP_EVENT_C5H_20H) \
+__PMC_EV_ALIAS("FP_ASSIST.X87_OUTPUT", IAP_EVENT_CAH_02H) \
+__PMC_EV_ALIAS("FP_ASSIST.X87_INPUT", IAP_EVENT_CAH_04H) \
+__PMC_EV_ALIAS("FP_ASSIST.SIMD_OUTPUT", IAP_EVENT_CAH_08H) \
+__PMC_EV_ALIAS("FP_ASSIST.SIMD_INPUT", IAP_EVENT_CAH_10H) \
+__PMC_EV_ALIAS("FP_ASSIST.ANY", IAP_EVENT_CAH_1EH) \
+__PMC_EV_ALIAS("ROB_MISC_EVENTS.LBR_INSERTS", IAP_EVENT_CCH_20H) \
+__PMC_EV_ALIAS("MEM_TRANS_RETIRED.LOAD_LATENCY", IAP_EVENT_CDH_01H) \
+__PMC_EV_ALIAS("MEM_TRANS_RETIRED.PRECISE_STORE", IAP_EVENT_CDH_02H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.LOADS", IAP_EVENT_D0H_01H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.STORES", IAP_EVENT_D0H_02H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.STLB_MISS", IAP_EVENT_D0H_10H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.LOCK", IAP_EVENT_D0H_20H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.SPLIT", IAP_EVENT_D0H_40H) \
+__PMC_EV_ALIAS("MEM_UOP_RETIRED.ALL", IAP_EVENT_D0H_80H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_RETIRED.L1_HIT", IAP_EVENT_D1H_01H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_RETIRED.L2_HIT", IAP_EVENT_D1H_02H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_RETIRED.LLC_HIT", IAP_EVENT_D1H_04H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_RETIRED.LLC_MISS", IAP_EVENT_D1H_20H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_RETIRED.HIT_LFB", IAP_EVENT_D1H_40H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS", IAP_EVENT_D2H_01H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT", IAP_EVENT_D2H_02H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM", IAP_EVENT_D2H_04H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_NONE", IAP_EVENT_D2H_08H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM", IAP_EVENT_D3H_01H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_DRAM", IAP_EVENT_D3H_04H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_HITM", IAP_EVENT_D3H_10H) \
+__PMC_EV_ALIAS("MEM_LOAD_UOPS_LLC_MISS_RETIRED.REMOTE_FWD", IAP_EVENT_D3H_20H) \
+__PMC_EV_ALIAS("BACLEARS.ANY", IAP_EVENT_E6H_1FH) \
+__PMC_EV_ALIAS("L2_TRANS.DEMAND_DATA_RD", IAP_EVENT_F0H_01H) \
+__PMC_EV_ALIAS("L2_TRANS.RFO", IAP_EVENT_F0H_02H) \
+__PMC_EV_ALIAS("L2_TRANS.CODE_RD", IAP_EVENT_F0H_04H) \
+__PMC_EV_ALIAS("L2_TRANS.ALL_PF", IAP_EVENT_F0H_08H) \
+__PMC_EV_ALIAS("L2_TRANS.L1D_WB", IAP_EVENT_F0H_10H) \
+__PMC_EV_ALIAS("L2_TRANS.L2_FILL", IAP_EVENT_F0H_20H) \
+__PMC_EV_ALIAS("L2_TRANS.L2_WB", IAP_EVENT_F0H_40H) \
+__PMC_EV_ALIAS("L2_TRANS.ALL_REQUESTS", IAP_EVENT_F0H_80H) \
+__PMC_EV_ALIAS("L2_LINES_IN.I", IAP_EVENT_F1H_01H) \
+__PMC_EV_ALIAS("L2_LINES_IN.S", IAP_EVENT_F1H_02H) \
+__PMC_EV_ALIAS("L2_LINES_IN.E", IAP_EVENT_F1H_04H) \
+__PMC_EV_ALIAS("L2_LINES_IN.ALL", IAP_EVENT_F1H_07H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.DEMAND_CLEAN", IAP_EVENT_F2H_01H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.DEMAND_DIRTY", IAP_EVENT_F2H_02H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.PF_CLEAN", IAP_EVENT_F2H_04H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.PF_DIRTY", IAP_EVENT_F2H_08H) \
+__PMC_EV_ALIAS("L2_LINES_OUT.DIRTY_ALL", IAP_EVENT_F2H_0AH)
+
+/*
* Aliases for Sandy Bridge PMC events (253669-039US May 2011)
*/
diff --git a/sys/dev/iicbus/ad7418.c b/sys/dev/iicbus/ad7418.c
index 3875307..dcb8b95 100644
--- a/sys/dev/iicbus/ad7418.c
+++ b/sys/dev/iicbus/ad7418.c
@@ -219,7 +219,7 @@ static device_method_t ad7418_methods[] = {
DEVMETHOD(device_probe, ad7418_probe),
DEVMETHOD(device_attach, ad7418_attach),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t ad7418_driver = {
diff --git a/sys/dev/iicbus/ds133x.c b/sys/dev/iicbus/ds133x.c
index 572384f..20f1d40 100644
--- a/sys/dev/iicbus/ds133x.c
+++ b/sys/dev/iicbus/ds133x.c
@@ -347,7 +347,7 @@ static device_method_t ds133x_methods[] = {
DEVMETHOD(clock_gettime, ds133x_gettime),
DEVMETHOD(clock_settime, ds133x_settime),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t ds133x_driver = {
diff --git a/sys/dev/iicbus/ds1672.c b/sys/dev/iicbus/ds1672.c
index a9209bd..1dd0ab0 100644
--- a/sys/dev/iicbus/ds1672.c
+++ b/sys/dev/iicbus/ds1672.c
@@ -167,7 +167,7 @@ static device_method_t ds1672_methods[] = {
DEVMETHOD(clock_gettime, ds1672_gettime),
DEVMETHOD(clock_settime, ds1672_settime),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t ds1672_driver = {
diff --git a/sys/dev/iicbus/icee.c b/sys/dev/iicbus/icee.c
index 93c03ad..2e26d0e 100644
--- a/sys/dev/iicbus/icee.c
+++ b/sys/dev/iicbus/icee.c
@@ -262,7 +262,7 @@ static device_method_t icee_methods[] = {
DEVMETHOD(device_probe, icee_probe),
DEVMETHOD(device_attach, icee_attach),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t icee_driver = {
diff --git a/sys/dev/isf/isf.c b/sys/dev/isf/isf.c
index e537799..eaaad15 100644
--- a/sys/dev/isf/isf.c
+++ b/sys/dev/isf/isf.c
@@ -150,6 +150,7 @@ static void isf_task(void *arg);
* physical package, due to variable block size support in the StrataFlash
* part.
*/
+devclass_t isf_devclass;
static uint16_t
isf_read_reg(struct isf_softc *sc, uint16_t reg)
diff --git a/sys/dev/isf/isf.h b/sys/dev/isf/isf.h
index f5cdc08..bfcca07 100644
--- a/sys/dev/isf/isf.h
+++ b/sys/dev/isf/isf.h
@@ -89,6 +89,8 @@ struct isf_softc {
int isf_attach(struct isf_softc *sc);
void isf_detach(struct isf_softc *sc);
+
+extern devclass_t isf_devclass;
#endif /* _KERNEL */
#endif /* _DEV_ISF_H_ */
diff --git a/sys/dev/isf/isf_fdt.c b/sys/dev/isf/isf_fdt.c
new file mode 100644
index 0000000..f4c20a2
--- /dev/null
+++ b/sys/dev/isf/isf_fdt.c
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * Copyright (c) 2012 SRI International
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/isf/isf.h>
+
+/*
+ * FDT bus attachment for the Intel Strata Flash devices.
+ */
+static int
+isf_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "intel,strataflash")) {
+ device_set_desc(dev, "Intel StrataFlash NOR flash device");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+isf_fdt_attach(device_t dev)
+{
+ int error;
+ struct isf_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->isf_dev = dev;
+ sc->isf_unit = device_get_unit(dev);
+ sc->isf_rid = 0;
+ sc->isf_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->isf_rid, RF_ACTIVE);
+ if (sc->isf_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ return (ENXIO);
+ }
+ error = isf_attach(sc);
+ if (error)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->isf_rid,
+ sc->isf_res);
+ return (error);
+}
+
+static int
+isf_fdt_detach(device_t dev)
+{
+ struct isf_softc *sc;
+
+ sc = device_get_softc(dev);
+ KASSERT(sc->isf_res != NULL, ("%s: resources not allocated",
+ __func__));
+ isf_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->isf_rid, sc->isf_res);
+ return (0);
+}
+
+static device_method_t isf_fdt_methods[] = {
+ DEVMETHOD(device_probe, isf_fdt_probe),
+ DEVMETHOD(device_attach, isf_fdt_attach),
+ DEVMETHOD(device_detach, isf_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t isf_fdt_driver = {
+ "isf",
+ isf_fdt_methods,
+ sizeof(struct isf_softc),
+};
+
+DRIVER_MODULE(isf, simplebus, isf_fdt_driver, isf_devclass, 0, 0);
diff --git a/sys/dev/isf/isf_nexus.c b/sys/dev/isf/isf_nexus.c
index af2f874..7631453 100644
--- a/sys/dev/isf/isf_nexus.c
+++ b/sys/dev/isf/isf_nexus.c
@@ -115,6 +115,4 @@ static driver_t isf_nexus_driver = {
sizeof(struct isf_softc),
};
-static devclass_t isf_devclass;
-
DRIVER_MODULE(isf, nexus, isf_nexus_driver, isf_devclass, 0, 0);
diff --git a/sys/dev/ixgb/if_ixgb.c b/sys/dev/ixgb/if_ixgb.c
index e9acae0..69a8fb9 100644
--- a/sys/dev/ixgb/if_ixgb.c
+++ b/sys/dev/ixgb/if_ixgb.c
@@ -159,7 +159,8 @@ static device_method_t ixgb_methods[] = {
DEVMETHOD(device_attach, ixgb_attach),
DEVMETHOD(device_detach, ixgb_detach),
DEVMETHOD(device_shutdown, ixgb_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ixgb_driver = {
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
index 1d97343..cfcc342 100644
--- a/sys/dev/ixgbe/ixgbe.c
+++ b/sys/dev/ixgbe/ixgbe.c
@@ -216,7 +216,8 @@ static device_method_t ixgbe_methods[] = {
DEVMETHOD(device_attach, ixgbe_attach),
DEVMETHOD(device_detach, ixgbe_detach),
DEVMETHOD(device_shutdown, ixgbe_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ixgbe_driver = {
diff --git a/sys/dev/ixgbe/ixgbe_82598.h b/sys/dev/ixgbe/ixgbe_82598.h
index a195b15..a195b15 100755..100644
--- a/sys/dev/ixgbe/ixgbe_82598.h
+++ b/sys/dev/ixgbe/ixgbe_82598.h
diff --git a/sys/dev/ixgbe/ixgbe_82599.h b/sys/dev/ixgbe/ixgbe_82599.h
index dca39b7..dca39b7 100755..100644
--- a/sys/dev/ixgbe/ixgbe_82599.h
+++ b/sys/dev/ixgbe/ixgbe_82599.h
diff --git a/sys/dev/ixgbe/ixgbe_x540.c b/sys/dev/ixgbe/ixgbe_x540.c
index 0635cda..0635cda 100755..100644
--- a/sys/dev/ixgbe/ixgbe_x540.c
+++ b/sys/dev/ixgbe/ixgbe_x540.c
diff --git a/sys/dev/ixgbe/ixgbe_x540.h b/sys/dev/ixgbe/ixgbe_x540.h
index 29cf8bb..29cf8bb 100755..100644
--- a/sys/dev/ixgbe/ixgbe_x540.h
+++ b/sys/dev/ixgbe/ixgbe_x540.h
diff --git a/sys/dev/ixgbe/ixv.c b/sys/dev/ixgbe/ixv.c
index b9aff80..ef5f753 100644
--- a/sys/dev/ixgbe/ixv.c
+++ b/sys/dev/ixgbe/ixv.c
@@ -169,7 +169,8 @@ static device_method_t ixv_methods[] = {
DEVMETHOD(device_attach, ixv_attach),
DEVMETHOD(device_detach, ixv_detach),
DEVMETHOD(device_shutdown, ixv_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ixv_driver = {
diff --git a/sys/dev/mfi/mfi_cam.c b/sys/dev/mfi/mfi_cam.c
index 599ff3b..2bbfafe 100644
--- a/sys/dev/mfi/mfi_cam.c
+++ b/sys/dev/mfi/mfi_cam.c
@@ -99,7 +99,8 @@ static device_method_t mfip_methods[] = {
DEVMETHOD(device_probe, mfip_probe),
DEVMETHOD(device_attach, mfip_attach),
DEVMETHOD(device_detach, mfip_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t mfip_driver = {
"mfip",
diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c
index 27447ad..e7f6648 100644
--- a/sys/dev/mmc/mmc.c
+++ b/sys/dev/mmc/mmc.c
@@ -353,7 +353,8 @@ mmc_highest_voltage(uint32_t ocr)
{
int i;
- for (i = 30; i >= 0; i--)
+ for (i = MMC_OCR_MAX_VOLTAGE_SHIFT;
+ i >= MMC_OCR_MIN_VOLTAGE_SHIFT; i--)
if (ocr & (1 << i))
return (i);
return (-1);
diff --git a/sys/dev/mmc/mmcreg.h b/sys/dev/mmc/mmcreg.h
index 3d2b569..f454ddb 100644
--- a/sys/dev/mmc/mmcreg.h
+++ b/sys/dev/mmc/mmcreg.h
@@ -353,6 +353,7 @@ struct mmc_request {
#define MMC_OCR_VOLTAGE 0x3fffffffU /* Vdd Voltage mask */
#define MMC_OCR_LOW_VOLTAGE (1u << 7) /* Low Voltage Range -- tbd */
#define MMC_OCR_200_210 (1U << 8) /* Vdd voltage 2.00 ~ 2.10 */
+#define MMC_OCR_MIN_VOLTAGE_SHIFT 8
#define MMC_OCR_210_220 (1U << 9) /* Vdd voltage 2.10 ~ 2.20 */
#define MMC_OCR_220_230 (1U << 10) /* Vdd voltage 2.20 ~ 2.30 */
#define MMC_OCR_230_240 (1U << 11) /* Vdd voltage 2.30 ~ 2.40 */
@@ -368,6 +369,7 @@ struct mmc_request {
#define MMC_OCR_330_340 (1U << 21) /* Vdd voltage 3.30 ~ 3.40 */
#define MMC_OCR_340_350 (1U << 22) /* Vdd voltage 3.40 ~ 3.50 */
#define MMC_OCR_350_360 (1U << 23) /* Vdd voltage 3.50 ~ 3.60 */
+#define MMC_OCR_MAX_VOLTAGE_SHIFT 23
#define MMC_OCR_CCS (1u << 30) /* Card Capacity status (SD vs SDHC) */
#define MMC_OCR_CARD_BUSY (1U << 31) /* Card Power up status */
diff --git a/sys/dev/mn/if_mn.c b/sys/dev/mn/if_mn.c
index 48fc3dc..239aa0f 100644
--- a/sys/dev/mn/if_mn.c
+++ b/sys/dev/mn/if_mn.c
@@ -1418,7 +1418,7 @@ static device_method_t mn_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t mn_driver = {
diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c
index c04e0df2..feefc3b 100644
--- a/sys/dev/mxge/if_mxge.c
+++ b/sys/dev/mxge/if_mxge.c
@@ -124,7 +124,8 @@ static device_method_t mxge_methods[] =
DEVMETHOD(device_attach, mxge_attach),
DEVMETHOD(device_detach, mxge_detach),
DEVMETHOD(device_shutdown, mxge_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t mxge_driver =
diff --git a/sys/dev/my/if_my.c b/sys/dev/my/if_my.c
index 9648412..a487d90 100644
--- a/sys/dev/my/if_my.c
+++ b/sys/dev/my/if_my.c
@@ -153,7 +153,7 @@ static device_method_t my_methods[] = {
DEVMETHOD(device_detach, my_detach),
DEVMETHOD(device_shutdown, my_shutdown),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t my_driver = {
diff --git a/sys/dev/nand/nand_id.c b/sys/dev/nand/nand_id.c
index 75c5834..76c5f9f 100644
--- a/sys/dev/nand/nand_id.c
+++ b/sys/dev/nand/nand_id.c
@@ -37,6 +37,8 @@ struct nand_params nand_ids[] = {
0x20, 0x200, 0x10, 0x20, 0 },
{ { NAND_MAN_SAMSUNG, 0xd3 }, "Samsung NAND 1GiB 3,3V 8-bit",
0x400, 0x800, 0x40, 0x40, 0 },
+ { { NAND_MAN_SAMSUNG, 0xdc }, "Samsung NAND 512MiB 3,3V 8-bit",
+ 0x200, 0x800, 0x40, 0x40, 0 },
{ { NAND_MAN_HYNIX, 0x76 }, "Hynix NAND 64MiB 3,3V 8-bit",
0x40, 0x200, 0x10, 0x20, 0 },
{ { NAND_MAN_HYNIX, 0xdc }, "Hynix NAND 512MiB 3,3V 8-bit",
diff --git a/sys/dev/netmap/if_em_netmap.h b/sys/dev/netmap/if_em_netmap.h
index b4b268a..776f0e0 100644
--- a/sys/dev/netmap/if_em_netmap.h
+++ b/sys/dev/netmap/if_em_netmap.h
@@ -292,6 +292,8 @@ em_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
l = rxr->next_to_check;
j = netmap_idx_n2k(kring, l);
if (netmap_no_pendintr || force_update) {
+ uint16_t slot_flags = kring->nkr_slot_flags;
+
for (n = 0; ; n++) {
struct e1000_rx_desc *curr = &rxr->rx_base[l];
uint32_t staterr = le32toh(curr->status);
@@ -299,6 +301,7 @@ em_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
if ((staterr & E1000_RXD_STAT_DD) == 0)
break;
ring->slot[j].len = le16toh(curr->length);
+ ring->slot[j].flags = slot_flags;
bus_dmamap_sync(rxr->rxtag, rxr->rx_buffers[l].map,
BUS_DMASYNC_POSTREAD);
j = (j == lim) ? 0 : j + 1;
diff --git a/sys/dev/netmap/if_igb_netmap.h b/sys/dev/netmap/if_igb_netmap.h
index bd83563..e817341 100644
--- a/sys/dev/netmap/if_igb_netmap.h
+++ b/sys/dev/netmap/if_igb_netmap.h
@@ -263,6 +263,8 @@ igb_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
l = rxr->next_to_check;
j = netmap_idx_n2k(kring, l);
if (netmap_no_pendintr || force_update) {
+ uint16_t slot_flags = kring->nkr_slot_flags;
+
for (n = 0; ; n++) {
union e1000_adv_rx_desc *curr = &rxr->rx_base[l];
uint32_t staterr = le32toh(curr->wb.upper.status_error);
@@ -270,6 +272,7 @@ igb_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
if ((staterr & E1000_RXD_STAT_DD) == 0)
break;
ring->slot[j].len = le16toh(curr->wb.upper.length);
+ ring->slot[j].flags = slot_flags;
bus_dmamap_sync(rxr->ptag,
rxr->rx_buffers[l].pmap, BUS_DMASYNC_POSTREAD);
j = (j == lim) ? 0 : j + 1;
diff --git a/sys/dev/netmap/if_lem_netmap.h b/sys/dev/netmap/if_lem_netmap.h
index 9f24580..d3be700 100644
--- a/sys/dev/netmap/if_lem_netmap.h
+++ b/sys/dev/netmap/if_lem_netmap.h
@@ -253,6 +253,8 @@ lem_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
l = adapter->next_rx_desc_to_check;
j = netmap_idx_n2k(kring, l);
if (netmap_no_pendintr || force_update) {
+ uint16_t slot_flags = kring->nkr_slot_flags;
+
for (n = 0; ; n++) {
struct e1000_rx_desc *curr = &adapter->rx_desc_base[l];
uint32_t staterr = le32toh(curr->status);
@@ -266,6 +268,7 @@ lem_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
len = 0;
}
ring->slot[j].len = len;
+ ring->slot[j].flags = slot_flags;
bus_dmamap_sync(adapter->rxtag,
adapter->rx_buffer_area[l].map,
BUS_DMASYNC_POSTREAD);
diff --git a/sys/dev/netmap/if_re_netmap.h b/sys/dev/netmap/if_re_netmap.h
index bdd5703..1c747b7 100644
--- a/sys/dev/netmap/if_re_netmap.h
+++ b/sys/dev/netmap/if_re_netmap.h
@@ -245,6 +245,8 @@ re_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
l = sc->rl_ldata.rl_rx_prodidx; /* next pkt to check */
j = netmap_idx_n2k(kring, l); /* the kring index */
if (netmap_no_pendintr || force_update) {
+ uint16_t slot_flags = kring->nkr_slot_flags;
+
for (n = kring->nr_hwavail; n < lim ; n++) {
struct rl_desc *cur_rx = &sc->rl_ldata.rl_rx_list[l];
uint32_t rxstat = le32toh(cur_rx->rl_cmdstat);
@@ -256,6 +258,7 @@ re_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
/* XXX subtract crc */
total_len = (total_len < 4) ? 0 : total_len - 4;
kring->ring->slot[j].len = total_len;
+ kring->ring->slot[j].flags = slot_flags;
/* sync was in re_newbuf() */
bus_dmamap_sync(sc->rl_ldata.rl_rx_mtag,
rxd[l].rx_dmamap, BUS_DMASYNC_POSTREAD);
diff --git a/sys/dev/netmap/ixgbe_netmap.h b/sys/dev/netmap/ixgbe_netmap.h
index 55bd21f..55660ec 100644
--- a/sys/dev/netmap/ixgbe_netmap.h
+++ b/sys/dev/netmap/ixgbe_netmap.h
@@ -63,9 +63,6 @@
* This is tricky, much better to use TDH for now.
*/
SYSCTL_DECL(_dev_netmap);
-static int ix_write_len;
-SYSCTL_INT(_dev_netmap, OID_AUTO, ix_write_len,
- CTLFLAG_RW, &ix_write_len, 0, "write rx len");
static int ix_rx_miss, ix_rx_miss_bufs, ix_use_dd, ix_crcstrip;
SYSCTL_INT(_dev_netmap, OID_AUTO, ix_crcstrip,
CTLFLAG_RW, &ix_crcstrip, 0, "strip CRC on rx frames");
@@ -485,12 +482,9 @@ ixgbe_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
* rxr->next_to_check is set to 0 on a ring reinit
*/
if (netmap_no_pendintr || force_update) {
- /* XXX apparently the length field in advanced descriptors
- * does not include the CRC irrespective of the setting
- * of CRCSTRIP. The data sheets say differently.
- * Very strange.
- */
int crclen = ix_crcstrip ? 0 : 4;
+ uint16_t slot_flags = kring->nkr_slot_flags;
+
l = rxr->next_to_check;
j = netmap_idx_n2k(kring, l);
@@ -501,8 +495,7 @@ ixgbe_netmap_rxsync(struct ifnet *ifp, u_int ring_nr, int do_lock)
if ((staterr & IXGBE_RXD_STAT_DD) == 0)
break;
ring->slot[j].len = le16toh(curr->wb.upper.length) - crclen;
- if (ix_write_len)
- D("rx[%d] len %d", j, ring->slot[j].len);
+ ring->slot[j].flags = slot_flags;
bus_dmamap_sync(rxr->ptag,
rxr->rx_buffers[l].pmap, BUS_DMASYNC_POSTREAD);
j = (j == lim) ? 0 : j + 1;
diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c
index 4f5d486..35d5303 100644
--- a/sys/dev/netmap/netmap.c
+++ b/sys/dev/netmap/netmap.c
@@ -120,10 +120,12 @@ SYSCTL_INT(_dev_netmap, OID_AUTO, no_pendintr,
int netmap_drop = 0; /* debugging */
int netmap_flags = 0; /* debug flags */
+int netmap_fwd = 0; /* force transparent mode */
int netmap_copy = 0; /* debugging, copy content */
SYSCTL_INT(_dev_netmap, OID_AUTO, drop, CTLFLAG_RW, &netmap_drop, 0 , "");
SYSCTL_INT(_dev_netmap, OID_AUTO, flags, CTLFLAG_RW, &netmap_flags, 0 , "");
+SYSCTL_INT(_dev_netmap, OID_AUTO, fwd, CTLFLAG_RW, &netmap_fwd, 0 , "");
SYSCTL_INT(_dev_netmap, OID_AUTO, copy, CTLFLAG_RW, &netmap_copy, 0 , "");
#ifdef NM_BRIDGE /* support for netmap bridge */
@@ -275,6 +277,51 @@ nm_find_bridge(const char *name)
}
#endif /* NM_BRIDGE */
+
+/*
+ * Fetch configuration from the device, to cope with dynamic
+ * reconfigurations after loading the module.
+ */
+static int
+netmap_update_config(struct netmap_adapter *na)
+{
+ struct ifnet *ifp = na->ifp;
+ u_int txr, txd, rxr, rxd;
+
+ txr = txd = rxr = rxd = 0;
+ if (na->nm_config) {
+ na->nm_config(ifp, &txr, &txd, &rxr, &rxd);
+ } else {
+ /* take whatever we had at init time */
+ txr = na->num_tx_rings;
+ txd = na->num_tx_desc;
+ rxr = na->num_rx_rings;
+ rxd = na->num_rx_desc;
+ }
+
+ if (na->num_tx_rings == txr && na->num_tx_desc == txd &&
+ na->num_rx_rings == rxr && na->num_rx_desc == rxd)
+ return 0; /* nothing changed */
+ if (netmap_verbose || na->refcount > 0) {
+ D("stored config %s: txring %d x %d, rxring %d x %d",
+ ifp->if_xname,
+ na->num_tx_rings, na->num_tx_desc,
+ na->num_rx_rings, na->num_rx_desc);
+ D("new config %s: txring %d x %d, rxring %d x %d",
+ ifp->if_xname, txr, txd, rxr, rxd);
+ }
+ if (na->refcount == 0) {
+ D("configuration changed (but fine)");
+ na->num_tx_rings = txr;
+ na->num_tx_desc = txd;
+ na->num_rx_rings = rxr;
+ na->num_rx_desc = rxd;
+ return 0;
+ }
+ D("configuration changed while active, this is bad...");
+ return 1;
+}
+
/*------------- memory allocator -----------------*/
#ifdef NETMAP_MEM2
#include "netmap_mem2.c"
@@ -351,7 +398,8 @@ netmap_dtor_locked(void *data)
if (na->refcount <= 0) { /* last instance */
u_int i, j, lim;
- D("deleting last netmap instance for %s", ifp->if_xname);
+ if (netmap_verbose)
+ D("deleting last instance for %s", ifp->if_xname);
/*
* there is a race here with *_netmap_task() and
* netmap_poll(), which don't run under NETMAP_REG_LOCK.
@@ -482,7 +530,8 @@ static int
netmap_dev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot,
vm_ooffset_t foff, struct ucred *cred, u_short *color)
{
- D("first mmap for %p", handle);
+ if (netmap_verbose)
+ D("first mmap for %p", handle);
return saved_cdev_pager_ops.cdev_pg_ctor(handle,
size, prot, foff, cred, color);
}
@@ -491,7 +540,7 @@ static void
netmap_dev_pager_dtor(void *handle)
{
saved_cdev_pager_ops.cdev_pg_dtor(handle);
- D("ready to release memory for %p", handle);
+ ND("ready to release memory for %p", handle);
}
@@ -507,7 +556,7 @@ netmap_mmap_single(struct cdev *cdev, vm_ooffset_t *foff,
{
vm_object_t obj;
- D("cdev %p foff %jd size %jd objp %p prot %d", cdev,
+ ND("cdev %p foff %jd size %jd objp %p prot %d", cdev,
(intmax_t )*foff, (intmax_t )objsize, objp, prot);
obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, *foff,
curthread->td_ucred);
@@ -515,7 +564,7 @@ netmap_mmap_single(struct cdev *cdev, vm_ooffset_t *foff,
if (obj == NULL)
return EINVAL;
if (saved_cdev_pager_ops.cdev_pg_fault == NULL) {
- D("initialize cdev_pager_ops");
+ ND("initialize cdev_pager_ops");
saved_cdev_pager_ops = *(obj->un_pager.devp.ops);
netmap_cdev_pager_ops.cdev_pg_fault =
saved_cdev_pager_ops.cdev_pg_fault;
@@ -572,7 +621,9 @@ netmap_mmap(__unused struct cdev *dev,
static int
netmap_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
- D("dev %p fflag 0x%x devtype %d td %p", dev, fflag, devtype, td);
+ if (netmap_verbose)
+ D("dev %p fflag 0x%x devtype %d td %p",
+ dev, fflag, devtype, td);
return 0;
}
@@ -598,63 +649,170 @@ netmap_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
/*
* Handlers for synchronization of the queues from/to the host.
- *
- * netmap_sync_to_host() passes packets up. We are called from a
- * system call in user process context, and the only contention
- * can be among multiple user threads erroneously calling
- * this routine concurrently. In principle we should not even
- * need to lock.
+ * Netmap has two operating modes:
+ * - in the default mode, the rings connected to the host stack are
+ * just another ring pair managed by userspace;
+ * - in transparent mode (XXX to be defined) incoming packets
+ * (from the host or the NIC) are marked as NS_FORWARD upon
+ * arrival, and the user application has a chance to reset the
+ * flag for packets that should be dropped.
+ * On the RXSYNC or poll(), packets in RX rings between
+ * kring->nr_kcur and ring->cur with NS_FORWARD still set are moved
+ * to the other side.
+ * The transfer NIC --> host is relatively easy, just encapsulate
+ * into mbufs and we are done. The host --> NIC side is slightly
+ * harder because there might not be room in the tx ring so it
+ * might take a while before releasing the buffer.
+ */
+
+/*
+ * pass a chain of buffers to the host stack as coming from 'dst'
*/
static void
-netmap_sync_to_host(struct netmap_adapter *na)
+netmap_send_up(struct ifnet *dst, struct mbuf *head)
{
- struct netmap_kring *kring = &na->tx_rings[na->num_tx_rings];
- struct netmap_ring *ring = kring->ring;
- struct mbuf *head = NULL, *tail = NULL, *m;
- u_int k, n, lim = kring->nkr_num_slots - 1;
+ struct mbuf *m;
- k = ring->cur;
- if (k > lim) {
- netmap_ring_reinit(kring);
- return;
+ /* send packets up, outside the lock */
+ while ((m = head) != NULL) {
+ head = head->m_nextpkt;
+ m->m_nextpkt = NULL;
+ if (netmap_verbose & NM_VERB_HOST)
+ D("sending up pkt %p size %d", m, MBUF_LEN(m));
+ NM_SEND_UP(dst, m);
}
- // na->nm_lock(na->ifp, NETMAP_CORE_LOCK, 0);
+}
- /* Take packets from hwcur to cur and pass them up.
+struct mbq {
+ struct mbuf *head;
+ struct mbuf *tail;
+ int count;
+};
+
+/*
+ * put a copy of the buffers marked NS_FORWARD into an mbuf chain.
+ * Run from hwcur to cur - reserved
+ */
+static void
+netmap_grab_packets(struct netmap_kring *kring, struct mbq *q, int force)
+{
+ /* Take packets from hwcur to cur-reserved and pass them up.
* In case of no buffers we give up. At the end of the loop,
* the queue is drained in all cases.
+ * XXX handle reserved
*/
+ int k = kring->ring->cur - kring->ring->reserved;
+ u_int n, lim = kring->nkr_num_slots - 1;
+ struct mbuf *m, *tail = q->tail;
+
+ if (k < 0)
+ k = k + kring->nkr_num_slots;
for (n = kring->nr_hwcur; n != k;) {
- struct netmap_slot *slot = &ring->slot[n];
+ struct netmap_slot *slot = &kring->ring->slot[n];
n = (n == lim) ? 0 : n + 1;
+ if ((slot->flags & NS_FORWARD) == 0 && !force)
+ continue;
if (slot->len < 14 || slot->len > NETMAP_BUF_SIZE) {
D("bad pkt at %d len %d", n, slot->len);
continue;
}
- m = m_devget(NMB(slot), slot->len, 0, na->ifp, NULL);
+ slot->flags &= ~NS_FORWARD; // XXX needed ?
+ m = m_devget(NMB(slot), slot->len, 0, kring->na->ifp, NULL);
if (m == NULL)
break;
if (tail)
tail->m_nextpkt = m;
else
- head = m;
+ q->head = m;
tail = m;
+ q->count++;
m->m_nextpkt = NULL;
}
+ q->tail = tail;
+}
+
+/*
+ * called under main lock to send packets from the host to the NIC
+ * The host ring has packets from nr_hwcur to (cur - reserved)
+ * to be sent down. We scan the tx rings, which have just been
+ * flushed so nr_hwcur == cur. Pushing packets down means
+ * increment cur and decrement avail.
+ * XXX to be verified
+ */
+static void
+netmap_sw_to_nic(struct netmap_adapter *na)
+{
+ struct netmap_kring *kring = &na->rx_rings[na->num_rx_rings];
+ struct netmap_kring *k1 = &na->tx_rings[0];
+ int i, howmany, src_lim, dst_lim;
+
+ howmany = kring->nr_hwavail; /* XXX otherwise cur - reserved - nr_hwcur */
+
+ src_lim = kring->nkr_num_slots;
+ for (i = 0; howmany > 0 && i < na->num_tx_rings; i++, k1++) {
+ ND("%d packets left to ring %d (space %d)", howmany, i, k1->nr_hwavail);
+ dst_lim = k1->nkr_num_slots;
+ while (howmany > 0 && k1->ring->avail > 0) {
+ struct netmap_slot *src, *dst, tmp;
+ src = &kring->ring->slot[kring->nr_hwcur];
+ dst = &k1->ring->slot[k1->ring->cur];
+ tmp = *src;
+ src->buf_idx = dst->buf_idx;
+ src->flags = NS_BUF_CHANGED;
+
+ dst->buf_idx = tmp.buf_idx;
+ dst->len = tmp.len;
+ dst->flags = NS_BUF_CHANGED;
+ ND("out len %d buf %d from %d to %d",
+ dst->len, dst->buf_idx,
+ kring->nr_hwcur, k1->ring->cur);
+
+ if (++kring->nr_hwcur >= src_lim)
+ kring->nr_hwcur = 0;
+ howmany--;
+ kring->nr_hwavail--;
+ if (++k1->ring->cur >= dst_lim)
+ k1->ring->cur = 0;
+ k1->ring->avail--;
+ }
+ kring->ring->cur = kring->nr_hwcur; // XXX
+ k1++;
+ }
+}
+
+/*
+ * netmap_sync_to_host() passes packets up. We are called from a
+ * system call in user process context, and the only contention
+ * can be among multiple user threads erroneously calling
+ * this routine concurrently.
+ */
+static void
+netmap_sync_to_host(struct netmap_adapter *na)
+{
+ struct netmap_kring *kring = &na->tx_rings[na->num_tx_rings];
+ struct netmap_ring *ring = kring->ring;
+ u_int k, lim = kring->nkr_num_slots - 1;
+ struct mbq q = { NULL, NULL };
+
+ k = ring->cur;
+ if (k > lim) {
+ netmap_ring_reinit(kring);
+ return;
+ }
+ // na->nm_lock(na->ifp, NETMAP_CORE_LOCK, 0);
+
+ /* Take packets from hwcur to cur and pass them up.
+ * In case of no buffers we give up. At the end of the loop,
+ * the queue is drained in all cases.
+ */
+ netmap_grab_packets(kring, &q, 1);
kring->nr_hwcur = k;
kring->nr_hwavail = ring->avail = lim;
// na->nm_lock(na->ifp, NETMAP_CORE_UNLOCK, 0);
- /* send packets up, outside the lock */
- while ((m = head) != NULL) {
- head = head->m_nextpkt;
- m->m_nextpkt = NULL;
- if (netmap_verbose & NM_VERB_HOST)
- D("sending up pkt %p size %d", m, MBUF_LEN(m));
- NM_SEND_UP(na->ifp, m);
- }
+ netmap_send_up(na->ifp, q.head);
}
/*
@@ -877,6 +1035,7 @@ netmap_set_ringid(struct netmap_priv_d *priv, u_int ringid)
priv->np_txpoll = (ringid & NETMAP_NO_TX_POLL) ? 0 : 1;
if (need_lock)
na->nm_lock(ifp, NETMAP_CORE_UNLOCK, 0);
+ if (netmap_verbose) {
if (ringid & NETMAP_SW_RING)
D("ringid %s set to SW RING", ifp->if_xname);
else if (ringid & NETMAP_HW_RING)
@@ -884,6 +1043,7 @@ netmap_set_ringid(struct netmap_priv_d *priv, u_int ringid)
priv->np_qfirst);
else
D("ringid %s set to all %d HW RINGS", ifp->if_xname, lim);
+ }
return 0;
}
@@ -965,6 +1125,7 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
if (error)
break;
na = NA(ifp); /* retrieve netmap_adapter */
+ netmap_update_config(na);
nmr->nr_rx_rings = na->num_rx_rings;
nmr->nr_tx_rings = na->num_tx_rings;
nmr->nr_rx_slots = na->num_rx_desc;
@@ -1014,6 +1175,8 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
break;
}
+ /* ring configuration may have changed, fetch from the card */
+ netmap_update_config(na);
priv->np_ifp = ifp; /* store the reference */
error = netmap_set_ringid(priv, nmr->nr_ringid);
if (error)
@@ -1182,7 +1345,8 @@ netmap_poll(struct cdev *dev, int events, struct thread *td)
struct ifnet *ifp;
struct netmap_kring *kring;
u_int core_lock, i, check_all, want_tx, want_rx, revents = 0;
- u_int lim_tx, lim_rx;
+ u_int lim_tx, lim_rx, host_forwarded = 0;
+ struct mbq q = { NULL, NULL, 0 };
enum {NO_CL, NEED_CL, LOCKED_CL }; /* see below */
void *pwait = dev; /* linux compatibility */
@@ -1230,6 +1394,17 @@ netmap_poll(struct cdev *dev, int events, struct thread *td)
return (revents);
}
+ /* if we are in transparent mode, check also the host rx ring */
+ kring = &na->rx_rings[lim_rx];
+ if ( (priv->np_qlast == NETMAP_HW_RING) // XXX check_all
+ && want_rx
+ && (netmap_fwd || kring->ring->flags & NR_FORWARD) ) {
+ if (kring->ring->avail == 0)
+ netmap_sync_from_host(na, td, dev);
+ if (kring->ring->avail > 0)
+ revents |= want_rx;
+ }
+
/*
* check_all is set if the card has more than one queue and
* the client is polling all of them. If true, we sleep on
@@ -1305,6 +1480,7 @@ netmap_poll(struct cdev *dev, int events, struct thread *td)
* to avoid that the tx rings stall).
*/
if (priv->np_txpoll || want_tx) {
+flush_tx:
for (i = priv->np_qfirst; i < lim_tx; i++) {
kring = &na->tx_rings[i];
/*
@@ -1357,6 +1533,11 @@ netmap_poll(struct cdev *dev, int events, struct thread *td)
}
if (na->separate_locks)
na->nm_lock(ifp, NETMAP_RX_LOCK, i);
+ if (netmap_fwd ||kring->ring->flags & NR_FORWARD) {
+ ND(10, "forwarding some buffers up %d to %d",
+ kring->nr_hwcur, kring->ring->cur);
+ netmap_grab_packets(kring, &q, netmap_fwd);
+ }
if (na->nm_rxsync(ifp, i, 0 /* no lock */))
revents |= POLLERR;
@@ -1379,8 +1560,28 @@ netmap_poll(struct cdev *dev, int events, struct thread *td)
if (want_rx)
selrecord(td, &na->rx_si);
}
+
+ /* forward host to the netmap ring */
+ kring = &na->rx_rings[lim_rx];
+ if (kring->nr_hwavail > 0)
+ ND("host rx %d has %d packets", lim_rx, kring->nr_hwavail);
+ if ( (priv->np_qlast == NETMAP_HW_RING) // XXX check_all
+ && (netmap_fwd || kring->ring->flags & NR_FORWARD)
+ && kring->nr_hwavail > 0 && !host_forwarded) {
+ if (core_lock == NEED_CL) {
+ na->nm_lock(ifp, NETMAP_CORE_LOCK, 0);
+ core_lock = LOCKED_CL;
+ }
+ netmap_sw_to_nic(na);
+ host_forwarded = 1; /* prevent another pass */
+ want_rx = 0;
+ goto flush_tx;
+ }
+
if (core_lock == LOCKED_CL)
na->nm_lock(ifp, NETMAP_CORE_UNLOCK, 0);
+ if (q.head)
+ netmap_send_up(na->ifp, q.head);
return (revents);
}
@@ -1444,46 +1645,28 @@ netmap_lock_wrapper(struct ifnet *dev, int what, u_int queueid)
* setups.
*/
int
-netmap_attach(struct netmap_adapter *na, int num_queues)
+netmap_attach(struct netmap_adapter *arg, int num_queues)
{
- int n, size;
- void *buf;
- struct ifnet *ifp = na->ifp;
+ struct netmap_adapter *na = NULL;
+ struct ifnet *ifp = arg ? arg->ifp : NULL;
- if (ifp == NULL) {
- D("ifp not set, giving up");
- return EINVAL;
- }
- /* clear other fields ? */
- na->refcount = 0;
+ if (arg == NULL || ifp == NULL)
+ goto fail;
+ na = malloc(sizeof(*na), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (na == NULL)
+ goto fail;
+ WNA(ifp) = na;
+ *na = *arg; /* copy everything, trust the driver to not pass junk */
+ NETMAP_SET_CAPABLE(ifp);
if (na->num_tx_rings == 0)
na->num_tx_rings = num_queues;
na->num_rx_rings = num_queues;
- /* on each direction we have N+1 resources
- * 0..n-1 are the hardware rings
- * n is the ring attached to the stack.
- */
- n = na->num_rx_rings + na->num_tx_rings + 2;
- size = sizeof(*na) + n * sizeof(struct netmap_kring);
-
- buf = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
- if (buf) {
- WNA(ifp) = buf;
- na->tx_rings = (void *)((char *)buf + sizeof(*na));
- na->rx_rings = na->tx_rings + na->num_tx_rings + 1;
- bcopy(na, buf, sizeof(*na));
- NETMAP_SET_CAPABLE(ifp);
-
- na = buf;
- /* Core lock initialized here. Others are initialized after
- * netmap_if_new.
- */
- mtx_init(&na->core_lock, "netmap core lock", MTX_NETWORK_LOCK,
- MTX_DEF);
- if (na->nm_lock == NULL) {
- ND("using default locks for %s", ifp->if_xname);
- na->nm_lock = netmap_lock_wrapper;
- }
+ na->refcount = na->na_single = na->na_multi = 0;
+ /* Core lock initialized here, others after netmap_if_new. */
+ mtx_init(&na->core_lock, "netmap core lock", MTX_NETWORK_LOCK, MTX_DEF);
+ if (na->nm_lock == NULL) {
+ ND("using default locks for %s", ifp->if_xname);
+ na->nm_lock = netmap_lock_wrapper;
}
#ifdef linux
if (ifp->netdev_ops) {
@@ -1493,9 +1676,12 @@ netmap_attach(struct netmap_adapter *na, int num_queues)
}
na->nm_ndo.ndo_start_xmit = linux_netmap_start;
#endif
- D("%s for %s", buf ? "ok" : "failed", ifp->if_xname);
+ D("success for %s", ifp->if_xname);
+ return 0;
- return (buf ? 0 : ENOMEM);
+fail:
+ D("fail, arg %p ifp %p na %p", arg, ifp, na);
+ return (na ? EINVAL : ENOMEM);
}
@@ -1513,6 +1699,10 @@ netmap_detach(struct ifnet *ifp)
mtx_destroy(&na->core_lock);
+ if (na->tx_rings) { /* XXX should not happen */
+ D("freeing leftover tx_rings");
+ free(na->tx_rings, M_DEVBUF);
+ }
bzero(na, sizeof(*na));
WNA(ifp) = NULL;
free(na, M_DEVBUF);
@@ -1543,7 +1733,8 @@ netmap_start(struct ifnet *ifp, struct mbuf *m)
goto done; /* no space */
}
if (len > NETMAP_BUF_SIZE) {
- D("drop packet size %d > %d", len, NETMAP_BUF_SIZE);
+ D("%s from_host, drop packet size %d > %d", ifp->if_xname,
+ len, NETMAP_BUF_SIZE);
goto done; /* too long for us */
}
@@ -1554,6 +1745,7 @@ netmap_start(struct ifnet *ifp, struct mbuf *m)
slot = &kring->ring->slot[i];
m_copydata(m, 0, len, NMB(slot));
slot->len = len;
+ slot->flags = kring->nkr_slot_flags;
kring->nr_hwavail++;
if (netmap_verbose & NM_VERB_HOST)
D("wake up host ring %s %d", na->ifp->if_xname, na->num_rx_rings);
diff --git a/sys/dev/netmap/netmap_kern.h b/sys/dev/netmap/netmap_kern.h
index bb0d3fa..86a26fb 100644
--- a/sys/dev/netmap/netmap_kern.h
+++ b/sys/dev/netmap/netmap_kern.h
@@ -119,6 +119,10 @@ struct netmap_adapter;
* RX rings: the next empty buffer (hwcur + hwavail + hwofs) coincides with
* the next empty buffer as known by the hardware (next_to_check or so).
* TX rings: hwcur + hwofs coincides with next_to_send
+ *
+ * For received packets, slot->flags is set to nkr_slot_flags
+ * so we can provide a proper initial value (e.g. set NS_FORWARD
+ * when operating in 'transparent' mode).
*/
struct netmap_kring {
struct netmap_ring *ring;
@@ -128,6 +132,7 @@ struct netmap_kring {
#define NKR_PENDINTR 0x1 // Pending interrupt.
u_int nkr_num_slots;
+ uint16_t nkr_slot_flags; /* initial value for flags */
int nkr_hwofs; /* offset between NIC and netmap ring */
struct netmap_adapter *na;
NM_SELINFO_T si; /* poll/select wait queue */
@@ -198,6 +203,9 @@ struct netmap_adapter {
void (*nm_lock)(struct ifnet *, int what, u_int ringid);
int (*nm_txsync)(struct ifnet *, u_int ring, int lock);
int (*nm_rxsync)(struct ifnet *, u_int ring, int lock);
+ /* return configuration information */
+ int (*nm_config)(struct ifnet *, u_int *txr, u_int *txd,
+ u_int *rxr, u_int *rxd);
int bdg_port;
#ifdef linux
diff --git a/sys/dev/netmap/netmap_mem1.c b/sys/dev/netmap/netmap_mem1.c
deleted file mode 100644
index 521855a..0000000
--- a/sys/dev/netmap/netmap_mem1.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * $FreeBSD$
- *
- * The original netmap memory allocator, using a single large
- * chunk of memory allocated with contigmalloc.
- */
-
-/*
- * Default amount of memory pre-allocated by the module.
- * We start with a large size and then shrink our demand
- * according to what is avalable when the module is loaded.
- */
-#define NETMAP_MEMORY_SIZE (64 * 1024 * PAGE_SIZE)
-static void * netmap_malloc(size_t size, const char *msg);
-static void netmap_free(void *addr, const char *msg);
-
-#define netmap_if_malloc(len) netmap_malloc(len, "nifp")
-#define netmap_if_free(v) netmap_free((v), "nifp")
-
-#define netmap_ring_malloc(len) netmap_malloc(len, "ring")
-#define netmap_free_rings(na) \
- netmap_free((na)->tx_rings[0].ring, "shadow rings");
-
-/*
- * Allocator for a pool of packet buffers. For each buffer we have
- * one entry in the bitmap to signal the state. Allocation scans
- * the bitmap, but since this is done only on attach, we are not
- * too worried about performance
- * XXX if we need to allocate small blocks, a translation
- * table is used both for kernel virtual address and physical
- * addresses.
- */
-struct netmap_buf_pool {
- u_int total_buffers; /* total buffers. */
- u_int free;
- u_int bufsize;
- char *base; /* buffer base address */
- uint32_t *bitmap; /* one bit per buffer, 1 means free */
-};
-struct netmap_buf_pool nm_buf_pool;
-SYSCTL_INT(_dev_netmap, OID_AUTO, total_buffers,
- CTLFLAG_RD, &nm_buf_pool.total_buffers, 0, "total_buffers");
-SYSCTL_INT(_dev_netmap, OID_AUTO, free_buffers,
- CTLFLAG_RD, &nm_buf_pool.free, 0, "free_buffers");
-
-
-/*
- * Allocate n buffers from the ring, and fill the slot.
- * Buffer 0 is the 'junk' buffer.
- */
-static void
-netmap_new_bufs(struct netmap_if *nifp __unused,
- struct netmap_slot *slot, u_int n)
-{
- struct netmap_buf_pool *p = &nm_buf_pool;
- uint32_t bi = 0; /* index in the bitmap */
- uint32_t mask, j, i = 0; /* slot counter */
-
- if (n > p->free) {
- D("only %d out of %d buffers available", i, n);
- return;
- }
- /* termination is guaranteed by p->free */
- while (i < n && p->free > 0) {
- uint32_t cur = p->bitmap[bi];
- if (cur == 0) { /* bitmask is fully used */
- bi++;
- continue;
- }
- /* locate a slot */
- for (j = 0, mask = 1; (cur & mask) == 0; j++, mask <<= 1) ;
- p->bitmap[bi] &= ~mask; /* slot in use */
- p->free--;
- slot[i].buf_idx = bi*32+j;
- slot[i].len = p->bufsize;
- slot[i].flags = NS_BUF_CHANGED;
- i++;
- }
- ND("allocated %d buffers, %d available", n, p->free);
-}
-
-
-static void
-netmap_free_buf(struct netmap_if *nifp __unused, uint32_t i)
-{
- struct netmap_buf_pool *p = &nm_buf_pool;
-
- uint32_t pos, mask;
- if (i >= p->total_buffers) {
- D("invalid free index %d", i);
- return;
- }
- pos = i / 32;
- mask = 1 << (i % 32);
- if (p->bitmap[pos] & mask) {
- D("slot %d already free", i);
- return;
- }
- p->bitmap[pos] |= mask;
- p->free++;
-}
-
-
-/* Descriptor of the memory objects handled by our memory allocator. */
-struct netmap_mem_obj {
- TAILQ_ENTRY(netmap_mem_obj) nmo_next; /* next object in the
- chain. */
- int nmo_used; /* flag set on used memory objects. */
- size_t nmo_size; /* size of the memory area reserved for the
- object. */
- void *nmo_data; /* pointer to the memory area. */
-};
-
-/* Wrap our memory objects to make them ``chainable``. */
-TAILQ_HEAD(netmap_mem_obj_h, netmap_mem_obj);
-
-
-/* Descriptor of our custom memory allocator. */
-struct netmap_mem_d {
- struct mtx nm_mtx; /* lock used to handle the chain of memory
- objects. */
- struct netmap_mem_obj_h nm_molist; /* list of memory objects */
- size_t nm_size; /* total amount of memory used for rings etc. */
- size_t nm_totalsize; /* total amount of allocated memory
- (the difference is used for buffers) */
- size_t nm_buf_start; /* offset of packet buffers.
- This is page-aligned. */
- size_t nm_buf_len; /* total memory for buffers */
- void *nm_buffer; /* pointer to the whole pre-allocated memory
- area. */
-};
-
-/* Shorthand to compute a netmap interface offset. */
-#define netmap_if_offset(v) \
- ((char *) (v) - (char *) nm_mem->nm_buffer)
-/* .. and get a physical address given a memory offset */
-#define netmap_ofstophys(o) \
- (vtophys(nm_mem->nm_buffer) + (o))
-
-
-/*------ netmap memory allocator -------*/
-/*
- * Request for a chunk of memory.
- *
- * Memory objects are arranged into a list, hence we need to walk this
- * list until we find an object with the needed amount of data free.
- * This sounds like a completely inefficient implementation, but given
- * the fact that data allocation is done once, we can handle it
- * flawlessly.
- *
- * Return NULL on failure.
- */
-static void *
-netmap_malloc(size_t size, __unused const char *msg)
-{
- struct netmap_mem_obj *mem_obj, *new_mem_obj;
- void *ret = NULL;
-
- NMA_LOCK();
- TAILQ_FOREACH(mem_obj, &nm_mem->nm_molist, nmo_next) {
- if (mem_obj->nmo_used != 0 || mem_obj->nmo_size < size)
- continue;
-
- new_mem_obj = malloc(sizeof(struct netmap_mem_obj), M_NETMAP,
- M_WAITOK | M_ZERO);
- TAILQ_INSERT_BEFORE(mem_obj, new_mem_obj, nmo_next);
-
- new_mem_obj->nmo_used = 1;
- new_mem_obj->nmo_size = size;
- new_mem_obj->nmo_data = mem_obj->nmo_data;
- memset(new_mem_obj->nmo_data, 0, new_mem_obj->nmo_size);
-
- mem_obj->nmo_size -= size;
- mem_obj->nmo_data = (char *) mem_obj->nmo_data + size;
- if (mem_obj->nmo_size == 0) {
- TAILQ_REMOVE(&nm_mem->nm_molist, mem_obj,
- nmo_next);
- free(mem_obj, M_NETMAP);
- }
-
- ret = new_mem_obj->nmo_data;
-
- break;
- }
- NMA_UNLOCK();
- ND("%s: %d bytes at %p", msg, size, ret);
-
- return (ret);
-}
-
-/*
- * Return the memory to the allocator.
- *
- * While freeing a memory object, we try to merge adjacent chunks in
- * order to reduce memory fragmentation.
- */
-static void
-netmap_free(void *addr, const char *msg)
-{
- size_t size;
- struct netmap_mem_obj *cur, *prev, *next;
-
- if (addr == NULL) {
- D("NULL addr for %s", msg);
- return;
- }
-
- NMA_LOCK();
- TAILQ_FOREACH(cur, &nm_mem->nm_molist, nmo_next) {
- if (cur->nmo_data == addr && cur->nmo_used)
- break;
- }
- if (cur == NULL) {
- NMA_UNLOCK();
- D("invalid addr %s %p", msg, addr);
- return;
- }
-
- size = cur->nmo_size;
- cur->nmo_used = 0;
-
- /* merge current chunk of memory with the previous one,
- if present. */
- prev = TAILQ_PREV(cur, netmap_mem_obj_h, nmo_next);
- if (prev && prev->nmo_used == 0) {
- TAILQ_REMOVE(&nm_mem->nm_molist, cur, nmo_next);
- prev->nmo_size += cur->nmo_size;
- free(cur, M_NETMAP);
- cur = prev;
- }
-
- /* merge with the next one */
- next = TAILQ_NEXT(cur, nmo_next);
- if (next && next->nmo_used == 0) {
- TAILQ_REMOVE(&nm_mem->nm_molist, next, nmo_next);
- cur->nmo_size += next->nmo_size;
- free(next, M_NETMAP);
- }
- NMA_UNLOCK();
- ND("freed %s %d bytes at %p", msg, size, addr);
-}
-
-
-/*
- * Create and return a new ``netmap_if`` object, and possibly also
- * rings and packet buffors.
- *
- * Return NULL on failure.
- */
-static void *
-netmap_if_new(const char *ifname, struct netmap_adapter *na)
-{
- struct netmap_if *nifp;
- struct netmap_ring *ring;
- struct netmap_kring *kring;
- char *buff;
- u_int i, len, ofs, numdesc;
- u_int nrx = na->num_rx_rings + 1; /* shorthand, include stack queue */
- u_int ntx = na->num_tx_rings + 1; /* shorthand, include stack queue */
-
- /*
- * the descriptor is followed inline by an array of offsets
- * to the tx and rx rings in the shared memory region.
- */
- len = sizeof(struct netmap_if) + (nrx + ntx) * sizeof(ssize_t);
- nifp = netmap_if_malloc(len);
- if (nifp == NULL)
- return (NULL);
-
- /* initialize base fields */
- *(int *)(uintptr_t)&nifp->ni_rx_rings = na->num_rx_rings;
- *(int *)(uintptr_t)&nifp->ni_tx_rings = na->num_tx_rings;
- strncpy(nifp->ni_name, ifname, IFNAMSIZ);
-
- (na->refcount)++; /* XXX atomic ? we are under lock */
- if (na->refcount > 1)
- goto final;
-
- /*
- * First instance. Allocate the netmap rings
- * (one for each hw queue, one pair for the host).
- * The rings are contiguous, but have variable size.
- * The entire block is reachable at
- * na->tx_rings[0]
- */
- len = (ntx + nrx) * sizeof(struct netmap_ring) +
- (ntx * na->num_tx_desc + nrx * na->num_rx_desc) *
- sizeof(struct netmap_slot);
- buff = netmap_ring_malloc(len);
- if (buff == NULL) {
- D("failed to allocate %d bytes for %s shadow ring",
- len, ifname);
-error:
- (na->refcount)--;
- netmap_if_free(nifp);
- return (NULL);
- }
- /* Check whether we have enough buffers */
- len = ntx * na->num_tx_desc + nrx * na->num_rx_desc;
- NMA_LOCK();
- if (nm_buf_pool.free < len) {
- NMA_UNLOCK();
- netmap_free(buff, "not enough bufs");
- goto error;
- }
- /*
- * in the kring, store the pointers to the shared rings
- * and initialize the rings. We are under NMA_LOCK().
- */
- ofs = 0;
- for (i = 0; i < ntx; i++) { /* Transmit rings */
- kring = &na->tx_rings[i];
- numdesc = na->num_tx_desc;
- bzero(kring, sizeof(*kring));
- kring->na = na;
-
- ring = kring->ring = (struct netmap_ring *)(buff + ofs);
- *(ssize_t *)(uintptr_t)&ring->buf_ofs =
- nm_buf_pool.base - (char *)ring;
- ND("txring[%d] at %p ofs %d", i, ring, ring->buf_ofs);
- *(uint32_t *)(uintptr_t)&ring->num_slots =
- kring->nkr_num_slots = numdesc;
-
- /*
- * IMPORTANT:
- * Always keep one slot empty, so we can detect new
- * transmissions comparing cur and nr_hwcur (they are
- * the same only if there are no new transmissions).
- */
- ring->avail = kring->nr_hwavail = numdesc - 1;
- ring->cur = kring->nr_hwcur = 0;
- *(uint16_t *)(uintptr_t)&ring->nr_buf_size = NETMAP_BUF_SIZE;
- netmap_new_bufs(nifp, ring->slot, numdesc);
-
- ofs += sizeof(struct netmap_ring) +
- numdesc * sizeof(struct netmap_slot);
- }
-
- for (i = 0; i < nrx; i++) { /* Receive rings */
- kring = &na->rx_rings[i];
- numdesc = na->num_rx_desc;
- bzero(kring, sizeof(*kring));
- kring->na = na;
-
- ring = kring->ring = (struct netmap_ring *)(buff + ofs);
- *(ssize_t *)(uintptr_t)&ring->buf_ofs =
- nm_buf_pool.base - (char *)ring;
- ND("rxring[%d] at %p offset %d", i, ring, ring->buf_ofs);
- *(uint32_t *)(uintptr_t)&ring->num_slots =
- kring->nkr_num_slots = numdesc;
- ring->cur = kring->nr_hwcur = 0;
- ring->avail = kring->nr_hwavail = 0; /* empty */
- *(uint16_t *)(uintptr_t)&ring->nr_buf_size = NETMAP_BUF_SIZE;
- netmap_new_bufs(nifp, ring->slot, numdesc);
- ofs += sizeof(struct netmap_ring) +
- numdesc * sizeof(struct netmap_slot);
- }
- NMA_UNLOCK();
- // XXX initialize the selrecord structs.
-
-final:
- /*
- * fill the slots for the rx and tx queues. They contain the offset
- * between the ring and nifp, so the information is usable in
- * userspace to reach the ring from the nifp.
- */
- for (i = 0; i < ntx; i++) {
- *(ssize_t *)(uintptr_t)&nifp->ring_ofs[i] =
- (char *)na->tx_rings[i].ring - (char *)nifp;
- }
- for (i = 0; i < nrx; i++) {
- *(ssize_t *)(uintptr_t)&nifp->ring_ofs[i+ntx] =
- (char *)na->rx_rings[i].ring - (char *)nifp;
- }
- return (nifp);
-}
-
-/*
- * Initialize the memory allocator.
- *
- * Create the descriptor for the memory , allocate the pool of memory
- * and initialize the list of memory objects with a single chunk
- * containing the whole pre-allocated memory marked as free.
- *
- * Start with a large size, then halve as needed if we fail to
- * allocate the block. While halving, always add one extra page
- * because buffers 0 and 1 are used for special purposes.
- * Return 0 on success, errno otherwise.
- */
-static int
-netmap_memory_init(void)
-{
- struct netmap_mem_obj *mem_obj;
- void *buf = NULL;
- int i, n, sz = NETMAP_MEMORY_SIZE;
- int extra_sz = 0; // space for rings and two spare buffers
-
- for (; sz >= 1<<20; sz >>=1) {
- extra_sz = sz/200;
- extra_sz = (extra_sz + 2*PAGE_SIZE - 1) & ~(PAGE_SIZE-1);
- buf = contigmalloc(sz + extra_sz,
- M_NETMAP,
- M_WAITOK | M_ZERO,
- 0, /* low address */
- -1UL, /* high address */
- PAGE_SIZE, /* alignment */
- 0 /* boundary */
- );
- if (buf)
- break;
- }
- if (buf == NULL)
- return (ENOMEM);
- sz += extra_sz;
- nm_mem = malloc(sizeof(struct netmap_mem_d), M_NETMAP,
- M_WAITOK | M_ZERO);
- mtx_init(&nm_mem->nm_mtx, "netmap memory allocator lock", NULL,
- MTX_DEF);
- TAILQ_INIT(&nm_mem->nm_molist);
- nm_mem->nm_buffer = buf;
- nm_mem->nm_totalsize = sz;
-
- /*
- * A buffer takes 2k, a slot takes 8 bytes + ring overhead,
- * so the ratio is 200:1. In other words, we can use 1/200 of
- * the memory for the rings, and the rest for the buffers,
- * and be sure we never run out.
- */
- nm_mem->nm_size = sz/200;
- nm_mem->nm_buf_start =
- (nm_mem->nm_size + PAGE_SIZE - 1) & ~(PAGE_SIZE-1);
- nm_mem->nm_buf_len = sz - nm_mem->nm_buf_start;
-
- nm_buf_pool.base = nm_mem->nm_buffer;
- nm_buf_pool.base += nm_mem->nm_buf_start;
- netmap_buffer_base = nm_buf_pool.base;
- D("netmap_buffer_base %p (offset %d)",
- netmap_buffer_base, (int)nm_mem->nm_buf_start);
- /* number of buffers, they all start as free */
-
- netmap_total_buffers = nm_buf_pool.total_buffers =
- nm_mem->nm_buf_len / NETMAP_BUF_SIZE;
- nm_buf_pool.bufsize = NETMAP_BUF_SIZE;
-
- D("Have %d MB, use %dKB for rings, %d buffers at %p",
- (sz >> 20), (int)(nm_mem->nm_size >> 10),
- nm_buf_pool.total_buffers, nm_buf_pool.base);
-
- /* allocate and initialize the bitmap. Entry 0 is considered
- * always busy (used as default when there are no buffers left).
- */
- n = (nm_buf_pool.total_buffers + 31) / 32;
- nm_buf_pool.bitmap = malloc(sizeof(uint32_t) * n, M_NETMAP,
- M_WAITOK | M_ZERO);
- nm_buf_pool.bitmap[0] = ~3; /* slot 0 and 1 always busy */
- for (i = 1; i < n; i++)
- nm_buf_pool.bitmap[i] = ~0;
- nm_buf_pool.free = nm_buf_pool.total_buffers - 2;
-
- mem_obj = malloc(sizeof(struct netmap_mem_obj), M_NETMAP,
- M_WAITOK | M_ZERO);
- TAILQ_INSERT_HEAD(&nm_mem->nm_molist, mem_obj, nmo_next);
- mem_obj->nmo_used = 0;
- mem_obj->nmo_size = nm_mem->nm_size;
- mem_obj->nmo_data = nm_mem->nm_buffer;
-
- return (0);
-}
-
-
-/*
- * Finalize the memory allocator.
- *
- * Free all the memory objects contained inside the list, and deallocate
- * the pool of memory; finally free the memory allocator descriptor.
- */
-static void
-netmap_memory_fini(void)
-{
- struct netmap_mem_obj *mem_obj;
-
- while (!TAILQ_EMPTY(&nm_mem->nm_molist)) {
- mem_obj = TAILQ_FIRST(&nm_mem->nm_molist);
- TAILQ_REMOVE(&nm_mem->nm_molist, mem_obj, nmo_next);
- if (mem_obj->nmo_used == 1) {
- printf("netmap: leaked %d bytes at %p\n",
- (int)mem_obj->nmo_size,
- mem_obj->nmo_data);
- }
- free(mem_obj, M_NETMAP);
- }
- contigfree(nm_mem->nm_buffer, nm_mem->nm_totalsize, M_NETMAP);
- // XXX mutex_destroy(nm_mtx);
- free(nm_mem, M_NETMAP);
-}
-/*------------- end of memory allocator -----------------*/
diff --git a/sys/dev/netmap/netmap_mem2.c b/sys/dev/netmap/netmap_mem2.c
index 7472178..03a52b6 100644
--- a/sys/dev/netmap/netmap_mem2.c
+++ b/sys/dev/netmap/netmap_mem2.c
@@ -388,7 +388,7 @@ netmap_obj_free_va(struct netmap_obj_pool *p, void *vaddr)
netmap_obj_free(p, j);
return;
}
- ND("address %p is not contained inside any cluster (%s)",
+ D("address %p is not contained inside any cluster (%s)",
vaddr, p->name);
}
@@ -559,8 +559,9 @@ netmap_config_obj_allocator(struct netmap_obj_pool *p, u_int objtotal, u_int obj
i = (clustsize & (PAGE_SIZE - 1));
if (i)
clustsize += PAGE_SIZE - i;
- D("objsize %d clustsize %d objects %d",
- objsize, clustsize, clustentries);
+ if (netmap_verbose)
+ D("objsize %d clustsize %d objects %d",
+ objsize, clustsize, clustentries);
/*
* The number of clusters is n = ceil(objtotal/clustentries)
@@ -649,9 +650,10 @@ netmap_finalize_obj_allocator(struct netmap_obj_pool *p)
}
}
p->bitmap[0] = ~3; /* objs 0 and 1 is always busy */
- D("Pre-allocated %d clusters (%d/%dKB) for '%s'",
- p->_numclusters, p->_clustsize >> 10,
- p->_memtotal >> 10, p->name);
+ if (netmap_verbose)
+ D("Pre-allocated %d clusters (%d/%dKB) for '%s'",
+ p->_numclusters, p->_clustsize >> 10,
+ p->_memtotal >> 10, p->name);
return 0;
@@ -721,7 +723,7 @@ netmap_memory_finalize(void)
nm_mem.refcount++;
if (nm_mem.refcount > 1) {
- D("busy (refcount %d)", nm_mem.refcount);
+ ND("busy (refcount %d)", nm_mem.refcount);
goto out;
}
@@ -796,6 +798,8 @@ static void
netmap_free_rings(struct netmap_adapter *na)
{
int i;
+ if (!na->tx_rings)
+ return;
for (i = 0; i < na->num_tx_rings + 1; i++) {
netmap_ring_free(na->tx_rings[i].ring);
na->tx_rings[i].ring = NULL;
@@ -804,22 +808,32 @@ netmap_free_rings(struct netmap_adapter *na)
netmap_ring_free(na->rx_rings[i].ring);
na->rx_rings[i].ring = NULL;
}
+ free(na->tx_rings, M_DEVBUF);
+ na->tx_rings = na->rx_rings = NULL;
}
/* call with NMA_LOCK held */
+/*
+ * Allocate the per-fd structure netmap_if.
+ * If this is the first instance, also allocate the krings, rings etc.
+ */
static void *
netmap_if_new(const char *ifname, struct netmap_adapter *na)
{
struct netmap_if *nifp;
struct netmap_ring *ring;
ssize_t base; /* handy for relative offsets between rings and nifp */
- u_int i, len, ndesc;
- u_int ntx = na->num_tx_rings + 1; /* shorthand, include stack ring */
- u_int nrx = na->num_rx_rings + 1; /* shorthand, include stack ring */
+ u_int i, len, ndesc, ntx, nrx;
struct netmap_kring *kring;
+ if (netmap_update_config(na)) {
+ /* configuration mismatch, report and fail */
+ return NULL;
+ }
+ ntx = na->num_tx_rings + 1; /* shorthand, include stack ring */
+ nrx = na->num_rx_rings + 1; /* shorthand, include stack ring */
/*
* the descriptor is followed inline by an array of offsets
* to the tx and rx rings in the shared memory region.
@@ -840,6 +854,14 @@ netmap_if_new(const char *ifname, struct netmap_adapter *na)
goto final;
}
+ len = (ntx + nrx) * sizeof(struct netmap_kring);
+ na->tx_rings = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (na->tx_rings == NULL) {
+ D("Cannot allocate krings for %s", ifname);
+ goto cleanup;
+ }
+ na->rx_rings = na->tx_rings + ntx;
+
/*
* First instance, allocate netmap rings and buffers for this card
* The rings are contiguous, but have variable size.
@@ -947,5 +969,6 @@ static void
netmap_memory_deref(void)
{
nm_mem.refcount--;
- D("refcount = %d", nm_mem.refcount);
+ if (netmap_verbose)
+ D("refcount = %d", nm_mem.refcount);
}
diff --git a/sys/dev/nvram2env/nvram2env.c b/sys/dev/nvram2env/nvram2env.c
index 32f17f9..5de4f87 100644
--- a/sys/dev/nvram2env/nvram2env.c
+++ b/sys/dev/nvram2env/nvram2env.c
@@ -303,7 +303,8 @@ static device_method_t nvram2env_methods[] = {
DEVMETHOD(device_identify, nvram2env_identify),
DEVMETHOD(device_probe, nvram2env_probe),
DEVMETHOD(device_attach, nvram2env_attach),
- {0, 0},
+
+ DEVMETHOD_END
};
static driver_t nvram2env_driver = {
diff --git a/sys/dev/nxge/if_nxge.c b/sys/dev/nxge/if_nxge.c
index c7dbeb6..df1b9ec 100644
--- a/sys/dev/nxge/if_nxge.c
+++ b/sys/dev/nxge/if_nxge.c
@@ -3507,7 +3507,8 @@ static device_method_t xge_methods[] = {
DEVMETHOD(device_attach, xge_attach),
DEVMETHOD(device_detach, xge_detach),
DEVMETHOD(device_shutdown, xge_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t xge_driver = {
diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c
index 7d15fcc..cba57bf 100644
--- a/sys/dev/oce/oce_if.c
+++ b/sys/dev/oce/oce_if.c
@@ -108,7 +108,8 @@ static device_method_t oce_dispatch[] = {
DEVMETHOD(device_attach, oce_attach),
DEVMETHOD(device_detach, oce_detach),
DEVMETHOD(device_shutdown, oce_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t oce_driver = {
diff --git a/sys/dev/puc/puc.c b/sys/dev/puc/puc.c
index 7b93306..d7bfb63 100644
--- a/sys/dev/puc/puc.c
+++ b/sys/dev/puc/puc.c
@@ -622,7 +622,7 @@ puc_bus_setup_intr(device_t dev, device_t child, struct resource *res,
if (cookiep == NULL || res != port->p_ires)
return (EINVAL);
/* We demand that serdev devices use filter_only interrupts. */
- if (ihand != NULL)
+ if (port->p_type == PUC_TYPE_SERIAL && ihand != NULL)
return (ENXIO);
if (rman_get_device(port->p_ires) != originator)
return (ENXIO);
diff --git a/sys/dev/sdhci/sdhci_pci.c b/sys/dev/sdhci/sdhci_pci.c
index 02dc2a1..b8d8530 100644
--- a/sys/dev/sdhci/sdhci_pci.c
+++ b/sys/dev/sdhci/sdhci_pci.c
@@ -426,7 +426,7 @@ static device_method_t sdhci_methods[] = {
DEVMETHOD(sdhci_write_4, sdhci_pci_write_4),
DEVMETHOD(sdhci_write_multi_4, sdhci_pci_write_multi_4),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t sdhci_pci_driver = {
diff --git a/sys/dev/sound/pci/emu10kx-midi.c b/sys/dev/sound/pci/emu10kx-midi.c
index c85800e..0d5fa30 100644
--- a/sys/dev/sound/pci/emu10kx-midi.c
+++ b/sys/dev/sound/pci/emu10kx-midi.c
@@ -239,7 +239,7 @@ static device_method_t emu_midi_methods[] = {
DEVMETHOD(device_attach, emu_midi_attach),
DEVMETHOD(device_detach, emu_midi_detach),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t emu_midi_driver = {
diff --git a/sys/dev/sound/pci/emu10kx-pcm.c b/sys/dev/sound/pci/emu10kx-pcm.c
index ab20dc6..406a85f 100644
--- a/sys/dev/sound/pci/emu10kx-pcm.c
+++ b/sys/dev/sound/pci/emu10kx-pcm.c
@@ -1520,7 +1520,8 @@ static device_method_t emu_pcm_methods[] = {
DEVMETHOD(device_probe, emu_pcm_probe),
DEVMETHOD(device_attach, emu_pcm_attach),
DEVMETHOD(device_detach, emu_pcm_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t emu_pcm_driver = {
diff --git a/sys/dev/sound/pci/emu10kx.c b/sys/dev/sound/pci/emu10kx.c
index 5f217c1..35a4957 100644
--- a/sys/dev/sound/pci/emu10kx.c
+++ b/sys/dev/sound/pci/emu10kx.c
@@ -3529,7 +3529,7 @@ static device_method_t emu_methods[] = {
DEVMETHOD(bus_read_ivar, emu_read_ivar),
DEVMETHOD(bus_write_ivar, emu_write_ivar),
- {0, 0}
+ DEVMETHOD_END
};
diff --git a/sys/dev/sound/sbus/cs4231.c b/sys/dev/sound/sbus/cs4231.c
index e643a4e..83f70f3 100644
--- a/sys/dev/sound/sbus/cs4231.c
+++ b/sys/dev/sound/sbus/cs4231.c
@@ -231,7 +231,8 @@ static device_method_t cs4231_sbus_methods[] = {
DEVMETHOD(device_detach, cs4231_bus_detach),
DEVMETHOD(device_suspend, cs4231_bus_suspend),
DEVMETHOD(device_resume, cs4231_bus_resume),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t cs4231_sbus_driver = {
@@ -249,7 +250,8 @@ static device_method_t cs4231_ebus_methods[] = {
DEVMETHOD(device_detach, cs4231_bus_detach),
DEVMETHOD(device_suspend, cs4231_bus_suspend),
DEVMETHOD(device_resume, cs4231_bus_resume),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t cs4231_ebus_driver = {
diff --git a/sys/dev/sound/usb/uaudio_pcm.c b/sys/dev/sound/usb/uaudio_pcm.c
index b57d0fb..bd00a01 100644
--- a/sys/dev/sound/usb/uaudio_pcm.c
+++ b/sys/dev/sound/usb/uaudio_pcm.c
@@ -227,7 +227,7 @@ static device_method_t ua_pcm_methods[] = {
DEVMETHOD(device_attach, ua_attach),
DEVMETHOD(device_detach, ua_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ua_pcm_driver = {
diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c
index b644f94..7d0450c 100644
--- a/sys/dev/sym/sym_hipd.c
+++ b/sys/dev/sym/sym_hipd.c
@@ -86,6 +86,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
+#include <machine/atomic.h>
#ifdef __sparc64__
#include <dev/ofw/openfirm.h>
@@ -136,7 +137,7 @@ typedef u_int32_t u32;
#elif defined __sparc64__
#define MEMORY_BARRIER() __asm__ volatile("membar #Sync" : : : "memory")
#elif defined __arm__
-#define MEMORY_BARRIER() __do_dmb()
+#define MEMORY_BARRIER() dmb()
#else
#error "Not supported platform"
#endif
@@ -3426,7 +3427,6 @@ sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
/*
* Check against our hardware limits, or bugs :).
*/
- if (fak < 0) {fak = 0; ret = -1;}
if (fak > 2) {fak = 2; ret = -1;}
/*
diff --git a/sys/dev/terasic/de4led/terasic_de4led.c b/sys/dev/terasic/de4led/terasic_de4led.c
index 1fb92d2..bcef7af 100644
--- a/sys/dev/terasic/de4led/terasic_de4led.c
+++ b/sys/dev/terasic/de4led/terasic_de4led.c
@@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
#include <dev/led/led.h>
#include <dev/terasic/de4led/terasic_de4led.h>
+devclass_t terasic_de4led_devclass;
+
static void
terasic_de4led_update(struct terasic_de4led_softc *sc)
{
diff --git a/sys/dev/terasic/de4led/terasic_de4led.h b/sys/dev/terasic/de4led/terasic_de4led.h
index 89461d1..4475e9b 100644
--- a/sys/dev/terasic/de4led/terasic_de4led.h
+++ b/sys/dev/terasic/de4led/terasic_de4led.h
@@ -72,4 +72,6 @@ struct terasic_de4led_softc {
void terasic_de4led_attach(struct terasic_de4led_softc *sc);
void terasic_de4led_detach(struct terasic_de4led_softc *sc);
+extern devclass_t terasic_de4led_devclass;
+
#endif /* _DEV_TERASIC_DE4LED_H_ */
diff --git a/sys/dev/terasic/de4led/terasic_de4led_fdt.c b/sys/dev/terasic/de4led/terasic_de4led_fdt.c
new file mode 100644
index 0000000..0888d6d
--- /dev/null
+++ b/sys/dev/terasic/de4led/terasic_de4led_fdt.c
@@ -0,0 +1,118 @@
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/terasic/de4led/terasic_de4led.h>
+
+/*
+ * Nexus bus attachment for the 8-element LED on the Terasic DE-4 FPGA board,
+ * which is hooked up to the processor via a memory-mapped Avalon bus.
+ */
+static int
+terasic_de4led_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "sri-cambridge,de4led")) {
+ device_set_desc(dev, "Terasic DE4 8-element LED");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+terasic_de4led_fdt_attach(device_t dev)
+{
+ struct terasic_de4led_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->tdl_dev = dev;
+ sc->tdl_unit = device_get_unit(dev);
+ sc->tdl_rid = 0;
+ sc->tdl_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->tdl_rid, RF_ACTIVE);
+ if (sc->tdl_res == NULL) {
+ device_printf(dev, "couldn't map memory\n");
+ return (ENXIO);
+ }
+ terasic_de4led_attach(sc);
+ return (0);
+}
+
+static int
+terasic_de4led_fdt_detach(device_t dev)
+{
+ struct terasic_de4led_softc *sc;
+
+ sc = device_get_softc(dev);
+ KASSERT(sc->tdl_res != NULL, ("%s: resources not allocated",
+ __func__));
+ terasic_de4led_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->tdl_rid, sc->tdl_res);
+ return (0);
+}
+
+static device_method_t terasic_de4led_fdt_methods[] = {
+ DEVMETHOD(device_probe, terasic_de4led_fdt_probe),
+ DEVMETHOD(device_attach, terasic_de4led_fdt_attach),
+ DEVMETHOD(device_detach, terasic_de4led_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t terasic_de4led_fdt_driver = {
+ "terasic_de4led",
+ terasic_de4led_fdt_methods,
+ sizeof(struct terasic_de4led_softc),
+};
+
+DRIVER_MODULE(terasic_de4led, simplebus, terasic_de4led_fdt_driver,
+ terasic_de4led_devclass, 0, 0);
diff --git a/sys/dev/terasic/de4led/terasic_de4led_nexus.c b/sys/dev/terasic/de4led/terasic_de4led_nexus.c
index 92da503..870d412 100644
--- a/sys/dev/terasic/de4led/terasic_de4led_nexus.c
+++ b/sys/dev/terasic/de4led/terasic_de4led_nexus.c
@@ -106,7 +106,5 @@ static driver_t terasic_de4led_nexus_driver = {
sizeof(struct terasic_de4led_softc),
};
-static devclass_t terasic_de4led_devclass;
-
DRIVER_MODULE(terasic_de4led, nexus, terasic_de4led_nexus_driver,
terasic_de4led_devclass, 0, 0);
diff --git a/sys/dev/terasic/mtl/terasic_mtl.c b/sys/dev/terasic/mtl/terasic_mtl.c
index 48e60c7..5305172 100644
--- a/sys/dev/terasic/mtl/terasic_mtl.c
+++ b/sys/dev/terasic/mtl/terasic_mtl.c
@@ -63,6 +63,9 @@ __FBSDID("$FreeBSD$");
* attached as they may be called even if the attach routine hasn't been, on
* an error.
*/
+
+devclass_t terasic_mtl_devclass;
+
int
terasic_mtl_attach(struct terasic_mtl_softc *sc)
{
diff --git a/sys/dev/terasic/mtl/terasic_mtl.h b/sys/dev/terasic/mtl/terasic_mtl.h
index ae41067..e07bbf4 100644
--- a/sys/dev/terasic/mtl/terasic_mtl.h
+++ b/sys/dev/terasic/mtl/terasic_mtl.h
@@ -159,6 +159,8 @@ struct terasic_mtl_softc {
int terasic_mtl_attach(struct terasic_mtl_softc *sc);
void terasic_mtl_detach(struct terasic_mtl_softc *sc);
+extern devclass_t terasic_mtl_devclass;
+
/*
* Sub-driver setup routines.
*/
diff --git a/sys/dev/terasic/mtl/terasic_mtl_fdt.c b/sys/dev/terasic/mtl/terasic_mtl_fdt.c
new file mode 100644
index 0000000..7ffffb2
--- /dev/null
+++ b/sys/dev/terasic/mtl/terasic_mtl_fdt.c
@@ -0,0 +1,200 @@
+/*-
+ * Copyright (c) 2012-2013 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/consio.h> /* struct vt_mode */
+#include <sys/fbio.h> /* video_adapter_t */
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/terasic/mtl/terasic_mtl.h>
+
+static int
+terasic_mtl_fdt_probe(device_t dev)
+{
+
+ if (ofw_bus_is_compatible(dev, "sri-cambridge,mtl")) {
+ device_set_desc(dev, "Terasic Multi-touch LCD (MTL)");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+terasic_mtl_fdt_attach(device_t dev)
+{
+ struct terasic_mtl_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ sc->mtl_dev = dev;
+ sc->mtl_unit = device_get_unit(dev);
+
+ /*
+ * FDT allows multiple memory resources to be defined for a device;
+ * query them in the order registers, pixel buffer, text buffer.
+ * However, we need to sanity-check that they are page-aligned and
+ * page-sized, so we may still abort.
+ */
+ sc->mtl_reg_rid = 0;
+ sc->mtl_reg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->mtl_reg_rid, RF_ACTIVE);
+ if (sc->mtl_reg_res == NULL) {
+ device_printf(dev, "couldn't map register memory\n");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_start(sc->mtl_reg_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper register address");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_size(sc->mtl_reg_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper register size");
+ error = ENXIO;
+ goto error;
+ }
+ device_printf(sc->mtl_dev, "registers at mem %p-%p\n",
+ (void *)rman_get_start(sc->mtl_reg_res),
+ (void *)(rman_get_start(sc->mtl_reg_res) +
+ rman_get_size(sc->mtl_reg_res)));
+
+ sc->mtl_pixel_rid = 1;
+ sc->mtl_pixel_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->mtl_pixel_rid, RF_ACTIVE);
+ if (sc->mtl_pixel_res == NULL) {
+ device_printf(dev, "couldn't map pixel memory\n");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_start(sc->mtl_pixel_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper pixel address");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_size(sc->mtl_pixel_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper pixel size");
+ error = ENXIO;
+ goto error;
+ }
+ device_printf(sc->mtl_dev, "pixel frame buffer at mem %p-%p\n",
+ (void *)rman_get_start(sc->mtl_pixel_res),
+ (void *)(rman_get_start(sc->mtl_pixel_res) +
+ rman_get_size(sc->mtl_pixel_res)));
+
+ sc->mtl_text_rid = 2;
+ sc->mtl_text_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->mtl_text_rid, RF_ACTIVE);
+ if (sc->mtl_text_res == NULL) {
+ device_printf(dev, "couldn't map text memory\n");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_start(sc->mtl_text_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper text address");
+ error = ENXIO;
+ goto error;
+ }
+ if (rman_get_size(sc->mtl_text_res) % PAGE_SIZE != 0) {
+ device_printf(dev, "improper text size");
+ error = ENXIO;
+ goto error;
+ }
+ device_printf(sc->mtl_dev, "text frame buffer at mem %p-%p\n",
+ (void *)rman_get_start(sc->mtl_text_res),
+ (void *)(rman_get_start(sc->mtl_text_res) +
+ rman_get_size(sc->mtl_text_res)));
+
+ error = terasic_mtl_attach(sc);
+ if (error == 0)
+ return (0);
+error:
+ if (sc->mtl_text_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_text_rid,
+ sc->mtl_text_res);
+ if (sc->mtl_pixel_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_pixel_rid,
+ sc->mtl_pixel_res);
+ if (sc->mtl_reg_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_reg_rid,
+ sc->mtl_reg_res);
+ return (error);
+}
+
+static int
+terasic_mtl_fdt_detach(device_t dev)
+{
+ struct terasic_mtl_softc *sc;
+
+ sc = device_get_softc(dev);
+ terasic_mtl_detach(sc);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_text_rid,
+ sc->mtl_text_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_pixel_rid,
+ sc->mtl_pixel_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_reg_rid,
+ sc->mtl_reg_res);
+ return (0);
+}
+
+static device_method_t terasic_mtl_fdt_methods[] = {
+ DEVMETHOD(device_probe, terasic_mtl_fdt_probe),
+ DEVMETHOD(device_attach, terasic_mtl_fdt_attach),
+ DEVMETHOD(device_detach, terasic_mtl_fdt_detach),
+ { 0, 0 }
+};
+
+static driver_t terasic_mtl_fdt_driver = {
+ "terasic_mtl",
+ terasic_mtl_fdt_methods,
+ sizeof(struct terasic_mtl_softc),
+};
+
+DRIVER_MODULE(mtl, simplebus, terasic_mtl_fdt_driver, terasic_mtl_devclass, 0,
+ 0);
diff --git a/sys/dev/terasic/mtl/terasic_mtl_nexus.c b/sys/dev/terasic/mtl/terasic_mtl_nexus.c
index 4a6f2ba..2dff7db 100644
--- a/sys/dev/terasic/mtl/terasic_mtl_nexus.c
+++ b/sys/dev/terasic/mtl/terasic_mtl_nexus.c
@@ -190,7 +190,5 @@ static driver_t terasic_mtl_nexus_driver = {
sizeof(struct terasic_mtl_softc),
};
-static devclass_t terasic_mtl_devclass;
-
DRIVER_MODULE(mtl, nexus, terasic_mtl_nexus_driver, terasic_mtl_devclass, 0,
0);
diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h
index 01752d0..322e9a8 100644
--- a/sys/dev/uart/uart_bus.h
+++ b/sys/dev/uart/uart_bus.h
@@ -138,6 +138,7 @@ extern char uart_driver_name[];
int uart_bus_attach(device_t dev);
int uart_bus_detach(device_t dev);
+int uart_bus_resume(device_t dev);
serdev_intr_t *uart_bus_ihand(device_t dev, int ipend);
int uart_bus_ipend(device_t dev);
int uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan);
diff --git a/sys/dev/uart/uart_bus_acpi.c b/sys/dev/uart/uart_bus_acpi.c
index 756f7f2..ccd213d 100644
--- a/sys/dev/uart/uart_bus_acpi.c
+++ b/sys/dev/uart/uart_bus_acpi.c
@@ -47,6 +47,7 @@ static device_method_t uart_acpi_methods[] = {
DEVMETHOD(device_probe, uart_acpi_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
+ DEVMETHOD(device_resume, uart_bus_resume),
{ 0, 0 }
};
diff --git a/sys/dev/uart/uart_bus_isa.c b/sys/dev/uart/uart_bus_isa.c
index 1836663..1fda15f 100644
--- a/sys/dev/uart/uart_bus_isa.c
+++ b/sys/dev/uart/uart_bus_isa.c
@@ -50,6 +50,7 @@ static device_method_t uart_isa_methods[] = {
DEVMETHOD(device_probe, uart_isa_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
+ DEVMETHOD(device_resume, uart_bus_resume),
{ 0, 0 }
};
diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c
index 307ee340..4237fa4 100644
--- a/sys/dev/uart/uart_bus_pci.c
+++ b/sys/dev/uart/uart_bus_pci.c
@@ -51,6 +51,7 @@ static device_method_t uart_pci_methods[] = {
DEVMETHOD(device_probe, uart_pci_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
+ DEVMETHOD(device_resume, uart_bus_resume),
{ 0, 0 }
};
diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c
index 47d5f3d..f5a9a1c 100644
--- a/sys/dev/uart/uart_core.c
+++ b/sys/dev/uart/uart_core.c
@@ -590,3 +590,12 @@ uart_bus_detach(device_t dev)
return (0);
}
+
+int
+uart_bus_resume(device_t dev)
+{
+ struct uart_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (UART_ATTACH(sc));
+}
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 5d56a68..eb36da1 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
@@ -845,6 +847,11 @@ ns8250_bus_setsig(struct uart_softc *sc, int sig)
return (0);
}
+static int broken_txfifo = 0;
+SYSCTL_INT(_hw, OID_AUTO, broken_txfifo, CTLFLAG_RW | CTLFLAG_TUN,
+ &broken_txfifo, 0, "UART FIFO has QEMU emulation bug");
+TUNABLE_INT("hw.broken_txfifo", &broken_txfifo);
+
static int
ns8250_bus_transmit(struct uart_softc *sc)
{
@@ -862,7 +869,12 @@ ns8250_bus_transmit(struct uart_softc *sc)
uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
uart_barrier(bas);
}
- sc->sc_txbusy = 1;
+ if (broken_txfifo)
+ ns8250_drain(bas, UART_DRAIN_TRANSMITTER);
+ else
+ sc->sc_txbusy = 1;
uart_unlock(sc->sc_hwmtx);
+ if (broken_txfifo)
+ uart_sched_softih(sc, SER_INT_TXIDLE);
return (0);
}
diff --git a/sys/dev/usb/controller/at91dci.c b/sys/dev/usb/controller/at91dci.c
index 55688d9..6ebd37c 100644
--- a/sys/dev/usb/controller/at91dci.c
+++ b/sys/dev/usb/controller/at91dci.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved.
*
@@ -44,6 +42,9 @@ __FBSDID("$FreeBSD$");
* endpoints, Function-address and more.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -79,6 +80,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/at91dci.h>
#define AT9100_DCI_BUS2SC(bus) \
@@ -1737,18 +1740,12 @@ static const struct usb_hub_descriptor_min at91dci_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'A', 0, 'T', 0, 'M', 0, 'E', 0, 'L', 0
+ "A\0T\0M\0E\0L"
#define STRING_PRODUCT \
- 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "D\0C\0I\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, at91dci_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, at91dci_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, at91dci_product);
@@ -1950,8 +1947,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(at91dci_langtab);
- ptr = (const void *)&at91dci_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/atmegadci.c b/sys/dev/usb/controller/atmegadci.c
index 132fd48..0dc726c 100644
--- a/sys/dev/usb/controller/atmegadci.c
+++ b/sys/dev/usb/controller/atmegadci.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
*
@@ -36,6 +34,9 @@ __FBSDID("$FreeBSD$");
* endpoints, Function-address and more.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -71,6 +72,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/atmegadci.h>
#define ATMEGA_BUS2SC(bus) \
@@ -1562,18 +1565,12 @@ static const struct usb_hub_descriptor_min atmegadci_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'A', 0, 'T', 0, 'M', 0, 'E', 0, 'G', 0, 'A', 0
+ "A\0T\0M\0E\0G\0A"
#define STRING_PRODUCT \
- 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "D\0C\0I\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, atmegadci_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, atmegadci_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, atmegadci_product);
@@ -1776,8 +1773,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(atmegadci_langtab);
- ptr = (const void *)&atmegadci_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/avr32dci.c b/sys/dev/usb/controller/avr32dci.c
index 14b4f64..1d2ce87 100644
--- a/sys/dev/usb/controller/avr32dci.c
+++ b/sys/dev/usb/controller/avr32dci.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
*
@@ -35,7 +33,9 @@ __FBSDID("$FreeBSD$");
* NOTE: When the chip detects BUS-reset it will also reset the
* endpoints, Function-address and more.
*/
-
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -71,6 +71,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/avr32dci.h>
#define AVR32_BUS2SC(bus) \
@@ -1503,18 +1505,12 @@ static const struct usb_hub_descriptor_min avr32dci_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'A', 0, 'V', 0, 'R', 0, '3', 0, '2', 0
+ "A\0V\0R\0003\0002"
#define STRING_PRODUCT \
- 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "D\0C\0I\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, avr32dci_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, avr32dci_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, avr32dci_product);
@@ -1717,8 +1713,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(avr32dci_langtab);
- ptr = (const void *)&avr32dci_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c
index 89e312a..d08b3d9 100644
--- a/sys/dev/usb/controller/dwc_otg.c
+++ b/sys/dev/usb/controller/dwc_otg.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2012 Hans Petter Selasky. All rights reserved.
* Copyright (c) 2010-2011 Aleksandr Rybalko. All rights reserved.
@@ -41,9 +42,9 @@
* internal reset.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -79,6 +80,7 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#include <dev/usb/controller/dwc_otg.h>
#include <dev/usb/controller/dwc_otgreg.h>
@@ -3489,18 +3491,12 @@ static const struct usb_hub_descriptor_min dwc_otg_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'D', 0, 'W', 0, 'C', 0, 'O', 0, 'T', 0, 'G', 0
+ "D\0W\0C\0O\0T\0G"
#define STRING_PRODUCT \
- 'O', 0, 'T', 0, 'G', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "O\0T\0G\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, dwc_otg_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, dwc_otg_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, dwc_otg_product);
@@ -3702,8 +3698,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(dwc_otg_langtab);
- ptr = (const void *)&dwc_otg_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/ehci.c b/sys/dev/usb/controller/ehci.c
index b301ea4..51b012b 100644
--- a/sys/dev/usb/controller/ehci.c
+++ b/sys/dev/usb/controller/ehci.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
* Copyright (c) 2004 The NetBSD Foundation, Inc. All rights reserved.
@@ -43,9 +44,9 @@
* 1) command failures are not recovered correctly
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -81,6 +82,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/ehci.h>
#include <dev/usb/controller/ehcireg.h>
diff --git a/sys/dev/usb/controller/musb_otg.c b/sys/dev/usb/controller/musb_otg.c
index 627b40b..10dc90b 100644
--- a/sys/dev/usb/controller/musb_otg.c
+++ b/sys/dev/usb/controller/musb_otg.c
@@ -36,6 +36,9 @@
* NOTE: The current implementation only supports Device Side Mode!
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -71,6 +74,8 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/musb_otg.h>
#define MUSBOTG_INTR_ENDPT 1
@@ -2206,19 +2211,12 @@ static const struct usb_hub_descriptor_min musbotg_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'M', 0, 'e', 0, 'n', 0, 't', 0, 'o', 0, 'r', 0, ' ', 0, \
- 'G', 0, 'r', 0, 'a', 0, 'p', 0, 'h', 0, 'i', 0, 'c', 0, 's', 0
+ "M\0e\0n\0t\0o\0r\0 \0G\0r\0a\0p\0h\0i\0c\0s"
#define STRING_PRODUCT \
- 'O', 0, 'T', 0, 'G', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "O\0T\0G\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, musbotg_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, musbotg_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, musbotg_product);
@@ -2420,8 +2418,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(musbotg_langtab);
- ptr = (const void *)&musbotg_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/ohci.c b/sys/dev/usb/controller/ohci.c
index d499506..e78c9e9 100644
--- a/sys/dev/usb/controller/ohci.c
+++ b/sys/dev/usb/controller/ohci.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -25,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/*
* USB Open Host Controller driver.
*
@@ -35,6 +33,9 @@ __FBSDID("$FreeBSD$");
* USB spec: http://www.usb.org/developers/docs/usbspec.zip
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -70,6 +71,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/ohci.h>
#include <dev/usb/controller/ohcireg.h>
diff --git a/sys/dev/usb/controller/uhci.c b/sys/dev/usb/controller/uhci.c
index 78399cc..fe3cf93 100644
--- a/sys/dev/usb/controller/uhci.c
+++ b/sys/dev/usb/controller/uhci.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -25,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/*
* USB Universal Host Controller driver.
* Handles e.g. PIIX3 and PIIX4.
@@ -38,6 +36,9 @@ __FBSDID("$FreeBSD$");
* ftp://download.intel.com/design/intarch/datashts/29056201.pdf
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -73,6 +74,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/uhci.h>
#include <dev/usb/controller/uhcireg.h>
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index 5f28640..204569f 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include "opt_ddb.h"
#include <sys/stdint.h>
@@ -62,6 +65,7 @@
#include <dev/usb/usb_bus.h>
#include <dev/usb/usb_pf.h>
#include "usb_if.h"
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/* function prototypes */
@@ -84,10 +88,12 @@ SYSCTL_INT(_hw_usb_ctrl, OID_AUTO, debug, CTLFLAG_RW, &usb_ctrl_debug, 0,
"Debug level");
#endif
+#if USB_HAVE_ROOT_MOUNT_HOLD
static int usb_no_boot_wait = 0;
TUNABLE_INT("hw.usb.no_boot_wait", &usb_no_boot_wait);
SYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RD|CTLFLAG_TUN, &usb_no_boot_wait, 0,
"No USB device enumerate waiting at boot.");
+#endif
static int usb_no_suspend_wait = 0;
TUNABLE_INT("hw.usb.no_suspend_wait", &usb_no_suspend_wait);
@@ -108,7 +114,8 @@ static device_method_t usb_methods[] = {
DEVMETHOD(device_suspend, usb_suspend),
DEVMETHOD(device_resume, usb_resume),
DEVMETHOD(device_shutdown, usb_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t usb_driver = {
@@ -144,6 +151,7 @@ usb_probe(device_t dev)
return (0);
}
+#if USB_HAVE_ROOT_MOUNT_HOLD
static void
usb_root_mount_rel(struct usb_bus *bus)
{
@@ -153,6 +161,7 @@ usb_root_mount_rel(struct usb_bus *bus)
bus->bus_roothold = NULL;
}
}
+#endif
/*------------------------------------------------------------------------*
* usb_attach
@@ -169,11 +178,12 @@ usb_attach(device_t dev)
return (ENXIO);
}
+#if USB_HAVE_ROOT_MOUNT_HOLD
if (usb_no_boot_wait == 0) {
/* delay vfs_mountroot until the bus is explored */
bus->bus_roothold = root_mount_hold(device_get_nameunit(dev));
}
-
+#endif
usb_attach_sub(dev, bus);
return (0); /* return success */
@@ -196,8 +206,10 @@ usb_detach(device_t dev)
/* Stop power watchdog */
usb_callout_drain(&bus->power_wdog);
+#if USB_HAVE_ROOT_MOUNT_HOLD
/* Let the USB explore process detach all devices. */
usb_root_mount_rel(bus);
+#endif
USB_BUS_LOCK(bus);
@@ -363,7 +375,9 @@ usb_bus_explore(struct usb_proc_msg *pm)
(udev->hub->explore) (udev);
USB_BUS_LOCK(bus);
}
+#if USB_HAVE_ROOT_MOUNT_HOLD
usb_root_mount_rel(bus);
+#endif
}
/*------------------------------------------------------------------------*
@@ -630,7 +644,9 @@ usb_bus_attach(struct usb_proc_msg *pm)
default:
device_printf(bus->bdev, "Unsupported USB revision\n");
+#if USB_HAVE_ROOT_MOUNT_HOLD
usb_root_mount_rel(bus);
+#endif
return;
}
@@ -672,7 +688,9 @@ usb_bus_attach(struct usb_proc_msg *pm)
if (err) {
device_printf(bus->bdev, "Root HUB problem, error=%s\n",
usbd_errstr(err));
+#if USB_HAVE_ROOT_MOUNT_HOLD
usb_root_mount_rel(bus);
+#endif
}
/* set softc - we are ready */
diff --git a/sys/dev/usb/controller/uss820dci.c b/sys/dev/usb/controller/uss820dci.c
index bbb9f75..6750f32 100644
--- a/sys/dev/usb/controller/uss820dci.c
+++ b/sys/dev/usb/controller/uss820dci.c
@@ -32,6 +32,9 @@
* NOTE: The datasheet does not document everything.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -67,6 +70,8 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/uss820dci.h>
#define USS820_DCI_BUS2SC(bus) \
@@ -1803,18 +1808,12 @@ static const struct usb_hub_descriptor_min uss820dci_hubd = {
.DeviceRemovable = {0}, /* port is removable */
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_VENDOR \
- 'A', 0, 'G', 0, 'E', 0, 'R', 0, 'E', 0
+ "A\0G\0E\0R\0E"
#define STRING_PRODUCT \
- 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \
- 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \
- 'U', 0, 'B', 0,
+ "D\0C\0I\0 \0R\0o\0o\0t\0 \0H\0U\0B"
-USB_MAKE_STRING_DESC(STRING_LANG, uss820dci_langtab);
USB_MAKE_STRING_DESC(STRING_VENDOR, uss820dci_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, uss820dci_product);
@@ -2016,8 +2015,8 @@ tr_handle_get_descriptor:
case UDESC_STRING:
switch (value & 0xff) {
case 0: /* Language table */
- len = sizeof(uss820dci_langtab);
- ptr = (const void *)&uss820dci_langtab;
+ len = sizeof(usb_string_lang_en);
+ ptr = (const void *)&usb_string_lang_en;
goto tr_valid;
case 1: /* Vendor */
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index c62f781..4023ecc 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
*
@@ -38,9 +39,9 @@
* way we avoid too much diveration among USB drivers.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -76,6 +77,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
#include <dev/usb/controller/xhci.h>
#include <dev/usb/controller/xhcireg.h>
@@ -886,6 +889,12 @@ xhci_check_transfer(struct xhci_softc *sc, struct xhci_trb *trb)
* a short packet also makes the transfer done
*/
if (td->remainder > 0) {
+ if (td->alt_next == NULL) {
+ DPRINTF(
+ "short TD has no alternate next\n");
+ xhci_generic_done(xfer);
+ break;
+ }
DPRINTF("TD has short pkt\n");
if (xfer->flags_int.short_frames_ok ||
xfer->flags_int.isochronous_xfr ||
diff --git a/sys/dev/usb/input/uhid.c b/sys/dev/usb/input/uhid.c
index 333d437..48d9c4f 100644
--- a/sys/dev/usb/input/uhid.c
+++ b/sys/dev/usb/input/uhid.c
@@ -852,7 +852,8 @@ static device_method_t uhid_methods[] = {
DEVMETHOD(device_probe, uhid_probe),
DEVMETHOD(device_attach, uhid_attach),
DEVMETHOD(device_detach, uhid_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t uhid_driver = {
diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
index 45ac8fc..0c56ce0 100644
--- a/sys/dev/usb/input/ukbd.c
+++ b/sys/dev/usb/input/ukbd.c
@@ -995,13 +995,12 @@ ukbd_probe(device_t dev)
if (uaa->info.bInterfaceClass != UICLASS_HID)
return (ENXIO);
+ if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
+ return (ENXIO);
+
if ((uaa->info.bInterfaceSubClass == UISUBCLASS_BOOT) &&
- (uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD)) {
- if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
- return (ENXIO);
- else
- return (BUS_PROBE_DEFAULT);
- }
+ (uaa->info.bInterfaceProtocol == UIPROTO_BOOT_KEYBOARD))
+ return (BUS_PROBE_DEFAULT);
error = usbd_req_get_hid_desc(uaa->device, NULL,
&d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex);
@@ -1009,23 +1008,20 @@ ukbd_probe(device_t dev)
if (error)
return (ENXIO);
- /*
- * NOTE: we currently don't support USB mouse and USB keyboard
- * on the same USB endpoint.
- */
- if (hid_is_collection(d_ptr, d_len,
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) {
- /* most likely a mouse */
- error = ENXIO;
- } else if (hid_is_collection(d_ptr, d_len,
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) {
- if (usb_test_quirk(uaa, UQ_KBD_IGNORE))
+ if (hid_is_keyboard(d_ptr, d_len)) {
+ if (hid_is_mouse(d_ptr, d_len)) {
+ /*
+ * NOTE: We currently don't support USB mouse
+ * and USB keyboard on the same USB endpoint.
+ * Let "ums" driver win.
+ */
error = ENXIO;
- else
+ } else {
error = BUS_PROBE_DEFAULT;
- } else
+ }
+ } else {
error = ENXIO;
-
+ }
free(d_ptr, M_TEMP);
return (error);
}
@@ -2124,7 +2120,8 @@ static device_method_t ukbd_methods[] = {
DEVMETHOD(device_attach, ukbd_attach),
DEVMETHOD(device_detach, ukbd_detach),
DEVMETHOD(device_resume, ukbd_resume),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ukbd_driver = {
diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c
index c20c986..cc52b99 100644
--- a/sys/dev/usb/input/ums.c
+++ b/sys/dev/usb/input/ums.c
@@ -368,9 +368,7 @@ ums_probe(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
void *d_ptr;
- struct hid_data *hd;
- struct hid_item hi;
- int error, mdepth, found;
+ int error;
uint16_t d_len;
DPRINTFN(11, "\n");
@@ -394,44 +392,13 @@ ums_probe(device_t dev)
if (error)
return (ENXIO);
- hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
- if (hd == NULL)
- return (0);
- mdepth = 0;
- found = 0;
- while (hid_get_item(hd, &hi)) {
- switch (hi.kind) {
- case hid_collection:
- if (mdepth != 0)
- mdepth++;
- else if (hi.collection == 1 &&
- hi.usage ==
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
- mdepth++;
- break;
- case hid_endcollection:
- if (mdepth != 0)
- mdepth--;
- break;
- case hid_input:
- if (mdepth == 0)
- break;
- if (hi.usage ==
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
- (hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS)
- found++;
- if (hi.usage ==
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
- (hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS)
- found++;
- break;
- default:
- break;
- }
- }
- hid_end_parse(hd);
+ if (hid_is_mouse(d_ptr, d_len))
+ error = BUS_PROBE_DEFAULT;
+ else
+ error = ENXIO;
+
free(d_ptr, M_TEMP);
- return (found ? BUS_PROBE_DEFAULT : ENXIO);
+ return (error);
}
static void
@@ -1072,7 +1039,8 @@ static device_method_t ums_methods[] = {
DEVMETHOD(device_probe, ums_probe),
DEVMETHOD(device_attach, ums_attach),
DEVMETHOD(device_detach, ums_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ums_driver = {
diff --git a/sys/dev/usb/misc/udbp.c b/sys/dev/usb/misc/udbp.c
index 56f86ae..8b949ef 100644
--- a/sys/dev/usb/misc/udbp.c
+++ b/sys/dev/usb/misc/udbp.c
@@ -248,7 +248,8 @@ static device_method_t udbp_methods[] = {
DEVMETHOD(device_probe, udbp_probe),
DEVMETHOD(device_attach, udbp_attach),
DEVMETHOD(device_detach, udbp_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t udbp_driver = {
diff --git a/sys/dev/usb/misc/ufm.c b/sys/dev/usb/misc/ufm.c
index 032b635..0612dd2 100644
--- a/sys/dev/usb/misc/ufm.c
+++ b/sys/dev/usb/misc/ufm.c
@@ -105,7 +105,8 @@ static device_method_t ufm_methods[] = {
DEVMETHOD(device_probe, ufm_probe),
DEVMETHOD(device_attach, ufm_attach),
DEVMETHOD(device_detach, ufm_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t ufm_driver = {
diff --git a/sys/dev/usb/net/if_axe.c b/sys/dev/usb/net/if_axe.c
index 694e5a5..f0d1044 100644
--- a/sys/dev/usb/net/if_axe.c
+++ b/sys/dev/usb/net/if_axe.c
@@ -159,6 +159,7 @@ static const STRUCT_USB_HOST_ID axe_devs[] = {
AXE_DEV(COREGA, FETHER_USB2_TX, 0),
AXE_DEV(DLINK, DUBE100, 0),
AXE_DEV(DLINK, DUBE100B1, AXE_FLAG_772),
+ AXE_DEV(DLINK, DUBE100C1, AXE_FLAG_772B),
AXE_DEV(GOODWAY, GWUSB2E, 0),
AXE_DEV(IODATA, ETGUS2, AXE_FLAG_178),
AXE_DEV(JVC, MP_PRX1, 0),
diff --git a/sys/dev/usb/net/if_cdce.c b/sys/dev/usb/net/if_cdce.c
index 6e0ce97..6649bc0 100644
--- a/sys/dev/usb/net/if_cdce.c
+++ b/sys/dev/usb/net/if_cdce.c
@@ -237,7 +237,7 @@ static device_method_t cdce_methods[] = {
DEVMETHOD(device_suspend, cdce_suspend),
DEVMETHOD(device_resume, cdce_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t cdce_driver = {
@@ -500,6 +500,7 @@ cdce_attach(device_t dev)
const struct usb_interface_descriptor *id;
const struct usb_cdc_ethernet_descriptor *ued;
const struct usb_config *pcfg;
+ uint32_t seed;
int error;
uint8_t i;
uint8_t data_iface_no;
@@ -612,8 +613,9 @@ alloc_transfers:
/* fake MAC address */
device_printf(dev, "faking MAC address\n");
+ seed = ticks;
sc->sc_ue.ue_eaddr[0] = 0x2a;
- memcpy(&sc->sc_ue.ue_eaddr[1], &ticks, sizeof(uint32_t));
+ memcpy(&sc->sc_ue.ue_eaddr[1], &seed, sizeof(uint32_t));
sc->sc_ue.ue_eaddr[5] = device_get_unit(dev);
} else {
diff --git a/sys/dev/usb/net/if_cue.c b/sys/dev/usb/net/if_cue.c
index 30c5247a..6414e7a 100644
--- a/sys/dev/usb/net/if_cue.c
+++ b/sys/dev/usb/net/if_cue.c
@@ -157,7 +157,7 @@ static device_method_t cue_methods[] = {
DEVMETHOD(device_attach, cue_attach),
DEVMETHOD(device_detach, cue_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t cue_driver = {
diff --git a/sys/dev/usb/net/if_ipheth.c b/sys/dev/usb/net/if_ipheth.c
index 28f941c..3eb2582 100644
--- a/sys/dev/usb/net/if_ipheth.c
+++ b/sys/dev/usb/net/if_ipheth.c
@@ -116,7 +116,7 @@ static device_method_t ipheth_methods[] = {
DEVMETHOD(device_attach, ipheth_attach),
DEVMETHOD(device_detach, ipheth_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ipheth_driver = {
diff --git a/sys/dev/usb/net/if_kue.c b/sys/dev/usb/net/if_kue.c
index 791c73a..ec0c5f0 100644
--- a/sys/dev/usb/net/if_kue.c
+++ b/sys/dev/usb/net/if_kue.c
@@ -199,7 +199,7 @@ static device_method_t kue_methods[] = {
DEVMETHOD(device_attach, kue_attach),
DEVMETHOD(device_detach, kue_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t kue_driver = {
diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c
index 5ce45bc..5c3db72 100644
--- a/sys/dev/usb/net/if_smsc.c
+++ b/sys/dev/usb/net/if_smsc.c
@@ -1009,6 +1009,10 @@ smsc_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
/* Check if RX TCP/UDP checksumming is being offloaded */
if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
+
+ struct ether_header *eh;
+
+ eh = mtod(m, struct ether_header *);
/* Remove the extra 2 bytes of the csum */
pktlen -= 2;
@@ -1020,8 +1024,10 @@ smsc_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
* the padding bytes as well. Therefore to be safe we
* ignore the H/W csum on frames less than or equal to
* 64 bytes.
+ *
+ * Ignore H/W csum for non-IPv4 packets.
*/
- if (pktlen > ETHER_MIN_LEN) {
+ if (be16toh(eh->ether_type) == ETHERTYPE_IP && pktlen > ETHER_MIN_LEN) {
/* Indicate the UDP/TCP csum has been calculated */
m->m_pkthdr.csum_flags |= CSUM_DATA_VALID;
@@ -1810,7 +1816,7 @@ static device_method_t smsc_methods[] = {
DEVMETHOD(miibus_writereg, smsc_miibus_writereg),
DEVMETHOD(miibus_statchg, smsc_miibus_statchg),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t smsc_driver = {
diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c
index b8f07aa..52f511d 100644
--- a/sys/dev/usb/quirk/usb_quirk.c
+++ b/sys/dev/usb/quirk/usb_quirk.c
@@ -111,6 +111,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(ITUNERNET, USBLCD2X20, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(ITUNERNET, USBLCD4X20, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(LIEBERT, POWERSURE_PXT, 0x0000, 0xffff, UQ_HID_IGNORE),
+ USB_QUIRK(LIEBERT2, PSI1000, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(MGE, UPS1, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(MGE, UPS2, 0x0000, 0xffff, UQ_HID_IGNORE),
USB_QUIRK(APPLE, IPHONE, 0x0000, 0xffff, UQ_HID_IGNORE),
@@ -302,7 +303,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
USB_QUIRK(ONSPEC, READER, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(ONSPEC, UCF100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
- UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY | UQ_MSC_NO_GETMAXLUN),
+ UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(ONSPEC2, IMAGEMATE_SDDR55, 0x0000, 0xffff,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(PANASONIC, KXL840AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -338,6 +339,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
USB_QUIRK(SANDISK, SDDR31, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1),
+ USB_QUIRK(SANDISK, IMAGEMATE_SDDR289, 0x0000, 0xffff,
+ UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(SCANLOGIC, SL11R, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
USB_QUIRK(SHUTTLE, EUSB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
@@ -799,7 +802,7 @@ usb_quirk_ioctl(unsigned long cmd, caddr_t data,
}
if (x == USB_SUB_QUIRKS_MAX) {
/* all quirk entries are unused - release */
- memset(pqe, 0, sizeof(pqe));
+ memset(pqe, 0, sizeof(*pqe));
}
mtx_unlock(&usb_quirk_mtx);
return (0); /* success */
diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c
index dc670d66..f2c3a45 100644
--- a/sys/dev/usb/serial/u3g.c
+++ b/sys/dev/usb/serial/u3g.c
@@ -356,6 +356,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = {
U3G_DEV(NOVATEL, V740, 0),
U3G_DEV(NOVATEL, X950D, 0),
U3G_DEV(NOVATEL, XU870, 0),
+ U3G_DEV(MOTOROLA2, MB886, U3GINIT_SCSIEJECT),
U3G_DEV(OPTION, E6500, 0),
U3G_DEV(OPTION, E6501, 0),
U3G_DEV(OPTION, E6601, 0),
diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c
index 48ae389..e2ff0ef 100644
--- a/sys/dev/usb/storage/umass.c
+++ b/sys/dev/usb/storage/umass.c
@@ -698,7 +698,8 @@ static device_method_t umass_methods[] = {
DEVMETHOD(device_probe, umass_probe),
DEVMETHOD(device_attach, umass_attach),
DEVMETHOD(device_detach, umass_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t umass_driver = {
@@ -2251,8 +2252,11 @@ umass_cam_action(struct cam_sim *sim, union ccb *ccb)
/*ascq*/ 0x00,
/*extra args*/ SSD_ELEM_NONE);
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
- CAM_AUTOSNS_VALID;
+ ccb->ccb_h.status =
+ CAM_SCSI_STATUS_ERROR |
+ CAM_AUTOSNS_VALID |
+ CAM_DEV_QFRZN;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
xpt_done(ccb);
goto done;
}
@@ -2512,7 +2516,8 @@ umass_cam_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
* recovered. We return an error to CAM and let CAM
* retry the command if necessary.
*/
- ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
xpt_done(ccb);
break;
}
@@ -2575,8 +2580,9 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
* usual.
*/
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
+ | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN;
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
#if 0
@@ -2587,18 +2593,23 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
/* the rest of the command was filled in at attach */
- if (umass_std_transform(sc, ccb,
+ if ((sc->sc_transform)(sc,
&sc->cam_scsi_test_unit_ready.opcode,
- sizeof(sc->cam_scsi_test_unit_ready))) {
+ sizeof(sc->cam_scsi_test_unit_ready)) == 1) {
umass_command_start(sc, DIR_NONE, NULL, 0,
ccb->ccb_h.timeout,
&umass_cam_quirk_cb, ccb);
+ break;
}
- break;
} else {
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
- ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ if (key >= 0) {
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
+ | CAM_AUTOSNS_VALID | CAM_DEV_QFRZN;
+ ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+ } else
+ ccb->ccb_h.status = CAM_AUTOSENSE_FAIL
+ | CAM_DEV_QFRZN;
}
xpt_done(ccb);
break;
@@ -2606,15 +2617,16 @@ umass_cam_sense_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
default:
DPRINTF(sc, UDMASS_SCSI, "Autosense failed, "
"status %d\n", status);
- ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_AUTOSENSE_FAIL | CAM_DEV_QFRZN;
xpt_done(ccb);
}
}
/*
* This completion code just handles the fact that we sent a test-unit-ready
- * after having previously failed a READ CAPACITY with CHECK_COND. Even
- * though this command succeeded, we have to tell CAM to retry.
+ * after having previously failed a READ CAPACITY with CHECK_COND. The CCB
+ * status for CAM is already set earlier.
*/
static void
umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
@@ -2623,9 +2635,6 @@ umass_cam_quirk_cb(struct umass_softc *sc, union ccb *ccb, uint32_t residue,
DPRINTF(sc, UDMASS_SCSI, "Test unit ready "
"returned status %d\n", status);
- ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR
- | CAM_AUTOSNS_VALID;
- ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
xpt_done(ccb);
}
@@ -2914,7 +2923,8 @@ umass_std_transform(struct umass_softc *sc, union ccb *ccb,
xpt_done(ccb);
return (0);
} else if (retval == 0) {
- ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ccb->ccb_h.status = CAM_REQ_INVALID | CAM_DEV_QFRZN;
xpt_done(ccb);
return (0);
}
diff --git a/sys/dev/usb/storage/urio.c b/sys/dev/usb/storage/urio.c
index 39fcbe9..6cbb596 100644
--- a/sys/dev/usb/storage/urio.c
+++ b/sys/dev/usb/storage/urio.c
@@ -185,7 +185,8 @@ static device_method_t urio_methods[] = {
DEVMETHOD(device_probe, urio_probe),
DEVMETHOD(device_attach, urio_attach),
DEVMETHOD(device_detach, urio_detach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t urio_driver = {
diff --git a/sys/dev/usb/storage/ustorage_fs.c b/sys/dev/usb/storage/ustorage_fs.c
index df89619..15a5ba9 100644
--- a/sys/dev/usb/storage/ustorage_fs.c
+++ b/sys/dev/usb/storage/ustorage_fs.c
@@ -36,6 +36,9 @@
* Linux USB gadget stack.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -62,6 +65,7 @@
#define USB_DEBUG_VAR ustorage_fs_debug
#include <dev/usb/usb_debug.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#ifdef USB_DEBUG
static int ustorage_fs_debug = 0;
@@ -252,7 +256,7 @@ static device_method_t ustorage_fs_methods[] = {
DEVMETHOD(device_suspend, ustorage_fs_suspend),
DEVMETHOD(device_resume, ustorage_fs_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ustorage_fs_driver = {
diff --git a/sys/dev/usb/template/usb_template.c b/sys/dev/usb/template/usb_template.c
index 9934202..36c11d9 100644
--- a/sys/dev/usb/template/usb_template.c
+++ b/sys/dev/usb/template/usb_template.c
@@ -29,6 +29,9 @@
* USB templates.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -67,6 +70,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
MODULE_DEPEND(usb_template, usb, 1, 1, 1);
MODULE_VERSION(usb_template, 1);
diff --git a/sys/dev/usb/template/usb_template_audio.c b/sys/dev/usb/template/usb_template_audio.c
index 8e9e7f0..7c7cebe 100644
--- a/sys/dev/usb/template/usb_template_audio.c
+++ b/sys/dev/usb/template/usb_template_audio.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
*
@@ -30,6 +28,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB template for an USB Audio Device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -51,9 +52,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
INDEX_AUDIO_LANG,
@@ -64,30 +67,21 @@ enum {
INDEX_AUDIO_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_AUDIO_PRODUCT \
- 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0, ' ', 0, \
- 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \
- 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0,
+ "A\0u\0d\0i\0o\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e"
#define STRING_AUDIO_MIXER \
- 'M', 0, 'i', 0, 'x', 0, 'e', 0, 'r', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "M\0i\0x\0e\0r\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_AUDIO_RECORD \
- 'R', 0, 'e', 0, 'c', 0, 'o', 0, 'r', 0, 'd', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "R\0e\0c\0o\0r\0d\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_AUDIO_PLAYBACK \
- 'P', 0, 'l', 0, 'a', 0, 'y', 0, 'b', 0, 'a', 0, 'c', 0, 'k', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "P\0l\0a\0y\0b\0a\0c\0k\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_AUDIO_MIXER, string_audio_mixer);
USB_MAKE_STRING_DESC(STRING_AUDIO_RECORD, string_audio_record);
USB_MAKE_STRING_DESC(STRING_AUDIO_PLAYBACK, string_audio_playback);
@@ -385,7 +379,7 @@ static const void *
audio_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[INDEX_AUDIO_MAX] = {
- [INDEX_AUDIO_LANG] = &string_lang,
+ [INDEX_AUDIO_LANG] = &usb_string_lang_en,
[INDEX_AUDIO_MIXER] = &string_audio_mixer,
[INDEX_AUDIO_RECORD] = &string_audio_record,
[INDEX_AUDIO_PLAYBACK] = &string_audio_playback,
@@ -393,7 +387,7 @@ audio_get_string_desc(uint16_t lang_id, uint8_t string_index)
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_cdce.c b/sys/dev/usb/template/usb_template_cdce.c
index 481a69c..68f69d0 100644
--- a/sys/dev/usb/template/usb_template_cdce.c
+++ b/sys/dev/usb/template/usb_template_cdce.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2007 Hans Petter Selasky <hselasky@FreeBSD.org>
* All rights reserved.
@@ -31,6 +29,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB templates for a CDC USB ethernet device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -52,9 +53,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
STRING_LANG_INDEX,
@@ -68,61 +71,31 @@ enum {
STRING_ETH_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_MAC \
- '2', 0, 'A', 0, '2', 0, '3', 0, \
- '4', 0, '5', 0, '6', 0, '7', 0, \
- '8', 0, '9', 0, 'A', 0, 'B', 0,
+ "2\0A\0002\0003\0004\0005\0006\0007\08\09\0A\0B"
#define STRING_ETH_CONTROL \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'E', 0, 't', 0, 'h', 0, 'e', 0, \
- 'r', 0, 'n', 0, 'e', 0, 't', 0, \
- ' ', 0, 'C', 0, 'o', 0, 'm', 0, \
- 'm', 0, ' ', 0, 'i', 0, 'n', 0, \
- 't', 0, 'e', 0, 'r', 0, 'f', 0, \
- 'a', 0, 'c', 0, 'e', 0,
+ "U\0S\0B\0 \0E\0t\0h\0e\0r\0n\0e\0t\0 " \
+ "\0C\0o\0m\0m\0 \0I\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_ETH_DATA \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'E', 0, 't', 0, 'h', 0, 'e', 0, \
- 'r', 0, 'n', 0, 'e', 0, 't', 0, \
- ' ', 0, 'D', 0, 'a', 0, 't', 0, \
- 'a', 0, ' ', 0, 'i', 0, 'n', 0, \
- 't', 0, 'e', 0, 'r', 0, 'f', 0, \
- 'a', 0, 'c', 0, 'e', 0,
+ "U\0S\0B\0 \0E\0t\0h\0e\0r\0n\0e\0t\0 \0D\0a\0t\0a\0 " \
+ "\0I\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_ETH_CONFIG \
- 'D', 0, 'e', 0, 'f', 0, 'a', 0, \
- 'u', 0, 'l', 0, 't', 0, ' ', 0, \
- 'c', 0, 'o', 0, 'n', 0, 'f', 0, \
- 'i', 0, 'g', 0,
+ "D\0e\0f\0a\0u\0l\0t\0 \0c\0o\0n\0f\0i\0g"
#define STRING_ETH_VENDOR \
- 'F', 0, 'r', 0, 'e', 0, 'e', 0, \
- 'B', 0, 'S', 0, 'D', 0, ' ', 0, \
- 'f', 0, 'o', 0, 'u', 0, 'n', 0, \
- 'd', 0, 'a', 0, 't', 0, 'i', 0, \
- 'o', 0, 'n', 0,
+ "F\0r\0e\0e\0B\0S\0D\0 \0f\0o\0u\0n\0d\0a\0t\0i\0o\0n"
#define STRING_ETH_PRODUCT \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'E', 0, 't', 0, 'h', 0, 'e', 0, \
- 'r', 0, 'n', 0, 'e', 0, 't', 0, \
- ' ', 0, 'A', 0, 'd', 0, 'a', 0, \
- 'p', 0, 't', 0, 'e', 0, 'r', 0,
+ "U\0S\0B\0 \0E\0t\0h\0e\0r\0n\0e\0t\0 \0A\0d\0a\0p\0t\0e\0r"
#define STRING_ETH_SERIAL \
- 'D', 0, 'e', 0, 'c', 0, 'e', 0, \
- 'm', 0, 'b', 0, 'e', 0, 'r', 0, \
- ' ', 0, '2', 0, '0', 0, '0', 0, \
- '7', 0,
+ "D\0e\0c\0e\0m\0b\0e\0r\0 \0002\0000\0000\0007"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_MAC, string_mac);
USB_MAKE_STRING_DESC(STRING_ETH_CONTROL, string_eth_control);
USB_MAKE_STRING_DESC(STRING_ETH_DATA, string_eth_data);
@@ -286,7 +259,7 @@ static const void *
eth_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[STRING_ETH_MAX] = {
- [STRING_LANG_INDEX] = &string_lang,
+ [STRING_LANG_INDEX] = &usb_string_lang_en,
[STRING_MAC_INDEX] = &string_mac,
[STRING_ETH_CONTROL_INDEX] = &string_eth_control,
[STRING_ETH_DATA_INDEX] = &string_eth_data,
@@ -297,7 +270,7 @@ eth_get_string_desc(uint16_t lang_id, uint8_t string_index)
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_kbd.c b/sys/dev/usb/template/usb_template_kbd.c
index 6295825..306b2fe 100644
--- a/sys/dev/usb/template/usb_template_kbd.c
+++ b/sys/dev/usb/template/usb_template_kbd.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
*
@@ -30,6 +28,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB template for an USB Keyboard Device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -51,9 +52,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
INDEX_LANG,
@@ -62,21 +65,14 @@ enum {
INDEX_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_PRODUCT \
- 'K', 0, 'e', 0, 'y', 0, 'b', 0, 'o', 0, 'a', 0, 'r', 0, 'd', 0, ' ', 0, \
- 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \
- 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0,
+ "K\0e\0y\0b\0o\0a\0r\0d\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e"
#define STRING_KEYBOARD \
- 'K', 0, 'e', 0, 'y', 0, 'b', 0, 'o', 0, 'a', 0, 'r', 0, 'd', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "K\0e\0y\0b\0o\0a\0r\0d\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_KEYBOARD, string_keyboard);
USB_MAKE_STRING_DESC(STRING_PRODUCT, string_product);
@@ -206,13 +202,13 @@ static const void *
keyboard_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[INDEX_MAX] = {
- [INDEX_LANG] = &string_lang,
+ [INDEX_LANG] = &usb_string_lang_en,
[INDEX_KEYBOARD] = &string_keyboard,
[INDEX_PRODUCT] = &string_product,
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_modem.c b/sys/dev/usb/template/usb_template_modem.c
index abc6f26..6a976f7 100644
--- a/sys/dev/usb/template/usb_template_modem.c
+++ b/sys/dev/usb/template/usb_template_modem.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
*
@@ -30,6 +28,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB template for an USB Modem Device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -51,9 +52,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
INDEX_LANG,
@@ -62,21 +65,14 @@ enum {
INDEX_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_PRODUCT \
- 'M', 0, 'o', 0, 'd', 0, 'e', 0, 'm', 0, ' ', 0, \
- 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \
- 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0,
+ "M\0o\0d\0e\0m\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e"
#define STRING_MODEM \
- 'M', 0, 'o', 0, 'd', 0, 'e', 0, 'm', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "M\0o\0d\0e\0m\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_MODEM, string_modem);
USB_MAKE_STRING_DESC(STRING_PRODUCT, string_product);
@@ -234,13 +230,13 @@ static const void *
modem_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[INDEX_MAX] = {
- [INDEX_LANG] = &string_lang,
+ [INDEX_LANG] = &usb_string_lang_en,
[INDEX_MODEM] = &string_modem,
[INDEX_PRODUCT] = &string_product,
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_mouse.c b/sys/dev/usb/template/usb_template_mouse.c
index 628c9a5..a48ccf4 100644
--- a/sys/dev/usb/template/usb_template_mouse.c
+++ b/sys/dev/usb/template/usb_template_mouse.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
*
@@ -30,6 +28,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB template for an USB Mouse Device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -51,9 +52,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
INDEX_LANG,
@@ -62,21 +65,14 @@ enum {
INDEX_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_PRODUCT \
- 'M', 0, 'o', 0, 'u', 0, 's', 0, 'e', 0, ' ', 0, \
- 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \
- 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
+ "M\0o\0u\0s\0e\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e"
#define STRING_MOUSE \
- 'M', 0, 'o', 0, 'u', 0, 's', 0, 'e', 0, ' ', 0, \
- 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
+ "M\0o\0u\0s\0e\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_MOUSE, string_mouse);
USB_MAKE_STRING_DESC(STRING_PRODUCT, string_product);
@@ -204,13 +200,13 @@ static const void *
mouse_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[INDEX_MAX] = {
- [INDEX_LANG] = &string_lang,
+ [INDEX_LANG] = &usb_string_lang_en,
[INDEX_MOUSE] = &string_mouse,
[INDEX_PRODUCT] = &string_product,
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_msc.c b/sys/dev/usb/template/usb_template_msc.c
index 5c05ffe..6809e63 100644
--- a/sys/dev/usb/template/usb_template_msc.c
+++ b/sys/dev/usb/template/usb_template_msc.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2008 Hans Petter Selasky <hselasky@FreeBSD.org>
* All rights reserved.
@@ -31,6 +29,9 @@ __FBSDID("$FreeBSD$");
* This file contains the USB templates for an USB Mass Storage Device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -52,8 +53,10 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
STRING_LANG_INDEX,
@@ -65,45 +68,24 @@ enum {
STRING_MSC_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_MSC_DATA \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'M', 0, 'a', 0, 's', 0, 's', 0, \
- ' ', 0, 'S', 0, 't', 0, 'o', 0, \
- 'r', 0, 'a', 0, 'g', 0, 'e', 0, \
- ' ', 0, 'I', 0, 'n', 0, 't', 0, \
- 'e', 0, 'r', 0, 'f', 0, 'a', 0, \
- 'c', 0, 'e', 0,
+ "U\0S\0B\0 \0M\0a\0s\0s\0 \0S\0t\0o\0r\0a\0g\0e\0 " \
+ "\0I\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_MSC_CONFIG \
- 'D', 0, 'e', 0, 'f', 0, 'a', 0, \
- 'u', 0, 'l', 0, 't', 0, ' ', 0, \
- 'c', 0, 'o', 0, 'n', 0, 'f', 0, \
- 'i', 0, 'g', 0,
+ "D\0e\0f\0a\0u\0l\0t\0 \0c\0o\0n\0f\0i\0g"
#define STRING_MSC_VENDOR \
- 'F', 0, 'r', 0, 'e', 0, 'e', 0, \
- 'B', 0, 'S', 0, 'D', 0, ' ', 0, \
- 'f', 0, 'o', 0, 'u', 0, 'n', 0, \
- 'd', 0, 'a', 0, 't', 0, 'i', 0, \
- 'o', 0, 'n', 0,
+ "F\0r\0e\0e\0B\0S\0D\0 \0f\0o\0u\0n\0d\0a\0t\0i\0o\0n"
#define STRING_MSC_PRODUCT \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'M', 0, 'e', 0, 'm', 0, 'o', 0, \
- 'r', 0, 'y', 0, ' ', 0, 'S', 0, \
- 't', 0, 'i', 0, 'c', 0, 'k', 0
+ "U\0S\0B\0 \0M\0e\0m\0o\0r\0y\0 \0S\0t\0i\0c\0k"
#define STRING_MSC_SERIAL \
- 'M', 0, 'a', 0, 'r', 0, 'c', 0, \
- 'h', 0, ' ', 0, '2', 0, '0', 0, \
- '0', 0, '8', 0,
+ "M\0a\0r\0c\0h\0 \0002\0000\0000\08"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_MSC_DATA, string_msc_data);
USB_MAKE_STRING_DESC(STRING_MSC_CONFIG, string_msc_config);
USB_MAKE_STRING_DESC(STRING_MSC_VENDOR, string_msc_vendor);
@@ -195,7 +177,7 @@ static const void *
msc_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[STRING_MSC_MAX] = {
- [STRING_LANG_INDEX] = &string_lang,
+ [STRING_LANG_INDEX] = &usb_string_lang_en,
[STRING_MSC_DATA_INDEX] = &string_msc_data,
[STRING_MSC_CONFIG_INDEX] = &string_msc_config,
[STRING_MSC_VENDOR_INDEX] = &string_msc_vendor,
@@ -204,7 +186,7 @@ msc_get_string_desc(uint16_t lang_id, uint8_t string_index)
};
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/template/usb_template_mtp.c b/sys/dev/usb/template/usb_template_mtp.c
index f48fbf4..f0528a5 100644
--- a/sys/dev/usb/template/usb_template_mtp.c
+++ b/sys/dev/usb/template/usb_template_mtp.c
@@ -1,6 +1,4 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+/* $FreeBSD$ */
/*-
* Copyright (c) 2008 Hans Petter Selasky <hselasky@FreeBSD.org>
* All rights reserved.
@@ -38,6 +36,9 @@ __FBSDID("$FreeBSD$");
* operating system the VID and PID of your device.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -59,7 +60,10 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
+
#include <dev/usb/template/usb_template.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#define MTP_BREQUEST 0x08
@@ -73,41 +77,23 @@ enum {
STRING_MTP_MAX,
};
-#define STRING_LANG \
- 0x09, 0x04, /* American English */
-
#define STRING_MTP_DATA \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'M', 0, 'T', 0, 'P', 0, \
- ' ', 0, 'I', 0, 'n', 0, 't', 0, \
- 'e', 0, 'r', 0, 'f', 0, 'a', 0, \
- 'c', 0, 'e', 0,
+ "U\0S\0B\0 \0M\0T\0P\0 \0I\0n\0t\0e\0r\0f\0a\0c\0e"
#define STRING_MTP_CONFIG \
- 'D', 0, 'e', 0, 'f', 0, 'a', 0, \
- 'u', 0, 'l', 0, 't', 0, ' ', 0, \
- 'c', 0, 'o', 0, 'n', 0, 'f', 0, \
- 'i', 0, 'g', 0,
+ "D\0e\0f\0a\0u\0l\0t\0 \0c\0o\0n\0f\0i\0g"
#define STRING_MTP_VENDOR \
- 'F', 0, 'r', 0, 'e', 0, 'e', 0, \
- 'B', 0, 'S', 0, 'D', 0, ' ', 0, \
- 'f', 0, 'o', 0, 'u', 0, 'n', 0, \
- 'd', 0, 'a', 0, 't', 0, 'i', 0, \
- 'o', 0, 'n', 0,
+ "F\0r\0e\0e\0B\0S\0D\0 \0f\0o\0u\0n\0d\0a\0t\0i\0o\0n"
#define STRING_MTP_PRODUCT \
- 'U', 0, 'S', 0, 'B', 0, ' ', 0, \
- 'M', 0, 'T', 0, 'P', 0,
+ "U\0S\0B\0 \0M\0T\0P"
#define STRING_MTP_SERIAL \
- 'J', 0, 'u', 0, 'n', 0, 'e', 0, \
- ' ', 0, '2', 0, '0', 0, '0', 0, \
- '8', 0,
+ "J\0u\0n\0e\0 \0002\0000\0000\08"
/* make the real string descriptors */
-USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
USB_MAKE_STRING_DESC(STRING_MTP_DATA, string_mtp_data);
USB_MAKE_STRING_DESC(STRING_MTP_CONFIG, string_mtp_config);
USB_MAKE_STRING_DESC(STRING_MTP_VENDOR, string_mtp_vendor);
@@ -244,7 +230,7 @@ static const void *
mtp_get_string_desc(uint16_t lang_id, uint8_t string_index)
{
static const void *ptr[STRING_MTP_MAX] = {
- [STRING_LANG_INDEX] = &string_lang,
+ [STRING_LANG_INDEX] = &usb_string_lang_en,
[STRING_MTP_DATA_INDEX] = &string_mtp_data,
[STRING_MTP_CONFIG_INDEX] = &string_mtp_config,
[STRING_MTP_VENDOR_INDEX] = &string_mtp_vendor,
@@ -266,7 +252,7 @@ mtp_get_string_desc(uint16_t lang_id, uint8_t string_index)
return (dummy_desc);
}
if (string_index == 0) {
- return (&string_lang);
+ return (&usb_string_lang_en);
}
if (lang_id != 0x0409) {
return (NULL);
diff --git a/sys/dev/usb/ufm_ioctl.h b/sys/dev/usb/ufm_ioctl.h
index 921b3d4..5a23388 100644
--- a/sys/dev/usb/ufm_ioctl.h
+++ b/sys/dev/usb/ufm_ioctl.h
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 2001 M. Warner Losh
* All rights reserved.
@@ -28,7 +29,8 @@
* its contributors.
*/
-/* $FreeBSD$ */
+#ifndef _UFM_IOCTL_H_
+#define _UFM_IOCTL_H_
#include <sys/ioccom.h>
@@ -37,3 +39,5 @@
#define FM_START _IOWR('U', 202, int)
#define FM_STOP _IOWR('U', 203, int)
#define FM_GET_STAT _IOWR('U', 204, int)
+
+#endif /* _UFM_IOCTL_H_ */
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index a47c9d8..b8b52d5 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -40,22 +40,28 @@
#define _USB_STANDARD_H_
#if defined(_KERNEL)
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include "opt_usb.h"
+#endif
/* Declare parent SYSCTL USB node. */
#ifdef SYSCTL_DECL
SYSCTL_DECL(_hw_usb);
#endif
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/malloc.h>
+#endif
MALLOC_DECLARE(M_USB);
MALLOC_DECLARE(M_USBDEV);
MALLOC_DECLARE(M_USBHC);
#endif /* _KERNEL */
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <dev/usb/usb_endian.h>
#include <dev/usb/usb_freebsd.h>
+#endif
#define USB_STACK_VERSION 2000 /* 2.0 */
@@ -560,17 +566,23 @@ struct usb_string_descriptor {
typedef struct usb_string_descriptor usb_string_descriptor_t;
#define USB_MAKE_STRING_DESC(m,name) \
-struct name { \
+static const struct { \
uByte bLength; \
uByte bDescriptorType; \
uByte bData[sizeof((uint8_t []){m})]; \
-} __packed; \
-static const struct name name = { \
- .bLength = sizeof(struct name), \
+} __packed name = { \
+ .bLength = sizeof(name), \
.bDescriptorType = UDESC_STRING, \
.bData = { m }, \
}
+struct usb_string_lang {
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bData[2];
+} __packed;
+typedef struct usb_string_lang usb_string_lang_t;
+
struct usb_hub_descriptor {
uByte bDescLength;
uByte bDescriptorType;
diff --git a/sys/dev/usb/usb_busdma.c b/sys/dev/usb/usb_busdma.c
index f3c4833..1808ab4 100644
--- a/sys/dev/usb/usb_busdma.c
+++ b/sys/dev/usb/usb_busdma.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -59,6 +62,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#if USB_HAVE_BUSDMA
static void usb_dma_tag_create(struct usb_dma_tag *, usb_size_t, usb_size_t);
@@ -440,7 +444,6 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
pc->page_offset_buf = rem;
pc->page_offset_end += rem;
- nseg--;
#ifdef USB_DEBUG
if (rem != (USB_P2U(pc->buffer) & (USB_PAGE_SIZE - 1))) {
/*
@@ -451,7 +454,7 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
goto done;
}
#endif
- while (nseg > 0) {
+ while (1) {
off += USB_PAGE_SIZE;
if (off >= (segs->ds_len + rem)) {
/* page crossing */
@@ -459,6 +462,8 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
segs++;
off = 0;
rem = 0;
+ if (nseg == 0)
+ break;
}
pg++;
pg->physaddr = (segs->ds_addr + off) & ~(USB_PAGE_SIZE - 1);
diff --git a/sys/dev/usb/usb_busdma.h b/sys/dev/usb/usb_busdma.h
index 6b6e403..1050af5 100644
--- a/sys/dev/usb/usb_busdma.h
+++ b/sys/dev/usb/usb_busdma.h
@@ -27,10 +27,12 @@
#ifndef _USB_BUSDMA_H_
#define _USB_BUSDMA_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/uio.h>
#include <sys/mbuf.h>
#include <machine/bus.h>
+#endif
/* defines */
diff --git a/sys/dev/usb/usb_compat_linux.c b/sys/dev/usb/usb_compat_linux.c
index 22bf1f4..a42f636 100644
--- a/sys/dev/usb/usb_compat_linux.c
+++ b/sys/dev/usb/usb_compat_linux.c
@@ -25,6 +25,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -61,6 +64,7 @@
#include <dev/usb/usb_hub.h>
#include <dev/usb/usb_request.h>
#include <dev/usb/usb_debug.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
struct usb_linux_softc {
LIST_ENTRY(usb_linux_softc) sc_attached_list;
@@ -109,7 +113,7 @@ static device_method_t usb_linux_methods[] = {
DEVMETHOD(device_suspend, usb_linux_suspend),
DEVMETHOD(device_resume, usb_linux_resume),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t usb_linux_driver = {
diff --git a/sys/dev/usb/usb_core.c b/sys/dev/usb/usb_core.c
index 1bd05c8..8a5b93c 100644
--- a/sys/dev/usb/usb_core.c
+++ b/sys/dev/usb/usb_core.c
@@ -30,6 +30,9 @@
* http://www.usb.org/developers/devclass_docs/
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -51,6 +54,12 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
+
+const struct usb_string_lang usb_string_lang_en = {
+ sizeof(usb_string_lang_en), UDESC_STRING,
+ { 0x09, 0x04 } /* American English */
+};
MALLOC_DEFINE(M_USB, "USB", "USB");
MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device");
diff --git a/sys/dev/usb/usb_core.h b/sys/dev/usb/usb_core.h
index 776cf17..afd74ed 100644
--- a/sys/dev/usb/usb_core.h
+++ b/sys/dev/usb/usb_core.h
@@ -69,6 +69,7 @@ struct usb_page;
struct usb_page_cache;
struct usb_xfer;
struct usb_xfer_root;
+struct usb_string_lang;
/* typedefs */
@@ -174,6 +175,7 @@ struct usb_xfer {
/* external variables */
extern struct mtx usb_ref_lock;
+extern const struct usb_string_lang usb_string_lang_en;
/* typedefs */
diff --git a/sys/dev/usb/usb_debug.c b/sys/dev/usb/usb_debug.c
index 7ca4daa..3382988 100644
--- a/sys/dev/usb/usb_debug.c
+++ b/sys/dev/usb/usb_debug.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -55,6 +58,7 @@
#include <ddb/ddb.h>
#include <ddb/db_sym.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/*
* Define this unconditionally in case a kernel module is loaded that
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
index a8adbf6..c4264c5 100644
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -27,6 +27,9 @@
* usb_dev.c - An abstraction layer for creating devices under /dev/...
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -75,6 +78,7 @@
#include <sys/syscallsubr.h>
#include <machine/stdarg.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#if USB_HAVE_UGEN
diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h
index aa9197f..3c75701 100644
--- a/sys/dev/usb/usb_dev.h
+++ b/sys/dev/usb/usb_dev.h
@@ -27,11 +27,13 @@
#ifndef _USB_DEV_H_
#define _USB_DEV_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/file.h>
#include <sys/selinfo.h>
#include <sys/poll.h>
#include <sys/signalvar.h>
#include <sys/proc.h>
+#endif
struct usb_fifo;
struct usb_mbuf;
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 05c0a4c..8d88bf5 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -78,6 +81,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/* function prototypes */
diff --git a/sys/dev/usb/usb_dynamic.c b/sys/dev/usb/usb_dynamic.c
index 1358b30..f8bb03f 100644
--- a/sys/dev/usb/usb_dynamic.c
+++ b/sys/dev/usb/usb_dynamic.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -50,6 +53,7 @@
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_dynamic.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/* function prototypes */
static usb_handle_req_t usb_temp_get_desc_w;
diff --git a/sys/dev/usb/usb_endian.h b/sys/dev/usb/usb_endian.h
index 29479f1..0bbcb9b 100644
--- a/sys/dev/usb/usb_endian.h
+++ b/sys/dev/usb/usb_endian.h
@@ -27,8 +27,10 @@
#ifndef _USB_ENDIAN_H_
#define _USB_ENDIAN_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/stdint.h>
#include <sys/endian.h>
+#endif
/*
* Declare the basic USB record types. USB records have an alignment
diff --git a/sys/dev/usb/usb_error.c b/sys/dev/usb/usb_error.c
index 119c617..5987d81 100644
--- a/sys/dev/usb/usb_error.c
+++ b/sys/dev/usb/usb_error.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -45,6 +48,7 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
static const char* usb_errstr_table[USB_ERR_MAX] = {
[USB_ERR_NORMAL_COMPLETION] = "USB_ERR_NORMAL_COMPLETION",
diff --git a/sys/dev/usb/usb_freebsd.h b/sys/dev/usb/usb_freebsd.h
index 42a54c5..e93bee7 100644
--- a/sys/dev/usb/usb_freebsd.h
+++ b/sys/dev/usb/usb_freebsd.h
@@ -42,6 +42,8 @@
#define USB_HAVE_POWERD 1
#define USB_HAVE_MSCTEST 1
#define USB_HAVE_PF 1
+#define USB_HAVE_ROOT_MOUNT_HOLD 1
+#define USB_HAVE_ID_SECTION 1
#define USB_TD_GET_PROC(td) (td)->td_proc
#define USB_PROC_GET_GID(td) (td)->p_pgid
diff --git a/sys/dev/usb/usb_freebsd_loader.h b/sys/dev/usb/usb_freebsd_loader.h
new file mode 100644
index 0000000..566f922
--- /dev/null
+++ b/sys/dev/usb/usb_freebsd_loader.h
@@ -0,0 +1,84 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2013 Hans Petter Selasky. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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.
+ */
+
+/*
+ * Including this file is mandatory for all USB related c-files in the loader.
+ */
+
+#ifndef _USB_FREEBSD_LOADER_H_
+#define _USB_FREEBSD_LOADER_H_
+
+/* Default USB configuration */
+#define USB_HAVE_UGEN 0
+#define USB_HAVE_DEVCTL 0
+#define USB_HAVE_BUSDMA 1
+#define USB_HAVE_COMPAT_LINUX 0
+#define USB_HAVE_USER_IO 0
+#define USB_HAVE_MBUF 0
+#define USB_HAVE_TT_SUPPORT 1
+#define USB_HAVE_POWERD 1
+#define USB_HAVE_MSCTEST 0
+#define USB_HAVE_PF 0
+#define USB_HAVE_ROOT_MOUNT_HOLD 0
+#define USB_HAVE_ID_SECTION 0
+
+#define USB_TD_GET_PROC(td) (td)->td_proc
+#define USB_PROC_GET_GID(td) (td)->p_pgid
+
+#if (!defined(USB_HOST_ALIGN)) || (USB_HOST_ALIGN <= 0)
+/* Use default value. */
+#undef USB_HOST_ALIGN
+#define USB_HOST_ALIGN 8 /* bytes, must be power of two */
+#endif
+/* Sanity check for USB_HOST_ALIGN: Verify power of two. */
+#if ((-USB_HOST_ALIGN) & USB_HOST_ALIGN) != USB_HOST_ALIGN
+#error "USB_HOST_ALIGN is not power of two."
+#endif
+#define USB_FS_ISOC_UFRAME_MAX 4 /* exclusive unit */
+#define USB_BUS_MAX 256 /* units */
+#define USB_MAX_DEVICES 128 /* units */
+#define USB_IFACE_MAX 32 /* units */
+#define USB_FIFO_MAX 128 /* units */
+#define USB_MAX_EP_STREAMS 8 /* units */
+
+#define USB_MAX_FS_ISOC_FRAMES_PER_XFER (120) /* units */
+#define USB_MAX_HS_ISOC_FRAMES_PER_XFER (8*120) /* units */
+
+#define USB_HUB_MAX_DEPTH 5
+#define USB_EP0_BUFSIZE 1024 /* bytes */
+#define USB_CS_RESET_LIMIT 20 /* failures = 20 * 50 ms = 1sec */
+
+#define USB_MAX_AUTO_QUIRK 4 /* maximum number of dynamic quirks */
+
+typedef uint32_t usb_timeout_t; /* milliseconds */
+typedef uint32_t usb_frlength_t; /* bytes */
+typedef uint32_t usb_frcount_t; /* units */
+typedef uint32_t usb_size_t; /* bytes */
+typedef uint32_t usb_ticks_t; /* system defined */
+typedef uint16_t usb_power_mask_t; /* see "USB_HW_POWER_XXX" */
+typedef uint16_t usb_stream_t; /* stream ID */
+
+#endif /* _USB_FREEBSD_LOADER_H_ */
diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c
index f8376bf..13f5bd6 100644
--- a/sys/dev/usb/usb_generic.c
+++ b/sys/dev/usb/usb_generic.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -67,6 +70,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#if USB_HAVE_UGEN
diff --git a/sys/dev/usb/usb_handle_request.c b/sys/dev/usb/usb_handle_request.c
index f5b226e..13fff91 100644
--- a/sys/dev/usb/usb_handle_request.c
+++ b/sys/dev/usb/usb_handle_request.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -61,6 +64,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/* function prototypes */
diff --git a/sys/dev/usb/usb_hid.c b/sys/dev/usb/usb_hid.c
index 6552546..e6361a6 100644
--- a/sys/dev/usb/usb_hid.c
+++ b/sys/dev/usb/usb_hid.c
@@ -1,8 +1,5 @@
+/* $FreeBSD$ */
/* $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $ */
-
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -33,6 +30,9 @@ __FBSDID("$FreeBSD$");
* POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_request.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
static void hid_clear_local(struct hid_item *);
static uint8_t hid_get_byte(struct hid_data *s, const uint16_t wSize);
@@ -845,3 +846,79 @@ usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
}
return (USB_ERR_NORMAL_COMPLETION);
}
+
+/*------------------------------------------------------------------------*
+ * hid_is_mouse
+ *
+ * This function will decide if a USB descriptor belongs to a USB mouse.
+ *
+ * Return values:
+ * Zero: Not a USB mouse.
+ * Else: Is a USB mouse.
+ *------------------------------------------------------------------------*/
+int
+hid_is_mouse(const void *d_ptr, uint16_t d_len)
+{
+ struct hid_data *hd;
+ struct hid_item hi;
+ int mdepth;
+ int found;
+
+ hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
+ if (hd == NULL)
+ return (0);
+
+ mdepth = 0;
+ found = 0;
+
+ while (hid_get_item(hd, &hi)) {
+ switch (hi.kind) {
+ case hid_collection:
+ if (mdepth != 0)
+ mdepth++;
+ else if (hi.collection == 1 &&
+ hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
+ mdepth++;
+ break;
+ case hid_endcollection:
+ if (mdepth != 0)
+ mdepth--;
+ break;
+ case hid_input:
+ if (mdepth == 0)
+ break;
+ if (hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
+ (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
+ found++;
+ if (hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
+ (hi.flags & (HIO_CONST|HIO_RELATIVE)) == HIO_RELATIVE)
+ found++;
+ break;
+ default:
+ break;
+ }
+ }
+ hid_end_parse(hd);
+ return (found);
+}
+
+/*------------------------------------------------------------------------*
+ * hid_is_keyboard
+ *
+ * This function will decide if a USB descriptor belongs to a USB keyboard.
+ *
+ * Return values:
+ * Zero: Not a USB keyboard.
+ * Else: Is a USB keyboard.
+ *------------------------------------------------------------------------*/
+int
+hid_is_keyboard(const void *d_ptr, uint16_t d_len)
+{
+ if (hid_is_collection(d_ptr, d_len,
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD)))
+ return (1);
+ return (0);
+}
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index e3a673d..5e372c8 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -30,6 +30,9 @@
* USB spec: http://www.usb.org/developers/docs/usbspec.zip
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -69,6 +72,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#define UHUB_INTR_INTERVAL 250 /* ms */
#define UHUB_N_TRANSFER 1
diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h
index 62edb99..1d9b223 100644
--- a/sys/dev/usb/usb_ioctl.h
+++ b/sys/dev/usb/usb_ioctl.h
@@ -29,12 +29,14 @@
#ifndef _USB_IOCTL_H_
#define _USB_IOCTL_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/ioccom.h>
/* Building "kdump" depends on these includes */
#include <dev/usb/usb_endian.h>
#include <dev/usb/usb.h>
+#endif
#define USB_DEVICE_NAME "usbctl"
#define USB_DEVICE_DIR "usb"
diff --git a/sys/dev/usb/usb_lookup.c b/sys/dev/usb/usb_lookup.c
index e03f9b6..f3dc551 100644
--- a/sys/dev/usb/usb_lookup.c
+++ b/sys/dev/usb/usb_lookup.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -47,6 +50,7 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/*------------------------------------------------------------------------*
* usbd_lookup_id_by_info
@@ -174,7 +178,7 @@ usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id,
#define MFL_SIZE "0"
#endif
-#ifdef KLD_MODULE
+#if defined(KLD_MODULE) && (USB_HAVE_ID_SECTION != 0)
static const char __section("bus_autoconf_format") __used usb_id_format[] = {
/* Declare that three different sections use the same format */
diff --git a/sys/dev/usb/usb_mbuf.c b/sys/dev/usb/usb_mbuf.c
index 65b2a91..ff2f6da 100644
--- a/sys/dev/usb/usb_mbuf.c
+++ b/sys/dev/usb/usb_mbuf.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -47,6 +50,7 @@
#include <dev/usb/usbdi.h>
#include <dev/usb/usb_dev.h>
#include <dev/usb/usb_mbuf.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/*------------------------------------------------------------------------*
* usb_alloc_mbufs - allocate mbufs to an usbd interface queue
diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c
index c5e8f49..497e382 100644
--- a/sys/dev/usb/usb_msctest.c
+++ b/sys/dev/usb/usb_msctest.c
@@ -32,6 +32,9 @@
* mass storage quirks for not supported SCSI commands!
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -66,6 +69,7 @@
#include <dev/usb/usb_request.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/quirk/usb_quirk.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
enum {
ST_COMMAND,
diff --git a/sys/dev/usb/usb_parse.c b/sys/dev/usb/usb_parse.c
index 66ab5fa..d6e54ad 100644
--- a/sys/dev/usb/usb_parse.c
+++ b/sys/dev/usb/usb_parse.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -46,7 +49,7 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
-
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/*------------------------------------------------------------------------*
* usb_desc_foreach
diff --git a/sys/dev/usb/usb_pci.h b/sys/dev/usb/usb_pci.h
index 071dfc3..6eebc55 100644
--- a/sys/dev/usb/usb_pci.h
+++ b/sys/dev/usb/usb_pci.h
@@ -31,9 +31,11 @@
* We don't want the following files included everywhere, that's why
* they are in a separate file.
*/
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <sys/rman.h>
+#endif
#endif /* _USB_PCI_H_ */
diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c
index d9c8dac..98705eb 100644
--- a/sys/dev/usb/usb_pf.c
+++ b/sys/dev/usb/usb_pf.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/*-
* Copyright (c) 1990, 1991, 1993
* The Regents of the University of California. All rights reserved.
@@ -32,8 +33,9 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/bus.h>
@@ -59,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_bus.h>
#include <dev/usb/usb_pf.h>
#include <dev/usb/usb_transfer.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
static void usbpf_init(void);
static void usbpf_uninit(void);
diff --git a/sys/dev/usb/usb_process.c b/sys/dev/usb/usb_process.c
index c006f51..34314f4 100644
--- a/sys/dev/usb/usb_process.c
+++ b/sys/dev/usb/usb_process.c
@@ -26,6 +26,9 @@
#define USB_DEBUG_VAR usb_proc_debug
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -55,6 +58,7 @@
#include <sys/proc.h>
#include <sys/kthread.h>
#include <sys/sched.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
#if (__FreeBSD_version < 700000)
#define thread_lock(td) mtx_lock_spin(&sched_lock)
diff --git a/sys/dev/usb/usb_process.h b/sys/dev/usb/usb_process.h
index 23cf660..923f645 100644
--- a/sys/dev/usb/usb_process.h
+++ b/sys/dev/usb/usb_process.h
@@ -27,9 +27,11 @@
#ifndef _USB_PROCESS_H_
#define _USB_PROCESS_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/interrupt.h>
#include <sys/priority.h>
#include <sys/runq.h>
+#endif
/* defines */
#define USB_PRI_HIGH PI_SWI(SWI_NET)
diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c
index ce50d9b..6a81945 100644
--- a/sys/dev/usb/usb_request.c
+++ b/sys/dev/usb/usb_request.c
@@ -26,6 +26,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -66,6 +69,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <sys/ctype.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
static int usb_no_cs_fail;
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index 6e48a3e..397b0b7 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -61,6 +64,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <dev/usb/usb_pf.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
struct usb_std_packet_size {
struct {
diff --git a/sys/dev/usb/usb_util.c b/sys/dev/usb/usb_util.c
index 4fe79c5..f9fec76 100644
--- a/sys/dev/usb/usb_util.c
+++ b/sys/dev/usb/usb_util.c
@@ -24,6 +24,9 @@
* SUCH DAMAGE.
*/
+#ifdef USB_GLOBAL_INCLUDE_FILE
+#include USB_GLOBAL_INCLUDE_FILE
+#else
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -56,6 +59,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#endif /* USB_GLOBAL_INCLUDE_FILE */
/*------------------------------------------------------------------------*
* device_set_usb_desc
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 0cd43ef..aff55fd 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -581,6 +581,7 @@ vendor CCYU 0x1065 CCYU Technology
vendor CURITEL 0x106c Curitel Communications Inc
vendor SILABS2 0x10a6 SILABS2
vendor USI 0x10ab USI
+vendor LIEBERT2 0x10af Liebert
vendor PLX 0x10b5 PLX
vendor ASANTE 0x10bd Asante
vendor SILABS 0x10c4 Silicon Labs
@@ -1486,6 +1487,7 @@ product DIGIANSWER ZIGBEE802154 0x000a ZigBee/802.15.4 MAC
/* D-Link products */
/*product DLINK DSBS25 0x0100 DSB-S25 serial*/
product DLINK DUBE100 0x1a00 10/100 Ethernet
+product DLINK DUBE100C1 0x1a02 DUB-E100 rev C1
product DLINK DSB650TX4 0x200c 10/100 Ethernet
product DLINK DWL120E 0x3200 DWL-120 rev E
product DLINK DWL122 0x3700 DWL-122
@@ -2426,6 +2428,7 @@ product LEXMARK S2450 0x0009 Optra S 2450
/* Liebert products */
product LIEBERT POWERSURE_PXT 0xffff PowerSure Personal XT
+product LIEBERT2 PSI1000 0x0004 UPS PSI 1000 FW:08
/* Link Instruments Inc. products */
product LINKINSTRUMENTS MSO19 0xf190 Link Instruments MSO-19
@@ -2939,6 +2942,7 @@ product MOTOROLA2 A41XV32X 0x2a22 A41x/V32x Mobile Phones
product MOTOROLA2 E398 0x4810 E398 Mobile Phone
product MOTOROLA2 USBLAN 0x600c USBLAN
product MOTOROLA2 USBLAN2 0x6027 USBLAN
+product MOTOROLA2 MB886 0x710f MB886 Mobile Phone (Atria HD)
product MOTOROLA4 RT2770 0x9031 RT2770
product MOTOROLA4 RT3070 0x9032 RT3070
@@ -3560,6 +3564,7 @@ product SANDISK SDDR75 0x0810 ImageMate SDDR-75
product SANDISK SDCZ2_256 0x7104 Cruzer Mini 256MB
product SANDISK SDCZ4_128 0x7112 Cruzer Micro 128MB
product SANDISK SDCZ4_256 0x7113 Cruzer Micro 256MB
+product SANDISK IMAGEMATE_SDDR289 0xb6ba ImageMate SDDR-289
/* Sanwa Electric Instrument Co., Ltd. products */
product SANWA KB_USB2 0x0701 KB-USB2 multimeter cable
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index d753fe1..26f7769 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -102,7 +102,9 @@ typedef void (usb_fifo_filter_t)(struct usb_fifo *fifo, struct usb_mbuf *m);
/* USB events */
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <sys/eventhandler.h>
+#endif
typedef void (*usb_dev_configured_t)(void *, struct usb_device *,
struct usb_attach_arg *);
EVENTHANDLER_DECLARE(usb_dev_configured, usb_dev_configured_t);
@@ -239,12 +241,21 @@ struct usb_config {
* have your driver module automatically loaded in host, device or
* both modes respectivly:
*/
+#if USB_HAVE_ID_SECTION
#define STRUCT_USB_HOST_ID \
struct usb_device_id __section("usb_host_id")
#define STRUCT_USB_DEVICE_ID \
struct usb_device_id __section("usb_device_id")
#define STRUCT_USB_DUAL_ID \
struct usb_device_id __section("usb_dual_id")
+#else
+#define STRUCT_USB_HOST_ID \
+ struct usb_device_id
+#define STRUCT_USB_DEVICE_ID \
+ struct usb_device_id
+#define STRUCT_USB_DUAL_ID \
+ struct usb_device_id
+#endif /* USB_HAVE_ID_SECTION */
/*
* The following structure is used when looking up an USB driver for
diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h
index f40232a..28dfede 100644
--- a/sys/dev/usb/usbhid.h
+++ b/sys/dev/usb/usbhid.h
@@ -29,7 +29,9 @@
#ifndef _USB_HID_H_
#define _USB_HID_H_
+#ifndef USB_GLOBAL_INCLUDE_FILE
#include <dev/usb/usb_endian.h>
+#endif
#define UR_GET_HID_DESCRIPTOR 0x06
#define UDESC_HID 0x21
@@ -242,5 +244,7 @@ struct usb_hid_descriptor *hid_get_descriptor_from_usb(
usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
void **descp, uint16_t *sizep, struct malloc_type *mem,
uint8_t iface_index);
+int hid_is_mouse(const void *d_ptr, uint16_t d_len);
+int hid_is_keyboard(const void *d_ptr, uint16_t d_len);
#endif /* _KERNEL */
#endif /* _USB_HID_H_ */
diff --git a/sys/dev/vx/if_vx_eisa.c b/sys/dev/vx/if_vx_eisa.c
index 80fb5c6..24dc2dd 100644
--- a/sys/dev/vx/if_vx_eisa.c
+++ b/sys/dev/vx/if_vx_eisa.c
@@ -177,7 +177,7 @@ static device_method_t vx_eisa_methods[] = {
DEVMETHOD(device_probe, vx_eisa_probe),
DEVMETHOD(device_attach, vx_eisa_attach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t vx_eisa_driver = {
diff --git a/sys/dev/vx/if_vx_pci.c b/sys/dev/vx/if_vx_pci.c
index 0412778..38037fa 100644
--- a/sys/dev/vx/if_vx_pci.c
+++ b/sys/dev/vx/if_vx_pci.c
@@ -61,7 +61,7 @@ static device_method_t vx_methods[] = {
DEVMETHOD(device_attach, vx_pci_attach),
DEVMETHOD(device_shutdown, vx_pci_shutdown),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t vx_driver = {
diff --git a/sys/dev/vxge/vxge.c b/sys/dev/vxge/vxge.c
index c35d84b..3650843 100644
--- a/sys/dev/vxge/vxge.c
+++ b/sys/dev/vxge/vxge.c
@@ -4188,7 +4188,8 @@ static device_method_t vxge_methods[] = {
DEVMETHOD(device_attach, vxge_attach),
DEVMETHOD(device_detach, vxge_detach),
DEVMETHOD(device_shutdown, vxge_shutdown),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t vxge_driver = {
diff --git a/sys/dev/wbwd/wbwd.c b/sys/dev/wbwd/wbwd.c
index dfd8f3c..484b5bf 100644
--- a/sys/dev/wbwd/wbwd.c
+++ b/sys/dev/wbwd/wbwd.c
@@ -179,6 +179,12 @@ struct winbond_vendor_device_id {
.device_rev = 0x73,
.descr = "Winbond 83627DHG-P",
},
+ {
+ .vendor_id = 0x5ca3,
+ .device_id = 0xc3,
+ .device_rev = 0x33,
+ .descr = "Nuvoton WPCM450RA0BX",
+ },
};
static void
@@ -596,6 +602,9 @@ wb_probe_enable(device_t dev, int probe)
goto cleanup;
}
+ if (dev_id == 0xff && dev_rev == 0xff)
+ goto cleanup;
+
for (j = 0; j < sizeof(wb_devs) / sizeof(*wb_devs); j++) {
if (wb_devs[j].device_id == dev_id &&
wb_devs[j].device_rev == dev_rev) {
@@ -605,6 +614,16 @@ wb_probe_enable(device_t dev, int probe)
break;
}
}
+
+ if (!found) {
+ if (probe && dev != NULL) {
+ device_set_desc(dev, "Unknown Winbond/Nuvoton model");
+ device_printf(dev, "DevID 0x%02x DevRev 0x%02x, "
+ "please report this.\n", dev_id, dev_rev);
+ }
+ found++;
+ }
+
if (probe && found && bootverbose && dev != NULL)
device_printf(dev, "%s EFER 0x%02x ID 0x%02x Rev 0x%02x"
" CR26 0x%02x (probing)\n", device_get_desc(dev),
diff --git a/sys/dev/xen/console/console.c b/sys/dev/xen/console/console.c
index 6a845ca..6281bf2 100644
--- a/sys/dev/xen/console/console.c
+++ b/sys/dev/xen/console/console.c
@@ -410,7 +410,8 @@ static device_method_t xc_methods[] = {
DEVMETHOD(device_identify, xc_identify),
DEVMETHOD(device_probe, xc_probe),
DEVMETHOD(device_attach, xc_attach),
- {0, 0}
+
+ DEVMETHOD_END
};
static driver_t xc_driver = {
diff --git a/sys/fs/ext2fs/ext2_alloc.c b/sys/fs/ext2fs/ext2_alloc.c
index a701087..cafd32d 100644
--- a/sys/fs/ext2fs/ext2_alloc.c
+++ b/sys/fs/ext2fs/ext2_alloc.c
@@ -151,11 +151,11 @@ nospace:
static SYSCTL_NODE(_vfs, OID_AUTO, ext2fs, CTLFLAG_RW, 0, "EXT2FS filesystem");
-static int doasyncfree = 1;
+static int doasyncfree = 0;
SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0,
"Use asychronous writes to update block pointers when freeing blocks");
-static int doreallocblks = 1;
+static int doreallocblks = 0;
SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, "");
int
@@ -169,7 +169,7 @@ ext2_reallocblks(ap)
struct inode *ip;
struct vnode *vp;
struct buf *sbp, *ebp;
- int32_t *bap, *sbap, *ebap = 0;
+ uint32_t *bap, *sbap, *ebap = 0;
struct ext2mount *ump;
struct cluster_save *buflist;
struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
@@ -242,7 +242,7 @@ ext2_reallocblks(ap)
} else {
#ifdef DIAGNOSTIC
if (start_ap[start_lvl-1].in_lbn == idp->in_lbn)
- panic("ext2_reallocblk: start == end");
+ panic("ext2_reallocblks: start == end");
#endif
ssize = len - (idp->in_off + 1);
if (bread(vp, idp->in_lbn, (int)fs->e2fs_bsize, NOCRED, &ebp))
@@ -1004,7 +1004,7 @@ ext2_blkfree(ip, bno, size)
if (isclr(bbp, bno)) {
printf("block = %lld, fs = %s\n",
(long long)bno, fs->e2fs_fsmnt);
- panic("blkfree: freeing free block");
+ panic("ext2_blkfree: freeing free block");
}
clrbit(bbp, bno);
EXT2_LOCK(ump);
@@ -1032,7 +1032,6 @@ ext2_vfree(pvp, ino, mode)
struct ext2mount *ump;
int error, cg;
char * ibp;
-/* mode_t save_i_mode; */
pip = VTOI(pvp);
fs = pip->i_e2fs;
@@ -1055,7 +1054,7 @@ ext2_vfree(pvp, ino, mode)
printf("ino = %llu, fs = %s\n",
(unsigned long long)ino, fs->e2fs_fsmnt);
if (fs->e2fs_ronly == 0)
- panic("ifree: freeing free inode");
+ panic("ext2_vfree: freeing free inode");
}
clrbit(ibp, ino);
EXT2_LOCK(ump);
@@ -1100,7 +1099,7 @@ ext2_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t bpref)
if (loc == NULL) {
printf("start = %d, len = %d, fs = %s\n",
start, len, fs->e2fs_fsmnt);
- panic("ext2fs_alloccg: map corrupted");
+ panic("ext2_mapsearch: map corrupted");
/* NOTREACHED */
}
}
diff --git a/sys/fs/ext2fs/ext2_balloc.c b/sys/fs/ext2fs/ext2_balloc.c
index 6e60c6e..1861f69 100644
--- a/sys/fs/ext2fs/ext2_balloc.c
+++ b/sys/fs/ext2fs/ext2_balloc.c
@@ -69,7 +69,7 @@ ext2_balloc(ip, lbn, size, cred, bpp, flags)
struct buf *bp, *nbp;
struct vnode *vp = ITOV(ip);
struct indir indirs[NIADDR + 2];
- int32_t newb, *bap, pref;
+ uint32_t newb, *bap, pref;
int osize, nsize, num, i, error;
*bpp = NULL;
diff --git a/sys/fs/ext2fs/ext2_dinode.h b/sys/fs/ext2fs/ext2_dinode.h
index 7d97bb8..7d97bb8 100755..100644
--- a/sys/fs/ext2fs/ext2_dinode.h
+++ b/sys/fs/ext2fs/ext2_dinode.h
diff --git a/sys/fs/ext2fs/ext2_dir.h b/sys/fs/ext2fs/ext2_dir.h
index 5e11166..2bad4cd 100755..100644
--- a/sys/fs/ext2fs/ext2_dir.h
+++ b/sys/fs/ext2fs/ext2_dir.h
@@ -37,7 +37,7 @@
struct ext2fs_direct {
uint32_t e2d_ino; /* inode number of entry */
uint16_t e2d_reclen; /* length of this record */
- uint16_t e2d_namlen; /* length of string in d_name */
+ uint16_t e2d_namlen; /* length of string in e2d_name */
char e2d_name[EXT2FS_MAXNAMLEN];/* name with length<=EXT2FS_MAXNAMLEN */
};
/*
@@ -49,7 +49,7 @@ struct ext2fs_direct {
struct ext2fs_direct_2 {
uint32_t e2d_ino; /* inode number of entry */
uint16_t e2d_reclen; /* length of this record */
- uint8_t e2d_namlen; /* length of string in d_name */
+ uint8_t e2d_namlen; /* length of string in e2d_name */
uint8_t e2d_type; /* file type */
char e2d_name[EXT2FS_MAXNAMLEN];/* name with length<=EXT2FS_MAXNAMLEN */
};
diff --git a/sys/fs/ext2fs/ext2_inode.c b/sys/fs/ext2fs/ext2_inode.c
index e7fc9a8..fe9b50d 100644
--- a/sys/fs/ext2fs/ext2_inode.c
+++ b/sys/fs/ext2fs/ext2_inode.c
@@ -119,7 +119,7 @@ ext2_truncate(vp, length, flags, cred, td)
int32_t lastblock;
struct inode *oip;
int32_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR];
- int32_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
+ uint32_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
struct bufobj *bo;
struct m_ext2fs *fs;
struct buf *bp;
@@ -180,7 +180,7 @@ ext2_truncate(vp, length, flags, cred, td)
else
bawrite(bp);
oip->i_flag |= IN_CHANGE | IN_UPDATE;
- return (ext2_update(ovp, 1));
+ return (ext2_update(ovp, !DOINGASYNC(ovp)));
}
/*
* Shorten the size of the file. If the file is not being
@@ -238,7 +238,7 @@ ext2_truncate(vp, length, flags, cred, td)
for (i = NDADDR - 1; i > lastblock; i--)
oip->i_db[i] = 0;
oip->i_flag |= IN_CHANGE | IN_UPDATE;
- allerror = ext2_update(ovp, 1);
+ allerror = ext2_update(ovp, !DOINGASYNC(ovp));
/*
* Having written the new inode to disk, save its new configuration
@@ -311,7 +311,7 @@ ext2_truncate(vp, length, flags, cred, td)
oip->i_size = length;
newspace = blksize(fs, oip, lastblock);
if (newspace == 0)
- panic("itrunc: newspace");
+ panic("ext2_truncate: newspace");
if (oldspace - newspace > 0) {
/*
* Block number of space to be free'd is
@@ -341,8 +341,9 @@ done:
* Put back the real size.
*/
oip->i_size = length;
- oip->i_blocks -= blocksreleased;
- if (oip->i_blocks < 0) /* sanity */
+ if (oip->i_blocks >= blocksreleased)
+ oip->i_blocks -= blocksreleased;
+ else /* sanity */
oip->i_blocks = 0;
oip->i_flag |= IN_CHANGE;
vnode_pager_setsize(ovp, length);
@@ -420,9 +421,13 @@ ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
(u_int)(NINDIR(fs) - (last + 1)) * sizeof(int32_t));
if (last == -1)
bp->b_flags |= B_INVAL;
- error = bwrite(bp);
- if (error)
- allerror = error;
+ if (DOINGASYNC(vp)) {
+ bdwrite(bp);
+ } else {
+ error = bwrite(bp);
+ if (error)
+ allerror = error;
+ }
bap = copy;
/*
diff --git a/sys/fs/ext2fs/ext2_lookup.c b/sys/fs/ext2fs/ext2_lookup.c
index c279998..9aadb6a 100644
--- a/sys/fs/ext2fs/ext2_lookup.c
+++ b/sys/fs/ext2fs/ext2_lookup.c
@@ -812,7 +812,7 @@ ext2_direnter(ip, dvp, cnp)
#ifdef DIAGNOSTIC
if ((cnp->cn_flags & SAVENAME) == 0)
- panic("direnter: missing name");
+ panic("ext2_direnter: missing name");
#endif
dp = VTOI(dvp);
newdir.e2d_ino = ip->i_number;
diff --git a/sys/fs/ext2fs/ext2_vfsops.c b/sys/fs/ext2fs/ext2_vfsops.c
index 3f181fd..136f01c 100644
--- a/sys/fs/ext2fs/ext2_vfsops.c
+++ b/sys/fs/ext2fs/ext2_vfsops.c
@@ -127,7 +127,7 @@ ext2_mount(struct mount *mp)
vfs_getopt(opts, "fspath", (void **)&path, NULL);
/* Double-check the length of path.. */
- if (strlen(path) >= MAXMNTLEN - 1)
+ if (strlen(path) >= MAXMNTLEN)
return (ENAMETOOLONG);
fspec = NULL;
@@ -318,12 +318,12 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
int i;
int logic_sb_block = 1; /* XXX for now */
struct buf *bp;
+ uint32_t e2fs_descpb;
fs->e2fs_bsize = EXT2_MIN_BLOCK_SIZE << es->e2fs_log_bsize;
fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize;
fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1;
fs->e2fs_qbmask = fs->e2fs_bsize - 1;
- fs->e2fs_blocksize_bits = es->e2fs_log_bsize + 10;
fs->e2fs_fsize = EXT2_MIN_FRAG_SIZE << es->e2fs_log_fsize;
if (fs->e2fs_fsize)
fs->e2fs_fpb = fs->e2fs_bsize / fs->e2fs_fsize;
@@ -331,10 +331,8 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
fs->e2fs_fpg = es->e2fs_fpg;
fs->e2fs_ipg = es->e2fs_ipg;
if (es->e2fs_rev == E2FS_REV0) {
- fs->e2fs_first_inode = EXT2_FIRSTINO;
fs->e2fs_isize = E2FS_REV0_INODE_SIZE ;
} else {
- fs->e2fs_first_inode = es->e2fs_first_ino;
fs->e2fs_isize = es->e2fs_inode_size;
/*
@@ -357,12 +355,11 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
fs->e2fs_itpg = fs->e2fs_ipg /fs->e2fs_ipb;
- fs->e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
/* s_resuid / s_resgid ? */
fs->e2fs_gcount = (es->e2fs_bcount - es->e2fs_first_dblock +
EXT2_BLOCKS_PER_GROUP(fs) - 1) / EXT2_BLOCKS_PER_GROUP(fs);
- db_count = (fs->e2fs_gcount + EXT2_DESC_PER_BLOCK(fs) - 1) /
- EXT2_DESC_PER_BLOCK(fs);
+ e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
+ db_count = (fs->e2fs_gcount + e2fs_descpb - 1) / e2fs_descpb;
fs->e2fs_gdbcount = db_count;
fs->e2fs_gd = malloc(db_count * fs->e2fs_bsize,
M_EXT2MNT, M_WAITOK);
@@ -766,7 +763,7 @@ ext2_statfs(struct mount *mp, struct statfs *sbp)
ump = VFSTOEXT2(mp);
fs = ump->um_e2fs;
if (fs->e2fs->e2fs_magic != E2FS_MAGIC)
- panic("ext2fs_statfs");
+ panic("ext2_statfs");
/*
* Compute the overhead (FS structures)
diff --git a/sys/fs/ext2fs/ext2fs.h b/sys/fs/ext2fs/ext2fs.h
index 5cafc7b..c5a4c15 100755..100644
--- a/sys/fs/ext2fs/ext2fs.h
+++ b/sys/fs/ext2fs/ext2fs.h
@@ -153,7 +153,6 @@ struct m_ext2fs {
char e2fs_fmod; /* super block modified flag */
uint32_t e2fs_bsize; /* Block size */
uint32_t e2fs_bshift; /* calc of logical block no */
- int32_t e2fs_bmask; /* calc of block offset */
int32_t e2fs_bpg; /* Number of blocks per group */
int64_t e2fs_qbmask; /* = s_blocksize -1 */
uint32_t e2fs_fsbtodb; /* Shift to get disk block */
@@ -163,14 +162,9 @@ struct m_ext2fs {
uint32_t e2fs_fsize; /* Size of fragments per block */
uint32_t e2fs_fpb; /* Number of fragments per block */
uint32_t e2fs_fpg; /* Number of fragments per group */
- uint32_t e2fs_dbpg; /* Number of descriptor blocks per group */
- uint32_t e2fs_descpb; /* Number of group descriptors per block */
uint32_t e2fs_gdbcount; /* Number of group descriptors */
uint32_t e2fs_gcount; /* Number of groups */
- uint32_t e2fs_first_inode;/* First inode on fs */
int32_t e2fs_isize; /* Size of inode */
- uint32_t e2fs_mount_opt;
- uint32_t e2fs_blocksize_bits;
uint32_t e2fs_total_dir; /* Total number of directories */
uint8_t *e2fs_contigdirs; /* (u) # of contig. allocated dirs */
char e2fs_wasvalid; /* valid at mount time */
@@ -313,27 +307,9 @@ struct csum {
#define EXT2_MIN_BLOCK_SIZE 1024
#define EXT2_MAX_BLOCK_SIZE 4096
#define EXT2_MIN_BLOCK_LOG_SIZE 10
-#if defined(_KERNEL)
-# define EXT2_BLOCK_SIZE(s) ((s)->e2fs_bsize)
-#else
-# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->e2fs_log_bsize)
-#endif
+#define EXT2_BLOCK_SIZE(s) ((s)->e2fs_bsize)
#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(uint32_t))
-#if defined(_KERNEL)
-# define EXT2_BLOCK_SIZE_BITS(s) ((s)->e2fs_blocksize_bits)
-#else
-# define EXT2_BLOCK_SIZE_BITS(s) ((s)->e2fs_log_bsize + 10)
-#endif
-#if defined(_KERNEL)
-#define EXT2_ADDR_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_addr_per_block_bits)
#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->e2fs_isize)
-#define EXT2_FIRST_INO(s) (EXT2_SB(s)->e2fs_first_inode)
-#else
-#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == E2FS_REV0) ? \
- E2FS_REV0 : (s)->s_inode_size)
-#define EXT2_FIRST_INO(s) (((s)->s_rev_level == E2FS_REV0) ? \
- E2FS_REV0 : (s)->e2fs_first_ino)
-#endif
/*
* Macro-instructions used to manage fragments
@@ -341,25 +317,12 @@ struct csum {
#define EXT2_MIN_FRAG_SIZE 1024
#define EXT2_MAX_FRAG_SIZE 4096
#define EXT2_MIN_FRAG_LOG_SIZE 10
-#if defined(_KERNEL)
-# define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->e2fs_fsize)
-# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->e2fs_fpb)
-#else
-# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->e2fs_log_fsize)
-# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
-#endif
+#define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->e2fs_fsize)
+#define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->e2fs_fpb)
/*
* Macro-instructions used to manage group descriptors
*/
-#if defined(_KERNEL)
-# define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->e2fs_bpg)
-# define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->e2fs_descpb)
-# define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits)
-#else
-# define EXT2_BLOCKS_PER_GROUP(s) ((s)->e2fs_bpg)
-# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(struct ext2_gd))
-
-#endif
+#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->e2fs_bpg)
#endif /* !_FS_EXT2FS_EXT2FS_H_ */
diff --git a/sys/fs/ext2fs/fs.h b/sys/fs/ext2fs/fs.h
index 880c500..7068e79 100644
--- a/sys/fs/ext2fs/fs.h
+++ b/sys/fs/ext2fs/fs.h
@@ -149,7 +149,4 @@
*/
#define NINDIR(fs) (EXT2_ADDR_PER_BLOCK(fs))
-extern int inside[], around[];
-extern u_char *fragtbl[];
-
#endif /* !_FS_EXT2FS_FS_H_ */
diff --git a/sys/fs/ext2fs/inode.h b/sys/fs/ext2fs/inode.h
index d8aaac9..ec47216 100644
--- a/sys/fs/ext2fs/inode.h
+++ b/sys/fs/ext2fs/inode.h
@@ -90,11 +90,11 @@ struct inode {
int32_t i_atimensec; /* Last access time. */
int32_t i_ctimensec; /* Last inode change time. */
int32_t i_birthnsec; /* Inode creation time. */
- int32_t i_db[NDADDR]; /* Direct disk blocks. */
- int32_t i_ib[NIADDR]; /* Indirect disk blocks. */
+ uint32_t i_db[NDADDR]; /* Direct disk blocks. */
+ uint32_t i_ib[NIADDR]; /* Indirect disk blocks. */
uint32_t i_flags; /* Status flags (chflags). */
- int32_t i_blocks; /* Blocks actually held. */
- int32_t i_gen; /* Generation number. */
+ uint32_t i_blocks; /* Blocks actually held. */
+ uint32_t i_gen; /* Generation number. */
uint32_t i_uid; /* File owner. */
uint32_t i_gid; /* File group. */
};
@@ -162,7 +162,7 @@ struct ufid {
uint16_t ufid_len; /* Length of structure. */
uint16_t ufid_pad; /* Force 32-bit alignment. */
ino_t ufid_ino; /* File number (ino). */
- int32_t ufid_gen; /* Generation number. */
+ uint32_t ufid_gen; /* Generation number. */
};
#endif /* _KERNEL */
diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c
index 0b1899f..3994042 100644
--- a/sys/fs/msdosfs/msdosfs_fat.c
+++ b/sys/fs/msdosfs/msdosfs_fat.c
@@ -321,8 +321,8 @@ updatefats(pmp, bp, fatbn)
struct buf *bp;
u_long fatbn;
{
- int i;
struct buf *bpn;
+ int cleanfat, i;
#ifdef MSDOSFS_DEBUG
printf("updatefats(pmp %p, bp %p, fatbn %lu)\n", pmp, bp, fatbn);
@@ -362,13 +362,24 @@ updatefats(pmp, bp, fatbn)
* filesystem was mounted. If synch is asked for then use
* bwrite()'s and really slow things down.
*/
+ if (fatbn != pmp->pm_fatblk || FAT12(pmp))
+ cleanfat = 0;
+ else if (FAT16(pmp))
+ cleanfat = 16;
+ else
+ cleanfat = 32;
for (i = 1; i < pmp->pm_FATs; i++) {
fatbn += pmp->pm_FATsecs;
/* getblk() never fails */
bpn = getblk(pmp->pm_devvp, fatbn, bp->b_bcount,
0, 0, 0);
bcopy(bp->b_data, bpn->b_data, bp->b_bcount);
- if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
+ /* Force the clean bit on in the other copies. */
+ if (cleanfat == 16)
+ ((u_int8_t *)bpn->b_data)[3] |= 0x80;
+ else if (cleanfat == 32)
+ ((u_int8_t *)bpn->b_data)[7] |= 0x08;
+ if (pmp->pm_mountp->mnt_flag & MNT_SYNCHRONOUS)
bwrite(bpn);
else
bdwrite(bpn);
@@ -378,7 +389,7 @@ updatefats(pmp, bp, fatbn)
/*
* Write out the first (or current) fat last.
*/
- if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
+ if (pmp->pm_mountp->mnt_flag & MNT_SYNCHRONOUS)
bwrite(bp);
else
bdwrite(bp);
@@ -1114,7 +1125,7 @@ extendfile(dep, count, bpp, ncp, flags)
* Routine to mark a FAT16 or FAT32 volume as "clean" or "dirty" by
* manipulating the upper bit of the FAT entry for cluster 1. Note that
* this bit is not defined for FAT12 volumes, which are always assumed to
- * be dirty.
+ * be clean.
*
* The fatentry() routine only works on cluster numbers that a file could
* occupy, so it won't manipulate the entry for cluster 1. So we have to do
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
index e99fff3..a209970 100644
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -553,8 +553,7 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp)
}
if (pmp->pm_RootDirEnts == 0) {
- if (pmp->pm_Sectors
- || pmp->pm_FATsecs
+ if (pmp->pm_FATsecs
|| getushort(b710->bpbFSVers)) {
error = EINVAL;
#ifdef MSDOSFS_DEBUG
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index a90ee8d..8e045cb 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -973,7 +973,7 @@ msdosfs_rename(ap)
u_char to_count;
int doingdirectory = 0, newparent = 0;
int error;
- u_long cn;
+ u_long cn, pcl;
daddr_t bn;
struct denode *fddep; /* from file's parent directory */
struct msdosfsmount *pmp;
@@ -1246,9 +1246,12 @@ abortit:
goto bad;
}
dotdotp = (struct direntry *)bp->b_data + 1;
- putushort(dotdotp->deStartCluster, dp->de_StartCluster);
+ pcl = dp->de_StartCluster;
+ if (FAT32(pmp) && pcl == pmp->pm_rootdirblk)
+ pcl = MSDOSFSROOT;
+ putushort(dotdotp->deStartCluster, pcl);
if (FAT32(pmp))
- putushort(dotdotp->deHighClust, dp->de_StartCluster >> 16);
+ putushort(dotdotp->deHighClust, pcl >> 16);
if (DOINGASYNC(fvp))
bdwrite(bp);
else if ((error = bwrite(bp)) != 0) {
@@ -1369,8 +1372,13 @@ msdosfs_mkdir(ap)
putushort(denp[0].deMDate, ndirent.de_MDate);
putushort(denp[0].deMTime, ndirent.de_MTime);
pcl = pdep->de_StartCluster;
+ /*
+ * Although the root directory has a non-magic starting cluster
+ * number for FAT32, chkdsk and fsck_msdosfs still require
+ * references to it in dotdot entries to be magic.
+ */
if (FAT32(pmp) && pcl == pmp->pm_rootdirblk)
- pcl = 0;
+ pcl = MSDOSFSROOT;
putushort(denp[1].deStartCluster, pcl);
putushort(denp[1].deCDate, ndirent.de_CDate);
putushort(denp[1].deCTime, ndirent.de_CTime);
@@ -1380,7 +1388,7 @@ msdosfs_mkdir(ap)
putushort(denp[1].deMTime, ndirent.de_MTime);
if (FAT32(pmp)) {
putushort(denp[0].deHighClust, newcluster >> 16);
- putushort(denp[1].deHighClust, pdep->de_StartCluster >> 16);
+ putushort(denp[1].deHighClust, pcl >> 16);
}
if (DOINGASYNC(ap->a_dvp))
diff --git a/sys/fs/nfs/nfs.h b/sys/fs/nfs/nfs.h
index 3cc8c8f..febb631 100644
--- a/sys/fs/nfs/nfs.h
+++ b/sys/fs/nfs/nfs.h
@@ -523,7 +523,6 @@ struct nfsrv_descript {
int *nd_errp; /* Pointer to ret status */
u_int32_t nd_retxid; /* Reply xid */
struct nfsrvcache *nd_rp; /* Assoc. cache entry */
- struct timeval nd_starttime; /* Time RPC initiated */
fhandle_t nd_fh; /* File handle */
struct ucred *nd_cred; /* Credentials */
uid_t nd_saveduid; /* Saved uid */
diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c
index 6640c1f..23d8954 100644
--- a/sys/fs/nfs/nfs_commonkrpc.c
+++ b/sys/fs/nfs/nfs_commonkrpc.c
@@ -459,18 +459,17 @@ nfs_feedback(int type, int proc, void *arg)
{
struct nfs_feedback_arg *nf = (struct nfs_feedback_arg *) arg;
struct nfsmount *nmp = nf->nf_mount;
- struct timeval now;
-
- getmicrouptime(&now);
+ time_t now;
switch (type) {
case FEEDBACK_REXMIT2:
case FEEDBACK_RECONNECT:
- if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now.tv_sec) {
+ now = NFSD_MONOSEC;
+ if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now) {
nfs_down(nmp, nf->nf_td,
"not responding", 0, NFSSTA_TIMEO);
nf->nf_tprintfmsg = TRUE;
- nf->nf_lastmsg = now.tv_sec;
+ nf->nf_lastmsg = now;
}
break;
@@ -501,7 +500,7 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
u_int16_t procnum;
u_int trylater_delay = 1;
struct nfs_feedback_arg nf;
- struct timeval timo, now;
+ struct timeval timo;
AUTH *auth;
struct rpc_callextra ext;
enum clnt_stat stat;
@@ -617,8 +616,7 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
bzero(&nf, sizeof(struct nfs_feedback_arg));
nf.nf_mount = nmp;
nf.nf_td = td;
- getmicrouptime(&now);
- nf.nf_lastmsg = now.tv_sec -
+ nf.nf_lastmsg = NFSD_MONOSEC -
((nmp->nm_tprintf_delay)-(nmp->nm_tprintf_initial_delay));
}
@@ -767,12 +765,18 @@ tryagain:
if (stat == RPC_SUCCESS) {
error = 0;
} else if (stat == RPC_TIMEDOUT) {
+ NFSINCRGLOBAL(newnfsstats.rpctimeouts);
error = ETIMEDOUT;
} else if (stat == RPC_VERSMISMATCH) {
+ NFSINCRGLOBAL(newnfsstats.rpcinvalid);
error = EOPNOTSUPP;
} else if (stat == RPC_PROGVERSMISMATCH) {
+ NFSINCRGLOBAL(newnfsstats.rpcinvalid);
error = EPROTONOSUPPORT;
+ } else if (stat == RPC_INTR) {
+ error = EINTR;
} else {
+ NFSINCRGLOBAL(newnfsstats.rpcinvalid);
error = EACCES;
}
if (error) {
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 95aa7bd..b2d74c7 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -218,6 +218,7 @@ nfsm_mbufuio(struct nfsrv_descript *nd, struct uio *uiop, int siz)
}
mbufcp = NFSMTOD(mp, caddr_t);
len = mbuf_len(mp);
+ KASSERT(len > 0, ("len %d", len));
}
xfer = (left > len) ? len : left;
#ifdef notdef
@@ -1998,7 +1999,6 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
struct statfs fs;
struct nfsfsinfo fsinf;
struct timespec temptime;
- struct timeval curtime;
NFSACL_T *aclp, *naclp = NULL;
#ifdef QUOTA
struct dqblk dqb;
@@ -2412,8 +2412,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
retnum += NFSX_V4TIME;
break;
case NFSATTRBIT_TIMEACCESSSET:
- NFSGETTIME(&curtime);
- if (vap->va_atime.tv_sec != curtime.tv_sec) {
+ if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME);
*tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT);
txdr_nfsv4time(&vap->va_atime, tl);
@@ -2442,8 +2441,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
retnum += NFSX_V4TIME;
break;
case NFSATTRBIT_TIMEMODIFYSET:
- NFSGETTIME(&curtime);
- if (vap->va_mtime.tv_sec != curtime.tv_sec) {
+ if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
NFSM_BUILD(tl, u_int32_t *, NFSX_V4SETTIME);
*tl++ = txdr_unsigned(NFSV4SATTRTIME_TOCLIENT);
txdr_nfsv4time(&vap->va_mtime, tl);
diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h
index 3f22b7a..ea04525 100644
--- a/sys/fs/nfs/nfsport.h
+++ b/sys/fs/nfs/nfsport.h
@@ -588,12 +588,6 @@ void nfsrvd_rcv(struct socket *, void *, int);
#define NCHNAMLEN 9999999
/*
- * Define these to use the time of day clock.
- */
-#define NFSGETTIME(t) (getmicrotime(t))
-#define NFSGETNANOTIME(t) (getnanotime(t))
-
-/*
* These macros are defined to initialize and set the timer routine.
*/
#define NFS_TIMERINIT \
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index 145ff63..1179eb5 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -726,7 +726,6 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,
u_int32_t *tl;
struct nfsv2_sattr *sp;
nfsattrbit_t attrbits;
- struct timeval curtime;
switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) {
case ND_NFSV2:
@@ -755,7 +754,6 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,
txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
break;
case ND_NFSV3:
- getmicrotime(&curtime);
if (vap->va_mode != (mode_t)VNOVAL) {
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
*tl++ = newnfs_true;
@@ -789,7 +787,7 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,
*tl = newnfs_false;
}
if (vap->va_atime.tv_sec != VNOVAL) {
- if (vap->va_atime.tv_sec != curtime.tv_sec) {
+ if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
txdr_nfsv3time(&vap->va_atime, tl);
@@ -802,7 +800,7 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,
*tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
}
if (vap->va_mtime.tv_sec != VNOVAL) {
- if (vap->va_mtime.tv_sec != curtime.tv_sec) {
+ if ((vap->va_vaflags & VA_UTIMES_NULL) == 0) {
NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
txdr_nfsv3time(&vap->va_mtime, tl);
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index be0476a..a89b907 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -1444,7 +1444,7 @@ nfsrpc_readrpc(vnode_t vp, struct uio *uiop, struct ucred *cred,
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
eof = fxdr_unsigned(int, *tl);
}
- NFSM_STRSIZ(retlen, rsize);
+ NFSM_STRSIZ(retlen, len);
error = nfsm_mbufuio(nd, uiop, retlen);
if (error)
goto nfsmout;
diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c
index 8b5acb9..a774103 100644
--- a/sys/fs/nfsclient/nfs_clstate.c
+++ b/sys/fs/nfsclient/nfs_clstate.c
@@ -2447,7 +2447,7 @@ nfscl_renewthread(struct nfsclclient *clp, NFSPROC_T *p)
u_int32_t clidrev;
int error, cbpathdown, islept, igotlock, ret, clearok;
uint32_t recover_done_time = 0;
- struct timespec mytime;
+ time_t mytime;
static time_t prevsec = 0;
struct nfscllockownerfh *lfhp, *nlfhp;
struct nfscllockownerfhhead lfh;
@@ -2720,9 +2720,9 @@ tryagain2:
* Call nfscl_cleanupkext() once per second to check for
* open/lock owners where the process has exited.
*/
- NFSGETNANOTIME(&mytime);
- if (prevsec != mytime.tv_sec) {
- prevsec = mytime.tv_sec;
+ mytime = NFSD_MONOSEC;
+ if (prevsec != mytime) {
+ prevsec = mytime;
nfscl_cleanupkext(clp, &lfh);
}
@@ -4611,7 +4611,7 @@ nfscl_delegmodtime(vnode_t vp)
}
dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
if (dp != NULL && (dp->nfsdl_flags & NFSCLDL_WRITE)) {
- NFSGETNANOTIME(&dp->nfsdl_modtime);
+ nanotime(&dp->nfsdl_modtime);
dp->nfsdl_flags |= NFSCLDL_MODTIMESET;
}
NFSUNLOCKCLSTATE();
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index 3a898f2..f778009 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -3247,7 +3247,7 @@ nfsfifo_read(struct vop_read_args *ap)
*/
mtx_lock(&np->n_mtx);
np->n_flag |= NACC;
- getnanotime(&np->n_atim);
+ vfs_timestamp(&np->n_atim);
mtx_unlock(&np->n_mtx);
error = fifo_specops.vop_read(ap);
return error;
@@ -3266,7 +3266,7 @@ nfsfifo_write(struct vop_write_args *ap)
*/
mtx_lock(&np->n_mtx);
np->n_flag |= NUPD;
- getnanotime(&np->n_mtim);
+ vfs_timestamp(&np->n_mtim);
mtx_unlock(&np->n_mtx);
return(fifo_specops.vop_write(ap));
}
@@ -3286,7 +3286,7 @@ nfsfifo_close(struct vop_close_args *ap)
mtx_lock(&np->n_mtx);
if (np->n_flag & (NACC | NUPD)) {
- getnanotime(&ts);
+ vfs_timestamp(&ts);
if (np->n_flag & NACC)
np->n_atim = ts;
if (np->n_flag & NUPD)
diff --git a/sys/fs/nfsserver/nfs_nfsdkrpc.c b/sys/fs/nfsserver/nfs_nfsdkrpc.c
index 337951b..cffb46f 100644
--- a/sys/fs/nfsserver/nfs_nfsdkrpc.c
+++ b/sys/fs/nfsserver/nfs_nfsdkrpc.c
@@ -310,7 +310,6 @@ nfs_proc(struct nfsrv_descript *nd, u_int32_t xid, struct socket *so,
} else {
isdgram = 1;
}
- NFSGETTIME(&nd->nd_starttime);
/*
* Two cases:
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index f56a292..1731c72 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -1476,7 +1476,7 @@ nfsvno_updfilerev(struct vnode *vp, struct nfsvattr *nvap,
struct vattr va;
VATTR_NULL(&va);
- getnanotime(&va.va_mtime);
+ vfs_timestamp(&va.va_mtime);
(void) VOP_SETATTR(vp, &va, cred);
(void) nfsvno_getattr(vp, nvap, cred, p, 1);
}
@@ -2248,7 +2248,6 @@ nfsrv_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
{
u_int32_t *tl;
struct nfsv2_sattr *sp;
- struct timeval curtime;
int error = 0, toclient = 0;
switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) {
@@ -2307,9 +2306,7 @@ nfsrv_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
toclient = 1;
break;
case NFSV3SATTRTIME_TOSERVER:
- NFSGETTIME(&curtime);
- nvap->na_atime.tv_sec = curtime.tv_sec;
- nvap->na_atime.tv_nsec = curtime.tv_usec * 1000;
+ vfs_timestamp(&nvap->na_atime);
nvap->na_vaflags |= VA_UTIMES_NULL;
break;
};
@@ -2321,9 +2318,7 @@ nfsrv_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
nvap->na_vaflags &= ~VA_UTIMES_NULL;
break;
case NFSV3SATTRTIME_TOSERVER:
- NFSGETTIME(&curtime);
- nvap->na_mtime.tv_sec = curtime.tv_sec;
- nvap->na_mtime.tv_nsec = curtime.tv_usec * 1000;
+ vfs_timestamp(&nvap->na_mtime);
if (!toclient)
nvap->na_vaflags |= VA_UTIMES_NULL;
break;
@@ -2353,7 +2348,6 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
u_char *cp, namestr[NFSV4_SMALLSTR + 1];
uid_t uid;
gid_t gid;
- struct timeval curtime;
error = nfsrv_getattrbits(nd, attrbitp, NULL, &retnotsup);
if (error)
@@ -2488,9 +2482,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
toclient = 1;
attrsum += NFSX_V4TIME;
} else {
- NFSGETTIME(&curtime);
- nvap->na_atime.tv_sec = curtime.tv_sec;
- nvap->na_atime.tv_nsec = curtime.tv_usec * 1000;
+ vfs_timestamp(&nvap->na_atime);
nvap->na_vaflags |= VA_UTIMES_NULL;
}
break;
@@ -2515,9 +2507,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
nvap->na_vaflags &= ~VA_UTIMES_NULL;
attrsum += NFSX_V4TIME;
} else {
- NFSGETTIME(&curtime);
- nvap->na_mtime.tv_sec = curtime.tv_sec;
- nvap->na_mtime.tv_nsec = curtime.tv_usec * 1000;
+ vfs_timestamp(&nvap->na_mtime);
if (!toclient)
nvap->na_vaflags |= VA_UTIMES_NULL;
}
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index 85fbbd2..307b1f6 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -55,6 +55,11 @@ extern int nfs_rootfhset;
extern int nfsrv_enable_crossmntpt;
#endif /* !APPLEKEXT */
+static int nfs_async = 0;
+SYSCTL_DECL(_vfs_nfsd);
+SYSCTL_INT(_vfs_nfsd, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0,
+ "Tell client that writes were synced even though they were not");
+
/*
* This list defines the GSS mechanisms supported.
* (Don't ask me how you get these strings from the RFC stuff like
@@ -912,7 +917,13 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int isdgram,
goto out;
NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(retlen);
- if (stable == NFSWRITE_UNSTABLE)
+ /*
+ * If nfs_async is set, then pretend the write was FILESYNC.
+ * Warning: Doing this violates RFC1813 and runs a risk
+ * of data written by a client being lost when the server
+ * crashes/reboots.
+ */
+ if (stable == NFSWRITE_UNSTABLE && nfs_async == 0)
*tl++ = txdr_unsigned(stable);
else
*tl++ = txdr_unsigned(NFSWRITE_FILESYNC);
diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c
index 8b2f8b8..d74a5a9 100644
--- a/sys/fs/nfsserver/nfs_nfsdstate.c
+++ b/sys/fs/nfsserver/nfs_nfsdstate.c
@@ -3967,7 +3967,6 @@ nfsrv_setupstable(NFSPROC_T *p)
int error, i, tryagain;
off_t off = 0;
ssize_t aresid, len;
- struct timeval curtime;
/*
* If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without
@@ -3978,8 +3977,7 @@ nfsrv_setupstable(NFSPROC_T *p)
/*
* Set Grace over just until the file reads successfully.
*/
- NFSGETTIME(&curtime);
- nfsrvboottime = curtime.tv_sec;
+ nfsrvboottime = time_second;
LIST_INIT(&sf->nsf_head);
sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK);
sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA;
@@ -4650,8 +4648,7 @@ out:
APPLESTATIC void
nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
{
- struct timespec mytime;
- int32_t starttime;
+ time_t starttime;
int error;
/*
@@ -4675,8 +4672,7 @@ nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
* Now, call nfsrv_checkremove() in a loop while it returns
* NFSERR_DELAY. Return upon any other error or when timed out.
*/
- NFSGETNANOTIME(&mytime);
- starttime = (u_int32_t)mytime.tv_sec;
+ starttime = NFSD_MONOSEC;
do {
if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
error = nfsrv_checkremove(vp, 0, p);
@@ -4684,11 +4680,7 @@ nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
} else
error = EPERM;
if (error == NFSERR_DELAY) {
- NFSGETNANOTIME(&mytime);
- if (((u_int32_t)mytime.tv_sec - starttime) >
- NFS_REMOVETIMEO &&
- ((u_int32_t)mytime.tv_sec - starttime) <
- 100000)
+ if (NFSD_MONOSEC - starttime > NFS_REMOVETIMEO)
break;
/* Sleep for a short period of time */
(void) nfs_catnap(PZERO, 0, "nfsremove");
@@ -4949,9 +4941,7 @@ nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp)
static time_t
nfsrv_leaseexpiry(void)
{
- struct timeval curtime;
- NFSGETTIME(&curtime);
if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC)
return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA));
return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA);
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index 0b72249..90e56ea 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -46,9 +46,6 @@
#include <fs/nullfs/null.h>
-#define LOG2_SIZEVNODE 8 /* log2(sizeof struct vnode) */
-#define NNULLNODECACHE 16
-
/*
* Null layer cache:
* Each cache entry holds a reference to the lower vnode
@@ -57,12 +54,11 @@
* alias is removed the lower vnode is vrele'd.
*/
-#define NULL_NHASH(vp) \
- (&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash])
+#define NULL_NHASH(vp) (&null_node_hashtbl[vfs_hash_index(vp) & null_hash_mask])
static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
-static u_long null_node_hash;
-struct mtx null_hashmtx;
+static struct mtx null_hashmtx;
+static u_long null_hash_mask;
static MALLOC_DEFINE(M_NULLFSHASH, "nullfs_hash", "NULLFS hash table");
MALLOC_DEFINE(M_NULLFSNODE, "nullfs_node", "NULLFS vnode private part");
@@ -77,8 +73,8 @@ nullfs_init(vfsp)
struct vfsconf *vfsp;
{
- NULLFSDEBUG("nullfs_init\n"); /* printed during system boot */
- null_node_hashtbl = hashinit(NNULLNODECACHE, M_NULLFSHASH, &null_node_hash);
+ null_node_hashtbl = hashinit(desiredvnodes, M_NULLFSHASH,
+ &null_hash_mask);
mtx_init(&null_hashmtx, "nullhs", NULL, MTX_DEF);
return (0);
}
@@ -89,7 +85,7 @@ nullfs_uninit(vfsp)
{
mtx_destroy(&null_hashmtx);
- hashdestroy(null_node_hashtbl, M_NULLFSHASH, null_node_hash);
+ hashdestroy(null_node_hashtbl, M_NULLFSHASH, null_hash_mask);
return (0);
}
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index 5abfa49..3724e0a 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -67,15 +67,6 @@ static vfs_vget_t nullfs_vget;
static vfs_extattrctl_t nullfs_extattrctl;
static vfs_reclaim_lowervp_t nullfs_reclaim_lowervp;
-/* Mount options that we support. */
-static const char *nullfs_opts[] = {
- "cache",
- "export",
- "from",
- "target",
- NULL
-};
-
/*
* Mount null layer
*/
@@ -97,8 +88,6 @@ nullfs_mount(struct mount *mp)
return (EPERM);
if (mp->mnt_flag & MNT_ROOTFS)
return (EOPNOTSUPP);
- if (vfs_filteropt(mp->mnt_optnew, nullfs_opts))
- return (EINVAL);
/*
* Update is a no-op
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index cc35d81..f59865f 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -740,6 +740,14 @@ null_reclaim(struct vop_reclaim_args *ap)
vp->v_object = NULL;
vp->v_vnlock = &vp->v_lock;
VI_UNLOCK(vp);
+
+ /*
+ * If we were opened for write, we leased one write reference
+ * to the lower vnode. If this is a reclamation due to the
+ * forced unmount, undo the reference now.
+ */
+ if (vp->v_writecount > 0)
+ VOP_ADD_WRITECOUNT(lowervp, -1);
vput(lowervp);
free(xp, M_NULLFSNODE);
diff --git a/sys/geom/journal/g_journal.c b/sys/geom/journal/g_journal.c
index 4581430..a3c996c 100644
--- a/sys/geom/journal/g_journal.c
+++ b/sys/geom/journal/g_journal.c
@@ -2976,7 +2976,7 @@ g_journal_do_switch(struct g_class *classp)
g_journal_switch_wait(sc);
mtx_unlock(&sc->sc_mtx);
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
next:
mtx_lock(&mountlist_mtx);
vfs_unbusy(mp);
diff --git a/sys/geom/mirror/g_mirror.c b/sys/geom/mirror/g_mirror.c
index 17271dd..0a8aeb0 100644
--- a/sys/geom/mirror/g_mirror.c
+++ b/sys/geom/mirror/g_mirror.c
@@ -81,7 +81,8 @@ SYSCTL_UINT(_kern_geom_mirror, OID_AUTO, sync_requests, CTLFLAG_RDTUN,
G_MIRROR_DEBUG(4, "%s: Woken up %p.", __func__, (ident)); \
} while (0)
-static eventhandler_tag g_mirror_pre_sync = NULL;
+static eventhandler_tag g_mirror_post_sync = NULL;
+static int g_mirror_shutdown = 0;
static int g_mirror_destroy_geom(struct gctl_req *req, struct g_class *mp,
struct g_geom *gp);
@@ -456,9 +457,7 @@ g_mirror_init_disk(struct g_mirror_softc *sc, struct g_provider *pp,
disk->d_priority = md->md_priority;
disk->d_flags = md->md_dflags;
error = g_getattr("GEOM::candelete", disk->d_consumer, &i);
- if (error != 0)
- goto fail;
- if (i)
+ if (error == 0 && i != 0)
disk->d_flags |= G_MIRROR_DISK_FLAG_CANDELETE;
if (md->md_provider[0] != '\0')
disk->d_flags |= G_MIRROR_DISK_FLAG_HARDCODED;
@@ -815,7 +814,7 @@ g_mirror_idle(struct g_mirror_softc *sc, int acw)
return (0);
if (acw > 0 || (acw == -1 && sc->sc_provider->acw > 0)) {
timeout = g_mirror_idletime - (time_uptime - sc->sc_last_write);
- if (timeout > 0)
+ if (!g_mirror_shutdown && timeout > 0)
return (timeout);
}
sc->sc_idle = 1;
@@ -2821,7 +2820,7 @@ g_mirror_access(struct g_provider *pp, int acr, int acw, int ace)
error = ENXIO;
goto end;
}
- if (dcw == 0 && !sc->sc_idle)
+ if (dcw == 0)
g_mirror_idle(sc, dcw);
if ((sc->sc_flags & G_MIRROR_DEVICE_FLAG_DESTROYING) != 0) {
if (acr > 0 || acw > 0 || ace > 0) {
@@ -3232,7 +3231,7 @@ g_mirror_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
}
static void
-g_mirror_shutdown_pre_sync(void *arg, int howto)
+g_mirror_shutdown_post_sync(void *arg, int howto)
{
struct g_class *mp;
struct g_geom *gp, *gp2;
@@ -3242,6 +3241,7 @@ g_mirror_shutdown_pre_sync(void *arg, int howto)
mp = arg;
DROP_GIANT();
g_topology_lock();
+ g_mirror_shutdown = 1;
LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
if ((sc = gp->softc) == NULL)
continue;
@@ -3250,6 +3250,7 @@ g_mirror_shutdown_pre_sync(void *arg, int howto)
continue;
g_topology_unlock();
sx_xlock(&sc->sc_lock);
+ g_mirror_idle(sc, -1);
g_cancel_event(sc);
error = g_mirror_destroy(sc, G_MIRROR_DESTROY_DELAYED);
if (error != 0)
@@ -3264,9 +3265,9 @@ static void
g_mirror_init(struct g_class *mp)
{
- g_mirror_pre_sync = EVENTHANDLER_REGISTER(shutdown_pre_sync,
- g_mirror_shutdown_pre_sync, mp, SHUTDOWN_PRI_FIRST);
- if (g_mirror_pre_sync == NULL)
+ g_mirror_post_sync = EVENTHANDLER_REGISTER(shutdown_post_sync,
+ g_mirror_shutdown_post_sync, mp, SHUTDOWN_PRI_FIRST);
+ if (g_mirror_post_sync == NULL)
G_MIRROR_DEBUG(0, "Warning! Cannot register shutdown event.");
}
@@ -3274,8 +3275,8 @@ static void
g_mirror_fini(struct g_class *mp)
{
- if (g_mirror_pre_sync != NULL)
- EVENTHANDLER_DEREGISTER(shutdown_pre_sync, g_mirror_pre_sync);
+ if (g_mirror_post_sync != NULL)
+ EVENTHANDLER_DEREGISTER(shutdown_post_sync, g_mirror_post_sync);
}
DECLARE_GEOM_CLASS(g_mirror_class, g_mirror);
diff --git a/sys/geom/raid/g_raid.c b/sys/geom/raid/g_raid.c
index 19b6d9b..91d14c3 100644
--- a/sys/geom/raid/g_raid.c
+++ b/sys/geom/raid/g_raid.c
@@ -163,6 +163,8 @@ g_raid_disk_state2str(int state)
return ("NONE");
case G_RAID_DISK_S_OFFLINE:
return ("OFFLINE");
+ case G_RAID_DISK_S_DISABLED:
+ return ("DISABLED");
case G_RAID_DISK_S_FAILED:
return ("FAILED");
case G_RAID_DISK_S_STALE_FAILED:
@@ -535,7 +537,9 @@ g_raid_report_disk_state(struct g_raid_disk *disk)
if (disk->d_consumer == NULL)
return;
- if (disk->d_state == G_RAID_DISK_S_FAILED ||
+ if (disk->d_state == G_RAID_DISK_S_DISABLED) {
+ s = G_STATE_ACTIVE; /* XXX */
+ } else if (disk->d_state == G_RAID_DISK_S_FAILED ||
disk->d_state == G_RAID_DISK_S_STALE_FAILED) {
s = G_STATE_FAILED;
} else {
diff --git a/sys/geom/raid/g_raid.h b/sys/geom/raid/g_raid.h
index 20b0822..183edff6 100644
--- a/sys/geom/raid/g_raid.h
+++ b/sys/geom/raid/g_raid.h
@@ -140,11 +140,12 @@ struct g_raid_event {
};
#define G_RAID_DISK_S_NONE 0x00 /* State is unknown. */
#define G_RAID_DISK_S_OFFLINE 0x01 /* Missing disk placeholder. */
-#define G_RAID_DISK_S_FAILED 0x02 /* Failed. */
-#define G_RAID_DISK_S_STALE_FAILED 0x03 /* Old failed. */
-#define G_RAID_DISK_S_SPARE 0x04 /* Hot-spare. */
-#define G_RAID_DISK_S_STALE 0x05 /* Old disk, unused now. */
-#define G_RAID_DISK_S_ACTIVE 0x06 /* Operational. */
+#define G_RAID_DISK_S_DISABLED 0x02 /* Disabled. */
+#define G_RAID_DISK_S_FAILED 0x03 /* Failed. */
+#define G_RAID_DISK_S_STALE_FAILED 0x04 /* Old failed. */
+#define G_RAID_DISK_S_SPARE 0x05 /* Hot-spare. */
+#define G_RAID_DISK_S_STALE 0x06 /* Old disk, unused now. */
+#define G_RAID_DISK_S_ACTIVE 0x07 /* Operational. */
#define G_RAID_DISK_E_DISCONNECTED 0x01
diff --git a/sys/geom/raid/md_intel.c b/sys/geom/raid/md_intel.c
index 12122b0..eeb42d5 100644
--- a/sys/geom/raid/md_intel.c
+++ b/sys/geom/raid/md_intel.c
@@ -98,6 +98,9 @@ struct intel_raid_vol {
uint8_t cng_master_disk;
uint16_t cache_policy;
uint8_t cng_state;
+#define INTEL_CNGST_UPDATED 0
+#define INTEL_CNGST_NEEDS_UPDATE 1
+#define INTEL_CNGST_MASTER_MISSING 2
uint8_t cng_sub_state;
uint32_t filler_0[10];
@@ -130,6 +133,7 @@ struct intel_raid_disk {
#define INTEL_F_ASSIGNED 0x02
#define INTEL_F_FAILED 0x04
#define INTEL_F_ONLINE 0x08
+#define INTEL_F_DISABLED 0x80
uint32_t owner_cfg_num;
uint32_t sectors_hi;
uint32_t filler[3];
@@ -162,18 +166,33 @@ struct intel_raid_conf {
#define INTEL_ATTR_RAID1E 0x00000008
#define INTEL_ATTR_RAID5 0x00000010
#define INTEL_ATTR_RAIDCNG 0x00000020
+#define INTEL_ATTR_EXT_STRIP 0x00000040
+#define INTEL_ATTR_NVM_CACHE 0x02000000
+#define INTEL_ATTR_2TB_DISK 0x04000000
+#define INTEL_ATTR_BBM 0x08000000
+#define INTEL_ATTR_NVM_CACHE2 0x10000000
#define INTEL_ATTR_2TB 0x20000000
#define INTEL_ATTR_PM 0x40000000
#define INTEL_ATTR_CHECKSUM 0x80000000
uint8_t total_disks;
uint8_t total_volumes;
- uint8_t dummy_2[2];
- uint32_t filler_0[39];
+ uint8_t error_log_pos;
+ uint8_t dummy_2[1];
+ uint32_t cache_size;
+ uint32_t orig_config_id;
+ uint32_t pwr_cycle_count;
+ uint32_t bbm_log_size;
+ uint32_t filler_0[35];
struct intel_raid_disk disk[1]; /* total_disks entries. */
/* Here goes total_volumes of struct intel_raid_vol. */
} __packed;
+#define INTEL_ATTR_SUPPORTED ( INTEL_ATTR_RAID0 | INTEL_ATTR_RAID1 | \
+ INTEL_ATTR_RAID10 | INTEL_ATTR_RAID1E | INTEL_ATTR_RAID5 | \
+ INTEL_ATTR_RAIDCNG | INTEL_ATTR_EXT_STRIP | INTEL_ATTR_2TB_DISK | \
+ INTEL_ATTR_2TB | INTEL_ATTR_PM | INTEL_ATTR_CHECKSUM )
+
#define INTEL_MAX_MD_SIZE(ndisks) \
(sizeof(struct intel_raid_conf) + \
sizeof(struct intel_raid_disk) * (ndisks - 1) + \
@@ -187,9 +206,17 @@ struct g_raid_md_intel_perdisk {
struct intel_raid_disk pd_disk_meta;
};
+struct g_raid_md_intel_pervolume {
+ int pv_volume_pos;
+ int pv_cng;
+ int pv_cng_man_sync;
+ int pv_cng_master_disk;
+};
+
struct g_raid_md_intel_object {
struct g_raid_md_object mdio_base;
uint32_t mdio_config_id;
+ uint32_t mdio_orig_config_id;
uint32_t mdio_generation;
struct intel_raid_conf *mdio_meta;
struct callout mdio_start_co; /* STARTING state timer. */
@@ -206,6 +233,7 @@ static g_raid_md_ctl_t g_raid_md_ctl_intel;
static g_raid_md_write_t g_raid_md_write_intel;
static g_raid_md_fail_disk_t g_raid_md_fail_disk_intel;
static g_raid_md_free_disk_t g_raid_md_free_disk_intel;
+static g_raid_md_free_volume_t g_raid_md_free_volume_intel;
static g_raid_md_free_t g_raid_md_free_intel;
static kobj_method_t g_raid_md_intel_methods[] = {
@@ -216,6 +244,7 @@ static kobj_method_t g_raid_md_intel_methods[] = {
KOBJMETHOD(g_raid_md_write, g_raid_md_write_intel),
KOBJMETHOD(g_raid_md_fail_disk, g_raid_md_fail_disk_intel),
KOBJMETHOD(g_raid_md_free_disk, g_raid_md_free_disk_intel),
+ KOBJMETHOD(g_raid_md_free_volume, g_raid_md_free_volume_intel),
KOBJMETHOD(g_raid_md_free, g_raid_md_free_intel),
{ 0, 0 }
};
@@ -354,29 +383,45 @@ g_raid_md_intel_print(struct intel_raid_conf *meta)
printf("config_size 0x%08x\n", meta->config_size);
printf("config_id 0x%08x\n", meta->config_id);
printf("generation 0x%08x\n", meta->generation);
+ printf("error_log_size %d\n", meta->error_log_size);
printf("attributes 0x%08x\n", meta->attributes);
printf("total_disks %u\n", meta->total_disks);
printf("total_volumes %u\n", meta->total_volumes);
- printf("DISK# serial disk_sectors disk_sectors_hi disk_id flags\n");
+ printf("error_log_pos %u\n", meta->error_log_pos);
+ printf("cache_size %u\n", meta->cache_size);
+ printf("orig_config_id 0x%08x\n", meta->orig_config_id);
+ printf("pwr_cycle_count %u\n", meta->pwr_cycle_count);
+ printf("bbm_log_size %u\n", meta->bbm_log_size);
+ printf("DISK# serial disk_sectors disk_sectors_hi disk_id flags owner\n");
for (i = 0; i < meta->total_disks; i++ ) {
- printf(" %d <%.16s> %u %u 0x%08x 0x%08x\n", i,
+ printf(" %d <%.16s> %u %u 0x%08x 0x%08x %08x\n", i,
meta->disk[i].serial, meta->disk[i].sectors,
- meta->disk[i].sectors_hi,
- meta->disk[i].id, meta->disk[i].flags);
+ meta->disk[i].sectors_hi, meta->disk[i].id,
+ meta->disk[i].flags, meta->disk[i].owner_cfg_num);
}
for (i = 0; i < meta->total_volumes; i++) {
mvol = intel_get_volume(meta, i);
printf(" ****** Volume %d ******\n", i);
printf(" name %.16s\n", mvol->name);
printf(" total_sectors %ju\n", mvol->total_sectors);
- printf(" state %u\n", mvol->state);
+ printf(" state 0x%08x\n", mvol->state);
printf(" reserved %u\n", mvol->reserved);
+ printf(" migr_priority %u\n", mvol->migr_priority);
+ printf(" num_sub_vols %u\n", mvol->num_sub_vols);
+ printf(" tid %u\n", mvol->tid);
+ printf(" cng_master_disk %u\n", mvol->cng_master_disk);
+ printf(" cache_policy %u\n", mvol->cache_policy);
+ printf(" cng_state %u\n", mvol->cng_state);
+ printf(" cng_sub_state %u\n", mvol->cng_sub_state);
printf(" curr_migr_unit %u\n", mvol->curr_migr_unit);
printf(" curr_migr_unit_hi %u\n", mvol->curr_migr_unit_hi);
printf(" checkpoint_id %u\n", mvol->checkpoint_id);
printf(" migr_state %u\n", mvol->migr_state);
printf(" migr_type %u\n", mvol->migr_type);
printf(" dirty %u\n", mvol->dirty);
+ printf(" fs_state %u\n", mvol->fs_state);
+ printf(" verify_errors %u\n", mvol->verify_errors);
+ printf(" bad_blocks %u\n", mvol->bad_blocks);
for (j = 0; j < (mvol->migr_state ? 2 : 1); j++) {
printf(" *** Map %d ***\n", j);
@@ -432,7 +477,7 @@ intel_meta_read(struct g_consumer *cp)
struct g_provider *pp;
struct intel_raid_conf *meta;
struct intel_raid_vol *mvol;
- struct intel_raid_map *mmap;
+ struct intel_raid_map *mmap, *mmap1;
char *buf;
int error, i, j, k, left, size;
uint32_t checksum, *ptr;
@@ -525,6 +570,23 @@ badsize:
}
}
+ g_raid_md_intel_print(meta);
+
+ if (strncmp(meta->version, INTEL_VERSION_1300, 6) > 0) {
+ G_RAID_DEBUG(1, "Intel unsupported version: '%.6s'",
+ meta->version);
+ free(meta, M_MD_INTEL);
+ return (NULL);
+ }
+
+ if (strncmp(meta->version, INTEL_VERSION_1300, 6) >= 0 &&
+ (meta->attributes & ~INTEL_ATTR_SUPPORTED) != 0) {
+ G_RAID_DEBUG(1, "Intel unsupported attributes: 0x%08x",
+ meta->attributes & ~INTEL_ATTR_SUPPORTED);
+ free(meta, M_MD_INTEL);
+ return (NULL);
+ }
+
/* Validate disk indexes. */
for (i = 0; i < meta->total_volumes; i++) {
mvol = intel_get_volume(meta, i);
@@ -547,16 +609,39 @@ badsize:
/* Validate migration types. */
for (i = 0; i < meta->total_volumes; i++) {
mvol = intel_get_volume(meta, i);
+ /* Deny unknown migration types. */
if (mvol->migr_state &&
mvol->migr_type != INTEL_MT_INIT &&
mvol->migr_type != INTEL_MT_REBUILD &&
mvol->migr_type != INTEL_MT_VERIFY &&
+ mvol->migr_type != INTEL_MT_GEN_MIGR &&
mvol->migr_type != INTEL_MT_REPAIR) {
G_RAID_DEBUG(1, "Intel metadata has unsupported"
" migration type %d", mvol->migr_type);
free(meta, M_MD_INTEL);
return (NULL);
}
+ /* Deny general migrations except SINGLE->RAID1. */
+ if (mvol->migr_state &&
+ mvol->migr_type == INTEL_MT_GEN_MIGR) {
+ mmap = intel_get_map(mvol, 0);
+ mmap1 = intel_get_map(mvol, 1);
+ if (mmap1->total_disks != 1 ||
+ mmap->type != INTEL_T_RAID1 ||
+ mmap->total_disks != 2 ||
+ mmap->offset != mmap1->offset ||
+ mmap->disk_sectors != mmap1->disk_sectors ||
+ mmap->total_domains != mmap->total_disks ||
+ mmap->offset_hi != mmap1->offset_hi ||
+ mmap->disk_sectors_hi != mmap1->disk_sectors_hi ||
+ (mmap->disk_idx[0] != mmap1->disk_idx[0] &&
+ mmap->disk_idx[0] != mmap1->disk_idx[1])) {
+ G_RAID_DEBUG(1, "Intel metadata has unsupported"
+ " variant of general migration");
+ free(meta, M_MD_INTEL);
+ return (NULL);
+ }
+ }
}
return (meta);
@@ -633,7 +718,7 @@ intel_meta_write_spare(struct g_consumer *cp, struct intel_raid_disk *d)
memcpy(&meta->version[0], INTEL_VERSION_1000,
sizeof(INTEL_VERSION_1000) - 1);
meta->config_size = INTEL_MAX_MD_SIZE(1);
- meta->config_id = arc4random();
+ meta->config_id = meta->orig_config_id = arc4random();
meta->generation = 1;
meta->total_disks = 1;
meta->disk[0] = *d;
@@ -699,9 +784,11 @@ static struct g_raid_volume *
g_raid_md_intel_get_volume(struct g_raid_softc *sc, int id)
{
struct g_raid_volume *mvol;
+ struct g_raid_md_intel_pervolume *pv;
TAILQ_FOREACH(mvol, &sc->sc_volumes, v_next) {
- if ((intptr_t)(mvol->v_md_data) == id)
+ pv = mvol->v_md_data;
+ if (pv->pv_volume_pos == id)
break;
}
return (mvol);
@@ -715,11 +802,12 @@ g_raid_md_intel_start_disk(struct g_raid_disk *disk)
struct g_raid_disk *olddisk, *tmpdisk;
struct g_raid_md_object *md;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd, *oldpd;
struct intel_raid_conf *meta;
struct intel_raid_vol *mvol;
struct intel_raid_map *mmap0, *mmap1;
- int disk_pos, resurrection = 0;
+ int disk_pos, resurrection = 0, migr_global, i;
sc = disk->d_softc;
md = sc->sc_md;
@@ -733,7 +821,8 @@ g_raid_md_intel_start_disk(struct g_raid_disk *disk)
if (disk_pos < 0) {
G_RAID_DEBUG1(1, sc, "Unknown, probably new or stale disk");
/* Failed stale disk is useless for us. */
- if (pd->pd_disk_meta.flags & INTEL_F_FAILED) {
+ if ((pd->pd_disk_meta.flags & INTEL_F_FAILED) &&
+ !(pd->pd_disk_meta.flags & INTEL_F_DISABLED)) {
g_raid_change_disk_state(disk, G_RAID_DISK_S_STALE_FAILED);
return (0);
}
@@ -824,7 +913,10 @@ nofit:
}
/* Welcome the new disk. */
- if (resurrection)
+ if ((meta->disk[disk_pos].flags & INTEL_F_DISABLED) &&
+ !(pd->pd_disk_meta.flags & INTEL_F_SPARE))
+ g_raid_change_disk_state(disk, G_RAID_DISK_S_DISABLED);
+ else if (resurrection)
g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
else if (meta->disk[disk_pos].flags & INTEL_F_FAILED)
g_raid_change_disk_state(disk, G_RAID_DISK_S_FAILED);
@@ -833,15 +925,27 @@ nofit:
else
g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
- mvol = intel_get_volume(meta,
- (uintptr_t)(sd->sd_volume->v_md_data));
+ pv = sd->sd_volume->v_md_data;
+ mvol = intel_get_volume(meta, pv->pv_volume_pos);
mmap0 = intel_get_map(mvol, 0);
if (mvol->migr_state)
mmap1 = intel_get_map(mvol, 1);
else
mmap1 = mmap0;
- if (resurrection) {
+ migr_global = 1;
+ for (i = 0; i < mmap0->total_disks; i++) {
+ if ((mmap0->disk_idx[i] & INTEL_DI_RBLD) == 0 &&
+ (mmap1->disk_idx[i] & INTEL_DI_RBLD) != 0)
+ migr_global = 0;
+ }
+
+ if ((meta->disk[disk_pos].flags & INTEL_F_DISABLED) &&
+ !(pd->pd_disk_meta.flags & INTEL_F_SPARE)) {
+ /* Disabled disk, useless. */
+ g_raid_change_subdisk_state(sd,
+ G_RAID_SUBDISK_S_NONE);
+ } else if (resurrection) {
/* Stale disk, almost same as new. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_NEW);
@@ -850,7 +954,8 @@ nofit:
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_FAILED);
} else if (mvol->migr_state == 0) {
- if (mmap0->status == INTEL_S_UNINITIALIZED) {
+ if (mmap0->status == INTEL_S_UNINITIALIZED &&
+ (!pv->pv_cng || pv->pv_cng_master_disk != disk_pos)) {
/* Freshly created uninitialized volume. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_UNINITIALIZED);
@@ -858,7 +963,8 @@ nofit:
/* Freshly inserted disk. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_NEW);
- } else if (mvol->dirty) {
+ } else if (mvol->dirty && (!pv->pv_cng ||
+ pv->pv_cng_master_disk != disk_pos)) {
/* Dirty volume (unclean shutdown). */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_STALE);
@@ -885,7 +991,13 @@ nofit:
sd->sd_volume->v_strip_size *
mmap0->total_domains;
}
- } else if (mvol->dirty) {
+ } else if (mvol->migr_type == INTEL_MT_INIT &&
+ migr_global) {
+ /* Freshly created uninitialized volume. */
+ g_raid_change_subdisk_state(sd,
+ G_RAID_SUBDISK_S_UNINITIALIZED);
+ } else if (mvol->dirty && (!pv->pv_cng ||
+ pv->pv_cng_master_disk != disk_pos)) {
/* Dirty volume (unclean shutdown). */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_STALE);
@@ -900,7 +1012,8 @@ nofit:
/* Freshly inserted disk. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_NEW);
- } else if (mmap1->disk_idx[sd->sd_pos] & INTEL_DI_RBLD) {
+ } else if ((mmap1->disk_idx[sd->sd_pos] & INTEL_DI_RBLD) ||
+ migr_global) {
/* Resyncing disk. */
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_RESYNC);
@@ -921,6 +1034,16 @@ nofit:
g_raid_change_subdisk_state(sd,
G_RAID_SUBDISK_S_ACTIVE);
}
+ } else if (mvol->migr_type == INTEL_MT_GEN_MIGR) {
+ if ((mmap1->disk_idx[0] & INTEL_DI_IDX) != disk_pos) {
+ /* Freshly inserted disk. */
+ g_raid_change_subdisk_state(sd,
+ G_RAID_SUBDISK_S_NEW);
+ } else {
+ /* Up to date disk. */
+ g_raid_change_subdisk_state(sd,
+ G_RAID_SUBDISK_S_ACTIVE);
+ }
}
g_raid_event_send(sd, G_RAID_SUBDISK_E_NEW,
G_RAID_EVENT_SUBDISK);
@@ -929,7 +1052,8 @@ nofit:
/* Update status of our need for spare. */
if (mdi->mdio_started) {
mdi->mdio_incomplete =
- (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) <
+ (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) +
+ g_raid_ndisks(sc, G_RAID_DISK_S_DISABLED) <
meta->total_disks);
}
@@ -961,7 +1085,8 @@ g_raid_md_intel_refill(struct g_raid_softc *sc)
update = 0;
do {
/* Make sure we miss anything. */
- na = g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE);
+ na = g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) +
+ g_raid_ndisks(sc, G_RAID_DISK_S_DISABLED);
if (na == meta->total_disks)
break;
@@ -973,7 +1098,8 @@ g_raid_md_intel_refill(struct g_raid_softc *sc)
TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
if (disk->d_state == G_RAID_DISK_S_STALE) {
update += g_raid_md_intel_start_disk(disk);
- if (disk->d_state == G_RAID_DISK_S_ACTIVE)
+ if (disk->d_state == G_RAID_DISK_S_ACTIVE ||
+ disk->d_state == G_RAID_DISK_S_DISABLED)
break;
}
}
@@ -997,8 +1123,8 @@ g_raid_md_intel_refill(struct g_raid_softc *sc)
}
/* Update status of our need for spare. */
- mdi->mdio_incomplete = (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) <
- meta->total_disks);
+ mdi->mdio_incomplete = (g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) +
+ g_raid_ndisks(sc, G_RAID_DISK_S_DISABLED) < meta->total_disks);
/* Request retaste hoping to find spare. */
if (mdi->mdio_incomplete) {
@@ -1014,6 +1140,7 @@ g_raid_md_intel_start(struct g_raid_softc *sc)
{
struct g_raid_md_object *md;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd;
struct intel_raid_conf *meta;
struct intel_raid_vol *mvol;
@@ -1031,8 +1158,14 @@ g_raid_md_intel_start(struct g_raid_softc *sc)
for (i = 0; i < meta->total_volumes; i++) {
mvol = intel_get_volume(meta, i);
mmap = intel_get_map(mvol, 0);
- vol = g_raid_create_volume(sc, mvol->name, -1);
- vol->v_md_data = (void *)(intptr_t)i;
+ vol = g_raid_create_volume(sc, mvol->name, mvol->tid - 1);
+ pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO);
+ pv->pv_volume_pos = i;
+ pv->pv_cng = (mvol->state & INTEL_ST_CLONE_N_GO) != 0;
+ pv->pv_cng_man_sync = (mvol->state & INTEL_ST_CLONE_MAN_SYNC) != 0;
+ if (mvol->cng_master_disk < mmap->total_disks)
+ pv->pv_cng_master_disk = mvol->cng_master_disk;
+ vol->v_md_data = pv;
vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_NONE;
if (mmap->type == INTEL_T_RAID0)
vol->v_raid_level = G_RAID_VOLUME_RL_RAID0;
@@ -1186,7 +1319,7 @@ g_raid_md_create_intel(struct g_raid_md_object *md, struct g_class *mp,
char name[16];
mdi = (struct g_raid_md_intel_object *)md;
- mdi->mdio_config_id = arc4random();
+ mdi->mdio_config_id = mdi->mdio_orig_config_id = arc4random();
mdi->mdio_generation = 0;
snprintf(name, sizeof(name), "Intel-%08x", mdi->mdio_config_id);
sc = g_raid_create_node(mp, name, md);
@@ -1294,8 +1427,6 @@ g_raid_md_taste_intel(struct g_raid_md_object *md, struct g_class *mp,
goto fail1;
}
- /* Metadata valid. Print it. */
- g_raid_md_intel_print(meta);
G_RAID_DEBUG(1, "Intel disk position %d", disk_pos);
spare = meta->disk[disk_pos].flags & INTEL_F_SPARE;
@@ -1333,6 +1464,7 @@ search:
} else { /* Not found matching node -- create one. */
result = G_RAID_MD_TASTE_NEW;
mdi->mdio_config_id = meta->config_id;
+ mdi->mdio_orig_config_id = meta->orig_config_id;
snprintf(name, sizeof(name), "Intel-%08x", meta->config_id);
sc = g_raid_create_node(mp, name, md);
md->mdo_softc = sc;
@@ -1450,6 +1582,7 @@ g_raid_md_ctl_intel(struct g_raid_md_object *md,
struct g_raid_subdisk *sd;
struct g_raid_disk *disk;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd;
struct g_consumer *cp;
struct g_provider *pp;
@@ -1621,7 +1754,9 @@ g_raid_md_ctl_intel(struct g_raid_md_object *md,
/* We have all we need, create things: volume, ... */
mdi->mdio_started = 1;
vol = g_raid_create_volume(sc, volname, -1);
- vol->v_md_data = (void *)(intptr_t)0;
+ pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO);
+ pv->pv_volume_pos = 0;
+ vol->v_md_data = pv;
vol->v_raid_level = level;
vol->v_raid_level_qualifier = qual;
vol->v_strip_size = strip;
@@ -1814,7 +1949,9 @@ g_raid_md_ctl_intel(struct g_raid_md_object *md,
/* We have all we need, create things: volume, ... */
vol = g_raid_create_volume(sc, volname, -1);
- vol->v_md_data = (void *)(intptr_t)i;
+ pv = malloc(sizeof(*pv), M_MD_INTEL, M_WAITOK | M_ZERO);
+ pv->pv_volume_pos = i;
+ vol->v_md_data = pv;
vol->v_raid_level = level;
vol->v_raid_level_qualifier = qual;
vol->v_strip_size = strip;
@@ -2105,6 +2242,7 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
struct g_raid_subdisk *sd;
struct g_raid_disk *disk;
struct g_raid_md_intel_object *mdi;
+ struct g_raid_md_intel_pervolume *pv;
struct g_raid_md_intel_perdisk *pd;
struct intel_raid_conf *meta;
struct intel_raid_vol *mvol;
@@ -2133,9 +2271,14 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
pd->pd_disk_meta.flags =
INTEL_F_ONLINE | INTEL_F_ASSIGNED;
} else if (disk->d_state == G_RAID_DISK_S_FAILED) {
- pd->pd_disk_meta.flags = INTEL_F_FAILED | INTEL_F_ASSIGNED;
+ pd->pd_disk_meta.flags = INTEL_F_FAILED |
+ INTEL_F_ASSIGNED;
+ } else if (disk->d_state == G_RAID_DISK_S_DISABLED) {
+ pd->pd_disk_meta.flags = INTEL_F_FAILED |
+ INTEL_F_ASSIGNED | INTEL_F_DISABLED;
} else {
- pd->pd_disk_meta.flags = INTEL_F_ASSIGNED;
+ if (!(pd->pd_disk_meta.flags & INTEL_F_DISABLED))
+ pd->pd_disk_meta.flags = INTEL_F_ASSIGNED;
if (pd->pd_disk_meta.id != 0xffffffff) {
pd->pd_disk_meta.id = 0xffffffff;
len = strlen(pd->pd_disk_meta.serial);
@@ -2151,6 +2294,7 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
memcpy(&meta->intel_id[0], INTEL_MAGIC, sizeof(INTEL_MAGIC) - 1);
meta->config_size = INTEL_MAX_MD_SIZE(numdisks);
meta->config_id = mdi->mdio_config_id;
+ meta->orig_config_id = mdi->mdio_orig_config_id;
meta->generation = mdi->mdio_generation;
meta->attributes = INTEL_ATTR_CHECKSUM;
meta->total_disks = numdisks;
@@ -2159,18 +2303,21 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
if (pd->pd_disk_pos < 0)
continue;
meta->disk[pd->pd_disk_pos] = pd->pd_disk_meta;
+ if (pd->pd_disk_meta.sectors_hi != 0)
+ meta->attributes |= INTEL_ATTR_2TB_DISK;
}
/* Fill volumes and maps. */
vi = 0;
version = INTEL_VERSION_1000;
TAILQ_FOREACH(vol, &sc->sc_volumes, v_next) {
+ pv = vol->v_md_data;
if (vol->v_stopping)
continue;
mvol = intel_get_volume(meta, vi);
/* New metadata may have different volumes order. */
- vol->v_md_data = (void *)(intptr_t)vi;
+ pv->pv_volume_pos = vi;
for (sdi = 0; sdi < vol->v_disks_count; sdi++) {
sd = &vol->v_subdisks[sdi];
@@ -2187,21 +2334,23 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
meta->attributes |= INTEL_ATTR_RAID1;
else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID5)
meta->attributes |= INTEL_ATTR_RAID5;
- else
+ else if ((vol->v_disks_count & 1) == 0)
meta->attributes |= INTEL_ATTR_RAID10;
-
- if (meta->attributes & INTEL_ATTR_2TB)
- cv = INTEL_VERSION_1300;
-// else if (dev->status == DEV_CLONE_N_GO)
-// cv = INTEL_VERSION_1206;
+ else
+ meta->attributes |= INTEL_ATTR_RAID1E;
+ if (pv->pv_cng)
+ meta->attributes |= INTEL_ATTR_RAIDCNG;
+ if (vol->v_strip_size > 131072)
+ meta->attributes |= INTEL_ATTR_EXT_STRIP;
+
+ if (pv->pv_cng)
+ cv = INTEL_VERSION_1206;
else if (vol->v_disks_count > 4)
cv = INTEL_VERSION_1204;
else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID5)
cv = INTEL_VERSION_1202;
else if (vol->v_disks_count > 2)
cv = INTEL_VERSION_1201;
- else if (vi > 0)
- cv = INTEL_VERSION_1200;
else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1)
cv = INTEL_VERSION_1100;
else
@@ -2211,6 +2360,22 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
strlcpy(&mvol->name[0], vol->v_name, sizeof(mvol->name));
mvol->total_sectors = vol->v_mediasize / sectorsize;
+ mvol->state = (INTEL_ST_READ_COALESCING |
+ INTEL_ST_WRITE_COALESCING);
+ mvol->tid = vol->v_global_id + 1;
+ if (pv->pv_cng) {
+ mvol->state |= INTEL_ST_CLONE_N_GO;
+ if (pv->pv_cng_man_sync)
+ mvol->state |= INTEL_ST_CLONE_MAN_SYNC;
+ mvol->cng_master_disk = pv->pv_cng_master_disk;
+ if (vol->v_subdisks[pv->pv_cng_master_disk].sd_state ==
+ G_RAID_SUBDISK_S_NONE)
+ mvol->cng_state = INTEL_CNGST_MASTER_MISSING;
+ else if (vol->v_state != G_RAID_VOLUME_S_OPTIMAL)
+ mvol->cng_state = INTEL_CNGST_NEEDS_UPDATE;
+ else
+ mvol->cng_state = INTEL_CNGST_UPDATED;
+ }
/* Check for any recovery in progress. */
state = G_RAID_SUBDISK_S_ACTIVE;
@@ -2305,7 +2470,8 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
mmap1->disk_idx[sdi] |= INTEL_DI_RBLD;
}
if ((sd->sd_state == G_RAID_SUBDISK_S_NONE ||
- sd->sd_state == G_RAID_SUBDISK_S_FAILED) &&
+ sd->sd_state == G_RAID_SUBDISK_S_FAILED ||
+ sd->sd_state == G_RAID_SUBDISK_S_REBUILD) &&
mmap0->failed_disk_num == 0xff) {
mmap0->failed_disk_num = sdi;
if (mvol->migr_state)
@@ -2315,7 +2481,10 @@ g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
vi++;
}
meta->total_volumes = vi;
- if (strcmp(version, INTEL_VERSION_1300) != 0)
+ if (vi > 1 || meta->attributes &
+ (INTEL_ATTR_EXT_STRIP | INTEL_ATTR_2TB_DISK | INTEL_ATTR_2TB))
+ version = INTEL_VERSION_1300;
+ if (strcmp(version, INTEL_VERSION_1300) < 0)
meta->attributes &= INTEL_ATTR_CHECKSUM;
memcpy(&meta->version[0], version, sizeof(INTEL_VERSION_1000) - 1);
@@ -2403,6 +2572,18 @@ g_raid_md_free_disk_intel(struct g_raid_md_object *md,
}
static int
+g_raid_md_free_volume_intel(struct g_raid_md_object *md,
+ struct g_raid_volume *vol)
+{
+ struct g_raid_md_intel_pervolume *pv;
+
+ pv = (struct g_raid_md_intel_pervolume *)vol->v_md_data;
+ free(pv, M_MD_INTEL);
+ vol->v_md_data = NULL;
+ return (0);
+}
+
+static int
g_raid_md_free_intel(struct g_raid_md_object *md)
{
struct g_raid_md_intel_object *mdi;
diff --git a/sys/geom/raid/md_promise.c b/sys/geom/raid/md_promise.c
index 5512b5a..0007b20 100644
--- a/sys/geom/raid/md_promise.c
+++ b/sys/geom/raid/md_promise.c
@@ -84,7 +84,7 @@ struct promise_raid_conf {
struct promise_raid_disk disk; /* This subdisk info. */
uint32_t disk_offset; /* Subdisk offset. */
uint32_t disk_sectors; /* Subdisk size */
- uint32_t rebuild_lba; /* Rebuild position. */
+ uint32_t disk_rebuild; /* Rebuild position. */
uint16_t generation; /* Generation number. */
uint8_t status; /* Volume status. */
#define PROMISE_S_VALID 0x01
@@ -123,7 +123,18 @@ struct promise_raid_conf {
uint32_t magic_4;
uint32_t magic_5;
uint32_t total_sectors_high;
- uint32_t filler3[324];
+ uint8_t magic_6;
+ uint8_t sector_size;
+ uint16_t magic_7;
+ uint32_t magic_8[31];
+ uint32_t backup_time;
+ uint16_t magic_9;
+ uint32_t disk_offset_high;
+ uint32_t disk_sectors_high;
+ uint32_t disk_rebuild_high;
+ uint16_t magic_10;
+ uint32_t magic_11[3];
+ uint32_t filler3[284];
uint32_t checksum;
} __packed;
@@ -191,7 +202,7 @@ g_raid_md_promise_print(struct promise_raid_conf *meta)
meta->disk.device, meta->disk.id);
printf("disk_offset %u\n", meta->disk_offset);
printf("disk_sectors %u\n", meta->disk_sectors);
- printf("rebuild_lba %u\n", meta->rebuild_lba);
+ printf("disk_rebuild %u\n", meta->disk_rebuild);
printf("generation %u\n", meta->generation);
printf("status 0x%02x\n", meta->status);
printf("type %u\n", meta->type);
@@ -217,6 +228,11 @@ g_raid_md_promise_print(struct promise_raid_conf *meta)
printf("magic_4 0x%08x\n", meta->magic_4);
printf("magic_5 0x%08x\n", meta->magic_5);
printf("total_sectors_high 0x%08x\n", meta->total_sectors_high);
+ printf("sector_size %u\n", meta->sector_size);
+ printf("backup_time %d\n", meta->backup_time);
+ printf("disk_offset_high 0x%08x\n", meta->disk_offset_high);
+ printf("disk_sectors_high 0x%08x\n", meta->disk_sectors_high);
+ printf("disk_rebuild_high 0x%08x\n", meta->disk_rebuild_high);
printf("=================================================\n");
}
@@ -244,9 +260,9 @@ promise_meta_find_disk(struct promise_raid_conf *meta, uint64_t id)
static int
promise_meta_unused_range(struct promise_raid_conf **metaarr, int nsd,
- uint32_t sectors, uint32_t *off, uint32_t *size)
+ off_t sectors, off_t *off, off_t *size)
{
- uint32_t coff, csize;
+ off_t coff, csize, tmp;
int i, j;
sectors -= 131072;
@@ -257,10 +273,10 @@ promise_meta_unused_range(struct promise_raid_conf **metaarr, int nsd,
i = 0;
while (1) {
for (j = 0; j < nsd; j++) {
- if (metaarr[j]->disk_offset >= coff) {
- csize = MIN(csize,
- metaarr[j]->disk_offset - coff);
- }
+ tmp = ((off_t)metaarr[j]->disk_offset_high << 32) +
+ metaarr[j]->disk_offset;
+ if (tmp >= coff)
+ csize = MIN(csize, tmp - coff);
}
if (csize > *size) {
*off = coff;
@@ -268,7 +284,10 @@ promise_meta_unused_range(struct promise_raid_conf **metaarr, int nsd,
}
if (i >= nsd)
break;
- coff = metaarr[i]->disk_offset + metaarr[i]->disk_sectors;
+ coff = ((off_t)metaarr[i]->disk_offset_high << 32) +
+ metaarr[i]->disk_offset +
+ ((off_t)metaarr[i]->disk_sectors_high << 32) +
+ metaarr[i]->disk_sectors;
csize = sectors - coff;
i++;
};
@@ -369,6 +388,26 @@ next:
return (subdisks);
}
+ /* Remove filler garbage from fields used in newer metadata. */
+ if (meta->disk_offset_high == 0x8b8c8d8e &&
+ meta->disk_sectors_high == 0x8788898a &&
+ meta->disk_rebuild_high == 0x83848586) {
+ meta->disk_offset_high = 0;
+ meta->disk_sectors_high = 0;
+ if (meta->disk_rebuild == UINT32_MAX)
+ meta->disk_rebuild_high = UINT32_MAX;
+ else
+ meta->disk_rebuild_high = 0;
+ if (meta->total_sectors_high == 0x15161718) {
+ meta->total_sectors_high = 0;
+ meta->backup_time = 0;
+ if (meta->rebuild_lba64 == 0x2122232425262728)
+ meta->rebuild_lba64 = UINT64_MAX;
+ }
+ }
+ if (meta->sector_size < 1 || meta->sector_size > 8)
+ meta->sector_size = 1;
+
/* Save this part and look for next. */
*metaarr = meta;
metaarr++;
@@ -386,8 +425,9 @@ promise_meta_write(struct g_consumer *cp,
struct g_provider *pp;
struct promise_raid_conf *meta;
char *buf;
+ off_t off, size;
int error, i, subdisk, fake;
- uint32_t checksum, *ptr, off, size;
+ uint32_t checksum, *ptr;
pp = cp->provider;
subdisk = 0;
@@ -409,9 +449,12 @@ next:
meta->disk.flags = PROMISE_F_ONLINE | PROMISE_F_VALID;
meta->disk.number = 0xff;
arc4rand(&meta->disk.id, sizeof(meta->disk.id), 0);
- meta->disk_offset = off;
- meta->disk_sectors = size;
- meta->rebuild_lba = UINT32_MAX;
+ meta->disk_offset_high = off >> 32;
+ meta->disk_offset = (uint32_t)off;
+ meta->disk_sectors_high = size >> 32;
+ meta->disk_sectors = (uint32_t)size;
+ meta->disk_rebuild_high = UINT32_MAX;
+ meta->disk_rebuild = UINT32_MAX;
fake = 1;
}
if (meta != NULL) {
@@ -464,6 +507,7 @@ static int
promise_meta_write_spare(struct g_consumer *cp)
{
struct promise_raid_conf *meta;
+ off_t tmp;
int error;
meta = malloc(sizeof(*meta), M_MD_PROMISE, M_WAITOK | M_ZERO);
@@ -473,9 +517,11 @@ promise_meta_write_spare(struct g_consumer *cp)
meta->disk.flags = PROMISE_F_SPARE | PROMISE_F_ONLINE | PROMISE_F_VALID;
meta->disk.number = 0xff;
arc4rand(&meta->disk.id, sizeof(meta->disk.id), 0);
- meta->disk_sectors = cp->provider->mediasize / cp->provider->sectorsize;
- meta->disk_sectors -= 131072;
- meta->rebuild_lba = UINT32_MAX;
+ tmp = cp->provider->mediasize / cp->provider->sectorsize - 131072;
+ meta->disk_sectors_high = tmp >> 32;
+ meta->disk_sectors = (uint32_t)tmp;
+ meta->disk_rebuild_high = UINT32_MAX;
+ meta->disk_rebuild = UINT32_MAX;
error = promise_meta_write(cp, &meta, 1);
free(meta, M_MD_PROMISE);
return (error);
@@ -617,9 +663,8 @@ g_raid_md_promise_start_disk(struct g_raid_disk *disk, int sdn,
struct g_raid_md_promise_perdisk *pd;
struct g_raid_md_promise_pervolume *pv;
struct promise_raid_conf *meta;
- off_t size;
+ off_t eoff, esize, size;
int disk_pos, md_disk_pos, i, resurrection = 0;
- uint32_t eoff, esize;
sc = disk->d_softc;
pd = (struct g_raid_md_promise_perdisk *)disk->d_md_data;
@@ -729,8 +774,10 @@ nofit:
sd->sd_offset = (off_t)eoff * 512;
sd->sd_size = (off_t)esize * 512;
} else {
- sd->sd_offset = (off_t)pd->pd_meta[sdn]->disk_offset * 512;
- sd->sd_size = (off_t)pd->pd_meta[sdn]->disk_sectors * 512;
+ sd->sd_offset = (((off_t)pd->pd_meta[sdn]->disk_offset_high
+ << 32) + pd->pd_meta[sdn]->disk_offset) * 512;
+ sd->sd_size = (((off_t)pd->pd_meta[sdn]->disk_sectors_high
+ << 32) + pd->pd_meta[sdn]->disk_sectors) * 512;
}
if (resurrection) {
@@ -749,7 +796,8 @@ nofit:
sd->sd_rebuild_pos = 0;
else {
sd->sd_rebuild_pos =
- (off_t)pd->pd_meta[sdn]->rebuild_lba * 512;
+ (((off_t)pd->pd_meta[sdn]->disk_rebuild_high << 32) +
+ pd->pd_meta[sdn]->disk_rebuild) * 512;
}
} else if (!(meta->disks[md_disk_pos].flags & PROMISE_F_ONLINE)) {
/* Rebuilding disk. */
@@ -875,13 +923,15 @@ g_raid_md_promise_start(struct g_raid_volume *vol)
vol->v_disks_count = meta->total_disks;
vol->v_mediasize = (off_t)meta->total_sectors * 512; //ZZZ
if (meta->total_sectors_high < 256) /* If value looks sane. */
- vol->v_mediasize |=
+ vol->v_mediasize +=
((off_t)meta->total_sectors_high << 32) * 512; //ZZZ
- vol->v_sectorsize = 512; //ZZZ
+ vol->v_sectorsize = 512 * meta->sector_size;
for (i = 0; i < vol->v_disks_count; i++) {
sd = &vol->v_subdisks[i];
- sd->sd_offset = (off_t)meta->disk_offset * 512; //ZZZ
- sd->sd_size = (off_t)meta->disk_sectors * 512; //ZZZ
+ sd->sd_offset = (((off_t)meta->disk_offset_high << 32) +
+ meta->disk_offset) * 512;
+ sd->sd_size = (((off_t)meta->disk_sectors_high << 32) +
+ meta->disk_sectors) * 512;
}
g_raid_start_volume(vol);
@@ -1213,9 +1263,8 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
const char *nodename, *verb, *volname, *levelname, *diskname;
char *tmp;
int *nargs, *force;
- off_t size, sectorsize, strip;
+ off_t esize, offs[PROMISE_MAX_DISKS], size, sectorsize, strip;
intmax_t *sizearg, *striparg;
- uint32_t offs[PROMISE_MAX_DISKS], esize;
int numdisks, i, len, level, qual;
int error;
@@ -1323,13 +1372,6 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
cp->private = disk;
g_topology_unlock();
- if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
- gctl_error(req,
- "Disk '%s' is too big.", diskname);
- error = -8;
- break;
- }
-
g_raid_get_disk_info(disk);
/* Reserve some space for metadata. */
@@ -1394,10 +1436,6 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
gctl_error(req, "Size too small.");
return (-13);
}
- if (size > 0xffffffffllu * sectorsize) {
- gctl_error(req, "Size too big.");
- return (-14);
- }
/* We have all we need, create things: volume, ... */
pv = malloc(sizeof(*pv), M_MD_PROMISE, M_WAITOK | M_ZERO);
@@ -1629,14 +1667,6 @@ g_raid_md_ctl_promise(struct g_raid_md_object *md,
pp = cp->provider;
g_topology_unlock();
- if (pp->mediasize / pp->sectorsize > UINT32_MAX) {
- gctl_error(req,
- "Disk '%s' is too big.", diskname);
- g_raid_kill_consumer(sc, cp);
- error = -8;
- break;
- }
-
pd = malloc(sizeof(*pd), M_MD_PROMISE, M_WAITOK | M_ZERO);
disk = g_raid_create_disk(sc);
@@ -1733,9 +1763,9 @@ g_raid_md_write_promise(struct g_raid_md_object *md, struct g_raid_volume *tvol,
vol->v_raid_level == G_RAID_VOLUME_RL_RAID1E)
meta->array_width /= 2;
meta->array_number = vol->v_global_id;
- meta->total_sectors = vol->v_mediasize / vol->v_sectorsize;
- meta->total_sectors_high =
- (vol->v_mediasize / vol->v_sectorsize) >> 32;
+ meta->total_sectors = vol->v_mediasize / 512;
+ meta->total_sectors_high = (vol->v_mediasize / 512) >> 32;
+ meta->sector_size = vol->v_sectorsize / 512;
meta->cylinders = meta->total_sectors / (255 * 63) - 1;
meta->heads = 254;
meta->sectors = 63;
@@ -1828,15 +1858,24 @@ g_raid_md_write_promise(struct g_raid_md_object *md, struct g_raid_volume *tvol,
pd->pd_meta[j] = promise_meta_copy(meta);
pd->pd_meta[j]->disk = meta->disks[pos];
pd->pd_meta[j]->disk.number = pos;
+ pd->pd_meta[j]->disk_offset_high =
+ (sd->sd_offset / 512) >> 32;
pd->pd_meta[j]->disk_offset = sd->sd_offset / 512;
+ pd->pd_meta[j]->disk_sectors_high =
+ (sd->sd_size / 512) >> 32;
pd->pd_meta[j]->disk_sectors = sd->sd_size / 512;
if (sd->sd_state == G_RAID_SUBDISK_S_REBUILD) {
- pd->pd_meta[j]->rebuild_lba =
+ pd->pd_meta[j]->disk_rebuild_high =
+ (sd->sd_rebuild_pos / 512) >> 32;
+ pd->pd_meta[j]->disk_rebuild =
sd->sd_rebuild_pos / 512;
- } else if (sd->sd_state < G_RAID_SUBDISK_S_REBUILD)
- pd->pd_meta[j]->rebuild_lba = 0;
- else
- pd->pd_meta[j]->rebuild_lba = UINT32_MAX;
+ } else if (sd->sd_state < G_RAID_SUBDISK_S_REBUILD) {
+ pd->pd_meta[j]->disk_rebuild_high = 0;
+ pd->pd_meta[j]->disk_rebuild = 0;
+ } else {
+ pd->pd_meta[j]->disk_rebuild_high = UINT32_MAX;
+ pd->pd_meta[j]->disk_rebuild = UINT32_MAX;
+ }
pd->pd_updated = 1;
}
}
diff --git a/sys/geom/raid/tr_concat.c b/sys/geom/raid/tr_concat.c
index f3935d7..60db472 100644
--- a/sys/geom/raid/tr_concat.c
+++ b/sys/geom/raid/tr_concat.c
@@ -124,7 +124,8 @@ g_raid_tr_update_state_concat(struct g_raid_volume *vol)
* Some metadata modules may not know CONCAT volume
* mediasize until all disks connected. Recalculate.
*/
- if (G_RAID_VOLUME_S_ALIVE(s) &&
+ if (vol->v_raid_level == G_RAID_VOLUME_RL_CONCAT &&
+ G_RAID_VOLUME_S_ALIVE(s) &&
!G_RAID_VOLUME_S_ALIVE(vol->v_state)) {
size = 0;
for (i = 0; i < vol->v_disks_count; i++) {
diff --git a/sys/geom/raid3/g_raid3.c b/sys/geom/raid3/g_raid3.c
index 711e9e1..927cb31 100644
--- a/sys/geom/raid3/g_raid3.c
+++ b/sys/geom/raid3/g_raid3.c
@@ -104,7 +104,8 @@ SYSCTL_UINT(_kern_geom_raid3_stat, OID_AUTO, parity_mismatch, CTLFLAG_RD,
G_RAID3_DEBUG(4, "%s: Woken up %p.", __func__, (ident)); \
} while (0)
-static eventhandler_tag g_raid3_pre_sync = NULL;
+static eventhandler_tag g_raid3_post_sync = NULL;
+static int g_raid3_shutdown = 0;
static int g_raid3_destroy_geom(struct gctl_req *req, struct g_class *mp,
struct g_geom *gp);
@@ -876,7 +877,7 @@ g_raid3_idle(struct g_raid3_softc *sc, int acw)
return (0);
if (acw > 0 || (acw == -1 && sc->sc_provider->acw > 0)) {
timeout = g_raid3_idletime - (time_uptime - sc->sc_last_write);
- if (timeout > 0)
+ if (!g_raid3_shutdown && timeout > 0)
return (timeout);
}
sc->sc_idle = 1;
@@ -3098,7 +3099,7 @@ g_raid3_access(struct g_provider *pp, int acr, int acw, int ace)
error = ENXIO;
goto end;
}
- if (dcw == 0 && !sc->sc_idle)
+ if (dcw == 0)
g_raid3_idle(sc, dcw);
if ((sc->sc_flags & G_RAID3_DEVICE_FLAG_DESTROYING) != 0) {
if (acr > 0 || acw > 0 || ace > 0) {
@@ -3544,7 +3545,7 @@ g_raid3_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
}
static void
-g_raid3_shutdown_pre_sync(void *arg, int howto)
+g_raid3_shutdown_post_sync(void *arg, int howto)
{
struct g_class *mp;
struct g_geom *gp, *gp2;
@@ -3554,6 +3555,7 @@ g_raid3_shutdown_pre_sync(void *arg, int howto)
mp = arg;
DROP_GIANT();
g_topology_lock();
+ g_raid3_shutdown = 1;
LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
if ((sc = gp->softc) == NULL)
continue;
@@ -3562,6 +3564,7 @@ g_raid3_shutdown_pre_sync(void *arg, int howto)
continue;
g_topology_unlock();
sx_xlock(&sc->sc_lock);
+ g_raid3_idle(sc, -1);
g_cancel_event(sc);
error = g_raid3_destroy(sc, G_RAID3_DESTROY_DELAYED);
if (error != 0)
@@ -3576,9 +3579,9 @@ static void
g_raid3_init(struct g_class *mp)
{
- g_raid3_pre_sync = EVENTHANDLER_REGISTER(shutdown_pre_sync,
- g_raid3_shutdown_pre_sync, mp, SHUTDOWN_PRI_FIRST);
- if (g_raid3_pre_sync == NULL)
+ g_raid3_post_sync = EVENTHANDLER_REGISTER(shutdown_post_sync,
+ g_raid3_shutdown_post_sync, mp, SHUTDOWN_PRI_FIRST);
+ if (g_raid3_post_sync == NULL)
G_RAID3_DEBUG(0, "Warning! Cannot register shutdown event.");
}
@@ -3586,8 +3589,8 @@ static void
g_raid3_fini(struct g_class *mp)
{
- if (g_raid3_pre_sync != NULL)
- EVENTHANDLER_DEREGISTER(shutdown_pre_sync, g_raid3_pre_sync);
+ if (g_raid3_post_sync != NULL)
+ EVENTHANDLER_DEREGISTER(shutdown_post_sync, g_raid3_post_sync);
}
DECLARE_GEOM_CLASS(g_raid3_class, g_raid3);
diff --git a/sys/geom/raid3/g_raid3_ctl.c b/sys/geom/raid3/g_raid3_ctl.c
index 952ac2b..b3a42ff 100644
--- a/sys/geom/raid3/g_raid3_ctl.c
+++ b/sys/geom/raid3/g_raid3_ctl.c
@@ -404,7 +404,7 @@ g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp)
u_char *sector;
off_t compsize;
intmax_t *no;
- int *hardcode, *nargs, error;
+ int *hardcode, *nargs, error, autono;
nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
if (nargs == NULL) {
@@ -425,11 +425,10 @@ g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp)
gctl_error(req, "No 'arg%u' argument.", 1);
return;
}
- no = gctl_get_paraml(req, "number", sizeof(*no));
- if (no == NULL) {
- gctl_error(req, "No '%s' argument.", "no");
- return;
- }
+ if (gctl_get_param(req, "number", NULL) != NULL)
+ no = gctl_get_paraml(req, "number", sizeof(*no));
+ else
+ no = NULL;
if (strncmp(name, "/dev/", 5) == 0)
name += 5;
g_topology_lock();
@@ -465,16 +464,30 @@ g_raid3_ctl_insert(struct gctl_req *req, struct g_class *mp)
gctl_error(req, "No such device: %s.", name);
goto end;
}
- if (*no >= sc->sc_ndisks) {
- sx_xunlock(&sc->sc_lock);
- gctl_error(req, "Invalid component number.");
- goto end;
- }
- disk = &sc->sc_disks[*no];
- if (disk->d_state != G_RAID3_DISK_STATE_NODISK) {
- sx_xunlock(&sc->sc_lock);
- gctl_error(req, "Component %jd is already connected.", *no);
- goto end;
+ if (no != NULL) {
+ if (*no < 0 || *no >= sc->sc_ndisks) {
+ sx_xunlock(&sc->sc_lock);
+ gctl_error(req, "Invalid component number.");
+ goto end;
+ }
+ disk = &sc->sc_disks[*no];
+ if (disk->d_state != G_RAID3_DISK_STATE_NODISK) {
+ sx_xunlock(&sc->sc_lock);
+ gctl_error(req, "Component %jd is already connected.",
+ *no);
+ goto end;
+ }
+ } else {
+ disk = NULL;
+ for (autono = 0; autono < sc->sc_ndisks && disk == NULL; autono++)
+ if (sc->sc_disks[autono].d_state ==
+ G_RAID3_DISK_STATE_NODISK)
+ disk = &sc->sc_disks[autono];
+ if (disk == NULL) {
+ sx_xunlock(&sc->sc_lock);
+ gctl_error(req, "No disconnected components.");
+ goto end;
+ }
}
if (((sc->sc_sectorsize / (sc->sc_ndisks - 1)) % pp->sectorsize) != 0) {
sx_xunlock(&sc->sc_lock);
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index 3a808ba..47af43b 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -208,7 +208,6 @@ device uart # Generic UART driver
device ppc
device ppbus # Parallel port bus (required)
device lpt # Printer
-device plip # TCP/IP over parallel
device ppi # Parallel port interface device
#device vpo # Requires scbus and da
@@ -346,3 +345,11 @@ device snd_via8233 # VIA VT8233x Audio
device mmc # MMC/SD bus
device mmcsd # MMC/SD memory card
device sdhci # Generic PCI SD Host Controller
+
+# VirtIO support
+device virtio # Generic VirtIO bus (required)
+device virtio_pci # VirtIO PCI device
+device vtnet # VirtIO Ethernet device
+device virtio_blk # VirtIO Block device
+device virtio_scsi # VirtIO SCSI device
+device virtio_balloon # VirtIO Memory Balloon device
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 1868595..95ccd4e 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -771,6 +771,15 @@ device glxiic # AMD Geode LX CS5536 System Management Bus
#
device glxsb # AMD Geode LX Security Block
+#
+# VirtIO support
+device virtio # Generic VirtIO bus (required)
+device virtio_pci # VirtIO PCI Interface
+device vtnet # VirtIO Ethernet device
+device virtio_blk # VirtIO Block device
+device virtio_scsi # VirtIO SCSI device
+device virtio_balloon # VirtIO Memory Balloon device
+
#####################################################################
#
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index 89c0430..a7046d8 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -1528,11 +1528,11 @@ cpususpend_handler(void)
while (!CPU_ISSET(cpu, &started_cpus))
ia32_pause();
- CPU_CLR_ATOMIC(cpu, &started_cpus);
-
/* Resume MCA and local APIC */
mca_resume();
lapic_setup(0);
+
+ CPU_CLR_ATOMIC(cpu, &started_cpus);
}
/*
* This is called once the rest of the system is up and running and we're
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index d719e80..f6ce067 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -96,6 +96,7 @@ __FBSDID("$FreeBSD$");
* and to when physical maps must be made correct.
*/
+#include "opt_apic.h"
#include "opt_cpu.h"
#include "opt_pmap.h"
#include "opt_smp.h"
@@ -135,6 +136,11 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_reserv.h>
#include <vm/uma.h>
+#ifdef DEV_APIC
+#include <sys/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/apicvar.h>
+#endif
#include <machine/cpu.h>
#include <machine/cputypes.h>
#include <machine/md_var.h>
@@ -1176,6 +1182,16 @@ pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva)
else if ((cpu_feature & CPUID_CLFSH) != 0 &&
eva - sva < PMAP_CLFLUSH_THRESHOLD) {
+#ifdef DEV_APIC
+ /*
+ * XXX: Some CPUs fault, hang, or trash the local APIC
+ * registers if we use CLFLUSH on the local APIC
+ * range. The local APIC is always uncached, so we
+ * don't need to flush for that range anyway.
+ */
+ if (pmap_kextract(sva) == lapic_paddr)
+ return;
+#endif
/*
* Otherwise, do per-cache line flush. Use the mfence
* instruction to insure that previous stores are
diff --git a/sys/i386/include/intr_machdep.h b/sys/i386/include/intr_machdep.h
index 004ed52..b3dd122 100644
--- a/sys/i386/include/intr_machdep.h
+++ b/sys/i386/include/intr_machdep.h
@@ -94,7 +94,7 @@ struct pic {
int (*pic_config_intr)(struct intsrc *, enum intr_trigger,
enum intr_polarity);
int (*pic_assign_cpu)(struct intsrc *, u_int apic_id);
- STAILQ_ENTRY(pic) pics;
+ TAILQ_ENTRY(pic) pics;
};
/* Flags for pic_disable_source() */
diff --git a/sys/i386/include/vmparam.h b/sys/i386/include/vmparam.h
index 9cfd692..f974495 100644
--- a/sys/i386/include/vmparam.h
+++ b/sys/i386/include/vmparam.h
@@ -206,9 +206,4 @@
#define VM_MAX_AUTOTUNE_MAXUSERS 384
#endif
-#ifndef VM_MAX_AUTOTUNE_NMBCLUSTERS
-/* old maxusers max value. */
-#define VM_MAX_AUTOTUNE_NMBCLUSTERS (1024 + VM_MAX_AUTOTUNE_MAXUSERS * 64)
-#endif
-
#endif /* _MACHINE_VMPARAM_H_ */
diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h
index 799259c..87d419f 100644
--- a/sys/i386/linux/linux.h
+++ b/sys/i386/linux/linux.h
@@ -101,11 +101,6 @@ typedef struct {
/*
* Miscellaneous
*/
-#define LINUX_NAME_MAX 255
-#define LINUX_MAX_UTSNAME 65
-
-#define LINUX_CTL_MAXNAME 10
-
#define LINUX_AT_COUNT 16 /* Count of used aux entry types.
* Keep this synchronized with
* elf_linux_fixup() code.
@@ -121,11 +116,6 @@ struct l___sysctl_args
l_ulong __spare[4];
};
-/* Scheduling policies */
-#define LINUX_SCHED_OTHER 0
-#define LINUX_SCHED_FIFO 1
-#define LINUX_SCHED_RR 2
-
/* Resource limits */
#define LINUX_RLIMIT_CPU 0
#define LINUX_RLIMIT_FSIZE 1
@@ -240,15 +230,6 @@ struct l_statfs64 {
l_int f_spare[6];
};
-struct l_new_utsname {
- char sysname[LINUX_MAX_UTSNAME];
- char nodename[LINUX_MAX_UTSNAME];
- char release[LINUX_MAX_UTSNAME];
- char version[LINUX_MAX_UTSNAME];
- char machine[LINUX_MAX_UTSNAME];
- char domainname[LINUX_MAX_UTSNAME];
-};
-
/*
* Signalling
*/
@@ -510,28 +491,10 @@ struct l_rt_sigframe {
l_handler_t sf_handler;
};
-extern int bsd_to_linux_signal[];
-extern int linux_to_bsd_signal[];
extern struct sysentvec linux_sysvec;
extern struct sysentvec elf_linux_sysvec;
/*
- * Pluggable ioctl handlers
- */
-struct linux_ioctl_args;
-struct thread;
-
-typedef int linux_ioctl_function_t(struct thread *, struct linux_ioctl_args *);
-
-struct linux_ioctl_handler {
- linux_ioctl_function_t *func;
- int low, high;
-};
-
-int linux_ioctl_register_handler(struct linux_ioctl_handler *h);
-int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
-
-/*
* open/fcntl flags
*/
#define LINUX_O_RDONLY 00000000
@@ -573,65 +536,6 @@ int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
#define LINUX_F_WRLCK 1
#define LINUX_F_UNLCK 2
-/*
- * posix_fadvise advice
- */
-#define LINUX_POSIX_FADV_NORMAL 0
-#define LINUX_POSIX_FADV_RANDOM 1
-#define LINUX_POSIX_FADV_SEQUENTIAL 2
-#define LINUX_POSIX_FADV_WILLNEED 3
-#define LINUX_POSIX_FADV_DONTNEED 4
-#define LINUX_POSIX_FADV_NOREUSE 5
-
-/*
- * mount flags
- */
-#define LINUX_MS_RDONLY 0x0001
-#define LINUX_MS_NOSUID 0x0002
-#define LINUX_MS_NODEV 0x0004
-#define LINUX_MS_NOEXEC 0x0008
-#define LINUX_MS_REMOUNT 0x0020
-
-/*
- * SystemV IPC defines
- */
-#define LINUX_SEMOP 1
-#define LINUX_SEMGET 2
-#define LINUX_SEMCTL 3
-#define LINUX_MSGSND 11
-#define LINUX_MSGRCV 12
-#define LINUX_MSGGET 13
-#define LINUX_MSGCTL 14
-#define LINUX_SHMAT 21
-#define LINUX_SHMDT 22
-#define LINUX_SHMGET 23
-#define LINUX_SHMCTL 24
-
-#define LINUX_IPC_RMID 0
-#define LINUX_IPC_SET 1
-#define LINUX_IPC_STAT 2
-#define LINUX_IPC_INFO 3
-
-#define LINUX_SHM_LOCK 11
-#define LINUX_SHM_UNLOCK 12
-#define LINUX_SHM_STAT 13
-#define LINUX_SHM_INFO 14
-
-#define LINUX_SHM_RDONLY 0x1000
-#define LINUX_SHM_RND 0x2000
-#define LINUX_SHM_REMAP 0x4000
-
-/* semctl commands */
-#define LINUX_GETPID 11
-#define LINUX_GETVAL 12
-#define LINUX_GETALL 13
-#define LINUX_GETNCNT 14
-#define LINUX_GETZCNT 15
-#define LINUX_SETVAL 16
-#define LINUX_SETALL 17
-#define LINUX_SEM_STAT 18
-#define LINUX_SEM_INFO 19
-
union l_semun {
l_int val;
struct l_semid_ds *buf;
@@ -643,25 +547,6 @@ union l_semun {
/*
* Socket defines
*/
-#define LINUX_SOCKET 1
-#define LINUX_BIND 2
-#define LINUX_CONNECT 3
-#define LINUX_LISTEN 4
-#define LINUX_ACCEPT 5
-#define LINUX_GETSOCKNAME 6
-#define LINUX_GETPEERNAME 7
-#define LINUX_SOCKETPAIR 8
-#define LINUX_SEND 9
-#define LINUX_RECV 10
-#define LINUX_SENDTO 11
-#define LINUX_RECVFROM 12
-#define LINUX_SHUTDOWN 13
-#define LINUX_SETSOCKOPT 14
-#define LINUX_GETSOCKOPT 15
-#define LINUX_SENDMSG 16
-#define LINUX_RECVMSG 17
-#define LINUX_ACCEPT4 18
-
#define LINUX_SOL_SOCKET 1
#define LINUX_SOL_IP 0
#define LINUX_SOL_IPX 256
@@ -690,17 +575,6 @@ union l_semun {
#define LINUX_SO_TIMESTAMP 29
#define LINUX_SO_ACCEPTCONN 30
-#define LINUX_IP_TOS 1
-#define LINUX_IP_TTL 2
-#define LINUX_IP_HDRINCL 3
-#define LINUX_IP_OPTIONS 4
-
-#define LINUX_IP_MULTICAST_IF 32
-#define LINUX_IP_MULTICAST_TTL 33
-#define LINUX_IP_MULTICAST_LOOP 34
-#define LINUX_IP_ADD_MEMBERSHIP 35
-#define LINUX_IP_DROP_MEMBERSHIP 36
-
struct l_sockaddr {
l_ushort sa_family;
char sa_data[14];
@@ -860,30 +734,6 @@ struct l_desc_struct {
#define LINUX_GET_USEABLE(desc) \
(((desc)->b >> LINUX_ENTRY_B_USEABLE) & 1)
-#define LINUX_CLOCK_REALTIME 0
-#define LINUX_CLOCK_MONOTONIC 1
-#define LINUX_CLOCK_PROCESS_CPUTIME_ID 2
-#define LINUX_CLOCK_THREAD_CPUTIME_ID 3
-#define LINUX_CLOCK_REALTIME_HR 4
-#define LINUX_CLOCK_MONOTONIC_HR 5
-
-#define LINUX_CLONE_VM 0x00000100
-#define LINUX_CLONE_FS 0x00000200
-#define LINUX_CLONE_FILES 0x00000400
-#define LINUX_CLONE_SIGHAND 0x00000800
-#define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */
-#define LINUX_CLONE_VFORK 0x00004000
-#define LINUX_CLONE_PARENT 0x00008000
-#define LINUX_CLONE_THREAD 0x00010000
-#define LINUX_CLONE_SETTLS 0x00080000
-#define LINUX_CLONE_PARENT_SETTID 0x00100000
-#define LINUX_CLONE_CHILD_CLEARTID 0x00200000
-#define LINUX_CLONE_CHILD_SETTID 0x01000000
-
-#define LINUX_THREADING_FLAGS \
- (LINUX_CLONE_VM | LINUX_CLONE_FS | LINUX_CLONE_FILES | \
- LINUX_CLONE_SIGHAND | LINUX_CLONE_THREAD)
-
/* robust futexes */
struct linux_robust_list {
struct linux_robust_list *next;
@@ -895,7 +745,4 @@ struct linux_robust_list_head {
struct linux_robust_list *pending_list;
};
-int linux_set_upcall_kse(struct thread *td, register_t stack);
-int linux_set_cloned_tls(struct thread *td, void *desc);
-
#endif /* !_I386_LINUX_H_ */
diff --git a/sys/i386/linux/linux_ptrace.c b/sys/i386/linux/linux_ptrace.c
index e9559f8..1074d21 100644
--- a/sys/i386/linux/linux_ptrace.c
+++ b/sys/i386/linux/linux_ptrace.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <i386/linux/linux.h>
#include <i386/linux/linux_proto.h>
+#include <compat/linux/linux_signal.h>
#if !defined(CPU_DISABLE_SSE) && defined(I686_CPU)
#define CPU_ENABLE_SSE
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index d4e23e1..71417e0 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
#include <i386/linux/linux_proto.h>
#include <compat/linux/linux_emul.h>
#include <compat/linux/linux_futex.h>
+#include <compat/linux/linux_ioctl.h>
#include <compat/linux/linux_mib.h>
#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_signal.h>
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 00b1c3f..a92b6db 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -325,6 +325,7 @@ print_version(void *data __unused)
while (len > 0 && version[len - 1] == '\n')
len--;
printf("%.*s %s\n", len, version, machine);
+ printf("%s\n", compiler_version);
}
SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t,
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index 5e10200..9d62c58 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -382,7 +382,7 @@ static void watchdog_config(void *, u_int, int *);
int stathz;
int profhz;
int profprocs;
-int ticks;
+volatile int ticks;
int psratio;
static DPCPU_DEFINE(int, pcputicks); /* Per-CPU version of ticks. */
@@ -469,7 +469,7 @@ void
hardclock(int usermode, uintfptr_t pc)
{
- atomic_add_int((volatile int *)&ticks, 1);
+ atomic_add_int(&ticks, 1);
hardclock_cpu(usermode);
tc_ticktock(1);
cpu_tick_calibration();
diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c
index 05e47e0..6fd40a8 100644
--- a/sys/kern/kern_clocksource.c
+++ b/sys/kern/kern_clocksource.c
@@ -317,14 +317,16 @@ getnextevent(struct bintime *event)
nonidle = !state->idle;
if ((timer->et_flags & ET_FLAGS_PERCPU) == 0) {
#ifdef SMP
- CPU_FOREACH(cpu) {
- if (curcpu == cpu)
- continue;
- state = DPCPU_ID_PTR(cpu, timerstate);
- nonidle += !state->idle;
- if (bintime_cmp(event, &state->nextevent, >)) {
- *event = state->nextevent;
- c = cpu;
+ if (smp_started) {
+ CPU_FOREACH(cpu) {
+ if (curcpu == cpu)
+ continue;
+ state = DPCPU_ID_PTR(cpu, timerstate);
+ nonidle += !state->idle;
+ if (bintime_cmp(event, &state->nextevent, >)) {
+ *event = state->nextevent;
+ c = cpu;
+ }
}
}
#endif
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 6dae173..87d75ea 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -779,8 +779,10 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
if (arg != 0) {
vp = fp->f_vnode;
error = vn_lock(vp, LK_SHARED);
- if (error != 0)
- goto readahead_vnlock_fail;
+ if (error != 0) {
+ fdrop(fp, td);
+ break;
+ }
bsize = fp->f_vnode->v_mount->mnt_stat.f_iosize;
VOP_UNLOCK(vp, 0);
fp->f_seqcount = (arg + bsize - 1) / bsize;
@@ -788,7 +790,6 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
new = old = fp->f_flag;
new |= FRDAHEAD;
} while (!atomic_cmpset_rel_int(&fp->f_flag, old, new));
- readahead_vnlock_fail:;
} else {
do {
new = old = fp->f_flag;
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 50b47fb..3a9a3a4 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1024,20 +1024,18 @@ kern_wait(struct thread *td, pid_t pid, int *status, int options,
struct rusage *rusage)
{
struct __wrusage wru, *wrup;
- struct proc *q;
idtype_t idtype;
id_t id;
int ret;
+ /*
+ * Translate the special pid values into the (idtype, pid)
+ * pair for kern_wait6. The WAIT_MYPGRP case is handled by
+ * kern_wait6() on its own.
+ */
if (pid == WAIT_ANY) {
idtype = P_ALL;
id = 0;
- } else if (pid == WAIT_MYPGRP) {
- idtype = P_PGID;
- q = td->td_proc;
- PROC_LOCK(q);
- id = (id_t)q->p_pgid;
- PROC_UNLOCK(q);
} else if (pid < 0) {
idtype = P_PGID;
id = (id_t)-pid;
@@ -1045,10 +1043,12 @@ kern_wait(struct thread *td, pid_t pid, int *status, int options,
idtype = P_PID;
id = (id_t)pid;
}
+
if (rusage != NULL)
wrup = &wru;
else
wrup = NULL;
+
/*
* For backward compatibility we implicitly add flags WEXITED
* and WTRAPPED here.
diff --git a/sys/kern/kern_ktr.c b/sys/kern/kern_ktr.c
index a83cedf..5b9d7aa 100644
--- a/sys/kern/kern_ktr.c
+++ b/sys/kern/kern_ktr.c
@@ -66,6 +66,10 @@ __FBSDID("$FreeBSD$");
#include <ddb/db_output.h>
#endif
+#ifndef KTR_BOOT_ENTRIES
+#define KTR_BOOT_ENTRIES 1024
+#endif
+
#ifndef KTR_ENTRIES
#define KTR_ENTRIES 1024
#endif
@@ -96,9 +100,9 @@ FEATURE(ktr, "Kernel support for KTR kernel tracing facility");
volatile int ktr_idx = 0;
int ktr_mask = KTR_MASK;
int ktr_compile = KTR_COMPILE;
-int ktr_entries = KTR_ENTRIES;
+int ktr_entries = KTR_BOOT_ENTRIES;
int ktr_version = KTR_VERSION;
-struct ktr_entry ktr_buf_init[KTR_ENTRIES];
+struct ktr_entry ktr_buf_init[KTR_BOOT_ENTRIES];
struct ktr_entry *ktr_buf = ktr_buf_init;
cpuset_t ktr_cpumask = CPUSET_T_INITIALIZER(KTR_CPUMASK);
static char ktr_cpumask_str[CPUSETBUFSIZ];
@@ -194,6 +198,28 @@ SYSCTL_PROC(_debug_ktr, OID_AUTO, mask, CTLTYPE_UINT|CTLFLAG_RW, 0, 0,
sysctl_debug_ktr_mask, "IU",
"Bitmask of KTR event classes for which logging is enabled");
+#if KTR_ENTRIES != KTR_BOOT_ENTRIES
+/*
+ * A simplified version of sysctl_debug_ktr_entries.
+ * No need to care about SMP, scheduling, etc.
+ */
+static void
+ktr_entries_initializer(void *dummy __unused)
+{
+ int mask;
+
+ /* Temporarily disable ktr in case malloc() is being traced. */
+ mask = ktr_mask;
+ ktr_mask = 0;
+ ktr_buf = malloc(sizeof(*ktr_buf) * KTR_ENTRIES, M_KTR,
+ M_WAITOK | M_ZERO);
+ ktr_entries = KTR_ENTRIES;
+ ktr_mask = mask;
+}
+SYSINIT(ktr_entries_initializer, SI_SUB_KMEM, SI_ORDER_ANY,
+ ktr_entries_initializer, NULL);
+#endif
+
static int
sysctl_debug_ktr_entries(SYSCTL_HANDLER_ARGS)
{
diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c
index 3bdfd88..2259aa2 100644
--- a/sys/kern/kern_mbuf.c
+++ b/sys/kern/kern_mbuf.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_extern.h>
#include <vm/vm_kern.h>
#include <vm/vm_page.h>
+#include <vm/vm_map.h>
#include <vm/uma.h>
#include <vm/uma_int.h>
#include <vm/uma_dbg.h>
@@ -104,15 +105,24 @@ int nmbjumbo16; /* limits number of 16k jumbo clusters */
struct mbstat mbstat;
/*
- * tunable_mbinit() has to be run before init_maxsockets() thus
- * the SYSINIT order below is SI_ORDER_MIDDLE while init_maxsockets()
- * runs at SI_ORDER_ANY.
- *
- * NB: This has to be done before VM init.
+ * tunable_mbinit() has to be run before any mbuf allocations are done.
*/
static void
tunable_mbinit(void *dummy)
{
+ quad_t realmem, maxmbufmem;
+
+ /*
+ * The default limit for all mbuf related memory is 1/2 of all
+ * available kernel memory (physical or kmem).
+ * At most it can be 3/4 of available kernel memory.
+ */
+ realmem = qmin((quad_t)physmem * PAGE_SIZE,
+ vm_map_max(kernel_map) - vm_map_min(kernel_map));
+ maxmbufmem = realmem / 2;
+ TUNABLE_QUAD_FETCH("kern.maxmbufmem", &maxmbufmem);
+ if (maxmbufmem > realmem / 4 * 3)
+ maxmbufmem = realmem / 4 * 3;
TUNABLE_INT_FETCH("kern.ipc.nmbclusters", &nmbclusters);
if (nmbclusters == 0)
@@ -139,7 +149,7 @@ tunable_mbinit(void *dummy)
nmbufs = lmax(maxmbufmem / MSIZE / 5,
nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16);
}
-SYSINIT(tunable_mbinit, SI_SUB_TUNABLES, SI_ORDER_MIDDLE, tunable_mbinit, NULL);
+SYSINIT(tunable_mbinit, SI_SUB_KMEM, SI_ORDER_MIDDLE, tunable_mbinit, NULL);
static int
sysctl_nmbclusters(SYSCTL_HANDLER_ARGS)
@@ -279,16 +289,14 @@ static int mb_zinit_pack(void *, int, int);
static void mb_zfini_pack(void *, int);
static void mb_reclaim(void *);
-static void mbuf_init(void *);
static void *mbuf_jumbo_alloc(uma_zone_t, int, uint8_t *, int);
-/* Ensure that MSIZE must be a power of 2. */
+/* Ensure that MSIZE is a power of 2. */
CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE);
/*
* Initialize FreeBSD Network buffer allocation.
*/
-SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbuf_init, NULL);
static void
mbuf_init(void *dummy)
{
@@ -396,6 +404,7 @@ mbuf_init(void *dummy)
mbstat.sf_iocnt = 0;
mbstat.sf_allocwait = mbstat.sf_allocfail = 0;
}
+SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbuf_init, NULL);
/*
* UMA backend page allocator for the jumbo frame zones.
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index 29864a8..c84d4b2 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -99,6 +99,9 @@ SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD|CTLFLAG_CAPRD,
SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD|CTLFLAG_MPSAFE,
version, 0, "Kernel version");
+SYSCTL_STRING(_kern, OID_AUTO, compiler_version, CTLFLAG_RD|CTLFLAG_MPSAFE,
+ compiler_version, 0, "Version of compiler used to compile kernel");
+
SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD|CTLFLAG_MPSAFE|
CTLFLAG_CAPRD, ostype, 0, "Operating system type");
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index a08b218..2ffa2f9 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -103,8 +103,8 @@ static struct timecounter *timecounters = &dummy_timecounter;
int tc_min_ticktock_freq = 1;
-time_t time_second = 1;
-time_t time_uptime = 1;
+volatile time_t time_second = 1;
+volatile time_t time_uptime = 1;
struct bintime boottimebin;
struct timeval boottime;
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index c41fba0..1d45f28 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -3318,7 +3318,7 @@ resource_list_release(struct resource_list *rl, device_t bus, device_t child,
/**
* @brief Fully release a reserved resource
*
- * Fully releases a resouce reserved via resource_list_reserve().
+ * Fully releases a resource reserved via resource_list_reserve().
*
* @param rl the resource list which was allocated from
* @param bus the parent device of @p child
diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c
index fe10a87..f36c769 100644
--- a/sys/kern/subr_param.c
+++ b/sys/kern/subr_param.c
@@ -93,7 +93,6 @@ int ncallout; /* maximum # of timer events */
int nbuf;
int ngroups_max; /* max # groups per process */
int nswbuf;
-quad_t maxmbufmem; /* max mbuf memory */
pid_t pid_max = PID_MAX;
long maxswzone; /* max swmeta KVA storage */
long maxbcache; /* max buffer cache KVA storage */
@@ -161,6 +160,7 @@ static const char *const vm_bnames[] = {
"Bochs", /* Bochs */
"Xen", /* Xen */
"BHYVE", /* bhyve */
+ "Seabios", /* KVM */
NULL
};
@@ -169,6 +169,7 @@ static const char *const vm_pnames[] = {
"Virtual Machine", /* Microsoft VirtualPC */
"VirtualBox", /* Sun xVM VirtualBox */
"Parallels Virtual Platform", /* Parallels VM */
+ "KVM", /* KVM */
NULL
};
@@ -272,7 +273,6 @@ init_param1(void)
void
init_param2(long physpages)
{
- quad_t realmem;
/* Base parameters */
maxusers = MAXUSERS;
@@ -324,23 +324,14 @@ init_param2(long physpages)
/*
* XXX: Does the callout wheel have to be so big?
+ *
+ * Clip callout to result of previous function of maxusers maximum
+ * 384. This is still huge, but acceptable.
*/
- ncallout = 16 + maxproc + maxfiles;
+ ncallout = imin(16 + maxproc + maxfiles, 18508);
TUNABLE_INT_FETCH("kern.ncallout", &ncallout);
/*
- * The default limit for all mbuf related memory is 1/2 of all
- * available kernel memory (physical or kmem).
- * At most it can be 3/4 of available kernel memory.
- */
- realmem = qmin((quad_t)physpages * PAGE_SIZE,
- VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS);
- maxmbufmem = realmem / 2;
- TUNABLE_QUAD_FETCH("kern.maxmbufmem", &maxmbufmem);
- if (maxmbufmem > (realmem / 4) * 3)
- maxmbufmem = (realmem / 4) * 3;
-
- /*
* The default for maxpipekva is min(1/64 of the kernel address space,
* max(1/64 of main memory, 512KB)). See sys_pipe.c for more details.
*/
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index ab6163d..4606f37 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -85,6 +85,79 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragrandomfailures, CTLFLAG_RW,
#endif
/*
+ * m_get2() allocates minimum mbuf that would fit "size" argument.
+ */
+struct mbuf *
+m_get2(int how, short type, int flags, int size)
+{
+ struct mb_args args;
+ struct mbuf *m, *n;
+ uma_zone_t zone;
+
+ args.flags = flags;
+ args.type = type;
+
+ if (size <= MHLEN || (size <= MLEN && (flags & M_PKTHDR) == 0))
+ return (uma_zalloc_arg(zone_mbuf, &args, how));
+ if (size <= MCLBYTES)
+ return (uma_zalloc_arg(zone_pack, &args, how));
+ if (size > MJUM16BYTES)
+ return (NULL);
+
+ m = uma_zalloc_arg(zone_mbuf, &args, how);
+ if (m == NULL)
+ return (NULL);
+
+#if MJUMPAGESIZE != MCLBYTES
+ if (size <= MJUMPAGESIZE)
+ zone = zone_jumbop;
+ else
+#endif
+ if (size <= MJUM9BYTES)
+ zone = zone_jumbo9;
+ else
+ zone = zone_jumbo16;
+
+ n = uma_zalloc_arg(zone, m, how);
+ if (n == NULL) {
+ uma_zfree(zone_mbuf, m);
+ return (NULL);
+ }
+
+ return (m);
+}
+
+/*
+ * m_getjcl() returns an mbuf with a cluster of the specified size attached.
+ * For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
+ */
+struct mbuf *
+m_getjcl(int how, short type, int flags, int size)
+{
+ struct mb_args args;
+ struct mbuf *m, *n;
+ uma_zone_t zone;
+
+ if (size == MCLBYTES)
+ return m_getcl(how, type, flags);
+
+ args.flags = flags;
+ args.type = type;
+
+ m = uma_zalloc_arg(zone_mbuf, &args, how);
+ if (m == NULL)
+ return (NULL);
+
+ zone = m_getzone(size);
+ n = uma_zalloc_arg(zone, m, how);
+ if (n == NULL) {
+ uma_zfree(zone_mbuf, m);
+ return (NULL);
+ }
+ return (m);
+}
+
+/*
* Allocate a given length worth of mbufs and/or clusters (whatever fits
* best) and return a pointer to the top of the allocated chain. If an
* existing mbuf chain is provided, then we will append the new chain
diff --git a/sys/kern/vfs_hash.c b/sys/kern/vfs_hash.c
index aad22e0..0271e49 100644
--- a/sys/kern/vfs_hash.c
+++ b/sys/kern/vfs_hash.c
@@ -54,11 +54,18 @@ vfs_hashinit(void *dummy __unused)
/* Must be SI_ORDER_SECOND so desiredvnodes is available */
SYSINIT(vfs_hash, SI_SUB_VFS, SI_ORDER_SECOND, vfs_hashinit, NULL);
+u_int
+vfs_hash_index(struct vnode *vp)
+{
+
+ return (vp->v_hash + vp->v_mount->mnt_hashseed);
+}
+
static struct vfs_hash_head *
-vfs_hash_index(const struct mount *mp, u_int hash)
+vfs_hash_bucket(const struct mount *mp, u_int hash)
{
- return(&vfs_hash_tbl[(hash + mp->mnt_hashseed) & vfs_hash_mask]);
+ return (&vfs_hash_tbl[(hash + mp->mnt_hashseed) & vfs_hash_mask]);
}
int
@@ -69,7 +76,7 @@ vfs_hash_get(const struct mount *mp, u_int hash, int flags, struct thread *td, s
while (1) {
mtx_lock(&vfs_hash_mtx);
- LIST_FOREACH(vp, vfs_hash_index(mp, hash), v_hashlist) {
+ LIST_FOREACH(vp, vfs_hash_bucket(mp, hash), v_hashlist) {
if (vp->v_hash != hash)
continue;
if (vp->v_mount != mp)
@@ -113,7 +120,7 @@ vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, stru
while (1) {
mtx_lock(&vfs_hash_mtx);
LIST_FOREACH(vp2,
- vfs_hash_index(vp->v_mount, hash), v_hashlist) {
+ vfs_hash_bucket(vp->v_mount, hash), v_hashlist) {
if (vp2->v_hash != hash)
continue;
if (vp2->v_mount != vp->v_mount)
@@ -138,7 +145,7 @@ vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, stru
}
vp->v_hash = hash;
- LIST_INSERT_HEAD(vfs_hash_index(vp->v_mount, hash), vp, v_hashlist);
+ LIST_INSERT_HEAD(vfs_hash_bucket(vp->v_mount, hash), vp, v_hashlist);
mtx_unlock(&vfs_hash_mtx);
return (0);
}
@@ -149,7 +156,7 @@ vfs_hash_rehash(struct vnode *vp, u_int hash)
mtx_lock(&vfs_hash_mtx);
LIST_REMOVE(vp, v_hashlist);
- LIST_INSERT_HEAD(vfs_hash_index(vp->v_mount, hash), vp, v_hashlist);
+ LIST_INSERT_HEAD(vfs_hash_bucket(vp->v_mount, hash), vp, v_hashlist);
vp->v_hash = hash;
mtx_unlock(&vfs_hash_mtx);
}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 7c243b6..1c26368 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -279,6 +279,8 @@ SYSCTL_INT(_debug, OID_AUTO, vnlru_nowhere, CTLFLAG_RW,
#define VSHOULDFREE(vp) (!((vp)->v_iflag & VI_FREE) && !(vp)->v_holdcnt)
#define VSHOULDBUSY(vp) (((vp)->v_iflag & VI_FREE) && (vp)->v_holdcnt)
+/* Shift count for (uintptr_t)vp to initialize vp->v_hash. */
+static int vnsz2log;
/*
* Initialize the vnode management data structures.
@@ -293,6 +295,7 @@ SYSCTL_INT(_debug, OID_AUTO, vnlru_nowhere, CTLFLAG_RW,
static void
vntblinit(void *dummy __unused)
{
+ u_int i;
int physvnodes, virtvnodes;
/*
@@ -332,6 +335,9 @@ vntblinit(void *dummy __unused)
syncer_maxdelay = syncer_mask + 1;
mtx_init(&sync_mtx, "Syncer mtx", NULL, MTX_DEF);
cv_init(&sync_wakeup, "syncer");
+ for (i = 1; i <= sizeof(struct vnode); i <<= 1)
+ vnsz2log++;
+ vnsz2log--;
}
SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vntblinit, NULL);
@@ -1067,6 +1073,14 @@ alloc:
}
rangelock_init(&vp->v_rl);
+ /*
+ * For the filesystems which do not use vfs_hash_insert(),
+ * still initialize v_hash to have vfs_hash_index() useful.
+ * E.g., nullfs uses vfs_hash_index() on the lower vnode for
+ * its own hashing.
+ */
+ vp->v_hash = (uintptr_t)vp >> vnsz2log;
+
*vpp = vp;
return (0);
}
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 3f2e523..1a5f2ae 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -187,8 +187,8 @@ sys_quotactl(td, uap)
AUDIT_ARG_UID(uap->uid);
if (!prison_allow(td->td_ucred, PR_ALLOW_QUOTAS))
return (EPERM);
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1,
- UIO_USERSPACE, uap->path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
+ uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -293,8 +293,8 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF |
- AUDITVNODE1, pathseg, path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
+ pathseg, path, td);
error = namei(&nd);
if (error)
return (error);
@@ -871,8 +871,8 @@ sys_chroot(td, uap)
error = priv_check(td, PRIV_VFS_CHROOT);
if (error)
return (error);
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF |
- AUDITVNODE1, UIO_USERSPACE, uap->path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
+ UIO_USERSPACE, uap->path, td);
error = namei(&nd);
if (error)
goto error;
@@ -1077,8 +1077,8 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
/* Set the flags early so the finit in devfs can pick them up. */
fp->f_flag = flags & FMASK;
cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
- NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg,
- path, fd, rights_needed, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,
+ rights_needed, td);
td->td_dupfd = -1; /* XXX check for fdopen */
error = vn_open(&nd, &flags, cmode, fp);
if (error) {
@@ -1108,7 +1108,7 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
if (error == ERESTART)
error = EINTR;
- goto bad_unlocked;
+ goto bad;
}
td->td_dupfd = 0;
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -1150,12 +1150,11 @@ success:
*/
if ((error = kern_capwrap(td, fp, nd.ni_baserights,
&indx)) != 0)
- goto bad_unlocked;
+ goto bad;
} else
#endif
if ((error = finstall(td, fp, &indx, flags)) != 0)
- goto bad_unlocked;
-
+ goto bad;
}
/*
@@ -1166,7 +1165,6 @@ success:
td->td_retval[0] = indx;
return (0);
bad:
-bad_unlocked:
KASSERT(indx == -1, ("indx=%d, should be -1", indx));
fdrop(fp, td);
return (error);
@@ -1279,9 +1277,8 @@ kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
return (error);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE,
- LOCKPARENT | SAVENAME | AUDITVNODE1, pathseg, path, fd,
- CAP_MKNOD, td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
+ pathseg, path, fd, CAP_MKNOD, td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
@@ -1400,9 +1397,8 @@ kern_mkfifoat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
AUDIT_ARG_MODE(mode);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE,
- LOCKPARENT | SAVENAME | AUDITVNODE1, pathseg, path, fd,
- CAP_MKFIFO, td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
+ pathseg, path, fd, CAP_MKFIFO, td);
if ((error = namei(&nd)) != 0)
return (error);
if (nd.ni_vp != NULL) {
@@ -1541,8 +1537,7 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2,
int error;
bwillwrite();
- NDINIT_AT(&nd, LOOKUP, follow | AUDITVNODE1, segflg, path1,
- fd1, td);
+ NDINIT_AT(&nd, LOOKUP, follow | AUDITVNODE1, segflg, path1, fd1, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -1556,8 +1551,8 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2,
vrele(vp);
return (error);
}
- NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME |
- AUDITVNODE2, segflg, path2, fd2, CAP_CREATE, td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE2,
+ segflg, path2, fd2, CAP_CREATE, td);
if ((error = namei(&nd)) == 0) {
if (nd.ni_vp != NULL) {
if (nd.ni_dvp == nd.ni_vp)
@@ -1649,8 +1644,8 @@ kern_symlinkat(struct thread *td, char *path1, int fd, char *path2,
AUDIT_ARG_TEXT(syspath);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME |
- AUDITVNODE1, segflg, path2, fd, CAP_CREATE, td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
+ segflg, path2, fd, CAP_CREATE, td);
if ((error = namei(&nd)) != 0)
goto out;
if (nd.ni_vp) {
@@ -1801,8 +1796,8 @@ kern_unlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF |
- AUDITVNODE1, pathseg, path, fd, CAP_DELETE, td);
+ NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1,
+ pathseg, path, fd, CAP_DELETE, td);
if ((error = namei(&nd)) != 0)
return (error == EINVAL ? EPERM : error);
vp = nd.ni_vp;
@@ -2309,8 +2304,8 @@ kern_statat_vnhook(struct thread *td, int flag, int fd, char *path,
return (EINVAL);
NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW :
- FOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg,
- path, fd, CAP_FSTAT, td);
+ FOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, fd,
+ CAP_FSTAT, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -2486,7 +2481,8 @@ sys_lpathconf(td, uap)
} */ *uap;
{
- return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name, NOFOLLOW));
+ return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name,
+ NOFOLLOW));
}
int
@@ -2572,8 +2568,8 @@ kern_readlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
if (count > IOSIZE_MAX)
return (EINVAL);
- NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKSHARED | LOCKLEAF |
- AUDITVNODE1, pathseg, path, fd, td);
+ NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
+ pathseg, path, fd, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -2670,8 +2666,7 @@ sys_chflags(td, uap)
struct nameidata nd;
AUDIT_ARG_FFLAGS(uap->flags);
- NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE,
- uap->path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -2695,8 +2690,8 @@ sys_lchflags(td, uap)
struct nameidata nd;
AUDIT_ARG_FFLAGS(uap->flags);
- NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
- uap->path, td);
+ NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path,
+ td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -2852,8 +2847,8 @@ kern_fchmodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
AUDIT_ARG_MODE(mode);
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
- NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg,
- path, fd, CAP_FCHMOD, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
+ CAP_FCHMOD, td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -2982,8 +2977,8 @@ kern_fchownat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
AUDIT_ARG_OWNER(uid, gid);
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
- NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg,
- path, fd, CAP_FCHOWN, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
+ CAP_FCHOWN, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -3188,8 +3183,8 @@ kern_utimesat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
if ((error = getutimes(tptr, tptrseg, ts)) != 0)
return (error);
- NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg,
- path, fd, CAP_FUTIMES, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,
+ CAP_FUTIMES, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -3510,8 +3505,8 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
NDINIT_ATRIGHTS(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART |
AUDITVNODE1, pathseg, old, oldfd, CAP_DELETE, td);
#else
- NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART |
- AUDITVNODE1, pathseg, old, oldfd, CAP_DELETE, td);
+ NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART | AUDITVNODE1,
+ pathseg, old, oldfd, CAP_DELETE, td);
#endif
if ((error = namei(&fromnd)) != 0)
@@ -3656,8 +3651,8 @@ kern_mkdirat(struct thread *td, int fd, char *path, enum uio_seg segflg,
AUDIT_ARG_MODE(mode);
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME |
- AUDITVNODE1, segflg, path, fd, CAP_MKDIR, td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
+ segflg, path, fd, CAP_MKDIR, td);
nd.ni_cnd.cn_flags |= WILLBEDIR;
if ((error = namei(&nd)) != 0)
return (error);
@@ -3740,8 +3735,8 @@ kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg)
restart:
bwillwrite();
- NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF |
- AUDITVNODE1, pathseg, path, fd, CAP_RMDIR, td);
+ NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1,
+ pathseg, path, fd, CAP_RMDIR, td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
@@ -4123,8 +4118,8 @@ sys_revoke(td, uap)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1,
- UIO_USERSPACE, uap->path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
+ uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
@@ -4230,8 +4225,8 @@ sys_lgetfh(td, uap)
error = priv_check(td, PRIV_VFS_GETFH);
if (error)
return (error);
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | AUDITVNODE1,
- UIO_USERSPACE, uap->fname, td);
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
+ uap->fname, td);
error = namei(&nd);
if (error)
return (error);
@@ -4266,8 +4261,8 @@ sys_getfh(td, uap)
error = priv_check(td, PRIV_VFS_GETFH);
if (error)
return (error);
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1,
- UIO_USERSPACE, uap->fname, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
+ uap->fname, td);
error = namei(&nd);
if (error)
return (error);
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index bbe837a..4ebf4b5 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1642,7 +1642,7 @@ vfs_write_suspend(mp)
else
MNT_IUNLOCK(mp);
if ((error = VFS_SYNC(mp, MNT_SUSPEND)) != 0)
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
return (error);
}
@@ -1650,7 +1650,7 @@ vfs_write_suspend(mp)
* Request a filesystem to resume write operations.
*/
void
-vfs_write_resume_flags(struct mount *mp, int flags)
+vfs_write_resume(struct mount *mp, int flags)
{
MNT_ILOCK(mp);
@@ -1677,23 +1677,14 @@ vfs_write_resume_flags(struct mount *mp, int flags)
}
}
-void
-vfs_write_resume(struct mount *mp)
-{
-
- vfs_write_resume_flags(mp, 0);
-}
-
/*
* Implement kqueues for files by translating it to vnode operation.
*/
static int
vn_kqfilter(struct file *fp, struct knote *kn)
{
- int error;
- error = VOP_KQFILTER(fp->f_vnode, kn);
- return (error);
+ return (VOP_KQFILTER(fp->f_vnode, kn));
}
/*
diff --git a/sys/libkern/arm/divsi3.S b/sys/libkern/arm/divsi3.S
index 00bacfa..700ae37 100644
--- a/sys/libkern/arm/divsi3.S
+++ b/sys/libkern/arm/divsi3.S
@@ -49,6 +49,10 @@ ENTRY_NP(__modsi3)
#endif
RET
+#ifdef __ARM_EABI__
+ENTRY_NP(__aeabi_uidiv)
+ENTRY_NP(__aeabi_uidivmod)
+#endif
ENTRY_NP(__udivsi3)
.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */
eor r0, r1, r0
@@ -71,6 +75,10 @@ ENTRY_NP(__udivsi3)
mov r1, #0
RET
+#ifdef __ARM_EABI__
+ENTRY_NP(__aeabi_idiv)
+ENTRY_NP(__aeabi_idivmod)
+#endif
ENTRY_NP(__divsi3)
.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */
eor r0, r1, r0
diff --git a/sys/libkern/arm/ldivmod.S b/sys/libkern/arm/ldivmod.S
new file mode 100644
index 0000000..a88db54
--- /dev/null
+++ b/sys/libkern/arm/ldivmod.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef __ARM_EABI__
+
+/*
+ * These calculate:
+ * q = n / m
+ * With a remainer r.
+ *
+ * They take n in {r0, r1} and m in {r2, r3} then pass them into the
+ * helper function. The hepler functions return q in {r0, r1} as
+ * required by the API spec however r is returned on the stack. The
+ * ABI required us to return r in {r2, r3}.
+ *
+ * We need to allocate 8 bytes on the stack to store r, the link
+ * register, and a pointer to the space where the helper function
+ * will write r to. After returning from the helper fuinction we load
+ * the old link register and r from the stack and return.
+ */
+ENTRY_NP(__aeabi_ldivmod)
+ sub sp, sp, #8 /* Space for the remainder */
+ stmfd sp!, {sp, lr} /* Save a pointer to the above space and lr */
+ bl PIC_SYM(_C_LABEL(__kern_ldivmod), PLT)
+ ldr lr, [sp, #4] /* Restore lr */
+ add sp, sp, #8 /* Move sp to the remainder value */
+ ldmfd sp!, {r2, r3} /* Load the remainder */
+ RET
+
+ENTRY_NP(__aeabi_uldivmod)
+ sub sp, sp, #8 /* Space for the remainder */
+ stmfd sp!, {sp, lr} /* Save a pointer to the above space and lr */
+ bl PIC_SYM(_C_LABEL(__qdivrem), PLT)
+ ldr lr, [sp, #4] /* Restore lr */
+ add sp, sp, #8 /* Move sp to the remainder value */
+ ldmfd sp!, {r2, r3} /* Load the remainder */
+ RET
+
+#endif
+
diff --git a/sys/arm/mv/kirkwood/sheevaplug.c b/sys/libkern/arm/ldivmod_helper.c
index 3463106..9061ae4 100644
--- a/sys/arm/mv/kirkwood/sheevaplug.c
+++ b/sys/libkern/arm/ldivmod_helper.c
@@ -1,10 +1,7 @@
-/*-
- * Copyright (c) 2010 The FreeBSD Foundation
+/*
+ * Copyright (C) 2012 Andrew Turner
* All rights reserved.
*
- * This software was developed by Semihalf under sponsorship from
- * the FreeBSD Foundation.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +14,7 @@
* 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
+ * 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)
@@ -25,20 +22,32 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <dev/fdt/fdt_common.h>
-#include <dev/ofw/openfirm.h>
+#ifdef __ARM_EABI__
+#include <libkern/quad.h>
-#include <machine/fdt.h>
+/*
+ * Helper for __aeabi_ldivmod.
+ * TODO: __divdi3 calls __qdivrem. We should do the same and use the
+ * remainder value rather than re-calculating it.
+ */
+long long __kern_ldivmod(long long, long long, long long *);
-int
-fdt_pci_devmap(phandle_t node, struct pmap_devmap *devmap, vm_offset_t io_va,
- vm_offset_t mem_va)
+long long
+__kern_ldivmod(long long n, long long m, long long *rem)
{
+ long long q;
- return (0);
+ q = __divdi3(n, m); /* q = n / m */
+ *rem = n - m * q;
+
+ return q;
}
+
+#endif
+
diff --git a/sys/libkern/quad.h b/sys/libkern/quad.h
index 5d4f844..4850d89 100644
--- a/sys/libkern/quad.h
+++ b/sys/libkern/quad.h
@@ -110,4 +110,9 @@ u_quad_t __udivdi3(u_quad_t a, u_quad_t b);
u_quad_t __umoddi3(u_quad_t a, u_quad_t b);
int __ucmpdi2(u_quad_t a, u_quad_t b);
+/* ARM EABI support functions. */
+#ifdef __ARM_EABI__
+int __aeabi_ulcmp(unsigned long long, unsigned long long);
+#endif
+
#endif /* !_LIBKERN_QUAD_H_ */
diff --git a/sys/libkern/ucmpdi2.c b/sys/libkern/ucmpdi2.c
index 376d9c4..cd41c69 100644
--- a/sys/libkern/ucmpdi2.c
+++ b/sys/libkern/ucmpdi2.c
@@ -51,3 +51,15 @@ __ucmpdi2(a, b)
return (aa.ul[H] < bb.ul[H] ? 0 : aa.ul[H] > bb.ul[H] ? 2 :
aa.ul[L] < bb.ul[L] ? 0 : aa.ul[L] > bb.ul[L] ? 2 : 1);
}
+
+#ifdef __ARM_EABI__
+/*
+ * Return -1, 0 or 1 as a <, =, > b respectively.
+ */
+int
+__aeabi_ulcmp(unsigned long long a, unsigned long long b)
+{
+ return __ucmpdi2(a, b) - 1;
+}
+#endif
+
diff --git a/sys/mips/beri/beri_machdep.c b/sys/mips/beri/beri_machdep.c
index f2ef5a7..98fcb85a 100644
--- a/sys/mips/beri/beri_machdep.c
+++ b/sys/mips/beri/beri_machdep.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/cpu.h>
#include <sys/cons.h>
#include <sys/exec.h>
+#include <sys/linker.h>
#include <sys/ucontext.h>
#include <sys/proc.h>
#include <sys/kdb.h>
@@ -70,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/md_var.h>
+#include <machine/metadata.h>
#include <machine/pmap.h>
#include <machine/trap.h>
@@ -87,17 +89,6 @@ mips_init(void)
{
int i;
-#ifdef FDT
-#ifndef FDT_DTB_STATIC
-#error "mips_init with FDT requires FDT_DTB_STATIC"
-#endif
-
- if (OF_install(OFW_FDT, 0) == FALSE)
- while (1);
- if (OF_init(&fdt_static_dtb) != 0)
- while (1);
-#endif
-
for (i = 0; i < 10; i++) {
phys_avail[i] = 0;
}
@@ -146,6 +137,10 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
char **argv = (char **)a1;
char **envp = (char **)a2;
unsigned int memsize = a3;
+#ifdef FDT
+ vm_offset_t dtbp;
+ void *kmdp;
+#endif
int i;
/* clear the BSS and SBSS segments */
@@ -156,6 +151,33 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
mips_pcpu0_init();
+#ifdef FDT
+ /*
+ * Find the dtb passed in by the boot loader (currently fictional).
+ */
+ kmdp = preload_search_by_type("elf kernel");
+ if (kmdp != NULL)
+ dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t);
+ else
+ dtbp = (vm_offset_t)NULL;
+
+#if defined(FDT_DTB_STATIC)
+ /*
+ * In case the device tree blob was not retrieved (from metadata) try
+ * to use the statically embedded one.
+ */
+ if (dtbp == (vm_offset_t)NULL)
+ dtbp = (vm_offset_t)&fdt_static_dtb;
+#else
+#error "Non-static FDT not yet supported on BERI"
+#endif
+
+ if (OF_install(OFW_FDT, 0) == FALSE)
+ while (1);
+ if (OF_init(&fdt_static_dtb) != 0)
+ while (1);
+#endif
+
/*
* XXXRW: We have no way to compare wallclock time to cycle rate on
* BERI, so for now assume we run at the MALTA default (100MHz).
diff --git a/sys/mips/beri/files.beri b/sys/mips/beri/files.beri
index 02a27f8..6794793 100644
--- a/sys/mips/beri/files.beri
+++ b/sys/mips/beri/files.beri
@@ -1,10 +1,13 @@
# $FreeBSD$
dev/altera/jtag_uart/altera_jtag_uart_cons.c optional altera_jtag_uart
dev/altera/jtag_uart/altera_jtag_uart_tty.c optional altera_jtag_uart
+dev/altera/jtag_uart/altera_jtag_uart_fdt.c optional altera_jtag_uart fdt
dev/altera/jtag_uart/altera_jtag_uart_nexus.c optional altera_jtag_uart
dev/terasic/de4led/terasic_de4led.c optional terasic_de4led
+dev/terasic/de4led/terasic_de4led_fdt.c optional terasic_de4led fdt
dev/terasic/de4led/terasic_de4led_nexus.c optional terasic_de4led
dev/terasic/mtl/terasic_mtl.c optional terasic_mtl
+dev/terasic/mtl/terasic_mtl_fdt.c optional terasic_mtl fdt
dev/terasic/mtl/terasic_mtl_nexus.c optional terasic_mtl
dev/terasic/mtl/terasic_mtl_pixel.c optional terasic_mtl
dev/terasic/mtl/terasic_mtl_reg.c optional terasic_mtl
diff --git a/sys/mips/include/bus.h b/sys/mips/include/bus.h
index b904a5d..6825b23 100644
--- a/sys/mips/include/bus.h
+++ b/sys/mips/include/bus.h
@@ -728,6 +728,8 @@ void __bs_c(f,_bs_c_8) (void *t, bus_space_handle_t bsh1, \
*/
DECLARE_BUS_SPACE_PROTOTYPES(generic);
extern bus_space_tag_t mips_bus_space_generic;
+extern bus_space_tag_t mips_bus_space_fdt;
+
/* Special bus space for RMI processors */
#if defined(CPU_RMI) || defined (CPU_NLM)
extern bus_space_tag_t rmi_bus_space;
diff --git a/sys/mips/include/fdt.h b/sys/mips/include/fdt.h
index 3b20a72..2f1fda5 100644
--- a/sys/mips/include/fdt.h
+++ b/sys/mips/include/fdt.h
@@ -51,7 +51,7 @@
#if defined(CPU_RMI) || defined(CPU_NLM)
#define fdtbus_bs_tag rmi_uart_bus_space
#else
-#define fdtbus_bs_tag NULL
+#define fdtbus_bs_tag mips_bus_space_fdt
#endif
#endif /* _MACHINE_FDT_H_ */
diff --git a/sys/mips/include/metadata.h b/sys/mips/include/metadata.h
index 84e6f87..779c2f6 100644
--- a/sys/mips/include/metadata.h
+++ b/sys/mips/include/metadata.h
@@ -30,5 +30,6 @@
#define _MACHINE_METADATA_H_
#define MODINFOMD_SMAP 0x1001
+#define MODINFOMD_DTBP 0x1002
#endif /* !_MACHINE_METADATA_H_ */
diff --git a/sys/mips/include/vmparam.h b/sys/mips/include/vmparam.h
index aa0a5d7..ef97336 100644
--- a/sys/mips/include/vmparam.h
+++ b/sys/mips/include/vmparam.h
@@ -130,10 +130,11 @@
#endif
/*
- * Ceiling on amount of kmem_map kva space.
+ * Ceiling on the amount of kmem_map KVA space: 40% of the entire KVA space.
*/
#ifndef VM_KMEM_SIZE_MAX
-#define VM_KMEM_SIZE_MAX (200 * 1024 * 1024)
+#define VM_KMEM_SIZE_MAX ((VM_MAX_KERNEL_ADDRESS - \
+ VM_MIN_KERNEL_ADDRESS + 1) * 2 / 5)
#endif
/* initial pagein size of beginning of executable file */
diff --git a/sys/mips/mips/bus_space_fdt.c b/sys/mips/mips/bus_space_fdt.c
new file mode 100644
index 0000000..38efea1
--- /dev/null
+++ b/sys/mips/mips/bus_space_fdt.c
@@ -0,0 +1,212 @@
+/* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */
+/*-
+ * $Id: bus.h,v 1.6 2007/08/09 11:23:32 katta Exp $
+ *
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1996 Christopher G. Demetriou. 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 Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: src/sys/alpha/include/bus.h,v 1.5 1999/08/28 00:38:40 peter
+ * $FreeBSD$
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/ktr.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+#include <machine/cache.h>
+
+static int fdt_bs_map(void *, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *);
+
+static struct bus_space fdt_space = {
+ /* cookie */
+ (void *) 0,
+
+ /* mapping/unmapping */
+ fdt_bs_map,
+ generic_bs_unmap,
+ generic_bs_subregion,
+
+ /* allocation/deallocation */
+ generic_bs_alloc,
+ generic_bs_free,
+
+ /* barrier */
+ generic_bs_barrier,
+
+ /* read (single) */
+ generic_bs_r_1,
+ generic_bs_r_2,
+ generic_bs_r_4,
+ generic_bs_r_8,
+
+ /* read multiple */
+ generic_bs_rm_1,
+ generic_bs_rm_2,
+ generic_bs_rm_4,
+ generic_bs_rm_8,
+
+ /* read region */
+ generic_bs_rr_1,
+ generic_bs_rr_2,
+ generic_bs_rr_4,
+ generic_bs_rr_8,
+
+ /* write (single) */
+ generic_bs_w_1,
+ generic_bs_w_2,
+ generic_bs_w_4,
+ generic_bs_w_8,
+
+ /* write multiple */
+ generic_bs_wm_1,
+ generic_bs_wm_2,
+ generic_bs_wm_4,
+ generic_bs_wm_8,
+
+ /* write region */
+ generic_bs_wr_1,
+ generic_bs_wr_2,
+ generic_bs_wr_4,
+ generic_bs_wr_8,
+
+ /* set multiple */
+ generic_bs_sm_1,
+ generic_bs_sm_2,
+ generic_bs_sm_4,
+ generic_bs_sm_8,
+
+ /* set region */
+ generic_bs_sr_1,
+ generic_bs_sr_2,
+ generic_bs_sr_4,
+ generic_bs_sr_8,
+
+ /* copy */
+ generic_bs_c_1,
+ generic_bs_c_2,
+ generic_bs_c_4,
+ generic_bs_c_8,
+
+ /* read (single) stream */
+ generic_bs_r_1,
+ generic_bs_r_2,
+ generic_bs_r_4,
+ generic_bs_r_8,
+
+ /* read multiple stream */
+ generic_bs_rm_1,
+ generic_bs_rm_2,
+ generic_bs_rm_4,
+ generic_bs_rm_8,
+
+ /* read region stream */
+ generic_bs_rr_1,
+ generic_bs_rr_2,
+ generic_bs_rr_4,
+ generic_bs_rr_8,
+
+ /* write (single) stream */
+ generic_bs_w_1,
+ generic_bs_w_2,
+ generic_bs_w_4,
+ generic_bs_w_8,
+
+ /* write multiple stream */
+ generic_bs_wm_1,
+ generic_bs_wm_2,
+ generic_bs_wm_4,
+ generic_bs_wm_8,
+
+ /* write region stream */
+ generic_bs_wr_1,
+ generic_bs_wr_2,
+ generic_bs_wr_4,
+ generic_bs_wr_8,
+};
+
+/* generic bus_space tag */
+bus_space_tag_t mips_bus_space_fdt = &fdt_space;
+
+static int
+fdt_bs_map(void *t __unused, bus_addr_t addr, bus_size_t size __unused,
+ int flags __unused, bus_space_handle_t *bshp)
+{
+
+ *bshp = MIPS_PHYS_TO_DIRECT_UNCACHED(addr);
+ return (0);
+}
diff --git a/sys/mips/nlm/dev/net/mdio.c b/sys/mips/nlm/dev/net/mdio.c
index ed2abe4..0845339 100644
--- a/sys/mips/nlm/dev/net/mdio.c
+++ b/sys/mips/nlm/dev/net/mdio.c
@@ -149,7 +149,8 @@ nlm_int_gmac_mdio_reset(uint64_t nae_base, int bus, int block,
uint32_t val;
val = (7 << INT_MDIO_CTRL_XDIV_POS) |
- (1 << INT_MDIO_CTRL_MCDIV_POS);
+ (1 << INT_MDIO_CTRL_MCDIV_POS) |
+ (INT_MDIO_CTRL_SMP);
nlm_write_nae_reg(nae_base,
NAE_REG(block, intf_type, (INT_MDIO_CTRL + bus * 4)),
@@ -302,10 +303,13 @@ nlm_gmac_mdio_reset(uint64_t nae_base, int bus, int block,
{
uint32_t ctrlval;
+ ctrlval = nlm_read_nae_reg(nae_base,
+ NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL+bus*4)));
+
if (nlm_is_xlp8xx_ax() || nlm_is_xlp8xx_b0() || nlm_is_xlp3xx_ax())
- ctrlval = EXT_G_MDIO_DIV;
+ ctrlval |= EXT_G_MDIO_DIV;
else
- ctrlval = EXT_G_MDIO_DIV_WITH_HW_DIV64;
+ ctrlval |= EXT_G_MDIO_DIV_WITH_HW_DIV64;
nlm_write_nae_reg(nae_base,
NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)),
@@ -314,3 +318,16 @@ nlm_gmac_mdio_reset(uint64_t nae_base, int bus, int block,
NAE_REG(block, intf_type, (EXT_G0_MDIO_CTRL + bus * 4)), ctrlval);
return (0);
}
+
+/*
+ * nlm_mdio_reset_all : reset all internal and external MDIO
+ */
+void
+nlm_mdio_reset_all(uint64_t nae_base)
+{
+ /* reset internal MDIO */
+ nlm_int_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
+ /* reset external MDIO */
+ nlm_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
+ nlm_gmac_mdio_reset(nae_base, 1, BLOCK_7, LANE_CFG);
+}
diff --git a/sys/mips/nlm/dev/net/nae.c b/sys/mips/nlm/dev/net/nae.c
index dce4836..d97b290 100644
--- a/sys/mips/nlm/dev/net/nae.c
+++ b/sys/mips/nlm/dev/net/nae.c
@@ -1427,9 +1427,8 @@ nlm_nae_open_if(uint64_t nae_base, int nblock, int port_type,
int port, uint32_t desc_size)
{
uint32_t netwk_inf;
- uint32_t mac_cfg1, mac_cfg2, netior_ctrl3;
- int iface, speed, duplex, ifmode;
- int iface_ctrl_reg, iface_ctrl3_reg, conf1_reg, conf2_reg;
+ uint32_t mac_cfg1, netior_ctrl3;
+ int iface, iface_ctrl_reg, iface_ctrl3_reg, conf1_reg, conf2_reg;
switch (port_type) {
case XAUIC:
@@ -1487,6 +1486,7 @@ nlm_nae_open_if(uint64_t nae_base, int nblock, int port_type,
/* clear gmac reset */
mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
nlm_write_nae_reg(nae_base, conf1_reg, mac_cfg1 & ~(1 << 31));
+
/* clear speed debug bit */
iface_ctrl3_reg = SGMII_NET_IFACE_CTRL3(nblock, iface);
netior_ctrl3 = nlm_read_nae_reg(nae_base, iface_ctrl3_reg);
@@ -1500,33 +1500,21 @@ nlm_nae_open_if(uint64_t nae_base, int nblock, int port_type,
nlm_write_nae_reg(nae_base, iface_ctrl_reg,
netwk_inf & ~(0x1 << 2));
- /* setup defaults */ /* XXXJC: take defaults from sc? */
- speed = 2;
- duplex = 1;
- ifmode = 0x2;
- netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
- netwk_inf &= ~(0x3);
- nlm_write_nae_reg(nae_base, iface_ctrl_reg,
- netwk_inf | (speed & 0x3));
- mac_cfg2 = nlm_read_nae_reg(nae_base, conf2_reg);
- mac_cfg2 &= ~(0x3 << 8);
- nlm_write_nae_reg(nae_base, conf2_reg,
- mac_cfg2 |
- ((ifmode & 0x3) << 8) | /* interface mode */
- (duplex & 0x1));
-
/* clear stats counters */
netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
nlm_write_nae_reg(nae_base, iface_ctrl_reg,
netwk_inf | (1 << 15));
+
/* enable stats counters */
netwk_inf = nlm_read_nae_reg(nae_base, iface_ctrl_reg);
nlm_write_nae_reg(nae_base, iface_ctrl_reg,
(netwk_inf & ~(1 << 15)) | (1 << 16));
+
+ /* flow control? */
mac_cfg1 = nlm_read_nae_reg(nae_base, conf1_reg);
nlm_write_nae_reg(nae_base, conf1_reg,
mac_cfg1 | (0x3 << 4));
- break;
+ break;
}
nlm_nae_init_ingress(nae_base, desc_size);
diff --git a/sys/mips/nlm/dev/net/sgmii.c b/sys/mips/nlm/dev/net/sgmii.c
index 91f5f7a..18b1411 100644
--- a/sys/mips/nlm/dev/net/sgmii.c
+++ b/sys/mips/nlm/dev/net/sgmii.c
@@ -69,13 +69,6 @@ nlm_configure_sgmii_interface(uint64_t nae_base, int block, int port,
void
nlm_sgmii_pcs_init(uint64_t nae_base, uint32_t cplx_mask)
{
- /* reset internal MDIO */
- nlm_int_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
-
- /* reset external MDIO */
- nlm_gmac_mdio_reset(nae_base, 0, BLOCK_7, LANE_CFG);
- nlm_gmac_mdio_reset(nae_base, 1, BLOCK_7, LANE_CFG);
-
xlp_nae_config_lane_gmac(nae_base, cplx_mask);
}
diff --git a/sys/mips/nlm/dev/net/xlpge.c b/sys/mips/nlm/dev/net/xlpge.c
index 0e41559..6d221e4 100644
--- a/sys/mips/nlm/dev/net/xlpge.c
+++ b/sys/mips/nlm/dev/net/xlpge.c
@@ -444,6 +444,8 @@ nlm_xlpnae_init(int node, struct nlm_xlpnae_softc *sc)
val = nlm_set_device_frequency(node, DFS_DEVICE_NAE, sc->freq);
printf("Setup NAE frequency to %dMHz\n", val);
+ nlm_mdio_reset_all(nae_base);
+
printf("Initialze SGMII PCS for blocks 0x%x\n", sc->sgmiimask);
nlm_sgmii_pcs_init(nae_base, sc->sgmiimask);
@@ -797,8 +799,9 @@ nlm_xlpge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
nlm_xlpge_init(sc);
- nlm_xlpge_mac_set_rx_mode(sc);
- nlm_xlpge_port_enable(sc);
+ else
+ nlm_xlpge_port_enable(sc);
+ nlm_xlpge_mac_set_rx_mode(sc);
sc->link = NLM_LINK_UP;
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
@@ -866,6 +869,7 @@ xlpge_tx(struct ifnet *ifp, struct mbuf *mbuf_chain)
vm_offset_t buf = (vm_offset_t) m->m_data;
int len = m->m_len;
int frag_sz;
+ uint64_t desc;
/*printf("m_data = %p len %d\n", m->m_data, len); */
while (len) {
@@ -880,8 +884,9 @@ xlpge_tx(struct ifnet *ifp, struct mbuf *mbuf_chain)
frag_sz = PAGE_SIZE - (buf & PAGE_MASK);
if (len < frag_sz)
frag_sz = len;
- p2p->frag[pos] = nae_tx_desc(P2D_NEOP, 0, 127,
+ desc = nae_tx_desc(P2D_NEOP, 0, 127,
frag_sz, paddr);
+ p2p->frag[pos] = htobe64(desc);
pos++;
len -= frag_sz;
buf += frag_sz;
@@ -891,7 +896,7 @@ xlpge_tx(struct ifnet *ifp, struct mbuf *mbuf_chain)
KASSERT(pos != 0, ("Zero-length mbuf chain?\n"));
/* Make the last one P2D EOP */
- p2p->frag[pos-1] |= (uint64_t)P2D_EOP << 62;
+ p2p->frag[pos-1] |= htobe64((uint64_t)P2D_EOP << 62);
/* stash useful pointers in the desc */
p2p->frag[XLP_NTXFRAGS-3] = 0xf00bad;
@@ -1128,7 +1133,8 @@ get_buf(void)
if ((m_new = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR)) == NULL)
return (NULL);
m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
- m_adj(m_new, NAE_CACHELINE_SIZE - ((uintptr_t)m_new->m_data & 0x1f));
+ KASSERT(((uintptr_t)m_new->m_data & (NAE_CACHELINE_SIZE - 1)) == 0,
+ ("m_new->m_data is not cacheline aligned"));
md = (uint64_t *)m_new->m_data;
md[0] = (intptr_t)m_new; /* Back Ptr */
md[1] = 0xf00bad;
@@ -1137,10 +1143,9 @@ get_buf(void)
#ifdef INVARIANTS
temp1 = vtophys((vm_offset_t) m_new->m_data);
temp2 = vtophys((vm_offset_t) m_new->m_data + 1536);
- KASSERT(temp1 + 1536) != temp2,
+ KASSERT((temp1 + 1536) != temp2,
("Alloced buffer is not contiguous"));
#endif
-
return ((void *)m_new->m_data);
}
@@ -1288,6 +1293,7 @@ nlm_xlpge_attach(device_t dev)
nlm_xlpge_ifinit(sc);
ifp_ports[port].xlpge_sc = sc;
nlm_xlpge_mii_init(dev, sc);
+
nlm_xlpge_setup_stats_sysctl(dev, sc);
return (0);
@@ -1364,13 +1370,13 @@ nlm_xlpge_mii_statchg(device_t dev)
if (mii->mii_media_status & IFM_ACTIVE) {
if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) {
sc->speed = NLM_SGMII_SPEED_10;
- speed = "10-Mbps";
+ speed = "10Mbps";
} else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) {
sc->speed = NLM_SGMII_SPEED_100;
- speed = "100-Mbps";
+ speed = "100Mbps";
} else { /* default to 1G */
sc->speed = NLM_SGMII_SPEED_1000;
- speed = "1-Gbps";
+ speed = "1Gbps";
}
if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
@@ -1381,11 +1387,11 @@ nlm_xlpge_mii_statchg(device_t dev)
duplexity = "half";
}
- printf("Setup [complex=%d, port=%d] with speed=%s duplex=%s\n",
+ printf("Port [%d, %d] setup with speed=%s duplex=%s\n",
sc->block, sc->port, speed, duplexity);
nlm_nae_setup_mac(sc->base_addr, sc->block, sc->port, 0, 1, 1,
- sc->speed, sc->duplexity);
+ sc->speed, sc->duplexity);
}
}
@@ -1548,7 +1554,7 @@ nlm_xlpge_msgring_handler(int vc, int size, int code, int src_id,
ifp->if_opackets++;
} else if (size > 1) { /* Recieve packet */
- phys_addr = msg->msg[1] & 0xffffffffe0ULL;
+ phys_addr = msg->msg[1] & 0xffffffffc0ULL;
length = (msg->msg[1] >> 40) & 0x3fff;
length -= MAC_CRC_LEN;
diff --git a/sys/mips/nlm/hal/fmn.c b/sys/mips/nlm/hal/fmn.c
index 6d40134..8ebc7537 100644
--- a/sys/mips/nlm/hal/fmn.c
+++ b/sys/mips/nlm/hal/fmn.c
@@ -138,9 +138,9 @@ uint32_t nlm_cms_total_stations = 18 * 4 /*xlp_num_nodes*/;
void nlm_cms_setup_credits(uint64_t base, int destid, int srcid, int credit)
{
- uint32_t val;
+ uint64_t val;
- val = ((credit << 24) | (destid << 12) | (srcid << 0));
+ val = (((uint64_t)credit << 24) | (destid << 12) | (srcid << 0));
nlm_write_cms_reg(base, CMS_OUTPUTQ_CREDIT_CFG, val);
}
diff --git a/sys/mips/nlm/hal/mdio.h b/sys/mips/nlm/hal/mdio.h
index a1e720b..31b2aa0 100644
--- a/sys/mips/nlm/hal/mdio.h
+++ b/sys/mips/nlm/hal/mdio.h
@@ -100,6 +100,7 @@ int nlm_int_gmac_mdio_reset(uint64_t, int, int, int);
int nlm_gmac_mdio_read(uint64_t, int, int, int, int, int);
int nlm_gmac_mdio_write(uint64_t, int, int, int, int, int, uint16_t);
int nlm_gmac_mdio_reset(uint64_t, int, int, int);
+void nlm_mdio_reset_all(uint64_t);
#endif /* !(LOCORE) && !(__ASSEMBLY__) */
#endif
diff --git a/sys/mips/nlm/hal/sys.h b/sys/mips/nlm/hal/sys.h
index adfd8a8..2092d37 100644
--- a/sys/mips/nlm/hal/sys.h
+++ b/sys/mips/nlm/hal/sys.h
@@ -140,5 +140,18 @@ enum {
INVALID_DFS_DEVICE = 0xFF
};
+static __inline
+void nlm_sys_enable_block(uint64_t sys_base, int block)
+{
+ uint32_t dfsdis, mask;
+
+ mask = 1 << block;
+ dfsdis = nlm_read_sys_reg(sys_base, SYS_DFS_DIS_CTRL);
+ if ((dfsdis & mask) == 0)
+ return; /* already enabled, nothing to do */
+ dfsdis &= ~mask;
+ nlm_write_sys_reg(sys_base, SYS_DFS_DIS_CTRL, dfsdis);
+}
+
#endif
#endif
diff --git a/sys/mips/nlm/hal/ucore_loader.h b/sys/mips/nlm/hal/ucore_loader.h
index 8298c82..cace077 100644
--- a/sys/mips/nlm/hal/ucore_loader.h
+++ b/sys/mips/nlm/hal/ucore_loader.h
@@ -49,7 +49,7 @@ nlm_ucore_load_image(uint64_t nae_base, int ucore)
size = sizeof(ucore_app_bin)/sizeof(uint32_t);
for (i = 0; i < size; i++, addr += 4)
- nlm_store_word_daddr(addr, p[i]);
+ nlm_store_word_daddr(addr, htobe32(p[i]));
/* add a 'nop' if number of instructions are odd */
if (size & 0x1)
diff --git a/sys/mips/nlm/xlp_machdep.c b/sys/mips/nlm/xlp_machdep.c
index a4ffc73..f95592e 100644
--- a/sys/mips/nlm/xlp_machdep.c
+++ b/sys/mips/nlm/xlp_machdep.c
@@ -157,6 +157,20 @@ xlp_setup_mmu(void)
}
static void
+xlp_enable_blocks(void)
+{
+ uint64_t sysbase;
+ int i;
+
+ for (i = 0; i < XLP_MAX_NODES; i++) {
+ if (!nlm_dev_exists(XLP_IO_SYS_OFFSET(i)))
+ continue;
+ sysbase = nlm_get_sys_regbase(i);
+ nlm_sys_enable_block(sysbase, DFS_DEVICE_RSA);
+ }
+}
+
+static void
xlp_parse_mmu_options(void)
{
uint64_t sysbase;
@@ -420,9 +434,8 @@ xlp_pic_init(void)
#define XLP_MEM_LIM 0xfffff000UL
#endif
static vm_paddr_t xlp_mem_excl[] = {
- 0, 0, /* entry for kernel image, set by xlp_mem_init*/
- 0x0c000000, 0x0d000000, /* uboot mess */
- 0x10000000, 0x14000000, /* cms queue and other stuff */
+ 0, 0, /* for kernel image region, see xlp_mem_init */
+ 0x0c000000, 0x14000000, /* uboot area, cms queue and other stuff */
0x1fc00000, 0x1fd00000, /* reset vec */
0x1e000000, 0x1e200000, /* poe buffers */
};
@@ -559,6 +572,8 @@ platform_start(__register_t a0 __unused,
/* setup for the startup core */
xlp_setup_mmu();
+ xlp_enable_blocks();
+
/* Read/Guess/setup board information */
nlm_board_info_setup();
diff --git a/sys/mips/nlm/xlp_pci.c b/sys/mips/nlm/xlp_pci.c
index 0610a15..23bd46c 100644
--- a/sys/mips/nlm/xlp_pci.c
+++ b/sys/mips/nlm/xlp_pci.c
@@ -487,12 +487,14 @@ xlp_pcib_write_config(device_t dev, u_int b, u_int s, u_int f,
}
/*
- * Enable byte swap in hardware. Program a link's PCIe SWAP regions
- * from the link's IO and MEM address ranges.
+ * Enable byte swap in hardware when compiled big-endian.
+ * Programs a link's PCIe SWAP regions from the link's IO and MEM address
+ * ranges.
*/
static void
xlp_pcib_hardware_swap_enable(int node, int link)
{
+#if BYTE_ORDER == BIG_ENDIAN
uint64_t bbase, linkpcibase;
uint32_t bar;
int pcieoffset;
@@ -514,6 +516,7 @@ xlp_pcib_hardware_swap_enable(int node, int link)
bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_LIMIT0 + link);
nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_LIM, bar | 0xFFF);
+#endif
}
static int
diff --git a/sys/mips/rmi/msgring_xls.cfg b/sys/mips/rmi/msgring_xls.cfg
index 35bfb17..35bfb17 100755..100644
--- a/sys/mips/rmi/msgring_xls.cfg
+++ b/sys/mips/rmi/msgring_xls.cfg
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 1344297..28cb56c 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -335,6 +335,7 @@ SUBDIR= \
vge \
${_viawd} \
vkbd \
+ ${_vmm} \
${_vpo} \
vr \
vte \
@@ -720,6 +721,7 @@ _twa= twa
_vesa= vesa
_viawd= viawd
_virtio= virtio
+_vmm= vmm
_vxge= vxge
_x86bios= x86bios
_wbwd= wbwd
diff --git a/sys/modules/cxgbe/tom/Makefile b/sys/modules/cxgbe/tom/Makefile
index 72721be..d02afd4 100644
--- a/sys/modules/cxgbe/tom/Makefile
+++ b/sys/modules/cxgbe/tom/Makefile
@@ -10,15 +10,20 @@ CXGBE = ${.CURDIR}/../../../dev/cxgbe
KMOD = t4_tom
SRCS = t4_tom.c t4_connect.c t4_listen.c t4_cpl_io.c t4_tom_l2t.c t4_ddp.c
SRCS+= device_if.h bus_if.h pci_if.h
-SRCS+= opt_inet.h
+SRCS+= opt_inet.h opt_inet6.h
CFLAGS+= -I${CXGBE}
.if !defined(KERNBUILDDIR)
.if ${MK_INET_SUPPORT} != "no"
opt_inet.h:
- echo "#define INET 1" > ${.TARGET}
- echo "#define TCP_OFFLOAD 1" >> ${.TARGET}
+ @echo "#define INET 1" > ${.TARGET}
+ @echo "#define TCP_OFFLOAD 1" >> ${.TARGET}
+.endif
+
+.if ${MK_INET6_SUPPORT} != "no"
+opt_inet6.h:
+ @echo "#define INET6 1" > ${.TARGET}
.endif
.endif
diff --git a/sys/modules/digi/Makefile b/sys/modules/digi/Makefile
index 9d9aea6..9d9aea6 100755..100644
--- a/sys/modules/digi/Makefile
+++ b/sys/modules/digi/Makefile
diff --git a/sys/modules/digi/Makefile.inc b/sys/modules/digi/Makefile.inc
index 265f86d..265f86d 100755..100644
--- a/sys/modules/digi/Makefile.inc
+++ b/sys/modules/digi/Makefile.inc
diff --git a/sys/modules/hpt27xx/Makefile b/sys/modules/hpt27xx/Makefile
index 883229b..82b51408 100644
--- a/sys/modules/hpt27xx/Makefile
+++ b/sys/modules/hpt27xx/Makefile
@@ -12,6 +12,3 @@ hpt27xx_lib.o:
uudecode -p < ${HPT27XX}/$(MACHINE_ARCH)-elf.hpt27xx_lib.o.uu > ${.TARGET}
.include <bsd.kmod.mk>
-
-CWARNFLAGS.osm_bsd.c= ${NO_WFORMAT_SECURITY}
-CWARNFLAGS+= ${CWARNFLAGS.${.IMPSRC:T}}
diff --git a/sys/modules/isci/Makefile b/sys/modules/isci/Makefile
index 82d4018..82d4018 100755..100644
--- a/sys/modules/isci/Makefile
+++ b/sys/modules/isci/Makefile
diff --git a/sys/modules/sound/driver/ich/Makefile b/sys/modules/sound/driver/ich/Makefile
index e0f2ce7..e0f2ce7 100755..100644
--- a/sys/modules/sound/driver/ich/Makefile
+++ b/sys/modules/sound/driver/ich/Makefile
diff --git a/sys/modules/usb/Makefile b/sys/modules/usb/Makefile
index 4492755..6481838 100644
--- a/sys/modules/usb/Makefile
+++ b/sys/modules/usb/Makefile
@@ -36,7 +36,7 @@ SUBDIR += ${_rum} run ${_uath} upgt usie ural ${_zyd} ${_urtw}
SUBDIR += atp uhid ukbd ums udbp ufm uep
SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \
umct umcs umodem umoscom uplcom uslcom uvisor uvscom
-SUBDIR += uether aue axe cdce cue ${_kue} mos rue udav uhso ipheth
+SUBDIR += uether aue axe cdce cue ${_kue} mos rue smsc udav uhso ipheth
SUBDIR += usfs umass urio
SUBDIR += quirk template
diff --git a/sys/modules/usb/smsc/Makefile b/sys/modules/usb/smsc/Makefile
index a97e9ba..c6f2de8 100644
--- a/sys/modules/usb/smsc/Makefile
+++ b/sys/modules/usb/smsc/Makefile
@@ -31,7 +31,7 @@ S= ${.CURDIR}/../../..
KMOD= if_smsc
SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h \
- miibus_if.h opt_inet.h \
+ miibus_if.h opt_inet.h opt_platform.h \
if_smsc.c
.include <bsd.kmod.mk>
diff --git a/sys/modules/vmm/Makefile b/sys/modules/vmm/Makefile
new file mode 100644
index 0000000..8b565da
--- /dev/null
+++ b/sys/modules/vmm/Makefile
@@ -0,0 +1,62 @@
+# $FreeBSD$
+
+KMOD= vmm
+
+SRCS= opt_ddb.h device_if.h bus_if.h pci_if.h
+
+CFLAGS+= -DVMM_KEEP_STATS -DSMP
+CFLAGS+= -I${.CURDIR}/../../amd64/vmm
+CFLAGS+= -I${.CURDIR}/../../amd64/vmm/io
+CFLAGS+= -I${.CURDIR}/../../amd64/vmm/intel
+
+# generic vmm support
+.PATH: ${.CURDIR}/../../amd64/vmm
+SRCS+= vmm.c \
+ vmm_dev.c \
+ vmm_host.c \
+ vmm_instruction_emul.c \
+ vmm_ipi.c \
+ vmm_lapic.c \
+ vmm_mem.c \
+ vmm_msr.c \
+ vmm_stat.c \
+ vmm_util.c \
+ x86.c \
+ vmm_support.S
+
+.PATH: ${.CURDIR}/../../amd64/vmm/io
+SRCS+= iommu.c \
+ ppt.c \
+ vdev.c \
+ vlapic.c
+
+# intel-specific files
+.PATH: ${.CURDIR}/../../amd64/vmm/intel
+SRCS+= ept.c \
+ vmcs.c \
+ vmx_msr.c \
+ vmx.c \
+ vtd.c
+
+# amd-specific files
+.PATH: ${.CURDIR}/../../amd64/vmm/amd
+SRCS+= amdv.c
+
+OBJS= vmx_support.o
+
+CLEANFILES= vmx_assym.s vmx_genassym.o
+
+vmx_assym.s: vmx_genassym.o
+.if exists(@)
+vmx_assym.s: @/kern/genassym.sh
+.endif
+ sh @/kern/genassym.sh vmx_genassym.o > ${.TARGET}
+
+vmx_support.o: vmx_support.S vmx_assym.s
+ ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
+ ${.IMPSRC} -o ${.TARGET}
+
+vmx_genassym.o: vmx_genassym.c @ machine x86
+ ${CC} -c ${CFLAGS:N-fno-common} ${.IMPSRC}
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/wlan/Makefile b/sys/modules/wlan/Makefile
index 7205e28..30aa745 100644
--- a/sys/modules/wlan/Makefile
+++ b/sys/modules/wlan/Makefile
@@ -12,7 +12,7 @@ SRCS= ieee80211.c ieee80211_action.c ieee80211_ageq.c \
ieee80211_ratectl_none.c ieee80211_regdomain.c \
ieee80211_ht.c ieee80211_hwmp.c ieee80211_adhoc.c ieee80211_hostap.c \
ieee80211_monitor.c ieee80211_sta.c ieee80211_wds.c ieee80211_ddb.c \
- ieee80211_tdma.c
+ ieee80211_tdma.c ieee80211_superg.c
SRCS+= bus_if.h device_if.h opt_ddb.h opt_inet.h opt_inet6.h opt_ipx.h \
opt_tdma.h opt_wlan.h
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 9ee1964..ba31c66 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -522,32 +522,15 @@ bpf_movein(struct uio *uio, int linktype, struct ifnet *ifp, struct mbuf **mp,
}
len = uio->uio_resid;
-
- if (len - hlen > ifp->if_mtu)
+ if (len < hlen || len - hlen > ifp->if_mtu)
return (EMSGSIZE);
- if ((unsigned)len > MJUM16BYTES)
+ m = m_get2(M_WAITOK, MT_DATA, M_PKTHDR, len);
+ if (m == NULL)
return (EIO);
-
- if (len <= MHLEN)
- MGETHDR(m, M_WAITOK, MT_DATA);
- else if (len <= MCLBYTES)
- m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
- else
- m = m_getjcl(M_WAITOK, MT_DATA, M_PKTHDR,
-#if (MJUMPAGESIZE > MCLBYTES)
- len <= MJUMPAGESIZE ? MJUMPAGESIZE :
-#endif
- (len <= MJUM9BYTES ? MJUM9BYTES : MJUM16BYTES));
m->m_pkthdr.len = m->m_len = len;
- m->m_pkthdr.rcvif = NULL;
*mp = m;
- if (m->m_len < hlen) {
- error = EPERM;
- goto bad;
- }
-
error = uiomove(mtod(m, u_char *), len, uio);
if (error)
goto bad;
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 0428cbe..3634d0b 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -789,7 +789,7 @@ lagg_port_output(struct ifnet *ifp, struct mbuf *m,
/* drop any other frames */
m_freem(m);
- return (EBUSY);
+ return (ENETDOWN);
}
static void
@@ -1862,7 +1862,7 @@ lagg_lacp_start(struct lagg_softc *sc, struct mbuf *m)
lp = lacp_select_tx_port(sc, m);
if (lp == NULL) {
m_freem(m);
- return (EBUSY);
+ return (ENETDOWN);
}
/* Send mbuf */
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
index 5812623..84ea6c6 100644
--- a/sys/net/if_llatbl.c
+++ b/sys/net/if_llatbl.c
@@ -273,10 +273,9 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
u_int laflags = 0, flags = 0;
int error = 0;
- if (dl == NULL || dl->sdl_family != AF_LINK) {
- log(LOG_INFO, "%s: invalid dl\n", __func__);
- return EINVAL;
- }
+ KASSERT(dl != NULL && dl->sdl_family == AF_LINK,
+ ("%s: invalid dl\n", __func__));
+
ifp = ifnet_byindex(dl->sdl_index);
if (ifp == NULL) {
log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n",
@@ -286,28 +285,8 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
switch (rtm->rtm_type) {
case RTM_ADD:
- if (rtm->rtm_flags & RTF_ANNOUNCE) {
+ if (rtm->rtm_flags & RTF_ANNOUNCE)
flags |= LLE_PUB;
-#ifdef INET
- if (dst->sa_family == AF_INET &&
- ((struct sockaddr_inarp *)dst)->sin_other != 0) {
- struct rtentry *rt;
- ((struct sockaddr_inarp *)dst)->sin_other = 0;
- rt = rtalloc1(dst, 0, 0);
- if (rt == NULL || !(rt->rt_flags & RTF_HOST)) {
- log(LOG_INFO, "%s: RTM_ADD publish "
- "(proxy only) is invalid\n",
- __func__);
- if (rt)
- RTFREE_LOCKED(rt);
- return EINVAL;
- }
- RTFREE_LOCKED(rt);
-
- flags |= LLE_PROXY;
- }
-#endif
- }
flags |= LLE_CREATE;
break;
@@ -346,7 +325,7 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
* LLE_DELETED flag, and reset the expiration timer
*/
bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen);
- lle->la_flags |= (flags & (LLE_PUB | LLE_PROXY));
+ lle->la_flags |= (flags & LLE_PUB);
lle->la_flags |= LLE_VALID;
lle->la_flags &= ~LLE_DELETED;
#ifdef INET6
@@ -368,15 +347,12 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
laflags = lle->la_flags;
LLE_WUNLOCK(lle);
#ifdef INET
- /* gratuitous ARP */
- if ((laflags & LLE_PUB) && dst->sa_family == AF_INET) {
+ /* gratuitous ARP */
+ if ((laflags & LLE_PUB) && dst->sa_family == AF_INET)
arprequest(ifp,
&((struct sockaddr_in *)dst)->sin_addr,
&((struct sockaddr_in *)dst)->sin_addr,
- ((laflags & LLE_PROXY) ?
- (u_char *)IF_LLADDR(ifp) :
- (u_char *)LLADDR(dl)));
- }
+ (u_char *)LLADDR(dl));
#endif
} else {
if (flags & LLE_EXCLUSIVE)
diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h
index 8da08ba..693ccd5 100644
--- a/sys/net/if_llatbl.h
+++ b/sys/net/if_llatbl.h
@@ -172,7 +172,6 @@ MALLOC_DECLARE(M_LLTABLE);
#define LLE_STATIC 0x0002 /* entry is static */
#define LLE_IFADDR 0x0004 /* entry is interface addr */
#define LLE_VALID 0x0008 /* ll_addr is valid */
-#define LLE_PROXY 0x0010 /* proxy entry ??? */
#define LLE_PUB 0x0020 /* publish entry ??? */
#define LLE_LINKED 0x0040 /* linked to lookup structure */
#define LLE_EXCLUSIVE 0x2000 /* return lle xlocked */
@@ -205,4 +204,14 @@ lla_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
}
int lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *);
+
+#include <sys/eventhandler.h>
+enum {
+ LLENTRY_RESOLVED,
+ LLENTRY_TIMEDOUT,
+ LLENTRY_DELETED,
+ LLENTRY_EXPIRED,
+};
+typedef void (*lle_event_fn)(void *, struct llentry *, int);
+EVENTHANDLER_DECLARE(lle_event, lle_event_fn);
#endif /* _NET_IF_LLATBL_H_ */
diff --git a/sys/net/netmap.h b/sys/net/netmap.h
index 1aa5e29..638cb18 100644
--- a/sys/net/netmap.h
+++ b/sys/net/netmap.h
@@ -32,7 +32,7 @@
/*
* $FreeBSD$
- * $Id: netmap.h 10601 2012-02-21 16:40:14Z luigi $
+ * $Id: netmap.h 11997 2013-01-17 21:59:12Z luigi $
*
* Definitions of constants and the structures used by the netmap
* framework, for the part visible to both kernel and userspace.
@@ -113,15 +113,28 @@
* In the kernel, buffers do not necessarily need to be contiguous,
* and the virtual and physical addresses are derived through
* a lookup table.
- * To associate a different buffer to a slot, applications must
- * write the new index in buf_idx, and set NS_BUF_CHANGED flag to
- * make sure that the kernel updates the hardware ring as needed.
*
- * Normally the driver is not requested to report the result of
- * transmissions (this can dramatically speed up operation).
- * However the user may request to report completion by setting
- * NS_REPORT.
+ * struct netmap_slot:
+ *
+ * buf_idx is the index of the buffer associated to the slot.
+ * len is the length of the payload
+ * NS_BUF_CHANGED must be set whenever userspace wants
+ * to change buf_idx (it might be necessary to
+ * reprogram the NIC slot)
+ * NS_REPORT must be set if we want the NIC to generate an interrupt
+ * when this slot is used. Leaving it to 0 improves
+ * performance.
+ * NS_FORWARD if set on a receive ring, and the device is in
+ * transparent mode, buffers released with the flag set
+ * will be forwarded to the 'other' side (host stack
+ * or NIC, respectively) on the next select() or ioctl()
+ * NS_NO_LEARN on a VALE switch, do not 'learn' the source port for
+ * this packet.
+ * NS_PORT_MASK the high 8 bits of the flag, if not zero, indicate the
+ * destination port for the VALE switch, overriding
+ * the lookup table.
*/
+
struct netmap_slot {
uint32_t buf_idx; /* buffer index */
uint16_t len; /* packet length, to be copied to/from the hw ring */
@@ -130,6 +143,12 @@ struct netmap_slot {
#define NS_REPORT 0x0002 /* ask the hardware to report results
* e.g. by generating an interrupt
*/
+#define NS_FORWARD 0x0004 /* pass packet to the other endpoint
+ * (host stack or device)
+ */
+#define NS_NO_LEARN 0x0008
+#define NS_PORT_SHIFT 8
+#define NS_PORT_MASK (0xff << NS_PORT_SHIFT)
};
/*
@@ -186,6 +205,18 @@ struct netmap_slot {
* a system call.
*
* The netmap_kring is only modified by the upper half of the kernel.
+ *
+ * FLAGS
+ * NR_TIMESTAMP updates the 'ts' field on each syscall. This is
+ * a global timestamp for all packets.
+ * NR_RX_TSTMP if set, the last 64 byte in each buffer will
+ * contain a timestamp for the frame supplied by
+ * the hardware (if supported)
+ * NR_FORWARD if set, the NS_FORWARD flag in each slot of the
+ * RX ring is checked, and if set the packet is
+ * passed to the other side (host stack or device,
+ * respectively). This permits bpf-like behaviour
+ * or transparency for selected packets.
*/
struct netmap_ring {
/*
@@ -202,6 +233,8 @@ struct netmap_ring {
const uint16_t nr_buf_size;
uint16_t flags;
#define NR_TIMESTAMP 0x0002 /* set timestamp on *sync() */
+#define NR_FORWARD 0x0004 /* enable NS_FORWARD for ring */
+#define NR_RX_TSTMP 0x0008 /* set rx timestamp in slots */
struct timeval ts; /* time of last *sync() */
diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c
index 0220474..b0998f5 100644
--- a/sys/net80211/ieee80211_adhoc.c
+++ b/sys/net80211/ieee80211_adhoc.c
@@ -688,6 +688,7 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
struct ieee80211_frame *wh;
uint8_t *frm, *efrm, *sfrm;
uint8_t *ssid, *rates, *xrates;
+ int ht_state_change = 0;
wh = mtod(m0, struct ieee80211_frame *);
frm = (uint8_t *)&wh[1];
@@ -748,10 +749,27 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
memcpy(ni->ni_tstamp.data, scan.tstamp,
sizeof(ni->ni_tstamp));
}
+ /*
+ * This isn't enabled yet - otherwise it would
+ * update the HT parameters and channel width
+ * from any node, which could lead to lots of
+ * strange behaviour if the 11n nodes aren't
+ * exactly configured to match.
+ */
+#if 0
+ if (scan.htcap != NULL && scan.htinfo != NULL &&
+ (vap->iv_flags_ht & IEEE80211_FHT_HT)) {
+ if (ieee80211_ht_updateparams(ni,
+ scan.htcap, scan.htinfo))
+ ht_state_change = 1;
+ }
+#endif
if (ni != NULL) {
IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
ni->ni_noise = nf;
}
+ if (ht_state_change)
+ ieee80211_update_chw(ic);
}
break;
}
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 7ed3523..a81c481 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -771,6 +771,7 @@ ieee80211_sta_join(struct ieee80211vap *vap, struct ieee80211_channel *chan,
/* XXX msg */
return 0;
}
+
/*
* Expand scan state into node's format.
* XXX may not need all this stuff
@@ -821,6 +822,29 @@ ieee80211_sta_join(struct ieee80211vap *vap, struct ieee80211_channel *chan,
IEEE80211_F_DOSORT);
if (ieee80211_iserp_rateset(&ni->ni_rates))
ni->ni_flags |= IEEE80211_NODE_ERP;
+
+ /*
+ * Setup HT state for this node if it's available, otherwise
+ * non-STA modes won't pick this state up.
+ *
+ * For IBSS and related modes that don't go through an
+ * association request/response, the only appropriate place
+ * to setup the HT state is here.
+ */
+ if (ni->ni_ies.htinfo_ie != NULL &&
+ ni->ni_ies.htcap_ie != NULL &&
+ vap->iv_flags_ht & IEEE80211_FHT_HT) {
+ ieee80211_ht_node_init(ni);
+ ieee80211_ht_updateparams(ni,
+ ni->ni_ies.htcap_ie,
+ ni->ni_ies.htinfo_ie);
+ ieee80211_setup_htrates(ni, ni->ni_ies.htcap_ie,
+ IEEE80211_F_JOIN | IEEE80211_F_DOBRS);
+ ieee80211_setup_basic_htrates(ni, ni->ni_ies.htinfo_ie);
+ }
+ /* XXX else check for ath FF? */
+ /* XXX QoS? Difficult given that WME config is specific to a master */
+
ieee80211_node_setuptxparms(ni);
ieee80211_ratectl_node_init(ni);
@@ -938,6 +962,9 @@ ieee80211_ies_expand(struct ieee80211_ies *ies)
case IEEE80211_ELEMID_HTCAP:
ies->htcap_ie = ie;
break;
+ case IEEE80211_ELEMID_HTINFO:
+ ies->htinfo_ie = ie;
+ break;
#ifdef IEEE80211_SUPPORT_MESH
case IEEE80211_ELEMID_MESHID:
ies->meshid_ie = ie;
@@ -1404,7 +1431,7 @@ ieee80211_fakeup_adhoc_node(struct ieee80211vap *vap,
{
struct ieee80211_node *ni;
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE | IEEE80211_MSG_ASSOC,
"%s: mac<%s>\n", __func__, ether_sprintf(macaddr));
ni = ieee80211_dup_bss(vap, macaddr);
if (ni != NULL) {
@@ -1444,6 +1471,8 @@ ieee80211_init_neighbor(struct ieee80211_node *ni,
const struct ieee80211_frame *wh,
const struct ieee80211_scanparams *sp)
{
+ int do_ht_setup = 0;
+
ni->ni_esslen = sp->ssid[1];
memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
@@ -1469,12 +1498,41 @@ ieee80211_init_neighbor(struct ieee80211_node *ni,
if (ni->ni_ies.ath_ie != NULL)
ieee80211_parse_ath(ni, ni->ni_ies.ath_ie);
#endif
+ if (ni->ni_ies.htcap_ie != NULL)
+ ieee80211_parse_htcap(ni, ni->ni_ies.htcap_ie);
+ if (ni->ni_ies.htinfo_ie != NULL)
+ ieee80211_parse_htinfo(ni, ni->ni_ies.htinfo_ie);
+
+ if ((ni->ni_ies.htcap_ie != NULL) &&
+ (ni->ni_ies.htinfo_ie != NULL) &&
+ (ni->ni_vap->iv_flags_ht & IEEE80211_FHT_HT)) {
+ do_ht_setup = 1;
+ }
}
/* NB: must be after ni_chan is setup */
ieee80211_setup_rates(ni, sp->rates, sp->xrates,
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
+
+ /*
+ * If the neighbor is HT compatible, flip that on.
+ */
+ if (do_ht_setup) {
+ IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_ASSOC,
+ "%s: doing HT setup\n", __func__);
+ ieee80211_ht_node_init(ni);
+ ieee80211_ht_updateparams(ni,
+ ni->ni_ies.htcap_ie,
+ ni->ni_ies.htinfo_ie);
+ ieee80211_setup_htrates(ni,
+ ni->ni_ies.htcap_ie,
+ IEEE80211_F_JOIN | IEEE80211_F_DOBRS);
+ ieee80211_setup_basic_htrates(ni,
+ ni->ni_ies.htinfo_ie);
+ ieee80211_node_setuptxparms(ni);
+ ieee80211_ratectl_node_init(ni);
+ }
}
/*
@@ -1490,7 +1548,7 @@ ieee80211_add_neighbor(struct ieee80211vap *vap,
{
struct ieee80211_node *ni;
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
"%s: mac<%s>\n", __func__, ether_sprintf(wh->i_addr2));
ni = ieee80211_dup_bss(vap, wh->i_addr2);/* XXX alloc_node? */
if (ni != NULL) {
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index 558e1f3..31bc578 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -416,6 +416,8 @@ pwrsave_flushq(struct ieee80211_node *ni)
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_psq_head *qhead;
struct ifnet *parent, *ifp;
+ struct mbuf *parent_q = NULL, *ifp_q = NULL;
+ struct mbuf *m;
IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
"flush ps queue, %u packets queued", psq->psq_len);
@@ -427,8 +429,7 @@ pwrsave_flushq(struct ieee80211_node *ni)
parent = vap->iv_ic->ic_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
- IF_PREPEND_LIST(&parent->if_snd, qhead->head, qhead->tail,
- qhead->len);
+ parent_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
} else
@@ -439,8 +440,7 @@ pwrsave_flushq(struct ieee80211_node *ni)
ifp = vap->iv_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
- IF_PREPEND_LIST(&ifp->if_snd, qhead->head, qhead->tail,
- qhead->len);
+ ifp_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
} else
@@ -450,10 +450,34 @@ pwrsave_flushq(struct ieee80211_node *ni)
/* NB: do this outside the psq lock */
/* XXX packets might get reordered if parent is OACTIVE */
- if (parent != NULL)
- if_start(parent);
- if (ifp != NULL)
- if_start(ifp);
+ /* parent frames, should be encapsulated */
+ if (parent != NULL) {
+ while (parent_q != NULL) {
+ m = parent_q;
+ parent_q = m->m_nextpkt;
+ /* must be encapsulated */
+ KASSERT((m->m_flags & M_ENCAP),
+ ("%s: parentq with non-M_ENCAP frame!\n",
+ __func__));
+ /*
+ * For encaped frames, we need to free the node
+ * reference upon failure.
+ */
+ if (parent->if_transmit(parent, m) != 0)
+ ieee80211_free_node(ni);
+ }
+ }
+
+ /* VAP frames, aren't encapsulated */
+ if (ifp != NULL) {
+ while (ifp_q != NULL) {
+ m = ifp_q;
+ ifp_q = m->m_nextpkt;
+ KASSERT((!(m->m_flags & M_ENCAP)),
+ ("%s: vapq with M_ENCAP frame!\n", __func__));
+ (void) ifp->if_transmit(ifp, m);
+ }
+ }
}
/*
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index 6f5e9d2..381faca 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#ifdef IEEE80211_SUPPORT_MESH
#include <net80211/ieee80211_mesh.h>
#endif
+#include <net80211/ieee80211_ratectl.h>
#include <net/bpf.h>
@@ -1567,6 +1568,7 @@ adhoc_pick_bss(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
struct sta_table *st = ss->ss_priv;
struct sta_entry *selbs;
struct ieee80211_channel *chan;
+ struct ieee80211com *ic = vap->iv_ic;
KASSERT(vap->iv_opmode == IEEE80211_M_IBSS ||
vap->iv_opmode == IEEE80211_M_AHDEMO ||
@@ -1612,15 +1614,19 @@ notfound:
*/
if (vap->iv_des_chan == IEEE80211_CHAN_ANYC ||
IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan)) {
- struct ieee80211com *ic = vap->iv_ic;
-
chan = adhoc_pick_channel(ss, 0);
- if (chan != NULL)
- chan = ieee80211_ht_adjust_channel(ic,
- chan, vap->iv_flags_ht);
} else
chan = vap->iv_des_chan;
if (chan != NULL) {
+ struct ieee80211com *ic = vap->iv_ic;
+ /*
+ * Create a HT capable IBSS; the per-node
+ * probe request/response will result in
+ * "correct" rate control capabilities being
+ * negotiated.
+ */
+ chan = ieee80211_ht_adjust_channel(ic,
+ chan, vap->iv_flags_ht);
ieee80211_create_ibss(vap, chan);
return 1;
}
@@ -1644,6 +1650,14 @@ notfound:
chan = selbs->base.se_chan;
if (selbs->se_flags & STA_DEMOTE11B)
chan = demote11b(vap, chan);
+ /*
+ * If HT is available, make it a possibility here.
+ * The intent is to enable HT20/HT40 when joining a non-HT
+ * IBSS node; we can then advertise HT IEs and speak HT
+ * to any subsequent nodes that support it.
+ */
+ chan = ieee80211_ht_adjust_channel(ic,
+ chan, vap->iv_flags_ht);
if (!ieee80211_sta_join(vap, chan, &selbs->base))
goto notfound;
return 1; /* terminate scan */
diff --git a/sys/net80211/ieee80211_superg.c b/sys/net80211/ieee80211_superg.c
index 0599f45..9ac5878 100644
--- a/sys/net80211/ieee80211_superg.c
+++ b/sys/net80211/ieee80211_superg.c
@@ -28,6 +28,8 @@ __FBSDID("$FreeBSD$");
#include "opt_wlan.h"
+#ifdef IEEE80211_SUPPORT_SUPERG
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
@@ -921,3 +923,5 @@ superg_ioctl_set80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
return 0;
}
IEEE80211_IOCTL_SET(superg, superg_ioctl_set80211);
+
+#endif /* IEEE80211_SUPPORT_SUPERG */
diff --git a/sys/netgraph/ng_ether.c b/sys/netgraph/ng_ether.c
index 05d2e6e..6266f40 100644
--- a/sys/netgraph/ng_ether.c
+++ b/sys/netgraph/ng_ether.c
@@ -117,6 +117,8 @@ static ng_rcvdata_t ng_ether_rcvdata;
static ng_disconnect_t ng_ether_disconnect;
static int ng_ether_mod_event(module_t mod, int event, void *data);
+static eventhandler_tag ng_ether_ifnet_arrival_cookie;
+
/* List of commands and how to convert arguments to/from ASCII */
static const struct ng_cmdlist ng_ether_cmdlist[] = {
{
@@ -214,6 +216,24 @@ static struct ng_type ng_ether_typestruct = {
NETGRAPH_INIT(ether, &ng_ether_typestruct);
/******************************************************************
+ UTILITY FUNCTIONS
+******************************************************************/
+static void
+ng_ether_sanitize_ifname(const char *ifname, char *name)
+{
+ int i;
+
+ for (i = 0; i < IFNAMSIZ; i++) {
+ if (ifname[i] == '.' || ifname[i] == ':')
+ name[i] = '_';
+ else
+ name[i] = ifname[i];
+ if (name[i] == '\0')
+ break;
+ }
+}
+
+/******************************************************************
ETHERNET FUNCTION HOOKS
******************************************************************/
@@ -282,6 +302,7 @@ ng_ether_output(struct ifnet *ifp, struct mbuf **mp)
static void
ng_ether_attach(struct ifnet *ifp)
{
+ char name[IFNAMSIZ];
priv_p priv;
node_p node;
@@ -319,10 +340,9 @@ ng_ether_attach(struct ifnet *ifp)
priv->hwassist = ifp->if_hwassist;
/* Try to give the node the same name as the interface */
- if (ng_name_node(node, ifp->if_xname) != 0) {
- log(LOG_WARNING, "%s: can't name node %s\n",
- __func__, ifp->if_xname);
- }
+ ng_ether_sanitize_ifname(ifp->if_xname, name);
+ if (ng_name_node(node, name) != 0)
+ log(LOG_WARNING, "%s: can't name node %s\n", __func__, name);
}
/*
@@ -378,6 +398,32 @@ ng_ether_link_state(struct ifnet *ifp, int state)
}
}
+/*
+ * Interface arrival notification handler.
+ * The notification is produced in two cases:
+ * o a new interface arrives
+ * o an existing interface got renamed
+ * Currently the first case is handled by ng_ether_attach via special
+ * hook ng_ether_attach_p.
+ */
+static void
+ng_ether_ifnet_arrival_event(void *arg __unused, struct ifnet *ifp)
+{
+ char name[IFNAMSIZ];
+ node_p node = IFP2NG(ifp);
+
+ /*
+ * Just return if it's a new interface without an ng_ether companion.
+ */
+ if (node == NULL)
+ return;
+
+ /* Try to give the node the same name as the new interface name */
+ ng_ether_sanitize_ifname(ifp->if_xname, name);
+ if (ng_name_node(node, name) != 0)
+ log(LOG_WARNING, "%s: can't re-name node %s\n", __func__, name);
+}
+
/******************************************************************
NETGRAPH NODE METHODS
******************************************************************/
@@ -771,6 +817,9 @@ ng_ether_mod_event(module_t mod, int event, void *data)
ng_ether_input_orphan_p = ng_ether_input_orphan;
ng_ether_link_state_p = ng_ether_link_state;
+ ng_ether_ifnet_arrival_cookie =
+ EVENTHANDLER_REGISTER(ifnet_arrival_event,
+ ng_ether_ifnet_arrival_event, NULL, EVENTHANDLER_PRI_ANY);
break;
case MOD_UNLOAD:
@@ -783,6 +832,9 @@ ng_ether_mod_event(module_t mod, int event, void *data)
* is MOD_UNLOAD, so there's no need to detach any nodes.
*/
+ EVENTHANDLER_DEREGISTER(ifnet_arrival_event,
+ ng_ether_ifnet_arrival_cookie);
+
/* Unregister function hooks */
ng_ether_attach_p = NULL;
ng_ether_detach_p = NULL;
diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h
index e37a964..6b47912 100644
--- a/sys/netinet/if_ether.h
+++ b/sys/netinet/if_ether.h
@@ -89,6 +89,7 @@ struct ether_arp {
#define arp_pln ea_hdr.ar_pln
#define arp_op ea_hdr.ar_op
+#ifndef BURN_BRIDGES /* Can be used by third party software. */
struct sockaddr_inarp {
u_char sin_len;
u_char sin_family;
@@ -99,6 +100,8 @@ struct sockaddr_inarp {
u_short sin_other;
#define SIN_PROXY 1
};
+#endif /* !BURN_BRIDGES */
+
/*
* IP and ethernet specific routing flags
*/
@@ -120,17 +123,6 @@ void arprequest(struct ifnet *, struct in_addr *, struct in_addr *,
void arp_ifinit(struct ifnet *, struct ifaddr *);
void arp_ifinit2(struct ifnet *, struct ifaddr *, u_char *);
void arp_ifscrub(struct ifnet *, uint32_t);
-
-#include <sys/eventhandler.h>
-enum {
- LLENTRY_RESOLVED,
- LLENTRY_TIMEDOUT,
- LLENTRY_DELETED,
- LLENTRY_EXPIRED,
-};
-typedef void (*lle_event_fn)(void *, struct llentry *, int);
-EVENTHANDLER_DECLARE(lle_event, lle_event_fn);
-
#endif
#endif
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 2b805c6..3ddb46c 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1494,7 +1494,7 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
/* XXX stack use */
struct {
struct rt_msghdr rtm;
- struct sockaddr_inarp sin;
+ struct sockaddr_in sin;
struct sockaddr_dl sdl;
} arpc;
int error, i;
@@ -1515,7 +1515,7 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
/*
* produce a msg made of:
* struct rt_msghdr;
- * struct sockaddr_inarp; (IPv4)
+ * struct sockaddr_in; (IPv4)
* struct sockaddr_dl;
*/
bzero(&arpc, sizeof(arpc));
@@ -1529,12 +1529,8 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
arpc.sin.sin_addr.s_addr = SIN(lle)->sin_addr.s_addr;
/* publish */
- if (lle->la_flags & LLE_PUB) {
+ if (lle->la_flags & LLE_PUB)
arpc.rtm.rtm_flags |= RTF_ANNOUNCE;
- /* proxy only */
- if (lle->la_flags & LLE_PROXY)
- arpc.sin.sin_other = SIN_PROXY;
- }
sdl = &arpc.sdl;
sdl->sdl_family = AF_LINK;
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 6706bc4..f5e2ef2 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -334,8 +334,7 @@ in_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY)
return (EINVAL);
- anonport = inp->inp_lport == 0 && (nam == NULL ||
- ((struct sockaddr_in *)nam)->sin_port == 0);
+ anonport = nam == NULL || ((struct sockaddr_in *)nam)->sin_port == 0;
error = in_pcbbind_setup(inp, nam, &inp->inp_laddr.s_addr,
&inp->inp_lport, cred);
if (error)
diff --git a/sys/netinet/libalias/alias.c b/sys/netinet/libalias/alias.c
index da28b22..3b2068b 100644
--- a/sys/netinet/libalias/alias.c
+++ b/sys/netinet/libalias/alias.c
@@ -1760,21 +1760,7 @@ m_megapullup(struct mbuf *m, int len) {
if (m->m_next == NULL && M_WRITABLE(m) && M_TRAILINGSPACE(m) >= RESERVE)
return (m);
- if (len <= MCLBYTES - RESERVE) {
- mcl = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
- } else if (len < MJUM16BYTES) {
- int size;
- if (len <= MJUMPAGESIZE - RESERVE) {
- size = MJUMPAGESIZE;
- } else if (len <= MJUM9BYTES - RESERVE) {
- size = MJUM9BYTES;
- } else {
- size = MJUM16BYTES;
- };
- mcl = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, size);
- } else {
- goto bad;
- }
+ mcl = m_get2(M_NOWAIT, MT_DATA, M_PKTHDR, len + RESERVE);
if (mcl == NULL)
goto bad;
diff --git a/sys/netinet/libalias/libalias.3 b/sys/netinet/libalias/libalias.3
index 1837c29..4d02cc4 100644
--- a/sys/netinet/libalias/libalias.3
+++ b/sys/netinet/libalias/libalias.3
@@ -901,39 +901,6 @@ is provided for error checking purposes.
This function can be used if an already-aliased packet needs to have its
original IP header restored for further processing (e.g.\& logging).
.Ed
-.Sh AUTHORS
-.An Charles Mott Aq cm@linktel.net ,
-versions 1.0 - 1.8, 2.0 - 2.4.
-.An Eivind Eklund Aq eivind@FreeBSD.org ,
-versions 1.8b, 1.9 and 2.5.
-Added IRC DCC support as well as contributing a number of architectural
-improvements; added the firewall bypass for FTP/IRC DCC.
-.An Erik Salander Aq erik@whistle.com
-added support for PPTP and RTSP.
-.An Junichi Satoh Aq junichi@junichi.org
-added support for RTSP/PNA.
-.An Ruslan Ermilov Aq ru@FreeBSD.org
-added support for PPTP and LSNAT as well as general hacking.
-.An Paolo Pisati Aq piso@FreeBSD.org
-made the library modular, moving support for all
-protocols (except for IP, TCP and UDP) to external modules.
-.Sh ACKNOWLEDGEMENTS
-Listed below, in approximate chronological order, are individuals who
-have provided valuable comments and/or debugging assistance.
-.Bd -ragged -offset indent
-.An -split
-.An Gary Roberts
-.An Tom Torrance
-.An Reto Burkhalter
-.An Martin Renters
-.An Brian Somers
-.An Paul Traina
-.An Ari Suutari
-.An Dave Remien
-.An J. Fortes
-.An Andrzej Bialecki
-.An Gordon Burditt
-.Ed
.Sh CONCEPTUAL BACKGROUND
This section is intended for those who are planning to modify the source
code or want to create somewhat esoteric applications using the packet
@@ -1475,3 +1442,38 @@ with the
facility and the
.Dv LOG_INFO
level.
+.Sh AUTHORS
+.An Charles Mott Aq cm@linktel.net ,
+versions 1.0 - 1.8, 2.0 - 2.4.
+.An Eivind Eklund Aq eivind@FreeBSD.org ,
+versions 1.8b, 1.9 and 2.5.
+Added IRC DCC support as well as contributing a number of architectural
+improvements; added the firewall bypass for FTP/IRC DCC.
+.An Erik Salander Aq erik@whistle.com
+added support for PPTP and RTSP.
+.An Junichi Satoh Aq junichi@junichi.org
+added support for RTSP/PNA.
+.An Ruslan Ermilov Aq ru@FreeBSD.org
+added support for PPTP and LSNAT as well as general hacking.
+.An Gleb Smirnoff Aq glebius@FreeBSD.org
+ported the library to kernel space.
+.An Paolo Pisati Aq piso@FreeBSD.org
+made the library modular, moving support for all
+protocols (except for IP, TCP and UDP) to external modules.
+.Sh ACKNOWLEDGEMENTS
+Listed below, in approximate chronological order, are individuals who
+have provided valuable comments and/or debugging assistance.
+.Bd -ragged -offset indent
+.An -split
+.An Gary Roberts
+.An Tom Torrance
+.An Reto Burkhalter
+.An Martin Renters
+.An Brian Somers
+.An Paul Traina
+.An Ari Suutari
+.An Dave Remien
+.An J. Fortes
+.An Andrzej Bialecki
+.An Gordon Burditt
+.Ed
diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h
index c714360..fb2f810 100644
--- a/sys/netinet/tcp.h
+++ b/sys/netinet/tcp.h
@@ -149,20 +149,25 @@ struct tcphdr {
#endif /* __BSD_VISIBLE */
/*
- * User-settable options (used with setsockopt).
+ * User-settable options (used with setsockopt). These are discrete
+ * values and are not masked together. Some values appear to be
+ * bitmasks for historical reasons.
*/
-#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
+#define TCP_NODELAY 1 /* don't delay send to coalesce packets */
#if __BSD_VISIBLE
-#define TCP_MAXSEG 0x02 /* set maximum segment size */
-#define TCP_NOPUSH 0x04 /* don't push last block of write */
-#define TCP_NOOPT 0x08 /* don't use TCP options */
-#define TCP_MD5SIG 0x10 /* use MD5 digests (RFC2385) */
-#define TCP_INFO 0x20 /* retrieve tcp_info structure */
-#define TCP_CONGESTION 0x40 /* get/set congestion control algorithm */
-#define TCP_KEEPINIT 0x80 /* N, time to establish connection */
-#define TCP_KEEPIDLE 0x100 /* L,N,X start keeplives after this period */
-#define TCP_KEEPINTVL 0x200 /* L,N interval between keepalives */
-#define TCP_KEEPCNT 0x400 /* L,N number of keepalives before close */
+#define TCP_MAXSEG 2 /* set maximum segment size */
+#define TCP_NOPUSH 4 /* don't push last block of write */
+#define TCP_NOOPT 8 /* don't use TCP options */
+#define TCP_MD5SIG 16 /* use MD5 digests (RFC2385) */
+#define TCP_INFO 32 /* retrieve tcp_info structure */
+#define TCP_CONGESTION 64 /* get/set congestion control algorithm */
+#define TCP_KEEPINIT 128 /* N, time to establish connection */
+#define TCP_KEEPIDLE 256 /* L,N,X start keeplives after this period */
+#define TCP_KEEPINTVL 512 /* L,N interval between keepalives */
+#define TCP_KEEPCNT 1024 /* L,N number of keepalives before close */
+
+/* Start of reserved space for third-party user-settable options. */
+#define TCP_VENDOR SO_VENDOR
#define TCP_CA_NAME_MAX 16 /* max congestion control name length */
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 846887d2..e37de24 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -285,7 +285,7 @@ cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t type)
INP_WLOCK_ASSERT(tp->t_inpcb);
tp->ccv->bytes_this_ack = BYTES_THIS_ACK(tp, th);
- if (tp->snd_cwnd == min(tp->snd_cwnd, tp->snd_wnd))
+ if (tp->snd_cwnd <= tp->snd_wnd)
tp->ccv->flags |= CCF_CWND_LIMITED;
else
tp->ccv->flags &= ~CCF_CWND_LIMITED;
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index 289b58a..5fd29b8 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -106,8 +106,8 @@ tcp_reass_zone_change(void *tag)
/* Set the zone limit and read back the effective value. */
V_tcp_reass_maxseg = nmbclusters / 16;
- uma_zone_set_max(V_tcp_reass_zone, V_tcp_reass_maxseg);
- V_tcp_reass_maxseg = uma_zone_get_max(V_tcp_reass_zone);
+ V_tcp_reass_maxseg = uma_zone_set_max(V_tcp_reass_zone,
+ V_tcp_reass_maxseg);
}
void
@@ -120,8 +120,8 @@ tcp_reass_init(void)
V_tcp_reass_zone = uma_zcreate("tcpreass", sizeof (struct tseg_qent),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
/* Set the zone limit and read back the effective value. */
- uma_zone_set_max(V_tcp_reass_zone, V_tcp_reass_maxseg);
- V_tcp_reass_maxseg = uma_zone_get_max(V_tcp_reass_zone);
+ V_tcp_reass_maxseg = uma_zone_set_max(V_tcp_reass_zone,
+ V_tcp_reass_maxseg);
EVENTHANDLER_REGISTER(nmbclusters_change,
tcp_reass_zone_change, NULL, EVENTHANDLER_PRI_ANY);
}
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 5baf3b8..441c269 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -268,8 +268,8 @@ syncache_init(void)
/* Create the syncache entry zone. */
V_tcp_syncache.zone = uma_zcreate("syncache", sizeof(struct syncache),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
- uma_zone_set_max(V_tcp_syncache.zone, V_tcp_syncache.cache_limit);
- V_tcp_syncache.cache_limit = uma_zone_get_max(V_tcp_syncache.zone);
+ V_tcp_syncache.cache_limit = uma_zone_set_max(V_tcp_syncache.zone,
+ V_tcp_syncache.cache_limit);
}
#ifdef VIMAGE
@@ -1493,6 +1493,15 @@ syncache_respond(struct syncache *sc)
th->th_sum = in6_cksum_pseudo(ip6, tlen + optlen - hlen,
IPPROTO_TCP, 0);
ip6->ip6_hlim = in6_selecthlim(NULL, NULL);
+#ifdef TCP_OFFLOAD
+ if (ADDED_BY_TOE(sc)) {
+ struct toedev *tod = sc->sc_tod;
+
+ error = tod->tod_syncache_respond(tod, sc->sc_todctx, m);
+
+ return (error);
+ }
+#endif
error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
}
#endif
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index b943eb6..48444c1 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -119,6 +119,11 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, keepcnt, CTLFLAG_RW, &tcp_keepcnt, 0,
/* max idle probes */
int tcp_maxpersistidle;
+static int tcp_rexmit_drop_options = 0;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, rexmit_drop_options, CTLFLAG_RW,
+ &tcp_rexmit_drop_options, 0,
+ "Drop TCP options from 3rd and later retransmitted SYN");
+
static int per_cpu_timers = 0;
SYSCTL_INT(_net_inet_tcp, OID_AUTO, per_cpu_timers, CTLFLAG_RW,
&per_cpu_timers , 0, "run tcp timers on all cpus");
@@ -595,7 +600,8 @@ tcp_timer_rexmt(void * xtp)
* header compression code which trashes TCP segments containing
* unknown-to-them TCP options.
*/
- if ((tp->t_state == TCPS_SYN_SENT) && (tp->t_rxtshift == 3))
+ if (tcp_rexmit_drop_options && (tp->t_state == TCPS_SYN_SENT) &&
+ (tp->t_rxtshift == 3))
tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP|TF_SACK_PERMIT);
/*
* If we backed off this far, our srtt estimate is probably bogus.
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 85597d9..ef0aad1 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -370,7 +370,8 @@ tcp_usr_listen(struct socket *so, int backlog, struct thread *td)
tp->t_state = TCPS_LISTEN;
solisten_proto(so, backlog);
#ifdef TCP_OFFLOAD
- tcp_offload_listen_start(tp);
+ if ((so->so_options & SO_NO_OFFLOAD) == 0)
+ tcp_offload_listen_start(tp);
#endif
}
SOCK_UNLOCK(so);
@@ -414,7 +415,8 @@ tcp6_usr_listen(struct socket *so, int backlog, struct thread *td)
tp->t_state = TCPS_LISTEN;
solisten_proto(so, backlog);
#ifdef TCP_OFFLOAD
- tcp_offload_listen_start(tp);
+ if ((so->so_options & SO_NO_OFFLOAD) == 0)
+ tcp_offload_listen_start(tp);
#endif
}
SOCK_UNLOCK(so);
@@ -468,6 +470,7 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
goto out;
#ifdef TCP_OFFLOAD
if (registered_toedevs > 0 &&
+ (so->so_options & SO_NO_OFFLOAD) == 0 &&
(error = tcp_offload_connect(so, nam)) == 0)
goto out;
#endif
@@ -534,6 +537,7 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
goto out;
#ifdef TCP_OFFLOAD
if (registered_toedevs > 0 &&
+ (so->so_options & SO_NO_OFFLOAD) == 0 &&
(error = tcp_offload_connect(so, nam)) == 0)
goto out;
#endif
@@ -550,6 +554,7 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
goto out;
#ifdef TCP_OFFLOAD
if (registered_toedevs > 0 &&
+ (so->so_options & SO_NO_OFFLOAD) == 0 &&
(error = tcp_offload_connect(so, nam)) == 0)
goto out;
#endif
@@ -766,6 +771,7 @@ tcp_usr_rcvd(struct socket *so, int flags)
#ifdef TCP_OFFLOAD
if (tp->t_flags & TF_TOE)
tcp_offload_rcvd(tp);
+ else
#endif
tcp_output(tp);
diff --git a/sys/netinet/toecore.c b/sys/netinet/toecore.c
index 7e498dd..53d4778 100644
--- a/sys/netinet/toecore.c
+++ b/sys/netinet/toecore.c
@@ -52,6 +52,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/in6_pcb.h>
#include <netinet6/nd6.h>
#define TCPSTATES
#include <netinet/tcp.h>
@@ -355,11 +357,14 @@ toe_4tuple_check(struct in_conninfo *inc, struct tcphdr *th, struct ifnet *ifp)
{
struct inpcb *inp;
- if (inc->inc_flags & INC_ISIPV6)
- return (ENOSYS); /* XXX: implement */
-
- inp = in_pcblookup(&V_tcbinfo, inc->inc_faddr, inc->inc_fport,
- inc->inc_laddr, inc->inc_lport, INPLOOKUP_WLOCKPCB, ifp);
+ if (inc->inc_flags & INC_ISIPV6) {
+ inp = in6_pcblookup(&V_tcbinfo, &inc->inc6_faddr,
+ inc->inc_fport, &inc->inc6_laddr, inc->inc_lport,
+ INPLOOKUP_WLOCKPCB, ifp);
+ } else {
+ inp = in_pcblookup(&V_tcbinfo, inc->inc_faddr, inc->inc_fport,
+ inc->inc_laddr, inc->inc_lport, INPLOOKUP_WLOCKPCB, ifp);
+ }
if (inp != NULL) {
INP_WLOCK_ASSERT(inp);
@@ -440,6 +445,68 @@ toe_route_redirect_event(void *arg __unused, struct rtentry *rt0,
return;
}
+#ifdef INET6
+/*
+ * XXX: no checks to verify that sa is really a neighbor because we assume it is
+ * the result of a route lookup and is on-link on the given ifp.
+ */
+static int
+toe_nd6_resolve(struct ifnet *ifp, struct sockaddr *sa, uint8_t *lladdr)
+{
+ struct llentry *lle;
+ struct sockaddr_in6 *sin6 = (void *)sa;
+ int rc, flags = 0;
+
+restart:
+ IF_AFDATA_RLOCK(ifp);
+ lle = lla_lookup(LLTABLE6(ifp), flags, sa);
+ IF_AFDATA_RUNLOCK(ifp);
+ if (lle == NULL) {
+ IF_AFDATA_LOCK(ifp);
+ lle = nd6_lookup(&sin6->sin6_addr, ND6_CREATE | ND6_EXCLUSIVE,
+ ifp);
+ IF_AFDATA_UNLOCK(ifp);
+ if (lle == NULL)
+ return (ENOMEM); /* Couldn't create entry in cache. */
+ lle->ln_state = ND6_LLINFO_INCOMPLETE;
+ nd6_llinfo_settimer_locked(lle,
+ (long)ND_IFINFO(ifp)->retrans * hz / 1000);
+ LLE_WUNLOCK(lle);
+
+ nd6_ns_output(ifp, NULL, &sin6->sin6_addr, NULL, 0);
+
+ return (EWOULDBLOCK);
+ }
+
+ if (lle->ln_state == ND6_LLINFO_STALE) {
+ if ((flags & LLE_EXCLUSIVE) == 0) {
+ LLE_RUNLOCK(lle);
+ flags |= LLE_EXCLUSIVE;
+ goto restart;
+ }
+
+ LLE_WLOCK_ASSERT(lle);
+
+ lle->la_asked = 0;
+ lle->ln_state = ND6_LLINFO_DELAY;
+ nd6_llinfo_settimer_locked(lle, (long)V_nd6_delay * hz);
+ }
+
+ if (lle->la_flags & LLE_VALID) {
+ memcpy(lladdr, &lle->ll_addr, ifp->if_addrlen);
+ rc = 0;
+ } else
+ rc = EWOULDBLOCK;
+
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(lle);
+ else
+ LLE_RUNLOCK(lle);
+
+ return (rc);
+}
+#endif
+
/*
* Returns 0 or EWOULDBLOCK on success (any other value is an error). 0 means
* lladdr and vtag are valid on return, EWOULDBLOCK means the TOE driver's
@@ -449,7 +516,9 @@ int
toe_l2_resolve(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
uint8_t *lladdr, uint16_t *vtag)
{
+#ifdef INET
struct llentry *lle;
+#endif
int rc;
switch (sa->sa_family) {
@@ -460,7 +529,7 @@ toe_l2_resolve(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
#endif
#ifdef INET6
case AF_INET6:
- rc = nd6_storelladdr(ifp, NULL, sa, lladdr, &lle);
+ rc = toe_nd6_resolve(ifp, sa, lladdr);
break;
#endif
default:
diff --git a/sys/netinet/udp.h b/sys/netinet/udp.h
index 2dbcaca..c2d638d 100644
--- a/sys/netinet/udp.h
+++ b/sys/netinet/udp.h
@@ -48,8 +48,10 @@ struct udphdr {
/*
* User-settable options (used with setsockopt).
*/
-#define UDP_ENCAP 0x01
+#define UDP_ENCAP 1
+/* Start of reserved space for third-party user-settable options. */
+#define UDP_VENDOR SO_VENDOR
/*
* UDP Encapsulation of IPsec Packets options.
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index fb7e6f0..8d04c46 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -383,10 +383,12 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
*/
/* Rule 5: Prefer outgoing interface */
- if (ia_best->ia_ifp == ifp && ia->ia_ifp != ifp)
- NEXT(5);
- if (ia_best->ia_ifp != ifp && ia->ia_ifp == ifp)
- REPLACE(5);
+ if (!(ND_IFINFO(ifp)->flags & ND6_IFF_NO_PREFER_IFACE)) {
+ if (ia_best->ia_ifp == ifp && ia->ia_ifp != ifp)
+ NEXT(5);
+ if (ia_best->ia_ifp != ifp && ia->ia_ifp == ifp)
+ REPLACE(5);
+ }
/*
* Rule 6: Prefer matching label
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 5107f1d..fd420d8 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -509,6 +509,7 @@ nd6_llinfo_timer(void *arg)
ln->la_hold = m0;
clear_llinfo_pqueue(ln);
}
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_TIMEDOUT);
(void)nd6_free(ln, 0);
ln = NULL;
if (m != NULL)
@@ -526,6 +527,7 @@ nd6_llinfo_timer(void *arg)
case ND6_LLINFO_STALE:
/* Garbage Collection(RFC 2461 5.3) */
if (!ND6_LLINFO_PERMANENT(ln)) {
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED);
(void)nd6_free(ln, 1);
ln = NULL;
}
@@ -553,6 +555,7 @@ nd6_llinfo_timer(void *arg)
nd6_ns_output(ifp, dst, dst, ln, 0);
LLE_WLOCK(ln);
} else {
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED);
(void)nd6_free(ln, 0);
ln = NULL;
}
@@ -1601,6 +1604,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
*/
bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
ln->la_flags |= LLE_VALID;
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
}
if (!is_newentry) {
@@ -2166,7 +2170,7 @@ nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
*lle = NULL;
IF_AFDATA_UNLOCK_ASSERT(ifp);
- if (m->m_flags & M_MCAST) {
+ if (m != NULL && m->m_flags & M_MCAST) {
int i;
switch (ifp->if_type) {
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 1655a6c..94202e1 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -86,6 +86,7 @@ struct nd_ifinfo {
#define ND6_IFF_DONT_SET_IFROUTE 0x10
#define ND6_IFF_AUTO_LINKLOCAL 0x20
#define ND6_IFF_NO_RADR 0x40
+#define ND6_IFF_NO_PREFER_IFACE 0x80 /* XXX: not related to ND. */
#define ND6_CREATE LLE_CREATE
#define ND6_EXCLUSIVE LLE_EXCLUSIVE
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index 31d0ccb..7fe75bf 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -762,6 +762,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
*/
bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
ln->la_flags |= LLE_VALID;
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
if (is_solicited) {
ln->ln_state = ND6_LLINFO_REACHABLE;
ln->ln_byhint = 0;
@@ -837,6 +838,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
if (lladdr != NULL) {
bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
ln->la_flags |= LLE_VALID;
+ EVENTHANDLER_INVOKE(lle_event, ln,
+ LLENTRY_RESOLVED);
}
/*
diff --git a/sys/netinet6/scope6.c b/sys/netinet6/scope6.c
index 74d034e..b6479a1 100644
--- a/sys/netinet6/scope6.c
+++ b/sys/netinet6/scope6.c
@@ -336,7 +336,6 @@ scope6_addr2default(struct in6_addr *addr)
int
sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok)
{
- struct ifnet *ifp;
u_int32_t zoneid;
if ((zoneid = sin6->sin6_scope_id) == 0 && defaultok)
@@ -351,15 +350,11 @@ sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok)
* zone IDs assuming a one-to-one mapping between interfaces
* and links.
*/
- if (V_if_index < zoneid)
- return (ENXIO);
- ifp = ifnet_byindex(zoneid);
- if (ifp == NULL) /* XXX: this can happen for some OS */
+ if (V_if_index < zoneid || ifnet_byindex(zoneid) == NULL)
return (ENXIO);
/* XXX assignment to 16bit from 32bit variable */
sin6->sin6_addr.s6_addr16[1] = htons(zoneid & 0xffff);
-
sin6->sin6_scope_id = 0;
}
@@ -425,59 +420,30 @@ in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id)
* interface.
*/
if (IN6_IS_ADDR_LOOPBACK(in6)) {
- if (!(ifp->if_flags & IFF_LOOPBACK)) {
+ if (!(ifp->if_flags & IFF_LOOPBACK))
return (EINVAL);
- } else {
- if (ret_id != NULL)
- *ret_id = 0; /* there's no ambiguity */
- return (0);
+ } else {
+ scope = in6_addrscope(in6);
+ if (scope == IPV6_ADDR_SCOPE_INTFACELOCAL ||
+ scope == IPV6_ADDR_SCOPE_LINKLOCAL) {
+ /*
+ * Currently we use interface indeces as the
+ * zone IDs for interface-local and link-local
+ * scopes.
+ */
+ zoneid = ifp->if_index;
+ in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */
+ } else if (scope != IPV6_ADDR_SCOPE_GLOBAL) {
+ IF_AFDATA_RLOCK(ifp);
+ sid = SID(ifp);
+ zoneid = sid->s6id_list[scope];
+ IF_AFDATA_RUNLOCK(ifp);
}
}
- if (ret_id == NULL && !IN6_IS_SCOPE_EMBED(in6))
- return (0);
-
- IF_AFDATA_RLOCK(ifp);
-
- sid = SID(ifp);
-
-#ifdef DIAGNOSTIC
- if (sid == NULL) { /* should not happen */
- panic("in6_setscope: scope array is NULL");
- /* NOTREACHED */
- }
-#endif
-
- scope = in6_addrscope(in6);
- switch (scope) {
- case IPV6_ADDR_SCOPE_INTFACELOCAL: /* should be interface index */
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL];
- break;
-
- case IPV6_ADDR_SCOPE_LINKLOCAL:
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL];
- break;
-
- case IPV6_ADDR_SCOPE_SITELOCAL:
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL];
- break;
-
- case IPV6_ADDR_SCOPE_ORGLOCAL:
- zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL];
- break;
-
- default:
- zoneid = 0; /* XXX: treat as global. */
- break;
- }
- IF_AFDATA_RUNLOCK(ifp);
-
if (ret_id != NULL)
*ret_id = zoneid;
- if (IN6_IS_SCOPE_EMBED(in6))
- in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */
-
return (0);
}
diff --git a/sys/nfs/nfs_common.c b/sys/nfs/nfs_common.c
index 6f03948..83e7125 100644
--- a/sys/nfs/nfs_common.c
+++ b/sys/nfs/nfs_common.c
@@ -90,15 +90,6 @@ static int nfs_realign_count;
SYSCTL_INT(_vfs_nfs_common, OID_AUTO, realign_count, CTLFLAG_RD,
&nfs_realign_count, 0, "Number of mbuf realignments done");
-u_quad_t
-nfs_curusec(void)
-{
- struct timeval tv;
-
- getmicrotime(&tv);
- return ((u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec);
-}
-
/*
* copies mbuf chain to the uio scatter/gather list
*/
diff --git a/sys/nfs/nfs_common.h b/sys/nfs/nfs_common.h
index 1c0b315..c3420b3 100644
--- a/sys/nfs/nfs_common.h
+++ b/sys/nfs/nfs_common.h
@@ -46,7 +46,6 @@ extern nfstype nfsv3_type[];
#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))])
int nfs_adv(struct mbuf **, caddr_t *, int, int);
-u_quad_t nfs_curusec(void);
void *nfsm_disct(struct mbuf **, caddr_t *, int, int, int);
int nfs_realign(struct mbuf **, int);
diff --git a/sys/nfsclient/nfs_krpc.c b/sys/nfsclient/nfs_krpc.c
index 0e4a83e..dd441ae 100644
--- a/sys/nfsclient/nfs_krpc.c
+++ b/sys/nfsclient/nfs_krpc.c
@@ -394,18 +394,17 @@ nfs_feedback(int type, int proc, void *arg)
{
struct nfs_feedback_arg *nf = (struct nfs_feedback_arg *) arg;
struct nfsmount *nmp = nf->nf_mount;
- struct timeval now;
-
- getmicrouptime(&now);
+ time_t now;
switch (type) {
case FEEDBACK_REXMIT2:
case FEEDBACK_RECONNECT:
- if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now.tv_sec) {
+ now = time_uptime;
+ if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now) {
nfs_down(nmp, nf->nf_td,
"not responding", 0, NFSSTA_TIMEO);
nf->nf_tprintfmsg = TRUE;
- nf->nf_lastmsg = now.tv_sec;
+ nf->nf_lastmsg = now;
}
break;
@@ -438,7 +437,6 @@ nfs_request(struct vnode *vp, struct mbuf *mreq, int procnum,
time_t waituntil;
caddr_t dpos;
int error = 0, timeo;
- struct timeval now;
AUTH *auth = NULL;
enum nfs_rto_timer_t timer;
struct nfs_feedback_arg nf;
@@ -455,8 +453,7 @@ nfs_request(struct vnode *vp, struct mbuf *mreq, int procnum,
bzero(&nf, sizeof(struct nfs_feedback_arg));
nf.nf_mount = nmp;
nf.nf_td = td;
- getmicrouptime(&now);
- nf.nf_lastmsg = now.tv_sec -
+ nf.nf_lastmsg = time_uptime -
((nmp->nm_tprintf_delay) - (nmp->nm_tprintf_initial_delay));
/*
@@ -549,14 +546,21 @@ tryagain:
*/
if (stat == RPC_SUCCESS)
error = 0;
- else if (stat == RPC_TIMEDOUT)
+ else if (stat == RPC_TIMEDOUT) {
+ nfsstats.rpctimeouts++;
error = ETIMEDOUT;
- else if (stat == RPC_VERSMISMATCH)
+ } else if (stat == RPC_VERSMISMATCH) {
+ nfsstats.rpcinvalid++;
error = EOPNOTSUPP;
- else if (stat == RPC_PROGVERSMISMATCH)
+ } else if (stat == RPC_PROGVERSMISMATCH) {
+ nfsstats.rpcinvalid++;
error = EPROTONOSUPPORT;
- else
+ } else if (stat == RPC_INTR) {
+ error = EINTR;
+ } else {
+ nfsstats.rpcinvalid++;
error = EACCES;
+ }
if (error)
goto nfsmout;
@@ -572,6 +576,7 @@ tryagain:
if (error == ENOMEM) {
m_freem(mrep);
AUTH_DESTROY(auth);
+ nfsstats.rpcinvalid++;
return (error);
}
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c
index fd83794..3723223 100644
--- a/sys/nfsclient/nfs_subs.c
+++ b/sys/nfsclient/nfs_subs.c
@@ -1110,7 +1110,7 @@ nfsm_v3attrbuild_xx(struct vattr *va, int full, struct mbuf **mb,
*tl = nfs_false;
}
if (va->va_atime.tv_sec != VNOVAL) {
- if (va->va_atime.tv_sec != time_second) {
+ if ((va->va_vaflags & VA_UTIMES_NULL) == 0) {
tl = nfsm_build_xx(3 * NFSX_UNSIGNED, mb, bpos);
*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
txdr_nfsv3time(&va->va_atime, tl);
@@ -1123,7 +1123,7 @@ nfsm_v3attrbuild_xx(struct vattr *va, int full, struct mbuf **mb,
*tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
}
if (va->va_mtime.tv_sec != VNOVAL) {
- if (va->va_mtime.tv_sec != time_second) {
+ if ((va->va_vaflags & VA_UTIMES_NULL) == 0) {
tl = nfsm_build_xx(3 * NFSX_UNSIGNED, mb, bpos);
*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
txdr_nfsv3time(&va->va_mtime, tl);
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index ca9edad..5026daf 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -3458,7 +3458,7 @@ nfsfifo_read(struct vop_read_args *ap)
*/
mtx_lock(&np->n_mtx);
np->n_flag |= NACC;
- getnanotime(&np->n_atim);
+ vfs_timestamp(&np->n_atim);
mtx_unlock(&np->n_mtx);
error = fifo_specops.vop_read(ap);
return error;
@@ -3477,7 +3477,7 @@ nfsfifo_write(struct vop_write_args *ap)
*/
mtx_lock(&np->n_mtx);
np->n_flag |= NUPD;
- getnanotime(&np->n_mtim);
+ vfs_timestamp(&np->n_mtim);
mtx_unlock(&np->n_mtx);
return(fifo_specops.vop_write(ap));
}
@@ -3497,7 +3497,7 @@ nfsfifo_close(struct vop_close_args *ap)
mtx_lock(&np->n_mtx);
if (np->n_flag & (NACC | NUPD)) {
- getnanotime(&ts);
+ vfs_timestamp(&ts);
if (np->n_flag & NACC)
np->n_atim = ts;
if (np->n_flag & NUPD)
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index eedac6c..04371da 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.c
@@ -1393,7 +1393,7 @@ nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos)
toclient = 1;
break;
case NFSV3SATTRTIME_TOSERVER:
- getnanotime(&(a)->va_atime);
+ vfs_timestamp(&a->va_atime);
a->va_vaflags |= VA_UTIMES_NULL;
break;
}
@@ -1409,7 +1409,7 @@ nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos)
a->va_vaflags &= ~VA_UTIMES_NULL;
break;
case NFSV3SATTRTIME_TOSERVER:
- getnanotime(&(a)->va_mtime);
+ vfs_timestamp(&a->va_mtime);
if (toclient == 0)
a->va_vaflags |= VA_UTIMES_NULL;
break;
diff --git a/sys/pc98/cbus/pckbd.c b/sys/pc98/cbus/pckbd.c
index 5efb983..e424294 100644
--- a/sys/pc98/cbus/pckbd.c
+++ b/sys/pc98/cbus/pckbd.c
@@ -77,9 +77,9 @@ DRIVER_MODULE(pckbd, isa, pckbd_driver, pckbd_devclass, 0, 0);
static bus_addr_t pckbd_iat[] = {0, 2};
-static int pckbd_probe_unit(int unit, int port, int irq,
+static int pckbd_probe_unit(device_t dev, int port, int irq,
int flags);
-static int pckbd_attach_unit(int unit, keyboard_t **kbd,
+static int pckbd_attach_unit(device_t dev, keyboard_t **kbd,
int port, int irq, int flags);
static timeout_t pckbd_timeout;
@@ -103,7 +103,7 @@ pckbdprobe(device_t dev)
return ENXIO;
isa_load_resourcev(res, pckbd_iat, 2);
- error = pckbd_probe_unit(device_get_unit(dev),
+ error = pckbd_probe_unit(dev,
isa_get_port(dev),
(1 << isa_get_irq(dev)),
device_get_flags(dev));
@@ -128,7 +128,7 @@ pckbdattach(device_t dev)
return ENXIO;
isa_load_resourcev(res, pckbd_iat, 2);
- error = pckbd_attach_unit(device_get_unit(dev), &kbd,
+ error = pckbd_attach_unit(dev, &kbd,
isa_get_port(dev),
(1 << isa_get_irq(dev)),
device_get_flags(dev));
@@ -164,7 +164,7 @@ pckbd_isa_intr(void *arg)
}
static int
-pckbd_probe_unit(int unit, int port, int irq, int flags)
+pckbd_probe_unit(device_t dev, int port, int irq, int flags)
{
keyboard_switch_t *sw;
int args[2];
@@ -176,24 +176,26 @@ pckbd_probe_unit(int unit, int port, int irq, int flags)
args[0] = port;
args[1] = irq;
- error = (*sw->probe)(unit, args, flags);
+ error = (*sw->probe)(device_get_unit(dev), args, flags);
if (error)
return error;
return 0;
}
static int
-pckbd_attach_unit(int unit, keyboard_t **kbd, int port, int irq, int flags)
+pckbd_attach_unit(device_t dev, keyboard_t **kbd, int port, int irq, int flags)
{
keyboard_switch_t *sw;
int args[2];
int error;
+ int unit;
sw = kbd_get_switch(DRIVER_NAME);
if (sw == NULL)
return ENXIO;
/* reset, initialize and enable the device */
+ unit = device_get_unit(dev);
args[0] = port;
args[1] = irq;
*kbd = NULL;
diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC
index 2b048a9..eda1d14 100644
--- a/sys/pc98/conf/GENERIC
+++ b/sys/pc98/conf/GENERIC
@@ -151,7 +151,6 @@ device mse
device ppc
device ppbus # Parallel port bus (required)
device lpt # Printer
-device plip # TCP/IP over parallel
device ppi # Parallel port interface device
#device vpo # Requires scbus and da
# OLD Parallel port
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c
index 98e3352..4f91d1f 100644
--- a/sys/pci/if_rl.c
+++ b/sys/pci/if_rl.c
@@ -148,6 +148,8 @@ static const struct rl_type rl_devs[] = {
"Delta Electronics 8139 10/100BaseTX" },
{ ADDTRON_VENDORID, ADDTRON_DEVICEID_8139, RL_8139,
"Addtron Technology 8139 10/100BaseTX" },
+ { DLINK_VENDORID, DLINK_DEVICEID_520TX_REVC1, RL_8139,
+ "D-Link DFE-520TX (rev. C1) 10/100BaseTX" },
{ DLINK_VENDORID, DLINK_DEVICEID_530TXPLUS, RL_8139,
"D-Link DFE-530TX+ 10/100BaseTX" },
{ DLINK_VENDORID, DLINK_DEVICEID_690TXD, RL_8139,
diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h
index 7822ce3..be89c4f5 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/pci/if_rlreg.h
@@ -1048,6 +1048,11 @@ struct rl_softc {
#define DLINK_DEVICEID_530TXPLUS 0x1300
/*
+ * D-Link DFE-520TX rev. C1 device ID
+ */
+#define DLINK_DEVICEID_520TX_REVC1 0x4200
+
+/*
* D-Link DFE-5280T device ID
*/
#define DLINK_DEVICEID_528T 0x4300
diff --git a/sys/pci/ncr.c b/sys/pci/ncr.c
index 793ae80..ead7d43 100644
--- a/sys/pci/ncr.c
+++ b/sys/pci/ncr.c
@@ -1386,7 +1386,7 @@ static char *ncr_name (ncb_p np)
* Kernel variables referenced in the scripts.
* THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY.
*/
-static void *script_kvars[] =
+static volatile void *script_kvars[] =
{ &time_second, &ticks, &ncr_cache };
static struct script script0 = {
diff --git a/sys/security/audit/audit.c b/sys/security/audit/audit.c
index 2063c9d..cb3406d 100644
--- a/sys/security/audit/audit.c
+++ b/sys/security/audit/audit.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/filedesc.h>
#include <sys/fcntl.h>
#include <sys/ipc.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/malloc.h>
@@ -211,6 +212,7 @@ audit_record_ctor(void *mem, int size, void *arg, int flags)
struct kaudit_record *ar;
struct thread *td;
struct ucred *cred;
+ struct prison *pr;
KASSERT(sizeof(*ar) == size, ("audit_record_ctor: wrong size"));
@@ -233,6 +235,17 @@ audit_record_ctor(void *mem, int size, void *arg, int flags)
ar->k_ar.ar_subj_pid = td->td_proc->p_pid;
ar->k_ar.ar_subj_amask = cred->cr_audit.ai_mask;
ar->k_ar.ar_subj_term_addr = cred->cr_audit.ai_termid;
+ /*
+ * If this process is jailed, make sure we capture the name of the
+ * jail so we can use it to generate a zonename token when we covert
+ * this record to BSM.
+ */
+ if (jailed(cred)) {
+ pr = cred->cr_prison;
+ (void) strlcpy(ar->k_ar.ar_jailname, pr->pr_name,
+ sizeof(ar->k_ar.ar_jailname));
+ } else
+ ar->k_ar.ar_jailname[0] = '\0';
return (0);
}
diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c
index 6e49b51..b02d677 100644
--- a/sys/security/audit/audit_bsm.c
+++ b/sys/security/audit/audit_bsm.c
@@ -462,7 +462,7 @@ audit_sys_auditon(struct audit_record *ar, struct au_record *rec)
int
kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
{
- struct au_token *tok, *subj_tok;
+ struct au_token *tok, *subj_tok, *jail_tok;
struct au_record *rec;
au_tid_t tid;
struct audit_record *ar;
@@ -475,8 +475,13 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
rec = kau_open();
/*
- * Create the subject token.
+ * Create the subject token. If this credential was jailed be sure to
+ * generate a zonename token.
*/
+ if (ar->ar_jailname[0] != '\0')
+ jail_tok = au_to_zonename(ar->ar_jailname);
+ else
+ jail_tok = NULL;
switch (ar->ar_subj_term_addr.at_type) {
case AU_IPv4:
tid.port = ar->ar_subj_term_addr.at_port;
@@ -1623,11 +1628,15 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
/*
* Write the subject token so it is properly freed here.
*/
+ if (jail_tok != NULL)
+ kau_write(rec, jail_tok);
kau_write(rec, subj_tok);
kau_free(rec);
return (BSM_NOAUDIT);
}
+ if (jail_tok != NULL)
+ kau_write(rec, jail_tok);
kau_write(rec, subj_tok);
tok = au_to_return32(au_errno_to_bsm(ar->ar_errno), ar->ar_retval);
kau_write(rec, tok); /* Every record gets a return token */
diff --git a/sys/security/audit/audit_private.h b/sys/security/audit/audit_private.h
index ad931c0..a5716d0 100644
--- a/sys/security/audit/audit_private.h
+++ b/sys/security/audit/audit_private.h
@@ -230,6 +230,7 @@ struct audit_record {
int ar_arg_exitretval;
struct sockaddr_storage ar_arg_sockaddr;
cap_rights_t ar_arg_rights;
+ char ar_jailname[MAXHOSTNAMELEN];
};
/*
diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC
index f9d3b93..79124ab 100644
--- a/sys/sparc64/conf/GENERIC
+++ b/sys/sparc64/conf/GENERIC
@@ -161,7 +161,6 @@ device uart # Multi-uart driver
#device ppc
#device ppbus # Parallel port bus (required)
#device lpt # Printer
-#device plip # TCP/IP over parallel
#device ppi # Parallel port interface device
#device vpo # Requires scbus and da
diff --git a/sys/sparc64/include/smp.h b/sys/sparc64/include/smp.h
index db17309..2e1110b 100644
--- a/sys/sparc64/include/smp.h
+++ b/sys/sparc64/include/smp.h
@@ -42,6 +42,7 @@
#include <sys/cpuset.h>
#include <sys/proc.h>
#include <sys/sched.h>
+#include <sys/smp.h>
#include <machine/intr_machdep.h>
#include <machine/pcb.h>
@@ -202,6 +203,7 @@ ipi_rd(u_int cpu, void *func, u_long *val)
return (NULL);
sched_pin();
ira = &ipi_rd_args;
+ mtx_lock_spin(&smp_ipi_mtx);
CPU_SETOF(cpu, &ira->ira_mask);
ira->ira_val = val;
cpu_ipi_single(cpu, 0, (u_long)func, (u_long)ira);
@@ -298,18 +300,6 @@ ipi_wait(void *cookie)
}
}
-static __inline void
-ipi_wait_unlocked(void *cookie)
-{
- volatile cpuset_t *mask;
-
- if ((mask = cookie) != NULL) {
- while (!CPU_EMPTY(mask))
- ;
- sched_unpin();
- }
-}
-
#endif /* _MACHINE_PMAP_H_ && _SYS_MUTEX_H_ */
#endif /* !LOCORE */
@@ -368,12 +358,6 @@ ipi_wait(void *cookie __unused)
}
static __inline void
-ipi_wait_unlocked(void *cookie __unused)
-{
-
-}
-
-static __inline void
tl_ipi_cheetah_dcache_page_inval(void)
{
diff --git a/sys/sparc64/sparc64/tick.c b/sys/sparc64/sparc64/tick.c
index 69062ec..cfd5776 100644
--- a/sys/sparc64/sparc64/tick.c
+++ b/sys/sparc64/sparc64/tick.c
@@ -334,7 +334,7 @@ stick_get_timecount_mp(struct timecounter *tc)
if (curcpu == 0)
stick = rdstick();
else
- ipi_wait_unlocked(ipi_rd(0, tl_ipi_stick_rd, &stick));
+ ipi_wait(ipi_rd(0, tl_ipi_stick_rd, &stick));
sched_unpin();
return (stick);
}
@@ -348,7 +348,7 @@ tick_get_timecount_mp(struct timecounter *tc)
if (curcpu == 0)
tick = rd(tick);
else
- ipi_wait_unlocked(ipi_rd(0, tl_ipi_tick_rd, &tick));
+ ipi_wait(ipi_rd(0, tl_ipi_tick_rd, &tick));
sched_unpin();
return (tick);
}
diff --git a/sys/sys/bufobj.h b/sys/sys/bufobj.h
index 3934553..79bef84 100644
--- a/sys/sys/bufobj.h
+++ b/sys/sys/bufobj.h
@@ -89,12 +89,7 @@ struct buf_ops {
struct bufobj {
struct mtx bo_mtx; /* Mutex which protects "i" things */
- struct bufv bo_clean; /* i Clean buffers */
- struct bufv bo_dirty; /* i Dirty buffers */
- long bo_numoutput; /* i Writes in progress */
- u_int bo_flag; /* i Flags */
struct buf_ops *bo_ops; /* - Buffer operations */
- int bo_bsize; /* - Block size for i/o */
struct vm_object *bo_object; /* v Place to store VM object */
LIST_ENTRY(bufobj) bo_synclist; /* S dirty vnode list */
void *bo_private; /* private pointer */
@@ -103,6 +98,11 @@ struct bufobj {
* XXX: only to keep the syncer working
* XXX: for now.
*/
+ struct bufv bo_clean; /* i Clean buffers */
+ struct bufv bo_dirty; /* i Dirty buffers */
+ long bo_numoutput; /* i Writes in progress */
+ u_int bo_flag; /* i Flags */
+ int bo_bsize; /* - Block size for i/o */
};
/*
diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h
index 441bcb3..c54677a 100644
--- a/sys/sys/kernel.h
+++ b/sys/sys/kernel.h
@@ -63,7 +63,7 @@ extern int psratio; /* ratio: prof / stat */
extern int stathz; /* statistics clock's frequency */
extern int profhz; /* profiling clock's frequency */
extern int profprocs; /* number of process's profiling */
-extern int ticks;
+extern volatile int ticks;
#endif /* _KERNEL */
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 22742c9..af7f92b 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -52,11 +52,14 @@
* stored. Additionally, it is possible to allocate a separate buffer
* externally and attach it to the mbuf in a way similar to that of mbuf
* clusters.
+ *
+ * MLEN is data length in a normal mbuf.
+ * MHLEN is data length in an mbuf with pktheader.
+ * MINCLSIZE is a smallest amount of data that should be put into cluster.
*/
-#define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */
-#define MHLEN (MLEN - sizeof(struct pkthdr)) /* data len w/pkthdr */
-#define MINCLSIZE (MHLEN + 1) /* smallest amount to put in cluster */
-#define M_MAXCOMPRESS (MHLEN / 2) /* max amount to copy for compression */
+#define MLEN ((int)(MSIZE - sizeof(struct m_hdr)))
+#define MHLEN ((int)(MLEN - sizeof(struct pkthdr)))
+#define MINCLSIZE (MHLEN + 1)
#ifdef _KERNEL
/*-
@@ -384,7 +387,6 @@ struct mbstat {
*
* The rest of it is defined in kern/kern_mbuf.c
*/
-extern quad_t maxmbufmem;
extern uma_zone_t zone_mbuf;
extern uma_zone_t zone_clust;
extern uma_zone_t zone_pack;
@@ -393,23 +395,8 @@ extern uma_zone_t zone_jumbo9;
extern uma_zone_t zone_jumbo16;
extern uma_zone_t zone_ext_refcnt;
-static __inline struct mbuf *m_getcl(int how, short type, int flags);
-static __inline struct mbuf *m_get(int how, short type);
-static __inline struct mbuf *m_get2(int how, short type, int flags,
- u_int size);
-static __inline struct mbuf *m_gethdr(int how, short type);
-static __inline struct mbuf *m_getjcl(int how, short type, int flags,
- int size);
-static __inline struct mbuf *m_getclr(int how, short type); /* XXX */
-static __inline int m_init(struct mbuf *m, uma_zone_t zone,
- int size, int how, short type, int flags);
-static __inline struct mbuf *m_free(struct mbuf *m);
-static __inline void m_clget(struct mbuf *m, int how);
-static __inline void *m_cljget(struct mbuf *m, int how, int size);
-static __inline void m_chtype(struct mbuf *m, short new_type);
-void mb_free_ext(struct mbuf *);
-static __inline struct mbuf *m_last(struct mbuf *m);
-int m_pkthdr_init(struct mbuf *m, int how);
+void mb_free_ext(struct mbuf *);
+int m_pkthdr_init(struct mbuf *, int);
static __inline int
m_gettype(int size)
@@ -502,7 +489,7 @@ m_get(int how, short type)
args.flags = 0;
args.type = type;
- return ((struct mbuf *)(uma_zalloc_arg(zone_mbuf, &args, how)));
+ return (uma_zalloc_arg(zone_mbuf, &args, how));
}
/*
@@ -529,7 +516,7 @@ m_gethdr(int how, short type)
args.flags = M_PKTHDR;
args.type = type;
- return ((struct mbuf *)(uma_zalloc_arg(zone_mbuf, &args, how)));
+ return (uma_zalloc_arg(zone_mbuf, &args, how));
}
static __inline struct mbuf *
@@ -539,85 +526,7 @@ m_getcl(int how, short type, int flags)
args.flags = flags;
args.type = type;
- return ((struct mbuf *)(uma_zalloc_arg(zone_pack, &args, how)));
-}
-
-/*
- * m_get2() allocates minimum mbuf that would fit "size" argument.
- *
- * XXX: This is rather large, should be real function maybe.
- */
-static __inline struct mbuf *
-m_get2(int how, short type, int flags, u_int size)
-{
- struct mb_args args;
- struct mbuf *m, *n;
- uma_zone_t zone;
-
- args.flags = flags;
- args.type = type;
-
- if (size <= MHLEN || (size <= MLEN && (flags & M_PKTHDR) == 0))
- return ((struct mbuf *)(uma_zalloc_arg(zone_mbuf, &args, how)));
- if (size <= MCLBYTES)
- return ((struct mbuf *)(uma_zalloc_arg(zone_pack, &args, how)));
-
- if (size > MJUM16BYTES)
- return (NULL);
-
- m = uma_zalloc_arg(zone_mbuf, &args, how);
- if (m == NULL)
- return (NULL);
-
-#if MJUMPAGESIZE != MCLBYTES
- if (size <= MJUMPAGESIZE)
- zone = zone_jumbop;
- else
-#endif
- if (size <= MJUM9BYTES)
- zone = zone_jumbo9;
- else
- zone = zone_jumbo16;
-
- n = uma_zalloc_arg(zone, m, how);
- if (n == NULL) {
- uma_zfree(zone_mbuf, m);
- return (NULL);
- }
-
- return (m);
-}
-
-/*
- * m_getjcl() returns an mbuf with a cluster of the specified size attached.
- * For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
- *
- * XXX: This is rather large, should be real function maybe.
- */
-static __inline struct mbuf *
-m_getjcl(int how, short type, int flags, int size)
-{
- struct mb_args args;
- struct mbuf *m, *n;
- uma_zone_t zone;
-
- if (size == MCLBYTES)
- return m_getcl(how, type, flags);
-
- args.flags = flags;
- args.type = type;
-
- m = uma_zalloc_arg(zone_mbuf, &args, how);
- if (m == NULL)
- return (NULL);
-
- zone = m_getzone(size);
- n = uma_zalloc_arg(zone, m, how);
- if (n == NULL) {
- uma_zfree(zone_mbuf, m);
- return (NULL);
- }
- return (m);
+ return (uma_zalloc_arg(zone_pack, &args, how));
}
static __inline void
@@ -881,7 +790,7 @@ struct mbuf *m_copymdata(struct mbuf *, struct mbuf *,
int, int, int, int);
struct mbuf *m_copypacket(struct mbuf *, int);
void m_copy_pkthdr(struct mbuf *, struct mbuf *);
-struct mbuf *m_copyup(struct mbuf *n, int len, int dstoff);
+struct mbuf *m_copyup(struct mbuf *, int, int);
struct mbuf *m_defrag(struct mbuf *, int);
void m_demote(struct mbuf *, int);
struct mbuf *m_devget(char *, int, int, struct ifnet *,
@@ -891,6 +800,8 @@ int m_dup_pkthdr(struct mbuf *, struct mbuf *, int);
u_int m_fixhdr(struct mbuf *);
struct mbuf *m_fragment(struct mbuf *, int, int);
void m_freem(struct mbuf *);
+struct mbuf *m_get2(int, short, int, int);
+struct mbuf *m_getjcl(int, short, int, int);
struct mbuf *m_getm2(struct mbuf *, int, int, short, int);
struct mbuf *m_getptr(struct mbuf *, int, int *);
u_int m_length(struct mbuf *, struct mbuf **);
@@ -900,10 +811,10 @@ struct mbuf *m_prepend(struct mbuf *, int, int);
void m_print(const struct mbuf *, int);
struct mbuf *m_pulldown(struct mbuf *, int, int, int *);
struct mbuf *m_pullup(struct mbuf *, int);
-int m_sanity(struct mbuf *, int);
+int m_sanity(struct mbuf *, int);
struct mbuf *m_split(struct mbuf *, int, int);
struct mbuf *m_uiotombuf(struct uio *, int, int, int, int);
-struct mbuf *m_unshare(struct mbuf *, int how);
+struct mbuf *m_unshare(struct mbuf *, int);
/*-
* Network packets may have annotations attached by affixing a list of
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 992227c..bbbc569 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -762,8 +762,9 @@ extern struct nfs_public nfs_pub;
/*
* Declarations for these vfs default operations are located in
- * kern/vfs_default.c, they should be used instead of making "dummy"
- * functions or casting entries in the VFS op table to "enopnotsupp()".
+ * kern/vfs_default.c. They will be automatically used to replace
+ * null entries in VFS ops tables when registering a new filesystem
+ * type in the global table.
*/
vfs_root_t vfs_stdroot;
vfs_quotactl_t vfs_stdquotactl;
diff --git a/sys/sys/param.h b/sys/sys/param.h
index d7a74f2..c290466 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -48,9 +48,9 @@
* __FreeBSD_version numbers are documented in the Porter's Handbook.
* If you bump the version for any reason, you should update the documentation
* there.
- * Currently this lives here:
+ * Currently this lives here in the doc/ repository:
*
- * doc/en_US.ISO8859-1/books/porters-handbook/book.sgml
+ * head/en_US.ISO8859-1/books/porters-handbook/book.xml
*
* scheme is: <major><two digit minor>Rxx
* 'R' is in the range 0 to 4 if this is a release branch or
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1000025 /* Master, propagated to newvers */
+#define __FreeBSD_version 1000027 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
@@ -156,8 +156,8 @@
* MCLBYTES must be no larger than PAGE_SIZE.
*/
#ifndef MSIZE
-#define MSIZE 256 /* size of an mbuf */
-#endif /* MSIZE */
+#define MSIZE 256 /* size of an mbuf */
+#endif
#ifndef MCLSHIFT
#define MCLSHIFT 11 /* convert bytes to mbuf clusters */
diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h
index 7db7dff..2d7665a 100644
--- a/sys/sys/pmc.h
+++ b/sys/sys/pmc.h
@@ -89,6 +89,7 @@
__PMC_CPU(INTEL_SANDYBRIDGE, 0x8D, "Intel Sandy Bridge") \
__PMC_CPU(INTEL_IVYBRIDGE, 0x8E, "Intel Ivy Bridge") \
__PMC_CPU(INTEL_SANDYBRIDGE_XEON, 0x8F, "Intel Sandy Bridge Xeon") \
+ __PMC_CPU(INTEL_IVYBRIDGE_XEON, 0x90, "Intel Ivy Bridge Xeon") \
__PMC_CPU(INTEL_XSCALE, 0x100, "Intel XScale") \
__PMC_CPU(MIPS_24K, 0x200, "MIPS 24K") \
__PMC_CPU(MIPS_OCTEON, 0x201, "Cavium Octeon") \
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
index d7c6c79..c29a689 100644
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -143,6 +143,15 @@ typedef __uid_t uid_t;
#endif
/*
+ * Space reserved for new socket options added by third-party vendors.
+ * This range applies to all socket option levels. New socket options
+ * in FreeBSD should always use an option value less than SO_VENDOR.
+ */
+#if __BSD_VISIBLE
+#define SO_VENDOR 0x80000000
+#endif
+
+/*
* Structure used for manipulating linger option.
*/
struct linger {
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 7c3f13e..dd96d70 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -49,6 +49,7 @@ extern int cold; /* nonzero if we are doing a cold boot */
extern int rebooting; /* kern_reboot() has been called. */
extern const char *panicstr; /* panic message */
extern char version[]; /* system version */
+extern char compiler_version[]; /* compiler version */
extern char copyright[]; /* system copyright */
extern int kstack_pages; /* number of kernel stack pages */
diff --git a/sys/sys/time.h b/sys/sys/time.h
index 12d43cf..80878c0 100644
--- a/sys/sys/time.h
+++ b/sys/sys/time.h
@@ -287,8 +287,8 @@ struct clockinfo {
void inittodr(time_t base);
void resettodr(void);
-extern time_t time_second;
-extern time_t time_uptime;
+extern volatile time_t time_second;
+extern volatile time_t time_uptime;
extern struct bintime boottimebin;
extern struct timeval boottime;
diff --git a/sys/sys/un.h b/sys/sys/un.h
index 1f4731e..7837e76 100644
--- a/sys/sys/un.h
+++ b/sys/sys/un.h
@@ -53,9 +53,12 @@ struct sockaddr_un {
#if __BSD_VISIBLE
/* Socket options. */
-#define LOCAL_PEERCRED 0x001 /* retrieve peer credentials */
-#define LOCAL_CREDS 0x002 /* pass credentials to receiver */
-#define LOCAL_CONNWAIT 0x004 /* connects block until accepted */
+#define LOCAL_PEERCRED 1 /* retrieve peer credentials */
+#define LOCAL_CREDS 2 /* pass credentials to receiver */
+#define LOCAL_CONNWAIT 4 /* connects block until accepted */
+
+/* Start of reserved space for third-party socket options. */
+#define LOCAL_VENDOR SO_VENDOR
#ifndef _KERNEL
diff --git a/sys/sys/vdso.h b/sys/sys/vdso.h
index 653a606..f584315 100644
--- a/sys/sys/vdso.h
+++ b/sys/sys/vdso.h
@@ -61,13 +61,9 @@ struct timeval;
struct timezone;
int __vdso_clock_gettime(clockid_t clock_id, struct timespec *ts);
-#pragma weak __vdso_clock_gettime
-
int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz);
-#pragma weak __vdso_gettimeofday
-
u_int __vdso_gettc(const struct vdso_timehands *vdso_th);
-#pragma weak __vdso_gettc
+int __vdso_gettimekeep(struct vdso_timekeep **tk);
#endif
diff --git a/sys/sys/vmmeter.h b/sys/sys/vmmeter.h
index 1a29ec1..59b430d 100644
--- a/sys/sys/vmmeter.h
+++ b/sys/sys/vmmeter.h
@@ -61,6 +61,7 @@ struct vmmeter {
* Virtual memory activity.
*/
u_int v_vm_faults; /* (p) address memory faults */
+ u_int v_io_faults; /* (p) page faults requiring I/O */
u_int v_cow_faults; /* (p) copy-on-writes faults */
u_int v_cow_optim; /* (p) optimized copy-on-writes faults */
u_int v_zfod; /* (p) pages zero filled on demand */
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index f487f37..b54dc04 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -99,7 +99,6 @@ struct vnode {
* Fields which define the identity of the vnode. These fields are
* owned by the filesystem (XXX: and vgone() ?)
*/
- enum vtype v_type; /* u vnode type */
const char *v_tag; /* u type of underlying data */
struct vop_vector *v_op; /* u vnode operations vector */
void *v_data; /* u private data for fs */
@@ -122,10 +121,10 @@ struct vnode {
} v_un;
/*
- * vfs_hash: (mount + inode) -> vnode hash.
+ * vfs_hash: (mount + inode) -> vnode hash. The hash value
+ * itself is grouped with other int fields, to avoid padding.
*/
LIST_ENTRY(vnode) v_hashlist;
- u_int v_hash;
/*
* VFS_namecache stuff
@@ -135,24 +134,11 @@ struct vnode {
struct namecache *v_cache_dd; /* c Cache entry for .. vnode */
/*
- * clustering stuff
- */
- daddr_t v_cstart; /* v start block of cluster */
- daddr_t v_lasta; /* v last allocation */
- daddr_t v_lastw; /* v last write */
- int v_clen; /* v length of cur. cluster */
-
- /*
* Locking
*/
struct lock v_lock; /* u (if fs don't have one) */
struct mtx v_interlock; /* lock for "i" things */
struct lock *v_vnlock; /* u pointer to vnode lock */
- int v_holdcnt; /* i prevents recycling. */
- int v_usecount; /* i ref count of users */
- u_int v_iflag; /* i vnode flags (see below) */
- u_int v_vflag; /* v vnode flags */
- int v_writecount; /* v ref count of writers */
/*
* The machinery of being a vnode
@@ -167,6 +153,22 @@ struct vnode {
struct label *v_label; /* MAC label for vnode */
struct lockf *v_lockf; /* Byte-level advisory lock list */
struct rangelock v_rl; /* Byte-range lock */
+
+ /*
+ * clustering stuff
+ */
+ daddr_t v_cstart; /* v start block of cluster */
+ daddr_t v_lasta; /* v last allocation */
+ daddr_t v_lastw; /* v last write */
+ int v_clen; /* v length of cur. cluster */
+
+ int v_holdcnt; /* i prevents recycling. */
+ int v_usecount; /* i ref count of users */
+ u_int v_iflag; /* i vnode flags (see below) */
+ u_int v_vflag; /* v vnode flags */
+ int v_writecount; /* v ref count of writers */
+ u_int v_hash;
+ enum vtype v_type; /* u vnode type */
};
#endif /* defined(_KERNEL) || defined(_KVM_VNODE) */
@@ -703,8 +705,7 @@ int vn_io_fault_uiomove(char *data, int xfersize, struct uio *uio);
int vfs_cache_lookup(struct vop_lookup_args *ap);
void vfs_timestamp(struct timespec *);
-void vfs_write_resume(struct mount *mp);
-void vfs_write_resume_flags(struct mount *mp, int flags);
+void vfs_write_resume(struct mount *mp, int flags);
int vfs_write_suspend(struct mount *mp);
int vop_stdbmap(struct vop_bmap_args *);
int vop_stdfsync(struct vop_fsync_args *);
@@ -813,6 +814,7 @@ int fifo_printinfo(struct vnode *);
typedef int vfs_hash_cmp_t(struct vnode *vp, void *arg);
int vfs_hash_get(const struct mount *mp, u_int hash, int flags, struct thread *td, struct vnode **vpp, vfs_hash_cmp_t *fn, void *arg);
+u_int vfs_hash_index(struct vnode *vp);
int vfs_hash_insert(struct vnode *vp, u_int hash, int flags, struct thread *td, struct vnode **vpp, vfs_hash_cmp_t *fn, void *arg);
void vfs_hash_rehash(struct vnode *vp, u_int hash);
void vfs_hash_remove(struct vnode *vp);
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index f8584d5..4571a1c 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -546,9 +546,9 @@ done:
*/
ip->i_size = length;
DIP_SET(ip, i_size, length);
- DIP_SET(ip, i_blocks, DIP(ip, i_blocks) - blocksreleased);
-
- if (DIP(ip, i_blocks) < 0) /* sanity */
+ if (DIP(ip, i_blocks) >= blocksreleased)
+ DIP_SET(ip, i_blocks, DIP(ip, i_blocks) - blocksreleased);
+ else /* sanity */
DIP_SET(ip, i_blocks, 0);
ip->i_flag |= IN_CHANGE;
#ifdef QUOTA
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 5f67ae5..0c653c2 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -687,7 +687,7 @@ out1:
/*
* Resume operation on filesystem.
*/
- vfs_write_resume_flags(vp->v_mount, VR_START_WRITE | VR_NO_SUSPCLR);
+ vfs_write_resume(vp->v_mount, VR_START_WRITE | VR_NO_SUSPCLR);
if (collectsnapstats && starttime.tv_sec > 0) {
nanotime(&endtime);
timespecsub(&endtime, &starttime);
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 4ee16ab..16fe134 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -2802,7 +2802,7 @@ journal_unsuspend(struct ufsmount *ump)
jblocks->jb_suspended = 0;
FREE_LOCK(&lk);
mp->mnt_susp_owner = curthread;
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
ACQUIRE_LOCK(&lk);
return (1);
}
diff --git a/sys/ufs/ffs/ffs_suspend.c b/sys/ufs/ffs/ffs_suspend.c
index 9d8e2c1..3198c1a 100644
--- a/sys/ufs/ffs/ffs_suspend.c
+++ b/sys/ufs/ffs/ffs_suspend.c
@@ -252,7 +252,7 @@ ffs_susp_dtor(void *data)
*/
mp->mnt_susp_owner = curthread;
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
vfs_unbusy(mp);
ump->um_writesuspended = 0;
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 83ae202..0204613 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -292,7 +292,7 @@ ffs_mount(struct mount *mp)
error = ffs_flushfiles(mp, flags, td);
}
if (error) {
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
return (error);
}
if (fs->fs_pendingblocks != 0 ||
@@ -309,7 +309,7 @@ ffs_mount(struct mount *mp)
if ((error = ffs_sbupdate(ump, MNT_WAIT, 0)) != 0) {
fs->fs_ronly = 0;
fs->fs_clean = 0;
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
return (error);
}
if (MOUNTEDSOFTDEP(mp))
@@ -330,7 +330,7 @@ ffs_mount(struct mount *mp)
* Allow the writers to note that filesystem
* is ro now.
*/
- vfs_write_resume(mp);
+ vfs_write_resume(mp, 0);
}
if ((mp->mnt_flag & MNT_RELOAD) &&
(error = ffs_reload(mp, td, 0)) != 0)
@@ -1294,10 +1294,8 @@ ffs_unmount(mp, mntflags)
goto fail;
}
}
- if (susp) {
- vfs_write_resume(mp);
- vn_start_write(NULL, &mp, V_WAIT);
- }
+ if (susp)
+ vfs_write_resume(mp, VR_START_WRITE);
DROP_GIANT();
g_topology_lock();
if (ump->um_fsckpid > 0) {
@@ -1329,10 +1327,8 @@ ffs_unmount(mp, mntflags)
return (error);
fail:
- if (susp) {
- vfs_write_resume(mp);
- vn_start_write(NULL, &mp, V_WAIT);
- }
+ if (susp)
+ vfs_write_resume(mp, VR_START_WRITE);
#ifdef UFS_EXTATTR
if (e_restart) {
ufs_extattr_uepm_init(&ump->um_extattr);
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index 2a18b0d..30aaac0 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -160,6 +160,7 @@ cdev_pager_allocate(void *handle, enum obj_type tp, struct cdev_pager_ops *ops,
object1->pg_color = color;
object1->handle = handle;
object1->un_pager.devp.ops = ops;
+ object1->un_pager.devp.dev = handle;
TAILQ_INIT(&object1->un_pager.devp.devp_pglist);
mtx_lock(&dev_pager_mtx);
object = vm_pager_object_lookup(&dev_pager_object_list, handle);
@@ -237,7 +238,7 @@ dev_pager_dealloc(object)
vm_page_t m;
VM_OBJECT_UNLOCK(object);
- object->un_pager.devp.ops->cdev_pg_dtor(object->handle);
+ object->un_pager.devp.ops->cdev_pg_dtor(object->un_pager.devp.dev);
mtx_lock(&dev_pager_mtx);
TAILQ_REMOVE(&dev_pager_object_list, object, pager_object_list);
diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c
index 36a149e..2d5b555 100644
--- a/sys/vm/uma_core.c
+++ b/sys/vm/uma_core.c
@@ -1702,7 +1702,7 @@ uma_startup(void *bootmem, int boot_pages)
#ifdef UMA_DEBUG
printf("Calculated uma_max_ipers (for OFFPAGE) is %d\n", uma_max_ipers);
- printf("Calculated uma_max_ipers_slab (for OFFPAGE) is %d\n",
+ printf("Calculated uma_max_ipers_ref (for OFFPAGE) is %d\n",
uma_max_ipers_ref);
#endif
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 2274464..9883dcf 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -937,9 +937,10 @@ vnode_locked:
* Unlock everything, and return
*/
unlock_and_deallocate(&fs);
- if (hardfault)
+ if (hardfault) {
+ PCPU_INC(cnt.v_io_faults);
curthread->td_ru.ru_majflt++;
- else
+ } else
curthread->td_ru.ru_minflt++;
return (KERN_SUCCESS);
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index f87e5b9..26de826 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -726,12 +726,6 @@ vmspace_resident_count(struct vmspace *vmspace)
return pmap_resident_count(vmspace_pmap(vmspace));
}
-long
-vmspace_wired_count(struct vmspace *vmspace)
-{
- return pmap_wired_count(vmspace_pmap(vmspace));
-}
-
/*
* vm_map_create:
*
@@ -3281,8 +3275,7 @@ vm_map_stack(vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize,
}
if (!old_mlock && map->flags & MAP_WIREFUTURE) {
- if (ptoa(vmspace_wired_count(curproc->p_vmspace)) +
- init_ssize > lmemlim) {
+ if (ptoa(pmap_wired_count(map->pmap)) + init_ssize > lmemlim) {
vm_map_unlock(map);
return (KERN_NO_SPACE);
}
@@ -3505,8 +3498,7 @@ Retry:
grow_amount = limit - ctob(vm->vm_ssize);
#endif
if (!old_mlock && map->flags & MAP_WIREFUTURE) {
- if (ptoa(vmspace_wired_count(p->p_vmspace)) + grow_amount >
- lmemlim) {
+ if (ptoa(pmap_wired_count(map->pmap)) + grow_amount > lmemlim) {
vm_map_unlock_read(map);
rv = KERN_NO_SPACE;
goto out;
@@ -3514,7 +3506,7 @@ Retry:
#ifdef RACCT
PROC_LOCK(p);
if (racct_set(p, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(p->p_vmspace)) + grow_amount)) {
+ ptoa(pmap_wired_count(map->pmap)) + grow_amount)) {
PROC_UNLOCK(p);
vm_map_unlock_read(map);
rv = KERN_NO_SPACE;
@@ -3645,7 +3637,7 @@ out:
KASSERT(error == 0, ("decreasing RACCT_VMEM failed"));
if (!old_mlock) {
error = racct_set(p, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(p->p_vmspace)));
+ ptoa(pmap_wired_count(map->pmap)));
KASSERT(error == 0, ("decreasing RACCT_MEMLOCK failed"));
}
error = racct_set(p, RACCT_STACK, ctob(vm->vm_ssize));
diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
index b3b1ad4..135b555 100644
--- a/sys/vm/vm_map.h
+++ b/sys/vm/vm_map.h
@@ -298,7 +298,6 @@ void vm_map_wait_busy(vm_map_t map);
_vm_map_lock_downgrade(map, LOCK_FILE, LOCK_LINE)
long vmspace_resident_count(struct vmspace *vmspace);
-long vmspace_wired_count(struct vmspace *vmspace);
#endif /* _KERNEL */
diff --git a/sys/vm/vm_meter.c b/sys/vm/vm_meter.c
index b5bb0fa..05174e9 100644
--- a/sys/vm/vm_meter.c
+++ b/sys/vm/vm_meter.c
@@ -283,6 +283,7 @@ VM_STATS_SYS(v_syscall, "System calls");
VM_STATS_SYS(v_intr, "Device interrupts");
VM_STATS_SYS(v_soft, "Software interrupts");
VM_STATS_VM(v_vm_faults, "Address memory faults");
+VM_STATS_VM(v_io_faults, "Page faults requiring I/O");
VM_STATS_VM(v_cow_faults, "Copy-on-write faults");
VM_STATS_VM(v_cow_optim, "Optimized COW faults");
VM_STATS_VM(v_zfod, "Pages zero-filled on demand");
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index 3ad7c37..4ae1f90 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -1044,6 +1044,7 @@ sys_mlock(td, uap)
struct proc *proc;
vm_offset_t addr, end, last, start;
vm_size_t npages, size;
+ vm_map_t map;
unsigned long nsize;
int error;
@@ -1061,8 +1062,9 @@ sys_mlock(td, uap)
if (npages > vm_page_max_wired)
return (ENOMEM);
proc = td->td_proc;
+ map = &proc->p_vmspace->vm_map;
PROC_LOCK(proc);
- nsize = ptoa(npages + vmspace_wired_count(proc->p_vmspace));
+ nsize = ptoa(npages + pmap_wired_count(map->pmap));
if (nsize > lim_cur(proc, RLIMIT_MEMLOCK)) {
PROC_UNLOCK(proc);
return (ENOMEM);
@@ -1077,13 +1079,13 @@ sys_mlock(td, uap)
if (error != 0)
return (ENOMEM);
#endif
- error = vm_map_wire(&proc->p_vmspace->vm_map, start, end,
+ error = vm_map_wire(map, start, end,
VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
#ifdef RACCT
if (error != KERN_SUCCESS) {
PROC_LOCK(proc);
racct_set(proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(proc->p_vmspace)));
+ ptoa(pmap_wired_count(map->pmap)));
PROC_UNLOCK(proc);
}
#endif
@@ -1157,7 +1159,7 @@ sys_mlockall(td, uap)
if (error != KERN_SUCCESS) {
PROC_LOCK(td->td_proc);
racct_set(td->td_proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(td->td_proc->p_vmspace)));
+ ptoa(pmap_wired_count(map->pmap)));
PROC_UNLOCK(td->td_proc);
}
#endif
@@ -1491,16 +1493,15 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
return (ENOMEM);
}
if (!old_mlock && map->flags & MAP_WIREFUTURE) {
- if (ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
- size > lim_cur(td->td_proc, RLIMIT_MEMLOCK)) {
+ if (ptoa(pmap_wired_count(map->pmap)) + size >
+ lim_cur(td->td_proc, RLIMIT_MEMLOCK)) {
racct_set_force(td->td_proc, RACCT_VMEM,
map->size);
PROC_UNLOCK(td->td_proc);
return (ENOMEM);
}
error = racct_set(td->td_proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
- size);
+ ptoa(pmap_wired_count(map->pmap)) + size);
if (error != 0) {
racct_set_force(td->td_proc, RACCT_VMEM,
map->size);
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index 6aee2bc..7beee59 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -138,6 +138,7 @@ struct vm_object {
struct {
TAILQ_HEAD(, vm_page) devp_pglist;
struct cdev_pager_ops *ops;
+ struct cdev *dev;
} devp;
/*
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index b5e9747..ac593a4 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -151,18 +151,21 @@ static struct mtx vm_daemon_mtx;
MTX_SYSINIT(vm_daemon, &vm_daemon_mtx, "vm daemon", MTX_DEF);
#endif
static int vm_max_launder = 32;
-static int vm_pageout_stats_max=0, vm_pageout_stats_interval = 0;
-static int vm_pageout_full_stats_interval = 0;
-static int vm_pageout_algorithm=0;
-static int defer_swap_pageouts=0;
-static int disable_swap_pageouts=0;
+static int vm_pageout_stats_max;
+static int vm_pageout_stats;
+static int vm_pageout_stats_interval;
+static int vm_pageout_full_stats;
+static int vm_pageout_full_stats_interval;
+static int vm_pageout_algorithm;
+static int defer_swap_pageouts;
+static int disable_swap_pageouts;
#if defined(NO_SWAPPING)
-static int vm_swap_enabled=0;
-static int vm_swap_idle_enabled=0;
+static int vm_swap_enabled = 0;
+static int vm_swap_idle_enabled = 0;
#else
-static int vm_swap_enabled=1;
-static int vm_swap_idle_enabled=0;
+static int vm_swap_enabled = 1;
+static int vm_swap_idle_enabled = 0;
#endif
SYSCTL_INT(_vm, VM_PAGEOUT_ALGORITHM, pageout_algorithm,
@@ -174,12 +177,18 @@ SYSCTL_INT(_vm, OID_AUTO, max_launder,
SYSCTL_INT(_vm, OID_AUTO, pageout_stats_max,
CTLFLAG_RW, &vm_pageout_stats_max, 0, "Max pageout stats scan length");
-SYSCTL_INT(_vm, OID_AUTO, pageout_full_stats_interval,
- CTLFLAG_RW, &vm_pageout_full_stats_interval, 0, "Interval for full stats scan");
+SYSCTL_INT(_vm, OID_AUTO, pageout_stats,
+ CTLFLAG_RD, &vm_pageout_stats, 0, "Number of partial stats scans");
SYSCTL_INT(_vm, OID_AUTO, pageout_stats_interval,
CTLFLAG_RW, &vm_pageout_stats_interval, 0, "Interval for partial stats scan");
+SYSCTL_INT(_vm, OID_AUTO, pageout_full_stats,
+ CTLFLAG_RD, &vm_pageout_full_stats, 0, "Number of full stats scans");
+
+SYSCTL_INT(_vm, OID_AUTO, pageout_full_stats_interval,
+ CTLFLAG_RW, &vm_pageout_full_stats_interval, 0, "Interval for full stats scan");
+
#if defined(NO_SWAPPING)
SYSCTL_INT(_vm, VM_SWAPPING_ENABLED, swap_enabled,
CTLFLAG_RD, &vm_swap_enabled, 0, "Enable entire process swapout");
@@ -1512,12 +1521,12 @@ vm_pageout_oom(int shortage)
* helps the situation where paging just starts to occur.
*/
static void
-vm_pageout_page_stats()
+vm_pageout_page_stats(void)
{
struct vm_pagequeue *pq;
vm_object_t object;
- vm_page_t m,next;
- int pcount,tpcount; /* Number of pages to check */
+ vm_page_t m, next;
+ int pcount, tpcount; /* Number of pages to check */
static int fullintervalcount = 0;
int page_shortage;
@@ -1531,11 +1540,13 @@ vm_pageout_page_stats()
pcount = cnt.v_active_count;
fullintervalcount += vm_pageout_stats_interval;
if (fullintervalcount < vm_pageout_full_stats_interval) {
+ vm_pageout_stats++;
tpcount = (int64_t)vm_pageout_stats_max * cnt.v_active_count /
cnt.v_page_count;
if (pcount > tpcount)
pcount = tpcount;
} else {
+ vm_pageout_full_stats++;
fullintervalcount = 0;
}
@@ -1624,7 +1635,7 @@ vm_pageout_page_stats()
* vm_pageout is the high level pageout daemon.
*/
static void
-vm_pageout()
+vm_pageout(void)
{
int error, pass;
@@ -1757,7 +1768,7 @@ vm_pageout()
* the free page queue lock is held until the msleep() is performed.
*/
void
-pagedaemon_wakeup()
+pagedaemon_wakeup(void)
{
if (!vm_pages_needed && curthread->td_proc != pageproc) {
@@ -1782,7 +1793,7 @@ vm_req_vmdaemon(int req)
}
static void
-vm_daemon()
+vm_daemon(void)
{
struct rlimit rsslim;
struct proc *p;
diff --git a/sys/vm/vm_unix.c b/sys/vm/vm_unix.c
index d6da08b..edb6ecc 100644
--- a/sys/vm/vm_unix.c
+++ b/sys/vm/vm_unix.c
@@ -76,6 +76,7 @@ sys_obreak(td, uap)
struct obreak_args *uap;
{
struct vmspace *vm = td->td_proc->p_vmspace;
+ vm_map_t map = &vm->vm_map;
vm_offset_t new, old, base;
rlim_t datalim, lmemlim, vmemlim;
int prot, rv;
@@ -90,7 +91,7 @@ sys_obreak(td, uap)
do_map_wirefuture = FALSE;
new = round_page((vm_offset_t)uap->nsize);
- vm_map_lock(&vm->vm_map);
+ vm_map_lock(map);
base = round_page((vm_offset_t) vm->vm_daddr);
old = base + ctob(vm->vm_dsize);
@@ -103,7 +104,7 @@ sys_obreak(td, uap)
error = ENOMEM;
goto done;
}
- if (new > vm_map_max(&vm->vm_map)) {
+ if (new > vm_map_max(map)) {
error = ENOMEM;
goto done;
}
@@ -117,14 +118,14 @@ sys_obreak(td, uap)
goto done;
}
if (new > old) {
- if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
- if (ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
+ if (!old_mlock && map->flags & MAP_WIREFUTURE) {
+ if (ptoa(pmap_wired_count(map->pmap)) +
(new - old) > lmemlim) {
error = ENOMEM;
goto done;
}
}
- if (vm->vm_map.size + (new - old) > vmemlim) {
+ if (map->size + (new - old) > vmemlim) {
error = ENOMEM;
goto done;
}
@@ -137,22 +138,21 @@ sys_obreak(td, uap)
goto done;
}
error = racct_set(td->td_proc, RACCT_VMEM,
- vm->vm_map.size + (new - old));
+ map->size + (new - old));
if (error != 0) {
racct_set_force(td->td_proc, RACCT_DATA, old - base);
PROC_UNLOCK(td->td_proc);
error = ENOMEM;
goto done;
}
- if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
+ if (!old_mlock && map->flags & MAP_WIREFUTURE) {
error = racct_set(td->td_proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(td->td_proc->p_vmspace)) +
- (new - old));
+ ptoa(pmap_wired_count(map->pmap)) + (new - old));
if (error != 0) {
racct_set_force(td->td_proc, RACCT_DATA,
old - base);
racct_set_force(td->td_proc, RACCT_VMEM,
- vm->vm_map.size);
+ map->size);
PROC_UNLOCK(td->td_proc);
error = ENOMEM;
goto done;
@@ -167,17 +167,15 @@ sys_obreak(td, uap)
prot |= VM_PROT_EXECUTE;
#endif
#endif
- rv = vm_map_insert(&vm->vm_map, NULL, 0, old, new,
- prot, VM_PROT_ALL, 0);
+ rv = vm_map_insert(map, NULL, 0, old, new, prot, VM_PROT_ALL, 0);
if (rv != KERN_SUCCESS) {
#ifdef RACCT
PROC_LOCK(td->td_proc);
racct_set_force(td->td_proc, RACCT_DATA, old - base);
- racct_set_force(td->td_proc, RACCT_VMEM, vm->vm_map.size);
- if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
+ racct_set_force(td->td_proc, RACCT_VMEM, map->size);
+ if (!old_mlock && map->flags & MAP_WIREFUTURE) {
racct_set_force(td->td_proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(
- td->td_proc->p_vmspace)));
+ ptoa(pmap_wired_count(map->pmap)));
}
PROC_UNLOCK(td->td_proc);
#endif
@@ -194,13 +192,13 @@ sys_obreak(td, uap)
*
* XXX If the pages cannot be wired, no error is returned.
*/
- if ((vm->vm_map.flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) {
+ if ((map->flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) {
if (bootverbose)
printf("obreak: MAP_WIREFUTURE set\n");
do_map_wirefuture = TRUE;
}
} else if (new < old) {
- rv = vm_map_delete(&vm->vm_map, new, old);
+ rv = vm_map_delete(map, new, old);
if (rv != KERN_SUCCESS) {
error = ENOMEM;
goto done;
@@ -209,19 +207,19 @@ sys_obreak(td, uap)
#ifdef RACCT
PROC_LOCK(td->td_proc);
racct_set_force(td->td_proc, RACCT_DATA, new - base);
- racct_set_force(td->td_proc, RACCT_VMEM, vm->vm_map.size);
- if (!old_mlock && vm->vm_map.flags & MAP_WIREFUTURE) {
+ racct_set_force(td->td_proc, RACCT_VMEM, map->size);
+ if (!old_mlock && map->flags & MAP_WIREFUTURE) {
racct_set_force(td->td_proc, RACCT_MEMLOCK,
- ptoa(vmspace_wired_count(td->td_proc->p_vmspace)));
+ ptoa(pmap_wired_count(map->pmap)));
}
PROC_UNLOCK(td->td_proc);
#endif
}
done:
- vm_map_unlock(&vm->vm_map);
+ vm_map_unlock(map);
if (do_map_wirefuture)
- (void) vm_map_wire(&vm->vm_map, old, new,
+ (void) vm_map_wire(map, old, new,
VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES);
return (error);
diff --git a/sys/x86/x86/intr_machdep.c b/sys/x86/x86/intr_machdep.c
index 31cc80b..e21635f 100644
--- a/sys/x86/x86/intr_machdep.c
+++ b/sys/x86/x86/intr_machdep.c
@@ -78,7 +78,7 @@ static int intrcnt_index;
static struct intsrc *interrupt_sources[NUM_IO_INTS];
static struct mtx intr_table_lock;
static struct mtx intrcnt_lock;
-static STAILQ_HEAD(, pic) pics;
+static TAILQ_HEAD(pics_head, pic) pics;
#ifdef SMP
static int assign_cpu;
@@ -102,7 +102,7 @@ intr_pic_registered(struct pic *pic)
{
struct pic *p;
- STAILQ_FOREACH(p, &pics, pics) {
+ TAILQ_FOREACH(p, &pics, pics) {
if (p == pic)
return (1);
}
@@ -124,7 +124,7 @@ intr_register_pic(struct pic *pic)
if (intr_pic_registered(pic))
error = EBUSY;
else {
- STAILQ_INSERT_TAIL(&pics, pic, pics);
+ TAILQ_INSERT_TAIL(&pics, pic, pics);
error = 0;
}
mtx_unlock(&intr_table_lock);
@@ -287,7 +287,7 @@ intr_resume(void)
atpic_reset();
#endif
mtx_lock(&intr_table_lock);
- STAILQ_FOREACH(pic, &pics, pics) {
+ TAILQ_FOREACH(pic, &pics, pics) {
if (pic->pic_resume != NULL)
pic->pic_resume(pic);
}
@@ -300,7 +300,7 @@ intr_suspend(void)
struct pic *pic;
mtx_lock(&intr_table_lock);
- STAILQ_FOREACH(pic, &pics, pics) {
+ TAILQ_FOREACH_REVERSE(pic, &pics, pics_head, pics) {
if (pic->pic_suspend != NULL)
pic->pic_suspend(pic);
}
@@ -381,7 +381,7 @@ intr_init(void *dummy __unused)
intrcnt_setname("???", 0);
intrcnt_index = 1;
- STAILQ_INIT(&pics);
+ TAILQ_INIT(&pics);
mtx_init(&intr_table_lock, "intr sources", NULL, MTX_DEF);
mtx_init(&intrcnt_lock, "intrcnt", NULL, MTX_SPIN);
}
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index e994172..c60db22 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -227,8 +227,8 @@ lapic_init(vm_paddr_t addr)
/* Map the local APIC and setup the spurious interrupt handler. */
KASSERT(trunc_page(addr) == addr,
("local APIC not aligned on a page boundary"));
- lapic = pmap_mapdev(addr, sizeof(lapic_t));
lapic_paddr = addr;
+ lapic = pmap_mapdev(addr, sizeof(lapic_t));
setidt(APIC_SPURIOUS_INT, IDTVEC(spuriousint), SDT_APIC, SEL_KPL,
GSEL_APIC);
@@ -1360,11 +1360,19 @@ apic_setup_io(void *dummy __unused)
if (best_enum == NULL)
return;
+
+ /*
+ * Local APIC must be registered before other PICs and pseudo PICs
+ * for proper suspend/resume order.
+ */
+#ifndef XEN
+ intr_register_pic(&lapic_pic);
+#endif
+
retval = best_enum->apic_setup_io();
if (retval != 0)
printf("%s: Failed to setup I/O APICs: returned %d\n",
best_enum->apic_name, retval);
-
#ifdef XEN
return;
#endif
@@ -1373,7 +1381,6 @@ apic_setup_io(void *dummy __unused)
* properly program the LINT pins.
*/
lapic_setup(1);
- intr_register_pic(&lapic_pic);
if (bootverbose)
lapic_dump("BSP");
diff --git a/sys/x86/x86/tsc.c b/sys/x86/x86/tsc.c
index 04231b8..4f67818 100644
--- a/sys/x86/x86/tsc.c
+++ b/sys/x86/x86/tsc.c
@@ -67,6 +67,11 @@ SYSCTL_INT(_kern_timecounter, OID_AUTO, smp_tsc, CTLFLAG_RDTUN, &smp_tsc, 0,
TUNABLE_INT("kern.timecounter.smp_tsc", &smp_tsc);
#endif
+static int tsc_shift = 1;
+SYSCTL_INT(_kern_timecounter, OID_AUTO, tsc_shift, CTLFLAG_RDTUN,
+ &tsc_shift, 0, "Shift to pre-apply for the maximum TSC frequency");
+TUNABLE_INT("kern.timecounter.tsc_shift", &tsc_shift);
+
static int tsc_disabled;
SYSCTL_INT(_machdep, OID_AUTO, disable_tsc, CTLFLAG_RDTUN, &tsc_disabled, 0,
"Disable x86 Time Stamp Counter");
@@ -399,12 +404,12 @@ comp_smp_tsc(void *arg)
}
static int
-test_smp_tsc(void)
+test_tsc(void)
{
uint64_t *data, *tsc;
u_int i, size;
- if (!smp_tsc && !tsc_is_invariant)
+ if ((!smp_tsc && !tsc_is_invariant) || vm_guest)
return (-100);
size = (mp_maxid + 1) * 3;
data = malloc(sizeof(*data) * size * N, M_TEMP, M_WAITOK);
@@ -444,6 +449,19 @@ test_smp_tsc(void)
#undef N
+#else
+
+/*
+ * The function is not called, it is provided to avoid linking failure
+ * on uniprocessor kernel.
+ */
+static int
+test_tsc(void)
+{
+
+ return (0);
+}
+
#endif /* SMP */
static void
@@ -492,41 +510,37 @@ init_TSC_tc(void)
goto init;
}
-#ifdef SMP
/*
- * We can not use the TSC in SMP mode unless the TSCs on all CPUs are
- * synchronized. If the user is sure that the system has synchronized
- * TSCs, set kern.timecounter.smp_tsc tunable to a non-zero value.
- * We also limit the frequency even lower to avoid "temporal anomalies"
- * as much as possible. The TSC seems unreliable in virtualized SMP
+ * We can not use the TSC in SMP mode unless the TSCs on all CPUs
+ * are synchronized. If the user is sure that the system has
+ * synchronized TSCs, set kern.timecounter.smp_tsc tunable to a
+ * non-zero value. The TSC seems unreliable in virtualized SMP
* environments, so it is set to a negative quality in those cases.
*/
- if (smp_cpus > 1) {
- if (vm_guest != 0) {
- tsc_timecounter.tc_quality = -100;
- } else {
- tsc_timecounter.tc_quality = test_smp_tsc();
- max_freq >>= 8;
- }
- } else
-#endif
- if (tsc_is_invariant)
+ if (mp_ncpus > 1)
+ tsc_timecounter.tc_quality = test_tsc();
+ else if (tsc_is_invariant)
tsc_timecounter.tc_quality = 1000;
+ max_freq >>= tsc_shift;
init:
- for (shift = 0; shift < 31 && (tsc_freq >> shift) > max_freq; shift++)
+ for (shift = 0; shift <= 31 && (tsc_freq >> shift) > max_freq; shift++)
;
+ if ((cpu_feature & CPUID_SSE2) != 0 && mp_ncpus > 1) {
+ if (cpu_vendor_id == CPU_VENDOR_AMD) {
+ tsc_timecounter.tc_get_timecount = shift > 0 ?
+ tsc_get_timecount_low_mfence :
+ tsc_get_timecount_mfence;
+ } else {
+ tsc_timecounter.tc_get_timecount = shift > 0 ?
+ tsc_get_timecount_low_lfence :
+ tsc_get_timecount_lfence;
+ }
+ } else {
+ tsc_timecounter.tc_get_timecount = shift > 0 ?
+ tsc_get_timecount_low : tsc_get_timecount;
+ }
if (shift > 0) {
- if (cpu_feature & CPUID_SSE2) {
- if (cpu_vendor_id == CPU_VENDOR_AMD) {
- tsc_timecounter.tc_get_timecount =
- tsc_get_timecount_low_mfence;
- } else {
- tsc_timecounter.tc_get_timecount =
- tsc_get_timecount_low_lfence;
- }
- } else
- tsc_timecounter.tc_get_timecount = tsc_get_timecount_low;
tsc_timecounter.tc_name = "TSC-low";
if (bootverbose)
printf("TSC timecounter discards lower %d bit(s)\n",
OpenPOWER on IntegriCloud