Home | History | Annotate | Line # | Download | only in dev
vatapi.c revision 1.2.18.1
      1  1.2.18.1  thorpej /* $NetBSD: vatapi.c,v 1.2.18.1 2021/03/23 07:14:51 thorpej Exp $ */
      2       1.1  reinoud 
      3       1.1  reinoud /*-
      4       1.1  reinoud  * Copyright (c) 2018 Reinoud Zandijk <reinoud (at) NetBSD.org>
      5       1.1  reinoud  * All rights reserved.
      6       1.1  reinoud  *
      7       1.1  reinoud  * Redistribution and use in source and binary forms, with or without
      8       1.1  reinoud  * modification, are permitted provided that the following conditions
      9       1.1  reinoud  * are met:
     10       1.1  reinoud  * 1. Redistributions of source code must retain the above copyright
     11       1.1  reinoud  *    notice, this list of conditions and the following disclaimer.
     12       1.1  reinoud  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1  reinoud  *    notice, this list of conditions and the following disclaimer in the
     14       1.1  reinoud  *    documentation and/or other materials provided with the distribution.
     15       1.1  reinoud  *
     16       1.1  reinoud  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17       1.1  reinoud  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18       1.1  reinoud  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19       1.1  reinoud  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20       1.1  reinoud  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21       1.1  reinoud  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22       1.1  reinoud  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23       1.1  reinoud  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24       1.1  reinoud  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25       1.1  reinoud  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26       1.1  reinoud  * POSSIBILITY OF SUCH DAMAGE.
     27       1.1  reinoud  */
     28       1.1  reinoud 
     29       1.1  reinoud #include <sys/cdefs.h>
     30  1.2.18.1  thorpej __KERNEL_RCSID(0, "$NetBSD: vatapi.c,v 1.2.18.1 2021/03/23 07:14:51 thorpej Exp $");
     31       1.1  reinoud 
     32       1.1  reinoud #include <sys/param.h>
     33       1.1  reinoud #include <sys/proc.h>
     34       1.1  reinoud #include <sys/systm.h>
     35       1.1  reinoud #include <sys/device.h>
     36       1.1  reinoud #include <sys/buf.h>
     37       1.1  reinoud #include <sys/disk.h>
     38       1.1  reinoud #include <sys/kmem.h>
     39       1.1  reinoud #include <sys/malloc.h>
     40       1.1  reinoud #include <sys/scsiio.h>
     41       1.1  reinoud 
     42       1.1  reinoud #include <machine/mainbus.h>
     43       1.1  reinoud #include <machine/thunk.h>
     44       1.1  reinoud #include <machine/intr.h>
     45       1.1  reinoud 
     46       1.1  reinoud #include <dev/scsipi/scsi_all.h>	/* for SCSI status */
     47       1.1  reinoud #include <dev/scsipi/scsipi_all.h>
     48       1.1  reinoud #include <dev/scsipi/scsipiconf.h>
     49       1.1  reinoud #include <dev/scsipi/atapiconf.h>
     50       1.1  reinoud 
     51       1.2  reinoud #include "opt_scsi.h"
     52       1.2  reinoud 
     53       1.1  reinoud /* parameter? */
     54       1.1  reinoud #define VDEV_ATAPI_DRIVE	0
     55       1.1  reinoud #define MAX_SIZE		((1<<16))
     56       1.1  reinoud 
     57       1.1  reinoud /* forwards */
     58       1.1  reinoud struct vatapi_softc;
     59       1.1  reinoud 
     60       1.1  reinoud static int	vatapi_match(device_t, cfdata_t, void *);
     61       1.1  reinoud static void	vatapi_attach(device_t, device_t, void *);
     62       1.1  reinoud static void	vatapi_callback(device_t self);
     63       1.1  reinoud 
     64       1.1  reinoud static void	vatapi_minphys(struct buf *bp);
     65       1.1  reinoud static void	vatapi_kill_pending(struct scsipi_periph *periph);
     66       1.1  reinoud static void	vatapi_scsipi_request(struct scsipi_channel *chan,
     67       1.1  reinoud 	scsipi_adapter_req_t req, void *arg);
     68       1.1  reinoud static void	vatapi_probe_device(struct atapibus_softc *, int);
     69       1.1  reinoud 
     70       1.1  reinoud static void	vatapi_complete(void *arg);
     71       1.1  reinoud 
     72       1.1  reinoud /* for debugging */
     73       1.2  reinoud #ifdef SCSIVERBOSE
     74       1.1  reinoud void	scsipi_print_sense_data_real(struct scsi_sense_data *sense, int verbosity);
     75       1.2  reinoud #endif
     76       1.1  reinoud 
     77       1.1  reinoud 
     78       1.1  reinoud /* Note its one vdev, one adapter, one channel for now */
     79       1.1  reinoud struct vatapi_softc {
     80       1.1  reinoud 	device_t	sc_dev;
     81       1.1  reinoud 	device_t	sc_pdev;
     82       1.1  reinoud 
     83       1.1  reinoud 	int		sc_flags;
     84       1.1  reinoud #define VATAPI_FLAG_POLLING	1
     85       1.1  reinoud #define VATAPI_FLAG_INTR	2
     86       1.1  reinoud 	/* backing `device' with its active command */
     87       1.1  reinoud 	int		sc_fd;
     88       1.1  reinoud 	void		*sc_ih;
     89       1.1  reinoud 	struct scsipi_xfer *sc_xs;
     90       1.1  reinoud 
     91       1.1  reinoud 	/* atapibus */
     92       1.1  reinoud 	device_t	sc_vatapibus;
     93       1.1  reinoud 	struct atapi_adapter    sc_atapi_adapter;
     94       1.1  reinoud #define sc_adapter sc_atapi_adapter._generic
     95       1.1  reinoud 	struct scsipi_channel sc_channel;
     96       1.1  reinoud };
     97       1.1  reinoud 
     98       1.1  reinoud CFATTACH_DECL_NEW(vatapi_thunkbus, sizeof(struct vatapi_softc),
     99       1.1  reinoud     vatapi_match, vatapi_attach, NULL, NULL);
    100       1.1  reinoud 
    101       1.1  reinoud 
    102       1.1  reinoud static const struct scsipi_bustype vatapi_bustype = {
    103       1.1  reinoud 	SCSIPI_BUSTYPE_ATAPI,
    104       1.1  reinoud 	atapi_scsipi_cmd,
    105       1.1  reinoud 	atapi_interpret_sense,
    106       1.1  reinoud 	atapi_print_addr,
    107       1.1  reinoud 	vatapi_kill_pending,
    108       1.1  reinoud 	NULL
    109       1.1  reinoud };
    110       1.1  reinoud 
    111       1.1  reinoud int
    112       1.1  reinoud vatapi_match(device_t parent, cfdata_t match, void *opaque)
    113       1.1  reinoud {
    114       1.1  reinoud 	struct thunkbus_attach_args *taa = opaque;
    115       1.1  reinoud 
    116       1.1  reinoud 	if (taa->taa_type != THUNKBUS_TYPE_VATAPI)
    117       1.1  reinoud 		return 0;
    118       1.1  reinoud 
    119       1.1  reinoud 	return 1;
    120       1.1  reinoud }
    121       1.1  reinoud 
    122       1.1  reinoud static void
    123       1.1  reinoud vatapi_attach(device_t parent, device_t self, void *opaque)
    124       1.1  reinoud {
    125       1.1  reinoud 	struct vatapi_softc *sc = device_private(self);
    126       1.1  reinoud 	struct thunkbus_attach_args *taa = opaque;
    127       1.1  reinoud 
    128       1.1  reinoud 	sc->sc_dev = self;
    129       1.1  reinoud 	sc->sc_pdev = parent;
    130       1.1  reinoud 
    131       1.1  reinoud 	/* open device */
    132       1.1  reinoud 	sc->sc_fd = thunk_open(taa->u.vdev.path, O_RDWR, 0);
    133       1.1  reinoud 	if (sc->sc_fd < 0) {
    134       1.1  reinoud 		aprint_error(": error %d opening path\n", thunk_geterrno());
    135       1.1  reinoud 		return;
    136       1.1  reinoud 	}
    137       1.1  reinoud 
    138       1.1  reinoud 	aprint_naive("\n");
    139       1.1  reinoud 	aprint_normal("\n");
    140       1.1  reinoud 
    141       1.1  reinoud 	sc->sc_ih = softint_establish(SOFTINT_BIO,
    142       1.1  reinoud 		vatapi_complete, sc);
    143       1.1  reinoud 
    144       1.1  reinoud 	/* rest of the configuration is deferred */
    145       1.1  reinoud 	config_interrupts(self, vatapi_callback);
    146       1.1  reinoud }
    147       1.1  reinoud 
    148       1.1  reinoud static void
    149       1.1  reinoud vatapi_callback(device_t self)
    150       1.1  reinoud {
    151       1.1  reinoud 	struct vatapi_softc *sc = device_private(self);
    152       1.1  reinoud 	struct scsipi_adapter *adapt = &sc->sc_adapter;
    153       1.1  reinoud 	struct scsipi_channel *chan  = &sc->sc_channel;
    154       1.1  reinoud 
    155       1.1  reinoud 	/* set up the scsipi adapter and channel */
    156       1.1  reinoud 	memset(adapt, 0, sizeof(*adapt));
    157       1.1  reinoud 	adapt->adapt_dev = sc->sc_dev;
    158       1.1  reinoud 	adapt->adapt_nchannels = 1;
    159       1.1  reinoud 	adapt->adapt_request   = vatapi_scsipi_request;
    160       1.1  reinoud 	adapt->adapt_minphys   = vatapi_minphys;
    161       1.1  reinoud 	adapt->adapt_flags     = 0; //SCSIPI_ADAPT_POLL_ONLY;
    162       1.1  reinoud 	sc->sc_atapi_adapter.atapi_probe_device = vatapi_probe_device;
    163       1.1  reinoud 
    164       1.1  reinoud 	memset(chan,  0, sizeof(*chan));
    165       1.1  reinoud 	chan->chan_adapter    = adapt;
    166       1.1  reinoud 	chan->chan_bustype    = &vatapi_bustype;
    167       1.1  reinoud 	chan->chan_channel    = 0;	/* location */
    168       1.1  reinoud 	chan->chan_flags      = SCSIPI_CHAN_OPENINGS;
    169       1.1  reinoud 	chan->chan_openings   = 1;
    170       1.1  reinoud 	chan->chan_max_periph = 1;
    171       1.1  reinoud 	chan->chan_ntargets   = 1;
    172       1.1  reinoud 	chan->chan_nluns      = 1;
    173       1.1  reinoud 
    174       1.1  reinoud 	/* set polling */
    175       1.1  reinoud 	//sc->sc_flags = VATAPI_FLAG_POLLING;
    176       1.1  reinoud 
    177       1.1  reinoud 	/* we `discovered' an atapi adapter */
    178  1.2.18.1  thorpej 	sc->sc_vatapibus =
    179  1.2.18.1  thorpej 	    config_found(sc->sc_dev, chan, atapiprint, CFARG_EOL);
    180       1.1  reinoud }
    181       1.1  reinoud 
    182       1.1  reinoud 
    183       1.1  reinoud /* XXX why is it be called minphys, when it enforces maxphys? */
    184       1.1  reinoud static void
    185       1.1  reinoud vatapi_minphys(struct buf *bp)
    186       1.1  reinoud {
    187       1.1  reinoud 	if (bp->b_bcount > MAX_SIZE)
    188       1.1  reinoud 		bp->b_bcount = MAX_SIZE;
    189       1.1  reinoud 	minphys(bp);
    190       1.1  reinoud }
    191       1.1  reinoud 
    192       1.1  reinoud /*
    193       1.1  reinoud  * ATAPI device probing
    194       1.1  reinoud  */
    195       1.1  reinoud static void
    196       1.1  reinoud vatapi_probe_device(struct atapibus_softc *atapi, int target)
    197       1.1  reinoud {
    198       1.1  reinoud 	struct scsipi_channel *chan = atapi->sc_channel;
    199       1.1  reinoud 	struct scsipi_periph *periph;
    200       1.1  reinoud 	struct scsipibus_attach_args sa;
    201       1.1  reinoud 	char vendor[33], product[65], revision[17];
    202       1.1  reinoud 	struct scsipi_inquiry_data inqbuf;
    203       1.1  reinoud 
    204       1.1  reinoud 	if (target != VDEV_ATAPI_DRIVE)	/* only probe drive 0 */
    205       1.1  reinoud 		return;
    206       1.1  reinoud 
    207       1.1  reinoud 	/* skip if already attached */
    208       1.1  reinoud 	if (scsipi_lookup_periph(chan, target, 0) != NULL)
    209       1.1  reinoud 		return;
    210       1.1  reinoud 
    211       1.1  reinoud 	/* allocate and set up periph structure */
    212       1.1  reinoud 	periph = scsipi_alloc_periph(M_NOWAIT);
    213       1.1  reinoud 	if (periph == NULL) {
    214       1.1  reinoud 		aprint_error_dev(atapi->sc_dev,
    215       1.1  reinoud 		    "can't allocate link for drive %d\n", target);
    216       1.1  reinoud 		return;
    217       1.1  reinoud 	}
    218       1.1  reinoud 	periph->periph_channel = chan;
    219       1.1  reinoud 	periph->periph_switch = &atapi_probe_periphsw;
    220       1.1  reinoud 	periph->periph_target = target;
    221       1.1  reinoud 	periph->periph_quirks = chan->chan_defquirks;
    222       1.1  reinoud 
    223       1.1  reinoud 	/* inquiry */
    224       1.1  reinoud 	aprint_verbose("%s: inquiry devices\n", __func__);
    225       1.1  reinoud 	memset(&inqbuf, 0, sizeof(inqbuf));
    226       1.1  reinoud 	if (scsipi_inquire(periph, &inqbuf, XS_CTL_DISCOVERY) != 0) {
    227       1.1  reinoud 		aprint_error_dev(atapi->sc_dev, ": scsipi_inquire failed\n");
    228       1.1  reinoud 		free(periph, M_DEVBUF);
    229       1.1  reinoud 		return;
    230       1.1  reinoud 	}
    231       1.1  reinoud 
    232       1.1  reinoud #define scsipi_strvis(a, al, b, bl) strlcpy(a, b, al)
    233       1.1  reinoud 	scsipi_strvis(vendor, 33, inqbuf.vendor, 8);
    234       1.1  reinoud 	scsipi_strvis(product, 65, inqbuf.product, 16);
    235       1.1  reinoud 	scsipi_strvis(revision, 17, inqbuf.revision, 4);
    236       1.1  reinoud #undef scsipi_strvis
    237       1.1  reinoud 
    238       1.1  reinoud 	sa.sa_periph = periph;
    239       1.1  reinoud 	sa.sa_inqbuf.type = inqbuf.device;
    240       1.1  reinoud 	sa.sa_inqbuf.removable = inqbuf.dev_qual2 & SID_REMOVABLE ?
    241       1.1  reinoud 	    T_REMOV : T_FIXED;
    242       1.1  reinoud 	if (sa.sa_inqbuf.removable)
    243       1.1  reinoud 		periph->periph_flags |= PERIPH_REMOVABLE;
    244       1.1  reinoud 	sa.sa_inqbuf.vendor = vendor;
    245       1.1  reinoud 	sa.sa_inqbuf.product = product;
    246       1.1  reinoud 	sa.sa_inqbuf.revision = revision;
    247       1.1  reinoud 	sa.sa_inqptr = NULL;
    248       1.1  reinoud 
    249       1.1  reinoud 	/* ATAPI demands only READ10 and higher IIRC */
    250       1.1  reinoud 	periph->periph_quirks |= PQUIRK_ONLYBIG;
    251       1.1  reinoud 
    252       1.1  reinoud 	aprint_verbose(": probedev on vendor '%s' product '%s' revision '%s'\n",
    253       1.1  reinoud 		vendor, product, revision);
    254       1.1  reinoud 
    255       1.1  reinoud 	atapi_probe_device(atapi, target, periph, &sa);
    256       1.1  reinoud 	/* atapi_probe_device() frees the periph when there is no device.*/
    257       1.1  reinoud }
    258       1.1  reinoud 
    259       1.1  reinoud /*
    260       1.1  reinoud  * Issue a request for a periph.
    261       1.1  reinoud  */
    262       1.1  reinoud static void
    263       1.1  reinoud vatapi_scsipi_request(struct scsipi_channel *chan,
    264       1.1  reinoud 	scsipi_adapter_req_t req, void *arg)
    265       1.1  reinoud {
    266       1.1  reinoud 	device_t sc_dev = chan->chan_adapter->adapt_dev;
    267       1.1  reinoud 	struct vatapi_softc *sc = device_private(sc_dev);
    268       1.1  reinoud  	struct scsipi_xfer *xs = arg;
    269       1.1  reinoud 
    270       1.1  reinoud 	switch (req) {
    271       1.1  reinoud  	case ADAPTER_REQ_GROW_RESOURCES:
    272       1.1  reinoud  	case ADAPTER_REQ_SET_XFER_MODE:
    273       1.1  reinoud 		return;
    274       1.1  reinoud 	case ADAPTER_REQ_RUN_XFER :
    275       1.1  reinoud 		KASSERT(sc->sc_xs == NULL);
    276       1.1  reinoud 
    277       1.1  reinoud 		/* queue the command */
    278       1.1  reinoud 		KASSERT(sc->sc_xs == NULL);
    279       1.1  reinoud 		sc->sc_xs = xs;
    280       1.1  reinoud 		softint_schedule(sc->sc_ih);
    281       1.1  reinoud 	}
    282       1.1  reinoud }
    283       1.1  reinoud 
    284       1.1  reinoud 
    285       1.1  reinoud static void
    286       1.2  reinoud vatapi_report_problem(scsireq_t *kreq)
    287       1.2  reinoud {
    288       1.2  reinoud #ifdef SCSIVERBOSE
    289       1.2  reinoud 	printf("vatapi cmd failed: ");
    290       1.2  reinoud 	for (int i = 0; i < kreq->cmdlen; i++) {
    291       1.2  reinoud 		printf("%02x ", kreq->cmd[i]);
    292       1.2  reinoud 	}
    293       1.2  reinoud 	printf("\n");
    294       1.2  reinoud 	scsipi_print_sense_data_real(
    295       1.2  reinoud 		(struct scsi_sense_data *) kreq->sense, 1);
    296       1.2  reinoud #endif
    297       1.2  reinoud }
    298       1.2  reinoud 
    299       1.2  reinoud 
    300       1.2  reinoud static void
    301       1.1  reinoud vatapi_complete(void *arg)
    302       1.1  reinoud {
    303       1.1  reinoud 	struct vatapi_softc *sc = arg;
    304       1.1  reinoud  	struct scsipi_xfer *xs = sc->sc_xs;
    305       1.1  reinoud 	scsireq_t kreq;
    306       1.1  reinoud 
    307       1.1  reinoud 	memset(&kreq, 0, sizeof(kreq));
    308       1.1  reinoud 	memcpy(kreq.cmd, xs->cmd, xs->cmdlen);
    309       1.1  reinoud 	kreq.cmdlen = xs->cmdlen;
    310       1.1  reinoud 	kreq.databuf = xs->data;		/* in virt? */
    311       1.1  reinoud 	kreq.datalen = xs->datalen;
    312       1.1  reinoud 	kreq.timeout = xs->timeout;
    313       1.1  reinoud 
    314       1.1  reinoud 	kreq.flags = (xs->xs_control & XS_CTL_DATA_IN) ?
    315       1.1  reinoud 		SCCMD_READ : SCCMD_WRITE;
    316       1.1  reinoud 
    317       1.1  reinoud 	kreq.senselen = sizeof(struct scsi_sense_data);
    318       1.1  reinoud 
    319       1.1  reinoud 	xs->error = XS_SHORTSENSE;
    320       1.1  reinoud 	/* this is silly, but better make sure */
    321       1.1  reinoud 	thunk_assert_presence((vaddr_t) kreq.databuf,
    322       1.1  reinoud 		(size_t) kreq.datalen);
    323       1.1  reinoud 
    324       1.1  reinoud 	if (thunk_ioctl(sc->sc_fd, SCIOCCOMMAND, &kreq) != -1) {
    325       1.1  reinoud 		switch (kreq.retsts) {
    326       1.1  reinoud 		case SCCMD_OK :
    327       1.1  reinoud 			xs->resid = 0;
    328       1.1  reinoud 			xs->error = 0;
    329       1.1  reinoud 			break;
    330       1.1  reinoud 		case SCCMD_TIMEOUT :
    331       1.1  reinoud 			break;
    332       1.1  reinoud 		case SCCMD_BUSY :
    333       1.1  reinoud 			break;
    334       1.1  reinoud 		case SCCMD_SENSE :
    335       1.1  reinoud 			xs->error = XS_SHORTSENSE;	/* ATAPI */
    336       1.1  reinoud 			memcpy(&xs->sense.scsi_sense, kreq.sense,
    337       1.1  reinoud 				sizeof(struct scsi_sense_data));
    338       1.2  reinoud 			vatapi_report_problem(&kreq);
    339       1.1  reinoud 			break;
    340       1.1  reinoud 		default:
    341       1.1  reinoud 			thunk_printf("unhandled/unknown retstst %d\n", kreq.retsts);
    342       1.1  reinoud 			break;
    343       1.1  reinoud 		}
    344       1.1  reinoud 	} else {
    345       1.1  reinoud 		printf("thunk_ioctl == -1, errno %d\n", thunk_geterrno());
    346       1.1  reinoud 	}
    347       1.1  reinoud 	sc->sc_xs = NULL;
    348       1.1  reinoud 	scsipi_done(xs);
    349       1.1  reinoud }
    350       1.1  reinoud 
    351       1.1  reinoud 
    352       1.1  reinoud /*
    353       1.1  reinoud  * Kill off all pending xfers for a periph.
    354       1.1  reinoud  *
    355       1.1  reinoud  * Must be called at splbio().
    356       1.1  reinoud  */
    357       1.1  reinoud static void
    358       1.1  reinoud vatapi_kill_pending(struct scsipi_periph *periph)
    359       1.1  reinoud {
    360       1.1  reinoud 	/* do we need to do anything ? (yet?) */
    361       1.1  reinoud 	printf("%s: target %d\n", __func__, periph->periph_target);
    362       1.1  reinoud }
    363       1.1  reinoud 
    364