Home | History | Annotate | Line # | Download | only in ic
ciss.c revision 1.6
      1 /*	$NetBSD: ciss.c,v 1.6 2006/11/16 01:32:51 christos Exp $	*/
      2 /*	$OpenBSD: ciss.c,v 1.14 2006/03/13 16:02:23 mickey Exp $	*/
      3 
      4 /*
      5  * Copyright (c) 2005 Michael Shalayeff
      6  * All rights reserved.
      7  *
      8  * Permission to use, copy, modify, and distribute this software for any
      9  * purpose with or without fee is hereby granted, provided that the above
     10  * copyright notice and this permission notice appear in all copies.
     11  *
     12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     16  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
     17  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     18  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     19  */
     20 
     21 #include <sys/cdefs.h>
     22 __KERNEL_RCSID(0, "$NetBSD: ciss.c,v 1.6 2006/11/16 01:32:51 christos Exp $");
     23 
     24 /* #define CISS_DEBUG */
     25 
     26 #include <sys/param.h>
     27 #include <sys/systm.h>
     28 #include <sys/buf.h>
     29 #include <sys/ioctl.h>
     30 #include <sys/device.h>
     31 #include <sys/kernel.h>
     32 #include <sys/malloc.h>
     33 #include <sys/proc.h>
     34 #include <sys/kthread.h>
     35 
     36 #include <uvm/uvm_extern.h>
     37 
     38 #include <machine/bus.h>
     39 
     40 #include <dev/scsipi/scsi_all.h>
     41 #include <dev/scsipi/scsi_disk.h>
     42 #include <dev/scsipi/scsiconf.h>
     43 
     44 #include <dev/ic/cissreg.h>
     45 #include <dev/ic/cissvar.h>
     46 
     47 #ifdef CISS_DEBUG
     48 #define	CISS_DPRINTF(m,a)	if (ciss_debug & (m)) printf a
     49 #define	CISS_D_CMD	0x0001
     50 #define	CISS_D_INTR	0x0002
     51 #define	CISS_D_MISC	0x0004
     52 #define	CISS_D_DMA	0x0008
     53 #define	CISS_D_IOCTL	0x0010
     54 #define	CISS_D_ERR	0x0020
     55 int ciss_debug = 0
     56 	| CISS_D_CMD
     57 	| CISS_D_INTR
     58 	| CISS_D_MISC
     59 	| CISS_D_DMA
     60 	| CISS_D_IOCTL
     61 	| CISS_D_ERR
     62 	;
     63 #else
     64 #define	CISS_DPRINTF(m,a)	/* m, a */
     65 #endif
     66 
     67 static void	ciss_scsi_cmd(struct scsipi_channel *chan,
     68 			scsipi_adapter_req_t req, void *arg);
     69 static int	ciss_scsi_ioctl(struct scsipi_channel *chan, u_long cmd,
     70 	    caddr_t addr, int flag, struct proc *p);
     71 static void	cissminphys(struct buf *bp);
     72 
     73 #if 0
     74 static void	ciss_scsi_raw_cmd(struct scsipi_channel *chan,
     75 			scsipi_adapter_req_t req, void *arg);
     76 #endif
     77 
     78 #if NBIO > 0
     79 static int	ciss_ioctl(struct device *, u_long, caddr_t);
     80 #endif
     81 static int	ciss_sync(struct ciss_softc *sc);
     82 static void	ciss_heartbeat(void *v);
     83 static void	ciss_shutdown(void *v);
     84 #if 0
     85 static void	ciss_kthread(void *v);
     86 #endif
     87 
     88 static struct ciss_ccb *ciss_get_ccb(struct ciss_softc *sc);
     89 static void	ciss_put_ccb(struct ciss_ccb *ccb);
     90 static int	ciss_cmd(struct ciss_ccb *ccb, int flags, int wait);
     91 static int	ciss_done(struct ciss_ccb *ccb);
     92 static int	ciss_error(struct ciss_ccb *ccb);
     93 static int	ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq);
     94 static int	ciss_ldmap(struct ciss_softc *sc);
     95 
     96 static struct ciss_ccb *
     97 ciss_get_ccb(struct ciss_softc *sc)
     98 {
     99 	struct ciss_ccb *ccb;
    100 
    101 	if ((ccb = TAILQ_LAST(&sc->sc_free_ccb, ciss_queue_head))) {
    102 		TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_link);
    103 		ccb->ccb_state = CISS_CCB_READY;
    104 	}
    105 	return ccb;
    106 }
    107 
    108 static void
    109 ciss_put_ccb(struct ciss_ccb *ccb)
    110 {
    111 	struct ciss_softc *sc = ccb->ccb_sc;
    112 
    113 	ccb->ccb_state = CISS_CCB_FREE;
    114 	TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
    115 }
    116 
    117 int
    118 ciss_attach(struct ciss_softc *sc)
    119 {
    120 	struct ciss_ccb *ccb;
    121 	struct ciss_cmd *cmd;
    122 	struct ciss_inquiry *inq;
    123 	bus_dma_segment_t seg[1];
    124 	int error, i, total, rseg, maxfer;
    125 	ciss_lock_t lock;
    126 	paddr_t pa;
    127 
    128 	bus_space_read_region_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff,
    129 	    (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
    130 
    131 	if (sc->cfg.signature != CISS_SIGNATURE) {
    132 		printf(": bad sign 0x%08x\n", sc->cfg.signature);
    133 		return -1;
    134 	}
    135 
    136 	if (!(sc->cfg.methods & CISS_METH_SIMPL)) {
    137 		printf(": not simple 0x%08x\n", sc->cfg.methods);
    138 		return -1;
    139 	}
    140 
    141 	sc->cfg.rmethod = CISS_METH_SIMPL;
    142 	sc->cfg.paddr_lim = 0;			/* 32bit addrs */
    143 	sc->cfg.int_delay = 0;			/* disable coalescing */
    144 	sc->cfg.int_count = 0;
    145 	strlcpy(sc->cfg.hostname, "HUMPPA", sizeof(sc->cfg.hostname));
    146 	sc->cfg.driverf |= CISS_DRV_PRF;	/* enable prefetch */
    147 	if (!sc->cfg.maxsg)
    148 		sc->cfg.maxsg = MAXPHYS / PAGE_SIZE + 1;
    149 
    150 	bus_space_write_region_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff,
    151 	    (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
    152 	bus_space_barrier(sc->sc_iot, sc->cfg_ioh, sc->cfgoff, sizeof(sc->cfg),
    153 	    BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
    154 
    155 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IDB, CISS_IDB_CFG);
    156 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, CISS_IDB, 4,
    157 	    BUS_SPACE_BARRIER_WRITE);
    158 	for (i = 1000; i--; DELAY(1000)) {
    159 		/* XXX maybe IDB is really 64bit? - hp dl380 needs this */
    160 		(void)bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IDB + 4);
    161 		if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IDB) & CISS_IDB_CFG))
    162 			break;
    163 		bus_space_barrier(sc->sc_iot, sc->sc_ioh, CISS_IDB, 4,
    164 		    BUS_SPACE_BARRIER_READ);
    165 	}
    166 
    167 	if (bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IDB) & CISS_IDB_CFG) {
    168 		printf(": cannot set config\n");
    169 		return -1;
    170 	}
    171 
    172 	bus_space_read_region_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff,
    173 	    (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
    174 
    175 	if (!(sc->cfg.amethod & CISS_METH_SIMPL)) {
    176 		printf(": cannot simplify 0x%08x\n", sc->cfg.amethod);
    177 		return -1;
    178 	}
    179 
    180 	/* i'm ready for you and i hope you're ready for me */
    181 	for (i = 30000; i--; DELAY(1000)) {
    182 		if (bus_space_read_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff +
    183 		    offsetof(struct ciss_config, amethod)) & CISS_METH_READY)
    184 			break;
    185 		bus_space_barrier(sc->sc_iot, sc->cfg_ioh, sc->cfgoff +
    186 		    offsetof(struct ciss_config, amethod), 4,
    187 		    BUS_SPACE_BARRIER_READ);
    188 	}
    189 
    190 	if (!(bus_space_read_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff +
    191 	    offsetof(struct ciss_config, amethod)) & CISS_METH_READY)) {
    192 		printf(": she never came ready for me 0x%08x\n",
    193 		    sc->cfg.amethod);
    194 		return -1;
    195 	}
    196 
    197 	sc->maxcmd = sc->cfg.maxcmd;
    198 	sc->maxsg = sc->cfg.maxsg;
    199 	if (sc->maxsg > MAXPHYS / PAGE_SIZE + 1)
    200 		sc->maxsg = MAXPHYS / PAGE_SIZE + 1;
    201 	i = sizeof(struct ciss_ccb) +
    202 	    sizeof(ccb->ccb_cmd.sgl[0]) * (sc->maxsg - 1);
    203 	for (sc->ccblen = 0x10; sc->ccblen < i; sc->ccblen <<= 1);
    204 
    205 	total = sc->ccblen * sc->maxcmd;
    206 	if ((error = bus_dmamem_alloc(sc->sc_dmat, total, PAGE_SIZE, 0,
    207 	    sc->cmdseg, 1, &rseg, BUS_DMA_NOWAIT))) {
    208 		printf(": cannot allocate CCBs (%d)\n", error);
    209 		return -1;
    210 	}
    211 
    212 	if ((error = bus_dmamem_map(sc->sc_dmat, sc->cmdseg, rseg, total,
    213 	    (caddr_t *)&sc->ccbs, BUS_DMA_NOWAIT))) {
    214 		printf(": cannot map CCBs (%d)\n", error);
    215 		return -1;
    216 	}
    217 	bzero(sc->ccbs, total);
    218 
    219 	if ((error = bus_dmamap_create(sc->sc_dmat, total, 1,
    220 	    total, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->cmdmap))) {
    221 		printf(": cannot create CCBs dmamap (%d)\n", error);
    222 		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
    223 		return -1;
    224 	}
    225 
    226 	if ((error = bus_dmamap_load(sc->sc_dmat, sc->cmdmap, sc->ccbs, total,
    227 	    NULL, BUS_DMA_NOWAIT))) {
    228 		printf(": cannot load CCBs dmamap (%d)\n", error);
    229 		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
    230 		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
    231 		return -1;
    232 	}
    233 
    234 	TAILQ_INIT(&sc->sc_ccbq);
    235 	TAILQ_INIT(&sc->sc_ccbdone);
    236 	TAILQ_INIT(&sc->sc_free_ccb);
    237 
    238 	maxfer = sc->maxsg * PAGE_SIZE;
    239 	for (i = 0; total > 0 && i < sc->maxcmd; i++, total -= sc->ccblen) {
    240 		ccb = (struct ciss_ccb *) (sc->ccbs + i * sc->ccblen);
    241 		cmd = &ccb->ccb_cmd;
    242 		pa = sc->cmdseg[0].ds_addr + i * sc->ccblen;
    243 
    244 		ccb->ccb_sc = sc;
    245 		ccb->ccb_cmdpa = pa + offsetof(struct ciss_ccb, ccb_cmd);
    246 		ccb->ccb_state = CISS_CCB_FREE;
    247 
    248 		cmd->id = htole32(i << 2);
    249 		cmd->id_hi = htole32(0);
    250 		cmd->sgin = sc->maxsg;
    251 		cmd->sglen = htole16((u_int16_t)cmd->sgin);
    252 		cmd->err_len = htole32(sizeof(ccb->ccb_err));
    253 		pa += offsetof(struct ciss_ccb, ccb_err);
    254 		cmd->err_pa = htole64((u_int64_t)pa);
    255 
    256 		if ((error = bus_dmamap_create(sc->sc_dmat, maxfer, sc->maxsg,
    257 		    maxfer, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
    258 		    &ccb->ccb_dmamap)))
    259 			break;
    260 
    261 		TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
    262 	}
    263 
    264 	if (i < sc->maxcmd) {
    265 		printf(": cannot create ccb#%d dmamap (%d)\n", i, error);
    266 		if (i == 0) {
    267 			/* TODO leaking cmd's dmamaps and shitz */
    268 			bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
    269 			bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
    270 			return -1;
    271 		}
    272 	}
    273 
    274 	if ((error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
    275 	    seg, 1, &rseg, BUS_DMA_NOWAIT))) {
    276 		printf(": cannot allocate scratch buffer (%d)\n", error);
    277 		return -1;
    278 	}
    279 
    280 	if ((error = bus_dmamem_map(sc->sc_dmat, seg, rseg, PAGE_SIZE,
    281 	    (caddr_t *)&sc->scratch, BUS_DMA_NOWAIT))) {
    282 		printf(": cannot map scratch buffer (%d)\n", error);
    283 		return -1;
    284 	}
    285 	bzero(sc->scratch, PAGE_SIZE);
    286 
    287 	lock = CISS_LOCK_SCRATCH(sc);
    288 	inq = sc->scratch;
    289 	if (ciss_inq(sc, inq)) {
    290 		printf(": adapter inquiry failed\n");
    291 		CISS_UNLOCK_SCRATCH(sc, lock);
    292 		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
    293 		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
    294 		return -1;
    295 	}
    296 
    297 	if (!(inq->flags & CISS_INQ_BIGMAP)) {
    298 		printf(": big map is not supported, flags=0x%x\n",
    299 		    inq->flags);
    300 		CISS_UNLOCK_SCRATCH(sc, lock);
    301 		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
    302 		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
    303 		return -1;
    304 	}
    305 
    306 	sc->maxunits = inq->numld;
    307 	sc->nbus = inq->nscsi_bus;
    308 	sc->ndrives = inq->buswidth;
    309 	printf(": %d LD%s, HW rev %d, FW %4.4s/%4.4s\n",
    310 	    inq->numld, inq->numld == 1? "" : "s",
    311 	    inq->hw_rev, inq->fw_running, inq->fw_stored);
    312 
    313 	CISS_UNLOCK_SCRATCH(sc, lock);
    314 
    315 	callout_init(&sc->sc_hb);
    316 	callout_setfunc(&sc->sc_hb, ciss_heartbeat, sc);
    317 	callout_schedule(&sc->sc_hb, hz * 3);
    318 
    319 	/* map LDs */
    320 	if (ciss_ldmap(sc)) {
    321 		printf("%s: adapter LD map failed\n", sc->sc_dev.dv_xname);
    322 		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
    323 		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
    324 		return -1;
    325 	}
    326 
    327 /* TODO scan all physdev */
    328 /* TODO scan all logdev */
    329 
    330 	sc->sc_flush = CISS_FLUSH_ENABLE;
    331 	if (!(sc->sc_sh = shutdownhook_establish(ciss_shutdown, sc))) {
    332 		printf(": unable to establish shutdown hook\n");
    333 		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
    334 		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
    335 		return -1;
    336 	}
    337 
    338 #if 0
    339 	if (kthread_create(ciss_kthread, sc, NULL, "%s", sc->sc_dev.dv_xname)) {
    340 		printf(": unable to create kernel thread\n");
    341 		shutdownhook_disestablish(sc->sc_sh);
    342 		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
    343 		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
    344 		return -1;
    345 	}
    346 #endif
    347 
    348 	sc->sc_channel.chan_adapter = &sc->sc_adapter;
    349 	sc->sc_channel.chan_bustype = &scsi_bustype;
    350 	sc->sc_channel.chan_channel = 0;
    351 	sc->sc_channel.chan_ntargets = sc->maxunits;
    352 	sc->sc_channel.chan_nluns = 8;
    353 	sc->sc_channel.chan_openings = sc->maxcmd / (sc->maxunits? sc->maxunits : 1);
    354 	sc->sc_channel.chan_flags = 0;
    355 	sc->sc_channel.chan_id = sc->maxunits;
    356 
    357 	sc->sc_adapter.adapt_dev = (struct device *) sc;
    358 	sc->sc_adapter.adapt_openings = sc->maxcmd / (sc->maxunits? sc->maxunits : 1);
    359 	sc->sc_adapter.adapt_max_periph = sc->maxunits;
    360 	sc->sc_adapter.adapt_request = ciss_scsi_cmd;
    361 	sc->sc_adapter.adapt_minphys = cissminphys;
    362 	sc->sc_adapter.adapt_ioctl = ciss_scsi_ioctl;
    363 	sc->sc_adapter.adapt_nchannels = 1;
    364 	config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
    365 
    366 #if 0
    367 	sc->sc_link_raw.adapter_softc = sc;
    368 	sc->sc_link.openings = sc->maxcmd / (sc->maxunits? sc->maxunits : 1);
    369 	sc->sc_link_raw.adapter = &ciss_raw_switch;
    370 	sc->sc_link_raw.adapter_target = sc->ndrives;
    371 	sc->sc_link_raw.adapter_buswidth = sc->ndrives;
    372 	config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
    373 #endif
    374 
    375 #if NBIO1 > 0
    376 	if (bio_register(&sc->sc_dev, ciss_ioctl) != 0)
    377 		printf("%s: controller registration failed",
    378 		    sc->sc_dev.dv_xname);
    379 #endif
    380 
    381 	return 0;
    382 }
    383 
    384 static void
    385 ciss_shutdown(void *v)
    386 {
    387 	struct ciss_softc *sc = v;
    388 
    389 	sc->sc_flush = CISS_FLUSH_DISABLE;
    390 	/* timeout_del(&sc->sc_hb); */
    391 	ciss_sync(sc);
    392 }
    393 
    394 static void
    395 cissminphys(struct buf *bp)
    396 {
    397 #if 0	/* TOSO */
    398 #define	CISS_MAXFER	(PAGE_SIZE * (sc->maxsg + 1))
    399 	if (bp->b_bcount > CISS_MAXFER)
    400 		bp->b_bcount = CISS_MAXFER;
    401 #endif
    402 	minphys(bp);
    403 }
    404 
    405 /*
    406  * submit a command and optionally wait for completition.
    407  * wait arg abuses XS_CTL_POLL|XS_CTL_NOSLEEP flags to request
    408  * to wait (XS_CTL_POLL) and to allow tsleep() (!XS_CTL_NOSLEEP)
    409  * instead of busy loop waiting
    410  */
    411 static int
    412 ciss_cmd(struct ciss_ccb *ccb, int flags, int wait)
    413 {
    414 	struct ciss_softc *sc = ccb->ccb_sc;
    415 	struct ciss_cmd *cmd = &ccb->ccb_cmd;
    416 	struct ciss_ccb *ccb1;
    417 	bus_dmamap_t dmap = ccb->ccb_dmamap;
    418 	u_int32_t id;
    419 	int i, tohz, error = 0;
    420 
    421 	if (ccb->ccb_state != CISS_CCB_READY) {
    422 		printf("%s: ccb %d not ready state=0x%x\n", sc->sc_dev.dv_xname,
    423 		    cmd->id, ccb->ccb_state);
    424 		return (EINVAL);
    425 	}
    426 
    427 	if (ccb->ccb_data) {
    428 		bus_dma_segment_t *sgd;
    429 
    430 		if ((error = bus_dmamap_load(sc->sc_dmat, dmap, ccb->ccb_data,
    431 		    ccb->ccb_len, NULL, flags))) {
    432 			if (error == EFBIG)
    433 				printf("more than %d dma segs\n", sc->maxsg);
    434 			else
    435 				printf("error %d loading dma map\n", error);
    436 			ciss_put_ccb(ccb);
    437 			return (error);
    438 		}
    439 		cmd->sgin = dmap->dm_nsegs;
    440 
    441 		sgd = dmap->dm_segs;
    442 		CISS_DPRINTF(CISS_D_DMA, ("data=%p/%u<0x%lx/%lu",
    443 		    ccb->ccb_data, ccb->ccb_len, sgd->ds_addr, sgd->ds_len));
    444 
    445 		for (i = 0; i < dmap->dm_nsegs; sgd++, i++) {
    446 			cmd->sgl[i].addr_lo = htole32(sgd->ds_addr);
    447 			cmd->sgl[i].addr_hi =
    448 			    htole32((u_int64_t)sgd->ds_addr >> 32);
    449 			cmd->sgl[i].len = htole32(sgd->ds_len);
    450 			cmd->sgl[i].flags = htole32(0);
    451 			if (i) {
    452 				CISS_DPRINTF(CISS_D_DMA,
    453 				    (",0x%lx/%lu", sgd->ds_addr, sgd->ds_len));
    454 			}
    455 		}
    456 
    457 		CISS_DPRINTF(CISS_D_DMA, ("> "));
    458 
    459 		bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
    460 		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
    461 	} else
    462 		cmd->sgin = 0;
    463 	cmd->sglen = htole16((u_int16_t)cmd->sgin);
    464 	bzero(&ccb->ccb_err, sizeof(ccb->ccb_err));
    465 
    466 	bus_dmamap_sync(sc->sc_dmat, sc->cmdmap, 0, sc->cmdmap->dm_mapsize,
    467 	    BUS_DMASYNC_PREWRITE);
    468 
    469 	if ((wait & (XS_CTL_POLL|XS_CTL_NOSLEEP)) == (XS_CTL_POLL|XS_CTL_NOSLEEP))
    470 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IMR,
    471 		    bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IMR) | sc->iem);
    472 
    473 	TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
    474 	ccb->ccb_state = CISS_CCB_ONQ;
    475 	CISS_DPRINTF(CISS_D_CMD, ("submit=0x%x ", cmd->id));
    476 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_INQ, ccb->ccb_cmdpa);
    477 
    478 	if (wait & XS_CTL_POLL) {
    479 		int etick;
    480 		CISS_DPRINTF(CISS_D_CMD, ("waiting "));
    481 
    482 		i = ccb->ccb_xs? ccb->ccb_xs->timeout : 60000;
    483 		tohz = (i / 1000) * hz + (i % 1000) * (hz / 1000);
    484 		if (tohz == 0)
    485 			tohz = 1;
    486 		for (i *= 100, etick = tick + tohz; i--; ) {
    487 			if (!(wait & XS_CTL_NOSLEEP)) {
    488 				ccb->ccb_state = CISS_CCB_POLL;
    489 				CISS_DPRINTF(CISS_D_CMD, ("tsleep(%d) ", tohz));
    490 				if (tsleep(ccb, PRIBIO + 1, "ciss_cmd",
    491 				    tohz) == EWOULDBLOCK) {
    492 					break;
    493 				}
    494 				if (ccb->ccb_state != CISS_CCB_ONQ) {
    495 					tohz = etick - tick;
    496 					if (tohz <= 0)
    497 						break;
    498 					CISS_DPRINTF(CISS_D_CMD, ("T"));
    499 					continue;
    500 				}
    501 				ccb1 = ccb;
    502 			} else {
    503 				DELAY(10);
    504 
    505 				if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh,
    506 				    CISS_ISR) & sc->iem)) {
    507 					CISS_DPRINTF(CISS_D_CMD, ("N"));
    508 					continue;
    509 				}
    510 
    511 				if ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
    512 				    CISS_OUTQ)) == 0xffffffff) {
    513 					CISS_DPRINTF(CISS_D_CMD, ("Q"));
    514 					continue;
    515 				}
    516 
    517 				CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id));
    518 				ccb1 = (struct ciss_ccb *)
    519 					(sc->ccbs + (id >> 2) * sc->ccblen);
    520 				ccb1->ccb_cmd.id = htole32(id);
    521 			}
    522 
    523 			error = ciss_done(ccb1);
    524 			if (ccb1 == ccb)
    525 				break;
    526 		}
    527 
    528 		/* if never got a chance to be done above... */
    529 		if (ccb->ccb_state != CISS_CCB_FREE) {
    530 			ccb->ccb_err.cmd_stat = CISS_ERR_TMO;
    531 			error = ciss_done(ccb);
    532 		}
    533 
    534 		CISS_DPRINTF(CISS_D_CMD, ("done %d:%d",
    535 		    ccb->ccb_err.cmd_stat, ccb->ccb_err.scsi_stat));
    536 	}
    537 
    538 	if ((wait & (XS_CTL_POLL|XS_CTL_NOSLEEP)) == (XS_CTL_POLL|XS_CTL_NOSLEEP))
    539 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IMR,
    540 		    bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IMR) & ~sc->iem);
    541 
    542 	return (error);
    543 }
    544 
    545 static int
    546 ciss_done(struct ciss_ccb *ccb)
    547 {
    548 	struct ciss_softc *sc = ccb->ccb_sc;
    549 	struct scsipi_xfer *xs = ccb->ccb_xs;
    550 	struct ciss_cmd *cmd;
    551 	ciss_lock_t lock;
    552 	int error = 0;
    553 
    554 	CISS_DPRINTF(CISS_D_CMD, ("ciss_done(%p) ", ccb));
    555 
    556 	if (ccb->ccb_state != CISS_CCB_ONQ) {
    557 		printf("%s: unqueued ccb %p ready, state=0x%x\n",
    558 		    sc->sc_dev.dv_xname, ccb, ccb->ccb_state);
    559 		return 1;
    560 	}
    561 
    562 	lock = CISS_LOCK(sc);
    563 	ccb->ccb_state = CISS_CCB_READY;
    564 	TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link);
    565 
    566 	if (ccb->ccb_cmd.id & CISS_CMD_ERR)
    567 		error = ciss_error(ccb);
    568 
    569 	cmd = &ccb->ccb_cmd;
    570 	if (ccb->ccb_data) {
    571 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
    572 		    ccb->ccb_dmamap->dm_mapsize, (cmd->flags & CISS_CDB_IN) ?
    573 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
    574 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
    575 		ccb->ccb_xs = NULL;
    576 		ccb->ccb_data = NULL;
    577 	}
    578 
    579 	ciss_put_ccb(ccb);
    580 
    581 	if (xs) {
    582 		xs->resid = 0;
    583 		CISS_DPRINTF(CISS_D_CMD, ("scsipi_done(%p) ", xs));
    584 		scsipi_done(xs);
    585 	}
    586 	CISS_UNLOCK(sc, lock);
    587 
    588 	return error;
    589 }
    590 
    591 static int
    592 ciss_error(struct ciss_ccb *ccb)
    593 {
    594 	struct ciss_softc *sc = ccb->ccb_sc;
    595 	struct ciss_error *err = &ccb->ccb_err;
    596 	struct scsipi_xfer *xs = ccb->ccb_xs;
    597 	int rv;
    598 
    599 	switch ((rv = le16toh(err->cmd_stat))) {
    600 	case CISS_ERR_OK:
    601 		break;
    602 
    603 	case CISS_ERR_INVCMD:
    604 		printf("%s: invalid cmd 0x%x: 0x%x is not valid @ 0x%x[%d]\n",
    605 		    sc->sc_dev.dv_xname, ccb->ccb_cmd.id,
    606 		    err->err_info, err->err_type[3], err->err_type[2]);
    607 		if (xs) {
    608 			bzero(&xs->sense, sizeof(xs->sense));
    609 			xs->sense.scsi_sense.response_code =
    610 				SSD_RCODE_CURRENT | SSD_RCODE_VALID;
    611 			xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
    612 			xs->sense.scsi_sense.asc = 0x24; /* ill field */
    613 			xs->sense.scsi_sense.ascq = 0x0;
    614 			xs->error = XS_SENSE;
    615 		}
    616 		break;
    617 
    618 	case CISS_ERR_TMO:
    619 		xs->error = XS_TIMEOUT;
    620 		break;
    621 
    622 	case CISS_ERR_UNRUN:
    623 		/* Underrun */
    624 		xs->resid = le32toh(err->resid);
    625 		CISS_DPRINTF(CISS_D_CMD, (" underrun resid=0x%x ",
    626 					  xs->resid));
    627 		break;
    628 	default:
    629 		if (xs) {
    630 			CISS_DPRINTF(CISS_D_CMD, ("scsi_stat=%x ", err->scsi_stat));
    631 			switch (err->scsi_stat) {
    632 			case SCSI_CHECK:
    633 				xs->error = XS_SENSE;
    634 				bcopy(&err->sense[0], &xs->sense,
    635 				    sizeof(xs->sense));
    636 				CISS_DPRINTF(CISS_D_CMD, (" sense=%02x %02x %02x %02x ",
    637 					     err->sense[0], err->sense[1], err->sense[2], err->sense[3]));
    638 				break;
    639 
    640 			case XS_BUSY:
    641 				xs->error = XS_BUSY;
    642 				break;
    643 
    644 			default:
    645 				CISS_DPRINTF(CISS_D_ERR, ("%s: "
    646 				    "cmd_stat=%x scsi_stat=0x%x resid=0x%x\n",
    647 				    sc->sc_dev.dv_xname, rv, err->scsi_stat,
    648 				    le32toh(err->resid)));
    649 				printf("ciss driver stuffup in %s:%d: %s()\n",
    650 				       __FILE__, __LINE__, __FUNCTION__);
    651 				xs->error = XS_DRIVER_STUFFUP;
    652 				break;
    653 			}
    654 			xs->resid = le32toh(err->resid);
    655 		}
    656 	}
    657 	ccb->ccb_cmd.id &= htole32(~3);
    658 
    659 	return rv;
    660 }
    661 
    662 static int
    663 ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq)
    664 {
    665 	struct ciss_ccb *ccb;
    666 	struct ciss_cmd *cmd;
    667 
    668 	ccb = ciss_get_ccb(sc);
    669 	ccb->ccb_len = sizeof(*inq);
    670 	ccb->ccb_data = inq;
    671 	ccb->ccb_xs = NULL;
    672 	cmd = &ccb->ccb_cmd;
    673 	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
    674 	cmd->tgt2 = 0;
    675 	cmd->cdblen = 10;
    676 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
    677 	cmd->tmo = htole16(0);
    678 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
    679 	cmd->cdb[0] = CISS_CMD_CTRL_GET;
    680 	cmd->cdb[6] = CISS_CMS_CTRL_CTRL;
    681 	cmd->cdb[7] = sizeof(*inq) >> 8;	/* biiiig endian */
    682 	cmd->cdb[8] = sizeof(*inq) & 0xff;
    683 
    684 	return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP);
    685 }
    686 
    687 static int
    688 ciss_ldmap(struct ciss_softc *sc)
    689 {
    690 	struct ciss_ccb *ccb;
    691 	struct ciss_cmd *cmd;
    692 	struct ciss_ldmap *lmap;
    693 	ciss_lock_t lock;
    694 	int total, rv;
    695 
    696 	lock = CISS_LOCK_SCRATCH(sc);
    697 	lmap = sc->scratch;
    698 	lmap->size = htobe32(sc->maxunits * sizeof(lmap->map));
    699 	total = sizeof(*lmap) + (sc->maxunits - 1) * sizeof(lmap->map);
    700 
    701 	ccb = ciss_get_ccb(sc);
    702 	ccb->ccb_len = total;
    703 	ccb->ccb_data = lmap;
    704 	ccb->ccb_xs = NULL;
    705 	cmd = &ccb->ccb_cmd;
    706 	cmd->tgt = CISS_CMD_MODE_PERIPH;
    707 	cmd->tgt2 = 0;
    708 	cmd->cdblen = 12;
    709 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
    710 	cmd->tmo = htole16(30);
    711 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
    712 	cmd->cdb[0] = CISS_CMD_LDMAP;
    713 	cmd->cdb[8] = total >> 8;	/* biiiig endian */
    714 	cmd->cdb[9] = total & 0xff;
    715 
    716 	rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP);
    717 	CISS_UNLOCK_SCRATCH(sc, lock);
    718 
    719 	if (rv)
    720 		return rv;
    721 
    722 	CISS_DPRINTF(CISS_D_MISC, ("lmap %x:%x\n",
    723 	    lmap->map[0].tgt, lmap->map[0].tgt2));
    724 
    725 	return 0;
    726 }
    727 
    728 static int
    729 ciss_sync(struct ciss_softc *sc)
    730 {
    731 	struct ciss_ccb *ccb;
    732 	struct ciss_cmd *cmd;
    733 	struct ciss_flush *flush;
    734 	ciss_lock_t lock;
    735 	int rv;
    736 
    737 	lock = CISS_LOCK_SCRATCH(sc);
    738 	flush = sc->scratch;
    739 	bzero(flush, sizeof(*flush));
    740 	flush->flush = sc->sc_flush;
    741 
    742 	ccb = ciss_get_ccb(sc);
    743 	ccb->ccb_len = sizeof(*flush);
    744 	ccb->ccb_data = flush;
    745 	ccb->ccb_xs = NULL;
    746 	cmd = &ccb->ccb_cmd;
    747 	cmd->tgt = CISS_CMD_MODE_PERIPH;
    748 	cmd->tgt2 = 0;
    749 	cmd->cdblen = 10;
    750 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT;
    751 	cmd->tmo = 0;
    752 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
    753 	cmd->cdb[0] = CISS_CMD_CTRL_SET;
    754 	cmd->cdb[6] = CISS_CMS_CTRL_FLUSH;
    755 	cmd->cdb[7] = sizeof(*flush) >> 8;	/* biiiig endian */
    756 	cmd->cdb[8] = sizeof(*flush) & 0xff;
    757 
    758 	rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP);
    759 	CISS_UNLOCK_SCRATCH(sc, lock);
    760 
    761 	return rv;
    762 }
    763 
    764 #if 0
    765 static void
    766 ciss_scsi_raw_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req,
    767 	void *arg)				/* TODO */
    768 {
    769 	struct scsipi_xfer *xs = (struct scsipi_xfer *) arg;
    770 	struct ciss_rawsoftc *rsc =
    771 		(struct ciss_rawsoftc *) chan->chan_adapter->adapt_dev;
    772 	struct ciss_softc *sc = rsc->sc_softc;
    773 	struct ciss_ccb *ccb;
    774 	struct ciss_cmd *cmd;
    775 	ciss_lock_t lock;
    776 	int error;
    777 
    778 	CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_raw_cmd "));
    779 
    780 	switch (req)
    781 	{
    782 	case ADAPTER_REQ_RUN_XFER:
    783 		if (xs->cmdlen > CISS_MAX_CDB) {
    784 			CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs));
    785 			bzero(&xs->sense, sizeof(xs->sense));
    786 			printf("ciss driver stuffup in %s:%d: %s()\n",
    787 			       __FILE__, __LINE__, __FUNCTION__);
    788 			xs->error = XS_DRIVER_STUFFUP;
    789 			scsipi_done(xs);
    790 			break;
    791 		}
    792 
    793 		lock = CISS_LOCK(sc);
    794 		error = 0;
    795 		xs->error = XS_NOERROR;
    796 
    797 		/* TODO check this target has not yet employed w/ any volume */
    798 
    799 		ccb = ciss_get_ccb(sc);
    800 		cmd = &ccb->ccb_cmd;
    801 		ccb->ccb_len = xs->datalen;
    802 		ccb->ccb_data = xs->data;
    803 		ccb->ccb_xs = xs;
    804 
    805 		cmd->cdblen = xs->cmdlen;
    806 		cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL;
    807 		if (xs->xs_control & XS_CTL_DATA_IN)
    808 			cmd->flags |= CISS_CDB_IN;
    809 		else if (xs->xs_control & XS_CTL_DATA_OUT)
    810 			cmd->flags |= CISS_CDB_OUT;
    811 		cmd->tmo = xs->timeout < 1000? 1 : xs->timeout / 1000;
    812 		bzero(&cmd->cdb[0], sizeof(cmd->cdb));
    813 		bcopy(xs->cmd, &cmd->cdb[0], CISS_MAX_CDB);
    814 
    815 		if (ciss_cmd(ccb, BUS_DMA_WAITOK,
    816 		    xs->xs_control & (XS_CTL_POLL|XS_CTL_NOSLEEP))) {
    817 			printf("ciss driver stuffup in %s:%d: %s()\n",
    818 			       __FILE__, __LINE__, __FUNCTION__);
    819 			xs->error = XS_DRIVER_STUFFUP;
    820 			scsipi_done(xs);
    821 			CISS_UNLOCK(sc, lock);
    822 			break;
    823 		}
    824 
    825 		CISS_UNLOCK(sc, lock);
    826 		break;
    827 
    828 	case ADAPTER_REQ_GROW_RESOURCES:
    829 		/*
    830 		 * Not supported.
    831 		 */
    832 		break;
    833 
    834 	case ADAPTER_REQ_SET_XFER_MODE:
    835 		/*
    836 		 * We can't change the transfer mode, but at least let
    837 		 * scsipi know what the adapter has negociated.
    838 		 */
    839 		 /* Get xfer mode and return it */
    840 		break;
    841 	}
    842 }
    843 #endif
    844 
    845 static void
    846 ciss_scsi_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req,
    847 	void *arg)
    848 {
    849 	struct scsipi_xfer *xs = (struct scsipi_xfer *) arg;
    850 	struct ciss_softc *sc =
    851 		(struct ciss_softc *) chan->chan_adapter->adapt_dev;
    852 	u_int8_t target;
    853 	struct ciss_ccb *ccb;
    854 	struct ciss_cmd *cmd;
    855 	int error;
    856 	ciss_lock_t lock;
    857 
    858 	CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_cmd "));
    859 
    860 	switch (req)
    861 	{
    862 	case ADAPTER_REQ_RUN_XFER:
    863 		target = xs->xs_periph->periph_target;
    864 		CISS_DPRINTF(CISS_D_CMD, ("targ=%d ", target));
    865 		if (xs->cmdlen > CISS_MAX_CDB) {
    866 			CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs));
    867 			bzero(&xs->sense, sizeof(xs->sense));
    868 			printf("ciss driver stuffup in %s:%d: %s()\n",
    869 			       __FILE__, __LINE__, __FUNCTION__);
    870 			xs->error = XS_DRIVER_STUFFUP;
    871 			scsipi_done(xs);
    872 			break;
    873 		}
    874 
    875 		lock = CISS_LOCK(sc);
    876 		error = 0;
    877 		xs->error = XS_NOERROR;
    878 
    879 		/* XXX emulate SYNCHRONIZE_CACHE ??? */
    880 
    881 		ccb = ciss_get_ccb(sc);
    882 		cmd = &ccb->ccb_cmd;
    883 		ccb->ccb_len = xs->datalen;
    884 		ccb->ccb_data = xs->data;
    885 		ccb->ccb_xs = xs;
    886 		cmd->tgt = CISS_CMD_MODE_LD | target;
    887 		cmd->tgt2 = 0;
    888 		cmd->cdblen = xs->cmdlen;
    889 		cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL;
    890 		if (xs->xs_control & XS_CTL_DATA_IN)
    891 			cmd->flags |= CISS_CDB_IN;
    892 		else if (xs->xs_control & XS_CTL_DATA_OUT)
    893 			cmd->flags |= CISS_CDB_OUT;
    894 		cmd->tmo = xs->timeout < 1000? 1 : xs->timeout / 1000;
    895 		bzero(&cmd->cdb[0], sizeof(cmd->cdb));
    896 		bcopy(xs->cmd, &cmd->cdb[0], CISS_MAX_CDB);
    897 		CISS_DPRINTF(CISS_D_CMD, ("cmd=%02x %02x %02x %02x %02x %02x ",
    898 			     cmd->cdb[0], cmd->cdb[1], cmd->cdb[2],
    899 			     cmd->cdb[3], cmd->cdb[4], cmd->cdb[5]));
    900 
    901 		if (ciss_cmd(ccb, BUS_DMA_WAITOK,
    902 		    xs->xs_control & (XS_CTL_POLL|XS_CTL_NOSLEEP))) {
    903 			printf("ciss driver stuffup in %s:%d: %s()\n",
    904 			       __FILE__, __LINE__, __FUNCTION__);
    905 			xs->error = XS_DRIVER_STUFFUP;
    906 			scsipi_done(xs);
    907 			CISS_UNLOCK(sc, lock);
    908 			return;
    909 		}
    910 
    911 		CISS_UNLOCK(sc, lock);
    912 		break;
    913 	case ADAPTER_REQ_GROW_RESOURCES:
    914 		/*
    915 		 * Not supported.
    916 		 */
    917 		break;
    918 	case ADAPTER_REQ_SET_XFER_MODE:
    919 		/*
    920 		 * We can't change the transfer mode, but at least let
    921 		 * scsipi know what the adapter has negociated.
    922 		 */
    923 		/* FIXME: get xfer mode and write it into arg */
    924 		break;
    925 	}
    926 }
    927 
    928 int
    929 ciss_intr(void *v)
    930 {
    931 	struct ciss_softc *sc = v;
    932 	struct ciss_ccb *ccb;
    933 	ciss_lock_t lock;
    934 	u_int32_t id;
    935 	int hit = 0;
    936 
    937 	CISS_DPRINTF(CISS_D_INTR, ("intr "));
    938 
    939 	if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_ISR) & sc->iem))
    940 		return 0;
    941 
    942 	lock = CISS_LOCK(sc);
    943 	while ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ)) !=
    944 	    0xffffffff) {
    945 
    946 		ccb = (struct ciss_ccb *) (sc->ccbs + (id >> 2) * sc->ccblen);
    947 		ccb->ccb_cmd.id = htole32(id);
    948 		if (ccb->ccb_state == CISS_CCB_POLL) {
    949 			ccb->ccb_state = CISS_CCB_ONQ;
    950 			wakeup(ccb);
    951 		} else
    952 			ciss_done(ccb);
    953 
    954 		hit = 1;
    955 	}
    956 	CISS_UNLOCK(sc, lock);
    957 
    958 	CISS_DPRINTF(CISS_D_INTR, ("exit\n"));
    959 	return hit;
    960 }
    961 
    962 static void
    963 ciss_heartbeat(void *v)
    964 {
    965 	struct ciss_softc *sc = v;
    966 	u_int32_t hb;
    967 
    968 	hb = bus_space_read_4(sc->sc_iot, sc->cfg_ioh,
    969 	    sc->cfgoff + offsetof(struct ciss_config, heartbeat));
    970 	if (hb == sc->heartbeat)
    971 		panic("ciss: dead");	/* XX reset! */
    972 	else
    973 		sc->heartbeat = hb;
    974 
    975 	callout_schedule(&sc->sc_hb, hz * 3);
    976 }
    977 
    978 #if 0
    979 static void
    980 ciss_kthread(void *v)
    981 {
    982 	struct ciss_softc *sc = v;
    983 	ciss_lock_t lock;
    984 
    985 	for (;;) {
    986 		tsleep(sc, PRIBIO, sc->sc_dev.dv_xname, 0);
    987 
    988 		lock = CISS_LOCK(sc);
    989 
    990 
    991 
    992 		CISS_UNLOCK(sc, lock);
    993 	}
    994 }
    995 #endif
    996 
    997 static int
    998 ciss_scsi_ioctl(struct scsipi_channel *chan, u_long cmd,
    999     caddr_t addr, int flag, struct proc *p)
   1000 {
   1001 #if NBIO > 0
   1002 	return ciss_ioctl(chan->chan_adapter->adapt_dev, cmd, addr);
   1003 #else
   1004 	return ENOTTY;
   1005 #endif
   1006 }
   1007 
   1008 #if NBIO > 0
   1009 static int
   1010 ciss_ioctl(struct device *dev, u_long cmd, caddr_t addr)	/* TODO */
   1011 {
   1012 	/* struct ciss_softc *sc = (struct ciss_softc *)dev; */
   1013 	ciss_lock_t lock;
   1014 	int error;
   1015 
   1016 	lock = CISS_LOCK(sc);
   1017 	switch (cmd) {
   1018 	case BIOCINQ:
   1019 	case BIOCVOL:
   1020 	case BIOCDISK:
   1021 	case BIOCALARM:
   1022 	case BIOCBLINK:
   1023 	case BIOCSETSTATE:
   1024 	default:
   1025 		CISS_DPRINTF(CISS_D_IOCTL, ("%s: invalid ioctl\n",
   1026 		    sc->sc_dev.dv_xname));
   1027 		error = ENOTTY;
   1028 	}
   1029 	CISS_UNLOCK(sc, lock);
   1030 
   1031 	return error;
   1032 }
   1033 #endif
   1034