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 * Copyright 2023 Racktop Systems, Inc. 14 */ 15 16 #include <stdlib.h> 17 #include <sys/types.h> 18 #include <sys/stat.h> 19 #include <fcntl.h> 20 #include <unistd.h> 21 #include <stropts.h> 22 #include <string.h> 23 #include <strings.h> 24 25 #include <fm/topo_mod.h> 26 #include <fm/topo_list.h> 27 28 #include <sys/scsi/adapters/mpi/mpi2_type.h> 29 #include <sys/scsi/adapters/mpi/mpi2.h> 30 #include <sys/scsi/adapters/mpi/mpi2_init.h> 31 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h> 32 33 #include "disk.h" 34 #include "disk_drivers.h" 35 36 static int 37 get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure, 38 uint32_t slot, char **sas_address) 39 { 40 int fd, err, i; 41 mptsas_get_disk_info_t gdi; 42 mptsas_disk_info_t *di; 43 size_t disz; 44 45 bzero(&gdi, sizeof (gdi)); 46 47 if ((fd = open(devctl, O_RDWR)) == -1) { 48 topo_mod_dprintf(mod, "could not open '%s' for ioctl: %s\n", 49 devctl, strerror(errno)); 50 return (-1); 51 } 52 53 if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) { 54 topo_mod_dprintf(mod, "ioctl 1 on '%s' failed: %s\n", devctl, 55 strerror(errno)); 56 (void) close(fd); 57 return (-1); 58 } 59 60 gdi.DiskInfoArraySize = disz = sizeof (mptsas_disk_info_t) * 61 gdi.DiskCount; 62 gdi.PtrDiskInfoArray = di = topo_mod_alloc(mod, disz); 63 if (di == NULL) { 64 topo_mod_dprintf(mod, "memory allocation failed\n"); 65 (void) close(fd); 66 return (-1); 67 } 68 69 if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) { 70 topo_mod_dprintf(mod, "ioctl 2 on '%s' failed: %s\n", devctl, 71 strerror(errno)); 72 topo_mod_free(mod, di, disz); 73 (void) close(fd); 74 return (-1); 75 } 76 77 err = -1; 78 for (i = 0; i < gdi.DiskCount; i++) { 79 if (di[i].Enclosure == enclosure && di[i].Slot == slot) { 80 char sas[17]; /* 16 hex digits and NUL */ 81 (void) snprintf(sas, 17, "%llx", di[i].SasAddress); 82 topo_mod_dprintf(mod, "found mpt_sas disk (%d/%d) " 83 "with adddress %s\n", enclosure, slot, sas); 84 *sas_address = topo_mod_strdup(mod, sas); 85 err = 0; 86 break; 87 } 88 } 89 90 topo_mod_free(mod, di, disz); 91 (void) close(fd); 92 return (err); 93 } 94 95 int 96 disk_mptsas_find_disk(topo_mod_t *mod, tnode_t *baynode, char **sas_address) 97 { 98 char *devctl = NULL; 99 uint32_t enclosure, slot; 100 int err; 101 102 /* 103 * Get the required properties from the node. These come from 104 * the static XML mapping. 105 */ 106 if (topo_prop_get_string(baynode, TOPO_PGROUP_BINDING, 107 TOPO_BINDING_DEVCTL, &devctl, &err) != 0 || 108 topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING, 109 TOPO_BINDING_ENCLOSURE, &enclosure, &err) != 0 || 110 topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING, 111 TOPO_BINDING_SLOT, &slot, &err) != 0) { 112 if (devctl != NULL) 113 topo_mod_strfree(mod, devctl); 114 topo_mod_dprintf(mod, "bay node was missing mpt_sas binding " 115 "properties\n"); 116 return (-1); 117 } 118 119 return (get_sas_address(mod, devctl, enclosure, slot, sas_address)); 120 121 } 122