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