Home | History | Annotate | Line # | Download | only in pci
      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