/* the scsi_ioctl() function differs from most ioctls in that it does not take a major/minor number as the dev filed. Rather, it takes a pointer to a scsi_devices[] element, a structure. */ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) { char scsi_cmd[12]; if ((cmd != 0 && dev->index > NR_SCSI_DEVICES)) return -ENODEV; switch (cmd) { case SCSI_IOCTL_GET_IDLUN: verify_area(VERIFY_WRITE, (void *) arg, sizeof(int)); put_fs_long(dev->id + (dev->lun << 8) + (dev->host->host_no << 16), (unsigned long *) arg); return 0; case SCSI_IOCTL_TAGGED_ENABLE: if(!suser()) return -EACCES; if(!dev->tagged_supported) return -EINVAL; dev->tagged_queue = 1; dev->current_tag = 1; break; case SCSI_IOCTL_TAGGED_DISABLE: if(!suser()) return -EACCES; if(!dev->tagged_supported) return -EINVAL; dev->tagged_queue = 0; dev->current_tag = 0; break; case SCSI_IOCTL_PROBE_HOST: return ioctl_probe(dev->host, arg); case SCSI_IOCTL_SEND_COMMAND: if(!suser()) return -EACCES; return ioctl_command((Scsi_Device *) dev, arg); case SCSI_IOCTL_DOORLOCK: if (!dev->removable || !dev->lockable) return 0; scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = SCSI_REMOVAL_PREVENT; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); break; case SCSI_IOCTL_DOORUNLOCK: if (!dev->removable || !dev->lockable) return 0; scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = SCSI_REMOVAL_ALLOW; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); case SCSI_IOCTL_TEST_UNIT_READY: scsi_cmd[0] = TEST_UNIT_READY; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 0; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); break; default : return -EINVAL; } return -EINVAL; }
/* the scsi_ioctl() function differs from most ioctls in that it does not take a major/minor number as the dev filed. Rather, it takes a pointer to a scsi_devices[] element, a structure. */ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) { char scsi_cmd[10]; if ((cmd != 0 && dev->index > NR_SCSI_DEVICES)) return -ENODEV; if ((cmd == 0 && dev->host_no > max_scsi_hosts)) return -ENODEV; switch (cmd) { case SCSI_IOCTL_GET_IDLUN: verify_area(VERIFY_WRITE, (void *) arg, sizeof(int)); put_fs_long(dev->id + (dev->lun << 8) + (dev->host_no << 16), (long *) arg); return 0; case SCSI_IOCTL_PROBE_HOST: return ioctl_probe(dev->host_no, arg); case SCSI_IOCTL_SEND_COMMAND: return ioctl_command((Scsi_Device *) dev, arg); case SCSI_IOCTL_DOORLOCK: if (!dev->removable || !dev->lockable) return 0; scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = SCSI_REMOVAL_PREVENT; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); break; case SCSI_IOCTL_DOORUNLOCK: if (!dev->removable || !dev->lockable) return 0; scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = SCSI_REMOVAL_ALLOW; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); case SCSI_IOCTL_TEST_UNIT_READY: scsi_cmd[0] = TEST_UNIT_READY; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 0; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); break; default : return -EINVAL; } }
/* * the scsi_ioctl() function differs from most ioctls in that it does * not take a major/minor number as the dev field. Rather, it takes * a pointer to a scsi_devices[] element, a structure. */ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg) { int result; char scsi_cmd[12]; /* No idea how this happens.... */ if (!dev) return -ENXIO; switch (cmd) { case SCSI_IOCTL_GET_IDLUN: result = verify_area(VERIFY_WRITE, (void *) arg, 2*sizeof(long)); if (result) return result; put_user(dev->id + (dev->lun << 8) + (dev->channel << 16) + ((dev->host->hostt->proc_dir->low_ino & 0xff) << 24), (unsigned long *) arg); put_user( dev->host->unique_id, (unsigned long *) arg+1); return 0; case SCSI_IOCTL_TAGGED_ENABLE: if(!suser()) return -EACCES; if(!dev->tagged_supported) return -EINVAL; dev->tagged_queue = 1; dev->current_tag = 1; return 0; case SCSI_IOCTL_TAGGED_DISABLE: if(!suser()) return -EACCES; if(!dev->tagged_supported) return -EINVAL; dev->tagged_queue = 0; dev->current_tag = 0; return 0; case SCSI_IOCTL_PROBE_HOST: return ioctl_probe(dev->host, arg); case SCSI_IOCTL_SEND_COMMAND: if(!suser()) return -EACCES; return ioctl_command((Scsi_Device *) dev, arg); case SCSI_IOCTL_DOORLOCK: if (!dev->removable || !dev->lockable) return 0; scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = SCSI_REMOVAL_PREVENT; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, NORMAL_TIMEOUT, NORMAL_RETRIES); break; case SCSI_IOCTL_DOORUNLOCK: if (!dev->removable || !dev->lockable) return 0; scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = SCSI_REMOVAL_ALLOW; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, NORMAL_TIMEOUT, NORMAL_RETRIES); case SCSI_IOCTL_TEST_UNIT_READY: scsi_cmd[0] = TEST_UNIT_READY; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 0; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, NORMAL_TIMEOUT, NORMAL_RETRIES); break; case SCSI_IOCTL_START_UNIT: scsi_cmd[0] = START_STOP; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 1; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, START_STOP_TIMEOUT, NORMAL_RETRIES); break; case SCSI_IOCTL_STOP_UNIT: scsi_cmd[0] = START_STOP; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 0; return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, START_STOP_TIMEOUT, NORMAL_RETRIES); break; default : return -EINVAL; } return -EINVAL; }