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
;
55 sprintf(path
, "/sys/bus/%s/drivers/%s", bus
, driver
);
56 driver_dir
= opendir(path
);
59 for (de
= readdir(driver_dir
); de
; de
= readdir(driver_dir
)) {
62 /* is 'de' a device? check that the 'subsystem' link exists and
63 * that its target matches 'bus'
65 sprintf(path
, "/sys/bus/%s/drivers/%s/%s/subsystem",
66 bus
, driver
, de
->d_name
);
67 n
= readlink(path
, link
, sizeof(link
));
68 if (n
< 0 || n
>= (int)sizeof(link
))
71 c
= strrchr(link
, '/');
74 if (strncmp(bus
, c
+1, strlen(bus
)) != 0)
77 /* start / add list entry */
79 head
= malloc(sizeof(*head
));
82 list
->next
= malloc(sizeof(*head
));
91 /* generate canonical path name for the device */
92 sprintf(path
, "/sys/bus/%s/drivers/%s/%s",
93 bus
, driver
, de
->d_name
);
94 list
->path
= canonicalize_file_name(path
);
101 __u16
devpath_to_vendor(const char *dev_path
)
103 char path
[strlen(dev_path
) + strlen("/vendor") + 1];
109 sprintf(path
, "%s/vendor", dev_path
);
111 fd
= open(path
, O_RDONLY
);
115 n
= read(fd
, vendor
, sizeof(vendor
));
116 if (n
== sizeof(vendor
)) {
117 vendor
[n
- 1] = '\0';
118 id
= strtoul(vendor
, NULL
, 16);
125 static int platform_has_intel_ahci(void)
127 struct sys_dev
*devices
= find_driver_devices("pci", "ahci");
131 for (dev
= devices
; dev
; dev
= dev
->next
)
132 if (devpath_to_vendor(dev
->path
) == 0x8086) {
137 free_sys_dev(&devices
);
143 static struct imsm_orom imsm_orom
;
144 static int scan(const void *start
, const void *end
)
147 const struct imsm_orom
*imsm_mem
;
148 int len
= (end
- start
);
150 for (offset
= 0; offset
< len
; offset
+= 4) {
151 imsm_mem
= start
+ offset
;
152 if (memcmp(imsm_mem
->signature
, "$VER", 4) == 0) {
153 imsm_orom
= *imsm_mem
;
161 const struct imsm_orom
*find_imsm_orom(void)
163 static int populated
= 0;
166 /* it's static data so we only need to read it once */
170 if (check_env("IMSM_TEST_OROM")) {
171 memset(&imsm_orom
, 0, sizeof(imsm_orom
));
172 imsm_orom
.rlc
= IMSM_OROM_RLC_RAID0
| IMSM_OROM_RLC_RAID1
|
173 IMSM_OROM_RLC_RAID10
| IMSM_OROM_RLC_RAID5
;
174 imsm_orom
.sss
= IMSM_OROM_SSS_4kB
| IMSM_OROM_SSS_8kB
|
175 IMSM_OROM_SSS_16kB
| IMSM_OROM_SSS_32kB
|
176 IMSM_OROM_SSS_64kB
| IMSM_OROM_SSS_128kB
|
177 IMSM_OROM_SSS_256kB
| IMSM_OROM_SSS_512kB
|
178 IMSM_OROM_SSS_1MB
| IMSM_OROM_SSS_2MB
;
183 imsm_orom
.attr
= imsm_orom
.rlc
| IMSM_OROM_ATTR_ChecksumVerify
;
188 if (!platform_has_intel_ahci())
191 /* scan option-rom memory looking for an imsm signature */
192 if (check_env("IMSM_SAFE_OROM_SCAN"))
196 if (probe_roms_init(align
) != 0)
199 populated
= scan_adapter_roms(scan
);
207 char *devt_to_devpath(dev_t dev
)
211 sprintf(device
, "/sys/dev/block/%d:%d/device", major(dev
), minor(dev
));
212 return canonicalize_file_name(device
);
215 static char *diskfd_to_devpath(int fd
)
217 /* return the device path for a disk, return NULL on error or fd
218 * refers to a partition
222 if (fstat(fd
, &st
) != 0)
224 if (!S_ISBLK(st
.st_mode
))
227 return devt_to_devpath(st
.st_rdev
);
230 int path_attached_to_hba(const char *disk_path
, const char *hba_path
)
234 if (!disk_path
|| !hba_path
)
237 if (strncmp(disk_path
, hba_path
, strlen(hba_path
)) == 0)
245 int devt_attached_to_hba(dev_t dev
, const char *hba_path
)
247 char *disk_path
= devt_to_devpath(dev
);
248 int rc
= path_attached_to_hba(disk_path
, hba_path
);
256 int disk_attached_to_hba(int fd
, const char *hba_path
)
258 char *disk_path
= diskfd_to_devpath(fd
);
259 int rc
= path_attached_to_hba(disk_path
, hba_path
);