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