aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/ch.c120
1 files changed, 54 insertions, 66 deletions
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 2b07014cbc83..7aad15436d24 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -90,16 +90,6 @@ static const char * vendor_labels[CH_TYPES-4] = {
90 90
91#define MAX_RETRIES 1 91#define MAX_RETRIES 1
92 92
93static int ch_probe(struct device *);
94static int ch_remove(struct device *);
95static int ch_open(struct inode * inode, struct file * filp);
96static int ch_release(struct inode * inode, struct file * filp);
97static long ch_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
98#ifdef CONFIG_COMPAT
99static long ch_ioctl_compat(struct file * filp,
100 unsigned int cmd, unsigned long arg);
101#endif
102
103static struct class * ch_sysfs_class; 93static struct class * ch_sysfs_class;
104 94
105typedef struct { 95typedef struct {
@@ -118,27 +108,6 @@ typedef struct {
118static DEFINE_IDR(ch_index_idr); 108static DEFINE_IDR(ch_index_idr);
119static DEFINE_SPINLOCK(ch_index_lock); 109static DEFINE_SPINLOCK(ch_index_lock);
120 110
121static struct scsi_driver ch_template =
122{
123 .owner = THIS_MODULE,
124 .gendrv = {
125 .name = "ch",
126 .probe = ch_probe,
127 .remove = ch_remove,
128 },
129};
130
131static const struct file_operations changer_fops =
132{
133 .owner = THIS_MODULE,
134 .open = ch_open,
135 .release = ch_release,
136 .unlocked_ioctl = ch_ioctl,
137#ifdef CONFIG_COMPAT
138 .compat_ioctl = ch_ioctl_compat,
139#endif
140};
141
142static const struct { 111static const struct {
143 unsigned char sense; 112 unsigned char sense;
144 unsigned char asc; 113 unsigned char asc;
@@ -207,7 +176,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
207{ 176{
208 int errno, retries = 0, timeout, result; 177 int errno, retries = 0, timeout, result;
209 struct scsi_sense_hdr sshdr; 178 struct scsi_sense_hdr sshdr;
210 179
211 timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS) 180 timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS)
212 ? timeout_init : timeout_move; 181 ? timeout_init : timeout_move;
213 182
@@ -245,7 +214,7 @@ static int
245ch_elem_to_typecode(scsi_changer *ch, u_int elem) 214ch_elem_to_typecode(scsi_changer *ch, u_int elem)
246{ 215{
247 int i; 216 int i;
248 217
249 for (i = 0; i < CH_TYPES; i++) { 218 for (i = 0; i < CH_TYPES; i++) {
250 if (elem >= ch->firsts[i] && 219 if (elem >= ch->firsts[i] &&
251 elem < ch->firsts[i] + 220 elem < ch->firsts[i] +
@@ -261,15 +230,15 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data)
261 u_char cmd[12]; 230 u_char cmd[12];
262 u_char *buffer; 231 u_char *buffer;
263 int result; 232 int result;
264 233
265 buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); 234 buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
266 if(!buffer) 235 if(!buffer)
267 return -ENOMEM; 236 return -ENOMEM;
268 237
269 retry: 238 retry:
270 memset(cmd,0,sizeof(cmd)); 239 memset(cmd,0,sizeof(cmd));
271 cmd[0] = READ_ELEMENT_STATUS; 240 cmd[0] = READ_ELEMENT_STATUS;
272 cmd[1] = (ch->device->lun << 5) | 241 cmd[1] = (ch->device->lun << 5) |
273 (ch->voltags ? 0x10 : 0) | 242 (ch->voltags ? 0x10 : 0) |
274 ch_elem_to_typecode(ch,elem); 243 ch_elem_to_typecode(ch,elem);
275 cmd[2] = (elem >> 8) & 0xff; 244 cmd[2] = (elem >> 8) & 0xff;
@@ -296,7 +265,7 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data)
296 return result; 265 return result;
297} 266}
298 267
299static int 268static int
300ch_init_elem(scsi_changer *ch) 269ch_init_elem(scsi_changer *ch)
301{ 270{
302 int err; 271 int err;
@@ -322,7 +291,7 @@ ch_readconfig(scsi_changer *ch)
322 buffer = kzalloc(512, GFP_KERNEL | GFP_DMA); 291 buffer = kzalloc(512, GFP_KERNEL | GFP_DMA);
323 if (!buffer) 292 if (!buffer)
324 return -ENOMEM; 293 return -ENOMEM;
325 294
326 memset(cmd,0,sizeof(cmd)); 295 memset(cmd,0,sizeof(cmd));
327 cmd[0] = MODE_SENSE; 296 cmd[0] = MODE_SENSE;
328 cmd[1] = ch->device->lun << 5; 297 cmd[1] = ch->device->lun << 5;
@@ -365,7 +334,7 @@ ch_readconfig(scsi_changer *ch)
365 } else { 334 } else {
366 vprintk("reading element address assigment page failed!\n"); 335 vprintk("reading element address assigment page failed!\n");
367 } 336 }
368 337
369 /* vendor specific element types */ 338 /* vendor specific element types */
370 for (i = 0; i < 4; i++) { 339 for (i = 0; i < 4; i++) {
371 if (0 == vendor_counts[i]) 340 if (0 == vendor_counts[i])
@@ -443,7 +412,7 @@ static int
443ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate) 412ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate)
444{ 413{
445 u_char cmd[10]; 414 u_char cmd[10];
446 415
447 dprintk("position: 0x%x\n",elem); 416 dprintk("position: 0x%x\n",elem);
448 if (0 == trans) 417 if (0 == trans)
449 trans = ch->firsts[CHET_MT]; 418 trans = ch->firsts[CHET_MT];
@@ -462,7 +431,7 @@ static int
462ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate) 431ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate)
463{ 432{
464 u_char cmd[12]; 433 u_char cmd[12];
465 434
466 dprintk("move: 0x%x => 0x%x\n",src,dest); 435 dprintk("move: 0x%x => 0x%x\n",src,dest);
467 if (0 == trans) 436 if (0 == trans)
468 trans = ch->firsts[CHET_MT]; 437 trans = ch->firsts[CHET_MT];
@@ -484,7 +453,7 @@ ch_exchange(scsi_changer *ch, u_int trans, u_int src,
484 u_int dest1, u_int dest2, int rotate1, int rotate2) 453 u_int dest1, u_int dest2, int rotate1, int rotate2)
485{ 454{
486 u_char cmd[12]; 455 u_char cmd[12];
487 456
488 dprintk("exchange: 0x%x => 0x%x => 0x%x\n", 457 dprintk("exchange: 0x%x => 0x%x => 0x%x\n",
489 src,dest1,dest2); 458 src,dest1,dest2);
490 if (0 == trans) 459 if (0 == trans)
@@ -501,7 +470,7 @@ ch_exchange(scsi_changer *ch, u_int trans, u_int src,
501 cmd[8] = (dest2 >> 8) & 0xff; 470 cmd[8] = (dest2 >> 8) & 0xff;
502 cmd[9] = dest2 & 0xff; 471 cmd[9] = dest2 & 0xff;
503 cmd[10] = (rotate1 ? 1 : 0) | (rotate2 ? 2 : 0); 472 cmd[10] = (rotate1 ? 1 : 0) | (rotate2 ? 2 : 0);
504 473
505 return ch_do_scsi(ch, cmd, NULL,0, DMA_NONE); 474 return ch_do_scsi(ch, cmd, NULL,0, DMA_NONE);
506} 475}
507 476
@@ -539,14 +508,14 @@ ch_set_voltag(scsi_changer *ch, u_int elem,
539 elem, tag); 508 elem, tag);
540 memset(cmd,0,sizeof(cmd)); 509 memset(cmd,0,sizeof(cmd));
541 cmd[0] = SEND_VOLUME_TAG; 510 cmd[0] = SEND_VOLUME_TAG;
542 cmd[1] = (ch->device->lun << 5) | 511 cmd[1] = (ch->device->lun << 5) |
543 ch_elem_to_typecode(ch,elem); 512 ch_elem_to_typecode(ch,elem);
544 cmd[2] = (elem >> 8) & 0xff; 513 cmd[2] = (elem >> 8) & 0xff;
545 cmd[3] = elem & 0xff; 514 cmd[3] = elem & 0xff;
546 cmd[5] = clear 515 cmd[5] = clear
547 ? (alternate ? 0x0d : 0x0c) 516 ? (alternate ? 0x0d : 0x0c)
548 : (alternate ? 0x0b : 0x0a); 517 : (alternate ? 0x0b : 0x0a);
549 518
550 cmd[9] = 255; 519 cmd[9] = 255;
551 520
552 memcpy(buffer,tag,32); 521 memcpy(buffer,tag,32);
@@ -562,7 +531,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
562 int retval = 0; 531 int retval = 0;
563 u_char data[16]; 532 u_char data[16];
564 unsigned int i; 533 unsigned int i;
565 534
566 mutex_lock(&ch->lock); 535 mutex_lock(&ch->lock);
567 for (i = 0; i < ch->counts[type]; i++) { 536 for (i = 0; i < ch->counts[type]; i++) {
568 if (0 != ch_read_element_status 537 if (0 != ch_read_element_status
@@ -629,18 +598,18 @@ static long ch_ioctl(struct file *file,
629 scsi_changer *ch = file->private_data; 598 scsi_changer *ch = file->private_data;
630 int retval; 599 int retval;
631 void __user *argp = (void __user *)arg; 600 void __user *argp = (void __user *)arg;
632 601
633 switch (cmd) { 602 switch (cmd) {
634 case CHIOGPARAMS: 603 case CHIOGPARAMS:
635 { 604 {
636 struct changer_params params; 605 struct changer_params params;
637 606
638 params.cp_curpicker = 0; 607 params.cp_curpicker = 0;
639 params.cp_npickers = ch->counts[CHET_MT]; 608 params.cp_npickers = ch->counts[CHET_MT];
640 params.cp_nslots = ch->counts[CHET_ST]; 609 params.cp_nslots = ch->counts[CHET_ST];
641 params.cp_nportals = ch->counts[CHET_IE]; 610 params.cp_nportals = ch->counts[CHET_IE];
642 params.cp_ndrives = ch->counts[CHET_DT]; 611 params.cp_ndrives = ch->counts[CHET_DT];
643 612
644 if (copy_to_user(argp, &params, sizeof(params))) 613 if (copy_to_user(argp, &params, sizeof(params)))
645 return -EFAULT; 614 return -EFAULT;
646 return 0; 615 return 0;
@@ -670,11 +639,11 @@ static long ch_ioctl(struct file *file,
670 return -EFAULT; 639 return -EFAULT;
671 return 0; 640 return 0;
672 } 641 }
673 642
674 case CHIOPOSITION: 643 case CHIOPOSITION:
675 { 644 {
676 struct changer_position pos; 645 struct changer_position pos;
677 646
678 if (copy_from_user(&pos, argp, sizeof (pos))) 647 if (copy_from_user(&pos, argp, sizeof (pos)))
679 return -EFAULT; 648 return -EFAULT;
680 649
@@ -689,7 +658,7 @@ static long ch_ioctl(struct file *file,
689 mutex_unlock(&ch->lock); 658 mutex_unlock(&ch->lock);
690 return retval; 659 return retval;
691 } 660 }
692 661
693 case CHIOMOVE: 662 case CHIOMOVE:
694 { 663 {
695 struct changer_move mv; 664 struct changer_move mv;
@@ -702,7 +671,7 @@ static long ch_ioctl(struct file *file,
702 dprintk("CHIOMOVE: invalid parameter\n"); 671 dprintk("CHIOMOVE: invalid parameter\n");
703 return -EBADSLT; 672 return -EBADSLT;
704 } 673 }
705 674
706 mutex_lock(&ch->lock); 675 mutex_lock(&ch->lock);
707 retval = ch_move(ch,0, 676 retval = ch_move(ch,0,
708 ch->firsts[mv.cm_fromtype] + mv.cm_fromunit, 677 ch->firsts[mv.cm_fromtype] + mv.cm_fromunit,
@@ -715,7 +684,7 @@ static long ch_ioctl(struct file *file,
715 case CHIOEXCHANGE: 684 case CHIOEXCHANGE:
716 { 685 {
717 struct changer_exchange mv; 686 struct changer_exchange mv;
718 687
719 if (copy_from_user(&mv, argp, sizeof (mv))) 688 if (copy_from_user(&mv, argp, sizeof (mv)))
720 return -EFAULT; 689 return -EFAULT;
721 690
@@ -725,7 +694,7 @@ static long ch_ioctl(struct file *file,
725 dprintk("CHIOEXCHANGE: invalid parameter\n"); 694 dprintk("CHIOEXCHANGE: invalid parameter\n");
726 return -EBADSLT; 695 return -EBADSLT;
727 } 696 }
728 697
729 mutex_lock(&ch->lock); 698 mutex_lock(&ch->lock);
730 retval = ch_exchange 699 retval = ch_exchange
731 (ch,0, 700 (ch,0,
@@ -740,7 +709,7 @@ static long ch_ioctl(struct file *file,
740 case CHIOGSTATUS: 709 case CHIOGSTATUS:
741 { 710 {
742 struct changer_element_status ces; 711 struct changer_element_status ces;
743 712
744 if (copy_from_user(&ces, argp, sizeof (ces))) 713 if (copy_from_user(&ces, argp, sizeof (ces)))
745 return -EFAULT; 714 return -EFAULT;
746 if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES) 715 if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES)
@@ -756,19 +725,19 @@ static long ch_ioctl(struct file *file,
756 u_char *buffer; 725 u_char *buffer;
757 unsigned int elem; 726 unsigned int elem;
758 int result,i; 727 int result,i;
759 728
760 if (copy_from_user(&cge, argp, sizeof (cge))) 729 if (copy_from_user(&cge, argp, sizeof (cge)))
761 return -EFAULT; 730 return -EFAULT;
762 731
763 if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit)) 732 if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit))
764 return -EINVAL; 733 return -EINVAL;
765 elem = ch->firsts[cge.cge_type] + cge.cge_unit; 734 elem = ch->firsts[cge.cge_type] + cge.cge_unit;
766 735
767 buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); 736 buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
768 if (!buffer) 737 if (!buffer)
769 return -ENOMEM; 738 return -ENOMEM;
770 mutex_lock(&ch->lock); 739 mutex_lock(&ch->lock);
771 740
772 voltag_retry: 741 voltag_retry:
773 memset(cmd,0,sizeof(cmd)); 742 memset(cmd,0,sizeof(cmd));
774 cmd[0] = READ_ELEMENT_STATUS; 743 cmd[0] = READ_ELEMENT_STATUS;
@@ -779,7 +748,7 @@ static long ch_ioctl(struct file *file,
779 cmd[3] = elem & 0xff; 748 cmd[3] = elem & 0xff;
780 cmd[5] = 1; 749 cmd[5] = 1;
781 cmd[9] = 255; 750 cmd[9] = 255;
782 751
783 if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) { 752 if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) {
784 cge.cge_status = buffer[18]; 753 cge.cge_status = buffer[18];
785 cge.cge_flags = 0; 754 cge.cge_flags = 0;
@@ -819,7 +788,7 @@ static long ch_ioctl(struct file *file,
819 } 788 }
820 kfree(buffer); 789 kfree(buffer);
821 mutex_unlock(&ch->lock); 790 mutex_unlock(&ch->lock);
822 791
823 if (copy_to_user(argp, &cge, sizeof (cge))) 792 if (copy_to_user(argp, &cge, sizeof (cge)))
824 return -EFAULT; 793 return -EFAULT;
825 return result; 794 return result;
@@ -832,7 +801,7 @@ static long ch_ioctl(struct file *file,
832 mutex_unlock(&ch->lock); 801 mutex_unlock(&ch->lock);
833 return retval; 802 return retval;
834 } 803 }
835 804
836 case CHIOSVOLTAG: 805 case CHIOSVOLTAG:
837 { 806 {
838 struct changer_set_voltag csv; 807 struct changer_set_voltag csv;
@@ -873,7 +842,7 @@ static long ch_ioctl_compat(struct file * file,
873 unsigned int cmd, unsigned long arg) 842 unsigned int cmd, unsigned long arg)
874{ 843{
875 scsi_changer *ch = file->private_data; 844 scsi_changer *ch = file->private_data;
876 845
877 switch (cmd) { 846 switch (cmd) {
878 case CHIOGPARAMS: 847 case CHIOGPARAMS:
879 case CHIOGVPARAMS: 848 case CHIOGVPARAMS:
@@ -889,7 +858,7 @@ static long ch_ioctl_compat(struct file * file,
889 { 858 {
890 struct changer_element_status32 ces32; 859 struct changer_element_status32 ces32;
891 unsigned char __user *data; 860 unsigned char __user *data;
892 861
893 if (copy_from_user(&ces32, (void __user *)arg, sizeof (ces32))) 862 if (copy_from_user(&ces32, (void __user *)arg, sizeof (ces32)))
894 return -EFAULT; 863 return -EFAULT;
895 if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES) 864 if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
@@ -982,10 +951,29 @@ static int ch_remove(struct device *dev)
982 return 0; 951 return 0;
983} 952}
984 953
954static struct scsi_driver ch_template = {
955 .owner = THIS_MODULE,
956 .gendrv = {
957 .name = "ch",
958 .probe = ch_probe,
959 .remove = ch_remove,
960 },
961};
962
963static const struct file_operations changer_fops = {
964 .owner = THIS_MODULE,
965 .open = ch_open,
966 .release = ch_release,
967 .unlocked_ioctl = ch_ioctl,
968#ifdef CONFIG_COMPAT
969 .compat_ioctl = ch_ioctl_compat,
970#endif
971};
972
985static int __init init_ch_module(void) 973static int __init init_ch_module(void)
986{ 974{
987 int rc; 975 int rc;
988 976
989 printk(KERN_INFO "SCSI Media Changer driver v" VERSION " \n"); 977 printk(KERN_INFO "SCSI Media Changer driver v" VERSION " \n");
990 ch_sysfs_class = class_create(THIS_MODULE, "scsi_changer"); 978 ch_sysfs_class = class_create(THIS_MODULE, "scsi_changer");
991 if (IS_ERR(ch_sysfs_class)) { 979 if (IS_ERR(ch_sysfs_class)) {
@@ -1010,7 +998,7 @@ static int __init init_ch_module(void)
1010 return rc; 998 return rc;
1011} 999}
1012 1000
1013static void __exit exit_ch_module(void) 1001static void __exit exit_ch_module(void)
1014{ 1002{
1015 scsi_unregister_driver(&ch_template.gendrv); 1003 scsi_unregister_driver(&ch_template.gendrv);
1016 unregister_chrdev(SCSI_CHANGER_MAJOR, "ch"); 1004 unregister_chrdev(SCSI_CHANGER_MAJOR, "ch");