ch.c (33ca8a53f262b4af40611bea331b8c87d133af72) ch.c (f42cf8d6a3ec934551ac0f20f4654dccb11fa30d)
1/*
2 * SCSI Media Changer device driver for Linux 2.6
3 *
4 * (c) 1996-2003 Gerd Knorr <kraxel@bytesex.org>
5 *
6 */
7
8#define VERSION "0.25"

--- 71 unchanged lines hidden (view full) ---

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...) \
1/*
2 * SCSI Media Changer device driver for Linux 2.6
3 *
4 * (c) 1996-2003 Gerd Knorr <kraxel@bytesex.org>
5 *
6 */
7
8#define VERSION "0.25"

--- 71 unchanged lines hidden (view full) ---

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)
88 sdev_printk(prefix, (ch)->device, "[%s] " fmt, \
89 (ch)->name, ##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 { \

--- 80 unchanged lines hidden (view full) ---

177 }
178 }
179 if (errno == 0)
180 errno = -EIO;
181 return errno;
182}
183
184static int
90
91#define DPRINTK(fmt, arg...) \
92do { \
93 if (debug) \
94 ch_printk(KERN_DEBUG, ch, fmt, ##arg); \
95} while (0)
96#define VPRINTK(level, fmt, arg...) \
97do { \

--- 80 unchanged lines hidden (view full) ---

178 }
179 }
180 if (errno == 0)
181 errno = -EIO;
182 return errno;
183}
184
185static int
185ch_do_scsi(scsi_changer *ch, unsigned char *cmd, int cmd_len,
186ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
186 void *buffer, unsigned buflength,
187 enum dma_data_direction direction)
188{
189 int errno, retries = 0, timeout, result;
190 struct scsi_sense_hdr sshdr;
191
192 timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS)
193 ? timeout_init : timeout_move;
194
195 retry:
196 errno = 0;
187 void *buffer, unsigned buflength,
188 enum dma_data_direction direction)
189{
190 int errno, retries = 0, timeout, result;
191 struct scsi_sense_hdr sshdr;
192
193 timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS)
194 ? timeout_init : timeout_move;
195
196 retry:
197 errno = 0;
198 if (debug) {
199 DPRINTK("command: ");
200 __scsi_print_command(cmd);
201 }
202
197 result = scsi_execute_req(ch->device, cmd, direction, buffer,
198 buflength, &sshdr, timeout * HZ,
199 MAX_RETRIES, NULL);
200
203 result = scsi_execute_req(ch->device, cmd, direction, buffer,
204 buflength, &sshdr, timeout * HZ,
205 MAX_RETRIES, NULL);
206
207 DPRINTK("result: 0x%x\n",result);
201 if (driver_byte(result) & DRIVER_SENSE) {
202 if (debug)
208 if (driver_byte(result) & DRIVER_SENSE) {
209 if (debug)
203 scsi_print_sense_hdr(ch->device, ch->name, &sshdr);
210 scsi_print_sense_hdr(ch->name, &sshdr);
204 errno = ch_find_errno(&sshdr);
205
206 switch(sshdr.sense_key) {
207 case UNIT_ATTENTION:
208 ch->unit_attention = 1;
209 if (retries++ < 3)
210 goto retry;
211 break;

--- 34 unchanged lines hidden (view full) ---

246 cmd[0] = READ_ELEMENT_STATUS;
247 cmd[1] = ((ch->device->lun & 0x7) << 5) |
248 (ch->voltags ? 0x10 : 0) |
249 ch_elem_to_typecode(ch,elem);
250 cmd[2] = (elem >> 8) & 0xff;
251 cmd[3] = elem & 0xff;
252 cmd[5] = 1;
253 cmd[9] = 255;
211 errno = ch_find_errno(&sshdr);
212
213 switch(sshdr.sense_key) {
214 case UNIT_ATTENTION:
215 ch->unit_attention = 1;
216 if (retries++ < 3)
217 goto retry;
218 break;

--- 34 unchanged lines hidden (view full) ---

253 cmd[0] = READ_ELEMENT_STATUS;
254 cmd[1] = ((ch->device->lun & 0x7) << 5) |
255 (ch->voltags ? 0x10 : 0) |
256 ch_elem_to_typecode(ch,elem);
257 cmd[2] = (elem >> 8) & 0xff;
258 cmd[3] = elem & 0xff;
259 cmd[5] = 1;
260 cmd[9] = 255;
254 if (0 == (result = ch_do_scsi(ch, cmd, 12,
255 buffer, 256, DMA_FROM_DEVICE))) {
261 if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) {
256 if (((buffer[16] << 8) | buffer[17]) != elem) {
257 DPRINTK("asked for element 0x%02x, got 0x%02x\n",
258 elem,(buffer[16] << 8) | buffer[17]);
259 kfree(buffer);
260 return -EIO;
261 }
262 memcpy(data,buffer+16,16);
263 } else {

--- 13 unchanged lines hidden (view full) ---

277{
278 int err;
279 u_char cmd[6];
280
281 VPRINTK(KERN_INFO, "INITIALIZE ELEMENT STATUS, may take some time ...\n");
282 memset(cmd,0,sizeof(cmd));
283 cmd[0] = INITIALIZE_ELEMENT_STATUS;
284 cmd[1] = (ch->device->lun & 0x7) << 5;
262 if (((buffer[16] << 8) | buffer[17]) != elem) {
263 DPRINTK("asked for element 0x%02x, got 0x%02x\n",
264 elem,(buffer[16] << 8) | buffer[17]);
265 kfree(buffer);
266 return -EIO;
267 }
268 memcpy(data,buffer+16,16);
269 } else {

--- 13 unchanged lines hidden (view full) ---

283{
284 int err;
285 u_char cmd[6];
286
287 VPRINTK(KERN_INFO, "INITIALIZE ELEMENT STATUS, may take some time ...\n");
288 memset(cmd,0,sizeof(cmd));
289 cmd[0] = INITIALIZE_ELEMENT_STATUS;
290 cmd[1] = (ch->device->lun & 0x7) << 5;
285 err = ch_do_scsi(ch, cmd, 6, NULL, 0, DMA_NONE);
291 err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE);
286 VPRINTK(KERN_INFO, "... finished\n");
287 return err;
288}
289
290static int
291ch_readconfig(scsi_changer *ch)
292{
293 u_char cmd[10], data[16];

--- 5 unchanged lines hidden (view full) ---

299 if (!buffer)
300 return -ENOMEM;
301
302 memset(cmd,0,sizeof(cmd));
303 cmd[0] = MODE_SENSE;
304 cmd[1] = (ch->device->lun & 0x7) << 5;
305 cmd[2] = 0x1d;
306 cmd[4] = 255;
292 VPRINTK(KERN_INFO, "... finished\n");
293 return err;
294}
295
296static int
297ch_readconfig(scsi_changer *ch)
298{
299 u_char cmd[10], data[16];

--- 5 unchanged lines hidden (view full) ---

305 if (!buffer)
306 return -ENOMEM;
307
308 memset(cmd,0,sizeof(cmd));
309 cmd[0] = MODE_SENSE;
310 cmd[1] = (ch->device->lun & 0x7) << 5;
311 cmd[2] = 0x1d;
312 cmd[4] = 255;
307 result = ch_do_scsi(ch, cmd, 10, buffer, 255, DMA_FROM_DEVICE);
313 result = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE);
308 if (0 != result) {
309 cmd[1] |= (1<<3);
314 if (0 != result) {
315 cmd[1] |= (1<<3);
310 result = ch_do_scsi(ch, cmd, 10, buffer, 255, DMA_FROM_DEVICE);
316 result = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE);
311 }
312 if (0 == result) {
313 ch->firsts[CHET_MT] =
314 (buffer[buffer[3]+ 6] << 8) | buffer[buffer[3]+ 7];
315 ch->counts[CHET_MT] =
316 (buffer[buffer[3]+ 8] << 8) | buffer[buffer[3]+ 9];
317 ch->firsts[CHET_ST] =
318 (buffer[buffer[3]+10] << 8) | buffer[buffer[3]+11];

--- 15 unchanged lines hidden (view full) ---

334 ch->counts[CHET_ST]);
335 VPRINTK(KERN_INFO, "type #3 (ie): 0x%x+%d [import/export]\n",
336 ch->firsts[CHET_IE],
337 ch->counts[CHET_IE]);
338 VPRINTK(KERN_INFO, "type #4 (dt): 0x%x+%d [data transfer]\n",
339 ch->firsts[CHET_DT],
340 ch->counts[CHET_DT]);
341 } else {
317 }
318 if (0 == result) {
319 ch->firsts[CHET_MT] =
320 (buffer[buffer[3]+ 6] << 8) | buffer[buffer[3]+ 7];
321 ch->counts[CHET_MT] =
322 (buffer[buffer[3]+ 8] << 8) | buffer[buffer[3]+ 9];
323 ch->firsts[CHET_ST] =
324 (buffer[buffer[3]+10] << 8) | buffer[buffer[3]+11];

--- 15 unchanged lines hidden (view full) ---

340 ch->counts[CHET_ST]);
341 VPRINTK(KERN_INFO, "type #3 (ie): 0x%x+%d [import/export]\n",
342 ch->firsts[CHET_IE],
343 ch->counts[CHET_IE]);
344 VPRINTK(KERN_INFO, "type #4 (dt): 0x%x+%d [data transfer]\n",
345 ch->firsts[CHET_DT],
346 ch->counts[CHET_DT]);
347 } else {
342 VPRINTK(KERN_INFO, "reading element address assigment page failed!\n");
348 VPRINTK(KERN_INFO, "reading element address assignment page failed!\n");
343 }
344
345 /* vendor specific element types */
346 for (i = 0; i < 4; i++) {
347 if (0 == vendor_counts[i])
348 continue;
349 if (NULL == vendor_labels[i])
350 continue;

--- 76 unchanged lines hidden (view full) ---

427 memset(cmd,0,sizeof(cmd));
428 cmd[0] = POSITION_TO_ELEMENT;
429 cmd[1] = (ch->device->lun & 0x7) << 5;
430 cmd[2] = (trans >> 8) & 0xff;
431 cmd[3] = trans & 0xff;
432 cmd[4] = (elem >> 8) & 0xff;
433 cmd[5] = elem & 0xff;
434 cmd[8] = rotate ? 1 : 0;
349 }
350
351 /* vendor specific element types */
352 for (i = 0; i < 4; i++) {
353 if (0 == vendor_counts[i])
354 continue;
355 if (NULL == vendor_labels[i])
356 continue;

--- 76 unchanged lines hidden (view full) ---

433 memset(cmd,0,sizeof(cmd));
434 cmd[0] = POSITION_TO_ELEMENT;
435 cmd[1] = (ch->device->lun & 0x7) << 5;
436 cmd[2] = (trans >> 8) & 0xff;
437 cmd[3] = trans & 0xff;
438 cmd[4] = (elem >> 8) & 0xff;
439 cmd[5] = elem & 0xff;
440 cmd[8] = rotate ? 1 : 0;
435 return ch_do_scsi(ch, cmd, 10, NULL, 0, DMA_NONE);
441 return ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE);
436}
437
438static int
439ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate)
440{
441 u_char cmd[12];
442
443 DPRINTK("move: 0x%x => 0x%x\n",src,dest);

--- 4 unchanged lines hidden (view full) ---

448 cmd[1] = (ch->device->lun & 0x7) << 5;
449 cmd[2] = (trans >> 8) & 0xff;
450 cmd[3] = trans & 0xff;
451 cmd[4] = (src >> 8) & 0xff;
452 cmd[5] = src & 0xff;
453 cmd[6] = (dest >> 8) & 0xff;
454 cmd[7] = dest & 0xff;
455 cmd[10] = rotate ? 1 : 0;
442}
443
444static int
445ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate)
446{
447 u_char cmd[12];
448
449 DPRINTK("move: 0x%x => 0x%x\n",src,dest);

--- 4 unchanged lines hidden (view full) ---

454 cmd[1] = (ch->device->lun & 0x7) << 5;
455 cmd[2] = (trans >> 8) & 0xff;
456 cmd[3] = trans & 0xff;
457 cmd[4] = (src >> 8) & 0xff;
458 cmd[5] = src & 0xff;
459 cmd[6] = (dest >> 8) & 0xff;
460 cmd[7] = dest & 0xff;
461 cmd[10] = rotate ? 1 : 0;
456 return ch_do_scsi(ch, cmd, 12, NULL,0, DMA_NONE);
462 return ch_do_scsi(ch, cmd, NULL,0, DMA_NONE);
457}
458
459static int
460ch_exchange(scsi_changer *ch, u_int trans, u_int src,
461 u_int dest1, u_int dest2, int rotate1, int rotate2)
462{
463 u_char cmd[12];
464

--- 9 unchanged lines hidden (view full) ---

474 cmd[4] = (src >> 8) & 0xff;
475 cmd[5] = src & 0xff;
476 cmd[6] = (dest1 >> 8) & 0xff;
477 cmd[7] = dest1 & 0xff;
478 cmd[8] = (dest2 >> 8) & 0xff;
479 cmd[9] = dest2 & 0xff;
480 cmd[10] = (rotate1 ? 1 : 0) | (rotate2 ? 2 : 0);
481
463}
464
465static int
466ch_exchange(scsi_changer *ch, u_int trans, u_int src,
467 u_int dest1, u_int dest2, int rotate1, int rotate2)
468{
469 u_char cmd[12];
470

--- 9 unchanged lines hidden (view full) ---

480 cmd[4] = (src >> 8) & 0xff;
481 cmd[5] = src & 0xff;
482 cmd[6] = (dest1 >> 8) & 0xff;
483 cmd[7] = dest1 & 0xff;
484 cmd[8] = (dest2 >> 8) & 0xff;
485 cmd[9] = dest2 & 0xff;
486 cmd[10] = (rotate1 ? 1 : 0) | (rotate2 ? 2 : 0);
487
482 return ch_do_scsi(ch, cmd, 12, NULL, 0, DMA_NONE);
488 return ch_do_scsi(ch, cmd, NULL,0, DMA_NONE);
483}
484
485static void
486ch_check_voltag(char *tag)
487{
488 int i;
489
490 for (i = 0; i < 32; i++) {

--- 33 unchanged lines hidden (view full) ---

524 ? (alternate ? 0x0d : 0x0c)
525 : (alternate ? 0x0b : 0x0a);
526
527 cmd[9] = 255;
528
529 memcpy(buffer,tag,32);
530 ch_check_voltag(buffer);
531
489}
490
491static void
492ch_check_voltag(char *tag)
493{
494 int i;
495
496 for (i = 0; i < 32; i++) {

--- 33 unchanged lines hidden (view full) ---

530 ? (alternate ? 0x0d : 0x0c)
531 : (alternate ? 0x0b : 0x0a);
532
533 cmd[9] = 255;
534
535 memcpy(buffer,tag,32);
536 ch_check_voltag(buffer);
537
532 result = ch_do_scsi(ch, cmd, 12, buffer, 256, DMA_TO_DEVICE);
538 result = ch_do_scsi(ch, cmd, buffer, 256, DMA_TO_DEVICE);
533 kfree(buffer);
534 return result;
535}
536
537static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
538{
539 int retval = 0;
540 u_char data[16];

--- 64 unchanged lines hidden (view full) ---

605
606static long ch_ioctl(struct file *file,
607 unsigned int cmd, unsigned long arg)
608{
609 scsi_changer *ch = file->private_data;
610 int retval;
611 void __user *argp = (void __user *)arg;
612
539 kfree(buffer);
540 return result;
541}
542
543static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
544{
545 int retval = 0;
546 u_char data[16];

--- 64 unchanged lines hidden (view full) ---

611
612static long ch_ioctl(struct file *file,
613 unsigned int cmd, unsigned long arg)
614{
615 scsi_changer *ch = file->private_data;
616 int retval;
617 void __user *argp = (void __user *)arg;
618
613 retval = scsi_ioctl_block_when_processing_errors(ch->device, cmd,
614 file->f_flags & O_NDELAY);
615 if (retval)
616 return retval;
617
618 switch (cmd) {
619 case CHIOGPARAMS:
620 {
621 struct changer_params params;
622
623 params.cp_curpicker = 0;
624 params.cp_npickers = ch->counts[CHET_MT];
625 params.cp_nslots = ch->counts[CHET_ST];

--- 134 unchanged lines hidden (view full) ---

760 ch_cmd[1] = ((ch->device->lun & 0x7) << 5) |
761 (ch->voltags ? 0x10 : 0) |
762 ch_elem_to_typecode(ch,elem);
763 ch_cmd[2] = (elem >> 8) & 0xff;
764 ch_cmd[3] = elem & 0xff;
765 ch_cmd[5] = 1;
766 ch_cmd[9] = 255;
767
619 switch (cmd) {
620 case CHIOGPARAMS:
621 {
622 struct changer_params params;
623
624 params.cp_curpicker = 0;
625 params.cp_npickers = ch->counts[CHET_MT];
626 params.cp_nslots = ch->counts[CHET_ST];

--- 134 unchanged lines hidden (view full) ---

761 ch_cmd[1] = ((ch->device->lun & 0x7) << 5) |
762 (ch->voltags ? 0x10 : 0) |
763 ch_elem_to_typecode(ch,elem);
764 ch_cmd[2] = (elem >> 8) & 0xff;
765 ch_cmd[3] = elem & 0xff;
766 ch_cmd[5] = 1;
767 ch_cmd[9] = 255;
768
768 result = ch_do_scsi(ch, ch_cmd, 12,
769 buffer, 256, DMA_FROM_DEVICE);
769 result = ch_do_scsi(ch, ch_cmd, buffer, 256, DMA_FROM_DEVICE);
770 if (!result) {
771 cge.cge_status = buffer[18];
772 cge.cge_flags = 0;
773 if (buffer[18] & CESTATUS_EXCEPT) {
774 cge.cge_errno = EIO;
775 }
776 if (buffer[25] & 0x80) {
777 cge.cge_flags |= CGE_SRC;

--- 183 unchanged lines hidden (view full) ---

961
962 device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
963 kfree(ch->dt);
964 kfree(ch);
965 return 0;
966}
967
968static struct scsi_driver ch_template = {
770 if (!result) {
771 cge.cge_status = buffer[18];
772 cge.cge_flags = 0;
773 if (buffer[18] & CESTATUS_EXCEPT) {
774 cge.cge_errno = EIO;
775 }
776 if (buffer[25] & 0x80) {
777 cge.cge_flags |= CGE_SRC;

--- 183 unchanged lines hidden (view full) ---

961
962 device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
963 kfree(ch->dt);
964 kfree(ch);
965 return 0;
966}
967
968static struct scsi_driver ch_template = {
969 .owner = THIS_MODULE,
969 .gendrv = {
970 .name = "ch",
970 .gendrv = {
971 .name = "ch",
971 .owner = THIS_MODULE,
972 .probe = ch_probe,
973 .remove = ch_remove,
974 },
975};
976
977static const struct file_operations changer_fops = {
978 .owner = THIS_MODULE,
979 .open = ch_open,

--- 52 unchanged lines hidden ---
972 .probe = ch_probe,
973 .remove = ch_remove,
974 },
975};
976
977static const struct file_operations changer_fops = {
978 .owner = THIS_MODULE,
979 .open = ch_open,

--- 52 unchanged lines hidden ---