xref: /onnv-gate/usr/src/cmd/hal/hald/solaris/devinfo_storage.c (revision 12426:cdff5d2ea989)
12912Sartem /***************************************************************************
22912Sartem  *
32912Sartem  * devinfo_storage.c : storage devices
42912Sartem  *
5*12426Sgdamore@opensolaris.org  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
62912Sartem  *
72912Sartem  * Licensed under the Academic Free License version 2.1
82912Sartem  *
92912Sartem  **************************************************************************/
102912Sartem 
113121Sartem #ifdef HAVE_CONFIG_H
123121Sartem #  include <config.h>
133121Sartem #endif
143121Sartem 
152912Sartem #include <stdio.h>
162912Sartem #include <string.h>
172912Sartem #include <strings.h>
182912Sartem #include <ctype.h>
192912Sartem #include <libdevinfo.h>
202912Sartem #include <sys/types.h>
212912Sartem #include <sys/mkdev.h>
222912Sartem #include <sys/stat.h>
232912Sartem #include <sys/mntent.h>
242912Sartem #include <sys/mnttab.h>
252912Sartem 
262912Sartem #include "../osspec.h"
272912Sartem #include "../logger.h"
282912Sartem #include "../hald.h"
292912Sartem #include "../hald_dbus.h"
302912Sartem #include "../device_info.h"
312912Sartem #include "../util.h"
322912Sartem #include "../hald_runner.h"
332912Sartem #include "hotplug.h"
342912Sartem #include "devinfo.h"
352912Sartem #include "devinfo_misc.h"
362912Sartem #include "devinfo_storage.h"
372912Sartem #include "osspec_solaris.h"
382912Sartem 
392912Sartem #ifdef sparc
402912Sartem #define	WHOLE_DISK	"s2"
412912Sartem #else
422912Sartem #define	WHOLE_DISK	"p0"
432912Sartem #endif
442912Sartem 
452912Sartem /* some devices,especially CDROMs, may take a while to be probed (values in ms) */
462912Sartem #define	DEVINFO_PROBE_STORAGE_TIMEOUT	60000
472912Sartem #define	DEVINFO_PROBE_VOLUME_TIMEOUT	60000
482912Sartem 
492912Sartem typedef struct devinfo_storage_minor {
502912Sartem 	char	*devpath;
512912Sartem 	char	*devlink;
522912Sartem 	char	*slice;
532912Sartem 	dev_t	dev;
542912Sartem 	int	dosnum;	/* dos disk number or -1 */
552912Sartem } devinfo_storage_minor_t;
562912Sartem 
572912Sartem HalDevice *devinfo_ide_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
582912Sartem static HalDevice *devinfo_ide_host_add(HalDevice *parent, di_node_t node, char *devfs_path);
592912Sartem static HalDevice *devinfo_ide_device_add(HalDevice *parent, di_node_t node, char *devfs_path);
603121Sartem static HalDevice *devinfo_ide_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
612912Sartem HalDevice *devinfo_scsi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
623121Sartem static HalDevice *devinfo_scsi_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
633121Sartem HalDevice *devinfo_pcata_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
643121Sartem static HalDevice *devinfo_pcata_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
65*12426Sgdamore@opensolaris.org HalDevice *devinfo_blkdev_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
66*12426Sgdamore@opensolaris.org static HalDevice *devinfo_blkdev_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
672912Sartem HalDevice *devinfo_floppy_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
682912Sartem static void devinfo_floppy_add_volume(HalDevice *parent, di_node_t node);
692912Sartem static HalDevice *devinfo_lofi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
702912Sartem static void devinfo_lofi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, char *devlink, dev_t dev);
712912Sartem static void devinfo_storage_minors(HalDevice *parent, di_node_t node, gchar *devfs_path, gboolean);
722912Sartem static struct devinfo_storage_minor *devinfo_storage_new_minor(char *maindev_path, char *slice,
732912Sartem     char *devlink, dev_t dev, int dosnum);
742912Sartem static void devinfo_storage_free_minor(struct devinfo_storage_minor *m);
752912Sartem HalDevice *devinfo_volume_add(HalDevice *parent, di_node_t node, devinfo_storage_minor_t *m);
762912Sartem static void devinfo_volume_preprobing_done(HalDevice *d, gpointer userdata1, gpointer userdata2);
772912Sartem static void devinfo_volume_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
782912Sartem static void devinfo_storage_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
792912Sartem static void devinfo_storage_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2);
802912Sartem const gchar *devinfo_volume_get_prober (HalDevice *d, int *timeout);
812912Sartem const gchar *devinfo_storage_get_prober (HalDevice *d, int *timeout);
822912Sartem 
832912Sartem static char *devinfo_scsi_dtype2str(int dtype);
842912Sartem static char *devinfo_volume_get_slice_name (char *devlink);
852912Sartem static gboolean dos_to_dev(char *path, char **devpath, int *partnum);
862912Sartem static gboolean is_dos_path(char *path, int *partnum);
872912Sartem 
882912Sartem static void devinfo_storage_set_nicknames (HalDevice *d);
892912Sartem 
902912Sartem DevinfoDevHandler devinfo_ide_handler = {
912912Sartem         devinfo_ide_add,
922912Sartem 	NULL,
932912Sartem 	NULL,
942912Sartem 	NULL,
952912Sartem 	NULL,
962912Sartem         NULL
972912Sartem };
982912Sartem DevinfoDevHandler devinfo_scsi_handler = {
992912Sartem         devinfo_scsi_add,
1002912Sartem 	NULL,
1012912Sartem 	NULL,
1022912Sartem 	NULL,
1032912Sartem 	NULL,
1042912Sartem         NULL
1052912Sartem };
1063121Sartem DevinfoDevHandler devinfo_pcata_handler = {
1073121Sartem         devinfo_pcata_add,
1083121Sartem 	NULL,
1093121Sartem 	NULL,
1103121Sartem 	NULL,
1113121Sartem 	NULL,
1123121Sartem         NULL
1133121Sartem };
114*12426Sgdamore@opensolaris.org DevinfoDevHandler devinfo_blkdev_handler = {
115*12426Sgdamore@opensolaris.org         devinfo_blkdev_add,
116*12426Sgdamore@opensolaris.org 	NULL,
117*12426Sgdamore@opensolaris.org 	NULL,
118*12426Sgdamore@opensolaris.org 	NULL,
119*12426Sgdamore@opensolaris.org 	NULL,
120*12426Sgdamore@opensolaris.org         NULL
121*12426Sgdamore@opensolaris.org };
1222912Sartem DevinfoDevHandler devinfo_floppy_handler = {
1232912Sartem         devinfo_floppy_add,
1242912Sartem 	NULL,
1252912Sartem 	NULL,
1262912Sartem 	NULL,
1272912Sartem 	NULL,
1282912Sartem         NULL
1292912Sartem };
1302912Sartem DevinfoDevHandler devinfo_lofi_handler = {
1312912Sartem         devinfo_lofi_add,
1322912Sartem 	NULL,
1332912Sartem 	NULL,
1342912Sartem 	NULL,
1352912Sartem 	NULL,
1362912Sartem         NULL
1372912Sartem };
1382912Sartem DevinfoDevHandler devinfo_storage_handler = {
1392912Sartem 	NULL,
1402912Sartem 	NULL,
1412912Sartem 	devinfo_storage_hotplug_begin_add,
1422912Sartem 	NULL,
1432912Sartem 	devinfo_storage_probing_done,
1442912Sartem 	devinfo_storage_get_prober
1452912Sartem };
1462912Sartem DevinfoDevHandler devinfo_volume_handler = {
1472912Sartem 	NULL,
1482912Sartem 	NULL,
1492912Sartem 	devinfo_volume_hotplug_begin_add,
1502912Sartem 	NULL,
1512912Sartem 	NULL,
1522912Sartem 	devinfo_volume_get_prober
1532912Sartem };
1542912Sartem 
1552912Sartem /* IDE */
1562912Sartem 
1572912Sartem HalDevice *
devinfo_ide_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)1582912Sartem devinfo_ide_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
1592912Sartem {
1602912Sartem 	char	*s;
1612912Sartem 
1622912Sartem 	if ((device_type != NULL) && (strcmp(device_type, "ide") == 0)) {
1632912Sartem 		return (devinfo_ide_host_add(parent, node, devfs_path));
1642912Sartem 	}
1652912Sartem 
1662912Sartem         if ((di_prop_lookup_strings (DDI_DEV_T_ANY, node, "class", &s) > 0) &&
1672912Sartem 	    (strcmp (s, "dada") == 0)) {
1682912Sartem 		return (devinfo_ide_device_add(parent, node, devfs_path));
1692912Sartem 	}
1702912Sartem 
1712912Sartem 	return (NULL);
1722912Sartem }
1732912Sartem 
1742912Sartem static HalDevice *
devinfo_ide_host_add(HalDevice * parent,di_node_t node,char * devfs_path)1752912Sartem devinfo_ide_host_add(HalDevice *parent, di_node_t node, char *devfs_path)
1762912Sartem {
1772912Sartem 	HalDevice *d;
1782912Sartem 
1792912Sartem 	d = hal_device_new ();
1802912Sartem 
1812912Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
1822912Sartem 	hal_device_property_set_string (d, "info.product", "IDE host controller");
1836112Sqz150045 	hal_device_property_set_string (d, "info.subsystem", "ide_host");
1842912Sartem 	hal_device_property_set_int (d, "ide_host.number", 0); /* XXX */
1852912Sartem 
1862912Sartem 	devinfo_add_enqueue (d, devfs_path, &devinfo_ide_handler);
1872912Sartem 
1882912Sartem 	return (d);
1892912Sartem }
1902912Sartem 
1912912Sartem static HalDevice *
devinfo_ide_device_add(HalDevice * parent,di_node_t node,char * devfs_path)1922912Sartem devinfo_ide_device_add(HalDevice *parent, di_node_t node, char *devfs_path)
1932912Sartem {
1942912Sartem 	HalDevice *d;
1952912Sartem 
1962912Sartem 	d = hal_device_new();
1972912Sartem 
1982912Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
1992912Sartem         hal_device_property_set_string (parent, "info.product", "IDE device");
2006112Sqz150045 	hal_device_property_set_string (parent, "info.subsystem", "ide");
2012912Sartem 	hal_device_property_set_int (parent, "ide.host", 0); /* XXX */
2022912Sartem 	hal_device_property_set_int (parent, "ide.channel", 0);
2032912Sartem 
2042912Sartem 	devinfo_add_enqueue (d, devfs_path, &devinfo_ide_handler);
2052912Sartem 
2063121Sartem 	return (devinfo_ide_storage_add (d, node, devfs_path));
2072912Sartem }
2082912Sartem 
2092912Sartem static HalDevice *
devinfo_ide_storage_add(HalDevice * parent,di_node_t node,char * devfs_path)2103121Sartem devinfo_ide_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
2112912Sartem {
2122912Sartem 	HalDevice *d;
2132912Sartem 	char	*s;
2142912Sartem 	int	*i;
2152912Sartem 	char	*driver_name;
2162912Sartem 	char	udi[HAL_PATH_MAX];
2172912Sartem 
2182912Sartem 	if ((driver_name = di_driver_name (node)) == NULL) {
2192912Sartem 		return (NULL);
2202912Sartem 	}
2212912Sartem 
2222912Sartem         d = hal_device_new ();
2232912Sartem 
2242912Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
2252912Sartem         hal_device_property_set_string (d, "info.category", "storage");
2262912Sartem 
2272912Sartem         hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
2283121Sartem                 "%s/%s%d", hal_device_get_udi (parent), driver_name, di_instance (node));
2292912Sartem         hal_device_set_udi (d, udi);
2302912Sartem         hal_device_property_set_string (d, "info.udi", udi);
2312912Sartem 	PROP_STR(d, node, s, "devid", "info.product");
2322912Sartem 
2332912Sartem         hal_device_add_capability (d, "storage");
2342912Sartem         hal_device_property_set_string (d, "storage.bus", "ide");
2352912Sartem         hal_device_property_set_int (d, "storage.lun", 0);
2362912Sartem 	hal_device_property_set_string (d, "storage.drive_type", "disk");
2372912Sartem 
2382912Sartem 	PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
2392912Sartem 	PROP_BOOL(d, node, i, "removable-media", "storage.removable");
2402912Sartem 
2412912Sartem         hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
2422912Sartem 
2432912Sartem 	/* XXX */
2442912Sartem         hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
2452912Sartem 
2462912Sartem 	hal_device_add_capability (d, "block");
2472912Sartem 
2482912Sartem 	devinfo_storage_minors (d, node, (char *)devfs_path, FALSE);
2492912Sartem 
2502912Sartem 	return (d);
2512912Sartem }
2522912Sartem 
2532912Sartem /* SCSI */
2542912Sartem 
2552912Sartem HalDevice *
devinfo_scsi_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)2562912Sartem devinfo_scsi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
2572912Sartem {
2582912Sartem 	int	*i;
2592912Sartem 	char	*driver_name;
2602912Sartem 	HalDevice *d;
2612912Sartem 	char	udi[HAL_PATH_MAX];
2622912Sartem 
2632912Sartem 	driver_name = di_driver_name (node);
2642912Sartem 	if ((driver_name == NULL) || (strcmp (driver_name, "sd") != 0)) {
2652912Sartem 		return (NULL);
2662912Sartem 	}
2672912Sartem 
2682912Sartem 	d = hal_device_new ();
2692912Sartem 
2702912Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
2716112Sqz150045 	hal_device_property_set_string (d, "info.subsystem", "scsi");
2722912Sartem 
2732912Sartem         hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
2743121Sartem                 "%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
2752912Sartem         hal_device_set_udi (d, udi);
2762912Sartem         hal_device_property_set_string (d, "info.udi", udi);
2772912Sartem 
2782912Sartem 	hal_device_property_set_int (d, "scsi.host",
2792912Sartem 		hal_device_property_get_int (parent, "scsi_host.host"));
2802912Sartem 	hal_device_property_set_int (d, "scsi.bus", 0);
2812912Sartem 	PROP_INT(d, node, i, "target", "scsi.target");
2822912Sartem 	PROP_INT(d, node, i, "lun", "scsi.lun");
2832912Sartem         hal_device_property_set_string (d, "info.product", "SCSI Device");
2842912Sartem 
2852912Sartem         devinfo_add_enqueue (d, devfs_path, &devinfo_scsi_handler);
2862912Sartem 
2873121Sartem         return (devinfo_scsi_storage_add (d, node, devfs_path));
2882912Sartem }
2892912Sartem 
2902912Sartem static HalDevice *
devinfo_scsi_storage_add(HalDevice * parent,di_node_t node,char * devfs_path)2913121Sartem devinfo_scsi_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
2922912Sartem {
2932912Sartem 	HalDevice *d;
2942912Sartem 	int	*i;
2952912Sartem 	char	*s;
2962912Sartem 	char	udi[HAL_PATH_MAX];
2972912Sartem 
2982912Sartem 	d = hal_device_new ();
2992912Sartem 
3002912Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
3012912Sartem         hal_device_property_set_string (d, "info.category", "storage");
3022912Sartem 
3032912Sartem         hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
3043121Sartem 		"%s/sd%d", hal_device_get_udi (parent), di_instance (node));
3052912Sartem         hal_device_set_udi (d, udi);
3062912Sartem         hal_device_property_set_string (d, "info.udi", udi);
3072912Sartem 	PROP_STR(d, node, s, "inquiry-product-id", "info.product");
3082912Sartem 
3092912Sartem         hal_device_add_capability (d, "storage");
3102912Sartem 
3112912Sartem         hal_device_property_set_int (d, "storage.lun",
3122912Sartem 		hal_device_property_get_int (parent, "scsi.lun"));
3132912Sartem 	PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
3142912Sartem 	PROP_BOOL(d, node, i, "removable-media", "storage.removable");
3152912Sartem         hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
3162912Sartem 
3172912Sartem 	/*
3182912Sartem 	 * We have to enable polling not only for drives with removable media,
3192912Sartem 	 * but also for hotpluggable devices, because when a disk is
3202912Sartem 	 * unplugged while busy/mounted, there is not sysevent generated.
3212912Sartem 	 * Instead, the HBA driver (scsa2usb, scsa1394) will notify sd driver
3222912Sartem 	 * and the latter will report DKIO_DEV_GONE via DKIOCSTATE ioctl.
3232912Sartem 	 * So we have to enable media check so that hald-addon-storage notices
3242912Sartem 	 * the "device gone" condition and unmounts all associated volumes.
3252912Sartem 	 */
3262912Sartem 	hal_device_property_set_bool (d, "storage.media_check_enabled",
3272912Sartem 	    ((di_prop_lookup_ints(DDI_DEV_T_ANY, node, "removable-media", &i) >= 0) ||
3282912Sartem 	    (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "hotpluggable", &i) >= 0)));
3292912Sartem 
3302912Sartem         if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "inquiry-device-type",
3312912Sartem 	    &i) > 0) {
3322912Sartem 		s = devinfo_scsi_dtype2str (*i);
3332912Sartem         	hal_device_property_set_string (d, "storage.drive_type", s);
3342912Sartem 
3352912Sartem 		if (strcmp (s, "cdrom") == 0) {
3362912Sartem 			hal_device_add_capability (d, "storage.cdrom");
3372912Sartem 			hal_device_property_set_bool (d, "storage.no_partitions_hint", TRUE);
3382912Sartem         		hal_device_property_set_bool (d, "storage.requires_eject", TRUE);
3392912Sartem 		}
3402912Sartem 	}
3412912Sartem 
3422912Sartem         hal_device_add_capability (d, "block");
3432912Sartem 
3442912Sartem 	devinfo_storage_minors (d, node, devfs_path, FALSE);
3452912Sartem 
3462912Sartem 	return (d);
3472912Sartem }
3482912Sartem 
3493121Sartem static char *
devinfo_scsi_dtype2str(int dtype)3503121Sartem devinfo_scsi_dtype2str(int dtype)
3512912Sartem {
3522912Sartem         char *dtype2str[] = {
3532912Sartem                 "disk"	,         /* DTYPE_DIRECT         0x00 */
3542912Sartem                 "tape"	,         /* DTYPE_SEQUENTIAL     0x01 */
3552912Sartem                 "printer",         /* DTYPE_PRINTER        0x02 */
3562912Sartem                 "processor",         /* DTYPE_PROCESSOR      0x03 */
3572912Sartem                 "worm"	,         /* DTYPE_WORM           0x04 */
3582912Sartem                 "cdrom"	,         /* DTYPE_RODIRECT       0x05 */
3592912Sartem                 "scanner",         /* DTYPE_SCANNER        0x06 */
3602912Sartem                 "cdrom"	,         /* DTYPE_OPTICAL        0x07 */
3612912Sartem                 "changer",         /* DTYPE_CHANGER        0x08 */
3622912Sartem                 "comm"	,         /* DTYPE_COMM           0x09 */
3632912Sartem                 "scsi"	,         /* DTYPE_???            0x0A */
3642912Sartem                 "scsi"	,         /* DTYPE_???            0x0B */
3652912Sartem                 "array_ctrl",         /* DTYPE_ARRAY_CTRL     0x0C */
3662912Sartem                 "esi"	,         /* DTYPE_ESI            0x0D */
3672912Sartem                 "disk"	          /* DTYPE_RBC            0x0E */
3682912Sartem         };
3692912Sartem 
3702912Sartem         if (dtype < NELEM(dtype2str)) {
3712912Sartem                 return (dtype2str[dtype]);
3722912Sartem         } else {
3732912Sartem 		return ("scsi");
3742912Sartem         }
3752912Sartem 
3762912Sartem }
3772912Sartem 
3783121Sartem /* PCMCIA */
3793121Sartem 
3803121Sartem HalDevice *
devinfo_pcata_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)3813121Sartem devinfo_pcata_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
3823121Sartem {
3833121Sartem 	int	*i;
3843121Sartem 	char	*driver_name;
3853121Sartem 	HalDevice *d;
3863121Sartem 	char	udi[HAL_PATH_MAX];
3873121Sartem 
3883121Sartem 	driver_name = di_driver_name (node);
3893121Sartem 	if ((driver_name == NULL) || (strcmp (driver_name, "pcata") != 0)) {
3903121Sartem 		return (NULL);
3913121Sartem 	}
3923121Sartem 
3933121Sartem 	d = hal_device_new ();
3943121Sartem 
3953121Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
3966112Sqz150045 	hal_device_property_set_string (d, "info.subsystem", "pcmcia");
3973121Sartem 
3983121Sartem         hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
3993121Sartem                 "%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
4003121Sartem         hal_device_set_udi (d, udi);
4013121Sartem         hal_device_property_set_string (d, "info.udi", udi);
4023121Sartem         hal_device_property_set_string (d, "info.product", "PCMCIA Disk");
4033121Sartem 
4043121Sartem         devinfo_add_enqueue (d, devfs_path, &devinfo_pcata_handler);
4053121Sartem 
4063121Sartem         return (devinfo_pcata_storage_add (d, node, devfs_path));
4073121Sartem }
4083121Sartem 
4093121Sartem static HalDevice *
devinfo_pcata_storage_add(HalDevice * parent,di_node_t node,char * devfs_path)4103121Sartem devinfo_pcata_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
4113121Sartem {
4123121Sartem 	HalDevice *d;
4133121Sartem 	char	*driver_name;
4143121Sartem 	int	*i;
4153121Sartem 	char	*s;
4163121Sartem 	char	udi[HAL_PATH_MAX];
4173121Sartem 
4183121Sartem 	d = hal_device_new ();
4193121Sartem 
4203121Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
4213121Sartem 	hal_device_property_set_string (d, "info.category", "storage");
4223121Sartem 
4233121Sartem 	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
4243121Sartem 		"%s/sd%d", hal_device_get_udi (parent), di_instance (node));
4253121Sartem 	hal_device_set_udi (d, udi);
4263121Sartem 	hal_device_property_set_string (d, "info.udi", udi);
4273121Sartem 
4283121Sartem 	hal_device_add_capability (d, "storage");
4293121Sartem 
4303121Sartem 	hal_device_property_set_int (d, "storage.lun", 0);
4313121Sartem 	hal_device_property_set_bool (d, "storage.hotpluggable", TRUE);
4323121Sartem 	hal_device_property_set_bool (d, "storage.removable", FALSE);
4333121Sartem 	hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
4343121Sartem 	hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
4353121Sartem        	hal_device_property_set_string (d, "storage.drive_type", "disk");
4363121Sartem 	hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
4373121Sartem 
4383121Sartem 	hal_device_add_capability (d, "block");
4393121Sartem 
4403121Sartem 	devinfo_storage_minors (d, node, devfs_path, FALSE);
4413121Sartem 
4423121Sartem 	return (d);
4433121Sartem }
4443121Sartem 
445*12426Sgdamore@opensolaris.org /* blkdev */
446*12426Sgdamore@opensolaris.org 
447*12426Sgdamore@opensolaris.org HalDevice *
devinfo_blkdev_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)448*12426Sgdamore@opensolaris.org devinfo_blkdev_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
449*12426Sgdamore@opensolaris.org {
450*12426Sgdamore@opensolaris.org 	int	*i;
451*12426Sgdamore@opensolaris.org 	char	*driver_name;
452*12426Sgdamore@opensolaris.org 	HalDevice *d;
453*12426Sgdamore@opensolaris.org 	char	udi[HAL_PATH_MAX];
454*12426Sgdamore@opensolaris.org 
455*12426Sgdamore@opensolaris.org 	driver_name = di_driver_name (node);
456*12426Sgdamore@opensolaris.org 	if ((driver_name == NULL) || (strcmp (driver_name, "blkdev") != 0)) {
457*12426Sgdamore@opensolaris.org 		return (NULL);
458*12426Sgdamore@opensolaris.org 	}
459*12426Sgdamore@opensolaris.org 
460*12426Sgdamore@opensolaris.org 	d = hal_device_new ();
461*12426Sgdamore@opensolaris.org 
462*12426Sgdamore@opensolaris.org 	devinfo_set_default_properties (d, parent, node, devfs_path);
463*12426Sgdamore@opensolaris.org 	hal_device_property_set_string (d, "info.subsystem", "pseudo");
464*12426Sgdamore@opensolaris.org 
465*12426Sgdamore@opensolaris.org         hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
466*12426Sgdamore@opensolaris.org                 "%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
467*12426Sgdamore@opensolaris.org         hal_device_set_udi (d, udi);
468*12426Sgdamore@opensolaris.org         hal_device_property_set_string (d, "info.udi", udi);
469*12426Sgdamore@opensolaris.org         hal_device_property_set_string (d, "info.product", "Block Device");
470*12426Sgdamore@opensolaris.org 
471*12426Sgdamore@opensolaris.org         devinfo_add_enqueue (d, devfs_path, &devinfo_blkdev_handler);
472*12426Sgdamore@opensolaris.org 
473*12426Sgdamore@opensolaris.org         return (devinfo_blkdev_storage_add (d, node, devfs_path));
474*12426Sgdamore@opensolaris.org }
475*12426Sgdamore@opensolaris.org 
476*12426Sgdamore@opensolaris.org static HalDevice *
devinfo_blkdev_storage_add(HalDevice * parent,di_node_t node,char * devfs_path)477*12426Sgdamore@opensolaris.org devinfo_blkdev_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
478*12426Sgdamore@opensolaris.org {
479*12426Sgdamore@opensolaris.org 	HalDevice *d;
480*12426Sgdamore@opensolaris.org 	char	*driver_name;
481*12426Sgdamore@opensolaris.org 	int	*i;
482*12426Sgdamore@opensolaris.org 	char	*s;
483*12426Sgdamore@opensolaris.org 	char	udi[HAL_PATH_MAX];
484*12426Sgdamore@opensolaris.org 
485*12426Sgdamore@opensolaris.org 	d = hal_device_new ();
486*12426Sgdamore@opensolaris.org 
487*12426Sgdamore@opensolaris.org 	devinfo_set_default_properties (d, parent, node, devfs_path);
488*12426Sgdamore@opensolaris.org 	hal_device_property_set_string (d, "info.category", "storage");
489*12426Sgdamore@opensolaris.org 
490*12426Sgdamore@opensolaris.org 	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
491*12426Sgdamore@opensolaris.org 		"%s/blkdev%d", hal_device_get_udi (parent), di_instance (node));
492*12426Sgdamore@opensolaris.org 	hal_device_set_udi (d, udi);
493*12426Sgdamore@opensolaris.org 	hal_device_property_set_string (d, "info.udi", udi);
494*12426Sgdamore@opensolaris.org 
495*12426Sgdamore@opensolaris.org 	hal_device_add_capability (d, "storage");
496*12426Sgdamore@opensolaris.org 
497*12426Sgdamore@opensolaris.org 	hal_device_property_set_int (d, "storage.lun", 0);
498*12426Sgdamore@opensolaris.org 
499*12426Sgdamore@opensolaris.org 	PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
500*12426Sgdamore@opensolaris.org 	PROP_BOOL(d, node, i, "removable-media", "storage.removable");
501*12426Sgdamore@opensolaris.org 
502*12426Sgdamore@opensolaris.org 	hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
503*12426Sgdamore@opensolaris.org 	hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
504*12426Sgdamore@opensolaris.org        	hal_device_property_set_string (d, "storage.drive_type", "disk");
505*12426Sgdamore@opensolaris.org 
506*12426Sgdamore@opensolaris.org 	hal_device_add_capability (d, "block");
507*12426Sgdamore@opensolaris.org 
508*12426Sgdamore@opensolaris.org 	devinfo_storage_minors (d, node, devfs_path, FALSE);
509*12426Sgdamore@opensolaris.org 
510*12426Sgdamore@opensolaris.org 	return (d);
511*12426Sgdamore@opensolaris.org }
512*12426Sgdamore@opensolaris.org 
5132912Sartem /* floppy */
5142912Sartem 
5152912Sartem HalDevice *
devinfo_floppy_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)5162912Sartem devinfo_floppy_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
5172912Sartem {
5182912Sartem 	char	*driver_name;
5192912Sartem 	char	*raw;
5202912Sartem 	char	udi[HAL_PATH_MAX];
5212912Sartem 	di_devlink_handle_t devlink_hdl;
5222912Sartem         int     major;
5232912Sartem         di_minor_t minor;
5242912Sartem         dev_t   dev;
5252912Sartem 	HalDevice *d = NULL;
5262912Sartem         char    *minor_path = NULL;
5272912Sartem 	char	*devlink = NULL;
5282912Sartem 
5292912Sartem 	driver_name = di_driver_name (node);
5302912Sartem 	if ((driver_name == NULL) || (strcmp (driver_name, "fd") != 0)) {
5312912Sartem 		return (NULL);
5322912Sartem 	}
5332912Sartem 
5342912Sartem 	/*
5352912Sartem 	 * The only minor node we're interested in is /dev/diskette*
5362912Sartem 	 */
5372912Sartem 	major = di_driver_major(node);
5382912Sartem 	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
5392912Sartem 		return (NULL);
5402912Sartem 	}
5412912Sartem 	minor = DI_MINOR_NIL;
5422912Sartem 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
5432912Sartem 		dev = di_minor_devt(minor);
5442912Sartem 		if ((major != major(dev)) ||
5452912Sartem 		    (di_minor_type(minor) != DDM_MINOR) ||
5462912Sartem 		    (di_minor_spectype(minor) != S_IFBLK) ||
5472912Sartem 		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
5482912Sartem 			continue;
5492912Sartem 		}
5503536Sjacobs 		if ((devlink = get_devlink(devlink_hdl, "diskette.+" , minor_path)) != NULL) {
5512912Sartem 			break;
5522912Sartem 		}
5532912Sartem 		di_devfs_path_free (minor_path);
5542912Sartem 		minor_path = NULL;
5552912Sartem 		free(devlink);
5562912Sartem 		devlink = NULL;
5572912Sartem 	}
5582912Sartem 	di_devlink_fini (&devlink_hdl);
5592912Sartem 
5602912Sartem 	if ((devlink == NULL) || (minor_path == NULL)) {
5612912Sartem 		HAL_INFO (("floppy devlink not found %s", devfs_path));
5622912Sartem 		goto out;
5632912Sartem 	}
5642912Sartem 
5652912Sartem 	d = hal_device_new ();
5662912Sartem 
5672912Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
5682912Sartem         hal_device_property_set_string (d, "info.category", "storage");
5692912Sartem         hal_device_add_capability (d, "storage");
5702912Sartem        	hal_device_property_set_string (d, "storage.bus", "platform");
5712912Sartem         hal_device_property_set_bool (d, "storage.hotpluggable", FALSE);
5722912Sartem         hal_device_property_set_bool (d, "storage.removable", TRUE);
5732912Sartem         hal_device_property_set_bool (d, "storage.requires_eject", TRUE);
5742912Sartem         hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
5752912Sartem        	hal_device_property_set_string (d, "storage.drive_type", "floppy");
5762912Sartem 
5772912Sartem         hal_device_add_capability (d, "block");
5782912Sartem 	hal_device_property_set_bool (d, "block.is_volume", FALSE);
5792912Sartem 	hal_device_property_set_int (d, "block.major", major(dev));
5802912Sartem 	hal_device_property_set_int (d, "block.minor", minor(dev));
5812912Sartem 	hal_device_property_set_string (d, "block.device", devlink);
5822912Sartem 	raw = dsk_to_rdsk (devlink);
5832912Sartem 	hal_device_property_set_string (d, "block.solaris.raw_device", raw);
5842912Sartem 	free (raw);
5852912Sartem 
5862912Sartem 	devinfo_add_enqueue (d, devfs_path, &devinfo_storage_handler);
5872912Sartem 
5882912Sartem 	/* trigger initial probe-volume */
5892912Sartem 	devinfo_floppy_add_volume(d, node);
5902912Sartem 
5912912Sartem out:
5922912Sartem 	di_devfs_path_free (minor_path);
5932912Sartem 	free(devlink);
5942912Sartem 
5952912Sartem 	return (d);
5962912Sartem }
5972912Sartem 
5982912Sartem static void
devinfo_floppy_add_volume(HalDevice * parent,di_node_t node)5992912Sartem devinfo_floppy_add_volume(HalDevice *parent, di_node_t node)
6002912Sartem {
6012912Sartem 	char	*devlink;
6022912Sartem 	char	*devfs_path;
6032912Sartem 	int	minor, major;
6042912Sartem 	dev_t	dev;
6052912Sartem 	struct devinfo_storage_minor *m;
6062912Sartem 
6072912Sartem 	devfs_path = (char *)hal_device_property_get_string (parent, "solaris.devfs_path");
6082912Sartem 	devlink = (char *)hal_device_property_get_string (parent, "block.device");
6092912Sartem 	major = hal_device_property_get_int (parent, "block.major");
6102912Sartem 	minor = hal_device_property_get_int (parent, "block.minor");
6112912Sartem 	dev = makedev (major, minor);
6122912Sartem 
6132912Sartem 	m = devinfo_storage_new_minor (devfs_path, WHOLE_DISK, devlink, dev, -1);
6142912Sartem 	devinfo_volume_add (parent, node, m);
6152912Sartem 	devinfo_storage_free_minor (m);
6162912Sartem }
6172912Sartem 
6182912Sartem /*
6192912Sartem  * After reprobing storage, reprobe its volumes.
6202912Sartem  */
6212912Sartem static void
devinfo_floppy_rescan_probing_done(HalDevice * d,guint32 exit_type,gint return_code,char ** error,gpointer userdata1,gpointer userdata2)6222912Sartem devinfo_floppy_rescan_probing_done (HalDevice *d, guint32 exit_type, gint return_code,
6232912Sartem     char **error, gpointer userdata1, gpointer userdata2)
6242912Sartem {
6252912Sartem         void *end_token = (void *) userdata1;
6262912Sartem 	const char *devfs_path;
6272912Sartem 	di_node_t node;
6282912Sartem 	HalDevice *v;
6292912Sartem 
6302912Sartem 	if (!hal_device_property_get_bool (d, "storage.removable.media_available")) {
6313121Sartem 		HAL_INFO (("no floppy media", hal_device_get_udi (d)));
6322912Sartem 
6332912Sartem 		/* remove child (can only be single volume) */
6342912Sartem 		if (((v = hal_device_store_match_key_value_string (hald_get_gdl(),
6353121Sartem         	    "info.parent", hal_device_get_udi (d))) != NULL) &&
6362912Sartem 		    ((devfs_path = hal_device_property_get_string (v,
6372912Sartem 		    "solaris.devfs_path")) != NULL)) {
6382912Sartem 			devinfo_remove_enqueue ((char *)devfs_path, NULL);
6392912Sartem 		}
6402912Sartem 	} else {
6413121Sartem 		HAL_INFO (("floppy media found", hal_device_get_udi (d)));
6422912Sartem 
6432912Sartem 		if ((devfs_path = hal_device_property_get_string(d, "solaris.devfs_path")) == NULL) {
6443121Sartem 			HAL_INFO (("no devfs_path", hal_device_get_udi (d)));
6452912Sartem 			hotplug_event_process_queue ();
6462912Sartem 			return;
6472912Sartem 		}
6482912Sartem 		if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
6492912Sartem 			HAL_INFO (("di_init %s failed %d", devfs_path, errno));
6502912Sartem 			hotplug_event_process_queue ();
6512912Sartem 			return;
6522912Sartem 		}
6532912Sartem 
6542912Sartem 		devinfo_floppy_add_volume (d, node);
6552912Sartem 
6562912Sartem 		di_fini (node);
6572912Sartem 	}
6582912Sartem 
6592912Sartem 	hotplug_event_process_queue ();
6602912Sartem }
6612912Sartem 
6622912Sartem /* lofi */
6632912Sartem 
6642912Sartem HalDevice *
devinfo_lofi_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)6652912Sartem devinfo_lofi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
6662912Sartem {
6672912Sartem 	return (devinfo_lofi_add_major(parent,node, devfs_path, device_type, FALSE, NULL));
6682912Sartem }
6692912Sartem 
6702912Sartem HalDevice *
devinfo_lofi_add_major(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type,gboolean rescan,HalDevice * lofi_d)6712912Sartem devinfo_lofi_add_major(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type,
6722912Sartem     gboolean rescan, HalDevice *lofi_d)
6732912Sartem {
6742912Sartem 	char	*driver_name;
6752912Sartem 	HalDevice *d = NULL;
6762912Sartem 	char	udi[HAL_PATH_MAX];
6772912Sartem 	di_devlink_handle_t devlink_hdl;
6782912Sartem         int     major;
6792912Sartem         di_minor_t minor;
6802912Sartem         dev_t   dev;
6812912Sartem         char    *minor_path = NULL;
6828100SLin.Guo@Sun.COM         char    *devlink = NULL;
6832912Sartem 
6842912Sartem 	driver_name = di_driver_name (node);
6852912Sartem 	if ((driver_name == NULL) || (strcmp (driver_name, "lofi") != 0)) {
6862912Sartem 		return (NULL);
6872912Sartem 	}
6882912Sartem 
6892912Sartem 	if (!rescan) {
6902912Sartem 		d = hal_device_new ();
6912912Sartem 
6922912Sartem 		devinfo_set_default_properties (d, parent, node, devfs_path);
6936112Sqz150045 		hal_device_property_set_string (d, "info.subsystem", "pseudo");
6942912Sartem 
6952912Sartem         	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
6963121Sartem                 	"%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
6972912Sartem         	hal_device_set_udi (d, udi);
6982912Sartem         	hal_device_property_set_string (d, "info.udi", udi);
6992912Sartem 
7002912Sartem         	devinfo_add_enqueue (d, devfs_path, &devinfo_lofi_handler);
7012912Sartem 	} else {
7022912Sartem 		d = lofi_d;
7032912Sartem 	}
7042912Sartem 
7052912Sartem 	/*
7062912Sartem 	 * Unlike normal storage, as in devinfo_storage_minors(), where
7072912Sartem 	 * sd instance -> HAL storage, sd minor node -> HAL volume,
7082912Sartem 	 * lofi always has one instance, lofi minor -> HAL storage.
7092912Sartem 	 * lofi storage never has slices, but it can have
7102912Sartem 	 * embedded pcfs partitions that fstyp would recognize
7112912Sartem 	 */
7122912Sartem 	major = di_driver_major(node);
7132912Sartem 	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
7142912Sartem 		return (d);
7152912Sartem 	}
7162912Sartem 	minor = DI_MINOR_NIL;
7172912Sartem 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
7182912Sartem 		dev = di_minor_devt(minor);
7192912Sartem 		if ((major != major(dev)) ||
7202912Sartem 		    (di_minor_type(minor) != DDM_MINOR) ||
7212912Sartem 		    (di_minor_spectype(minor) != S_IFBLK) ||
7222912Sartem 		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
7232912Sartem 			continue;
7242912Sartem 		}
7253536Sjacobs 		if ((devlink = get_devlink(devlink_hdl, NULL, minor_path)) == NULL) {
7262912Sartem 			di_devfs_path_free (minor_path);
7272912Sartem         		continue;
7282912Sartem 		}
7292912Sartem 
7302912Sartem 		if (!rescan ||
7312912Sartem 		    (hal_device_store_match_key_value_string (hald_get_gdl (),
7322912Sartem 		    "solaris.devfs_path", minor_path) == NULL)) {
7332912Sartem 			devinfo_lofi_add_minor(d, node, minor_path, devlink, dev);
7342912Sartem 		}
7352912Sartem 
7362912Sartem 		di_devfs_path_free (minor_path);
7372912Sartem 		free(devlink);
7382912Sartem 	}
7392912Sartem 	di_devlink_fini (&devlink_hdl);
7402912Sartem 
7412912Sartem 	return (d);
7422912Sartem }
7432912Sartem 
7442912Sartem static void
devinfo_lofi_add_minor(HalDevice * parent,di_node_t node,char * minor_path,char * devlink,dev_t dev)7452912Sartem devinfo_lofi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, char *devlink, dev_t dev)
7462912Sartem {
7472912Sartem 	HalDevice *d;
7482912Sartem 	char	*raw;
7492912Sartem 	char	*doslink;
7502912Sartem 	char	dospath[64];
7512912Sartem 	struct devinfo_storage_minor *m;
7522912Sartem 	int	i;
7532912Sartem 
7542912Sartem 	/* add storage */
7552912Sartem 	d = hal_device_new ();
7562912Sartem 
7572912Sartem 	devinfo_set_default_properties (d, parent, node, minor_path);
7582912Sartem         hal_device_property_set_string (d, "info.category", "storage");
7592912Sartem         hal_device_add_capability (d, "storage");
7602912Sartem        	hal_device_property_set_string (d, "storage.bus", "lofi");
7612912Sartem         hal_device_property_set_bool (d, "storage.hotpluggable", TRUE);
7622912Sartem         hal_device_property_set_bool (d, "storage.removable", FALSE);
7632912Sartem         hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
7642912Sartem        	hal_device_property_set_string (d, "storage.drive_type", "disk");
7652912Sartem         hal_device_add_capability (d, "block");
7662912Sartem 	hal_device_property_set_int (d, "block.major", major(dev));
7672912Sartem 	hal_device_property_set_int (d, "block.minor", minor(dev));
7682912Sartem 	hal_device_property_set_string (d, "block.device", devlink);
7692912Sartem 	raw = dsk_to_rdsk (devlink);
7702912Sartem 	hal_device_property_set_string (d, "block.solaris.raw_device", raw);
7712912Sartem 	free (raw);
7722912Sartem 	hal_device_property_set_bool (d, "block.is_volume", FALSE);
7732912Sartem 
7742912Sartem 	devinfo_add_enqueue (d, minor_path, &devinfo_storage_handler);
7752912Sartem 
7762912Sartem 	/* add volumes: one on main device and a few pcfs candidates */
7772912Sartem 	m = devinfo_storage_new_minor(minor_path, WHOLE_DISK, devlink, dev, -1);
7782912Sartem 	devinfo_volume_add (d, node, m);
7792912Sartem 	devinfo_storage_free_minor (m);
7802912Sartem 
7812912Sartem 	doslink = (char *)calloc (1, strlen (devlink) + sizeof (":NNN") + 1);
7822912Sartem 	if (doslink != NULL) {
7832912Sartem 		for (i = 1; i < 16; i++) {
7842912Sartem 			snprintf(dospath, sizeof (dospath), WHOLE_DISK":%d", i);
7852912Sartem 			sprintf(doslink, "%s:%d", devlink, i);
7862912Sartem 			m = devinfo_storage_new_minor(minor_path, dospath, doslink, dev, i);
7872912Sartem 			devinfo_volume_add (d, node, m);
7882912Sartem 			devinfo_storage_free_minor (m);
7892912Sartem 		}
7902912Sartem 		free (doslink);
7912912Sartem 	}
7922912Sartem }
7932912Sartem 
7942912Sartem void
devinfo_lofi_remove_minor(char * parent_devfs_path,char * name)7952912Sartem devinfo_lofi_remove_minor(char *parent_devfs_path, char *name)
7962912Sartem {
7972912Sartem 	GSList *i;
7982912Sartem 	GSList *devices;
7992912Sartem 	HalDevice *d = NULL;
8002912Sartem 	const char *devfs_path;
8012912Sartem 
8022912Sartem 	devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
8032912Sartem 		"block.solaris.raw_device", name);
8042912Sartem         for (i = devices; i != NULL; i = g_slist_next (i)) {
8052912Sartem 		if (hal_device_has_capability (HAL_DEVICE (i->data), "storage")) {
8062912Sartem 			d = HAL_DEVICE (i->data);
8072912Sartem 			break;
8082912Sartem 		}
8092912Sartem 	}
8102912Sartem 	g_slist_free (devices);
8112912Sartem 
8122912Sartem 	if (d == NULL) {
8132912Sartem 		HAL_INFO (("device not found %s", name));
8142912Sartem 		return;
8152912Sartem 	}
8162912Sartem 
8172912Sartem 	if ((devfs_path = hal_device_property_get_string (d,
8182912Sartem 	    "solaris.devfs_path")) == NULL) {
8193121Sartem 		HAL_INFO (("devfs_path not found %s", hal_device_get_udi (d)));
8202912Sartem 		return;
8212912Sartem 	}
8222912Sartem 
8232912Sartem 	if (d != NULL) {
8242912Sartem 		devinfo_remove_branch ((char *)devfs_path, d);
8252912Sartem 	}
8262912Sartem }
8272912Sartem 
8282912Sartem /* common storage */
8292912Sartem 
8302912Sartem static void
devinfo_storage_free_minor(struct devinfo_storage_minor * m)8312912Sartem devinfo_storage_free_minor(struct devinfo_storage_minor *m)
8322912Sartem {
8332912Sartem 	if (m != NULL) {
8342912Sartem 		free (m->slice);
8352912Sartem 		free (m->devlink);
8362912Sartem 		free (m->devpath);
8372912Sartem 		free (m);
8382912Sartem 	}
8392912Sartem }
8402912Sartem 
8412912Sartem static struct devinfo_storage_minor *
devinfo_storage_new_minor(char * maindev_path,char * slice,char * devlink,dev_t dev,int dosnum)8422912Sartem devinfo_storage_new_minor(char *maindev_path, char *slice, char *devlink, dev_t dev, int dosnum)
8432912Sartem {
8442912Sartem 	struct devinfo_storage_minor *m;
8452912Sartem 	int pathlen;
8462912Sartem 	char *devpath;
8472912Sartem 
8482912Sartem 	m = (struct devinfo_storage_minor *)calloc (sizeof (struct devinfo_storage_minor), 1);
8492912Sartem 	if (m != NULL) {
8502912Sartem 		/*
8512912Sartem 		 * For volume's devfs_path we'll use minor_path/slice instead of
8522912Sartem 		 * minor_path which we use for parent storage device.
8532912Sartem 		 */
8542912Sartem 		pathlen = strlen (maindev_path) + strlen (slice) + 2;
8552912Sartem 		devpath = (char *)calloc (1, pathlen);
8562912Sartem 		snprintf(devpath, pathlen, "%s/%s", maindev_path, slice);
8572912Sartem 
8582912Sartem 		m->devpath = devpath;
8592912Sartem 		m->devlink = strdup (devlink);
8602912Sartem 		m->slice = strdup (slice);
8612912Sartem 		m->dev = dev;
8622912Sartem 		m->dosnum = dosnum;
8632912Sartem 		if ((m->devpath == NULL) || (m->devlink == NULL)) {
8642912Sartem 			devinfo_storage_free_minor (m);
8652912Sartem 			m = NULL;
8662912Sartem 		}
8672912Sartem 	}
8682912Sartem 	return (m);
8692912Sartem }
8702912Sartem 
8712912Sartem /*
8722912Sartem  * Storage minor nodes are potential "volume" objects.
8732912Sartem  * This function also completes building the parent object (main storage device).
8742912Sartem  */
8752912Sartem static void
devinfo_storage_minors(HalDevice * parent,di_node_t node,gchar * devfs_path,gboolean rescan)8762912Sartem devinfo_storage_minors(HalDevice *parent, di_node_t node, gchar *devfs_path, gboolean rescan)
8772912Sartem {
8782912Sartem 	di_devlink_handle_t devlink_hdl;
8792912Sartem 	gboolean is_cdrom;
8802912Sartem 	const char *whole_disk;
8812912Sartem 	int     major;
8822912Sartem 	di_minor_t minor;
8832912Sartem 	dev_t   dev;
8842912Sartem 	char    *minor_path = NULL;
8852912Sartem 	char    *maindev_path = NULL;
8862912Sartem 	char    *devpath, *devlink;
8872912Sartem 	int	doslink_len;
8882912Sartem 	char	*doslink;
8892912Sartem 	char	dospath[64];
8902912Sartem 	char    *slice;
8912912Sartem 	int	pathlen;
8922912Sartem 	int	i;
8932912Sartem 	char	*raw;
8942912Sartem 	boolean_t maindev_is_d0;
8952912Sartem 	GQueue	*mq;
8962912Sartem 	HalDevice *volume;
8972912Sartem 	struct devinfo_storage_minor *m;
8982912Sartem 	struct devinfo_storage_minor *maindev = NULL;
8992912Sartem 
9002912Sartem 	/* for cdroms whole disk is always s2 */
9012912Sartem 	is_cdrom = hal_device_has_capability (parent, "storage.cdrom");
9022912Sartem 	whole_disk = is_cdrom ? "s2" : WHOLE_DISK;
9032912Sartem 
9042912Sartem 	major = di_driver_major(node);
9052912Sartem 
9062912Sartem 	/* the "whole disk" p0/s2/d0 node must come first in the hotplug queue
9072912Sartem 	 * so we put other minor nodes on the local queue and move to the
9082912Sartem 	 * hotplug queue up in the end
9092912Sartem 	 */
9102912Sartem 	if ((mq = g_queue_new()) == NULL) {
9112912Sartem 		goto err;
9122912Sartem 	}
9132912Sartem 	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
9142912Sartem 		g_queue_free (mq);
9152912Sartem 		goto err;
9162912Sartem 	}
9172912Sartem 	minor = DI_MINOR_NIL;
9182912Sartem 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
9192912Sartem 		dev = di_minor_devt(minor);
9202912Sartem 		if ((major != major(dev)) ||
9212912Sartem 		    (di_minor_type(minor) != DDM_MINOR) ||
9222912Sartem 		    (di_minor_spectype(minor) != S_IFBLK) ||
9232912Sartem 		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
9242912Sartem 			continue;
9252912Sartem 		}
9263536Sjacobs 		if ((devlink = get_devlink(devlink_hdl, NULL, minor_path)) == NULL) {
9272912Sartem 			di_devfs_path_free (minor_path);
9282912Sartem         		continue;
9292912Sartem 		}
9302912Sartem 
9312912Sartem 		slice = devinfo_volume_get_slice_name (devlink);
9322912Sartem 		if (strlen (slice) < 2) {
9332912Sartem 			free (devlink);
9342912Sartem 			di_devfs_path_free (minor_path);
9352912Sartem 			continue;
9362912Sartem 		}
9372912Sartem 
9382912Sartem 		/* ignore p1..N - we'll use p0:N instead */
9392912Sartem 		if ((strlen (slice) > 1) && (slice[0] == 'p') && isdigit(slice[1]) &&
9402912Sartem 		    ((atol(&slice[1])) > 0)) {
9412912Sartem 			free (devlink);
9422912Sartem 			di_devfs_path_free (minor_path);
9432912Sartem 			continue;
9442912Sartem 		}
9452912Sartem 
9462912Sartem 		m = devinfo_storage_new_minor(minor_path, slice, devlink, dev, -1);
9472912Sartem 		if (m == NULL) {
9482912Sartem 			free (devlink);
9492912Sartem 			di_devfs_path_free (minor_path);
9502912Sartem 			continue;
9512912Sartem 		}
9522912Sartem 
9532912Sartem 		/* main device is either s2/p0 or d0, the latter taking precedence */
9542912Sartem 		if ((strcmp (slice, "d0") == 0) ||
9552912Sartem 		    (((strcmp (slice, whole_disk) == 0) && (maindev == NULL)))) {
9562912Sartem 			if (maindev_path != NULL) {
9572912Sartem 				di_devfs_path_free (maindev_path);
9582912Sartem 			}
9592912Sartem 			maindev_path = minor_path;
9602912Sartem 			maindev = m;
9612912Sartem 			g_queue_push_head (mq, maindev);
9622912Sartem 		} else {
9632912Sartem 			di_devfs_path_free (minor_path);
9642912Sartem 			g_queue_push_tail (mq, m);
9652912Sartem 		}
9662912Sartem 
9672912Sartem 		free (devlink);
9682912Sartem 	}
9692912Sartem 	di_devlink_fini (&devlink_hdl);
9702912Sartem 
9712912Sartem 	if (maindev == NULL) {
9722912Sartem 		/* shouldn't typically happen */
9732912Sartem 		while (!g_queue_is_empty (mq)) {
9742912Sartem 			devinfo_storage_free_minor (g_queue_pop_head (mq));
9752912Sartem 		}
9762912Sartem 		goto err;
9772912Sartem 	}
9782912Sartem 
9792912Sartem 	/* first enqueue main storage device */
9802912Sartem 	if (!rescan) {
9812912Sartem 		hal_device_property_set_int (parent, "block.major", major);
9822912Sartem 		hal_device_property_set_int (parent, "block.minor", minor(maindev->dev));
9832912Sartem 		hal_device_property_set_string (parent, "block.device", maindev->devlink);
9842912Sartem 		raw = dsk_to_rdsk (maindev->devlink);
9852912Sartem 		hal_device_property_set_string (parent, "block.solaris.raw_device", raw);
9862912Sartem 		free (raw);
9872912Sartem 		hal_device_property_set_bool (parent, "block.is_volume", FALSE);
9882912Sartem 		hal_device_property_set_string (parent, "solaris.devfs_path", maindev_path);
9892912Sartem 		devinfo_add_enqueue (parent, maindev_path, &devinfo_storage_handler);
9902912Sartem 	}
9912912Sartem 
9922912Sartem 	/* add virtual dos volumes to enable pcfs probing */
9932912Sartem 	if (!is_cdrom) {
9942912Sartem 		doslink_len = strlen (maindev->devlink) + sizeof (":NNN") + 1;
9952912Sartem 		if ((doslink = (char *)calloc (1, doslink_len)) != NULL) {
9962912Sartem 			for (i = 1; i < 16; i++) {
9972912Sartem 				snprintf(dospath, sizeof (dospath), "%s:%d", maindev->slice, i);
9982912Sartem 				snprintf(doslink, doslink_len, "%s:%d", maindev->devlink, i);
9992912Sartem 				m = devinfo_storage_new_minor(maindev_path, dospath, doslink, maindev->dev, i);
10002912Sartem 				g_queue_push_tail (mq, m);
10012912Sartem 			}
10022912Sartem 			free (doslink);
10032912Sartem 		}
10042912Sartem 	}
10052912Sartem 
10062912Sartem 	maindev_is_d0 = (strcmp (maindev->slice, "d0") == 0);
10072912Sartem 
10082912Sartem 	/* enqueue all volumes */
10092912Sartem 	while (!g_queue_is_empty (mq)) {
10102912Sartem 		m = g_queue_pop_head (mq);
10112912Sartem 
10122912Sartem 		/* if main device is d0, we'll throw away s2/p0 */
10132912Sartem 		if (maindev_is_d0 && (strcmp (m->slice, whole_disk) == 0)) {
10142912Sartem 			devinfo_storage_free_minor (m);
10152912Sartem 			continue;
10162912Sartem 		}
10172912Sartem 		/* don't do p0 on cdrom */
10182912Sartem 		if (is_cdrom && (strcmp (m->slice, "p0") == 0)) {
10192912Sartem 			devinfo_storage_free_minor (m);
10202912Sartem 			continue;
10212912Sartem 		}
10222912Sartem 		if (rescan) {
10232912Sartem 			/* in rescan mode, don't reprobe existing volumes */
10242912Sartem 			/* XXX detect volume removal? */
10252912Sartem 			volume = hal_device_store_match_key_value_string (hald_get_gdl (),
10262912Sartem 			    "solaris.devfs_path", m->devpath);
10272912Sartem 			if ((volume == NULL) || !hal_device_has_capability(volume, "volume")) {
10282912Sartem 				devinfo_volume_add (parent, node, m);
10292912Sartem 			} else {
10302912Sartem 				HAL_INFO(("rescan volume exists %s", m->devpath));
10312912Sartem 			}
10322912Sartem 		} else {
10332912Sartem 			devinfo_volume_add (parent, node, m);
10342912Sartem 		}
10352912Sartem 		devinfo_storage_free_minor (m);
10362912Sartem 	}
10372912Sartem 
10382912Sartem 	if (maindev_path != NULL) {
10392912Sartem 		di_devfs_path_free (maindev_path);
10402912Sartem 	}
10412912Sartem 
10422912Sartem 	return;
10432912Sartem 
10442912Sartem err:
10452912Sartem 	if (maindev_path != NULL) {
10462912Sartem 		di_devfs_path_free (maindev_path);
10472912Sartem 	}
10482912Sartem 	if (!rescan) {
10492912Sartem 		devinfo_add_enqueue (parent, devfs_path, &devinfo_storage_handler);
10502912Sartem 	}
10512912Sartem }
10522912Sartem 
10532912Sartem HalDevice *
devinfo_volume_add(HalDevice * parent,di_node_t node,devinfo_storage_minor_t * m)10542912Sartem devinfo_volume_add(HalDevice *parent, di_node_t node, devinfo_storage_minor_t *m)
10552912Sartem {
10562912Sartem 	HalDevice *d;
10572912Sartem 	char	*raw;
10582912Sartem         char    udi[HAL_PATH_MAX];
10592912Sartem 	char	*devfs_path = m->devpath;
10602912Sartem 	char	*devlink = m->devlink;
10612912Sartem 	dev_t	dev = m->dev;
10622912Sartem 	int	dosnum = m->dosnum;
10632912Sartem 	char	*slice = m->slice;
10642912Sartem 
10652912Sartem 	HAL_INFO (("volume_add: devfs_path=%s devlink=%s", devfs_path, devlink));
10662912Sartem 	d = hal_device_new ();
10672912Sartem 
10682912Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
10692912Sartem         hal_device_property_set_string (d, "info.category", "volume");
10702912Sartem 
10712912Sartem        	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
10723121Sartem 		"%s/%s", hal_device_get_udi (parent), slice);
10732912Sartem         hal_device_set_udi (d, udi);
10742912Sartem         hal_device_property_set_string (d, "info.udi", udi);
10752912Sartem         hal_device_property_set_string (d, "info.product", slice);
10762912Sartem 
10772912Sartem        	hal_device_add_capability (d, "volume");
10782912Sartem        	hal_device_add_capability (d, "block");
10792912Sartem 	hal_device_property_set_int (d, "block.major", major (dev));
10802912Sartem 	hal_device_property_set_int (d, "block.minor", minor (dev));
10812912Sartem 	hal_device_property_set_string (d, "block.device", devlink);
10822912Sartem 	raw = dsk_to_rdsk (devlink);
10832912Sartem 	hal_device_property_set_string (d, "block.solaris.raw_device", raw);
10842912Sartem 	free (raw);
10852912Sartem 	hal_device_property_set_string (d, "block.solaris.slice", slice);
10862912Sartem 	hal_device_property_set_bool (d, "block.is_volume", TRUE); /* XXX */
10872912Sartem 
10883121Sartem 	hal_device_property_set_string (d, "block.storage_device", hal_device_get_udi (parent));
10892912Sartem 
10902912Sartem 	/* set volume defaults */
10912912Sartem 	hal_device_property_set_string (d, "volume.fstype", "");
10922912Sartem 	hal_device_property_set_string (d, "volume.fsusage", "");
10932912Sartem 	hal_device_property_set_string (d, "volume.fsversion", "");
10942912Sartem 	hal_device_property_set_string (d, "volume.uuid", "");
10952912Sartem 	hal_device_property_set_string (d, "volume.label", "");
10962912Sartem 	hal_device_property_set_string (d, "volume.mount_point", "");
10972912Sartem 	hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
10982912Sartem 	if (strcmp (hal_device_property_get_string (parent, "storage.drive_type"), "cdrom") == 0) {
10992912Sartem 		hal_device_property_set_bool (d, "volume.is_disc", TRUE);
11002912Sartem 		hal_device_add_capability (d, "volume.disc");
11012912Sartem 	} else {
11022912Sartem 		hal_device_property_set_bool (d, "volume.is_disc", FALSE);
11032912Sartem 	}
11042912Sartem 
11052912Sartem 	if (dosnum > 0) {
11062912Sartem 		hal_device_property_set_bool (d, "volume.is_partition", TRUE);
11072912Sartem 		hal_device_property_set_int (d, "volume.partition.number", dosnum);
11082912Sartem 	} else {
11092912Sartem 		hal_device_property_set_bool (d, "volume.is_partition", FALSE);
11102912Sartem 	}
11112912Sartem 
11122912Sartem 	/* prober may override these */
11132912Sartem         hal_device_property_set_int (d, "volume.block_size", 512);
11142912Sartem 
11152912Sartem 	devinfo_add_enqueue (d, devfs_path, &devinfo_volume_handler);
11162912Sartem 
11172912Sartem 	return (d);
11182912Sartem }
11192912Sartem 
11202912Sartem static void
devinfo_volume_preprobing_done(HalDevice * d,gpointer userdata1,gpointer userdata2)11212912Sartem devinfo_volume_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
11222912Sartem {
11232912Sartem 	void *end_token = (void *) userdata1;
11242912Sartem 	char *whole_disk;
11252912Sartem 	char *block_device;
11262912Sartem 	const char *storage_udi;
11272912Sartem 	HalDevice *storage_d;
11282912Sartem 	const char *slice;
11292912Sartem 	int dos_num;
11302912Sartem 
11312912Sartem 	if (hal_device_property_get_bool (d, "info.ignore")) {
11323121Sartem 		HAL_INFO (("Preprobing merged info.ignore==TRUE %s", hal_device_get_udi (d)));
11332912Sartem 		goto skip;
11342912Sartem 	}
11352912Sartem 
11362912Sartem 	/*
11372912Sartem 	 * Optimizations: only probe if there's a chance to find something
11382912Sartem 	 */
11392912Sartem 	block_device = (char *)hal_device_property_get_string (d, "block.device");
11402912Sartem 	storage_udi = hal_device_property_get_string (d, "block.storage_device");
11412912Sartem 	slice = hal_device_property_get_string(d, "block.solaris.slice");
11422912Sartem 	if ((block_device == NULL) || (storage_udi == NULL) ||
11432912Sartem 	    (slice == NULL) || (strlen (slice) < 2)) {
11443121Sartem 		HAL_INFO (("Malformed volume properties %s", hal_device_get_udi (d)));
11452912Sartem 		goto skip;
11462912Sartem 	}
11472912Sartem 	storage_d = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", storage_udi);
11482912Sartem 	if (storage_d == NULL) {
11493121Sartem 		HAL_INFO (("Storage device not found %s", hal_device_get_udi (d)));
11502912Sartem 		goto skip;
11512912Sartem 	}
11522912Sartem 
11532912Sartem 	whole_disk = hal_device_has_capability (storage_d,
11542912Sartem 	    "storage.cdrom") ? "s2" : WHOLE_DISK;
11552912Sartem 
11562912Sartem 	if (is_dos_path(block_device, &dos_num)) {
11572912Sartem 		/* don't probe more dos volumes than probe-storage found */
11582912Sartem 		if ((hal_device_property_get_bool (storage_d, "storage.no_partitions_hint") ||
11592912Sartem 		    (dos_num > hal_device_property_get_int (storage_d, "storage.solaris.num_dos_partitions")))) {
11602912Sartem 			    HAL_INFO (("%d > %d %s", dos_num, hal_device_property_get_int (storage_d,
11613121Sartem 				"storage.solaris.num_dos_partitions"), hal_device_get_udi (storage_d)));
11622912Sartem 			goto skip;
11632912Sartem 		}
11642912Sartem 	} else {
11652912Sartem 		/* if no VTOC slices found, don't probe slices except s2 */
11662912Sartem 		if ((slice[0] == 's') && (isdigit(slice[1])) && ((strcmp (slice, whole_disk)) != 0) &&
11672912Sartem 		    !hal_device_property_get_bool (storage_d, "storage.solaris.vtoc_slices")) {
11683121Sartem 			HAL_INFO (("Not probing slice %s", hal_device_get_udi (d)));
11692912Sartem 			goto skip;
11702912Sartem 		}
11712912Sartem 	}
11722912Sartem 
11733121Sartem 	HAL_INFO(("Probing udi=%s", hal_device_get_udi (d)));
11742912Sartem 	hald_runner_run (d,
11752912Sartem 			"hald-probe-volume", NULL,
11762912Sartem 			DEVINFO_PROBE_VOLUME_TIMEOUT,
11772912Sartem 			devinfo_callouts_probing_done,
11782912Sartem 			(gpointer) end_token, userdata2);
11792912Sartem 
11802912Sartem 	return;
11812912Sartem 
11822912Sartem skip:
11832912Sartem 	hal_device_store_remove (hald_get_tdl (), d);
11842912Sartem 	g_object_unref (d);
11852912Sartem 	hotplug_event_end (end_token);
11862912Sartem }
11872912Sartem 
11882912Sartem static void
devinfo_volume_hotplug_begin_add(HalDevice * d,HalDevice * parent,DevinfoDevHandler * handler,void * end_token)11892912Sartem devinfo_volume_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token)
11902912Sartem {
11913121Sartem 	HAL_INFO(("Preprobing volume udi=%s", hal_device_get_udi (d)));
11922912Sartem 
11938100SLin.Guo@Sun.COM 	if (parent == NULL) {
11948100SLin.Guo@Sun.COM 		HAL_INFO (("no parent %s", hal_device_get_udi (d)));
11958100SLin.Guo@Sun.COM 		goto skip;
11968100SLin.Guo@Sun.COM 	}
11978100SLin.Guo@Sun.COM 
11982912Sartem 	if (hal_device_property_get_bool (parent, "info.ignore")) {
11992912Sartem 		HAL_INFO (("Ignoring volume: parent's info.ignore is TRUE"));
12002912Sartem 		goto skip;
12012912Sartem 	}
12022912Sartem 
12032912Sartem         /* add to TDL so preprobing callouts and prober can access it */
12042912Sartem         hal_device_store_add (hald_get_tdl (), d);
12052912Sartem 
12062912Sartem         /* Process preprobe fdi files */
12072912Sartem         di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
12082912Sartem 
12092912Sartem         /* Run preprobe callouts */
12102912Sartem         hal_util_callout_device_preprobe (d, devinfo_volume_preprobing_done, end_token, handler);
12112912Sartem 
12122912Sartem 	return;
12132912Sartem 
12142912Sartem skip:
12152912Sartem 	g_object_unref (d);
12162912Sartem 	hotplug_event_end (end_token);
12172912Sartem }
12182912Sartem 
12192912Sartem void
devinfo_storage_hotplug_begin_add(HalDevice * d,HalDevice * parent,DevinfoDevHandler * handler,void * end_token)12202912Sartem devinfo_storage_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token)
12212912Sartem {
12222912Sartem 	const char *drive_type;
12232912Sartem 	const char *p_udi;
12242912Sartem 	HalDevice *p_d;
12252912Sartem 	HalDevice *phys_d = NULL;
12262912Sartem 	const char *phys_bus;
12272912Sartem 	const char *bus;
12282912Sartem 	static const char *busses[] = { "usb", "ide", "scsi", "ieee1394",
12292912Sartem 					"pseudo" };
12302912Sartem 	int i;
12312912Sartem 
12323121Sartem 	HAL_INFO (("Preprobing udi=%s", hal_device_get_udi (d)));
12332912Sartem 
12342912Sartem 	if (parent == NULL) {
12353121Sartem 		HAL_INFO (("no parent %s", hal_device_get_udi (d)));
12362912Sartem 		goto error;
12372912Sartem 	}
12382912Sartem 
12392912Sartem 	/*
12402912Sartem 	 * figure out physical device and bus, except for floppy
12412912Sartem 	 */
12422912Sartem 	drive_type = hal_device_property_get_string (d, "storage.drive_type");
12432912Sartem 	if ((drive_type != NULL) && (strcmp (drive_type, "floppy") == 0)) {
12442912Sartem 		goto skip_bus;
12452912Sartem 	}
12462912Sartem 
12472912Sartem 	p_d = parent;
12482912Sartem 	for (;;) {
12496112Sqz150045 		bus = hal_device_property_get_string (p_d, "info.subsystem");
12502912Sartem 		if (bus != NULL) {
12512912Sartem 			for (i = 0; i < NELEM(busses); i++) {
12522912Sartem 				if (strcmp(bus, busses[i]) == 0) {
12532912Sartem 					phys_d = p_d;
12542912Sartem 					phys_bus = busses[i];
12552912Sartem 					break;
12562912Sartem 				}
12572912Sartem 			}
12582912Sartem 		}
12592912Sartem 		/* up the tree */
12602912Sartem 		p_udi = hal_device_property_get_string (p_d, "info.parent");
12612912Sartem 		if (p_udi == NULL) {
12622912Sartem 			break;
12632912Sartem 		}
12642912Sartem 		p_d = hal_device_store_find (hald_get_gdl (), p_udi);
12652912Sartem 	}
12662912Sartem 	if (phys_d == NULL) {
12673121Sartem 		HAL_INFO (("no physical device %s", hal_device_get_udi (d)));
12683121Sartem 	} else {
12693121Sartem 		hal_device_property_set_string (d, "storage.physical_device", hal_device_get_udi (phys_d));
12703121Sartem 		hal_device_property_set_string (d, "storage.bus", phys_bus);
12712912Sartem 	}
12722912Sartem 
12732912Sartem skip_bus:
12742912Sartem 
12752912Sartem 	/* add to TDL so preprobing callouts and prober can access it */
12762912Sartem 	hal_device_store_add (hald_get_tdl (), d);
12772912Sartem 
12782912Sartem 	/* Process preprobe fdi files */
12792912Sartem 	di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
12802912Sartem 
12812912Sartem 	/* Run preprobe callouts */
12822912Sartem 	hal_util_callout_device_preprobe (d, devinfo_callouts_preprobing_done, end_token, handler);
12832912Sartem 
12842912Sartem 	return;
12852912Sartem 
12862912Sartem error:
12872912Sartem 	g_object_unref (d);
12882912Sartem 	hotplug_event_end (end_token);
12892912Sartem }
12902912Sartem 
12912912Sartem static void
devinfo_storage_probing_done(HalDevice * d,guint32 exit_type,gint return_code,char ** error,gpointer userdata1,gpointer userdata2)12922912Sartem devinfo_storage_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2)
12932912Sartem {
12942912Sartem         void *end_token = (void *) userdata1;
12952912Sartem 
12963121Sartem 	HAL_INFO (("devinfo_storage_probing_done %s", hal_device_get_udi (d)));
12972912Sartem 
12982912Sartem         /* Discard device if probing reports failure */
12992912Sartem         if (exit_type != HALD_RUN_SUCCESS || return_code != 0) {
13002912Sartem 		HAL_INFO (("devinfo_storage_probing_done returning exit_type=%d return_code=%d", exit_type, return_code));
13012912Sartem                 hal_device_store_remove (hald_get_tdl (), d);
13022912Sartem                 g_object_unref (d);
13032912Sartem                 hotplug_event_end (end_token);
13042912Sartem 		return;
13052912Sartem         }
13062912Sartem 
13072912Sartem 	devinfo_storage_set_nicknames (d);
13082912Sartem 
13092912Sartem         /* Merge properties from .fdi files */
13102912Sartem         di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
13112912Sartem         di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
13122912Sartem 
13132912Sartem 	hal_util_callout_device_add (d, devinfo_callouts_add_done, end_token, NULL);
13142912Sartem }
13152912Sartem 
13162912Sartem const gchar *
devinfo_storage_get_prober(HalDevice * d,int * timeout)13172912Sartem devinfo_storage_get_prober (HalDevice *d, int *timeout)
13182912Sartem {
13192912Sartem 	*timeout = DEVINFO_PROBE_STORAGE_TIMEOUT;
13202912Sartem 	return "hald-probe-storage";
13212912Sartem }
13222912Sartem 
13232912Sartem const gchar *
devinfo_volume_get_prober(HalDevice * d,int * timeout)13242912Sartem devinfo_volume_get_prober (HalDevice *d, int *timeout)
13252912Sartem {
13262912Sartem 	*timeout = DEVINFO_PROBE_VOLUME_TIMEOUT;
13272912Sartem 	return "hald-probe-volume";
13282912Sartem }
13292912Sartem 
13302912Sartem /*
13312912Sartem  * After reprobing storage, reprobe its volumes.
13322912Sartem  */
13332912Sartem static void
devinfo_storage_rescan_probing_done(HalDevice * d,guint32 exit_type,gint return_code,char ** error,gpointer userdata1,gpointer userdata2)13342912Sartem devinfo_storage_rescan_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2)
13352912Sartem {
13362912Sartem         void *end_token = (void *) userdata1;
13372912Sartem 	const char *devfs_path_orig = NULL;
13382912Sartem 	char *devfs_path = NULL;
13392912Sartem 	char *p;
13402912Sartem 	di_node_t node;
13412912Sartem 
13423121Sartem 	HAL_INFO (("devinfo_storage_rescan_probing_done %s", hal_device_get_udi (d)));
13432912Sartem 
13442912Sartem 	devfs_path_orig = hal_device_property_get_string (d, "solaris.devfs_path");
13452912Sartem 	if (devfs_path_orig == NULL) {
13462912Sartem 		HAL_INFO (("device has no solaris.devfs_path"));
13472912Sartem 		hotplug_event_process_queue ();
13482912Sartem 		return;
13492912Sartem 	}
13502912Sartem 
13512912Sartem 	/* strip trailing minor part if any */
13522912Sartem 	if (strrchr(devfs_path_orig, ':') != NULL) {
13532912Sartem 		if ((devfs_path = strdup (devfs_path_orig)) != NULL) {
13542912Sartem 			p = strrchr(devfs_path, ':');
13552912Sartem 			*p = '\0';
13562912Sartem 		}
13572912Sartem 	} else {
13582912Sartem 		devfs_path = (char *)devfs_path_orig;
13592912Sartem 	}
13602912Sartem 
13612912Sartem 	if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
13623121Sartem 		HAL_INFO (("di_init %s failed %d %s", devfs_path, errno, hal_device_get_udi (d)));
13632912Sartem 		hotplug_event_process_queue ();
13642912Sartem 		return;
13652912Sartem 	} else {
13662912Sartem 		devinfo_storage_minors (d, node, (char *)devfs_path, TRUE);
13672912Sartem 		di_fini (node);
13682912Sartem 	}
13692912Sartem 
13702912Sartem 	if (devfs_path != devfs_path_orig) {
13712912Sartem 		free (devfs_path);
13722912Sartem 	}
13732912Sartem 
13742912Sartem 	hotplug_event_process_queue ();
13752912Sartem }
13762912Sartem 
13772912Sartem /*
13782912Sartem  * For removable media devices, check for "storage.removable.media_available".
13792912Sartem  * For non-removable media devices, assume media is always there.
13802912Sartem  *
13812912Sartem  * If media is gone, enqueue remove events for all children volumes.
13822912Sartem  * If media is there, first reprobe storage, then probe for new volumes (but leave existing volumes alone).
13832912Sartem  */
13842912Sartem gboolean
devinfo_storage_device_rescan(HalDevice * d)13852912Sartem devinfo_storage_device_rescan (HalDevice *d)
13862912Sartem {
13872912Sartem 	GSList *i;
13882912Sartem 	GSList *volumes;
13892912Sartem 	HalDevice *v;
13902912Sartem 	gchar *v_devfs_path;
13912912Sartem 	const char *drive_type;
13922912Sartem 	gboolean is_floppy;
13932912Sartem 	gboolean media_available;
13942912Sartem 
13953121Sartem 	HAL_INFO (("devinfo_storage_device_rescan udi=%s", hal_device_get_udi (d)));
13962912Sartem 
13972912Sartem 	if (hal_device_property_get_bool (d, "block.is_volume")) {
13982912Sartem 		HAL_INFO (("nothing to do for volume"));
13992912Sartem 		return (FALSE);
14002912Sartem 	}
14012912Sartem 
14022912Sartem 	drive_type = hal_device_property_get_string (d, "storage.drive_type");
14032912Sartem 	is_floppy = (drive_type != NULL) && (strcmp (drive_type, "floppy") == 0);
14042912Sartem 
14052912Sartem 	media_available = !hal_device_property_get_bool (d, "storage.removable") ||
14062912Sartem 	    hal_device_property_get_bool (d, "storage.removable.media_available");
14072912Sartem 
14082912Sartem 	if (!media_available && !is_floppy) {
14093121Sartem 		HAL_INFO (("media gone %s", hal_device_get_udi (d)));
14102912Sartem 
14112912Sartem 		volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
14123121Sartem         	    "block.storage_device", hal_device_get_udi (d));
14132912Sartem 		for (i = volumes; i != NULL; i = g_slist_next (i)) {
14142912Sartem         		v = HAL_DEVICE (i->data);
14152912Sartem 			v_devfs_path = (gchar *)hal_device_property_get_string (v, "solaris.devfs_path");
14163121Sartem 			HAL_INFO (("child volume %s", hal_device_get_udi (v)));
14172912Sartem 			if ((v_devfs_path != NULL) && hal_device_has_capability (v, "volume")) {
14183121Sartem 				HAL_INFO (("removing volume %s", hal_device_get_udi (v)));
14192912Sartem 				devinfo_remove_enqueue (v_devfs_path, NULL);
14202912Sartem 			} else {
14213121Sartem 				HAL_INFO (("not a volume %s", hal_device_get_udi (v)));
14222912Sartem 			}
14232912Sartem 		}
14242912Sartem 		g_slist_free (volumes);
14252912Sartem 
14262912Sartem 		hotplug_event_process_queue ();
14272912Sartem 	} else if (is_floppy) {
14283121Sartem 		HAL_INFO (("rescanning floppy %s", hal_device_get_udi (d)));
14292912Sartem 
14302912Sartem 		hald_runner_run (d,
14312912Sartem 				 "hald-probe-storage --only-check-for-media", NULL,
14322912Sartem 				 DEVINFO_PROBE_STORAGE_TIMEOUT,
14332912Sartem 				 devinfo_floppy_rescan_probing_done,
14342912Sartem 				 NULL, NULL);
14352912Sartem 	} else {
14363121Sartem 		HAL_INFO (("media available %s", hal_device_get_udi (d)));
14372912Sartem 
14382912Sartem 		hald_runner_run (d,
14392912Sartem 				 "hald-probe-storage --only-check-for-media", NULL,
14402912Sartem 				 DEVINFO_PROBE_STORAGE_TIMEOUT,
14412912Sartem 				 devinfo_storage_rescan_probing_done,
14422912Sartem 				 NULL, NULL);
14432912Sartem 	}
14442912Sartem 
14452912Sartem 	return TRUE;
14462912Sartem }
14472912Sartem 
14482912Sartem static char *
devinfo_volume_get_slice_name(char * devlink)14492912Sartem devinfo_volume_get_slice_name (char *devlink)
14502912Sartem {
14512912Sartem 	char	*part, *slice, *disk;
14522912Sartem 	char	*s = NULL;
14532912Sartem 	char	*p;
14542912Sartem 
14552912Sartem 	if ((p = strstr(devlink, "/lofi/")) != 0) {
14562912Sartem 		return (p + sizeof ("/lofi/") - 1);
14572912Sartem 	}
14582912Sartem 
14592912Sartem 	part = strrchr(devlink, 'p');
14602912Sartem 	slice = strrchr(devlink, 's');
14612912Sartem 	disk = strrchr(devlink, 'd');
14622912Sartem 
14632912Sartem 	if ((part != NULL) && (part > slice) && (part > disk)) {
14642912Sartem 		s = part;
14652912Sartem 	} else if ((slice != NULL) && (slice > disk)) {
14662912Sartem 		s = slice;
14672912Sartem 	} else {
14682912Sartem 		s = disk;
14692912Sartem 	}
14702912Sartem 	if ((s != NULL) && isdigit(s[1])) {
14712912Sartem 		return (s);
14722912Sartem 	} else {
14732912Sartem 		return ("");
14742912Sartem 	}
14752912Sartem }
14762912Sartem 
14772912Sartem static gboolean
is_dos_path(char * path,int * partnum)14782912Sartem is_dos_path(char *path, int *partnum)
14792912Sartem {
14802912Sartem 	char *p;
14812912Sartem 
14822912Sartem 	if ((p = strrchr (path, ':')) == NULL) {
14832912Sartem 		return (FALSE);
14842912Sartem 	}
14852912Sartem 	return ((*partnum = atoi(p + 1)) != 0);
14862912Sartem }
14872912Sartem 
14882912Sartem static gboolean
dos_to_dev(char * path,char ** devpath,int * partnum)14892912Sartem dos_to_dev(char *path, char **devpath, int *partnum)
14902912Sartem {
14912912Sartem 	char *p;
14922912Sartem 
14932912Sartem 	if ((p = strrchr (path, ':')) == NULL) {
14942912Sartem 		return (FALSE);
14952912Sartem 	}
14962912Sartem 	if ((*partnum = atoi(p + 1)) == 0) {
14972912Sartem 		return (FALSE);
14982912Sartem 	}
14992912Sartem 	p[0] = '\0';
15002912Sartem 	*devpath = strdup(path);
15012912Sartem 	p[0] = ':';
15022912Sartem 	return (*devpath != NULL);
15032912Sartem }
15042912Sartem 
15052912Sartem static void
devinfo_storage_cleanup_mountpoint_cb(HalDevice * d,guint32 exit_type,gint return_code,gchar ** error,gpointer data1,gpointer data2)15062912Sartem devinfo_storage_cleanup_mountpoint_cb (HalDevice *d, guint32 exit_type,
15072912Sartem 		       gint return_code, gchar **error,
15082912Sartem 		       gpointer data1, gpointer data2)
15092912Sartem {
15102912Sartem 	char *mount_point = (char *) data1;
15112912Sartem 
15122912Sartem 	HAL_INFO (("Cleaned up mount point '%s'", mount_point));
15132912Sartem 	g_free (mount_point);
15142912Sartem }
15152912Sartem 
15162912Sartem 
15172912Sartem void
devinfo_storage_mnttab_event(HalDevice * hal_volume)15182912Sartem devinfo_storage_mnttab_event (HalDevice *hal_volume)
15192912Sartem {
15202912Sartem 	FILE *fp = NULL;
15212912Sartem         struct extmnttab m;
15222912Sartem 	HalDevice *d;
15232912Sartem 	unsigned int major;
15242912Sartem 	unsigned int minor;
15252912Sartem 	GSList *volumes = NULL;
15262912Sartem 	GSList *v;
15272912Sartem 	char *mount_point;
15282912Sartem 	dbus_bool_t is_partition;
15292912Sartem 	const char *fstype;
15302912Sartem 	int partition_number;
15312912Sartem 
15322912Sartem 	if (hal_volume != NULL) {
15332912Sartem 		volumes = g_slist_append (NULL, hal_volume);
15342912Sartem 	} else {
15352912Sartem 		volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.category", "volume");
15362912Sartem 	}
15372912Sartem 	if (volumes == NULL) {
15382912Sartem 		return;
15392912Sartem 	}
15402912Sartem 
15412912Sartem 	if ((fp = fopen(MNTTAB, "r")) == NULL) {
15422912Sartem 		HAL_ERROR (("Open failed %s errno %d", MNTTAB, errno));
15432912Sartem 		return;
15442912Sartem 	}
15452912Sartem 
15462912Sartem 	while (getextmntent(fp, &m, 1) == 0) {
15472912Sartem 		for (v = volumes; v != NULL; v = g_slist_next (v)) {
15482912Sartem 			d = HAL_DEVICE (v->data);
15492912Sartem 			major = hal_device_property_get_int (d, "block.major");
15502912Sartem 			minor = hal_device_property_get_int (d, "block.minor");
15512912Sartem 
15522912Sartem 			/*
15532912Sartem 			 * special handling for pcfs, which encodes logical
15542912Sartem 			 * drive number into the 6 upper bits of the minor
15552912Sartem 			 */
15562912Sartem 			is_partition = hal_device_property_get_bool (d, "volume.is_partition");
15572912Sartem 			partition_number = hal_device_property_get_int (d, "volume.partition.number");
15582912Sartem 			fstype = hal_device_property_get_string (d, "volume.fstype");
15592912Sartem 
15602912Sartem 			if (is_partition && (partition_number > 0) && (strcmp (fstype, "pcfs") == 0)) {
15612912Sartem 				minor |= partition_number << 12;
15622912Sartem 			}
15632912Sartem 
15642912Sartem 			if (m.mnt_major != major || m.mnt_minor != minor) {
15652912Sartem 				continue;
15662912Sartem 			}
15672912Sartem 
15682912Sartem 			/* this volume matches the mnttab entry */
15692912Sartem 			device_property_atomic_update_begin ();
15702912Sartem 			hal_device_property_set_bool (d, "volume.is_mounted", TRUE);
15712912Sartem 			hal_device_property_set_bool (d, "volume.is_mounted_read_only",
15722912Sartem 						      hasmntopt ((struct mnttab *)&m, "ro") ? TRUE : FALSE);
15732912Sartem 			hal_device_property_set_string (d, "volume.mount_point", m.mnt_mountp);
15742912Sartem 			device_property_atomic_update_end ();
15752912Sartem 
15762912Sartem 			HAL_INFO (("set %s to be mounted at %s",
15772912Sartem 				   hal_device_get_udi (d), m.mnt_mountp));
15782912Sartem 			volumes = g_slist_delete_link (volumes, v);
15792912Sartem 		}
15802912Sartem 	}
15812912Sartem 
15822912Sartem 	/* all remaining volumes are not mounted */
15832912Sartem 	for (v = volumes; v != NULL; v = g_slist_next (v)) {
15842912Sartem 		d = HAL_DEVICE (v->data);
15852912Sartem 		mount_point = g_strdup (hal_device_property_get_string (d, "volume.mount_point"));
15862912Sartem 		if (mount_point == NULL || strlen (mount_point) == 0) {
15872912Sartem 			g_free (mount_point);
15882912Sartem 			continue;
15892912Sartem 		}
15902912Sartem 
15912912Sartem 		device_property_atomic_update_begin ();
15922912Sartem 		hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
15932912Sartem 		hal_device_property_set_bool (d, "volume.is_mounted_read_only", FALSE);
15942912Sartem 		hal_device_property_set_string (d, "volume.mount_point", "");
15952912Sartem 		device_property_atomic_update_end ();
15962912Sartem 
15972912Sartem 		HAL_INFO (("set %s to unmounted", hal_device_get_udi (d)));
15982912Sartem 
15992912Sartem 		/* cleanup if was mounted by us */
16002912Sartem 		if (hal_util_is_mounted_by_hald (mount_point)) {
16012912Sartem 			char *cleanup_stdin;
16022912Sartem 			char *extra_env[2];
16032912Sartem 
16042912Sartem 			HAL_INFO (("Cleaning up '%s'", mount_point));
16052912Sartem 
16062912Sartem 			extra_env[0] = g_strdup_printf ("HALD_CLEANUP=%s", mount_point);
16072912Sartem 			extra_env[1] = NULL;
16082912Sartem 			cleanup_stdin = "\n";
16092912Sartem 
16102912Sartem 			hald_runner_run_method (d,
16112912Sartem 						"hal-storage-cleanup-mountpoint",
16122912Sartem 						extra_env,
16132912Sartem 						cleanup_stdin, TRUE,
16142912Sartem 						0,
16152912Sartem 						devinfo_storage_cleanup_mountpoint_cb,
16162912Sartem 						g_strdup (mount_point), NULL);
16172912Sartem 
16182912Sartem 			g_free (extra_env[0]);
16192912Sartem 		}
16202912Sartem 
16212912Sartem 		g_free (mount_point);
16222912Sartem 	}
16232912Sartem 	g_slist_free (volumes);
16242912Sartem 
16252912Sartem 	(void) fclose (fp);
16262912Sartem }
16272912Sartem 
16282912Sartem static void
devinfo_volume_force_unmount_cb(HalDevice * d,guint32 exit_type,gint return_code,gchar ** error,gpointer data1,gpointer data2)16292912Sartem devinfo_volume_force_unmount_cb (HalDevice *d, guint32 exit_type,
16302912Sartem 		  gint return_code, gchar **error,
16312912Sartem 		  gpointer data1, gpointer data2)
16322912Sartem {
16332912Sartem 	void *end_token = (void *) data1;
16342912Sartem 
16353121Sartem 	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));
16362912Sartem 
16372912Sartem 	if (exit_type == HALD_RUN_SUCCESS && error != NULL &&
16382912Sartem 	    error[0] != NULL && error[1] != NULL) {
16392912Sartem 		char *exp_name = NULL;
16402912Sartem 		char *exp_detail = NULL;
16412912Sartem 
16422912Sartem 		exp_name = error[0];
16432912Sartem 		if (error[0] != NULL) {
16442912Sartem 			exp_detail = error[1];
16452912Sartem 		}
16462912Sartem 		HAL_INFO (("failed with '%s' '%s'", exp_name, exp_detail));
16472912Sartem 	}
16482912Sartem 
16492912Sartem 	hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
16502912Sartem }
16512912Sartem 
16522912Sartem static void
devinfo_volume_force_unmount(HalDevice * d,void * end_token)16532912Sartem devinfo_volume_force_unmount (HalDevice *d, void *end_token)
16542912Sartem {
16552912Sartem 	const char *device_file;
16562912Sartem 	const char *mount_point;
16572912Sartem 	char *unmount_stdin;
16582912Sartem 	char *extra_env[2];
16592912Sartem 	extra_env[0] = "HAL_METHOD_INVOKED_BY_UID=0";
16602912Sartem 	extra_env[1] = NULL;
16612912Sartem 
16622912Sartem 	device_file = hal_device_property_get_string (d, "block.device");
16632912Sartem 	mount_point = hal_device_property_get_string (d, "volume.mount_point");
16642912Sartem 
16652912Sartem 	if (mount_point == NULL || strlen (mount_point) == 0 || !hal_util_is_mounted_by_hald (mount_point)) {
16662912Sartem 		hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
16672912Sartem 		return;
16682912Sartem 	}
16692912Sartem 
16703121Sartem 	HAL_INFO (("devinfo_volume_force_unmount for udi='%s'", hal_device_get_udi (d)));
16712912Sartem 
16722912Sartem 	unmount_stdin = "\n";
16732912Sartem 
16742912Sartem 	hald_runner_run_method (d,
16752912Sartem 				"hal-storage-unmount",
16762912Sartem 				extra_env,
16772912Sartem 				unmount_stdin, TRUE,
16782912Sartem 				0,
16792912Sartem 				devinfo_volume_force_unmount_cb,
16802912Sartem 				end_token, NULL);
16812912Sartem }
16822912Sartem 
16832912Sartem void
devinfo_volume_hotplug_begin_remove(HalDevice * d,char * devfs_path,void * end_token)16842912Sartem devinfo_volume_hotplug_begin_remove (HalDevice *d, char *devfs_path, void *end_token)
16852912Sartem {
16862912Sartem 	if (hal_device_property_get_bool (d, "volume.is_mounted")) {
16872912Sartem 		devinfo_volume_force_unmount (d, end_token);
16882912Sartem 	} else {
16892912Sartem 		hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
16902912Sartem 	}
16912912Sartem }
16922912Sartem 
16932912Sartem 
16942912Sartem enum {
16952912Sartem 	LEGACY_CDROM,
16962912Sartem 	LEGACY_FLOPPY,
16972912Sartem 	LEGACY_RMDISK
16982912Sartem };
16992912Sartem 
17002912Sartem static const char *legacy_media_str[] = {
17012912Sartem 	"cdrom",
17022912Sartem 	"floppy",
17032912Sartem 	"rmdisk"
17042912Sartem };
17052912Sartem 
17062912Sartem struct enum_nick {
17072912Sartem 	const char *type;
17082912Sartem 	GSList	*nums;
17092912Sartem };
17102912Sartem 
17112912Sartem static int
devinfo_storage_get_legacy_media(HalDevice * d)17122912Sartem devinfo_storage_get_legacy_media(HalDevice *d)
17132912Sartem {
17142912Sartem 	const char *drive_type;
17152912Sartem 
17162912Sartem 	if (hal_device_has_capability (d, "storage.cdrom")) {
17172912Sartem 		return (LEGACY_CDROM);
17182912Sartem 	} else if (((drive_type = hal_device_property_get_string (d,
17192912Sartem 	    "storage.drive_type")) != NULL) && (strcmp (drive_type, "floppy") == 0)) {
17202912Sartem 		return (LEGACY_FLOPPY);
17212912Sartem 	} else if (hal_device_property_get_bool (d, "storage.removable") ||
17222912Sartem 	           hal_device_property_get_bool (d, "storage.hotpluggable")) {
17232912Sartem 		return (LEGACY_RMDISK);
17242912Sartem 	} else {
17252912Sartem 		return (-1);
17262912Sartem 	}
17272912Sartem }
17282912Sartem 
17292912Sartem static gboolean
devinfo_storage_foreach_nick(HalDeviceStore * store,HalDevice * d,gpointer user_data)17302912Sartem devinfo_storage_foreach_nick (HalDeviceStore *store, HalDevice *d, gpointer user_data)
17312912Sartem {
17322912Sartem 	struct enum_nick *en = (struct enum_nick *) user_data;
17332912Sartem 	const char *media_type;
17342912Sartem 	int media_num;
17352912Sartem 
17362912Sartem 	media_type = hal_device_property_get_string (d, "storage.solaris.legacy.media_type");
17372912Sartem 	media_num = hal_device_property_get_int (d, "storage.solaris.legacy.media_num");
17382912Sartem 	if ((media_type != NULL) && (strcmp (media_type, en->type) == 0) &&
17392912Sartem 	    (media_num >= 0)) {
17402912Sartem 		en->nums = g_slist_prepend (en->nums, GINT_TO_POINTER(media_num));
17412912Sartem 	}
17422912Sartem 	return TRUE;
17432912Sartem }
17442912Sartem 
17452912Sartem static void
devinfo_storage_append_nickname(HalDevice * d,const char * media_type,int media_num)17462912Sartem devinfo_storage_append_nickname (HalDevice *d, const char *media_type, int media_num)
17472912Sartem {
17482912Sartem 	char buf[64];
17492912Sartem 
17502912Sartem 	if (media_num == 0) {
17512912Sartem 		hal_device_property_strlist_append (d, "storage.solaris.nicknames", media_type);
17522912Sartem 	}
17532912Sartem 	snprintf(buf, sizeof (buf), "%s%d", media_type, media_num);
17542912Sartem 	hal_device_property_strlist_append (d, "storage.solaris.nicknames", buf);
17552912Sartem }
17562912Sartem 
17572912Sartem static void
devinfo_storage_set_nicknames(HalDevice * d)17582912Sartem devinfo_storage_set_nicknames (HalDevice *d)
17592912Sartem {
17602912Sartem 	int media;
17612912Sartem 	const char *media_type;
17622912Sartem 	int media_num;
17632912Sartem 	GSList *i;
17642912Sartem 	struct enum_nick en;
17652912Sartem 	char buf[64];
17662912Sartem 
17672912Sartem 	if ((media = devinfo_storage_get_legacy_media (d)) < 0) {
17682912Sartem 		return;
17692912Sartem 	}
17702912Sartem 	media_type = legacy_media_str[media];
17712912Sartem 
17722912Sartem 	/* enumerate all storage devices of this media type */
17732912Sartem 	en.type = media_type;
17742912Sartem 	en.nums = NULL;
17752912Sartem 	hal_device_store_foreach (hald_get_gdl (), devinfo_storage_foreach_nick, &en);
17762912Sartem 
17772912Sartem 	/* find a free number */
17782912Sartem 	for (media_num = 0; ; media_num++) {
17792912Sartem 		for (i = en.nums; i != NULL; i = g_slist_next (i)) {
17802912Sartem         		if (GPOINTER_TO_INT (i->data) == media_num) {
17812912Sartem 				break;
17822912Sartem 			}
17832912Sartem 		}
17842912Sartem 		if (i == NULL) {
17852912Sartem 			break;
17862912Sartem 		}
17872912Sartem 	}
17882912Sartem 	g_slist_free (en.nums);
17892912Sartem 
17902912Sartem 	hal_device_property_set_string (d, "storage.solaris.legacy.media_type", media_type);
17912912Sartem 	hal_device_property_set_int (d, "storage.solaris.legacy.media_num", media_num);
17922912Sartem 
17932912Sartem 	/* primary nickname, and also vold-style symdev */
17942912Sartem 	snprintf(buf, sizeof (buf), "%s%d", media_type, media_num);
17952912Sartem 	hal_device_property_set_string (d, "storage.solaris.legacy.symdev", buf);
17962912Sartem 	devinfo_storage_append_nickname(d, media_type, media_num);
17972912Sartem 
17982912Sartem 	/* additional nicknames */
17992912Sartem 	if (media == LEGACY_CDROM) {
18002912Sartem 		devinfo_storage_append_nickname(d, "cd", media_num);
18012912Sartem 		devinfo_storage_append_nickname(d, "sr", media_num);
18022912Sartem 	} else if (media == LEGACY_FLOPPY) {
18032912Sartem 		devinfo_storage_append_nickname(d, "fd", media_num);
18042912Sartem 		devinfo_storage_append_nickname(d, "diskette", media_num);
18052912Sartem 		devinfo_storage_append_nickname(d, "rdiskette", media_num);
18062912Sartem 	}
18072912Sartem }
1808