patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / firmware / edd.c
1 /*
2  * linux/arch/i386/kernel/edd.c
3  *  Copyright (C) 2002, 2003, 2004 Dell Inc.
4  *  by Matt Domsch <Matt_Domsch@dell.com>
5  *  disk80 signature by Matt Domsch, Andrew Wilks, and Sandeep K. Shandilya
6  *  legacy CHS by Patrick J. LoPresti <patl@users.sourceforge.net>
7  *
8  * BIOS Enhanced Disk Drive Services (EDD)
9  * conformant to T13 Committee www.t13.org
10  *   projects 1572D, 1484D, 1386D, 1226DT
11  *
12  * This code takes information provided by BIOS EDD calls
13  * fn41 - Check Extensions Present and
14  * fn48 - Get Device Parametes with EDD extensions
15  * made in setup.S, copied to safe structures in setup.c,
16  * and presents it in sysfs.
17  *
18  * Please see http://linux.dell.com/edd30/results.html for
19  * the list of BIOSs which have been reported to implement EDD.
20  *
21  * This program is free software; you can redistribute it and/or modify
22  * it under the terms of the GNU General Public License v2.0 as published by
23  * the Free Software Foundation
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  */
31
32 #include <linux/module.h>
33 #include <linux/string.h>
34 #include <linux/types.h>
35 #include <linux/init.h>
36 #include <linux/stat.h>
37 #include <linux/err.h>
38 #include <linux/ctype.h>
39 #include <linux/slab.h>
40 #include <linux/limits.h>
41 #include <linux/device.h>
42 #include <linux/pci.h>
43 #include <linux/blkdev.h>
44 #include <linux/edd.h>
45
46 #define EDD_VERSION "0.15"
47 #define EDD_DATE    "2004-May-17"
48
49 MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
50 MODULE_DESCRIPTION("sysfs interface to BIOS EDD information");
51 MODULE_LICENSE("GPL");
52 MODULE_VERSION(EDD_VERSION);
53
54 #define left (PAGE_SIZE - (p - buf) - 1)
55
56 struct edd_device {
57         struct edd_info *info;
58         struct kobject kobj;
59 };
60
61 struct edd_attribute {
62         struct attribute attr;
63         ssize_t(*show) (struct edd_device * edev, char *buf);
64         int (*test) (struct edd_device * edev);
65 };
66
67 /* forward declarations */
68 static int edd_dev_is_type(struct edd_device *edev, const char *type);
69 static struct pci_dev *edd_get_pci_dev(struct edd_device *edev);
70
71 static struct edd_device *edd_devices[EDDMAXNR];
72
73 #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \
74 struct edd_attribute edd_attr_##_name = {       \
75         .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },     \
76         .show   = _show,                                \
77         .test   = _test,                                \
78 };
79
80 static inline struct edd_info *
81 edd_dev_get_info(struct edd_device *edev)
82 {
83         return edev->info;
84 }
85
86 static inline void
87 edd_dev_set_info(struct edd_device *edev, struct edd_info *info)
88 {
89         edev->info = info;
90 }
91
92 #define to_edd_attr(_attr) container_of(_attr,struct edd_attribute,attr)
93 #define to_edd_device(obj) container_of(obj,struct edd_device,kobj)
94
95 static ssize_t
96 edd_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
97 {
98         struct edd_device *dev = to_edd_device(kobj);
99         struct edd_attribute *edd_attr = to_edd_attr(attr);
100         ssize_t ret = 0;
101
102         if (edd_attr->show)
103                 ret = edd_attr->show(dev, buf);
104         return ret;
105 }
106
107 static struct sysfs_ops edd_attr_ops = {
108         .show = edd_attr_show,
109 };
110
111 static ssize_t
112 edd_show_host_bus(struct edd_device *edev, char *buf)
113 {
114         struct edd_info *info;
115         char *p = buf;
116         int i;
117
118         if (!edev)
119                 return -EINVAL;
120         info = edd_dev_get_info(edev);
121         if (!info || !buf)
122                 return -EINVAL;
123
124         for (i = 0; i < 4; i++) {
125                 if (isprint(info->params.host_bus_type[i])) {
126                         p += scnprintf(p, left, "%c", info->params.host_bus_type[i]);
127                 } else {
128                         p += scnprintf(p, left, " ");
129                 }
130         }
131
132         if (!strncmp(info->params.host_bus_type, "ISA", 3)) {
133                 p += scnprintf(p, left, "\tbase_address: %x\n",
134                              info->params.interface_path.isa.base_address);
135         } else if (!strncmp(info->params.host_bus_type, "PCIX", 4) ||
136                    !strncmp(info->params.host_bus_type, "PCI", 3)) {
137                 p += scnprintf(p, left,
138                              "\t%02x:%02x.%d  channel: %u\n",
139                              info->params.interface_path.pci.bus,
140                              info->params.interface_path.pci.slot,
141                              info->params.interface_path.pci.function,
142                              info->params.interface_path.pci.channel);
143         } else if (!strncmp(info->params.host_bus_type, "IBND", 4) ||
144                    !strncmp(info->params.host_bus_type, "XPRS", 4) ||
145                    !strncmp(info->params.host_bus_type, "HTPT", 4)) {
146                 p += scnprintf(p, left,
147                              "\tTBD: %llx\n",
148                              info->params.interface_path.ibnd.reserved);
149
150         } else {
151                 p += scnprintf(p, left, "\tunknown: %llx\n",
152                              info->params.interface_path.unknown.reserved);
153         }
154         return (p - buf);
155 }
156
157 static ssize_t
158 edd_show_interface(struct edd_device *edev, char *buf)
159 {
160         struct edd_info *info;
161         char *p = buf;
162         int i;
163
164         if (!edev)
165                 return -EINVAL;
166         info = edd_dev_get_info(edev);
167         if (!info || !buf)
168                 return -EINVAL;
169
170         for (i = 0; i < 8; i++) {
171                 if (isprint(info->params.interface_type[i])) {
172                         p += scnprintf(p, left, "%c", info->params.interface_type[i]);
173                 } else {
174                         p += scnprintf(p, left, " ");
175                 }
176         }
177         if (!strncmp(info->params.interface_type, "ATAPI", 5)) {
178                 p += scnprintf(p, left, "\tdevice: %u  lun: %u\n",
179                              info->params.device_path.atapi.device,
180                              info->params.device_path.atapi.lun);
181         } else if (!strncmp(info->params.interface_type, "ATA", 3)) {
182                 p += scnprintf(p, left, "\tdevice: %u\n",
183                              info->params.device_path.ata.device);
184         } else if (!strncmp(info->params.interface_type, "SCSI", 4)) {
185                 p += scnprintf(p, left, "\tid: %u  lun: %llu\n",
186                              info->params.device_path.scsi.id,
187                              info->params.device_path.scsi.lun);
188         } else if (!strncmp(info->params.interface_type, "USB", 3)) {
189                 p += scnprintf(p, left, "\tserial_number: %llx\n",
190                              info->params.device_path.usb.serial_number);
191         } else if (!strncmp(info->params.interface_type, "1394", 4)) {
192                 p += scnprintf(p, left, "\teui: %llx\n",
193                              info->params.device_path.i1394.eui);
194         } else if (!strncmp(info->params.interface_type, "FIBRE", 5)) {
195                 p += scnprintf(p, left, "\twwid: %llx lun: %llx\n",
196                              info->params.device_path.fibre.wwid,
197                              info->params.device_path.fibre.lun);
198         } else if (!strncmp(info->params.interface_type, "I2O", 3)) {
199                 p += scnprintf(p, left, "\tidentity_tag: %llx\n",
200                              info->params.device_path.i2o.identity_tag);
201         } else if (!strncmp(info->params.interface_type, "RAID", 4)) {
202                 p += scnprintf(p, left, "\tidentity_tag: %x\n",
203                              info->params.device_path.raid.array_number);
204         } else if (!strncmp(info->params.interface_type, "SATA", 4)) {
205                 p += scnprintf(p, left, "\tdevice: %u\n",
206                              info->params.device_path.sata.device);
207         } else {
208                 p += scnprintf(p, left, "\tunknown: %llx %llx\n",
209                              info->params.device_path.unknown.reserved1,
210                              info->params.device_path.unknown.reserved2);
211         }
212
213         return (p - buf);
214 }
215
216 /**
217  * edd_show_raw_data() - copies raw data to buffer for userspace to parse
218  *
219  * Returns: number of bytes written, or -EINVAL on failure
220  */
221 static ssize_t
222 edd_show_raw_data(struct edd_device *edev, char *buf)
223 {
224         struct edd_info *info;
225         ssize_t len = sizeof (info->params);
226         if (!edev)
227                 return -EINVAL;
228         info = edd_dev_get_info(edev);
229         if (!info || !buf)
230                 return -EINVAL;
231
232         if (!(info->params.key == 0xBEDD || info->params.key == 0xDDBE))
233                 len = info->params.length;
234
235         /* In case of buggy BIOSs */
236         if (len > (sizeof(info->params)))
237                 len = sizeof(info->params);
238
239         memcpy(buf, &info->params, len);
240         return len;
241 }
242
243 static ssize_t
244 edd_show_version(struct edd_device *edev, char *buf)
245 {
246         struct edd_info *info;
247         char *p = buf;
248         if (!edev)
249                 return -EINVAL;
250         info = edd_dev_get_info(edev);
251         if (!info || !buf)
252                 return -EINVAL;
253
254         p += scnprintf(p, left, "0x%02x\n", info->version);
255         return (p - buf);
256 }
257
258 static ssize_t
259 edd_show_disk80_sig(struct edd_device *edev, char *buf)
260 {
261         char *p = buf;
262         p += scnprintf(p, left, "0x%08x\n", edd_disk80_sig);
263         return (p - buf);
264 }
265
266 static ssize_t
267 edd_show_extensions(struct edd_device *edev, char *buf)
268 {
269         struct edd_info *info;
270         char *p = buf;
271         if (!edev)
272                 return -EINVAL;
273         info = edd_dev_get_info(edev);
274         if (!info || !buf)
275                 return -EINVAL;
276
277         if (info->interface_support & EDD_EXT_FIXED_DISK_ACCESS) {
278                 p += scnprintf(p, left, "Fixed disk access\n");
279         }
280         if (info->interface_support & EDD_EXT_DEVICE_LOCKING_AND_EJECTING) {
281                 p += scnprintf(p, left, "Device locking and ejecting\n");
282         }
283         if (info->interface_support & EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT) {
284                 p += scnprintf(p, left, "Enhanced Disk Drive support\n");
285         }
286         if (info->interface_support & EDD_EXT_64BIT_EXTENSIONS) {
287                 p += scnprintf(p, left, "64-bit extensions\n");
288         }
289         return (p - buf);
290 }
291
292 static ssize_t
293 edd_show_info_flags(struct edd_device *edev, char *buf)
294 {
295         struct edd_info *info;
296         char *p = buf;
297         if (!edev)
298                 return -EINVAL;
299         info = edd_dev_get_info(edev);
300         if (!info || !buf)
301                 return -EINVAL;
302
303         if (info->params.info_flags & EDD_INFO_DMA_BOUNDARY_ERROR_TRANSPARENT)
304                 p += scnprintf(p, left, "DMA boundary error transparent\n");
305         if (info->params.info_flags & EDD_INFO_GEOMETRY_VALID)
306                 p += scnprintf(p, left, "geometry valid\n");
307         if (info->params.info_flags & EDD_INFO_REMOVABLE)
308                 p += scnprintf(p, left, "removable\n");
309         if (info->params.info_flags & EDD_INFO_WRITE_VERIFY)
310                 p += scnprintf(p, left, "write verify\n");
311         if (info->params.info_flags & EDD_INFO_MEDIA_CHANGE_NOTIFICATION)
312                 p += scnprintf(p, left, "media change notification\n");
313         if (info->params.info_flags & EDD_INFO_LOCKABLE)
314                 p += scnprintf(p, left, "lockable\n");
315         if (info->params.info_flags & EDD_INFO_NO_MEDIA_PRESENT)
316                 p += scnprintf(p, left, "no media present\n");
317         if (info->params.info_flags & EDD_INFO_USE_INT13_FN50)
318                 p += scnprintf(p, left, "use int13 fn50\n");
319         return (p - buf);
320 }
321
322 static ssize_t
323 edd_show_legacy_max_cylinder(struct edd_device *edev, char *buf)
324 {
325         struct edd_info *info;
326         char *p = buf;
327         if (!edev)
328                 return -EINVAL;
329         info = edd_dev_get_info(edev);
330         if (!info || !buf)
331                 return -EINVAL;
332
333         p += snprintf(p, left, "%u\n", info->legacy_max_cylinder);
334         return (p - buf);
335 }
336
337 static ssize_t
338 edd_show_legacy_max_head(struct edd_device *edev, char *buf)
339 {
340         struct edd_info *info;
341         char *p = buf;
342         if (!edev)
343                 return -EINVAL;
344         info = edd_dev_get_info(edev);
345         if (!info || !buf)
346                 return -EINVAL;
347
348         p += snprintf(p, left, "%u\n", info->legacy_max_head);
349         return (p - buf);
350 }
351
352 static ssize_t
353 edd_show_legacy_sectors_per_track(struct edd_device *edev, char *buf)
354 {
355         struct edd_info *info;
356         char *p = buf;
357         if (!edev)
358                 return -EINVAL;
359         info = edd_dev_get_info(edev);
360         if (!info || !buf)
361                 return -EINVAL;
362
363         p += snprintf(p, left, "%u\n", info->legacy_sectors_per_track);
364         return (p - buf);
365 }
366
367 static ssize_t
368 edd_show_default_cylinders(struct edd_device *edev, char *buf)
369 {
370         struct edd_info *info;
371         char *p = buf;
372         if (!edev)
373                 return -EINVAL;
374         info = edd_dev_get_info(edev);
375         if (!info || !buf)
376                 return -EINVAL;
377
378         p += scnprintf(p, left, "%u\n", info->params.num_default_cylinders);
379         return (p - buf);
380 }
381
382 static ssize_t
383 edd_show_default_heads(struct edd_device *edev, char *buf)
384 {
385         struct edd_info *info;
386         char *p = buf;
387         if (!edev)
388                 return -EINVAL;
389         info = edd_dev_get_info(edev);
390         if (!info || !buf)
391                 return -EINVAL;
392
393         p += scnprintf(p, left, "%u\n", info->params.num_default_heads);
394         return (p - buf);
395 }
396
397 static ssize_t
398 edd_show_default_sectors_per_track(struct edd_device *edev, char *buf)
399 {
400         struct edd_info *info;
401         char *p = buf;
402         if (!edev)
403                 return -EINVAL;
404         info = edd_dev_get_info(edev);
405         if (!info || !buf)
406                 return -EINVAL;
407
408         p += scnprintf(p, left, "%u\n", info->params.sectors_per_track);
409         return (p - buf);
410 }
411
412 static ssize_t
413 edd_show_sectors(struct edd_device *edev, char *buf)
414 {
415         struct edd_info *info;
416         char *p = buf;
417         if (!edev)
418                 return -EINVAL;
419         info = edd_dev_get_info(edev);
420         if (!info || !buf)
421                 return -EINVAL;
422
423         p += scnprintf(p, left, "%llu\n", info->params.number_of_sectors);
424         return (p - buf);
425 }
426
427
428 /*
429  * Some device instances may not have all the above attributes,
430  * or the attribute values may be meaningless (i.e. if
431  * the device is < EDD 3.0, it won't have host_bus and interface
432  * information), so don't bother making files for them.  Likewise
433  * if the default_{cylinders,heads,sectors_per_track} values
434  * are zero, the BIOS doesn't provide sane values, don't bother
435  * creating files for them either.
436  */
437
438 static int
439 edd_has_legacy_max_cylinder(struct edd_device *edev)
440 {
441         struct edd_info *info;
442         if (!edev)
443                 return -EINVAL;
444         info = edd_dev_get_info(edev);
445         if (!info)
446                 return -EINVAL;
447         return info->legacy_max_cylinder > 0;
448 }
449
450 static int
451 edd_has_legacy_max_head(struct edd_device *edev)
452 {
453         struct edd_info *info;
454         if (!edev)
455                 return -EINVAL;
456         info = edd_dev_get_info(edev);
457         if (!info)
458                 return -EINVAL;
459         return info->legacy_max_head > 0;
460 }
461
462 static int
463 edd_has_legacy_sectors_per_track(struct edd_device *edev)
464 {
465         struct edd_info *info;
466         if (!edev)
467                 return -EINVAL;
468         info = edd_dev_get_info(edev);
469         if (!info)
470                 return -EINVAL;
471         return info->legacy_sectors_per_track > 0;
472 }
473
474 static int
475 edd_has_default_cylinders(struct edd_device *edev)
476 {
477         struct edd_info *info;
478         if (!edev)
479                 return -EINVAL;
480         info = edd_dev_get_info(edev);
481         if (!info)
482                 return -EINVAL;
483         return info->params.num_default_cylinders > 0;
484 }
485
486 static int
487 edd_has_default_heads(struct edd_device *edev)
488 {
489         struct edd_info *info;
490         if (!edev)
491                 return -EINVAL;
492         info = edd_dev_get_info(edev);
493         if (!info)
494                 return -EINVAL;
495         return info->params.num_default_heads > 0;
496 }
497
498 static int
499 edd_has_default_sectors_per_track(struct edd_device *edev)
500 {
501         struct edd_info *info;
502         if (!edev)
503                 return -EINVAL;
504         info = edd_dev_get_info(edev);
505         if (!info)
506                 return -EINVAL;
507         return info->params.sectors_per_track > 0;
508 }
509
510 static int
511 edd_has_edd30(struct edd_device *edev)
512 {
513         struct edd_info *info;
514         int i, nonzero_path = 0;
515         char c;
516
517         if (!edev)
518                 return 0;
519         info = edd_dev_get_info(edev);
520         if (!info)
521                 return 0;
522
523         if (!(info->params.key == 0xBEDD || info->params.key == 0xDDBE)) {
524                 return 0;
525         }
526
527         for (i = 30; i <= 73; i++) {
528                 c = *(((uint8_t *) info) + i + 4);
529                 if (c) {
530                         nonzero_path++;
531                         break;
532                 }
533         }
534         if (!nonzero_path) {
535                 return 0;
536         }
537
538         return 1;
539 }
540
541 static int
542 edd_has_disk80_sig(struct edd_device *edev)
543 {
544         struct edd_info *info;
545         if (!edev)
546                 return 0;
547         info = edd_dev_get_info(edev);
548         if (!info)
549                 return 0;
550         return info->device == 0x80;
551 }
552
553 static EDD_DEVICE_ATTR(raw_data, 0444, edd_show_raw_data, NULL);
554 static EDD_DEVICE_ATTR(version, 0444, edd_show_version, NULL);
555 static EDD_DEVICE_ATTR(extensions, 0444, edd_show_extensions, NULL);
556 static EDD_DEVICE_ATTR(info_flags, 0444, edd_show_info_flags, NULL);
557 static EDD_DEVICE_ATTR(sectors, 0444, edd_show_sectors, NULL);
558 static EDD_DEVICE_ATTR(legacy_max_cylinder, 0444,
559                        edd_show_legacy_max_cylinder,
560                        edd_has_legacy_max_cylinder);
561 static EDD_DEVICE_ATTR(legacy_max_head, 0444, edd_show_legacy_max_head,
562                        edd_has_legacy_max_head);
563 static EDD_DEVICE_ATTR(legacy_sectors_per_track, 0444,
564                        edd_show_legacy_sectors_per_track,
565                        edd_has_legacy_sectors_per_track);
566 static EDD_DEVICE_ATTR(default_cylinders, 0444, edd_show_default_cylinders,
567                        edd_has_default_cylinders);
568 static EDD_DEVICE_ATTR(default_heads, 0444, edd_show_default_heads,
569                        edd_has_default_heads);
570 static EDD_DEVICE_ATTR(default_sectors_per_track, 0444,
571                        edd_show_default_sectors_per_track,
572                        edd_has_default_sectors_per_track);
573 static EDD_DEVICE_ATTR(interface, 0444, edd_show_interface, edd_has_edd30);
574 static EDD_DEVICE_ATTR(host_bus, 0444, edd_show_host_bus, edd_has_edd30);
575 static EDD_DEVICE_ATTR(mbr_signature, 0444, edd_show_disk80_sig, edd_has_disk80_sig);
576
577
578 /* These are default attributes that are added for every edd
579  * device discovered.
580  */
581 static struct attribute * def_attrs[] = {
582         &edd_attr_raw_data.attr,
583         &edd_attr_version.attr,
584         &edd_attr_extensions.attr,
585         &edd_attr_info_flags.attr,
586         &edd_attr_sectors.attr,
587         NULL,
588 };
589
590 /* These attributes are conditional and only added for some devices. */
591 static struct edd_attribute * edd_attrs[] = {
592         &edd_attr_legacy_max_cylinder,
593         &edd_attr_legacy_max_head,
594         &edd_attr_legacy_sectors_per_track,
595         &edd_attr_default_cylinders,
596         &edd_attr_default_heads,
597         &edd_attr_default_sectors_per_track,
598         &edd_attr_interface,
599         &edd_attr_host_bus,
600         &edd_attr_mbr_signature,
601         NULL,
602 };
603
604 /**
605  *      edd_release - free edd structure
606  *      @kobj:  kobject of edd structure
607  *
608  *      This is called when the refcount of the edd structure
609  *      reaches 0. This should happen right after we unregister,
610  *      but just in case, we use the release callback anyway.
611  */
612
613 static void edd_release(struct kobject * kobj)
614 {
615         struct edd_device * dev = to_edd_device(kobj);
616         kfree(dev);
617 }
618
619 static struct kobj_type ktype_edd = {
620         .release        = edd_release,
621         .sysfs_ops      = &edd_attr_ops,
622         .default_attrs  = def_attrs,
623 };
624
625 static decl_subsys(edd,&ktype_edd,NULL);
626
627
628 /**
629  * edd_dev_is_type() - is this EDD device a 'type' device?
630  * @edev
631  * @type - a host bus or interface identifier string per the EDD spec
632  *
633  * Returns 1 (TRUE) if it is a 'type' device, 0 otherwise.
634  */
635 static int
636 edd_dev_is_type(struct edd_device *edev, const char *type)
637 {
638         struct edd_info *info;
639         if (!edev)
640                 return 0;
641         info = edd_dev_get_info(edev);
642
643         if (type && info) {
644                 if (!strncmp(info->params.host_bus_type, type, strlen(type)) ||
645                     !strncmp(info->params.interface_type, type, strlen(type)))
646                         return 1;
647         }
648         return 0;
649 }
650
651 /**
652  * edd_get_pci_dev() - finds pci_dev that matches edev
653  * @edev - edd_device
654  *
655  * Returns pci_dev if found, or NULL
656  */
657 static struct pci_dev *
658 edd_get_pci_dev(struct edd_device *edev)
659 {
660         struct edd_info *info = edd_dev_get_info(edev);
661
662         if (edd_dev_is_type(edev, "PCI")) {
663                 return pci_find_slot(info->params.interface_path.pci.bus,
664                                      PCI_DEVFN(info->params.interface_path.pci.slot,
665                                                info->params.interface_path.pci.
666                                                function));
667         }
668         return NULL;
669 }
670
671 static int
672 edd_create_symlink_to_pcidev(struct edd_device *edev)
673 {
674
675         struct pci_dev *pci_dev = edd_get_pci_dev(edev);
676         if (!pci_dev)
677                 return 1;
678         return sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
679 }
680
681 static inline void
682 edd_device_unregister(struct edd_device *edev)
683 {
684         kobject_unregister(&edev->kobj);
685 }
686
687 static void edd_populate_dir(struct edd_device * edev)
688 {
689         struct edd_attribute * attr;
690         int error = 0;
691         int i;
692
693         for (i = 0; (attr = edd_attrs[i]) && !error; i++) {
694                 if (!attr->test ||
695                     (attr->test && attr->test(edev)))
696                         error = sysfs_create_file(&edev->kobj,&attr->attr);
697         }
698
699         if (!error) {
700                 edd_create_symlink_to_pcidev(edev);
701         }
702 }
703
704 static int
705 edd_device_register(struct edd_device *edev, int i)
706 {
707         int error;
708
709         if (!edev)
710                 return 1;
711         memset(edev, 0, sizeof (*edev));
712         edd_dev_set_info(edev, &edd[i]);
713         kobject_set_name(&edev->kobj, "int13_dev%02x",
714                          edd[i].device);
715         kobj_set_kset_s(edev,edd_subsys);
716         error = kobject_register(&edev->kobj);
717         if (!error)
718                 edd_populate_dir(edev);
719         return error;
720 }
721
722 /**
723  * edd_init() - creates sysfs tree of EDD data
724  *
725  * This assumes that eddnr and edd were
726  * assigned in setup.c already.
727  */
728 static int __init
729 edd_init(void)
730 {
731         unsigned int i;
732         int rc=0;
733         struct edd_device *edev;
734
735         printk(KERN_INFO "BIOS EDD facility v%s %s, %d devices found\n",
736                EDD_VERSION, EDD_DATE, eddnr);
737
738         if (!eddnr) {
739                 printk(KERN_INFO "EDD information not available.\n");
740                 return 1;
741         }
742
743         rc = firmware_register(&edd_subsys);
744         if (rc)
745                 return rc;
746
747         for (i = 0; i < eddnr && i < EDDMAXNR && !rc; i++) {
748                 edev = kmalloc(sizeof (*edev), GFP_KERNEL);
749                 if (!edev)
750                         return -ENOMEM;
751
752                 rc = edd_device_register(edev, i);
753                 if (rc) {
754                         kfree(edev);
755                         break;
756                 }
757                 edd_devices[i] = edev;
758         }
759
760         if (rc)
761                 firmware_unregister(&edd_subsys);
762         return rc;
763 }
764
765 static void __exit
766 edd_exit(void)
767 {
768         int i;
769         struct edd_device *edev;
770
771         for (i = 0; i < eddnr && i < EDDMAXNR; i++) {
772                 if ((edev = edd_devices[i]))
773                         edd_device_unregister(edev);
774         }
775         firmware_unregister(&edd_subsys);
776 }
777
778 late_initcall(edd_init);
779 module_exit(edd_exit);