1 /* $NetBSD: vioscsi.c,v 1.37 2026/08/16 23:39:51 tls Exp $ */ 2 /* $OpenBSD: vioscsi.c,v 1.3 2015/03/14 03:38:49 jsg Exp $ */ 3 4 /* 5 * Copyright (c) 2013 Google Inc. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/cdefs.h> 21 __KERNEL_RCSID(0, "$NetBSD: vioscsi.c,v 1.37 2026/08/16 23:39:51 tls Exp $"); 22 23 #ifdef _KERNEL_OPT 24 #include "opt_vioscsi.h" 25 #endif 26 27 #include <sys/param.h> 28 #include <sys/systm.h> 29 #include <sys/device.h> 30 #include <sys/bus.h> 31 #include <sys/buf.h> 32 #include <sys/module.h> 33 34 #include <dev/pci/vioscsireg.h> 35 #include <dev/pci/virtiovar.h> 36 37 #include <dev/scsipi/scsi_all.h> 38 #include <dev/scsipi/scsiconf.h> 39 40 #ifndef VIOSCSI_MAX_TARGET 41 #define VIOSCSI_MAX_TARGET 256 42 #endif 43 #ifndef VIOSCSI_MAX_LUN 44 #define VIOSCSI_MAX_LUN 16384 45 #endif 46 47 #ifdef VIOSCSI_DEBUG 48 static int vioscsi_debug = 1; 49 #define DPRINTF(f) do { if (vioscsi_debug) printf f; } while (/*CONSTCOND*/0) 50 #else 51 #define DPRINTF(f) ((void)0) 52 #endif 53 54 struct vioscsi_req { 55 struct virtio_scsi_req_hdr vr_req; 56 struct virtio_scsi_res_hdr vr_res; 57 struct scsipi_xfer *vr_xs; 58 bus_dmamap_t vr_control; 59 bus_dmamap_t vr_data; 60 }; 61 62 struct vioscsi_softc { 63 device_t sc_dev; 64 struct scsipi_adapter sc_adapter; 65 struct scsipi_channel sc_channel; 66 67 struct virtqueue sc_vqs[3]; 68 #define VIOSCSI_VQ_CONTROL 0 69 #define VIOSCSI_VQ_EVENT 1 70 #define VIOSCSI_VQ_REQUEST 2 71 72 struct vioscsi_req *sc_reqs; 73 int sc_nreqs; 74 bus_dma_segment_t sc_reqs_segs[1]; 75 76 u_int32_t sc_seg_max; 77 78 kmutex_t sc_mutex; 79 }; 80 81 /* 82 * Each block request uses at least two segments - one for the header 83 * and one for the status. 84 */ 85 #define VIRTIO_SCSI_MIN_SEGMENTS 2 86 87 static int vioscsi_match(device_t, cfdata_t, void *); 88 static void vioscsi_attach(device_t, device_t, void *); 89 static int vioscsi_detach(device_t, int); 90 91 static int vioscsi_alloc_reqs(struct vioscsi_softc *, 92 struct virtio_softc *, int); 93 static void vioscsi_free_reqs(struct vioscsi_softc *, 94 struct virtio_softc *); 95 static void vioscsi_scsipi_request(struct scsipi_channel *, 96 scsipi_adapter_req_t, void *); 97 static int vioscsi_vq_done(struct virtqueue *); 98 static void vioscsi_req_done(struct vioscsi_softc *, struct virtio_softc *, 99 struct vioscsi_req *, struct virtqueue *, int); 100 static struct vioscsi_req *vioscsi_req_get(struct vioscsi_softc *); 101 static void vioscsi_bad_target(struct scsipi_xfer *); 102 103 static const char *const vioscsi_vq_names[] = { 104 "control", 105 "event", 106 "request", 107 }; 108 109 CFATTACH_DECL3_NEW(vioscsi, sizeof(struct vioscsi_softc), 110 vioscsi_match, vioscsi_attach, vioscsi_detach, NULL, NULL, NULL, 111 DVF_DETACH_SHUTDOWN); 112 113 static int 114 vioscsi_match(device_t parent, cfdata_t match, void *aux) 115 { 116 struct virtio_attach_args *va = aux; 117 118 if (va->sc_childdevid == VIRTIO_DEVICE_ID_SCSI) 119 return 1; 120 121 return 0; 122 } 123 124 static void 125 vioscsi_attach(device_t parent, device_t self, void *aux) 126 { 127 struct vioscsi_softc *sc = device_private(self); 128 struct virtio_softc *vsc = device_private(parent); 129 struct scsipi_adapter *adapt = &sc->sc_adapter; 130 struct scsipi_channel *chan = &sc->sc_channel; 131 int rv, qsize = 0, i = 0; 132 int ipl = IPL_BIO; 133 134 if (virtio_child(vsc) != NULL) { 135 aprint_error(": parent %s already has a child\n", 136 device_xname(parent)); 137 return; 138 } 139 140 sc->sc_dev = self; 141 142 virtio_child_attach_start(vsc, self, ipl, 143 0, VIRTIO_COMMON_FLAG_BITS); 144 145 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, ipl); 146 147 uint32_t cmd_per_lun = virtio_read_device_config_4(vsc, 148 VIRTIO_SCSI_CONFIG_CMD_PER_LUN); 149 150 uint32_t seg_max = virtio_read_device_config_4(vsc, 151 VIRTIO_SCSI_CONFIG_SEG_MAX); 152 153 uint16_t max_target = virtio_read_device_config_2(vsc, 154 VIRTIO_SCSI_CONFIG_MAX_TARGET); 155 156 uint32_t max_lun = virtio_read_device_config_4(vsc, 157 VIRTIO_SCSI_CONFIG_MAX_LUN); 158 159 sc->sc_seg_max = seg_max; 160 161 for(i=0; i < __arraycount(sc->sc_vqs); i++) { 162 virtio_init_vq_vqdone(vsc, &sc->sc_vqs[i], i, 163 vioscsi_vq_done); 164 rv = virtio_alloc_vq(vsc, &sc->sc_vqs[i], MAXPHYS, 165 VIRTIO_SCSI_MIN_SEGMENTS + howmany(MAXPHYS, NBPG), 166 vioscsi_vq_names[i]); 167 if (rv) { 168 aprint_error_dev(sc->sc_dev, 169 "failed to allocate virtqueue %d\n", i); 170 goto err; 171 } 172 173 if (i == VIOSCSI_VQ_REQUEST) 174 sc->sc_vqs[i].vq_done = vioscsi_vq_done; 175 } 176 177 qsize = sc->sc_vqs[VIOSCSI_VQ_REQUEST].vq_num; 178 if (vioscsi_alloc_reqs(sc, vsc, qsize)) 179 goto err; 180 181 aprint_normal_dev(sc->sc_dev, 182 "cmd_per_lun %u qsize %d seg_max %u max_target %hu" 183 " max_lun %u\n", 184 cmd_per_lun, qsize, seg_max, max_target, max_lun); 185 186 if (virtio_child_attach_finish(vsc, sc->sc_vqs, 187 __arraycount(sc->sc_vqs), NULL, 188 VIRTIO_F_INTR_MSIX | VIRTIO_F_INTR_MPSAFE) != 0) 189 goto err; 190 191 /* 192 * Fill in the scsipi_adapter. 193 */ 194 memset(adapt, 0, sizeof(*adapt)); 195 adapt->adapt_dev = sc->sc_dev; 196 adapt->adapt_nchannels = 1; 197 adapt->adapt_openings = MIN(qsize, cmd_per_lun); 198 adapt->adapt_max_periph = adapt->adapt_openings; 199 adapt->adapt_request = vioscsi_scsipi_request; 200 adapt->adapt_minphys = minphys; 201 adapt->adapt_flags = SCSIPI_ADAPT_MPSAFE; 202 203 /* 204 * Fill in the scsipi_channel. 205 * 206 * This looks odd in a couple of ways but is correct. 207 * Unfortunately, QEMU, which might be the most common host 208 * side implementation, always reports 255 targets and 16383 209 * LUNs. This can take multiple seconds to probe! At least we 210 * let the user override these silly values in the kernel config. 211 * 212 * Also, note there isn't really an initiator ID, so letting it 213 * end up at 16384 here is acceptable - good, even, since it 214 * will properly bound the loop that does probe the targets. 215 */ 216 memset(chan, 0, sizeof(*chan)); 217 chan->chan_adapter = adapt; 218 chan->chan_bustype = &scsi_bustype; 219 chan->chan_channel = 0; 220 chan->chan_ntargets = MIN(1 + max_target, VIOSCSI_MAX_TARGET); 221 chan->chan_nluns = MIN(1 + max_lun, VIOSCSI_MAX_LUN); 222 chan->chan_id = max_target + 1; 223 chan->chan_flags = SCSIPI_CHAN_NOSETTLE; 224 225 config_found(self, &sc->sc_channel, scsiprint, CFARGS_NONE); 226 return; 227 228 err: 229 if (qsize > 0) 230 vioscsi_free_reqs(sc, vsc); 231 232 for (i=0; i < __arraycount(sc->sc_vqs); i++) { 233 virtio_free_vq(vsc, &sc->sc_vqs[i]); 234 } 235 236 virtio_child_attach_failed(vsc); 237 } 238 239 static int 240 vioscsi_detach(device_t self, int flags) 241 { 242 struct vioscsi_softc *sc = device_private(self); 243 struct virtio_softc *vsc = device_private(device_parent(sc->sc_dev)); 244 int rc, i; 245 246 /* 247 * Dequeue all pending finished requests. Must be done 248 * before we try to detach children so that we process 249 * their pending requests while they still exist. 250 */ 251 if (sc->sc_vqs[VIOSCSI_VQ_REQUEST].vq_num > 0) 252 vioscsi_vq_done(&sc->sc_vqs[VIOSCSI_VQ_REQUEST]); 253 254 if ((rc = config_detach_children(self, flags)) != 0) 255 return rc; 256 257 virtio_reset(vsc); 258 259 for (i = 0; i < __arraycount(sc->sc_vqs); i++) { 260 if (sc->sc_vqs[i].vq_num > 0) 261 virtio_free_vq(vsc, &sc->sc_vqs[i]); 262 } 263 264 vioscsi_free_reqs(sc, vsc); 265 266 virtio_child_detach(vsc); 267 268 mutex_destroy(&sc->sc_mutex); 269 270 return 0; 271 } 272 273 #define XS2DMA(xs) \ 274 ((((xs)->xs_control & XS_CTL_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE) | \ 275 (((xs)->xs_control & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | \ 276 BUS_DMA_STREAMING) 277 278 #define XS2DMAPRE(xs) (((xs)->xs_control & XS_CTL_DATA_IN) ? \ 279 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE) 280 281 #define XS2DMAPOST(xs) (((xs)->xs_control & XS_CTL_DATA_IN) ? \ 282 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE) 283 284 static void 285 vioscsi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t 286 request, void *arg) 287 { 288 struct vioscsi_softc *sc = 289 device_private(chan->chan_adapter->adapt_dev); 290 struct virtio_softc *vsc = device_private(device_parent(sc->sc_dev)); 291 struct scsipi_xfer *xs; 292 struct scsipi_periph *periph; 293 struct vioscsi_req *vr; 294 struct virtio_scsi_req_hdr *req; 295 struct virtqueue *vq = &sc->sc_vqs[VIOSCSI_VQ_REQUEST]; 296 int slot, error; 297 bool dopoll; 298 299 DPRINTF(("%s: enter\n", __func__)); 300 301 switch (request) { 302 case ADAPTER_REQ_RUN_XFER: 303 break; 304 case ADAPTER_REQ_SET_XFER_MODE: 305 { 306 struct scsipi_xfer_mode *xm = arg; 307 xm->xm_mode = PERIPH_CAP_TQING; 308 xm->xm_period = 0; 309 xm->xm_offset = 0; 310 scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm); 311 return; 312 } 313 default: 314 DPRINTF(("%s: unhandled %d\n", __func__, request)); 315 return; 316 } 317 318 xs = arg; 319 periph = xs->xs_periph; 320 321 /* 322 * This can happen when we run out of queue slots. 323 */ 324 vr = vioscsi_req_get(sc); 325 if (vr == NULL) { 326 xs->error = XS_BUSY; 327 scsipi_done(xs); 328 return; 329 } 330 331 req = &vr->vr_req; 332 slot = vr - sc->sc_reqs; 333 334 /* 335 * "The only supported format for the LUN field is: first byte set to 336 * 1, second byte set to target, third and fourth byte representing a 337 * single level LUN structure, followed by four zero bytes." 338 */ 339 if (periph->periph_target >= 256 || periph->periph_lun >= 16384 340 || periph->periph_target < 0 || periph->periph_lun < 0) { 341 goto stuffup; 342 } 343 344 req->lun[0] = 1; 345 req->lun[1] = periph->periph_target; 346 req->lun[2] = 0x40 | ((periph->periph_lun >> 8) & 0x3F); 347 req->lun[3] = periph->periph_lun & 0xFF; 348 memset(req->lun + 4, 0, 4); 349 DPRINTF(("%s: command %p for %d:%d at slot %d\n", __func__, 350 xs, periph->periph_target, periph->periph_lun, slot)); 351 352 /* tag */ 353 switch (XS_CTL_TAGTYPE(xs)) { 354 case XS_CTL_HEAD_TAG: 355 req->task_attr = VIRTIO_SCSI_S_HEAD; 356 break; 357 358 #if 0 /* XXX */ 359 case XS_CTL_ACA_TAG: 360 req->task_attr = VIRTIO_SCSI_S_ACA; 361 break; 362 #endif 363 364 case XS_CTL_ORDERED_TAG: 365 req->task_attr = VIRTIO_SCSI_S_ORDERED; 366 break; 367 368 case XS_CTL_SIMPLE_TAG: 369 default: 370 req->task_attr = VIRTIO_SCSI_S_SIMPLE; 371 break; 372 } 373 req->id = virtio_rw64(vsc, slot); 374 375 if ((size_t)xs->cmdlen > sizeof(req->cdb)) { 376 DPRINTF(("%s: bad cmdlen %zu > %zu\n", __func__, 377 (size_t)xs->cmdlen, sizeof(req->cdb))); 378 goto stuffup; 379 } 380 381 memset(req->cdb, 0, sizeof(req->cdb)); 382 memcpy(req->cdb, xs->cmd, xs->cmdlen); 383 384 error = bus_dmamap_load(virtio_dmat(vsc), vr->vr_data, 385 xs->data, xs->datalen, NULL, XS2DMA(xs)); 386 if (error) { 387 aprint_error_dev(sc->sc_dev, "%s: error %d loading DMA map\n", 388 __func__, error); 389 390 if (error == ENOMEM || error == EAGAIN) { 391 /* 392 * Map is allocated with ALLOCNOW, so this should 393 * actually never ever happen. 394 */ 395 xs->error = XS_RESOURCE_SHORTAGE; 396 } else { 397 stuffup: 398 /* not a temporary condition */ 399 xs->error = XS_DRIVER_STUFFUP; 400 } 401 402 virtio_enqueue_abort(vsc, vq, slot); 403 scsipi_done(xs); 404 return; 405 } 406 407 int nsegs = VIRTIO_SCSI_MIN_SEGMENTS; 408 if ((xs->xs_control & (XS_CTL_DATA_IN|XS_CTL_DATA_OUT)) != 0) 409 nsegs += vr->vr_data->dm_nsegs; 410 411 error = virtio_enqueue_reserve(vsc, vq, slot, nsegs); 412 if (error) { 413 bus_dmamap_unload(virtio_dmat(vsc), vr->vr_data); 414 /* slot already freed by virtio_enqueue_reserve() */ 415 xs->error = XS_BUSY; 416 scsipi_done(xs); 417 return; 418 } 419 420 vr->vr_xs = xs; 421 422 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_control, 423 offsetof(struct vioscsi_req, vr_req), 424 sizeof(struct virtio_scsi_req_hdr), 425 BUS_DMASYNC_PREWRITE); 426 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_control, 427 offsetof(struct vioscsi_req, vr_res), 428 sizeof(struct virtio_scsi_res_hdr), 429 BUS_DMASYNC_PREREAD); 430 if ((xs->xs_control & (XS_CTL_DATA_IN|XS_CTL_DATA_OUT)) != 0) 431 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_data, 0, xs->datalen, 432 XS2DMAPRE(xs)); 433 434 virtio_enqueue_p(vsc, vq, slot, vr->vr_control, 435 offsetof(struct vioscsi_req, vr_req), 436 sizeof(struct virtio_scsi_req_hdr), 1); 437 if (xs->xs_control & XS_CTL_DATA_OUT) 438 virtio_enqueue(vsc, vq, slot, vr->vr_data, 1); 439 virtio_enqueue_p(vsc, vq, slot, vr->vr_control, 440 offsetof(struct vioscsi_req, vr_res), 441 sizeof(struct virtio_scsi_res_hdr), 0); 442 if (xs->xs_control & XS_CTL_DATA_IN) 443 virtio_enqueue(vsc, vq, slot, vr->vr_data, 0); 444 dopoll = (xs->xs_control & XS_CTL_POLL) != 0; 445 virtio_enqueue_commit(vsc, vq, slot, 1); 446 447 if (!dopoll) 448 return; 449 450 DPRINTF(("%s: polling...\n", __func__)); 451 // XXX: do this better. 452 int timeout = 1000; 453 do { 454 virtio_intrhand(vsc); 455 if (vr->vr_xs != xs) 456 break; 457 delay(1000); 458 } while (--timeout > 0); 459 460 if (vr->vr_xs == xs) { 461 // XXX: Abort! 462 xs->error = XS_TIMEOUT; 463 xs->resid = xs->datalen; 464 DPRINTF(("%s: polling timeout\n", __func__)); 465 scsipi_done(xs); 466 } 467 DPRINTF(("%s: command %p done (timeout=%d)\n", __func__, 468 xs, timeout)); 469 } 470 471 static void 472 vioscsi_req_done(struct vioscsi_softc *sc, struct virtio_softc *vsc, 473 struct vioscsi_req *vr, struct virtqueue *vq, int slot) 474 { 475 struct scsipi_xfer *xs = vr->vr_xs; 476 size_t sense_len; 477 478 DPRINTF(("%s: enter\n", __func__)); 479 480 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_control, 481 offsetof(struct vioscsi_req, vr_req), 482 sizeof(struct virtio_scsi_req_hdr), 483 BUS_DMASYNC_POSTWRITE); 484 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_control, 485 offsetof(struct vioscsi_req, vr_res), 486 sizeof(struct virtio_scsi_res_hdr), 487 BUS_DMASYNC_POSTREAD); 488 if (xs->datalen) 489 bus_dmamap_sync(virtio_dmat(vsc), vr->vr_data, 0, xs->datalen, 490 XS2DMAPOST(xs)); 491 492 xs->status = vr->vr_res.status; 493 xs->resid = virtio_rw32(vsc, vr->vr_res.residual); 494 495 switch (vr->vr_res.response) { 496 case VIRTIO_SCSI_S_OK: 497 sense_len = MIN(sizeof(xs->sense), 498 virtio_rw32(vsc, vr->vr_res.sense_len)); 499 memcpy(&xs->sense, vr->vr_res.sense, sense_len); 500 xs->error = (sense_len == 0) ? XS_NOERROR : XS_SENSE; 501 break; 502 case VIRTIO_SCSI_S_BAD_TARGET: 503 vioscsi_bad_target(xs); 504 break; 505 default: 506 DPRINTF(("%s: stuffup: %d\n", __func__, vr->vr_res.response)); 507 xs->error = XS_DRIVER_STUFFUP; 508 xs->resid = xs->datalen; 509 break; 510 } 511 512 DPRINTF(("%s: command %p done %d, %d, %d\n", __func__, 513 xs, xs->error, xs->status, xs->resid)); 514 515 bus_dmamap_unload(virtio_dmat(vsc), vr->vr_data); 516 vr->vr_xs = NULL; 517 518 virtio_dequeue_commit(vsc, vq, slot); 519 520 mutex_exit(&sc->sc_mutex); 521 scsipi_done(xs); 522 mutex_enter(&sc->sc_mutex); 523 } 524 525 static void 526 vioscsi_bad_target(struct scsipi_xfer *xs) 527 { 528 struct scsi_sense_data *sense = &xs->sense.scsi_sense; 529 530 DPRINTF(("%s: bad target %d:%d\n", __func__, 531 xs->xs_periph->periph_target, xs->xs_periph->periph_lun)); 532 533 memset(sense, 0, sizeof(*sense)); 534 sense->response_code = 0x70; 535 sense->flags = SKEY_ILLEGAL_REQUEST; 536 xs->error = XS_SENSE; 537 xs->status = 0; 538 xs->resid = 0; 539 } 540 541 static int 542 vioscsi_vq_done(struct virtqueue *vq) 543 { 544 struct virtio_softc *vsc = vq->vq_owner; 545 struct vioscsi_softc *sc = device_private(virtio_child(vsc)); 546 int ret = 0; 547 548 DPRINTF(("%s: enter %d\n", __func__, vq->vq_index)); 549 550 mutex_enter(&sc->sc_mutex); 551 552 for (;;) { 553 int r, slot; 554 555 r = virtio_dequeue(vsc, vq, &slot, NULL); 556 if (r != 0) 557 break; 558 559 DPRINTF(("%s: slot=%d\n", __func__, slot)); 560 561 vioscsi_req_done(sc, vsc, &sc->sc_reqs[slot], vq, slot); 562 563 ret = 1; 564 } 565 566 mutex_exit(&sc->sc_mutex); 567 568 DPRINTF(("%s: exit %d: %d\n", __func__, vq->vq_index, ret)); 569 570 return ret; 571 } 572 573 static struct vioscsi_req * 574 vioscsi_req_get(struct vioscsi_softc *sc) 575 { 576 struct virtio_softc *vsc = device_private(device_parent(sc->sc_dev)); 577 struct virtqueue *vq = &sc->sc_vqs[VIOSCSI_VQ_REQUEST]; 578 struct vioscsi_req *vr = NULL; 579 int r, slot; 580 581 mutex_enter(&sc->sc_mutex); 582 583 if ((r = virtio_enqueue_prep(vsc, vq, &slot)) != 0) { 584 DPRINTF(("%s: virtio_enqueue_get error %d\n", __func__, r)); 585 goto out; 586 } 587 KASSERT(slot < sc->sc_nreqs); 588 vr = &sc->sc_reqs[slot]; 589 590 DPRINTF(("%s: %p, %d\n", __func__, vr, slot)); 591 592 out: 593 mutex_exit(&sc->sc_mutex); 594 595 return vr; 596 } 597 598 static int 599 vioscsi_alloc_reqs(struct vioscsi_softc *sc, struct virtio_softc *vsc, 600 int qsize) 601 { 602 size_t allocsize; 603 int r, rsegs, slot; 604 void *vaddr; 605 struct vioscsi_req *vr; 606 607 allocsize = qsize * sizeof(struct vioscsi_req); 608 r = bus_dmamem_alloc(virtio_dmat(vsc), allocsize, 0, 0, 609 &sc->sc_reqs_segs[0], 1, &rsegs, BUS_DMA_NOWAIT); 610 if (r != 0) { 611 aprint_error_dev(sc->sc_dev, 612 "%s: bus_dmamem_alloc, size %zu, error %d\n", __func__, 613 allocsize, r); 614 return r; 615 } 616 r = bus_dmamem_map(virtio_dmat(vsc), &sc->sc_reqs_segs[0], 1, 617 allocsize, &vaddr, BUS_DMA_NOWAIT); 618 if (r != 0) { 619 aprint_error_dev(sc->sc_dev, 620 "%s: bus_dmamem_map failed, error %d\n", __func__, r); 621 bus_dmamem_free(virtio_dmat(vsc), &sc->sc_reqs_segs[0], 1); 622 return r; 623 } 624 memset(vaddr, 0, allocsize); 625 626 sc->sc_reqs = vaddr; 627 sc->sc_nreqs = qsize; 628 629 /* Prepare maps for the requests */ 630 for (slot=0; slot < qsize; slot++) { 631 vr = &sc->sc_reqs[slot]; 632 633 r = bus_dmamap_create(virtio_dmat(vsc), 634 offsetof(struct vioscsi_req, vr_xs), 1, 635 offsetof(struct vioscsi_req, vr_xs), 0, 636 BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_control); 637 if (r != 0) { 638 aprint_error_dev(sc->sc_dev, 639 "%s: bus_dmamap_create ctrl failed, error %d\n", 640 __func__, r); 641 goto cleanup; 642 } 643 644 r = bus_dmamap_create(virtio_dmat(vsc), MAXPHYS, sc->sc_seg_max, 645 MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &vr->vr_data); 646 if (r != 0) { 647 aprint_error_dev(sc->sc_dev, 648 "%s: bus_dmamap_create data failed, error %d\n", 649 __func__, r); 650 goto cleanup; 651 } 652 653 r = bus_dmamap_load(virtio_dmat(vsc), vr->vr_control, 654 vr, offsetof(struct vioscsi_req, vr_xs), NULL, 655 BUS_DMA_NOWAIT); 656 if (r != 0) { 657 aprint_error_dev(sc->sc_dev, 658 "%s: bus_dmamap_load ctrl error %d\n", 659 __func__, r); 660 goto cleanup; 661 } 662 } 663 664 return 0; 665 666 cleanup: 667 for (; slot > 0; slot--) { 668 vr = &sc->sc_reqs[slot]; 669 670 if (vr->vr_control) { 671 /* this will also unload the mapping if loaded */ 672 bus_dmamap_destroy(virtio_dmat(vsc), vr->vr_control); 673 vr->vr_control = NULL; 674 } 675 676 if (vr->vr_data) { 677 bus_dmamap_destroy(virtio_dmat(vsc), vr->vr_data); 678 vr->vr_data = NULL; 679 } 680 } 681 682 bus_dmamem_unmap(virtio_dmat(vsc), vaddr, allocsize); 683 bus_dmamem_free(virtio_dmat(vsc), &sc->sc_reqs_segs[0], 1); 684 685 return r; 686 } 687 688 static void 689 vioscsi_free_reqs(struct vioscsi_softc *sc, struct virtio_softc *vsc) 690 { 691 int slot; 692 struct vioscsi_req *vr; 693 694 if (sc->sc_nreqs == 0) { 695 /* Not allocated */ 696 return; 697 } 698 699 /* Free request maps */ 700 for (slot=0; slot < sc->sc_nreqs; slot++) { 701 vr = &sc->sc_reqs[slot]; 702 703 bus_dmamap_destroy(virtio_dmat(vsc), vr->vr_control); 704 bus_dmamap_destroy(virtio_dmat(vsc), vr->vr_data); 705 } 706 707 bus_dmamem_unmap(virtio_dmat(vsc), sc->sc_reqs, 708 sc->sc_nreqs * sizeof(struct vioscsi_req)); 709 bus_dmamem_free(virtio_dmat(vsc), &sc->sc_reqs_segs[0], 1); 710 } 711 712 MODULE(MODULE_CLASS_DRIVER, vioscsi, "virtio"); 713 714 #ifdef _MODULE 715 #include "ioconf.c" 716 #endif 717 718 static int 719 vioscsi_modcmd(modcmd_t cmd, void *opaque) 720 { 721 int error = 0; 722 723 #ifdef _MODULE 724 switch (cmd) { 725 case MODULE_CMD_INIT: 726 error = config_init_component(cfdriver_ioconf_vioscsi, 727 cfattach_ioconf_vioscsi, cfdata_ioconf_vioscsi); 728 break; 729 case MODULE_CMD_FINI: 730 error = config_fini_component(cfdriver_ioconf_vioscsi, 731 cfattach_ioconf_vioscsi, cfdata_ioconf_vioscsi); 732 break; 733 default: 734 error = ENOTTY; 735 break; 736 } 737 #endif 738 739 return error; 740 } 741