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 * 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 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.16" 47 #define EDD_DATE "2004-Jun-25" 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 unsigned int index; 58 unsigned int mbr_signature; 59 struct edd_info *info; 60 struct kobject kobj; 61 }; 62 63 struct 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 */ 70 static int edd_dev_is_type(struct edd_device *edev, const char *type); 71 static struct pci_dev *edd_get_pci_dev(struct edd_device *edev); 72 73 static struct edd_device *edd_devices[EDD_MBR_SIG_MAX]; 74 75 #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \ 76 struct edd_attribute edd_attr_##_name = { \ 77 .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ 78 .show = _show, \ 79 .test = _test, \ 80 }; 81 82 static int 83 edd_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 88 static int 89 edd_has_edd_info(struct edd_device *edev) 90 { 91 return edev->index < min_t(unsigned char, edd.edd_info_nr, EDDMAXNR); 92 } 93 94 static inline struct edd_info * 95 edd_dev_get_info(struct edd_device *edev) 96 { 97 return edev->info; 98 } 99 100 static inline void 101 edd_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 113 static ssize_t 114 edd_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 125 static struct sysfs_ops edd_attr_ops = { 126 .show = edd_attr_show, 127 }; 128 129 static ssize_t 130 edd_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 p += scnprintf(p, left, 156 "\t%02x:%02x.%d channel: %u\n", 157 info->params.interface_path.pci.bus, 158 info->params.interface_path.pci.slot, 159 info->params.interface_path.pci.function, 160 info->params.interface_path.pci.channel); 161 } else if (!strncmp(info->params.host_bus_type, "IBND", 4) || 162 !strncmp(info->params.host_bus_type, "XPRS", 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 175 static ssize_t 176 edd_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 * 237 * Returns: number of bytes written, or -EINVAL on failure 238 */ 239 static ssize_t 240 edd_show_raw_data(struct edd_device *edev, char *buf) 241 { 242 struct edd_info *info; 243 ssize_t len = sizeof (info->params); 244 if (!edev) 245 return -EINVAL; 246 info = edd_dev_get_info(edev); 247 if (!info || !buf) 248 return -EINVAL; 249 250 if (!(info->params.key == 0xBEDD || info->params.key == 0xDDBE)) 251 len = info->params.length; 252 253 /* In case of buggy BIOSs */ 254 if (len > (sizeof(info->params))) 255 len = sizeof(info->params); 256 257 memcpy(buf, &info->params, len); 258 return len; 259 } 260 261 static ssize_t 262 edd_show_version(struct edd_device *edev, char *buf) 263 { 264 struct edd_info *info; 265 char *p = buf; 266 if (!edev) 267 return -EINVAL; 268 info = edd_dev_get_info(edev); 269 if (!info || !buf) 270 return -EINVAL; 271 272 p += scnprintf(p, left, "0x%02x\n", info->version); 273 return (p - buf); 274 } 275 276 static ssize_t 277 edd_show_mbr_signature(struct edd_device *edev, char *buf) 278 { 279 char *p = buf; 280 p += scnprintf(p, left, "0x%08x\n", edev->mbr_signature); 281 return (p - buf); 282 } 283 284 static ssize_t 285 edd_show_extensions(struct edd_device *edev, char *buf) 286 { 287 struct edd_info *info; 288 char *p = buf; 289 if (!edev) 290 return -EINVAL; 291 info = edd_dev_get_info(edev); 292 if (!info || !buf) 293 return -EINVAL; 294 295 if (info->interface_support & EDD_EXT_FIXED_DISK_ACCESS) { 296 p += scnprintf(p, left, "Fixed disk access\n"); 297 } 298 if (info->interface_support & EDD_EXT_DEVICE_LOCKING_AND_EJECTING) { 299 p += scnprintf(p, left, "Device locking and ejecting\n"); 300 } 301 if (info->interface_support & EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT) { 302 p += scnprintf(p, left, "Enhanced Disk Drive support\n"); 303 } 304 if (info->interface_support & EDD_EXT_64BIT_EXTENSIONS) { 305 p += scnprintf(p, left, "64-bit extensions\n"); 306 } 307 return (p - buf); 308 } 309 310 static ssize_t 311 edd_show_info_flags(struct edd_device *edev, char *buf) 312 { 313 struct edd_info *info; 314 char *p = buf; 315 if (!edev) 316 return -EINVAL; 317 info = edd_dev_get_info(edev); 318 if (!info || !buf) 319 return -EINVAL; 320 321 if (info->params.info_flags & EDD_INFO_DMA_BOUNDARY_ERROR_TRANSPARENT) 322 p += scnprintf(p, left, "DMA boundary error transparent\n"); 323 if (info->params.info_flags & EDD_INFO_GEOMETRY_VALID) 324 p += scnprintf(p, left, "geometry valid\n"); 325 if (info->params.info_flags & EDD_INFO_REMOVABLE) 326 p += scnprintf(p, left, "removable\n"); 327 if (info->params.info_flags & EDD_INFO_WRITE_VERIFY) 328 p += scnprintf(p, left, "write verify\n"); 329 if (info->params.info_flags & EDD_INFO_MEDIA_CHANGE_NOTIFICATION) 330 p += scnprintf(p, left, "media change notification\n"); 331 if (info->params.info_flags & EDD_INFO_LOCKABLE) 332 p += scnprintf(p, left, "lockable\n"); 333 if (info->params.info_flags & EDD_INFO_NO_MEDIA_PRESENT) 334 p += scnprintf(p, left, "no media present\n"); 335 if (info->params.info_flags & EDD_INFO_USE_INT13_FN50) 336 p += scnprintf(p, left, "use int13 fn50\n"); 337 return (p - buf); 338 } 339 340 static ssize_t 341 edd_show_legacy_max_cylinder(struct edd_device *edev, char *buf) 342 { 343 struct edd_info *info; 344 char *p = buf; 345 if (!edev) 346 return -EINVAL; 347 info = edd_dev_get_info(edev); 348 if (!info || !buf) 349 return -EINVAL; 350 351 p += snprintf(p, left, "%u\n", info->legacy_max_cylinder); 352 return (p - buf); 353 } 354 355 static ssize_t 356 edd_show_legacy_max_head(struct edd_device *edev, char *buf) 357 { 358 struct edd_info *info; 359 char *p = buf; 360 if (!edev) 361 return -EINVAL; 362 info = edd_dev_get_info(edev); 363 if (!info || !buf) 364 return -EINVAL; 365 366 p += snprintf(p, left, "%u\n", info->legacy_max_head); 367 return (p - buf); 368 } 369 370 static ssize_t 371 edd_show_legacy_sectors_per_track(struct edd_device *edev, char *buf) 372 { 373 struct edd_info *info; 374 char *p = buf; 375 if (!edev) 376 return -EINVAL; 377 info = edd_dev_get_info(edev); 378 if (!info || !buf) 379 return -EINVAL; 380 381 p += snprintf(p, left, "%u\n", info->legacy_sectors_per_track); 382 return (p - buf); 383 } 384 385 static ssize_t 386 edd_show_default_cylinders(struct edd_device *edev, char *buf) 387 { 388 struct edd_info *info; 389 char *p = buf; 390 if (!edev) 391 return -EINVAL; 392 info = edd_dev_get_info(edev); 393 if (!info || !buf) 394 return -EINVAL; 395 396 p += scnprintf(p, left, "%u\n", info->params.num_default_cylinders); 397 return (p - buf); 398 } 399 400 static ssize_t 401 edd_show_default_heads(struct edd_device *edev, char *buf) 402 { 403 struct edd_info *info; 404 char *p = buf; 405 if (!edev) 406 return -EINVAL; 407 info = edd_dev_get_info(edev); 408 if (!info || !buf) 409 return -EINVAL; 410 411 p += scnprintf(p, left, "%u\n", info->params.num_default_heads); 412 return (p - buf); 413 } 414 415 static ssize_t 416 edd_show_default_sectors_per_track(struct edd_device *edev, char *buf) 417 { 418 struct edd_info *info; 419 char *p = buf; 420 if (!edev) 421 return -EINVAL; 422 info = edd_dev_get_info(edev); 423 if (!info || !buf) 424 return -EINVAL; 425 426 p += scnprintf(p, left, "%u\n", info->params.sectors_per_track); 427 return (p - buf); 428 } 429 430 static ssize_t 431 edd_show_sectors(struct edd_device *edev, char *buf) 432 { 433 struct edd_info *info; 434 char *p = buf; 435 if (!edev) 436 return -EINVAL; 437 info = edd_dev_get_info(edev); 438 if (!info || !buf) 439 return -EINVAL; 440 441 p += scnprintf(p, left, "%llu\n", info->params.number_of_sectors); 442 return (p - buf); 443 } 444 445 446 /* 447 * Some device instances may not have all the above attributes, 448 * or the attribute values may be meaningless (i.e. if 449 * the device is < EDD 3.0, it won't have host_bus and interface 450 * information), so don't bother making files for them. Likewise 451 * if the default_{cylinders,heads,sectors_per_track} values 452 * are zero, the BIOS doesn't provide sane values, don't bother 453 * creating files for them either. 454 */ 455 456 static int 457 edd_has_legacy_max_cylinder(struct edd_device *edev) 458 { 459 struct edd_info *info; 460 if (!edev) 461 return 0; 462 info = edd_dev_get_info(edev); 463 if (!info) 464 return 0; 465 return info->legacy_max_cylinder > 0; 466 } 467 468 static int 469 edd_has_legacy_max_head(struct edd_device *edev) 470 { 471 struct edd_info *info; 472 if (!edev) 473 return 0; 474 info = edd_dev_get_info(edev); 475 if (!info) 476 return 0; 477 return info->legacy_max_head > 0; 478 } 479 480 static int 481 edd_has_legacy_sectors_per_track(struct edd_device *edev) 482 { 483 struct edd_info *info; 484 if (!edev) 485 return 0; 486 info = edd_dev_get_info(edev); 487 if (!info) 488 return 0; 489 return info->legacy_sectors_per_track > 0; 490 } 491 492 static int 493 edd_has_default_cylinders(struct edd_device *edev) 494 { 495 struct edd_info *info; 496 if (!edev) 497 return 0; 498 info = edd_dev_get_info(edev); 499 if (!info) 500 return 0; 501 return info->params.num_default_cylinders > 0; 502 } 503 504 static int 505 edd_has_default_heads(struct edd_device *edev) 506 { 507 struct edd_info *info; 508 if (!edev) 509 return 0; 510 info = edd_dev_get_info(edev); 511 if (!info) 512 return 0; 513 return info->params.num_default_heads > 0; 514 } 515 516 static int 517 edd_has_default_sectors_per_track(struct edd_device *edev) 518 { 519 struct edd_info *info; 520 if (!edev) 521 return 0; 522 info = edd_dev_get_info(edev); 523 if (!info) 524 return 0; 525 return info->params.sectors_per_track > 0; 526 } 527 528 static int 529 edd_has_edd30(struct edd_device *edev) 530 { 531 struct edd_info *info; 532 int i, nonzero_path = 0; 533 char c; 534 535 if (!edev) 536 return 0; 537 info = edd_dev_get_info(edev); 538 if (!info) 539 return 0; 540 541 if (!(info->params.key == 0xBEDD || info->params.key == 0xDDBE)) { 542 return 0; 543 } 544 545 for (i = 30; i <= 73; i++) { 546 c = *(((uint8_t *) info) + i + 4); 547 if (c) { 548 nonzero_path++; 549 break; 550 } 551 } 552 if (!nonzero_path) { 553 return 0; 554 } 555 556 return 1; 557 } 558 559 560 static EDD_DEVICE_ATTR(raw_data, 0444, edd_show_raw_data, edd_has_edd_info); 561 static EDD_DEVICE_ATTR(version, 0444, edd_show_version, edd_has_edd_info); 562 static EDD_DEVICE_ATTR(extensions, 0444, edd_show_extensions, edd_has_edd_info); 563 static EDD_DEVICE_ATTR(info_flags, 0444, edd_show_info_flags, edd_has_edd_info); 564 static EDD_DEVICE_ATTR(sectors, 0444, edd_show_sectors, edd_has_edd_info); 565 static EDD_DEVICE_ATTR(legacy_max_cylinder, 0444, 566 edd_show_legacy_max_cylinder, 567 edd_has_legacy_max_cylinder); 568 static EDD_DEVICE_ATTR(legacy_max_head, 0444, edd_show_legacy_max_head, 569 edd_has_legacy_max_head); 570 static EDD_DEVICE_ATTR(legacy_sectors_per_track, 0444, 571 edd_show_legacy_sectors_per_track, 572 edd_has_legacy_sectors_per_track); 573 static EDD_DEVICE_ATTR(default_cylinders, 0444, edd_show_default_cylinders, 574 edd_has_default_cylinders); 575 static EDD_DEVICE_ATTR(default_heads, 0444, edd_show_default_heads, 576 edd_has_default_heads); 577 static EDD_DEVICE_ATTR(default_sectors_per_track, 0444, 578 edd_show_default_sectors_per_track, 579 edd_has_default_sectors_per_track); 580 static EDD_DEVICE_ATTR(interface, 0444, edd_show_interface, edd_has_edd30); 581 static EDD_DEVICE_ATTR(host_bus, 0444, edd_show_host_bus, edd_has_edd30); 582 static EDD_DEVICE_ATTR(mbr_signature, 0444, edd_show_mbr_signature, edd_has_mbr_signature); 583 584 585 /* These are default attributes that are added for every edd 586 * device discovered. There are none. 587 */ 588 static struct attribute * def_attrs[] = { 589 NULL, 590 }; 591 592 /* These attributes are conditional and only added for some devices. */ 593 static struct edd_attribute * edd_attrs[] = { 594 &edd_attr_raw_data, 595 &edd_attr_version, 596 &edd_attr_extensions, 597 &edd_attr_info_flags, 598 &edd_attr_sectors, 599 &edd_attr_legacy_max_cylinder, 600 &edd_attr_legacy_max_head, 601 &edd_attr_legacy_sectors_per_track, 602 &edd_attr_default_cylinders, 603 &edd_attr_default_heads, 604 &edd_attr_default_sectors_per_track, 605 &edd_attr_interface, 606 &edd_attr_host_bus, 607 &edd_attr_mbr_signature, 608 NULL, 609 }; 610 611 /** 612 * edd_release - free edd structure 613 * @kobj: kobject of edd structure 614 * 615 * This is called when the refcount of the edd structure 616 * reaches 0. This should happen right after we unregister, 617 * but just in case, we use the release callback anyway. 618 */ 619 620 static void edd_release(struct kobject * kobj) 621 { 622 struct edd_device * dev = to_edd_device(kobj); 623 kfree(dev); 624 } 625 626 static struct kobj_type ktype_edd = { 627 .release = edd_release, 628 .sysfs_ops = &edd_attr_ops, 629 .default_attrs = def_attrs, 630 }; 631 632 static decl_subsys(edd,&ktype_edd,NULL); 633 634 635 /** 636 * edd_dev_is_type() - is this EDD device a 'type' device? 637 * @edev 638 * @type - a host bus or interface identifier string per the EDD spec 639 * 640 * Returns 1 (TRUE) if it is a 'type' device, 0 otherwise. 641 */ 642 static int 643 edd_dev_is_type(struct edd_device *edev, const char *type) 644 { 645 struct edd_info *info; 646 if (!edev) 647 return 0; 648 info = edd_dev_get_info(edev); 649 650 if (type && info) { 651 if (!strncmp(info->params.host_bus_type, type, strlen(type)) || 652 !strncmp(info->params.interface_type, type, strlen(type))) 653 return 1; 654 } 655 return 0; 656 } 657 658 /** 659 * edd_get_pci_dev() - finds pci_dev that matches edev 660 * @edev - edd_device 661 * 662 * Returns pci_dev if found, or NULL 663 */ 664 static struct pci_dev * 665 edd_get_pci_dev(struct edd_device *edev) 666 { 667 struct edd_info *info = edd_dev_get_info(edev); 668 669 if (edd_dev_is_type(edev, "PCI")) { 670 return pci_find_slot(info->params.interface_path.pci.bus, 671 PCI_DEVFN(info->params.interface_path.pci.slot, 672 info->params.interface_path.pci. 673 function)); 674 } 675 return NULL; 676 } 677 678 static int 679 edd_create_symlink_to_pcidev(struct edd_device *edev) 680 { 681 682 struct pci_dev *pci_dev = edd_get_pci_dev(edev); 683 if (!pci_dev) 684 return 1; 685 return sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev"); 686 } 687 688 static inline void 689 edd_device_unregister(struct edd_device *edev) 690 { 691 kobject_unregister(&edev->kobj); 692 } 693 694 static void edd_populate_dir(struct edd_device * edev) 695 { 696 struct edd_attribute * attr; 697 int error = 0; 698 int i; 699 700 for (i = 0; (attr = edd_attrs[i]) && !error; i++) { 701 if (!attr->test || 702 (attr->test && attr->test(edev))) 703 error = sysfs_create_file(&edev->kobj,&attr->attr); 704 } 705 706 if (!error) { 707 edd_create_symlink_to_pcidev(edev); 708 } 709 } 710 711 static int 712 edd_device_register(struct edd_device *edev, int i) 713 { 714 int error; 715 716 if (!edev) 717 return 1; 718 edd_dev_set_info(edev, i); 719 kobject_set_name(&edev->kobj, "int13_dev%02x", 720 0x80 + i); 721 kobj_set_kset_s(edev,edd_subsys); 722 error = kobject_register(&edev->kobj); 723 if (!error) 724 edd_populate_dir(edev); 725 return error; 726 } 727 728 static inline int edd_num_devices(void) 729 { 730 return max_t(unsigned char, 731 min_t(unsigned char, EDD_MBR_SIG_MAX, edd.mbr_signature_nr), 732 min_t(unsigned char, EDDMAXNR, edd.edd_info_nr)); 733 } 734 735 /** 736 * edd_init() - creates sysfs tree of EDD data 737 */ 738 static int __init 739 edd_init(void) 740 { 741 unsigned int i; 742 int rc=0; 743 struct edd_device *edev; 744 745 printk(KERN_INFO "BIOS EDD facility v%s %s, %d devices found\n", 746 EDD_VERSION, EDD_DATE, edd_num_devices()); 747 748 if (!edd_num_devices()) { 749 printk(KERN_INFO "EDD information not available.\n"); 750 return 1; 751 } 752 753 rc = firmware_register(&edd_subsys); 754 if (rc) 755 return rc; 756 757 for (i = 0; i < edd_num_devices() && !rc; i++) { 758 edev = kzalloc(sizeof (*edev), GFP_KERNEL); 759 if (!edev) 760 return -ENOMEM; 761 762 rc = edd_device_register(edev, i); 763 if (rc) { 764 kfree(edev); 765 break; 766 } 767 edd_devices[i] = edev; 768 } 769 770 if (rc) 771 firmware_unregister(&edd_subsys); 772 return rc; 773 } 774 775 static void __exit 776 edd_exit(void) 777 { 778 int i; 779 struct edd_device *edev; 780 781 for (i = 0; i < edd_num_devices(); i++) { 782 if ((edev = edd_devices[i])) 783 edd_device_unregister(edev); 784 } 785 firmware_unregister(&edd_subsys); 786 } 787 788 late_initcall(edd_init); 789 module_exit(edd_exit); 790