[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree
zrouter-src-freebsd at zrouter.org
zrouter-src-freebsd at zrouter.org
Wed Jul 25 14:36:14 UTC 2012
details: http://zrouter.org/hg/FreeBSD/head//rev/58b18bd1429e
changeset: 496:58b18bd1429e
user: Aleksandr Rybalko <ray at ddteam.net>
date: Wed Jul 25 16:45:04 2012 +0300
description:
Lazy update
diffstat:
head/sys/boot/Makefile.sparc64 | 3 +-
head/sys/boot/arm/at91/boot0spi/main.c | 18 +-
head/sys/boot/arm/at91/boot2/boot2.c | 14 +-
head/sys/boot/arm/at91/bootspi/ee.c | 10 +-
head/sys/boot/arm/at91/libat91/Makefile | 6 +-
head/sys/boot/arm/at91/libat91/at91rm9200.h | 6 +-
head/sys/boot/arm/at91/libat91/at91rm9200_lowlevel.c | 6 +-
head/sys/boot/arm/at91/libat91/eeprom.c | 10 +-
head/sys/boot/arm/at91/libat91/emac_init.c | 30 +-
head/sys/boot/arm/at91/libat91/lib_AT91RM9200.h | 14 +-
head/sys/boot/arm/at91/libat91/spi_flash.c | 10 +-
head/sys/boot/arm/at91/linker.cfg | 234 +-
head/sys/boot/arm/ixp425/boot2/boot2.c | 9 +-
head/sys/boot/arm/uboot/Makefile | 29 +-
head/sys/boot/arm/uboot/conf.c | 5 +-
head/sys/boot/arm/uboot/ldscript.arm | 4 +-
head/sys/boot/arm/uboot/start.S | 13 +-
head/sys/boot/arm/uboot/version | 3 +-
head/sys/boot/common/boot.c | 20 +-
head/sys/boot/common/bootstrap.h | 16 +-
head/sys/boot/common/load_elf.c | 4 +-
head/sys/boot/common/load_elf_obj.c | 4 +-
head/sys/boot/common/loader.8 | 4 +-
head/sys/boot/common/ufsread.c | 18 +-
head/sys/boot/fdt/dts/bindings-localbus.txt | 83 +
head/sys/boot/fdt/dts/db78100.dts | 21 +-
head/sys/boot/fdt/dts/db88f6281.dts | 50 +-
head/sys/boot/fdt/dts/p2041rdb.dts | 490 +
head/sys/boot/fdt/dts/p2041si.dtsi | 1296 +
head/sys/boot/fdt/dts/p3041ds.dts | 998 +-
head/sys/boot/fdt/dts/p3041si.dtsi | 1339 +
head/sys/boot/fdt/dts/p5020ds.dts | 583 +
head/sys/boot/fdt/dts/p5020si.dtsi | 1389 +
head/sys/boot/fdt/dts/sheevaplug.dts | 45 +-
head/sys/boot/fdt/fdt_loader_cmd.c | 107 +-
head/sys/boot/forth/beastie.4th | 4 +-
head/sys/boot/forth/beastie.4th.8 | 6 +-
head/sys/boot/forth/brand.4th | 4 +-
head/sys/boot/forth/brand.4th.8 | 6 +-
head/sys/boot/forth/check-password.4th | 4 +-
head/sys/boot/forth/check-password.4th.8 | 6 +-
head/sys/boot/forth/color.4th | 4 +-
head/sys/boot/forth/color.4th.8 | 6 +-
head/sys/boot/forth/delay.4th | 4 +-
head/sys/boot/forth/delay.4th.8 | 6 +-
head/sys/boot/forth/menu-commands.4th | 4 +-
head/sys/boot/forth/menu.4th | 4 +-
head/sys/boot/forth/menu.4th.8 | 6 +-
head/sys/boot/forth/shortcuts.4th | 4 +-
head/sys/boot/forth/version.4th | 4 +-
head/sys/boot/forth/version.4th.8 | 6 +-
head/sys/boot/i386/boot2/boot2.c | 13 +-
head/sys/boot/i386/btx/btx/Makefile | 3 +-
head/sys/boot/i386/btx/btx/btx.S | 6 +-
head/sys/boot/i386/btx/btxldr/Makefile | 3 +-
head/sys/boot/i386/btx/btxldr/btxldr.S | 24 +-
head/sys/boot/i386/btx/lib/Makefile | 5 +-
head/sys/boot/i386/btx/lib/btxcsu.S | 49 +
head/sys/boot/i386/btx/lib/btxcsu.s | 51 -
head/sys/boot/i386/cdboot/Makefile | 10 +-
head/sys/boot/i386/cdboot/cdboot.S | 597 +
head/sys/boot/i386/cdboot/cdboot.s | 600 -
head/sys/boot/i386/common/bootargs.h | 69 +
head/sys/boot/i386/efi/reloc.c | 13 +-
head/sys/boot/i386/gptboot/gptboot.c | 9 +-
head/sys/boot/i386/libi386/Makefile | 4 +-
head/sys/boot/i386/libi386/biosdisk.c | 3 +-
head/sys/boot/i386/libi386/biospnp.c | 3 +-
head/sys/boot/i386/libi386/devicename.c | 13 +-
head/sys/boot/i386/libi386/libi386.h | 14 +-
head/sys/boot/i386/loader/Makefile | 13 +-
head/sys/boot/i386/loader/conf.c | 16 +-
head/sys/boot/i386/loader/main.c | 114 +-
head/sys/boot/i386/pxeldr/Makefile | 4 +-
head/sys/boot/i386/pxeldr/pxeldr.S | 8 +-
head/sys/boot/i386/zfsboot/zfsboot.c | 73 +-
head/sys/boot/ofw/libofw/Makefile | 4 +-
head/sys/boot/ofw/libofw/devicename.c | 23 +-
head/sys/boot/ofw/libofw/libofw.h | 10 +-
head/sys/boot/ofw/libofw/ofw_disk.c | 124 +-
head/sys/boot/pc98/boot2/boot2.c | 9 +-
head/sys/boot/pc98/btx/btx/Makefile | 3 +-
head/sys/boot/pc98/btx/btx/btx.S | 6 +-
head/sys/boot/pc98/btx/btxldr/Makefile | 3 +-
head/sys/boot/pc98/btx/btxldr/btxldr.S | 24 +-
head/sys/boot/pc98/btx/lib/Makefile | 5 +-
head/sys/boot/pc98/btx/lib/btxcsu.S | 49 +
head/sys/boot/pc98/btx/lib/btxcsu.s | 51 -
head/sys/boot/pc98/cdboot/Makefile | 6 +-
head/sys/boot/pc98/cdboot/cdboot.S | 808 +
head/sys/boot/pc98/cdboot/cdboot.s | 811 -
head/sys/boot/pc98/libpc98/Makefile | 4 +-
head/sys/boot/pc98/libpc98/biosdisk.c | 3 +-
head/sys/boot/pc98/loader/main.c | 20 +-
head/sys/boot/powerpc/boot1.chrp/boot1.c | 5 +-
head/sys/boot/sparc64/Makefile | 4 +-
head/sys/boot/sparc64/boot1/Makefile | 13 +-
head/sys/boot/sparc64/boot1/boot1.c | 139 +-
head/sys/boot/sparc64/loader/Makefile | 29 +-
head/sys/boot/sparc64/loader/main.c | 107 +-
head/sys/boot/sparc64/zfsboot/Makefile | 9 +
head/sys/boot/sparc64/zfsloader/Makefile | 9 +
head/sys/boot/uboot/common/metadata.c | 17 +-
head/sys/boot/uboot/lib/api_public.h | 3 +-
head/sys/boot/uboot/lib/copy.c | 50 +-
head/sys/boot/uboot/lib/devicename.c | 9 +-
head/sys/boot/uboot/lib/disk.c | 99 +-
head/sys/boot/uboot/lib/elf_freebsd.c | 9 +-
head/sys/boot/uboot/lib/glue.c | 5 +-
head/sys/boot/uboot/lib/libuboot.h | 4 +-
head/sys/boot/userboot/libstand/Makefile | 19 +-
head/sys/boot/zfs/devicename_stubs.c | 47 +
head/sys/boot/zfs/libzfs.h | 66 +
head/sys/boot/zfs/zfs.c | 256 +-
head/sys/boot/zfs/zfsimpl.c | 444 +-
head/sys/cam/ata/ata_all.c | 120 +-
head/sys/cam/ata/ata_all.h | 38 +-
head/sys/cam/ata/ata_da.c | 147 +-
head/sys/cam/ata/ata_pmp.c | 60 +-
head/sys/cam/ata/ata_xpt.c | 551 +-
head/sys/cam/cam.h | 11 +-
head/sys/cam/cam_ccb.h | 16 +-
head/sys/cam/cam_debug.h | 52 +-
head/sys/cam/cam_periph.c | 650 +-
head/sys/cam/cam_periph.h | 3 +-
head/sys/cam/cam_sim.h | 3 +-
head/sys/cam/cam_xpt.c | 145 +-
head/sys/cam/cam_xpt.h | 24 +-
head/sys/cam/cam_xpt_periph.h | 5 +-
head/sys/cam/cam_xpt_sim.h | 4 +-
head/sys/cam/ctl/ctl.c | 14 +-
head/sys/cam/ctl/ctl_backend.c | 7 +-
head/sys/cam/ctl/ctl_frontend_cam_sim.c | 7 +-
head/sys/cam/ctl/ctl_frontend_internal.c | 7 +-
head/sys/cam/ctl/scsi_ctl.c | 61 +-
head/sys/cam/scsi/scsi_all.c | 298 +-
head/sys/cam/scsi/scsi_all.h | 49 +-
head/sys/cam/scsi/scsi_cd.c | 123 +-
head/sys/cam/scsi/scsi_ch.c | 28 +-
head/sys/cam/scsi/scsi_da.c | 238 +-
head/sys/cam/scsi/scsi_da.h | 3 +-
head/sys/cam/scsi/scsi_enc.c | 1023 +
head/sys/cam/scsi/scsi_enc.h | 219 +
head/sys/cam/scsi/scsi_enc_internal.h | 230 +
head/sys/cam/scsi/scsi_enc_safte.c | 1137 +
head/sys/cam/scsi/scsi_enc_ses.c | 2816 ++
head/sys/cam/scsi/scsi_pass.c | 109 +-
head/sys/cam/scsi/scsi_pt.c | 13 +-
head/sys/cam/scsi/scsi_sa.c | 8 +-
head/sys/cam/scsi/scsi_ses.c | 2533 --
head/sys/cam/scsi/scsi_ses.h | 2452 +-
head/sys/cam/scsi/scsi_sg.c | 27 +-
head/sys/cam/scsi/scsi_target.c | 6 +-
head/sys/cam/scsi/scsi_xpt.c | 93 +-
head/sys/cddl/boot/zfs/zfsimpl.h | 16 +-
head/sys/cddl/contrib/opensolaris/common/nvpair/fnvpair.c | 498 +
head/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c | 155 +
head/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h | 70 +
head/sys/cddl/contrib/opensolaris/common/zfs/zpool_prop.c | 26 +-
head/sys/cddl/contrib/opensolaris/uts/common/Makefile.files | 10 +-
head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c | 107 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c | 4 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c | 224 +
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c | 3 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c | 9 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c | 126 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c | 280 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c | 107 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c | 5 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c | 19 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c | 4 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c | 202 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c | 8 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c | 57 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c | 187 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c | 16 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c | 483 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c | 9 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c | 57 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c | 5 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/bptree.h | 64 +
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h | 101 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_impl.h | 30 +
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_traverse.h | 4 +
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h | 13 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h | 9 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_scan.h | 4 +
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h | 17 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h | 9 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev.h | 5 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_impl.h | 8 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h | 9 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfeature.h | 52 +
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio.h | 14 +
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_impl.h | 2 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c | 30 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_disk.c | 64 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_file.c | 6 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c | 7 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_label.c | 103 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_mirror.c | 8 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_missing.c | 8 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_raidz.c | 6 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_root.c | 8 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c | 14 +
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c | 6 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c | 414 +
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 92 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c | 2 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c | 11 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c | 2 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c | 46 +-
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c | 12 +-
head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h | 34 +
head/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h | 28 +-
head/sys/cddl/contrib/opensolaris/uts/common/sys/nvpair.h | 68 +
head/sys/cddl/dev/dtrace/amd64/dis_tables.c | 12 +-
head/sys/cddl/dev/dtrace/amd64/dtrace_subr.c | 32 +-
head/sys/cddl/dev/dtrace/i386/dis_tables.c | 12 +-
head/sys/cddl/dev/dtrace/i386/dtrace_subr.c | 32 +-
head/sys/compat/freebsd32/freebsd32.h | 4 +-
head/sys/compat/freebsd32/freebsd32_misc.c | 5 +-
head/sys/compat/freebsd32/freebsd32_proto.h | 132 +-
head/sys/compat/freebsd32/freebsd32_syscall.h | 4 +-
head/sys/compat/freebsd32/freebsd32_syscalls.c | 4 +-
head/sys/compat/freebsd32/freebsd32_sysent.c | 4 +-
head/sys/compat/freebsd32/freebsd32_systrace_args.c | 238 +-
head/sys/compat/freebsd32/syscalls.master | 76 +-
head/sys/compat/ia32/ia32_sysvec.c | 4 +-
head/sys/compat/ia32/ia32_util.h | 19 +-
head/sys/compat/linux/check_error.d | 144 +
head/sys/compat/linux/check_internal_locks.d | 132 +
head/sys/compat/linux/linux_dtrace.h | 95 +
head/sys/compat/linux/linux_emul.c | 127 +-
head/sys/compat/linux/linux_emul.h | 43 +-
head/sys/compat/linux/linux_file.c | 7 +-
head/sys/compat/linux/linux_fork.c | 12 +-
head/sys/compat/linux/linux_futex.c | 511 +-
head/sys/compat/linux/linux_mib.c | 316 +-
head/sys/compat/linux/linux_misc.c | 16 +-
head/sys/compat/linux/linux_sysctl.c | 60 +-
head/sys/compat/linux/linux_time.c | 231 +-
head/sys/compat/linux/linux_uid16.c | 191 +-
head/sys/compat/linux/linux_util.c | 124 +-
head/sys/compat/linux/linux_util.h | 10 +-
head/sys/compat/linux/stats_timing.d | 94 +
head/sys/compat/linux/trace_futexes.d | 182 +
head/sys/compat/ndis/subr_ntoskrnl.c | 3 +-
head/sys/contrib/dev/acpica/acpica_prep.sh | 11 +-
head/sys/contrib/dev/acpica/changes.txt | 277 +-
head/sys/contrib/dev/acpica/common/adfile.c | 19 +-
head/sys/contrib/dev/acpica/common/adwalk.c | 30 +-
head/sys/contrib/dev/acpica/common/ahpredef.c | 323 +
head/sys/contrib/dev/acpica/common/dmextern.c | 36 +-
head/sys/contrib/dev/acpica/common/dmrestag.c | 21 +-
head/sys/contrib/dev/acpica/compiler/aslcompile.c | 178 +-
head/sys/contrib/dev/acpica/compiler/aslcompiler.h | 24 +-
head/sys/contrib/dev/acpica/compiler/aslcompiler.l | 712 +-
head/sys/contrib/dev/acpica/compiler/aslcompiler.y | 228 +-
head/sys/contrib/dev/acpica/compiler/aslerror.c | 40 +-
head/sys/contrib/dev/acpica/compiler/aslfiles.c | 184 +-
head/sys/contrib/dev/acpica/compiler/aslglobal.h | 5 +-
head/sys/contrib/dev/acpica/compiler/asllookup.c | 2 +-
head/sys/contrib/dev/acpica/compiler/aslmain.c | 91 +-
head/sys/contrib/dev/acpica/compiler/aslmap.c | 3 +-
head/sys/contrib/dev/acpica/compiler/aslmessages.h | 11 +-
head/sys/contrib/dev/acpica/compiler/aslrestype1.c | 8 +
head/sys/contrib/dev/acpica/compiler/aslstartup.c | 78 +-
head/sys/contrib/dev/acpica/compiler/aslsupport.l | 804 +
head/sys/contrib/dev/acpica/compiler/aslutils.c | 90 +-
head/sys/contrib/dev/acpica/compiler/dtio.c | 60 +-
head/sys/contrib/dev/acpica/compiler/dttemplate.c | 2 +-
head/sys/contrib/dev/acpica/compiler/preprocess.h | 17 -
head/sys/contrib/dev/acpica/compiler/prscan.c | 73 +-
head/sys/contrib/dev/acpica/compiler/prutils.c | 125 +-
head/sys/contrib/dev/acpica/components/debugger/dbcmds.c | 120 +-
head/sys/contrib/dev/acpica/components/debugger/dbdisply.c | 15 +-
head/sys/contrib/dev/acpica/components/debugger/dbexec.c | 6 +-
head/sys/contrib/dev/acpica/components/debugger/dbfileio.c | 13 +
head/sys/contrib/dev/acpica/components/debugger/dbinput.c | 4 +-
head/sys/contrib/dev/acpica/components/debugger/dbstats.c | 28 +-
head/sys/contrib/dev/acpica/components/debugger/dbutils.c | 9 +-
head/sys/contrib/dev/acpica/components/disassembler/dmopcode.c | 213 +
head/sys/contrib/dev/acpica/components/disassembler/dmwalk.c | 55 +-
head/sys/contrib/dev/acpica/components/dispatcher/dsfield.c | 88 +-
head/sys/contrib/dev/acpica/components/dispatcher/dsopcode.c | 14 +-
head/sys/contrib/dev/acpica/components/events/evgpe.c | 15 +-
head/sys/contrib/dev/acpica/components/events/evgpeutil.c | 19 +
head/sys/contrib/dev/acpica/components/events/evmisc.c | 203 +-
head/sys/contrib/dev/acpica/components/events/evxface.c | 362 +-
head/sys/contrib/dev/acpica/components/events/evxfgpe.c | 86 +-
head/sys/contrib/dev/acpica/components/executer/exconfig.c | 2 +-
head/sys/contrib/dev/acpica/components/executer/exdump.c | 29 +-
head/sys/contrib/dev/acpica/components/executer/exprep.c | 4 +-
head/sys/contrib/dev/acpica/components/executer/exresolv.c | 2 +-
head/sys/contrib/dev/acpica/components/executer/exstore.c | 6 +-
head/sys/contrib/dev/acpica/components/executer/exutils.c | 2 +-
head/sys/contrib/dev/acpica/components/hardware/hwesleep.c | 8 +-
head/sys/contrib/dev/acpica/components/hardware/hwsleep.c | 25 -
head/sys/contrib/dev/acpica/components/hardware/hwxfsleep.c | 8 +
head/sys/contrib/dev/acpica/components/namespace/nspredef.c | 2 +-
head/sys/contrib/dev/acpica/components/parser/psxface.c | 4 +-
head/sys/contrib/dev/acpica/components/resources/rscreate.c | 6 +-
head/sys/contrib/dev/acpica/components/resources/rsutils.c | 2 +-
head/sys/contrib/dev/acpica/components/tables/tbfadt.c | 64 +-
head/sys/contrib/dev/acpica/components/tables/tbinstal.c | 5 +-
head/sys/contrib/dev/acpica/components/tables/tbutils.c | 45 +-
head/sys/contrib/dev/acpica/components/tables/tbxface.c | 169 +-
head/sys/contrib/dev/acpica/components/tables/tbxfload.c | 415 +
head/sys/contrib/dev/acpica/components/tables/tbxfroot.c | 2 +-
head/sys/contrib/dev/acpica/components/utilities/utdecode.c | 62 +-
head/sys/contrib/dev/acpica/components/utilities/utdelete.c | 21 +-
head/sys/contrib/dev/acpica/components/utilities/utexcep.c | 174 +
head/sys/contrib/dev/acpica/components/utilities/utglobal.c | 9 +-
head/sys/contrib/dev/acpica/components/utilities/utmisc.c | 87 +-
head/sys/contrib/dev/acpica/components/utilities/utobject.c | 6 +-
head/sys/contrib/dev/acpica/components/utilities/utresrc.c | 4 +-
head/sys/contrib/dev/acpica/components/utilities/uttrack.c | 6 +-
head/sys/contrib/dev/acpica/components/utilities/utxferror.c | 81 +
head/sys/contrib/dev/acpica/include/acdebug.h | 5 +-
head/sys/contrib/dev/acpica/include/acdisasm.h | 8 +
head/sys/contrib/dev/acpica/include/acexcep.h | 5 +-
head/sys/contrib/dev/acpica/include/acglobal.h | 22 +-
head/sys/contrib/dev/acpica/include/aclocal.h | 45 +-
head/sys/contrib/dev/acpica/include/acmacros.h | 4 +-
head/sys/contrib/dev/acpica/include/acobject.h | 15 +-
head/sys/contrib/dev/acpica/include/acoutput.h | 4 +
head/sys/contrib/dev/acpica/include/acpiosxf.h | 2 +-
head/sys/contrib/dev/acpica/include/acpixf.h | 36 +-
head/sys/contrib/dev/acpica/include/acpredef.h | 6 +-
head/sys/contrib/dev/acpica/include/actbl1.h | 2 +-
head/sys/contrib/dev/acpica/include/actypes.h | 7 +-
head/sys/contrib/dev/acpica/include/acutils.h | 6 +-
head/sys/contrib/dev/acpica/include/platform/acenv.h | 2 +-
head/sys/contrib/dev/acpica/os_specific/service_layers/osunixxf.c | 21 +
head/sys/contrib/dev/iwn/iwlwifi-6000g2a-17.168.5.3.fw.uu | 7833 ++++++
head/sys/contrib/dev/iwn/iwlwifi-6000g2b-18.168.6.1.fw.uu | 11961 ++++++++++
head/sys/contrib/dev/ral/LICENSE.orig | 16 +
head/sys/contrib/dev/ral/rt2561.fw.uu.orig | 202 +
head/sys/contrib/dev/ral/rt2561s.fw.uu.orig | 202 +
head/sys/contrib/dev/ral/rt2661.fw.uu.orig | 202 +
head/sys/contrib/dev/ral/rt2860.fw.uu.orig | 202 +
head/sys/contrib/libfdt/fdt.c | 9 +
head/sys/contrib/libfdt/fdt_empty_tree.c | 84 +
head/sys/contrib/libfdt/fdt_ro.c | 125 +-
head/sys/contrib/libfdt/fdt_rw.c | 27 +
head/sys/contrib/libfdt/libfdt.h | 378 +-
head/sys/contrib/libfdt/libfdt_env.h | 16 +-
head/sys/contrib/libfdt/libfdt_internal.h | 1 +
head/sys/contrib/pf/net/pf.c | 6 +-
head/sys/contrib/pf/net/pf_if.c | 5 +-
head/sys/contrib/pf/net/pf_ioctl.c | 6 +-
head/sys/contrib/pf/net/pf_table.c | 3 +-
head/sys/contrib/pf/net/pfvar.h | 2 +
head/sys/contrib/rdma/krping/krping.c | 50 +-
head/sys/contrib/rdma/krping/krping.h | 6 +-
head/sys/contrib/rdma/krping/krping_dev.c | 8 +-
head/sys/contrib/rdma/rdma_addr.c | 7 +-
head/sys/contrib/rdma/rdma_cache.c | 4 +-
head/sys/geom/bde/g_bde.c | 8 +-
head/sys/geom/eli/g_eli.c | 4 +-
head/sys/geom/eli/g_eli.h | 19 +-
head/sys/geom/eli/g_eli_ctl.c | 8 +-
head/sys/geom/eli/g_eli_integrity.c | 9 +-
head/sys/geom/eli/g_eli_key.c | 6 +-
head/sys/geom/eli/g_eli_key_cache.c | 12 +-
head/sys/geom/gate/g_gate.c | 322 +-
head/sys/geom/gate/g_gate.h | 31 +-
head/sys/geom/geom.h | 9 +-
head/sys/geom/geom_aes.c | 6 +-
head/sys/geom/geom_dev.c | 4 +-
head/sys/geom/geom_disk.c | 75 +-
head/sys/geom/geom_disk.h | 8 +-
head/sys/geom/geom_flashmap.c | 256 +
head/sys/geom/geom_map.c | 21 +-
head/sys/geom/geom_slice.c | 6 +-
head/sys/geom/geom_subr.c | 88 +-
head/sys/geom/label/g_label_ufs.c | 8 +-
head/sys/geom/mirror/g_mirror.c | 28 +-
head/sys/geom/mirror/g_mirror.h | 7 +-
head/sys/geom/mirror/g_mirror_ctl.c | 15 +-
head/sys/geom/mountver/g_mountver.c | 16 +-
head/sys/geom/multipath/g_multipath.c | 31 +-
head/sys/geom/nop/g_nop.c | 30 +-
head/sys/geom/nop/g_nop.h | 3 +-
head/sys/geom/part/g_part.c | 14 +-
head/sys/geom/part/g_part.h | 3 +-
head/sys/geom/part/g_part_apm.c | 9 +-
head/sys/geom/part/g_part_bsd.c | 9 +-
head/sys/geom/part/g_part_gpt.c | 27 +-
head/sys/geom/part/g_part_vtoc8.c | 9 +-
head/sys/geom/raid/g_raid.c | 178 +-
head/sys/geom/raid/g_raid.h | 41 +-
head/sys/geom/raid/g_raid_ctl.c | 4 +-
head/sys/geom/raid/g_raid_md_if.m | 21 +-
head/sys/geom/raid/md_ddf.c | 3068 ++
head/sys/geom/raid/md_ddf.h | 345 +
head/sys/geom/raid/md_intel.c | 7 +-
head/sys/geom/raid/md_jmicron.c | 5 +-
head/sys/geom/raid/md_nvidia.c | 5 +-
head/sys/geom/raid/md_promise.c | 7 +-
head/sys/geom/raid/md_sii.c | 5 +-
head/sys/geom/raid/tr_raid1.c | 16 +-
head/sys/geom/raid/tr_raid1e.c | 26 +-
head/sys/geom/raid/tr_raid5.c | 112 +-
head/sys/geom/uncompress/g_uncompress.c | 6 +-
head/sys/geom/uzip/g_uzip.c | 6 +-
head/sys/gnu/fs/reiserfs/reiserfs_inode.c | 6 +-
head/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c | 6 +-
head/sys/ofed/drivers/infiniband/core/cma.c | 21 +-
head/sys/ofed/drivers/infiniband/core/iwcm.c | 3 +
head/sys/ofed/drivers/net/mlx4/en_netdev.c | 2 +-
head/sys/ofed/include/linux/net.h | 8 +-
head/sys/ofed/include/linux/workqueue.h | 2 +-
head/sys/ofed/include/net/netevent.h | 7 +-
head/sys/ofed/include/rdma/iw_cm.h | 4 +-
head/sys/security/mac_mls/mac_mls.c | 5 +-
head/sys/ufs/ffs/ffs_alloc.c | 9 +-
head/sys/ufs/ffs/ffs_extern.h | 4 +-
head/sys/ufs/ffs/ffs_inode.c | 7 +-
head/sys/ufs/ffs/ffs_snapshot.c | 12 +-
head/sys/ufs/ffs/ffs_softdep.c | 79 +-
head/sys/ufs/ffs/ffs_vfsops.c | 6 +-
head/sys/ufs/ffs/ffs_vnops.c | 25 +-
head/sys/ufs/ufs/ufs_extattr.c | 44 +-
head/sys/ufs/ufs/ufs_inode.c | 10 +-
head/sys/ufs/ufs/ufs_lookup.c | 4 +-
head/sys/ufs/ufs/ufs_vnops.c | 27 +-
head/sys/ufs/ufs/ufsmount.h | 6 +-
head/sys/vm/device_pager.c | 57 +-
head/sys/vm/memguard.c | 28 +-
head/sys/vm/memguard.h | 4 +-
head/sys/vm/pmap.h | 5 +-
head/sys/vm/swap_pager.c | 4 +-
head/sys/vm/uma_core.c | 10 +-
head/sys/vm/vm.h | 4 +-
head/sys/vm/vm_contig.c | 351 -
head/sys/vm/vm_fault.c | 169 +-
head/sys/vm/vm_kern.c | 144 +-
head/sys/vm/vm_map.c | 19 +-
head/sys/vm/vm_map.h | 17 +-
head/sys/vm/vm_mmap.c | 8 +-
head/sys/vm/vm_object.c | 11 +-
head/sys/vm/vm_object.h | 17 +-
head/sys/vm/vm_page.c | 90 +-
head/sys/vm/vm_page.h | 57 +-
head/sys/vm/vm_pageout.c | 236 +-
head/sys/vm/vm_pageout.h | 6 +-
head/sys/vm/vm_pager.c | 18 +-
head/sys/vm/vm_pager.h | 3 +-
head/sys/vm/vm_phys.c | 119 +-
head/sys/vm/vm_phys.h | 6 +-
head/sys/vm/vm_reserv.c | 4 +-
head/sys/vm/vnode_pager.c | 6 +-
454 files changed, 55199 insertions(+), 11136 deletions(-)
diffs (85172 lines):
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/Makefile.sparc64
--- a/head/sys/boot/Makefile.sparc64 Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/Makefile.sparc64 Wed Jul 25 16:45:04 2012 +0300
@@ -1,3 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/boot/Makefile.sparc64 235364 2012-05-12 20:27:33Z avg $
SUBDIR+= ofw
+SUBDIR+= zfs
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/at91/boot0spi/main.c
--- a/head/sys/boot/arm/at91/boot0spi/main.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/at91/boot0spi/main.c Wed Jul 25 16:45:04 2012 +0300
@@ -21,7 +21,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/arm/at91/boot0spi/main.c 238188 2012-07-07 04:55:42Z imp $
*/
#include "at91rm9200.h"
@@ -29,31 +29,26 @@
#include "at91rm9200_lowlevel.h"
#include "spi_flash.h"
-#define LOADER_OFFSET 0
-#define FPGA_OFFSET (15 * FLASH_PAGE_SIZE)
-#define OFFSET FPGA_OFFSET
+#define OFFSET 0
-int
+void
main(void)
{
int len, i, j, off, sec;
char *addr = (char *)SDRAM_BASE + (1 << 20); /* download at + 1MB */
char *addr2 = (char *)SDRAM_BASE + (2 << 20); /* readback to + 2MB */
- char *addr3 = (char *)SDRAM_BASE + (3 << 20); /* extra copy at + 3MB */
SPI_InitFlash();
printf("Waiting for data\n");
while ((len = xmodem_rx(addr)) == -1)
continue;
- // Need extra copy at addr3
- memcpy(addr3, addr, (len + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE * FLASH_PAGE_SIZE);
- printf("Writing %u bytes to flash at %u\n", len, OFFSET);
+ printf("Writing %u bytes at %u\n", len, OFFSET);
for (i = 0; i < len; i+= FLASH_PAGE_SIZE) {
+ off = i + OFFSET;
for (j = 0; j < 10; j++) {
- off = i + OFFSET;
SPI_WriteFlash(off, addr + i, FLASH_PAGE_SIZE);
SPI_ReadFlash(off, addr2 + i, FLASH_PAGE_SIZE);
- if (p_memcmp(addr3 + i, addr2 + i, FLASH_PAGE_SIZE) == 0)
+ if (p_memcmp(addr + i, addr2 + i, FLASH_PAGE_SIZE) == 0)
break;
}
if (j >= 10)
@@ -64,5 +59,4 @@
continue;
printf("Done\n");
reset();
- return (1);
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/at91/boot2/boot2.c
--- a/head/sys/boot/arm/at91/boot2/boot2.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/at91/boot2/boot2.c Wed Jul 25 16:45:04 2012 +0300
@@ -16,7 +16,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/arm/at91/boot2/boot2.c 226506 2011-10-18 09:46:52Z des $");
+__FBSDID("$FreeBSD: head/sys/boot/arm/at91/boot2/boot2.c 235988 2012-05-25 09:36:39Z gleb $");
#include <sys/param.h>
#include <sys/disklabel.h>
@@ -86,15 +86,15 @@
RBX_VERBOSE
};
+unsigned board_id; /* board type to pass to kernel, if set by board_* code */
unsigned dsk_start;
static char cmd[512];
static char kname[1024];
static uint32_t opts;
-static int dsk_meta;
+static uint8_t dsk_meta;
static void load(void);
static int parse(void);
-static int xfsread(ino_t, void *, size_t);
static int dskread(void *, unsigned, unsigned);
#ifdef FIXUP_BOOT_DRV
static void fixup_boot_drv(caddr_t, int, int, int);
@@ -110,7 +110,7 @@
#endif
static inline int
-xfsread(ino_t inode, void *buf, size_t nbyte)
+xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
{
if ((size_t)fsread(inode, buf, nbyte) != nbyte)
return -1;
@@ -153,7 +153,7 @@
main(void)
{
int autoboot, c = 0;
- ino_t ino;
+ ufs_ino_t ino;
dmadat = (void *)(0x20000000 + (16 << 20));
board_init();
@@ -198,7 +198,7 @@
Elf32_Ehdr eh;
static Elf32_Phdr ep[2];
caddr_t p;
- ino_t ino;
+ ufs_ino_t ino;
uint32_t addr;
int i, j;
#ifdef FIXUP_BOOT_DRV
@@ -241,7 +241,7 @@
#ifdef FIXUP_BOOT_DRV
fixup_boot_drv(staddr, klen, bootslice, bootpart);
#endif
- ((void(*)(int))addr)(opts & RBX_MASK);
+ ((void(*)(int, int, int, int))addr)(opts & RBX_MASK, board_id, 0, 0);
}
static int
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/at91/bootspi/ee.c
--- a/head/sys/boot/arm/at91/bootspi/ee.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/at91/bootspi/ee.c Wed Jul 25 16:45:04 2012 +0300
@@ -18,7 +18,7 @@
* only.
* END_BLOCK
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/arm/at91/bootspi/ee.c 238463 2012-07-15 05:35:14Z imp $
*****************************************************************************/
#include "at91rm9200_lowlevel.h"
@@ -59,11 +59,11 @@
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
- pPio->PIO_ASR = AT91C_PA25_TWD | AT91C_PA26_TWCK;
- pPio->PIO_PDR = AT91C_PA25_TWD | AT91C_PA26_TWCK;
+ pPio->PIO_ASR = AT91C_PIO_PA25 | AT91C_PIO_PA26;
+ pPio->PIO_PDR = AT91C_PIO_PA25 | AT91C_PIO_PA26;
- pPio->PIO_MDDR = ~AT91C_PA25_TWD;
- pPio->PIO_MDER = AT91C_PA25_TWD;
+ pPio->PIO_MDDR = ~AT91C_PIO_PA25;
+ pPio->PIO_MDER = AT91C_PIO_PA25;
pPMC->PMC_PCER = 1u << AT91C_ID_TWI;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/at91/libat91/Makefile
--- a/head/sys/boot/arm/at91/libat91/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/at91/libat91/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,10 +1,12 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/boot/arm/at91/libat91/Makefile 238187 2012-07-07 04:51:59Z imp $
.include "${.CURDIR}/../Makefile.inc"
+SOC?=at91rm9200
+
LIB= at91
INTERNALLIB=
-SRCS=at91rm9200_lowlevel.c delay.c eeprom.c emac.c emac_init.c getc.c \
+SRCS=${SOC}_lowlevel.c delay.c eeprom.c emac.c emac_init.c getc.c \
putchar.c printf.c reset.c spi_flash.c xmodem.c \
sd-card.c strcvt.c strlen.c strcmp.c memcpy.c strcpy.c \
memset.c memcmp.c
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/at91/libat91/at91rm9200.h
--- a/head/sys/boot/arm/at91/libat91/at91rm9200.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/at91/libat91/at91rm9200.h Wed Jul 25 16:45:04 2012 +0300
@@ -7,7 +7,7 @@
// fitness for any particular purpose, or against the infringements of
// intellectual property rights of others.
// ----------------------------------------------------------------------------
-// $FreeBSD$
+// $FreeBSD: head/sys/boot/arm/at91/libat91/at91rm9200.h 238463 2012-07-15 05:35:14Z imp $
//
// File Name : AT91RM9200.h
// Object : AT91RM9200 definitions
@@ -41,6 +41,8 @@
#ifndef AT91RM9200_H
#define AT91RM9200_H
+#define ATMEL_ENV
+
typedef volatile unsigned int AT91_REG;// Hardware register definition
// *****************************************************************************
@@ -2309,7 +2311,7 @@
// ========== Register definition for BFC peripheral ==========
#define AT91C_BFC_MR ((AT91_REG *) 0xFFFFFFC0) // (BFC) BFC Mode Register
-#include <at91/at91_pio_rm9200.h>
+#include <at91/at91_pioreg.h>
// *****************************************************************************
// PERIPHERAL ID DEFINITIONS FOR AT91RM9200
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/at91/libat91/at91rm9200_lowlevel.c
--- a/head/sys/boot/arm/at91/libat91/at91rm9200_lowlevel.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/at91/libat91/at91rm9200_lowlevel.c Wed Jul 25 16:45:04 2012 +0300
@@ -24,7 +24,7 @@
* This software is derived from software provide by Kwikbyte who specifically
* disclaimed copyright on the code.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/arm/at91/libat91/at91rm9200_lowlevel.c 238463 2012-07-15 05:35:14Z imp $
*/
#include "at91rm9200.h"
@@ -188,8 +188,8 @@
AT91C_BASE_PIOC->PIO_PDR = 0xffff0000;
#endif
// Configure DBGU -use local routine optimized for space
- AT91C_BASE_PIOA->PIO_ASR = AT91C_PA31_DTXD | AT91C_PA30_DRXD;
- AT91C_BASE_PIOA->PIO_PDR = AT91C_PA31_DTXD | AT91C_PA30_DRXD;
+ AT91C_BASE_PIOA->PIO_ASR = AT91C_PIO_PA31 | AT91C_PIO_PA30;
+ AT91C_BASE_PIOA->PIO_PDR = AT91C_PIO_PA31 | AT91C_PIO_PA30;
pUSART->US_IDR = (unsigned int) -1;
pUSART->US_CR =
AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/at91/libat91/eeprom.c
--- a/head/sys/boot/arm/at91/libat91/eeprom.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/at91/libat91/eeprom.c Wed Jul 25 16:45:04 2012 +0300
@@ -18,7 +18,7 @@
* only.
* END_BLOCK
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/arm/at91/libat91/eeprom.c 238463 2012-07-15 05:35:14Z imp $
*****************************************************************************/
#include "at91rm9200_lowlevel.h"
@@ -58,11 +58,11 @@
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
- pPio->PIO_ASR = AT91C_PA25_TWD | AT91C_PA26_TWCK;
- pPio->PIO_PDR = AT91C_PA25_TWD | AT91C_PA26_TWCK;
+ pPio->PIO_ASR = AT91C_PIO_PA25 | AT91C_PIO_PA26;
+ pPio->PIO_PDR = AT91C_PIO_PA25 | AT91C_PIO_PA26;
- pPio->PIO_MDDR = ~AT91C_PA25_TWD;
- pPio->PIO_MDER = AT91C_PA25_TWD;
+ pPio->PIO_MDDR = ~AT91C_PIO_PA25;
+ pPio->PIO_MDER = AT91C_PIO_PA25;
pPMC->PMC_PCER = 1u << AT91C_ID_TWI;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/at91/libat91/emac_init.c
--- a/head/sys/boot/arm/at91/libat91/emac_init.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/at91/libat91/emac_init.c Wed Jul 25 16:45:04 2012 +0300
@@ -24,7 +24,7 @@
* This software is derived from software provide by Kwikbyte who specifically
* disclaimed copyright on the code.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/arm/at91/libat91/emac_init.c 238463 2012-07-15 05:35:14Z imp $
*/
/******************************************************************************
@@ -85,24 +85,24 @@
AT91C_BASE_PMC->PMC_PCER = 1u << AT91C_ID_EMAC;
AT91C_BASE_PIOA->PIO_ASR =
- AT91C_PA14_ERXER | AT91C_PA12_ERX0 | AT91C_PA13_ERX1 |
- AT91C_PA8_ETXEN | AT91C_PA16_EMDIO | AT91C_PA9_ETX0 |
- AT91C_PA10_ETX1 | AT91C_PA11_ECRS_ECRSDV | AT91C_PA15_EMDC |
- AT91C_PA7_ETXCK_EREFCK;
+ AT91C_PIO_PA14 | AT91C_PIO_PA12 | AT91C_PIO_PA13 |
+ AT91C_PIO_PA8 | AT91C_PIO_PA16 | AT91C_PIO_PA9 |
+ AT91C_PIO_PA10 | AT91C_PIO_PA11 | AT91C_PIO_PA15 |
+ AT91C_PIO_PA7;
AT91C_BASE_PIOA->PIO_PDR =
- AT91C_PA14_ERXER | AT91C_PA12_ERX0 | AT91C_PA13_ERX1 |
- AT91C_PA8_ETXEN | AT91C_PA16_EMDIO | AT91C_PA9_ETX0 |
- AT91C_PA10_ETX1 | AT91C_PA11_ECRS_ECRSDV | AT91C_PA15_EMDC |
- AT91C_PA7_ETXCK_EREFCK;
+ AT91C_PIO_PA14 | AT91C_PIO_PA12 | AT91C_PIO_PA13 |
+ AT91C_PIO_PA8 | AT91C_PIO_PA16 | AT91C_PIO_PA9 |
+ AT91C_PIO_PA10 | AT91C_PIO_PA11 | AT91C_PIO_PA15 |
+ AT91C_PIO_PA7;
#if defined(BOOT_KB920X) | defined(BOOT_BWCT) /* Really !RMII */
AT91C_BASE_PIOB->PIO_BSR =
- AT91C_PB12_ETX2 | AT91C_PB13_ETX3 | AT91C_PB14_ETXER |
- AT91C_PB15_ERX2 | AT91C_PB16_ERX3 | AT91C_PB17_ERXDV |
- AT91C_PB18_ECOL | AT91C_PB19_ERXCK;
+ AT91C_PIO_PB12 | AT91C_PIO_PB13 | AT91C_PIO_PB14 |
+ AT91C_PIO_PB15 | AT91C_PIO_PB16 | AT91C_PIO_PB17 |
+ AT91C_PIO_PB18 | AT91C_PIO_PB19;
AT91C_BASE_PIOB->PIO_PDR =
- AT91C_PB12_ETX2 | AT91C_PB13_ETX3 | AT91C_PB14_ETXER |
- AT91C_PB15_ERX2 | AT91C_PB16_ERX3 | AT91C_PB17_ERXDV |
- AT91C_PB18_ECOL | AT91C_PB19_ERXCK;
+ AT91C_PIO_PB12 | AT91C_PIO_PB13 | AT91C_PIO_PB14 |
+ AT91C_PIO_PB15 | AT91C_PIO_PB16 | AT91C_PIO_PB17 |
+ AT91C_PIO_PB18 | AT91C_PIO_PB19;
#endif
pEmac->EMAC_CTL = 0;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/at91/libat91/lib_AT91RM9200.h
--- a/head/sys/boot/arm/at91/libat91/lib_AT91RM9200.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/at91/libat91/lib_AT91RM9200.h Wed Jul 25 16:45:04 2012 +0300
@@ -24,7 +24,7 @@
* This software is derived from software provide by Kwikbyte who specifically
* disclaimed copyright on the code.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/arm/at91/libat91/lib_AT91RM9200.h 238463 2012-07-15 05:35:14Z imp $
*/
#ifndef __LIBAT91RM9200_H
@@ -134,17 +134,17 @@
// Configure PIO controllers to periph mode
AT91F_PIO_CfgPeriph(
AT91C_BASE_PIOA, // PIO controller base address
- ((unsigned int) AT91C_PA28_MCCDA ) |
- ((unsigned int) AT91C_PA29_MCDA0 ) |
- ((unsigned int) AT91C_PA27_MCCK ), // Peripheral A
+ ((unsigned int) AT91C_PIO_PA28 ) |
+ ((unsigned int) AT91C_PIO_PA29 ) |
+ ((unsigned int) AT91C_PIO_PA27 ), // Peripheral A
0); // Peripheral B
// Configure PIO controllers to periph mode
AT91F_PIO_CfgPeriph(
AT91C_BASE_PIOB, // PIO controller base address
0, // Peripheral A
- ((unsigned int) AT91C_PB5_MCDA3 ) |
- ((unsigned int) AT91C_PB3_MCDA1 ) |
- ((unsigned int) AT91C_PB4_MCDA2 )); // Peripheral B
+ ((unsigned int) AT91C_PIO_PB5 ) |
+ ((unsigned int) AT91C_PIO_PB3 ) |
+ ((unsigned int) AT91C_PIO_PB4 )); // Peripheral B
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/at91/libat91/spi_flash.c
--- a/head/sys/boot/arm/at91/libat91/spi_flash.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/at91/libat91/spi_flash.c Wed Jul 25 16:45:04 2012 +0300
@@ -19,7 +19,7 @@
* only.
* END_BLOCK
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/arm/at91/libat91/spi_flash.c 238463 2012-07-15 05:35:14Z imp $
*****************************************************************************/
#include "at91rm9200.h"
@@ -223,10 +223,10 @@
// enable CS0, CLK, MOSI, MISO
pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
- pPio->PIO_ASR = AT91C_PA3_NPCS0 | AT91C_PA1_MOSI | AT91C_PA0_MISO |
- AT91C_PA2_SPCK;
- pPio->PIO_PDR = AT91C_PA3_NPCS0 | AT91C_PA1_MOSI | AT91C_PA0_MISO |
- AT91C_PA2_SPCK;
+ pPio->PIO_ASR = AT91C_PIO_PA3 | AT91C_PIO_PA1 | AT91C_PIO_PA0 |
+ AT91C_PIO_PA2;
+ pPio->PIO_PDR = AT91C_PIO_PA3 | AT91C_PIO_PA1 | AT91C_PIO_PA0 |
+ AT91C_PIO_PA2;
// enable clocks to SPI
AT91C_BASE_PMC->PMC_PCER = 1u << AT91C_ID_SPI;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/at91/linker.cfg
--- a/head/sys/boot/arm/at91/linker.cfg Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/at91/linker.cfg Wed Jul 25 16:45:04 2012 +0300
@@ -18,7 +18,7 @@
* only.
* END_BLOCK
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/arm/at91/linker.cfg 238186 2012-07-07 04:49:53Z imp $
******************************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",
"elf32-littlearm")
@@ -31,258 +31,26 @@
.text :
{
*(.text)
- *(.text.*)
- *(.stub)
- /* .gnu.warning sections are handled specially by elf32.em. */
- *(.gnu.warning)
- *(.gnu.linkonce.t.*)
- *(.glue_7t) *(.glue_7)
}
- .interp : { *(.interp) }
- .hash : { *(.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
- .rel.init : { *(.rel.init) }
- .rela.init : { *(.rela.init) }
- .rel.text :
- {
- *(.rel.text)
- *(.rel.text.*)
- *(.rel.gnu.linkonce.t.*)
- }
- .rela.text :
- {
- *(.rela.text)
- *(.rela.text.*)
- *(.rela.gnu.linkonce.t.*)
- }
- .rel.fini : { *(.rel.fini) }
- .rela.fini : { *(.rela.fini) }
- .rel.rodata :
- {
- *(.rel.rodata)
- *(.rel.rodata.*)
- *(.rel.gnu.linkonce.r.*)
- }
- .rela.rodata :
- {
- *(.rela.rodata)
- *(.rela.rodata.*)
- *(.rela.gnu.linkonce.r.*)
- }
- .rel.data :
- {
- *(.rel.data)
- *(.rel.data.*)
- *(.rel.gnu.linkonce.d.*)
- }
- .rela.data :
- {
- *(.rela.data)
- *(.rela.data.*)
- *(.rela.gnu.linkonce.d.*)
- }
- .rel.ctors : { *(.rel.ctors) }
- .rela.ctors : { *(.rela.ctors) }
- .rel.dtors : { *(.rel.dtors) }
- .rela.dtors : { *(.rela.dtors) }
- .rel.got : { *(.rel.got) }
- .rela.got : { *(.rela.got) }
- .rel.sdata :
- {
- *(.rel.sdata)
- *(.rel.sdata.*)
- *(.rel.gnu.linkonce.s.*)
- }
- .rela.sdata :
- {
- *(.rela.sdata)
- *(.rela.sdata.*)
- *(.rela.gnu.linkonce.s.*)
- }
- .rel.sbss :
- {
- *(.rel.sbss)
- *(.rel.sbss.*)
- *(.rel.gnu.linkonce.sb.*)
- }
- .rela.sbss :
- {
- *(.rela.sbss)
- *(.rela.sbss.*)
- *(.rel.gnu.linkonce.sb.*)
- }
- .rel.sdata2 :
- {
- *(.rel.sdata2)
- *(.rel.sdata2.*)
- *(.rel.gnu.linkonce.s2.*)
- }
- .rela.sdata2 :
- {
- *(.rela.sdata2)
- *(.rela.sdata2.*)
- *(.rela.gnu.linkonce.s2.*)
- }
- .rel.sbss2 :
- {
- *(.rel.sbss2)
- *(.rel.sbss2.*)
- *(.rel.gnu.linkonce.sb2.*)
- }
- .rela.sbss2 :
- {
- *(.rela.sbss2)
- *(.rela.sbss2.*)
- *(.rela.gnu.linkonce.sb2.*)
- }
- .rel.bss :
- {
- *(.rel.bss)
- *(.rel.bss.*)
- *(.rel.gnu.linkonce.b.*)
- }
- .rela.bss :
- {
- *(.rela.bss)
- *(.rela.bss.*)
- *(.rela.gnu.linkonce.b.*)
- }
- .rel.plt : { *(.rel.plt) }
- .rela.plt : { *(.rela.plt) }
- .init :
- {
- KEEP (*(.init))
- } =0
- .plt : { *(.plt) }
- .fini :
- {
- KEEP (*(.fini))
- } =0
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
- .rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) }
- .rodata1 : { *(.rodata1) }
- .sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) }
- .sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) }
.data :
{
__data_start = . ;
*(.data)
- *(.data.*)
- *(.gnu.linkonce.d.*)
- SORT(CONSTRUCTORS)
- }
- .data1 : { *(.data1) }
- . = 0x21200000;
- .eh_frame : { KEEP (*(.eh_frame)) }
- .gcc_except_table : { *(.gcc_except_table) }
- .ctors :
- {
- /* gcc uses crtbegin.o to find the start of
- the constructors, so we make sure it is
- first. Because this is a wildcard, it
- doesn't matter if the user does not
- actually link against crtbegin.o; the
- linker won't look for a file to match a
- wildcard. The wildcard also means that it
- doesn't matter which directory crtbegin.o
- is in. */
- KEEP (*crtbegin.o(.ctors))
- /* We don't want to include the .ctor section from
- from the crtend.o file until after the sorted ctors.
- The .ctor section from the crtend file contains the
- end of ctors marker and it must be last */
- KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
- KEEP (*(SORT(.ctors.*)))
- KEEP (*(.ctors))
- }
- .dtors :
- {
- KEEP (*crtbegin.o(.dtors))
- KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
- KEEP (*(SORT(.dtors.*)))
- KEEP (*(.dtors))
- }
- .got : { *(.got.plt) *(.got) }
- .dynamic : { *(.dynamic) }
- /* We want the small data sections together, so single-instruction offsets
- can access them all, and initialized data all before uninitialized, so
- we can shorten the on-disk segment size. */
- .sdata :
- {
- *(.sdata)
- *(.sdata.*)
- *(.gnu.linkonce.s.*)
}
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
__bss_start__ = .;
- .sbss :
- {
- PROVIDE (__sbss_start = .);
- PROVIDE (___sbss_start = .);
- *(.dynsbss)
- *(.sbss)
- *(.sbss.*)
- *(.gnu.linkonce.sb.*)
- *(.scommon)
- PROVIDE (__sbss_end = .);
- PROVIDE (___sbss_end = .);
- }
.bss :
{
- *(.dynbss)
*(.bss)
- *(.bss.*)
- *(.gnu.linkonce.b.*)
- *(COMMON)
- /* Align here to ensure that the .bss section occupies space up to
- _end. Align after .bss to ensure correct alignment even if the
- .bss section disappears because there are no input sections. */
. = ALIGN(32 / 8);
}
. = ALIGN(32 / 8);
_end = .;
_bss_end__ = . ; __bss_end__ = . ; __end__ = . ;
PROVIDE (end = .);
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
- /* DWARF debug sections.
- Symbols in the DWARF debugging sections are relative to the beginning
- of the section so we begin them at 0. */
- /* DWARF 1 */
- .debug 0 : { *(.debug) }
- .line 0 : { *(.line) }
- /* GNU DWARF 1 extensions */
- .debug_srcinfo 0 : { *(.debug_srcinfo) }
- .debug_sfnames 0 : { *(.debug_sfnames) }
- /* DWARF 1.1 and DWARF 2 */
- .debug_aranges 0 : { *(.debug_aranges) }
- .debug_pubnames 0 : { *(.debug_pubnames) }
- /* DWARF 2 */
- .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
- .debug_abbrev 0 : { *(.debug_abbrev) }
- .debug_line 0 : { *(.debug_line) }
- .debug_frame 0 : { *(.debug_frame) }
- .debug_str 0 : { *(.debug_str) }
- .debug_loc 0 : { *(.debug_loc) }
- .debug_macinfo 0 : { *(.debug_macinfo) }
- /* SGI/MIPS DWARF 2 extensions */
- .debug_weaknames 0 : { *(.debug_weaknames) }
- .debug_funcnames 0 : { *(.debug_funcnames) }
- .debug_typenames 0 : { *(.debug_typenames) }
- .debug_varnames 0 : { *(.debug_varnames) }
- /* These must appear regardless of . */
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/ixp425/boot2/boot2.c
--- a/head/sys/boot/arm/ixp425/boot2/boot2.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/ixp425/boot2/boot2.c Wed Jul 25 16:45:04 2012 +0300
@@ -15,7 +15,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/arm/ixp425/boot2/boot2.c 226506 2011-10-18 09:46:52Z des $");
+__FBSDID("$FreeBSD: head/sys/boot/arm/ixp425/boot2/boot2.c 235988 2012-05-25 09:36:39Z gleb $");
#include <sys/param.h>
#include <sys/disklabel.h>
@@ -98,7 +98,6 @@
static void load(void);
static int parse(void);
-static int xfsread(ino_t, void *, size_t);
static int dskread(void *, unsigned, unsigned);
static int drvread(void *, unsigned, unsigned);
#ifdef FIXUP_BOOT_DRV
@@ -114,7 +113,7 @@
#endif
static inline int
-xfsread(ino_t inode, void *buf, size_t nbyte)
+xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
{
if ((size_t)fsread(inode, buf, nbyte) != nbyte)
return -1;
@@ -158,7 +157,7 @@
{
const char *bt;
int autoboot, c = 0;
- ino_t ino;
+ ufs_ino_t ino;
dmadat = (void *)(0x1c0000);
p_memset((char *)dmadat, 0, 32 * 1024);
@@ -207,7 +206,7 @@
Elf32_Ehdr eh;
static Elf32_Phdr ep[2];
caddr_t p;
- ino_t ino;
+ ufs_ino_t ino;
uint32_t addr;
int i, j;
#ifdef FIXUP_BOOT_DRV
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/uboot/Makefile
--- a/head/sys/boot/arm/uboot/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/uboot/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/boot/arm/uboot/Makefile 236159 2012-05-27 16:27:04Z kientzle $
.include <bsd.own.mk>
@@ -7,6 +7,9 @@
BINDIR?= /boot
INSTALLFLAGS= -b
WARNS?= 1
+# Address at which ubldr will be loaded.
+# This varies for different boards and SOCs.
+UBLDR_LOADADDR?= 0x1000000
# Architecture-specific loader code
SRCS= start.S conf.c vers.c
@@ -15,6 +18,11 @@
LOADER_UFS_SUPPORT?= yes
LOADER_CD9660_SUPPORT?= no
LOADER_EXT2FS_SUPPORT?= no
+.if ${MK_NAND} != "no"
+LOADER_NANDFS_SUPPORT?= yes
+.else
+LOADER_NANDFS_SUPPORT?= no
+.endif
LOADER_NET_SUPPORT?= yes
LOADER_NFS_SUPPORT?= yes
LOADER_TFTP_SUPPORT?= no
@@ -38,6 +46,9 @@
.if ${LOADER_EXT2FS_SUPPORT} == "yes"
CFLAGS+= -DLOADER_EXT2FS_SUPPORT
.endif
+.if ${LOADER_NANDFS_SUPPORT} == "yes"
+CFLAGS+= -DLOADER_NANDFS_SUPPORT
+.endif
.if ${LOADER_GZIP_SUPPORT} == "yes"
CFLAGS+= -DLOADER_GZIP_SUPPORT
.endif
@@ -77,7 +88,9 @@
CFLAGS+= -ffreestanding
-LDFLAGS= -nostdlib -static -T ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
+LDFLAGS= -nostdlib -static
+LDFLAGS+= -T ldscript.generated
+LDFLAGS+= -T ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
# Pull in common loader code
.PATH: ${.CURDIR}/../../uboot/common
@@ -102,6 +115,18 @@
cat ${.ALLSRC} | \
awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET}
+${PROG}: ldscript.generated ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
+
+ldscript.generated::
+ rm -f ldscript.generated.tmp
+ echo "UBLDR_LOADADDR = ${UBLDR_LOADADDR};" >ldscript.generated.tmp
+ if diff ldscript.generated ldscript.generated.tmp > /dev/null; then \
+ true; \
+ else \
+ rm -f ldscript.generated; \
+ mv ldscript.generated.tmp ldscript.generated; \
+ fi
+
.PATH: ${.CURDIR}/../../forth
FILES= loader.help
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/uboot/conf.c
--- a/head/sys/boot/arm/uboot/conf.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/uboot/conf.c Wed Jul 25 16:45:04 2012 +0300
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/arm/uboot/conf.c 235537 2012-05-17 10:11:18Z gber $");
#include <stand.h>
#include "bootstrap.h"
@@ -56,6 +56,9 @@
#if defined(LOADER_EXT2FS_SUPPORT)
&ext2fs_fsops,
#endif
+#if defined(LOADER_NANDFS_SUPPORT)
+ &nandfs_fsops,
+#endif
#if defined(LOADER_NFS_SUPPORT)
&nfs_fsops,
#endif
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/uboot/ldscript.arm
--- a/head/sys/boot/arm/uboot/ldscript.arm Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/uboot/ldscript.arm Wed Jul 25 16:45:04 2012 +0300
@@ -1,11 +1,11 @@
-/* $FreeBSD$ */
+/* $FreeBSD: head/sys/boot/arm/uboot/ldscript.arm 236159 2012-05-27 16:27:04Z kientzle $ */
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
- . = 0x1000000 + SIZEOF_HEADERS;
+ . = UBLDR_LOADADDR + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/uboot/start.S
--- a/head/sys/boot/arm/uboot/start.S Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/uboot/start.S Wed Jul 25 16:45:04 2012 +0300
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/arm/uboot/start.S 234908 2012-05-02 05:49:58Z kientzle $
*/
#include <machine/asm.h>
@@ -49,27 +49,20 @@
* syscall()
*/
ENTRY(syscall)
- /* Save caller's lr */
+ /* Save caller's lr and r8 */
ldr ip, =saved_regs
str lr, [ip, #4]
- /* Save loader's r8 */
- ldr ip, =saved_regs
str r8, [ip, #8]
-
/* Restore U-Boot's r8 */
- ldr ip, =saved_regs
ldr r8, [ip, #0]
/* Call into U-Boot */
ldr lr, =return_from_syscall
ldr ip, =syscall_ptr
ldr pc, [ip]
-
return_from_syscall:
- /* Restore loader's r8 */
+ /* Restore loader's r8 and lr */
ldr ip, =saved_regs
ldr r8, [ip, #8]
- /* Restore caller's lr */
- ldr ip, =saved_regs
ldr lr, [ip, #4]
/* Return to caller */
mov pc, lr
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/arm/uboot/version
--- a/head/sys/boot/arm/uboot/version Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/arm/uboot/version Wed Jul 25 16:45:04 2012 +0300
@@ -1,8 +1,9 @@
-$FreeBSD$
+$FreeBSD: head/sys/boot/arm/uboot/version 235537 2012-05-17 10:11:18Z gber $
NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this
file is important. Make sure the current version number is on line 6.
+1.2: Extended with NAND FS support.
1.1: Flattened Device Tree blob support.
1.0: Added storage support. Booting from HDD, USB, etc. is now possible.
0.5: Initial U-Boot/arm version (netbooting only).
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/common/boot.c
--- a/head/sys/boot/common/boot.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/common/boot.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/common/boot.c 235330 2012-05-12 09:07:41Z avg $");
/*
* Loading modules, booting the system
@@ -311,12 +311,12 @@
if (getenv("vfs.root.mountfrom") != NULL)
return(0);
+ error = 1;
sprintf(lbuf, "%s/etc/fstab", rootdev);
if ((fd = open(lbuf, O_RDONLY)) < 0)
- return(1);
+ goto notfound;
/* loop reading lines from /etc/fstab What was that about sscanf again? */
- error = 1;
while (fgetstr(lbuf, sizeof(lbuf), fd) >= 0) {
if ((lbuf[0] == 0) || (lbuf[0] == '#'))
continue;
@@ -377,6 +377,20 @@
break;
}
close(fd);
+
+notfound:
+ if (error) {
+ const char *currdev;
+
+ currdev = getenv("currdev");
+ if (currdev != NULL && strncmp("zfs:", currdev, 4) == 0) {
+ cp = strdup(currdev);
+ cp[strlen(cp) - 1] = '\0';
+ setenv("vfs.root.mountfrom", cp, 0);
+ error = 0;
+ }
+ }
+
return(error);
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/common/bootstrap.h
--- a/head/sys/boot/common/bootstrap.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/common/bootstrap.h Wed Jul 25 16:45:04 2012 +0300
@@ -23,9 +23,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/boot/common/bootstrap.h 220311 2011-04-03 22:31:51Z marcel $
+ * $FreeBSD: head/sys/boot/common/bootstrap.h 235329 2012-05-12 09:03:30Z avg $
*/
+#ifndef _BOOTSTRAP_H_
+#define _BOOTSTRAP_H_
+
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/linker_set.h>
@@ -314,6 +317,9 @@
#else
void (*arch_loadseg)(void *eh, void *ph, uint64_t delta);
#endif
+
+ /* Probe ZFS pool(s), if needed. */
+ void (*arch_zfs_probe)(void);
};
extern struct arch_switch archsw;
@@ -323,3 +329,11 @@
void dev_cleanup(void);
time_t time(time_t *tloc);
+
+#ifndef CTASSERT /* Allow lint to override */
+#define CTASSERT(x) _CTASSERT(x, __LINE__)
+#define _CTASSERT(x, y) __CTASSERT(x, y)
+#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1]
+#endif
+
+#endif /* !_BOOTSTRAP_H_ */
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/common/load_elf.c
--- a/head/sys/boot/common/load_elf.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/common/load_elf.c Wed Jul 25 16:45:04 2012 +0300
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/common/load_elf.c 223695 2011-06-30 16:08:56Z dfr $");
+__FBSDID("$FreeBSD: head/sys/boot/common/load_elf.c 237338 2012-06-20 21:06:51Z jhb $");
#include <sys/param.h>
#include <sys/exec.h>
@@ -612,7 +612,7 @@
Elf_Addr v, p, p_stop;
if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0)
- return ENOENT;
+ return 0;
p = sym.st_value + ef->off;
if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0)
return ENOENT;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/common/load_elf_obj.c
--- a/head/sys/boot/common/load_elf_obj.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/common/load_elf_obj.c Wed Jul 25 16:45:04 2012 +0300
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/common/load_elf_obj.c 223295 2011-06-19 13:35:41Z kan $");
+__FBSDID("$FreeBSD: head/sys/boot/common/load_elf_obj.c 237338 2012-06-20 21:06:51Z jhb $");
#include <sys/param.h>
#include <sys/exec.h>
@@ -369,7 +369,7 @@
if (__elfN(obj_lookup_set)(fp, ef, "modmetadata_set", &p, &p_stop,
&modcnt) != 0)
- return ENOENT;
+ return 0;
modcnt = 0;
while (p < p_stop) {
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/common/loader.8
--- a/head/sys/boot/common/loader.8 Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/common/loader.8 Wed Jul 25 16:45:04 2012 +0300
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/sys/boot/common/loader.8 233648 2012-03-29 05:02:12Z eadler $
+.\" $FreeBSD: head/sys/boot/common/loader.8 235873 2012-05-24 02:24:03Z wblock $
.\"
.Dd January 7, 2012
.Dt LOADER 8
@@ -423,7 +423,7 @@
Defines the base i/o port used to access console UART
(i386 and amd64 only).
If the variable is not set, its assumed value is 0x3F8, which
-corresponds to PC port COM1, unless overriden by
+corresponds to PC port COM1, unless overridden by
.Va BOOT_COMCONSOLE_PORT
variable during the compilation of
.Nm .
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/common/ufsread.c
--- a/head/sys/boot/common/ufsread.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/common/ufsread.c Wed Jul 25 16:45:04 2012 +0300
@@ -44,7 +44,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/common/ufsread.c 233105 2012-03-18 02:19:30Z marius $");
+__FBSDID("$FreeBSD: head/sys/boot/common/ufsread.c 235988 2012-05-25 09:36:39Z gleb $");
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
@@ -58,6 +58,8 @@
#define cgbase(fs, c) ((ufs2_daddr_t)((fs)->fs_fpg * (c)))
#endif
+typedef uint32_t ufs_ino_t;
+
/*
* We use 4k `virtual' blocks for filesystem data, whatever the actual
* filesystem block size. FFS blocks are always a multiple of 4k.
@@ -85,14 +87,14 @@
};
static struct dmadat *dmadat;
-static ino_t lookup(const char *);
-static ssize_t fsread(ino_t, void *, size_t);
+static ufs_ino_t lookup(const char *);
+static ssize_t fsread(ufs_ino_t, void *, size_t);
static uint8_t ls, dsk_meta;
static uint32_t fs_off;
static __inline uint8_t
-fsfind(const char *name, ino_t * ino)
+fsfind(const char *name, ufs_ino_t * ino)
{
static char buf[DEV_BSIZE];
struct direct *d;
@@ -116,12 +118,12 @@
return 0;
}
-static ino_t
+static ufs_ino_t
lookup(const char *path)
{
static char name[MAXNAMLEN + 1];
const char *s;
- ino_t ino;
+ ufs_ino_t ino;
ssize_t n;
uint8_t dt;
@@ -163,7 +165,7 @@
#endif
static ssize_t
-fsread(ino_t inode, void *buf, size_t nbyte)
+fsread(ufs_ino_t inode, void *buf, size_t nbyte)
{
#ifndef UFS2_ONLY
static struct ufs1_dinode dp1;
@@ -173,7 +175,7 @@
static struct ufs2_dinode dp2;
#endif
static struct fs fs;
- static ino_t inomap;
+ static ufs_ino_t inomap;
char *blkbuf;
void *indbuf;
char *s;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/fdt/dts/bindings-localbus.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/bindings-localbus.txt Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,83 @@
+$FreeBSD: head/sys/boot/fdt/dts/bindings-localbus.txt 235609 2012-05-18 14:41:14Z gber $
+
+Marvell Device bus (localbus) configuration.
+============================================
+
+1. Properties for localbus nodes
+
+1.1 ranges
+
+Property: ranges
+
+Value type: <prop-encoded-array> encoded as arbitrary number of localbus
+ nodes specifiers.
+
+Description: ranges property defines values used for mapping devices
+ connected to localbus, in Marvell devices it is used also for
+ setting decoding windows.
+
+ a) child node address-cells:
+ - first cell: number of bank (chip select)
+ - second cell: (Marvell devices) Target ID for decoding
+ windows setup
+
+ b) parent node address cells:
+ - address offset: used with parent's node base address to
+ specify base address of mapped device
+
+ c) child node size-cells:
+ - size: defines amount of memory that should be reserved for
+ device
+
+1.2 bank-count
+
+Property: bank-count
+
+Value type: <u32>
+
+Description: The bank_count property defines maximum number of banks on
+ localbus node. Bank is most often interpreted as device chip
+ select, but may also describe another device (e.g. SPI flash).
+
+1.3 Example
+
+ localbus at 0 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "mrvl,lbc";
+ bank-count = <5>;
+
+ /* This reflects CPU decode windows setup. */
+ ranges = <0x0 0x2f 0xb2200000 0x00100000
+ 0x1 0x3e 0xb2100000 0x00100000
+ 0x2 0x3d 0xb0000000 0x02000000
+ 0x3 0x3b 0xb2000000 0x00100000>;
+ };
+
+2. Properties for localbus consumer nodes:
+
+2.1 reg
+
+Property: reg
+
+Value type: <prop-encoded-array>
+
+Description: A standard property required for localbus child nodes. Defines
+ the device memory region.
+
+ a) first cell: number of bank (chip select)
+
+ b) address offset: used with address offset from parent's ranges
+ for corresponding bank to specify base address of
+ the device
+
+ c) size: defines size of the device memory region
+
+2.2 Example
+
+ nor at 0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x00100000>;
+ };
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/fdt/dts/db78100.dts
--- a/head/sys/boot/fdt/dts/db78100.dts Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/fdt/dts/db78100.dts Wed Jul 25 16:45:04 2012 +0300
@@ -28,7 +28,7 @@
*
* Marvell DB-78100 Device Tree Source.
*
- * $FreeBSD: head/sys/boot/fdt/dts/db78100.dts 232518 2012-03-04 19:22:52Z raj $
+ * $FreeBSD: head/sys/boot/fdt/dts/db78100.dts 235609 2012-05-18 14:41:14Z gber $
*/
/dts-v1/;
@@ -69,25 +69,23 @@
reg = <0x0 0x20000000>; // 512M at 0x0
};
- localbus at f1000000 {
+ localbus at 0 {
#address-cells = <2>;
#size-cells = <1>;
compatible = "mrvl,lbc";
- win-count = <14>;
+ bank-count = <5>;
/* This reflects CPU decode windows setup. */
- ranges = <0x0 0x0f 0xf9300000 0x00100000
- 0x1 0x1e 0xfa000000 0x00100000
- 0x2 0x1d 0xfa100000 0x02000000
- 0x3 0x1b 0xfc100000 0x00000400>;
+ ranges = <0x0 0x2f 0xf9300000 0x00100000
+ 0x1 0x3e 0xf9400000 0x00100000
+ 0x2 0x3d 0xf9500000 0x02000000
+ 0x3 0x3b 0xfb500000 0x00100000>;
nor at 0,0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "cfi-flash";
reg = <0x0 0x0 0x00100000>;
- bank-width = <2>;
- device-width = <1>;
};
led at 1,0 {
@@ -102,16 +100,13 @@
#size-cells = <1>;
compatible = "cfi-flash";
reg = <0x2 0x0 0x02000000>;
- bank-width = <2>;
- device-width = <1>;
};
nand at 3,0 {
#address-cells = <1>;
#size-cells = <1>;
+ compatible = "mrvl,nfc";
reg = <0x3 0x0 0x00100000>;
- bank-width = <2>;
- device-width = <1>;
};
};
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/fdt/dts/db88f6281.dts
--- a/head/sys/boot/fdt/dts/db88f6281.dts Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/fdt/dts/db88f6281.dts Wed Jul 25 16:45:04 2012 +0300
@@ -28,7 +28,7 @@
*
* Marvell DB-88F6281 Device Tree Source.
*
- * $FreeBSD: head/sys/boot/fdt/dts/db88f6281.dts 227730 2011-11-19 16:30:06Z raj $
+ * $FreeBSD: head/sys/boot/fdt/dts/db88f6281.dts 235779 2012-05-22 09:27:57Z gber $
*/
/dts-v1/;
@@ -72,48 +72,33 @@
reg = <0x0 0x20000000>; // 512M at 0x0
};
- localbus at f1000000 {
+ localbus at 0 {
#address-cells = <2>;
#size-cells = <1>;
compatible = "mrvl,lbc";
+ bank-count = <3>;
/* This reflects CPU decode windows setup. */
- ranges = <0x0 0x0f 0xf9300000 0x00100000
- 0x1 0x1e 0xfa000000 0x00100000
- 0x2 0x1d 0xfa100000 0x02000000
- 0x3 0x1b 0xfc100000 0x00000400>;
+ ranges = <0x0 0x2f 0xf9300000 0x00100000>;
- nor at 0,0 {
+ nand at 0,0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "cfi-flash";
+ compatible = "mrvl,nfc";
reg = <0x0 0x0 0x00100000>;
bank-width = <2>;
device-width = <1>;
- };
- led at 1,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "led";
- reg = <0x1 0x0 0x00100000>;
- };
+ slice at 0 {
+ reg = <0x0 0x200000>;
+ label = "u-boot";
+ read-only;
+ };
- nor at 2,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "cfi-flash";
- reg = <0x2 0x0 0x02000000>;
- bank-width = <2>;
- device-width = <1>;
- };
-
- nand at 3,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- reg = <0x3 0x0 0x00100000>;
- bank-width = <2>;
- device-width = <1>;
+ slice at 200000 {
+ reg = <0x200000 0x7e00000>;
+ label = "root";
+ };
};
};
@@ -305,4 +290,9 @@
0x0 0x00100000>;
};
};
+
+ chosen {
+ stdin = "serial0";
+ stdout = "serial0";
+ };
};
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/fdt/dts/p2041rdb.dts
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/p2041rdb.dts Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,490 @@
+/*
+ * P2041RDB Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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: head/sys/boot/fdt/dts/p2041rdb.dts 236024 2012-05-25 20:43:38Z raj $ */
+
+/include/ "p2041si.dtsi"
+
+/ {
+ model = "fsl,P2041RDB";
+ compatible = "fsl,P2041RDB";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ phy_rgmii_0 = &phy_rgmii_0;
+ phy_rgmii_1 = &phy_rgmii_1;
+ phy_sgmii_2 = &phy_sgmii_2;
+ phy_sgmii_3 = &phy_sgmii_3;
+ phy_sgmii_4 = &phy_sgmii_4;
+ phy_sgmii_1c = &phy_sgmii_1c;
+ phy_sgmii_1d = &phy_sgmii_1d;
+ phy_sgmii_1e = &phy_sgmii_1e;
+ phy_sgmii_1f = &phy_sgmii_1f;
+ phy_xgmii_2 = &phy_xgmii_2;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x00000000 0x80000000>;
+ };
+
+ dcsr: dcsr at f00000000 {
+ ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+ };
+
+ bman-portals at ff4000000 {
+ bman-portal at 0 {
+ cpu-handle = <&cpu0>;
+ };
+ bman-portal at 4000 {
+ cpu-handle = <&cpu1>;
+ };
+ bman-portal at 8000 {
+ cpu-handle = <&cpu2>;
+ };
+ bman-portal at c000 {
+ cpu-handle = <&cpu3>;
+ };
+ bman-portal at 10000 {
+ };
+ bman-portal at 14000 {
+ };
+ bman-portal at 18000 {
+ };
+ bman-portal at 1c000 {
+ };
+ bman-portal at 20000 {
+ };
+ bman-portal at 24000 {
+ };
+
+ buffer-pool at 0 {
+ compatible = "fsl,p2041-bpool", "fsl,bpool";
+ fsl,bpid = <0>;
+ fsl,bpool-cfg = <0 0x100 0 1 0 0x100>;
+ };
+ };
+
+ qman-portals at ff4200000 {
+ qportal0: qman-portal at 0 {
+ cpu-handle = <&cpu0>;
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal1: qman-portal at 4000 {
+ cpu-handle = <&cpu1>;
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal2: qman-portal at 8000 {
+ cpu-handle = <&cpu2>;
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal3: qman-portal at c000 {
+ cpu-handle = <&cpu3>;
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal4: qman-portal at 10000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal5: qman-portal at 14000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal6: qman-portal at 18000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal7: qman-portal at 1c000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal8: qman-portal at 20000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal9: qman-portal at 24000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+ };
+
+ soc: soc at ffe000000 {
+ spi at 110000 {
+ flash at 0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,s25sl12801";
+ reg = <0>;
+ spi-max-frequency = <40000000>; /* input clock */
+ partition at u-boot {
+ label = "u-boot";
+ reg = <0x00000000 0x00100000>;
+ read-only;
+ };
+ partition at kernel {
+ label = "kernel";
+ reg = <0x00100000 0x00500000>;
+ read-only;
+ };
+ partition at dtb {
+ label = "dtb";
+ reg = <0x00600000 0x00100000>;
+ read-only;
+ };
+ partition at fs {
+ label = "file system";
+ reg = <0x00700000 0x00900000>;
+ };
+ };
+ };
+
+ i2c at 118000 {
+ lm75b at 48 {
+ compatible = "nxp,lm75a";
+ reg = <0x48>;
+ };
+ eeprom at 50 {
+ compatible = "at24,24c256";
+ reg = <0x50>;
+ };
+ rtc at 68 {
+ compatible = "pericom,pt7c4338";
+ reg = <0x68>;
+ };
+ };
+
+ i2c at 118100 {
+ eeprom at 50 {
+ compatible = "at24,24c256";
+ reg = <0x50>;
+ };
+ };
+
+ usb1: usb at 211000 {
+ dr_mode = "host";
+ };
+
+ pme: pme at 316000 {
+ /* Commented out, use default allocation */
+ /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
+ /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
+ };
+
+ qman: qman at 318000 {
+ /* Commented out, use default allocation */
+ /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
+ /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
+ };
+
+ bman: bman at 31a000 {
+ /* Same as fsl,qman-*, use default allocation */
+ /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
+ };
+
+ fman0: fman at 400000 {
+ enet0: ethernet at e0000 {
+ tbi-handle = <&tbi0>;
+ phy-handle = <&phy_sgmii_2>;
+ phy-connection-type = "sgmii";
+ };
+
+ mdio0: mdio at e1120 {
+ tbi0: tbi-phy at 8 {
+ reg = <0x8>;
+ device_type = "tbi-phy";
+ };
+
+ phy_rgmii_0: ethernet-phy at 0 {
+ reg = <0x0>;
+ };
+ phy_rgmii_1: ethernet-phy at 1 {
+ reg = <0x1>;
+ };
+ phy_sgmii_2: ethernet-phy at 2 {
+ reg = <0x2>;
+ };
+ phy_sgmii_3: ethernet-phy at 3 {
+ reg = <0x3>;
+ };
+ phy_sgmii_4: ethernet-phy at 4 {
+ reg = <0x4>;
+ };
+ phy_sgmii_1c: ethernet-phy at 1c {
+ reg = <0x1c>;
+ };
+ phy_sgmii_1d: ethernet-phy at 1d {
+ reg = <0x1d>;
+ };
+ phy_sgmii_1e: ethernet-phy at 1e {
+ reg = <0x1e>;
+ };
+ phy_sgmii_1f: ethernet-phy at 1f {
+ reg = <0x1f>;
+ };
+ };
+
+ enet1: ethernet at e2000 {
+ tbi-handle = <&tbi1>;
+ phy-handle = <&phy_sgmii_3>;
+ phy-connection-type = "sgmii";
+ };
+
+ mdio at e3120 {
+ tbi1: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet2: ethernet at e4000 {
+ tbi-handle = <&tbi2>;
+ phy-handle = <&phy_sgmii_4>;
+ phy-connection-type = "sgmii";
+ };
+
+ mdio at e5120 {
+ tbi2: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet3: ethernet at e6000 {
+ tbi-handle = <&tbi3>;
+ phy-handle = <&phy_rgmii_1>;
+ phy-connection-type = "rgmii";
+ };
+
+ mdio at e7120 {
+ tbi3: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet4: ethernet at e8000 {
+ tbi-handle = <&tbi4>;
+ phy-handle = <&phy_rgmii_0>;
+ phy-connection-type = "rgmii";
+ };
+
+ mdio at e9120 {
+ tbi4: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet5: ethernet at f0000 {
+ /*
+ * phy-handle will be updated by U-Boot to
+ * reflect the actual slot the XAUI card is in.
+ */
+ phy-handle = <&phy_xgmii_2>;
+ phy-connection-type = "xgmii";
+ };
+
+ mdio at f1000 {
+ /* XAUI card in slot 2 */
+ phy_xgmii_2: ethernet-phy at 0 {
+ reg = <0x0>;
+ };
+ };
+ };
+ };
+
+ rapidio at ffe0c0000 {
+ reg = <0xf 0xfe0c0000 0 0x11000>;
+
+ port1 {
+ ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+ };
+ port2 {
+ ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+ };
+ };
+
+ localbus at ffe124000 {
+ reg = <0xf 0xfe124000 0 0x1000>;
+ ranges = <0 0 0xf 0xb8000000 0x04000000>;
+
+ flash at 0,0 {
+ compatible = "cfi-flash";
+ /*
+ * Map 64Mb of 128MB NOR flash memory. Since highest
+ * line of address of NOR flash memory are set by
+ * FPGA, memory are divided into two pages equal to
+ * 64MB. One of the pages can be accessed at once.
+ */
+ reg = <0 0 0x04000000>;
+ bank-width = <2>;
+ device-width = <2>;
+ };
+ };
+
+ pci0: pcie at ffe200000 {
+ reg = <0xf 0xfe200000 0 0x1000>;
+ ranges = <0x02000000 0 0x80000000 0x0 0x80000000 0x0 0x10000000
+ 0x01000000 0 0x00000000 0x0 0xff000000 0x0 0x00010000>;
+ pcie at 0 {
+ ranges = <0x02000000 0 0x80000000
+ 0x02000000 0 0x80000000
+ 0 0x10000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0xff000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci1: pcie at ffe201000 {
+ reg = <0xf 0xfe201000 0 0x1000>;
+ ranges = <0x02000000 0x0 0x90000000 0x0 0x90000000 0x0 0x10000000
+ 0x01000000 0x0 0x00000000 0x0 0xff010000 0x0 0x00010000>;
+ pcie at 0 {
+ ranges = <0x02000000 0 0x90000000
+ 0x02000000 0 0x90000000
+ 0 0x10000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0xff010000
+ 0 0x00010000>;
+ };
+ };
+
+ pci2: pcie at ffe202000 {
+ reg = <0xf 0xfe202000 0 0x1000>;
+ ranges = <0x02000000 0 0xa0000000 0x0 0xa0000000 0 0x10000000
+ 0x01000000 0 0x00000000 0x0 0xff020000 0 0x00010000>;
+ pcie at 0 {
+ ranges = <0x02000000 0 0xa0000000
+ 0x02000000 0 0xa0000000
+ 0 0x10000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0xff020000
+ 0 0x00010000>;
+ };
+ };
+
+ fsl,dpaa {
+ compatible = "fsl,p2041-dpaa", "fsl,dpaa";
+
+ ethernet at 0 {
+ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet0>;
+ status = "okay";
+ };
+ ethernet at 1 {
+ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet1>;
+ status = "okay";
+ };
+ ethernet at 2 {
+ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet2>;
+ status = "okay";
+ };
+ ethernet at 3 {
+ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet3>;
+ status = "okay";
+ };
+ ethernet at 4 {
+ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet4>;
+ status = "okay";
+ };
+ ethernet at 5 {
+ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet5>;
+ status = "okay";
+ };
+ };
+
+ chosen {
+ stdin = "serial0";
+ stdout = "serial0";
+ };
+};
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/fdt/dts/p2041si.dtsi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/p2041si.dtsi Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,1296 @@
+/*
+ * P2041 Silicon Device Tree Source
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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: head/sys/boot/fdt/dts/p2041si.dtsi 236024 2012-05-25 20:43:38Z raj $ */
+
+/dts-v1/;
+
+/ {
+ compatible = "fsl,P2041";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+ dcsr = &dcsr;
+
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ ethernet2 = &enet2;
+ ethernet3 = &enet3;
+ ethernet4 = &enet4;
+ ethernet5 = &enet5;
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ bman = &bman;
+ qman = &qman;
+ pme = &pme;
+ rman = &rman;
+ sdhc = &sdhc;
+ msi0 = &msi0;
+ msi1 = &msi1;
+ msi2 = &msi2;
+
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ sec_mon = &sec_mon;
+
+ fman0 = &fman0;
+ fman0_oh0 = &fman0_oh0;
+ fman0_oh1 = &fman0_oh1;
+ fman0_oh2 = &fman0_oh2;
+ fman0_oh3 = &fman0_oh3;
+ fman0_oh4 = &fman0_oh4;
+ fman0_oh5 = &fman0_oh5;
+ fman0_oh6 = &fman0_oh6;
+ fman0_rx0 = &fman0_rx0;
+ fman0_rx1 = &fman0_rx1;
+ fman0_rx2 = &fman0_rx2;
+ fman0_rx3 = &fman0_rx3;
+ fman0_rx4 = &fman0_rx4;
+ fman0_rx5 = &fman0_rx5;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: PowerPC,e500mc at 0 {
+ device_type = "cpu";
+ reg = <0>;
+ bus-frequency = <749999996>;
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu1: PowerPC,e500mc at 1 {
+ device_type = "cpu";
+ reg = <1>;
+ next-level-cache = <&L2_1>;
+ L2_1: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu2: PowerPC,e500mc at 2 {
+ device_type = "cpu";
+ reg = <2>;
+ next-level-cache = <&L2_2>;
+ L2_2: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu3: PowerPC,e500mc at 3 {
+ device_type = "cpu";
+ reg = <3>;
+ next-level-cache = <&L2_3>;
+ L2_3: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ };
+
+ dcsr: dcsr at f00000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,dcsr", "simple-bus";
+
+ dcsr-epu at 0 {
+ compatible = "fsl,dcsr-epu";
+ interrupts = <52 2 0 0
+ 84 2 0 0
+ 85 2 0 0>;
+ interrupt-parent = <&mpic>;
+ reg = <0x0 0x1000>;
+ };
+ dcsr-npc {
+ compatible = "fsl,dcsr-npc";
+ reg = <0x1000 0x1000 0x1000000 0x8000>;
+ };
+ dcsr-nxc at 2000 {
+ compatible = "fsl,dcsr-nxc";
+ reg = <0x2000 0x1000>;
+ };
+ dcsr-corenet {
+ compatible = "fsl,dcsr-corenet";
+ reg = <0x8000 0x1000 0xB0000 0x1000>;
+ };
+ dcsr-dpaa at 9000 {
+ compatible = "fsl,p2041-dcsr-dpaa", "fsl,dcsr-dpaa";
+ reg = <0x9000 0x1000>;
+ };
+ dcsr-ocn at 11000 {
+ compatible = "fsl,p2041-dcsr-ocn", "fsl,dcsr-ocn";
+ reg = <0x11000 0x1000>;
+ };
+ dcsr-ddr at 12000 {
+ compatible = "fsl,dcsr-ddr";
+ dev-handle = <&ddr>;
+ reg = <0x12000 0x1000>;
+ };
+ dcsr-nal at 18000 {
+ compatible = "fsl,p2041-dcsr-nal", "fsl,dcsr-nal";
+ reg = <0x18000 0x1000>;
+ };
+ dcsr-rcpm at 22000 {
+ compatible = "fsl,p2041-dcsr-rcpm", "fsl,dcsr-rcpm";
+ reg = <0x22000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy at 40000 {
+ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu0>;
+ reg = <0x40000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy at 41000 {
+ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu1>;
+ reg = <0x41000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy at 42000 {
+ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu2>;
+ reg = <0x42000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy at 43000 {
+ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu3>;
+ reg = <0x43000 0x1000>;
+ };
+ };
+
+ bman-portals at ff4000000 {
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ compatible = "bman-portals";
+ ranges = <0x0 0xf 0xfde00000 0x200000>;
+ bman-portal at 0 {
+ cell-index = <0x0>;
+ compatible = "fsl,p2041-bman-portal", "fsl,bman-portal";
+ reg = <0x0 0x4000 0x100000 0x1000>;
+ interrupts = <105 2 0 0>;
+ };
+ bman-portal at 4000 {
+ cell-index = <0x1>;
+ compatible = "fsl,p2041-bman-portal", "fsl,bman-portal";
+ reg = <0x4000 0x4000 0x101000 0x1000>;
+ interrupts = <107 2 0 0>;
+ };
+ bman-portal at 8000 {
+ cell-index = <2>;
+ compatible = "fsl,p2041-bman-portal", "fsl,bman-portal";
+ reg = <0x8000 0x4000 0x102000 0x1000>;
+ interrupts = <109 2 0 0>;
+ };
+ bman-portal at c000 {
+ cell-index = <0x3>;
+ compatible = "fsl,p2041-bman-portal", "fsl,bman-portal";
+ reg = <0xc000 0x4000 0x103000 0x1000>;
+ interrupts = <111 2 0 0>;
+ };
+ bman-portal at 10000 {
+ cell-index = <0x4>;
+ compatible = "fsl,p2041-bman-portal", "fsl,bman-portal";
+ reg = <0x10000 0x4000 0x104000 0x1000>;
+ interrupts = <113 2 0 0>;
+ };
+ bman-portal at 14000 {
+ cell-index = <0x5>;
+ compatible = "fsl,p2041-bman-portal", "fsl,bman-portal";
+ reg = <0x14000 0x4000 0x105000 0x1000>;
+ interrupts = <115 2 0 0>;
+ };
+ bman-portal at 18000 {
+ cell-index = <0x6>;
+ compatible = "fsl,p2041-bman-portal", "fsl,bman-portal";
+ reg = <0x18000 0x4000 0x106000 0x1000>;
+ interrupts = <117 2 0 0>;
+ };
+ bman-portal at 1c000 {
+ cell-index = <0x7>;
+ compatible = "fsl,p2041-bman-portal", "fsl,bman-portal";
+ reg = <0x1c000 0x4000 0x107000 0x1000>;
+ interrupts = <119 2 0 0>;
+ };
+ bman-portal at 20000 {
+ cell-index = <0x8>;
+ compatible = "fsl,p2041-bman-portal", "fsl,bman-portal";
+ reg = <0x20000 0x4000 0x108000 0x1000>;
+ interrupts = <121 2 0 0>;
+ };
+ bman-portal at 24000 {
+ cell-index = <0x9>;
+ compatible = "fsl,p2041-bman-portal", "fsl,bman-portal";
+ reg = <0x24000 0x4000 0x109000 0x1000>;
+ interrupts = <123 2 0 0>;
+ };
+
+ buffer-pool at 0 {
+ compatible = "fsl,p2041-bpool", "fsl,bpool";
+ fsl,bpid = <0>;
+ fsl,bpool-cfg = <0 0x100 0 1 0 0x100>;
+ };
+ };
+
+ qman-portals at ff4200000 {
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ compatible = "qman-portals";
+ ranges = <0x0 0xf 0xfdc00000 0x200000>;
+ qportal0: qman-portal at 0 {
+ cell-index = <0x0>;
+ compatible = "fsl,p2041-qman-portal", "fsl,qman-portal";
+ reg = <0x0 0x4000 0x100000 0x1000>;
+ interrupts = <104 0x2 0 0>;
+ fsl,qman-channel-id = <0x0>;
+ };
+
+ qportal1: qman-portal at 4000 {
+ cell-index = <0x1>;
+ compatible = "fsl,p2041-qman-portal", "fsl,qman-portal";
+ reg = <0x4000 0x4000 0x101000 0x1000>;
+ interrupts = <106 0x2 0 0>;
+ fsl,qman-channel-id = <0x1>;
+ };
+
+ qportal2: qman-portal at 8000 {
+ cell-index = <0x2>;
+ compatible = "fsl,p2041-qman-portal", "fsl,qman-portal";
+ reg = <0x8000 0x4000 0x102000 0x1000>;
+ interrupts = <108 0x2 0 0>;
+ fsl,qman-channel-id = <0x2>;
+ };
+
+ qportal3: qman-portal at c000 {
+ cell-index = <0x3>;
+ compatible = "fsl,p2041-qman-portal", "fsl,qman-portal";
+ reg = <0xc000 0x4000 0x103000 0x1000>;
+ interrupts = <110 0x2 0 0>;
+ fsl,qman-channel-id = <0x3>;
+ };
+
+ qportal4: qman-portal at 10000 {
+ cell-index = <0x4>;
+ compatible = "fsl,p2041-qman-portal", "fsl,qman-portal";
+ reg = <0x10000 0x4000 0x104000 0x1000>;
+ interrupts = <112 0x2 0 0>;
+ fsl,qman-channel-id = <0x4>;
+ };
+
+ qportal5: qman-portal at 14000 {
+ cell-index = <0x5>;
+ compatible = "fsl,p2041-qman-portal", "fsl,qman-portal";
+ reg = <0x14000 0x4000 0x105000 0x1000>;
+ interrupts = <114 0x2 0 0>;
+ fsl,qman-channel-id = <0x5>;
+ };
+
+ qportal6: qman-portal at 18000 {
+ cell-index = <0x6>;
+ compatible = "fsl,p2041-qman-portal", "fsl,qman-portal";
+ reg = <0x18000 0x4000 0x106000 0x1000>;
+ interrupts = <116 0x2 0 0>;
+ fsl,qman-channel-id = <0x6>;
+ };
+
+ qportal7: qman-portal at 1c000 {
+ cell-index = <0x7>;
+ compatible = "fsl,p2041-qman-portal", "fsl,qman-portal";
+ reg = <0x1c000 0x4000 0x107000 0x1000>;
+ interrupts = <118 0x2 0 0>;
+ fsl,qman-channel-id = <0x7>;
+ };
+
+ qportal8: qman-portal at 20000 {
+ cell-index = <0x8>;
+ compatible = "fsl,p2041-qman-portal", "fsl,qman-portal";
+ reg = <0x20000 0x4000 0x108000 0x1000>;
+ interrupts = <120 0x2 0 0>;
+ fsl,qman-channel-id = <0x8>;
+ };
+
+ qportal9: qman-portal at 24000 {
+ cell-index = <0x9>;
+ compatible = "fsl,p2041-qman-portal", "fsl,qman-portal";
+ reg = <0x24000 0x4000 0x109000 0x1000>;
+ interrupts = <122 0x2 0 0>;
+ fsl,qman-channel-id = <0x9>;
+ };
+
+ qpool1: qman-pool at 1 {
+ cell-index = <1>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x21>;
+ };
+
+ qpool2: qman-pool at 2 {
+ cell-index = <2>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x22>;
+ };
+
+ qpool3: qman-pool at 3 {
+ cell-index = <3>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x23>;
+ };
+
+ qpool4: qman-pool at 4 {
+ cell-index = <4>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x24>;
+ };
+
+ qpool5: qman-pool at 5 {
+ cell-index = <5>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x25>;
+ };
+
+ qpool6: qman-pool at 6 {
+ cell-index = <6>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x26>;
+ };
+
+ qpool7: qman-pool at 7 {
+ cell-index = <7>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x27>;
+ };
+
+ qpool8: qman-pool at 8 {
+ cell-index = <8>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x28>;
+ };
+
+ qpool9: qman-pool at 9 {
+ cell-index = <9>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x29>;
+ };
+
+ qpool10: qman-pool at 10 {
+ cell-index = <10>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2a>;
+ };
+
+ qpool11: qman-pool at 11 {
+ cell-index = <11>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2b>;
+ };
+
+ qpool12: qman-pool at 12 {
+ cell-index = <12>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2c>;
+ };
+
+ qpool13: qman-pool at 13 {
+ cell-index = <13>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2d>;
+ };
+
+ qpool14: qman-pool at 14 {
+ cell-index = <14>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2e>;
+ };
+
+ qpool15: qman-pool at 15 {
+ cell-index = <15>;
+ compatible = "fsl,p2041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2f>;
+ };
+ };
+
+ soc: soc at ffe000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "simple-bus";
+
+ bus-frequency = <0>; // Filled out by kernel.
+
+ ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+ reg = <0xf 0xfe000000 0 0x00001000>;
+
+ soc-sram-error {
+ compatible = "fsl,soc-sram-error";
+ interrupts = <16 2 1 29>;
+ };
+
+ corenet-law at 0 {
+ compatible = "fsl,corenet-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <32>;
+ };
+
+ ddr: memory-controller at 8000 {
+ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+ reg = <0x8000 0x1000>;
+ interrupts = <16 2 1 23>;
+ };
+
+ cpc: l3-cache-controller at 10000 {
+ compatible = "fsl,p2041-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+ reg = <0x10000 0x1000>;
+ interrupts = <16 2 1 27>;
+ };
+
+ corenet-cf at 18000 {
+ compatible = "fsl,corenet-cf";
+ reg = <0x18000 0x1000>;
+ interrupts = <16 2 1 31>;
+ fsl,ccf-num-csdids = <32>;
+ fsl,ccf-num-snoopids = <32>;
+ };
+
+ iommu at 20000 {
+ compatible = "fsl,pamu-v1.0", "fsl,pamu";
+ reg = <0x20000 0x4000>;
+ interrupts = <
+ 24 2 0 0
+ 16 2 1 30>;
+ };
+
+ mpic: pic at 40000 {
+ clock-frequency = <0>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <4>;
+ reg = <0x40000 0x40000>;
+ compatible = "fsl,mpic", "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ msi0: msi at 41600 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41600 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe0 0 0 0
+ 0xe1 0 0 0
+ 0xe2 0 0 0
+ 0xe3 0 0 0
+ 0xe4 0 0 0
+ 0xe5 0 0 0
+ 0xe6 0 0 0
+ 0xe7 0 0 0>;
+ };
+
+ msi1: msi at 41800 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41800 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe8 0 0 0
+ 0xe9 0 0 0
+ 0xea 0 0 0
+ 0xeb 0 0 0
+ 0xec 0 0 0
+ 0xed 0 0 0
+ 0xee 0 0 0
+ 0xef 0 0 0>;
+ };
+
+ msi2: msi at 41a00 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41a00 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xf0 0 0 0
+ 0xf1 0 0 0
+ 0xf2 0 0 0
+ 0xf3 0 0 0
+ 0xf4 0 0 0
+ 0xf5 0 0 0
+ 0xf6 0 0 0
+ 0xf7 0 0 0>;
+ };
+
+ guts: global-utilities at e0000 {
+ compatible = "fsl,qoriq-device-config-1.0";
+ reg = <0xe0000 0xe00>;
+ fsl,has-rstcr;
+ #sleep-cells = <1>;
+ fsl,liodn-bits = <12>;
+ };
+
+ pins: global-utilities at e0e00 {
+ compatible = "fsl,qoriq-pin-control-1.0";
+ reg = <0xe0e00 0x200>;
+ #sleep-cells = <2>;
+ };
+
+ clockgen: global-utilities at e1000 {
+ compatible = "fsl,p2041-clockgen", "fsl,qoriq-clockgen-1.0";
+ reg = <0xe1000 0x1000>;
+ clock-frequency = <0>;
+ };
+
+ rcpm: global-utilities at e2000 {
+ compatible = "fsl,qoriq-rcpm-1.0";
+ reg = <0xe2000 0x1000>;
+ #sleep-cells = <1>;
+ };
+
+ sfp: sfp at e8000 {
+ compatible = "fsl,p2041-sfp", "fsl,qoriq-sfp-1.0";
+ reg = <0xe8000 0x1000>;
+ };
+
+ serdes: serdes at ea000 {
+ compatible = "fsl,p2041-serdes";
+ reg = <0xea000 0x1000>;
+ };
+
+ dma0: dma at 100300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p2041-dma", "fsl,eloplus-dma";
+ reg = <0x100300 0x4>;
+ ranges = <0x0 0x100100 0x200>;
+ cell-index = <0>;
+ dma-channel at 0 {
+ compatible = "fsl,p2041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <28 2 0 0>;
+ };
+ dma-channel at 80 {
+ compatible = "fsl,p2041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <29 2 0 0>;
+ };
+ dma-channel at 100 {
+ compatible = "fsl,p2041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <30 2 0 0>;
+ };
+ dma-channel at 180 {
+ compatible = "fsl,p2041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <31 2 0 0>;
+ };
+ };
+
+ dma1: dma at 101300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p2041-dma", "fsl,eloplus-dma";
+ reg = <0x101300 0x4>;
+ ranges = <0x0 0x101100 0x200>;
+ cell-index = <1>;
+ dma-channel at 0 {
+ compatible = "fsl,p2041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <32 2 0 0>;
+ };
+ dma-channel at 80 {
+ compatible = "fsl,p2041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <33 2 0 0>;
+ };
+ dma-channel at 100 {
+ compatible = "fsl,p2041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <34 2 0 0>;
+ };
+ dma-channel at 180 {
+ compatible = "fsl,p2041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <35 2 0 0>;
+ };
+ };
+
+ spi at 110000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,p2041-espi", "fsl,mpc8536-espi";
+ reg = <0x110000 0x1000>;
+ interrupts = <53 0x2 0 0>;
+ fsl,espi-num-chipselects = <4>;
+ };
+
+ sdhc: sdhc at 114000 {
+ compatible = "fsl,p2041-esdhc", "fsl,esdhc";
+ reg = <0x114000 0x1000>;
+ interrupts = <48 2 0 0>;
+ sdhci,auto-cmd12;
+ clock-frequency = <0>;
+ };
+
+ i2c at 118000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x118000 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c at 118100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x118100 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c at 119000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <2>;
+ compatible = "fsl-i2c";
+ reg = <0x119000 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ i2c at 119100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <3>;
+ compatible = "fsl-i2c";
+ reg = <0x119100 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ serial0: serial at 11c500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial1: serial at 11c600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial2: serial at 11d500 {
+ cell-index = <2>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ serial3: serial at 11d600 {
+ cell-index = <3>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ gpio0: gpio at 130000 {
+ compatible = "fsl,p2041-gpio", "fsl,qoriq-gpio";
+ reg = <0x130000 0x1000>;
+ interrupts = <55 2 0 0>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ };
+
+ rman: rman at 1e0000 {
+ compatible = "fsl,rman";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x1e0000 0x20000>;
+ reg = <0x1e0000 0x20000>;
+ interrupts = <16 2 1 11>; /* err_irq */
+ fsl,qman-channels-id = <0x62 0x63>;
+
+ inbound-block at 0 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x0 0x800>;
+ };
+ global-cfg at b00 {
+ compatible = "fsl,rman-global-cfg";
+ reg = <0xb00 0x500>;
+ };
+ inbound-block at 1000 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x1000 0x800>;
+ };
+ inbound-block at 2000 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x2000 0x800>;
+ };
+ inbound-block at 3000 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x3000 0x800>;
+ };
+ };
+
+ usb0: usb at 210000 {
+ compatible = "fsl,p2041-usb2-mph",
+ "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+ reg = <0x210000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <44 0x2 0 0>;
+ phy_type = "utmi";
+ port0;
+ };
+
+ usb1: usb at 211000 {
+ compatible = "fsl,p2041-usb2-dr",
+ "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+ reg = <0x211000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <45 0x2 0 0>;
+ phy_type = "utmi";
+ };
+
+ sata at 220000 {
+ compatible = "fsl,p2041-sata", "fsl,pq-sata-v2";
+ reg = <0x220000 0x1000>;
+ interrupts = <68 0x2 0 0>;
+ };
+
+ sata at 221000 {
+ compatible = "fsl,p2041-sata", "fsl,pq-sata-v2";
+ reg = <0x221000 0x1000>;
+ interrupts = <69 0x2 0 0>;
+ };
+
+ crypto: crypto at 300000 {
+ compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupts = <92 2 0 0>;
+
+ sec_jr0: jr at 1000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupts = <88 2 0 0>;
+ };
+
+ sec_jr1: jr at 2000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupts = <89 2 0 0>;
+ };
+
+ sec_jr2: jr at 3000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupts = <90 2 0 0>;
+ };
+
+ sec_jr3: jr at 4000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupts = <91 2 0 0>;
+ };
+
+ rtic at 6000 {
+ compatible = "fsl,sec-v4.2-rtic",
+ "fsl,sec-v4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a at 0 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b at 20 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c at 40 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d at 60 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ sec_mon: sec_mon at 314000 {
+ compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupts = <93 2 0 0>;
+ };
+
+ pme: pme at 316000 {
+ compatible = "fsl,pme";
+ reg = <0x316000 0x10000>;
+ /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
+ /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
+ interrupts = <16 2 1 5>;
+ };
+
+ qman: qman at 318000 {
+ compatible = "fsl,p2041-qman", "fsl,qman";
+ reg = <0x318000 0x1000>;
+ interrupts = <16 2 1 3>;
+ /* Commented out, use default allocation */
+ /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
+ /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
+ };
+
+ bman: bman at 31a000 {
+ compatible = "fsl,p2041-bman", "fsl,bman";
+ reg = <0x31a000 0x1000>;
+ interrupts = <16 2 1 2>;
+ /* Same as fsl,qman-*, use default allocation */
+ /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
+ };
+
+ fman0: fman at 400000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cell-index = <0>;
+ compatible = "fsl,p2041-fman", "fsl,fman", "simple-bus";
+ ranges = <0 0x400000 0x100000>;
+ reg = <0x400000 0x100000>;
+ clock-frequency = <0>;
+ interrupts = <
+ 96 2 0 0
+ 16 2 1 1>;
+
+ cc at 0 {
+ compatible = "fsl,p2041-fman-cc", "fsl,fman-cc";
+ };
+
+ parser at c7000 {
+ compatible = "fsl,p2041-fman-parser", "fsl,fman-parser";
+ reg = <0xc7000 0x1000>;
+ };
+
+ keygen at c1000 {
+ compatible = "fsl,p2041-fman-keygen", "fsl,fman-keygen";
+ reg = <0xc1000 0x1000>;
+ };
+
+ policer at c0000 {
+ compatible = "fsl,p2041-fman-policer", "fsl,fman-policer";
+ reg = <0xc0000 0x1000>;
+ };
+
+ muram at 0 {
+ compatible = "fsl,p2041-fman-muram", "fsl,fman-muram";
+ reg = <0x0 0x28000>;
+ };
+
+ bmi at 80000 {
+ compatible = "fsl,p2041-fman-bmi", "fsl,fman-bmi";
+ reg = <0x80000 0x400>;
+ };
+
+ qmi at 80400 {
+ compatible = "fsl,p2041-fman-qmi", "fsl,fman-qmi";
+ reg = <0x80400 0x400>;
+ };
+
+ fman0_rx0: port at 88000 {
+ cell-index = <0>;
+ compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x88000 0x1000>;
+ };
+ fman0_rx1: port at 89000 {
+ cell-index = <1>;
+ compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x89000 0x1000>;
+ };
+ fman0_rx2: port at 8a000 {
+ cell-index = <2>;
+ compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x8a000 0x1000>;
+ };
+ fman0_rx3: port at 8b000 {
+ cell-index = <3>;
+ compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x8b000 0x1000>;
+ };
+ fman0_rx4: port at 8c000 {
+ cell-index = <4>;
+ compatible = "fsl,p2041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x8c000 0x1000>;
+ };
+ fman0_rx5: port at 90000 {
+ cell-index = <0>;
+ compatible = "fsl,p2041-fman-port-10g-rx", "fsl,fman-port-10g-rx";
+ reg = <0x90000 0x1000>;
+ };
+
+ fman0_tx5: port at b0000 {
+ cell-index = <0>;
+ compatible = "fsl,p2041-fman-port-10g-tx", "fsl,fman-port-10g-tx";
+ reg = <0xb0000 0x1000>;
+ fsl,qman-channel-id = <0x40>;
+ };
+ fman0_tx0: port at a8000 {
+ cell-index = <0>;
+ compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xa8000 0x1000>;
+ fsl,qman-channel-id = <0x41>;
+ };
+ fman0_tx1: port at a9000 {
+ cell-index = <1>;
+ compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xa9000 0x1000>;
+ fsl,qman-channel-id = <0x42>;
+ };
+ fman0_tx2: port at aa000 {
+ cell-index = <2>;
+ compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xaa000 0x1000>;
+ fsl,qman-channel-id = <0x43>;
+ };
+ fman0_tx3: port at ab000 {
+ cell-index = <3>;
+ compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xab000 0x1000>;
+ fsl,qman-channel-id = <0x44>;
+ };
+ fman0_tx4: port at ac000 {
+ cell-index = <4>;
+ compatible = "fsl,p2041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xac000 0x1000>;
+ fsl,qman-channel-id = <0x45>;
+ };
+
+ fman0_oh0: port at 81000 {
+ cell-index = <0>;
+ compatible = "fsl,p2041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x81000 0x1000>;
+ fsl,qman-channel-id = <0x46>;
+ };
+ fman0_oh1: port at 82000 {
+ cell-index = <1>;
+ compatible = "fsl,p2041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x82000 0x1000>;
+ fsl,qman-channel-id = <0x47>;
+ };
+ fman0_oh2: port at 83000 {
+ cell-index = <2>;
+ compatible = "fsl,p2041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x83000 0x1000>;
+ fsl,qman-channel-id = <0x48>;
+ };
+ fman0_oh3: port at 84000 {
+ cell-index = <3>;
+ compatible = "fsl,p2041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x84000 0x1000>;
+ fsl,qman-channel-id = <0x49>;
+ };
+ fman0_oh4: port at 85000 {
+ cell-index = <4>;
+ compatible = "fsl,p2041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x85000 0x1000>;
+ fsl,qman-channel-id = <0x4a>;
+ };
+ fman0_oh5: port at 86000 {
+ cell-index = <5>;
+ compatible = "fsl,p2041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x86000 0x1000>;
+ fsl,qman-channel-id = <0x4b>;
+ };
+ fman0_oh6: port at 87000 {
+ cell-index = <6>;
+ compatible = "fsl,p2041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x87000 0x1000>;
+ };
+
+ enet0: ethernet at e0000 {
+ cell-index = <0>;
+ compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe0000 0x1000>;
+ fsl,port-handles = <&fman0_rx0 &fman0_tx0>;
+ };
+
+ mdio0: mdio at e1120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-mdio";
+ reg = <0xe1120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet1: ethernet at e2000 {
+ cell-index = <1>;
+ compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe2000 0x1000>;
+ fsl,port-handles = <&fman0_rx1 &fman0_tx1>;
+ };
+
+ mdio at e3120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe3120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet2: ethernet at e4000 {
+ cell-index = <2>;
+ compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe4000 0x1000>;
+ fsl,port-handles = <&fman0_rx2 &fman0_tx2>;
+ };
+
+ mdio at e5120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe5120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet3: ethernet at e6000 {
+ cell-index = <3>;
+ compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe6000 0x1000>;
+ fsl,port-handles = <&fman0_rx3 &fman0_tx3>;
+ };
+
+ mdio at e7120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe7120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet4: ethernet at e8000 {
+ cell-index = <4>;
+ compatible = "fsl,p2041-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe8000 0x1000>;
+ fsl,port-handles = <&fman0_rx4 &fman0_tx4>;
+ };
+
+ mdio at e9120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe9120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet5: ethernet at f0000 {
+ cell-index = <0>;
+ compatible = "fsl,p2041-fman-10g-mac", "fsl,fman-10g-mac";
+ reg = <0xf0000 0x1000>;
+ fsl,port-handles = <&fman0_rx5 &fman0_tx5>;
+ };
+
+ mdio at f1000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-xmdio";
+ reg = <0xf1000 0x1000>;
+ interrupts = <100 1 0 0>;
+ };
+ };
+ };
+
+ rapidio at ffe0c0000 {
+ compatible = "fsl,srio";
+ interrupts = <16 2 1 11>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ port1 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ cell-index = <1>;
+ };
+
+ port2 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ cell-index = <2>;
+ };
+ };
+
+ localbus at ffe124000 {
+ compatible = "fsl,p2041-elbc", "fsl,elbc", "simple-bus";
+ interrupts = <25 2 0 0>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ };
+
+ pci0: pcie at ffe200000 {
+ compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ status = "disabled";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <33333333>;
+ fsl,msi = <&msi0>;
+ interrupts = <16 2 1 15>;
+ pcie at 0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 15>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 40 1 0 0
+ 0000 0 0 2 &mpic 1 1 0 0
+ 0000 0 0 3 &mpic 2 1 0 0
+ 0000 0 0 4 &mpic 3 1 0 0
+ >;
+ };
+ };
+
+ pci1: pcie at ffe201000 {
+ compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ status = "okay";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0 0xff>;
+ clock-frequency = <33333333>;
+ fsl,msi = <&msi1>;
+ interrupts = <16 2 1 14>;
+ pcie at 0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 14>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 41 1 0 0
+ 0000 0 0 2 &mpic 5 1 0 0
+ 0000 0 0 3 &mpic 6 1 0 0
+ 0000 0 0 4 &mpic 7 1 0 0
+ >;
+ };
+ };
+
+ pci2: pcie at ffe202000 {
+ compatible = "fsl,p2041-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ status = "disabled";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <33333333>;
+ fsl,msi = <&msi2>;
+ interrupts = <16 2 1 13>;
+ pcie at 0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 13>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 42 1 0 0
+ 0000 0 0 2 &mpic 9 1 0 0
+ 0000 0 0 3 &mpic 10 1 0 0
+ 0000 0 0 4 &mpic 11 1 0 0
+ >;
+ };
+ };
+};
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/fdt/dts/p3041ds.dts
--- a/head/sys/boot/fdt/dts/p3041ds.dts Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/fdt/dts/p3041ds.dts Wed Jul 25 16:45:04 2012 +0300
@@ -31,9 +31,9 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $FreeBSD: head/sys/boot/fdt/dts/p3041ds.dts 227506 2011-11-14 18:51:39Z marcel $ */
+/* $FreeBSD: head/sys/boot/fdt/dts/p3041ds.dts 236024 2012-05-25 20:43:38Z raj $ */
-/dts-v1/;
+/include/ "p3041si.dtsi"
/ {
model = "fsl,P3041DS";
@@ -43,305 +43,155 @@
interrupt-parent = <&mpic>;
aliases {
- ccsr = &soc;
-
- serial0 = &serial0;
- serial1 = &serial1;
- serial2 = &serial2;
- serial3 = &serial3;
- pci0 = &pci0;
- pci1 = &pci1;
- pci2 = &pci2;
- pci3 = &pci3;
- usb0 = &usb0;
- usb1 = &usb1;
- dma0 = &dma0;
- dma1 = &dma1;
- sdhc = &sdhc;
- msi0 = &msi0;
- msi1 = &msi1;
- msi2 = &msi2;
-
- crypto = &crypto;
- sec_jr0 = &sec_jr0;
- sec_jr1 = &sec_jr1;
- sec_jr2 = &sec_jr2;
- sec_jr3 = &sec_jr3;
- rtic_a = &rtic_a;
- rtic_b = &rtic_b;
- rtic_c = &rtic_c;
- rtic_d = &rtic_d;
- sec_mon = &sec_mon;
- };
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- cpu0: PowerPC,e500mc at 0 {
- device_type = "cpu";
- reg = <0>;
- next-level-cache = <&L2_0>;
- L2_0: l2-cache {
- next-level-cache = <&cpc>;
- };
- };
- cpu1: PowerPC,e500mc at 1 {
- device_type = "cpu";
- reg = <1>;
- next-level-cache = <&L2_1>;
- L2_1: l2-cache {
- next-level-cache = <&cpc>;
- };
- };
- cpu2: PowerPC,e500mc at 2 {
- device_type = "cpu";
- reg = <2>;
- next-level-cache = <&L2_2>;
- L2_2: l2-cache {
- next-level-cache = <&cpc>;
- };
- };
- cpu3: PowerPC,e500mc at 3 {
- device_type = "cpu";
- reg = <3>;
- next-level-cache = <&L2_3>;
- L2_3: l2-cache {
- next-level-cache = <&cpc>;
- };
- };
+ phy_rgmii_0 = &phy_rgmii_0;
+ phy_rgmii_1 = &phy_rgmii_1;
+ phy_sgmii_1c = &phy_sgmii_1c;
+ phy_sgmii_1d = &phy_sgmii_1d;
+ phy_sgmii_1e = &phy_sgmii_1e;
+ phy_sgmii_1f = &phy_sgmii_1f;
+ phy_xgmii_1 = &phy_xgmii_1;
+ phy_xgmii_2 = &phy_xgmii_2;
+ emi1_rgmii = &hydra_mdio_rgmii;
+ emi1_sgmii = &hydra_mdio_sgmii;
+ emi2_xgmii = &hydra_mdio_xgmii;
};
memory {
device_type = "memory";
+ reg = <0x00000000 0x00000000 0x00000000 0x80000000>;
+ };
+
+ dcsr: dcsr at f00000000 {
+ ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+ };
+
+ bman-portals at ff4000000 {
+ bman-portal at 0 {
+ cpu-handle = <&cpu0>;
+ };
+ bman-portal at 4000 {
+ cpu-handle = <&cpu1>;
+ };
+ bman-portal at 8000 {
+ cpu-handle = <&cpu2>;
+ };
+ bman-portal at c000 {
+ cpu-handle = <&cpu3>;
+ };
+ bman-portal at 10000 {
+ };
+ bman-portal at 14000 {
+ };
+ bman-portal at 18000 {
+ };
+ bman-portal at 1c000 {
+ };
+ bman-portal at 20000 {
+ };
+ bman-portal at 24000 {
+ };
+
+ buffer-pool at 0 {
+ compatible = "fsl,p3041-bpool", "fsl,bpool";
+ fsl,bpid = <0>;
+ fsl,bpool-cfg = <0 0x100 0 1 0 0x100>;
+ };
+ };
+
+ qman-portals at ff4200000 {
+ qportal0: qman-portal at 0 {
+ cpu-handle = <&cpu0>;
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal1: qman-portal at 4000 {
+ cpu-handle = <&cpu1>;
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal2: qman-portal at 8000 {
+ cpu-handle = <&cpu2>;
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal3: qman-portal at c000 {
+ cpu-handle = <&cpu3>;
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal4: qman-portal at 10000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal5: qman-portal at 14000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal6: qman-portal at 18000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal7: qman-portal at 1c000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal8: qman-portal at 20000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal9: qman-portal at 24000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
};
soc: soc at ffe000000 {
- #address-cells = <1>;
- #size-cells = <1>;
- device_type = "soc";
- compatible = "simple-bus";
- ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
- reg = <0xf 0xfe000000 0 0x00001000>;
-
- soc-sram-error {
- compatible = "fsl,soc-sram-error";
- interrupts = <16 2 1 29>;
- };
-
- corenet-law at 0 {
- compatible = "fsl,corenet-law";
- reg = <0x0 0x1000>;
- fsl,num-laws = <32>;
- };
-
- memory-controller at 8000 {
- compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
- reg = <0x8000 0x1000>;
- interrupts = <16 2 1 23>;
- };
-
- cpc: l3-cache-controller at 10000 {
- compatible = "fsl,p3041-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
- reg = <0x10000 0x1000>;
- interrupts = <16 2 1 27>;
- };
-
- corenet-cf at 18000 {
- compatible = "fsl,corenet-cf";
- reg = <0x18000 0x1000>;
- interrupts = <16 2 1 31>;
- fsl,ccf-num-csdids = <32>;
- fsl,ccf-num-snoopids = <32>;
- };
-
- iommu at 20000 {
- compatible = "fsl,pamu-v1.0", "fsl,pamu";
- reg = <0x20000 0x4000>;
- interrupts = <
- 24 2 0 0
- 16 2 1 30>;
- };
-
- mpic: pic at 40000 {
- clock-frequency = <0>;
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <4>;
- reg = <0x40000 0x40000>;
- compatible = "fsl,mpic", "chrp,open-pic";
- device_type = "open-pic";
- };
-
- msi0: msi at 41600 {
- compatible = "fsl,mpic-msi";
- reg = <0x41600 0x200>;
- msi-available-ranges = <0 0x100>;
- interrupts = <
- 0xe0 0 0 0
- 0xe1 0 0 0
- 0xe2 0 0 0
- 0xe3 0 0 0
- 0xe4 0 0 0
- 0xe5 0 0 0
- 0xe6 0 0 0
- 0xe7 0 0 0>;
- };
-
- msi1: msi at 41800 {
- compatible = "fsl,mpic-msi";
- reg = <0x41800 0x200>;
- msi-available-ranges = <0 0x100>;
- interrupts = <
- 0xe8 0 0 0
- 0xe9 0 0 0
- 0xea 0 0 0
- 0xeb 0 0 0
- 0xec 0 0 0
- 0xed 0 0 0
- 0xee 0 0 0
- 0xef 0 0 0>;
- };
-
- msi2: msi at 41a00 {
- compatible = "fsl,mpic-msi";
- reg = <0x41a00 0x200>;
- msi-available-ranges = <0 0x100>;
- interrupts = <
- 0xf0 0 0 0
- 0xf1 0 0 0
- 0xf2 0 0 0
- 0xf3 0 0 0
- 0xf4 0 0 0
- 0xf5 0 0 0
- 0xf6 0 0 0
- 0xf7 0 0 0>;
- };
-
- guts: global-utilities at e0000 {
- compatible = "fsl,qoriq-device-config-1.0";
- reg = <0xe0000 0xe00>;
- fsl,has-rstcr;
- #sleep-cells = <1>;
- fsl,liodn-bits = <12>;
- };
-
- pins: global-utilities at e0e00 {
- compatible = "fsl,qoriq-pin-control-1.0";
- reg = <0xe0e00 0x200>;
- #sleep-cells = <2>;
- };
-
- clockgen: global-utilities at e1000 {
- compatible = "fsl,p3041-clockgen", "fsl,qoriq-clockgen-1.0";
- reg = <0xe1000 0x1000>;
- clock-frequency = <0>;
- };
-
- rcpm: global-utilities at e2000 {
- compatible = "fsl,qoriq-rcpm-1.0";
- reg = <0xe2000 0x1000>;
- #sleep-cells = <1>;
- };
-
- sfp: sfp at e8000 {
- compatible = "fsl,p3041-sfp", "fsl,qoriq-sfp-1.0";
- reg = <0xe8000 0x1000>;
- };
-
- serdes: serdes at ea000 {
- compatible = "fsl,p3041-serdes";
- reg = <0xea000 0x1000>;
- };
-
- dma0: dma at 100300 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "fsl,p3041-dma", "fsl,eloplus-dma";
- reg = <0x100300 0x4>;
- ranges = <0x0 0x100100 0x200>;
- cell-index = <0>;
- dma-channel at 0 {
- compatible = "fsl,p3041-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x0 0x80>;
- cell-index = <0>;
- interrupts = <28 2 0 0>;
- };
- dma-channel at 80 {
- compatible = "fsl,p3041-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x80 0x80>;
- cell-index = <1>;
- interrupts = <29 2 0 0>;
- };
- dma-channel at 100 {
- compatible = "fsl,p3041-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x100 0x80>;
- cell-index = <2>;
- interrupts = <30 2 0 0>;
- };
- dma-channel at 180 {
- compatible = "fsl,p3041-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x180 0x80>;
- cell-index = <3>;
- interrupts = <31 2 0 0>;
- };
- };
-
- dma1: dma at 101300 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "fsl,p3041-dma", "fsl,eloplus-dma";
- reg = <0x101300 0x4>;
- ranges = <0x0 0x101100 0x200>;
- cell-index = <1>;
- dma-channel at 0 {
- compatible = "fsl,p3041-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x0 0x80>;
- cell-index = <0>;
- interrupts = <32 2 0 0>;
- };
- dma-channel at 80 {
- compatible = "fsl,p3041-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x80 0x80>;
- cell-index = <1>;
- interrupts = <33 2 0 0>;
- };
- dma-channel at 100 {
- compatible = "fsl,p3041-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x100 0x80>;
- cell-index = <2>;
- interrupts = <34 2 0 0>;
- };
- dma-channel at 180 {
- compatible = "fsl,p3041-dma-channel",
- "fsl,eloplus-dma-channel";
- reg = <0x180 0x80>;
- cell-index = <3>;
- interrupts = <35 2 0 0>;
- };
- };
-
spi at 110000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "fsl,p3041-espi", "fsl,mpc8536-espi";
- reg = <0x110000 0x1000>;
- interrupts = <53 0x2 0 0>;
- fsl,espi-num-chipselects = <4>;
-
flash at 0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "spansion,s25sl12801";
reg = <0>;
- spi-max-frequency = <40000000>; /* input clock */
+ spi-max-frequency = <35000000>; /* input clock */
partition at u-boot {
label = "u-boot";
reg = <0x00000000 0x00100000>;
@@ -364,32 +214,7 @@
};
};
- sdhc: sdhc at 114000 {
- compatible = "fsl,p3041-esdhc", "fsl,esdhc";
- reg = <0x114000 0x1000>;
- interrupts = <48 2 0 0>;
- sdhci,auto-cmd12;
- clock-frequency = <0>;
- };
-
- i2c at 118000 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <0>;
- compatible = "fsl-i2c";
- reg = <0x118000 0x100>;
- interrupts = <38 2 0 0>;
- dfsrr;
- };
-
i2c at 118100 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <1>;
- compatible = "fsl-i2c";
- reg = <0x118100 0x100>;
- interrupts = <38 2 0 0>;
- dfsrr;
eeprom at 51 {
compatible = "at24,24c256";
reg = <0x51>;
@@ -400,24 +225,7 @@
};
};
- i2c at 119000 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <2>;
- compatible = "fsl-i2c";
- reg = <0x119000 0x100>;
- interrupts = <39 2 0 0>;
- dfsrr;
- };
-
i2c at 119100 {
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <3>;
- compatible = "fsl-i2c";
- reg = <0x119100 0x100>;
- interrupts = <39 2 0 0>;
- dfsrr;
rtc at 68 {
compatible = "dallas,ds3232";
reg = <0x68>;
@@ -425,329 +233,355 @@
};
};
- serial0: serial at 11c500 {
- cell-index = <0>;
- device_type = "serial";
- compatible = "ns16550";
- reg = <0x11c500 0x100>;
- clock-frequency = <0>;
- interrupts = <36 2 0 0>;
+ pme: pme at 316000 {
+ /* Commented out, use default allocation */
+ /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
+ /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
};
- serial1: serial at 11c600 {
- cell-index = <1>;
- device_type = "serial";
- compatible = "ns16550";
- reg = <0x11c600 0x100>;
- clock-frequency = <0>;
- interrupts = <36 2 0 0>;
+ qman: qman at 318000 {
+ /* Commented out, use default allocation */
+ /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
+ /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
};
- serial2: serial at 11d500 {
- cell-index = <2>;
- device_type = "serial";
- compatible = "ns16550";
- reg = <0x11d500 0x100>;
- clock-frequency = <0>;
- interrupts = <37 2 0 0>;
+ bman: bman at 31a000 {
+ /* Same as fsl,qman-*, use default allocation */
+ /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
};
- serial3: serial at 11d600 {
- cell-index = <3>;
- device_type = "serial";
- compatible = "ns16550";
- reg = <0x11d600 0x100>;
- clock-frequency = <0>;
- interrupts = <37 2 0 0>;
- };
-
- gpio0: gpio at 130000 {
- compatible = "fsl,p3041-gpio", "fsl,qoriq-gpio";
- reg = <0x130000 0x1000>;
- interrupts = <55 2 0 0>;
- #gpio-cells = <2>;
- gpio-controller;
- };
-
- usb0: usb at 210000 {
- compatible = "fsl,p3041-usb2-mph",
- "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
- reg = <0x210000 0x1000>;
- #address-cells = <1>;
- #size-cells = <0>;
- interrupts = <44 0x2 0 0>;
- phy_type = "utmi";
- port0;
- };
-
- usb1: usb at 211000 {
- compatible = "fsl,p3041-usb2-dr",
- "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
- reg = <0x211000 0x1000>;
- #address-cells = <1>;
- #size-cells = <0>;
- interrupts = <45 0x2 0 0>;
- dr_mode = "host";
- phy_type = "utmi";
- };
-
- sata at 220000 {
- compatible = "fsl,p3041-sata", "fsl,pq-sata-v2";
- reg = <0x220000 0x1000>;
- interrupts = <68 0x2 0 0>;
- };
-
- sata at 221000 {
- compatible = "fsl,p3041-sata", "fsl,pq-sata-v2";
- reg = <0x221000 0x1000>;
- interrupts = <69 0x2 0 0>;
- };
-
- crypto: crypto at 300000 {
- compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
- #address-cells = <1>;
- #size-cells = <1>;
- reg = <0x300000 0x10000>;
- ranges = <0 0x300000 0x10000>;
- interrupts = <92 2 0 0>;
-
- sec_jr0: jr at 1000 {
- compatible = "fsl,sec-v4.2-job-ring",
- "fsl,sec-v4.0-job-ring";
- reg = <0x1000 0x1000>;
- interrupts = <88 2 0 0>;
+ fman0: fman at 400000 {
+ enet0: ethernet at e0000 {
+ tbi-handle = <&tbi0>;
+ phy-handle = <&phy_rgmii_0>;
+ phy-connection-type = "rgmii";
};
- sec_jr1: jr at 2000 {
- compatible = "fsl,sec-v4.2-job-ring",
- "fsl,sec-v4.0-job-ring";
- reg = <0x2000 0x1000>;
- interrupts = <89 2 0 0>;
+ mdio0: mdio at e1120 {
+ tbi0: tbi-phy at 8 {
+ reg = <0x8>;
+ device_type = "tbi-phy";
+ };
+
+ /*
+ * Virtual MDIO for the two on-board RGMII
+ * ports. The fsl,hydra-mdio-muxval property
+ * is already correct.
+ */
+ hydra_mdio_rgmii: hydra-mdio-rgmii {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,hydra-mdio";
+ fsl,mdio-handle = <&mdio0>;
+ fsl,hydra-mdio-muxval = <0x00>;
+ status = "disabled";
+
+ phy_rgmii_0: ethernet-phy at 0 {
+ reg = <0x0>;
+ };
+ phy_rgmii_1: ethernet-phy at 1 {
+ reg = <0x1>;
+ };
+ };
+
+ /*
+ * Virtual MDIO for the four-port SGMII card.
+ * The fsl,hydra-mdio-muxval property will be
+ * fixed-up by U-Boot based on the slot that
+ * the SGMII card is in.
+ *
+ * Note: we do not support DTSEC5 connected to
+ * SGMII, so this is the only SGMII node.
+ */
+ hydra_mdio_sgmii: hydra-mdio-sgmii {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,hydra-mdio";
+ fsl,mdio-handle = <&mdio0>;
+ fsl,hydra-mdio-muxval = <0x00>;
+ status = "disabled";
+
+ phy_sgmii_1c: ethernet-phy at 1c {
+ reg = <0x1c>;
+ };
+ phy_sgmii_1d: ethernet-phy at 1d {
+ reg = <0x1d>;
+ };
+ phy_sgmii_1e: ethernet-phy at 1e {
+ reg = <0x1e>;
+ };
+ phy_sgmii_1f: ethernet-phy at 1f {
+ reg = <0x1f>;
+ };
+ };
};
- sec_jr2: jr at 3000 {
- compatible = "fsl,sec-v4.2-job-ring",
- "fsl,sec-v4.0-job-ring";
- reg = <0x3000 0x1000>;
- interrupts = <90 2 0 0>;
+ enet1: ethernet at e2000 {
+ tbi-handle = <&tbi1>;
+ phy-handle = <&phy_sgmii_1d>;
+ phy-connection-type = "sgmii";
};
- sec_jr3: jr at 4000 {
- compatible = "fsl,sec-v4.2-job-ring",
- "fsl,sec-v4.0-job-ring";
- reg = <0x4000 0x1000>;
- interrupts = <91 2 0 0>;
+ mdio at e3120 {
+ tbi1: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
};
- rtic at 6000 {
- compatible = "fsl,sec-v4.2-rtic",
- "fsl,sec-v4.0-rtic";
+ enet2: ethernet at e4000 {
+ tbi-handle = <&tbi2>;
+ phy-handle = <&phy_sgmii_1e>;
+ phy-connection-type = "sgmii";
+ };
+
+ mdio at e5120 {
+ tbi2: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet3: ethernet at e6000 {
+ tbi-handle = <&tbi3>;
+ phy-handle = <&phy_sgmii_1f>;
+ phy-connection-type = "sgmii";
+ };
+
+ mdio at e7120 {
#address-cells = <1>;
- #size-cells = <1>;
- reg = <0x6000 0x100>;
- ranges = <0x0 0x6100 0xe00>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe7120 0xee0>;
+ interrupts = <100 1 0 0>;
- rtic_a: rtic-a at 0 {
- compatible = "fsl,sec-v4.2-rtic-memory",
- "fsl,sec-v4.0-rtic-memory";
- reg = <0x00 0x20 0x100 0x80>;
+ tbi3: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet4: ethernet at e8000 {
+ tbi-handle = <&tbi4>;
+ phy-handle = <&phy_rgmii_1>;
+ phy-connection-type = "rgmii";
+ };
+
+ mdio at e9120 {
+ tbi4: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet5: ethernet at f0000 {
+ /*
+ * phy-handle will be updated by U-Boot to
+ * reflect the actual slot the XAUI card is in.
+ */
+ phy-handle = <&phy_xgmii_1>;
+ phy-connection-type = "xgmii";
+ };
+
+ /*
+ * We only support one XAUI card, so the MDIO muxing
+ * is set by U-Boot, and Linux never touches it.
+ * Therefore, we don't need a virtual MDIO node.
+ * However, the phy address depends on the slot, so
+ * only one of the ethernet-phy nodes below will be
+ * used.
+ */
+ hydra_mdio_xgmii: mdio at f1000 {
+ status = "disabled";
+
+ /* XAUI card in slot 1 */
+ phy_xgmii_1: ethernet-phy at 4 {
+ reg = <0x4>;
};
- rtic_b: rtic-b at 20 {
- compatible = "fsl,sec-v4.2-rtic-memory",
- "fsl,sec-v4.0-rtic-memory";
- reg = <0x20 0x20 0x200 0x80>;
- };
-
- rtic_c: rtic-c at 40 {
- compatible = "fsl,sec-v4.2-rtic-memory",
- "fsl,sec-v4.0-rtic-memory";
- reg = <0x40 0x20 0x300 0x80>;
- };
-
- rtic_d: rtic-d at 60 {
- compatible = "fsl,sec-v4.2-rtic-memory",
- "fsl,sec-v4.0-rtic-memory";
- reg = <0x60 0x20 0x500 0x80>;
+ /* XAUI card in slot 2 */
+ phy_xgmii_2: ethernet-phy at 0 {
+ reg = <0x0>;
};
};
};
+ };
- sec_mon: sec_mon at 314000 {
- compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
- reg = <0x314000 0x1000>;
- interrupts = <93 2 0 0>;
+ rapidio at ffe0c0000 {
+ reg = <0xf 0xfe0c0000 0 0x11000>;
+
+ port1 {
+ ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+ };
+ port2 {
+ ranges = <0 0 0xc 0x30000000 0 0x10000000>;
};
};
localbus at ffe124000 {
- compatible = "fsl,p3041-elbc", "fsl,elbc", "simple-bus";
reg = <0xf 0xfe124000 0 0x1000>;
- interrupts = <25 2 0 0>;
- #address-cells = <2>;
- #size-cells = <1>;
-
- ranges = <0 0 0xf 0xe8000000 0x08000000
- 3 0 0xf 0xffdf0000 0x00008000>;
+ ranges = <0 0 0xf 0xb8000000 0x04000000>;
flash at 0,0 {
compatible = "cfi-flash";
- reg = <0 0 0x08000000>;
+ /*
+ * Map 64Mb of 128MB NOR flash memory. Since highest
+ * line of address of NOR flash memory are set by
+ * FPGA, memory are divided into two pages equal to
+ * 64MB. One of the pages can be accessed at once.
+ */
+ reg = <0 0 0x04000000>;
bank-width = <2>;
device-width = <2>;
};
+ nand at 2,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,elbc-fcm-nand";
+ reg = <0x2 0x0 0x40000>;
+
+ partition at 0 {
+ label = "NAND U-Boot Image";
+ reg = <0x0 0x02000000>;
+ read-only;
+ };
+
+ partition at 2000000 {
+ label = "NAND Root File System";
+ reg = <0x02000000 0x10000000>;
+ };
+
+ partition at 12000000 {
+ label = "NAND Compressed RFS Image";
+ reg = <0x12000000 0x08000000>;
+ };
+
+ partition at 1a000000 {
+ label = "NAND Linux Kernel Image";
+ reg = <0x1a000000 0x04000000>;
+ };
+
+ partition at 1e000000 {
+ label = "NAND DTB Image";
+ reg = <0x1e000000 0x01000000>;
+ };
+
+ partition at 1f000000 {
+ label = "NAND Writable User area";
+ reg = <0x1f000000 0x21000000>;
+ };
+ };
+
board-control at 3,0 {
- compatible = "fsl,p3041ds-pixis";
- reg = <3 0 0x20>;
+ compatible = "fsl,p3041ds-fpga", "fsl,fpga-ngpixis";
+ reg = <3 0 0x30>;
};
};
pci0: pcie at ffe200000 {
- compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
- device_type = "pci";
- #size-cells = <2>;
- #address-cells = <3>;
reg = <0xf 0xfe200000 0 0x1000>;
- bus-range = <0x0 0xff>;
- ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
- 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
- clock-frequency = <0x1fca055>;
- fsl,msi = <&msi0>;
- interrupts = <16 2 1 15>;
+ ranges = <0x02000000 0 0x80000000 0x0 0x80000000 0x0 0x10000000
+ 0x01000000 0 0x00000000 0x0 0xff000000 0x0 0x00010000>;
pcie at 0 {
- reg = <0 0 0 0 0>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
- interrupts = <16 2 1 15>;
- interrupt-map-mask = <0xf800 0 0 7>;
- interrupt-map = <
- /* IDSEL 0x0 */
- 0000 0 0 1 &mpic 40 1 0 0
- 0000 0 0 2 &mpic 1 1 0 0
- 0000 0 0 3 &mpic 2 1 0 0
- 0000 0 0 4 &mpic 3 1 0 0
- >;
- ranges = <0x02000000 0 0xe0000000
- 0x02000000 0 0xe0000000
- 0 0x20000000
+ ranges = <0x02000000 0 0x80000000
+ 0x02000000 0 0x80000000
+ 0 0x10000000
0x01000000 0 0x00000000
- 0x01000000 0 0x00000000
+ 0x01000000 0 0xff000000
0 0x00010000>;
};
};
pci1: pcie at ffe201000 {
- compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
- device_type = "pci";
- #size-cells = <2>;
- #address-cells = <3>;
reg = <0xf 0xfe201000 0 0x1000>;
- bus-range = <0 0xff>;
- ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
- 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
- clock-frequency = <0x1fca055>;
- fsl,msi = <&msi1>;
- interrupts = <16 2 1 14>;
+ ranges = <0x02000000 0x0 0x90000000 0x0 0x90000000 0x0 0x10000000
+ 0x01000000 0x0 0x00000000 0x0 0xff010000 0x0 0x00010000>;
pcie at 0 {
- reg = <0 0 0 0 0>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
- interrupts = <16 2 1 14>;
- interrupt-map-mask = <0xf800 0 0 7>;
- interrupt-map = <
- /* IDSEL 0x0 */
- 0000 0 0 1 &mpic 41 1 0 0
- 0000 0 0 2 &mpic 5 1 0 0
- 0000 0 0 3 &mpic 6 1 0 0
- 0000 0 0 4 &mpic 7 1 0 0
- >;
- ranges = <0x02000000 0 0xe0000000
- 0x02000000 0 0xe0000000
- 0 0x20000000
+ ranges = <0x02000000 0 0x90000000
+ 0x02000000 0 0x90000000
+ 0 0x10000000
0x01000000 0 0x00000000
- 0x01000000 0 0x00000000
+ 0x01000000 0 0xff010000
0 0x00010000>;
};
};
pci2: pcie at ffe202000 {
- compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
- device_type = "pci";
- #size-cells = <2>;
- #address-cells = <3>;
reg = <0xf 0xfe202000 0 0x1000>;
- bus-range = <0x0 0xff>;
- ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
- 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
- clock-frequency = <0x1fca055>;
- fsl,msi = <&msi2>;
- interrupts = <16 2 1 13>;
+ ranges = <0x02000000 0 0xa0000000 0x0 0xa0000000 0 0x10000000
+ 0x01000000 0 0x00000000 0x0 0xff020000 0 0x00010000>;
pcie at 0 {
- reg = <0 0 0 0 0>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
- interrupts = <16 2 1 13>;
- interrupt-map-mask = <0xf800 0 0 7>;
- interrupt-map = <
- /* IDSEL 0x0 */
- 0000 0 0 1 &mpic 42 1 0 0
- 0000 0 0 2 &mpic 9 1 0 0
- 0000 0 0 3 &mpic 10 1 0 0
- 0000 0 0 4 &mpic 11 1 0 0
- >;
- ranges = <0x02000000 0 0xe0000000
- 0x02000000 0 0xe0000000
- 0 0x20000000
+ ranges = <0x02000000 0 0xa0000000
+ 0x02000000 0 0xa0000000
+ 0 0x10000000
0x01000000 0 0x00000000
- 0x01000000 0 0x00000000
+ 0x01000000 0 0xff020000
0 0x00010000>;
};
};
pci3: pcie at ffe203000 {
- compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
- device_type = "pci";
- #size-cells = <2>;
- #address-cells = <3>;
reg = <0xf 0xfe203000 0 0x1000>;
- bus-range = <0x0 0xff>;
- ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000
- 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
- clock-frequency = <0x1fca055>;
- fsl,msi = <&msi2>;
- interrupts = <16 2 1 12>;
+ ranges = <0x02000000 0 0xb0000000 0x0 0xb0000000 0 0x08000000
+ 0x01000000 0 0x00000000 0x0 0xff030000 0 0x00010000>;
pcie at 0 {
- reg = <0 0 0 0 0>;
- #interrupt-cells = <1>;
- #size-cells = <2>;
- #address-cells = <3>;
- device_type = "pci";
- interrupts = <16 2 1 12>;
- interrupt-map-mask = <0xf800 0 0 7>;
- interrupt-map = <
- /* IDSEL 0x0 */
- 0000 0 0 1 &mpic 43 1 0 0
- 0000 0 0 2 &mpic 0 1 0 0
- 0000 0 0 3 &mpic 4 1 0 0
- 0000 0 0 4 &mpic 8 1 0 0
- >;
- ranges = <0x02000000 0 0xe0000000
- 0x02000000 0 0xe0000000
- 0 0x20000000
+ ranges = <0x02000000 0 0xb0000000
+ 0x02000000 0 0xb0000000
+ 0 0x08000000
0x01000000 0 0x00000000
- 0x01000000 0 0x00000000
+ 0x01000000 0 0xff030000
0 0x00010000>;
};
};
+
+ fsl,dpaa {
+ compatible = "fsl,p3041-dpaa", "fsl,dpaa";
+
+ ethernet at 0 {
+ compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet0>;
+ status="okay";
+ };
+ ethernet at 1 {
+ compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet1>;
+ status = "disabled";
+ };
+ ethernet at 2 {
+ compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet2>;
+ status = "disabled";
+ };
+ ethernet at 3 {
+ compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet3>;
+ status = "disabled";
+ };
+ ethernet at 4 {
+ compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet4>;
+ status = "okay";
+ };
+ ethernet at 5 {
+ compatible = "fsl,p3041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet5>;
+ status = "disabled";
+ };
+ };
+
+ chosen {
+ stdin = "serial0";
+ stdout = "serial0";
+ };
};
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/fdt/dts/p3041si.dtsi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/p3041si.dtsi Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,1339 @@
+/*
+ * P3041 Silicon Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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: head/sys/boot/fdt/dts/p3041si.dtsi 236024 2012-05-25 20:43:38Z raj $ */
+
+/dts-v1/;
+
+/ {
+ compatible = "fsl,P3041";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+ dcsr = &dcsr;
+
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ ethernet2 = &enet2;
+ ethernet3 = &enet3;
+ ethernet4 = &enet4;
+ ethernet5 = &enet5;
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ pci3 = &pci3;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ bman = &bman;
+ qman = &qman;
+ pme = &pme;
+ rman = &rman;
+ sdhc = &sdhc;
+ msi0 = &msi0;
+ msi1 = &msi1;
+ msi2 = &msi2;
+
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ sec_mon = &sec_mon;
+
+ fman0 = &fman0;
+ fman0_oh0 = &fman0_oh0;
+ fman0_oh1 = &fman0_oh1;
+ fman0_oh2 = &fman0_oh2;
+ fman0_oh3 = &fman0_oh3;
+ fman0_oh4 = &fman0_oh4;
+ fman0_oh5 = &fman0_oh5;
+ fman0_oh6 = &fman0_oh6;
+ fman0_rx0 = &fman0_rx0;
+ fman0_rx1 = &fman0_rx1;
+ fman0_rx2 = &fman0_rx2;
+ fman0_rx3 = &fman0_rx3;
+ fman0_rx4 = &fman0_rx4;
+ fman0_rx5 = &fman0_rx5;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: PowerPC,e500mc at 0 {
+ device_type = "cpu";
+ reg = <0>;
+ bus-frequency = <749999996>;
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu1: PowerPC,e500mc at 1 {
+ device_type = "cpu";
+ reg = <1>;
+ next-level-cache = <&L2_1>;
+ L2_1: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu2: PowerPC,e500mc at 2 {
+ device_type = "cpu";
+ reg = <2>;
+ next-level-cache = <&L2_2>;
+ L2_2: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu3: PowerPC,e500mc at 3 {
+ device_type = "cpu";
+ reg = <3>;
+ next-level-cache = <&L2_3>;
+ L2_3: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ };
+
+ dcsr: dcsr at f00000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,dcsr", "simple-bus";
+
+ dcsr-epu at 0 {
+ compatible = "fsl,dcsr-epu";
+ interrupts = <52 2 0 0
+ 84 2 0 0
+ 85 2 0 0>;
+ interrupt-parent = <&mpic>;
+ reg = <0x0 0x1000>;
+ };
+ dcsr-npc {
+ compatible = "fsl,dcsr-npc";
+ reg = <0x1000 0x1000 0x1000000 0x8000>;
+ };
+ dcsr-nxc at 2000 {
+ compatible = "fsl,dcsr-nxc";
+ reg = <0x2000 0x1000>;
+ };
+ dcsr-corenet {
+ compatible = "fsl,dcsr-corenet";
+ reg = <0x8000 0x1000 0xB0000 0x1000>;
+ };
+ dcsr-dpaa at 9000 {
+ compatible = "fsl,p43041-dcsr-dpaa", "fsl,dcsr-dpaa";
+ reg = <0x9000 0x1000>;
+ };
+ dcsr-ocn at 11000 {
+ compatible = "fsl,p43041-dcsr-ocn", "fsl,dcsr-ocn";
+ reg = <0x11000 0x1000>;
+ };
+ dcsr-ddr at 12000 {
+ compatible = "fsl,dcsr-ddr";
+ dev-handle = <&ddr>;
+ reg = <0x12000 0x1000>;
+ };
+ dcsr-nal at 18000 {
+ compatible = "fsl,p43041-dcsr-nal", "fsl,dcsr-nal";
+ reg = <0x18000 0x1000>;
+ };
+ dcsr-rcpm at 22000 {
+ compatible = "fsl,p43041-dcsr-rcpm", "fsl,dcsr-rcpm";
+ reg = <0x22000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy at 40000 {
+ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu0>;
+ reg = <0x40000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy at 41000 {
+ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu1>;
+ reg = <0x41000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy at 42000 {
+ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu2>;
+ reg = <0x42000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy at 43000 {
+ compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu3>;
+ reg = <0x43000 0x1000>;
+ };
+ };
+
+ bman-portals at ff4000000 {
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ compatible = "bman-portals";
+ ranges = <0x0 0xf 0xfde00000 0x200000>;
+ bman-portal at 0 {
+ cell-index = <0x0>;
+ compatible = "fsl,p3041-bman-portal", "fsl,bman-portal";
+ reg = <0x0 0x4000 0x100000 0x1000>;
+ interrupts = <105 2 0 0>;
+ };
+ bman-portal at 4000 {
+ cell-index = <0x1>;
+ compatible = "fsl,p3041-bman-portal", "fsl,bman-portal";
+ reg = <0x4000 0x4000 0x101000 0x1000>;
+ interrupts = <107 2 0 0>;
+ };
+ bman-portal at 8000 {
+ cell-index = <2>;
+ compatible = "fsl,p3041-bman-portal", "fsl,bman-portal";
+ reg = <0x8000 0x4000 0x102000 0x1000>;
+ interrupts = <109 2 0 0>;
+ };
+ bman-portal at c000 {
+ cell-index = <0x3>;
+ compatible = "fsl,p3041-bman-portal", "fsl,bman-portal";
+ reg = <0xc000 0x4000 0x103000 0x1000>;
+ interrupts = <111 2 0 0>;
+ };
+ bman-portal at 10000 {
+ cell-index = <0x4>;
+ compatible = "fsl,p3041-bman-portal", "fsl,bman-portal";
+ reg = <0x10000 0x4000 0x104000 0x1000>;
+ interrupts = <113 2 0 0>;
+ };
+ bman-portal at 14000 {
+ cell-index = <0x5>;
+ compatible = "fsl,p3041-bman-portal", "fsl,bman-portal";
+ reg = <0x14000 0x4000 0x105000 0x1000>;
+ interrupts = <115 2 0 0>;
+ };
+ bman-portal at 18000 {
+ cell-index = <0x6>;
+ compatible = "fsl,p3041-bman-portal", "fsl,bman-portal";
+ reg = <0x18000 0x4000 0x106000 0x1000>;
+ interrupts = <117 2 0 0>;
+ };
+ bman-portal at 1c000 {
+ cell-index = <0x7>;
+ compatible = "fsl,p3041-bman-portal", "fsl,bman-portal";
+ reg = <0x1c000 0x4000 0x107000 0x1000>;
+ interrupts = <119 2 0 0>;
+ };
+ bman-portal at 20000 {
+ cell-index = <0x8>;
+ compatible = "fsl,p3041-bman-portal", "fsl,bman-portal";
+ reg = <0x20000 0x4000 0x108000 0x1000>;
+ interrupts = <121 2 0 0>;
+ };
+ bman-portal at 24000 {
+ cell-index = <0x9>;
+ compatible = "fsl,p3041-bman-portal", "fsl,bman-portal";
+ reg = <0x24000 0x4000 0x109000 0x1000>;
+ interrupts = <123 2 0 0>;
+ };
+
+ buffer-pool at 0 {
+ compatible = "fsl,p3041-bpool", "fsl,bpool";
+ fsl,bpid = <0>;
+ fsl,bpool-cfg = <0 0x100 0 1 0 0x100>;
+ };
+ };
+
+ qman-portals at ff4200000 {
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ compatible = "qman-portals";
+ ranges = <0x0 0xf 0xfdc00000 0x200000>;
+ qportal0: qman-portal at 0 {
+ cell-index = <0x0>;
+ compatible = "fsl,p3041-qman-portal", "fsl,qman-portal";
+ reg = <0x0 0x4000 0x100000 0x1000>;
+ interrupts = <104 0x2 0 0>;
+ fsl,qman-channel-id = <0x0>;
+ };
+
+ qportal1: qman-portal at 4000 {
+ cell-index = <0x1>;
+ compatible = "fsl,p3041-qman-portal", "fsl,qman-portal";
+ reg = <0x4000 0x4000 0x101000 0x1000>;
+ interrupts = <106 0x2 0 0>;
+ fsl,qman-channel-id = <0x1>;
+ };
+
+ qportal2: qman-portal at 8000 {
+ cell-index = <0x2>;
+ compatible = "fsl,p3041-qman-portal", "fsl,qman-portal";
+ reg = <0x8000 0x4000 0x102000 0x1000>;
+ interrupts = <108 0x2 0 0>;
+ fsl,qman-channel-id = <0x2>;
+ };
+
+ qportal3: qman-portal at c000 {
+ cell-index = <0x3>;
+ compatible = "fsl,p3041-qman-portal", "fsl,qman-portal";
+ reg = <0xc000 0x4000 0x103000 0x1000>;
+ interrupts = <110 0x2 0 0>;
+ fsl,qman-channel-id = <0x3>;
+ };
+
+ qportal4: qman-portal at 10000 {
+ cell-index = <0x4>;
+ compatible = "fsl,p3041-qman-portal", "fsl,qman-portal";
+ reg = <0x10000 0x4000 0x104000 0x1000>;
+ interrupts = <112 0x2 0 0>;
+ fsl,qman-channel-id = <0x4>;
+ };
+
+ qportal5: qman-portal at 14000 {
+ cell-index = <0x5>;
+ compatible = "fsl,p3041-qman-portal", "fsl,qman-portal";
+ reg = <0x14000 0x4000 0x105000 0x1000>;
+ interrupts = <114 0x2 0 0>;
+ fsl,qman-channel-id = <0x5>;
+ };
+
+ qportal6: qman-portal at 18000 {
+ cell-index = <0x6>;
+ compatible = "fsl,p3041-qman-portal", "fsl,qman-portal";
+ reg = <0x18000 0x4000 0x106000 0x1000>;
+ interrupts = <116 0x2 0 0>;
+ fsl,qman-channel-id = <0x6>;
+ };
+
+ qportal7: qman-portal at 1c000 {
+ cell-index = <0x7>;
+ compatible = "fsl,p3041-qman-portal", "fsl,qman-portal";
+ reg = <0x1c000 0x4000 0x107000 0x1000>;
+ interrupts = <118 0x2 0 0>;
+ fsl,qman-channel-id = <0x7>;
+ };
+
+ qportal8: qman-portal at 20000 {
+ cell-index = <0x8>;
+ compatible = "fsl,p3041-qman-portal", "fsl,qman-portal";
+ reg = <0x20000 0x4000 0x108000 0x1000>;
+ interrupts = <120 0x2 0 0>;
+ fsl,qman-channel-id = <0x8>;
+ };
+
+ qportal9: qman-portal at 24000 {
+ cell-index = <0x9>;
+ compatible = "fsl,p3041-qman-portal", "fsl,qman-portal";
+ reg = <0x24000 0x4000 0x109000 0x1000>;
+ interrupts = <122 0x2 0 0>;
+ fsl,qman-channel-id = <0x9>;
+ };
+
+ qpool1: qman-pool at 1 {
+ cell-index = <1>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x21>;
+ };
+
+ qpool2: qman-pool at 2 {
+ cell-index = <2>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x22>;
+ };
+
+ qpool3: qman-pool at 3 {
+ cell-index = <3>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x23>;
+ };
+
+ qpool4: qman-pool at 4 {
+ cell-index = <4>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x24>;
+ };
+
+ qpool5: qman-pool at 5 {
+ cell-index = <5>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x25>;
+ };
+
+ qpool6: qman-pool at 6 {
+ cell-index = <6>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x26>;
+ };
+
+ qpool7: qman-pool at 7 {
+ cell-index = <7>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x27>;
+ };
+
+ qpool8: qman-pool at 8 {
+ cell-index = <8>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x28>;
+ };
+
+ qpool9: qman-pool at 9 {
+ cell-index = <9>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x29>;
+ };
+
+ qpool10: qman-pool at 10 {
+ cell-index = <10>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2a>;
+ };
+
+ qpool11: qman-pool at 11 {
+ cell-index = <11>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2b>;
+ };
+
+ qpool12: qman-pool at 12 {
+ cell-index = <12>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2c>;
+ };
+
+ qpool13: qman-pool at 13 {
+ cell-index = <13>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2d>;
+ };
+
+ qpool14: qman-pool at 14 {
+ cell-index = <14>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2e>;
+ };
+
+ qpool15: qman-pool at 15 {
+ cell-index = <15>;
+ compatible = "fsl,p3041-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2f>;
+ };
+ };
+
+ soc: soc at ffe000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "simple-bus";
+
+ bus-frequency = <0>; // Filled out by kernel.
+
+ ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+ reg = <0xf 0xfe000000 0 0x00001000>;
+
+ soc-sram-error {
+ compatible = "fsl,soc-sram-error";
+ interrupts = <16 2 1 29>;
+ };
+
+ corenet-law at 0 {
+ compatible = "fsl,corenet-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <32>;
+ };
+
+ ddr: memory-controller at 8000 {
+ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+ reg = <0x8000 0x1000>;
+ interrupts = <16 2 1 23>;
+ };
+
+ cpc: l3-cache-controller at 10000 {
+ compatible = "fsl,p3041-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+ reg = <0x10000 0x1000>;
+ interrupts = <16 2 1 27>;
+ };
+
+ corenet-cf at 18000 {
+ compatible = "fsl,corenet-cf";
+ reg = <0x18000 0x1000>;
+ interrupts = <16 2 1 31>;
+ fsl,ccf-num-csdids = <32>;
+ fsl,ccf-num-snoopids = <32>;
+ };
+
+ iommu at 20000 {
+ compatible = "fsl,pamu-v1.0", "fsl,pamu";
+ reg = <0x20000 0x4000>;
+ interrupts = <
+ 24 2 0 0
+ 16 2 1 30>;
+ };
+
+ mpic: pic at 40000 {
+ clock-frequency = <0>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <4>;
+ reg = <0x40000 0x40000>;
+ compatible = "fsl,mpic", "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ msi0: msi at 41600 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41600 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe0 0 0 0
+ 0xe1 0 0 0
+ 0xe2 0 0 0
+ 0xe3 0 0 0
+ 0xe4 0 0 0
+ 0xe5 0 0 0
+ 0xe6 0 0 0
+ 0xe7 0 0 0>;
+ };
+
+ msi1: msi at 41800 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41800 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe8 0 0 0
+ 0xe9 0 0 0
+ 0xea 0 0 0
+ 0xeb 0 0 0
+ 0xec 0 0 0
+ 0xed 0 0 0
+ 0xee 0 0 0
+ 0xef 0 0 0>;
+ };
+
+ msi2: msi at 41a00 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41a00 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xf0 0 0 0
+ 0xf1 0 0 0
+ 0xf2 0 0 0
+ 0xf3 0 0 0
+ 0xf4 0 0 0
+ 0xf5 0 0 0
+ 0xf6 0 0 0
+ 0xf7 0 0 0>;
+ };
+
+ guts: global-utilities at e0000 {
+ compatible = "fsl,qoriq-device-config-1.0";
+ reg = <0xe0000 0xe00>;
+ fsl,has-rstcr;
+ #sleep-cells = <1>;
+ fsl,liodn-bits = <12>;
+ };
+
+ pins: global-utilities at e0e00 {
+ compatible = "fsl,qoriq-pin-control-1.0";
+ reg = <0xe0e00 0x200>;
+ #sleep-cells = <2>;
+ };
+
+ clockgen: global-utilities at e1000 {
+ compatible = "fsl,p3041-clockgen", "fsl,qoriq-clockgen-1.0";
+ reg = <0xe1000 0x1000>;
+ clock-frequency = <0>;
+ };
+
+ rcpm: global-utilities at e2000 {
+ compatible = "fsl,qoriq-rcpm-1.0";
+ reg = <0xe2000 0x1000>;
+ #sleep-cells = <1>;
+ };
+
+ sfp: sfp at e8000 {
+ compatible = "fsl,p3041-sfp", "fsl,qoriq-sfp-1.0";
+ reg = <0xe8000 0x1000>;
+ };
+
+ serdes: serdes at ea000 {
+ compatible = "fsl,p3041-serdes";
+ reg = <0xea000 0x1000>;
+ };
+
+ dma0: dma at 100300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p3041-dma", "fsl,eloplus-dma";
+ reg = <0x100300 0x4>;
+ ranges = <0x0 0x100100 0x200>;
+ cell-index = <0>;
+ dma-channel at 0 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <28 2 0 0>;
+ };
+ dma-channel at 80 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <29 2 0 0>;
+ };
+ dma-channel at 100 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <30 2 0 0>;
+ };
+ dma-channel at 180 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <31 2 0 0>;
+ };
+ };
+
+ dma1: dma at 101300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p3041-dma", "fsl,eloplus-dma";
+ reg = <0x101300 0x4>;
+ ranges = <0x0 0x101100 0x200>;
+ cell-index = <1>;
+ dma-channel at 0 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <32 2 0 0>;
+ };
+ dma-channel at 80 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <33 2 0 0>;
+ };
+ dma-channel at 100 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <34 2 0 0>;
+ };
+ dma-channel at 180 {
+ compatible = "fsl,p3041-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <35 2 0 0>;
+ };
+ };
+
+ spi at 110000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,p3041-espi", "fsl,mpc8536-espi";
+ reg = <0x110000 0x1000>;
+ interrupts = <53 0x2 0 0>;
+ fsl,espi-num-chipselects = <4>;
+ };
+
+ sdhc: sdhc at 114000 {
+ compatible = "fsl,p3041-esdhc", "fsl,esdhc";
+ reg = <0x114000 0x1000>;
+ interrupts = <48 2 0 0>;
+ sdhci,auto-cmd12;
+ clock-frequency = <0>;
+ };
+
+ i2c at 118000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x118000 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c at 118100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x118100 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c at 119000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <2>;
+ compatible = "fsl-i2c";
+ reg = <0x119000 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ i2c at 119100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <3>;
+ compatible = "fsl-i2c";
+ reg = <0x119100 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ serial0: serial at 11c500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial1: serial at 11c600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial2: serial at 11d500 {
+ cell-index = <2>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ serial3: serial at 11d600 {
+ cell-index = <3>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ gpio0: gpio at 130000 {
+ compatible = "fsl,p3041-gpio", "fsl,qoriq-gpio";
+ reg = <0x130000 0x1000>;
+ interrupts = <55 2 0 0>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ };
+
+ rman: rman at 1e0000 {
+ compatible = "fsl,rman";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x1e0000 0x20000>;
+ reg = <0x1e0000 0x20000>;
+ interrupts = <16 2 1 11>; /* err_irq */
+ fsl,qman-channels-id = <0x62 0x63>;
+
+ inbound-block at 0 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x0 0x800>;
+ };
+ global-cfg at b00 {
+ compatible = "fsl,rman-global-cfg";
+ reg = <0xb00 0x500>;
+ };
+ inbound-block at 1000 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x1000 0x800>;
+ };
+ inbound-block at 2000 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x2000 0x800>;
+ };
+ inbound-block at 3000 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x3000 0x800>;
+ };
+ };
+
+ usb0: usb at 210000 {
+ compatible = "fsl,p3041-usb2-mph",
+ "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+ reg = <0x210000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <44 0x2 0 0>;
+ phy_type = "utmi";
+ port0;
+ };
+
+ usb1: usb at 211000 {
+ compatible = "fsl,p3041-usb2-dr",
+ "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+ reg = <0x211000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <45 0x2 0 0>;
+ dr_mode = "host";
+ phy_type = "utmi";
+ };
+
+ sata at 220000 {
+ compatible = "fsl,p3041-sata", "fsl,pq-sata-v2";
+ reg = <0x220000 0x1000>;
+ interrupts = <68 0x2 0 0>;
+ };
+
+ sata at 221000 {
+ compatible = "fsl,p3041-sata", "fsl,pq-sata-v2";
+ reg = <0x221000 0x1000>;
+ interrupts = <69 0x2 0 0>;
+ };
+
+ crypto: crypto at 300000 {
+ compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupts = <92 2 0 0>;
+
+ sec_jr0: jr at 1000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupts = <88 2 0 0>;
+ };
+
+ sec_jr1: jr at 2000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupts = <89 2 0 0>;
+ };
+
+ sec_jr2: jr at 3000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupts = <90 2 0 0>;
+ };
+
+ sec_jr3: jr at 4000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupts = <91 2 0 0>;
+ };
+
+ rtic at 6000 {
+ compatible = "fsl,sec-v4.2-rtic",
+ "fsl,sec-v4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a at 0 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b at 20 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c at 40 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d at 60 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ sec_mon: sec_mon at 314000 {
+ compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupts = <93 2 0 0>;
+ };
+
+ pme: pme at 316000 {
+ compatible = "fsl,pme";
+ reg = <0x316000 0x10000>;
+ /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
+ /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
+ interrupts = <16 2 1 5>;
+ };
+
+ qman: qman at 318000 {
+ compatible = "fsl,p3041-qman", "fsl,qman";
+ reg = <0x318000 0x1000>;
+ interrupts = <16 2 1 3>;
+ /* Commented out, use default allocation */
+ /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
+ /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
+ };
+
+ bman: bman at 31a000 {
+ compatible = "fsl,p3041-bman", "fsl,bman";
+ reg = <0x31a000 0x1000>;
+ interrupts = <16 2 1 2>;
+ /* Same as fsl,qman-*, use default allocation */
+ /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
+ };
+
+ fman0: fman at 400000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cell-index = <0>;
+ compatible = "fsl,p3041-fman", "fsl,fman", "simple-bus";
+ ranges = <0 0x400000 0x100000>;
+ reg = <0x400000 0x100000>;
+ clock-frequency = <0>;
+ interrupts = <
+ 96 2 0 0
+ 16 2 1 1>;
+
+ cc at 0 {
+ compatible = "fsl,p3041-fman-cc", "fsl,fman-cc";
+ };
+
+ parser at c7000 {
+ compatible = "fsl,p3041-fman-parser", "fsl,fman-parser";
+ reg = <0xc7000 0x1000>;
+ };
+
+ keygen at c1000 {
+ compatible = "fsl,p3041-fman-keygen", "fsl,fman-keygen";
+ reg = <0xc1000 0x1000>;
+ };
+
+ policer at c0000 {
+ compatible = "fsl,p3041-fman-policer", "fsl,fman-policer";
+ reg = <0xc0000 0x1000>;
+ };
+
+ muram at 0 {
+ compatible = "fsl,p3041-fman-muram", "fsl,fman-muram";
+ reg = <0x0 0x28000>;
+ };
+
+ bmi at 80000 {
+ compatible = "fsl,p3041-fman-bmi", "fsl,fman-bmi";
+ reg = <0x80000 0x400>;
+ };
+
+ qmi at 80400 {
+ compatible = "fsl,p3041-fman-qmi", "fsl,fman-qmi";
+ reg = <0x80400 0x400>;
+ };
+
+ fman0_rx0: port at 88000 {
+ cell-index = <0>;
+ compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x88000 0x1000>;
+ };
+ fman0_rx1: port at 89000 {
+ cell-index = <1>;
+ compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x89000 0x1000>;
+ };
+ fman0_rx2: port at 8a000 {
+ cell-index = <2>;
+ compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x8a000 0x1000>;
+ };
+ fman0_rx3: port at 8b000 {
+ cell-index = <3>;
+ compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x8b000 0x1000>;
+ };
+ fman0_rx4: port at 8c000 {
+ cell-index = <4>;
+ compatible = "fsl,p3041-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x8c000 0x1000>;
+ };
+ fman0_rx5: port at 90000 {
+ cell-index = <0>;
+ compatible = "fsl,p3041-fman-port-10g-rx", "fsl,fman-port-10g-rx";
+ reg = <0x90000 0x1000>;
+ };
+
+ fman0_tx5: port at b0000 {
+ cell-index = <0>;
+ compatible = "fsl,p3041-fman-port-10g-tx", "fsl,fman-port-10g-tx";
+ reg = <0xb0000 0x1000>;
+ fsl,qman-channel-id = <0x40>;
+ };
+ fman0_tx0: port at a8000 {
+ cell-index = <0>;
+ compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xa8000 0x1000>;
+ fsl,qman-channel-id = <0x41>;
+ };
+ fman0_tx1: port at a9000 {
+ cell-index = <1>;
+ compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xa9000 0x1000>;
+ fsl,qman-channel-id = <0x42>;
+ };
+ fman0_tx2: port at aa000 {
+ cell-index = <2>;
+ compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xaa000 0x1000>;
+ fsl,qman-channel-id = <0x43>;
+ };
+ fman0_tx3: port at ab000 {
+ cell-index = <3>;
+ compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xab000 0x1000>;
+ fsl,qman-channel-id = <0x44>;
+ };
+ fman0_tx4: port at ac000 {
+ cell-index = <4>;
+ compatible = "fsl,p3041-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xac000 0x1000>;
+ fsl,qman-channel-id = <0x45>;
+ };
+
+ fman0_oh0: port at 81000 {
+ cell-index = <0>;
+ compatible = "fsl,p3041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x81000 0x1000>;
+ fsl,qman-channel-id = <0x46>;
+ };
+ fman0_oh1: port at 82000 {
+ cell-index = <1>;
+ compatible = "fsl,p3041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x82000 0x1000>;
+ fsl,qman-channel-id = <0x47>;
+ };
+ fman0_oh2: port at 83000 {
+ cell-index = <2>;
+ compatible = "fsl,p3041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x83000 0x1000>;
+ fsl,qman-channel-id = <0x48>;
+ };
+ fman0_oh3: port at 84000 {
+ cell-index = <3>;
+ compatible = "fsl,p3041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x84000 0x1000>;
+ fsl,qman-channel-id = <0x49>;
+ };
+ fman0_oh4: port at 85000 {
+ cell-index = <4>;
+ compatible = "fsl,p3041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x85000 0x1000>;
+ fsl,qman-channel-id = <0x4a>;
+ };
+ fman0_oh5: port at 86000 {
+ cell-index = <5>;
+ compatible = "fsl,p3041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x86000 0x1000>;
+ fsl,qman-channel-id = <0x4b>;
+ };
+ fman0_oh6: port at 87000 {
+ cell-index = <6>;
+ compatible = "fsl,p3041-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x87000 0x1000>;
+ };
+
+ enet0: ethernet at e0000 {
+ cell-index = <0>;
+ compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe0000 0x1000>;
+ fsl,port-handles = <&fman0_rx0 &fman0_tx0>;
+ ptimer-handle = <&ptp_timer0>;
+ };
+
+ mdio0: mdio at e1120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-mdio";
+ reg = <0xe1120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet1: ethernet at e2000 {
+ cell-index = <1>;
+ compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe2000 0x1000>;
+ fsl,port-handles = <&fman0_rx1 &fman0_tx1>;
+ ptimer-handle = <&ptp_timer0>;
+ };
+
+ mdio at e3120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe3120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet2: ethernet at e4000 {
+ cell-index = <2>;
+ compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe4000 0x1000>;
+ fsl,port-handles = <&fman0_rx2 &fman0_tx2>;
+ ptimer-handle = <&ptp_timer0>;
+ };
+
+ mdio at e5120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe5120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet3: ethernet at e6000 {
+ cell-index = <3>;
+ compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe6000 0x1000>;
+ fsl,port-handles = <&fman0_rx3 &fman0_tx3>;
+ };
+
+ mdio at e7120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe7120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet4: ethernet at e8000 {
+ cell-index = <4>;
+ compatible = "fsl,p3041-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe8000 0x1000>;
+ fsl,port-handles = <&fman0_rx4 &fman0_tx4>;
+ ptimer-handle = <&ptp_timer0>;
+ };
+
+ mdio at e9120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe9120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet5: ethernet at f0000 {
+ cell-index = <0>;
+ compatible = "fsl,p3041-fman-10g-mac", "fsl,fman-10g-mac";
+ reg = <0xf0000 0x1000>;
+ fsl,port-handles = <&fman0_rx5 &fman0_tx5>;
+ };
+
+ mdio at f1000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-xmdio";
+ reg = <0xf1000 0x1000>;
+ interrupts = <100 1 0 0>;
+ };
+
+ ptp_timer0: rtc at fe000 {
+ compatible = "fsl,fman-rtc";
+ reg = <0xfe000 0x1000>;
+ };
+ };
+ };
+
+ rapidio at ffe0c0000 {
+ compatible = "fsl,srio";
+ interrupts = <16 2 1 11>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ port1 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ cell-index = <1>;
+ };
+
+ port2 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ cell-index = <2>;
+ };
+ };
+
+ localbus at ffe124000 {
+ compatible = "fsl,p3041-rev1.0-elbc", "simple-bus", "fsl,elbc";
+ interrupts = <
+ 25 2 0 0
+ 16 2 1 19
+ >;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ };
+
+ pci0: pcie at ffe200000 {
+ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ status = "okay";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi0>;
+ interrupts = <16 2 1 15>;
+
+ pcie at 0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 15>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 40 1 0 0
+ 0000 0 0 2 &mpic 1 1 0 0
+ 0000 0 0 3 &mpic 2 1 0 0
+ 0000 0 0 4 &mpic 3 1 0 0
+ >;
+ };
+ };
+
+ pci1: pcie at ffe201000 {
+ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ status = "disabled";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi1>;
+ interrupts = <16 2 1 14>;
+ pcie at 0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 14>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 41 1 0 0
+ 0000 0 0 2 &mpic 5 1 0 0
+ 0000 0 0 3 &mpic 6 1 0 0
+ 0000 0 0 4 &mpic 7 1 0 0
+ >;
+ };
+ };
+
+ pci2: pcie at ffe202000 {
+ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ status = "okay";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi2>;
+ interrupts = <16 2 1 13>;
+ pcie at 0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 13>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 42 1 0 0
+ 0000 0 0 2 &mpic 9 1 0 0
+ 0000 0 0 3 &mpic 10 1 0 0
+ 0000 0 0 4 &mpic 11 1 0 0
+ >;
+ };
+ };
+
+ pci3: pcie at ffe203000 {
+ compatible = "fsl,p3041-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ status = "disabled";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi2>;
+ interrupts = <16 2 1 12>;
+ pcie at 0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 12>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 43 1 0 0
+ 0000 0 0 2 &mpic 0 1 0 0
+ 0000 0 0 3 &mpic 4 1 0 0
+ 0000 0 0 4 &mpic 8 1 0 0
+ >;
+ };
+ };
+};
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/fdt/dts/p5020ds.dts
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/p5020ds.dts Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,583 @@
+/*
+ * P5020DS Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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: head/sys/boot/fdt/dts/p5020ds.dts 236024 2012-05-25 20:43:38Z raj $ */
+
+/include/ "p5020si.dtsi"
+
+/ {
+ model = "fsl,P5020DS";
+ compatible = "fsl,P5020DS";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ phy_rgmii_0 = &phy_rgmii_0;
+ phy_rgmii_1 = &phy_rgmii_1;
+ phy_sgmii_1c = &phy_sgmii_1c;
+ phy_sgmii_1d = &phy_sgmii_1d;
+ phy_sgmii_1e = &phy_sgmii_1e;
+ phy_sgmii_1f = &phy_sgmii_1f;
+ phy_xgmii_1 = &phy_xgmii_1;
+ phy_xgmii_2 = &phy_xgmii_2;
+ emi1_rgmii = &hydra_mdio_rgmii;
+ emi1_sgmii = &hydra_mdio_sgmii;
+ emi2_xgmii = &hydra_mdio_xgmii;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x00000000 0x80000000>;
+ };
+
+ dcsr: dcsr at f00000000 {
+ ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+ };
+
+ bman-portals at ff4000000 {
+ bman-portal at 0 {
+ cpu-handle = <&cpu0>;
+ };
+ bman-portal at 4000 {
+ cpu-handle = <&cpu1>;
+ };
+ bman-portal at 8000 {
+ };
+ bman-portal at c000 {
+ };
+ bman-portal at 10000 {
+ };
+ bman-portal at 14000 {
+ };
+ bman-portal at 18000 {
+ };
+ bman-portal at 1c000 {
+ };
+ bman-portal at 20000 {
+ };
+ bman-portal at 24000 {
+ };
+
+ buffer-pool at 0 {
+ compatible = "fsl,p5020-bpool", "fsl,bpool";
+ fsl,bpid = <0>;
+ fsl,bpool-cfg = <0 0x100 0 1 0 0x100>;
+ };
+ };
+
+ qman-portals at ff4200000 {
+ qportal0: qman-portal at 0 {
+ cpu-handle = <&cpu0>;
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal1: qman-portal at 4000 {
+ cpu-handle = <&cpu1>;
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal2: qman-portal at 8000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal3: qman-portal at c000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal4: qman-portal at 10000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal5: qman-portal at 14000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal6: qman-portal at 18000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal7: qman-portal at 1c000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal8: qman-portal at 20000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+
+ qportal9: qman-portal at 24000 {
+ fsl,qman-pool-channels = <&qpool1 &qpool2 &qpool3
+ &qpool4 &qpool5 &qpool6
+ &qpool7 &qpool8 &qpool9
+ &qpool10 &qpool11 &qpool12
+ &qpool13 &qpool14 &qpool15>;
+ };
+ };
+
+ soc: soc at ffe000000 {
+ spi at 110000 {
+ flash at 0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,s25sl12801";
+ reg = <0>;
+ spi-max-frequency = <40000000>; /* input clock */
+ partition at u-boot {
+ label = "u-boot";
+ reg = <0x00000000 0x00100000>;
+ read-only;
+ };
+ partition at kernel {
+ label = "kernel";
+ reg = <0x00100000 0x00500000>;
+ read-only;
+ };
+ partition at dtb {
+ label = "dtb";
+ reg = <0x00600000 0x00100000>;
+ read-only;
+ };
+ partition at fs {
+ label = "file system";
+ reg = <0x00700000 0x00900000>;
+ };
+ };
+ };
+
+ i2c at 118100 {
+ eeprom at 51 {
+ compatible = "at24,24c256";
+ reg = <0x51>;
+ };
+ eeprom at 52 {
+ compatible = "at24,24c256";
+ reg = <0x52>;
+ };
+ };
+
+ i2c at 119100 {
+ rtc at 68 {
+ compatible = "dallas,ds3232";
+ reg = <0x68>;
+ interrupts = <0x1 0x1 0 0>;
+ };
+ };
+
+ pme: pme at 316000 {
+ /* Commented out, use default allocation */
+ /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
+ /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
+ };
+
+ qman: qman at 318000 {
+ /* Commented out, use default allocation */
+ /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
+ /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
+ };
+
+ bman: bman at 31a000 {
+ /* Same as fsl,qman-*, use default allocation */
+ /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
+ };
+
+ fman0: fman at 400000 {
+ enet0: ethernet at e0000 {
+ tbi-handle = <&tbi0>;
+ phy-handle = <&phy_rgmii_0>;
+ phy-connection-type = "rgmii";
+ };
+
+ mdio0: mdio at e1120 {
+ tbi0: tbi-phy at 8 {
+ reg = <0x8>;
+ device_type = "tbi-phy";
+ };
+
+ /*
+ * Virtual MDIO for the two on-board RGMII
+ * ports. The fsl,hydra-mdio-muxval property
+ * is already correct.
+ */
+ hydra_mdio_rgmii: hydra-mdio-rgmii {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,hydra-mdio";
+ fsl,mdio-handle = <&mdio0>;
+ fsl,hydra-mdio-muxval = <0x00>;
+ status = "disabled";
+
+ phy_rgmii_0: ethernet-phy at 0 {
+ reg = <0x0>;
+ };
+ phy_rgmii_1: ethernet-phy at 1 {
+ reg = <0x1>;
+ };
+ };
+
+ /*
+ * Virtual MDIO for the four-port SGMII card.
+ * The fsl,hydra-mdio-muxval property will be
+ * fixed-up by U-Boot based on the slot that
+ * the SGMII card is in.
+ *
+ * Note: we do not support DTSEC5 connected to
+ * SGMII, so this is the only SGMII node.
+ */
+ hydra_mdio_sgmii: hydra-mdio-sgmii {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,hydra-mdio";
+ fsl,mdio-handle = <&mdio0>;
+ fsl,hydra-mdio-muxval = <0x00>;
+ status = "disabled";
+
+ phy_sgmii_1c: ethernet-phy at 1c {
+ reg = <0x1c>;
+ };
+ phy_sgmii_1d: ethernet-phy at 1d {
+ reg = <0x1d>;
+ };
+ phy_sgmii_1e: ethernet-phy at 1e {
+ reg = <0x1e>;
+ };
+ phy_sgmii_1f: ethernet-phy at 1f {
+ reg = <0x1f>;
+ };
+ };
+ };
+
+ enet1: ethernet at e2000 {
+ tbi-handle = <&tbi1>;
+ phy-handle = <&phy_sgmii_1d>;
+ phy-connection-type = "sgmii";
+ };
+
+ mdio at e3120 {
+ tbi1: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet2: ethernet at e4000 {
+ tbi-handle = <&tbi2>;
+ phy-handle = <&phy_sgmii_1e>;
+ phy-connection-type = "sgmii";
+ };
+
+ mdio at e5120 {
+ tbi2: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet3: ethernet at e6000 {
+ tbi-handle = <&tbi3>;
+ phy-handle = <&phy_sgmii_1f>;
+ phy-connection-type = "sgmii";
+ };
+
+ mdio at e7120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe7120 0xee0>;
+ interrupts = <100 1 0 0>;
+
+ tbi3: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet4: ethernet at e8000 {
+ tbi-handle = <&tbi4>;
+ phy-handle = <&phy_rgmii_1>;
+ phy-connection-type = "rgmii";
+ };
+
+ mdio at e9120 {
+ tbi4: tbi-phy at 8 {
+ reg = <8>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet5: ethernet at f0000 {
+ /*
+ * phy-handle will be updated by U-Boot to
+ * reflect the actual slot the XAUI card is in.
+ */
+ phy-handle = <&phy_xgmii_1>;
+ phy-connection-type = "xgmii";
+ };
+
+ /*
+ * We only support one XAUI card, so the MDIO muxing
+ * is set by U-Boot, and Linux never touches it.
+ * Therefore, we don't need a virtual MDIO node.
+ * However, the phy address depends on the slot, so
+ * only one of the ethernet-phy nodes below will be
+ * used.
+ */
+ hydra_mdio_xgmii: mdio at f1000 {
+ status = "disabled";
+
+ /* XAUI card in slot 1 */
+ phy_xgmii_1: ethernet-phy at 4 {
+ reg = <0x4>;
+ };
+
+ /* XAUI card in slot 2 */
+ phy_xgmii_2: ethernet-phy at 0 {
+ reg = <0x0>;
+ };
+ };
+ };
+ };
+
+ rapidio at ffe0c0000 {
+ reg = <0xf 0xfe0c0000 0 0x11000>;
+
+ port1 {
+ ranges = <0 0 0xc 0x20000000 0 0x10000000>;
+ };
+ port2 {
+ ranges = <0 0 0xc 0x30000000 0 0x10000000>;
+ };
+ };
+
+ localbus at ffe124000 {
+ reg = <0xf 0xfe124000 0 0x1000>;
+ ranges = <0 0 0xf 0xb8000000 0x04000000>;
+
+ flash at 0,0 {
+ compatible = "cfi-flash";
+ /*
+ * Map 64Mb of 128MB NOR flash memory. Since highest
+ * line of address of NOR flash memory are set by
+ * FPGA, memory are divided into two pages equal to
+ * 64MB. One of the pages can be accessed at once.
+ */
+ reg = <0 0 0x04000000>;
+ bank-width = <2>;
+ device-width = <2>;
+ };
+
+ nand at 2,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,elbc-fcm-nand";
+ reg = <0x2 0x0 0x40000>;
+
+ partition at 0 {
+ label = "NAND U-Boot Image";
+ reg = <0x0 0x02000000>;
+ read-only;
+ };
+
+ partition at 2000000 {
+ label = "NAND Root File System";
+ reg = <0x02000000 0x10000000>;
+ };
+
+ partition at 12000000 {
+ label = "NAND Compressed RFS Image";
+ reg = <0x12000000 0x08000000>;
+ };
+
+ partition at 1a000000 {
+ label = "NAND Linux Kernel Image";
+ reg = <0x1a000000 0x04000000>;
+ };
+
+ partition at 1e000000 {
+ label = "NAND DTB Image";
+ reg = <0x1e000000 0x01000000>;
+ };
+
+ partition at 1f000000 {
+ label = "NAND Writable User area";
+ reg = <0x1f000000 0x21000000>;
+ };
+ };
+
+ board-control at 3,0 {
+ compatible = "fsl,p5020ds-fpga", "fsl,fpga-ngpixis";
+ reg = <3 0 0x30>;
+ };
+ };
+
+ pci0: pcie at ffe200000 {
+ reg = <0xf 0xfe200000 0 0x1000>;
+ ranges = <0x02000000 0 0x80000000 0x0 0x80000000 0x0 0x10000000
+ 0x01000000 0 0x00000000 0x0 0xff000000 0x0 0x00010000>;
+ pcie at 0 {
+ ranges = <0x02000000 0 0x80000000
+ 0x02000000 0 0x80000000
+ 0 0x10000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0xff000000
+ 0 0x00010000>;
+ };
+ };
+
+ pci1: pcie at ffe201000 {
+ reg = <0xf 0xfe201000 0 0x1000>;
+ ranges = <0x02000000 0x0 0x90000000 0x0 0x90000000 0x0 0x10000000
+ 0x01000000 0x0 0x00000000 0x0 0xff010000 0x0 0x00010000>;
+ pcie at 0 {
+ ranges = <0x02000000 0 0x90000000
+ 0x02000000 0 0x90000000
+ 0 0x10000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0xff010000
+ 0 0x00010000>;
+ };
+ };
+
+ pci2: pcie at ffe202000 {
+ reg = <0xf 0xfe202000 0 0x1000>;
+ ranges = <0x02000000 0 0xa0000000 0x0 0xa0000000 0 0x10000000
+ 0x01000000 0 0x00000000 0x0 0xff020000 0 0x00010000>;
+ pcie at 0 {
+ ranges = <0x02000000 0 0xa0000000
+ 0x02000000 0 0xa0000000
+ 0 0x10000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0xff020000
+ 0 0x00010000>;
+ };
+ };
+
+ pci3: pcie at ffe203000 {
+ reg = <0xf 0xfe203000 0 0x1000>;
+ ranges = <0x02000000 0 0xb0000000 0x0 0xb0000000 0 0x08000000
+ 0x01000000 0 0x00000000 0x0 0xff030000 0 0x00010000>;
+ pcie at 0 {
+ ranges = <0x02000000 0 0xb0000000
+ 0x02000000 0 0xb0000000
+ 0 0x08000000
+
+ 0x01000000 0 0x00000000
+ 0x01000000 0 0xff030000
+ 0 0x00010000>;
+ };
+ };
+
+ fsl,dpaa {
+ compatible = "fsl,p5020-dpaa", "fsl,dpaa";
+
+ ethernet at 0 {
+ compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet0>;
+ status = "okay";
+ };
+ ethernet at 1 {
+ compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet1>;
+ status = "disabled";
+ };
+ ethernet at 2 {
+ compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet2>;
+ status = "disabled";
+ };
+ ethernet at 3 {
+ compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet3>;
+ status = "disabled";
+ };
+ ethernet at 4 {
+ compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet4>;
+ status = "okay";
+ };
+ ethernet at 5 {
+ compatible = "fsl,p5020-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,qman-channel = <&qpool1>;
+ fsl,fman-mac = <&enet5>;
+ status = "disabled";
+ };
+ };
+
+ chosen {
+ stdin = "serial0";
+ stdout = "serial0";
+ };
+};
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/fdt/dts/p5020si.dtsi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/p5020si.dtsi Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,1389 @@
+/*
+ * P5020 Silicon Device Tree Source
+ *
+ * Copyright 2010-2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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: head/sys/boot/fdt/dts/p5020si.dtsi 236024 2012-05-25 20:43:38Z raj $ */
+
+/dts-v1/;
+
+/ {
+ compatible = "fsl,P5020";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+ dcsr = &dcsr;
+
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ ethernet2 = &enet2;
+ ethernet3 = &enet3;
+ ethernet4 = &enet4;
+ ethernet5 = &enet5;
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ pci3 = &pci3;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ bman = &bman;
+ qman = &qman;
+ pme = &pme;
+ rman = &rman;
+ sdhc = &sdhc;
+ msi0 = &msi0;
+ msi1 = &msi1;
+ msi2 = &msi2;
+
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ sec_mon = &sec_mon;
+
+ raideng = &raideng;
+ raideng_jr0 = &raideng_jr0;
+ raideng_jr1 = &raideng_jr1;
+ raideng_jr2 = &raideng_jr2;
+ raideng_jr3 = &raideng_jr3;
+
+ fman0 = &fman0;
+ fman0_oh0 = &fman0_oh0;
+ fman0_oh1 = &fman0_oh1;
+ fman0_oh2 = &fman0_oh2;
+ fman0_oh3 = &fman0_oh3;
+ fman0_oh4 = &fman0_oh4;
+ fman0_oh5 = &fman0_oh5;
+ fman0_oh6 = &fman0_oh6;
+ fman0_rx0 = &fman0_rx0;
+ fman0_rx1 = &fman0_rx1;
+ fman0_rx2 = &fman0_rx2;
+ fman0_rx3 = &fman0_rx3;
+ fman0_rx4 = &fman0_rx4;
+ fman0_rx5 = &fman0_rx5;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: PowerPC,e5500 at 0 {
+ device_type = "cpu";
+ reg = <0>;
+ bus-frequency = <799999998>;
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu1: PowerPC,e5500 at 1 {
+ device_type = "cpu";
+ reg = <1>;
+ next-level-cache = <&L2_1>;
+ L2_1: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ };
+
+ dcsr: dcsr at f00000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,dcsr", "simple-bus";
+
+ dcsr-epu at 0 {
+ compatible = "fsl,dcsr-epu";
+ interrupts = <52 2 0 0
+ 84 2 0 0
+ 85 2 0 0>;
+ interrupt-parent = <&mpic>;
+ reg = <0x0 0x1000>;
+ };
+ dcsr-npc {
+ compatible = "fsl,dcsr-npc";
+ reg = <0x1000 0x1000 0x1000000 0x8000>;
+ };
+ dcsr-nxc at 2000 {
+ compatible = "fsl,dcsr-nxc";
+ reg = <0x2000 0x1000>;
+ };
+ dcsr-corenet {
+ compatible = "fsl,dcsr-corenet";
+ reg = <0x8000 0x1000 0xB0000 0x1000>;
+ };
+ dcsr-dpaa at 9000 {
+ compatible = "fsl,p5020-dcsr-dpaa", "fsl,dcsr-dpaa";
+ reg = <0x9000 0x1000>;
+ };
+ dcsr-ocn at 11000 {
+ compatible = "fsl,p5020-dcsr-ocn", "fsl,dcsr-ocn";
+ reg = <0x11000 0x1000>;
+ };
+ dcsr-ddr at 12000 {
+ compatible = "fsl,dcsr-ddr";
+ dev-handle = <&ddr1>;
+ reg = <0x12000 0x1000>;
+ };
+ dcsr-ddr at 13000 {
+ compatible = "fsl,dcsr-ddr";
+ dev-handle = <&ddr2>;
+ reg = <0x13000 0x1000>;
+ };
+ dcsr-nal at 18000 {
+ compatible = "fsl,p5020-dcsr-nal", "fsl,dcsr-nal";
+ reg = <0x18000 0x1000>;
+ };
+ dcsr-rcpm at 22000 {
+ compatible = "fsl,p5020-dcsr-rcpm", "fsl,dcsr-rcpm";
+ reg = <0x22000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy at 40000 {
+ compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu0>;
+ reg = <0x40000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy at 41000 {
+ compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu1>;
+ reg = <0x41000 0x1000>;
+ };
+ };
+
+ bman-portals at ff4000000 {
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ compatible = "bman-portals";
+ ranges = <0x0 0xf 0xfde00000 0x200000>;
+ bman-portal at 0 {
+ cell-index = <0x0>;
+ compatible = "fsl,p5020-bman-portal", "fsl,bman-portal";
+ reg = <0x0 0x4000 0x100000 0x1000>;
+ interrupts = <105 2 0 0>;
+ };
+ bman-portal at 4000 {
+ cell-index = <0x1>;
+ compatible = "fsl,p5020-bman-portal", "fsl,bman-portal";
+ reg = <0x4000 0x4000 0x101000 0x1000>;
+ interrupts = <107 2 0 0>;
+ };
+ bman-portal at 8000 {
+ cell-index = <2>;
+ compatible = "fsl,p5020-bman-portal", "fsl,bman-portal";
+ reg = <0x8000 0x4000 0x102000 0x1000>;
+ interrupts = <109 2 0 0>;
+ };
+ bman-portal at c000 {
+ cell-index = <0x3>;
+ compatible = "fsl,p5020-bman-portal", "fsl,bman-portal";
+ reg = <0xc000 0x4000 0x103000 0x1000>;
+ interrupts = <111 2 0 0>;
+ };
+ bman-portal at 10000 {
+ cell-index = <0x4>;
+ compatible = "fsl,p5020-bman-portal", "fsl,bman-portal";
+ reg = <0x10000 0x4000 0x104000 0x1000>;
+ interrupts = <113 2 0 0>;
+ };
+ bman-portal at 14000 {
+ cell-index = <0x5>;
+ compatible = "fsl,p5020-bman-portal", "fsl,bman-portal";
+ reg = <0x14000 0x4000 0x105000 0x1000>;
+ interrupts = <115 2 0 0>;
+ };
+ bman-portal at 18000 {
+ cell-index = <0x6>;
+ compatible = "fsl,p5020-bman-portal", "fsl,bman-portal";
+ reg = <0x18000 0x4000 0x106000 0x1000>;
+ interrupts = <117 2 0 0>;
+ };
+ bman-portal at 1c000 {
+ cell-index = <0x7>;
+ compatible = "fsl,p5020-bman-portal", "fsl,bman-portal";
+ reg = <0x1c000 0x4000 0x107000 0x1000>;
+ interrupts = <119 2 0 0>;
+ };
+ bman-portal at 20000 {
+ cell-index = <0x8>;
+ compatible = "fsl,p5020-bman-portal", "fsl,bman-portal";
+ reg = <0x20000 0x4000 0x108000 0x1000>;
+ interrupts = <121 2 0 0>;
+ };
+ bman-portal at 24000 {
+ cell-index = <0x9>;
+ compatible = "fsl,p5020-bman-portal", "fsl,bman-portal";
+ reg = <0x24000 0x4000 0x109000 0x1000>;
+ interrupts = <123 2 0 0>;
+ };
+
+ buffer-pool at 0 {
+ compatible = "fsl,p5020-bpool", "fsl,bpool";
+ fsl,bpid = <0>;
+ fsl,bpool-cfg = <0 0x100 0 1 0 0x100>;
+ };
+ };
+
+ qman-portals at ff4200000 {
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ compatible = "qman-portals";
+ ranges = <0x0 0xf 0xfdc00000 0x200000>;
+ qportal0: qman-portal at 0 {
+ cell-index = <0x0>;
+ compatible = "fsl,p5020-qman-portal", "fsl,qman-portal";
+ reg = <0x0 0x4000 0x100000 0x1000>;
+ interrupts = <104 0x2 0 0>;
+ fsl,qman-channel-id = <0x0>;
+ };
+
+ qportal1: qman-portal at 4000 {
+ cell-index = <0x1>;
+ compatible = "fsl,p5020-qman-portal", "fsl,qman-portal";
+ reg = <0x4000 0x4000 0x101000 0x1000>;
+ interrupts = <106 0x2 0 0>;
+ fsl,qman-channel-id = <0x1>;
+ };
+
+ qportal2: qman-portal at 8000 {
+ cell-index = <0x2>;
+ compatible = "fsl,p5020-qman-portal", "fsl,qman-portal";
+ reg = <0x8000 0x4000 0x102000 0x1000>;
+ interrupts = <108 0x2 0 0>;
+ fsl,qman-channel-id = <0x2>;
+ };
+
+ qportal3: qman-portal at c000 {
+ cell-index = <0x3>;
+ compatible = "fsl,p5020-qman-portal", "fsl,qman-portal";
+ reg = <0xc000 0x4000 0x103000 0x1000>;
+ interrupts = <110 0x2 0 0>;
+ fsl,qman-channel-id = <0x3>;
+ };
+
+ qportal4: qman-portal at 10000 {
+ cell-index = <0x4>;
+ compatible = "fsl,p5020-qman-portal", "fsl,qman-portal";
+ reg = <0x10000 0x4000 0x104000 0x1000>;
+ interrupts = <112 0x2 0 0>;
+ fsl,qman-channel-id = <0x4>;
+ };
+
+ qportal5: qman-portal at 14000 {
+ cell-index = <0x5>;
+ compatible = "fsl,p5020-qman-portal", "fsl,qman-portal";
+ reg = <0x14000 0x4000 0x105000 0x1000>;
+ interrupts = <114 0x2 0 0>;
+ fsl,qman-channel-id = <0x5>;
+ };
+
+ qportal6: qman-portal at 18000 {
+ cell-index = <0x6>;
+ compatible = "fsl,p5020-qman-portal", "fsl,qman-portal";
+ reg = <0x18000 0x4000 0x106000 0x1000>;
+ interrupts = <116 0x2 0 0>;
+ fsl,qman-channel-id = <0x6>;
+ };
+
+ qportal7: qman-portal at 1c000 {
+ cell-index = <0x7>;
+ compatible = "fsl,p5020-qman-portal", "fsl,qman-portal";
+ reg = <0x1c000 0x4000 0x107000 0x1000>;
+ interrupts = <118 0x2 0 0>;
+ fsl,qman-channel-id = <0x7>;
+ };
+
+ qportal8: qman-portal at 20000 {
+ cell-index = <0x8>;
+ compatible = "fsl,p5020-qman-portal", "fsl,qman-portal";
+ reg = <0x20000 0x4000 0x108000 0x1000>;
+ interrupts = <120 0x2 0 0>;
+ fsl,qman-channel-id = <0x8>;
+ };
+
+ qportal9: qman-portal at 24000 {
+ cell-index = <0x9>;
+ compatible = "fsl,p5020-qman-portal", "fsl,qman-portal";
+ reg = <0x24000 0x4000 0x109000 0x1000>;
+ interrupts = <122 0x2 0 0>;
+ fsl,qman-channel-id = <0x9>;
+ };
+
+ qpool1: qman-pool at 1 {
+ cell-index = <1>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x21>;
+ };
+
+ qpool2: qman-pool at 2 {
+ cell-index = <2>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x22>;
+ };
+
+ qpool3: qman-pool at 3 {
+ cell-index = <3>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x23>;
+ };
+
+ qpool4: qman-pool at 4 {
+ cell-index = <4>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x24>;
+ };
+
+ qpool5: qman-pool at 5 {
+ cell-index = <5>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x25>;
+ };
+
+ qpool6: qman-pool at 6 {
+ cell-index = <6>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x26>;
+ };
+
+ qpool7: qman-pool at 7 {
+ cell-index = <7>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x27>;
+ };
+
+ qpool8: qman-pool at 8 {
+ cell-index = <8>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x28>;
+ };
+
+ qpool9: qman-pool at 9 {
+ cell-index = <9>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x29>;
+ };
+
+ qpool10: qman-pool at 10 {
+ cell-index = <10>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2a>;
+ };
+
+ qpool11: qman-pool at 11 {
+ cell-index = <11>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2b>;
+ };
+
+ qpool12: qman-pool at 12 {
+ cell-index = <12>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2c>;
+ };
+
+ qpool13: qman-pool at 13 {
+ cell-index = <13>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2d>;
+ };
+
+ qpool14: qman-pool at 14 {
+ cell-index = <14>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2e>;
+ };
+
+ qpool15: qman-pool at 15 {
+ cell-index = <15>;
+ compatible = "fsl,p5020-qman-pool-channel", "fsl,qman-pool-channel";
+ fsl,qman-channel-id = <0x2f>;
+ };
+ };
+
+ soc: soc at ffe000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "simple-bus";
+
+ bus-frequency = <0>; // Filled out by kernel.
+
+ ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+ reg = <0xf 0xfe000000 0 0x00001000>;
+
+ soc-sram-error {
+ compatible = "fsl,soc-sram-error";
+ interrupts = <16 2 1 29>;
+ };
+
+ corenet-law at 0 {
+ compatible = "fsl,corenet-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <32>;
+ };
+
+ ddr1: memory-controller at 8000 {
+ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+ reg = <0x8000 0x1000>;
+ interrupts = <16 2 1 23>;
+ };
+
+ ddr2: memory-controller at 9000 {
+ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+ reg = <0x9000 0x1000>;
+ interrupts = <16 2 1 22>;
+ };
+
+ cpc: l3-cache-controller at 10000 {
+ compatible = "fsl,p5020-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+ reg = <0x10000 0x1000
+ 0x11000 0x1000>;
+ interrupts = <16 2 1 27
+ 16 2 1 26>;
+ };
+
+ corenet-cf at 18000 {
+ compatible = "fsl,corenet-cf";
+ reg = <0x18000 0x1000>;
+ interrupts = <16 2 1 31>;
+ fsl,ccf-num-csdids = <32>;
+ fsl,ccf-num-snoopids = <32>;
+ };
+
+ iommu at 20000 {
+ compatible = "fsl,pamu-v1.0", "fsl,pamu";
+ reg = <0x20000 0x4000>;
+ interrupts = <
+ 24 2 0 0
+ 16 2 1 30>;
+ };
+
+ mpic: pic at 40000 {
+ clock-frequency = <0>;
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <4>;
+ reg = <0x40000 0x40000>;
+ compatible = "fsl,mpic", "chrp,open-pic";
+ device_type = "open-pic";
+ };
+
+ msi0: msi at 41600 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41600 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe0 0 0 0
+ 0xe1 0 0 0
+ 0xe2 0 0 0
+ 0xe3 0 0 0
+ 0xe4 0 0 0
+ 0xe5 0 0 0
+ 0xe6 0 0 0
+ 0xe7 0 0 0>;
+ };
+
+ msi1: msi at 41800 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41800 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xe8 0 0 0
+ 0xe9 0 0 0
+ 0xea 0 0 0
+ 0xeb 0 0 0
+ 0xec 0 0 0
+ 0xed 0 0 0
+ 0xee 0 0 0
+ 0xef 0 0 0>;
+ };
+
+ msi2: msi at 41a00 {
+ compatible = "fsl,mpic-msi";
+ reg = <0x41a00 0x200>;
+ msi-available-ranges = <0 0x100>;
+ interrupts = <
+ 0xf0 0 0 0
+ 0xf1 0 0 0
+ 0xf2 0 0 0
+ 0xf3 0 0 0
+ 0xf4 0 0 0
+ 0xf5 0 0 0
+ 0xf6 0 0 0
+ 0xf7 0 0 0>;
+ };
+
+ guts: global-utilities at e0000 {
+ compatible = "fsl,qoriq-device-config-1.0";
+ reg = <0xe0000 0xe00>;
+ fsl,has-rstcr;
+ #sleep-cells = <1>;
+ fsl,liodn-bits = <12>;
+ };
+
+ pins: global-utilities at e0e00 {
+ compatible = "fsl,qoriq-pin-control-1.0";
+ reg = <0xe0e00 0x200>;
+ #sleep-cells = <2>;
+ };
+
+ clockgen: global-utilities at e1000 {
+ compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
+ reg = <0xe1000 0x1000>;
+ clock-frequency = <0>;
+ };
+
+ rcpm: global-utilities at e2000 {
+ compatible = "fsl,qoriq-rcpm-1.0";
+ reg = <0xe2000 0x1000>;
+ #sleep-cells = <1>;
+ };
+
+ sfp: sfp at e8000 {
+ compatible = "fsl,p5020-sfp", "fsl,qoriq-sfp-1.0";
+ reg = <0xe8000 0x1000>;
+ };
+
+ serdes: serdes at ea000 {
+ compatible = "fsl,p5020-serdes";
+ reg = <0xea000 0x1000>;
+ };
+
+ dma0: dma at 100300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p5020-dma", "fsl,eloplus-dma";
+ reg = <0x100300 0x4>;
+ ranges = <0x0 0x100100 0x200>;
+ cell-index = <0>;
+ dma-channel at 0 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <28 2 0 0>;
+ };
+ dma-channel at 80 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <29 2 0 0>;
+ };
+ dma-channel at 100 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <30 2 0 0>;
+ };
+ dma-channel at 180 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <31 2 0 0>;
+ };
+ };
+
+ dma1: dma at 101300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,p5020-dma", "fsl,eloplus-dma";
+ reg = <0x101300 0x4>;
+ ranges = <0x0 0x101100 0x200>;
+ cell-index = <1>;
+ dma-channel at 0 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x0 0x80>;
+ cell-index = <0>;
+ interrupts = <32 2 0 0>;
+ };
+ dma-channel at 80 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x80 0x80>;
+ cell-index = <1>;
+ interrupts = <33 2 0 0>;
+ };
+ dma-channel at 100 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x100 0x80>;
+ cell-index = <2>;
+ interrupts = <34 2 0 0>;
+ };
+ dma-channel at 180 {
+ compatible = "fsl,p5020-dma-channel",
+ "fsl,eloplus-dma-channel";
+ reg = <0x180 0x80>;
+ cell-index = <3>;
+ interrupts = <35 2 0 0>;
+ };
+ };
+
+ spi at 110000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,p5020-espi", "fsl,mpc8536-espi";
+ reg = <0x110000 0x1000>;
+ interrupts = <53 0x2 0 0>;
+ fsl,espi-num-chipselects = <4>;
+ };
+
+ sdhc: sdhc at 114000 {
+ compatible = "fsl,p5020-esdhc", "fsl,esdhc";
+ reg = <0x114000 0x1000>;
+ interrupts = <48 2 0 0>;
+ sdhci,auto-cmd12;
+ clock-frequency = <0>;
+ };
+
+ i2c at 118000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ compatible = "fsl-i2c";
+ reg = <0x118000 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c at 118100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ compatible = "fsl-i2c";
+ reg = <0x118100 0x100>;
+ interrupts = <38 2 0 0>;
+ dfsrr;
+ };
+
+ i2c at 119000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <2>;
+ compatible = "fsl-i2c";
+ reg = <0x119000 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ i2c at 119100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <3>;
+ compatible = "fsl-i2c";
+ reg = <0x119100 0x100>;
+ interrupts = <39 2 0 0>;
+ dfsrr;
+ };
+
+ serial0: serial at 11c500 {
+ cell-index = <0>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial1: serial at 11c600 {
+ cell-index = <1>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11c600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <36 2 0 0>;
+ };
+
+ serial2: serial at 11d500 {
+ cell-index = <2>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d500 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ serial3: serial at 11d600 {
+ cell-index = <3>;
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <0x11d600 0x100>;
+ clock-frequency = <0>;
+ interrupts = <37 2 0 0>;
+ };
+
+ gpio0: gpio at 130000 {
+ compatible = "fsl,p5020-gpio", "fsl,qoriq-gpio";
+ reg = <0x130000 0x1000>;
+ interrupts = <55 2 0 0>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ };
+
+ rman: rman at 1e0000 {
+ compatible = "fsl,rman";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x1e0000 0x20000>;
+ reg = <0x1e0000 0x20000>;
+ interrupts = <16 2 1 11>; /* err_irq */
+ fsl,qman-channels-id = <0x62 0x63>;
+
+ inbound-block at 0 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x0 0x800>;
+ };
+ global-cfg at b00 {
+ compatible = "fsl,rman-global-cfg";
+ reg = <0xb00 0x500>;
+ };
+ inbound-block at 1000 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x1000 0x800>;
+ };
+ inbound-block at 2000 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x2000 0x800>;
+ };
+ inbound-block at 3000 {
+ compatible = "fsl,rman-inbound-block";
+ reg = <0x3000 0x800>;
+ };
+ };
+
+ usb0: usb at 210000 {
+ compatible = "fsl,p5020-usb2-mph",
+ "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+ reg = <0x210000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <44 0x2 0 0>;
+ phy_type = "utmi";
+ port0;
+ };
+
+ usb1: usb at 211000 {
+ compatible = "fsl,p5020-usb2-dr",
+ "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+ reg = <0x211000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <45 0x2 0 0>;
+ dr_mode = "host";
+ phy_type = "utmi";
+ };
+
+ sata at 220000 {
+ compatible = "fsl,p5020-sata", "fsl,pq-sata-v2";
+ reg = <0x220000 0x1000>;
+ interrupts = <68 0x2 0 0>;
+ };
+
+ sata at 221000 {
+ compatible = "fsl,p5020-sata", "fsl,pq-sata-v2";
+ reg = <0x221000 0x1000>;
+ interrupts = <69 0x2 0 0>;
+ };
+
+ crypto: crypto at 300000 {
+ compatible = "fsl,sec-v4.2", "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupts = <92 2 0 0>;
+
+ sec_jr0: jr at 1000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupts = <88 2 0 0>;
+ };
+
+ sec_jr1: jr at 2000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupts = <89 2 0 0>;
+ };
+
+ sec_jr2: jr at 3000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupts = <90 2 0 0>;
+ };
+
+ sec_jr3: jr at 4000 {
+ compatible = "fsl,sec-v4.2-job-ring",
+ "fsl,sec-v4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupts = <91 2 0 0>;
+ };
+
+ rtic at 6000 {
+ compatible = "fsl,sec-v4.2-rtic",
+ "fsl,sec-v4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a at 0 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b at 20 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c at 40 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d at 60 {
+ compatible = "fsl,sec-v4.2-rtic-memory",
+ "fsl,sec-v4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ sec_mon: sec_mon at 314000 {
+ compatible = "fsl,sec-v4.2-mon", "fsl,sec-v4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupts = <93 2 0 0>;
+ };
+
+ raideng: raideng at 320000 {
+ compatible = "fsl,raideng-v1.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x320000 0x10000>;
+ ranges = <0 0x320000 0x10000>;
+
+ raideng_jq0 at 1000 {
+ compatible = "fsl,raideng-v1.0-job-queue";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x1000 0x1000>;
+ ranges = <0x0 0x1000 0x1000>;
+
+ raideng_jr0: jr at 0 {
+ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring";
+ reg = <0x0 0x400>;
+ interrupts = <139 2 0 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+ raideng_jr1: jr at 400 {
+ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-lp-ring";
+ reg = <0x400 0x400>;
+ interrupts = <140 2 0 0>;
+ interrupt-parent = <&mpic>;
+ };
+ };
+
+ raideng_jq1 at 2000 {
+ compatible = "fsl,raideng-v1.0-job-queue";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x2000 0x1000>;
+ ranges = <0x0 0x2000 0x1000>;
+
+ raideng_jr2: jr at 0 {
+ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring";
+ reg = <0x0 0x400>;
+ interrupts = <141 2 0 0>;
+ interrupt-parent = <&mpic>;
+ };
+
+ raideng_jr3: jr at 400 {
+ compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-lp-ring";
+ reg = <0x400 0x400>;
+ interrupts = <142 2 0 0>;
+ interrupt-parent = <&mpic>;
+ };
+ };
+ };
+
+ pme: pme at 316000 {
+ compatible = "fsl,pme";
+ reg = <0x316000 0x10000>;
+ /* fsl,pme-pdsr = <0x0 0x23000000 0x0 0x01000000>; */
+ /* fsl,pme-sre = <0x0 0x24000000 0x0 0x00a00000>; */
+ interrupts = <16 2 1 5>;
+ };
+
+ qman: qman at 318000 {
+ compatible = "fsl,p5020-qman", "fsl,qman";
+ reg = <0x318000 0x1000>;
+ interrupts = <16 2 1 3>;
+ /* Commented out, use default allocation */
+ /* fsl,qman-fqd = <0x0 0x20000000 0x0 0x01000000>; */
+ /* fsl,qman-pfdr = <0x0 0x21000000 0x0 0x01000000>; */
+ };
+
+ bman: bman at 31a000 {
+ compatible = "fsl,p5020-bman", "fsl,bman";
+ reg = <0x31a000 0x1000>;
+ interrupts = <16 2 1 2>;
+ /* Same as fsl,qman-*, use default allocation */
+ /* fsl,bman-fbpr = <0x0 0x22000000 0x0 0x01000000>; */
+ };
+
+ fman0: fman at 400000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ cell-index = <0>;
+ compatible = "fsl,p5020-fman", "fsl,fman", "simple-bus";
+ ranges = <0 0x400000 0x100000>;
+ reg = <0x400000 0x100000>;
+ clock-frequency = <0>;
+ interrupts = <
+ 96 2 0 0
+ 16 2 1 1>;
+
+ cc at 0 {
+ compatible = "fsl,p5020-fman-cc", "fsl,fman-cc";
+ };
+
+ parser at c7000 {
+ compatible = "fsl,p5020-fman-parser", "fsl,fman-parser";
+ reg = <0xc7000 0x1000>;
+ };
+
+ keygen at c1000 {
+ compatible = "fsl,p5020-fman-keygen", "fsl,fman-keygen";
+ reg = <0xc1000 0x1000>;
+ };
+
+ policer at c0000 {
+ compatible = "fsl,p5020-fman-policer", "fsl,fman-policer";
+ reg = <0xc0000 0x1000>;
+ };
+
+ muram at 0 {
+ compatible = "fsl,p5020-fman-muram", "fsl,fman-muram";
+ reg = <0x0 0x28000>;
+ };
+
+ bmi at 80000 {
+ compatible = "fsl,p5020-fman-bmi", "fsl,fman-bmi";
+ reg = <0x80000 0x400>;
+ };
+
+ qmi at 80400 {
+ compatible = "fsl,p5020-fman-qmi", "fsl,fman-qmi";
+ reg = <0x80400 0x400>;
+ };
+
+ fman0_rx0: port at 88000 {
+ cell-index = <0>;
+ compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x88000 0x1000>;
+ };
+ fman0_rx1: port at 89000 {
+ cell-index = <1>;
+ compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x89000 0x1000>;
+ };
+ fman0_rx2: port at 8a000 {
+ cell-index = <2>;
+ compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x8a000 0x1000>;
+ };
+ fman0_rx3: port at 8b000 {
+ cell-index = <3>;
+ compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x8b000 0x1000>;
+ };
+ fman0_rx4: port at 8c000 {
+ cell-index = <4>;
+ compatible = "fsl,p5020-fman-port-1g-rx", "fsl,fman-port-1g-rx";
+ reg = <0x8c000 0x1000>;
+ };
+ fman0_rx5: port at 90000 {
+ cell-index = <0>;
+ compatible = "fsl,p5020-fman-port-10g-rx", "fsl,fman-port-10g-rx";
+ reg = <0x90000 0x1000>;
+ };
+
+ fman0_tx5: port at b0000 {
+ cell-index = <0>;
+ compatible = "fsl,p5020-fman-port-10g-tx", "fsl,fman-port-10g-tx";
+ reg = <0xb0000 0x1000>;
+ fsl,qman-channel-id = <0x40>;
+ };
+ fman0_tx0: port at a8000 {
+ cell-index = <0>;
+ compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xa8000 0x1000>;
+ fsl,qman-channel-id = <0x41>;
+ };
+ fman0_tx1: port at a9000 {
+ cell-index = <1>;
+ compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xa9000 0x1000>;
+ fsl,qman-channel-id = <0x42>;
+ };
+ fman0_tx2: port at aa000 {
+ cell-index = <2>;
+ compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xaa000 0x1000>;
+ fsl,qman-channel-id = <0x43>;
+ };
+ fman0_tx3: port at ab000 {
+ cell-index = <3>;
+ compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xab000 0x1000>;
+ fsl,qman-channel-id = <0x44>;
+ };
+ fman0_tx4: port at ac000 {
+ cell-index = <4>;
+ compatible = "fsl,p5020-fman-port-1g-tx", "fsl,fman-port-1g-tx";
+ reg = <0xac000 0x1000>;
+ fsl,qman-channel-id = <0x45>;
+ };
+
+ fman0_oh0: port at 81000 {
+ cell-index = <0>;
+ compatible = "fsl,p5020-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x81000 0x1000>;
+ fsl,qman-channel-id = <0x46>;
+ };
+ fman0_oh1: port at 82000 {
+ cell-index = <1>;
+ compatible = "fsl,p5020-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x82000 0x1000>;
+ fsl,qman-channel-id = <0x47>;
+ };
+ fman0_oh2: port at 83000 {
+ cell-index = <2>;
+ compatible = "fsl,p5020-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x83000 0x1000>;
+ fsl,qman-channel-id = <0x48>;
+ };
+ fman0_oh3: port at 84000 {
+ cell-index = <3>;
+ compatible = "fsl,p5020-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x84000 0x1000>;
+ fsl,qman-channel-id = <0x49>;
+ };
+ fman0_oh4: port at 85000 {
+ cell-index = <4>;
+ compatible = "fsl,p5020-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x85000 0x1000>;
+ fsl,qman-channel-id = <0x4a>;
+ };
+ fman0_oh5: port at 86000 {
+ cell-index = <5>;
+ compatible = "fsl,p5020-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x86000 0x1000>;
+ fsl,qman-channel-id = <0x4b>;
+ };
+ fman0_oh6: port at 87000 {
+ cell-index = <6>;
+ compatible = "fsl,p5020-fman-port-oh", "fsl,fman-port-oh";
+ reg = <0x87000 0x1000>;
+ };
+
+ enet0: ethernet at e0000 {
+ cell-index = <0>;
+ compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe0000 0x1000>;
+ fsl,port-handles = <&fman0_rx0 &fman0_tx0>;
+ ptimer-handle = <&ptp_timer0>;
+ };
+
+ mdio0: mdio at e1120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-mdio";
+ reg = <0xe1120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet1: ethernet at e2000 {
+ cell-index = <1>;
+ compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe2000 0x1000>;
+ fsl,port-handles = <&fman0_rx1 &fman0_tx1>;
+ ptimer-handle = <&ptp_timer0>;
+ };
+
+ mdio at e3120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe3120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet2: ethernet at e4000 {
+ cell-index = <2>;
+ compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe4000 0x1000>;
+ fsl,port-handles = <&fman0_rx2 &fman0_tx2>;
+ ptimer-handle = <&ptp_timer0>;
+ };
+
+ mdio at e5120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe5120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet3: ethernet at e6000 {
+ cell-index = <3>;
+ compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe6000 0x1000>;
+ fsl,port-handles = <&fman0_rx3 &fman0_tx3>;
+ ptimer-handle = <&ptp_timer0>;
+ };
+
+ mdio at e7120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe7120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet4: ethernet at e8000 {
+ cell-index = <4>;
+ compatible = "fsl,p5020-fman-1g-mac", "fsl,fman-1g-mac";
+ reg = <0xe8000 0x1000>;
+ fsl,port-handles = <&fman0_rx4 &fman0_tx4>;
+ ptimer-handle = <&ptp_timer0>;
+ };
+
+ mdio at e9120 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-tbi";
+ reg = <0xe9120 0xee0>;
+ interrupts = <100 1 0 0>;
+ };
+
+ enet5: ethernet at f0000 {
+ cell-index = <0>;
+ compatible = "fsl,p5020-fman-10g-mac", "fsl,fman-10g-mac";
+ reg = <0xf0000 0x1000>;
+ fsl,port-handles = <&fman0_rx5 &fman0_tx5>;
+ };
+
+ mdio at f1000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,fman-xmdio";
+ reg = <0xf1000 0x1000>;
+ interrupts = <100 1 0 0>;
+ };
+
+ ptp_timer0: rtc at fe000 {
+ compatible = "fsl,fman-rtc";
+ reg = <0xfe000 0x1000>;
+ };
+ };
+ };
+
+ rapidio at ffe0c0000 {
+ compatible = "fsl,srio";
+ interrupts = <16 2 1 11>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ port1 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ cell-index = <1>;
+ };
+
+ port2 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ cell-index = <2>;
+ };
+ };
+
+ localbus at ffe124000 {
+ compatible = "fsl,p5020-rev1.0-elbc", "simple-bus", "fsl,elbc";
+ interrupts = <
+ 25 2 0 0
+ 16 2 1 19
+ >;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ };
+
+ pci0: pcie at ffe200000 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ status = "okay";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ cell-index = <0>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi0>;
+ interrupts = <16 2 1 15>;
+
+ pcie at 0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 15>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 40 1 0 0
+ 0000 0 0 2 &mpic 1 1 0 0
+ 0000 0 0 3 &mpic 2 1 0 0
+ 0000 0 0 4 &mpic 3 1 0 0
+ >;
+ };
+ };
+
+ pci1: pcie at ffe201000 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ status = "disabled";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ cell-index = <1>;
+ bus-range = <0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi1>;
+ interrupts = <16 2 1 14>;
+ pcie at 0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 14>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 41 1 0 0
+ 0000 0 0 2 &mpic 5 1 0 0
+ 0000 0 0 3 &mpic 6 1 0 0
+ 0000 0 0 4 &mpic 7 1 0 0
+ >;
+ };
+ };
+
+ pci2: pcie at ffe202000 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ status = "okay";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ cell-index = <2>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi2>;
+ interrupts = <16 2 1 13>;
+ pcie at 0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 13>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 42 1 0 0
+ 0000 0 0 2 &mpic 9 1 0 0
+ 0000 0 0 3 &mpic 10 1 0 0
+ 0000 0 0 4 &mpic 11 1 0 0
+ >;
+ };
+ };
+
+ pci3: pcie at ffe203000 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ status = "disabled";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ cell-index = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <0x1fca055>;
+ fsl,msi = <&msi2>;
+ interrupts = <16 2 1 12>;
+ pcie at 0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 12>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 43 1 0 0
+ 0000 0 0 2 &mpic 0 1 0 0
+ 0000 0 0 3 &mpic 4 1 0 0
+ 0000 0 0 4 &mpic 8 1 0 0
+ >;
+ };
+ };
+};
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/fdt/dts/sheevaplug.dts
--- a/head/sys/boot/fdt/dts/sheevaplug.dts Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/fdt/dts/sheevaplug.dts Wed Jul 25 16:45:04 2012 +0300
@@ -28,7 +28,7 @@
*
* Marvell SheevaPlug Device Tree Source.
*
- * $FreeBSD: head/sys/boot/fdt/dts/sheevaplug.dts 227730 2011-11-19 16:30:06Z raj $
+ * $FreeBSD: head/sys/boot/fdt/dts/sheevaplug.dts 235778 2012-05-22 08:33:14Z gber $
*/
/dts-v1/;
@@ -71,48 +71,33 @@
reg = <0x0 0x20000000>; // 512M at 0x0
};
- localbus at f1000000 {
+ localbus at 0 {
#address-cells = <2>;
#size-cells = <1>;
compatible = "mrvl,lbc";
+ bank-count = <3>;
/* This reflects CPU decode windows setup. */
- ranges = <0x0 0x0f 0xf9300000 0x00100000
- 0x1 0x1e 0xfa000000 0x00100000
- 0x2 0x1d 0xfa100000 0x02000000
- 0x3 0x1b 0xfc100000 0x00000400>;
+ ranges = <0x0 0x2f 0xf9300000 0x00100000>;
- nor at 0,0 {
+ nand at 0,0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "cfi-flash";
+ compatible = "mrvl,nfc";
reg = <0x0 0x0 0x00100000>;
bank-width = <2>;
device-width = <1>;
- };
- led at 1,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "led";
- reg = <0x1 0x0 0x00100000>;
- };
+ slice at 0 {
+ reg = <0x0 0x200000>;
+ label = "u-boot";
+ read-only;
+ };
- nor at 2,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "cfi-flash";
- reg = <0x2 0x0 0x02000000>;
- bank-width = <2>;
- device-width = <1>;
- };
-
- nand at 3,0 {
- #address-cells = <1>;
- #size-cells = <1>;
- reg = <0x3 0x0 0x00100000>;
- bank-width = <2>;
- device-width = <1>;
+ slice at 200000 {
+ reg = <0x200000 0x1fe00000>;
+ label = "root";
+ };
};
};
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/fdt/fdt_loader_cmd.c
--- a/head/sys/boot/fdt/fdt_loader_cmd.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/fdt/fdt_loader_cmd.c Wed Jul 25 16:45:04 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/fdt/fdt_loader_cmd.c 233323 2012-03-22 20:34:26Z raj $");
+__FBSDID("$FreeBSD: head/sys/boot/fdt/fdt_loader_cmd.c 235529 2012-05-17 04:04:48Z kientzle $");
#include <stand.h>
#include <fdt.h>
@@ -57,11 +57,17 @@
#define STR(number) #number
#define STRINGIFY(number) STR(number)
-#define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l)
+#define COPYOUT(s,d,l) archsw.arch_copyout(s, d, l)
+#define COPYIN(s,d,l) archsw.arch_copyin(s, d, l)
#define FDT_STATIC_DTB_SYMBOL "fdt_static_dtb"
+/* Local copy of FDT */
static struct fdt_header *fdtp = NULL;
+/* Size of FDT blob */
+static size_t fdtp_size = 0;
+/* Location of FDT in kernel or module */
+static vm_offset_t fdtp_va = 0;
static int fdt_cmd_nyi(int argc, char *argv[]);
@@ -98,21 +104,19 @@
static char cwd[FDT_CWD_LEN] = "/";
static vm_offset_t
-fdt_find_static_dtb(void)
+fdt_find_static_dtb()
{
+ Elf_Dyn dyn;
Elf_Sym sym;
- vm_offset_t dyntab, esym;
+ vm_offset_t dyntab, esym, strtab, symtab, fdt_start;
uint64_t offs;
struct preloaded_file *kfp;
struct file_metadata *md;
- Elf_Sym *symtab;
- Elf_Dyn *dyn;
- char *strtab, *strp;
- int i, sym_count;
+ char *strp;
+ int sym_count;
- symtab = NULL;
- dyntab = esym = 0;
- strtab = strp = NULL;
+ symtab = strtab = dyntab = esym = 0;
+ strp = NULL;
offs = __elfN(relocation_offset);
@@ -123,28 +127,29 @@
md = file_findmetadata(kfp, MODINFOMD_ESYM);
if (md == NULL)
return (0);
- COPYOUT(md->md_data, &esym, sizeof(esym));
+ bcopy(md->md_data, &esym, sizeof(esym));
+ // esym is already offset
md = file_findmetadata(kfp, MODINFOMD_DYNAMIC);
if (md == NULL)
return (0);
- COPYOUT(md->md_data, &dyntab, sizeof(dyntab));
-
+ bcopy(md->md_data, &dyntab, sizeof(dyntab));
dyntab += offs;
/* Locate STRTAB and DYNTAB */
- for (dyn = (Elf_Dyn *)dyntab; dyn->d_tag != DT_NULL; dyn++) {
- if (dyn->d_tag == DT_STRTAB) {
- strtab = (char *)(uintptr_t)(dyn->d_un.d_ptr + offs);
- continue;
- } else if (dyn->d_tag == DT_SYMTAB) {
- symtab = (Elf_Sym *)(uintptr_t)
- (dyn->d_un.d_ptr + offs);
- continue;
+ for (;;) {
+ COPYOUT(dyntab, &dyn, sizeof(dyn));
+ if (dyn.d_tag == DT_STRTAB) {
+ strtab = (vm_offset_t)(dyn.d_un.d_ptr) + offs;
+ } else if (dyn.d_tag == DT_SYMTAB) {
+ symtab = (vm_offset_t)(dyn.d_un.d_ptr) + offs;
+ } else if (dyn.d_tag == DT_NULL) {
+ break;
}
+ dyntab += sizeof(dyn);
}
- if (symtab == NULL || strtab == NULL) {
+ if (symtab == 0 || strtab == 0) {
/*
* No symtab? No strtab? That should not happen here,
* and should have been verified during __elfN(loadimage).
@@ -153,7 +158,7 @@
return (0);
}
- sym_count = (int)((Elf_Sym *)esym - symtab) / sizeof(Elf_Sym);
+ sym_count = (int)(esym - symtab) / sizeof(Elf_Sym);
/*
* The most efficent way to find a symbol would be to calculate a
@@ -165,26 +170,27 @@
* we are eliminating symbols type of which is not STT_NOTYPE, or(and)
* those which binding attribute is not STB_GLOBAL.
*/
- for (i = 0; i < sym_count; i++) {
- COPYOUT(symtab + i, &sym, sizeof(sym));
+ fdt_start = 0;
+ while (sym_count > 0 && fdt_start == 0) {
+ COPYOUT(symtab, &sym, sizeof(sym));
+ symtab += sizeof(sym);
+ --sym_count;
if (ELF_ST_BIND(sym.st_info) != STB_GLOBAL ||
ELF_ST_TYPE(sym.st_info) != STT_NOTYPE)
continue;
-
- strp = strdupout((vm_offset_t)(strtab + sym.st_name));
- if (strcmp(strp, FDT_STATIC_DTB_SYMBOL) == 0) {
- /* Found a match ! */
- free(strp);
- return ((vm_offset_t)(sym.st_value + offs));
- }
+ strp = strdupout(strtab + sym.st_name);
+ if (strcmp(strp, FDT_STATIC_DTB_SYMBOL) == 0)
+ fdt_start = (vm_offset_t)sym.st_value + offs;
free(strp);
}
- return (0);
+ printf("fdt_start: 0x%08jX\n", (intmax_t)fdt_start);
+ return (fdt_start);
}
static int
fdt_setup_fdtp()
{
+ struct fdt_header header;
struct preloaded_file *bfp;
int err;
@@ -193,15 +199,26 @@
*/
bfp = file_findfile(NULL, "dtb");
if (bfp == NULL) {
- if ((fdtp = (struct fdt_header *)fdt_find_static_dtb()) == 0) {
+ if ((fdtp_va = fdt_find_static_dtb()) == 0) {
command_errmsg = "no device tree blob found!";
+ printf("%s\n", command_errmsg);
return (CMD_ERROR);
}
} else {
/* Dynamic blob has precedence over static. */
- fdtp = (struct fdt_header *)bfp->f_addr;
+ fdtp_va = bfp->f_addr;
}
+ COPYOUT(fdtp_va, &header, sizeof(header));
+ fdtp_size = fdt_totalsize(&header);
+ fdtp = malloc(fdtp_size);
+ if (fdtp == NULL) {
+ command_errmsg = "can't allocate memory for device tree copy";
+ printf("%s\n", command_errmsg);
+ return (CMD_ERROR);
+ }
+ COPYOUT(fdtp_va, fdtp, fdtp_size);
+
/*
* Validate the blob.
*/
@@ -317,6 +334,8 @@
/* We want to modify every subnode of /cpus */
o = fdt_path_offset(fdtp, "/cpus");
+ if (o < 0)
+ return;
/* maxo should contain offset of node next to /cpus */
depth = 0;
@@ -545,7 +564,7 @@
/*
* Locate the blob, fix it up and return its location.
*/
-void *
+vm_offset_t
fdt_fixup(void)
{
const char *env;
@@ -561,7 +580,7 @@
err = fdt_setup_fdtp();
if (err) {
sprintf(command_errbuf, "No valid device tree blob found!");
- return (NULL);
+ return (0);
}
/* Create /chosen node (if not exists) */
@@ -616,7 +635,9 @@
fdt_setprop(fdtp, chosen, "fixup-applied", NULL, 0);
success:
- return (fdtp);
+ /* Overwrite the FDT with the fixed version. */
+ COPYIN(fdtp, fdtp_va, fdtp_size);
+ return (fdtp_va);
}
int
@@ -634,7 +655,7 @@
/*
* Check if uboot env vars were parsed already. If not, do it now.
*/
- if (fdt_fixup() == NULL)
+ if (fdt_fixup() == 0)
return (CMD_ERROR);
/*
@@ -1151,6 +1172,8 @@
else
sprintf(command_errbuf,
"Could not add/modify property!\n");
+ } else {
+ COPYIN(fdtp, fdtp_va, fdtp_size);
}
return (rv);
}
@@ -1371,6 +1394,8 @@
if (rv) {
sprintf(command_errbuf, "could not delete node");
return (CMD_ERROR);
+ } else {
+ COPYIN(fdtp, fdtp_va, fdtp_size);
}
return (CMD_OK);
}
@@ -1401,6 +1426,8 @@
sprintf(command_errbuf,
"Could not add node!\n");
return (CMD_ERROR);
+ } else {
+ COPYIN(fdtp, fdtp_va, fdtp_size);
}
return (CMD_OK);
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/beastie.4th
--- a/head/sys/boot/forth/beastie.4th Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/beastie.4th Wed Jul 25 16:45:04 2012 +0300
@@ -1,6 +1,6 @@
\ Copyright (c) 2003 Scott Long <scottl at freebsd.org>
\ Copyright (c) 2003 Aleksander Fafula <alex at fafula.com>
-\ Copyright (c) 2006-2011 Devin Teske <devinteske at hotmail.com>
+\ Copyright (c) 2006-2011 Devin Teske <dteske at FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@
\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
\ SUCH DAMAGE.
\
-\ $FreeBSD: head/sys/boot/forth/beastie.4th 222417 2011-05-28 08:50:38Z julian $
+\ $FreeBSD: head/sys/boot/forth/beastie.4th 238431 2012-07-14 01:45:35Z dteske $
marker task-beastie.4th
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/beastie.4th.8
--- a/head/sys/boot/forth/beastie.4th.8 Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/beastie.4th.8 Wed Jul 25 16:45:04 2012 +0300
@@ -22,14 +22,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/sys/boot/forth/beastie.4th.8 222417 2011-05-28 08:50:38Z julian $
+.\" $FreeBSD: head/sys/boot/forth/beastie.4th.8 238431 2012-07-14 01:45:35Z dteske $
.\"
.Dd May 16, 2011
.Dt BEASTIE.4TH 8
.Os
.Sh NAME
.Nm beastie.4th
-.Nd FreeBSD ASCII art boot module.
+.Nd FreeBSD ASCII art boot module
.Sh DESCRIPTION
The file that goes by the name of
.Nm
@@ -168,4 +168,4 @@
.An Scott Long Aq scottl at FreeBSD.org ,
.An Aleksander Fafula Aq alex at fafula.com
and
-.An Devin Teske Aq devinteske at hotmail.com .
+.An Devin Teske Aq dteske at FreeBSD.org .
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/brand.4th
--- a/head/sys/boot/forth/brand.4th Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/brand.4th Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-\ Copyright (c) 2006-2011 Devin Teske <devinteske at hotmail.com>
+\ Copyright (c) 2006-2011 Devin Teske <dteske at FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
\ SUCH DAMAGE.
\
-\ $FreeBSD: head/sys/boot/forth/brand.4th 222417 2011-05-28 08:50:38Z julian $
+\ $FreeBSD: head/sys/boot/forth/brand.4th 238431 2012-07-14 01:45:35Z dteske $
marker task-brand.4th
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/brand.4th.8
--- a/head/sys/boot/forth/brand.4th.8 Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/brand.4th.8 Wed Jul 25 16:45:04 2012 +0300
@@ -22,14 +22,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/sys/boot/forth/brand.4th.8 222417 2011-05-28 08:50:38Z julian $
+.\" $FreeBSD: head/sys/boot/forth/brand.4th.8 238431 2012-07-14 01:45:35Z dteske $
.\"
.Dd May 18, 2011
.Dt BRAND.4TH 8
.Os
.Sh NAME
.Nm brand.4th
-.Nd FreeBSD ASCII art boot module.
+.Nd FreeBSD ASCII art boot module
.Sh DESCRIPTION
The file that goes by the name of
.Nm
@@ -122,4 +122,4 @@
.Nm
set of commands was written by
.An -nosplit
-.An Devin Teske Aq devinteske at hotmail.com .
+.An Devin Teske Aq dteske at FreeBSD.org .
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/check-password.4th
--- a/head/sys/boot/forth/check-password.4th Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/check-password.4th Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-\ Copyright (c) 2006-2011 Devin Teske <devinteske at hotmail.com>
+\ Copyright (c) 2006-2011 Devin Teske <dteske at FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
\ SUCH DAMAGE.
\
-\ $FreeBSD: head/sys/boot/forth/check-password.4th 222417 2011-05-28 08:50:38Z julian $
+\ $FreeBSD: head/sys/boot/forth/check-password.4th 238431 2012-07-14 01:45:35Z dteske $
marker task-check-password.4th
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/check-password.4th.8
--- a/head/sys/boot/forth/check-password.4th.8 Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/check-password.4th.8 Wed Jul 25 16:45:04 2012 +0300
@@ -22,14 +22,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/sys/boot/forth/check-password.4th.8 222599 2011-06-02 09:56:42Z uqs $
+.\" $FreeBSD: head/sys/boot/forth/check-password.4th.8 238431 2012-07-14 01:45:35Z dteske $
.\"
.Dd May 18, 2011
.Dt CHECK-PASSWORD.4TH 8
.Os
.Sh NAME
.Nm check-password.4th
-.Nd FreeBSD password-checking boot module.
+.Nd FreeBSD password-checking boot module
.Sh DESCRIPTION
The file that goes by the name of
.Nm
@@ -120,4 +120,4 @@
.Nm
set of commands was written by
.An -nosplit
-.An Devin Teske Aq devinteske at hotmail.com .
+.An Devin Teske Aq dteske at FreeBSD.org .
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/color.4th
--- a/head/sys/boot/forth/color.4th Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/color.4th Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-\ Copyright (c) 2011 Devin Teske <devinteske at hotmail.com>
+\ Copyright (c) 2011 Devin Teske <dteske at FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
\ SUCH DAMAGE.
\
-\ $FreeBSD: head/sys/boot/forth/color.4th 222417 2011-05-28 08:50:38Z julian $
+\ $FreeBSD: head/sys/boot/forth/color.4th 238431 2012-07-14 01:45:35Z dteske $
marker task-color.4th
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/color.4th.8
--- a/head/sys/boot/forth/color.4th.8 Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/color.4th.8 Wed Jul 25 16:45:04 2012 +0300
@@ -22,14 +22,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/sys/boot/forth/color.4th.8 222417 2011-05-28 08:50:38Z julian $
+.\" $FreeBSD: head/sys/boot/forth/color.4th.8 238431 2012-07-14 01:45:35Z dteske $
.\"
.Dd May 18, 2011
.Dt COLOR.4TH 8
.Os
.Sh NAME
.Nm color.4th
-.Nd FreeBSD color-detection boot module.
+.Nd FreeBSD color-detection boot module
.Sh DESCRIPTION
The file that goes by the name of
.Nm
@@ -114,4 +114,4 @@
.Nm
set of commands was written by
.An -nosplit
-.An Devin Teske Aq devinteske at hotmail.com .
+.An Devin Teske Aq dteske at FreeBSD.org .
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/delay.4th
--- a/head/sys/boot/forth/delay.4th Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/delay.4th Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-\ Copyright (c) 2008-2011 Devin Teske <devinteske at hotmail.com>
+\ Copyright (c) 2008-2011 Devin Teske <dteske at FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
\ SUCH DAMAGE.
\
-\ $FreeBSD: head/sys/boot/forth/delay.4th 222417 2011-05-28 08:50:38Z julian $
+\ $FreeBSD: head/sys/boot/forth/delay.4th 238431 2012-07-14 01:45:35Z dteske $
marker task-delay.4th
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/delay.4th.8
--- a/head/sys/boot/forth/delay.4th.8 Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/delay.4th.8 Wed Jul 25 16:45:04 2012 +0300
@@ -22,14 +22,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/sys/boot/forth/delay.4th.8 222417 2011-05-28 08:50:38Z julian $
+.\" $FreeBSD: head/sys/boot/forth/delay.4th.8 238431 2012-07-14 01:45:35Z dteske $
.\"
.Dd May 18, 2011
.Dt DELAY.4TH 8
.Os
.Sh NAME
.Nm delay.4th
-.Nd FreeBSD debugging boot module.
+.Nd FreeBSD debugging boot module
.Sh DESCRIPTION
The file that goes by the name of
.Nm
@@ -123,4 +123,4 @@
.Nm
set of commands was written by
.An -nosplit
-.An Devin Teske Aq devinteske at hotmail.com .
+.An Devin Teske Aq dteske at FreeBSD.org .
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/menu-commands.4th
--- a/head/sys/boot/forth/menu-commands.4th Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/menu-commands.4th Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-\ Copyright (c) 2006-2011 Devin Teske <devinteske at hotmail.com>
+\ Copyright (c) 2006-2011 Devin Teske <dteske at FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
\ SUCH DAMAGE.
\
-\ $FreeBSD: head/sys/boot/forth/menu-commands.4th 233941 2012-04-06 09:36:22Z avg $
+\ $FreeBSD: head/sys/boot/forth/menu-commands.4th 238431 2012-07-14 01:45:35Z dteske $
marker task-menu-commands.4th
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/menu.4th
--- a/head/sys/boot/forth/menu.4th Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/menu.4th Wed Jul 25 16:45:04 2012 +0300
@@ -1,6 +1,6 @@
\ Copyright (c) 2003 Scott Long <scottl at freebsd.org>
\ Copyright (c) 2003 Aleksander Fafula <alex at fafula.com>
-\ Copyright (c) 2006-2011 Devin Teske <devinteske at hotmail.com>
+\ Copyright (c) 2006-2011 Devin Teske <dteske at FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@
\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
\ SUCH DAMAGE.
\
-\ $FreeBSD: head/sys/boot/forth/menu.4th 228985 2011-12-30 06:24:59Z pluknet $
+\ $FreeBSD: head/sys/boot/forth/menu.4th 238431 2012-07-14 01:45:35Z dteske $
marker task-menu.4th
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/menu.4th.8
--- a/head/sys/boot/forth/menu.4th.8 Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/menu.4th.8 Wed Jul 25 16:45:04 2012 +0300
@@ -22,14 +22,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/sys/boot/forth/menu.4th.8 232158 2012-02-25 15:21:43Z gjb $
+.\" $FreeBSD: head/sys/boot/forth/menu.4th.8 238431 2012-07-14 01:45:35Z dteske $
.\"
.Dd February 25, 2012
.Dt MENU.4TH 8
.Os
.Sh NAME
.Nm menu.4th
-.Nd FreeBSD dynamic menu boot module.
+.Nd FreeBSD dynamic menu boot module
.Sh DESCRIPTION
The file that goes by the name of
.Nm
@@ -320,4 +320,4 @@
.Nm
set of commands was written by
.An -nosplit
-.An Devin Teske Aq devinteske at hotmail.com .
+.An Devin Teske Aq dteske at FreeBSD.org .
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/shortcuts.4th
--- a/head/sys/boot/forth/shortcuts.4th Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/shortcuts.4th Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-\ Copyright (c) 2008-2011 Devin Teske <devinteske at hotmail.com>
+\ Copyright (c) 2008-2011 Devin Teske <dteske at FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
\ SUCH DAMAGE.
\
-\ $FreeBSD: head/sys/boot/forth/shortcuts.4th 222417 2011-05-28 08:50:38Z julian $
+\ $FreeBSD: head/sys/boot/forth/shortcuts.4th 238431 2012-07-14 01:45:35Z dteske $
\ FICL words intended to be used as shortcuts for carrying out common tasks or
\ producing common results. Generally, words defined here are simply groupings
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/version.4th
--- a/head/sys/boot/forth/version.4th Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/version.4th Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-\ Copyright (c) 2006-2011 Devin Teske <devinteske at hotmail.com>
+\ Copyright (c) 2006-2011 Devin Teske <dteske at FreeBSD.org>
\ All rights reserved.
\
\ Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
\ SUCH DAMAGE.
\
-\ $FreeBSD: head/sys/boot/forth/version.4th 222417 2011-05-28 08:50:38Z julian $
+\ $FreeBSD: head/sys/boot/forth/version.4th 238431 2012-07-14 01:45:35Z dteske $
marker task-version.4th
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/forth/version.4th.8
--- a/head/sys/boot/forth/version.4th.8 Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/forth/version.4th.8 Wed Jul 25 16:45:04 2012 +0300
@@ -22,14 +22,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/sys/boot/forth/version.4th.8 222417 2011-05-28 08:50:38Z julian $
+.\" $FreeBSD: head/sys/boot/forth/version.4th.8 238431 2012-07-14 01:45:35Z dteske $
.\"
.Dd May 19, 2011
.Dt VERSION.4TH 8
.Os
.Sh NAME
.Nm version.4th
-.Nd FreeBSD version string boot module.
+.Nd FreeBSD version string boot module
.Sh DESCRIPTION
The file that goes by the name of
.Nm
@@ -123,4 +123,4 @@
.Nm
set of commands was written by
.An -nosplit
-.An Devin Teske Aq devinteske at hotmail.com .
+.An Devin Teske Aq dteske at FreeBSD.org .
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/boot2/boot2.c
--- a/head/sys/boot/i386/boot2/boot2.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/boot2/boot2.c Wed Jul 25 16:45:04 2012 +0300
@@ -14,7 +14,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/i386/boot2/boot2.c 232754 2012-03-09 23:30:30Z jkim $");
+__FBSDID("$FreeBSD: head/sys/boot/i386/boot2/boot2.c 236405 2012-06-01 15:48:24Z jhb $");
#include <sys/param.h>
#include <sys/disklabel.h>
@@ -129,8 +129,8 @@
int init;
} dsk;
static char cmd[512], cmddup[512], knamebuf[1024];
-static const char *kname = NULL;
-static uint32_t opts = 0;
+static const char *kname;
+static uint32_t opts;
static int comspeed = SIOSPD;
static struct bootinfo bootinfo;
static uint8_t ioctrl = IO_KEYBOARD;
@@ -138,7 +138,6 @@
void exit(int);
static void load(void);
static int parse(void);
-static int xfsread(ino_t, void *, size_t);
static int dskread(void *, unsigned, unsigned);
static void printf(const char *,...);
static void putchar(int);
@@ -170,7 +169,7 @@
#include "ufsread.c"
static inline int
-xfsread(ino_t inode, void *buf, size_t nbyte)
+xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
{
if ((size_t)fsread(inode, buf, nbyte) != nbyte) {
printf("Invalid %s\n", "format");
@@ -222,7 +221,7 @@
main(void)
{
uint8_t autoboot;
- ino_t ino;
+ ufs_ino_t ino;
size_t nbyte;
dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
@@ -307,7 +306,7 @@
static Elf32_Phdr ep[2];
static Elf32_Shdr es[2];
caddr_t p;
- ino_t ino;
+ ufs_ino_t ino;
uint32_t addr;
int i, j;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/btx/btx/Makefile
--- a/head/sys/boot/i386/btx/btx/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/btx/btx/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/boot/i386/btx/btx/Makefile 232263 2012-02-28 18:30:18Z dim $
+# $FreeBSD: head/sys/boot/i386/btx/btx/Makefile 235154 2012-05-09 08:04:29Z avg $
PROG= btx
INTERNALPROG=
@@ -12,6 +12,7 @@
.endif
CFLAGS+=-DBTX_FLAGS=${BOOT_BTX_FLAGS}
+CFLAGS+=-I${.CURDIR}/../../common
.if defined(BTX_SERIAL)
BOOT_COMCONSOLE_PORT?= 0x3f8
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/btx/btx/btx.S
--- a/head/sys/boot/i386/btx/btx/btx.S Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/btx/btx/btx.S Wed Jul 25 16:45:04 2012 +0300
@@ -12,9 +12,11 @@
* warranties of merchantability and fitness for a particular
* purpose.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/i386/btx/btx/btx.S 235154 2012-05-09 08:04:29Z avg $
*/
+#include <bootargs.h>
+
/*
* Memory layout.
*/
@@ -205,7 +207,7 @@
movl $MEM_USR,%edx # User base address
movzwl %ss:BDA_MEM,%eax # Get free memory
shll $0xa,%eax # To bytes
- subl $0x1000,%eax # Less arg space
+ subl $ARGSPACE,%eax # Less arg space
subl %edx,%eax # Less base
movb $SEL_UDATA,%cl # User data selector
pushl %ecx # Set SS
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/btx/btxldr/Makefile
--- a/head/sys/boot/i386/btx/btxldr/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/btx/btxldr/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/boot/i386/btx/btxldr/Makefile 232263 2012-02-28 18:30:18Z dim $
+# $FreeBSD: head/sys/boot/i386/btx/btxldr/Makefile 235154 2012-05-09 08:04:29Z avg $
PROG= btxldr
INTERNALPROG=
@@ -6,6 +6,7 @@
SRCS= btxldr.S
CFLAGS+=-DLOADER_ADDRESS=${LOADER_ADDRESS}
+CFLAGS+=-I${.CURDIR}/../../common
.if defined(BTXLDR_VERBOSE)
CFLAGS+=-DBTXLDR_VERBOSE
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/btx/btxldr/btxldr.S
--- a/head/sys/boot/i386/btx/btxldr/btxldr.S Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/btx/btxldr/btxldr.S Wed Jul 25 16:45:04 2012 +0300
@@ -12,9 +12,11 @@
* warranties of merchantability and fitness for a particular
* purpose.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/i386/btx/btxldr/btxldr.S 235154 2012-05-09 08:04:29Z avg $
*/
+#include <bootargs.h>
+
#define RBX_MUTE 0x10 /* -m */
#define OPT_SET(opt) (1 << (opt))
@@ -89,7 +91,7 @@
call hexout # stack
call putstr # pointer
movl $m_args,%esi # Format string
- leal 0x4(%esp,1),%ebx # First argument
+ leal 0x4(%esp),%ebx # First argument
movl $0x6,%ecx # Count
start.1: movl (%ebx),%eax # Get argument and
addl $0x4,%ebx # bump pointer
@@ -97,24 +99,28 @@
loop start.1 # Till done
call putstr # End message
#endif
- movl $0x48,%ecx # Allocate space
- subl %ecx,%ebp # for bootinfo
- movl 0x18(%esp,1),%esi # Source: bootinfo
+ movl BA_BOOTINFO+4(%esp),%esi # Source: bootinfo
cmpl $0x0, %esi # If the bootinfo pointer
je start_null_bi # is null, don't copy it
+ movl BI_SIZE(%esi),%ecx # Allocate space
+ subl %ecx,%ebp # for bootinfo
movl %ebp,%edi # Destination
rep # Copy
movsb # it
- movl %ebp,0x18(%esp,1) # Update pointer
+ movl %ebp,BA_BOOTINFO+4(%esp) # Update pointer
+ movl %edi,%ebp # Restore base pointer
#ifdef BTXLDR_VERBOSE
movl $m_rel_bi,%esi # Display
movl %ebp,%eax # bootinfo
call hexout # relocation
call putstr # message
#endif
-start_null_bi: movl $0x18,%ecx # Allocate space
- subl %ecx,%ebp # for arguments
- leal 0x4(%esp,1),%esi # Source
+start_null_bi: movl $BOOTARGS_SIZE,%ecx # Fixed size of arguments
+ testl $KARGS_FLAGS_EXTARG, BA_BOOTFLAGS+4(%esp) # Check for extra data
+ jz start_fixed # Skip if the flag is not set
+ addl BOOTARGS_SIZE+4(%esp),%ecx # Add size of variable args
+start_fixed: subl $ARGOFF,%ebp # Place args at fixed offset
+ leal 0x4(%esp),%esi # Source
movl %ebp,%edi # Destination
rep # Copy
movsb # them
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/btx/lib/Makefile
--- a/head/sys/boot/i386/btx/lib/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/btx/lib/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,9 +1,10 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/boot/i386/btx/lib/Makefile 235154 2012-05-09 08:04:29Z avg $
PROG= crt0.o
INTERNALPROG=
NO_MAN=
-SRCS= btxcsu.s btxsys.s btxv86.s
+SRCS= btxcsu.S btxsys.s btxv86.s
+CFLAGS+=-I${.CURDIR}/../../common
LDFLAGS=-Wl,-r
.include <bsd.prog.mk>
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/btx/lib/btxcsu.S
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/i386/btx/lib/btxcsu.S Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 1998 Robert Nordier
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are freely
+# permitted provided that the above copyright notice and this
+# paragraph and the following disclaimer are duplicated in all
+# such forms.
+#
+# This software is provided "AS IS" and without any express or
+# implied warranties, including, without limitation, the implied
+# warranties of merchantability and fitness for a particular
+# purpose.
+#
+
+# $FreeBSD: head/sys/boot/i386/btx/lib/btxcsu.S 235154 2012-05-09 08:04:29Z avg $
+
+#include <bootargs.h>
+
+#
+# BTX C startup code (ELF).
+#
+
+#
+# Globals.
+#
+ .global _start
+#
+# Client entry point.
+#
+_start: cld
+ pushl %eax
+ movl $_edata,%edi
+ movl $_end,%ecx
+ subl %edi, %ecx
+ xorb %al, %al
+ rep
+ stosb
+ popl __base
+ movl %esp,%eax # Set
+ addl $ARGADJ,%eax # argument
+ movl %eax,__args # pointer
+ call main # Invoke client main()
+ call exit # Invoke client exit()
+#
+# Data.
+#
+ .comm __base,4 # Client base address
+ .comm __args,4 # Client arguments
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/btx/lib/btxcsu.s
--- a/head/sys/boot/i386/btx/lib/btxcsu.s Wed Jul 25 16:42:35 2012 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-#
-# Copyright (c) 1998 Robert Nordier
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms are freely
-# permitted provided that the above copyright notice and this
-# paragraph and the following disclaimer are duplicated in all
-# such forms.
-#
-# This software is provided "AS IS" and without any express or
-# implied warranties, including, without limitation, the implied
-# warranties of merchantability and fitness for a particular
-# purpose.
-#
-
-# $FreeBSD$
-
-#
-# BTX C startup code (ELF).
-#
-
-#
-# Globals.
-#
- .global _start
-#
-# Constants.
-#
- .set ARGADJ,0xfa0 # Argument adjustment
-#
-# Client entry point.
-#
-_start: cld
- pushl %eax
- movl $_edata,%edi
- movl $_end,%ecx
- subl %edi, %ecx
- xorb %al, %al
- rep
- stosb
- popl __base
- movl %esp,%eax # Set
- addl $ARGADJ,%eax # argument
- movl %eax,__args # pointer
- call main # Invoke client main()
- call exit # Invoke client exit()
-#
-# Data.
-#
- .comm __base,4 # Client base address
- .comm __args,4 # Client arguments
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/cdboot/Makefile
--- a/head/sys/boot/i386/cdboot/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/cdboot/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,13 +1,19 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/boot/i386/cdboot/Makefile 235281 2012-05-11 18:07:23Z dim $
PROG= cdboot
STRIP=
BINMODE=${NOBINMODE}
NO_MAN=
-SRCS= ${PROG}.s
+SRCS= ${PROG}.S
+
+CFLAGS+=-I${.CURDIR}/../common
ORG= 0x7c00
LDFLAGS=-e start -Ttext ${ORG} -Wl,-N,-S,--oformat,binary
.include <bsd.prog.mk>
+
+# XXX: clang integrated-as doesn't grok .codeNN directives yet
+CFLAGS.cdboot.S= ${CLANG_NO_IAS}
+CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/cdboot/cdboot.S
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/i386/cdboot/cdboot.S Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,597 @@
+#
+# Copyright (c) 2001 John Baldwin <jhb at FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the author nor the names of any co-contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+# $FreeBSD: head/sys/boot/i386/cdboot/cdboot.S 235219 2012-05-10 09:47:04Z avg $
+
+#
+# This program is a freestanding boot program to load an a.out binary
+# from a CD-ROM booted with no emulation mode as described by the El
+# Torito standard. Due to broken BIOSen that do not load the desired
+# number of sectors, we try to fit this in as small a space as possible.
+#
+# Basically, we first create a set of boot arguments to pass to the loaded
+# binary. Then we attempt to load /boot/loader from the CD we were booted
+# off of.
+#
+
+#include <bootargs.h>
+
+#
+# Memory locations.
+#
+ .set MEM_PAGE_SIZE,0x1000 # memory page size, 4k
+ .set MEM_ARG,0x900 # Arguments at start
+ .set MEM_ARG_BTX,0xa100 # Where we move them to so the
+ # BTX client can see them
+ .set MEM_ARG_SIZE,0x18 # Size of the arguments
+ .set MEM_BTX_ADDRESS,0x9000 # where BTX lives
+ .set MEM_BTX_ENTRY,0x9010 # where BTX starts to execute
+ .set MEM_BTX_OFFSET,MEM_PAGE_SIZE # offset of BTX in the loader
+ .set MEM_BTX_CLIENT,0xa000 # where BTX clients live
+#
+# a.out header fields
+#
+ .set AOUT_TEXT,0x04 # text segment size
+ .set AOUT_DATA,0x08 # data segment size
+ .set AOUT_BSS,0x0c # zero'd BSS size
+ .set AOUT_SYMBOLS,0x10 # symbol table
+ .set AOUT_ENTRY,0x14 # entry point
+ .set AOUT_HEADER,MEM_PAGE_SIZE # size of the a.out header
+#
+# Segment selectors.
+#
+ .set SEL_SDATA,0x8 # Supervisor data
+ .set SEL_RDATA,0x10 # Real mode data
+ .set SEL_SCODE,0x18 # PM-32 code
+ .set SEL_SCODE16,0x20 # PM-16 code
+#
+# BTX constants
+#
+ .set INT_SYS,0x30 # BTX syscall interrupt
+#
+# Constants for reading from the CD.
+#
+ .set ERROR_TIMEOUT,0x80 # BIOS timeout on read
+ .set NUM_RETRIES,3 # Num times to retry
+ .set SECTOR_SIZE,0x800 # size of a sector
+ .set SECTOR_SHIFT,11 # number of place to shift
+ .set BUFFER_LEN,0x100 # number of sectors in buffer
+ .set MAX_READ,0x10000 # max we can read at a time
+ .set MAX_READ_SEC,MAX_READ >> SECTOR_SHIFT
+ .set MEM_READ_BUFFER,0x9000 # buffer to read from CD
+ .set MEM_VOLDESC,MEM_READ_BUFFER # volume descriptor
+ .set MEM_DIR,MEM_VOLDESC+SECTOR_SIZE # Lookup buffer
+ .set VOLDESC_LBA,0x10 # LBA of vol descriptor
+ .set VD_PRIMARY,1 # Primary VD
+ .set VD_END,255 # VD Terminator
+ .set VD_ROOTDIR,156 # Offset of Root Dir Record
+ .set DIR_LEN,0 # Offset of Dir Record length
+ .set DIR_EA_LEN,1 # Offset of EA length
+ .set DIR_EXTENT,2 # Offset of 64-bit LBA
+ .set DIR_SIZE,10 # Offset of 64-bit length
+ .set DIR_NAMELEN,32 # Offset of 8-bit name len
+ .set DIR_NAME,33 # Offset of dir name
+#
+# We expect to be loaded by the BIOS at 0x7c00 (standard boot loader entry
+# point)
+#
+ .code16
+ .globl start
+ .org 0x0, 0x0
+#
+# Program start.
+#
+start: cld # string ops inc
+ xor %ax,%ax # zero %ax
+ mov %ax,%ss # setup the
+ mov $start,%sp # stack
+ mov %ax,%ds # setup the
+ mov %ax,%es # data segments
+ mov %dl,drive # Save BIOS boot device
+ mov $msg_welcome,%si # %ds:(%si) -> welcome message
+ call putstr # display the welcome message
+#
+# Setup the arguments that the loader is expecting from boot[12]
+#
+ mov $msg_bootinfo,%si # %ds:(%si) -> boot args message
+ call putstr # display the message
+ mov $MEM_ARG,%bx # %ds:(%bx) -> boot args
+ mov %bx,%di # %es:(%di) -> boot args
+ xor %eax,%eax # zero %eax
+ mov $(MEM_ARG_SIZE/4),%cx # Size of arguments in 32-bit
+ # dwords
+ rep # Clear the arguments
+ stosl # to zero
+ mov drive,%dl # Store BIOS boot device
+ mov %dl,0x4(%bx) # in kargs->bootdev
+ or $KARGS_FLAGS_CD,0x8(%bx) # kargs->bootflags |=
+ # KARGS_FLAGS_CD
+#
+# Load Volume Descriptor
+#
+ mov $VOLDESC_LBA,%eax # Set LBA of first VD
+load_vd: push %eax # Save %eax
+ mov $1,%dh # One sector
+ mov $MEM_VOLDESC,%ebx # Destination
+ call read # Read it in
+ cmpb $VD_PRIMARY,(%bx) # Primary VD?
+ je have_vd # Yes
+ pop %eax # Prepare to
+ inc %eax # try next
+ cmpb $VD_END,(%bx) # Last VD?
+ jne load_vd # No, read next
+ mov $msg_novd,%si # No VD
+ jmp error # Halt
+have_vd: # Have Primary VD
+#
+# Try to look up the loader binary using the paths in the loader_paths
+# array.
+#
+ mov $loader_paths,%si # Point to start of array
+lookup_path: push %si # Save file name pointer
+ call lookup # Try to find file
+ pop %di # Restore file name pointer
+ jnc lookup_found # Found this file
+ xor %al,%al # Look for next
+ mov $0xffff,%cx # path name by
+ repnz # scanning for
+ scasb # nul char
+ mov %di,%si # Point %si at next path
+ mov (%si),%al # Get first char of next path
+ or %al,%al # Is it double nul?
+ jnz lookup_path # No, try it.
+ mov $msg_failed,%si # Failed message
+ jmp error # Halt
+lookup_found: # Found a loader file
+#
+# Load the binary into the buffer. Due to real mode addressing limitations
+# we have to read it in 64k chunks.
+#
+ mov DIR_SIZE(%bx),%eax # Read file length
+ add $SECTOR_SIZE-1,%eax # Convert length to sectors
+ shr $SECTOR_SHIFT,%eax
+ cmp $BUFFER_LEN,%eax
+ jbe load_sizeok
+ mov $msg_load2big,%si # Error message
+ call error
+load_sizeok: movzbw %al,%cx # Num sectors to read
+ mov DIR_EXTENT(%bx),%eax # Load extent
+ xor %edx,%edx
+ mov DIR_EA_LEN(%bx),%dl
+ add %edx,%eax # Skip extended
+ mov $MEM_READ_BUFFER,%ebx # Read into the buffer
+load_loop: mov %cl,%dh
+ cmp $MAX_READ_SEC,%cl # Truncate to max read size
+ jbe load_notrunc
+ mov $MAX_READ_SEC,%dh
+load_notrunc: sub %dh,%cl # Update count
+ push %eax # Save
+ call read # Read it in
+ pop %eax # Restore
+ add $MAX_READ_SEC,%eax # Update LBA
+ add $MAX_READ,%ebx # Update dest addr
+ jcxz load_done # Done?
+ jmp load_loop # Keep going
+load_done:
+#
+# Turn on the A20 address line
+#
+ call seta20 # Turn A20 on
+#
+# Relocate the loader and BTX using a very lazy protected mode
+#
+ mov $msg_relocate,%si # Display the
+ call putstr # relocation message
+ mov MEM_READ_BUFFER+AOUT_ENTRY,%edi # %edi is the destination
+ mov $(MEM_READ_BUFFER+AOUT_HEADER),%esi # %esi is
+ # the start of the text
+ # segment
+ mov MEM_READ_BUFFER+AOUT_TEXT,%ecx # %ecx = length of the text
+ # segment
+ push %edi # Save entry point for later
+ lgdt gdtdesc # setup our own gdt
+ cli # turn off interrupts
+ mov %cr0,%eax # Turn on
+ or $0x1,%al # protected
+ mov %eax,%cr0 # mode
+ ljmp $SEL_SCODE,$pm_start # long jump to clear the
+ # instruction pre-fetch queue
+ .code32
+pm_start: mov $SEL_SDATA,%ax # Initialize
+ mov %ax,%ds # %ds and
+ mov %ax,%es # %es to a flat selector
+ rep # Relocate the
+ movsb # text segment
+ add $(MEM_PAGE_SIZE - 1),%edi # pad %edi out to a new page
+ and $~(MEM_PAGE_SIZE - 1),%edi # for the data segment
+ mov MEM_READ_BUFFER+AOUT_DATA,%ecx # size of the data segment
+ rep # Relocate the
+ movsb # data segment
+ mov MEM_READ_BUFFER+AOUT_BSS,%ecx # size of the bss
+ xor %eax,%eax # zero %eax
+ add $3,%cl # round %ecx up to
+ shr $2,%ecx # a multiple of 4
+ rep # zero the
+ stosl # bss
+ mov MEM_READ_BUFFER+AOUT_ENTRY,%esi # %esi -> relocated loader
+ add $MEM_BTX_OFFSET,%esi # %esi -> BTX in the loader
+ mov $MEM_BTX_ADDRESS,%edi # %edi -> where BTX needs to go
+ movzwl 0xa(%esi),%ecx # %ecx -> length of BTX
+ rep # Relocate
+ movsb # BTX
+ ljmp $SEL_SCODE16,$pm_16 # Jump to 16-bit PM
+ .code16
+pm_16: mov $SEL_RDATA,%ax # Initialize
+ mov %ax,%ds # %ds and
+ mov %ax,%es # %es to a real mode selector
+ mov %cr0,%eax # Turn off
+ and $~0x1,%al # protected
+ mov %eax,%cr0 # mode
+ ljmp $0,$pm_end # Long jump to clear the
+ # instruction pre-fetch queue
+pm_end: sti # Turn interrupts back on now
+#
+# Copy the BTX client to MEM_BTX_CLIENT
+#
+ xor %ax,%ax # zero %ax and set
+ mov %ax,%ds # %ds and %es
+ mov %ax,%es # to segment 0
+ mov $MEM_BTX_CLIENT,%di # Prepare to relocate
+ mov $btx_client,%si # the simple btx client
+ mov $(btx_client_end-btx_client),%cx # length of btx client
+ rep # Relocate the
+ movsb # simple BTX client
+#
+# Copy the boot[12] args to where the BTX client can see them
+#
+ mov $MEM_ARG,%si # where the args are at now
+ mov $MEM_ARG_BTX,%di # where the args are moving to
+ mov $(MEM_ARG_SIZE/4),%cx # size of the arguments in longs
+ rep # Relocate
+ movsl # the words
+#
+# Save the entry point so the client can get to it later on
+#
+ pop %eax # Restore saved entry point
+ stosl # and add it to the end of
+ # the arguments
+#
+# Now we just start up BTX and let it do the rest
+#
+ mov $msg_jump,%si # Display the
+ call putstr # jump message
+ ljmp $0,$MEM_BTX_ENTRY # Jump to the BTX entry point
+
+#
+# Lookup the file in the path at [SI] from the root directory.
+#
+# Trashes: All but BX
+# Returns: CF = 0 (success), BX = pointer to record
+# CF = 1 (not found)
+#
+lookup: mov $VD_ROOTDIR+MEM_VOLDESC,%bx # Root directory record
+ push %si
+ mov $msg_lookup,%si # Display lookup message
+ call putstr
+ pop %si
+ push %si
+ call putstr
+ mov $msg_lookup2,%si
+ call putstr
+ pop %si
+lookup_dir: lodsb # Get first char of path
+ cmp $0,%al # Are we done?
+ je lookup_done # Yes
+ cmp $'/',%al # Skip path separator.
+ je lookup_dir
+ dec %si # Undo lodsb side effect
+ call find_file # Lookup first path item
+ jnc lookup_dir # Try next component
+ mov $msg_lookupfail,%si # Not found message
+ call putstr
+ stc # Set carry
+ ret
+ jmp error
+lookup_done: mov $msg_lookupok,%si # Success message
+ call putstr
+ clc # Clear carry
+ ret
+
+#
+# Lookup file at [SI] in directory whose record is at [BX].
+#
+# Trashes: All but returns
+# Returns: CF = 0 (success), BX = pointer to record, SI = next path item
+# CF = 1 (not found), SI = preserved
+#
+find_file: mov DIR_EXTENT(%bx),%eax # Load extent
+ xor %edx,%edx
+ mov DIR_EA_LEN(%bx),%dl
+ add %edx,%eax # Skip extended attributes
+ mov %eax,rec_lba # Save LBA
+ mov DIR_SIZE(%bx),%eax # Save size
+ mov %eax,rec_size
+ xor %cl,%cl # Zero length
+ push %si # Save
+ff.namelen: inc %cl # Update length
+ lodsb # Read char
+ cmp $0,%al # Nul?
+ je ff.namedone # Yes
+ cmp $'/',%al # Path separator?
+ jnz ff.namelen # No, keep going
+ff.namedone: dec %cl # Adjust length and save
+ mov %cl,name_len
+ pop %si # Restore
+ff.load: mov rec_lba,%eax # Load LBA
+ mov $MEM_DIR,%ebx # Address buffer
+ mov $1,%dh # One sector
+ call read # Read directory block
+ incl rec_lba # Update LBA to next block
+ff.scan: mov %ebx,%edx # Check for EOF
+ sub $MEM_DIR,%edx
+ cmp %edx,rec_size
+ ja ff.scan.1
+ stc # EOF reached
+ ret
+ff.scan.1: cmpb $0,DIR_LEN(%bx) # Last record in block?
+ je ff.nextblock
+ push %si # Save
+ movzbw DIR_NAMELEN(%bx),%si # Find end of string
+ff.checkver: cmpb $'0',DIR_NAME-1(%bx,%si) # Less than '0'?
+ jb ff.checkver.1
+ cmpb $'9',DIR_NAME-1(%bx,%si) # Greater than '9'?
+ ja ff.checkver.1
+ dec %si # Next char
+ jnz ff.checkver
+ jmp ff.checklen # All numbers in name, so
+ # no version
+ff.checkver.1: movzbw DIR_NAMELEN(%bx),%cx
+ cmp %cx,%si # Did we find any digits?
+ je ff.checkdot # No
+ cmpb $';',DIR_NAME-1(%bx,%si) # Check for semicolon
+ jne ff.checkver.2
+ dec %si # Skip semicolon
+ mov %si,%cx
+ mov %cl,DIR_NAMELEN(%bx) # Adjust length
+ jmp ff.checkdot
+ff.checkver.2: mov %cx,%si # Restore %si to end of string
+ff.checkdot: cmpb $'.',DIR_NAME-1(%bx,%si) # Trailing dot?
+ jne ff.checklen # No
+ decb DIR_NAMELEN(%bx) # Adjust length
+ff.checklen: pop %si # Restore
+ movzbw name_len,%cx # Load length of name
+ cmp %cl,DIR_NAMELEN(%bx) # Does length match?
+ je ff.checkname # Yes, check name
+ff.nextrec: add DIR_LEN(%bx),%bl # Next record
+ adc $0,%bh
+ jmp ff.scan
+ff.nextblock: subl $SECTOR_SIZE,rec_size # Adjust size
+ jnc ff.load # If subtract ok, keep going
+ ret # End of file, so not found
+ff.checkname: lea DIR_NAME(%bx),%di # Address name in record
+ push %si # Save
+ repe cmpsb # Compare name
+ je ff.match # We have a winner!
+ pop %si # Restore
+ jmp ff.nextrec # Keep looking.
+ff.match: add $2,%sp # Discard saved %si
+ clc # Clear carry
+ ret
+
+#
+# Load DH sectors starting at LBA EAX into [EBX].
+#
+# Trashes: EAX
+#
+read: push %si # Save
+ push %cx # Save since some BIOSs trash
+ mov %eax,edd_lba # LBA to read from
+ mov %ebx,%eax # Convert address
+ shr $4,%eax # to segment
+ mov %ax,edd_addr+0x2 # and store
+read.retry: call twiddle # Entertain the user
+ push %dx # Save
+ mov $edd_packet,%si # Address Packet
+ mov %dh,edd_len # Set length
+ mov drive,%dl # BIOS Device
+ mov $0x42,%ah # BIOS: Extended Read
+ int $0x13 # Call BIOS
+ pop %dx # Restore
+ jc read.fail # Worked?
+ pop %cx # Restore
+ pop %si
+ ret # Return
+read.fail: cmp $ERROR_TIMEOUT,%ah # Timeout?
+ je read.retry # Yes, Retry.
+read.error: mov %ah,%al # Save error
+ mov $hex_error,%di # Format it
+ call hex8 # as hex
+ mov $msg_badread,%si # Display Read error message
+
+#
+# Display error message at [SI] and halt.
+#
+error: call putstr # Display message
+halt: hlt
+ jmp halt # Spin
+
+#
+# Display a null-terminated string.
+#
+# Trashes: AX, SI
+#
+putstr: push %bx # Save
+putstr.load: lodsb # load %al from %ds:(%si)
+ test %al,%al # stop at null
+ jnz putstr.putc # if the char != null, output it
+ pop %bx # Restore
+ ret # return when null is hit
+putstr.putc: call putc # output char
+ jmp putstr.load # next char
+
+#
+# Display a single char.
+#
+putc: mov $0x7,%bx # attribute for output
+ mov $0xe,%ah # BIOS: put_char
+ int $0x10 # call BIOS, print char in %al
+ ret # Return to caller
+
+#
+# Output the "twiddle"
+#
+twiddle: push %ax # Save
+ push %bx # Save
+ mov twiddle_index,%al # Load index
+ mov $twiddle_chars,%bx # Address table
+ inc %al # Next
+ and $3,%al # char
+ mov %al,twiddle_index # Save index for next call
+ xlat # Get char
+ call putc # Output it
+ mov $8,%al # Backspace
+ call putc # Output it
+ pop %bx # Restore
+ pop %ax # Restore
+ ret
+
+#
+# Enable A20. Put an upper limit on the amount of time we wait for the
+# keyboard controller to get ready (65K x ISA access time). If
+# we wait more than that amount, the hardware is probably
+# legacy-free and simply doesn't have a keyboard controller.
+# Thus, the A20 line is already enabled.
+#
+seta20: cli # Disable interrupts
+ xor %cx,%cx # Clear
+seta20.1: inc %cx # Increment, overflow?
+ jz seta20.3 # Yes
+ in $0x64,%al # Get status
+ test $0x2,%al # Busy?
+ jnz seta20.1 # Yes
+ mov $0xd1,%al # Command: Write
+ out %al,$0x64 # output port
+seta20.2: in $0x64,%al # Get status
+ test $0x2,%al # Busy?
+ jnz seta20.2 # Yes
+ mov $0xdf,%al # Enable
+ out %al,$0x60 # A20
+seta20.3: sti # Enable interrupts
+ ret # To caller
+
+#
+# Convert AL to hex, saving the result to [EDI].
+#
+hex8: pushl %eax # Save
+ shrb $0x4,%al # Do upper
+ call hex8.1 # 4
+ popl %eax # Restore
+hex8.1: andb $0xf,%al # Get lower 4
+ cmpb $0xa,%al # Convert
+ sbbb $0x69,%al # to hex
+ das # digit
+ orb $0x20,%al # To lower case
+ stosb # Save char
+ ret # (Recursive)
+
+#
+# BTX client to start btxldr
+#
+ .code32
+btx_client: mov $(MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE-4), %esi
+ # %ds:(%esi) -> end
+ # of boot[12] args
+ mov $(MEM_ARG_SIZE/4),%ecx # Number of words to push
+ std # Go backwards
+push_arg: lodsl # Read argument
+ push %eax # Push it onto the stack
+ loop push_arg # Push all of the arguments
+ cld # In case anyone depends on this
+ pushl MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE # Entry point of
+ # the loader
+ push %eax # Emulate a near call
+ mov $0x1,%eax # 'exec' system call
+ int $INT_SYS # BTX system call
+btx_client_end:
+ .code16
+
+ .p2align 4
+#
+# Global descriptor table.
+#
+gdt: .word 0x0,0x0,0x0,0x0 # Null entry
+ .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
+ .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
+ .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE (32-bit)
+ .word 0xffff,0x0,0x9a00,0x8f # SEL_SCODE16 (16-bit)
+gdt.1:
+#
+# Pseudo-descriptors.
+#
+gdtdesc: .word gdt.1-gdt-1 # Limit
+ .long gdt # Base
+#
+# EDD Packet
+#
+edd_packet: .byte 0x10 # Length
+ .byte 0 # Reserved
+edd_len: .byte 0x0 # Num to read
+ .byte 0 # Reserved
+edd_addr: .word 0x0,0x0 # Seg:Off
+edd_lba: .quad 0x0 # LBA
+
+drive: .byte 0
+
+#
+# State for searching dir
+#
+rec_lba: .long 0x0 # LBA (adjusted for EA)
+rec_size: .long 0x0 # File size
+name_len: .byte 0x0 # Length of current name
+
+twiddle_index: .byte 0x0
+
+msg_welcome: .asciz "CD Loader 1.2\r\n\n"
+msg_bootinfo: .asciz "Building the boot loader arguments\r\n"
+msg_relocate: .asciz "Relocating the loader and the BTX\r\n"
+msg_jump: .asciz "Starting the BTX loader\r\n"
+msg_badread: .ascii "Read Error: 0x"
+hex_error: .asciz "00\r\n"
+msg_novd: .asciz "Could not find Primary Volume Descriptor\r\n"
+msg_lookup: .asciz "Looking up "
+msg_lookup2: .asciz "... "
+msg_lookupok: .asciz "Found\r\n"
+msg_lookupfail: .asciz "File not found\r\n"
+msg_load2big: .asciz "File too big\r\n"
+msg_failed: .asciz "Boot failed\r\n"
+twiddle_chars: .ascii "|/-\\"
+loader_paths: .asciz "/BOOT/LOADER"
+ .asciz "/boot/loader"
+ .byte 0
+
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/cdboot/cdboot.s
--- a/head/sys/boot/i386/cdboot/cdboot.s Wed Jul 25 16:42:35 2012 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,600 +0,0 @@
-#
-# Copyright (c) 2001 John Baldwin <jhb at FreeBSD.org>
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# 3. Neither the name of the author nor the names of any co-contributors
-# may be used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-
-# $FreeBSD$
-
-#
-# This program is a freestanding boot program to load an a.out binary
-# from a CD-ROM booted with no emulation mode as described by the El
-# Torito standard. Due to broken BIOSen that do not load the desired
-# number of sectors, we try to fit this in as small a space as possible.
-#
-# Basically, we first create a set of boot arguments to pass to the loaded
-# binary. Then we attempt to load /boot/loader from the CD we were booted
-# off of.
-#
-
-#
-# Memory locations.
-#
- .set MEM_PAGE_SIZE,0x1000 # memory page size, 4k
- .set MEM_ARG,0x900 # Arguments at start
- .set MEM_ARG_BTX,0xa100 # Where we move them to so the
- # BTX client can see them
- .set MEM_ARG_SIZE,0x18 # Size of the arguments
- .set MEM_BTX_ADDRESS,0x9000 # where BTX lives
- .set MEM_BTX_ENTRY,0x9010 # where BTX starts to execute
- .set MEM_BTX_OFFSET,MEM_PAGE_SIZE # offset of BTX in the loader
- .set MEM_BTX_CLIENT,0xa000 # where BTX clients live
-#
-# a.out header fields
-#
- .set AOUT_TEXT,0x04 # text segment size
- .set AOUT_DATA,0x08 # data segment size
- .set AOUT_BSS,0x0c # zero'd BSS size
- .set AOUT_SYMBOLS,0x10 # symbol table
- .set AOUT_ENTRY,0x14 # entry point
- .set AOUT_HEADER,MEM_PAGE_SIZE # size of the a.out header
-#
-# Flags for kargs->bootflags
-#
- .set KARGS_FLAGS_CD,0x1 # flag to indicate booting from
- # CD loader
-#
-# Segment selectors.
-#
- .set SEL_SDATA,0x8 # Supervisor data
- .set SEL_RDATA,0x10 # Real mode data
- .set SEL_SCODE,0x18 # PM-32 code
- .set SEL_SCODE16,0x20 # PM-16 code
-#
-# BTX constants
-#
- .set INT_SYS,0x30 # BTX syscall interrupt
-#
-# Constants for reading from the CD.
-#
- .set ERROR_TIMEOUT,0x80 # BIOS timeout on read
- .set NUM_RETRIES,3 # Num times to retry
- .set SECTOR_SIZE,0x800 # size of a sector
- .set SECTOR_SHIFT,11 # number of place to shift
- .set BUFFER_LEN,0x100 # number of sectors in buffer
- .set MAX_READ,0x10000 # max we can read at a time
- .set MAX_READ_SEC,MAX_READ >> SECTOR_SHIFT
- .set MEM_READ_BUFFER,0x9000 # buffer to read from CD
- .set MEM_VOLDESC,MEM_READ_BUFFER # volume descriptor
- .set MEM_DIR,MEM_VOLDESC+SECTOR_SIZE # Lookup buffer
- .set VOLDESC_LBA,0x10 # LBA of vol descriptor
- .set VD_PRIMARY,1 # Primary VD
- .set VD_END,255 # VD Terminator
- .set VD_ROOTDIR,156 # Offset of Root Dir Record
- .set DIR_LEN,0 # Offset of Dir Record length
- .set DIR_EA_LEN,1 # Offset of EA length
- .set DIR_EXTENT,2 # Offset of 64-bit LBA
- .set DIR_SIZE,10 # Offset of 64-bit length
- .set DIR_NAMELEN,32 # Offset of 8-bit name len
- .set DIR_NAME,33 # Offset of dir name
-#
-# We expect to be loaded by the BIOS at 0x7c00 (standard boot loader entry
-# point)
-#
- .code16
- .globl start
- .org 0x0, 0x0
-#
-# Program start.
-#
-start: cld # string ops inc
- xor %ax,%ax # zero %ax
- mov %ax,%ss # setup the
- mov $start,%sp # stack
- mov %ax,%ds # setup the
- mov %ax,%es # data segments
- mov %dl,drive # Save BIOS boot device
- mov $msg_welcome,%si # %ds:(%si) -> welcome message
- call putstr # display the welcome message
-#
-# Setup the arguments that the loader is expecting from boot[12]
-#
- mov $msg_bootinfo,%si # %ds:(%si) -> boot args message
- call putstr # display the message
- mov $MEM_ARG,%bx # %ds:(%bx) -> boot args
- mov %bx,%di # %es:(%di) -> boot args
- xor %eax,%eax # zero %eax
- mov $(MEM_ARG_SIZE/4),%cx # Size of arguments in 32-bit
- # dwords
- rep # Clear the arguments
- stosl # to zero
- mov drive,%dl # Store BIOS boot device
- mov %dl,0x4(%bx) # in kargs->bootdev
- or $KARGS_FLAGS_CD,0x8(%bx) # kargs->bootflags |=
- # KARGS_FLAGS_CD
-#
-# Load Volume Descriptor
-#
- mov $VOLDESC_LBA,%eax # Set LBA of first VD
-load_vd: push %eax # Save %eax
- mov $1,%dh # One sector
- mov $MEM_VOLDESC,%ebx # Destination
- call read # Read it in
- cmpb $VD_PRIMARY,(%bx) # Primary VD?
- je have_vd # Yes
- pop %eax # Prepare to
- inc %eax # try next
- cmpb $VD_END,(%bx) # Last VD?
- jne load_vd # No, read next
- mov $msg_novd,%si # No VD
- jmp error # Halt
-have_vd: # Have Primary VD
-#
-# Try to look up the loader binary using the paths in the loader_paths
-# array.
-#
- mov $loader_paths,%si # Point to start of array
-lookup_path: push %si # Save file name pointer
- call lookup # Try to find file
- pop %di # Restore file name pointer
- jnc lookup_found # Found this file
- xor %al,%al # Look for next
- mov $0xffff,%cx # path name by
- repnz # scanning for
- scasb # nul char
- mov %di,%si # Point %si at next path
- mov (%si),%al # Get first char of next path
- or %al,%al # Is it double nul?
- jnz lookup_path # No, try it.
- mov $msg_failed,%si # Failed message
- jmp error # Halt
-lookup_found: # Found a loader file
-#
-# Load the binary into the buffer. Due to real mode addressing limitations
-# we have to read it in 64k chunks.
-#
- mov DIR_SIZE(%bx),%eax # Read file length
- add $SECTOR_SIZE-1,%eax # Convert length to sectors
- shr $SECTOR_SHIFT,%eax
- cmp $BUFFER_LEN,%eax
- jbe load_sizeok
- mov $msg_load2big,%si # Error message
- call error
-load_sizeok: movzbw %al,%cx # Num sectors to read
- mov DIR_EXTENT(%bx),%eax # Load extent
- xor %edx,%edx
- mov DIR_EA_LEN(%bx),%dl
- add %edx,%eax # Skip extended
- mov $MEM_READ_BUFFER,%ebx # Read into the buffer
-load_loop: mov %cl,%dh
- cmp $MAX_READ_SEC,%cl # Truncate to max read size
- jbe load_notrunc
- mov $MAX_READ_SEC,%dh
-load_notrunc: sub %dh,%cl # Update count
- push %eax # Save
- call read # Read it in
- pop %eax # Restore
- add $MAX_READ_SEC,%eax # Update LBA
- add $MAX_READ,%ebx # Update dest addr
- jcxz load_done # Done?
- jmp load_loop # Keep going
-load_done:
-#
-# Turn on the A20 address line
-#
- call seta20 # Turn A20 on
-#
-# Relocate the loader and BTX using a very lazy protected mode
-#
- mov $msg_relocate,%si # Display the
- call putstr # relocation message
- mov MEM_READ_BUFFER+AOUT_ENTRY,%edi # %edi is the destination
- mov $(MEM_READ_BUFFER+AOUT_HEADER),%esi # %esi is
- # the start of the text
- # segment
- mov MEM_READ_BUFFER+AOUT_TEXT,%ecx # %ecx = length of the text
- # segment
- push %edi # Save entry point for later
- lgdt gdtdesc # setup our own gdt
- cli # turn off interrupts
- mov %cr0,%eax # Turn on
- or $0x1,%al # protected
- mov %eax,%cr0 # mode
- ljmp $SEL_SCODE,$pm_start # long jump to clear the
- # instruction pre-fetch queue
- .code32
-pm_start: mov $SEL_SDATA,%ax # Initialize
- mov %ax,%ds # %ds and
- mov %ax,%es # %es to a flat selector
- rep # Relocate the
- movsb # text segment
- add $(MEM_PAGE_SIZE - 1),%edi # pad %edi out to a new page
- and $~(MEM_PAGE_SIZE - 1),%edi # for the data segment
- mov MEM_READ_BUFFER+AOUT_DATA,%ecx # size of the data segment
- rep # Relocate the
- movsb # data segment
- mov MEM_READ_BUFFER+AOUT_BSS,%ecx # size of the bss
- xor %eax,%eax # zero %eax
- add $3,%cl # round %ecx up to
- shr $2,%ecx # a multiple of 4
- rep # zero the
- stosl # bss
- mov MEM_READ_BUFFER+AOUT_ENTRY,%esi # %esi -> relocated loader
- add $MEM_BTX_OFFSET,%esi # %esi -> BTX in the loader
- mov $MEM_BTX_ADDRESS,%edi # %edi -> where BTX needs to go
- movzwl 0xa(%esi),%ecx # %ecx -> length of BTX
- rep # Relocate
- movsb # BTX
- ljmp $SEL_SCODE16,$pm_16 # Jump to 16-bit PM
- .code16
-pm_16: mov $SEL_RDATA,%ax # Initialize
- mov %ax,%ds # %ds and
- mov %ax,%es # %es to a real mode selector
- mov %cr0,%eax # Turn off
- and $~0x1,%al # protected
- mov %eax,%cr0 # mode
- ljmp $0,$pm_end # Long jump to clear the
- # instruction pre-fetch queue
-pm_end: sti # Turn interrupts back on now
-#
-# Copy the BTX client to MEM_BTX_CLIENT
-#
- xor %ax,%ax # zero %ax and set
- mov %ax,%ds # %ds and %es
- mov %ax,%es # to segment 0
- mov $MEM_BTX_CLIENT,%di # Prepare to relocate
- mov $btx_client,%si # the simple btx client
- mov $(btx_client_end-btx_client),%cx # length of btx client
- rep # Relocate the
- movsb # simple BTX client
-#
-# Copy the boot[12] args to where the BTX client can see them
-#
- mov $MEM_ARG,%si # where the args are at now
- mov $MEM_ARG_BTX,%di # where the args are moving to
- mov $(MEM_ARG_SIZE/4),%cx # size of the arguments in longs
- rep # Relocate
- movsl # the words
-#
-# Save the entry point so the client can get to it later on
-#
- pop %eax # Restore saved entry point
- stosl # and add it to the end of
- # the arguments
-#
-# Now we just start up BTX and let it do the rest
-#
- mov $msg_jump,%si # Display the
- call putstr # jump message
- ljmp $0,$MEM_BTX_ENTRY # Jump to the BTX entry point
-
-#
-# Lookup the file in the path at [SI] from the root directory.
-#
-# Trashes: All but BX
-# Returns: CF = 0 (success), BX = pointer to record
-# CF = 1 (not found)
-#
-lookup: mov $VD_ROOTDIR+MEM_VOLDESC,%bx # Root directory record
- push %si
- mov $msg_lookup,%si # Display lookup message
- call putstr
- pop %si
- push %si
- call putstr
- mov $msg_lookup2,%si
- call putstr
- pop %si
-lookup_dir: lodsb # Get first char of path
- cmp $0,%al # Are we done?
- je lookup_done # Yes
- cmp $'/',%al # Skip path separator.
- je lookup_dir
- dec %si # Undo lodsb side effect
- call find_file # Lookup first path item
- jnc lookup_dir # Try next component
- mov $msg_lookupfail,%si # Not found message
- call putstr
- stc # Set carry
- ret
- jmp error
-lookup_done: mov $msg_lookupok,%si # Success message
- call putstr
- clc # Clear carry
- ret
-
-#
-# Lookup file at [SI] in directory whose record is at [BX].
-#
-# Trashes: All but returns
-# Returns: CF = 0 (success), BX = pointer to record, SI = next path item
-# CF = 1 (not found), SI = preserved
-#
-find_file: mov DIR_EXTENT(%bx),%eax # Load extent
- xor %edx,%edx
- mov DIR_EA_LEN(%bx),%dl
- add %edx,%eax # Skip extended attributes
- mov %eax,rec_lba # Save LBA
- mov DIR_SIZE(%bx),%eax # Save size
- mov %eax,rec_size
- xor %cl,%cl # Zero length
- push %si # Save
-ff.namelen: inc %cl # Update length
- lodsb # Read char
- cmp $0,%al # Nul?
- je ff.namedone # Yes
- cmp $'/',%al # Path separator?
- jnz ff.namelen # No, keep going
-ff.namedone: dec %cl # Adjust length and save
- mov %cl,name_len
- pop %si # Restore
-ff.load: mov rec_lba,%eax # Load LBA
- mov $MEM_DIR,%ebx # Address buffer
- mov $1,%dh # One sector
- call read # Read directory block
- incl rec_lba # Update LBA to next block
-ff.scan: mov %ebx,%edx # Check for EOF
- sub $MEM_DIR,%edx
- cmp %edx,rec_size
- ja ff.scan.1
- stc # EOF reached
- ret
-ff.scan.1: cmpb $0,DIR_LEN(%bx) # Last record in block?
- je ff.nextblock
- push %si # Save
- movzbw DIR_NAMELEN(%bx),%si # Find end of string
-ff.checkver: cmpb $'0',DIR_NAME-1(%bx,%si) # Less than '0'?
- jb ff.checkver.1
- cmpb $'9',DIR_NAME-1(%bx,%si) # Greater than '9'?
- ja ff.checkver.1
- dec %si # Next char
- jnz ff.checkver
- jmp ff.checklen # All numbers in name, so
- # no version
-ff.checkver.1: movzbw DIR_NAMELEN(%bx),%cx
- cmp %cx,%si # Did we find any digits?
- je ff.checkdot # No
- cmpb $';',DIR_NAME-1(%bx,%si) # Check for semicolon
- jne ff.checkver.2
- dec %si # Skip semicolon
- mov %si,%cx
- mov %cl,DIR_NAMELEN(%bx) # Adjust length
- jmp ff.checkdot
-ff.checkver.2: mov %cx,%si # Restore %si to end of string
-ff.checkdot: cmpb $'.',DIR_NAME-1(%bx,%si) # Trailing dot?
- jne ff.checklen # No
- decb DIR_NAMELEN(%bx) # Adjust length
-ff.checklen: pop %si # Restore
- movzbw name_len,%cx # Load length of name
- cmp %cl,DIR_NAMELEN(%bx) # Does length match?
- je ff.checkname # Yes, check name
-ff.nextrec: add DIR_LEN(%bx),%bl # Next record
- adc $0,%bh
- jmp ff.scan
-ff.nextblock: subl $SECTOR_SIZE,rec_size # Adjust size
- jnc ff.load # If subtract ok, keep going
- ret # End of file, so not found
-ff.checkname: lea DIR_NAME(%bx),%di # Address name in record
- push %si # Save
- repe cmpsb # Compare name
- je ff.match # We have a winner!
- pop %si # Restore
- jmp ff.nextrec # Keep looking.
-ff.match: add $2,%sp # Discard saved %si
- clc # Clear carry
- ret
-
-#
-# Load DH sectors starting at LBA EAX into [EBX].
-#
-# Trashes: EAX
-#
-read: push %si # Save
- push %cx # Save since some BIOSs trash
- mov %eax,edd_lba # LBA to read from
- mov %ebx,%eax # Convert address
- shr $4,%eax # to segment
- mov %ax,edd_addr+0x2 # and store
-read.retry: call twiddle # Entertain the user
- push %dx # Save
- mov $edd_packet,%si # Address Packet
- mov %dh,edd_len # Set length
- mov drive,%dl # BIOS Device
- mov $0x42,%ah # BIOS: Extended Read
- int $0x13 # Call BIOS
- pop %dx # Restore
- jc read.fail # Worked?
- pop %cx # Restore
- pop %si
- ret # Return
-read.fail: cmp $ERROR_TIMEOUT,%ah # Timeout?
- je read.retry # Yes, Retry.
-read.error: mov %ah,%al # Save error
- mov $hex_error,%di # Format it
- call hex8 # as hex
- mov $msg_badread,%si # Display Read error message
-
-#
-# Display error message at [SI] and halt.
-#
-error: call putstr # Display message
-halt: hlt
- jmp halt # Spin
-
-#
-# Display a null-terminated string.
-#
-# Trashes: AX, SI
-#
-putstr: push %bx # Save
-putstr.load: lodsb # load %al from %ds:(%si)
- test %al,%al # stop at null
- jnz putstr.putc # if the char != null, output it
- pop %bx # Restore
- ret # return when null is hit
-putstr.putc: call putc # output char
- jmp putstr.load # next char
-
-#
-# Display a single char.
-#
-putc: mov $0x7,%bx # attribute for output
- mov $0xe,%ah # BIOS: put_char
- int $0x10 # call BIOS, print char in %al
- ret # Return to caller
-
-#
-# Output the "twiddle"
-#
-twiddle: push %ax # Save
- push %bx # Save
- mov twiddle_index,%al # Load index
- mov $twiddle_chars,%bx # Address table
- inc %al # Next
- and $3,%al # char
- mov %al,twiddle_index # Save index for next call
- xlat # Get char
- call putc # Output it
- mov $8,%al # Backspace
- call putc # Output it
- pop %bx # Restore
- pop %ax # Restore
- ret
-
-#
-# Enable A20. Put an upper limit on the amount of time we wait for the
-# keyboard controller to get ready (65K x ISA access time). If
-# we wait more than that amount, the hardware is probably
-# legacy-free and simply doesn't have a keyboard controller.
-# Thus, the A20 line is already enabled.
-#
-seta20: cli # Disable interrupts
- xor %cx,%cx # Clear
-seta20.1: inc %cx # Increment, overflow?
- jz seta20.3 # Yes
- in $0x64,%al # Get status
- test $0x2,%al # Busy?
- jnz seta20.1 # Yes
- mov $0xd1,%al # Command: Write
- out %al,$0x64 # output port
-seta20.2: in $0x64,%al # Get status
- test $0x2,%al # Busy?
- jnz seta20.2 # Yes
- mov $0xdf,%al # Enable
- out %al,$0x60 # A20
-seta20.3: sti # Enable interrupts
- ret # To caller
-
-#
-# Convert AL to hex, saving the result to [EDI].
-#
-hex8: pushl %eax # Save
- shrb $0x4,%al # Do upper
- call hex8.1 # 4
- popl %eax # Restore
-hex8.1: andb $0xf,%al # Get lower 4
- cmpb $0xa,%al # Convert
- sbbb $0x69,%al # to hex
- das # digit
- orb $0x20,%al # To lower case
- stosb # Save char
- ret # (Recursive)
-
-#
-# BTX client to start btxldr
-#
- .code32
-btx_client: mov $(MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE-4), %esi
- # %ds:(%esi) -> end
- # of boot[12] args
- mov $(MEM_ARG_SIZE/4),%ecx # Number of words to push
- std # Go backwards
-push_arg: lodsl # Read argument
- push %eax # Push it onto the stack
- loop push_arg # Push all of the arguments
- cld # In case anyone depends on this
- pushl MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE # Entry point of
- # the loader
- push %eax # Emulate a near call
- mov $0x1,%eax # 'exec' system call
- int $INT_SYS # BTX system call
-btx_client_end:
- .code16
-
- .p2align 4
-#
-# Global descriptor table.
-#
-gdt: .word 0x0,0x0,0x0,0x0 # Null entry
- .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
- .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
- .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE (32-bit)
- .word 0xffff,0x0,0x9a00,0x8f # SEL_SCODE16 (16-bit)
-gdt.1:
-#
-# Pseudo-descriptors.
-#
-gdtdesc: .word gdt.1-gdt-1 # Limit
- .long gdt # Base
-#
-# EDD Packet
-#
-edd_packet: .byte 0x10 # Length
- .byte 0 # Reserved
-edd_len: .byte 0x0 # Num to read
- .byte 0 # Reserved
-edd_addr: .word 0x0,0x0 # Seg:Off
-edd_lba: .quad 0x0 # LBA
-
-drive: .byte 0
-
-#
-# State for searching dir
-#
-rec_lba: .long 0x0 # LBA (adjusted for EA)
-rec_size: .long 0x0 # File size
-name_len: .byte 0x0 # Length of current name
-
-twiddle_index: .byte 0x0
-
-msg_welcome: .asciz "CD Loader 1.2\r\n\n"
-msg_bootinfo: .asciz "Building the boot loader arguments\r\n"
-msg_relocate: .asciz "Relocating the loader and the BTX\r\n"
-msg_jump: .asciz "Starting the BTX loader\r\n"
-msg_badread: .ascii "Read Error: 0x"
-hex_error: .asciz "00\r\n"
-msg_novd: .asciz "Could not find Primary Volume Descriptor\r\n"
-msg_lookup: .asciz "Looking up "
-msg_lookup2: .asciz "... "
-msg_lookupok: .asciz "Found\r\n"
-msg_lookupfail: .asciz "File not found\r\n"
-msg_load2big: .asciz "File too big\r\n"
-msg_failed: .asciz "Boot failed\r\n"
-twiddle_chars: .ascii "|/-\\"
-loader_paths: .asciz "/BOOT/LOADER"
- .asciz "/boot/loader"
- .byte 0
-
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/common/bootargs.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/i386/common/bootargs.h Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2012 Andriy Gapon <avg at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ *
+ * $FreeBSD: head/sys/boot/i386/common/bootargs.h 235154 2012-05-09 08:04:29Z avg $
+ */
+
+#ifndef _BOOT_I386_ARGS_H_
+#define _BOOT_I386_ARGS_H_
+
+#define KARGS_FLAGS_CD 0x1
+#define KARGS_FLAGS_PXE 0x2
+#define KARGS_FLAGS_ZFS 0x4
+#define KARGS_FLAGS_EXTARG 0x8 /* variably sized extended argument */
+
+#define BOOTARGS_SIZE 24 /* sizeof(struct bootargs) */
+#define BA_BOOTFLAGS 8 /* offsetof(struct bootargs, bootflags) */
+#define BA_BOOTINFO 20 /* offsetof(struct bootargs, bootinfo) */
+#define BI_SIZE 48 /* offsetof(struct bootinfo, bi_size) */
+
+/*
+ * We reserve some space above BTX allocated stack for the arguments
+ * and certain data that could hang off them. Currently only struct bootinfo
+ * is supported in that category. The bootinfo is placed at the top
+ * of the arguments area and the actual arguments are placed at ARGOFF offset
+ * from the top and grow towards the top. Hopefully we have enough space
+ * for bootinfo and the arguments to not run into each other.
+ * Arguments area below ARGOFF is reserved for future use.
+ */
+#define ARGSPACE 0x1000 /* total size of the BTX args area */
+#define ARGOFF 0x800 /* actual args offset within the args area */
+#define ARGADJ (ARGSPACE - ARGOFF)
+
+#ifndef __ASSEMBLER__
+
+struct bootargs
+{
+ uint32_t howto;
+ uint32_t bootdev;
+ uint32_t bootflags;
+ union {
+ struct {
+ uint32_t pxeinfo;
+ uint32_t reserved;
+ };
+ uint64_t zfspool;
+ };
+ uint32_t bootinfo;
+
+ /*
+ * If KARGS_FLAGS_EXTARG is set in bootflags, then the above fields
+ * are followed by a uint32_t field that specifies a size of the
+ * extended arguments (including the size field).
+ */
+};
+
+#endif /*__ASSEMBLER__*/
+
+#endif /* !_BOOT_I386_ARGS_H_ */
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/efi/reloc.c
--- a/head/sys/boot/i386/efi/reloc.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/efi/reloc.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,21 +25,12 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/i386/efi/reloc.c 235153 2012-05-09 07:55:42Z avg $");
#include <sys/types.h>
#include <sys/elf32.h>
#include <efi.h>
-
-/*
- * XXX: we can't include sys/systm.h.
- */
-#ifndef CTASSERT /* Allow lint to override */
-#define CTASSERT(x) _CTASSERT(x, __LINE__)
-#define _CTASSERT(x, y) __CTASSERT(x, y)
-#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1]
-#endif
-
+#include <bootstrap.h>
/*
* A simple relocator for IA32 EFI binaries.
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/gptboot/gptboot.c
--- a/head/sys/boot/i386/gptboot/gptboot.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/gptboot/gptboot.c Wed Jul 25 16:45:04 2012 +0300
@@ -14,7 +14,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/i386/gptboot/gptboot.c 226506 2011-10-18 09:46:52Z des $");
+__FBSDID("$FreeBSD: head/sys/boot/i386/gptboot/gptboot.c 235988 2012-05-25 09:36:39Z gleb $");
#include <sys/param.h>
#include <sys/gpt.h>
@@ -90,14 +90,13 @@
void exit(int);
static void load(void);
static int parse(char *, int *);
-static int xfsread(ino_t, void *, size_t);
static int dskread(void *, daddr_t, unsigned);
static uint32_t memsize(void);
#include "ufsread.c"
static inline int
-xfsread(ino_t inode, void *buf, size_t nbyte)
+xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
{
if ((size_t)fsread(inode, buf, nbyte) != nbyte) {
@@ -138,7 +137,7 @@
{
char cmd[512], cmdtmp[512];
int autoboot, dskupdated;
- ino_t ino;
+ ufs_ino_t ino;
dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
v86.ctl = V86_FLAGS;
@@ -247,7 +246,7 @@
static Elf32_Phdr ep[2];
static Elf32_Shdr es[2];
caddr_t p;
- ino_t ino;
+ ufs_ino_t ino;
uint32_t addr, x;
int fmt, i, j;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/libi386/Makefile
--- a/head/sys/boot/i386/libi386/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/libi386/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/boot/i386/libi386/Makefile 232263 2012-02-28 18:30:18Z dim $
+# $FreeBSD: head/sys/boot/i386/libi386/Makefile 235329 2012-05-12 09:03:30Z avg $
#
LIB= i386
INTERNALLIB=
@@ -9,6 +9,8 @@
elf64_freebsd.c \
i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \
smbios.c time.c vidconsole.c amd64_tramp.S spinconsole.c
+.PATH: ${.CURDIR}/../../zfs
+SRCS+= devicename_stubs.c
# Enable PXE TFTP or NFS support, not both.
.if defined(LOADER_TFTP_SUPPORT)
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/libi386/biosdisk.c
--- a/head/sys/boot/i386/libi386/biosdisk.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/libi386/biosdisk.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/biosdisk.c 226748 2011-10-25 19:54:06Z jhb $");
+__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/biosdisk.c 235155 2012-05-09 08:05:50Z avg $");
/*
* BIOS disk device handling.
@@ -55,7 +55,6 @@
#define BIOS_NUMDRIVES 0x475
#define BIOSDISK_SECSIZE 512
#define BUFSIZE (1 * BIOSDISK_SECSIZE)
-#define MAXBDDEV MAXDEV
#define DT_ATAPI 0x10 /* disk type for ATAPI floppies */
#define WDMAJOR 0 /* major numbers for devices we frontend for */
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/libi386/biospnp.c
--- a/head/sys/boot/i386/libi386/biospnp.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/libi386/biospnp.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/biospnp.c 236213 2012-05-29 01:48:06Z kevlo $");
/*
* PnP BIOS enumerator.
@@ -276,6 +276,7 @@
break;
}
}
+ va_end(ap);
/* BIOS segment last */
*(u_int16_t *)argp = pnp_Icheck->pnp_rmds;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/libi386/devicename.c
--- a/head/sys/boot/i386/libi386/devicename.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/libi386/devicename.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,13 +25,14 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/devicename.c 235329 2012-05-12 09:03:30Z avg $");
#include <stand.h>
#include <string.h>
#include <sys/disklabel.h>
#include "bootstrap.h"
#include "libi386.h"
+#include "../zfs/libzfs.h"
static int i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path);
@@ -171,7 +172,6 @@
case DEVT_CD:
case DEVT_NET:
- case DEVT_ZFS:
unit = 0;
if (*np && (*np != ':')) {
@@ -192,7 +192,11 @@
if (path != NULL)
*path = (*cp == 0) ? cp : cp + 1;
break;
-
+ case DEVT_ZFS:
+ err = zfs_parsedev((struct zfs_devdesc *)idev, np, path);
+ if (err != 0)
+ goto fail;
+ break;
default:
err = EINVAL;
goto fail;
@@ -247,9 +251,10 @@
break;
case DEVT_NET:
- case DEVT_ZFS:
sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit);
break;
+ case DEVT_ZFS:
+ return(zfs_fmtdev(vdev));
}
return(buf);
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/libi386/libi386.h
--- a/head/sys/boot/i386/libi386/libi386.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/libi386/libi386.h Wed Jul 25 16:45:04 2012 +0300
@@ -23,14 +23,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/boot/i386/libi386/libi386.h 229435 2012-01-03 22:36:12Z kib $
+ * $FreeBSD: head/sys/boot/i386/libi386/libi386.h 235329 2012-05-12 09:03:30Z avg $
*/
/*
* i386 fully-qualified device descriptor.
* Note, this must match the 'struct devdesc' declaration
- * in bootstrap.h.
+ * in bootstrap.h and also with struct zfs_devdesc for zfs
+ * support.
*/
struct i386_devdesc
{
@@ -49,6 +50,12 @@
{
void *data;
} bioscd;
+ struct
+ {
+ void *data;
+ uint64_t pool_guid;
+ uint64_t root_guid;
+ } zfs;
} d_kind;
};
@@ -58,7 +65,8 @@
extern struct devdesc currdev; /* our current device */
-#define MAXDEV 31 /* maximum number of distinct devices */
+#define MAXDEV 31 /* maximum number of distinct devices */
+#define MAXBDDEV MAXDEV
/* exported devices XXX rename? */
extern struct devsw bioscd;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/loader/Makefile
--- a/head/sys/boot/i386/loader/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/loader/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/boot/i386/loader/Makefile 227726 2011-11-19 14:42:06Z miwi $
+# $FreeBSD: head/sys/boot/i386/loader/Makefile 235537 2012-05-17 10:11:18Z gber $
.include <bsd.own.mk>
MK_SSP= no
@@ -20,9 +20,7 @@
# Set by zfsloader Makefile
.if defined(LOADER_ZFS_SUPPORT)
CFLAGS+= -DLOADER_ZFS_SUPPORT
-LIBZFS= ${.OBJDIR}/../../zfs/libzfsboot.a
-.else
-LIBZFS=
+LIBZFSBOOT= ${.OBJDIR}/../../zfs/libzfsboot.a
.endif
# Enable PXE TFTP or NFS support, not both.
@@ -55,6 +53,9 @@
.if !defined(LOADER_NO_GPT_SUPPORT)
CFLAGS+= -DLOADER_GPT_SUPPORT
.endif
+.if defined(LOADER_NANDFS_SUPPORT)
+CFLAGS+= -DLOADER_NANDFS_SUPPORT
+.endif
# Always add MI sources
.PATH: ${.CURDIR}/../../common
@@ -119,8 +120,8 @@
# XXX crt0.o needs to be first for pxeboot(8) to work
OBJS= ${BTXCRT}
-DPADD= ${LIBFICL} ${LIBFIREWIRE} ${LIBZFS} ${LIBI386} ${LIBSTAND}
-LDADD= ${LIBFICL} ${LIBFIREWIRE} ${LIBZFS} ${LIBI386} ${LIBSTAND}
+DPADD= ${LIBFICL} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBSTAND}
+LDADD= ${LIBFICL} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBSTAND}
.include <bsd.prog.mk>
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/loader/conf.c
--- a/head/sys/boot/i386/loader/conf.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/loader/conf.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,11 +25,14 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/i386/loader/conf.c 235537 2012-05-17 10:11:18Z gber $");
#include <stand.h>
#include <bootstrap.h>
#include "libi386/libi386.h"
+#if defined(LOADER_ZFS_SUPPORT)
+#include "../zfs/libzfs.h"
+#endif
/*
* We could use linker sets for some or all of these, but
@@ -50,10 +53,6 @@
extern struct devsw fwohci;
#endif
-#if defined(LOADER_ZFS_SUPPORT)
-extern struct devsw zfs_dev;
-#endif
-
/* Exported for libstand */
struct devsw *devsw[] = {
&bioscd,
@@ -70,15 +69,14 @@
NULL
};
-#if defined(LOADER_ZFS_SUPPORT)
-extern struct fs_ops zfs_fsops;
-#endif
-
struct fs_ops *file_system[] = {
&ufs_fsops,
&ext2fs_fsops,
&dosfs_fsops,
&cd9660_fsops,
+#if defined(LOADER_NANDFS_SUPPORT)
+ &nandfs_fsops,
+#endif
&splitfs_fsops,
#if defined(LOADER_ZFS_SUPPORT)
&zfs_fsops,
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/loader/main.c
--- a/head/sys/boot/i386/loader/main.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/loader/main.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/i386/loader/main.c 235329 2012-05-12 09:03:30Z avg $");
/*
* MD bootstrap main() and assorted miscellaneous
@@ -33,34 +33,28 @@
*/
#include <stand.h>
+#include <stddef.h>
#include <string.h>
#include <machine/bootinfo.h>
#include <machine/psl.h>
#include <sys/reboot.h>
#include "bootstrap.h"
+#include "common/bootargs.h"
#include "libi386/libi386.h"
#include "btxv86.h"
-#define KARGS_FLAGS_CD 0x1
-#define KARGS_FLAGS_PXE 0x2
-#define KARGS_FLAGS_ZFS 0x4
+#ifdef LOADER_ZFS_SUPPORT
+#include "../zfs/libzfs.h"
+#endif
+
+CTASSERT(sizeof(struct bootargs) == BOOTARGS_SIZE);
+CTASSERT(offsetof(struct bootargs, bootinfo) == BA_BOOTINFO);
+CTASSERT(offsetof(struct bootargs, bootflags) == BA_BOOTFLAGS);
+CTASSERT(offsetof(struct bootinfo, bi_size) == BI_SIZE);
/* Arguments passed in from the boot1/boot2 loader */
-static struct
-{
- u_int32_t howto;
- u_int32_t bootdev;
- u_int32_t bootflags;
- union {
- struct {
- u_int32_t pxeinfo;
- u_int32_t res2;
- };
- uint64_t zfspool;
- };
- u_int32_t bootinfo;
-} *kargs;
+static struct bootargs *kargs;
static u_int32_t initial_howto;
static u_int32_t initial_bootdev;
@@ -72,6 +66,9 @@
static int isa_inb(int port);
static void isa_outb(int port, int value);
void exit(int code);
+#ifdef LOADER_ZFS_SUPPORT
+static void i386_zfs_probe(void);
+#endif
/* from vers.c */
extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
@@ -163,6 +160,9 @@
archsw.arch_readin = i386_readin;
archsw.arch_isainb = isa_inb;
archsw.arch_isaoutb = isa_outb;
+#ifdef LOADER_ZFS_SUPPORT
+ archsw.arch_zfs_probe = i386_zfs_probe;
+#endif
/*
* March through the device switch probing for things.
@@ -206,8 +206,11 @@
static void
extract_currdev(void)
{
- struct i386_devdesc new_currdev;
- int biosdev = -1;
+ struct i386_devdesc new_currdev;
+#ifdef LOADER_ZFS_SUPPORT
+ struct zfs_boot_args *zargs;
+#endif
+ int biosdev = -1;
/* Assume we are booting from a BIOS disk by default */
new_currdev.d_dev = &biosdisk;
@@ -228,6 +231,24 @@
new_currdev.d_kind.biosdisk.partition = 0;
biosdev = -1;
}
+#ifdef LOADER_ZFS_SUPPORT
+ } else if ((kargs->bootflags & KARGS_FLAGS_ZFS) != 0) {
+ zargs = NULL;
+ /* check for new style extended argument */
+ if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0)
+ zargs = (struct zfs_boot_args *)(kargs + 1);
+
+ if (zargs != NULL && zargs->size >= sizeof(*zargs)) {
+ /* sufficient data is provided */
+ new_currdev.d_kind.zfs.pool_guid = zargs->pool;
+ new_currdev.d_kind.zfs.root_guid = zargs->root;
+ } else {
+ /* old style zfsboot block */
+ new_currdev.d_kind.zfs.pool_guid = kargs->zfspool;
+ new_currdev.d_kind.zfs.root_guid = 0;
+ }
+ new_currdev.d_dev = &zfs_dev;
+#endif
} else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) {
/* The passed-in boot device is bad */
new_currdev.d_kind.biosdisk.slice = -1;
@@ -248,7 +269,7 @@
biosdev = 0x80 + B_UNIT(initial_bootdev); /* assume harddisk */
}
new_currdev.d_type = new_currdev.d_dev->dv_type;
-
+
/*
* If we are booting off of a BIOS disk and we didn't succeed in determining
* which one we booted off of, just use disk0: as a reasonable default.
@@ -259,33 +280,11 @@
"Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev);
new_currdev.d_unit = 0;
}
+
env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
i386_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset,
env_nounset);
-
-#ifdef LOADER_ZFS_SUPPORT
- /*
- * If we were started from a ZFS-aware boot2, we can work out
- * which ZFS pool we are booting from.
- */
- if (kargs->bootflags & KARGS_FLAGS_ZFS) {
- /*
- * Dig out the pool guid and convert it to a 'unit number'
- */
- uint64_t guid;
- int unit;
- char devname[32];
- extern int zfs_guid_to_unit(uint64_t);
-
- guid = kargs->zfspool;
- unit = zfs_guid_to_unit(guid);
- if (unit >= 0) {
- sprintf(devname, "zfs%d", unit);
- setenv("currdev", devname, 1);
- }
- }
-#endif
}
COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
@@ -352,3 +351,30 @@
}
}
+#ifdef LOADER_ZFS_SUPPORT
+static void
+i386_zfs_probe(void)
+{
+ char devname[32];
+ int unit, slice;
+
+ /*
+ * Open all the disks we can find and see if we can reconstruct
+ * ZFS pools from them. Bogusly assumes that the disks are named
+ * diskN, diskNpM or diskNsM.
+ */
+ for (unit = 0; unit < MAXBDDEV; unit++) {
+ sprintf(devname, "disk%d:", unit);
+ if (zfs_probe_dev(devname, NULL) == ENXIO)
+ continue;
+ for (slice = 1; slice <= 128; slice++) {
+ sprintf(devname, "disk%dp%d:", unit, slice);
+ zfs_probe_dev(devname, NULL);
+ }
+ for (slice = 1; slice <= 4; slice++) {
+ sprintf(devname, "disk%ds%d:", unit, slice);
+ zfs_probe_dev(devname, NULL);
+ }
+ }
+}
+#endif
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/pxeldr/Makefile
--- a/head/sys/boot/i386/pxeldr/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/pxeldr/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/boot/i386/pxeldr/Makefile 232263 2012-02-28 18:30:18Z dim $
+# $FreeBSD: head/sys/boot/i386/pxeldr/Makefile 235219 2012-05-10 09:47:04Z avg $
# Pick up ../Makefile.inc early.
.include <bsd.init.mk>
@@ -23,6 +23,8 @@
CFLAGS+=-DALWAYS_SERIAL
.endif
+CFLAGS+=-I${.CURDIR}/../common
+
LOADERBIN= ${.OBJDIR}/../loader/loader.bin
CLEANFILES+= ${BOOT}.tmp
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/pxeldr/pxeldr.S
--- a/head/sys/boot/i386/pxeldr/pxeldr.S Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/pxeldr/pxeldr.S Wed Jul 25 16:45:04 2012 +0300
@@ -12,7 +12,7 @@
* warranties of merchantability and fitness for a particular
* purpose.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/i386/pxeldr/pxeldr.S 235219 2012-05-10 09:47:04Z avg $
*/
/*
@@ -26,6 +26,7 @@
*/
#include <sys/reboot.h>
+#include <bootargs.h>
/*
* Memory locations.
@@ -50,11 +51,6 @@
.set AOUT_ENTRY,0x14 # entry point
.set AOUT_HEADER,MEM_PAGE_SIZE # size of the a.out header
/*
- * Flags for kargs->bootflags
- */
- .set KARGS_FLAGS_PXE,0x2 # flag to indicate booting from
- # PXE loader
-/*
* Segment selectors.
*/
.set SEL_SDATA,0x8 # Supervisor data
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/i386/zfsboot/zfsboot.c
--- a/head/sys/boot/i386/zfsboot/zfsboot.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/i386/zfsboot/zfsboot.c Wed Jul 25 16:45:04 2012 +0300
@@ -14,7 +14,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/i386/zfsboot/zfsboot.c 234339 2012-04-16 10:43:06Z avg $");
+__FBSDID("$FreeBSD: head/sys/boot/i386/zfsboot/zfsboot.c 235329 2012-05-12 09:03:30Z avg $");
#include <sys/param.h>
#include <sys/errno.h>
@@ -41,9 +41,9 @@
#include "drv.h"
#include "util.h"
#include "cons.h"
+#include "bootargs.h"
-/* Hint to loader that we came from ZFS */
-#define KARGS_FLAGS_ZFS 0x4
+#include "libzfs.h"
#define PATH_DOTCONFIG "/boot.config"
#define PATH_CONFIG "/boot/config"
@@ -63,8 +63,6 @@
#define TYPE_MAXHARD TYPE_DA
#define TYPE_FD 2
-#define MAXBDDEV 31
-
extern uint32_t _end;
#ifdef GPT
@@ -95,9 +93,12 @@
static char cmd[512];
static char cmddup[512];
static char kname[1024];
+static char rootname[256];
static int comspeed = SIOSPD;
static struct bootinfo bootinfo;
static uint32_t bootdev;
+static struct zfs_boot_args zfsargs;
+static struct zfsmount zfsmount;
vm_offset_t high_heap_base;
uint32_t bios_basemem, bios_extmem, high_heap_size;
@@ -174,7 +175,7 @@
/*
* Current ZFS pool
*/
-spa_t *spa;
+static spa_t *spa;
/*
* A wrapper for dskread that doesn't have to worry about whether the
@@ -213,7 +214,7 @@
xfsread(const dnode_phys_t *dnode, off_t *offp, void *buf, size_t nbyte)
{
if ((size_t)zfs_read(spa, dnode, offp, buf, nbyte) != nbyte) {
- printf("Invalid %s\n", "format");
+ printf("Invalid format\n");
return -1;
}
return 0;
@@ -533,10 +534,12 @@
}
}
- zfs_mount_pool(spa);
-
- if (zfs_lookup(spa, PATH_CONFIG, &dn) == 0 ||
- zfs_lookup(spa, PATH_DOTCONFIG, &dn) == 0) {
+ if (zfs_spa_init(spa) != 0 || zfs_mount(spa, 0, &zfsmount) != 0) {
+ printf("%s: failed to mount default pool %s\n",
+ BOOTPROG, spa->spa_name);
+ autoboot = 0;
+ } else if (zfs_lookup(&zfsmount, PATH_CONFIG, &dn) == 0 ||
+ zfs_lookup(&zfsmount, PATH_DOTCONFIG, &dn) == 0) {
off = 0;
zfs_read(spa, &dn, &off, cmd, sizeof(cmd));
}
@@ -571,11 +574,17 @@
/* Present the user with the boot2 prompt. */
for (;;) {
- if (!autoboot || !OPT_CHECK(RBX_QUIET))
- printf("\nFreeBSD/x86 boot\n"
- "Default: %s:%s\n"
- "boot: ",
- spa->spa_name, kname);
+ if (!autoboot || !OPT_CHECK(RBX_QUIET)) {
+ printf("\nFreeBSD/x86 boot\n");
+ if (zfs_rlookup(spa, zfsmount.rootobj, rootname) != 0)
+ printf("Default: %s:<0x%llx>:%s\n"
+ "boot: ",
+ spa->spa_name, zfsmount.rootobj, kname);
+ else
+ printf("Default: %s:%s:%s\n"
+ "boot: ",
+ spa->spa_name, rootname, kname);
+ }
if (ioctrl & IO_SERIAL)
sio_flush();
if (!autoboot || keyhit(5))
@@ -611,7 +620,8 @@
uint32_t addr, x;
int fmt, i, j;
- if (zfs_lookup(spa, kname, &dn)) {
+ if (zfs_lookup(&zfsmount, kname, &dn)) {
+ printf("\nCan't find %s\n", kname);
return;
}
off = 0;
@@ -685,12 +695,16 @@
}
bootinfo.bi_esymtab = VTOP(p);
bootinfo.bi_kernelname = VTOP(kname);
+ zfsargs.size = sizeof(zfsargs);
+ zfsargs.pool = zfsmount.spa->spa_guid;
+ zfsargs.root = zfsmount.rootobj;
__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
bootdev,
- KARGS_FLAGS_ZFS,
+ KARGS_FLAGS_ZFS | KARGS_FLAGS_EXTARG,
(uint32_t) spa->spa_guid,
(uint32_t) (spa->spa_guid >> 32),
- VTOP(&bootinfo));
+ VTOP(&bootinfo),
+ zfsargs);
}
static int
@@ -742,7 +756,7 @@
} if (c == '?') {
dnode_phys_t dn;
- if (zfs_lookup(spa, arg, &dn) == 0) {
+ if (zfs_lookup(&zfsmount, arg, &dn) == 0) {
zap_list(spa, &dn);
}
return -1;
@@ -764,17 +778,32 @@
q = (char *) strchr(arg, ':');
if (q) {
spa_t *newspa;
+ uint64_t newroot;
*q++ = 0;
newspa = spa_find_by_name(arg);
if (newspa) {
+ arg = q;
spa = newspa;
- zfs_mount_pool(spa);
+ newroot = 0;
+ q = (char *) strchr(arg, ':');
+ if (q) {
+ *q++ = 0;
+ if (zfs_lookup_dataset(spa, arg, &newroot)) {
+ printf("\nCan't find dataset %s in ZFS pool %s\n",
+ arg, spa->spa_name);
+ return -1;
+ }
+ arg = q;
+ }
+ if (zfs_mount(spa, newroot, &zfsmount)) {
+ printf("\nCan't mount ZFS dataset\n");
+ return -1;
+ }
} else {
printf("\nCan't find ZFS pool %s\n", arg);
return -1;
}
- arg = q;
}
if ((i = ep - arg)) {
if ((size_t)i >= sizeof(kname))
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/ofw/libofw/Makefile
--- a/head/sys/boot/ofw/libofw/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/ofw/libofw/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/boot/ofw/libofw/Makefile 235364 2012-05-12 20:27:33Z avg $
LIB= ofw
INTERNALLIB=
@@ -6,6 +6,8 @@
SRCS= devicename.c elf_freebsd.c ofw_console.c ofw_copy.c ofw_disk.c \
ofw_memory.c ofw_module.c ofw_net.c ofw_reboot.c \
ofw_time.c openfirm.c
+.PATH: ${.CURDIR}/../../zfs
+SRCS+= devicename_stubs.c
CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/ofw/libofw/devicename.c
--- a/head/sys/boot/ofw/libofw/devicename.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/ofw/libofw/devicename.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,10 +25,13 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/ofw/libofw/devicename.c 235364 2012-05-12 20:27:33Z avg $");
#include <stand.h>
+
+#include "bootstrap.h"
#include "libofw.h"
+#include "../zfs/libzfs.h"
static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **);
@@ -76,8 +79,10 @@
phandle_t handle;
const char *p;
const char *s;
+ char *ep;
char name[256];
char type[64];
+ int err;
int len;
int i;
@@ -87,9 +92,10 @@
len = s - devspec;
bcopy(devspec, name, len);
name[len] = '\0';
- if ((handle = OF_finddevice(name)) == -1)
- break;
- if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1)
+ if ((handle = OF_finddevice(name)) == -1) {
+ bcopy(name, type, len);
+ type[len] = '\0';
+ } else if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1)
continue;
for (i = 0; (dv = devsw[i]) != NULL; i++) {
if (strncmp(dv->dv_name, type, strlen(dv->dv_name)) == 0)
@@ -109,6 +115,15 @@
strcpy(idev->d_path, name);
idev->d_dev = dv;
idev->d_type = dv->dv_type;
+ if (idev->d_type == DEVT_ZFS) {
+ p = devspec + strlen(dv->dv_name);
+ err = zfs_parsedev((struct zfs_devdesc *)idev, p, path);
+ if (err != 0) {
+ free(idev);
+ return (err);
+ }
+ }
+
if (dev == NULL) {
free(idev);
} else {
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/ofw/libofw/libofw.h
--- a/head/sys/boot/ofw/libofw/libofw.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/ofw/libofw/libofw.h Wed Jul 25 16:45:04 2012 +0300
@@ -22,7 +22,7 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/ofw/libofw/libofw.h 235364 2012-05-12 20:27:33Z avg $
*/
#include "openfirm.h"
@@ -33,7 +33,13 @@
int d_type;
int d_unit;
ihandle_t d_handle;
- char d_path[256];
+ union {
+ char d_path[256];
+ struct {
+ uint64_t pool_guid;
+ uint64_t root_guid;
+ };
+ };
};
extern int ofw_getdev(void **vdev, const char *devspec, const char **path);
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/ofw/libofw/ofw_disk.c
--- a/head/sys/boot/ofw/libofw/ofw_disk.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/ofw/libofw/ofw_disk.c Wed Jul 25 16:45:04 2012 +0300
@@ -24,14 +24,13 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/ofw/libofw/ofw_disk.c 236579 2012-06-04 20:45:33Z marius $");
/*
* Disk I/O routines using Open Firmware
*/
#include <sys/param.h>
-#include <sys/queue.h>
#include <netinet/in.h>
@@ -43,8 +42,8 @@
#include "libofw.h"
static int ofwd_init(void);
-static int ofwd_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
+static int ofwd_strategy(void *devdata, int flag, daddr_t dblk,
+ size_t size, char *buf, size_t *rsize);
static int ofwd_open(struct open_file *f, ...);
static int ofwd_close(struct open_file *f);
static int ofwd_ioctl(struct open_file *f, u_long cmd, void *data);
@@ -61,120 +60,109 @@
ofwd_print
};
-struct opened_dev {
- ihandle_t handle;
- u_int count;
- SLIST_ENTRY(opened_dev) link;
-};
-
-SLIST_HEAD(, opened_dev) opened_devs = SLIST_HEAD_INITIALIZER(opened_devs);
+/*
+ * We're not guaranteed to be able to open a device more than once and there
+ * is no OFW standard method to determine whether a device is already opened.
+ * Opening a device multiple times simultaneously happens to work with most
+ * OFW block device drivers but triggers a trap with at least the driver for
+ * the on-board controllers of Sun Fire V100 and Ultra 1. Upper layers and MI
+ * code expect to be able to open a device more than once however. Given that
+ * different partitions of the same device might be opened at the same time as
+ * done by ZFS, we can't generally just keep track of the opened devices and
+ * reuse the instance handle when asked to open an already opened device. So
+ * the best we can do is to cache the lastly used device path and close and
+ * open devices in ofwd_strategy() as needed.
+ */
+static struct ofw_devdesc *kdp;
static int
ofwd_init(void)
{
- return 0;
+ return (0);
}
static int
-ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf,
- size_t *rsize)
+ofwd_strategy(void *devdata, int flag __unused, daddr_t dblk, size_t size,
+ char *buf, size_t *rsize)
{
struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata;
daddr_t pos;
int n;
+ if (dp != kdp) {
+ if (kdp != NULL) {
+#if !defined(__powerpc__)
+ OF_close(kdp->d_handle);
+#endif
+ kdp = NULL;
+ }
+ if ((dp->d_handle = OF_open(dp->d_path)) == -1)
+ return (ENOENT);
+ kdp = dp;
+ }
+
pos = dblk * 512;
do {
if (OF_seek(dp->d_handle, pos) < 0)
- return EIO;
+ return (EIO);
n = OF_read(dp->d_handle, buf, size);
if (n < 0 && n != -2)
- return EIO;
+ return (EIO);
} while (n == -2);
*rsize = size;
- return 0;
+ return (0);
}
static int
ofwd_open(struct open_file *f, ...)
{
- char path[256];
struct ofw_devdesc *dp;
- struct opened_dev *odp;
va_list vl;
va_start(vl, f);
dp = va_arg(vl, struct ofw_devdesc *);
va_end(vl);
- /*
- * We're not guaranteed to be able to open a device more than once
- * simultaneously and there is no OFW standard method to determine
- * whether a device is already opened. Opening a device more than
- * once happens to work with most OFW block device drivers but
- * triggers a trap with at least the driver for the on-board SCSI
- * controller in Sun Ultra 1. Upper layers and MI code expect to
- * be able to open a device more than once however. As a workaround
- * keep track of the opened devices and reuse the instance handle
- * when asked to open an already opened device.
- */
- SLIST_FOREACH(odp, &opened_devs, link) {
- if (OF_instance_to_path(odp->handle, path, sizeof(path)) == -1)
- continue;
- if (strcmp(path, dp->d_path) == 0) {
- odp->count++;
- dp->d_handle = odp->handle;
- return 0;
+
+ if (dp != kdp) {
+ if (kdp != NULL) {
+ OF_close(kdp->d_handle);
+ kdp = NULL;
}
+ if ((dp->d_handle = OF_open(dp->d_path)) == -1) {
+ printf("%s: Could not open %s\n", __func__,
+ dp->d_path);
+ return (ENOENT);
+ }
+ kdp = dp;
}
- odp = malloc(sizeof(struct opened_dev));
- if (odp == NULL) {
- printf("ofwd_open: malloc failed\n");
- return ENOMEM;
- }
- if ((odp->handle = OF_open(dp->d_path)) == -1) {
- printf("ofwd_open: Could not open %s\n", dp->d_path);
- free(odp);
- return ENOENT;
- }
- odp->count = 1;
- SLIST_INSERT_HEAD(&opened_devs, odp, link);
- dp->d_handle = odp->handle;
- return 0;
+ return (0);
}
static int
ofwd_close(struct open_file *f)
{
struct ofw_devdesc *dev = f->f_devdata;
- struct opened_dev *odp;
- SLIST_FOREACH(odp, &opened_devs, link) {
- if (odp->handle == dev->d_handle) {
- odp->count--;
- if (odp->count == 0) {
- SLIST_REMOVE(&opened_devs, odp, opened_dev,
- link);
- #if !defined(__powerpc__)
- OF_close(odp->handle);
- #endif
- free(odp);
- }
- break;
- }
+ if (dev == kdp) {
+#if !defined(__powerpc__)
+ OF_close(dev->d_handle);
+#endif
+ kdp = NULL;
}
- return 0;
+ return (0);
}
static int
-ofwd_ioctl(struct open_file *f, u_long cmd, void *data)
+ofwd_ioctl(struct open_file *f __unused, u_long cmd __unused,
+ void *data __unused)
{
return (EINVAL);
}
static void
-ofwd_print(int verbose)
+ofwd_print(int verbose __unused)
{
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/boot2/boot2.c
--- a/head/sys/boot/pc98/boot2/boot2.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/pc98/boot2/boot2.c Wed Jul 25 16:45:04 2012 +0300
@@ -15,7 +15,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/pc98/boot2/boot2.c 232784 2012-03-10 15:08:37Z nyan $");
+__FBSDID("$FreeBSD: head/sys/boot/pc98/boot2/boot2.c 235988 2012-05-25 09:36:39Z gleb $");
#include <sys/param.h>
#include <sys/disklabel.h>
@@ -140,7 +140,6 @@
void exit(int);
static void load(void);
static int parse(void);
-static int xfsread(ino_t, void *, size_t);
static int dskread(void *, unsigned, unsigned);
static void printf(const char *,...);
static void putchar(int);
@@ -172,7 +171,7 @@
#include "ufsread.c"
static inline int
-xfsread(ino_t inode, void *buf, size_t nbyte)
+xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
{
if ((size_t)fsread(inode, buf, nbyte) != nbyte) {
printf("Invalid %s\n", "format");
@@ -351,7 +350,7 @@
int i;
#endif
uint8_t autoboot;
- ino_t ino;
+ ufs_ino_t ino;
size_t nbyte;
dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
@@ -446,7 +445,7 @@
static Elf32_Phdr ep[2];
static Elf32_Shdr es[2];
caddr_t p;
- ino_t ino;
+ ufs_ino_t ino;
uint32_t addr;
int i, j;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/btx/btx/Makefile
--- a/head/sys/boot/pc98/btx/btx/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/pc98/btx/btx/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/boot/pc98/btx/btx/Makefile 232263 2012-02-28 18:30:18Z dim $
+# $FreeBSD: head/sys/boot/pc98/btx/btx/Makefile 235264 2012-05-11 09:46:17Z avg $
PROG= btx
INTERNALPROG=
@@ -12,6 +12,7 @@
.endif
CFLAGS+=-DBTX_FLAGS=${BOOT_BTX_FLAGS}
+CFLAGS+=-I${.CURDIR}/../../../i386/common
.if defined(BTX_SERIAL)
BOOT_COMCONSOLE_PORT?= 0x238
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/btx/btx/btx.S
--- a/head/sys/boot/pc98/btx/btx/btx.S Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/pc98/btx/btx/btx.S Wed Jul 25 16:45:04 2012 +0300
@@ -12,9 +12,11 @@
* warranties of merchantability and fitness for a particular
* purpose.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/pc98/btx/btx/btx.S 235264 2012-05-11 09:46:17Z avg $
*/
+#include <bootargs.h>
+
/*
* Memory layout.
*/
@@ -205,7 +207,7 @@
andl $0x7,%eax
incl %eax
shll $0x11,%eax # To bytes
- subl $0x1000,%eax # Less arg space
+ subl $ARGSPACE,%eax # Less arg space
subl %edx,%eax # Less base
movb $SEL_UDATA,%cl # User data selector
pushl %ecx # Set SS
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/btx/btxldr/Makefile
--- a/head/sys/boot/pc98/btx/btxldr/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/pc98/btx/btxldr/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/boot/pc98/btx/btxldr/Makefile 232263 2012-02-28 18:30:18Z dim $
+# $FreeBSD: head/sys/boot/pc98/btx/btxldr/Makefile 235264 2012-05-11 09:46:17Z avg $
PROG= btxldr
INTERNALPROG=
@@ -6,6 +6,7 @@
SRCS= btxldr.S
CFLAGS+=-DLOADER_ADDRESS=${LOADER_ADDRESS}
+CFLAGS+=-I${.CURDIR}/../../../i386/common
.if defined(BTXLDR_VERBOSE)
CFLAGS+=-DBTXLDR_VERBOSE
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/btx/btxldr/btxldr.S
--- a/head/sys/boot/pc98/btx/btxldr/btxldr.S Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/pc98/btx/btxldr/btxldr.S Wed Jul 25 16:45:04 2012 +0300
@@ -12,7 +12,7 @@
* warranties of merchantability and fitness for a particular
* purpose.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/pc98/btx/btxldr/btxldr.S 235264 2012-05-11 09:46:17Z avg $
*/
/*
@@ -20,6 +20,8 @@
* real thing should probably be more flexible, and in C.
*/
+#include <bootargs.h>
+
/*
* Memory locations.
*/
@@ -105,7 +107,7 @@
call hexout # stack
call putstr # pointer
movl $m_args,%esi # Format string
- leal 0x4(%esp,1),%ebx # First argument
+ leal 0x4(%esp),%ebx # First argument
movl $0x6,%ecx # Count
start.1: movl (%ebx),%eax # Get argument and
addl $0x4,%ebx # bump pointer
@@ -113,24 +115,28 @@
loop start.1 # Till done
call putstr # End message
#endif
- movl $0x48,%ecx # Allocate space
- subl %ecx,%ebp # for bootinfo
- movl 0x18(%esp,1),%esi # Source: bootinfo
+ movl BA_BOOTINFO+4(%esp),%esi # Source: bootinfo
cmpl $0x0, %esi # If the bootinfo pointer
je start_null_bi # is null, don't copy it
+ movl BI_SIZE(%esi),%ecx # Allocate space
+ subl %ecx,%ebp # for bootinfo
movl %ebp,%edi # Destination
rep # Copy
movsb # it
- movl %ebp,0x18(%esp,1) # Update pointer
+ movl %ebp,BA_BOOTINFO+4(%esp) # Update pointer
+ movl %edi,%ebp # Restore base pointer
#ifdef BTXLDR_VERBOSE
movl $m_rel_bi,%esi # Display
movl %ebp,%eax # bootinfo
call hexout # relocation
call putstr # message
#endif
-start_null_bi: movl $0x18,%ecx # Allocate space
- subl %ecx,%ebp # for arguments
- leal 0x4(%esp,1),%esi # Source
+start_null_bi: movl $BOOTARGS_SIZE,%ecx # Fixed size of arguments
+ testl $KARGS_FLAGS_EXTARG, BA_BOOTFLAGS+4(%esp) # Check for extra data
+ jz start_fixed # Skip if the flag is not set
+ addl BOOTARGS_SIZE+4(%esp),%ecx # Add size of variable args
+start_fixed: subl $ARGOFF,%ebp # Place args at fixed offset
+ leal 0x4(%esp),%esi # Source
movl %ebp,%edi # Destination
rep # Copy
movsb # them
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/btx/lib/Makefile
--- a/head/sys/boot/pc98/btx/lib/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/pc98/btx/lib/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,9 +1,10 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/boot/pc98/btx/lib/Makefile 235264 2012-05-11 09:46:17Z avg $
PROG= crt0.o
INTERNALPROG=
NO_MAN=
-SRCS= btxcsu.s btxsys.s btxv86.s
+SRCS= btxcsu.S btxsys.s btxv86.s
+CFLAGS+=-I${.CURDIR}/../../../i386/common
LDFLAGS=-Wl,-r
.include <bsd.prog.mk>
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/btx/lib/btxcsu.S
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/pc98/btx/lib/btxcsu.S Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 1998 Robert Nordier
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are freely
+# permitted provided that the above copyright notice and this
+# paragraph and the following disclaimer are duplicated in all
+# such forms.
+#
+# This software is provided "AS IS" and without any express or
+# implied warranties, including, without limitation, the implied
+# warranties of merchantability and fitness for a particular
+# purpose.
+#
+
+# $FreeBSD: head/sys/boot/pc98/btx/lib/btxcsu.S 235264 2012-05-11 09:46:17Z avg $
+
+#
+# BTX C startup code (ELF).
+#
+
+#include <bootargs.h>
+
+#
+# Globals.
+#
+ .global _start
+#
+# Client entry point.
+#
+_start: cld
+ pushl %eax
+ movl $_edata,%edi
+ movl $_end,%ecx
+ subl %edi, %ecx
+ xorb %al, %al
+ rep
+ stosb
+ popl __base
+ movl %esp,%eax # Set
+ addl $ARGADJ,%eax # argument
+ movl %eax,__args # pointer
+ call main # Invoke client main()
+ call exit # Invoke client exit()
+#
+# Data.
+#
+ .comm __base,4 # Client base address
+ .comm __args,4 # Client arguments
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/btx/lib/btxcsu.s
--- a/head/sys/boot/pc98/btx/lib/btxcsu.s Wed Jul 25 16:42:35 2012 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-#
-# Copyright (c) 1998 Robert Nordier
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms are freely
-# permitted provided that the above copyright notice and this
-# paragraph and the following disclaimer are duplicated in all
-# such forms.
-#
-# This software is provided "AS IS" and without any express or
-# implied warranties, including, without limitation, the implied
-# warranties of merchantability and fitness for a particular
-# purpose.
-#
-
-# $FreeBSD$
-
-#
-# BTX C startup code (ELF).
-#
-
-#
-# Globals.
-#
- .global _start
-#
-# Constants.
-#
- .set ARGADJ,0xfa0 # Argument adjustment
-#
-# Client entry point.
-#
-_start: cld
- pushl %eax
- movl $_edata,%edi
- movl $_end,%ecx
- subl %edi, %ecx
- xorb %al, %al
- rep
- stosb
- popl __base
- movl %esp,%eax # Set
- addl $ARGADJ,%eax # argument
- movl %eax,__args # pointer
- call main # Invoke client main()
- call exit # Invoke client exit()
-#
-# Data.
-#
- .comm __base,4 # Client base address
- .comm __args,4 # Client arguments
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/cdboot/Makefile
--- a/head/sys/boot/pc98/cdboot/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/pc98/cdboot/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,10 +1,12 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/boot/pc98/cdboot/Makefile 235264 2012-05-11 09:46:17Z avg $
PROG= cdboot
STRIP=
BINMODE=${NOBINMODE}
NO_MAN=
-SRCS= ${PROG}.s
+SRCS= ${PROG}.S
+
+CFLAGS+=-I${.CURDIR}/../../i386/common
ORG= 0x0000
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/cdboot/cdboot.S
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/pc98/cdboot/cdboot.S Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,808 @@
+#
+# Copyright (c) 2006 TAKAHASHI Yoshihiro <nyan at FreeBSD.org>
+# Copyright (c) 2001 John Baldwin <jhb at FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the author nor the names of any co-contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+# $FreeBSD: head/sys/boot/pc98/cdboot/cdboot.S 235264 2012-05-11 09:46:17Z avg $
+
+#include <bootargs.h>
+
+#
+# Basically, we first create a set of boot arguments to pass to the loaded
+# binary. Then we attempt to load /boot/loader from the CD we were booted
+# off of.
+#
+
+#
+# Memory locations.
+#
+ .set STACK_OFF,0x6000 # Stack offset
+ .set LOAD_SEG,0x0700 # Load segment
+ .set LOAD_SIZE,2048 # Load size
+ .set DAUA,0x0584 # DA/UA
+
+ .set MEM_PAGE_SIZE,0x1000 # memory page size, 4k
+ .set MEM_ARG,0x900 # Arguments at start
+ .set MEM_ARG_BTX,0xa100 # Where we move them to so the
+ # BTX client can see them
+ .set MEM_ARG_SIZE,0x18 # Size of the arguments
+ .set MEM_BTX_ADDRESS,0x9000 # where BTX lives
+ .set MEM_BTX_ENTRY,0x9010 # where BTX starts to execute
+ .set MEM_BTX_OFFSET,MEM_PAGE_SIZE # offset of BTX in the loader
+ .set MEM_BTX_CLIENT,0xa000 # where BTX clients live
+#
+# PC98 machine type from sys/pc98/pc98/pc98_machdep.h
+#
+ .set MEM_SYS, 0xa100 # System common area segment
+ .set PC98_MACHINE_TYPE, 0x0620 # PC98 machine type
+ .set EPSON_ID, 0x0624 # EPSON machine id
+
+ .set M_NEC_PC98, 0x0001
+ .set M_EPSON_PC98, 0x0002
+ .set M_NOT_H98, 0x0010
+ .set M_H98, 0x0020
+ .set M_NOTE, 0x0040
+ .set M_NORMAL, 0x1000
+ .set M_8M, 0x8000
+#
+# Signature Constants
+#
+ .set SIG1_OFF,0x1fe # Signature offset
+ .set SIG2_OFF,0x7fe # Signature offset
+#
+# a.out header fields
+#
+ .set AOUT_TEXT,0x04 # text segment size
+ .set AOUT_DATA,0x08 # data segment size
+ .set AOUT_BSS,0x0c # zero'd BSS size
+ .set AOUT_SYMBOLS,0x10 # symbol table
+ .set AOUT_ENTRY,0x14 # entry point
+ .set AOUT_HEADER,MEM_PAGE_SIZE # size of the a.out header
+#
+# Segment selectors.
+#
+ .set SEL_SDATA,0x8 # Supervisor data
+ .set SEL_RDATA,0x10 # Real mode data
+ .set SEL_SCODE,0x18 # PM-32 code
+ .set SEL_SCODE16,0x20 # PM-16 code
+#
+# BTX constants
+#
+ .set INT_SYS,0x30 # BTX syscall interrupt
+#
+# Constants for reading from the CD.
+#
+ .set ERROR_TIMEOUT,0x90 # BIOS timeout on read
+ .set NUM_RETRIES,3 # Num times to retry
+ .set SECTOR_SIZE,0x800 # size of a sector
+ .set SECTOR_SHIFT,11 # number of place to shift
+ .set BUFFER_LEN,0x100 # number of sectors in buffer
+ .set MAX_READ,0xf800 # max we can read at a time
+ .set MAX_READ_SEC,MAX_READ >> SECTOR_SHIFT
+ .set MEM_READ_BUFFER,0x9000 # buffer to read from CD
+ .set MEM_VOLDESC,MEM_READ_BUFFER # volume descriptor
+ .set MEM_DIR,MEM_VOLDESC+SECTOR_SIZE # Lookup buffer
+ .set VOLDESC_LBA,0x10 # LBA of vol descriptor
+ .set VD_PRIMARY,1 # Primary VD
+ .set VD_END,255 # VD Terminator
+ .set VD_ROOTDIR,156 # Offset of Root Dir Record
+ .set DIR_LEN,0 # Offset of Dir Record length
+ .set DIR_EA_LEN,1 # Offset of EA length
+ .set DIR_EXTENT,2 # Offset of 64-bit LBA
+ .set DIR_SIZE,10 # Offset of 64-bit length
+ .set DIR_NAMELEN,32 # Offset of 8-bit name len
+ .set DIR_NAME,33 # Offset of dir name
+
+#
+# Program start.
+#
+ .code16
+ .globl start
+
+start: jmp main
+
+ .org 4
+ .ascii "IPL1 "
+
+main: cld
+
+ /* Setup the stack */
+ xor %ax,%ax
+ mov %ax,%ss
+ mov $STACK_OFF,%sp
+
+ push %ecx
+
+ /* Setup graphic screen */
+ mov $0x42,%ah # 640x400
+ mov $0xc0,%ch
+ int $0x18
+ mov $0x40,%ah # graph on
+ int $0x18
+
+ /* Setup text screen */
+ mov $0x0a00,%ax # 80x25
+ int $0x18
+ mov $0x0c,%ah # text on
+ int $0x18
+ mov $0x13,%ah # cursor home
+ xor %dx,%dx
+ int $0x18
+ mov $0x11,%ah # cursor on
+ int $0x18
+
+ /* Setup keyboard */
+ mov $0x03,%ah
+ int $0x18
+
+ /* Transfer PC-9801 system common area */
+ xor %ax,%ax
+ mov %ax,%si
+ mov %ax,%ds
+ mov %ax,%di
+ mov $MEM_SYS,%ax
+ mov %ax,%es
+ mov $0x0600,%cx
+ rep
+ movsb
+
+ /* Transfer EPSON machine type */
+ mov $0xfd00,%ax
+ mov %ax,%ds
+ mov (0x804),%eax
+ and $0x00ffffff,%eax
+ mov %eax,%es:(EPSON_ID)
+
+ /* Set machine type to PC98_SYSTEM_PARAMETER */
+ call machine_check
+
+ /* Load cdboot */
+ xor %ax,%ax
+ mov %ax,%ds
+ mov $0x06,%ah /* Read data */
+ mov (DAUA),%al /* Read drive */
+ pop %ecx /* cylinder */
+ xor %dx,%dx /* head / sector */
+ mov $LOAD_SEG,%bx /* Load address */
+ mov %bx,%es
+ xor %bp,%bp
+ mov $LOAD_SIZE,%bx /* Load size */
+ int $0x1b
+ mov $msg_readerr,%si
+ jc error
+
+ /* Jump to cdboot */
+ ljmp $LOAD_SEG,$cdboot
+
+#
+# Set machine type to PC98_SYSTEM_PARAMETER.
+#
+machine_check: xor %edx,%edx
+ mov %dx,%ds
+ mov $MEM_SYS,%ax
+ mov %ax,%es
+
+ /* Wait V-SYNC */
+vsync.1: inb $0x60,%al
+ test $0x20,%al
+ jnz vsync.1
+vsync.2: inb $0x60,%al
+ test $0x20,%al
+ jz vsync.2
+
+ /* ANK 'A' font */
+ xor %al,%al
+ outb %al,$0xa1
+ mov $0x41,%al
+ outb %al,$0xa3
+
+ /* Get 'A' font from CG window */
+ push %ds
+ mov $0xa400,%ax
+ mov %ax,%ds
+ xor %eax,%eax
+ xor %bx,%bx
+ mov $4,%cx
+font.1: add (%bx),%eax
+ add $4,%bx
+ loop font.1
+ pop %ds
+ cmp $0x6efc58fc,%eax
+ jnz m_epson
+
+m_pc98: or $M_NEC_PC98,%edx
+ mov $0x0458,%bx
+ mov (%bx),%al
+ test $0x80,%al
+ jz m_not_h98
+ or $M_H98,%edx
+ jmp 1f
+m_epson: or $M_EPSON_PC98,%edx
+m_not_h98: or $M_NOT_H98,%edx
+
+1: inb $0x42,%al
+ test $0x20,%al
+ jz 1f
+ or $M_8M,%edx
+
+1: mov $0x0400,%bx
+ mov (%bx),%al
+ test $0x80,%al
+ jz 1f
+ or $M_NOTE,%edx
+
+1: mov $PC98_MACHINE_TYPE,%bx
+ mov %edx,%es:(%bx)
+ ret
+
+#
+# Print out the error message at [SI], wait for a keypress, and then
+# reboot the machine.
+#
+error: call putstr
+ mov $msg_keypress,%si
+ call putstr
+ xor %ax,%ax # Get keypress
+ int $0x18
+ xor %ax,%ax # CPU reset
+ outb %al,$0xf0
+halt: hlt
+ jmp halt # Spin
+
+#
+# Display a null-terminated string at [SI].
+#
+# Trashes: AX, BX, CX, DX, SI, DI
+#
+putstr: push %ds
+ push %es
+ mov %cs,%ax
+ mov %ax,%ds
+ mov $0xa000,%ax
+ mov %ax,%es
+ mov cursor,%di
+ mov $0x00e1,%bx # Attribute
+ mov $160,%cx
+putstr.0: lodsb
+ testb %al,%al
+ jz putstr.done
+ cmp $0x0d,%al
+ jz putstr.cr
+ cmp $0x0a,%al
+ jz putstr.lf
+ mov %bl,%es:0x2000(%di)
+ stosb
+ inc %di
+ jmp putstr.move
+putstr.cr: xor %dx,%dx
+ mov %di,%ax
+ div %cx
+ sub %dx,%di
+ jmp putstr.move
+putstr.lf: add %cx,%di
+putstr.move: mov %di,%dx
+ mov $0x13,%ah # Move cursor
+ int $0x18
+ jmp putstr.0
+putstr.done: mov %di,cursor
+ pop %es
+ pop %ds
+ ret
+
+#
+# Display a single char at [AL], but don't move a cursor.
+#
+putc: push %es
+ push %di
+ push %bx
+ mov $0xa000,%bx
+ mov %bx,%es
+ mov cursor,%di
+ mov $0xe1,%bl # Attribute
+ mov %bl,%es:0x2000(%di)
+ stosb
+ pop %bx
+ pop %di
+ pop %es
+ ret
+
+msg_readerr: .asciz "Read Error\r\n"
+msg_keypress: .asciz "\r\nPress any key to reboot\r\n"
+
+/* Boot signature */
+
+ .org SIG1_OFF,0x90
+
+ .word 0xaa55 # Magic number
+
+#
+# cdboot
+#
+cdboot: mov %cs,%ax
+ mov %ax,%ds
+ xor %ax,%ax
+ mov %ax,%es
+ mov %es:(DAUA),%al # Save BIOS boot device
+ mov %al,drive
+ mov %cx,cylinder # Save BIOS boot cylinder
+
+ mov $msg_welcome,%si # %ds:(%si) -> welcome message
+ call putstr # display the welcome message
+#
+# Setup the arguments that the loader is expecting from boot[12]
+#
+ mov $msg_bootinfo,%si # %ds:(%si) -> boot args message
+ call putstr # display the message
+ mov $MEM_ARG,%bx # %ds:(%bx) -> boot args
+ mov %bx,%di # %es:(%di) -> boot args
+ xor %eax,%eax # zero %eax
+ mov $(MEM_ARG_SIZE/4),%cx # Size of arguments in 32-bit
+ # dwords
+ rep # Clear the arguments
+ stosl # to zero
+ mov drive,%dl # Store BIOS boot device
+ mov %dl,%es:0x4(%bx) # in kargs->bootdev
+ or $KARGS_FLAGS_CD,%es:0x8(%bx) # kargs->bootflags |=
+ # KARGS_FLAGS_CD
+#
+# Load Volume Descriptor
+#
+ mov $VOLDESC_LBA,%eax # Set LBA of first VD
+load_vd: push %eax # Save %eax
+ mov $1,%dh # One sector
+ mov $MEM_VOLDESC,%ebx # Destination
+ call read # Read it in
+ cmpb $VD_PRIMARY,%es:(%bx) # Primary VD?
+ je have_vd # Yes
+ pop %eax # Prepare to
+ inc %eax # try next
+ cmpb $VD_END,%es:(%bx) # Last VD?
+ jne load_vd # No, read next
+ mov $msg_novd,%si # No VD
+ jmp error # Halt
+have_vd: # Have Primary VD
+#
+# Try to look up the loader binary using the paths in the loader_paths
+# array.
+#
+ mov $loader_paths,%si # Point to start of array
+lookup_path: push %si # Save file name pointer
+ call lookup # Try to find file
+ pop %di # Restore file name pointer
+ jnc lookup_found # Found this file
+ push %es
+ mov %cs,%ax
+ mov %ax,%es
+ xor %al,%al # Look for next
+ mov $0xffff,%cx # path name by
+ repnz # scanning for
+ scasb # nul char
+ pop %es
+ mov %di,%si # Point %si at next path
+ mov (%si),%al # Get first char of next path
+ or %al,%al # Is it double nul?
+ jnz lookup_path # No, try it.
+ mov $msg_failed,%si # Failed message
+ jmp error # Halt
+lookup_found: # Found a loader file
+#
+# Load the binary into the buffer. Due to real mode addressing limitations
+# we have to read it in 64k chunks.
+#
+ mov %es:DIR_SIZE(%bx),%eax # Read file length
+ add $SECTOR_SIZE-1,%eax # Convert length to sectors
+ shr $SECTOR_SHIFT,%eax
+ cmp $BUFFER_LEN,%eax
+ jbe load_sizeok
+ mov $msg_load2big,%si # Error message
+ jmp error
+load_sizeok: movzbw %al,%cx # Num sectors to read
+ mov %es:DIR_EXTENT(%bx),%eax # Load extent
+ xor %edx,%edx
+ mov %es:DIR_EA_LEN(%bx),%dl
+ add %edx,%eax # Skip extended
+ mov $MEM_READ_BUFFER,%ebx # Read into the buffer
+load_loop: mov %cl,%dh
+ cmp $MAX_READ_SEC,%cl # Truncate to max read size
+ jbe load_notrunc
+ mov $MAX_READ_SEC,%dh
+load_notrunc: sub %dh,%cl # Update count
+ push %eax # Save
+ call read # Read it in
+ pop %eax # Restore
+ add $MAX_READ_SEC,%eax # Update LBA
+ add $MAX_READ,%ebx # Update dest addr
+ jcxz load_done # Done?
+ jmp load_loop # Keep going
+load_done:
+#
+# Turn on the A20 address line
+#
+ xor %ax,%ax # Turn A20 on
+ outb %al,$0xf2
+ mov $0x02,%al
+ outb %al,$0xf6
+#
+# Relocate the loader and BTX using a very lazy protected mode
+#
+ mov $msg_relocate,%si # Display the
+ call putstr # relocation message
+ mov %es:(MEM_READ_BUFFER+AOUT_ENTRY),%edi # %edi is the destination
+ mov $(MEM_READ_BUFFER+AOUT_HEADER),%esi # %esi is
+ # the start of the text
+ # segment
+ mov %es:(MEM_READ_BUFFER+AOUT_TEXT),%ecx # %ecx = length of the text
+ # segment
+ push %edi # Save entry point for later
+ lgdt gdtdesc # setup our own gdt
+ cli # turn off interrupts
+ mov %cr0,%eax # Turn on
+ or $0x1,%al # protected
+ mov %eax,%cr0 # mode
+ ljmp $SEL_SCODE,$pm_start # long jump to clear the
+ # instruction pre-fetch queue
+ .code32
+pm_start: mov $SEL_SDATA,%ax # Initialize
+ mov %ax,%ds # %ds and
+ mov %ax,%es # %es to a flat selector
+ rep # Relocate the
+ movsb # text segment
+ add $(MEM_PAGE_SIZE - 1),%edi # pad %edi out to a new page
+ and $~(MEM_PAGE_SIZE - 1),%edi # for the data segment
+ mov MEM_READ_BUFFER+AOUT_DATA,%ecx # size of the data segment
+ rep # Relocate the
+ movsb # data segment
+ mov MEM_READ_BUFFER+AOUT_BSS,%ecx # size of the bss
+ xor %eax,%eax # zero %eax
+ add $3,%cl # round %ecx up to
+ shr $2,%ecx # a multiple of 4
+ rep # zero the
+ stosl # bss
+ mov MEM_READ_BUFFER+AOUT_ENTRY,%esi # %esi -> relocated loader
+ add $MEM_BTX_OFFSET,%esi # %esi -> BTX in the loader
+ mov $MEM_BTX_ADDRESS,%edi # %edi -> where BTX needs to go
+ movzwl 0xa(%esi),%ecx # %ecx -> length of BTX
+ rep # Relocate
+ movsb # BTX
+ ljmp $SEL_SCODE16,$pm_16 # Jump to 16-bit PM
+ .code16
+pm_16: mov $SEL_RDATA,%ax # Initialize
+ mov %ax,%ds # %ds and
+ mov %ax,%es # %es to a real mode selector
+ mov %cr0,%eax # Turn off
+ and $~0x1,%al # protected
+ mov %eax,%cr0 # mode
+ ljmp $LOAD_SEG,$pm_end # Long jump to clear the
+ # instruction pre-fetch queue
+pm_end: sti # Turn interrupts back on now
+#
+# Copy the BTX client to MEM_BTX_CLIENT
+#
+ mov %cs,%ax
+ mov %ax,%ds
+ xor %ax,%ax
+ mov %ax,%es
+ mov $MEM_BTX_CLIENT,%di # Prepare to relocate
+ mov $btx_client,%si # the simple btx client
+ mov $(btx_client_end-btx_client),%cx # length of btx client
+ rep # Relocate the
+ movsb # simple BTX client
+#
+# Copy the boot[12] args to where the BTX client can see them
+#
+ xor %ax,%ax
+ mov %ax,%ds
+ mov $MEM_ARG,%si # where the args are at now
+ mov $MEM_ARG_BTX,%di # where the args are moving to
+ mov $(MEM_ARG_SIZE/4),%cx # size of the arguments in longs
+ rep # Relocate
+ movsl # the words
+#
+# Save the entry point so the client can get to it later on
+#
+ pop %eax # Restore saved entry point
+ stosl # and add it to the end of
+ # the arguments
+#
+# Now we just start up BTX and let it do the rest
+#
+ mov $msg_jump,%si # Display the
+ call putstr # jump message
+ ljmp $0,$MEM_BTX_ENTRY # Jump to the BTX entry point
+
+#
+# Lookup the file in the path at [SI] from the root directory.
+#
+# Trashes: All but BX
+# Returns: CF = 0 (success), BX = pointer to record
+# CF = 1 (not found)
+#
+lookup: mov $VD_ROOTDIR+MEM_VOLDESC,%bx # Root directory record
+ push %bx
+ push %si
+ mov $msg_lookup,%si # Display lookup message
+ call putstr
+ pop %si
+ push %si
+ call putstr
+ mov $msg_lookup2,%si
+ call putstr
+ pop %si
+ pop %bx
+lookup_dir: lodsb # Get first char of path
+ cmp $0,%al # Are we done?
+ je lookup_done # Yes
+ cmp $'/',%al # Skip path separator.
+ je lookup_dir
+ dec %si # Undo lodsb side effect
+ call find_file # Lookup first path item
+ jnc lookup_dir # Try next component
+ mov $msg_lookupfail,%si # Not found message
+ push %bx
+ call putstr
+ pop %bx
+ stc # Set carry
+ ret
+lookup_done: mov $msg_lookupok,%si # Success message
+ push %bx
+ call putstr
+ pop %bx
+ clc # Clear carry
+ ret
+
+#
+# Lookup file at [SI] in directory whose record is at [BX].
+#
+# Trashes: All but returns
+# Returns: CF = 0 (success), BX = pointer to record, SI = next path item
+# CF = 1 (not found), SI = preserved
+#
+find_file: mov %es:DIR_EXTENT(%bx),%eax # Load extent
+ xor %edx,%edx
+ mov %es:DIR_EA_LEN(%bx),%dl
+ add %edx,%eax # Skip extended attributes
+ mov %eax,rec_lba # Save LBA
+ mov %es:DIR_SIZE(%bx),%eax # Save size
+ mov %eax,rec_size
+ xor %cl,%cl # Zero length
+ push %si # Save
+ff.namelen: inc %cl # Update length
+ lodsb # Read char
+ cmp $0,%al # Nul?
+ je ff.namedone # Yes
+ cmp $'/',%al # Path separator?
+ jnz ff.namelen # No, keep going
+ff.namedone: dec %cl # Adjust length and save
+ mov %cl,name_len
+ pop %si # Restore
+ff.load: mov rec_lba,%eax # Load LBA
+ mov $MEM_DIR,%ebx # Address buffer
+ mov $1,%dh # One sector
+ call read # Read directory block
+ incl rec_lba # Update LBA to next block
+ff.scan: mov %ebx,%edx # Check for EOF
+ sub $MEM_DIR,%edx
+ cmp %edx,rec_size
+ ja ff.scan.1
+ stc # EOF reached
+ ret
+ff.scan.1: cmpb $0,%es:DIR_LEN(%bx) # Last record in block?
+ je ff.nextblock
+ push %si # Save
+ movzbw %es:DIR_NAMELEN(%bx),%si # Find end of string
+ff.checkver: cmpb $'0',%es:DIR_NAME-1(%bx,%si) # Less than '0'?
+ jb ff.checkver.1
+ cmpb $'9',%es:DIR_NAME-1(%bx,%si) # Greater than '9'?
+ ja ff.checkver.1
+ dec %si # Next char
+ jnz ff.checkver
+ jmp ff.checklen # All numbers in name, so
+ # no version
+ff.checkver.1: movzbw %es:DIR_NAMELEN(%bx),%cx
+ cmp %cx,%si # Did we find any digits?
+ je ff.checkdot # No
+ cmpb $';',%es:DIR_NAME-1(%bx,%si) # Check for semicolon
+ jne ff.checkver.2
+ dec %si # Skip semicolon
+ mov %si,%cx
+ mov %cl,%es:DIR_NAMELEN(%bx) # Adjust length
+ jmp ff.checkdot
+ff.checkver.2: mov %cx,%si # Restore %si to end of string
+ff.checkdot: cmpb $'.',%es:DIR_NAME-1(%bx,%si) # Trailing dot?
+ jne ff.checklen # No
+ decb %es:DIR_NAMELEN(%bx) # Adjust length
+ff.checklen: pop %si # Restore
+ movzbw name_len,%cx # Load length of name
+ cmp %cl,%es:DIR_NAMELEN(%bx) # Does length match?
+ je ff.checkname # Yes, check name
+ff.nextrec: add %es:DIR_LEN(%bx),%bl # Next record
+ adc $0,%bh
+ jmp ff.scan
+ff.nextblock: subl $SECTOR_SIZE,rec_size # Adjust size
+ jnc ff.load # If subtract ok, keep going
+ ret # End of file, so not found
+ff.checkname: lea DIR_NAME(%bx),%di # Address name in record
+ push %si # Save
+ repe cmpsb # Compare name
+ je ff.match # We have a winner!
+ pop %si # Restore
+ jmp ff.nextrec # Keep looking.
+ff.match: add $2,%sp # Discard saved %si
+ clc # Clear carry
+ ret
+
+#
+# Load DH sectors starting at LBA EAX into [EBX].
+#
+# Trashes: EAX
+#
+read: push %es # Save
+ push %bp
+ push %dx
+ push %cx
+ push %ebx
+ mov %bx,%bp # Set destination address
+ and $0x000f,%bp
+ shr $4,%ebx
+ mov %bx,%es
+ xor %bx,%bx # Set read bytes
+ mov %dh,%bl
+ shl $SECTOR_SHIFT,%bx # 2048 bytes/sec
+ mov %ax,%cx # Set LBA
+ shr $16,%eax
+ mov %ax,%dx
+read.retry: mov $0x06,%ah # BIOS device read
+ mov drive,%al
+ and $0x7f,%al
+ call twiddle # Entertain the user
+ int $0x1b # Call BIOS
+ jc read.fail # Worked?
+ pop %ebx # Restore
+ pop %cx
+ pop %dx
+ pop %bp
+ pop %es
+ ret # Return
+read.fail: cmp $ERROR_TIMEOUT,%ah # Timeout?
+ je read.retry # Yes, Retry.
+read.error: mov %ah,%al # Save error
+ mov $hex_error,%di # Format it
+ call hex8 # as hex
+ mov $msg_badread,%si # Display Read error message
+ jmp error
+
+#
+# Output the "twiddle"
+#
+twiddle: push %ax # Save
+ push %bx # Save
+ mov twiddle_index,%al # Load index
+ mov $twiddle_chars,%bx # Address table
+ inc %al # Next
+ and $3,%al # char
+ mov %al,twiddle_index # Save index for next call
+ xlat # Get char
+ call putc # Output it
+ pop %bx # Restore
+ pop %ax # Restore
+ ret
+
+#
+# Convert AL to hex, saving the result to [EDI].
+#
+hex8: pushl %eax # Save
+ shrb $0x4,%al # Do upper
+ call hex8.1 # 4
+ popl %eax # Restore
+hex8.1: andb $0xf,%al # Get lower 4
+ cmpb $0xa,%al # Convert
+ sbbb $0x69,%al # to hex
+ das # digit
+ orb $0x20,%al # To lower case
+ mov %al,(%di) # Save char
+ inc %di
+ ret # (Recursive)
+
+#
+# BTX client to start btxldr
+#
+ .code32
+btx_client: mov $(MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE-4), %esi
+ # %ds:(%esi) -> end
+ # of boot[12] args
+ mov $(MEM_ARG_SIZE/4),%ecx # Number of words to push
+ std # Go backwards
+push_arg: lodsl # Read argument
+ push %eax # Push it onto the stack
+ loop push_arg # Push all of the arguments
+ cld # In case anyone depends on this
+ pushl MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE # Entry point of
+ # the loader
+ push %eax # Emulate a near call
+ mov $0x1,%eax # 'exec' system call
+ int $INT_SYS # BTX system call
+btx_client_end:
+ .code16
+
+ .p2align 4
+#
+# Global descriptor table.
+#
+gdt: .word 0x0,0x0,0x0,0x0 # Null entry
+ .word 0xffff,0x0000,0x9200,0x00cf # SEL_SDATA
+ .word 0xffff,0x0000,0x9200,0x0000 # SEL_RDATA
+ .word 0xffff,LOAD_SEG<<4,0x9a00,0x00cf # SEL_SCODE (32-bit)
+ .word 0xffff,LOAD_SEG<<4,0x9a00,0x008f # SEL_SCODE16 (16-bit)
+gdt.1:
+#
+# Pseudo-descriptors.
+#
+gdtdesc: .word gdt.1-gdt-1 # Limit
+ .long LOAD_SEG<<4 + gdt # Base
+
+#
+# BOOT device
+#
+drive: .byte 0
+cylinder: .word 0
+
+#
+# State for searching dir
+#
+rec_lba: .long 0x0 # LBA (adjusted for EA)
+rec_size: .long 0x0 # File size
+name_len: .byte 0x0 # Length of current name
+
+cursor: .word 0
+twiddle_index: .byte 0x0
+
+msg_welcome: .asciz "CD Loader 1.2\r\n\n"
+msg_bootinfo: .asciz "Building the boot loader arguments\r\n"
+msg_relocate: .asciz "Relocating the loader and the BTX\r\n"
+msg_jump: .asciz "Starting the BTX loader\r\n"
+msg_badread: .ascii "Read Error: 0x"
+hex_error: .asciz "00\r\n"
+msg_novd: .asciz "Could not find Primary Volume Descriptor\r\n"
+msg_lookup: .asciz "Looking up "
+msg_lookup2: .asciz "... "
+msg_lookupok: .asciz "Found\r\n"
+msg_lookupfail: .asciz "File not found\r\n"
+msg_load2big: .asciz "File too big\r\n"
+msg_failed: .asciz "Boot failed\r\n"
+twiddle_chars: .ascii "|/-\\"
+loader_paths: .asciz "/BOOT.PC98/LOADER"
+ .asciz "/boot.pc98/loader"
+ .asciz "/BOOT/LOADER"
+ .asciz "/boot/loader"
+ .byte 0
+
+/* Boot signature */
+
+ .org SIG2_OFF,0x90
+
+ .word 0xaa55 # Magic number
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/cdboot/cdboot.s
--- a/head/sys/boot/pc98/cdboot/cdboot.s Wed Jul 25 16:42:35 2012 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,811 +0,0 @@
-#
-# Copyright (c) 2006 TAKAHASHI Yoshihiro <nyan at FreeBSD.org>
-# Copyright (c) 2001 John Baldwin <jhb at FreeBSD.org>
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# 3. Neither the name of the author nor the names of any co-contributors
-# may be used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-
-# $FreeBSD$
-
-#
-# Basically, we first create a set of boot arguments to pass to the loaded
-# binary. Then we attempt to load /boot/loader from the CD we were booted
-# off of.
-#
-
-#
-# Memory locations.
-#
- .set STACK_OFF,0x6000 # Stack offset
- .set LOAD_SEG,0x0700 # Load segment
- .set LOAD_SIZE,2048 # Load size
- .set DAUA,0x0584 # DA/UA
-
- .set MEM_PAGE_SIZE,0x1000 # memory page size, 4k
- .set MEM_ARG,0x900 # Arguments at start
- .set MEM_ARG_BTX,0xa100 # Where we move them to so the
- # BTX client can see them
- .set MEM_ARG_SIZE,0x18 # Size of the arguments
- .set MEM_BTX_ADDRESS,0x9000 # where BTX lives
- .set MEM_BTX_ENTRY,0x9010 # where BTX starts to execute
- .set MEM_BTX_OFFSET,MEM_PAGE_SIZE # offset of BTX in the loader
- .set MEM_BTX_CLIENT,0xa000 # where BTX clients live
-#
-# PC98 machine type from sys/pc98/pc98/pc98_machdep.h
-#
- .set MEM_SYS, 0xa100 # System common area segment
- .set PC98_MACHINE_TYPE, 0x0620 # PC98 machine type
- .set EPSON_ID, 0x0624 # EPSON machine id
-
- .set M_NEC_PC98, 0x0001
- .set M_EPSON_PC98, 0x0002
- .set M_NOT_H98, 0x0010
- .set M_H98, 0x0020
- .set M_NOTE, 0x0040
- .set M_NORMAL, 0x1000
- .set M_8M, 0x8000
-#
-# Signature Constants
-#
- .set SIG1_OFF,0x1fe # Signature offset
- .set SIG2_OFF,0x7fe # Signature offset
-#
-# a.out header fields
-#
- .set AOUT_TEXT,0x04 # text segment size
- .set AOUT_DATA,0x08 # data segment size
- .set AOUT_BSS,0x0c # zero'd BSS size
- .set AOUT_SYMBOLS,0x10 # symbol table
- .set AOUT_ENTRY,0x14 # entry point
- .set AOUT_HEADER,MEM_PAGE_SIZE # size of the a.out header
-#
-# Flags for kargs->bootflags
-#
- .set KARGS_FLAGS_CD,0x1 # flag to indicate booting from
- # CD loader
-#
-# Segment selectors.
-#
- .set SEL_SDATA,0x8 # Supervisor data
- .set SEL_RDATA,0x10 # Real mode data
- .set SEL_SCODE,0x18 # PM-32 code
- .set SEL_SCODE16,0x20 # PM-16 code
-#
-# BTX constants
-#
- .set INT_SYS,0x30 # BTX syscall interrupt
-#
-# Constants for reading from the CD.
-#
- .set ERROR_TIMEOUT,0x90 # BIOS timeout on read
- .set NUM_RETRIES,3 # Num times to retry
- .set SECTOR_SIZE,0x800 # size of a sector
- .set SECTOR_SHIFT,11 # number of place to shift
- .set BUFFER_LEN,0x100 # number of sectors in buffer
- .set MAX_READ,0xf800 # max we can read at a time
- .set MAX_READ_SEC,MAX_READ >> SECTOR_SHIFT
- .set MEM_READ_BUFFER,0x9000 # buffer to read from CD
- .set MEM_VOLDESC,MEM_READ_BUFFER # volume descriptor
- .set MEM_DIR,MEM_VOLDESC+SECTOR_SIZE # Lookup buffer
- .set VOLDESC_LBA,0x10 # LBA of vol descriptor
- .set VD_PRIMARY,1 # Primary VD
- .set VD_END,255 # VD Terminator
- .set VD_ROOTDIR,156 # Offset of Root Dir Record
- .set DIR_LEN,0 # Offset of Dir Record length
- .set DIR_EA_LEN,1 # Offset of EA length
- .set DIR_EXTENT,2 # Offset of 64-bit LBA
- .set DIR_SIZE,10 # Offset of 64-bit length
- .set DIR_NAMELEN,32 # Offset of 8-bit name len
- .set DIR_NAME,33 # Offset of dir name
-
-#
-# Program start.
-#
- .code16
- .globl start
-
-start: jmp main
-
- .org 4
- .ascii "IPL1 "
-
-main: cld
-
- /* Setup the stack */
- xor %ax,%ax
- mov %ax,%ss
- mov $STACK_OFF,%sp
-
- push %ecx
-
- /* Setup graphic screen */
- mov $0x42,%ah # 640x400
- mov $0xc0,%ch
- int $0x18
- mov $0x40,%ah # graph on
- int $0x18
-
- /* Setup text screen */
- mov $0x0a00,%ax # 80x25
- int $0x18
- mov $0x0c,%ah # text on
- int $0x18
- mov $0x13,%ah # cursor home
- xor %dx,%dx
- int $0x18
- mov $0x11,%ah # cursor on
- int $0x18
-
- /* Setup keyboard */
- mov $0x03,%ah
- int $0x18
-
- /* Transfer PC-9801 system common area */
- xor %ax,%ax
- mov %ax,%si
- mov %ax,%ds
- mov %ax,%di
- mov $MEM_SYS,%ax
- mov %ax,%es
- mov $0x0600,%cx
- rep
- movsb
-
- /* Transfer EPSON machine type */
- mov $0xfd00,%ax
- mov %ax,%ds
- mov (0x804),%eax
- and $0x00ffffff,%eax
- mov %eax,%es:(EPSON_ID)
-
- /* Set machine type to PC98_SYSTEM_PARAMETER */
- call machine_check
-
- /* Load cdboot */
- xor %ax,%ax
- mov %ax,%ds
- mov $0x06,%ah /* Read data */
- mov (DAUA),%al /* Read drive */
- pop %ecx /* cylinder */
- xor %dx,%dx /* head / sector */
- mov $LOAD_SEG,%bx /* Load address */
- mov %bx,%es
- xor %bp,%bp
- mov $LOAD_SIZE,%bx /* Load size */
- int $0x1b
- mov $msg_readerr,%si
- jc error
-
- /* Jump to cdboot */
- ljmp $LOAD_SEG,$cdboot
-
-#
-# Set machine type to PC98_SYSTEM_PARAMETER.
-#
-machine_check: xor %edx,%edx
- mov %dx,%ds
- mov $MEM_SYS,%ax
- mov %ax,%es
-
- /* Wait V-SYNC */
-vsync.1: inb $0x60,%al
- test $0x20,%al
- jnz vsync.1
-vsync.2: inb $0x60,%al
- test $0x20,%al
- jz vsync.2
-
- /* ANK 'A' font */
- xor %al,%al
- outb %al,$0xa1
- mov $0x41,%al
- outb %al,$0xa3
-
- /* Get 'A' font from CG window */
- push %ds
- mov $0xa400,%ax
- mov %ax,%ds
- xor %eax,%eax
- xor %bx,%bx
- mov $4,%cx
-font.1: add (%bx),%eax
- add $4,%bx
- loop font.1
- pop %ds
- cmp $0x6efc58fc,%eax
- jnz m_epson
-
-m_pc98: or $M_NEC_PC98,%edx
- mov $0x0458,%bx
- mov (%bx),%al
- test $0x80,%al
- jz m_not_h98
- or $M_H98,%edx
- jmp 1f
-m_epson: or $M_EPSON_PC98,%edx
-m_not_h98: or $M_NOT_H98,%edx
-
-1: inb $0x42,%al
- test $0x20,%al
- jz 1f
- or $M_8M,%edx
-
-1: mov $0x0400,%bx
- mov (%bx),%al
- test $0x80,%al
- jz 1f
- or $M_NOTE,%edx
-
-1: mov $PC98_MACHINE_TYPE,%bx
- mov %edx,%es:(%bx)
- ret
-
-#
-# Print out the error message at [SI], wait for a keypress, and then
-# reboot the machine.
-#
-error: call putstr
- mov $msg_keypress,%si
- call putstr
- xor %ax,%ax # Get keypress
- int $0x18
- xor %ax,%ax # CPU reset
- outb %al,$0xf0
-halt: hlt
- jmp halt # Spin
-
-#
-# Display a null-terminated string at [SI].
-#
-# Trashes: AX, BX, CX, DX, SI, DI
-#
-putstr: push %ds
- push %es
- mov %cs,%ax
- mov %ax,%ds
- mov $0xa000,%ax
- mov %ax,%es
- mov cursor,%di
- mov $0x00e1,%bx # Attribute
- mov $160,%cx
-putstr.0: lodsb
- testb %al,%al
- jz putstr.done
- cmp $0x0d,%al
- jz putstr.cr
- cmp $0x0a,%al
- jz putstr.lf
- mov %bl,%es:0x2000(%di)
- stosb
- inc %di
- jmp putstr.move
-putstr.cr: xor %dx,%dx
- mov %di,%ax
- div %cx
- sub %dx,%di
- jmp putstr.move
-putstr.lf: add %cx,%di
-putstr.move: mov %di,%dx
- mov $0x13,%ah # Move cursor
- int $0x18
- jmp putstr.0
-putstr.done: mov %di,cursor
- pop %es
- pop %ds
- ret
-
-#
-# Display a single char at [AL], but don't move a cursor.
-#
-putc: push %es
- push %di
- push %bx
- mov $0xa000,%bx
- mov %bx,%es
- mov cursor,%di
- mov $0xe1,%bl # Attribute
- mov %bl,%es:0x2000(%di)
- stosb
- pop %bx
- pop %di
- pop %es
- ret
-
-msg_readerr: .asciz "Read Error\r\n"
-msg_keypress: .asciz "\r\nPress any key to reboot\r\n"
-
-/* Boot signature */
-
- .org SIG1_OFF,0x90
-
- .word 0xaa55 # Magic number
-
-#
-# cdboot
-#
-cdboot: mov %cs,%ax
- mov %ax,%ds
- xor %ax,%ax
- mov %ax,%es
- mov %es:(DAUA),%al # Save BIOS boot device
- mov %al,drive
- mov %cx,cylinder # Save BIOS boot cylinder
-
- mov $msg_welcome,%si # %ds:(%si) -> welcome message
- call putstr # display the welcome message
-#
-# Setup the arguments that the loader is expecting from boot[12]
-#
- mov $msg_bootinfo,%si # %ds:(%si) -> boot args message
- call putstr # display the message
- mov $MEM_ARG,%bx # %ds:(%bx) -> boot args
- mov %bx,%di # %es:(%di) -> boot args
- xor %eax,%eax # zero %eax
- mov $(MEM_ARG_SIZE/4),%cx # Size of arguments in 32-bit
- # dwords
- rep # Clear the arguments
- stosl # to zero
- mov drive,%dl # Store BIOS boot device
- mov %dl,%es:0x4(%bx) # in kargs->bootdev
- or $KARGS_FLAGS_CD,%es:0x8(%bx) # kargs->bootflags |=
- # KARGS_FLAGS_CD
-#
-# Load Volume Descriptor
-#
- mov $VOLDESC_LBA,%eax # Set LBA of first VD
-load_vd: push %eax # Save %eax
- mov $1,%dh # One sector
- mov $MEM_VOLDESC,%ebx # Destination
- call read # Read it in
- cmpb $VD_PRIMARY,%es:(%bx) # Primary VD?
- je have_vd # Yes
- pop %eax # Prepare to
- inc %eax # try next
- cmpb $VD_END,%es:(%bx) # Last VD?
- jne load_vd # No, read next
- mov $msg_novd,%si # No VD
- jmp error # Halt
-have_vd: # Have Primary VD
-#
-# Try to look up the loader binary using the paths in the loader_paths
-# array.
-#
- mov $loader_paths,%si # Point to start of array
-lookup_path: push %si # Save file name pointer
- call lookup # Try to find file
- pop %di # Restore file name pointer
- jnc lookup_found # Found this file
- push %es
- mov %cs,%ax
- mov %ax,%es
- xor %al,%al # Look for next
- mov $0xffff,%cx # path name by
- repnz # scanning for
- scasb # nul char
- pop %es
- mov %di,%si # Point %si at next path
- mov (%si),%al # Get first char of next path
- or %al,%al # Is it double nul?
- jnz lookup_path # No, try it.
- mov $msg_failed,%si # Failed message
- jmp error # Halt
-lookup_found: # Found a loader file
-#
-# Load the binary into the buffer. Due to real mode addressing limitations
-# we have to read it in 64k chunks.
-#
- mov %es:DIR_SIZE(%bx),%eax # Read file length
- add $SECTOR_SIZE-1,%eax # Convert length to sectors
- shr $SECTOR_SHIFT,%eax
- cmp $BUFFER_LEN,%eax
- jbe load_sizeok
- mov $msg_load2big,%si # Error message
- jmp error
-load_sizeok: movzbw %al,%cx # Num sectors to read
- mov %es:DIR_EXTENT(%bx),%eax # Load extent
- xor %edx,%edx
- mov %es:DIR_EA_LEN(%bx),%dl
- add %edx,%eax # Skip extended
- mov $MEM_READ_BUFFER,%ebx # Read into the buffer
-load_loop: mov %cl,%dh
- cmp $MAX_READ_SEC,%cl # Truncate to max read size
- jbe load_notrunc
- mov $MAX_READ_SEC,%dh
-load_notrunc: sub %dh,%cl # Update count
- push %eax # Save
- call read # Read it in
- pop %eax # Restore
- add $MAX_READ_SEC,%eax # Update LBA
- add $MAX_READ,%ebx # Update dest addr
- jcxz load_done # Done?
- jmp load_loop # Keep going
-load_done:
-#
-# Turn on the A20 address line
-#
- xor %ax,%ax # Turn A20 on
- outb %al,$0xf2
- mov $0x02,%al
- outb %al,$0xf6
-#
-# Relocate the loader and BTX using a very lazy protected mode
-#
- mov $msg_relocate,%si # Display the
- call putstr # relocation message
- mov %es:(MEM_READ_BUFFER+AOUT_ENTRY),%edi # %edi is the destination
- mov $(MEM_READ_BUFFER+AOUT_HEADER),%esi # %esi is
- # the start of the text
- # segment
- mov %es:(MEM_READ_BUFFER+AOUT_TEXT),%ecx # %ecx = length of the text
- # segment
- push %edi # Save entry point for later
- lgdt gdtdesc # setup our own gdt
- cli # turn off interrupts
- mov %cr0,%eax # Turn on
- or $0x1,%al # protected
- mov %eax,%cr0 # mode
- ljmp $SEL_SCODE,$pm_start # long jump to clear the
- # instruction pre-fetch queue
- .code32
-pm_start: mov $SEL_SDATA,%ax # Initialize
- mov %ax,%ds # %ds and
- mov %ax,%es # %es to a flat selector
- rep # Relocate the
- movsb # text segment
- add $(MEM_PAGE_SIZE - 1),%edi # pad %edi out to a new page
- and $~(MEM_PAGE_SIZE - 1),%edi # for the data segment
- mov MEM_READ_BUFFER+AOUT_DATA,%ecx # size of the data segment
- rep # Relocate the
- movsb # data segment
- mov MEM_READ_BUFFER+AOUT_BSS,%ecx # size of the bss
- xor %eax,%eax # zero %eax
- add $3,%cl # round %ecx up to
- shr $2,%ecx # a multiple of 4
- rep # zero the
- stosl # bss
- mov MEM_READ_BUFFER+AOUT_ENTRY,%esi # %esi -> relocated loader
- add $MEM_BTX_OFFSET,%esi # %esi -> BTX in the loader
- mov $MEM_BTX_ADDRESS,%edi # %edi -> where BTX needs to go
- movzwl 0xa(%esi),%ecx # %ecx -> length of BTX
- rep # Relocate
- movsb # BTX
- ljmp $SEL_SCODE16,$pm_16 # Jump to 16-bit PM
- .code16
-pm_16: mov $SEL_RDATA,%ax # Initialize
- mov %ax,%ds # %ds and
- mov %ax,%es # %es to a real mode selector
- mov %cr0,%eax # Turn off
- and $~0x1,%al # protected
- mov %eax,%cr0 # mode
- ljmp $LOAD_SEG,$pm_end # Long jump to clear the
- # instruction pre-fetch queue
-pm_end: sti # Turn interrupts back on now
-#
-# Copy the BTX client to MEM_BTX_CLIENT
-#
- mov %cs,%ax
- mov %ax,%ds
- xor %ax,%ax
- mov %ax,%es
- mov $MEM_BTX_CLIENT,%di # Prepare to relocate
- mov $btx_client,%si # the simple btx client
- mov $(btx_client_end-btx_client),%cx # length of btx client
- rep # Relocate the
- movsb # simple BTX client
-#
-# Copy the boot[12] args to where the BTX client can see them
-#
- xor %ax,%ax
- mov %ax,%ds
- mov $MEM_ARG,%si # where the args are at now
- mov $MEM_ARG_BTX,%di # where the args are moving to
- mov $(MEM_ARG_SIZE/4),%cx # size of the arguments in longs
- rep # Relocate
- movsl # the words
-#
-# Save the entry point so the client can get to it later on
-#
- pop %eax # Restore saved entry point
- stosl # and add it to the end of
- # the arguments
-#
-# Now we just start up BTX and let it do the rest
-#
- mov $msg_jump,%si # Display the
- call putstr # jump message
- ljmp $0,$MEM_BTX_ENTRY # Jump to the BTX entry point
-
-#
-# Lookup the file in the path at [SI] from the root directory.
-#
-# Trashes: All but BX
-# Returns: CF = 0 (success), BX = pointer to record
-# CF = 1 (not found)
-#
-lookup: mov $VD_ROOTDIR+MEM_VOLDESC,%bx # Root directory record
- push %bx
- push %si
- mov $msg_lookup,%si # Display lookup message
- call putstr
- pop %si
- push %si
- call putstr
- mov $msg_lookup2,%si
- call putstr
- pop %si
- pop %bx
-lookup_dir: lodsb # Get first char of path
- cmp $0,%al # Are we done?
- je lookup_done # Yes
- cmp $'/',%al # Skip path separator.
- je lookup_dir
- dec %si # Undo lodsb side effect
- call find_file # Lookup first path item
- jnc lookup_dir # Try next component
- mov $msg_lookupfail,%si # Not found message
- push %bx
- call putstr
- pop %bx
- stc # Set carry
- ret
-lookup_done: mov $msg_lookupok,%si # Success message
- push %bx
- call putstr
- pop %bx
- clc # Clear carry
- ret
-
-#
-# Lookup file at [SI] in directory whose record is at [BX].
-#
-# Trashes: All but returns
-# Returns: CF = 0 (success), BX = pointer to record, SI = next path item
-# CF = 1 (not found), SI = preserved
-#
-find_file: mov %es:DIR_EXTENT(%bx),%eax # Load extent
- xor %edx,%edx
- mov %es:DIR_EA_LEN(%bx),%dl
- add %edx,%eax # Skip extended attributes
- mov %eax,rec_lba # Save LBA
- mov %es:DIR_SIZE(%bx),%eax # Save size
- mov %eax,rec_size
- xor %cl,%cl # Zero length
- push %si # Save
-ff.namelen: inc %cl # Update length
- lodsb # Read char
- cmp $0,%al # Nul?
- je ff.namedone # Yes
- cmp $'/',%al # Path separator?
- jnz ff.namelen # No, keep going
-ff.namedone: dec %cl # Adjust length and save
- mov %cl,name_len
- pop %si # Restore
-ff.load: mov rec_lba,%eax # Load LBA
- mov $MEM_DIR,%ebx # Address buffer
- mov $1,%dh # One sector
- call read # Read directory block
- incl rec_lba # Update LBA to next block
-ff.scan: mov %ebx,%edx # Check for EOF
- sub $MEM_DIR,%edx
- cmp %edx,rec_size
- ja ff.scan.1
- stc # EOF reached
- ret
-ff.scan.1: cmpb $0,%es:DIR_LEN(%bx) # Last record in block?
- je ff.nextblock
- push %si # Save
- movzbw %es:DIR_NAMELEN(%bx),%si # Find end of string
-ff.checkver: cmpb $'0',%es:DIR_NAME-1(%bx,%si) # Less than '0'?
- jb ff.checkver.1
- cmpb $'9',%es:DIR_NAME-1(%bx,%si) # Greater than '9'?
- ja ff.checkver.1
- dec %si # Next char
- jnz ff.checkver
- jmp ff.checklen # All numbers in name, so
- # no version
-ff.checkver.1: movzbw %es:DIR_NAMELEN(%bx),%cx
- cmp %cx,%si # Did we find any digits?
- je ff.checkdot # No
- cmpb $';',%es:DIR_NAME-1(%bx,%si) # Check for semicolon
- jne ff.checkver.2
- dec %si # Skip semicolon
- mov %si,%cx
- mov %cl,%es:DIR_NAMELEN(%bx) # Adjust length
- jmp ff.checkdot
-ff.checkver.2: mov %cx,%si # Restore %si to end of string
-ff.checkdot: cmpb $'.',%es:DIR_NAME-1(%bx,%si) # Trailing dot?
- jne ff.checklen # No
- decb %es:DIR_NAMELEN(%bx) # Adjust length
-ff.checklen: pop %si # Restore
- movzbw name_len,%cx # Load length of name
- cmp %cl,%es:DIR_NAMELEN(%bx) # Does length match?
- je ff.checkname # Yes, check name
-ff.nextrec: add %es:DIR_LEN(%bx),%bl # Next record
- adc $0,%bh
- jmp ff.scan
-ff.nextblock: subl $SECTOR_SIZE,rec_size # Adjust size
- jnc ff.load # If subtract ok, keep going
- ret # End of file, so not found
-ff.checkname: lea DIR_NAME(%bx),%di # Address name in record
- push %si # Save
- repe cmpsb # Compare name
- je ff.match # We have a winner!
- pop %si # Restore
- jmp ff.nextrec # Keep looking.
-ff.match: add $2,%sp # Discard saved %si
- clc # Clear carry
- ret
-
-#
-# Load DH sectors starting at LBA EAX into [EBX].
-#
-# Trashes: EAX
-#
-read: push %es # Save
- push %bp
- push %dx
- push %cx
- push %ebx
- mov %bx,%bp # Set destination address
- and $0x000f,%bp
- shr $4,%ebx
- mov %bx,%es
- xor %bx,%bx # Set read bytes
- mov %dh,%bl
- shl $SECTOR_SHIFT,%bx # 2048 bytes/sec
- mov %ax,%cx # Set LBA
- shr $16,%eax
- mov %ax,%dx
-read.retry: mov $0x06,%ah # BIOS device read
- mov drive,%al
- and $0x7f,%al
- call twiddle # Entertain the user
- int $0x1b # Call BIOS
- jc read.fail # Worked?
- pop %ebx # Restore
- pop %cx
- pop %dx
- pop %bp
- pop %es
- ret # Return
-read.fail: cmp $ERROR_TIMEOUT,%ah # Timeout?
- je read.retry # Yes, Retry.
-read.error: mov %ah,%al # Save error
- mov $hex_error,%di # Format it
- call hex8 # as hex
- mov $msg_badread,%si # Display Read error message
- jmp error
-
-#
-# Output the "twiddle"
-#
-twiddle: push %ax # Save
- push %bx # Save
- mov twiddle_index,%al # Load index
- mov $twiddle_chars,%bx # Address table
- inc %al # Next
- and $3,%al # char
- mov %al,twiddle_index # Save index for next call
- xlat # Get char
- call putc # Output it
- pop %bx # Restore
- pop %ax # Restore
- ret
-
-#
-# Convert AL to hex, saving the result to [EDI].
-#
-hex8: pushl %eax # Save
- shrb $0x4,%al # Do upper
- call hex8.1 # 4
- popl %eax # Restore
-hex8.1: andb $0xf,%al # Get lower 4
- cmpb $0xa,%al # Convert
- sbbb $0x69,%al # to hex
- das # digit
- orb $0x20,%al # To lower case
- mov %al,(%di) # Save char
- inc %di
- ret # (Recursive)
-
-#
-# BTX client to start btxldr
-#
- .code32
-btx_client: mov $(MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE-4), %esi
- # %ds:(%esi) -> end
- # of boot[12] args
- mov $(MEM_ARG_SIZE/4),%ecx # Number of words to push
- std # Go backwards
-push_arg: lodsl # Read argument
- push %eax # Push it onto the stack
- loop push_arg # Push all of the arguments
- cld # In case anyone depends on this
- pushl MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE # Entry point of
- # the loader
- push %eax # Emulate a near call
- mov $0x1,%eax # 'exec' system call
- int $INT_SYS # BTX system call
-btx_client_end:
- .code16
-
- .p2align 4
-#
-# Global descriptor table.
-#
-gdt: .word 0x0,0x0,0x0,0x0 # Null entry
- .word 0xffff,0x0000,0x9200,0x00cf # SEL_SDATA
- .word 0xffff,0x0000,0x9200,0x0000 # SEL_RDATA
- .word 0xffff,LOAD_SEG<<4,0x9a00,0x00cf # SEL_SCODE (32-bit)
- .word 0xffff,LOAD_SEG<<4,0x9a00,0x008f # SEL_SCODE16 (16-bit)
-gdt.1:
-#
-# Pseudo-descriptors.
-#
-gdtdesc: .word gdt.1-gdt-1 # Limit
- .long LOAD_SEG<<4 + gdt # Base
-
-#
-# BOOT device
-#
-drive: .byte 0
-cylinder: .word 0
-
-#
-# State for searching dir
-#
-rec_lba: .long 0x0 # LBA (adjusted for EA)
-rec_size: .long 0x0 # File size
-name_len: .byte 0x0 # Length of current name
-
-cursor: .word 0
-twiddle_index: .byte 0x0
-
-msg_welcome: .asciz "CD Loader 1.2\r\n\n"
-msg_bootinfo: .asciz "Building the boot loader arguments\r\n"
-msg_relocate: .asciz "Relocating the loader and the BTX\r\n"
-msg_jump: .asciz "Starting the BTX loader\r\n"
-msg_badread: .ascii "Read Error: 0x"
-hex_error: .asciz "00\r\n"
-msg_novd: .asciz "Could not find Primary Volume Descriptor\r\n"
-msg_lookup: .asciz "Looking up "
-msg_lookup2: .asciz "... "
-msg_lookupok: .asciz "Found\r\n"
-msg_lookupfail: .asciz "File not found\r\n"
-msg_load2big: .asciz "File too big\r\n"
-msg_failed: .asciz "Boot failed\r\n"
-twiddle_chars: .ascii "|/-\\"
-loader_paths: .asciz "/BOOT.PC98/LOADER"
- .asciz "/boot.pc98/loader"
- .asciz "/BOOT/LOADER"
- .asciz "/boot/loader"
- .byte 0
-
-/* Boot signature */
-
- .org SIG2_OFF,0x90
-
- .word 0xaa55 # Magic number
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/libpc98/Makefile
--- a/head/sys/boot/pc98/libpc98/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/pc98/libpc98/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/boot/pc98/libpc98/Makefile 235395 2012-05-13 11:34:05Z avg $
#
LIB= pc98
INTERNALLIB=
@@ -10,6 +10,8 @@
comconsole.c devicename.c elf32_freebsd.c \
i386_copy.c i386_module.c nullconsole.c pc98_sys.c pxe.c pxetramp.s \
time.c vidconsole.c
+.PATH: ${.CURDIR}/../../zfs
+SRCS+= devicename_stubs.c
# Enable PXE TFTP or NFS support, not both.
.if defined(LOADER_TFTP_SUPPORT)
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/libpc98/biosdisk.c
--- a/head/sys/boot/pc98/libpc98/biosdisk.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/pc98/libpc98/biosdisk.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/pc98/libpc98/biosdisk.c 235155 2012-05-09 08:05:50Z avg $");
/*
* BIOS disk device handling.
@@ -52,7 +52,6 @@
#define BIOS_NUMDRIVES 0x475
#define BIOSDISK_SECSIZE 512
#define BUFSIZE (1 * BIOSDISK_SECSIZE)
-#define MAXBDDEV MAXDEV
#define DT_ATAPI 0x10 /* disk type for ATAPI floppies */
#define WDMAJOR 0 /* major numbers for devices we frontend for */
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/pc98/loader/main.c
--- a/head/sys/boot/pc98/loader/main.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/pc98/loader/main.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/pc98/loader/main.c 226746 2011-10-25 19:45:12Z jhb $");
+__FBSDID("$FreeBSD: head/sys/boot/pc98/loader/main.c 235264 2012-05-11 09:46:17Z avg $");
/*
* MD bootstrap main() and assorted miscellaneous
@@ -33,29 +33,25 @@
*/
#include <stand.h>
+#include <stddef.h>
#include <string.h>
#include <machine/bootinfo.h>
#include <sys/param.h>
#include <sys/reboot.h>
#include "bootstrap.h"
+#include "common/bootargs.h"
#include "libi386/libi386.h"
#include "libpc98/libpc98.h"
#include "btxv86.h"
-#define KARGS_FLAGS_CD 0x1
-#define KARGS_FLAGS_PXE 0x2
+CTASSERT(sizeof(struct bootargs) == BOOTARGS_SIZE);
+CTASSERT(offsetof(struct bootargs, bootinfo) == BA_BOOTINFO);
+CTASSERT(offsetof(struct bootargs, bootflags) == BA_BOOTFLAGS);
+CTASSERT(offsetof(struct bootinfo, bi_size) == BI_SIZE);
/* Arguments passed in from the boot1/boot2 loader */
-static struct
-{
- u_int32_t howto;
- u_int32_t bootdev;
- u_int32_t bootflags;
- u_int32_t pxeinfo;
- u_int32_t res2;
- u_int32_t bootinfo;
-} *kargs;
+static struct bootargs *kargs;
static u_int32_t initial_howto;
static u_int32_t initial_bootdev;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/powerpc/boot1.chrp/boot1.c
--- a/head/sys/boot/powerpc/boot1.chrp/boot1.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/powerpc/boot1.chrp/boot1.c Wed Jul 25 16:45:04 2012 +0300
@@ -16,7 +16,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/powerpc/boot1.chrp/boot1.c 231810 2012-02-16 03:27:38Z nwhitehorn $");
+__FBSDID("$FreeBSD: head/sys/boot/powerpc/boot1.chrp/boot1.c 235988 2012-05-25 09:36:39Z gleb $");
#include <sys/param.h>
#include <sys/dirent.h>
@@ -45,7 +45,6 @@
static ofwh_t bootdev;
static struct fs fs;
-static ino_t inomap;
static char blkbuf[BSIZEMAX];
static unsigned int fsblks;
@@ -492,7 +491,7 @@
Elf32_Ehdr eh;
Elf32_Phdr ph;
caddr_t p;
- ino_t ino;
+ ufs_ino_t ino;
int i;
if ((ino = lookup(fname)) == 0) {
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/sparc64/Makefile
--- a/head/sys/boot/sparc64/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/sparc64/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,5 +1,5 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/boot/sparc64/Makefile 234898 2012-05-01 17:16:01Z marius $
-SUBDIR= boot1 loader
+SUBDIR= boot1 loader zfsboot zfsloader
.include <bsd.subdir.mk>
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/sparc64/boot1/Makefile
--- a/head/sys/boot/sparc64/boot1/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/sparc64/boot1/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,24 +1,25 @@
-# $FreeBSD$
+# $FreeBSD: head/sys/boot/sparc64/boot1/Makefile 235207 2012-05-09 19:08:54Z marius $
PROG= boot1.elf
INTERNALPROG=
NO_MAN=
-FILES= boot1
+FILES?= boot1
SRCS= _start.s boot1.c
+CLEANFILES=${FILES} boot1.aout
BOOTBLOCKBASE= 0x4000
-CFLAGS= -mcmodel=medlow -Os -I${.CURDIR}/../../common
+CFLAGS+=-mcmodel=medlow -Os -I${.CURDIR}/../../common
LDFLAGS=-Ttext ${BOOTBLOCKBASE} -Wl,-N
# Construct boot1. sunlabel expects it to contain zeroed-out space for the
# label, and to be of the correct size.
-boot1: boot1.aout
+${FILES}: boot1.aout
+ @set -- `ls -l boot1.aout`; x=$$((7680-$$5)); \
+ echo "$$x bytes available"; test $$x -ge 0
dd if=/dev/zero of=${.TARGET} bs=512 count=16
dd if=boot1.aout of=${.TARGET} bs=512 oseek=1 conv=notrunc
-CLEANFILES= boot1.aout
-
boot1.aout: boot1.elf
elf2aout -o ${.TARGET} ${.ALLSRC}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/sparc64/boot1/boot1.c
--- a/head/sys/boot/sparc64/boot1/boot1.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/sparc64/boot1/boot1.c Wed Jul 25 16:45:04 2012 +0300
@@ -16,15 +16,17 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/sparc64/boot1/boot1.c 235988 2012-05-25 09:36:39Z gleb $");
#include <sys/param.h>
#include <sys/dirent.h>
+
#include <machine/elf.h>
#include <machine/stdarg.h>
-#define _PATH_LOADER "/boot/loader"
-#define _PATH_KERNEL "/boot/kernel/kernel"
+#define _PATH_LOADER "/boot/loader"
+#define _PATH_KERNEL "/boot/kernel/kernel"
+#define READ_BUF_SIZE 8192
typedef int putc_func_t(char c, void *arg);
typedef int32_t ofwh_t;
@@ -45,17 +47,21 @@
static uint32_t fs_off;
int main(int ac, char **av);
+static void exit(int) __dead2;
+static void usage(void);
-static void exit(int) __dead2;
+#ifdef ZFSBOOT
+static void loadzfs(void);
+static int zbread(char *buf, off_t off, size_t bytes);
+#else
static void load(const char *);
-static int dskread(void *, u_int64_t, int);
-
-static void usage(void);
+#endif
static void bcopy(const void *src, void *dst, size_t len);
static void bzero(void *b, size_t len);
static int mount(const char *device);
+static int dskread(void *buf, u_int64_t lba, int nblk);
static void panic(const char *fmt, ...) __dead2;
static int printf(const char *fmt, ...);
@@ -312,8 +318,6 @@
return ((u_char)*s1 - (u_char)*s2);
}
-#include "ufsread.c"
-
int
main(int ac, char **av)
{
@@ -335,14 +339,22 @@
}
}
- printf(" \n>> FreeBSD/sparc64 boot block\n"
- " Boot path: %s\n"
- " Boot loader: %s\n", bootpath, path);
+#ifdef ZFSBOOT
+ printf(" \n>> FreeBSD/sparc64 ZFS boot block\n Boot path: %s\n",
+ bootpath);
+#else
+ printf(" \n>> FreeBSD/sparc64 boot block\n Boot path: %s\n"
+ " Boot loader: %s\n", "", bootpath, path);
+#endif
if (mount(bootpath) == -1)
panic("mount");
+#ifdef ZFSBOOT
+ loadzfs();
+#else
load(path);
+#endif
return (1);
}
@@ -361,31 +373,92 @@
ofw_exit();
}
-static struct dmadat __dmadat;
+#ifdef ZFSBOOT
+
+#define VDEV_BOOT_OFFSET (2 * 256 * 1024)
+static char zbuf[READ_BUF_SIZE];
static int
-mount(const char *device)
+zbread(char *buf, off_t off, size_t bytes)
{
+ size_t len;
+ off_t poff;
+ off_t soff;
+ char *p;
+ unsigned int nb;
+ unsigned int lb;
- dmadat = &__dmadat;
- if ((bootdev = ofw_open(device)) == -1) {
- printf("mount: can't open device\n");
- return (-1);
+ p = buf;
+ soff = VDEV_BOOT_OFFSET + off;
+ lb = (soff + bytes + DEV_BSIZE - 1) / DEV_BSIZE;
+ poff = soff;
+ while (poff < soff + bytes) {
+ nb = lb - poff / DEV_BSIZE;
+ if (nb > READ_BUF_SIZE / DEV_BSIZE)
+ nb = READ_BUF_SIZE / DEV_BSIZE;
+ if (dskread(zbuf, poff / DEV_BSIZE, nb))
+ break;
+ if ((poff / DEV_BSIZE + nb) * DEV_BSIZE > soff + bytes)
+ len = soff + bytes - poff;
+ else
+ len = (poff / DEV_BSIZE + nb) * DEV_BSIZE - poff;
+ memcpy(p, zbuf + poff % DEV_BSIZE, len);
+ p += len;
+ poff += len;
}
- if (fsread(0, NULL, 0)) {
- printf("mount: can't read superblock\n");
- return (-1);
+ return (poff - soff);
+}
+
+static void
+loadzfs(void)
+{
+ Elf64_Ehdr eh;
+ Elf64_Phdr ph;
+ caddr_t p;
+ int i;
+
+ if (zbread((char *)&eh, 0, sizeof(eh)) != sizeof(eh)) {
+ printf("Can't read elf header\n");
+ return;
}
- return (0);
+ if (!IS_ELF(eh)) {
+ printf("Not an ELF file\n");
+ return;
+ }
+ for (i = 0; i < eh.e_phnum; i++) {
+ fs_off = eh.e_phoff + i * eh.e_phentsize;
+ if (zbread((char *)&ph, fs_off, sizeof(ph)) != sizeof(ph)) {
+ printf("Can't read program header %d\n", i);
+ return;
+ }
+ if (ph.p_type != PT_LOAD)
+ continue;
+ fs_off = ph.p_offset;
+ p = (caddr_t)ph.p_vaddr;
+ if (zbread(p, fs_off, ph.p_filesz) != ph.p_filesz) {
+ printf("Can't read content of section %d\n", i);
+ return;
+ }
+ if (ph.p_filesz != ph.p_memsz)
+ bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz);
+ }
+ ofw_close(bootdev);
+ (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw);
}
+#else
+
+#include "ufsread.c"
+
+static struct dmadat __dmadat;
+
static void
load(const char *fname)
{
Elf64_Ehdr eh;
Elf64_Phdr ph;
caddr_t p;
- ino_t ino;
+ ufs_ino_t ino;
int i;
if ((ino = lookup(fname)) == 0) {
@@ -421,6 +494,26 @@
(*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw);
}
+#endif /* ZFSBOOT */
+
+static int
+mount(const char *device)
+{
+
+ if ((bootdev = ofw_open(device)) == -1) {
+ printf("mount: can't open device\n");
+ return (-1);
+ }
+#ifndef ZFSBOOT
+ dmadat = &__dmadat;
+ if (fsread(0, NULL, 0)) {
+ printf("mount: can't read superblock\n");
+ return (-1);
+ }
+#endif
+ return (0);
+}
+
static int
dskread(void *buf, u_int64_t lba, int nblk)
{
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/sparc64/loader/Makefile
--- a/head/sys/boot/sparc64/loader/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/sparc64/loader/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,10 +1,10 @@
-# $FreeBSD: head/sys/boot/sparc64/loader/Makefile 222472 2011-05-30 04:23:33Z julian $
+# $FreeBSD: head/sys/boot/sparc64/loader/Makefile 235364 2012-05-12 20:27:33Z avg $
.include <bsd.own.mk>
MK_SSP= no
-PROG= loader
-NEWVERSWHAT= "bootstrap loader" sparc64
+PROG?= loader
+NEWVERSWHAT?= "bootstrap loader" sparc64
INSTALLFLAGS= -b
# Architecture-specific loader code
@@ -13,12 +13,17 @@
LOADER_DISK_SUPPORT?= yes
LOADER_UFS_SUPPORT?= yes
LOADER_CD9660_SUPPORT?= yes
+LOADER_ZFS_SUPPORT?= no
LOADER_NET_SUPPORT?= yes
LOADER_NFS_SUPPORT?= yes
LOADER_TFTP_SUPPORT?= yes
LOADER_GZIP_SUPPORT?= yes
LOADER_BZIP2_SUPPORT?= no
+LOADER_DEBUG?= no
+.if ${LOADER_DEBUG} == "yes"
+CFLAGS+= -DLOADER_DEBUG
+.endif
.if ${LOADER_DISK_SUPPORT} == "yes"
CFLAGS+= -DLOADER_DISK_SUPPORT
.endif
@@ -28,6 +33,12 @@
.if ${LOADER_CD9660_SUPPORT} == "yes"
CFLAGS+= -DLOADER_CD9660_SUPPORT
.endif
+.if ${LOADER_ZFS_SUPPORT} == "yes"
+CFLAGS+= -DLOADER_ZFS_SUPPORT
+CFLAGS+= -I${.CURDIR}/../../zfs
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs
+LIBZFSBOOT= ${.OBJDIR}/../../zfs/libzfsboot.a
+.endif
.if ${LOADER_GZIP_SUPPORT} == "yes"
CFLAGS+= -DLOADER_GZIP_SUPPORT
.endif
@@ -47,7 +58,8 @@
.if ${MK_FORTH} != "no"
# Enable BootForth
BOOT_FORTH= yes
-CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/sparc64
+CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl
+CFLAGS+= -I${.CURDIR}/../../ficl/sparc64
LIBFICL= ${.OBJDIR}/../../ficl/libficl.a
.endif
@@ -72,11 +84,12 @@
# where to get libstand from
CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
-DPADD= ${LIBFICL} ${LIBOFW} ${LIBSTAND}
-LDADD= ${LIBFICL} ${LIBOFW} -lstand
+DPADD= ${LIBFICL} ${LIBZFSBOOT} ${LIBOFW} ${LIBSTAND}
+LDADD= ${LIBFICL} ${LIBZFSBOOT} ${LIBOFW} -lstand
-vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
- sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
+vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version
+ sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version \
+ ${NEWVERSWHAT}
loader.help: help.common help.sparc64
cat ${.ALLSRC} | \
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/sparc64/loader/main.c
--- a/head/sys/boot/sparc64/loader/main.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/sparc64/loader/main.c Wed Jul 25 16:45:04 2012 +0300
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/sparc64/loader/main.c 223719 2011-07-02 11:14:54Z marius $");
+__FBSDID("$FreeBSD: head/sys/boot/sparc64/loader/main.c 236581 2012-06-04 20:56:40Z marius $");
/*
* FreeBSD/sparc64 kernel loader - machine dependent part
@@ -51,6 +51,10 @@
#include <sys/linker.h>
#include <sys/queue.h>
#include <sys/types.h>
+#ifdef LOADER_ZFS_SUPPORT
+#include <sys/vtoc.h>
+#include "../zfs/libzfs.h"
+#endif
#include <vm/vm.h>
#include <machine/asi.h>
@@ -71,11 +75,7 @@
#include "libofw.h"
#include "dev_net.h"
-#ifndef CTASSERT
-#define CTASSERT(x) _CTASSERT(x, __LINE__)
-#define _CTASSERT(x, y) __CTASSERT(x, y)
-#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1]
-#endif
+#define MAXDEV 31
extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
@@ -141,6 +141,7 @@
static vm_offset_t curkva = 0;
static vm_offset_t heapva;
+static char bootpath[64];
static phandle_t root;
/*
@@ -154,6 +155,9 @@
#ifdef LOADER_NET_SUPPORT
&netdev,
#endif
+#ifdef LOADER_ZFS_SUPPORT
+ &zfs_dev,
+#endif
0
};
struct arch_switch archsw;
@@ -166,6 +170,7 @@
&sparc64_elf,
0
};
+
struct fs_ops *file_system[] = {
#ifdef LOADER_UFS_SUPPORT
&ufs_fsops,
@@ -173,6 +178,9 @@
#ifdef LOADER_CD9660_SUPPORT
&cd9660_fsops,
#endif
+#ifdef LOADER_ZFS_SUPPORT
+ &zfs_fsops,
+#endif
#ifdef LOADER_ZIP_SUPPORT
&zipfs_fsops,
#endif
@@ -721,10 +729,58 @@
panic("%s: can't allocate TLB store", __func__);
}
+#ifdef LOADER_ZFS_SUPPORT
+static void
+sparc64_zfs_probe(void)
+{
+ struct vtoc8 vtoc;
+ struct zfs_devdesc zfs_currdev;
+ char devname[32];
+ uint64_t guid;
+ int fd, part, unit;
+
+ /* Get the GUID of the ZFS pool on the boot device. */
+ guid = 0;
+ zfs_probe_dev(bootpath, &guid);
+
+ for (unit = 0; unit < MAXDEV; unit++) {
+ /* Find freebsd-zfs slices in the VTOC. */
+ sprintf(devname, "disk%d:", unit);
+ fd = open(devname, O_RDONLY);
+ if (fd == -1)
+ continue;
+ lseek(fd, 0, SEEK_SET);
+ if (read(fd, &vtoc, sizeof(vtoc)) != sizeof(vtoc)) {
+ close(fd);
+ continue;
+ }
+ close(fd);
+
+ for (part = 0; part < 8; part++) {
+ if (part == 2 || vtoc.part[part].tag !=
+ VTOC_TAG_FREEBSD_ZFS)
+ continue;
+ sprintf(devname, "disk%d:%c", unit, part + 'a');
+ if (zfs_probe_dev(devname, NULL) == ENXIO)
+ break;
+ }
+ }
+
+ if (guid != 0) {
+ zfs_currdev.pool_guid = guid;
+ 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 */
+
int
main(int (*openfirm)(void *))
{
- char bootpath[64];
char compatible[32];
struct devsw **dp;
@@ -738,6 +794,9 @@
archsw.arch_copyout = ofw_copyout;
archsw.arch_readin = sparc64_readin;
archsw.arch_autoload = sparc64_autoload;
+#ifdef LOADER_ZFS_SUPPORT
+ archsw.arch_zfs_probe = sparc64_zfs_probe;
+#endif
if (init_heap() == (vm_offset_t)-1)
OF_exit();
@@ -756,14 +815,6 @@
mmu_ops->tlb_init();
/*
- * Initialize devices.
- */
- for (dp = devsw; *dp != 0; dp++) {
- if ((*dp)->dv_init != 0)
- (*dp)->dv_init();
- }
-
- /*
* Set up the current device.
*/
OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath));
@@ -780,11 +831,23 @@
* needs to be altered.
*/
if (bootpath[strlen(bootpath) - 2] == ':' &&
- bootpath[strlen(bootpath) - 1] == 'f') {
+ bootpath[strlen(bootpath) - 1] == 'f' &&
+ strstr(bootpath, "cdrom") != NULL) {
bootpath[strlen(bootpath) - 1] = 'a';
printf("Boot path set to %s\n", bootpath);
}
+ /*
+ * Initialize devices.
+ */
+ for (dp = devsw; *dp != 0; dp++)
+ if ((*dp)->dv_init != 0)
+ (*dp)->dv_init();
+
+ /*
+ * Now that sparc64_zfs_probe() might have altered bootpath,
+ * export it.
+ */
env_setenv("currdev", EV_VOLATILE, bootpath,
ofw_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, bootpath,
@@ -800,6 +863,18 @@
return (1);
}
+COMMAND_SET(heap, "heap", "show heap usage", command_heap);
+
+static int
+command_heap(int argc, char *argv[])
+{
+
+ mallocstats();
+ printf("heap base at %p, top at %p, upper limit at %p\n", heapva,
+ sbrk(0), heapva + HEAPSZ);
+ return(CMD_OK);
+}
+
COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
static int
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/sparc64/zfsboot/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/sparc64/zfsboot/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,9 @@
+# $FreeBSD: head/sys/boot/sparc64/zfsboot/Makefile 235207 2012-05-09 19:08:54Z marius $
+
+.PATH: ${.CURDIR}/../boot1
+
+PROGNAME= zfsboot
+CFLAGS+= -DZFSBOOT
+FILES= zfsboot
+
+.include "${.CURDIR}/../boot1/Makefile"
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/sparc64/zfsloader/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/sparc64/zfsloader/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,9 @@
+# $FreeBSD: head/sys/boot/sparc64/zfsloader/Makefile 234898 2012-05-01 17:16:01Z marius $
+
+.PATH: ${.CURDIR}/../loader
+
+PROG= zfsloader
+NEWVERSWHAT= "ZFS enabled bootstrap loader" sparc64
+LOADER_ZFS_SUPPORT=yes
+
+.include "${.CURDIR}/../loader/Makefile"
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/uboot/common/metadata.c
--- a/head/sys/boot/uboot/common/metadata.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/uboot/common/metadata.c Wed Jul 25 16:45:04 2012 +0300
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/uboot/common/metadata.c 233230 2012-03-20 13:08:57Z raj $");
+__FBSDID("$FreeBSD: head/sys/boot/uboot/common/metadata.c 235529 2012-05-17 04:04:48Z kientzle $");
#include <stand.h>
#include <sys/param.h>
@@ -42,7 +42,7 @@
#include "glue.h"
#if defined(LOADER_FDT_SUPPORT)
-extern int fdt_fixup(void);
+extern vm_offset_t fdt_fixup(void);
#endif
/*
@@ -72,6 +72,7 @@
md_getboothowto(char *kargs)
{
char *cp;
+ char *p;
int howto;
int active;
int i;
@@ -132,10 +133,12 @@
if (getenv(howto_names[i].ev) != NULL)
howto |= howto_names[i].mask;
}
- if (!strcmp(getenv("console"), "comconsole"))
- howto |= RB_SERIAL;
- if (!strcmp(getenv("console"), "nullconsole"))
- howto |= RB_MUTE;
+ if ((p = getenv("console"))) {
+ if (!strcmp(p, "comconsole"))
+ howto |= RB_SERIAL;
+ if (!strcmp(p, "nullconsole"))
+ howto |= RB_MUTE;
+ }
return(howto);
}
@@ -334,7 +337,7 @@
#if defined(LOADER_FDT_SUPPORT)
/* Handle device tree blob */
dtbp = fdt_fixup();
- if (dtbp != (vm_offset_t)NULL)
+ if (dtbp != 0)
file_addmetadata(kfp, MODINFOMD_DTBP, sizeof dtbp, &dtbp);
else
pager_output("WARNING! Trying to fire up the kernel, but no "
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/uboot/lib/api_public.h
--- a/head/sys/boot/uboot/lib/api_public.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/uboot/lib/api_public.h Wed Jul 25 16:45:04 2012 +0300
@@ -48,7 +48,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/uboot/lib/api_public.h 235609 2012-05-18 14:41:14Z gber $
*
* This file needs to be kept in sync with U-Boot reference:
* http://www.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=blob;f=include/api_public.h
@@ -132,6 +132,7 @@
#define DT_STOR_SCSI 0x0020
#define DT_STOR_USB 0x0040
#define DT_STOR_MMC 0x0080
+#define DT_STOR_NAND 0x0100
#define DEV_STA_CLOSED 0x0000 /* invalid, closed */
#define DEV_STA_OPEN 0x0001 /* open i.e. active */
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/uboot/lib/copy.c
--- a/head/sys/boot/uboot/lib/copy.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/uboot/lib/copy.c Wed Jul 25 16:45:04 2012 +0300
@@ -26,35 +26,67 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/uboot/lib/copy.c 235694 2012-05-20 18:07:35Z kientzle $");
#include <stand.h>
+#include <stdint.h>
+
+#include "api_public.h"
+#include "glue.h"
/*
* MD primitives supporting placement of module data
- *
- * XXX should check load address/size against memory top.
*/
+void *
+uboot_vm_translate(vm_offset_t o) {
+ struct sys_info *si;
+ static uintptr_t start = 0;
+ static size_t size = 0;
+ int i;
+
+ if (size == 0) {
+ if ((si = ub_get_sys_info()) == NULL)
+ panic("could not retrieve system info");
+
+ /* Find start/size of largest DRAM block. */
+ for (i = 0; i < si->mr_no; i++) {
+ if (si->mr[i].flags == MR_ATTR_DRAM
+ && si->mr[i].size > size) {
+ start = si->mr[i].start;
+ size = si->mr[i].size;
+ }
+ }
+
+ if (size <= 0)
+ panic("No suitable DRAM?\n");
+ /*
+ printf("Loading into memory region 0x%08X-0x%08X (%d MiB)\n",
+ start, start + size, size / 1024 / 1024);
+ */
+ }
+ if (o > size)
+ panic("Address 0x%08jX bigger than size 0x%08X\n",
+ (intmax_t)o, size);
+ return (void *)(start + o);
+}
+
ssize_t
uboot_copyin(const void *src, vm_offset_t dest, const size_t len)
{
-
- bcopy(src, (void *)dest, len);
+ bcopy(src, uboot_vm_translate(dest), len);
return (len);
}
ssize_t
uboot_copyout(const vm_offset_t src, void *dest, const size_t len)
{
-
- bcopy((void *)src, dest, len);
+ bcopy(uboot_vm_translate(src), dest, len);
return (len);
}
ssize_t
uboot_readin(const int fd, vm_offset_t dest, const size_t len)
{
-
- return (read(fd, (void *) dest, len));
+ return (read(fd, uboot_vm_translate(dest), len));
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/uboot/lib/devicename.c
--- a/head/sys/boot/uboot/lib/devicename.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/uboot/lib/devicename.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/uboot/lib/devicename.c 234860 2012-05-01 05:04:49Z kientzle $");
#include <sys/disklabel.h>
@@ -131,6 +131,10 @@
*(cp + 1) != ':') {
pnum = strtol(cp + 1, &cp, 10);
ptype = PTYPE_GPT;
+ } else if (*cp == 's' && *(cp + 1) &&
+ *(cp + 1) != ':') {
+ pnum = strtol(cp + 1, &cp, 10);
+ ptype = PTYPE_MBR;
} else {
pnum = *cp - 'a';
ptype = PTYPE_BSDLABEL;
@@ -218,6 +222,9 @@
else if (dev->d_kind.disk.ptype == PTYPE_GPT)
cp += sprintf(cp, "p%i",
dev->d_kind.disk.pnum);
+ else if (dev->d_kind.disk.ptype == PTYPE_MBR)
+ cp += sprintf(cp, "s%i",
+ dev->d_kind.disk.pnum);
}
strcat(cp, ":");
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/uboot/lib/disk.c
--- a/head/sys/boot/uboot/lib/disk.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/uboot/lib/disk.c Wed Jul 25 16:45:04 2012 +0300
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/uboot/lib/disk.c 234860 2012-05-01 05:04:49Z kientzle $");
#include <sys/param.h>
#include <sys/endian.h>
@@ -398,6 +398,94 @@
}
static int
+stor_open_mbr(struct open_dev *od, struct uboot_devdesc *dev)
+{
+ char *buf = NULL;
+ struct dos_partition *dp;
+ int err, i, part;
+
+ od->od_nparts = 0;
+ od->od_partitions = NULL;
+
+ /* Block size must be at least 512 bytes. */
+ if (od->od_bsize < 512)
+ return (ENXIO);
+
+ /* Read MBR */
+ buf = malloc(od->od_bsize);
+ if (!buf) {
+ stor_printf("could not allocate memory for MBR\n");
+ return (ENOMEM);
+ }
+ err = stor_readdev(dev, 0, 1, buf);
+ if (err) {
+ stor_printf("MBR read error=%d\n", err);
+ err = EIO;
+ goto out;
+ }
+
+ /* Check the slice table magic. */
+ if (le16toh(*((uint16_t *)(buf + DOSMAGICOFFSET))) != DOSMAGIC) {
+ err = ENXIO;
+ goto out;
+ }
+
+ /* Save information about partitions. */
+ dp = (struct dos_partition *)(buf + DOSPARTOFF);
+ od->od_partitions = calloc(NDOSPART, sizeof(struct gpt_part));
+ if (!od->od_partitions) {
+ stor_printf("could not allocate memory for MBR partitions\n");
+ err = ENOMEM;
+ goto out;
+ }
+
+ part = 0;
+ for (i = 0; i < NDOSPART; i++) {
+ u_int32_t start = le32dec(&dp[i].dp_start);
+ u_int32_t size = le32dec(&dp[i].dp_size);
+ uuid_t *u = NULL;
+
+ /* Map MBR partition types to GPT partition types. */
+ switch (dp[i].dp_typ) {
+ case DOSPTYP_386BSD:
+ u = &freebsd_ufs;
+ break;
+ /* XXX Other types XXX */
+ }
+
+ if (u) {
+ od->od_partitions[part].gp_type = *u;
+ od->od_partitions[part].gp_index = i + 1;
+ od->od_partitions[part].gp_start = start;
+ od->od_partitions[part].gp_end = start + size;
+ part += 1;
+ }
+ }
+ od->od_nparts = part;
+
+ if (od->od_nparts == 0) {
+ err = EINVAL;
+ goto out;
+ }
+
+ dev->d_disk.ptype = PTYPE_MBR;
+
+ /* XXX Be smarter here? XXX */
+ if (dev->d_disk.pnum == 0)
+ dev->d_disk.pnum = od->od_partitions[0].gp_index;
+
+ for (i = 0; i < od->od_nparts; i++)
+ if (od->od_partitions[i].gp_index == dev->d_disk.pnum)
+ od->od_bstart = od->od_partitions[i].gp_start;
+
+out:
+ if (err && od->od_partitions)
+ free(od->od_partitions);
+ free(buf);
+ return (err);
+}
+
+static int
stor_open_bsdlabel(struct open_dev *od, struct uboot_devdesc *dev)
{
char *buf;
@@ -443,7 +531,7 @@
lbasize_t real_size;
int err, handle;
- debugf("reading size=%d @ 0x%08x\n", size, (uint32_t)buf);
+ debugf("reading blk=%d size=%d @ 0x%08x\n", (int)blk, size, (uint32_t)buf);
handle = stor_info[dev->d_unit];
err = ub_dev_read(handle, buf, size, blk, &real_size);
@@ -495,7 +583,10 @@
od->od_bsize = di->di_stor.block_size;
od->od_bstart = 0;
- if ((err = stor_open_gpt(od, dev)) != 0)
+ err = stor_open_gpt(od, dev);
+ if (err != 0)
+ err = stor_open_mbr(od, dev);
+ if (err != 0)
err = stor_open_bsdlabel(od, dev);
if (err != 0)
@@ -517,6 +608,8 @@
od = (struct open_dev *)dev->d_disk.data;
if (dev->d_disk.ptype == PTYPE_GPT && od->od_nparts != 0)
free(od->od_partitions);
+ if (dev->d_disk.ptype == PTYPE_MBR && od->od_nparts != 0)
+ free(od->od_partitions);
free(od);
dev->d_disk.data = NULL;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/uboot/lib/elf_freebsd.c
--- a/head/sys/boot/uboot/lib/elf_freebsd.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/uboot/lib/elf_freebsd.c Wed Jul 25 16:45:04 2012 +0300
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/uboot/lib/elf_freebsd.c 235694 2012-05-20 18:07:35Z kientzle $");
#include <sys/param.h>
#include <sys/linker.h>
@@ -38,6 +38,7 @@
#include <stand.h>
#include "bootstrap.h"
+#include "libuboot.h"
extern vm_offset_t md_load(char *, vm_offset_t *);
@@ -69,6 +70,7 @@
vm_offset_t mdp;
Elf_Ehdr *e;
int error;
+ void (*entry)(void *);
if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
return (EFTYPE);
@@ -78,11 +80,12 @@
if ((error = md_load(fp->f_args, &mdp)) != 0)
return (error);
- printf("Kernel entry at 0x%x ...\n", e->e_entry);
+ entry = uboot_vm_translate(e->e_entry);
+ printf("Kernel entry at 0x%x...\n", (unsigned)entry);
dev_cleanup();
- (*(void (*)())e->e_entry)((void *)mdp);
+ (*entry)((void *)mdp);
panic("exec returned");
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/uboot/lib/glue.c
--- a/head/sys/boot/uboot/lib/glue.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/uboot/lib/glue.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/uboot/lib/glue.c 233287 2012-03-21 20:53:47Z marius $");
+__FBSDID("$FreeBSD: head/sys/boot/uboot/lib/glue.c 235609 2012-05-18 14:41:14Z gber $");
#include <sys/types.h>
@@ -407,6 +407,9 @@
if (type & DT_STOR_MMC)
return ("MMC");
+ if (type & DT_STOR_NAND)
+ return ("NAND");
+
return ("Unknown");
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/uboot/lib/libuboot.h
--- a/head/sys/boot/uboot/lib/libuboot.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/uboot/lib/libuboot.h Wed Jul 25 16:45:04 2012 +0300
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/uboot/lib/libuboot.h 235694 2012-05-20 18:07:35Z kientzle $
*/
struct uboot_devdesc
@@ -45,6 +45,7 @@
#define PTYPE_BSDLABEL 1
#define PTYPE_GPT 2
+#define PTYPE_MBR 3
/*
* Default network packet alignment in memory
@@ -59,6 +60,7 @@
extern struct netif_driver uboot_net;
extern struct devsw uboot_storage;
+void *uboot_vm_translate(vm_offset_t);
ssize_t uboot_copyin(const void *src, vm_offset_t dest, const size_t len);
ssize_t uboot_copyout(const vm_offset_t src, void *dest, const size_t len);
ssize_t uboot_readin(const int fd, vm_offset_t dest, const size_t len);
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/userboot/libstand/Makefile
--- a/head/sys/boot/userboot/libstand/Makefile Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/userboot/libstand/Makefile Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/boot/userboot/libstand/Makefile 229368 2012-01-03 07:14:01Z ed $
+# $FreeBSD: head/sys/boot/userboot/libstand/Makefile 237410 2012-06-21 21:47:08Z delphij $
# Originally from $NetBSD: Makefile,v 1.21 1997/10/26 22:08:38 lukem Exp $
#
# Notes:
@@ -42,7 +42,7 @@
.endif
# standalone components and stuff we have modified locally
-SRCS+= zutil.h __main.c assert.c bcd.c bswap.c environment.c getopt.c gets.c \
+SRCS+= gzguts.h zutil.h __main.c assert.c bcd.c bswap.c environment.c getopt.c gets.c \
globals.c pager.c printf.c strdup.c strerror.c strtol.c random.c \
sbrk.c twiddle.c zalloc.c zalloc_malloc.c
@@ -125,23 +125,28 @@
# decompression functionality from libz
.PATH: ${.CURDIR}/../../../../lib/libz
CFLAGS+=-DHAVE_MEMCPY -I${.CURDIR}/../../../../lib/libz
-SRCS+= adler32.c crc32.c libstand_zutil.h
+SRCS+= adler32.c crc32.c libstand_zutil.h libstand_gzguts.h
.for file in infback.c inffast.c inflate.c inftrees.c zutil.c
SRCS+= _${file}
CLEANFILES+= _${file}
_${file}: ${file}
- sed "s|zutil\.h|libstand_zutil.h|" ${.ALLSRC} > ${.TARGET}
+ sed -e "s|zutil\.h|libstand_zutil.h|" \
+ -e "s|gzguts\.h|libstand_gzguts.h|" ${.ALLSRC} > ${.TARGET}
.endfor
# depend on stand.h being able to be included multiple times
-CLEANFILES+= libstand_zutil.h
-libstand_zutil.h: zutil.h
- sed -e 's|<stddef.h>|"stand.h"|' \
+.for file in zutil.h gzguts.h
+CLEANFILES+= libstand_${file}
+libstand_${file}: ${file}
+ sed -e 's|<fcntl.h>|"stand.h"|' \
+ -e 's|<stddef.h>|"stand.h"|' \
-e 's|<string.h>|"stand.h"|' \
+ -e 's|<stdio.h>|"stand.h"|' \
-e 's|<stdlib.h>|"stand.h"|' \
${.ALLSRC} > ${.TARGET}
+.endfor
# io routines
SRCS+= closeall.c dev.c ioctl.c nullfs.c stat.c \
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/zfs/devicename_stubs.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/zfs/devicename_stubs.c Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2012 Andriy Gapon <avg at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/boot/zfs/devicename_stubs.c 235329 2012-05-12 09:03:30Z avg $");
+
+#include <stand.h>
+#include "libzfs.h"
+
+__attribute__((weak))
+int
+zfs_parsedev(struct zfs_devdesc *dev, const char *devspec, const char **path)
+{
+ return (EINVAL);
+}
+
+__attribute__((weak))
+char *
+zfs_fmtdev(void *vdev)
+{
+ static char buf[128];
+
+ return (buf);
+}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/zfs/libzfs.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/zfs/libzfs.h Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2012 Andriy Gapon <avg at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: head/sys/boot/zfs/libzfs.h 235329 2012-05-12 09:03:30Z avg $
+ */
+
+#ifndef _BOOT_LIBZFS_H_
+#define _BOOT_LIBZFS_H_
+
+#define ZFS_MAXNAMELEN 256
+
+/*
+ * ZFS fully-qualified device descriptor.
+ * Note, this must match the 'struct devdesc' declaration in bootstrap.h.
+ * Arch-specific device descriptors should be binary compatible with this
+ * structure if they are to support ZFS.
+ */
+struct zfs_devdesc
+{
+ struct devsw *d_dev;
+ int d_type;
+ int d_unit;
+ void *d_opendata;
+ uint64_t pool_guid;
+ uint64_t root_guid;
+};
+
+struct zfs_boot_args
+{
+ uint32_t size;
+ uint32_t reserved;
+ uint64_t pool;
+ uint64_t root;
+};
+
+int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec,
+ const char **path);
+char *zfs_fmtdev(void *vdev);
+int zfs_probe_dev(const char *devname, uint64_t *pool_guid);
+
+extern struct devsw zfs_dev;
+extern struct fs_ops zfs_fsops;
+
+#endif /*_BOOT_LIBZFS_H_*/
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/zfs/zfs.c
--- a/head/sys/boot/zfs/zfs.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/zfs/zfs.c Wed Jul 25 16:45:04 2012 +0300
@@ -23,11 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/boot/zfs/zfs.c 235394 2012-05-13 10:54:43Z avg $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/boot/zfs/zfs.c 235394 2012-05-13 10:54:43Z avg $");
/*
* Stand-alone file reading package.
@@ -43,10 +43,10 @@
#include <stand.h>
#include <bootstrap.h>
+#include "libzfs.h"
+
#include "zfsimpl.c"
-#define MAXBDDEV 31
-
static int zfs_open(const char *path, struct open_file *f);
static int zfs_write(struct open_file *f, void *buf, size_t size, size_t *resid);
static int zfs_close(struct open_file *f);
@@ -85,35 +85,20 @@
static int
zfs_open(const char *upath, struct open_file *f)
{
- spa_t *spa = (spa_t *) f->f_devdata;
+ struct zfsmount *mount = (struct zfsmount *)f->f_devdata;
struct file *fp;
int rc;
if (f->f_dev != &zfs_dev)
return (EINVAL);
- rc = zfs_mount_pool(spa);
- if (rc)
- return (rc);
-
/* allocate file system specific data structure */
fp = malloc(sizeof(struct file));
bzero(fp, sizeof(struct file));
f->f_fsdata = (void *)fp;
- if (spa->spa_root_objset.os_type != DMU_OST_ZFS) {
- printf("Unexpected object set type %llu\n",
- spa->spa_root_objset.os_type);
- rc = EIO;
- goto out;
- }
-
- rc = zfs_lookup(spa, upath, &fp->f_dnode);
- if (rc)
- goto out;
-
+ rc = zfs_lookup(mount, upath, &fp->f_dnode);
fp->f_seekp = 0;
-out:
if (rc) {
f->f_fsdata = NULL;
free(fp);
@@ -142,7 +127,7 @@
static int
zfs_read(struct open_file *f, void *start, size_t size, size_t *resid /* out */)
{
- spa_t *spa = (spa_t *) f->f_devdata;
+ const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
struct file *fp = (struct file *)f->f_fsdata;
struct stat sb;
size_t n;
@@ -216,7 +201,7 @@
static int
zfs_stat(struct open_file *f, struct stat *sb)
{
- spa_t *spa = (spa_t *) f->f_devdata;
+ const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
struct file *fp = (struct file *)f->f_fsdata;
return (zfs_dnode_stat(spa, &fp->f_dnode, sb));
@@ -225,7 +210,7 @@
static int
zfs_readdir(struct open_file *f, struct dirent *d)
{
- spa_t *spa = (spa_t *) f->f_devdata;
+ const spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
struct file *fp = (struct file *)f->f_fsdata;
mzap_ent_phys_t mze;
struct stat sb;
@@ -381,64 +366,31 @@
}
}
-/*
- * Convert a pool guid to a 'unit number' suitable for use with zfs_dev_open.
- */
+static int
+zfs_dev_init(void)
+{
+ zfs_init();
+ if (archsw.arch_zfs_probe == NULL)
+ return (ENXIO);
+ archsw.arch_zfs_probe();
+ return (0);
+}
+
int
-zfs_guid_to_unit(uint64_t guid)
+zfs_probe_dev(const char *devname, uint64_t *pool_guid)
{
spa_t *spa;
- int unit;
+ int fd;
+ int ret;
- unit = 0;
- STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
- if (spa->spa_guid == guid)
- return unit;
- unit++;
- }
- return (-1);
-}
-
-static int
-zfs_dev_init(void)
-{
- char devname[512];
- int unit, slice;
- int fd;
-
- /*
- * Open all the disks we can find and see if we can reconstruct
- * ZFS pools from them. Bogusly assumes that the disks are named
- * diskN, diskNpM or diskNsM.
- */
- zfs_init();
- for (unit = 0; unit < MAXBDDEV; unit++) {
- sprintf(devname, "disk%d:", unit);
- fd = open(devname, O_RDONLY);
- if (fd == -1)
- continue;
-
- /*
- * If we find a vdev, the zfs code will eat the fd, otherwise
- * we close it.
- */
- if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
- close(fd);
-
- for (slice = 1; slice <= 128; slice++) {
- sprintf(devname, "disk%dp%d:", unit, slice);
- fd = open(devname, O_RDONLY);
- if (fd == -1) {
- sprintf(devname, "disk%ds%d:", unit, slice);
- fd = open(devname, O_RDONLY);
- if (fd == -1)
- continue;
- }
- if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
- close(fd);
- }
- }
-
+ fd = open(devname, O_RDONLY);
+ if (fd == -1)
+ return (ENXIO);
+ ret = vdev_probe(vdev_read, (void *)(uintptr_t)fd, &spa);
+ if (ret != 0)
+ close(fd);
+ else if (pool_guid != NULL)
+ *pool_guid = spa->spa_guid;
return (0);
}
@@ -450,54 +402,52 @@
{
spa_t *spa;
char line[80];
- int unit;
if (verbose) {
spa_all_status();
return;
}
- unit = 0;
STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
- sprintf(line, " zfs%d: %s\n", unit, spa->spa_name);
+ sprintf(line, " zfs:%s\n", spa->spa_name);
pager_output(line);
- unit++;
}
}
/*
* Attempt to open the pool described by (dev) for use by (f).
*/
-static int
+static int
zfs_dev_open(struct open_file *f, ...)
{
va_list args;
- struct devdesc *dev;
- int unit, i;
+ struct zfs_devdesc *dev;
+ struct zfsmount *mount;
spa_t *spa;
+ int rv;
va_start(args, f);
- dev = va_arg(args, struct devdesc*);
+ dev = va_arg(args, struct zfs_devdesc *);
va_end(args);
- /*
- * We mostly ignore the stuff that devopen sends us. For now,
- * use the unit to find a pool - later we will override the
- * devname parsing so that we can name a pool and a fs within
- * the pool.
- */
- unit = dev->d_unit;
-
- i = 0;
- STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
- if (i == unit)
- break;
- i++;
+ spa = spa_find_by_guid(dev->pool_guid);
+ if (!spa)
+ return (ENXIO);
+ rv = zfs_spa_init(spa);
+ if (rv != 0)
+ return (rv);
+ mount = malloc(sizeof(*mount));
+ rv = zfs_mount(spa, dev->root_guid, mount);
+ if (rv != 0) {
+ free(mount);
+ return (rv);
}
- if (!spa) {
- return (ENXIO);
+ if (mount->objset.os_type != DMU_OST_ZFS) {
+ printf("Unexpected object set type %ju\n",
+ (uintmax_t)mount->objset.os_type);
+ free(mount);
+ return (EIO);
}
-
- f->f_devdata = spa;
+ f->f_devdata = mount;
free(dev);
return (0);
}
@@ -506,6 +456,7 @@
zfs_dev_close(struct open_file *f)
{
+ free(f->f_devdata);
f->f_devdata = NULL;
return (0);
}
@@ -518,13 +469,102 @@
}
struct devsw zfs_dev = {
- .dv_name = "zfs",
- .dv_type = DEVT_ZFS,
+ .dv_name = "zfs",
+ .dv_type = DEVT_ZFS,
.dv_init = zfs_dev_init,
- .dv_strategy = zfs_dev_strategy,
- .dv_open = zfs_dev_open,
- .dv_close = zfs_dev_close,
+ .dv_strategy = zfs_dev_strategy,
+ .dv_open = zfs_dev_open,
+ .dv_close = zfs_dev_close,
.dv_ioctl = noioctl,
.dv_print = zfs_dev_print,
.dv_cleanup = NULL
};
+
+int
+zfs_parsedev(struct zfs_devdesc *dev, const char *devspec, const char **path)
+{
+ static char rootname[ZFS_MAXNAMELEN];
+ static char poolname[ZFS_MAXNAMELEN];
+ spa_t *spa;
+ const char *end;
+ const char *np;
+ const char *sep;
+ int rv;
+
+ np = devspec;
+ if (*np != ':')
+ return (EINVAL);
+ np++;
+ end = strchr(np, ':');
+ if (end == NULL)
+ return (EINVAL);
+ sep = strchr(np, '/');
+ if (sep == NULL || sep >= end)
+ sep = end;
+ memcpy(poolname, np, sep - np);
+ poolname[sep - np] = '\0';
+ if (sep < end) {
+ sep++;
+ memcpy(rootname, sep, end - sep);
+ rootname[end - sep] = '\0';
+ }
+ else
+ rootname[0] = '\0';
+
+ spa = spa_find_by_name(poolname);
+ if (!spa)
+ return (ENXIO);
+ rv = zfs_spa_init(spa);
+ if (rv != 0)
+ return (rv);
+ dev->pool_guid = spa->spa_guid;
+ if (rootname[0] != '\0') {
+ rv = zfs_lookup_dataset(spa, rootname, &dev->root_guid);
+ if (rv != 0)
+ return (rv);
+ } else
+ dev->root_guid = 0;
+ if (path != NULL)
+ *path = (*end == '\0') ? end : end + 1;
+ dev->d_dev = &zfs_dev;
+ dev->d_type = zfs_dev.dv_type;
+ return (0);
+}
+
+char *
+zfs_fmtdev(void *vdev)
+{
+ static char rootname[ZFS_MAXNAMELEN];
+ static char buf[2 * ZFS_MAXNAMELEN + 8];
+ struct zfs_devdesc *dev = (struct zfs_devdesc *)vdev;
+ spa_t *spa;
+
+ buf[0] = '\0';
+ if (dev->d_type != DEVT_ZFS)
+ return (buf);
+
+ spa = spa_find_by_guid(dev->pool_guid);
+ if (spa == NULL) {
+ printf("ZFS: can't find pool by guid\n");
+ return (buf);
+ }
+ if (zfs_spa_init(spa) != 0) {
+ printf("ZFS: can't init pool\n");
+ return (buf);
+ }
+ if (dev->root_guid == 0 && zfs_get_root(spa, &dev->root_guid)) {
+ printf("ZFS: can't find root filesystem\n");
+ return (buf);
+ }
+ if (zfs_rlookup(spa, dev->root_guid, rootname)) {
+ printf("ZFS: can't find filesystem by guid\n");
+ return (buf);
+ }
+
+ if (rootname[0] == '\0')
+ sprintf(buf, "%s:%s:", dev->d_dev->dv_name, spa->spa_name);
+ else
+ sprintf(buf, "%s:%s/%s:", dev->d_dev->dv_name, spa->spa_name,
+ rootname);
+ return (buf);
+}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/boot/zfs/zfsimpl.c
--- a/head/sys/boot/zfs/zfsimpl.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/boot/zfs/zfsimpl.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,22 +25,37 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/zfs/zfsimpl.c 228266 2011-12-04 21:29:56Z avg $");
+__FBSDID("$FreeBSD: head/sys/boot/zfs/zfsimpl.c 237001 2012-06-13 08:00:32Z mm $");
/*
* Stand-alone ZFS file reader.
*/
#include <sys/stat.h>
+#include <sys/stdint.h>
#include "zfsimpl.h"
#include "zfssubr.c"
+
+struct zfsmount {
+ const spa_t *spa;
+ objset_phys_t objset;
+ uint64_t rootobj;
+};
+
/*
* List of all vdevs, chained through v_alllink.
*/
static vdev_list_t zfs_vdevs;
+ /*
+ * List of ZFS features supported for read
+ */
+static const char *features_for_read[] = {
+ NULL
+};
+
/*
* List of all pools, chained through spa_link.
*/
@@ -55,7 +70,7 @@
#define TEMP_SIZE (1024 * 1024)
-static int zio_read(spa_t *spa, const blkptr_t *bp, void *buf);
+static int zio_read(const spa_t *spa, const blkptr_t *bp, void *buf);
static void
zfs_init(void)
@@ -190,6 +205,57 @@
return (EIO);
}
+static int
+nvlist_check_features_for_read(const unsigned char *nvlist)
+{
+ const unsigned char *p, *pair;
+ int junk;
+ int encoded_size, decoded_size;
+ int rc;
+
+ rc = 0;
+
+ p = nvlist;
+ xdr_int(&p, &junk);
+ xdr_int(&p, &junk);
+
+ pair = p;
+ xdr_int(&p, &encoded_size);
+ xdr_int(&p, &decoded_size);
+ while (encoded_size && decoded_size) {
+ int namelen, pairtype;
+ const char *pairname;
+ int i, found;
+
+ found = 0;
+
+ xdr_int(&p, &namelen);
+ pairname = (const char*) p;
+ p += roundup(namelen, 4);
+ xdr_int(&p, &pairtype);
+
+ for (i = 0; features_for_read[i] != NULL; i++) {
+ if (!memcmp(pairname, features_for_read[i], namelen)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ printf("ZFS: unsupported feature: %s\n", pairname);
+ rc = EIO;
+ }
+
+ p = pair + encoded_size;
+
+ pair = p;
+ xdr_int(&p, &encoded_size);
+ xdr_int(&p, &decoded_size);
+ }
+
+ return (rc);
+}
+
/*
* Return the next nvlist in an nvlist array.
*/
@@ -283,7 +349,7 @@
case DATA_TYPE_UINT64: {
uint64_t val;
xdr_uint64_t(&p, &val);
- printf(" = 0x%llx\n", val);
+ printf(" = 0x%jx\n", (uintmax_t)val);
break;
}
@@ -343,7 +409,7 @@
psize = size;
}
- /*printf("ZFS: reading %d bytes at 0x%llx to %p\n", psize, offset, buf);*/
+ /*printf("ZFS: reading %d bytes at 0x%jx to %p\n", psize, (uintmax_t)offset, buf);*/
rc = vdev->v_phys_read(vdev, vdev->v_read_priv, offset, buf, psize);
if (rc)
return (rc);
@@ -626,8 +692,6 @@
return (0);
}
-#ifdef BOOT2
-
static spa_t *
spa_find_by_name(const char *name)
{
@@ -640,8 +704,6 @@
return (0);
}
-#endif
-
static spa_t *
spa_create(uint64_t guid)
{
@@ -784,6 +846,7 @@
uint64_t is_log;
const char *pool_name;
const unsigned char *vdevs;
+ const unsigned char *features;
int i, rc, is_newer;
char *upbuf;
const struct uberblock *up;
@@ -818,12 +881,19 @@
return (EIO);
}
- if (val > SPA_VERSION) {
+ if (!SPA_VERSION_IS_SUPPORTED(val)) {
printf("ZFS: unsupported ZFS version %u (should be %u)\n",
(unsigned) val, (unsigned) SPA_VERSION);
return (EIO);
}
+ /* Check ZFS features for read */
+ if (nvlist_find(nvlist,
+ ZPOOL_CONFIG_FEATURES_FOR_READ,
+ DATA_TYPE_NVLIST, 0, &features) == 0
+ && nvlist_check_features_for_read(features) != 0)
+ return (EIO);
+
if (nvlist_find(nvlist,
ZPOOL_CONFIG_POOL_STATE,
DATA_TYPE_UINT64, 0, &val)) {
@@ -977,7 +1047,7 @@
}
static int
-zio_read_gang(spa_t *spa, const blkptr_t *bp, void *buf)
+zio_read_gang(const spa_t *spa, const blkptr_t *bp, void *buf)
{
blkptr_t gbh_bp;
zio_gbh_phys_t zio_gb;
@@ -1014,7 +1084,7 @@
}
static int
-zio_read(spa_t *spa, const blkptr_t *bp, void *buf)
+zio_read(const spa_t *spa, const blkptr_t *bp, void *buf)
{
int cpfunc = BP_GET_COMPRESS(bp);
uint64_t align, size;
@@ -1074,7 +1144,7 @@
}
static int
-dnode_read(spa_t *spa, const dnode_phys_t *dnode, off_t offset, void *buf, size_t buflen)
+dnode_read(const spa_t *spa, const dnode_phys_t *dnode, off_t offset, void *buf, size_t buflen)
{
int ibshift = dnode->dn_indblkshift - SPA_BLKPTRSHIFT;
int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
@@ -1137,7 +1207,7 @@
* scratch buffer contains the directory contents.
*/
static int
-mzap_lookup(spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64_t *value)
+mzap_lookup(const dnode_phys_t *dnode, const char *name, uint64_t *value)
{
const mzap_phys_t *mz;
const mzap_ent_phys_t *mze;
@@ -1218,7 +1288,7 @@
* buffer contains the directory header.
*/
static int
-fzap_lookup(spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64_t *value)
+fzap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64_t *value)
{
int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
zap_phys_t zh = *(zap_phys_t *) zap_scratch;
@@ -1296,7 +1366,7 @@
* Lookup a name in a zap object and return its value as a uint64_t.
*/
static int
-zap_lookup(spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64_t *value)
+zap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64_t *value)
{
int rc;
uint64_t zap_type;
@@ -1308,7 +1378,7 @@
zap_type = *(uint64_t *) zap_scratch;
if (zap_type == ZBT_MICRO)
- return mzap_lookup(spa, dnode, name, value);
+ return mzap_lookup(dnode, name, value);
else if (zap_type == ZBT_HEADER)
return fzap_lookup(spa, dnode, name, value);
printf("ZFS: invalid zap_type=%d\n", (int)zap_type);
@@ -1322,7 +1392,7 @@
* the directory contents.
*/
static int
-mzap_list(spa_t *spa, const dnode_phys_t *dnode)
+mzap_list(const dnode_phys_t *dnode)
{
const mzap_phys_t *mz;
const mzap_ent_phys_t *mze;
@@ -1340,7 +1410,7 @@
for (i = 0; i < chunks; i++) {
mze = &mz->mz_chunk[i];
if (mze->mze_name[0])
- //printf("%-32s 0x%llx\n", mze->mze_name, mze->mze_value);
+ //printf("%-32s 0x%jx\n", mze->mze_name, (uintmax_t)mze->mze_value);
printf("%s\n", mze->mze_name);
}
@@ -1352,7 +1422,7 @@
* the directory header.
*/
static int
-fzap_list(spa_t *spa, const dnode_phys_t *dnode)
+fzap_list(const spa_t *spa, const dnode_phys_t *dnode)
{
int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
zap_phys_t zh = *(zap_phys_t *) zap_scratch;
@@ -1391,7 +1461,7 @@
namelen = zc->l_entry.le_name_length;
if (namelen > sizeof(name))
namelen = sizeof(name);
-
+
/*
* Paste the name back together.
*/
@@ -1414,7 +1484,7 @@
*/
value = fzap_leaf_value(&zl, zc);
- printf("%s 0x%llx\n", name, value);
+ printf("%s 0x%jx\n", name, (uintmax_t)value);
}
}
@@ -1425,7 +1495,7 @@
* List a zap directory.
*/
static int
-zap_list(spa_t *spa, const dnode_phys_t *dnode)
+zap_list(const spa_t *spa, const dnode_phys_t *dnode)
{
uint64_t zap_type;
size_t size = dnode->dn_datablkszsec * 512;
@@ -1435,7 +1505,7 @@
zap_type = *(uint64_t *) zap_scratch;
if (zap_type == ZBT_MICRO)
- return mzap_list(spa, dnode);
+ return mzap_list(dnode);
else
return fzap_list(spa, dnode);
}
@@ -1443,7 +1513,7 @@
#endif
static int
-objset_get_dnode(spa_t *spa, const objset_phys_t *os, uint64_t objnum, dnode_phys_t *dnode)
+objset_get_dnode(const spa_t *spa, const objset_phys_t *os, uint64_t objnum, dnode_phys_t *dnode)
{
off_t offset;
@@ -1452,24 +1522,278 @@
dnode, sizeof(dnode_phys_t));
}
+static int
+mzap_rlookup(const spa_t *spa, const dnode_phys_t *dnode, char *name, uint64_t value)
+{
+ const mzap_phys_t *mz;
+ const mzap_ent_phys_t *mze;
+ size_t size;
+ int chunks, i;
+
+ /*
+ * Microzap objects use exactly one block. Read the whole
+ * thing.
+ */
+ size = dnode->dn_datablkszsec * 512;
+
+ mz = (const mzap_phys_t *) zap_scratch;
+ chunks = size / MZAP_ENT_LEN - 1;
+
+ for (i = 0; i < chunks; i++) {
+ mze = &mz->mz_chunk[i];
+ if (value == mze->mze_value) {
+ strcpy(name, mze->mze_name);
+ return (0);
+ }
+ }
+
+ return (ENOENT);
+}
+
+static void
+fzap_name_copy(const zap_leaf_t *zl, const zap_leaf_chunk_t *zc, char *name)
+{
+ size_t namelen;
+ const zap_leaf_chunk_t *nc;
+ char *p;
+
+ namelen = zc->l_entry.le_name_length;
+
+ nc = &ZAP_LEAF_CHUNK(zl, zc->l_entry.le_name_chunk);
+ p = name;
+ while (namelen > 0) {
+ size_t len;
+ len = namelen;
+ if (len > ZAP_LEAF_ARRAY_BYTES)
+ len = ZAP_LEAF_ARRAY_BYTES;
+ memcpy(p, nc->l_array.la_array, len);
+ p += len;
+ namelen -= len;
+ nc = &ZAP_LEAF_CHUNK(zl, nc->l_array.la_next);
+ }
+
+ *p = '\0';
+}
+
+static int
+fzap_rlookup(const spa_t *spa, const dnode_phys_t *dnode, char *name, uint64_t value)
+{
+ int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
+ zap_phys_t zh = *(zap_phys_t *) zap_scratch;
+ fat_zap_t z;
+ uint64_t *ptrtbl;
+ uint64_t hash;
+ int rc;
+
+ if (zh.zap_magic != ZAP_MAGIC)
+ return (EIO);
+
+ z.zap_block_shift = ilog2(bsize);
+ z.zap_phys = (zap_phys_t *) zap_scratch;
+
+ /*
+ * Figure out where the pointer table is and read it in if necessary.
+ */
+ if (zh.zap_ptrtbl.zt_blk) {
+ rc = dnode_read(spa, dnode, zh.zap_ptrtbl.zt_blk * bsize,
+ zap_scratch, bsize);
+ if (rc)
+ return (rc);
+ ptrtbl = (uint64_t *) zap_scratch;
+ } else {
+ ptrtbl = &ZAP_EMBEDDED_PTRTBL_ENT(&z, 0);
+ }
+
+ hash = zap_hash(zh.zap_salt, name);
+
+ zap_leaf_t zl;
+ zl.l_bs = z.zap_block_shift;
+
+ off_t off = ptrtbl[hash >> (64 - zh.zap_ptrtbl.zt_shift)] << zl.l_bs;
+ zap_leaf_chunk_t *zc;
+
+ rc = dnode_read(spa, dnode, off, zap_scratch, bsize);
+ if (rc)
+ return (rc);
+
+ zl.l_phys = (zap_leaf_phys_t *) zap_scratch;
+
+ /*
+ * Make sure this chunk matches our hash.
+ */
+ if (zl.l_phys->l_hdr.lh_prefix_len > 0
+ && zl.l_phys->l_hdr.lh_prefix
+ != hash >> (64 - zl.l_phys->l_hdr.lh_prefix_len))
+ return (ENOENT);
+
+ /*
+ * Hash within the chunk to find our entry.
+ */
+ int shift = (64 - ZAP_LEAF_HASH_SHIFT(&zl) - zl.l_phys->l_hdr.lh_prefix_len);
+ int h = (hash >> shift) & ((1 << ZAP_LEAF_HASH_SHIFT(&zl)) - 1);
+ h = zl.l_phys->l_hash[h];
+ if (h == 0xffff)
+ return (ENOENT);
+ zc = &ZAP_LEAF_CHUNK(&zl, h);
+ while (zc->l_entry.le_hash != hash) {
+ if (zc->l_entry.le_next == 0xffff) {
+ zc = 0;
+ break;
+ }
+ zc = &ZAP_LEAF_CHUNK(&zl, zc->l_entry.le_next);
+ }
+ if (fzap_leaf_value(&zl, zc) == value) {
+ fzap_name_copy(&zl, zc, name);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static int
+zap_rlookup(const spa_t *spa, const dnode_phys_t *dnode, char *name, uint64_t value)
+{
+ int rc;
+ uint64_t zap_type;
+ size_t size = dnode->dn_datablkszsec * 512;
+
+ rc = dnode_read(spa, dnode, 0, zap_scratch, size);
+ if (rc)
+ return (rc);
+
+ zap_type = *(uint64_t *) zap_scratch;
+ if (zap_type == ZBT_MICRO)
+ return mzap_rlookup(spa, dnode, name, value);
+ else
+ return fzap_rlookup(spa, dnode, name, value);
+}
+
+static int
+zfs_rlookup(const spa_t *spa, uint64_t objnum, char *result)
+{
+ char name[256];
+ char component[256];
+ uint64_t dir_obj, parent_obj, child_dir_zapobj;
+ dnode_phys_t child_dir_zap, dataset, dir, parent;
+ dsl_dir_phys_t *dd;
+ dsl_dataset_phys_t *ds;
+ char *p;
+ int len;
+
+ p = &name[sizeof(name) - 1];
+ *p = '\0';
+
+ if (objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset)) {
+ printf("ZFS: can't find dataset %ju\n", (uintmax_t)objnum);
+ return (EIO);
+ }
+ ds = (dsl_dataset_phys_t *)&dataset.dn_bonus;
+ dir_obj = ds->ds_dir_obj;
+
+ for (;;) {
+ if (objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir) != 0)
+ return (EIO);
+ dd = (dsl_dir_phys_t *)&dir.dn_bonus;
+
+ /* Actual loop condition. */
+ parent_obj = dd->dd_parent_obj;
+ if (parent_obj == 0)
+ break;
+
+ if (objset_get_dnode(spa, &spa->spa_mos, parent_obj, &parent) != 0)
+ return (EIO);
+ dd = (dsl_dir_phys_t *)&parent.dn_bonus;
+ child_dir_zapobj = dd->dd_child_dir_zapobj;
+ if (objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj, &child_dir_zap) != 0)
+ return (EIO);
+ if (zap_rlookup(spa, &child_dir_zap, component, dir_obj) != 0)
+ return (EIO);
+
+ len = strlen(component);
+ p -= len;
+ memcpy(p, component, len);
+ --p;
+ *p = '/';
+
+ /* Actual loop iteration. */
+ dir_obj = parent_obj;
+ }
+
+ if (*p != '\0')
+ ++p;
+ strcpy(result, p);
+
+ return (0);
+}
+
+static int
+zfs_lookup_dataset(const spa_t *spa, const char *name, uint64_t *objnum)
+{
+ char element[256];
+ uint64_t dir_obj, child_dir_zapobj;
+ dnode_phys_t child_dir_zap, dir;
+ dsl_dir_phys_t *dd;
+ const char *p, *q;
+
+ if (objset_get_dnode(spa, &spa->spa_mos, DMU_POOL_DIRECTORY_OBJECT, &dir))
+ return (EIO);
+ if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET, &dir_obj))
+ return (EIO);
+
+ p = name;
+ for (;;) {
+ if (objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir))
+ return (EIO);
+ dd = (dsl_dir_phys_t *)&dir.dn_bonus;
+
+ while (*p == '/')
+ p++;
+ /* Actual loop condition #1. */
+ if (*p == '\0')
+ break;
+
+ q = strchr(p, '/');
+ if (q) {
+ memcpy(element, p, q - p);
+ element[q - p] = '\0';
+ p = q + 1;
+ } else {
+ strcpy(element, p);
+ p += strlen(p);
+ }
+
+ child_dir_zapobj = dd->dd_child_dir_zapobj;
+ if (objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj, &child_dir_zap) != 0)
+ return (EIO);
+
+ /* Actual loop condition #2. */
+ if (zap_lookup(spa, &child_dir_zap, element, &dir_obj) != 0)
+ return (ENOENT);
+ }
+
+ *objnum = dd->dd_head_dataset_obj;
+ return (0);
+}
+
/*
* Find the object set given the object number of its dataset object
* and return its details in *objset
*/
static int
-zfs_mount_dataset(spa_t *spa, uint64_t objnum, objset_phys_t *objset)
+zfs_mount_dataset(const spa_t *spa, uint64_t objnum, objset_phys_t *objset)
{
dnode_phys_t dataset;
dsl_dataset_phys_t *ds;
if (objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset)) {
- printf("ZFS: can't find dataset %llu\n", objnum);
+ printf("ZFS: can't find dataset %ju\n", (uintmax_t)objnum);
return (EIO);
}
ds = (dsl_dataset_phys_t *) &dataset.dn_bonus;
if (zio_read(spa, &ds->ds_bp, objset)) {
- printf("ZFS: can't read object set for dataset %llu\n", objnum);
+ printf("ZFS: can't read object set for dataset %ju\n",
+ (uintmax_t)objnum);
return (EIO);
}
@@ -1481,11 +1805,13 @@
* dataset if there is none and return its details in *objset
*/
static int
-zfs_mount_root(spa_t *spa, objset_phys_t *objset)
+zfs_get_root(const spa_t *spa, uint64_t *objid)
{
dnode_phys_t dir, propdir;
uint64_t props, bootfs, root;
+ *objid = 0;
+
/*
* Start with the MOS directory object.
*/
@@ -1501,8 +1827,10 @@
&& objset_get_dnode(spa, &spa->spa_mos, props, &propdir) == 0
&& zap_lookup(spa, &propdir, "bootfs", &bootfs) == 0
&& bootfs != 0)
- return zfs_mount_dataset(spa, bootfs, objset);
-
+ {
+ *objid = bootfs;
+ return (0);
+ }
/*
* Lookup the root dataset directory
*/
@@ -1517,34 +1845,50 @@
* to find the dataset object and from that the object set itself.
*/
dsl_dir_phys_t *dd = (dsl_dir_phys_t *) &dir.dn_bonus;
- return zfs_mount_dataset(spa, dd->dd_head_dataset_obj, objset);
+ *objid = dd->dd_head_dataset_obj;
+ return (0);
}
static int
-zfs_mount_pool(spa_t *spa)
+zfs_mount(const spa_t *spa, uint64_t rootobj, struct zfsmount *mount)
{
+ mount->spa = spa;
+
/*
- * Find the MOS and work our way in from there.
+ * Find the root object set if not explicitly provided
*/
- if (zio_read(spa, &spa->spa_uberblock.ub_rootbp, &spa->spa_mos)) {
- printf("ZFS: can't read MOS\n");
+ if (rootobj == 0 && zfs_get_root(spa, &rootobj)) {
+ printf("ZFS: can't find root filesystem\n");
return (EIO);
}
- /*
- * Find the root object set
- */
- if (zfs_mount_root(spa, &spa->spa_root_objset)) {
- printf("Can't find root filesystem - giving up\n");
+ if (zfs_mount_dataset(spa, rootobj, &mount->objset)) {
+ printf("ZFS: can't open root filesystem\n");
return (EIO);
}
+ mount->rootobj = rootobj;
+
return (0);
}
static int
-zfs_dnode_stat(spa_t *spa, dnode_phys_t *dn, struct stat *sb)
+zfs_spa_init(spa_t *spa)
+{
+
+ if (spa->spa_inited)
+ return (0);
+ if (zio_read(spa, &spa->spa_uberblock.ub_rootbp, &spa->spa_mos)) {
+ printf("ZFS: can't read MOS of pool %s\n", spa->spa_name);
+ return (EIO);
+ }
+ spa->spa_inited = 1;
+ return (0);
+}
+
+static int
+zfs_dnode_stat(const spa_t *spa, dnode_phys_t *dn, struct stat *sb)
{
if (dn->dn_bonustype != DMU_OT_SA) {
@@ -1599,10 +1943,11 @@
* Lookup a file and return its dnode.
*/
static int
-zfs_lookup(spa_t *spa, const char *upath, dnode_phys_t *dnode)
+zfs_lookup(const struct zfsmount *mount, const char *upath, dnode_phys_t *dnode)
{
int rc;
uint64_t objnum, rootnum, parentnum;
+ const spa_t *spa;
dnode_phys_t dn;
const char *p, *q;
char element[256];
@@ -1610,16 +1955,17 @@
int symlinks_followed = 0;
struct stat sb;
- if (spa->spa_root_objset.os_type != DMU_OST_ZFS) {
- printf("ZFS: unexpected object set type %llu\n",
- spa->spa_root_objset.os_type);
+ spa = mount->spa;
+ if (mount->objset.os_type != DMU_OST_ZFS) {
+ printf("ZFS: unexpected object set type %ju\n",
+ (uintmax_t)mount->objset.os_type);
return (EIO);
}
/*
* Get the root directory dnode.
*/
- rc = objset_get_dnode(spa, &spa->spa_root_objset, MASTER_NODE_OBJ, &dn);
+ rc = objset_get_dnode(spa, &mount->objset, MASTER_NODE_OBJ, &dn);
if (rc)
return (rc);
@@ -1627,7 +1973,7 @@
if (rc)
return (rc);
- rc = objset_get_dnode(spa, &spa->spa_root_objset, rootnum, &dn);
+ rc = objset_get_dnode(spa, &mount->objset, rootnum, &dn);
if (rc)
return (rc);
@@ -1660,7 +2006,7 @@
return (rc);
objnum = ZFS_DIRENT_OBJ(objnum);
- rc = objset_get_dnode(spa, &spa->spa_root_objset, objnum, &dn);
+ rc = objset_get_dnode(spa, &mount->objset, objnum, &dn);
if (rc)
return (rc);
@@ -1702,7 +2048,7 @@
objnum = rootnum;
else
objnum = parentnum;
- objset_get_dnode(spa, &spa->spa_root_objset, objnum, &dn);
+ objset_get_dnode(spa, &mount->objset, objnum, &dn);
}
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/ata/ata_all.c
--- a/head/sys/cam/ata/ata_all.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/ata/ata_all.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/ata/ata_all.c 223019 2011-06-12 18:52:39Z mav $");
+__FBSDID("$FreeBSD: head/sys/cam/ata/ata_all.c 238393 2012-07-12 10:09:34Z brueffer $");
#include <sys/param.h>
@@ -108,6 +108,16 @@
case 0x51: return ("CONFIGURE_STREAM");
case 0x60: return ("READ_FPDMA_QUEUED");
case 0x61: return ("WRITE_FPDMA_QUEUED");
+ case 0x67:
+ if (cmd->features == 0xec)
+ return ("SEP_ATTN IDENTIFY");
+ switch (cmd->lba_low) {
+ case 0x00: return ("SEP_ATTN READ BUFFER");
+ case 0x02: return ("SEP_ATTN RECEIVE DIAGNOSTIC RESULTS");
+ case 0x80: return ("SEP_ATTN WRITE BUFFER");
+ case 0x82: return ("SEP_ATTN SEND DIAGNOSTIC");
+ }
+ return ("SEP_ATTN");
case 0x70: return ("SEEK");
case 0x87: return ("CFA_TRANSLATE_SECTOR");
case 0x90: return ("EXECUTE_DEVICE_DIAGNOSTIC");
@@ -161,8 +171,8 @@
case 0xf2: return ("SECURITY_UNLOCK");
case 0xf3: return ("SECURITY_ERASE_PREPARE");
case 0xf4: return ("SECURITY_ERASE_UNIT");
- case 0xf5: return ("SECURITY_FREE_LOCK");
- case 0xf6: return ("SECURITY DISABLE PASSWORD");
+ case 0xf5: return ("SECURITY_FREEZE_LOCK");
+ case 0xf6: return ("SECURITY_DISABLE_PASSWORD");
case 0xf8: return ("READ_NATIVE_MAX_ADDRESS");
case 0xf9: return ("SET_MAX_ADDRESS");
}
@@ -286,6 +296,21 @@
printf(" device\n");
}
+void
+semb_print_ident(struct sep_identify_data *ident_data)
+{
+ char vendor[9], product[17], revision[5], fw[5], in[7], ins[5];
+
+ cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor));
+ cam_strvis(product, ident_data->product_id, 16, sizeof(product));
+ cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision));
+ cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw));
+ cam_strvis(in, ident_data->interface_id, 6, sizeof(in));
+ cam_strvis(ins, ident_data->interface_rev, 4, sizeof(ins));
+ printf("<%s %s %s %s> SEMB %s %s device\n",
+ vendor, product, revision, fw, in, ins);
+}
+
uint32_t
ata_logical_sector_size(struct ata_params *ident_data)
{
@@ -334,7 +359,7 @@
ataio->cmd.lba_low = lba;
ataio->cmd.lba_mid = lba >> 8;
ataio->cmd.lba_high = lba >> 16;
- ataio->cmd.device = 0x40 | ((lba >> 24) & 0x0f);
+ ataio->cmd.device = ATA_DEV_LBA | ((lba >> 24) & 0x0f);
ataio->cmd.sector_count = sector_count;
}
@@ -359,7 +384,7 @@
ataio->cmd.lba_low = lba;
ataio->cmd.lba_mid = lba >> 8;
ataio->cmd.lba_high = lba >> 16;
- ataio->cmd.device = 0x40;
+ ataio->cmd.device = ATA_DEV_LBA;
ataio->cmd.lba_low_exp = lba >> 24;
ataio->cmd.lba_mid_exp = lba >> 32;
ataio->cmd.lba_high_exp = lba >> 40;
@@ -379,7 +404,7 @@
ataio->cmd.lba_low = lba;
ataio->cmd.lba_mid = lba >> 8;
ataio->cmd.lba_high = lba >> 16;
- ataio->cmd.device = 0x40;
+ ataio->cmd.device = ATA_DEV_LBA;
ataio->cmd.lba_low_exp = lba >> 24;
ataio->cmd.lba_mid_exp = lba >> 32;
ataio->cmd.lba_high_exp = lba >> 40;
@@ -695,3 +720,86 @@
}
return (-1);
}
+
+void
+semb_receive_diagnostic_results(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
+ uint8_t tag_action, int pcv, uint8_t page_code,
+ uint8_t *data_ptr, uint16_t length, uint32_t timeout)
+{
+
+ length = min(length, 1020);
+ length = (length + 3) & ~3;
+ cam_fill_ataio(ataio,
+ retries,
+ cbfcnp,
+ /*flags*/CAM_DIR_IN,
+ tag_action,
+ data_ptr,
+ length,
+ timeout);
+ ata_28bit_cmd(ataio, ATA_SEP_ATTN,
+ pcv ? page_code : 0, 0x02, length / 4);
+}
+
+void
+semb_send_diagnostic(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout)
+{
+
+ length = min(length, 1020);
+ length = (length + 3) & ~3;
+ cam_fill_ataio(ataio,
+ retries,
+ cbfcnp,
+ /*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE,
+ tag_action,
+ data_ptr,
+ length,
+ timeout);
+ ata_28bit_cmd(ataio, ATA_SEP_ATTN,
+ length > 0 ? data_ptr[0] : 0, 0x82, length / 4);
+}
+
+void
+semb_read_buffer(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
+ uint8_t tag_action, uint8_t page_code,
+ uint8_t *data_ptr, uint16_t length, uint32_t timeout)
+{
+
+ length = min(length, 1020);
+ length = (length + 3) & ~3;
+ cam_fill_ataio(ataio,
+ retries,
+ cbfcnp,
+ /*flags*/CAM_DIR_IN,
+ tag_action,
+ data_ptr,
+ length,
+ timeout);
+ ata_28bit_cmd(ataio, ATA_SEP_ATTN,
+ page_code, 0x00, length / 4);
+}
+
+void
+semb_write_buffer(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout)
+{
+
+ length = min(length, 1020);
+ length = (length + 3) & ~3;
+ cam_fill_ataio(ataio,
+ retries,
+ cbfcnp,
+ /*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE,
+ tag_action,
+ data_ptr,
+ length,
+ timeout);
+ ata_28bit_cmd(ataio, ATA_SEP_ATTN,
+ length > 0 ? data_ptr[0] : 0, 0x80, length / 4);
+}
+
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/ata/ata_all.h
--- a/head/sys/cam/ata/ata_all.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/ata/ata_all.h Wed Jul 25 16:45:04 2012 +0300
@@ -23,7 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: head/sys/cam/ata/ata_all.h 220886 2011-04-20 13:27:50Z mav $
+ * $FreeBSD: head/sys/cam/ata/ata_all.h 235897 2012-05-24 11:07:39Z mav $
*/
#ifndef CAM_ATA_ALL_H
@@ -83,6 +83,20 @@
u_int8_t sector_count_exp;
};
+struct sep_identify_data {
+ uint8_t length; /* Enclosure descriptor length */
+ uint8_t subenc_id; /* Sub-enclosure identifier */
+ uint8_t logical_id[8]; /* Enclosure logical identifier (WWN) */
+ uint8_t vendor_id[8]; /* Vendor identification string */
+ uint8_t product_id[16]; /* Product identification string */
+ uint8_t product_rev[4]; /* Product revision string */
+ uint8_t channel_id; /* Channel identifier */
+ uint8_t firmware_rev[4];/* Firmware revision */
+ uint8_t interface_id[6];/* Interface spec ("S-E-S "/"SAF-TE")*/
+ uint8_t interface_rev[4];/* Interface spec revision */
+ uint8_t vend_spec[11]; /* Vendor specific information */
+};
+
int ata_version(int ver);
char * ata_op_string(struct ata_cmd *cmd);
@@ -126,4 +140,26 @@
int ata_identify_match(caddr_t identbuffer, caddr_t table_entry);
int ata_static_identify_match(caddr_t identbuffer, caddr_t table_entry);
+void semb_print_ident(struct sep_identify_data *ident_data);
+
+void semb_receive_diagnostic_results(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
+ uint8_t tag_action, int pcv, uint8_t page_code,
+ uint8_t *data_ptr, uint16_t allocation_length, uint32_t timeout);
+
+void semb_send_diagnostic(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint8_t tag_action, uint8_t *data_ptr, uint16_t param_list_length,
+ uint32_t timeout);
+
+void semb_read_buffer(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
+ uint8_t tag_action, uint8_t page_code,
+ uint8_t *data_ptr, uint16_t allocation_length, uint32_t timeout);
+
+void semb_write_buffer(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint8_t tag_action, uint8_t *data_ptr, uint16_t param_list_length,
+ uint32_t timeout);
+
#endif
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/ata/ata_da.c
--- a/head/sys/cam/ata/ata_da.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/ata/ata_da.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/ata/ata_da.c 234414 2012-04-18 08:55:26Z mav $");
+__FBSDID("$FreeBSD: head/sys/cam/ata/ata_da.c 238382 2012-07-11 23:22:09Z brueffer $");
#include "opt_ada.h"
#include "opt_ata.h"
@@ -368,9 +368,9 @@
SYSCTL_INT(_kern_cam_ada, OID_AUTO, default_timeout, CTLFLAG_RW,
&ada_default_timeout, 0, "Normal I/O timeout (in seconds)");
TUNABLE_INT("kern.cam.ada.default_timeout", &ada_default_timeout);
-SYSCTL_INT(_kern_cam_ada, OID_AUTO, ada_send_ordered, CTLFLAG_RW,
+SYSCTL_INT(_kern_cam_ada, OID_AUTO, send_ordered, CTLFLAG_RW,
&ada_send_ordered, 0, "Send Ordered Tags");
-TUNABLE_INT("kern.cam.ada.ada_send_ordered", &ada_send_ordered);
+TUNABLE_INT("kern.cam.ada.send_ordered", &ada_send_ordered);
SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_shutdown, CTLFLAG_RW,
&ada_spindown_shutdown, 0, "Spin down upon shutdown");
TUNABLE_INT("kern.cam.ada.spindown_shutdown", &ada_spindown_shutdown);
@@ -436,9 +436,8 @@
softc = (struct ada_softc *)periph->softc;
softc->flags |= ADA_FLAG_OPEN;
- CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
- ("adaopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit,
- periph->unit_number));
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
+ ("adaopen\n"));
if ((softc->flags & ADA_FLAG_PACK_INVALID) != 0) {
/* Invalidate our pack information. */
@@ -469,6 +468,10 @@
}
softc = (struct ada_softc *)periph->softc;
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
+ ("adaclose\n"));
+
/* We only sync the cache if the drive is capable of it. */
if ((softc->flags & ADA_FLAG_CAN_FLUSHCACHE) != 0 &&
(softc->flags & ADA_FLAG_PACK_INVALID) == 0) {
@@ -487,7 +490,7 @@
ata_48bit_cmd(&ccb->ataio, ATA_FLUSHCACHE48, 0, 0, 0);
else
ata_28bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0);
- cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0,
+ cam_periph_runccb(ccb, adaerror, /*cam_flags*/0,
/*sense_flags*/0, softc->disk->d_devstat);
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
@@ -542,6 +545,8 @@
cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("adastrategy(%p)\n", bp));
+
/*
* If the device has been made invalid, error out
*/
@@ -579,6 +584,7 @@
struct disk *dp;
uint64_t lba;
uint16_t count;
+ int error = 0;
dp = arg;
periph = dp->d_drv1;
@@ -617,13 +623,16 @@
}
xpt_polled_action(&ccb);
- if ((ccb.ataio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ error = cam_periph_error(&ccb,
+ 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL);
+ if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
+ cam_release_devq(ccb.ccb_h.path, /*relsim_flags*/0,
+ /*reduction*/0, /*timeout*/0, /*getcount_only*/0);
+ if (error != 0)
printf("Aborting dump due to I/O error.\n");
- cam_periph_unlock(periph);
- return(EIO);
- }
+
cam_periph_unlock(periph);
- return(0);
+ return (error);
}
if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) {
@@ -631,7 +640,7 @@
ccb.ccb_h.ccb_state = ADA_CCB_DUMP;
cam_fill_ataio(&ccb.ataio,
- 1,
+ 0,
adadone,
CAM_DIR_NONE,
0,
@@ -645,18 +654,16 @@
ata_28bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0);
xpt_polled_action(&ccb);
- if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
+ error = cam_periph_error(&ccb,
+ 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL);
+ if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
+ cam_release_devq(ccb.ccb_h.path, /*relsim_flags*/0,
+ /*reduction*/0, /*timeout*/0, /*getcount_only*/0);
+ if (error != 0)
xpt_print(periph->path, "Synchronize cache failed\n");
-
- if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
- cam_release_devq(ccb.ccb_h.path,
- /*relsim_flags*/0,
- /*reduction*/0,
- /*timeout*/0,
- /*getcount_only*/0);
}
cam_periph_unlock(periph);
- return (0);
+ return (error);
}
static void
@@ -742,6 +749,7 @@
adaasync(void *callback_arg, u_int32_t code,
struct cam_path *path, void *arg)
{
+ struct ccb_getdev cgd;
struct cam_periph *periph;
struct ada_softc *softc;
@@ -776,11 +784,49 @@
"due to status 0x%x\n", status);
break;
}
+ case AC_GETDEV_CHANGED:
+ {
+ softc = (struct ada_softc *)periph->softc;
+ xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+ cgd.ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action((union ccb *)&cgd);
+
+ if ((cgd.ident_data.capabilities1 & ATA_SUPPORT_DMA) &&
+ (cgd.inq_flags & SID_DMA))
+ softc->flags |= ADA_FLAG_CAN_DMA;
+ else
+ softc->flags &= ~ADA_FLAG_CAN_DMA;
+ if ((cgd.ident_data.satacapabilities & ATA_SUPPORT_NCQ) &&
+ (cgd.inq_flags & SID_DMA) && (cgd.inq_flags & SID_CmdQue))
+ softc->flags |= ADA_FLAG_CAN_NCQ;
+ else
+ softc->flags &= ~ADA_FLAG_CAN_NCQ;
+ if ((cgd.ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) &&
+ (cgd.inq_flags & SID_DMA))
+ softc->flags |= ADA_FLAG_CAN_TRIM;
+ else
+ softc->flags &= ~ADA_FLAG_CAN_TRIM;
+
+ cam_periph_async(periph, code, path, arg);
+ break;
+ }
+ case AC_ADVINFO_CHANGED:
+ {
+ uintptr_t buftype;
+
+ buftype = (uintptr_t)arg;
+ if (buftype == CDAI_TYPE_PHYS_PATH) {
+ struct ada_softc *softc;
+
+ softc = periph->softc;
+ disk_attr_changed(softc->disk, "GEOM::physpath",
+ M_NOWAIT);
+ }
+ break;
+ }
case AC_SENT_BDR:
case AC_BUS_RESET:
{
- struct ccb_getdev cgd;
-
softc = (struct ada_softc *)periph->softc;
cam_periph_async(periph, code, path, arg);
if (softc->state != ADA_STATE_NORMAL)
@@ -919,7 +965,7 @@
bioq_init(&softc->bio_queue);
bioq_init(&softc->trim_queue);
- if (cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA &&
+ if ((cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA) &&
(cgd->inq_flags & SID_DMA))
softc->flags |= ADA_FLAG_CAN_DMA;
if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48)
@@ -928,10 +974,11 @@
softc->flags |= ADA_FLAG_CAN_FLUSHCACHE;
if (cgd->ident_data.support.command1 & ATA_SUPPORT_POWERMGT)
softc->flags |= ADA_FLAG_CAN_POWERMGT;
- if (cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ &&
+ if ((cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ) &&
(cgd->inq_flags & SID_DMA) && (cgd->inq_flags & SID_CmdQue))
softc->flags |= ADA_FLAG_CAN_NCQ;
- if (cgd->ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) {
+ if ((cgd->ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) &&
+ (cgd->inq_flags & SID_DMA)) {
softc->flags |= ADA_FLAG_CAN_TRIM;
softc->trim_max_ranges = TRIM_MAX_RANGES;
if (cgd->ident_data.max_dsm_blocks != 0) {
@@ -1088,8 +1135,9 @@
* them and the only alternative would be to
* not attach the device on failure.
*/
- xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
- adaasync, periph, periph->path);
+ xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE |
+ AC_GETDEV_CHANGED | AC_ADVINFO_CHANGED,
+ adaasync, periph, periph->path);
/*
* Schedule a periodic event to occasionally send an
@@ -1126,6 +1174,8 @@
struct ada_softc *softc = (struct ada_softc *)periph->softc;
struct ccb_ataio *ataio = &start_ccb->ataio;
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("adastart\n"));
+
switch (softc->state) {
case ADA_STATE_NORMAL:
{
@@ -1134,7 +1184,7 @@
/* Execute immediate CCB if waiting. */
if (periph->immediate_priority <= periph->pinfo.priority) {
- CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("queuing for immediate ccb\n"));
start_ccb->ccb_h.ccb_state = ADA_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
@@ -1426,6 +1476,9 @@
softc = (struct ada_softc *)periph->softc;
ataio = &done_ccb->ataio;
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("adadone\n"));
+
switch (ataio->ccb_h.ccb_state & ADA_CCB_TYPE_MASK) {
case ADA_CCB_BUFFER_IO:
case ADA_CCB_TRIM:
@@ -1665,6 +1718,7 @@
{
struct cam_periph *periph;
struct ada_softc *softc;
+ int error;
TAILQ_FOREACH(periph, &adadriver.units, unit_links) {
union ccb ccb;
@@ -1688,7 +1742,7 @@
ccb.ccb_h.ccb_state = ADA_CCB_DUMP;
cam_fill_ataio(&ccb.ataio,
- 1,
+ 0,
adadone,
CAM_DIR_NONE,
0,
@@ -1702,15 +1756,13 @@
ata_28bit_cmd(&ccb.ataio, ATA_FLUSHCACHE, 0, 0, 0);
xpt_polled_action(&ccb);
- if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
+ error = cam_periph_error(&ccb,
+ 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL);
+ if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
+ cam_release_devq(ccb.ccb_h.path, /*relsim_flags*/0,
+ /*reduction*/0, /*timeout*/0, /*getcount_only*/0);
+ if (error != 0)
xpt_print(periph->path, "Synchronize cache failed\n");
-
- if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
- cam_release_devq(ccb.ccb_h.path,
- /*relsim_flags*/0,
- /*reduction*/0,
- /*timeout*/0,
- /*getcount_only*/0);
cam_periph_unlock(periph);
}
}
@@ -1720,6 +1772,7 @@
{
struct cam_periph *periph;
struct ada_softc *softc;
+ int error;
TAILQ_FOREACH(periph, &adadriver.units, unit_links) {
union ccb ccb;
@@ -1744,7 +1797,7 @@
ccb.ccb_h.ccb_state = ADA_CCB_DUMP;
cam_fill_ataio(&ccb.ataio,
- 1,
+ 0,
adadone,
CAM_DIR_NONE | flags,
0,
@@ -1755,15 +1808,13 @@
ata_28bit_cmd(&ccb.ataio, cmd, 0, 0, 0);
xpt_polled_action(&ccb);
- if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
+ error = cam_periph_error(&ccb,
+ 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL);
+ if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
+ cam_release_devq(ccb.ccb_h.path, /*relsim_flags*/0,
+ /*reduction*/0, /*timeout*/0, /*getcount_only*/0);
+ if (error != 0)
xpt_print(periph->path, "Spin-down disk failed\n");
-
- if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
- cam_release_devq(ccb.ccb_h.path,
- /*relsim_flags*/0,
- /*reduction*/0,
- /*timeout*/0,
- /*getcount_only*/0);
cam_periph_unlock(periph);
}
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/ata/ata_pmp.c
--- a/head/sys/cam/ata/ata_pmp.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/ata/ata_pmp.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/ata/ata_pmp.c 227309 2011-11-07 15:43:11Z ed $");
+__FBSDID("$FreeBSD: head/sys/cam/ata/ata_pmp.c 236602 2012-06-05 09:45:42Z mav $");
#include <sys/param.h>
@@ -126,8 +126,13 @@
#define PMP_DEFAULT_RETRY 1
#endif
+#ifndef PMP_DEFAULT_HIDE_SPECIAL
+#define PMP_DEFAULT_HIDE_SPECIAL 1
+#endif
+
static int pmp_retry_count = PMP_DEFAULT_RETRY;
static int pmp_default_timeout = PMP_DEFAULT_TIMEOUT;
+static int pmp_hide_special = PMP_DEFAULT_HIDE_SPECIAL;
static SYSCTL_NODE(_kern_cam, OID_AUTO, pmp, CTLFLAG_RD, 0,
"CAM Direct Access Disk driver");
@@ -137,6 +142,9 @@
SYSCTL_INT(_kern_cam_pmp, OID_AUTO, default_timeout, CTLFLAG_RW,
&pmp_default_timeout, 0, "Normal I/O timeout (in seconds)");
TUNABLE_INT("kern.cam.pmp.default_timeout", &pmp_default_timeout);
+SYSCTL_INT(_kern_cam_pmp, OID_AUTO, hide_special, CTLFLAG_RW,
+ &pmp_hide_special, 0, "Hide extra ports");
+TUNABLE_INT("kern.cam.pmp.hide_special", &pmp_hide_special);
static struct periph_driver pmpdriver =
{
@@ -421,7 +429,9 @@
softc = (struct pmp_softc *)periph->softc;
ataio = &start_ccb->ataio;
-
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("pmpstart\n"));
+
if (softc->restart) {
softc->restart = 0;
softc->state = min(softc->state, PMP_STATE_PRECONFIG);
@@ -552,7 +562,7 @@
softc = (struct pmp_softc *)periph->softc;
ataio = &done_ccb->ataio;
- CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("pmpdone\n"));
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("pmpdone\n"));
priority = done_ccb->ccb_h.pinfo.priority;
@@ -583,23 +593,33 @@
(ataio->res.lba_mid << 16) +
(ataio->res.lba_low << 8) +
ataio->res.sector_count;
- /* This PMP declares 6 ports, while only 5 of them are real.
- * Port 5 is enclosure management bridge port, which has implementation
- * problems, causing probe faults. Hide it for now. */
- if (softc->pm_pid == 0x37261095 && softc->pm_ports == 6)
- softc->pm_ports = 5;
- /* This PMP declares 7 ports, while only 5 of them are real.
- * Port 5 is some fake "Config Disk" with 640 sectors size,
- * port 6 is enclosure management bridge port.
- * Both fake ports has implementation problems, causing
- * probe faults. Hide them for now. */
- if (softc->pm_pid == 0x47261095 && softc->pm_ports == 7)
- softc->pm_ports = 5;
- /* These PMPs declare one more port then actually have,
- * for configuration purposes. Hide it for now. */
- if (softc->pm_pid == 0x57231095 || softc->pm_pid == 0x57331095 ||
- softc->pm_pid == 0x57341095 || softc->pm_pid == 0x57441095)
- softc->pm_ports--;
+ if (pmp_hide_special) {
+ /*
+ * This PMP declares 6 ports, while only 5 of them
+ * are real. Port 5 is a SEMB port, probing which
+ * causes timeouts if external SEP is not connected
+ * to PMP over I2C.
+ */
+ if (softc->pm_pid == 0x37261095 && softc->pm_ports == 6)
+ softc->pm_ports = 5;
+
+ /*
+ * This PMP declares 7 ports, while only 5 of them
+ * are real. Port 5 is a fake "Config Disk" with
+ * 640 sectors size. Port 6 is a SEMB port.
+ */
+ if (softc->pm_pid == 0x47261095 && softc->pm_ports == 7)
+ softc->pm_ports = 5;
+
+ /*
+ * These PMPs have extra configuration port.
+ */
+ if (softc->pm_pid == 0x57231095 ||
+ softc->pm_pid == 0x57331095 ||
+ softc->pm_pid == 0x57341095 ||
+ softc->pm_pid == 0x57441095)
+ softc->pm_ports--;
+ }
printf("%s%d: %d fan-out ports\n",
periph->periph_name, periph->unit_number,
softc->pm_ports);
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/ata/ata_xpt.c
--- a/head/sys/cam/ata/ata_xpt.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/ata/ata_xpt.c Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/ata/ata_xpt.c 230912 2012-02-02 14:17:58Z mav $");
+__FBSDID("$FreeBSD: head/sys/cam/ata/ata_xpt.c 236814 2012-06-09 13:07:44Z mav $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -65,6 +65,7 @@
struct scsi_inquiry_pattern inq_pat;
u_int8_t quirks;
#define CAM_QUIRK_MAXTAGS 0x01
+ u_int mintags;
u_int maxtags;
};
@@ -93,6 +94,9 @@
PROBE_FULL_INQUIRY,
PROBE_PM_PID,
PROBE_PM_PRV,
+ PROBE_IDENTIFY_SES,
+ PROBE_IDENTIFY_SAFTE,
+ PROBE_DONE,
PROBE_INVALID
} probe_action;
@@ -110,6 +114,9 @@
"PROBE_FULL_INQUIRY",
"PROBE_PM_PID",
"PROBE_PM_PRV",
+ "PROBE_IDENTIFY_SES",
+ "PROBE_IDENTIFY_SAFTE",
+ "PROBE_DONE",
"PROBE_INVALID"
};
@@ -117,7 +124,7 @@
do { \
char **text; \
text = probe_action_text; \
- CAM_DEBUG((softc)->periph->path, CAM_DEBUG_INFO, \
+ CAM_DEBUG((softc)->periph->path, CAM_DEBUG_PROBE, \
("Probe %s to %s\n", text[(softc)->action], \
text[(newaction)])); \
(softc)->action = (newaction); \
@@ -149,7 +156,7 @@
T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED,
/*vendor*/"*", /*product*/"*", /*revision*/"*"
},
- /*quirks*/0, /*maxtags*/0
+ /*quirks*/0, /*mintags*/0, /*maxtags*/0
},
};
@@ -160,9 +167,7 @@
void *arg);
static void probeschedule(struct cam_periph *probe_periph);
static void probestart(struct cam_periph *periph, union ccb *start_ccb);
-//static void proberequestdefaultnegotiation(struct cam_periph *periph);
-//static int proberequestbackoff(struct cam_periph *periph,
-// struct cam_ed *device);
+static void proberequestdefaultnegotiation(struct cam_periph *periph);
static void probedone(struct cam_periph *periph, union ccb *done_ccb);
static void probecleanup(struct cam_periph *periph);
static void ata_find_quirk(struct cam_ed *device);
@@ -175,6 +180,7 @@
ata_alloc_device(struct cam_eb *bus, struct cam_et *target,
lun_id_t lun_id);
static void ata_device_transport(struct cam_path *path);
+static void ata_get_transfer_settings(struct ccb_trans_settings *cts);
static void ata_set_transfer_settings(struct ccb_trans_settings *cts,
struct cam_ed *device,
int async_update);
@@ -247,6 +253,8 @@
if (status != CAM_REQ_CMP) {
return (status);
}
+ CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe started\n"));
+
/*
* Ensure nobody slip in until probe finish.
*/
@@ -266,7 +274,8 @@
ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) ||
- periph->path->device->protocol == PROTO_SATAPM)
+ periph->path->device->protocol == PROTO_SATAPM ||
+ periph->path->device->protocol == PROTO_SEMB)
PROBE_SET_ACTION(softc, PROBE_RESET);
else
PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
@@ -300,7 +309,8 @@
if (softc->restart) {
softc->restart = 0;
if ((path->device->flags & CAM_DEV_UNCONFIGURED) ||
- path->device->protocol == PROTO_SATAPM)
+ path->device->protocol == PROTO_SATAPM ||
+ path->device->protocol == PROTO_SEMB)
softc->action = PROBE_RESET;
else
softc->action = PROBE_IDENTIFY;
@@ -406,6 +416,7 @@
path->device->inq_flags &= ~SID_DMA;
else
path->device->inq_flags |= SID_DMA;
+ xpt_async(AC_GETDEV_CHANGED, path, NULL);
cam_fill_ataio(ataio,
1,
probedone,
@@ -622,15 +633,36 @@
10 * 1000);
ata_pm_read_cmd(ataio, 1, 15);
break;
- case PROBE_INVALID:
- CAM_DEBUG(path, CAM_DEBUG_INFO,
- ("probestart: invalid action state\n"));
+ case PROBE_IDENTIFY_SES:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ /*flags*/CAM_DIR_IN,
+ 0,
+ /*data_ptr*/(u_int8_t *)&softc->ident_data,
+ /*dxfer_len*/sizeof(softc->ident_data),
+ 30 * 1000);
+ ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x02,
+ sizeof(softc->ident_data) / 4);
+ break;
+ case PROBE_IDENTIFY_SAFTE:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ /*flags*/CAM_DIR_IN,
+ 0,
+ /*data_ptr*/(u_int8_t *)&softc->ident_data,
+ /*dxfer_len*/sizeof(softc->ident_data),
+ 30 * 1000);
+ ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x00,
+ sizeof(softc->ident_data) / 4);
+ break;
default:
- break;
+ panic("probestart: invalid action state 0x%x\n", softc->action);
}
xpt_action(start_ccb);
}
-#if 0
+
static void
proberequestdefaultnegotiation(struct cam_periph *periph)
{
@@ -640,130 +672,29 @@
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_USER_SETTINGS;
xpt_action((union ccb *)&cts);
- if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
return;
- }
+ cts.xport_specific.valid = 0;
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
xpt_action((union ccb *)&cts);
}
-/*
- * Backoff Negotiation Code- only pertinent for SPI devices.
- */
-static int
-proberequestbackoff(struct cam_periph *periph, struct cam_ed *device)
-{
- struct ccb_trans_settings cts;
- struct ccb_trans_settings_spi *spi;
-
- memset(&cts, 0, sizeof (cts));
- xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
- cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
- cts.type = CTS_TYPE_CURRENT_SETTINGS;
- xpt_action((union ccb *)&cts);
- if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- if (bootverbose) {
- xpt_print(periph->path,
- "failed to get current device settings\n");
- }
- return (0);
- }
- if (cts.transport != XPORT_SPI) {
- if (bootverbose) {
- xpt_print(periph->path, "not SPI transport\n");
- }
- return (0);
- }
- spi = &cts.xport_specific.spi;
-
- /*
- * We cannot renegotiate sync rate if we don't have one.
- */
- if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) {
- if (bootverbose) {
- xpt_print(periph->path, "no sync rate known\n");
- }
- return (0);
- }
-
- /*
- * We'll assert that we don't have to touch PPR options- the
- * SIM will see what we do with period and offset and adjust
- * the PPR options as appropriate.
- */
-
- /*
- * A sync rate with unknown or zero offset is nonsensical.
- * A sync period of zero means Async.
- */
- if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0
- || spi->sync_offset == 0 || spi->sync_period == 0) {
- if (bootverbose) {
- xpt_print(periph->path, "no sync rate available\n");
- }
- return (0);
- }
-
- if (device->flags & CAM_DEV_DV_HIT_BOTTOM) {
- CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
- ("hit async: giving up on DV\n"));
- return (0);
- }
-
-
- /*
- * Jump sync_period up by one, but stop at 5MHz and fall back to Async.
- * We don't try to remember 'last' settings to see if the SIM actually
- * gets into the speed we want to set. We check on the SIM telling
- * us that a requested speed is bad, but otherwise don't try and
- * check the speed due to the asynchronous and handshake nature
- * of speed setting.
- */
- spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET;
- for (;;) {
- spi->sync_period++;
- if (spi->sync_period >= 0xf) {
- spi->sync_period = 0;
- spi->sync_offset = 0;
- CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
- ("setting to async for DV\n"));
- /*
- * Once we hit async, we don't want to try
- * any more settings.
- */
- device->flags |= CAM_DEV_DV_HIT_BOTTOM;
- } else if (bootverbose) {
- CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
- ("DV: period 0x%x\n", spi->sync_period));
- printf("setting period to 0x%x\n", spi->sync_period);
- }
- cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
- cts.type = CTS_TYPE_CURRENT_SETTINGS;
- xpt_action((union ccb *)&cts);
- if ((cts.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
- break;
- }
- CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
- ("DV: failed to set period 0x%x\n", spi->sync_period));
- if (spi->sync_period == 0) {
- return (0);
- }
- }
- return (1);
-}
-#endif
static void
probedone(struct cam_periph *periph, union ccb *done_ccb)
{
struct ccb_trans_settings cts;
struct ata_params *ident_buf;
+ struct scsi_inquiry_data *inq_buf;
probe_softc *softc;
struct cam_path *path;
cam_status status;
u_int32_t priority;
u_int caps;
- int found = 1;
+ int changed = 1, found = 1;
+ static const uint8_t fake_device_id_hdr[8] =
+ {0, SVPD_DEVICE_ID, 0, 12,
+ SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8};
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n"));
@@ -771,14 +702,12 @@
path = done_ccb->ccb_h.path;
priority = done_ccb->ccb_h.pinfo.priority;
ident_buf = &path->device->ident_data;
+ inq_buf = &path->device->inq_data;
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- if (softc->restart) {
- if (bootverbose) {
- cam_error_print(done_ccb,
- CAM_ESF_ALL, CAM_EPF_ALL);
- }
- } else if (cam_periph_error(done_ccb, 0, 0, NULL) == ERESTART)
+ if (cam_periph_error(done_ccb,
+ 0, softc->restart ? (SF_NO_RECOVERY | SF_NO_RETRY) : 0,
+ NULL) == ERESTART)
return;
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
/* Don't wedge the queue */
@@ -819,6 +748,18 @@
} else if (softc->action == PROBE_SETDMAAA &&
status == CAM_ATA_STATUS_ERROR) {
goto noerror;
+
+ /*
+ * SES and SAF-TE SEPs have different IDENTIFY commands,
+ * but SATA specification doesn't tell how to identify them.
+ * Until better way found, just try another if first fail.
+ */
+ } else if (softc->action == PROBE_IDENTIFY_SES &&
+ status == CAM_ATA_STATUS_ERROR) {
+ PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
}
/*
@@ -833,6 +774,7 @@
*/
device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
xpt_async(AC_LOST_DEVICE, path, NULL);
+ PROBE_SET_ACTION(softc, PROBE_INVALID);
found = 0;
goto done;
}
@@ -844,8 +786,8 @@
{
int sign = (done_ccb->ataio.res.lba_high << 8) +
done_ccb->ataio.res.lba_mid;
- if (bootverbose)
- xpt_print(path, "SIGNATURE: %04x\n", sign);
+ CAM_DEBUG(path, CAM_DEBUG_PROBE,
+ ("SIGNATURE: %04x\n", sign));
if (sign == 0x0000 &&
done_ccb->ccb_h.target_id != 15) {
path->device->protocol = PROTO_ATA;
@@ -862,6 +804,10 @@
xpt_action((union ccb *)&cts);
path->device->protocol = PROTO_SATAPM;
PROBE_SET_ACTION(softc, PROBE_PM_PID);
+ } else if (sign == 0xc33c &&
+ done_ccb->ccb_h.target_id != 15) {
+ path->device->protocol = PROTO_SEMB;
+ PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES);
} else if (sign == 0xeb14 &&
done_ccb->ccb_h.target_id != 15) {
path->device->protocol = PROTO_SCSI;
@@ -881,7 +827,6 @@
{
struct ccb_pathinq cpi;
int16_t *ptr;
- int changed = 1;
ident_buf = &softc->ident_data;
for (ptr = (int16_t *)ident_buf;
@@ -936,6 +881,11 @@
path->device->serial_num = NULL;
path->device->serial_num_len = 0;
}
+ if (path->device->device_id != NULL) {
+ free(path->device->device_id, M_CAMXPT);
+ path->device->device_id = NULL;
+ path->device->device_id_len = 0;
+ }
path->device->serial_num =
(u_int8_t *)malloc((sizeof(ident_buf->serial) + 1),
M_CAMXPT, M_NOWAIT);
@@ -948,11 +898,25 @@
path->device->serial_num_len =
strlen(path->device->serial_num);
}
+ if (ident_buf->enabled.extension &
+ ATA_SUPPORT_64BITWWN) {
+ path->device->device_id =
+ malloc(16, M_CAMXPT, M_NOWAIT);
+ if (path->device->device_id != NULL) {
+ path->device->device_id_len = 16;
+ bcopy(&fake_device_id_hdr,
+ path->device->device_id, 8);
+ bcopy(ident_buf->wwn,
+ path->device->device_id + 8, 8);
+ }
+ }
path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
+ xpt_async(AC_GETDEV_CHANGED, path, NULL);
}
if (ident_buf->satacapabilities & ATA_SUPPORT_NCQ) {
- path->device->mintags = path->device->maxtags =
+ path->device->mintags = 2;
+ path->device->maxtags =
ATA_QUEUE_LEN(ident_buf->queue) + 1;
}
ata_find_quirk(path->device);
@@ -973,11 +937,11 @@
cts.xport_specific.sata.tags = path->device->maxtags;
cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS;
xpt_action((union ccb *)&cts);
- /* Reconfigure queues for tagged queueing. */
- xpt_start_tags(path);
}
}
ata_device_transport(path);
+ if (changed)
+ proberequestdefaultnegotiation(periph);
PROBE_SET_ACTION(softc, PROBE_SETMODE);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
@@ -1088,15 +1052,14 @@
xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
done_ccb);
}
+ PROBE_SET_ACTION(softc, PROBE_DONE);
break;
case PROBE_INQUIRY:
case PROBE_FULL_INQUIRY:
{
- struct scsi_inquiry_data *inq_buf;
u_int8_t periph_qual, len;
path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID;
- inq_buf = &path->device->inq_data;
periph_qual = SID_QUAL(inq_buf);
@@ -1131,6 +1094,7 @@
xpt_action(done_ccb);
xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, done_ccb);
}
+ PROBE_SET_ACTION(softc, PROBE_DONE);
break;
}
case PROBE_PM_PID:
@@ -1156,6 +1120,9 @@
snprintf(ident_buf->revision, sizeof(ident_buf->revision),
"%04x", softc->pm_prv);
path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
+ ata_device_transport(path);
+ if (periph->path->device->flags & CAM_DEV_UNCONFIGURED)
+ proberequestdefaultnegotiation(periph);
/* Set supported bits. */
bzero(&cts, sizeof(cts));
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
@@ -1199,12 +1166,56 @@
xpt_action(done_ccb);
xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, done_ccb);
}
+ PROBE_SET_ACTION(softc, PROBE_DONE);
break;
- case PROBE_INVALID:
- CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_INFO,
- ("probedone: invalid action state\n"));
+ case PROBE_IDENTIFY_SES:
+ case PROBE_IDENTIFY_SAFTE:
+ if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) {
+ /* Check that it is the same device. */
+ if (bcmp(&softc->ident_data, ident_buf, 53)) {
+ /* Device changed. */
+ xpt_async(AC_LOST_DEVICE, path, NULL);
+ } else {
+ bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params));
+ changed = 0;
+ }
+ }
+ if (changed) {
+ bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params));
+ /* Clean up from previous instance of this device */
+ if (path->device->device_id != NULL) {
+ free(path->device->device_id, M_CAMXPT);
+ path->device->device_id = NULL;
+ path->device->device_id_len = 0;
+ }
+ path->device->device_id =
+ malloc(16, M_CAMXPT, M_NOWAIT);
+ if (path->device->device_id != NULL) {
+ path->device->device_id_len = 16;
+ bcopy(&fake_device_id_hdr,
+ path->device->device_id, 8);
+ bcopy(((uint8_t*)ident_buf) + 2,
+ path->device->device_id + 8, 8);
+ }
+
+ path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
+ }
+ ata_device_transport(path);
+ if (changed)
+ proberequestdefaultnegotiation(periph);
+
+ if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
+ path->device->flags &= ~CAM_DEV_UNCONFIGURED;
+ xpt_acquire_device(path->device);
+ done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action(done_ccb);
+ xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
+ done_ccb);
+ }
+ PROBE_SET_ACTION(softc, PROBE_DONE);
+ break;
default:
- break;
+ panic("probedone: invalid action state 0x%x\n", softc->action);
}
done:
if (softc->restart) {
@@ -1214,15 +1225,16 @@
return;
}
xpt_release_ccb(done_ccb);
+ CAM_DEBUG(periph->path, CAM_DEBUG_PROBE, ("Probe completed\n"));
while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) {
TAILQ_REMOVE(&softc->request_ccbs,
&done_ccb->ccb_h, periph_links.tqe);
done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR;
xpt_done(done_ccb);
}
+ cam_periph_invalidate(periph);
cam_release_devq(periph->path,
RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE);
- cam_periph_invalidate(periph);
cam_periph_release_locked(periph);
}
@@ -1248,8 +1260,10 @@
quirk = (struct ata_quirk_entry *)match;
device->quirk = quirk;
- if (quirk->quirks & CAM_QUIRK_MAXTAGS)
- device->mintags = device->maxtags = quirk->maxtags;
+ if (quirk->quirks & CAM_QUIRK_MAXTAGS) {
+ device->mintags = quirk->mintags;
+ device->maxtags = quirk->maxtags;
+ }
}
typedef struct {
@@ -1473,12 +1487,17 @@
}
if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) {
- probe_softc *softc;
+ if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) {
+ probe_softc *softc;
- softc = (probe_softc *)old_periph->softc;
- TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h,
- periph_links.tqe);
- softc->restart = 1;
+ softc = (probe_softc *)old_periph->softc;
+ TAILQ_INSERT_TAIL(&softc->request_ccbs,
+ &request_ccb->ccb_h, periph_links.tqe);
+ softc->restart = 1;
+ } else {
+ request_ccb->ccb_h.status = CAM_REQ_CMP_ERR;
+ xpt_done(request_ccb);
+ }
} else {
status = cam_periph_alloc(proberegister, NULL, probecleanup,
probestart, "aprobe",
@@ -1624,10 +1643,20 @@
device = start_ccb->ccb_h.path->device;
cdai = &start_ccb->cdai;
switch(cdai->buftype) {
+ case CDAI_TYPE_SCSI_DEVID:
+ if (cdai->flags & CDAI_FLAG_STORE)
+ return;
+ cdai->provsiz = device->device_id_len;
+ if (device->device_id_len == 0)
+ break;
+ amt = device->device_id_len;
+ if (cdai->provsiz > cdai->bufsiz)
+ amt = cdai->bufsiz;
+ memcpy(cdai->buf, device->device_id, amt);
+ break;
case CDAI_TYPE_SERIAL_NUM:
if (cdai->flags & CDAI_FLAG_STORE)
- break;
- start_ccb->ccb_h.status = CAM_REQ_CMP;
+ return;
cdai->provsiz = device->serial_num_len;
if (device->serial_num_len == 0)
break;
@@ -1636,8 +1665,45 @@
amt = cdai->bufsiz;
memcpy(cdai->buf, device->serial_num, amt);
break;
+ case CDAI_TYPE_PHYS_PATH:
+ if (cdai->flags & CDAI_FLAG_STORE) {
+ if (device->physpath != NULL)
+ free(device->physpath, M_CAMXPT);
+ device->physpath_len = cdai->bufsiz;
+ /* Clear existing buffer if zero length */
+ if (cdai->bufsiz == 0)
+ break;
+ device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT);
+ if (device->physpath == NULL) {
+ start_ccb->ccb_h.status = CAM_REQ_ABORTED;
+ return;
+ }
+ memcpy(device->physpath, cdai->buf, cdai->bufsiz);
+ } else {
+ cdai->provsiz = device->physpath_len;
+ if (device->physpath_len == 0)
+ break;
+ amt = device->physpath_len;
+ if (cdai->provsiz > cdai->bufsiz)
+ amt = cdai->bufsiz;
+ memcpy(cdai->buf, device->physpath, amt);
+ }
+ break;
default:
- break;
+ return;
+ }
+ start_ccb->ccb_h.status = CAM_REQ_CMP;
+
+ if (cdai->flags & CDAI_FLAG_STORE) {
+ int owned;
+
+ owned = mtx_owned(start_ccb->ccb_h.path->bus->sim->mtx);
+ if (owned == 0)
+ mtx_lock(start_ccb->ccb_h.path->bus->sim->mtx);
+ xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path,
+ (void *)(uintptr_t)cdai->buftype);
+ if (owned == 0)
+ mtx_unlock(start_ccb->ccb_h.path->bus->sim->mtx);
}
}
@@ -1664,10 +1730,7 @@
break;
case XPT_GET_TRAN_SETTINGS:
{
- struct cam_sim *sim;
-
- sim = start_ccb->ccb_h.path->bus->sim;
- (*(sim->sim_action))(sim, start_ccb);
+ ata_get_transfer_settings(&start_ccb->cts);
break;
}
case XPT_SCSI_IO:
@@ -1706,14 +1769,60 @@
}
static void
+ata_get_transfer_settings(struct ccb_trans_settings *cts)
+{
+ struct ccb_trans_settings_ata *ata;
+ struct ccb_trans_settings_scsi *scsi;
+ struct cam_ed *device;
+ struct cam_sim *sim;
+
+ device = cts->ccb_h.path->device;
+ sim = cts->ccb_h.path->bus->sim;
+ (*(sim->sim_action))(sim, (union ccb *)cts);
+
+ if (cts->protocol == PROTO_UNKNOWN ||
+ cts->protocol == PROTO_UNSPECIFIED) {
+ cts->protocol = device->protocol;
+ cts->protocol_version = device->protocol_version;
+ }
+
+ if (cts->protocol == PROTO_ATA) {
+ ata = &cts->proto_specific.ata;
+ if ((ata->valid & CTS_ATA_VALID_TQ) == 0) {
+ ata->valid |= CTS_ATA_VALID_TQ;
+ if (cts->type == CTS_TYPE_USER_SETTINGS ||
+ (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 ||
+ (device->inq_flags & SID_CmdQue) != 0)
+ ata->flags |= CTS_ATA_FLAGS_TAG_ENB;
+ }
+ }
+ if (cts->protocol == PROTO_SCSI) {
+ scsi = &cts->proto_specific.scsi;
+ if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) {
+ scsi->valid |= CTS_SCSI_VALID_TQ;
+ if (cts->type == CTS_TYPE_USER_SETTINGS ||
+ (device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 ||
+ (device->inq_flags & SID_CmdQue) != 0)
+ scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
+ }
+ }
+
+ if (cts->transport == XPORT_UNKNOWN ||
+ cts->transport == XPORT_UNSPECIFIED) {
+ cts->transport = device->transport;
+ cts->transport_version = device->transport_version;
+ }
+}
+
+static void
ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
int async_update)
{
struct ccb_pathinq cpi;
- struct ccb_trans_settings cur_cts;
+ struct ccb_trans_settings_ata *ata;
struct ccb_trans_settings_scsi *scsi;
- struct ccb_trans_settings_scsi *cur_scsi;
struct cam_sim *sim;
+ struct ata_params *ident_data;
struct scsi_inquiry_data *inq_data;
if (device == NULL) {
@@ -1773,95 +1882,63 @@
}
sim = cts->ccb_h.path->bus->sim;
-
- /*
- * Nothing more of interest to do unless
- * this is a device connected via the
- * SCSI protocol.
- */
- if (cts->protocol != PROTO_SCSI) {
- if (async_update == FALSE)
- (*(sim->sim_action))(sim, (union ccb *)cts);
- return;
- }
-
+ ident_data = &device->ident_data;
inq_data = &device->inq_data;
- scsi = &cts->proto_specific.scsi;
+ if (cts->protocol == PROTO_ATA)
+ ata = &cts->proto_specific.ata;
+ else
+ ata = NULL;
+ if (cts->protocol == PROTO_SCSI)
+ scsi = &cts->proto_specific.scsi;
+ else
+ scsi = NULL;
xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
- /* SCSI specific sanity checking */
+ /* Sanity checking */
if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0
- || (INQ_DATA_TQ_ENABLED(inq_data)) == 0
+ || (ata && (ident_data->satacapabilities & ATA_SUPPORT_NCQ) == 0)
+ || (scsi && (INQ_DATA_TQ_ENABLED(inq_data)) == 0)
|| (device->queue_flags & SCP_QUEUE_DQUE) != 0
|| (device->mintags == 0)) {
/*
* Can't tag on hardware that doesn't support tags,
* doesn't have it enabled, or has broken tag support.
*/
- scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
- }
-
- if (async_update == FALSE) {
- /*
- * Perform sanity checking against what the
- * controller and device can do.
- */
- xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
- cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
- cur_cts.type = cts->type;
- xpt_action((union ccb *)&cur_cts);
- if ((cur_cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- return;
- }
- cur_scsi = &cur_cts.proto_specific.scsi;
- if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) {
- scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
- scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB;
- }
- if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0)
+ if (ata)
+ ata->flags &= ~CTS_ATA_FLAGS_TAG_ENB;
+ if (scsi)
scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
}
- if (cts->type == CTS_TYPE_CURRENT_SETTINGS
- && (scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
- int device_tagenb;
+ /* Start/stop tags use. */
+ if (cts->type == CTS_TYPE_CURRENT_SETTINGS &&
+ ((ata && (ata->valid & CTS_ATA_VALID_TQ) != 0) ||
+ (scsi && (scsi->valid & CTS_SCSI_VALID_TQ) != 0))) {
+ int nowt, newt = 0;
- /*
- * If we are transitioning from tags to no-tags or
- * vice-versa, we need to carefully freeze and restart
- * the queue so that we don't overlap tagged and non-tagged
- * commands. We also temporarily stop tags if there is
- * a change in transfer negotiation settings to allow
- * "tag-less" negotiation.
- */
- if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
- || (device->inq_flags & SID_CmdQue) != 0)
- device_tagenb = TRUE;
- else
- device_tagenb = FALSE;
+ nowt = ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 ||
+ (device->inq_flags & SID_CmdQue) != 0);
+ if (ata)
+ newt = (ata->flags & CTS_ATA_FLAGS_TAG_ENB) != 0;
+ if (scsi)
+ newt = (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0;
- if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0
- && device_tagenb == FALSE)
- || ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0
- && device_tagenb == TRUE)) {
+ if (newt && !nowt) {
+ /*
+ * Delay change to use tags until after a
+ * few commands have gone to this device so
+ * the controller has time to perform transfer
+ * negotiations without tagged messages getting
+ * in the way.
+ */
+ device->tag_delay_count = CAM_TAG_DELAY_COUNT;
+ device->flags |= CAM_DEV_TAG_AFTER_COUNT;
+ } else if (nowt && !newt)
+ xpt_stop_tags(cts->ccb_h.path);
+ }
- if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) {
- /*
- * Delay change to use tags until after a
- * few commands have gone to this device so
- * the controller has time to perform transfer
- * negotiations without tagged messages getting
- * in the way.
- */
- device->tag_delay_count = CAM_TAG_DELAY_COUNT;
- device->flags |= CAM_DEV_TAG_AFTER_COUNT;
- } else {
- xpt_stop_tags(cts->ccb_h.path);
- }
- }
- }
if (async_update == FALSE)
(*(sim->sim_action))(sim, (union ccb *)cts);
}
@@ -1951,11 +2028,11 @@
/* Report connection speed */
speed = cpi.base_transfer_speed;
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) {
- struct ccb_trans_settings_ata *ata =
+ struct ccb_trans_settings_pata *pata =
&cts.xport_specific.ata;
- if (ata->valid & CTS_ATA_VALID_MODE)
- speed = ata_mode2speed(ata->mode);
+ if (pata->valid & CTS_ATA_VALID_MODE)
+ speed = ata_mode2speed(pata->mode);
}
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) {
struct ccb_trans_settings_sata *sata =
@@ -1974,16 +2051,16 @@
periph->unit_number, speed);
/* Report additional information about connection */
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) {
- struct ccb_trans_settings_ata *ata =
+ struct ccb_trans_settings_pata *pata =
&cts.xport_specific.ata;
printf(" (");
- if (ata->valid & CTS_ATA_VALID_MODE)
- printf("%s, ", ata_mode2string(ata->mode));
- if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0)
- printf("ATAPI %dbytes, ", ata->atapi);
- if (ata->valid & CTS_ATA_VALID_BYTECOUNT)
- printf("PIO %dbytes", ata->bytecount);
+ if (pata->valid & CTS_ATA_VALID_MODE)
+ printf("%s, ", ata_mode2string(pata->mode));
+ if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
+ printf("ATAPI %dbytes, ", pata->atapi);
+ if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
+ printf("PIO %dbytes", pata->bytecount);
printf(")");
}
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) {
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/cam.h
--- a/head/sys/cam/cam.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/cam.h Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/cam/cam.h 236814 2012-06-09 13:07:44Z mav $
*/
#ifndef _CAM_CAM_H
@@ -108,6 +108,15 @@
CAM_RETRY_SELTO = 0x02 /* Retry Selection Timeouts */
} cam_flags;
+enum {
+ SF_RETRY_UA = 0x01, /* Retry UNIT ATTENTION conditions. */
+ SF_NO_PRINT = 0x02, /* Never print error status. */
+ SF_QUIET_IR = 0x04, /* Be quiet about Illegal Request reponses */
+ SF_PRINT_ALWAYS = 0x08, /* Always print error status. */
+ SF_NO_RECOVERY = 0x10, /* Don't do active error recovery. */
+ SF_NO_RETRY = 0x20 /* Don't do any retries. */
+};
+
/* CAM Status field values */
typedef enum {
CAM_REQ_INPROG, /* CCB request is in progress */
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/cam_ccb.h
--- a/head/sys/cam/cam_ccb.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/cam_ccb.h Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/cam/cam_ccb.h 230590 2012-01-26 18:09:28Z ken $
+ * $FreeBSD: head/sys/cam/cam_ccb.h 236437 2012-06-02 08:29:07Z mav $
*/
#ifndef _CAM_CAM_CCB_H
@@ -242,6 +242,7 @@
PROTO_ATA, /* AT Attachment */
PROTO_ATAPI, /* AT Attachment Packetized Interface */
PROTO_SATAPM, /* SATA Port Multiplier */
+ PROTO_SEMB, /* SATA Enclosure Management Bridge */
} cam_proto;
typedef enum {
@@ -843,6 +844,14 @@
#define CTS_SCSI_FLAGS_TAG_ENB 0x01
};
+struct ccb_trans_settings_ata
+{
+ u_int valid; /* Which fields to honor */
+#define CTS_ATA_VALID_TQ 0x01
+ u_int flags;
+#define CTS_ATA_FLAGS_TAG_ENB 0x01
+};
+
struct ccb_trans_settings_spi
{
u_int valid; /* Which fields to honor */
@@ -877,7 +886,7 @@
u_int32_t bitrate; /* Mbps */
};
-struct ccb_trans_settings_ata {
+struct ccb_trans_settings_pata {
u_int valid; /* Which fields to honor */
#define CTS_ATA_VALID_MODE 0x01
#define CTS_ATA_VALID_BYTECOUNT 0x02
@@ -923,6 +932,7 @@
u_int transport_version;
union {
u_int valid; /* Which fields to honor */
+ struct ccb_trans_settings_ata ata;
struct ccb_trans_settings_scsi scsi;
} proto_specific;
union {
@@ -930,7 +940,7 @@
struct ccb_trans_settings_spi spi;
struct ccb_trans_settings_fc fc;
struct ccb_trans_settings_sas sas;
- struct ccb_trans_settings_ata ata;
+ struct ccb_trans_settings_pata ata;
struct ccb_trans_settings_sata sata;
} xport_specific;
};
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/cam_debug.h
--- a/head/sys/cam/cam_debug.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/cam_debug.h Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/cam/cam_debug.h 236712 2012-06-07 10:05:51Z mav $
*/
#ifndef _CAM_CAM_DEBUG_H
#define _CAM_CAM_DEBUG_H 1
@@ -44,7 +44,35 @@
CAM_DEBUG_PROBE = 0x40 /* print out probe actions */
} cam_debug_flags;
-#if defined(CAMDEBUG) && defined(_KERNEL)
+#if defined(_KERNEL)
+
+#ifndef CAM_DEBUG_FLAGS
+#define CAM_DEBUG_FLAGS CAM_DEBUG_NONE
+#endif
+
+#ifndef CAM_DEBUG_COMPILE
+#ifdef CAMDEBUG
+#define CAM_DEBUG_COMPILE (-1)
+#else
+#define CAM_DEBUG_COMPILE (CAM_DEBUG_INFO | CAM_DEBUG_CDB | \
+ CAM_DEBUG_PERIPH | CAM_DEBUG_PROBE | \
+ CAM_DEBUG_FLAGS)
+#endif
+#endif
+
+#ifndef CAM_DEBUG_BUS
+#define CAM_DEBUG_BUS (-1)
+#endif
+#ifndef CAM_DEBUG_TARGET
+#define CAM_DEBUG_TARGET (-1)
+#endif
+#ifndef CAM_DEBUG_LUN
+#define CAM_DEBUG_LUN (-1)
+#endif
+
+#ifndef CAM_DEBUG_DELAY
+#define CAM_DEBUG_DELAY 0
+#endif
/* Path we want to debug */
extern struct cam_path *cam_dpath;
@@ -52,48 +80,48 @@
extern u_int32_t cam_dflags;
/* Printf delay value (to prevent scrolling) */
extern u_int32_t cam_debug_delay;
-
+
/* Debugging macros. */
#define CAM_DEBUGGED(path, flag) \
- ((cam_dflags & (flag)) \
+ (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags) \
&& (cam_dpath != NULL) \
&& (xpt_path_comp(cam_dpath, path) >= 0) \
&& (xpt_path_comp(cam_dpath, path) < 2))
#define CAM_DEBUG(path, flag, printfargs) \
- if ((cam_dflags & (flag)) \
+ if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags) \
&& (cam_dpath != NULL) \
&& (xpt_path_comp(cam_dpath, path) >= 0) \
&& (xpt_path_comp(cam_dpath, path) < 2)) { \
xpt_print_path(path); \
- printf printfargs; \
+ printf printfargs; \
if (cam_debug_delay != 0) \
DELAY(cam_debug_delay); \
}
#define CAM_DEBUG_PRINT(flag, printfargs) \
- if (cam_dflags & (flag)) { \
+ if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) { \
printf("cam_debug: "); \
- printf printfargs; \
+ printf printfargs; \
if (cam_debug_delay != 0) \
DELAY(cam_debug_delay); \
}
#define CAM_DEBUG_PATH_PRINT(flag, path, printfargs) \
- if (cam_dflags & (flag)) { \
+ if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) { \
xpt_print(path, "cam_debug: "); \
- printf printfargs; \
+ printf printfargs; \
if (cam_debug_delay != 0) \
DELAY(cam_debug_delay); \
}
-#else /* !CAMDEBUG || !_KERNEL */
+#else /* !_KERNEL */
#define CAM_DEBUGGED(A, B) 0
#define CAM_DEBUG(A, B, C)
#define CAM_DEBUG_PRINT(A, B)
#define CAM_DEBUG_PATH_PRINT(A, B, C)
-#endif /* CAMDEBUG && _KERNEL */
+#endif /* _KERNEL */
#endif /* _CAM_CAM_DEBUG_H */
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/cam_periph.c
--- a/head/sys/cam/cam_periph.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/cam_periph.c Wed Jul 25 16:45:04 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/cam_periph.c 230544 2012-01-25 17:58:47Z ken $");
+__FBSDID("$FreeBSD: head/sys/cam/cam_periph.c 237682 2012-06-28 03:36:13Z ken $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -69,18 +69,22 @@
union ccb *done_ccb);
static void camperiphfree(struct cam_periph *periph);
static int camperiphscsistatuserror(union ccb *ccb,
+ union ccb **orig_ccb,
cam_flags camflags,
u_int32_t sense_flags,
int *openings,
u_int32_t *relsim_flags,
u_int32_t *timeout,
+ int *print,
const char **action_string);
static int camperiphscsisenseerror(union ccb *ccb,
+ union ccb **orig_ccb,
cam_flags camflags,
u_int32_t sense_flags,
int *openings,
u_int32_t *relsim_flags,
u_int32_t *timeout,
+ int *print,
const char **action_string);
static int nperiph_drivers;
@@ -240,6 +244,7 @@
goto failure;
init_level++;
+ CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph created\n"));
status = periph_ctor(periph, arg);
@@ -252,7 +257,8 @@
/* Initialized successfully */
break;
case 3:
- xpt_remove_periph(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph destroyed\n"));
+ xpt_remove_periph(periph, /*topology_lock_held*/ 0);
/* FALLTHROUGH */
case 2:
xpt_lock_buses();
@@ -267,7 +273,7 @@
/* No cleanup to perform. */
break;
default:
- panic("cam_periph_alloc: Unkown init level");
+ panic("%s: Unknown init level", __func__);
}
return(status);
}
@@ -434,6 +440,10 @@
cam_periph_release_locked(periph);
return (error);
}
+ if (periph->flags & CAM_PERIPH_INVALID) {
+ cam_periph_release_locked(periph);
+ return (ENXIO);
+ }
}
periph->flags |= CAM_PERIPH_LOCKED;
@@ -572,6 +582,7 @@
cam_periph_invalidate(struct cam_periph *periph)
{
+ CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph invalidated\n"));
/*
* We only call this routine the first time a peripheral is
* invalidated.
@@ -603,13 +614,39 @@
return;
}
+ /*
+ * The peripheral destructor semantics dictate calling with only the
+ * SIM mutex held. Since it might sleep, it should not be called
+ * with the topology lock held.
+ */
+ xpt_unlock_buses();
+
+ /*
+ * We need to call the peripheral destructor prior to removing the
+ * peripheral from the list. Otherwise, we risk running into a
+ * scenario where the peripheral unit number may get reused
+ * (because it has been removed from the list), but some resources
+ * used by the peripheral are still hanging around. In particular,
+ * the devfs nodes used by some peripherals like the pass(4) driver
+ * aren't fully cleaned up until the destructor is run. If the
+ * unit number is reused before the devfs instance is fully gone,
+ * devfs will panic.
+ */
+ if (periph->periph_dtor != NULL)
+ periph->periph_dtor(periph);
+
+ /*
+ * The peripheral list is protected by the topology lock.
+ */
+ xpt_lock_buses();
+
TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links);
(*p_drv)->generation++;
+
+ xpt_remove_periph(periph, /*topology_lock_held*/ 1);
+
xpt_unlock_buses();
-
- if (periph->periph_dtor != NULL)
- periph->periph_dtor(periph);
- xpt_remove_periph(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph destroyed\n"));
if (periph->flags & CAM_PERIPH_NEW_DEV_FOUND) {
union ccb ccb;
@@ -1104,107 +1141,52 @@
}
#define saved_ccb_ptr ppriv_ptr0
-#define recovery_depth ppriv_field1
-static void
-camperiphsensedone(struct cam_periph *periph, union ccb *done_ccb)
-{
- union ccb *saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr;
- cam_status status;
- int frozen = 0;
- int depth = done_ccb->ccb_h.recovery_depth;
-
- status = done_ccb->ccb_h.status;
- if (status & CAM_DEV_QFRZN) {
- frozen = 1;
- /*
- * Clear freeze flag now for case of retry,
- * freeze will be dropped later.
- */
- done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
- }
- status &= CAM_STATUS_MASK;
- switch (status) {
- case CAM_REQ_CMP:
- {
- int error_code, sense_key, asc, ascq;
-
- scsi_extract_sense_len(&saved_ccb->csio.sense_data,
- saved_ccb->csio.sense_len -
- saved_ccb->csio.sense_resid,
- &error_code, &sense_key, &asc, &ascq,
- /*show_errors*/ 1);
- /*
- * If we manually retrieved sense into a CCB and got
- * something other than "NO SENSE" send the updated CCB
- * back to the client via xpt_done() to be processed via
- * the error recovery code again.
- */
- if ((sense_key != -1)
- && (sense_key != SSD_KEY_NO_SENSE)) {
- saved_ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
- } else {
- saved_ccb->ccb_h.status &= ~CAM_STATUS_MASK;
- saved_ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
- }
- saved_ccb->csio.sense_resid = done_ccb->csio.resid;
- bcopy(saved_ccb, done_ccb, sizeof(union ccb));
- xpt_free_ccb(saved_ccb);
- break;
- }
- default:
- bcopy(saved_ccb, done_ccb, sizeof(union ccb));
- xpt_free_ccb(saved_ccb);
- done_ccb->ccb_h.status &= ~CAM_STATUS_MASK;
- done_ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
- break;
- }
- periph->flags &= ~CAM_PERIPH_SENSE_INPROG;
- /*
- * If it is the end of recovery, drop freeze, taken due to
- * CAM_DEV_QFREEZE flag, set on recovery request.
- */
- if (depth == 0) {
- cam_release_devq(done_ccb->ccb_h.path,
- /*relsim_flags*/0,
- /*openings*/0,
- /*timeout*/0,
- /*getcount_only*/0);
- }
- /*
- * Copy frozen flag from recovery request if it is set there
- * for some reason.
- */
- if (frozen != 0)
- done_ccb->ccb_h.status |= CAM_DEV_QFRZN;
- (*done_ccb->ccb_h.cbfcnp)(periph, done_ccb);
-}
-
static void
camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
{
- union ccb *saved_ccb, *save_ccb;
+ union ccb *saved_ccb;
cam_status status;
- int frozen = 0;
struct scsi_start_stop_unit *scsi_cmd;
- u_int32_t relsim_flags, timeout;
+ int error_code, sense_key, asc, ascq;
+ scsi_cmd = (struct scsi_start_stop_unit *)
+ &done_ccb->csio.cdb_io.cdb_bytes;
status = done_ccb->ccb_h.status;
- if (status & CAM_DEV_QFRZN) {
- frozen = 1;
- /*
- * Clear freeze flag now for case of retry,
- * freeze will be dropped later.
- */
- done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
- }
- timeout = 0;
- relsim_flags = 0;
- saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr;
-
- switch (status & CAM_STATUS_MASK) {
- case CAM_REQ_CMP:
- {
+ if ((status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ if (scsi_extract_sense_ccb(done_ccb,
+ &error_code, &sense_key, &asc, &ascq)) {
+ /*
+ * If the error is "invalid field in CDB",
+ * and the load/eject flag is set, turn the
+ * flag off and try again. This is just in
+ * case the drive in question barfs on the
+ * load eject flag. The CAM code should set
+ * the load/eject flag by default for
+ * removable media.
+ */
+ if ((scsi_cmd->opcode == START_STOP_UNIT) &&
+ ((scsi_cmd->how & SSS_LOEJ) != 0) &&
+ (asc == 0x24) && (ascq == 0x00)) {
+ scsi_cmd->how &= ~SSS_LOEJ;
+ if (status & CAM_DEV_QFRZN) {
+ cam_release_devq(done_ccb->ccb_h.path,
+ 0, 0, 0, 0);
+ done_ccb->ccb_h.status &=
+ ~CAM_DEV_QFRZN;
+ }
+ xpt_action(done_ccb);
+ goto out;
+ }
+ }
+ if (cam_periph_error(done_ccb,
+ 0, SF_RETRY_UA | SF_NO_PRINT, NULL) == ERESTART)
+ goto out;
+ if (done_ccb->ccb_h.status & CAM_DEV_QFRZN) {
+ cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0);
+ done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
+ }
+ } else {
/*
* If we have successfully taken a device from the not
* ready to ready state, re-scan the device and re-get
@@ -1212,147 +1194,24 @@
* don't properly report their inquiry information unless
* they are spun up.
*/
- scsi_cmd = (struct scsi_start_stop_unit *)
- &done_ccb->csio.cdb_io.cdb_bytes;
-
- if (scsi_cmd->opcode == START_STOP_UNIT)
- xpt_async(AC_INQ_CHANGED,
- done_ccb->ccb_h.path, NULL);
- goto final;
- }
- case CAM_SCSI_STATUS_ERROR:
- scsi_cmd = (struct scsi_start_stop_unit *)
- &done_ccb->csio.cdb_io.cdb_bytes;
- if (status & CAM_AUTOSNS_VALID) {
- struct ccb_getdev cgd;
- struct scsi_sense_data *sense;
- int error_code, sense_key, asc, ascq, sense_len;
- scsi_sense_action err_action;
-
- sense = &done_ccb->csio.sense_data;
- sense_len = done_ccb->csio.sense_len -
- done_ccb->csio.sense_resid;
- scsi_extract_sense_len(sense, sense_len, &error_code,
- &sense_key, &asc, &ascq,
- /*show_errors*/ 1);
- /*
- * Grab the inquiry data for this device.
- */
- xpt_setup_ccb(&cgd.ccb_h, done_ccb->ccb_h.path,
- CAM_PRIORITY_NORMAL);
- cgd.ccb_h.func_code = XPT_GDEV_TYPE;
- xpt_action((union ccb *)&cgd);
- err_action = scsi_error_action(&done_ccb->csio,
- &cgd.inq_data, 0);
- /*
- * If the error is "invalid field in CDB",
- * and the load/eject flag is set, turn the
- * flag off and try again. This is just in
- * case the drive in question barfs on the
- * load eject flag. The CAM code should set
- * the load/eject flag by default for
- * removable media.
- */
- /* XXX KDM
- * Should we check to see what the specific
- * scsi status is?? Or does it not matter
- * since we already know that there was an
- * error, and we know what the specific
- * error code was, and we know what the
- * opcode is..
- */
- if ((scsi_cmd->opcode == START_STOP_UNIT) &&
- ((scsi_cmd->how & SSS_LOEJ) != 0) &&
- (asc == 0x24) && (ascq == 0x00) &&
- (done_ccb->ccb_h.retry_count > 0)) {
-
- scsi_cmd->how &= ~SSS_LOEJ;
- xpt_action(done_ccb);
- } else if ((done_ccb->ccb_h.retry_count > 1)
- && ((err_action & SS_MASK) != SS_FAIL)) {
-
- /*
- * In this case, the error recovery
- * command failed, but we've got
- * some retries left on it. Give
- * it another try unless this is an
- * unretryable error.
- */
- /* set the timeout to .5 sec */
- relsim_flags =
- RELSIM_RELEASE_AFTER_TIMEOUT;
- timeout = 500;
- xpt_action(done_ccb);
- break;
- } else {
- /*
- * Perform the final retry with the original
- * CCB so that final error processing is
- * performed by the owner of the CCB.
- */
- goto final;
- }
- } else {
- save_ccb = xpt_alloc_ccb_nowait();
- if (save_ccb == NULL)
- goto final;
- bcopy(done_ccb, save_ccb, sizeof(*save_ccb));
- periph->flags |= CAM_PERIPH_SENSE_INPROG;
- /*
- * Send a Request Sense to the device. We
- * assume that we are in a contingent allegiance
- * condition so we do not tag this request.
- */
- scsi_request_sense(&done_ccb->csio, /*retries*/1,
- camperiphsensedone,
- &save_ccb->csio.sense_data,
- save_ccb->csio.sense_len,
- CAM_TAG_ACTION_NONE,
- /*sense_len*/SSD_FULL_SIZE,
- /*timeout*/5000);
- done_ccb->ccb_h.pinfo.priority--;
- done_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
- done_ccb->ccb_h.saved_ccb_ptr = save_ccb;
- done_ccb->ccb_h.recovery_depth++;
- xpt_action(done_ccb);
- }
- break;
- default:
-final:
- bcopy(saved_ccb, done_ccb, sizeof(*done_ccb));
- xpt_free_ccb(saved_ccb);
- periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
- xpt_action(done_ccb);
- break;
+ if (scsi_cmd->opcode == START_STOP_UNIT)
+ xpt_async(AC_INQ_CHANGED, done_ccb->ccb_h.path, NULL);
}
- /* decrement the retry count */
/*
- * XXX This isn't appropriate in all cases. Restructure,
- * so that the retry count is only decremented on an
- * actual retry. Remeber that the orignal ccb had its
- * retry count dropped before entering recovery, so
- * doing it again is a bug.
+ * Perform the final retry with the original CCB so that final
+ * error processing is performed by the owner of the CCB.
*/
- if (done_ccb->ccb_h.retry_count > 0)
- done_ccb->ccb_h.retry_count--;
- /*
- * Drop freeze taken due to CAM_DEV_QFREEZE flag set on recovery
- * request.
- */
- cam_release_devq(done_ccb->ccb_h.path,
- /*relsim_flags*/relsim_flags,
- /*openings*/0,
- /*timeout*/timeout,
- /*getcount_only*/0);
- /* Drop freeze taken, if this recovery request got error. */
- if (frozen != 0) {
- cam_release_devq(done_ccb->ccb_h.path,
- /*relsim_flags*/0,
- /*openings*/0,
- /*timeout*/0,
- /*getcount_only*/0);
- }
+ saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr;
+ bcopy(saved_ccb, done_ccb, sizeof(*done_ccb));
+ xpt_free_ccb(saved_ccb);
+ if (done_ccb->ccb_h.cbfcnp != camperiphdone)
+ periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
+ xpt_action(done_ccb);
+
+out:
+ /* Drop freeze taken due to CAM_DEV_QFREEZE flag set. */
+ cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0);
}
/*
@@ -1411,10 +1270,10 @@
}
static int
-camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
- u_int32_t sense_flags,
- int *openings, u_int32_t *relsim_flags,
- u_int32_t *timeout, const char **action_string)
+camperiphscsistatuserror(union ccb *ccb, union ccb **orig_ccb,
+ cam_flags camflags, u_int32_t sense_flags,
+ int *openings, u_int32_t *relsim_flags,
+ u_int32_t *timeout, int *print, const char **action_string)
{
int error;
@@ -1427,14 +1286,13 @@
break;
case SCSI_STATUS_CMD_TERMINATED:
case SCSI_STATUS_CHECK_COND:
- if (bootverbose)
- xpt_print(ccb->ccb_h.path, "SCSI status error\n");
- error = camperiphscsisenseerror(ccb,
+ error = camperiphscsisenseerror(ccb, orig_ccb,
camflags,
sense_flags,
openings,
relsim_flags,
timeout,
+ print,
action_string);
break;
case SCSI_STATUS_QUEUE_FULL:
@@ -1489,9 +1347,7 @@
}
*timeout = 0;
error = ERESTART;
- if (bootverbose) {
- xpt_print(ccb->ccb_h.path, "Queue full\n");
- }
+ *print = 0;
break;
}
/* FALLTHROUGH */
@@ -1501,9 +1357,6 @@
* Restart the queue after either another
* command completes or a 1 second timeout.
*/
- if (bootverbose) {
- xpt_print(ccb->ccb_h.path, "Device busy\n");
- }
if (ccb->ccb_h.retry_count > 0) {
ccb->ccb_h.retry_count--;
error = ERESTART;
@@ -1515,12 +1368,7 @@
}
break;
case SCSI_STATUS_RESERV_CONFLICT:
- xpt_print(ccb->ccb_h.path, "Reservation conflict\n");
- error = EIO;
- break;
default:
- xpt_print(ccb->ccb_h.path, "SCSI status 0x%x\n",
- ccb->csio.scsi_status);
error = EIO;
break;
}
@@ -1528,18 +1376,18 @@
}
static int
-camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
- u_int32_t sense_flags,
- int *openings, u_int32_t *relsim_flags,
- u_int32_t *timeout, const char **action_string)
+camperiphscsisenseerror(union ccb *ccb, union ccb **orig,
+ cam_flags camflags, u_int32_t sense_flags,
+ int *openings, u_int32_t *relsim_flags,
+ u_int32_t *timeout, int *print, const char **action_string)
{
struct cam_periph *periph;
union ccb *orig_ccb = ccb;
- int error;
+ int error, recoveryccb;
periph = xpt_path_periph(ccb->ccb_h.path);
- if (periph->flags &
- (CAM_PERIPH_RECOVERY_INPROG | CAM_PERIPH_SENSE_INPROG)) {
+ recoveryccb = (ccb->ccb_h.cbfcnp == camperiphdone);
+ if ((periph->flags & CAM_PERIPH_RECOVERY_INPROG) && !recoveryccb) {
/*
* If error recovery is already in progress, don't attempt
* to process this error, but requeue it unconditionally
@@ -1554,6 +1402,7 @@
* imperitive that we don't violate this assumption.
*/
error = ERESTART;
+ *print = 0;
} else {
scsi_sense_action err_action;
struct ccb_getdev cgd;
@@ -1565,16 +1414,34 @@
cgd.ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action((union ccb *)&cgd);
- if ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)
- err_action = scsi_error_action(&ccb->csio,
- &cgd.inq_data,
- sense_flags);
- else if ((ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0)
- err_action = SS_REQSENSE;
- else
- err_action = SS_RETRY|SSQ_DECREMENT_COUNT|EIO;
+ err_action = scsi_error_action(&ccb->csio, &cgd.inq_data,
+ sense_flags);
+ error = err_action & SS_ERRMASK;
- error = err_action & SS_ERRMASK;
+ /*
+ * Do not autostart sequential access devices
+ * to avoid unexpected tape loading.
+ */
+ if ((err_action & SS_MASK) == SS_START &&
+ SID_TYPE(&cgd.inq_data) == T_SEQUENTIAL) {
+ *action_string = "Will not autostart a "
+ "sequential access device";
+ goto sense_error_done;
+ }
+
+ /*
+ * Avoid recovery recursion if recovery action is the same.
+ */
+ if ((err_action & SS_MASK) >= SS_START && recoveryccb) {
+ if (((err_action & SS_MASK) == SS_START &&
+ ccb->csio.cdb_io.cdb_bytes[0] == START_STOP_UNIT) ||
+ ((err_action & SS_MASK) == SS_TUR &&
+ (ccb->csio.cdb_io.cdb_bytes[0] == TEST_UNIT_READY))) {
+ err_action = SS_RETRY|SSQ_DECREMENT_COUNT|EIO;
+ *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT;
+ *timeout = 500;
+ }
+ }
/*
* If the recovery action will consume a retry,
@@ -1623,15 +1490,6 @@
case SS_START:
{
int le;
- if (SID_TYPE(&cgd.inq_data) == T_SEQUENTIAL) {
- xpt_free_ccb(orig_ccb);
- ccb->ccb_h.status |= CAM_DEV_QFRZN;
- *action_string = "Will not autostart a "
- "sequential access device";
- err_action = SS_FAIL;
- error = EIO;
- break;
- }
/*
* Send a start unit command to the device, and
@@ -1695,24 +1553,6 @@
*timeout = 500;
break;
}
- case SS_REQSENSE:
- {
- *action_string = "Requesting SCSI sense data";
- periph->flags |= CAM_PERIPH_SENSE_INPROG;
- /*
- * Send a Request Sense to the device. We
- * assume that we are in a contingent allegiance
- * condition so we do not tag this request.
- */
- scsi_request_sense(&ccb->csio, /*retries*/1,
- camperiphsensedone,
- &orig_ccb->csio.sense_data,
- orig_ccb->csio.sense_len,
- CAM_TAG_ACTION_NONE,
- /*sense_len*/SSD_FULL_SIZE,
- /*timeout*/5000);
- break;
- }
default:
panic("Unhandled error action %x", err_action);
}
@@ -1729,14 +1569,12 @@
ccb->ccb_h.pinfo.priority--;
ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
ccb->ccb_h.saved_ccb_ptr = orig_ccb;
- ccb->ccb_h.recovery_depth = 0;
error = ERESTART;
+ *orig = orig_ccb;
}
sense_error_done:
- if ((err_action & SSQ_PRINT_SENSE) != 0
- && (ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)
- cam_error_print(orig_ccb, CAM_ESF_ALL, CAM_EPF_ALL);
+ *print = ((err_action & SSQ_PRINT_SENSE) != 0);
}
return (error);
}
@@ -1750,87 +1588,35 @@
cam_periph_error(union ccb *ccb, cam_flags camflags,
u_int32_t sense_flags, union ccb *save_ccb)
{
+ union ccb *orig_ccb;
struct cam_periph *periph;
const char *action_string;
cam_status status;
- int frozen;
- int error, printed = 0;
- int openings;
- u_int32_t relsim_flags;
- u_int32_t timeout = 0;
+ int frozen, error, openings, print, lost_device;
+ u_int32_t relsim_flags, timeout;
+ print = 1;
periph = xpt_path_periph(ccb->ccb_h.path);
action_string = NULL;
status = ccb->ccb_h.status;
frozen = (status & CAM_DEV_QFRZN) != 0;
status &= CAM_STATUS_MASK;
- openings = relsim_flags = 0;
+ openings = relsim_flags = timeout = lost_device = 0;
+ orig_ccb = ccb;
switch (status) {
case CAM_REQ_CMP:
error = 0;
+ print = 0;
break;
case CAM_SCSI_STATUS_ERROR:
- error = camperiphscsistatuserror(ccb,
- camflags,
- sense_flags,
- &openings,
- &relsim_flags,
- &timeout,
- &action_string);
+ error = camperiphscsistatuserror(ccb, &orig_ccb,
+ camflags, sense_flags, &openings, &relsim_flags,
+ &timeout, &print, &action_string);
break;
case CAM_AUTOSENSE_FAIL:
- xpt_print(ccb->ccb_h.path, "AutoSense failed\n");
error = EIO; /* we have to kill the command */
break;
- case CAM_ATA_STATUS_ERROR:
- if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path, "ATA status error\n");
- cam_error_print(ccb, CAM_ESF_ALL, CAM_EPF_ALL);
- printed++;
- }
- /* FALLTHROUGH */
- case CAM_REQ_CMP_ERR:
- if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path,
- "Request completed with CAM_REQ_CMP_ERR\n");
- printed++;
- }
- /* FALLTHROUGH */
- case CAM_CMD_TIMEOUT:
- if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path, "Command timed out\n");
- printed++;
- }
- /* FALLTHROUGH */
- case CAM_UNEXP_BUSFREE:
- if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path, "Unexpected Bus Free\n");
- printed++;
- }
- /* FALLTHROUGH */
- case CAM_UNCOR_PARITY:
- if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path,
- "Uncorrected parity error\n");
- printed++;
- }
- /* FALLTHROUGH */
- case CAM_DATA_RUN_ERR:
- if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path, "Data overrun\n");
- printed++;
- }
- /* decrement the number of retries */
- if (ccb->ccb_h.retry_count > 0 &&
- (periph->flags & CAM_PERIPH_INVALID) == 0) {
- ccb->ccb_h.retry_count--;
- error = ERESTART;
- } else {
- action_string = "Retries exhausted";
- error = EIO;
- }
- break;
case CAM_UA_ABORT:
case CAM_UA_TERMIO:
case CAM_MSG_REJECT_REC:
@@ -1841,14 +1627,8 @@
if ((camflags & CAM_RETRY_SELTO) != 0) {
if (ccb->ccb_h.retry_count > 0 &&
(periph->flags & CAM_PERIPH_INVALID) == 0) {
-
ccb->ccb_h.retry_count--;
error = ERESTART;
- if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path,
- "Selection timeout\n");
- printed++;
- }
/*
* Wait a bit to give the device
@@ -1862,38 +1642,10 @@
}
/* FALLTHROUGH */
case CAM_DEV_NOT_THERE:
- {
- struct cam_path *newpath;
- lun_id_t lun_id;
-
error = ENXIO;
-
- /*
- * For a selection timeout, we consider all of the LUNs on
- * the target to be gone. If the status is CAM_DEV_NOT_THERE,
- * then we only get rid of the device(s) specified by the
- * path in the original CCB.
- */
- if (status == CAM_DEV_NOT_THERE)
- lun_id = xpt_path_lun_id(ccb->ccb_h.path);
- else
- lun_id = CAM_LUN_WILDCARD;
-
- /* Should we do more if we can't create the path?? */
- if (xpt_create_path(&newpath, periph,
- xpt_path_path_id(ccb->ccb_h.path),
- xpt_path_target_id(ccb->ccb_h.path),
- lun_id) != CAM_REQ_CMP)
- break;
-
- /*
- * Let peripheral drivers know that this device has gone
- * away.
- */
- xpt_async(AC_LOST_DEVICE, newpath, NULL);
- xpt_free_path(newpath);
+ print = 0;
+ lost_device = 1;
break;
- }
case CAM_REQ_INVALID:
case CAM_PATH_INVALID:
case CAM_NO_HBA:
@@ -1913,26 +1665,17 @@
* these events and should be unconditionally
* retried.
*/
- if (bootverbose && printed == 0) {
- xpt_print_path(ccb->ccb_h.path);
- if (status == CAM_BDR_SENT)
- printf("Bus Device Reset sent\n");
- else
- printf("Bus Reset issued\n");
- printed++;
- }
- /* FALLTHROUGH */
case CAM_REQUEUE_REQ:
- /* Unconditional requeue */
- if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path, "Request requeued\n");
- printed++;
- }
- if ((periph->flags & CAM_PERIPH_INVALID) == 0)
+ /* Unconditional requeue if device is still there */
+ if (periph->flags & CAM_PERIPH_INVALID) {
+ action_string = "Periph was invalidated";
+ error = EIO;
+ } else if (sense_flags & SF_NO_RETRY) {
+ error = EIO;
+ action_string = "Retry was blocked";
+ } else {
error = ERESTART;
- else {
- action_string = "Retries exhausted";
- error = EIO;
+ print = 0;
}
break;
case CAM_RESRC_UNAVAIL:
@@ -1946,30 +1689,37 @@
}
relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT;
/* FALLTHROUGH */
+ case CAM_ATA_STATUS_ERROR:
+ case CAM_REQ_CMP_ERR:
+ case CAM_CMD_TIMEOUT:
+ case CAM_UNEXP_BUSFREE:
+ case CAM_UNCOR_PARITY:
+ case CAM_DATA_RUN_ERR:
default:
- /* decrement the number of retries */
- if (ccb->ccb_h.retry_count > 0 &&
- (periph->flags & CAM_PERIPH_INVALID) == 0) {
+ if (periph->flags & CAM_PERIPH_INVALID) {
+ error = EIO;
+ action_string = "Periph was invalidated";
+ } else if (ccb->ccb_h.retry_count == 0) {
+ error = EIO;
+ action_string = "Retries exhausted";
+ } else if (sense_flags & SF_NO_RETRY) {
+ error = EIO;
+ action_string = "Retry was blocked";
+ } else {
ccb->ccb_h.retry_count--;
error = ERESTART;
- if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path, "CAM status 0x%x\n",
- status);
- printed++;
- }
- } else {
- error = EIO;
- action_string = "Retries exhausted";
}
break;
}
- /*
- * If we have and error and are booting verbosely, whine
- * *unless* this was a non-retryable selection timeout.
- */
- if (error != 0 && bootverbose &&
- !(status == CAM_SEL_TIMEOUT && (camflags & CAM_RETRY_SELTO) == 0)) {
+ if ((sense_flags & SF_PRINT_ALWAYS) ||
+ CAM_DEBUGGED(ccb->ccb_h.path, CAM_DEBUG_INFO))
+ print = 1;
+ else if (sense_flags & SF_NO_PRINT)
+ print = 0;
+ if (print)
+ cam_error_print(orig_ccb, CAM_ESF_ALL, CAM_EPF_ALL);
+ if (error != 0 && print) {
if (error != ERESTART) {
if (action_string == NULL)
action_string = "Unretryable error";
@@ -1981,6 +1731,36 @@
xpt_print(ccb->ccb_h.path, "Retrying command\n");
}
+ if (lost_device) {
+ struct cam_path *newpath;
+ lun_id_t lun_id;
+
+ /*
+ * For a selection timeout, we consider all of the LUNs on
+ * the target to be gone. If the status is CAM_DEV_NOT_THERE,
+ * then we only get rid of the device(s) specified by the
+ * path in the original CCB.
+ */
+ if (status == CAM_DEV_NOT_THERE)
+ lun_id = xpt_path_lun_id(ccb->ccb_h.path);
+ else
+ lun_id = CAM_LUN_WILDCARD;
+
+ /* Should we do more if we can't create the path?? */
+ if (xpt_create_path(&newpath, periph,
+ xpt_path_path_id(ccb->ccb_h.path),
+ xpt_path_target_id(ccb->ccb_h.path),
+ lun_id) == CAM_REQ_CMP) {
+
+ /*
+ * Let peripheral drivers know that this
+ * device has gone away.
+ */
+ xpt_async(AC_LOST_DEVICE, newpath, NULL);
+ xpt_free_path(newpath);
+ }
+ }
+
/* Attempt a retry */
if (error == ERESTART || error == 0) {
if (frozen != 0)
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/cam_periph.h
--- a/head/sys/cam/cam_periph.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/cam_periph.h Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/cam/cam_periph.h 230000 2012-01-12 00:41:48Z ken $
+ * $FreeBSD: head/sys/cam/cam_periph.h 236814 2012-06-09 13:07:44Z mav $
*/
#ifndef _CAM_CAM_PERIPH_H
@@ -118,7 +118,6 @@
#define CAM_PERIPH_INVALID 0x08
#define CAM_PERIPH_NEW_DEV_FOUND 0x10
#define CAM_PERIPH_RECOVERY_INPROG 0x20
-#define CAM_PERIPH_SENSE_INPROG 0x40
#define CAM_PERIPH_FREE 0x80
u_int32_t immediate_priority;
u_int32_t refcount;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/cam_sim.h
--- a/head/sys/cam/cam_sim.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/cam_sim.h Wed Jul 25 16:45:04 2012 +0300
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/cam/cam_sim.h 227637 2011-11-17 21:07:56Z mav $
+ * $FreeBSD: head/sys/cam/cam_sim.h 235333 2012-05-12 13:55:36Z mav $
*/
#ifndef _CAM_CAM_SIM_H
@@ -106,6 +106,7 @@
#define CAM_SIM_MPSAFE 0x02
#define CAM_SIM_ON_DONEQ 0x04
#define CAM_SIM_POLLED 0x08
+#define CAM_SIM_BATCH 0x10
struct callout callout;
struct cam_devq *devq; /* Device Queue to use for this SIM */
int refcount; /* References to the SIM. */
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/cam_xpt.c
--- a/head/sys/cam/cam_xpt.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/cam_xpt.c Wed Jul 25 16:45:04 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/cam_xpt.c 230590 2012-01-26 18:09:28Z ken $");
+__FBSDID("$FreeBSD: head/sys/cam/cam_xpt.c 237398 2012-06-21 14:35:46Z mav $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -188,21 +188,15 @@
};
/* Storage for debugging datastructures */
-#ifdef CAMDEBUG
struct cam_path *cam_dpath;
-#ifdef CAM_DEBUG_FLAGS
u_int32_t cam_dflags = CAM_DEBUG_FLAGS;
-#else
-u_int32_t cam_dflags = CAM_DEBUG_NONE;
-#endif
TUNABLE_INT("kern.cam.dflags", &cam_dflags);
SYSCTL_UINT(_kern_cam, OID_AUTO, dflags, CTLFLAG_RW,
- &cam_dflags, 0, "Cam Debug Flags");
-u_int32_t cam_debug_delay;
+ &cam_dflags, 0, "Enabled debug flags");
+u_int32_t cam_debug_delay = CAM_DEBUG_DELAY;
TUNABLE_INT("kern.cam.debug_delay", &cam_debug_delay);
SYSCTL_UINT(_kern_cam, OID_AUTO, debug_delay, CTLFLAG_RW,
- &cam_debug_delay, 0, "Cam Debug Flags");
-#endif
+ &cam_debug_delay, 0, "Delay in us after each debug message");
/* Our boot-time initialization hook */
static int cam_module_event_handler(module_t, int /*modeventtype_t*/, void *);
@@ -1032,7 +1026,7 @@
}
void
-xpt_remove_periph(struct cam_periph *periph)
+xpt_remove_periph(struct cam_periph *periph, int topology_lock_held)
{
struct cam_ed *device;
@@ -1053,9 +1047,13 @@
SLIST_REMOVE(periph_head, periph, cam_periph, periph_links);
}
- mtx_lock(&xsoftc.xpt_topo_lock);
+ if (topology_lock_held == 0)
+ mtx_lock(&xsoftc.xpt_topo_lock);
+
xsoftc.xpt_generation++;
- mtx_unlock(&xsoftc.xpt_topo_lock);
+
+ if (topology_lock_held == 0)
+ mtx_unlock(&xsoftc.xpt_topo_lock);
}
@@ -1080,6 +1078,9 @@
else if (path->device->protocol == PROTO_ATA ||
path->device->protocol == PROTO_SATAPM)
ata_print_ident(&path->device->ident_data);
+ else if (path->device->protocol == PROTO_SEMB)
+ semb_print_ident(
+ (struct sep_identify_data *)&path->device->ident_data);
else
printf("Unknown protocol device\n");
if (bootverbose && path->device->serial_num_len > 0) {
@@ -2469,9 +2470,7 @@
void
xpt_action_default(union ccb *start_ccb)
{
-#ifdef CAMDEBUG
char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
-#endif
struct cam_path *path;
path = start_ccb->ccb_h.path;
@@ -2902,17 +2901,13 @@
if ((crs->release_flags & RELSIM_ADJUST_OPENINGS) != 0) {
- if (INQ_DATA_TQ_ENABLED(&dev->inq_data)) {
- /* Don't ever go below one opening */
- if (crs->openings > 0) {
- xpt_dev_ccbq_resize(path,
- crs->openings);
-
- if (bootverbose) {
- xpt_print(path,
- "tagged openings now %d\n",
- crs->openings);
- }
+ /* Don't ever go below one opening */
+ if (crs->openings > 0) {
+ xpt_dev_ccbq_resize(path, crs->openings);
+ if (bootverbose) {
+ xpt_print(path,
+ "number of openings is now %d\n",
+ crs->openings);
}
}
}
@@ -2981,16 +2976,17 @@
break;
}
case XPT_DEBUG: {
-#ifdef CAMDEBUG
-#ifdef CAM_DEBUG_DELAY
- cam_debug_delay = CAM_DEBUG_DELAY;
-#endif
+ /* Check that all request bits are supported. */
+ if (start_ccb->cdbg.flags & ~(CAM_DEBUG_COMPILE)) {
+ start_ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
+ break;
+ }
+
cam_dflags = start_ccb->cdbg.flags;
if (cam_dpath != NULL) {
xpt_free_path(cam_dpath);
cam_dpath = NULL;
}
-
if (cam_dflags != CAM_DEBUG_NONE) {
if (xpt_create_path(&cam_dpath, xpt_periph,
start_ccb->ccb_h.path_id,
@@ -3008,9 +3004,6 @@
cam_dpath = NULL;
start_ccb->ccb_h.status = CAM_REQ_CMP;
}
-#else /* !CAMDEBUG */
- start_ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
-#endif /* CAMDEBUG */
break;
}
case XPT_FREEZE_QUEUE:
@@ -3227,13 +3220,8 @@
("running device %p\n", device));
drvq = &device->drvq;
-
-#ifdef CAMDEBUG
- if (drvq->entries <= 0) {
- panic("xpt_run_dev_allocq: "
- "Device on queue without any work to do");
- }
-#endif
+ KASSERT(drvq->entries > 0, ("xpt_run_dev_allocq: "
+ "Device on queue without any work to do"));
if ((work_ccb = xpt_get_ccb(device)) != NULL) {
devq->alloc_openings--;
devq->alloc_active++;
@@ -4049,6 +4037,28 @@
return (pathid);
}
+static const char *
+xpt_async_string(u_int32_t async_code)
+{
+
+ switch (async_code) {
+ case AC_BUS_RESET: return ("AC_BUS_RESET");
+ case AC_UNSOL_RESEL: return ("AC_UNSOL_RESEL");
+ case AC_SCSI_AEN: return ("AC_SCSI_AEN");
+ case AC_SENT_BDR: return ("AC_SENT_BDR");
+ case AC_PATH_REGISTERED: return ("AC_PATH_REGISTERED");
+ case AC_PATH_DEREGISTERED: return ("AC_PATH_DEREGISTERED");
+ case AC_FOUND_DEVICE: return ("AC_FOUND_DEVICE");
+ case AC_LOST_DEVICE: return ("AC_LOST_DEVICE");
+ case AC_TRANSFER_NEG: return ("AC_TRANSFER_NEG");
+ case AC_INQ_CHANGED: return ("AC_INQ_CHANGED");
+ case AC_GETDEV_CHANGED: return ("AC_GETDEV_CHANGED");
+ case AC_CONTRACT: return ("AC_CONTRACT");
+ case AC_ADVINFO_CHANGED: return ("AC_ADVINFO_CHANGED");
+ }
+ return ("AC_UNKNOWN");
+}
+
void
xpt_async(u_int32_t async_code, struct cam_path *path, void *async_arg)
{
@@ -4057,8 +4067,8 @@
struct cam_ed *device, *next_device;
mtx_assert(path->bus->sim->mtx, MA_OWNED);
-
- CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_async\n"));
+ CAM_DEBUG(path, CAM_DEBUG_TRACE | CAM_DEBUG_INFO,
+ ("xpt_async(%s)\n", xpt_async_string(async_code)));
/*
* Most async events come from a CAM interrupt context. In
@@ -4332,7 +4342,8 @@
TAILQ_INSERT_TAIL(&sim->sim_doneq, &done_ccb->ccb_h,
sim_links.tqe);
done_ccb->ccb_h.pinfo.index = CAM_DONEQ_INDEX;
- if ((sim->flags & (CAM_SIM_ON_DONEQ | CAM_SIM_POLLED)) == 0) {
+ if ((sim->flags & (CAM_SIM_ON_DONEQ | CAM_SIM_POLLED |
+ CAM_SIM_BATCH)) == 0) {
mtx_lock(&cam_simq_lock);
first = TAILQ_EMPTY(&cam_simq);
TAILQ_INSERT_TAIL(&cam_simq, sim, links);
@@ -4344,6 +4355,25 @@
}
}
+void
+xpt_batch_start(struct cam_sim *sim)
+{
+
+ KASSERT((sim->flags & CAM_SIM_BATCH) == 0, ("Batch flag already set"));
+ sim->flags |= CAM_SIM_BATCH;
+}
+
+void
+xpt_batch_done(struct cam_sim *sim)
+{
+
+ KASSERT((sim->flags & CAM_SIM_BATCH) != 0, ("Batch flag was not set"));
+ sim->flags &= ~CAM_SIM_BATCH;
+ if (!TAILQ_EMPTY(&sim->sim_doneq) &&
+ (sim->flags & CAM_SIM_ON_DONEQ) == 0)
+ camisr_runqueue(&sim->sim_doneq);
+}
+
union ccb *
xpt_alloc_ccb()
{
@@ -4696,6 +4726,7 @@
newopenings = min(device->maxtags,
sim->max_tagged_dev_openings);
xpt_dev_ccbq_resize(path, newopenings);
+ xpt_async(AC_GETDEV_CHANGED, path, NULL);
xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL);
crs.ccb_h.func_code = XPT_REL_SIMQ;
crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY;
@@ -4720,6 +4751,7 @@
xpt_freeze_devq(path, /*count*/1);
device->inq_flags &= ~SID_CmdQue;
xpt_dev_ccbq_resize(path, sim->max_dev_openings);
+ xpt_async(AC_GETDEV_CHANGED, path, NULL);
xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NORMAL);
crs.ccb_h.func_code = XPT_REL_SIMQ;
crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY;
@@ -4744,9 +4776,7 @@
* Now that interrupts are enabled, go find our devices
*/
-#ifdef CAMDEBUG
- /* Setup debugging flags and path */
-#ifdef CAM_DEBUG_BUS
+ /* Setup debugging path */
if (cam_dflags != CAM_DEBUG_NONE) {
/*
* Locking is specifically omitted here. No SIMs have
@@ -4763,10 +4793,6 @@
}
} else
cam_dpath = NULL;
-#else /* !CAM_DEBUG_BUS */
- cam_dpath = NULL;
-#endif /* CAM_DEBUG_BUS */
-#endif /* CAMDEBUG */
periphdriver_init(1);
xpt_hold_boot();
@@ -4839,7 +4865,8 @@
* attached. For any devices like that, announce the
* passthrough driver so the user will see something.
*/
- xpt_for_all_devices(xptpassannouncefunc, NULL);
+ if (!bootverbose)
+ xpt_for_all_devices(xptpassannouncefunc, NULL);
/* Release our hook so that the boot can continue. */
config_intrhook_disestablish(xsoftc.xpt_config_hook);
@@ -4978,8 +5005,8 @@
while ((sim = TAILQ_FIRST(&queue)) != NULL) {
TAILQ_REMOVE(&queue, sim, links);
CAM_SIM_LOCK(sim);
+ camisr_runqueue(&sim->sim_doneq);
sim->flags &= ~CAM_SIM_ON_DONEQ;
- camisr_runqueue(&sim->sim_doneq);
CAM_SIM_UNLOCK(sim);
}
mtx_lock(&cam_simq_lock);
@@ -5042,10 +5069,16 @@
ccb_h->path->bus->sim->devq->send_openings++;
runq = TRUE;
+ if (((dev->flags & CAM_DEV_REL_ON_QUEUE_EMPTY) != 0
+ && (dev->ccbq.dev_active == 0))) {
+ dev->flags &= ~CAM_DEV_REL_ON_QUEUE_EMPTY;
+ xpt_release_devq(ccb_h->path, /*count*/1,
+ /*run_queue*/FALSE);
+ }
+
if (((dev->flags & CAM_DEV_REL_ON_COMPLETE) != 0
- && (ccb_h->status&CAM_STATUS_MASK) != CAM_REQUEUE_REQ)
- || ((dev->flags & CAM_DEV_REL_ON_QUEUE_EMPTY) != 0
- && (dev->ccbq.dev_active == 0))) {
+ && (ccb_h->status&CAM_STATUS_MASK) != CAM_REQUEUE_REQ)) {
+ dev->flags &= ~CAM_DEV_REL_ON_COMPLETE;
xpt_release_devq(ccb_h->path, /*count*/1,
/*run_queue*/FALSE);
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/cam_xpt.h
--- a/head/sys/cam/cam_xpt.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/cam_xpt.h Wed Jul 25 16:45:04 2012 +0300
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/cam/cam_xpt.h 224806 2011-08-12 20:09:38Z mjacob $
+ * $FreeBSD: head/sys/cam/cam_xpt.h 236712 2012-06-07 10:05:51Z mav $
*/
#ifndef _CAM_CAM_XPT_H
@@ -63,28 +63,6 @@
SLIST_HEAD(async_list, async_node);
SLIST_HEAD(periph_list, cam_periph);
-#if defined(CAM_DEBUG_FLAGS) && !defined(CAMDEBUG)
-#error "You must have options CAMDEBUG to use options CAM_DEBUG_FLAGS"
-#endif
-
-/*
- * In order to enable the CAM_DEBUG_* options, the user must have CAMDEBUG
- * enabled. Also, the user must have either none, or all of CAM_DEBUG_BUS,
- * CAM_DEBUG_TARGET, and CAM_DEBUG_LUN specified.
- */
-#if defined(CAM_DEBUG_BUS) || defined(CAM_DEBUG_TARGET) \
- || defined(CAM_DEBUG_LUN)
-#ifdef CAMDEBUG
-#if !defined(CAM_DEBUG_BUS) || !defined(CAM_DEBUG_TARGET) \
- || !defined(CAM_DEBUG_LUN)
-#error "You must define all or none of CAM_DEBUG_BUS, CAM_DEBUG_TARGET \
- and CAM_DEBUG_LUN"
-#endif /* !CAM_DEBUG_BUS || !CAM_DEBUG_TARGET || !CAM_DEBUG_LUN */
-#else /* !CAMDEBUG */
-#error "You must use options CAMDEBUG if you use the CAM_DEBUG_* options"
-#endif /* CAMDEBUG */
-#endif /* CAM_DEBUG_BUS || CAM_DEBUG_TARGET || CAM_DEBUG_LUN */
-
void xpt_action(union ccb *new_ccb);
void xpt_action_default(union ccb *new_ccb);
union ccb *xpt_alloc_ccb(void);
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/cam_xpt_periph.h
--- a/head/sys/cam/cam_xpt_periph.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/cam_xpt_periph.h Wed Jul 25 16:45:04 2012 +0300
@@ -27,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/cam/cam_xpt_periph.h 237328 2012-06-20 17:08:00Z ken $
*/
#ifndef _CAM_CAM_XPT_PERIPH_H
@@ -42,7 +42,8 @@
void xpt_release_ccb(union ccb *released_ccb);
void xpt_schedule(struct cam_periph *perph, u_int32_t new_priority);
int32_t xpt_add_periph(struct cam_periph *periph);
-void xpt_remove_periph(struct cam_periph *periph);
+void xpt_remove_periph(struct cam_periph *periph,
+ int topology_lock_held);
void xpt_announce_periph(struct cam_periph *periph,
char *announce_string);
#endif
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/cam_xpt_sim.h
--- a/head/sys/cam/cam_xpt_sim.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/cam_xpt_sim.h Wed Jul 25 16:45:04 2012 +0300
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/cam/cam_xpt_sim.h 235333 2012-05-12 13:55:36Z mav $
*/
#ifndef _CAM_CAM_XPT_SIM_H
@@ -51,6 +51,8 @@
u_int count, int run_queue);
int xpt_sim_opened(struct cam_sim *sim);
void xpt_done(union ccb *done_ccb);
+void xpt_batch_start(struct cam_sim *sim);
+void xpt_batch_done(struct cam_sim *sim);
#endif
#endif /* _CAM_CAM_XPT_SIM_H */
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/ctl/ctl.c
--- a/head/sys/cam/ctl/ctl.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/ctl/ctl.c Wed Jul 25 16:45:04 2012 +0300
@@ -42,7 +42,7 @@
#define _CTL_C
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/ctl/ctl.c 233963 2012-04-06 22:23:13Z ken $");
+__FBSDID("$FreeBSD: head/sys/cam/ctl/ctl.c 237726 2012-06-28 19:39:30Z ken $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -308,7 +308,6 @@
/*aen_holdoff_period*/{0, 0}
};
-SYSCTL_NODE(_kern_cam, OID_AUTO, ctl, CTLFLAG_RD, 0, "CAM Target Layer");
/*
* XXX KDM move these into the softc.
@@ -318,7 +317,12 @@
static uint8_t ctl_pause_rtr;
static int ctl_is_single;
static int index_to_aps_page;
-
+int ctl_disable = 0;
+
+SYSCTL_NODE(_kern_cam, OID_AUTO, ctl, CTLFLAG_RD, 0, "CAM Target Layer");
+SYSCTL_INT(_kern_cam_ctl, OID_AUTO, disable, CTLFLAG_RDTUN, &ctl_disable, 0,
+ "Disable CTL");
+TUNABLE_INT("kern.cam.ctl.disable", &ctl_disable);
/*
* Serial number (0x80), device id (0x83), and supported pages (0x00)
@@ -949,6 +953,10 @@
ctl_pause_rtr = 0;
rcv_sync_msg = 0;
+ /* If we're disabled, don't initialize. */
+ if (ctl_disable != 0)
+ return;
+
control_softc = malloc(sizeof(*control_softc), M_DEVBUF, M_WAITOK);
softc = control_softc;
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/ctl/ctl_backend.c
--- a/head/sys/cam/ctl/ctl_backend.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/ctl/ctl_backend.c Wed Jul 25 16:45:04 2012 +0300
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/ctl/ctl_backend.c 233963 2012-04-06 22:23:13Z ken $");
+__FBSDID("$FreeBSD: head/sys/cam/ctl/ctl_backend.c 237726 2012-06-28 19:39:30Z ken $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -62,6 +62,7 @@
#include <cam/ctl/ctl_debug.h>
extern struct ctl_softc *control_softc;
+extern int ctl_disable;
int
ctl_backend_register(struct ctl_backend_driver *be)
@@ -71,6 +72,10 @@
ctl_softc = control_softc;
+ /* Don't continue if CTL is disabled */
+ if (ctl_disable != 0)
+ return (0);
+
mtx_lock(&ctl_softc->ctl_lock);
/*
* Sanity check, make sure this isn't a duplicate registration.
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/ctl/ctl_frontend_cam_sim.c
--- a/head/sys/cam/ctl/ctl_frontend_cam_sim.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/ctl/ctl_frontend_cam_sim.c Wed Jul 25 16:45:04 2012 +0300
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/ctl/ctl_frontend_cam_sim.c 231092 2012-02-06 18:11:00Z emaste $");
+__FBSDID("$FreeBSD: head/sys/cam/ctl/ctl_frontend_cam_sim.c 237726 2012-06-28 19:39:30Z ken $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -119,6 +119,7 @@
* amount of SCSI sense data that we will report to CAM.
*/
static int cfcs_max_sense = sizeof(struct scsi_sense_data);
+extern int ctl_disable;
SYSINIT(cfcs_init, SI_SUB_CONFIGURE, SI_ORDER_FOURTH, cfcs_init, NULL);
SYSCTL_NODE(_kern_cam, OID_AUTO, ctl2cam, CTLFLAG_RD, 0,
@@ -138,6 +139,10 @@
#endif
int retval;
+ /* Don't continue if CTL is disabled */
+ if (ctl_disable != 0)
+ return (0);
+
softc = &cfcs_softc;
retval = 0;
bzero(softc, sizeof(*softc));
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/ctl/ctl_frontend_internal.c
--- a/head/sys/cam/ctl/ctl_frontend_internal.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/ctl/ctl_frontend_internal.c Wed Jul 25 16:45:04 2012 +0300
@@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/ctl/ctl_frontend_internal.c 233963 2012-04-06 22:23:13Z ken $");
+__FBSDID("$FreeBSD: head/sys/cam/ctl/ctl_frontend_internal.c 237726 2012-06-28 19:39:30Z ken $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -187,6 +187,7 @@
MALLOC_DEFINE(M_CTL_CFI, "ctlcfi", "CTL CFI");
static struct cfi_softc fetd_internal_softc;
+extern int ctl_disable;
void cfi_init(void);
void cfi_shutdown(void) __unused;
@@ -231,6 +232,10 @@
retval = 0;
+ /* If we're disabled, don't initialize */
+ if (ctl_disable != 0)
+ return;
+
if (sizeof(struct cfi_lun_io) > CTL_PORT_PRIV_SIZE) {
printf("%s: size of struct cfi_lun_io %zd > "
"CTL_PORT_PRIV_SIZE %d\n", __func__,
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/ctl/scsi_ctl.c
--- a/head/sys/cam/ctl/scsi_ctl.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/ctl/scsi_ctl.c Wed Jul 25 16:45:04 2012 +0300
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/ctl/scsi_ctl.c 230033 2012-01-12 22:08:33Z ken $");
+__FBSDID("$FreeBSD: head/sys/cam/ctl/scsi_ctl.c 237726 2012-06-28 19:39:30Z ken $");
#include <sys/param.h>
#include <sys/queue.h>
@@ -227,12 +227,17 @@
PERIPHDRIVER_DECLARE(ctl, ctlfe_driver);
extern struct ctl_softc *control_softc;
+extern int ctl_disable;
int
ctlfeinitialize(void)
{
cam_status status;
+ /* Don't initialize if we're disabled */
+ if (ctl_disable != 0)
+ return (0);
+
STAILQ_INIT(&ctlfe_softc_list);
mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF);
@@ -263,6 +268,10 @@
{
cam_status status;
+ /* Don't initialize if we're disabled */
+ if (ctl_disable != 0)
+ return;
+
STAILQ_INIT(&ctlfe_softc_list);
mtx_init(&ctlfe_list_mtx, ctlfe_mtx_desc, NULL, MTX_DEF);
@@ -490,7 +499,7 @@
dev_chg = (struct ac_device_changed *)ac->contract_data;
- printf("%s: WWPN %#jx port %u path %u target %u %s\n",
+ printf("%s: WWPN %#jx port 0x%06x path %u target %u %s\n",
__func__, dev_chg->wwpn, dev_chg->port,
xpt_path_path_id(path), dev_chg->target,
(dev_chg->arrived == 0) ? "left" : "arrived");
@@ -558,7 +567,6 @@
TAILQ_INIT(&softc->work_queue);
softc->periph = periph;
- softc->parent_softc = bus_softc;
callout_init_mtx(&softc->dma_callout, sim->mtx, /*flags*/ 0);
periph->softc = softc;
@@ -582,7 +590,7 @@
union ccb *new_ccb;
new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE,
- M_NOWAIT);
+ M_ZERO|M_NOWAIT);
if (new_ccb == NULL) {
status = CAM_RESRC_UNAVAIL;
break;
@@ -616,7 +624,7 @@
union ccb *new_ccb;
new_ccb = (union ccb *)malloc(sizeof(*new_ccb), M_CTLFE,
- M_NOWAIT);
+ M_ZERO|M_NOWAIT);
if (new_ccb == NULL) {
status = CAM_RESRC_UNAVAIL;
break;
@@ -628,12 +636,22 @@
xpt_action(new_ccb);
softc->inots_sent++;
status = new_ccb->ccb_h.status;
- if (status != CAM_REQ_INPROG) {
- free(new_ccb, M_CTLFE);
+ if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
+ /*
+ * Note that we don't free the CCB here. If the
+ * status is not CAM_REQ_INPROG, then we're
+ * probably talking to a SIM that says it is
+ * target-capable but doesn't support the
+ * XPT_IMMEDIATE_NOTIFY CCB. i.e. it supports the
+ * older API. In that case, it'll call xpt_done()
+ * on the CCB, and we need to free it in our done
+ * routine as a result.
+ */
break;
}
}
- if (i == 0) {
+ if ((i == 0)
+ || (status != CAM_REQ_INPROG)) {
xpt_print(periph->path, "%s: could not allocate immediate "
"notify CCBs, status 0x%x\n", __func__, status);
return (CAM_REQ_CMP_ERR);
@@ -1460,12 +1478,29 @@
*/
send_ctl_io = 0;
break;
+ case CAM_REQ_INVALID:
+ case CAM_PROVIDE_FAIL:
default:
- xpt_print(periph->path, "%s: "
- "unsupported CAM status 0x%x\n",
- __func__, status);
- send_ctl_io = 0;
- break;
+ /*
+ * We should only get here if we're talking
+ * to a talking to a SIM that is target
+ * capable but supports the old API. In
+ * that case, we need to just free the CCB.
+ * If we actually send a notify acknowledge,
+ * it will send that back with an error as
+ * well.
+ */
+
+ if ((status != CAM_REQ_INVALID)
+ && (status != CAM_PROVIDE_FAIL))
+ xpt_print(periph->path, "%s: "
+ "unsupported CAM status "
+ "0x%x\n", __func__, status);
+
+ ctl_free_io(io);
+ ctlfe_free_ccb(periph, done_ccb);
+
+ return;
}
if (send_ctl_io != 0) {
ctl_queue(io);
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_all.c
--- a/head/sys/cam/scsi/scsi_all.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/scsi/scsi_all.c Wed Jul 25 16:45:04 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_all.c 230590 2012-01-26 18:09:28Z ken $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_all.c 238596 2012-07-18 12:41:09Z mav $");
#include <sys/param.h>
#include <sys/types.h>
@@ -768,7 +768,7 @@
*
* SCSI ASC/ASCQ Assignments
* Numeric Sorted Listing
- * as of 7/29/08
+ * as of 5/20/12
*
* D - DIRECT ACCESS DEVICE (SBC-2) device column key
* .T - SEQUENTIAL ACCESS DEVICE (SSC) -------------------
@@ -854,6 +854,12 @@
/* DT R MAEBKV */
{ SST(0x00, 0x1E, SS_RDEF, /* XXX TBD */
"Conflicting SA creation request") },
+ /* DT B */
+ { SST(0x00, 0x1F, SS_RDEF, /* XXX TBD */
+ "Logical unit transitioning to another power condition") },
+ /* DT P B */
+ { SST(0x00, 0x20, SS_RDEF, /* XXX TBD */
+ "Extended copy information available") },
/* D W O BK */
{ SST(0x01, 0x00, SS_RDEF,
"No index/sector signal") },
@@ -923,6 +929,33 @@
/* DT R MAEBKV */
{ SST(0x04, 0x13, SS_RDEF, /* XXX TBD */
"Logical unit not ready, SA creation in progress") },
+ /* D B */
+ { SST(0x04, 0x14, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, space allocation in progress") },
+ /* M */
+ { SST(0x04, 0x15, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, robotics disabled") },
+ /* M */
+ { SST(0x04, 0x16, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, configuration required") },
+ /* M */
+ { SST(0x04, 0x17, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, calibration required") },
+ /* M */
+ { SST(0x04, 0x18, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, a door is open") },
+ /* M */
+ { SST(0x04, 0x19, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, operating in sequential mode") },
+ /* DT B */
+ { SST(0x04, 0x1A, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, START/STOP UNIT command in progress") },
+ /* D B */
+ { SST(0x04, 0x1B, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, sanitize in progress") },
+ /* DT MAEB */
+ { SST(0x04, 0x1C, SS_RDEF, /* XXX TBD */
+ "Logical unit not ready, additional power use not yet granted") },
/* DTL WROMAEBKVF */
{ SST(0x05, 0x00, SS_RDEF,
"Logical unit does not respond to selection") },
@@ -989,6 +1022,12 @@
/* DTLPWROMAEBKVF */
{ SST(0x0B, 0x07, SS_RDEF, /* XXX TBD */
"Warning - degraded power to non-volatile cache") },
+ /* DTLPWROMAEBKVF */
+ { SST(0x0B, 0x08, SS_RDEF, /* XXX TBD */
+ "Warning - power loss expected") },
+ /* D */
+ { SST(0x0B, 0x09, SS_RDEF, /* XXX TBD */
+ "Warning - device statistics notification available") },
/* T R */
{ SST(0x0C, 0x00, SS_RDEF,
"Write error") },
@@ -1031,6 +1070,9 @@
/* DTLPWRO AEBKVF */
{ SST(0x0C, 0x0D, SS_RDEF, /* XXX TBD */
"Write error - not enough unsolicited data") },
+ /* DT W O BK */
+ { SST(0x0C, 0x0E, SS_RDEF, /* XXX TBD */
+ "Multiple write errors") },
/* R */
{ SST(0x0C, 0x0F, SS_RDEF, /* XXX TBD */
"Defects in error window") },
@@ -1076,6 +1118,12 @@
/* DT W O */
{ SST(0x10, 0x03, SS_RDEF, /* XXX TBD */
"Logical block reference tag check failed") },
+ /* T */
+ { SST(0x10, 0x04, SS_RDEF, /* XXX TBD */
+ "Logical block protection error on recovered buffer data") },
+ /* T */
+ { SST(0x10, 0x05, SS_RDEF, /* XXX TBD */
+ "Logical block protection method error") },
/* DT WRO BK */
{ SST(0x11, 0x00, SS_FATAL|EIO,
"Unrecovered read error") },
@@ -1280,6 +1328,9 @@
/* DT WRO BK */
{ SST(0x1D, 0x00, SS_FATAL,
"Miscompare during verify operation") },
+ /* D B */
+ { SST(0x1D, 0x01, SS_RDEF, /* XXX TBD */
+ "Miscomparable verify of unmapped LBA") },
/* D W O BK */
{ SST(0x1E, 0x00, SS_NOP | SSQ_PRINT_SENSE,
"Recovered ID with ECC correction") },
@@ -1322,6 +1373,9 @@
/* DT PWROMAEBK */
{ SST(0x20, 0x0B, SS_RDEF, /* XXX TBD */
"Access denied - ACL LUN conflict") },
+ /* T */
+ { SST(0x20, 0x0C, SS_FATAL | EINVAL,
+ "Illegal command when not in append-only mode") },
/* DT WRO BK */
{ SST(0x21, 0x00, SS_FATAL | EINVAL,
"Logical block address out of range") },
@@ -1337,6 +1391,39 @@
/* D */
{ SST(0x22, 0x00, SS_FATAL | EINVAL,
"Illegal function (use 20 00, 24 00, or 26 00)") },
+ /* DT P B */
+ { SST(0x23, 0x00, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, cause not reportable") },
+ /* DT P B */
+ { SST(0x23, 0x01, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, unsupported token type") },
+ /* DT P B */
+ { SST(0x23, 0x02, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, remote token usage not supported") },
+ /* DT P B */
+ { SST(0x23, 0x03, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, remote ROD token creation not supported") },
+ /* DT P B */
+ { SST(0x23, 0x04, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token unknown") },
+ /* DT P B */
+ { SST(0x23, 0x05, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token corrupt") },
+ /* DT P B */
+ { SST(0x23, 0x06, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token revoked") },
+ /* DT P B */
+ { SST(0x23, 0x07, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token expired") },
+ /* DT P B */
+ { SST(0x23, 0x08, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token cancelled") },
+ /* DT P B */
+ { SST(0x23, 0x09, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, token deleted") },
+ /* DT P B */
+ { SST(0x23, 0x0A, SS_RDEF, /* XXX TBD */
+ "Invalid token operation, invalid token length") },
/* DTLPWROMAEBKVF */
{ SST(0x24, 0x00, SS_FATAL | EINVAL,
"Invalid field in CDB") },
@@ -1445,6 +1532,9 @@
/* R F */
{ SST(0x27, 0x06, SS_RDEF, /* XXX TBD */
"Conditional write protect") },
+ /* D B */
+ { SST(0x27, 0x07, SS_RDEF, /* XXX TBD */
+ "Space allocation failed write protect") },
/* DTLPWROMAEBKVF */
{ SST(0x28, 0x00, SS_FATAL | ENXIO,
"Not ready to ready change, medium may have changed") },
@@ -1543,6 +1633,9 @@
/* DT R MAEBKV */
{ SST(0x2A, 0x14, SS_RDEF, /* XXX TBD */
"SA creation capabilities data has changed") },
+ /* T M V */
+ { SST(0x2A, 0x15, SS_RDEF, /* XXX TBD */
+ "Medium removal prevention preempted") },
/* DTLPWRO K */
{ SST(0x2B, 0x00, SS_RDEF,
"Copy cannot execute since host cannot disconnect") },
@@ -1582,6 +1675,9 @@
/* T */
{ SST(0x2C, 0x0B, SS_RDEF, /* XXX TBD */
"Not reserved") },
+ /* D */
+ { SST(0x2C, 0x0C, SS_RDEF, /* XXX TBD */
+ "ORWRITE generation does not match") },
/* T */
{ SST(0x2D, 0x00, SS_RDEF,
"Overwrite error on update in place") },
@@ -1645,6 +1741,9 @@
/* M */
{ SST(0x30, 0x12, SS_RDEF, /* XXX TBD */
"Incompatible volume qualifier") },
+ /* M */
+ { SST(0x30, 0x13, SS_RDEF, /* XXX TBD */
+ "Cleaning volume expired") },
/* DT WRO BK */
{ SST(0x31, 0x00, SS_RDEF,
"Medium format corrupted") },
@@ -1654,6 +1753,9 @@
/* R */
{ SST(0x31, 0x02, SS_RDEF, /* XXX TBD */
"Zoned formatting failed due to spare linking") },
+ /* D B */
+ { SST(0x31, 0x03, SS_RDEF, /* XXX TBD */
+ "SANITIZE command failed") },
/* D W O BK */
{ SST(0x32, 0x00, SS_RDEF,
"No defect spare location available") },
@@ -1702,6 +1804,9 @@
/* B */
{ SST(0x38, 0x06, SS_RDEF, /* XXX TBD */
"ESN - device busy class event") },
+ /* D */
+ { SST(0x38, 0x07, SS_RDEF, /* XXX TBD */
+ "Thin provisioning soft threshold reached") },
/* DTL WROMAE K */
{ SST(0x39, 0x00, SS_RDEF,
"Saving parameters not supported") },
@@ -1801,6 +1906,9 @@
/* M */
{ SST(0x3B, 0x1B, SS_RDEF, /* XXX TBD */
"Data transfer device inserted") },
+ /* T */
+ { SST(0x3B, 0x1C, SS_RDEF, /* XXX TBD */
+ "Too many logical objects on partition to support operation") },
/* DTLPWROMAE K */
{ SST(0x3D, 0x00, SS_RDEF,
"Invalid bits in IDENTIFY message") },
@@ -1904,6 +2012,9 @@
/* DTLPWROMAEBKVF */
{ SST(0x44, 0x00, SS_RDEF,
"Internal target failure") },
+ /* DT P MAEBKVF */
+ { SST(0x44, 0x01, SS_RDEF, /* XXX TBD */
+ "Persistent reservation information lost") },
/* DT B */
{ SST(0x44, 0x71, SS_RDEF, /* XXX TBD */
"ATA device failed set features") },
@@ -1967,6 +2078,27 @@
/* DT PWROMAEBK */
{ SST(0x4B, 0x06, SS_RDEF, /* XXX TBD */
"Initiator response timeout") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x07, SS_RDEF, /* XXX TBD */
+ "Connection lost") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x08, SS_RDEF, /* XXX TBD */
+ "Data-in buffer overflow - data buffer size") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x09, SS_RDEF, /* XXX TBD */
+ "Data-in buffer overflow - data buffer descriptor area") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x0A, SS_RDEF, /* XXX TBD */
+ "Data-in buffer error") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x0B, SS_RDEF, /* XXX TBD */
+ "Data-out buffer overflow - data buffer size") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x0C, SS_RDEF, /* XXX TBD */
+ "Data-out buffer overflow - data buffer descriptor area") },
+ /* DT PWROMAEBK F */
+ { SST(0x4B, 0x0D, SS_RDEF, /* XXX TBD */
+ "Data-out buffer error") },
/* DTLPWROMAEBKVF */
{ SST(0x4C, 0x00, SS_RDEF,
"Logical unit failed self-configuration") },
@@ -2012,6 +2144,18 @@
/* T */
{ SST(0x53, 0x04, SS_RDEF, /* XXX TBD */
"Medium thread or unthread failure") },
+ /* M */
+ { SST(0x53, 0x05, SS_RDEF, /* XXX TBD */
+ "Volume identifier invalid") },
+ /* T */
+ { SST(0x53, 0x06, SS_RDEF, /* XXX TBD */
+ "Volume identifier missing") },
+ /* M */
+ { SST(0x53, 0x07, SS_RDEF, /* XXX TBD */
+ "Duplicate volume identifier") },
+ /* M */
+ { SST(0x53, 0x08, SS_RDEF, /* XXX TBD */
+ "Element status unknown") },
/* P */
{ SST(0x54, 0x00, SS_RDEF,
"SCSI to host system interface failure") },
@@ -2048,6 +2192,15 @@
/* M */
{ SST(0x55, 0x0A, SS_RDEF, /* XXX TBD */
"Data currently unavailable") },
+ /* DTLPWROMAEBKVF */
+ { SST(0x55, 0x0B, SS_RDEF, /* XXX TBD */
+ "Insufficient power for operation") },
+ /* DT P B */
+ { SST(0x55, 0x0C, SS_RDEF, /* XXX TBD */
+ "Insufficient resources to create ROD") },
+ /* DT P B */
+ { SST(0x55, 0x0D, SS_RDEF, /* XXX TBD */
+ "Insufficient resources to create ROD token") },
/* R */
{ SST(0x57, 0x00, SS_RDEF,
"Unable to recover table-of-contents") },
@@ -2354,6 +2507,24 @@
/* DTLPWRO A K */
{ SST(0x5E, 0x04, SS_RDEF,
"Standby condition activated by command") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x05, SS_RDEF,
+ "Idle-B condition activated by timer") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x06, SS_RDEF,
+ "Idle-B condition activated by command") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x07, SS_RDEF,
+ "Idle-C condition activated by timer") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x08, SS_RDEF,
+ "Idle-C condition activated by command") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x09, SS_RDEF,
+ "Standby-Y condition activated by timer") },
+ /* DTLPWRO A K */
+ { SST(0x5E, 0x0A, SS_RDEF,
+ "Standby-Y condition activated by command") },
/* B */
{ SST(0x5E, 0x41, SS_RDEF, /* XXX TBD */
"Power state change to active") },
@@ -2834,11 +3005,10 @@
int error_code, sense_key, asc, ascq;
scsi_sense_action action;
- scsi_extract_sense_len(&csio->sense_data, csio->sense_len -
- csio->sense_resid, &error_code,
- &sense_key, &asc, &ascq, /*show_errors*/ 1);
-
- if ((error_code == SSD_DEFERRED_ERROR)
+ if (!scsi_extract_sense_ccb((union ccb *)csio,
+ &error_code, &sense_key, &asc, &ascq)) {
+ action = SS_RETRY | SSQ_DECREMENT_COUNT | SSQ_PRINT_SENSE | EIO;
+ } else if ((error_code == SSD_DEFERRED_ERROR)
|| (error_code == SSD_DESC_DEFERRED_ERROR)) {
/*
* XXX dufault at FreeBSD.org
@@ -2901,11 +3071,17 @@
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;
+ }
+
}
-#ifdef _KERNEL
- if (bootverbose)
- sense_flags |= SF_PRINT_ALWAYS;
-#endif
if ((sense_flags & SF_PRINT_ALWAYS) != 0)
action |= SSQ_PRINT_SENSE;
else if ((sense_flags & SF_NO_PRINT) != 0)
@@ -3059,6 +3235,10 @@
sizeof(cdb_str)));
}
+#ifdef _KERNEL
+ xpt_free_ccb((union ccb *)cgd);
+#endif
+
return(0);
}
@@ -4138,9 +4318,9 @@
struct scsi_inquiry_data *inq_data,
struct scsi_sense_desc_header *header)
{
- int i, found;
-
- for (i = 0, found = 0; i < (sizeof(scsi_sense_printers) /
+ int i;
+
+ for (i = 0; i < (sizeof(scsi_sense_printers) /
sizeof(scsi_sense_printers[0])); i++) {
struct scsi_sense_desc_printer *printer;
@@ -4612,6 +4792,36 @@
}
/*
+ * Extract basic sense information from SCSI I/O CCB structure.
+ */
+int
+scsi_extract_sense_ccb(union ccb *ccb,
+ int *error_code, int *sense_key, int *asc, int *ascq)
+{
+ struct scsi_sense_data *sense_data;
+
+ /* Make sure there are some sense data we can access. */
+ if (ccb->ccb_h.func_code != XPT_SCSI_IO ||
+ (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR ||
+ (ccb->csio.scsi_status != SCSI_STATUS_CHECK_COND) ||
+ (ccb->ccb_h.status & CAM_AUTOSNS_VALID) == 0 ||
+ (ccb->ccb_h.flags & CAM_SENSE_PHYS))
+ return (0);
+
+ if (ccb->ccb_h.flags & CAM_SENSE_PTR)
+ bcopy(&ccb->csio.sense_data, &sense_data,
+ sizeof(struct scsi_sense_data *));
+ else
+ sense_data = &ccb->csio.sense_data;
+ scsi_extract_sense_len(sense_data,
+ ccb->csio.sense_len - ccb->csio.sense_resid,
+ error_code, sense_key, asc, ascq, 1);
+ if (*error_code == -1)
+ return (0);
+ return (1);
+}
+
+/*
* Extract basic sense information. If show_errors is set, sense values
* will be set to -1 if they are not present.
*/
@@ -5740,6 +5950,66 @@
timeout);
}
+void
+scsi_read_buffer(struct ccb_scsiio *csio, u_int32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb*),
+ uint8_t tag_action, int mode,
+ uint8_t buffer_id, u_int32_t offset,
+ uint8_t *data_ptr, uint32_t allocation_length,
+ uint8_t sense_len, uint32_t timeout)
+{
+ struct scsi_read_buffer *scsi_cmd;
+
+ scsi_cmd = (struct scsi_read_buffer *)&csio->cdb_io.cdb_bytes;
+ memset(scsi_cmd, 0, sizeof(*scsi_cmd));
+ scsi_cmd->opcode = READ_BUFFER;
+ scsi_cmd->byte2 = mode;
+ scsi_cmd->buffer_id = buffer_id;
+ scsi_ulto3b(offset, scsi_cmd->offset);
+ scsi_ulto3b(allocation_length, scsi_cmd->length);
+
+ cam_fill_csio(csio,
+ retries,
+ cbfcnp,
+ /*flags*/CAM_DIR_IN,
+ tag_action,
+ data_ptr,
+ allocation_length,
+ sense_len,
+ sizeof(*scsi_cmd),
+ timeout);
+}
+
+void
+scsi_write_buffer(struct ccb_scsiio *csio, u_int32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint8_t tag_action, int mode,
+ uint8_t buffer_id, u_int32_t offset,
+ uint8_t *data_ptr, uint32_t param_list_length,
+ uint8_t sense_len, uint32_t timeout)
+{
+ struct scsi_write_buffer *scsi_cmd;
+
+ scsi_cmd = (struct scsi_write_buffer *)&csio->cdb_io.cdb_bytes;
+ memset(scsi_cmd, 0, sizeof(*scsi_cmd));
+ scsi_cmd->opcode = WRITE_BUFFER;
+ scsi_cmd->byte2 = mode;
+ scsi_cmd->buffer_id = buffer_id;
+ scsi_ulto3b(offset, scsi_cmd->offset);
+ scsi_ulto3b(param_list_length, scsi_cmd->length);
+
+ cam_fill_csio(csio,
+ retries,
+ cbfcnp,
+ /*flags*/param_list_length ? CAM_DIR_OUT : CAM_DIR_NONE,
+ tag_action,
+ data_ptr,
+ param_list_length,
+ sense_len,
+ sizeof(*scsi_cmd),
+ timeout);
+}
+
void
scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_all.h
--- a/head/sys/cam/scsi/scsi_all.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/scsi/scsi_all.h Wed Jul 25 16:45:04 2012 +0300
@@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian at tfs.com) Sept 1992
*
- * $FreeBSD: head/sys/cam/scsi/scsi_all.h 230590 2012-01-26 18:09:28Z ken $
+ * $FreeBSD: head/sys/cam/scsi/scsi_all.h 237478 2012-06-23 12:32:53Z mav $
*/
/*
@@ -74,9 +74,6 @@
SS_TUR = 0x040000, /* Send a Test Unit Ready command to the
* device, then retry the original command.
*/
- SS_REQSENSE = 0x050000, /* Send a RequestSense command to the
- * device, then retry the original command.
- */
SS_MASK = 0xff0000
} scsi_sense_action;
@@ -1267,6 +1264,8 @@
#define SCSI_PROTO_RDMA 0x04
#define SCSI_PROTO_iSCSI 0x05
#define SCSI_PROTO_SAS 0x06
+#define SCSI_PROTO_ADT 0x07
+#define SCSI_PROTO_ATA 0x08
#define SVPD_ID_PROTO_SHIFT 4
#define SVPD_ID_CODESET_BINARY 0x01
#define SVPD_ID_CODESET_ASCII 0x02
@@ -1400,6 +1399,13 @@
uint8_t control;
};
+struct scsi_diag_page {
+ uint8_t page_code;
+ uint8_t page_specific_flags;
+ uint8_t length[2];
+ uint8_t params[0];
+};
+
struct scsi_read_capacity
{
u_int8_t opcode;
@@ -2174,12 +2180,6 @@
char * scsi_sense_string(struct ccb_scsiio *csio,
char *str, int str_len);
void scsi_sense_print(struct ccb_scsiio *csio);
-int scsi_interpret_sense(union ccb *ccb,
- u_int32_t sense_flags,
- u_int32_t *relsim_flags,
- u_int32_t *reduction,
- u_int32_t *timeout,
- scsi_sense_action error_action);
#else /* _KERNEL */
int scsi_command_string(struct cam_device *device,
struct ccb_scsiio *csio, struct sbuf *sb);
@@ -2191,21 +2191,8 @@
char *str, int str_len);
void scsi_sense_print(struct cam_device *device,
struct ccb_scsiio *csio, FILE *ofile);
-int scsi_interpret_sense(struct cam_device *device,
- union ccb *ccb,
- u_int32_t sense_flags,
- u_int32_t *relsim_flags,
- u_int32_t *reduction,
- u_int32_t *timeout,
- scsi_sense_action error_action);
#endif /* _KERNEL */
-#define SF_RETRY_UA 0x01
-#define SF_NO_PRINT 0x02
-#define SF_QUIET_IR 0x04 /* Be quiet about Illegal Request reponses */
-#define SF_PRINT_ALWAYS 0x08
-
-
const char * scsi_op_desc(u_int16_t opcode,
struct scsi_inquiry_data *inq_data);
char * scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string,
@@ -2352,6 +2339,20 @@
uint16_t param_list_length, uint8_t sense_len,
uint32_t timeout);
+void scsi_read_buffer(struct ccb_scsiio *csio, u_int32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb*),
+ uint8_t tag_action, int mode,
+ uint8_t buffer_id, u_int32_t offset,
+ uint8_t *data_ptr, uint32_t allocation_length,
+ uint8_t sense_len, uint32_t timeout);
+
+void scsi_write_buffer(struct ccb_scsiio *csio, u_int32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint8_t tag_action, int mode,
+ uint8_t buffer_id, u_int32_t offset,
+ uint8_t *data_ptr, uint32_t param_list_length,
+ uint8_t sense_len, uint32_t timeout);
+
void scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
u_int8_t tag_action, int readop, u_int8_t byte2,
@@ -2387,6 +2388,8 @@
void scsi_extract_sense(struct scsi_sense_data *sense, int *error_code,
int *sense_key, int *asc, int *ascq);
+int scsi_extract_sense_ccb(union ccb *ccb, int *error_code, int *sense_key,
+ int *asc, int *ascq);
void scsi_extract_sense_len(struct scsi_sense_data *sense,
u_int sense_len, int *error_code, int *sense_key,
int *asc, int *ascq, int show_errors);
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_cd.c
--- a/head/sys/cam/scsi/scsi_cd.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/scsi/scsi_cd.c Wed Jul 25 16:45:04 2012 +0300
@@ -46,7 +46,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_cd.c 229395 2012-01-03 17:04:09Z mav $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_cd.c 237689 2012-06-28 07:01:48Z imp $");
#include "opt_cd.h"
@@ -97,15 +97,13 @@
CD_FLAG_NEW_DISC = 0x0002,
CD_FLAG_DISC_LOCKED = 0x0004,
CD_FLAG_DISC_REMOVABLE = 0x0008,
- CD_FLAG_TAGGED_QUEUING = 0x0010,
CD_FLAG_CHANGER = 0x0040,
CD_FLAG_ACTIVE = 0x0080,
CD_FLAG_SCHED_ON_COMP = 0x0100,
CD_FLAG_RETRY_UA = 0x0200,
CD_FLAG_VALID_MEDIA = 0x0400,
CD_FLAG_VALID_TOC = 0x0800,
- CD_FLAG_SCTX_INIT = 0x1000,
- CD_FLAG_OPEN = 0x2000
+ CD_FLAG_SCTX_INIT = 0x1000
} cd_flags;
typedef enum {
@@ -295,6 +293,9 @@
#ifndef CD_DEFAULT_RETRY
#define CD_DEFAULT_RETRY 4
#endif
+#ifndef CD_DEFAULT_TIMEOUT
+#define CD_DEFAULT_TIMEOUT 30000
+#endif
#ifndef CHANGER_MIN_BUSY_SECONDS
#define CHANGER_MIN_BUSY_SECONDS 5
#endif
@@ -303,6 +304,7 @@
#endif
static int cd_retry_count = CD_DEFAULT_RETRY;
+static int cd_timeout = CD_DEFAULT_TIMEOUT;
static int changer_min_busy_seconds = CHANGER_MIN_BUSY_SECONDS;
static int changer_max_busy_seconds = CHANGER_MAX_BUSY_SECONDS;
@@ -312,6 +314,9 @@
SYSCTL_INT(_kern_cam_cd, OID_AUTO, retry_count, CTLFLAG_RW,
&cd_retry_count, 0, "Normal I/O retry count");
TUNABLE_INT("kern.cam.cd.retry_count", &cd_retry_count);
+SYSCTL_INT(_kern_cam_cd, OID_AUTO, timeout, CTLFLAG_RW,
+ &cd_timeout, 0, "Timeout, in us, for read operations");
+TUNABLE_INT("kern.cam.cd.timeout", &cd_timeout);
SYSCTL_INT(_kern_cam_cd_changer, OID_AUTO, min_busy_seconds, CTLFLAG_RW,
&changer_min_busy_seconds, 0, "Minimum changer scheduling quantum");
TUNABLE_INT("kern.cam.cd.changer.min_busy_seconds", &changer_min_busy_seconds);
@@ -359,6 +364,20 @@
}
}
+/*
+ * Callback from GEOM, called when it has finished cleaning up its
+ * resources.
+ */
+static void
+cddiskgonecb(struct disk *dp)
+{
+ struct cam_periph *periph;
+
+ periph = (struct cam_periph *)dp->d_drv1;
+
+ cam_periph_release(periph);
+}
+
static void
cdoninvalidate(struct cam_periph *periph)
{
@@ -390,7 +409,7 @@
camq_remove(&softc->changer->devq, softc->pinfo.index);
disk_gone(softc->disk);
- xpt_print(periph->path, "lost device\n");
+ xpt_print(periph->path, "lost device, %d refs\n", periph->refcount);
}
static void
@@ -653,8 +672,6 @@
bioq_init(&softc->bio_queue);
if (SID_IS_REMOVABLE(&cgd->inq_data))
softc->flags |= CD_FLAG_DISC_REMOVABLE;
- if ((cgd->inq_data.flags & SID_CmdQue) != 0)
- softc->flags |= CD_FLAG_TAGGED_QUEUING;
periph->softc = softc;
softc->periph = periph;
@@ -729,6 +746,7 @@
softc->disk->d_open = cdopen;
softc->disk->d_close = cdclose;
softc->disk->d_strategy = cdstrategy;
+ softc->disk->d_gone = cddiskgonecb;
softc->disk->d_ioctl = cdioctl;
softc->disk->d_name = "cd";
cam_strvis(softc->disk->d_descr, cgd->inq_data.vendor,
@@ -750,6 +768,19 @@
softc->disk->d_hba_device = cpi.hba_device;
softc->disk->d_hba_subvendor = cpi.hba_subvendor;
softc->disk->d_hba_subdevice = cpi.hba_subdevice;
+
+ /*
+ * Acquire a reference to the periph before we register with GEOM.
+ * We'll release this reference once GEOM calls us back (via
+ * dadiskgonecb()) telling us that our provider has been freed.
+ */
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
+ xpt_print(periph->path, "%s: lost periph during "
+ "registration!\n", __func__);
+ cam_periph_lock(periph);
+ return (CAM_REQ_CMP_ERR);
+ }
+
disk_create(softc->disk, DISK_VERSION);
cam_periph_lock(periph);
@@ -1003,17 +1034,20 @@
cam_periph_lock(periph);
if (softc->flags & CD_FLAG_INVALID) {
+ cam_periph_release_locked(periph);
cam_periph_unlock(periph);
- cam_periph_release(periph);
return(ENXIO);
}
if ((error = cam_periph_hold(periph, PRIBIO | PCATCH)) != 0) {
+ cam_periph_release_locked(periph);
cam_periph_unlock(periph);
- cam_periph_release(periph);
return (error);
}
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
+ ("cdopen\n"));
+
/*
* Check for media, and set the appropriate flags. We don't bail
* if we don't have media, but then we don't allow anything but the
@@ -1024,14 +1058,7 @@
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n"));
cam_periph_unhold(periph);
- /* Closes aren't symmetrical with opens, so fix up the refcounting. */
- if ((softc->flags & CD_FLAG_OPEN) == 0) {
- softc->flags |= CD_FLAG_OPEN;
- cam_periph_unlock(periph);
- } else {
- cam_periph_unlock(periph);
- cam_periph_release(periph);
- }
+ cam_periph_unlock(periph);
return (0);
}
@@ -1049,7 +1076,14 @@
softc = (struct cd_softc *)periph->softc;
cam_periph_lock(periph);
- cam_periph_hold(periph, PRIBIO);
+ if (cam_periph_hold(periph, PRIBIO) != 0) {
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+ return (0);
+ }
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
+ ("cdclose\n"));
if ((softc->flags & CD_FLAG_DISC_REMOVABLE) != 0)
cdprevent(periph, PR_ALLOW);
@@ -1063,11 +1097,11 @@
/*
* We'll check the media and toc again at the next open().
*/
- softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC|CD_FLAG_OPEN);
+ softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC);
cam_periph_unhold(periph);
+ cam_periph_release_locked(periph);
cam_periph_unlock(periph);
- cam_periph_release(periph);
return (0);
}
@@ -1395,7 +1429,8 @@
}
cam_periph_lock(periph);
- CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdstrategy\n"));
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
+ ("cdstrategy(%p)\n", bp));
softc = (struct cd_softc *)periph->softc;
@@ -1481,8 +1516,9 @@
bp->bio_bcount / softc->params.blksize,
/* data_ptr */ bp->bio_data,
/* dxfer_len */ bp->bio_bcount,
- /* sense_len */ SSD_FULL_SIZE,
- /* timeout */ 30000);
+ /* sense_len */ cd_retry_count ?
+ SSD_FULL_SIZE : SF_NO_PRINT,
+ /* timeout */ cd_timeout);
/* Use READ CD command for audio tracks. */
if (softc->params.blksize == 2352) {
start_ccb->csio.cdb_io.cdb_bytes[0] = READ_CD;
@@ -1668,7 +1704,6 @@
return;
} else if (error != 0) {
- struct scsi_sense_data *sense;
int asc, ascq;
int sense_key, error_code;
int have_sense;
@@ -1691,20 +1726,12 @@
cgd.ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action((union ccb *)&cgd);
- if (((csio->ccb_h.flags & CAM_SENSE_PHYS) != 0)
- || ((csio->ccb_h.flags & CAM_SENSE_PTR) != 0)
- || ((status & CAM_AUTOSNS_VALID) == 0))
+ if (scsi_extract_sense_ccb(done_ccb,
+ &error_code, &sense_key, &asc, &ascq))
+ have_sense = TRUE;
+ else
have_sense = FALSE;
- else
- have_sense = TRUE;
-
- if (have_sense) {
- sense = &csio->sense_data;
- scsi_extract_sense_len(sense,
- csio->sense_len - csio->sense_resid,
- &error_code, &sense_key, &asc,
- &ascq, /*show_errors*/ 1);
- }
+
/*
* Attach to anything that claims to be a
* CDROM or WORM device, as long as it
@@ -1861,12 +1888,11 @@
return(ENXIO);
cam_periph_lock(periph);
- CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdioctl\n"));
softc = (struct cd_softc *)periph->softc;
- CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
- ("trying to do ioctl %#lx\n", cmd));
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
+ ("cdioctl(%#lx)\n", cmd));
if ((error = cam_periph_hold(periph, PRIBIO | PCATCH)) != 0) {
cam_periph_unlock(periph);
@@ -3131,7 +3157,7 @@
{
struct cd_softc *softc;
struct cam_periph *periph;
- int error;
+ int error, error_code, sense_key, asc, ascq;
periph = xpt_path_periph(ccb->ccb_h.path);
softc = (struct cd_softc *)periph->softc;
@@ -3145,19 +3171,10 @@
*/
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
error = cd6byteworkaround(ccb);
- } else if (((ccb->ccb_h.status & CAM_STATUS_MASK) ==
- CAM_SCSI_STATUS_ERROR)
- && (ccb->ccb_h.status & CAM_AUTOSNS_VALID)
- && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
- && ((ccb->ccb_h.flags & CAM_SENSE_PHYS) == 0)
- && ((ccb->ccb_h.flags & CAM_SENSE_PTR) == 0)) {
- int sense_key, error_code, asc, ascq;
-
- scsi_extract_sense_len(&ccb->csio.sense_data,
- ccb->csio.sense_len - ccb->csio.sense_resid, &error_code,
- &sense_key, &asc, &ascq, /*show_errors*/ 1);
+ } else if (scsi_extract_sense_ccb(ccb,
+ &error_code, &sense_key, &asc, &ascq)) {
if (sense_key == SSD_KEY_ILLEGAL_REQUEST)
- error = cd6byteworkaround(ccb);
+ error = cd6byteworkaround(ccb);
}
if (error == ERESTART)
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_ch.c
--- a/head/sys/cam/scsi/scsi_ch.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/scsi/scsi_ch.c Wed Jul 25 16:45:04 2012 +0300
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_ch.c 227293 2011-11-07 06:44:47Z ed $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_ch.c 238200 2012-07-07 17:17:43Z eadler $");
#include <sys/param.h>
#include <sys/queue.h>
@@ -107,8 +107,7 @@
static const u_int32_t CH_TIMEOUT_INITIALIZE_ELEMENT_STATUS = 500000;
typedef enum {
- CH_FLAG_INVALID = 0x001,
- CH_FLAG_OPEN = 0x002
+ CH_FLAG_INVALID = 0x001
} ch_flags;
typedef enum {
@@ -211,7 +210,7 @@
static struct cdevsw ch_cdevsw = {
.d_version = D_VERSION,
- .d_flags = 0,
+ .d_flags = D_TRACKCLOSE,
.d_open = chopen,
.d_close = chclose,
.d_ioctl = chioctl,
@@ -404,16 +403,11 @@
cam_periph_lock(periph);
if (softc->flags & CH_FLAG_INVALID) {
+ cam_periph_release_locked(periph);
cam_periph_unlock(periph);
- cam_periph_release(periph);
return(ENXIO);
}
- if ((softc->flags & CH_FLAG_OPEN) == 0)
- softc->flags |= CH_FLAG_OPEN;
- else
- cam_periph_release(periph);
-
if ((error = cam_periph_hold(periph, PRIBIO | PCATCH)) != 0) {
cam_periph_unlock(periph);
cam_periph_release(periph);
@@ -424,9 +418,8 @@
* Load information about this changer device into the softc.
*/
if ((error = chgetparams(periph)) != 0) {
- softc->flags &= ~CH_FLAG_OPEN;
+ cam_periph_release_locked(periph);
cam_periph_unlock(periph);
- cam_periph_release(periph);
return(error);
}
@@ -440,22 +433,11 @@
chclose(struct cdev *dev, int flag, int fmt, struct thread *td)
{
struct cam_periph *periph;
- struct ch_softc *softc;
- int error;
-
- error = 0;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
return(ENXIO);
- softc = (struct ch_softc *)periph->softc;
-
- cam_periph_lock(periph);
-
- softc->flags &= ~CH_FLAG_OPEN;
-
- cam_periph_unlock(periph);
cam_periph_release(periph);
return(0);
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_da.c
--- a/head/sys/cam/scsi/scsi_da.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/scsi/scsi_da.c Wed Jul 25 16:45:04 2012 +0300
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_da.c 234374 2012-04-17 10:44:28Z trasz $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_da.c 238437 2012-07-14 02:59:11Z mjacob $");
#include <sys/param.h>
@@ -77,7 +77,6 @@
DA_FLAG_NEW_PACK = 0x002,
DA_FLAG_PACK_LOCKED = 0x004,
DA_FLAG_PACK_REMOVABLE = 0x008,
- DA_FLAG_TAGGED_QUEUING = 0x010,
DA_FLAG_NEED_OTAG = 0x020,
DA_FLAG_WENT_IDLE = 0x040,
DA_FLAG_RETRY_UA = 0x080,
@@ -811,6 +810,27 @@
{ T_DIRECT, SIP_MEDIA_FIXED, "WDC WD??", "???PVT*", "*" },
/*quirks*/DA_Q_4K
},
+ {
+ /*
+ * Olympus FE-210 camera
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "OLYMPUS", "FE210*",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * LG UP3S MP3 player
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "LG", "UP3S",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * Laser MP3-2GA13 MP3 player
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "USB 2.0", "(HS) Flash Disk",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
};
static disk_strategy_t dastrategy;
@@ -863,9 +883,9 @@
SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RW,
&da_default_timeout, 0, "Normal I/O timeout (in seconds)");
TUNABLE_INT("kern.cam.da.default_timeout", &da_default_timeout);
-SYSCTL_INT(_kern_cam_da, OID_AUTO, da_send_ordered, CTLFLAG_RW,
+SYSCTL_INT(_kern_cam_da, OID_AUTO, send_ordered, CTLFLAG_RW,
&da_send_ordered, 0, "Send Ordered Tags");
-TUNABLE_INT("kern.cam.da.da_send_ordered", &da_send_ordered);
+TUNABLE_INT("kern.cam.da.send_ordered", &da_send_ordered);
/*
* DA_ORDEREDTAG_INTERVAL determines how often, relative
@@ -921,9 +941,8 @@
softc = (struct da_softc *)periph->softc;
softc->flags |= DA_FLAG_OPEN;
- CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
- ("daopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit,
- unit));
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
+ ("daopen\n"));
if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
/* Invalidate our pack information. */
@@ -963,14 +982,13 @@
{
struct cam_periph *periph;
struct da_softc *softc;
- int error;
periph = (struct cam_periph *)dp->d_drv1;
if (periph == NULL)
return (0);
cam_periph_lock(periph);
- if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
+ if (cam_periph_hold(periph, PRIBIO) != 0) {
cam_periph_unlock(periph);
cam_periph_release(periph);
return (0);
@@ -978,6 +996,9 @@
softc = (struct da_softc *)periph->softc;
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
+ ("daclose\n"));
+
if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0
&& (softc->flags & DA_FLAG_PACK_INVALID) == 0) {
union ccb *ccb;
@@ -993,30 +1014,9 @@
SSD_FULL_SIZE,
5 * 60 * 1000);
- cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0,
- /*sense_flags*/SF_RETRY_UA,
+ cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
+ /*sense_flags*/SF_RETRY_UA | SF_QUIET_IR,
softc->disk->d_devstat);
-
- if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
- CAM_SCSI_STATUS_ERROR) {
- int asc, ascq;
- int sense_key, error_code;
-
- scsi_extract_sense_len(&ccb->csio.sense_data,
- ccb->csio.sense_len - ccb->csio.sense_resid,
- &error_code, &sense_key, &asc, &ascq,
- /*show_errors*/ 1);
- if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
- scsi_sense_print(&ccb->csio);
- } else {
- xpt_print(periph->path, "Synchronize cache "
- "failed, status == 0x%x, scsi status == "
- "0x%x\n", ccb->csio.ccb_h.status,
- ccb->csio.scsi_status);
- }
- }
-
xpt_release_ccb(ccb);
}
@@ -1087,7 +1087,9 @@
biofinish(bp, NULL, ENXIO);
return;
}
-
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dastrategy(%p)\n", bp));
+
/*
* Place it in the queue of disk activities for this disk
*/
@@ -1116,6 +1118,7 @@
u_int secsize;
struct ccb_scsiio csio;
struct disk *dp;
+ int error = 0;
dp = arg;
periph = dp->d_drv1;
@@ -1134,7 +1137,7 @@
xpt_setup_ccb(&csio.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
csio.ccb_h.ccb_state = DA_CCB_DUMP;
scsi_read_write(&csio,
- /*retries*/1,
+ /*retries*/0,
dadone,
MSG_ORDERED_Q_TAG,
/*read*/FALSE,
@@ -1147,19 +1150,16 @@
/*sense_len*/SSD_FULL_SIZE,
da_default_timeout * 1000);
xpt_polled_action((union ccb *)&csio);
+
+ error = cam_periph_error((union ccb *)&csio,
+ 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL);
+ if ((csio.ccb_h.status & CAM_DEV_QFRZN) != 0)
+ cam_release_devq(csio.ccb_h.path, /*relsim_flags*/0,
+ /*reduction*/0, /*timeout*/0, /*getcount_only*/0);
+ if (error != 0)
+ printf("Aborting dump due to I/O error.\n");
cam_periph_unlock(periph);
-
- if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- printf("Aborting dump due to I/O error.\n");
- if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
- CAM_SCSI_STATUS_ERROR)
- scsi_sense_print(&csio);
- else
- printf("status == 0x%x, scsi status == 0x%x\n",
- csio.ccb_h.status, csio.scsi_status);
- return(EIO);
- }
- return(0);
+ return (error);
}
/*
@@ -1170,7 +1170,7 @@
xpt_setup_ccb(&csio.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
csio.ccb_h.ccb_state = DA_CCB_DUMP;
scsi_synchronize_cache(&csio,
- /*retries*/1,
+ /*retries*/0,
/*cbfcnp*/dadone,
MSG_SIMPLE_Q_TAG,
/*begin_lba*/0,/* Cover the whole disk */
@@ -1179,28 +1179,16 @@
5 * 60 * 1000);
xpt_polled_action((union ccb *)&csio);
- if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
- CAM_SCSI_STATUS_ERROR) {
- int asc, ascq;
- int sense_key, error_code;
-
- scsi_extract_sense_len(&csio.sense_data,
- csio.sense_len - csio.sense_resid,
- &error_code, &sense_key, &asc, &ascq,
- /*show_errors*/ 1);
- if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
- scsi_sense_print(&csio);
- } else {
- xpt_print(periph->path, "Synchronize cache "
- "failed, status == 0x%x, scsi status == "
- "0x%x\n", csio.ccb_h.status,
- csio.scsi_status);
- }
- }
+ error = cam_periph_error((union ccb *)&csio,
+ 0, SF_NO_RECOVERY | SF_NO_RETRY | SF_QUIET_IR, NULL);
+ if ((csio.ccb_h.status & CAM_DEV_QFRZN) != 0)
+ cam_release_devq(csio.ccb_h.path, /*relsim_flags*/0,
+ /*reduction*/0, /*timeout*/0, /*getcount_only*/0);
+ if (error != 0)
+ xpt_print(periph->path, "Synchronize cache failed\n");
}
cam_periph_unlock(periph);
- return (0);
+ return (error);
}
static int
@@ -1245,6 +1233,20 @@
}
}
+/*
+ * Callback from GEOM, called when it has finished cleaning up its
+ * resources.
+ */
+static void
+dadiskgonecb(struct disk *dp)
+{
+ struct cam_periph *periph;
+
+ periph = (struct cam_periph *)dp->d_drv1;
+
+ cam_periph_release(periph);
+}
+
static void
daoninvalidate(struct cam_periph *periph)
{
@@ -1267,7 +1269,12 @@
bioq_flush(&softc->bio_queue, NULL, ENXIO);
bioq_flush(&softc->delete_queue, NULL, ENXIO);
+ /*
+ * Tell GEOM that we've gone away, we'll get a callback when it is
+ * done cleaning up its resources.
+ */
disk_gone(softc->disk);
+
xpt_print(periph->path, "lost device - %d outstanding, %d refs\n",
softc->outstanding_cmds, periph->refcount);
}
@@ -1550,8 +1557,6 @@
bioq_init(&softc->delete_run_queue);
if (SID_IS_REMOVABLE(&cgd->inq_data))
softc->flags |= DA_FLAG_PACK_REMOVABLE;
- if ((cgd->inq_data.flags & SID_CmdQue) != 0)
- softc->flags |= DA_FLAG_TAGGED_QUEUING;
softc->unmap_max_ranges = UNMAP_MAX_RANGES;
softc->unmap_max_lba = 1024*1024*2;
@@ -1647,6 +1652,7 @@
softc->disk->d_strategy = dastrategy;
softc->disk->d_dump = dadump;
softc->disk->d_getattr = dagetattr;
+ softc->disk->d_gone = dadiskgonecb;
softc->disk->d_name = "da";
softc->disk->d_drv1 = periph;
if (cpi.maxio == 0)
@@ -1669,6 +1675,19 @@
softc->disk->d_hba_device = cpi.hba_device;
softc->disk->d_hba_subvendor = cpi.hba_subvendor;
softc->disk->d_hba_subdevice = cpi.hba_subdevice;
+
+ /*
+ * Acquire a reference to the periph before we register with GEOM.
+ * We'll release this reference once GEOM calls us back (via
+ * dadiskgonecb()) telling us that our provider has been freed.
+ */
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
+ xpt_print(periph->path, "%s: lost periph during "
+ "registration!\n", __func__);
+ mtx_lock(periph->sim->mtx);
+ return (CAM_REQ_CMP_ERR);
+ }
+
disk_create(softc->disk, DISK_VERSION);
mtx_lock(periph->sim->mtx);
@@ -1703,6 +1722,8 @@
softc = (struct da_softc *)periph->softc;
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dastart\n"));
+
switch (softc->state) {
case DA_STATE_NORMAL:
{
@@ -1711,7 +1732,7 @@
/* Execute immediate CCB if waiting. */
if (periph->immediate_priority <= periph->pinfo.priority) {
- CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("queuing for immediate ccb\n"));
start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
@@ -2043,6 +2064,9 @@
softc = (struct da_softc *)periph->softc;
priority = done_ccb->ccb_h.pinfo.priority;
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n"));
+
csio = &done_ccb->csio;
switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
case DA_CCB_BUFFER_IO:
@@ -2263,7 +2287,6 @@
*/
return;
} else if (error != 0) {
- struct scsi_sense_data *sense;
int asc, ascq;
int sense_key, error_code;
int have_sense;
@@ -2286,20 +2309,12 @@
cgd.ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action((union ccb *)&cgd);
- if (((csio->ccb_h.flags & CAM_SENSE_PHYS) != 0)
- || ((csio->ccb_h.flags & CAM_SENSE_PTR) != 0)
- || ((status & CAM_AUTOSNS_VALID) == 0))
+ if (scsi_extract_sense_ccb(done_ccb,
+ &error_code, &sense_key, &asc, &ascq))
+ have_sense = TRUE;
+ else
have_sense = FALSE;
- else
- have_sense = TRUE;
- if (have_sense) {
- sense = &csio->sense_data;
- scsi_extract_sense_len(sense,
- csio->sense_len - csio->sense_resid,
- &error_code, &sense_key, &asc,
- &ascq, /*show_errors*/ 1);
- }
/*
* If we tried READ CAPACITY(16) and failed,
* fallback to READ CAPACITY(10).
@@ -2437,7 +2452,7 @@
{
struct da_softc *softc;
struct cam_periph *periph;
- int error;
+ int error, error_code, sense_key, asc, ascq;
periph = xpt_path_periph(ccb->ccb_h.path);
softc = (struct da_softc *)periph->softc;
@@ -2449,16 +2464,8 @@
error = 0;
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
error = cmd6workaround(ccb);
- } else if (((ccb->ccb_h.status & CAM_STATUS_MASK) ==
- CAM_SCSI_STATUS_ERROR)
- && (ccb->ccb_h.status & CAM_AUTOSNS_VALID)
- && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
- && ((ccb->ccb_h.flags & CAM_SENSE_PHYS) == 0)
- && ((ccb->ccb_h.flags & CAM_SENSE_PTR) == 0)) {
- int sense_key, error_code, asc, ascq;
-
- scsi_extract_sense(&ccb->csio.sense_data,
- &error_code, &sense_key, &asc, &ascq);
+ } else if (scsi_extract_sense_ccb(ccb,
+ &error_code, &sense_key, &asc, &ascq)) {
if (sense_key == SSD_KEY_ILLEGAL_REQUEST)
error = cmd6workaround(ccb);
/*
@@ -2511,8 +2518,8 @@
SSD_FULL_SIZE,
5000);
- error = cam_periph_runccb(ccb, /*error_routine*/NULL, CAM_RETRY_SELTO,
- SF_RETRY_UA, softc->disk->d_devstat);
+ error = cam_periph_runccb(ccb, daerror, CAM_RETRY_SELTO,
+ SF_RETRY_UA | SF_QUIET_IR, softc->disk->d_devstat);
if (error == 0) {
if (action == PR_ALLOW)
@@ -2637,6 +2644,11 @@
softc->disk->d_flags |= DISKFLAG_CANDELETE;
else
softc->disk->d_flags &= ~DISKFLAG_CANDELETE;
+
+/* Currently as of 6/13/2012, panics if DIAGNOSTIC is set */
+#ifndef DIAGNOSTIC
+ disk_resize(softc->disk);
+#endif
}
static void
@@ -2669,6 +2681,7 @@
{
struct cam_periph *periph;
struct da_softc *softc;
+ int error;
TAILQ_FOREACH(periph, &dadriver.units, unit_links) {
union ccb ccb;
@@ -2690,7 +2703,7 @@
ccb.ccb_h.ccb_state = DA_CCB_DUMP;
scsi_synchronize_cache(&ccb.csio,
- /*retries*/1,
+ /*retries*/0,
/*cbfcnp*/dadone,
MSG_SIMPLE_Q_TAG,
/*begin_lba*/0, /* whole disk */
@@ -2700,32 +2713,13 @@
xpt_polled_action(&ccb);
- if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- if (((ccb.ccb_h.status & CAM_STATUS_MASK) ==
- CAM_SCSI_STATUS_ERROR)
- && (ccb.csio.scsi_status == SCSI_STATUS_CHECK_COND)){
- int error_code, sense_key, asc, ascq;
-
- scsi_extract_sense(&ccb.csio.sense_data,
- &error_code, &sense_key,
- &asc, &ascq);
-
- if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
- scsi_sense_print(&ccb.csio);
- } else {
- xpt_print(periph->path, "Synchronize "
- "cache failed, status == 0x%x, scsi status "
- "== 0x%x\n", ccb.ccb_h.status,
- ccb.csio.scsi_status);
- }
- }
-
+ error = cam_periph_error(&ccb,
+ 0, SF_NO_RECOVERY | SF_NO_RETRY | SF_QUIET_IR, NULL);
if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
- cam_release_devq(ccb.ccb_h.path,
- /*relsim_flags*/0,
- /*reduction*/0,
- /*timeout*/0,
- /*getcount_only*/0);
+ cam_release_devq(ccb.ccb_h.path, /*relsim_flags*/0,
+ /*reduction*/0, /*timeout*/0, /*getcount_only*/0);
+ if (error != 0)
+ xpt_print(periph->path, "Synchronize cache failed\n");
cam_periph_unlock(periph);
}
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_da.h
--- a/head/sys/cam/scsi/scsi_da.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/scsi/scsi_da.h Wed Jul 25 16:45:04 2012 +0300
@@ -46,7 +46,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian at tfs.com) Sept 1992
*
- * $FreeBSD: head/sys/cam/scsi/scsi_da.h 229997 2012-01-12 00:34:33Z ken $
+ * $FreeBSD: head/sys/cam/scsi/scsi_da.h 237452 2012-06-22 18:57:06Z ken $
*/
#ifndef _SCSI_SCSI_DA_H
@@ -111,6 +111,7 @@
u_int8_t reserved[4];
u_int8_t alloc_length[2];
+#define SRDD10_MAX_LENGTH 0xffff
u_int8_t control;
};
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_enc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/cam/scsi/scsi_enc.c Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,1023 @@
+/*-
+ * Copyright (c) 2000 Matthew Jacob
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. 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 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: head/sys/cam/scsi/scsi_enc.c 237328 2012-06-20 17:08:00Z ken $");
+
+#include <sys/param.h>
+
+#include <sys/conf.h>
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/sx.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+
+#include <machine/stdarg.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_periph.h>
+#include <cam/cam_xpt_periph.h>
+
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_message.h>
+#include <cam/scsi/scsi_enc.h>
+#include <cam/scsi/scsi_enc_internal.h>
+
+#include <opt_enc.h>
+
+MALLOC_DEFINE(M_SCSIENC, "SCSI ENC", "SCSI ENC buffers");
+
+/* Enclosure type independent driver */
+
+#define SEN_ID "UNISYS SUN_SEN"
+#define SEN_ID_LEN 24
+
+static d_open_t enc_open;
+static d_close_t enc_close;
+static d_ioctl_t enc_ioctl;
+static periph_init_t enc_init;
+static periph_ctor_t enc_ctor;
+static periph_oninv_t enc_oninvalidate;
+static periph_dtor_t enc_dtor;
+static periph_start_t enc_start;
+
+static void enc_async(void *, uint32_t, struct cam_path *, void *);
+static enctyp enc_type(struct ccb_getdev *);
+
+SYSCTL_NODE(_kern_cam, OID_AUTO, enc, CTLFLAG_RD, 0,
+ "CAM Enclosure Services driver");
+
+static struct periph_driver encdriver = {
+ enc_init, "ses",
+ TAILQ_HEAD_INITIALIZER(encdriver.units), /* generation */ 0
+};
+
+PERIPHDRIVER_DECLARE(enc, encdriver);
+
+static struct cdevsw enc_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = enc_open,
+ .d_close = enc_close,
+ .d_ioctl = enc_ioctl,
+ .d_name = "ses",
+ .d_flags = D_TRACKCLOSE,
+};
+
+static void
+enc_init(void)
+{
+ cam_status status;
+
+ /*
+ * Install a global async callback. This callback will
+ * receive async callbacks like "new device found".
+ */
+ status = xpt_register_async(AC_FOUND_DEVICE, enc_async, NULL, NULL);
+
+ if (status != CAM_REQ_CMP) {
+ printf("enc: Failed to attach master async callback "
+ "due to status 0x%x!\n", status);
+ }
+}
+
+static void
+enc_devgonecb(void *arg)
+{
+ struct cam_periph *periph;
+
+ periph = (struct cam_periph *)arg;
+
+ cam_periph_release(periph);
+}
+
+static void
+enc_oninvalidate(struct cam_periph *periph)
+{
+ struct enc_softc *enc;
+
+ enc = periph->softc;
+
+ enc->enc_flags |= ENC_FLAG_INVALID;
+
+ /* If the sub-driver has an invalidate routine, call it */
+ if (enc->enc_vec.softc_invalidate != NULL)
+ enc->enc_vec.softc_invalidate(enc);
+
+ /*
+ * Unregister any async callbacks.
+ */
+ xpt_register_async(0, enc_async, periph, periph->path);
+
+ /*
+ * Shutdown our daemon.
+ */
+ enc->enc_flags |= ENC_FLAG_SHUTDOWN;
+ if (enc->enc_daemon != NULL) {
+ /* Signal the ses daemon to terminate. */
+ wakeup(enc->enc_daemon);
+ }
+ callout_drain(&enc->status_updater);
+
+ destroy_dev_sched_cb(enc->enc_dev, enc_devgonecb, periph);
+
+ xpt_print(periph->path, "lost device\n");
+}
+
+static void
+enc_dtor(struct cam_periph *periph)
+{
+ struct enc_softc *enc;
+
+ enc = periph->softc;
+
+ xpt_print(periph->path, "removing device entry\n");
+
+
+ /* If the sub-driver has a cleanup routine, call it */
+ if (enc->enc_vec.softc_cleanup != NULL)
+ enc->enc_vec.softc_cleanup(enc);
+
+ if (enc->enc_boot_hold_ch.ich_func != NULL) {
+ config_intrhook_disestablish(&enc->enc_boot_hold_ch);
+ enc->enc_boot_hold_ch.ich_func = NULL;
+ }
+
+ ENC_FREE(enc);
+}
+
+static void
+enc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
+{
+ struct cam_periph *periph;
+
+ periph = (struct cam_periph *)callback_arg;
+
+ switch(code) {
+ case AC_FOUND_DEVICE:
+ {
+ struct ccb_getdev *cgd;
+ cam_status status;
+ path_id_t path_id;
+
+ cgd = (struct ccb_getdev *)arg;
+ if (arg == NULL) {
+ break;
+ }
+
+ if (enc_type(cgd) == ENC_NONE) {
+ /*
+ * Schedule announcement of the ENC bindings for
+ * this device if it is managed by a SEP.
+ */
+ path_id = xpt_path_path_id(path);
+ xpt_lock_buses();
+ TAILQ_FOREACH(periph, &encdriver.units, unit_links) {
+ struct enc_softc *softc;
+
+ softc = (struct enc_softc *)periph->softc;
+ if (xpt_path_path_id(periph->path) != path_id
+ || softc == NULL
+ || (softc->enc_flags & ENC_FLAG_INITIALIZED)
+ == 0
+ || softc->enc_vec.device_found == NULL)
+ continue;
+
+ softc->enc_vec.device_found(softc);
+ }
+ xpt_unlock_buses();
+ return;
+ }
+
+ status = cam_periph_alloc(enc_ctor, enc_oninvalidate,
+ enc_dtor, enc_start, "ses", CAM_PERIPH_BIO,
+ cgd->ccb_h.path, enc_async, AC_FOUND_DEVICE, cgd);
+
+ if (status != CAM_REQ_CMP && status != CAM_REQ_INPROG) {
+ printf("enc_async: Unable to probe new device due to "
+ "status 0x%x\n", status);
+ }
+ break;
+ }
+ default:
+ cam_periph_async(periph, code, path, arg);
+ break;
+ }
+}
+
+static int
+enc_open(struct cdev *dev, int flags, int fmt, struct thread *td)
+{
+ struct cam_periph *periph;
+ struct enc_softc *softc;
+ int error = 0;
+
+ periph = (struct cam_periph *)dev->si_drv1;
+ if (periph == NULL) {
+ return (ENXIO);
+ }
+
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP)
+ return (ENXIO);
+
+ cam_periph_lock(periph);
+
+ softc = (struct enc_softc *)periph->softc;
+
+ if ((softc->enc_flags & ENC_FLAG_INITIALIZED) == 0) {
+ error = ENXIO;
+ goto out;
+ }
+ if (softc->enc_flags & ENC_FLAG_INVALID) {
+ error = ENXIO;
+ goto out;
+ }
+out:
+ if (error != 0)
+ cam_periph_release_locked(periph);
+
+ cam_periph_unlock(periph);
+
+ return (error);
+}
+
+static int
+enc_close(struct cdev *dev, int flag, int fmt, struct thread *td)
+{
+ struct cam_periph *periph;
+
+ periph = (struct cam_periph *)dev->si_drv1;
+ if (periph == NULL)
+ return (ENXIO);
+
+ cam_periph_release(periph);
+
+ return (0);
+}
+
+static void
+enc_start(struct cam_periph *p, union ccb *sccb)
+{
+ struct enc_softc *enc;
+
+ enc = p->softc;
+ ENC_DLOG(enc, "%s enter imm=%d prio=%d\n",
+ __func__, p->immediate_priority, p->pinfo.priority);
+ if (p->immediate_priority <= p->pinfo.priority) {
+ SLIST_INSERT_HEAD(&p->ccb_list, &sccb->ccb_h, periph_links.sle);
+ p->immediate_priority = CAM_PRIORITY_NONE;
+ wakeup(&p->ccb_list);
+ } else
+ xpt_release_ccb(sccb);
+ ENC_DLOG(enc, "%s exit\n", __func__);
+}
+
+void
+enc_done(struct cam_periph *periph, union ccb *dccb)
+{
+ wakeup(&dccb->ccb_h.cbfcnp);
+}
+
+int
+enc_error(union ccb *ccb, uint32_t cflags, uint32_t sflags)
+{
+ struct enc_softc *softc;
+ struct cam_periph *periph;
+
+ periph = xpt_path_periph(ccb->ccb_h.path);
+ softc = (struct enc_softc *)periph->softc;
+
+ return (cam_periph_error(ccb, cflags, sflags, &softc->saved_ccb));
+}
+
+static int
+enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag,
+ struct thread *td)
+{
+ struct cam_periph *periph;
+ encioc_enc_status_t tmp;
+ encioc_string_t sstr;
+ encioc_elm_status_t elms;
+ encioc_elm_desc_t elmd;
+ encioc_elm_devnames_t elmdn;
+ encioc_element_t *uelm;
+ enc_softc_t *enc;
+ enc_cache_t *cache;
+ void *addr;
+ int error, i;
+
+
+ if (arg_addr)
+ addr = *((caddr_t *) arg_addr);
+ else
+ addr = NULL;
+
+ periph = (struct cam_periph *)dev->si_drv1;
+ if (periph == NULL)
+ return (ENXIO);
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering encioctl\n"));
+
+ cam_periph_lock(periph);
+ enc = (struct enc_softc *)periph->softc;
+ cache = &enc->enc_cache;
+
+ /*
+ * Now check to see whether we're initialized or not.
+ * This actually should never fail as we're not supposed
+ * to get past enc_open w/o successfully initializing
+ * things.
+ */
+ if ((enc->enc_flags & ENC_FLAG_INITIALIZED) == 0) {
+ cam_periph_unlock(periph);
+ return (ENXIO);
+ }
+ cam_periph_unlock(periph);
+
+ error = 0;
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
+ ("trying to do ioctl %#lx\n", cmd));
+
+ /*
+ * If this command can change the device's state,
+ * we must have the device open for writing.
+ *
+ * For commands that get information about the
+ * device- we don't need to lock the peripheral
+ * if we aren't running a command. The periph
+ * also can't go away while a user process has
+ * it open.
+ */
+ switch (cmd) {
+ case ENCIOC_GETNELM:
+ case ENCIOC_GETELMMAP:
+ case ENCIOC_GETENCSTAT:
+ case ENCIOC_GETELMSTAT:
+ case ENCIOC_GETELMDESC:
+ case ENCIOC_GETELMDEVNAMES:
+ break;
+ default:
+ if ((flag & FWRITE) == 0) {
+ return (EBADF);
+ }
+ }
+
+ /*
+ * XXX The values read here are only valid for the current
+ * configuration generation. We need these ioctls
+ * to also pass in/out a generation number.
+ */
+ sx_slock(&enc->enc_cache_lock);
+ switch (cmd) {
+ case ENCIOC_GETNELM:
+ error = copyout(&cache->nelms, addr, sizeof (cache->nelms));
+ break;
+
+ case ENCIOC_GETELMMAP:
+ for (uelm = addr, i = 0; i != cache->nelms; i++) {
+ encioc_element_t kelm;
+ kelm.elm_idx = i;
+ kelm.elm_subenc_id = cache->elm_map[i].subenclosure;
+ kelm.elm_type = cache->elm_map[i].enctype;
+ error = copyout(&kelm, &uelm[i], sizeof(kelm));
+ if (error)
+ break;
+ }
+ break;
+
+ case ENCIOC_GETENCSTAT:
+ cam_periph_lock(periph);
+ error = enc->enc_vec.get_enc_status(enc, 1);
+ if (error) {
+ cam_periph_unlock(periph);
+ break;
+ }
+ tmp = cache->enc_status;
+ cam_periph_unlock(periph);
+ error = copyout(&tmp, addr, sizeof(tmp));
+ cache->enc_status = tmp;
+ break;
+
+ case ENCIOC_SETENCSTAT:
+ error = copyin(addr, &tmp, sizeof(tmp));
+ if (error)
+ break;
+ cam_periph_lock(periph);
+ error = enc->enc_vec.set_enc_status(enc, tmp, 1);
+ cam_periph_unlock(periph);
+ break;
+
+ case ENCIOC_GETSTRING:
+ case ENCIOC_SETSTRING:
+ if (enc->enc_vec.handle_string == NULL) {
+ error = EINVAL;
+ break;
+ }
+ error = copyin(addr, &sstr, sizeof(sstr));
+ if (error)
+ break;
+ cam_periph_lock(periph);
+ error = enc->enc_vec.handle_string(enc, &sstr, cmd);
+ cam_periph_unlock(periph);
+ break;
+
+ case ENCIOC_GETELMSTAT:
+ error = copyin(addr, &elms, sizeof(elms));
+ if (error)
+ break;
+ if (elms.elm_idx >= cache->nelms) {
+ error = EINVAL;
+ break;
+ }
+ cam_periph_lock(periph);
+ error = enc->enc_vec.get_elm_status(enc, &elms, 1);
+ cam_periph_unlock(periph);
+ if (error)
+ break;
+ error = copyout(&elms, addr, sizeof(elms));
+ break;
+
+ case ENCIOC_GETELMDESC:
+ error = copyin(addr, &elmd, sizeof(elmd));
+ if (error)
+ break;
+ if (elmd.elm_idx >= cache->nelms) {
+ error = EINVAL;
+ break;
+ }
+ if (enc->enc_vec.get_elm_desc != NULL) {
+ error = enc->enc_vec.get_elm_desc(enc, &elmd);
+ if (error)
+ break;
+ } else
+ elmd.elm_desc_len = 0;
+ error = copyout(&elmd, addr, sizeof(elmd));
+ break;
+
+ case ENCIOC_GETELMDEVNAMES:
+ if (enc->enc_vec.get_elm_devnames == NULL) {
+ error = EINVAL;
+ break;
+ }
+ error = copyin(addr, &elmdn, sizeof(elmdn));
+ if (error)
+ break;
+ if (elmdn.elm_idx >= cache->nelms) {
+ error = EINVAL;
+ break;
+ }
+ cam_periph_lock(periph);
+ error = (*enc->enc_vec.get_elm_devnames)(enc, &elmdn);
+ cam_periph_unlock(periph);
+ if (error)
+ break;
+ error = copyout(&elmdn, addr, sizeof(elmdn));
+ break;
+
+ case ENCIOC_SETELMSTAT:
+ error = copyin(addr, &elms, sizeof(elms));
+ if (error)
+ break;
+
+ if (elms.elm_idx >= cache->nelms) {
+ error = EINVAL;
+ break;
+ }
+ cam_periph_lock(periph);
+ error = enc->enc_vec.set_elm_status(enc, &elms, 1);
+ cam_periph_unlock(periph);
+
+ break;
+
+ case ENCIOC_INIT:
+
+ cam_periph_lock(periph);
+ error = enc->enc_vec.init_enc(enc);
+ cam_periph_unlock(periph);
+ break;
+
+ default:
+ cam_periph_lock(periph);
+ error = cam_periph_ioctl(periph, cmd, arg_addr, enc_error);
+ cam_periph_unlock(periph);
+ break;
+ }
+ sx_sunlock(&enc->enc_cache_lock);
+ return (error);
+}
+
+int
+enc_runcmd(struct enc_softc *enc, char *cdb, int cdbl, char *dptr, int *dlenp)
+{
+ int error, dlen, tdlen;
+ ccb_flags ddf;
+ union ccb *ccb;
+
+ CAM_DEBUG(enc->periph->path, CAM_DEBUG_TRACE,
+ ("entering enc_runcmd\n"));
+ if (dptr) {
+ if ((dlen = *dlenp) < 0) {
+ dlen = -dlen;
+ ddf = CAM_DIR_OUT;
+ } else {
+ ddf = CAM_DIR_IN;
+ }
+ } else {
+ dlen = 0;
+ ddf = CAM_DIR_NONE;
+ }
+
+ if (cdbl > IOCDBLEN) {
+ cdbl = IOCDBLEN;
+ }
+
+ ccb = cam_periph_getccb(enc->periph, 1);
+ if (enc->enc_type == ENC_SEMB_SES || enc->enc_type == ENC_SEMB_SAFT) {
+ tdlen = min(dlen, 1020);
+ tdlen = (tdlen + 3) & ~3;
+ cam_fill_ataio(&ccb->ataio, 0, enc_done, ddf, 0, dptr, tdlen,
+ 30 * 1000);
+ if (cdb[0] == RECEIVE_DIAGNOSTIC)
+ ata_28bit_cmd(&ccb->ataio,
+ ATA_SEP_ATTN, cdb[2], 0x02, tdlen / 4);
+ else if (cdb[0] == SEND_DIAGNOSTIC)
+ ata_28bit_cmd(&ccb->ataio,
+ ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0,
+ 0x82, tdlen / 4);
+ else if (cdb[0] == READ_BUFFER)
+ ata_28bit_cmd(&ccb->ataio,
+ ATA_SEP_ATTN, cdb[2], 0x00, tdlen / 4);
+ else
+ ata_28bit_cmd(&ccb->ataio,
+ ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0,
+ 0x80, tdlen / 4);
+ } else {
+ tdlen = dlen;
+ cam_fill_csio(&ccb->csio, 0, enc_done, ddf, MSG_SIMPLE_Q_TAG,
+ dptr, dlen, sizeof (struct scsi_sense_data), cdbl,
+ 60 * 1000);
+ bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl);
+ }
+
+ error = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS, ENC_FLAGS, NULL);
+ if (error) {
+ if (dptr) {
+ *dlenp = dlen;
+ }
+ } else {
+ if (dptr) {
+ if (ccb->ccb_h.func_code == XPT_ATA_IO)
+ *dlenp = ccb->ataio.resid;
+ else
+ *dlenp = ccb->csio.resid;
+ *dlenp += tdlen - dlen;
+ }
+ }
+ xpt_release_ccb(ccb);
+ CAM_DEBUG(enc->periph->path, CAM_DEBUG_SUBTRACE,
+ ("exiting enc_runcmd: *dlenp = %d\n", *dlenp));
+ return (error);
+}
+
+void
+enc_log(struct enc_softc *enc, const char *fmt, ...)
+{
+ va_list ap;
+
+ printf("%s%d: ", enc->periph->periph_name, enc->periph->unit_number);
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * The code after this point runs on many platforms,
+ * so forgive the slightly awkward and nonconforming
+ * appearance.
+ */
+
+/*
+ * Is this a device that supports enclosure services?
+ *
+ * It's a a pretty simple ruleset- if it is device type 0x0D (13), it's
+ * an ENC device. If it happens to be an old UNISYS SEN device, we can
+ * handle that too.
+ */
+
+#define SAFTE_START 44
+#define SAFTE_END 50
+#define SAFTE_LEN SAFTE_END-SAFTE_START
+
+static enctyp
+enc_type(struct ccb_getdev *cgd)
+{
+ int buflen;
+ unsigned char *iqd;
+
+ if (cgd->protocol == PROTO_SEMB) {
+ iqd = (unsigned char *)&cgd->ident_data;
+ if (STRNCMP(iqd + 43, "S-E-S", 5) == 0)
+ return (ENC_SEMB_SES);
+ else if (STRNCMP(iqd + 43, "SAF-TE", 6) == 0)
+ return (ENC_SEMB_SAFT);
+ return (ENC_NONE);
+
+ } else if (cgd->protocol != PROTO_SCSI)
+ return (ENC_NONE);
+
+ iqd = (unsigned char *)&cgd->inq_data;
+ buflen = min(sizeof(cgd->inq_data),
+ SID_ADDITIONAL_LENGTH(&cgd->inq_data));
+ if (buflen < 8+SEN_ID_LEN)
+ return (ENC_NONE);
+
+ if ((iqd[0] & 0x1f) == T_ENCLOSURE) {
+ if (STRNCMP(&iqd[8], SEN_ID, SEN_ID_LEN) == 0) {
+ return (ENC_SEN);
+ } else if ((iqd[2] & 0x7) > 2) {
+ return (ENC_SES);
+ } else {
+ return (ENC_SES_SCSI2);
+ }
+ return (ENC_NONE);
+ }
+
+#ifdef ENC_ENABLE_PASSTHROUGH
+ if ((iqd[6] & 0x40) && (iqd[2] & 0x7) >= 2) {
+ /*
+ * PassThrough Device.
+ */
+ return (ENC_ENC_PASSTHROUGH);
+ }
+#endif
+
+ /*
+ * The comparison is short for a reason-
+ * some vendors were chopping it short.
+ */
+
+ if (buflen < SAFTE_END - 2) {
+ return (ENC_NONE);
+ }
+
+ if (STRNCMP((char *)&iqd[SAFTE_START], "SAF-TE", SAFTE_LEN - 2) == 0) {
+ return (ENC_SAFT);
+ }
+ return (ENC_NONE);
+}
+
+/*================== Enclosure Monitoring/Processing Daemon ==================*/
+/**
+ * \brief Queue an update request for a given action, if needed.
+ *
+ * \param enc SES softc to queue the request for.
+ * \param action Action requested.
+ */
+void
+enc_update_request(enc_softc_t *enc, uint32_t action)
+{
+ if ((enc->pending_actions & (0x1 << action)) == 0) {
+ enc->pending_actions |= (0x1 << action);
+ ENC_DLOG(enc, "%s: queing requested action %d\n",
+ __func__, action);
+ if (enc->current_action == ENC_UPDATE_NONE)
+ wakeup(enc->enc_daemon);
+ } else {
+ ENC_DLOG(enc, "%s: ignoring requested action %d - "
+ "Already queued\n", __func__, action);
+ }
+}
+
+/**
+ * \brief Invoke the handler of the highest priority pending
+ * state in the SES state machine.
+ *
+ * \param enc The SES instance invoking the state machine.
+ */
+static void
+enc_fsm_step(enc_softc_t *enc)
+{
+ union ccb *ccb;
+ uint8_t *buf;
+ struct enc_fsm_state *cur_state;
+ int error;
+ uint32_t xfer_len;
+
+ ENC_DLOG(enc, "%s enter %p\n", __func__, enc);
+
+ enc->current_action = ffs(enc->pending_actions) - 1;
+ enc->pending_actions &= ~(0x1 << enc->current_action);
+
+ cur_state = &enc->enc_fsm_states[enc->current_action];
+
+ buf = NULL;
+ if (cur_state->buf_size != 0) {
+ cam_periph_unlock(enc->periph);
+ buf = malloc(cur_state->buf_size, M_SCSIENC, M_WAITOK|M_ZERO);
+ cam_periph_lock(enc->periph);
+ }
+
+ error = 0;
+ ccb = NULL;
+ if (cur_state->fill != NULL) {
+ ccb = cam_periph_getccb(enc->periph, CAM_PRIORITY_NORMAL);
+
+ error = cur_state->fill(enc, cur_state, ccb, buf);
+ if (error != 0)
+ goto done;
+
+ error = cam_periph_runccb(ccb, cur_state->error,
+ ENC_CFLAGS,
+ ENC_FLAGS|SF_QUIET_IR, NULL);
+ }
+
+ if (ccb != NULL) {
+ if (ccb->ccb_h.func_code == XPT_ATA_IO)
+ xfer_len = ccb->ataio.dxfer_len - ccb->ataio.resid;
+ else
+ xfer_len = ccb->csio.dxfer_len - ccb->csio.resid;
+ } else
+ xfer_len = 0;
+
+ cam_periph_unlock(enc->periph);
+ cur_state->done(enc, cur_state, ccb, &buf, error, xfer_len);
+ cam_periph_lock(enc->periph);
+
+done:
+ ENC_DLOG(enc, "%s exit - result %d\n", __func__, error);
+ ENC_FREE_AND_NULL(buf);
+ if (ccb != NULL)
+ xpt_release_ccb(ccb);
+}
+
+/**
+ * \invariant Called with cam_periph mutex held.
+ */
+static void
+enc_status_updater(void *arg)
+{
+ enc_softc_t *enc;
+
+ enc = arg;
+ if (enc->enc_vec.poll_status != NULL)
+ enc->enc_vec.poll_status(enc);
+}
+
+static void
+enc_daemon(void *arg)
+{
+ enc_softc_t *enc;
+
+ enc = arg;
+
+ cam_periph_lock(enc->periph);
+ while ((enc->enc_flags & ENC_FLAG_SHUTDOWN) == 0) {
+ if (enc->pending_actions == 0) {
+ struct intr_config_hook *hook;
+
+ /*
+ * Reset callout and msleep, or
+ * issue timed task completion
+ * status command.
+ */
+ enc->current_action = ENC_UPDATE_NONE;
+
+ /*
+ * We've been through our state machine at least
+ * once. Allow the transition to userland.
+ */
+ hook = &enc->enc_boot_hold_ch;
+ if (hook->ich_func != NULL) {
+ config_intrhook_disestablish(hook);
+ hook->ich_func = NULL;
+ }
+
+ callout_reset(&enc->status_updater, 60*hz,
+ enc_status_updater, enc);
+
+ cam_periph_sleep(enc->periph, enc->enc_daemon,
+ PUSER, "idle", 0);
+ } else {
+ enc_fsm_step(enc);
+ }
+ }
+ enc->enc_daemon = NULL;
+ cam_periph_unlock(enc->periph);
+ cam_periph_release(enc->periph);
+ kproc_exit(0);
+}
+
+static int
+enc_kproc_init(enc_softc_t *enc)
+{
+ int result;
+
+ callout_init_mtx(&enc->status_updater, enc->periph->sim->mtx, 0);
+
+ if (cam_periph_acquire(enc->periph) != CAM_REQ_CMP)
+ return (ENXIO);
+
+ result = kproc_create(enc_daemon, enc, &enc->enc_daemon, /*flags*/0,
+ /*stackpgs*/0, "enc_daemon%d",
+ enc->periph->unit_number);
+ if (result == 0) {
+ /* Do an initial load of all page data. */
+ cam_periph_lock(enc->periph);
+ enc->enc_vec.poll_status(enc);
+ cam_periph_unlock(enc->periph);
+ } else
+ cam_periph_release(enc->periph);
+ return (result);
+}
+
+/**
+ * \brief Interrupt configuration hook callback associated with
+ * enc_boot_hold_ch.
+ *
+ * Since interrupts are always functional at the time of enclosure
+ * configuration, there is nothing to be done when the callback occurs.
+ * This hook is only registered to hold up boot processing while initial
+ * eclosure processing occurs.
+ *
+ * \param arg The enclosure softc, but currently unused in this callback.
+ */
+static void
+enc_nop_confighook_cb(void *arg __unused)
+{
+}
+
+static cam_status
+enc_ctor(struct cam_periph *periph, void *arg)
+{
+ cam_status status = CAM_REQ_CMP_ERR;
+ int err;
+ enc_softc_t *enc;
+ struct ccb_getdev *cgd;
+ char *tname;
+
+ cgd = (struct ccb_getdev *)arg;
+ if (periph == NULL) {
+ printf("enc_ctor: periph was NULL!!\n");
+ goto out;
+ }
+
+ if (cgd == NULL) {
+ printf("enc_ctor: no getdev CCB, can't register device\n");
+ goto out;
+ }
+
+ enc = ENC_MALLOCZ(sizeof(*enc));
+ if (enc == NULL) {
+ printf("enc_ctor: Unable to probe new device. "
+ "Unable to allocate enc\n");
+ goto out;
+ }
+ enc->periph = periph;
+ enc->current_action = ENC_UPDATE_INVALID;
+
+ enc->enc_type = enc_type(cgd);
+ sx_init(&enc->enc_cache_lock, "enccache");
+
+ switch (enc->enc_type) {
+ case ENC_SES:
+ case ENC_SES_SCSI2:
+ case ENC_SES_PASSTHROUGH:
+ case ENC_SEMB_SES:
+ err = ses_softc_init(enc);
+ break;
+ case ENC_SAFT:
+ case ENC_SEMB_SAFT:
+ err = safte_softc_init(enc);
+ break;
+ case ENC_SEN:
+ case ENC_NONE:
+ default:
+ ENC_FREE(enc);
+ return (CAM_REQ_CMP_ERR);
+ }
+
+ if (err) {
+ xpt_print(periph->path, "error %d initializing\n", err);
+ goto out;
+ }
+
+ /*
+ * Hold off userland until we have made at least one pass
+ * through our state machine so that physical path data is
+ * present.
+ */
+ if (enc->enc_vec.poll_status != NULL) {
+ enc->enc_boot_hold_ch.ich_func = enc_nop_confighook_cb;
+ enc->enc_boot_hold_ch.ich_arg = enc;
+ config_intrhook_establish(&enc->enc_boot_hold_ch);
+ }
+
+ /*
+ * The softc field is set only once the enc is fully initialized
+ * so that we can rely on this field to detect partially
+ * initialized periph objects in the AC_FOUND_DEVICE handler.
+ */
+ periph->softc = enc;
+
+ cam_periph_unlock(periph);
+ if (enc->enc_vec.poll_status != NULL) {
+ err = enc_kproc_init(enc);
+ if (err) {
+ xpt_print(periph->path,
+ "error %d starting enc_daemon\n", err);
+ goto out;
+ }
+ }
+
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
+ xpt_print(periph->path, "%s: lost periph during "
+ "registration!\n", __func__);
+ cam_periph_lock(periph);
+
+ return (CAM_REQ_CMP_ERR);
+ }
+
+ enc->enc_dev = make_dev(&enc_cdevsw, periph->unit_number,
+ UID_ROOT, GID_OPERATOR, 0600, "%s%d",
+ periph->periph_name, periph->unit_number);
+
+ cam_periph_lock(periph);
+ enc->enc_dev->si_drv1 = periph;
+
+ enc->enc_flags |= ENC_FLAG_INITIALIZED;
+
+ /*
+ * Add an async callback so that we get notified if this
+ * device goes away.
+ */
+ xpt_register_async(AC_LOST_DEVICE, enc_async, periph, periph->path);
+
+ switch (enc->enc_type) {
+ default:
+ case ENC_NONE:
+ tname = "No ENC device";
+ break;
+ case ENC_SES_SCSI2:
+ tname = "SCSI-2 ENC Device";
+ break;
+ case ENC_SES:
+ tname = "SCSI-3 ENC Device";
+ break;
+ case ENC_SES_PASSTHROUGH:
+ tname = "ENC Passthrough Device";
+ break;
+ case ENC_SEN:
+ tname = "UNISYS SEN Device (NOT HANDLED YET)";
+ break;
+ case ENC_SAFT:
+ tname = "SAF-TE Compliant Device";
+ break;
+ case ENC_SEMB_SES:
+ tname = "SEMB SES Device";
+ break;
+ case ENC_SEMB_SAFT:
+ tname = "SEMB SAF-TE Device";
+ break;
+ }
+ xpt_announce_periph(periph, tname);
+ status = CAM_REQ_CMP;
+
+out:
+ if (status != CAM_REQ_CMP)
+ enc_dtor(periph);
+ return (status);
+}
+
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_enc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/cam/scsi/scsi_enc.h Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,219 @@
+/* $FreeBSD: head/sys/cam/scsi/scsi_enc.h 235911 2012-05-24 14:07:44Z mav $ */
+/*-
+ * Copyright (c) 2000 by Matthew Jacob
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not 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
+ * the GNU Public License ("GPL").
+ *
+ * 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 _SCSI_ENC_H_
+#define _SCSI_ENC_H_
+
+#include <cam/scsi/scsi_ses.h>
+
+#define ENCIOC ('s' - 040)
+#define ENCIOC_GETNELM _IO(ENCIOC, 1)
+#define ENCIOC_GETELMMAP _IO(ENCIOC, 2)
+#define ENCIOC_GETENCSTAT _IO(ENCIOC, 3)
+#define ENCIOC_SETENCSTAT _IO(ENCIOC, 4)
+#define ENCIOC_GETELMSTAT _IO(ENCIOC, 5)
+#define ENCIOC_SETELMSTAT _IO(ENCIOC, 6)
+#define ENCIOC_GETTEXT _IO(ENCIOC, 7)
+#define ENCIOC_INIT _IO(ENCIOC, 8)
+#define ENCIOC_GETELMDESC _IO(ENCIOC, 9)
+#define ENCIOC_GETELMDEVNAMES _IO(ENCIOC, 10)
+#define ENCIOC_GETSTRING _IO(ENCIOC, 11)
+#define ENCIOC_SETSTRING _IO(ENCIOC, 12)
+
+/*
+ * Platform Independent Definitions for enclosure devices.
+ */
+/*
+ * SCSI Based Environmental Services Application Defines
+ *
+ * Based almost entirely on SCSI-3 ENC Revision 8A specification,
+ * but slightly abstracted as the underlying device may in fact
+ * be a SAF-TE or vendor unique device.
+ */
+/*
+ * ENC Driver Operations:
+ * (The defines themselves are platform and access method specific)
+ *
+ * ENCIOC_GETNELM
+ * ENCIOC_GETELMMAP
+ * ENCIOC_GETENCSTAT
+ * ENCIOC_SETENCSTAT
+ * ENCIOC_GETELMSTAT
+ * ENCIOC_SETELMSTAT
+ * ENCIOC_INIT
+ *
+ *
+ * An application finds out how many elements an enclosure instance
+ * is managing by performing a ENCIOC_GETNELM operation. It then
+ * performs a ENCIOC_GETELMMAP to get the map that contains the
+ * elment identifiers for all elements (see encioc_element_t below).
+ * This information is static.
+ *
+ * The application may perform ENCIOC_GETELMSTAT operations to retrieve
+ * status on an element (see the enc_elm_status_t structure below),
+ * ENCIOC_SETELMSTAT operations to set status for an element.
+ *
+ * Similarly, overall enclosure status me be fetched or set via
+ * ENCIOC_GETENCSTAT or ENCIOC_SETENCSTAT operations (see encioc_enc_status_t
+ * below).
+ *
+ * Readers should note that there is nothing that requires either a set
+ * or a clear operation to actually latch and do anything in the target.
+ *
+ * A ENCIOC_INIT operation causes the enclosure to be initialized.
+ */
+
+/* Element Types */
+typedef enum {
+ ELMTYP_UNSPECIFIED = 0x00,
+ ELMTYP_DEVICE = 0x01,
+ ELMTYP_POWER = 0x02,
+ ELMTYP_FAN = 0x03,
+ ELMTYP_THERM = 0x04,
+ ELMTYP_DOORLOCK = 0x05,
+ ELMTYP_ALARM = 0x06,
+ ELMTYP_ESCC = 0x07, /* Enclosure SCC */
+ ELMTYP_SCC = 0x08, /* SCC */
+ ELMTYP_NVRAM = 0x09,
+ ELMTYP_INV_OP_REASON = 0x0a,
+ ELMTYP_UPS = 0x0b,
+ ELMTYP_DISPLAY = 0x0c,
+ ELMTYP_KEYPAD = 0x0d,
+ ELMTYP_ENCLOSURE = 0x0e,
+ ELMTYP_SCSIXVR = 0x0f,
+ ELMTYP_LANGUAGE = 0x10,
+ ELMTYP_COMPORT = 0x11,
+ ELMTYP_VOM = 0x12,
+ ELMTYP_AMMETER = 0x13,
+ ELMTYP_SCSI_TGT = 0x14,
+ ELMTYP_SCSI_INI = 0x15,
+ ELMTYP_SUBENC = 0x16,
+ ELMTYP_ARRAY_DEV = 0x17,
+ ELMTYP_SAS_EXP = 0x18, /* SAS expander */
+ ELMTYP_SAS_CONN = 0x19 /* SAS connector */
+} elm_type_t;
+
+typedef struct encioc_element {
+ /* Element Index */
+ unsigned int elm_idx;
+
+ /* ID of SubEnclosure containing Element*/
+ unsigned int elm_subenc_id;
+
+ /* Element Type */
+ elm_type_t elm_type;
+} encioc_element_t;
+
+/*
+ * Overall Enclosure Status
+ */
+typedef unsigned char encioc_enc_status_t;
+
+/*
+ * Element Status
+ */
+typedef struct encioc_elm_status {
+ unsigned int elm_idx;
+ unsigned char cstat[4];
+} encioc_elm_status_t;
+
+/*
+ * ENC String structure, for StringIn and StringOut commands; use this with
+ * the ENCIOC_GETSTRING and ENCIOC_SETSTRING ioctls.
+ */
+typedef struct encioc_string {
+ size_t bufsiz; /* IN/OUT: length of string provided/returned */
+#define ENC_STRING_MAX 0xffff
+ uint8_t *buf; /* IN/OUT: string */
+} encioc_string_t;
+
+/*============================================================================*/
+
+/*
+ * SES v2 r20 6.1.10 (pg 39) - Element Descriptor diagnostic page
+ * Tables 21, 22, and 23
+ */
+typedef struct encioc_elm_desc {
+ unsigned int elm_idx; /* IN: elment requested */
+ uint16_t elm_desc_len; /* IN: buffer size; OUT: bytes written */
+ char *elm_desc_str; /* IN/OUT: buffer for descriptor data */
+} encioc_elm_desc_t;
+
+/*
+ * ENCIOC_GETELMDEVNAMES:
+ * ioctl structure to get an element's device names, if available
+ */
+typedef struct encioc_elm_devnames {
+ unsigned int elm_idx; /* IN: element index */
+ size_t elm_names_size;/* IN: size of elm_devnames */
+ size_t elm_names_len; /* OUT: actual size returned */
+ /*
+ * IN/OUT: comma separated list of peripheral driver
+ * instances servicing this element.
+ */
+ char *elm_devnames;
+} encioc_elm_devnames_t;
+
+/* ioctl structure for requesting FC info for a port */
+typedef struct encioc_elm_fc_port {
+ unsigned int elm_idx;
+ unsigned int port_idx;
+ struct ses_elm_fc_port port_data;
+} encioc_elm_fc_port_t;
+
+/* ioctl structure for requesting SAS info for element phys */
+typedef struct encioc_elm_sas_device_phy {
+ unsigned int elm_idx;
+ unsigned int phy_idx;
+ struct ses_elm_sas_device_phy phy_data;
+} enioc_elm_sas_phy_t;
+
+/* ioctl structure for requesting SAS info for an expander phy */
+typedef struct encioc_elm_sas_expander_phy {
+ unsigned int elm_idx;
+ unsigned int phy_idx;
+ struct ses_elm_sas_expander_phy phy_data;
+} encioc_elm_sas_expander_phy_t;
+
+/* ioctl structure for requesting SAS info for a port phy */
+typedef struct encioc_elm_sas_port_phy {
+ unsigned int elm_idx;
+ unsigned int phy_idx;
+ struct ses_elm_sas_port_phy phy_data;
+} enioc_elm_sas_port_phy_t;
+
+/* ioctl structure for requesting additional status for an element */
+typedef struct encioc_addl_status {
+ unsigned int elm_idx;
+ union ses_elm_addlstatus_descr_hdr addl_hdr;
+ union ses_elm_addlstatus_proto_hdr proto_hdr;
+} enioc_addl_status_t;
+
+#endif /* _SCSI_ENC_H_ */
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_enc_internal.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/cam/scsi/scsi_enc_internal.h Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,230 @@
+/*-
+ * Copyright (c) 2000 Matthew Jacob
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. 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 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: head/sys/cam/scsi/scsi_enc_internal.h 235911 2012-05-24 14:07:44Z mav $
+ */
+
+/*
+ * This file contains definitions only intended for use within
+ * sys/cam/scsi/scsi_enc*.c, and not in other kernel components.
+ */
+
+#ifndef __SCSI_ENC_INTERNAL_H__
+#define __SCSI_ENC_INTERNAL_H__
+
+typedef struct enc_element {
+ uint32_t
+ enctype : 8, /* enclosure type */
+ subenclosure : 8, /* subenclosure id */
+ svalid : 1, /* enclosure information valid */
+ overall_status_elem: 1,/*
+ * This object represents generic
+ * status about all objects of this
+ * type.
+ */
+ priv : 14; /* private data, per object */
+ uint8_t encstat[4]; /* state && stats */
+ uint8_t *physical_path; /* Device physical path data. */
+ u_int physical_path_len; /* Length of device path data. */
+ void *elm_private; /* per-type object data */
+} enc_element_t;
+
+typedef enum {
+ ENC_NONE,
+ ENC_SES_SCSI2,
+ ENC_SES,
+ ENC_SES_PASSTHROUGH,
+ ENC_SEN,
+ ENC_SAFT,
+ ENC_SEMB_SES,
+ ENC_SEMB_SAFT
+} enctyp;
+
+/* Platform Independent Driver Internal Definitions for enclosure devices. */
+typedef struct enc_softc enc_softc_t;
+
+struct enc_fsm_state;
+typedef int fsm_fill_handler_t(enc_softc_t *ssc,
+ struct enc_fsm_state *state,
+ union ccb *ccb,
+ uint8_t *buf);
+typedef int fsm_error_handler_t(union ccb *ccb, uint32_t cflags,
+ uint32_t sflags);
+typedef int fsm_done_handler_t(enc_softc_t *ssc,
+ struct enc_fsm_state *state, union ccb *ccb,
+ uint8_t **bufp, int error, int xfer_len);
+
+struct enc_fsm_state {
+ const char *name;
+ int page_code;
+ size_t buf_size;
+ uint32_t timeout;
+ fsm_fill_handler_t *fill;
+ fsm_done_handler_t *done;
+ fsm_error_handler_t *error;
+};
+
+typedef int (enc_softc_init_t)(enc_softc_t *);
+typedef void (enc_softc_invalidate_t)(enc_softc_t *);
+typedef void (enc_softc_cleanup_t)(enc_softc_t *);
+typedef int (enc_init_enc_t)(enc_softc_t *);
+typedef int (enc_get_enc_status_t)(enc_softc_t *, int);
+typedef int (enc_set_enc_status_t)(enc_softc_t *, encioc_enc_status_t, int);
+typedef int (enc_get_elm_status_t)(enc_softc_t *, encioc_elm_status_t *, int);
+typedef int (enc_set_elm_status_t)(enc_softc_t *, encioc_elm_status_t *, int);
+typedef int (enc_get_elm_desc_t)(enc_softc_t *, encioc_elm_desc_t *);
+typedef int (enc_get_elm_devnames_t)(enc_softc_t *, encioc_elm_devnames_t *);
+typedef int (enc_handle_string_t)(enc_softc_t *, encioc_string_t *, int);
+typedef void (enc_device_found_t)(enc_softc_t *);
+typedef void (enc_poll_status_t)(enc_softc_t *);
+
+struct enc_vec {
+ enc_softc_invalidate_t *softc_invalidate;
+ enc_softc_cleanup_t *softc_cleanup;
+ enc_init_enc_t *init_enc;
+ enc_get_enc_status_t *get_enc_status;
+ enc_set_enc_status_t *set_enc_status;
+ enc_get_elm_status_t *get_elm_status;
+ enc_set_elm_status_t *set_elm_status;
+ enc_get_elm_desc_t *get_elm_desc;
+ enc_get_elm_devnames_t *get_elm_devnames;
+ enc_handle_string_t *handle_string;
+ enc_device_found_t *device_found;
+ enc_poll_status_t *poll_status;
+};
+
+typedef struct enc_cache {
+ enc_element_t *elm_map; /* objects */
+ int nelms; /* number of objects */
+ encioc_enc_status_t enc_status; /* overall status */
+ void *private; /* per-type private data */
+} enc_cache_t;
+
+/* Enclosure instance toplevel structure */
+struct enc_softc {
+ enctyp enc_type; /* type of enclosure */
+ struct enc_vec enc_vec; /* vector to handlers */
+ void *enc_private; /* per-type private data */
+
+ /**
+ * "Published" configuration and state data available to
+ * external consumers.
+ */
+ enc_cache_t enc_cache;
+
+ /**
+ * Configuration and state data being actively updated
+ * by the enclosure daemon.
+ */
+ enc_cache_t enc_daemon_cache;
+
+ struct sx enc_cache_lock;
+ uint8_t enc_flags;
+#define ENC_FLAG_INVALID 0x01
+#define ENC_FLAG_INITIALIZED 0x02
+#define ENC_FLAG_SHUTDOWN 0x04
+ union ccb saved_ccb;
+ struct cdev *enc_dev;
+ struct cam_periph *periph;
+
+ /* Bitmap of pending operations. */
+ uint32_t pending_actions;
+
+ /* The action on which the state machine is currently working. */
+ uint32_t current_action;
+#define ENC_UPDATE_NONE 0x00
+#define ENC_UPDATE_INVALID 0xff
+
+ /* Callout for auto-updating enclosure status */
+ struct callout status_updater;
+
+ struct proc *enc_daemon;
+
+ struct enc_fsm_state *enc_fsm_states;
+
+ struct intr_config_hook enc_boot_hold_ch;
+};
+
+static inline enc_cache_t *
+enc_other_cache(enc_softc_t *enc, enc_cache_t *primary)
+{
+ return (primary == &enc->enc_cache
+ ? &enc->enc_daemon_cache : &enc->enc_cache);
+}
+
+/* SES Management mode page - SES2r20 Table 59 */
+struct ses_mgmt_mode_page {
+ struct scsi_mode_header_6 header;
+ struct scsi_mode_blk_desc blk_desc;
+ uint8_t byte0; /* ps : 1, spf : 1, page_code : 6 */
+#define SES_MGMT_MODE_PAGE_CODE 0x14
+ uint8_t length;
+#define SES_MGMT_MODE_PAGE_LEN 6
+ uint8_t reserved[3];
+ uint8_t byte5; /* reserved : 7, enbltc : 1 */
+#define SES_MGMT_TIMED_COMP_EN 0x1
+ uint8_t max_comp_time[2];
+};
+
+/* Enclosure core interface for sub-drivers */
+int enc_runcmd(struct enc_softc *, char *, int, char *, int *);
+void enc_log(struct enc_softc *, const char *, ...);
+void enc_done(struct cam_periph *, union ccb *);
+int enc_error(union ccb *, uint32_t, uint32_t);
+void enc_update_request(enc_softc_t *, uint32_t);
+
+/* SES Native interface */
+enc_softc_init_t ses_softc_init;
+
+/* SAF-TE interface */
+enc_softc_init_t safte_softc_init;
+
+/* Helper macros */
+MALLOC_DECLARE(M_SCSIENC);
+#define ENC_CFLAGS CAM_RETRY_SELTO
+#define ENC_FLAGS SF_NO_PRINT | SF_RETRY_UA
+#define STRNCMP strncmp
+#define PRINTF printf
+#define ENC_LOG enc_log
+#if defined(DEBUG) || defined(ENC_DEBUG)
+#define ENC_DLOG enc_log
+#else
+#define ENC_DLOG if (0) enc_log
+#endif
+#define ENC_VLOG if (bootverbose) enc_log
+#define ENC_MALLOC(amt) malloc(amt, M_SCSIENC, M_NOWAIT)
+#define ENC_MALLOCZ(amt) malloc(amt, M_SCSIENC, M_ZERO|M_NOWAIT)
+/* Cast away const avoiding GCC warnings. */
+#define ENC_FREE(ptr) free((void *)((uintptr_t)ptr), M_SCSIENC)
+#define ENC_FREE_AND_NULL(ptr) do { \
+ if (ptr != NULL) { \
+ ENC_FREE(ptr); \
+ ptr = NULL; \
+ } \
+} while(0)
+#define MEMZERO bzero
+#define MEMCPY(dest, src, amt) bcopy(src, dest, amt)
+
+#endif /* __SCSI_ENC_INTERNAL_H__ */
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_enc_safte.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/cam/scsi/scsi_enc_safte.c Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,1137 @@
+/*-
+ * Copyright (c) 2000 Matthew Jacob
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. 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 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: head/sys/cam/scsi/scsi_enc_safte.c 235911 2012-05-24 14:07:44Z mav $");
+
+#include <sys/param.h>
+
+#include <sys/conf.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/sx.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_periph.h>
+
+#include <cam/scsi/scsi_enc.h>
+#include <cam/scsi/scsi_enc_internal.h>
+#include <cam/scsi/scsi_message.h>
+
+#include <opt_enc.h>
+
+/*
+ * SAF-TE Type Device Emulation
+ */
+
+static int safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag);
+
+#define ALL_ENC_STAT (SES_ENCSTAT_CRITICAL | SES_ENCSTAT_UNRECOV | \
+ SES_ENCSTAT_NONCRITICAL | SES_ENCSTAT_INFO)
+/*
+ * SAF-TE specific defines- Mandatory ones only...
+ */
+
+/*
+ * READ BUFFER ('get' commands) IDs- placed in offset 2 of cdb
+ */
+#define SAFTE_RD_RDCFG 0x00 /* read enclosure configuration */
+#define SAFTE_RD_RDESTS 0x01 /* read enclosure status */
+#define SAFTE_RD_RDDSTS 0x04 /* read drive slot status */
+#define SAFTE_RD_RDGFLG 0x05 /* read global flags */
+
+/*
+ * WRITE BUFFER ('set' commands) IDs- placed in offset 0 of databuf
+ */
+#define SAFTE_WT_DSTAT 0x10 /* write device slot status */
+#define SAFTE_WT_SLTOP 0x12 /* perform slot operation */
+#define SAFTE_WT_FANSPD 0x13 /* set fan speed */
+#define SAFTE_WT_ACTPWS 0x14 /* turn on/off power supply */
+#define SAFTE_WT_GLOBAL 0x15 /* send global command */
+
+#define SAFT_SCRATCH 64
+#define SCSZ 0x8000
+
+typedef enum {
+ SAFTE_UPDATE_NONE,
+ SAFTE_UPDATE_READCONFIG,
+ SAFTE_UPDATE_READGFLAGS,
+ SAFTE_UPDATE_READENCSTATUS,
+ SAFTE_UPDATE_READSLOTSTATUS,
+ SAFTE_PROCESS_CONTROL_REQS,
+ SAFTE_NUM_UPDATE_STATES
+} safte_update_action;
+
+static fsm_fill_handler_t safte_fill_read_buf_io;
+static fsm_fill_handler_t safte_fill_control_request;
+static fsm_done_handler_t safte_process_config;
+static fsm_done_handler_t safte_process_gflags;
+static fsm_done_handler_t safte_process_status;
+static fsm_done_handler_t safte_process_slotstatus;
+static fsm_done_handler_t safte_process_control_request;
+
+static struct enc_fsm_state enc_fsm_states[SAFTE_NUM_UPDATE_STATES] =
+{
+ { "SAFTE_UPDATE_NONE", 0, 0, 0, NULL, NULL, NULL },
+ {
+ "SAFTE_UPDATE_READCONFIG",
+ SAFTE_RD_RDCFG,
+ SAFT_SCRATCH,
+ 60 * 1000,
+ safte_fill_read_buf_io,
+ safte_process_config,
+ enc_error
+ },
+ {
+ "SAFTE_UPDATE_READGFLAGS",
+ SAFTE_RD_RDGFLG,
+ 16,
+ 60 * 1000,
+ safte_fill_read_buf_io,
+ safte_process_gflags,
+ enc_error
+ },
+ {
+ "SAFTE_UPDATE_READENCSTATUS",
+ SAFTE_RD_RDESTS,
+ SCSZ,
+ 60 * 1000,
+ safte_fill_read_buf_io,
+ safte_process_status,
+ enc_error
+ },
+ {
+ "SAFTE_UPDATE_READSLOTSTATUS",
+ SAFTE_RD_RDDSTS,
+ SCSZ,
+ 60 * 1000,
+ safte_fill_read_buf_io,
+ safte_process_slotstatus,
+ enc_error
+ },
+ {
+ "SAFTE_PROCESS_CONTROL_REQS",
+ 0,
+ SCSZ,
+ 60 * 1000,
+ safte_fill_control_request,
+ safte_process_control_request,
+ enc_error
+ }
+};
+
+typedef struct safte_control_request {
+ int elm_idx;
+ uint8_t elm_stat[4];
+ int result;
+ TAILQ_ENTRY(safte_control_request) links;
+} safte_control_request_t;
+TAILQ_HEAD(safte_control_reqlist, safte_control_request);
+typedef struct safte_control_reqlist safte_control_reqlist_t;
+enum {
+ SES_SETSTATUS_ENC_IDX = -1
+};
+
+static void
+safte_terminate_control_requests(safte_control_reqlist_t *reqlist, int result)
+{
+ safte_control_request_t *req;
+
+ while ((req = TAILQ_FIRST(reqlist)) != NULL) {
+ TAILQ_REMOVE(reqlist, req, links);
+ req->result = result;
+ wakeup(req);
+ }
+}
+
+struct scfg {
+ /*
+ * Cached Configuration
+ */
+ uint8_t Nfans; /* Number of Fans */
+ uint8_t Npwr; /* Number of Power Supplies */
+ uint8_t Nslots; /* Number of Device Slots */
+ uint8_t DoorLock; /* Door Lock Installed */
+ uint8_t Ntherm; /* Number of Temperature Sensors */
+ uint8_t Nspkrs; /* Number of Speakers */
+ uint8_t Ntstats; /* Number of Thermostats */
+ /*
+ * Cached Flag Bytes for Global Status
+ */
+ uint8_t flag1;
+ uint8_t flag2;
+ /*
+ * What object index ID is where various slots start.
+ */
+ uint8_t pwroff;
+ uint8_t slotoff;
+#define SAFT_ALARM_OFFSET(cc) (cc)->slotoff - 1
+
+ encioc_enc_status_t adm_status;
+ encioc_enc_status_t enc_status;
+ encioc_enc_status_t slot_status;
+
+ safte_control_reqlist_t requests;
+ safte_control_request_t *current_request;
+ int current_request_stage;
+ int current_request_stages;
+};
+
+#define SAFT_FLG1_ALARM 0x1
+#define SAFT_FLG1_GLOBFAIL 0x2
+#define SAFT_FLG1_GLOBWARN 0x4
+#define SAFT_FLG1_ENCPWROFF 0x8
+#define SAFT_FLG1_ENCFANFAIL 0x10
+#define SAFT_FLG1_ENCPWRFAIL 0x20
+#define SAFT_FLG1_ENCDRVFAIL 0x40
+#define SAFT_FLG1_ENCDRVWARN 0x80
+
+#define SAFT_FLG2_LOCKDOOR 0x4
+#define SAFT_PRIVATE sizeof (struct scfg)
+
+static char *safte_2little = "Too Little Data Returned (%d) at line %d\n";
+#define SAFT_BAIL(r, x) \
+ if ((r) >= (x)) { \
+ ENC_LOG(enc, safte_2little, x, __LINE__);\
+ return (EIO); \
+ }
+
+int emulate_array_devices = 1;
+SYSCTL_DECL(_kern_cam_enc);
+SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RW,
+ &emulate_array_devices, 0, "Emulate Array Devices for SAF-TE");
+TUNABLE_INT("kern.cam.enc.emulate_array_devices", &emulate_array_devices);
+
+static int
+safte_fill_read_buf_io(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t *buf)
+{
+
+ if (state->page_code != SAFTE_RD_RDCFG &&
+ enc->enc_cache.nelms == 0) {
+ enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
+ return (-1);
+ }
+
+ if (enc->enc_type == ENC_SEMB_SAFT) {
+ semb_read_buffer(&ccb->ataio, /*retries*/5,
+ enc_done, MSG_SIMPLE_Q_TAG,
+ state->page_code, buf, state->buf_size,
+ state->timeout);
+ } else {
+ scsi_read_buffer(&ccb->csio, /*retries*/5,
+ enc_done, MSG_SIMPLE_Q_TAG, 1,
+ state->page_code, 0, buf, state->buf_size,
+ SSD_FULL_SIZE, state->timeout);
+ }
+ return (0);
+}
+
+static int
+safte_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ struct scfg *cfg;
+ uint8_t *buf = *bufp;
+ int i, r;
+
+ cfg = enc->enc_private;
+ if (cfg == NULL)
+ return (ENXIO);
+ if (error != 0)
+ return (error);
+ if (xfer_len < 6) {
+ ENC_LOG(enc, "too little data (%d) for configuration\n",
+ xfer_len);
+ return (EIO);
+ }
+ cfg->Nfans = buf[0];
+ cfg->Npwr = buf[1];
+ cfg->Nslots = buf[2];
+ cfg->DoorLock = buf[3];
+ cfg->Ntherm = buf[4];
+ cfg->Nspkrs = buf[5];
+ if (xfer_len >= 7)
+ cfg->Ntstats = buf[6] & 0x0f;
+ else
+ cfg->Ntstats = 0;
+ ENC_VLOG(enc, "Nfans %d Npwr %d Nslots %d Lck %d Ntherm %d Nspkrs %d "
+ "Ntstats %d\n",
+ cfg->Nfans, cfg->Npwr, cfg->Nslots, cfg->DoorLock, cfg->Ntherm,
+ cfg->Nspkrs, cfg->Ntstats);
+
+ enc->enc_cache.nelms = cfg->Nfans + cfg->Npwr + cfg->Nslots +
+ cfg->DoorLock + cfg->Ntherm + cfg->Nspkrs + cfg->Ntstats + 1;
+ ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
+ enc->enc_cache.elm_map =
+ ENC_MALLOCZ(enc->enc_cache.nelms * sizeof(enc_element_t));
+ if (enc->enc_cache.elm_map == NULL) {
+ enc->enc_cache.nelms = 0;
+ return (ENOMEM);
+ }
+
+ r = 0;
+ /*
+ * Note that this is all arranged for the convenience
+ * in later fetches of status.
+ */
+ for (i = 0; i < cfg->Nfans; i++)
+ enc->enc_cache.elm_map[r++].enctype = ELMTYP_FAN;
+ cfg->pwroff = (uint8_t) r;
+ for (i = 0; i < cfg->Npwr; i++)
+ enc->enc_cache.elm_map[r++].enctype = ELMTYP_POWER;
+ for (i = 0; i < cfg->DoorLock; i++)
+ enc->enc_cache.elm_map[r++].enctype = ELMTYP_DOORLOCK;
+ if (cfg->Nspkrs > 0)
+ enc->enc_cache.elm_map[r++].enctype = ELMTYP_ALARM;
+ for (i = 0; i < cfg->Ntherm; i++)
+ enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
+ for (i = 0; i <= cfg->Ntstats; i++)
+ enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
+ cfg->slotoff = (uint8_t) r;
+ for (i = 0; i < cfg->Nslots; i++)
+ enc->enc_cache.elm_map[r++].enctype =
+ emulate_array_devices ? ELMTYP_ARRAY_DEV :
+ ELMTYP_DEVICE;
+
+ enc_update_request(enc, SAFTE_UPDATE_READGFLAGS);
+ enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
+ enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
+
+ return (0);
+}
+
+static int
+safte_process_gflags(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ struct scfg *cfg;
+ uint8_t *buf = *bufp;
+
+ cfg = enc->enc_private;
+ if (cfg == NULL)
+ return (ENXIO);
+ if (error != 0)
+ return (error);
+ SAFT_BAIL(3, xfer_len);
+ cfg->flag1 = buf[1];
+ cfg->flag2 = buf[2];
+
+ cfg->adm_status = 0;
+ if (cfg->flag1 & SAFT_FLG1_GLOBFAIL)
+ cfg->adm_status |= SES_ENCSTAT_CRITICAL;
+ else if (cfg->flag1 & SAFT_FLG1_GLOBWARN)
+ cfg->adm_status |= SES_ENCSTAT_NONCRITICAL;
+
+ return (0);
+}
+
+static int
+safte_process_status(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ struct scfg *cfg;
+ uint8_t *buf = *bufp;
+ int oid, r, i, nitems;
+ uint16_t tempflags;
+ enc_cache_t *cache = &enc->enc_cache;
+
+ cfg = enc->enc_private;
+ if (cfg == NULL)
+ return (ENXIO);
+ if (error != 0)
+ return (error);
+
+ oid = r = 0;
+ cfg->enc_status = 0;
+
+ for (nitems = i = 0; i < cfg->Nfans; i++) {
+ SAFT_BAIL(r, xfer_len);
+ /*
+ * 0 = Fan Operational
+ * 1 = Fan is malfunctioning
+ * 2 = Fan is not present
+ * 0x80 = Unknown or Not Reportable Status
+ */
+ cache->elm_map[oid].encstat[1] = 0; /* resvd */
+ cache->elm_map[oid].encstat[2] = 0; /* resvd */
+ if (cfg->flag1 & SAFT_FLG1_ENCFANFAIL)
+ cache->elm_map[oid].encstat[3] |= 0x40;
+ else
+ cache->elm_map[oid].encstat[3] &= ~0x40;
+ switch ((int)buf[r]) {
+ case 0:
+ nitems++;
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
+ if ((cache->elm_map[oid].encstat[3] & 0x37) == 0)
+ cache->elm_map[oid].encstat[3] |= 0x27;
+ break;
+
+ case 1:
+ cache->elm_map[oid].encstat[0] =
+ SES_OBJSTAT_CRIT;
+ /*
+ * FAIL and FAN STOPPED synthesized
+ */
+ cache->elm_map[oid].encstat[3] |= 0x10;
+ cache->elm_map[oid].encstat[3] &= ~0x07;
+ /*
+ * Enclosure marked with CRITICAL error
+ * if only one fan or no thermometers,
+ * else the NONCRITICAL error is set.
+ */
+ if (cfg->Nfans == 1 || (cfg->Ntherm + cfg->Ntstats) == 0)
+ cfg->enc_status |= SES_ENCSTAT_CRITICAL;
+ else
+ cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
+ break;
+ case 2:
+ cache->elm_map[oid].encstat[0] =
+ SES_OBJSTAT_NOTINSTALLED;
+ cache->elm_map[oid].encstat[3] |= 0x10;
+ cache->elm_map[oid].encstat[3] &= ~0x07;
+ /*
+ * Enclosure marked with CRITICAL error
+ * if only one fan or no thermometers,
+ * else the NONCRITICAL error is set.
+ */
+ if (cfg->Nfans == 1)
+ cfg->enc_status |= SES_ENCSTAT_CRITICAL;
+ else
+ cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
+ break;
+ case 0x80:
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
+ cache->elm_map[oid].encstat[3] = 0;
+ cfg->enc_status |= SES_ENCSTAT_INFO;
+ break;
+ default:
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED;
+ ENC_LOG(enc, "Unknown fan%d status 0x%x\n", i,
+ buf[r] & 0xff);
+ break;
+ }
+ cache->elm_map[oid++].svalid = 1;
+ r++;
+ }
+
+ /*
+ * No matter how you cut it, no cooling elements when there
+ * should be some there is critical.
+ */
+ if (cfg->Nfans && nitems == 0)
+ cfg->enc_status |= SES_ENCSTAT_CRITICAL;
+
+ for (i = 0; i < cfg->Npwr; i++) {
+ SAFT_BAIL(r, xfer_len);
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
+ cache->elm_map[oid].encstat[1] = 0; /* resvd */
+ cache->elm_map[oid].encstat[2] = 0; /* resvd */
+ cache->elm_map[oid].encstat[3] = 0x20; /* requested on */
+ switch (buf[r]) {
+ case 0x00: /* pws operational and on */
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
+ break;
+ case 0x01: /* pws operational and off */
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
+ cache->elm_map[oid].encstat[3] = 0x10;
+ cfg->enc_status |= SES_ENCSTAT_INFO;
+ break;
+ case 0x10: /* pws is malfunctioning and commanded on */
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
+ cache->elm_map[oid].encstat[3] = 0x61;
+ cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
+ break;
+
+ case 0x11: /* pws is malfunctioning and commanded off */
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
+ cache->elm_map[oid].encstat[3] = 0x51;
+ cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
+ break;
+ case 0x20: /* pws is not present */
+ cache->elm_map[oid].encstat[0] =
+ SES_OBJSTAT_NOTINSTALLED;
+ cache->elm_map[oid].encstat[3] = 0;
+ cfg->enc_status |= SES_ENCSTAT_INFO;
+ break;
+ case 0x21: /* pws is present */
+ /*
+ * This is for enclosures that cannot tell whether the
+ * device is on or malfunctioning, but know that it is
+ * present. Just fall through.
+ */
+ /* FALLTHROUGH */
+ case 0x80: /* Unknown or Not Reportable Status */
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
+ cache->elm_map[oid].encstat[3] = 0;
+ cfg->enc_status |= SES_ENCSTAT_INFO;
+ break;
+ default:
+ ENC_LOG(enc, "unknown power supply %d status (0x%x)\n",
+ i, buf[r] & 0xff);
+ break;
+ }
+ enc->enc_cache.elm_map[oid++].svalid = 1;
+ r++;
+ }
+
+ /*
+ * Copy Slot SCSI IDs
+ */
+ for (i = 0; i < cfg->Nslots; i++) {
+ SAFT_BAIL(r, xfer_len);
+ if (cache->elm_map[cfg->slotoff + i].enctype == ELMTYP_DEVICE)
+ cache->elm_map[cfg->slotoff + i].encstat[1] = buf[r];
+ r++;
+ }
+
+ /*
+ * We always have doorlock status, no matter what,
+ * but we only save the status if we have one.
+ */
+ SAFT_BAIL(r, xfer_len);
+ if (cfg->DoorLock) {
+ /*
+ * 0 = Door Locked
+ * 1 = Door Unlocked, or no Lock Installed
+ * 0x80 = Unknown or Not Reportable Status
+ */
+ cache->elm_map[oid].encstat[1] = 0;
+ cache->elm_map[oid].encstat[2] = 0;
+ switch (buf[r]) {
+ case 0:
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
+ cache->elm_map[oid].encstat[3] = 0;
+ break;
+ case 1:
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
+ cache->elm_map[oid].encstat[3] = 1;
+ break;
+ case 0x80:
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
+ cache->elm_map[oid].encstat[3] = 0;
+ cfg->enc_status |= SES_ENCSTAT_INFO;
+ break;
+ default:
+ cache->elm_map[oid].encstat[0] =
+ SES_OBJSTAT_UNSUPPORTED;
+ ENC_LOG(enc, "unknown lock status 0x%x\n",
+ buf[r] & 0xff);
+ break;
+ }
+ cache->elm_map[oid++].svalid = 1;
+ }
+ r++;
+
+ /*
+ * We always have speaker status, no matter what,
+ * but we only save the status if we have one.
+ */
+ SAFT_BAIL(r, xfer_len);
+ if (cfg->Nspkrs) {
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
+ cache->elm_map[oid].encstat[1] = 0;
+ cache->elm_map[oid].encstat[2] = 0;
+ if (buf[r] == 0) {
+ cache->elm_map[oid].encstat[0] |= SESCTL_DISABLE;
+ cache->elm_map[oid].encstat[3] |= 0x40;
+ }
+ cache->elm_map[oid++].svalid = 1;
+ }
+ r++;
+
+ /*
+ * Now, for "pseudo" thermometers, we have two bytes
+ * of information in enclosure status- 16 bits. Actually,
+ * the MSB is a single TEMP ALERT flag indicating whether
+ * any other bits are set, but, thanks to fuzzy thinking,
+ * in the SAF-TE spec, this can also be set even if no
+ * other bits are set, thus making this really another
+ * binary temperature sensor.
+ */
+
+ SAFT_BAIL(r + cfg->Ntherm, xfer_len);
+ tempflags = buf[r + cfg->Ntherm];
+ SAFT_BAIL(r + cfg->Ntherm + 1, xfer_len);
+ tempflags |= (tempflags << 8) | buf[r + cfg->Ntherm + 1];
+
+ for (i = 0; i < cfg->Ntherm; i++) {
+ SAFT_BAIL(r, xfer_len);
+ /*
+ * Status is a range from -10 to 245 deg Celsius,
+ * which we need to normalize to -20 to -245 according
+ * to the latest SCSI spec, which makes little
+ * sense since this would overflow an 8bit value.
+ * Well, still, the base normalization is -20,
+ * not -10, so we have to adjust.
+ *
+ * So what's over and under temperature?
+ * Hmm- we'll state that 'normal' operating
+ * is 10 to 40 deg Celsius.
+ */
+
+ /*
+ * Actually.... All of the units that people out in the world
+ * seem to have do not come even close to setting a value that
+ * complies with this spec.
+ *
+ * The closest explanation I could find was in an
+ * LSI-Logic manual, which seemed to indicate that
+ * this value would be set by whatever the I2C code
+ * would interpolate from the output of an LM75
+ * temperature sensor.
+ *
+ * This means that it is impossible to use the actual
+ * numeric value to predict anything. But we don't want
+ * to lose the value. So, we'll propagate the *uncorrected*
+ * value and set SES_OBJSTAT_NOTAVAIL. We'll depend on the
+ * temperature flags for warnings.
+ */
+ if (tempflags & (1 << i)) {
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
+ cfg->enc_status |= SES_ENCSTAT_CRITICAL;
+ } else
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
+ cache->elm_map[oid].encstat[1] = 0;
+ cache->elm_map[oid].encstat[2] = buf[r];
+ cache->elm_map[oid].encstat[3] = 0;
+ cache->elm_map[oid++].svalid = 1;
+ r++;
+ }
+
+ for (i = 0; i <= cfg->Ntstats; i++) {
+ cache->elm_map[oid].encstat[1] = 0;
+ if (tempflags & (1 <<
+ ((i == cfg->Ntstats) ? 15 : (cfg->Ntherm + i)))) {
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
+ cache->elm_map[4].encstat[2] = 0xff;
+ /*
+ * Set 'over temperature' failure.
+ */
+ cache->elm_map[oid].encstat[3] = 8;
+ cfg->enc_status |= SES_ENCSTAT_CRITICAL;
+ } else {
+ /*
+ * We used to say 'not available' and synthesize a
+ * nominal 30 deg (C)- that was wrong. Actually,
+ * Just say 'OK', and use the reserved value of
+ * zero.
+ */
+ if ((cfg->Ntherm + cfg->Ntstats) == 0)
+ cache->elm_map[oid].encstat[0] =
+ SES_OBJSTAT_NOTAVAIL;
+ else
+ cache->elm_map[oid].encstat[0] =
+ SES_OBJSTAT_OK;
+ cache->elm_map[oid].encstat[2] = 0;
+ cache->elm_map[oid].encstat[3] = 0;
+ }
+ cache->elm_map[oid++].svalid = 1;
+ }
+ r += 2;
+
+ cache->enc_status =
+ cfg->enc_status | cfg->slot_status | cfg->adm_status;
+ return (0);
+}
+
+static int
+safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ struct scfg *cfg;
+ uint8_t *buf = *bufp;
+ enc_cache_t *cache = &enc->enc_cache;
+ int oid, r, i;
+
+ cfg = enc->enc_private;
+ if (cfg == NULL)
+ return (ENXIO);
+ if (error != 0)
+ return (error);
+ cfg->slot_status = 0;
+ oid = cfg->slotoff;
+ for (r = i = 0; i < cfg->Nslots; i++, r += 4) {
+ SAFT_BAIL(r+3, xfer_len);
+ if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV)
+ cache->elm_map[oid].encstat[1] = 0;
+ cache->elm_map[oid].encstat[2] &= SESCTL_RQSID;
+ cache->elm_map[oid].encstat[3] = 0;
+ if ((buf[r+3] & 0x01) == 0) { /* no device */
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NOTINSTALLED;
+ } else if (buf[r+0] & 0x02) {
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
+ cfg->slot_status |= SES_ENCSTAT_CRITICAL;
+ } else if (buf[r+0] & 0x40) {
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
+ cfg->slot_status |= SES_ENCSTAT_NONCRITICAL;
+ } else {
+ cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
+ }
+ if (buf[r+3] & 0x2) {
+ if (buf[r+3] & 0x01)
+ cache->elm_map[oid].encstat[2] |= SESCTL_RQSRMV;
+ else
+ cache->elm_map[oid].encstat[2] |= SESCTL_RQSINS;
+ }
+ if ((buf[r+3] & 0x04) == 0)
+ cache->elm_map[oid].encstat[3] |= SESCTL_DEVOFF;
+ if (buf[r+0] & 0x02)
+ cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT;
+ if (buf[r+0] & 0x40)
+ cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL;
+ if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV) {
+ if (buf[r+0] & 0x01)
+ cache->elm_map[oid].encstat[1] |= 0x80;
+ if (buf[r+0] & 0x04)
+ cache->elm_map[oid].encstat[1] |= 0x02;
+ if (buf[r+0] & 0x08)
+ cache->elm_map[oid].encstat[1] |= 0x04;
+ if (buf[r+0] & 0x10)
+ cache->elm_map[oid].encstat[1] |= 0x08;
+ if (buf[r+0] & 0x20)
+ cache->elm_map[oid].encstat[1] |= 0x10;
+ if (buf[r+1] & 0x01)
+ cache->elm_map[oid].encstat[1] |= 0x20;
+ if (buf[r+1] & 0x02)
+ cache->elm_map[oid].encstat[1] |= 0x01;
+ }
+ cache->elm_map[oid++].svalid = 1;
+ }
+
+ cache->enc_status =
+ cfg->enc_status | cfg->slot_status | cfg->adm_status;
+ return (0);
+}
+
+static int
+safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t *buf)
+{
+ struct scfg *cfg;
+ enc_element_t *ep, *ep1;
+ safte_control_request_t *req;
+ int i, idx, xfer_len;
+
+ cfg = enc->enc_private;
+ if (cfg == NULL)
+ return (ENXIO);
+
+ if (enc->enc_cache.nelms == 0) {
+ enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
+ return (-1);
+ }
+
+ if (cfg->current_request == NULL) {
+ cfg->current_request = TAILQ_FIRST(&cfg->requests);
+ TAILQ_REMOVE(&cfg->requests, cfg->current_request, links);
+ cfg->current_request_stage = 0;
+ cfg->current_request_stages = 1;
+ }
+ req = cfg->current_request;
+
+ idx = (int)req->elm_idx;
+ if (req->elm_idx == SES_SETSTATUS_ENC_IDX) {
+ cfg->adm_status = req->elm_stat[0] & ALL_ENC_STAT;
+ cfg->flag1 &= ~(SAFT_FLG1_GLOBFAIL|SAFT_FLG1_GLOBWARN);
+ if (req->elm_stat[0] & (SES_ENCSTAT_CRITICAL|SES_ENCSTAT_UNRECOV))
+ cfg->flag1 |= SAFT_FLG1_GLOBFAIL;
+ else if (req->elm_stat[0] & SES_ENCSTAT_NONCRITICAL)
+ cfg->flag1 |= SAFT_FLG1_GLOBWARN;
+ buf[0] = SAFTE_WT_GLOBAL;
+ buf[1] = cfg->flag1;
+ buf[2] = cfg->flag2;
+ buf[3] = 0;
+ xfer_len = 16;
+ } else {
+ ep = &enc->enc_cache.elm_map[idx];
+
+ switch (ep->enctype) {
+ case ELMTYP_DEVICE:
+ case ELMTYP_ARRAY_DEV:
+ switch (cfg->current_request_stage) {
+ case 0:
+ ep->priv = 0;
+ if (req->elm_stat[0] & SESCTL_PRDFAIL)
+ ep->priv |= 0x40;
+ if (req->elm_stat[3] & SESCTL_RQSFLT)
+ ep->priv |= 0x02;
+ if (ep->enctype == ELMTYP_ARRAY_DEV) {
+ if (req->elm_stat[1] & 0x01)
+ ep->priv |= 0x200;
+ if (req->elm_stat[1] & 0x02)
+ ep->priv |= 0x04;
+ if (req->elm_stat[1] & 0x04)
+ ep->priv |= 0x08;
+ if (req->elm_stat[1] & 0x08)
+ ep->priv |= 0x10;
+ if (req->elm_stat[1] & 0x10)
+ ep->priv |= 0x20;
+ if (req->elm_stat[1] & 0x20)
+ ep->priv |= 0x100;
+ if (req->elm_stat[1] & 0x80)
+ ep->priv |= 0x01;
+ }
+ if (ep->priv == 0)
+ ep->priv |= 0x01; /* no errors */
+
+ buf[0] = SAFTE_WT_DSTAT;
+ for (i = 0; i < cfg->Nslots; i++) {
+ ep1 = &enc->enc_cache.elm_map[cfg->slotoff + i];
+ buf[1 + (3 * i)] = ep1->priv;
+ buf[2 + (3 * i)] = ep1->priv >> 8;
+ }
+ xfer_len = cfg->Nslots * 3 + 1;
+#define DEVON(x) (!(((x)[2] & SESCTL_RQSINS) | \
+ ((x)[2] & SESCTL_RQSRMV) | \
+ ((x)[3] & SESCTL_DEVOFF)))
+ if (DEVON(req->elm_stat) != DEVON(ep->encstat))
+ cfg->current_request_stages++;
+#define IDON(x) (!!((x)[2] & SESCTL_RQSID))
+ if (IDON(req->elm_stat) != IDON(ep->encstat))
+ cfg->current_request_stages++;
+ break;
+ case 1:
+ case 2:
+ buf[0] = SAFTE_WT_SLTOP;
+ buf[1] = idx - cfg->slotoff;
+ if (cfg->current_request_stage == 1 &&
+ DEVON(req->elm_stat) != DEVON(ep->encstat)) {
+ if (DEVON(req->elm_stat))
+ buf[2] = 0x01;
+ else
+ buf[2] = 0x02;
+ } else {
+ if (IDON(req->elm_stat))
+ buf[2] = 0x04;
+ else
+ buf[2] = 0x00;
+ ep->encstat[2] &= ~SESCTL_RQSID;
+ ep->encstat[2] |= req->elm_stat[2] &
+ SESCTL_RQSID;
+ }
+ xfer_len = 64;
+ break;
+ default:
+ return (EINVAL);
+ }
+ break;
+ case ELMTYP_POWER:
+ cfg->current_request_stages = 2;
+ switch (cfg->current_request_stage) {
+ case 0:
+ if (req->elm_stat[3] & SESCTL_RQSTFAIL) {
+ cfg->flag1 |= SAFT_FLG1_ENCPWRFAIL;
+ } else {
+ cfg->flag1 &= ~SAFT_FLG1_ENCPWRFAIL;
+ }
+ buf[0] = SAFTE_WT_GLOBAL;
+ buf[1] = cfg->flag1;
+ buf[2] = cfg->flag2;
+ buf[3] = 0;
+ xfer_len = 16;
+ break;
+ case 1:
+ buf[0] = SAFTE_WT_ACTPWS;
+ buf[1] = idx - cfg->pwroff;
+ if (req->elm_stat[3] & SESCTL_RQSTON)
+ buf[2] = 0x01;
+ else
+ buf[2] = 0x00;
+ buf[3] = 0;
+ xfer_len = 16;
+ default:
+ return (EINVAL);
+ }
+ break;
+ case ELMTYP_FAN:
+ if ((req->elm_stat[3] & 0x7) != 0)
+ cfg->current_request_stages = 2;
+ switch (cfg->current_request_stage) {
+ case 0:
+ if (req->elm_stat[3] & SESCTL_RQSTFAIL)
+ cfg->flag1 |= SAFT_FLG1_ENCFANFAIL;
+ else
+ cfg->flag1 &= ~SAFT_FLG1_ENCFANFAIL;
+ buf[0] = SAFTE_WT_GLOBAL;
+ buf[1] = cfg->flag1;
+ buf[2] = cfg->flag2;
+ buf[3] = 0;
+ xfer_len = 16;
+ break;
+ case 1:
+ buf[0] = SAFTE_WT_FANSPD;
+ buf[1] = idx;
+ if (req->elm_stat[3] & SESCTL_RQSTON) {
+ if ((req->elm_stat[3] & 0x7) == 7)
+ buf[2] = 4;
+ else if ((req->elm_stat[3] & 0x7) >= 5)
+ buf[2] = 3;
+ else if ((req->elm_stat[3] & 0x7) >= 3)
+ buf[2] = 2;
+ else
+ buf[2] = 1;
+ } else
+ buf[2] = 0;
+ buf[3] = 0;
+ xfer_len = 16;
+ ep->encstat[3] = req->elm_stat[3] & 0x67;
+ default:
+ return (EINVAL);
+ }
+ break;
+ case ELMTYP_DOORLOCK:
+ if (req->elm_stat[3] & 0x1)
+ cfg->flag2 &= ~SAFT_FLG2_LOCKDOOR;
+ else
+ cfg->flag2 |= SAFT_FLG2_LOCKDOOR;
+ buf[0] = SAFTE_WT_GLOBAL;
+ buf[1] = cfg->flag1;
+ buf[2] = cfg->flag2;
+ buf[3] = 0;
+ xfer_len = 16;
+ break;
+ case ELMTYP_ALARM:
+ if ((req->elm_stat[0] & SESCTL_DISABLE) ||
+ (req->elm_stat[3] & 0x40)) {
+ cfg->flag2 &= ~SAFT_FLG1_ALARM;
+ } else if ((req->elm_stat[3] & 0x0f) != 0) {
+ cfg->flag2 |= SAFT_FLG1_ALARM;
+ } else {
+ cfg->flag2 &= ~SAFT_FLG1_ALARM;
+ }
+ buf[0] = SAFTE_WT_GLOBAL;
+ buf[1] = cfg->flag1;
+ buf[2] = cfg->flag2;
+ buf[3] = 0;
+ xfer_len = 16;
+ ep->encstat[3] = req->elm_stat[3];
+ break;
+ default:
+ return (EINVAL);
+ }
+ }
+
+ if (enc->enc_type == ENC_SEMB_SAFT) {
+ semb_write_buffer(&ccb->ataio, /*retries*/5,
+ enc_done, MSG_SIMPLE_Q_TAG,
+ buf, xfer_len, state->timeout);
+ } else {
+ scsi_write_buffer(&ccb->csio, /*retries*/5,
+ enc_done, MSG_SIMPLE_Q_TAG, 1,
+ 0, 0, buf, xfer_len,
+ SSD_FULL_SIZE, state->timeout);
+ }
+ return (0);
+}
+
+static int
+safte_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ struct scfg *cfg;
+ safte_control_request_t *req;
+ int idx, type;
+
+ cfg = enc->enc_private;
+ if (cfg == NULL)
+ return (ENXIO);
+
+ req = cfg->current_request;
+ if (req->result == 0)
+ req->result = error;
+ if (++cfg->current_request_stage >= cfg->current_request_stages) {
+ idx = req->elm_idx;
+ if (idx == SES_SETSTATUS_ENC_IDX)
+ type = -1;
+ else
+ type = enc->enc_cache.elm_map[idx].enctype;
+ if (type == ELMTYP_DEVICE || type == ELMTYP_ARRAY_DEV)
+ enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
+ else
+ enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
+ cfg->current_request = NULL;
+ wakeup(req);
+ } else {
+ enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
+ }
+ return (0);
+}
+
+static void
+safte_softc_invalidate(enc_softc_t *enc)
+{
+ struct scfg *cfg;
+
+ cfg = enc->enc_private;
+ safte_terminate_control_requests(&cfg->requests, ENXIO);
+}
+
+static void
+safte_softc_cleanup(enc_softc_t *enc)
+{
+
+ ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
+ ENC_FREE_AND_NULL(enc->enc_private);
+ enc->enc_cache.nelms = 0;
+}
+
+static int
+safte_init_enc(enc_softc_t *enc)
+{
+ struct scfg *cfg;
+ int err;
+ static char cdb0[6] = { SEND_DIAGNOSTIC };
+
+ cfg = enc->enc_private;
+ if (cfg == NULL)
+ return (ENXIO);
+
+ err = enc_runcmd(enc, cdb0, 6, NULL, 0);
+ if (err) {
+ return (err);
+ }
+ DELAY(5000);
+ cfg->flag1 = 0;
+ cfg->flag2 = 0;
+ err = safte_set_enc_status(enc, 0, 1);
+ return (err);
+}
+
+static int
+safte_get_enc_status(enc_softc_t *enc, int slpflg)
+{
+
+ return (0);
+}
+
+static int
+safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag)
+{
+ struct scfg *cfg;
+ safte_control_request_t req;
+
+ cfg = enc->enc_private;
+ if (cfg == NULL)
+ return (ENXIO);
+
+ req.elm_idx = SES_SETSTATUS_ENC_IDX;
+ req.elm_stat[0] = encstat & 0xf;
+ req.result = 0;
+
+ TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
+ enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
+ cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
+
+ return (req.result);
+}
+
+static int
+safte_get_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflg)
+{
+ int i = (int)elms->elm_idx;
+
+ elms->cstat[0] = enc->enc_cache.elm_map[i].encstat[0];
+ elms->cstat[1] = enc->enc_cache.elm_map[i].encstat[1];
+ elms->cstat[2] = enc->enc_cache.elm_map[i].encstat[2];
+ elms->cstat[3] = enc->enc_cache.elm_map[i].encstat[3];
+ return (0);
+}
+
+static int
+safte_set_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag)
+{
+ struct scfg *cfg;
+ safte_control_request_t req;
+
+ cfg = enc->enc_private;
+ if (cfg == NULL)
+ return (ENXIO);
+
+ /* If this is clear, we don't do diddly. */
+ if ((elms->cstat[0] & SESCTL_CSEL) == 0)
+ return (0);
+
+ req.elm_idx = elms->elm_idx;
+ memcpy(&req.elm_stat, elms->cstat, sizeof(req.elm_stat));
+ req.result = 0;
+
+ TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
+ enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
+ cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
+
+ return (req.result);
+}
+
+static void
+safte_poll_status(enc_softc_t *enc)
+{
+
+ enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
+ enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
+}
+
+static struct enc_vec safte_enc_vec =
+{
+ .softc_invalidate = safte_softc_invalidate,
+ .softc_cleanup = safte_softc_cleanup,
+ .init_enc = safte_init_enc,
+ .get_enc_status = safte_get_enc_status,
+ .set_enc_status = safte_set_enc_status,
+ .get_elm_status = safte_get_elm_status,
+ .set_elm_status = safte_set_elm_status,
+ .poll_status = safte_poll_status
+};
+
+int
+safte_softc_init(enc_softc_t *enc)
+{
+ struct scfg *cfg;
+
+ enc->enc_vec = safte_enc_vec;
+ enc->enc_fsm_states = enc_fsm_states;
+
+ if (enc->enc_private == NULL) {
+ enc->enc_private = ENC_MALLOCZ(SAFT_PRIVATE);
+ if (enc->enc_private == NULL)
+ return (ENOMEM);
+ }
+ cfg = enc->enc_private;
+
+ enc->enc_cache.nelms = 0;
+ enc->enc_cache.enc_status = 0;
+
+ TAILQ_INIT(&cfg->requests);
+ return (0);
+}
+
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_enc_ses.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/cam/scsi/scsi_enc_ses.c Wed Jul 25 16:45:04 2012 +0300
@@ -0,0 +1,2816 @@
+/*-
+ * Copyright (c) 2000 Matthew Jacob
+ * Copyright (c) 2010 Spectra Logic Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. 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 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.
+ */
+
+/**
+ * \file scsi_enc_ses.c
+ *
+ * Structures and routines specific && private to SES only
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc_ses.c 238739 2012-07-24 13:08:43Z mav $");
+
+#include <sys/param.h>
+
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/sbuf.h>
+#include <sys/sx.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_xpt_periph.h>
+#include <cam/cam_periph.h>
+
+#include <cam/scsi/scsi_message.h>
+#include <cam/scsi/scsi_enc.h>
+#include <cam/scsi/scsi_enc_internal.h>
+
+#include <opt_enc.h>
+
+/* SES Native Type Device Support */
+
+/* SES Diagnostic Page Codes */
+typedef enum {
+ SesSupportedPages = 0x0,
+ SesConfigPage = 0x1,
+ SesControlPage = 0x2,
+ SesStatusPage = SesControlPage,
+ SesHelpTxt = 0x3,
+ SesStringOut = 0x4,
+ SesStringIn = SesStringOut,
+ SesThresholdOut = 0x5,
+ SesThresholdIn = SesThresholdOut,
+ SesArrayControl = 0x6, /* Obsolete in SES v2 */
+ SesArrayStatus = SesArrayControl,
+ SesElementDescriptor = 0x7,
+ SesShortStatus = 0x8,
+ SesEnclosureBusy = 0x9,
+ SesAddlElementStatus = 0xa
+} SesDiagPageCodes;
+
+typedef struct ses_type {
+ const struct ses_elm_type_desc *hdr;
+ const char *text;
+} ses_type_t;
+
+typedef struct ses_comstat {
+ uint8_t comstatus;
+ uint8_t comstat[3];
+} ses_comstat_t;
+
+typedef union ses_addl_data {
+ struct ses_elm_sas_device_phy *sasdev_phys;
+ struct ses_elm_sas_expander_phy *sasexp_phys;
+ struct ses_elm_sas_port_phy *sasport_phys;
+ struct ses_fcobj_port *fc_ports;
+} ses_add_data_t;
+
+typedef struct ses_addl_status {
+ struct ses_elm_addlstatus_base_hdr *hdr;
+ union {
+ union ses_fcobj_hdr *fc;
+ union ses_elm_sas_hdr *sas;
+ } proto_hdr;
+ union ses_addl_data proto_data; /* array sizes stored in header */
+} ses_add_status_t;
+
+typedef struct ses_element {
+ uint8_t eip; /* eip bit is set */
+ uint16_t descr_len; /* length of the descriptor */
+ char *descr; /* descriptor for this object */
+ struct ses_addl_status addl; /* additional status info */
+} ses_element_t;
+
+typedef struct ses_control_request {
+ int elm_idx;
+ ses_comstat_t elm_stat;
+ int result;
+ TAILQ_ENTRY(ses_control_request) links;
+} ses_control_request_t;
+TAILQ_HEAD(ses_control_reqlist, ses_control_request);
+typedef struct ses_control_reqlist ses_control_reqlist_t;
+enum {
+ SES_SETSTATUS_ENC_IDX = -1
+};
+
+static void
+ses_terminate_control_requests(ses_control_reqlist_t *reqlist, int result)
+{
+ ses_control_request_t *req;
+
+ while ((req = TAILQ_FIRST(reqlist)) != NULL) {
+ TAILQ_REMOVE(reqlist, req, links);
+ req->result = result;
+ wakeup(req);
+ }
+}
+
+enum ses_iter_index_values {
+ /**
+ * \brief Value of an initialized but invalid index
+ * in a ses_iterator object.
+ *
+ * This value is used for the individual_element_index of
+ * overal status elements and for all index types when
+ * an iterator is first initialized.
+ */
+ ITERATOR_INDEX_INVALID = -1,
+
+ /**
+ * \brief Value of an index in a ses_iterator object
+ * when the iterator has traversed past the last
+ * valid element..
+ */
+ ITERATOR_INDEX_END = INT_MAX
+};
+
+/**
+ * \brief Structure encapsulating all data necessary to traverse the
+ * elements of a SES configuration.
+ *
+ * The ses_iterator object simplifies the task of iterating through all
+ * elements detected via the SES configuration page by tracking the numerous
+ * element indexes that, instead of memoizing in the softc, we calculate
+ * on the fly during the traversal of the element objects. The various
+ * indexes are necessary due to the varying needs of matching objects in
+ * the different SES pages. Some pages (e.g. Status/Control) contain all
+ * elements, while others (e.g. Additional Element Status) only contain
+ * individual elements (no overal status elements) of particular types.
+ *
+ * To use an iterator, initialize it with ses_iter_init(), and then
+ * use ses_iter_next() to traverse the elements (including the first) in
+ * the configuration. Once an iterator is initiailized with ses_iter_init(),
+ * you may also seek to any particular element by either it's global or
+ * individual element index via the ses_iter_seek_to() function. You may
+ * also return an iterator to the position just before the first element
+ * (i.e. the same state as after an ses_iter_init()), with ses_iter_reset().
+ */
+struct ses_iterator {
+ /**
+ * \brief Backlink to the overal software configuration structure.
+ *
+ * This is included for convenience so the iteration functions
+ * need only take a single, struct ses_iterator *, argument.
+ */
+ enc_softc_t *enc;
+
+ enc_cache_t *cache;
+
+ /**
+ * \brief Index of the type of the current element within the
+ * ses_cache's ses_types array.
+ */
+ int type_index;
+
+ /**
+ * \brief The position (0 based) of this element relative to all other
+ * elements of this type.
+ *
+ * This index resets to zero every time the iterator transitions
+ * to elements of a new type in the configuration.
+ */
+ int type_element_index;
+
+ /**
+ * \brief The position (0 based) of this element relative to all
+ * other individual status elements in the configuration.
+ *
+ * This index ranges from 0 through the number of individual
+ * elements in the configuration. When the iterator returns
+ * an overall status element, individual_element_index is
+ * set to ITERATOR_INDEX_INVALID, to indicate that it does
+ * not apply to the current element.
+ */
+ int individual_element_index;
+
+ /**
+ * \brief The position (0 based) of this element relative to
+ * all elements in the configration.
+ *
+ * This index is appropriate for indexing into enc->ses_elm_map.
+ */
+ int global_element_index;
+
+ /**
+ * \brief The last valid individual element index of this
+ * iterator.
+ *
+ * When an iterator traverses an overal status element, the
+ * individual element index is reset to ITERATOR_INDEX_INVALID
+ * to prevent unintential use of the individual_element_index
+ * field. The saved_individual_element_index allows the iterator
+ * to restore it's position in the individual elements upon
+ * reaching the next individual element.
+ */
+ int saved_individual_element_index;
+};
+
+typedef enum {
+ SES_UPDATE_NONE,
+ SES_UPDATE_PAGES,
+ SES_UPDATE_GETCONFIG,
+ SES_UPDATE_GETSTATUS,
+ SES_UPDATE_GETELMDESCS,
+ SES_UPDATE_GETELMADDLSTATUS,
+ SES_PROCESS_CONTROL_REQS,
+ SES_PUBLISH_PHYSPATHS,
+ SES_PUBLISH_CACHE,
+ SES_NUM_UPDATE_STATES
+} ses_update_action;
+
+static enc_softc_cleanup_t ses_softc_cleanup;
+
+#define SCSZ 0x8000
+
+static fsm_fill_handler_t ses_fill_rcv_diag_io;
+static fsm_fill_handler_t ses_fill_control_request;
+static fsm_done_handler_t ses_process_pages;
+static fsm_done_handler_t ses_process_config;
+static fsm_done_handler_t ses_process_status;
+static fsm_done_handler_t ses_process_elm_descs;
+static fsm_done_handler_t ses_process_elm_addlstatus;
+static fsm_done_handler_t ses_process_control_request;
+static fsm_done_handler_t ses_publish_physpaths;
+static fsm_done_handler_t ses_publish_cache;
+
+static struct enc_fsm_state enc_fsm_states[SES_NUM_UPDATE_STATES] =
+{
+ { "SES_UPDATE_NONE", 0, 0, 0, NULL, NULL, NULL },
+ {
+ "SES_UPDATE_PAGES",
+ SesSupportedPages,
+ SCSZ,
+ 60 * 1000,
+ ses_fill_rcv_diag_io,
+ ses_process_pages,
+ enc_error
+ },
+ {
+ "SES_UPDATE_GETCONFIG",
+ SesConfigPage,
+ SCSZ,
+ 60 * 1000,
+ ses_fill_rcv_diag_io,
+ ses_process_config,
+ enc_error
+ },
+ {
+ "SES_UPDATE_GETSTATUS",
+ SesStatusPage,
+ SCSZ,
+ 60 * 1000,
+ ses_fill_rcv_diag_io,
+ ses_process_status,
+ enc_error
+ },
+ {
+ "SES_UPDATE_GETELMDESCS",
+ SesElementDescriptor,
+ SCSZ,
+ 60 * 1000,
+ ses_fill_rcv_diag_io,
+ ses_process_elm_descs,
+ enc_error
+ },
+ {
+ "SES_UPDATE_GETELMADDLSTATUS",
+ SesAddlElementStatus,
+ SCSZ,
+ 60 * 1000,
+ ses_fill_rcv_diag_io,
+ ses_process_elm_addlstatus,
+ enc_error
+ },
+ {
+ "SES_PROCESS_CONTROL_REQS",
+ SesControlPage,
+ SCSZ,
+ 60 * 1000,
+ ses_fill_control_request,
+ ses_process_control_request,
+ enc_error
+ },
+ {
+ "SES_PUBLISH_PHYSPATHS",
+ 0,
+ 0,
+ 0,
+ NULL,
+ ses_publish_physpaths,
+ NULL
+ },
+ {
+ "SES_PUBLISH_CACHE",
+ 0,
+ 0,
+ 0,
+ NULL,
+ ses_publish_cache,
+ NULL
+ }
+};
+
+typedef struct ses_cache {
+ /* Source for all the configuration data pointers */
+ const struct ses_cfg_page *cfg_page;
+
+ /* References into the config page. */
+ const struct ses_enc_desc * const *subencs;
+ uint8_t ses_ntypes;
+ const ses_type_t *ses_types;
+
+ /* Source for all the status pointers */
+ const struct ses_status_page *status_page;
+
+ /* Source for all the object descriptor pointers */
+ const struct ses_elem_descr_page *elm_descs_page;
+
+ /* Source for all the additional object status pointers */
+ const struct ses_addl_elem_status_page *elm_addlstatus_page;
+
+} ses_cache_t;
+
+typedef struct ses_softc {
+ uint32_t ses_flags;
+#define SES_FLAG_TIMEDCOMP 0x01
+#define SES_FLAG_ADDLSTATUS 0x02
+
+ ses_control_reqlist_t ses_requests;
+ ses_control_reqlist_t ses_pending_requests;
+} ses_softc_t;
+
+/**
+ * \brief Reset a SES iterator to just before the first element
+ * in the configuration.
+ *
+ * \param iter The iterator object to reset.
+ *
+ * The indexes within a reset iterator are invalid and will only
+ * become valid upon completion of a ses_iter_seek_to() or a
+ * ses_iter_next().
+ */
+static void
+ses_iter_reset(struct ses_iterator *iter)
+{
+ /*
+ * Set our indexes to just before the first valid element
+ * of the first type (ITERATOR_INDEX_INVALID == -1). This
+ * simplifies the implementation of ses_iter_next().
+ */
+ iter->type_index = 0;
+ iter->type_element_index = ITERATOR_INDEX_INVALID;
+ iter->global_element_index = ITERATOR_INDEX_INVALID;
+ iter->individual_element_index = ITERATOR_INDEX_INVALID;
+ iter->saved_individual_element_index = ITERATOR_INDEX_INVALID;
+}
+
+/**
+ * \brief Initialize the storage of a SES iterator and reset it to
+ * the position just before the first element of the
+ * configuration.
+ *
+ * \param enc The SES softc for the SES instance whose configuration
+ * will be enumerated by this iterator.
+ * \param iter The iterator object to initialize.
+ */
+static void
+ses_iter_init(enc_softc_t *enc, enc_cache_t *cache, struct ses_iterator *iter)
+{
+ iter->enc = enc;
+ iter->cache = cache;
+ ses_iter_reset(iter);
+}
+
+/**
+ * \brief Traverse the provided SES iterator to the next element
+ * within the configuraiton.
+ *
+ * \param iter The iterator to move.
+ *
+ * \return If a valid next element exists, a pointer to it's enc_element_t.
+ * Otherwise NULL.
+ */
+static enc_element_t *
+ses_iter_next(struct ses_iterator *iter)
+{
+ ses_cache_t *ses_cache;
+ const ses_type_t *element_type;
+
+ ses_cache = iter->cache->private;
+
+ /*
+ * Note: Treat nelms as signed, so we will hit this case
+ * and immediately terminate the iteration if the
+ * configuration has 0 objects.
+ */
+ if (iter->global_element_index >= (int)iter->cache->nelms - 1) {
+
+ /* Elements exhausted. */
+ iter->type_index = ITERATOR_INDEX_END;
+ iter->type_element_index = ITERATOR_INDEX_END;
+ iter->global_element_index = ITERATOR_INDEX_END;
+ iter->individual_element_index = ITERATOR_INDEX_END;
+ return (NULL);
+ }
+
+ KASSERT((iter->type_index < ses_cache->ses_ntypes),
+ ("Corrupted element iterator. %d not less than %d",
+ iter->type_index, ses_cache->ses_ntypes));
+
+ element_type = &ses_cache->ses_types[iter->type_index];
+ iter->global_element_index++;
+ iter->type_element_index++;
+
+ /*
+ * There is an object for overal type status in addition
+ * to one for each allowed element, but only if the element
+ * count is non-zero.
+ */
+ if (iter->type_element_index > element_type->hdr->etype_maxelt) {
+
+ /*
+ * We've exhausted the elements of this type.
+ * This next element belongs to the next type.
+ */
+ iter->type_index++;
+ iter->type_element_index = 0;
+ iter->saved_individual_element_index
+ = iter->individual_element_index;
+ iter->individual_element_index = ITERATOR_INDEX_INVALID;
+ }
+
+ if (iter->type_element_index > 0) {
+ if (iter->type_element_index == 1) {
+ iter->individual_element_index
+ = iter->saved_individual_element_index;
+ }
+ iter->individual_element_index++;
+ }
+
+ return (&iter->cache->elm_map[iter->global_element_index]);
+}
+
+/**
+ * Element index types tracked by a SES iterator.
+ */
+typedef enum {
+ /**
+ * Index relative to all elements (overall and individual)
+ * in the system.
+ */
+ SES_ELEM_INDEX_GLOBAL,
+
+ /**
+ * \brief Index relative to all individual elements in the system.
+ *
+ * This index counts only individual elements, skipping overall
+ * status elements. This is the index space of the additional
+ * element status page (page 0xa).
+ */
+ SES_ELEM_INDEX_INDIVIDUAL
+} ses_elem_index_type_t;
+
+/**
+ * \brief Move the provided iterator forwards or backwards to the object
+ * having the give index.
+ *
+ * \param iter The iterator on which to perform the seek.
+ * \param element_index The index of the element to find.
+ * \param index_type The type (global or individual) of element_index.
+ *
+ * \return If the element is found, a pointer to it's enc_element_t.
+ * Otherwise NULL.
+ */
+static enc_element_t *
+ses_iter_seek_to(struct ses_iterator *iter, int element_index,
+ ses_elem_index_type_t index_type)
+{
+ enc_element_t *element;
+ int *cur_index;
+
+ if (index_type == SES_ELEM_INDEX_GLOBAL)
+ cur_index = &iter->global_element_index;
+ else
+ cur_index = &iter->individual_element_index;
+
+ if (*cur_index == element_index) {
+ /* Already there. */
+ return (&iter->cache->elm_map[iter->global_element_index]);
+ }
+
+ ses_iter_reset(iter);
+ while ((element = ses_iter_next(iter)) != NULL
+ && *cur_index != element_index)
+ ;
+
+ if (*cur_index != element_index)
+ return (NULL);
+
+ return (element);
+}
+
+#if 0
+static int ses_encode(enc_softc_t *, uint8_t *, int, int,
+ struct ses_comstat *);
+#endif
+static int ses_set_timed_completion(enc_softc_t *, uint8_t);
+#if 0
+static int ses_putstatus(enc_softc_t *, int, struct ses_comstat *);
+#endif
+
+static void ses_print_addl_data(enc_softc_t *, enc_element_t *);
+
+/*=========================== SES cleanup routines ===========================*/
+
+static void
+ses_cache_free_elm_addlstatus(enc_softc_t *enc, enc_cache_t *cache)
+{
+ ses_cache_t *ses_cache;
+ ses_cache_t *other_ses_cache;
+ enc_element_t *cur_elm;
+ enc_element_t *last_elm;
+
+ ENC_DLOG(enc, "%s: enter\n", __func__);
+ ses_cache = cache->private;
+ if (ses_cache->elm_addlstatus_page == NULL)
+ return;
+
+ for (cur_elm = cache->elm_map,
+ last_elm = &cache->elm_map[cache->nelms - 1];
+ cur_elm <= last_elm; cur_elm++) {
+ ses_element_t *elmpriv;
+
+ elmpriv = cur_elm->elm_private;
+
+ /* Clear references to the additional status page. */
+ bzero(&elmpriv->addl, sizeof(elmpriv->addl));
+ }
+
+ other_ses_cache = enc_other_cache(enc, cache)->private;
+ if (other_ses_cache->elm_addlstatus_page
+ != ses_cache->elm_addlstatus_page)
+ ENC_FREE(ses_cache->elm_addlstatus_page);
+ ses_cache->elm_addlstatus_page = NULL;
+}
+
+static void
+ses_cache_free_elm_descs(enc_softc_t *enc, enc_cache_t *cache)
+{
+ ses_cache_t *ses_cache;
+ ses_cache_t *other_ses_cache;
+ enc_element_t *cur_elm;
+ enc_element_t *last_elm;
+
+ ENC_DLOG(enc, "%s: enter\n", __func__);
+ ses_cache = cache->private;
+ if (ses_cache->elm_descs_page == NULL)
+ return;
+
+ for (cur_elm = cache->elm_map,
+ last_elm = &cache->elm_map[cache->nelms - 1];
+ cur_elm <= last_elm; cur_elm++) {
+ ses_element_t *elmpriv;
+
+ elmpriv = cur_elm->elm_private;
+ elmpriv->descr_len = 0;
+ elmpriv->descr = NULL;
+ }
+
+ other_ses_cache = enc_other_cache(enc, cache)->private;
+ if (other_ses_cache->elm_descs_page
+ != ses_cache->elm_descs_page)
+ ENC_FREE(ses_cache->elm_descs_page);
+ ses_cache->elm_descs_page = NULL;
+}
+
+static void
+ses_cache_free_status(enc_softc_t *enc, enc_cache_t *cache)
+{
+ ses_cache_t *ses_cache;
+ ses_cache_t *other_ses_cache;
+
+ ENC_DLOG(enc, "%s: enter\n", __func__);
+ ses_cache = cache->private;
+ if (ses_cache->status_page == NULL)
+ return;
+
+ other_ses_cache = enc_other_cache(enc, cache)->private;
+ if (other_ses_cache->status_page != ses_cache->status_page)
+ ENC_FREE(ses_cache->status_page);
+ ses_cache->status_page = NULL;
+}
+
+static void
+ses_cache_free_elm_map(enc_softc_t *enc, enc_cache_t *cache)
+{
+ enc_element_t *cur_elm;
+ enc_element_t *last_elm;
+
+ ENC_DLOG(enc, "%s: enter\n", __func__);
+ if (cache->elm_map == NULL)
+ return;
+
+ ses_cache_free_elm_descs(enc, cache);
+ ses_cache_free_elm_addlstatus(enc, cache);
+ for (cur_elm = cache->elm_map,
+ last_elm = &cache->elm_map[cache->nelms - 1];
+ cur_elm <= last_elm; cur_elm++) {
+
+ ENC_FREE_AND_NULL(cur_elm->elm_private);
+ }
+ ENC_FREE_AND_NULL(cache->elm_map);
+ cache->nelms = 0;
+ ENC_DLOG(enc, "%s: exit\n", __func__);
+}
+
+static void
+ses_cache_free(enc_softc_t *enc, enc_cache_t *cache)
+{
+ ses_cache_t *other_ses_cache;
+ ses_cache_t *ses_cache;
+
+ ENC_DLOG(enc, "%s: enter\n", __func__);
+ ses_cache_free_elm_addlstatus(enc, cache);
+ ses_cache_free_status(enc, cache);
+ ses_cache_free_elm_map(enc, cache);
+
+ ses_cache = cache->private;
+ ses_cache->ses_ntypes = 0;
+
+ other_ses_cache = enc_other_cache(enc, cache)->private;
+ if (other_ses_cache->subencs != ses_cache->subencs)
+ ENC_FREE(ses_cache->subencs);
+ ses_cache->subencs = NULL;
+
+ if (other_ses_cache->ses_types != ses_cache->ses_types)
+ ENC_FREE(ses_cache->ses_types);
+ ses_cache->ses_types = NULL;
+
+ if (other_ses_cache->cfg_page != ses_cache->cfg_page)
+ ENC_FREE(ses_cache->cfg_page);
+ ses_cache->cfg_page = NULL;
+
+ ENC_DLOG(enc, "%s: exit\n", __func__);
+}
+
+static void
+ses_cache_clone(enc_softc_t *enc, enc_cache_t *src, enc_cache_t *dst)
+{
+ ses_cache_t *dst_ses_cache;
+ ses_cache_t *src_ses_cache;
+ enc_element_t *src_elm;
+ enc_element_t *dst_elm;
+ enc_element_t *last_elm;
+
+ ses_cache_free(enc, dst);
+ src_ses_cache = src->private;
+ dst_ses_cache = dst->private;
+
+ /*
+ * The cloned enclosure cache and ses specific cache are
+ * mostly identical to the source.
+ */
+ *dst = *src;
+ *dst_ses_cache = *src_ses_cache;
+
+ /*
+ * But the ses cache storage is still independent. Restore
+ * the pointer that was clobbered by the structure copy above.
+ */
+ dst->private = dst_ses_cache;
+
+ /*
+ * The element map is independent even though it starts out
+ * pointing to the same constant page data.
+ */
+ dst->elm_map = ENC_MALLOCZ(dst->nelms * sizeof(enc_element_t));
+ memcpy(dst->elm_map, src->elm_map, dst->nelms * sizeof(enc_element_t));
+ for (dst_elm = dst->elm_map, src_elm = src->elm_map,
+ last_elm = &src->elm_map[src->nelms - 1];
+ src_elm <= last_elm; src_elm++, dst_elm++) {
+
+ dst_elm->elm_private = ENC_MALLOCZ(sizeof(ses_element_t));
+ memcpy(dst_elm->elm_private, src_elm->elm_private,
+ sizeof(ses_element_t));
+ }
+}
+
+/* Structure accessors. These are strongly typed to avoid errors. */
+
+int
+ses_elm_sas_descr_type(union ses_elm_sas_hdr *obj)
+{
+ return ((obj)->base_hdr.byte1 >> 6);
+}
+int
+ses_elm_addlstatus_proto(struct ses_elm_addlstatus_base_hdr *hdr)
+{
+ return ((hdr)->byte0 & 0xf);
+}
+int
+ses_elm_addlstatus_eip(struct ses_elm_addlstatus_base_hdr *hdr)
+{
+ return ((hdr)->byte0 >> 4) & 0x1;
+}
+int
+ses_elm_addlstatus_invalid(struct ses_elm_addlstatus_base_hdr *hdr)
+{
+ return ((hdr)->byte0 >> 7);
+}
+int
+ses_elm_sas_type0_not_all_phys(union ses_elm_sas_hdr *hdr)
+{
+ return ((hdr)->type0_noneip.byte1 & 0x1);
+}
+int
+ses_elm_sas_dev_phy_sata_dev(struct ses_elm_sas_device_phy *phy)
+{
+ return ((phy)->target_ports & 0x1);
+}
+int
+ses_elm_sas_dev_phy_sata_port(struct ses_elm_sas_device_phy *phy)
+{
+ return ((phy)->target_ports >> 7);
+}
+int
+ses_elm_sas_dev_phy_dev_type(struct ses_elm_sas_device_phy *phy)
+{
+ return (((phy)->byte0 >> 4) & 0x7);
+}
+
+/**
+ * \brief Verify that the cached configuration data in our softc
+ * is valid for processing the page data corresponding to
+ * the provided page header.
+ *
+ * \param ses_cache The SES cache to validate.
+ * \param gen_code The 4 byte generation code from a SES diagnostic
+ * page header.
+ *
+ * \return non-zero if true, 0 if false.
+ */
+static int
+ses_config_cache_valid(ses_cache_t *ses_cache, const uint8_t *gen_code)
+{
+ uint32_t cache_gc;
+ uint32_t cur_gc;
+
+ if (ses_cache->cfg_page == NULL)
+ return (0);
+
+ cache_gc = scsi_4btoul(ses_cache->cfg_page->hdr.gen_code);
+ cur_gc = scsi_4btoul(gen_code);
+ return (cache_gc == cur_gc);
+}
+
+/**
+ * Function signature for consumers of the ses_devids_iter() interface.
+ */
+typedef void ses_devid_callback_t(enc_softc_t *, enc_element_t *,
+ struct scsi_vpd_id_descriptor *, void *);
+
+/**
+ * \brief Iterate over and create vpd device id records from the
+ * additional element status data for elm, passing that data
+ * to the provided callback.
+ *
+ * \param enc SES instance containing elm
+ * \param elm Element for which to extract device ID data.
+ * \param callback The callback function to invoke on each generated
+ * device id descriptor for elm.
+ * \param callback_arg Argument passed through to callback on each invocation.
+ */
+static void
+ses_devids_iter(enc_softc_t *enc, enc_element_t *elm,
+ ses_devid_callback_t *callback, void *callback_arg)
+{
+ ses_element_t *elmpriv;
+ struct ses_addl_status *addl;
+ u_int i;
+ size_t devid_record_size;
+
+ elmpriv = elm->elm_private;
+ addl = &(elmpriv->addl);
+
+ /*
+ * Don't assume this object has additional status information, or
+ * that it is a SAS device, or that it is a device slot device.
+ */
+ if (addl->hdr == NULL || addl->proto_hdr.sas == NULL
+ || addl->proto_data.sasdev_phys == NULL)
+ return;
+
+ devid_record_size = SVPD_DEVICE_ID_DESC_HDR_LEN
+ + sizeof(struct scsi_vpd_id_naa_ieee_reg);
+ for (i = 0; i < addl->proto_hdr.sas->base_hdr.num_phys; i++) {
+ uint8_t devid_buf[devid_record_size];
+ struct scsi_vpd_id_descriptor *devid;
+ uint8_t *phy_addr;
+
+ devid = (struct scsi_vpd_id_descriptor *)devid_buf;
+ phy_addr = addl->proto_data.sasdev_phys[i].phy_addr;
+ devid->proto_codeset = (SCSI_PROTO_SAS << SVPD_ID_PROTO_SHIFT)
+ | SVPD_ID_CODESET_BINARY;
+ devid->id_type = SVPD_ID_PIV
+ | SVPD_ID_ASSOC_PORT
+ | SVPD_ID_TYPE_NAA;
+ devid->reserved = 0;
+ devid->length = sizeof(struct scsi_vpd_id_naa_ieee_reg);
+ memcpy(devid->identifier, phy_addr, devid->length);
+
+ callback(enc, elm, devid, callback_arg);
+ }
+}
+
+/**
+ * Function signature for consumers of the ses_paths_iter() interface.
+ */
+typedef void ses_path_callback_t(enc_softc_t *, enc_element_t *,
+ struct cam_path *, void *);
+
+/**
+ * Argument package passed through ses_devids_iter() by
+ * ses_paths_iter() to ses_path_iter_devid_callback().
+ */
+typedef struct ses_path_iter_args {
+ ses_path_callback_t *callback;
+ void *callback_arg;
+} ses_path_iter_args_t;
+
+/**
+ * ses_devids_iter() callback function used by ses_paths_iter()
+ * to map device ids to peripheral driver instances.
+ *
+ * \param enc SES instance containing elm
+ * \param elm Element on which device ID matching is active.
+ * \param periph A device ID corresponding to elm.
+ * \param arg Argument passed through to callback on each invocation.
+ */
+static void
+ses_path_iter_devid_callback(enc_softc_t *enc, enc_element_t *elem,
+ struct scsi_vpd_id_descriptor *devid,
+ void *arg)
+{
+ struct ccb_dev_match cdm;
+ struct dev_match_pattern match_pattern;
+ struct dev_match_result match_result;
+ struct device_match_result *device_match;
+ struct device_match_pattern *device_pattern;
+ ses_path_iter_args_t *args;
+
+ args = (ses_path_iter_args_t *)arg;
+ match_pattern.type = DEV_MATCH_DEVICE;
+ device_pattern = &match_pattern.pattern.device_pattern;
+ device_pattern->flags = DEV_MATCH_DEVID;
+ device_pattern->data.devid_pat.id_len =
+ offsetof(struct scsi_vpd_id_descriptor, identifier)
+ + devid->length;
+ memcpy(device_pattern->data.devid_pat.id, devid,
+ device_pattern->data.devid_pat.id_len);
+
+ memset(&cdm, 0, sizeof(cdm));
+ if (xpt_create_path(&cdm.ccb_h.path, /*periph*/NULL, CAM_XPT_PATH_ID,
+ CAM_TARGET_WILDCARD,
+ CAM_LUN_WILDCARD) != CAM_REQ_CMP)
+ return;
+
+ cdm.ccb_h.func_code = XPT_DEV_MATCH;
+ cdm.num_patterns = 1;
+ cdm.patterns = &match_pattern;
+ cdm.pattern_buf_len = sizeof(match_pattern);
+ cdm.match_buf_len = sizeof(match_result);
+ cdm.matches = &match_result;
+
+ xpt_action((union ccb *)&cdm);
+ xpt_free_path(cdm.ccb_h.path);
+
+ if ((cdm.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP
+ || (cdm.status != CAM_DEV_MATCH_LAST
+ && cdm.status != CAM_DEV_MATCH_MORE)
+ || cdm.num_matches == 0)
+ return;
+
+ device_match = &match_result.result.device_result;
+ if (xpt_create_path(&cdm.ccb_h.path, /*periph*/NULL,
+ device_match->path_id,
+ device_match->target_id,
+ device_match->target_lun) != CAM_REQ_CMP)
+ return;
+
+ args->callback(enc, elem, cdm.ccb_h.path, args->callback_arg);
+ xpt_free_path(cdm.ccb_h.path);
+}
+
+/**
+ * \brief Iterate over and find the matching periph objects for the
+ * specified element.
+ *
+ * \param enc SES instance containing elm
+ * \param elm Element for which to perform periph object matching.
+ * \param callback The callback function to invoke with each matching
+ * periph object.
+ * \param callback_arg Argument passed through to callback on each invocation.
+ */
+static void
+ses_paths_iter(enc_softc_t *enc, enc_element_t *elm,
+ ses_path_callback_t *callback, void *callback_arg)
+{
+ ses_path_iter_args_t args;
+
+ args.callback = callback;
+ args.callback_arg = callback_arg;
+ ses_devids_iter(enc, elm, ses_path_iter_devid_callback, &args);
+}
+
+/**
+ * ses_paths_iter() callback function used by ses_get_elmdevname()
+ * to record periph driver instance strings corresponding to a SES
+ * element.
+ *
+ * \param enc SES instance containing elm
+ * \param elm Element on which periph matching is active.
+ * \param periph A periph instance that matches elm.
+ * \param arg Argument passed through to callback on each invocation.
+ */
+static void
+ses_elmdevname_callback(enc_softc_t *enc, enc_element_t *elem,
+ struct cam_path *path, void *arg)
+{
+ struct sbuf *sb;
+
+ sb = (struct sbuf *)arg;
+ cam_periph_list(path, sb);
+}
+
+/**
+ * Argument package passed through ses_paths_iter() to
+ * ses_getcampath_callback.
+ */
+typedef struct ses_setphyspath_callback_args {
+ struct sbuf *physpath;
+ int num_set;
+} ses_setphyspath_callback_args_t;
+
+/**
+ * \brief ses_paths_iter() callback to set the physical path on the
+ * CAM EDT entries corresponding to a given SES element.
+ *
+ * \param enc SES instance containing elm
+ * \param elm Element on which periph matching is active.
+ * \param periph A periph instance that matches elm.
+ * \param arg Argument passed through to callback on each invocation.
+ */
+static void
+ses_setphyspath_callback(enc_softc_t *enc, enc_element_t *elm,
+ struct cam_path *path, void *arg)
+{
+ struct ccb_dev_advinfo cdai;
+ ses_setphyspath_callback_args_t *args;
+ char *old_physpath;
+
+ args = (ses_setphyspath_callback_args_t *)arg;
+ old_physpath = malloc(MAXPATHLEN, M_SCSIENC, M_WAITOK|M_ZERO);
+
+ xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL);
+ cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
+ cdai.buftype = CDAI_TYPE_PHYS_PATH;
+ cdai.flags = 0;
+ cdai.bufsiz = MAXPATHLEN;
+ cdai.buf = old_physpath;
+ xpt_action((union ccb *)&cdai);
+ if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
+ cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
+
+ if (strcmp(old_physpath, sbuf_data(args->physpath)) != 0) {
+
+ xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL);
+ cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
+ cdai.buftype = CDAI_TYPE_PHYS_PATH;
+ cdai.flags |= CDAI_FLAG_STORE;
+ cdai.bufsiz = sbuf_len(args->physpath);
+ cdai.buf = sbuf_data(args->physpath);
+ xpt_action((union ccb *)&cdai);
+ if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
+ cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
+ if (cdai.ccb_h.status == CAM_REQ_CMP)
+ args->num_set++;
+ }
+ free(old_physpath, M_SCSIENC);
+}
+
+/**
+ * \brief Set a device's physical path string in CAM XPT.
+ *
+ * \param enc SES instance containing elm
+ * \param elm Element to publish physical path string for
+ * \param iter Iterator whose state corresponds to elm
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
+ struct ses_iterator *iter)
+{
+ struct ccb_dev_advinfo cdai;
+ ses_setphyspath_callback_args_t args;
+ int ret;
+ struct sbuf sb;
+ uint8_t *devid, *elmaddr;
+ ses_element_t *elmpriv;
+
+ ret = EIO;
+ devid = NULL;
+
+ /*
+ * Assemble the components of the physical path starting with
+ * the device ID of the enclosure itself.
+ */
+ xpt_setup_ccb(&cdai.ccb_h, enc->periph->path, CAM_PRIORITY_NORMAL);
+ cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
+ cdai.buftype = CDAI_TYPE_SCSI_DEVID;
+ cdai.bufsiz = CAM_SCSI_DEVID_MAXLEN;
+ cdai.buf = devid = ENC_MALLOCZ(cdai.bufsiz);
+ if (devid == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+ xpt_action((union ccb *)&cdai);
+ if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
+ cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
+ if (cdai.ccb_h.status != CAM_REQ_CMP)
+ goto out;
+
+ elmaddr = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
+ cdai.provsiz, scsi_devid_is_naa_ieee_reg);
+ if (elmaddr == NULL)
+ goto out;
+
+ if (sbuf_new(&sb, NULL, 128, SBUF_AUTOEXTEND) == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+ /* Next, generate the physical path string */
+ sbuf_printf(&sb, "id1,enc at n%jx/type@%x/slot@%x",
+ scsi_8btou64(elmaddr), iter->type_index,
+ iter->type_element_index);
+ /* Append the element descriptor if one exists */
+ elmpriv = elm->elm_private;
+ if (elmpriv->descr != NULL && elmpriv->descr_len > 0) {
+ sbuf_cat(&sb, "/elmdesc@");
+ sbuf_bcat(&sb, elmpriv->descr, elmpriv->descr_len);
+ }
+ sbuf_finish(&sb);
+
+ /*
+ * Set this physical path on any CAM devices with a device ID
+ * descriptor that matches one created from the SES additional
+ * status data for this element.
+ */
+ args.physpath= &sb;
+ args.num_set = 0;
+ ses_paths_iter(enc, elm, ses_setphyspath_callback, &args);
+ sbuf_delete(&sb);
+
+ ret = args.num_set == 0 ? ENOENT : 0;
+
+out:
+ if (devid != NULL)
+ ENC_FREE(devid);
+ return (ret);
+}
+
+/**
+ * \brief Helper to set the CDB fields appropriately.
+ *
+ * \param cdb Buffer containing the cdb.
+ * \param pagenum SES diagnostic page to query for.
+ * \param dir Direction of query.
+ */
+static void
+ses_page_cdb(char *cdb, int bufsiz, SesDiagPageCodes pagenum, int dir)
+{
+
+ /* Ref: SPC-4 r25 Section 6.20 Table 223 */
+ if (dir == CAM_DIR_IN) {
+ cdb[0] = RECEIVE_DIAGNOSTIC;
+ cdb[1] = 1; /* Set page code valid bit */
+ cdb[2] = pagenum;
+ } else {
+ cdb[0] = SEND_DIAGNOSTIC;
+ cdb[1] = 0x10;
+ cdb[2] = pagenum;
+ }
+ cdb[3] = bufsiz >> 8; /* high bits */
+ cdb[4] = bufsiz & 0xff; /* low bits */
+ cdb[5] = 0;
+}
+
+/**
+ * \brief Discover whether this instance supports timed completion of a
+ * RECEIVE DIAGNOSTIC RESULTS command requesting the Enclosure Status
+ * page, and store the result in the softc, updating if necessary.
+ *
+ * \param enc SES instance to query and update.
+ * \param tc_en Value of timed completion to set (see \return).
+ *
+ * \return 1 if timed completion enabled, 0 otherwise.
+ */
+static int
+ses_set_timed_completion(enc_softc_t *enc, uint8_t tc_en)
+{
+ int err;
+ union ccb *ccb;
+ struct cam_periph *periph;
+ struct ses_mgmt_mode_page *mgmt;
+ uint8_t *mode_buf;
+ size_t mode_buf_len;
+ ses_softc_t *ses;
+
+ periph = enc->periph;
+ ses = enc->enc_private;
+ ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
+
+ mode_buf_len = sizeof(struct ses_mgmt_mode_page);
+ mode_buf = ENC_MALLOCZ(mode_buf_len);
+ if (mode_buf == NULL)
+ goto out;
+
+ scsi_mode_sense(&ccb->csio, /*retries*/4, enc_done, MSG_SIMPLE_Q_TAG,
+ /*dbd*/FALSE, SMS_PAGE_CTRL_CURRENT, SES_MGMT_MODE_PAGE_CODE,
+ mode_buf, mode_buf_len, SSD_FULL_SIZE, /*timeout*/60 * 1000);
+
+ /*
+ * Ignore illegal request errors, as they are quite common and we
+ * will print something out in that case anyway.
+ */
+ err = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS,
+ ENC_FLAGS|SF_QUIET_IR, NULL);
+ if (ccb->ccb_h.status != CAM_REQ_CMP) {
+ ENC_LOG(enc, "Timed Completion Unsupported\n");
+ goto release;
+ }
+
+ /* Skip the mode select if the desired value is already set */
+ mgmt = (struct ses_mgmt_mode_page *)mode_buf;
+ if ((mgmt->byte5 & SES_MGMT_TIMED_COMP_EN) == tc_en)
+ goto done;
+
+ /* Value is not what we wanted, set it */
+ if (tc_en)
+ mgmt->byte5 |= SES_MGMT_TIMED_COMP_EN;
+ else
+ mgmt->byte5 &= ~SES_MGMT_TIMED_COMP_EN;
+ /* SES2r20: a completion time of zero means as long as possible */
+ bzero(&mgmt->max_comp_time, sizeof(mgmt->max_comp_time));
+
+ scsi_mode_select(&ccb->csio, 5, enc_done, MSG_SIMPLE_Q_TAG,
+ /*page_fmt*/FALSE, /*save_pages*/TRUE, mode_buf, mode_buf_len,
+ SSD_FULL_SIZE, /*timeout*/60 * 1000);
+
+ err = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS, ENC_FLAGS, NULL);
+ if (ccb->ccb_h.status != CAM_REQ_CMP) {
+ ENC_LOG(enc, "Timed Completion Set Failed\n");
+ goto release;
+ }
+
+done:
+ if ((mgmt->byte5 & SES_MGMT_TIMED_COMP_EN) != 0) {
+ ENC_LOG(enc, "Timed Completion Enabled\n");
+ ses->ses_flags |= SES_FLAG_TIMEDCOMP;
+ } else {
+ ENC_LOG(enc, "Timed Completion Disabled\n");
+ ses->ses_flags &= ~SES_FLAG_TIMEDCOMP;
+ }
+release:
+ ENC_FREE(mode_buf);
+ xpt_release_ccb(ccb);
+out:
+ return (ses->ses_flags & SES_FLAG_TIMEDCOMP);
+}
+
+/**
+ * \brief Process the list of supported pages and update flags.
+ *
+ * \param enc SES device to query.
+ * \param buf Buffer containing the config page.
+ * \param xfer_len Length of the config page in the buffer.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_process_pages(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ ses_softc_t *ses;
+ struct scsi_diag_page *page;
+ int err, i, length;
+
+ CAM_DEBUG(enc->periph->path, CAM_DEBUG_SUBTRACE,
+ ("entering %s(%p, %d)\n", __func__, bufp, xfer_len));
+ ses = enc->enc_private;
+ err = -1;
+
+ if (error != 0) {
+ err = error;
+ goto out;
+ }
+ if (xfer_len < sizeof(*page)) {
+ ENC_LOG(enc, "Unable to parse Diag Pages List Header\n");
+ err = EIO;
+ goto out;
+ }
+ page = (struct scsi_diag_page *)*bufp;
+ length = scsi_2btoul(page->length);
+ if (length + offsetof(struct scsi_diag_page, params) > xfer_len) {
+ ENC_LOG(enc, "Diag Pages List Too Long\n");
+ goto out;
+ }
+ ENC_DLOG(enc, "%s: page length %d, xfer_len %d\n",
+ __func__, length, xfer_len);
+
+ err = 0;
+ for (i = 0; i < length; i++) {
+ if (page->params[i] == SesAddlElementStatus) {
+ ses->ses_flags |= SES_FLAG_ADDLSTATUS;
+ break;
+ }
+ }
+
+out:
+ ENC_DLOG(enc, "%s: exiting with err %d\n", __func__, err);
+ return (err);
+}
+
+/**
+ * \brief Process the config page and update associated structures.
+ *
+ * \param enc SES device to query.
+ * \param buf Buffer containing the config page.
+ * \param xfer_len Length of the config page in the buffer.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ struct ses_iterator iter;
+ ses_softc_t *ses;
+ enc_cache_t *enc_cache;
+ ses_cache_t *ses_cache;
+ uint8_t *buf;
+ int length;
+ int err;
+ int nelm;
+ int ntype;
+ struct ses_cfg_page *cfg_page;
+ struct ses_enc_desc *buf_subenc;
+ const struct ses_enc_desc **subencs;
+ const struct ses_enc_desc **cur_subenc;
+ const struct ses_enc_desc **last_subenc;
+ ses_type_t *ses_types;
+ ses_type_t *sestype;
+ const struct ses_elm_type_desc *cur_buf_type;
+ const struct ses_elm_type_desc *last_buf_type;
+ uint8_t *last_valid_byte;
+ enc_element_t *element;
+ const char *type_text;
+
+ CAM_DEBUG(enc->periph->path, CAM_DEBUG_SUBTRACE,
+ ("entering %s(%p, %d)\n", __func__, bufp, xfer_len));
+ ses = enc->enc_private;
+ enc_cache = &enc->enc_daemon_cache;
+ ses_cache = enc_cache->private;
+ buf = *bufp;
+ err = -1;;
+
+ if (error != 0) {
+ err = error;
+ goto out;
+ }
+ if (xfer_len < sizeof(cfg_page->hdr)) {
+ ENC_LOG(enc, "Unable to parse SES Config Header\n");
+ err = EIO;
+ goto out;
+ }
+
+ cfg_page = (struct ses_cfg_page *)buf;
+ length = ses_page_length(&cfg_page->hdr);
+ if (length > xfer_len) {
+ ENC_LOG(enc, "Enclosure Config Page Too Long\n");
+ goto out;
+ }
+ last_valid_byte = &buf[length - 1];
+
+ ENC_DLOG(enc, "%s: total page length %d, xfer_len %d\n",
+ __func__, length, xfer_len);
+
+ err = 0;
+ if (ses_config_cache_valid(ses_cache, cfg_page->hdr.gen_code)) {
+
+ /* Our cache is still valid. Proceed to fetching status. */
+ goto out;
+ }
+
+ /* Cache is no longer valid. Free old data to make way for new. */
+ ses_cache_free(enc, enc_cache);
+ ENC_VLOG(enc, "Generation Code 0x%x has %d SubEnclosures\n",
+ scsi_4btoul(cfg_page->hdr.gen_code),
+ ses_cfg_page_get_num_subenc(cfg_page));
+
+ /* Take ownership of the buffer. */
+ ses_cache->cfg_page = cfg_page;
+ *bufp = NULL;
+
+ /*
+ * Now waltz through all the subenclosures summing the number of
+ * types available in each.
+ */
+ subencs = ENC_MALLOCZ(ses_cfg_page_get_num_subenc(cfg_page)
+ * sizeof(*subencs));
+ if (subencs == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+ /*
+ * Sub-enclosure data is const after construction (i.e. when
+ * accessed via our cache object.
+ *
+ * The cast here is not required in C++ but C99 is not so
+ * sophisticated (see C99 6.5.16.1(1)).
+ */
+ ses_cache->subencs = subencs;
+
+ buf_subenc = cfg_page->subencs;
+ cur_subenc = subencs;
+ last_subenc = &subencs[ses_cfg_page_get_num_subenc(cfg_page) - 1];
+ ntype = 0;
+ while (cur_subenc <= last_subenc) {
+
+ if (!ses_enc_desc_is_complete(buf_subenc, last_valid_byte)) {
+ ENC_LOG(enc, "Enclosure %d Beyond End of "
+ "Descriptors\n", cur_subenc - subencs);
+ err = EIO;
+ goto out;
+ }
+
+ ENC_VLOG(enc, " SubEnclosure ID %d, %d Types With this ID, "
+ "Descriptor Length %d, offset %d\n", buf_subenc->subenc_id,
+ buf_subenc->num_types, buf_subenc->length,
+ &buf_subenc->byte0 - buf);
+ ENC_VLOG(enc, "WWN: %jx\n",
+ (uintmax_t)scsi_8btou64(buf_subenc->logical_id));
+
+ ntype += buf_subenc->num_types;
+ *cur_subenc = buf_subenc;
+ cur_subenc++;
+ buf_subenc = ses_enc_desc_next(buf_subenc);
+ }
+
+ /* Process the type headers. */
+ ses_types = ENC_MALLOCZ(ntype * sizeof(*ses_types));
+ if (ses_types == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+ /*
+ * Type data is const after construction (i.e. when accessed via
+ * our cache object.
+ */
+ ses_cache->ses_types = ses_types;
+
+ cur_buf_type = (const struct ses_elm_type_desc *)
+ (&(*last_subenc)->length + (*last_subenc)->length + 1);
+ last_buf_type = cur_buf_type + ntype - 1;
+ type_text = (const uint8_t *)(last_buf_type + 1);
+ nelm = 0;
+ sestype = ses_types;
+ while (cur_buf_type <= last_buf_type) {
+ if (&cur_buf_type->etype_txt_len > last_valid_byte) {
+ ENC_LOG(enc, "Runt Enclosure Type Header %d\n",
+ sestype - ses_types);
+ err = EIO;
+ goto out;
+ }
+ sestype->hdr = cur_buf_type;
+ sestype->text = type_text;
+ type_text += cur_buf_type->etype_txt_len;
+ ENC_LOG(enc, " Type Desc[%d]: Type 0x%x, MaxElt %d, In Subenc "
+ "%d, Text Length %d: %.*s\n", sestype - ses_types,
+ sestype->hdr->etype_elm_type, sestype->hdr->etype_maxelt,
+ sestype->hdr->etype_subenc, sestype->hdr->etype_txt_len,
+ sestype->hdr->etype_txt_len, sestype->text);
+
+ nelm += sestype->hdr->etype_maxelt
+ + /*overall status element*/1;
+ sestype++;
+ cur_buf_type++;
+ }
+
+ /* Create the object map. */
+ enc_cache->elm_map = ENC_MALLOCZ(nelm * sizeof(enc_element_t));
+ if (enc_cache->elm_map == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+ ses_cache->ses_ntypes = (uint8_t)ntype;
+ enc_cache->nelms = nelm;
+
+ ses_iter_init(enc, enc_cache, &iter);
+ while ((element = ses_iter_next(&iter)) != NULL) {
+ const struct ses_elm_type_desc *thdr;
+
+ ENC_DLOG(enc, "%s: checking obj %d(%d,%d)\n", __func__,
+ iter.global_element_index, iter.type_index, nelm,
+ iter.type_element_index);
+ thdr = ses_cache->ses_types[iter.type_index].hdr;
+ element->subenclosure = thdr->etype_subenc;
+ element->enctype = thdr->etype_elm_type;
+ element->overall_status_elem = iter.type_element_index == 0;
+ element->elm_private = ENC_MALLOCZ(sizeof(ses_element_t));
+ if (element->elm_private == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+ ENC_DLOG(enc, "%s: creating elmpriv %d(%d,%d) subenc %d "
+ "type 0x%x\n", __func__, iter.global_element_index,
+ iter.type_index, iter.type_element_index,
+ thdr->etype_subenc, thdr->etype_elm_type);
+ }
+
+ err = 0;
+
+out:
+ if (err)
+ ses_cache_free(enc, enc_cache);
+ else {
+ enc_update_request(enc, SES_UPDATE_GETSTATUS);
+ enc_update_request(enc, SES_UPDATE_GETELMDESCS);
+ if (ses->ses_flags & SES_FLAG_ADDLSTATUS)
+ enc_update_request(enc, SES_UPDATE_GETELMADDLSTATUS);
+ enc_update_request(enc, SES_PUBLISH_CACHE);
+ }
+ ENC_DLOG(enc, "%s: exiting with err %d\n", __func__, err);
+ return (err);
+}
+
+/**
+ * \brief Update the status page and associated structures.
+ *
+ * \param enc SES softc to update for.
+ * \param buf Buffer containing the status page.
+ * \param bufsz Amount of data in the buffer.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_process_status(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ struct ses_iterator iter;
+ enc_element_t *element;
+ ses_softc_t *ses;
+ enc_cache_t *enc_cache;
+ ses_cache_t *ses_cache;
+ uint8_t *buf;
+ int err = -1;
+ int length;
+ struct ses_status_page *page;
+ union ses_status_element *cur_stat;
+ union ses_status_element *last_stat;
+
+ ses = enc->enc_private;
+ enc_cache = &enc->enc_daemon_cache;
+ ses_cache = enc_cache->private;
+ buf = *bufp;
+
+ ENC_DLOG(enc, "%s: enter (%p, %p, %d)\n", __func__, enc, buf, xfer_len);
+ page = (struct ses_status_page *)buf;
+ length = ses_page_length(&page->hdr);
+
+ if (error != 0) {
+ err = error;
+ goto out;
+ }
+ /*
+ * Make sure the length fits in the buffer.
+ *
+ * XXX all this means is that the page is larger than the space
+ * we allocated. Since we use a statically sized buffer, this
+ * could happen... Need to use dynamic discovery of the size.
+ */
+ if (length > xfer_len) {
+ ENC_LOG(enc, "Enclosure Status Page Too Long\n");
+ goto out;
+ }
+ /* Make sure the length contains at least one header and status */
+ if (length < (sizeof(*page) + sizeof(*page->elements))) {
+ ENC_LOG(enc, "Enclosure Status Page Too Short\n");
+ goto out;
+ }
+
+ if (!ses_config_cache_valid(ses_cache, page->hdr.gen_code)) {
+ ENC_DLOG(enc, "%s: Generation count change detected\n",
+ __func__);
+ enc_update_request(enc, SES_UPDATE_GETCONFIG);
+ goto out;
+ }
+
+ ses_cache_free_status(enc, enc_cache);
+ ses_cache->status_page = page;
+ *bufp = NULL;
+
+ enc_cache->enc_status = page->hdr.page_specific_flags;
+
+ /*
+ * Read in individual element status. The element order
+ * matches the order reported in the config page (i.e. the
+ * order of an unfiltered iteration of the config objects)..
+ */
+ ses_iter_init(enc, enc_cache, &iter);
+ cur_stat = page->elements;
+ last_stat = (union ses_status_element *)
+ &buf[length - sizeof(*last_stat)];
+ ENC_DLOG(enc, "%s: total page length %d, xfer_len %d\n",
+ __func__, length, xfer_len);
+ while (cur_stat <= last_stat
+ && (element = ses_iter_next(&iter)) != NULL) {
+
+ ENC_DLOG(enc, "%s: obj %d(%d,%d) off=0x%tx status=%jx\n",
+ __func__, iter.global_element_index, iter.type_index,
+ iter.type_element_index, (uint8_t *)cur_stat - buf,
+ scsi_4btoul(cur_stat->bytes));
+
+ memcpy(&element->encstat, cur_stat, sizeof(element->encstat));
+ element->svalid = 1;
+ cur_stat++;
+ }
+
+ if (ses_iter_next(&iter) != NULL) {
+ ENC_LOG(enc, "Status page, length insufficient for "
+ "expected number of objects\n");
+ } else {
+ if (cur_stat <= last_stat)
+ ENC_LOG(enc, "Status page, exhausted objects before "
+ "exhausing page\n");
+ enc_update_request(enc, SES_PUBLISH_CACHE);
+ err = 0;
+ }
+out:
+ ENC_DLOG(enc, "%s: exiting with error %d\n", __func__, err);
+ return (err);
+}
+
+typedef enum {
+ /**
+ * The enclosure should not provide additional element
+ * status for this element type in page 0x0A.
+ *
+ * \note This status is returned for any types not
+ * listed SES3r02. Further types added in a
+ * future specification will be incorrectly
+ * classified.
+ */
+ TYPE_ADDLSTATUS_NONE,
+
+ /**
+ * The element type provides additional element status
+ * in page 0x0A.
+ */
+ TYPE_ADDLSTATUS_MANDATORY,
+
+ /**
+ * The element type may provide additional element status
+ * in page 0x0A, but i
+ */
+ TYPE_ADDLSTATUS_OPTIONAL
+} ses_addlstatus_avail_t;
+
+/**
+ * \brief Check to see whether a given type (as obtained via type headers) is
+ * supported by the additional status command.
+ *
+ * \param enc SES softc to check.
+ * \param typidx Type index to check for.
+ *
+ * \return An enumeration indicating if additional status is mandatory,
+ * optional, or not required for this type.
+ */
+static ses_addlstatus_avail_t
+ses_typehasaddlstatus(enc_softc_t *enc, uint8_t typidx)
+{
+ enc_cache_t *enc_cache;
+ ses_cache_t *ses_cache;
+
+ enc_cache = &enc->enc_daemon_cache;
+ ses_cache = enc_cache->private;
+ switch(ses_cache->ses_types[typidx].hdr->etype_elm_type) {
+ case ELMTYP_DEVICE:
+ case ELMTYP_ARRAY_DEV:
+ case ELMTYP_SAS_EXP:
+ return (TYPE_ADDLSTATUS_MANDATORY);
+ case ELMTYP_SCSI_INI:
+ case ELMTYP_SCSI_TGT:
+ case ELMTYP_ESCC:
+ return (TYPE_ADDLSTATUS_OPTIONAL);
+ default:
+ /* No additional status information available. */
+ break;
+ }
+ return (TYPE_ADDLSTATUS_NONE);
+}
+
+static int ses_get_elm_addlstatus_fc(enc_softc_t *, enc_cache_t *,
+ uint8_t *, int);
+static int ses_get_elm_addlstatus_sas(enc_softc_t *, enc_cache_t *, uint8_t *,
+ int, int, int, int);
+
+/**
+ * \brief Parse the additional status element data for each object.
+ *
+ * \param enc The SES softc to update.
+ * \param buf The buffer containing the additional status
+ * element response.
+ * \param xfer_len Size of the buffer.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_process_elm_addlstatus(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ struct ses_iterator iter, titer;
+ int eip;
+ int err;
+ int ignore_index = 0;
+ int length;
+ int offset;
+ enc_cache_t *enc_cache;
+ ses_cache_t *ses_cache;
+ uint8_t *buf;
+ ses_element_t *elmpriv;
+ const struct ses_page_hdr *hdr;
+ enc_element_t *element, *telement;
+
+ enc_cache = &enc->enc_daemon_cache;
+ ses_cache = enc_cache->private;
+ buf = *bufp;
+ err = -1;
+
+ if (error != 0) {
+ err = error;
+ goto out;
+ }
+ ses_cache_free_elm_addlstatus(enc, enc_cache);
+ ses_cache->elm_addlstatus_page =
+ (struct ses_addl_elem_status_page *)buf;
+ *bufp = NULL;
+
+ /*
+ * The objects appear in the same order here as in Enclosure Status,
+ * which itself is ordered by the Type Descriptors from the Config
+ * page. However, it is necessary to skip elements that are not
+ * supported by this page when counting them.
+ */
+ hdr = &ses_cache->elm_addlstatus_page->hdr;
+ length = ses_page_length(hdr);
+ ENC_DLOG(enc, "Additional Element Status Page Length 0x%x\n", length);
+ /* Make sure the length includes at least one header. */
+ if (length < sizeof(*hdr)+sizeof(struct ses_elm_addlstatus_base_hdr)) {
+ ENC_LOG(enc, "Runt Additional Element Status Page\n");
+ goto out;
+ }
+ if (length > xfer_len) {
+ ENC_LOG(enc, "Additional Element Status Page Too Long\n");
+ goto out;
+ }
+
+ if (!ses_config_cache_valid(ses_cache, hdr->gen_code)) {
+ ENC_DLOG(enc, "%s: Generation count change detected\n",
+ __func__);
+ enc_update_request(enc, SES_UPDATE_GETCONFIG);
+ goto out;
+ }
+
+ offset = sizeof(struct ses_page_hdr);
+ ses_iter_init(enc, enc_cache, &iter);
+ while (offset < length
+ && (element = ses_iter_next(&iter)) != NULL) {
+ struct ses_elm_addlstatus_base_hdr *elm_hdr;
+ int proto_info_len;
+ ses_addlstatus_avail_t status_type;
+
+ /*
+ * Additional element status is only provided for
+ * individual elements (i.e. overal status elements
+ * are excluded) and those of the types specified
+ * in the SES spec.
+ */
+ status_type = ses_typehasaddlstatus(enc, iter.type_index);
+ if (iter.individual_element_index == ITERATOR_INDEX_INVALID
+ || status_type == TYPE_ADDLSTATUS_NONE)
+ continue;
+
+ elm_hdr = (struct ses_elm_addlstatus_base_hdr *)&buf[offset];
+ eip = ses_elm_addlstatus_eip(elm_hdr);
+ if (eip && !ignore_index) {
+ struct ses_elm_addlstatus_eip_hdr *eip_hdr;
+ int expected_index;
+
+ eip_hdr = (struct ses_elm_addlstatus_eip_hdr *)elm_hdr;
+ expected_index = iter.individual_element_index;
+ titer = iter;
+ telement = ses_iter_seek_to(&titer,
+ eip_hdr->element_index,
+ SES_ELEM_INDEX_INDIVIDUAL);
+ if (telement != NULL &&
+ (ses_typehasaddlstatus(enc, titer.type_index) !=
+ TYPE_ADDLSTATUS_NONE ||
+ titer.type_index > ELMTYP_SAS_CONN)) {
+ iter = titer;
+ element = telement;
+ } else
+ ignore_index = 1;
+
+ if (iter.individual_element_index > expected_index
+ && status_type == TYPE_ADDLSTATUS_MANDATORY) {
+ ENC_LOG(enc, "%s: provided element "
+ "index %d skips mandatory status "
+ " element at index %d\n",
+ __func__, eip_hdr->element_index,
+ expected_index);
+ }
+ }
+ elmpriv = element->elm_private;
+ elmpriv->addl.hdr = elm_hdr;
+ ENC_DLOG(enc, "%s: global element index=%d, type index=%d "
+ "type element index=%d, offset=0x%x, "
+ "byte0=0x%x, length=0x%x\n", __func__,
+ iter.global_element_index, iter.type_index,
+ iter.type_element_index, offset, elmpriv->addl.hdr->byte0,
+ elmpriv->addl.hdr->length);
+
+ /* Skip to after the length field */
+ offset += sizeof(struct ses_elm_addlstatus_base_hdr);
+
+ /* Make sure the descriptor is within bounds */
+ if ((offset + elmpriv->addl.hdr->length) > length) {
+ ENC_LOG(enc, "Element %d Beyond End "
+ "of Additional Element Status Descriptors\n",
+ iter.global_element_index);
+ err = EIO;
+ goto out;
+ }
+
+ /* Advance to the protocol data, skipping eip bytes if needed */
+ offset += (eip * SES_EIP_HDR_EXTRA_LEN);
+ proto_info_len = elmpriv->addl.hdr->length
+ - (eip * SES_EIP_HDR_EXTRA_LEN);
+
+ /* Errors in this block are ignored as they are non-fatal */
+ switch(ses_elm_addlstatus_proto(elmpriv->addl.hdr)) {
+ case SPSP_PROTO_FC:
+ if (elmpriv->addl.hdr->length == 0)
+ break;
+ ses_get_elm_addlstatus_fc(enc, enc_cache,
+ &buf[offset], proto_info_len);
+ break;
+ case SPSP_PROTO_SAS:
+ if (elmpriv->addl.hdr->length <= 2)
+ break;
+ ses_get_elm_addlstatus_sas(enc, enc_cache,
+ &buf[offset],
+ proto_info_len,
+ eip, iter.type_index,
+ iter.global_element_index);
+ break;
+ default:
+ ENC_LOG(enc, "Element %d: Unknown Additional Element "
+ "Protocol 0x%x\n", iter.global_element_index,
+ ses_elm_addlstatus_proto(elmpriv->addl.hdr));
+ goto out;
+ }
+
+ offset += proto_info_len;
+ }
+ err = 0;
+out:
+ if (err)
+ ses_cache_free_elm_addlstatus(enc, enc_cache);
+ enc_update_request(enc, SES_PUBLISH_PHYSPATHS);
+ enc_update_request(enc, SES_PUBLISH_CACHE);
+ return (err);
+}
+
+static int
+ses_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ ses_softc_t *ses;
+
+ ses = enc->enc_private;
+ /*
+ * Possible errors:
+ * o Generation count wrong.
+ * o Some SCSI status error.
+ */
+ ses_terminate_control_requests(&ses->ses_pending_requests, error);
+ enc_update_request(enc, SES_UPDATE_GETSTATUS);
+ return (0);
+}
+
+static int
+ses_publish_physpaths(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ struct ses_iterator iter;
+ enc_cache_t *enc_cache;
+ ses_cache_t *ses_cache;
+ enc_element_t *element;
+
+ enc_cache = &enc->enc_daemon_cache;
+ ses_cache = enc_cache->private;
+
+ ses_iter_init(enc, enc_cache, &iter);
+ while ((element = ses_iter_next(&iter)) != NULL) {
+ /*
+ * ses_set_physpath() returns success if we changed
+ * the physpath of any element. This allows us to
+ * only announce devices once regardless of how
+ * many times we process additional element status.
+ */
+ if (ses_set_physpath(enc, element, &iter) == 0)
+ ses_print_addl_data(enc, element);
+ }
+
+ return (0);
+}
+
+static int
+ses_publish_cache(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+
+ sx_xlock(&enc->enc_cache_lock);
+ ses_cache_clone(enc, /*src*/&enc->enc_daemon_cache,
+ /*dst*/&enc->enc_cache);
+ sx_xunlock(&enc->enc_cache_lock);
+
+ return (0);
+}
+
+/**
+ * \brief Parse the descriptors for each object.
+ *
+ * \param enc The SES softc to update.
+ * \param buf The buffer containing the descriptor list response.
+ * \param xfer_len Size of the buffer.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_process_elm_descs(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
+{
+ ses_softc_t *ses;
+ struct ses_iterator iter;
+ enc_element_t *element;
+ int err;
+ int offset;
+ u_long length, plength;
+ enc_cache_t *enc_cache;
+ ses_cache_t *ses_cache;
+ uint8_t *buf;
+ ses_element_t *elmpriv;
+ const struct ses_page_hdr *phdr;
+ const struct ses_elm_desc_hdr *hdr;
+
+ ses = enc->enc_private;
+ enc_cache = &enc->enc_daemon_cache;
+ ses_cache = enc_cache->private;
+ buf = *bufp;
+ err = -1;
+
+ if (error != 0) {
+ err = error;
+ goto out;
+ }
+ ses_cache_free_elm_descs(enc, enc_cache);
+ ses_cache->elm_descs_page = (struct ses_elem_descr_page *)buf;
+ *bufp = NULL;
+
+ phdr = &ses_cache->elm_descs_page->hdr;
+ plength = ses_page_length(phdr);
+ if (xfer_len < sizeof(struct ses_page_hdr)) {
+ ENC_LOG(enc, "Runt Element Descriptor Page\n");
+ goto out;
+ }
+ if (plength > xfer_len) {
+ ENC_LOG(enc, "Element Descriptor Page Too Long\n");
+ goto out;
+ }
+
+ if (!ses_config_cache_valid(ses_cache, phdr->gen_code)) {
+ ENC_VLOG(enc, "%s: Generation count change detected\n",
+ __func__);
+ enc_update_request(enc, SES_UPDATE_GETCONFIG);
+ goto out;
+ }
+
+ offset = sizeof(struct ses_page_hdr);
+
+ ses_iter_init(enc, enc_cache, &iter);
+ while (offset < plength
+ && (element = ses_iter_next(&iter)) != NULL) {
+
+ if ((offset + sizeof(struct ses_elm_desc_hdr)) > plength) {
+ ENC_LOG(enc, "Element %d Descriptor Header Past "
+ "End of Buffer\n", iter.global_element_index);
+ goto out;
+ }
+ hdr = (struct ses_elm_desc_hdr *)&buf[offset];
+ length = scsi_2btoul(hdr->length);
+ ENC_DLOG(enc, "%s: obj %d(%d,%d) length=%d off=%d\n", __func__,
+ iter.global_element_index, iter.type_index,
+ iter.type_element_index, length, offset);
+ if ((offset + sizeof(*hdr) + length) > plength) {
+ ENC_LOG(enc, "Element%d Descriptor Past "
+ "End of Buffer\n", iter.global_element_index);
+ goto out;
+ }
+ offset += sizeof(*hdr);
+
+ if (length > 0) {
+ elmpriv = element->elm_private;
+ elmpriv->descr_len = length;
+ elmpriv->descr = &buf[offset];
+ }
+
+ /* skip over the descriptor itself */
+ offset += length;
+ }
+
+ err = 0;
+out:
+ if (err == 0) {
+ if (ses->ses_flags & SES_FLAG_ADDLSTATUS)
+ enc_update_request(enc, SES_UPDATE_GETELMADDLSTATUS);
+ }
+ enc_update_request(enc, SES_PUBLISH_CACHE);
+ return (err);
+}
+
+static int
+ses_fill_rcv_diag_io(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t *buf)
+{
+
+ if (enc->enc_type == ENC_SEMB_SES) {
+ semb_receive_diagnostic_results(&ccb->ataio, /*retries*/5,
+ enc_done, MSG_SIMPLE_Q_TAG, /*pcv*/1,
+ state->page_code, buf, state->buf_size,
+ state->timeout);
+ } else {
+ scsi_receive_diagnostic_results(&ccb->csio, /*retries*/5,
+ enc_done, MSG_SIMPLE_Q_TAG, /*pcv*/1,
+ state->page_code, buf, state->buf_size,
+ SSD_FULL_SIZE, state->timeout);
+ }
+ return (0);
+}
+
+/**
+ * \brief Encode the object status into the response buffer, which is
+ * expected to contain the current enclosure status. This function
+ * turns off all the 'select' bits for the objects except for the
+ * object specified, then sends it back to the enclosure.
+ *
+ * \param enc SES enclosure the change is being applied to.
+ * \param buf Buffer containing the current enclosure status response.
+ * \param amt Length of the response in the buffer.
+ * \param req The control request to be applied to buf.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_encode(enc_softc_t *enc, uint8_t *buf, int amt, ses_control_request_t *req)
+{
+ struct ses_iterator iter;
+ enc_element_t *element;
+ int offset;
+ struct ses_control_page_hdr *hdr;
+
+ ses_iter_init(enc, &enc->enc_cache, &iter);
+ hdr = (struct ses_control_page_hdr *)buf;
+ if (req->elm_idx == -1) {
+ /* for enclosure status, at least 2 bytes are needed */
+ if (amt < 2)
+ return EIO;
+ hdr->control_flags =
+ req->elm_stat.comstatus & SES_SET_STATUS_MASK;
+ ENC_DLOG(enc, "Set EncStat %x\n", hdr->control_flags);
+ return (0);
+ }
+
+ element = ses_iter_seek_to(&iter, req->elm_idx, SES_ELEM_INDEX_GLOBAL);
+ if (element == NULL)
+ return (ENXIO);
+
+ /*
+ * Seek to the type set that corresponds to the requested object.
+ * The +1 is for the overall status element for the type.
+ */
+ offset = sizeof(struct ses_control_page_hdr)
+ + (iter.global_element_index * sizeof(struct ses_comstat));
+
+ /* Check for buffer overflow. */
+ if (offset + sizeof(struct ses_comstat) > amt)
+ return (EIO);
+
+ /* Set the status. */
+ memcpy(&buf[offset], &req->elm_stat, sizeof(struct ses_comstat));
+
+ ENC_DLOG(enc, "Set Type 0x%x Obj 0x%x (offset %d) with %x %x %x %x\n",
+ iter.type_index, iter.global_element_index, offset,
+ req->elm_stat.comstatus, req->elm_stat.comstat[0],
+ req->elm_stat.comstat[1], req->elm_stat.comstat[2]);
+
+ return (0);
+}
+
+static int
+ses_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
+ union ccb *ccb, uint8_t *buf)
+{
+ ses_softc_t *ses;
+ enc_cache_t *enc_cache;
+ ses_cache_t *ses_cache;
+ struct ses_control_page_hdr *hdr;
+ ses_control_request_t *req;
+ size_t plength;
+ size_t offset;
+
+ ses = enc->enc_private;
+ enc_cache = &enc->enc_daemon_cache;
+ ses_cache = enc_cache->private;
+ hdr = (struct ses_control_page_hdr *)buf;
+
+ if (ses_cache->status_page == NULL) {
+ ses_terminate_control_requests(&ses->ses_requests, EIO);
+ return (EIO);
+ }
+
+ plength = ses_page_length(&ses_cache->status_page->hdr);
+ memcpy(buf, ses_cache->status_page, plength);
+
+ /* Disable the select bits in all status entries. */
+ offset = sizeof(struct ses_control_page_hdr);
+ for (offset = sizeof(struct ses_control_page_hdr);
+ offset < plength; offset += sizeof(struct ses_comstat)) {
+ buf[offset] &= ~SESCTL_CSEL;
+ }
+
+ /* And make sure the INVOP bit is clear. */
+ hdr->control_flags &= ~SES_ENCSTAT_INVOP;
+
+ /* Apply incoming requests. */
+ while ((req = TAILQ_FIRST(&ses->ses_requests)) != NULL) {
+
+ TAILQ_REMOVE(&ses->ses_requests, req, links);
+ req->result = ses_encode(enc, buf, plength, req);
+ if (req->result != 0) {
+ wakeup(req);
+ continue;
+ }
+ TAILQ_INSERT_TAIL(&ses->ses_pending_requests, req, links);
+ }
+
+ if (TAILQ_EMPTY(&ses->ses_pending_requests) != 0)
+ return (ENOENT);
+
+ /* Fill out the ccb */
+ if (enc->enc_type == ENC_SEMB_SES) {
+ semb_send_diagnostic(&ccb->ataio, /*retries*/5, enc_done,
+ MSG_SIMPLE_Q_TAG,
+ buf, ses_page_length(&ses_cache->status_page->hdr),
+ state->timeout);
+ } else {
+ scsi_send_diagnostic(&ccb->csio, /*retries*/5, enc_done,
+ MSG_SIMPLE_Q_TAG, /*unit_offline*/0,
+ /*device_offline*/0, /*self_test*/0,
+ /*page_format*/1, /*self_test_code*/0,
+ buf, ses_page_length(&ses_cache->status_page->hdr),
+ SSD_FULL_SIZE, state->timeout);
+ }
+ return (0);
+}
+
+static int
+ses_get_elm_addlstatus_fc(enc_softc_t *enc, enc_cache_t *enc_cache,
+ uint8_t *buf, int bufsiz)
+{
+ ENC_LOG(enc, "FC Device Support Stubbed in Additional Status Page\n");
+ return (ENODEV);
+}
+
+#define SES_PRINT_PORTS(p, type) do { \
+ sbuf_printf(sbp, " %s(", type); \
+ if (((p) & SES_SASOBJ_DEV_PHY_PROTOMASK) == 0) \
+ sbuf_printf(sbp, " None"); \
+ else { \
+ if ((p) & SES_SASOBJ_DEV_PHY_SMP) \
+ sbuf_printf(sbp, " SMP"); \
+ if ((p) & SES_SASOBJ_DEV_PHY_STP) \
+ sbuf_printf(sbp, " STP"); \
+ if ((p) & SES_SASOBJ_DEV_PHY_SSP) \
+ sbuf_printf(sbp, " SSP"); \
+ } \
+ sbuf_printf(sbp, " )"); \
+} while(0)
+
+/**
+ * \brief Print the additional element status data for this object, for SAS
+ * type 0 objects. See SES2 r20 Section 6.1.13.3.2.
+ *
+ * \param sesname SES device name associated with the object.
+ * \param sbp Sbuf to print to.
+ * \param obj The object to print the data for.
+ * \param periph_name Peripheral string associated with the object.
+ */
+static void
+ses_print_addl_data_sas_type0(char *sesname, struct sbuf *sbp,
+ enc_element_t *obj, char *periph_name)
+{
+ int i;
+ ses_element_t *elmpriv;
+ struct ses_addl_status *addl;
+ struct ses_elm_sas_device_phy *phy;
+
+ elmpriv = obj->elm_private;
+ addl = &(elmpriv->addl);
+ if (addl->proto_hdr.sas == NULL)
+ return;
+ sbuf_printf(sbp, "%s: %s: SAS Device Slot Element:",
+ sesname, periph_name);
+ sbuf_printf(sbp, " %d Phys", addl->proto_hdr.sas->base_hdr.num_phys);
+ if (ses_elm_addlstatus_eip(addl->hdr))
+ sbuf_printf(sbp, " at Slot %d",
+ addl->proto_hdr.sas->type0_eip.dev_slot_num);
+ if (ses_elm_sas_type0_not_all_phys(addl->proto_hdr.sas))
+ sbuf_printf(sbp, ", Not All Phys");
+ sbuf_printf(sbp, "\n");
+ if (addl->proto_data.sasdev_phys == NULL)
+ return;
+ for (i = 0;i < addl->proto_hdr.sas->base_hdr.num_phys;i++) {
+ phy = &addl->proto_data.sasdev_phys[i];
+ sbuf_printf(sbp, "%s: phy %d:", sesname, i);
+ if (ses_elm_sas_dev_phy_sata_dev(phy))
+ /* Spec says all other fields are specific values */
+ sbuf_printf(sbp, " SATA device\n");
+ else {
+ sbuf_printf(sbp, " SAS device type %d id %d\n",
+ ses_elm_sas_dev_phy_dev_type(phy), phy->phy_id);
+ sbuf_printf(sbp, "%s: phy %d: protocols:", sesname, i);
+ SES_PRINT_PORTS(phy->initiator_ports, "Initiator");
+ SES_PRINT_PORTS(phy->target_ports, "Target");
+ sbuf_printf(sbp, "\n");
+ }
+ sbuf_printf(sbp, "%s: phy %d: parent %jx addr %jx\n",
+ sesname, i,
+ (uintmax_t)scsi_8btou64(phy->parent_addr),
+ (uintmax_t)scsi_8btou64(phy->phy_addr));
+ }
+}
+#undef SES_PRINT_PORTS
+
+/**
+ * \brief Report whether a given enclosure object is an expander.
+ *
+ * \param enc SES softc associated with object.
+ * \param obj Enclosure object to report for.
+ *
+ * \return 1 if true, 0 otherwise.
+ */
+static int
+ses_obj_is_expander(enc_softc_t *enc, enc_element_t *obj)
+{
+ return (obj->enctype == ELMTYP_SAS_EXP);
+}
+
+/**
+ * \brief Print the additional element status data for this object, for SAS
+ * type 1 objects. See SES2 r20 Sections 6.1.13.3.3 and 6.1.13.3.4.
+ *
+ * \param enc SES enclosure, needed for type identification.
+ * \param sesname SES device name associated with the object.
+ * \param sbp Sbuf to print to.
+ * \param obj The object to print the data for.
+ * \param periph_name Peripheral string associated with the object.
+ */
+static void
+ses_print_addl_data_sas_type1(enc_softc_t *enc, char *sesname,
+ struct sbuf *sbp, enc_element_t *obj, char *periph_name)
+{
+ int i, num_phys;
+ ses_element_t *elmpriv;
+ struct ses_addl_status *addl;
+ struct ses_elm_sas_expander_phy *exp_phy;
+ struct ses_elm_sas_port_phy *port_phy;
+
+ elmpriv = obj->elm_private;
+ addl = &(elmpriv->addl);
+ if (addl->proto_hdr.sas == NULL)
+ return;
+ sbuf_printf(sbp, "%s: %s: SAS ", sesname, periph_name);
+ if (ses_obj_is_expander(enc, obj)) {
+ num_phys = addl->proto_hdr.sas->base_hdr.num_phys;
+ sbuf_printf(sbp, "Expander: %d Phys", num_phys);
+ if (addl->proto_data.sasexp_phys == NULL)
+ return;
+ for (i = 0;i < num_phys;i++) {
+ exp_phy = &addl->proto_data.sasexp_phys[i];
+ sbuf_printf(sbp, "%s: phy %d: connector %d other %d\n",
+ sesname, i, exp_phy->connector_index,
+ exp_phy->other_index);
+ }
+ } else {
+ num_phys = addl->proto_hdr.sas->base_hdr.num_phys;
+ sbuf_printf(sbp, "Port: %d Phys", num_phys);
+ if (addl->proto_data.sasport_phys == NULL)
+ return;
+ for (i = 0;i < num_phys;i++) {
+ port_phy = &addl->proto_data.sasport_phys[i];
+ sbuf_printf(sbp,
+ "%s: phy %d: id %d connector %d other %d\n",
+ sesname, i, port_phy->phy_id,
+ port_phy->connector_index, port_phy->other_index);
+ sbuf_printf(sbp, "%s: phy %d: addr %jx\n", sesname, i,
+ (uintmax_t)scsi_8btou64(port_phy->phy_addr));
+ }
+ }
+}
+
+/**
+ * \brief Print the additional element status data for this object.
+ *
+ * \param enc SES softc associated with the object.
+ * \param obj The object to print the data for.
+ */
+static void
+ses_print_addl_data(enc_softc_t *enc, enc_element_t *obj)
+{
+ ses_element_t *elmpriv;
+ struct ses_addl_status *addl;
+ struct sbuf sesname, name, out;
+
+ elmpriv = obj->elm_private;
+ if (elmpriv == NULL)
+ return;
+
+ addl = &(elmpriv->addl);
+ if (addl->hdr == NULL)
+ return;
+
+ sbuf_new(&sesname, NULL, 16, SBUF_AUTOEXTEND);
+ sbuf_new(&name, NULL, 16, SBUF_AUTOEXTEND);
+ sbuf_new(&out, NULL, 512, SBUF_AUTOEXTEND);
+ ses_paths_iter(enc, obj, ses_elmdevname_callback, &name);
+ if (sbuf_len(&name) == 0)
+ sbuf_printf(&name, "(none)");
+ sbuf_finish(&name);
+ sbuf_printf(&sesname, "%s%d", enc->periph->periph_name,
+ enc->periph->unit_number);
+ sbuf_finish(&sesname);
+ if (elmpriv->descr != NULL)
+ sbuf_printf(&out, "%s: %s: Element descriptor: '%s'\n",
+ sbuf_data(&sesname), sbuf_data(&name), elmpriv->descr);
+ switch(ses_elm_addlstatus_proto(addl->hdr)) {
+ case SPSP_PROTO_SAS:
+ switch(ses_elm_sas_descr_type(addl->proto_hdr.sas)) {
+ case SES_SASOBJ_TYPE_SLOT:
+ ses_print_addl_data_sas_type0(sbuf_data(&sesname),
+ &out, obj, sbuf_data(&name));
+ break;
+ case SES_SASOBJ_TYPE_OTHER:
+ ses_print_addl_data_sas_type1(enc, sbuf_data(&sesname),
+ &out, obj, sbuf_data(&name));
+ break;
+ default:
+ break;
+ }
+ break;
+ case SPSP_PROTO_FC: /* stubbed for now */
+ break;
+ default:
+ break;
+ }
+ sbuf_finish(&out);
+ printf("%s", sbuf_data(&out));
+ sbuf_delete(&out);
+ sbuf_delete(&name);
+ sbuf_delete(&sesname);
+}
+
+/**
+ * \brief Update the softc with the additional element status data for this
+ * object, for SAS type 0 objects.
+ *
+ * \param enc SES softc to be updated.
+ * \param buf The additional element status response buffer.
+ * \param bufsiz Size of the response buffer.
+ * \param eip The EIP bit value.
+ * \param nobj Number of objects attached to the SES softc.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_get_elm_addlstatus_sas_type0(enc_softc_t *enc, enc_cache_t *enc_cache,
+ uint8_t *buf, int bufsiz, int eip, int nobj)
+{
+ int err, offset, physz;
+ enc_element_t *obj;
+ ses_element_t *elmpriv;
+ struct ses_addl_status *addl;
+
+ err = offset = 0;
+
+ /* basic object setup */
+ obj = &(enc_cache->elm_map[nobj]);
+ elmpriv = obj->elm_private;
+ addl = &(elmpriv->addl);
+
+ addl->proto_hdr.sas = (union ses_elm_sas_hdr *)&buf[offset];
+
+ /* Don't assume this object has any phys */
+ bzero(&addl->proto_data, sizeof(addl->proto_data));
+ if (addl->proto_hdr.sas->base_hdr.num_phys == 0)
+ goto out;
+
+ /* Skip forward to the phy list */
+ if (eip)
+ offset += sizeof(struct ses_elm_sas_type0_eip_hdr);
+ else
+ offset += sizeof(struct ses_elm_sas_type0_base_hdr);
+
+ /* Make sure the phy list fits in the buffer */
+ physz = addl->proto_hdr.sas->base_hdr.num_phys;
+ physz *= sizeof(struct ses_elm_sas_device_phy);
+ if (physz > (bufsiz - offset + 4)) {
+ ENC_LOG(enc, "Element %d Device Phy List Beyond End Of Buffer\n",
+ nobj);
+ err = EIO;
+ goto out;
+ }
+
+ /* Point to the phy list */
+ addl->proto_data.sasdev_phys =
+ (struct ses_elm_sas_device_phy *)&buf[offset];
+
+out:
+ return (err);
+}
+
+/**
+ * \brief Update the softc with the additional element status data for this
+ * object, for SAS type 1 objects.
+ *
+ * \param enc SES softc to be updated.
+ * \param buf The additional element status response buffer.
+ * \param bufsiz Size of the response buffer.
+ * \param eip The EIP bit value.
+ * \param nobj Number of objects attached to the SES softc.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_get_elm_addlstatus_sas_type1(enc_softc_t *enc, enc_cache_t *enc_cache,
+ uint8_t *buf, int bufsiz, int eip, int nobj)
+{
+ int err, offset, physz;
+ enc_element_t *obj;
+ ses_element_t *elmpriv;
+ struct ses_addl_status *addl;
+
+ err = offset = 0;
+
+ /* basic object setup */
+ obj = &(enc_cache->elm_map[nobj]);
+ elmpriv = obj->elm_private;
+ addl = &(elmpriv->addl);
+
+ addl->proto_hdr.sas = (union ses_elm_sas_hdr *)&buf[offset];
+
+ /* Don't assume this object has any phys */
+ bzero(&addl->proto_data, sizeof(addl->proto_data));
+ if (addl->proto_hdr.sas->base_hdr.num_phys == 0)
+ goto out;
+
+ /* Process expanders differently from other type1 cases */
+ if (ses_obj_is_expander(enc, obj)) {
+ offset += sizeof(struct ses_elm_sas_type1_expander_hdr);
+ physz = addl->proto_hdr.sas->base_hdr.num_phys *
+ sizeof(struct ses_elm_sas_expander_phy);
+ if (physz > (bufsiz - offset)) {
+ ENC_LOG(enc, "Element %d: Expander Phy List Beyond "
+ "End Of Buffer\n", nobj);
+ err = EIO;
+ goto out;
+ }
+ addl->proto_data.sasexp_phys =
+ (struct ses_elm_sas_expander_phy *)&buf[offset];
+ } else {
+ offset += sizeof(struct ses_elm_sas_type1_nonexpander_hdr);
+ physz = addl->proto_hdr.sas->base_hdr.num_phys *
+ sizeof(struct ses_elm_sas_port_phy);
+ if (physz > (bufsiz - offset + 4)) {
+ ENC_LOG(enc, "Element %d: Port Phy List Beyond End "
+ "Of Buffer\n", nobj);
+ err = EIO;
+ goto out;
+ }
+ addl->proto_data.sasport_phys =
+ (struct ses_elm_sas_port_phy *)&buf[offset];
+ }
+
+out:
+ return (err);
+}
+
+/**
+ * \brief Update the softc with the additional element status data for this
+ * object, for SAS objects.
+ *
+ * \param enc SES softc to be updated.
+ * \param buf The additional element status response buffer.
+ * \param bufsiz Size of the response buffer.
+ * \param eip The EIP bit value.
+ * \param tidx Type index for this object.
+ * \param nobj Number of objects attached to the SES softc.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_get_elm_addlstatus_sas(enc_softc_t *enc, enc_cache_t *enc_cache,
+ uint8_t *buf, int bufsiz, int eip, int tidx,
+ int nobj)
+{
+ int dtype, err;
+ ses_cache_t *ses_cache;
+ union ses_elm_sas_hdr *hdr;
+
+ /* Need to be able to read the descriptor type! */
+ if (bufsiz < sizeof(union ses_elm_sas_hdr)) {
+ err = EIO;
+ goto out;
+ }
+
+ ses_cache = enc_cache->private;
+
+ hdr = (union ses_elm_sas_hdr *)buf;
+ dtype = ses_elm_sas_descr_type(hdr);
+ switch(dtype) {
+ case SES_SASOBJ_TYPE_SLOT:
+ switch(ses_cache->ses_types[tidx].hdr->etype_elm_type) {
+ case ELMTYP_DEVICE:
+ case ELMTYP_ARRAY_DEV:
+ break;
+ default:
+ ENC_LOG(enc, "Element %d has Additional Status type 0, "
+ "invalid for SES element type 0x%x\n", nobj,
+ ses_cache->ses_types[tidx].hdr->etype_elm_type);
+ err = ENODEV;
+ goto out;
+ }
+ err = ses_get_elm_addlstatus_sas_type0(enc, enc_cache,
+ buf, bufsiz, eip,
+ nobj);
+ break;
+ case SES_SASOBJ_TYPE_OTHER:
+ switch(ses_cache->ses_types[tidx].hdr->etype_elm_type) {
+ case ELMTYP_SAS_EXP:
+ case ELMTYP_SCSI_INI:
+ case ELMTYP_SCSI_TGT:
+ case ELMTYP_ESCC:
+ break;
+ default:
+ ENC_LOG(enc, "Element %d has Additional Status type 1, "
+ "invalid for SES element type 0x%x\n", nobj,
+ ses_cache->ses_types[tidx].hdr->etype_elm_type);
+ err = ENODEV;
+ goto out;
+ }
+ err = ses_get_elm_addlstatus_sas_type1(enc, enc_cache, buf,
+ bufsiz, eip, nobj);
+ break;
+ default:
+ ENC_LOG(enc, "Element %d of type 0x%x has Additional Status "
+ "of unknown type 0x%x\n", nobj,
+ ses_cache->ses_types[tidx].hdr->etype_elm_type, dtype);
+ err = ENODEV;
+ break;
+ }
+
+out:
+ return (err);
+}
+
+static void
+ses_softc_invalidate(enc_softc_t *enc)
+{
+ ses_softc_t *ses;
+
+ ses = enc->enc_private;
+ ses_terminate_control_requests(&ses->ses_requests, ENXIO);
+}
+
+static void
+ses_softc_cleanup(enc_softc_t *enc)
+{
+
+ ses_cache_free(enc, &enc->enc_cache);
+ ses_cache_free(enc, &enc->enc_daemon_cache);
+ ENC_FREE_AND_NULL(enc->enc_private);
+ ENC_FREE_AND_NULL(enc->enc_cache.private);
+ ENC_FREE_AND_NULL(enc->enc_daemon_cache.private);
+}
+
+static int
+ses_init_enc(enc_softc_t *enc)
+{
+ return (0);
+}
+
+static int
+ses_get_enc_status(enc_softc_t *enc, int slpflag)
+{
+ /* Automatically updated, caller checks enc_cache->encstat itself */
+ return (0);
+}
+
+static int
+ses_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag)
+{
+ ses_control_request_t req;
+ ses_softc_t *ses;
+
+ ses = enc->enc_private;
+ req.elm_idx = SES_SETSTATUS_ENC_IDX;
+ req.elm_stat.comstatus = encstat & 0xf;
+
+ TAILQ_INSERT_TAIL(&ses->ses_requests, &req, links);
+ enc_update_request(enc, SES_PROCESS_CONTROL_REQS);
+ cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
+
+ return (req.result);
+}
+
+static int
+ses_get_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag)
+{
+ unsigned int i = elms->elm_idx;
+
+ memcpy(elms->cstat, &enc->enc_cache.elm_map[i].encstat, 4);
+ return (0);
+}
+
+static int
+ses_set_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag)
+{
+ ses_control_request_t req;
+ ses_softc_t *ses;
+
+ /* If this is clear, we don't do diddly. */
+ if ((elms->cstat[0] & SESCTL_CSEL) == 0)
+ return (0);
+
+ ses = enc->enc_private;
+ req.elm_idx = elms->elm_idx;
+ memcpy(&req.elm_stat, elms->cstat, sizeof(req.elm_stat));
+
+ TAILQ_INSERT_TAIL(&ses->ses_requests, &req, links);
+ enc_update_request(enc, SES_PROCESS_CONTROL_REQS);
+ cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
+
+ return (req.result);
+}
+
+static int
+ses_get_elm_desc(enc_softc_t *enc, encioc_elm_desc_t *elmd)
+{
+ int i = (int)elmd->elm_idx;
+ ses_element_t *elmpriv;
+
+ /* Assume caller has already checked obj_id validity */
+ elmpriv = enc->enc_cache.elm_map[i].elm_private;
+ /* object might not have a descriptor */
+ if (elmpriv == NULL || elmpriv->descr == NULL) {
+ elmd->elm_desc_len = 0;
+ return (0);
+ }
+ if (elmd->elm_desc_len > elmpriv->descr_len)
+ elmd->elm_desc_len = elmpriv->descr_len;
+ copyout(elmpriv->descr, elmd->elm_desc_str, elmd->elm_desc_len);
+ return (0);
+}
+
+/**
+ * \brief Respond to ENCIOC_GETELMDEVNAME, providing a device name for the
+ * given object id if one is available.
+ *
+ * \param enc SES softc to examine.
+ * \param objdn ioctl structure to read/write device name info.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_get_elm_devnames(enc_softc_t *enc, encioc_elm_devnames_t *elmdn)
+{
+ struct sbuf sb;
+ int len;
+
+ len = elmdn->elm_names_size;
+ if (len < 0)
+ return (EINVAL);
+
+ sbuf_new(&sb, elmdn->elm_devnames, len, 0);
+
+ cam_periph_unlock(enc->periph);
+ ses_paths_iter(enc, &enc->enc_cache.elm_map[elmdn->elm_idx],
+ ses_elmdevname_callback, &sb);
+ sbuf_finish(&sb);
+ elmdn->elm_names_len = sbuf_len(&sb);
+ cam_periph_lock(enc->periph);
+ return (elmdn->elm_names_len > 0 ? 0 : ENODEV);
+}
+
+/**
+ * \brief Send a string to the primary subenclosure using the String Out
+ * SES diagnostic page.
+ *
+ * \param enc SES enclosure to run the command on.
+ * \param sstr SES string structure to operate on
+ * \param ioc Ioctl being performed
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_handle_string(enc_softc_t *enc, encioc_string_t *sstr, int ioc)
+{
+ int amt, payload, ret;
+ char cdb[6];
+ uint8_t *buf;
+
+ /* Implement SES2r20 6.1.6 */
+ if (sstr->bufsiz > 0xffff)
+ return (EINVAL); /* buffer size too large */
+
+ if (ioc == ENCIOC_SETSTRING) {
+ payload = sstr->bufsiz + 4; /* header for SEND DIAGNOSTIC */
+ amt = 0 - payload;
+ buf = ENC_MALLOC(payload);
+ if (buf == NULL)
+ return ENOMEM;
+
+ ses_page_cdb(cdb, payload, 0, CAM_DIR_OUT);
+ /* Construct the page request */
+ buf[0] = SesStringOut;
+ buf[1] = 0;
+ buf[2] = sstr->bufsiz >> 8;
+ buf[3] = sstr->bufsiz & 0xff;
+ memcpy(&buf[4], sstr->buf, sstr->bufsiz);
+ } else if (ioc == ENCIOC_GETSTRING) {
+ payload = sstr->bufsiz;
+ amt = payload;
+ ses_page_cdb(cdb, payload, SesStringIn, CAM_DIR_IN);
+ buf = sstr->buf;
+ } else
+ return EINVAL;
+
+ ret = enc_runcmd(enc, cdb, 6, buf, &amt);
+ if (ioc == ENCIOC_SETSTRING)
+ ENC_FREE(buf);
+ return ret;
+}
+
+/**
+ * \invariant Called with cam_periph mutex held.
+ */
+static void
+ses_poll_status(enc_softc_t *enc)
+{
+ ses_softc_t *ses;
+
+ ses = enc->enc_private;
+ enc_update_request(enc, SES_UPDATE_GETSTATUS);
+ if (ses->ses_flags & SES_FLAG_ADDLSTATUS)
+ enc_update_request(enc, SES_UPDATE_GETELMADDLSTATUS);
+}
+
+/**
+ * \brief Notification received when CAM detects a new device in the
+ * SCSI domain in which this SEP resides.
+ *
+ * \param enc SES enclosure instance.
+ */
+static void
+ses_device_found(enc_softc_t *enc)
+{
+ ses_poll_status(enc);
+ enc_update_request(enc, SES_PUBLISH_PHYSPATHS);
+}
+
+static struct enc_vec ses_enc_vec =
+{
+ .softc_invalidate = ses_softc_invalidate,
+ .softc_cleanup = ses_softc_cleanup,
+ .init_enc = ses_init_enc,
+ .get_enc_status = ses_get_enc_status,
+ .set_enc_status = ses_set_enc_status,
+ .get_elm_status = ses_get_elm_status,
+ .set_elm_status = ses_set_elm_status,
+ .get_elm_desc = ses_get_elm_desc,
+ .get_elm_devnames = ses_get_elm_devnames,
+ .handle_string = ses_handle_string,
+ .device_found = ses_device_found,
+ .poll_status = ses_poll_status
+};
+
+/**
+ * \brief Initialize a new SES instance.
+ *
+ * \param enc SES softc structure to set up the instance in.
+ * \param doinit Do the initialization (see main driver).
+ *
+ * \return 0 on success, errno otherwise.
+ */
+int
+ses_softc_init(enc_softc_t *enc)
+{
+ ses_softc_t *ses_softc;
+
+ CAM_DEBUG(enc->periph->path, CAM_DEBUG_SUBTRACE,
+ ("entering enc_softc_init(%p)\n", enc));
+
+ enc->enc_vec = ses_enc_vec;
+ enc->enc_fsm_states = enc_fsm_states;
+
+ if (enc->enc_private == NULL)
+ enc->enc_private = ENC_MALLOCZ(sizeof(ses_softc_t));
+ if (enc->enc_cache.private == NULL)
+ enc->enc_cache.private = ENC_MALLOCZ(sizeof(ses_cache_t));
+ if (enc->enc_daemon_cache.private == NULL)
+ enc->enc_daemon_cache.private =
+ ENC_MALLOCZ(sizeof(ses_cache_t));
+
+ if (enc->enc_private == NULL
+ || enc->enc_cache.private == NULL
+ || enc->enc_daemon_cache.private == NULL) {
+ ENC_FREE_AND_NULL(enc->enc_private);
+ ENC_FREE_AND_NULL(enc->enc_cache.private);
+ ENC_FREE_AND_NULL(enc->enc_daemon_cache.private);
+ return (ENOMEM);
+ }
+
+ ses_softc = enc->enc_private;
+ TAILQ_INIT(&ses_softc->ses_requests);
+ TAILQ_INIT(&ses_softc->ses_pending_requests);
+
+ enc_update_request(enc, SES_UPDATE_PAGES);
+
+ // XXX: Move this to the FSM so it doesn't hang init
+ if (0) (void) ses_set_timed_completion(enc, 1);
+
+ return (0);
+}
+
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_pass.c
--- a/head/sys/cam/scsi/scsi_pass.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/scsi/scsi_pass.c Wed Jul 25 16:45:04 2012 +0300
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_pass.c 223089 2011-06-14 17:10:32Z gibbs $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_pass.c 237328 2012-06-20 17:08:00Z ken $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -55,7 +55,8 @@
typedef enum {
PASS_FLAG_OPEN = 0x01,
PASS_FLAG_LOCKED = 0x02,
- PASS_FLAG_INVALID = 0x04
+ PASS_FLAG_INVALID = 0x04,
+ PASS_FLAG_INITIAL_PHYSPATH = 0x08
} pass_flags;
typedef enum {
@@ -111,7 +112,7 @@
static struct cdevsw pass_cdevsw = {
.d_version = D_VERSION,
- .d_flags = 0,
+ .d_flags = D_TRACKCLOSE,
.d_open = passopen,
.d_close = passclose,
.d_ioctl = passioctl,
@@ -133,7 +134,18 @@
printf("pass: Failed to attach master async callback "
"due to status 0x%x!\n", status);
}
-
+
+}
+
+static void
+passdevgonecb(void *arg)
+{
+ struct cam_periph *periph;
+
+ periph = (struct cam_periph *)arg;
+
+ xpt_print(periph->path, "%s: devfs entry is gone\n", __func__);
+ cam_periph_release(periph);
}
static void
@@ -151,6 +163,12 @@
softc->flags |= PASS_FLAG_INVALID;
/*
+ * Tell devfs this device has gone away, and ask for a callback
+ * when it has cleaned up its state.
+ */
+ destroy_dev_sched_cb(softc->dev, passdevgonecb, periph);
+
+ /*
* XXX Return all queued I/O with ENXIO.
* XXX Handle any transactions queued to the card
* with XPT_ABORT_CCB.
@@ -176,11 +194,6 @@
cam_periph_unlock(periph);
taskqueue_drain(taskqueue_thread, &softc->add_physpath_task);
- /*
- * passcleanup() is indirectly a d_close method via passclose,
- * so using destroy_dev(9) directly can result in deadlock.
- */
- destroy_dev_sched(softc->dev);
cam_periph_lock(periph);
free(softc, M_DEVBUF);
@@ -199,6 +212,12 @@
*/
periph = context;
softc = periph->softc;
+ cam_periph_lock(periph);
+ if (periph->flags & CAM_PERIPH_INVALID) {
+ cam_periph_unlock(periph);
+ return;
+ }
+ cam_periph_unlock(periph);
physpath = malloc(MAXPATHLEN, M_DEVBUF, M_WAITOK);
if (xpt_getattr(physpath, MAXPATHLEN,
"GEOM::physpath", periph->path) == 0
@@ -208,6 +227,19 @@
softc->dev, softc->alias_dev, physpath);
}
free(physpath, M_DEVBUF);
+
+ /*
+ * Now that we've made our alias, we no longer have to have a
+ * reference to the device.
+ */
+ cam_periph_lock(periph);
+ if ((softc->flags & PASS_FLAG_INITIAL_PHYSPATH) == 0) {
+ softc->flags |= PASS_FLAG_INITIAL_PHYSPATH;
+ cam_periph_unlock(periph);
+ dev_rel(softc->dev);
+ }
+ else
+ cam_periph_unlock(periph);
}
static void
@@ -281,12 +313,12 @@
cgd = (struct ccb_getdev *)arg;
if (periph == NULL) {
- printf("passregister: periph was NULL!!\n");
+ printf("%s: periph was NULL!!\n", __func__);
return(CAM_REQ_CMP_ERR);
}
if (cgd == NULL) {
- printf("passregister: no getdev CCB, can't register device\n");
+ printf("%s: no getdev CCB, can't register device\n", __func__);
return(CAM_REQ_CMP_ERR);
}
@@ -294,8 +326,8 @@
M_DEVBUF, M_NOWAIT);
if (softc == NULL) {
- printf("passregister: Unable to probe new device. "
- "Unable to allocate softc\n");
+ printf("%s: Unable to probe new device. "
+ "Unable to allocate softc\n", __func__);
return(CAM_REQ_CMP_ERR);
}
@@ -331,10 +363,31 @@
DEVSTAT_TYPE_PASS,
DEVSTAT_PRIORITY_PASS);
+ /*
+ * Acquire a reference to the periph before we create the devfs
+ * instance for it. We'll release this reference once the devfs
+ * instance has been freed.
+ */
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
+ xpt_print(periph->path, "%s: lost periph during "
+ "registration!\n", __func__);
+ mtx_lock(periph->sim->mtx);
+ return (CAM_REQ_CMP_ERR);
+ }
+
/* Register the device */
softc->dev = make_dev(&pass_cdevsw, periph->unit_number,
UID_ROOT, GID_OPERATOR, 0600, "%s%d",
periph->periph_name, periph->unit_number);
+
+ /*
+ * Now that we have made the devfs instance, hold a reference to it
+ * until the task queue has run to setup the physical path alias.
+ * That way devfs won't get rid of the device before we add our
+ * alias.
+ */
+ dev_ref(softc->dev);
+
mtx_lock(periph->sim->mtx);
softc->dev->si_drv1 = periph;
@@ -377,8 +430,8 @@
softc = (struct pass_softc *)periph->softc;
if (softc->flags & PASS_FLAG_INVALID) {
+ cam_periph_release_locked(periph);
cam_periph_unlock(periph);
- cam_periph_release(periph);
return(ENXIO);
}
@@ -387,8 +440,8 @@
*/
error = securelevel_gt(td->td_ucred, 1);
if (error) {
+ cam_periph_release_locked(periph);
cam_periph_unlock(periph);
- cam_periph_release(periph);
return(error);
}
@@ -396,8 +449,8 @@
* Only allow read-write access.
*/
if (((flags & FWRITE) == 0) || ((flags & FREAD) == 0)) {
+ cam_periph_release_locked(periph);
cam_periph_unlock(periph);
- cam_periph_release(periph);
return(EPERM);
}
@@ -406,19 +459,12 @@
*/
if ((flags & O_NONBLOCK) != 0) {
xpt_print(periph->path, "can't do nonblocking access\n");
+ cam_periph_release_locked(periph);
cam_periph_unlock(periph);
- cam_periph_release(periph);
return(EINVAL);
}
- if ((softc->flags & PASS_FLAG_OPEN) == 0) {
- softc->flags |= PASS_FLAG_OPEN;
- cam_periph_unlock(periph);
- } else {
- /* Device closes aren't symmertical, so fix up the refcount */
- cam_periph_unlock(periph);
- cam_periph_release(periph);
- }
+ cam_periph_unlock(periph);
return (error);
}
@@ -427,18 +473,11 @@
passclose(struct cdev *dev, int flag, int fmt, struct thread *td)
{
struct cam_periph *periph;
- struct pass_softc *softc;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
return (ENXIO);
- cam_periph_lock(periph);
-
- softc = (struct pass_softc *)periph->softc;
- softc->flags &= ~PASS_FLAG_OPEN;
-
- cam_periph_unlock(periph);
cam_periph_release(periph);
return (0);
@@ -638,9 +677,9 @@
* that request. Otherwise, it's up to the user to perform any
* error recovery.
*/
- cam_periph_runccb(ccb,
- (ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ? passerror : NULL,
- /* cam_flags */ CAM_RETRY_SELTO, /* sense_flags */SF_RETRY_UA,
+ cam_periph_runccb(ccb, passerror, /* cam_flags */ CAM_RETRY_SELTO,
+ /* sense_flags */ ((ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ?
+ SF_RETRY_UA : SF_NO_RECOVERY) | SF_NO_PRINT,
softc->device_stats);
if (need_unmap != 0)
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_pt.c
--- a/head/sys/cam/scsi/scsi_pt.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/scsi/scsi_pt.c Wed Jul 25 16:45:04 2012 +0300
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_pt.c 220644 2011-04-14 21:25:32Z mav $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_pt.c 236602 2012-06-05 09:45:42Z mav $");
#include <sys/param.h>
#include <sys/queue.h>
@@ -148,8 +148,8 @@
cam_periph_lock(periph);
if (softc->flags & PT_FLAG_DEVICE_INVALID) {
+ cam_periph_release_locked(periph);
cam_periph_unlock(periph);
- cam_periph_release(periph);
return(ENXIO);
}
@@ -182,8 +182,8 @@
cam_periph_lock(periph);
softc->flags &= ~PT_FLAG_OPEN;
+ cam_periph_release_locked(periph);
cam_periph_unlock(periph);
- cam_periph_release(periph);
return (0);
}
@@ -425,12 +425,14 @@
softc = (struct pt_softc *)periph->softc;
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("ptstart\n"));
+
/*
* See if there is a buf with work for us to do..
*/
bp = bioq_first(&softc->bio_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
- CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("queuing for immediate ccb\n"));
start_ccb->ccb_h.ccb_state = PT_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
@@ -483,6 +485,9 @@
struct ccb_scsiio *csio;
softc = (struct pt_softc *)periph->softc;
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("ptdone\n"));
+
csio = &done_ccb->csio;
switch (csio->ccb_h.ccb_state) {
case PT_CCB_BUFFER_IO:
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_sa.c
--- a/head/sys/cam/scsi/scsi_sa.c Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/scsi/scsi_sa.c Wed Jul 25 16:45:04 2012 +0300
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_sa.c 229288 2012-01-02 17:02:45Z mav $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_sa.c 236712 2012-06-07 10:05:51Z mav $");
#include <sys/param.h>
#include <sys/queue.h>
@@ -1482,10 +1482,6 @@
softc->quirks = ((struct sa_quirk_entry *)match)->quirks;
softc->last_media_blksize =
((struct sa_quirk_entry *)match)->prefblk;
-#ifdef CAMDEBUG
- xpt_print(periph->path, "found quirk entry %d\n",
- (int) (((struct sa_quirk_entry *) match) - sa_quirk_table));
-#endif
} else
softc->quirks = SA_QUIRK_NONE;
@@ -1798,13 +1794,11 @@
*/
if (error || (softc->flags & SA_FLAG_ERR_PENDING))
cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0);
-#ifdef CAMDEBUG
if (error || bp->bio_resid) {
CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
("error %d resid %ld count %ld\n", error,
bp->bio_resid, bp->bio_bcount));
}
-#endif
biofinish(bp, softc->device_stats, 0);
break;
}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_ses.c
--- a/head/sys/cam/scsi/scsi_ses.c Wed Jul 25 16:42:35 2012 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2533 +0,0 @@
-/*-
- * Copyright (c) 2000 Matthew Jacob
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions, and the following disclaimer,
- * without modification, immediately at the beginning of the file.
- * 2. 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 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: head/sys/cam/scsi/scsi_ses.c 229288 2012-01-02 17:02:45Z mav $");
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/types.h>
-#include <sys/malloc.h>
-#include <sys/fcntl.h>
-#include <sys/conf.h>
-#include <sys/errno.h>
-#include <machine/stdarg.h>
-
-#include <cam/cam.h>
-#include <cam/cam_ccb.h>
-#include <cam/cam_periph.h>
-#include <cam/cam_xpt_periph.h>
-#include <cam/cam_debug.h>
-#include <cam/cam_sim.h>
-
-#include <cam/scsi/scsi_all.h>
-#include <cam/scsi/scsi_message.h>
-#include <sys/ioccom.h>
-#include <cam/scsi/scsi_ses.h>
-
-#include <opt_ses.h>
-
-static MALLOC_DEFINE(M_SCSISES, "SCSI SES", "SCSI SES buffers");
-
-/*
- * Platform Independent Driver Internal Definitions for SES devices.
- */
-typedef enum {
- SES_NONE,
- SES_SES_SCSI2,
- SES_SES,
- SES_SES_PASSTHROUGH,
- SES_SEN,
- SES_SAFT
-} enctyp;
-
-struct ses_softc;
-typedef struct ses_softc ses_softc_t;
-typedef struct {
- int (*softc_init)(ses_softc_t *, int);
- int (*init_enc)(ses_softc_t *);
- int (*get_encstat)(ses_softc_t *, int);
- int (*set_encstat)(ses_softc_t *, ses_encstat, int);
- int (*get_objstat)(ses_softc_t *, ses_objstat *, int);
- int (*set_objstat)(ses_softc_t *, ses_objstat *, int);
-} encvec;
-
-#define ENCI_SVALID 0x80
-
-typedef struct {
- uint32_t
- enctype : 8, /* enclosure type */
- subenclosure : 8, /* subenclosure id */
- svalid : 1, /* enclosure information valid */
- priv : 15; /* private data, per object */
- uint8_t encstat[4]; /* state && stats */
-} encobj;
-
-#define SEN_ID "UNISYS SUN_SEN"
-#define SEN_ID_LEN 24
-
-
-static enctyp ses_type(void *, int);
-
-
-/* Forward reference to Enclosure Functions */
-static int ses_softc_init(ses_softc_t *, int);
-static int ses_init_enc(ses_softc_t *);
-static int ses_get_encstat(ses_softc_t *, int);
-static int ses_set_encstat(ses_softc_t *, uint8_t, int);
-static int ses_get_objstat(ses_softc_t *, ses_objstat *, int);
-static int ses_set_objstat(ses_softc_t *, ses_objstat *, int);
-
-static int safte_softc_init(ses_softc_t *, int);
-static int safte_init_enc(ses_softc_t *);
-static int safte_get_encstat(ses_softc_t *, int);
-static int safte_set_encstat(ses_softc_t *, uint8_t, int);
-static int safte_get_objstat(ses_softc_t *, ses_objstat *, int);
-static int safte_set_objstat(ses_softc_t *, ses_objstat *, int);
-
-/*
- * Platform implementation defines/functions for SES internal kernel stuff
- */
-
-#define STRNCMP strncmp
-#define PRINTF printf
-#define SES_LOG ses_log
-#ifdef DEBUG
-#define SES_DLOG ses_log
-#else
-#define SES_DLOG if (0) ses_log
-#endif
-#define SES_VLOG if (bootverbose) ses_log
-#define SES_MALLOC(amt) malloc(amt, M_SCSISES, M_NOWAIT)
-#define SES_FREE(ptr, amt) free(ptr, M_SCSISES)
-#define MEMZERO bzero
-#define MEMCPY(dest, src, amt) bcopy(src, dest, amt)
-
-static int ses_runcmd(struct ses_softc *, char *, int, char *, int *);
-static void ses_log(struct ses_softc *, const char *, ...);
-
-/*
- * Gerenal FreeBSD kernel stuff.
- */
-
-
-#define ccb_state ppriv_field0
-#define ccb_bp ppriv_ptr1
-
-struct ses_softc {
- enctyp ses_type; /* type of enclosure */
- encvec ses_vec; /* vector to handlers */
- void * ses_private; /* per-type private data */
- encobj * ses_objmap; /* objects */
- uint32_t ses_nobjects; /* number of objects */
- ses_encstat ses_encstat; /* overall status */
- uint8_t ses_flags;
- union ccb ses_saved_ccb;
- struct cdev *ses_dev;
- struct cam_periph *periph;
-};
-#define SES_FLAG_INVALID 0x01
-#define SES_FLAG_OPEN 0x02
-#define SES_FLAG_INITIALIZED 0x04
-
-static d_open_t sesopen;
-static d_close_t sesclose;
-static d_ioctl_t sesioctl;
-static periph_init_t sesinit;
-static periph_ctor_t sesregister;
-static periph_oninv_t sesoninvalidate;
-static periph_dtor_t sescleanup;
-static periph_start_t sesstart;
-
-static void sesasync(void *, uint32_t, struct cam_path *, void *);
-static void sesdone(struct cam_periph *, union ccb *);
-static int seserror(union ccb *, uint32_t, uint32_t);
-
-static struct periph_driver sesdriver = {
- sesinit, "ses",
- TAILQ_HEAD_INITIALIZER(sesdriver.units), /* generation */ 0
-};
-
-PERIPHDRIVER_DECLARE(ses, sesdriver);
-
-static struct cdevsw ses_cdevsw = {
- .d_version = D_VERSION,
- .d_open = sesopen,
- .d_close = sesclose,
- .d_ioctl = sesioctl,
- .d_name = "ses",
- .d_flags = 0,
-};
-
-static void
-sesinit(void)
-{
- cam_status status;
-
- /*
- * Install a global async callback. This callback will
- * receive async callbacks like "new device found".
- */
- status = xpt_register_async(AC_FOUND_DEVICE, sesasync, NULL, NULL);
-
- if (status != CAM_REQ_CMP) {
- printf("ses: Failed to attach master async callback "
- "due to status 0x%x!\n", status);
- }
-}
-
-static void
-sesoninvalidate(struct cam_periph *periph)
-{
- struct ses_softc *softc;
-
- softc = (struct ses_softc *)periph->softc;
-
- /*
- * Unregister any async callbacks.
- */
- xpt_register_async(0, sesasync, periph, periph->path);
-
- softc->ses_flags |= SES_FLAG_INVALID;
-
- xpt_print(periph->path, "lost device\n");
-}
-
-static void
-sescleanup(struct cam_periph *periph)
-{
- struct ses_softc *softc;
-
- softc = (struct ses_softc *)periph->softc;
-
- xpt_print(periph->path, "removing device entry\n");
- cam_periph_unlock(periph);
- destroy_dev(softc->ses_dev);
- cam_periph_lock(periph);
- free(softc, M_SCSISES);
-}
-
-static void
-sesasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
-{
- struct cam_periph *periph;
-
- periph = (struct cam_periph *)callback_arg;
-
- switch(code) {
- case AC_FOUND_DEVICE:
- {
- cam_status status;
- struct ccb_getdev *cgd;
- int inq_len;
-
- cgd = (struct ccb_getdev *)arg;
- if (arg == NULL) {
- break;
- }
-
- if (cgd->protocol != PROTO_SCSI)
- break;
-
- inq_len = cgd->inq_data.additional_length + 4;
-
- /*
- * PROBLEM: WE NEED TO LOOK AT BYTES 48-53 TO SEE IF THIS IS
- * PROBLEM: IS A SAF-TE DEVICE.
- */
- switch (ses_type(&cgd->inq_data, inq_len)) {
- case SES_SES:
- case SES_SES_SCSI2:
- case SES_SES_PASSTHROUGH:
- case SES_SEN:
- case SES_SAFT:
- break;
- default:
- return;
- }
-
- status = cam_periph_alloc(sesregister, sesoninvalidate,
- sescleanup, sesstart, "ses", CAM_PERIPH_BIO,
- cgd->ccb_h.path, sesasync, AC_FOUND_DEVICE, cgd);
-
- if (status != CAM_REQ_CMP && status != CAM_REQ_INPROG) {
- printf("sesasync: Unable to probe new device due to "
- "status 0x%x\n", status);
- }
- break;
- }
- default:
- cam_periph_async(periph, code, path, arg);
- break;
- }
-}
-
-static cam_status
-sesregister(struct cam_periph *periph, void *arg)
-{
- struct ses_softc *softc;
- struct ccb_getdev *cgd;
- char *tname;
-
- cgd = (struct ccb_getdev *)arg;
- if (periph == NULL) {
- printf("sesregister: periph was NULL!!\n");
- return (CAM_REQ_CMP_ERR);
- }
-
- if (cgd == NULL) {
- printf("sesregister: no getdev CCB, can't register device\n");
- return (CAM_REQ_CMP_ERR);
- }
-
- softc = SES_MALLOC(sizeof (struct ses_softc));
- if (softc == NULL) {
- printf("sesregister: Unable to probe new device. "
- "Unable to allocate softc\n");
- return (CAM_REQ_CMP_ERR);
- }
- bzero(softc, sizeof (struct ses_softc));
- periph->softc = softc;
- softc->periph = periph;
-
- softc->ses_type = ses_type(&cgd->inq_data, sizeof (cgd->inq_data));
-
- switch (softc->ses_type) {
- case SES_SES:
- case SES_SES_SCSI2:
- case SES_SES_PASSTHROUGH:
- softc->ses_vec.softc_init = ses_softc_init;
- softc->ses_vec.init_enc = ses_init_enc;
- softc->ses_vec.get_encstat = ses_get_encstat;
- softc->ses_vec.set_encstat = ses_set_encstat;
- softc->ses_vec.get_objstat = ses_get_objstat;
- softc->ses_vec.set_objstat = ses_set_objstat;
- break;
- case SES_SAFT:
- softc->ses_vec.softc_init = safte_softc_init;
- softc->ses_vec.init_enc = safte_init_enc;
- softc->ses_vec.get_encstat = safte_get_encstat;
- softc->ses_vec.set_encstat = safte_set_encstat;
- softc->ses_vec.get_objstat = safte_get_objstat;
- softc->ses_vec.set_objstat = safte_set_objstat;
- break;
- case SES_SEN:
- break;
- case SES_NONE:
- default:
- free(softc, M_SCSISES);
- return (CAM_REQ_CMP_ERR);
- }
-
- cam_periph_unlock(periph);
- softc->ses_dev = make_dev(&ses_cdevsw, periph->unit_number,
- UID_ROOT, GID_OPERATOR, 0600, "%s%d",
- periph->periph_name, periph->unit_number);
- cam_periph_lock(periph);
- softc->ses_dev->si_drv1 = periph;
-
- /*
- * Add an async callback so that we get
- * notified if this device goes away.
- */
- xpt_register_async(AC_LOST_DEVICE, sesasync, periph, periph->path);
-
- switch (softc->ses_type) {
- default:
- case SES_NONE:
- tname = "No SES device";
- break;
- case SES_SES_SCSI2:
- tname = "SCSI-2 SES Device";
- break;
- case SES_SES:
- tname = "SCSI-3 SES Device";
- break;
- case SES_SES_PASSTHROUGH:
- tname = "SES Passthrough Device";
- break;
- case SES_SEN:
- tname = "UNISYS SEN Device (NOT HANDLED YET)";
- break;
- case SES_SAFT:
- tname = "SAF-TE Compliant Device";
- break;
- }
- xpt_announce_periph(periph, tname);
- return (CAM_REQ_CMP);
-}
-
-static int
-sesopen(struct cdev *dev, int flags, int fmt, struct thread *td)
-{
- struct cam_periph *periph;
- struct ses_softc *softc;
- int error = 0;
-
- periph = (struct cam_periph *)dev->si_drv1;
- if (periph == NULL) {
- return (ENXIO);
- }
-
- if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
- cam_periph_unlock(periph);
- return (ENXIO);
- }
-
- cam_periph_lock(periph);
-
- softc = (struct ses_softc *)periph->softc;
-
- if (softc->ses_flags & SES_FLAG_INVALID) {
- error = ENXIO;
- goto out;
- }
- if (softc->ses_flags & SES_FLAG_OPEN) {
- error = EBUSY;
- goto out;
- }
- if (softc->ses_vec.softc_init == NULL) {
- error = ENXIO;
- goto out;
- }
-
- softc->ses_flags |= SES_FLAG_OPEN;
- if ((softc->ses_flags & SES_FLAG_INITIALIZED) == 0) {
- error = (*softc->ses_vec.softc_init)(softc, 1);
- if (error)
- softc->ses_flags &= ~SES_FLAG_OPEN;
- else
- softc->ses_flags |= SES_FLAG_INITIALIZED;
- }
-
-out:
- cam_periph_unlock(periph);
- if (error) {
- cam_periph_release(periph);
- }
- return (error);
-}
-
-static int
-sesclose(struct cdev *dev, int flag, int fmt, struct thread *td)
-{
- struct cam_periph *periph;
- struct ses_softc *softc;
- int error;
-
- error = 0;
-
- periph = (struct cam_periph *)dev->si_drv1;
- if (periph == NULL)
- return (ENXIO);
-
- cam_periph_lock(periph);
-
- softc = (struct ses_softc *)periph->softc;
- softc->ses_flags &= ~SES_FLAG_OPEN;
-
- cam_periph_unlock(periph);
- cam_periph_release(periph);
-
- return (0);
-}
-
-static void
-sesstart(struct cam_periph *p, union ccb *sccb)
-{
- if (p->immediate_priority <= p->pinfo.priority) {
- SLIST_INSERT_HEAD(&p->ccb_list, &sccb->ccb_h, periph_links.sle);
- p->immediate_priority = CAM_PRIORITY_NONE;
- wakeup(&p->ccb_list);
- }
-}
-
-static void
-sesdone(struct cam_periph *periph, union ccb *dccb)
-{
- wakeup(&dccb->ccb_h.cbfcnp);
-}
-
-static int
-seserror(union ccb *ccb, uint32_t cflags, uint32_t sflags)
-{
- struct ses_softc *softc;
- struct cam_periph *periph;
-
- periph = xpt_path_periph(ccb->ccb_h.path);
- softc = (struct ses_softc *)periph->softc;
-
- return (cam_periph_error(ccb, cflags, sflags, &softc->ses_saved_ccb));
-}
-
-static int
-sesioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag, struct thread *td)
-{
- struct cam_periph *periph;
- ses_encstat tmp;
- ses_objstat objs;
- ses_object *uobj;
- struct ses_softc *ssc;
- void *addr;
- int error, i;
-
-
- if (arg_addr)
- addr = *((caddr_t *) arg_addr);
- else
- addr = NULL;
-
- periph = (struct cam_periph *)dev->si_drv1;
- if (periph == NULL)
- return (ENXIO);
-
- CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering sesioctl\n"));
-
- cam_periph_lock(periph);
- ssc = (struct ses_softc *)periph->softc;
-
- /*
- * Now check to see whether we're initialized or not.
- * This actually should never fail as we're not supposed
- * to get past ses_open w/o successfully initializing
- * things.
- */
- if ((ssc->ses_flags & SES_FLAG_INITIALIZED) == 0) {
- cam_periph_unlock(periph);
- return (ENXIO);
- }
- cam_periph_unlock(periph);
-
- error = 0;
-
- CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
- ("trying to do ioctl %#lx\n", cmd));
-
- /*
- * If this command can change the device's state,
- * we must have the device open for writing.
- *
- * For commands that get information about the
- * device- we don't need to lock the peripheral
- * if we aren't running a command. The number
- * of objects and the contents will stay stable
- * after the first open that does initialization.
- * The periph also can't go away while a user
- * process has it open.
- */
- switch (cmd) {
- case SESIOC_GETNOBJ:
- case SESIOC_GETOBJMAP:
- case SESIOC_GETENCSTAT:
- case SESIOC_GETOBJSTAT:
- break;
- default:
- if ((flag & FWRITE) == 0) {
- return (EBADF);
- }
- }
-
- switch (cmd) {
- case SESIOC_GETNOBJ:
- error = copyout(&ssc->ses_nobjects, addr,
- sizeof (ssc->ses_nobjects));
- break;
-
- case SESIOC_GETOBJMAP:
- for (uobj = addr, i = 0; i != ssc->ses_nobjects; i++) {
- ses_object kobj;
- kobj.obj_id = i;
- kobj.subencid = ssc->ses_objmap[i].subenclosure;
- kobj.object_type = ssc->ses_objmap[i].enctype;
- error = copyout(&kobj, &uobj[i], sizeof (ses_object));
- if (error) {
- break;
- }
- }
- break;
-
- case SESIOC_GETENCSTAT:
- cam_periph_lock(periph);
- error = (*ssc->ses_vec.get_encstat)(ssc, 1);
- if (error) {
- cam_periph_unlock(periph);
- break;
- }
- tmp = ssc->ses_encstat & ~ENCI_SVALID;
- cam_periph_unlock(periph);
- error = copyout(&tmp, addr, sizeof (ses_encstat));
- ssc->ses_encstat = tmp;
- break;
-
- case SESIOC_SETENCSTAT:
- error = copyin(addr, &tmp, sizeof (ses_encstat));
- if (error)
- break;
- cam_periph_lock(periph);
- error = (*ssc->ses_vec.set_encstat)(ssc, tmp, 1);
- cam_periph_unlock(periph);
- break;
-
- case SESIOC_GETOBJSTAT:
- error = copyin(addr, &objs, sizeof (ses_objstat));
- if (error)
- break;
- if (objs.obj_id >= ssc->ses_nobjects) {
- error = EINVAL;
- break;
- }
- cam_periph_lock(periph);
- error = (*ssc->ses_vec.get_objstat)(ssc, &objs, 1);
- cam_periph_unlock(periph);
- if (error)
- break;
- error = copyout(&objs, addr, sizeof (ses_objstat));
- /*
- * Always (for now) invalidate entry.
- */
- ssc->ses_objmap[objs.obj_id].svalid = 0;
- break;
-
- case SESIOC_SETOBJSTAT:
- error = copyin(addr, &objs, sizeof (ses_objstat));
- if (error)
- break;
-
- if (objs.obj_id >= ssc->ses_nobjects) {
- error = EINVAL;
- break;
- }
- cam_periph_lock(periph);
- error = (*ssc->ses_vec.set_objstat)(ssc, &objs, 1);
- cam_periph_unlock(periph);
-
- /*
- * Always (for now) invalidate entry.
- */
- ssc->ses_objmap[objs.obj_id].svalid = 0;
- break;
-
- case SESIOC_INIT:
-
- cam_periph_lock(periph);
- error = (*ssc->ses_vec.init_enc)(ssc);
- cam_periph_unlock(periph);
- break;
-
- default:
- cam_periph_lock(periph);
- error = cam_periph_ioctl(periph, cmd, arg_addr, seserror);
- cam_periph_unlock(periph);
- break;
- }
- return (error);
-}
-
-#define SES_CFLAGS CAM_RETRY_SELTO
-#define SES_FLAGS SF_NO_PRINT | SF_RETRY_UA
-static int
-ses_runcmd(struct ses_softc *ssc, char *cdb, int cdbl, char *dptr, int *dlenp)
-{
- int error, dlen;
- ccb_flags ddf;
- union ccb *ccb;
-
- if (dptr) {
- if ((dlen = *dlenp) < 0) {
- dlen = -dlen;
- ddf = CAM_DIR_OUT;
- } else {
- ddf = CAM_DIR_IN;
- }
- } else {
- dlen = 0;
- ddf = CAM_DIR_NONE;
- }
-
- if (cdbl > IOCDBLEN) {
- cdbl = IOCDBLEN;
- }
-
- ccb = cam_periph_getccb(ssc->periph, 1);
- cam_fill_csio(&ccb->csio, 0, sesdone, ddf, MSG_SIMPLE_Q_TAG, dptr,
- dlen, sizeof (struct scsi_sense_data), cdbl, 60 * 1000);
- bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl);
-
- error = cam_periph_runccb(ccb, seserror, SES_CFLAGS, SES_FLAGS, NULL);
- if (error) {
- if (dptr) {
- *dlenp = dlen;
- }
- } else {
- if (dptr) {
- *dlenp = ccb->csio.resid;
- }
- }
- xpt_release_ccb(ccb);
- return (error);
-}
-
-static void
-ses_log(struct ses_softc *ssc, const char *fmt, ...)
-{
- va_list ap;
-
- printf("%s%d: ", ssc->periph->periph_name, ssc->periph->unit_number);
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
-}
-
-/*
- * The code after this point runs on many platforms,
- * so forgive the slightly awkward and nonconforming
- * appearance.
- */
-
-/*
- * Is this a device that supports enclosure services?
- *
- * It's a pretty simple ruleset- if it is device type 0x0D (13), it's
- * an SES device. If it happens to be an old UNISYS SEN device, we can
- * handle that too.
- */
-
-#define SAFTE_START 44
-#define SAFTE_END 50
-#define SAFTE_LEN SAFTE_END-SAFTE_START
-
-static enctyp
-ses_type(void *buf, int buflen)
-{
- unsigned char *iqd = buf;
-
- if (buflen < 8+SEN_ID_LEN)
- return (SES_NONE);
-
- if ((iqd[0] & 0x1f) == T_ENCLOSURE) {
- if (STRNCMP(&iqd[8], SEN_ID, SEN_ID_LEN) == 0) {
- return (SES_SEN);
- } else if ((iqd[2] & 0x7) > 2) {
- return (SES_SES);
- } else {
- return (SES_SES_SCSI2);
- }
- return (SES_NONE);
- }
-
-#ifdef SES_ENABLE_PASSTHROUGH
- if ((iqd[6] & 0x40) && (iqd[2] & 0x7) >= 2) {
- /*
- * PassThrough Device.
- */
- return (SES_SES_PASSTHROUGH);
- }
-#endif
-
- /*
- * The comparison is short for a reason-
- * some vendors were chopping it short.
- */
-
- if (buflen < SAFTE_END - 2) {
- return (SES_NONE);
- }
-
- if (STRNCMP((char *)&iqd[SAFTE_START], "SAF-TE", SAFTE_LEN - 2) == 0) {
- return (SES_SAFT);
- }
- return (SES_NONE);
-}
-
-/*
- * SES Native Type Device Support
- */
-
-/*
- * SES Diagnostic Page Codes
- */
-
-typedef enum {
- SesConfigPage = 0x1,
- SesControlPage,
-#define SesStatusPage SesControlPage
- SesHelpTxt,
- SesStringOut,
-#define SesStringIn SesStringOut
- SesThresholdOut,
-#define SesThresholdIn SesThresholdOut
- SesArrayControl,
-#define SesArrayStatus SesArrayControl
- SesElementDescriptor,
- SesShortStatus
-} SesDiagPageCodes;
-
-/*
- * minimal amounts
- */
-
-/*
- * Minimum amount of data, starting from byte 0, to have
- * the config header.
- */
-#define SES_CFGHDR_MINLEN 12
-
-/*
- * Minimum amount of data, starting from byte 0, to have
- * the config header and one enclosure header.
- */
-#define SES_ENCHDR_MINLEN 48
-
-/*
- * Take this value, subtract it from VEnclen and you know
- * the length of the vendor unique bytes.
- */
-#define SES_ENCHDR_VMIN 36
-
-/*
- * SES Data Structures
- */
-
-typedef struct {
- uint32_t GenCode; /* Generation Code */
- uint8_t Nsubenc; /* Number of Subenclosures */
-} SesCfgHdr;
-
-typedef struct {
- uint8_t Subencid; /* SubEnclosure Identifier */
- uint8_t Ntypes; /* # of supported types */
- uint8_t VEnclen; /* Enclosure Descriptor Length */
-} SesEncHdr;
-
-typedef struct {
- uint8_t encWWN[8]; /* XXX- Not Right Yet */
- uint8_t encVid[8];
- uint8_t encPid[16];
- uint8_t encRev[4];
- uint8_t encVen[1];
-} SesEncDesc;
-
-typedef struct {
- uint8_t enc_type; /* type of element */
- uint8_t enc_maxelt; /* maximum supported */
- uint8_t enc_subenc; /* in SubEnc # N */
- uint8_t enc_tlen; /* Type Descriptor Text Length */
-} SesThdr;
-
-typedef struct {
- uint8_t comstatus;
- uint8_t comstat[3];
-} SesComStat;
-
-struct typidx {
- int ses_tidx;
- int ses_oidx;
-};
-
-struct sscfg {
- uint8_t ses_ntypes; /* total number of types supported */
-
- /*
- * We need to keep a type index as well as an
- * object index for each object in an enclosure.
- */
- struct typidx *ses_typidx;
-
- /*
- * We also need to keep track of the number of elements
- * per type of element. This is needed later so that we
- * can find precisely in the returned status data the
- * status for the Nth element of the Kth type.
- */
- uint8_t * ses_eltmap;
-};
-
-
-/*
- * (de)canonicalization defines
- */
-#define sbyte(x, byte) ((((uint32_t)(x)) >> (byte * 8)) & 0xff)
-#define sbit(x, bit) (((uint32_t)(x)) << bit)
-#define sset8(outp, idx, sval) (((uint8_t *)(outp))[idx++]) = sbyte(sval, 0)
-
-#define sset16(outp, idx, sval) \
- (((uint8_t *)(outp))[idx++]) = sbyte(sval, 1), \
- (((uint8_t *)(outp))[idx++]) = sbyte(sval, 0)
-
-
-#define sset24(outp, idx, sval) \
- (((uint8_t *)(outp))[idx++]) = sbyte(sval, 2), \
- (((uint8_t *)(outp))[idx++]) = sbyte(sval, 1), \
- (((uint8_t *)(outp))[idx++]) = sbyte(sval, 0)
-
-
-#define sset32(outp, idx, sval) \
- (((uint8_t *)(outp))[idx++]) = sbyte(sval, 3), \
- (((uint8_t *)(outp))[idx++]) = sbyte(sval, 2), \
- (((uint8_t *)(outp))[idx++]) = sbyte(sval, 1), \
- (((uint8_t *)(outp))[idx++]) = sbyte(sval, 0)
-
-#define gbyte(x, byte) ((((uint32_t)(x)) & 0xff) << (byte * 8))
-#define gbit(lv, in, idx, shft, mask) lv = ((in[idx] >> shft) & mask)
-#define sget8(inp, idx, lval) lval = (((uint8_t *)(inp))[idx++])
-#define gget8(inp, idx, lval) lval = (((uint8_t *)(inp))[idx])
-
-#define sget16(inp, idx, lval) \
- lval = gbyte((((uint8_t *)(inp))[idx]), 1) | \
- (((uint8_t *)(inp))[idx+1]), idx += 2
-
-#define gget16(inp, idx, lval) \
- lval = gbyte((((uint8_t *)(inp))[idx]), 1) | \
- (((uint8_t *)(inp))[idx+1])
-
-#define sget24(inp, idx, lval) \
- lval = gbyte((((uint8_t *)(inp))[idx]), 2) | \
- gbyte((((uint8_t *)(inp))[idx+1]), 1) | \
- (((uint8_t *)(inp))[idx+2]), idx += 3
-
-#define gget24(inp, idx, lval) \
- lval = gbyte((((uint8_t *)(inp))[idx]), 2) | \
- gbyte((((uint8_t *)(inp))[idx+1]), 1) | \
- (((uint8_t *)(inp))[idx+2])
-
-#define sget32(inp, idx, lval) \
- lval = gbyte((((uint8_t *)(inp))[idx]), 3) | \
- gbyte((((uint8_t *)(inp))[idx+1]), 2) | \
- gbyte((((uint8_t *)(inp))[idx+2]), 1) | \
- (((uint8_t *)(inp))[idx+3]), idx += 4
-
-#define gget32(inp, idx, lval) \
- lval = gbyte((((uint8_t *)(inp))[idx]), 3) | \
- gbyte((((uint8_t *)(inp))[idx+1]), 2) | \
- gbyte((((uint8_t *)(inp))[idx+2]), 1) | \
- (((uint8_t *)(inp))[idx+3])
-
-#define SCSZ 0x2000
-#define CFLEN (256 + SES_ENCHDR_MINLEN)
-
-/*
- * Routines specific && private to SES only
- */
-
-static int ses_getconfig(ses_softc_t *);
-static int ses_getputstat(ses_softc_t *, int, SesComStat *, int, int);
-static int ses_cfghdr(uint8_t *, int, SesCfgHdr *);
-static int ses_enchdr(uint8_t *, int, uint8_t, SesEncHdr *);
-static int ses_encdesc(uint8_t *, int, uint8_t, SesEncDesc *);
-static int ses_getthdr(uint8_t *, int, int, SesThdr *);
-static int ses_decode(char *, int, uint8_t *, int, int, SesComStat *);
-static int ses_encode(char *, int, uint8_t *, int, int, SesComStat *);
-
-static int
-ses_softc_init(ses_softc_t *ssc, int doinit)
-{
- if (doinit == 0) {
- struct sscfg *cc;
- if (ssc->ses_nobjects) {
- SES_FREE(ssc->ses_objmap,
- ssc->ses_nobjects * sizeof (encobj));
- ssc->ses_objmap = NULL;
- }
- if ((cc = ssc->ses_private) != NULL) {
- if (cc->ses_eltmap && cc->ses_ntypes) {
- SES_FREE(cc->ses_eltmap, cc->ses_ntypes);
- cc->ses_eltmap = NULL;
- cc->ses_ntypes = 0;
- }
- if (cc->ses_typidx && ssc->ses_nobjects) {
- SES_FREE(cc->ses_typidx,
- ssc->ses_nobjects * sizeof (struct typidx));
- cc->ses_typidx = NULL;
- }
- SES_FREE(cc, sizeof (struct sscfg));
- ssc->ses_private = NULL;
- }
- ssc->ses_nobjects = 0;
- return (0);
- }
- if (ssc->ses_private == NULL) {
- ssc->ses_private = SES_MALLOC(sizeof (struct sscfg));
- }
- if (ssc->ses_private == NULL) {
- return (ENOMEM);
- }
- ssc->ses_nobjects = 0;
- ssc->ses_encstat = 0;
- return (ses_getconfig(ssc));
-}
-
-static int
-ses_init_enc(ses_softc_t *ssc)
-{
- return (0);
-}
-
-static int
-ses_get_encstat(ses_softc_t *ssc, int slpflag)
-{
- SesComStat ComStat;
- int status;
-
- if ((status = ses_getputstat(ssc, -1, &ComStat, slpflag, 1)) != 0) {
- return (status);
- }
- ssc->ses_encstat = ComStat.comstatus | ENCI_SVALID;
- return (0);
-}
-
-static int
-ses_set_encstat(ses_softc_t *ssc, uint8_t encstat, int slpflag)
-{
- SesComStat ComStat;
- int status;
-
- ComStat.comstatus = encstat & 0xf;
- if ((status = ses_getputstat(ssc, -1, &ComStat, slpflag, 0)) != 0) {
- return (status);
- }
- ssc->ses_encstat = encstat & 0xf; /* note no SVALID set */
- return (0);
-}
-
-static int
-ses_get_objstat(ses_softc_t *ssc, ses_objstat *obp, int slpflag)
-{
- int i = (int)obp->obj_id;
-
- if (ssc->ses_objmap[i].svalid == 0) {
- SesComStat ComStat;
- int err = ses_getputstat(ssc, i, &ComStat, slpflag, 1);
- if (err)
- return (err);
- ssc->ses_objmap[i].encstat[0] = ComStat.comstatus;
- ssc->ses_objmap[i].encstat[1] = ComStat.comstat[0];
- ssc->ses_objmap[i].encstat[2] = ComStat.comstat[1];
- ssc->ses_objmap[i].encstat[3] = ComStat.comstat[2];
- ssc->ses_objmap[i].svalid = 1;
- }
- obp->cstat[0] = ssc->ses_objmap[i].encstat[0];
- obp->cstat[1] = ssc->ses_objmap[i].encstat[1];
- obp->cstat[2] = ssc->ses_objmap[i].encstat[2];
- obp->cstat[3] = ssc->ses_objmap[i].encstat[3];
- return (0);
-}
-
-static int
-ses_set_objstat(ses_softc_t *ssc, ses_objstat *obp, int slpflag)
-{
- SesComStat ComStat;
- int err;
- /*
- * If this is clear, we don't do diddly.
- */
- if ((obp->cstat[0] & SESCTL_CSEL) == 0) {
- return (0);
- }
- ComStat.comstatus = obp->cstat[0];
- ComStat.comstat[0] = obp->cstat[1];
- ComStat.comstat[1] = obp->cstat[2];
- ComStat.comstat[2] = obp->cstat[3];
- err = ses_getputstat(ssc, (int)obp->obj_id, &ComStat, slpflag, 0);
- ssc->ses_objmap[(int)obp->obj_id].svalid = 0;
- return (err);
-}
-
-static int
-ses_getconfig(ses_softc_t *ssc)
-{
- struct sscfg *cc;
- SesCfgHdr cf;
- SesEncHdr hd;
- SesEncDesc *cdp;
- SesThdr thdr;
- int err, amt, i, nobj, ntype, maxima;
- char storage[CFLEN], *sdata;
- static char cdb[6] = {
- RECEIVE_DIAGNOSTIC, 0x1, SesConfigPage, SCSZ >> 8, SCSZ & 0xff, 0
- };
-
- cc = ssc->ses_private;
- if (cc == NULL) {
- return (ENXIO);
- }
-
- sdata = SES_MALLOC(SCSZ);
- if (sdata == NULL)
- return (ENOMEM);
-
- amt = SCSZ;
- err = ses_runcmd(ssc, cdb, 6, sdata, &amt);
- if (err) {
- SES_FREE(sdata, SCSZ);
- return (err);
- }
- amt = SCSZ - amt;
-
- if (ses_cfghdr((uint8_t *) sdata, amt, &cf)) {
- SES_LOG(ssc, "Unable to parse SES Config Header\n");
- SES_FREE(sdata, SCSZ);
- return (EIO);
- }
- if (amt < SES_ENCHDR_MINLEN) {
- SES_LOG(ssc, "runt enclosure length (%d)\n", amt);
- SES_FREE(sdata, SCSZ);
- return (EIO);
- }
-
- SES_VLOG(ssc, "GenCode %x %d Subenclosures\n", cf.GenCode, cf.Nsubenc);
-
- /*
- * Now waltz through all the subenclosures toting up the
- * number of types available in each. For this, we only
- * really need the enclosure header. However, we get the
- * enclosure descriptor for debug purposes, as well
- * as self-consistency checking purposes.
- */
-
- maxima = cf.Nsubenc + 1;
- cdp = (SesEncDesc *) storage;
- for (ntype = i = 0; i < maxima; i++) {
- MEMZERO((caddr_t)cdp, sizeof (*cdp));
- if (ses_enchdr((uint8_t *) sdata, amt, i, &hd)) {
- SES_LOG(ssc, "Cannot Extract Enclosure Header %d\n", i);
- SES_FREE(sdata, SCSZ);
- return (EIO);
- }
- SES_VLOG(ssc, " SubEnclosure ID %d, %d Types With this ID, En"
- "closure Length %d\n", hd.Subencid, hd.Ntypes, hd.VEnclen);
-
- if (ses_encdesc((uint8_t *)sdata, amt, i, cdp)) {
- SES_LOG(ssc, "Can't get Enclosure Descriptor %d\n", i);
- SES_FREE(sdata, SCSZ);
- return (EIO);
- }
- SES_VLOG(ssc, " WWN: %02x%02x%02x%02x%02x%02x%02x%02x\n",
- cdp->encWWN[0], cdp->encWWN[1], cdp->encWWN[2],
- cdp->encWWN[3], cdp->encWWN[4], cdp->encWWN[5],
- cdp->encWWN[6], cdp->encWWN[7]);
- ntype += hd.Ntypes;
- }
-
- /*
- * Now waltz through all the types that are available, getting
- * the type header so we can start adding up the number of
- * objects available.
- */
- for (nobj = i = 0; i < ntype; i++) {
- if (ses_getthdr((uint8_t *)sdata, amt, i, &thdr)) {
- SES_LOG(ssc, "Can't get Enclosure Type Header %d\n", i);
- SES_FREE(sdata, SCSZ);
- return (EIO);
- }
- SES_LOG(ssc, " Type Desc[%d]: Type 0x%x, MaxElt %d, In Subenc "
- "%d, Text Length %d\n", i, thdr.enc_type, thdr.enc_maxelt,
- thdr.enc_subenc, thdr.enc_tlen);
- nobj += thdr.enc_maxelt;
- }
-
-
- /*
- * Now allocate the object array and type map.
- */
-
- ssc->ses_objmap = SES_MALLOC(nobj * sizeof (encobj));
- cc->ses_typidx = SES_MALLOC(nobj * sizeof (struct typidx));
- cc->ses_eltmap = SES_MALLOC(ntype);
-
- if (ssc->ses_objmap == NULL || cc->ses_typidx == NULL ||
- cc->ses_eltmap == NULL) {
- if (ssc->ses_objmap) {
- SES_FREE(ssc->ses_objmap, (nobj * sizeof (encobj)));
- ssc->ses_objmap = NULL;
- }
- if (cc->ses_typidx) {
- SES_FREE(cc->ses_typidx,
- (nobj * sizeof (struct typidx)));
- cc->ses_typidx = NULL;
- }
- if (cc->ses_eltmap) {
- SES_FREE(cc->ses_eltmap, ntype);
- cc->ses_eltmap = NULL;
- }
- SES_FREE(sdata, SCSZ);
- return (ENOMEM);
- }
- MEMZERO(ssc->ses_objmap, nobj * sizeof (encobj));
- MEMZERO(cc->ses_typidx, nobj * sizeof (struct typidx));
- MEMZERO(cc->ses_eltmap, ntype);
- cc->ses_ntypes = (uint8_t) ntype;
- ssc->ses_nobjects = nobj;
-
- /*
- * Now waltz through the # of types again to fill in the types
- * (and subenclosure ids) of the allocated objects.
- */
- nobj = 0;
- for (i = 0; i < ntype; i++) {
- int j;
- if (ses_getthdr((uint8_t *)sdata, amt, i, &thdr)) {
- continue;
- }
- cc->ses_eltmap[i] = thdr.enc_maxelt;
- for (j = 0; j < thdr.enc_maxelt; j++) {
- cc->ses_typidx[nobj].ses_tidx = i;
- cc->ses_typidx[nobj].ses_oidx = j;
- ssc->ses_objmap[nobj].subenclosure = thdr.enc_subenc;
- ssc->ses_objmap[nobj++].enctype = thdr.enc_type;
- }
- }
- SES_FREE(sdata, SCSZ);
- return (0);
-}
-
-static int
-ses_getputstat(ses_softc_t *ssc, int objid, SesComStat *sp, int slp, int in)
-{
- struct sscfg *cc;
- int err, amt, bufsiz, tidx, oidx;
- char cdb[6], *sdata;
-
- cc = ssc->ses_private;
- if (cc == NULL) {
- return (ENXIO);
- }
-
- /*
- * If we're just getting overall enclosure status,
- * we only need 2 bytes of data storage.
- *
- * If we're getting anything else, we know how much
- * storage we need by noting that starting at offset
- * 8 in returned data, all object status bytes are 4
- * bytes long, and are stored in chunks of types(M)
- * and nth+1 instances of type M.
- */
- if (objid == -1) {
- bufsiz = 2;
- } else {
- bufsiz = (ssc->ses_nobjects * 4) + (cc->ses_ntypes * 4) + 8;
- }
- sdata = SES_MALLOC(bufsiz);
- if (sdata == NULL)
- return (ENOMEM);
-
- cdb[0] = RECEIVE_DIAGNOSTIC;
- cdb[1] = 1;
- cdb[2] = SesStatusPage;
- cdb[3] = bufsiz >> 8;
- cdb[4] = bufsiz & 0xff;
- cdb[5] = 0;
- amt = bufsiz;
- err = ses_runcmd(ssc, cdb, 6, sdata, &amt);
- if (err) {
- SES_FREE(sdata, bufsiz);
- return (err);
- }
- amt = bufsiz - amt;
-
- if (objid == -1) {
- tidx = -1;
- oidx = -1;
- } else {
- tidx = cc->ses_typidx[objid].ses_tidx;
- oidx = cc->ses_typidx[objid].ses_oidx;
- }
- if (in) {
- if (ses_decode(sdata, amt, cc->ses_eltmap, tidx, oidx, sp)) {
- err = ENODEV;
- }
- } else {
- if (ses_encode(sdata, amt, cc->ses_eltmap, tidx, oidx, sp)) {
- err = ENODEV;
- } else {
- cdb[0] = SEND_DIAGNOSTIC;
- cdb[1] = 0x10;
- cdb[2] = 0;
- cdb[3] = bufsiz >> 8;
- cdb[4] = bufsiz & 0xff;
- cdb[5] = 0;
- amt = -bufsiz;
- err = ses_runcmd(ssc, cdb, 6, sdata, &amt);
- }
- }
- SES_FREE(sdata, bufsiz);
- return (0);
-}
-
-
-/*
- * Routines to parse returned SES data structures.
- * Architecture and compiler independent.
- */
-
-static int
-ses_cfghdr(uint8_t *buffer, int buflen, SesCfgHdr *cfp)
-{
- if (buflen < SES_CFGHDR_MINLEN) {
- return (-1);
- }
- gget8(buffer, 1, cfp->Nsubenc);
- gget32(buffer, 4, cfp->GenCode);
- return (0);
-}
-
-static int
-ses_enchdr(uint8_t *buffer, int amt, uint8_t SubEncId, SesEncHdr *chp)
-{
- int s, off = 8;
- for (s = 0; s < SubEncId; s++) {
- if (off + 3 > amt)
- return (-1);
- off += buffer[off+3] + 4;
- }
- if (off + 3 > amt) {
- return (-1);
- }
- gget8(buffer, off+1, chp->Subencid);
- gget8(buffer, off+2, chp->Ntypes);
- gget8(buffer, off+3, chp->VEnclen);
- return (0);
-}
-
-static int
-ses_encdesc(uint8_t *buffer, int amt, uint8_t SubEncId, SesEncDesc *cdp)
-{
- int s, e, enclen, off = 8;
- for (s = 0; s < SubEncId; s++) {
- if (off + 3 > amt)
- return (-1);
- off += buffer[off+3] + 4;
- }
- if (off + 3 > amt) {
- return (-1);
- }
- gget8(buffer, off+3, enclen);
- off += 4;
- if (off >= amt)
- return (-1);
-
- e = off + enclen;
- if (e > amt) {
- e = amt;
- }
- MEMCPY(cdp, &buffer[off], e - off);
- return (0);
-}
-
-static int
-ses_getthdr(uint8_t *buffer, int amt, int nth, SesThdr *thp)
-{
- int s, off = 8;
-
- if (amt < SES_CFGHDR_MINLEN) {
- return (-1);
- }
- for (s = 0; s < buffer[1]; s++) {
- if (off + 3 > amt)
- return (-1);
- off += buffer[off+3] + 4;
- }
- if (off + 3 > amt) {
- return (-1);
- }
- off += buffer[off+3] + 4 + (nth * 4);
- if (amt < (off + 4))
- return (-1);
-
- gget8(buffer, off++, thp->enc_type);
- gget8(buffer, off++, thp->enc_maxelt);
- gget8(buffer, off++, thp->enc_subenc);
- gget8(buffer, off, thp->enc_tlen);
- return (0);
-}
-
-/*
- * This function needs a little explanation.
- *
- * The arguments are:
- *
- *
- * char *b, int amt
- *
- * These describes the raw input SES status data and length.
- *
- * uint8_t *ep
- *
- * This is a map of the number of types for each element type
- * in the enclosure.
- *
- * int elt
- *
- * This is the element type being sought. If elt is -1,
- * then overall enclosure status is being sought.
- *
- * int elm
- *
- * This is the ordinal Mth element of type elt being sought.
- *
- * SesComStat *sp
- *
- * This is the output area to store the status for
- * the Mth element of type Elt.
- */
-
-static int
-ses_decode(char *b, int amt, uint8_t *ep, int elt, int elm, SesComStat *sp)
-{
- int idx, i;
-
- /*
- * If it's overall enclosure status being sought, get that.
- * We need at least 2 bytes of status data to get that.
- */
- if (elt == -1) {
- if (amt < 2)
- return (-1);
- gget8(b, 1, sp->comstatus);
- sp->comstat[0] = 0;
- sp->comstat[1] = 0;
- sp->comstat[2] = 0;
- return (0);
- }
-
- /*
- * Check to make sure that the Mth element is legal for type Elt.
- */
-
- if (elm >= ep[elt])
- return (-1);
-
- /*
- * Starting at offset 8, start skipping over the storage
- * for the element types we're not interested in.
- */
- for (idx = 8, i = 0; i < elt; i++) {
- idx += ((ep[i] + 1) * 4);
- }
-
- /*
- * Skip over Overall status for this element type.
- */
- idx += 4;
-
- /*
- * And skip to the index for the Mth element that we're going for.
- */
- idx += (4 * elm);
-
- /*
- * Make sure we haven't overflowed the buffer.
- */
- if (idx+4 > amt)
- return (-1);
-
- /*
- * Retrieve the status.
- */
- gget8(b, idx++, sp->comstatus);
- gget8(b, idx++, sp->comstat[0]);
- gget8(b, idx++, sp->comstat[1]);
- gget8(b, idx++, sp->comstat[2]);
-#if 0
- PRINTF("Get Elt 0x%x Elm 0x%x (idx %d)\n", elt, elm, idx-4);
-#endif
- return (0);
-}
-
-/*
- * This is the mirror function to ses_decode, but we set the 'select'
- * bit for the object which we're interested in. All other objects,
- * after a status fetch, should have that bit off. Hmm. It'd be easy
- * enough to ensure this, so we will.
- */
-
-static int
-ses_encode(char *b, int amt, uint8_t *ep, int elt, int elm, SesComStat *sp)
-{
- int idx, i;
-
- /*
- * If it's overall enclosure status being sought, get that.
- * We need at least 2 bytes of status data to get that.
- */
- if (elt == -1) {
- if (amt < 2)
- return (-1);
- i = 0;
- sset8(b, i, 0);
- sset8(b, i, sp->comstatus & 0xf);
-#if 0
- PRINTF("set EncStat %x\n", sp->comstatus);
-#endif
- return (0);
- }
-
- /*
- * Check to make sure that the Mth element is legal for type Elt.
- */
-
- if (elm >= ep[elt])
- return (-1);
-
- /*
- * Starting at offset 8, start skipping over the storage
- * for the element types we're not interested in.
- */
- for (idx = 8, i = 0; i < elt; i++) {
- idx += ((ep[i] + 1) * 4);
- }
-
- /*
- * Skip over Overall status for this element type.
- */
- idx += 4;
-
- /*
- * And skip to the index for the Mth element that we're going for.
- */
- idx += (4 * elm);
-
- /*
- * Make sure we haven't overflowed the buffer.
- */
- if (idx+4 > amt)
- return (-1);
-
- /*
- * Set the status.
- */
- sset8(b, idx, sp->comstatus);
- sset8(b, idx, sp->comstat[0]);
- sset8(b, idx, sp->comstat[1]);
- sset8(b, idx, sp->comstat[2]);
- idx -= 4;
-
-#if 0
- PRINTF("Set Elt 0x%x Elm 0x%x (idx %d) with %x %x %x %x\n",
- elt, elm, idx, sp->comstatus, sp->comstat[0],
- sp->comstat[1], sp->comstat[2]);
-#endif
-
- /*
- * Now make sure all other 'Select' bits are off.
- */
- for (i = 8; i < amt; i += 4) {
- if (i != idx)
- b[i] &= ~0x80;
- }
- /*
- * And make sure the INVOP bit is clear.
- */
- b[2] &= ~0x10;
-
- return (0);
-}
-
-/*
- * SAF-TE Type Device Emulation
- */
-
-static int safte_getconfig(ses_softc_t *);
-static int safte_rdstat(ses_softc_t *, int);
-static int set_objstat_sel(ses_softc_t *, ses_objstat *, int);
-static int wrbuf16(ses_softc_t *, uint8_t, uint8_t, uint8_t, uint8_t, int);
-static void wrslot_stat(ses_softc_t *, int);
-static int perf_slotop(ses_softc_t *, uint8_t, uint8_t, int);
-
-#define ALL_ENC_STAT (SES_ENCSTAT_CRITICAL | SES_ENCSTAT_UNRECOV | \
- SES_ENCSTAT_NONCRITICAL | SES_ENCSTAT_INFO)
-/*
- * SAF-TE specific defines- Mandatory ones only...
- */
-
-/*
- * READ BUFFER ('get' commands) IDs- placed in offset 2 of cdb
- */
-#define SAFTE_RD_RDCFG 0x00 /* read enclosure configuration */
-#define SAFTE_RD_RDESTS 0x01 /* read enclosure status */
-#define SAFTE_RD_RDDSTS 0x04 /* read drive slot status */
-
-/*
- * WRITE BUFFER ('set' commands) IDs- placed in offset 0 of databuf
- */
-#define SAFTE_WT_DSTAT 0x10 /* write device slot status */
-#define SAFTE_WT_SLTOP 0x12 /* perform slot operation */
-#define SAFTE_WT_FANSPD 0x13 /* set fan speed */
-#define SAFTE_WT_ACTPWS 0x14 /* turn on/off power supply */
-#define SAFTE_WT_GLOBAL 0x15 /* send global command */
-
-
-#define SAFT_SCRATCH 64
-#define NPSEUDO_THERM 16
-#define NPSEUDO_ALARM 1
-struct scfg {
- /*
- * Cached Configuration
- */
- uint8_t Nfans; /* Number of Fans */
- uint8_t Npwr; /* Number of Power Supplies */
- uint8_t Nslots; /* Number of Device Slots */
- uint8_t DoorLock; /* Door Lock Installed */
- uint8_t Ntherm; /* Number of Temperature Sensors */
- uint8_t Nspkrs; /* Number of Speakers */
- uint8_t Nalarm; /* Number of Alarms (at least one) */
- /*
- * Cached Flag Bytes for Global Status
- */
- uint8_t flag1;
- uint8_t flag2;
- /*
- * What object index ID is where various slots start.
- */
- uint8_t pwroff;
- uint8_t slotoff;
-#define SAFT_ALARM_OFFSET(cc) (cc)->slotoff - 1
-};
-
-#define SAFT_FLG1_ALARM 0x1
-#define SAFT_FLG1_GLOBFAIL 0x2
-#define SAFT_FLG1_GLOBWARN 0x4
-#define SAFT_FLG1_ENCPWROFF 0x8
-#define SAFT_FLG1_ENCFANFAIL 0x10
-#define SAFT_FLG1_ENCPWRFAIL 0x20
-#define SAFT_FLG1_ENCDRVFAIL 0x40
-#define SAFT_FLG1_ENCDRVWARN 0x80
-
-#define SAFT_FLG2_LOCKDOOR 0x4
-#define SAFT_PRIVATE sizeof (struct scfg)
-
-static char *safte_2little = "Too Little Data Returned (%d) at line %d\n";
-#define SAFT_BAIL(r, x, k, l) \
- if ((r) >= (x)) { \
- SES_LOG(ssc, safte_2little, x, __LINE__);\
- SES_FREE((k), (l)); \
- return (EIO); \
- }
-
-
-static int
-safte_softc_init(ses_softc_t *ssc, int doinit)
-{
- int err, i, r;
- struct scfg *cc;
-
- if (doinit == 0) {
- if (ssc->ses_nobjects) {
- if (ssc->ses_objmap) {
- SES_FREE(ssc->ses_objmap,
- ssc->ses_nobjects * sizeof (encobj));
- ssc->ses_objmap = NULL;
- }
- ssc->ses_nobjects = 0;
- }
- if (ssc->ses_private) {
- SES_FREE(ssc->ses_private, SAFT_PRIVATE);
- ssc->ses_private = NULL;
- }
- return (0);
- }
-
- if (ssc->ses_private == NULL) {
- ssc->ses_private = SES_MALLOC(SAFT_PRIVATE);
- if (ssc->ses_private == NULL) {
- return (ENOMEM);
- }
- MEMZERO(ssc->ses_private, SAFT_PRIVATE);
- }
-
- ssc->ses_nobjects = 0;
- ssc->ses_encstat = 0;
-
- if ((err = safte_getconfig(ssc)) != 0) {
- return (err);
- }
-
- /*
- * The number of objects here, as well as that reported by the
- * READ_BUFFER/GET_CONFIG call, are the over-temperature flags (15)
- * that get reported during READ_BUFFER/READ_ENC_STATUS.
- */
- cc = ssc->ses_private;
- ssc->ses_nobjects = cc->Nfans + cc->Npwr + cc->Nslots + cc->DoorLock +
- cc->Ntherm + cc->Nspkrs + NPSEUDO_THERM + NPSEUDO_ALARM;
- ssc->ses_objmap = (encobj *)
- SES_MALLOC(ssc->ses_nobjects * sizeof (encobj));
- if (ssc->ses_objmap == NULL) {
- return (ENOMEM);
- }
- MEMZERO(ssc->ses_objmap, ssc->ses_nobjects * sizeof (encobj));
-
- r = 0;
- /*
- * Note that this is all arranged for the convenience
- * in later fetches of status.
- */
- for (i = 0; i < cc->Nfans; i++)
- ssc->ses_objmap[r++].enctype = SESTYP_FAN;
- cc->pwroff = (uint8_t) r;
- for (i = 0; i < cc->Npwr; i++)
- ssc->ses_objmap[r++].enctype = SESTYP_POWER;
- for (i = 0; i < cc->DoorLock; i++)
- ssc->ses_objmap[r++].enctype = SESTYP_DOORLOCK;
- for (i = 0; i < cc->Nspkrs; i++)
- ssc->ses_objmap[r++].enctype = SESTYP_ALARM;
- for (i = 0; i < cc->Ntherm; i++)
- ssc->ses_objmap[r++].enctype = SESTYP_THERM;
- for (i = 0; i < NPSEUDO_THERM; i++)
- ssc->ses_objmap[r++].enctype = SESTYP_THERM;
- ssc->ses_objmap[r++].enctype = SESTYP_ALARM;
- cc->slotoff = (uint8_t) r;
- for (i = 0; i < cc->Nslots; i++)
- ssc->ses_objmap[r++].enctype = SESTYP_DEVICE;
- return (0);
-}
-
-static int
-safte_init_enc(ses_softc_t *ssc)
-{
- int err;
- static char cdb0[6] = { SEND_DIAGNOSTIC };
-
- err = ses_runcmd(ssc, cdb0, 6, NULL, 0);
- if (err) {
- return (err);
- }
- DELAY(5000);
- err = wrbuf16(ssc, SAFTE_WT_GLOBAL, 0, 0, 0, 1);
- return (err);
-}
-
-static int
-safte_get_encstat(ses_softc_t *ssc, int slpflg)
-{
- return (safte_rdstat(ssc, slpflg));
-}
-
-static int
-safte_set_encstat(ses_softc_t *ssc, uint8_t encstat, int slpflg)
-{
- struct scfg *cc = ssc->ses_private;
- if (cc == NULL)
- return (0);
- /*
- * Since SAF-TE devices aren't necessarily sticky in terms
- * of state, make our soft copy of enclosure status 'sticky'-
- * that is, things set in enclosure status stay set (as implied
- * by conditions set in reading object status) until cleared.
- */
- ssc->ses_encstat &= ~ALL_ENC_STAT;
- ssc->ses_encstat |= (encstat & ALL_ENC_STAT);
- ssc->ses_encstat |= ENCI_SVALID;
- cc->flag1 &= ~(SAFT_FLG1_ALARM|SAFT_FLG1_GLOBFAIL|SAFT_FLG1_GLOBWARN);
- if ((encstat & (SES_ENCSTAT_CRITICAL|SES_ENCSTAT_UNRECOV)) != 0) {
- cc->flag1 |= SAFT_FLG1_ALARM|SAFT_FLG1_GLOBFAIL;
- } else if ((encstat & SES_ENCSTAT_NONCRITICAL) != 0) {
- cc->flag1 |= SAFT_FLG1_GLOBWARN;
- }
- return (wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1, cc->flag2, 0, slpflg));
-}
-
-static int
-safte_get_objstat(ses_softc_t *ssc, ses_objstat *obp, int slpflg)
-{
- int i = (int)obp->obj_id;
-
- if ((ssc->ses_encstat & ENCI_SVALID) == 0 ||
- (ssc->ses_objmap[i].svalid) == 0) {
- int err = safte_rdstat(ssc, slpflg);
- if (err)
- return (err);
- }
- obp->cstat[0] = ssc->ses_objmap[i].encstat[0];
- obp->cstat[1] = ssc->ses_objmap[i].encstat[1];
- obp->cstat[2] = ssc->ses_objmap[i].encstat[2];
- obp->cstat[3] = ssc->ses_objmap[i].encstat[3];
- return (0);
-}
-
-
-static int
-safte_set_objstat(ses_softc_t *ssc, ses_objstat *obp, int slp)
-{
- int idx, err;
- encobj *ep;
- struct scfg *cc;
-
-
- SES_DLOG(ssc, "safte_set_objstat(%d): %x %x %x %x\n",
- (int)obp->obj_id, obp->cstat[0], obp->cstat[1], obp->cstat[2],
- obp->cstat[3]);
-
- /*
- * If this is clear, we don't do diddly.
- */
- if ((obp->cstat[0] & SESCTL_CSEL) == 0) {
- return (0);
- }
-
- err = 0;
- /*
- * Check to see if the common bits are set and do them first.
- */
- if (obp->cstat[0] & ~SESCTL_CSEL) {
- err = set_objstat_sel(ssc, obp, slp);
- if (err)
- return (err);
- }
-
- cc = ssc->ses_private;
- if (cc == NULL)
- return (0);
-
- idx = (int)obp->obj_id;
- ep = &ssc->ses_objmap[idx];
-
- switch (ep->enctype) {
- case SESTYP_DEVICE:
- {
- uint8_t slotop = 0;
- /*
- * XXX: I should probably cache the previous state
- * XXX: of SESCTL_DEVOFF so that when it goes from
- * XXX: true to false I can then set PREPARE FOR OPERATION
- * XXX: flag in PERFORM SLOT OPERATION write buffer command.
- */
- if (obp->cstat[2] & (SESCTL_RQSINS|SESCTL_RQSRMV)) {
- slotop |= 0x2;
- }
- if (obp->cstat[2] & SESCTL_RQSID) {
- slotop |= 0x4;
- }
- err = perf_slotop(ssc, (uint8_t) idx - (uint8_t) cc->slotoff,
- slotop, slp);
- if (err)
- return (err);
- if (obp->cstat[3] & SESCTL_RQSFLT) {
- ep->priv |= 0x2;
- } else {
- ep->priv &= ~0x2;
- }
- if (ep->priv & 0xc6) {
- ep->priv &= ~0x1;
- } else {
- ep->priv |= 0x1; /* no errors */
- }
- wrslot_stat(ssc, slp);
- break;
- }
- case SESTYP_POWER:
- if (obp->cstat[3] & SESCTL_RQSTFAIL) {
- cc->flag1 |= SAFT_FLG1_ENCPWRFAIL;
- } else {
- cc->flag1 &= ~SAFT_FLG1_ENCPWRFAIL;
- }
- err = wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
- cc->flag2, 0, slp);
- if (err)
- return (err);
- if (obp->cstat[3] & SESCTL_RQSTON) {
- (void) wrbuf16(ssc, SAFTE_WT_ACTPWS,
- idx - cc->pwroff, 0, 0, slp);
- } else {
- (void) wrbuf16(ssc, SAFTE_WT_ACTPWS,
- idx - cc->pwroff, 0, 1, slp);
- }
- break;
- case SESTYP_FAN:
- if (obp->cstat[3] & SESCTL_RQSTFAIL) {
- cc->flag1 |= SAFT_FLG1_ENCFANFAIL;
- } else {
- cc->flag1 &= ~SAFT_FLG1_ENCFANFAIL;
- }
- err = wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
- cc->flag2, 0, slp);
- if (err)
- return (err);
- if (obp->cstat[3] & SESCTL_RQSTON) {
- uint8_t fsp;
- if ((obp->cstat[3] & 0x7) == 7) {
- fsp = 4;
- } else if ((obp->cstat[3] & 0x7) == 6) {
- fsp = 3;
- } else if ((obp->cstat[3] & 0x7) == 4) {
- fsp = 2;
- } else {
- fsp = 1;
- }
- (void) wrbuf16(ssc, SAFTE_WT_FANSPD, idx, fsp, 0, slp);
- } else {
- (void) wrbuf16(ssc, SAFTE_WT_FANSPD, idx, 0, 0, slp);
- }
- break;
- case SESTYP_DOORLOCK:
- if (obp->cstat[3] & 0x1) {
- cc->flag2 &= ~SAFT_FLG2_LOCKDOOR;
- } else {
- cc->flag2 |= SAFT_FLG2_LOCKDOOR;
- }
- (void) wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
- cc->flag2, 0, slp);
- break;
- case SESTYP_ALARM:
- /*
- * On all nonzero but the 'muted' bit, we turn on the alarm,
- */
- obp->cstat[3] &= ~0xa;
- if (obp->cstat[3] & 0x40) {
- cc->flag2 &= ~SAFT_FLG1_ALARM;
- } else if (obp->cstat[3] != 0) {
- cc->flag2 |= SAFT_FLG1_ALARM;
- } else {
- cc->flag2 &= ~SAFT_FLG1_ALARM;
- }
- ep->priv = obp->cstat[3];
- (void) wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
- cc->flag2, 0, slp);
- break;
- default:
- break;
- }
- ep->svalid = 0;
- return (0);
-}
-
-static int
-safte_getconfig(ses_softc_t *ssc)
-{
- struct scfg *cfg;
- int err, amt;
- char *sdata;
- static char cdb[10] =
- { READ_BUFFER, 1, SAFTE_RD_RDCFG, 0, 0, 0, 0, 0, SAFT_SCRATCH, 0 };
-
- cfg = ssc->ses_private;
- if (cfg == NULL)
- return (ENXIO);
-
- sdata = SES_MALLOC(SAFT_SCRATCH);
- if (sdata == NULL)
- return (ENOMEM);
-
- amt = SAFT_SCRATCH;
- err = ses_runcmd(ssc, cdb, 10, sdata, &amt);
- if (err) {
- SES_FREE(sdata, SAFT_SCRATCH);
- return (err);
- }
- amt = SAFT_SCRATCH - amt;
- if (amt < 6) {
- SES_LOG(ssc, "too little data (%d) for configuration\n", amt);
- SES_FREE(sdata, SAFT_SCRATCH);
- return (EIO);
- }
- SES_VLOG(ssc, "Nfans %d Npwr %d Nslots %d Lck %d Ntherm %d Nspkrs %d\n",
- sdata[0], sdata[1], sdata[2], sdata[3], sdata[4], sdata[5]);
- cfg->Nfans = sdata[0];
- cfg->Npwr = sdata[1];
- cfg->Nslots = sdata[2];
- cfg->DoorLock = sdata[3];
- cfg->Ntherm = sdata[4];
- cfg->Nspkrs = sdata[5];
- cfg->Nalarm = NPSEUDO_ALARM;
- SES_FREE(sdata, SAFT_SCRATCH);
- return (0);
-}
-
-static int
-safte_rdstat(ses_softc_t *ssc, int slpflg)
-{
- int err, oid, r, i, hiwater, nitems, amt;
- uint16_t tempflags;
- size_t buflen;
- uint8_t status, oencstat;
- char *sdata, cdb[10];
- struct scfg *cc = ssc->ses_private;
-
-
- /*
- * The number of objects overstates things a bit,
- * both for the bogus 'thermometer' entries and
- * the drive status (which isn't read at the same
- * time as the enclosure status), but that's okay.
- */
- buflen = 4 * cc->Nslots;
- if (ssc->ses_nobjects > buflen)
- buflen = ssc->ses_nobjects;
- sdata = SES_MALLOC(buflen);
- if (sdata == NULL)
- return (ENOMEM);
-
- cdb[0] = READ_BUFFER;
- cdb[1] = 1;
- cdb[2] = SAFTE_RD_RDESTS;
- cdb[3] = 0;
- cdb[4] = 0;
- cdb[5] = 0;
- cdb[6] = 0;
- cdb[7] = (buflen >> 8) & 0xff;
- cdb[8] = buflen & 0xff;
- cdb[9] = 0;
- amt = buflen;
- err = ses_runcmd(ssc, cdb, 10, sdata, &amt);
- if (err) {
- SES_FREE(sdata, buflen);
- return (err);
- }
- hiwater = buflen - amt;
-
-
- /*
- * invalidate all status bits.
- */
- for (i = 0; i < ssc->ses_nobjects; i++)
- ssc->ses_objmap[i].svalid = 0;
- oencstat = ssc->ses_encstat & ALL_ENC_STAT;
- ssc->ses_encstat = 0;
-
-
- /*
- * Now parse returned buffer.
- * If we didn't get enough data back,
- * that's considered a fatal error.
- */
- oid = r = 0;
-
- for (nitems = i = 0; i < cc->Nfans; i++) {
- SAFT_BAIL(r, hiwater, sdata, buflen);
- /*
- * 0 = Fan Operational
- * 1 = Fan is malfunctioning
- * 2 = Fan is not present
- * 0x80 = Unknown or Not Reportable Status
- */
- ssc->ses_objmap[oid].encstat[1] = 0; /* resvd */
- ssc->ses_objmap[oid].encstat[2] = 0; /* resvd */
- switch ((int)(uint8_t)sdata[r]) {
- case 0:
- nitems++;
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_OK;
- /*
- * We could get fancier and cache
- * fan speeds that we have set, but
- * that isn't done now.
- */
- ssc->ses_objmap[oid].encstat[3] = 7;
- break;
-
- case 1:
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_CRIT;
- /*
- * FAIL and FAN STOPPED synthesized
- */
- ssc->ses_objmap[oid].encstat[3] = 0x40;
- /*
- * Enclosure marked with CRITICAL error
- * if only one fan or no thermometers,
- * else the NONCRITICAL error is set.
- */
- if (cc->Nfans == 1 || cc->Ntherm == 0)
- ssc->ses_encstat |= SES_ENCSTAT_CRITICAL;
- else
- ssc->ses_encstat |= SES_ENCSTAT_NONCRITICAL;
- break;
- case 2:
- ssc->ses_objmap[oid].encstat[0] =
- SES_OBJSTAT_NOTINSTALLED;
- ssc->ses_objmap[oid].encstat[3] = 0;
- /*
- * Enclosure marked with CRITICAL error
- * if only one fan or no thermometers,
- * else the NONCRITICAL error is set.
- */
- if (cc->Nfans == 1)
- ssc->ses_encstat |= SES_ENCSTAT_CRITICAL;
- else
- ssc->ses_encstat |= SES_ENCSTAT_NONCRITICAL;
- break;
- case 0x80:
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
- ssc->ses_objmap[oid].encstat[3] = 0;
- ssc->ses_encstat |= SES_ENCSTAT_INFO;
- break;
- default:
- ssc->ses_objmap[oid].encstat[0] =
- SES_OBJSTAT_UNSUPPORTED;
- SES_LOG(ssc, "Unknown fan%d status 0x%x\n", i,
- sdata[r] & 0xff);
- break;
- }
- ssc->ses_objmap[oid++].svalid = 1;
- r++;
- }
-
- /*
- * No matter how you cut it, no cooling elements when there
- * should be some there is critical.
- */
- if (cc->Nfans && nitems == 0) {
- ssc->ses_encstat |= SES_ENCSTAT_CRITICAL;
- }
-
-
- for (i = 0; i < cc->Npwr; i++) {
- SAFT_BAIL(r, hiwater, sdata, buflen);
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
- ssc->ses_objmap[oid].encstat[1] = 0; /* resvd */
- ssc->ses_objmap[oid].encstat[2] = 0; /* resvd */
- ssc->ses_objmap[oid].encstat[3] = 0x20; /* requested on */
- switch ((uint8_t)sdata[r]) {
- case 0x00: /* pws operational and on */
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_OK;
- break;
- case 0x01: /* pws operational and off */
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_OK;
- ssc->ses_objmap[oid].encstat[3] = 0x10;
- ssc->ses_encstat |= SES_ENCSTAT_INFO;
- break;
- case 0x10: /* pws is malfunctioning and commanded on */
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_CRIT;
- ssc->ses_objmap[oid].encstat[3] = 0x61;
- ssc->ses_encstat |= SES_ENCSTAT_NONCRITICAL;
- break;
-
- case 0x11: /* pws is malfunctioning and commanded off */
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
- ssc->ses_objmap[oid].encstat[3] = 0x51;
- ssc->ses_encstat |= SES_ENCSTAT_NONCRITICAL;
- break;
- case 0x20: /* pws is not present */
- ssc->ses_objmap[oid].encstat[0] =
- SES_OBJSTAT_NOTINSTALLED;
- ssc->ses_objmap[oid].encstat[3] = 0;
- ssc->ses_encstat |= SES_ENCSTAT_INFO;
- break;
- case 0x21: /* pws is present */
- /*
- * This is for enclosures that cannot tell whether the
- * device is on or malfunctioning, but know that it is
- * present. Just fall through.
- */
- /* FALLTHROUGH */
- case 0x80: /* Unknown or Not Reportable Status */
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
- ssc->ses_objmap[oid].encstat[3] = 0;
- ssc->ses_encstat |= SES_ENCSTAT_INFO;
- break;
- default:
- SES_LOG(ssc, "unknown power supply %d status (0x%x)\n",
- i, sdata[r] & 0xff);
- break;
- }
- ssc->ses_objmap[oid++].svalid = 1;
- r++;
- }
-
- /*
- * Skip over Slot SCSI IDs
- */
- r += cc->Nslots;
-
- /*
- * We always have doorlock status, no matter what,
- * but we only save the status if we have one.
- */
- SAFT_BAIL(r, hiwater, sdata, buflen);
- if (cc->DoorLock) {
- /*
- * 0 = Door Locked
- * 1 = Door Unlocked, or no Lock Installed
- * 0x80 = Unknown or Not Reportable Status
- */
- ssc->ses_objmap[oid].encstat[1] = 0;
- ssc->ses_objmap[oid].encstat[2] = 0;
- switch ((uint8_t)sdata[r]) {
- case 0:
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_OK;
- ssc->ses_objmap[oid].encstat[3] = 0;
- break;
- case 1:
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_OK;
- ssc->ses_objmap[oid].encstat[3] = 1;
- break;
- case 0x80:
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
- ssc->ses_objmap[oid].encstat[3] = 0;
- ssc->ses_encstat |= SES_ENCSTAT_INFO;
- break;
- default:
- ssc->ses_objmap[oid].encstat[0] =
- SES_OBJSTAT_UNSUPPORTED;
- SES_LOG(ssc, "unknown lock status 0x%x\n",
- sdata[r] & 0xff);
- break;
- }
- ssc->ses_objmap[oid++].svalid = 1;
- }
- r++;
-
- /*
- * We always have speaker status, no matter what,
- * but we only save the status if we have one.
- */
- SAFT_BAIL(r, hiwater, sdata, buflen);
- if (cc->Nspkrs) {
- ssc->ses_objmap[oid].encstat[1] = 0;
- ssc->ses_objmap[oid].encstat[2] = 0;
- if (sdata[r] == 1) {
- /*
- * We need to cache tone urgency indicators.
- * Someday.
- */
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
- ssc->ses_objmap[oid].encstat[3] = 0x8;
- ssc->ses_encstat |= SES_ENCSTAT_NONCRITICAL;
- } else if (sdata[r] == 0) {
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_OK;
- ssc->ses_objmap[oid].encstat[3] = 0;
- } else {
- ssc->ses_objmap[oid].encstat[0] =
- SES_OBJSTAT_UNSUPPORTED;
- ssc->ses_objmap[oid].encstat[3] = 0;
- SES_LOG(ssc, "unknown spkr status 0x%x\n",
- sdata[r] & 0xff);
- }
- ssc->ses_objmap[oid++].svalid = 1;
- }
- r++;
-
- for (i = 0; i < cc->Ntherm; i++) {
- SAFT_BAIL(r, hiwater, sdata, buflen);
- /*
- * Status is a range from -10 to 245 deg Celsius,
- * which we need to normalize to -20 to -245 according
- * to the latest SCSI spec, which makes little
- * sense since this would overflow an 8bit value.
- * Well, still, the base normalization is -20,
- * not -10, so we have to adjust.
- *
- * So what's over and under temperature?
- * Hmm- we'll state that 'normal' operating
- * is 10 to 40 deg Celsius.
- */
-
- /*
- * Actually.... All of the units that people out in the world
- * seem to have do not come even close to setting a value that
- * complies with this spec.
- *
- * The closest explanation I could find was in an
- * LSI-Logic manual, which seemed to indicate that
- * this value would be set by whatever the I2C code
- * would interpolate from the output of an LM75
- * temperature sensor.
- *
- * This means that it is impossible to use the actual
- * numeric value to predict anything. But we don't want
- * to lose the value. So, we'll propagate the *uncorrected*
- * value and set SES_OBJSTAT_NOTAVAIL. We'll depend on the
- * temperature flags for warnings.
- */
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_NOTAVAIL;
- ssc->ses_objmap[oid].encstat[1] = 0;
- ssc->ses_objmap[oid].encstat[2] = sdata[r];
- ssc->ses_objmap[oid].encstat[3] = 0;
- ssc->ses_objmap[oid++].svalid = 1;
- r++;
- }
-
- /*
- * Now, for "pseudo" thermometers, we have two bytes
- * of information in enclosure status- 16 bits. Actually,
- * the MSB is a single TEMP ALERT flag indicating whether
- * any other bits are set, but, thanks to fuzzy thinking,
- * in the SAF-TE spec, this can also be set even if no
- * other bits are set, thus making this really another
- * binary temperature sensor.
- */
-
- SAFT_BAIL(r, hiwater, sdata, buflen);
- tempflags = sdata[r++];
- SAFT_BAIL(r, hiwater, sdata, buflen);
- tempflags |= (tempflags << 8) | sdata[r++];
-
- for (i = 0; i < NPSEUDO_THERM; i++) {
- ssc->ses_objmap[oid].encstat[1] = 0;
- if (tempflags & (1 << (NPSEUDO_THERM - i - 1))) {
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_CRIT;
- ssc->ses_objmap[4].encstat[2] = 0xff;
- /*
- * Set 'over temperature' failure.
- */
- ssc->ses_objmap[oid].encstat[3] = 8;
- ssc->ses_encstat |= SES_ENCSTAT_CRITICAL;
- } else {
- /*
- * We used to say 'not available' and synthesize a
- * nominal 30 deg (C)- that was wrong. Actually,
- * Just say 'OK', and use the reserved value of
- * zero.
- */
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_OK;
- ssc->ses_objmap[oid].encstat[2] = 0;
- ssc->ses_objmap[oid].encstat[3] = 0;
- }
- ssc->ses_objmap[oid++].svalid = 1;
- }
-
- /*
- * Get alarm status.
- */
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_OK;
- ssc->ses_objmap[oid].encstat[3] = ssc->ses_objmap[oid].priv;
- ssc->ses_objmap[oid++].svalid = 1;
-
- /*
- * Now get drive slot status
- */
- cdb[2] = SAFTE_RD_RDDSTS;
- amt = buflen;
- err = ses_runcmd(ssc, cdb, 10, sdata, &amt);
- if (err) {
- SES_FREE(sdata, buflen);
- return (err);
- }
- hiwater = buflen - amt;
- for (r = i = 0; i < cc->Nslots; i++, r += 4) {
- SAFT_BAIL(r+3, hiwater, sdata, buflen);
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED;
- ssc->ses_objmap[oid].encstat[1] = (uint8_t) i;
- ssc->ses_objmap[oid].encstat[2] = 0;
- ssc->ses_objmap[oid].encstat[3] = 0;
- status = sdata[r+3];
- if ((status & 0x1) == 0) { /* no device */
- ssc->ses_objmap[oid].encstat[0] =
- SES_OBJSTAT_NOTINSTALLED;
- } else {
- ssc->ses_objmap[oid].encstat[0] = SES_OBJSTAT_OK;
- }
- if (status & 0x2) {
- ssc->ses_objmap[oid].encstat[2] = 0x8;
- }
- if ((status & 0x4) == 0) {
- ssc->ses_objmap[oid].encstat[3] = 0x10;
- }
- ssc->ses_objmap[oid++].svalid = 1;
- }
- /* see comment below about sticky enclosure status */
- ssc->ses_encstat |= ENCI_SVALID | oencstat;
- SES_FREE(sdata, buflen);
- return (0);
-}
-
-static int
-set_objstat_sel(ses_softc_t *ssc, ses_objstat *obp, int slp)
-{
- int idx;
- encobj *ep;
- struct scfg *cc = ssc->ses_private;
-
- if (cc == NULL)
- return (0);
-
- idx = (int)obp->obj_id;
- ep = &ssc->ses_objmap[idx];
-
- switch (ep->enctype) {
- case SESTYP_DEVICE:
- if (obp->cstat[0] & SESCTL_PRDFAIL) {
- ep->priv |= 0x40;
- }
- /* SESCTL_RSTSWAP has no correspondence in SAF-TE */
- if (obp->cstat[0] & SESCTL_DISABLE) {
- ep->priv |= 0x80;
- /*
- * Hmm. Try to set the 'No Drive' flag.
- * Maybe that will count as a 'disable'.
- */
- }
- if (ep->priv & 0xc6) {
- ep->priv &= ~0x1;
- } else {
- ep->priv |= 0x1; /* no errors */
- }
- wrslot_stat(ssc, slp);
- break;
- case SESTYP_POWER:
- /*
- * Okay- the only one that makes sense here is to
- * do the 'disable' for a power supply.
- */
- if (obp->cstat[0] & SESCTL_DISABLE) {
- (void) wrbuf16(ssc, SAFTE_WT_ACTPWS,
- idx - cc->pwroff, 0, 0, slp);
- }
- break;
- case SESTYP_FAN:
- /*
- * Okay- the only one that makes sense here is to
- * set fan speed to zero on disable.
- */
- if (obp->cstat[0] & SESCTL_DISABLE) {
- /* remember- fans are the first items, so idx works */
- (void) wrbuf16(ssc, SAFTE_WT_FANSPD, idx, 0, 0, slp);
- }
- break;
- case SESTYP_DOORLOCK:
- /*
- * Well, we can 'disable' the lock.
- */
- if (obp->cstat[0] & SESCTL_DISABLE) {
- cc->flag2 &= ~SAFT_FLG2_LOCKDOOR;
- (void) wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
- cc->flag2, 0, slp);
- }
- break;
- case SESTYP_ALARM:
- /*
- * Well, we can 'disable' the alarm.
- */
- if (obp->cstat[0] & SESCTL_DISABLE) {
- cc->flag2 &= ~SAFT_FLG1_ALARM;
- ep->priv |= 0x40; /* Muted */
- (void) wrbuf16(ssc, SAFTE_WT_GLOBAL, cc->flag1,
- cc->flag2, 0, slp);
- }
- break;
- default:
- break;
- }
- ep->svalid = 0;
- return (0);
-}
-
-/*
- * This function handles all of the 16 byte WRITE BUFFER commands.
- */
-static int
-wrbuf16(ses_softc_t *ssc, uint8_t op, uint8_t b1, uint8_t b2,
- uint8_t b3, int slp)
-{
- int err, amt;
- char *sdata;
- struct scfg *cc = ssc->ses_private;
- static char cdb[10] = { WRITE_BUFFER, 1, 0, 0, 0, 0, 0, 0, 16, 0 };
-
- if (cc == NULL)
- return (0);
-
- sdata = SES_MALLOC(16);
- if (sdata == NULL)
- return (ENOMEM);
-
- SES_DLOG(ssc, "saf_wrbuf16 %x %x %x %x\n", op, b1, b2, b3);
-
- sdata[0] = op;
- sdata[1] = b1;
- sdata[2] = b2;
- sdata[3] = b3;
- MEMZERO(&sdata[4], 12);
- amt = -16;
- err = ses_runcmd(ssc, cdb, 10, sdata, &amt);
- SES_FREE(sdata, 16);
- return (err);
-}
-
-/*
- * This function updates the status byte for the device slot described.
- *
- * Since this is an optional SAF-TE command, there's no point in
- * returning an error.
- */
-static void
-wrslot_stat(ses_softc_t *ssc, int slp)
-{
- int i, amt;
- encobj *ep;
- char cdb[10], *sdata;
- struct scfg *cc = ssc->ses_private;
-
- if (cc == NULL)
- return;
-
- SES_DLOG(ssc, "saf_wrslot\n");
- cdb[0] = WRITE_BUFFER;
- cdb[1] = 1;
- cdb[2] = 0;
- cdb[3] = 0;
- cdb[4] = 0;
- cdb[5] = 0;
- cdb[6] = 0;
- cdb[7] = 0;
- cdb[8] = cc->Nslots * 3 + 1;
- cdb[9] = 0;
-
- sdata = SES_MALLOC(cc->Nslots * 3 + 1);
- if (sdata == NULL)
- return;
- MEMZERO(sdata, cc->Nslots * 3 + 1);
-
- sdata[0] = SAFTE_WT_DSTAT;
- for (i = 0; i < cc->Nslots; i++) {
- ep = &ssc->ses_objmap[cc->slotoff + i];
- SES_DLOG(ssc, "saf_wrslot %d <- %x\n", i, ep->priv & 0xff);
- sdata[1 + (3 * i)] = ep->priv & 0xff;
- }
- amt = -(cc->Nslots * 3 + 1);
- (void) ses_runcmd(ssc, cdb, 10, sdata, &amt);
- SES_FREE(sdata, cc->Nslots * 3 + 1);
-}
-
-/*
- * This function issues the "PERFORM SLOT OPERATION" command.
- */
-static int
-perf_slotop(ses_softc_t *ssc, uint8_t slot, uint8_t opflag, int slp)
-{
- int err, amt;
- char *sdata;
- struct scfg *cc = ssc->ses_private;
- static char cdb[10] =
- { WRITE_BUFFER, 1, 0, 0, 0, 0, 0, 0, SAFT_SCRATCH, 0 };
-
- if (cc == NULL)
- return (0);
-
- sdata = SES_MALLOC(SAFT_SCRATCH);
- if (sdata == NULL)
- return (ENOMEM);
- MEMZERO(sdata, SAFT_SCRATCH);
-
- sdata[0] = SAFTE_WT_SLTOP;
- sdata[1] = slot;
- sdata[2] = opflag;
- SES_DLOG(ssc, "saf_slotop slot %d op %x\n", slot, opflag);
- amt = -SAFT_SCRATCH;
- err = ses_runcmd(ssc, cdb, 10, sdata, &amt);
- SES_FREE(sdata, SAFT_SCRATCH);
- return (err);
-}
diff -r 99650cb861f2 -r 58b18bd1429e head/sys/cam/scsi/scsi_ses.h
--- a/head/sys/cam/scsi/scsi_ses.h Wed Jul 25 16:42:35 2012 +0300
+++ b/head/sys/cam/scsi/scsi_ses.h Wed Jul 25 16:45:04 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/cam/scsi/scsi_ses.h 222339 2011-05-27 03:44:47Z mav $ */
+/* $FreeBSD: head/sys/cam/scsi/scsi_ses.h 238740 2012-07-24 13:32:49Z mav $ */
/*-
* Copyright (c) 2000 by Matthew Jacob
* All rights reserved.
@@ -29,107 +29,2131 @@
*
*/
-#define SESIOC ('s' - 040)
-#define SESIOC_GETNOBJ _IO(SESIOC, 1)
-#define SESIOC_GETOBJMAP _IO(SESIOC, 2)
-#define SESIOC_GETENCSTAT _IO(SESIOC, 3)
-#define SESIOC_SETENCSTAT _IO(SESIOC, 4)
-#define SESIOC_GETOBJSTAT _IO(SESIOC, 5)
-#define SESIOC_SETOBJSTAT _IO(SESIOC, 6)
-#define SESIOC_GETTEXT _IO(SESIOC, 7)
-#define SESIOC_INIT _IO(SESIOC, 8)
+#ifndef _SCSI_SES_H_
+#define _SCSI_SES_H_
+#include <cam/scsi/scsi_all.h>
+
+/*========================== Field Extraction Macros =========================*/
+#define MK_ENUM(S, F, SUFFIX) S ## _ ## F ## SUFFIX
+
+#define GEN_GETTER(LS, US, LF, UF) \
+static inline int \
+LS ## _get_ ## LF(struct LS *elem) { \
+ return ((elem->bytes[MK_ENUM(US,UF,_BYTE)] & MK_ENUM(US,UF,_MASK)) \
+ >> MK_ENUM(US,UF,_SHIFT)); \
+}
+
+#define GEN_SETTER(LS, US, LF, UF) \
+static inline void \
+LS ## _set_ ## LF(struct LS *elem, int val) { \
+ elem->bytes[MK_ENUM(US,UF,_BYTE)] &= ~MK_ENUM(US,UF,_MASK); \
+ elem->bytes[MK_ENUM(US,UF,_BYTE)] |= \
+ (val << MK_ENUM(US,UF,_SHIFT)) & MK_ENUM(US,UF,_MASK); \
+}
+
+#define GEN_HDR_GETTER(LS, US, LF, UF) \
+static inline int \
+LS ## _get_ ## LF(struct LS *page) { \
+ return ((page->hdr.page_specific_flags & MK_ENUM(US,UF,_MASK)) \
+ >> MK_ENUM(US,UF,_SHIFT)); \
+}
+
+#define GEN_HDR_SETTER(LS, US, LF, UF) \
+static inline void \
+LS ## _set_ ## LF(struct LS *page, int val) { \
+ page->hdr.page_specific_flags &= ~MK_ENUM(US,UF,_MASK); \
+ page->hdr.page_specific_flags |= \
+ (val << MK_ENUM(US,UF,_SHIFT)) & MK_ENUM(US,UF,_MASK); \
+}
+
+#define GEN_ACCESSORS(LS, US, LF, UF) \
+GEN_GETTER(LS, US, LF, UF) \
+GEN_SETTER(LS, US, LF, UF)
+
+#define GEN_HDR_ACCESSORS(LS, US, LF, UF) \
+GEN_HDR_GETTER(LS, US, LF, UF) \
+GEN_HDR_SETTER(LS, US, LF, UF)
+
+/*=============== Common SCSI ENC Diagnostic Page Structures ===============*/
+struct ses_page_hdr {
+ uint8_t page_code;
+ uint8_t page_specific_flags;
+ uint8_t length[2];
+ uint8_t gen_code[4];
+};
+
+static inline size_t
+ses_page_length(const struct ses_page_hdr *hdr)
+{
+ /*
+ * The page length as received only accounts for bytes that
+ * follow the length field, namely starting with the generation
+ * code field.
+ */
+ return (scsi_2btoul(hdr->length)
+ + offsetof(struct ses_page_hdr, gen_code));
+}
+
+/*============= SCSI ENC Configuration Diagnostic Page Structures ============*/
+struct ses_enc_desc {
+ uint8_t byte0;
+ /*
+ * reserved0 : 1,
+ * rel_id : 3, relative enclosure process id
+ * reserved1 : 1,
+ * num_procs : 3; number of enclosure procesenc
+ */
+ uint8_t subenc_id; /* Sub-enclosure Identifier */
+ uint8_t num_types; /* # of supported types */
+ uint8_t length; /* Enclosure Descriptor Length */
+ uint8_t logical_id[8]; /* formerly wwn */
+ uint8_t vendor_id[8];
+ uint8_t product_id[16];
+ uint8_t product_rev[4];
+ uint8_t vendor_bytes[];
+};
+
+static inline uint8_t *
+ses_enc_desc_last_byte(struct ses_enc_desc *encdesc)
+{
+ return (&encdesc->length + encdesc->length);
+}
+
+static inline struct ses_enc_desc *
+ses_enc_desc_next(struct ses_enc_desc *encdesc)
+{
+ return ((struct ses_enc_desc *)(ses_enc_desc_last_byte(encdesc) + 1));
+}
+
+static inline int
+ses_enc_desc_is_complete(struct ses_enc_desc *encdesc, uint8_t *last_buf_byte)
+{
+ return (&encdesc->length <= last_buf_byte
+ && ses_enc_desc_last_byte(encdesc) <= last_buf_byte);
+}
+
+struct ses_elm_type_desc {
+ uint8_t etype_elm_type; /* type of element */
+ uint8_t etype_maxelt; /* maximum supported */
+ uint8_t etype_subenc; /* in sub-enclosure #n */
+ uint8_t etype_txt_len; /* Type Descriptor Text Length */
+};
+
+struct ses_cfg_page {
+ struct ses_page_hdr hdr;
+ struct ses_enc_desc subencs[];
+ /* type descriptors */
+ /* type text */
+};
+
+static inline int
+ses_cfg_page_get_num_subenc(struct ses_cfg_page *page)
+{
+ return (page->hdr.page_specific_flags + 1);
+}
+
+
+/*================ SCSI SES Control Diagnostic Page Structures ==============*/
+struct ses_ctrl_common {
+ uint8_t bytes[1];
+};
+
+enum ses_ctrl_common_field_data {
+ SES_CTRL_COMMON_SELECT_BYTE = 0,
+ SES_CTRL_COMMON_SELECT_MASK = 0x80,
+ SES_CTRL_COMMON_SELECT_SHIFT = 7,
+
+ SES_CTRL_COMMON_PRDFAIL_BYTE = 0,
+ SES_CTRL_COMMON_PRDFAIL_MASK = 0x40,
+ SES_CTRL_COMMON_PRDFAIL_SHIFT = 6,
+
+ SES_CTRL_COMMON_DISABLE_BYTE = 0,
+ SES_CTRL_COMMON_DISABLE_MASK = 0x20,
+ SES_CTRL_COMMON_DISABLE_SHIFT = 5,
+
+ SES_CTRL_COMMON_RST_SWAP_BYTE = 0,
+ SES_CTRL_COMMON_RST_SWAP_MASK = 0x10,
+ SES_CTRL_COMMON_RST_SWAP_SHIFT = 4
+};
+
+#define GEN_SES_CTRL_COMMON_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_common, SES_CTRL_COMMON, LCASE, UCASE)
+GEN_SES_CTRL_COMMON_ACCESSORS(select, SELECT)
+GEN_SES_CTRL_COMMON_ACCESSORS(prdfail, PRDFAIL)
+GEN_SES_CTRL_COMMON_ACCESSORS(disable, DISABLE)
+GEN_SES_CTRL_COMMON_ACCESSORS(rst_swap, RST_SWAP)
+#undef GEN_SES_CTRL_COMMON_ACCESSORS
+
+/*------------------------ Device Slot Control Element ----------------------*/
+struct ses_ctrl_dev_slot {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_dev_slot_field_data {
+ SES_CTRL_DEV_SLOT_RQST_ACTIVE_BYTE = 1,
+ SES_CTRL_DEV_SLOT_RQST_ACTIVE_MASK = 0x80,
+ SES_CTRL_DEV_SLOT_RQST_ACTIVE_SHIFT = 7,
+
+ SES_CTRL_DEV_SLOT_DO_NOT_REMOVE_BYTE = 1,
+ SES_CTRL_DEV_SLOT_DO_NOT_REMOVE_MASK = 0x40,
+ SES_CTRL_DEV_SLOT_DO_NOT_REMOVE_SHIFT = 6,
+
+ SES_CTRL_DEV_SLOT_RQST_MISSING_BYTE = 1,
+ SES_CTRL_DEV_SLOT_RQST_MISSING_MASK = 0x10,
+ SES_CTRL_DEV_SLOT_RQST_MISSING_SHIFT = 4,
+
+ SES_CTRL_DEV_SLOT_RQST_INSERT_BYTE = 1,
+ SES_CTRL_DEV_SLOT_RQST_INSERT_MASK = 0x08,
+ SES_CTRL_DEV_SLOT_RQST_INSERT_SHIFT = 3,
+
+ SES_CTRL_DEV_SLOT_RQST_REMOVE_BYTE = 1,
+ SES_CTRL_DEV_SLOT_RQST_REMOVE_MASK = 0x04,
+ SES_CTRL_DEV_SLOT_RQST_REMOVE_SHIFT = 2,
+
+ SES_CTRL_DEV_SLOT_RQST_IDENT_BYTE = 1,
+ SES_CTRL_DEV_SLOT_RQST_IDENT_MASK = 0x02,
+ SES_CTRL_DEV_SLOT_RQST_IDENT_SHIFT = 1,
+
+ SES_CTRL_DEV_SLOT_RQST_FAULT_BYTE = 2,
+ SES_CTRL_DEV_SLOT_RQST_FAULT_MASK = 0x20,
+ SES_CTRL_DEV_SLOT_RQST_FAULT_SHIFT = 5,
+
+ SES_CTRL_DEV_SLOT_DEVICE_OFF_BYTE = 2,
+ SES_CTRL_DEV_SLOT_DEVICE_OFF_MASK = 0x10,
+ SES_CTRL_DEV_SLOT_DEVICE_OFF_SHIFT = 4,
+
+ SES_CTRL_DEV_SLOT_ENABLE_BYP_A_BYTE = 2,
+ SES_CTRL_DEV_SLOT_ENABLE_BYP_A_MASK = 0x08,
+ SES_CTRL_DEV_SLOT_ENABLE_BYP_A_SHIFT = 3,
+
+ SES_CTRL_DEV_SLOT_ENABLE_BYP_B_BYTE = 2,
+ SES_CTRL_DEV_SLOT_ENABLE_BYP_B_MASK = 0x04,
+ SES_CTRL_DEV_SLOT_ENABLE_BYP_B_SHIFT = 2
+};
+#define GEN_SES_CTRL_DEV_SLOT_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_dev_slot, SES_CTRL_DEV_SLOT, LCASE, UCASE)
+
+GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_active, RQST_ACTIVE)
+GEN_SES_CTRL_DEV_SLOT_ACCESSORS(do_not_remove, DO_NOT_REMOVE)
+GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_missing, RQST_MISSING)
+GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_insert, RQST_INSERT)
+GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_remove, RQST_REMOVE)
+GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_DEV_SLOT_ACCESSORS(rqst_fault, RQST_FAULT)
+GEN_SES_CTRL_DEV_SLOT_ACCESSORS(device_off, DEVICE_OFF)
+GEN_SES_CTRL_DEV_SLOT_ACCESSORS(enable_byp_a, ENABLE_BYP_A)
+GEN_SES_CTRL_DEV_SLOT_ACCESSORS(enable_byp_b, ENABLE_BYP_B)
+#undef GEN_SES_CTRL_DEV_SLOT_ACCESSORS
+
+/*--------------------- Array Device Slot Control Element --------------------*/
+struct ses_ctrl_array_dev_slot {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_array_dev_slot_field_data {
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_OK_BYTE = 0,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_OK_MASK = 0x80,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_OK_SHIFT = 7,
+
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_RSVD_DEVICE_BYTE = 0,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_RSVD_DEVICE_MASK = 0x40,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_RSVD_DEVICE_SHIFT = 6,
+
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_HOT_SPARE_BYTE = 0,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_HOT_SPARE_MASK = 0x20,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_HOT_SPARE_SHIFT = 5,
+
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_CONS_CHECK_BYTE = 0,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_CONS_CHECK_MASK = 0x10,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_CONS_CHECK_SHIFT = 4,
+
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_CRIT_ARRAY_BYTE = 0,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_CRIT_ARRAY_MASK = 0x08,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_CRIT_ARRAY_SHIFT = 3,
+
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_FAILED_ARRAY_BYTE = 0,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_FAILED_ARRAY_MASK = 0x04,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_IN_FAILED_ARRAY_SHIFT = 2,
+
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_BYTE = 0,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_MASK = 0x02,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_SHIFT = 1,
+
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_ABORT_BYTE = 0,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_ABORT_MASK = 0x01,
+ SES_CTRL_ARRAY_DEV_SLOT_RQST_REBUILD_REMAP_ABORT_SHIFT = 0
+
+ /*
+ * The remaining fields are identical to the device
+ * slot element type. Access them through the device slot
+ * element type and its accessors.
+ */
+};
+#define GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_array_dev_slot, SES_CTRL_ARRAY_DEV_SLOT, \
+ LCASE, UCASE)
+GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_ok, RQST_OK)
+GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_rsvd_device, RQST_RSVD_DEVICE)
+GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_hot_spare, RQST_HOT_SPARE)
+GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_cons_check, RQST_CONS_CHECK)
+GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_in_crit_array, RQST_IN_CRIT_ARRAY)
+GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_in_failed_array,
+ RQST_IN_FAILED_ARRAY)
+GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_rebuild_remap, RQST_REBUILD_REMAP)
+GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS(rqst_rebuild_remap_abort,
+ RQST_REBUILD_REMAP_ABORT)
+#undef GEN_SES_CTRL_ARRAY_DEV_SLOT_ACCESSORS
+
+/*----------------------- Power Supply Control Element -----------------------*/
+struct ses_ctrl_power_supply {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_power_supply_field_data {
+ SES_CTRL_POWER_SUPPLY_RQST_IDENT_BYTE = 0,
+ SES_CTRL_POWER_SUPPLY_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_POWER_SUPPLY_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_POWER_SUPPLY_RQST_FAIL_BYTE = 2,
+ SES_CTRL_POWER_SUPPLY_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_POWER_SUPPLY_RQST_FAIL_SHIFT = 6,
+
+ SES_CTRL_POWER_SUPPLY_RQST_ON_BYTE = 2,
+ SES_CTRL_POWER_SUPPLY_RQST_ON_MASK = 0x20,
+ SES_CTRL_POWER_SUPPLY_RQST_ON_SHIFT = 5
+};
+
+#define GEN_SES_CTRL_POWER_SUPPLY_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_power_supply, SES_CTRL_POWER_SUPPLY, LCASE, UCASE)
+GEN_SES_CTRL_POWER_SUPPLY_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_POWER_SUPPLY_ACCESSORS(rqst_fail, RQST_FAIL)
+GEN_SES_CTRL_POWER_SUPPLY_ACCESSORS(rqst_on, RQST_ON)
+#undef GEN_SES_CTRL_POWER_SUPPLY_ACCESSORS
+
+/*-------------------------- Cooling Control Element -------------------------*/
+struct ses_ctrl_cooling {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_cooling_field_data {
+ SES_CTRL_COOLING_RQST_IDENT_BYTE = 0,
+ SES_CTRL_COOLING_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_COOLING_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_COOLING_RQST_FAIL_BYTE = 2,
+ SES_CTRL_COOLING_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_COOLING_RQST_FAIL_SHIFT = 6,
+
+ SES_CTRL_COOLING_RQST_ON_BYTE = 2,
+ SES_CTRL_COOLING_RQST_ON_MASK = 0x20,
+ SES_CTRL_COOLING_RQST_ON_SHIFT = 5,
+
+ SES_CTRL_COOLING_RQSTED_SPEED_CODE_BYTE = 2,
+ SES_CTRL_COOLING_RQSTED_SPEED_CODE_MASK = 0x07,
+ SES_CTRL_COOLING_RQSTED_SPEED_CODE_SHIFT = 2,
+ SES_CTRL_COOLING_RQSTED_SPEED_CODE_UNCHANGED = 0x00,
+ SES_CTRL_COOLING_RQSTED_SPEED_CODE_LOWEST = 0x01,
+ SES_CTRL_COOLING_RQSTED_SPEED_CODE_HIGHEST = 0x07
+};
+
+#define GEN_SES_CTRL_COOLING_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_cooling, SES_CTRL_COOLING, LCASE, UCASE)
+GEN_SES_CTRL_COOLING_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_COOLING_ACCESSORS(rqst_fail, RQST_FAIL)
+GEN_SES_CTRL_COOLING_ACCESSORS(rqst_on, RQST_ON)
+GEN_SES_CTRL_COOLING_ACCESSORS(rqsted_speed_code, RQSTED_SPEED_CODE)
+#undef GEN_SES_CTRL_COOLING_ACCESSORS
+
+/*-------------------- Temperature Sensor Control Element --------------------*/
+struct ses_ctrl_temp_sensor {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_temp_sensor_field_data {
+ SES_CTRL_TEMP_SENSOR_RQST_IDENT_BYTE = 0,
+ SES_CTRL_TEMP_SENSOR_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_TEMP_SENSOR_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_TEMP_SENSOR_RQST_FAIL_BYTE = 0,
+ SES_CTRL_TEMP_SENSOR_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_TEMP_SENSOR_RQST_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_CTRL_TEMP_SENSOR_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_temp_sensor, SES_CTRL_TEMP_SENSOR, LCASE, UCASE)
+GEN_SES_CTRL_TEMP_SENSOR_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_TEMP_SENSOR_ACCESSORS(rqst_fail, RQST_FAIL)
+#undef GEN_SES_CTRL_TEMP_SENSOR_ACCESSORS
+
+/*------------------------- Door Lock Control Element ------------------------*/
+struct ses_ctrl_door_lock {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_door_lock_field_data {
+ SES_CTRL_DOOR_LOCK_RQST_IDENT_BYTE = 0,
+ SES_CTRL_DOOR_LOCK_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_DOOR_LOCK_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_DOOR_LOCK_RQST_FAIL_BYTE = 0,
+ SES_CTRL_DOOR_LOCK_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_DOOR_LOCK_RQST_FAIL_SHIFT = 6,
+
+ SES_CTRL_DOOR_LOCK_UNLOCK_BYTE = 2,
+ SES_CTRL_DOOR_LOCK_UNLOCK_MASK = 0x01,
+ SES_CTRL_DOOR_LOCK_UNLOCK_SHIFT = 0
+};
+
+#define GEN_SES_CTRL_DOOR_LOCK_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_door_lock, SES_CTRL_DOOR_LOCK, LCASE, UCASE)
+GEN_SES_CTRL_DOOR_LOCK_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_DOOR_LOCK_ACCESSORS(rqst_fail, RQST_FAIL)
+GEN_SES_CTRL_DOOR_LOCK_ACCESSORS(unlock, UNLOCK)
+#undef GEN_SES_CTRL_DOOR_LOCK_ACCESSORS
+
+/*----------------------- Audible Alarm Control Element ----------------------*/
+struct ses_ctrl_audible_alarm {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_audible_alarm_field_data {
+ SES_CTRL_AUDIBLE_ALARM_RQST_IDENT_BYTE = 0,
+ SES_CTRL_AUDIBLE_ALARM_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_AUDIBLE_ALARM_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_AUDIBLE_ALARM_RQST_FAIL_BYTE = 0,
+ SES_CTRL_AUDIBLE_ALARM_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_AUDIBLE_ALARM_RQST_FAIL_SHIFT = 6,
+
+ SES_CTRL_AUDIBLE_ALARM_SET_MUTE_BYTE = 2,
+ SES_CTRL_AUDIBLE_ALARM_SET_MUTE_MASK = 0x40,
+ SES_CTRL_AUDIBLE_ALARM_SET_MUTE_SHIFT = 6,
+
+ SES_CTRL_AUDIBLE_ALARM_SET_REMIND_BYTE = 2,
+ SES_CTRL_AUDIBLE_ALARM_SET_REMIND_MASK = 0x10,
+ SES_CTRL_AUDIBLE_ALARM_SET_REMIND_SHIFT = 4,
+
+ SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_BYTE = 2,
+ SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_MASK = 0x0F,
+ SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_SHIFT = 0,
+ SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_INFO = 0x08,
+ SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_NON_CRIT = 0x04,
+ SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_CRIT = 0x02,
+ SES_CTRL_AUDIBLE_ALARM_TONE_CONTROL_UNRECOV = 0x01
+};
+
+#define GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_audible_alarm, SES_CTRL_AUDIBLE_ALARM, LCASE, UCASE)
+GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(rqst_fail, RQST_FAIL)
+GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(set_mute, SET_MUTE)
+GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(set_remind, SET_REMIND)
+GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS(tone_control, TONE_CONTROL)
+#undef GEN_SES_CTRL_AUDIBLE_ALARM_ACCESSORS
+
+/*--------- Enclosure Services Controller Electronics Control Element --------*/
+struct ses_ctrl_ecc_electronics {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_ecc_electronics_field_data {
+ SES_CTRL_ECC_ELECTRONICS_RQST_IDENT_BYTE = 0,
+ SES_CTRL_ECC_ELECTRONICS_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_ECC_ELECTRONICS_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_ECC_ELECTRONICS_RQST_FAIL_BYTE = 0,
+ SES_CTRL_ECC_ELECTRONICS_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_ECC_ELECTRONICS_RQST_FAIL_SHIFT = 6,
+
+ SES_CTRL_ECC_ELECTRONICS_SELECT_ELEMENT_BYTE = 1,
+ SES_CTRL_ECC_ELECTRONICS_SELECT_ELEMENT_MASK = 0x01,
+ SES_CTRL_ECC_ELECTRONICS_SELECT_ELEMENT_SHIFT = 0
+};
+
+#define GEN_SES_CTRL_ECC_ELECTRONICS_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_ecc_electronics, SES_CTRL_ECC_ELECTRONICS, \
+ LCASE, UCASE)
+GEN_SES_CTRL_ECC_ELECTRONICS_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_ECC_ELECTRONICS_ACCESSORS(rqst_fail, RQST_FAIL)
+GEN_SES_CTRL_ECC_ELECTRONICS_ACCESSORS(select_element, SELECT_ELEMENT)
+#undef GEN_SES_CTRL_ECC_ELECTRONICS_ACCESSORS
+
+/*----------- SCSI Services Controller Electronics Control Element -----------*/
+struct ses_ctrl_scc_electronics {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_scc_electronics_field_data {
+ SES_CTRL_SCC_ELECTRONICS_RQST_IDENT_BYTE = 0,
+ SES_CTRL_SCC_ELECTRONICS_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_SCC_ELECTRONICS_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_SCC_ELECTRONICS_RQST_FAIL_BYTE = 0,
+ SES_CTRL_SCC_ELECTRONICS_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_SCC_ELECTRONICS_RQST_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_CTRL_SCC_ELECTRONICS_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_scc_electronics, SES_CTRL_SCC_ELECTRONICS, \
+ LCASE, UCASE)
+GEN_SES_CTRL_SCC_ELECTRONICS_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_SCC_ELECTRONICS_ACCESSORS(rqst_fail, RQST_FAIL)
+#undef GEN_SES_CTRL_SCC_ELECTRONICS_ACCESSORS
+
+/*--------------------- Nonvolatile Cache Control Element --------------------*/
+struct ses_ctrl_nv_cache {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_nv_cache_field_data {
+ SES_CTRL_NV_CACHE_RQST_IDENT_BYTE = 0,
+ SES_CTRL_NV_CACHE_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_NV_CACHE_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_NV_CACHE_RQST_FAIL_BYTE = 0,
+ SES_CTRL_NV_CACHE_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_NV_CACHE_RQST_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_CTRL_NV_CACHE_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_nv_cache, SES_CTRL_NV_CACHE, LCASE, UCASE)
+GEN_SES_CTRL_NV_CACHE_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_NV_CACHE_ACCESSORS(rqst_fail, RQST_FAIL)
+#undef GEN_SES_CTRL_NV_CACHE_ACCESSORS
+
+/*----------------- Invalid Operation Reason Control Element -----------------*/
+struct ses_ctrl_invalid_op_reason {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+/* There are no element specific fields currently defined in the spec. */
+
+/*--------------- Uninterruptible Power Supply Control Element ---------------*/
+struct ses_ctrl_ups {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_ups_field_data {
+ SES_CTRL_UPS_RQST_IDENT_BYTE = 2,
+ SES_CTRL_UPS_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_UPS_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_UPS_RQST_FAIL_BYTE = 2,
+ SES_CTRL_UPS_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_UPS_RQST_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_CTRL_UPS_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_ups, SES_CTRL_UPS, LCASE, UCASE)
+GEN_SES_CTRL_UPS_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_UPS_ACCESSORS(rqst_fail, RQST_FAIL)
+#undef GEN_SES_CTRL_UPS_ACCESSORS
+
+/*-------------------------- Display Control Element -------------------------*/
+struct ses_ctrl_display {
+ struct ses_ctrl_common common;
+ uint8_t bytes[1];
+ uint8_t display_character[2];
+};
+
+enum ses_ctrl_display_field_data {
+ SES_CTRL_DISPLAY_RQST_IDENT_BYTE = 0,
+ SES_CTRL_DISPLAY_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_DISPLAY_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_DISPLAY_RQST_FAIL_BYTE = 0,
+ SES_CTRL_DISPLAY_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_DISPLAY_RQST_FAIL_SHIFT = 6,
+
+ SES_CTRL_DISPLAY_DISPLAY_MODE_BYTE = 0,
+ SES_CTRL_DISPLAY_DISPLAY_MODE_MASK = 0x03,
+ SES_CTRL_DISPLAY_DISPLAY_MODE_SHIFT = 6,
+ SES_CTRL_DISPLAY_DISPLAY_MODE_UNCHANGED = 0x0,
+ SES_CTRL_DISPLAY_DISPLAY_MODE_ESP = 0x1,
+ SES_CTRL_DISPLAY_DISPLAY_MODE_DC_FIELD = 0x2
+};
+
+#define GEN_SES_CTRL_DISPLAY_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_display, SES_CTRL_DISPLAY, LCASE, UCASE)
+GEN_SES_CTRL_DISPLAY_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_DISPLAY_ACCESSORS(rqst_fail, RQST_FAIL)
+GEN_SES_CTRL_DISPLAY_ACCESSORS(display_mode, DISPLAY_MODE)
+#undef GEN_SES_CTRL_DISPLAY_ACCESSORS
+
+/*----------------------- Key Pad Entry Control Element ----------------------*/
+struct ses_ctrl_key_pad_entry {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_key_pad_entry_field_data {
+ SES_CTRL_KEY_PAD_ENTRY_RQST_IDENT_BYTE = 0,
+ SES_CTRL_KEY_PAD_ENTRY_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_KEY_PAD_ENTRY_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_KEY_PAD_ENTRY_RQST_FAIL_BYTE = 0,
+ SES_CTRL_KEY_PAD_ENTRY_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_KEY_PAD_ENTRY_RQST_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_CTRL_KEY_PAD_ENTRY_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_key_pad_entry, SES_CTRL_KEY_PAD_ENTRY, LCASE, UCASE)
+GEN_SES_CTRL_KEY_PAD_ENTRY_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_KEY_PAD_ENTRY_ACCESSORS(rqst_fail, RQST_FAIL)
+#undef GEN_SES_CTRL_KEY_PAD_ENTRY_ACCESSORS
+
+/*------------------------- Enclosure Control Element ------------------------*/
+struct ses_ctrl_enclosure {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_enclosure_field_data {
+ SES_CTRL_ENCLOSURE_RQST_IDENT_BYTE = 0,
+ SES_CTRL_ENCLOSURE_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_ENCLOSURE_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_BYTE = 1,
+ SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_MASK = 0xC0,
+ SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_SHIFT = 6,
+ SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_NONE = 0x0,
+ SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_AFTER_DELAY = 0x1,
+ SES_CTRL_ENCLOSURE_POWER_CYCLE_RQST_CANCEL = 0x2,
+
+ SES_CTRL_ENCLOSURE_POWER_CYCLE_DELAY_BYTE = 1,
+ SES_CTRL_ENCLOSURE_POWER_CYCLE_DELAY_MASK = 0x3F,
+ SES_CTRL_ENCLOSURE_POWER_CYCLE_DELAY_SHIFT = 0,
+ SES_CTRL_ENCLOSURE_POWER_CYCLE_DELAY_MAX = 60,/*minutes*/
+
+ SES_CTRL_ENCLOSURE_POWER_OFF_DURATION_BYTE = 2,
+ SES_CTRL_ENCLOSURE_POWER_OFF_DURATION_MASK = 0xFC,
+ SES_CTRL_ENCLOSURE_POWER_OFF_DURATION_SHIFT = 2,
+ SES_CTRL_ENCLOSURE_POWER_OFF_DURATION_MAX_AUTO = 60,
+ SES_CTRL_ENCLOSURE_POWER_OFF_DURATION_MANUAL = 63,
+
+ SES_CTRL_ENCLOSURE_RQST_FAIL_BYTE = 2,
+ SES_CTRL_ENCLOSURE_RQST_FAIL_MASK = 0x02,
+ SES_CTRL_ENCLOSURE_RQST_FAIL_SHIFT = 1,
+
+ SES_CTRL_ENCLOSURE_RQST_WARN_BYTE = 2,
+ SES_CTRL_ENCLOSURE_RQST_WARN_MASK = 0x01,
+ SES_CTRL_ENCLOSURE_RQST_WARN_SHIFT = 0
+};
+
+#define GEN_SES_CTRL_ENCLOSURE_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_enclosure, SES_CTRL_ENCLOSURE, LCASE, UCASE)
+GEN_SES_CTRL_ENCLOSURE_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_ENCLOSURE_ACCESSORS(power_cycle_rqst, POWER_CYCLE_RQST)
+GEN_SES_CTRL_ENCLOSURE_ACCESSORS(power_cycle_delay, POWER_CYCLE_DELAY)
+GEN_SES_CTRL_ENCLOSURE_ACCESSORS(power_off_duration, POWER_OFF_DURATION)
+GEN_SES_CTRL_ENCLOSURE_ACCESSORS(rqst_fail, RQST_FAIL)
+GEN_SES_CTRL_ENCLOSURE_ACCESSORS(rqst_warn, RQST_WARN)
+#undef GEN_SES_CTRL_ENCLOSURE_ACCESSORS
+
+/*------------------- SCSI Port/Transceiver Control Element ------------------*/
+struct ses_ctrl_scsi_port_or_xcvr {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_scsi_port_or_xcvr_field_data {
+ SES_CTRL_SCSI_PORT_OR_XCVR_RQST_IDENT_BYTE = 0,
+ SES_CTRL_SCSI_PORT_OR_XCVR_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_SCSI_PORT_OR_XCVR_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_SCSI_PORT_OR_XCVR_RQST_FAIL_BYTE = 0,
+ SES_CTRL_SCSI_PORT_OR_XCVR_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_SCSI_PORT_OR_XCVR_RQST_FAIL_SHIFT = 6,
+
+ SES_CTRL_SCSI_PORT_OR_XCVR_DISABLE_BYTE = 2,
+ SES_CTRL_SCSI_PORT_OR_XCVR_DISABLE_MASK = 0x10,
+ SES_CTRL_SCSI_PORT_OR_XCVR_DISABLE_SHIFT = 4
+};
+
+#define GEN_SES_CTRL_SCSI_PORT_OR_XCVR_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_scsi_port_or_xcvr, SES_CTRL_SCSI_PORT_OR_XCVR,\
+ LCASE, UCASE)
+GEN_SES_CTRL_SCSI_PORT_OR_XCVR_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_SCSI_PORT_OR_XCVR_ACCESSORS(disable, DISABLE)
+GEN_SES_CTRL_SCSI_PORT_OR_XCVR_ACCESSORS(rqst_fail, RQST_FAIL)
+#undef GEN_SES_CTRL_SCSI_PORT_OR_XCVR_ACCESSORS
+
+/*------------------------- Language Control Element -------------------------*/
+struct ses_ctrl_language {
+ struct ses_ctrl_common common;
+ uint8_t bytes[1];
+ uint8_t language_code[2];
+};
+
+enum ses_ctrl_language_field_data {
+ SES_CTRL_LANGUAGE_RQST_IDENT_BYTE = 0,
+ SES_CTRL_LANGUAGE_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_LANGUAGE_RQST_IDENT_SHIFT = 7
+};
+
+#define GEN_SES_CTRL_LANGUAGE_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_language, SES_CTRL_LANGUAGE, LCASE, UCASE)
+GEN_SES_CTRL_LANGUAGE_ACCESSORS(rqst_ident, RQST_IDENT)
+#undef GEN_SES_CTRL_LANGUAGE_ACCESSORS
+
+/*-------------------- Communication Port Control Element --------------------*/
+struct ses_ctrl_comm_port {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_comm_port_field_data {
+ SES_CTRL_COMM_PORT_RQST_IDENT_BYTE = 0,
+ SES_CTRL_COMM_PORT_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_COMM_PORT_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_COMM_PORT_RQST_FAIL_BYTE = 0,
+ SES_CTRL_COMM_PORT_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_COMM_PORT_RQST_FAIL_SHIFT = 6,
+
+ SES_CTRL_COMM_PORT_DISABLE_BYTE = 2,
+ SES_CTRL_COMM_PORT_DISABLE_MASK = 0x01,
+ SES_CTRL_COMM_PORT_DISABLE_SHIFT = 0
+};
+
+#define GEN_SES_CTRL_COMM_PORT_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_comm_port, SES_CTRL_COMM_PORT, LCASE, UCASE)
+GEN_SES_CTRL_COMM_PORT_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_COMM_PORT_ACCESSORS(rqst_fail, RQST_FAIL)
+GEN_SES_CTRL_COMM_PORT_ACCESSORS(disable, DISABLE)
+#undef GEN_SES_CTRL_COMM_PORT_ACCESSORS
+
+/*---------------------- Voltage Sensor Control Element ----------------------*/
+struct ses_ctrl_voltage_sensor {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_voltage_sensor_field_data {
+ SES_CTRL_VOLTAGE_SENSOR_RQST_IDENT_BYTE = 0,
+ SES_CTRL_VOLTAGE_SENSOR_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_VOLTAGE_SENSOR_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_VOLTAGE_SENSOR_RQST_FAIL_BYTE = 0,
+ SES_CTRL_VOLTAGE_SENSOR_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_VOLTAGE_SENSOR_RQST_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_CTRL_VOLTAGE_SENSOR_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_voltage_sensor, SES_CTRL_VOLTAGE_SENSOR, \
+ LCASE, UCASE)
+GEN_SES_CTRL_VOLTAGE_SENSOR_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_VOLTAGE_SENSOR_ACCESSORS(rqst_fail, RQST_FAIL)
+#undef GEN_SES_CTRL_VOLTAGE_SENSOR_ACCESSORS
+
+/*---------------------- Current Sensor Control Element ----------------------*/
+struct ses_ctrl_current_sensor {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_current_sensor_field_data {
+ SES_CTRL_CURRENT_SENSOR_RQST_IDENT_BYTE = 0,
+ SES_CTRL_CURRENT_SENSOR_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_CURRENT_SENSOR_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_CURRENT_SENSOR_RQST_FAIL_BYTE = 0,
+ SES_CTRL_CURRENT_SENSOR_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_CURRENT_SENSOR_RQST_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_CTRL_CURRENT_SENSOR_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_current_sensor, SES_CTRL_CURRENT_SENSOR, \
+ LCASE, UCASE)
+GEN_SES_CTRL_CURRENT_SENSOR_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_CURRENT_SENSOR_ACCESSORS(rqst_fail, RQST_FAIL)
+#undef GEN_SES_CTRL_CURRENT_SENSOR_ACCESSORS
+
+/*--------------------- SCSI Target Port Control Element ---------------------*/
+struct ses_ctrl_target_port {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_scsi_target_port_field_data {
+ SES_CTRL_TARGET_PORT_RQST_IDENT_BYTE = 0,
+ SES_CTRL_TARGET_PORT_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_TARGET_PORT_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_TARGET_PORT_RQST_FAIL_BYTE = 0,
+ SES_CTRL_TARGET_PORT_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_TARGET_PORT_RQST_FAIL_SHIFT = 6,
+
+ SES_CTRL_TARGET_PORT_ENABLE_BYTE = 2,
+ SES_CTRL_TARGET_PORT_ENABLE_MASK = 0x01,
+ SES_CTRL_TARGET_PORT_ENABLE_SHIFT = 0
+};
+
+#define GEN_SES_CTRL_TARGET_PORT_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_target_port, SES_CTRL_TARGET_PORT, LCASE, UCASE)
+GEN_SES_CTRL_TARGET_PORT_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_TARGET_PORT_ACCESSORS(rqst_fail, RQST_FAIL)
+GEN_SES_CTRL_TARGET_PORT_ACCESSORS(enable, ENABLE)
+#undef GEN_SES_CTRL_TARGET_PORT_ACCESSORS
+
+/*-------------------- SCSI Initiator Port Control Element -------------------*/
+struct ses_ctrl_initiator_port {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_initiator_port_field_data {
+ SES_CTRL_INITIATOR_PORT_RQST_IDENT_BYTE = 0,
+ SES_CTRL_INITIATOR_PORT_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_INITIATOR_PORT_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_INITIATOR_PORT_RQST_FAIL_BYTE = 0,
+ SES_CTRL_INITIATOR_PORT_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_INITIATOR_PORT_RQST_FAIL_SHIFT = 6,
+
+ SES_CTRL_INITIATOR_PORT_ENABLE_BYTE = 2,
+ SES_CTRL_INITIATOR_PORT_ENABLE_MASK = 0x01,
+ SES_CTRL_INITIATOR_PORT_ENABLE_SHIFT = 0
+};
+
+#define GEN_SES_CTRL_INITIATOR_PORT_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_initiator_port, SES_CTRL_INITIATOR_PORT, \
+ LCASE, UCASE)
+GEN_SES_CTRL_INITIATOR_PORT_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_INITIATOR_PORT_ACCESSORS(rqst_fail, RQST_FAIL)
+GEN_SES_CTRL_INITIATOR_PORT_ACCESSORS(enable, ENABLE)
+#undef GEN_SES_CTRL_INITIATOR_PORT_ACCESSORS
+
+/*-------------------- Simple Subenclosure Control Element -------------------*/
+struct ses_ctrl_simple_subenc {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_simple_subenc_field_data {
+ SES_CTRL_SIMPlE_SUBSES_RQST_IDENT_BYTE = 0,
+ SES_CTRL_SIMPlE_SUBSES_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_SIMPlE_SUBSES_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_SIMPlE_SUBSES_RQST_FAIL_BYTE = 0,
+ SES_CTRL_SIMPlE_SUBSES_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_SIMPlE_SUBSES_RQST_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_CTRL_SIMPlE_SUBSES_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_simple_subenc, SES_CTRL_SIMPlE_SUBSES, \
+ LCASE, UCASE)
+GEN_SES_CTRL_SIMPlE_SUBSES_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_SIMPlE_SUBSES_ACCESSORS(rqst_fail, RQST_FAIL)
+#undef GEN_SES_CTRL_SIMPlE_SUBSES_ACCESSORS
+
+/*----------------------- SAS Expander Control Element -----------------------*/
+struct ses_ctrl_sas_expander {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_sas_expander_field_data {
+ SES_CTRL_SAS_EXPANDER_RQST_IDENT_BYTE = 0,
+ SES_CTRL_SAS_EXPANDER_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_SAS_EXPANDER_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_SAS_EXPANDER_RQST_FAIL_BYTE = 0,
+ SES_CTRL_SAS_EXPANDER_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_SAS_EXPANDER_RQST_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_CTRL_SAS_EXPANDER_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_sas_expander, SES_CTRL_SAS_EXPANDER, LCASE, UCASE)
+GEN_SES_CTRL_SAS_EXPANDER_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_SAS_EXPANDER_ACCESSORS(rqst_fail, RQST_FAIL)
+#undef GEN_SES_CTRL_SAS_EXPANDER_ACCESSORS
+
+/*----------------------- SAS Connector Control Element ----------------------*/
+struct ses_ctrl_sas_connector {
+ struct ses_ctrl_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_ctrl_sas_connector_field_data {
+ SES_CTRL_SAS_CONNECTOR_RQST_IDENT_BYTE = 0,
+ SES_CTRL_SAS_CONNECTOR_RQST_IDENT_MASK = 0x80,
+ SES_CTRL_SAS_CONNECTOR_RQST_IDENT_SHIFT = 7,
+
+ SES_CTRL_SAS_CONNECTOR_RQST_FAIL_BYTE = 2,
+ SES_CTRL_SAS_CONNECTOR_RQST_FAIL_MASK = 0x40,
+ SES_CTRL_SAS_CONNECTOR_RQST_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_CTRL_SAS_CONNECTOR_ACCESSORS(LCASE, UCASE) \
+ GEN_ACCESSORS(ses_ctrl_sas_connector, SES_CTRL_SAS_CONNECTOR, \
+ LCASE, UCASE)
+GEN_SES_CTRL_SAS_CONNECTOR_ACCESSORS(rqst_ident, RQST_IDENT)
+GEN_SES_CTRL_SAS_CONNECTOR_ACCESSORS(rqst_fail, RQST_FAIL)
+#undef GEN_SES_CTRL_SAS_CONNECTOR_ACCESSORS
+
+/*------------------------- Universal Control Element ------------------------*/
+union ses_ctrl_element {
+ struct ses_ctrl_common common;
+ struct ses_ctrl_dev_slot dev_slot;
+ struct ses_ctrl_array_dev_slot array_dev_slot;
+ struct ses_ctrl_power_supply power_supply;
+ struct ses_ctrl_cooling cooling;
+ struct ses_ctrl_temp_sensor temp_sensor;
+ struct ses_ctrl_door_lock door_lock;
+ struct ses_ctrl_audible_alarm audible_alarm;
+ struct ses_ctrl_ecc_electronics ecc_electronics;
+ struct ses_ctrl_scc_electronics scc_electronics;
+ struct ses_ctrl_nv_cache nv_cache;
+ struct ses_ctrl_invalid_op_reason invalid_op_reason;
+ struct ses_ctrl_ups ups;
+ struct ses_ctrl_display display;
+ struct ses_ctrl_key_pad_entry key_pad_entry;
+ struct ses_ctrl_scsi_port_or_xcvr scsi_port_or_xcvr;
+ struct ses_ctrl_language language;
+ struct ses_ctrl_comm_port comm_port;
+ struct ses_ctrl_voltage_sensor voltage_sensor;
+ struct ses_ctrl_current_sensor current_sensor;
+ struct ses_ctrl_target_port target_port;
+ struct ses_ctrl_initiator_port initiator_port;
+ struct ses_ctrl_simple_subenc simple_subenc;
+ struct ses_ctrl_sas_expander sas_expander;
+ struct ses_ctrl_sas_connector sas_connector;
+};
+
+/*--------------------- SCSI SES Control Diagnostic Page ---------------------*/
+struct ses_ctrl_page {
+ struct ses_page_hdr hdr;
+ union ses_ctrl_element elements[];
+};
+
+enum ses_ctrl_page_field_data {
+ SES_CTRL_PAGE_INFO_MASK = 0x08,
+ SES_CTRL_PAGE_INFO_SHIFT = 3,
+
+ SES_CTRL_PAGE_NON_CRIT_MASK = 0x04,
+ SES_CTRL_PAGE_NON_CRIT_SHIFT = 2,
+
+ SES_CTRL_PAGE_CRIT_MASK = 0x02,
+ SES_CTRL_PAGE_CRIT_SHIFT = 1,
+
+ SES_CTRL_PAGE_UNRECOV_MASK = 0x01,
+ SES_CTRL_PAGE_UNRECOV_SHIFT = 0
+};
+
+#define GEN_SES_CTRL_PAGE_ACCESSORS(LCASE, UCASE) \
+ GEN_HDR_ACCESSORS(ses_ctrl_page, SES_CTRL_PAGE, LCASE, UCASE)
+
+GEN_SES_CTRL_PAGE_ACCESSORS(info, INFO)
+GEN_SES_CTRL_PAGE_ACCESSORS(non_crit, NON_CRIT)
+GEN_SES_CTRL_PAGE_ACCESSORS(crit, CRIT)
+GEN_SES_CTRL_PAGE_ACCESSORS(unrecov, UNRECOV)
+#undef GEN_SES_CTRL_PAGE_ACCESSORS
+
+/*================= SCSI SES Status Diagnostic Page Structures ===============*/
+struct ses_status_common {
+ uint8_t bytes[1];
+};
+
+enum ses_status_common_field_data {
+ SES_STATUS_COMMON_PRDFAIL_BYTE = 0,
+ SES_STATUS_COMMON_PRDFAIL_MASK = 0x40,
+ SES_STATUS_COMMON_PRDFAIL_SHIFT = 6,
+
+ SES_STATUS_COMMON_DISABLED_BYTE = 0,
+ SES_STATUS_COMMON_DISABLED_MASK = 0x20,
+ SES_STATUS_COMMON_DISABLED_SHIFT = 5,
+
+ SES_STATUS_COMMON_SWAP_BYTE = 0,
+ SES_STATUS_COMMON_SWAP_MASK = 0x10,
+ SES_STATUS_COMMON_SWAP_SHIFT = 4,
+
+ SES_STATUS_COMMON_ELEMENT_STATUS_CODE_BYTE = 0,
+ SES_STATUS_COMMON_ELEMENT_STATUS_CODE_MASK = 0x0F,
+ SES_STATUS_COMMON_ELEMENT_STATUS_CODE_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_COMMON_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_common, SES_STATUS_COMMON, LCASE, UCASE)
+
+GEN_SES_STATUS_COMMON_ACCESSORS(prdfail, PRDFAIL)
+GEN_SES_STATUS_COMMON_ACCESSORS(disabled, DISABLED)
+GEN_SES_STATUS_COMMON_ACCESSORS(swap, SWAP)
+GEN_SES_STATUS_COMMON_ACCESSORS(element_status_code, ELEMENT_STATUS_CODE)
+#undef GEN_SES_STATUS_COMMON_ACCESSORS
+
+/*------------------------- Device Slot Status Element -----------------------*/
+struct ses_status_dev_slot {
+ struct ses_status_common common;
+ uint8_t slot_address;
+ uint8_t bytes[2];
+};
+
+enum ses_status_dev_slot_field_data {
+ SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_A_BYTE = 0,
+ SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_A_MASK = 0x80,
+ SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_A_SHIFT = 7,
+
+ SES_STATUS_DEV_SLOT_DO_NOT_REMOVE_BYTE = 0,
+ SES_STATUS_DEV_SLOT_DO_NOT_REMOVE_MASK = 0x40,
+ SES_STATUS_DEV_SLOT_DO_NOT_REMOVE_SHIFT = 6,
+
+ SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_A_BYTE = 0,
+ SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_A_MASK = 0x20,
+ SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_A_SHIFT = 5,
+
+ SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_B_BYTE = 0,
+ SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_B_MASK = 0x10,
+ SES_STATUS_DEV_SLOT_ENCLOSURE_BYPED_B_SHIFT = 4,
+
+ SES_STATUS_DEV_SLOT_INSERT_READY_BYTE = 0,
+ SES_STATUS_DEV_SLOT_INSERT_READY_MASK = 0x08,
+ SES_STATUS_DEV_SLOT_INSERT_READY_SHIFT = 3,
+
+ SES_STATUS_DEV_SLOT_REMOVE_BYTE = 0,
+ SES_STATUS_DEV_SLOT_REMOVE_MASK = 0x04,
+ SES_STATUS_DEV_SLOT_REMOVE_SHIFT = 2,
+
+ SES_STATUS_DEV_SLOT_IDENT_BYTE = 0,
+ SES_STATUS_DEV_SLOT_IDENT_MASK = 0x02,
+ SES_STATUS_DEV_SLOT_IDENT_SHIFT = 1,
+
+ SES_STATUS_DEV_SLOT_REPORT_BYTE = 0,
+ SES_STATUS_DEV_SLOT_REPORT_MASK = 0x01,
+ SES_STATUS_DEV_SLOT_REPORT_SHIFT = 0,
+
+ SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_B_BYTE = 1,
+ SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_B_MASK = 0x80,
+ SES_STATUS_DEV_SLOT_APP_CLIENT_BYPED_B_SHIFT = 7,
+
+ SES_STATUS_DEV_SLOT_FAULT_SENSED_BYTE = 1,
+ SES_STATUS_DEV_SLOT_FAULT_SENSED_MASK = 0x40,
+ SES_STATUS_DEV_SLOT_FAULT_SENSED_SHIFT = 6,
+
+ SES_STATUS_DEV_SLOT_FAULT_REQUESTED_BYTE = 1,
+ SES_STATUS_DEV_SLOT_FAULT_REQUESTED_MASK = 0x20,
+ SES_STATUS_DEV_SLOT_FAULT_REQUESTED_SHIFT = 5,
+
+ SES_STATUS_DEV_SLOT_DEVICE_OFF_BYTE = 1,
+ SES_STATUS_DEV_SLOT_DEVICE_OFF_MASK = 0x10,
+ SES_STATUS_DEV_SLOT_DEVICE_OFF_SHIFT = 4,
+
+ SES_STATUS_DEV_SLOT_BYPED_A_BYTE = 1,
+ SES_STATUS_DEV_SLOT_BYPED_A_MASK = 0x08,
+ SES_STATUS_DEV_SLOT_BYPED_A_SHIFT = 3,
+
+ SES_STATUS_DEV_SLOT_BYPED_B_BYTE = 1,
+ SES_STATUS_DEV_SLOT_BYPED_B_MASK = 0x04,
+ SES_STATUS_DEV_SLOT_BYPED_B_SHIFT = 2,
+
+ SES_STATUS_DEV_SLOT_DEVICE_BYPED_A_BYTE = 1,
+ SES_STATUS_DEV_SLOT_DEVICE_BYPED_A_MASK = 0x02,
+ SES_STATUS_DEV_SLOT_DEVICE_BYPED_A_SHIFT = 1,
+
+ SES_STATUS_DEV_SLOT_DEVICE_BYPED_B_BYTE = 1,
+ SES_STATUS_DEV_SLOT_DEVICE_BYPED_B_MASK = 0x01,
+ SES_STATUS_DEV_SLOT_DEVICE_BYPED_B_SHIFT = 0
+};
+#define GEN_SES_STATUS_DEV_SLOT_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_dev_slot, SES_STATUS_DEV_SLOT, LCASE, UCASE)
+
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(app_client_byped_a, APP_CLIENT_BYPED_A)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(do_not_remove, DO_NOT_REMOVE)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(enclosure_byped_a, ENCLOSURE_BYPED_A)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(enclosure_byped_b, ENCLOSURE_BYPED_B)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(insert_ready, INSERT_READY)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(remove, REMOVE)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(report, REPORT)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(app_client_byped_b, APP_CLIENT_BYPED_B)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(fault_sensed, FAULT_SENSED)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(fault_requested, FAULT_REQUESTED)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(device_off, DEVICE_OFF)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(byped_a, BYPED_A)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(byped_b, BYPED_B)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(device_byped_a, DEVICE_BYPED_A)
+GEN_SES_STATUS_DEV_SLOT_ACCESSORS(device_byped_b, DEVICE_BYPED_B)
+#undef GEN_SES_STATUS_DEV_SLOT_ACCESSORS
+
+/*---------------------- Array Device Slot Status Element --------------------*/
+struct ses_status_array_dev_slot {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_array_dev_slot_field_data {
+ SES_STATUS_ARRAY_DEV_SLOT_OK_BYTE = 0,
+ SES_STATUS_ARRAY_DEV_SLOT_OK_MASK = 0x80,
+ SES_STATUS_ARRAY_DEV_SLOT_OK_SHIFT = 7,
+
+ SES_STATUS_ARRAY_DEV_SLOT_RSVD_DEVICE_BYTE = 0,
+ SES_STATUS_ARRAY_DEV_SLOT_RSVD_DEVICE_MASK = 0x40,
+ SES_STATUS_ARRAY_DEV_SLOT_RSVD_DEVICE_SHIFT = 6,
+
+ SES_STATUS_ARRAY_DEV_SLOT_HOT_SPARE_BYTE = 0,
+ SES_STATUS_ARRAY_DEV_SLOT_HOT_SPARE_MASK = 0x20,
+ SES_STATUS_ARRAY_DEV_SLOT_HOT_SPARE_SHIFT = 5,
+
+ SES_STATUS_ARRAY_DEV_SLOT_CONS_CHECK_BYTE = 0,
+ SES_STATUS_ARRAY_DEV_SLOT_CONS_CHECK_MASK = 0x10,
+ SES_STATUS_ARRAY_DEV_SLOT_CONS_CHECK_SHIFT = 4,
+
+ SES_STATUS_ARRAY_DEV_SLOT_IN_CRIT_ARRAY_BYTE = 0,
+ SES_STATUS_ARRAY_DEV_SLOT_IN_CRIT_ARRAY_MASK = 0x08,
+ SES_STATUS_ARRAY_DEV_SLOT_IN_CRIT_ARRAY_SHIFT = 3,
+
+ SES_STATUS_ARRAY_DEV_SLOT_IN_FAILED_ARRAY_BYTE = 0,
+ SES_STATUS_ARRAY_DEV_SLOT_IN_FAILED_ARRAY_MASK = 0x04,
+ SES_STATUS_ARRAY_DEV_SLOT_IN_FAILED_ARRAY_SHIFT = 2,
+
+ SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_BYTE = 0,
+ SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_MASK = 0x02,
+ SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_SHIFT = 1,
+
+ SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_ABORT_BYTE = 0,
+ SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_ABORT_MASK = 0x01,
+ SES_STATUS_ARRAY_DEV_SLOT_REBUILD_REMAP_ABORT_SHIFT = 0
+
+ /*
+ * The remaining fields are identical to the device
+ * slot element type. Access them through the device slot
+ * element type and its accessors.
+ */
+};
+#define GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_array_dev_slot, SES_STATUS_ARRAY_DEV_SLOT, \
+ LCASE, UCASE)
+GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(ok, OK)
+GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(rsvd_device, RSVD_DEVICE)
+GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(hot_spare, HOT_SPARE)
+GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(cons_check, CONS_CHECK)
+GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(in_crit_array, IN_CRIT_ARRAY)
+GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(in_failed_array, IN_FAILED_ARRAY)
+GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(rebuild_remap, REBUILD_REMAP)
+GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS(rebuild_remap_abort,
+ REBUILD_REMAP_ABORT)
+#undef GEN_SES_STATUS_ARRAY_DEV_SLOT_ACCESSORS
+
+/*----------------------- Power Supply Status Element ------------------------*/
+struct ses_status_power_supply {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_power_supply_field_data {
+ SES_STATUS_POWER_SUPPLY_IDENT_BYTE = 0,
+ SES_STATUS_POWER_SUPPLY_IDENT_MASK = 0x80,
+ SES_STATUS_POWER_SUPPLY_IDENT_SHIFT = 7,
+
+ SES_STATUS_POWER_SUPPLY_DC_OVER_VOLTAGE_BYTE = 1,
+ SES_STATUS_POWER_SUPPLY_DC_OVER_VOLTAGE_MASK = 0x08,
+ SES_STATUS_POWER_SUPPLY_DC_OVER_VOLTAGE_SHIFT = 3,
+
+ SES_STATUS_POWER_SUPPLY_DC_UNDER_VOLTAGE_BYTE = 1,
+ SES_STATUS_POWER_SUPPLY_DC_UNDER_VOLTAGE_MASK = 0x04,
+ SES_STATUS_POWER_SUPPLY_DC_UNDER_VOLTAGE_SHIFT = 2,
+
+ SES_STATUS_POWER_SUPPLY_DC_OVER_CURRENT_BYTE = 1,
+ SES_STATUS_POWER_SUPPLY_DC_OVER_CURRENT_MASK = 0x02,
+ SES_STATUS_POWER_SUPPLY_DC_OVER_CURRENT_SHIFT = 1,
+
+ SES_STATUS_POWER_SUPPLY_HOT_SWAP_BYTE = 2,
+ SES_STATUS_POWER_SUPPLY_HOT_SWAP_MASK = 0x80,
+ SES_STATUS_POWER_SUPPLY_HOT_SWAP_SHIFT = 7,
+
+ SES_STATUS_POWER_SUPPLY_FAIL_BYTE = 2,
+ SES_STATUS_POWER_SUPPLY_FAIL_MASK = 0x40,
+ SES_STATUS_POWER_SUPPLY_FAIL_SHIFT = 6,
+
+ SES_STATUS_POWER_SUPPLY_REQUESTED_ON_BYTE = 2,
+ SES_STATUS_POWER_SUPPLY_REQUESTED_ON_MASK = 0x20,
+ SES_STATUS_POWER_SUPPLY_REQUESTED_ON_SHIFT = 5,
+
+ SES_STATUS_POWER_SUPPLY_OFF_BYTE = 2,
+ SES_STATUS_POWER_SUPPLY_OFF_MASK = 0x10,
+ SES_STATUS_POWER_SUPPLY_OFF_SHIFT = 4,
+
+ SES_STATUS_POWER_SUPPLY_OVERTMP_FAIL_BYTE = 2,
+ SES_STATUS_POWER_SUPPLY_OVERTMP_FAIL_MASK = 0x08,
+ SES_STATUS_POWER_SUPPLY_OVERTMP_FAIL_SHIFT = 3,
+
+ SES_STATUS_POWER_SUPPLY_TEMP_WARN_BYTE = 2,
+ SES_STATUS_POWER_SUPPLY_TEMP_WARN_MASK = 0x04,
+ SES_STATUS_POWER_SUPPLY_TEMP_WARN_SHIFT = 2,
+
+ SES_STATUS_POWER_SUPPLY_AC_FAIL_BYTE = 2,
+ SES_STATUS_POWER_SUPPLY_AC_FAIL_MASK = 0x02,
+ SES_STATUS_POWER_SUPPLY_AC_FAIL_SHIFT = 1,
+
+ SES_STATUS_POWER_SUPPLY_DC_FAIL_BYTE = 2,
+ SES_STATUS_POWER_SUPPLY_DC_FAIL_MASK = 0x01,
+ SES_STATUS_POWER_SUPPLY_DC_FAIL_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_power_supply, SES_STATUS_POWER_SUPPLY, LCASE, UCASE)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(dc_over_voltage, DC_OVER_VOLTAGE)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(dc_under_voltage, DC_UNDER_VOLTAGE)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(dc_over_current, DC_OVER_CURRENT)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(hot_swap, HOT_SWAP)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(requested_on, REQUESTED_ON)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(off, OFF)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(overtmp_fail, OVERTMP_FAIL)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(temp_warn, TEMP_WARN)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(ac_fail, AC_FAIL)
+GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS(dc_fail, DC_FAIL)
+#undef GEN_SES_STATUS_POWER_SUPPLY_ACCESSORS
+
+/*-------------------------- Cooling Status Element --------------------------*/
+struct ses_status_cooling {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_cooling_field_data {
+ SES_STATUS_COOLING_IDENT_BYTE = 0,
+ SES_STATUS_COOLING_IDENT_MASK = 0x80,
+ SES_STATUS_COOLING_IDENT_SHIFT = 7,
+
+ SES_STATUS_COOLING_ACTUAL_FAN_SPEED_MSB_BYTE = 0,
+ SES_STATUS_COOLING_ACTUAL_FAN_SPEED_MSB_MASK = 0x07,
+ SES_STATUS_COOLING_ACTUAL_FAN_SPEED_MSB_SHIFT = 0,
+
+ SES_STATUS_COOLING_ACTUAL_FAN_SPEED_LSB_BYTE = 1,
+ SES_STATUS_COOLING_ACTUAL_FAN_SPEED_LSB_MASK = 0xFF,
+ SES_STATUS_COOLING_ACTUAL_FAN_SPEED_LSB_SHIFT = 0,
+
+ SES_STATUS_COOLING_HOT_SWAP_BYTE = 2,
+ SES_STATUS_COOLING_HOT_SWAP_MASK = 0x40,
+ SES_STATUS_COOLING_HOT_SWAP_SHIFT = 6,
+
+ SES_STATUS_COOLING_FAIL_BYTE = 2,
+ SES_STATUS_COOLING_FAIL_MASK = 0x40,
+ SES_STATUS_COOLING_FAIL_SHIFT = 6,
+
+ SES_STATUS_COOLING_REQUESTED_ON_BYTE = 2,
+ SES_STATUS_COOLING_REQUESTED_ON_MASK = 0x20,
+ SES_STATUS_COOLING_REQUESTED_ON_SHIFT = 5,
+
+ SES_STATUS_COOLING_OFF_BYTE = 2,
+ SES_STATUS_COOLING_OFF_MASK = 0x20,
+ SES_STATUS_COOLING_OFF_SHIFT = 5,
+
+ SES_STATUS_COOLING_ACTUAL_SPEED_CODE_BYTE = 2,
+ SES_STATUS_COOLING_ACTUAL_SPEED_CODE_MASK = 0x07,
+ SES_STATUS_COOLING_ACTUAL_SPEED_CODE_SHIFT = 2,
+ SES_STATUS_COOLING_ACTUAL_SPEED_CODE_STOPPED = 0x00,
+ SES_STATUS_COOLING_ACTUAL_SPEED_CODE_LOWEST = 0x01,
+ SES_STATUS_COOLING_ACTUAL_SPEED_CODE_HIGHEST = 0x07
+};
+
+#define GEN_SES_STATUS_COOLING_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_cooling, SES_STATUS_COOLING, LCASE, UCASE)
+GEN_SES_STATUS_COOLING_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_COOLING_ACCESSORS(actual_fan_speed_msb, ACTUAL_FAN_SPEED_MSB)
+GEN_SES_STATUS_COOLING_ACCESSORS(actual_fan_speed_lsb, ACTUAL_FAN_SPEED_LSB)
+GEN_SES_STATUS_COOLING_ACCESSORS(hot_swap, HOT_SWAP)
+GEN_SES_STATUS_COOLING_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_COOLING_ACCESSORS(requested_on, REQUESTED_ON)
+GEN_SES_STATUS_COOLING_ACCESSORS(off, OFF)
+GEN_SES_STATUS_COOLING_ACCESSORS(actual_speed_code, ACTUAL_SPEED_CODE)
+#undef GEN_SES_STATUS_COOLING_ACCESSORS
+
+static inline int
+ses_status_cooling_get_actual_fan_speed(struct ses_status_cooling *elem)
+{
+ return (ses_status_cooling_get_actual_fan_speed_msb(elem) << 8
+ | ses_status_cooling_get_actual_fan_speed_lsb(elem));
+}
+
+/*-------------------- Temperature Sensor Status Element ---------------------*/
+struct ses_status_temp_sensor {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_temp_sensor_field_data {
+ SES_STATUS_TEMP_SENSOR_IDENT_BYTE = 0,
+ SES_STATUS_TEMP_SENSOR_IDENT_MASK = 0x80,
+ SES_STATUS_TEMP_SENSOR_IDENT_SHIFT = 7,
+
+ SES_STATUS_TEMP_SENSOR_FAIL_BYTE = 0,
+ SES_STATUS_TEMP_SENSOR_FAIL_MASK = 0x40,
+ SES_STATUS_TEMP_SENSOR_FAIL_SHIFT = 6,
+
+ SES_STATUS_TEMP_SENSOR_TEMPERATURE_BYTE = 1,
+ SES_STATUS_TEMP_SENSOR_TEMPERATURE_MASK = 0xFF,
+ SES_STATUS_TEMP_SENSOR_TEMPERATURE_SHIFT = 0,
+
+ SES_STATUS_TEMP_SENSOR_OT_FAILURE_BYTE = 2,
+ SES_STATUS_TEMP_SENSOR_OT_FAILURE_MASK = 0x08,
+ SES_STATUS_TEMP_SENSOR_OT_FAILURE_SHIFT = 3,
+
+ SES_STATUS_TEMP_SENSOR_OT_WARNING_BYTE = 2,
+ SES_STATUS_TEMP_SENSOR_OT_WARNING_MASK = 0x04,
+ SES_STATUS_TEMP_SENSOR_OT_WARNING_SHIFT = 2,
+
+ SES_STATUS_TEMP_SENSOR_UT_FAILURE_BYTE = 2,
+ SES_STATUS_TEMP_SENSOR_UT_FAILURE_MASK = 0x02,
+ SES_STATUS_TEMP_SENSOR_UT_FAILURE_SHIFT = 1,
+
+ SES_STATUS_TEMP_SENSOR_UT_WARNING_BYTE = 2,
+ SES_STATUS_TEMP_SENSOR_UT_WARNING_MASK = 0x01,
+ SES_STATUS_TEMP_SENSOR_UT_WARNING_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_temp_sensor, SES_STATUS_TEMP_SENSOR, LCASE, UCASE)
+GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(temperature, TEMPERATURE)
+GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(ot_failure, OT_FAILURE)
+GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(ot_warning, OT_WARNING)
+GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(ut_failure, UT_FAILURE)
+GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS(ut_warning, UT_WARNING)
+#undef GEN_SES_STATUS_TEMP_SENSOR_ACCESSORS
+
+/*------------------------- Door Lock Status Element -------------------------*/
+struct ses_status_door_lock {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_door_lock_field_data {
+ SES_STATUS_DOOR_LOCK_IDENT_BYTE = 0,
+ SES_STATUS_DOOR_LOCK_IDENT_MASK = 0x80,
+ SES_STATUS_DOOR_LOCK_IDENT_SHIFT = 7,
+
+ SES_STATUS_DOOR_LOCK_FAIL_BYTE = 0,
+ SES_STATUS_DOOR_LOCK_FAIL_MASK = 0x40,
+ SES_STATUS_DOOR_LOCK_FAIL_SHIFT = 6,
+
+ SES_STATUS_DOOR_LOCK_UNLOCKED_BYTE = 2,
+ SES_STATUS_DOOR_LOCK_UNLOCKED_MASK = 0x01,
+ SES_STATUS_DOOR_LOCK_UNLOCKED_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_DOOR_LOCK_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_door_lock, SES_STATUS_DOOR_LOCK, LCASE, UCASE)
+GEN_SES_STATUS_DOOR_LOCK_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_DOOR_LOCK_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_DOOR_LOCK_ACCESSORS(unlocked, UNLOCKED)
+#undef GEN_SES_STATUS_DOOR_LOCK_ACCESSORS
+
+/*----------------------- Audible Alarm Status Element -----------------------*/
+struct ses_status_audible_alarm {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_audible_alarm_field_data {
+ SES_STATUS_AUDIBLE_ALARM_IDENT_BYTE = 0,
+ SES_STATUS_AUDIBLE_ALARM_IDENT_MASK = 0x80,
+ SES_STATUS_AUDIBLE_ALARM_IDENT_SHIFT = 7,
+
+ SES_STATUS_AUDIBLE_ALARM_FAIL_BYTE = 0,
+ SES_STATUS_AUDIBLE_ALARM_FAIL_MASK = 0x40,
+ SES_STATUS_AUDIBLE_ALARM_FAIL_SHIFT = 6,
+
+ SES_STATUS_AUDIBLE_ALARM_RQST_MUTE_BYTE = 2,
+ SES_STATUS_AUDIBLE_ALARM_RQST_MUTE_MASK = 0x80,
+ SES_STATUS_AUDIBLE_ALARM_RQST_MUTE_SHIFT = 7,
+
+ SES_STATUS_AUDIBLE_ALARM_MUTED_BYTE = 2,
+ SES_STATUS_AUDIBLE_ALARM_MUTED_MASK = 0x40,
+ SES_STATUS_AUDIBLE_ALARM_MUTED_SHIFT = 6,
+
+ SES_STATUS_AUDIBLE_ALARM_REMIND_BYTE = 2,
+ SES_STATUS_AUDIBLE_ALARM_REMIND_MASK = 0x10,
+ SES_STATUS_AUDIBLE_ALARM_REMIND_SHIFT = 4,
+
+ SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_BYTE = 2,
+ SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_MASK = 0x0F,
+ SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_SHIFT = 0,
+ SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_INFO = 0x08,
+ SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_NON_CRIT = 0x04,
+ SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_CRIT = 0x02,
+ SES_STATUS_AUDIBLE_ALARM_TONE_INDICATOR_UNRECOV = 0x01
+};
+
+#define GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_audible_alarm, SES_STATUS_AUDIBLE_ALARM, LCASE, UCASE)
+GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(rqst_mute, RQST_MUTE)
+GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(muted, MUTED)
+GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(remind, REMIND)
+GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS(tone_indicator, TONE_INDICATOR)
+#undef GEN_SES_STATUS_AUDIBLE_ALARM_ACCESSORS
+
+/*---------- Enclosure Services Statusler Electronics Status Element ---------*/
+struct ses_status_ecc_electronics {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_ecc_electronics_field_data {
+ SES_STATUS_ECC_ELECTRONICS_IDENT_BYTE = 0,
+ SES_STATUS_ECC_ELECTRONICS_IDENT_MASK = 0x80,
+ SES_STATUS_ECC_ELECTRONICS_IDENT_SHIFT = 7,
+
+ SES_STATUS_ECC_ELECTRONICS_FAIL_BYTE = 0,
+ SES_STATUS_ECC_ELECTRONICS_FAIL_MASK = 0x40,
+ SES_STATUS_ECC_ELECTRONICS_FAIL_SHIFT = 6,
+
+ SES_STATUS_ECC_ELECTRONICS_REPORT_BYTE = 1,
+ SES_STATUS_ECC_ELECTRONICS_REPORT_MASK = 0x01,
+ SES_STATUS_ECC_ELECTRONICS_REPORT_SHIFT = 0,
+
+ SES_STATUS_ECC_ELECTRONICS_HOT_SWAP_BYTE = 2,
+ SES_STATUS_ECC_ELECTRONICS_HOT_SWAP_MASK = 0x80,
+ SES_STATUS_ECC_ELECTRONICS_HOT_SWAP_SHIFT = 7
+};
+
+#define GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_ecc_electronics, SES_STATUS_ECC_ELECTRONICS, \
+ LCASE, UCASE)
+GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS(report, REPORT)
+GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS(hot_swap, HOT_SWAP)
+#undef GEN_SES_STATUS_ECC_ELECTRONICS_ACCESSORS
+
+/*------------ SCSI Services Statusler Electronics Status Element ------------*/
+struct ses_status_scc_electronics {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_scc_electronics_field_data {
+ SES_STATUS_SCC_ELECTRONICS_IDENT_BYTE = 0,
+ SES_STATUS_SCC_ELECTRONICS_IDENT_MASK = 0x80,
+ SES_STATUS_SCC_ELECTRONICS_IDENT_SHIFT = 7,
+
+ SES_STATUS_SCC_ELECTRONICS_FAIL_BYTE = 0,
+ SES_STATUS_SCC_ELECTRONICS_FAIL_MASK = 0x40,
+ SES_STATUS_SCC_ELECTRONICS_FAIL_SHIFT = 6,
+
+ SES_STATUS_SCC_ELECTRONICS_REPORT_BYTE = 1,
+ SES_STATUS_SCC_ELECTRONICS_REPORT_MASK = 0x01,
+ SES_STATUS_SCC_ELECTRONICS_REPORT_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_SCC_ELECTRONICS_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_scc_electronics, SES_STATUS_SCC_ELECTRONICS, \
+ LCASE, UCASE)
+GEN_SES_STATUS_SCC_ELECTRONICS_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_SCC_ELECTRONICS_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_SCC_ELECTRONICS_ACCESSORS(report, REPORT)
+#undef GEN_SES_STATUS_SCC_ELECTRONICS_ACCESSORS
+
+/*--------------------- Nonvolatile Cache Status Element ---------------------*/
+struct ses_status_nv_cache {
+ struct ses_status_common common;
+ uint8_t bytes[1];
+ uint8_t cache_size[2];
+};
+
+enum ses_status_nv_cache_field_data {
+ SES_STATUS_NV_CACHE_IDENT_BYTE = 0,
+ SES_STATUS_NV_CACHE_IDENT_MASK = 0x80,
+ SES_STATUS_NV_CACHE_IDENT_SHIFT = 7,
+
+ SES_STATUS_NV_CACHE_FAIL_BYTE = 0,
+ SES_STATUS_NV_CACHE_FAIL_MASK = 0x40,
+ SES_STATUS_NV_CACHE_FAIL_SHIFT = 6,
+
+ SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_BYTE = 0,
+ SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_MASK = 0x03,
+ SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_SHIFT = 0,
+ SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_BYTES = 0x0,
+ SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_KBYTES = 0x1,
+ SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_MBYTES = 0x2,
+ SES_STATUS_NV_CACHE_SIZE_MULTIPLIER_GBYTES = 0x3
+};
+
+#define GEN_SES_STATUS_NV_CACHE_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_nv_cache, SES_STATUS_NV_CACHE, LCASE, UCASE)
+GEN_SES_STATUS_NV_CACHE_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_NV_CACHE_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_NV_CACHE_ACCESSORS(size_multiplier, SIZE_MULTIPLIER)
+#undef GEN_SES_STATUS_NV_CACHE_ACCESSORS
+
+static inline uintmax_t
+ses_status_nv_cache_get_cache_size(struct ses_status_nv_cache *elem)
+{
+ uintmax_t cache_size;
+ int multiplier;
+
+ /* Multiplier is in units of 2^10 */
+ cache_size = scsi_2btoul(elem->cache_size);
+ multiplier = 10 * ses_status_nv_cache_get_size_multiplier(elem);
+ return (cache_size << multiplier);
+}
+
+/*----------------- Invalid Operation Reason Status Element ------------------*/
+struct ses_status_invalid_op_reason {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_invalid_op_field_data {
+ SES_STATUS_INVALID_OP_REASON_TYPE_BYTE = 0,
+ SES_STATUS_INVALID_OP_REASON_TYPE_MASK = 0xC0,
+ SES_STATUS_INVALID_OP_REASON_TYPE_SHIFT = 6,
+ SES_STATUS_INVALID_OP_REASON_TYPE_PC_ERROR = 0x00,
+ SES_STATUS_INVALID_OP_REASON_TYPE_PF_ERROR = 0x01,
+ SES_STATUS_INVALID_OP_REASON_TYPE_VS_ERROR = 0x03,
+
+ SES_STATUS_INVALID_OP_REASON_PC_ERROR_PC_NOT_SUPPORTED_BYTE = 0,
+ SES_STATUS_INVALID_OP_REASON_PC_ERROR_PC_NOT_SUPPORTED_MASK = 0x01,
+ SES_STATUS_INVALID_OP_REASON_PC_ERROR_PC_NOT_SUPPORTED_SHIFT = 0,
+
+ SES_STATUS_INVALID_OP_REASON_PF_ERROR_BIT_NUMBER_BYTE = 0,
+ SES_STATUS_INVALID_OP_REASON_PF_ERROR_BIT_NUMBER_MASK = 0x03,
+ SES_STATUS_INVALID_OP_REASON_PF_ERROR_BIT_NUMBER_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_INVALID_OP_REASON_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_invalid_op_reason, SES_STATUS_INVALID_OP_REASON, \
+ LCASE, UCASE)
+GEN_SES_STATUS_INVALID_OP_REASON_ACCESSORS(type, TYPE)
+GEN_SES_STATUS_INVALID_OP_REASON_ACCESSORS(pc_error_pc_not_supported,
+ PC_ERROR_PC_NOT_SUPPORTED)
+GEN_SES_STATUS_INVALID_OP_REASON_ACCESSORS(pf_error_bit_number,
+ PF_ERROR_BIT_NUMBER)
+#undef GEN_SES_STATUS_INVALID_OP_ACCESSORS
+
+/*--------------- Uninterruptible Power Supply Status Element ----------------*/
+struct ses_status_ups {
+ struct ses_status_common common;
+ /* Minutes of remaining capacity. */
+ uint8_t battery_status;
+ uint8_t bytes[2];
+};
+
+enum ses_status_ups_field_data {
+ SES_STATUS_UPS_AC_LO_BYTE = 0,
+ SES_STATUS_UPS_AC_LO_MASK = 0x80,
+ SES_STATUS_UPS_AC_LO_SHIFT = 7,
+
+ SES_STATUS_UPS_AC_HI_BYTE = 0,
+ SES_STATUS_UPS_AC_HI_MASK = 0x40,
+ SES_STATUS_UPS_AC_HI_SHIFT = 6,
+
+ SES_STATUS_UPS_AC_QUAL_BYTE = 0,
+ SES_STATUS_UPS_AC_QUAL_MASK = 0x20,
+ SES_STATUS_UPS_AC_QUAL_SHIFT = 5,
+
+ SES_STATUS_UPS_AC_FAIL_BYTE = 0,
+ SES_STATUS_UPS_AC_FAIL_MASK = 0x10,
+ SES_STATUS_UPS_AC_FAIL_SHIFT = 4,
+
+ SES_STATUS_UPS_DC_FAIL_BYTE = 0,
+ SES_STATUS_UPS_DC_FAIL_MASK = 0x08,
+ SES_STATUS_UPS_DC_FAIL_SHIFT = 3,
+
+ SES_STATUS_UPS_UPS_FAIL_BYTE = 0,
+ SES_STATUS_UPS_UPS_FAIL_MASK = 0x04,
+ SES_STATUS_UPS_UPS_FAIL_SHIFT = 2,
+
+ SES_STATUS_UPS_WARN_BYTE = 0,
+ SES_STATUS_UPS_WARN_MASK = 0x02,
+ SES_STATUS_UPS_WARN_SHIFT = 1,
+
+ SES_STATUS_UPS_INTF_FAIL_BYTE = 0,
+ SES_STATUS_UPS_INTF_FAIL_MASK = 0x01,
+ SES_STATUS_UPS_INTF_FAIL_SHIFT = 0,
+
+ SES_STATUS_UPS_IDENT_BYTE = 0,
+ SES_STATUS_UPS_IDENT_MASK = 0x80,
+ SES_STATUS_UPS_IDENT_SHIFT = 7,
+
+ SES_STATUS_UPS_FAIL_BYTE = 1,
+ SES_STATUS_UPS_FAIL_MASK = 0x40,
+ SES_STATUS_UPS_FAIL_SHIFT = 6,
+
+ SES_STATUS_UPS_BATT_FAIL_BYTE = 1,
+ SES_STATUS_UPS_BATT_FAIL_MASK = 0x02,
+ SES_STATUS_UPS_BATT_FAIL_SHIFT = 1,
+
+ SES_STATUS_UPS_BPF_BYTE = 1,
+ SES_STATUS_UPS_BPF_MASK = 0x01,
+ SES_STATUS_UPS_BPF_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_UPS_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_ups, SES_STATUS_UPS, LCASE, UCASE)
+GEN_SES_STATUS_UPS_ACCESSORS(ac_lo, AC_LO)
+GEN_SES_STATUS_UPS_ACCESSORS(ac_hi, AC_HI)
+GEN_SES_STATUS_UPS_ACCESSORS(ac_qual, AC_QUAL)
+GEN_SES_STATUS_UPS_ACCESSORS(ac_fail, AC_FAIL)
+GEN_SES_STATUS_UPS_ACCESSORS(dc_fail, DC_FAIL)
+GEN_SES_STATUS_UPS_ACCESSORS(ups_fail, UPS_FAIL)
+GEN_SES_STATUS_UPS_ACCESSORS(warn, WARN)
+GEN_SES_STATUS_UPS_ACCESSORS(intf_fail, INTF_FAIL)
+GEN_SES_STATUS_UPS_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_UPS_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_UPS_ACCESSORS(batt_fail, BATT_FAIL)
+GEN_SES_STATUS_UPS_ACCESSORS(bpf, BPF)
+#undef GEN_SES_STATUS_UPS_ACCESSORS
+
+/*-------------------------- Display Status Element --------------------------*/
+struct ses_status_display {
+ struct ses_status_common common;
+ uint8_t bytes[1];
+ uint8_t display_character[2];
+};
+
+enum ses_status_display_field_data {
+ SES_STATUS_DISPLAY_IDENT_BYTE = 0,
+ SES_STATUS_DISPLAY_IDENT_MASK = 0x80,
+ SES_STATUS_DISPLAY_IDENT_SHIFT = 7,
+
+ SES_STATUS_DISPLAY_FAIL_BYTE = 0,
+ SES_STATUS_DISPLAY_FAIL_MASK = 0x40,
+ SES_STATUS_DISPLAY_FAIL_SHIFT = 6,
+
+ SES_STATUS_DISPLAY_DISPLAY_MODE_BYTE = 0,
+ SES_STATUS_DISPLAY_DISPLAY_MODE_MASK = 0x03,
+ SES_STATUS_DISPLAY_DISPLAY_MODE_SHIFT = 6,
+ SES_STATUS_DISPLAY_DISPLAY_MODE_DC_FIELD_UNSUPP = 0x0,
+ SES_STATUS_DISPLAY_DISPLAY_MODE_DC_FIELD_SUPP = 0x1,
+ SES_STATUS_DISPLAY_DISPLAY_MODE_DC_FIELD = 0x2
+};
+
+#define GEN_SES_STATUS_DISPLAY_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_display, SES_STATUS_DISPLAY, LCASE, UCASE)
+GEN_SES_STATUS_DISPLAY_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_DISPLAY_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_DISPLAY_ACCESSORS(display_mode, DISPLAY_MODE)
+#undef GEN_SES_STATUS_DISPLAY_ACCESSORS
+
+/*----------------------- Key Pad Entry Status Element -----------------------*/
+struct ses_status_key_pad_entry {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_key_pad_entry_field_data {
+ SES_STATUS_KEY_PAD_ENTRY_IDENT_BYTE = 0,
+ SES_STATUS_KEY_PAD_ENTRY_IDENT_MASK = 0x80,
+ SES_STATUS_KEY_PAD_ENTRY_IDENT_SHIFT = 7,
+
+ SES_STATUS_KEY_PAD_ENTRY_FAIL_BYTE = 0,
+ SES_STATUS_KEY_PAD_ENTRY_FAIL_MASK = 0x40,
+ SES_STATUS_KEY_PAD_ENTRY_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_STATUS_KEY_PAD_ENTRY_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_key_pad_entry, SES_STATUS_KEY_PAD_ENTRY, LCASE, UCASE)
+GEN_SES_STATUS_KEY_PAD_ENTRY_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_KEY_PAD_ENTRY_ACCESSORS(fail, FAIL)
+#undef GEN_SES_STATUS_KEY_PAD_ENTRY_ACCESSORS
+
+/*------------------------- Enclosure Status Element -------------------------*/
+struct ses_status_enclosure {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_enclosure_field_data {
+ SES_STATUS_ENCLOSURE_IDENT_BYTE = 0,
+ SES_STATUS_ENCLOSURE_IDENT_MASK = 0x80,
+ SES_STATUS_ENCLOSURE_IDENT_SHIFT = 7,
+
+ SES_STATUS_ENCLOSURE_TIME_UNTIL_POWER_CYCLE_BYTE = 1,
+ SES_STATUS_ENCLOSURE_TIME_UNTIL_POWER_CYCLE_MASK = 0xFC,
+ SES_STATUS_ENCLOSURE_TIME_UNTIL_POWER_CYCLE_SHIFT = 2,
+
+ SES_STATUS_ENCLOSURE_FAIL_BYTE = 1,
+ SES_STATUS_ENCLOSURE_FAIL_MASK = 0x02,
+ SES_STATUS_ENCLOSURE_FAIL_SHIFT = 1,
+
+ SES_STATUS_ENCLOSURE_WARN_BYTE = 1,
+ SES_STATUS_ENCLOSURE_WARN_MASK = 0x01,
+ SES_STATUS_ENCLOSURE_WARN_SHIFT = 0,
+
+ SES_STATUS_ENCLOSURE_REQUESTED_POWER_OFF_DURATION_BYTE = 2,
+ SES_STATUS_ENCLOSURE_REQUESTED_POWER_OFF_DURATION_MASK = 0xFC,
+ SES_STATUS_ENCLOSURE_REQUESTED_POWER_OFF_DURATION_SHIFT = 2,
+ SES_STATUS_ENCLOSURE_REQUESTED_POWER_OFF_DURATION_MAX_AUTO = 60,
+ SES_STATUS_ENCLOSURE_REQUESTED_POWER_OFF_DURATION_MANUAL = 63,
+
+ SES_STATUS_ENCLOSURE_REQUESTED_FAIL_BYTE = 2,
+ SES_STATUS_ENCLOSURE_REQUESTED_FAIL_MASK = 0x02,
+ SES_STATUS_ENCLOSURE_REQUESTED_FAIL_SHIFT = 1,
+
+ SES_STATUS_ENCLOSURE_REQUESTED_WARN_BYTE = 2,
+ SES_STATUS_ENCLOSURE_REQUESTED_WARN_MASK = 0x01,
+ SES_STATUS_ENCLOSURE_REQUESTED_WARN_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_ENCLOSURE_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_enclosure, SES_STATUS_ENCLOSURE, LCASE, UCASE)
+GEN_SES_STATUS_ENCLOSURE_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_ENCLOSURE_ACCESSORS(time_until_power_cycle,
+ TIME_UNTIL_POWER_CYCLE)
+GEN_SES_STATUS_ENCLOSURE_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_ENCLOSURE_ACCESSORS(warn, WARN)
+GEN_SES_STATUS_ENCLOSURE_ACCESSORS(requested_power_off_duration,
+ REQUESTED_POWER_OFF_DURATION)
+GEN_SES_STATUS_ENCLOSURE_ACCESSORS(requested_fail, REQUESTED_FAIL)
+GEN_SES_STATUS_ENCLOSURE_ACCESSORS(requested_warn, REQUESTED_WARN)
+#undef GEN_SES_STATUS_ENCLOSURE_ACCESSORS
+
+/*------------------- SCSI Port/Transceiver Status Element -------------------*/
+struct ses_status_scsi_port_or_xcvr {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_scsi_port_or_xcvr_field_data {
+ SES_STATUS_SCSI_PORT_OR_XCVR_IDENT_BYTE = 0,
+ SES_STATUS_SCSI_PORT_OR_XCVR_IDENT_MASK = 0x80,
+ SES_STATUS_SCSI_PORT_OR_XCVR_IDENT_SHIFT = 7,
+
+ SES_STATUS_SCSI_PORT_OR_XCVR_FAIL_BYTE = 0,
+ SES_STATUS_SCSI_PORT_OR_XCVR_FAIL_MASK = 0x40,
+ SES_STATUS_SCSI_PORT_OR_XCVR_FAIL_SHIFT = 6,
+
+ SES_STATUS_SCSI_PORT_OR_XCVR_REPORT_BYTE = 1,
+ SES_STATUS_SCSI_PORT_OR_XCVR_REPORT_MASK = 0x01,
+ SES_STATUS_SCSI_PORT_OR_XCVR_REPORT_SHIFT = 0,
+
+ SES_STATUS_SCSI_PORT_OR_XCVR_DISABLED_BYTE = 2,
+ SES_STATUS_SCSI_PORT_OR_XCVR_DISABLED_MASK = 0x10,
+ SES_STATUS_SCSI_PORT_OR_XCVR_DISABLED_SHIFT = 4,
+
+ SES_STATUS_SCSI_PORT_OR_XCVR_LOL_BYTE = 2,
+ SES_STATUS_SCSI_PORT_OR_XCVR_LOL_MASK = 0x02,
+ SES_STATUS_SCSI_PORT_OR_XCVR_LOL_SHIFT = 1,
+
+ SES_STATUS_SCSI_PORT_OR_XCVR_XMIT_FAIL_BYTE = 2,
+ SES_STATUS_SCSI_PORT_OR_XCVR_XMIT_FAIL_MASK = 0x01,
+ SES_STATUS_SCSI_PORT_OR_XCVR_XMIT_FAIL_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_scsi_port_or_xcvr, SES_STATUS_SCSI_PORT_OR_XCVR,\
+ LCASE, UCASE)
+GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(report, REPORT)
+GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(disable, DISABLED)
+GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(lol, LOL)
+GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS(xmit_fail, XMIT_FAIL)
+#undef GEN_SES_STATUS_SCSI_PORT_OR_XCVR_ACCESSORS
+
+/*------------------------- Language Status Element --------------------------*/
+struct ses_status_language {
+ struct ses_status_common common;
+ uint8_t bytes[1];
+ uint8_t language_code[2];
+};
+
+enum ses_status_language_field_data {
+ SES_STATUS_LANGUAGE_IDENT_BYTE = 0,
+ SES_STATUS_LANGUAGE_IDENT_MASK = 0x80,
+ SES_STATUS_LANGUAGE_IDENT_SHIFT = 7
+};
+
+#define GEN_SES_STATUS_LANGUAGE_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_language, SES_STATUS_LANGUAGE, LCASE, UCASE)
+GEN_SES_STATUS_LANGUAGE_ACCESSORS(ident, IDENT)
+#undef GEN_SES_STATUS_LANGUAGE_ACCESSORS
+
+/*-------------------- Communication Port Status Element ---------------------*/
+struct ses_status_comm_port {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_comm_port_field_data {
+ SES_STATUS_COMM_PORT_IDENT_BYTE = 0,
+ SES_STATUS_COMM_PORT_IDENT_MASK = 0x80,
+ SES_STATUS_COMM_PORT_IDENT_SHIFT = 7,
+
+ SES_STATUS_COMM_PORT_FAIL_BYTE = 0,
+ SES_STATUS_COMM_PORT_FAIL_MASK = 0x40,
+ SES_STATUS_COMM_PORT_FAIL_SHIFT = 6,
+
+ SES_STATUS_COMM_PORT_DISABLED_BYTE = 2,
+ SES_STATUS_COMM_PORT_DISABLED_MASK = 0x01,
+ SES_STATUS_COMM_PORT_DISABLED_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_COMM_PORT_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_comm_port, SES_STATUS_COMM_PORT, LCASE, UCASE)
+GEN_SES_STATUS_COMM_PORT_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_COMM_PORT_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_COMM_PORT_ACCESSORS(disabled, DISABLED)
+#undef GEN_SES_STATUS_COMM_PORT_ACCESSORS
+
+/*---------------------- Voltage Sensor Status Element -----------------------*/
+struct ses_status_voltage_sensor {
+ struct ses_status_common common;
+ uint8_t bytes[1];
+ uint8_t voltage[2];
+};
+
+enum ses_status_voltage_sensor_field_data {
+ SES_STATUS_VOLTAGE_SENSOR_IDENT_BYTE = 0,
+ SES_STATUS_VOLTAGE_SENSOR_IDENT_MASK = 0x80,
+ SES_STATUS_VOLTAGE_SENSOR_IDENT_SHIFT = 7,
+
+ SES_STATUS_VOLTAGE_SENSOR_FAIL_BYTE = 0,
+ SES_STATUS_VOLTAGE_SENSOR_FAIL_MASK = 0x40,
+ SES_STATUS_VOLTAGE_SENSOR_FAIL_SHIFT = 6,
+
+ SES_STATUS_VOLTAGE_SENSOR_WARN_OVER_BYTE = 0,
+ SES_STATUS_VOLTAGE_SENSOR_WARN_OVER_MASK = 0x08,
+ SES_STATUS_VOLTAGE_SENSOR_WARN_OVER_SHIFT = 3,
+
+ SES_STATUS_VOLTAGE_SENSOR_WARN_UNDER_BYTE = 0,
+ SES_STATUS_VOLTAGE_SENSOR_WARN_UNDER_MASK = 0x04,
+ SES_STATUS_VOLTAGE_SENSOR_WARN_UNDER_SHIFT = 2,
+
+ SES_STATUS_VOLTAGE_SENSOR_CRIT_OVER_BYTE = 0,
+ SES_STATUS_VOLTAGE_SENSOR_CRIT_OVER_MASK = 0x02,
+ SES_STATUS_VOLTAGE_SENSOR_CRIT_OVER_SHIFT = 1,
+
+ SES_STATUS_VOLTAGE_SENSOR_CRIT_UNDER_BYTE = 0,
+ SES_STATUS_VOLTAGE_SENSOR_CRIT_UNDER_MASK = 0x01,
+ SES_STATUS_VOLTAGE_SENSOR_CRIT_UNDER_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_voltage_sensor, SES_STATUS_VOLTAGE_SENSOR, \
+ LCASE, UCASE)
+GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(warn_over, WARN_OVER)
+GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(warn_under, WARN_UNDER)
+GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(crit_over, CRIT_OVER)
+GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS(crit_under, CRIT_UNDER)
+#undef GEN_SES_STATUS_VOLTAGE_SENSOR_ACCESSORS
+
+/*---------------------- Current Sensor Status Element -----------------------*/
+struct ses_status_current_sensor {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_current_sensor_field_data {
+ SES_STATUS_CURRENT_SENSOR_IDENT_BYTE = 0,
+ SES_STATUS_CURRENT_SENSOR_IDENT_MASK = 0x80,
+ SES_STATUS_CURRENT_SENSOR_IDENT_SHIFT = 7,
+
+ SES_STATUS_CURRENT_SENSOR_FAIL_BYTE = 0,
+ SES_STATUS_CURRENT_SENSOR_FAIL_MASK = 0x40,
+ SES_STATUS_CURRENT_SENSOR_FAIL_SHIFT = 6,
+
+ SES_STATUS_CURRENT_SENSOR_WARN_OVER_BYTE = 0,
+ SES_STATUS_CURRENT_SENSOR_WARN_OVER_MASK = 0x08,
+ SES_STATUS_CURRENT_SENSOR_WARN_OVER_SHIFT = 3,
+
+ SES_STATUS_CURRENT_SENSOR_CRIT_OVER_BYTE = 0,
+ SES_STATUS_CURRENT_SENSOR_CRIT_OVER_MASK = 0x02,
+ SES_STATUS_CURRENT_SENSOR_CRIT_OVER_SHIFT = 1
+};
+
+#define GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_current_sensor, SES_STATUS_CURRENT_SENSOR, \
+ LCASE, UCASE)
+GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS(warn_over, WARN_OVER)
+GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS(crit_over, CRIT_OVER)
+#undef GEN_SES_STATUS_CURRENT_SENSOR_ACCESSORS
+
+/*--------------------- SCSI Target Port Status Element ----------------------*/
+struct ses_status_target_port {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_scsi_target_port_field_data {
+ SES_STATUS_TARGET_PORT_IDENT_BYTE = 0,
+ SES_STATUS_TARGET_PORT_IDENT_MASK = 0x80,
+ SES_STATUS_TARGET_PORT_IDENT_SHIFT = 7,
+
+ SES_STATUS_TARGET_PORT_FAIL_BYTE = 0,
+ SES_STATUS_TARGET_PORT_FAIL_MASK = 0x40,
+ SES_STATUS_TARGET_PORT_FAIL_SHIFT = 6,
+
+ SES_STATUS_TARGET_PORT_REPORT_BYTE = 1,
+ SES_STATUS_TARGET_PORT_REPORT_MASK = 0x01,
+ SES_STATUS_TARGET_PORT_REPORT_SHIFT = 0,
+
+ SES_STATUS_TARGET_PORT_ENABLED_BYTE = 2,
+ SES_STATUS_TARGET_PORT_ENABLED_MASK = 0x01,
+ SES_STATUS_TARGET_PORT_ENABLED_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_TARGET_PORT_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_target_port, SES_STATUS_TARGET_PORT, LCASE, UCASE)
+GEN_SES_STATUS_TARGET_PORT_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_TARGET_PORT_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_TARGET_PORT_ACCESSORS(report, REPORT)
+GEN_SES_STATUS_TARGET_PORT_ACCESSORS(enabled, ENABLED)
+#undef GEN_SES_STATUS_TARGET_PORT_ACCESSORS
+
+/*-------------------- SCSI Initiator Port Status Element --------------------*/
+struct ses_status_initiator_port {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_scsi_initiator_port_field_data {
+ SES_STATUS_INITIATOR_PORT_IDENT_BYTE = 0,
+ SES_STATUS_INITIATOR_PORT_IDENT_MASK = 0x80,
+ SES_STATUS_INITIATOR_PORT_IDENT_SHIFT = 7,
+
+ SES_STATUS_INITIATOR_PORT_FAIL_BYTE = 0,
+ SES_STATUS_INITIATOR_PORT_FAIL_MASK = 0x40,
+ SES_STATUS_INITIATOR_PORT_FAIL_SHIFT = 6,
+
+ SES_STATUS_INITIATOR_PORT_REPORT_BYTE = 1,
+ SES_STATUS_INITIATOR_PORT_REPORT_MASK = 0x01,
+ SES_STATUS_INITIATOR_PORT_REPORT_SHIFT = 0,
+
+ SES_STATUS_INITIATOR_PORT_ENABLED_BYTE = 2,
+ SES_STATUS_INITIATOR_PORT_ENABLED_MASK = 0x01,
+ SES_STATUS_INITIATOR_PORT_ENABLED_SHIFT = 0
+};
+
+#define GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_initiator_port, SES_STATUS_INITIATOR_PORT, \
+ LCASE, UCASE)
+GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS(fail, FAIL)
+GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS(report, REPORT)
+GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS(enabled, ENABLED)
+#undef GEN_SES_STATUS_INITIATOR_PORT_ACCESSORS
+
+/*-------------------- Simple Subenclosure Status Element --------------------*/
+struct ses_status_simple_subses {
+ struct ses_status_common common;
+ uint8_t bytes[2];
+ uint8_t short_enclosure_status;
+};
+
+enum ses_status_simple_subses_field_data {
+ SES_STATUS_SIMPlE_SUBSES_IDENT_BYTE = 0,
+ SES_STATUS_SIMPlE_SUBSES_IDENT_MASK = 0x80,
+ SES_STATUS_SIMPlE_SUBSES_IDENT_SHIFT = 7,
+
+ SES_STATUS_SIMPlE_SUBSES_FAIL_BYTE = 0,
+ SES_STATUS_SIMPlE_SUBSES_FAIL_MASK = 0x40,
+ SES_STATUS_SIMPlE_SUBSES_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_STATUS_SIMPlE_SUBSES_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_simple_subses, SES_STATUS_SIMPlE_SUBSES, \
+ LCASE, UCASE)
+GEN_SES_STATUS_SIMPlE_SUBSES_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_SIMPlE_SUBSES_ACCESSORS(fail, FAIL)
+#undef GEN_SES_STATUS_SIMPlE_SUBSES_ACCESSORS
+
+/*----------------------- SAS Expander Status Element ------------------------*/
+struct ses_status_sas_expander {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_sas_expander_field_data {
+ SES_STATUS_SAS_EXPANDER_IDENT_BYTE = 0,
+ SES_STATUS_SAS_EXPANDER_IDENT_MASK = 0x80,
+ SES_STATUS_SAS_EXPANDER_IDENT_SHIFT = 7,
+
+ SES_STATUS_SAS_EXPANDER_FAIL_BYTE = 0,
+ SES_STATUS_SAS_EXPANDER_FAIL_MASK = 0x40,
+ SES_STATUS_SAS_EXPANDER_FAIL_SHIFT = 6
+};
+
+#define GEN_SES_STATUS_SAS_EXPANDER_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_sas_expander, SES_STATUS_SAS_EXPANDER, LCASE, UCASE)
+GEN_SES_STATUS_SAS_EXPANDER_ACCESSORS(ident, IDENT)
+GEN_SES_STATUS_SAS_EXPANDER_ACCESSORS(fail, FAIL)
+#undef GEN_SES_STATUS_SAS_EXPANDER_ACCESSORS
+
+/*----------------------- SAS Connector Status Element -----------------------*/
+struct ses_status_sas_connector {
+ struct ses_status_common common;
+ uint8_t bytes[3];
+};
+
+enum ses_status_sas_connector_field_data {
+ SES_STATUS_SAS_CONNECTOR_IDENT_BYTE = 0,
+ SES_STATUS_SAS_CONNECTOR_IDENT_MASK = 0x80,
+ SES_STATUS_SAS_CONNECTOR_IDENT_SHIFT = 7,
+
+ SES_STATUS_SAS_CONNECTOR_TYPE_BYTE = 0,
+ SES_STATUS_SAS_CONNECTOR_TYPE_MASK = 0x7F,
+ SES_STATUS_SAS_CONNECTOR_TYPE_SHIFT = 0,
+
+ SES_STATUS_SAS_CONNECTOR_PHYS_LINK_BYTE = 1,
+ SES_STATUS_SAS_CONNECTOR_PHYS_LINK_MASK = 0xFF,
+ SES_STATUS_SAS_CONNECTOR_PHYS_LINK_SHIFT = 0,
+ SES_STATUS_SAS_CONNECTOR_PHYS_LINK_ALL = 0xFF,
+
+ SES_STATUS_SAS_CONNECTOR_FAIL_BYTE = 2,
+ SES_STATUS_SAS_CONNECTOR_FAIL_MASK = 0x40,
+ SES_STATUS_SAS_CONNECTOR_FAIL_SHIFT = 6,
+};
+
+#define GEN_SES_STATUS_SAS_CONNECTOR_ACCESSORS(LCASE, UCASE) \
+ GEN_GETTER(ses_status_sas_connector, SES_STATUS_SAS_CONNECTOR, \
+ LCASE, UCASE)
+GEN_SES_STATUS_SAS_CONNECTOR_ACCESSORS(ide