Merge tag 'rust-fixes-6.9' of https://github.com/Rust-for-Linux/linux
[sfrench/cifs-2.6.git] / drivers / scsi / ch.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * SCSI Media Changer device driver for Linux 2.6
4  *
5  *     (c) 1996-2003 Gerd Knorr <kraxel@bytesex.org>
6  *
7  */
8
9 #define VERSION "0.25"
10
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/fs.h>
14 #include <linux/kernel.h>
15 #include <linux/mm.h>
16 #include <linux/major.h>
17 #include <linux/string.h>
18 #include <linux/errno.h>
19 #include <linux/interrupt.h>
20 #include <linux/blkdev.h>
21 #include <linux/completion.h>
22 #include <linux/compat.h>
23 #include <linux/chio.h>                 /* here are all the ioctls */
24 #include <linux/mutex.h>
25 #include <linux/idr.h>
26 #include <linux/slab.h>
27
28 #include <scsi/scsi.h>
29 #include <scsi/scsi_cmnd.h>
30 #include <scsi/scsi_driver.h>
31 #include <scsi/scsi_ioctl.h>
32 #include <scsi/scsi_host.h>
33 #include <scsi/scsi_device.h>
34 #include <scsi/scsi_eh.h>
35 #include <scsi/scsi_dbg.h>
36
37 #define CH_DT_MAX       16
38 #define CH_TYPES        8
39 #define CH_MAX_DEVS     128
40
41 MODULE_DESCRIPTION("device driver for scsi media changer devices");
42 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org>");
43 MODULE_LICENSE("GPL");
44 MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR);
45 MODULE_ALIAS_SCSI_DEVICE(TYPE_MEDIUM_CHANGER);
46
47 static int init = 1;
48 module_param(init, int, 0444);
49 MODULE_PARM_DESC(init, \
50     "initialize element status on driver load (default: on)");
51
52 static int timeout_move = 300;
53 module_param(timeout_move, int, 0644);
54 MODULE_PARM_DESC(timeout_move,"timeout for move commands "
55                  "(default: 300 seconds)");
56
57 static int timeout_init = 3600;
58 module_param(timeout_init, int, 0644);
59 MODULE_PARM_DESC(timeout_init,"timeout for INITIALIZE ELEMENT STATUS "
60                  "(default: 3600 seconds)");
61
62 static int verbose = 1;
63 module_param(verbose, int, 0644);
64 MODULE_PARM_DESC(verbose,"be verbose (default: on)");
65
66 static int debug;
67 module_param(debug, int, 0644);
68 MODULE_PARM_DESC(debug,"enable/disable debug messages, also prints more "
69                  "detailed sense codes on scsi errors (default: off)");
70
71 static int dt_id[CH_DT_MAX] = { [ 0 ... (CH_DT_MAX-1) ] = -1 };
72 static int dt_lun[CH_DT_MAX];
73 module_param_array(dt_id,  int, NULL, 0444);
74 module_param_array(dt_lun, int, NULL, 0444);
75
76 /* tell the driver about vendor-specific slots */
77 static int vendor_firsts[CH_TYPES-4];
78 static int vendor_counts[CH_TYPES-4];
79 module_param_array(vendor_firsts, int, NULL, 0444);
80 module_param_array(vendor_counts, int, NULL, 0444);
81
82 static const char * vendor_labels[CH_TYPES-4] = {
83         "v0", "v1", "v2", "v3"
84 };
85 // module_param_string_array(vendor_labels, NULL, 0444);
86
87 #define ch_printk(prefix, ch, fmt, a...) \
88         sdev_prefix_printk(prefix, (ch)->device, (ch)->name, fmt, ##a)
89
90 #define DPRINTK(fmt, arg...)                                            \
91 do {                                                                    \
92         if (debug)                                                      \
93                 ch_printk(KERN_DEBUG, ch, fmt, ##arg);                  \
94 } while (0)
95 #define VPRINTK(level, fmt, arg...)                                     \
96 do {                                                                    \
97         if (verbose)                                                    \
98                 ch_printk(level, ch, fmt, ##arg);                       \
99 } while (0)
100
101 /* ------------------------------------------------------------------- */
102
103 #define MAX_RETRIES   1
104
105 static const struct class ch_sysfs_class = {
106         .name = "scsi_changer",
107 };
108
109 typedef struct {
110         struct kref         ref;
111         struct list_head    list;
112         int                 minor;
113         char                name[8];
114         struct scsi_device  *device;
115         struct scsi_device  **dt;        /* ptrs to data transfer elements */
116         u_int               firsts[CH_TYPES];
117         u_int               counts[CH_TYPES];
118         u_int               voltags;
119         struct mutex        lock;
120 } scsi_changer;
121
122 static DEFINE_IDR(ch_index_idr);
123 static DEFINE_SPINLOCK(ch_index_lock);
124
125 static const struct {
126         unsigned char  sense;
127         unsigned char  asc;
128         unsigned char  ascq;
129         int            errno;
130 } ch_err[] = {
131 /* Just filled in what looks right. Hav'nt checked any standard paper for
132    these errno assignments, so they may be wrong... */
133         {
134                 .sense  = ILLEGAL_REQUEST,
135                 .asc    = 0x21,
136                 .ascq   = 0x01,
137                 .errno  = EBADSLT, /* Invalid element address */
138         },{
139                 .sense  = ILLEGAL_REQUEST,
140                 .asc    = 0x28,
141                 .ascq   = 0x01,
142                 .errno  = EBADE,   /* Import or export element accessed */
143         },{
144                 .sense  = ILLEGAL_REQUEST,
145                 .asc    = 0x3B,
146                 .ascq   = 0x0D,
147                 .errno  = EXFULL,  /* Medium destination element full */
148         },{
149                 .sense  = ILLEGAL_REQUEST,
150                 .asc    = 0x3B,
151                 .ascq   = 0x0E,
152                 .errno  = EBADE,   /* Medium source element empty */
153         },{
154                 .sense  = ILLEGAL_REQUEST,
155                 .asc    = 0x20,
156                 .ascq   = 0x00,
157                 .errno  = EBADRQC, /* Invalid command operation code */
158         },{
159                 /* end of list */
160         }
161 };
162
163 /* ------------------------------------------------------------------- */
164
165 static int ch_find_errno(struct scsi_sense_hdr *sshdr)
166 {
167         int i,errno = 0;
168
169         /* Check to see if additional sense information is available */
170         if (scsi_sense_valid(sshdr) &&
171             sshdr->asc != 0) {
172                 for (i = 0; ch_err[i].errno != 0; i++) {
173                         if (ch_err[i].sense == sshdr->sense_key &&
174                             ch_err[i].asc   == sshdr->asc &&
175                             ch_err[i].ascq  == sshdr->ascq) {
176                                 errno = -ch_err[i].errno;
177                                 break;
178                         }
179                 }
180         }
181         if (errno == 0)
182                 errno = -EIO;
183         return errno;
184 }
185
186 static int
187 ch_do_scsi(scsi_changer *ch, unsigned char *cmd, int cmd_len,
188            void *buffer, unsigned int buflength, enum req_op op)
189 {
190         int errno = 0, timeout, result;
191         struct scsi_sense_hdr sshdr;
192         struct scsi_failure failure_defs[] = {
193                 {
194                         .sense = UNIT_ATTENTION,
195                         .asc = SCMD_FAILURE_ASC_ANY,
196                         .ascq = SCMD_FAILURE_ASCQ_ANY,
197                         .allowed = 3,
198                         .result = SAM_STAT_CHECK_CONDITION,
199                 },
200                 {}
201         };
202         struct scsi_failures failures = {
203                 .failure_definitions = failure_defs,
204         };
205         const struct scsi_exec_args exec_args = {
206                 .sshdr = &sshdr,
207                 .failures = &failures,
208         };
209
210         timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS)
211                 ? timeout_init : timeout_move;
212
213         result = scsi_execute_cmd(ch->device, cmd, op, buffer, buflength,
214                                   timeout * HZ, MAX_RETRIES, &exec_args);
215         if (result < 0)
216                 return result;
217         if (scsi_sense_valid(&sshdr)) {
218                 if (debug)
219                         scsi_print_sense_hdr(ch->device, ch->name, &sshdr);
220                 errno = ch_find_errno(&sshdr);
221         }
222         return errno;
223 }
224
225 /* ------------------------------------------------------------------------ */
226
227 static int
228 ch_elem_to_typecode(scsi_changer *ch, u_int elem)
229 {
230         int i;
231
232         for (i = 0; i < CH_TYPES; i++) {
233                 if (elem >= ch->firsts[i]  &&
234                     elem <  ch->firsts[i] +
235                     ch->counts[i])
236                         return i+1;
237         }
238         return 0;
239 }
240
241 static int
242 ch_read_element_status(scsi_changer *ch, u_int elem, char *data)
243 {
244         u_char  cmd[12];
245         u_char  *buffer;
246         int     result;
247
248         buffer = kmalloc(512, GFP_KERNEL);
249         if(!buffer)
250                 return -ENOMEM;
251
252  retry:
253         memset(cmd,0,sizeof(cmd));
254         cmd[0] = READ_ELEMENT_STATUS;
255         cmd[1] = ((ch->device->lun & 0x7) << 5) |
256                 (ch->voltags ? 0x10 : 0) |
257                 ch_elem_to_typecode(ch,elem);
258         cmd[2] = (elem >> 8) & 0xff;
259         cmd[3] = elem        & 0xff;
260         cmd[5] = 1;
261         cmd[9] = 255;
262         if (0 == (result = ch_do_scsi(ch, cmd, 12,
263                                       buffer, 256, REQ_OP_DRV_IN))) {
264                 if (((buffer[16] << 8) | buffer[17]) != elem) {
265                         DPRINTK("asked for element 0x%02x, got 0x%02x\n",
266                                 elem,(buffer[16] << 8) | buffer[17]);
267                         kfree(buffer);
268                         return -EIO;
269                 }
270                 memcpy(data,buffer+16,16);
271         } else {
272                 if (ch->voltags) {
273                         ch->voltags = 0;
274                         VPRINTK(KERN_INFO, "device has no volume tag support\n");
275                         goto retry;
276                 }
277                 DPRINTK("READ ELEMENT STATUS for element 0x%x failed\n",elem);
278         }
279         kfree(buffer);
280         return result;
281 }
282
283 static int
284 ch_init_elem(scsi_changer *ch)
285 {
286         int err;
287         u_char cmd[6];
288
289         VPRINTK(KERN_INFO, "INITIALIZE ELEMENT STATUS, may take some time ...\n");
290         memset(cmd,0,sizeof(cmd));
291         cmd[0] = INITIALIZE_ELEMENT_STATUS;
292         cmd[1] = (ch->device->lun & 0x7) << 5;
293         err = ch_do_scsi(ch, cmd, 6, NULL, 0, REQ_OP_DRV_IN);
294         VPRINTK(KERN_INFO, "... finished\n");
295         return err;
296 }
297
298 static int
299 ch_readconfig(scsi_changer *ch)
300 {
301         u_char  cmd[10], data[16];
302         u_char  *buffer;
303         int     result,id,lun,i;
304         u_int   elem;
305
306         buffer = kzalloc(512, GFP_KERNEL);
307         if (!buffer)
308                 return -ENOMEM;
309
310         memset(cmd,0,sizeof(cmd));
311         cmd[0] = MODE_SENSE;
312         cmd[1] = (ch->device->lun & 0x7) << 5;
313         cmd[2] = 0x1d;
314         cmd[4] = 255;
315         result = ch_do_scsi(ch, cmd, 10, buffer, 255, REQ_OP_DRV_IN);
316         if (0 != result) {
317                 cmd[1] |= (1<<3);
318                 result  = ch_do_scsi(ch, cmd, 10, buffer, 255, REQ_OP_DRV_IN);
319         }
320         if (0 == result) {
321                 ch->firsts[CHET_MT] =
322                         (buffer[buffer[3]+ 6] << 8) | buffer[buffer[3]+ 7];
323                 ch->counts[CHET_MT] =
324                         (buffer[buffer[3]+ 8] << 8) | buffer[buffer[3]+ 9];
325                 ch->firsts[CHET_ST] =
326                         (buffer[buffer[3]+10] << 8) | buffer[buffer[3]+11];
327                 ch->counts[CHET_ST] =
328                         (buffer[buffer[3]+12] << 8) | buffer[buffer[3]+13];
329                 ch->firsts[CHET_IE] =
330                         (buffer[buffer[3]+14] << 8) | buffer[buffer[3]+15];
331                 ch->counts[CHET_IE] =
332                         (buffer[buffer[3]+16] << 8) | buffer[buffer[3]+17];
333                 ch->firsts[CHET_DT] =
334                         (buffer[buffer[3]+18] << 8) | buffer[buffer[3]+19];
335                 ch->counts[CHET_DT] =
336                         (buffer[buffer[3]+20] << 8) | buffer[buffer[3]+21];
337                 VPRINTK(KERN_INFO, "type #1 (mt): 0x%x+%d [medium transport]\n",
338                         ch->firsts[CHET_MT],
339                         ch->counts[CHET_MT]);
340                 VPRINTK(KERN_INFO, "type #2 (st): 0x%x+%d [storage]\n",
341                         ch->firsts[CHET_ST],
342                         ch->counts[CHET_ST]);
343                 VPRINTK(KERN_INFO, "type #3 (ie): 0x%x+%d [import/export]\n",
344                         ch->firsts[CHET_IE],
345                         ch->counts[CHET_IE]);
346                 VPRINTK(KERN_INFO, "type #4 (dt): 0x%x+%d [data transfer]\n",
347                         ch->firsts[CHET_DT],
348                         ch->counts[CHET_DT]);
349         } else {
350                 VPRINTK(KERN_INFO, "reading element address assignment page failed!\n");
351         }
352
353         /* vendor specific element types */
354         for (i = 0; i < 4; i++) {
355                 if (0 == vendor_counts[i])
356                         continue;
357                 if (NULL == vendor_labels[i])
358                         continue;
359                 ch->firsts[CHET_V1+i] = vendor_firsts[i];
360                 ch->counts[CHET_V1+i] = vendor_counts[i];
361                 VPRINTK(KERN_INFO, "type #%d (v%d): 0x%x+%d [%s, vendor specific]\n",
362                         i+5,i+1,vendor_firsts[i],vendor_counts[i],
363                         vendor_labels[i]);
364         }
365
366         /* look up the devices of the data transfer elements */
367         ch->dt = kcalloc(ch->counts[CHET_DT], sizeof(*ch->dt),
368                          GFP_KERNEL);
369
370         if (!ch->dt) {
371                 kfree(buffer);
372                 return -ENOMEM;
373         }
374
375         for (elem = 0; elem < ch->counts[CHET_DT]; elem++) {
376                 id  = -1;
377                 lun = 0;
378                 if (elem < CH_DT_MAX  &&  -1 != dt_id[elem]) {
379                         id  = dt_id[elem];
380                         lun = dt_lun[elem];
381                         VPRINTK(KERN_INFO, "dt 0x%x: [insmod option] ",
382                                 elem+ch->firsts[CHET_DT]);
383                 } else if (0 != ch_read_element_status
384                            (ch,elem+ch->firsts[CHET_DT],data)) {
385                         VPRINTK(KERN_INFO, "dt 0x%x: READ ELEMENT STATUS failed\n",
386                                 elem+ch->firsts[CHET_DT]);
387                 } else {
388                         VPRINTK(KERN_INFO, "dt 0x%x: ",elem+ch->firsts[CHET_DT]);
389                         if (data[6] & 0x80) {
390                                 VPRINTK(KERN_CONT, "not this SCSI bus\n");
391                                 ch->dt[elem] = NULL;
392                         } else if (0 == (data[6] & 0x30)) {
393                                 VPRINTK(KERN_CONT, "ID/LUN unknown\n");
394                                 ch->dt[elem] = NULL;
395                         } else {
396                                 id  = ch->device->id;
397                                 lun = 0;
398                                 if (data[6] & 0x20) id  = data[7];
399                                 if (data[6] & 0x10) lun = data[6] & 7;
400                         }
401                 }
402                 if (-1 != id) {
403                         VPRINTK(KERN_CONT, "ID %i, LUN %i, ",id,lun);
404                         ch->dt[elem] =
405                                 scsi_device_lookup(ch->device->host,
406                                                    ch->device->channel,
407                                                    id,lun);
408                         if (!ch->dt[elem]) {
409                                 /* should not happen */
410                                 VPRINTK(KERN_CONT, "Huh? device not found!\n");
411                         } else {
412                                 VPRINTK(KERN_CONT, "name: %8.8s %16.16s %4.4s\n",
413                                         ch->dt[elem]->vendor,
414                                         ch->dt[elem]->model,
415                                         ch->dt[elem]->rev);
416                         }
417                 }
418         }
419         ch->voltags = 1;
420         kfree(buffer);
421
422         return 0;
423 }
424
425 /* ------------------------------------------------------------------------ */
426
427 static int
428 ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate)
429 {
430         u_char  cmd[10];
431
432         DPRINTK("position: 0x%x\n",elem);
433         if (0 == trans)
434                 trans = ch->firsts[CHET_MT];
435         memset(cmd,0,sizeof(cmd));
436         cmd[0]  = POSITION_TO_ELEMENT;
437         cmd[1]  = (ch->device->lun & 0x7) << 5;
438         cmd[2]  = (trans >> 8) & 0xff;
439         cmd[3]  =  trans       & 0xff;
440         cmd[4]  = (elem  >> 8) & 0xff;
441         cmd[5]  =  elem        & 0xff;
442         cmd[8]  = rotate ? 1 : 0;
443         return ch_do_scsi(ch, cmd, 10, NULL, 0, REQ_OP_DRV_IN);
444 }
445
446 static int
447 ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate)
448 {
449         u_char  cmd[12];
450
451         DPRINTK("move: 0x%x => 0x%x\n",src,dest);
452         if (0 == trans)
453                 trans = ch->firsts[CHET_MT];
454         memset(cmd,0,sizeof(cmd));
455         cmd[0]  = MOVE_MEDIUM;
456         cmd[1]  = (ch->device->lun & 0x7) << 5;
457         cmd[2]  = (trans >> 8) & 0xff;
458         cmd[3]  =  trans       & 0xff;
459         cmd[4]  = (src   >> 8) & 0xff;
460         cmd[5]  =  src         & 0xff;
461         cmd[6]  = (dest  >> 8) & 0xff;
462         cmd[7]  =  dest        & 0xff;
463         cmd[10] = rotate ? 1 : 0;
464         return ch_do_scsi(ch, cmd, 12, NULL, 0, REQ_OP_DRV_IN);
465 }
466
467 static int
468 ch_exchange(scsi_changer *ch, u_int trans, u_int src,
469             u_int dest1, u_int dest2, int rotate1, int rotate2)
470 {
471         u_char  cmd[12];
472
473         DPRINTK("exchange: 0x%x => 0x%x => 0x%x\n",
474                 src,dest1,dest2);
475         if (0 == trans)
476                 trans = ch->firsts[CHET_MT];
477         memset(cmd,0,sizeof(cmd));
478         cmd[0]  = EXCHANGE_MEDIUM;
479         cmd[1]  = (ch->device->lun & 0x7) << 5;
480         cmd[2]  = (trans >> 8) & 0xff;
481         cmd[3]  =  trans       & 0xff;
482         cmd[4]  = (src   >> 8) & 0xff;
483         cmd[5]  =  src         & 0xff;
484         cmd[6]  = (dest1 >> 8) & 0xff;
485         cmd[7]  =  dest1       & 0xff;
486         cmd[8]  = (dest2 >> 8) & 0xff;
487         cmd[9]  =  dest2       & 0xff;
488         cmd[10] = (rotate1 ? 1 : 0) | (rotate2 ? 2 : 0);
489
490         return ch_do_scsi(ch, cmd, 12, NULL, 0, REQ_OP_DRV_IN);
491 }
492
493 static void
494 ch_check_voltag(char *tag)
495 {
496         int i;
497
498         for (i = 0; i < 32; i++) {
499                 /* restrict to ascii */
500                 if (tag[i] >= 0x7f || tag[i] < 0x20)
501                         tag[i] = ' ';
502                 /* don't allow search wildcards */
503                 if (tag[i] == '?' ||
504                     tag[i] == '*')
505                         tag[i] = ' ';
506         }
507 }
508
509 static int
510 ch_set_voltag(scsi_changer *ch, u_int elem,
511               int alternate, int clear, u_char *tag)
512 {
513         u_char  cmd[12];
514         u_char  *buffer;
515         int result;
516
517         buffer = kzalloc(512, GFP_KERNEL);
518         if (!buffer)
519                 return -ENOMEM;
520
521         DPRINTK("%s %s voltag: 0x%x => \"%s\"\n",
522                 clear     ? "clear"     : "set",
523                 alternate ? "alternate" : "primary",
524                 elem, tag);
525         memset(cmd,0,sizeof(cmd));
526         cmd[0]  = SEND_VOLUME_TAG;
527         cmd[1] = ((ch->device->lun & 0x7) << 5) |
528                 ch_elem_to_typecode(ch,elem);
529         cmd[2] = (elem >> 8) & 0xff;
530         cmd[3] = elem        & 0xff;
531         cmd[5] = clear
532                 ? (alternate ? 0x0d : 0x0c)
533                 : (alternate ? 0x0b : 0x0a);
534
535         cmd[9] = 255;
536
537         memcpy(buffer,tag,32);
538         ch_check_voltag(buffer);
539
540         result = ch_do_scsi(ch, cmd, 12, buffer, 256, REQ_OP_DRV_OUT);
541         kfree(buffer);
542         return result;
543 }
544
545 static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
546 {
547         int retval = 0;
548         u_char data[16];
549         unsigned int i;
550
551         mutex_lock(&ch->lock);
552         for (i = 0; i < ch->counts[type]; i++) {
553                 if (0 != ch_read_element_status
554                     (ch, ch->firsts[type]+i,data)) {
555                         retval = -EIO;
556                         break;
557                 }
558                 put_user(data[2], dest+i);
559                 if (data[2] & CESTATUS_EXCEPT)
560                         VPRINTK(KERN_INFO, "element 0x%x: asc=0x%x, ascq=0x%x\n",
561                                 ch->firsts[type]+i,
562                                 (int)data[4],(int)data[5]);
563                 retval = ch_read_element_status
564                         (ch, ch->firsts[type]+i,data);
565                 if (0 != retval)
566                         break;
567         }
568         mutex_unlock(&ch->lock);
569         return retval;
570 }
571
572 /* ------------------------------------------------------------------------ */
573
574 static void ch_destroy(struct kref *ref)
575 {
576         scsi_changer *ch = container_of(ref, scsi_changer, ref);
577
578         ch->device = NULL;
579         kfree(ch->dt);
580         kfree(ch);
581 }
582
583 static int
584 ch_release(struct inode *inode, struct file *file)
585 {
586         scsi_changer *ch = file->private_data;
587
588         scsi_device_put(ch->device);
589         file->private_data = NULL;
590         kref_put(&ch->ref, ch_destroy);
591         return 0;
592 }
593
594 static int
595 ch_open(struct inode *inode, struct file *file)
596 {
597         scsi_changer *ch;
598         int minor = iminor(inode);
599
600         spin_lock(&ch_index_lock);
601         ch = idr_find(&ch_index_idr, minor);
602
603         if (ch == NULL || !kref_get_unless_zero(&ch->ref)) {
604                 spin_unlock(&ch_index_lock);
605                 return -ENXIO;
606         }
607         spin_unlock(&ch_index_lock);
608         if (scsi_device_get(ch->device)) {
609                 kref_put(&ch->ref, ch_destroy);
610                 return -ENXIO;
611         }
612         /* Synchronize with ch_probe() */
613         mutex_lock(&ch->lock);
614         file->private_data = ch;
615         mutex_unlock(&ch->lock);
616         return 0;
617 }
618
619 static int
620 ch_checkrange(scsi_changer *ch, unsigned int type, unsigned int unit)
621 {
622         if (type >= CH_TYPES  ||  unit >= ch->counts[type])
623                 return -1;
624         return 0;
625 }
626
627 struct changer_element_status32 {
628         int             ces_type;
629         compat_uptr_t   ces_data;
630 };
631 #define CHIOGSTATUS32  _IOW('c', 8, struct changer_element_status32)
632
633 static long ch_ioctl(struct file *file,
634                     unsigned int cmd, unsigned long arg)
635 {
636         scsi_changer *ch = file->private_data;
637         int retval;
638         void __user *argp = (void __user *)arg;
639
640         retval = scsi_ioctl_block_when_processing_errors(ch->device, cmd,
641                         file->f_flags & O_NDELAY);
642         if (retval)
643                 return retval;
644
645         switch (cmd) {
646         case CHIOGPARAMS:
647         {
648                 struct changer_params params;
649
650                 params.cp_curpicker = 0;
651                 params.cp_npickers  = ch->counts[CHET_MT];
652                 params.cp_nslots    = ch->counts[CHET_ST];
653                 params.cp_nportals  = ch->counts[CHET_IE];
654                 params.cp_ndrives   = ch->counts[CHET_DT];
655
656                 if (copy_to_user(argp, &params, sizeof(params)))
657                         return -EFAULT;
658                 return 0;
659         }
660         case CHIOGVPARAMS:
661         {
662                 struct changer_vendor_params vparams;
663
664                 memset(&vparams,0,sizeof(vparams));
665                 if (ch->counts[CHET_V1]) {
666                         vparams.cvp_n1  = ch->counts[CHET_V1];
667                         strscpy(vparams.cvp_label1, vendor_labels[0],
668                                 sizeof(vparams.cvp_label1));
669                 }
670                 if (ch->counts[CHET_V2]) {
671                         vparams.cvp_n2  = ch->counts[CHET_V2];
672                         strscpy(vparams.cvp_label2, vendor_labels[1],
673                                 sizeof(vparams.cvp_label2));
674                 }
675                 if (ch->counts[CHET_V3]) {
676                         vparams.cvp_n3  = ch->counts[CHET_V3];
677                         strscpy(vparams.cvp_label3, vendor_labels[2],
678                                 sizeof(vparams.cvp_label3));
679                 }
680                 if (ch->counts[CHET_V4]) {
681                         vparams.cvp_n4  = ch->counts[CHET_V4];
682                         strscpy(vparams.cvp_label4, vendor_labels[3],
683                                 sizeof(vparams.cvp_label4));
684                 }
685                 if (copy_to_user(argp, &vparams, sizeof(vparams)))
686                         return -EFAULT;
687                 return 0;
688         }
689
690         case CHIOPOSITION:
691         {
692                 struct changer_position pos;
693
694                 if (copy_from_user(&pos, argp, sizeof (pos)))
695                         return -EFAULT;
696
697                 if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) {
698                         DPRINTK("CHIOPOSITION: invalid parameter\n");
699                         return -EBADSLT;
700                 }
701                 mutex_lock(&ch->lock);
702                 retval = ch_position(ch,0,
703                                      ch->firsts[pos.cp_type] + pos.cp_unit,
704                                      pos.cp_flags & CP_INVERT);
705                 mutex_unlock(&ch->lock);
706                 return retval;
707         }
708
709         case CHIOMOVE:
710         {
711                 struct changer_move mv;
712
713                 if (copy_from_user(&mv, argp, sizeof (mv)))
714                         return -EFAULT;
715
716                 if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) ||
717                     0 != ch_checkrange(ch, mv.cm_totype,   mv.cm_tounit  )) {
718                         DPRINTK("CHIOMOVE: invalid parameter\n");
719                         return -EBADSLT;
720                 }
721
722                 mutex_lock(&ch->lock);
723                 retval = ch_move(ch,0,
724                                  ch->firsts[mv.cm_fromtype] + mv.cm_fromunit,
725                                  ch->firsts[mv.cm_totype]   + mv.cm_tounit,
726                                  mv.cm_flags & CM_INVERT);
727                 mutex_unlock(&ch->lock);
728                 return retval;
729         }
730
731         case CHIOEXCHANGE:
732         {
733                 struct changer_exchange mv;
734
735                 if (copy_from_user(&mv, argp, sizeof (mv)))
736                         return -EFAULT;
737
738                 if (0 != ch_checkrange(ch, mv.ce_srctype,  mv.ce_srcunit ) ||
739                     0 != ch_checkrange(ch, mv.ce_fdsttype, mv.ce_fdstunit) ||
740                     0 != ch_checkrange(ch, mv.ce_sdsttype, mv.ce_sdstunit)) {
741                         DPRINTK("CHIOEXCHANGE: invalid parameter\n");
742                         return -EBADSLT;
743                 }
744
745                 mutex_lock(&ch->lock);
746                 retval = ch_exchange
747                         (ch,0,
748                          ch->firsts[mv.ce_srctype]  + mv.ce_srcunit,
749                          ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit,
750                          ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit,
751                          mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2);
752                 mutex_unlock(&ch->lock);
753                 return retval;
754         }
755
756         case CHIOGSTATUS:
757         {
758                 struct changer_element_status ces;
759
760                 if (copy_from_user(&ces, argp, sizeof (ces)))
761                         return -EFAULT;
762                 if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES)
763                         return -EINVAL;
764
765                 return ch_gstatus(ch, ces.ces_type, ces.ces_data);
766         }
767 #ifdef CONFIG_COMPAT
768         case CHIOGSTATUS32:
769         {
770                 struct changer_element_status32 ces32;
771
772                 if (copy_from_user(&ces32, argp, sizeof(ces32)))
773                         return -EFAULT;
774                 if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
775                         return -EINVAL;
776
777                 return ch_gstatus(ch, ces32.ces_type,
778                                   compat_ptr(ces32.ces_data));
779         }
780 #endif
781         case CHIOGELEM:
782         {
783                 struct changer_get_element cge;
784                 u_char ch_cmd[12];
785                 u_char *buffer;
786                 unsigned int elem;
787                 int     result,i;
788
789                 if (copy_from_user(&cge, argp, sizeof (cge)))
790                         return -EFAULT;
791
792                 if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit))
793                         return -EINVAL;
794                 elem = ch->firsts[cge.cge_type] + cge.cge_unit;
795
796                 buffer = kmalloc(512, GFP_KERNEL);
797                 if (!buffer)
798                         return -ENOMEM;
799                 mutex_lock(&ch->lock);
800
801         voltag_retry:
802                 memset(ch_cmd, 0, sizeof(ch_cmd));
803                 ch_cmd[0] = READ_ELEMENT_STATUS;
804                 ch_cmd[1] = ((ch->device->lun & 0x7) << 5) |
805                         (ch->voltags ? 0x10 : 0) |
806                         ch_elem_to_typecode(ch,elem);
807                 ch_cmd[2] = (elem >> 8) & 0xff;
808                 ch_cmd[3] = elem        & 0xff;
809                 ch_cmd[5] = 1;
810                 ch_cmd[9] = 255;
811
812                 result = ch_do_scsi(ch, ch_cmd, 12, buffer, 256, REQ_OP_DRV_IN);
813                 if (!result) {
814                         cge.cge_status = buffer[18];
815                         cge.cge_flags = 0;
816                         if (buffer[18] & CESTATUS_EXCEPT) {
817                                 cge.cge_errno = EIO;
818                         }
819                         if (buffer[25] & 0x80) {
820                                 cge.cge_flags |= CGE_SRC;
821                                 if (buffer[25] & 0x40)
822                                         cge.cge_flags |= CGE_INVERT;
823                                 elem = (buffer[26]<<8) | buffer[27];
824                                 for (i = 0; i < 4; i++) {
825                                         if (elem >= ch->firsts[i] &&
826                                             elem <  ch->firsts[i] + ch->counts[i]) {
827                                                 cge.cge_srctype = i;
828                                                 cge.cge_srcunit = elem-ch->firsts[i];
829                                         }
830                                 }
831                         }
832                         if ((buffer[22] & 0x30) == 0x30) {
833                                 cge.cge_flags |= CGE_IDLUN;
834                                 cge.cge_id  = buffer[23];
835                                 cge.cge_lun = buffer[22] & 7;
836                         }
837                         if (buffer[9] & 0x80) {
838                                 cge.cge_flags |= CGE_PVOLTAG;
839                                 memcpy(cge.cge_pvoltag,buffer+28,36);
840                         }
841                         if (buffer[9] & 0x40) {
842                                 cge.cge_flags |= CGE_AVOLTAG;
843                                 memcpy(cge.cge_avoltag,buffer+64,36);
844                         }
845                 } else if (ch->voltags) {
846                         ch->voltags = 0;
847                         VPRINTK(KERN_INFO, "device has no volume tag support\n");
848                         goto voltag_retry;
849                 }
850                 kfree(buffer);
851                 mutex_unlock(&ch->lock);
852
853                 if (copy_to_user(argp, &cge, sizeof (cge)))
854                         return -EFAULT;
855                 return result;
856         }
857
858         case CHIOINITELEM:
859         {
860                 mutex_lock(&ch->lock);
861                 retval = ch_init_elem(ch);
862                 mutex_unlock(&ch->lock);
863                 return retval;
864         }
865
866         case CHIOSVOLTAG:
867         {
868                 struct changer_set_voltag csv;
869                 int elem;
870
871                 if (copy_from_user(&csv, argp, sizeof(csv)))
872                         return -EFAULT;
873
874                 if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) {
875                         DPRINTK("CHIOSVOLTAG: invalid parameter\n");
876                         return -EBADSLT;
877                 }
878                 elem = ch->firsts[csv.csv_type] + csv.csv_unit;
879                 mutex_lock(&ch->lock);
880                 retval = ch_set_voltag(ch, elem,
881                                        csv.csv_flags & CSV_AVOLTAG,
882                                        csv.csv_flags & CSV_CLEARTAG,
883                                        csv.csv_voltag);
884                 mutex_unlock(&ch->lock);
885                 return retval;
886         }
887
888         default:
889                 return scsi_ioctl(ch->device, file->f_mode & FMODE_WRITE, cmd,
890                                   argp);
891
892         }
893 }
894
895 /* ------------------------------------------------------------------------ */
896
897 static int ch_probe(struct device *dev)
898 {
899         struct scsi_device *sd = to_scsi_device(dev);
900         struct device *class_dev;
901         int ret;
902         scsi_changer *ch;
903
904         if (sd->type != TYPE_MEDIUM_CHANGER)
905                 return -ENODEV;
906
907         ch = kzalloc(sizeof(*ch), GFP_KERNEL);
908         if (NULL == ch)
909                 return -ENOMEM;
910
911         idr_preload(GFP_KERNEL);
912         spin_lock(&ch_index_lock);
913         ret = idr_alloc(&ch_index_idr, ch, 0, CH_MAX_DEVS + 1, GFP_NOWAIT);
914         spin_unlock(&ch_index_lock);
915         idr_preload_end();
916
917         if (ret < 0) {
918                 if (ret == -ENOSPC)
919                         ret = -ENODEV;
920                 goto free_ch;
921         }
922
923         ch->minor = ret;
924         sprintf(ch->name,"ch%d",ch->minor);
925         ret = scsi_device_get(sd);
926         if (ret) {
927                 sdev_printk(KERN_WARNING, sd, "ch%d: failed to get device\n",
928                             ch->minor);
929                 goto remove_idr;
930         }
931
932         mutex_init(&ch->lock);
933         kref_init(&ch->ref);
934         ch->device = sd;
935         class_dev = device_create(&ch_sysfs_class, dev,
936                                   MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch,
937                                   "s%s", ch->name);
938         if (IS_ERR(class_dev)) {
939                 sdev_printk(KERN_WARNING, sd, "ch%d: device_create failed\n",
940                             ch->minor);
941                 ret = PTR_ERR(class_dev);
942                 goto put_device;
943         }
944
945         mutex_lock(&ch->lock);
946         ret = ch_readconfig(ch);
947         if (ret) {
948                 mutex_unlock(&ch->lock);
949                 goto destroy_dev;
950         }
951         if (init)
952                 ch_init_elem(ch);
953
954         mutex_unlock(&ch->lock);
955         dev_set_drvdata(dev, ch);
956         sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name);
957
958         return 0;
959 destroy_dev:
960         device_destroy(&ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR, ch->minor));
961 put_device:
962         scsi_device_put(sd);
963 remove_idr:
964         idr_remove(&ch_index_idr, ch->minor);
965 free_ch:
966         kfree(ch);
967         return ret;
968 }
969
970 static int ch_remove(struct device *dev)
971 {
972         scsi_changer *ch = dev_get_drvdata(dev);
973
974         spin_lock(&ch_index_lock);
975         idr_remove(&ch_index_idr, ch->minor);
976         dev_set_drvdata(dev, NULL);
977         spin_unlock(&ch_index_lock);
978
979         device_destroy(&ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR, ch->minor));
980         scsi_device_put(ch->device);
981         kref_put(&ch->ref, ch_destroy);
982         return 0;
983 }
984
985 static struct scsi_driver ch_template = {
986         .gendrv         = {
987                 .name   = "ch",
988                 .owner  = THIS_MODULE,
989                 .probe  = ch_probe,
990                 .remove = ch_remove,
991         },
992 };
993
994 static const struct file_operations changer_fops = {
995         .owner          = THIS_MODULE,
996         .open           = ch_open,
997         .release        = ch_release,
998         .unlocked_ioctl = ch_ioctl,
999         .compat_ioctl   = compat_ptr_ioctl,
1000         .llseek         = noop_llseek,
1001 };
1002
1003 static int __init init_ch_module(void)
1004 {
1005         int rc;
1006
1007         printk(KERN_INFO "SCSI Media Changer driver v" VERSION " \n");
1008         rc = class_register(&ch_sysfs_class);
1009         if (rc)
1010                 return rc;
1011         rc = register_chrdev(SCSI_CHANGER_MAJOR,"ch",&changer_fops);
1012         if (rc < 0) {
1013                 printk("Unable to get major %d for SCSI-Changer\n",
1014                        SCSI_CHANGER_MAJOR);
1015                 goto fail1;
1016         }
1017         rc = scsi_register_driver(&ch_template.gendrv);
1018         if (rc < 0)
1019                 goto fail2;
1020         return 0;
1021
1022  fail2:
1023         unregister_chrdev(SCSI_CHANGER_MAJOR, "ch");
1024  fail1:
1025         class_unregister(&ch_sysfs_class);
1026         return rc;
1027 }
1028
1029 static void __exit exit_ch_module(void)
1030 {
1031         scsi_unregister_driver(&ch_template.gendrv);
1032         unregister_chrdev(SCSI_CHANGER_MAJOR, "ch");
1033         class_unregister(&ch_sysfs_class);
1034         idr_destroy(&ch_index_idr);
1035 }
1036
1037 module_init(init_ch_module);
1038 module_exit(exit_ch_module);