예제 #1
0
/*
	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;
}
예제 #2
0
/*
	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;
	}
}
예제 #3
0
/*
 * 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;
}