2 * Intel(R) Matrix Storage Manager hardware and firmware support routines
4 * Copyright (C) 2008 Intel Corporation
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "platform-intel.h"
21 #include "probe_roms.h"
29 #include <sys/types.h>
32 void free_sys_dev(struct sys_dev
**list
)
35 struct sys_dev
*next
= (*list
)->next
;
44 struct sys_dev
*find_driver_devices(const char *bus
, const char *driver
)
46 /* search sysfs for devices driven by 'driver' */
52 struct sys_dev
*head
= NULL
;
53 struct sys_dev
*list
= NULL
;
54 enum sys_dev_type type
;
56 if (strcmp(driver
, "isci") == 0)
58 else if (strcmp(driver
, "ahci") == 0)
61 type
= SYS_DEV_UNKNOWN
;
63 sprintf(path
, "/sys/bus/%s/drivers/%s", bus
, driver
);
64 driver_dir
= opendir(path
);
67 for (de
= readdir(driver_dir
); de
; de
= readdir(driver_dir
)) {
70 /* is 'de' a device? check that the 'subsystem' link exists and
71 * that its target matches 'bus'
73 sprintf(path
, "/sys/bus/%s/drivers/%s/%s/subsystem",
74 bus
, driver
, de
->d_name
);
75 n
= readlink(path
, link
, sizeof(link
));
76 if (n
< 0 || n
>= (int)sizeof(link
))
79 c
= strrchr(link
, '/');
82 if (strncmp(bus
, c
+1, strlen(bus
)) != 0)
85 sprintf(path
, "/sys/bus/%s/drivers/%s/%s",
86 bus
, driver
, de
->d_name
);
88 /* if it's not Intel device skip it. */
89 if (devpath_to_vendor(path
) != 0x8086)
92 /* start / add list entry */
94 head
= malloc(sizeof(*head
));
97 list
->next
= malloc(sizeof(*head
));
107 list
->path
= canonicalize_file_name(path
);
109 if ((list
->pci_id
= strrchr(list
->path
, '/')) != NULL
)
112 closedir(driver_dir
);
116 __u16
devpath_to_vendor(const char *dev_path
)
118 char path
[strlen(dev_path
) + strlen("/vendor") + 1];
124 sprintf(path
, "%s/vendor", dev_path
);
126 fd
= open(path
, O_RDONLY
);
130 n
= read(fd
, vendor
, sizeof(vendor
));
131 if (n
== sizeof(vendor
)) {
132 vendor
[n
- 1] = '\0';
133 id
= strtoul(vendor
, NULL
, 16);
140 struct sys_dev
*find_intel_devices(void)
142 struct sys_dev
*ahci
, *isci
;
144 isci
= find_driver_devices("pci", "isci");
145 ahci
= find_driver_devices("pci", "ahci");
150 struct sys_dev
*elem
= ahci
;
158 static int platform_has_intel_devices(void)
160 struct sys_dev
*devices
;
161 devices
= find_intel_devices();
163 free_sys_dev(&devices
);
169 static struct imsm_orom imsm_orom
;
170 static int scan(const void *start
, const void *end
)
173 const struct imsm_orom
*imsm_mem
;
174 int len
= (end
- start
);
176 for (offset
= 0; offset
< len
; offset
+= 4) {
177 imsm_mem
= start
+ offset
;
178 if (memcmp(imsm_mem
->signature
, "$VER", 4) == 0) {
179 imsm_orom
= *imsm_mem
;
187 const struct imsm_orom
*find_imsm_orom(void)
189 static int populated
= 0;
192 /* it's static data so we only need to read it once */
196 if (check_env("IMSM_TEST_OROM")) {
197 memset(&imsm_orom
, 0, sizeof(imsm_orom
));
198 imsm_orom
.rlc
= IMSM_OROM_RLC_RAID0
| IMSM_OROM_RLC_RAID1
|
199 IMSM_OROM_RLC_RAID10
| IMSM_OROM_RLC_RAID5
;
200 imsm_orom
.sss
= IMSM_OROM_SSS_4kB
| IMSM_OROM_SSS_8kB
|
201 IMSM_OROM_SSS_16kB
| IMSM_OROM_SSS_32kB
|
202 IMSM_OROM_SSS_64kB
| IMSM_OROM_SSS_128kB
|
203 IMSM_OROM_SSS_256kB
| IMSM_OROM_SSS_512kB
|
204 IMSM_OROM_SSS_1MB
| IMSM_OROM_SSS_2MB
;
209 imsm_orom
.attr
= imsm_orom
.rlc
| IMSM_OROM_ATTR_ChecksumVerify
;
214 if (!platform_has_intel_devices())
217 /* scan option-rom memory looking for an imsm signature */
218 if (check_env("IMSM_SAFE_OROM_SCAN"))
222 if (probe_roms_init(align
) != 0)
225 populated
= scan_adapter_roms(scan
);
233 char *devt_to_devpath(dev_t dev
)
237 sprintf(device
, "/sys/dev/block/%d:%d/device", major(dev
), minor(dev
));
238 return canonicalize_file_name(device
);
241 char *diskfd_to_devpath(int fd
)
243 /* return the device path for a disk, return NULL on error or fd
244 * refers to a partition
248 if (fstat(fd
, &st
) != 0)
250 if (!S_ISBLK(st
.st_mode
))
253 return devt_to_devpath(st
.st_rdev
);
256 int path_attached_to_hba(const char *disk_path
, const char *hba_path
)
260 if (!disk_path
|| !hba_path
)
262 dprintf("hba: %s - disk: %s\n", hba_path
, disk_path
);
263 if (strncmp(disk_path
, hba_path
, strlen(hba_path
)) == 0)
271 int devt_attached_to_hba(dev_t dev
, const char *hba_path
)
273 char *disk_path
= devt_to_devpath(dev
);
274 int rc
= path_attached_to_hba(disk_path
, hba_path
);
282 int disk_attached_to_hba(int fd
, const char *hba_path
)
284 char *disk_path
= diskfd_to_devpath(fd
);
285 int rc
= path_attached_to_hba(disk_path
, hba_path
);