]> git.ipfire.org Git - ipfire-2.x.git/blame - src/hwinfo/src/hd/edd.c
Kleiner netter neuer Versuch.
[ipfire-2.x.git] / src / hwinfo / src / hd / edd.c
CommitLineData
a6316ce4
MT
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <fcntl.h>
6#include <sys/stat.h>
7#include <sys/types.h>
8
9#include "hd.h"
10#include "hd_int.h"
11#include "hddb.h"
12#include "edd.h"
13
14/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
15 * edd
16 *
17 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
18 */
19
20static void get_edd_info(hd_data_t *hd_data);
21
22void hd_scan_sysfs_edd(hd_data_t *hd_data)
23{
24 if(!hd_probe_feature(hd_data, pr_edd)) return;
25
26 hd_data->module = mod_edd;
27
28 /* some clean-up */
29 remove_hd_entries(hd_data);
30
31 hd_data->flags.edd_used = 0;
32
33 if(hd_probe_feature(hd_data, pr_edd_mod)) {
34 PROGRESS(1, 0, "edd mod");
35 load_module(hd_data, "edd");
36 }
37
38 PROGRESS(2, 0, "edd info");
39
40 get_edd_info(hd_data);
41}
42
43
44void get_edd_info(hd_data_t *hd_data)
45{
46 hd_t *hd;
47 hd_res_t *res;
48 unsigned u, u1, u2, edd_cnt = 0, lba;
49 uint64_t ul0;
50 str_list_t *sl;
51 bios_info_t *bt;
52 edd_info_t *ei;
53
54 struct sysfs_directory *sf_dir;
55 struct sysfs_directory *sf_dir_2;
56 struct sysfs_link *sf_link;
57
58 for(u = 0; u < sizeof hd_data->edd / sizeof *hd_data->edd; u++) {
59 free_mem(hd_data->edd[u].sysfs_id);
60 }
61
62 memset(hd_data->edd, 0, sizeof hd_data->edd);
63
64 sf_dir = sysfs_open_directory("/sys/firmware/edd");
65
66 if(sf_dir) {
67 if(!sysfs_read_all_subdirs(sf_dir)) {
68 if(sf_dir->subdirs) {
69 dlist_for_each_data(sf_dir->subdirs, sf_dir_2, struct sysfs_directory) {
70
71 if(
72 sscanf(sf_dir_2->name, "int13_dev%02x", &u) == 1 &&
73 u >= 0x80 &&
74 u <= 0xff
75 ) {
76 edd_cnt++;
77
78 u -= 0x80;
79
80 ei = hd_data->edd + u;
81
82 if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "sectors"), &ul0, 0)) {
83 ei->sectors = ul0;
84 }
85
86 if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "default_cylinders"), &ul0, 0)) {
87 ei->edd.cyls = ul0;
88 }
89
90 if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "default_heads"), &ul0, 0)) {
91 ei->edd.heads = ul0;
92 }
93
94 if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "default_sectors_per_track"), &ul0, 0)) {
95 ei->edd.sectors = ul0;
96 }
97
98 if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "legacy_max_cylinder"), &ul0, 0)) {
99 ei->legacy.cyls = ul0 + 1;
100 }
101
102 if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "legacy_max_head"), &ul0, 0)) {
103 ei->legacy.heads = ul0 + 1;
104 }
105
106 if(hd_attr_uint(sysfs_get_directory_attribute(sf_dir_2, "legacy_sectors_per_track"), &ul0, 0)) {
107 ei->legacy.sectors = ul0;
108 }
109
110 if(ei->sectors && ei->edd.heads && ei->edd.sectors) {
111 ei->edd.cyls = ei->sectors / (ei->edd.heads * ei->edd.sectors);
112 }
113
114 sf_link = sysfs_get_directory_link(sf_dir_2, "pci_dev");
115 if(sf_link) {
116 hd_data->edd[u].sysfs_id = new_str(hd_sysfs_id(sf_link->target));
117 if((hd = hd_find_sysfs_id(hd_data, hd_data->edd[u].sysfs_id))) {
118 hd_data->edd[u].hd_idx = hd->idx;
119 }
120 }
121
122 sl = hd_attr_list(sysfs_get_directory_attribute(sf_dir_2, "extensions"));
123 if(search_str_list(sl, "Fixed disk access")) hd_data->edd[u].ext_fixed_disk = 1;
124 if(search_str_list(sl, "Device locking and ejecting")) hd_data->edd[u].ext_lock_eject = 1;
125 if(search_str_list(sl, "Enhanced Disk Drive support")) hd_data->edd[u].ext_edd = 1;
126 if(search_str_list(sl, "64-bit extensions")) hd_data->edd[u].ext_64bit = 1;
127
128 ADD2LOG(
129 "edd: 0x%02x\n size: %"PRIu64"\n chs default: %u/%u/%u\n chs legacy: %u/%u/%u\n caps: %s%s%s%s\n attached: #%u %s\n",
130 u + 0x80,
131 ei->sectors,
132 ei->edd.cyls,
133 ei->edd.heads,
134 ei->edd.sectors,
135 ei->legacy.cyls,
136 ei->legacy.heads,
137 ei->legacy.sectors,
138 ei->ext_fixed_disk ? "fixed " : "",
139 ei->ext_lock_eject ? "lock " : "",
140 ei->ext_edd ? "edd " : "",
141 ei->ext_64bit ? "64bit " : "",
142 ei->hd_idx,
143 ei->sysfs_id ?: ""
144 );
145 }
146 }
147 }
148 }
149 }
150
151 sysfs_close_directory(sf_dir);
152
153 if(!edd_cnt) return;
154
155 for(hd = hd_data->hd; hd; hd = hd->next) {
156 if(
157 hd->base_class.id == bc_storage_device &&
158 hd->sub_class.id == sc_sdev_disk
159 ) {
160 hd->rom_id = free_mem(hd->rom_id);
161 }
162 }
163
164 /* add BIOS drive ids to disks */
165
166 /* first, check sysfs link */
167 for(u = 0; u < sizeof hd_data->edd / sizeof *hd_data->edd; u++) {
168 if(!hd_data->edd[u].hd_idx) continue;
169 for(hd = hd_data->hd; hd; hd = hd->next) {
170 if(
171 hd->base_class.id == bc_storage_device &&
172 hd->sub_class.id == sc_sdev_disk &&
173 hd->attached_to == hd_data->edd[u].hd_idx &&
174 !hd->rom_id
175 ) {
176 str_printf(&hd->rom_id, 0, "0x%02x", u + 0x80);
177 hd_data->flags.edd_used = 1;
178 hd_data->edd[u].assigned = 1;
179 break;
180 }
181 }
182 }
183
184 /* try based on disk size */
185 for(u = 0; u < sizeof hd_data->edd / sizeof *hd_data->edd; u++) {
186 if(hd_data->edd[u].assigned) continue;
187 if(!(ul0 = hd_data->edd[u].sectors)) continue;
188 for(u1 = u2 = 0; u1 < sizeof hd_data->edd / sizeof *hd_data->edd; u1++) {
189 if(ul0 == hd_data->edd[u1].sectors) u2++;
190 }
191
192 /* more than one disk with this size */
193 if(u2 != 1) continue;
194
195 for(hd = hd_data->hd; hd; hd = hd->next) {
196 if(
197 hd->base_class.id == bc_storage_device &&
198 hd->sub_class.id == sc_sdev_disk &&
199 !hd->rom_id
200 ) {
201 for(res = hd->res; res; res = res->next) {
202 if(
203 res->any.type == res_size &&
204 res->size.unit == size_unit_sectors &&
205 res->size.val1 == ul0
206 ) break;
207 }
208
209 if(!res) continue;
210
211 str_printf(&hd->rom_id, 0, "0x%02x", u + 0x80);
212 hd_data->flags.edd_used = 1;
213 hd_data->edd[u].assigned = 1;
214 break;
215 }
216 }
217 }
218
219 /* set lba support flag in BIOS data */
220 for(lba = u = 0; u < sizeof hd_data->edd / sizeof *hd_data->edd; u++) {
221 if(hd_data->edd[u].ext_fixed_disk) {
222 lba = 1;
223 break;
224 }
225 }
226
227 if(lba) {
228 for(hd = hd_data->hd; hd; hd = hd->next) {
229 if(
230 hd->base_class.id == bc_internal &&
231 hd->sub_class.id == sc_int_bios &&
232 hd->detail &&
233 hd->detail->type == hd_detail_bios &&
234 (bt = hd->detail->bios.data)
235 ) {
236 bt->lba_support = lba;
237 }
238 }
239 }
240
241}
242