pkgsrc-WIP-changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Modify drvctl.c to not read from /dev/drvctl but use information from devpubd because information of device-attach/device-detach sequence is missing, when devpubd is used this way, a fifo is created in /tmp the /libexec/devpubd-hooks/03-hal pushes correct sequence of attach/detach device into the fifo, than it is read by drvctl.c. Also a new /etc/rc.d/hal is modified so that drvctl.c does not block on read from an empty fifo. the Patch is in the patches directory => patch-hald_netbsd_drvctl.c



Module Name:	pkgsrc-wip
Committed By:	sergio lenzi <nervoso%k1.com.br@localhost>
Pushed By:	lenzi.sergio
Date:		Tue Sep 29 17:03:56 2020 -0300
Changeset:	cdb3d27492001f3f3ec7415cabb2eaf65f5d2d63

Added Files:
	hal/DESCR
	hal/MESSAGE.NetBSD
	hal/Makefile
	hal/PLIST
	hal/PLIST.DragonFly
	hal/PLIST.FreeBSD
	hal/PLIST.Linux
	hal/PLIST.NetBSD
	hal/buildlink3.mk
	hal/distinfo
	hal/files/03-hal
	hal/files/hal.sh
	hal/files/hald-netbsd/Makefile.am
	hal/files/hald-netbsd/addons/Makefile.am
	hal/files/hald-netbsd/addons/addon-storage.c
	hal/files/hald-netbsd/devinfo.c
	hal/files/hald-netbsd/devinfo.h
	hal/files/hald-netbsd/devinfo_acpi.h
	hal/files/hald-netbsd/devinfo_audio.c
	hal/files/hald-netbsd/devinfo_audio.h
	hal/files/hald-netbsd/devinfo_cpu.h
	hal/files/hald-netbsd/devinfo_mass.c
	hal/files/hald-netbsd/devinfo_mass.h
	hal/files/hald-netbsd/devinfo_misc.c
	hal/files/hald-netbsd/devinfo_misc.h
	hal/files/hald-netbsd/devinfo_optical.c
	hal/files/hald-netbsd/devinfo_optical.h
	hal/files/hald-netbsd/devinfo_pci.c
	hal/files/hald-netbsd/devinfo_pci.h
	hal/files/hald-netbsd/devinfo_storage.c
	hal/files/hald-netbsd/devinfo_storage.h
	hal/files/hald-netbsd/devinfo_usb.c
	hal/files/hald-netbsd/devinfo_usb.h
	hal/files/hald-netbsd/devinfo_video.c
	hal/files/hald-netbsd/devinfo_video.h
	hal/files/hald-netbsd/drvctl.c
	hal/files/hald-netbsd/drvctl.h
	hal/files/hald-netbsd/envsys.c
	hal/files/hald-netbsd/envsys.h
	hal/files/hald-netbsd/hal-file-monitor.c
	hal/files/hald-netbsd/hotplug.c
	hal/files/hald-netbsd/hotplug.h
	hal/files/hald-netbsd/osspec.c
	hal/files/hald-netbsd/osspec_netbsd.h
	hal/files/hald-netbsd/probing/Makefile.am
	hal/files/hald-netbsd/probing/cdutils.c
	hal/files/hald-netbsd/probing/cdutils.h
	hal/files/hald-netbsd/probing/fsutils.c
	hal/files/hald-netbsd/probing/fsutils.h
	hal/files/hald-netbsd/probing/probe-storage.c
	hal/files/hald-netbsd/probing/probe-volume.c
	hal/files/hald-netbsd/vfsstat.c
	hal/files/hald-netbsd/vfsstat.h
	hal/files/smf/hal.sh
	hal/files/smf/manifest.xml
	hal/files/tools-netbsd/Makefile.am
	hal/files/tools-netbsd/hal-system-power-reboot-netbsd
	hal/files/tools-netbsd/hal-system-power-shutdown-netbsd
	hal/files/tools-netbsd/hal-system-power-suspend-netbsd
	hal/patches/patch-Makefile.am
	hal/patches/patch-configure.in
	hal/patches/patch-fdi_policy_10osvendor_20-storage-methods.fdi
	hal/patches/patch-hald_Makefile.am
	hal/patches/patch-hald_device__info.c
	hal/patches/patch-hald_freebsd_addons_addon-mouse.c
	hal/patches/patch-hald_freebsd_addons_addon-storage.c
	hal/patches/patch-hald_freebsd_hf-ata.c
	hal/patches/patch-hald_freebsd_hf-devd.c
	hal/patches/patch-hald_freebsd_hf-pci.c
	hal/patches/patch-hald_freebsd_hf-storage.c
	hal/patches/patch-hald_freebsd_hf-usb.c
	hal/patches/patch-hald_freebsd_hf-usb2.c
	hal/patches/patch-hald_freebsd_hf-volume.c
	hal/patches/patch-hald_freebsd_libprobe_hfp-cdrom.c
	hal/patches/patch-hald_freebsd_probing_Makefile.am
	hal/patches/patch-hald_freebsd_probing_probe-hiddev.c
	hal/patches/patch-hald_freebsd_probing_probe-storage.c
	hal/patches/patch-hald_freebsd_probing_probe-usb2-device.c
	hal/patches/patch-hald_freebsd_probing_probe-usb2-interface.c
	hal/patches/patch-hald_freebsd_probing_probe-volume.c
	hal/patches/patch-hald_linux_addons_addon-acpi-buttons-toshiba.c
	hal/patches/patch-hald_linux_addons_addon-cpufreq.c
	hal/patches/patch-hald_linux_addons_addon-dell-backlight.cpp
	hal/patches/patch-hald_linux_addons_addon-generic-backlight.c
	hal/patches/patch-hald_linux_addons_addon-imac-backlight.c
	hal/patches/patch-hald_linux_addons_addon-input.c
	hal/patches/patch-hald_linux_addons_addon-ipw-killswitch.c
	hal/patches/patch-hald_linux_addons_addon-leds.c
	hal/patches/patch-hald_linux_addons_addon-macbookpro-backlight.c
	hal/patches/patch-hald_linux_addons_addon-omap-backlight.c
	hal/patches/patch-hald_linux_addons_addon-rfkill-killswitch.c
	hal/patches/patch-hald_linux_addons_addon-storage.c
	hal/patches/patch-hald_linux_addons_addon-usb-csr.c
	hal/patches/patch-hald_linux_probing_probe-video4linux.c
	hal/patches/patch-hald_netbsd_devinfo__mass.c
	hal/patches/patch-hald_netbsd_drvctl.c
	hal/patches/patch-libhal_libhal.c
	hal/patches/patch-policy_Makefile.am
	hal/patches/patch-tools_Makefile.am
	hal/patches/patch-tools_hal-luks-setup
	hal/patches/patch-tools_hal-luks-teardown
	hal/patches/patch-tools_hal-storage-mount.c
	hal/patches/patch-tools_hal-storage-shared.c
	hal/patches/patch-tools_hal-storage-unmount.c
	hal/patches/patch-tools_hal-system-power-pmu.c
	hal/patches/patch-tools_linux_Makefile.am

Log Message:
Modify drvctl.c to not read from /dev/drvctl but use information from devpubd because
information of device-attach/device-detach sequence is missing, when devpubd is used
this way, a fifo is created in /tmp the /libexec/devpubd-hooks/03-hal pushes correct
sequence of attach/detach device into the fifo, than it is read by drvctl.c. Also a new
/etc/rc.d/hal is modified so that drvctl.c does not block on read from an empty fifo.
the Patch is in the patches directory => patch-hald_netbsd_drvctl.c

To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=cdb3d27492001f3f3ec7415cabb2eaf65f5d2d63

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

diffstat:
 hal/DESCR                                          |   15 +
 hal/MESSAGE.NetBSD                                 |   16 +
 hal/Makefile                                       |  144 ++
 hal/PLIST                                          |  108 ++
 hal/PLIST.DragonFly                                |   15 +
 hal/PLIST.FreeBSD                                  |   17 +
 hal/PLIST.Linux                                    |   46 +
 hal/PLIST.NetBSD                                   |    8 +
 hal/buildlink3.mk                                  |   16 +
 hal/distinfo                                       |   53 +
 hal/files/03-hal                                   |   26 +
 hal/files/hal.sh                                   |   25 +
 hal/files/hald-netbsd/Makefile.am                  |   27 +
 hal/files/hald-netbsd/addons/Makefile.am           |   17 +
 hal/files/hald-netbsd/addons/addon-storage.c       |  516 ++++++
 hal/files/hald-netbsd/devinfo.c                    |  418 +++++
 hal/files/hald-netbsd/devinfo.h                    |   72 +
 hal/files/hald-netbsd/devinfo_acpi.h               |   44 +
 hal/files/hald-netbsd/devinfo_audio.c              |  233 +++
 hal/files/hald-netbsd/devinfo_audio.h              |   38 +
 hal/files/hald-netbsd/devinfo_cpu.h                |   19 +
 hal/files/hald-netbsd/devinfo_mass.c               |  418 +++++
 hal/files/hald-netbsd/devinfo_mass.h               |   37 +
 hal/files/hald-netbsd/devinfo_misc.c               |  168 ++
 hal/files/hald-netbsd/devinfo_misc.h               |   21 +
 hal/files/hald-netbsd/devinfo_optical.c            |  485 ++++++
 hal/files/hald-netbsd/devinfo_optical.h            |   20 +
 hal/files/hald-netbsd/devinfo_pci.c                |  122 ++
 hal/files/hald-netbsd/devinfo_pci.h                |   21 +
 hal/files/hald-netbsd/devinfo_storage.c            | 1671 ++++++++++++++++++++
 hal/files/hald-netbsd/devinfo_storage.h            |   30 +
 hal/files/hald-netbsd/devinfo_usb.c                |  229 +++
 hal/files/hald-netbsd/devinfo_usb.h                |   23 +
 hal/files/hald-netbsd/devinfo_video.c              |  125 ++
 hal/files/hald-netbsd/devinfo_video.h              |   36 +
 hal/files/hald-netbsd/drvctl.c                     |  303 ++++
 hal/files/hald-netbsd/drvctl.h                     |   24 +
 hal/files/hald-netbsd/envsys.c                     |  249 +++
 hal/files/hald-netbsd/envsys.h                     |   36 +
 hal/files/hald-netbsd/hal-file-monitor.c           |  821 ++++++++++
 hal/files/hald-netbsd/hotplug.c                    |  204 +++
 hal/files/hald-netbsd/hotplug.h                    |   58 +
 hal/files/hald-netbsd/osspec.c                     |  183 +++
 hal/files/hald-netbsd/osspec_netbsd.h              |   21 +
 hal/files/hald-netbsd/probing/Makefile.am          |   20 +
 hal/files/hald-netbsd/probing/cdutils.c            |  379 +++++
 hal/files/hald-netbsd/probing/cdutils.h            |   61 +
 hal/files/hald-netbsd/probing/fsutils.c            |  217 +++
 hal/files/hald-netbsd/probing/fsutils.h            |   25 +
 hal/files/hald-netbsd/probing/probe-storage.c      |  414 +++++
 hal/files/hald-netbsd/probing/probe-volume.c       |  629 ++++++++
 hal/files/hald-netbsd/vfsstat.c                    |  157 ++
 hal/files/hald-netbsd/vfsstat.h                    |   36 +
 hal/files/smf/hal.sh                               |   35 +
 hal/files/smf/manifest.xml                         |   79 +
 hal/files/tools-netbsd/Makefile.am                 |   40 +
 .../tools-netbsd/hal-system-power-reboot-netbsd    |   19 +
 .../tools-netbsd/hal-system-power-shutdown-netbsd  |   19 +
 .../tools-netbsd/hal-system-power-suspend-netbsd   |   29 +
 hal/patches/patch-Makefile.am                      |   13 +
 hal/patches/patch-configure.in                     |  100 ++
 ...ch-fdi_policy_10osvendor_20-storage-methods.fdi |   98 ++
 hal/patches/patch-hald_Makefile.am                 |   12 +
 hal/patches/patch-hald_device__info.c              |   20 +
 .../patch-hald_freebsd_addons_addon-mouse.c        |   14 +
 .../patch-hald_freebsd_addons_addon-storage.c      |  140 ++
 hal/patches/patch-hald_freebsd_hf-ata.c            |   16 +
 hal/patches/patch-hald_freebsd_hf-devd.c           |   40 +
 hal/patches/patch-hald_freebsd_hf-pci.c            |   16 +
 hal/patches/patch-hald_freebsd_hf-storage.c        |   14 +
 hal/patches/patch-hald_freebsd_hf-usb.c            |   47 +
 hal/patches/patch-hald_freebsd_hf-usb2.c           |  415 +++++
 hal/patches/patch-hald_freebsd_hf-volume.c         |   18 +
 .../patch-hald_freebsd_libprobe_hfp-cdrom.c        |   16 +
 hal/patches/patch-hald_freebsd_probing_Makefile.am |   11 +
 .../patch-hald_freebsd_probing_probe-hiddev.c      |   18 +
 .../patch-hald_freebsd_probing_probe-storage.c     |   44 +
 .../patch-hald_freebsd_probing_probe-usb2-device.c |   44 +
 ...tch-hald_freebsd_probing_probe-usb2-interface.c |   18 +
 .../patch-hald_freebsd_probing_probe-volume.c      |  127 ++
 ...-hald_linux_addons_addon-acpi-buttons-toshiba.c |   13 +
 .../patch-hald_linux_addons_addon-cpufreq.c        |   12 +
 ...atch-hald_linux_addons_addon-dell-backlight.cpp |   13 +
 ...tch-hald_linux_addons_addon-generic-backlight.c |   13 +
 .../patch-hald_linux_addons_addon-imac-backlight.c |   13 +
 hal/patches/patch-hald_linux_addons_addon-input.c  |   14 +
 .../patch-hald_linux_addons_addon-ipw-killswitch.c |   13 +
 hal/patches/patch-hald_linux_addons_addon-leds.c   |   13 +
 ...-hald_linux_addons_addon-macbookpro-backlight.c |   13 +
 .../patch-hald_linux_addons_addon-omap-backlight.c |   13 +
 ...tch-hald_linux_addons_addon-rfkill-killswitch.c |   13 +
 .../patch-hald_linux_addons_addon-storage.c        |   13 +
 .../patch-hald_linux_addons_addon-usb-csr.c        |   13 +
 .../patch-hald_linux_probing_probe-video4linux.c   |   43 +
 hal/patches/patch-hald_netbsd_devinfo__mass.c      |   12 +
 hal/patches/patch-hald_netbsd_drvctl.c             |  111 ++
 hal/patches/patch-libhal_libhal.c                  |   15 +
 hal/patches/patch-policy_Makefile.am               |   13 +
 hal/patches/patch-tools_Makefile.am                |   30 +
 hal/patches/patch-tools_hal-luks-setup             |   22 +
 hal/patches/patch-tools_hal-luks-teardown          |   22 +
 hal/patches/patch-tools_hal-storage-mount.c        |  134 ++
 hal/patches/patch-tools_hal-storage-shared.c       |  138 ++
 hal/patches/patch-tools_hal-storage-unmount.c      |   23 +
 hal/patches/patch-tools_hal-system-power-pmu.c     |   37 +
 hal/patches/patch-tools_linux_Makefile.am          |   12 +
 106 files changed, 11359 insertions(+)

diffs:
diff --git a/hal/DESCR b/hal/DESCR
new file mode 100644
index 0000000000..988d7b66d9
--- /dev/null
+++ b/hal/DESCR
@@ -0,0 +1,15 @@
+What is the point of HAL?
+
+To merge information from various sources such that desktop applications can
+locate and use hardware devices. The point is that the exact set of
+information to merge varies by device and bus type. In order to do this, we
+need to define a format for the information, hence the HAL specification.
+
+We may read some stuff from the hardware itself, then add some info provided
+by the kernel, then add some metadata from some systemwide files, then add
+some data that has been obtained by the desktop and stored per-user, then
+look at some blacklist, and finally we have a complete picture of everything
+known about that particular device.
+
+An extra value is that we can do this in an operating system independent way.
+Stuff like this is important to the major desktop environments.
diff --git a/hal/MESSAGE.NetBSD b/hal/MESSAGE.NetBSD
new file mode 100644
index 0000000000..055de4ab32
--- /dev/null
+++ b/hal/MESSAGE.NetBSD
@@ -0,0 +1,16 @@
+===========================================================================
+$NetBSD: MESSAGE.NetBSD,v 1.2 2008/12/24 13:55:24 wiz Exp $
+
+For the NetBSD 5.0+ HAL backend to function properly, your kernel needs
+to include /dev/drvctl support. If the /dev/drvctl device node does not
+exist, run the following command:
+
+  # cd /dev
+  # sh MAKEDEV drvctl
+
+For proper kernel support, the following directive must be in your kernel
+config:
+
+  pseudo-device drvctl
+
+===========================================================================
diff --git a/hal/Makefile b/hal/Makefile
new file mode 100644
index 0000000000..be04e32924
--- /dev/null
+++ b/hal/Makefile
@@ -0,0 +1,144 @@
+# $NetBSD: Makefile,v 1.78 2016/09/17 15:33:59 richard Exp $
+
+DISTNAME=		hal-0.5.14
+PKGREVISION=		18
+CATEGORIES?=		sysutils mate
+MASTER_SITES=		http://hal.freedesktop.org/releases/
+EXTRACT_SUFX=		.tar.bz2
+
+MAINTAINER=		nervoso%k1.com.br@localhost
+HOMEPAGE=		http://hal.freedesktop.org/
+COMMENT=		FreeDesktop hardware abstraction layer
+LICENSE=		gnu-gpl-v2
+
+DEPENDS+=		pciids-[0-9]*:../../misc/pciids
+
+BUILD_DEFS+=		VARBASE PKG_SYSCONFBASE
+
+GNU_CONFIGURE=		YES
+USE_PKGLOCALEDIR=	YES
+USE_TOOLS+=		gmake intltool msgfmt perl pkg-config
+USE_TOOLS+=		autoconf automake autoreconf
+USE_LIBTOOL=		YES
+USE_LANGUAGES+=		c c++
+
+MAKE_DIRS+=		/media
+MAKE_DIRS+=		${VARBASE}/cache/hald
+SPECIAL_PERMS+=		${VARBASE}/cache/hald ${HAL_USER} ${HAL_GROUP} 0644
+
+EGDIR=			${PREFIX}/share/examples/hal
+
+CONF_FILES+=		${EGDIR}/hal.conf ${PKG_SYSCONFBASE}/dbus-1/system.d/hal.conf
+CONF_FILES_PERMS+=	${EGDIR}/03-hal /libexec/devpubd-hooks/03-hal \
+				${REAL_ROOT_USER} ${REAL_ROOT_GROUP} 0755
+
+CONFIGURE_ARGS+=        --sysconfdir=${PKG_SYSCONFBASE}
+CONFIGURE_ARGS+=	--localstatedir=${VARBASE}
+CONFIGURE_ARGS+=	--with-pci-ids=${PREFIX}/share/pciids
+CONFIGURE_ARGS+=	--with-usb-ids=${PREFIX}/share/usbids
+CONFIGURE_ARGS+=	--without-os-type
+CONFIGURE_ARGS+=	--disable-console-kit
+CONFIGURE_ARGS+=	--disable-policy-kit
+
+.include "../../mk/bsd.prefs.mk"
+
+.if ${OPSYS} == "DragonFly"
+.include "../../devel/libvolume_id/buildlink3.mk"
+CONFIGURE_ARGS+=	--with-eject=/usr/sbin/cdcontrol
+CONFIGURE_ARGS+=	--with-backend=freebsd
+PLIST_SRC=		PLIST.DragonFly PLIST
+
+.elif ${OPSYS} == "FreeBSD"
+.include "../../devel/libvolume_id/buildlink3.mk"
+CONFIGURE_ARGS+=	--with-eject=/usr/sbin/cdcontrol
+CONFIGURE_ARGS+=	--with-backend=freebsd
+PLIST_SRC=		PLIST.FreeBSD PLIST
+
+.elif !empty(MACHINE_PLATFORM:MNetBSD-[5-9]*)
+.include "../../devel/libvolume_id/buildlink3.mk"
+CONFIGURE_ARGS+=	--with-backend=netbsd
+HAL_GROUP=		operator
+
+.elif ${OPSYS} == "Linux"
+.include "../../devel/gperf/buildlink3.mk"
+.include "../../devel/libblkid/buildlink3.mk"
+.include "../../devel/libvolume_id/buildlink3.mk"
+.include "../../sysutils/pciutils/buildlink3.mk"
+CONFIGURE_ARGS+=	--with-backend=linux
+MAKE_DIRS+=		/etc/udev
+MAKE_DIRS+=		/etc/udev/rules.d
+CONF_FILES+=		${EGDIR}/90-hal.rules \
+			/etc/udev/rules.d/90-hal.rules
+PLIST_VARS+=	imac
+.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "x86_64"
+PLIST.imac=	yes
+CONFIGURE_ARGS+=	--with-imac
+.else
+CONFIGURE_ARGS+=	--without-imac
+.endif
+.else	# Unsupported systems
+# Pull in the dummy backend
+.include "../../devel/libvolume_id/buildlink3.mk"
+CONFIGURE_ARGS+=	--with-backend=dummy
+PLIST_SRC=		PLIST 
+.endif
+
+CFLAGS.SunOS+=		-Du_int32_t=uint32_t
+
+BUILDLINK_TRANSFORM.Darwin+=	rm:-Wl,--as-needed
+BUILDLINK_TRANSFORM.SunOS+=	opt:-Wl,--as-needed:-Wl,-zignore
+
+REPLACE_INTERPRETER+=	bash
+REPLACE.bash.old=	/bin/bash
+REPLACE.bash.new=	${SH}
+.for halscript in luks-remove luks-setup luks-teardown system-wol-enable system-wol-enabled system-wol-supported
+REPLACE_FILES.bash+=	tools/hal-${halscript}
+.endfor
+
+HAL_USER?=		haldaemon
+HAL_GROUP?=		haldaemon
+CONFIGURE_ARGS+=	--with-hal-user=${HAL_USER}
+CONFIGURE_ARGS+=	--with-hal-group=${HAL_GROUP}
+CONFIGURE_ARGS+=	--disable-pmu
+
+RCD_SCRIPTS=		hal
+SMF_METHODS=		hal
+
+.if ${HAL_GROUP} != "operator"
+PKG_GROUPS=		${HAL_GROUP}
+.endif
+PKG_USERS=		${HAL_USER}:${HAL_GROUP}
+PKG_HOME.haldaemon=	${VARBASE}/run/hald
+
+FILES_SUBST+=		HAL_USER=${HAL_USER}
+FILES_SUBST+=		HAL_GROUP=${HAL_GROUP}
+FILES_SUBST+=		PKG_HOME.haldaemon=${PKG_HOME.haldaemon}
+
+PLIST_SUBST+=		PKG_SYSCONFDIR=${PKG_SYSCONFDIR}
+
+TEST_TARGET=		check
+
+post-extract:
+	${CP} -r ${FILESDIR}/hald-netbsd ${WRKSRC}/hald/netbsd
+	${CP} -r ${FILESDIR}/tools-netbsd ${WRKSRC}/tools/netbsd
+
+CONFIGURE_ARGS+=	--disable-silent-rules
+
+INSTALLATION_DIRS+=	share/examples/hal
+
+post-install:
+	${INSTALL_SCRIPT} ${FILESDIR}/03-hal ${DESTDIR}${EGDIR}
+	cd ${WRKSRC}/fdi;gmake
+	cd ${WRKSRC}/fdi;gmake install
+
+pre-configure:
+	cd ${WRKSRC} && autoreconf -vi ${AUTORECONF_ARGS}
+
+.include "../../devel/GConf/schemas.mk"
+.include "../../devel/glib2/buildlink3.mk"
+.include "../../misc/usbids/buildlink3.mk"
+.include "../../sysutils/dbus/buildlink3.mk"
+.include "../../sysutils/dbus-glib/buildlink3.mk"
+.include "../../wip/hal-info/buildlink3.mk"
+.include "../../textproc/expat/buildlink3.mk"
+.include "../../mk/bsd.pkg.mk"
diff --git a/hal/PLIST b/hal/PLIST
new file mode 100644
index 0000000000..772ad0c011
--- /dev/null
+++ b/hal/PLIST
@@ -0,0 +1,108 @@
+@comment $NetBSD$
+bin/hal-device
+bin/hal-disable-polling
+bin/hal-find-by-capability
+bin/hal-find-by-property
+bin/hal-get-property
+bin/hal-is-caller-locked-out
+bin/hal-lock
+bin/hal-set-property
+bin/lshal
+include/hal/libhal-storage.h
+include/hal/libhal.h
+lib/libhal-storage.la
+lib/libhal.la
+lib/pkgconfig/hal-storage.pc
+lib/pkgconfig/hal.pc
+libexec/hal-storage-cleanup-all-mountpoints
+libexec/hal-storage-cleanup-mountpoint
+libexec/hal-storage-closetray
+libexec/hal-storage-eject
+libexec/hal-storage-mount
+libexec/hal-storage-unmount
+libexec/hal-system-power-pm-is-supported
+libexec/hal-system-setserial
+libexec/hald-addon-storage
+libexec/hald-generate-fdi-cache
+libexec/hald-probe-storage
+libexec/hald-probe-volume
+libexec/hald-runner
+libexec/scripts/hal-dockstation-undock
+libexec/scripts/hal-functions
+libexec/scripts/hal-luks-remove
+libexec/scripts/hal-luks-setup
+libexec/scripts/hal-luks-teardown
+libexec/scripts/hal-system-killswitch-get-power
+libexec/scripts/hal-system-killswitch-set-power
+libexec/scripts/hal-system-lcd-get-brightness
+libexec/scripts/hal-system-lcd-set-brightness
+libexec/scripts/hal-system-power-hibernate
+libexec/scripts/hal-system-power-reboot
+libexec/scripts/hal-system-power-set-power-save
+libexec/scripts/hal-system-power-shutdown
+libexec/scripts/hal-system-power-suspend
+libexec/scripts/hal-system-power-suspend-hybrid
+libexec/scripts/hal-system-wol-enable
+libexec/scripts/hal-system-wol-enabled
+libexec/scripts/hal-system-wol-supported
+libexec/scripts/netbsd/hal-system-power-reboot-netbsd
+libexec/scripts/netbsd/hal-system-power-shutdown-netbsd
+libexec/scripts/netbsd/hal-system-power-suspend-netbsd
+man/man1/hal-disable-polling.1
+man/man1/hal-find-by-capability.1
+man/man1/hal-find-by-property.1
+man/man1/hal-get-property.1
+man/man1/hal-is-caller-locked-out.1
+man/man1/hal-lock.1
+man/man1/hal-set-property.1
+man/man1/lshal.1
+man/man8/hald.8
+sbin/hald
+share/examples/hal/hal.conf
+share/gtk-doc/html/libhal-storage/home.png
+share/gtk-doc/html/libhal-storage/index.html
+share/gtk-doc/html/libhal-storage/index.sgml
+share/gtk-doc/html/libhal-storage/ix01.html
+share/gtk-doc/html/libhal-storage/left.png
+share/gtk-doc/html/libhal-storage/libhal-storage-libhal-storage.html
+share/gtk-doc/html/libhal-storage/libhal-storage.devhelp
+share/gtk-doc/html/libhal-storage/libhal-storage.devhelp2
+share/gtk-doc/html/libhal-storage/license.html
+share/gtk-doc/html/libhal-storage/right.png
+share/gtk-doc/html/libhal-storage/rn01.html
+share/gtk-doc/html/libhal-storage/style.css
+share/gtk-doc/html/libhal-storage/up.png
+share/gtk-doc/html/libhal-storage/version.xml
+share/gtk-doc/html/libhal/home.png
+share/gtk-doc/html/libhal/index.html
+share/gtk-doc/html/libhal/index.sgml
+share/gtk-doc/html/libhal/ix01.html
+share/gtk-doc/html/libhal/left.png
+share/gtk-doc/html/libhal/libhal-libhal.html
+share/gtk-doc/html/libhal/libhal.devhelp
+share/gtk-doc/html/libhal/libhal.devhelp2
+share/gtk-doc/html/libhal/license.html
+share/gtk-doc/html/libhal/right.png
+share/gtk-doc/html/libhal/rn01.html
+share/gtk-doc/html/libhal/style.css
+share/gtk-doc/html/libhal/up.png
+share/hal/fdi/fdi.dtd
+share/hal/fdi/policy/10osvendor/10-dockstation.fdi
+share/hal/fdi/policy/10osvendor/10-input-policy.fdi
+share/hal/fdi/policy/10osvendor/10-laptop-panel-mgmt-policy.fdi
+share/hal/fdi/policy/10osvendor/10-leds.fdi
+share/hal/fdi/policy/10osvendor/10-power-mgmt-policy.fdi
+share/hal/fdi/policy/10osvendor/10-rfkill-switch.fdi
+share/hal/fdi/policy/10osvendor/10-tabletPCs.fdi
+share/hal/fdi/policy/10osvendor/10-x11-input.fdi
+share/hal/fdi/policy/10osvendor/15-storage-luks.fdi
+share/hal/fdi/policy/10osvendor/20-storage-methods.fdi
+share/hal/fdi/policy/10osvendor/30-wol.fdi
+@exec ${MKDIR} ${PKG_SYSCONFDIR}/hal/fdi/information
+@exec ${MKDIR} ${PKG_SYSCONFDIR}/hal/fdi/policy
+@exec ${MKDIR} ${PKG_SYSCONFDIR}/hal/fdi/preprobe
+@unexec ${RMDIR} ${PKG_SYSCONFDIR}/hal/fdi/preprobe 2>/dev/null || ${TRUE}
+@unexec ${RMDIR} ${PKG_SYSCONFDIR}/hal/fdi/policy 2>/dev/null || ${TRUE}
+@unexec ${RMDIR} ${PKG_SYSCONFDIR}/hal/fdi/information 2>/dev/null || ${TRUE}
+@unexec ${RMDIR} ${PKG_SYSCONFDIR}/hal/fdi 2>/dev/null || ${TRUE}
+@unexec ${RMDIR} ${PKG_SYSCONFDIR}/hal 2>/dev/null || ${TRUE}
diff --git a/hal/PLIST.DragonFly b/hal/PLIST.DragonFly
new file mode 100755
index 0000000000..2d7baf7c73
--- /dev/null
+++ b/hal/PLIST.DragonFly
@@ -0,0 +1,15 @@
+@comment $NetBSD: PLIST.DragonFly,v 1.1 2012/03/31 16:06:56 ryoon Exp $
+libexec/hald-addon-mouse-sysmouse
+libexec/hald-addon-storage
+libexec/hald-probe-hiddev
+libexec/hald-probe-mouse
+libexec/hald-probe-scsi
+libexec/hald-probe-smbios
+libexec/hald-probe-storage
+libexec/hald-probe-volume
+libexec/scripts/freebsd/hal-system-lcd-get-brightness-freebsd
+libexec/scripts/freebsd/hal-system-lcd-set-brightness-freebsd
+libexec/scripts/freebsd/hal-system-power-reboot-freebsd
+libexec/scripts/freebsd/hal-system-power-set-power-save-freebsd
+libexec/scripts/freebsd/hal-system-power-shutdown-freebsd
+libexec/scripts/freebsd/hal-system-power-suspend-freebsd
diff --git a/hal/PLIST.FreeBSD b/hal/PLIST.FreeBSD
new file mode 100644
index 0000000000..f1b79972ef
--- /dev/null
+++ b/hal/PLIST.FreeBSD
@@ -0,0 +1,17 @@
+@comment $NetBSD: PLIST.FreeBSD,v 1.4 2012/03/31 16:06:56 ryoon Exp $
+libexec/hald-addon-mouse-sysmouse
+libexec/hald-addon-storage
+libexec/hald-probe-hiddev
+libexec/hald-probe-mouse
+libexec/hald-probe-scsi
+libexec/hald-probe-smbios
+libexec/hald-probe-storage
+libexec/hald-probe-usb2-device
+libexec/hald-probe-usb2-interface
+libexec/hald-probe-volume
+libexec/scripts/freebsd/hal-system-lcd-get-brightness-freebsd
+libexec/scripts/freebsd/hal-system-lcd-set-brightness-freebsd
+libexec/scripts/freebsd/hal-system-power-reboot-freebsd
+libexec/scripts/freebsd/hal-system-power-set-power-save-freebsd
+libexec/scripts/freebsd/hal-system-power-shutdown-freebsd
+libexec/scripts/freebsd/hal-system-power-suspend-freebsd
diff --git a/hal/PLIST.Linux b/hal/PLIST.Linux
new file mode 100644
index 0000000000..f7cc3b5220
--- /dev/null
+++ b/hal/PLIST.Linux
@@ -0,0 +1,46 @@
+@comment $NetBSD: PLIST.Linux,v 1.6 2016/09/17 15:33:59 richard Exp $
+bin/hal-setup-keymap
+libexec/hal-system-sonypic
+libexec/hald-addon-acpi
+libexec/hald-addon-cpufreq
+libexec/hald-addon-generic-backlight
+libexec/hald-addon-hid-ups
+${PLIST.imac}libexec/hald-addon-imac-backlight
+libexec/hald-addon-input
+libexec/hald-addon-ipw-killswitch
+libexec/hald-addon-leds
+libexec/hald-addon-rfkill-killswitch
+libexec/hald-addon-storage
+libexec/hald-probe-hiddev
+libexec/hald-probe-ieee1394-unit
+libexec/hald-probe-input
+libexec/hald-probe-net-bluetooth
+libexec/hald-probe-pc-floppy
+libexec/hald-probe-printer
+libexec/hald-probe-serial
+libexec/hald-probe-smbios
+libexec/hald-probe-storage
+libexec/hald-probe-video4linux
+libexec/hald-probe-volume
+libexec/scripts/linux/hal-dockstation-undock-linux
+libexec/scripts/linux/hal-luks-remove-linux
+libexec/scripts/linux/hal-luks-setup-linux
+libexec/scripts/linux/hal-luks-teardown-linux
+libexec/scripts/linux/hal-system-killswitch-get-power-linux
+libexec/scripts/linux/hal-system-killswitch-set-power-linux
+libexec/scripts/linux/hal-system-lcd-get-brightness-linux
+libexec/scripts/linux/hal-system-lcd-set-brightness-linux
+libexec/scripts/linux/hal-system-power-hibernate-linux
+libexec/scripts/linux/hal-system-power-reboot-linux
+libexec/scripts/linux/hal-system-power-set-power-save-linux
+libexec/scripts/linux/hal-system-power-shutdown-linux
+libexec/scripts/linux/hal-system-power-suspend-hybrid-linux
+libexec/scripts/linux/hal-system-power-suspend-linux
+libexec/scripts/linux/hal-system-wol-enable-linux
+libexec/scripts/linux/hal-system-wol-enabled-linux
+libexec/scripts/linux/hal-system-wol-linux
+libexec/scripts/linux/hal-system-wol-supported-linux
+share/examples/hal/90-hal.rules
+share/hal/fdi/policy/10osvendor/10-cpufreq.fdi
+${PLIST.imac}share/hal/fdi/policy/10osvendor/10-imac-backlight.fdi
+share/hal/fdi/policy/10osvendor/10-keymap.fdi
diff --git a/hal/PLIST.NetBSD b/hal/PLIST.NetBSD
new file mode 100644
index 0000000000..b469c19149
--- /dev/null
+++ b/hal/PLIST.NetBSD
@@ -0,0 +1,8 @@
+@comment $NetBSD: PLIST.NetBSD,v 1.4 2011/01/08 13:39:08 obache Exp $
+libexec/hald-addon-storage
+libexec/hald-probe-storage
+libexec/hald-probe-volume
+libexec/scripts/netbsd/hal-system-power-reboot-netbsd
+libexec/scripts/netbsd/hal-system-power-shutdown-netbsd
+libexec/scripts/netbsd/hal-system-power-suspend-netbsd
+share/examples/hal/03-hal
diff --git a/hal/buildlink3.mk b/hal/buildlink3.mk
new file mode 100644
index 0000000000..9addba73d2
--- /dev/null
+++ b/hal/buildlink3.mk
@@ -0,0 +1,16 @@
+# $NetBSD: buildlink3.mk,v 1.7 2012/09/15 10:06:27 obache Exp $
+
+BUILDLINK_TREE+=	hal
+
+.if !defined(HAL_BUILDLINK3_MK)
+HAL_BUILDLINK3_MK:=
+
+BUILDLINK_API_DEPENDS.hal+=	hal>=0.5.11
+BUILDLINK_ABI_DEPENDS.hal+=	hal>=0.5.14nb8
+BUILDLINK_PKGSRCDIR.hal?=	../../wip/hal
+
+.include "../../sysutils/dbus/buildlink3.mk"
+.include "../../sysutils/dbus-glib/buildlink3.mk"
+.endif # HAL_BUILDLINK3_MK
+
+BUILDLINK_TREE+=	-hal
diff --git a/hal/distinfo b/hal/distinfo
new file mode 100644
index 0000000000..4b275e9f76
--- /dev/null
+++ b/hal/distinfo
@@ -0,0 +1,53 @@
+$NetBSD: distinfo,v 1.26 2016/09/17 15:33:59 richard Exp $
+
+SHA1 (hal-0.5.14.tar.bz2) = a6ec098d78112e18e2773afa5f9ed642b00c4c59
+RMD160 (hal-0.5.14.tar.bz2) = 0314dace9512bf49a62bd1556963fc60a6c9caf9
+SHA512 (hal-0.5.14.tar.bz2) = fe34e0dd0a630b943ea1ce2a2af71260309144fb76ae0f482c475610f0347f403f2a3bac81d27a95868bf640fca78e6e8de0051e8e1a3f39ff6804232ecc333c
+Size (hal-0.5.14.tar.bz2) = 942954 bytes
+SHA1 (patch-Makefile.am) = abf9318414838890c0eb344b6b15a8ec3a2600ef
+SHA1 (patch-configure.in) = 7b17a5bef17a030eca69f11843fb35957e66fd76
+SHA1 (patch-fdi_policy_10osvendor_20-storage-methods.fdi) = 0dff37971d139198d286b5970b2d5435cb7044cc
+SHA1 (patch-hald_Makefile.am) = db979b9ed3246a0fb3ed9d86dfcf60a40a48812a
+SHA1 (patch-hald_device__info.c) = b88a1ee1ae06cee798a9c46f963e86d41e6ac8d8
+SHA1 (patch-hald_freebsd_addons_addon-mouse.c) = a6319e523affc90701f09266949cb7891c044ba7
+SHA1 (patch-hald_freebsd_addons_addon-storage.c) = 209d7558e35644a68cb5feaf8e59c08e0ef563e1
+SHA1 (patch-hald_freebsd_hf-ata.c) = d8d72c49cb528d3b34a4ab369d07fa0278c4c9aa
+SHA1 (patch-hald_freebsd_hf-devd.c) = 5003677cbe438a7fa1429a77b27f3824b3207b8a
+SHA1 (patch-hald_freebsd_hf-pci.c) = 040a018a7be5b28a0dc23dd66a0c10bbb0abc6bf
+SHA1 (patch-hald_freebsd_hf-storage.c) = f20e4b1286d177e53a550b2ba1608d22e4b5c609
+SHA1 (patch-hald_freebsd_hf-usb.c) = 4323ab79fe068cfe4098ecc84923b14b37ff8537
+SHA1 (patch-hald_freebsd_hf-usb2.c) = de4dbe7ceadf462bf9e4b2f9ceffa499df7e9aad
+SHA1 (patch-hald_freebsd_hf-volume.c) = 5b17c899c3cf6ef1c825a18bd8571383b00bc770
+SHA1 (patch-hald_freebsd_libprobe_hfp-cdrom.c) = b6d8a2f5fe06120bae22608d065395e1ed43a19c
+SHA1 (patch-hald_freebsd_probing_Makefile.am) = c9e843f57b8a31f1bdc42478d450ea5606b4d7db
+SHA1 (patch-hald_freebsd_probing_probe-hiddev.c) = fe567d7504e961cb623e492f8dc155ef2f3b4c9e
+SHA1 (patch-hald_freebsd_probing_probe-storage.c) = bf44c939b338359f18457b1e65434731c3605130
+SHA1 (patch-hald_freebsd_probing_probe-usb2-device.c) = 6c9dc4b65c507ac2ce7896d8019fa5335aa1275c
+SHA1 (patch-hald_freebsd_probing_probe-usb2-interface.c) = 3e18a3861a2ba21de5a7718c890e653bd0f6825d
+SHA1 (patch-hald_freebsd_probing_probe-volume.c) = 2964207f8907229b5d00ecce7f56fb3359d01f0d
+SHA1 (patch-hald_linux_addons_addon-acpi-buttons-toshiba.c) = 82f266ac27c290470adedfe1ba820a0b5a8e1d27
+SHA1 (patch-hald_linux_addons_addon-cpufreq.c) = 1e94d9a00f57fa4197f460953ba540564fa1441c
+SHA1 (patch-hald_linux_addons_addon-dell-backlight.cpp) = 72bd150adff60dfeca4a261ee9387783a5e99262
+SHA1 (patch-hald_linux_addons_addon-generic-backlight.c) = ebf060a72948e4301477eedbbcaaa766d88265b5
+SHA1 (patch-hald_linux_addons_addon-imac-backlight.c) = c594f0dfb2b659faee9f88a0254db3e9180c2b3d
+SHA1 (patch-hald_linux_addons_addon-input.c) = c893c803e2870af97cdcae23f3c6f66e45234888
+SHA1 (patch-hald_linux_addons_addon-ipw-killswitch.c) = d3d8270dddaa132c3fefbc667f315f697c900245
+SHA1 (patch-hald_linux_addons_addon-leds.c) = e56747b39bf5e6e03286fedcb73ef226c0231bbd
+SHA1 (patch-hald_linux_addons_addon-macbookpro-backlight.c) = c508a7b9070c319679b8b8e715d29410957ba41a
+SHA1 (patch-hald_linux_addons_addon-omap-backlight.c) = 72ba398a1d661fb726778bf7df7460735fee988f
+SHA1 (patch-hald_linux_addons_addon-rfkill-killswitch.c) = 800fac10408b65b12cd644b93b8612c8b2970da0
+SHA1 (patch-hald_linux_addons_addon-storage.c) = 9949c8768395295f27aebc792b8b8091e988d2d9
+SHA1 (patch-hald_linux_addons_addon-usb-csr.c) = 34b5be5ff308f9aafcf505b303d36cbc2483d015
+SHA1 (patch-hald_linux_probing_probe-video4linux.c) = 023c679c42802dac6970ac0843c3244d274ba6bd
+SHA1 (patch-hald_netbsd_devinfo__mass.c) = 9fd6cfcd04211a87e810536216fab3443ad08bd1
+SHA1 (patch-hald_netbsd_drvctl.c) = b6e5d08735233cfb17b30740673324a0b080b61e
+SHA1 (patch-libhal_libhal.c) = 78013280a42c68150ea926366f085ede84b94958
+SHA1 (patch-policy_Makefile.am) = 075ab5e265be4733d856a17184129d0b301bc0b8
+SHA1 (patch-tools_Makefile.am) = ebbac0ca2995a1dd5d72206f6a89e5d820677e81
+SHA1 (patch-tools_hal-luks-setup) = cccc411359aa6ada37496923fe3bec883076d78d
+SHA1 (patch-tools_hal-luks-teardown) = e5346dcbbbd11b726174b99cb7a64647d7a35062
+SHA1 (patch-tools_hal-storage-mount.c) = 83d20e99943be5c4e9eaeff7a86d79a8912d9c99
+SHA1 (patch-tools_hal-storage-shared.c) = f76078748c3a8f64c4811da2b43c8635c90249b3
+SHA1 (patch-tools_hal-storage-unmount.c) = 1a1307b1448880dbdd0cec5731790985cbfea140
+SHA1 (patch-tools_hal-system-power-pmu.c) = d1ccd7c21008304998293031632f572f250033c1
+SHA1 (patch-tools_linux_Makefile.am) = 00143e34bee7010dd6c0e6be5ecb4fef31212381
diff --git a/hal/files/03-hal b/hal/files/03-hal
new file mode 100755
index 0000000000..3968f52832
--- /dev/null
+++ b/hal/files/03-hal
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# signal devices to hal daemon
+#
+FIFO=/tmp/halfifo
+ACTION=$1
+DEV=$2
+
+/usr/bin/logger $0 $*
+
+if [ -p $FIFO ]
+then
+	(echo $1 $2 >> $FIFO)&
+fi
+
+case ${ACTION} in
+device-attach)
+	case ${DEV} in
+	sd*)
+		pkill -hup gvfs-hal-volume-monitor
+	;;
+	esac
+;;
+device-detach)
+;;
+esac
diff --git a/hal/files/hal.sh b/hal/files/hal.sh
new file mode 100644
index 0000000000..cfcbd81798
--- /dev/null
+++ b/hal/files/hal.sh
@@ -0,0 +1,25 @@
+#!@RCD_SCRIPTS_SHELL@
+#
+# $NetBSD: hal.sh,v 1.3 2015/09/25 16:26:16 richard Exp $
+#
+# PROVIDE: hal
+# REQUIRE: dbus
+# KEYWORD: shutdown
+
+. /etc/rc.subr
+
+name="hal"
+rcvar=$name
+command="@PREFIX@/sbin/hald"
+start_precmd=hal_prestart
+
+hal_prestart() {
+	/usr/bin/mkfifo -m 600 /tmp/halfifo
+	(echo "ping" > /tmp/halfifo)&
+	@MKDIR@ -m 0755 $dir "@VARBASE@/cache/hald" "@PKG_HOME.haldaemon@"
+	@CHOWN@ -R @HAL_USER@:@HAL_GROUP@ "@PKG_HOME.haldaemon@" "@VARBASE@/cache/hald"
+	sleep 3
+}
+
+load_rc_config $name
+run_rc_command "$1"
diff --git a/hal/files/hald-netbsd/Makefile.am b/hal/files/hald-netbsd/Makefile.am
new file mode 100644
index 0000000000..c5ba9a9163
--- /dev/null
+++ b/hal/files/hald-netbsd/Makefile.am
@@ -0,0 +1,27 @@
+
+SUBDIRS = probing addons .
+
+AM_CPPFLAGS = \
+	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
+	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
+	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
+	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
+	-I$(top_srcdir) -I.. \
+	@GLIB_CFLAGS@ @DBUS_CFLAGS@ @POLKIT_CFLAGS@ @VOLUME_ID_CFLAGS@
+
+if HALD_COMPILE_NETBSD
+noinst_LTLIBRARIES = libhald_netbsd.la
+endif
+
+libhald_netbsd_la_SOURCES = \
+	osspec.c drvctl.c envsys.c vfsstat.c \
+	devinfo.c devinfo_misc.c devinfo_audio.c devinfo_video.c \
+	devinfo_mass.c \
+	hotplug.c hal-file-monitor.c \
+	devinfo_optical.c 
+#	devinfo_scsipi.c
+#	devinfo_usb.c \
+#	devinfo_pci.c
+
+libhald_netbsd_la_LDFLAGS = -lprop @VOLUME_ID_LIBS@
diff --git a/hal/files/hald-netbsd/addons/Makefile.am b/hal/files/hald-netbsd/addons/Makefile.am
new file mode 100644
index 0000000000..8434fb0334
--- /dev/null
+++ b/hal/files/hald-netbsd/addons/Makefile.am
@@ -0,0 +1,17 @@
+
+AM_CPPFLAGS = \
+	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
+	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
+	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
+	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
+        -I$(top_srcdir) -I$(top_srcdir)/hald -I$(top_srcdir)/libhal -I$(top_srcdir)/libhal-storage \
+        @GLIB_CFLAGS@ @DBUS_CFLAGS@
+
+if HALD_COMPILE_NETBSD
+libexec_PROGRAMS  = hald-addon-storage
+endif
+
+hald_addon_storage_SOURCES = addon-storage.c ../../logger.c
+hald_addon_storage_LDADD = $(top_builddir)/libhal/libhal.la
+
diff --git a/hal/files/hald-netbsd/addons/addon-storage.c b/hal/files/hald-netbsd/addons/addon-storage.c
new file mode 100644
index 0000000000..ed20019728
--- /dev/null
+++ b/hal/files/hald-netbsd/addons/addon-storage.c
@@ -0,0 +1,516 @@
+/***************************************************************************
+ *
+ * addon-storage.c : watch removable media state changes
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/statvfs.h>
+#include <sys/dkio.h>
+#include <dev/scsipi/scsi_spc.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsipi_cd.h>
+#include <sys/scsiio.h>
+
+#include <libhal.h>
+
+#include <logger.h>
+
+#define	SLEEP_PERIOD	5
+
+#define _EXPOSE_MMC
+#include <sys/cdio.h>
+
+
+enum discstate {
+	DISC_INSERTED,
+	DISC_EJECTED,
+	DISC_NONE,
+	DISC_UNKNOWN
+};
+
+static enum discstate
+scsi_test_unit_ready (int fd)
+{
+	struct scsi_test_unit_ready tur;
+	scsireq_t req;
+
+	memset(&tur, 0, sizeof(tur));
+	tur.opcode = SCSI_TEST_UNIT_READY;
+
+	memset(&req, 0, sizeof(req));
+	memcpy(req.cmd, &tur, sizeof(tur));
+	req.cmdlen = sizeof(tur);
+	req.databuf = NULL;
+	req.datalen = 0;
+	req.timeout = 10000;
+	req.flags = SCCMD_READ;
+	req.senselen = SENSEBUFLEN;
+
+	if (ioctl(fd, SCIOCCOMMAND, &req) == -1)
+		return DISC_UNKNOWN;
+	if (req.retsts == SCCMD_OK)
+		return DISC_INSERTED;
+	return DISC_EJECTED;
+}
+
+static void
+my_dbus_error_free(DBusError *error)
+{
+	if (dbus_error_is_set(error)) {
+		dbus_error_free(error);
+	}
+}
+
+static void
+force_unmount (LibHalContext *ctx, const char *udi)
+{
+	DBusError error;
+	DBusMessage *msg = NULL;
+	DBusMessage *reply = NULL;
+	char **options = NULL;
+	unsigned int num_options = 0;
+	DBusConnection *dbus_connection;
+	char *device_file;
+
+	dbus_error_init (&error);
+
+	dbus_connection = libhal_ctx_get_dbus_connection (ctx);
+
+	msg = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
+					    "org.freedesktop.Hal.Device.Volume",
+					    "Unmount");
+	if (msg == NULL) {
+		HAL_DEBUG (("Could not create dbus message for %s", udi));
+		goto out;
+	}
+
+
+	options = calloc (1, sizeof (char *));
+	if (options == NULL) {
+		HAL_DEBUG (("Could not allocate options array"));
+		goto out;
+	}
+
+	device_file = libhal_device_get_property_string (ctx, udi, "block.device", &error);
+	if (device_file != NULL) {
+		libhal_free_string (device_file);
+	}
+	dbus_error_free (&error);
+
+	if (!dbus_message_append_args (msg, 
+				       DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
+				       DBUS_TYPE_INVALID)) {
+		HAL_DEBUG (("Could not append args to dbus message for %s", udi));
+		goto out;
+	}
+	
+	if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, msg, -1, &error))) {
+		HAL_DEBUG (("Unmount failed for %s: %s : %s\n", udi, error.name, error.message));
+		goto out;
+	}
+
+	if (dbus_error_is_set (&error)) {
+		HAL_DEBUG (("Unmount failed for %s\n%s : %s\n", udi, error.name, error.message));
+		goto out;
+	}
+
+	HAL_DEBUG (("Succesfully unmounted udi '%s'", udi));
+
+out:
+	dbus_error_free (&error);
+	if (options != NULL)
+		free (options);
+	if (msg != NULL)
+		dbus_message_unref (msg);
+	if (reply != NULL)
+		dbus_message_unref (reply);
+}
+
+static void 
+unmount_childs (LibHalContext *ctx, const char *udi)
+{
+	DBusError error;
+	int num_volumes;
+	char **volumes;
+
+	dbus_error_init (&error);
+
+	/* need to force unmount all partitions */
+	if ((volumes = libhal_manager_find_device_string_match (
+	     ctx, "block.storage_device", udi, &num_volumes, &error)) != NULL) {
+		dbus_error_free (&error);
+		int i;
+
+		for (i = 0; i < num_volumes; i++) {
+			char *vol_udi;
+
+			vol_udi = volumes[i];
+			if (libhal_device_get_property_bool (ctx, vol_udi, "block.is_volume", &error)) {
+				dbus_error_free (&error);
+				if (libhal_device_get_property_bool (ctx, vol_udi, "volume.is_mounted", &error)) {
+					dbus_error_free (&error);
+					HAL_DEBUG (("Forcing unmount of child '%s'", vol_udi));
+					force_unmount (ctx, vol_udi);
+				}
+			}
+		}
+		libhal_free_string_array (volumes);
+	}
+	my_dbus_error_free (&error);
+}
+
+/** Check if a filesystem on a special device file is mounted
+ *
+ *  @param  device_file         Special device file, e.g. /dev/cdrom
+ *  @return                     TRUE iff there is a filesystem system mounted
+ *                              on the special device file
+ */
+static dbus_bool_t
+is_mounted (const char *device_file)
+{
+        int count;
+	struct statvfs *statvfs;
+
+	count = getmntinfo(&statvfs, ST_WAIT);
+	while (count-- > 0) {
+		if (strcmp(statvfs->f_mntfromname, device_file) == 0)
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void
+close_device (int *fd)
+{
+	if (*fd > 0) {
+		close (*fd);
+		*fd = -1;
+	}
+}
+
+
+/* XXX why not share this further */
+static char const *
+get_profile_typestring(int profile)
+{
+	switch (profile) {
+	case 0x00 : return "unknown";	  // "Unknown[0] profile";
+	case 0x01 : return "unknown";	  // "Non removeable disc";
+	case 0x02 : return "unknown";	  // "Removable disc";
+	case 0x03 : return "mo";	  // Magneto Optical with sector erase";
+	case 0x04 : return "mo";	  // "Magneto Optical write once";
+	case 0x05 : return "mo";	  // "Advance Storage Magneto Optical";
+	case 0x08 : return "cd_rom";	  // "CD-ROM"; no writing
+	case 0x09 : return "cd_r";	  // "CD-R recordable";
+	case 0x0a : return "cd_rw";	  // "CD-RW rewritable";
+	case 0x10 : return "dvd_rom";	  // "DVD-ROM"; no writing
+	case 0x11 : return "dvd_r";	  // "DVD-R sequential";
+	case 0x12 : return "dvd_ram";	  // "DVD-RAM rewritable";
+	case 0x13 : return "dvd_rw";	  // "DVD-RW restricted overwrite";
+	case 0x14 : return "dvd_rw";	  // "DVD-RW sequential";
+	case 0x15 : return "dvd_r";	  // "DVD-R dual layer sequential";
+	case 0x16 : return "dvd_r";	  // "DVD-R dual layer jump";
+	case 0x17 : return "dvd_rw";	  // "DVD-RW dual layer";
+	case 0x18 : return "unknown";	  // "DVD-Download disc"; UNKNOWN
+	case 0x1a : return "dvd_plus_rw"; // "DVD+RW rewritable";
+	case 0x1b : return "dvd_plus_r";  // "DVD+R recordable";
+	case 0x20 : return "ddcd_rom";	  // "DDCD readonly (retracted)"; no writing
+	case 0x21 : return "ddcd_r";	  // "DDCD-R recordable (retracted)";	OK?
+	case 0x22 : return "ddcd_rw";	  // "DDCD-RW rewritable (retracted)"; OK?
+	case 0x2a : return "dvd_plus_rw_dl";//"DVD+RW double layer";
+	case 0x2b : return "dvd_plus_r_dl";// "DVD+R double layer";
+	case 0x40 : return "bd_rom";	  // "BD-ROM";
+	case 0x41 : return "bd_r";	  // "BD-R Sequential Recording (SRM)";
+	case 0x42 : return "bd_r";	  // "BD-R Random Recording (RRM)";
+	case 0x43 : return "bd_re";	  // "BD-RE rewritable";
+	case 0x50 : return "hddvd_rom";	  // "HD DVD-ROM (retracted)";
+	case 0x51 : return "hddvd_r";	  // "HD DVD-R (retracted)";
+	case 0x52 : return "hddvd_ram";	  // "HD DVD-RAM (retracted)";
+	case 0x53 : return "hddvd_rw";	  // "HD DVD-RW (retracted)";
+	case 0x58 : return "hddvd_r_dl";  // "HD DVD-R dual layer (retracted)";
+	case 0x5a : return "hddvd_rw_dl"; // "HD DVD-RW dual layer (retracted)";
+	}
+	/* reserved */
+	return "unknown";
+}
+
+
+static void
+set_volume_properties(int fd, LibHalContext *ctx, char *udi, int state)
+{
+	struct mmc_discinfo  di;
+	struct mmc_trackinfo ti;
+	struct volume_id *vid;
+	DBusError error;
+	uint64_t capacity;
+	char const *disc_type;
+	char *disc_fstype, *disc_label;
+	int has_audio, has_data, is_vcd, is_svcd, is_videodvd, is_appendable, is_blank, is_rewritable;
+	int tracknr, err;
+
+	disc_fstype = "";
+	disc_label  = "";
+	disc_type   = "unknown";
+	has_audio = has_data = is_vcd = is_svcd = is_videodvd = is_appendable = is_blank = is_rewritable = 0;
+	capacity  = 0;
+
+	dbus_error_init (&error);
+	if (state == DISC_INSERTED) {
+		/* fetch new values */
+		memset(&di, 0, sizeof(struct mmc_discinfo));
+		err = ioctl(fd, MMCGETDISCINFO, &di);
+		if (!err) {
+			disc_type = get_profile_typestring(di.mmc_profile);
+			is_rewritable = di.mmc_cur & MMC_CAP_REWRITABLE;
+			is_blank      = (di.disc_state == MMC_STATE_EMPTY);
+			is_appendable = (di.disc_state != MMC_STATE_FULL);
+
+			/* can't check is_videodvd, is_svcd, is_vcd (yet); use volume lib */
+			disc_fstype = "cd9660";
+			disc_label  = "label";
+vid = NULL;
+#if 0
+			vid = volume_id_open_fd (fd);
+			if (vid) {
+				if (volume_id_probe_all (vid, 0, psize) == 0) {
+					hal_device_property_set_string (d, "volume.label", vid->label);
+					hal_device_property_set_string (d, "volume.partition.label", vid->label);
+					hal_device_property_set_string (d, "volume.uuid", vid->uuid);
+					hal_device_property_set_string (d, "volume.partition.uuid", vid->uuid);
+				}
+				volume_id_close (vid);
+			}
+#endif
+			for (tracknr = di.first_track; tracknr <= di.last_track_last_session; tracknr++) {
+				memset(&ti, 0, sizeof(struct mmc_trackinfo));
+				ti.tracknr = tracknr;
+				err = ioctl(fd, MMCGETTRACKINFO, &ti);
+				if (err)
+					break;
+				if (!(ti.flags & MMC_TRACKINFO_BLANK)) {
+					if (ti.flags & MMC_TRACKINFO_DATA)
+						has_data = TRUE;
+					if (ti.flags & MMC_TRACKINFO_AUDIO)
+						has_audio = TRUE;
+				}
+				capacity += (ti.track_size + ti.free_blocks) * di.sector_size;
+			}
+		}
+	}
+
+	/* add volume properties (ignoring dbus errors) */
+	libhal_device_set_property_bool   (ctx, udi, "volume.ignore", FALSE, &error);		/* make visible */
+	libhal_device_set_property_bool   (ctx, udi, "volume.is_mounted", FALSE, &error);	/* XXX fixme XXX */
+	libhal_device_set_property_bool   (ctx, udi, "volume.is_mounted_readonly", FALSE, &error);	/* XXX fixme XXX */
+	libhal_device_set_property_string (ctx, udi, "volume.fsusage", "filesystem", &error);
+	libhal_device_set_property_string (ctx, udi, "volume.fstype",  disc_fstype, &error);
+	libhal_device_set_property_string (ctx, udi, "volume.label", disc_label, &error);
+	libhal_device_set_property_string (ctx, udi, "volume.uuid", "", &error);
+	libhal_device_set_property_uint64 (ctx, udi, "volume.size", capacity, &error);
+
+	/* add volume.disc properties (ignoring dbus errors) */
+	libhal_device_set_property_bool   (ctx, udi, "volume.disc.has_audio", has_audio, &error);
+	libhal_device_set_property_bool   (ctx, udi, "volume.disc.has_data", has_data, &error);
+	libhal_device_set_property_bool   (ctx, udi, "volume.disc.is_vcd", is_vcd, &error);
+	libhal_device_set_property_bool   (ctx, udi, "volume.disc.is_svcd", is_svcd, &error);
+	libhal_device_set_property_bool   (ctx, udi, "volume.disc.is_videodvd", is_videodvd, &error);
+	libhal_device_set_property_bool   (ctx, udi, "volume.disc.is_appendable", is_appendable, &error);
+	libhal_device_set_property_bool   (ctx, udi, "volume.disc.is_blank", is_blank, &error);
+	libhal_device_set_property_bool   (ctx, udi, "volume.disc.is_rewritable", is_rewritable, &error);
+
+	libhal_device_set_property_string (ctx, udi, "volume.disc.type", disc_type, &error);
+	libhal_device_set_property_uint64 (ctx, udi, "volume.disc.capacity", capacity, &error);
+
+	my_dbus_error_free (&error);
+}
+
+
+static void 
+update_disc_volume_properties(int fd, LibHalContext *ctx, const char *udi, int state)
+{
+	DBusError error;
+	char **volumes;
+	char *vol_udi;
+	int num_volumes, i;
+
+	dbus_error_init (&error);
+
+	/* update volume children */
+	if ((volumes = libhal_manager_find_device_string_match (
+	     ctx, "info.parent", udi, &num_volumes, &error)) != NULL) {
+		dbus_error_free (&error);
+
+		for (i = 0; i < num_volumes; i++) {
+			vol_udi = volumes[i];
+			if (libhal_device_get_property_bool (ctx, vol_udi, "block.is_volume", &error)) {
+				dbus_error_free (&error);
+				HAL_DEBUG(("Updating child %s of %s\n", udi, vol_udi));
+				set_volume_properties(fd, ctx, vol_udi, state);
+
+#if 0
+				if (libhal_device_get_property_bool (ctx, vol_udi, "volume.is_mounted", &error)) {
+					dbus_error_free (&error);
+					HAL_DEBUG (("Forcing unmount of child '%s'", vol_udi));
+					force_unmount (ctx, vol_udi);
+				}
+#endif
+			}
+		}
+		libhal_free_string_array (volumes);
+	}
+	my_dbus_error_free (&error);
+}
+
+
+int 
+main (int argc, char *argv[])
+{
+	char *udi;
+	char *device_file, *raw_device_file;
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	char *bus;
+	char *drive_type;
+	int state, last_state;
+	char *support_media_changed_str;
+	int support_media_changed;
+	int fd = -1;
+
+	if ((udi = getenv ("UDI")) == NULL)
+		goto out;
+	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
+		goto out;
+	if ((raw_device_file = getenv ("HAL_PROP_BLOCK_NETBSD_RAW_DEVICE")) == NULL)
+		goto out;
+	if ((bus = getenv ("HAL_PROP_STORAGE_BUS")) == NULL)
+		goto out;
+	if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
+		goto out;
+
+	setup_logger ();
+
+	support_media_changed_str = getenv ("HAL_PROP_STORAGE_CDROM_SUPPORT_MEDIA_CHANGED");
+	if (support_media_changed_str != NULL && strcmp (support_media_changed_str, "true") == 0)
+		support_media_changed = TRUE;
+	else
+		support_media_changed = FALSE;
+
+	dbus_error_init (&error);
+
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
+		goto out;
+	}
+	my_dbus_error_free (&error);
+
+	if (!libhal_device_addon_is_ready (ctx, udi, &error)) {
+		goto out;
+	}
+	my_dbus_error_free (&error);
+
+	printf ("Doing addon-storage for %s (bus %s) (drive_type %s) (udi %s)\n", device_file, bus, drive_type, udi);
+
+	last_state = state = DISC_NONE;
+
+	/* Linux version of this addon attempts to re-open the device O_EXCL
+	 * every 2 seconds, trying to figure out if some other app,
+	 * like a cd burner, is using the device. Aside from questionable
+	 * value of this (apps should use HAL's locked property or/and
+	 * Solaris in_use facility), but also frequent opens/closes
+	 * keeps media constantly spun up. All this needs more thought.
+	 */
+	for (;;) {
+		sleep (SLEEP_PERIOD);
+		if (is_mounted (device_file)) {
+			close_device (&fd);
+		} else if ((fd < 0) && ((fd = open (raw_device_file, O_RDONLY | O_NONBLOCK)) < 0)) {
+			HAL_DEBUG (("open failed for %s: %s", raw_device_file, strerror (errno)));
+		} else {
+			/* Check if a disc is in the drive */
+			state = scsi_test_unit_ready (fd);
+
+			if (state == last_state) {
+				HAL_DEBUG (("state has not changed %d %s", state, device_file));
+				/* TODO check if eject button was pressed */
+				/* see linux addons/addon-storage.c */
+				continue;
+			} else {
+				HAL_DEBUG (("new state %d %s", state, device_file));
+			}
+
+			switch (state) {
+			case DISC_EJECTED:
+				HAL_DEBUG (("Media removal detected on %s", device_file));
+				last_state = state;
+
+				libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error);
+				my_dbus_error_free (&error);
+
+				/* attempt to unmount all childs */
+				unmount_childs (ctx, udi);
+
+				update_disc_volume_properties(fd, ctx, udi, state);
+
+				/* could have a fs on the main block device; do a rescan to remove it */
+				libhal_device_rescan (ctx, udi, &error);
+				my_dbus_error_free (&error);
+				break;
+
+			case DISC_INSERTED:
+				HAL_DEBUG (("Media insertion detected on %s", device_file));
+				last_state = state;
+
+				libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error);
+				my_dbus_error_free (&error);
+
+				update_disc_volume_properties(fd, ctx, udi, state);
+
+				/* could have a fs on the main block device; do a rescan to add it */
+				libhal_device_rescan (ctx, udi, &error);
+				my_dbus_error_free (&error);
+				break;
+
+			case DISC_UNKNOWN:
+			default:
+				HAL_DEBUG (("Device gone detected on %s", device_file));
+				last_state = state;
+
+				unmount_childs (ctx, udi);
+				close_device (&fd);
+				goto out;
+
+			}
+		}
+	}
+
+out:
+	if (ctx != NULL) {
+		my_dbus_error_free (&error);
+		libhal_ctx_shutdown (ctx, &error);
+		libhal_ctx_free (ctx);
+	}
+
+	return 0;
+}
diff --git a/hal/files/hald-netbsd/devinfo.c b/hal/files/hald-netbsd/devinfo.c
new file mode 100644
index 0000000000..7e47383675
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo.c
@@ -0,0 +1,418 @@
+/***************************************************************************
+ *
+ * devinfo.c : main file for drvctl-based device enumeration
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/drvctlio.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "../hald_runner.h"
+#include "osspec_netbsd.h"
+#include "hotplug.h"
+#include "devinfo.h"
+#include "devinfo_audio.h"
+#include "devinfo_video.h"
+#include "devinfo_pci.h"
+#include "devinfo_storage.h"
+#include "devinfo_mass.h"
+#include "devinfo_usb.h"
+#include "devinfo_misc.h"
+#include "devinfo_cpu.h"
+#include "devinfo_optical.h"
+/* #include "devinfo_scsipi.h" */
+#include "drvctl.h"
+
+void devinfo_add_subtree(HalDevice *parent, const char *devnode, gboolean is_root);
+
+void
+devinfo_add(HalDevice *parent, gchar *name)
+{
+	devinfo_add_subtree (parent, name, TRUE);
+}
+
+void
+devinfo_add_subtree(HalDevice *parent, const char *devnode, gboolean is_root)
+{
+	HalDevice *d;
+	struct devlistargs laa;
+	int i;
+
+	HAL_INFO (("add_subtree: %s", devnode));
+
+	if (parent == NULL) {
+		parent = devinfo_add_node (NULL, devnode);
+	}
+
+	if (drvctl_list (devnode, &laa) == -1) {
+		HAL_INFO (("devinfo_add_subtree: drvctl_list failed"));
+		return;
+	}
+
+	for (i = 0; i < laa.l_children; i++) {
+		d = devinfo_add_node (parent, laa.l_childname[i]);
+		if (d)
+			devinfo_add_subtree (d, laa.l_childname[i], FALSE);
+	}
+
+	if (laa.l_childname)
+		free(laa.l_childname);
+}
+
+void
+devinfo_set_default_properties (HalDevice *d, HalDevice *parent, const char *devnode, char *devfs_path)
+{
+	char	*driver_name, *s;
+	const char *s1;
+	char	udi[HAL_PATH_MAX];
+
+	if (parent != NULL) {
+		char *pdevice = hal_device_property_get_string (parent, "netbsd.device");
+		if (pdevice) {
+			gchar *path;
+			if (strcmp (pdevice, "mainbus0") == 0)
+				pdevice = "computer";
+			path = g_strdup_printf ("/org/freedesktop/Hal/devices/%s", pdevice);
+			hal_device_property_set_string (d, "info.parent", path);
+			g_free (path);
+		}
+	} else {
+		gchar pdevnode[512];
+		char *pdevice = pdevnode;
+		if (drvctl_find_parent (devnode, pdevnode) == TRUE) {
+			gchar *path;
+			if (strcmp (pdevnode, "mainbus0") == 0)
+				pdevice = "computer";
+			path = g_strdup_printf ("/org/freedesktop/Hal/devices/%s", pdevice);
+			hal_device_property_set_string (d, "info.parent", path);
+			g_free (path);
+		} else
+			hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/local");
+	}
+
+	hald_compute_udi (udi, sizeof (udi),
+			  "/org/freedesktop/Hal/devices/%s", devnode);
+	hal_device_set_udi (d, udi);
+
+#if notyet
+	if (di_prop_lookup_strings (DDI_DEV_T_ANY, node, "model", &s) > 0) {
+		hal_device_property_set_string (d, "info.product", s);
+	} else {
+		hal_device_property_set_string (d, "info.product", di_node_name (node));
+	}
+#else
+	hal_device_property_set_string (d, "info.product", devnode);
+#endif
+
+	hal_device_property_set_string (d, "netbsd.device", devnode);
+
+#if notyet
+	if ((driver_name = di_driver_name (node)) != NULL) {
+		hal_device_property_set_string (d, "info.solaris.driver",
+						driver_name);
+	}
+
+	/* inherit parent's claim attributes */
+	if (hal_device_property_get_bool (parent, "info.claimed")) {
+		s1 = hal_device_property_get_string (parent, "info.claimed.service");
+		if (s1 != NULL) {
+			hal_device_property_set_bool (d, "info.claimed", TRUE);
+			hal_device_property_set_string (d, "info.claimed.service", s1);
+		}
+	}
+#endif
+}
+
+/* device handlers, ordered specific to generic */
+static DevinfoDevHandler *devinfo_handlers[] = {
+	&devinfo_computer_handler,
+	&devinfo_cpu_handler,
+	&devinfo_optical_handler,
+#if notyet
+	&devinfo_scsipi_handler,
+	&devinfo_ide_handler,
+	&devinfo_scsi_handler,
+	&devinfo_floppy_handler,
+	&devinfo_usb_handler,
+	&devinfo_pci_handler,
+	&devinfo_lofi_handler,
+#endif
+	&devinfo_audio_handler,
+	&devinfo_audio_mixer_handler,
+	&devinfo_audio_dsp_handler,
+	&devinfo_video_handler,
+	&devinfo_mass_handler,
+	&devinfo_default_handler,
+	NULL
+};
+
+HalDevice *
+devinfo_add_node(HalDevice *parent, const char *devnode)
+{
+	HalDevice *d = NULL;
+	char	*devfs_path;
+	char	*device_type = NULL;
+	DevinfoDevHandler *handler;
+	int	i;
+
+	devfs_path = g_strdup_printf ("%s", devnode);
+
+#if notyet
+        (void) di_prop_lookup_strings (DDI_DEV_T_ANY, node, "device_type",
+	    &device_type);
+#else
+	device_type = "unknown";
+#endif
+
+	for (i = 0; (d == NULL) && (devinfo_handlers[i] != NULL); i++) {
+		handler = devinfo_handlers[i];
+		d = handler->add (parent, devnode, devfs_path, device_type);
+	}
+
+	g_free(devfs_path);
+
+	HAL_INFO (("add_node: %s", d ? hal_device_get_udi (d) : "none"));
+	return (d);
+}
+
+void
+devinfo_hotplug_enqueue(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler, int action, int front)
+{
+	HotplugEvent *hotplug_event;
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = action;
+	hotplug_event->type = HOTPLUG_EVENT_DEVFS;
+	hotplug_event->d = d;
+	strlcpy (hotplug_event->un.devfs.devfs_path, devfs_path,
+		sizeof (hotplug_event->un.devfs.devfs_path));
+	hotplug_event->un.devfs.handler = handler;
+
+	hotplug_event_enqueue (hotplug_event, front);
+}
+
+void
+devinfo_add_enqueue(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler)
+{
+	devinfo_hotplug_enqueue (d, devfs_path, handler, HOTPLUG_ACTION_ADD, 0);
+}
+
+void
+devinfo_add_enqueue_at_front(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler)
+{
+	devinfo_hotplug_enqueue (d, devfs_path, handler, HOTPLUG_ACTION_ADD, 1);
+}
+
+void
+devinfo_remove_enqueue(gchar *devfs_path, DevinfoDevHandler *handler)
+{
+	devinfo_hotplug_enqueue (NULL, devfs_path, handler, HOTPLUG_ACTION_REMOVE, 0);
+}
+
+void
+devinfo_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
+{
+        void *end_token = (void *) userdata1;
+
+        /* Move from temporary to global device store */
+        hal_device_store_remove (hald_get_tdl (), d);
+        hal_device_store_add (hald_get_gdl (), d);
+
+        hotplug_event_end (end_token);
+}
+
+void
+devinfo_callouts_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2)
+{
+        void *end_token = (void *) userdata1;
+
+        /* Discard device if probing reports failure */
+        if (exit_type != HALD_RUN_SUCCESS || (return_code != 0)) {
+		HAL_INFO (("Probing for %s failed %d", hal_device_get_udi (d), return_code));
+                hal_device_store_remove (hald_get_tdl (), d);
+                g_object_unref (d);
+                hotplug_event_end (end_token);
+		return;
+        }
+
+        /* Merge properties from .fdi files */
+        di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
+        di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
+
+	hal_util_callout_device_add (d, devinfo_callouts_add_done, end_token, NULL);
+}
+
+void
+devinfo_callouts_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
+{
+        void *end_token = (void *) userdata1;
+	DevinfoDevHandler *handler = (DevinfoDevHandler *) userdata2;
+	void (*probing_done) (HalDevice *, guint32, gint, char **, gpointer, gpointer);
+	const gchar *prober;
+	int prober_timeout;
+
+        if (hal_device_property_get_bool (d, "info.ignore")) {
+		HAL_INFO (("Preprobing merged info.ignore==TRUE"));
+
+                /* Leave device with info.ignore==TRUE so we won't pick up children */
+		hal_device_property_remove (d, "info.category");
+		hal_device_property_remove (d, "info.capabilities");
+
+		hal_device_store_remove (hald_get_tdl (), d);
+		hal_device_store_add (hald_get_gdl (), d);
+
+		hotplug_event_end (end_token);
+		return;
+        }
+
+        if (handler != NULL && handler->get_prober != NULL) {
+                prober = handler->get_prober (d, &prober_timeout);
+        } else {
+                prober = NULL;
+	}
+
+	if (handler->probing_done != NULL) {
+		probing_done = handler->probing_done;
+	} else {
+		probing_done = devinfo_callouts_probing_done;
+	}
+
+        if (prober != NULL) {
+                /* probe the device */
+		HAL_INFO(("Probing udi=%s", hal_device_get_udi (d)));
+                hald_runner_run (d,
+				prober, NULL,
+				prober_timeout,
+				probing_done,
+				(gpointer) end_token, (gpointer) handler);
+	} else {
+		probing_done (d, 0, 0, NULL, userdata1, userdata2);
+	}
+}
+
+/* This is the beginning of hotplug even handling */
+void
+hotplug_event_begin_add_devinfo (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token)
+{
+	HAL_INFO(("Preprobing udi=%s", hal_device_get_udi (d)));
+
+	if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) {
+		HAL_INFO (("Ignoring device since parent has info.ignore==TRUE"));
+
+		hotplug_event_end (end_token);
+		return;
+	}
+
+        /* add to TDL so preprobing callouts and prober can access it */
+        hal_device_store_add (hald_get_tdl (), d);
+
+#if 0
+        /* Process preprobe fdi files */
+        di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
+#endif
+
+        /* Run preprobe callouts */
+        hal_util_callout_device_preprobe (d, devinfo_callouts_preprobing_done, end_token, handler);
+}
+
+void
+devinfo_remove (gchar *devfs_path)
+{
+	devinfo_remove_enqueue ((gchar *)devfs_path, NULL);
+}
+
+/* generate hotplug event for each device in this branch */
+void
+devinfo_remove_branch (gchar *devnode, HalDevice *d)
+{
+	GSList *i;
+	GSList *children;
+	HalDevice *child;
+	char *child_devfs_path;
+
+	if (d == NULL) {
+		d = hal_device_store_match_key_value_string (hald_get_gdl (),
+			"netbsd.device", devnode);
+		if (d == NULL)
+			return;
+	}
+
+	HAL_INFO (("remove_branch: %s %s\n", devnode, hal_device_get_udi (d)));
+
+	/* first remove children */
+	children = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
+		"info.parent", hal_device_get_udi (d));
+        for (i = children; i != NULL; i = g_slist_next (i)) {
+                child = HAL_DEVICE (i->data);
+		HAL_INFO (("remove_branch: child %s\n", hal_device_get_udi (child)));
+		devinfo_remove_branch ((gchar *)hal_device_property_get_string (child, "netbsd.device"), child);
+	}
+	g_slist_free (children);
+	HAL_INFO (("remove_branch: done with children"));
+
+	/* then remove self */
+	HAL_INFO (("remove_branch: queueing %s", devnode));
+	devinfo_remove_enqueue (devnode, NULL);
+}
+
+void
+devinfo_callouts_remove_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
+{
+        void *end_token = (void *) userdata1;
+
+        HAL_INFO (("Remove callouts completed udi=%s", hal_device_get_udi (d)));
+
+        if (!hal_device_store_remove (hald_get_gdl (), d)) {
+                HAL_WARNING (("Error removing device"));
+        }
+        g_object_unref (d);
+
+        hotplug_event_end (end_token);
+}
+
+void
+hotplug_event_begin_remove_devinfo (HalDevice *d, gchar *devfs_path, void *end_token)
+{
+#if notyet
+	if (hal_device_has_capability (d, "volume")) {
+		devinfo_volume_hotplug_begin_remove (d, devfs_path, end_token);
+	} else {
+		hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
+	}
+#else
+#warning hotplug_event_begin_remove_devinfo TODO
+	hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
+#endif
+}
+
+gboolean
+devinfo_device_rescan (HalDevice *d)
+{
+#if notyet
+	if (hal_device_has_capability (d, "block")) {
+		return (devinfo_storage_device_rescan (d));
+	} else {
+		return (FALSE);
+	}
+#else
+#warning devinfo_device_rescan TODO
+	return FALSE;
+#endif
+}
diff --git a/hal/files/hald-netbsd/devinfo.h b/hal/files/hald-netbsd/devinfo.h
new file mode 100644
index 0000000000..6ed0dd0f5e
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ *
+ * devinfo.h : definitions for libdevinfo-based device enumeration
+ *
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef DEVINFO_H
+#define DEVINFO_H
+
+#include <glib.h>
+
+#include <prop/proplib.h>
+
+#include "../hald.h"
+#include "../device_info.h"
+
+typedef struct DevinfoDevHandler_s
+{
+	HalDevice *(*add) (HalDevice *parent, const char *devnode, char *devfs_path, char *device_type);
+
+	/* yet unused */
+	void (*remove) (char *devfs_path);
+
+	void (*hotplug_begin_add) (HalDevice *d, HalDevice *parent, struct DevinfoDevHandler_s *handler, void *end_token);
+
+	void (*hotplug_begin_remove) (HalDevice *d, struct DevinfoDevHandler_s *handler, void *end_token);
+
+	void (*probing_done) (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2);
+
+	const gchar *(*get_prober) (HalDevice *d, int *timeout);
+} DevinfoDevHandler;
+
+#define PROP_INT(d, node, v, diprop, halprop) \
+	if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, diprop, &(v)) > 0) { \
+		hal_device_property_set_int (d, halprop, *(v)); \
+	}
+
+#define PROP_STR(d, node, v, diprop, halprop) \
+	if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, diprop, &(v)) > 0) { \
+		hal_device_property_set_string (d, halprop, v); \
+	}
+
+#define PROP_BOOL(d, node, v, diprop, halprop) \
+	hal_device_property_set_bool (d, halprop, \
+	    (di_prop_lookup_ints(DDI_DEV_T_ANY, node, diprop, &(v)) >= 0));
+
+#define	NELEM(a)	(sizeof (a) / sizeof (*(a)))
+
+void devinfo_add (HalDevice *parent, gchar *path);
+HalDevice *devinfo_add_node(HalDevice *parent, const char *devnode);
+void devinfo_set_default_properties (HalDevice *d, HalDevice *parent, const char *devnode, char *devfs_path);
+void devinfo_callouts_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2);
+void devinfo_callouts_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error,
+	gpointer userdata1, gpointer userdata2);
+void devinfo_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2);
+void devinfo_callouts_remove_done (HalDevice *d, gpointer userdata1, gpointer userdata2);
+void hotplug_event_begin_add_devinfo (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
+void devinfo_remove (gchar *path);
+void devinfo_remove_branch (gchar *path, HalDevice *d);
+void hotplug_event_begin_remove_devinfo (HalDevice *d, gchar *devfs_path, void *end_token);
+void devinfo_hotplug_enqueue(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler, int action, int front);
+void devinfo_add_enqueue(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler);
+void devinfo_add_enqueue_at_front(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler);
+void devinfo_remove_enqueue(gchar *devfs_path, DevinfoDevHandler *handler);
+gboolean devinfo_device_rescan (HalDevice *d);
+
+#endif /* DEVINFO_H */
diff --git a/hal/files/hald-netbsd/devinfo_acpi.h b/hal/files/hald-netbsd/devinfo_acpi.h
new file mode 100644
index 0000000000..6e841cc48e
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_acpi.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ *
+ * devinfo_acpi.h : definitions for acpi devices
+ *
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef DEVINFO_ACPI_H
+#define	DEVINFO_ACPI_H
+
+#include "devinfo.h"
+
+extern DevinfoDevHandler devinfo_acpi_handler;
+extern DevinfoDevHandler devinfo_power_button_handler;
+
+#define	MINOR_SHIFT			8
+#define	MINOR2TYPE(minor)		((minor) >> MINOR_SHIFT)
+
+/* Battery device types */
+enum batt_type {
+	BATT_TYPE_UNKNOWN = -1,
+	BATT_TYPE_CBAT,
+	BATT_TYPE_AC,
+	BATT_TYPE_SBAT
+};
+
+HalDevice *devinfo_battery_add_major(HalDevice *parent, const char *devnode,
+    char *devfs_path, char *device_type, gboolean rescan, HalDevice *battery_d);
+void devinfo_acpi_add_minor(HalDevice *parent, const char *devnode,
+    char *minor_path, dev_t dev);
+void devinfo_battery_remove_minor(char *parent_devfs_path, gchar *udi);
+void devinfo_battery_rescan(char *parent_devfs_path, gchar *udi);
+const gchar *devinfo_acpi_get_prober(HalDevice *d, int *timeout);
+void devinfo_power_button_event(void);
+void devinfo_brightness_hotkeys_event(char *subclass);
+
+void devinfo_lid_event(char *subclass, gchar *udi);
+gboolean devinfo_lid_rescan(HalDevice *d);
+
+#endif /* DEVINFO_ACPI_H */
diff --git a/hal/files/hald-netbsd/devinfo_audio.c b/hal/files/hald-netbsd/devinfo_audio.c
new file mode 100644
index 0000000000..faf0063fe6
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_audio.c
@@ -0,0 +1,233 @@
+/* $NetBSD: devinfo_audio.c,v 1.2 2008/11/27 18:00:44 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2008 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/audioio.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <paths.h>
+#include <unistd.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "../ids.h"
+#include "hotplug.h"
+#include "devinfo.h"
+#include "devinfo_audio.h"
+#include "drvctl.h"
+
+HalDevice *devinfo_audio_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type);
+HalDevice *devinfo_audio_mixer_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type);
+HalDevice *devinfo_audio_dsp_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type);
+
+DevinfoDevHandler devinfo_audio_handler = {
+	devinfo_audio_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+DevinfoDevHandler devinfo_audio_mixer_handler = {
+	devinfo_audio_mixer_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+DevinfoDevHandler devinfo_audio_dsp_handler = {
+	devinfo_audio_dsp_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+HalDevice *
+devinfo_audio_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
+{
+	HalDevice *d = NULL, *mixer, *dsp;
+	prop_dictionary_t dict;
+	const char *driver, *parent_udi;
+	char *childnode;
+	int16_t unit;
+	char *audioctl;
+	struct audio_device audiodev;
+	int fd;
+
+	if (drvctl_find_device (devnode, &dict) == FALSE || dict == NULL)
+		return NULL;
+
+	if (prop_dictionary_get_int16 (dict, "device-unit", &unit) == false ||
+	    prop_dictionary_get_cstring_nocopy (dict, "device-driver", &driver) == false) {
+		prop_object_release (dict);
+		return NULL;
+	}
+
+	if (strcmp (driver, "audio") != 0) {
+		prop_object_release (dict);
+		return NULL;
+	}
+
+	audioctl = g_strdup_printf (_PATH_AUDIOCTL "%d", unit);
+	fd = open (audioctl, O_RDONLY);
+	if (fd < 0) {
+		HAL_WARNING (("couldn't open %s: %s", audioctl, strerror(errno)));
+		goto done;
+	}
+
+	if (ioctl (fd, AUDIO_GETDEV, &audiodev) == -1) {
+		HAL_WARNING (("couldn't query %s: %s", audioctl, strerror(errno)));
+		goto done;
+	}
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, devnode, devfs_path);
+	hal_device_add_capability (d, "sound");
+	hal_device_property_set_string (d, "info.category", "sound");
+	hal_device_property_set_string (d, "info.subsystem", "sound");
+
+	hal_device_property_set_int (d, "sound.card", unit);
+	hal_device_property_set_string (d, "sound.card_id", audiodev.name);
+	hal_device_property_set_string (d, "netbsd.sound.hardware", audiodev.config);
+
+	parent_udi = hal_device_property_get_string (parent, "info.udi");
+	if (parent_udi)
+		hal_device_property_set_string (d, "sound.originating_device", parent_udi);
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_audio_handler);
+
+	childnode = g_strdup_printf ("oss_mixer_%d", unit);
+	devinfo_add_node (d, childnode);
+	g_free (childnode);
+
+	childnode = g_strdup_printf ("oss_dsp_%d", unit);
+	devinfo_add_node (d, childnode);
+	g_free (childnode);
+
+done:
+	if (dict)
+		prop_object_release (dict);
+	if (audioctl)
+		g_free (audioctl);
+	if (fd >= 0)
+		close (fd);
+
+	return d;
+}
+
+HalDevice *
+devinfo_audio_mixer_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
+{
+	HalDevice *d = NULL;
+	char *device_file, *parent_udi, *card_id, *device_id;
+	int16_t unit;
+
+	if (strstr (devnode, "oss_mixer_") != devnode)
+		return NULL;
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, devnode, devfs_path);
+	hal_device_add_capability (d, "oss");
+	hal_device_property_set_string (d, "info.category", "oss");
+	hal_device_property_set_string (d, "info.subsystem", "sound");
+
+	card_id = hal_device_property_get_string (parent, "sound.card_id");
+	hal_device_property_set_string (d, "oss.card_id", card_id);
+	unit = hal_device_property_get_int (parent, "sound.card");
+	hal_device_property_set_int (d, "oss.card", unit);
+	hal_device_property_set_int (d, "oss.device", unit + 16);
+	device_id = hal_device_property_get_string (parent, "netbsd.sound.hardware");
+	hal_device_property_set_string (d, "oss.device_id", device_id);
+	hal_device_property_set_string (d, "oss.type", "mixer");
+
+	device_file = g_strdup_printf (_PATH_MIXER "%d", unit);
+	hal_device_property_set_string (d, "oss.device_file", device_file);
+	g_free (device_file);
+
+	parent_udi = hal_device_property_get_string (parent, "info.udi");
+	if (parent_udi)
+		hal_device_property_set_string (d, "sound.originating_device", parent_udi);
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_audio_mixer_handler);
+
+	return d;
+}
+
+HalDevice *
+devinfo_audio_dsp_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
+{
+	HalDevice *d = NULL;
+	char *device_file, *parent_udi, *card_id, *device_id;
+	int16_t unit;
+
+	if (strstr (devnode, "oss_dsp_") != devnode)
+		return NULL;
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, devnode, devfs_path);
+	hal_device_add_capability (d, "oss");
+	hal_device_property_set_string (d, "info.category", "oss");
+	hal_device_property_set_string (d, "info.subsystem", "sound");
+
+	card_id = hal_device_property_get_string (parent, "sound.card_id");
+	hal_device_property_set_string (d, "oss.card_id", card_id);
+	unit = hal_device_property_get_int (parent, "sound.card");
+	hal_device_property_set_int (d, "oss.card", unit);
+	hal_device_property_set_int (d, "oss.device", unit);
+	device_id = hal_device_property_get_string (parent, "netbsd.sound.hardware");
+	hal_device_property_set_string (d, "oss.device_id", device_id);
+	hal_device_property_set_string (d, "oss.type", "pcm");
+
+	device_file = g_strdup_printf (_PATH_SOUND "%d", unit);
+	hal_device_property_set_string (d, "oss.device_file", device_file);
+	g_free (device_file);
+
+	parent_udi = hal_device_property_get_string (parent, "info.udi");
+	if (parent_udi)
+		hal_device_property_set_string (d, "sound.originating_device", parent_udi);
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_audio_dsp_handler);
+
+	return d;
+}
diff --git a/hal/files/hald-netbsd/devinfo_audio.h b/hal/files/hald-netbsd/devinfo_audio.h
new file mode 100644
index 0000000000..0c60623bcd
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_audio.h
@@ -0,0 +1,38 @@
+/* $NetBSD: devinfo_audio.h,v 1.1 2008/11/27 16:07:14 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2008 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DEVINFO_AUDIO_H
+#define DEVINFO_AUDIO_H
+
+#include "devinfo.h"
+
+extern DevinfoDevHandler devinfo_audio_handler;
+extern DevinfoDevHandler devinfo_audio_mixer_handler;
+extern DevinfoDevHandler devinfo_audio_dsp_handler;
+
+#endif /* DEVINFO_AUDIO_H */
diff --git a/hal/files/hald-netbsd/devinfo_cpu.h b/hal/files/hald-netbsd/devinfo_cpu.h
new file mode 100644
index 0000000000..441acdf10e
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_cpu.h
@@ -0,0 +1,19 @@
+/***************************************************************************
+ *
+ * devinfo_cpu.h : definition for cpu devices
+ *
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef DEVINFO_CPU_H
+#define DEVINFO_CPU_H
+
+#include "devinfo.h"
+
+extern DevinfoDevHandler devinfo_cpu_handler;
+
+#endif /* DEVINFO_CPU_H */
diff --git a/hal/files/hald-netbsd/devinfo_mass.c b/hal/files/hald-netbsd/devinfo_mass.c
new file mode 100644
index 0000000000..4c125752dc
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_mass.c
@@ -0,0 +1,418 @@
+/* $NetBSD: devinfo_mass.c,v 1.6 2015/01/31 12:08:55 wiz Exp $ */
+
+/*-
+ * Copyright (c) 2008 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/disklabel.h>
+#include <sys/bootblock.h>
+#include <sys/ioctl.h>
+#include <sys/scsiio.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <paths.h>
+#include <unistd.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "../ids.h"
+#include "hotplug.h"
+#include "devinfo.h"
+#include "devinfo_mass.h"
+#include "drvctl.h"
+
+#include <libvolume_id.h>
+
+HalDevice *devinfo_mass_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type);
+HalDevice *devinfo_mass_disklabel_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type);
+
+/* XXX from devinfo_optical */
+extern bool scsi_command(int, void *, size_t, void *, size_t, int, int);
+
+DevinfoDevHandler devinfo_mass_handler = {
+	devinfo_mass_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+DevinfoDevHandler devinfo_mass_disklabel_handler = {
+	devinfo_mass_disklabel_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static char *
+rtrim_copy(char *src, int len)
+{
+        char    *dst, *p;
+
+	if (len == 0) {
+		len = strlen(src);
+	}
+	if ((dst = calloc(1, len + 1)) != NULL) {
+		strncpy(dst, src, len);
+		p = dst + len - 1;
+		while ((p >= dst) && (isspace((int)*p))) {
+			*p-- = '\0';
+		}
+	}
+	return (dst);
+}
+
+static const char *
+devinfo_mass_get_fstype(uint8_t fstype)
+{
+	switch (fstype) {
+	case FS_BSDFFS:
+		return "ffs";
+	case FS_MSDOS:
+		return "vfat";
+	case FS_EX2FS:
+		return "ext2";
+	case FS_NTFS:
+		return "ntfs";
+	case FS_APPLEUFS:
+		return "ffs";
+	default:
+		return NULL;
+	}
+}
+
+static uint8_t
+devinfo_mass_get_mbrtype(uint8_t fstype)
+{
+	switch (fstype) {
+	case FS_BSDFFS:
+		return MBR_PTYPE_NETBSD;
+	case FS_MSDOS:
+		return MBR_PTYPE_FAT32;	/* XXX */
+	case FS_EX2FS:
+		return MBR_PTYPE_LNXEXT2;
+	case FS_NTFS:
+		return MBR_PTYPE_NTFS;
+	case FS_APPLEUFS:
+		return MBR_PTYPE_APPLE_UFS;
+	default:
+		return MBR_PTYPE_UNUSED;
+	}
+}
+
+HalDevice *
+devinfo_mass_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
+{
+	HalDevice *d = NULL, *gparent = NULL;
+	prop_dictionary_t dict;
+	struct disklabel label;
+	struct stat st;
+	const char *driver;
+	char *rdevpath, *devpath;
+	char *childnode;
+	char *parent_devnode, *gparent_devnode = NULL;
+	char *gparent_udi;
+	int16_t unit;
+	int i, fd;
+	struct scsipi_inquiry_data inqbuf;
+	struct scsipi_inquiry cmd;
+	bool scsiinq_status;
+	char *storage_model = NULL, *storage_vendor = NULL;
+
+	if (drvctl_find_device (devnode, &dict) == FALSE || dict == NULL)
+		return NULL;
+
+	if (prop_dictionary_get_int16 (dict, "device-unit", &unit) == false ||
+	    prop_dictionary_get_cstring_nocopy (dict, "device-driver", &driver) == false) {
+		prop_object_release (dict);
+		return NULL;
+	}
+
+	if (strcmp (driver, "wd") != 0 && strcmp (driver, "sd") != 0 &&
+	    strcmp (driver, "ld") != 0) {
+		prop_object_release (dict);
+		return NULL;
+	}
+
+	sleep (1);
+
+	devpath = g_strdup_printf ("/dev/%s%c", devnode, RAW_PART + 'a');
+	rdevpath = g_strdup_printf ("/dev/r%s%c", devnode, RAW_PART + 'a');
+	HAL_INFO (("  going to open %s", rdevpath));
+	fd = open (rdevpath, O_RDONLY);
+	if (fd < 0) {
+		HAL_WARNING (("couldn't open %s: %s", rdevpath, strerror (errno)));
+		g_free (rdevpath);
+		g_free (devpath);
+		return NULL;
+	}
+
+	HAL_INFO (("  going to DIOCGDINFO %s", rdevpath));
+	if (ioctl (fd, DIOCGDINFO, &label) == -1) {
+		HAL_WARNING (("DIOCGDINFO failed on %s: %s", rdevpath, strerror (errno)));
+		g_free (rdevpath);
+		g_free (devpath);
+		close (fd);
+		return NULL;
+	}
+
+	if (strcmp (driver, "sd") == 0) {
+		memset(&cmd, 0, sizeof (cmd));
+		memset(&inqbuf, 0, sizeof (inqbuf));
+		cmd.opcode = INQUIRY;
+		cmd.length = sizeof (inqbuf);
+
+		scsiinq_status = scsi_command (fd, &cmd, sizeof (cmd), &inqbuf, sizeof (inqbuf), 10000, SCCMD_READ);
+	} else
+		scsiinq_status = false;
+
+	close (fd);
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, devnode, devfs_path);
+
+	hal_device_add_capability (d, "block");
+	hal_device_property_set_string (d, "info.subsystem", "block");
+	hal_device_property_set_string (d, "block.device", devpath);
+	if (stat (devpath, &st) == 0) {
+		hal_device_property_set_int (d, "block.major", major (st.st_rdev));
+		hal_device_property_set_int (d, "block.minor", minor (st.st_rdev));
+	}
+	hal_device_property_set_bool (d, "block.is_volume", FALSE);
+	hal_device_property_set_bool (d, "block.no_partitions", FALSE);
+	hal_device_property_set_bool (d, "block.have_scanned", TRUE);
+
+	hal_device_add_capability (d, "storage");
+	hal_device_property_set_string (d, "info.category", "storage");
+	parent_devnode = hal_device_property_get_string (parent, "netbsd.device");
+	gparent_udi = hal_device_property_get_string (parent, "info.parent");
+	if (gparent_udi) {
+		gparent = hal_device_store_find (hald_get_gdl (), gparent_udi);
+		if (gparent)
+			gparent_devnode = hal_device_property_get_string (gparent, "netbsd.device");
+	}
+	if (gparent_devnode && strstr (gparent_devnode, "umass") == gparent_devnode)
+		hal_device_property_set_string (d, "storage.bus", "usb");
+	else if (parent_devnode && strstr (parent_devnode, "atabus") == parent_devnode)
+		hal_device_property_set_string (d, "storage.bus", "ide");
+	else
+		hal_device_property_set_string (d, "storage.bus", "scsi");
+	hal_device_property_set_string (d, "storage.device_type", "disk");
+	hal_device_property_set_bool (d, "storage.removable", label.d_flags & D_REMOVABLE ? TRUE : FALSE);
+	if (label.d_flags & D_REMOVABLE) {
+		hal_device_property_set_bool (d, "storage.removable.media_available", TRUE);
+		hal_device_property_set_uint64 (d, "storage.removable.media_size",
+		    (uint64_t)label.d_secsize * (uint64_t)label.d_secperunit);
+		hal_device_property_set_uint64 (d, "storage.size", 0);
+		hal_device_property_set_bool (d, "storage.hotpluggable", TRUE);
+		hal_device_property_set_bool (d, "storage.automount_enabled_hint", TRUE);
+	} else {
+		hal_device_property_set_bool (d, "storage.removable.media_available", FALSE);
+		hal_device_property_set_uint64 (d, "storage.removable.media_size", 0);
+		hal_device_property_set_uint64 (d, "storage.size",
+		    (uint64_t)label.d_secsize * (uint64_t)label.d_secperunit);
+		hal_device_property_set_bool (d, "storage.hotpluggable", FALSE);
+		hal_device_property_set_bool (d, "storage.automount_enabled_hint", FALSE);
+	}
+	hal_device_property_set_bool (d, "storage.no_partitions_hint", FALSE);
+	hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
+	hal_device_property_set_bool (d, "storage.removable.support_async_notification", FALSE);
+	hal_device_property_set_string (d, "storage.partitioning_scheme", "mbr");
+	hal_device_property_set_string (d, "storage.originating_device",
+	    hal_device_property_get_string (d, "info.udi"));
+
+	if (scsiinq_status == true) {
+		storage_model = rtrim_copy(inqbuf.product, sizeof (inqbuf.product));
+		storage_vendor = rtrim_copy(inqbuf.vendor, sizeof (inqbuf.vendor));
+	}
+
+	if (storage_model) {
+		hal_device_property_set_string (d, "storage.model", storage_model);
+		free (storage_model);
+	} else
+		hal_device_property_set_string (d, "storage.model", label.d_packname);
+
+	if (storage_vendor) {
+		hal_device_property_set_string (d, "storage.vendor", storage_vendor);
+		free (storage_vendor);
+	} else
+		hal_device_property_set_string (d, "storage.vendor", label.d_typename);
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_mass_handler);
+
+	for (i = 0; i < MAXPARTITIONS; i++) {
+		const char *fstype;
+
+		fstype = devinfo_mass_get_fstype(label.d_partitions[i].p_fstype);
+		if (fstype == NULL)
+			continue;
+
+		childnode = g_strdup_printf ("%s%c", devnode, 'a' + i);
+		HAL_INFO (("  adding %s on %s", childnode, rdevpath));
+		devinfo_mass_disklabel_add (d, childnode, childnode, childnode);
+		g_free (childnode);
+	}
+
+	HAL_INFO (("  returning"));
+	g_free (rdevpath);
+	g_free (devpath);
+
+done:
+	prop_object_release (dict);
+
+	return d;
+}
+
+HalDevice *
+devinfo_mass_disklabel_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
+{
+	HalDevice *d = NULL;
+	struct disklabel label;
+	struct partition *part;
+	struct stat st;
+	const char *driver;
+	char *devpath, *rdevpath, *partname;
+	char *childnode;
+	char unit;
+	struct volume_id *vid;
+	uint64_t psize, msize;
+	int i, fd;
+
+	partname = devnode;
+	unit = partname[strlen (partname) - 1] - 'a';
+
+	if (unit >= MAXPARTITIONS)
+		return NULL;
+
+	devpath = g_strdup_printf ("/dev/%s", partname);
+	rdevpath = g_strdup_printf ("/dev/r%s", partname);
+	fd = open (rdevpath, O_RDONLY);
+	if (fd < 0) {
+		HAL_WARNING (("couldn't open %s: %s", rdevpath, strerror (errno)));
+		g_free (rdevpath);
+		return NULL;
+	}
+
+	if (ioctl (fd, DIOCGDINFO, &label) == -1) {
+		HAL_WARNING (("DIOCGDINFO failed on %s: %s", rdevpath, strerror (errno)));
+		g_free (rdevpath);
+		close (fd);
+		return NULL;
+	}
+	part = &label.d_partitions[unit];
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, devnode, devfs_path);
+
+	hal_device_add_capability (d, "block");
+	hal_device_property_set_string (d, "info.subsystem", "block");
+	hal_device_property_set_string (d, "info.category", "volume");
+	hal_device_property_set_string (d, "block.device", devpath);
+	hal_device_property_set_string (d, "block.storage_device",
+	    hal_device_property_get_string (parent, "info.udi"));
+
+	if (stat (devpath, &st) == 0) {
+		hal_device_property_set_int (d, "block.major", major (st.st_rdev));
+		hal_device_property_set_int (d, "block.minor", minor (st.st_rdev));
+	}
+
+	hal_device_property_set_bool (d, "block.is_volume", TRUE);
+	hal_device_property_set_bool (d, "block.no_partitions", FALSE);
+	hal_device_property_set_bool (d, "block.have_scanned", TRUE);
+
+	hal_device_add_capability (d, "volume");
+	hal_device_property_set_bool (d, "volume.ignore", FALSE);
+	hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
+	hal_device_property_set_bool (d, "volume.is_mounted_read_only", FALSE);
+	hal_device_property_set_string (d, "volume.mount_point", "");
+	hal_device_property_set_string (d, "volume.fsusage", "filesystem");
+	hal_device_property_set_string (d, "volume.fstype", devinfo_mass_get_fstype (part->p_fstype));
+	hal_device_property_set_bool (d, "volume.is_disc", FALSE);
+
+	hal_device_property_set_string (d, "volume.label", "");
+	hal_device_property_set_string (d, "volume.partition.label", "");
+	hal_device_property_set_string (d, "volume.uuid", "");
+	hal_device_property_set_string (d, "volume.partition.uuid", "");
+
+	psize = (uint64_t)part->p_size * (uint64_t)label.d_secsize;
+	msize = (uint64_t)label.d_secsize * (uint64_t)label.d_secperunit;
+
+	hal_device_property_set_uint64 (d, "volume.size", psize);
+	hal_device_property_set_int (d, "volume.block_size", label.d_secsize);
+	hal_device_property_set_uint64 (d, "volume.num_blocks", part->p_size);
+	hal_device_property_set_uint64 (d, "volume.partition.media_size", msize);
+
+	hal_device_property_set_bool (d, "volume.is_partition", TRUE);
+	hal_device_property_set_int (d, "volume.partition.number", unit);
+	hal_device_property_set_string (d, "volume.partition.scheme", "mbr");
+
+	vid = volume_id_open_fd (fd);
+	if (vid) {
+		if (volume_id_probe_all (vid, 0, psize) == 0) {
+			const char *type,*fstype;
+
+			hal_device_property_set_string (d, "volume.label", vid->label);
+			hal_device_property_set_string (d, "volume.partition.label", vid->label);
+			hal_device_property_set_string (d, "volume.uuid", vid->uuid);
+			hal_device_property_set_string (d, "volume.partition.uuid", vid->uuid);
+
+			if ( type && volume_id_get_type (vid, &type)) {
+				fstype=devinfo_mass_get_fstype (part->p_fstype);
+				if (strcmp (type, fstype)) {
+					HAL_INFO (("%s disklabel reports [%s] but libvolume_id says it is "
+					    "[%s], assuming disklabel is incorrect",
+					    devpath, fstype, type));
+					hal_device_property_set_string (d, "volume.fstype", type);
+				}
+			}
+		}
+		volume_id_close (vid);
+	}
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_mass_disklabel_handler);
+
+	close (fd);
+
+	g_free (rdevpath);
+	g_free (devpath);
+
+	return d;
+}
diff --git a/hal/files/hald-netbsd/devinfo_mass.h b/hal/files/hald-netbsd/devinfo_mass.h
new file mode 100644
index 0000000000..1b7bdc91f4
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_mass.h
@@ -0,0 +1,37 @@
+/* $NetBSD: devinfo_mass.h,v 1.1 2008/12/01 02:02:33 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2008 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DEVINFO_MASS_H
+#define DEVINFO_MASS_H
+
+#include "devinfo.h"
+
+extern DevinfoDevHandler devinfo_mass_handler;
+extern DevinfoDevHandler devinfo_mass_disklabel_handler;
+
+#endif /* DEVINFO_MASS_H */
diff --git a/hal/files/hald-netbsd/devinfo_misc.c b/hal/files/hald-netbsd/devinfo_misc.c
new file mode 100644
index 0000000000..ffb8d2a079
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_misc.c
@@ -0,0 +1,168 @@
+/***************************************************************************
+ *
+ * devinfo_misc : misc devices
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/utsname.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "devinfo_misc.h"
+#include "drvctl.h"
+
+static HalDevice *devinfo_computer_add(HalDevice *, const char *, char *, char *);
+static HalDevice *devinfo_cpu_add(HalDevice *, const char *, char *,char *);
+static HalDevice *devinfo_default_add(HalDevice *, const char *, char *, char *);
+
+DevinfoDevHandler devinfo_computer_handler = {
+        devinfo_computer_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+        NULL
+};
+DevinfoDevHandler devinfo_cpu_handler = {
+        devinfo_cpu_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+        NULL
+};
+DevinfoDevHandler devinfo_default_handler = {
+        devinfo_default_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+        NULL
+};
+
+static HalDevice *
+devinfo_computer_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
+{
+	HalDevice *d;
+	struct utsname un;
+	char acpi_supported_states[20];
+	size_t len = sizeof(acpi_supported_states);
+
+	if (strcmp (devnode, "mainbus0") != 0) {
+		return (NULL);
+	}
+
+	HAL_INFO (("devinfo_computer_add parent=%p devnode=%s devfs_path=%s device_type=%s",
+	    parent, devnode, devfs_path, device_type));
+
+	d = hal_device_new ();
+
+        hal_device_property_set_string (d, "info.subsystem", "unknown");
+        hal_device_property_set_string (d, "info.product", "Computer");
+        hal_device_set_udi (d, "/org/freedesktop/Hal/devices/computer");
+	hal_device_property_set_string (d, "netbsd.device", devnode);
+
+	if (uname (&un) >= 0) {
+		hal_device_property_set_string (d, "system.kernel.name", un.sysname);
+		hal_device_property_set_string (d, "system.kernel.version", un.release);
+		hal_device_property_set_string (d, "system.kernel.machine", un.machine);
+	}
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_computer_handler);
+
+	if (sysctlbyname ("hw.acpi.supported_states", acpi_supported_states, &len, NULL, 0) == 0 ||
+	    sysctlbyname ("hw.acpi.sleep.states", acpi_supported_states, &len, NULL, 0) == 0) {
+		hal_device_property_set_string (d, "power_management.type", "acpi");
+		if (strstr (acpi_supported_states, "S3") != NULL)
+			hal_device_property_set_bool (d, "power_management.can_suspend", TRUE);
+		else
+			hal_device_property_set_bool (d, "power_management.can_suspend", FALSE);
+
+		hal_device_property_set_bool (d, "power_management.can_hibernate", FALSE);
+	}
+
+	if (drvctl_find_device ("acpibat0", NULL) == TRUE)
+		hal_device_property_set_string (d, "system.formfactor", "laptop");
+	else
+		hal_device_property_set_string (d, "system.formfactor", "desktop");	/* XXX */
+
+	devinfo_add_enqueue (d, devnode, &devinfo_default_handler);
+
+	return d;
+}
+
+static HalDevice *
+devinfo_cpu_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
+{
+	HalDevice *d;
+
+	if (strncmp(devnode, "cpu", 3) != 0) {
+		return (NULL);
+	}
+
+	HAL_INFO (("devinfo_cpu_add: parent=%p devnode=%s devfs_path=%s device_type=%s",
+	    parent, devnode, devfs_path, device_type));
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, devnode, devnode);
+	hal_device_add_capability (d, "processor");
+
+	devinfo_add_enqueue (d, devnode, &devinfo_cpu_handler);
+
+	return (d);
+}
+
+static void
+devinfo_default_apply_quirks(HalDevice *d, const char *devnode)
+{
+
+/* acpiacad(4) */
+	if (strncmp (devnode, "acpiacad", 8) == 0) {
+		HAL_INFO (("%s: applying acpiacad quirks",devnode));
+		hal_device_add_capability (d, "ac_adapter");
+
+/* acpibat(4) */
+	} else if (strncmp (devnode, "acpibat", 7) == 0) {
+		HAL_INFO (("%s: applying acpibat quirks",devnode));
+		hal_device_add_capability (d, "battery");
+		hal_device_property_set_string (d, "battery.type", "primary");
+	}
+
+}
+
+static HalDevice *
+devinfo_default_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
+{
+	char *driver_name;
+	const char *parent_path;
+	HalDevice *d;
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, devnode, devnode);
+
+	devinfo_default_apply_quirks (d, devnode);
+
+	devinfo_add_enqueue (d, devnode, &devinfo_default_handler);
+
+	return (d);
+}
diff --git a/hal/files/hald-netbsd/devinfo_misc.h b/hal/files/hald-netbsd/devinfo_misc.h
new file mode 100644
index 0000000000..ef666ff38c
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_misc.h
@@ -0,0 +1,21 @@
+/***************************************************************************
+ *
+ * devinfo_misc.h : definitions for misc devices
+ *
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef DEVINFO_MISC_H
+#define DEVINFO_MISC_H
+
+#include "devinfo.h"
+
+extern DevinfoDevHandler devinfo_computer_handler;
+extern DevinfoDevHandler devinfo_keyboard_handler;
+extern DevinfoDevHandler devinfo_default_handler;
+
+#endif /* DEVINFO_MISC_H */
diff --git a/hal/files/hald-netbsd/devinfo_optical.c b/hal/files/hald-netbsd/devinfo_optical.c
new file mode 100644
index 0000000000..e435f32231
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_optical.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright (c) 2008 Reinoud Zandijk
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/scsiio.h>
+#include <sys/disklabel.h>
+#include <dev/scsipi/scsi_spc.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsipi_cd.h>
+#include <string.h>
+#include <machine/disklabel.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <fcntl.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "devinfo_optical.h"
+
+#include "devinfo.h"
+
+
+#define	DEVINFO_PROBE_STORAGE_TIMEOUT   60000
+static HalDevice *devinfo_optical_add(HalDevice *, const char *, char *,char *);
+static HalDevice *devinfo_optical_volume_add(HalDevice *, const char *, char *, char *);
+
+
+static const gchar *
+devinfo_storage_get_prober (HalDevice *d, int *timeout)
+{
+	        *timeout = DEVINFO_PROBE_STORAGE_TIMEOUT;
+		        return "hald-probe-storage";
+}
+
+#if notyet
+const gchar *
+devinfo_volume_get_prober (HalDevice *d, int *timeout)
+{
+	        *timeout = DEVINFO_PROBE_VOLUME_TIMEOUT;
+		        return "hald-probe-volume";
+}
+#endif
+
+DevinfoDevHandler devinfo_optical_handler = {
+        devinfo_optical_add,
+	NULL,	/* remove */
+	NULL,	/* hotplug_begin_add */
+	NULL,	/* hotplug_begin_remove */
+	NULL,	/* probing_done */
+        NULL /* devinfo_storage_get_prober */	/* get_prober */
+};
+
+
+DevinfoDevHandler devinfo_optical_volume_handler = {
+        devinfo_optical_volume_add,
+	NULL,	/* remove */
+	NULL,	/* hotplug_begin_add */
+	NULL,	/* hotplug_begin_remove */
+	NULL,	/* probing_done */
+        NULL /* devinfo_storage_get_prober */	/* get_prober */
+};
+
+
+/* XXX i dont know how to link cdutils here XXX ! */
+bool
+scsi_command (int fd, void *cmd, size_t cmdlen, void *data, size_t datalen,
+    int timeout, int flags)
+{
+	scsireq_t req;
+
+	memset(&req, 0, sizeof(req));
+	memcpy(req.cmd, cmd, cmdlen);
+	req.cmdlen = cmdlen;
+	req.databuf = data;
+	req.datalen = datalen;
+	req.timeout = timeout;
+	req.flags = flags;
+	req.senselen = SENSEBUFLEN;
+
+	if (ioctl(fd, SCIOCCOMMAND, &req) == -1)
+		return false;
+	if (req.retsts == SCCMD_OK)
+		return true;
+	return false;
+}
+
+
+static void
+optical_get_str(char *str, unsigned char *buf, int len)
+{
+	char *pos;
+	int i;
+
+	pos = str;
+	for (i = 0; i < len; i++) {
+		if (isprint(buf[i]))
+			*pos++ = buf[i];
+	}
+	*pos = (char) 0;
+	pos--;
+	while (*pos == ' ')
+		*pos-- = (char) 0;
+}
+
+
+static void
+devinfo_optical_identify_drive(HalDevice *d, char *devstr)
+{
+	uint8_t cmd[12], buf[100];
+	char str[100];
+	int fd, ok;
+
+	fd = open(devstr, O_RDONLY, 0);
+	if(!fd)
+		return;
+
+	HAL_INFO(("devinfo_optical_identify_drive: SCSI call"));
+	cmd[0] = 0x12;	/* INQUIRY */
+	cmd[1] = 0;	/* basic inquiry */
+	cmd[2] = 0;	/* no page or operation code */
+	cmd[3] = 0;	/* reserved/MSB result */
+	cmd[4] = 96;	/* all but vendor specific */
+	cmd[5] = 0;	/* control */
+	ok = scsi_command(fd, cmd, 6, buf, 96, 30000, SCCMD_READ);
+	close(fd);
+
+	if (!ok)
+		return;
+
+	optical_get_str(str, buf+8, 8);
+	hal_device_property_set_string (d, "storage.vendor", str);
+	optical_get_str(str, buf+16, 16);
+	hal_device_property_set_string (d, "storage.model", str);
+	optical_get_str(str, buf+32, 4);
+	hal_device_property_set_string (d, "storage.firmware_version", str);
+}
+
+
+static char const *
+get_profile_name(HalDevice *d, int profile)
+{
+	switch (profile) {
+	case 0x00 : return NULL;	// "Unknown[0] profile";
+	case 0x01 : return NULL;	// "Non removeable disc";
+	case 0x02 : return NULL;	// "Removable disc";
+	case 0x03 : return "mo";	// Magneto Optical with sector erase";
+	case 0x04 : return "mo";	// "Magneto Optical write once";
+	case 0x05 : return "mo";	// "Advance Storage Magneto Optical";
+	case 0x08 : return "cd";	// "CD-ROM"; no writing
+	case 0x09 : return "cdr";	// "CD-R recordable";
+	case 0x0a : return "cdrw";	// "CD-RW rewritable";
+	case 0x10 : return "dvd";	// "DVD-ROM"; no writing
+	case 0x11 : return "dvdr";	// "DVD-R sequential";
+	case 0x12 : return "dvdram";	// "DVD-RAM rewritable";
+	case 0x13 : return "dvdrw";	// "DVD-RW restricted overwrite";
+	case 0x14 : return "dvdrw";	// "DVD-RW sequential";
+	case 0x15 : return "dvdr";	// "DVD-R dual layer sequential";
+	case 0x16 : return "dvdr";	// "DVD-R dual layer jump";
+	case 0x17 : return "dvdrw";	// "DVD-RW dual layer";
+	case 0x18 : return NULL;	// "DVD-Download disc"; UNKNOWN
+	case 0x1a : return "dvdplusrw";	// "DVD+RW rewritable";
+	case 0x1b : return "dvdplusr";	// "DVD+R recordable";
+	case 0x20 : return "ddcd";	// "DDCD readonly (retracted)"; no writing
+	case 0x21 : return "ddcdr";	// "DDCD-R recordable (retracted)";	OK?
+	case 0x22 : return "ddcdrw";	// "DDCD-RW rewritable (retracted)"; OK?
+	case 0x2a : return "dvdplusrwdl";//"DVD+RW double layer";
+	case 0x2b : return "dvdplusrdl";// "DVD+R double layer";
+	case 0x40 : return "bd";	// "BD-ROM";
+	case 0x41 : return "bdr";	// "BD-R Sequential Recording (SRM)";
+	case 0x42 : return "bdr";	// "BD-R Random Recording (RRM)";
+	case 0x43 : return "bdre";	// "BD-RE rewritable";
+	case 0x50 : return "hddvd";	// "HD DVD-ROM (retracted)";
+	case 0x51 : return "hddvdr";	// "HD DVD-R (retracted)";
+	case 0x52 : return "hddvdram";	// "HD DVD-RAM (retracted)";
+	case 0x53 : return "hddvdrw";	// "HD DVD-RW (retracted)";
+	case 0x58 : return "hddvdrdl";	// "HD DVD-R dual layer (retracted)";
+	case 0x5a : return "hddvdrwdl"; // "HD DVD-RW dual layer (retracted)";
+	}
+	/* reserved */
+	return NULL;
+}
+
+
+#define feat_tbl_len 300
+#define max_profile 255
+static void
+devinfo_optical_disc_caps(int fd, HalDevice *d)
+{
+	uint8_t cmd[12], buf[feat_tbl_len], *fpos, *pos;
+	char str[100];
+	uint8_t present[max_profile+1];
+	char const *name;
+	int feature, feature_cur, feature_len, req_feature;
+	int cnt, profile;
+	int mrw, mrw_w, ok;
+
+	/* set defaults */
+	for (profile = 0; profile <= max_profile; profile++) {
+		present[profile] = FALSE;
+	}
+
+	HAL_INFO(("devinfo_optical_disc_caps: get feature 0 SCSI call"));
+	req_feature = 0;
+	cmd[0] = 0x46;			/* Get configuration */
+	cmd[1] = 0;			/* RT=0 -> all independent of current setting */
+	cmd[2] = (req_feature) >> 8;	/* MSB feature number */
+	cmd[3] = (req_feature) & 0xff;	/* LSB feature number */
+	cmd[7] = (feat_tbl_len) >> 8;	/* MSB buffersize */
+	cmd[8] = (feat_tbl_len) & 0xff;	/* LSB buffersize */
+	cmd[9] = 0;			/* control */
+	ok = scsi_command(fd, cmd, 10, buf, feat_tbl_len, 30000, SCCMD_READ);
+
+	if (!ok)
+		return;
+
+	HAL_INFO(("devinfo_optical_disc_caps: processing profiles\n"));
+	fpos = buf + 8;
+
+	feature     =  fpos[1] | (fpos[0] << 8);
+	feature_cur = (fpos[2] & 1);
+	feature_len =  fpos[3];
+	if (feature != 0) {
+		HAL_INFO(("cdrom drive on crack, its not returning feature 0\n"));
+		return;
+	}
+
+	if ((feature_len & 3) != 0)
+		HAL_INFO(("*** drive returned bad feature length ***"));
+
+	/* process feature */
+	pos = &fpos[4];
+	for (cnt=0; cnt < feature_len; cnt += 4) {
+		profile = pos[1] | (pos[0] << 8);
+		if (profile <= max_profile) {
+			present[profile] = TRUE;
+		} else {
+			if (profile != 0xffff)
+				HAL_INFO(("devinfo_optical_disc_caps: bump max_profile!, "
+					  "found profile %d", profile));
+		}
+		pos += 4;
+	}
+
+	/* set hal properties */
+	for (profile = 0; profile <= max_profile; profile++) {
+		/* process profile */
+		name = get_profile_name(d, profile);
+		if (name) {
+			strcpy(str, "storage.cdrom.");
+			strcat(str, name);
+			HAL_INFO(("Profile %d : %s : %s", profile, str,
+				present[profile] ? "true":"false"));
+			hal_device_property_set_bool(d, str, present[profile]);
+		}
+	}
+
+	/* set MRW support; feature 0x28, version 0/1 */
+	HAL_INFO(("devinfo_optical_disc_caps: get feature 0x28 SCSI call"));
+	req_feature = 0x28;
+	cmd[0] = 0x46;			/* Get configuration */
+	cmd[1] = 0;			/* RT=0 -> all independent of current setting */
+	cmd[2] = (req_feature) >> 8;	/* MSB feature number */
+	cmd[3] = (req_feature) & 0xff;	/* LSB feature number */
+	cmd[7] = (feat_tbl_len) >> 8;	/* MSB buffersize */
+	cmd[8] = (feat_tbl_len) & 0xff;	/* LSB buffersize */
+	cmd[9] = 0;			/* control */
+	ok = scsi_command(fd, cmd, 10, buf, feat_tbl_len, 30000, SCCMD_READ);
+
+	if (!ok)
+		return;
+
+	feature     =  fpos[1] | (fpos[0] << 8);
+	feature_cur = (fpos[2] & 1);
+	feature_len =  fpos[3];
+
+	if ((feature_len & 3) != 0)
+		HAL_INFO(("*** drive returned bad feature length ***"));
+
+	HAL_INFO(("devinfo_optical_disc_caps: processing MRW\n"));
+	/* process feature */
+	pos = &fpos[4];
+	mrw   = FALSE;
+	mrw_w = FALSE;
+	if (feature == 0x28) {
+		mrw = TRUE;
+		if (pos[0] & 1)
+			mrw_w = TRUE;
+	}
+	hal_device_property_set_bool(d, "storage.cdrom.mrw", mrw);
+	hal_device_property_set_bool(d, "storage.cdrom.mrw_w", mrw_w);
+
+	/*
+	 * XXX very rare to now have multi-session support; could be detected
+	 * in the change bits of page 5, but set to true for now
+	 */
+	hal_device_property_set_bool(d, "storage.cdrom.support_multisession", TRUE);
+
+	/* XXX realy? */
+	hal_device_property_set_bool(d, "storage.cdrom.support_media_changed", TRUE);
+
+	/* media dependent; addon-storage will handle these */
+	//hal_device_property_set_int(d,"storage.cdrom.read_speed", 0);
+	//hal_device_property_set_int(d,"storage.cdrom.write_speed", 0);
+	//hal_device_property_set_string(d, "storage.cdrom.write_speeds", FALSE);
+	
+}
+#undef max_profile
+#undef feat_tbl_len
+
+
+static HalDevice *
+devinfo_optical_volume_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
+{
+	HalDevice *d;
+	struct stat devstat;
+	char *devstr;
+	int error;
+
+	HAL_INFO (("devinfo_optical_volume_add: parent=%p devnode=%s devfs_path=%s device_type=%s",
+	    parent, devnode, devfs_path, device_type));
+
+	d = hal_device_new ();
+
+	devstr = malloc(strlen(devnode) + 10);
+
+	/* info */
+	devinfo_set_default_properties (d, parent, devnode, devnode);
+	hal_device_add_capability (d, "block");
+	hal_device_add_capability (d, "volume");
+	hal_device_add_capability (d, "volume.disc");
+	hal_device_property_set_string (d, "info.category", "volume");
+
+	/* block */
+	sprintf(devstr, "/dev/%s", devnode);
+        hal_device_property_set_string (d, "block.device", devstr);
+	error = stat(devstr, &devstat);
+	if (!error) {
+	        hal_device_property_set_int (d, "block.major", major(devstat.st_rdev));
+	        hal_device_property_set_int (d, "block.minor", minor(devstat.st_rdev));
+	}
+	sprintf(devstr, "/dev/r%s", devnode);
+        hal_device_property_set_string (d, "block.netbsd.raw_device", devstr);
+
+        hal_device_property_set_bool (d, "block.is_volume", TRUE);
+        hal_device_property_set_bool (d, "block.no_partitions", TRUE);
+        hal_device_property_set_bool (d, "block.have_scanned", TRUE);
+        hal_device_property_set_string (d, "block.storage_device",
+            hal_device_property_get_string (parent, "info.udi"));
+
+	/* volume */
+	hal_device_property_set_bool  (d, "volume.ignore", FALSE);
+	hal_device_property_set_string(d, "volume.fsusage", "filesytem");
+	hal_device_property_set_string(d, "volume.fstype",  "");
+	hal_device_property_set_string(d, "volume.label",   "");
+	hal_device_property_set_bool  (d, "volume.is_disc", TRUE);
+	hal_device_property_set_bool  (d, "volume.is_partition", FALSE);
+	/* rest by addon */
+
+	/* volume.disc */
+	/* by addon */
+
+	devinfo_add_enqueue (d, devnode, &devinfo_optical_volume_handler);
+
+	return d;
+}
+
+
+static HalDevice *
+devinfo_optical_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
+{
+	HalDevice *d;
+	struct stat devstat;
+	char *devstr;
+	char *parent_devnode;
+	int fd, error;
+
+	if (strncmp(devnode, "cd", 2) != 0) {
+		return (NULL);
+	}
+
+	HAL_INFO (("devinfo_optical_add: parent=%p devnode=%s devfs_path=%s device_type=%s",
+	    parent, devnode, devfs_path, device_type));
+
+	d = hal_device_new ();
+
+	devstr = malloc(strlen(devnode) + 10);
+
+	/* info */
+	devinfo_set_default_properties (d, parent, devnode, devnode);
+//	hal_device_property_set_string (d, "netbsd.device", devfs_path);
+
+        hal_device_property_set_string (d, "info.subsystem", "block");
+	hal_device_add_capability (d, "block");
+	hal_device_add_capability (d, "storage");
+	hal_device_add_capability (d, "storage.cdrom");
+
+	/* block */
+	sprintf(devstr, "/dev/%s%c", devnode, 'a' + RAW_PART);
+        hal_device_property_set_string (d, "block.device", devstr);
+	error = stat(devstr, &devstat);
+	if (!error) {
+	        hal_device_property_set_int (d, "block.major", major(devstat.st_rdev));
+	        hal_device_property_set_int (d, "block.minor", minor(devstat.st_rdev));
+	}
+	sprintf(devstr, "/dev/r%s%c", devnode, 'a' + RAW_PART);
+        hal_device_property_set_string (d, "block.netbsd.raw_device", devstr);
+
+        hal_device_property_set_bool (d, "block.is_volume", FALSE);
+        hal_device_property_set_bool (d, "block.no_partitions", TRUE);
+        hal_device_property_set_bool (d, "block.have_scanned", TRUE);
+
+	/* storage */
+	parent_devnode = hal_device_property_get_string (parent, "netbsd.device");
+	if (strstr (parent_devnode, "umass") == parent_devnode)
+		hal_device_property_set_string (d, "storage.bus", "usb");
+	else if (strstr (parent_devnode, "atapi") == parent_devnode)
+		hal_device_property_set_string (d, "storage.bus", "ide");
+	else
+		hal_device_property_set_string (d, "storage.bus", "scsi");
+
+	hal_device_property_set_string (d, "storage.drive_type", "cdrom");
+	hal_device_property_set_bool (d, "storage.removable", TRUE);
+	/* "storage.removable.media_available" set by addon-storage */
+	/* "storage.removable.media_size" set by addon-storage */
+	hal_device_property_set_bool (d, "storage.removable.support_async_notification", FALSE);
+	hal_device_property_set_bool (d, "storage.requires_eject", TRUE);
+	hal_device_property_set_bool (d, "storage.hotpluggable", TRUE);
+	hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);	   /* XXX */
+	hal_device_property_set_bool (d, "storage.automount_enabled_hint", FALSE); /* multiple choice */
+	hal_device_property_set_bool (d, "storage.no_partitions_hint", TRUE);
+	hal_device_property_set_string (d, "storage.originating_device", "");      /* XXX */
+
+	fd = open(devstr, O_RDONLY, 0);
+	if (fd) {
+		/* get drive's vendor and model name */
+		devinfo_optical_identify_drive(d, devstr);
+
+		/* get CD specific `storage.cdrom' values */
+		devinfo_optical_disc_caps(fd, d);
+
+	}
+	devinfo_add_enqueue (d, devnode, &devinfo_optical_handler);
+	if (fd) {
+		/* create CD volume node */
+		sprintf(devstr, "%s%c", devnode, 'a' + RAW_PART);
+		devinfo_optical_volume_add(d, devstr, devfs_path, "volume");
+	}
+	close(fd);
+
+	return (d);
+}
+
diff --git a/hal/files/hald-netbsd/devinfo_optical.h b/hal/files/hald-netbsd/devinfo_optical.h
new file mode 100644
index 0000000000..2dc7775a7a
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_optical.h
@@ -0,0 +1,20 @@
+/***************************************************************************
+ *
+ * devinfo_optical.h : definition for optical (MMC compliant) media
+ *
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef DEVINFO_OPTICAL_H
+#define DEVINFO_OPTICAL_H
+
+#include "devinfo.h"
+
+extern DevinfoDevHandler devinfo_optical_handler;
+
+#endif /* DEVINFO_OPTICAL_H */
+
diff --git a/hal/files/hald-netbsd/devinfo_pci.c b/hal/files/hald-netbsd/devinfo_pci.c
new file mode 100644
index 0000000000..415d2f6dc9
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_pci.c
@@ -0,0 +1,122 @@
+/***************************************************************************
+ *
+ * devinfo_pci.c : PCI devices
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#pragma ident	"@(#)devinfo_pci.c	1.2	06/10/13 SMI"
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <libdevinfo.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "../ids.h"
+#include "devinfo_pci.h"
+
+HalDevice *devinfo_pci_add (HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
+
+DevinfoDevHandler devinfo_pci_handler = {
+        devinfo_pci_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+        NULL
+};
+
+HalDevice *devinfo_pci_add (HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
+{
+	HalDevice *d;
+	char	*s;
+	int	*i;
+	int	vid, pid, svid, spid;
+
+	if ((device_type == NULL) ||
+	    ((strcmp (device_type, "pci") != 0) &&
+	    (strcmp (device_type, "pci-ide") != 0))) {
+		if (parent == NULL) {
+			return (NULL);
+		} else {
+			s = (char *)hal_device_property_get_string (parent, "info.subsystem");
+			if ((s == NULL) || (strcmp (s, "pci") != 0)) {
+				return (NULL);
+			}
+		}
+	}
+
+	d = hal_device_new ();
+	devinfo_set_default_properties (d, parent, node, devfs_path);
+
+	hal_device_property_set_string (d, "info.subsystem", "pci");
+
+	vid = pid = svid = spid = 0;
+        if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "vendor-id", &i) > 0) {
+		vid = i[0];
+	}
+        if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "device-id", &i) > 0) {
+		pid = i[0];
+	}
+        if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "subsystem-vendor-id", &i) > 0) {
+		svid = i[0];
+	}
+        if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, "subsystem-id", &i) > 0) {
+		spid = i[0];
+	}
+	hal_device_property_set_int (d, "pci.vendor_id", vid);
+	hal_device_property_set_int (d, "pci.product_id", pid);
+	hal_device_property_set_int (d, "pci.subsys_vendor_id", svid);
+	hal_device_property_set_int (d, "pci.subsys_product_id", spid);
+
+        {
+                char *vendor_name;
+                char *product_name;
+                char *subsys_vendor_name;
+                char *subsys_product_name;
+
+                ids_find_pci (hal_device_property_get_int (d, "pci.vendor_id"),
+                              hal_device_property_get_int (d, "pci.product_id"),
+                              hal_device_property_get_int (d, "pci.subsys_vendor_id"),
+                              hal_device_property_get_int (d, "pci.subsys_product_id"),
+                              &vendor_name, &product_name, &subsys_vendor_name,
+&subsys_product_name);
+
+                if (vendor_name != NULL) {
+                        hal_device_property_set_string (d, "pci.vendor", vendor_name);
+                        hal_device_property_set_string (d, "info.vendor", vendor_name);
+                }
+
+                if (product_name != NULL) {
+                        hal_device_property_set_string (d, "pci.product", product_name);
+                        hal_device_property_set_string (d, "info.product", product_name);
+                }
+
+                if (subsys_vendor_name != NULL) {
+                        hal_device_property_set_string (d, "pci.subsys_vendor",
+subsys_vendor_name);
+                }
+
+                if (subsys_product_name != NULL) {
+                        hal_device_property_set_string (d, "pci.subsys_product", subsys_product_name);
+                }
+        }
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_pci_handler);
+
+	return (d);
+}
+
diff --git a/hal/files/hald-netbsd/devinfo_pci.h b/hal/files/hald-netbsd/devinfo_pci.h
new file mode 100644
index 0000000000..dbeb4f6e47
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_pci.h
@@ -0,0 +1,21 @@
+/***************************************************************************
+ *
+ * devinfo_pci.h : definitions for PCI devices
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#ifndef DEVINFO_PCI_H
+#define DEVINFO_PCI_H
+
+#include "devinfo.h"
+
+extern DevinfoDevHandler devinfo_pci_handler;
+
+#endif /* DEVINFO_PCI_H */
diff --git a/hal/files/hald-netbsd/devinfo_storage.c b/hal/files/hald-netbsd/devinfo_storage.c
new file mode 100644
index 0000000000..ca711bb9db
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_storage.c
@@ -0,0 +1,1671 @@
+/***************************************************************************
+ *
+ * devinfo_storage.c : storage devices
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#pragma ident	"@(#)devinfo_storage.c	1.2	06/10/13 SMI"
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <libdevinfo.h>
+#include <sys/types.h>
+#include <sys/mkdev.h>
+#include <sys/stat.h>
+#include <sys/mntent.h>
+#include <sys/mnttab.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "../hald_runner.h"
+#include "hotplug.h"
+#include "devinfo.h"
+#include "devinfo_misc.h"
+#include "devinfo_storage.h"
+#include "osspec_netbsd.h"
+
+#ifdef sparc
+#define	WHOLE_DISK	"s2"
+#else
+#define	WHOLE_DISK	"p0"
+#endif
+
+/* some devices,especially CDROMs, may take a while to be probed (values in ms) */
+#define	DEVINFO_PROBE_STORAGE_TIMEOUT	60000
+#define	DEVINFO_PROBE_VOLUME_TIMEOUT	60000
+
+typedef struct devinfo_storage_minor {
+	char	*devpath;
+	char	*devlink;
+	char	*slice;
+	dev_t	dev;
+	int	dosnum;	/* dos disk number or -1 */
+} devinfo_storage_minor_t;
+
+HalDevice *devinfo_ide_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
+static HalDevice *devinfo_ide_host_add(HalDevice *parent, di_node_t node, char *devfs_path);
+static HalDevice *devinfo_ide_device_add(HalDevice *parent, di_node_t node, char *devfs_path);
+static HalDevice *devinfo_ide_storage_add(HalDevice *grampa, HalDevice *parent, di_node_t node, char *devfs_path);
+HalDevice *devinfo_scsi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
+static HalDevice *devinfo_scsi_storage_add(HalDevice *grampa, HalDevice *parent, di_node_t node, char *devfs_path);
+HalDevice *devinfo_floppy_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
+static void devinfo_floppy_add_volume(HalDevice *parent, di_node_t node);
+static HalDevice *devinfo_lofi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
+static void devinfo_lofi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, char *devlink, dev_t dev);
+static int walk_devlinks(di_devlink_t devlink, void *arg);
+static char *get_devlink(di_devlink_handle_t devlink_hdl, char *path);
+static void devinfo_storage_minors(HalDevice *parent, di_node_t node, gchar *devfs_path, gboolean);
+static struct devinfo_storage_minor *devinfo_storage_new_minor(char *maindev_path, char *slice,
+    char *devlink, dev_t dev, int dosnum);
+static void devinfo_storage_free_minor(struct devinfo_storage_minor *m);
+HalDevice *devinfo_volume_add(HalDevice *parent, di_node_t node, devinfo_storage_minor_t *m);
+static void devinfo_volume_preprobing_done(HalDevice *d, gpointer userdata1, gpointer userdata2);
+static void devinfo_volume_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
+static void devinfo_storage_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
+static void devinfo_storage_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2);
+const gchar *devinfo_volume_get_prober (HalDevice *d, int *timeout);
+const gchar *devinfo_storage_get_prober (HalDevice *d, int *timeout);
+
+static char *devinfo_scsi_dtype2str(int dtype);
+static char *devinfo_volume_get_slice_name (char *devlink);
+static gboolean dos_to_dev(char *path, char **devpath, int *partnum);
+static gboolean is_dos_path(char *path, int *partnum);
+
+static void devinfo_storage_set_nicknames (HalDevice *d);
+
+DevinfoDevHandler devinfo_ide_handler = {
+        devinfo_ide_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+        NULL
+};
+DevinfoDevHandler devinfo_scsi_handler = {
+        devinfo_scsi_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+        NULL
+};
+DevinfoDevHandler devinfo_floppy_handler = {
+        devinfo_floppy_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+        NULL
+};
+DevinfoDevHandler devinfo_lofi_handler = {
+        devinfo_lofi_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+        NULL
+};
+DevinfoDevHandler devinfo_storage_handler = {
+	NULL,
+	NULL,
+	devinfo_storage_hotplug_begin_add,
+	NULL,
+	devinfo_storage_probing_done,
+	devinfo_storage_get_prober
+};
+DevinfoDevHandler devinfo_volume_handler = {
+	NULL,
+	NULL,
+	devinfo_volume_hotplug_begin_add,
+	NULL,
+	NULL,
+	devinfo_volume_get_prober
+};
+
+/* IDE */
+
+HalDevice *
+devinfo_ide_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
+{
+	char	*s;
+
+	if ((device_type != NULL) && (strcmp(device_type, "ide") == 0)) {
+		return (devinfo_ide_host_add(parent, node, devfs_path));
+	}
+
+        if ((di_prop_lookup_strings (DDI_DEV_T_ANY, node, "class", &s) > 0) &&
+	    (strcmp (s, "dada") == 0)) {
+		return (devinfo_ide_device_add(parent, node, devfs_path));
+	}
+
+	return (NULL);
+}
+
+static HalDevice *
+devinfo_ide_host_add(HalDevice *parent, di_node_t node, char *devfs_path)
+{
+	HalDevice *d;
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, node, devfs_path);
+	hal_device_property_set_string (d, "info.product", "IDE host controller");
+	hal_device_property_set_string (d, "info.subsystem", "ide_host");
+	hal_device_property_set_int (d, "ide_host.number", 0); /* XXX */
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_ide_handler);
+
+	return (d);
+}
+
+static HalDevice *
+devinfo_ide_device_add(HalDevice *parent, di_node_t node, char *devfs_path)
+{
+	HalDevice *d;
+
+	d = hal_device_new();
+
+	devinfo_set_default_properties (d, parent, node, devfs_path);
+        hal_device_property_set_string (parent, "info.product", "IDE device");
+	hal_device_property_set_string (parent, "info.subsystem", "ide");
+	hal_device_property_set_int (parent, "ide.host", 0); /* XXX */
+	hal_device_property_set_int (parent, "ide.channel", 0);
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_ide_handler);
+
+	return (devinfo_ide_storage_add (parent, d, node, devfs_path));
+}
+
+static HalDevice *
+devinfo_ide_storage_add(HalDevice *grampa, HalDevice *parent, di_node_t node, char *devfs_path)
+{
+	HalDevice *d;
+	char	*s;
+	int	*i;
+	char	*driver_name;
+	char	udi[HAL_PATH_MAX];
+
+	if ((driver_name = di_driver_name (node)) == NULL) {
+		return (NULL);
+	}
+
+        d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, node, devfs_path);
+        hal_device_property_set_string (d, "info.category", "storage");
+
+	hald_compute_udi (udi, sizeof (udi),
+			  "%s/%s%d", hal_device_get_udi (parent),
+			  driver_name, di_instance (node));
+        hal_device_set_udi (d, udi);
+	PROP_STR(d, node, s, "devid", "info.product");
+
+        hal_device_add_capability (d, "storage");
+        hal_device_property_set_string (d, "storage.bus", "ide");
+        hal_device_property_set_int (d, "storage.lun", 0);
+	hal_device_property_set_string (d, "storage.drive_type", "disk");
+
+	PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
+	PROP_BOOL(d, node, i, "removable-media", "storage.removable");
+
+        hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
+
+	/* XXX */
+        hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
+
+	hal_device_add_capability (d, "block");
+
+	devinfo_storage_minors (d, node, (char *)devfs_path, FALSE);
+
+	return (d);
+}
+
+/* SCSI */
+
+HalDevice *
+devinfo_scsi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
+{
+	int	*i;
+	char	*driver_name;
+	HalDevice *d;
+	char	udi[HAL_PATH_MAX];
+
+	driver_name = di_driver_name (node);
+	if ((driver_name == NULL) || (strcmp (driver_name, "sd") != 0)) {
+		return (NULL);
+	}
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, node, devfs_path);
+	hal_device_property_set_string (d, "info.subsystem", "scsi");
+
+	hald_compute_udi (udi, sizeof (udi),
+			  "%s/%s%d", hal_device_get_udi (parent),
+			  di_node_name(node), di_instance (node));
+	hal_device_set_udi (d, udi);
+
+	hal_device_property_set_int (d, "scsi.host", 
+		hal_device_property_get_int (parent, "scsi_host.host"));
+	hal_device_property_set_int (d, "scsi.bus", 0);
+	PROP_INT(d, node, i, "target", "scsi.target");
+	PROP_INT(d, node, i, "lun", "scsi.lun");
+        hal_device_property_set_string (d, "info.product", "SCSI Device");
+
+        devinfo_add_enqueue (d, devfs_path, &devinfo_scsi_handler);
+
+        return (devinfo_scsi_storage_add (parent, d, node, devfs_path));
+}
+
+static HalDevice *
+devinfo_scsi_storage_add(HalDevice *grampa, HalDevice *parent, di_node_t node, char *devfs_path)
+{
+	HalDevice *d;
+	int	*i;
+	char	*s;
+	char	udi[HAL_PATH_MAX];
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, node, devfs_path);
+        hal_device_property_set_string (d, "info.category", "storage");
+
+	hald_compute_udi (udi, sizeof (udi),
+			  "%s/sd%d", hal_device_get_udi (parent),
+			  di_instance (node));
+	hal_device_set_udi (d, udi);
+	PROP_STR(d, node, s, "inquiry-product-id", "info.product");
+
+        hal_device_add_capability (d, "storage");
+
+        hal_device_property_set_int (d, "storage.lun",
+		hal_device_property_get_int (parent, "scsi.lun"));
+	PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
+	PROP_BOOL(d, node, i, "removable-media", "storage.removable");
+        hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
+
+	/*
+	 * We have to enable polling not only for drives with removable media,
+	 * but also for hotpluggable devices, because when a disk is
+	 * unplugged while busy/mounted, there is not sysevent generated.
+	 * Instead, the HBA driver (scsa2usb, scsa1394) will notify sd driver
+	 * and the latter will report DKIO_DEV_GONE via DKIOCSTATE ioctl.
+	 * So we have to enable media check so that hald-addon-storage notices
+	 * the "device gone" condition and unmounts all associated volumes.
+	 */
+	hal_device_property_set_bool (d, "storage.media_check_enabled",
+	    ((di_prop_lookup_ints(DDI_DEV_T_ANY, node, "removable-media", &i) >= 0) ||
+	    (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "hotpluggable", &i) >= 0)));
+
+        if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "inquiry-device-type",
+	    &i) > 0) {
+		s = devinfo_scsi_dtype2str (*i);
+        	hal_device_property_set_string (d, "storage.drive_type", s);
+
+		if (strcmp (s, "cdrom") == 0) {
+			hal_device_add_capability (d, "storage.cdrom");
+			hal_device_property_set_bool (d, "storage.no_partitions_hint", TRUE);
+        		hal_device_property_set_bool (d, "storage.requires_eject", TRUE);
+		}
+	}
+
+        hal_device_add_capability (d, "block");
+
+	devinfo_storage_minors (d, node, devfs_path, FALSE);
+
+	return (d);
+}
+
+static char *devinfo_scsi_dtype2str(int dtype)
+{
+        char *dtype2str[] = {
+                "disk"	,         /* DTYPE_DIRECT         0x00 */
+                "tape"	,         /* DTYPE_SEQUENTIAL     0x01 */
+                "printer",         /* DTYPE_PRINTER        0x02 */
+                "processor",         /* DTYPE_PROCESSOR      0x03 */
+                "worm"	,         /* DTYPE_WORM           0x04 */
+                "cdrom"	,         /* DTYPE_RODIRECT       0x05 */
+                "scanner",         /* DTYPE_SCANNER        0x06 */
+                "cdrom"	,         /* DTYPE_OPTICAL        0x07 */
+                "changer",         /* DTYPE_CHANGER        0x08 */
+                "comm"	,         /* DTYPE_COMM           0x09 */
+                "scsi"	,         /* DTYPE_???            0x0A */
+                "scsi"	,         /* DTYPE_???            0x0B */
+                "array_ctrl",         /* DTYPE_ARRAY_CTRL     0x0C */
+                "esi"	,         /* DTYPE_ESI            0x0D */
+                "disk"	          /* DTYPE_RBC            0x0E */
+        };
+
+        if (dtype < NELEM(dtype2str)) {
+                return (dtype2str[dtype]);
+        } else {
+		return ("scsi");
+        }
+
+}
+
+/* floppy */
+
+HalDevice *
+devinfo_floppy_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
+{
+	char	*driver_name;
+	char	*raw;
+	char	udi[HAL_PATH_MAX];
+	di_devlink_handle_t devlink_hdl;
+        int     major;
+        di_minor_t minor;
+        dev_t   dev;
+	HalDevice *d = NULL;
+        char    *minor_path = NULL;
+	char	*devlink = NULL;
+
+	driver_name = di_driver_name (node);
+	if ((driver_name == NULL) || (strcmp (driver_name, "fd") != 0)) {
+		return (NULL);
+	}
+
+	/*
+	 * The only minor node we're interested in is /dev/diskette*
+	 */
+	major = di_driver_major(node);
+	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
+		return (NULL);
+	}
+	minor = DI_MINOR_NIL;
+	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
+		dev = di_minor_devt(minor);
+		if ((major != major(dev)) ||
+		    (di_minor_type(minor) != DDM_MINOR) ||
+		    (di_minor_spectype(minor) != S_IFBLK) ||
+		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
+			continue;
+		}
+		if (((devlink = get_devlink(devlink_hdl, minor_path)) != NULL) &&
+		    (strncmp (devlink, "/dev/diskette", sizeof ("/dev/diskette") - 1) == 0)) {
+			break;
+		}
+		di_devfs_path_free (minor_path);
+		minor_path = NULL;
+		free(devlink);
+		devlink = NULL;
+	}
+	di_devlink_fini (&devlink_hdl);
+
+	if ((devlink == NULL) || (minor_path == NULL)) {
+		HAL_INFO (("floppy devlink not found %s", devfs_path));
+		goto out;
+	}
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, node, devfs_path);
+        hal_device_property_set_string (d, "info.category", "storage");
+        hal_device_add_capability (d, "storage");
+       	hal_device_property_set_string (d, "storage.bus", "platform");
+        hal_device_property_set_bool (d, "storage.hotpluggable", FALSE);
+        hal_device_property_set_bool (d, "storage.removable", TRUE);
+        hal_device_property_set_bool (d, "storage.requires_eject", TRUE);
+        hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
+       	hal_device_property_set_string (d, "storage.drive_type", "floppy");
+
+        hal_device_add_capability (d, "block");
+	hal_device_property_set_bool (d, "block.is_volume", FALSE);
+	hal_device_property_set_int (d, "block.major", major(dev));
+	hal_device_property_set_int (d, "block.minor", minor(dev));
+	hal_device_property_set_string (d, "block.device", devlink);
+	raw = dsk_to_rdsk (devlink);
+	hal_device_property_set_string (d, "block.solaris.raw_device", raw);
+	free (raw);
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_storage_handler);
+
+	/* trigger initial probe-volume */
+	devinfo_floppy_add_volume(d, node);
+
+out:
+	di_devfs_path_free (minor_path);
+	free(devlink);
+
+	return (d);
+}
+
+static void
+devinfo_floppy_add_volume(HalDevice *parent, di_node_t node)
+{
+	char	*devlink;
+	char	*devfs_path;
+	int	minor, major;
+	dev_t	dev;
+	struct devinfo_storage_minor *m;
+
+	devfs_path = (char *)hal_device_property_get_string (parent, "solaris.devfs_path");
+	devlink = (char *)hal_device_property_get_string (parent, "block.device");
+	major = hal_device_property_get_int (parent, "block.major");
+	minor = hal_device_property_get_int (parent, "block.minor");
+	dev = makedev (major, minor);
+
+	m = devinfo_storage_new_minor (devfs_path, WHOLE_DISK, devlink, dev, -1);
+	devinfo_volume_add (parent, node, m);
+	devinfo_storage_free_minor (m);
+}
+
+/*
+ * After reprobing storage, reprobe its volumes.
+ */
+static void
+devinfo_floppy_rescan_probing_done (HalDevice *d, guint32 exit_type, gint return_code,
+    char **error, gpointer userdata1, gpointer userdata2)
+{
+        void *end_token = (void *) userdata1;
+	const char *devfs_path;
+	di_node_t node;
+	HalDevice *v;
+
+	if (!hal_device_property_get_bool (d, "storage.removable.media_available")) {
+		HAL_INFO (("no floppy media", hal_device_get_udi (d)));
+
+		/* remove child (can only be single volume) */
+		if (((v = hal_device_store_match_key_value_string (hald_get_gdl(),
+        	    "info.parent", hal_device_get_udi (d))) != NULL) &&
+		    ((devfs_path = hal_device_property_get_string (v,
+		    "solaris.devfs_path")) != NULL)) {
+			devinfo_remove_enqueue ((char *)devfs_path, NULL);
+		}
+	} else {
+		HAL_INFO (("floppy media found", hal_device_get_udi (d)));
+
+		if ((devfs_path = hal_device_property_get_string(d, "solaris.devfs_path")) == NULL) {
+			HAL_INFO (("no devfs_path", hal_device_get_udi (d)));
+			hotplug_event_process_queue ();
+			return;
+		}
+		if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
+			HAL_INFO (("di_init %s failed %d", devfs_path, errno));
+			hotplug_event_process_queue ();
+			return;
+		}
+
+		devinfo_floppy_add_volume (d, node);
+
+		di_fini (node);
+	}
+
+	hotplug_event_process_queue ();
+}
+	
+/* lofi */
+
+HalDevice *
+devinfo_lofi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
+{
+	return (devinfo_lofi_add_major(parent,node, devfs_path, device_type, FALSE, NULL));
+}
+
+HalDevice *
+devinfo_lofi_add_major(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type,
+    gboolean rescan, HalDevice *lofi_d)
+{
+	char	*driver_name;
+	HalDevice *d = NULL;
+	char	udi[HAL_PATH_MAX];
+	di_devlink_handle_t devlink_hdl;
+        int     major;
+        di_minor_t minor;
+        dev_t   dev;
+        char    *minor_path = NULL;
+        char    *devpath, *devlink;
+
+	driver_name = di_driver_name (node);
+	if ((driver_name == NULL) || (strcmp (driver_name, "lofi") != 0)) {
+		return (NULL);
+	}
+
+	if (!rescan) {
+		d = hal_device_new ();
+
+		devinfo_set_default_properties (d, parent, node, devfs_path);
+		hal_device_property_set_string (d, "info.subsystem", "pseudo");
+
+	hald_compute_udi (udi, sizeof (udi),
+			  "%s/%s%d", hal_device_get_udi (parent),
+			  di_node_name(node), di_instance (node));
+		hal_device_set_udi (d, udi);
+
+		devinfo_add_enqueue (d, devfs_path, &devinfo_lofi_handler);
+	} else {
+		d = lofi_d;
+	}
+
+	/*
+	 * Unlike normal storage, as in devinfo_storage_minors(), where
+	 * sd instance -> HAL storage, sd minor node -> HAL volume,
+	 * lofi always has one instance, lofi minor -> HAL storage.
+	 * lofi storage never has slices, but it can have
+	 * embedded pcfs partitions that fstyp would recognize
+	 */
+	major = di_driver_major(node);
+	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
+		return (d);
+	}
+	minor = DI_MINOR_NIL;
+	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
+		dev = di_minor_devt(minor);
+		if ((major != major(dev)) ||
+		    (di_minor_type(minor) != DDM_MINOR) ||
+		    (di_minor_spectype(minor) != S_IFBLK) ||
+		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
+			continue;
+		}
+		if ((devlink = get_devlink(devlink_hdl, minor_path)) == NULL) {
+			di_devfs_path_free (minor_path);
+        		continue;
+		}
+
+		if (!rescan ||
+		    (hal_device_store_match_key_value_string (hald_get_gdl (),
+		    "solaris.devfs_path", minor_path) == NULL)) {
+			devinfo_lofi_add_minor(d, node, minor_path, devlink, dev);
+		}
+
+		di_devfs_path_free (minor_path);
+		free(devlink);
+	}
+	di_devlink_fini (&devlink_hdl);
+
+	return (d);
+}
+
+static void
+devinfo_lofi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, char *devlink, dev_t dev)
+{
+	HalDevice *d;
+	char	*raw;
+	char	*doslink;
+	char	dospath[64];
+	struct devinfo_storage_minor *m;
+	int	i;
+
+	/* add storage */
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, node, minor_path);
+        hal_device_property_set_string (d, "info.category", "storage");
+        hal_device_add_capability (d, "storage");
+       	hal_device_property_set_string (d, "storage.bus", "lofi");
+        hal_device_property_set_bool (d, "storage.hotpluggable", TRUE);
+        hal_device_property_set_bool (d, "storage.removable", FALSE);
+        hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
+       	hal_device_property_set_string (d, "storage.drive_type", "disk");
+        hal_device_add_capability (d, "block");
+	hal_device_property_set_int (d, "block.major", major(dev));
+	hal_device_property_set_int (d, "block.minor", minor(dev));
+	hal_device_property_set_string (d, "block.device", devlink);
+	raw = dsk_to_rdsk (devlink);
+	hal_device_property_set_string (d, "block.solaris.raw_device", raw);
+	free (raw);
+	hal_device_property_set_bool (d, "block.is_volume", FALSE);
+
+	devinfo_add_enqueue (d, minor_path, &devinfo_storage_handler);
+
+	/* add volumes: one on main device and a few pcfs candidates */
+	m = devinfo_storage_new_minor(minor_path, WHOLE_DISK, devlink, dev, -1);
+	devinfo_volume_add (d, node, m);
+	devinfo_storage_free_minor (m);
+
+	doslink = (char *)calloc (1, strlen (devlink) + sizeof (":NNN") + 1);
+	if (doslink != NULL) {
+		for (i = 1; i < 16; i++) {
+			snprintf(dospath, sizeof (dospath), WHOLE_DISK":%d", i);
+			sprintf(doslink, "%s:%d", devlink, i);
+			m = devinfo_storage_new_minor(minor_path, dospath, doslink, dev, i);
+			devinfo_volume_add (d, node, m);
+			devinfo_storage_free_minor (m);
+		}
+		free (doslink);
+	}
+}
+
+void
+devinfo_lofi_remove_minor(char *parent_devfs_path, char *name)
+{
+	GSList *i;
+	GSList *devices;
+	HalDevice *d = NULL;
+	const char *devfs_path;
+
+	devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
+		"block.solaris.raw_device", name);
+        for (i = devices; i != NULL; i = g_slist_next (i)) {
+		if (hal_device_has_capability (HAL_DEVICE (i->data), "storage")) {
+			d = HAL_DEVICE (i->data);
+			break;
+		}
+	}
+	g_slist_free (devices);
+
+	if (d == NULL) {
+		HAL_INFO (("device not found %s", name));
+		return;
+	}
+
+	if ((devfs_path = hal_device_property_get_string (d,
+	    "solaris.devfs_path")) == NULL) {
+		HAL_INFO (("devfs_path not found %s", hal_device_get_udi (d)));
+		return;
+	}
+
+	if (d != NULL) {
+		devinfo_remove_branch ((char *)devfs_path, d);
+	}
+}
+
+/* common storage */
+
+static int
+walk_devlinks(di_devlink_t devlink, void *arg)
+{
+        char    **path= (char **)arg;
+
+        *path = strdup(di_devlink_path(devlink));
+
+        return (DI_WALK_TERMINATE);
+}
+
+static char *
+get_devlink(di_devlink_handle_t devlink_hdl, char *path)
+{
+        char    *devlink_path = NULL;
+
+        (void) di_devlink_walk(devlink_hdl, NULL, path,
+            DI_PRIMARY_LINK, &devlink_path, walk_devlinks);
+
+        return (devlink_path);
+}
+
+static void
+devinfo_storage_free_minor(struct devinfo_storage_minor *m)
+{
+	if (m != NULL) {
+		free (m->slice);
+		free (m->devlink);
+		free (m->devpath);
+		free (m);
+	}
+}
+
+static struct devinfo_storage_minor *
+devinfo_storage_new_minor(char *maindev_path, char *slice, char *devlink, dev_t dev, int dosnum)
+{
+	struct devinfo_storage_minor *m;
+	int pathlen;
+	char *devpath;
+
+	m = (struct devinfo_storage_minor *)calloc (sizeof (struct devinfo_storage_minor), 1);
+	if (m != NULL) {
+		/*
+		 * For volume's devfs_path we'll use minor_path/slice instead of
+		 * minor_path which we use for parent storage device.
+		 */
+		pathlen = strlen (maindev_path) + strlen (slice) + 2;
+		devpath = (char *)calloc (1, pathlen);
+		snprintf(devpath, pathlen, "%s/%s", maindev_path, slice);
+
+		m->devpath = devpath;
+		m->devlink = strdup (devlink);
+		m->slice = strdup (slice);
+		m->dev = dev;
+		m->dosnum = dosnum;
+		if ((m->devpath == NULL) || (m->devlink == NULL)) {
+			devinfo_storage_free_minor (m);
+			m = NULL;
+		}
+	}
+	return (m);
+}
+
+/*
+ * Storage minor nodes are potential "volume" objects.
+ * This function also completes building the parent object (main storage device).
+ */
+static void
+devinfo_storage_minors(HalDevice *parent, di_node_t node, gchar *devfs_path, gboolean rescan)
+{
+	di_devlink_handle_t devlink_hdl;
+	gboolean is_cdrom;
+	const char *whole_disk;
+	int     major;
+	di_minor_t minor;
+	dev_t   dev;
+	char    *minor_path = NULL;
+	char    *maindev_path = NULL;
+	char    *devpath, *devlink;
+	int	doslink_len;
+	char	*doslink;
+	char	dospath[64];
+	char    *slice;
+	int	pathlen;
+	int	i;
+	char	*raw;
+	boolean_t maindev_is_d0;
+	GQueue	*mq;
+	HalDevice *volume;
+	struct devinfo_storage_minor *m;
+	struct devinfo_storage_minor *maindev = NULL;
+
+	/* for cdroms whole disk is always s2 */
+	is_cdrom = hal_device_has_capability (parent, "storage.cdrom");
+	whole_disk = is_cdrom ? "s2" : WHOLE_DISK;
+
+	major = di_driver_major(node);
+
+	/* the "whole disk" p0/s2/d0 node must come first in the hotplug queue
+	 * so we put other minor nodes on the local queue and move to the
+	 * hotplug queue up in the end
+	 */
+	if ((mq = g_queue_new()) == NULL) {
+		goto err;
+	}
+	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
+		g_queue_free (mq);
+		goto err;
+	}
+	minor = DI_MINOR_NIL;
+	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
+		dev = di_minor_devt(minor);
+		if ((major != major(dev)) ||
+		    (di_minor_type(minor) != DDM_MINOR) ||
+		    (di_minor_spectype(minor) != S_IFBLK) ||
+		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
+			continue;
+		}
+		if ((devlink = get_devlink(devlink_hdl, minor_path)) == NULL) {
+			di_devfs_path_free (minor_path);
+        		continue;
+		}
+
+		slice = devinfo_volume_get_slice_name (devlink);
+		if (strlen (slice) < 2) {
+			free (devlink);
+			di_devfs_path_free (minor_path);
+			continue;
+		}
+
+		/* ignore p1..N - we'll use p0:N instead */
+		if ((strlen (slice) > 1) && (slice[0] == 'p') && isdigit(slice[1]) &&
+		    ((atol(&slice[1])) > 0)) {
+			free (devlink);
+			di_devfs_path_free (minor_path);
+			continue;
+		}
+
+		m = devinfo_storage_new_minor(minor_path, slice, devlink, dev, -1);
+		if (m == NULL) {
+			free (devlink);
+			di_devfs_path_free (minor_path);
+			continue;
+		}
+
+		/* main device is either s2/p0 or d0, the latter taking precedence */
+		if ((strcmp (slice, "d0") == 0) ||
+		    (((strcmp (slice, whole_disk) == 0) && (maindev == NULL)))) {
+			if (maindev_path != NULL) {
+				di_devfs_path_free (maindev_path);
+			}
+			maindev_path = minor_path;
+			maindev = m;
+			g_queue_push_head (mq, maindev);
+		} else {
+			di_devfs_path_free (minor_path);
+			g_queue_push_tail (mq, m);
+		}
+
+		free (devlink);
+	}
+	di_devlink_fini (&devlink_hdl);
+
+	if (maindev == NULL) {
+		/* shouldn't typically happen */
+		while (!g_queue_is_empty (mq)) {
+			devinfo_storage_free_minor (g_queue_pop_head (mq));
+		}
+		goto err;
+	}
+
+	/* first enqueue main storage device */
+	if (!rescan) {
+		hal_device_property_set_int (parent, "block.major", major);
+		hal_device_property_set_int (parent, "block.minor", minor(maindev->dev));
+		hal_device_property_set_string (parent, "block.device", maindev->devlink);
+		raw = dsk_to_rdsk (maindev->devlink);
+		hal_device_property_set_string (parent, "block.solaris.raw_device", raw);
+		free (raw);
+		hal_device_property_set_bool (parent, "block.is_volume", FALSE);
+		hal_device_property_set_string (parent, "solaris.devfs_path", maindev_path);
+		devinfo_add_enqueue (parent, maindev_path, &devinfo_storage_handler);
+	}
+
+	/* add virtual dos volumes to enable pcfs probing */
+	if (!is_cdrom) {
+		doslink_len = strlen (maindev->devlink) + sizeof (":NNN") + 1;
+		if ((doslink = (char *)calloc (1, doslink_len)) != NULL) {
+			for (i = 1; i < 16; i++) {
+				snprintf(dospath, sizeof (dospath), "%s:%d", maindev->slice, i);
+				snprintf(doslink, doslink_len, "%s:%d", maindev->devlink, i);
+				m = devinfo_storage_new_minor(maindev_path, dospath, doslink, maindev->dev, i);
+				g_queue_push_tail (mq, m);
+			}
+			free (doslink);
+		}
+	}
+
+	maindev_is_d0 = (strcmp (maindev->slice, "d0") == 0);
+
+	/* enqueue all volumes */
+	while (!g_queue_is_empty (mq)) {
+		m = g_queue_pop_head (mq);
+
+		/* if main device is d0, we'll throw away s2/p0 */
+		if (maindev_is_d0 && (strcmp (m->slice, whole_disk) == 0)) {
+			devinfo_storage_free_minor (m);
+			continue;
+		}
+		/* don't do p0 on cdrom */
+		if (is_cdrom && (strcmp (m->slice, "p0") == 0)) {
+			devinfo_storage_free_minor (m);
+			continue;
+		}
+		if (rescan) {
+			/* in rescan mode, don't reprobe existing volumes */
+			/* XXX detect volume removal? */
+			volume = hal_device_store_match_key_value_string (hald_get_gdl (),
+			    "solaris.devfs_path", m->devpath);
+			if ((volume == NULL) || !hal_device_has_capability(volume, "volume")) {
+				devinfo_volume_add (parent, node, m);
+			} else {
+				HAL_INFO(("rescan volume exists %s", m->devpath));
+			}
+		} else {
+			devinfo_volume_add (parent, node, m);
+		}
+		devinfo_storage_free_minor (m);
+	}
+
+	if (maindev_path != NULL) {
+		di_devfs_path_free (maindev_path);
+	}
+
+	return;
+
+err:
+	if (maindev_path != NULL) {
+		di_devfs_path_free (maindev_path);
+	}
+	if (!rescan) {
+		devinfo_add_enqueue (parent, devfs_path, &devinfo_storage_handler);
+	}
+}
+
+HalDevice *
+devinfo_volume_add(HalDevice *parent, di_node_t node, devinfo_storage_minor_t *m)
+{
+	HalDevice *d;
+	char	*raw;
+        char    udi[HAL_PATH_MAX];
+	char	*devfs_path = m->devpath;
+	char	*devlink = m->devlink;
+	dev_t	dev = m->dev;
+	int	dosnum = m->dosnum;
+	char	*slice = m->slice;
+
+	HAL_INFO (("volume_add: devfs_path=%s devlink=%s", devfs_path, devlink));
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, node, devfs_path);
+        hal_device_property_set_string (d, "info.category", "volume");
+
+	hald_compute_udi (udi, sizeof (udi),
+			  "%s/%s", hal_device_get_udi (parent), slice);
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.product", slice);
+
+	hal_device_add_capability (d, "volume");
+	hal_device_add_capability (d, "block");
+	hal_device_property_set_int (d, "block.major", major (dev));
+	hal_device_property_set_int (d, "block.minor", minor (dev));
+	hal_device_property_set_string (d, "block.device", devlink);
+	raw = dsk_to_rdsk (devlink);
+	hal_device_property_set_string (d, "block.solaris.raw_device", raw);
+	free (raw);
+	hal_device_property_set_string (d, "block.solaris.slice", slice);
+	hal_device_property_set_bool (d, "block.is_volume", TRUE); /* XXX */
+
+	hal_device_property_set_string (d, "block.storage_device", hal_device_get_udi (parent));
+
+	/* set volume defaults */
+	hal_device_property_set_string (d, "volume.fstype", "");
+	hal_device_property_set_string (d, "volume.fsusage", "");
+	hal_device_property_set_string (d, "volume.fsversion", "");
+	hal_device_property_set_string (d, "volume.uuid", "");
+	hal_device_property_set_string (d, "volume.label", "");
+	hal_device_property_set_string (d, "volume.mount_point", "");
+	hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
+	if (strcmp (hal_device_property_get_string (parent, "storage.drive_type"), "cdrom") == 0) {
+		hal_device_property_set_bool (d, "volume.is_disc", TRUE);
+		hal_device_add_capability (d, "volume.disc");
+	} else {
+		hal_device_property_set_bool (d, "volume.is_disc", FALSE);
+	}
+
+	if (dosnum > 0) {
+		hal_device_property_set_bool (d, "volume.is_partition", TRUE);
+		hal_device_property_set_int (d, "volume.partition.number", dosnum);
+	} else {
+		hal_device_property_set_bool (d, "volume.is_partition", FALSE);
+	}
+
+	/* prober may override these */
+        hal_device_property_set_int (d, "volume.block_size", 512);
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_volume_handler);
+
+	return (d);
+}
+
+static void
+devinfo_volume_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
+{
+	void *end_token = (void *) userdata1;
+	char *whole_disk;
+	char *block_device;
+	const char *storage_udi;
+	HalDevice *storage_d;
+	const char *slice;
+	int dos_num;
+
+	if (hal_device_property_get_bool (d, "info.ignore")) {
+		HAL_INFO (("Preprobing merged info.ignore==TRUE %s", hal_device_get_udi (d)));
+		goto skip;
+	}
+
+	/*
+	 * Optimizations: only probe if there's a chance to find something
+	 */
+	block_device = (char *)hal_device_property_get_string (d, "block.device");
+	storage_udi = hal_device_property_get_string (d, "block.storage_device");
+	slice = hal_device_property_get_string(d, "block.solaris.slice");
+	if ((block_device == NULL) || (storage_udi == NULL) ||
+	    (slice == NULL) || (strlen (slice) < 2)) {
+		HAL_INFO (("Malformed volume properties %s", hal_device_get_udi (d)));
+		goto skip;
+	}
+	storage_d = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", storage_udi);
+	if (storage_d == NULL) {
+		HAL_INFO (("Storage device not found %s", hal_device_get_udi (d)));
+		goto skip;
+	}
+
+	whole_disk = hal_device_has_capability (storage_d,
+	    "storage.cdrom") ? "s2" : WHOLE_DISK;
+
+	if (is_dos_path(block_device, &dos_num)) {
+		/* don't probe more dos volumes than probe-storage found */
+		if ((hal_device_property_get_bool (storage_d, "storage.no_partitions_hint") ||
+		    (dos_num > hal_device_property_get_int (storage_d, "storage.solaris.num_dos_partitions")))) {
+			    HAL_INFO (("%d > %d %s", dos_num, hal_device_property_get_int (storage_d,
+				"storage.solaris.num_dos_partitions"), hal_device_get_udi (storage_d)));
+			goto skip;
+		}
+	} else {
+		/* if no VTOC slices found, don't probe slices except s2 */
+		if ((slice[0] == 's') && (isdigit(slice[1])) && ((strcmp (slice, whole_disk)) != 0) &&
+		    !hal_device_property_get_bool (storage_d, "storage.solaris.vtoc_slices")) {
+			HAL_INFO (("Not probing slice %s", hal_device_get_udi (d)));
+			goto skip;
+		}
+	}
+
+	HAL_INFO(("Probing udi=%s", hal_device_get_udi (d)));
+	hald_runner_run (d,
+			"hald-probe-volume", NULL,
+			DEVINFO_PROBE_VOLUME_TIMEOUT,
+			devinfo_callouts_probing_done,
+			(gpointer) end_token, userdata2);
+
+	return;
+
+skip:
+	hal_device_store_remove (hald_get_tdl (), d);
+	g_object_unref (d);
+	hotplug_event_end (end_token);
+}
+
+static void
+devinfo_volume_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token)
+{
+	HAL_INFO(("Preprobing volume udi=%s", hal_device_get_udi (d)));
+
+	if (hal_device_property_get_bool (parent, "info.ignore")) {
+		HAL_INFO (("Ignoring volume: parent's info.ignore is TRUE"));
+		goto skip;
+	}
+
+        /* add to TDL so preprobing callouts and prober can access it */
+        hal_device_store_add (hald_get_tdl (), d);
+
+        /* Process preprobe fdi files */
+        di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
+
+        /* Run preprobe callouts */
+        hal_util_callout_device_preprobe (d, devinfo_volume_preprobing_done, end_token, handler);
+
+	return;
+
+skip:
+	g_object_unref (d);
+	hotplug_event_end (end_token);
+}
+
+void
+devinfo_storage_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token)
+{
+	const char *drive_type;
+	const char *p_udi;
+	HalDevice *p_d;
+	HalDevice *phys_d = NULL;
+	const char *phys_bus;
+	const char *bus;
+	static const char *busses[] = { "usb", "ide", "scsi", "pseudo" };
+	int i;
+
+	HAL_INFO (("Preprobing udi=%s", hal_device_get_udi (d)));
+
+	if (parent == NULL) {
+		HAL_INFO (("no parent %s", hal_device_get_udi (d)));
+		goto error;
+	}
+
+	/*
+	 * figure out physical device and bus, except for floppy
+	 */
+	drive_type = hal_device_property_get_string (d, "storage.drive_type");
+	if ((drive_type != NULL) && (strcmp (drive_type, "floppy") == 0)) {
+		goto skip_bus;
+	}
+
+	p_d = parent;
+	for (;;) {
+		bus = hal_device_property_get_string (p_d, "info.subsystem");
+		if (bus != NULL) {
+			for (i = 0; i < NELEM(busses); i++) {
+				if (strcmp(bus, busses[i]) == 0) {
+					phys_d = p_d;
+					phys_bus = busses[i];
+					break;
+				}
+			}
+		}
+		/* up the tree */
+		p_udi = hal_device_property_get_string (p_d, "info.parent");
+		if (p_udi == NULL) {
+			break;
+		}
+		p_d = hal_device_store_find (hald_get_gdl (), p_udi);
+	}
+	if (phys_d == NULL) {
+		HAL_INFO (("no physical device %s", hal_device_get_udi (d)));
+		goto error;
+	}
+	hal_device_property_set_string (d, "storage.originating_device", hal_device_get_udi (phys_d));
+	hal_device_property_set_string (d, "storage.bus", phys_bus);
+
+skip_bus:
+
+	/* add to TDL so preprobing callouts and prober can access it */
+	hal_device_store_add (hald_get_tdl (), d);
+
+	/* Process preprobe fdi files */
+	di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
+
+	/* Run preprobe callouts */
+	hal_util_callout_device_preprobe (d, devinfo_callouts_preprobing_done, end_token, handler);
+
+	return;
+
+error:
+	g_object_unref (d);
+	hotplug_event_end (end_token);
+}
+
+static void
+devinfo_storage_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2)
+{
+        void *end_token = (void *) userdata1;
+
+	HAL_INFO (("devinfo_storage_probing_done %s", hal_device_get_udi (d)));
+
+        /* Discard device if probing reports failure */
+        if (exit_type != HALD_RUN_SUCCESS || return_code != 0) {
+		HAL_INFO (("devinfo_storage_probing_done returning exit_type=%d return_code=%d", exit_type, return_code));
+                hal_device_store_remove (hald_get_tdl (), d);
+                g_object_unref (d);
+                hotplug_event_end (end_token);
+		return;
+        }
+
+	devinfo_storage_set_nicknames (d);
+
+        /* Merge properties from .fdi files */
+        di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
+        di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
+
+	hal_util_callout_device_add (d, devinfo_callouts_add_done, end_token, NULL);
+}
+
+const gchar *
+devinfo_storage_get_prober (HalDevice *d, int *timeout)
+{
+	*timeout = DEVINFO_PROBE_STORAGE_TIMEOUT;
+	return "hald-probe-storage";
+}
+
+const gchar *
+devinfo_volume_get_prober (HalDevice *d, int *timeout)
+{
+	*timeout = DEVINFO_PROBE_VOLUME_TIMEOUT;
+	return "hald-probe-volume";
+}
+
+/*
+ * After reprobing storage, reprobe its volumes.
+ */
+static void
+devinfo_storage_rescan_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2)
+{
+        void *end_token = (void *) userdata1;
+	const char *devfs_path_orig = NULL;
+	char *devfs_path = NULL;
+	char *p;
+	di_node_t node;
+
+	HAL_INFO (("devinfo_storage_rescan_probing_done %s", hal_device_get_udi (d)));
+
+	devfs_path_orig = hal_device_property_get_string (d, "solaris.devfs_path");
+	if (devfs_path_orig == NULL) {
+		HAL_INFO (("device has no solaris.devfs_path"));
+		hotplug_event_process_queue ();
+		return;
+	}
+
+	/* strip trailing minor part if any */
+	if (strrchr(devfs_path_orig, ':') != NULL) {
+		if ((devfs_path = strdup (devfs_path_orig)) != NULL) {
+			p = strrchr(devfs_path, ':');
+			*p = '\0';
+		}
+	} else {
+		devfs_path = (char *)devfs_path_orig;
+	}
+
+	if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
+		HAL_INFO (("di_init %s failed %d %s", devfs_path, errno, hal_device_get_udi (d)));
+		hotplug_event_process_queue ();
+		return;
+	} else {
+		devinfo_storage_minors (d, node, (char *)devfs_path, TRUE);
+		di_fini (node);
+	}
+
+	if (devfs_path != devfs_path_orig) {
+		free (devfs_path);
+	}
+
+	hotplug_event_process_queue ();
+}
+
+/*
+ * For removable media devices, check for "storage.removable.media_available".
+ * For non-removable media devices, assume media is always there.
+ *
+ * If media is gone, enqueue remove events for all children volumes.
+ * If media is there, first reprobe storage, then probe for new volumes (but leave existing volumes alone).
+ */
+gboolean
+devinfo_storage_device_rescan (HalDevice *d)
+{
+	GSList *i;
+	GSList *volumes;
+	HalDevice *v;
+	gchar *v_devfs_path;
+	const char *drive_type;
+	gboolean is_floppy;
+	gboolean media_available;
+
+	HAL_INFO (("devinfo_storage_device_rescan udi=%s", hal_device_get_udi (d)));
+
+	if (hal_device_property_get_bool (d, "block.is_volume")) {
+		HAL_INFO (("nothing to do for volume"));
+		return (FALSE);
+	}
+
+	drive_type = hal_device_property_get_string (d, "storage.drive_type");
+	is_floppy = (drive_type != NULL) && (strcmp (drive_type, "floppy") == 0);
+		
+	media_available = !hal_device_property_get_bool (d, "storage.removable") ||
+	    hal_device_property_get_bool (d, "storage.removable.media_available");
+
+	if (!media_available && !is_floppy) {
+		HAL_INFO (("media gone %s", hal_device_get_udi (d)));
+
+		volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
+        	    "block.storage_device", hal_device_get_udi (d));
+		for (i = volumes; i != NULL; i = g_slist_next (i)) {
+        		v = HAL_DEVICE (i->data);
+			v_devfs_path = (gchar *)hal_device_property_get_string (v, "solaris.devfs_path");
+			HAL_INFO (("child volume %s", hal_device_get_udi (v)));
+			if ((v_devfs_path != NULL) && hal_device_has_capability (v, "volume")) {
+				HAL_INFO (("removing volume %s", hal_device_get_udi (v)));
+				devinfo_remove_enqueue (v_devfs_path, NULL);
+			} else {
+				HAL_INFO (("not a volume %s", hal_device_get_udi (v)));
+			}
+		}
+		g_slist_free (volumes);
+
+		hotplug_event_process_queue ();
+	} else if (is_floppy) {
+		HAL_INFO (("rescanning floppy %s", hal_device_get_udi (d)));
+		
+		hald_runner_run (d,
+				 "hald-probe-storage --only-check-for-media", NULL,
+				 DEVINFO_PROBE_STORAGE_TIMEOUT,
+				 devinfo_floppy_rescan_probing_done,
+				 NULL, NULL);
+	} else {
+		HAL_INFO (("media available %s", hal_device_get_udi (d)));
+
+		hald_runner_run (d,
+				 "hald-probe-storage --only-check-for-media", NULL,
+				 DEVINFO_PROBE_STORAGE_TIMEOUT,
+				 devinfo_storage_rescan_probing_done,
+				 NULL, NULL);
+	}
+
+	return TRUE;
+}
+
+static char *
+devinfo_volume_get_slice_name (char *devlink)
+{
+	char	*part, *slice, *disk;
+	char	*s = NULL;
+	char	*p;
+
+	if ((p = strstr(devlink, "/lofi/")) != 0) {
+		return (p + sizeof ("/lofi/") - 1);
+	}
+
+	part = strrchr(devlink, 'p');
+	slice = strrchr(devlink, 's');
+	disk = strrchr(devlink, 'd');
+
+	if ((part != NULL) && (part > slice) && (part > disk)) {
+		s = part;
+	} else if ((slice != NULL) && (slice > disk)) {
+		s = slice;
+	} else {
+		s = disk;
+	}
+	if ((s != NULL) && isdigit(s[1])) {
+		return (s);
+	} else {
+		return ("");
+	}
+}
+
+static gboolean
+is_dos_path(char *path, int *partnum)
+{
+	char *p;
+
+	if ((p = strrchr (path, ':')) == NULL) {
+		return (FALSE);
+	}
+	return ((*partnum = atoi(p + 1)) != 0);
+}
+
+static gboolean
+dos_to_dev(char *path, char **devpath, int *partnum)
+{
+	char *p;
+
+	if ((p = strrchr (path, ':')) == NULL) {
+		return (FALSE);
+	}
+	if ((*partnum = atoi(p + 1)) == 0) {
+		return (FALSE);
+	}
+	p[0] = '\0';
+	*devpath = strdup(path);
+	p[0] = ':';
+	return (*devpath != NULL);
+}
+
+static void
+devinfo_storage_cleanup_mountpoint_cb (HalDevice *d, guint32 exit_type, 
+		       gint return_code, gchar **error,
+		       gpointer data1, gpointer data2)
+{
+	char *mount_point = (char *) data1;
+
+	HAL_INFO (("Cleaned up mount point '%s'", mount_point));
+	g_free (mount_point);
+}
+
+
+void
+devinfo_storage_mnttab_event (HalDevice *hal_volume)
+{
+	FILE *fp = NULL;
+        struct extmnttab m;
+	HalDevice *d;
+	unsigned int major;
+	unsigned int minor;
+	GSList *volumes = NULL;
+	GSList *v;
+	char *mount_point;
+	dbus_bool_t is_partition;
+	const char *fstype;
+	int partition_number;
+
+	if (hal_volume != NULL) {
+		volumes = g_slist_append (NULL, hal_volume);
+	} else {
+		volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.category", "volume");
+	}
+	if (volumes == NULL) {
+		return;
+	}
+
+	if ((fp = fopen(MNTTAB, "r")) == NULL) {
+		HAL_ERROR (("Open failed %s errno %d", MNTTAB, errno));
+		return;
+	}
+
+	while (getextmntent(fp, &m, 1) == 0) {
+		for (v = volumes; v != NULL; v = g_slist_next (v)) {
+			d = HAL_DEVICE (v->data);
+			major = hal_device_property_get_int (d, "block.major");
+			minor = hal_device_property_get_int (d, "block.minor");
+
+			/*
+			 * special handling for pcfs, which encodes logical
+			 * drive number into the 6 upper bits of the minor
+			 */
+			is_partition = hal_device_property_get_bool (d, "volume.is_partition");
+			partition_number = hal_device_property_get_int (d, "volume.partition.number");
+			fstype = hal_device_property_get_string (d, "volume.fstype");
+
+			if (is_partition && (partition_number > 0) && (strcmp (fstype, "pcfs") == 0)) {
+				minor |= partition_number << 12;
+			}
+
+			if (m.mnt_major != major || m.mnt_minor != minor) {
+				continue;
+			}
+
+			/* this volume matches the mnttab entry */
+			device_property_atomic_update_begin ();
+			hal_device_property_set_bool (d, "volume.is_mounted", TRUE);
+			hal_device_property_set_bool (d, "volume.is_mounted_read_only",
+						      hasmntopt ((struct mnttab *)&m, "ro") ? TRUE : FALSE);
+			hal_device_property_set_string (d, "volume.mount_point", m.mnt_mountp);
+			device_property_atomic_update_end ();
+
+			HAL_INFO (("set %s to be mounted at %s",
+				   hal_device_get_udi (d), m.mnt_mountp));
+			volumes = g_slist_delete_link (volumes, v);
+		}
+	}
+
+	/* all remaining volumes are not mounted */
+	for (v = volumes; v != NULL; v = g_slist_next (v)) {
+		d = HAL_DEVICE (v->data);
+		mount_point = g_strdup (hal_device_property_get_string (d, "volume.mount_point"));
+		if (mount_point == NULL || strlen (mount_point) == 0) {
+			g_free (mount_point);
+			continue;
+		}
+
+		device_property_atomic_update_begin ();
+		hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
+		hal_device_property_set_bool (d, "volume.is_mounted_read_only", FALSE);
+		hal_device_property_set_string (d, "volume.mount_point", "");
+		device_property_atomic_update_end ();
+
+		HAL_INFO (("set %s to unmounted", hal_device_get_udi (d)));
+
+		/* cleanup if was mounted by us */
+		if (hal_util_is_mounted_by_hald (mount_point)) {
+			char *cleanup_stdin;
+			char *extra_env[2];
+
+			HAL_INFO (("Cleaning up '%s'", mount_point));
+
+			extra_env[0] = g_strdup_printf ("HALD_CLEANUP=%s", mount_point);
+			extra_env[1] = NULL;
+			cleanup_stdin = "\n";
+
+			hald_runner_run_method (d, 
+						"hal-storage-cleanup-mountpoint", 
+						extra_env, 
+						cleanup_stdin, TRUE,
+						0,
+						devinfo_storage_cleanup_mountpoint_cb,
+						g_strdup (mount_point), NULL);
+
+			g_free (extra_env[0]);
+		}
+
+		g_free (mount_point);
+	}
+	g_slist_free (volumes);
+
+	(void) fclose (fp);
+}
+
+static void
+devinfo_volume_force_unmount_cb (HalDevice *d, guint32 exit_type, 
+		  gint return_code, gchar **error,
+		  gpointer data1, gpointer data2)
+{
+	void *end_token = (void *) data1;
+
+	HAL_INFO (("devinfo_volume_force_unmount_cb for udi='%s', exit_type=%d, return_code=%d", hal_device_get_udi (d), exit_type, return_code));
+
+	if (exit_type == HALD_RUN_SUCCESS && error != NULL && 
+	    error[0] != NULL && error[1] != NULL) {
+		char *exp_name = NULL;
+		char *exp_detail = NULL;
+
+		exp_name = error[0];
+		if (error[0] != NULL) {
+			exp_detail = error[1];
+		}
+		HAL_INFO (("failed with '%s' '%s'", exp_name, exp_detail));
+	}
+
+	hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
+}
+
+static void
+devinfo_volume_force_unmount (HalDevice *d, void *end_token)
+{
+	const char *device_file;
+	const char *mount_point;
+	char *unmount_stdin;
+	char *extra_env[2];
+	extra_env[0] = "HAL_METHOD_INVOKED_BY_UID=0";
+	extra_env[1] = NULL;
+
+	device_file = hal_device_property_get_string (d, "block.device");
+	mount_point = hal_device_property_get_string (d, "volume.mount_point");
+
+	if (mount_point == NULL || strlen (mount_point) == 0 || !hal_util_is_mounted_by_hald (mount_point)) {
+		hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
+		return;
+	}
+
+	HAL_INFO (("devinfo_volume_force_unmount for udi='%s'", hal_device_get_udi (d)));
+		
+	unmount_stdin = "\n";
+		
+	hald_runner_run_method (d, 
+				"hal-storage-unmount", 
+				extra_env, 
+				unmount_stdin, TRUE,
+				0,
+				devinfo_volume_force_unmount_cb,
+				end_token, NULL);
+}
+
+void
+devinfo_volume_hotplug_begin_remove (HalDevice *d, char *devfs_path, void *end_token)
+{
+	if (hal_device_property_get_bool (d, "volume.is_mounted")) {
+		devinfo_volume_force_unmount (d, end_token);
+	} else {
+		hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
+	}
+}
+
+
+enum {
+	LEGACY_CDROM,
+	LEGACY_FLOPPY,
+	LEGACY_RMDISK
+};
+
+static const char *legacy_media_str[] = {
+	"cdrom",
+	"floppy",
+	"rmdisk"
+};
+
+struct enum_nick {
+	const char *type;
+	GSList	*nums;
+};
+
+static int
+devinfo_storage_get_legacy_media(HalDevice *d)
+{
+	const char *drive_type;
+
+	if (hal_device_has_capability (d, "storage.cdrom")) {
+		return (LEGACY_CDROM);
+	} else if (((drive_type = hal_device_property_get_string (d,
+	    "storage.drive_type")) != NULL) && (strcmp (drive_type, "floppy") == 0)) {
+		return (LEGACY_FLOPPY);
+	} else if (hal_device_property_get_bool (d, "storage.removable") ||
+	           hal_device_property_get_bool (d, "storage.hotpluggable")) {
+		return (LEGACY_RMDISK);
+	} else {
+		return (-1);
+	}
+}
+
+static gboolean
+devinfo_storage_foreach_nick (HalDeviceStore *store, HalDevice *d, gpointer user_data)
+{
+	struct enum_nick *en = (struct enum_nick *) user_data;
+	const char *media_type;
+	int media_num;
+
+	media_type = hal_device_property_get_string (d, "storage.solaris.legacy.media_type");
+	media_num = hal_device_property_get_int (d, "storage.solaris.legacy.media_num");
+	if ((media_type != NULL) && (strcmp (media_type, en->type) == 0) &&
+	    (media_num >= 0)) {
+		en->nums = g_slist_prepend (en->nums, GINT_TO_POINTER(media_num));
+	}
+	return TRUE;
+}
+
+static void
+devinfo_storage_append_nickname (HalDevice *d, const char *media_type, int media_num)
+{
+	char buf[64];
+
+	if (media_num == 0) {
+		hal_device_property_strlist_append (d, "storage.solaris.nicknames", media_type, FALSE);
+	}
+	snprintf(buf, sizeof (buf), "%s%d", media_type, media_num);
+	hal_device_property_strlist_append (d, "storage.solaris.nicknames", buf, FALSE);
+}
+
+static void
+devinfo_storage_set_nicknames (HalDevice *d)
+{
+	int media;
+	const char *media_type;
+	int media_num;
+	GSList *i;
+	struct enum_nick en;
+	char buf[64];
+
+	if ((media = devinfo_storage_get_legacy_media (d)) < 0) {
+		return;
+	}
+	media_type = legacy_media_str[media];
+
+	/* enumerate all storage devices of this media type */
+	en.type = media_type;
+	en.nums = NULL;
+	hal_device_store_foreach (hald_get_gdl (), devinfo_storage_foreach_nick, &en);
+
+	/* find a free number */
+	for (media_num = 0; ; media_num++) {
+		for (i = en.nums; i != NULL; i = g_slist_next (i)) {
+        		if (GPOINTER_TO_INT (i->data) == media_num) {
+				break;
+			}
+		}
+		if (i == NULL) {
+			break;
+		}
+	}
+	g_slist_free (en.nums);
+
+	hal_device_property_set_string (d, "storage.solaris.legacy.media_type", media_type);
+	hal_device_property_set_int (d, "storage.solaris.legacy.media_num", media_num);
+
+	/* primary nickname, and also vold-style symdev */
+	snprintf(buf, sizeof (buf), "%s%d", media_type, media_num);
+	hal_device_property_set_string (d, "storage.solaris.legacy.symdev", buf);
+	devinfo_storage_append_nickname(d, media_type, media_num);
+
+	/* additional nicknames */
+	if (media == LEGACY_CDROM) {
+		devinfo_storage_append_nickname(d, "cd", media_num);
+		devinfo_storage_append_nickname(d, "sr", media_num);
+	} else if (media == LEGACY_FLOPPY) {
+		devinfo_storage_append_nickname(d, "fd", media_num);
+		devinfo_storage_append_nickname(d, "diskette", media_num);
+		devinfo_storage_append_nickname(d, "rdiskette", media_num);
+	}
+}
diff --git a/hal/files/hald-netbsd/devinfo_storage.h b/hal/files/hald-netbsd/devinfo_storage.h
new file mode 100644
index 0000000000..9238fe539c
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_storage.h
@@ -0,0 +1,30 @@
+/***************************************************************************
+ *
+ * devinfo_storage.h : definitions for storage devices
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef DEVINFO_STORAGE_H
+#define DEVINFO_STORAGE_H
+
+#include "devinfo.h"
+
+extern DevinfoDevHandler devinfo_ide_handler;
+extern DevinfoDevHandler devinfo_scsi_handler;
+extern DevinfoDevHandler devinfo_pcata_handler;
+extern DevinfoDevHandler devinfo_floppy_handler;
+extern DevinfoDevHandler devinfo_lofi_handler;
+
+gboolean devinfo_storage_device_rescan (HalDevice *d);
+HalDevice *devinfo_lofi_add_major(HalDevice *parent, const char *devinfo, char *devfs_path,
+    char *device_type, gboolean rescan, HalDevice *lofi_d);
+void devinfo_lofi_remove_minor(char *parent_devfs_path, char *name);
+void devinfo_storage_mnttab_event (HalDevice *hal_volume);
+void devinfo_volume_hotplug_begin_remove (HalDevice *d, char *devfs_path, void *end_token);
+
+#endif /* DEVINFO_STORAGE_H */
diff --git a/hal/files/hald-netbsd/devinfo_usb.c b/hal/files/hald-netbsd/devinfo_usb.c
new file mode 100644
index 0000000000..a93327296c
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_usb.c
@@ -0,0 +1,229 @@
+/***************************************************************************
+ *
+ * devinfo_usb.h : USB devices
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#pragma ident	"@(#)devinfo_usb.c	1.2	06/10/13 SMI"
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <libdevinfo.h>
+#include <sys/types.h>
+#include <sys/mkdev.h>
+#include <sys/stat.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "../ids.h"
+#include "hotplug.h"
+#include "devinfo.h"
+#include "devinfo_usb.h"
+
+HalDevice *devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
+static HalDevice *devinfo_usb_if_add(HalDevice *d, di_node_t node, gchar *devfs_path, int ifnum);
+static HalDevice *devinfo_usb_scsa2usb_add(HalDevice *d, di_node_t node, gchar *devfs_path);
+
+DevinfoDevHandler devinfo_usb_handler = {
+        devinfo_usb_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+        NULL
+};
+
+HalDevice *
+devinfo_usb_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
+{
+	HalDevice *d, *nd = NULL;
+	char	*s;
+	int	*i, *vid;
+	char	*driver_name, *binding_name;
+        char    if_devfs_path[HAL_PATH_MAX];
+
+	/*
+	 * we distinguish USB devices by presence of "usb-vendor-id"
+	 * property. should USB devices have "device_type"?
+	 */
+        if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "usb-vendor-id", &vid) <= 0) {
+		return (NULL);
+	}
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, node, devfs_path);
+	hal_device_property_set_string (d, "info.subsystem", "usb_device");
+	PROP_STR(d, node, s, "usb-product-name", "info.product");
+	PROP_STR(d, node, s, "usb-product-name", "usb_device.product");
+	PROP_STR(d, node, s, "usb-vendor-name", "usb_device.vendor");
+	PROP_INT(d, node, i, "usb-vendor-id", "usb_device.vendor_id");
+	PROP_INT(d, node, i, "usb-product-id", "usb_device.product_id");
+	PROP_INT(d, node, i, "usb-revision-id", "usb_device.device_revision_bcd");
+	PROP_INT(d, node, i, "usb-release-id", "usb_device.version_bcd");
+	PROP_STR(d, node, s, "usb-serialno", "usb_device.serial");
+
+	/* class, subclass */
+	/* hal_device_property_set_int (d, "usb_device.device_class", 8); */
+
+	/* binding name tells us if driver is bound to interface or device */
+	if (((binding_name = di_binding_name(node)) != NULL) &&
+	    (strncmp(binding_name, "usbif,", sizeof ("usbif,") - 1) == 0)) {
+		snprintf(if_devfs_path, sizeof (if_devfs_path), "%s:if%d", devfs_path, 0);
+		if ((nd = devinfo_usb_if_add(d, node, if_devfs_path, 0)) != NULL) {
+			d = nd;
+			nd = NULL;
+			devfs_path = if_devfs_path;
+		}
+	}
+
+	/* driver specific */
+	driver_name = di_driver_name (node);
+	if ((driver_name != NULL) && (strcmp (driver_name, "scsa2usb") == 0)) {
+		nd = devinfo_usb_scsa2usb_add (d, node, devfs_path);
+	} else {
+		devinfo_add_enqueue (d, devfs_path, &devinfo_usb_handler);
+	}
+
+out:
+	if (nd != NULL) {
+		return (nd);
+	} else {
+		return (d);
+	}
+}
+
+static HalDevice *
+devinfo_usb_if_add(HalDevice *parent, di_node_t node, gchar *devfs_path, int ifnum)
+{
+	HalDevice *d = NULL;
+        char    udi[HAL_PATH_MAX];
+
+	devinfo_add_enqueue (parent, devfs_path, &devinfo_usb_handler);
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, node, devfs_path);
+        hal_device_property_set_string (d, "info.subsystem", "usb");
+
+	hald_compute_udi (udi, sizeof (udi),
+			  "%s_if%d", hal_device_get_udi (parent), ifnum);
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.product", "USB Device Interface");
+
+	/* copy parent's usb_device.* properties */
+	hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device.");
+
+	return (d);
+}
+
+static int
+walk_devlinks(di_devlink_t devlink, void *arg)
+{
+        char **path = (char **)arg;
+
+        *path = strdup(di_devlink_path(devlink));
+
+        return (DI_WALK_TERMINATE);
+}
+
+static char *
+get_devlink(di_devlink_handle_t devlink_hdl, char *path)
+{
+	char *devlink = NULL;
+
+        (void) di_devlink_walk(devlink_hdl, NULL, path,
+            DI_PRIMARY_LINK, &devlink, walk_devlinks);
+
+        return (devlink);
+}
+
+static HalDevice *
+devinfo_usb_scsa2usb_add(HalDevice *usbd, di_node_t node, gchar *devfs_path)
+{
+	HalDevice *d = NULL;
+	di_devlink_handle_t devlink_hdl;
+        int     major;
+        di_minor_t minor;
+        dev_t   devt;
+        char    *minor_path = NULL;
+	char	*devlink = NULL;
+        char    udi[HAL_PATH_MAX];
+
+	devinfo_add_enqueue (usbd, devfs_path, &devinfo_usb_handler);
+
+        if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
+                printf("di_devlink_init() failed\n");
+                return (NULL);
+        }
+
+        major = di_driver_major(node);
+        minor = DI_MINOR_NIL;
+        while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
+                devt = di_minor_devt(minor);
+                if (major != major(devt)) {
+                        continue;
+                }
+                if ((minor_path = di_devfs_minor_path(minor)) == NULL) {
+                        continue;
+                }
+                if (di_minor_type(minor) != DDM_MINOR) {
+                        continue;
+                }
+		if (strcmp (di_minor_nodetype(minor),
+		    "ddi_ctl:devctl:scsi") == 0) {
+                	devlink = get_devlink(devlink_hdl, minor_path);
+                	if (devlink == NULL) {
+				devlink = strdup("");
+			}
+			break;
+		}
+		di_devfs_path_free (minor_path);
+		minor_path = NULL;
+        }
+
+	di_devlink_fini (&devlink_hdl);
+
+	if (devlink == NULL) {
+		goto out;
+	}
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, usbd, node, minor_path);
+       	hal_device_property_set_string (d, "scsi_host.solaris.device", devlink);
+        hal_device_property_set_string (d, "info.category", "scsi_host");
+        hal_device_property_set_int (d, "scsi_host.host", 0);
+
+	hald_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			  "%s/scsi_host%d", hal_device_get_udi (usbd),
+			  hal_device_property_get_int (d, "scsi_host.host"));
+        hal_device_set_udi (d, udi);
+        hal_device_property_set_string (d, "info.product", "SCSI Host Adapter");
+
+	devinfo_add_enqueue (d, minor_path, &devinfo_usb_handler);
+
+out:
+	if (devlink) {
+		free(devlink);
+	}
+	if (minor_path) {
+		di_devfs_path_free (minor_path);
+	}
+
+	return (d);
+}
+
diff --git a/hal/files/hald-netbsd/devinfo_usb.h b/hal/files/hald-netbsd/devinfo_usb.h
new file mode 100644
index 0000000000..01864c2011
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_usb.h
@@ -0,0 +1,23 @@
+/***************************************************************************
+ *
+ * devinfo_usb.h : definitions for USB devices
+ *
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef DEVINFO_USB_H
+#define	DEVINFO_USB_H
+
+#include "devinfo.h"
+
+#define bcd(a) ((((a) & 0xf000) >> 12) * 1000 + (((a) & 0xf00) >> 8) * 100 + (((a) & 0xf0) >> 4) * 10 + ((a) & 0xf))
+
+extern DevinfoDevHandler devinfo_usb_handler;
+
+HalDevice *devinfo_usb_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type);
+
+#endif /* DEVINFO_USB_H */
diff --git a/hal/files/hald-netbsd/devinfo_video.c b/hal/files/hald-netbsd/devinfo_video.c
new file mode 100644
index 0000000000..8325065895
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_video.c
@@ -0,0 +1,125 @@
+/* $NetBSD: devinfo_video.c,v 1.1 2008/11/27 22:19:10 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2008 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/videoio.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <paths.h>
+#include <unistd.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "../ids.h"
+#include "hotplug.h"
+#include "devinfo.h"
+#include "devinfo_video.h"
+#include "drvctl.h"
+
+HalDevice *devinfo_video_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type);
+
+DevinfoDevHandler devinfo_video_handler = {
+	devinfo_video_add,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+HalDevice *
+devinfo_video_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
+{
+	HalDevice *d = NULL;
+	prop_dictionary_t dict;
+	const char *driver, *parent_udi;
+	char *videodev;
+	int16_t unit;
+	struct v4l2_capability caps;
+	int fd;
+
+	if (drvctl_find_device (devnode, &dict) == FALSE || dict == NULL)
+		return NULL;
+
+	if (prop_dictionary_get_int16 (dict, "device-unit", &unit) == false ||
+	    prop_dictionary_get_cstring_nocopy (dict, "device-driver", &driver) == false) {
+		prop_object_release (dict);
+		return NULL;
+	}
+
+	prop_object_release (dict);
+
+	if (strcmp (driver, "video") != 0)
+		return NULL;
+
+	videodev = g_strdup_printf ("/dev/video%d", unit);
+	fd = open (videodev, O_RDONLY);
+	if (fd < 0) {
+		HAL_WARNING (("couldn't open %s: %s", videodev, strerror(errno)));
+		goto done;
+	}
+
+	if (ioctl (fd, VIDIOC_QUERYCAP, &caps) == -1) {
+		HAL_WARNING (("couldn't query %s: %s", videodev, strerror(errno)));
+		close (fd);
+		goto done;
+	}
+
+	close (fd);
+
+	d = hal_device_new ();
+
+	devinfo_set_default_properties (d, parent, devnode, devfs_path);
+	hal_device_add_capability (d, "video4linux");
+	if (caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)
+		hal_device_add_capability (d, "video4linux.video_capture");
+	hal_device_property_set_string (d, "info.category", "video4linux");
+	hal_device_property_set_string (d, "info.subsystem", "video4linux");
+
+	hal_device_property_set_string (d, "video4linux.device", videodev);
+	hal_device_property_set_int (d, "video4linux.version", 2);
+	hal_device_property_set_string (d, "info.product", caps.card);
+
+	devinfo_add_enqueue (d, devfs_path, &devinfo_video_handler);
+
+done:
+	if (videodev)
+		g_free (videodev);
+
+	return d;
+}
diff --git a/hal/files/hald-netbsd/devinfo_video.h b/hal/files/hald-netbsd/devinfo_video.h
new file mode 100644
index 0000000000..d9828ce2b8
--- /dev/null
+++ b/hal/files/hald-netbsd/devinfo_video.h
@@ -0,0 +1,36 @@
+/* $NetBSD: devinfo_video.h,v 1.1 2008/11/27 22:19:10 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2008 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DEVINFO_VIDEO_H
+#define DEVINFO_VIDEO_H
+
+#include "devinfo.h"
+
+extern DevinfoDevHandler devinfo_video_handler;
+
+#endif /* DEVINFO_VIDEO_H */
diff --git a/hal/files/hald-netbsd/drvctl.c b/hal/files/hald-netbsd/drvctl.c
new file mode 100644
index 0000000000..5384a1f792
--- /dev/null
+++ b/hal/files/hald-netbsd/drvctl.c
@@ -0,0 +1,303 @@
+/***************************************************************************
+ *
+ * drvctl.c : NetBSD drvctl events
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/drvctlio.h>
+#include <sys/dkio.h>
+#include <sys/stat.h>
+#include <sys/drvctlio.h>
+#include <glib.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "osspec_netbsd.h"
+#include "hotplug.h"
+#include "devinfo.h"
+#include "devinfo_storage.h"
+#include "drvctl.h"
+
+static gboolean drvctl_iochannel_data(GIOChannel *, GIOCondition, gpointer);
+static void	drvctl_dev_add(gchar *);
+static void	drvctl_dev_remove(gchar *);
+static void	drvctl_dev_branch(gchar *);
+
+static int drvctl_fd;
+static GIOChannel *drvctl_iochannel;
+
+gboolean
+drvctl_init(void)
+{
+	drvctl_fd = open (DRVCTLDEV, O_RDWR);
+	if (drvctl_fd == -1) {
+		HAL_INFO (("open(%s, O_RDWR) failed: %s", DRVCTLDEV, strerror(errno)));
+		return FALSE;
+	}
+
+        drvctl_iochannel = g_io_channel_unix_new (drvctl_fd);
+	if (drvctl_iochannel == NULL) {
+                HAL_INFO (("g_io_channel_unix_new failed"));
+		return FALSE;
+	}
+        g_io_add_watch (drvctl_iochannel, G_IO_IN, drvctl_iochannel_data, NULL);
+
+	return TRUE;
+}
+
+void
+drvctl_fini(void)
+{
+	HAL_INFO (("drvctl_fini"));
+}
+
+static gboolean
+drvctl_iochannel_data (GIOChannel *source,
+                    GIOCondition condition,
+                    gpointer user_data)
+{
+	prop_dictionary_t ev;
+	const char *event, *device;
+	int res;
+
+	HAL_INFO (("drvctl_iochannel_data"));
+
+	res = prop_dictionary_recv_ioctl (drvctl_fd, DRVGETEVENT, &ev);
+	if (res) {
+		HAL_WARNING (("DRVGETEVENT failed: %s", strerror(errno)));
+		return FALSE;
+	}
+
+	if (!prop_dictionary_get_cstring_nocopy (ev, "event", &event)) {
+		HAL_WARNING (("DRVGETEVENT missing \"event\" parameter"));
+		goto done;
+	}
+	if (!prop_dictionary_get_cstring_nocopy (ev, "device", &device)) {
+		HAL_WARNING (("DRVGETEVENT missing \"device\" parameter"));
+		goto done;
+	}
+
+	HAL_INFO (("DRVGETEVENT event=%s device=%s", event, device));
+
+	if (strcmp (event, "device-attach") == 0) {
+		drvctl_dev_add (device);
+	} else {
+		drvctl_dev_remove (device);
+	}
+
+done:
+	prop_object_release(ev);
+	return TRUE;
+}
+
+static void
+drvctl_dev_add(gchar *name)
+{
+	HalDevice *parent, *d;
+	gchar pdevnode[512];
+
+	if (drvctl_find_parent (name, pdevnode) == FALSE) {
+		HAL_INFO (("dev_add: name=%s orphan", name));
+		parent = NULL;
+	} else {
+		parent = hal_device_store_match_key_value_string (
+		    hald_get_gdl(), "netbsd.device", pdevnode);
+		if (parent == NULL)
+			HAL_INFO (("dev_add: name=%s but netbsd.device=%s not found",name, pdevnode));
+	}
+
+	d = devinfo_add_node (parent, name);
+	if (d == NULL)
+		HAL_WARNING (("dev_add: couldn't add %s node (parent=%p)", name, parent));
+
+	hotplug_event_process_queue ();
+}
+
+static void
+drvctl_dev_remove(gchar *name)
+{
+	HAL_INFO (("dev_remove: %s", name));
+
+	devinfo_remove_branch (name, NULL);
+	hotplug_event_process_queue ();
+}
+
+static void
+drvctl_dev_branch(gchar *name)
+{
+	HAL_INFO (("branch_remove: %s", name));
+
+	devinfo_remove_branch (name, NULL);
+	hotplug_event_process_queue ();
+}
+
+int
+drvctl_list(const gchar *name, struct devlistargs *laa)
+{
+	size_t children;
+
+	/* HAL_INFO (("drvctl_list: %s", name)); */
+
+	memset (laa, 0, sizeof (*laa));
+	strlcpy (laa->l_devname, name, sizeof (laa->l_devname));
+	if (ioctl (drvctl_fd, DRVLISTDEV, laa) == -1) {
+		HAL_INFO (("DRVLISTDEV/1 failed: %s", strerror(errno)));
+		return -1;
+	}
+	children = laa->l_children;
+	/* HAL_INFO (("%s: found %d children", name, children)); */
+	if (children == 0)
+		return -1;
+	laa->l_childname = malloc (children * sizeof (laa->l_childname[0]));
+	if (laa->l_childname == NULL) {
+		HAL_INFO (("drvctl_list couldn't allocate %d children: %s\n", children, strerror(errno)));
+		return -1;
+	}
+	if (ioctl (drvctl_fd, DRVLISTDEV, laa) == -1) {
+		HAL_INFO (("DRVLISTDEV/2 failed: %s", strerror(errno)));
+		return -1;
+	}
+	if (children != laa->l_children)
+		HAL_WARNING (("DRVLISTDEV/3 expected %d children, got %d", children, laa->l_childname));
+}
+
+gboolean
+drvctl_find_device(const gchar *devnode, prop_dictionary_t *properties)
+{
+	prop_dictionary_t command_dict;
+	prop_dictionary_t args_dict;
+	prop_dictionary_t results_dict;
+	int err;
+	   
+	command_dict = prop_dictionary_create ();
+	args_dict = prop_dictionary_create ();
+		
+	prop_dictionary_set_cstring_nocopy (command_dict, "drvctl-command", "get-properties");
+	prop_dictionary_set_cstring_nocopy (args_dict, "device-name", devnode);  
+	prop_dictionary_set (command_dict, "drvctl-arguments", args_dict);
+	prop_object_release (args_dict);
+
+	err = prop_dictionary_sendrecv_ioctl (command_dict, drvctl_fd,
+					      DRVCTLCOMMAND, &results_dict);
+	prop_object_release (command_dict);
+	if (err)
+		return FALSE;
+
+	if (prop_dictionary_get_int8 (results_dict, "drvctl-error", &err) == false || err != 0) {
+		prop_object_release (results_dict);
+		return FALSE;
+	}
+
+	if (properties) {
+		prop_dictionary_t result_data;
+		result_data = prop_dictionary_get (results_dict, "drvctl-result-data");
+		if (result_data)
+			*properties = prop_dictionary_copy (result_data);
+	}
+
+	prop_object_release (results_dict);
+
+	return TRUE;
+}
+
+static gboolean
+drvctl_find_device_with_child(const gchar *curnode, const gchar *devnode,
+    char *parent)
+{
+	struct devlistargs laa;
+	u_int i;
+
+	if (drvctl_list (curnode, &laa) == -1)
+		return FALSE;
+
+	for (i = 0; i < laa.l_children; i++) {
+		if (strcmp (laa.l_childname[i], devnode) == 0) {
+			strlcpy(parent, curnode, 16);
+			free(laa.l_childname);
+			return TRUE;
+		}
+		if (drvctl_find_device_with_child (laa.l_childname[i], devnode, parent) == TRUE) {
+			free(laa.l_childname);
+			return TRUE;
+		}
+	}
+
+	if (laa.l_childname)
+		free(laa.l_childname);
+
+	HAL_INFO (("%s: couldn't find device with child %s", curnode, devnode));
+	return FALSE;
+}
+
+gboolean
+drvctl_find_parent(const gchar *devnode, char *parent)
+{
+	return drvctl_find_device_with_child("mainbus0", devnode, parent);
+}
+
+#if 0
+static void
+drvctl_lofi_add(gchar *devfs_path, gchar *name)
+{
+	di_node_t node;
+	const char *parent_udi;
+	HalDevice *d, *parent;
+
+	HAL_INFO (("lofi_add: %s %s", name, devfs_path));
+
+	if ((d = hal_device_store_match_key_value_string (hald_get_gdl (),
+	    "solaris.devfs_path", devfs_path)) == NULL) {
+		HAL_INFO (("device not found in GDL %s", devfs_path));
+		return;
+	}
+	parent_udi = hal_device_property_get_string (d, "info.parent");
+	if ((parent_udi == NULL) || (strlen(parent_udi) == 0)) {
+		HAL_INFO (("parent not found in GDL %s", parent_udi));
+		return;
+	}
+	if ((parent = hal_device_store_match_key_value_string (hald_get_gdl (),
+	    "info.udi", parent_udi)) == NULL) {
+		HAL_INFO (("parent not found in GDL %s", parent_udi));
+		return;
+	}
+
+	if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
+		HAL_INFO (("device not found in devinfo %s", devfs_path));
+		return;
+	}
+
+	HAL_INFO (("device %s parent %s", hal_device_get_udi (d), parent_udi));
+	devinfo_lofi_add_major (parent, node, devfs_path, NULL, TRUE, d);
+
+	di_fini (node);
+
+	hotplug_event_process_queue ();
+}
+
+static void
+drvctl_lofi_remove(gchar *parent_devfs_path, gchar *name)
+{
+	devinfo_lofi_remove_minor(parent_devfs_path, name);
+	hotplug_event_process_queue ();
+}
+#endif
diff --git a/hal/files/hald-netbsd/drvctl.h b/hal/files/hald-netbsd/drvctl.h
new file mode 100644
index 0000000000..9e94fae49b
--- /dev/null
+++ b/hal/files/hald-netbsd/drvctl.h
@@ -0,0 +1,24 @@
+/***************************************************************************
+ *
+ * drvctl.h : definitions for NetBSD drvctl events
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef DRVCTL_H
+#define DRVCTL_H
+
+#include <glib.h>
+#include <sys/drvctlio.h>
+
+gboolean drvctl_init(void);
+void drvctl_fini(void);
+int drvctl_list(const gchar *devnode, struct devlistargs *laa);
+gboolean drvctl_find_parent(const gchar *devnode, char *parent);
+gboolean drvctl_find_device(const gchar *devnode, prop_dictionary_t *properties);
+
+#endif /* DRVCTL_H */
diff --git a/hal/files/hald-netbsd/envsys.c b/hal/files/hald-netbsd/envsys.c
new file mode 100644
index 0000000000..7ecf8f7caa
--- /dev/null
+++ b/hal/files/hald-netbsd/envsys.c
@@ -0,0 +1,249 @@
+/* $NetBSD: envsys.c,v 1.6 2010/12/16 11:34:51 ahoka Exp $ */
+
+/*-
+ * Copyright (c) 2008 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/envsys.h>
+
+#include <prop/proplib.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "devinfo.h"
+#include "envsys.h"
+
+#define _DEV_SYSMON	"/dev/sysmon"
+
+static int envsys_fd = -1;
+
+static gboolean	envsys_timeout(gpointer user_data);
+static void envsys_handle_devnode(const char *devnode, prop_array_t properties);
+
+static void envsys_acadapter_handler(HalDevice *d, prop_array_t properties);
+static void envsys_battery_handler(HalDevice *d, prop_array_t properties);
+
+enum battery_state {
+	CHARGING,
+	DISCHARGING,
+	NORMAL
+};
+
+static struct envsys_devmap {
+	const char *capability;
+	void (*handler)(HalDevice *d, prop_array_t properties);
+} devmap[] = {
+	{ "ac_adapter",	envsys_acadapter_handler },
+	{ "battery",	envsys_battery_handler },
+};
+
+void
+envsys_init(void)
+{
+	envsys_fd = open (_DEV_SYSMON, O_RDONLY);
+	if (envsys_fd == -1) {
+		HAL_WARNING (("Couldn't open " _DEV_SYSMON ": %s", strerror(errno)));
+		return;
+	}
+
+	g_timeout_add (1000, envsys_timeout, NULL);
+}
+
+static gboolean
+envsys_timeout(gpointer user_data)
+{
+	prop_dictionary_t global_dict;
+	prop_array_t global_array;
+	prop_object_iterator_t iter;
+	prop_dictionary_keysym_t keysym;
+	int status;
+
+	status = prop_dictionary_recv_ioctl (envsys_fd, ENVSYS_GETDICTIONARY, &global_dict);
+	if (status) {
+		HAL_WARNING (("envsys_timeout: ENVSYS_GETDICTIONARY failed: %s", strerror(status)));
+		return FALSE;
+	}
+
+	global_array = prop_dictionary_all_keys (global_dict);
+	if (global_array == NULL) {
+		HAL_WARNING (("envsys_timeout: prop_dictionary_all_keys returned NULL"));
+		return FALSE;
+	}
+	iter = prop_array_iterator (global_array);
+	while ((keysym = (prop_dictionary_keysym_t)prop_object_iterator_next (iter)) != NULL) {
+		const char *devnode;
+		prop_object_t obj;
+
+		devnode = prop_dictionary_keysym_cstring_nocopy (keysym);
+		obj = prop_dictionary_get_keysym (global_dict, keysym);
+		if (obj == NULL || prop_object_type (obj) != PROP_TYPE_ARRAY)
+			continue;
+
+		envsys_handle_devnode (devnode, (prop_array_t)obj);
+	}
+	prop_object_iterator_release (iter);
+
+	prop_object_release (global_array);
+	prop_object_release (global_dict);
+	return TRUE;
+}
+
+static void
+envsys_handle_devnode(const char *devnode, prop_array_t properties)
+{
+	HalDevice *d;
+	unsigned int i;
+
+	d = hal_device_store_match_key_value_string (hald_get_gdl (), "netbsd.device", devnode);
+	if (d == NULL)
+		return;
+
+	for (i = 0; i < __arraycount (devmap); i++) {
+		if (!hal_device_has_capability (d, devmap[i].capability))
+			continue;
+		devmap[i].handler (d, properties);
+	}
+
+	return;
+}
+
+static void
+envsys_acadapter_handler(HalDevice *d, prop_array_t properties)
+{
+	prop_object_iterator_t iter;
+	prop_dictionary_t prop;
+
+	iter = prop_array_iterator (properties);
+	while ((prop = (prop_dictionary_t)prop_object_iterator_next (iter)) != NULL) {
+		const char *descr;
+		uint8_t connected;
+
+		if (prop_dictionary_get_cstring_nocopy (prop, "description", &descr) == false)
+			continue;
+
+		if (strcmp (descr, "connected") != 0)
+			continue;
+
+		if (prop_dictionary_get_uint8 (prop, "cur-value", &connected) == false)
+			continue;
+
+		hal_device_property_set_bool (d, "ac_adapter.present", connected);
+	}
+
+	prop_object_iterator_release (iter);
+}
+
+static void
+envsys_battery_handler(HalDevice *d, prop_array_t properties)
+{
+	prop_object_iterator_t iter;
+	prop_dictionary_t prop;
+	enum battery_state battstate = NORMAL;
+
+	device_property_atomic_update_begin ();
+
+	hal_device_property_set_bool (d, "battery.is_rechargeable", TRUE);
+
+	iter = prop_array_iterator (properties);
+	while ((prop = (prop_dictionary_t)prop_object_iterator_next (iter)) != NULL) {
+		const char *descr;
+		const char *valid;
+		int64_t intval;
+
+		if (prop_dictionary_get_cstring_nocopy (prop, "description", &descr) == false ||
+		    prop_dictionary_get_int64 (prop, "cur-value", &intval) == false ||
+		    prop_dictionary_get_cstring_nocopy (prop, "state", &valid) == false ||
+		    strcmp (valid, "valid") != 0)
+			continue;
+
+		if (strcmp (descr, "present") == 0)
+			hal_device_property_set_bool (d, "battery.present", intval);
+		else if (strcmp (descr, "design cap") == 0)
+			hal_device_property_set_int (d, "battery.charge_level.design", intval);
+		else if (strcmp (descr, "last full cap") == 0)
+			hal_device_property_set_int (d, "battery.charge_level.last_full", intval);
+		else if (strcmp (descr, "charge") == 0) {
+			int64_t maxval;
+			const char *type;
+
+			if (prop_dictionary_get_cstring_nocopy (prop, "type", &type))
+				if (strcmp (type, "Ampere hour") == 0) {
+					/* HAL 0.5.12 spec discourages this, but what can we do about it? */
+					hal_device_property_set_string (d, "battery.charge_level.unit", "mAh");
+				}
+
+			hal_device_property_set_int (d, "battery.charge_level.current", intval);
+
+			if (prop_dictionary_get_int64 (prop, "max-value", &maxval) && maxval > 0)
+				hal_device_property_set_int (d, "battery.charge_level.percentage", intval * 100 / maxval);
+			else
+				hal_device_property_set_int (d, "battery.charge_level.percentage", 0);
+		}
+		else if (strcmp (descr, "charge rate") == 0) {
+			battstate = CHARGING;
+			hal_device_property_set_int (d, "battery.charge_level.rate", intval);
+		} else if (strcmp (descr, "discharge rate") == 0) {
+			battstate = DISCHARGING;
+			hal_device_property_set_int (d, "battery.charge_level.rate", intval);
+		}
+	}
+
+	switch (battstate) {
+	case NORMAL:
+		hal_device_property_set_bool (d, "battery.rechargeable.is_charging", FALSE);
+		hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", FALSE);
+		hal_device_property_set_int (d, "battery.charge_level.rate", 0);
+		break;
+	case CHARGING:
+		hal_device_property_set_bool (d, "battery.rechargeable.is_charging", TRUE);
+		hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", FALSE);
+		break;
+	case DISCHARGING:
+		hal_device_property_set_bool (d, "battery.rechargeable.is_charging", FALSE);
+		hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", TRUE);
+		break;
+	}
+
+	device_property_atomic_update_end ();
+
+	prop_object_iterator_release (iter);
+}
diff --git a/hal/files/hald-netbsd/envsys.h b/hal/files/hald-netbsd/envsys.h
new file mode 100644
index 0000000000..fa228f3caf
--- /dev/null
+++ b/hal/files/hald-netbsd/envsys.h
@@ -0,0 +1,36 @@
+/* $NetBSD: envsys.h,v 1.1 2008/11/27 01:45:00 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2008 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DEVINFO_ENVSYS_H
+#define DEVINFO_ENVSYS_H
+
+#include "devinfo.h"
+
+void	envsys_init(void);
+
+#endif /* DEVINFO_ENVSYS_H */
diff --git a/hal/files/hald-netbsd/hal-file-monitor.c b/hal/files/hald-netbsd/hal-file-monitor.c
new file mode 100644
index 0000000000..1dddfa319d
--- /dev/null
+++ b/hal/files/hald-netbsd/hal-file-monitor.c
@@ -0,0 +1,821 @@
+/***************************************************************************
+ * CVSID: hal-file-monitor.c,v 1.1.1.1 2017/04/16 15:28:00 cvs Exp
+ *
+ * hal-file-monitor.c: Kqueue-based file monitor
+ *
+ * Copyright (C) 2007 Joe Marcus Clarke <marcus%FreeBSD.org@localhost>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ **************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <glib-object.h>
+
+#include "../hal-file-monitor.h"
+
+#define HAL_FILE_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), HAL_TYPE_FILE_MONITOR, HalFileMonitorPrivate))
+
+#define VN_NOTE_CHANGED (NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_LINK)
+#define VN_NOTE_DELETED (NOTE_DELETE | NOTE_REVOKE)
+#define VN_NOTE_ALL     (VN_NOTE_CHANGED | VN_NOTE_DELETED | NOTE_RENAME)
+
+typedef struct
+{
+  char *path;
+  int omask;
+  gboolean isdir;
+  HalFileMonitorNotifyFunc func;
+  gpointer udata;
+  GHashTable *dir_contents;
+} FileKqueueData;
+
+typedef struct
+{
+  char *path;
+  time_t atime;
+  gboolean owner;
+  HalFileMonitorNotifyFunc func;
+  gpointer udata;
+} FileAccessData;
+
+struct HalFileMonitorPrivate
+{
+  int kqueue_fd;
+  guint io_watch;
+  guint access_source;
+
+  gboolean initialized_kqueue;
+
+  GHashTable *fd_to_kdata;
+  GHashTable *fd_to_adata;
+};
+
+G_DEFINE_TYPE (HalFileMonitor, hal_file_monitor, G_TYPE_OBJECT)
+
+static gpointer monitor_object = NULL;
+
+static void hal_file_monitor_finalize (GObject *object);
+static GHashTable *get_dir_contents (const char *path);
+static GHashTable *diff_dir_contents (FileKqueueData *data, GSList **added, GSList **removed);
+static int hal_mask_to_kmask (int mask);
+static void monitor_release_kdata (HalFileMonitor *monitor, int fd, FileKqueueData *data);
+static void monitor_release_adata (HalFileMonitor *monitor, int fd, FileAccessData *data);
+static gboolean remove_kdata_foreach (gpointer fd, FileKqueueData *data, HalFileMonitor *monitor);
+static gboolean remove_adata_foreach (gpointer fd, FileAccessData *data, HalFileMonitor *monitor);
+static void hal_file_monitor_remove_kdata (HalFileMonitor *monitor, guint id);
+static void hal_file_monitor_remove_adata (HalFileMonitor *monitor, guint id);
+static void setup_monitor (HalFileMonitor *monitor);
+static void close_monitor (HalFileMonitor *monitor);
+static gboolean hal_file_access_monitor (gpointer data);
+/*static char *fflags_to_str (int fflags);*/
+static void emit_monitor_event (HalFileMonitor *monitor, HalFileMonitorEvent event, const char *path, HalFileMonitorNotifyFunc func, gpointer udata);
+static gboolean handle_kqueue_event (GIOChannel *source, GIOCondition condition, gpointer udata);
+
+GQuark
+hal_file_monitor_error_quark (void)
+{
+  static GQuark ret = 0;
+  if (ret == 0)
+    {
+      ret = g_quark_from_static_string ("hal_file_monitor_error");
+    }
+
+  return ret;
+}
+
+static int
+hal_mask_to_kmask (int mask)
+{
+  int kmask = 0;
+
+  if (mask & HAL_FILE_MONITOR_EVENT_CREATE)
+    {
+      kmask |= NOTE_WRITE | NOTE_LINK;
+    }
+
+  if (mask & HAL_FILE_MONITOR_EVENT_DELETE)
+    {
+      kmask |= NOTE_WRITE | NOTE_LINK | VN_NOTE_DELETED;
+    }
+
+  if (mask & HAL_FILE_MONITOR_EVENT_CHANGE)
+    {
+      kmask |= VN_NOTE_CHANGED;
+    }
+
+  return kmask;
+}
+
+guint
+hal_file_monitor_add_notify (HalFileMonitor *monitor,
+                             const char *path,
+                             int mask,
+                             HalFileMonitorNotifyFunc notify_func,
+                             gpointer data)
+{
+  struct kevent ev;
+  struct stat sb;
+  int fd;
+  int id = 0;
+
+  if (! monitor->priv->initialized_kqueue)
+    {
+      return id;
+    }
+
+  fd = open (path, O_RDONLY);
+  if (fd < 0)
+    {
+      return id;
+    }
+
+  if (fstat (fd, &sb) == -1)
+    {
+      close (fd);
+      return id;
+    }
+
+  if (mask & HAL_FILE_MONITOR_EVENT_ACCESS)
+    {
+      FileAccessData *adata;
+
+      adata = g_new0 (FileAccessData, 1);
+      adata->path = g_strdup (path);
+      adata->atime = sb.st_atime;
+      adata->func = notify_func;
+      adata->udata = data;
+      if (mask == HAL_FILE_MONITOR_EVENT_ACCESS)
+        {
+          /* We will close the file descriptor when we release the adata. */
+          adata->owner = TRUE;
+        }
+      g_hash_table_insert (monitor->priv->fd_to_adata,
+                           GINT_TO_POINTER (fd),
+                           adata);
+      id = fd;
+    }
+
+  if ((mask & HAL_FILE_MONITOR_EVENT_CREATE) ||
+      (mask & HAL_FILE_MONITOR_EVENT_DELETE) ||
+      (mask & HAL_FILE_MONITOR_EVENT_CHANGE))
+    {
+      FileKqueueData *kdata;
+      int kmask;
+      gboolean isdir;
+
+      kmask = hal_mask_to_kmask (mask);
+
+      isdir = (sb.st_mode & S_IFDIR) != 0;
+      if (! isdir && mask == HAL_FILE_MONITOR_EVENT_CREATE)
+        {
+          /* We can't monitor creation on a file. */
+          goto done;
+        }
+
+      kdata = g_new0 (FileKqueueData, 1);
+      kdata->path = g_strdup (path);
+      kdata->omask = mask;
+      kdata->isdir = isdir;
+      kdata->func = notify_func;
+      kdata->udata = data;
+      if (isdir)
+        {
+          kdata->dir_contents = get_dir_contents (path);
+        }
+
+      /*g_warning ("XXX: Adding event with mask %s", fflags_to_str (kmask));*/
+      EV_SET (&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
+              kmask, 0, monitor);
+      if (kevent (monitor->priv->kqueue_fd, &ev, 1, NULL, 0, NULL) < 0)
+        {
+          monitor_release_kdata (monitor, fd, kdata);
+          goto done;
+        }
+      g_hash_table_insert (monitor->priv->fd_to_kdata,
+                           GINT_TO_POINTER (fd),
+                           kdata);
+      id = fd;
+    }
+
+done:
+  return id;
+}
+
+static void
+hal_file_monitor_remove_kdata (HalFileMonitor *monitor,
+                               guint id)
+{
+  FileKqueueData *kdata;
+
+  kdata = (FileKqueueData *) g_hash_table_lookup (monitor->priv->fd_to_kdata, GINT_TO_POINTER (id));
+
+  if (kdata)
+    {
+      g_hash_table_remove (monitor->priv->fd_to_kdata, GINT_TO_POINTER (id));
+      monitor_release_kdata (monitor, id, kdata);
+    }
+}
+
+static void
+hal_file_monitor_remove_adata (HalFileMonitor *monitor,
+                               guint id)
+{
+  FileAccessData *adata;
+
+  adata = (FileAccessData *) g_hash_table_lookup (monitor->priv->fd_to_adata, GINT_TO_POINTER (id));
+
+  if (adata)
+    {
+      g_hash_table_remove (monitor->priv->fd_to_adata, GINT_TO_POINTER (id));
+      monitor_release_adata (monitor, id, adata);
+    }
+}
+
+void
+hal_file_monitor_remove_notify (HalFileMonitor *monitor,
+                                guint id)
+{
+  if (! monitor->priv->initialized_kqueue)
+    return;
+
+  hal_file_monitor_remove_kdata (monitor, id);
+  hal_file_monitor_remove_adata (monitor, id);
+
+}
+
+static void
+monitor_release_kdata (HalFileMonitor *monitor,
+                       int fd,
+                       FileKqueueData *data)
+{
+  g_free (data->path);
+  data->path = NULL;
+
+  if (data->dir_contents)
+    {
+      g_hash_table_remove_all (data->dir_contents);
+      g_hash_table_destroy (data->dir_contents);
+    }
+  data->dir_contents = NULL;
+
+  close (fd);
+
+  g_free (data);
+}
+
+static void
+monitor_release_adata (HalFileMonitor *monitor,
+                       int fd,
+                       FileAccessData *data)
+{
+  g_free (data->path);
+  data->path = NULL;
+
+  if (data->owner)
+    {
+      close (fd);
+    }
+
+  g_free (data);
+}
+
+static gboolean
+remove_kdata_foreach (gpointer fd,
+                      FileKqueueData *data,
+                      HalFileMonitor *monitor)
+{
+  monitor_release_kdata (monitor, GPOINTER_TO_INT (fd), data);
+  return TRUE;
+}
+
+static gboolean
+remove_adata_foreach (gpointer fd,
+                      FileAccessData *data,
+                      HalFileMonitor *monitor)
+{
+  monitor_release_adata (monitor, GPOINTER_TO_INT (fd), data);
+  return TRUE;
+}
+
+static void
+close_monitor (HalFileMonitor *monitor)
+{
+  if (! monitor->priv->initialized_kqueue)
+    {
+      return;
+    }
+
+  monitor->priv->initialized_kqueue = FALSE;
+
+  g_hash_table_foreach_remove (monitor->priv->fd_to_kdata,
+                               (GHRFunc) remove_kdata_foreach,
+                               monitor);
+
+  g_hash_table_foreach_remove (monitor->priv->fd_to_adata,
+                               (GHRFunc) remove_adata_foreach,
+                               monitor);
+
+  if (monitor->priv->io_watch)
+    {
+      g_source_remove (monitor->priv->io_watch);
+    }
+  monitor->priv->io_watch = 0;
+
+  if (monitor->priv->access_source)
+    {
+      g_source_remove (monitor->priv->access_source);
+    }
+  monitor->priv->access_source = 0;
+
+  if (monitor->priv->kqueue_fd > -1)
+    {
+      close (monitor->priv->kqueue_fd);
+    }
+  monitor->priv->kqueue_fd = -1;
+}
+
+static gboolean
+hal_file_access_monitor (gpointer data)
+{
+  HalFileMonitor *monitor;
+  GList *keys, *l;
+
+  g_return_val_if_fail (HAL_IS_FILE_MONITOR (data), FALSE);
+
+  monitor = HAL_FILE_MONITOR (data);
+
+  g_return_val_if_fail (monitor->priv != NULL, FALSE);
+
+  keys = g_hash_table_get_keys (monitor->priv->fd_to_adata);
+
+  for (l = keys; l != NULL; l = l->next)
+    {
+      FileAccessData *adata;
+      struct stat sb;
+      int fd;
+
+      fd = GPOINTER_TO_INT (l->data);
+      adata = g_hash_table_lookup (monitor->priv->fd_to_adata,
+                                   l->data);
+
+      if (! adata)
+        {
+          continue;
+        }
+
+      if (fstat (fd, &sb) == -1)
+        {
+          g_warning ("Failed to stat %s: %s", adata->path, g_strerror (errno));
+          hal_file_monitor_remove_adata (monitor, fd);
+          continue;
+        }
+
+      if (sb.st_atime != adata->atime)
+        {
+          adata->atime = sb.st_atime;
+          emit_monitor_event (monitor, HAL_FILE_MONITOR_EVENT_ACCESS, adata->path, adata->func, adata->udata);
+        }
+    }
+
+  return TRUE;
+}
+
+static void
+setup_monitor (HalFileMonitor *monitor)
+{
+  GIOChannel *io_channel;
+  int fd;
+
+  if (monitor->priv->initialized_kqueue)
+    {
+      return;
+    }
+
+  if ((fd = kqueue ()) < 0)
+    {
+      g_warning ("Failed to initialize kqueue: %s",
+                 g_strerror (errno));
+      return;
+    }
+
+  monitor->priv->kqueue_fd = fd;
+
+  monitor->priv->fd_to_kdata = g_hash_table_new (g_direct_hash,
+                               g_direct_equal);
+  monitor->priv->fd_to_adata = g_hash_table_new (g_direct_hash,
+                               g_direct_equal);
+
+  io_channel = g_io_channel_unix_new (fd);
+  monitor->priv->io_watch = g_io_add_watch (io_channel,
+                            G_IO_IN|G_IO_PRI,
+                            (GIOFunc) handle_kqueue_event,
+                            monitor);
+  g_io_channel_unref (io_channel);
+
+  monitor->priv->access_source = g_timeout_add (1000, (GSourceFunc) hal_file_access_monitor, monitor);
+
+  monitor->priv->initialized_kqueue = TRUE;
+}
+
+static void
+hal_file_monitor_init (HalFileMonitor *monitor)
+{
+  monitor->priv = HAL_FILE_MONITOR_GET_PRIVATE (monitor);
+
+  setup_monitor (monitor);
+}
+
+static void
+hal_file_monitor_class_init (HalFileMonitorClass *klass)
+{
+  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = hal_file_monitor_finalize;
+
+  g_type_class_add_private (klass, sizeof (HalFileMonitorPrivate));
+}
+
+static void
+hal_file_monitor_finalize (GObject *object)
+{
+  HalFileMonitor *monitor;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (HAL_IS_FILE_MONITOR (object));
+
+  monitor = HAL_FILE_MONITOR (object);
+
+  g_return_if_fail (monitor->priv != NULL);
+
+  close_monitor (monitor);
+
+  g_hash_table_destroy (monitor->priv->fd_to_kdata);
+  g_hash_table_destroy (monitor->priv->fd_to_adata);
+
+  G_OBJECT_CLASS (hal_file_monitor_parent_class)->finalize (object);
+}
+
+HalFileMonitor *
+hal_file_monitor_new (void)
+{
+  if (monitor_object != NULL)
+    {
+      g_object_ref (monitor_object);
+    }
+  else
+    {
+      monitor_object = g_object_new (HAL_TYPE_FILE_MONITOR, NULL);
+
+      g_object_add_weak_pointer (monitor_object,
+                                 (gpointer *) &monitor_object);
+    }
+
+  return HAL_FILE_MONITOR (monitor_object);
+}
+
+/*
+static char *
+fflags_to_str (int fflags)
+{
+
+  GString *out;
+
+  out = g_string_new (NULL);
+
+  if (fflags & NOTE_WRITE)
+    {
+      g_string_append (out, " WRITE ");
+    }
+  if (fflags & NOTE_EXTEND)
+    {
+      g_string_append (out, " EXTEND ");
+    }
+  if (fflags & NOTE_ATTRIB)
+    {
+      g_string_append (out, " ATTRIB ");
+    }
+  if (fflags & NOTE_LINK)
+    {
+      g_string_append (out, " LINK ");
+    }
+  if (fflags & NOTE_DELETE)
+    {
+      g_string_append (out, " DELETE ");
+    }
+  if (fflags & NOTE_REVOKE)
+    {
+      g_string_append (out, " REVOKE ");
+    }
+  if (fflags & NOTE_RENAME)
+    {
+      g_string_append (out, " RENAME ");
+    }
+
+  return g_string_free (out, FALSE);
+}
+*/
+
+static void
+emit_monitor_event (HalFileMonitor *monitor,
+                    HalFileMonitorEvent event,
+                    const char *path,
+                    HalFileMonitorNotifyFunc func,
+                    gpointer udata)
+{
+  if (func)
+    {
+      func (monitor, event, path, udata);
+    }
+}
+
+static gboolean
+handle_kqueue_event (GIOChannel *source,
+                     GIOCondition   condition,
+                     gpointer udata)
+{
+  struct kevent ev;
+  struct timespec timeout = { 0, 0 };
+  int nevents;
+  HalFileMonitor *monitor;
+
+  g_return_val_if_fail (HAL_IS_FILE_MONITOR (udata), FALSE);
+
+  monitor = HAL_FILE_MONITOR (udata);
+
+  g_return_val_if_fail (monitor->priv != NULL, FALSE);
+
+  g_return_val_if_fail (monitor->priv->kqueue_fd > -1, FALSE);
+
+  nevents = kevent (monitor->priv->kqueue_fd, NULL, 0, &ev, 1, &timeout);
+  if (nevents == 1)
+    {
+      int fd;
+      FileKqueueData *data;
+
+      fd = ev.ident;
+      data = g_hash_table_lookup (monitor->priv->fd_to_kdata,
+                                  GINT_TO_POINTER (fd));
+      if (! data)
+        {
+          /* The monitor may have been deleted. */
+          return TRUE;
+        }
+
+      if ((data->omask & HAL_FILE_MONITOR_EVENT_DELETE) &&
+          (ev.fflags & VN_NOTE_DELETED))
+        {
+          emit_monitor_event (monitor, HAL_FILE_MONITOR_EVENT_DELETE, data->path, data->func, data->udata);
+          hal_file_monitor_remove_kdata (monitor, fd);
+          return TRUE;
+        }
+
+      if ((data->omask & HAL_FILE_MONITOR_EVENT_CREATE) ||
+          (data->omask & HAL_FILE_MONITOR_EVENT_DELETE))
+        {
+          if (data->isdir)
+            {
+              GSList *added = NULL;
+              GSList *removed = NULL;
+              GSList *l;
+              GHashTable *table;
+              gboolean found_change = FALSE;
+
+              table = diff_dir_contents (data, &added, &removed);
+              if (data->omask & HAL_FILE_MONITOR_EVENT_CREATE)
+                {
+                  for (l = added; l != NULL; l = l->next)
+                    {
+                      char *path;
+
+                      path = g_build_filename (data->path, l->data, NULL);
+                      emit_monitor_event (monitor, HAL_FILE_MONITOR_EVENT_CREATE, path, data->func, data->udata);
+                      g_free (path);
+                    }
+                }
+
+              if (data->omask & HAL_FILE_MONITOR_EVENT_DELETE)
+                {
+                  for (l = removed; l != NULL; l = l->next)
+                    {
+                      char *path;
+
+                      path = g_build_filename (data->path, l->data, NULL);
+                      emit_monitor_event (monitor, HAL_FILE_MONITOR_EVENT_DELETE, path, data->func, data->udata);
+                      g_free (path);
+                    }
+                }
+
+              if (added || removed)
+                {
+                  g_hash_table_remove_all (data->dir_contents);
+                  g_hash_table_destroy (data->dir_contents);
+                  data->dir_contents = table;
+                  found_change = TRUE;
+                }
+              else if (table)
+                {
+                  g_hash_table_remove_all (table);
+                  g_hash_table_destroy (table);
+                }
+              else
+                {
+                  hal_file_monitor_remove_kdata (monitor, fd);
+                }
+
+              if (added)
+                {
+                  g_slist_foreach (added, (GFunc) g_free, NULL);
+                  g_slist_free (added);
+                }
+              if (removed)
+                {
+                  g_slist_foreach (removed, (GFunc) g_free, NULL);
+                  g_slist_free (removed);
+                }
+
+              if (found_change)
+                {
+                  return TRUE;
+                }
+            }
+        }
+
+      if (data->omask & HAL_FILE_MONITOR_EVENT_CHANGE)
+        {
+          emit_monitor_event (monitor, HAL_FILE_MONITOR_EVENT_CHANGE, data->path, data->func, data->udata);
+        }
+    }
+  else
+    {
+      g_warning ("Failed to read from kqueue: %s", g_strerror (errno));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static GHashTable *
+diff_dir_contents (FileKqueueData *data,
+                   GSList **added,
+                   GSList **removed)
+{
+  GDir *dir;
+  GError *err = NULL;
+  GHashTable *table = NULL;
+
+  dir = g_dir_open (data->path, 0, &err);
+  if (dir)
+    {
+      const char *fname;
+
+      table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+      while ((fname = g_dir_read_name (dir)))
+        {
+          if (added)
+            {
+              if (! g_hash_table_lookup (data->dir_contents, fname))
+                {
+                  *added = g_slist_prepend (*added, g_strdup (fname));
+                }
+            }
+
+          g_hash_table_insert (table, g_strdup (fname), GINT_TO_POINTER (TRUE));
+        }
+
+      g_dir_close (dir);
+
+      if (removed)
+        {
+          GList *keys;
+          GList *l;
+
+          keys = g_hash_table_get_keys (data->dir_contents);
+
+          for (l = keys; l != NULL; l = l->next)
+            {
+              if (! g_hash_table_lookup (table, l->data))
+                {
+                  *removed = g_slist_prepend (*removed, g_strdup (l->data));
+                }
+            }
+        }
+
+    }
+  else
+    {
+      g_warning ("Failed to open directory: %s", err->message);
+      g_error_free (err);
+    }
+
+  return table;
+}
+
+static GHashTable *
+get_dir_contents (const char *path)
+{
+  GDir *dir;
+  GError *err = NULL;
+  GHashTable *table = NULL;
+
+  dir = g_dir_open (path, 0, &err);
+  if (dir)
+    {
+      const char *fname;
+
+      table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+      while ((fname = g_dir_read_name (dir)))
+        {
+          g_hash_table_insert (table, g_strdup (fname), GINT_TO_POINTER (TRUE));
+        }
+      g_dir_close (dir);
+    }
+  else
+    {
+      g_warning ("Failed to open directory %s: %s\n", path, err->message);
+      g_error_free (err);
+    }
+
+  return table;
+}
+
+/*
+static void
+print_event (HalFileMonitor *monitor,
+             HalFileMonitorEvent event,
+             const char *path,
+             gpointer udata)
+{
+  GString *ename;
+
+  ename = g_string_new (NULL);
+
+  if (event & HAL_FILE_MONITOR_EVENT_ACCESS)
+    {
+      g_string_append (ename, "ACCESS ");
+    }
+  if (event & HAL_FILE_MONITOR_EVENT_CREATE)
+    {
+      g_string_append (ename, "CREATE ");
+    }
+  if (event & HAL_FILE_MONITOR_EVENT_DELETE)
+    {
+      g_string_append (ename, "DELETE ");
+    }
+  if (event & HAL_FILE_MONITOR_EVENT_CHANGE)
+    {
+      g_string_append (ename, "CHANGE ");
+    }
+
+  printf("Received event for %s: %s\n", path, g_string_free (ename, FALSE));
+}
+
+int
+main(void)
+{
+  const char *path = "/tmp/kqueue.d";
+  guint watch;
+  GMainLoop *loop;
+  HalFileMonitor *monitor;
+
+  g_type_init ();
+
+  monitor = hal_file_monitor_new ();
+  hal_file_monitor_add_notify (monitor, path, HAL_FILE_MONITOR_EVENT_CREATE|HAL_FILE_MONITOR_EVENT_DELETE|HAL_FILE_MONITOR_EVENT_CHANGE,print_event, NULL);
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  g_main_loop_run (loop);
+
+  return 0;
+}
+*/
diff --git a/hal/files/hald-netbsd/hotplug.c b/hal/files/hald-netbsd/hotplug.c
new file mode 100644
index 0000000000..ce96f84f5e
--- /dev/null
+++ b/hal/files/hald-netbsd/hotplug.c
@@ -0,0 +1,204 @@
+/***************************************************************************
+ *
+ * hotplug.c : HAL-internal hotplug events
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#pragma ident	"@(#)hotplug.c	1.2	06/10/13 SMI"
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../device_info.h"
+
+#include "osspec_netbsd.h"
+#include "hotplug.h"
+#include "devinfo.h"
+
+/** Queue of ordered hotplug events */
+GQueue *hotplug_event_queue;
+
+/** List of HotplugEvent objects we are currently processing */
+GSList *hotplug_events_in_progress = NULL;
+
+static void hotplug_event_begin (HotplugEvent *hotplug_event);
+
+void 
+hotplug_event_end (void *end_token)
+{
+	HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
+
+	hotplug_events_in_progress = g_slist_remove (hotplug_events_in_progress, hotplug_event);
+	g_free (hotplug_event);
+	hotplug_event_process_queue ();
+}
+
+static void
+hotplug_event_begin_devfs_add (HotplugEvent *hotplug_event, HalDevice *d)
+{
+	HalDevice *parent;
+	const gchar *parent_udi;
+	void (*begin_add_func) (HalDevice *, HalDevice *, DevinfoDevHandler *, void *);
+
+	if (d != NULL) {
+		/* XXX */
+		HAL_ERROR (("devpath %s already present in store, ignore event", hotplug_event->un.devfs.devfs_path));
+		hotplug_event_end ((void *) hotplug_event);
+		return;
+	}
+
+	/* find parent */
+	parent_udi = hal_device_property_get_string (hotplug_event->d, "info.parent");
+	if (parent_udi == NULL || strlen(parent_udi) == 0) {
+		parent = NULL;
+		HAL_INFO (("no info.parent parameter found"));
+	} else {
+		parent = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", parent_udi);
+		if (parent == NULL)
+			HAL_INFO (("no info.udi=%s parameter found", parent_udi));
+	}
+
+	if (parent == NULL) {
+		gchar pdevnode[512];
+		HAL_INFO (("couldn't look up %s parent by udi, trying netbsd.device", hotplug_event->un.devfs.devfs_path));
+		if (drvctl_find_parent (hotplug_event->un.devfs.devfs_path, pdevnode) == TRUE)
+			parent = hal_device_store_match_key_value_string (hald_get_gdl (), "netbsd.device", pdevnode);
+	}
+
+	/* only root node is allowed to be orphan */
+	if (parent == NULL) {
+		if (strcmp(hotplug_event->un.devfs.devfs_path, "mainbus0") != 0) {
+			HAL_ERROR (("Parent is NULL devfs_path=%s parent_udi=%s", hotplug_event->un.devfs.devfs_path, parent_udi ? parent_udi : "<null>"));
+			hotplug_event_end ((void *) hotplug_event);
+			return;
+		}
+	}
+
+	/* children of ignored parent should be ignored */
+	if (hal_device_property_get_bool (parent, "info.ignore")) {
+		HAL_INFO (("parent ignored %s", parent_udi));
+			hotplug_event_end ((void *) hotplug_event);
+			return;
+	}
+
+	/* custom or generic add function */
+	begin_add_func = hotplug_event->un.devfs.handler->hotplug_begin_add;
+	if (begin_add_func == NULL) {
+		begin_add_func = hotplug_event_begin_add_devinfo;
+	}
+	begin_add_func (hotplug_event->d, 
+			 parent,
+			 hotplug_event->un.devfs.handler, 
+			 (void *) hotplug_event);
+}
+
+static void
+hotplug_event_begin_devfs_remove (HotplugEvent *hotplug_event, HalDevice *d)
+{
+	if (d == NULL) {
+		HAL_ERROR (("devpath %s not present in store, ignore event", hotplug_event->un.devfs.devfs_path));
+		hotplug_event_end ((void *) hotplug_event);
+		return;
+	}
+	HAL_INFO (("hotplug_event_begin_devfs_remove %s", hal_device_get_udi (d)));
+
+	hotplug_event_begin_remove_devinfo(d, 
+			 hotplug_event->un.devfs.devfs_path, 
+			 (void *) hotplug_event);
+}
+
+static void
+hotplug_event_begin_devfs (HotplugEvent *hotplug_event)
+{
+	HalDevice *d;
+
+	HAL_INFO (("hotplug_event_begin_devfs: %s", hotplug_event->un.devfs.devfs_path));
+	d = hal_device_store_match_key_value_string (hald_get_gdl (),
+						"netbsd.device",
+						hotplug_event->un.devfs.devfs_path);
+
+	if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
+		hotplug_event_begin_devfs_add (hotplug_event, d);
+	} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
+		hotplug_event_begin_devfs_remove (hotplug_event, d);
+	} else {
+		hotplug_event_end ((void *) hotplug_event);
+	}
+}
+
+static void
+hotplug_event_begin (HotplugEvent *hotplug_event)
+{
+	switch (hotplug_event->type) {
+
+	case HOTPLUG_EVENT_DEVFS:
+		hotplug_event_begin_devfs (hotplug_event);
+		break;
+
+	default:
+		HAL_ERROR (("Unknown hotplug event type %d", hotplug_event->type));
+		hotplug_event_end ((void *) hotplug_event);
+		break;
+	}
+}
+
+void 
+hotplug_event_enqueue (HotplugEvent *hotplug_event, int front)
+{
+	if (hotplug_event_queue == NULL)
+		hotplug_event_queue = g_queue_new ();
+
+	if (front) {
+		g_queue_push_head (hotplug_event_queue, hotplug_event);
+	} else {
+		g_queue_push_tail (hotplug_event_queue, hotplug_event);
+	}
+}
+
+void 
+hotplug_event_process_queue (void)
+{
+	HotplugEvent *hotplug_event;
+
+	if (hotplug_events_in_progress == NULL && 
+	    (hotplug_event_queue == NULL || g_queue_is_empty (hotplug_event_queue))) {
+		hotplug_queue_now_empty ();
+		goto out;
+	}
+
+	/* do not process events if some other event is in progress */
+	if (hotplug_events_in_progress != NULL && g_slist_length (hotplug_events_in_progress) > 0)
+		goto out;
+
+	hotplug_event = g_queue_pop_head (hotplug_event_queue);
+	if (hotplug_event == NULL)
+		goto out;
+
+	hotplug_events_in_progress = g_slist_append (hotplug_events_in_progress, hotplug_event);
+	hotplug_event_begin (hotplug_event);
+
+out:
+	;	
+}
diff --git a/hal/files/hald-netbsd/hotplug.h b/hal/files/hald-netbsd/hotplug.h
new file mode 100644
index 0000000000..fc9f92ec1c
--- /dev/null
+++ b/hal/files/hald-netbsd/hotplug.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ *
+ * hotplug.h : definitions for HAL-internal hotplug events
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef HOTPLUG_H
+#define HOTPLUG_H
+
+#include <glib.h>
+
+#include "../device.h"
+#include "../util.h"
+
+#include "devinfo.h"
+
+typedef enum {
+	HOTPLUG_ACTION_ADD,
+	HOTPLUG_ACTION_REMOVE,
+} HotplugActionType;
+
+typedef enum {
+	HOTPLUG_EVENT_DEVFS       = 0,
+} HotplugEventType;
+
+/** Data structure representing a hotplug event; also used for
+ *  coldplugging.
+ */
+typedef struct
+{
+	HotplugActionType action;               /**< Whether the event is add or remove */
+	HotplugEventType type;                  /**< Type of hotplug event */
+
+	HalDevice *d;
+
+	union {
+		struct {
+			char devfs_path[HAL_PATH_MAX];
+			DevinfoDevHandler *handler;
+		} devfs;
+	} un;
+
+} HotplugEvent;
+
+void hotplug_event_enqueue (HotplugEvent *event, int front);
+
+void hotplug_event_process_queue (void);
+
+void hotplug_event_end (void *end_token);
+
+void hotplug_queue_now_empty (void);
+
+#endif /* HOTPLUG_H */
diff --git a/hal/files/hald-netbsd/osspec.c b/hal/files/hald-netbsd/osspec.c
new file mode 100644
index 0000000000..44a035dd81
--- /dev/null
+++ b/hal/files/hald-netbsd/osspec.c
@@ -0,0 +1,183 @@
+/***************************************************************************
+ *
+ * osspec.c : NetBSD HAL backend entry points
+ *
+ * Copyright 2008 Jared D. McNeill <jmcneill%NetBSD.org@localhost>
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/statvfs.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "../ids.h"
+#include "osspec_netbsd.h"
+#include "hotplug.h"
+#include "drvctl.h"
+#include "envsys.h"
+#include "devinfo.h"
+#include "devinfo_storage.h"
+
+static void mntinfo_event_init ();
+static gboolean mntinfo_timeout (gpointer user_data);
+
+HalFileMonitor *
+osspec_get_file_monitor (void)
+{
+#warning Please implement
+        return NULL;
+}
+
+void
+osspec_init (void)
+{
+	ids_init ();
+	mntinfo_event_init ();
+	envsys_init ();
+}
+
+void
+osspec_privileged_init (void)
+{
+	drvctl_init ();
+}
+
+void
+hotplug_queue_now_empty (void)
+{
+        if (hald_is_initialising) {
+                osspec_probe_done ();
+	}
+}
+
+void 
+osspec_probe (void)
+{
+	/* add entire device tree */
+	devinfo_add (NULL, "mainbus0");
+
+	/* start processing events */
+	hotplug_event_process_queue ();
+}
+
+gboolean
+osspec_device_rescan (HalDevice *d)
+{
+	   return (devinfo_device_rescan (d));
+}
+
+gboolean
+osspec_device_reprobe (HalDevice *d)
+{
+	   return FALSE;
+}
+
+DBusHandlerResult
+osspec_filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/** 
+ *  hal_util_find_closest_ancestor:
+ *  @devfs_path:           Path into devfs, e.g. /pci@0,0/pci1025,57@10,2/storage@1
+ *
+ *  Returns:               Parent Hal Device Object or #NULL if there is none
+ *
+ *  Find the closest ancestor by looking at devfs paths
+ */
+HalDevice *
+hal_util_find_closest_ancestor (const gchar *devfs_path, gchar **ancestor_devfs_path, gchar **hotplug_devfs_path)
+{
+        gchar buf[512];
+	gchar c;
+        HalDevice *parent;
+
+        parent = NULL;
+
+	if (drvctl_find_parent (devfs_path, buf) == FALSE)
+		return NULL;
+
+	HAL_INFO (("hal_util_find_closest_ancestor: devnode=%s parent=%s\n", devfs_path, buf));
+
+        parent = hal_device_store_match_key_value_string (hald_get_gdl (),
+                                                          "netbsd.device",
+                                                          buf);
+        if (parent != NULL) {
+		if (ancestor_devfs_path != NULL) {
+			*ancestor_devfs_path = g_strdup (buf);
+		}
+		if (hotplug_devfs_path != NULL) {
+			*hotplug_devfs_path = g_strdup (buf);
+		}
+	}
+
+        return parent;
+}
+
+char *
+dsk_to_rdsk(char *dsk)
+{
+        int     len, pos;
+        char    *p;
+        char    *rdsk;
+
+	if ((len = strlen (dsk)) < sizeof ("/dev/AANA") - 1) {
+		return (strdup(""));
+	}
+	p = strstr (dsk, "/dev/");
+	if (p == NULL) {
+		return (strdup(""));
+	}
+
+	pos = (uintptr_t)p - (uintptr_t)dsk;
+	if ((rdsk = (char *)calloc (len + 2, 1)) != NULL) {
+        	strncpy (rdsk, dsk, pos + 1);
+        	rdsk[pos + 1] = 'r';
+        	strcpy (rdsk + pos + 2, dsk + pos + 1);
+	}
+
+        return (rdsk);
+}
+
+/*
+ * Setup to watch mntinfo changes
+ */
+static void
+mntinfo_event_init ()
+{
+	g_timeout_add (1000, mntinfo_timeout, NULL);
+}
+
+static gboolean
+mntinfo_timeout (gpointer user_data)
+{
+	if (!hald_is_initialising)
+		vfsstat_event (NULL);
+
+	return TRUE;
+}
+
+void
+osspec_refresh_mount_state_for_block_device (HalDevice *d)
+{
+	vfsstat_event (d);
+}
diff --git a/hal/files/hald-netbsd/osspec_netbsd.h b/hal/files/hald-netbsd/osspec_netbsd.h
new file mode 100644
index 0000000000..13ba327711
--- /dev/null
+++ b/hal/files/hald-netbsd/osspec_netbsd.h
@@ -0,0 +1,21 @@
+/***************************************************************************
+ *
+ * osspec_netbsd.h : definitions for NetBSD HAL backend
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef OSSPEC_NETBSD_H
+#define OSSPEC_NETBSD_H
+
+#include <glib.h>
+
+void hotplug_queue_now_empty (void);
+HalDevice *hal_util_find_closest_ancestor (const gchar *devfs_path, gchar **ancestor_devfs_path, gchar **hotplug_devfs_path);
+char *dsk_to_rdsk(char *);
+
+#endif /* OSSPEC_NETBSD_H */
diff --git a/hal/files/hald-netbsd/probing/Makefile.am b/hal/files/hald-netbsd/probing/Makefile.am
new file mode 100644
index 0000000000..c9a58549ee
--- /dev/null
+++ b/hal/files/hald-netbsd/probing/Makefile.am
@@ -0,0 +1,20 @@
+
+AM_CPPFLAGS = \
+	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
+	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
+	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
+	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
+	-I$(top_srcdir) -I$(top_srcdir)/hald -I$(top_srcdir)/libhal -I$(top_srcdir)/libhal-storage \
+	@GLIB_CFLAGS@ @DBUS_CFLAGS@
+
+if HALD_COMPILE_NETBSD
+libexec_PROGRAMS = hald-probe-storage hald-probe-volume
+endif
+
+hald_probe_storage_SOURCES = probe-storage.c cdutils.c fsutils.c ../../logger.c
+hald_probe_storage_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@ -lprop
+
+hald_probe_volume_SOURCES = probe-volume.c cdutils.c fsutils.c ../../logger.c 
+hald_probe_volume_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@ -lprop
+
diff --git a/hal/files/hald-netbsd/probing/cdutils.c b/hal/files/hald-netbsd/probing/cdutils.c
new file mode 100644
index 0000000000..0d524eb92e
--- /dev/null
+++ b/hal/files/hald-netbsd/probing/cdutils.c
@@ -0,0 +1,379 @@
+/***************************************************************************
+ *
+ * cdutils.h : CD/DVD utilities
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/scsiio.h>
+#include <sys/disklabel.h>
+#include <dev/scsipi/scsi_spc.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsipi_cd.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/dkio.h>
+#include <libintl.h>
+
+#include <logger.h>
+
+#include "cdutils.h"
+
+#define	RQLEN	32
+#define SENSE_KEY(rqbuf)        (rqbuf[2])      /* scsi error category */
+#define ASC(rqbuf)              (rqbuf[12])     /* additional sense code */
+#define ASCQ(rqbuf)             (rqbuf[13])     /* ASC qualifier */
+
+#define	GET16(a) (((a)[0] << 8) | (a)[1])
+#define	GET32(a) (((a)[0] << 24) | ((a)[1] << 16) | ((a)[2] << 8) | (a)[3])
+
+bool
+scsi_command (int fd, void *cmd, size_t cmdlen, void *data, size_t datalen,
+    int timeout, int flags)
+{
+	scsireq_t req;
+
+	memset(&req, 0, sizeof(req));
+	memcpy(req.cmd, cmd, cmdlen);
+	req.cmdlen = cmdlen;
+	req.databuf = data;
+	req.datalen = datalen;
+	req.timeout = timeout;
+	req.flags = flags;
+	req.senselen = SENSEBUFLEN;
+
+	if (ioctl(fd, SCIOCCOMMAND, &req) == -1)
+		return false;
+	if (req.retsts == SCCMD_OK)
+		return true;
+	return false;
+}
+
+int
+mode_sense(int fd, u_char pc, int dbd, int page_len, u_char *buffer)
+{
+	struct scsi_mode_sense_10 sms10;
+
+        memset(&sms10, 0, sizeof(sms10));
+	sms10.opcode = SCSI_MODE_SENSE_10; 
+	if (dbd)
+		sms10.byte2 = SMS_DBD; /* no block descriptors */
+	sms10.page = pc;
+	sms10.length[0] = (page_len >> 8) & 0xff;
+	sms10.length[1] = page_len & 0xff;
+
+        return (scsi_command(fd, &sms10, sizeof(sms10), buffer, page_len, 10000, SCCMD_READ) == true);
+}
+
+/*
+ * will get the mode page only i.e. will strip off the header.
+ */
+int
+get_mode_page(int fd, int page_no, int pc, int buf_len, u_char *buffer, int *plen)
+{
+	int ret;
+	u_char byte2;
+	u_char buf[256];
+	u_int header_len, page_len, copy_cnt;
+
+	byte2 = (u_char)(((pc << 6) & 0xC0) | (page_no & 0x3f));
+
+	/* Ask 254 bytes only to make our IDE driver happy */
+	if ((ret = mode_sense(fd, byte2, 1, 254, buf)) == 0) {
+		return (0);
+	}
+
+	header_len = 8 + GET16(&buf[6]);
+	page_len = buf[header_len + 1] + 2;
+
+	copy_cnt = ((int)page_len > buf_len) ? (u_int)buf_len : page_len;
+	(void) memcpy(buffer, &buf[header_len], copy_cnt);
+
+	if (plen) {
+		*plen = page_len;
+	}
+
+	return (1);
+}
+
+/* Get information about the Logical Unit's capabilities */
+int
+get_configuration(int fd, uint16_t feature, int bufsize, u_char *buf)
+{
+	struct scsipi_get_configuration conf;
+
+	memset(&conf, 0, sizeof(conf));
+	conf.opcode = GET_CONFIGURATION;
+	conf.request_type = 0x2;
+	conf.start_at_feature[0] = (feature >> 8) & 0xff;
+	conf.start_at_feature[1] = feature & 0xff;
+	conf.data_len[0] = (bufsize >> 8) & 0xff;
+	conf.data_len[1] = bufsize & 0xff;
+
+        return (scsi_command(fd, &conf, sizeof(conf), buf, bufsize, 10000, SCCMD_READ) == true);
+}
+
+bool
+get_current_profile(int fd, int *profile)
+{
+	u_char smallbuf[4];
+	size_t buflen;
+	u_char *bufp;
+	int ret = false;
+
+	/* first determine amount of memory needed to hold all profiles */
+	if (get_configuration(fd, 0, 4, &smallbuf[0])) {
+		buflen = GET32(smallbuf) + 4;
+		bufp = (u_char *)malloc(buflen);
+
+	 	/* now get all profiles */
+		if (get_configuration(fd, 0, buflen, bufp)) {
+			*profile = GET16(&bufp[6]);
+			ret = true;
+		}
+		free(bufp);
+	}
+
+	return (ret);
+}
+
+void
+walk_profiles(int fd, int (*f)(void *, int, bool), void *arg)
+{
+	size_t i;
+	uint16_t profile, current_profile;
+	u_char smallbuf[4];
+	size_t buflen;
+	u_char *bufp;
+	int ret;
+
+	/* first determine amount of memory needed to hold all profiles */
+	if (get_configuration(fd, 0, 4, &smallbuf[0])) {
+		buflen = GET32(smallbuf) + 4;
+		bufp = (u_char *)malloc(buflen);
+
+	 	/* now get all profiles */
+		if (get_configuration(fd, 0, buflen, bufp)) {
+			current_profile = GET16(&bufp[6]);
+			for (i = 8 + 4;  i < buflen; i += 4) {
+				profile = GET16(&bufp[i]);
+				ret = f(arg, profile, (profile == current_profile));
+				if (ret == CDUTIL_WALK_STOP) {
+					break;
+				}
+			}
+		}
+
+		free(bufp);
+	}
+}
+
+/* retrieve speed list from the Write Speed Performance Descriptor Blocks
+ */
+static void
+get_write_speeds(u_char *page, int n, intlist_t **speeds, int *n_speeds, intlist_t **speeds_mem)
+{
+	u_char	*p = page + 2;
+	int	i;
+	intlist_t **nextp;
+	intlist_t *current;
+	bool skip;
+
+	*n_speeds = 0;
+	*speeds = NULL;
+	*speeds_mem = (intlist_t *)calloc(n, sizeof (intlist_t));
+	if (*speeds_mem == NULL) {
+		return;
+	}
+
+	for (i = 0; i < n; i++, p += 4) {
+		current = &(*speeds_mem)[i];
+		current->val = GET16(p);
+
+		/* keep the list sorted */
+		skip = false;
+		for (nextp = speeds; *nextp != NULL; nextp = &((*nextp)->next)) {
+			if (current->val == (*nextp)->val) {
+				skip = true; /* skip duplicates */
+				break;
+			} else if (current->val > (*nextp)->val) {
+				break;
+			}
+		}
+		if (!skip) {
+			current->next = *nextp;
+			*nextp = current;
+			*n_speeds++;
+		}
+	}
+}
+
+void
+get_read_write_speeds(int fd, int *read_speed, int *write_speed,
+    intlist_t **speeds, int *n_speeds, intlist_t **speeds_mem)
+{
+	int page_len;
+	u_char	p[254];
+	int n; /* number of write speed performance descriptor blocks */
+
+	*read_speed = *write_speed = 0;
+	*speeds = *speeds_mem = NULL;
+
+	if (!get_mode_page(fd, 0x2A, 0, sizeof (p), p, &page_len)) {
+		return;
+	}
+
+	if (page_len > 8) {
+		*read_speed = GET16(&p[8]);
+	}
+	if (page_len > 18) {
+		*write_speed = GET16(&p[18]);
+	}
+	if (page_len < 28) {
+		printf("MMC-2\n");
+		return;
+	} else {
+		printf("MMC-3\n");
+	}
+
+	*write_speed = GET16(&p[28]);
+
+	if (page_len < 30) {
+		return;
+	}
+
+	/* retrieve speed list */
+	n = GET16(&p[30]);
+	n = min(n, (sizeof (p) - 32) / 4);
+
+	get_write_speeds(&p[32], n, speeds, n_speeds, speeds_mem);
+
+	if (*speeds != NULL) {
+		*write_speed = max(*write_speed, (*speeds)[0].val);
+	}
+}
+
+bool
+get_disc_info(int fd, disc_info_t *di)
+{
+	struct scsipi_read_discinfo discinfo;
+	uint8_t	buf[32];
+	int bufsize = sizeof (buf);
+
+	bzero(buf, bufsize);
+	memset(&discinfo, 0, sizeof(discinfo));
+	discinfo.opcode = READ_DISCINFO;
+	discinfo.data_len[0] = (bufsize >> 8) & 0xff;
+	discinfo.data_len[1] = bufsize & 0xff;
+
+        if (scsi_command(fd, &discinfo, sizeof(discinfo), buf, bufsize, 10000, SCCMD_READ) == false)
+		return false;
+
+	di->disc_status = buf[2] & 0x03;
+	di->erasable = buf[2] & 0x10;
+	if ((buf[21] != 0) && (buf[21] != 0xff)) {
+		di->capacity = ((buf[21] * 60) + buf[22]) * 75;
+	} else {
+		di->capacity = 0;
+        }
+
+	return true;
+}
+
+/*
+ * returns current/maximum format capacity in bytes
+ */
+bool
+read_format_capacity(int fd, uint64_t *capacity)
+{
+	char cdb[12];
+	uint8_t	buf[32];
+	int bufsize = sizeof (buf);
+	uint32_t num_blocks;
+	uint32_t block_len;
+
+	memset(buf, 0, bufsize);
+	memset(cdb, 0, sizeof(cdb));
+	cdb[0] = 0x23;	/* READ FORMAT CAPACITIES */
+	cdb[7] = (bufsize >> 8) & 0xff;	/* allocation length */
+	cdb[8] = bufsize & 0xff;
+
+        if (scsi_command(fd, &cdb, sizeof(cdb), buf, bufsize, 10000, SCCMD_READ) == false)
+		return false;
+
+	num_blocks = (uint32_t)(buf[4] << 24) + (buf[5] << 16) + (buf[6] << 8) + buf[7];
+	block_len = (uint32_t)(buf[9] << 16) + (buf[10] << 8) + buf[11];
+	*capacity = (uint64_t)num_blocks * block_len;
+
+	return (true);
+}
+
+bool
+get_media_info(int fd, uint64_t *capacity)
+{
+	struct disklabel d;
+	int ret;
+
+	ret = ioctl(fd, DIOCGDINFO, &d);
+	if (ret == -1)
+		return false;
+	*capacity = d.d_secsize * d.d_secperunit;
+	return true;
+}
+
+/*
+ * given current profile, use the best method for determining
+ * disc capacity (in bytes)
+ */
+bool
+get_disc_capacity_for_profile(int fd, int profile, uint64_t *capacity)
+{
+	disc_info_t	di;
+	bool	ret = false;
+
+	switch (profile) {
+	case 0x08: /* CD-ROM */
+	case 0x10: /* DVD-ROM */
+		if (get_media_info(fd, capacity))
+			ret = true;
+		break;
+	default:
+		if (read_format_capacity(fd, capacity) && (*capacity > 0)) {
+			ret = true;
+		} else if (get_disc_info(fd, &di) && (di.capacity > 0)) {
+			if (get_media_info(fd, capacity))
+				ret = true;
+		}
+	}
+
+	return (ret);
+}
+
+bool
+read_toc(int fd, int format, int trackno, int buflen, u_char *buf)
+{
+	struct scsipi_read_toc toc;
+
+	memset(buf, 0, buflen);
+	toc.opcode = READ_TOC;
+	toc.resp_format = format & 0xf;
+	toc.from_track = trackno;
+	toc.data_len[0] = (buflen >> 8) & 0xff;
+	toc.data_len[1] = buflen & 0xff;
+
+        return scsi_command(fd, &toc, sizeof(toc), buf, buflen, 10000, SCCMD_READ);
+}
diff --git a/hal/files/hald-netbsd/probing/cdutils.h b/hal/files/hald-netbsd/probing/cdutils.h
new file mode 100644
index 0000000000..f79a4a2bdd
--- /dev/null
+++ b/hal/files/hald-netbsd/probing/cdutils.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ *
+ * cdutils.h : definitions for CD/DVD utilities
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef CDUTILS_H
+#define CDUTILS_H
+
+#include <sys/types.h>
+#include <sys/dkio.h>
+#include <sys/cdio.h>
+#include <sys/scsiio.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+enum {
+	CDUTIL_WALK_CONTINUE,
+	CDUTIL_WALK_STOP
+};
+
+typedef struct intlist {
+	int	val;
+	struct intlist *next;
+} intlist_t;
+
+typedef struct disc_info {
+	int	disc_status;
+	int	erasable;
+	uint64_t capacity;
+} disc_info_t;
+
+#define	min(a, b)	((a) < (b) ? (a) : (b))
+#define	max(a, b)	((a) > (b) ? (a) : (b))
+
+bool		scsi_command(int fd, void *cmd, size_t cmdlen, void *data,
+			size_t datalen, int timeout, int flags);
+int		mode_sense(int fd, u_char pc, int dbd, int page_len,
+			u_char *buffer);
+int		get_mode_page(int fd, int page_no, int pc, int buf_len,
+			u_char *buffer, int *plen);
+int		get_configuration(int fd, uint16_t feature, int bufsize,
+			u_char *buf);
+bool		get_current_profile(int fd, int *profile);
+void		walk_profiles(int fd, int (*f)(void *, int, bool), void *);
+void		get_read_write_speeds(int fd, int *read_speed, int *write_speed,
+			intlist_t **wspeeds, int *n_wspeeds, intlist_t **wspeeds_mem);
+bool		get_disc_info(int fd, disc_info_t *);
+bool		read_format_capacity(int fd, uint64_t *capacity);
+bool		get_media_info(int fd, uint64_t *capacity);
+bool		get_disc_capacity_for_profile(int fd, int profile,
+			uint64_t *capacity);
+bool		read_toc(int fd, int format, int trackno, int buflen,
+			u_char *buf);
+
+#endif /* CDUTILS_H */
diff --git a/hal/files/hald-netbsd/probing/fsutils.c b/hal/files/hald-netbsd/probing/fsutils.c
new file mode 100644
index 0000000000..fa0a16c2a3
--- /dev/null
+++ b/hal/files/hald-netbsd/probing/fsutils.c
@@ -0,0 +1,217 @@
+/***************************************************************************
+ *
+ * fsutils.c : filesystem utilities
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/scsiio.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/dkio.h>
+#include <libintl.h>
+#include <sys/disklabel.h>
+#include <sys/bootblock.h>
+
+#include <libhal.h>
+#include "fsutils.h"
+
+/*
+ * Separates dos notation device spec into device and drive number
+ */
+bool
+dos_to_dev(char *path, char **devpath, int *num)
+{
+	char *p;
+
+	if ((p = strrchr(path, ':')) == NULL) {
+		return (false);
+	}
+	if ((*num = atoi(p + 1)) == 0) {
+		return (false);
+	}
+	p[0] = '\0';
+	*devpath = strdup(path);
+	p[0] = ':';
+	return (*devpath != NULL);
+}
+
+char *
+get_slice_name (char *devlink)
+{
+	char	*part, *slice, *disk;
+	char	*s = NULL;
+	char	*p;
+
+	if ((p = strstr(devlink, "/lofi/")) != 0) {
+		return (p + sizeof ("/lofi/") - 1);
+	}
+
+	part = strrchr(devlink, 'p');
+	slice = strrchr(devlink, 's');
+	disk = strrchr(devlink, 'd');
+
+	if ((part != NULL) && (part > slice) && (part > disk)) {
+		s = part;
+	} else if ((slice != NULL) && (slice > disk)) {
+		s = slice;
+	} else {
+		s = disk;
+	}
+	if ((s != NULL) && isdigit(s[1])) {
+		return (s);
+	} else {
+		return ("");
+	}
+}
+
+bool
+is_dos_drive(u_char type)
+{
+	return ((type == 1) || (type == 4) || (type == 5) || (type == 6) ||
+	    ((type >= 8) && (type <= 0xf)));
+}
+
+bool
+is_dos_extended(u_char id)
+{
+	return MBR_IS_EXTENDED(id);
+}
+
+struct part_find_s {
+	int	num;
+	int	count;
+	int	systid;
+	int	r_systid;
+	int	r_relsect;
+	int	r_numsect;
+};
+
+enum { WALK_CONTINUE, WALK_TERMINATE };
+
+/*
+ * Walk partition tables and invoke a callback for each.
+ */
+static void
+walk_partitions(int fd, int startsec, int (*f)(void *, int, int, int),
+    void *arg)
+{
+	uint32_t buf[1024/4];
+	int bufsize = 1024;
+	struct mbr_sector *msect = (struct mbr_sector *)&buf[0];
+	struct mbr_partition mpart[MBR_PART_COUNT];
+	int sec = startsec;
+	int lastsec = sec + 1;
+	int relsect;
+	int ext = 0;
+	int systid;
+	bool valid;
+	int i;
+
+	while (sec != lastsec) {
+		if (pread(fd, buf, bufsize, (off_t)sec * 512) != bufsize) {
+			break;
+		}
+		lastsec = sec;
+		if (le16toh(msect->mbr_magic) != MBR_MAGIC) {
+			break;
+		}
+		memcpy(mpart, msect->mbr_parts, MBR_PART_COUNT * sizeof (struct mbr_partition));
+
+		for (i = 0; i < MBR_PART_COUNT; i++) {
+			systid = mpart[i].mbrp_type;
+			relsect = sec + le32toh(mpart[i].mbrp_start);
+			if (systid == 0) {
+				continue;
+			}
+			valid = true;
+			if (is_dos_extended(systid) && (sec == lastsec)) {
+				sec = startsec + le32toh(mpart[i].mbrp_start);
+				if (ext++ == 0) {
+					relsect = startsec = sec;
+				} else {
+					valid = false;
+				}
+			}
+			if (valid && f(arg, mpart[i].mbrp_type, relsect,
+			    le32toh(mpart[i].mbrp_size)) == WALK_TERMINATE) {
+				return;
+			}
+		}
+	}
+}
+
+static int
+find_dos_drive_cb(void *arg, int systid, int relsect, int numsect)
+{
+	struct part_find_s *p = arg;
+
+	if (is_dos_drive(systid)) {
+		if (++p->count == p->num) {
+			p->r_relsect = relsect;
+			p->r_numsect = numsect;
+			p->r_systid = systid;
+			return (WALK_TERMINATE);
+		}
+	}
+
+	return (WALK_CONTINUE);
+}
+
+/*
+ * Given a dos drive number, return its relative sector number,
+ * number of sectors in partition and the system id.
+ */
+bool
+find_dos_drive(int fd, int num, int *relsect, int *numsect, int *systid)
+{
+	struct part_find_s p = { 0, 0, 0, 0, 0, 0 };
+
+	p.num = num;
+
+	if (num > 0) {
+		walk_partitions(fd, 0, find_dos_drive_cb, &p);
+		if (p.count == num) {
+			*relsect = p.r_relsect;
+			*numsect = p.r_numsect;
+			*systid = p.r_systid;
+			return (true);
+		}
+	}
+
+	return (false);
+}
+
+static int
+get_num_dos_drives_cb(void *arg, int systid, int relsect, int numsect)
+{
+	if (is_dos_drive(systid)) {
+		(*(int *)arg)++;
+	}
+	return (WALK_CONTINUE);
+}
+
+int
+get_num_dos_drives(int fd)
+{
+	int count = 0;
+
+	walk_partitions(fd, 0, get_num_dos_drives_cb, &count);
+
+	return (count);
+}
diff --git a/hal/files/hald-netbsd/probing/fsutils.h b/hal/files/hald-netbsd/probing/fsutils.h
new file mode 100644
index 0000000000..8f4558d7d6
--- /dev/null
+++ b/hal/files/hald-netbsd/probing/fsutils.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+ *
+ * fsutils.h : definitions for filesystem utilities
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifndef FSUTILS_H
+#define FSUTILS_H
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+bool dos_to_dev(char *path, char **devpath, int *num);
+char *get_slice_name (char *devlink);
+bool is_dos_drive(u_char id);
+bool is_dos_extended(u_char id);
+bool find_dos_drive(int fd, int num, int *relsect, int *numsect, int *systid);
+
+#endif /* FSUTILS_H */
diff --git a/hal/files/hald-netbsd/probing/probe-storage.c b/hal/files/hald-netbsd/probing/probe-storage.c
new file mode 100644
index 0000000000..ac03ec25f7
--- /dev/null
+++ b/hal/files/hald-netbsd/probing/probe-storage.c
@@ -0,0 +1,414 @@
+/***************************************************************************
+ *
+ * probe-storage.c : Probe for storage devices
+ *
+ * Copyright 2008 Jared D. McNeill <jmcneill%NetBSD.org@localhost>
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/fdio.h>
+#include <sys/statvfs.h>
+#include <sys/syslog.h>
+
+#include <sys/scsiio.h>
+#include <dev/scsipi/scsi_spc.h>
+#include <dev/scsipi/scsipi_all.h>
+
+#include <libhal.h>
+#include <cdutils.h>
+#include <fsutils.h>
+#include <logger.h>
+
+#if notyet
+/** Check if a filesystem on a special device file is mounted
+ *
+ *  @param  device_file         Special device file, e.g. /dev/cd0a
+ *  @return                     TRUE iff there is a filesystem system mounted
+ *                              on the special device file
+ */
+static dbus_bool_t
+is_mounted (const char *device_file)
+{
+	int count;
+	struct statvfs *statvfs;
+
+	count = getmntinfo(&statvfs, ST_WAIT);
+	while (count-- > 0) {
+		if (strcmp(statvfs->f_mntfromname, device_file) == 0)
+			return TRUE;
+	}
+
+	return FALSE;
+}
+#endif
+
+static int
+get_cdrom_properties_walker (void *arg, int profile, bool is_current)
+{
+	LibHalChangeSet	*cs = (LibHalChangeSet *)arg;
+
+	switch (profile) {
+	case 0x09:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.cdr", TRUE);
+		break;
+	case 0x0a:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.cdrw", TRUE);
+		break;
+	case 0x10:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.dvd", TRUE);
+		break;
+	case 0x11:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdr", TRUE);
+		break;
+	case 0x12:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdram", TRUE);
+		break;
+	case 0x13:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdrw", TRUE);
+		break;
+	case 0x14:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdrw", TRUE);
+		break;
+	case 0x1a:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdplusrw", TRUE);
+		break;
+	case 0x1b:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdplusr", TRUE);
+		break;
+	case 0x2b:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdplusrdl", TRUE);
+		break;
+	case 0x40:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.bd", TRUE);
+		break;
+	case 0x41:
+	case 0x42:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.bdr", TRUE);
+		break;
+	case 0x43:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.bdre", TRUE);
+		break;
+	case 0x50:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.hddvd", TRUE);
+		break;
+	case 0x51:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.hddvdr", TRUE);
+		break;
+	case 0x52:
+		libhal_changeset_set_property_bool (cs, "storage.cdrom.hddvdrw", TRUE);
+		break;
+	}
+
+	return CDUTIL_WALK_CONTINUE;
+}
+
+#define	WSPLEN	64
+
+static void
+get_cdrom_properties (int fd, LibHalChangeSet *cs)
+{
+	int read_speed, write_speed;
+	intlist_t *write_speeds, *write_speeds_mem, *sp;
+	int n_wspeeds;
+	char **wspeeds;
+	char *wspeeds_mem;
+	int i;
+			
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.cdr", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.cdrw", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.dvd", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdr", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdrw", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdram", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdplusr", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdplusrw", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.dvdplusrdl", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.bd", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.bdr", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.bdre", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.hddvd", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.hddvdr", FALSE);
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.hddvdrw", FALSE);
+
+	walk_profiles(fd, get_cdrom_properties_walker, cs);
+
+	/* XXX */		
+	libhal_changeset_set_property_bool (cs, "storage.cdrom.support_media_changed", TRUE);
+			
+	get_read_write_speeds(fd, &read_speed, &write_speed, &write_speeds, &n_wspeeds, &write_speeds_mem);
+
+	libhal_changeset_set_property_int (cs, "storage.cdrom.read_speed", read_speed);
+	libhal_changeset_set_property_int (cs, "storage.cdrom.write_speed", write_speed);
+
+	if (n_wspeeds <= 0) {
+		wspeeds_mem = NULL;
+ 		libhal_changeset_set_property_strlist (cs, "storage.cdrom.write_speeds", (const char **)&wspeeds_mem);
+		return;
+	}
+	if ((wspeeds = (char **)calloc(n_wspeeds + 1, sizeof (char *))) == NULL) {
+		free (write_speeds_mem);
+		return;
+	}
+	if ((wspeeds_mem = (char *)calloc(n_wspeeds, WSPLEN)) == NULL) {
+		free (wspeeds);
+		free (write_speeds_mem);
+		return;
+	}
+	for (i = 0; i < n_wspeeds; i++) {
+		wspeeds[i] = &wspeeds_mem[i * WSPLEN];
+	}
+
+	for (sp = write_speeds, i = 0; sp != NULL; sp = sp->next, i++) {
+		snprintf (wspeeds[i], WSPLEN, "%d", sp->val);
+	}
+	libhal_changeset_set_property_strlist (cs, "storage.cdrom.write_speeds", (const char **)wspeeds);
+
+	free (wspeeds);
+	free (wspeeds_mem);
+	free (write_speeds_mem);
+}
+
+/*
+ * Return a copy of a string without trailing spaces. If 'len' is non-zero,
+ * it specifies max length, otherwise the string must be null-terminated.
+ */
+static char *
+rtrim_copy(char *src, int len)
+{
+	char	*dst, *p;
+
+	if (len == 0) {
+		len = strlen(src);
+	}
+	if ((dst = calloc(1, len + 1)) != NULL) {
+		strncpy(dst, src, len);
+		p = dst + len - 1;
+		while ((p >= dst) && (isspace((int)*p))) {
+			*p-- = '\0';
+		}
+	}
+	return (dst);
+}
+
+static void
+get_disk_properties (int fd, LibHalChangeSet *cs)
+{
+	struct scsipi_inquiry_data inqbuf;
+	struct scsipi_inquiry cmd;
+	dbus_bool_t status;
+	char		*s;
+
+	/* INQUIRY */
+	memset(&cmd, 0, sizeof(cmd));
+	memset(&inqbuf, 0, sizeof(inqbuf));
+	cmd.opcode = INQUIRY;
+	cmd.length = sizeof(inqbuf);
+	status = scsi_command(fd, &cmd, sizeof(cmd), &inqbuf, sizeof(inqbuf), 10000, SCCMD_READ);
+	if (status == false)
+		return;
+
+	if ((s = rtrim_copy(inqbuf.vendor, sizeof (inqbuf.vendor))) != NULL) {
+		libhal_changeset_set_property_string (cs, "storage.vendor", s);
+		free(s);
+	}
+	if ((s = rtrim_copy(inqbuf.product, sizeof (inqbuf.product))) != NULL) {
+		libhal_changeset_set_property_string (cs, "storage.model", s);
+		free(s);
+	}
+	if ((s = rtrim_copy(inqbuf.revision, sizeof (inqbuf.revision))) != NULL) {
+		libhal_changeset_set_property_string (cs, "storage.firmware_revision", s);
+		free(s);
+	}
+	if ((s = rtrim_copy((char *)inqbuf.vendor_specific, sizeof (inqbuf.vendor_specific))) != NULL) {
+		libhal_changeset_set_property_string (cs, "storage.serial", s);
+		free(s);
+	}
+}
+
+#if notyet
+/*
+ * returns TRUE if diskette is inserted.
+ * also returns write protection status.
+ */
+static dbus_bool_t
+check_floppy(int fd, dbus_bool_t *wprot)
+{
+	int	chg;
+
+	if ((ioctl(fd, FDGETCHANGE, &chg) == 0) && !(chg & FDGC_CURRENT)) {
+		*wprot = ((chg & FDGC_CURWPROT) != NULL);
+		return (TRUE);
+	} else {
+		return (FALSE);
+	}
+}
+#endif
+
+int 
+main (int argc, char *argv[])
+{
+	int ret = 1;
+	int fd = -1;
+	int rfd = -1;
+	char *udi;
+	char *device_file;
+	char *raw_device_file;
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	char *bus;
+	char *drive_type;
+	dbus_bool_t is_cdrom;
+	dbus_bool_t is_floppy;
+	dbus_bool_t only_check_for_media;
+	int got_media = FALSE;
+	dbus_bool_t is_write_protected = FALSE;
+	dbus_bool_t is_mbr = FALSE;
+	dbus_bool_t is_smi = FALSE;
+	dbus_bool_t is_gpt = FALSE;
+	dbus_bool_t is_partitioned = FALSE;
+	int dos_cnt = 0;
+	const char *scheme = "";
+	LibHalChangeSet *cs = NULL;
+
+	HAL_INFO(("f0"));
+	if ((udi = getenv ("UDI")) == NULL)
+		goto out;
+	HAL_INFO(("f0-1"));
+	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
+		goto out;
+	HAL_INFO(("f0-2"));
+	if ((raw_device_file = getenv ("HAL_PROP_BLOCK_NETBSD_RAW_DEVICE")) == NULL)
+		goto out;
+	HAL_INFO(("f0-3"));
+	if ((bus = getenv ("HAL_PROP_STORAGE_BUS")) == NULL)
+		goto out;
+	HAL_INFO(("f0-4"));
+	if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
+		goto out;
+
+	HAL_INFO(("f1"));
+	setup_logger ();
+
+	if (argc == 2 && strcmp (argv[1], "--only-check-for-media") == 0)
+		only_check_for_media = TRUE;
+	else
+		only_check_for_media = FALSE;
+
+	is_cdrom = (strcmp (drive_type, "cdrom") == 0);
+	is_floppy = (strcmp (drive_type, "floppy") == 0);
+
+	HAL_INFO(("f2"));
+	dbus_error_init (&error);
+	HAL_INFO(("f3"));
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
+		goto out;
+
+	HAL_INFO(("f4"));
+	if ((cs = libhal_device_new_changeset (udi)) == NULL) {
+		HAL_DEBUG (("Cannot allocate changeset"));
+		goto out;
+	}
+	HAL_INFO(("f5"));
+
+	HAL_DEBUG (("Doing probe-storage for %s (bus %s) (drive_type %s) (udi=%s) (--only-check-for-media==%d)", 
+	     device_file, bus, drive_type, udi, only_check_for_media));
+
+	if ((rfd = open (raw_device_file, O_RDONLY | O_NONBLOCK)) < 0) {
+		HAL_DEBUG (("Cannot open %s: %s", raw_device_file, strerror (errno)));
+		goto out;
+	}
+
+	if (!only_check_for_media) {
+		if (strcmp (drive_type, "cdrom") == 0) {
+			get_cdrom_properties (rfd, cs);
+		} else if (strcmp (drive_type, "disk") == 0) {
+			get_disk_properties (rfd, cs);
+		}
+	}
+
+	ret = 0;
+
+	if (is_cdrom) {
+		uint64_t capacity;
+
+		HAL_DEBUG (("Checking for optical disc on %s", raw_device_file));
+		got_media = get_media_info(rfd, &capacity);
+		if (!got_media) {
+			goto out_cs;
+		}
+		/* XXX */
+		is_write_protected = TRUE;
+	} else if (is_floppy) {
+#if 0
+		HAL_DEBUG (("Checking for floppy on %s", raw_device_file));
+		if (check_floppy(rfd, &is_write_protected)) {
+			got_media = TRUE;
+		}
+#endif
+		/* don't look for partitions on floppy */
+		goto out_cs;
+	} else {
+		got_media = TRUE;
+	}
+
+	HAL_DEBUG (("Checking for partitions on %s", device_file));
+
+	if ((fd = open (device_file, O_RDONLY | O_NONBLOCK)) < 0) {
+		HAL_DEBUG (("Cannot open %s: %s", device_file, strerror (errno)));
+		goto out_cs;
+	}
+
+	scheme = "mbr";
+	dos_cnt = 1;
+
+out_cs:
+	is_partitioned = is_mbr || is_smi || is_gpt;
+	libhal_changeset_set_property_bool (cs, "storage.no_partitions_hint", !is_partitioned);
+	libhal_changeset_set_property_bool (cs, "block.no_partitions", !is_partitioned);
+	libhal_changeset_set_property_string (cs, "storage.partitioning_scheme", scheme);
+	libhal_changeset_set_property_int (cs, "storage.netbsd.num_dos_partitions", dos_cnt);
+	/* XXX should only set for removable drives */
+	libhal_changeset_set_property_bool (cs, "storage.removable.media_available", got_media);
+	libhal_changeset_set_property_bool (cs, "storage.removable.netbsd.read_only", is_write_protected);
+
+	libhal_device_commit_changeset (ctx, cs, &error);
+
+out:
+	if (cs != NULL) {
+		libhal_device_free_changeset (cs);
+	}
+	if (fd >= 0) {
+		close (fd);
+	}
+	if (rfd >= 0) {
+		close (rfd);
+	}
+	if (ctx != NULL) {
+		if (dbus_error_is_set(&error)) {
+			dbus_error_free (&error);
+		}
+		libhal_ctx_shutdown (ctx, &error);
+		libhal_ctx_free (ctx);
+	}
+
+	return ret;
+}
diff --git a/hal/files/hald-netbsd/probing/probe-volume.c b/hal/files/hald-netbsd/probing/probe-volume.c
new file mode 100644
index 0000000000..9b9c66a19d
--- /dev/null
+++ b/hal/files/hald-netbsd/probing/probe-volume.c
@@ -0,0 +1,629 @@
+/***************************************************************************
+ *
+ * probe-volume.c : probe volumes
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/dkio.h>
+#include <sys/cdio.h>
+#include <sys/fdio.h>
+#include <sys/disklabel.h>
+#include <isofs/cd9660/iso.h>
+
+#include <libhal.h>
+#include <cdutils.h>
+#include <fsutils.h>
+#include <logger.h>
+
+static void
+my_dbus_error_free(DBusError *error)
+{
+	if (dbus_error_is_set(error)) {
+		dbus_error_free(error);
+	}
+}
+
+/*
+ * Return a copy of a string without trailing spaces. If 'len' is non-zero,
+ * it specifies max length, otherwise the string must be null-terminated.
+ */
+static char *
+rtrim_copy(char *src, int len)
+{
+	char	*dst, *p;
+
+	if (len == 0) {
+		len = strlen(src);
+	}
+	if ((dst = calloc(1, len + 1)) != NULL) {
+		strncpy(dst, src, len);
+		p = dst + len - 1;
+		while ((p >= dst) && (isspace(*p))) {
+			*p-- = '\0';
+		}
+	}
+	return (dst);
+}
+
+static void
+set_fstyp_properties (LibHalContext *ctx, const char *udi, const char *fstype)
+{
+	char buf[256];
+	DBusError error;
+	char *uuid = NULL;
+	char *label_orig = NULL;
+	char *label = NULL;
+	LibHalChangeSet *cs;
+
+	dbus_error_init (&error);
+
+	if ((cs = libhal_device_new_changeset (udi)) == NULL) {
+		return;
+	}
+
+	libhal_changeset_set_property_string (cs, "volume.fsusage", "filesystem");
+	libhal_changeset_set_property_string (cs, "volume.fstype", fstype);
+
+#if notyet
+	/* label */
+	(void) nvlist_lookup_string(fsattr, "gen_volume_label", &label_orig);
+#endif
+	if (label_orig != NULL) {
+		label = rtrim_copy(label_orig, 0);
+	}
+	if ((label != NULL) && (label[0] != '\0')) {
+		libhal_changeset_set_property_string (cs, "volume.label", label);
+		libhal_changeset_set_property_string (cs, "info.product", label);
+	} else {
+		libhal_changeset_set_property_string (cs, "volume.label", "");
+		snprintf (buf, sizeof (buf), "Volume (%s)", fstype);
+		libhal_changeset_set_property_string (cs, "info.product", buf);
+	}
+	if (label)
+		free(label);
+
+#if notyet
+	/* uuid */
+	if (nvlist_lookup_string(fsattr, "gen_uuid", &uuid) == 0) {
+		libhal_changeset_set_property_string (cs, "volume.uuid", uuid);
+	} else {
+		libhal_changeset_set_property_string (cs, "volume.uuid", "");
+	}
+#else
+	libhal_changeset_set_property_string (cs, "volume.uuid", "");
+#endif
+
+	libhal_device_commit_changeset (ctx, cs, &error);
+	libhal_device_free_changeset (cs);
+
+	my_dbus_error_free (&error);
+}
+
+#define ISO_VOLDESC_SEC 16
+#define IPE_FPESIZE 8
+#define IDE_MAX_NAME_LEN (255 - ISO_DIRECTORY_RECORD_SIZE)
+
+/*
+ * isofs/cd9660 contents detection: Video DVD, Video CD, etc.
+ */
+static void
+isofs_contents(int fd, off_t probe_offset, LibHalContext *ctx, const char *udi)
+{
+	size_t	secsz = sizeof(struct iso_primary_descriptor);
+	struct iso_primary_descriptor ipdesc;
+	uint8_t buf[sizeof(struct iso_volume_descriptor)];
+	int	ptbl_lbn, ptbl_size;
+	int	off, reloff, readoff;
+	char	*name;
+	int	name_len;
+	int	ipe_len;
+	DBusError error;
+
+	/*
+	 * find 1st Primary Volume Descriptor
+	 */
+	readoff = probe_offset + ISO_VOLDESC_SEC * secsz;
+	if (pread (fd, &ipdesc, secsz, readoff) != secsz) {
+		return;
+	}
+	while (isonum_711 (ipdesc.type) != ISO_VD_PRIMARY) {
+		if (isonum_711 (ipdesc.type) == ISO_VD_END) {
+			return;
+		}
+		readoff += secsz;
+		if (pread (fd, buf, secsz, readoff) != secsz) {
+			return;
+		}
+	}
+
+	/*
+	 * PVD contains size and offset of the LSB/MSB path table
+	 */
+	ptbl_size = isonum_733 (ipdesc.path_table_size);
+	ptbl_lbn = isonum_732 (ipdesc.type_m_path_table);
+
+	/*
+	 * Look through path table entries
+	 */
+	readoff = probe_offset + ptbl_lbn * secsz;
+	if (pread (fd, buf, secsz, readoff) != secsz) {
+		return;
+	}
+	dbus_error_init (&error);
+
+	for (off = reloff = 0;
+	    off < ptbl_size;
+	    off += ipe_len, reloff += ipe_len) {
+		uint8_t *p;
+
+		/* load sectors on demand */
+		if (reloff >= secsz) {
+			readoff += secsz;
+			if (pread (fd, buf, secsz, readoff) != secsz) {
+				break;
+			}
+			reloff -= secsz;
+		}
+
+		p = buf + reloff;
+		name_len = isonum_711 (p[0]);
+		ipe_len = IPE_FPESIZE + name_len + (name_len % 2);
+
+		/* only interested in root directories */
+		if (isonum_711 (p[6]) != 1) {
+			continue;
+		}
+		if ((name_len < 2) || (name_len > IDE_MAX_NAME_LEN)) {
+			continue;
+		}
+
+		name = (char *)&p[8];
+		if (strncasecmp (name, "VIDEO_TS", min (8, name_len)) == 0) {
+			libhal_device_set_property_bool (ctx, udi,
+			    "volume.disc.is_videodvd", TRUE, &error);
+		} else if (strncasecmp (name, "VCD", min (3, name_len)) == 0) {
+			libhal_device_set_property_bool (ctx, udi,
+			    "volume.disc.is_vcd", TRUE, &error);
+		} else if (strncasecmp (name, "SVCD", min (4, name_len)) == 0) {
+			libhal_device_set_property_bool (ctx, udi,
+			    "volume.disc.is_svcd", TRUE, &error);
+		}
+	}
+
+	my_dbus_error_free (&error);
+}
+
+static dbus_bool_t
+probe_disc (int fd, LibHalContext *ctx, const char *udi, dbus_bool_t *should_probe_for_fs)
+{
+	DBusError error;
+	disc_info_t di;
+	int profile;
+	dbus_bool_t has_audio, has_data, is_blank, is_appendable, is_rewritable;
+	char *disc_type = "cd_rom";
+	uint64_t capacity = 0;
+	int i;
+	LibHalChangeSet *cs;
+
+	dbus_error_init (&error);
+
+	if (get_disc_info (fd, &di)) {
+		is_blank = (di.disc_status == 0);
+		is_appendable = (di.disc_status == 1);
+		is_rewritable = (di.erasable != 0);
+	} else {
+		is_blank = is_appendable = is_rewritable = FALSE;
+	}
+
+	if (get_current_profile (fd, &profile)) {
+		switch (profile) {
+		case 0x08: /* CD-ROM */
+			disc_type = "cd_rom";
+			break;
+		case 0x09: /* CD-R */
+			disc_type = "cd_r";
+			break;
+		case 0x0A: /* CD-RW */
+			disc_type = "cd_rw";
+			is_rewritable = TRUE;
+			break;
+		case 0x10: /* DVD-ROM */
+			disc_type = "dvd_rom";
+			break;
+		case 0x11: /* DVD-R Sequential */
+			disc_type = "dvd_r";
+			break;
+		case 0x12: /* DVD-RAM */
+			disc_type = "dvd_ram";
+			is_rewritable = TRUE;
+			break;
+		case 0x13: /* DVD-RW Restricted Overwrite */
+			disc_type = "dvd_rw";
+			is_rewritable = TRUE;
+			break;
+		case 0x14: /* DVD-RW Sequential */
+			disc_type = "dvd_rw";
+			is_rewritable = TRUE;
+			break;
+		case 0x1A: /* DVD+RW */
+			disc_type = "dvd_plus_rw";
+			is_rewritable = TRUE;
+			break;
+		case 0x1B: /* DVD+R */
+			disc_type = "dvd_plus_r";
+			break;
+		case 0x2B: /* DVD+R Double Layer */
+                        disc_type = "dvd_plus_r_dl";
+			break;
+		case 0x40: /* BD-ROM */
+                        disc_type = "bd_rom";
+			break;
+		case 0x41: /* BD-R Sequential */
+		case 0x42: /* BD-R Random */
+                        disc_type = "bd_r";
+			break;
+		case 0x43: /* BD-RE */
+                        disc_type = "bd_re";
+			is_rewritable = TRUE;
+			break;
+		case 0x50: /* HD DVD-ROM */
+                        disc_type = "hddvd_rom";
+			break;
+		case 0x51: /* HD DVD-R */
+                        disc_type = "hddvd_r";
+			break;
+		case 0x52: /* HD DVD-Rewritable */
+                        disc_type = "hddvd_rw";
+			is_rewritable = TRUE;
+			break;
+		}
+
+		(void) get_disc_capacity_for_profile(fd, profile, &capacity);
+	}
+
+	has_audio = has_data = FALSE;
+	if (!is_blank) {
+		u_char	smalltoc[12];
+		size_t	toc_size;
+		u_char	*toc, *p;
+
+		/*
+		 * XXX for some reason CDROMREADTOCENTRY fails on video DVDs,
+		 * but extracting the toc directly works okay.
+		 */
+        	if (!read_toc(fd, 0, 1, 4, smalltoc)) {
+                	HAL_DEBUG(("read_toc failed"));
+			has_data = TRUE; /* probe for fs anyway */
+        	} else {
+        		toc_size = smalltoc[0] * 256 + smalltoc[1] + 2;
+        		toc = (u_char *)calloc(1, toc_size);
+        		if (toc == NULL || !read_toc(fd, 0, 1, toc_size, toc)) {
+                		HAL_DEBUG (("read_toc again failed"));
+        		} else {
+        			for (p = &toc[4]; p < (toc + toc_size); p += 8) {
+					/* skip leadout */
+                			if (p[2] == 0xAA) {
+						continue;
+					}
+					if (p[1] & 4) {
+						has_data = TRUE;
+					} else {
+						has_audio = TRUE;
+					}
+        			}
+			}
+			free(toc);
+		}
+	}
+
+	if ((cs = libhal_device_new_changeset (udi)) == NULL) {
+		return (FALSE);
+	}
+	libhal_changeset_set_property_string (cs, "volume.disc.type", disc_type);
+	libhal_changeset_set_property_bool (cs, "volume.disc.is_blank", is_blank);
+	libhal_changeset_set_property_bool (cs, "volume.disc.has_audio", has_audio);
+	libhal_changeset_set_property_bool (cs, "volume.disc.has_data", has_data);
+	libhal_changeset_set_property_bool (cs, "volume.disc.is_appendable", is_appendable);
+	libhal_changeset_set_property_bool (cs, "volume.disc.is_rewritable", is_rewritable);
+	libhal_changeset_set_property_uint64 (cs, "volume.disc.capacity", capacity);
+
+	libhal_changeset_set_property_bool (cs, "volume.disc.is_videodvd", FALSE);
+	libhal_changeset_set_property_bool (cs, "volume.disc.is_vcd", FALSE);
+	libhal_changeset_set_property_bool (cs, "volume.disc.is_svcd", FALSE);
+
+	libhal_device_commit_changeset (ctx, cs, &error);
+	libhal_device_free_changeset (cs);
+
+out:
+
+	*should_probe_for_fs = has_data;
+
+	my_dbus_error_free (&error);
+
+	return (TRUE);
+}
+
+int 
+main (int argc, char *argv[])
+{
+	int fd, rfd;
+	int ret;
+	char *udi;
+	char *device_file, *raw_device_file;
+	char *devpath, *rdevpath;
+	bool is_dos;
+	int dos_num;
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	DBusConnection *conn;
+	char *parent_udi;
+	char *storage_device;
+	char *is_disc_str;
+	int fdc;
+	dbus_bool_t is_disc = FALSE;
+	dbus_bool_t is_floppy = FALSE;
+	unsigned int block_size;
+	dbus_uint64_t vol_size;
+	dbus_bool_t should_probe_for_fs;
+	char *partition_scheme = NULL;
+	struct disklabel d;
+	dbus_uint64_t partition_start = 0;
+	int partition_number = 0;
+	int i, dos_cnt;
+	int systid, relsect, numsect;
+	off_t probe_offset = 0;
+	int num_volumes;
+	char **volumes;
+	dbus_uint64_t v_start;
+	const char *fstype;
+
+	fd = rfd = -1;
+
+	ret = 1;
+
+	if ((udi = getenv ("UDI")) == NULL) {
+		goto out;
+	}
+	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL) {
+		goto out;
+	}
+	if ((raw_device_file = getenv ("HAL_PROP_BLOCK_SOLARIS_RAW_DEVICE")) == NULL) {
+		goto out;
+	}
+	if (!dos_to_dev(device_file, &rdevpath, &dos_num)) {
+		rdevpath = raw_device_file;
+	}
+	if (!(is_dos = dos_to_dev(device_file, &devpath, &dos_num))) {
+		devpath = device_file;
+	}
+	if ((parent_udi = getenv ("HAL_PROP_INFO_PARENT")) == NULL) {
+		goto out;
+	}
+	if ((storage_device = getenv ("HAL_PROP_BLOCK_STORAGE_DEVICE")) == NULL) {
+		goto out;
+	}
+
+	is_disc_str = getenv ("HAL_PROP_VOLUME_IS_DISC");
+	if (is_disc_str != NULL && strcmp (is_disc_str, "true") == 0) {
+		is_disc = TRUE;
+	} else {
+		is_disc = FALSE;
+	}
+
+	setup_logger ();
+
+	dbus_error_init (&error);
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
+		goto out;
+
+	HAL_DEBUG (("Doing probe-volume for %s\n", device_file));
+
+	fd = open (devpath, O_RDONLY | O_NONBLOCK);
+	if (fd < 0) {
+		goto out;
+	}
+	rfd = open (rdevpath, O_RDONLY | O_NONBLOCK);
+	if (rfd < 0) {
+		goto out;
+	}
+
+#if notyet
+	/* if it's a floppy with no media, bail out */
+	if (ioctl(rfd, FDGETCHANGE, &fdc) == 0) {
+		is_floppy = TRUE;
+		if (fdc & FDGC_CURRENT) {
+			goto out;
+		}
+	}
+#endif
+
+	/* block size and total size */
+	if (ioctl(rfd, DIOCGDINFO, &d) != -1) {
+		block_size = d.d_secsize;
+		vol_size = d.d_secsize * d.d_secperunit;
+	} else {
+		block_size = 512;
+		vol_size = 0;
+	}
+	libhal_device_set_property_int (ctx, udi, "volume.block_size", block_size, &error);
+	my_dbus_error_free (&error);
+	libhal_device_set_property_uint64 (ctx, udi, "volume.size", vol_size, &error);
+	my_dbus_error_free (&error);
+
+	should_probe_for_fs = TRUE;
+
+	if (is_disc) {
+		if (!probe_disc (rfd, ctx, udi, &should_probe_for_fs)) {
+			HAL_DEBUG (("probe_disc failed, skipping fstyp"));
+			goto out;
+		}
+		/* XXX vol_probe_offset for multisession discs? */
+	}
+
+	if (!should_probe_for_fs) {
+		goto skip_fs;
+	}
+
+	/* don't support partitioned floppy */
+	if (is_floppy) {
+		goto skip_part;
+	}
+
+	/*
+	 * first get partitioning info
+	 */
+	if (is_dos) {
+		/* for a dos drive find partition offset */
+		if (!find_dos_drive(fd, dos_num, &relsect, &numsect, &systid)) {
+			goto out;
+		}
+		partition_scheme = "mbr";
+		partition_start = (dbus_uint64_t)relsect * 512;
+		partition_number = dos_num;
+		probe_offset = (off_t)relsect * 512;
+	} else {
+#if notyet
+		if ((partition_number = read_vtoc(rfd, &vtoc)) >= 0) {
+			if (!vtoc_one_slice_entire_disk(&vtoc)) {
+				partition_scheme = "smi";
+				if (partition_number < vtoc.v_nparts) {
+					if (vtoc.v_part[partition_number].p_size == 0) {
+						HAL_DEBUG (("zero size partition"));
+					}
+					partition_start = vtoc.v_part[partition_number].p_start * block_size;
+				}
+			}
+		} else if ((partition_number = efi_alloc_and_read(rfd, &gpt)) >= 0) {
+			partition_scheme = "gpt";
+			if (partition_number < gpt->efi_nparts) {
+				if (gpt->efi_parts[partition_number].p_size == 0) {
+					HAL_DEBUG (("zero size partition"));
+				}
+				partition_start = gpt->efi_parts[partition_number].p_start * block_size;
+			}
+			efi_free(gpt);
+		}
+#endif
+		probe_offset = 0;
+	}
+
+	if (partition_scheme != NULL) {
+		libhal_device_set_property_string (ctx, udi, "volume.partition.scheme", partition_scheme, &error);
+		my_dbus_error_free (&error);
+		libhal_device_set_property_int (ctx, udi, "volume.partition.number", partition_number, &error);
+		my_dbus_error_free (&error);
+		libhal_device_set_property_uint64 (ctx, udi, "volume.partition.start", partition_start, &error);
+		my_dbus_error_free (&error);
+		libhal_device_set_property_bool (ctx, udi, "volume.is_partition", TRUE, &error);
+		my_dbus_error_free (&error);
+	} else {
+		libhal_device_set_property_bool (ctx, udi, "volume.is_partition", FALSE, &error);
+		my_dbus_error_free (&error);
+	}
+
+	/*
+	 * ignore duplicate partitions
+	 */
+	if ((volumes = libhal_manager_find_device_string_match (
+	    ctx, "block.storage_device", storage_device, &num_volumes, &error)) != NULL) {
+		my_dbus_error_free (&error);
+		for (i = 0; i < num_volumes; i++) {
+			if (strcmp (udi, volumes[i]) == 0) {
+				continue; /* skip self */
+			}
+			v_start = libhal_device_get_property_uint64 (ctx, volumes[i], "volume.partition.start", &error);
+			if (dbus_error_is_set(&error)) {
+				dbus_error_free(&error);
+				continue;
+			}
+			if (v_start == partition_start) {
+				HAL_DEBUG (("duplicate partition"));
+				goto out;
+			}
+		}
+		libhal_free_string_array (volumes);
+	}
+
+skip_part:
+
+#if notyet
+	/*
+	 * now determine fs type
+	 */
+	if (fstyp_init(fd, probe_offset, NULL, &fstyp_handle) != 0) {
+		HAL_DEBUG (("fstyp_init failed"));
+		goto out;
+	}
+	if ((fstyp_ident(fstyp_handle, NULL, &fstype) != 0) ||
+	    (fstyp_get_attr(fstyp_handle, &fsattr) != 0)) {
+		HAL_DEBUG (("fstyp ident or get_attr failed"));
+
+		/*
+		 * XXX fstyp_udfs has a bug that it only works on raw,
+		 * but we don't want to slow down the fast path above.
+		 * Try raw for just udfs here until the bug is fixed.
+		 */
+		HAL_DEBUG (("trying udfs workaround"));
+		fstyp_fini(fstyp_handle);
+		if (fstyp_init(rfd, probe_offset, NULL, &fstyp_handle) != 0) {
+			goto out;
+		}
+		if ((fstyp_ident(fstyp_handle, "udfs", &fstype) != 0) ||
+		    (fstyp_get_attr(fstyp_handle, &fsattr) != 0)) {
+			fstyp_fini(fstyp_handle);
+			goto out;
+		}
+	}
+#else
+	fstype = "cd9660";
+#endif
+	set_fstyp_properties (ctx, udi, fstype);
+
+	if (strcmp (fstype, "cd9660") == 0) {
+		isofs_contents (fd, probe_offset, ctx, udi);
+	}
+
+#if notyet
+	fstyp_fini(fstyp_handle);
+#endif
+
+skip_fs:
+
+	ret = 0;
+
+out:
+	if (fd >= 0)
+		close (fd);
+	if (rfd >= 0)
+		close (rfd);
+
+	if (ctx != NULL) {
+		my_dbus_error_free (&error);
+		libhal_ctx_shutdown (ctx, &error);
+		libhal_ctx_free (ctx);
+	}
+
+	return ret;
+
+}
diff --git a/hal/files/hald-netbsd/vfsstat.c b/hal/files/hald-netbsd/vfsstat.c
new file mode 100644
index 0000000000..9a09c0ef53
--- /dev/null
+++ b/hal/files/hald-netbsd/vfsstat.c
@@ -0,0 +1,157 @@
+/* $NetBSD: vfsstat.c,v 1.1 2008/12/01 02:02:33 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2008 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <paths.h>
+#include <unistd.h>
+
+#include "../osspec.h"
+#include "../logger.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../hald_runner.h"
+#include "../device_info.h"
+#include "../util.h"
+#include "../ids.h"
+#include "hotplug.h"
+#include "devinfo.h"
+#include "vfsstat.h"
+#include "drvctl.h"
+
+static void
+vfsstat_cleanup_mountpoint_cb(HalDevice *d, guint32 exit_type,
+    gint return_code, gchar **error, gpointer data1, gpointer data2)
+{
+	char *mount_point = data1;
+
+	HAL_INFO (("cleaned up mount point %s", mount_point));
+
+	g_free (mount_point);
+}
+
+void
+vfsstat_event(HalDevice *volume)
+{
+	GSList *volumes, *v;
+	HalDevice *d;
+	struct statvfs *statvfs;
+	int nmounts, i;
+
+	if (volume == NULL)
+		volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.category", "volume");
+	else
+		volumes = g_slist_append (NULL, volume);
+
+	if (volumes == NULL)
+		return;
+
+	nmounts = getvfsstat (NULL, 0, ST_WAIT);
+	if (nmounts <= 0)
+		return;
+	statvfs = calloc (nmounts, sizeof (*statvfs));
+	if (statvfs == NULL)
+		return;
+	nmounts = getvfsstat (statvfs, nmounts * sizeof (*statvfs), ST_WAIT);
+	if (nmounts <= 0)
+		goto done;
+
+	for (i = 0; i < nmounts; i++)
+		for (v = volumes; v; v = g_slist_next (v)) {
+			const char *devpath;
+
+			d = HAL_DEVICE (v->data);
+			devpath = hal_device_property_get_string (d, "block.device");
+			if (devpath == NULL || strlen (devpath) == 0)
+				continue;
+			if (strcmp (devpath, statvfs[i].f_mntfromname) != 0)
+				continue;
+
+			device_property_atomic_update_begin ();
+			hal_device_property_set_bool (d, "volume.is_mounted", TRUE);
+			hal_device_property_set_bool (d, "volume.is_mounted_read_only",
+			    statvfs[i].f_flag & ST_RDONLY ? TRUE : FALSE);
+			hal_device_property_set_string (d, "volume.mount_point", statvfs[i].f_mntonname);
+			device_property_atomic_update_end ();
+
+			volumes = g_slist_delete_link (volumes, v);
+		}
+
+	for (v = volumes; v; v = g_slist_next (v)) {
+		const char *mount_path;
+
+		d = HAL_DEVICE (v->data);
+		mount_path = g_strdup (hal_device_property_get_string (d, "volume.mount_point"));
+		if (mount_path == NULL || strlen (mount_path) == 0) {
+			if (mount_path)
+				g_free (mount_path);
+			continue;
+		}
+
+		device_property_atomic_update_begin ();
+		hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
+		hal_device_property_set_bool (d, "volume.is_mounted_read_only", FALSE);
+		hal_device_property_set_string (d, "volume.mount_point", "");
+		device_property_atomic_update_end ();
+
+		if (hal_util_is_mounted_by_hald (mount_path)) {
+			char *cleanup_stdin;
+			char *extra_env[2];
+
+			extra_env[0] = g_strdup_printf ("HALD_CLEANUP=%s", mount_path);
+			extra_env[1] = NULL;
+			cleanup_stdin = "\n";
+
+			hald_runner_run_method (d,
+						"hal-storage-cleanup-mountpoint",
+						extra_env,
+						cleanup_stdin, TRUE,
+						0,
+						vfsstat_cleanup_mountpoint_cb,
+						g_strdup (mount_path), NULL);
+
+			g_free (extra_env[0]);
+		}
+
+		g_free (mount_path);
+	}
+
+	g_slist_free (volumes);
+
+done:
+	free (statvfs);
+}
diff --git a/hal/files/hald-netbsd/vfsstat.h b/hal/files/hald-netbsd/vfsstat.h
new file mode 100644
index 0000000000..a78bc7aa52
--- /dev/null
+++ b/hal/files/hald-netbsd/vfsstat.h
@@ -0,0 +1,36 @@
+/* $NetBSD: vfsstat.h,v 1.1 2008/12/01 02:02:33 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2008 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef VFSSTAT_H
+#define VFSSTAT_H
+
+#include "devinfo.h"
+
+void vfsstat_event(HalDevice *volume);
+
+#endif /* VFSSTAT_H */
diff --git a/hal/files/smf/hal.sh b/hal/files/smf/hal.sh
new file mode 100755
index 0000000000..c9d6cc0460
--- /dev/null
+++ b/hal/files/smf/hal.sh
@@ -0,0 +1,35 @@
+#!/sbin/sh
+
+. /lib/svc/share/smf_include.sh
+
+if [ ! -x @PREFIX@/sbin/hald ] ; then
+	echo "@PREFIX@/sbin/hald not found or not executable"
+	exit $SMF_EXIT_ERR_FATAL
+fi
+
+case "$1" in
+'start')
+	dir="@PKG_HOME.haldaemon@"
+	if ! [ -d $dir ]; then
+		@MKDIR@ -m 0755 $dir
+		@CHOWN@ @HAL_USER@:@HAL_GROUP@ $dir
+	fi
+
+	if ! [ -d /media ]; then
+		@MKDIR@ -m 755 /media
+	fi
+
+	@PREFIX@/sbin/hald --daemon=yes --use-syslog
+	err=$?
+	if [ $err -ne 0 ]; then
+		echo "hal failed to start: error $err"
+		exit $SMF_EXIT_ERR_FATAL
+	fi
+	;;
+*)
+        echo "Usage: $0 { start }"
+	exit $SMF_EXIT_ERR_FATAL
+        ;;
+esac
+
+exit $SMF_EXIT_OK
diff --git a/hal/files/smf/manifest.xml b/hal/files/smf/manifest.xml
new file mode 100644
index 0000000000..1d7a93f173
--- /dev/null
+++ b/hal/files/smf/manifest.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<service_bundle type='manifest' name='export'>
+<service
+	name='@SMF_PREFIX@/@SMF_NAME@'
+	type='service'
+	version='1'>
+	<create_default_instance enabled='false' />
+	<single_instance />
+	<dependency name='usr'
+		type='service'
+		grouping='require_all'
+		restart_on='none'>
+		<service_fmri value='svc:/system/filesystem/minimal' />
+	</dependency>
+	<dependency
+		name='devices'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri value='svc:/system/device/local' />
+	</dependency>
+	<dependency name='dbus'
+		type='service'
+		grouping='require_all'
+		restart_on='none'>
+		<service_fmri value='svc:/@SMF_PREFIX@/dbus' />
+	</dependency>
+	<dependency name='sysevent'
+		type='service'
+		grouping='require_all'
+		restart_on='none'>
+		<service_fmri value='svc:/system/sysevent' />
+	</dependency>
+
+	<dependency name='keymap'
+		type='service'
+		grouping='optional_all'
+		restart_on='none'>
+		<service_fmri value='svc:/system/keymap' />
+	</dependency>
+
+	<exec_method
+		type='method'
+		name='start'
+		exec='@PREFIX@/@SMF_METHOD_FILE.hal@ start'
+		timeout_seconds='600'>
+		<method_context>
+			<method_credential user='root' group='root' />
+		</method_context>
+	</exec_method>
+
+	<exec_method
+		type='method'
+		name='stop'
+		exec=':kill'
+		timeout_seconds='30' />
+
+	<property_group name='startd' type='framework'>
+		<!-- sub-process core dumps shouldn't restart session -->
+		<propval name='ignore_error' type='astring'
+		    value='core,signal' />
+	</property_group>
+
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>
+			Hardware Abstraction Layer daemon
+			</loctext>
+		</common_name>
+		<documentation>
+			<manpage title='hald' section='8' manpath='@PREFIX@/@PKGMANDIR@'/>
+		</documentation>
+	</template>
+
+</service>
+
+</service_bundle>
diff --git a/hal/files/tools-netbsd/Makefile.am b/hal/files/tools-netbsd/Makefile.am
new file mode 100644
index 0000000000..6876866e70
--- /dev/null
+++ b/hal/files/tools-netbsd/Makefile.am
@@ -0,0 +1,40 @@
+## Process this file with automake to produce Makefile.in
+# $NetBSD: Makefile.am,v 1.2 2011/01/08 13:39:08 obache Exp $
+
+AM_CPPFLAGS = \
+	-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
+	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
+	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
+	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
+	-DPACKAGE_SCRIPT_DIR=\""$(libexecdir)/scripts"\" \
+	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
+	-I$(top_srcdir) -I$(top_srcdir)/libhal -I$(top_srcdir)/libhal-storage \
+	@DBUS_CFLAGS@ @GLIB_CFLAGS@ @POLKIT_CFLAGS@
+
+scriptdir = $(libexecdir)/scripts/netbsd
+
+script_SCRIPTS =					\
+	hal-system-power-suspend-netbsd			\
+	hal-system-power-shutdown-netbsd		\
+	hal-system-power-reboot-netbsd
+
+EXTRA_DIST = $(script_SCRIPTS)
+
+check:
+	for f in $(script_SCRIPTS); do \
+            echo -n "Validate bash syntax in $$f : "; \
+            bash -n $(srcdir)/$$f 2> bash.error;\
+            if test -s bash.error; then \
+                echo failed; \
+                cat bash.error; \
+                rm -f bash.error; \
+                exit 1; \
+            else \
+                echo ok; \
+                rm -f bash.error; \
+            fi; \
+        done;
+
+clean-local :
+	rm -f *~
diff --git a/hal/files/tools-netbsd/hal-system-power-reboot-netbsd b/hal/files/tools-netbsd/hal-system-power-reboot-netbsd
new file mode 100755
index 0000000000..7d1a62d1da
--- /dev/null
+++ b/hal/files/tools-netbsd/hal-system-power-reboot-netbsd
@@ -0,0 +1,19 @@
+#!/bin/sh
+# $NetBSD: hal-system-power-reboot-netbsd,v 1.1 2008/11/27 03:32:19 jmcneill Exp $
+
+unsupported() {
+	echo "org.freedesktop.Hal.Device.SystemPowerManagement.NotSupported" >&2
+	echo "No reboot command found" >&2
+	exit 1
+}
+
+#Try for common tools
+if [ -x "/sbin/shutdown" ] ; then
+	/sbin/shutdown -r now
+	exit $?
+elif [ -x "/usr/sbin/shutdown" ] ; then
+	/usr/sbin/shutdown -r now
+	exit $?
+else
+	unsupported
+fi
diff --git a/hal/files/tools-netbsd/hal-system-power-shutdown-netbsd b/hal/files/tools-netbsd/hal-system-power-shutdown-netbsd
new file mode 100755
index 0000000000..d05d8bca9b
--- /dev/null
+++ b/hal/files/tools-netbsd/hal-system-power-shutdown-netbsd
@@ -0,0 +1,19 @@
+#!/bin/sh
+# $NetBSD: hal-system-power-shutdown-netbsd,v 1.1 2008/11/27 03:32:19 jmcneill Exp $
+
+unsupported() {
+	echo "org.freedesktop.Hal.Device.SystemPowerManagement.NotSupported" >&2
+	echo "No shutdown command found" >&2
+	exit 1
+}
+
+#Try for common tools
+if [ -x "/sbin/shutdown" ] ; then
+	/sbin/shutdown -p now
+	exit $?
+elif [ -x "/usr/sbin/shutdown" ] ; then
+	/usr/sbin/shutdown -p now
+	exit $?
+else
+	unsupported
+fi
diff --git a/hal/files/tools-netbsd/hal-system-power-suspend-netbsd b/hal/files/tools-netbsd/hal-system-power-suspend-netbsd
new file mode 100755
index 0000000000..21b2ed38af
--- /dev/null
+++ b/hal/files/tools-netbsd/hal-system-power-suspend-netbsd
@@ -0,0 +1,29 @@
+#!/bin/sh
+# $NetBSD: hal-system-power-suspend-netbsd,v 1.1 2008/11/27 03:32:19 jmcneill Exp $
+
+alarm_not_supported() {
+	echo org.freedesktop.Hal.Device.SystemPowerManagement.AlarmNotSupported >&2
+	echo Waking the system up is not supported >&2
+	exit 1
+}
+
+unsupported() {
+	echo org.freedesktop.Hal.Device.SystemPowerManagement.NotSupported >&2
+	echo No suspend method found >&2
+	exit 1
+}
+
+read seconds_to_sleep
+
+if [ -x /usr/sbin/apm ] ; then
+	if [ -e /var/run/apmdev ]; then
+		/usr/sbin/apm -z 2>/dev/null
+	else
+		/usr/sbin/apm -z -d 2>/dev/null
+	fi
+	RET=$?
+else
+	unsupported
+fi
+
+exit $RET
diff --git a/hal/patches/patch-Makefile.am b/hal/patches/patch-Makefile.am
new file mode 100644
index 0000000000..cc4a462ee7
--- /dev/null
+++ b/hal/patches/patch-Makefile.am
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- Makefile.am.orig	2008-08-10 13:50:10.000000000 +0000
++++ Makefile.am
+@@ -6,7 +6,7 @@ SUBDIRS = libhal libhal-storage partutil
+ pkgconfigdir = $(libdir)/pkgconfig
+ pkgconfig_DATA = hal.pc hal-storage.pc
+ 
+-dbusdir = $(DBUS_SYS_DIR)
++dbusdir = $(PREFIX)/share/examples/hal
+ dist_dbus_DATA = hal.conf
+ 
+ # Creating ChangeLog from git log (taken from cairo/Makefile.am):
diff --git a/hal/patches/patch-configure.in b/hal/patches/patch-configure.in
new file mode 100644
index 0000000000..6b94bed13a
--- /dev/null
+++ b/hal/patches/patch-configure.in
@@ -0,0 +1,100 @@
+$NetBSD$
+
+--- configure.in.orig	2009-08-24 12:42:29.000000000 +0000
++++ configure.in
+@@ -479,12 +479,16 @@ if test "x$with_libpci" != xno ; then
+ fi 
+ AM_CONDITIONAL([HAVE_LIBPCI], [test "x$USE_LIBPCI" = "xyes"])
+ 
++AC_CHECK_HEADERS([linux/videodev.h], [have_videodev_h=yes], [])
++AM_CONDITIONAL(HAVE_V4L1, [test "x$have_videodev_h" = "xyes"])
++
+ USE_LIBUSB20=no
+ USE_LIBUSB=no
+ LIBUSB20_LIBS=""
++LIBUFS_LIBS=""
+ AC_ARG_WITH([backend],
+ 	    AS_HELP_STRING([--with-backend=<name>],
+-	                   [backend to use (linux/solaris/freebsd/dummy)]),
++	                   [backend to use (linux/solaris/netbsd/freebsd/dummy)]),
+ 	    [backend=$withval])
+ if ! test -z "$with_backend" ; then
+     HALD_BACKEND="$with_backend"
+@@ -493,6 +497,9 @@ else
+         *-*-solaris*)
+ 		   HALD_BACKEND="solaris"
+ 		   ;;
++        *-*-netbsd*)
++		   HALD_BACKEND="netbsd"
++		   ;;
+         *-*-freebsd* | *-*-kfreebsd*-gnu)
+                    HALD_BACKEND="freebsd"
+                    ;;
+@@ -508,8 +515,10 @@ AM_CONDITIONAL(HALD_COMPILE_DUMMY, [test
+ AM_CONDITIONAL(HALD_COMPILE_LINUX, [test x$HALD_BACKEND = xlinux], [Compiling for Linux])
+ AM_CONDITIONAL(HALD_COMPILE_FREEBSD, [test x$HALD_BACKEND = xfreebsd], [Compiling for FreeBSD])
+ AM_CONDITIONAL(HALD_COMPILE_SOLARIS, [test x$HALD_BACKEND = xsolaris], [Compiling for Solaris])
++AM_CONDITIONAL(HALD_COMPILE_NETBSD, [test x$HALD_BACKEND = xnetbsd], [Compiling for NetBSD])
+ AC_SUBST(HALD_BACKEND)
+ if test "x$HALD_BACKEND" = "xfreebsd"; then
++    AC_SEARCH_LIBS([ufs_disk_fillout], [ufs], [LIBUFS_LIBS="-lufs"], [])
+     AC_CHECK_LIB([usb20], [libusb20_dev_get_info], [USE_LIBUSB20=yes], [USE_LIBUSB20=no])
+ fi
+ if test "x$USE_LIBUSB20" = "xno"; then
+@@ -526,6 +535,8 @@ elif test "x$USE_LIBUSB" = "xyes"; then
+ fi
+ AC_SUBST(LIBUSB20_LIBS)
+ 
++AC_SUBST(LIBUFS_LIBS)
++
+ dnl DBUS API is subject to changes
+ AC_DEFINE_UNQUOTED(DBUS_API_SUBJECT_TO_CHANGE, [], [DBUS API is subject to change])
+ 
+@@ -706,8 +717,8 @@ else
+ fi
+ AC_MSG_RESULT($have_glib_2_14)
+ 
+-case "$host" in
+-    *-*-freebsd*)
++case "$HALD_BACKEND" in
++    freebsd | netbsd)
+         PKG_CHECK_MODULES(VOLUME_ID, [$volume_id_module])
+ 	AC_SUBST(VOLUME_ID_CFLAGS)
+ 	AC_SUBST(VOLUME_ID_LIBS)
+@@ -718,14 +729,13 @@ esac
+ 
+ # blkid (util-linux-ng)
+ case "$host" in
+-*-*-freebsd*)
+-        ;;
+-*-*-solaris*)
+-	;;
+-*)
++*linux*)
+ 	PKG_CHECK_MODULES(BLKID, [$blkid_module])
+ 	AC_SUBST(BLKID_CFLAGS)
+ 	AC_SUBST(BLKID_LIBS)
++	;;
++*)
++	;;
+ esac
+ 
+ # OS specific libs
+@@ -1086,6 +1096,9 @@ hald/linux/addons/Makefile
+ hald/solaris/Makefile
+ hald/solaris/probing/Makefile
+ hald/solaris/addons/Makefile
++hald/netbsd/Makefile
++hald/netbsd/probing/Makefile
++hald/netbsd/addons/Makefile
+ hald/freebsd/Makefile
+ hald/freebsd/probing/Makefile
+ hald/freebsd/libprobe/Makefile
+@@ -1096,6 +1109,7 @@ libhal-storage/Makefile
+ tools/Makefile
+ tools/freebsd/Makefile
+ tools/linux/Makefile
++tools/netbsd/Makefile
+ partutil/Makefile
+ policy/Makefile
+ fdi/Makefile
diff --git a/hal/patches/patch-fdi_policy_10osvendor_20-storage-methods.fdi b/hal/patches/patch-fdi_policy_10osvendor_20-storage-methods.fdi
new file mode 100644
index 0000000000..2b37934f84
--- /dev/null
+++ b/hal/patches/patch-fdi_policy_10osvendor_20-storage-methods.fdi
@@ -0,0 +1,98 @@
+$NetBSD$
+
+--- fdi/policy/10osvendor/20-storage-methods.fdi.orig	2009-11-05 14:09:01.000000000 +0000
++++ fdi/policy/10osvendor/20-storage-methods.fdi
+@@ -74,6 +74,11 @@
+ 	  <append key="volume.mount.valid_options" type="strlist">noexec</append>
+ 	  <append key="volume.mount.valid_options" type="strlist">noatime</append>
+ 	</match>
++	<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" string="NetBSD">
++	  <append key="volume.mount.valid_options" type="strlist">ro</append>
++	  <append key="volume.mount.valid_options" type="strlist">noexec</append>
++	  <append key="volume.mount.valid_options" type="strlist">noatime</append>
++	</match>
+       </match>
+     </match>
+ 
+@@ -182,6 +187,13 @@
+ 	<append key="org.freedesktop.Hal.Device.Volume.method_execpaths" type="strlist">hal-storage-eject</append>
+       </match>
+ 
++      <match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" string="NetBSD">
++        <append key="org.freedesktop.Hal.Device.Volume.method_names" type="strlist">Eject</append>
++	<append key="org.freedesktop.Hal.Device.Volume.method_signatures" type="strlist">as</append>
++	<append key="org.freedesktop.Hal.Device.Volume.method_argnames" type="strlist">extra_options</append>
++	<append key="org.freedesktop.Hal.Device.Volume.method_execpaths" type="strlist">hal-storage-eject</append>
++      </match>
++
+       <!-- allow these mount options for all file systems -->
+       <match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" string="Linux">
+         <append key="volume.mount.valid_options" type="strlist">ro</append>
+@@ -200,6 +212,11 @@
+ 	<append key="volume.mount.valid_options" type="strlist">noexec</append>
+ 	<append key="volume.mount.valid_options" type="strlist">noatime</append>
+       </match>
++      <match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" string="NetBSD">
++        <append key="volume.mount.valid_options" type="strlist">ro</append>
++	<append key="volume.mount.valid_options" type="strlist">noexec</append>
++	<append key="volume.mount.valid_options" type="strlist">noatime</append>
++      </match>
+ 
+       <!-- allow these mount options for vfat -->
+       <match key="volume.fstype" string="vfat">
+@@ -226,6 +243,15 @@
+ 	  <append key="volume.mount.valid_options" type="strlist">-D=</append>
+ 	  <append key="volume.mount.valid_options" type="strlist">large</append>
+ 	</match>
++	<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" string="NetBSD">
++	  <append key="volume.mount.valid_options" type="strlist">-u=</append>
++	  <append key="volume.mount.valid_options" type="strlist">-g=</append>
++	  <append key="volume.mount.valid_options" type="strlist">-m=</append>
++	  <append key="volume.mount.valid_options" type="strlist">-M=</append>
++	  <append key="volume.mount.valid_options" type="strlist">-9</append>
++	  <append key="volume.mount.valid_options" type="strlist">-l</append>
++	  <append key="volume.mount.valid_options" type="strlist">-s</append>
++	</match>
+       </match>
+ 
+ 
+@@ -258,6 +284,13 @@
+ 	  <append key="volume.mount.valid_options" type="strlist">-C=</append>
+ 	  <append key="volume.mount.valid_options" type="strlist">-W=</append>
+ 	</match>
++	<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" string="NetBSD">
++	  <append key="volume.mount.valid_options" type="strlist">-u=</append>
++	  <append key="volume.mount.valid_options" type="strlist">-g=</append>
++	  <append key="volume.mount.valid_options" type="strlist">-m=</append>
++	  <append key="volume.mount.valid_options" type="strlist">-a</append>
++	  <append key="volume.mount.valid_options" type="strlist">-i</append>
++	</match>
+       </match>
+ 
+       <!-- allow these mount options for ext3 -->
+@@ -296,6 +329,10 @@
+ 	  <append key="volume.mount.valid_options" type="strlist">-C=</append>
+ 	  <append key="volume.mount.valid_options" type="strlist">-v</append>
+ 	</match>
++	<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" string="NetBSD">
++	  <append key="volume.mount.valid_options" type="strlist">-u=</append>
++	  <append key="volume.mount.valid_options" type="strlist">-g=</append>
++	</match>
+       </match>
+ 
+       <!-- iso9660 -->
+@@ -316,6 +353,14 @@
+ 	  <append key="volume.mount.valid_options" type="strlist">-C=</append>
+ 	  <append key="volume.mount.valid_options" type="strlist">-v</append>
+ 	</match>
++	<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name" string="NetBSD">
++	  <append key="volume.mount.valid_options" type="strlist">extatt</append>
++	  <append key="volume.mount.valid_options" type="strlist">gens</append>
++	  <append key="volume.mount.valid_options" type="strlist">nojoliet</append>
++	  <append key="volume.mount.valid_options" type="strlist">norrip</append>
++	  <append key="volume.mount.valid_options" type="strlist">nomaplcase</append>
++	  <append key="volume.mount.valid_options" type="strlist">rcaseins</append>
++	</match>
+       </match>
+ 
+       <!-- allow these unmount options -->
diff --git a/hal/patches/patch-hald_Makefile.am b/hal/patches/patch-hald_Makefile.am
new file mode 100644
index 0000000000..35643abd05
--- /dev/null
+++ b/hal/patches/patch-hald_Makefile.am
@@ -0,0 +1,12 @@
+$NetBSD$
+
+--- hald/Makefile.am.orig	2009-07-15 06:52:51.000000000 +0000
++++ hald/Makefile.am
+@@ -1,6 +1,6 @@
+ ## Process this file with automake to produce Makefile.in
+ 
+-SUBDIRS = dummy freebsd linux solaris .
++SUBDIRS = dummy freebsd linux solaris netbsd .
+ 
+ AM_CPPFLAGS = \
+ 	-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
diff --git a/hal/patches/patch-hald_device__info.c b/hal/patches/patch-hald_device__info.c
new file mode 100644
index 0000000000..748f57d746
--- /dev/null
+++ b/hal/patches/patch-hald_device__info.c
@@ -0,0 +1,20 @@
+$NetBSD$
+
+--- hald/device_info.c.orig	2009-08-24 12:42:29.000000000 +0000
++++ hald/device_info.c
+@@ -1110,8 +1110,15 @@ rules_match_and_merge_device (void *fdi_
+ 				/*HAL_INFO(("no match, skip to rule (%llx)", rule->jump_position));*/
+ 				rule = di_jump(rule);
+ 
++#if 0
++				/*
++				 * XXX
++				 * this fires when a node has a single child
++				 * which happens on some non-x86 machines
++				 */
+ 				if(rule == NULL)
+ 					DIE(("Rule is NULL on jump"));
++#endif
+ 
+ 				continue;
+ 			}
diff --git a/hal/patches/patch-hald_freebsd_addons_addon-mouse.c b/hal/patches/patch-hald_freebsd_addons_addon-mouse.c
new file mode 100644
index 0000000000..994ae2f684
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_addons_addon-mouse.c
@@ -0,0 +1,14 @@
+$NetBSD$
+
+--- hald/freebsd/addons/addon-mouse.c.orig	2009-08-24 12:42:29.000000000 +0000
++++ hald/freebsd/addons/addon-mouse.c
+@@ -29,7 +29,9 @@
+ #include <sys/types.h>
+ #include <sys/event.h>
+ #include <sys/time.h>
++#ifdef __FreeBSD__
+ #include <sys/proc.h>
++#endif
+ #if __FreeBSD_version >= 800058
+ #include <sys/types.h>
+ #include <sys/user.h>
diff --git a/hal/patches/patch-hald_freebsd_addons_addon-storage.c b/hal/patches/patch-hald_freebsd_addons_addon-storage.c
new file mode 100644
index 0000000000..6e3f654cdf
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_addons_addon-storage.c
@@ -0,0 +1,140 @@
+$NetBSD$
+
+--- hald/freebsd/addons/addon-storage.c.orig	2009-08-24 12:42:29.000000000 +0000
++++ hald/freebsd/addons/addon-storage.c
+@@ -107,8 +107,12 @@ hf_addon_storage_update (void)
+ 
+ 	  if (hf_addon_storage_cdrom_eject_pressed(cdrom))
+ 	    {
++#if defined(__FreeBSD__)
++	      libhal_device_emit_condition(hfp_ctx, hfp_udi, "EjectPressed", "", NULL);
++#else
+ 	      libhal_device_emit_condition(hfp_ctx, hfp_udi, "EjectPressed", "", &hfp_error);
+ 	      dbus_error_free(&hfp_error);
++#endif
+ 	    }
+ 
+ 	  hfp_cdrom_free(cdrom);
+@@ -164,11 +168,17 @@ unmount_volumes (void)
+                                                          "block.storage_device",
+ 							 hfp_udi,
+ 							 &num_volumes,
++#if defined(__FreeBSD__)
++							 NULL)) != NULL)
++#else
+ 							 &hfp_error)) != NULL)
++#endif
+     {
+       int i;
+ 
++#if !defined(__FreeBSD__)
+       dbus_error_free(&hfp_error);
++#endif
+ 
+       for (i = 0; i < num_volumes; i++)
+         {
+@@ -176,7 +186,11 @@ unmount_volumes (void)
+ 
+ 	  vol_udi = volumes[i];
+ 
++#if defined(__FreeBSD__)
++	  if (libhal_device_get_property_bool(hfp_ctx, vol_udi, "volume.is_mounted", NULL))
++#else
+ 	  if (libhal_device_get_property_bool(hfp_ctx, vol_udi, "volume.is_mounted", &hfp_error))
++#endif
+             {
+               DBusMessage *msg = NULL;
+ 	      DBusMessage *reply = NULL;
+@@ -185,7 +199,9 @@ unmount_volumes (void)
+ 	      char **options = NULL;
+ 	      char *devfile;
+ 
++#if !defined(__FreeBSD__)
+ 	      dbus_error_free(&hfp_error);
++#endif
+               hfp_info("Forcing unmount of volume '%s'", vol_udi);
+ 
+ 	      dbus_connection = libhal_ctx_get_dbus_connection(hfp_ctx);
+@@ -265,10 +281,16 @@ poll_for_media (boolean check_only, bool
+       check_lock_state = FALSE;
+ 
+       hfp_info("Checking whether device %s is locked by HAL", addon.device_file);
++#if defined(__FreeBSD__)
++      if (libhal_device_is_locked_by_others(hfp_ctx, hfp_udi, "org.freedesktop.Hal.Device.Storage", NULL))
++#else
+       if (libhal_device_is_locked_by_others(hfp_ctx, hfp_udi, "org.freedesktop.Hal.Device.Storage", &hfp_error))
++#endif
+         {
+           hfp_info("... device %s is locked by HAL", addon.device_file);
++#if !defined(__FreeBSD__)
+ 	  dbus_error_free(&hfp_error);
++#endif
+ 	  is_locked_by_hal = TRUE;
+ 	  update_proc_title(addon.device_file);
+ 	  goto skip_check;
+@@ -278,9 +300,13 @@ poll_for_media (boolean check_only, bool
+           hfp_info("... device %s is not locked by HAL", addon.device_file);
+ 	  is_locked_by_hal = FALSE;
+ 	}
++#if defined(__FreeBSD__)
++      should_poll = libhal_device_get_property_bool(hfp_ctx, hfp_udi, "storage.media_check_enabled", NULL);
++#else
+       dbus_error_free(&hfp_error);
+ 
+       should_poll = libhal_device_get_property_bool(hfp_ctx, hfp_udi, "storage.media_check_enabled", &hfp_error);
++#endif
+       dbus_error_free(&hfp_error);
+       polling_disabled = ! should_poll;
+       update_proc_title(addon.device_file);
+@@ -314,8 +340,12 @@ poll_for_media (boolean check_only, bool
+       unmount_volumes();
+ #endif
+ 
++#if defined(__FreeBSD__)
++      libhal_device_rescan(hfp_ctx, hfp_udi, NULL);
++#else
+       libhal_device_rescan(hfp_ctx, hfp_udi, &hfp_error);
+       dbus_error_free(&hfp_error);
++#endif
+       addon.had_media = has_media;
+ 
+       return TRUE;
+@@ -412,12 +442,19 @@ main (int argc, char **argv)
+     ! strcmp(driver, "cd")))) && ! strcmp(removable, "true");
+   addon.had_media = poll_for_media(TRUE, FALSE);
+ 
++#if defined(__FreeBSD__)
++  if (! libhal_device_addon_is_ready(hfp_ctx, hfp_udi, NULL))
++    goto end;
++
++  syscon = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
++#else
+   if (! libhal_device_addon_is_ready(hfp_ctx, hfp_udi, &hfp_error))
+     goto end;
+   dbus_error_free(&hfp_error);
+ 
+   syscon = dbus_bus_get(DBUS_BUS_SYSTEM, &hfp_error);
+   dbus_error_free(&hfp_error);
++#endif
+   assert(syscon != NULL);
+   dbus_connection_set_exit_on_disconnect(syscon, 0);
+ 
+@@ -452,12 +489,18 @@ main (int argc, char **argv)
+ 				      "    <method name=\"CheckForMedia\">\n"
+ 				      "      <arg name=\"call_had_sideeffect\" direction=\"out\" type=\"b\"/>\n"
+ 				      "    </method>\n",
++#if defined(__FreeBSD__)
++				      NULL))
++#else
+ 				      &hfp_error))
++#endif
+     {
+       hfp_critical("Cannot claim interface 'org.freedesktop.Hal.Device.Storage.Removable'");
+       goto end;
+     }
++#if !defined(__FreeBSD__)
+   dbus_error_free(&hfp_error);
++#endif
+ 
+   while (TRUE)
+     {
diff --git a/hal/patches/patch-hald_freebsd_hf-ata.c b/hal/patches/patch-hald_freebsd_hf-ata.c
new file mode 100644
index 0000000000..720dcac4df
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_hf-ata.c
@@ -0,0 +1,16 @@
+$NetBSD$
+
+--- hald/freebsd/hf-ata.c.orig	2008-08-10 13:50:10.000000000 +0000
++++ hald/freebsd/hf-ata.c
+@@ -30,7 +30,11 @@
+ #include <unistd.h>
+ #include <errno.h>
+ #include <sys/ioctl.h>
++#ifdef __DragonFly__
++#include <sys/nata.h>
++#else
+ #include <sys/ata.h>
++#endif
+ 
+ #include "../logger.h"
+ 
diff --git a/hal/patches/patch-hald_freebsd_hf-devd.c b/hal/patches/patch-hald_freebsd_hf-devd.c
new file mode 100644
index 0000000000..48e81c6127
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_hf-devd.c
@@ -0,0 +1,40 @@
+$NetBSD$
+
+--- hald/freebsd/hf-devd.c.orig	2009-08-24 12:42:29.000000000 +0000
++++ hald/freebsd/hf-devd.c
+@@ -122,7 +122,11 @@ hf_devd_parse_add_remove (const char *ev
+   g_return_val_if_fail(parent != NULL, FALSE);
+ 
+   if ((params_ptr = strchr(event, ' '))
++#if defined(__FreeBSD__)
++      && (at_ptr = strstr(params_ptr, "at "))
++#else
+       && (at_ptr = strstr(params_ptr + 1, " at "))
++#endif
+       && (parent_ptr = strstr(at_ptr + 4, " on ")))
+     {
+       char *params_str;
+@@ -130,7 +134,11 @@ hf_devd_parse_add_remove (const char *ev
+ 
+       *name = g_strndup(event, params_ptr - event);
+       params_str = g_strndup(params_ptr + 1, at_ptr - params_ptr - 1);
++#if defined(__FreeBSD__)
++      at_str = g_strndup(at_ptr + 3, parent_ptr - at_ptr - 3);
++#else
+       at_str = g_strndup(at_ptr + 4, parent_ptr - at_ptr - 4);
++#endif
+       *parent = g_strdup(parent_ptr + 4);
+ 
+       if (! strcmp(*parent, ".")) /* sys/kern/subr_bus.c */
+@@ -398,7 +406,11 @@ hf_devd_event_cb (GIOChannel *source, GI
+       hf_devd_process_event(event);
+       g_free(event);
+     }
++#if defined(__FreeBSD__)
++  else if (status == G_IO_STATUS_AGAIN || status == G_IO_STATUS_EOF)
++#else
+   else if (status == G_IO_STATUS_AGAIN)
++#endif
+     {
+       hf_devd_init();
+       if (hf_devd_inited)
diff --git a/hal/patches/patch-hald_freebsd_hf-pci.c b/hal/patches/patch-hald_freebsd_hf-pci.c
new file mode 100644
index 0000000000..985e21c0ab
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_hf-pci.c
@@ -0,0 +1,16 @@
+$NetBSD$
+
+--- hald/freebsd/hf-pci.c.orig	2009-05-12 12:27:00.000000000 +0000
++++ hald/freebsd/hf-pci.c
+@@ -27,7 +27,11 @@
+ 
+ #include <stdio.h>
+ #include <string.h>
++#ifdef __DragonFly__
++#include <bitstring.h>
++#else
+ #include <sys/bitstring.h>
++#endif
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <unistd.h>
diff --git a/hal/patches/patch-hald_freebsd_hf-storage.c b/hal/patches/patch-hald_freebsd_hf-storage.c
new file mode 100644
index 0000000000..f5695ba439
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_hf-storage.c
@@ -0,0 +1,14 @@
+$NetBSD$
+
+--- hald/freebsd/hf-storage.c.orig	2009-08-24 12:42:29.000000000 +0000
++++ hald/freebsd/hf-storage.c
+@@ -33,6 +33,9 @@
+ #include <sys/param.h>
+ #include <sys/types.h>
+ #include <sys/disklabel.h>
++#ifdef __DragonFly__
++#include <sys/dtype.h>
++#endif
+ 
+ #include "../logger.h"
+ #include "../osspec.h"
diff --git a/hal/patches/patch-hald_freebsd_hf-usb.c b/hal/patches/patch-hald_freebsd_hf-usb.c
new file mode 100644
index 0000000000..abcccc8e9e
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_hf-usb.c
@@ -0,0 +1,47 @@
+$NetBSD$
+
+--- hald/freebsd/hf-usb.c.orig	2009-09-17 13:49:46.000000000 +0000
++++ hald/freebsd/hf-usb.c
+@@ -36,9 +36,13 @@
+ #if __FreeBSD_version >= 800064
+ #include <legacy/dev/usb/usb.h>
+ #else
++#ifdef __DragonFly__
++#include <bus/usb/usb.h>
++#else
+ #include <dev/usb/usb.h>
+ #endif
+ #endif
++#endif
+ 
+ #include "../logger.h"
+ #include "../osspec.h"
+@@ -392,7 +396,11 @@ hf_usb_device_new (HalDevice *parent,
+     hf_devtree_device_set_name(device, di->udi_devnames[0]);
+ 
+   if ((devname = hf_usb_get_devname(di, "ukbd")))	/* USB keyboard */
++#if defined(__FreeBSD__)
++    hf_device_set_input(device, "keyboard", "keys", NULL);
++#else
+     hf_device_set_input(device, "keyboard", "keys", devname);
++#endif
+   else if ((devname = hf_usb_get_devname(di, "ums")))	/* USB mouse */
+     hf_device_set_input(device, "mouse", NULL, devname);
+   else if ((devname = hf_usb_get_devname(di, "uhid")))	/* UHID device */
+@@ -613,7 +621,6 @@ hf_usb_privileged_init (void)
+   if (hf_usb_fd < 0)
+     {
+       HAL_INFO(("unable to open %s: %s", HF_USB_DEVICE, g_strerror(errno)));
+-      return;
+     }
+ 
+   for (i = 0; i < 16; i++)
+@@ -908,6 +915,8 @@ hf_usb_add_webcam_properties (HalDevice 
+ 
+   hal_device_property_set_string(device, "info.category", "video4linux");
+   hal_device_add_capability(device, "video4linux");
++  hal_device_add_capability(device, "video4linux.video_capture");
+   hf_device_property_set_string_printf(device, "video4linux.device", "/dev/video%i", unit);
+   hal_device_property_set_string(device, "info.product", "Video Device");
++  hal_device_property_set_string(device, "video4linux.version", "1");
+ }
diff --git a/hal/patches/patch-hald_freebsd_hf-usb2.c b/hal/patches/patch-hald_freebsd_hf-usb2.c
new file mode 100644
index 0000000000..cebec39bb7
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_hf-usb2.c
@@ -0,0 +1,415 @@
+$NetBSD$
+
+--- hald/freebsd/hf-usb2.c.orig	2009-08-24 12:42:29.000000000 +0000
++++ hald/freebsd/hf-usb2.c
+@@ -22,7 +22,7 @@
+  **************************************************************************/
+ 
+ #ifdef HAVE_CONFIG_H
+-#  include <config.h>
++#include <config.h>
+ #endif
+ 
+ #include <string.h>
+@@ -42,246 +42,200 @@
+ static struct libusb20_backend *hf_usb2_be = NULL;
+ 
+ static void
+-hf_usb2_copy_parent (HalDevice *parent,
+-		     const char *key,
+-		     gpointer user_data)
++hf_usb2_probe_interfaces(HalDevice * parent)
+ {
+-  HalDevice *device;
++	int num_interfaces;
++	int i;
+ 
+-  g_return_if_fail(HAL_IS_DEVICE(parent));
+-  g_return_if_fail(HAL_IS_DEVICE(user_data));
++	g_return_if_fail(HAL_IS_DEVICE(parent));
+ 
+-  device = HAL_DEVICE(user_data);
+-
+-  if (! strncmp(key, "usb_device.", strlen("usb_device.")))
+-    hal_device_copy_property(parent, key, device, key);
++	if (hal_device_property_get_bool(parent, "info.ignore"))
++		return;
++
++	num_interfaces = hal_device_property_get_int(parent,
++	    "usb_device.num_interfaces");
++
++	for (i = 0; i < num_interfaces; i++) {
++		HalDevice *device;
++
++		device = hf_device_new(parent);
++
++		hal_device_property_set_string(device, "info.subsystem", "usb");
++		hal_device_property_set_int(device, "usb.interface.number", i);
++		hal_device_copy_property(parent, "info.product", device, "info.product");
++		hal_device_copy_property(parent, "info.vendor", device, "info.vendor");
++		hal_device_merge_with_rewrite(device, parent, "usb.", "usb_device.");
++
++		if (hf_device_preprobe(device)) {
++			const char *driver, *devname;
++
++			hf_runner_run_sync(device, 0, "hald-probe-usb2-interface", NULL);
++
++			devname = hal_device_property_get_string(device,
++			    "usb.freebsd.devname");
++			if (devname)
++				hf_devtree_device_set_name(device, devname);
++
++			driver = hal_device_property_get_string(device, "freebsd.driver");
++			if (driver) {
++				if (!strcmp(driver, "ukbd"))
++					hf_device_set_input(device, "keyboard", "keys", NULL);
++				else if (!strcmp(driver, "ums") || !strcmp(driver, "atp")) {
++					hf_device_set_input(device, "mouse", NULL, devname);
++					hf_runner_run_sync(device, 0, "hald-probe-mouse", NULL);
++				} else if (!strcmp(driver, "uhid")) {
++					hal_device_property_set_string(device, "info.category",
++					    "hiddev");
++					hal_device_add_capability(device, "hiddev");
++					hf_device_property_set_string_printf(device, "hiddev.device",
++					    "/dev/%s", devname);
++					hal_device_copy_property(device, "info.product", device,
++					    "hiddev.product");
++					hf_runner_run_sync(device, 0, "hald-probe-hiddev", NULL);
++				} else if (!strcmp(driver, "ldev")) {
++					/* Linux driver (webcam) */
++
++					/*
++		                         * XXX This is a hack.  Currently, all ldev devices are
++				         * webcams.  That may not always be the case.  Hopefully,
++				         * when other Linux driver support is added, there will be
++				         * a sysctl or some other way to determine device class.
++			                 */
++					hf_usb_add_webcam_properties(device);
++				} else if (!strcmp(driver, "pwc")) {
++					/* Phillips Web Cam */
++					hf_usb_add_webcam_properties(device);
++				}
++			} else {
++				/* Try and detect webcamd devices. */
++				hf_runner_run_sync(device, 0, "hald-probe-video4linux", NULL);
++			}
++
++			hf_usb_device_compute_udi(device);
++			hf_device_add(device);
++		}
++	}
+ }
+ 
+ static void
+-hf_usb2_probe_interfaces(HalDevice *parent)
++hf_usb2_probe_device(HalDevice * parent, int bus, int addr)
+ {
+-  int num_interfaces;
+-  int i;
++	HalDevice *device;
+ 
+-  g_return_if_fail(HAL_IS_DEVICE(parent));
++	g_return_if_fail(HAL_IS_DEVICE(parent));
+ 
+-  if (hal_device_property_get_bool(parent, "info.ignore"))
+-    return;
++	device = hf_device_new(parent);
+ 
+-  num_interfaces = hal_device_property_get_int(parent,
+-    "usb_device.num_interfaces");
+-
+-  for (i = 0; i < num_interfaces; i++)
+-    {
+-      HalDevice *device;
+-
+-      device = hf_device_new(parent);
+-
+-      hal_device_property_set_string(device, "info.subsystem", "usb");
+-      hal_device_property_set_int(device, "usb.interface.number", i);
+-      hal_device_property_foreach(parent, hf_usb2_copy_parent, device);
+-      hal_device_copy_property(parent, "info.product", device, "info.product");
+-      hal_device_copy_property(parent, "info.vendor", device, "info.vendor");
+-
+-      if (hf_device_preprobe(device))
+-        {
+-          const char *driver, *devname;
+-
+-          hf_runner_run_sync(device, 0, "hald-probe-usb2-interface", NULL);
+-
+-	  devname = hal_device_property_get_string(device,
+-            "usb.freebsd.devname");
+-	  if (devname)
+-            hf_devtree_device_set_name(device, devname);
+-
+-	  driver = hal_device_property_get_string(device, "freebsd.driver");
+-	  if (driver)
+-            {
+-	      if (! strcmp(driver, "ukbd"))
+-                hf_device_set_input(device, "keyboard", NULL);
+-	      else if (! strcmp(driver, "ums"))
+-                {
+-                  hf_device_set_input(device, "mouse", devname);
+-	          hf_runner_run_sync(device, 0, "hald-probe-mouse", NULL);
+-	        }
+-	      else if (! strcmp(driver, "uhid"))
+-                {
+-                  hal_device_property_set_string(device, "info.category",
+-                    "hiddev");
+-	          hal_device_add_capability(device, "hiddev");
+-	          hf_device_property_set_string_printf(device, "hiddev.device",
+-                    "/dev/%s", devname);
+-	          hal_device_copy_property(device, "info.product", device,
+-                    "hiddev.product");
+-	          hf_runner_run_sync(device, 0, "hald-probe-hiddev", NULL);
+-	        }
+-	      else if (! strcmp(driver, "ldev"))
+-                {
+-                  /* Linux driver (webcam) */
+-
+-	          /*
+-                   * XXX This is a hack.  Currently, all ldev devices are
+-		   * webcams.  That may not always be the case.  Hopefully,
+-		   * when other Linux driver support is added, there will be
+-		   * a sysctl or some other way to determine device class.
+-	           */
+-                  hf_usb_add_webcam_properties(device);
+-	        }
+-	      else if (! strcmp(driver, "pwc"))
+-                {
+-                  /* Phillips Web Cam */
+-                  hf_usb_add_webcam_properties(device);
+-	        }
+-	    }
++	hal_device_property_set_string(device, "info.subsystem", "usb_device");
++	hal_device_property_set_int(device, "usb_device.bus_number", bus);
++	hal_device_property_set_int(device, "usb_device.level_number", 1);
++	hal_device_property_set_int(device, "usb_device.port_number", addr);
+ 
+-	  hf_usb_device_compute_udi(device);
+-	  hf_device_add(device);
++	if (hf_device_preprobe(device)) {
++		hf_runner_run_sync(device, 0, "hald-probe-usb2-device", NULL);
++		hf_usb_device_compute_udi(device);
++		hf_device_add(device);
++		hf_usb2_probe_interfaces(device);
+ 	}
+-    }
+ }
+ 
+ static void
+-hf_usb2_probe_device (HalDevice *parent, int bus, int addr)
++hf_usb2_privileged_init(void)
+ {
+-  HalDevice *device;
+-
+-  g_return_if_fail(HAL_IS_DEVICE(parent));
+-
+-  device = hf_device_new(parent);
++	hf_usb2_be = libusb20_be_alloc_default();
++	if (hf_usb2_be == NULL)
++		HAL_INFO(("unable to open USB backend: %s", g_strerror(errno)));
++}
+ 
+-  hal_device_property_set_string(device, "info.subsystem", "usb_device");
+-  hal_device_property_set_int(device, "usb_device.bus_number", bus);
+-  hal_device_property_set_int(device, "usb_device.level_number", addr - 1);
+-  hal_device_property_set_int(device, "usb_device.port_number", addr);
++static void
++hf_usb2_new_device(int bus, int addr)
++{
++	HalDevice *parent;
+ 
+-  if (hf_device_preprobe(device))
+-    {
+-      hf_runner_run_sync(device, 0, "hald-probe-usb2-device", NULL);
+-      hf_usb_device_compute_udi(device);
++	parent = hf_devtree_find_from_info(hald_get_gdl(), "usbus", bus);
+ 
+-      hf_device_add(device);
+-    }
+-  else
+-    return;
++	if (!parent || hal_device_property_get_bool(parent, "info.ignore"))
++		return;
+ 
+-  hf_usb2_probe_interfaces(device);
++	hf_usb2_probe_device(parent, bus, addr);
+ }
+ 
+ static void
+-hf_usb2_privileged_init (void)
++hf_usb2_probe(void)
+ {
+-  hf_usb2_be = libusb20_be_alloc_default();
+-  if (hf_usb2_be == NULL)
+-    HAL_INFO(("unable to open USB backend: %s", g_strerror(errno)));
+-}
++	struct libusb20_device *pdev = NULL;
+ 
+-static void
+-hf_usb2_probe (void)
+-{
+-  struct libusb20_device *pdev = NULL;
++	if (hf_usb2_be == NULL)
++		return;
+ 
+-  if (hf_usb2_be == NULL)
+-    return;
++	while ((pdev = libusb20_be_device_foreach(hf_usb2_be, pdev))) {
++		hf_usb2_new_device(libusb20_dev_get_bus_number(pdev),
++		    libusb20_dev_get_address(pdev));
++	}
+ 
+-  while ((pdev = libusb20_be_device_foreach(hf_usb2_be, pdev)))
+-    {
+-      HalDevice *parent;
+-      int bus, addr;
+-
+-      bus = libusb20_dev_get_bus_number(pdev);
+-      addr = libusb20_dev_get_address(pdev);
+-
+-      if (addr == 1)
+-        parent = hf_devtree_find_parent_from_info(hald_get_gdl(), "usbus", bus);
+-      else
+-        parent = hf_device_store_match(hald_get_gdl(), "usb_device.bus_number",
+-          HAL_PROPERTY_TYPE_INT32, bus, "usb_device.port_number",
+-	  HAL_PROPERTY_TYPE_INT32, addr - 1, NULL);
+-      if (! parent || hal_device_property_get_bool(parent, "info.ignore"))
+-        continue;
++	libusb20_be_free(hf_usb2_be);
++	hf_usb2_be = NULL;
++}
+ 
+-      hf_usb2_probe_device(parent, bus, addr);
+-    }
++static	gboolean
++hf_usb2_devd_notify(const char *system,
++    const char *subsystem,
++    const char *type,
++    const char *data)
++{
++	const char *ugen;
++	int bus;
++	int addr;
++
++	if (!data || strcmp(system, "USB") || strcmp(subsystem, "DEVICE") ||
++	    (strcmp(type, "ATTACH") && strcmp(type, "DETACH")))
++		return FALSE;
++
++	ugen = strstr(data, "ugen=");
++	if (ugen == NULL) {
++		/*
++		 * The following case is not required in
++		 * FreeBSD 8-stable and newer:
++		 */
++		ugen = strstr(data, "cdev=");
++		if (ugen == NULL)
++			return FALSE;
++
++		if (sscanf(ugen, "cdev=ugen%i.%i", &bus, &addr) != 2)
++			return FALSE;
++	} else {
++		if (sscanf(ugen, "ugen=ugen%i.%i", &bus, &addr) != 2)
++			return FALSE;
++	}
+ 
+-  libusb20_be_free(hf_usb2_be);
+-  hf_usb2_be = NULL;
+-}
++	if (strcmp(type, "ATTACH") == 0) {
+ 
+-static gboolean
+-hf_usb2_devd_add (const char *name,
+-		  GHashTable *params,
+-		  GHashTable *at,
+-		  const char *parent)
+-{
+-  HalDevice *parent_device;
+-  int bus, addr, pbus, paddr;
++		HAL_INFO(("received devd attach event, device %s", data));
+ 
+-  if (strncmp(name, "ugen", strlen("ugen")))
+-    return FALSE;
+-  else if (strncmp(parent, "ugen", strlen("ugen")))
+-    return TRUE;
+-
+-  if (sscanf(name, "ugen%i.%i", &bus, &addr) != 2)
+-    return FALSE;
+-
+-  if (sscanf(parent, "ugen%i.%i", &pbus, &paddr) != 2)
+-    return FALSE;
+-
+-  HAL_INFO(("received devd add event for device '%s' with parent '%s'",
+-           name, parent));
+-
+-  parent_device = hf_device_store_match(hald_get_gdl(),
+-    "usb_device.bus_number", HAL_PROPERTY_TYPE_INT32, pbus,
+-    "usb_device.port_number", HAL_PROPERTY_TYPE_INT32, paddr, NULL);
+-
+-  if (parent_device && ! hal_device_property_get_bool(parent_device,
+-      "info.ignore"))
+-    {
+-      hf_usb2_probe_device(parent_device, bus, addr);
+-      return TRUE;
+-    }
++		hf_usb2_new_device(bus, addr);
++	}
++	if (strcmp(type, "DETACH") == 0) {
+ 
+-  return FALSE;
+-}
++		HalDevice *device;
+ 
+-static gboolean
+-hf_usb2_devd_remove (const char *name,
+-		     GHashTable *params,
+-		     GHashTable *at,
+-		     const char *parent)
+-{
+-  HalDevice *device;
+-  int bus, addr;
++		HAL_INFO(("received devd detach event, device %s", data));
+ 
+-  if (strncmp(name, "ugen", strlen("ugen")))
+-    return FALSE;
+-  else if (strncmp(parent, "ugen", strlen("ugen")))
+-    return TRUE;
+-
+-  if (sscanf(name, "ugen%i.%i", &bus, &addr) != 2)
+-    return FALSE;
+-
+-  HAL_INFO(("received devd remove event, device %s", name));
+-
+-  device = hf_device_store_match(hald_get_gdl(), "usb_device.bus_number",
+-    HAL_PROPERTY_TYPE_INT32, bus, "usb_device.port_number",
+-    HAL_PROPERTY_TYPE_INT32, addr, NULL);
+-
+-  if (device)
+-    {
+-      hf_device_remove_tree(device);
+-      return TRUE;
+-    }
++		device = hf_device_store_match(hald_get_gdl(),
++		    "usb_device.bus_number", HAL_PROPERTY_TYPE_INT32, bus,
++		    "usb_device.port_number", HAL_PROPERTY_TYPE_INT32, addr,
++		    "info.bus", HAL_PROPERTY_TYPE_STRING, "usb_device", NULL);
+ 
+-  return FALSE;
++		if (device)
++			hf_device_remove_tree(device);
++	}
++	return TRUE;
+ }
+ 
+ HFHandler hf_usb2_handler = {
+-  .privileged_init	= hf_usb2_privileged_init,
+-  .probe		= hf_usb2_probe
++	.privileged_init = hf_usb2_privileged_init,
++	.probe = hf_usb2_probe
+ };
+ 
+ HFDevdHandler hf_usb2_devd_handler = {
+-  .add =	hf_usb2_devd_add,
+-  .remove =	hf_usb2_devd_remove
++	.notify = hf_usb2_devd_notify
+ };
diff --git a/hal/patches/patch-hald_freebsd_hf-volume.c b/hal/patches/patch-hald_freebsd_hf-volume.c
new file mode 100644
index 0000000000..f8f501c6ab
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_hf-volume.c
@@ -0,0 +1,18 @@
+$NetBSD$
+
+--- hald/freebsd/hf-volume.c.orig	2009-08-24 12:42:29.000000000 +0000
++++ hald/freebsd/hf-volume.c
+@@ -86,9 +86,12 @@ hf_volume_resolve_fuse (const char *spec
+         {
+           if (strcmp(fields[0], special) == 0)
+ 	    {
++	      char *ret;
++
++	      ret = g_strdup(fields[1]);
+ 	      g_strfreev(fields);
+ 	      g_strfreev(lines);
+-	      return g_strdup(fields[1]);
++	      return ret;
+ 	    }
+ 	}
+       g_strfreev(fields);
diff --git a/hal/patches/patch-hald_freebsd_libprobe_hfp-cdrom.c b/hal/patches/patch-hald_freebsd_libprobe_hfp-cdrom.c
new file mode 100644
index 0000000000..1078b086af
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_libprobe_hfp-cdrom.c
@@ -0,0 +1,16 @@
+$NetBSD$
+
+--- hald/freebsd/libprobe/hfp-cdrom.c.orig	2008-08-10 13:50:10.000000000 +0000
++++ hald/freebsd/libprobe/hfp-cdrom.c
+@@ -32,7 +32,11 @@
+ #include <unistd.h>
+ #include <sys/ioctl.h>
+ #include <sys/types.h>
++#ifdef __DragonFly__
++#include <sys/nata.h>
++#else
+ #include <sys/ata.h>
++#endif
+ #include <stdio.h>
+ #include <camlib.h>
+ #include <cam/scsi/scsi_message.h>
diff --git a/hal/patches/patch-hald_freebsd_probing_Makefile.am b/hal/patches/patch-hald_freebsd_probing_Makefile.am
new file mode 100644
index 0000000000..a8ea37df76
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_probing_Makefile.am
@@ -0,0 +1,11 @@
+$NetBSD$
+
+--- hald/freebsd/probing/Makefile.am.orig	2009-08-24 12:42:29.000000000 +0000
++++ hald/freebsd/probing/Makefile.am
+@@ -67,5 +67,5 @@ hald_probe_volume_CPPFLAGS = $(AM_CPPFLA
+ hald_probe_volume_LDADD = \
+ 	@GLIB_LIBS@							\
+ 	@VOLUME_ID_LIBS@						\
+-	-lufs								\
++	@LIBUFS_LIBS@							\
+ 	$(top_builddir)/hald/freebsd/libprobe/libhald_freebsd_probe.la
diff --git a/hal/patches/patch-hald_freebsd_probing_probe-hiddev.c b/hal/patches/patch-hald_freebsd_probing_probe-hiddev.c
new file mode 100644
index 0000000000..b9b0e5abcb
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_probing_probe-hiddev.c
@@ -0,0 +1,18 @@
+$NetBSD$
+
+--- hald/freebsd/probing/probe-hiddev.c.orig	2009-09-17 13:47:14.000000000 +0000
++++ hald/freebsd/probing/probe-hiddev.c
+@@ -31,8 +31,13 @@
+ #include <fcntl.h>
+ #ifndef HAVE_LIBUSB20
+ #include <sys/ioctl.h>
++#ifdef __DragonFly__
++#include <bus/usb/usb.h>
++#include <bus/usb/usbhid.h>
++#else
+ #include <dev/usb/usb.h>
+ #include <dev/usb/usbhid.h>
++#endif
+ #else
+ #if __FreeBSD_version >= 800064
+ #include <dev/usb/usbhid.h>
diff --git a/hal/patches/patch-hald_freebsd_probing_probe-storage.c b/hal/patches/patch-hald_freebsd_probing_probe-storage.c
new file mode 100644
index 0000000000..7759bd12cf
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_probing_probe-storage.c
@@ -0,0 +1,44 @@
+$NetBSD$
+
+--- hald/freebsd/probing/probe-storage.c.orig	2009-08-24 12:42:29.000000000 +0000
++++ hald/freebsd/probing/probe-storage.c
+@@ -32,7 +32,11 @@
+ #include <errno.h>
+ #include <sys/types.h>
+ #include <sys/ioctl.h>
++#ifdef __DragonFly__
++#include <sys/diskslice.h>
++#else
+ #include <sys/disk.h>
++#endif
+ #include <netinet/in.h>
+ #include <glib.h>
+ #include <libvolume_id.h>
+@@ -171,6 +175,9 @@ int
+ main (int argc, char **argv)
+ {
+   char *device_file;
++#ifdef __DragonFly__
++  struct partinfo device_info;
++#endif
+   char *drive_type;
+   char *parent;
+   int ret = 0;			/* no media/filesystem */
+@@ -221,10 +228,17 @@ main (int argc, char **argv)
+ 	  fd = open(device_file, O_RDONLY | O_NONBLOCK);
+ 	  if (fd > -1)
+             {
++#ifdef __DragonFly__
++              if (ioctl (fd, DIOCGPART, &device_info) == 0)
++                {
++                  libhal_device_set_property_uint64(hfp_ctx, hfp_udi, "storage.removable.media_size", device_info.media_size, &hfp_error);
++                }
++#else
+               if (ioctl (fd, DIOCGMEDIASIZE, &size) == 0)
+                 {
+                   libhal_device_set_property_uint64(hfp_ctx, hfp_udi, "storage.removable.media_size", size, &hfp_error);
+ 		}
++#endif
+ 	      close(fd);
+ 	    }
+ 	  ret = 2;		/* has media */
diff --git a/hal/patches/patch-hald_freebsd_probing_probe-usb2-device.c b/hal/patches/patch-hald_freebsd_probing_probe-usb2-device.c
new file mode 100644
index 0000000000..2f45baf299
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_probing_probe-usb2-device.c
@@ -0,0 +1,44 @@
+$NetBSD$
+
+--- hald/freebsd/probing/probe-usb2-device.c.orig	2009-08-24 12:42:29.000000000 +0000
++++ hald/freebsd/probing/probe-usb2-device.c
+@@ -147,16 +147,16 @@ main(int argc, char **argv)
+ 	    speed = 12.0;
+ 	    bcdspeed = 0x01200;
+ 	    break;
+-	  case LIBUSB20_SPEED_HIGH:
++	  case LIBUSB20_SPEED_VARIABLE:
+ 	    speed = 480.0;
+ 	    bcdspeed = 0x48000;
+ 	    break;
+ 	  case LIBUSB20_SPEED_SUPER:
+-	    speed = 4800.0;
+-	    bcdspeed = 0x480000;
++	    speed = 5000.0;
++	    bcdspeed = 0x500000;
+ 	    break;
+ 	  default:
+-	    ;
++	    break;
+ 	}
+ 
+       libhal_device_set_property_double(hfp_ctx, hfp_udi, "usb_device.speed",
+@@ -169,6 +169,9 @@ main(int argc, char **argv)
+           case UD_USB_2_0:
+             version = 2.0;
+ 	    break;
++	  case 0x0250:
++	    version = 2.5;
++	    break;
+ 	  case UD_USB_3_0:
+ 	    version = 3.0;
+ 	    break;
+@@ -184,7 +187,7 @@ main(int argc, char **argv)
+       libhal_device_set_property_int(hfp_ctx, hfp_udi,
+         "usb_device.vendor_id", di.udi_vendorNo, &hfp_error);
+       libhal_device_set_property_int(hfp_ctx, hfp_udi,
+-        "usb_device.device_revision_bcd", ddesc->bcdUSB, &hfp_error);
++        "usb_device.device_revision_bcd", ddesc->bcdDevice, &hfp_error);
+       libhal_device_set_property_string(hfp_ctx, hfp_udi,
+         "usb_device.serial", di.udi_serial, &hfp_error);
+       libhal_device_set_property_string(hfp_ctx, hfp_udi,
diff --git a/hal/patches/patch-hald_freebsd_probing_probe-usb2-interface.c b/hal/patches/patch-hald_freebsd_probing_probe-usb2-interface.c
new file mode 100644
index 0000000000..a6b8acf70a
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_probing_probe-usb2-interface.c
@@ -0,0 +1,18 @@
+$NetBSD$
+
+--- hald/freebsd/probing/probe-usb2-interface.c.orig	2009-08-24 12:42:29.000000000 +0000
++++ hald/freebsd/probing/probe-usb2-interface.c
+@@ -58,11 +58,11 @@ main(int argc, char **argv)
+   if (pbe == NULL)
+     goto end;
+ 
+-  busstr = getenv("HAL_PROP_USB_DEVICE_BUS_NUMBER");
++  busstr = getenv("HAL_PROP_USB_BUS_NUMBER");
+   if (! busstr)
+     goto end;
+ 
+-  addrstr = getenv("HAL_PROP_USB_DEVICE_PORT_NUMBER");
++  addrstr = getenv("HAL_PROP_USB_PORT_NUMBER");
+   if (! addrstr)
+     goto end;
+ 
diff --git a/hal/patches/patch-hald_freebsd_probing_probe-volume.c b/hal/patches/patch-hald_freebsd_probing_probe-volume.c
new file mode 100644
index 0000000000..32636fa56b
--- /dev/null
+++ b/hal/patches/patch-hald_freebsd_probing_probe-volume.c
@@ -0,0 +1,127 @@
+$NetBSD$
+
+--- hald/freebsd/probing/probe-volume.c.orig	2009-09-17 13:45:09.000000000 +0000
++++ hald/freebsd/probing/probe-volume.c
+@@ -33,7 +33,11 @@
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include <sys/ioctl.h>
++#ifdef __DragonFly__
++#include <sys/diskslice.h>
++#else
+ #include <sys/disk.h>
++#endif
+ #include <sys/cdio.h>
+ #include <sys/param.h>
+ #include <sys/mount.h>
+@@ -41,7 +45,11 @@
+ #include <ufs/ufs/ufsmount.h>
+ #include <ufs/ufs/dinode.h>
+ #include <ufs/ffs/fs.h>
++#ifdef __DragonFly__
++#include <ufs/ufs/ufs_types.h>
++#else
+ #include <libufs.h>
++#endif
+ #include <isofs/cd9660/iso.h>
+ #include <glib.h>
+ #include <libvolume_id.h>
+@@ -332,6 +340,9 @@ main (int argc, char **argv)
+   gboolean is_blank = FALSE;
+   const char *usage;
+   char *label;
++#ifdef __DragonFly__
++  struct partinfo device_info;
++#endif
+   unsigned int sector_size = 0;
+   off_t media_size = 0;
+ 
+@@ -371,7 +382,12 @@ main (int argc, char **argv)
+       is_blank = (! has_audio && ! has_data);
+     }
+ 
++#ifdef __DragonFly__
++  ioctl(fd, DIOCGPART, &device_info);
++  media_size = device_info.media_size;
++#else
+   ioctl(fd, DIOCGMEDIASIZE, &media_size);
++#endif
+ 
+   /*
+    * We only check for filesystems if the volume has no children,
+@@ -563,16 +579,35 @@ main (int argc, char **argv)
+ 
+   if (vid && ! strcmp (vid->type, "ufs"))
+     {
++#ifdef __DragonFly__
++      struct fs fs;
++      int rfd;
++      ssize_t nr;
++      
++      if ((rfd = open(device_file, O_RDONLY)) >= 0) {
++          lseek(rfd, (off_t) SBOFF, SEEK_SET);
++          
++          nr = read(rfd, &fs, (size_t) SBSIZE);
++          close(rfd);
++      }
++          
++      if (nr == (ssize_t) SBSIZE)
++#else
+       struct uufsd ufsdisk;
+ 
+       if (ufs_disk_fillout(&ufsdisk, device_file) == 0)
++#endif
+         {
+ 	  char ufsid[64];
+ 	  char **ufs_devs = NULL;
+ 	  int num_udis;
+ 	  int i;
+ 
++#ifdef __DragonFly__
++          snprintf(ufsid, sizeof(ufsid), "%08x%08x", fs.fs_id[0], fs.fs_id[1]);
++#else
+ 	  snprintf(ufsid, sizeof(ufsid), "%08x%08x", ufsdisk.d_fs.fs_id[0], ufsdisk.d_fs.fs_id[1]);
++#endif
+ 	  libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.freebsd.ufsid", ufsid, &hfp_error);
+ 	  ufs_devs = libhal_manager_find_device_string_match(hfp_ctx,
+ 			  				     "volume.freebsd.ufsid",
+@@ -582,7 +617,11 @@ main (int argc, char **argv)
+ 	  dbus_error_free(&hfp_error);
+ 	  for (i = 0; i < num_udis; i++)
+             {
++#if defined(__FreeBSD__)
++	      if (ufs_devs[i] != NULL && strcmp(ufs_devs[i], hfp_udi))
++#else
+               if (ufs_devs[i] != NULL)
++#endif
+                 {
+                   gboolean mounted;
+ 
+@@ -592,12 +631,15 @@ main (int argc, char **argv)
+ 		    {
+                       libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.ignore", TRUE, &hfp_error);
+ 		      dbus_error_free(&hfp_error);
++		      break;
+ 		    }
+ 		}
+ 	    }
+ 	  if (ufs_devs)
+ 	    libhal_free_string_array(ufs_devs);
++#ifndef __DragonFly__
+ 	  ufs_disk_close(&ufsdisk);
++#endif
+ 	}
+     }
+ 
+@@ -628,7 +670,11 @@ main (int argc, char **argv)
+ 
+   libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.uuid", vid ? vid->uuid : "", &hfp_error);
+ 
++#ifdef __DragonFly__
++  sector_size = device_info.media_blksize;
++#else
+   ioctl(fd, DIOCGSECTORSIZE, &sector_size);
++#endif
+ 
+   if (sector_size != 0)
+     libhal_device_set_property_uint64(hfp_ctx, hfp_udi, "volume.block_size", sector_size, &hfp_error);
diff --git a/hal/patches/patch-hald_linux_addons_addon-acpi-buttons-toshiba.c b/hal/patches/patch-hald_linux_addons_addon-acpi-buttons-toshiba.c
new file mode 100644
index 0000000000..23bba951a5
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-acpi-buttons-toshiba.c
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-acpi-buttons-toshiba.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-acpi-buttons-toshiba.c
+@@ -40,7 +40,7 @@ else
+ #include <string.h>
+ #include <unistd.h>
+ 
+-#include <glib/gmain.h>
++#include <glib.h>
+ 
+ #include "libhal/libhal.h"
+ #include "../../logger.h"
diff --git a/hal/patches/patch-hald_linux_addons_addon-cpufreq.c b/hal/patches/patch-hald_linux_addons_addon-cpufreq.c
new file mode 100644
index 0000000000..62ad064e70
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-cpufreq.c
@@ -0,0 +1,12 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-cpufreq.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-cpufreq.c
+@@ -32,7 +32,6 @@
+ #include <unistd.h>
+ #include <signal.h>
+ #include <getopt.h>
+-#include <glib/gprintf.h>
+ 
+ #include "addon-cpufreq.h"
+ #include "addon-cpufreq-userspace.h"
diff --git a/hal/patches/patch-hald_linux_addons_addon-dell-backlight.cpp b/hal/patches/patch-hald_linux_addons_addon-dell-backlight.cpp
new file mode 100644
index 0000000000..103269870c
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-dell-backlight.cpp
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-dell-backlight.cpp.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-dell-backlight.cpp
+@@ -29,7 +29,7 @@
+ 
+ #include <string.h>
+ 
+-#include <glib/gmain.h>
++#include <glib.h>
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
diff --git a/hal/patches/patch-hald_linux_addons_addon-generic-backlight.c b/hal/patches/patch-hald_linux_addons_addon-generic-backlight.c
new file mode 100644
index 0000000000..eed39c0b76
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-generic-backlight.c
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-generic-backlight.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-generic-backlight.c
+@@ -35,7 +35,7 @@
+ #include <sys/stat.h>
+ #include <unistd.h> 
+ 
+-#include <glib/gmain.h>
++#include <glib.h>
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
diff --git a/hal/patches/patch-hald_linux_addons_addon-imac-backlight.c b/hal/patches/patch-hald_linux_addons_addon-imac-backlight.c
new file mode 100644
index 0000000000..107750b83c
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-imac-backlight.c
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-imac-backlight.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-imac-backlight.c
+@@ -29,7 +29,7 @@
+ #include <stdlib.h>
+ #include <sys/io.h>
+ 
+-#include <glib/gmain.h>
++#include <glib.h>
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
diff --git a/hal/patches/patch-hald_linux_addons_addon-input.c b/hal/patches/patch-hald_linux_addons_addon-input.c
new file mode 100644
index 0000000000..1e2429b460
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-input.c
@@ -0,0 +1,14 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-input.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-input.c
+@@ -41,8 +41,7 @@
+ #else
+   #include <linux/input.h>
+ #endif
+-#include <glib/gmain.h>
+-#include <glib/gprintf.h>
++#include <glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
+ #include "libhal/libhal.h"
diff --git a/hal/patches/patch-hald_linux_addons_addon-ipw-killswitch.c b/hal/patches/patch-hald_linux_addons_addon-ipw-killswitch.c
new file mode 100644
index 0000000000..cb2ce9564a
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-ipw-killswitch.c
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-ipw-killswitch.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-ipw-killswitch.c
+@@ -36,8 +36,6 @@
+ #include <unistd.h> 
+ 
+ #include <glib.h>
+-#include <glib/gmain.h>
+-#include <glib/gstdio.h>
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
diff --git a/hal/patches/patch-hald_linux_addons_addon-leds.c b/hal/patches/patch-hald_linux_addons_addon-leds.c
new file mode 100644
index 0000000000..f7d76cd4b2
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-leds.c
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-leds.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-leds.c
+@@ -36,8 +36,6 @@
+ #include <unistd.h> 
+ 
+ #include <glib.h>
+-#include <glib/gmain.h>
+-#include <glib/gstdio.h>
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
diff --git a/hal/patches/patch-hald_linux_addons_addon-macbookpro-backlight.c b/hal/patches/patch-hald_linux_addons_addon-macbookpro-backlight.c
new file mode 100644
index 0000000000..5388499748
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-macbookpro-backlight.c
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-macbookpro-backlight.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-macbookpro-backlight.c
+@@ -39,7 +39,7 @@
+ #include <pci/pci.h>
+ #include <unistd.h> 
+ 
+-#include <glib/gmain.h>
++#include <glib.h>
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
diff --git a/hal/patches/patch-hald_linux_addons_addon-omap-backlight.c b/hal/patches/patch-hald_linux_addons_addon-omap-backlight.c
new file mode 100644
index 0000000000..4ef43b78da
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-omap-backlight.c
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-omap-backlight.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-omap-backlight.c
+@@ -41,7 +41,7 @@
+ #include <fcntl.h>
+ #include <unistd.h> 
+ 
+-#include <glib/gmain.h>
++#include <glib.h>
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
diff --git a/hal/patches/patch-hald_linux_addons_addon-rfkill-killswitch.c b/hal/patches/patch-hald_linux_addons_addon-rfkill-killswitch.c
new file mode 100644
index 0000000000..970faa913c
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-rfkill-killswitch.c
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-rfkill-killswitch.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-rfkill-killswitch.c
+@@ -36,8 +36,6 @@
+ #include <unistd.h> 
+ 
+ #include <glib.h>
+-#include <glib/gmain.h>
+-#include <glib/gstdio.h>
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
diff --git a/hal/patches/patch-hald_linux_addons_addon-storage.c b/hal/patches/patch-hald_linux_addons_addon-storage.c
new file mode 100644
index 0000000000..404fc0e41e
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-storage.c
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-storage.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-storage.c
+@@ -39,7 +39,7 @@
+ #include <string.h>
+ #include <sys/ioctl.h>
+ #include <unistd.h>
+-#include <glib/gmain.h>
++#include <glib.h>
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
diff --git a/hal/patches/patch-hald_linux_addons_addon-usb-csr.c b/hal/patches/patch-hald_linux_addons_addon-usb-csr.c
new file mode 100644
index 0000000000..85835205fa
--- /dev/null
+++ b/hal/patches/patch-hald_linux_addons_addon-usb-csr.c
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- hald/linux/addons/addon-usb-csr.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/addons/addon-usb-csr.c
+@@ -29,7 +29,7 @@
+ #include <string.h>
+ #include <usb.h>
+ 
+-#include <glib/gmain.h>
++#include <glib.h>
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
diff --git a/hal/patches/patch-hald_linux_probing_probe-video4linux.c b/hal/patches/patch-hald_linux_probing_probe-video4linux.c
new file mode 100644
index 0000000000..0883614e77
--- /dev/null
+++ b/hal/patches/patch-hald_linux_probing_probe-video4linux.c
@@ -0,0 +1,43 @@
+$NetBSD$
+
+--- hald/linux/probing/probe-video4linux.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ hald/linux/probing/probe-video4linux.c
+@@ -30,7 +30,9 @@
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <sys/ioctl.h>
++#ifdef HAVE_LINUX_VIDEODEV_H
+ #include <linux/videodev.h>
++#endif
+ #include <linux/videodev2.h>
+ #include <errno.h>
+ #include <fcntl.h>
+@@ -50,7 +52,9 @@ main (int argc, char *argv[])
+ 	int ret = -1;
+ 	char *udi;
+ 	char *device_file;
++#ifdef HAVE_LINUX_VIDEODEV_H
+ 	struct video_capability v1cap;
++#endif
+ 	struct v4l2_capability v2cap;
+ 	LibHalContext *ctx = NULL;
+ 	LibHalChangeSet *cset;
+@@ -106,7 +110,9 @@ main (int argc, char *argv[])
+ 			LIBHAL_FREE_DBUS_ERROR (&error);
+ 			libhal_device_add_capability (ctx, udi, "video4linux.radio", &error);
+ 		}
+-	} else {
++	}
++#ifdef HAVE_LINUX_VIDEODEV_H
++	else {
+ 		HAL_DEBUG (("ioctl VIDIOC_QUERYCAP failed"));
+ 
+ 		if (ioctl (fd, VIDIOCGCAP, &v1cap) == 0) {
+@@ -133,6 +139,7 @@ main (int argc, char *argv[])
+ 			HAL_DEBUG (("ioctl VIDIOCGCAP failed"));
+ 		}
+ 	}
++#endif
+ 
+ 	LIBHAL_FREE_DBUS_ERROR (&error);
+ 	libhal_device_commit_changeset (ctx, cset, &error);
diff --git a/hal/patches/patch-hald_netbsd_devinfo__mass.c b/hal/patches/patch-hald_netbsd_devinfo__mass.c
new file mode 100644
index 0000000000..0fa1e87ea8
--- /dev/null
+++ b/hal/patches/patch-hald_netbsd_devinfo__mass.c
@@ -0,0 +1,12 @@
+$NetBSD$
+
+--- hald/netbsd/devinfo_mass.c.orig	2018-09-22 22:22:46.346651150 +0000
++++ hald/netbsd/devinfo_mass.c
+@@ -41,6 +41,7 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <paths.h>
++#include <sys/stat.h>
+ #include <unistd.h>
+ 
+ #include "../osspec.h"
diff --git a/hal/patches/patch-hald_netbsd_drvctl.c b/hal/patches/patch-hald_netbsd_drvctl.c
new file mode 100644
index 0000000000..a4dd73a0d6
--- /dev/null
+++ b/hal/patches/patch-hald_netbsd_drvctl.c
@@ -0,0 +1,111 @@
+$NetBSD$
+
+--- hald/netbsd/drvctl.c.orig	2020-09-28 21:35:53.183246491 +0000
++++ hald/netbsd/drvctl.c
+@@ -25,6 +25,7 @@
+ #include <sys/stat.h>
+ #include <sys/drvctlio.h>
+ #include <glib.h>
++#include <glib/gprintf.h>
+ 
+ #include "../osspec.h"
+ #include "../logger.h"
+@@ -46,22 +47,19 @@ static void	drvctl_dev_branch(gchar *);
+ static int drvctl_fd;
+ static GIOChannel *drvctl_iochannel;
+ 
++#define	FIFODEV	"/tmp/halfifo"
+ gboolean
+ drvctl_init(void)
+ {
+-	drvctl_fd = open (DRVCTLDEV, O_RDWR);
+-	if (drvctl_fd == -1) {
+-		HAL_INFO (("open(%s, O_RDWR) failed: %s", DRVCTLDEV, strerror(errno)));
+-		return FALSE;
+-	}
++	GError           *rc=NULL;
+ 
+-        drvctl_iochannel = g_io_channel_unix_new (drvctl_fd);
++	drvctl_fd = open (DRVCTLDEV, O_RDWR);
++        drvctl_iochannel = g_io_channel_new_file(FIFODEV,"r",&rc);
+ 	if (drvctl_iochannel == NULL) {
+-                HAL_INFO (("g_io_channel_unix_new failed"));
++                HAL_INFO (("g_io_channel_new_file failed"));
+ 		return FALSE;
+ 	}
+         g_io_add_watch (drvctl_iochannel, G_IO_IN, drvctl_iochannel_data, NULL);
+-
+ 	return TRUE;
+ }
+ 
+@@ -76,37 +74,22 @@ drvctl_iochannel_data (GIOChannel *sourc
+                     GIOCondition condition,
+                     gpointer user_data)
+ {
+-	prop_dictionary_t ev;
+-	const char *event, *device;
+-	int res;
+-
+-	HAL_INFO (("drvctl_iochannel_data"));
+-
+-	res = prop_dictionary_recv_ioctl (drvctl_fd, DRVGETEVENT, &ev);
+-	if (res) {
+-		HAL_WARNING (("DRVGETEVENT failed: %s", strerror(errno)));
+-		return FALSE;
+-	}
+-
+-	if (!prop_dictionary_get_cstring_nocopy (ev, "event", &event)) {
+-		HAL_WARNING (("DRVGETEVENT missing \"event\" parameter"));
+-		goto done;
+-	}
+-	if (!prop_dictionary_get_cstring_nocopy (ev, "device", &device)) {
+-		HAL_WARNING (("DRVGETEVENT missing \"device\" parameter"));
+-		goto done;
+-	}
+-
+-	HAL_INFO (("DRVGETEVENT event=%s device=%s", event, device));
+-
+-	if (strcmp (event, "device-attach") == 0) {
+-		drvctl_dev_add (device);
+-	} else {
+-		drvctl_dev_remove (device);
+-	}
+-
+-done:
+-	prop_object_release(ev);
++	GError		*rc=NULL;
++	gint		i;
++	struct timeval	timeout={1,0};
++	gchar		**vect,*line;
++
++	g_io_channel_read_line(source,&line,NULL,NULL,&rc);
++	if (!line)
++		return TRUE;
++	g_strstrip(line);
++	vect=g_strsplit(line," ",3);
++	if (! strcmp (vect[0], "device-attach")) 
++		drvctl_dev_add (vect[1]);
++	else if (! strcmp (vect[0], "device-detach"))
++		drvctl_dev_remove (vect[1]);
++	g_strfreev(vect);
++	g_free(line);
+ 	return TRUE;
+ }
+ 
+@@ -179,6 +162,7 @@ drvctl_list(const gchar *name, struct de
+ 	}
+ 	if (children != laa->l_children)
+ 		HAL_WARNING (("DRVLISTDEV/3 expected %d children, got %d", children, laa->l_childname));
++	return 0;
+ }
+ 
+ gboolean
+@@ -187,7 +171,7 @@ drvctl_find_device(const gchar *devnode,
+ 	prop_dictionary_t command_dict;
+ 	prop_dictionary_t args_dict;
+ 	prop_dictionary_t results_dict;
+-	int err;
++	signed char err;
+ 	   
+ 	command_dict = prop_dictionary_create ();
+ 	args_dict = prop_dictionary_create ();
diff --git a/hal/patches/patch-libhal_libhal.c b/hal/patches/patch-libhal_libhal.c
new file mode 100644
index 0000000000..d5bc719699
--- /dev/null
+++ b/hal/patches/patch-libhal_libhal.c
@@ -0,0 +1,15 @@
+$NetBSD$
+
+--- libhal/libhal.c.orig	2009-08-24 12:42:30.000000000 +0000
++++ libhal/libhal.c
+@@ -4121,8 +4121,10 @@ out:
+ static void
+ libhal_changeset_append (LibHalChangeSet *changeset, LibHalChangeSetElement *elem)
+ {
++#if !defined(__SUNPRO_C)
+ 	LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", (void) NULL );
+ 	LIBHAL_CHECK_PARAM_VALID(elem, "*elem", (void) NULL);
++#endif
+ 
+ 	if (changeset->head == NULL) {
+ 		changeset->head = elem;
diff --git a/hal/patches/patch-policy_Makefile.am b/hal/patches/patch-policy_Makefile.am
new file mode 100644
index 0000000000..18c9b592a3
--- /dev/null
+++ b/hal/patches/patch-policy_Makefile.am
@@ -0,0 +1,13 @@
+$NetBSD$
+
+--- policy/Makefile.am.orig	2009-01-21 00:14:28.000000000 +0000
++++ policy/Makefile.am
+@@ -20,7 +20,7 @@ check:
+             echo -n "Validate PolicyKit policy in $$f : "; \
+             $(POLKIT_POLICY_FILE_VALIDATE) $(srcdir)/$$f ; \
+ 	    ret=$$?; \
+-            if  [ "$$ret" == "0" ]; \
++            if  [ "$$ret" = "0" ]; \
+ 	      then \
+                 echo ok; \
+             else \
diff --git a/hal/patches/patch-tools_Makefile.am b/hal/patches/patch-tools_Makefile.am
new file mode 100644
index 0000000000..3e0a5a28c5
--- /dev/null
+++ b/hal/patches/patch-tools_Makefile.am
@@ -0,0 +1,30 @@
+$NetBSD$
+
+--- tools/Makefile.am.orig	2009-11-09 15:33:53.000000000 +0000
++++ tools/Makefile.am
+@@ -8,8 +8,11 @@ endif
+ if HALD_COMPILE_FREEBSD
+ SUBDIRS += freebsd
+ endif
++if HALD_COMPILE_NETBSD
++SUBDIRS += netbsd
++endif
+ 
+-DIST_SUBDIRS = freebsd linux
++DIST_SUBDIRS = freebsd linux netbsd
+ 
+ AM_CPPFLAGS = \
+ 	-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
+@@ -80,7 +83,11 @@ if BUILD_KEYMAPS
+ 
+ if HAVE_GPERF
+ hal-setup-keymap-keys.txt: @LINUX_INPUT_H@
+-	awk '/^#define.*KEY_/ { if ($$2 != "KEY_MAX") { print substr($$2, 5) } }' < $< > $@
++	if test -f /usr/include/linux/input-event-codes.h; then \
++		awk '/^#define.*KEY_/ { if ($$2 != "KEY_MAX") { print substr($$2, 5) } }' < /usr/include/linux/input-event-codes.h > $@; \
++	else \
++		awk '/^#define.*KEY_/ { if ($$2 != "KEY_MAX") { print substr($$2, 5) } }' < $< > $@; \
++	fi
+ 
+ hal-setup-keymap-hash-name.gperf: hal-setup-keymap-keys.txt
+ 	awk 'BEGIN{ print "struct key { const char* name; unsigned short id; };"; print "%null-strings"; print "%%";} { print $$1 ", KEY_" $$1 }' < $< > $@
diff --git a/hal/patches/patch-tools_hal-luks-setup b/hal/patches/patch-tools_hal-luks-setup
new file mode 100644
index 0000000000..7c3c463312
--- /dev/null
+++ b/hal/patches/patch-tools_hal-luks-setup
@@ -0,0 +1,22 @@
+$NetBSD$
+
+--- tools/hal-luks-setup.orig	2008-08-10 13:50:10.000000000 +0000
++++ tools/hal-luks-setup
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ # Copyright (C) 2005 W. Michael Petullo <mike%flyn.org@localhost>
+ # Copyright (C) 2006 David Zeuthen <davidz%redhat.com@localhost>
+@@ -44,9 +44,9 @@ if [ -n "$HAL_METHOD_INVOKED_BY_SYSTEMBU
+ fi
+ 
+ IS_HOTPLUGGABLE=`hal-get-property --udi $HAL_PROP_BLOCK_STORAGE_DEVICE --key storage.hotpluggable`
+-if [ "$IS_HOTPLUGGABLE" == "true" ] ; then
++if [ "$IS_HOTPLUGGABLE" = "true" ] ; then
+     ACTION="org.freedesktop.hal.storage.crypto-setup-removable"
+-elif [ "$IS_HOTPLUGGABLE" == "false" ] ; then
++elif [ "$IS_HOTPLUGGABLE" = "false" ] ; then
+     ACTION="org.freedesktop.hal.storage.crypto-setup-fixed"
+ else
+     unknown_error
diff --git a/hal/patches/patch-tools_hal-luks-teardown b/hal/patches/patch-tools_hal-luks-teardown
new file mode 100644
index 0000000000..1b7e274a34
--- /dev/null
+++ b/hal/patches/patch-tools_hal-luks-teardown
@@ -0,0 +1,22 @@
+$NetBSD$
+
+--- tools/hal-luks-teardown.orig	2008-08-10 13:50:10.000000000 +0000
++++ tools/hal-luks-teardown
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ 
+ # Copyright (C) 2005 W. Michael Petullo <mike%flyn.org@localhost>
+ # Copyright (C) 2006 David Zeuthen <davidz%redhat.com@localhost>
+@@ -47,9 +47,9 @@ fi
+ # TODO: this is a little sketchy; we should check for hal-storage-crypto-teardown-others?
+ #
+ IS_HOTPLUGGABLE=`hal-get-property --udi $HAL_PROP_BLOCK_STORAGE_DEVICE --key storage.hotpluggable`
+-if [ "$IS_HOTPLUGGABLE" == "true" ] ; then
++if [ "$IS_HOTPLUGGABLE" = "true" ] ; then
+     ACTION="org.freedesktop.hal.storage.crypto-setup-removable"
+-elif [ "$IS_HOTPLUGGABLE" == "false" ] ; then
++elif [ "$IS_HOTPLUGGABLE" = "false" ] ; then
+     ACTION="org.freedesktop.hal.storage.crypto-setup-fixed"
+ else
+     unknown_error
diff --git a/hal/patches/patch-tools_hal-storage-mount.c b/hal/patches/patch-tools_hal-storage-mount.c
new file mode 100644
index 0000000000..9111f77992
--- /dev/null
+++ b/hal/patches/patch-tools_hal-storage-mount.c
@@ -0,0 +1,134 @@
+$NetBSD$
+
+--- tools/hal-storage-mount.c.orig	2009-05-27 20:26:03.000000000 +0000
++++ tools/hal-storage-mount.c
+@@ -31,7 +31,7 @@
+ #include <string.h>
+ #include <glib.h>
+ #include <glib/gstdio.h>
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+ #include <fstab.h>
+ #include <sys/param.h>
+ #include <sys/ucred.h>
+@@ -41,6 +41,14 @@
+ #elif sun
+ #include <sys/mnttab.h>
+ #include <sys/vfstab.h>
++#elif __NetBSD__
++#include <fstab.h>
++#include <sys/param.h>
++#include <sys/mount.h>
++#include <fcntl.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#include <pwd.h>
+ #else
+ #include <mntent.h>
+ #endif
+@@ -54,10 +62,14 @@
+ 
+ #include "hal-storage-shared.h"
+ 
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__DragonFly__)
+ #define MOUNT		"/sbin/mount"
+ #define MOUNT_OPTIONS	"noexec,nosuid"
+ #define MOUNT_TYPE_OPT	"-t"
++#elif __NetBSD__
++#define MOUNT		"/sbin/mount"
++#define MOUNT_OPTIONS	"noexec,nosuid,nodev"
++#define	MOUNT_TYPE_OPT	"-t"
+ #elif sun
+ #define MOUNT		"/sbin/mount"
+ #define MOUNT_OPTIONS	"noexec,nosuid"
+@@ -421,7 +433,7 @@ device_is_mounted (const char *device, c
+ static const char *
+ map_fstype (const char *fstype)
+ {
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__DragonFly__)
+ 	if (! strcmp (fstype, "iso9660"))
+ 		return "cd9660";
+ 	else if (! strcmp (fstype, "ext2"))
+@@ -430,6 +442,13 @@ map_fstype (const char *fstype)
+ 		return "ext2fs";
+ 	else if (! strcmp (fstype, "vfat"))
+ 		return "msdosfs";
++#elif __NetBSD__
++	if (! strcmp (fstype, "iso9660"))
++		return "cd9660";
++	else if (! strcmp (fstype, "ext2"))
++		return "ext2fs";
++	else if (! strcmp (fstype, "vfat"))
++		return "msdos";
+ #elif sun
+ 	if (! strcmp (fstype, "iso9660"))
+ 		return "hsfs";
+@@ -471,11 +490,16 @@ handle_mount (LibHalContext *hal_ctx, 
+ 	gboolean explicit_mount_point_given;
+ 	gboolean found_alternative_fstype = FALSE;
+ 	const char *end;
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__NetBSD__)
+ 	struct passwd *pw;
+ 	uid_t calling_uid;
+ 	gid_t calling_gid;
+ #endif
++	gboolean have_rump = FALSE;
++#ifdef __NetBSD__
++	char *rump_cmd;
++	struct stat st;
++#endif
+ 	const char *label;
+ 	const char *uuid;
+ 
+@@ -646,8 +670,6 @@ handle_mount (LibHalContext *hal_ctx, 
+ 	/* construct arguments to mount */
+ 	na = 0;
+ 	
+-	args[na++] = MOUNT;
+-
+ 	if (strlen (mount_fstype) > 0) {
+ 		mount_do_fstype = (char *) map_fstype (mount_fstype);
+ 		if (volume && strcmp(mount_do_fstype, mount_fstype) == 0) {
+@@ -797,8 +819,28 @@ handle_mount (LibHalContext *hal_ctx, 
+ 		}
+ 	}
+ 
+-	args[na++] = MOUNT_TYPE_OPT;
+-	args[na++] = mount_do_fstype;
++#ifdef __NetBSD__
++	rump_cmd = g_strdup_printf ("/usr/sbin/rump_%s", mount_do_fstype);
++	if (stat (rump_cmd, &st) == 0) {
++		int rump_fd = open ("/dev/puffs", O_RDONLY);
++		if (rump_fd >= 0) {
++			have_rump = TRUE;
++			close (rump_fd);
++		}
++	}
++
++	/* XXX rump_* option handling is different, disable for now */
++	have_rump = FALSE;
++
++	if (have_rump == TRUE)
++		args[na++] = rump_cmd;
++	else
++#endif
++	{
++		args[na++] = MOUNT;
++		args[na++] = MOUNT_TYPE_OPT;
++		args[na++] = mount_do_fstype;
++	}
+ 
+ 	args[na++] = "-o";
+ #ifdef HAVE_UMOUNT_HAL
+@@ -869,7 +911,7 @@ handle_mount (LibHalContext *hal_ctx, 
+ 			unknown_error ("Cannot create mount directory");
+ 		}
+ 		
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__NetBSD__)
+ 		calling_uid = (uid_t) strtol (invoked_by_uid, (char **) NULL, 10);
+ 		pw = getpwuid (calling_uid);
+ 		if (pw != NULL) {
diff --git a/hal/patches/patch-tools_hal-storage-shared.c b/hal/patches/patch-tools_hal-storage-shared.c
new file mode 100644
index 0000000000..dc906460e5
--- /dev/null
+++ b/hal/patches/patch-tools_hal-storage-shared.c
@@ -0,0 +1,138 @@
+$NetBSD$
+
+--- tools/hal-storage-shared.c.orig	2008-08-10 13:50:10.000000000 +0000
++++ tools/hal-storage-shared.c
+@@ -31,7 +31,7 @@
+ #include <string.h>
+ #include <glib.h>
+ #include <glib/gstdio.h>
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+ #include <fstab.h>
+ #include <sys/param.h>
+ #include <sys/ucred.h>
+@@ -42,6 +42,10 @@
+ #include <fcntl.h>
+ #include <sys/mnttab.h>
+ #include <sys/vfstab.h>
++#elif __NetBSD__
++#include <fstab.h>
++#include <sys/param.h>
++#include <sys/mount.h>
+ #else
+ #include <mntent.h>
+ #endif
+@@ -53,20 +57,27 @@
+ 
+ #include "hal-storage-shared.h"
+ 
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+ struct mtab_handle
+ {
+   struct statfs	*mounts;
+   int		n_mounts;
+   int		iter;
+ };
++#elif __NetBSD__
++struct mtab_handle
++{
++  struct statvfs *mounts;
++  int		n_mounts;
++  int		iter;
++};
+ #endif
+ 
+ 
+ gboolean
+ mtab_open (gpointer *handle)
+ {
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+ 	struct mtab_handle *mtab;
+ 
+ 	mtab = g_new0 (struct mtab_handle, 1);
+@@ -90,7 +101,7 @@ mtab_open (gpointer *handle)
+ char *
+ mtab_next (gpointer handle, char **mount_point)
+ {
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+ 	struct mtab_handle *mtab = handle;
+ 
+ 	if (mtab->iter < mtab->n_mounts) {
+@@ -131,7 +142,7 @@ mtab_next (gpointer handle, char **mount
+ void
+ mtab_close (gpointer handle)
+ {
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+ 	g_free (handle);
+ #else
+ 	fclose (handle);
+@@ -143,7 +154,7 @@ mtab_close (gpointer handle)
+ gboolean
+ fstab_open (gpointer *handle)
+ {
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+ 	return setfsent () == 1;
+ #elif sun
+ 	*handle = fopen (VFSTAB, "r");
+@@ -157,7 +168,7 @@ fstab_open (gpointer *handle)
+ char *
+ fstab_next (gpointer handle, char **mount_point)
+ {
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+ 	struct fstab *fstab;
+ 
+ 	fstab = getfsent ();
+@@ -188,14 +199,16 @@ fstab_next (gpointer handle, char **moun
+ void
+ fstab_close (gpointer handle)
+ {
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+ 	endfsent ();
+ #else
+ 	fclose (handle);
+ #endif
+ }
+ 
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__DragonFly__)
++#define UMOUNT		"/sbin/umount"
++#elif __NetBSD__
+ #define UMOUNT		"/sbin/umount"
+ #elif sun
+ #define UMOUNT		"/sbin/umount"
+@@ -467,7 +480,7 @@ line_found:
+ 	/* construct arguments to /bin/umount */
+ 	na = 0;
+ 	args[na++] = UMOUNT;
+-#ifndef __FreeBSD__
++#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)
+ 	if (option_lazy)
+ 		args[na++] = "-l";
+ #endif
+@@ -625,13 +638,18 @@ try_open_excl_again:
+ 	/* construct arguments to EJECT_PROGRAM (e.g. /usr/bin/eject) */
+ 	na = 0;
+ 	args[na++] = EJECT_PROGRAM;
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__DragonFly__)
+ 	args[na++] = "-f";
+ 	args[na++] = (char *) device;
+ 	if (closetray)
+ 		args[na++] = "close";
+ 	else
+ 		args[na++] = "eject";
++#elif __NetBSD__
++	args[na++] = "-f";
++	if (closetray)
++		args[na++] = "-l";
++	args[na++] = (char *) device;
+ #else
+ 	if (closetray) {
+ 		args[na++] = "-t";
diff --git a/hal/patches/patch-tools_hal-storage-unmount.c b/hal/patches/patch-tools_hal-storage-unmount.c
new file mode 100644
index 0000000000..ed4ed013b8
--- /dev/null
+++ b/hal/patches/patch-tools_hal-storage-unmount.c
@@ -0,0 +1,23 @@
+$NetBSD$
+
+--- tools/hal-storage-unmount.c.orig	2008-08-10 13:50:10.000000000 +0000
++++ tools/hal-storage-unmount.c
+@@ -31,13 +31,17 @@
+ #include <string.h>
+ #include <glib.h>
+ #include <glib/gstdio.h>
+-#ifdef __FreeBSD__
++#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+ #include <fstab.h>
+ #include <sys/param.h>
+ #include <sys/ucred.h>
+ #include <sys/mount.h>
+ #include <limits.h>
+ #include <pwd.h>
++#elif __NetBSD__
++#include <fstab.h>
++#include <sys/param.h>
++#include <sys/mount.h>
+ #elif sun
+ #include <fcntl.h>
+ #include <sys/mnttab.h>
diff --git a/hal/patches/patch-tools_hal-system-power-pmu.c b/hal/patches/patch-tools_hal-system-power-pmu.c
new file mode 100644
index 0000000000..e7d0dde040
--- /dev/null
+++ b/hal/patches/patch-tools_hal-system-power-pmu.c
@@ -0,0 +1,37 @@
+$NetBSD$
+
+--- tools/hal-system-power-pmu.c.orig	2009-05-12 12:25:58.000000000 +0000
++++ tools/hal-system-power-pmu.c
+@@ -55,6 +55,10 @@ pmac_sleep (void)
+ {
+ #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+ 	return FALSE;			/* FIXME implement */
++#elif __NetBSD__
++	return FALSE;			/* FIXME implement */
++#elif __DragonFly__
++	return FALSE;			/* FIXME implement */
+ #elif sun
+ 	return FALSE;			/* FIXME implement */
+ #elif __GNU__
+@@ -92,6 +96,10 @@ pmac_get_lcd_brightness (int *val)
+ {
+ #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+ 	return FALSE;			/* FIXME implement */
++#elif __NetBSD__
++	return FALSE;			/* FIXME implement */
++#elif __DragonFly__
++	return FALSE;			/* FIXME implement */
+ #elif sun
+ 	return FALSE;			/* FIXME implement */
+ #elif __GNU__
+@@ -129,6 +137,10 @@ pmac_set_lcd_brightness (int val)
+ {
+ #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+ 	return FALSE;			/* FIXME implement */
++#elif __NetBSD__
++	return FALSE;			/* FIXME implement */
++#elif __DragonFly__
++	return FALSE;			/* FIXME implement */
+ #elif sun
+ 	return FALSE;			/* FIXME implement */
+ #elif __GNU__
diff --git a/hal/patches/patch-tools_linux_Makefile.am b/hal/patches/patch-tools_linux_Makefile.am
new file mode 100644
index 0000000000..2807099f5b
--- /dev/null
+++ b/hal/patches/patch-tools_linux_Makefile.am
@@ -0,0 +1,12 @@
+$NetBSD$
+
+--- tools/linux/Makefile.am.orig	2009-07-15 06:52:51.000000000 +0000
++++ tools/linux/Makefile.am
+@@ -1,6 +1,6 @@
+ ## Process this file with automake to produce Makefile.in
+ 
+-udevrulesdir = $(udev_prefix)/udev/rules.d
++udevrulesdir = $(PREFIX)/share/examples/hal
+ udevrules_DATA = 90-hal.rules
+ 
+ 


Home | Main Index | Thread Index | Old Index