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; }
/* * 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 }