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 --- |