520 int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
521 {
522 request_queue_t *q;
523 int err;
524
525 q = bd_disk->queue;
526 if (!q)
527 return -ENXIO;
528
529 if (blk_get_queue(q))
530 return -ENXIO;
531
532 switch (cmd) {
533 /*
534 * new sgv3 interface
535 */
536 case SG_GET_VERSION_NUM:
537 err = sg_get_version(arg);
538 break;
539 case SCSI_IOCTL_GET_IDLUN:
540 err = scsi_get_idlun(q, arg);
541 break;
542 case SCSI_IOCTL_GET_BUS_NUMBER:
543 err = scsi_get_bus(q, arg);
544 break;
545 case SG_SET_TIMEOUT:
546 err = sg_set_timeout(q, arg);
547 break;
548 case SG_GET_TIMEOUT:
549 err = sg_get_timeout(q);
550 break;
551 case SG_GET_RESERVED_SIZE:
552 err = sg_get_reserved_size(q, arg);
553 break;
554 case SG_SET_RESERVED_SIZE:
555 err = sg_set_reserved_size(q, arg);
556 break;
557 case SG_EMULATED_HOST:
558 err = sg_emulated_host(q, arg);
559 break;
560 case SG_IO: {
561 struct sg_io_hdr hdr;
562
563 err = -EFAULT;
564 if (copy_from_user(&hdr, arg, sizeof(hdr)))
565 break;
566 err = sg_io(file, q, bd_disk, &hdr);
567 if (err == -EFAULT)
568 break;
569
570 if (copy_to_user(arg, &hdr, sizeof(hdr)))
571 err = -EFAULT;
572 break;
573 }
574 case CDROM_SEND_PACKET: {
575 struct cdrom_generic_command cgc;
576 struct sg_io_hdr hdr;
577
578 err = -EFAULT;
579 if (copy_from_user(&cgc, arg, sizeof(cgc)))
580 break;
581 cgc.timeout = clock_t_to_jiffies(cgc.timeout);
582 memset(&hdr, 0, sizeof(hdr));
583 hdr.interface_id = ‘S’;
584 hdr.cmd_len = sizeof(cgc.cmd);
585 hdr.dxfer_len = cgc.buflen;
586 err = 0;
587 switch (cgc.data_direction) {
588 case CGC_DATA_UNKNOWN:
589 hdr.dxfer_direction = SG_DXFER_UNKNOWN;
590 break;
591 case CGC_DATA_WRITE:
592 hdr.dxfer_direction = SG_DXFER_TO_DEV;
593 break;
594 case CGC_DATA_READ:
595 hdr.dxfer_direction = SG_DXFER_FROM_DEV;
596 break;
597 case CGC_DATA_NONE:
598 hdr.dxfer_direction = SG_DXFER_NONE;
599 break;
600 default:
601 err = -EINVAL;
602 }
603 if (err)
604 break;
605
606 hdr.dxferp = cgc.buffer;
607 hdr.sbp = cgc.sense;
608 if (hdr.sbp)
609 hdr.mx_sb_len = sizeof(struct request_sense);
610 hdr.timeout = cgc.timeout;
611 hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd;
612 hdr.cmd_len = sizeof(cgc.cmd);
613
614 err = sg_io(file, q, bd_disk, &hdr);
615 if (err == -EFAULT)
616 break;
617
618 if (hdr.status)
619 err = -EIO;
620
621 cgc.stat = err;
622 cgc.buflen = hdr.resid;
623 if (copy_to_user(arg, &cgc, sizeof(cgc)))
624 err = -EFAULT;
625
626 break;
627 }
628
629 /*
630 * old junk scsi send command ioctl
631 */
632 case SCSI_IOCTL_SEND_COMMAND:
633 printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO/ n", current->comm);
634 err = -EINVAL;
635 if (!arg)
636 break;
637
638 err = sg_scsi_ioctl(file, q, bd_disk, arg);
639 break;
640 case CDROMCLOSETRAY:
641 err = blk_send_start_stop(q, bd_disk, 0x03);
642 break;
643 case CDROMEJECT:
644 err = blk_send_start_stop(q, bd_disk, 0x02);
645 break;
646 default:
647 err = -ENOTTY;
648 }
649
650 blk_put_queue(q);
651 return err;
652 }
爱情使人忘记时间,时间也使人忘记爱情。