xref: /illumos-gate/usr/src/lib/fm/topo/modules/common/disk/disk_mptsas.c (revision d2a70789f056fc6c9ce3ab047b52126d80b0e3da)
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