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