1/*	$NetBSD: ciss.c,v 1.27 2011/06/20 22:02:55 pgoyette 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.27 2011/06/20 22:02:55 pgoyette Exp $");
23
24#include "bio.h"
25
26/* #define CISS_DEBUG */
27
28#include <sys/param.h>
29#include <sys/systm.h>
30#include <sys/buf.h>
31#include <sys/ioctl.h>
32#include <sys/device.h>
33#include <sys/kernel.h>
34#include <sys/malloc.h>
35#include <sys/proc.h>
36
37#include <sys/bus.h>
38
39#include <dev/scsipi/scsi_all.h>
40#include <dev/scsipi/scsi_disk.h>
41#include <dev/scsipi/scsiconf.h>
42#include <dev/scsipi/scsipi_all.h>
43
44#include <dev/ic/cissreg.h>
45#include <dev/ic/cissvar.h>
46
47#if NBIO > 0
48#include <dev/biovar.h>
49#endif /* NBIO > 0 */
50
51#ifdef CISS_DEBUG
52#define	CISS_DPRINTF(m,a)	if (ciss_debug & (m)) printf a
53#define	CISS_D_CMD	0x0001
54#define	CISS_D_INTR	0x0002
55#define	CISS_D_MISC	0x0004
56#define	CISS_D_DMA	0x0008
57#define	CISS_D_IOCTL	0x0010
58#define	CISS_D_ERR	0x0020
59int ciss_debug = 0
60	| CISS_D_CMD
61	| CISS_D_INTR
62	| CISS_D_MISC
63	| CISS_D_DMA
64	| CISS_D_IOCTL
65	| CISS_D_ERR
66	;
67#else
68#define	CISS_DPRINTF(m,a)	/* m, a */
69#endif
70
71static void	ciss_scsi_cmd(struct scsipi_channel *chan,
72			scsipi_adapter_req_t req, void *arg);
73static int	ciss_scsi_ioctl(struct scsipi_channel *chan, u_long cmd,
74	    void *addr, int flag, struct proc *p);
75static void	cissminphys(struct buf *bp);
76
77#if 0
78static void	ciss_scsi_raw_cmd(struct scsipi_channel *chan,
79			scsipi_adapter_req_t req, void *arg);
80#endif
81
82static int	ciss_sync(struct ciss_softc *sc);
83static void	ciss_heartbeat(void *v);
84static void	ciss_shutdown(void *v);
85
86static struct ciss_ccb *ciss_get_ccb(struct ciss_softc *sc);
87static void	ciss_put_ccb(struct ciss_ccb *ccb);
88static int	ciss_cmd(struct ciss_ccb *ccb, int flags, int wait);
89static int	ciss_done(struct ciss_ccb *ccb);
90static int	ciss_error(struct ciss_ccb *ccb);
91struct ciss_ld *ciss_pdscan(struct ciss_softc *sc, int ld);
92static int	ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq);
93int	ciss_ldid(struct ciss_softc *, int, struct ciss_ldid *);
94int	ciss_ldstat(struct ciss_softc *, int, struct ciss_ldstat *);
95static int	ciss_ldmap(struct ciss_softc *sc);
96int	ciss_pdid(struct ciss_softc *, u_int8_t, struct ciss_pdid *, int);
97
98#if NBIO > 0
99int		ciss_ioctl(device_t, u_long, void *);
100int		ciss_ioctl_vol(struct ciss_softc *, struct bioc_vol *);
101int		ciss_blink(struct ciss_softc *, int, int, int, struct ciss_blink *);
102int		ciss_create_sensors(struct ciss_softc *);
103void		ciss_sensor_refresh(struct sysmon_envsys *, envsys_data_t *);
104#endif /* NBIO > 0 */
105
106static struct ciss_ccb *
107ciss_get_ccb(struct ciss_softc *sc)
108{
109	struct ciss_ccb *ccb;
110
111	mutex_enter(&sc->sc_mutex);
112	if ((ccb = TAILQ_LAST(&sc->sc_free_ccb, ciss_queue_head))) {
113		TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_link);
114		ccb->ccb_state = CISS_CCB_READY;
115	}
116	mutex_exit(&sc->sc_mutex);
117	return ccb;
118}
119
120static void
121ciss_put_ccb(struct ciss_ccb *ccb)
122{
123	struct ciss_softc *sc = ccb->ccb_sc;
124
125	ccb->ccb_state = CISS_CCB_FREE;
126	mutex_enter(&sc->sc_mutex);
127	TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
128	mutex_exit(&sc->sc_mutex);
129}
130
131int
132ciss_attach(struct ciss_softc *sc)
133{
134	struct ciss_ccb *ccb;
135	struct ciss_cmd *cmd;
136	struct ciss_inquiry *inq;
137	bus_dma_segment_t seg[1];
138	int error, i, total, rseg, maxfer;
139	paddr_t pa;
140
141	bus_space_read_region_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff,
142	    (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
143
144	if (sc->cfg.signature != CISS_SIGNATURE) {
145		printf(": bad sign 0x%08x\n", sc->cfg.signature);
146		return -1;
147	}
148
149	if (!(sc->cfg.methods & CISS_METH_SIMPL)) {
150		printf(": not simple 0x%08x\n", sc->cfg.methods);
151		return -1;
152	}
153
154	sc->cfg.rmethod = CISS_METH_SIMPL;
155	sc->cfg.paddr_lim = 0;			/* 32bit addrs */
156	sc->cfg.int_delay = 0;			/* disable coalescing */
157	sc->cfg.int_count = 0;
158	strlcpy(sc->cfg.hostname, "HUMPPA", sizeof(sc->cfg.hostname));
159	sc->cfg.driverf |= CISS_DRV_PRF;	/* enable prefetch */
160	if (!sc->cfg.maxsg)
161		sc->cfg.maxsg = MAXPHYS / PAGE_SIZE + 1;
162
163	bus_space_write_region_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff,
164	    (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
165	bus_space_barrier(sc->sc_iot, sc->cfg_ioh, sc->cfgoff, sizeof(sc->cfg),
166	    BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
167
168	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IDB, CISS_IDB_CFG);
169	bus_space_barrier(sc->sc_iot, sc->sc_ioh, CISS_IDB, 4,
170	    BUS_SPACE_BARRIER_WRITE);
171	for (i = 1000; i--; DELAY(1000)) {
172		/* XXX maybe IDB is really 64bit? - hp dl380 needs this */
173		(void)bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IDB + 4);
174		if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IDB) & CISS_IDB_CFG))
175			break;
176		bus_space_barrier(sc->sc_iot, sc->sc_ioh, CISS_IDB, 4,
177		    BUS_SPACE_BARRIER_READ);
178	}
179
180	if (bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IDB) & CISS_IDB_CFG) {
181		printf(": cannot set config\n");
182		return -1;
183	}
184
185	bus_space_read_region_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff,
186	    (u_int32_t *)&sc->cfg, sizeof(sc->cfg) / 4);
187
188	if (!(sc->cfg.amethod & CISS_METH_SIMPL)) {
189		printf(": cannot simplify 0x%08x\n", sc->cfg.amethod);
190		return -1;
191	}
192
193	/* i'm ready for you and i hope you're ready for me */
194	for (i = 30000; i--; DELAY(1000)) {
195		if (bus_space_read_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff +
196		    offsetof(struct ciss_config, amethod)) & CISS_METH_READY)
197			break;
198		bus_space_barrier(sc->sc_iot, sc->cfg_ioh, sc->cfgoff +
199		    offsetof(struct ciss_config, amethod), 4,
200		    BUS_SPACE_BARRIER_READ);
201	}
202
203	if (!(bus_space_read_4(sc->sc_iot, sc->cfg_ioh, sc->cfgoff +
204	    offsetof(struct ciss_config, amethod)) & CISS_METH_READY)) {
205		printf(": she never came ready for me 0x%08x\n",
206		    sc->cfg.amethod);
207		return -1;
208	}
209
210	mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM);
211	mutex_init(&sc->sc_mutex_scratch, MUTEX_DEFAULT, IPL_VM);
212	cv_init(&sc->sc_condvar, "ciss_cmd");
213	sc->maxcmd = sc->cfg.maxcmd;
214	sc->maxsg = sc->cfg.maxsg;
215	if (sc->maxsg > MAXPHYS / PAGE_SIZE + 1)
216		sc->maxsg = MAXPHYS / PAGE_SIZE + 1;
217	i = sizeof(struct ciss_ccb) +
218	    sizeof(ccb->ccb_cmd.sgl[0]) * (sc->maxsg - 1);
219	for (sc->ccblen = 0x10; sc->ccblen < i; sc->ccblen <<= 1);
220
221	total = sc->ccblen * sc->maxcmd;
222	if ((error = bus_dmamem_alloc(sc->sc_dmat, total, PAGE_SIZE, 0,
223	    sc->cmdseg, 1, &rseg, BUS_DMA_NOWAIT))) {
224		printf(": cannot allocate CCBs (%d)\n", error);
225		return -1;
226	}
227
228	if ((error = bus_dmamem_map(sc->sc_dmat, sc->cmdseg, rseg, total,
229	    (void **)&sc->ccbs, BUS_DMA_NOWAIT))) {
230		printf(": cannot map CCBs (%d)\n", error);
231		return -1;
232	}
233	memset(sc->ccbs, 0, total);
234
235	if ((error = bus_dmamap_create(sc->sc_dmat, total, 1,
236	    total, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->cmdmap))) {
237		printf(": cannot create CCBs dmamap (%d)\n", error);
238		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
239		return -1;
240	}
241
242	if ((error = bus_dmamap_load(sc->sc_dmat, sc->cmdmap, sc->ccbs, total,
243	    NULL, BUS_DMA_NOWAIT))) {
244		printf(": cannot load CCBs dmamap (%d)\n", error);
245		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
246		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
247		return -1;
248	}
249
250	TAILQ_INIT(&sc->sc_ccbq);
251	TAILQ_INIT(&sc->sc_ccbdone);
252	TAILQ_INIT(&sc->sc_free_ccb);
253
254	maxfer = sc->maxsg * PAGE_SIZE;
255	for (i = 0; total > 0 && i < sc->maxcmd; i++, total -= sc->ccblen) {
256		ccb = (struct ciss_ccb *) ((char *)sc->ccbs + i * sc->ccblen);
257		cmd = &ccb->ccb_cmd;
258		pa = sc->cmdseg[0].ds_addr + i * sc->ccblen;
259
260		ccb->ccb_sc = sc;
261		ccb->ccb_cmdpa = pa + offsetof(struct ciss_ccb, ccb_cmd);
262		ccb->ccb_state = CISS_CCB_FREE;
263
264		cmd->id = htole32(i << 2);
265		cmd->id_hi = htole32(0);
266		cmd->sgin = sc->maxsg;
267		cmd->sglen = htole16((u_int16_t)cmd->sgin);
268		cmd->err_len = htole32(sizeof(ccb->ccb_err));
269		pa += offsetof(struct ciss_ccb, ccb_err);
270		cmd->err_pa = htole64((u_int64_t)pa);
271
272		if ((error = bus_dmamap_create(sc->sc_dmat, maxfer, sc->maxsg,
273		    maxfer, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
274		    &ccb->ccb_dmamap)))
275			break;
276
277		TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
278	}
279
280	if (i < sc->maxcmd) {
281		printf(": cannot create ccb#%d dmamap (%d)\n", i, error);
282		if (i == 0) {
283			/* TODO leaking cmd's dmamaps and shitz */
284			bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
285			bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
286			return -1;
287		}
288	}
289
290	if ((error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
291	    seg, 1, &rseg, BUS_DMA_NOWAIT))) {
292		printf(": cannot allocate scratch buffer (%d)\n", error);
293		return -1;
294	}
295
296	if ((error = bus_dmamem_map(sc->sc_dmat, seg, rseg, PAGE_SIZE,
297	    (void **)&sc->scratch, BUS_DMA_NOWAIT))) {
298		printf(": cannot map scratch buffer (%d)\n", error);
299		return -1;
300	}
301	memset(sc->scratch, 0, PAGE_SIZE);
302	sc->sc_waitflag = XS_CTL_NOSLEEP;		/* can't sleep yet */
303
304	mutex_enter(&sc->sc_mutex_scratch);		/* is this really needed? */
305	inq = sc->scratch;
306	if (ciss_inq(sc, inq)) {
307		printf(": adapter inquiry failed\n");
308		mutex_exit(&sc->sc_mutex_scratch);
309		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
310		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
311		return -1;
312	}
313
314	if (!(inq->flags & CISS_INQ_BIGMAP)) {
315		printf(": big map is not supported, flags=0x%x\n",
316		    inq->flags);
317		mutex_exit(&sc->sc_mutex_scratch);
318		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
319		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
320		return -1;
321	}
322
323	sc->maxunits = inq->numld;
324	sc->nbus = inq->nscsi_bus;
325	sc->ndrives = inq->buswidth ? inq->buswidth : 256;
326	printf(": %d LD%s, HW rev %d, FW %4.4s/%4.4s\n",
327	    inq->numld, inq->numld == 1? "" : "s",
328	    inq->hw_rev, inq->fw_running, inq->fw_stored);
329
330	mutex_exit(&sc->sc_mutex_scratch);
331
332	callout_init(&sc->sc_hb, 0);
333	callout_setfunc(&sc->sc_hb, ciss_heartbeat, sc);
334	callout_schedule(&sc->sc_hb, hz * 3);
335
336	/* map LDs */
337	if (ciss_ldmap(sc)) {
338		aprint_error_dev(&sc->sc_dev, "adapter LD map failed\n");
339		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
340		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
341		return -1;
342	}
343
344	if (!(sc->sc_lds = malloc(sc->maxunits * sizeof(*sc->sc_lds),
345	    M_DEVBUF, M_NOWAIT))) {
346		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
347		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
348		return -1;
349	}
350	memset(sc->sc_lds, 0, sc->maxunits * sizeof(*sc->sc_lds));
351
352	sc->sc_flush = CISS_FLUSH_ENABLE;
353	if (!(sc->sc_sh = shutdownhook_establish(ciss_shutdown, sc))) {
354		printf(": unable to establish shutdown hook\n");
355		bus_dmamem_free(sc->sc_dmat, sc->cmdseg, 1);
356		bus_dmamap_destroy(sc->sc_dmat, sc->cmdmap);
357		return -1;
358	}
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 = 1;	/* ciss doesn't really have SCSI luns */
365	sc->sc_channel.chan_openings = sc->maxcmd;
366#if NBIO > 0
367	/* XXX Reserve some ccb's for sensor and bioctl. */
368	if (sc->sc_channel.chan_openings > 2)
369		sc->sc_channel.chan_openings -= 2;
370#endif
371	sc->sc_channel.chan_flags = 0;
372	sc->sc_channel.chan_id = sc->maxunits;
373
374	sc->sc_adapter.adapt_dev = (device_t) sc;
375	sc->sc_adapter.adapt_openings = sc->sc_channel.chan_openings;
376	sc->sc_adapter.adapt_max_periph = min(sc->sc_adapter.adapt_openings, 256);
377	sc->sc_adapter.adapt_request = ciss_scsi_cmd;
378	sc->sc_adapter.adapt_minphys = cissminphys;
379	sc->sc_adapter.adapt_ioctl = ciss_scsi_ioctl;
380	sc->sc_adapter.adapt_nchannels = 1;
381	config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
382
383#if 0
384	sc->sc_link_raw.adapter_softc = sc;
385	sc->sc_link.openings = sc->sc_channel.chan_openings;
386	sc->sc_link_raw.adapter = &ciss_raw_switch;
387	sc->sc_link_raw.adapter_target = sc->ndrives;
388	sc->sc_link_raw.adapter_buswidth = sc->ndrives;
389	config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
390#endif
391
392#if NBIO > 0
393	/* now map all the physdevs into their lds */
394	/* XXX currently we assign all of them into ld0 */
395	for (i = 0; i < sc->maxunits && i < 1; i++)
396		if (!(sc->sc_lds[i] = ciss_pdscan(sc, i))) {
397			sc->sc_waitflag = 0;	/* we can sleep now */
398			return 0;
399		}
400
401	if (bio_register(&sc->sc_dev, ciss_ioctl) != 0)
402		aprint_error_dev(&sc->sc_dev, "controller registration failed");
403	else
404		sc->sc_ioctl = ciss_ioctl;
405	if (ciss_create_sensors(sc) != 0)
406		aprint_error_dev(&sc->sc_dev, "unable to create sensors");
407#endif
408	sc->sc_waitflag = 0;			/* we can sleep now */
409
410	return 0;
411}
412
413static void
414ciss_shutdown(void *v)
415{
416	struct ciss_softc *sc = v;
417
418	sc->sc_flush = CISS_FLUSH_DISABLE;
419	/* timeout_del(&sc->sc_hb); */
420	ciss_sync(sc);
421}
422
423static void
424cissminphys(struct buf *bp)
425{
426#if 0	/* TOSO */
427#define	CISS_MAXFER	(PAGE_SIZE * (sc->maxsg + 1))
428	if (bp->b_bcount > CISS_MAXFER)
429		bp->b_bcount = CISS_MAXFER;
430#endif
431	minphys(bp);
432}
433
434/*
435 * submit a command and optionally wait for completition.
436 * wait arg abuses XS_CTL_POLL|XS_CTL_NOSLEEP flags to request
437 * to wait (XS_CTL_POLL) and to allow tsleep() (!XS_CTL_NOSLEEP)
438 * instead of busy loop waiting
439 */
440static int
441ciss_cmd(struct ciss_ccb *ccb, int flags, int wait)
442{
443	struct ciss_softc *sc = ccb->ccb_sc;
444	struct ciss_cmd *cmd = &ccb->ccb_cmd;
445	struct ciss_ccb *ccb1;
446	bus_dmamap_t dmap = ccb->ccb_dmamap;
447	u_int32_t id;
448	int i, tohz, error = 0;
449
450	if (ccb->ccb_state != CISS_CCB_READY) {
451		printf("%s: ccb %d not ready state=0x%x\n", device_xname(&sc->sc_dev),
452		    cmd->id, ccb->ccb_state);
453		return (EINVAL);
454	}
455
456	if (ccb->ccb_data) {
457		bus_dma_segment_t *sgd;
458
459		if ((error = bus_dmamap_load(sc->sc_dmat, dmap, ccb->ccb_data,
460		    ccb->ccb_len, NULL, flags))) {
461			if (error == EFBIG)
462				printf("more than %d dma segs\n", sc->maxsg);
463			else
464				printf("error %d loading dma map\n", error);
465			ciss_put_ccb(ccb);
466			return (error);
467		}
468		cmd->sgin = dmap->dm_nsegs;
469
470		sgd = dmap->dm_segs;
471		CISS_DPRINTF(CISS_D_DMA, ("data=%p/%zu<%#" PRIxPADDR "/%zu",
472		    ccb->ccb_data, ccb->ccb_len, sgd->ds_addr, sgd->ds_len));
473
474		for (i = 0; i < dmap->dm_nsegs; sgd++, i++) {
475			cmd->sgl[i].addr_lo = htole32(sgd->ds_addr);
476			cmd->sgl[i].addr_hi =
477			    htole32((u_int64_t)sgd->ds_addr >> 32);
478			cmd->sgl[i].len = htole32(sgd->ds_len);
479			cmd->sgl[i].flags = htole32(0);
480			if (i) {
481				CISS_DPRINTF(CISS_D_DMA,
482				    (",%#" PRIxPADDR "/%zu", sgd->ds_addr,
483				    sgd->ds_len));
484			}
485		}
486
487		CISS_DPRINTF(CISS_D_DMA, ("> "));
488
489		bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
490		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
491	} else
492		cmd->sgin = 0;
493	cmd->sglen = htole16((u_int16_t)cmd->sgin);
494	memset(&ccb->ccb_err, 0, sizeof(ccb->ccb_err));
495
496	bus_dmamap_sync(sc->sc_dmat, sc->cmdmap, 0, sc->cmdmap->dm_mapsize,
497	    BUS_DMASYNC_PREWRITE);
498
499	if ((wait & (XS_CTL_POLL|XS_CTL_NOSLEEP)) == (XS_CTL_POLL|XS_CTL_NOSLEEP))
500		bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IMR,
501		    bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IMR) | sc->iem);
502
503	mutex_enter(&sc->sc_mutex);
504	TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
505	mutex_exit(&sc->sc_mutex);
506	ccb->ccb_state = CISS_CCB_ONQ;
507	CISS_DPRINTF(CISS_D_CMD, ("submit=0x%x ", cmd->id));
508	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_INQ, ccb->ccb_cmdpa);
509
510	if (wait & XS_CTL_POLL) {
511		int etick;
512		CISS_DPRINTF(CISS_D_CMD, ("waiting "));
513
514		i = ccb->ccb_xs? ccb->ccb_xs->timeout : 60000;
515		tohz = (i / 1000) * hz + (i % 1000) * (hz / 1000);
516		if (tohz == 0)
517			tohz = 1;
518		for (i *= 100, etick = tick + tohz; i--; ) {
519			if (!(wait & XS_CTL_NOSLEEP)) {
520				ccb->ccb_state = CISS_CCB_POLL;
521				CISS_DPRINTF(CISS_D_CMD, ("cv_timedwait(%d) ", tohz));
522				mutex_enter(&sc->sc_mutex);
523				if (cv_timedwait(&sc->sc_condvar,
524				    &sc->sc_mutex, tohz) == EWOULDBLOCK) {
525					mutex_exit(&sc->sc_mutex);
526					break;
527				}
528				mutex_exit(&sc->sc_mutex);
529				if (ccb->ccb_state != CISS_CCB_ONQ) {
530					tohz = etick - tick;
531					if (tohz <= 0)
532						break;
533					CISS_DPRINTF(CISS_D_CMD, ("T"));
534					continue;
535				}
536				ccb1 = ccb;
537			} else {
538				DELAY(10);
539
540				if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh,
541				    CISS_ISR) & sc->iem)) {
542					CISS_DPRINTF(CISS_D_CMD, ("N"));
543					continue;
544				}
545
546				if ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
547				    CISS_OUTQ)) == 0xffffffff) {
548					CISS_DPRINTF(CISS_D_CMD, ("Q"));
549					continue;
550				}
551
552				CISS_DPRINTF(CISS_D_CMD, ("got=0x%x ", id));
553				ccb1 = (struct ciss_ccb *)
554					((char *)sc->ccbs + (id >> 2) * sc->ccblen);
555				ccb1->ccb_cmd.id = htole32(id);
556			}
557
558			error = ciss_done(ccb1);
559			if (ccb1 == ccb)
560				break;
561		}
562
563		/* if never got a chance to be done above... */
564		if (ccb->ccb_state != CISS_CCB_FREE) {
565			ccb->ccb_err.cmd_stat = CISS_ERR_TMO;
566			error = ciss_done(ccb);
567		}
568
569		CISS_DPRINTF(CISS_D_CMD, ("done %d:%d",
570		    ccb->ccb_err.cmd_stat, ccb->ccb_err.scsi_stat));
571	}
572
573	if ((wait & (XS_CTL_POLL|XS_CTL_NOSLEEP)) == (XS_CTL_POLL|XS_CTL_NOSLEEP))
574		bus_space_write_4(sc->sc_iot, sc->sc_ioh, CISS_IMR,
575		    bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_IMR) & ~sc->iem);
576
577	return (error);
578}
579
580static int
581ciss_done(struct ciss_ccb *ccb)
582{
583	struct ciss_softc *sc = ccb->ccb_sc;
584	struct scsipi_xfer *xs = ccb->ccb_xs;
585	struct ciss_cmd *cmd;
586	int error = 0;
587
588	CISS_DPRINTF(CISS_D_CMD, ("ciss_done(%p) ", ccb));
589
590	if (ccb->ccb_state != CISS_CCB_ONQ) {
591		printf("%s: unqueued ccb %p ready, state=0x%x\n",
592		    device_xname(&sc->sc_dev), ccb, ccb->ccb_state);
593		return 1;
594	}
595
596	ccb->ccb_state = CISS_CCB_READY;
597	mutex_enter(&sc->sc_mutex);
598	TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link);
599	mutex_exit(&sc->sc_mutex);
600
601	if (ccb->ccb_cmd.id & CISS_CMD_ERR)
602		error = ciss_error(ccb);
603
604	cmd = &ccb->ccb_cmd;
605	if (ccb->ccb_data) {
606		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
607		    ccb->ccb_dmamap->dm_mapsize, (cmd->flags & CISS_CDB_IN) ?
608		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
609		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
610		ccb->ccb_xs = NULL;
611		ccb->ccb_data = NULL;
612	}
613
614	ciss_put_ccb(ccb);
615
616	if (xs) {
617		xs->resid = 0;
618		CISS_DPRINTF(CISS_D_CMD, ("scsipi_done(%p) ", xs));
619		if (xs->cmd->opcode == INQUIRY) {
620			struct scsipi_inquiry_data *inq;
621			inq = (struct scsipi_inquiry_data *)xs->data;
622			if ((inq->version & SID_ANSII) == 0 &&
623			    (inq->flags3 & SID_CmdQue) != 0) {
624				inq->version |= 2;
625			}
626		}
627		scsipi_done(xs);
628	}
629
630	return error;
631}
632
633static int
634ciss_error(struct ciss_ccb *ccb)
635{
636	struct ciss_softc *sc = ccb->ccb_sc;
637	struct ciss_error *err = &ccb->ccb_err;
638	struct scsipi_xfer *xs = ccb->ccb_xs;
639	int rv;
640
641	switch ((rv = le16toh(err->cmd_stat))) {
642	case CISS_ERR_OK:
643		break;
644
645	case CISS_ERR_INVCMD:
646		if (xs == NULL ||
647		    xs->cmd->opcode != SCSI_SYNCHRONIZE_CACHE_10)
648			printf("%s: invalid cmd 0x%x: 0x%x is not valid @ 0x%x[%d]\n",
649			    device_xname(&sc->sc_dev), ccb->ccb_cmd.id,
650			    err->err_info, err->err_type[3], err->err_type[2]);
651		if (xs) {
652			memset(&xs->sense, 0, sizeof(xs->sense));
653			xs->sense.scsi_sense.response_code =
654				SSD_RCODE_CURRENT | SSD_RCODE_VALID;
655			xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
656			xs->sense.scsi_sense.asc = 0x24; /* ill field */
657			xs->sense.scsi_sense.ascq = 0x0;
658			xs->error = XS_SENSE;
659		}
660		break;
661
662	case CISS_ERR_TMO:
663		xs->error = XS_TIMEOUT;
664		break;
665
666	case CISS_ERR_UNRUN:
667		/* Underrun */
668		xs->resid = le32toh(err->resid);
669		CISS_DPRINTF(CISS_D_CMD, (" underrun resid=0x%x ",
670					  xs->resid));
671		break;
672	default:
673		if (xs) {
674			CISS_DPRINTF(CISS_D_CMD, ("scsi_stat=%x ", err->scsi_stat));
675			switch (err->scsi_stat) {
676			case SCSI_CHECK:
677				xs->error = XS_SENSE;
678				memcpy(&xs->sense, &err->sense[0],
679				    sizeof(xs->sense));
680				CISS_DPRINTF(CISS_D_CMD, (" sense=%02x %02x %02x %02x ",
681					     err->sense[0], err->sense[1], err->sense[2], err->sense[3]));
682				break;
683
684			case XS_BUSY:
685				xs->error = XS_BUSY;
686				break;
687
688			default:
689				CISS_DPRINTF(CISS_D_ERR, ("%s: "
690				    "cmd_stat=%x scsi_stat=0x%x resid=0x%x\n",
691				    device_xname(&sc->sc_dev), rv, err->scsi_stat,
692				    le32toh(err->resid)));
693				printf("ciss driver stuffup in %s:%d: %s()\n",
694				       __FILE__, __LINE__, __func__);
695				xs->error = XS_DRIVER_STUFFUP;
696				break;
697			}
698			xs->resid = le32toh(err->resid);
699		}
700	}
701	ccb->ccb_cmd.id &= htole32(~3);
702
703	return rv;
704}
705
706static int
707ciss_inq(struct ciss_softc *sc, struct ciss_inquiry *inq)
708{
709	struct ciss_ccb *ccb;
710	struct ciss_cmd *cmd;
711
712	ccb = ciss_get_ccb(sc);
713	ccb->ccb_len = sizeof(*inq);
714	ccb->ccb_data = inq;
715	ccb->ccb_xs = NULL;
716	cmd = &ccb->ccb_cmd;
717	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
718	cmd->tgt2 = 0;
719	cmd->cdblen = 10;
720	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
721	cmd->tmo = htole16(0);
722	memset(&cmd->cdb[0], 0, sizeof(cmd->cdb));
723	cmd->cdb[0] = CISS_CMD_CTRL_GET;
724	cmd->cdb[6] = CISS_CMS_CTRL_CTRL;
725	cmd->cdb[7] = sizeof(*inq) >> 8;	/* biiiig endian */
726	cmd->cdb[8] = sizeof(*inq) & 0xff;
727
728	return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP);
729}
730
731static int
732ciss_ldmap(struct ciss_softc *sc)
733{
734	struct ciss_ccb *ccb;
735	struct ciss_cmd *cmd;
736	struct ciss_ldmap *lmap;
737	int total, rv;
738
739	mutex_enter(&sc->sc_mutex_scratch);
740	lmap = sc->scratch;
741	lmap->size = htobe32(sc->maxunits * sizeof(lmap->map));
742	total = sizeof(*lmap) + (sc->maxunits - 1) * sizeof(lmap->map);
743
744	ccb = ciss_get_ccb(sc);
745	ccb->ccb_len = total;
746	ccb->ccb_data = lmap;
747	ccb->ccb_xs = NULL;
748	cmd = &ccb->ccb_cmd;
749	cmd->tgt = CISS_CMD_MODE_PERIPH;
750	cmd->tgt2 = 0;
751	cmd->cdblen = 12;
752	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
753	cmd->tmo = htole16(30);
754	memset(&cmd->cdb[0], 0, sizeof(cmd->cdb));
755	cmd->cdb[0] = CISS_CMD_LDMAP;
756	cmd->cdb[8] = total >> 8;	/* biiiig endian */
757	cmd->cdb[9] = total & 0xff;
758
759	rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP);
760
761	if (rv) {
762		mutex_exit(&sc->sc_mutex_scratch);
763		return rv;
764	}
765
766	CISS_DPRINTF(CISS_D_MISC, ("lmap %x:%x\n",
767	    lmap->map[0].tgt, lmap->map[0].tgt2));
768
769	mutex_exit(&sc->sc_mutex_scratch);
770	return 0;
771}
772
773static int
774ciss_sync(struct ciss_softc *sc)
775{
776	struct ciss_ccb *ccb;
777	struct ciss_cmd *cmd;
778	struct ciss_flush *flush;
779	int rv;
780
781	mutex_enter(&sc->sc_mutex_scratch);
782	flush = sc->scratch;
783	memset(flush, 0, sizeof(*flush));
784	flush->flush = sc->sc_flush;
785
786	ccb = ciss_get_ccb(sc);
787	ccb->ccb_len = sizeof(*flush);
788	ccb->ccb_data = flush;
789	ccb->ccb_xs = NULL;
790	cmd = &ccb->ccb_cmd;
791	cmd->tgt = CISS_CMD_MODE_PERIPH;
792	cmd->tgt2 = 0;
793	cmd->cdblen = 10;
794	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT;
795	cmd->tmo = 0;
796	memset(&cmd->cdb[0], 0, sizeof(cmd->cdb));
797	cmd->cdb[0] = CISS_CMD_CTRL_SET;
798	cmd->cdb[6] = CISS_CMS_CTRL_FLUSH;
799	cmd->cdb[7] = sizeof(*flush) >> 8;	/* biiiig endian */
800	cmd->cdb[8] = sizeof(*flush) & 0xff;
801
802	rv = ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL|XS_CTL_NOSLEEP);
803	mutex_exit(&sc->sc_mutex_scratch);
804
805	return rv;
806}
807
808int
809ciss_ldid(struct ciss_softc *sc, int target, struct ciss_ldid *id)
810{
811	struct ciss_ccb *ccb;
812	struct ciss_cmd *cmd;
813
814	ccb = ciss_get_ccb(sc);
815	if (ccb == NULL)
816		return ENOMEM;
817	ccb->ccb_len = sizeof(*id);
818	ccb->ccb_data = id;
819	ccb->ccb_xs = NULL;
820	cmd = &ccb->ccb_cmd;
821	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
822	cmd->tgt2 = 0;
823	cmd->cdblen = 10;
824	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
825	cmd->tmo = htole16(0);
826	memset(&cmd->cdb[0], 0, sizeof(cmd->cdb));
827	cmd->cdb[0] = CISS_CMD_CTRL_GET;
828	cmd->cdb[1] = target;
829	cmd->cdb[6] = CISS_CMS_CTRL_LDIDEXT;
830	cmd->cdb[7] = sizeof(*id) >> 8;	/* biiiig endian */
831	cmd->cdb[8] = sizeof(*id) & 0xff;
832
833	return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL | sc->sc_waitflag);
834}
835
836int
837ciss_ldstat(struct ciss_softc *sc, int target, struct ciss_ldstat *stat)
838{
839	struct ciss_ccb *ccb;
840	struct ciss_cmd *cmd;
841
842	ccb = ciss_get_ccb(sc);
843	if (ccb == NULL)
844		return ENOMEM;
845	ccb->ccb_len = sizeof(*stat);
846	ccb->ccb_data = stat;
847	ccb->ccb_xs = NULL;
848	cmd = &ccb->ccb_cmd;
849	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
850	cmd->tgt2 = 0;
851	cmd->cdblen = 10;
852	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
853	cmd->tmo = htole16(0);
854	memset(&cmd->cdb[0], 0, sizeof(cmd->cdb));
855	cmd->cdb[0] = CISS_CMD_CTRL_GET;
856	cmd->cdb[1] = target;
857	cmd->cdb[6] = CISS_CMS_CTRL_LDSTAT;
858	cmd->cdb[7] = sizeof(*stat) >> 8;	/* biiiig endian */
859	cmd->cdb[8] = sizeof(*stat) & 0xff;
860
861	return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL | sc->sc_waitflag);
862}
863
864int
865ciss_pdid(struct ciss_softc *sc, u_int8_t drv, struct ciss_pdid *id, int wait)
866{
867	struct ciss_ccb *ccb;
868	struct ciss_cmd *cmd;
869
870	ccb = ciss_get_ccb(sc);
871	if (ccb == NULL)
872		return ENOMEM;
873	ccb->ccb_len = sizeof(*id);
874	ccb->ccb_data = id;
875	ccb->ccb_xs = NULL;
876	cmd = &ccb->ccb_cmd;
877	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
878	cmd->tgt2 = 0;
879	cmd->cdblen = 10;
880	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_IN;
881	cmd->tmo = htole16(0);
882	memset(&cmd->cdb[0], 0, sizeof(cmd->cdb));
883	cmd->cdb[0] = CISS_CMD_CTRL_GET;
884	cmd->cdb[2] = drv;
885	cmd->cdb[6] = CISS_CMS_CTRL_PDID;
886	cmd->cdb[7] = sizeof(*id) >> 8;	/* biiiig endian */
887	cmd->cdb[8] = sizeof(*id) & 0xff;
888
889	return ciss_cmd(ccb, BUS_DMA_NOWAIT, wait);
890}
891
892
893struct ciss_ld *
894ciss_pdscan(struct ciss_softc *sc, int ld)
895{
896	struct ciss_pdid *pdid;
897	struct ciss_ld *ldp;
898	u_int8_t drv, buf[128];
899	int i, j, k = 0;
900
901	mutex_enter(&sc->sc_mutex_scratch);
902	pdid = sc->scratch;
903	if (sc->ndrives == 256) {
904		for (i = 0; i < CISS_BIGBIT; i++)
905			if (!ciss_pdid(sc, i, pdid,
906					XS_CTL_POLL|XS_CTL_NOSLEEP) &&
907			    (pdid->present & CISS_PD_PRESENT))
908				buf[k++] = i;
909	} else
910		for (i = 0; i < sc->nbus; i++)
911			for (j = 0; j < sc->ndrives; j++) {
912				drv = CISS_BIGBIT + i * sc->ndrives + j;
913				if (!ciss_pdid(sc, drv, pdid,
914						XS_CTL_POLL|XS_CTL_NOSLEEP))
915					buf[k++] = drv;
916			}
917	mutex_exit(&sc->sc_mutex_scratch);
918
919	if (!k)
920		return NULL;
921
922	ldp = malloc(sizeof(*ldp) + (k-1), M_DEVBUF, M_NOWAIT);
923	if (!ldp)
924		return NULL;
925
926	memset(&ldp->bling, 0, sizeof(ldp->bling));
927	ldp->ndrives = k;
928	ldp->xname[0] = 0;
929	memcpy(ldp->tgts, buf, k);
930	return ldp;
931}
932
933#if 0
934static void
935ciss_scsi_raw_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req,
936	void *arg)				/* TODO */
937{
938	struct scsipi_xfer *xs = (struct scsipi_xfer *) arg;
939	struct ciss_rawsoftc *rsc =
940		(struct ciss_rawsoftc *) chan->chan_adapter->adapt_dev;
941	struct ciss_softc *sc = rsc->sc_softc;
942	struct ciss_ccb *ccb;
943	struct ciss_cmd *cmd;
944	int error;
945
946	CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_raw_cmd "));
947
948	switch (req)
949	{
950	case ADAPTER_REQ_RUN_XFER:
951		if (xs->cmdlen > CISS_MAX_CDB) {
952			CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs));
953			memset(&xs->sense, 0, sizeof(xs->sense));
954			printf("ciss driver stuffup in %s:%d: %s()\n",
955			       __FILE__, __LINE__, __func__);
956			xs->error = XS_DRIVER_STUFFUP;
957			scsipi_done(xs);
958			break;
959		}
960
961		error = 0;
962		xs->error = XS_NOERROR;
963
964		/* TODO check this target has not yet employed w/ any volume */
965
966		ccb = ciss_get_ccb(sc);
967		cmd = &ccb->ccb_cmd;
968		ccb->ccb_len = xs->datalen;
969		ccb->ccb_data = xs->data;
970		ccb->ccb_xs = xs;
971
972		cmd->cdblen = xs->cmdlen;
973		cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL;
974		if (xs->xs_control & XS_CTL_DATA_IN)
975			cmd->flags |= CISS_CDB_IN;
976		else if (xs->xs_control & XS_CTL_DATA_OUT)
977			cmd->flags |= CISS_CDB_OUT;
978		cmd->tmo = xs->timeout < 1000? 1 : xs->timeout / 1000;
979		memset(&cmd->cdb[0], 0, sizeof(cmd->cdb));
980		memcpy(&cmd->cdb[0], xs->cmd, CISS_MAX_CDB);
981
982		if (ciss_cmd(ccb, BUS_DMA_WAITOK,
983		    xs->xs_control & (XS_CTL_POLL|XS_CTL_NOSLEEP))) {
984			printf("ciss driver stuffup in %s:%d: %s()\n",
985			       __FILE__, __LINE__, __func__);
986			xs->error = XS_DRIVER_STUFFUP;
987			scsipi_done(xs);
988			break;
989		}
990
991		break;
992
993	case ADAPTER_REQ_GROW_RESOURCES:
994		/*
995		 * Not supported.
996		 */
997		break;
998
999	case ADAPTER_REQ_SET_XFER_MODE:
1000		/*
1001		 * We can't change the transfer mode, but at least let
1002		 * scsipi know what the adapter has negociated.
1003		 */
1004		 /* Get xfer mode and return it */
1005		break;
1006	}
1007}
1008#endif
1009
1010static void
1011ciss_scsi_cmd(struct scsipi_channel *chan, scsipi_adapter_req_t req,
1012	void *arg)
1013{
1014	struct scsipi_xfer *xs;
1015	struct scsipi_xfer_mode *xm;
1016	struct ciss_softc *sc =
1017		(struct ciss_softc *) chan->chan_adapter->adapt_dev;
1018	u_int8_t target;
1019	struct ciss_ccb *ccb;
1020	struct ciss_cmd *cmd;
1021	int error;
1022
1023	CISS_DPRINTF(CISS_D_CMD, ("ciss_scsi_cmd "));
1024
1025	switch (req)
1026	{
1027	case ADAPTER_REQ_RUN_XFER:
1028		xs = (struct scsipi_xfer *) arg;
1029		target = xs->xs_periph->periph_target;
1030		CISS_DPRINTF(CISS_D_CMD, ("targ=%d ", target));
1031		if (xs->cmdlen > CISS_MAX_CDB) {
1032			CISS_DPRINTF(CISS_D_CMD, ("CDB too big %p ", xs));
1033			memset(&xs->sense, 0, sizeof(xs->sense));
1034			printf("ciss driver stuffup in %s:%d: %s()\n",
1035			       __FILE__, __LINE__, __func__);
1036			xs->error = XS_DRIVER_STUFFUP;
1037			scsipi_done(xs);
1038			break;
1039		}
1040
1041		error = 0;
1042		xs->error = XS_NOERROR;
1043
1044		/* XXX emulate SYNCHRONIZE_CACHE ??? */
1045
1046		ccb = ciss_get_ccb(sc);
1047		cmd = &ccb->ccb_cmd;
1048		ccb->ccb_len = xs->datalen;
1049		ccb->ccb_data = xs->data;
1050		ccb->ccb_xs = xs;
1051		cmd->tgt = CISS_CMD_MODE_LD | target;
1052		cmd->tgt2 = 0;
1053		cmd->cdblen = xs->cmdlen;
1054		cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL;
1055		if (xs->xs_control & XS_CTL_DATA_IN)
1056			cmd->flags |= CISS_CDB_IN;
1057		else if (xs->xs_control & XS_CTL_DATA_OUT)
1058			cmd->flags |= CISS_CDB_OUT;
1059		cmd->tmo = xs->timeout < 1000? 1 : xs->timeout / 1000;
1060		memset(&cmd->cdb[0], 0, sizeof(cmd->cdb));
1061		memcpy(&cmd->cdb[0], xs->cmd, CISS_MAX_CDB);
1062		CISS_DPRINTF(CISS_D_CMD, ("cmd=%02x %02x %02x %02x %02x %02x ",
1063			     cmd->cdb[0], cmd->cdb[1], cmd->cdb[2],
1064			     cmd->cdb[3], cmd->cdb[4], cmd->cdb[5]));
1065
1066		if (ciss_cmd(ccb, BUS_DMA_WAITOK,
1067		    xs->xs_control & (XS_CTL_POLL|XS_CTL_NOSLEEP))) {
1068			printf("ciss driver stuffup in %s:%d: %s()\n",
1069			       __FILE__, __LINE__, __func__);
1070			xs->error = XS_DRIVER_STUFFUP;
1071			scsipi_done(xs);
1072			return;
1073		}
1074
1075		break;
1076	case ADAPTER_REQ_GROW_RESOURCES:
1077		/*
1078		 * Not supported.
1079		 */
1080		break;
1081	case ADAPTER_REQ_SET_XFER_MODE:
1082		/*
1083		 * We can't change the transfer mode, but at least let
1084		 * scsipi know what the adapter has negociated.
1085		 */
1086		xm = (struct scsipi_xfer_mode *)arg;
1087		xm->xm_mode |= PERIPH_CAP_TQING;
1088		scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
1089		break;
1090	}
1091}
1092
1093int
1094ciss_intr(void *v)
1095{
1096	struct ciss_softc *sc = v;
1097	struct ciss_ccb *ccb;
1098	u_int32_t id;
1099	int hit = 0;
1100
1101	CISS_DPRINTF(CISS_D_INTR, ("intr "));
1102
1103	if (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_ISR) & sc->iem))
1104		return 0;
1105
1106	while ((id = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CISS_OUTQ)) !=
1107	    0xffffffff) {
1108
1109		ccb = (struct ciss_ccb *) ((char *)sc->ccbs + (id >> 2) * sc->ccblen);
1110		ccb->ccb_cmd.id = htole32(id);
1111		if (ccb->ccb_state == CISS_CCB_POLL) {
1112			ccb->ccb_state = CISS_CCB_ONQ;
1113			mutex_enter(&sc->sc_mutex);
1114			cv_broadcast(&sc->sc_condvar);
1115			mutex_exit(&sc->sc_mutex);
1116		} else
1117			ciss_done(ccb);
1118
1119		hit = 1;
1120	}
1121
1122	CISS_DPRINTF(CISS_D_INTR, ("exit\n"));
1123	return hit;
1124}
1125
1126static void
1127ciss_heartbeat(void *v)
1128{
1129	struct ciss_softc *sc = v;
1130	u_int32_t hb;
1131
1132	hb = bus_space_read_4(sc->sc_iot, sc->cfg_ioh,
1133	    sc->cfgoff + offsetof(struct ciss_config, heartbeat));
1134	if (hb == sc->heartbeat)
1135		panic("ciss: dead");	/* XX reset! */
1136	else
1137		sc->heartbeat = hb;
1138
1139	callout_schedule(&sc->sc_hb, hz * 3);
1140}
1141
1142static int
1143ciss_scsi_ioctl(struct scsipi_channel *chan, u_long cmd,
1144    void *addr, int flag, struct proc *p)
1145{
1146#if NBIO > 0
1147	return ciss_ioctl(chan->chan_adapter->adapt_dev, cmd, addr);
1148#else
1149	return ENOTTY;
1150#endif
1151}
1152
1153#if NBIO > 0
1154const int ciss_level[] = { 0, 4, 1, 5, 51, 7 };
1155const int ciss_stat[] = { BIOC_SVONLINE, BIOC_SVOFFLINE, BIOC_SVOFFLINE,
1156    BIOC_SVDEGRADED, BIOC_SVREBUILD, BIOC_SVREBUILD, BIOC_SVDEGRADED,
1157    BIOC_SVDEGRADED, BIOC_SVINVALID, BIOC_SVINVALID, BIOC_SVBUILDING,
1158    BIOC_SVOFFLINE, BIOC_SVBUILDING };
1159
1160int
1161ciss_ioctl(device_t dev, u_long cmd, void *addr)
1162{
1163	struct ciss_softc	*sc = (struct ciss_softc *)dev;
1164	struct bioc_inq *bi;
1165	struct bioc_disk *bd;
1166	struct bioc_blink *bb;
1167	struct ciss_ldstat *ldstat;
1168	struct ciss_pdid *pdid;
1169	struct ciss_blink *blink;
1170	struct ciss_ld *ldp;
1171	u_int8_t drv;
1172	int ld, pd, error = 0;
1173
1174	switch (cmd) {
1175	case BIOCINQ:
1176		bi = (struct bioc_inq *)addr;
1177		strlcpy(bi->bi_dev, device_xname(&sc->sc_dev), sizeof(bi->bi_dev));
1178		bi->bi_novol = sc->maxunits;
1179		bi->bi_nodisk = sc->sc_lds[0]->ndrives;
1180		break;
1181
1182	case BIOCVOL:
1183		error = ciss_ioctl_vol(sc, (struct bioc_vol *)addr);
1184		break;
1185
1186	case BIOCDISK_NOVOL:
1187/*
1188 * XXX since we don't know how to associate physical drives with logical drives
1189 * yet, BIOCDISK_NOVOL is equivalent to BIOCDISK to the volume that we've
1190 * associated all physical drives to.
1191 * Maybe assoicate all physical drives to all logical volumes, but only return
1192 * physical drives on one logical volume.  Which one?  Either 1st volume that
1193 * is degraded, rebuilding, or failed?
1194 */
1195		bd = (struct bioc_disk *)addr;
1196		bd->bd_volid = 0;
1197		bd->bd_disknovol = true;
1198		/* FALLTHROUGH */
1199	case BIOCDISK:
1200		bd = (struct bioc_disk *)addr;
1201		if (bd->bd_volid > sc->maxunits) {
1202			error = EINVAL;
1203			break;
1204		}
1205		ldp = sc->sc_lds[0];
1206		if (!ldp || (pd = bd->bd_diskid) > ldp->ndrives) {
1207			error = EINVAL;
1208			break;
1209		}
1210		ldstat = sc->scratch;
1211		if ((error = ciss_ldstat(sc, bd->bd_volid, ldstat))) {
1212			break;
1213		}
1214		bd->bd_status = -1;
1215		if (ldstat->stat == CISS_LD_REBLD &&
1216		    ldstat->bigrebuild == ldp->tgts[pd])
1217			bd->bd_status = BIOC_SDREBUILD;
1218		if (ciss_bitset(ldp->tgts[pd] & (~CISS_BIGBIT),
1219		    ldstat->bigfailed)) {
1220			bd->bd_status = BIOC_SDFAILED;
1221			bd->bd_size = 0;
1222			bd->bd_channel = (ldp->tgts[pd] & (~CISS_BIGBIT)) /
1223			    sc->ndrives;
1224			bd->bd_target = ldp->tgts[pd] % sc->ndrives;
1225			bd->bd_lun = 0;
1226			bd->bd_vendor[0] = '\0';
1227			bd->bd_serial[0] = '\0';
1228			bd->bd_procdev[0] = '\0';
1229		} else {
1230			pdid = sc->scratch;
1231			if ((error = ciss_pdid(sc, ldp->tgts[pd], pdid,
1232			    XS_CTL_POLL))) {
1233				bd->bd_status = BIOC_SDFAILED;
1234				bd->bd_size = 0;
1235				bd->bd_channel = (ldp->tgts[pd] & (~CISS_BIGBIT)) /
1236				    sc->ndrives;
1237				bd->bd_target = ldp->tgts[pd] % sc->ndrives;
1238				bd->bd_lun = 0;
1239				bd->bd_vendor[0] = '\0';
1240				bd->bd_serial[0] = '\0';
1241				bd->bd_procdev[0] = '\0';
1242				error = 0;
1243				break;
1244			}
1245			if (bd->bd_status < 0) {
1246				if (pdid->config & CISS_PD_SPARE)
1247					bd->bd_status = BIOC_SDHOTSPARE;
1248				else if (pdid->present & CISS_PD_PRESENT)
1249					bd->bd_status = BIOC_SDONLINE;
1250				else
1251					bd->bd_status = BIOC_SDINVALID;
1252			}
1253			bd->bd_size = (u_int64_t)le32toh(pdid->nblocks) *
1254			    le16toh(pdid->blksz);
1255			bd->bd_channel = pdid->bus;
1256			bd->bd_target = pdid->target;
1257			bd->bd_lun = 0;
1258			strlcpy(bd->bd_vendor, pdid->model,
1259			    sizeof(bd->bd_vendor));
1260			strlcpy(bd->bd_serial, pdid->serial,
1261			    sizeof(bd->bd_serial));
1262			bd->bd_procdev[0] = '\0';
1263		}
1264		break;
1265
1266	case BIOCBLINK:
1267		bb = (struct bioc_blink *)addr;
1268		blink = sc->scratch;
1269		error = EINVAL;
1270		/* XXX workaround completely dumb scsi addressing */
1271		for (ld = 0; ld < sc->maxunits; ld++) {
1272			ldp = sc->sc_lds[ld];
1273			if (!ldp)
1274				continue;
1275			if (sc->ndrives == 256)
1276				drv = bb->bb_target;
1277			else
1278				drv = CISS_BIGBIT +
1279				    bb->bb_channel * sc->ndrives +
1280				    bb->bb_target;
1281			for (pd = 0; pd < ldp->ndrives; pd++)
1282				if (ldp->tgts[pd] == drv)
1283					error = ciss_blink(sc, ld, pd,
1284					    bb->bb_status, blink);
1285		}
1286		break;
1287
1288	case BIOCALARM:
1289	case BIOCSETSTATE:
1290	default:
1291		error = EINVAL;
1292	}
1293
1294	return (error);
1295}
1296
1297int
1298ciss_ioctl_vol(struct ciss_softc *sc, struct bioc_vol *bv)
1299{
1300	struct ciss_ldid *ldid;
1301	struct ciss_ld *ldp;
1302	struct ciss_ldstat *ldstat;
1303	struct ciss_pdid *pdid;
1304	int error = 0;
1305	u_int blks;
1306
1307	if (bv->bv_volid > sc->maxunits) {
1308		return EINVAL;
1309	}
1310	ldp = sc->sc_lds[bv->bv_volid];
1311	ldid = sc->scratch;
1312	if ((error = ciss_ldid(sc, bv->bv_volid, ldid))) {
1313		return error;
1314	}
1315	bv->bv_status = BIOC_SVINVALID;
1316	blks = (u_int)le16toh(ldid->nblocks[1]) << 16 |
1317	    le16toh(ldid->nblocks[0]);
1318	bv->bv_size = blks * (u_quad_t)le16toh(ldid->blksize);
1319	bv->bv_level = ciss_level[ldid->type];
1320/*
1321 * XXX Should only return bv_nodisk for logigal volume that we've associated
1322 * the physical drives to:  either the 1st degraded, rebuilding, or failed
1323 * volume else volume 0?
1324 */
1325	if (ldp) {
1326		bv->bv_nodisk = ldp->ndrives;
1327		strlcpy(bv->bv_dev, ldp->xname, sizeof(bv->bv_dev));
1328	}
1329	strlcpy(bv->bv_vendor, "CISS", sizeof(bv->bv_vendor));
1330	ldstat = sc->scratch;
1331	memset(ldstat, 0, sizeof(*ldstat));
1332	if ((error = ciss_ldstat(sc, bv->bv_volid, ldstat))) {
1333		return error;
1334	}
1335	bv->bv_percent = -1;
1336	bv->bv_seconds = 0;
1337	if (ldstat->stat < sizeof(ciss_stat)/sizeof(ciss_stat[0]))
1338		bv->bv_status = ciss_stat[ldstat->stat];
1339	if (bv->bv_status == BIOC_SVREBUILD ||
1340	    bv->bv_status == BIOC_SVBUILDING) {
1341	 	u_int64_t prog;
1342
1343		ldp = sc->sc_lds[0];
1344		if (ldp) {
1345			bv->bv_nodisk = ldp->ndrives;
1346			strlcpy(bv->bv_dev, ldp->xname, sizeof(bv->bv_dev));
1347		}
1348/*
1349 * XXX ldstat->prog is blocks remaining on physical drive being rebuilt
1350 * blks is only correct for a RAID1 set;  RAID5 needs to determine the
1351 * size of the physical device - which we don't yet know.
1352 * ldstat->bigrebuild has physical device target, so could be used with
1353 * pdid to get size.   Another way is to save pd information in sc so it's
1354 * easy to reference.
1355 */
1356		prog = (u_int64_t)((ldstat->prog[3] << 24) |
1357		    (ldstat->prog[2] << 16) | (ldstat->prog[1] << 8) |
1358		    ldstat->prog[0]);
1359		pdid = sc->scratch;
1360		if (!ciss_pdid(sc, ldstat->bigrebuild, pdid, XS_CTL_POLL)) {
1361			blks = le32toh(pdid->nblocks);
1362			bv->bv_percent = (blks - prog) * 1000ULL / blks;
1363		 }
1364	}
1365	return 0;
1366}
1367
1368int
1369ciss_blink(struct ciss_softc *sc, int ld, int pd, int stat,
1370    struct ciss_blink *blink)
1371{
1372	struct ciss_ccb *ccb;
1373	struct ciss_cmd *cmd;
1374	struct ciss_ld *ldp;
1375
1376	if (ld > sc->maxunits)
1377		return EINVAL;
1378
1379	ldp = sc->sc_lds[ld];
1380	if (!ldp || pd > ldp->ndrives)
1381		return EINVAL;
1382
1383	ldp->bling.pdtab[ldp->tgts[pd]] = stat == BIOC_SBUNBLINK? 0 :
1384	    CISS_BLINK_ALL;
1385	memcpy(blink, &ldp->bling, sizeof(*blink));
1386
1387	ccb = ciss_get_ccb(sc);
1388	if (ccb == NULL)
1389		return ENOMEM;
1390	ccb->ccb_len = sizeof(*blink);
1391	ccb->ccb_data = blink;
1392	ccb->ccb_xs = NULL;
1393	cmd = &ccb->ccb_cmd;
1394	cmd->tgt = htole32(CISS_CMD_MODE_PERIPH);
1395	cmd->tgt2 = 0;
1396	cmd->cdblen = 10;
1397	cmd->flags = CISS_CDB_CMD | CISS_CDB_SIMPL | CISS_CDB_OUT;
1398	cmd->tmo = htole16(0);
1399	memset(&cmd->cdb[0], 0, sizeof(cmd->cdb));
1400	cmd->cdb[0] = CISS_CMD_CTRL_SET;
1401	cmd->cdb[6] = CISS_CMS_CTRL_PDBLINK;
1402	cmd->cdb[7] = sizeof(*blink) >> 8;	/* biiiig endian */
1403	cmd->cdb[8] = sizeof(*blink) & 0xff;
1404
1405	return ciss_cmd(ccb, BUS_DMA_NOWAIT, XS_CTL_POLL);
1406}
1407
1408int
1409ciss_create_sensors(struct ciss_softc *sc)
1410{
1411	int			i;
1412	int nsensors = sc->maxunits;
1413
1414	if (nsensors == 0) {
1415		return 0;
1416	}
1417
1418	sc->sc_sme = sysmon_envsys_create();
1419	sc->sc_sensor = malloc(sizeof(envsys_data_t) * nsensors,
1420		M_DEVBUF, M_NOWAIT | M_ZERO);
1421	if (sc->sc_sensor == NULL) {
1422		aprint_error_dev(&sc->sc_dev, "can't allocate envsys_data");
1423		return(ENOMEM);
1424	}
1425
1426	for (i = 0; i < nsensors; i++) {
1427		sc->sc_sensor[i].units = ENVSYS_DRIVE;
1428		sc->sc_sensor[i].state = ENVSYS_SINVALID;
1429		sc->sc_sensor[i].value_cur = ENVSYS_DRIVE_EMPTY;
1430		/* Enable monitoring for drive state changes */
1431		sc->sc_sensor[i].flags |= ENVSYS_FMONSTCHANGED;
1432		/* logical drives */
1433		snprintf(sc->sc_sensor[i].desc,
1434		    sizeof(sc->sc_sensor[i].desc), "%s:%d",
1435		    device_xname(&sc->sc_dev), i);
1436		if (sysmon_envsys_sensor_attach(sc->sc_sme,
1437		    &sc->sc_sensor[i]))
1438			goto out;
1439	}
1440
1441	sc->sc_sme->sme_name = device_xname(&sc->sc_dev);
1442	sc->sc_sme->sme_cookie = sc;
1443	sc->sc_sme->sme_refresh = ciss_sensor_refresh;
1444	if (sysmon_envsys_register(sc->sc_sme)) {
1445		printf("%s: unable to register with sysmon\n",
1446		    device_xname(&sc->sc_dev));
1447		return(1);
1448	}
1449	return (0);
1450
1451out:
1452	free(sc->sc_sensor, M_DEVBUF);
1453	sysmon_envsys_destroy(sc->sc_sme);
1454	return EINVAL;
1455}
1456
1457void
1458ciss_sensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
1459{
1460	struct ciss_softc	*sc = sme->sme_cookie;
1461	struct bioc_vol		bv;
1462
1463	if (edata->sensor >= sc->maxunits)
1464		return;
1465
1466	memset(&bv, 0, sizeof(bv));
1467	bv.bv_volid = edata->sensor;
1468	if (ciss_ioctl_vol(sc, &bv)) {
1469		return;
1470	}
1471
1472	switch(bv.bv_status) {
1473	case BIOC_SVOFFLINE:
1474		edata->value_cur = ENVSYS_DRIVE_FAIL;
1475		edata->state = ENVSYS_SCRITICAL;
1476		break;
1477
1478	case BIOC_SVDEGRADED:
1479		edata->value_cur = ENVSYS_DRIVE_PFAIL;
1480		edata->state = ENVSYS_SCRITICAL;
1481		break;
1482
1483	case BIOC_SVSCRUB:
1484	case BIOC_SVONLINE:
1485		edata->value_cur = ENVSYS_DRIVE_ONLINE;
1486		edata->state = ENVSYS_SVALID;
1487		break;
1488
1489	case BIOC_SVREBUILD:
1490	case BIOC_SVBUILDING:
1491		edata->value_cur = ENVSYS_DRIVE_REBUILD;
1492		edata->state = ENVSYS_SVALID;
1493		break;
1494
1495	case BIOC_SVINVALID:
1496		/* FALLTRHOUGH */
1497	default:
1498		edata->value_cur = 0; /* unknown */
1499		edata->state = ENVSYS_SINVALID;
1500	}
1501}
1502#endif /* NBIO > 0 */
1503