1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 #pragma ident "%Z%%M% %I% %E% SMI" 26 27 #include <strings.h> 28 #include <devid.h> 29 #include <pthread.h> 30 #include <inttypes.h> 31 #include <sys/dkio.h> 32 #include <sys/scsi/scsi_types.h> 33 #include <fm/topo_mod.h> 34 #include <fm/topo_list.h> 35 #include <fm/libdiskstatus.h> 36 #include <sys/fm/protocol.h> 37 #include "disk.h" 38 39 static int disk_enum(topo_mod_t *, tnode_t *, const char *, 40 topo_instance_t, topo_instance_t, void *, void *); 41 42 static const topo_modops_t disk_ops = 43 { disk_enum, NULL }; 44 45 static const topo_modinfo_t disk_info = 46 {DISK, FM_FMRI_SCHEME_HC, DISK_VERSION, &disk_ops}; 47 48 /*ARGSUSED*/ 49 static int 50 disk_enum(topo_mod_t *mod, tnode_t *baynode, 51 const char *name, topo_instance_t min, topo_instance_t max, 52 void *arg, void *notused) 53 { 54 char *device; 55 int err; 56 nvlist_t *fmri; 57 topo_list_t *dlistp = topo_mod_getspecific(mod); 58 59 if (strcmp(name, DISK) != 0) { 60 topo_mod_dprintf(mod, "disk_enum: " 61 "only know how to enumerate %s components.\n", DISK); 62 return (-1); 63 } 64 65 /* set the parent fru */ 66 if (topo_node_resource(baynode, &fmri, &err) != 0) { 67 topo_mod_dprintf(mod, "disk_enum: " 68 "topo_node_resource error %s\n", topo_strerror(err)); 69 return (-1); 70 } 71 if (topo_node_fru_set(baynode, fmri, 0, &err) != 0) { 72 topo_mod_dprintf(mod, "disk_enum: " 73 "topo_node_fru error %s\n", topo_strerror(err)); 74 nvlist_free(fmri); 75 return (-1); 76 } 77 nvlist_free(fmri); 78 79 /* 80 * For internal storage, get the path to the occupant from the 81 * binding group of the bay node 82 */ 83 if (topo_prop_get_string(baynode, TOPO_PGROUP_BINDING, 84 TOPO_BINDING_OCCUPANT, &device, &err) != 0) { 85 topo_mod_dprintf(mod, "disk_enum: " 86 "binding error %s\n", topo_strerror(err)); 87 return (-1); 88 } 89 90 91 /* locate and topo enumerate the disk with that path */ 92 err = disk_declare_path(mod, baynode, dlistp, device); 93 94 topo_mod_strfree(mod, device); 95 return (err); 96 } 97 98 /*ARGSUSED*/ 99 int 100 _topo_init(topo_mod_t *mod, topo_version_t version) 101 { 102 topo_list_t *dlistp; 103 104 /* 105 * Turn on module debugging output 106 */ 107 if (getenv("TOPODISKDEBUG") != NULL) 108 topo_mod_setdebug(mod); 109 topo_mod_dprintf(mod, "_topo_init: " 110 "initializing %s enumerator\n", DISK); 111 112 if (topo_mod_register(mod, &disk_info, TOPO_VERSION) != 0) { 113 topo_mod_dprintf(mod, "_topo_init: " 114 "%s registration failed: %s\n", DISK, topo_mod_errmsg(mod)); 115 return (-1); /* mod errno already set */ 116 } 117 118 if ((dlistp = topo_mod_zalloc(mod, sizeof (topo_list_t))) == NULL) { 119 topo_mod_dprintf(mod, "_topo_inti: failed to allocate " 120 "disk list"); 121 return (-1); 122 } 123 124 if (disk_list_gather(mod, dlistp) != 0) { 125 topo_mod_unregister(mod); 126 topo_mod_free(mod, dlistp, sizeof (topo_list_t)); 127 topo_mod_dprintf(mod, "_topo_init: " 128 "failed to locate disks"); 129 return (-1); 130 } 131 132 topo_mod_dprintf(mod, "_topo_init: " 133 "%s enumerator initialized\n", DISK); 134 135 topo_mod_setspecific(mod, dlistp); 136 137 return (0); 138 } 139 140 void 141 _topo_fini(topo_mod_t *mod) 142 { 143 topo_list_t *dlistp = topo_mod_getspecific(mod); 144 disk_list_free(mod, dlistp); 145 topo_mod_free(mod, dlistp, sizeof (topo_list_t)); 146 topo_mod_unregister(mod); 147 topo_mod_dprintf(mod, "_topo_fini: " 148 "%s enumerator uninitialized\n", DISK); 149 } 150