Home | History | Annotate | Line # | Download | only in pci
arcmsr.c revision 1.20.6.1
      1  1.20.6.1  wrstuden /*	$NetBSD: arcmsr.c,v 1.20.6.1 2008/09/18 04:35:05 wrstuden Exp $ */
      2       1.1   xtraeme /*	$OpenBSD: arc.c,v 1.68 2007/10/27 03:28:27 dlg Exp $ */
      3       1.1   xtraeme 
      4       1.1   xtraeme /*
      5      1.10   xtraeme  * Copyright (c) 2007, 2008 Juan Romero Pardines <xtraeme (at) netbsd.org>
      6       1.1   xtraeme  * Copyright (c) 2006 David Gwynne <dlg (at) openbsd.org>
      7       1.1   xtraeme  *
      8       1.1   xtraeme  * Permission to use, copy, modify, and distribute this software for any
      9       1.1   xtraeme  * purpose with or without fee is hereby granted, provided that the above
     10       1.1   xtraeme  * copyright notice and this permission notice appear in all copies.
     11       1.1   xtraeme  *
     12       1.1   xtraeme  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     13       1.1   xtraeme  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     14       1.1   xtraeme  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     15       1.1   xtraeme  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     16       1.1   xtraeme  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     17       1.1   xtraeme  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     18       1.1   xtraeme  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     19       1.1   xtraeme  */
     20       1.1   xtraeme 
     21       1.1   xtraeme #include "bio.h"
     22       1.1   xtraeme 
     23       1.1   xtraeme #include <sys/cdefs.h>
     24  1.20.6.1  wrstuden __KERNEL_RCSID(0, "$NetBSD: arcmsr.c,v 1.20.6.1 2008/09/18 04:35:05 wrstuden Exp $");
     25       1.1   xtraeme 
     26       1.1   xtraeme #include <sys/param.h>
     27       1.1   xtraeme #include <sys/buf.h>
     28       1.1   xtraeme #include <sys/kernel.h>
     29       1.1   xtraeme #include <sys/malloc.h>
     30       1.1   xtraeme #include <sys/device.h>
     31       1.7   xtraeme #include <sys/kmem.h>
     32       1.1   xtraeme #include <sys/kthread.h>
     33       1.3   xtraeme #include <sys/mutex.h>
     34       1.3   xtraeme #include <sys/condvar.h>
     35       1.5   xtraeme #include <sys/rwlock.h>
     36       1.1   xtraeme 
     37       1.1   xtraeme #if NBIO > 0
     38       1.1   xtraeme #include <sys/ioctl.h>
     39       1.1   xtraeme #include <dev/biovar.h>
     40       1.1   xtraeme #endif
     41       1.1   xtraeme 
     42       1.1   xtraeme #include <dev/pci/pcireg.h>
     43       1.1   xtraeme #include <dev/pci/pcivar.h>
     44       1.1   xtraeme #include <dev/pci/pcidevs.h>
     45       1.1   xtraeme 
     46       1.1   xtraeme #include <dev/scsipi/scsipi_all.h>
     47       1.1   xtraeme #include <dev/scsipi/scsi_all.h>
     48       1.1   xtraeme #include <dev/scsipi/scsiconf.h>
     49       1.1   xtraeme 
     50       1.1   xtraeme #include <dev/sysmon/sysmonvar.h>
     51       1.1   xtraeme 
     52       1.1   xtraeme #include <sys/bus.h>
     53       1.1   xtraeme 
     54       1.1   xtraeme #include <uvm/uvm_extern.h>	/* for PAGE_SIZE */
     55       1.1   xtraeme 
     56       1.1   xtraeme #include <dev/pci/arcmsrvar.h>
     57       1.1   xtraeme 
     58       1.1   xtraeme /* #define ARC_DEBUG */
     59       1.1   xtraeme #ifdef ARC_DEBUG
     60       1.1   xtraeme #define ARC_D_INIT	(1<<0)
     61       1.1   xtraeme #define ARC_D_RW	(1<<1)
     62       1.1   xtraeme #define ARC_D_DB	(1<<2)
     63       1.1   xtraeme 
     64       1.1   xtraeme int arcdebug = 0;
     65       1.1   xtraeme 
     66       1.1   xtraeme #define DPRINTF(p...)		do { if (arcdebug) printf(p); } while (0)
     67       1.1   xtraeme #define DNPRINTF(n, p...)	do { if ((n) & arcdebug) printf(p); } while (0)
     68       1.1   xtraeme 
     69       1.1   xtraeme #else
     70  1.20.6.1  wrstuden #define DPRINTF(p, ...)		/* p */
     71  1.20.6.1  wrstuden #define DNPRINTF(n, p, ...)	/* n, p */
     72       1.1   xtraeme #endif
     73       1.1   xtraeme 
     74       1.1   xtraeme /*
     75       1.1   xtraeme  * the fw header must always equal this.
     76       1.1   xtraeme  */
     77       1.1   xtraeme static struct arc_fw_hdr arc_fw_hdr = { 0x5e, 0x01, 0x61 };
     78       1.1   xtraeme 
     79       1.1   xtraeme /*
     80       1.1   xtraeme  * autoconf(9) glue.
     81       1.1   xtraeme  */
     82      1.19   xtraeme static int 	arc_match(device_t, cfdata_t, void *);
     83       1.1   xtraeme static void 	arc_attach(device_t, device_t, void *);
     84       1.1   xtraeme static int 	arc_detach(device_t, int);
     85      1.10   xtraeme static bool 	arc_shutdown(device_t, int);
     86       1.1   xtraeme static int 	arc_intr(void *);
     87       1.1   xtraeme static void	arc_minphys(struct buf *);
     88       1.1   xtraeme 
     89      1.19   xtraeme CFATTACH_DECL_NEW(arcmsr, sizeof(struct arc_softc),
     90       1.1   xtraeme 	arc_match, arc_attach, arc_detach, NULL);
     91       1.1   xtraeme 
     92       1.1   xtraeme /*
     93       1.1   xtraeme  * bio(4) and sysmon_envsys(9) glue.
     94       1.1   xtraeme  */
     95       1.1   xtraeme #if NBIO > 0
     96      1.19   xtraeme static int 	arc_bioctl(device_t, u_long, void *);
     97       1.1   xtraeme static int 	arc_bio_inq(struct arc_softc *, struct bioc_inq *);
     98       1.1   xtraeme static int 	arc_bio_vol(struct arc_softc *, struct bioc_vol *);
     99       1.9   xtraeme static int	arc_bio_disk_volume(struct arc_softc *, struct bioc_disk *);
    100       1.9   xtraeme static int	arc_bio_disk_novol(struct arc_softc *, struct bioc_disk *);
    101       1.9   xtraeme static void	arc_bio_disk_filldata(struct arc_softc *, struct bioc_disk *,
    102       1.9   xtraeme 				      struct arc_fw_diskinfo *, int);
    103       1.1   xtraeme static int 	arc_bio_alarm(struct arc_softc *, struct bioc_alarm *);
    104       1.1   xtraeme static int 	arc_bio_alarm_state(struct arc_softc *, struct bioc_alarm *);
    105       1.1   xtraeme static int 	arc_bio_getvol(struct arc_softc *, int,
    106       1.1   xtraeme 			       struct arc_fw_volinfo *);
    107       1.9   xtraeme static int	arc_bio_setstate(struct arc_softc *, struct bioc_setstate *);
    108       1.9   xtraeme static int 	arc_bio_volops(struct arc_softc *, struct bioc_volops *);
    109       1.1   xtraeme static void 	arc_create_sensors(void *);
    110       1.2   xtraeme static void 	arc_refresh_sensors(struct sysmon_envsys *, envsys_data_t *);
    111       1.9   xtraeme static int	arc_fw_parse_status_code(struct arc_softc *, uint8_t *);
    112       1.1   xtraeme #endif
    113       1.1   xtraeme 
    114       1.1   xtraeme static int
    115      1.19   xtraeme arc_match(device_t parent, cfdata_t match, void *aux)
    116       1.1   xtraeme {
    117       1.1   xtraeme 	struct pci_attach_args *pa = aux;
    118       1.1   xtraeme 
    119       1.1   xtraeme 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ARECA) {
    120       1.1   xtraeme 		switch (PCI_PRODUCT(pa->pa_id)) {
    121       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1110:
    122       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1120:
    123       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1130:
    124       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1160:
    125       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1170:
    126       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1200:
    127       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1202:
    128       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1210:
    129       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1220:
    130       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1230:
    131       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1260:
    132       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1270:
    133       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1280:
    134       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1380:
    135       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1381:
    136       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1680:
    137       1.1   xtraeme 		case PCI_PRODUCT_ARECA_ARC1681:
    138       1.1   xtraeme 			return 1;
    139       1.1   xtraeme 		default:
    140       1.1   xtraeme 			break;
    141       1.1   xtraeme 		}
    142       1.1   xtraeme 	}
    143       1.1   xtraeme 
    144       1.1   xtraeme 	return 0;
    145       1.1   xtraeme }
    146       1.1   xtraeme 
    147       1.1   xtraeme static void
    148       1.1   xtraeme arc_attach(device_t parent, device_t self, void *aux)
    149       1.1   xtraeme {
    150       1.1   xtraeme 	struct arc_softc	*sc = device_private(self);
    151       1.1   xtraeme 	struct pci_attach_args	*pa = aux;
    152       1.1   xtraeme 	struct scsipi_adapter	*adapt = &sc->sc_adapter;
    153       1.1   xtraeme 	struct scsipi_channel	*chan = &sc->sc_chan;
    154       1.1   xtraeme 
    155      1.19   xtraeme 	sc->sc_dev = self;
    156       1.1   xtraeme 	sc->sc_talking = 0;
    157       1.5   xtraeme 	rw_init(&sc->sc_rwlock);
    158       1.3   xtraeme 	mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_BIO);
    159       1.3   xtraeme 	cv_init(&sc->sc_condvar, "arcdb");
    160       1.1   xtraeme 
    161      1.19   xtraeme 	if (arc_map_pci_resources(self, pa) != 0) {
    162       1.1   xtraeme 		/* error message printed by arc_map_pci_resources */
    163       1.1   xtraeme 		return;
    164       1.1   xtraeme 	}
    165       1.1   xtraeme 
    166      1.19   xtraeme 	if (arc_query_firmware(self) != 0) {
    167       1.1   xtraeme 		/* error message printed by arc_query_firmware */
    168       1.1   xtraeme 		goto unmap_pci;
    169       1.1   xtraeme 	}
    170       1.1   xtraeme 
    171      1.19   xtraeme 	if (arc_alloc_ccbs(self) != 0) {
    172       1.1   xtraeme 		/* error message printed by arc_alloc_ccbs */
    173       1.1   xtraeme 		goto unmap_pci;
    174       1.1   xtraeme 	}
    175       1.1   xtraeme 
    176      1.10   xtraeme 	if (!pmf_device_register1(self, NULL, NULL, arc_shutdown))
    177      1.11   xtraeme 		panic("%s: couldn't establish shutdown handler\n",
    178      1.11   xtraeme 		    device_xname(self));
    179       1.1   xtraeme 
    180       1.1   xtraeme 	memset(adapt, 0, sizeof(*adapt));
    181       1.1   xtraeme 	adapt->adapt_dev = self;
    182       1.1   xtraeme 	adapt->adapt_nchannels = 1;
    183       1.1   xtraeme 	adapt->adapt_openings = sc->sc_req_count / ARC_MAX_TARGET;
    184       1.1   xtraeme 	adapt->adapt_max_periph = adapt->adapt_openings;
    185       1.1   xtraeme 	adapt->adapt_minphys = arc_minphys;
    186       1.1   xtraeme 	adapt->adapt_request = arc_scsi_cmd;
    187       1.1   xtraeme 
    188       1.1   xtraeme 	memset(chan, 0, sizeof(*chan));
    189       1.1   xtraeme 	chan->chan_adapter = adapt;
    190       1.1   xtraeme 	chan->chan_bustype = &scsi_bustype;
    191       1.1   xtraeme 	chan->chan_nluns = ARC_MAX_LUN;
    192       1.1   xtraeme 	chan->chan_ntargets = ARC_MAX_TARGET;
    193       1.1   xtraeme 	chan->chan_id = ARC_MAX_TARGET;
    194       1.4   xtraeme 	chan->chan_flags = SCSIPI_CHAN_NOSETTLE;
    195       1.1   xtraeme 
    196       1.9   xtraeme 	/*
    197       1.9   xtraeme 	 * Save the device_t returned, because we could to attach
    198       1.9   xtraeme 	 * devices via the management interface.
    199       1.9   xtraeme 	 */
    200       1.9   xtraeme 	sc->sc_scsibus_dv = config_found(self, &sc->sc_chan, scsiprint);
    201       1.1   xtraeme 
    202       1.1   xtraeme 	/* enable interrupts */
    203       1.1   xtraeme 	arc_write(sc, ARC_REG_INTRMASK,
    204       1.1   xtraeme 	    ~(ARC_REG_INTRMASK_POSTQUEUE|ARC_REG_INTRSTAT_DOORBELL));
    205       1.1   xtraeme 
    206       1.1   xtraeme #if NBIO > 0
    207       1.7   xtraeme 	/*
    208       1.7   xtraeme 	 * Register the driver to bio(4) and setup the sensors.
    209       1.7   xtraeme 	 */
    210       1.1   xtraeme 	if (bio_register(self, arc_bioctl) != 0)
    211       1.1   xtraeme 		panic("%s: bioctl registration failed\n", device_xname(self));
    212       1.7   xtraeme 
    213       1.7   xtraeme 	/*
    214       1.1   xtraeme 	 * you need to talk to the firmware to get volume info. our firmware
    215       1.1   xtraeme 	 * interface relies on being able to sleep, so we need to use a thread
    216       1.1   xtraeme 	 * to do the work.
    217       1.1   xtraeme 	 */
    218       1.1   xtraeme 	if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
    219       1.1   xtraeme 	    arc_create_sensors, sc, &sc->sc_lwp, "arcmsr_sensors") != 0)
    220       1.1   xtraeme 		panic("%s: unable to create a kernel thread for sensors\n",
    221       1.1   xtraeme 		    device_xname(self));
    222       1.1   xtraeme #endif
    223       1.1   xtraeme 
    224       1.1   xtraeme         return;
    225       1.1   xtraeme 
    226       1.1   xtraeme unmap_pci:
    227       1.1   xtraeme 	arc_unmap_pci_resources(sc);
    228       1.1   xtraeme }
    229       1.1   xtraeme 
    230       1.1   xtraeme static int
    231       1.1   xtraeme arc_detach(device_t self, int flags)
    232       1.1   xtraeme {
    233       1.1   xtraeme 	struct arc_softc		*sc = device_private(self);
    234       1.1   xtraeme 
    235       1.1   xtraeme 	if (arc_msg0(sc, ARC_REG_INB_MSG0_STOP_BGRB) != 0)
    236      1.19   xtraeme 		aprint_error_dev(self, "timeout waiting to stop bg rebuild\n");
    237       1.1   xtraeme 
    238       1.1   xtraeme 	if (arc_msg0(sc, ARC_REG_INB_MSG0_FLUSH_CACHE) != 0)
    239      1.19   xtraeme 		aprint_error_dev(self, "timeout waiting to flush cache\n");
    240       1.1   xtraeme 
    241       1.1   xtraeme 	return 0;
    242       1.1   xtraeme }
    243       1.1   xtraeme 
    244      1.10   xtraeme static bool
    245      1.10   xtraeme arc_shutdown(device_t self, int how)
    246       1.1   xtraeme {
    247      1.10   xtraeme 	struct arc_softc		*sc = device_private(self);
    248       1.1   xtraeme 
    249       1.1   xtraeme 	if (arc_msg0(sc, ARC_REG_INB_MSG0_STOP_BGRB) != 0)
    250      1.19   xtraeme 		aprint_error_dev(self, "timeout waiting to stop bg rebuild\n");
    251       1.1   xtraeme 
    252       1.1   xtraeme 	if (arc_msg0(sc, ARC_REG_INB_MSG0_FLUSH_CACHE) != 0)
    253      1.19   xtraeme 		aprint_error_dev(self, "timeout waiting to flush cache\n");
    254      1.10   xtraeme 
    255      1.10   xtraeme 	return true;
    256       1.1   xtraeme }
    257       1.1   xtraeme 
    258       1.1   xtraeme static void
    259       1.1   xtraeme arc_minphys(struct buf *bp)
    260       1.1   xtraeme {
    261       1.1   xtraeme 	if (bp->b_bcount > MAXPHYS)
    262       1.1   xtraeme 		bp->b_bcount = MAXPHYS;
    263       1.1   xtraeme 	minphys(bp);
    264       1.1   xtraeme }
    265       1.1   xtraeme 
    266       1.1   xtraeme static int
    267       1.1   xtraeme arc_intr(void *arg)
    268       1.1   xtraeme {
    269       1.1   xtraeme 	struct arc_softc		*sc = arg;
    270       1.1   xtraeme 	struct arc_ccb			*ccb = NULL;
    271       1.1   xtraeme 	char				*kva = ARC_DMA_KVA(sc->sc_requests);
    272       1.1   xtraeme 	struct arc_io_cmd		*cmd;
    273       1.1   xtraeme 	uint32_t			reg, intrstat;
    274       1.1   xtraeme 
    275       1.7   xtraeme 	mutex_spin_enter(&sc->sc_mutex);
    276       1.1   xtraeme 	intrstat = arc_read(sc, ARC_REG_INTRSTAT);
    277       1.3   xtraeme 	if (intrstat == 0x0) {
    278       1.7   xtraeme 		mutex_spin_exit(&sc->sc_mutex);
    279       1.1   xtraeme 		return 0;
    280       1.3   xtraeme 	}
    281       1.1   xtraeme 
    282       1.1   xtraeme 	intrstat &= ARC_REG_INTRSTAT_POSTQUEUE | ARC_REG_INTRSTAT_DOORBELL;
    283       1.1   xtraeme 	arc_write(sc, ARC_REG_INTRSTAT, intrstat);
    284       1.1   xtraeme 
    285       1.1   xtraeme 	if (intrstat & ARC_REG_INTRSTAT_DOORBELL) {
    286       1.1   xtraeme 		if (sc->sc_talking) {
    287       1.1   xtraeme 			arc_write(sc, ARC_REG_INTRMASK,
    288       1.1   xtraeme 			    ~ARC_REG_INTRMASK_POSTQUEUE);
    289       1.3   xtraeme 			cv_broadcast(&sc->sc_condvar);
    290       1.1   xtraeme 		} else {
    291       1.1   xtraeme 			/* otherwise drop it */
    292       1.1   xtraeme 			reg = arc_read(sc, ARC_REG_OUTB_DOORBELL);
    293       1.1   xtraeme 			arc_write(sc, ARC_REG_OUTB_DOORBELL, reg);
    294       1.1   xtraeme 			if (reg & ARC_REG_OUTB_DOORBELL_WRITE_OK)
    295       1.1   xtraeme 				arc_write(sc, ARC_REG_INB_DOORBELL,
    296       1.1   xtraeme 				    ARC_REG_INB_DOORBELL_READ_OK);
    297       1.1   xtraeme 		}
    298       1.1   xtraeme 	}
    299       1.7   xtraeme 	mutex_spin_exit(&sc->sc_mutex);
    300       1.1   xtraeme 
    301       1.1   xtraeme 	while ((reg = arc_pop(sc)) != 0xffffffff) {
    302       1.1   xtraeme 		cmd = (struct arc_io_cmd *)(kva +
    303       1.1   xtraeme 		    ((reg << ARC_REG_REPLY_QUEUE_ADDR_SHIFT) -
    304       1.1   xtraeme 		    (uint32_t)ARC_DMA_DVA(sc->sc_requests)));
    305       1.1   xtraeme 		ccb = &sc->sc_ccbs[htole32(cmd->cmd.context)];
    306       1.1   xtraeme 
    307       1.1   xtraeme 		bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
    308       1.1   xtraeme 		    ccb->ccb_offset, ARC_MAX_IOCMDLEN,
    309       1.1   xtraeme 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    310       1.1   xtraeme 
    311       1.1   xtraeme 		arc_scsi_cmd_done(sc, ccb, reg);
    312       1.1   xtraeme 	}
    313       1.1   xtraeme 
    314       1.9   xtraeme 
    315       1.1   xtraeme 	return 1;
    316       1.1   xtraeme }
    317       1.1   xtraeme 
    318       1.1   xtraeme void
    319       1.1   xtraeme arc_scsi_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg)
    320       1.1   xtraeme {
    321       1.1   xtraeme 	struct scsipi_periph		*periph;
    322       1.1   xtraeme 	struct scsipi_xfer		*xs;
    323       1.1   xtraeme 	struct scsipi_adapter		*adapt = chan->chan_adapter;
    324       1.1   xtraeme 	struct arc_softc		*sc = device_private(adapt->adapt_dev);
    325       1.1   xtraeme 	struct arc_ccb			*ccb;
    326       1.1   xtraeme 	struct arc_msg_scsicmd		*cmd;
    327       1.1   xtraeme 	uint32_t			reg;
    328       1.1   xtraeme 	uint8_t				target;
    329       1.1   xtraeme 
    330       1.1   xtraeme 	switch (req) {
    331       1.1   xtraeme 	case ADAPTER_REQ_GROW_RESOURCES:
    332       1.1   xtraeme 		/* Not supported. */
    333       1.1   xtraeme 		return;
    334       1.1   xtraeme 	case ADAPTER_REQ_SET_XFER_MODE:
    335       1.1   xtraeme 		/* Not supported. */
    336       1.1   xtraeme 		return;
    337       1.1   xtraeme 	case ADAPTER_REQ_RUN_XFER:
    338       1.1   xtraeme 		break;
    339       1.1   xtraeme 	}
    340       1.1   xtraeme 
    341       1.7   xtraeme 	mutex_spin_enter(&sc->sc_mutex);
    342       1.7   xtraeme 
    343       1.1   xtraeme 	xs = arg;
    344       1.1   xtraeme 	periph = xs->xs_periph;
    345       1.1   xtraeme 	target = periph->periph_target;
    346       1.1   xtraeme 
    347       1.1   xtraeme 	if (xs->cmdlen > ARC_MSG_CDBLEN) {
    348       1.1   xtraeme 		memset(&xs->sense, 0, sizeof(xs->sense));
    349       1.1   xtraeme 		xs->sense.scsi_sense.response_code = SSD_RCODE_VALID | 0x70;
    350       1.1   xtraeme 		xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
    351       1.1   xtraeme 		xs->sense.scsi_sense.asc = 0x20;
    352       1.1   xtraeme 		xs->error = XS_SENSE;
    353       1.1   xtraeme 		xs->status = SCSI_CHECK;
    354       1.7   xtraeme 		mutex_spin_exit(&sc->sc_mutex);
    355       1.1   xtraeme 		scsipi_done(xs);
    356       1.3   xtraeme 		return;
    357       1.1   xtraeme 	}
    358       1.1   xtraeme 
    359       1.1   xtraeme 	ccb = arc_get_ccb(sc);
    360       1.1   xtraeme 	if (ccb == NULL) {
    361       1.1   xtraeme 		xs->error = XS_RESOURCE_SHORTAGE;
    362       1.7   xtraeme 		mutex_spin_exit(&sc->sc_mutex);
    363       1.1   xtraeme 		scsipi_done(xs);
    364       1.3   xtraeme 		return;
    365       1.1   xtraeme 	}
    366       1.1   xtraeme 
    367       1.1   xtraeme 	ccb->ccb_xs = xs;
    368       1.1   xtraeme 
    369       1.1   xtraeme 	if (arc_load_xs(ccb) != 0) {
    370       1.1   xtraeme 		xs->error = XS_DRIVER_STUFFUP;
    371       1.1   xtraeme 		arc_put_ccb(sc, ccb);
    372       1.7   xtraeme 		mutex_spin_exit(&sc->sc_mutex);
    373       1.1   xtraeme 		scsipi_done(xs);
    374       1.3   xtraeme 		return;
    375       1.1   xtraeme 	}
    376       1.1   xtraeme 
    377       1.1   xtraeme 	cmd = &ccb->ccb_cmd->cmd;
    378       1.1   xtraeme 	reg = ccb->ccb_cmd_post;
    379       1.1   xtraeme 
    380       1.1   xtraeme 	/* bus is always 0 */
    381       1.1   xtraeme 	cmd->target = target;
    382       1.1   xtraeme 	cmd->lun = periph->periph_lun;
    383       1.1   xtraeme 	cmd->function = 1; /* XXX magic number */
    384       1.1   xtraeme 
    385       1.1   xtraeme 	cmd->cdb_len = xs->cmdlen;
    386       1.1   xtraeme 	cmd->sgl_len = ccb->ccb_dmamap->dm_nsegs;
    387       1.1   xtraeme 	if (xs->xs_control & XS_CTL_DATA_OUT)
    388       1.1   xtraeme 		cmd->flags = ARC_MSG_SCSICMD_FLAG_WRITE;
    389       1.1   xtraeme 	if (ccb->ccb_dmamap->dm_nsegs > ARC_SGL_256LEN) {
    390       1.1   xtraeme 		cmd->flags |= ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512;
    391       1.1   xtraeme 		reg |= ARC_REG_POST_QUEUE_BIGFRAME;
    392       1.1   xtraeme 	}
    393       1.1   xtraeme 
    394       1.1   xtraeme 	cmd->context = htole32(ccb->ccb_id);
    395       1.1   xtraeme 	cmd->data_len = htole32(xs->datalen);
    396       1.1   xtraeme 
    397       1.1   xtraeme 	memcpy(cmd->cdb, xs->cmd, xs->cmdlen);
    398       1.1   xtraeme 
    399       1.1   xtraeme 	/* we've built the command, let's put it on the hw */
    400       1.1   xtraeme 	bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
    401       1.1   xtraeme 	    ccb->ccb_offset, ARC_MAX_IOCMDLEN,
    402       1.1   xtraeme 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    403       1.1   xtraeme 
    404       1.1   xtraeme 	arc_push(sc, reg);
    405       1.1   xtraeme 	if (xs->xs_control & XS_CTL_POLL) {
    406       1.1   xtraeme 		if (arc_complete(sc, ccb, xs->timeout) != 0) {
    407       1.1   xtraeme 			xs->error = XS_DRIVER_STUFFUP;
    408       1.7   xtraeme 			mutex_spin_exit(&sc->sc_mutex);
    409       1.1   xtraeme 			scsipi_done(xs);
    410       1.7   xtraeme 			return;
    411       1.1   xtraeme 		}
    412       1.1   xtraeme 	}
    413       1.7   xtraeme 
    414       1.7   xtraeme 	mutex_spin_exit(&sc->sc_mutex);
    415       1.1   xtraeme }
    416       1.1   xtraeme 
    417       1.1   xtraeme int
    418       1.1   xtraeme arc_load_xs(struct arc_ccb *ccb)
    419       1.1   xtraeme {
    420       1.1   xtraeme 	struct arc_softc		*sc = ccb->ccb_sc;
    421       1.1   xtraeme 	struct scsipi_xfer		*xs = ccb->ccb_xs;
    422       1.1   xtraeme 	bus_dmamap_t			dmap = ccb->ccb_dmamap;
    423       1.1   xtraeme 	struct arc_sge			*sgl = ccb->ccb_cmd->sgl, *sge;
    424       1.1   xtraeme 	uint64_t			addr;
    425       1.1   xtraeme 	int				i, error;
    426       1.1   xtraeme 
    427       1.1   xtraeme 	if (xs->datalen == 0)
    428       1.1   xtraeme 		return 0;
    429       1.1   xtraeme 
    430       1.1   xtraeme 	error = bus_dmamap_load(sc->sc_dmat, dmap,
    431       1.1   xtraeme 	    xs->data, xs->datalen, NULL,
    432       1.1   xtraeme 	    (xs->xs_control & XS_CTL_NOSLEEP) ?
    433       1.1   xtraeme 	    BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
    434       1.1   xtraeme 	if (error != 0) {
    435       1.1   xtraeme 		aprint_error("%s: error %d loading dmamap\n",
    436      1.19   xtraeme 		    device_xname(sc->sc_dev), error);
    437       1.1   xtraeme 		return 1;
    438       1.1   xtraeme 	}
    439       1.1   xtraeme 
    440       1.1   xtraeme 	for (i = 0; i < dmap->dm_nsegs; i++) {
    441       1.1   xtraeme 		sge = &sgl[i];
    442       1.1   xtraeme 
    443       1.1   xtraeme 		sge->sg_hdr = htole32(ARC_SGE_64BIT | dmap->dm_segs[i].ds_len);
    444       1.1   xtraeme 		addr = dmap->dm_segs[i].ds_addr;
    445       1.1   xtraeme 		sge->sg_hi_addr = htole32((uint32_t)(addr >> 32));
    446       1.1   xtraeme 		sge->sg_lo_addr = htole32((uint32_t)addr);
    447       1.1   xtraeme 	}
    448       1.1   xtraeme 
    449       1.1   xtraeme 	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
    450       1.1   xtraeme 	    (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD :
    451       1.1   xtraeme 	    BUS_DMASYNC_PREWRITE);
    452       1.1   xtraeme 
    453       1.1   xtraeme 	return 0;
    454       1.1   xtraeme }
    455       1.1   xtraeme 
    456       1.1   xtraeme void
    457       1.1   xtraeme arc_scsi_cmd_done(struct arc_softc *sc, struct arc_ccb *ccb, uint32_t reg)
    458       1.1   xtraeme {
    459       1.1   xtraeme 	struct scsipi_xfer		*xs = ccb->ccb_xs;
    460       1.1   xtraeme 	struct arc_msg_scsicmd		*cmd;
    461       1.1   xtraeme 
    462       1.1   xtraeme 	if (xs->datalen != 0) {
    463       1.1   xtraeme 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
    464       1.1   xtraeme 		    ccb->ccb_dmamap->dm_mapsize,
    465       1.1   xtraeme 		    (xs->xs_control & XS_CTL_DATA_IN) ?
    466       1.1   xtraeme 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
    467       1.1   xtraeme 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
    468       1.1   xtraeme 	}
    469       1.1   xtraeme 
    470       1.1   xtraeme 	/* timeout_del */
    471       1.1   xtraeme 	xs->status |= XS_STS_DONE;
    472       1.1   xtraeme 
    473       1.1   xtraeme 	if (reg & ARC_REG_REPLY_QUEUE_ERR) {
    474       1.1   xtraeme 		cmd = &ccb->ccb_cmd->cmd;
    475       1.1   xtraeme 
    476       1.1   xtraeme 		switch (cmd->status) {
    477       1.1   xtraeme 		case ARC_MSG_STATUS_SELTIMEOUT:
    478       1.1   xtraeme 		case ARC_MSG_STATUS_ABORTED:
    479       1.1   xtraeme 		case ARC_MSG_STATUS_INIT_FAIL:
    480       1.1   xtraeme 			xs->status = SCSI_OK;
    481       1.1   xtraeme 			xs->error = XS_SELTIMEOUT;
    482       1.1   xtraeme 			break;
    483       1.1   xtraeme 
    484       1.1   xtraeme 		case SCSI_CHECK:
    485       1.1   xtraeme 			memset(&xs->sense, 0, sizeof(xs->sense));
    486       1.1   xtraeme 			memcpy(&xs->sense, cmd->sense_data,
    487       1.1   xtraeme 			    min(ARC_MSG_SENSELEN, sizeof(xs->sense)));
    488       1.1   xtraeme 			xs->sense.scsi_sense.response_code =
    489       1.1   xtraeme 			    SSD_RCODE_VALID | 0x70;
    490       1.1   xtraeme 			xs->status = SCSI_CHECK;
    491       1.1   xtraeme 			xs->error = XS_SENSE;
    492       1.1   xtraeme 			xs->resid = 0;
    493       1.1   xtraeme 			break;
    494       1.1   xtraeme 
    495       1.1   xtraeme 		default:
    496       1.1   xtraeme 			/* unknown device status */
    497       1.1   xtraeme 			xs->error = XS_BUSY; /* try again later? */
    498       1.1   xtraeme 			xs->status = SCSI_BUSY;
    499       1.1   xtraeme 			break;
    500       1.1   xtraeme 		}
    501       1.1   xtraeme 	} else {
    502       1.1   xtraeme 		xs->status = SCSI_OK;
    503       1.1   xtraeme 		xs->error = XS_NOERROR;
    504       1.1   xtraeme 		xs->resid = 0;
    505       1.1   xtraeme 	}
    506       1.1   xtraeme 
    507       1.1   xtraeme 	arc_put_ccb(sc, ccb);
    508       1.1   xtraeme 	scsipi_done(xs);
    509       1.1   xtraeme }
    510       1.1   xtraeme 
    511       1.1   xtraeme int
    512       1.1   xtraeme arc_complete(struct arc_softc *sc, struct arc_ccb *nccb, int timeout)
    513       1.1   xtraeme {
    514       1.1   xtraeme 	struct arc_ccb			*ccb = NULL;
    515       1.1   xtraeme 	char				*kva = ARC_DMA_KVA(sc->sc_requests);
    516       1.1   xtraeme 	struct arc_io_cmd		*cmd;
    517       1.1   xtraeme 	uint32_t			reg;
    518       1.1   xtraeme 
    519       1.1   xtraeme 	do {
    520       1.1   xtraeme 		reg = arc_pop(sc);
    521       1.1   xtraeme 		if (reg == 0xffffffff) {
    522       1.1   xtraeme 			if (timeout-- == 0)
    523       1.1   xtraeme 				return 1;
    524       1.1   xtraeme 
    525       1.1   xtraeme 			delay(1000);
    526       1.1   xtraeme 			continue;
    527       1.1   xtraeme 		}
    528       1.1   xtraeme 
    529       1.1   xtraeme 		cmd = (struct arc_io_cmd *)(kva +
    530       1.1   xtraeme 		    ((reg << ARC_REG_REPLY_QUEUE_ADDR_SHIFT) -
    531       1.1   xtraeme 		    ARC_DMA_DVA(sc->sc_requests)));
    532       1.1   xtraeme 		ccb = &sc->sc_ccbs[htole32(cmd->cmd.context)];
    533       1.1   xtraeme 
    534       1.1   xtraeme 		bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
    535       1.1   xtraeme 		    ccb->ccb_offset, ARC_MAX_IOCMDLEN,
    536       1.1   xtraeme 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    537       1.1   xtraeme 
    538       1.1   xtraeme 		arc_scsi_cmd_done(sc, ccb, reg);
    539       1.1   xtraeme 	} while (nccb != ccb);
    540       1.1   xtraeme 
    541       1.1   xtraeme 	return 0;
    542       1.1   xtraeme }
    543       1.1   xtraeme 
    544       1.1   xtraeme int
    545      1.19   xtraeme arc_map_pci_resources(device_t self, struct pci_attach_args *pa)
    546       1.1   xtraeme {
    547      1.19   xtraeme 	struct arc_softc		*sc = device_private(self);
    548       1.1   xtraeme 	pcireg_t			memtype;
    549       1.1   xtraeme 	pci_intr_handle_t		ih;
    550       1.1   xtraeme 
    551       1.1   xtraeme 	sc->sc_pc = pa->pa_pc;
    552       1.1   xtraeme 	sc->sc_tag = pa->pa_tag;
    553       1.1   xtraeme 	sc->sc_dmat = pa->pa_dmat;
    554       1.1   xtraeme 
    555       1.1   xtraeme 	memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, ARC_PCI_BAR);
    556       1.1   xtraeme 	if (pci_mapreg_map(pa, ARC_PCI_BAR, memtype, 0, &sc->sc_iot,
    557       1.1   xtraeme 	    &sc->sc_ioh, NULL, &sc->sc_ios) != 0) {
    558       1.1   xtraeme 		aprint_error(": unable to map system interface register\n");
    559       1.1   xtraeme 		return 1;
    560       1.1   xtraeme 	}
    561       1.1   xtraeme 
    562       1.1   xtraeme 	if (pci_intr_map(pa, &ih) != 0) {
    563       1.1   xtraeme 		aprint_error(": unable to map interrupt\n");
    564       1.1   xtraeme 		goto unmap;
    565       1.1   xtraeme 	}
    566       1.1   xtraeme 
    567       1.1   xtraeme 	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
    568       1.1   xtraeme 	    arc_intr, sc);
    569       1.1   xtraeme 	if (sc->sc_ih == NULL) {
    570       1.1   xtraeme 		aprint_error(": unable to map interrupt [2]\n");
    571       1.1   xtraeme 		goto unmap;
    572       1.1   xtraeme 	}
    573      1.10   xtraeme 
    574      1.10   xtraeme 	aprint_normal("\n");
    575      1.19   xtraeme 	aprint_normal_dev(self, "interrupting at %s\n",
    576      1.19   xtraeme 	    pci_intr_string(pa->pa_pc, ih));
    577       1.1   xtraeme 
    578       1.1   xtraeme 	return 0;
    579       1.1   xtraeme 
    580       1.1   xtraeme unmap:
    581       1.1   xtraeme 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    582       1.1   xtraeme 	sc->sc_ios = 0;
    583       1.1   xtraeme 	return 1;
    584       1.1   xtraeme }
    585       1.1   xtraeme 
    586       1.1   xtraeme void
    587       1.1   xtraeme arc_unmap_pci_resources(struct arc_softc *sc)
    588       1.1   xtraeme {
    589       1.1   xtraeme 	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    590       1.1   xtraeme 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    591       1.1   xtraeme 	sc->sc_ios = 0;
    592       1.1   xtraeme }
    593       1.1   xtraeme 
    594       1.1   xtraeme int
    595      1.19   xtraeme arc_query_firmware(device_t self)
    596       1.1   xtraeme {
    597      1.19   xtraeme 	struct arc_softc 		*sc = device_private(self);
    598       1.1   xtraeme 	struct arc_msg_firmware_info	fwinfo;
    599       1.1   xtraeme 	char				string[81]; /* sizeof(vendor)*2+1 */
    600       1.1   xtraeme 
    601       1.1   xtraeme 	if (arc_wait_eq(sc, ARC_REG_OUTB_ADDR1, ARC_REG_OUTB_ADDR1_FIRMWARE_OK,
    602       1.1   xtraeme 	    ARC_REG_OUTB_ADDR1_FIRMWARE_OK) != 0) {
    603      1.19   xtraeme 		aprint_debug_dev(self, "timeout waiting for firmware ok\n");
    604       1.1   xtraeme 		return 1;
    605       1.1   xtraeme 	}
    606       1.1   xtraeme 
    607       1.1   xtraeme 	if (arc_msg0(sc, ARC_REG_INB_MSG0_GET_CONFIG) != 0) {
    608      1.19   xtraeme 		aprint_debug_dev(self, "timeout waiting for get config\n");
    609       1.3   xtraeme 		return 1;
    610       1.3   xtraeme 	}
    611       1.3   xtraeme 
    612       1.3   xtraeme 	if (arc_msg0(sc, ARC_REG_INB_MSG0_START_BGRB) != 0) {
    613      1.19   xtraeme 		aprint_debug_dev(self, "timeout waiting to start bg rebuild\n");
    614       1.1   xtraeme 		return 1;
    615       1.1   xtraeme 	}
    616       1.1   xtraeme 
    617       1.1   xtraeme 	arc_read_region(sc, ARC_REG_MSGBUF, &fwinfo, sizeof(fwinfo));
    618       1.1   xtraeme 
    619       1.1   xtraeme 	DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n",
    620      1.19   xtraeme 	    device_xname(self), htole32(fwinfo.signature));
    621       1.1   xtraeme 
    622       1.1   xtraeme 	if (htole32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
    623      1.19   xtraeme 		aprint_error_dev(self, "invalid firmware info from iop\n");
    624       1.1   xtraeme 		return 1;
    625       1.1   xtraeme 	}
    626       1.1   xtraeme 
    627       1.1   xtraeme 	DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n",
    628      1.19   xtraeme 	    device_xname(self), htole32(fwinfo.request_len));
    629       1.1   xtraeme 	DNPRINTF(ARC_D_INIT, "%s: queue_len: %d\n",
    630      1.19   xtraeme 	    device_xname(self), htole32(fwinfo.queue_len));
    631       1.1   xtraeme 	DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n",
    632      1.19   xtraeme 	    device_xname(self), htole32(fwinfo.sdram_size));
    633       1.1   xtraeme 	DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n",
    634      1.19   xtraeme 	    device_xname(self), htole32(fwinfo.sata_ports));
    635       1.1   xtraeme 
    636       1.1   xtraeme 	scsipi_strvis(string, 81, fwinfo.vendor, sizeof(fwinfo.vendor));
    637       1.1   xtraeme 	DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n",
    638      1.19   xtraeme 	    device_xname(self), string);
    639       1.1   xtraeme 
    640       1.1   xtraeme 	scsipi_strvis(string, 17, fwinfo.model, sizeof(fwinfo.model));
    641      1.19   xtraeme 	aprint_normal_dev(self, "Areca %s Host Adapter RAID controller\n",
    642      1.19   xtraeme 	    string);
    643       1.1   xtraeme 
    644       1.1   xtraeme 	scsipi_strvis(string, 33, fwinfo.fw_version, sizeof(fwinfo.fw_version));
    645       1.1   xtraeme 	DNPRINTF(ARC_D_INIT, "%s: version: \"%s\"\n",
    646      1.19   xtraeme 	    device_xname(self), string);
    647       1.1   xtraeme 
    648      1.19   xtraeme 	aprint_normal_dev(self, "%d ports, %dMB SDRAM, firmware <%s>\n",
    649      1.19   xtraeme 	    htole32(fwinfo.sata_ports), htole32(fwinfo.sdram_size), string);
    650       1.9   xtraeme 
    651       1.1   xtraeme 	if (htole32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
    652      1.19   xtraeme 		aprint_error_dev(self,
    653      1.19   xtraeme 		    "unexpected request frame size (%d != %d)\n",
    654       1.1   xtraeme 		    htole32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
    655       1.1   xtraeme 		return 1;
    656       1.1   xtraeme 	}
    657       1.1   xtraeme 
    658       1.1   xtraeme 	sc->sc_req_count = htole32(fwinfo.queue_len);
    659       1.1   xtraeme 
    660       1.1   xtraeme 	return 0;
    661       1.1   xtraeme }
    662       1.1   xtraeme 
    663       1.1   xtraeme #if NBIO > 0
    664       1.1   xtraeme static int
    665      1.19   xtraeme arc_bioctl(device_t self, u_long cmd, void *addr)
    666       1.1   xtraeme {
    667       1.1   xtraeme 	struct arc_softc *sc = device_private(self);
    668       1.1   xtraeme 	int error = 0;
    669       1.1   xtraeme 
    670       1.1   xtraeme 	switch (cmd) {
    671       1.1   xtraeme 	case BIOCINQ:
    672       1.1   xtraeme 		error = arc_bio_inq(sc, (struct bioc_inq *)addr);
    673       1.1   xtraeme 		break;
    674       1.1   xtraeme 
    675       1.1   xtraeme 	case BIOCVOL:
    676       1.1   xtraeme 		error = arc_bio_vol(sc, (struct bioc_vol *)addr);
    677       1.1   xtraeme 		break;
    678       1.1   xtraeme 
    679       1.1   xtraeme 	case BIOCDISK:
    680       1.9   xtraeme 		error = arc_bio_disk_volume(sc, (struct bioc_disk *)addr);
    681       1.9   xtraeme 		break;
    682       1.9   xtraeme 
    683       1.9   xtraeme 	case BIOCDISK_NOVOL:
    684       1.9   xtraeme 		error = arc_bio_disk_novol(sc, (struct bioc_disk *)addr);
    685       1.1   xtraeme 		break;
    686       1.1   xtraeme 
    687       1.1   xtraeme 	case BIOCALARM:
    688       1.1   xtraeme 		error = arc_bio_alarm(sc, (struct bioc_alarm *)addr);
    689       1.1   xtraeme 		break;
    690       1.1   xtraeme 
    691       1.9   xtraeme 	case BIOCSETSTATE:
    692       1.9   xtraeme 		error = arc_bio_setstate(sc, (struct bioc_setstate *)addr);
    693       1.9   xtraeme 		break;
    694       1.9   xtraeme 
    695       1.9   xtraeme 	case BIOCVOLOPS:
    696       1.9   xtraeme 		error = arc_bio_volops(sc, (struct bioc_volops *)addr);
    697       1.9   xtraeme 		break;
    698       1.9   xtraeme 
    699       1.1   xtraeme 	default:
    700       1.1   xtraeme 		error = ENOTTY;
    701       1.1   xtraeme 		break;
    702       1.1   xtraeme 	}
    703       1.1   xtraeme 
    704       1.1   xtraeme 	return error;
    705       1.1   xtraeme }
    706       1.1   xtraeme 
    707       1.1   xtraeme static int
    708       1.9   xtraeme arc_fw_parse_status_code(struct arc_softc *sc, uint8_t *reply)
    709       1.9   xtraeme {
    710       1.9   xtraeme 	switch (*reply) {
    711       1.9   xtraeme 	case ARC_FW_CMD_RAIDINVAL:
    712       1.9   xtraeme 		printf("%s: firmware error (invalid raid set)\n",
    713      1.19   xtraeme 		    device_xname(sc->sc_dev));
    714       1.9   xtraeme 		return EINVAL;
    715       1.9   xtraeme 	case ARC_FW_CMD_VOLINVAL:
    716       1.9   xtraeme 		printf("%s: firmware error (invalid volume set)\n",
    717      1.19   xtraeme 		    device_xname(sc->sc_dev));
    718       1.9   xtraeme 		return EINVAL;
    719       1.9   xtraeme 	case ARC_FW_CMD_NORAID:
    720       1.9   xtraeme 		printf("%s: firmware error (unexistent raid set)\n",
    721      1.19   xtraeme 		    device_xname(sc->sc_dev));
    722       1.9   xtraeme 		return ENODEV;
    723       1.9   xtraeme 	case ARC_FW_CMD_NOVOLUME:
    724       1.9   xtraeme 		printf("%s: firmware error (unexistent volume set)\n",
    725      1.19   xtraeme 		    device_xname(sc->sc_dev));
    726       1.9   xtraeme 		return ENODEV;
    727       1.9   xtraeme 	case ARC_FW_CMD_NOPHYSDRV:
    728       1.9   xtraeme 		printf("%s: firmware error (unexistent physical drive)\n",
    729      1.19   xtraeme 		    device_xname(sc->sc_dev));
    730       1.9   xtraeme 		return ENODEV;
    731       1.9   xtraeme 	case ARC_FW_CMD_PARAM_ERR:
    732       1.9   xtraeme 		printf("%s: firmware error (parameter error)\n",
    733      1.19   xtraeme 		    device_xname(sc->sc_dev));
    734       1.9   xtraeme 		return EINVAL;
    735       1.9   xtraeme 	case ARC_FW_CMD_UNSUPPORTED:
    736       1.9   xtraeme 		printf("%s: firmware error (unsupported command)\n",
    737      1.19   xtraeme 		    device_xname(sc->sc_dev));
    738       1.9   xtraeme 		return EOPNOTSUPP;
    739       1.9   xtraeme 	case ARC_FW_CMD_DISKCFG_CHGD:
    740       1.9   xtraeme 		printf("%s: firmware error (disk configuration changed)\n",
    741      1.19   xtraeme 		    device_xname(sc->sc_dev));
    742       1.9   xtraeme 		return EINVAL;
    743       1.9   xtraeme 	case ARC_FW_CMD_PASS_INVAL:
    744       1.9   xtraeme 		printf("%s: firmware error (invalid password)\n",
    745      1.19   xtraeme 		    device_xname(sc->sc_dev));
    746       1.9   xtraeme 		return EINVAL;
    747       1.9   xtraeme 	case ARC_FW_CMD_NODISKSPACE:
    748       1.9   xtraeme 		printf("%s: firmware error (no disk space available)\n",
    749      1.19   xtraeme 		    device_xname(sc->sc_dev));
    750       1.9   xtraeme 		return EOPNOTSUPP;
    751       1.9   xtraeme 	case ARC_FW_CMD_CHECKSUM_ERR:
    752       1.9   xtraeme 		printf("%s: firmware error (checksum error)\n",
    753      1.19   xtraeme 		    device_xname(sc->sc_dev));
    754       1.9   xtraeme 		return EINVAL;
    755       1.9   xtraeme 	case ARC_FW_CMD_PASS_REQD:
    756       1.9   xtraeme 		printf("%s: firmware error (password required)\n",
    757      1.19   xtraeme 		    device_xname(sc->sc_dev));
    758       1.9   xtraeme 		return EPERM;
    759       1.9   xtraeme 	case ARC_FW_CMD_OK:
    760       1.9   xtraeme 	default:
    761       1.9   xtraeme 		return 0;
    762       1.9   xtraeme 	}
    763       1.9   xtraeme }
    764       1.9   xtraeme 
    765       1.9   xtraeme static int
    766       1.1   xtraeme arc_bio_alarm(struct arc_softc *sc, struct bioc_alarm *ba)
    767       1.1   xtraeme {
    768       1.1   xtraeme 	uint8_t	request[2], reply[1];
    769       1.1   xtraeme 	size_t	len;
    770       1.1   xtraeme 	int	error = 0;
    771       1.1   xtraeme 
    772       1.1   xtraeme 	switch (ba->ba_opcode) {
    773       1.1   xtraeme 	case BIOC_SAENABLE:
    774       1.1   xtraeme 	case BIOC_SADISABLE:
    775       1.1   xtraeme 		request[0] = ARC_FW_SET_ALARM;
    776       1.1   xtraeme 		request[1] = (ba->ba_opcode == BIOC_SAENABLE) ?
    777       1.1   xtraeme 		    ARC_FW_SET_ALARM_ENABLE : ARC_FW_SET_ALARM_DISABLE;
    778       1.1   xtraeme 		len = sizeof(request);
    779       1.1   xtraeme 
    780       1.1   xtraeme 		break;
    781       1.1   xtraeme 
    782       1.1   xtraeme 	case BIOC_SASILENCE:
    783       1.1   xtraeme 		request[0] = ARC_FW_MUTE_ALARM;
    784       1.1   xtraeme 		len = 1;
    785       1.1   xtraeme 
    786       1.1   xtraeme 		break;
    787       1.1   xtraeme 
    788       1.1   xtraeme 	case BIOC_GASTATUS:
    789       1.1   xtraeme 		/* system info is too big/ugly to deal with here */
    790       1.1   xtraeme 		return arc_bio_alarm_state(sc, ba);
    791       1.1   xtraeme 
    792       1.1   xtraeme 	default:
    793       1.1   xtraeme 		return EOPNOTSUPP;
    794       1.1   xtraeme 	}
    795       1.1   xtraeme 
    796       1.1   xtraeme 	error = arc_msgbuf(sc, request, len, reply, sizeof(reply));
    797       1.1   xtraeme 	if (error != 0)
    798       1.1   xtraeme 		return error;
    799       1.1   xtraeme 
    800       1.9   xtraeme 	return arc_fw_parse_status_code(sc, &reply[0]);
    801       1.1   xtraeme }
    802       1.1   xtraeme 
    803       1.1   xtraeme static int
    804       1.1   xtraeme arc_bio_alarm_state(struct arc_softc *sc, struct bioc_alarm *ba)
    805       1.1   xtraeme {
    806       1.1   xtraeme 	struct arc_fw_sysinfo	*sysinfo;
    807       1.9   xtraeme 	uint8_t			request;
    808       1.1   xtraeme 	int			error = 0;
    809       1.1   xtraeme 
    810      1.10   xtraeme 	sysinfo = kmem_zalloc(sizeof(*sysinfo), KM_SLEEP);
    811       1.1   xtraeme 
    812       1.1   xtraeme 	request = ARC_FW_SYSINFO;
    813       1.1   xtraeme 	error = arc_msgbuf(sc, &request, sizeof(request),
    814       1.1   xtraeme 	    sysinfo, sizeof(struct arc_fw_sysinfo));
    815       1.1   xtraeme 
    816       1.1   xtraeme 	if (error != 0)
    817       1.1   xtraeme 		goto out;
    818       1.1   xtraeme 
    819       1.1   xtraeme 	ba->ba_status = sysinfo->alarm;
    820       1.1   xtraeme 
    821       1.1   xtraeme out:
    822       1.7   xtraeme 	kmem_free(sysinfo, sizeof(*sysinfo));
    823       1.1   xtraeme 	return error;
    824       1.1   xtraeme }
    825       1.1   xtraeme 
    826       1.9   xtraeme static int
    827       1.9   xtraeme arc_bio_volops(struct arc_softc *sc, struct bioc_volops *bc)
    828       1.9   xtraeme {
    829       1.9   xtraeme 	/* to create a raid set */
    830       1.9   xtraeme 	struct req_craidset {
    831       1.9   xtraeme 		uint8_t		cmdcode;
    832       1.9   xtraeme 		uint32_t	devmask;
    833       1.9   xtraeme 		uint8_t 	raidset_name[16];
    834       1.9   xtraeme 	} __packed;
    835       1.9   xtraeme 
    836       1.9   xtraeme 	/* to create a volume set */
    837       1.9   xtraeme 	struct req_cvolset {
    838       1.9   xtraeme 		uint8_t 	cmdcode;
    839       1.9   xtraeme 		uint8_t 	raidset;
    840       1.9   xtraeme 		uint8_t 	volset_name[16];
    841       1.9   xtraeme 		uint64_t	capacity;
    842       1.9   xtraeme 		uint8_t 	raidlevel;
    843       1.9   xtraeme 		uint8_t 	stripe;
    844       1.9   xtraeme 		uint8_t 	scsi_chan;
    845       1.9   xtraeme 		uint8_t 	scsi_target;
    846       1.9   xtraeme 		uint8_t 	scsi_lun;
    847       1.9   xtraeme 		uint8_t 	tagqueue;
    848       1.9   xtraeme 		uint8_t 	cache;
    849       1.9   xtraeme 		uint8_t 	speed;
    850       1.9   xtraeme 		uint8_t 	quick_init;
    851       1.9   xtraeme 	} __packed;
    852       1.9   xtraeme 
    853       1.9   xtraeme 	struct scsibus_softc	*scsibus_sc = NULL;
    854       1.9   xtraeme 	struct req_craidset	req_craidset;
    855       1.9   xtraeme 	struct req_cvolset 	req_cvolset;
    856       1.9   xtraeme 	uint8_t 		request[2];
    857       1.9   xtraeme 	uint8_t 		reply[1];
    858       1.9   xtraeme 	int 			error = 0;
    859       1.9   xtraeme 
    860       1.9   xtraeme 	switch (bc->bc_opcode) {
    861       1.9   xtraeme 	case BIOC_VCREATE_VOLUME:
    862       1.9   xtraeme 	    {
    863       1.9   xtraeme 		/*
    864       1.9   xtraeme 		 * Zero out the structs so that we use some defaults
    865       1.9   xtraeme 		 * in raid and volume sets.
    866       1.9   xtraeme 		 */
    867       1.9   xtraeme 		memset(&req_craidset, 0, sizeof(req_craidset));
    868       1.9   xtraeme 		memset(&req_cvolset, 0, sizeof(req_cvolset));
    869       1.9   xtraeme 
    870       1.9   xtraeme 		/*
    871       1.9   xtraeme 		 * Firstly we have to create the raid set and
    872       1.9   xtraeme 		 * use the default name for all them.
    873       1.9   xtraeme 		 */
    874       1.9   xtraeme 		req_craidset.cmdcode = ARC_FW_CREATE_RAIDSET;
    875       1.9   xtraeme 		req_craidset.devmask = bc->bc_devmask;
    876       1.9   xtraeme 		error = arc_msgbuf(sc, &req_craidset, sizeof(req_craidset),
    877       1.9   xtraeme 		    reply, sizeof(reply));
    878       1.9   xtraeme 		if (error != 0)
    879       1.9   xtraeme 			return error;
    880       1.9   xtraeme 
    881       1.9   xtraeme 		error = arc_fw_parse_status_code(sc, &reply[0]);
    882       1.9   xtraeme 		if (error) {
    883       1.9   xtraeme 			printf("%s: create raidset%d failed\n",
    884      1.19   xtraeme 			    device_xname(sc->sc_dev), bc->bc_volid);
    885       1.9   xtraeme 			return error;
    886       1.9   xtraeme 		}
    887       1.9   xtraeme 
    888       1.9   xtraeme 		/*
    889       1.9   xtraeme 		 * At this point the raid set was created, so it's
    890       1.9   xtraeme 		 * time to create the volume set.
    891       1.9   xtraeme 		 */
    892       1.9   xtraeme 		req_cvolset.cmdcode = ARC_FW_CREATE_VOLUME;
    893       1.9   xtraeme 		req_cvolset.raidset = bc->bc_volid;
    894       1.9   xtraeme 		req_cvolset.capacity = bc->bc_size * ARC_BLOCKSIZE;
    895       1.9   xtraeme 
    896       1.9   xtraeme 		/*
    897       1.9   xtraeme 		 * Set the RAID level.
    898       1.9   xtraeme 		 */
    899       1.9   xtraeme 		switch (bc->bc_level) {
    900       1.9   xtraeme 		case 0:
    901       1.9   xtraeme 		case 1:
    902       1.9   xtraeme 			req_cvolset.raidlevel = bc->bc_level;
    903       1.9   xtraeme 			break;
    904      1.18   xtraeme 		case BIOC_SVOL_RAID10:
    905      1.18   xtraeme 			req_cvolset.raidlevel = 1;
    906      1.18   xtraeme 			break;
    907       1.9   xtraeme 		case 3:
    908       1.9   xtraeme 			req_cvolset.raidlevel = ARC_FW_VOL_RAIDLEVEL_3;
    909       1.9   xtraeme 			break;
    910       1.9   xtraeme 		case 5:
    911       1.9   xtraeme 			req_cvolset.raidlevel = ARC_FW_VOL_RAIDLEVEL_5;
    912       1.9   xtraeme 			break;
    913       1.9   xtraeme 		case 6:
    914       1.9   xtraeme 			req_cvolset.raidlevel = ARC_FW_VOL_RAIDLEVEL_6;
    915       1.9   xtraeme 			break;
    916       1.9   xtraeme 		default:
    917       1.9   xtraeme 			return EOPNOTSUPP;
    918       1.9   xtraeme 		}
    919       1.9   xtraeme 
    920       1.9   xtraeme 		/*
    921       1.9   xtraeme 		 * Set the stripe size.
    922       1.9   xtraeme 		 */
    923       1.9   xtraeme 		switch (bc->bc_stripe) {
    924       1.9   xtraeme 		case 4:
    925       1.9   xtraeme 			req_cvolset.stripe = 0;
    926       1.9   xtraeme 			break;
    927       1.9   xtraeme 		case 8:
    928       1.9   xtraeme 			req_cvolset.stripe = 1;
    929       1.9   xtraeme 			break;
    930       1.9   xtraeme 		case 16:
    931       1.9   xtraeme 			req_cvolset.stripe = 2;
    932       1.9   xtraeme 			break;
    933       1.9   xtraeme 		case 32:
    934       1.9   xtraeme 			req_cvolset.stripe = 3;
    935       1.9   xtraeme 			break;
    936       1.9   xtraeme 		case 64:
    937       1.9   xtraeme 			req_cvolset.stripe = 4;
    938       1.9   xtraeme 			break;
    939       1.9   xtraeme 		case 128:
    940       1.9   xtraeme 			req_cvolset.stripe = 5;
    941       1.9   xtraeme 			break;
    942       1.9   xtraeme 		default:
    943       1.9   xtraeme 			req_cvolset.stripe = 4; /* by default 64K */
    944       1.9   xtraeme 			break;
    945       1.9   xtraeme 		}
    946       1.9   xtraeme 
    947       1.9   xtraeme 		req_cvolset.scsi_chan = bc->bc_channel;
    948       1.9   xtraeme 		req_cvolset.scsi_target = bc->bc_target;
    949       1.9   xtraeme 		req_cvolset.scsi_lun = bc->bc_lun;
    950       1.9   xtraeme 		req_cvolset.tagqueue = 1; /* always enabled */
    951       1.9   xtraeme 		req_cvolset.cache = 1; /* always enabled */
    952       1.9   xtraeme 		req_cvolset.speed = 4; /* always max speed */
    953       1.9   xtraeme 
    954      1.18   xtraeme 		/* RAID 1 and 1+0 levels need foreground initialization */
    955      1.18   xtraeme 		if (bc->bc_level == 1 || bc->bc_level == BIOC_SVOL_RAID10)
    956      1.17   xtraeme 			req_cvolset.quick_init = 1; /* foreground init */
    957      1.17   xtraeme 
    958       1.9   xtraeme 		error = arc_msgbuf(sc, &req_cvolset, sizeof(req_cvolset),
    959       1.9   xtraeme 		    reply, sizeof(reply));
    960       1.9   xtraeme 		if (error != 0)
    961       1.9   xtraeme 			return error;
    962       1.9   xtraeme 
    963       1.9   xtraeme 		error = arc_fw_parse_status_code(sc, &reply[0]);
    964       1.9   xtraeme 		if (error) {
    965       1.9   xtraeme 			printf("%s: create volumeset%d failed\n",
    966      1.19   xtraeme 			    device_xname(sc->sc_dev), bc->bc_volid);
    967       1.9   xtraeme 			return error;
    968       1.9   xtraeme 		}
    969       1.9   xtraeme 
    970       1.9   xtraeme 		/*
    971      1.17   xtraeme 		 * If we are creating a RAID 1 or RAID 1+0 volume,
    972      1.17   xtraeme 		 * the volume will be created immediately but it won't
    973      1.17   xtraeme 		 * be available until the initialization is done... so
    974      1.17   xtraeme 		 * don't bother attaching the sd(4) device.
    975      1.17   xtraeme 		 */
    976      1.18   xtraeme 		if (bc->bc_level == 1 || bc->bc_level == BIOC_SVOL_RAID10)
    977      1.17   xtraeme 			break;
    978      1.17   xtraeme 
    979      1.17   xtraeme 		/*
    980       1.9   xtraeme 		 * Do a rescan on the bus to attach the device associated
    981       1.9   xtraeme 		 * with the new volume.
    982       1.9   xtraeme 		 */
    983       1.9   xtraeme 		scsibus_sc = device_private(sc->sc_scsibus_dv);
    984       1.9   xtraeme 		(void)scsi_probe_bus(scsibus_sc, bc->bc_target, bc->bc_lun);
    985       1.9   xtraeme 
    986       1.9   xtraeme 		break;
    987       1.9   xtraeme 	    }
    988       1.9   xtraeme 	case BIOC_VREMOVE_VOLUME:
    989       1.9   xtraeme 	    {
    990       1.9   xtraeme 		/*
    991       1.9   xtraeme 		 * Remove the volume set specified in bc_volid.
    992       1.9   xtraeme 		 */
    993       1.9   xtraeme 		request[0] = ARC_FW_DELETE_VOLUME;
    994       1.9   xtraeme 		request[1] = bc->bc_volid;
    995       1.9   xtraeme 		error = arc_msgbuf(sc, request, sizeof(request),
    996       1.9   xtraeme 		    reply, sizeof(reply));
    997       1.9   xtraeme 		if (error != 0)
    998       1.9   xtraeme 			return error;
    999       1.9   xtraeme 
   1000       1.9   xtraeme 		error = arc_fw_parse_status_code(sc, &reply[0]);
   1001       1.9   xtraeme 		if (error) {
   1002       1.9   xtraeme 			printf("%s: delete volumeset%d failed\n",
   1003      1.19   xtraeme 			    device_xname(sc->sc_dev), bc->bc_volid);
   1004       1.9   xtraeme 			return error;
   1005       1.9   xtraeme 		}
   1006       1.9   xtraeme 
   1007       1.9   xtraeme 		/*
   1008       1.9   xtraeme 		 * Detach the sd(4) device associated with the volume,
   1009       1.9   xtraeme 		 * but if there's an error don't make it a priority.
   1010       1.9   xtraeme 		 */
   1011       1.9   xtraeme 		error = scsipi_target_detach(&sc->sc_chan, bc->bc_target,
   1012       1.9   xtraeme 					     bc->bc_lun, 0);
   1013       1.9   xtraeme 		if (error)
   1014       1.9   xtraeme 			printf("%s: couldn't detach sd device for volume %d "
   1015       1.9   xtraeme 			    "at %u:%u.%u (error=%d)\n",
   1016      1.19   xtraeme 			    device_xname(sc->sc_dev), bc->bc_volid,
   1017       1.9   xtraeme 			    bc->bc_channel, bc->bc_target, bc->bc_lun, error);
   1018       1.9   xtraeme 
   1019       1.9   xtraeme 		/*
   1020       1.9   xtraeme 		 * and remove the raid set specified in bc_volid,
   1021       1.9   xtraeme 		 * we only care about volumes.
   1022       1.9   xtraeme 		 */
   1023       1.9   xtraeme 		request[0] = ARC_FW_DELETE_RAIDSET;
   1024       1.9   xtraeme 		request[1] = bc->bc_volid;
   1025       1.9   xtraeme 		error = arc_msgbuf(sc, request, sizeof(request),
   1026       1.9   xtraeme 		    reply, sizeof(reply));
   1027       1.9   xtraeme 		if (error != 0)
   1028       1.9   xtraeme 			return error;
   1029       1.9   xtraeme 
   1030       1.9   xtraeme 		error = arc_fw_parse_status_code(sc, &reply[0]);
   1031       1.9   xtraeme 		if (error) {
   1032       1.9   xtraeme 			printf("%s: delete raidset%d failed\n",
   1033      1.19   xtraeme 			    device_xname(sc->sc_dev), bc->bc_volid);
   1034       1.9   xtraeme 			return error;
   1035       1.9   xtraeme 		}
   1036       1.9   xtraeme 
   1037       1.9   xtraeme 		break;
   1038       1.9   xtraeme 	    }
   1039       1.9   xtraeme 	default:
   1040       1.9   xtraeme 		return EOPNOTSUPP;
   1041       1.9   xtraeme 	}
   1042       1.9   xtraeme 
   1043       1.9   xtraeme 	return error;
   1044       1.9   xtraeme }
   1045       1.9   xtraeme 
   1046       1.9   xtraeme static int
   1047       1.9   xtraeme arc_bio_setstate(struct arc_softc *sc, struct bioc_setstate *bs)
   1048       1.9   xtraeme {
   1049       1.9   xtraeme 	/* for a hotspare disk */
   1050       1.9   xtraeme 	struct request_hs {
   1051       1.9   xtraeme 		uint8_t		cmdcode;
   1052       1.9   xtraeme 		uint32_t	devmask;
   1053       1.9   xtraeme 	} __packed;
   1054       1.9   xtraeme 
   1055       1.9   xtraeme 	/* for a pass-through disk */
   1056       1.9   xtraeme 	struct request_pt {
   1057       1.9   xtraeme 		uint8_t 	cmdcode;
   1058       1.9   xtraeme 		uint8_t		devid;
   1059       1.9   xtraeme 		uint8_t		scsi_chan;
   1060       1.9   xtraeme 		uint8_t 	scsi_id;
   1061       1.9   xtraeme 		uint8_t 	scsi_lun;
   1062       1.9   xtraeme 		uint8_t 	tagged_queue;
   1063       1.9   xtraeme 		uint8_t 	cache_mode;
   1064       1.9   xtraeme 		uint8_t 	max_speed;
   1065       1.9   xtraeme 	} __packed;
   1066       1.9   xtraeme 
   1067       1.9   xtraeme 	struct scsibus_softc	*scsibus_sc = NULL;
   1068       1.9   xtraeme 	struct request_hs	req_hs; /* to add/remove hotspare */
   1069       1.9   xtraeme 	struct request_pt	req_pt;	/* to add a pass-through */
   1070       1.9   xtraeme 	uint8_t			req_gen[2];
   1071       1.9   xtraeme 	uint8_t			reply[1];
   1072       1.9   xtraeme 	int			error = 0;
   1073       1.9   xtraeme 
   1074       1.9   xtraeme 	switch (bs->bs_status) {
   1075       1.9   xtraeme 	case BIOC_SSHOTSPARE:
   1076       1.9   xtraeme 	    {
   1077       1.9   xtraeme 		req_hs.cmdcode = ARC_FW_CREATE_HOTSPARE;
   1078       1.9   xtraeme 		req_hs.devmask = (1 << bs->bs_target);
   1079       1.9   xtraeme 		goto hotspare;
   1080       1.9   xtraeme 	    }
   1081       1.9   xtraeme 	case BIOC_SSDELHOTSPARE:
   1082       1.9   xtraeme 	    {
   1083       1.9   xtraeme 		req_hs.cmdcode = ARC_FW_DELETE_HOTSPARE;
   1084       1.9   xtraeme 		req_hs.devmask = (1 << bs->bs_target);
   1085       1.9   xtraeme 		goto hotspare;
   1086       1.9   xtraeme 	    }
   1087       1.9   xtraeme 	case BIOC_SSPASSTHRU:
   1088       1.9   xtraeme 	    {
   1089       1.9   xtraeme 		req_pt.cmdcode = ARC_FW_CREATE_PASSTHRU;
   1090       1.9   xtraeme 		req_pt.devid = bs->bs_other_id; /* this wants device# */
   1091       1.9   xtraeme 		req_pt.scsi_chan = bs->bs_channel;
   1092       1.9   xtraeme 		req_pt.scsi_id = bs->bs_target;
   1093       1.9   xtraeme 		req_pt.scsi_lun = bs->bs_lun;
   1094       1.9   xtraeme 		req_pt.tagged_queue = 1; /* always enabled */
   1095       1.9   xtraeme 		req_pt.cache_mode = 1; /* always enabled */
   1096       1.9   xtraeme 		req_pt.max_speed = 4; /* always max speed */
   1097       1.9   xtraeme 
   1098       1.9   xtraeme 		error = arc_msgbuf(sc, &req_pt, sizeof(req_pt),
   1099       1.9   xtraeme 		    reply, sizeof(reply));
   1100       1.9   xtraeme 		if (error != 0)
   1101       1.9   xtraeme 			return error;
   1102       1.9   xtraeme 
   1103       1.9   xtraeme 		/*
   1104       1.9   xtraeme 		 * Do a rescan on the bus to attach the new device
   1105       1.9   xtraeme 		 * associated with the pass-through disk.
   1106       1.9   xtraeme 		 */
   1107       1.9   xtraeme 		scsibus_sc = device_private(sc->sc_scsibus_dv);
   1108       1.9   xtraeme 		(void)scsi_probe_bus(scsibus_sc, bs->bs_target, bs->bs_lun);
   1109       1.9   xtraeme 
   1110       1.9   xtraeme 		goto out;
   1111       1.9   xtraeme 	    }
   1112       1.9   xtraeme 	case BIOC_SSDELPASSTHRU:
   1113       1.9   xtraeme 	    {
   1114       1.9   xtraeme 		req_gen[0] = ARC_FW_DELETE_PASSTHRU;
   1115       1.9   xtraeme 		req_gen[1] = bs->bs_target;
   1116       1.9   xtraeme 		error = arc_msgbuf(sc, &req_gen, sizeof(req_gen),
   1117       1.9   xtraeme 		    reply, sizeof(reply));
   1118       1.9   xtraeme 		if (error != 0)
   1119       1.9   xtraeme 			return error;
   1120       1.9   xtraeme 
   1121       1.9   xtraeme 		/*
   1122       1.9   xtraeme 		 * Detach the sd device associated with this pass-through disk.
   1123       1.9   xtraeme 		 */
   1124       1.9   xtraeme 		error = scsipi_target_detach(&sc->sc_chan, bs->bs_target,
   1125       1.9   xtraeme 					     bs->bs_lun, 0);
   1126       1.9   xtraeme 		if (error)
   1127       1.9   xtraeme 			printf("%s: couldn't detach sd device for the "
   1128       1.9   xtraeme 			    "pass-through disk at %u:%u.%u (error=%d)\n",
   1129      1.19   xtraeme 			    device_xname(sc->sc_dev),
   1130       1.9   xtraeme 			    bs->bs_channel, bs->bs_target, bs->bs_lun, error);
   1131       1.9   xtraeme 
   1132       1.9   xtraeme 		goto out;
   1133       1.9   xtraeme 	    }
   1134       1.9   xtraeme 	case BIOC_SSCHECKSTART_VOL:
   1135       1.9   xtraeme 	    {
   1136       1.9   xtraeme 		req_gen[0] = ARC_FW_START_CHECKVOL;
   1137       1.9   xtraeme 		req_gen[1] = bs->bs_volid;
   1138       1.9   xtraeme 		error = arc_msgbuf(sc, &req_gen, sizeof(req_gen),
   1139       1.9   xtraeme 		    reply, sizeof(reply));
   1140       1.9   xtraeme 		if (error != 0)
   1141       1.9   xtraeme 			return error;
   1142       1.9   xtraeme 
   1143       1.9   xtraeme 		goto out;
   1144       1.9   xtraeme 	    }
   1145       1.9   xtraeme 	case BIOC_SSCHECKSTOP_VOL:
   1146       1.9   xtraeme 	    {
   1147       1.9   xtraeme 		uint8_t req = ARC_FW_STOP_CHECKVOL;
   1148       1.9   xtraeme 		error = arc_msgbuf(sc, &req, 1, reply, sizeof(reply));
   1149       1.9   xtraeme 		if (error != 0)
   1150       1.9   xtraeme 			return error;
   1151       1.9   xtraeme 
   1152       1.9   xtraeme 		goto out;
   1153       1.9   xtraeme 	    }
   1154       1.9   xtraeme 	default:
   1155       1.9   xtraeme 		return EOPNOTSUPP;
   1156       1.9   xtraeme 	}
   1157       1.9   xtraeme 
   1158       1.9   xtraeme hotspare:
   1159       1.9   xtraeme 	error = arc_msgbuf(sc, &req_hs, sizeof(req_hs),
   1160       1.9   xtraeme 	    reply, sizeof(reply));
   1161       1.9   xtraeme 	if (error != 0)
   1162       1.9   xtraeme 		return error;
   1163       1.9   xtraeme 
   1164       1.9   xtraeme out:
   1165       1.9   xtraeme 	return arc_fw_parse_status_code(sc, &reply[0]);
   1166       1.9   xtraeme }
   1167       1.1   xtraeme 
   1168       1.1   xtraeme static int
   1169       1.1   xtraeme arc_bio_inq(struct arc_softc *sc, struct bioc_inq *bi)
   1170       1.1   xtraeme {
   1171       1.1   xtraeme 	uint8_t			request[2];
   1172      1.15   xtraeme 	struct arc_fw_sysinfo	*sysinfo = NULL;
   1173       1.9   xtraeme 	struct arc_fw_raidinfo	*raidinfo;
   1174      1.14   xtraeme 	int			nvols = 0, i;
   1175       1.1   xtraeme 	int			error = 0;
   1176       1.1   xtraeme 
   1177      1.10   xtraeme 	raidinfo = kmem_zalloc(sizeof(*raidinfo), KM_SLEEP);
   1178       1.1   xtraeme 
   1179      1.15   xtraeme 	if (!sc->sc_maxraidset || !sc->sc_maxvolset || !sc->sc_cchans) {
   1180      1.15   xtraeme 		sysinfo = kmem_zalloc(sizeof(*sysinfo), KM_SLEEP);
   1181      1.15   xtraeme 
   1182      1.15   xtraeme 		request[0] = ARC_FW_SYSINFO;
   1183      1.15   xtraeme 		error = arc_msgbuf(sc, request, 1, sysinfo,
   1184      1.15   xtraeme 		    sizeof(struct arc_fw_sysinfo));
   1185      1.15   xtraeme 		if (error != 0)
   1186      1.15   xtraeme 			goto out;
   1187       1.1   xtraeme 
   1188      1.15   xtraeme 		sc->sc_maxraidset = sysinfo->max_raid_set;
   1189      1.15   xtraeme 		sc->sc_maxvolset = sysinfo->max_volume_set;
   1190      1.15   xtraeme 		sc->sc_cchans = sysinfo->ide_channels;
   1191      1.15   xtraeme 	}
   1192       1.1   xtraeme 
   1193       1.9   xtraeme 	request[0] = ARC_FW_RAIDINFO;
   1194      1.14   xtraeme 	for (i = 0; i < sc->sc_maxraidset; i++) {
   1195       1.1   xtraeme 		request[1] = i;
   1196       1.9   xtraeme 		error = arc_msgbuf(sc, request, sizeof(request), raidinfo,
   1197       1.9   xtraeme 		    sizeof(struct arc_fw_raidinfo));
   1198       1.1   xtraeme 		if (error != 0)
   1199       1.1   xtraeme 			goto out;
   1200       1.1   xtraeme 
   1201       1.9   xtraeme 		if (raidinfo->volumes)
   1202       1.1   xtraeme 			nvols++;
   1203       1.1   xtraeme 	}
   1204       1.1   xtraeme 
   1205      1.19   xtraeme 	strlcpy(bi->bi_dev, device_xname(sc->sc_dev), sizeof(bi->bi_dev));
   1206       1.1   xtraeme 	bi->bi_novol = nvols;
   1207      1.14   xtraeme 	bi->bi_nodisk = sc->sc_cchans;
   1208       1.9   xtraeme 
   1209       1.1   xtraeme out:
   1210      1.15   xtraeme 	if (sysinfo)
   1211      1.15   xtraeme 		kmem_free(sysinfo, sizeof(*sysinfo));
   1212       1.9   xtraeme 	kmem_free(raidinfo, sizeof(*raidinfo));
   1213       1.1   xtraeme 	return error;
   1214       1.1   xtraeme }
   1215       1.1   xtraeme 
   1216       1.1   xtraeme static int
   1217       1.1   xtraeme arc_bio_getvol(struct arc_softc *sc, int vol, struct arc_fw_volinfo *volinfo)
   1218       1.1   xtraeme {
   1219       1.1   xtraeme 	uint8_t			request[2];
   1220       1.1   xtraeme 	int			error = 0;
   1221      1.14   xtraeme 	int			nvols = 0, i;
   1222       1.1   xtraeme 
   1223       1.1   xtraeme 	request[0] = ARC_FW_VOLINFO;
   1224      1.14   xtraeme 	for (i = 0; i < sc->sc_maxvolset; i++) {
   1225       1.1   xtraeme 		request[1] = i;
   1226       1.1   xtraeme 		error = arc_msgbuf(sc, request, sizeof(request), volinfo,
   1227       1.1   xtraeme 		    sizeof(struct arc_fw_volinfo));
   1228       1.1   xtraeme 		if (error != 0)
   1229       1.1   xtraeme 			goto out;
   1230       1.1   xtraeme 
   1231       1.9   xtraeme 		if (volinfo->capacity == 0 && volinfo->capacity2 == 0)
   1232       1.1   xtraeme 			continue;
   1233       1.1   xtraeme 
   1234       1.1   xtraeme 		if (nvols == vol)
   1235       1.1   xtraeme 			break;
   1236       1.1   xtraeme 
   1237       1.1   xtraeme 		nvols++;
   1238       1.1   xtraeme 	}
   1239       1.1   xtraeme 
   1240       1.1   xtraeme 	if (nvols != vol ||
   1241       1.9   xtraeme 	    (volinfo->capacity == 0 && volinfo->capacity2 == 0)) {
   1242       1.1   xtraeme 		error = ENODEV;
   1243       1.1   xtraeme 		goto out;
   1244       1.1   xtraeme 	}
   1245       1.1   xtraeme 
   1246       1.1   xtraeme out:
   1247       1.1   xtraeme 	return error;
   1248       1.1   xtraeme }
   1249       1.1   xtraeme 
   1250       1.1   xtraeme static int
   1251       1.1   xtraeme arc_bio_vol(struct arc_softc *sc, struct bioc_vol *bv)
   1252       1.1   xtraeme {
   1253       1.1   xtraeme 	struct arc_fw_volinfo	*volinfo;
   1254       1.1   xtraeme 	uint64_t		blocks;
   1255       1.1   xtraeme 	uint32_t		status;
   1256       1.1   xtraeme 	int			error = 0;
   1257       1.1   xtraeme 
   1258      1.10   xtraeme 	volinfo = kmem_zalloc(sizeof(*volinfo), KM_SLEEP);
   1259       1.1   xtraeme 
   1260       1.1   xtraeme 	error = arc_bio_getvol(sc, bv->bv_volid, volinfo);
   1261       1.1   xtraeme 	if (error != 0)
   1262       1.1   xtraeme 		goto out;
   1263       1.1   xtraeme 
   1264       1.1   xtraeme 	bv->bv_percent = -1;
   1265       1.1   xtraeme 	bv->bv_seconds = 0;
   1266       1.1   xtraeme 
   1267       1.1   xtraeme 	status = htole32(volinfo->volume_status);
   1268       1.1   xtraeme 	if (status == 0x0) {
   1269       1.1   xtraeme 		if (htole32(volinfo->fail_mask) == 0x0)
   1270       1.1   xtraeme 			bv->bv_status = BIOC_SVONLINE;
   1271       1.1   xtraeme 		else
   1272       1.1   xtraeme 			bv->bv_status = BIOC_SVDEGRADED;
   1273       1.1   xtraeme 	} else if (status & ARC_FW_VOL_STATUS_NEED_REGEN) {
   1274       1.1   xtraeme 		bv->bv_status = BIOC_SVDEGRADED;
   1275       1.1   xtraeme 	} else if (status & ARC_FW_VOL_STATUS_FAILED) {
   1276       1.1   xtraeme 		bv->bv_status = BIOC_SVOFFLINE;
   1277       1.1   xtraeme 	} else if (status & ARC_FW_VOL_STATUS_INITTING) {
   1278       1.1   xtraeme 		bv->bv_status = BIOC_SVBUILDING;
   1279       1.9   xtraeme 		bv->bv_percent = htole32(volinfo->progress);
   1280       1.1   xtraeme 	} else if (status & ARC_FW_VOL_STATUS_REBUILDING) {
   1281       1.1   xtraeme 		bv->bv_status = BIOC_SVREBUILD;
   1282       1.9   xtraeme 		bv->bv_percent = htole32(volinfo->progress);
   1283       1.8   xtraeme 	} else if (status & ARC_FW_VOL_STATUS_MIGRATING) {
   1284       1.8   xtraeme 		bv->bv_status = BIOC_SVMIGRATING;
   1285       1.9   xtraeme 		bv->bv_percent = htole32(volinfo->progress);
   1286       1.9   xtraeme 	} else if (status & ARC_FW_VOL_STATUS_CHECKING) {
   1287       1.9   xtraeme 		bv->bv_status = BIOC_SVCHECKING;
   1288       1.9   xtraeme 		bv->bv_percent = htole32(volinfo->progress);
   1289      1.17   xtraeme 	} else if (status & ARC_FW_VOL_STATUS_NEED_INIT) {
   1290      1.17   xtraeme 		bv->bv_status = BIOC_SVOFFLINE;
   1291      1.17   xtraeme 	} else {
   1292      1.17   xtraeme 		printf("%s: volume %d status 0x%x\n",
   1293      1.19   xtraeme 		    device_xname(sc->sc_dev), bv->bv_volid, status);
   1294       1.1   xtraeme 	}
   1295       1.1   xtraeme 
   1296       1.1   xtraeme 	blocks = (uint64_t)htole32(volinfo->capacity2) << 32;
   1297       1.1   xtraeme 	blocks += (uint64_t)htole32(volinfo->capacity);
   1298       1.1   xtraeme 	bv->bv_size = blocks * ARC_BLOCKSIZE; /* XXX */
   1299       1.1   xtraeme 
   1300       1.1   xtraeme 	switch (volinfo->raid_level) {
   1301       1.1   xtraeme 	case ARC_FW_VOL_RAIDLEVEL_0:
   1302       1.1   xtraeme 		bv->bv_level = 0;
   1303       1.1   xtraeme 		break;
   1304       1.1   xtraeme 	case ARC_FW_VOL_RAIDLEVEL_1:
   1305      1.18   xtraeme 		if (volinfo->member_disks > 2)
   1306      1.18   xtraeme 			bv->bv_level = BIOC_SVOL_RAID10;
   1307      1.18   xtraeme 		else
   1308      1.18   xtraeme 			bv->bv_level = 1;
   1309       1.1   xtraeme 		break;
   1310       1.1   xtraeme 	case ARC_FW_VOL_RAIDLEVEL_3:
   1311       1.1   xtraeme 		bv->bv_level = 3;
   1312       1.1   xtraeme 		break;
   1313       1.1   xtraeme 	case ARC_FW_VOL_RAIDLEVEL_5:
   1314       1.1   xtraeme 		bv->bv_level = 5;
   1315       1.1   xtraeme 		break;
   1316       1.1   xtraeme 	case ARC_FW_VOL_RAIDLEVEL_6:
   1317       1.1   xtraeme 		bv->bv_level = 6;
   1318       1.1   xtraeme 		break;
   1319       1.1   xtraeme 	case ARC_FW_VOL_RAIDLEVEL_PASSTHRU:
   1320       1.9   xtraeme 		bv->bv_level = BIOC_SVOL_PASSTHRU;
   1321       1.9   xtraeme 		break;
   1322       1.1   xtraeme 	default:
   1323       1.1   xtraeme 		bv->bv_level = -1;
   1324       1.1   xtraeme 		break;
   1325       1.1   xtraeme 	}
   1326       1.1   xtraeme 
   1327       1.1   xtraeme 	bv->bv_nodisk = volinfo->member_disks;
   1328       1.9   xtraeme 	bv->bv_stripe_size = volinfo->stripe_size / 2;
   1329       1.9   xtraeme 	snprintf(bv->bv_dev, sizeof(bv->bv_dev), "sd%d", bv->bv_volid);
   1330       1.9   xtraeme 	scsipi_strvis(bv->bv_vendor, sizeof(bv->bv_vendor), volinfo->set_name,
   1331       1.9   xtraeme 	    sizeof(volinfo->set_name));
   1332       1.1   xtraeme 
   1333       1.1   xtraeme out:
   1334       1.7   xtraeme 	kmem_free(volinfo, sizeof(*volinfo));
   1335       1.1   xtraeme 	return error;
   1336       1.1   xtraeme }
   1337       1.1   xtraeme 
   1338       1.1   xtraeme static int
   1339       1.9   xtraeme arc_bio_disk_novol(struct arc_softc *sc, struct bioc_disk *bd)
   1340       1.1   xtraeme {
   1341       1.9   xtraeme 	struct arc_fw_diskinfo	*diskinfo;
   1342       1.1   xtraeme 	uint8_t			request[2];
   1343       1.1   xtraeme 	int			error = 0;
   1344       1.9   xtraeme 
   1345      1.10   xtraeme 	diskinfo = kmem_zalloc(sizeof(*diskinfo), KM_SLEEP);
   1346       1.9   xtraeme 
   1347      1.14   xtraeme 	if (bd->bd_diskid >= sc->sc_cchans) {
   1348       1.9   xtraeme 		error = ENODEV;
   1349       1.9   xtraeme 		goto out;
   1350       1.9   xtraeme 	}
   1351       1.9   xtraeme 
   1352       1.9   xtraeme 	request[0] = ARC_FW_DISKINFO;
   1353       1.9   xtraeme 	request[1] = bd->bd_diskid;
   1354       1.9   xtraeme 	error = arc_msgbuf(sc, request, sizeof(request),
   1355       1.9   xtraeme 	    diskinfo, sizeof(struct arc_fw_diskinfo));
   1356       1.9   xtraeme 	if (error != 0)
   1357      1.12   xtraeme 		goto out;
   1358       1.9   xtraeme 
   1359       1.9   xtraeme 	/* skip disks with no capacity */
   1360       1.9   xtraeme 	if (htole32(diskinfo->capacity) == 0 &&
   1361       1.9   xtraeme 	    htole32(diskinfo->capacity2) == 0)
   1362       1.9   xtraeme 		goto out;
   1363       1.9   xtraeme 
   1364       1.9   xtraeme 	bd->bd_disknovol = true;
   1365       1.9   xtraeme 	arc_bio_disk_filldata(sc, bd, diskinfo, bd->bd_diskid);
   1366       1.9   xtraeme 
   1367       1.9   xtraeme out:
   1368       1.9   xtraeme 	kmem_free(diskinfo, sizeof(*diskinfo));
   1369       1.9   xtraeme 	return error;
   1370       1.9   xtraeme }
   1371       1.9   xtraeme 
   1372       1.9   xtraeme static void
   1373       1.9   xtraeme arc_bio_disk_filldata(struct arc_softc *sc, struct bioc_disk *bd,
   1374       1.9   xtraeme 		     struct arc_fw_diskinfo *diskinfo, int diskid)
   1375       1.9   xtraeme {
   1376       1.1   xtraeme 	uint64_t		blocks;
   1377       1.1   xtraeme 	char			model[81];
   1378       1.1   xtraeme 	char			serial[41];
   1379       1.1   xtraeme 	char			rev[17];
   1380       1.1   xtraeme 
   1381      1.20   xtraeme 	switch (diskinfo->device_state) {
   1382       1.9   xtraeme 	case ARC_FW_DISK_PASSTHRU:
   1383       1.9   xtraeme 		bd->bd_status = BIOC_SDPASSTHRU;
   1384       1.9   xtraeme 		break;
   1385      1.20   xtraeme 	case ARC_FW_DISK_INITIALIZED:
   1386       1.9   xtraeme 	case ARC_FW_DISK_RAIDMEMBER:
   1387       1.9   xtraeme 		bd->bd_status = BIOC_SDONLINE;
   1388       1.9   xtraeme 		break;
   1389       1.9   xtraeme 	case ARC_FW_DISK_HOTSPARE:
   1390       1.9   xtraeme 		bd->bd_status = BIOC_SDHOTSPARE;
   1391       1.9   xtraeme 		break;
   1392       1.9   xtraeme 	case ARC_FW_DISK_UNUSED:
   1393       1.9   xtraeme 		bd->bd_status = BIOC_SDUNUSED;
   1394       1.9   xtraeme 		break;
   1395      1.14   xtraeme 	case 0:
   1396      1.14   xtraeme 		/* disk has been disconnected */
   1397      1.14   xtraeme 		bd->bd_status = BIOC_SDOFFLINE;
   1398      1.14   xtraeme 		bd->bd_channel = 1;
   1399      1.14   xtraeme 		bd->bd_target = 0;
   1400      1.14   xtraeme 		bd->bd_lun = 0;
   1401      1.14   xtraeme 		strlcpy(bd->bd_vendor, "disk missing", sizeof(bd->bd_vendor));
   1402      1.14   xtraeme 		break;
   1403       1.9   xtraeme 	default:
   1404       1.9   xtraeme 		printf("%s: unknown disk device_state: 0x%x\n", __func__,
   1405      1.20   xtraeme 		    diskinfo->device_state);
   1406       1.9   xtraeme 		bd->bd_status = BIOC_SDINVALID;
   1407       1.9   xtraeme 		return;
   1408       1.9   xtraeme 	}
   1409       1.9   xtraeme 
   1410       1.9   xtraeme 	blocks = (uint64_t)htole32(diskinfo->capacity2) << 32;
   1411       1.9   xtraeme 	blocks += (uint64_t)htole32(diskinfo->capacity);
   1412       1.9   xtraeme 	bd->bd_size = blocks * ARC_BLOCKSIZE; /* XXX */
   1413       1.9   xtraeme 
   1414       1.9   xtraeme 	scsipi_strvis(model, 81, diskinfo->model, sizeof(diskinfo->model));
   1415       1.9   xtraeme 	scsipi_strvis(serial, 41, diskinfo->serial, sizeof(diskinfo->serial));
   1416       1.9   xtraeme 	scsipi_strvis(rev, 17, diskinfo->firmware_rev,
   1417       1.9   xtraeme 	    sizeof(diskinfo->firmware_rev));
   1418       1.9   xtraeme 
   1419       1.9   xtraeme 	snprintf(bd->bd_vendor, sizeof(bd->bd_vendor), "%s %s", model, rev);
   1420       1.9   xtraeme 	strlcpy(bd->bd_serial, serial, sizeof(bd->bd_serial));
   1421       1.9   xtraeme 
   1422       1.9   xtraeme #if 0
   1423       1.9   xtraeme 	bd->bd_channel = diskinfo->scsi_attr.channel;
   1424       1.9   xtraeme 	bd->bd_target = diskinfo->scsi_attr.target;
   1425       1.9   xtraeme 	bd->bd_lun = diskinfo->scsi_attr.lun;
   1426       1.9   xtraeme #endif
   1427       1.9   xtraeme 
   1428       1.9   xtraeme 	/*
   1429       1.9   xtraeme 	 * the firwmare doesnt seem to fill scsi_attr in, so fake it with
   1430       1.9   xtraeme 	 * the diskid.
   1431       1.9   xtraeme 	 */
   1432       1.9   xtraeme 	bd->bd_channel = 0;
   1433       1.9   xtraeme 	bd->bd_target = diskid;
   1434       1.9   xtraeme 	bd->bd_lun = 0;
   1435       1.9   xtraeme }
   1436       1.9   xtraeme 
   1437       1.9   xtraeme static int
   1438       1.9   xtraeme arc_bio_disk_volume(struct arc_softc *sc, struct bioc_disk *bd)
   1439       1.9   xtraeme {
   1440       1.9   xtraeme 	struct arc_fw_raidinfo	*raidinfo;
   1441       1.9   xtraeme 	struct arc_fw_volinfo	*volinfo;
   1442       1.9   xtraeme 	struct arc_fw_diskinfo	*diskinfo;
   1443      1.14   xtraeme 	uint8_t			request[2];
   1444       1.9   xtraeme 	int			error = 0;
   1445       1.9   xtraeme 
   1446      1.10   xtraeme 	volinfo = kmem_zalloc(sizeof(*volinfo), KM_SLEEP);
   1447      1.10   xtraeme 	raidinfo = kmem_zalloc(sizeof(*raidinfo), KM_SLEEP);
   1448      1.10   xtraeme 	diskinfo = kmem_zalloc(sizeof(*diskinfo), KM_SLEEP);
   1449       1.1   xtraeme 
   1450       1.1   xtraeme 	error = arc_bio_getvol(sc, bd->bd_volid, volinfo);
   1451       1.1   xtraeme 	if (error != 0)
   1452       1.1   xtraeme 		goto out;
   1453       1.1   xtraeme 
   1454       1.1   xtraeme 	request[0] = ARC_FW_RAIDINFO;
   1455       1.1   xtraeme 	request[1] = volinfo->raid_set_number;
   1456       1.7   xtraeme 
   1457       1.1   xtraeme 	error = arc_msgbuf(sc, request, sizeof(request), raidinfo,
   1458       1.1   xtraeme 	    sizeof(struct arc_fw_raidinfo));
   1459       1.1   xtraeme 	if (error != 0)
   1460       1.1   xtraeme 		goto out;
   1461       1.1   xtraeme 
   1462      1.14   xtraeme 	if (bd->bd_diskid >= sc->sc_cchans ||
   1463      1.14   xtraeme 	    bd->bd_diskid >= raidinfo->member_devices) {
   1464       1.1   xtraeme 		error = ENODEV;
   1465       1.1   xtraeme 		goto out;
   1466       1.1   xtraeme 	}
   1467       1.1   xtraeme 
   1468      1.14   xtraeme 	if (raidinfo->device_array[bd->bd_diskid] == 0xff) {
   1469      1.14   xtraeme 		/*
   1470      1.14   xtraeme 		 * The disk has been disconnected, mark it offline
   1471      1.14   xtraeme 		 * and put it on another bus.
   1472      1.14   xtraeme 		 */
   1473      1.14   xtraeme 		bd->bd_channel = 1;
   1474      1.14   xtraeme 		bd->bd_target = 0;
   1475      1.14   xtraeme 		bd->bd_lun = 0;
   1476      1.14   xtraeme 		bd->bd_status = BIOC_SDOFFLINE;
   1477      1.14   xtraeme 		strlcpy(bd->bd_vendor, "disk missing", sizeof(bd->bd_vendor));
   1478      1.14   xtraeme 		goto out;
   1479      1.14   xtraeme 	}
   1480      1.14   xtraeme 
   1481       1.1   xtraeme 	request[0] = ARC_FW_DISKINFO;
   1482       1.1   xtraeme 	request[1] = raidinfo->device_array[bd->bd_diskid];
   1483       1.1   xtraeme 	error = arc_msgbuf(sc, request, sizeof(request), diskinfo,
   1484       1.1   xtraeme 	    sizeof(struct arc_fw_diskinfo));
   1485       1.1   xtraeme 	if (error != 0)
   1486       1.1   xtraeme 		goto out;
   1487       1.1   xtraeme 
   1488       1.9   xtraeme 	/* now fill our bio disk with data from the firmware */
   1489       1.9   xtraeme 	arc_bio_disk_filldata(sc, bd, diskinfo,
   1490       1.9   xtraeme 	    raidinfo->device_array[bd->bd_diskid]);
   1491       1.1   xtraeme 
   1492       1.1   xtraeme out:
   1493       1.7   xtraeme 	kmem_free(raidinfo, sizeof(*raidinfo));
   1494       1.7   xtraeme 	kmem_free(volinfo, sizeof(*volinfo));
   1495       1.9   xtraeme 	kmem_free(diskinfo, sizeof(*diskinfo));
   1496       1.1   xtraeme 	return error;
   1497       1.1   xtraeme }
   1498       1.1   xtraeme #endif /* NBIO > 0 */
   1499       1.1   xtraeme 
   1500       1.1   xtraeme uint8_t
   1501       1.1   xtraeme arc_msg_cksum(void *cmd, uint16_t len)
   1502       1.1   xtraeme {
   1503       1.1   xtraeme 	uint8_t	*buf = cmd;
   1504       1.1   xtraeme 	uint8_t	cksum;
   1505       1.1   xtraeme 	int	i;
   1506       1.1   xtraeme 
   1507       1.1   xtraeme 	cksum = (uint8_t)(len >> 8) + (uint8_t)len;
   1508       1.1   xtraeme 	for (i = 0; i < len; i++)
   1509       1.1   xtraeme 		cksum += buf[i];
   1510       1.1   xtraeme 
   1511       1.1   xtraeme 	return cksum;
   1512       1.1   xtraeme }
   1513       1.1   xtraeme 
   1514       1.1   xtraeme 
   1515       1.1   xtraeme int
   1516       1.1   xtraeme arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wbuflen, void *rptr,
   1517       1.1   xtraeme 	   size_t rbuflen)
   1518       1.1   xtraeme {
   1519       1.1   xtraeme 	uint8_t			rwbuf[ARC_REG_IOC_RWBUF_MAXLEN];
   1520       1.1   xtraeme 	uint8_t			*wbuf, *rbuf;
   1521       1.1   xtraeme 	int			wlen, wdone = 0, rlen, rdone = 0;
   1522       1.1   xtraeme 	struct arc_fw_bufhdr	*bufhdr;
   1523       1.1   xtraeme 	uint32_t		reg, rwlen;
   1524       1.1   xtraeme 	int			error = 0;
   1525       1.1   xtraeme #ifdef ARC_DEBUG
   1526       1.1   xtraeme 	int			i;
   1527       1.1   xtraeme #endif
   1528       1.1   xtraeme 
   1529       1.7   xtraeme 	wbuf = rbuf = NULL;
   1530       1.7   xtraeme 
   1531       1.1   xtraeme 	DNPRINTF(ARC_D_DB, "%s: arc_msgbuf wbuflen: %d rbuflen: %d\n",
   1532      1.19   xtraeme 	    device_xname(sc->sc_dev), wbuflen, rbuflen);
   1533       1.1   xtraeme 
   1534       1.1   xtraeme 	wlen = sizeof(struct arc_fw_bufhdr) + wbuflen + 1; /* 1 for cksum */
   1535       1.7   xtraeme 	wbuf = kmem_alloc(wlen, KM_SLEEP);
   1536       1.1   xtraeme 
   1537       1.1   xtraeme 	rlen = sizeof(struct arc_fw_bufhdr) + rbuflen + 1; /* 1 for cksum */
   1538       1.7   xtraeme 	rbuf = kmem_alloc(rlen, KM_SLEEP);
   1539       1.1   xtraeme 
   1540       1.1   xtraeme 	DNPRINTF(ARC_D_DB, "%s: arc_msgbuf wlen: %d rlen: %d\n",
   1541      1.19   xtraeme 	    device_xname(sc->sc_dev), wlen, rlen);
   1542       1.1   xtraeme 
   1543       1.1   xtraeme 	bufhdr = (struct arc_fw_bufhdr *)wbuf;
   1544       1.1   xtraeme 	bufhdr->hdr = arc_fw_hdr;
   1545       1.1   xtraeme 	bufhdr->len = htole16(wbuflen);
   1546       1.1   xtraeme 	memcpy(wbuf + sizeof(struct arc_fw_bufhdr), wptr, wbuflen);
   1547       1.1   xtraeme 	wbuf[wlen - 1] = arc_msg_cksum(wptr, wbuflen);
   1548       1.1   xtraeme 
   1549       1.7   xtraeme 	arc_lock(sc);
   1550       1.7   xtraeme 	if (arc_read(sc, ARC_REG_OUTB_DOORBELL) != 0) {
   1551       1.7   xtraeme 		error = EBUSY;
   1552       1.7   xtraeme 		goto out;
   1553       1.7   xtraeme 	}
   1554       1.7   xtraeme 
   1555       1.1   xtraeme 	reg = ARC_REG_OUTB_DOORBELL_READ_OK;
   1556       1.1   xtraeme 
   1557       1.1   xtraeme 	do {
   1558       1.1   xtraeme 		if ((reg & ARC_REG_OUTB_DOORBELL_READ_OK) && wdone < wlen) {
   1559       1.1   xtraeme 			memset(rwbuf, 0, sizeof(rwbuf));
   1560       1.1   xtraeme 			rwlen = (wlen - wdone) % sizeof(rwbuf);
   1561       1.1   xtraeme 			memcpy(rwbuf, &wbuf[wdone], rwlen);
   1562       1.1   xtraeme 
   1563       1.1   xtraeme #ifdef ARC_DEBUG
   1564       1.1   xtraeme 			if (arcdebug & ARC_D_DB) {
   1565       1.1   xtraeme 				printf("%s: write %d:",
   1566      1.19   xtraeme 				    device_xname(sc->sc_dev), rwlen);
   1567       1.1   xtraeme 				for (i = 0; i < rwlen; i++)
   1568       1.1   xtraeme 					printf(" 0x%02x", rwbuf[i]);
   1569       1.1   xtraeme 				printf("\n");
   1570       1.1   xtraeme 			}
   1571       1.1   xtraeme #endif
   1572       1.1   xtraeme 
   1573       1.1   xtraeme 			/* copy the chunk to the hw */
   1574       1.1   xtraeme 			arc_write(sc, ARC_REG_IOC_WBUF_LEN, rwlen);
   1575       1.1   xtraeme 			arc_write_region(sc, ARC_REG_IOC_WBUF, rwbuf,
   1576       1.1   xtraeme 			    sizeof(rwbuf));
   1577       1.1   xtraeme 
   1578       1.1   xtraeme 			/* say we have a buffer for the hw */
   1579       1.1   xtraeme 			arc_write(sc, ARC_REG_INB_DOORBELL,
   1580       1.1   xtraeme 			    ARC_REG_INB_DOORBELL_WRITE_OK);
   1581       1.1   xtraeme 
   1582       1.1   xtraeme 			wdone += rwlen;
   1583       1.1   xtraeme 		}
   1584       1.1   xtraeme 
   1585       1.1   xtraeme 		while ((reg = arc_read(sc, ARC_REG_OUTB_DOORBELL)) == 0)
   1586       1.1   xtraeme 			arc_wait(sc);
   1587       1.9   xtraeme 
   1588       1.1   xtraeme 		arc_write(sc, ARC_REG_OUTB_DOORBELL, reg);
   1589       1.1   xtraeme 
   1590       1.1   xtraeme 		DNPRINTF(ARC_D_DB, "%s: reg: 0x%08x\n",
   1591      1.19   xtraeme 		    device_xname(sc->sc_dev), reg);
   1592       1.1   xtraeme 
   1593       1.1   xtraeme 		if ((reg & ARC_REG_OUTB_DOORBELL_WRITE_OK) && rdone < rlen) {
   1594       1.1   xtraeme 			rwlen = arc_read(sc, ARC_REG_IOC_RBUF_LEN);
   1595       1.1   xtraeme 			if (rwlen > sizeof(rwbuf)) {
   1596       1.1   xtraeme 				DNPRINTF(ARC_D_DB, "%s:  rwlen too big\n",
   1597      1.19   xtraeme 				    device_xname(sc->sc_dev));
   1598       1.1   xtraeme 				error = EIO;
   1599       1.1   xtraeme 				goto out;
   1600       1.1   xtraeme 			}
   1601       1.1   xtraeme 
   1602       1.1   xtraeme 			arc_read_region(sc, ARC_REG_IOC_RBUF, rwbuf,
   1603       1.1   xtraeme 			    sizeof(rwbuf));
   1604       1.1   xtraeme 
   1605       1.1   xtraeme 			arc_write(sc, ARC_REG_INB_DOORBELL,
   1606       1.1   xtraeme 			    ARC_REG_INB_DOORBELL_READ_OK);
   1607       1.1   xtraeme 
   1608       1.1   xtraeme #ifdef ARC_DEBUG
   1609       1.1   xtraeme 			printf("%s:  len: %d+%d=%d/%d\n",
   1610      1.19   xtraeme 			    device_xname(sc->sc_dev),
   1611       1.1   xtraeme 			    rwlen, rdone, rwlen + rdone, rlen);
   1612       1.1   xtraeme 			if (arcdebug & ARC_D_DB) {
   1613       1.1   xtraeme 				printf("%s: read:",
   1614      1.19   xtraeme 				    device_xname(sc->sc_dev));
   1615       1.1   xtraeme 				for (i = 0; i < rwlen; i++)
   1616       1.1   xtraeme 					printf(" 0x%02x", rwbuf[i]);
   1617       1.1   xtraeme 				printf("\n");
   1618       1.1   xtraeme 			}
   1619       1.1   xtraeme #endif
   1620       1.1   xtraeme 
   1621       1.1   xtraeme 			if ((rdone + rwlen) > rlen) {
   1622       1.1   xtraeme 				DNPRINTF(ARC_D_DB, "%s:  rwbuf too big\n",
   1623      1.19   xtraeme 				    device_xname(sc->sc_dev));
   1624       1.1   xtraeme 				error = EIO;
   1625       1.1   xtraeme 				goto out;
   1626       1.1   xtraeme 			}
   1627       1.1   xtraeme 
   1628       1.1   xtraeme 			memcpy(&rbuf[rdone], rwbuf, rwlen);
   1629       1.1   xtraeme 			rdone += rwlen;
   1630       1.1   xtraeme 		}
   1631       1.1   xtraeme 	} while (rdone != rlen);
   1632       1.1   xtraeme 
   1633       1.1   xtraeme 	bufhdr = (struct arc_fw_bufhdr *)rbuf;
   1634       1.1   xtraeme 	if (memcmp(&bufhdr->hdr, &arc_fw_hdr, sizeof(bufhdr->hdr)) != 0 ||
   1635       1.1   xtraeme 	    bufhdr->len != htole16(rbuflen)) {
   1636       1.1   xtraeme 		DNPRINTF(ARC_D_DB, "%s:  rbuf hdr is wrong\n",
   1637      1.19   xtraeme 		    device_xname(sc->sc_dev));
   1638       1.1   xtraeme 		error = EIO;
   1639       1.1   xtraeme 		goto out;
   1640       1.1   xtraeme 	}
   1641       1.1   xtraeme 
   1642       1.1   xtraeme 	memcpy(rptr, rbuf + sizeof(struct arc_fw_bufhdr), rbuflen);
   1643       1.1   xtraeme 
   1644       1.1   xtraeme 	if (rbuf[rlen - 1] != arc_msg_cksum(rptr, rbuflen)) {
   1645       1.1   xtraeme 		DNPRINTF(ARC_D_DB, "%s:  invalid cksum\n",
   1646      1.19   xtraeme 		    device_xname(sc->sc_dev));
   1647       1.1   xtraeme 		error = EIO;
   1648       1.1   xtraeme 		goto out;
   1649       1.1   xtraeme 	}
   1650       1.1   xtraeme 
   1651       1.1   xtraeme out:
   1652       1.7   xtraeme 	arc_unlock(sc);
   1653       1.7   xtraeme 	kmem_free(wbuf, wlen);
   1654       1.7   xtraeme 	kmem_free(rbuf, rlen);
   1655       1.1   xtraeme 
   1656       1.1   xtraeme 	return error;
   1657       1.1   xtraeme }
   1658       1.1   xtraeme 
   1659       1.1   xtraeme void
   1660       1.1   xtraeme arc_lock(struct arc_softc *sc)
   1661       1.5   xtraeme {
   1662       1.5   xtraeme 	rw_enter(&sc->sc_rwlock, RW_WRITER);
   1663       1.7   xtraeme 	mutex_spin_enter(&sc->sc_mutex);
   1664       1.1   xtraeme 	arc_write(sc, ARC_REG_INTRMASK, ~ARC_REG_INTRMASK_POSTQUEUE);
   1665       1.1   xtraeme 	sc->sc_talking = 1;
   1666       1.1   xtraeme }
   1667       1.1   xtraeme 
   1668       1.1   xtraeme void
   1669       1.1   xtraeme arc_unlock(struct arc_softc *sc)
   1670       1.1   xtraeme {
   1671       1.3   xtraeme 	KASSERT(mutex_owned(&sc->sc_mutex));
   1672       1.1   xtraeme 
   1673       1.1   xtraeme 	arc_write(sc, ARC_REG_INTRMASK,
   1674       1.1   xtraeme 	    ~(ARC_REG_INTRMASK_POSTQUEUE|ARC_REG_INTRMASK_DOORBELL));
   1675       1.9   xtraeme 	sc->sc_talking = 0;
   1676       1.7   xtraeme 	mutex_spin_exit(&sc->sc_mutex);
   1677       1.5   xtraeme 	rw_exit(&sc->sc_rwlock);
   1678       1.1   xtraeme }
   1679       1.1   xtraeme 
   1680       1.1   xtraeme void
   1681       1.1   xtraeme arc_wait(struct arc_softc *sc)
   1682       1.1   xtraeme {
   1683       1.3   xtraeme 	KASSERT(mutex_owned(&sc->sc_mutex));
   1684       1.1   xtraeme 
   1685       1.1   xtraeme 	arc_write(sc, ARC_REG_INTRMASK,
   1686       1.1   xtraeme 	    ~(ARC_REG_INTRMASK_POSTQUEUE|ARC_REG_INTRMASK_DOORBELL));
   1687       1.9   xtraeme 	if (cv_timedwait(&sc->sc_condvar, &sc->sc_mutex, hz) == EWOULDBLOCK)
   1688       1.1   xtraeme 		arc_write(sc, ARC_REG_INTRMASK, ~ARC_REG_INTRMASK_POSTQUEUE);
   1689       1.1   xtraeme }
   1690       1.1   xtraeme 
   1691       1.1   xtraeme #if NBIO > 0
   1692       1.1   xtraeme static void
   1693       1.1   xtraeme arc_create_sensors(void *arg)
   1694       1.1   xtraeme {
   1695       1.1   xtraeme 	struct arc_softc	*sc = arg;
   1696       1.1   xtraeme 	struct bioc_inq		bi;
   1697       1.1   xtraeme 	struct bioc_vol		bv;
   1698      1.10   xtraeme 	int			i, j;
   1699      1.10   xtraeme 	size_t			slen, count = 0;
   1700       1.1   xtraeme 
   1701       1.1   xtraeme 	memset(&bi, 0, sizeof(bi));
   1702       1.1   xtraeme 	if (arc_bio_inq(sc, &bi) != 0) {
   1703       1.1   xtraeme 		aprint_error("%s: unable to query firmware for sensor info\n",
   1704      1.19   xtraeme 		    device_xname(sc->sc_dev));
   1705       1.1   xtraeme 		kthread_exit(0);
   1706       1.1   xtraeme 	}
   1707       1.1   xtraeme 
   1708      1.10   xtraeme 	/* There's no point to continue if there are no volumes */
   1709      1.10   xtraeme 	if (!bi.bi_novol)
   1710       1.1   xtraeme 		kthread_exit(0);
   1711       1.1   xtraeme 
   1712      1.10   xtraeme 	for (i = 0; i < bi.bi_novol; i++) {
   1713      1.10   xtraeme 		memset(&bv, 0, sizeof(bv));
   1714      1.10   xtraeme 		bv.bv_volid = i;
   1715      1.10   xtraeme 		if (arc_bio_vol(sc, &bv) != 0)
   1716      1.10   xtraeme 			kthread_exit(0);
   1717      1.10   xtraeme 
   1718      1.10   xtraeme 		/* Skip passthrough volumes */
   1719      1.10   xtraeme 		if (bv.bv_level == BIOC_SVOL_PASSTHRU)
   1720      1.10   xtraeme 			continue;
   1721      1.10   xtraeme 
   1722      1.10   xtraeme 		/* new volume found */
   1723      1.10   xtraeme 		sc->sc_nsensors++;
   1724      1.10   xtraeme 		/* new disk in a volume found */
   1725      1.10   xtraeme 		sc->sc_nsensors+= bv.bv_nodisk;
   1726      1.10   xtraeme 	}
   1727      1.10   xtraeme 
   1728      1.16   xtraeme 	/* No valid volumes */
   1729      1.16   xtraeme 	if (!sc->sc_nsensors)
   1730      1.16   xtraeme 		kthread_exit(0);
   1731      1.16   xtraeme 
   1732       1.1   xtraeme 	sc->sc_sme = sysmon_envsys_create();
   1733       1.7   xtraeme 	slen = sizeof(envsys_data_t) * sc->sc_nsensors;
   1734       1.7   xtraeme 	sc->sc_sensors = kmem_zalloc(slen, KM_SLEEP);
   1735       1.1   xtraeme 
   1736      1.10   xtraeme 	/* Attach sensors for volumes and disks */
   1737      1.10   xtraeme 	for (i = 0; i < bi.bi_novol; i++) {
   1738       1.1   xtraeme 		memset(&bv, 0, sizeof(bv));
   1739       1.1   xtraeme 		bv.bv_volid = i;
   1740       1.1   xtraeme 		if (arc_bio_vol(sc, &bv) != 0)
   1741       1.1   xtraeme 			goto bad;
   1742       1.1   xtraeme 
   1743      1.10   xtraeme 		sc->sc_sensors[count].units = ENVSYS_DRIVE;
   1744      1.10   xtraeme 		sc->sc_sensors[count].monitor = true;
   1745      1.10   xtraeme 		sc->sc_sensors[count].flags = ENVSYS_FMONSTCHANGED;
   1746      1.10   xtraeme 
   1747      1.10   xtraeme 		/* Skip passthrough volumes */
   1748      1.10   xtraeme 		if (bv.bv_level == BIOC_SVOL_PASSTHRU)
   1749      1.10   xtraeme 			continue;
   1750      1.10   xtraeme 
   1751      1.18   xtraeme 		if (bv.bv_level == BIOC_SVOL_RAID10)
   1752      1.18   xtraeme 			snprintf(sc->sc_sensors[count].desc,
   1753      1.18   xtraeme 			    sizeof(sc->sc_sensors[count].desc),
   1754      1.18   xtraeme 			    "RAID 1+0 volume%d (%s)", i, bv.bv_dev);
   1755      1.18   xtraeme 		else
   1756      1.18   xtraeme 			snprintf(sc->sc_sensors[count].desc,
   1757      1.18   xtraeme 			    sizeof(sc->sc_sensors[count].desc),
   1758      1.18   xtraeme 			    "RAID %d volume%d (%s)", bv.bv_level, i,
   1759      1.18   xtraeme 			    bv.bv_dev);
   1760      1.18   xtraeme 
   1761      1.10   xtraeme 		sc->sc_sensors[count].value_max = i;
   1762      1.10   xtraeme 
   1763      1.10   xtraeme 		if (sysmon_envsys_sensor_attach(sc->sc_sme,
   1764      1.10   xtraeme 		    &sc->sc_sensors[count]))
   1765       1.1   xtraeme 			goto bad;
   1766      1.10   xtraeme 
   1767      1.10   xtraeme 		count++;
   1768      1.10   xtraeme 
   1769      1.10   xtraeme 		/* Attach disk sensors for this volume */
   1770      1.10   xtraeme 		for (j = 0; j < bv.bv_nodisk; j++) {
   1771      1.10   xtraeme 			sc->sc_sensors[count].units = ENVSYS_DRIVE;
   1772      1.10   xtraeme 			sc->sc_sensors[count].monitor = true;
   1773      1.10   xtraeme 			sc->sc_sensors[count].flags = ENVSYS_FMONSTCHANGED;
   1774      1.10   xtraeme 
   1775      1.10   xtraeme 			snprintf(sc->sc_sensors[count].desc,
   1776      1.10   xtraeme 			    sizeof(sc->sc_sensors[count].desc),
   1777      1.10   xtraeme 			    "disk%d volume%d (%s)", j, i, bv.bv_dev);
   1778      1.10   xtraeme 			sc->sc_sensors[count].value_max = i;
   1779      1.10   xtraeme 			sc->sc_sensors[count].value_avg = j + 10;
   1780      1.10   xtraeme 
   1781      1.10   xtraeme 			if (sysmon_envsys_sensor_attach(sc->sc_sme,
   1782      1.10   xtraeme 			    &sc->sc_sensors[count]))
   1783      1.10   xtraeme 				goto bad;
   1784      1.10   xtraeme 
   1785      1.10   xtraeme 			count++;
   1786      1.10   xtraeme 		}
   1787       1.1   xtraeme 	}
   1788       1.1   xtraeme 
   1789      1.10   xtraeme 	/*
   1790      1.10   xtraeme 	 * Register our envsys driver with the framework now that the
   1791      1.10   xtraeme 	 * sensors were all attached.
   1792      1.10   xtraeme 	 */
   1793      1.19   xtraeme 	sc->sc_sme->sme_name = device_xname(sc->sc_dev);
   1794       1.2   xtraeme 	sc->sc_sme->sme_cookie = sc;
   1795       1.2   xtraeme 	sc->sc_sme->sme_refresh = arc_refresh_sensors;
   1796      1.10   xtraeme 
   1797       1.1   xtraeme 	if (sysmon_envsys_register(sc->sc_sme)) {
   1798       1.1   xtraeme 		aprint_debug("%s: unable to register with sysmon\n",
   1799      1.19   xtraeme 		    device_xname(sc->sc_dev));
   1800       1.1   xtraeme 		goto bad;
   1801       1.1   xtraeme 	}
   1802       1.1   xtraeme 	kthread_exit(0);
   1803       1.1   xtraeme 
   1804       1.1   xtraeme bad:
   1805       1.7   xtraeme 	kmem_free(sc->sc_sensors, slen);
   1806       1.1   xtraeme 	sysmon_envsys_destroy(sc->sc_sme);
   1807       1.1   xtraeme 	kthread_exit(0);
   1808       1.1   xtraeme }
   1809       1.1   xtraeme 
   1810       1.1   xtraeme static void
   1811       1.2   xtraeme arc_refresh_sensors(struct sysmon_envsys *sme, envsys_data_t *edata)
   1812       1.1   xtraeme {
   1813       1.2   xtraeme 	struct arc_softc	*sc = sme->sme_cookie;
   1814       1.1   xtraeme 	struct bioc_vol		bv;
   1815      1.10   xtraeme 	struct bioc_disk	bd;
   1816      1.10   xtraeme 
   1817      1.10   xtraeme 	/* sanity check */
   1818      1.10   xtraeme 	if (edata->units != ENVSYS_DRIVE)
   1819      1.10   xtraeme 		return;
   1820       1.1   xtraeme 
   1821       1.1   xtraeme 	memset(&bv, 0, sizeof(bv));
   1822      1.10   xtraeme 	bv.bv_volid = edata->value_max;
   1823       1.2   xtraeme 
   1824       1.2   xtraeme 	if (arc_bio_vol(sc, &bv)) {
   1825       1.2   xtraeme 		edata->value_cur = ENVSYS_DRIVE_EMPTY;
   1826       1.2   xtraeme 		edata->state = ENVSYS_SINVALID;
   1827       1.2   xtraeme 		return;
   1828       1.2   xtraeme 	}
   1829       1.1   xtraeme 
   1830      1.10   xtraeme 	/* Current sensor is handling a disk volume member */
   1831      1.10   xtraeme 	if (edata->value_avg) {
   1832      1.10   xtraeme 		memset(&bd, 0, sizeof(bd));
   1833      1.10   xtraeme 		bd.bd_volid = edata->value_max;
   1834      1.10   xtraeme 		bd.bd_diskid = edata->value_avg - 10;
   1835      1.10   xtraeme 
   1836      1.10   xtraeme 		if (arc_bio_disk_volume(sc, &bd)) {
   1837      1.14   xtraeme 			edata->value_cur = ENVSYS_DRIVE_OFFLINE;
   1838      1.14   xtraeme 			edata->state = ENVSYS_SCRITICAL;
   1839      1.10   xtraeme 			return;
   1840      1.10   xtraeme 		}
   1841      1.10   xtraeme 
   1842      1.10   xtraeme 		switch (bd.bd_status) {
   1843      1.10   xtraeme 		case BIOC_SDONLINE:
   1844      1.10   xtraeme 			edata->value_cur = ENVSYS_DRIVE_ONLINE;
   1845      1.10   xtraeme 			edata->state = ENVSYS_SVALID;
   1846      1.10   xtraeme 			break;
   1847      1.10   xtraeme 		case BIOC_SDOFFLINE:
   1848      1.10   xtraeme 			edata->value_cur = ENVSYS_DRIVE_OFFLINE;
   1849      1.10   xtraeme 			edata->state = ENVSYS_SCRITICAL;
   1850      1.10   xtraeme 			break;
   1851      1.10   xtraeme 		default:
   1852      1.14   xtraeme 			edata->value_cur = ENVSYS_DRIVE_FAIL;
   1853      1.10   xtraeme 			edata->state = ENVSYS_SCRITICAL;
   1854      1.10   xtraeme 			break;
   1855      1.10   xtraeme 		}
   1856      1.10   xtraeme 
   1857      1.10   xtraeme 		return;
   1858      1.10   xtraeme 	}
   1859      1.10   xtraeme 
   1860      1.10   xtraeme 	/* Current sensor is handling a volume */
   1861       1.2   xtraeme 	switch (bv.bv_status) {
   1862       1.2   xtraeme 	case BIOC_SVOFFLINE:
   1863      1.17   xtraeme 		edata->value_cur = ENVSYS_DRIVE_OFFLINE;
   1864       1.2   xtraeme 		edata->state = ENVSYS_SCRITICAL;
   1865       1.2   xtraeme 		break;
   1866       1.2   xtraeme 	case BIOC_SVDEGRADED:
   1867       1.2   xtraeme 		edata->value_cur = ENVSYS_DRIVE_PFAIL;
   1868       1.2   xtraeme 		edata->state = ENVSYS_SCRITICAL;
   1869       1.2   xtraeme 		break;
   1870       1.2   xtraeme 	case BIOC_SVBUILDING:
   1871      1.10   xtraeme 		edata->value_cur = ENVSYS_DRIVE_BUILD;
   1872       1.2   xtraeme 		edata->state = ENVSYS_SVALID;
   1873       1.2   xtraeme 		break;
   1874       1.8   xtraeme 	case BIOC_SVMIGRATING:
   1875       1.8   xtraeme 		edata->value_cur = ENVSYS_DRIVE_MIGRATING;
   1876       1.8   xtraeme 		edata->state = ENVSYS_SVALID;
   1877       1.8   xtraeme 		break;
   1878      1.10   xtraeme 	case BIOC_SVCHECKING:
   1879      1.10   xtraeme 		edata->value_cur = ENVSYS_DRIVE_CHECK;
   1880      1.10   xtraeme 		edata->state = ENVSYS_SVALID;
   1881      1.10   xtraeme 		break;
   1882      1.13   xtraeme 	case BIOC_SVREBUILD:
   1883      1.13   xtraeme 		edata->value_cur = ENVSYS_DRIVE_REBUILD;
   1884      1.13   xtraeme 		edata->state = ENVSYS_SCRITICAL;
   1885      1.13   xtraeme 		break;
   1886       1.2   xtraeme 	case BIOC_SVSCRUB:
   1887       1.2   xtraeme 	case BIOC_SVONLINE:
   1888       1.2   xtraeme 		edata->value_cur = ENVSYS_DRIVE_ONLINE;
   1889       1.2   xtraeme 		edata->state = ENVSYS_SVALID;
   1890       1.2   xtraeme 		break;
   1891       1.2   xtraeme 	case BIOC_SVINVALID:
   1892      1.10   xtraeme 		/* FALLTHROUGH */
   1893       1.2   xtraeme 	default:
   1894       1.2   xtraeme 		edata->value_cur = ENVSYS_DRIVE_EMPTY; /* unknown state */
   1895       1.2   xtraeme 		edata->state = ENVSYS_SINVALID;
   1896       1.2   xtraeme 		break;
   1897       1.1   xtraeme 	}
   1898       1.1   xtraeme }
   1899       1.1   xtraeme #endif /* NBIO > 0 */
   1900       1.1   xtraeme 
   1901       1.1   xtraeme uint32_t
   1902       1.1   xtraeme arc_read(struct arc_softc *sc, bus_size_t r)
   1903       1.1   xtraeme {
   1904       1.1   xtraeme 	uint32_t			v;
   1905       1.1   xtraeme 
   1906       1.1   xtraeme 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
   1907       1.1   xtraeme 	    BUS_SPACE_BARRIER_READ);
   1908       1.1   xtraeme 	v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
   1909       1.1   xtraeme 
   1910       1.1   xtraeme 	DNPRINTF(ARC_D_RW, "%s: arc_read 0x%lx 0x%08x\n",
   1911      1.19   xtraeme 	    device_xname(sc->sc_dev), r, v);
   1912       1.1   xtraeme 
   1913       1.1   xtraeme 	return v;
   1914       1.1   xtraeme }
   1915       1.1   xtraeme 
   1916       1.1   xtraeme void
   1917       1.1   xtraeme arc_read_region(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
   1918       1.1   xtraeme {
   1919       1.1   xtraeme 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, len,
   1920       1.1   xtraeme 	    BUS_SPACE_BARRIER_READ);
   1921       1.1   xtraeme 	bus_space_read_region_4(sc->sc_iot, sc->sc_ioh, r,
   1922       1.1   xtraeme 	    (uint32_t *)buf, len >> 2);
   1923       1.1   xtraeme }
   1924       1.1   xtraeme 
   1925       1.1   xtraeme void
   1926       1.1   xtraeme arc_write(struct arc_softc *sc, bus_size_t r, uint32_t v)
   1927       1.1   xtraeme {
   1928       1.1   xtraeme 	DNPRINTF(ARC_D_RW, "%s: arc_write 0x%lx 0x%08x\n",
   1929      1.19   xtraeme 	    device_xname(sc->sc_dev), r, v);
   1930       1.1   xtraeme 
   1931       1.1   xtraeme 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
   1932       1.1   xtraeme 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
   1933       1.1   xtraeme 	    BUS_SPACE_BARRIER_WRITE);
   1934       1.1   xtraeme }
   1935       1.1   xtraeme 
   1936       1.1   xtraeme void
   1937       1.1   xtraeme arc_write_region(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
   1938       1.1   xtraeme {
   1939       1.1   xtraeme 	bus_space_write_region_4(sc->sc_iot, sc->sc_ioh, r,
   1940       1.1   xtraeme 	    (const uint32_t *)buf, len >> 2);
   1941       1.1   xtraeme 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, len,
   1942       1.1   xtraeme 	    BUS_SPACE_BARRIER_WRITE);
   1943       1.1   xtraeme }
   1944       1.1   xtraeme 
   1945       1.1   xtraeme int
   1946       1.1   xtraeme arc_wait_eq(struct arc_softc *sc, bus_size_t r, uint32_t mask,
   1947       1.1   xtraeme 	    uint32_t target)
   1948       1.1   xtraeme {
   1949       1.1   xtraeme 	int i;
   1950       1.1   xtraeme 
   1951       1.1   xtraeme 	DNPRINTF(ARC_D_RW, "%s: arc_wait_eq 0x%lx 0x%08x 0x%08x\n",
   1952      1.19   xtraeme 	    device_xname(sc->sc_dev), r, mask, target);
   1953       1.1   xtraeme 
   1954       1.1   xtraeme 	for (i = 0; i < 10000; i++) {
   1955       1.1   xtraeme 		if ((arc_read(sc, r) & mask) == target)
   1956       1.1   xtraeme 			return 0;
   1957       1.1   xtraeme 		delay(1000);
   1958       1.1   xtraeme 	}
   1959       1.1   xtraeme 
   1960       1.1   xtraeme 	return 1;
   1961       1.1   xtraeme }
   1962       1.1   xtraeme 
   1963       1.1   xtraeme int
   1964       1.1   xtraeme arc_wait_ne(struct arc_softc *sc, bus_size_t r, uint32_t mask,
   1965       1.1   xtraeme 	    uint32_t target)
   1966       1.1   xtraeme {
   1967       1.1   xtraeme 	int i;
   1968       1.1   xtraeme 
   1969       1.1   xtraeme 	DNPRINTF(ARC_D_RW, "%s: arc_wait_ne 0x%lx 0x%08x 0x%08x\n",
   1970      1.19   xtraeme 	    device_xname(sc->sc_dev), r, mask, target);
   1971       1.1   xtraeme 
   1972       1.1   xtraeme 	for (i = 0; i < 10000; i++) {
   1973       1.1   xtraeme 		if ((arc_read(sc, r) & mask) != target)
   1974       1.1   xtraeme 			return 0;
   1975       1.1   xtraeme 		delay(1000);
   1976       1.1   xtraeme 	}
   1977       1.1   xtraeme 
   1978       1.1   xtraeme 	return 1;
   1979       1.1   xtraeme }
   1980       1.1   xtraeme 
   1981       1.1   xtraeme int
   1982       1.1   xtraeme arc_msg0(struct arc_softc *sc, uint32_t m)
   1983       1.1   xtraeme {
   1984       1.1   xtraeme 	/* post message */
   1985       1.1   xtraeme 	arc_write(sc, ARC_REG_INB_MSG0, m);
   1986       1.1   xtraeme 	/* wait for the fw to do it */
   1987       1.1   xtraeme 	if (arc_wait_eq(sc, ARC_REG_INTRSTAT, ARC_REG_INTRSTAT_MSG0,
   1988       1.1   xtraeme 	    ARC_REG_INTRSTAT_MSG0) != 0)
   1989       1.1   xtraeme 		return 1;
   1990       1.1   xtraeme 
   1991       1.1   xtraeme 	/* ack it */
   1992       1.1   xtraeme 	arc_write(sc, ARC_REG_INTRSTAT, ARC_REG_INTRSTAT_MSG0);
   1993       1.1   xtraeme 
   1994       1.1   xtraeme 	return 0;
   1995       1.1   xtraeme }
   1996       1.1   xtraeme 
   1997       1.1   xtraeme struct arc_dmamem *
   1998       1.1   xtraeme arc_dmamem_alloc(struct arc_softc *sc, size_t size)
   1999       1.1   xtraeme {
   2000       1.1   xtraeme 	struct arc_dmamem		*adm;
   2001       1.1   xtraeme 	int				nsegs;
   2002       1.1   xtraeme 
   2003       1.7   xtraeme 	adm = kmem_zalloc(sizeof(*adm), KM_NOSLEEP);
   2004       1.1   xtraeme 	if (adm == NULL)
   2005       1.1   xtraeme 		return NULL;
   2006       1.1   xtraeme 
   2007       1.1   xtraeme 	adm->adm_size = size;
   2008       1.1   xtraeme 
   2009       1.1   xtraeme 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
   2010       1.1   xtraeme 	    BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &adm->adm_map) != 0)
   2011       1.1   xtraeme 		goto admfree;
   2012       1.1   xtraeme 
   2013       1.1   xtraeme 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &adm->adm_seg,
   2014       1.1   xtraeme 	    1, &nsegs, BUS_DMA_NOWAIT) != 0)
   2015       1.1   xtraeme 		goto destroy;
   2016       1.1   xtraeme 
   2017       1.1   xtraeme 	if (bus_dmamem_map(sc->sc_dmat, &adm->adm_seg, nsegs, size,
   2018       1.1   xtraeme 	    &adm->adm_kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT) != 0)
   2019       1.1   xtraeme 		goto free;
   2020       1.1   xtraeme 
   2021       1.1   xtraeme 	if (bus_dmamap_load(sc->sc_dmat, adm->adm_map, adm->adm_kva, size,
   2022       1.1   xtraeme 	    NULL, BUS_DMA_NOWAIT) != 0)
   2023       1.1   xtraeme 		goto unmap;
   2024       1.1   xtraeme 
   2025       1.1   xtraeme 	memset(adm->adm_kva, 0, size);
   2026       1.1   xtraeme 
   2027       1.1   xtraeme 	return adm;
   2028       1.1   xtraeme 
   2029       1.1   xtraeme unmap:
   2030       1.1   xtraeme 	bus_dmamem_unmap(sc->sc_dmat, adm->adm_kva, size);
   2031       1.1   xtraeme free:
   2032       1.1   xtraeme 	bus_dmamem_free(sc->sc_dmat, &adm->adm_seg, 1);
   2033       1.1   xtraeme destroy:
   2034       1.1   xtraeme 	bus_dmamap_destroy(sc->sc_dmat, adm->adm_map);
   2035       1.1   xtraeme admfree:
   2036       1.7   xtraeme 	kmem_free(adm, sizeof(*adm));
   2037       1.1   xtraeme 
   2038       1.1   xtraeme 	return NULL;
   2039       1.1   xtraeme }
   2040       1.1   xtraeme 
   2041       1.1   xtraeme void
   2042       1.1   xtraeme arc_dmamem_free(struct arc_softc *sc, struct arc_dmamem *adm)
   2043       1.1   xtraeme {
   2044       1.1   xtraeme 	bus_dmamap_unload(sc->sc_dmat, adm->adm_map);
   2045       1.1   xtraeme 	bus_dmamem_unmap(sc->sc_dmat, adm->adm_kva, adm->adm_size);
   2046       1.1   xtraeme 	bus_dmamem_free(sc->sc_dmat, &adm->adm_seg, 1);
   2047       1.1   xtraeme 	bus_dmamap_destroy(sc->sc_dmat, adm->adm_map);
   2048       1.7   xtraeme 	kmem_free(adm, sizeof(*adm));
   2049       1.1   xtraeme }
   2050       1.1   xtraeme 
   2051       1.1   xtraeme int
   2052      1.19   xtraeme arc_alloc_ccbs(device_t self)
   2053       1.1   xtraeme {
   2054      1.19   xtraeme 	struct arc_softc 	*sc = device_private(self);
   2055       1.1   xtraeme 	struct arc_ccb		*ccb;
   2056       1.1   xtraeme 	uint8_t			*cmd;
   2057       1.1   xtraeme 	int			i;
   2058       1.7   xtraeme 	size_t			ccbslen;
   2059       1.1   xtraeme 
   2060       1.1   xtraeme 	TAILQ_INIT(&sc->sc_ccb_free);
   2061       1.1   xtraeme 
   2062       1.7   xtraeme 	ccbslen = sizeof(struct arc_ccb) * sc->sc_req_count;
   2063       1.7   xtraeme 	sc->sc_ccbs = kmem_zalloc(ccbslen, KM_SLEEP);
   2064       1.1   xtraeme 
   2065       1.1   xtraeme 	sc->sc_requests = arc_dmamem_alloc(sc,
   2066       1.1   xtraeme 	    ARC_MAX_IOCMDLEN * sc->sc_req_count);
   2067       1.1   xtraeme 	if (sc->sc_requests == NULL) {
   2068      1.19   xtraeme 		aprint_error_dev(self, "unable to allocate ccb dmamem\n");
   2069       1.1   xtraeme 		goto free_ccbs;
   2070       1.1   xtraeme 	}
   2071       1.1   xtraeme 	cmd = ARC_DMA_KVA(sc->sc_requests);
   2072       1.1   xtraeme 
   2073       1.1   xtraeme 	for (i = 0; i < sc->sc_req_count; i++) {
   2074       1.1   xtraeme 		ccb = &sc->sc_ccbs[i];
   2075       1.1   xtraeme 
   2076       1.1   xtraeme 		if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, ARC_SGL_MAXLEN,
   2077       1.1   xtraeme 		    MAXPHYS, 0, 0, &ccb->ccb_dmamap) != 0) {
   2078      1.19   xtraeme 			aprint_error_dev(self,
   2079      1.19   xtraeme 			    "unable to create dmamap for ccb %d\n", i);
   2080       1.1   xtraeme 			goto free_maps;
   2081       1.1   xtraeme 		}
   2082       1.1   xtraeme 
   2083       1.1   xtraeme 		ccb->ccb_sc = sc;
   2084       1.1   xtraeme 		ccb->ccb_id = i;
   2085       1.1   xtraeme 		ccb->ccb_offset = ARC_MAX_IOCMDLEN * i;
   2086       1.1   xtraeme 
   2087       1.1   xtraeme 		ccb->ccb_cmd = (struct arc_io_cmd *)&cmd[ccb->ccb_offset];
   2088       1.1   xtraeme 		ccb->ccb_cmd_post = (ARC_DMA_DVA(sc->sc_requests) +
   2089       1.1   xtraeme 		    ccb->ccb_offset) >> ARC_REG_POST_QUEUE_ADDR_SHIFT;
   2090       1.1   xtraeme 
   2091       1.1   xtraeme 		arc_put_ccb(sc, ccb);
   2092       1.1   xtraeme 	}
   2093       1.1   xtraeme 
   2094       1.1   xtraeme 	return 0;
   2095       1.1   xtraeme 
   2096       1.1   xtraeme free_maps:
   2097       1.1   xtraeme 	while ((ccb = arc_get_ccb(sc)) != NULL)
   2098       1.1   xtraeme 	    bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
   2099       1.1   xtraeme 	arc_dmamem_free(sc, sc->sc_requests);
   2100       1.1   xtraeme 
   2101       1.1   xtraeme free_ccbs:
   2102       1.7   xtraeme 	kmem_free(sc->sc_ccbs, ccbslen);
   2103       1.1   xtraeme 
   2104       1.1   xtraeme 	return 1;
   2105       1.1   xtraeme }
   2106       1.1   xtraeme 
   2107       1.1   xtraeme struct arc_ccb *
   2108       1.1   xtraeme arc_get_ccb(struct arc_softc *sc)
   2109       1.1   xtraeme {
   2110       1.1   xtraeme 	struct arc_ccb			*ccb;
   2111       1.1   xtraeme 
   2112       1.1   xtraeme 	ccb = TAILQ_FIRST(&sc->sc_ccb_free);
   2113       1.1   xtraeme 	if (ccb != NULL)
   2114       1.1   xtraeme 		TAILQ_REMOVE(&sc->sc_ccb_free, ccb, ccb_link);
   2115       1.3   xtraeme 
   2116       1.1   xtraeme 	return ccb;
   2117       1.1   xtraeme }
   2118       1.1   xtraeme 
   2119       1.1   xtraeme void
   2120       1.1   xtraeme arc_put_ccb(struct arc_softc *sc, struct arc_ccb *ccb)
   2121       1.1   xtraeme {
   2122       1.1   xtraeme 	ccb->ccb_xs = NULL;
   2123       1.1   xtraeme 	memset(ccb->ccb_cmd, 0, ARC_MAX_IOCMDLEN);
   2124       1.1   xtraeme 	TAILQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_link);
   2125       1.1   xtraeme }
   2126