Esempio n. 1
0
int si_read(siread *q)
{
	switch (q->order) {
	case SS_EQ:
		return si_get(q);
	case SS_LT:
	case SS_LTE:
	case SS_GT:
	case SS_GTE:
		return si_range(q);
	default:
		break;
	}
	return -1;
}
Esempio n. 2
0
/*
 * Something (e.g. another driver) has called us
 * with a periph and a scsi-specific ioctl to perform,
 * better try.  If user-level type command, we must
 * still be running in the context of the calling process
 */
int
scsipi_do_ioctl(struct scsipi_periph *periph, dev_t dev, u_long cmd,
    void *addr, int flag, struct lwp *l)
{
	int error;

	SC_DEBUG(periph, SCSIPI_DB2, ("scsipi_do_ioctl(0x%lx)\n", cmd));

	if (addr == NULL)
		return EINVAL;

	/* Check for the safe-ness of this request. */
	switch (cmd) {
	case OSCIOCIDENTIFY:
	case SCIOCIDENTIFY:
		break;
	case SCIOCCOMMAND:
		if ((((scsireq_t *)addr)->flags & SCCMD_READ) == 0 &&
		    (flag & FWRITE) == 0)
			return (EBADF);
		break;
	default:
		if ((flag & FWRITE) == 0)
			return (EBADF);
	}

	switch (cmd) {
	case SCIOCCOMMAND: {
		scsireq_t *screq = (scsireq_t *)addr;
		struct scsi_ioctl *si;
		int len;

		si = si_get();
		si->si_screq = *screq;
		si->si_periph = periph;
		len = screq->datalen;
		if (len) {
			si->si_iov.iov_base = screq->databuf;
			si->si_iov.iov_len = len;
			si->si_uio.uio_iov = &si->si_iov;
			si->si_uio.uio_iovcnt = 1;
			si->si_uio.uio_resid = len;
			si->si_uio.uio_offset = 0;
			si->si_uio.uio_rw =
			    (screq->flags & SCCMD_READ) ? UIO_READ : UIO_WRITE;
			if ((flag & FKIOCTL) == 0) {
				si->si_uio.uio_vmspace = l->l_proc->p_vmspace;
			} else {
				UIO_SETUP_SYSSPACE(&si->si_uio);
			}
			error = physio(scsistrategy, &si->si_bp, dev,
			    (screq->flags & SCCMD_READ) ? B_READ : B_WRITE,
			    periph->periph_channel->chan_adapter->adapt_minphys,
			    &si->si_uio);
		} else {
			/* if no data, no need to translate it.. */
			si->si_bp.b_flags = 0;
			si->si_bp.b_data = 0;
			si->si_bp.b_bcount = 0;
			si->si_bp.b_dev = dev;
			si->si_bp.b_proc = l->l_proc;
			scsistrategy(&si->si_bp);
			error = si->si_bp.b_error;
		}
		*screq = si->si_screq;
		si_free(si);
		return (error);
	}
	case SCIOCDEBUG: {
		int level = *((int *)addr);

		SC_DEBUG(periph, SCSIPI_DB3, ("debug set to %d\n", level));
		periph->periph_dbflags = 0;
		if (level & 1)
			periph->periph_dbflags |= SCSIPI_DB1;
		if (level & 2)
			periph->periph_dbflags |= SCSIPI_DB2;
		if (level & 4)
			periph->periph_dbflags |= SCSIPI_DB3;
		if (level & 8)
			periph->periph_dbflags |= SCSIPI_DB4;
		return (0);
	}
	case SCIOCRECONFIG:
	case SCIOCDECONFIG:
		return (EINVAL);
	case SCIOCIDENTIFY: {
		struct scsi_addr *sca = (struct scsi_addr *)addr;

		switch (scsipi_periph_bustype(periph)) {
		case SCSIPI_BUSTYPE_SCSI:
			sca->type = TYPE_SCSI;
			sca->addr.scsi.scbus =
			    device_unit(device_parent(periph->periph_dev));
			sca->addr.scsi.target = periph->periph_target;
			sca->addr.scsi.lun = periph->periph_lun;
			return (0);
		case SCSIPI_BUSTYPE_ATAPI:
			sca->type = TYPE_ATAPI;
			sca->addr.atapi.atbus =
			    device_unit(device_parent(periph->periph_dev));
			sca->addr.atapi.drive = periph->periph_target;
			return (0);
		}
		return (ENXIO);
	}
#if defined(COMPAT_12) || defined(COMPAT_FREEBSD)
	/* SCIOCIDENTIFY before ATAPI staff merge */
	case OSCIOCIDENTIFY: {
		struct oscsi_addr *sca = (struct oscsi_addr *)addr;

		switch (scsipi_periph_bustype(periph)) {
		case SCSIPI_BUSTYPE_SCSI:
			sca->scbus =
			    device_unit(device_parent(periph->periph_dev));
			sca->target = periph->periph_target;
			sca->lun = periph->periph_lun;
			return (0);
		}
		return (ENODEV);
	}
#endif
	default:
		return (ENOTTY);
	}

#ifdef DIAGNOSTIC
	panic("scsipi_do_ioctl: impossible");
#endif
}