Changeset View
Changeset View
Standalone View
Standalone View
sys/cam/ctl/ctl_frontend_ioctl.c
| Show First 20 Lines • Show All 582 Lines • ▼ Show 20 Lines | cfi_submit_wait(union ctl_io *io) | ||||
| return (CTL_RETVAL_COMPLETE); | return (CTL_RETVAL_COMPLETE); | ||||
| } | } | ||||
| int | int | ||||
| ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag, | ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag, | ||||
| struct thread *td) | struct thread *td) | ||||
| { | { | ||||
| struct cfi_port *cfi; | struct cfi_port *cfi; | ||||
| union ctl_io *io; | union ctl_io *io, *user_io; | ||||
| void *pool_tmp, *sc_tmp; | void *pool_tmp, *sc_tmp; | ||||
| int retval = 0; | int retval = 0; | ||||
| if (cmd != CTL_IO) | if (cmd != CTL_IO) | ||||
| return (ENOTTY); | return (ENOTTY); | ||||
| cfi = dev->si_drv2 == NULL | cfi = dev->si_drv2 == NULL | ||||
| ? TAILQ_FIRST(&cfi_softc.ports) | ? TAILQ_FIRST(&cfi_softc.ports) | ||||
| : dev->si_drv2; | : dev->si_drv2; | ||||
| /* | /* | ||||
| * If we haven't been "enabled", don't allow any SCSI I/O | * If we haven't been "enabled", don't allow any SCSI I/O | ||||
| * to this FETD. | * to this FETD. | ||||
| */ | */ | ||||
| if ((cfi->port.status & CTL_PORT_STATUS_ONLINE) == 0) | if ((cfi->port.status & CTL_PORT_STATUS_ONLINE) == 0) | ||||
| return (EPERM); | return (EPERM); | ||||
| /* Reject out-of-range initiator IDs. */ | |||||
| user_io = (void *)addr; | |||||
| if (user_io->io_hdr.nexus.initid >= CTL_MAX_INIT_PER_PORT) | |||||
| return (EINVAL); | |||||
| io = ctl_alloc_io(cfi->port.ctl_pool_ref); | io = ctl_alloc_io(cfi->port.ctl_pool_ref); | ||||
| /* | /* | ||||
| * Need to save the pool reference so it doesn't get | * Need to save the pool reference so it doesn't get | ||||
| * spammed by the user's ctl_io. | * spammed by the user's ctl_io. | ||||
| */ | */ | ||||
| pool_tmp = io->io_hdr.pool; | pool_tmp = io->io_hdr.pool; | ||||
| sc_tmp = CTL_SOFTC(io); | sc_tmp = CTL_SOFTC(io); | ||||
| memcpy(io, (void *)addr, sizeof(*io)); | memcpy(io, user_io, sizeof(*io)); | ||||
| io->io_hdr.pool = pool_tmp; | io->io_hdr.pool = pool_tmp; | ||||
| CTL_SOFTC(io) = sc_tmp; | CTL_SOFTC(io) = sc_tmp; | ||||
| TAILQ_INIT(&io->io_hdr.blocked_queue); | TAILQ_INIT(&io->io_hdr.blocked_queue); | ||||
| /* | /* | ||||
| * No status yet, so make sure the status is set properly. | * No status yet, so make sure the status is set properly. | ||||
| */ | */ | ||||
| io->io_hdr.status = CTL_STATUS_NONE; | io->io_hdr.status = CTL_STATUS_NONE; | ||||
| /* | /* | ||||
| * The user sets the initiator ID, target and LUN IDs. | * The user sets the initiator ID, target and LUN IDs. | ||||
| */ | */ | ||||
| io->io_hdr.nexus.targ_port = cfi->port.targ_port; | io->io_hdr.nexus.targ_port = cfi->port.targ_port; | ||||
| io->io_hdr.flags |= CTL_FLAG_USER_REQ; | io->io_hdr.flags |= CTL_FLAG_USER_REQ; | ||||
| if ((io->io_hdr.flags & CTL_FLAG_USER_TAG) == 0 && | if ((io->io_hdr.flags & CTL_FLAG_USER_TAG) == 0 && | ||||
| io->io_hdr.io_type == CTL_IO_SCSI && | io->io_hdr.io_type == CTL_IO_SCSI && | ||||
| io->scsiio.tag_type != CTL_TAG_UNTAGGED) | io->scsiio.tag_type != CTL_TAG_UNTAGGED) | ||||
| io->scsiio.tag_num = atomic_fetchadd_int(&cfi->cur_tag_num, 1); | io->scsiio.tag_num = atomic_fetchadd_int(&cfi->cur_tag_num, 1); | ||||
| retval = cfi_submit_wait(io); | retval = cfi_submit_wait(io); | ||||
| if (retval == 0) | if (retval == 0) | ||||
| memcpy((void *)addr, io, sizeof(*io)); | memcpy(user_io, io, sizeof(*io)); | ||||
| ctl_free_io(io); | ctl_free_io(io); | ||||
| return (retval); | return (retval); | ||||
| } | } | ||||