1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2009 Silicon Graphics International Corp. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions, and the following disclaimer, 12 * without modification. 13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 14 * substantially similar to the "NO WARRANTY" disclaimer below 15 * ("Disclaimer") and any redistribution must be conditioned upon 16 * including a substantially similar Disclaimer requirement for further 17 * binary redistribution. 18 * 19 * NO WARRANTY 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGES. 31 * 32 * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_frontend_cam_sim.c#4 $ 33 */ 34 /* 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. 37 * 38 * Author: Ken Merry <ken@FreeBSD.org> 39 */ 40 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/types.h> 48 #include <sys/malloc.h> 49 #include <sys/lock.h> 50 #include <sys/mutex.h> 51 #include <sys/condvar.h> 52 #include <sys/queue.h> 53 #include <sys/bus.h> 54 #include <sys/sysctl.h> 55 #include <machine/bus.h> 56 #include <sys/sbuf.h> 57 58 #include <cam/cam.h> 59 #include <cam/cam_ccb.h> 60 #include <cam/cam_sim.h> 61 #include <cam/cam_xpt_sim.h> 62 #include <cam/cam_xpt.h> 63 #include <cam/cam_periph.h> 64 #include <cam/scsi/scsi_all.h> 65 #include <cam/scsi/scsi_message.h> 66 #include <cam/ctl/ctl_io.h> 67 #include <cam/ctl/ctl.h> 68 #include <cam/ctl/ctl_frontend.h> 69 #include <cam/ctl/ctl_debug.h> 70 71 #define io_ptr spriv_ptr1 72 73 struct cfcs_io { 74 union ccb *ccb; 75 }; 76 77 struct cfcs_softc { 78 struct ctl_port port; 79 char port_name[32]; 80 struct cam_sim *sim; 81 struct cam_devq *devq; 82 struct cam_path *path; 83 struct mtx lock; 84 uint64_t wwnn; 85 uint64_t wwpn; 86 uint32_t cur_tag_num; 87 int online; 88 }; 89 90 /* 91 * We can't handle CCBs with these flags. For the most part, we just don't 92 * handle physical addresses yet. That would require mapping things in 93 * order to do the copy. 94 */ 95 #define CFCS_BAD_CCB_FLAGS (CAM_DATA_ISPHYS | CAM_MSG_BUF_PHYS | \ 96 CAM_SNS_BUF_PHYS | CAM_CDB_PHYS | CAM_SENSE_PTR | \ 97 CAM_SENSE_PHYS) 98 99 static int cfcs_init(void); 100 static int cfcs_shutdown(void); 101 static void cfcs_poll(struct cam_sim *sim); 102 static void cfcs_online(void *arg); 103 static void cfcs_offline(void *arg); 104 static void cfcs_datamove(union ctl_io *io); 105 static void cfcs_done(union ctl_io *io); 106 void cfcs_action(struct cam_sim *sim, union ccb *ccb); 107 108 struct cfcs_softc cfcs_softc; 109 /* 110 * This is primarily intended to allow for error injection to test the CAM 111 * sense data and sense residual handling code. This sets the maximum 112 * amount of SCSI sense data that we will report to CAM. 113 */ 114 static int cfcs_max_sense = sizeof(struct scsi_sense_data); 115 116 SYSCTL_NODE(_kern_cam, OID_AUTO, ctl2cam, CTLFLAG_RD, 0, 117 "CAM Target Layer SIM frontend"); 118 SYSCTL_INT(_kern_cam_ctl2cam, OID_AUTO, max_sense, CTLFLAG_RW, 119 &cfcs_max_sense, 0, "Maximum sense data size"); 120 121 static struct ctl_frontend cfcs_frontend = 122 { 123 .name = "camsim", 124 .init = cfcs_init, 125 .shutdown = cfcs_shutdown, 126 }; 127 CTL_FRONTEND_DECLARE(ctlcfcs, cfcs_frontend); 128 129 static int 130 cfcs_init(void) 131 { 132 struct cfcs_softc *softc; 133 struct ctl_port *port; 134 int retval; 135 136 softc = &cfcs_softc; 137 bzero(softc, sizeof(*softc)); 138 mtx_init(&softc->lock, "ctl2cam", NULL, MTX_DEF); 139 port = &softc->port; 140 141 port->frontend = &cfcs_frontend; 142 port->port_type = CTL_PORT_INTERNAL; 143 /* XXX KDM what should the real number be here? */ 144 port->num_requested_ctl_io = 4096; 145 snprintf(softc->port_name, sizeof(softc->port_name), "camsim"); 146 port->port_name = softc->port_name; 147 port->port_online = cfcs_online; 148 port->port_offline = cfcs_offline; 149 port->onoff_arg = softc; 150 port->fe_datamove = cfcs_datamove; 151 port->fe_done = cfcs_done; 152 port->targ_port = -1; 153 154 retval = ctl_port_register(port); 155 if (retval != 0) { 156 printf("%s: ctl_port_register() failed with error %d!\n", 157 __func__, retval); 158 mtx_destroy(&softc->lock); 159 return (retval); 160 } 161 162 /* 163 * If the CTL frontend didn't tell us what our WWNN/WWPN is, go 164 * ahead and set something random. 165 */ 166 if (port->wwnn == 0) { 167 uint64_t random_bits; 168 169 arc4rand(&random_bits, sizeof(random_bits), 0); 170 softc->wwnn = (random_bits & 0x0000000fffffff00ULL) | 171 /* Company ID */ 0x5000000000000000ULL | 172 /* NL-Port */ 0x0300; 173 softc->wwpn = softc->wwnn + port->targ_port + 1; 174 ctl_port_set_wwns(port, true, softc->wwnn, true, softc->wwpn); 175 } else { 176 softc->wwnn = port->wwnn; 177 softc->wwpn = port->wwpn; 178 } 179 180 mtx_lock(&softc->lock); 181 softc->devq = cam_simq_alloc(port->num_requested_ctl_io); 182 if (softc->devq == NULL) { 183 printf("%s: error allocating devq\n", __func__); 184 retval = ENOMEM; 185 goto bailout; 186 } 187 188 softc->sim = cam_sim_alloc(cfcs_action, cfcs_poll, softc->port_name, 189 softc, /*unit*/ 0, &softc->lock, 1, 190 port->num_requested_ctl_io, softc->devq); 191 if (softc->sim == NULL) { 192 printf("%s: error allocating SIM\n", __func__); 193 retval = ENOMEM; 194 goto bailout; 195 } 196 197 if (xpt_bus_register(softc->sim, NULL, 0) != CAM_SUCCESS) { 198 printf("%s: error registering SIM\n", __func__); 199 retval = ENOMEM; 200 goto bailout; 201 } 202 203 if (xpt_create_path(&softc->path, /*periph*/NULL, 204 cam_sim_path(softc->sim), 205 CAM_TARGET_WILDCARD, 206 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 207 printf("%s: error creating path\n", __func__); 208 xpt_bus_deregister(cam_sim_path(softc->sim)); 209 retval = EINVAL; 210 goto bailout; 211 } 212 213 mtx_unlock(&softc->lock); 214 215 return (retval); 216 217 bailout: 218 if (softc->sim) 219 cam_sim_free(softc->sim, /*free_devq*/ TRUE); 220 else if (softc->devq) 221 cam_simq_free(softc->devq); 222 mtx_unlock(&softc->lock); 223 mtx_destroy(&softc->lock); 224 225 return (retval); 226 } 227 228 static int 229 cfcs_shutdown(void) 230 { 231 struct cfcs_softc *softc = &cfcs_softc; 232 struct ctl_port *port = &softc->port; 233 int error; 234 235 ctl_port_offline(port); 236 237 mtx_lock(&softc->lock); 238 xpt_free_path(softc->path); 239 xpt_bus_deregister(cam_sim_path(softc->sim)); 240 cam_sim_free(softc->sim, /*free_devq*/ TRUE); 241 mtx_unlock(&softc->lock); 242 mtx_destroy(&softc->lock); 243 244 if ((error = ctl_port_deregister(port)) != 0) 245 printf("%s: cam_sim port deregistration failed\n", __func__); 246 return (error); 247 } 248 249 static void 250 cfcs_poll(struct cam_sim *sim) 251 { 252 253 } 254 255 static void 256 cfcs_onoffline(void *arg, int online) 257 { 258 struct cfcs_softc *softc; 259 union ccb *ccb; 260 261 softc = (struct cfcs_softc *)arg; 262 263 mtx_lock(&softc->lock); 264 softc->online = online; 265 266 ccb = xpt_alloc_ccb_nowait(); 267 if (ccb == NULL) { 268 printf("%s: unable to allocate CCB for rescan\n", __func__); 269 goto bailout; 270 } 271 272 if (xpt_create_path(&ccb->ccb_h.path, NULL, 273 cam_sim_path(softc->sim), CAM_TARGET_WILDCARD, 274 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 275 printf("%s: can't allocate path for rescan\n", __func__); 276 xpt_free_ccb(ccb); 277 goto bailout; 278 } 279 xpt_rescan(ccb); 280 281 bailout: 282 mtx_unlock(&softc->lock); 283 } 284 285 static void 286 cfcs_online(void *arg) 287 { 288 cfcs_onoffline(arg, /*online*/ 1); 289 } 290 291 static void 292 cfcs_offline(void *arg) 293 { 294 cfcs_onoffline(arg, /*online*/ 0); 295 } 296 297 /* 298 * This function is very similar to ctl_ioctl_do_datamove(). Is there a 299 * way to combine the functionality? 300 * 301 * XXX KDM may need to move this into a thread. We're doing a bcopy in the 302 * caller's context, which will usually be the backend. That may not be a 303 * good thing. 304 */ 305 static void 306 cfcs_datamove(union ctl_io *io) 307 { 308 union ccb *ccb; 309 bus_dma_segment_t cam_sg_entry, *cam_sglist; 310 struct ctl_sg_entry ctl_sg_entry, *ctl_sglist; 311 int cam_sg_count, ctl_sg_count, cam_sg_start; 312 int cam_sg_offset; 313 int len_to_copy; 314 int ctl_watermark, cam_watermark; 315 int i, j; 316 317 ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 318 319 /* 320 * Note that we have a check in cfcs_action() to make sure that any 321 * CCBs with "bad" flags are returned with CAM_REQ_INVALID. This 322 * is just to make sure no one removes that check without updating 323 * this code to provide the additional functionality necessary to 324 * support those modes of operation. 325 */ 326 KASSERT(((ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS) == 0), ("invalid " 327 "CAM flags %#x", (ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS))); 328 329 /* 330 * Simplify things on both sides by putting single buffers into a 331 * single entry S/G list. 332 */ 333 switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) { 334 case CAM_DATA_SG: { 335 int len_seen; 336 337 cam_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr; 338 cam_sg_count = ccb->csio.sglist_cnt; 339 cam_sg_start = cam_sg_count; 340 cam_sg_offset = 0; 341 342 for (i = 0, len_seen = 0; i < cam_sg_count; i++) { 343 if ((len_seen + cam_sglist[i].ds_len) >= 344 io->scsiio.kern_rel_offset) { 345 cam_sg_start = i; 346 cam_sg_offset = io->scsiio.kern_rel_offset - 347 len_seen; 348 break; 349 } 350 len_seen += cam_sglist[i].ds_len; 351 } 352 break; 353 } 354 case CAM_DATA_VADDR: 355 cam_sglist = &cam_sg_entry; 356 cam_sglist[0].ds_len = ccb->csio.dxfer_len; 357 cam_sglist[0].ds_addr = (bus_addr_t)(uintptr_t)ccb->csio.data_ptr; 358 cam_sg_count = 1; 359 cam_sg_start = 0; 360 cam_sg_offset = io->scsiio.kern_rel_offset; 361 break; 362 default: 363 panic("Invalid CAM flags %#x", ccb->ccb_h.flags); 364 } 365 366 if (io->scsiio.kern_sg_entries > 0) { 367 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; 368 ctl_sg_count = io->scsiio.kern_sg_entries; 369 } else { 370 ctl_sglist = &ctl_sg_entry; 371 ctl_sglist->addr = io->scsiio.kern_data_ptr; 372 ctl_sglist->len = io->scsiio.kern_data_len; 373 ctl_sg_count = 1; 374 } 375 376 ctl_watermark = 0; 377 cam_watermark = cam_sg_offset; 378 for (i = cam_sg_start, j = 0; 379 i < cam_sg_count && j < ctl_sg_count;) { 380 uint8_t *cam_ptr, *ctl_ptr; 381 382 len_to_copy = MIN(cam_sglist[i].ds_len - cam_watermark, 383 ctl_sglist[j].len - ctl_watermark); 384 385 cam_ptr = (uint8_t *)(uintptr_t)cam_sglist[i].ds_addr; 386 cam_ptr = cam_ptr + cam_watermark; 387 if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) { 388 /* 389 * XXX KDM fix this! 390 */ 391 panic("need to implement bus address support"); 392 #if 0 393 kern_ptr = bus_to_virt(kern_sglist[j].addr); 394 #endif 395 } else 396 ctl_ptr = (uint8_t *)ctl_sglist[j].addr; 397 ctl_ptr = ctl_ptr + ctl_watermark; 398 399 if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == 400 CTL_FLAG_DATA_IN) { 401 CTL_DEBUG_PRINT(("%s: copying %d bytes to CAM\n", 402 __func__, len_to_copy)); 403 CTL_DEBUG_PRINT(("%s: from %p to %p\n", ctl_ptr, 404 __func__, cam_ptr)); 405 bcopy(ctl_ptr, cam_ptr, len_to_copy); 406 } else { 407 CTL_DEBUG_PRINT(("%s: copying %d bytes from CAM\n", 408 __func__, len_to_copy)); 409 CTL_DEBUG_PRINT(("%s: from %p to %p\n", cam_ptr, 410 __func__, ctl_ptr)); 411 bcopy(cam_ptr, ctl_ptr, len_to_copy); 412 } 413 414 io->scsiio.ext_data_filled += len_to_copy; 415 io->scsiio.kern_data_resid -= len_to_copy; 416 417 cam_watermark += len_to_copy; 418 if (cam_sglist[i].ds_len == cam_watermark) { 419 i++; 420 cam_watermark = 0; 421 } 422 423 ctl_watermark += len_to_copy; 424 if (ctl_sglist[j].len == ctl_watermark) { 425 j++; 426 ctl_watermark = 0; 427 } 428 } 429 430 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { 431 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = NULL; 432 io->io_hdr.flags |= CTL_FLAG_STATUS_SENT; 433 ccb->csio.resid = ccb->csio.dxfer_len - 434 io->scsiio.ext_data_filled; 435 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 436 ccb->ccb_h.status |= CAM_REQ_CMP; 437 xpt_done(ccb); 438 } 439 440 io->scsiio.be_move_done(io); 441 } 442 443 static void 444 cfcs_done(union ctl_io *io) 445 { 446 union ccb *ccb; 447 448 ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 449 if (ccb == NULL) { 450 ctl_free_io(io); 451 return; 452 } 453 454 /* 455 * At this point we should have status. If we don't, that's a bug. 456 */ 457 KASSERT(((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE), 458 ("invalid CTL status %#x", io->io_hdr.status)); 459 460 /* 461 * Translate CTL status to CAM status. 462 */ 463 if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 464 ccb->csio.resid = ccb->csio.dxfer_len - 465 io->scsiio.ext_data_filled; 466 } 467 ccb->ccb_h.status &= ~CAM_STATUS_MASK; 468 switch (io->io_hdr.status & CTL_STATUS_MASK) { 469 case CTL_SUCCESS: 470 ccb->ccb_h.status |= CAM_REQ_CMP; 471 break; 472 case CTL_SCSI_ERROR: 473 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; 474 ccb->csio.scsi_status = io->scsiio.scsi_status; 475 bcopy(&io->scsiio.sense_data, &ccb->csio.sense_data, 476 min(io->scsiio.sense_len, ccb->csio.sense_len)); 477 if (ccb->csio.sense_len > io->scsiio.sense_len) 478 ccb->csio.sense_resid = ccb->csio.sense_len - 479 io->scsiio.sense_len; 480 else 481 ccb->csio.sense_resid = 0; 482 if ((ccb->csio.sense_len - ccb->csio.sense_resid) > 483 cfcs_max_sense) { 484 ccb->csio.sense_resid = ccb->csio.sense_len - 485 cfcs_max_sense; 486 } 487 break; 488 case CTL_CMD_ABORTED: 489 ccb->ccb_h.status |= CAM_REQ_ABORTED; 490 break; 491 case CTL_ERROR: 492 default: 493 ccb->ccb_h.status |= CAM_REQ_CMP_ERR; 494 break; 495 } 496 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP && 497 (ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 498 xpt_freeze_devq(ccb->ccb_h.path, 1); 499 ccb->ccb_h.status |= CAM_DEV_QFRZN; 500 } 501 xpt_done(ccb); 502 ctl_free_io(io); 503 } 504 505 void 506 cfcs_action(struct cam_sim *sim, union ccb *ccb) 507 { 508 struct cfcs_softc *softc; 509 int err; 510 511 softc = (struct cfcs_softc *)cam_sim_softc(sim); 512 mtx_assert(&softc->lock, MA_OWNED); 513 514 switch (ccb->ccb_h.func_code) { 515 case XPT_SCSI_IO: { 516 union ctl_io *io; 517 struct ccb_scsiio *csio; 518 519 csio = &ccb->csio; 520 521 /* 522 * Catch CCB flags, like physical address flags, that 523 * indicate situations we currently can't handle. 524 */ 525 if (ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS) { 526 ccb->ccb_h.status = CAM_REQ_INVALID; 527 printf("%s: bad CCB flags %#x (all flags %#x)\n", 528 __func__, ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS, 529 ccb->ccb_h.flags); 530 xpt_done(ccb); 531 return; 532 } 533 534 /* 535 * If we aren't online, there are no devices to see. 536 */ 537 if (softc->online == 0) { 538 ccb->ccb_h.status = CAM_DEV_NOT_THERE; 539 xpt_done(ccb); 540 return; 541 } 542 543 io = ctl_alloc_io_nowait(softc->port.ctl_pool_ref); 544 if (io == NULL) { 545 printf("%s: can't allocate ctl_io\n", __func__); 546 ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; 547 xpt_freeze_devq(ccb->ccb_h.path, 1); 548 xpt_done(ccb); 549 return; 550 } 551 ctl_zero_io(io); 552 /* Save pointers on both sides */ 553 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb; 554 ccb->ccb_h.io_ptr = io; 555 556 /* 557 * Only SCSI I/O comes down this path, resets, etc. come 558 * down via the XPT_RESET_BUS/LUN CCBs below. 559 */ 560 io->io_hdr.io_type = CTL_IO_SCSI; 561 io->io_hdr.nexus.initid = 1; 562 io->io_hdr.nexus.targ_port = softc->port.targ_port; 563 io->io_hdr.nexus.targ_lun = ctl_decode_lun( 564 CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun)); 565 /* 566 * This tag scheme isn't the best, since we could in theory 567 * have a very long-lived I/O and tag collision, especially 568 * in a high I/O environment. But it should work well 569 * enough for now. Since we're using unsigned ints, 570 * they'll just wrap around. 571 */ 572 io->scsiio.tag_num = softc->cur_tag_num++; 573 csio->tag_id = io->scsiio.tag_num; 574 switch (csio->tag_action) { 575 case CAM_TAG_ACTION_NONE: 576 io->scsiio.tag_type = CTL_TAG_UNTAGGED; 577 break; 578 case MSG_SIMPLE_TASK: 579 io->scsiio.tag_type = CTL_TAG_SIMPLE; 580 break; 581 case MSG_HEAD_OF_QUEUE_TASK: 582 io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE; 583 break; 584 case MSG_ORDERED_TASK: 585 io->scsiio.tag_type = CTL_TAG_ORDERED; 586 break; 587 case MSG_ACA_TASK: 588 io->scsiio.tag_type = CTL_TAG_ACA; 589 break; 590 default: 591 io->scsiio.tag_type = CTL_TAG_UNTAGGED; 592 printf("%s: unhandled tag type %#x!!\n", __func__, 593 csio->tag_action); 594 break; 595 } 596 if (csio->cdb_len > sizeof(io->scsiio.cdb)) { 597 printf("%s: WARNING: CDB len %d > ctl_io space %zd\n", 598 __func__, csio->cdb_len, sizeof(io->scsiio.cdb)); 599 } 600 io->scsiio.cdb_len = min(csio->cdb_len, sizeof(io->scsiio.cdb)); 601 bcopy(scsiio_cdb_ptr(csio), io->scsiio.cdb, io->scsiio.cdb_len); 602 603 ccb->ccb_h.status |= CAM_SIM_QUEUED; 604 err = ctl_queue(io); 605 if (err != CTL_RETVAL_COMPLETE) { 606 printf("%s: func %d: error %d returned by " 607 "ctl_queue()!\n", __func__, 608 ccb->ccb_h.func_code, err); 609 ctl_free_io(io); 610 ccb->ccb_h.status = CAM_REQ_INVALID; 611 xpt_done(ccb); 612 return; 613 } 614 break; 615 } 616 case XPT_ABORT: { 617 union ctl_io *io; 618 union ccb *abort_ccb; 619 620 abort_ccb = ccb->cab.abort_ccb; 621 622 if (abort_ccb->ccb_h.func_code != XPT_SCSI_IO) { 623 ccb->ccb_h.status = CAM_REQ_INVALID; 624 xpt_done(ccb); 625 } 626 627 /* 628 * If we aren't online, there are no devices to talk to. 629 */ 630 if (softc->online == 0) { 631 ccb->ccb_h.status = CAM_DEV_NOT_THERE; 632 xpt_done(ccb); 633 return; 634 } 635 636 io = ctl_alloc_io_nowait(softc->port.ctl_pool_ref); 637 if (io == NULL) { 638 ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; 639 xpt_freeze_devq(ccb->ccb_h.path, 1); 640 xpt_done(ccb); 641 return; 642 } 643 644 ctl_zero_io(io); 645 /* Save pointers on both sides */ 646 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb; 647 ccb->ccb_h.io_ptr = io; 648 649 io->io_hdr.io_type = CTL_IO_TASK; 650 io->io_hdr.nexus.initid = 1; 651 io->io_hdr.nexus.targ_port = softc->port.targ_port; 652 io->io_hdr.nexus.targ_lun = ctl_decode_lun( 653 CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun)); 654 io->taskio.task_action = CTL_TASK_ABORT_TASK; 655 io->taskio.tag_num = abort_ccb->csio.tag_id; 656 switch (abort_ccb->csio.tag_action) { 657 case CAM_TAG_ACTION_NONE: 658 io->taskio.tag_type = CTL_TAG_UNTAGGED; 659 break; 660 case MSG_SIMPLE_TASK: 661 io->taskio.tag_type = CTL_TAG_SIMPLE; 662 break; 663 case MSG_HEAD_OF_QUEUE_TASK: 664 io->taskio.tag_type = CTL_TAG_HEAD_OF_QUEUE; 665 break; 666 case MSG_ORDERED_TASK: 667 io->taskio.tag_type = CTL_TAG_ORDERED; 668 break; 669 case MSG_ACA_TASK: 670 io->taskio.tag_type = CTL_TAG_ACA; 671 break; 672 default: 673 io->taskio.tag_type = CTL_TAG_UNTAGGED; 674 printf("%s: unhandled tag type %#x!!\n", __func__, 675 abort_ccb->csio.tag_action); 676 break; 677 } 678 err = ctl_queue(io); 679 if (err != CTL_RETVAL_COMPLETE) { 680 printf("%s func %d: error %d returned by " 681 "ctl_queue()!\n", __func__, 682 ccb->ccb_h.func_code, err); 683 ctl_free_io(io); 684 } 685 break; 686 } 687 case XPT_GET_TRAN_SETTINGS: { 688 struct ccb_trans_settings *cts; 689 struct ccb_trans_settings_scsi *scsi; 690 struct ccb_trans_settings_fc *fc; 691 692 cts = &ccb->cts; 693 scsi = &cts->proto_specific.scsi; 694 fc = &cts->xport_specific.fc; 695 696 697 cts->protocol = PROTO_SCSI; 698 cts->protocol_version = SCSI_REV_SPC2; 699 cts->transport = XPORT_FC; 700 cts->transport_version = 0; 701 702 scsi->valid = CTS_SCSI_VALID_TQ; 703 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 704 fc->valid = CTS_FC_VALID_SPEED; 705 fc->bitrate = 800000; 706 fc->wwnn = softc->wwnn; 707 fc->wwpn = softc->wwpn; 708 fc->port = softc->port.targ_port; 709 fc->valid |= CTS_FC_VALID_WWNN | CTS_FC_VALID_WWPN | 710 CTS_FC_VALID_PORT; 711 ccb->ccb_h.status = CAM_REQ_CMP; 712 break; 713 } 714 case XPT_SET_TRAN_SETTINGS: 715 /* XXX KDM should we actually do something here? */ 716 ccb->ccb_h.status = CAM_REQ_CMP; 717 break; 718 case XPT_RESET_BUS: 719 case XPT_RESET_DEV: { 720 union ctl_io *io; 721 722 /* 723 * If we aren't online, there are no devices to talk to. 724 */ 725 if (softc->online == 0) { 726 ccb->ccb_h.status = CAM_DEV_NOT_THERE; 727 xpt_done(ccb); 728 return; 729 } 730 731 io = ctl_alloc_io_nowait(softc->port.ctl_pool_ref); 732 if (io == NULL) { 733 ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; 734 xpt_freeze_devq(ccb->ccb_h.path, 1); 735 xpt_done(ccb); 736 return; 737 } 738 739 ctl_zero_io(io); 740 /* Save pointers on both sides */ 741 if (ccb->ccb_h.func_code == XPT_RESET_DEV) 742 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb; 743 ccb->ccb_h.io_ptr = io; 744 745 io->io_hdr.io_type = CTL_IO_TASK; 746 io->io_hdr.nexus.initid = 1; 747 io->io_hdr.nexus.targ_port = softc->port.targ_port; 748 io->io_hdr.nexus.targ_lun = ctl_decode_lun( 749 CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun)); 750 if (ccb->ccb_h.func_code == XPT_RESET_BUS) 751 io->taskio.task_action = CTL_TASK_BUS_RESET; 752 else 753 io->taskio.task_action = CTL_TASK_LUN_RESET; 754 755 err = ctl_queue(io); 756 if (err != CTL_RETVAL_COMPLETE) { 757 printf("%s func %d: error %d returned by " 758 "ctl_queue()!\n", __func__, 759 ccb->ccb_h.func_code, err); 760 ctl_free_io(io); 761 } 762 break; 763 } 764 case XPT_CALC_GEOMETRY: 765 cam_calc_geometry(&ccb->ccg, 1); 766 xpt_done(ccb); 767 break; 768 case XPT_PATH_INQ: { 769 struct ccb_pathinq *cpi; 770 771 cpi = &ccb->cpi; 772 773 cpi->version_num = 0; 774 cpi->hba_inquiry = PI_TAG_ABLE; 775 cpi->target_sprt = 0; 776 cpi->hba_misc = PIM_EXTLUNS; 777 cpi->hba_eng_cnt = 0; 778 cpi->max_target = 1; 779 cpi->max_lun = 1024; 780 /* Do we really have a limit? */ 781 cpi->maxio = 1024 * 1024; 782 cpi->async_flags = 0; 783 cpi->hpath_id = 0; 784 cpi->initiator_id = 0; 785 786 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 787 strlcpy(cpi->hba_vid, "FreeBSD", HBA_IDLEN); 788 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 789 cpi->unit_number = 0; 790 cpi->bus_id = 0; 791 cpi->base_transfer_speed = 800000; 792 cpi->protocol = PROTO_SCSI; 793 cpi->protocol_version = SCSI_REV_SPC2; 794 /* 795 * Pretend to be Fibre Channel. 796 */ 797 cpi->transport = XPORT_FC; 798 cpi->transport_version = 0; 799 cpi->xport_specific.fc.wwnn = softc->wwnn; 800 cpi->xport_specific.fc.wwpn = softc->wwpn; 801 cpi->xport_specific.fc.port = softc->port.targ_port; 802 cpi->xport_specific.fc.bitrate = 8 * 1000 * 1000; 803 cpi->ccb_h.status = CAM_REQ_CMP; 804 break; 805 } 806 default: 807 ccb->ccb_h.status = CAM_PROVIDE_FAIL; 808 printf("%s: unsupported CCB type %#x\n", __func__, 809 ccb->ccb_h.func_code); 810 xpt_done(ccb); 811 break; 812 } 813 } 814