xref: /openbsd-src/sys/dev/ic/ciss.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: ciss.c,v 1.34 2009/04/29 08:24:26 reyk Exp $	*/
2 
3 /*
4  * Copyright (c) 2005,2006 Michael Shalayeff
5  * All rights reserved.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
16  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "bio.h"
21 
22 /* #define CISS_DEBUG */
23 
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/buf.h>
27 #include <sys/ioctl.h>
28 #include <sys/device.h>
29 #include <sys/kernel.h>
30 #include <sys/malloc.h>
31 #include <sys/proc.h>
32 #include <sys/kthread.h>
33 
34 #include <machine/bus.h>
35 
36 #include <scsi/scsi_all.h>
37 #include <scsi/scsi_disk.h>
38 #include <scsi/scsiconf.h>
39 
40 #include <dev/ic/cissreg.h>
41 #include <dev/ic/cissvar.h>
42 
43 #if NBIO > 0
44 #include <dev/biovar.h>
45 #endif
46 #include <sys/sensors.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 struct cfdriver ciss_cd = {
69 	NULL, "ciss", DV_DULL
70 };
71 
72 int	ciss_scsi_cmd(struct scsi_xfer *xs);
73 int	ciss_scsi_ioctl(struct scsi_link *link, u_long cmd,
74     caddr_t addr, int flag, struct proc *p);
75 void	cissminphys(struct buf *bp, struct scsi_link *sl);
76 
77 struct scsi_adapter ciss_switch = {
78 	ciss_scsi_cmd, cissminphys, NULL, NULL, ciss_scsi_ioctl
79 };
80 
81 struct scsi_device ciss_dev = {
82 	NULL, NULL, NULL, NULL
83 };
84 
85 int	ciss_scsi_raw_cmd(struct scsi_xfer *xs);
86 
87 struct scsi_adapter ciss_raw_switch = {
88 	ciss_scsi_raw_cmd, cissminphys, NULL, NULL,
89 };
90 
91 struct scsi_device ciss_raw_dev = {
92 	NULL, NULL, NULL, NULL
93 };
94 
95 #if NBIO > 0
96 int	ciss_ioctl(struct device *, u_long, caddr_t);
97 #endif
98 int	ciss_sync(struct ciss_softc *sc);
99 void	ciss_heartbeat(void *v);
100 void	ciss_shutdown(void *v);
101 void	ciss_kthread(void *v);
102 #ifndef SMALL_KERNEL
103 void	ciss_sensors(void *);
104 #endif
105 
106 struct ciss_ccb *ciss_get_ccb(struct ciss_softc *sc);
107 void	ciss_put_ccb(struct ciss_ccb *ccb);
108 int	ciss_cmd(struct ciss_ccb *ccb, int flags, int wait);
109 int	ciss_done(struct ciss_ccb *ccb);
110 int	ciss_error(struct ciss_ccb *ccb);
111 
112 struct ciss_ld *ciss_pdscan(struct ciss_softc *sc, int ld);
113 int	ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq);
114 int	ciss_ldmap(struct ciss_softc *sc);
115 int	ciss_ldid(struct ciss_softc *, int, struct ciss_ldid *);
116 int	ciss_ldstat(struct ciss_softc *, int, struct ciss_ldstat *);
117 int	ciss_pdid(struct ciss_softc *, u_int8_t, struct ciss_pdid *, int);
118 int	ciss_blink(struct ciss_softc *, int, int, int, struct ciss_blink *);
119 
120 struct ciss_ccb *
121 ciss_get_ccb(struct ciss_softc *sc)
122 {
123 	struct ciss_ccb *ccb;
124 
125 	if ((ccb = TAILQ_LAST(&sc->sc_free_ccb, ciss_queue_head))) {
126 		TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_link);
127 		ccb->ccb_state = CISS_CCB_READY;
128 	}
129 	return ccb;
130 }
131 
132 void
133 ciss_put_ccb(struct ciss_ccb *ccb)
134 {
135 	struct ciss_softc *sc = ccb->ccb_sc;
136 
137 	ccb->ccb_state = CISS_CCB_FREE;
138 	TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
139 }
140 
141 int
142 ciss_attach(struct ciss_softc *sc)
143 {
144 	struct scsibus_attach_args saa;
145 	struct scsibus_softc *scsibus;
146 	struct ciss_ccb *ccb;
147 	struct ciss_cmd *cmd;
148 	struct ciss_inquiry *inq;
149 	bus_dma_segment_t seg[1];
150 	int error, i, total, rseg, maxfer;
151 	ciss_lock_t lock;
152 	paddr_t pa;
153 
154 	bus_space_read_region_4(sc->iot, sc->cfg_ioh, sc->cfgoff,
155 	    (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
156 
157 	if (sc->cfg.signature != CISS_SIGNATURE) {
158 		printf(": bad sign 0x%08x\n", sc->cfg.signature);
159 		return -1;
160 	}
161 
162 	if (!(sc->cfg.methods & CISS_METH_SIMPL)) {
163 		printf(": not simple 0x%08x\n", sc->cfg.methods);
164 		return -1;
165 	}
166 
167 	sc->cfg.rmethod = CISS_METH_SIMPL;
168 	sc->cfg.paddr_lim = 0;			/* 32bit addrs */
169 	sc->cfg.int_delay = 0;			/* disable coalescing */
170 	sc->cfg.int_count = 0;
171 	strlcpy(sc->cfg.hostname, "HUMPPA", sizeof(sc->cfg.hostname));
172 	sc->cfg.driverf |= CISS_DRV_PRF;	/* enable prefetch */
173 	if (!sc->cfg.maxsg)
174 		sc->cfg.maxsg = MAXPHYS / PAGE_SIZE;
175 
176 	bus_space_write_region_4(sc->iot, sc->cfg_ioh, sc->cfgoff,
177 	    (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
178 	bus_space_barrier(sc->iot, sc->cfg_ioh, sc->cfgoff, sizeof(sc->cfg),
179 	    BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
180 
181 	bus_space_write_4(sc->iot, sc->ioh, CISS_IDB, CISS_IDB_CFG);
182 	bus_space_barrier(sc->iot, sc->ioh, CISS_IDB, 4,
183 	    BUS_SPACE_BARRIER_WRITE);
184 	for (i = 1000; i--; DELAY(1000)) {
185 		/* XXX maybe IDB is really 64bit? - hp dl380 needs this */
186 		(void)bus_space_read_4(sc->iot, sc->ioh, CISS_IDB + 4);
187 		if (!(bus_space_read_4(sc->iot, sc->ioh, CISS_IDB) & CISS_IDB_CFG))
188 			break;
189 		bus_space_barrier(sc->iot, sc->ioh, CISS_IDB, 4,
190 		    BUS_SPACE_BARRIER_READ);
191 	}
192 
193 	if (bus_space_read_4(sc->iot, sc->ioh, CISS_IDB) & CISS_IDB_CFG) {
194 		printf(": cannot set config\n");
195 		return -1;
196 	}
197 
198 	bus_space_read_region_4(sc->iot, sc->cfg_ioh, sc->cfgoff,
199 	    (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
200 
201 	if (!(sc->cfg.amethod & CISS_METH_SIMPL)) {
202 		printf(": cannot simplify 0x%08x\n", sc->cfg.amethod);
203 		return -1;
204 	}
205 
206 	/* i'm ready for you and i hope you're ready for me */
207 	for (i = 30000; i--; DELAY(1000)) {
208 		if (bus_space_read_4(sc->iot, sc->cfg_ioh, sc->cfgoff +
209 		    offsetof(struct ciss_config, amethod)) & CISS_METH_READY)
210 			break;
211 		bus_space_barrier(sc->iot, sc->cfg_ioh, sc->cfgoff +
212 		    offsetof(struct ciss_config, amethod), 4,
213 		    BUS_SPACE_BARRIER_READ);
214 	}
215 
216 	if (!(bus_space_read_4(sc->iot, sc->cfg_ioh, sc->cfgoff +
217 	    offsetof(struct ciss_config, amethod)) & CISS_METH_READY)) {
218 		printf(": she never came ready for me 0x%08x\n",
219 		    sc->cfg.amethod);
220 		return -1;
221 	}
222 
223 	sc->maxcmd = sc->cfg.maxcmd;
224 	sc->maxsg = sc->cfg.maxsg;
225 	if (sc->maxsg > MAXPHYS / PAGE_SIZE)
226 		sc->maxsg = MAXPHYS / PAGE_SIZE;
227 	i = sizeof(struct ciss_ccb) +
228 	    sizeof(ccb->ccb_cmd.sgl[0]) * (sc->maxsg - 1);
229 	for (sc->ccblen = 0x10; sc->ccblen < i; sc->ccblen <<= 1);
230 
231 	total = sc->ccblen * sc->maxcmd;
232 	if ((error = bus_dmamem_alloc(sc->dmat, total, PAGE_SIZE, 0,
233 	    sc->cmdseg, 1, &rseg, BUS_DMA_NOWAIT))) {
234 		printf(": cannot allocate CCBs (%d)\n", error);
235 		return -1;
236 	}
237 
238 	if ((error = bus_dmamem_map(sc->dmat, sc->cmdseg, rseg, total,
239 	    (caddr_t *)&sc->ccbs, BUS_DMA_NOWAIT))) {
240 		printf(": cannot map CCBs (%d)\n", error);
241 		return -1;
242 	}
243 	bzero(sc->ccbs, total);
244 
245 	if ((error = bus_dmamap_create(sc->dmat, total, 1,
246 	    total, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->cmdmap))) {
247 		printf(": cannot create CCBs dmamap (%d)\n", error);
248 		bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
249 		return -1;
250 	}
251 
252 	if ((error = bus_dmamap_load(sc->dmat, sc->cmdmap, sc->ccbs, total,
253 	    NULL, BUS_DMA_NOWAIT))) {
254 		printf(": cannot load CCBs dmamap (%d)\n", error);
255 		bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
256 		bus_dmamap_destroy(sc->dmat, sc->cmdmap);
257 		return -1;
258 	}
259 
260 	TAILQ_INIT(&sc->sc_ccbq);
261 	TAILQ_INIT(&sc->sc_ccbdone);
262 	TAILQ_INIT(&sc->sc_free_ccb);
263 
264 	maxfer = sc->maxsg * PAGE_SIZE;
265 	for (i = 0; total; i++, total -= sc->ccblen) {
266 		ccb = sc->ccbs + i * sc->ccblen;
267 		cmd = &ccb->ccb_cmd;
268 		pa = sc->cmdseg[0].ds_addr + i * sc->ccblen;
269 
270 		ccb->ccb_sc = sc;
271 		ccb->ccb_cmdpa = pa + offsetof(struct ciss_ccb, ccb_cmd);
272 		ccb->ccb_state = CISS_CCB_FREE;
273 
274 		cmd->id = htole32(i << 2);
275 		cmd->id_hi = htole32(0);
276 		cmd->sgin = sc->maxsg;
277 		cmd->sglen = htole16((u_int16_t)cmd->sgin);
278 		cmd->err_len = htole32(sizeof(ccb->ccb_err));
279 		pa += offsetof(struct ciss_ccb, ccb_err);
280 		cmd->err_pa = htole64((u_int64_t)pa);
281 
282 		if ((error = bus_dmamap_create(sc->dmat, maxfer, sc->maxsg,
283 		    maxfer, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
284 		    &ccb->ccb_dmamap)))
285 			break;
286 
287 		TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
288 	}
289 
290 	if (i < sc->maxcmd) {
291 		printf(": cannot create ccb#%d dmamap (%d)\n", i, error);
292 		if (i == 0) {
293 			/* TODO leaking cmd's dmamaps and shitz */
294 			bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
295 			bus_dmamap_destroy(sc->dmat, sc->cmdmap);
296 			return -1;
297 		}
298 	}
299 
300 	if ((error = bus_dmamem_alloc(sc->dmat, PAGE_SIZE, PAGE_SIZE, 0,
301 	    seg, 1, &rseg, BUS_DMA_NOWAIT))) {
302 		printf(": cannot allocate scratch buffer (%d)\n", error);
303 		return -1;
304 	}
305 
306 	if ((error = bus_dmamem_map(sc->dmat, seg, rseg, PAGE_SIZE,
307 	    (caddr_t *)&sc->scratch, BUS_DMA_NOWAIT))) {
308 		printf(": cannot map scratch buffer (%d)\n", error);
309 		return -1;
310 	}
311 	bzero(sc->scratch, PAGE_SIZE);
312 
313 	lock = CISS_LOCK_SCRATCH(sc);
314 	inq = sc->scratch;
315 	if (ciss_inq(sc, inq)) {
316 		printf(": adapter inquiry failed\n");
317 		CISS_UNLOCK_SCRATCH(sc, lock);
318 		bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
319 		bus_dmamap_destroy(sc->dmat, sc->cmdmap);
320 		return -1;
321 	}
322 
323 	if (!(inq->flags & CISS_INQ_BIGMAP)) {
324 		printf(": big map is not supported, flags=%b\n",
325 		    inq->flags, CISS_INQ_BITS);
326 		CISS_UNLOCK_SCRATCH(sc, lock);
327 		bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
328 		bus_dmamap_destroy(sc->dmat, sc->cmdmap);
329 		return -1;
330 	}
331 
332 	sc->maxunits = inq->numld;
333 	sc->nbus = inq->nscsi_bus;
334 	sc->ndrives = inq->buswidth? inq->buswidth : 256;
335 	printf(": %d LD%s, HW rev %d, FW %4.4s/%4.4s",
336 	    inq->numld, inq->numld == 1? "" : "s",
337 	    inq->hw_rev, inq->fw_running, inq->fw_stored);
338 	if (sc->cfg.methods & CISS_METH_FIFO64)
339 		printf(", 64bit fifo");
340 	else if (sc->cfg.methods & CISS_METH_FIFO64_RRO)
341 		printf(", 64bit fifo rro");
342 	printf("\n");
343 
344 	CISS_UNLOCK_SCRATCH(sc, lock);
345 
346 	timeout_set(&sc->sc_hb, ciss_heartbeat, sc);
347 	timeout_add_sec(&sc->sc_hb, 3);
348 
349 	/* map LDs */
350 	if (ciss_ldmap(sc)) {
351 		printf("%s: adapter LD map failed\n", sc->sc_dev.dv_xname);
352 		bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
353 		bus_dmamap_destroy(sc->dmat, sc->cmdmap);
354 		return -1;
355 	}
356 
357 	if (!(sc->sc_lds = malloc(sc->maxunits * sizeof(*sc->sc_lds),
358 	    M_DEVBUF, M_NOWAIT | M_ZERO))) {
359 		bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
360 		bus_dmamap_destroy(sc->dmat, sc->cmdmap);
361 		return -1;
362 	}
363 
364 	sc->sc_flush = CISS_FLUSH_ENABLE;
365 	if (!(sc->sc_sh = shutdownhook_establish(ciss_shutdown, sc))) {
366 		printf(": unable to establish shutdown hook\n");
367 		bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
368 		bus_dmamap_destroy(sc->dmat, sc->cmdmap);
369 		return -1;
370 	}
371 
372 #if 0
373 	if (kthread_create(ciss_kthread, sc, NULL, "%s", sc->sc_dev.dv_xname)) {
374 		printf(": unable to create kernel thread\n");
375 		shutdownhook_disestablish(sc->sc_sh);
376 		bus_dmamem_free(sc->dmat, sc->cmdseg, 1);
377 		bus_dmamap_destroy(sc->dmat, sc->cmdmap);
378 		return -1;
379 	}
380 #endif
381 
382 	sc->sc_link.device = &ciss_dev;
383 	sc->sc_link.adapter_softc = sc;
384 	sc->sc_link.openings = sc->maxcmd / (sc->maxunits? sc->maxunits : 1);
385 #if NBIO > 0
386 	/* XXX Reserve some ccb's for sensor and bioctl. */
387 	if (sc->maxunits < 2 && sc->sc_link.openings > 2)
388 		sc->sc_link.openings -= 2;
389 #endif
390 	sc->sc_link.adapter = &ciss_switch;
391 	sc->sc_link.adapter_target = sc->maxunits;
392 	sc->sc_link.adapter_buswidth = sc->maxunits;
393 	bzero(&saa, sizeof(saa));
394 	saa.saa_sc_link = &sc->sc_link;
395 	scsibus = (struct scsibus_softc *)config_found_sm(&sc->sc_dev,
396 	    &saa, scsiprint, NULL);
397 
398 #if 0
399 	sc->sc_link_raw.device = &ciss_raw_dev;
400 	sc->sc_link_raw.adapter_softc = sc;
401 	sc->sc_link.openings = sc->maxcmd / (sc->maxunits? sc->maxunits : 1);
402 	sc->sc_link_raw.adapter = &ciss_raw_switch;
403 	sc->sc_link_raw.adapter_target = sc->ndrives;
404 	sc->sc_link_raw.adapter_buswidth = sc->ndrives;
405 	bzero(&saa, sizeof(saa));
406 	saa.saa_sc_link = &sc->sc_link_raw;
407 	rawbus = (struct scsibus_softc *)config_found_sm(&sc->sc_dev,
408 	    &saa, scsiprint, NULL);
409 #endif
410 
411 #if NBIO > 0
412 	/* XXX for now we can only deal w/ one volume and need reserved ccbs. */
413 	if (!scsibus || sc->maxunits > 1 || sc->sc_link.openings == sc->maxcmd)
414 		return 0;
415 
416 	/* now map all the physdevs into their lds */
417 	/* XXX currently we assign all pf 'em into ld#0 */
418 	for (i = 0; i < sc->maxunits; i++)
419 		if (!(sc->sc_lds[i] = ciss_pdscan(sc, i)))
420 			return 0;
421 
422 	if (bio_register(&sc->sc_dev, ciss_ioctl) != 0)
423 		printf("%s: controller registration failed",
424 		    sc->sc_dev.dv_xname);
425 
426 	sc->sc_flags |= CISS_BIO;
427 #ifndef SMALL_KERNEL
428 	sc->sensors = malloc(sizeof(struct ksensor) * sc->maxunits,
429 	    M_DEVBUF, M_NOWAIT | M_ZERO);
430 	if (sc->sensors) {
431 		strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
432 		    sizeof(sc->sensordev.xname));
433 		for (i = 0; i < sc->maxunits;
434 		    sensor_attach(&sc->sensordev, &sc->sensors[i++])) {
435 			sc->sensors[i].type = SENSOR_DRIVE;
436 			sc->sensors[i].status = SENSOR_S_UNKNOWN;
437 			strlcpy(sc->sensors[i].desc, ((struct device *)
438 			    scsibus->sc_link[i][0]->device_softc)->dv_xname,
439 			    sizeof(sc->sensors[i].desc));
440 			strlcpy(sc->sc_lds[i]->xname, ((struct device *)
441 			    scsibus->sc_link[i][0]->device_softc)->dv_xname,
442 			    sizeof(sc->sc_lds[i]->xname));
443 		}
444 		if (sensor_task_register(sc, ciss_sensors, 10) == NULL)
445 			free(sc->sensors, M_DEVBUF);
446 		else
447 			sensordev_install(&sc->sensordev);
448 	}
449 #endif /* SMALL_KERNEL */
450 #endif /* BIO > 0 */
451 
452 	return 0;
453 }
454 
455 void
456 ciss_shutdown(void *v)
457 {
458 	struct ciss_softc *sc = v;
459 
460 	sc->sc_flush = CISS_FLUSH_DISABLE;
461 	timeout_del(&sc->sc_hb);
462 	ciss_sync(sc);
463 }
464 
465 void
466 cissminphys(struct buf *bp, struct scsi_link *sl)
467 {
468 #if 0	/* TODO */
469 #define	CISS_MAXFER	(PAGE_SIZE * (sc->maxsg + 1))
470 	if (bp->b_bcount > CISS_MAXFER)
471 		bp->b_bcount = CISS_MAXFER;
472 #endif
473 	minphys(bp);
474 }
475 
476 /*
477  * submit a command and optionally wait for completition.
478  * wait arg abuses SCSI_POLL|SCSI_NOSLEEP flags to request
479  * to wait (SCSI_POLL) and to allow tsleep() (!SCSI_NOSLEEP)
480  * instead of busy loop waiting
481  */
482 int
483 ciss_cmd(struct ciss_ccb *ccb, int flags, int wait)
484 {
485 	struct ciss_softc *sc = ccb->ccb_sc;
486 	struct ciss_cmd *cmd = &ccb->ccb_cmd;
487 	struct ciss_ccb *ccb1;
488 	bus_dmamap_t dmap = ccb->ccb_dmamap;
489 	u_int64_t addr;
490 	u_int32_t id;
491 	int i, tohz, error = 0;
492 
493 	if (ccb->ccb_state != CISS_CCB_READY) {
494 		printf("%s: ccb %d not ready state=%b\n", sc->sc_dev.dv_xname,
495 		    cmd->id, ccb->ccb_state, CISS_CCB_BITS);
496 		return (EINVAL);
497 	}
498 
499 	if (ccb->ccb_data) {
500 		bus_dma_segment_t *sgd;
501 
502 		if ((error = bus_dmamap_load(sc->dmat, dmap, ccb->ccb_data,
503 		    ccb->ccb_len, NULL, flags))) {
504 			if (error == EFBIG)
505 				printf("more than %d dma segs\n", sc->maxsg);
506 			else
507 				printf("error %d loading dma map\n", error);
508 			ciss_put_ccb(ccb);
509 			return (error);
510 		}
511 		cmd->sgin = dmap->dm_nsegs;
512 
513 		sgd = dmap->dm_segs;
514 		CISS_DPRINTF(CISS_D_DMA, ("data=%p/%u<0x%lx/%u",
515 		    ccb->ccb_data, ccb->ccb_len, sgd->ds_addr, sgd->ds_len));
516 
517 		for (i = 0; i < dmap->dm_nsegs; sgd++, i++) {
518 			cmd->sgl[i].addr_lo = htole32(sgd->ds_addr);
519 			cmd->sgl[i].addr_hi =
520 			    htole32((u_int64_t)sgd->ds_addr >> 32);
521 			cmd->sgl[i].len = htole32(sgd->ds_len);
522 			cmd->sgl[i].flags = htole32(0);
523 			if (i)
524 				CISS_DPRINTF(CISS_D_DMA,
525 				    (",0x%lx/%u", sgd->ds_addr, sgd->ds_len));
526 		}
527 
528 		CISS_DPRINTF(CISS_D_DMA, ("> "));
529 
530 		bus_dmamap_sync(sc->dmat, dmap, 0, dmap->dm_mapsize,
531 		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
532 	} else
533 		cmd->sgin = 0;
534 	cmd->sglen = htole16((u_int16_t)cmd->sgin);
535 	bzero(&ccb->ccb_err, sizeof(ccb->ccb_err));
536 
537 	bus_dmamap_sync(sc->dmat, sc->cmdmap, 0, sc->cmdmap->dm_mapsize,
538 	    BUS_DMASYNC_PREWRITE);
539 
540 	if ((wait & (SCSI_POLL|SCSI_NOSLEEP)) == (SCSI_POLL|SCSI_NOSLEEP))
541 		bus_space_write_4(sc->iot, sc->ioh, CISS_IMR,
542 		    bus_space_read_4(sc->iot, sc->ioh, CISS_IMR) | sc->iem);
543 
544 	TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
545 	ccb->ccb_state = CISS_CCB_ONQ;
546 	CISS_DPRINTF(CISS_D_CMD, ("submit=0x%x ", cmd->id));
547 	if (sc->cfg.methods & (CISS_METH_FIFO64|CISS_METH_FIFO64_RRO)) {
548 		/*
549 		 * Write the upper 32bits immediately before the lower
550 		 * 32bits and set bit 63 to indicate 64bit FIFO mode.
551 		 */
552 		addr = (u_int64_t)ccb->ccb_cmdpa;
553 		bus_space_write_4(sc->iot, sc->ioh, CISS_INQ64_HI,
554 		    (addr >> 32) | 0x80000000);
555 		bus_space_write_4(sc->iot, sc->ioh, CISS_INQ64_LO,
556 		    addr & 0x00000000ffffffffULL);
557 	} else
558 		bus_space_write_4(sc->iot, sc->ioh, CISS_INQ, ccb->ccb_cmdpa);
559 
560 	if (wait & SCSI_POLL) {
561 		struct timeval tv;
562 		int etick;
563 		CISS_DPRINTF(CISS_D_CMD, ("waiting "));
564 
565 		i = ccb->ccb_xs? ccb->ccb_xs->timeout : 60000;
566 		tv.tv_sec = i / 1000;
567 		tv.tv_usec = (i % 1000) * 1000;
568 		tohz = tvtohz(&tv);
569 		if (tohz == 0)
570 			tohz = 1;
571 		for (i *= 100, etick = tick + tohz; i--; ) {
572 			if (!(wait & SCSI_NOSLEEP)) {
573 				ccb->ccb_state = CISS_CCB_POLL;
574 				CISS_DPRINTF(CISS_D_CMD, ("tsleep(%d) ", tohz));
575 				if (tsleep(ccb, PRIBIO + 1, "ciss_cmd",
576 				    tohz) == EWOULDBLOCK) {
577 					break;
578 				}
579 				if (ccb->ccb_state != CISS_CCB_ONQ) {
580 					tohz = etick - tick;
581 					if (tohz <= 0)
582 						break;
583 					CISS_DPRINTF(CISS_D_CMD, ("T"));
584 					continue;
585 				}
586 				ccb1 = ccb;
587 			} else {
588 				DELAY(10);
589 
590 				if (!(bus_space_read_4(sc->iot, sc->ioh,
591 				    CISS_ISR) & sc->iem)) {
592 					CISS_DPRINTF(CISS_D_CMD, ("N"));
593 					continue;
594 				}
595 
596 				if (sc->cfg.methods & CISS_METH_FIFO64) {
597 					if (bus_space_read_4(sc->iot, sc->ioh,
598 					    CISS_OUTQ64_HI) == 0xffffffff) {
599 						CISS_DPRINTF(CISS_D_CMD, ("Q"));
600 						continue;
601 					}
602 					id = bus_space_read_4(sc->iot, sc->ioh,
603 					    CISS_OUTQ64_LO);
604 				} else if (sc->cfg.methods &
605 				    CISS_METH_FIFO64_RRO) {
606 					id = bus_space_read_4(sc->iot, sc->ioh,
607 					    CISS_OUTQ64_LO);
608 					if (id == 0xffffffff) {
609 						CISS_DPRINTF(CISS_D_CMD, ("Q"));
610 						continue;
611 					}
612 					(void)bus_space_read_4(sc->iot,
613 					    sc->ioh, CISS_OUTQ64_HI);
614 				} else {
615 					id = bus_space_read_4(sc->iot, sc->ioh,
616 					    CISS_OUTQ);
617 					if (id == 0xffffffff) {
618 						CISS_DPRINTF(CISS_D_CMD, ("Q"));
619 						continue;
620 					}
621 				}
622 
623 				CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id));
624 				ccb1 = sc->ccbs + (id >> 2) * sc->ccblen;
625 				ccb1->ccb_cmd.id = htole32(id);
626 				ccb1->ccb_cmd.id_hi = htole32(0);
627 			}
628 
629 			error = ciss_done(ccb1);
630 			if (ccb1 == ccb)
631 				break;
632 		}
633 
634 		/* if never got a chance to be done above... */
635 		if (ccb->ccb_state != CISS_CCB_FREE) {
636 			ccb->ccb_err.cmd_stat = CISS_ERR_TMO;
637 			error = ciss_done(ccb);
638 		}
639 
640 		CISS_DPRINTF(CISS_D_CMD, ("done %d:%d",
641 		    ccb->ccb_err.cmd_stat, ccb->ccb_err.scsi_stat));
642 	}
643 
644 	if ((wait & (SCSI_POLL|SCSI_NOSLEEP)) == (SCSI_POLL|SCSI_NOSLEEP))
645 		bus_space_write_4(sc->iot, sc->ioh, CISS_IMR,
646 		    bus_space_read_4(sc->iot, sc->ioh, CISS_IMR) & ~sc->iem);
647 
648 	return (error);
649 }
650 
651 int
652 ciss_done(struct ciss_ccb *ccb)
653 {
654 	struct ciss_softc *sc = ccb->ccb_sc;
655 	struct scsi_xfer *xs = ccb->ccb_xs;
656 	ciss_lock_t lock;
657 	int error = 0;
658 
659 	CISS_DPRINTF(CISS_D_CMD, ("ciss_done(%p) ", ccb));
660 
661 	if (ccb->ccb_state != CISS_CCB_ONQ) {
662 		printf("%s: unqueued ccb %p ready, state=%b\n",
663 		    sc->sc_dev.dv_xname, ccb, ccb->ccb_state, CISS_CCB_BITS);
664 		return 1;
665 	}
666 
667 	lock = CISS_LOCK(sc);
668 	ccb->ccb_state = CISS_CCB_READY;
669 	TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link);
670 
671 	if (ccb->ccb_cmd.id & CISS_CMD_ERR)
672 		error = ciss_error(ccb);
673 
674 	if (ccb->ccb_data) {
675 		bus_dmamap_sync(sc->dmat, ccb->ccb_dmamap, 0,
676 		    ccb->ccb_dmamap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?
677 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
678 		bus_dmamap_unload(sc->dmat, ccb->ccb_dmamap);
679 		ccb->ccb_xs = NULL;
680 		ccb->ccb_data = NULL;
681 	}
682 
683 	ciss_put_ccb(ccb);
684 
685 	if (xs) {
686 		xs->resid = 0;
687 		xs->flags |= ITSDONE;
688 		CISS_DPRINTF(CISS_D_CMD, ("scsi_done(%p) ", xs));
689 		scsi_done(xs);
690 	}
691 	CISS_UNLOCK(sc, lock);
692 
693 	return error;
694 }
695 
696 int
697 ciss_error(struct ciss_ccb *ccb)
698 {
699 	struct ciss_softc *sc = ccb->ccb_sc;
700 	struct ciss_error *err = &ccb->ccb_err;
701 	struct scsi_xfer *xs = ccb->ccb_xs;
702 	int rv;
703 
704 	switch ((rv = letoh16(err->cmd_stat))) {
705 	case CISS_ERR_OK:
706 		rv = 0;
707 		break;
708 
709 	case CISS_ERR_INVCMD:
710 		printf("%s: invalid cmd 0x%x: 0x%x is not valid @ 0x%x[%d]\n",
711 		    sc->sc_dev.dv_xname, ccb->ccb_cmd.id,
712 		    err->err_info, err->err_type[3], err->err_type[2]);
713 		if (xs) {
714 			bzero(&xs->sense, sizeof(xs->sense));
715 			xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
716 			xs->sense.flags = SKEY_ILLEGAL_REQUEST;
717 			xs->sense.add_sense_code = 0x24; /* ill field */
718 			xs->error = XS_SENSE;
719 		}
720 		rv = EIO;
721 		break;
722 
723 	case CISS_ERR_TMO:
724 		xs->error = XS_TIMEOUT;
725 		rv = ETIMEDOUT;
726 		break;
727 
728 	default:
729 		if (xs) {
730 			switch (err->scsi_stat) {
731 			case SCSI_CHECK:
732 				xs->error = XS_SENSE;
733 				bcopy(&err->sense[0], &xs->sense,
734 				    sizeof(xs->sense));
735 				rv = EIO;
736 				break;
737 
738 			case SCSI_BUSY:
739 				xs->error = XS_BUSY;
740 				rv = EBUSY;
741 				break;
742 
743 			default:
744 				CISS_DPRINTF(CISS_D_ERR, ("%s: "
745 				    "cmd_stat %x scsi_stat 0x%x\n",
746 				    sc->sc_dev.dv_xname, rv, err->scsi_stat));
747 				xs->error = XS_DRIVER_STUFFUP;
748 				rv = EIO;
749 				break;
750 			}
751 			xs->resid = letoh32(err->resid);
752 		} else
753 			rv = EIO;
754 	}
755 	ccb->ccb_cmd.id &= htole32(~3);
756 
757 	return rv;
758 }
759 
760 int
761 ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq)
762 {
763 	struct ciss_ccb *ccb;
764 	struct ciss_cmd *cmd;
765 
766 	ccb = ciss_get_ccb(sc);
767 	ccb->ccb_len = sizeof(*inq);
768 	ccb->ccb_data = inq;
769 	cmd = &ccb->ccb_cmd;
770 	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
771 	cmd->tgt2 = 0;
772 	cmd->cdblen = 10;
773 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
774 	cmd->tmo = htole16(0);
775 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
776 	cmd->cdb[0] = CISS_CMD_CTRL_GET;
777 	cmd->cdb[6] = CISS_CMS_CTRL_CTRL;
778 	cmd->cdb[7] = sizeof(*inq) >> 8;	/* biiiig endian */
779 	cmd->cdb[8] = sizeof(*inq) & 0xff;
780 
781 	return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP);
782 }
783 
784 int
785 ciss_ldmap(struct ciss_softc *sc)
786 {
787 	struct ciss_ccb *ccb;
788 	struct ciss_cmd *cmd;
789 	struct ciss_ldmap *lmap;
790 	ciss_lock_t lock;
791 	int total, rv;
792 
793 	lock = CISS_LOCK_SCRATCH(sc);
794 	lmap = sc->scratch;
795 	lmap->size = htobe32(sc->maxunits * sizeof(lmap->map));
796 	total = sizeof(*lmap) + (sc->maxunits - 1) * sizeof(lmap->map);
797 
798 	ccb = ciss_get_ccb(sc);
799 	ccb->ccb_len = total;
800 	ccb->ccb_data = lmap;
801 	cmd = &ccb->ccb_cmd;
802 	cmd->tgt = CISS_CMD_MODE_PERIPH;
803 	cmd->tgt2 = 0;
804 	cmd->cdblen = 12;
805 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
806 	cmd->tmo = htole16(30);
807 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
808 	cmd->cdb[0] = CISS_CMD_LDMAP;
809 	cmd->cdb[8] = total >> 8;	/* biiiig endian */
810 	cmd->cdb[9] = total & 0xff;
811 
812 	rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP);
813 	CISS_UNLOCK_SCRATCH(sc, lock);
814 
815 	if (rv)
816 		return rv;
817 
818 	CISS_DPRINTF(CISS_D_MISC, ("lmap %x:%x\n",
819 	    lmap->map[0].tgt, lmap->map[0].tgt2));
820 
821 	return 0;
822 }
823 
824 int
825 ciss_sync(struct ciss_softc *sc)
826 {
827 	struct ciss_ccb *ccb;
828 	struct ciss_cmd *cmd;
829 	struct ciss_flush *flush;
830 	ciss_lock_t lock;
831 	int rv;
832 
833 	lock = CISS_LOCK_SCRATCH(sc);
834 	flush = sc->scratch;
835 	bzero(flush, sizeof(*flush));
836 	flush->flush = sc->sc_flush;
837 
838 	ccb = ciss_get_ccb(sc);
839 	ccb->ccb_len = sizeof(*flush);
840 	ccb->ccb_data = flush;
841 	cmd = &ccb->ccb_cmd;
842 	cmd->tgt = CISS_CMD_MODE_PERIPH;
843 	cmd->tgt2 = 0;
844 	cmd->cdblen = 10;
845 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT;
846 	cmd->tmo = htole16(0);
847 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
848 	cmd->cdb[0] = CISS_CMD_CTRL_SET;
849 	cmd->cdb[6] = CISS_CMS_CTRL_FLUSH;
850 	cmd->cdb[7] = sizeof(*flush) >> 8;	/* biiiig endian */
851 	cmd->cdb[8] = sizeof(*flush) & 0xff;
852 
853 	rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL|SCSI_NOSLEEP);
854 	CISS_UNLOCK_SCRATCH(sc, lock);
855 
856 	return rv;
857 }
858 
859 int
860 ciss_scsi_raw_cmd(struct scsi_xfer *xs)	/* TODO */
861 {
862 	struct scsi_link *link = xs->sc_link;
863 	struct ciss_rawsoftc *rsc = link->adapter_softc;
864 	struct ciss_softc *sc = rsc->sc_softc;
865 	struct ciss_ccb *ccb;
866 	struct ciss_cmd *cmd;
867 	ciss_lock_t lock;
868 
869 	CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_raw_cmd "));
870 
871 	lock = CISS_LOCK(sc);
872 	if (xs->cmdlen > CISS_MAX_CDB) {
873 		CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs));
874 		bzero(&xs->sense, sizeof(xs->sense));
875 		xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
876 		xs->sense.flags = SKEY_ILLEGAL_REQUEST;
877 		xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */
878 		xs->error = XS_SENSE;
879 		scsi_done(xs);
880 		CISS_UNLOCK(sc, lock);
881 		return (COMPLETE);
882 	}
883 
884 	xs->error = XS_NOERROR;
885 
886 	/* TODO check this target has not yet employed w/ any volume */
887 
888 	ccb = ciss_get_ccb(sc);
889 	cmd = &ccb->ccb_cmd;
890 	ccb->ccb_len = xs->datalen;
891 	ccb->ccb_data = xs->data;
892 	ccb->ccb_xs = xs;
893 
894 
895 
896 	cmd->cdblen = xs->cmdlen;
897 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL;
898 	if (xs->flags & SCSI_DATA_IN)
899 		cmd->flags |= CISS_CDB_IN;
900 	else if (xs->flags & SCSI_DATA_OUT)
901 		cmd->flags |= CISS_CDB_OUT;
902 	cmd->tmo = htole16(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 
906 	if (ciss_cmd(ccb, BUS_DMA_WAITOK,
907 	    xs->flags & (SCSI_POLL|SCSI_NOSLEEP))) {
908 		xs->error = XS_DRIVER_STUFFUP;
909 		scsi_done(xs);
910 		CISS_UNLOCK(sc, lock);
911 		return (COMPLETE);
912 	}
913 
914 	CISS_UNLOCK(sc, lock);
915 	return xs->flags & SCSI_POLL? COMPLETE : SUCCESSFULLY_QUEUED;
916 }
917 
918 int
919 ciss_scsi_cmd(struct scsi_xfer *xs)
920 {
921 	struct scsi_link *link = xs->sc_link;
922 	struct ciss_softc *sc = link->adapter_softc;
923 	u_int8_t target = link->target;
924 	struct ciss_ccb *ccb;
925 	struct ciss_cmd *cmd;
926 	ciss_lock_t lock;
927 
928 	CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_cmd "));
929 
930 	lock = CISS_LOCK(sc);
931 	if (xs->cmdlen > CISS_MAX_CDB) {
932 		CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs));
933 		bzero(&xs->sense, sizeof(xs->sense));
934 		xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
935 		xs->sense.flags = SKEY_ILLEGAL_REQUEST;
936 		xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */
937 		xs->error = XS_SENSE;
938 		scsi_done(xs);
939 		CISS_UNLOCK(sc, lock);
940 		return (COMPLETE);
941 	}
942 
943 	xs->error = XS_NOERROR;
944 
945 	/* XXX emulate SYNCHRONIZE_CACHE ??? */
946 
947 	ccb = ciss_get_ccb(sc);
948 	cmd = &ccb->ccb_cmd;
949 	ccb->ccb_len = xs->datalen;
950 	ccb->ccb_data = xs->data;
951 	ccb->ccb_xs = xs;
952 	cmd->tgt = CISS_CMD_MODE_LD | target;
953 	cmd->tgt2 = 0;
954 	cmd->cdblen = xs->cmdlen;
955 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL;
956 	if (xs->flags & SCSI_DATA_IN)
957 		cmd->flags |= CISS_CDB_IN;
958 	else if (xs->flags & SCSI_DATA_OUT)
959 		cmd->flags |= CISS_CDB_OUT;
960 	cmd->tmo = htole16(xs->timeout < 1000? 1 : xs->timeout / 1000);
961 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
962 	bcopy(xs->cmd, &cmd->cdb[0], CISS_MAX_CDB);
963 
964 	if (ciss_cmd(ccb, BUS_DMA_WAITOK,
965 	    xs->flags & (SCSI_POLL|SCSI_NOSLEEP))) {
966 		xs->error = XS_DRIVER_STUFFUP;
967 		scsi_done(xs);
968 		CISS_UNLOCK(sc, lock);
969 		return (COMPLETE);
970 	}
971 
972 	CISS_UNLOCK(sc, lock);
973 	return xs->flags & SCSI_POLL? COMPLETE : SUCCESSFULLY_QUEUED;
974 }
975 
976 int
977 ciss_intr(void *v)
978 {
979 	struct ciss_softc *sc = v;
980 	struct ciss_ccb *ccb;
981 	ciss_lock_t lock;
982 	bus_size_t reg;
983 	u_int32_t id;
984 	int hit = 0;
985 
986 	CISS_DPRINTF(CISS_D_INTR, ("intr "));
987 
988 	if (!(bus_space_read_4(sc->iot, sc->ioh, CISS_ISR) & sc->iem))
989 		return 0;
990 
991 	lock = CISS_LOCK(sc);
992 
993 	if (sc->cfg.methods & CISS_METH_FIFO64)
994 		reg = CISS_OUTQ64_HI;
995 	else if (sc->cfg.methods & CISS_METH_FIFO64_RRO)
996 		reg = CISS_OUTQ64_LO;
997 	else
998 		reg = CISS_OUTQ;
999 	while ((id = bus_space_read_4(sc->iot, sc->ioh, reg)) != 0xffffffff) {
1000 		if (reg == CISS_OUTQ64_HI)
1001 			id = bus_space_read_4(sc->iot, sc->ioh,
1002 			    CISS_OUTQ64_LO);
1003 		else if (reg == CISS_OUTQ64_LO)
1004 			(void)bus_space_read_4(sc->iot, sc->ioh,
1005 			    CISS_OUTQ64_HI);
1006 		ccb = sc->ccbs + (id >> 2) * sc->ccblen;
1007 		ccb->ccb_cmd.id = htole32(id);
1008 		ccb->ccb_cmd.id_hi = htole32(0); /* ignore the upper 32bits */
1009 		if (ccb->ccb_state == CISS_CCB_POLL) {
1010 			ccb->ccb_state = CISS_CCB_ONQ;
1011 			wakeup(ccb);
1012 		} else
1013 			ciss_done(ccb);
1014 
1015 		hit = 1;
1016 	}
1017 	CISS_UNLOCK(sc, lock);
1018 
1019 	CISS_DPRINTF(CISS_D_INTR, ("exit "));
1020 	return hit;
1021 }
1022 
1023 void
1024 ciss_heartbeat(void *v)
1025 {
1026 	struct ciss_softc *sc = v;
1027 	u_int32_t hb;
1028 
1029 	hb = bus_space_read_4(sc->iot, sc->cfg_ioh,
1030 	    sc->cfgoff + offsetof(struct ciss_config, heartbeat));
1031 	if (hb == sc->heartbeat)
1032 		panic("%s: dead", sc->sc_dev.dv_xname);	/* XXX reset! */
1033 	else
1034 		sc->heartbeat = hb;
1035 
1036 	timeout_add_sec(&sc->sc_hb, 3);
1037 }
1038 
1039 void
1040 ciss_kthread(void *v)
1041 {
1042 	struct ciss_softc *sc = v;
1043 	ciss_lock_t lock;
1044 
1045 	for (;;) {
1046 		tsleep(sc, PRIBIO, sc->sc_dev.dv_xname, 0);
1047 
1048 		lock = CISS_LOCK(sc);
1049 
1050 
1051 
1052 		CISS_UNLOCK(sc, lock);
1053 	}
1054 }
1055 
1056 int
1057 ciss_scsi_ioctl(struct scsi_link *link, u_long cmd,
1058     caddr_t addr, int flag, struct proc *p)
1059 {
1060 #if NBIO > 0
1061 	return ciss_ioctl(link->adapter_softc, cmd, addr);
1062 #else
1063 	return ENOTTY;
1064 #endif
1065 }
1066 
1067 #if NBIO > 0
1068 const int ciss_level[] = { 0, 4, 1, 5, 51, 7 };
1069 const int ciss_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE,
1070     BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED,
1071     BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING,
1072     BIOC_SVOFFLINE, BIOC_SVBUILDING };
1073 
1074 int
1075 ciss_ioctl(struct device *dev, u_long cmd, caddr_t addr)
1076 {
1077 	struct ciss_softc *sc = (struct ciss_softc *)dev;
1078 	struct bioc_inq *bi;
1079 	struct bioc_vol *bv;
1080 	struct bioc_disk *bd;
1081 	struct bioc_blink *bb;
1082 	/* struct bioc_alarm *ba; */
1083 	/* struct bioc_setstate *bss; */
1084 	struct ciss_ldid *ldid;
1085 	struct ciss_ldstat *ldstat;
1086 	struct ciss_pdid *pdid;
1087 	struct ciss_blink *blink;
1088 	struct ciss_ld *ldp;
1089 	ciss_lock_t lock;
1090 	u_int8_t drv;
1091 	int ld, pd, error = 0;
1092 	u_int blks;
1093 
1094 	if (!(sc->sc_flags & CISS_BIO))
1095 		return ENOTTY;
1096 
1097 	lock = CISS_LOCK(sc);
1098 	switch (cmd) {
1099 	case BIOCINQ:
1100 		bi = (struct bioc_inq *)addr;
1101 		strlcpy(bi->bi_dev, sc->sc_dev.dv_xname, sizeof(bi->bi_dev));
1102 		bi->bi_novol = sc->maxunits;
1103 		bi->bi_nodisk = sc->ndrives;
1104 		break;
1105 
1106 	case BIOCVOL:
1107 		bv = (struct bioc_vol *)addr;
1108 		if (bv->bv_volid > sc->maxunits) {
1109 			error = EINVAL;
1110 			break;
1111 		}
1112 		ldp = sc->sc_lds[bv->bv_volid];
1113 		if (!ldp)
1114 			return EINVAL;
1115 		ldid = sc->scratch;
1116 		if ((error = ciss_ldid(sc, bv->bv_volid, ldid)))
1117 			break;
1118 		/* params 30:88:ff:00:00:00:00:00:00:00:00:00:00:00:20:00 */
1119 		bv->bv_status = BIOC_SVINVALID;
1120 		blks = (u_int)letoh16(ldid->nblocks[1]) << 16 |
1121 		    letoh16(ldid->nblocks[0]);
1122 		bv->bv_size = blks * (u_quad_t)letoh16(ldid->blksize);
1123 		bv->bv_level = ciss_level[ldid->type];
1124 		bv->bv_nodisk = ldp->ndrives;
1125 		strlcpy(bv->bv_dev, ldp->xname, sizeof(bv->bv_dev));
1126 		strlcpy(bv->bv_vendor, "CISS", sizeof(bv->bv_vendor));
1127 		ldstat = sc->scratch;
1128 		bzero(ldstat, sizeof(*ldstat));
1129 		if ((error = ciss_ldstat(sc, bv->bv_volid, ldstat)))
1130 			break;
1131 		bv->bv_percent = -1;
1132 		bv->bv_seconds = 0;
1133 		if (ldstat->stat < sizeof(ciss_stat)/sizeof(ciss_stat[0]))
1134 			bv->bv_status = ciss_stat[ldstat->stat];
1135 		if (bv->bv_status == BIOC_SVREBUILD ||
1136 		    bv->bv_status == BIOC_SVBUILDING)
1137 			bv->bv_percent = (blks -
1138 			    (((u_int)ldstat->prog[3] << 24) |
1139 			    ((u_int)ldstat->prog[2] << 16) |
1140 			    ((u_int)ldstat->prog[1] << 8) |
1141 			    (u_int)ldstat->prog[0])) * 100ULL / blks;
1142 		break;
1143 
1144 	case BIOCDISK:
1145 		bd = (struct bioc_disk *)addr;
1146 		if (bd->bd_volid > sc->maxunits) {
1147 			error = EINVAL;
1148 			break;
1149 		}
1150 		ldp = sc->sc_lds[bd->bd_volid];
1151 		if (!ldp || (pd = bd->bd_diskid) > ldp->ndrives) {
1152 			error = EINVAL;
1153 			break;
1154 		}
1155 		ldstat = sc->scratch;
1156 		if ((error = ciss_ldstat(sc, bd->bd_volid, ldstat)))
1157 			break;
1158 		bd->bd_status = -1;
1159 		if (ldstat->stat == CISS_LD_REBLD &&
1160 		    ldstat->bigrebuild == ldp->tgts[pd])
1161 			bd->bd_status = BIOC_SDREBUILD;
1162 		if (ciss_bitset(ldp->tgts[pd] & (~CISS_BIGBIT),
1163 		    ldstat->bigfailed)) {
1164 			bd->bd_status = BIOC_SDFAILED;
1165 			bd->bd_size = 0;
1166 			bd->bd_channel = (ldp->tgts[pd] & (~CISS_BIGBIT)) /
1167 			    sc->ndrives;
1168 			bd->bd_target = ldp->tgts[pd] % sc->ndrives;
1169 			bd->bd_lun = 0;
1170 			bd->bd_vendor[0] = '\0';
1171 			bd->bd_serial[0] = '\0';
1172 			bd->bd_procdev[0] = '\0';
1173 		} else {
1174 			pdid = sc->scratch;
1175 			if ((error = ciss_pdid(sc, ldp->tgts[pd], pdid,
1176 			    SCSI_POLL)))
1177 				break;
1178 			if (bd->bd_status < 0) {
1179 				if (pdid->config & CISS_PD_SPARE)
1180 					bd->bd_status = BIOC_SDHOTSPARE;
1181 				else if (pdid->present & CISS_PD_PRESENT)
1182 					bd->bd_status = BIOC_SDONLINE;
1183 				else
1184 					bd->bd_status = BIOC_SDINVALID;
1185 			}
1186 			bd->bd_size = (u_int64_t)letoh32(pdid->nblocks) *
1187 			    letoh16(pdid->blksz);
1188 			bd->bd_channel = pdid->bus;
1189 			bd->bd_target = pdid->target;
1190 			bd->bd_lun = 0;
1191 			strlcpy(bd->bd_vendor, pdid->model,
1192 			    sizeof(bd->bd_vendor));
1193 			strlcpy(bd->bd_serial, pdid->serial,
1194 			    sizeof(bd->bd_serial));
1195 			bd->bd_procdev[0] = '\0';
1196 		}
1197 		break;
1198 
1199 	case BIOCBLINK:
1200 		bb = (struct bioc_blink *)addr;
1201 		blink = sc->scratch;
1202 		error = EINVAL;
1203 		/* XXX workaround completely dumb scsi addressing */
1204 		for (ld = 0; ld < sc->maxunits; ld++) {
1205 			ldp = sc->sc_lds[ld];
1206 			if (!ldp)
1207 				continue;
1208 			if (sc->ndrives == 256)
1209 				drv = bb->bb_target;
1210 			else
1211 				drv = CISS_BIGBIT +
1212 				    bb->bb_channel * sc->ndrives +
1213 				    bb->bb_target;
1214 			for (pd = 0; pd < ldp->ndrives; pd++)
1215 				if (ldp->tgts[pd] == drv)
1216 					error = ciss_blink(sc, ld, pd,
1217 					    bb->bb_status, blink);
1218 		}
1219 		break;
1220 
1221 	case BIOCALARM:
1222 	case BIOCSETSTATE:
1223 	default:
1224 		CISS_DPRINTF(CISS_D_IOCTL, ("%s: invalid ioctl\n",
1225 		    sc->sc_dev.dv_xname));
1226 		error = ENOTTY;
1227 	}
1228 	CISS_UNLOCK(sc, lock);
1229 
1230 	return error;
1231 }
1232 
1233 #ifndef SMALL_KERNEL
1234 void
1235 ciss_sensors(void *v)
1236 {
1237 	struct ciss_softc *sc = v;
1238 	struct ciss_ldstat *ldstat;
1239 	int i, error;
1240 
1241 	for (i = 0; i < sc->maxunits; i++) {
1242 		ldstat = sc->scratch;
1243 		if ((error = ciss_ldstat(sc, i, ldstat))) {
1244 			sc->sensors[i].value = 0;
1245 			sc->sensors[i].status = SENSOR_S_UNKNOWN;
1246 			continue;
1247 		}
1248 
1249 		switch (ldstat->stat) {
1250 		case CISS_LD_OK:
1251 			sc->sensors[i].value = SENSOR_DRIVE_ONLINE;
1252 			sc->sensors[i].status = SENSOR_S_OK;
1253 			break;
1254 
1255 		case CISS_LD_DEGRAD:
1256 			sc->sensors[i].value = SENSOR_DRIVE_PFAIL;
1257 			sc->sensors[i].status = SENSOR_S_WARN;
1258 			break;
1259 
1260 		case CISS_LD_EXPND:
1261 		case CISS_LD_QEXPND:
1262 		case CISS_LD_RBLDRD:
1263 		case CISS_LD_REBLD:
1264 			sc->sensors[i].value = SENSOR_DRIVE_REBUILD;
1265 			sc->sensors[i].status = SENSOR_S_WARN;
1266 			break;
1267 
1268 		case CISS_LD_NORDY:
1269 		case CISS_LD_PDINV:
1270 		case CISS_LD_PDUNC:
1271 		case CISS_LD_FAILED:
1272 		case CISS_LD_UNCONF:
1273 			sc->sensors[i].value = SENSOR_DRIVE_FAIL;
1274 			sc->sensors[i].status = SENSOR_S_CRIT;
1275 			break;
1276 
1277 		default:
1278 			sc->sensors[i].value = 0;
1279 			sc->sensors[i].status = SENSOR_S_UNKNOWN;
1280 		}
1281 	}
1282 }
1283 #endif /* SMALL_KERNEL */
1284 
1285 int
1286 ciss_ldid(struct ciss_softc *sc, int target, struct ciss_ldid *id)
1287 {
1288 	struct ciss_ccb *ccb;
1289 	struct ciss_cmd *cmd;
1290 
1291 	ccb = ciss_get_ccb(sc);
1292 	if (ccb == NULL)
1293 		return ENOMEM;
1294 	ccb->ccb_len = sizeof(*id);
1295 	ccb->ccb_data = id;
1296 	ccb->ccb_xs = NULL;
1297 	cmd = &ccb->ccb_cmd;
1298 	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
1299 	cmd->tgt2 = 0;
1300 	cmd->cdblen = 10;
1301 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
1302 	cmd->tmo = htole16(0);
1303 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
1304 	cmd->cdb[0] = CISS_CMD_CTRL_GET;
1305 	cmd->cdb[5] = target;
1306 	cmd->cdb[6] = CISS_CMS_CTRL_LDIDEXT;
1307 	cmd->cdb[7] = sizeof(*id) >> 8;	/* biiiig endian */
1308 	cmd->cdb[8] = sizeof(*id) & 0xff;
1309 
1310 	return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL);
1311 }
1312 
1313 int
1314 ciss_ldstat(struct ciss_softc *sc, int target, struct ciss_ldstat *stat)
1315 {
1316 	struct ciss_ccb *ccb;
1317 	struct ciss_cmd *cmd;
1318 
1319 	ccb = ciss_get_ccb(sc);
1320 	if (ccb == NULL)
1321 		return ENOMEM;
1322 	ccb->ccb_len = sizeof(*stat);
1323 	ccb->ccb_data = stat;
1324 	ccb->ccb_xs = NULL;
1325 	cmd = &ccb->ccb_cmd;
1326 	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
1327 	cmd->tgt2 = 0;
1328 	cmd->cdblen = 10;
1329 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
1330 	cmd->tmo = htole16(0);
1331 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
1332 	cmd->cdb[0] = CISS_CMD_CTRL_GET;
1333 	cmd->cdb[5] = target;
1334 	cmd->cdb[6] = CISS_CMS_CTRL_LDSTAT;
1335 	cmd->cdb[7] = sizeof(*stat) >> 8;	/* biiiig endian */
1336 	cmd->cdb[8] = sizeof(*stat) & 0xff;
1337 
1338 	return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL);
1339 }
1340 
1341 int
1342 ciss_pdid(struct ciss_softc *sc, u_int8_t drv, struct ciss_pdid *id, int wait)
1343 {
1344 	struct ciss_ccb *ccb;
1345 	struct ciss_cmd *cmd;
1346 
1347 	ccb = ciss_get_ccb(sc);
1348 	if (ccb == NULL)
1349 		return ENOMEM;
1350 	ccb->ccb_len = sizeof(*id);
1351 	ccb->ccb_data = id;
1352 	ccb->ccb_xs = NULL;
1353 	cmd = &ccb->ccb_cmd;
1354 	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
1355 	cmd->tgt2 = 0;
1356 	cmd->cdblen = 10;
1357 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
1358 	cmd->tmo = htole16(0);
1359 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
1360 	cmd->cdb[0] = CISS_CMD_CTRL_GET;
1361 	cmd->cdb[2] = drv;
1362 	cmd->cdb[6] = CISS_CMS_CTRL_PDID;
1363 	cmd->cdb[7] = sizeof(*id) >> 8;	/* biiiig endian */
1364 	cmd->cdb[8] = sizeof(*id) & 0xff;
1365 
1366 	return ciss_cmd(ccb, BUS_DMA_NOWAIT, wait);
1367 }
1368 
1369 
1370 struct ciss_ld *
1371 ciss_pdscan(struct ciss_softc *sc, int ld)
1372 {
1373 	struct ciss_pdid *pdid;
1374 	struct ciss_ld *ldp;
1375 	u_int8_t drv, buf[128];
1376 	int i, j, k = 0;
1377 
1378 	pdid = sc->scratch;
1379 	if (sc->ndrives == 256) {
1380 		for (i = 0; i < CISS_BIGBIT; i++)
1381 			if (!ciss_pdid(sc, i, pdid, SCSI_NOSLEEP|SCSI_POLL) &&
1382 			    (pdid->present & CISS_PD_PRESENT))
1383 				buf[k++] = i;
1384 	} else
1385 		for (i = 0; i < sc->nbus; i++)
1386 			for (j = 0; j < sc->ndrives; j++) {
1387 				drv = CISS_BIGBIT + i * sc->ndrives + j;
1388 				if (!ciss_pdid(sc, drv, pdid,
1389 				    SCSI_NOSLEEP|SCSI_POLL))
1390 					buf[k++] = drv;
1391 			}
1392 
1393 	if (!k)
1394 		return NULL;
1395 
1396 	ldp = malloc(sizeof(*ldp) + (k-1), M_DEVBUF, M_NOWAIT);
1397 	if (!ldp)
1398 		return NULL;
1399 
1400 	bzero(&ldp->bling, sizeof(ldp->bling));
1401 	ldp->ndrives = k;
1402 	bcopy(buf, ldp->tgts, k);
1403 	return ldp;
1404 }
1405 
1406 int
1407 ciss_blink(struct ciss_softc *sc, int ld, int pd, int stat,
1408     struct ciss_blink *blink)
1409 {
1410 	struct ciss_ccb *ccb;
1411 	struct ciss_cmd *cmd;
1412 	struct ciss_ld *ldp;
1413 
1414 	if (ld > sc->maxunits)
1415 		return EINVAL;
1416 
1417 	ldp = sc->sc_lds[ld];
1418 	if (!ldp || pd > ldp->ndrives)
1419 		return EINVAL;
1420 
1421 	ldp->bling.pdtab[ldp->tgts[pd]] = stat == BIOC_SBUNBLINK? 0 :
1422 	    CISS_BLINK_ALL;
1423 	bcopy(&ldp->bling, blink, sizeof(*blink));
1424 
1425 	ccb = ciss_get_ccb(sc);
1426 	if (ccb == NULL)
1427 		return ENOMEM;
1428 	ccb->ccb_len = sizeof(*blink);
1429 	ccb->ccb_data = blink;
1430 	ccb->ccb_xs = NULL;
1431 	cmd = &ccb->ccb_cmd;
1432 	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
1433 	cmd->tgt2 = 0;
1434 	cmd->cdblen = 10;
1435 	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT;
1436 	cmd->tmo = htole16(0);
1437 	bzero(&cmd->cdb[0], sizeof(cmd->cdb));
1438 	cmd->cdb[0] = CISS_CMD_CTRL_SET;
1439 	cmd->cdb[6] = CISS_CMS_CTRL_PDBLINK;
1440 	cmd->cdb[7] = sizeof(*blink) >> 8;	/* biiiig endian */
1441 	cmd->cdb[8] = sizeof(*blink) & 0xff;
1442 
1443 	return ciss_cmd(ccb, BUS_DMA_NOWAIT, SCSI_POLL);
1444 }
1445 #endif
1446