Lines Matching +full:system +full:- +full:ctl

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
32 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_frontend_cam_sim.c#4 $
35 * CTL frontend to CAM SIM interface. This allows access to CTL LUNs via
36 * the da(4) and pass(4) drivers from inside the system.
60 #include <cam/ctl/ctl_io.h>
61 #include <cam/ctl/ctl.h>
62 #include <cam/ctl/ctl_frontend.h>
63 #include <cam/ctl/ctl_debug.h>
130 port = &softc->port; in cfcs_init()
132 port->frontend = &cfcs_frontend; in cfcs_init()
133 port->port_type = CTL_PORT_INTERNAL; in cfcs_init()
135 port->num_requested_ctl_io = 4096; in cfcs_init()
136 snprintf(softc->port_name, sizeof(softc->port_name), "camsim"); in cfcs_init()
137 port->port_name = softc->port_name; in cfcs_init()
138 port->port_online = cfcs_online; in cfcs_init()
139 port->port_offline = cfcs_offline; in cfcs_init()
140 port->onoff_arg = softc; in cfcs_init()
141 port->fe_datamove = cfcs_datamove; in cfcs_init()
142 port->fe_done = cfcs_done; in cfcs_init()
143 port->targ_port = -1; in cfcs_init()
153 * If the CTL frontend didn't tell us what our WWNN/WWPN is, go in cfcs_init()
156 if (port->wwnn == 0) { in cfcs_init()
160 softc->wwnn = (random_bits & 0x0000000fffffff00ULL) | in cfcs_init()
162 /* NL-Port */ 0x0300; in cfcs_init()
163 softc->wwpn = softc->wwnn + port->targ_port + 1; in cfcs_init()
164 ctl_port_set_wwns(port, true, softc->wwnn, true, softc->wwpn); in cfcs_init()
166 softc->wwnn = port->wwnn; in cfcs_init()
167 softc->wwpn = port->wwpn; in cfcs_init()
170 softc->devq = cam_simq_alloc(port->num_requested_ctl_io); in cfcs_init()
171 if (softc->devq == NULL) { in cfcs_init()
177 softc->sim = cam_sim_alloc(cfcs_action, cfcs_poll, softc->port_name, in cfcs_init()
179 port->num_requested_ctl_io, softc->devq); in cfcs_init()
180 if (softc->sim == NULL) { in cfcs_init()
186 if (xpt_bus_register(softc->sim, NULL, 0) != CAM_SUCCESS) { in cfcs_init()
192 if (xpt_create_path(&softc->path, /*periph*/NULL, in cfcs_init()
193 cam_sim_path(softc->sim), in cfcs_init()
197 xpt_bus_deregister(cam_sim_path(softc->sim)); in cfcs_init()
205 if (softc->sim) in cfcs_init()
206 cam_sim_free(softc->sim, /*free_devq*/ TRUE); in cfcs_init()
207 else if (softc->devq) in cfcs_init()
208 cam_simq_free(softc->devq); in cfcs_init()
216 struct ctl_port *port = &softc->port; in cfcs_shutdown()
221 xpt_free_path(softc->path); in cfcs_shutdown()
222 xpt_bus_deregister(cam_sim_path(softc->sim)); in cfcs_shutdown()
223 cam_sim_free(softc->sim, /*free_devq*/ TRUE); in cfcs_shutdown()
242 softc->online = online; in cfcs_onoffline()
250 if (xpt_create_path(&ccb->ccb_h.path, NULL, in cfcs_onoffline()
251 cam_sim_path(softc->sim), CAM_TARGET_WILDCARD, in cfcs_onoffline()
292 ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; in cfcs_datamove()
301 KASSERT(((ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS) == 0), ("invalid " in cfcs_datamove()
302 "CAM flags %#x", (ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS))); in cfcs_datamove()
308 switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) { in cfcs_datamove()
312 cam_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr; in cfcs_datamove()
313 cam_sg_count = ccb->csio.sglist_cnt; in cfcs_datamove()
319 io->scsiio.kern_rel_offset) { in cfcs_datamove()
321 cam_sg_offset = io->scsiio.kern_rel_offset - in cfcs_datamove()
331 cam_sglist[0].ds_len = ccb->csio.dxfer_len; in cfcs_datamove()
332 cam_sglist[0].ds_addr = (bus_addr_t)(uintptr_t)ccb->csio.data_ptr; in cfcs_datamove()
335 cam_sg_offset = io->scsiio.kern_rel_offset; in cfcs_datamove()
338 panic("Invalid CAM flags %#x", ccb->ccb_h.flags); in cfcs_datamove()
341 if (io->scsiio.kern_sg_entries > 0) { in cfcs_datamove()
342 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; in cfcs_datamove()
343 ctl_sg_count = io->scsiio.kern_sg_entries; in cfcs_datamove()
346 ctl_sglist->addr = io->scsiio.kern_data_ptr; in cfcs_datamove()
347 ctl_sglist->len = io->scsiio.kern_data_len; in cfcs_datamove()
357 len_to_copy = MIN(cam_sglist[i].ds_len - cam_watermark, in cfcs_datamove()
358 ctl_sglist[j].len - ctl_watermark); in cfcs_datamove()
362 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) { in cfcs_datamove()
374 if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == in cfcs_datamove()
389 io->scsiio.ext_data_filled += len_to_copy; in cfcs_datamove()
390 io->scsiio.kern_data_resid -= len_to_copy; in cfcs_datamove()
405 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { in cfcs_datamove()
406 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = NULL; in cfcs_datamove()
407 io->io_hdr.flags |= CTL_FLAG_STATUS_SENT; in cfcs_datamove()
408 ccb->csio.resid = ccb->csio.dxfer_len - in cfcs_datamove()
409 io->scsiio.ext_data_filled; in cfcs_datamove()
410 ccb->ccb_h.status &= ~CAM_STATUS_MASK; in cfcs_datamove()
411 ccb->ccb_h.status |= CAM_REQ_CMP; in cfcs_datamove()
423 ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; in cfcs_done()
432 KASSERT(((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE), in cfcs_done()
433 ("invalid CTL status %#x", io->io_hdr.status)); in cfcs_done()
436 * Translate CTL status to CAM status. in cfcs_done()
438 if (ccb->ccb_h.func_code == XPT_SCSI_IO) { in cfcs_done()
439 ccb->csio.resid = ccb->csio.dxfer_len - in cfcs_done()
440 io->scsiio.ext_data_filled; in cfcs_done()
442 ccb->ccb_h.status &= ~CAM_STATUS_MASK; in cfcs_done()
443 switch (io->io_hdr.status & CTL_STATUS_MASK) { in cfcs_done()
445 ccb->ccb_h.status |= CAM_REQ_CMP; in cfcs_done()
448 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; in cfcs_done()
449 ccb->csio.scsi_status = io->scsiio.scsi_status; in cfcs_done()
450 bcopy(&io->scsiio.sense_data, &ccb->csio.sense_data, in cfcs_done()
451 min(io->scsiio.sense_len, ccb->csio.sense_len)); in cfcs_done()
452 if (ccb->csio.sense_len > io->scsiio.sense_len) in cfcs_done()
453 ccb->csio.sense_resid = ccb->csio.sense_len - in cfcs_done()
454 io->scsiio.sense_len; in cfcs_done()
456 ccb->csio.sense_resid = 0; in cfcs_done()
457 if ((ccb->csio.sense_len - ccb->csio.sense_resid) > in cfcs_done()
459 ccb->csio.sense_resid = ccb->csio.sense_len - in cfcs_done()
464 ccb->ccb_h.status |= CAM_REQ_ABORTED; in cfcs_done()
468 ccb->ccb_h.status |= CAM_REQ_CMP_ERR; in cfcs_done()
472 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP && in cfcs_done()
473 (ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { in cfcs_done()
474 xpt_freeze_devq(ccb->ccb_h.path, 1); in cfcs_done()
475 ccb->ccb_h.status |= CAM_DEV_QFRZN; in cfcs_done()
488 switch (ccb->ccb_h.func_code) { in cfcs_action()
493 csio = &ccb->csio; in cfcs_action()
499 if (ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS) { in cfcs_action()
500 ccb->ccb_h.status = CAM_REQ_INVALID; in cfcs_action()
502 __func__, ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS, in cfcs_action()
503 ccb->ccb_h.flags); in cfcs_action()
511 if (softc->online == 0) { in cfcs_action()
512 ccb->ccb_h.status = CAM_DEV_NOT_THERE; in cfcs_action()
517 io = ctl_alloc_io_nowait(softc->port.ctl_pool_ref); in cfcs_action()
520 ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; in cfcs_action()
521 xpt_freeze_devq(ccb->ccb_h.path, 1); in cfcs_action()
527 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb; in cfcs_action()
528 ccb->ccb_h.io_ptr = io; in cfcs_action()
534 io->io_hdr.io_type = CTL_IO_SCSI; in cfcs_action()
535 io->io_hdr.nexus.initid = 1; in cfcs_action()
536 io->io_hdr.nexus.targ_port = softc->port.targ_port; in cfcs_action()
537 io->io_hdr.nexus.targ_lun = ctl_decode_lun( in cfcs_action()
538 CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun)); in cfcs_action()
539 io->scsiio.priority = csio->priority; in cfcs_action()
542 * have a very long-lived I/O and tag collision, especially in cfcs_action()
547 io->scsiio.tag_num = atomic_fetchadd_32(&softc->cur_tag_num, 1); in cfcs_action()
548 csio->tag_id = io->scsiio.tag_num; in cfcs_action()
549 switch (csio->tag_action) { in cfcs_action()
551 io->scsiio.tag_type = CTL_TAG_UNTAGGED; in cfcs_action()
554 io->scsiio.tag_type = CTL_TAG_SIMPLE; in cfcs_action()
557 io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE; in cfcs_action()
560 io->scsiio.tag_type = CTL_TAG_ORDERED; in cfcs_action()
563 io->scsiio.tag_type = CTL_TAG_ACA; in cfcs_action()
566 io->scsiio.tag_type = CTL_TAG_UNTAGGED; in cfcs_action()
568 csio->tag_action); in cfcs_action()
571 if (csio->cdb_len > sizeof(io->scsiio.cdb)) { in cfcs_action()
573 __func__, csio->cdb_len, sizeof(io->scsiio.cdb)); in cfcs_action()
575 io->scsiio.cdb_len = min(csio->cdb_len, sizeof(io->scsiio.cdb)); in cfcs_action()
576 bcopy(scsiio_cdb_ptr(csio), io->scsiio.cdb, io->scsiio.cdb_len); in cfcs_action()
578 ccb->ccb_h.status |= CAM_SIM_QUEUED; in cfcs_action()
583 ccb->ccb_h.func_code, err); in cfcs_action()
585 ccb->ccb_h.status = CAM_REQ_INVALID; in cfcs_action()
595 abort_ccb = ccb->cab.abort_ccb; in cfcs_action()
597 if (abort_ccb->ccb_h.func_code != XPT_SCSI_IO) { in cfcs_action()
598 ccb->ccb_h.status = CAM_REQ_INVALID; in cfcs_action()
605 if (softc->online == 0) { in cfcs_action()
606 ccb->ccb_h.status = CAM_DEV_NOT_THERE; in cfcs_action()
611 io = ctl_alloc_io_nowait(softc->port.ctl_pool_ref); in cfcs_action()
613 ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; in cfcs_action()
614 xpt_freeze_devq(ccb->ccb_h.path, 1); in cfcs_action()
621 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb; in cfcs_action()
622 ccb->ccb_h.io_ptr = io; in cfcs_action()
624 io->io_hdr.io_type = CTL_IO_TASK; in cfcs_action()
625 io->io_hdr.nexus.initid = 1; in cfcs_action()
626 io->io_hdr.nexus.targ_port = softc->port.targ_port; in cfcs_action()
627 io->io_hdr.nexus.targ_lun = ctl_decode_lun( in cfcs_action()
628 CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun)); in cfcs_action()
629 io->taskio.task_action = CTL_TASK_ABORT_TASK; in cfcs_action()
630 io->taskio.tag_num = abort_ccb->csio.tag_id; in cfcs_action()
631 switch (abort_ccb->csio.tag_action) { in cfcs_action()
633 io->taskio.tag_type = CTL_TAG_UNTAGGED; in cfcs_action()
636 io->taskio.tag_type = CTL_TAG_SIMPLE; in cfcs_action()
639 io->taskio.tag_type = CTL_TAG_HEAD_OF_QUEUE; in cfcs_action()
642 io->taskio.tag_type = CTL_TAG_ORDERED; in cfcs_action()
645 io->taskio.tag_type = CTL_TAG_ACA; in cfcs_action()
648 io->taskio.tag_type = CTL_TAG_UNTAGGED; in cfcs_action()
650 abort_ccb->csio.tag_action); in cfcs_action()
657 ccb->ccb_h.func_code, err); in cfcs_action()
667 cts = &ccb->cts; in cfcs_action()
668 scsi = &cts->proto_specific.scsi; in cfcs_action()
669 fc = &cts->xport_specific.fc; in cfcs_action()
672 cts->protocol = PROTO_SCSI; in cfcs_action()
673 cts->protocol_version = SCSI_REV_SPC2; in cfcs_action()
674 cts->transport = XPORT_FC; in cfcs_action()
675 cts->transport_version = 0; in cfcs_action()
677 scsi->valid = CTS_SCSI_VALID_TQ; in cfcs_action()
678 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; in cfcs_action()
679 fc->valid = CTS_FC_VALID_SPEED; in cfcs_action()
680 fc->bitrate = 800000; in cfcs_action()
681 fc->wwnn = softc->wwnn; in cfcs_action()
682 fc->wwpn = softc->wwpn; in cfcs_action()
683 fc->port = softc->port.targ_port; in cfcs_action()
684 fc->valid |= CTS_FC_VALID_WWNN | CTS_FC_VALID_WWPN | in cfcs_action()
686 ccb->ccb_h.status = CAM_REQ_CMP; in cfcs_action()
691 ccb->ccb_h.status = CAM_REQ_CMP; in cfcs_action()
700 if (softc->online == 0) { in cfcs_action()
701 ccb->ccb_h.status = CAM_DEV_NOT_THERE; in cfcs_action()
706 io = ctl_alloc_io_nowait(softc->port.ctl_pool_ref); in cfcs_action()
708 ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; in cfcs_action()
709 xpt_freeze_devq(ccb->ccb_h.path, 1); in cfcs_action()
716 if (ccb->ccb_h.func_code == XPT_RESET_DEV) in cfcs_action()
717 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb; in cfcs_action()
718 ccb->ccb_h.io_ptr = io; in cfcs_action()
720 io->io_hdr.io_type = CTL_IO_TASK; in cfcs_action()
721 io->io_hdr.nexus.initid = 1; in cfcs_action()
722 io->io_hdr.nexus.targ_port = softc->port.targ_port; in cfcs_action()
723 io->io_hdr.nexus.targ_lun = ctl_decode_lun( in cfcs_action()
724 CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun)); in cfcs_action()
725 if (ccb->ccb_h.func_code == XPT_RESET_BUS) in cfcs_action()
726 io->taskio.task_action = CTL_TASK_BUS_RESET; in cfcs_action()
728 io->taskio.task_action = CTL_TASK_LUN_RESET; in cfcs_action()
734 ccb->ccb_h.func_code, err); in cfcs_action()
740 cam_calc_geometry(&ccb->ccg, 1); in cfcs_action()
746 cpi = &ccb->cpi; in cfcs_action()
748 cpi->version_num = 0; in cfcs_action()
749 cpi->hba_inquiry = PI_TAG_ABLE; in cfcs_action()
750 cpi->target_sprt = 0; in cfcs_action()
751 cpi->hba_misc = PIM_EXTLUNS; in cfcs_action()
752 cpi->hba_eng_cnt = 0; in cfcs_action()
753 cpi->max_target = 0; in cfcs_action()
754 cpi->max_lun = 1024; in cfcs_action()
756 cpi->maxio = 1024 * 1024; in cfcs_action()
757 cpi->async_flags = 0; in cfcs_action()
758 cpi->hpath_id = 0; in cfcs_action()
759 cpi->initiator_id = 1; in cfcs_action()
761 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); in cfcs_action()
762 strlcpy(cpi->hba_vid, "FreeBSD", HBA_IDLEN); in cfcs_action()
763 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); in cfcs_action()
764 cpi->unit_number = 0; in cfcs_action()
765 cpi->bus_id = 0; in cfcs_action()
766 cpi->base_transfer_speed = 800000; in cfcs_action()
767 cpi->protocol = PROTO_SCSI; in cfcs_action()
768 cpi->protocol_version = SCSI_REV_SPC2; in cfcs_action()
772 cpi->transport = XPORT_FC; in cfcs_action()
773 cpi->transport_version = 0; in cfcs_action()
774 cpi->xport_specific.fc.wwnn = softc->wwnn; in cfcs_action()
775 cpi->xport_specific.fc.wwpn = softc->wwpn; in cfcs_action()
776 cpi->xport_specific.fc.port = softc->port.targ_port; in cfcs_action()
777 cpi->xport_specific.fc.bitrate = 8 * 1000 * 1000; in cfcs_action()
778 cpi->ccb_h.status = CAM_REQ_CMP; in cfcs_action()
782 ccb->ccb_h.status = CAM_PROVIDE_FAIL; in cfcs_action()
784 ccb->ccb_h.func_code); in cfcs_action()