1 /* $OpenBSD: vscsi.c,v 1.62 2023/10/25 09:36:47 mvs Exp $ */ 2 3 /* 4 * Copyright (c) 2008 David Gwynne <dlg@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/kernel.h> 22 #include <sys/malloc.h> 23 #include <sys/device.h> 24 #include <sys/conf.h> 25 #include <sys/queue.h> 26 #include <sys/rwlock.h> 27 #include <sys/pool.h> 28 #include <sys/task.h> 29 #include <sys/ioctl.h> 30 #include <sys/event.h> 31 32 #include <scsi/scsi_all.h> 33 #include <scsi/scsiconf.h> 34 35 #include <dev/vscsivar.h> 36 37 /* 38 * Locks used to protect struct members and global data 39 * s sc_state_mtx 40 */ 41 42 int vscsi_match(struct device *, void *, void *); 43 void vscsi_attach(struct device *, struct device *, void *); 44 void vscsi_shutdown(void *); 45 46 struct vscsi_ccb { 47 TAILQ_ENTRY(vscsi_ccb) ccb_entry; 48 int ccb_tag; 49 struct scsi_xfer *ccb_xs; 50 size_t ccb_datalen; 51 }; 52 53 TAILQ_HEAD(vscsi_ccb_list, vscsi_ccb); 54 55 enum vscsi_state { 56 VSCSI_S_CLOSED, 57 VSCSI_S_CONFIG, 58 VSCSI_S_RUNNING 59 }; 60 61 struct vscsi_softc { 62 struct device sc_dev; 63 struct scsibus_softc *sc_scsibus; 64 65 struct mutex sc_state_mtx; 66 enum vscsi_state sc_state; 67 u_int sc_ref_count; 68 struct pool sc_ccb_pool; 69 70 struct scsi_iopool sc_iopool; 71 72 struct vscsi_ccb_list sc_ccb_i2t; /* [s] */ 73 struct vscsi_ccb_list sc_ccb_t2i; 74 int sc_ccb_tag; 75 struct mutex sc_poll_mtx; 76 struct rwlock sc_ioc_lock; 77 78 struct klist sc_klist; /* [s] */ 79 }; 80 81 #define DEVNAME(_s) ((_s)->sc_dev.dv_xname) 82 #define DEV2SC(_d) ((struct vscsi_softc *)device_lookup(&vscsi_cd, minor(_d))) 83 84 const struct cfattach vscsi_ca = { 85 sizeof(struct vscsi_softc), 86 vscsi_match, 87 vscsi_attach 88 }; 89 90 struct cfdriver vscsi_cd = { 91 NULL, 92 "vscsi", 93 DV_DULL 94 }; 95 96 void vscsi_cmd(struct scsi_xfer *); 97 int vscsi_probe(struct scsi_link *); 98 void vscsi_free(struct scsi_link *); 99 100 const struct scsi_adapter vscsi_switch = { 101 vscsi_cmd, NULL, vscsi_probe, vscsi_free, NULL 102 }; 103 104 int vscsi_i2t(struct vscsi_softc *, struct vscsi_ioc_i2t *); 105 int vscsi_data(struct vscsi_softc *, struct vscsi_ioc_data *, int); 106 int vscsi_t2i(struct vscsi_softc *, struct vscsi_ioc_t2i *); 107 int vscsi_devevent(struct vscsi_softc *, u_long, 108 struct vscsi_ioc_devevent *); 109 void vscsi_devevent_task(void *); 110 void vscsi_done(struct vscsi_softc *, struct vscsi_ccb *); 111 112 void * vscsi_ccb_get(void *); 113 void vscsi_ccb_put(void *, void *); 114 115 void filt_vscsidetach(struct knote *); 116 int filt_vscsiread(struct knote *, long); 117 int filt_vscsimodify(struct kevent *, struct knote *); 118 int filt_vscsiprocess(struct knote *, struct kevent *); 119 120 const struct filterops vscsi_filtops = { 121 .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, 122 .f_attach = NULL, 123 .f_detach = filt_vscsidetach, 124 .f_event = filt_vscsiread, 125 .f_modify = filt_vscsimodify, 126 .f_process = filt_vscsiprocess, 127 }; 128 129 130 int 131 vscsi_match(struct device *parent, void *match, void *aux) 132 { 133 return (1); 134 } 135 136 void 137 vscsi_attach(struct device *parent, struct device *self, void *aux) 138 { 139 struct vscsi_softc *sc = (struct vscsi_softc *)self; 140 struct scsibus_attach_args saa; 141 142 printf("\n"); 143 144 mtx_init(&sc->sc_state_mtx, IPL_MPFLOOR); 145 sc->sc_state = VSCSI_S_CLOSED; 146 147 TAILQ_INIT(&sc->sc_ccb_i2t); 148 TAILQ_INIT(&sc->sc_ccb_t2i); 149 mtx_init(&sc->sc_poll_mtx, IPL_BIO); 150 rw_init(&sc->sc_ioc_lock, "vscsiioc"); 151 scsi_iopool_init(&sc->sc_iopool, sc, vscsi_ccb_get, vscsi_ccb_put); 152 klist_init_mutex(&sc->sc_klist, &sc->sc_state_mtx); 153 154 saa.saa_adapter = &vscsi_switch; 155 saa.saa_adapter_softc = sc; 156 saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET; 157 saa.saa_adapter_buswidth = 256; 158 saa.saa_luns = 8; 159 saa.saa_openings = 16; 160 saa.saa_pool = &sc->sc_iopool; 161 saa.saa_quirks = saa.saa_flags = 0; 162 saa.saa_wwpn = saa.saa_wwnn = 0; 163 164 sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev, 165 &saa, scsiprint); 166 } 167 168 void 169 vscsi_cmd(struct scsi_xfer *xs) 170 { 171 struct scsi_link *link = xs->sc_link; 172 struct vscsi_softc *sc = link->bus->sb_adapter_softc; 173 struct vscsi_ccb *ccb = xs->io; 174 int polled = ISSET(xs->flags, SCSI_POLL); 175 int running = 0; 176 177 if (ISSET(xs->flags, SCSI_POLL) && ISSET(xs->flags, SCSI_NOSLEEP)) { 178 printf("%s: POLL && NOSLEEP for 0x%02x\n", DEVNAME(sc), 179 xs->cmd.opcode); 180 xs->error = XS_DRIVER_STUFFUP; 181 scsi_done(xs); 182 return; 183 } 184 185 ccb->ccb_xs = xs; 186 187 mtx_enter(&sc->sc_state_mtx); 188 if (sc->sc_state == VSCSI_S_RUNNING) { 189 running = 1; 190 TAILQ_INSERT_TAIL(&sc->sc_ccb_i2t, ccb, ccb_entry); 191 } 192 knote_locked(&sc->sc_klist, 0); 193 mtx_leave(&sc->sc_state_mtx); 194 195 if (!running) { 196 xs->error = XS_DRIVER_STUFFUP; 197 scsi_done(xs); 198 return; 199 } 200 201 if (polled) { 202 mtx_enter(&sc->sc_poll_mtx); 203 while (ccb->ccb_xs != NULL) 204 msleep_nsec(ccb, &sc->sc_poll_mtx, PRIBIO, "vscsipoll", 205 INFSLP); 206 mtx_leave(&sc->sc_poll_mtx); 207 scsi_done(xs); 208 } 209 } 210 211 void 212 vscsi_done(struct vscsi_softc *sc, struct vscsi_ccb *ccb) 213 { 214 struct scsi_xfer *xs = ccb->ccb_xs; 215 216 if (ISSET(xs->flags, SCSI_POLL)) { 217 mtx_enter(&sc->sc_poll_mtx); 218 ccb->ccb_xs = NULL; 219 wakeup(ccb); 220 mtx_leave(&sc->sc_poll_mtx); 221 } else 222 scsi_done(xs); 223 } 224 225 int 226 vscsi_probe(struct scsi_link *link) 227 { 228 struct vscsi_softc *sc = link->bus->sb_adapter_softc; 229 int rv = 0; 230 231 mtx_enter(&sc->sc_state_mtx); 232 if (sc->sc_state == VSCSI_S_RUNNING) 233 sc->sc_ref_count++; 234 else 235 rv = ENXIO; 236 mtx_leave(&sc->sc_state_mtx); 237 238 return (rv); 239 } 240 241 void 242 vscsi_free(struct scsi_link *link) 243 { 244 struct vscsi_softc *sc = link->bus->sb_adapter_softc; 245 246 mtx_enter(&sc->sc_state_mtx); 247 sc->sc_ref_count--; 248 if (sc->sc_state != VSCSI_S_RUNNING && sc->sc_ref_count == 0) 249 wakeup(&sc->sc_ref_count); 250 mtx_leave(&sc->sc_state_mtx); 251 } 252 253 int 254 vscsiopen(dev_t dev, int flags, int mode, struct proc *p) 255 { 256 struct vscsi_softc *sc = DEV2SC(dev); 257 enum vscsi_state state = VSCSI_S_RUNNING; 258 int rv = 0; 259 260 if (sc == NULL) 261 return (ENXIO); 262 263 mtx_enter(&sc->sc_state_mtx); 264 if (sc->sc_state != VSCSI_S_CLOSED) 265 rv = EBUSY; 266 else 267 sc->sc_state = VSCSI_S_CONFIG; 268 mtx_leave(&sc->sc_state_mtx); 269 270 if (rv != 0) { 271 device_unref(&sc->sc_dev); 272 return (rv); 273 } 274 275 pool_init(&sc->sc_ccb_pool, sizeof(struct vscsi_ccb), 0, IPL_BIO, 0, 276 "vscsiccb", NULL); 277 278 /* we need to guarantee some ccbs will be available for the iopool */ 279 rv = pool_prime(&sc->sc_ccb_pool, 8); 280 if (rv != 0) { 281 pool_destroy(&sc->sc_ccb_pool); 282 state = VSCSI_S_CLOSED; 283 } 284 285 /* commit changes */ 286 mtx_enter(&sc->sc_state_mtx); 287 sc->sc_state = state; 288 mtx_leave(&sc->sc_state_mtx); 289 290 device_unref(&sc->sc_dev); 291 return (rv); 292 } 293 294 int 295 vscsiioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 296 { 297 struct vscsi_softc *sc = DEV2SC(dev); 298 int read = 0; 299 int err = 0; 300 301 if (sc == NULL) 302 return (ENXIO); 303 304 rw_enter_write(&sc->sc_ioc_lock); 305 306 switch (cmd) { 307 case VSCSI_I2T: 308 err = vscsi_i2t(sc, (struct vscsi_ioc_i2t *)addr); 309 break; 310 311 case VSCSI_DATA_READ: 312 read = 1; 313 case VSCSI_DATA_WRITE: 314 err = vscsi_data(sc, (struct vscsi_ioc_data *)addr, read); 315 break; 316 317 case VSCSI_T2I: 318 err = vscsi_t2i(sc, (struct vscsi_ioc_t2i *)addr); 319 break; 320 321 case VSCSI_REQPROBE: 322 case VSCSI_REQDETACH: 323 err = vscsi_devevent(sc, cmd, 324 (struct vscsi_ioc_devevent *)addr); 325 break; 326 327 default: 328 err = ENOTTY; 329 break; 330 } 331 332 rw_exit_write(&sc->sc_ioc_lock); 333 334 device_unref(&sc->sc_dev); 335 return (err); 336 } 337 338 int 339 vscsi_i2t(struct vscsi_softc *sc, struct vscsi_ioc_i2t *i2t) 340 { 341 struct vscsi_ccb *ccb; 342 struct scsi_xfer *xs; 343 struct scsi_link *link; 344 345 mtx_enter(&sc->sc_state_mtx); 346 ccb = TAILQ_FIRST(&sc->sc_ccb_i2t); 347 if (ccb != NULL) 348 TAILQ_REMOVE(&sc->sc_ccb_i2t, ccb, ccb_entry); 349 mtx_leave(&sc->sc_state_mtx); 350 351 if (ccb == NULL) 352 return (EAGAIN); 353 354 xs = ccb->ccb_xs; 355 link = xs->sc_link; 356 357 i2t->tag = ccb->ccb_tag; 358 i2t->target = link->target; 359 i2t->lun = link->lun; 360 memcpy(&i2t->cmd, &xs->cmd, xs->cmdlen); 361 i2t->cmdlen = xs->cmdlen; 362 i2t->datalen = xs->datalen; 363 364 switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { 365 case SCSI_DATA_IN: 366 i2t->direction = VSCSI_DIR_READ; 367 break; 368 case SCSI_DATA_OUT: 369 i2t->direction = VSCSI_DIR_WRITE; 370 break; 371 default: 372 i2t->direction = VSCSI_DIR_NONE; 373 break; 374 } 375 376 TAILQ_INSERT_TAIL(&sc->sc_ccb_t2i, ccb, ccb_entry); 377 378 return (0); 379 } 380 381 int 382 vscsi_data(struct vscsi_softc *sc, struct vscsi_ioc_data *data, int read) 383 { 384 struct vscsi_ccb *ccb; 385 struct scsi_xfer *xs; 386 int xsread; 387 u_int8_t *buf; 388 int rv = EINVAL; 389 390 TAILQ_FOREACH(ccb, &sc->sc_ccb_t2i, ccb_entry) { 391 if (ccb->ccb_tag == data->tag) 392 break; 393 } 394 if (ccb == NULL) 395 return (EFAULT); 396 397 xs = ccb->ccb_xs; 398 399 if (data->datalen > xs->datalen - ccb->ccb_datalen) 400 return (ENOMEM); 401 402 switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { 403 case SCSI_DATA_IN: 404 xsread = 1; 405 break; 406 case SCSI_DATA_OUT: 407 xsread = 0; 408 break; 409 default: 410 return (EINVAL); 411 } 412 413 if (read != xsread) 414 return (EINVAL); 415 416 buf = xs->data; 417 buf += ccb->ccb_datalen; 418 419 if (read) 420 rv = copyin(data->data, buf, data->datalen); 421 else 422 rv = copyout(buf, data->data, data->datalen); 423 424 if (rv == 0) 425 ccb->ccb_datalen += data->datalen; 426 427 return (rv); 428 } 429 430 int 431 vscsi_t2i(struct vscsi_softc *sc, struct vscsi_ioc_t2i *t2i) 432 { 433 struct vscsi_ccb *ccb; 434 struct scsi_xfer *xs; 435 int rv = 0; 436 437 TAILQ_FOREACH(ccb, &sc->sc_ccb_t2i, ccb_entry) { 438 if (ccb->ccb_tag == t2i->tag) 439 break; 440 } 441 if (ccb == NULL) 442 return (EFAULT); 443 444 TAILQ_REMOVE(&sc->sc_ccb_t2i, ccb, ccb_entry); 445 446 xs = ccb->ccb_xs; 447 448 xs->resid = xs->datalen - ccb->ccb_datalen; 449 xs->status = SCSI_OK; 450 451 switch (t2i->status) { 452 case VSCSI_STAT_DONE: 453 xs->error = XS_NOERROR; 454 break; 455 case VSCSI_STAT_SENSE: 456 xs->error = XS_SENSE; 457 memcpy(&xs->sense, &t2i->sense, sizeof(xs->sense)); 458 break; 459 case VSCSI_STAT_RESET: 460 xs->error = XS_RESET; 461 break; 462 case VSCSI_STAT_ERR: 463 default: 464 xs->error = XS_DRIVER_STUFFUP; 465 break; 466 } 467 468 vscsi_done(sc, ccb); 469 470 return (rv); 471 } 472 473 struct vscsi_devevent_task { 474 struct vscsi_softc *sc; 475 struct task t; 476 struct vscsi_ioc_devevent de; 477 u_long cmd; 478 }; 479 480 int 481 vscsi_devevent(struct vscsi_softc *sc, u_long cmd, 482 struct vscsi_ioc_devevent *de) 483 { 484 struct vscsi_devevent_task *dt; 485 486 dt = malloc(sizeof(*dt), M_TEMP, M_WAITOK | M_CANFAIL); 487 if (dt == NULL) 488 return (ENOMEM); 489 490 task_set(&dt->t, vscsi_devevent_task, dt); 491 dt->sc = sc; 492 dt->de = *de; 493 dt->cmd = cmd; 494 495 device_ref(&sc->sc_dev); 496 task_add(systq, &dt->t); 497 498 return (0); 499 } 500 501 void 502 vscsi_devevent_task(void *xdt) 503 { 504 struct vscsi_devevent_task *dt = xdt; 505 struct vscsi_softc *sc = dt->sc; 506 int state; 507 508 mtx_enter(&sc->sc_state_mtx); 509 state = sc->sc_state; 510 mtx_leave(&sc->sc_state_mtx); 511 512 if (state != VSCSI_S_RUNNING) 513 goto gone; 514 515 switch (dt->cmd) { 516 case VSCSI_REQPROBE: 517 scsi_probe(sc->sc_scsibus, dt->de.target, dt->de.lun); 518 break; 519 case VSCSI_REQDETACH: 520 scsi_detach(sc->sc_scsibus, dt->de.target, dt->de.lun, 521 DETACH_FORCE); 522 break; 523 #ifdef DIAGNOSTIC 524 default: 525 panic("unexpected vscsi_devevent cmd"); 526 /* NOTREACHED */ 527 #endif 528 } 529 530 gone: 531 device_unref(&sc->sc_dev); 532 533 free(dt, M_TEMP, sizeof(*dt)); 534 } 535 536 int 537 vscsikqfilter(dev_t dev, struct knote *kn) 538 { 539 struct vscsi_softc *sc = DEV2SC(dev); 540 541 if (sc == NULL) 542 return (ENXIO); 543 544 switch (kn->kn_filter) { 545 case EVFILT_READ: 546 kn->kn_fop = &vscsi_filtops; 547 break; 548 default: 549 device_unref(&sc->sc_dev); 550 return (EINVAL); 551 } 552 553 kn->kn_hook = sc; 554 klist_insert(&sc->sc_klist, kn); 555 556 /* device ref is given to the knote in the klist */ 557 558 return (0); 559 } 560 561 void 562 filt_vscsidetach(struct knote *kn) 563 { 564 struct vscsi_softc *sc = kn->kn_hook; 565 566 klist_remove(&sc->sc_klist, kn); 567 device_unref(&sc->sc_dev); 568 } 569 570 int 571 filt_vscsiread(struct knote *kn, long hint) 572 { 573 struct vscsi_softc *sc = kn->kn_hook; 574 575 return (!TAILQ_EMPTY(&sc->sc_ccb_i2t)); 576 } 577 578 int 579 filt_vscsimodify(struct kevent *kev, struct knote *kn) 580 { 581 struct vscsi_softc *sc = kn->kn_hook; 582 int active; 583 584 mtx_enter(&sc->sc_state_mtx); 585 active = knote_modify(kev, kn); 586 mtx_leave(&sc->sc_state_mtx); 587 588 return (active); 589 } 590 591 int 592 filt_vscsiprocess(struct knote *kn, struct kevent *kev) 593 { 594 struct vscsi_softc *sc = kn->kn_hook; 595 int active; 596 597 mtx_enter(&sc->sc_state_mtx); 598 active = knote_process(kn, kev); 599 mtx_leave(&sc->sc_state_mtx); 600 601 return (active); 602 } 603 604 int 605 vscsiclose(dev_t dev, int flags, int mode, struct proc *p) 606 { 607 struct vscsi_softc *sc = DEV2SC(dev); 608 struct vscsi_ccb *ccb; 609 610 if (sc == NULL) 611 return (ENXIO); 612 613 mtx_enter(&sc->sc_state_mtx); 614 KASSERT(sc->sc_state == VSCSI_S_RUNNING); 615 sc->sc_state = VSCSI_S_CONFIG; 616 mtx_leave(&sc->sc_state_mtx); 617 618 scsi_activate(sc->sc_scsibus, -1, -1, DVACT_DEACTIVATE); 619 620 while ((ccb = TAILQ_FIRST(&sc->sc_ccb_t2i)) != NULL) { 621 TAILQ_REMOVE(&sc->sc_ccb_t2i, ccb, ccb_entry); 622 ccb->ccb_xs->error = XS_RESET; 623 vscsi_done(sc, ccb); 624 } 625 626 while ((ccb = TAILQ_FIRST(&sc->sc_ccb_i2t)) != NULL) { 627 TAILQ_REMOVE(&sc->sc_ccb_i2t, ccb, ccb_entry); 628 ccb->ccb_xs->error = XS_RESET; 629 vscsi_done(sc, ccb); 630 } 631 632 scsi_req_detach(sc->sc_scsibus, -1, -1, DETACH_FORCE); 633 634 mtx_enter(&sc->sc_state_mtx); 635 while (sc->sc_ref_count > 0) { 636 msleep_nsec(&sc->sc_ref_count, &sc->sc_state_mtx, 637 PRIBIO, "vscsiref", INFSLP); 638 } 639 mtx_leave(&sc->sc_state_mtx); 640 641 pool_destroy(&sc->sc_ccb_pool); 642 643 mtx_enter(&sc->sc_state_mtx); 644 sc->sc_state = VSCSI_S_CLOSED; 645 mtx_leave(&sc->sc_state_mtx); 646 647 device_unref(&sc->sc_dev); 648 return (0); 649 } 650 651 void * 652 vscsi_ccb_get(void *cookie) 653 { 654 struct vscsi_softc *sc = cookie; 655 struct vscsi_ccb *ccb = NULL; 656 657 ccb = pool_get(&sc->sc_ccb_pool, PR_NOWAIT); 658 if (ccb != NULL) { 659 ccb->ccb_tag = sc->sc_ccb_tag++; 660 ccb->ccb_datalen = 0; 661 } 662 663 return (ccb); 664 } 665 666 void 667 vscsi_ccb_put(void *cookie, void *io) 668 { 669 struct vscsi_softc *sc = cookie; 670 struct vscsi_ccb *ccb = io; 671 672 pool_put(&sc->sc_ccb_pool, ccb); 673 } 674