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