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