Blame view

drivers/scsi/ch.c 24.5 KB
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
1
2
3
4
5
6
7
8
  /*
   * SCSI Media Changer device driver for Linux 2.6
   *
   *     (c) 1996-2003 Gerd Knorr <kraxel@bytesex.org>
   *
   */
  
  #define VERSION "0.25"
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
9
10
11
12
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/fs.h>
  #include <linux/kernel.h>
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
13
14
15
16
17
18
19
  #include <linux/mm.h>
  #include <linux/major.h>
  #include <linux/string.h>
  #include <linux/errno.h>
  #include <linux/interrupt.h>
  #include <linux/blkdev.h>
  #include <linux/completion.h>
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
20
21
  #include <linux/compat.h>
  #include <linux/chio.h>			/* here are all the ioctls */
0b9506723   Arjan van de Ven   [SCSI] turn most ...
22
  #include <linux/mutex.h>
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
23
  #include <linux/idr.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
24
  #include <linux/slab.h>
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
25
26
27
28
29
30
31
  
  #include <scsi/scsi.h>
  #include <scsi/scsi_cmnd.h>
  #include <scsi/scsi_driver.h>
  #include <scsi/scsi_ioctl.h>
  #include <scsi/scsi_host.h>
  #include <scsi/scsi_device.h>
84743bbcf   James Bottomley   [SCSI] convert ch...
32
  #include <scsi/scsi_eh.h>
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
33
34
35
36
  #include <scsi/scsi_dbg.h>
  
  #define CH_DT_MAX       16
  #define CH_TYPES        8
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
37
  #define CH_MAX_DEVS     128
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
38
39
40
41
  
  MODULE_DESCRIPTION("device driver for scsi media changer devices");
  MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org>");
  MODULE_LICENSE("GPL");
f018fa552   Rene Herman   [SCSI] MODULE_ALI...
42
  MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR);
95f6c83f6   Scott James Remnant   [SCSI] ch: Add sc...
43
  MODULE_ALIAS_SCSI_DEVICE(TYPE_MEDIUM_CHANGER);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
44

c45d15d24   Arnd Bergmann   scsi: autoconvert...
45
  static DEFINE_MUTEX(ch_mutex);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  static int init = 1;
  module_param(init, int, 0444);
  MODULE_PARM_DESC(init, \
      "initialize element status on driver load (default: on)");
  
  static int timeout_move = 300;
  module_param(timeout_move, int, 0644);
  MODULE_PARM_DESC(timeout_move,"timeout for move commands "
  		 "(default: 300 seconds)");
  
  static int timeout_init = 3600;
  module_param(timeout_init, int, 0644);
  MODULE_PARM_DESC(timeout_init,"timeout for INITIALIZE ELEMENT STATUS "
  		 "(default: 3600 seconds)");
  
  static int verbose = 1;
  module_param(verbose, int, 0644);
  MODULE_PARM_DESC(verbose,"be verbose (default: on)");
  
  static int debug = 0;
  module_param(debug, int, 0644);
  MODULE_PARM_DESC(debug,"enable/disable debug messages, also prints more "
  		 "detailed sense codes on scsi errors (default: off)");
  
  static int dt_id[CH_DT_MAX] = { [ 0 ... (CH_DT_MAX-1) ] = -1 };
  static int dt_lun[CH_DT_MAX];
  module_param_array(dt_id,  int, NULL, 0444);
  module_param_array(dt_lun, int, NULL, 0444);
  
  /* tell the driver about vendor-specific slots */
  static int vendor_firsts[CH_TYPES-4];
  static int vendor_counts[CH_TYPES-4];
  module_param_array(vendor_firsts, int, NULL, 0444);
  module_param_array(vendor_counts, int, NULL, 0444);
0ad78200b   Arjan van de Ven   [SCSI] Mark some ...
80
  static const char * vendor_labels[CH_TYPES-4] = {
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
81
82
83
  	"v0", "v1", "v2", "v3"
  };
  // module_param_string_array(vendor_labels, NULL, 0444);
28c31729c   Hannes Reinecke   scsi: Implement c...
84
  #define ch_printk(prefix, ch, fmt, a...) \
