1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 /* 12 * Copyright (c) 2013, Joyent, Inc. All rights reserved. 13 */ 14 15 #include <stdlib.h> 16 #include <sys/types.h> 17 #include <sys/stat.h> 18 #include <fcntl.h> 19 #include <unistd.h> 20 #include <stropts.h> 21 #include <string.h> 22 #include <strings.h> 23 24 #include <fm/topo_mod.h> 25 #include <fm/topo_list.h> 26 27 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h> 28 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h> 29 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h> 30 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h> 31 32 #include "disk.h" 33 #include "disk_drivers.h" 34 35 static int 36 get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure, 37 uint32_t slot, char **sas_address) 38 { 39 int fd, err, i; 40 mptsas_get_disk_info_t gdi; 41 mptsas_disk_info_t *di; 42 size_t disz; 43 44 bzero(&gdi, sizeof (gdi)); 45 46 if ((fd = open(devctl, O_RDWR)) == -1) { 47 topo_mod_dprintf(mod, "could not open '%s' for ioctl: %s\n", 48 devctl, strerror(errno)); 49 return (-1); 50 } 51 52 if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) { 53 topo_mod_dprintf(mod, "ioctl 1 on '%s' failed: %s\n", devctl, 54 strerror(errno)); 55 (void) close(fd); 56 return (-1); 57 } 58 59 gdi.DiskInfoArraySize = disz = sizeof (mptsas_disk_info_t) * 60 gdi.DiskCount; 61 gdi.PtrDiskInfoArray = di = topo_mod_alloc(mod, disz); 62 if (di == NULL) { 63 topo_mod_dprintf(mod, "memory allocation failed\n"); 64 (void) close(fd); 65 return (-1); 66 } 67 68 if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) { 69 topo_mod_dprintf(mod, "ioctl 2 on '%s' failed: %s\n", devctl, 70 strerror(errno)); 71 topo_mod_free(mod, di, disz); 72 (void) close(fd); 73 return (-1); 74 } 75 76 err = -1; 77 for (i = 0; i < gdi.DiskCount; i++) { 78 if (di[i].Enclosure == enclosure && di[i].Slot == slot) { 79 char sas[17]; /* 16 hex digits and NUL */ 80 (void) snprintf(sas, 17, "%llx", di[i].SasAddress); 81 topo_mod_dprintf(mod, "found mpt_sas disk (%d/%d) " 82 "with adddress %s\n", enclosure, slot, sas); 83 *sas_address = topo_mod_strdup(mod, sas); 84 err = 0; 85 break; 86 } 87 } 88 89 topo_mod_free(mod, di, disz); 90 (void) close(fd); 91 return (err); 92 } 93 94 int 95 disk_mptsas_find_disk(topo_mod_t *mod, tnode_t *baynode, char **sas_address) 96 { 97 char *devctl = NULL; 98 uint32_t enclosure, slot; 99 int err; 100 101 /* 102 * Get the required properties from the node. These come from 103 * the static XML mapping. 104 */ 105 if (topo_prop_get_string(baynode, TOPO_PGROUP_BINDING, 106 TOPO_BINDING_DEVCTL, &devctl, &err) != 0 || 107 topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING, 108 TOPO_BINDING_ENCLOSURE, &enclosure, &err) != 0 || 109 topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING, 110 TOPO_BINDING_SLOT, &slot, &err) != 0) { 111 if (devctl != NULL) 112 topo_mod_strfree(mod, devctl); 113 topo_mod_dprintf(mod, "bay node was missing mpt_sas binding " 114 "properties\n"); 115 return (-1); 116 } 117 118 return (get_sas_address(mod, devctl, enclosure, slot, sas_address)); 119 120 } 121