1 /* 2 * SCSI Enclosure Services 3 * 4 * Copyright (C) 2008 James Bottomley <James.Bottomley@HansenPartnership.com> 5 * 6 **----------------------------------------------------------------------------- 7 ** 8 ** This program is free software; you can redistribute it and/or 9 ** modify it under the terms of the GNU General Public License 10 ** version 2 as published by the Free Software Foundation. 11 ** 12 ** This program is distributed in the hope that it will be useful, 13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 ** GNU General Public License for more details. 16 ** 17 ** You should have received a copy of the GNU General Public License 18 ** along with this program; if not, write to the Free Software 19 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 ** 21 **----------------------------------------------------------------------------- 22 */ 23 24 #include <linux/slab.h> 25 #include <linux/module.h> 26 #include <linux/kernel.h> 27 #include <linux/enclosure.h> 28 29 #include <scsi/scsi.h> 30 #include <scsi/scsi_cmnd.h> 31 #include <scsi/scsi_dbg.h> 32 #include <scsi/scsi_device.h> 33 #include <scsi/scsi_driver.h> 34 #include <scsi/scsi_host.h> 35 36 struct ses_device { 37 unsigned char *page1; 38 unsigned char *page2; 39 unsigned char *page10; 40 short page1_len; 41 short page2_len; 42 short page10_len; 43 }; 44 45 struct ses_component { 46 u64 addr; 47 unsigned char *desc; 48 }; 49 50 static int ses_probe(struct device *dev) 51 { 52 struct scsi_device *sdev = to_scsi_device(dev); 53 int err = -ENODEV; 54 55 if (sdev->type != TYPE_ENCLOSURE) 56 goto out; 57 58 err = 0; 59 sdev_printk(KERN_NOTICE, sdev, "Attached Enclosure device\n"); 60 61 out: 62 return err; 63 } 64 65 #define SES_TIMEOUT (30 * HZ) 66 #define SES_RETRIES 3 67 68 static int ses_recv_diag(struct scsi_device *sdev, int page_code, 69 void *buf, int bufflen) 70 { 71 unsigned char cmd[] = { 72 RECEIVE_DIAGNOSTIC, 73 1, /* Set PCV bit */ 74 page_code, 75 bufflen >> 8, 76 bufflen & 0xff, 77 0 78 }; 79 80 return scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen, 81 NULL, SES_TIMEOUT, SES_RETRIES, NULL); 82 } 83 84 static int ses_send_diag(struct scsi_device *sdev, int page_code, 85 void *buf, int bufflen) 86 { 87 u32 result; 88 89 unsigned char cmd[] = { 90 SEND_DIAGNOSTIC, 91 0x10, /* Set PF bit */ 92 0, 93 bufflen >> 8, 94 bufflen & 0xff, 95 0 96 }; 97 98 result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, buf, bufflen, 99 NULL, SES_TIMEOUT, SES_RETRIES, NULL); 100 if (result) 101 sdev_printk(KERN_ERR, sdev, "SEND DIAGNOSTIC result: %8x\n", 102 result); 103 return result; 104 } 105 106 static int ses_set_page2_descriptor(struct enclosure_device *edev, 107 struct enclosure_component *ecomp, 108 unsigned char *desc) 109 { 110 int i, j, count = 0, descriptor = ecomp->number; 111 struct scsi_device *sdev = to_scsi_device(edev->edev.parent); 112 struct ses_device *ses_dev = edev->scratch; 113 unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11]; 114 unsigned char *desc_ptr = ses_dev->page2 + 8; 115 116 /* Clear everything */ 117 memset(desc_ptr, 0, ses_dev->page2_len - 8); 118 for (i = 0; i < ses_dev->page1[10]; i++, type_ptr += 4) { 119 for (j = 0; j < type_ptr[1]; j++) { 120 desc_ptr += 4; 121 if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE && 122 type_ptr[0] != ENCLOSURE_COMPONENT_ARRAY_DEVICE) 123 continue; 124 if (count++ == descriptor) { 125 memcpy(desc_ptr, desc, 4); 126 /* set select */ 127 desc_ptr[0] |= 0x80; 128 /* clear reserved, just in case */ 129 desc_ptr[0] &= 0xf0; 130 } 131 } 132 } 133 134 return ses_send_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len); 135 } 136 137 static unsigned char *ses_get_page2_descriptor(struct enclosure_device *edev, 138 struct enclosure_component *ecomp) 139 { 140 int i, j, count = 0, descriptor = ecomp->number; 141 struct scsi_device *sdev = to_scsi_device(edev->edev.parent); 142 struct ses_device *ses_dev = edev->scratch; 143 unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11]; 144 unsigned char *desc_ptr = ses_dev->page2 + 8; 145 146 ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len); 147 148 for (i = 0; i < ses_dev->page1[10]; i++, type_ptr += 4) { 149 for (j = 0; j < type_ptr[1]; j++) { 150 desc_ptr += 4; 151 if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE && 152 type_ptr[0] != ENCLOSURE_COMPONENT_ARRAY_DEVICE) 153 continue; 154 if (count++ == descriptor) 155 return desc_ptr; 156 } 157 } 158 return NULL; 159 } 160 161 static void ses_get_fault(struct enclosure_device *edev, 162 struct enclosure_component *ecomp) 163 { 164 unsigned char *desc; 165 166 desc = ses_get_page2_descriptor(edev, ecomp); 167 if (desc) 168 ecomp->fault = (desc[3] & 0x60) >> 4; 169 } 170 171 static int ses_set_fault(struct enclosure_device *edev, 172 struct enclosure_component *ecomp, 173 enum enclosure_component_setting val) 174 { 175 unsigned char desc[4] = {0 }; 176 177 switch (val) { 178 case ENCLOSURE_SETTING_DISABLED: 179 /* zero is disabled */ 180 break; 181 case ENCLOSURE_SETTING_ENABLED: 182 desc[2] = 0x02; 183 break; 184 default: 185 /* SES doesn't do the SGPIO blink settings */ 186 return -EINVAL; 187 } 188 189 return ses_set_page2_descriptor(edev, ecomp, desc); 190 } 191 192 static void ses_get_status(struct enclosure_device *edev, 193 struct enclosure_component *ecomp) 194 { 195 unsigned char *desc; 196 197 desc = ses_get_page2_descriptor(edev, ecomp); 198 if (desc) 199 ecomp->status = (desc[0] & 0x0f); 200 } 201 202 static void ses_get_locate(struct enclosure_device *edev, 203 struct enclosure_component *ecomp) 204 { 205 unsigned char *desc; 206 207 desc = ses_get_page2_descriptor(edev, ecomp); 208 if (desc) 209 ecomp->locate = (desc[2] & 0x02) ? 1 : 0; 210 } 211 212 static int ses_set_locate(struct enclosure_device *edev, 213 struct enclosure_component *ecomp, 214 enum enclosure_component_setting val) 215 { 216 unsigned char desc[4] = {0 }; 217 218 switch (val) { 219 case ENCLOSURE_SETTING_DISABLED: 220 /* zero is disabled */ 221 break; 222 case ENCLOSURE_SETTING_ENABLED: 223 desc[2] = 0x02; 224 break; 225 default: 226 /* SES doesn't do the SGPIO blink settings */ 227 return -EINVAL; 228 } 229 return ses_set_page2_descriptor(edev, ecomp, desc); 230 } 231 232 static int ses_set_active(struct enclosure_device *edev, 233 struct enclosure_component *ecomp, 234 enum enclosure_component_setting val) 235 { 236 unsigned char desc[4] = {0 }; 237 238 switch (val) { 239 case ENCLOSURE_SETTING_DISABLED: 240 /* zero is disabled */ 241 ecomp->active = 0; 242 break; 243 case ENCLOSURE_SETTING_ENABLED: 244 desc[2] = 0x80; 245 ecomp->active = 1; 246 break; 247 default: 248 /* SES doesn't do the SGPIO blink settings */ 249 return -EINVAL; 250 } 251 return ses_set_page2_descriptor(edev, ecomp, desc); 252 } 253 254 static struct enclosure_component_callbacks ses_enclosure_callbacks = { 255 .get_fault = ses_get_fault, 256 .set_fault = ses_set_fault, 257 .get_status = ses_get_status, 258 .get_locate = ses_get_locate, 259 .set_locate = ses_set_locate, 260 .set_active = ses_set_active, 261 }; 262 263 struct ses_host_edev { 264 struct Scsi_Host *shost; 265 struct enclosure_device *edev; 266 }; 267 268 #if 0 269 int ses_match_host(struct enclosure_device *edev, void *data) 270 { 271 struct ses_host_edev *sed = data; 272 struct scsi_device *sdev; 273 274 if (!scsi_is_sdev_device(edev->edev.parent)) 275 return 0; 276 277 sdev = to_scsi_device(edev->edev.parent); 278 279 if (sdev->host != sed->shost) 280 return 0; 281 282 sed->edev = edev; 283 return 1; 284 } 285 #endif /* 0 */ 286 287 static void ses_process_descriptor(struct enclosure_component *ecomp, 288 unsigned char *desc) 289 { 290 int eip = desc[0] & 0x10; 291 int invalid = desc[0] & 0x80; 292 enum scsi_protocol proto = desc[0] & 0x0f; 293 u64 addr = 0; 294 struct ses_component *scomp = ecomp->scratch; 295 unsigned char *d; 296 297 scomp->desc = desc; 298 299 if (invalid) 300 return; 301 302 switch (proto) { 303 case SCSI_PROTOCOL_SAS: 304 if (eip) 305 d = desc + 8; 306 else 307 d = desc + 4; 308 /* only take the phy0 addr */ 309 addr = (u64)d[12] << 56 | 310 (u64)d[13] << 48 | 311 (u64)d[14] << 40 | 312 (u64)d[15] << 32 | 313 (u64)d[16] << 24 | 314 (u64)d[17] << 16 | 315 (u64)d[18] << 8 | 316 (u64)d[19]; 317 break; 318 default: 319 /* FIXME: Need to add more protocols than just SAS */ 320 break; 321 } 322 scomp->addr = addr; 323 } 324 325 struct efd { 326 u64 addr; 327 struct device *dev; 328 }; 329 330 static int ses_enclosure_find_by_addr(struct enclosure_device *edev, 331 void *data) 332 { 333 struct efd *efd = data; 334 int i; 335 struct ses_component *scomp; 336 337 if (!edev->component[0].scratch) 338 return 0; 339 340 for (i = 0; i < edev->components; i++) { 341 scomp = edev->component[i].scratch; 342 if (scomp->addr != efd->addr) 343 continue; 344 345 enclosure_add_device(edev, i, efd->dev); 346 return 1; 347 } 348 return 0; 349 } 350 351 #define INIT_ALLOC_SIZE 32 352 353 static void ses_enclosure_data_process(struct enclosure_device *edev, 354 struct scsi_device *sdev, 355 int create) 356 { 357 u32 result; 358 unsigned char *buf = NULL, *type_ptr, *desc_ptr, *addl_desc_ptr = NULL; 359 int i, j, page7_len, len, components; 360 struct ses_device *ses_dev = edev->scratch; 361 int types = ses_dev->page1[10]; 362 unsigned char *hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL); 363 364 if (!hdr_buf) 365 goto simple_populate; 366 367 /* re-read page 10 */ 368 if (ses_dev->page10) 369 ses_recv_diag(sdev, 10, ses_dev->page10, ses_dev->page10_len); 370 /* Page 7 for the descriptors is optional */ 371 result = ses_recv_diag(sdev, 7, hdr_buf, INIT_ALLOC_SIZE); 372 if (result) 373 goto simple_populate; 374 375 page7_len = len = (hdr_buf[2] << 8) + hdr_buf[3] + 4; 376 /* add 1 for trailing '\0' we'll use */ 377 buf = kzalloc(len + 1, GFP_KERNEL); 378 if (!buf) 379 goto simple_populate; 380 result = ses_recv_diag(sdev, 7, buf, len); 381 if (result) { 382 simple_populate: 383 kfree(buf); 384 buf = NULL; 385 desc_ptr = NULL; 386 len = 0; 387 page7_len = 0; 388 } else { 389 desc_ptr = buf + 8; 390 len = (desc_ptr[2] << 8) + desc_ptr[3]; 391 /* skip past overall descriptor */ 392 desc_ptr += len + 4; 393 if (ses_dev->page10) 394 addl_desc_ptr = ses_dev->page10 + 8; 395 } 396 type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11]; 397 components = 0; 398 for (i = 0; i < types; i++, type_ptr += 4) { 399 for (j = 0; j < type_ptr[1]; j++) { 400 char *name = NULL; 401 struct enclosure_component *ecomp; 402 403 if (desc_ptr) { 404 if (desc_ptr >= buf + page7_len) { 405 desc_ptr = NULL; 406 } else { 407 len = (desc_ptr[2] << 8) + desc_ptr[3]; 408 desc_ptr += 4; 409 /* Add trailing zero - pushes into 410 * reserved space */ 411 desc_ptr[len] = '\0'; 412 name = desc_ptr; 413 } 414 } 415 if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE || 416 type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) { 417 418 if (create) 419 ecomp = enclosure_component_register(edev, 420 components++, 421 type_ptr[0], 422 name); 423 else 424 ecomp = &edev->component[components++]; 425 426 if (!IS_ERR(ecomp) && addl_desc_ptr) 427 ses_process_descriptor(ecomp, 428 addl_desc_ptr); 429 } 430 if (desc_ptr) 431 desc_ptr += len; 432 433 if (addl_desc_ptr) 434 addl_desc_ptr += addl_desc_ptr[1] + 2; 435 436 } 437 } 438 kfree(buf); 439 kfree(hdr_buf); 440 } 441 442 static void ses_match_to_enclosure(struct enclosure_device *edev, 443 struct scsi_device *sdev) 444 { 445 unsigned char *buf; 446 unsigned char *desc; 447 unsigned int vpd_len; 448 struct efd efd = { 449 .addr = 0, 450 }; 451 452 buf = kmalloc(INIT_ALLOC_SIZE, GFP_KERNEL); 453 if (!buf || scsi_get_vpd_page(sdev, 0x83, buf, INIT_ALLOC_SIZE)) 454 goto free; 455 456 ses_enclosure_data_process(edev, to_scsi_device(edev->edev.parent), 0); 457 458 vpd_len = ((buf[2] << 8) | buf[3]) + 4; 459 kfree(buf); 460 buf = kmalloc(vpd_len, GFP_KERNEL); 461 if (!buf ||scsi_get_vpd_page(sdev, 0x83, buf, vpd_len)) 462 goto free; 463 464 desc = buf + 4; 465 while (desc < buf + vpd_len) { 466 enum scsi_protocol proto = desc[0] >> 4; 467 u8 code_set = desc[0] & 0x0f; 468 u8 piv = desc[1] & 0x80; 469 u8 assoc = (desc[1] & 0x30) >> 4; 470 u8 type = desc[1] & 0x0f; 471 u8 len = desc[3]; 472 473 if (piv && code_set == 1 && assoc == 1 474 && proto == SCSI_PROTOCOL_SAS && type == 3 && len == 8) 475 efd.addr = (u64)desc[4] << 56 | 476 (u64)desc[5] << 48 | 477 (u64)desc[6] << 40 | 478 (u64)desc[7] << 32 | 479 (u64)desc[8] << 24 | 480 (u64)desc[9] << 16 | 481 (u64)desc[10] << 8 | 482 (u64)desc[11]; 483 484 desc += len + 4; 485 } 486 if (!efd.addr) 487 goto free; 488 489 efd.dev = &sdev->sdev_gendev; 490 491 enclosure_for_each_device(ses_enclosure_find_by_addr, &efd); 492 free: 493 kfree(buf); 494 } 495 496 static int ses_intf_add(struct device *cdev, 497 struct class_interface *intf) 498 { 499 struct scsi_device *sdev = to_scsi_device(cdev->parent); 500 struct scsi_device *tmp_sdev; 501 unsigned char *buf = NULL, *hdr_buf, *type_ptr; 502 struct ses_device *ses_dev; 503 u32 result; 504 int i, types, len, components = 0; 505 int err = -ENOMEM; 506 struct enclosure_device *edev; 507 struct ses_component *scomp = NULL; 508 509 if (!scsi_device_enclosure(sdev)) { 510 /* not an enclosure, but might be in one */ 511 struct enclosure_device *prev = NULL; 512 513 while ((edev = enclosure_find(&sdev->host->shost_gendev, prev)) != NULL) { 514 ses_match_to_enclosure(edev, sdev); 515 prev = edev; 516 } 517 return -ENODEV; 518 } 519 520 /* TYPE_ENCLOSURE prints a message in probe */ 521 if (sdev->type != TYPE_ENCLOSURE) 522 sdev_printk(KERN_NOTICE, sdev, "Embedded Enclosure Device\n"); 523 524 ses_dev = kzalloc(sizeof(*ses_dev), GFP_KERNEL); 525 hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL); 526 if (!hdr_buf || !ses_dev) 527 goto err_init_free; 528 529 result = ses_recv_diag(sdev, 1, hdr_buf, INIT_ALLOC_SIZE); 530 if (result) 531 goto recv_failed; 532 533 if (hdr_buf[1] != 0) { 534 /* FIXME: need subenclosure support; I've just never 535 * seen a device with subenclosures and it makes the 536 * traversal routines more complex */ 537 sdev_printk(KERN_ERR, sdev, 538 "FIXME driver has no support for subenclosures (%d)\n", 539 hdr_buf[1]); 540 goto err_free; 541 } 542 543 len = (hdr_buf[2] << 8) + hdr_buf[3] + 4; 544 buf = kzalloc(len, GFP_KERNEL); 545 if (!buf) 546 goto err_free; 547 548 result = ses_recv_diag(sdev, 1, buf, len); 549 if (result) 550 goto recv_failed; 551 552 types = buf[10]; 553 554 type_ptr = buf + 12 + buf[11]; 555 556 for (i = 0; i < types; i++, type_ptr += 4) { 557 if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE || 558 type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) 559 components += type_ptr[1]; 560 } 561 ses_dev->page1 = buf; 562 ses_dev->page1_len = len; 563 buf = NULL; 564 565 result = ses_recv_diag(sdev, 2, hdr_buf, INIT_ALLOC_SIZE); 566 if (result) 567 goto recv_failed; 568 569 len = (hdr_buf[2] << 8) + hdr_buf[3] + 4; 570 buf = kzalloc(len, GFP_KERNEL); 571 if (!buf) 572 goto err_free; 573 574 /* make sure getting page 2 actually works */ 575 result = ses_recv_diag(sdev, 2, buf, len); 576 if (result) 577 goto recv_failed; 578 ses_dev->page2 = buf; 579 ses_dev->page2_len = len; 580 buf = NULL; 581 582 /* The additional information page --- allows us 583 * to match up the devices */ 584 result = ses_recv_diag(sdev, 10, hdr_buf, INIT_ALLOC_SIZE); 585 if (!result) { 586 587 len = (hdr_buf[2] << 8) + hdr_buf[3] + 4; 588 buf = kzalloc(len, GFP_KERNEL); 589 if (!buf) 590 goto err_free; 591 592 result = ses_recv_diag(sdev, 10, buf, len); 593 if (result) 594 goto recv_failed; 595 ses_dev->page10 = buf; 596 ses_dev->page10_len = len; 597 buf = NULL; 598 } 599 scomp = kzalloc(sizeof(struct ses_component) * components, GFP_KERNEL); 600 if (!scomp) 601 goto err_free; 602 603 edev = enclosure_register(cdev->parent, dev_name(&sdev->sdev_gendev), 604 components, &ses_enclosure_callbacks); 605 if (IS_ERR(edev)) { 606 err = PTR_ERR(edev); 607 goto err_free; 608 } 609 610 kfree(hdr_buf); 611 612 edev->scratch = ses_dev; 613 for (i = 0; i < components; i++) 614 edev->component[i].scratch = scomp + i; 615 616 ses_enclosure_data_process(edev, sdev, 1); 617 618 /* see if there are any devices matching before 619 * we found the enclosure */ 620 shost_for_each_device(tmp_sdev, sdev->host) { 621 if (tmp_sdev->lun != 0 || scsi_device_enclosure(tmp_sdev)) 622 continue; 623 ses_match_to_enclosure(edev, tmp_sdev); 624 } 625 626 return 0; 627 628 recv_failed: 629 sdev_printk(KERN_ERR, sdev, "Failed to get diagnostic page 0x%x\n", 630 result); 631 err = -ENODEV; 632 err_free: 633 kfree(buf); 634 kfree(scomp); 635 kfree(ses_dev->page10); 636 kfree(ses_dev->page2); 637 kfree(ses_dev->page1); 638 err_init_free: 639 kfree(ses_dev); 640 kfree(hdr_buf); 641 sdev_printk(KERN_ERR, sdev, "Failed to bind enclosure %d\n", err); 642 return err; 643 } 644 645 static int ses_remove(struct device *dev) 646 { 647 return 0; 648 } 649 650 static void ses_intf_remove_component(struct scsi_device *sdev) 651 { 652 struct enclosure_device *edev, *prev = NULL; 653 654 while ((edev = enclosure_find(&sdev->host->shost_gendev, prev)) != NULL) { 655 prev = edev; 656 if (!enclosure_remove_device(edev, &sdev->sdev_gendev)) 657 break; 658 } 659 if (edev) 660 put_device(&edev->edev); 661 } 662 663 static void ses_intf_remove_enclosure(struct scsi_device *sdev) 664 { 665 struct enclosure_device *edev; 666 struct ses_device *ses_dev; 667 668 /* exact match to this enclosure */ 669 edev = enclosure_find(&sdev->sdev_gendev, NULL); 670 if (!edev) 671 return; 672 673 ses_dev = edev->scratch; 674 edev->scratch = NULL; 675 676 kfree(ses_dev->page10); 677 kfree(ses_dev->page1); 678 kfree(ses_dev->page2); 679 kfree(ses_dev); 680 681 kfree(edev->component[0].scratch); 682 683 put_device(&edev->edev); 684 enclosure_unregister(edev); 685 } 686 687 static void ses_intf_remove(struct device *cdev, 688 struct class_interface *intf) 689 { 690 struct scsi_device *sdev = to_scsi_device(cdev->parent); 691 692 if (!scsi_device_enclosure(sdev)) 693 ses_intf_remove_component(sdev); 694 else 695 ses_intf_remove_enclosure(sdev); 696 } 697 698 static struct class_interface ses_interface = { 699 .add_dev = ses_intf_add, 700 .remove_dev = ses_intf_remove, 701 }; 702 703 static struct scsi_driver ses_template = { 704 .owner = THIS_MODULE, 705 .gendrv = { 706 .name = "ses", 707 .probe = ses_probe, 708 .remove = ses_remove, 709 }, 710 }; 711 712 static int __init ses_init(void) 713 { 714 int err; 715 716 err = scsi_register_interface(&ses_interface); 717 if (err) 718 return err; 719 720 err = scsi_register_driver(&ses_template.gendrv); 721 if (err) 722 goto out_unreg; 723 724 return 0; 725 726 out_unreg: 727 scsi_unregister_interface(&ses_interface); 728 return err; 729 } 730 731 static void __exit ses_exit(void) 732 { 733 scsi_unregister_driver(&ses_template.gendrv); 734 scsi_unregister_interface(&ses_interface); 735 } 736 737 module_init(ses_init); 738 module_exit(ses_exit); 739 740 MODULE_ALIAS_SCSI_DEVICE(TYPE_ENCLOSURE); 741 742 MODULE_AUTHOR("James Bottomley"); 743 MODULE_DESCRIPTION("SCSI Enclosure Services (ses) driver"); 744 MODULE_LICENSE("GPL v2"); 745