22e0d9941   Hannes Reinecke   scsi: introduce s...
85
  	sdev_prefix_printk(prefix, (ch)->device, (ch)->name, fmt, ##a)
28c31729c   Hannes Reinecke   scsi: Implement c...
86

87da32356   Joe Perches   drivers/scsi/ch.c...
87
88
89
  #define DPRINTK(fmt, arg...)						\
  do {									\
  	if (debug)							\
28c31729c   Hannes Reinecke   scsi: Implement c...
90
  		ch_printk(KERN_DEBUG, ch, fmt, ##arg);			\
87da32356   Joe Perches   drivers/scsi/ch.c...
91
92
93
94
  } while (0)
  #define VPRINTK(level, fmt, arg...)					\
  do {									\
  	if (verbose)							\
28c31729c   Hannes Reinecke   scsi: Implement c...
95
  		ch_printk(level, ch, fmt, ##arg);			\
87da32356   Joe Perches   drivers/scsi/ch.c...
96
  } while (0)
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
97
98
99
100
  
  /* ------------------------------------------------------------------- */
  
  #define MAX_RETRIES   1
21feb5ccd   Gerd Knorr   [SCSI] convert sc...
101
  static struct class * ch_sysfs_class;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
102
103
104
105
106
107
108
109
110
111
112
  
  typedef struct {
  	struct list_head    list;
  	int                 minor;
  	char                name[8];
  	struct scsi_device  *device;
  	struct scsi_device  **dt;        /* ptrs to data transfer elements */
  	u_int               firsts[CH_TYPES];
  	u_int               counts[CH_TYPES];
  	u_int               unit_attention;
  	u_int		    voltags;
0b9506723   Arjan van de Ven   [SCSI] turn most ...
113
  	struct mutex	    lock;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
114
  } scsi_changer;
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
115
116
  static DEFINE_IDR(ch_index_idr);
  static DEFINE_SPINLOCK(ch_index_lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
117

0ad78200b   Arjan van de Ven   [SCSI] Mark some ...
118
  static const struct {
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
119
120
121
122
  	unsigned char  sense;
  	unsigned char  asc;
  	unsigned char  ascq;
  	int	       errno;
d70d4667e   Harvey Harrison   [SCSI] ch: fix sp...
123
  } ch_err[] = {
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  /* Just filled in what looks right. Hav'nt checked any standard paper for
     these errno assignments, so they may be wrong... */
  	{
  		.sense  = ILLEGAL_REQUEST,
  		.asc    = 0x21,
  		.ascq   = 0x01,
  		.errno  = EBADSLT, /* Invalid element address */
  	},{
  		.sense  = ILLEGAL_REQUEST,
  		.asc    = 0x28,
  		.ascq   = 0x01,
  		.errno  = EBADE,   /* Import or export element accessed */
  	},{
  		.sense  = ILLEGAL_REQUEST,
  		.asc    = 0x3B,
  		.ascq   = 0x0D,
  		.errno  = EXFULL,  /* Medium destination element full */
  	},{
  		.sense  = ILLEGAL_REQUEST,
  		.asc    = 0x3B,
  		.ascq   = 0x0E,
  		.errno  = EBADE,   /* Medium source element empty */
  	},{
  		.sense  = ILLEGAL_REQUEST,
  		.asc    = 0x20,
  		.ascq   = 0x00,
  		.errno  = EBADRQC, /* Invalid command operation code */
  	},{
  	        /* end of list */
  	}
  };
  
  /* ------------------------------------------------------------------- */
84743bbcf   James Bottomley   [SCSI] convert ch...
157
  static int ch_find_errno(struct scsi_sense_hdr *sshdr)
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
158
159
160
161
  {
  	int i,errno = 0;
  
  	/* Check to see if additional sense information is available */
84743bbcf   James Bottomley   [SCSI] convert ch...
162
163
  	if (scsi_sense_valid(sshdr) &&
  	    sshdr->asc != 0) {
d70d4667e   Harvey Harrison   [SCSI] ch: fix sp...
164
165
166
167
168
  		for (i = 0; ch_err[i].errno != 0; i++) {
  			if (ch_err[i].sense == sshdr->sense_key &&
  			    ch_err[i].asc   == sshdr->asc &&
  			    ch_err[i].ascq  == sshdr->ascq) {
  				errno = -ch_err[i].errno;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
169
170
171
172
173
174
175
176
177
178
  				break;
  			}
  		}
  	}
  	if (errno == 0)
  		errno = -EIO;
  	return errno;
  }
  
  static int
a9a47bf58   Hannes Reinecke   scsi: repurpose t...
179
  ch_do_scsi(scsi_changer *ch, unsigned char *cmd, int cmd_len,
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
180
181
182
  	   void *buffer, unsigned buflength,
  	   enum dma_data_direction direction)
  {
84743bbcf   James Bottomley   [SCSI] convert ch...
183
184
  	int errno, retries = 0, timeout, result;
  	struct scsi_sense_hdr sshdr;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
185

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
186
187
188
189
190
  	timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS)
  		? timeout_init : timeout_move;
  
   retry:
  	errno = 0;
28c31729c   Hannes Reinecke   scsi: Implement c...
191
  	result = scsi_execute_req(ch->device, cmd, direction, buffer,
84743bbcf   James Bottomley   [SCSI] convert ch...
192
  				  buflength, &sshdr, timeout * HZ,
f4f4e47e4   FUJITA Tomonori   [SCSI] add residu...
193
  				  MAX_RETRIES, NULL);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
194

84743bbcf   James Bottomley   [SCSI] convert ch...
195
  	if (driver_byte(result) & DRIVER_SENSE) {
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
196
  		if (debug)
d811b848e   Hannes Reinecke   scsi: use sdev as...
197
  			scsi_print_sense_hdr(ch->device, ch->name, &sshdr);
84743bbcf   James Bottomley   [SCSI] convert ch...
198
  		errno = ch_find_errno(&sshdr);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
199

84743bbcf   James Bottomley   [SCSI] convert ch...
200
  		switch(sshdr.sense_key) {
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
201
202
203
204
205
206
207
  		case UNIT_ATTENTION:
  			ch->unit_attention = 1;
  			if (retries++ < 3)
  				goto retry;
  			break;
  		}
  	}
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
208
209
210
211
212
213
214
215
216
  	return errno;
  }
  
  /* ------------------------------------------------------------------------ */
  
  static int
  ch_elem_to_typecode(scsi_changer *ch, u_int elem)
  {
  	int i;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
217

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  	for (i = 0; i < CH_TYPES; i++) {
  		if (elem >= ch->firsts[i]  &&
  		    elem <  ch->firsts[i] +
  	            ch->counts[i])
  			return i+1;
  	}
  	return 0;
  }
  
  static int
  ch_read_element_status(scsi_changer *ch, u_int elem, char *data)
  {
  	u_char  cmd[12];
  	u_char  *buffer;
  	int     result;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
233

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
234
235
236
  	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
  	if(!buffer)
  		return -ENOMEM;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
237

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
238
239
240
   retry:
  	memset(cmd,0,sizeof(cmd));
  	cmd[0] = READ_ELEMENT_STATUS;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
241
  	cmd[1] = ((ch->device->lun & 0x7) << 5) |
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
242
243
244
245
246
247
  		(ch->voltags ? 0x10 : 0) |
  		ch_elem_to_typecode(ch,elem);
  	cmd[2] = (elem >> 8) & 0xff;
  	cmd[3] = elem        & 0xff;
  	cmd[5] = 1;
  	cmd[9] = 255;
a9a47bf58   Hannes Reinecke   scsi: repurpose t...
248
249
  	if (0 == (result = ch_do_scsi(ch, cmd, 12,
  				      buffer, 256, DMA_FROM_DEVICE))) {
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
250
  		if (((buffer[16] << 8) | buffer[17]) != elem) {
87da32356   Joe Perches   drivers/scsi/ch.c...
251
252
  			DPRINTK("asked for element 0x%02x, got 0x%02x
  ",
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
253
254
255
256
257
258
259
260
  				elem,(buffer[16] << 8) | buffer[17]);
  			kfree(buffer);
  			return -EIO;
  		}
  		memcpy(data,buffer+16,16);
  	} else {
  		if (ch->voltags) {
  			ch->voltags = 0;
87da32356   Joe Perches   drivers/scsi/ch.c...
261
262
  			VPRINTK(KERN_INFO, "device has no volume tag support
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
263
264
  			goto retry;
  		}
87da32356   Joe Perches   drivers/scsi/ch.c...
265
266
  		DPRINTK("READ ELEMENT STATUS for element 0x%x failed
  ",elem);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
267
268
269
270
  	}
  	kfree(buffer);
  	return result;
  }
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
271
  static int
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
272
273
274
275
  ch_init_elem(scsi_changer *ch)
  {
  	int err;
  	u_char cmd[6];
87da32356   Joe Perches   drivers/scsi/ch.c...
276
277
  	VPRINTK(KERN_INFO, "INITIALIZE ELEMENT STATUS, may take some time ...
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
278
279
  	memset(cmd,0,sizeof(cmd));
  	cmd[0] = INITIALIZE_ELEMENT_STATUS;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
280
  	cmd[1] = (ch->device->lun & 0x7) << 5;
a9a47bf58   Hannes Reinecke   scsi: repurpose t...
281
  	err = ch_do_scsi(ch, cmd, 6, NULL, 0, DMA_NONE);
87da32356   Joe Perches   drivers/scsi/ch.c...
282
283
  	VPRINTK(KERN_INFO, "... finished
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
284
285
286
287
288
289
290
291
292
293
  	return err;
  }
  
  static int
  ch_readconfig(scsi_changer *ch)
  {
  	u_char  cmd[10], data[16];
  	u_char  *buffer;
  	int     result,id,lun,i;
  	u_int   elem;
4530a1696   vignesh.babu@wipro.com   [SCSI] ch: kmallo...
294
  	buffer = kzalloc(512, GFP_KERNEL | GFP_DMA);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
295
296
  	if (!buffer)
  		return -ENOMEM;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
297

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
298
299
  	memset(cmd,0,sizeof(cmd));
  	cmd[0] = MODE_SENSE;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
300
  	cmd[1] = (ch->device->lun & 0x7) << 5;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
301
302
  	cmd[2] = 0x1d;
  	cmd[4] = 255;
a9a47bf58   Hannes Reinecke   scsi: repurpose t...
303
  	result = ch_do_scsi(ch, cmd, 10, buffer, 255, DMA_FROM_DEVICE);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
304
305
  	if (0 != result) {
  		cmd[1] |= (1<<3);
a9a47bf58   Hannes Reinecke   scsi: repurpose t...
306
  		result  = ch_do_scsi(ch, cmd, 10, buffer, 255, DMA_FROM_DEVICE);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
  	}
  	if (0 == result) {
  		ch->firsts[CHET_MT] =
  			(buffer[buffer[3]+ 6] << 8) | buffer[buffer[3]+ 7];
  		ch->counts[CHET_MT] =
  			(buffer[buffer[3]+ 8] << 8) | buffer[buffer[3]+ 9];
  		ch->firsts[CHET_ST] =
  			(buffer[buffer[3]+10] << 8) | buffer[buffer[3]+11];
  		ch->counts[CHET_ST] =
  			(buffer[buffer[3]+12] << 8) | buffer[buffer[3]+13];
  		ch->firsts[CHET_IE] =
  			(buffer[buffer[3]+14] << 8) | buffer[buffer[3]+15];
  		ch->counts[CHET_IE] =
  			(buffer[buffer[3]+16] << 8) | buffer[buffer[3]+17];
  		ch->firsts[CHET_DT] =
  			(buffer[buffer[3]+18] << 8) | buffer[buffer[3]+19];
  		ch->counts[CHET_DT] =
  			(buffer[buffer[3]+20] << 8) | buffer[buffer[3]+21];
87da32356   Joe Perches   drivers/scsi/ch.c...
325
326
  		VPRINTK(KERN_INFO, "type #1 (mt): 0x%x+%d [medium transport]
  ",
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
327
328
  			ch->firsts[CHET_MT],
  			ch->counts[CHET_MT]);
87da32356   Joe Perches   drivers/scsi/ch.c...
329
330
  		VPRINTK(KERN_INFO, "type #2 (st): 0x%x+%d [storage]
  ",
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
331
332
  			ch->firsts[CHET_ST],
  			ch->counts[CHET_ST]);
87da32356   Joe Perches   drivers/scsi/ch.c...
333
334
  		VPRINTK(KERN_INFO, "type #3 (ie): 0x%x+%d [import/export]
  ",
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
335
336
  			ch->firsts[CHET_IE],
  			ch->counts[CHET_IE]);
87da32356   Joe Perches   drivers/scsi/ch.c...
337
338
  		VPRINTK(KERN_INFO, "type #4 (dt): 0x%x+%d [data transfer]
  ",
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
339
340
341
  			ch->firsts[CHET_DT],
  			ch->counts[CHET_DT]);
  	} else {
f42cf8d6a   Masanari Iida   treewide: Fix typ...
342
343
  		VPRINTK(KERN_INFO, "reading element address assignment page failed!
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
344
  	}
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
345

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
346
347
348
349
350
351
352
353
  	/* vendor specific element types */
  	for (i = 0; i < 4; i++) {
  		if (0 == vendor_counts[i])
  			continue;
  		if (NULL == vendor_labels[i])
  			continue;
  		ch->firsts[CHET_V1+i] = vendor_firsts[i];
  		ch->counts[CHET_V1+i] = vendor_counts[i];
87da32356   Joe Perches   drivers/scsi/ch.c...
354
355
  		VPRINTK(KERN_INFO, "type #%d (v%d): 0x%x+%d [%s, vendor specific]
  ",
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
356
357
358
359
360
  			i+5,i+1,vendor_firsts[i],vendor_counts[i],
  			vendor_labels[i]);
  	}
  
  	/* look up the devices of the data transfer elements */
85bc081f4   Julia Lawall   drivers/scsi/aic9...
361
  	ch->dt = kcalloc(ch->counts[CHET_DT], sizeof(*ch->dt),
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
362
  			 GFP_KERNEL);
a2cf8a630   Davidlohr Bueso A   [SCSI] ch: Check ...
363
364
365
366
367
  
  	if (!ch->dt) {
  		kfree(buffer);
  		return -ENOMEM;
  	}
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
368
369
370
371
372
373
  	for (elem = 0; elem < ch->counts[CHET_DT]; elem++) {
  		id  = -1;
  		lun = 0;
  		if (elem < CH_DT_MAX  &&  -1 != dt_id[elem]) {
  			id  = dt_id[elem];
  			lun = dt_lun[elem];
87da32356   Joe Perches   drivers/scsi/ch.c...
374
  			VPRINTK(KERN_INFO, "dt 0x%x: [insmod option] ",
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
375
376
377
  				elem+ch->firsts[CHET_DT]);
  		} else if (0 != ch_read_element_status
  			   (ch,elem+ch->firsts[CHET_DT],data)) {
87da32356   Joe Perches   drivers/scsi/ch.c...
378
379
  			VPRINTK(KERN_INFO, "dt 0x%x: READ ELEMENT STATUS failed
  ",
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
380
381
  				elem+ch->firsts[CHET_DT]);
  		} else {
87da32356   Joe Perches   drivers/scsi/ch.c...
382
  			VPRINTK(KERN_INFO, "dt 0x%x: ",elem+ch->firsts[CHET_DT]);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
383
  			if (data[6] & 0x80) {
87da32356   Joe Perches   drivers/scsi/ch.c...
384
385
  				VPRINTK(KERN_CONT, "not this SCSI bus
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
386
387
  				ch->dt[elem] = NULL;
  			} else if (0 == (data[6] & 0x30)) {
87da32356   Joe Perches   drivers/scsi/ch.c...
388
389
  				VPRINTK(KERN_CONT, "ID/LUN unknown
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
390
391
392
393
394
395
396
397
398
  				ch->dt[elem] = NULL;
  			} else {
  				id  = ch->device->id;
  				lun = 0;
  				if (data[6] & 0x20) id  = data[7];
  				if (data[6] & 0x10) lun = data[6] & 7;
  			}
  		}
  		if (-1 != id) {
87da32356   Joe Perches   drivers/scsi/ch.c...
399
  			VPRINTK(KERN_CONT, "ID %i, LUN %i, ",id,lun);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
400
401
402
403
404
405
  			ch->dt[elem] =
  				scsi_device_lookup(ch->device->host,
  						   ch->device->channel,
  						   id,lun);
  			if (!ch->dt[elem]) {
  				/* should not happen */
87da32356   Joe Perches   drivers/scsi/ch.c...
406
407
  				VPRINTK(KERN_CONT, "Huh? device not found!
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
408
  			} else {
87da32356   Joe Perches   drivers/scsi/ch.c...
409
410
411
412
413
  				VPRINTK(KERN_CONT, "name: %8.8s %16.16s %4.4s
  ",
  					ch->dt[elem]->vendor,
  					ch->dt[elem]->model,
  					ch->dt[elem]->rev);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
  			}
  		}
  	}
  	ch->voltags = 1;
  	kfree(buffer);
  
  	return 0;
  }
  
  /* ------------------------------------------------------------------------ */
  
  static int
  ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate)
  {
  	u_char  cmd[10];
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
429

87da32356   Joe Perches   drivers/scsi/ch.c...
430
431
  	DPRINTK("position: 0x%x
  ",elem);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
432
433
434
435
  	if (0 == trans)
  		trans = ch->firsts[CHET_MT];
  	memset(cmd,0,sizeof(cmd));
  	cmd[0]  = POSITION_TO_ELEMENT;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
436
  	cmd[1]  = (ch->device->lun & 0x7) << 5;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
437
438
439
440
441
  	cmd[2]  = (trans >> 8) & 0xff;
  	cmd[3]  =  trans       & 0xff;
  	cmd[4]  = (elem  >> 8) & 0xff;
  	cmd[5]  =  elem        & 0xff;
  	cmd[8]  = rotate ? 1 : 0;
a9a47bf58   Hannes Reinecke   scsi: repurpose t...
442
  	return ch_do_scsi(ch, cmd, 10, NULL, 0, DMA_NONE);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
443
444
445
446
447
448
  }
  
  static int
  ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate)
  {
  	u_char  cmd[12];
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
449

87da32356   Joe Perches   drivers/scsi/ch.c...
450
451
  	DPRINTK("move: 0x%x => 0x%x
  ",src,dest);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
452
453
454
455
  	if (0 == trans)
  		trans = ch->firsts[CHET_MT];
  	memset(cmd,0,sizeof(cmd));
  	cmd[0]  = MOVE_MEDIUM;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
456
  	cmd[1]  = (ch->device->lun & 0x7) << 5;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
457
458
459
460
461
462
463
  	cmd[2]  = (trans >> 8) & 0xff;
  	cmd[3]  =  trans       & 0xff;
  	cmd[4]  = (src   >> 8) & 0xff;
  	cmd[5]  =  src         & 0xff;
  	cmd[6]  = (dest  >> 8) & 0xff;
  	cmd[7]  =  dest        & 0xff;
  	cmd[10] = rotate ? 1 : 0;
a9a47bf58   Hannes Reinecke   scsi: repurpose t...
464
  	return ch_do_scsi(ch, cmd, 12, NULL,0, DMA_NONE);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
465
466
467
468
469
470
471
  }
  
  static int
  ch_exchange(scsi_changer *ch, u_int trans, u_int src,
  	    u_int dest1, u_int dest2, int rotate1, int rotate2)
  {
  	u_char  cmd[12];
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
472

87da32356   Joe Perches   drivers/scsi/ch.c...
473
474
  	DPRINTK("exchange: 0x%x => 0x%x => 0x%x
  ",
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
475
476
477
478
479
  		src,dest1,dest2);
  	if (0 == trans)
  		trans = ch->firsts[CHET_MT];
  	memset(cmd,0,sizeof(cmd));
  	cmd[0]  = EXCHANGE_MEDIUM;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
480
  	cmd[1]  = (ch->device->lun & 0x7) << 5;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
481
482
483
484
485
486
487
488
489
  	cmd[2]  = (trans >> 8) & 0xff;
  	cmd[3]  =  trans       & 0xff;
  	cmd[4]  = (src   >> 8) & 0xff;
  	cmd[5]  =  src         & 0xff;
  	cmd[6]  = (dest1 >> 8) & 0xff;
  	cmd[7]  =  dest1       & 0xff;
  	cmd[8]  = (dest2 >> 8) & 0xff;
  	cmd[9]  =  dest2       & 0xff;
  	cmd[10] = (rotate1 ? 1 : 0) | (rotate2 ? 2 : 0);
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
490

a9a47bf58   Hannes Reinecke   scsi: repurpose t...
491
  	return ch_do_scsi(ch, cmd, 12, NULL, 0, DMA_NONE);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
  }
  
  static void
  ch_check_voltag(char *tag)
  {
  	int i;
  
  	for (i = 0; i < 32; i++) {
  		/* restrict to ascii */
  		if (tag[i] >= 0x7f || tag[i] < 0x20)
  			tag[i] = ' ';
  		/* don't allow search wildcards */
  		if (tag[i] == '?' ||
  		    tag[i] == '*')
  			tag[i] = ' ';
  	}
  }
  
  static int
  ch_set_voltag(scsi_changer *ch, u_int elem,
  	      int alternate, int clear, u_char *tag)
  {
  	u_char  cmd[12];
  	u_char  *buffer;
  	int result;
4530a1696   vignesh.babu@wipro.com   [SCSI] ch: kmallo...
517
  	buffer = kzalloc(512, GFP_KERNEL);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
518
519
  	if (!buffer)
  		return -ENOMEM;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
520

87da32356   Joe Perches   drivers/scsi/ch.c...
521
522
  	DPRINTK("%s %s voltag: 0x%x => \"%s\"
  ",
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
523
524
525
526
527
  		clear     ? "clear"     : "set",
  		alternate ? "alternate" : "primary",
  		elem, tag);
  	memset(cmd,0,sizeof(cmd));
  	cmd[0]  = SEND_VOLUME_TAG;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
528
  	cmd[1] = ((ch->device->lun & 0x7) << 5) |
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
529
530
531
532
533
534
  		ch_elem_to_typecode(ch,elem);
  	cmd[2] = (elem >> 8) & 0xff;
  	cmd[3] = elem        & 0xff;
  	cmd[5] = clear
  		? (alternate ? 0x0d : 0x0c)
  		: (alternate ? 0x0b : 0x0a);
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
535

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
536
537
538
539
  	cmd[9] = 255;
  
  	memcpy(buffer,tag,32);
  	ch_check_voltag(buffer);
a9a47bf58   Hannes Reinecke   scsi: repurpose t...
540
  	result = ch_do_scsi(ch, cmd, 12, buffer, 256, DMA_TO_DEVICE);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
541
542
543
  	kfree(buffer);
  	return result;
  }
fe08ac317   Al Viro   [PATCH] __user an...
544
  static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
545
546
547
548
  {
  	int retval = 0;
  	u_char data[16];
  	unsigned int i;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
549

0b9506723   Arjan van de Ven   [SCSI] turn most ...
550
  	mutex_lock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
551
552
553
554
555
556
557
558
  	for (i = 0; i < ch->counts[type]; i++) {
  		if (0 != ch_read_element_status
  		    (ch, ch->firsts[type]+i,data)) {
  			retval = -EIO;
  			break;
  		}
  		put_user(data[2], dest+i);
  		if (data[2] & CESTATUS_EXCEPT)
87da32356   Joe Perches   drivers/scsi/ch.c...
559
560
  			VPRINTK(KERN_INFO, "element 0x%x: asc=0x%x, ascq=0x%x
  ",
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
561
562
563
564
565
566
567
  				ch->firsts[type]+i,
  				(int)data[4],(int)data[5]);
  		retval = ch_read_element_status
  			(ch, ch->firsts[type]+i,data);
  		if (0 != retval)
  			break;
  	}
0b9506723   Arjan van de Ven   [SCSI] turn most ...
568
  	mutex_unlock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
  	return retval;
  }
  
  /* ------------------------------------------------------------------------ */
  
  static int
  ch_release(struct inode *inode, struct file *file)
  {
  	scsi_changer *ch = file->private_data;
  
  	scsi_device_put(ch->device);
  	file->private_data = NULL;
  	return 0;
  }
  
  static int
  ch_open(struct inode *inode, struct file *file)
  {
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
587
  	scsi_changer *ch;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
588
  	int minor = iminor(inode);
c45d15d24   Arnd Bergmann   scsi: autoconvert...
589
  	mutex_lock(&ch_mutex);
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
590
591
  	spin_lock(&ch_index_lock);
  	ch = idr_find(&ch_index_idr, minor);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
592
  	if (NULL == ch || scsi_device_get(ch->device)) {
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
593
  		spin_unlock(&ch_index_lock);
c45d15d24   Arnd Bergmann   scsi: autoconvert...
594
  		mutex_unlock(&ch_mutex);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
595
596
  		return -ENXIO;
  	}
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
597
  	spin_unlock(&ch_index_lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
598
599
  
  	file->private_data = ch;
c45d15d24   Arnd Bergmann   scsi: autoconvert...
600
  	mutex_unlock(&ch_mutex);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
601
602
603
604
605
606
607
608
609
610
  	return 0;
  }
  
  static int
  ch_checkrange(scsi_changer *ch, unsigned int type, unsigned int unit)
  {
  	if (type >= CH_TYPES  ||  unit >= ch->counts[type])
  		return -1;
  	return 0;
  }
f7fea185d   Mathieu Segaud   [SCSI] ch: Conver...
611
  static long ch_ioctl(struct file *file,
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
612
613
614
615
  		    unsigned int cmd, unsigned long arg)
  {
  	scsi_changer *ch = file->private_data;
  	int retval;
fe08ac317   Al Viro   [PATCH] __user an...
616
  	void __user *argp = (void __user *)arg;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
617

906d15fbd   Christoph Hellwig   scsi: split scsi_...
618
619
620
621
  	retval = scsi_ioctl_block_when_processing_errors(ch->device, cmd,
  			file->f_flags & O_NDELAY);
  	if (retval)
  		return retval;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
622
623
624
625
  	switch (cmd) {
  	case CHIOGPARAMS:
  	{
  		struct changer_params params;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
626

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
627
628
629
630
631
  		params.cp_curpicker = 0;
  		params.cp_npickers  = ch->counts[CHET_MT];
  		params.cp_nslots    = ch->counts[CHET_ST];
  		params.cp_nportals  = ch->counts[CHET_IE];
  		params.cp_ndrives   = ch->counts[CHET_DT];
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
632

fe08ac317   Al Viro   [PATCH] __user an...
633
  		if (copy_to_user(argp, &params, sizeof(params)))
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
  			return -EFAULT;
  		return 0;
  	}
  	case CHIOGVPARAMS:
  	{
  		struct changer_vendor_params vparams;
  
  		memset(&vparams,0,sizeof(vparams));
  		if (ch->counts[CHET_V1]) {
  			vparams.cvp_n1  = ch->counts[CHET_V1];
  			strncpy(vparams.cvp_label1,vendor_labels[0],16);
  		}
  		if (ch->counts[CHET_V2]) {
  			vparams.cvp_n2  = ch->counts[CHET_V2];
  			strncpy(vparams.cvp_label2,vendor_labels[1],16);
  		}
  		if (ch->counts[CHET_V3]) {
  			vparams.cvp_n3  = ch->counts[CHET_V3];
  			strncpy(vparams.cvp_label3,vendor_labels[2],16);
  		}
  		if (ch->counts[CHET_V4]) {
  			vparams.cvp_n4  = ch->counts[CHET_V4];
  			strncpy(vparams.cvp_label4,vendor_labels[3],16);
  		}
fe08ac317   Al Viro   [PATCH] __user an...
658
  		if (copy_to_user(argp, &vparams, sizeof(vparams)))
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
659
660
661
  			return -EFAULT;
  		return 0;
  	}
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
662

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
663
664
665
  	case CHIOPOSITION:
  	{
  		struct changer_position pos;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
666

fe08ac317   Al Viro   [PATCH] __user an...
667
  		if (copy_from_user(&pos, argp, sizeof (pos)))
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
668
669
670
  			return -EFAULT;
  
  		if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) {
87da32356   Joe Perches   drivers/scsi/ch.c...
671
672
  			DPRINTK("CHIOPOSITION: invalid parameter
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
673
674
  			return -EBADSLT;
  		}
0b9506723   Arjan van de Ven   [SCSI] turn most ...
675
  		mutex_lock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
676
677
678
  		retval = ch_position(ch,0,
  				     ch->firsts[pos.cp_type] + pos.cp_unit,
  				     pos.cp_flags & CP_INVERT);
0b9506723   Arjan van de Ven   [SCSI] turn most ...
679
  		mutex_unlock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
680
681
  		return retval;
  	}
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
682

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
683
684
685
  	case CHIOMOVE:
  	{
  		struct changer_move mv;
fe08ac317   Al Viro   [PATCH] __user an...
686
  		if (copy_from_user(&mv, argp, sizeof (mv)))
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
687
688
689
690
  			return -EFAULT;
  
  		if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) ||
  		    0 != ch_checkrange(ch, mv.cm_totype,   mv.cm_tounit  )) {
87da32356   Joe Perches   drivers/scsi/ch.c...
691
692
  			DPRINTK("CHIOMOVE: invalid parameter
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
693
694
  			return -EBADSLT;
  		}
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
695

0b9506723   Arjan van de Ven   [SCSI] turn most ...
696
  		mutex_lock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
697
698
699
700
  		retval = ch_move(ch,0,
  				 ch->firsts[mv.cm_fromtype] + mv.cm_fromunit,
  				 ch->firsts[mv.cm_totype]   + mv.cm_tounit,
  				 mv.cm_flags & CM_INVERT);
0b9506723   Arjan van de Ven   [SCSI] turn most ...
701
  		mutex_unlock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
702
703
704
705
706
707
  		return retval;
  	}
  
  	case CHIOEXCHANGE:
  	{
  		struct changer_exchange mv;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
708

fe08ac317   Al Viro   [PATCH] __user an...
709
  		if (copy_from_user(&mv, argp, sizeof (mv)))
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
710
711
712
713
714
  			return -EFAULT;
  
  		if (0 != ch_checkrange(ch, mv.ce_srctype,  mv.ce_srcunit ) ||
  		    0 != ch_checkrange(ch, mv.ce_fdsttype, mv.ce_fdstunit) ||
  		    0 != ch_checkrange(ch, mv.ce_sdsttype, mv.ce_sdstunit)) {
87da32356   Joe Perches   drivers/scsi/ch.c...
715
716
  			DPRINTK("CHIOEXCHANGE: invalid parameter
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
717
718
  			return -EBADSLT;
  		}
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
719

0b9506723   Arjan van de Ven   [SCSI] turn most ...
720
  		mutex_lock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
721
722
723
724
725
726
  		retval = ch_exchange
  			(ch,0,
  			 ch->firsts[mv.ce_srctype]  + mv.ce_srcunit,
  			 ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit,
  			 ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit,
  			 mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2);
0b9506723   Arjan van de Ven   [SCSI] turn most ...
727
  		mutex_unlock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
728
729
730
731
732
733
  		return retval;
  	}
  
  	case CHIOGSTATUS:
  	{
  		struct changer_element_status ces;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
734

fe08ac317   Al Viro   [PATCH] __user an...
735
  		if (copy_from_user(&ces, argp, sizeof (ces)))
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
736
737
738
739
740
741
742
743
744
745
  			return -EFAULT;
  		if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES)
  			return -EINVAL;
  
  		return ch_gstatus(ch, ces.ces_type, ces.ces_data);
  	}
  
  	case CHIOGELEM:
  	{
  		struct changer_get_element cge;
d70d4667e   Harvey Harrison   [SCSI] ch: fix sp...
746
747
  		u_char ch_cmd[12];
  		u_char *buffer;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
748
749
  		unsigned int elem;
  		int     result,i;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
750

fe08ac317   Al Viro   [PATCH] __user an...
751
  		if (copy_from_user(&cge, argp, sizeof (cge)))
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
752
753
754
755
756
  			return -EFAULT;
  
  		if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit))
  			return -EINVAL;
  		elem = ch->firsts[cge.cge_type] + cge.cge_unit;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
757

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
758
759
760
  		buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
  		if (!buffer)
  			return -ENOMEM;
0b9506723   Arjan van de Ven   [SCSI] turn most ...
761
  		mutex_lock(&ch->lock);
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
762

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
763
  	voltag_retry:
d70d4667e   Harvey Harrison   [SCSI] ch: fix sp...
764
765
  		memset(ch_cmd, 0, sizeof(ch_cmd));
  		ch_cmd[0] = READ_ELEMENT_STATUS;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
766
  		ch_cmd[1] = ((ch->device->lun & 0x7) << 5) |
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
767
768
  			(ch->voltags ? 0x10 : 0) |
  			ch_elem_to_typecode(ch,elem);
d70d4667e   Harvey Harrison   [SCSI] ch: fix sp...
769
770
771
772
  		ch_cmd[2] = (elem >> 8) & 0xff;
  		ch_cmd[3] = elem        & 0xff;
  		ch_cmd[5] = 1;
  		ch_cmd[9] = 255;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
773

a9a47bf58   Hannes Reinecke   scsi: repurpose t...
774
775
  		result = ch_do_scsi(ch, ch_cmd, 12,
  				    buffer, 256, DMA_FROM_DEVICE);
d70d4667e   Harvey Harrison   [SCSI] ch: fix sp...
776
  		if (!result) {
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
  			cge.cge_status = buffer[18];
  			cge.cge_flags = 0;
  			if (buffer[18] & CESTATUS_EXCEPT) {
  				cge.cge_errno = EIO;
  			}
  			if (buffer[25] & 0x80) {
  				cge.cge_flags |= CGE_SRC;
  				if (buffer[25] & 0x40)
  					cge.cge_flags |= CGE_INVERT;
  				elem = (buffer[26]<<8) | buffer[27];
  				for (i = 0; i < 4; i++) {
  					if (elem >= ch->firsts[i] &&
  					    elem <  ch->firsts[i] + ch->counts[i]) {
  						cge.cge_srctype = i;
  						cge.cge_srcunit = elem-ch->firsts[i];
  					}
  				}
  			}
  			if ((buffer[22] & 0x30) == 0x30) {
  				cge.cge_flags |= CGE_IDLUN;
  				cge.cge_id  = buffer[23];
  				cge.cge_lun = buffer[22] & 7;
  			}
  			if (buffer[9] & 0x80) {
  				cge.cge_flags |= CGE_PVOLTAG;
  				memcpy(cge.cge_pvoltag,buffer+28,36);
  			}
  			if (buffer[9] & 0x40) {
  				cge.cge_flags |= CGE_AVOLTAG;
  				memcpy(cge.cge_avoltag,buffer+64,36);
  			}
  		} else if (ch->voltags) {
  			ch->voltags = 0;
87da32356   Joe Perches   drivers/scsi/ch.c...
810
811
  			VPRINTK(KERN_INFO, "device has no volume tag support
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
812
813
814
  			goto voltag_retry;
  		}
  		kfree(buffer);
0b9506723   Arjan van de Ven   [SCSI] turn most ...
815
  		mutex_unlock(&ch->lock);
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
816

fe08ac317   Al Viro   [PATCH] __user an...
817
  		if (copy_to_user(argp, &cge, sizeof (cge)))
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
818
819
820
821
822
823
  			return -EFAULT;
  		return result;
  	}
  
  	case CHIOINITELEM:
  	{
0b9506723   Arjan van de Ven   [SCSI] turn most ...
824
  		mutex_lock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
825
  		retval = ch_init_elem(ch);
0b9506723   Arjan van de Ven   [SCSI] turn most ...
826
  		mutex_unlock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
827
828
  		return retval;
  	}
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
829

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
830
831
832
833
  	case CHIOSVOLTAG:
  	{
  		struct changer_set_voltag csv;
  		int elem;
fe08ac317   Al Viro   [PATCH] __user an...
834
  		if (copy_from_user(&csv, argp, sizeof(csv)))
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
835
836
837
  			return -EFAULT;
  
  		if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) {
87da32356   Joe Perches   drivers/scsi/ch.c...
838
839
  			DPRINTK("CHIOSVOLTAG: invalid parameter
  ");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
840
841
842
  			return -EBADSLT;
  		}
  		elem = ch->firsts[csv.csv_type] + csv.csv_unit;
0b9506723   Arjan van de Ven   [SCSI] turn most ...
843
  		mutex_lock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
844
845
846
847
  		retval = ch_set_voltag(ch, elem,
  				       csv.csv_flags & CSV_AVOLTAG,
  				       csv.csv_flags & CSV_CLEARTAG,
  				       csv.csv_voltag);
0b9506723   Arjan van de Ven   [SCSI] turn most ...
848
  		mutex_unlock(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
849
850
851
852
  		return retval;
  	}
  
  	default:
fe08ac317   Al Viro   [PATCH] __user an...
853
  		return scsi_ioctl(ch->device, cmd, argp);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
  
  	}
  }
  
  #ifdef CONFIG_COMPAT
  
  struct changer_element_status32 {
  	int		ces_type;
  	compat_uptr_t	ces_data;
  };
  #define CHIOGSTATUS32  _IOW('c', 8,struct changer_element_status32)
  
  static long ch_ioctl_compat(struct file * file,
  			    unsigned int cmd, unsigned long arg)
  {
  	scsi_changer *ch = file->private_data;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
870

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
871
872
873
874
875
876
877
878
879
880
  	switch (cmd) {
  	case CHIOGPARAMS:
  	case CHIOGVPARAMS:
  	case CHIOPOSITION:
  	case CHIOMOVE:
  	case CHIOEXCHANGE:
  	case CHIOGELEM:
  	case CHIOINITELEM:
  	case CHIOSVOLTAG:
  		/* compatible */
f7fea185d   Mathieu Segaud   [SCSI] ch: Conver...
881
  		return ch_ioctl(file, cmd, arg);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
882
883
884
  	case CHIOGSTATUS32:
  	{
  		struct changer_element_status32 ces32;
fe08ac317   Al Viro   [PATCH] __user an...
885
  		unsigned char __user *data;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
886

fe08ac317   Al Viro   [PATCH] __user an...
887
  		if (copy_from_user(&ces32, (void __user *)arg, sizeof (ces32)))
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
  			return -EFAULT;
  		if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
  			return -EINVAL;
  
  		data = compat_ptr(ces32.ces_data);
  		return ch_gstatus(ch, ces32.ces_type, data);
  	}
  	default:
  		// return scsi_ioctl_compat(ch->device, cmd, (void*)arg);
  		return -ENOIOCTLCMD;
  
  	}
  }
  #endif
  
  /* ------------------------------------------------------------------------ */
  
  static int ch_probe(struct device *dev)
  {
  	struct scsi_device *sd = to_scsi_device(dev);
ee959b00c   Tony Jones   SCSI: convert str...
908
  	struct device *class_dev;
b98c52b57   Tejun Heo   scsi: convert to ...
909
  	int ret;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
910
  	scsi_changer *ch;
a3d2c2e8f   FUJITA Tomonori   [SCSI] ch: handle...
911

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
912
913
  	if (sd->type != TYPE_MEDIUM_CHANGER)
  		return -ENODEV;
a3d2c2e8f   FUJITA Tomonori   [SCSI] ch: handle...
914

4530a1696   vignesh.babu@wipro.com   [SCSI] ch: kmallo...
915
  	ch = kzalloc(sizeof(*ch), GFP_KERNEL);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
916
917
  	if (NULL == ch)
  		return -ENOMEM;
b98c52b57   Tejun Heo   scsi: convert to ...
918
  	idr_preload(GFP_KERNEL);
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
919
  	spin_lock(&ch_index_lock);
b98c52b57   Tejun Heo   scsi: convert to ...
920
  	ret = idr_alloc(&ch_index_idr, ch, 0, CH_MAX_DEVS + 1, GFP_NOWAIT);
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
921
  	spin_unlock(&ch_index_lock);
b98c52b57   Tejun Heo   scsi: convert to ...
922
  	idr_preload_end();
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
923

b98c52b57   Tejun Heo   scsi: convert to ...
924
925
926
  	if (ret < 0) {
  		if (ret == -ENOSPC)
  			ret = -ENODEV;
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
927
  		goto free_ch;
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
928
  	}
b98c52b57   Tejun Heo   scsi: convert to ...
929
  	ch->minor = ret;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
930
  	sprintf(ch->name,"ch%d",ch->minor);
a3d2c2e8f   FUJITA Tomonori   [SCSI] ch: handle...
931

d73a1a674   Greg Kroah-Hartman   device create: sc...
932
933
934
  	class_dev = device_create(ch_sysfs_class, dev,
  				  MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch,
  				  "s%s", ch->name);
a3d2c2e8f   FUJITA Tomonori   [SCSI] ch: handle...
935
  	if (IS_ERR(class_dev)) {
28c31729c   Hannes Reinecke   scsi: Implement c...
936
937
938
  		sdev_printk(KERN_WARNING, sd, "ch%d: device_create failed
  ",
  			    ch->minor);
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
939
940
  		ret = PTR_ERR(class_dev);
  		goto remove_idr;
a3d2c2e8f   FUJITA Tomonori   [SCSI] ch: handle...
941
  	}
0b9506723   Arjan van de Ven   [SCSI] turn most ...
942
  	mutex_init(&ch->lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
943
944
945
946
  	ch->device = sd;
  	ch_readconfig(ch);
  	if (init)
  		ch_init_elem(ch);
3d164fb09   FUJITA Tomonori   [SCSI] ch: fix ch...
947
  	dev_set_drvdata(dev, ch);
017560fca   Jeff Garzik   [SCSI] use sfoo_p...
948
949
  	sdev_printk(KERN_INFO, sd, "Attached scsi changer %s
  ", ch->name);
a3d2c2e8f   FUJITA Tomonori   [SCSI] ch: handle...
950

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
951
  	return 0;
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
952
  remove_idr:
b98c52b57   Tejun Heo   scsi: convert to ...
953
  	idr_remove(&ch_index_idr, ch->minor);
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
954
955
956
  free_ch:
  	kfree(ch);
  	return ret;
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
957
958
959
960
  }
  
  static int ch_remove(struct device *dev)
  {
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
961
  	scsi_changer *ch = dev_get_drvdata(dev);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
962

da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
963
964
965
  	spin_lock(&ch_index_lock);
  	idr_remove(&ch_index_idr, ch->minor);
  	spin_unlock(&ch_index_lock);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
966

ee959b00c   Tony Jones   SCSI: convert str...
967
  	device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
968
969
  	kfree(ch->dt);
  	kfree(ch);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
970
971
  	return 0;
  }
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
972
  static struct scsi_driver ch_template = {
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
973
974
  	.gendrv     	= {
  		.name	= "ch",
3af6b3526   Christoph Hellwig   scsi: remove scsi...
975
  		.owner	= THIS_MODULE,
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
976
977
978
979
980
981
982
983
984
985
986
987
988
  		.probe  = ch_probe,
  		.remove = ch_remove,
  	},
  };
  
  static const struct file_operations changer_fops = {
  	.owner		= THIS_MODULE,
  	.open		= ch_open,
  	.release	= ch_release,
  	.unlocked_ioctl	= ch_ioctl,
  #ifdef CONFIG_COMPAT
  	.compat_ioctl	= ch_ioctl_compat,
  #endif
6038f373a   Arnd Bergmann   llseek: automatic...
989
  	.llseek		= noop_llseek,
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
990
  };
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
991
992
993
  static int __init init_ch_module(void)
  {
  	int rc;
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
994

daa6eda65   Gerd Knorr   [SCSI] add scsi c...
995
996
  	printk(KERN_INFO "SCSI Media Changer driver v" VERSION " 
  ");
21feb5ccd   Gerd Knorr   [SCSI] convert sc...
997
          ch_sysfs_class = class_create(THIS_MODULE, "scsi_changer");
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
          if (IS_ERR(ch_sysfs_class)) {
  		rc = PTR_ERR(ch_sysfs_class);
  		return rc;
          }
  	rc = register_chrdev(SCSI_CHANGER_MAJOR,"ch",&changer_fops);
  	if (rc < 0) {
  		printk("Unable to get major %d for SCSI-Changer
  ",
  		       SCSI_CHANGER_MAJOR);
  		goto fail1;
  	}
  	rc = scsi_register_driver(&ch_template.gendrv);
  	if (rc < 0)
  		goto fail2;
  	return 0;
  
   fail2:
  	unregister_chrdev(SCSI_CHANGER_MAJOR, "ch");
   fail1:
21feb5ccd   Gerd Knorr   [SCSI] convert sc...
1017
  	class_destroy(ch_sysfs_class);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
1018
1019
  	return rc;
  }
5aa22af3d   FUJITA Tomonori   [SCSI] ch: remove...
1020
  static void __exit exit_ch_module(void)
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
1021
1022
1023
  {
  	scsi_unregister_driver(&ch_template.gendrv);
  	unregister_chrdev(SCSI_CHANGER_MAJOR, "ch");
21feb5ccd   Gerd Knorr   [SCSI] convert sc...
1024
  	class_destroy(ch_sysfs_class);
da707c54c   FUJITA Tomonori   [SCSI] ch: fix de...
1025
  	idr_destroy(&ch_index_idr);
daa6eda65   Gerd Knorr   [SCSI] add scsi c...
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
  }
  
  module_init(init_ch_module);
  module_exit(exit_ch_module);
  
  /*
   * Local variables:
   * c-basic-offset: 8
   * End:
   */