Module Name: src Committed By: reinoud Date: Tue Jun 5 20:02:43 UTC 2018
Modified Files: src/sys/arch/usermode/conf: GENERIC.common files.usermode src/sys/arch/usermode/dev: mainbus.c src/sys/arch/usermode/include: mainbus.h src/sys/arch/usermode/usermode: machdep.c Added Files: src/sys/arch/usermode/dev: vatapi.c Log Message: Add ATAPI passtrough support giving the NetBSD/usermode kernel full control of an ATAPI device. All ATAPI/SCSI commands are passed trough. Note that ATAPI/SCSI calls are made in the foreground still. Lengthy calls will still hug the CPU until completion. Making it asynchronous is in the pipeline To generate a diff of this commit: cvs rdiff -u -r1.27 -r1.28 src/sys/arch/usermode/conf/GENERIC.common cvs rdiff -u -r1.16 -r1.17 src/sys/arch/usermode/conf/files.usermode cvs rdiff -u -r1.9 -r1.10 src/sys/arch/usermode/dev/mainbus.c cvs rdiff -u -r0 -r1.1 src/sys/arch/usermode/dev/vatapi.c cvs rdiff -u -r1.7 -r1.8 src/sys/arch/usermode/include/mainbus.h cvs rdiff -u -r1.54 -r1.55 src/sys/arch/usermode/usermode/machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/usermode/conf/GENERIC.common diff -u src/sys/arch/usermode/conf/GENERIC.common:1.27 src/sys/arch/usermode/conf/GENERIC.common:1.28 --- src/sys/arch/usermode/conf/GENERIC.common:1.27 Sat Jan 13 16:20:33 2018 +++ src/sys/arch/usermode/conf/GENERIC.common Tue Jun 5 20:02:42 2018 @@ -1,9 +1,9 @@ -# $NetBSD: GENERIC.common,v 1.27 2018/01/13 16:20:33 reinoud Exp $ +# $NetBSD: GENERIC.common,v 1.28 2018/06/05 20:02:42 reinoud Exp $ include "arch/usermode/conf/std.usermode" options INCLUDE_CONFIG_FILE -#ident "GENERIC-$Revision: 1.27 $" +#ident "GENERIC-$Revision: 1.28 $" maxusers 32 makeoptions DEBUG="-O1 -g3" @@ -64,7 +64,6 @@ ld* at mainbus? veth0 at mainbus? vaudio0 at mainbus? audio0 at vaudio0 - spkr* at audio? # PC speaker (synthesized) vncfb0 at mainbus? @@ -77,6 +76,17 @@ options WSKBD_DEFAULT_KEYREPEAT_DEL1=10 options WSKBD_DEFAULT_KEYREPEAT_DELN=200 options WSDISPLAY_COMPAT_USL # wsconscfg VT handling +# virtual devices */ +vatapi* at mainbus? +atapibus* at vatapi? + +# cd, sd, and the like +cd* at atapibus? +sd* at atapibus? +st* at atapibus? +uk* at atapibus? + +# pseudo devices pseudo-device loop pseudo-device pty pseudo-device bpfilter Index: src/sys/arch/usermode/conf/files.usermode diff -u src/sys/arch/usermode/conf/files.usermode:1.16 src/sys/arch/usermode/conf/files.usermode:1.17 --- src/sys/arch/usermode/conf/files.usermode:1.16 Fri Dec 30 20:08:36 2011 +++ src/sys/arch/usermode/conf/files.usermode Tue Jun 5 20:02:42 2018 @@ -1,4 +1,4 @@ -# $NetBSD: files.usermode,v 1.16 2011/12/30 20:08:36 jmcneill Exp $ +# $NetBSD: files.usermode,v 1.17 2018/06/05 20:02:42 reinoud Exp $ maxpartitions 8 maxusers 8 16 64 @@ -42,6 +42,16 @@ attach vncfb at thunkbus file arch/usermode/dev/vncfb.c vncfb file arch/usermode/dev/vnckbdmap.c vncfb +include "dev/scsipi/files.scsipi" +#device vscsi: scsi +#file arch/usermode/dev/vscsi.c vscsi needs-flag +#attach vscsi at thunkbus with vscsi_thunkbus +#file atch/usermode/dev/vscsi_thunkbus.c vscsi_thunkbus + +device vatapi { } : atapi, atapibus +attach vatapi at thunkbus with vatapi_thunkbus +file arch/usermode/dev/vatapi.c vatapi_thunkbus + file arch/usermode/usermode/copy.c file arch/usermode/usermode/intr.c file arch/usermode/usermode/machdep.c Index: src/sys/arch/usermode/dev/mainbus.c diff -u src/sys/arch/usermode/dev/mainbus.c:1.9 src/sys/arch/usermode/dev/mainbus.c:1.10 --- src/sys/arch/usermode/dev/mainbus.c:1.9 Sat Jan 7 18:10:18 2012 +++ src/sys/arch/usermode/dev/mainbus.c Tue Jun 5 20:02:43 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: mainbus.c,v 1.9 2012/01/07 18:10:18 jmcneill Exp $ */ +/* $NetBSD: mainbus.c,v 1.10 2018/06/05 20:02:43 reinoud Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.9 2012/01/07 18:10:18 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.10 2018/06/05 20:02:43 reinoud Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -52,6 +52,9 @@ CFATTACH_DECL_NEW(mainbus, sizeof(mainbu extern char *usermode_disk_image_path[]; extern int usermode_disk_image_path_count; +extern int usermode_vdev_type[]; +extern char *usermode_vdev_path[]; +extern int usermode_vdev_count; extern char *usermode_tap_device; extern char *usermode_tap_eaddr; extern char *usermode_audio_device; @@ -111,6 +114,12 @@ mainbus_attach(device_t parent, device_t taa.u.diskimage.path = usermode_disk_image_path[i]; config_found_ia(self, "thunkbus", &taa, mainbus_print); } + + for (i = 0; i < usermode_vdev_count; i++) { + taa.taa_type = usermode_vdev_type[i]; + taa.u.vdev.path = usermode_vdev_path[i]; + config_found_ia(self, "thunkbus", &taa, mainbus_print); + } } static int Index: src/sys/arch/usermode/include/mainbus.h diff -u src/sys/arch/usermode/include/mainbus.h:1.7 src/sys/arch/usermode/include/mainbus.h:1.8 --- src/sys/arch/usermode/include/mainbus.h:1.7 Thu Dec 29 21:22:49 2011 +++ src/sys/arch/usermode/include/mainbus.h Tue Jun 5 20:02:43 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: mainbus.h,v 1.7 2011/12/29 21:22:49 jmcneill Exp $ */ +/* $NetBSD: mainbus.h,v 1.8 2018/06/05 20:02:43 reinoud Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca> @@ -38,10 +38,15 @@ struct thunkbus_attach_args { #define THUNKBUS_TYPE_VNCFB 4 #define THUNKBUS_TYPE_VETH 5 #define THUNKBUS_TYPE_VAUDIO 6 +#define THUNKBUS_TYPE_VATAPI 7 +#define THUNKBUS_TYPE_VSCSI 8 union { struct { const char *path; + } vdev; + struct { + const char *path; } diskimage; struct { const char *device; Index: src/sys/arch/usermode/usermode/machdep.c diff -u src/sys/arch/usermode/usermode/machdep.c:1.54 src/sys/arch/usermode/usermode/machdep.c:1.55 --- src/sys/arch/usermode/usermode/machdep.c:1.54 Thu Dec 22 14:47:59 2016 +++ src/sys/arch/usermode/usermode/machdep.c Tue Jun 5 20:02:43 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.54 2016/12/22 14:47:59 cherry Exp $ */ +/* $NetBSD: machdep.c,v 1.55 2018/06/05 20:02:43 reinoud Exp $ */ /*- * Copyright (c) 2011 Reinoud Zandijk <rein...@netbsd.org> @@ -37,7 +37,7 @@ #include "opt_memsize.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.54 2016/12/22 14:47:59 cherry Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.55 2018/06/05 20:02:43 reinoud Exp $"); #include <sys/types.h> #include <sys/systm.h> @@ -57,12 +57,17 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v #include <dev/mm.h> #include <machine/vmparam.h> #include <machine/machdep.h> +#include <machine/mainbus.h> #include <machine/thunk.h> #ifndef MAX_DISK_IMAGES #define MAX_DISK_IMAGES 4 #endif +#ifndef MAX_VDEVS +#define MAX_VDEVS 4 +#endif + char machine[_SYS_NMLN] = ""; char machine_arch[_SYS_NMLN] = ""; char module_machine_usermode[_SYS_NMLN] = ""; @@ -74,6 +79,10 @@ static char **saved_argv; char *usermode_disk_image_path[MAX_DISK_IMAGES]; int usermode_disk_image_path_count = 0; +int usermode_vdev_type[MAX_VDEVS]; +char *usermode_vdev_path[MAX_VDEVS]; +int usermode_vdev_count = 0; + static char usermode_tap_devicebuf[PATH_MAX] = ""; char *usermode_tap_device = NULL; char *usermode_tap_eaddr = NULL; @@ -95,23 +104,39 @@ usage(const char *pn) " [audio=<audiodev>]" " [disk=<diskimg> ...]" " [root=<device>]" - " [vnc=<width>x<height>,<port>]\n", + " [vnc=<width>x<height>,<port>]" + " [vdev=atapi,device]\n", pn); printf(" (ex. \"%s" " net=tap0,00:00:be:ef:ca:fe" " audio=audio0" " disk=root.fs" " root=ld0" - " vnc=640x480,5900\")\n", pn); + " vnc=640x480,5900" + " vdev=atapi,/dev/rcd0d\")\n", pn); +} + + +static int +vdev_type(const char *type) +{ + if (strcasecmp(type, "atapi")==0) + return THUNKBUS_TYPE_VATAPI; +#if 0 + if (strcasecmp(type, "scsi")==0) + return THUNKBUS_TYPE_VSCSI; +#endif + return -1; } + void main(int argc, char *argv[]) { extern void ttycons_consinit(void); extern void pmap_bootstrap(void); extern void kernmain(void); - int i, j, r, tmpopt = 0; + int type, i, j, r, tmpopt = 0; saved_argv = argv; @@ -189,6 +214,32 @@ main(int argc, char *argv[]) usermode_disk_image_path[ usermode_disk_image_path_count++] = argv[i] + strlen("disk="); + } else if (strncmp(argv[i], "vdev=", + strlen("vdev=")) == 0) { + char *vdev = argv[i] + strlen("vdev="); + char *t, *p; + if (usermode_disk_image_path_count == + MAX_VDEVS) { + printf("too many vdevs " + "(increase MAX_VDEVS)\n"); + usage(argv[0]); + return; + } + t = vdev; + p = strchr(t, ','); + if (p == NULL) { + printf("bad vdev= format\n"); + return; + } + *p++ = '\0'; + type = vdev_type(t); + if (type < 0) { + printf("unknown vdev device type\n"); + return; + } + usermode_vdev_type[usermode_vdev_count] = type; + usermode_vdev_path[usermode_vdev_count] = p; + usermode_vdev_count++; } else if (strncmp(argv[i], "root=", strlen("root=")) == 0) { usermode_root_device = argv[i] + Added files: Index: src/sys/arch/usermode/dev/vatapi.c diff -u /dev/null src/sys/arch/usermode/dev/vatapi.c:1.1 --- /dev/null Tue Jun 5 20:02:43 2018 +++ src/sys/arch/usermode/dev/vatapi.c Tue Jun 5 20:02:43 2018 @@ -0,0 +1,345 @@ +/* $NetBSD: vatapi.c,v 1.1 2018/06/05 20:02:43 reinoud Exp $ */ + +/*- + * Copyright (c) 2018 Reinoud Zandijk <rein...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: vatapi.c,v 1.1 2018/06/05 20:02:43 reinoud Exp $"); + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/buf.h> +#include <sys/disk.h> +#include <sys/kmem.h> +#include <sys/malloc.h> +#include <sys/scsiio.h> + +#include <machine/mainbus.h> +#include <machine/thunk.h> +#include <machine/intr.h> + +#include <dev/scsipi/scsi_all.h> /* for SCSI status */ +#include <dev/scsipi/scsipi_all.h> +#include <dev/scsipi/scsipiconf.h> +#include <dev/scsipi/atapiconf.h> + +/* parameter? */ +#define VDEV_ATAPI_DRIVE 0 +#define MAX_SIZE ((1<<16)) + +/* forwards */ +struct vatapi_softc; + +static int vatapi_match(device_t, cfdata_t, void *); +static void vatapi_attach(device_t, device_t, void *); +static void vatapi_callback(device_t self); + +static void vatapi_minphys(struct buf *bp); +static void vatapi_kill_pending(struct scsipi_periph *periph); +static void vatapi_scsipi_request(struct scsipi_channel *chan, + scsipi_adapter_req_t req, void *arg); +static void vatapi_probe_device(struct atapibus_softc *, int); + +static void vatapi_complete(void *arg); + +/* for debugging */ +void scsipi_print_sense_data_real(struct scsi_sense_data *sense, int verbosity); + + +/* Note its one vdev, one adapter, one channel for now */ +struct vatapi_softc { + device_t sc_dev; + device_t sc_pdev; + + int sc_flags; +#define VATAPI_FLAG_POLLING 1 +#define VATAPI_FLAG_INTR 2 + /* backing `device' with its active command */ + int sc_fd; + void *sc_ih; + struct scsipi_xfer *sc_xs; + + /* atapibus */ + device_t sc_vatapibus; + struct atapi_adapter sc_atapi_adapter; +#define sc_adapter sc_atapi_adapter._generic + struct scsipi_channel sc_channel; +}; + +CFATTACH_DECL_NEW(vatapi_thunkbus, sizeof(struct vatapi_softc), + vatapi_match, vatapi_attach, NULL, NULL); + + +static const struct scsipi_bustype vatapi_bustype = { + SCSIPI_BUSTYPE_ATAPI, + atapi_scsipi_cmd, + atapi_interpret_sense, + atapi_print_addr, + vatapi_kill_pending, + NULL +}; + +int +vatapi_match(device_t parent, cfdata_t match, void *opaque) +{ + struct thunkbus_attach_args *taa = opaque; + + if (taa->taa_type != THUNKBUS_TYPE_VATAPI) + return 0; + + return 1; +} + +static void +vatapi_attach(device_t parent, device_t self, void *opaque) +{ + struct vatapi_softc *sc = device_private(self); + struct thunkbus_attach_args *taa = opaque; + + sc->sc_dev = self; + sc->sc_pdev = parent; + + /* open device */ + sc->sc_fd = thunk_open(taa->u.vdev.path, O_RDWR, 0); + if (sc->sc_fd < 0) { + aprint_error(": error %d opening path\n", thunk_geterrno()); + return; + } + + aprint_naive("\n"); + aprint_normal("\n"); + + sc->sc_ih = softint_establish(SOFTINT_BIO, + vatapi_complete, sc); + + /* rest of the configuration is deferred */ + config_interrupts(self, vatapi_callback); +} + +static void +vatapi_callback(device_t self) +{ + struct vatapi_softc *sc = device_private(self); + struct scsipi_adapter *adapt = &sc->sc_adapter; + struct scsipi_channel *chan = &sc->sc_channel; + + /* set up the scsipi adapter and channel */ + memset(adapt, 0, sizeof(*adapt)); + adapt->adapt_dev = sc->sc_dev; + adapt->adapt_nchannels = 1; + adapt->adapt_request = vatapi_scsipi_request; + adapt->adapt_minphys = vatapi_minphys; + adapt->adapt_flags = 0; //SCSIPI_ADAPT_POLL_ONLY; + sc->sc_atapi_adapter.atapi_probe_device = vatapi_probe_device; + + memset(chan, 0, sizeof(*chan)); + chan->chan_adapter = adapt; + chan->chan_bustype = &vatapi_bustype; + chan->chan_channel = 0; /* location */ + chan->chan_flags = SCSIPI_CHAN_OPENINGS; + chan->chan_openings = 1; + chan->chan_max_periph = 1; + chan->chan_ntargets = 1; + chan->chan_nluns = 1; + + /* set polling */ + //sc->sc_flags = VATAPI_FLAG_POLLING; + + /* we `discovered' an atapi adapter */ + sc->sc_vatapibus = config_found_ia(sc->sc_dev, "atapi", chan, + atapiprint); +} + + +/* XXX why is it be called minphys, when it enforces maxphys? */ +static void +vatapi_minphys(struct buf *bp) +{ + if (bp->b_bcount > MAX_SIZE) + bp->b_bcount = MAX_SIZE; + minphys(bp); +} + +/* + * ATAPI device probing + */ +static void +vatapi_probe_device(struct atapibus_softc *atapi, int target) +{ + struct scsipi_channel *chan = atapi->sc_channel; + struct scsipi_periph *periph; + struct scsipibus_attach_args sa; + char vendor[33], product[65], revision[17]; + struct scsipi_inquiry_data inqbuf; + + if (target != VDEV_ATAPI_DRIVE) /* only probe drive 0 */ + return; + + /* skip if already attached */ + if (scsipi_lookup_periph(chan, target, 0) != NULL) + return; + + /* allocate and set up periph structure */ + periph = scsipi_alloc_periph(M_NOWAIT); + if (periph == NULL) { + aprint_error_dev(atapi->sc_dev, + "can't allocate link for drive %d\n", target); + return; + } + periph->periph_channel = chan; + periph->periph_switch = &atapi_probe_periphsw; + periph->periph_target = target; + periph->periph_quirks = chan->chan_defquirks; + + /* inquiry */ + aprint_verbose("%s: inquiry devices\n", __func__); + memset(&inqbuf, 0, sizeof(inqbuf)); + if (scsipi_inquire(periph, &inqbuf, XS_CTL_DISCOVERY) != 0) { + aprint_error_dev(atapi->sc_dev, ": scsipi_inquire failed\n"); + free(periph, M_DEVBUF); + return; + } + +#define scsipi_strvis(a, al, b, bl) strlcpy(a, b, al) + scsipi_strvis(vendor, 33, inqbuf.vendor, 8); + scsipi_strvis(product, 65, inqbuf.product, 16); + scsipi_strvis(revision, 17, inqbuf.revision, 4); +#undef scsipi_strvis + + sa.sa_periph = periph; + sa.sa_inqbuf.type = inqbuf.device; + sa.sa_inqbuf.removable = inqbuf.dev_qual2 & SID_REMOVABLE ? + T_REMOV : T_FIXED; + if (sa.sa_inqbuf.removable) + periph->periph_flags |= PERIPH_REMOVABLE; + sa.sa_inqbuf.vendor = vendor; + sa.sa_inqbuf.product = product; + sa.sa_inqbuf.revision = revision; + sa.sa_inqptr = NULL; + + /* ATAPI demands only READ10 and higher IIRC */ + periph->periph_quirks |= PQUIRK_ONLYBIG; + + aprint_verbose(": probedev on vendor '%s' product '%s' revision '%s'\n", + vendor, product, revision); + + atapi_probe_device(atapi, target, periph, &sa); + /* atapi_probe_device() frees the periph when there is no device.*/ +} + +/* + * Issue a request for a periph. + */ +static void +vatapi_scsipi_request(struct scsipi_channel *chan, + scsipi_adapter_req_t req, void *arg) +{ + device_t sc_dev = chan->chan_adapter->adapt_dev; + struct vatapi_softc *sc = device_private(sc_dev); + struct scsipi_xfer *xs = arg; + + switch (req) { + case ADAPTER_REQ_GROW_RESOURCES: + case ADAPTER_REQ_SET_XFER_MODE: + return; + case ADAPTER_REQ_RUN_XFER : + KASSERT(sc->sc_xs == NULL); + + /* queue the command */ + KASSERT(sc->sc_xs == NULL); + sc->sc_xs = xs; + softint_schedule(sc->sc_ih); + } +} + + +static void +vatapi_complete(void *arg) +{ + struct vatapi_softc *sc = arg; + struct scsipi_xfer *xs = sc->sc_xs; + scsireq_t kreq; + + memset(&kreq, 0, sizeof(kreq)); + memcpy(kreq.cmd, xs->cmd, xs->cmdlen); + kreq.cmdlen = xs->cmdlen; + kreq.databuf = xs->data; /* in virt? */ + kreq.datalen = xs->datalen; + kreq.timeout = xs->timeout; + + kreq.flags = (xs->xs_control & XS_CTL_DATA_IN) ? + SCCMD_READ : SCCMD_WRITE; + + kreq.senselen = sizeof(struct scsi_sense_data); + + xs->error = XS_SHORTSENSE; + /* this is silly, but better make sure */ + thunk_assert_presence((vaddr_t) kreq.databuf, + (size_t) kreq.datalen); + + if (thunk_ioctl(sc->sc_fd, SCIOCCOMMAND, &kreq) != -1) { + switch (kreq.retsts) { + case SCCMD_OK : + xs->resid = 0; + xs->error = 0; + break; + case SCCMD_TIMEOUT : + break; + case SCCMD_BUSY : + break; + case SCCMD_SENSE : + xs->error = XS_SHORTSENSE; /* ATAPI */ + memcpy(&xs->sense.scsi_sense, kreq.sense, + sizeof(struct scsi_sense_data)); +// scsipi_print_sense_data_real( +// (struct scsi_sense_data *) kreq.sense, 1); + break; + default: + thunk_printf("unhandled/unknown retstst %d\n", kreq.retsts); + break; + } + } else { + printf("thunk_ioctl == -1, errno %d\n", thunk_geterrno()); + } + sc->sc_xs = NULL; + scsipi_done(xs); +} + + +/* + * Kill off all pending xfers for a periph. + * + * Must be called at splbio(). + */ +static void +vatapi_kill_pending(struct scsipi_periph *periph) +{ + /* do we need to do anything ? (yet?) */ + printf("%s: target %d\n", __func__, periph->periph_target); +} +