Home | History | Annotate | Line # | Download | only in ic
ciss.c revision 1.11
      1 /*	$NetBSD: ciss.c,v 1.11 2008/04/08 12:07:25 cegger 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.11 2008/04/08 12:07:25 cegger 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 <sys/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 	    void *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, void *);
     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 	    (void **)&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 *) ((char *)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 	    (void **)&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, 0);
    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 		aprint_error_dev(&sc->sc_dev, "adapter LD map failed\n");
    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", device_xname(&sc->sc_dev))) {
    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 		aprint_error_dev(&sc->sc_dev, "controller registration failed");
    378 #endif
    379 
    380 	return 0;
    381 }
    382 
    383 static void
    384 ciss_shutdown(void *v)
    385 {
    386 	struct ciss_softc *sc = v;
    387 
    388 	sc->sc_flush = CISS_FLUSH_DISABLE;
    389 	/* timeout_del(&sc->sc_hb); */
    390 	ciss_sync(sc);
    391 }
    392 
    393 static void
    394 cissminphys(struct buf *bp)
    395 {
    396 #if 0	/* TOSO */
    397 #define	CISS_MAXFER	(PAGE_SIZE * (sc->maxsg + 1))
    398 	if (bp->b_bcount > CISS_MAXFER)
    399 		bp->b_bcount = CISS_MAXFER;
    400 #endif
    401 	minphys(bp);
    402 }
    403 
    404 /*
    405  * submit a command and optionally wait for completition.
    406  * wait arg abuses XS_CTL_POLL|XS_CTL_NOSLEEP flags to request
    407  * to wait (XS_CTL_POLL) and to allow tsleep() (!XS_CTL_NOSLEEP)
    408  * instead of busy loop waiting
    409  */
    410 static int
    411 ciss_cmd(struct ciss_ccb *ccb, int flags, int wait)
    412 {
    413 	struct ciss_softc *sc = ccb->ccb_sc;
    414 	struct ciss_cmd *cmd = &ccb->ccb_cmd;
    415 	struct ciss_ccb *ccb1;
    416 	bus_dmamap_t dmap = ccb->ccb_dmamap;
    417 	u_int32_t id;
    418 	int i, tohz, error = 0;
    419 
    420 	if (ccb->ccb_state != CISS_CCB_READY) {
    421 		printf("%s: ccb %d not ready state=0x%x\n", device_xname(&sc->sc_dev),
    422 		    cmd->id, ccb->ccb_state);
    423 		return (EINVAL);
    424 	}
    425 
    426 	if (ccb->ccb_data) {
    427 		bus_dma_segment_t *sgd;
    428 
    429 		if ((error = bus_dmamap_load(sc->sc_dmat, dmap, ccb->ccb_data,
    430 		    ccb->ccb_len, NULL, flags))) {
    431 			if (error == EFBIG)
    432 				printf("more than %d dma segs\n", sc->maxsg);
    433 			else
    434 				printf("error %d loading dma map\n", error);
    435 			ciss_put_ccb(ccb);
    436 			return (error);
    437 		}
    438 		cmd->sgin = dmap->dm_nsegs;
    439 
    440 		sgd = dmap->dm_segs;
    441 		CISS_DPRINTF(CISS_D_DMA, ("data=%p/%u<0x%lx/%lu",
    442 		    ccb->ccb_data, ccb->ccb_len, sgd->ds_addr, sgd->ds_len));
    443 
    444 		for (i = 0; i < dmap->dm_nsegs; sgd++, i++) {
    445 			cmd->sgl[i].addr_lo = htole32(sgd->ds_addr);
    446 			cmd->sgl[i].addr_hi =
    447 			    htole32((u_int64_t)sgd->ds_addr >> 32);
    448 			cmd->sgl[i].len = htole32(sgd->ds_len);
    449 			cmd->sgl[i].flags = htole32(0);
    450 			if (i) {
    451 				CISS_DPRINTF(CISS_D_DMA,
    452 				    (",0x%lx/%lu", sgd->ds_addr, sgd->ds_len));
    453 			}
    454 		}
    455 
    456 		CISS_DPRINTF(CISS_D_DMA, ("> "));
    457 
    458 		bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
    459 		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
    460 	} else
    461 		cmd->sgin = 0;
    462 	cmd->sglen = htole16((u_int16_t)cmd->sgin);
    463 	bzero(&ccb->ccb_err, sizeof(ccb->ccb_err));
    464 
    465 	bus_dmamap_sync(sc->sc_dmat, sc->cmdmap, 0, sc->cmdmap->dm_mapsize,
    466 	    BUS_DMASYNC_PREWRITE);
    467 
    468 	if ((wait & (XS_CTL_POLL|XS_CTL_NOSLEEP)) == (XS_CTL_POLL|XS_CTL_NOSLEEP))
    469 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IMR,
    470 		    bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IMR) | sc->iem);
    471 
    472 	TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
    473 	ccb->ccb_state = CISS_CCB_ONQ;
    474 	CISS_DPRINTF(CISS_D_CMD, ("submit=0x%x ", cmd->id));
    475 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_INQ, ccb->ccb_cmdpa);
    476 
    477 	if (wait & XS_CTL_POLL) {
    478 		int etick;
    479 		CISS_DPRINTF(CISS_D_CMD, ("waiting "));
    480 
    481 		i = ccb->ccb_xs? ccb->ccb_xs->timeout : 60000;
    482 		tohz = (i / 1000) * hz + (i % 1000) * (hz / 1000);
    483 		if (tohz == 0)
    484 			tohz = 1;
    485 		for (i *= 100, etick = tick + tohz; i--; ) {
    486 			if (!(wait & XS_CTL_NOSLEEP)) {
    487 				ccb->ccb_state = CISS_CCB_POLL;
    488 				CISS_DPRINTF(CISS_D_CMD, ("tsleep(%d) ", tohz));
    489 				if (tsleep(ccb, PRIBIO + 1, "ciss_cmd",
    490 				    tohz) == EWOULDBLOCK) {
    491 					break;
    492 				}
    493 				if (ccb->ccb_state != CISS_CCB_ONQ) {
    494 					tohz = etick - tick;
    495 					if (tohz <= 0)
    496 						break;
    497 					CISS_DPRINTF(CISS_D_CMD, ("T"));
    498 					continue;
    499 				}
    500 				ccb1 = ccb;
    501 			} else {
    502 				DELAY(10);
    503 
    504 				if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh,
    505 				    CISS_ISR) & sc->iem)) {
    506 					CISS_DPRINTF(CISS_D_CMD, ("N"));
    507 					continue;
    508 				}
    509 
    510 				if ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
    511 				    CISS_OUTQ)) == 0xffffffff) {
    512 					CISS_DPRINTF(CISS_D_CMD, ("Q"));
    513 					continue;
    514 				}
    515 
    516 				CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id));
    517 				ccb1 = (struct ciss_ccb *)
    518 					((char *)sc->ccbs + (id >> 2) * sc->ccblen);
    519 				ccb1->ccb_cmd.id = htole32(id);
    520 			}
    521 
    522 			error = ciss_done(ccb1);
    523 			if (ccb1 == ccb)
    524 				break;
    525 		}
    526 
    527 		/* if never got a chance to be done above... */
    528 		if (ccb->ccb_state != CISS_CCB_FREE) {
    529 			ccb->ccb_err.cmd_stat = CISS_ERR_TMO;
    530 			error = ciss_done(ccb);
    531 		}
    532 
    533 		CISS_DPRINTF(CISS_D_CMD, ("done %d:%d",
    534 		    ccb->ccb_err.cmd_stat, ccb->ccb_err.scsi_stat));
    535 	}
    536 
    537 	if ((wait & (XS_CTL_POLL|XS_CTL_NOSLEEP)) == (XS_CTL_POLL|XS_CTL_NOSLEEP))
    538 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IMR,
    539 		    bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IMR) & ~sc->iem);
    540 
    541 	return (error);
    542 }
    543 
    544 static int
    545 ciss_done(struct ciss_ccb *ccb)
    546 {
    547 	struct ciss_softc *sc = ccb->ccb_sc;
    548 	struct scsipi_xfer *xs = ccb->ccb_xs;
    549 	struct ciss_cmd *cmd;
    550 	ciss_lock_t lock;
    551 	int error = 0;
    552 
    553 	CISS_DPRINTF(CISS_D_CMD, ("ciss_done(%p) ", ccb));
    554 
    555 	if (ccb->ccb_state != CISS_CCB_ONQ) {
    556 		printf("%s: unqueued ccb %p ready, state=0x%x\n",
    557 		    device_xname(&sc->sc_dev), ccb, ccb->ccb_state);
    558 		return 1;
    559 	}
    560 
    561 	lock = CISS_LOCK(sc);
    562 	ccb->ccb_state = CISS_CCB_READY;
    563 	TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link);
    564 
    565 	if (ccb->ccb_cmd.id & CISS_CMD_ERR)
    566 		error = ciss_error(ccb);
    567 
    568 	cmd = &ccb->ccb_cmd;
    569 	if (ccb->ccb_data) {
    570 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
    571 		    ccb->ccb_dmamap->dm_mapsize, (cmd->flags & CISS_CDB_IN) ?
    572 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
    573 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
    574 		ccb->ccb_xs = NULL;
    575 		ccb->ccb_data = NULL;
    576 	}
    577 
    578 	ciss_put_ccb(ccb);
    579 
    580 	if (xs) {
    581 		xs->resid = 0;
    582 		CISS_DPRINTF(CISS_D_CMD, ("scsipi_done(%p) ", xs));
    583 		scsipi_done(xs);
    584 	}
    585 	CISS_UNLOCK(sc, lock);
    586 
    587 	return error;
    588 }
    589 
    590 static int
    591 ciss_error(struct ciss_ccb *ccb)
    592 {
    593 	struct ciss_softc *sc = ccb->ccb_sc;
    594 	struct ciss_error *err = &ccb->ccb_err;
    595 	struct scsipi_xfer *xs = ccb->ccb_xs;
    596 	int rv;
    597 
    598 	switch ((rv = le16toh(err->cmd_stat))) {
    599 	case CISS_ERR_OK:
    600 		break;
    601 
    602 	case CISS_ERR_INVCMD:
    603 		printf("%s: invalid cmd 0x%x: 0x%x is not valid @ 0x%x[%d]\n",
    604 		    device_xname(&sc->sc_dev), ccb->ccb_cmd.id,
    605 		    err->err_info, err->err_type[3], err->err_type[2]);
    606 		if (xs) {
    607 			bzero(&xs->sense, sizeof(xs->sense));
    608 			xs->sense.scsi_sense.response_code =
    609 				SSD_RCODE_CURRENT | SSD_RCODE_VALID;
    610 			xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
    611 			xs->sense.scsi_sense.asc = 0x24; /* ill field */
    612 			xs->sense.scsi_sense.ascq = 0x0;
    613 			xs->error = XS_SENSE;
    614 		}
    615 		break;
    616 
    617 	case CISS_ERR_TMO:
    618 		xs->error = XS_TIMEOUT;
    619 		break;
    620 
    621 	case CISS_ERR_UNRUN:
    622 		/* Underrun */
    623 		xs->resid = le32toh(err->resid);
    624 		CISS_DPRINTF(CISS_D_CMD, (" underrun resid=0x%x ",
    625 					  xs->resid));
    626 		break;
    627 	default:
    628 		if (xs) {
    629 			CISS_DPRINTF(CISS_D_CMD, ("scsi_stat=%x ", err->scsi_stat));
    630 			switch (err->scsi_stat) {
    631 			case SCSI_CHECK:
    632 				xs->error = XS_SENSE;
    633 				bcopy(&err->sense[0], &xs->sense,
    634 				    sizeof(xs->sense));
    635 				CISS_DPRINTF(CISS_D_CMD, (" sense=%02x %02x %02x %02x ",
    636 					     err->sense[0], err->sense[1], err->sense[2], err->sense[3]));
    637 				break;
    638 
    639 			case XS_BUSY:
    640 				xs->error = XS_BUSY;
    641 				break;
    642 
    643 			default:
    644 				CISS_DPRINTF(CISS_D_ERR, ("%s: "
    645 				    "cmd_stat=%x scsi_stat=0x%x resid=0x%x\n",
    646 				    device_xname(&sc->sc_dev), rv, err->scsi_stat,
    647 				    le32toh(err->resid)));
    648 				printf("ciss driver stuffup in %s:%d: %s()\n",
    649 				       __FILE__, __LINE__, __func__);
    650 				xs->error = XS_DRIVER_STUFFUP;
    651 				break;
    652 			}
    653 			xs->resid = le32toh(err->resid);
    654 		}
    655 	}
    656 	ccb->ccb_cmd.id &= htole32(~3);
    657 
    658 	return rv;
    659 }
    660 
    661 static int
    662 ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq)
    663 {
    664 	struct ciss_ccb *ccb;
    665 	struct ciss_cmd *cmd;
    666 
    667 	ccb = ciss_get_ccb(sc);
    668 	ccb->ccb_len = sizeof(*inq);
    669 	ccb->ccb_data = inq;
    670 	ccb->ccb_xs = NULL;
    671 	cmd = &ccb->ccb_cmd;
    672 	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
    673 	cmd->tgt2 = 0;
    674 	cmd->cdblen = 10;
    675 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
    676 	cmd->tmo = htole16(0);
    677 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
    678 	cmd->cdb[0] = CISS_CMD_CTRL_GET;
    679 	cmd->cdb[6] = CISS_CMS_CTRL_CTRL;
    680 	cmd->cdb[7] = sizeof(*inq) >> 8;	/* biiiig endian */
    681 	cmd->cdb[8] = sizeof(*inq) & 0xff;
    682 
    683 	return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP);
    684 }
    685 
    686 static int
    687 ciss_ldmap(struct ciss_softc *sc)
    688 {
    689 	struct ciss_ccb *ccb;
    690 	struct ciss_cmd *cmd;
    691 	struct ciss_ldmap *lmap;
    692 	ciss_lock_t lock;
    693 	int total, rv;
    694 
    695 	lock = CISS_LOCK_SCRATCH(sc);
    696 	lmap = sc->scratch;
    697 	lmap->size = htobe32(sc->maxunits * sizeof(lmap->map));
    698 	total = sizeof(*lmap) + (sc->maxunits - 1) * sizeof(lmap->map);
    699 
    700 	ccb = ciss_get_ccb(sc);
    701 	ccb->ccb_len = total;
    702 	ccb->ccb_data = lmap;
    703 	ccb->ccb_xs = NULL;
    704 	cmd = &ccb->ccb_cmd;
    705 	cmd->tgt = CISS_CMD_MODE_PERIPH;
    706 	cmd->tgt2 = 0;
    707 	cmd->cdblen = 12;
    708 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
    709 	cmd->tmo = htole16(30);
    710 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
    711 	cmd->cdb[0] = CISS_CMD_LDMAP;
    712 	cmd->cdb[8] = total >> 8;	/* biiiig endian */
    713 	cmd->cdb[9] = total & 0xff;
    714 
    715 	rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP);
    716 	CISS_UNLOCK_SCRATCH(sc, lock);
    717 
    718 	if (rv)
    719 		return rv;
    720 
    721 	CISS_DPRINTF(CISS_D_MISC, ("lmap %x:%x\n",
    722 	    lmap->map[0].tgt, lmap->map[0].tgt2));
    723 
    724 	return 0;
    725 }
    726 
    727 static int
    728 ciss_sync(struct ciss_softc *sc)
    729 {
    730 	struct ciss_ccb *ccb;
    731 	struct ciss_cmd *cmd;
    732 	struct ciss_flush *flush;
    733 	ciss_lock_t lock;
    734 	int rv;
    735 
    736 	lock = CISS_LOCK_SCRATCH(sc);
    737 	flush = sc->scratch;
    738 	bzero(flush, sizeof(*flush));
    739 	flush->flush = sc->sc_flush;
    740 
    741 	ccb = ciss_get_ccb(sc);
    742 	ccb->ccb_len = sizeof(*flush);
    743 	ccb->ccb_data = flush;
    744 	ccb->ccb_xs = NULL;
    745 	cmd = &ccb->ccb_cmd;
    746 	cmd->tgt = CISS_CMD_MODE_PERIPH;
    747 	cmd->tgt2 = 0;
    748 	cmd->cdblen = 10;
    749 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT;
    750 	cmd->tmo = 0;
    751 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
    752 	cmd->cdb[0] = CISS_CMD_CTRL_SET;
    753 	cmd->cdb[6] = CISS_CMS_CTRL_FLUSH;
    754 	cmd->cdb[7] = sizeof(*flush) >> 8;	/* biiiig endian */
    755 	cmd->cdb[8] = sizeof(*flush) & 0xff;
    756 
    757 	rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP);
    758 	CISS_UNLOCK_SCRATCH(sc, lock);
    759 
    760 	return rv;
    761 }
    762 
    763 #if 0
    764 static void
    765 ciss_scsi_raw_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req,
    766 	void *arg)				/* TODO */
    767 {
    768 	struct scsipi_xfer *xs = (struct scsipi_xfer *) arg;
    769 	struct ciss_rawsoftc *rsc =
    770 		(struct ciss_rawsoftc *) chan->chan_adapter->adapt_dev;
    771 	struct ciss_softc *sc = rsc->sc_softc;
    772 	struct ciss_ccb *ccb;
    773 	struct ciss_cmd *cmd;
    774 	ciss_lock_t lock;
    775 	int error;
    776 
    777 	CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_raw_cmd "));
    778 
    779 	switch (req)
    780 	{
    781 	case ADAPTER_REQ_RUN_XFER:
    782 		if (xs->cmdlen > CISS_MAX_CDB) {
    783 			CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs));
    784 			bzero(&xs->sense, sizeof(xs->sense));
    785 			printf("ciss driver stuffup in %s:%d: %s()\n",
    786 			       __FILE__, __LINE__, __func__);
    787 			xs->error = XS_DRIVER_STUFFUP;
    788 			scsipi_done(xs);
    789 			break;
    790 		}
    791 
    792 		lock = CISS_LOCK(sc);
    793 		error = 0;
    794 		xs->error = XS_NOERROR;
    795 
    796 		/* TODO check this target has not yet employed w/ any volume */
    797 
    798 		ccb = ciss_get_ccb(sc);
    799 		cmd = &ccb->ccb_cmd;
    800 		ccb->ccb_len = xs->datalen;
    801 		ccb->ccb_data = xs->data;
    802 		ccb->ccb_xs = xs;
    803 
    804 		cmd->cdblen = xs->cmdlen;
    805 		cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL;
    806 		if (xs->xs_control & XS_CTL_DATA_IN)
    807 			cmd->flags |= CISS_CDB_IN;
    808 		else if (xs->xs_control & XS_CTL_DATA_OUT)
    809 			cmd->flags |= CISS_CDB_OUT;
    810 		cmd->tmo = xs->timeout < 1000? 1 : xs->timeout / 1000;
    811 		bzero(&cmd->cdb[0], sizeof(cmd->cdb));
    812 		bcopy(xs->cmd, &cmd->cdb[0], CISS_MAX_CDB);
    813 
    814 		if (ciss_cmd(ccb, BUS_DMA_WAITOK,
    815 		    xs->xs_control & (XS_CTL_POLL|XS_CTL_NOSLEEP))) {
    816 			printf("ciss driver stuffup in %s:%d: %s()\n",
    817 			       __FILE__, __LINE__, __func__);
    818 			xs->error = XS_DRIVER_STUFFUP;
    819 			scsipi_done(xs);
    820 			CISS_UNLOCK(sc, lock);
    821 			break;
    822 		}
    823 
    824 		CISS_UNLOCK(sc, lock);
    825 		break;
    826 
    827 	case ADAPTER_REQ_GROW_RESOURCES:
    828 		/*
    829 		 * Not supported.
    830 		 */
    831 		break;
    832 
    833 	case ADAPTER_REQ_SET_XFER_MODE:
    834 		/*
    835 		 * We can't change the transfer mode, but at least let
    836 		 * scsipi know what the adapter has negociated.
    837 		 */
    838 		 /* Get xfer mode and return it */
    839 		break;
    840 	}
    841 }
    842 #endif
    843 
    844 static void
    845 ciss_scsi_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req,
    846 	void *arg)
    847 {
    848 	struct scsipi_xfer *xs = (struct scsipi_xfer *) arg;
    849 	struct ciss_softc *sc =
    850 		(struct ciss_softc *) chan->chan_adapter->adapt_dev;
    851 	u_int8_t target;
    852 	struct ciss_ccb *ccb;
    853 	struct ciss_cmd *cmd;
    854 	int error;
    855 	ciss_lock_t lock;
    856 
    857 	CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_cmd "));
    858 
    859 	switch (req)
    860 	{
    861 	case ADAPTER_REQ_RUN_XFER:
    862 		target = xs->xs_periph->periph_target;
    863 		CISS_DPRINTF(CISS_D_CMD, ("targ=%d ", target));
    864 		if (xs->cmdlen > CISS_MAX_CDB) {
    865 			CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs));
    866 			bzero(&xs->sense, sizeof(xs->sense));
    867 			printf("ciss driver stuffup in %s:%d: %s()\n",
    868 			       __FILE__, __LINE__, __func__);
    869 			xs->error = XS_DRIVER_STUFFUP;
    870 			scsipi_done(xs);
    871 			break;
    872 		}
    873 
    874 		lock = CISS_LOCK(sc);
    875 		error = 0;
    876 		xs->error = XS_NOERROR;
    877 
    878 		/* XXX emulate SYNCHRONIZE_CACHE ??? */
    879 
    880 		ccb = ciss_get_ccb(sc);
    881 		cmd = &ccb->ccb_cmd;
    882 		ccb->ccb_len = xs->datalen;
    883 		ccb->ccb_data = xs->data;
    884 		ccb->ccb_xs = xs;
    885 		cmd->tgt = CISS_CMD_MODE_LD | target;
    886 		cmd->tgt2 = 0;
    887 		cmd->cdblen = xs->cmdlen;
    888 		cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL;
    889 		if (xs->xs_control & XS_CTL_DATA_IN)
    890 			cmd->flags |= CISS_CDB_IN;
    891 		else if (xs->xs_control & XS_CTL_DATA_OUT)
    892 			cmd->flags |= CISS_CDB_OUT;
    893 		cmd->tmo = xs->timeout < 1000? 1 : xs->timeout / 1000;
    894 		bzero(&cmd->cdb[0], sizeof(cmd->cdb));
    895 		bcopy(xs->cmd, &cmd->cdb[0], CISS_MAX_CDB);
    896 		CISS_DPRINTF(CISS_D_CMD, ("cmd=%02x %02x %02x %02x %02x %02x ",
    897 			     cmd->cdb[0], cmd->cdb[1], cmd->cdb[2],
    898 			     cmd->cdb[3], cmd->cdb[4], cmd->cdb[5]));
    899 
    900 		if (ciss_cmd(ccb, BUS_DMA_WAITOK,
    901 		    xs->xs_control & (XS_CTL_POLL|XS_CTL_NOSLEEP))) {
    902 			printf("ciss driver stuffup in %s:%d: %s()\n",
    903 			       __FILE__, __LINE__, __func__);
    904 			xs->error = XS_DRIVER_STUFFUP;
    905 			scsipi_done(xs);
    906 			CISS_UNLOCK(sc, lock);
    907 			return;
    908 		}
    909 
    910 		CISS_UNLOCK(sc, lock);
    911 		break;
    912 	case ADAPTER_REQ_GROW_RESOURCES:
    913 		/*
    914 		 * Not supported.
    915 		 */
    916 		break;
    917 	case ADAPTER_REQ_SET_XFER_MODE:
    918 		/*
    919 		 * We can't change the transfer mode, but at least let
    920 		 * scsipi know what the adapter has negociated.
    921 		 */
    922 		/* FIXME: get xfer mode and write it into arg */
    923 		break;
    924 	}
    925 }
    926 
    927 int
    928 ciss_intr(void *v)
    929 {
    930 	struct ciss_softc *sc = v;
    931 	struct ciss_ccb *ccb;
    932 	ciss_lock_t lock;
    933 	u_int32_t id;
    934 	int hit = 0;
    935 
    936 	CISS_DPRINTF(CISS_D_INTR, ("intr "));
    937 
    938 	if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_ISR) & sc->iem))
    939 		return 0;
    940 
    941 	lock = CISS_LOCK(sc);
    942 	while ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ)) !=
    943 	    0xffffffff) {
    944 
    945 		ccb = (struct ciss_ccb *) ((char *)sc->ccbs + (id >> 2) * sc->ccblen);
    946 		ccb->ccb_cmd.id = htole32(id);
    947 		if (ccb->ccb_state == CISS_CCB_POLL) {
    948 			ccb->ccb_state = CISS_CCB_ONQ;
    949 			wakeup(ccb);
    950 		} else
    951 			ciss_done(ccb);
    952 
    953 		hit = 1;
    954 	}
    955 	CISS_UNLOCK(sc, lock);
    956 
    957 	CISS_DPRINTF(CISS_D_INTR, ("exit\n"));
    958 	return hit;
    959 }
    960 
    961 static void
    962 ciss_heartbeat(void *v)
    963 {
    964 	struct ciss_softc *sc = v;
    965 	u_int32_t hb;
    966 
    967 	hb = bus_space_read_4(sc->sc_iot, sc->cfg_ioh,
    968 	    sc->cfgoff + offsetof(struct ciss_config, heartbeat));
    969 	if (hb == sc->heartbeat)
    970 		panic("ciss: dead");	/* XX reset! */
    971 	else
    972 		sc->heartbeat = hb;
    973 
    974 	callout_schedule(&sc->sc_hb, hz * 3);
    975 }
    976 
    977 #if 0
    978 static void
    979 ciss_kthread(void *v)
    980 {
    981 	struct ciss_softc *sc = v;
    982 	ciss_lock_t lock;
    983 
    984 	for (;;) {
    985 		tsleep(sc, PRIBIO, device_xname(&sc->sc_dev), 0);
    986 
    987 		lock = CISS_LOCK(sc);
    988 
    989 
    990 
    991 		CISS_UNLOCK(sc, lock);
    992 	}
    993 }
    994 #endif
    995 
    996 static int
    997 ciss_scsi_ioctl(struct scsipi_channel *chan, u_long cmd,
    998     void *addr, int flag, struct proc *p)
    999 {
   1000 #if NBIO > 0
   1001 	return ciss_ioctl(chan->chan_adapter->adapt_dev, cmd, addr);
   1002 #else
   1003 	return ENOTTY;
   1004 #endif
   1005 }
   1006 
   1007 #if NBIO > 0
   1008 static int
   1009 ciss_ioctl(struct device *dev, u_long cmd, void *addr)	/* TODO */
   1010 {
   1011 	/* struct ciss_softc *sc = (struct ciss_softc *)dev; */
   1012 	ciss_lock_t lock;
   1013 	int error;
   1014 
   1015 	lock = CISS_LOCK(sc);
   1016 	switch (cmd) {
   1017 	case BIOCINQ:
   1018 	case BIOCVOL:
   1019 	case BIOCDISK:
   1020 	case BIOCALARM:
   1021 	case BIOCBLINK:
   1022 	case BIOCSETSTATE:
   1023 	default:
   1024 		CISS_DPRINTF(CISS_D_IOCTL, ("%s: invalid ioctl\n",
   1025 		    device_xname(&sc->sc_dev)));
   1026 		error = ENOTTY;
   1027 	}
   1028 	CISS_UNLOCK(sc, lock);
   1029 
   1030 	return error;
   1031 }
   1032 #endif
   1033