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
get_sas_address(topo_mod_t * mod,char * devctl,uint32_t enclosure,uint32_t slot,char ** sas_address)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
disk_mptsas_find_disk(topo_mod_t * mod,tnode_t * baynode,char ** sas_address)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