]>
Commit | Line | Data |
---|---|---|
93afd047 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 | ||
20 | static void get_edd_info(hd_data_t *hd_data); | |
21 | ||
22 | void 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 | ||
44 | void 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 |