118c2aff7Sartem /***************************************************************************
218c2aff7Sartem  *
318c2aff7Sartem  * devinfo_storage.c : storage devices
418c2aff7Sartem  *
53f7d54a6SGarrett D'Amore  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
6506aa7c6SGarrett D'Amore  * Copyright 2013 Garrett D'Amore <garrett@damore.org>
718c2aff7Sartem  *
818c2aff7Sartem  * Licensed under the Academic Free License version 2.1
918c2aff7Sartem  *
1018c2aff7Sartem  **************************************************************************/
1118c2aff7Sartem 
1200687e57Sartem #ifdef HAVE_CONFIG_H
1300687e57Sartem #  include <config.h>
1400687e57Sartem #endif
1500687e57Sartem 
1618c2aff7Sartem #include <stdio.h>
1718c2aff7Sartem #include <string.h>
1818c2aff7Sartem #include <strings.h>
1918c2aff7Sartem #include <ctype.h>
2018c2aff7Sartem #include <libdevinfo.h>
2118c2aff7Sartem #include <sys/types.h>
2218c2aff7Sartem #include <sys/mkdev.h>
2318c2aff7Sartem #include <sys/stat.h>
2418c2aff7Sartem #include <sys/mntent.h>
2518c2aff7Sartem #include <sys/mnttab.h>
2618c2aff7Sartem 
2718c2aff7Sartem #include "../osspec.h"
2818c2aff7Sartem #include "../logger.h"
2918c2aff7Sartem #include "../hald.h"
3018c2aff7Sartem #include "../hald_dbus.h"
3118c2aff7Sartem #include "../device_info.h"
3218c2aff7Sartem #include "../util.h"
3318c2aff7Sartem #include "../hald_runner.h"
3418c2aff7Sartem #include "hotplug.h"
3518c2aff7Sartem #include "devinfo.h"
3618c2aff7Sartem #include "devinfo_misc.h"
3718c2aff7Sartem #include "devinfo_storage.h"
3818c2aff7Sartem #include "osspec_solaris.h"
3918c2aff7Sartem 
4018c2aff7Sartem #ifdef sparc
4118c2aff7Sartem #define	WHOLE_DISK	"s2"
4218c2aff7Sartem #else
4318c2aff7Sartem #define	WHOLE_DISK	"p0"
4418c2aff7Sartem #endif
4518c2aff7Sartem 
4618c2aff7Sartem /* some devices,especially CDROMs, may take a while to be probed (values in ms) */
4718c2aff7Sartem #define	DEVINFO_PROBE_STORAGE_TIMEOUT	60000
4818c2aff7Sartem #define	DEVINFO_PROBE_VOLUME_TIMEOUT	60000
4918c2aff7Sartem 
5018c2aff7Sartem typedef struct devinfo_storage_minor {
5118c2aff7Sartem 	char	*devpath;
5218c2aff7Sartem 	char	*devlink;
5318c2aff7Sartem 	char	*slice;
5418c2aff7Sartem 	dev_t	dev;
5518c2aff7Sartem 	int	dosnum;	/* dos disk number or -1 */
5618c2aff7Sartem } devinfo_storage_minor_t;
5718c2aff7Sartem 
5818c2aff7Sartem HalDevice *devinfo_ide_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
5918c2aff7Sartem static HalDevice *devinfo_ide_host_add(HalDevice *parent, di_node_t node, char *devfs_path);
6018c2aff7Sartem static HalDevice *devinfo_ide_device_add(HalDevice *parent, di_node_t node, char *devfs_path);
6100687e57Sartem static HalDevice *devinfo_ide_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
6218c2aff7Sartem HalDevice *devinfo_scsi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
6300687e57Sartem static HalDevice *devinfo_scsi_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
643f7d54a6SGarrett D'Amore HalDevice *devinfo_blkdev_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
653f7d54a6SGarrett D'Amore static HalDevice *devinfo_blkdev_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
6618c2aff7Sartem HalDevice *devinfo_floppy_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
6718c2aff7Sartem static void devinfo_floppy_add_volume(HalDevice *parent, di_node_t node);
6818c2aff7Sartem static HalDevice *devinfo_lofi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
6918c2aff7Sartem static void devinfo_lofi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, char *devlink, dev_t dev);
7018c2aff7Sartem static void devinfo_storage_minors(HalDevice *parent, di_node_t node, gchar *devfs_path, gboolean);
7118c2aff7Sartem static struct devinfo_storage_minor *devinfo_storage_new_minor(char *maindev_path, char *slice,
7218c2aff7Sartem     char *devlink, dev_t dev, int dosnum);
7318c2aff7Sartem static void devinfo_storage_free_minor(struct devinfo_storage_minor *m);
7418c2aff7Sartem HalDevice *devinfo_volume_add(HalDevice *parent, di_node_t node, devinfo_storage_minor_t *m);
7518c2aff7Sartem static void devinfo_volume_preprobing_done(HalDevice *d, gpointer userdata1, gpointer userdata2);
7618c2aff7Sartem static void devinfo_volume_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
7718c2aff7Sartem static void devinfo_storage_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
7818c2aff7Sartem static void devinfo_storage_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2);
7918c2aff7Sartem const gchar *devinfo_volume_get_prober (HalDevice *d, int *timeout);
8018c2aff7Sartem const gchar *devinfo_storage_get_prober (HalDevice *d, int *timeout);
8118c2aff7Sartem 
8218c2aff7Sartem static char *devinfo_scsi_dtype2str(int dtype);
8318c2aff7Sartem static char *devinfo_volume_get_slice_name (char *devlink);
8418c2aff7Sartem static gboolean dos_to_dev(char *path, char **devpath, int *partnum);
8518c2aff7Sartem static gboolean is_dos_path(char *path, int *partnum);
8618c2aff7Sartem 
8718c2aff7Sartem static void devinfo_storage_set_nicknames (HalDevice *d);
8818c2aff7Sartem 
8918c2aff7Sartem DevinfoDevHandler devinfo_ide_handler = {
9018c2aff7Sartem         devinfo_ide_add,
9118c2aff7Sartem 	NULL,
9218c2aff7Sartem 	NULL,
9318c2aff7Sartem 	NULL,
9418c2aff7Sartem 	NULL,
9518c2aff7Sartem         NULL
9618c2aff7Sartem };
9718c2aff7Sartem DevinfoDevHandler devinfo_scsi_handler = {
9818c2aff7Sartem         devinfo_scsi_add,
9918c2aff7Sartem 	NULL,
10018c2aff7Sartem 	NULL,
10118c2aff7Sartem 	NULL,
10218c2aff7Sartem 	NULL,
10318c2aff7Sartem         NULL
10418c2aff7Sartem };
1053f7d54a6SGarrett D'Amore DevinfoDevHandler devinfo_blkdev_handler = {
1063f7d54a6SGarrett D'Amore         devinfo_blkdev_add,
1073f7d54a6SGarrett D'Amore 	NULL,
1083f7d54a6SGarrett D'Amore 	NULL,
1093f7d54a6SGarrett D'Amore 	NULL,
1103f7d54a6SGarrett D'Amore 	NULL,
1113f7d54a6SGarrett D'Amore         NULL
1123f7d54a6SGarrett D'Amore };
11318c2aff7Sartem DevinfoDevHandler devinfo_floppy_handler = {
11418c2aff7Sartem         devinfo_floppy_add,
11518c2aff7Sartem 	NULL,
11618c2aff7Sartem 	NULL,
11718c2aff7Sartem 	NULL,
11818c2aff7Sartem 	NULL,
11918c2aff7Sartem         NULL
12018c2aff7Sartem };
12118c2aff7Sartem DevinfoDevHandler devinfo_lofi_handler = {
12218c2aff7Sartem         devinfo_lofi_add,
12318c2aff7Sartem 	NULL,
12418c2aff7Sartem 	NULL,
12518c2aff7Sartem 	NULL,
12618c2aff7Sartem 	NULL,
12718c2aff7Sartem         NULL
12818c2aff7Sartem };
12918c2aff7Sartem DevinfoDevHandler devinfo_storage_handler = {
13018c2aff7Sartem 	NULL,
13118c2aff7Sartem 	NULL,
13218c2aff7Sartem 	devinfo_storage_hotplug_begin_add,
13318c2aff7Sartem 	NULL,
13418c2aff7Sartem 	devinfo_storage_probing_done,
13518c2aff7Sartem 	devinfo_storage_get_prober
13618c2aff7Sartem };
13718c2aff7Sartem DevinfoDevHandler devinfo_volume_handler = {
13818c2aff7Sartem 	NULL,
13918c2aff7Sartem 	NULL,
14018c2aff7Sartem 	devinfo_volume_hotplug_begin_add,
14118c2aff7Sartem 	NULL,
14218c2aff7Sartem 	NULL,
14318c2aff7Sartem 	devinfo_volume_get_prober
14418c2aff7Sartem };
14518c2aff7Sartem 
14618c2aff7Sartem /* IDE */
14718c2aff7Sartem 
14818c2aff7Sartem HalDevice *
devinfo_ide_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)14918c2aff7Sartem devinfo_ide_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
15018c2aff7Sartem {
15118c2aff7Sartem 	char	*s;
15218c2aff7Sartem 
15318c2aff7Sartem 	if ((device_type != NULL) && (strcmp(device_type, "ide") == 0)) {
15418c2aff7Sartem 		return (devinfo_ide_host_add(parent, node, devfs_path));
15518c2aff7Sartem 	}
15618c2aff7Sartem 
15718c2aff7Sartem         if ((di_prop_lookup_strings (DDI_DEV_T_ANY, node, "class", &s) > 0) &&
15818c2aff7Sartem 	    (strcmp (s, "dada") == 0)) {
15918c2aff7Sartem 		return (devinfo_ide_device_add(parent, node, devfs_path));
16018c2aff7Sartem 	}
16118c2aff7Sartem 
16218c2aff7Sartem 	return (NULL);
16318c2aff7Sartem }
16418c2aff7Sartem 
16518c2aff7Sartem static HalDevice *
devinfo_ide_host_add(HalDevice * parent,di_node_t node,char * devfs_path)16618c2aff7Sartem devinfo_ide_host_add(HalDevice *parent, di_node_t node, char *devfs_path)
16718c2aff7Sartem {
16818c2aff7Sartem 	HalDevice *d;
16918c2aff7Sartem 
17018c2aff7Sartem 	d = hal_device_new ();
17118c2aff7Sartem 
17218c2aff7Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
17318c2aff7Sartem 	hal_device_property_set_string (d, "info.product", "IDE host controller");
174112cd14aSqz 	hal_device_property_set_string (d, "info.subsystem", "ide_host");
17518c2aff7Sartem 	hal_device_property_set_int (d, "ide_host.number", 0); /* XXX */
17618c2aff7Sartem 
17718c2aff7Sartem 	devinfo_add_enqueue (d, devfs_path, &devinfo_ide_handler);
17818c2aff7Sartem 
17918c2aff7Sartem 	return (d);
18018c2aff7Sartem }
18118c2aff7Sartem 
18218c2aff7Sartem static HalDevice *
devinfo_ide_device_add(HalDevice * parent,di_node_t node,char * devfs_path)18318c2aff7Sartem devinfo_ide_device_add(HalDevice *parent, di_node_t node, char *devfs_path)
18418c2aff7Sartem {
18518c2aff7Sartem 	HalDevice *d;
18618c2aff7Sartem 
18718c2aff7Sartem 	d = hal_device_new();
18818c2aff7Sartem 
18918c2aff7Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
19018c2aff7Sartem         hal_device_property_set_string (parent, "info.product", "IDE device");
191112cd14aSqz 	hal_device_property_set_string (parent, "info.subsystem", "ide");
19218c2aff7Sartem 	hal_device_property_set_int (parent, "ide.host", 0); /* XXX */
19318c2aff7Sartem 	hal_device_property_set_int (parent, "ide.channel", 0);
19418c2aff7Sartem 
19518c2aff7Sartem 	devinfo_add_enqueue (d, devfs_path, &devinfo_ide_handler);
19618c2aff7Sartem 
19700687e57Sartem 	return (devinfo_ide_storage_add (d, node, devfs_path));
19818c2aff7Sartem }
19918c2aff7Sartem 
20018c2aff7Sartem static HalDevice *
devinfo_ide_storage_add(HalDevice * parent,di_node_t node,char * devfs_path)20100687e57Sartem devinfo_ide_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
20218c2aff7Sartem {
20318c2aff7Sartem 	HalDevice *d;
20418c2aff7Sartem 	char	*s;
20518c2aff7Sartem 	int	*i;
20618c2aff7Sartem 	char	*driver_name;
20718c2aff7Sartem 	char	udi[HAL_PATH_MAX];
20818c2aff7Sartem 
20918c2aff7Sartem 	if ((driver_name = di_driver_name (node)) == NULL) {
21018c2aff7Sartem 		return (NULL);
21118c2aff7Sartem 	}
21218c2aff7Sartem 
21318c2aff7Sartem         d = hal_device_new ();
21418c2aff7Sartem 
21518c2aff7Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
21618c2aff7Sartem         hal_device_property_set_string (d, "info.category", "storage");
21718c2aff7Sartem 
21818c2aff7Sartem         hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
21900687e57Sartem                 "%s/%s%d", hal_device_get_udi (parent), driver_name, di_instance (node));
22018c2aff7Sartem         hal_device_set_udi (d, udi);
22118c2aff7Sartem         hal_device_property_set_string (d, "info.udi", udi);
22218c2aff7Sartem 	PROP_STR(d, node, s, "devid", "info.product");
22318c2aff7Sartem 
22418c2aff7Sartem         hal_device_add_capability (d, "storage");
22518c2aff7Sartem         hal_device_property_set_string (d, "storage.bus", "ide");
22618c2aff7Sartem         hal_device_property_set_int (d, "storage.lun", 0);
22718c2aff7Sartem 	hal_device_property_set_string (d, "storage.drive_type", "disk");
22818c2aff7Sartem 
22918c2aff7Sartem 	PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
23018c2aff7Sartem 	PROP_BOOL(d, node, i, "removable-media", "storage.removable");
23118c2aff7Sartem 
23218c2aff7Sartem         hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
23318c2aff7Sartem 
23418c2aff7Sartem 	/* XXX */
23518c2aff7Sartem         hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
23618c2aff7Sartem 
23718c2aff7Sartem 	hal_device_add_capability (d, "block");
23818c2aff7Sartem 
23918c2aff7Sartem 	devinfo_storage_minors (d, node, (char *)devfs_path, FALSE);
24018c2aff7Sartem 
24118c2aff7Sartem 	return (d);
24218c2aff7Sartem }
24318c2aff7Sartem 
24418c2aff7Sartem /* SCSI */
24518c2aff7Sartem 
24618c2aff7Sartem HalDevice *
devinfo_scsi_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)24718c2aff7Sartem devinfo_scsi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
24818c2aff7Sartem {
24918c2aff7Sartem 	int	*i;
25018c2aff7Sartem 	char	*driver_name;
25118c2aff7Sartem 	HalDevice *d;
25218c2aff7Sartem 	char	udi[HAL_PATH_MAX];
25318c2aff7Sartem 
25418c2aff7Sartem 	driver_name = di_driver_name (node);
25518c2aff7Sartem 	if ((driver_name == NULL) || (strcmp (driver_name, "sd") != 0)) {
25618c2aff7Sartem 		return (NULL);
25718c2aff7Sartem 	}
25818c2aff7Sartem 
25918c2aff7Sartem 	d = hal_device_new ();
26018c2aff7Sartem 
26118c2aff7Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
262112cd14aSqz 	hal_device_property_set_string (d, "info.subsystem", "scsi");
26318c2aff7Sartem 
26418c2aff7Sartem         hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
26500687e57Sartem                 "%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
26618c2aff7Sartem         hal_device_set_udi (d, udi);
26718c2aff7Sartem         hal_device_property_set_string (d, "info.udi", udi);
26818c2aff7Sartem 
269*55fea89dSDan Cross 	hal_device_property_set_int (d, "scsi.host",
27018c2aff7Sartem 		hal_device_property_get_int (parent, "scsi_host.host"));
27118c2aff7Sartem 	hal_device_property_set_int (d, "scsi.bus", 0);
27218c2aff7Sartem 	PROP_INT(d, node, i, "target", "scsi.target");
27318c2aff7Sartem 	PROP_INT(d, node, i, "lun", "scsi.lun");
27418c2aff7Sartem         hal_device_property_set_string (d, "info.product", "SCSI Device");
27518c2aff7Sartem 
27618c2aff7Sartem         devinfo_add_enqueue (d, devfs_path, &devinfo_scsi_handler);
27718c2aff7Sartem 
27800687e57Sartem         return (devinfo_scsi_storage_add (d, node, devfs_path));
27918c2aff7Sartem }
28018c2aff7Sartem 
28118c2aff7Sartem static HalDevice *
devinfo_scsi_storage_add(HalDevice * parent,di_node_t node,char * devfs_path)28200687e57Sartem devinfo_scsi_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
28318c2aff7Sartem {
28418c2aff7Sartem 	HalDevice *d;
28518c2aff7Sartem 	int	*i;
28618c2aff7Sartem 	char	*s;
28718c2aff7Sartem 	char	udi[HAL_PATH_MAX];
28818c2aff7Sartem 
28918c2aff7Sartem 	d = hal_device_new ();
29018c2aff7Sartem 
29118c2aff7Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
29218c2aff7Sartem         hal_device_property_set_string (d, "info.category", "storage");
29318c2aff7Sartem 
29418c2aff7Sartem         hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
29500687e57Sartem 		"%s/sd%d", hal_device_get_udi (parent), di_instance (node));
29618c2aff7Sartem         hal_device_set_udi (d, udi);
29718c2aff7Sartem         hal_device_property_set_string (d, "info.udi", udi);
29818c2aff7Sartem 	PROP_STR(d, node, s, "inquiry-product-id", "info.product");
29918c2aff7Sartem 
30018c2aff7Sartem         hal_device_add_capability (d, "storage");
30118c2aff7Sartem 
30218c2aff7Sartem         hal_device_property_set_int (d, "storage.lun",
30318c2aff7Sartem 		hal_device_property_get_int (parent, "scsi.lun"));
30418c2aff7Sartem 	PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
30518c2aff7Sartem 	PROP_BOOL(d, node, i, "removable-media", "storage.removable");
30618c2aff7Sartem         hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
30718c2aff7Sartem 
30818c2aff7Sartem 	/*
30918c2aff7Sartem 	 * We have to enable polling not only for drives with removable media,
31018c2aff7Sartem 	 * but also for hotpluggable devices, because when a disk is
31118c2aff7Sartem 	 * unplugged while busy/mounted, there is not sysevent generated.
31218c2aff7Sartem 	 * Instead, the HBA driver (scsa2usb, scsa1394) will notify sd driver
31318c2aff7Sartem 	 * and the latter will report DKIO_DEV_GONE via DKIOCSTATE ioctl.
31418c2aff7Sartem 	 * So we have to enable media check so that hald-addon-storage notices
31518c2aff7Sartem 	 * the "device gone" condition and unmounts all associated volumes.
31618c2aff7Sartem 	 */
31718c2aff7Sartem 	hal_device_property_set_bool (d, "storage.media_check_enabled",
31818c2aff7Sartem 	    ((di_prop_lookup_ints(DDI_DEV_T_ANY, node, "removable-media", &i) >= 0) ||
31918c2aff7Sartem 	    (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "hotpluggable", &i) >= 0)));
32018c2aff7Sartem 
32118c2aff7Sartem         if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "inquiry-device-type",
32218c2aff7Sartem 	    &i) > 0) {
32318c2aff7Sartem 		s = devinfo_scsi_dtype2str (*i);
32418c2aff7Sartem         	hal_device_property_set_string (d, "storage.drive_type", s);
32518c2aff7Sartem 
32618c2aff7Sartem 		if (strcmp (s, "cdrom") == 0) {
32718c2aff7Sartem 			hal_device_add_capability (d, "storage.cdrom");
32818c2aff7Sartem 			hal_device_property_set_bool (d, "storage.no_partitions_hint", TRUE);
32918c2aff7Sartem         		hal_device_property_set_bool (d, "storage.requires_eject", TRUE);
33018c2aff7Sartem 		}
33118c2aff7Sartem 	}
33218c2aff7Sartem 
33318c2aff7Sartem         hal_device_add_capability (d, "block");
33418c2aff7Sartem 
33518c2aff7Sartem 	devinfo_storage_minors (d, node, devfs_path, FALSE);
33618c2aff7Sartem 
33718c2aff7Sartem 	return (d);
33818c2aff7Sartem }
33918c2aff7Sartem 
34000687e57Sartem static char *
devinfo_scsi_dtype2str(int dtype)34100687e57Sartem devinfo_scsi_dtype2str(int dtype)
34218c2aff7Sartem {
34318c2aff7Sartem         char *dtype2str[] = {
34418c2aff7Sartem                 "disk"	,         /* DTYPE_DIRECT         0x00 */
34518c2aff7Sartem                 "tape"	,         /* DTYPE_SEQUENTIAL     0x01 */
34618c2aff7Sartem                 "printer",         /* DTYPE_PRINTER        0x02 */
34718c2aff7Sartem                 "processor",         /* DTYPE_PROCESSOR      0x03 */
34818c2aff7Sartem                 "worm"	,         /* DTYPE_WORM           0x04 */
34918c2aff7Sartem                 "cdrom"	,         /* DTYPE_RODIRECT       0x05 */
35018c2aff7Sartem                 "scanner",         /* DTYPE_SCANNER        0x06 */
35118c2aff7Sartem                 "cdrom"	,         /* DTYPE_OPTICAL        0x07 */
35218c2aff7Sartem                 "changer",         /* DTYPE_CHANGER        0x08 */
35318c2aff7Sartem                 "comm"	,         /* DTYPE_COMM           0x09 */
35418c2aff7Sartem                 "scsi"	,         /* DTYPE_???            0x0A */
35518c2aff7Sartem                 "scsi"	,         /* DTYPE_???            0x0B */
35618c2aff7Sartem                 "array_ctrl",         /* DTYPE_ARRAY_CTRL     0x0C */
35718c2aff7Sartem                 "esi"	,         /* DTYPE_ESI            0x0D */
35818c2aff7Sartem                 "disk"	          /* DTYPE_RBC            0x0E */
35918c2aff7Sartem         };
36018c2aff7Sartem 
36118c2aff7Sartem         if (dtype < NELEM(dtype2str)) {
36218c2aff7Sartem                 return (dtype2str[dtype]);
36318c2aff7Sartem         } else {
36418c2aff7Sartem 		return ("scsi");
36518c2aff7Sartem         }
36618c2aff7Sartem 
36718c2aff7Sartem }
36818c2aff7Sartem 
3693f7d54a6SGarrett D'Amore /* blkdev */
3703f7d54a6SGarrett D'Amore 
3713f7d54a6SGarrett D'Amore HalDevice *
devinfo_blkdev_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)3723f7d54a6SGarrett D'Amore devinfo_blkdev_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
3733f7d54a6SGarrett D'Amore {
3743f7d54a6SGarrett D'Amore 	int	*i;
3753f7d54a6SGarrett D'Amore 	char	*driver_name;
3763f7d54a6SGarrett D'Amore 	HalDevice *d;
3773f7d54a6SGarrett D'Amore 	char	udi[HAL_PATH_MAX];
3783f7d54a6SGarrett D'Amore 
3793f7d54a6SGarrett D'Amore 	driver_name = di_driver_name (node);
3803f7d54a6SGarrett D'Amore 	if ((driver_name == NULL) || (strcmp (driver_name, "blkdev") != 0)) {
3813f7d54a6SGarrett D'Amore 		return (NULL);
3823f7d54a6SGarrett D'Amore 	}
3833f7d54a6SGarrett D'Amore 
3843f7d54a6SGarrett D'Amore 	d = hal_device_new ();
3853f7d54a6SGarrett D'Amore 
3863f7d54a6SGarrett D'Amore 	devinfo_set_default_properties (d, parent, node, devfs_path);
3873f7d54a6SGarrett D'Amore 	hal_device_property_set_string (d, "info.subsystem", "pseudo");
3883f7d54a6SGarrett D'Amore 
3893f7d54a6SGarrett D'Amore         hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
3903f7d54a6SGarrett D'Amore                 "%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
3913f7d54a6SGarrett D'Amore         hal_device_set_udi (d, udi);
3923f7d54a6SGarrett D'Amore         hal_device_property_set_string (d, "info.udi", udi);
3933f7d54a6SGarrett D'Amore         hal_device_property_set_string (d, "info.product", "Block Device");
3943f7d54a6SGarrett D'Amore 
3953f7d54a6SGarrett D'Amore         devinfo_add_enqueue (d, devfs_path, &devinfo_blkdev_handler);
3963f7d54a6SGarrett D'Amore 
3973f7d54a6SGarrett D'Amore         return (devinfo_blkdev_storage_add (d, node, devfs_path));
3983f7d54a6SGarrett D'Amore }
3993f7d54a6SGarrett D'Amore 
4003f7d54a6SGarrett D'Amore static HalDevice *
devinfo_blkdev_storage_add(HalDevice * parent,di_node_t node,char * devfs_path)4013f7d54a6SGarrett D'Amore devinfo_blkdev_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
4023f7d54a6SGarrett D'Amore {
4033f7d54a6SGarrett D'Amore 	HalDevice *d;
4043f7d54a6SGarrett D'Amore 	char	*driver_name;
4053f7d54a6SGarrett D'Amore 	int	*i;
4063f7d54a6SGarrett D'Amore 	char	*s;
4073f7d54a6SGarrett D'Amore 	char	udi[HAL_PATH_MAX];
4083f7d54a6SGarrett D'Amore 
4093f7d54a6SGarrett D'Amore 	d = hal_device_new ();
4103f7d54a6SGarrett D'Amore 
4113f7d54a6SGarrett D'Amore 	devinfo_set_default_properties (d, parent, node, devfs_path);
4123f7d54a6SGarrett D'Amore 	hal_device_property_set_string (d, "info.category", "storage");
4133f7d54a6SGarrett D'Amore 
4143f7d54a6SGarrett D'Amore 	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
4153f7d54a6SGarrett D'Amore 		"%s/blkdev%d", hal_device_get_udi (parent), di_instance (node));
4163f7d54a6SGarrett D'Amore 	hal_device_set_udi (d, udi);
4173f7d54a6SGarrett D'Amore 	hal_device_property_set_string (d, "info.udi", udi);
4183f7d54a6SGarrett D'Amore 
4193f7d54a6SGarrett D'Amore 	hal_device_add_capability (d, "storage");
4203f7d54a6SGarrett D'Amore 
4213f7d54a6SGarrett D'Amore 	hal_device_property_set_int (d, "storage.lun", 0);
4223f7d54a6SGarrett D'Amore 
4233f7d54a6SGarrett D'Amore 	PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
4243f7d54a6SGarrett D'Amore 	PROP_BOOL(d, node, i, "removable-media", "storage.removable");
4253f7d54a6SGarrett D'Amore 
4263f7d54a6SGarrett D'Amore 	hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
4273f7d54a6SGarrett D'Amore 	hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
4283f7d54a6SGarrett D'Amore        	hal_device_property_set_string (d, "storage.drive_type", "disk");
4293f7d54a6SGarrett D'Amore 
4303f7d54a6SGarrett D'Amore 	hal_device_add_capability (d, "block");
4313f7d54a6SGarrett D'Amore 
4323f7d54a6SGarrett D'Amore 	devinfo_storage_minors (d, node, devfs_path, FALSE);
4333f7d54a6SGarrett D'Amore 
4343f7d54a6SGarrett D'Amore 	return (d);
4353f7d54a6SGarrett D'Amore }
4363f7d54a6SGarrett D'Amore 
43718c2aff7Sartem /* floppy */
43818c2aff7Sartem 
43918c2aff7Sartem HalDevice *
devinfo_floppy_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)44018c2aff7Sartem devinfo_floppy_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
44118c2aff7Sartem {
44218c2aff7Sartem 	char	*driver_name;
44318c2aff7Sartem 	char	*raw;
44418c2aff7Sartem 	char	udi[HAL_PATH_MAX];
44518c2aff7Sartem 	di_devlink_handle_t devlink_hdl;
44618c2aff7Sartem         int     major;
44718c2aff7Sartem         di_minor_t minor;
44818c2aff7Sartem         dev_t   dev;
44918c2aff7Sartem 	HalDevice *d = NULL;
45018c2aff7Sartem         char    *minor_path = NULL;
45118c2aff7Sartem 	char	*devlink = NULL;
45218c2aff7Sartem 
45318c2aff7Sartem 	driver_name = di_driver_name (node);
45418c2aff7Sartem 	if ((driver_name == NULL) || (strcmp (driver_name, "fd") != 0)) {
45518c2aff7Sartem 		return (NULL);
45618c2aff7Sartem 	}
45718c2aff7Sartem 
45818c2aff7Sartem 	/*
45918c2aff7Sartem 	 * The only minor node we're interested in is /dev/diskette*
46018c2aff7Sartem 	 */
46118c2aff7Sartem 	major = di_driver_major(node);
46218c2aff7Sartem 	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
46318c2aff7Sartem 		return (NULL);
46418c2aff7Sartem 	}
46518c2aff7Sartem 	minor = DI_MINOR_NIL;
46618c2aff7Sartem 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
46718c2aff7Sartem 		dev = di_minor_devt(minor);
46818c2aff7Sartem 		if ((major != major(dev)) ||
46918c2aff7Sartem 		    (di_minor_type(minor) != DDM_MINOR) ||
47018c2aff7Sartem 		    (di_minor_spectype(minor) != S_IFBLK) ||
47118c2aff7Sartem 		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
47218c2aff7Sartem 			continue;
47318c2aff7Sartem 		}
47442a7bdedSjacobs 		if ((devlink = get_devlink(devlink_hdl, "diskette.+" , minor_path)) != NULL) {
47518c2aff7Sartem 			break;
47618c2aff7Sartem 		}
47718c2aff7Sartem 		di_devfs_path_free (minor_path);
47818c2aff7Sartem 		minor_path = NULL;
47918c2aff7Sartem 		free(devlink);
48018c2aff7Sartem 		devlink = NULL;
48118c2aff7Sartem 	}
48218c2aff7Sartem 	di_devlink_fini (&devlink_hdl);
48318c2aff7Sartem 
48418c2aff7Sartem 	if ((devlink == NULL) || (minor_path == NULL)) {
48518c2aff7Sartem 		HAL_INFO (("floppy devlink not found %s", devfs_path));
48618c2aff7Sartem 		goto out;
48718c2aff7Sartem 	}
48818c2aff7Sartem 
48918c2aff7Sartem 	d = hal_device_new ();
49018c2aff7Sartem 
49118c2aff7Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
49218c2aff7Sartem         hal_device_property_set_string (d, "info.category", "storage");
49318c2aff7Sartem         hal_device_add_capability (d, "storage");
49418c2aff7Sartem        	hal_device_property_set_string (d, "storage.bus", "platform");
49518c2aff7Sartem         hal_device_property_set_bool (d, "storage.hotpluggable", FALSE);
49618c2aff7Sartem         hal_device_property_set_bool (d, "storage.removable", TRUE);
49718c2aff7Sartem         hal_device_property_set_bool (d, "storage.requires_eject", TRUE);
49818c2aff7Sartem         hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
49918c2aff7Sartem        	hal_device_property_set_string (d, "storage.drive_type", "floppy");
50018c2aff7Sartem 
50118c2aff7Sartem         hal_device_add_capability (d, "block");
50218c2aff7Sartem 	hal_device_property_set_bool (d, "block.is_volume", FALSE);
50318c2aff7Sartem 	hal_device_property_set_int (d, "block.major", major(dev));
50418c2aff7Sartem 	hal_device_property_set_int (d, "block.minor", minor(dev));
50518c2aff7Sartem 	hal_device_property_set_string (d, "block.device", devlink);
50618c2aff7Sartem 	raw = dsk_to_rdsk (devlink);
50718c2aff7Sartem 	hal_device_property_set_string (d, "block.solaris.raw_device", raw);
50818c2aff7Sartem 	free (raw);
50918c2aff7Sartem 
51018c2aff7Sartem 	devinfo_add_enqueue (d, devfs_path, &devinfo_storage_handler);
51118c2aff7Sartem 
51218c2aff7Sartem 	/* trigger initial probe-volume */
51318c2aff7Sartem 	devinfo_floppy_add_volume(d, node);
51418c2aff7Sartem 
51518c2aff7Sartem out:
51618c2aff7Sartem 	di_devfs_path_free (minor_path);
51718c2aff7Sartem 	free(devlink);
51818c2aff7Sartem 
51918c2aff7Sartem 	return (d);
52018c2aff7Sartem }
52118c2aff7Sartem 
52218c2aff7Sartem static void
devinfo_floppy_add_volume(HalDevice * parent,di_node_t node)52318c2aff7Sartem devinfo_floppy_add_volume(HalDevice *parent, di_node_t node)
52418c2aff7Sartem {
52518c2aff7Sartem 	char	*devlink;
52618c2aff7Sartem 	char	*devfs_path;
52718c2aff7Sartem 	int	minor, major;
52818c2aff7Sartem 	dev_t	dev;
52918c2aff7Sartem 	struct devinfo_storage_minor *m;
53018c2aff7Sartem 
53118c2aff7Sartem 	devfs_path = (char *)hal_device_property_get_string (parent, "solaris.devfs_path");
53218c2aff7Sartem 	devlink = (char *)hal_device_property_get_string (parent, "block.device");
53318c2aff7Sartem 	major = hal_device_property_get_int (parent, "block.major");
53418c2aff7Sartem 	minor = hal_device_property_get_int (parent, "block.minor");
53518c2aff7Sartem 	dev = makedev (major, minor);
53618c2aff7Sartem 
53718c2aff7Sartem 	m = devinfo_storage_new_minor (devfs_path, WHOLE_DISK, devlink, dev, -1);
53818c2aff7Sartem 	devinfo_volume_add (parent, node, m);
53918c2aff7Sartem 	devinfo_storage_free_minor (m);
54018c2aff7Sartem }
54118c2aff7Sartem 
54218c2aff7Sartem /*
54318c2aff7Sartem  * After reprobing storage, reprobe its volumes.
54418c2aff7Sartem  */
54518c2aff7Sartem static void
devinfo_floppy_rescan_probing_done(HalDevice * d,guint32 exit_type,gint return_code,char ** error,gpointer userdata1,gpointer userdata2)54618c2aff7Sartem devinfo_floppy_rescan_probing_done (HalDevice *d, guint32 exit_type, gint return_code,
54718c2aff7Sartem     char **error, gpointer userdata1, gpointer userdata2)
54818c2aff7Sartem {
54918c2aff7Sartem         void *end_token = (void *) userdata1;
55018c2aff7Sartem 	const char *devfs_path;
55118c2aff7Sartem 	di_node_t node;
55218c2aff7Sartem 	HalDevice *v;
55318c2aff7Sartem 
55418c2aff7Sartem 	if (!hal_device_property_get_bool (d, "storage.removable.media_available")) {
55500687e57Sartem 		HAL_INFO (("no floppy media", hal_device_get_udi (d)));
55618c2aff7Sartem 
55718c2aff7Sartem 		/* remove child (can only be single volume) */
55818c2aff7Sartem 		if (((v = hal_device_store_match_key_value_string (hald_get_gdl(),
55900687e57Sartem         	    "info.parent", hal_device_get_udi (d))) != NULL) &&
56018c2aff7Sartem 		    ((devfs_path = hal_device_property_get_string (v,
56118c2aff7Sartem 		    "solaris.devfs_path")) != NULL)) {
56218c2aff7Sartem 			devinfo_remove_enqueue ((char *)devfs_path, NULL);
56318c2aff7Sartem 		}
56418c2aff7Sartem 	} else {
56500687e57Sartem 		HAL_INFO (("floppy media found", hal_device_get_udi (d)));
56618c2aff7Sartem 
56718c2aff7Sartem 		if ((devfs_path = hal_device_property_get_string(d, "solaris.devfs_path")) == NULL) {
56800687e57Sartem 			HAL_INFO (("no devfs_path", hal_device_get_udi (d)));
56918c2aff7Sartem 			hotplug_event_process_queue ();
57018c2aff7Sartem 			return;
57118c2aff7Sartem 		}
57218c2aff7Sartem 		if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
57318c2aff7Sartem 			HAL_INFO (("di_init %s failed %d", devfs_path, errno));
57418c2aff7Sartem 			hotplug_event_process_queue ();
57518c2aff7Sartem 			return;
57618c2aff7Sartem 		}
57718c2aff7Sartem 
57818c2aff7Sartem 		devinfo_floppy_add_volume (d, node);
57918c2aff7Sartem 
58018c2aff7Sartem 		di_fini (node);
58118c2aff7Sartem 	}
58218c2aff7Sartem 
58318c2aff7Sartem 	hotplug_event_process_queue ();
58418c2aff7Sartem }
585*55fea89dSDan Cross 
58618c2aff7Sartem /* lofi */
58718c2aff7Sartem 
58818c2aff7Sartem HalDevice *
devinfo_lofi_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)58918c2aff7Sartem devinfo_lofi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
59018c2aff7Sartem {
59118c2aff7Sartem 	return (devinfo_lofi_add_major(parent,node, devfs_path, device_type, FALSE, NULL));
59218c2aff7Sartem }
59318c2aff7Sartem 
59418c2aff7Sartem HalDevice *
devinfo_lofi_add_major(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type,gboolean rescan,HalDevice * lofi_d)59518c2aff7Sartem devinfo_lofi_add_major(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type,
59618c2aff7Sartem     gboolean rescan, HalDevice *lofi_d)
59718c2aff7Sartem {
59818c2aff7Sartem 	char	*driver_name;
59918c2aff7Sartem 	HalDevice *d = NULL;
60018c2aff7Sartem 	char	udi[HAL_PATH_MAX];
60118c2aff7Sartem 	di_devlink_handle_t devlink_hdl;
60218c2aff7Sartem         int     major;
60318c2aff7Sartem         di_minor_t minor;
60418c2aff7Sartem         dev_t   dev;
60518c2aff7Sartem         char    *minor_path = NULL;
6068b80e8cbSLin Guo - Sun Microsystems         char    *devlink = NULL;
60718c2aff7Sartem 
60818c2aff7Sartem 	driver_name = di_driver_name (node);
60918c2aff7Sartem 	if ((driver_name == NULL) || (strcmp (driver_name, "lofi") != 0)) {
61018c2aff7Sartem 		return (NULL);
61118c2aff7Sartem 	}
61218c2aff7Sartem 
61318c2aff7Sartem 	if (!rescan) {
61418c2aff7Sartem 		d = hal_device_new ();
61518c2aff7Sartem 
61618c2aff7Sartem 		devinfo_set_default_properties (d, parent, node, devfs_path);
617112cd14aSqz 		hal_device_property_set_string (d, "info.subsystem", "pseudo");
61818c2aff7Sartem 
61918c2aff7Sartem         	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
62000687e57Sartem                 	"%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
62118c2aff7Sartem         	hal_device_set_udi (d, udi);
62218c2aff7Sartem         	hal_device_property_set_string (d, "info.udi", udi);
62318c2aff7Sartem 
62418c2aff7Sartem         	devinfo_add_enqueue (d, devfs_path, &devinfo_lofi_handler);
62518c2aff7Sartem 	} else {
62618c2aff7Sartem 		d = lofi_d;
62718c2aff7Sartem 	}
62818c2aff7Sartem 
62918c2aff7Sartem 	/*
63018c2aff7Sartem 	 * Unlike normal storage, as in devinfo_storage_minors(), where
63118c2aff7Sartem 	 * sd instance -> HAL storage, sd minor node -> HAL volume,
63218c2aff7Sartem 	 * lofi always has one instance, lofi minor -> HAL storage.
63318c2aff7Sartem 	 * lofi storage never has slices, but it can have
63418c2aff7Sartem 	 * embedded pcfs partitions that fstyp would recognize
63518c2aff7Sartem 	 */
63618c2aff7Sartem 	major = di_driver_major(node);
63718c2aff7Sartem 	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
63818c2aff7Sartem 		return (d);
63918c2aff7Sartem 	}
64018c2aff7Sartem 	minor = DI_MINOR_NIL;
64118c2aff7Sartem 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
64218c2aff7Sartem 		dev = di_minor_devt(minor);
64318c2aff7Sartem 		if ((major != major(dev)) ||
64418c2aff7Sartem 		    (di_minor_type(minor) != DDM_MINOR) ||
64518c2aff7Sartem 		    (di_minor_spectype(minor) != S_IFBLK) ||
64618c2aff7Sartem 		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
64718c2aff7Sartem 			continue;
64818c2aff7Sartem 		}
64942a7bdedSjacobs 		if ((devlink = get_devlink(devlink_hdl, NULL, minor_path)) == NULL) {
65018c2aff7Sartem 			di_devfs_path_free (minor_path);
65118c2aff7Sartem         		continue;
65218c2aff7Sartem 		}
65318c2aff7Sartem 
65418c2aff7Sartem 		if (!rescan ||
65518c2aff7Sartem 		    (hal_device_store_match_key_value_string (hald_get_gdl (),
65618c2aff7Sartem 		    "solaris.devfs_path", minor_path) == NULL)) {
65718c2aff7Sartem 			devinfo_lofi_add_minor(d, node, minor_path, devlink, dev);
65818c2aff7Sartem 		}
65918c2aff7Sartem 
66018c2aff7Sartem 		di_devfs_path_free (minor_path);
66118c2aff7Sartem 		free(devlink);
66218c2aff7Sartem 	}
66318c2aff7Sartem 	di_devlink_fini (&devlink_hdl);
66418c2aff7Sartem 
66518c2aff7Sartem 	return (d);
66618c2aff7Sartem }
66718c2aff7Sartem 
66818c2aff7Sartem static void
devinfo_lofi_add_minor(HalDevice * parent,di_node_t node,char * minor_path,char * devlink,dev_t dev)66918c2aff7Sartem devinfo_lofi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, char *devlink, dev_t dev)
67018c2aff7Sartem {
67118c2aff7Sartem 	HalDevice *d;
67218c2aff7Sartem 	char	*raw;
67318c2aff7Sartem 	char	*doslink;
67418c2aff7Sartem 	char	dospath[64];
67518c2aff7Sartem 	struct devinfo_storage_minor *m;
67618c2aff7Sartem 	int	i;
67718c2aff7Sartem 
67818c2aff7Sartem 	/* add storage */
67918c2aff7Sartem 	d = hal_device_new ();
68018c2aff7Sartem 
68118c2aff7Sartem 	devinfo_set_default_properties (d, parent, node, minor_path);
68218c2aff7Sartem         hal_device_property_set_string (d, "info.category", "storage");
68318c2aff7Sartem         hal_device_add_capability (d, "storage");
68418c2aff7Sartem        	hal_device_property_set_string (d, "storage.bus", "lofi");
68518c2aff7Sartem         hal_device_property_set_bool (d, "storage.hotpluggable", TRUE);
68618c2aff7Sartem         hal_device_property_set_bool (d, "storage.removable", FALSE);
68718c2aff7Sartem         hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
68818c2aff7Sartem        	hal_device_property_set_string (d, "storage.drive_type", "disk");
68918c2aff7Sartem         hal_device_add_capability (d, "block");
69018c2aff7Sartem 	hal_device_property_set_int (d, "block.major", major(dev));
69118c2aff7Sartem 	hal_device_property_set_int (d, "block.minor", minor(dev));
69218c2aff7Sartem 	hal_device_property_set_string (d, "block.device", devlink);
69318c2aff7Sartem 	raw = dsk_to_rdsk (devlink);
69418c2aff7Sartem 	hal_device_property_set_string (d, "block.solaris.raw_device", raw);
69518c2aff7Sartem 	free (raw);
69618c2aff7Sartem 	hal_device_property_set_bool (d, "block.is_volume", FALSE);
69718c2aff7Sartem 
69818c2aff7Sartem 	devinfo_add_enqueue (d, minor_path, &devinfo_storage_handler);
69918c2aff7Sartem 
70018c2aff7Sartem 	/* add volumes: one on main device and a few pcfs candidates */
70118c2aff7Sartem 	m = devinfo_storage_new_minor(minor_path, WHOLE_DISK, devlink, dev, -1);
70218c2aff7Sartem 	devinfo_volume_add (d, node, m);
70318c2aff7Sartem 	devinfo_storage_free_minor (m);
70418c2aff7Sartem 
70518c2aff7Sartem 	doslink = (char *)calloc (1, strlen (devlink) + sizeof (":NNN") + 1);
70618c2aff7Sartem 	if (doslink != NULL) {
70718c2aff7Sartem 		for (i = 1; i < 16; i++) {
70818c2aff7Sartem 			snprintf(dospath, sizeof (dospath), WHOLE_DISK":%d", i);
70918c2aff7Sartem 			sprintf(doslink, "%s:%d", devlink, i);
71018c2aff7Sartem 			m = devinfo_storage_new_minor(minor_path, dospath, doslink, dev, i);
71118c2aff7Sartem 			devinfo_volume_add (d, node, m);
71218c2aff7Sartem 			devinfo_storage_free_minor (m);
71318c2aff7Sartem 		}
71418c2aff7Sartem 		free (doslink);
71518c2aff7Sartem 	}
71618c2aff7Sartem }
71718c2aff7Sartem 
71818c2aff7Sartem void
devinfo_lofi_remove_minor(char * parent_devfs_path,char * name)71918c2aff7Sartem devinfo_lofi_remove_minor(char *parent_devfs_path, char *name)
72018c2aff7Sartem {
72118c2aff7Sartem 	GSList *i;
72218c2aff7Sartem 	GSList *devices;
72318c2aff7Sartem 	HalDevice *d = NULL;
72418c2aff7Sartem 	const char *devfs_path;
72518c2aff7Sartem 
72618c2aff7Sartem 	devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
72718c2aff7Sartem 		"block.solaris.raw_device", name);
72818c2aff7Sartem         for (i = devices; i != NULL; i = g_slist_next (i)) {
72918c2aff7Sartem 		if (hal_device_has_capability (HAL_DEVICE (i->data), "storage")) {
73018c2aff7Sartem 			d = HAL_DEVICE (i->data);
73118c2aff7Sartem 			break;
73218c2aff7Sartem 		}
73318c2aff7Sartem 	}
73418c2aff7Sartem 	g_slist_free (devices);
73518c2aff7Sartem 
73618c2aff7Sartem 	if (d == NULL) {
73718c2aff7Sartem 		HAL_INFO (("device not found %s", name));
73818c2aff7Sartem 		return;
73918c2aff7Sartem 	}
74018c2aff7Sartem 
74118c2aff7Sartem 	if ((devfs_path = hal_device_property_get_string (d,
74218c2aff7Sartem 	    "solaris.devfs_path")) == NULL) {
74300687e57Sartem 		HAL_INFO (("devfs_path not found %s", hal_device_get_udi (d)));
74418c2aff7Sartem 		return;
74518c2aff7Sartem 	}
74618c2aff7Sartem 
74718c2aff7Sartem 	if (d != NULL) {
74818c2aff7Sartem 		devinfo_remove_branch ((char *)devfs_path, d);
74918c2aff7Sartem 	}
75018c2aff7Sartem }
75118c2aff7Sartem 
75218c2aff7Sartem /* common storage */
75318c2aff7Sartem 
75418c2aff7Sartem static void
devinfo_storage_free_minor(struct devinfo_storage_minor * m)75518c2aff7Sartem devinfo_storage_free_minor(struct devinfo_storage_minor *m)
75618c2aff7Sartem {
75718c2aff7Sartem 	if (m != NULL) {
75818c2aff7Sartem 		free (m->slice);
75918c2aff7Sartem 		free (m->devlink);
76018c2aff7Sartem 		free (m->devpath);
76118c2aff7Sartem 		free (m);
76218c2aff7Sartem 	}
76318c2aff7Sartem }
76418c2aff7Sartem 
76518c2aff7Sartem static struct devinfo_storage_minor *
devinfo_storage_new_minor(char * maindev_path,char * slice,char * devlink,dev_t dev,int dosnum)76618c2aff7Sartem devinfo_storage_new_minor(char *maindev_path, char *slice, char *devlink, dev_t dev, int dosnum)
76718c2aff7Sartem {
76818c2aff7Sartem 	struct devinfo_storage_minor *m;
76918c2aff7Sartem 	int pathlen;
77018c2aff7Sartem 	char *devpath;
77118c2aff7Sartem 
77218c2aff7Sartem 	m = (struct devinfo_storage_minor *)calloc (sizeof (struct devinfo_storage_minor), 1);
77318c2aff7Sartem 	if (m != NULL) {
77418c2aff7Sartem 		/*
77518c2aff7Sartem 		 * For volume's devfs_path we'll use minor_path/slice instead of
77618c2aff7Sartem 		 * minor_path which we use for parent storage device.
77718c2aff7Sartem 		 */
77818c2aff7Sartem 		pathlen = strlen (maindev_path) + strlen (slice) + 2;
77918c2aff7Sartem 		devpath = (char *)calloc (1, pathlen);
78018c2aff7Sartem 		snprintf(devpath, pathlen, "%s/%s", maindev_path, slice);
78118c2aff7Sartem 
78218c2aff7Sartem 		m->devpath = devpath;
78318c2aff7Sartem 		m->devlink = strdup (devlink);
78418c2aff7Sartem 		m->slice = strdup (slice);
78518c2aff7Sartem 		m->dev = dev;
78618c2aff7Sartem 		m->dosnum = dosnum;
78718c2aff7Sartem 		if ((m->devpath == NULL) || (m->devlink == NULL)) {
78818c2aff7Sartem 			devinfo_storage_free_minor (m);
78918c2aff7Sartem 			m = NULL;
79018c2aff7Sartem 		}
79118c2aff7Sartem 	}
79218c2aff7Sartem 	return (m);
79318c2aff7Sartem }
79418c2aff7Sartem 
79518c2aff7Sartem /*
79618c2aff7Sartem  * Storage minor nodes are potential "volume" objects.
79718c2aff7Sartem  * This function also completes building the parent object (main storage device).
79818c2aff7Sartem  */
79918c2aff7Sartem static void
devinfo_storage_minors(HalDevice * parent,di_node_t node,gchar * devfs_path,gboolean rescan)80018c2aff7Sartem devinfo_storage_minors(HalDevice *parent, di_node_t node, gchar *devfs_path, gboolean rescan)
80118c2aff7Sartem {
80218c2aff7Sartem 	di_devlink_handle_t devlink_hdl;
80318c2aff7Sartem 	gboolean is_cdrom;
80418c2aff7Sartem 	const char *whole_disk;
80518c2aff7Sartem 	int     major;
80618c2aff7Sartem 	di_minor_t minor;
80718c2aff7Sartem 	dev_t   dev;
80818c2aff7Sartem 	char    *minor_path = NULL;
80918c2aff7Sartem 	char    *maindev_path = NULL;
81018c2aff7Sartem 	char    *devpath, *devlink;
81118c2aff7Sartem 	int	doslink_len;
81218c2aff7Sartem 	char	*doslink;
81318c2aff7Sartem 	char	dospath[64];
81418c2aff7Sartem 	char    *slice;
81518c2aff7Sartem 	int	pathlen;
81618c2aff7Sartem 	int	i;
81718c2aff7Sartem 	char	*raw;
81818c2aff7Sartem 	boolean_t maindev_is_d0;
81918c2aff7Sartem 	GQueue	*mq;
82018c2aff7Sartem 	HalDevice *volume;
82118c2aff7Sartem 	struct devinfo_storage_minor *m;
82218c2aff7Sartem 	struct devinfo_storage_minor *maindev = NULL;
82318c2aff7Sartem 
82418c2aff7Sartem 	/* for cdroms whole disk is always s2 */
82518c2aff7Sartem 	is_cdrom = hal_device_has_capability (parent, "storage.cdrom");
82618c2aff7Sartem 	whole_disk = is_cdrom ? "s2" : WHOLE_DISK;
82718c2aff7Sartem 
82818c2aff7Sartem 	major = di_driver_major(node);
82918c2aff7Sartem 
83018c2aff7Sartem 	/* the "whole disk" p0/s2/d0 node must come first in the hotplug queue
83118c2aff7Sartem 	 * so we put other minor nodes on the local queue and move to the
83218c2aff7Sartem 	 * hotplug queue up in the end
83318c2aff7Sartem 	 */
83418c2aff7Sartem 	if ((mq = g_queue_new()) == NULL) {
83518c2aff7Sartem 		goto err;
83618c2aff7Sartem 	}
83718c2aff7Sartem 	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
83818c2aff7Sartem 		g_queue_free (mq);
83918c2aff7Sartem 		goto err;
84018c2aff7Sartem 	}
84118c2aff7Sartem 	minor = DI_MINOR_NIL;
84218c2aff7Sartem 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
84318c2aff7Sartem 		dev = di_minor_devt(minor);
84418c2aff7Sartem 		if ((major != major(dev)) ||
84518c2aff7Sartem 		    (di_minor_type(minor) != DDM_MINOR) ||
84618c2aff7Sartem 		    (di_minor_spectype(minor) != S_IFBLK) ||
84718c2aff7Sartem 		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
84818c2aff7Sartem 			continue;
84918c2aff7Sartem 		}
85042a7bdedSjacobs 		if ((devlink = get_devlink(devlink_hdl, NULL, minor_path)) == NULL) {
85118c2aff7Sartem 			di_devfs_path_free (minor_path);
85218c2aff7Sartem         		continue;
85318c2aff7Sartem 		}
85418c2aff7Sartem 
85518c2aff7Sartem 		slice = devinfo_volume_get_slice_name (devlink);
85618c2aff7Sartem 		if (strlen (slice) < 2) {
85718c2aff7Sartem 			free (devlink);
85818c2aff7Sartem 			di_devfs_path_free (minor_path);
85918c2aff7Sartem 			continue;
86018c2aff7Sartem 		}
86118c2aff7Sartem 
86218c2aff7Sartem 		/* ignore p1..N - we'll use p0:N instead */
86318c2aff7Sartem 		if ((strlen (slice) > 1) && (slice[0] == 'p') && isdigit(slice[1]) &&
86418c2aff7Sartem 		    ((atol(&slice[1])) > 0)) {
86518c2aff7Sartem 			free (devlink);
86618c2aff7Sartem 			di_devfs_path_free (minor_path);
86718c2aff7Sartem 			continue;
86818c2aff7Sartem 		}
86918c2aff7Sartem 
87018c2aff7Sartem 		m = devinfo_storage_new_minor(minor_path, slice, devlink, dev, -1);
87118c2aff7Sartem 		if (m == NULL) {
87218c2aff7Sartem 			free (devlink);
87318c2aff7Sartem 			di_devfs_path_free (minor_path);
87418c2aff7Sartem 			continue;
87518c2aff7Sartem 		}
87618c2aff7Sartem 
87718c2aff7Sartem 		/* main device is either s2/p0 or d0, the latter taking precedence */
87818c2aff7Sartem 		if ((strcmp (slice, "d0") == 0) ||
87918c2aff7Sartem 		    (((strcmp (slice, whole_disk) == 0) && (maindev == NULL)))) {
88018c2aff7Sartem 			if (maindev_path != NULL) {
88118c2aff7Sartem 				di_devfs_path_free (maindev_path);
88218c2aff7Sartem 			}
88318c2aff7Sartem 			maindev_path = minor_path;
88418c2aff7Sartem 			maindev = m;
88518c2aff7Sartem 			g_queue_push_head (mq, maindev);
88618c2aff7Sartem 		} else {
88718c2aff7Sartem 			di_devfs_path_free (minor_path);
88818c2aff7Sartem 			g_queue_push_tail (mq, m);
88918c2aff7Sartem 		}
89018c2aff7Sartem 
89118c2aff7Sartem 		free (devlink);
89218c2aff7Sartem 	}
89318c2aff7Sartem 	di_devlink_fini (&devlink_hdl);
89418c2aff7Sartem 
89518c2aff7Sartem 	if (maindev == NULL) {
89618c2aff7Sartem 		/* shouldn't typically happen */
89718c2aff7Sartem 		while (!g_queue_is_empty (mq)) {
89818c2aff7Sartem 			devinfo_storage_free_minor (g_queue_pop_head (mq));
89918c2aff7Sartem 		}
90018c2aff7Sartem 		goto err;
90118c2aff7Sartem 	}
90218c2aff7Sartem 
90318c2aff7Sartem 	/* first enqueue main storage device */
90418c2aff7Sartem 	if (!rescan) {
90518c2aff7Sartem 		hal_device_property_set_int (parent, "block.major", major);
90618c2aff7Sartem 		hal_device_property_set_int (parent, "block.minor", minor(maindev->dev));
90718c2aff7Sartem 		hal_device_property_set_string (parent, "block.device", maindev->devlink);
90818c2aff7Sartem 		raw = dsk_to_rdsk (maindev->devlink);
90918c2aff7Sartem 		hal_device_property_set_string (parent, "block.solaris.raw_device", raw);
91018c2aff7Sartem 		free (raw);
91118c2aff7Sartem 		hal_device_property_set_bool (parent, "block.is_volume", FALSE);
91218c2aff7Sartem 		hal_device_property_set_string (parent, "solaris.devfs_path", maindev_path);
91318c2aff7Sartem 		devinfo_add_enqueue (parent, maindev_path, &devinfo_storage_handler);
91418c2aff7Sartem 	}
91518c2aff7Sartem 
91618c2aff7Sartem 	/* add virtual dos volumes to enable pcfs probing */
91718c2aff7Sartem 	if (!is_cdrom) {
91818c2aff7Sartem 		doslink_len = strlen (maindev->devlink) + sizeof (":NNN") + 1;
91918c2aff7Sartem 		if ((doslink = (char *)calloc (1, doslink_len)) != NULL) {
92018c2aff7Sartem 			for (i = 1; i < 16; i++) {
92118c2aff7Sartem 				snprintf(dospath, sizeof (dospath), "%s:%d", maindev->slice, i);
92218c2aff7Sartem 				snprintf(doslink, doslink_len, "%s:%d", maindev->devlink, i);
92318c2aff7Sartem 				m = devinfo_storage_new_minor(maindev_path, dospath, doslink, maindev->dev, i);
92418c2aff7Sartem 				g_queue_push_tail (mq, m);
92518c2aff7Sartem 			}
92618c2aff7Sartem 			free (doslink);
92718c2aff7Sartem 		}
92818c2aff7Sartem 	}
92918c2aff7Sartem 
93018c2aff7Sartem 	maindev_is_d0 = (strcmp (maindev->slice, "d0") == 0);
93118c2aff7Sartem 
93218c2aff7Sartem 	/* enqueue all volumes */
93318c2aff7Sartem 	while (!g_queue_is_empty (mq)) {
93418c2aff7Sartem 		m = g_queue_pop_head (mq);
93518c2aff7Sartem 
93618c2aff7Sartem 		/* if main device is d0, we'll throw away s2/p0 */
93718c2aff7Sartem 		if (maindev_is_d0 && (strcmp (m->slice, whole_disk) == 0)) {
93818c2aff7Sartem 			devinfo_storage_free_minor (m);
93918c2aff7Sartem 			continue;
94018c2aff7Sartem 		}
94118c2aff7Sartem 		/* don't do p0 on cdrom */
94218c2aff7Sartem 		if (is_cdrom && (strcmp (m->slice, "p0") == 0)) {
94318c2aff7Sartem 			devinfo_storage_free_minor (m);
94418c2aff7Sartem 			continue;
94518c2aff7Sartem 		}
94618c2aff7Sartem 		if (rescan) {
94718c2aff7Sartem 			/* in rescan mode, don't reprobe existing volumes */
94818c2aff7Sartem 			/* XXX detect volume removal? */
94918c2aff7Sartem 			volume = hal_device_store_match_key_value_string (hald_get_gdl (),
95018c2aff7Sartem 			    "solaris.devfs_path", m->devpath);
95118c2aff7Sartem 			if ((volume == NULL) || !hal_device_has_capability(volume, "volume")) {
95218c2aff7Sartem 				devinfo_volume_add (parent, node, m);
95318c2aff7Sartem 			} else {
95418c2aff7Sartem 				HAL_INFO(("rescan volume exists %s", m->devpath));
95518c2aff7Sartem 			}
95618c2aff7Sartem 		} else {
95718c2aff7Sartem 			devinfo_volume_add (parent, node, m);
95818c2aff7Sartem 		}
95918c2aff7Sartem 		devinfo_storage_free_minor (m);
96018c2aff7Sartem 	}
96118c2aff7Sartem 
96218c2aff7Sartem 	if (maindev_path != NULL) {
96318c2aff7Sartem 		di_devfs_path_free (maindev_path);
96418c2aff7Sartem 	}
96518c2aff7Sartem 
96618c2aff7Sartem 	return;
96718c2aff7Sartem 
96818c2aff7Sartem err:
96918c2aff7Sartem 	if (maindev_path != NULL) {
97018c2aff7Sartem 		di_devfs_path_free (maindev_path);
97118c2aff7Sartem 	}
97218c2aff7Sartem 	if (!rescan) {
97318c2aff7Sartem 		devinfo_add_enqueue (parent, devfs_path, &devinfo_storage_handler);
97418c2aff7Sartem 	}
97518c2aff7Sartem }
97618c2aff7Sartem 
97718c2aff7Sartem HalDevice *
devinfo_volume_add(HalDevice * parent,di_node_t node,devinfo_storage_minor_t * m)97818c2aff7Sartem devinfo_volume_add(HalDevice *parent, di_node_t node, devinfo_storage_minor_t *m)
97918c2aff7Sartem {
98018c2aff7Sartem 	HalDevice *d;
98118c2aff7Sartem 	char	*raw;
98218c2aff7Sartem         char    udi[HAL_PATH_MAX];
98318c2aff7Sartem 	char	*devfs_path = m->devpath;
98418c2aff7Sartem 	char	*devlink = m->devlink;
98518c2aff7Sartem 	dev_t	dev = m->dev;
98618c2aff7Sartem 	int	dosnum = m->dosnum;
98718c2aff7Sartem 	char	*slice = m->slice;
98818c2aff7Sartem 
98918c2aff7Sartem 	HAL_INFO (("volume_add: devfs_path=%s devlink=%s", devfs_path, devlink));
99018c2aff7Sartem 	d = hal_device_new ();
99118c2aff7Sartem 
99218c2aff7Sartem 	devinfo_set_default_properties (d, parent, node, devfs_path);
99318c2aff7Sartem         hal_device_property_set_string (d, "info.category", "volume");
99418c2aff7Sartem 
99518c2aff7Sartem        	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
99600687e57Sartem 		"%s/%s", hal_device_get_udi (parent), slice);
99718c2aff7Sartem         hal_device_set_udi (d, udi);
99818c2aff7Sartem         hal_device_property_set_string (d, "info.udi", udi);
99918c2aff7Sartem         hal_device_property_set_string (d, "info.product", slice);
100018c2aff7Sartem 
100118c2aff7Sartem        	hal_device_add_capability (d, "volume");
100218c2aff7Sartem        	hal_device_add_capability (d, "block");
100318c2aff7Sartem 	hal_device_property_set_int (d, "block.major", major (dev));
100418c2aff7Sartem 	hal_device_property_set_int (d, "block.minor", minor (dev));
100518c2aff7Sartem 	hal_device_property_set_string (d, "block.device", devlink);
100618c2aff7Sartem 	raw = dsk_to_rdsk (devlink);
100718c2aff7Sartem 	hal_device_property_set_string (d, "block.solaris.raw_device", raw);
100818c2aff7Sartem 	free (raw);
100918c2aff7Sartem 	hal_device_property_set_string (d, "block.solaris.slice", slice);
101018c2aff7Sartem 	hal_device_property_set_bool (d, "block.is_volume", TRUE); /* XXX */
101118c2aff7Sartem 
101200687e57Sartem 	hal_device_property_set_string (d, "block.storage_device", hal_device_get_udi (parent));
101318c2aff7Sartem 
101418c2aff7Sartem 	/* set volume defaults */
101518c2aff7Sartem 	hal_device_property_set_string (d, "volume.fstype", "");
101618c2aff7Sartem 	hal_device_property_set_string (d, "volume.fsusage", "");
101718c2aff7Sartem 	hal_device_property_set_string (d, "volume.fsversion", "");
101818c2aff7Sartem 	hal_device_property_set_string (d, "volume.uuid", "");
101918c2aff7Sartem 	hal_device_property_set_string (d, "volume.label", "");
102018c2aff7Sartem 	hal_device_property_set_string (d, "volume.mount_point", "");
102118c2aff7Sartem 	hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
102218c2aff7Sartem 	if (strcmp (hal_device_property_get_string (parent, "storage.drive_type"), "cdrom") == 0) {
102318c2aff7Sartem 		hal_device_property_set_bool (d, "volume.is_disc", TRUE);
102418c2aff7Sartem 		hal_device_add_capability (d, "volume.disc");
102518c2aff7Sartem 	} else {
102618c2aff7Sartem 		hal_device_property_set_bool (d, "volume.is_disc", FALSE);
102718c2aff7Sartem 	}
102818c2aff7Sartem 
102918c2aff7Sartem 	if (dosnum > 0) {
103018c2aff7Sartem 		hal_device_property_set_bool (d, "volume.is_partition", TRUE);
103118c2aff7Sartem 		hal_device_property_set_int (d, "volume.partition.number", dosnum);
103218c2aff7Sartem 	} else {
103318c2aff7Sartem 		hal_device_property_set_bool (d, "volume.is_partition", FALSE);
103418c2aff7Sartem 	}
103518c2aff7Sartem 
103618c2aff7Sartem 	/* prober may override these */
103718c2aff7Sartem         hal_device_property_set_int (d, "volume.block_size", 512);
103818c2aff7Sartem 
103918c2aff7Sartem 	devinfo_add_enqueue (d, devfs_path, &devinfo_volume_handler);
104018c2aff7Sartem 
104118c2aff7Sartem 	return (d);
104218c2aff7Sartem }
104318c2aff7Sartem 
104418c2aff7Sartem static void
devinfo_volume_preprobing_done(HalDevice * d,gpointer userdata1,gpointer userdata2)104518c2aff7Sartem devinfo_volume_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
104618c2aff7Sartem {
104718c2aff7Sartem 	void *end_token = (void *) userdata1;
104818c2aff7Sartem 	char *whole_disk;
104918c2aff7Sartem 	char *block_device;
105018c2aff7Sartem 	const char *storage_udi;
105118c2aff7Sartem 	HalDevice *storage_d;
105218c2aff7Sartem 	const char *slice;
105318c2aff7Sartem 	int dos_num;
105418c2aff7Sartem 
105518c2aff7Sartem 	if (hal_device_property_get_bool (d, "info.ignore")) {
105600687e57Sartem 		HAL_INFO (("Preprobing merged info.ignore==TRUE %s", hal_device_get_udi (d)));
105718c2aff7Sartem 		goto skip;
105818c2aff7Sartem 	}
105918c2aff7Sartem 
106018c2aff7Sartem 	/*
106118c2aff7Sartem 	 * Optimizations: only probe if there's a chance to find something
106218c2aff7Sartem 	 */
106318c2aff7Sartem 	block_device = (char *)hal_device_property_get_string (d, "block.device");
106418c2aff7Sartem 	storage_udi = hal_device_property_get_string (d, "block.storage_device");
106518c2aff7Sartem 	slice = hal_device_property_get_string(d, "block.solaris.slice");
106618c2aff7Sartem 	if ((block_device == NULL) || (storage_udi == NULL) ||
106718c2aff7Sartem 	    (slice == NULL) || (strlen (slice) < 2)) {
106800687e57Sartem 		HAL_INFO (("Malformed volume properties %s", hal_device_get_udi (d)));
106918c2aff7Sartem 		goto skip;
107018c2aff7Sartem 	}
107118c2aff7Sartem 	storage_d = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", storage_udi);
107218c2aff7Sartem 	if (storage_d == NULL) {
107300687e57Sartem 		HAL_INFO (("Storage device not found %s", hal_device_get_udi (d)));
107418c2aff7Sartem 		goto skip;
107518c2aff7Sartem 	}
107618c2aff7Sartem 
107718c2aff7Sartem 	whole_disk = hal_device_has_capability (storage_d,
107818c2aff7Sartem 	    "storage.cdrom") ? "s2" : WHOLE_DISK;
107918c2aff7Sartem 
108018c2aff7Sartem 	if (is_dos_path(block_device, &dos_num)) {
108118c2aff7Sartem 		/* don't probe more dos volumes than probe-storage found */
108218c2aff7Sartem 		if ((hal_device_property_get_bool (storage_d, "storage.no_partitions_hint") ||
108318c2aff7Sartem 		    (dos_num > hal_device_property_get_int (storage_d, "storage.solaris.num_dos_partitions")))) {
108418c2aff7Sartem 			    HAL_INFO (("%d > %d %s", dos_num, hal_device_property_get_int (storage_d,
108500687e57Sartem 				"storage.solaris.num_dos_partitions"), hal_device_get_udi (storage_d)));
108618c2aff7Sartem 			goto skip;
108718c2aff7Sartem 		}
108818c2aff7Sartem 	} else {
108918c2aff7Sartem 		/* if no VTOC slices found, don't probe slices except s2 */
109018c2aff7Sartem 		if ((slice[0] == 's') && (isdigit(slice[1])) && ((strcmp (slice, whole_disk)) != 0) &&
109118c2aff7Sartem 		    !hal_device_property_get_bool (storage_d, "storage.solaris.vtoc_slices")) {
109200687e57Sartem 			HAL_INFO (("Not probing slice %s", hal_device_get_udi (d)));
109318c2aff7Sartem 			goto skip;
109418c2aff7Sartem 		}
109518c2aff7Sartem 	}
109618c2aff7Sartem 
109700687e57Sartem 	HAL_INFO(("Probing udi=%s", hal_device_get_udi (d)));
109818c2aff7Sartem 	hald_runner_run (d,
109918c2aff7Sartem 			"hald-probe-volume", NULL,
110018c2aff7Sartem 			DEVINFO_PROBE_VOLUME_TIMEOUT,
110118c2aff7Sartem 			devinfo_callouts_probing_done,
110218c2aff7Sartem 			(gpointer) end_token, userdata2);
110318c2aff7Sartem 
110418c2aff7Sartem 	return;
110518c2aff7Sartem 
110618c2aff7Sartem skip:
110718c2aff7Sartem 	hal_device_store_remove (hald_get_tdl (), d);
110818c2aff7Sartem 	g_object_unref (d);
110918c2aff7Sartem 	hotplug_event_end (end_token);
111018c2aff7Sartem }
111118c2aff7Sartem 
111218c2aff7Sartem static void
devinfo_volume_hotplug_begin_add(HalDevice * d,HalDevice * parent,DevinfoDevHandler * handler,void * end_token)111318c2aff7Sartem devinfo_volume_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token)
111418c2aff7Sartem {
111500687e57Sartem 	HAL_INFO(("Preprobing volume udi=%s", hal_device_get_udi (d)));
111618c2aff7Sartem 
11178b80e8cbSLin Guo - Sun Microsystems 	if (parent == NULL) {
11188b80e8cbSLin Guo - Sun Microsystems 		HAL_INFO (("no parent %s", hal_device_get_udi (d)));
11198b80e8cbSLin Guo - Sun Microsystems 		goto skip;
11208b80e8cbSLin Guo - Sun Microsystems 	}
11218b80e8cbSLin Guo - Sun Microsystems 
112218c2aff7Sartem 	if (hal_device_property_get_bool (parent, "info.ignore")) {
112318c2aff7Sartem 		HAL_INFO (("Ignoring volume: parent's info.ignore is TRUE"));
112418c2aff7Sartem 		goto skip;
112518c2aff7Sartem 	}
112618c2aff7Sartem 
112718c2aff7Sartem         /* add to TDL so preprobing callouts and prober can access it */
112818c2aff7Sartem         hal_device_store_add (hald_get_tdl (), d);
112918c2aff7Sartem 
113018c2aff7Sartem         /* Process preprobe fdi files */
113118c2aff7Sartem         di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
113218c2aff7Sartem 
113318c2aff7Sartem         /* Run preprobe callouts */
113418c2aff7Sartem         hal_util_callout_device_preprobe (d, devinfo_volume_preprobing_done, end_token, handler);
113518c2aff7Sartem 
113618c2aff7Sartem 	return;
113718c2aff7Sartem 
113818c2aff7Sartem skip:
113918c2aff7Sartem 	g_object_unref (d);
114018c2aff7Sartem 	hotplug_event_end (end_token);
114118c2aff7Sartem }
114218c2aff7Sartem 
114318c2aff7Sartem void
devinfo_storage_hotplug_begin_add(HalDevice * d,HalDevice * parent,DevinfoDevHandler * handler,void * end_token)114418c2aff7Sartem devinfo_storage_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token)
114518c2aff7Sartem {
114618c2aff7Sartem 	const char *drive_type;
114718c2aff7Sartem 	const char *p_udi;
114818c2aff7Sartem 	HalDevice *p_d;
114918c2aff7Sartem 	HalDevice *phys_d = NULL;
115018c2aff7Sartem 	const char *phys_bus;
115118c2aff7Sartem 	const char *bus;
115218c2aff7Sartem 	static const char *busses[] = { "usb", "ide", "scsi", "ieee1394",
115318c2aff7Sartem 					"pseudo" };
115418c2aff7Sartem 	int i;
115518c2aff7Sartem 
115600687e57Sartem 	HAL_INFO (("Preprobing udi=%s", hal_device_get_udi (d)));
115718c2aff7Sartem 
115818c2aff7Sartem 	if (parent == NULL) {
115900687e57Sartem 		HAL_INFO (("no parent %s", hal_device_get_udi (d)));
116018c2aff7Sartem 		goto error;
116118c2aff7Sartem 	}
116218c2aff7Sartem 
116318c2aff7Sartem 	/*
116418c2aff7Sartem 	 * figure out physical device and bus, except for floppy
116518c2aff7Sartem 	 */
116618c2aff7Sartem 	drive_type = hal_device_property_get_string (d, "storage.drive_type");
116718c2aff7Sartem 	if ((drive_type != NULL) && (strcmp (drive_type, "floppy") == 0)) {
116818c2aff7Sartem 		goto skip_bus;
116918c2aff7Sartem 	}
117018c2aff7Sartem 
117118c2aff7Sartem 	p_d = parent;
117218c2aff7Sartem 	for (;;) {
1173112cd14aSqz 		bus = hal_device_property_get_string (p_d, "info.subsystem");
117418c2aff7Sartem 		if (bus != NULL) {
117518c2aff7Sartem 			for (i = 0; i < NELEM(busses); i++) {
117618c2aff7Sartem 				if (strcmp(bus, busses[i]) == 0) {
117718c2aff7Sartem 					phys_d = p_d;
117818c2aff7Sartem 					phys_bus = busses[i];
117918c2aff7Sartem 					break;
118018c2aff7Sartem 				}
118118c2aff7Sartem 			}
118218c2aff7Sartem 		}
118318c2aff7Sartem 		/* up the tree */
118418c2aff7Sartem 		p_udi = hal_device_property_get_string (p_d, "info.parent");
118518c2aff7Sartem 		if (p_udi == NULL) {
118618c2aff7Sartem 			break;
118718c2aff7Sartem 		}
118818c2aff7Sartem 		p_d = hal_device_store_find (hald_get_gdl (), p_udi);
118918c2aff7Sartem 	}
119018c2aff7Sartem 	if (phys_d == NULL) {
119100687e57Sartem 		HAL_INFO (("no physical device %s", hal_device_get_udi (d)));
119200687e57Sartem 	} else {
119300687e57Sartem 		hal_device_property_set_string (d, "storage.physical_device", hal_device_get_udi (phys_d));
119400687e57Sartem 		hal_device_property_set_string (d, "storage.bus", phys_bus);
119518c2aff7Sartem 	}
119618c2aff7Sartem 
119718c2aff7Sartem skip_bus:
119818c2aff7Sartem 
119918c2aff7Sartem 	/* add to TDL so preprobing callouts and prober can access it */
120018c2aff7Sartem 	hal_device_store_add (hald_get_tdl (), d);
120118c2aff7Sartem 
120218c2aff7Sartem 	/* Process preprobe fdi files */
120318c2aff7Sartem 	di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
120418c2aff7Sartem 
120518c2aff7Sartem 	/* Run preprobe callouts */
120618c2aff7Sartem 	hal_util_callout_device_preprobe (d, devinfo_callouts_preprobing_done, end_token, handler);
120718c2aff7Sartem 
120818c2aff7Sartem 	return;
120918c2aff7Sartem 
121018c2aff7Sartem error:
121118c2aff7Sartem 	g_object_unref (d);
121218c2aff7Sartem 	hotplug_event_end (end_token);
121318c2aff7Sartem }
121418c2aff7Sartem 
121518c2aff7Sartem static void
devinfo_storage_probing_done(HalDevice * d,guint32 exit_type,gint return_code,char ** error,gpointer userdata1,gpointer userdata2)121618c2aff7Sartem devinfo_storage_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2)
121718c2aff7Sartem {
121818c2aff7Sartem         void *end_token = (void *) userdata1;
121918c2aff7Sartem 
122000687e57Sartem 	HAL_INFO (("devinfo_storage_probing_done %s", hal_device_get_udi (d)));
122118c2aff7Sartem 
122218c2aff7Sartem         /* Discard device if probing reports failure */
122318c2aff7Sartem         if (exit_type != HALD_RUN_SUCCESS || return_code != 0) {
122418c2aff7Sartem 		HAL_INFO (("devinfo_storage_probing_done returning exit_type=%d return_code=%d", exit_type, return_code));
122518c2aff7Sartem                 hal_device_store_remove (hald_get_tdl (), d);
122618c2aff7Sartem                 g_object_unref (d);
122718c2aff7Sartem                 hotplug_event_end (end_token);
122818c2aff7Sartem 		return;
122918c2aff7Sartem         }
123018c2aff7Sartem 
123118c2aff7Sartem 	devinfo_storage_set_nicknames (d);
123218c2aff7Sartem 
123318c2aff7Sartem         /* Merge properties from .fdi files */
123418c2aff7Sartem         di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
123518c2aff7Sartem         di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
123618c2aff7Sartem 
123718c2aff7Sartem 	hal_util_callout_device_add (d, devinfo_callouts_add_done, end_token, NULL);
123818c2aff7Sartem }
123918c2aff7Sartem 
124018c2aff7Sartem const gchar *
devinfo_storage_get_prober(HalDevice * d,int * timeout)124118c2aff7Sartem devinfo_storage_get_prober (HalDevice *d, int *timeout)
124218c2aff7Sartem {
124318c2aff7Sartem 	*timeout = DEVINFO_PROBE_STORAGE_TIMEOUT;
124418c2aff7Sartem 	return "hald-probe-storage";
124518c2aff7Sartem }
124618c2aff7Sartem 
124718c2aff7Sartem const gchar *
devinfo_volume_get_prober(HalDevice * d,int * timeout)124818c2aff7Sartem devinfo_volume_get_prober (HalDevice *d, int *timeout)
124918c2aff7Sartem {
125018c2aff7Sartem 	*timeout = DEVINFO_PROBE_VOLUME_TIMEOUT;
125118c2aff7Sartem 	return "hald-probe-volume";
125218c2aff7Sartem }
125318c2aff7Sartem 
125418c2aff7Sartem /*
125518c2aff7Sartem  * After reprobing storage, reprobe its volumes.
125618c2aff7Sartem  */
125718c2aff7Sartem static void
devinfo_storage_rescan_probing_done(HalDevice * d,guint32 exit_type,gint return_code,char ** error,gpointer userdata1,gpointer userdata2)125818c2aff7Sartem devinfo_storage_rescan_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2)
125918c2aff7Sartem {
126018c2aff7Sartem         void *end_token = (void *) userdata1;
126118c2aff7Sartem 	const char *devfs_path_orig = NULL;
126218c2aff7Sartem 	char *devfs_path = NULL;
126318c2aff7Sartem 	char *p;
126418c2aff7Sartem 	di_node_t node;
126518c2aff7Sartem 
126600687e57Sartem 	HAL_INFO (("devinfo_storage_rescan_probing_done %s", hal_device_get_udi (d)));
126718c2aff7Sartem 
126818c2aff7Sartem 	devfs_path_orig = hal_device_property_get_string (d, "solaris.devfs_path");
126918c2aff7Sartem 	if (devfs_path_orig == NULL) {
127018c2aff7Sartem 		HAL_INFO (("device has no solaris.devfs_path"));
127118c2aff7Sartem 		hotplug_event_process_queue ();
127218c2aff7Sartem 		return;
127318c2aff7Sartem 	}
127418c2aff7Sartem 
127518c2aff7Sartem 	/* strip trailing minor part if any */
127618c2aff7Sartem 	if (strrchr(devfs_path_orig, ':') != NULL) {
127718c2aff7Sartem 		if ((devfs_path = strdup (devfs_path_orig)) != NULL) {
127818c2aff7Sartem 			p = strrchr(devfs_path, ':');
127918c2aff7Sartem 			*p = '\0';
128018c2aff7Sartem 		}
128118c2aff7Sartem 	} else {
128218c2aff7Sartem 		devfs_path = (char *)devfs_path_orig;
128318c2aff7Sartem 	}
128418c2aff7Sartem 
128518c2aff7Sartem 	if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
128600687e57Sartem 		HAL_INFO (("di_init %s failed %d %s", devfs_path, errno, hal_device_get_udi (d)));
128718c2aff7Sartem 		hotplug_event_process_queue ();
128818c2aff7Sartem 		return;
128918c2aff7Sartem 	} else {
129018c2aff7Sartem 		devinfo_storage_minors (d, node, (char *)devfs_path, TRUE);
129118c2aff7Sartem 		di_fini (node);
129218c2aff7Sartem 	}
129318c2aff7Sartem 
129418c2aff7Sartem 	if (devfs_path != devfs_path_orig) {
129518c2aff7Sartem 		free (devfs_path);
129618c2aff7Sartem 	}
129718c2aff7Sartem 
129818c2aff7Sartem 	hotplug_event_process_queue ();
129918c2aff7Sartem }
130018c2aff7Sartem 
130118c2aff7Sartem /*
130218c2aff7Sartem  * For removable media devices, check for "storage.removable.media_available".
130318c2aff7Sartem  * For non-removable media devices, assume media is always there.
130418c2aff7Sartem  *
130518c2aff7Sartem  * If media is gone, enqueue remove events for all children volumes.
130618c2aff7Sartem  * If media is there, first reprobe storage, then probe for new volumes (but leave existing volumes alone).
130718c2aff7Sartem  */
130818c2aff7Sartem gboolean
devinfo_storage_device_rescan(HalDevice * d)130918c2aff7Sartem devinfo_storage_device_rescan (HalDevice *d)
131018c2aff7Sartem {
131118c2aff7Sartem 	GSList *i;
131218c2aff7Sartem 	GSList *volumes;
131318c2aff7Sartem 	HalDevice *v;
131418c2aff7Sartem 	gchar *v_devfs_path;
131518c2aff7Sartem 	const char *drive_type;
131618c2aff7Sartem 	gboolean is_floppy;
131718c2aff7Sartem 	gboolean media_available;
131818c2aff7Sartem 
131900687e57Sartem 	HAL_INFO (("devinfo_storage_device_rescan udi=%s", hal_device_get_udi (d)));
132018c2aff7Sartem 
132118c2aff7Sartem 	if (hal_device_property_get_bool (d, "block.is_volume")) {
132218c2aff7Sartem 		HAL_INFO (("nothing to do for volume"));
132318c2aff7Sartem 		return (FALSE);
132418c2aff7Sartem 	}
132518c2aff7Sartem 
132618c2aff7Sartem 	drive_type = hal_device_property_get_string (d, "storage.drive_type");
132718c2aff7Sartem 	is_floppy = (drive_type != NULL) && (strcmp (drive_type, "floppy") == 0);
1328*55fea89dSDan Cross 
132918c2aff7Sartem 	media_available = !hal_device_property_get_bool (d, "storage.removable") ||
133018c2aff7Sartem 	    hal_device_property_get_bool (d, "storage.removable.media_available");
133118c2aff7Sartem 
133218c2aff7Sartem 	if (!media_available && !is_floppy) {
133300687e57Sartem 		HAL_INFO (("media gone %s", hal_device_get_udi (d)));
133418c2aff7Sartem 
133518c2aff7Sartem 		volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
133600687e57Sartem         	    "block.storage_device", hal_device_get_udi (d));
133718c2aff7Sartem 		for (i = volumes; i != NULL; i = g_slist_next (i)) {
133818c2aff7Sartem         		v = HAL_DEVICE (i->data);
133918c2aff7Sartem 			v_devfs_path = (gchar *)hal_device_property_get_string (v, "solaris.devfs_path");
134000687e57Sartem 			HAL_INFO (("child volume %s", hal_device_get_udi (v)));
134118c2aff7Sartem 			if ((v_devfs_path != NULL) && hal_device_has_capability (v, "volume")) {
134200687e57Sartem 				HAL_INFO (("removing volume %s", hal_device_get_udi (v)));
134318c2aff7Sartem 				devinfo_remove_enqueue (v_devfs_path, NULL);
134418c2aff7Sartem 			} else {
134500687e57Sartem 				HAL_INFO (("not a volume %s", hal_device_get_udi (v)));
134618c2aff7Sartem 			}
134718c2aff7Sartem 		}
134818c2aff7Sartem 		g_slist_free (volumes);
134918c2aff7Sartem 
135018c2aff7Sartem 		hotplug_event_process_queue ();
135118c2aff7Sartem 	} else if (is_floppy) {
135200687e57Sartem 		HAL_INFO (("rescanning floppy %s", hal_device_get_udi (d)));
1353*55fea89dSDan Cross 
135418c2aff7Sartem 		hald_runner_run (d,
135518c2aff7Sartem 				 "hald-probe-storage --only-check-for-media", NULL,
135618c2aff7Sartem 				 DEVINFO_PROBE_STORAGE_TIMEOUT,
135718c2aff7Sartem 				 devinfo_floppy_rescan_probing_done,
135818c2aff7Sartem 				 NULL, NULL);
135918c2aff7Sartem 	} else {
136000687e57Sartem 		HAL_INFO (("media available %s", hal_device_get_udi (d)));
136118c2aff7Sartem 
136218c2aff7Sartem 		hald_runner_run (d,
136318c2aff7Sartem 				 "hald-probe-storage --only-check-for-media", NULL,
136418c2aff7Sartem 				 DEVINFO_PROBE_STORAGE_TIMEOUT,
136518c2aff7Sartem 				 devinfo_storage_rescan_probing_done,
136618c2aff7Sartem 				 NULL, NULL);
136718c2aff7Sartem 	}
136818c2aff7Sartem 
136918c2aff7Sartem 	return TRUE;
137018c2aff7Sartem }
137118c2aff7Sartem 
137218c2aff7Sartem static char *
devinfo_volume_get_slice_name(char * devlink)137318c2aff7Sartem devinfo_volume_get_slice_name (char *devlink)
137418c2aff7Sartem {
137518c2aff7Sartem 	char	*part, *slice, *disk;
137618c2aff7Sartem 	char	*s = NULL;
137718c2aff7Sartem 	char	*p;
137818c2aff7Sartem 
137918c2aff7Sartem 	if ((p = strstr(devlink, "/lofi/")) != 0) {
138018c2aff7Sartem 		return (p + sizeof ("/lofi/") - 1);
138118c2aff7Sartem 	}
138218c2aff7Sartem 
138318c2aff7Sartem 	part = strrchr(devlink, 'p');
138418c2aff7Sartem 	slice = strrchr(devlink, 's');
138518c2aff7Sartem 	disk = strrchr(devlink, 'd');
138618c2aff7Sartem 
138718c2aff7Sartem 	if ((part != NULL) && (part > slice) && (part > disk)) {
138818c2aff7Sartem 		s = part;
138918c2aff7Sartem 	} else if ((slice != NULL) && (slice > disk)) {
139018c2aff7Sartem 		s = slice;
139118c2aff7Sartem 	} else {
139218c2aff7Sartem 		s = disk;
139318c2aff7Sartem 	}
139418c2aff7Sartem 	if ((s != NULL) && isdigit(s[1])) {
139518c2aff7Sartem 		return (s);
139618c2aff7Sartem 	} else {
139718c2aff7Sartem 		return ("");
139818c2aff7Sartem 	}
139918c2aff7Sartem }
140018c2aff7Sartem 
140118c2aff7Sartem static gboolean
is_dos_path(char * path,int * partnum)140218c2aff7Sartem is_dos_path(char *path, int *partnum)
140318c2aff7Sartem {
140418c2aff7Sartem 	char *p;
140518c2aff7Sartem 
140618c2aff7Sartem 	if ((p = strrchr (path, ':')) == NULL) {
140718c2aff7Sartem 		return (FALSE);
140818c2aff7Sartem 	}
140918c2aff7Sartem 	return ((*partnum = atoi(p + 1)) != 0);
141018c2aff7Sartem }
141118c2aff7Sartem 
141218c2aff7Sartem static gboolean
dos_to_dev(char * path,char ** devpath,int * partnum)141318c2aff7Sartem dos_to_dev(char *path, char **devpath, int *partnum)
141418c2aff7Sartem {
141518c2aff7Sartem 	char *p;
141618c2aff7Sartem 
141718c2aff7Sartem 	if ((p = strrchr (path, ':')) == NULL) {
141818c2aff7Sartem 		return (FALSE);
141918c2aff7Sartem 	}
142018c2aff7Sartem 	if ((*partnum = atoi(p + 1)) == 0) {
142118c2aff7Sartem 		return (FALSE);
142218c2aff7Sartem 	}
142318c2aff7Sartem 	p[0] = '\0';
142418c2aff7Sartem 	*devpath = strdup(path);
142518c2aff7Sartem 	p[0] = ':';
142618c2aff7Sartem 	return (*devpath != NULL);
142718c2aff7Sartem }
142818c2aff7Sartem 
142918c2aff7Sartem static void
devinfo_storage_cleanup_mountpoint_cb(HalDevice * d,guint32 exit_type,gint return_code,gchar ** error,gpointer data1,gpointer data2)1430*55fea89dSDan Cross devinfo_storage_cleanup_mountpoint_cb (HalDevice *d, guint32 exit_type,
143118c2aff7Sartem 		       gint return_code, gchar **error,
143218c2aff7Sartem 		       gpointer data1, gpointer data2)
143318c2aff7Sartem {
143418c2aff7Sartem 	char *mount_point = (char *) data1;
143518c2aff7Sartem 
143618c2aff7Sartem 	HAL_INFO (("Cleaned up mount point '%s'", mount_point));
143718c2aff7Sartem 	g_free (mount_point);
143818c2aff7Sartem }
143918c2aff7Sartem 
144018c2aff7Sartem 
144118c2aff7Sartem void
devinfo_storage_mnttab_event(HalDevice * hal_volume)144218c2aff7Sartem devinfo_storage_mnttab_event (HalDevice *hal_volume)
144318c2aff7Sartem {
144418c2aff7Sartem 	FILE *fp = NULL;
144518c2aff7Sartem         struct extmnttab m;
144618c2aff7Sartem 	HalDevice *d;
144718c2aff7Sartem 	unsigned int major;
144818c2aff7Sartem 	unsigned int minor;
144918c2aff7Sartem 	GSList *volumes = NULL;
145018c2aff7Sartem 	GSList *v;
145118c2aff7Sartem 	char *mount_point;
145218c2aff7Sartem 	dbus_bool_t is_partition;
145318c2aff7Sartem 	const char *fstype;
145418c2aff7Sartem 	int partition_number;
145518c2aff7Sartem 
145618c2aff7Sartem 	if (hal_volume != NULL) {
145718c2aff7Sartem 		volumes = g_slist_append (NULL, hal_volume);
145818c2aff7Sartem 	} else {
145918c2aff7Sartem 		volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.category", "volume");
146018c2aff7Sartem 	}
146118c2aff7Sartem 	if (volumes == NULL) {
146218c2aff7Sartem 		return;
146318c2aff7Sartem 	}
146418c2aff7Sartem 
146518c2aff7Sartem 	if ((fp = fopen(MNTTAB, "r")) == NULL) {
146618c2aff7Sartem 		HAL_ERROR (("Open failed %s errno %d", MNTTAB, errno));
146718c2aff7Sartem 		return;
146818c2aff7Sartem 	}
146918c2aff7Sartem 
147018c2aff7Sartem 	while (getextmntent(fp, &m, 1) == 0) {
147118c2aff7Sartem 		for (v = volumes; v != NULL; v = g_slist_next (v)) {
147218c2aff7Sartem 			d = HAL_DEVICE (v->data);
147318c2aff7Sartem 			major = hal_device_property_get_int (d, "block.major");
147418c2aff7Sartem 			minor = hal_device_property_get_int (d, "block.minor");
147518c2aff7Sartem 
147618c2aff7Sartem 			/*
147718c2aff7Sartem 			 * special handling for pcfs, which encodes logical
147818c2aff7Sartem 			 * drive number into the 6 upper bits of the minor
147918c2aff7Sartem 			 */
148018c2aff7Sartem 			is_partition = hal_device_property_get_bool (d, "volume.is_partition");
148118c2aff7Sartem 			partition_number = hal_device_property_get_int (d, "volume.partition.number");
148218c2aff7Sartem 			fstype = hal_device_property_get_string (d, "volume.fstype");
148318c2aff7Sartem 
148418c2aff7Sartem 			if (is_partition && (partition_number > 0) && (strcmp (fstype, "pcfs") == 0)) {
148518c2aff7Sartem 				minor |= partition_number << 12;
148618c2aff7Sartem 			}
148718c2aff7Sartem 
148818c2aff7Sartem 			if (m.mnt_major != major || m.mnt_minor != minor) {
148918c2aff7Sartem 				continue;
149018c2aff7Sartem 			}
149118c2aff7Sartem 
149218c2aff7Sartem 			/* this volume matches the mnttab entry */
149318c2aff7Sartem 			device_property_atomic_update_begin ();
149418c2aff7Sartem 			hal_device_property_set_bool (d, "volume.is_mounted", TRUE);
149518c2aff7Sartem 			hal_device_property_set_bool (d, "volume.is_mounted_read_only",
149618c2aff7Sartem 						      hasmntopt ((struct mnttab *)&m, "ro") ? TRUE : FALSE);
149718c2aff7Sartem 			hal_device_property_set_string (d, "volume.mount_point", m.mnt_mountp);
149818c2aff7Sartem 			device_property_atomic_update_end ();
149918c2aff7Sartem 
150018c2aff7Sartem 			HAL_INFO (("set %s to be mounted at %s",
150118c2aff7Sartem 				   hal_device_get_udi (d), m.mnt_mountp));
150218c2aff7Sartem 			volumes = g_slist_delete_link (volumes, v);
150318c2aff7Sartem 		}
150418c2aff7Sartem 	}
150518c2aff7Sartem 
150618c2aff7Sartem 	/* all remaining volumes are not mounted */
150718c2aff7Sartem 	for (v = volumes; v != NULL; v = g_slist_next (v)) {
150818c2aff7Sartem 		d = HAL_DEVICE (v->data);
150918c2aff7Sartem 		mount_point = g_strdup (hal_device_property_get_string (d, "volume.mount_point"));
151018c2aff7Sartem 		if (mount_point == NULL || strlen (mount_point) == 0) {
151118c2aff7Sartem 			g_free (mount_point);
151218c2aff7Sartem 			continue;
151318c2aff7Sartem 		}
151418c2aff7Sartem 
151518c2aff7Sartem 		device_property_atomic_update_begin ();
151618c2aff7Sartem 		hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
151718c2aff7Sartem 		hal_device_property_set_bool (d, "volume.is_mounted_read_only", FALSE);
151818c2aff7Sartem 		hal_device_property_set_string (d, "volume.mount_point", "");
151918c2aff7Sartem 		device_property_atomic_update_end ();
152018c2aff7Sartem 
152118c2aff7Sartem 		HAL_INFO (("set %s to unmounted", hal_device_get_udi (d)));
152218c2aff7Sartem 
152318c2aff7Sartem 		/* cleanup if was mounted by us */
152418c2aff7Sartem 		if (hal_util_is_mounted_by_hald (mount_point)) {
152518c2aff7Sartem 			char *extra_env[2];
152618c2aff7Sartem 
152718c2aff7Sartem 			HAL_INFO (("Cleaning up '%s'", mount_point));
152818c2aff7Sartem 
152918c2aff7Sartem 			extra_env[0] = g_strdup_printf ("HALD_CLEANUP=%s", mount_point);
153018c2aff7Sartem 			extra_env[1] = NULL;
153118c2aff7Sartem 
1532*55fea89dSDan Cross 			hald_runner_run_method (d,
1533*55fea89dSDan Cross 						"hal-storage-cleanup-mountpoint",
1534*55fea89dSDan Cross 						extra_env,
1535b877e47fSAlexander Pyhalov 						"", TRUE,
153618c2aff7Sartem 						0,
153718c2aff7Sartem 						devinfo_storage_cleanup_mountpoint_cb,
153818c2aff7Sartem 						g_strdup (mount_point), NULL);
153918c2aff7Sartem 
154018c2aff7Sartem 			g_free (extra_env[0]);
154118c2aff7Sartem 		}
154218c2aff7Sartem 
154318c2aff7Sartem 		g_free (mount_point);
154418c2aff7Sartem 	}
154518c2aff7Sartem 	g_slist_free (volumes);
154618c2aff7Sartem 
154718c2aff7Sartem 	(void) fclose (fp);
154818c2aff7Sartem }
154918c2aff7Sartem 
155018c2aff7Sartem static void
devinfo_volume_force_unmount_cb(HalDevice * d,guint32 exit_type,gint return_code,gchar ** error,gpointer data1,gpointer data2)1551*55fea89dSDan Cross devinfo_volume_force_unmount_cb (HalDevice *d, guint32 exit_type,
155218c2aff7Sartem 		  gint return_code, gchar **error,
155318c2aff7Sartem 		  gpointer data1, gpointer data2)
155418c2aff7Sartem {
155518c2aff7Sartem 	void *end_token = (void *) data1;
155618c2aff7Sartem 
155700687e57Sartem 	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));
155818c2aff7Sartem 
1559*55fea89dSDan Cross 	if (exit_type == HALD_RUN_SUCCESS && error != NULL &&
156018c2aff7Sartem 	    error[0] != NULL && error[1] != NULL) {
156118c2aff7Sartem 		char *exp_name = NULL;
156218c2aff7Sartem 		char *exp_detail = NULL;
156318c2aff7Sartem 
156418c2aff7Sartem 		exp_name = error[0];
156518c2aff7Sartem 		if (error[0] != NULL) {
156618c2aff7Sartem 			exp_detail = error[1];
156718c2aff7Sartem 		}
156818c2aff7Sartem 		HAL_INFO (("failed with '%s' '%s'", exp_name, exp_detail));
156918c2aff7Sartem 	}
157018c2aff7Sartem 
157118c2aff7Sartem 	hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
157218c2aff7Sartem }
157318c2aff7Sartem 
157418c2aff7Sartem static void
devinfo_volume_force_unmount(HalDevice * d,void * end_token)157518c2aff7Sartem devinfo_volume_force_unmount (HalDevice *d, void *end_token)
157618c2aff7Sartem {
157718c2aff7Sartem 	const char *mount_point;
157818c2aff7Sartem 	char *extra_env[2];
157918c2aff7Sartem 	extra_env[0] = "HAL_METHOD_INVOKED_BY_UID=0";
158018c2aff7Sartem 	extra_env[1] = NULL;
158118c2aff7Sartem 
158218c2aff7Sartem 	mount_point = hal_device_property_get_string (d, "volume.mount_point");
158318c2aff7Sartem 
158418c2aff7Sartem 	if (mount_point == NULL || strlen (mount_point) == 0 || !hal_util_is_mounted_by_hald (mount_point)) {
158518c2aff7Sartem 		hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
158618c2aff7Sartem 		return;
158718c2aff7Sartem 	}
158818c2aff7Sartem 
158900687e57Sartem 	HAL_INFO (("devinfo_volume_force_unmount for udi='%s'", hal_device_get_udi (d)));
1590*55fea89dSDan Cross 
1591*55fea89dSDan Cross 	hald_runner_run_method (d,
1592*55fea89dSDan Cross 				"hal-storage-unmount",
1593*55fea89dSDan Cross 				extra_env,
1594b877e47fSAlexander Pyhalov 				"", TRUE,
159518c2aff7Sartem 				0,
159618c2aff7Sartem 				devinfo_volume_force_unmount_cb,
159718c2aff7Sartem 				end_token, NULL);
159818c2aff7Sartem }
159918c2aff7Sartem 
160018c2aff7Sartem void
devinfo_volume_hotplug_begin_remove(HalDevice * d,char * devfs_path,void * end_token)160118c2aff7Sartem devinfo_volume_hotplug_begin_remove (HalDevice *d, char *devfs_path, void *end_token)
160218c2aff7Sartem {
160318c2aff7Sartem 	if (hal_device_property_get_bool (d, "volume.is_mounted")) {
160418c2aff7Sartem 		devinfo_volume_force_unmount (d, end_token);
160518c2aff7Sartem 	} else {
160618c2aff7Sartem 		hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
160718c2aff7Sartem 	}
160818c2aff7Sartem }
160918c2aff7Sartem 
161018c2aff7Sartem 
161118c2aff7Sartem enum {
161218c2aff7Sartem 	LEGACY_CDROM,
161318c2aff7Sartem 	LEGACY_FLOPPY,
161418c2aff7Sartem 	LEGACY_RMDISK
161518c2aff7Sartem };
161618c2aff7Sartem 
161718c2aff7Sartem static const char *legacy_media_str[] = {
161818c2aff7Sartem 	"cdrom",
161918c2aff7Sartem 	"floppy",
162018c2aff7Sartem 	"rmdisk"
162118c2aff7Sartem };
162218c2aff7Sartem 
162318c2aff7Sartem struct enum_nick {
162418c2aff7Sartem 	const char *type;
162518c2aff7Sartem 	GSList	*nums;
162618c2aff7Sartem };
162718c2aff7Sartem 
162818c2aff7Sartem static int
devinfo_storage_get_legacy_media(HalDevice * d)162918c2aff7Sartem devinfo_storage_get_legacy_media(HalDevice *d)
163018c2aff7Sartem {
163118c2aff7Sartem 	const char *drive_type;
163218c2aff7Sartem 
163318c2aff7Sartem 	if (hal_device_has_capability (d, "storage.cdrom")) {
163418c2aff7Sartem 		return (LEGACY_CDROM);
163518c2aff7Sartem 	} else if (((drive_type = hal_device_property_get_string (d,
163618c2aff7Sartem 	    "storage.drive_type")) != NULL) && (strcmp (drive_type, "floppy") == 0)) {
163718c2aff7Sartem 		return (LEGACY_FLOPPY);
163818c2aff7Sartem 	} else if (hal_device_property_get_bool (d, "storage.removable") ||
163918c2aff7Sartem 	           hal_device_property_get_bool (d, "storage.hotpluggable")) {
164018c2aff7Sartem 		return (LEGACY_RMDISK);
164118c2aff7Sartem 	} else {
164218c2aff7Sartem 		return (-1);
164318c2aff7Sartem 	}
164418c2aff7Sartem }
164518c2aff7Sartem 
164618c2aff7Sartem static gboolean
devinfo_storage_foreach_nick(HalDeviceStore * store,HalDevice * d,gpointer user_data)164718c2aff7Sartem devinfo_storage_foreach_nick (HalDeviceStore *store, HalDevice *d, gpointer user_data)
164818c2aff7Sartem {
164918c2aff7Sartem 	struct enum_nick *en = (struct enum_nick *) user_data;
165018c2aff7Sartem 	const char *media_type;
165118c2aff7Sartem 	int media_num;
165218c2aff7Sartem 
165318c2aff7Sartem 	media_type = hal_device_property_get_string (d, "storage.solaris.legacy.media_type");
165418c2aff7Sartem 	media_num = hal_device_property_get_int (d, "storage.solaris.legacy.media_num");
165518c2aff7Sartem 	if ((media_type != NULL) && (strcmp (media_type, en->type) == 0) &&
165618c2aff7Sartem 	    (media_num >= 0)) {
165718c2aff7Sartem 		en->nums = g_slist_prepend (en->nums, GINT_TO_POINTER(media_num));
165818c2aff7Sartem 	}
165918c2aff7Sartem 	return TRUE;
166018c2aff7Sartem }
166118c2aff7Sartem 
166218c2aff7Sartem static void
devinfo_storage_append_nickname(HalDevice * d,const char * media_type,int media_num)166318c2aff7Sartem devinfo_storage_append_nickname (HalDevice *d, const char *media_type, int media_num)
166418c2aff7Sartem {
166518c2aff7Sartem 	char buf[64];
166618c2aff7Sartem 
166718c2aff7Sartem 	if (media_num == 0) {
166818c2aff7Sartem 		hal_device_property_strlist_append (d, "storage.solaris.nicknames", media_type);
166918c2aff7Sartem 	}
167018c2aff7Sartem 	snprintf(buf, sizeof (buf), "%s%d", media_type, media_num);
167118c2aff7Sartem 	hal_device_property_strlist_append (d, "storage.solaris.nicknames", buf);
167218c2aff7Sartem }
167318c2aff7Sartem 
167418c2aff7Sartem static void
devinfo_storage_set_nicknames(HalDevice * d)167518c2aff7Sartem devinfo_storage_set_nicknames (HalDevice *d)
167618c2aff7Sartem {
167718c2aff7Sartem 	int media;
167818c2aff7Sartem 	const char *media_type;
167918c2aff7Sartem 	int media_num;
168018c2aff7Sartem 	GSList *i;
168118c2aff7Sartem 	struct enum_nick en;
168218c2aff7Sartem 	char buf[64];
168318c2aff7Sartem 
168418c2aff7Sartem 	if ((media = devinfo_storage_get_legacy_media (d)) < 0) {
168518c2aff7Sartem 		return;
168618c2aff7Sartem 	}
168718c2aff7Sartem 	media_type = legacy_media_str[media];
168818c2aff7Sartem 
168918c2aff7Sartem 	/* enumerate all storage devices of this media type */
169018c2aff7Sartem 	en.type = media_type;
169118c2aff7Sartem 	en.nums = NULL;
169218c2aff7Sartem 	hal_device_store_foreach (hald_get_gdl (), devinfo_storage_foreach_nick, &en);
169318c2aff7Sartem 
169418c2aff7Sartem 	/* find a free number */
169518c2aff7Sartem 	for (media_num = 0; ; media_num++) {
169618c2aff7Sartem 		for (i = en.nums; i != NULL; i = g_slist_next (i)) {
169718c2aff7Sartem         		if (GPOINTER_TO_INT (i->data) == media_num) {
169818c2aff7Sartem 				break;
169918c2aff7Sartem 			}
170018c2aff7Sartem 		}
170118c2aff7Sartem 		if (i == NULL) {
170218c2aff7Sartem 			break;
170318c2aff7Sartem 		}
170418c2aff7Sartem 	}
170518c2aff7Sartem 	g_slist_free (en.nums);
170618c2aff7Sartem 
170718c2aff7Sartem 	hal_device_property_set_string (d, "storage.solaris.legacy.media_type", media_type);
170818c2aff7Sartem 	hal_device_property_set_int (d, "storage.solaris.legacy.media_num", media_num);
170918c2aff7Sartem 
171018c2aff7Sartem 	/* primary nickname, and also vold-style symdev */
171118c2aff7Sartem 	snprintf(buf, sizeof (buf), "%s%d", media_type, media_num);
171218c2aff7Sartem 	hal_device_property_set_string (d, "storage.solaris.legacy.symdev", buf);
171318c2aff7Sartem 	devinfo_storage_append_nickname(d, media_type, media_num);
171418c2aff7Sartem 
171518c2aff7Sartem 	/* additional nicknames */
171618c2aff7Sartem 	if (media == LEGACY_CDROM) {
171718c2aff7Sartem 		devinfo_storage_append_nickname(d, "cd", media_num);
171818c2aff7Sartem 		devinfo_storage_append_nickname(d, "sr", media_num);
171918c2aff7Sartem 	} else if (media == LEGACY_FLOPPY) {
172018c2aff7Sartem 		devinfo_storage_append_nickname(d, "fd", media_num);
172118c2aff7Sartem 		devinfo_storage_append_nickname(d, "diskette", media_num);
172218c2aff7Sartem 		devinfo_storage_append_nickname(d, "rdiskette", media_num);
172318c2aff7Sartem 	}
172418c2aff7Sartem }
1725