xref: /openbsd/sys/dev/ic/ami.c (revision e5dd7070)
1 /*	$OpenBSD: ami.c,v 1.254 2020/07/24 12:43:31 krw Exp $	*/
2 
3 /*
4  * Copyright (c) 2001 Michael Shalayeff
5  * Copyright (c) 2005 Marco Peereboom
6  * Copyright (c) 2006 David Gwynne
7  * All rights reserved.
8  *
9  * The SCSI emulation layer is derived from gdt(4) driver,
10  * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31  * THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 /*
34  * American Megatrends Inc. MegaRAID controllers driver
35  *
36  * This driver was made because these ppl and organizations
37  * donated hardware and provided documentation:
38  *
39  * - 428 model card
40  *	John Kerbawy, Stephan Matis, Mark Stovall;
41  *
42  * - 467 and 475 model cards, docs
43  *	American Megatrends Inc.;
44  *
45  * - uninterruptable electric power for cvs
46  *	Theo de Raadt.
47  */
48 
49 #include "bio.h"
50 
51 /* #define	AMI_DEBUG */
52 
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/buf.h>
56 #include <sys/ioctl.h>
57 #include <sys/device.h>
58 #include <sys/kernel.h>
59 #include <sys/malloc.h>
60 #include <sys/rwlock.h>
61 #include <sys/pool.h>
62 #include <sys/sensors.h>
63 
64 #include <machine/bus.h>
65 
66 #include <scsi/scsi_all.h>
67 #include <scsi/scsi_disk.h>
68 #include <scsi/scsiconf.h>
69 
70 #include <dev/biovar.h>
71 #include <dev/ic/amireg.h>
72 #include <dev/ic/amivar.h>
73 
74 #ifdef AMI_DEBUG
75 #define	AMI_DPRINTF(m,a)	do { if (ami_debug & (m)) printf a; } while (0)
76 #define	AMI_D_CMD	0x0001
77 #define	AMI_D_INTR	0x0002
78 #define	AMI_D_MISC	0x0004
79 #define	AMI_D_DMA	0x0008
80 #define	AMI_D_IOCTL	0x0010
81 int ami_debug = 0
82 /*	| AMI_D_CMD */
83 /*	| AMI_D_INTR */
84 /*	| AMI_D_MISC */
85 /*	| AMI_D_DMA */
86 /*	| AMI_D_IOCTL */
87 	;
88 #else
89 #define	AMI_DPRINTF(m,a)	/* m, a */
90 #endif
91 
92 struct cfdriver ami_cd = {
93 	NULL, "ami", DV_DULL
94 };
95 
96 void	ami_scsi_cmd(struct scsi_xfer *);
97 int	ami_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int);
98 
99 struct scsi_adapter ami_switch = {
100 	ami_scsi_cmd, NULL, NULL, NULL, ami_scsi_ioctl
101 };
102 
103 void	ami_scsi_raw_cmd(struct scsi_xfer *);
104 
105 struct scsi_adapter ami_raw_switch = {
106 	ami_scsi_raw_cmd, NULL, NULL, NULL, NULL
107 };
108 
109 void *		ami_get_ccb(void *);
110 void		ami_put_ccb(void *, void *);
111 
112 u_int32_t	ami_read(struct ami_softc *, bus_size_t);
113 void		ami_write(struct ami_softc *, bus_size_t, u_int32_t);
114 
115 void		ami_copyhds(struct ami_softc *, const u_int32_t *,
116 		    const u_int8_t *, const u_int8_t *);
117 struct ami_mem	*ami_allocmem(struct ami_softc *, size_t);
118 void		ami_freemem(struct ami_softc *, struct ami_mem *);
119 int		ami_alloc_ccbs(struct ami_softc *, int);
120 
121 int		ami_poll(struct ami_softc *, struct ami_ccb *);
122 void		ami_start(struct ami_softc *, struct ami_ccb *);
123 void		ami_complete(struct ami_softc *, struct ami_ccb *, int);
124 void		ami_runqueue_tick(void *);
125 void		ami_runqueue(struct ami_softc *);
126 
127 void 		ami_start_xs(struct ami_softc *sc, struct ami_ccb *,
128 		    struct scsi_xfer *);
129 void		ami_done_xs(struct ami_softc *, struct ami_ccb *);
130 void		ami_done_pt(struct ami_softc *, struct ami_ccb *);
131 void		ami_done_flush(struct ami_softc *, struct ami_ccb *);
132 void		ami_done_sysflush(struct ami_softc *, struct ami_ccb *);
133 
134 void		ami_done_dummy(struct ami_softc *, struct ami_ccb *);
135 void		ami_done_ioctl(struct ami_softc *, struct ami_ccb *);
136 void		ami_done_init(struct ami_softc *, struct ami_ccb *);
137 
138 void		ami_copy_internal_data(struct scsi_xfer *, void *, size_t);
139 
140 int		ami_load_ptmem(struct ami_softc*, struct ami_ccb *,
141 		    void *, size_t, int, int);
142 
143 #if NBIO > 0
144 int		ami_mgmt(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t,
145 		    u_int8_t, size_t, void *);
146 int		ami_drv_pt(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t *,
147 		    int, int, void *);
148 int		ami_drv_readcap(struct ami_softc *, u_int8_t, u_int8_t,
149 		    daddr_t *);
150 int		ami_drv_inq(struct ami_softc *, u_int8_t, u_int8_t, u_int8_t,
151 		    void *);
152 int		ami_ioctl(struct device *, u_long, caddr_t);
153 int		ami_ioctl_inq(struct ami_softc *, struct bioc_inq *);
154 int		ami_vol(struct ami_softc *, struct bioc_vol *,
155 		    struct ami_big_diskarray *);
156 int		ami_disk(struct ami_softc *, struct bioc_disk *,
157 		    struct ami_big_diskarray *);
158 int		ami_ioctl_vol(struct ami_softc *, struct bioc_vol *);
159 int		ami_ioctl_disk(struct ami_softc *, struct bioc_disk *);
160 int		ami_ioctl_alarm(struct ami_softc *, struct bioc_alarm *);
161 int		ami_ioctl_setstate(struct ami_softc *, struct bioc_setstate *);
162 
163 #ifndef SMALL_KERNEL
164 int		ami_create_sensors(struct ami_softc *);
165 void		ami_refresh_sensors(void *);
166 #endif
167 #endif /* NBIO > 0 */
168 
169 #define DEVNAME(_s)	((_s)->sc_dev.dv_xname)
170 
171 void *
172 ami_get_ccb(void *xsc)
173 {
174 	struct ami_softc *sc = xsc;
175 	struct ami_ccb *ccb;
176 
177 	mtx_enter(&sc->sc_ccb_freeq_mtx);
178 	ccb = TAILQ_FIRST(&sc->sc_ccb_freeq);
179 	if (ccb != NULL) {
180 		TAILQ_REMOVE(&sc->sc_ccb_freeq, ccb, ccb_link);
181 		ccb->ccb_state = AMI_CCB_READY;
182 	}
183 	mtx_leave(&sc->sc_ccb_freeq_mtx);
184 
185 	return (ccb);
186 }
187 
188 void
189 ami_put_ccb(void *xsc, void *xccb)
190 {
191 	struct ami_softc *sc = xsc;
192 	struct ami_ccb *ccb = xccb;
193 
194 	ccb->ccb_state = AMI_CCB_FREE;
195 	ccb->ccb_xs = NULL;
196 	ccb->ccb_flags = 0;
197 	ccb->ccb_done = NULL;
198 
199 	mtx_enter(&sc->sc_ccb_freeq_mtx);
200 	TAILQ_INSERT_TAIL(&sc->sc_ccb_freeq, ccb, ccb_link);
201 	mtx_leave(&sc->sc_ccb_freeq_mtx);
202 }
203 
204 u_int32_t
205 ami_read(struct ami_softc *sc, bus_size_t r)
206 {
207 	u_int32_t rv;
208 
209 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
210 	    BUS_SPACE_BARRIER_READ);
211 	rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
212 
213 	AMI_DPRINTF(AMI_D_CMD, ("ari 0x%lx 0x08%x ", r, rv));
214 	return (rv);
215 }
216 
217 void
218 ami_write(struct ami_softc *sc, bus_size_t r, u_int32_t v)
219 {
220 	AMI_DPRINTF(AMI_D_CMD, ("awo 0x%lx 0x%08x ", r, v));
221 
222 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
223 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
224 	    BUS_SPACE_BARRIER_WRITE);
225 }
226 
227 struct ami_mem *
228 ami_allocmem(struct ami_softc *sc, size_t size)
229 {
230 	struct ami_mem		*am;
231 	int			nsegs;
232 
233 	am = malloc(sizeof(struct ami_mem), M_DEVBUF, M_NOWAIT|M_ZERO);
234 	if (am == NULL)
235 		return (NULL);
236 
237 	am->am_size = size;
238 
239 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
240 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &am->am_map) != 0)
241 		goto amfree;
242 
243 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &am->am_seg, 1,
244 	    &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
245 		goto destroy;
246 
247 	if (bus_dmamem_map(sc->sc_dmat, &am->am_seg, nsegs, size, &am->am_kva,
248 	    BUS_DMA_NOWAIT) != 0)
249 		goto free;
250 
251 	if (bus_dmamap_load(sc->sc_dmat, am->am_map, am->am_kva, size, NULL,
252 	    BUS_DMA_NOWAIT) != 0)
253 		goto unmap;
254 
255 	return (am);
256 
257 unmap:
258 	bus_dmamem_unmap(sc->sc_dmat, am->am_kva, size);
259 free:
260 	bus_dmamem_free(sc->sc_dmat, &am->am_seg, 1);
261 destroy:
262 	bus_dmamap_destroy(sc->sc_dmat, am->am_map);
263 amfree:
264 	free(am, M_DEVBUF, sizeof *am);
265 
266 	return (NULL);
267 }
268 
269 void
270 ami_freemem(struct ami_softc *sc, struct ami_mem *am)
271 {
272 	bus_dmamap_unload(sc->sc_dmat, am->am_map);
273 	bus_dmamem_unmap(sc->sc_dmat, am->am_kva, am->am_size);
274 	bus_dmamem_free(sc->sc_dmat, &am->am_seg, 1);
275 	bus_dmamap_destroy(sc->sc_dmat, am->am_map);
276 	free(am, M_DEVBUF, sizeof *am);
277 }
278 
279 void
280 ami_copyhds(struct ami_softc *sc, const u_int32_t *sizes,
281     const u_int8_t *props, const u_int8_t *stats)
282 {
283 	int i;
284 
285 	for (i = 0; i < sc->sc_nunits; i++) {
286 		sc->sc_hdr[i].hd_present = 1;
287 		sc->sc_hdr[i].hd_is_logdrv = 1;
288 		sc->sc_hdr[i].hd_size = letoh32(sizes[i]);
289 		sc->sc_hdr[i].hd_prop = props[i];
290 		sc->sc_hdr[i].hd_stat = stats[i];
291 	}
292 }
293 
294 int
295 ami_alloc_ccbs(struct ami_softc *sc, int nccbs)
296 {
297 	struct ami_ccb *ccb;
298 	struct ami_ccbmem *ccbmem, *mem;
299 	int i, error;
300 
301 	sc->sc_ccbs = mallocarray(nccbs, sizeof(struct ami_ccb),
302 	    M_DEVBUF, M_NOWAIT);
303 	if (sc->sc_ccbs == NULL) {
304 		printf(": unable to allocate ccbs\n");
305 		return (1);
306 	}
307 
308 	sc->sc_ccbmem_am = ami_allocmem(sc, sizeof(struct ami_ccbmem) * nccbs);
309 	if (sc->sc_ccbmem_am == NULL) {
310 		printf(": unable to allocate ccb dmamem\n");
311 		goto free_ccbs;
312 	}
313 	ccbmem = AMIMEM_KVA(sc->sc_ccbmem_am);
314 
315 	TAILQ_INIT(&sc->sc_ccb_freeq);
316 	mtx_init(&sc->sc_ccb_freeq_mtx, IPL_BIO);
317 	TAILQ_INIT(&sc->sc_ccb_preq);
318 	TAILQ_INIT(&sc->sc_ccb_runq);
319 	timeout_set(&sc->sc_run_tmo, ami_runqueue_tick, sc);
320 
321 	scsi_iopool_init(&sc->sc_iopool, sc, ami_get_ccb, ami_put_ccb);
322 
323 	for (i = 0; i < nccbs; i++) {
324 		ccb = &sc->sc_ccbs[i];
325 		mem = &ccbmem[i];
326 
327 		error = bus_dmamap_create(sc->sc_dmat, AMI_MAXFER,
328 		    AMI_MAXOFFSETS, AMI_MAXFER, 0,
329 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap);
330 		if (error) {
331 			printf(": cannot create ccb dmamap (%d)\n", error);
332 			goto free_list;
333 		}
334 
335 		ccb->ccb_sc = sc;
336 
337 		ccb->ccb_cmd.acc_id = i + 1;
338 		ccb->ccb_offset = sizeof(struct ami_ccbmem) * i;
339 
340 		ccb->ccb_pt = &mem->cd_pt;
341 		ccb->ccb_ptpa = htole32(AMIMEM_DVA(sc->sc_ccbmem_am) +
342 		    ccb->ccb_offset);
343 
344 		ccb->ccb_sglist = mem->cd_sg;
345 		ccb->ccb_sglistpa = htole32(AMIMEM_DVA(sc->sc_ccbmem_am) +
346 		    ccb->ccb_offset + sizeof(struct ami_passthrough));
347 
348 		/* override last command for management */
349 		if (i == nccbs - 1) {
350 			ccb->ccb_cmd.acc_id = 0xfe;
351 			sc->sc_mgmtccb = ccb;
352 		} else {
353 			ami_put_ccb(sc, ccb);
354 		}
355 	}
356 
357 	return (0);
358 
359 free_list:
360 	while ((ccb = ami_get_ccb(sc)) != NULL)
361 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
362 
363 	ami_freemem(sc, sc->sc_ccbmem_am);
364 free_ccbs:
365 	free(sc->sc_ccbs, M_DEVBUF, 0);
366 
367 	return (1);
368 }
369 
370 int
371 ami_attach(struct ami_softc *sc)
372 {
373 	struct scsibus_attach_args saa;
374 	struct ami_rawsoftc *rsc;
375 	struct ami_ccb iccb;
376 	struct ami_iocmd *cmd;
377 	struct ami_mem *am;
378 	struct ami_inquiry *inq;
379 	struct ami_fc_einquiry *einq;
380 	struct ami_fc_prodinfo *pi;
381 	const char *p;
382 	paddr_t	pa;
383 
384 	mtx_init(&sc->sc_cmd_mtx, IPL_BIO);
385 
386 	am = ami_allocmem(sc, NBPG);
387 	if (am == NULL) {
388 		printf(": unable to allocate init data\n");
389 		return (1);
390 	}
391 	pa = htole32(AMIMEM_DVA(am));
392 
393 	sc->sc_mbox_am = ami_allocmem(sc, sizeof(struct ami_iocmd));
394 	if (sc->sc_mbox_am == NULL) {
395 		printf(": unable to allocate mbox\n");
396 		goto free_idata;
397 	}
398 	sc->sc_mbox = (volatile struct ami_iocmd *)AMIMEM_KVA(sc->sc_mbox_am);
399 	sc->sc_mbox_pa = htole32(AMIMEM_DVA(sc->sc_mbox_am));
400 	AMI_DPRINTF(AMI_D_CMD, ("mbox=%p ", sc->sc_mbox));
401 	AMI_DPRINTF(AMI_D_CMD, ("mbox_pa=0x%llx ", (long long)sc->sc_mbox_pa));
402 
403 	/* create a spartan ccb for use with ami_poll */
404 	bzero(&iccb, sizeof(iccb));
405 	iccb.ccb_sc = sc;
406 	iccb.ccb_done = ami_done_init;
407 	cmd = &iccb.ccb_cmd;
408 
409 	(sc->sc_init)(sc);
410 
411 	/* try FC inquiry first */
412 	cmd->acc_cmd = AMI_FCOP;
413 	cmd->acc_io.aio_channel = AMI_FC_EINQ3;
414 	cmd->acc_io.aio_param = AMI_FC_EINQ3_SOLICITED_FULL;
415 	cmd->acc_io.aio_data = pa;
416 	if (ami_poll(sc, &iccb) == 0) {
417 		einq = AMIMEM_KVA(am);
418 		pi = AMIMEM_KVA(am);
419 
420 		sc->sc_nunits = einq->ain_nlogdrv;
421 		sc->sc_drvinscnt = einq->ain_drvinscnt + 1; /* force scan */
422 		ami_copyhds(sc, einq->ain_ldsize, einq->ain_ldprop,
423 		    einq->ain_ldstat);
424 
425 		cmd->acc_cmd = AMI_FCOP;
426 		cmd->acc_io.aio_channel = AMI_FC_PRODINF;
427 		cmd->acc_io.aio_param = 0;
428 		cmd->acc_io.aio_data = pa;
429 		if (ami_poll(sc, &iccb) == 0) {
430 			sc->sc_maxunits = AMI_BIG_MAX_LDRIVES;
431 
432 			bcopy (pi->api_fwver, sc->sc_fwver, 16);
433 			sc->sc_fwver[15] = '\0';
434 			bcopy (pi->api_biosver, sc->sc_biosver, 16);
435 			sc->sc_biosver[15] = '\0';
436 			sc->sc_channels = pi->api_channels;
437 			sc->sc_targets = pi->api_fcloops;
438 			sc->sc_memory = letoh16(pi->api_ramsize);
439 			sc->sc_maxcmds = pi->api_maxcmd;
440 			p = "FC loop";
441 		}
442 	}
443 
444 	if (sc->sc_maxunits == 0) {
445 		inq = AMIMEM_KVA(am);
446 
447 		cmd->acc_cmd = AMI_EINQUIRY;
448 		cmd->acc_io.aio_channel = 0;
449 		cmd->acc_io.aio_param = 0;
450 		cmd->acc_io.aio_data = pa;
451 		if (ami_poll(sc, &iccb) != 0) {
452 			cmd->acc_cmd = AMI_INQUIRY;
453 			cmd->acc_io.aio_channel = 0;
454 			cmd->acc_io.aio_param = 0;
455 			cmd->acc_io.aio_data = pa;
456 			if (ami_poll(sc, &iccb) != 0) {
457 				printf(": cannot do inquiry\n");
458 				goto free_mbox;
459 			}
460 		}
461 
462 		sc->sc_maxunits = AMI_MAX_LDRIVES;
463 		sc->sc_nunits = inq->ain_nlogdrv;
464 		ami_copyhds(sc, inq->ain_ldsize, inq->ain_ldprop,
465 		    inq->ain_ldstat);
466 
467 		bcopy (inq->ain_fwver, sc->sc_fwver, 4);
468 		sc->sc_fwver[4] = '\0';
469 		bcopy (inq->ain_biosver, sc->sc_biosver, 4);
470 		sc->sc_biosver[4] = '\0';
471 		sc->sc_channels = inq->ain_channels;
472 		sc->sc_targets = inq->ain_targets;
473 		sc->sc_memory = inq->ain_ramsize;
474 		sc->sc_maxcmds = inq->ain_maxcmd;
475 		sc->sc_drvinscnt = inq->ain_drvinscnt + 1; /* force scan */
476 		p = "target";
477 	}
478 
479 	if (sc->sc_flags & AMI_BROKEN) {
480 		sc->sc_maxcmds = 1;
481 		sc->sc_maxunits = 1;
482 	} else {
483 		sc->sc_maxunits = AMI_BIG_MAX_LDRIVES;
484 		if (sc->sc_maxcmds > AMI_MAXCMDS)
485 			sc->sc_maxcmds = AMI_MAXCMDS;
486 		/*
487 		 * Reserve ccb's for ioctl's and raw commands to
488 		 * processors/enclosures by lowering the number of
489 		 * openings available for logical units.
490 		 */
491 		sc->sc_maxcmds -= AMI_MAXIOCTLCMDS + AMI_MAXPROCS *
492 		    AMI_MAXRAWCMDS * sc->sc_channels;
493 	}
494 
495 	if (ami_alloc_ccbs(sc, AMI_MAXCMDS + 1) != 0) {
496 		/* error already printed */
497 		goto free_mbox;
498 	}
499 
500 	ami_freemem(sc, am);
501 
502 	/* hack for hp netraid version encoding */
503 	if ('A' <= sc->sc_fwver[2] && sc->sc_fwver[2] <= 'Z' &&
504 	    sc->sc_fwver[1] < ' ' && sc->sc_fwver[0] < ' ' &&
505 	    'A' <= sc->sc_biosver[2] && sc->sc_biosver[2] <= 'Z' &&
506 	    sc->sc_biosver[1] < ' ' && sc->sc_biosver[0] < ' ') {
507 
508 		snprintf(sc->sc_fwver, sizeof sc->sc_fwver, "%c.%02d.%02d",
509 		    sc->sc_fwver[2], sc->sc_fwver[1], sc->sc_fwver[0]);
510 		snprintf(sc->sc_biosver, sizeof sc->sc_biosver, "%c.%02d.%02d",
511 		    sc->sc_biosver[2], sc->sc_biosver[1], sc->sc_biosver[0]);
512 	}
513 
514 	/* TODO: fetch & print cache strategy */
515 	/* TODO: fetch & print scsi and raid info */
516 
517 #ifdef AMI_DEBUG
518 	printf(", FW %s, BIOS v%s, %dMB RAM\n"
519 	    "%s: %d channels, %d %ss, %d logical drives, "
520 	    "max commands %d, quirks: %04x\n",
521 	    sc->sc_fwver, sc->sc_biosver, sc->sc_memory, DEVNAME(sc),
522 	    sc->sc_channels, sc->sc_targets, p, sc->sc_nunits,
523 	    sc->sc_maxcmds, sc->sc_flags);
524 #else
525 	printf(", FW %s, BIOS v%s, %dMB RAM\n"
526 	    "%s: %d channels, %d %ss, %d logical drives\n",
527 	    sc->sc_fwver, sc->sc_biosver, sc->sc_memory, DEVNAME(sc),
528 	    sc->sc_channels, sc->sc_targets, p, sc->sc_nunits);
529 #endif /* AMI_DEBUG */
530 
531 	if (sc->sc_flags & AMI_BROKEN && sc->sc_nunits > 1)
532 		printf("%s: firmware buggy, limiting access to first logical "
533 		    "disk\n", DEVNAME(sc));
534 
535 	/* lock around ioctl requests */
536 	rw_init(&sc->sc_lock, NULL);
537 
538 	saa.saa_adapter_softc = sc;
539 	saa.saa_adapter = &ami_switch;
540 	saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET;
541 	saa.saa_adapter_buswidth = sc->sc_maxunits;
542 	saa.saa_luns = 8;
543 	saa.saa_openings = sc->sc_maxcmds;
544 	saa.saa_pool = &sc->sc_iopool;
545 	saa.saa_quirks = saa.saa_flags = 0;
546 	saa.saa_wwpn = saa.saa_wwnn = 0;
547 
548 	sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev, &saa,
549 	    scsiprint);
550 
551 	/* can't do bioctls, sensors, or pass-through on broken devices */
552 	if (sc->sc_flags & AMI_BROKEN)
553 		return (0);
554 
555 #if NBIO > 0
556 	if (bio_register(&sc->sc_dev, ami_ioctl) != 0)
557 		printf("%s: controller registration failed\n", DEVNAME(sc));
558 	else
559 		sc->sc_ioctl = ami_ioctl;
560 
561 #ifndef SMALL_KERNEL
562 	if (ami_create_sensors(sc) != 0)
563 		printf("%s: unable to create sensors\n", DEVNAME(sc));
564 #endif
565 #endif
566 
567 	rsc = mallocarray(sc->sc_channels, sizeof(struct ami_rawsoftc),
568 	    M_DEVBUF, M_NOWAIT|M_ZERO);
569 	if (!rsc) {
570 		printf("%s: no memory for raw interface\n", DEVNAME(sc));
571 		return (0);
572 	}
573 
574 	for (sc->sc_rawsoftcs = rsc;
575 	     rsc < &sc->sc_rawsoftcs[sc->sc_channels]; rsc++) {
576 
577 		struct scsibus_softc *ptbus;
578 		struct scsi_link *proclink;
579 		struct device *procdev;
580 
581 		rsc->sc_softc = sc;
582 		rsc->sc_channel = rsc - sc->sc_rawsoftcs;
583 		rsc->sc_proctarget = -1;
584 
585 		/* TODO fetch adapter_target from the controller */
586 
587 		saa.saa_adapter_softc = rsc;
588 		saa.saa_adapter = &ami_raw_switch;
589 		saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET;
590 		saa.saa_adapter_buswidth = 16;
591 		saa.saa_luns = 8;
592 		saa.saa_openings = sc->sc_maxcmds;
593 		saa.saa_pool = &sc->sc_iopool;
594 		saa.saa_quirks = saa.saa_flags = 0;
595 		saa.saa_wwpn = saa.saa_wwnn = 0;
596 
597 		ptbus = (struct scsibus_softc *)config_found(&sc->sc_dev,
598 		    &saa, scsiprint);
599 
600 		if (ptbus == NULL || rsc->sc_proctarget == -1)
601 			continue;
602 
603 		proclink = scsi_get_link(ptbus, rsc->sc_proctarget, 0);
604 		if (proclink == NULL)
605 			continue;
606 
607 		procdev = proclink->device_softc;
608 		strlcpy(rsc->sc_procdev, procdev->dv_xname,
609 		    sizeof(rsc->sc_procdev));
610 	}
611 
612 	return (0);
613 
614 free_mbox:
615 	ami_freemem(sc, sc->sc_mbox_am);
616 free_idata:
617 	ami_freemem(sc, am);
618 
619 	return (1);
620 }
621 
622 int
623 ami_quartz_init(struct ami_softc *sc)
624 {
625 	ami_write(sc, AMI_QIDB, 0);
626 
627 	return (0);
628 }
629 
630 int
631 ami_quartz_exec(struct ami_softc *sc, struct ami_iocmd *cmd)
632 {
633 	if (sc->sc_mbox->acc_busy) {
634 		AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
635 		return (EBUSY);
636 	}
637 
638 	memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16);
639 	bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,
640 	    sizeof(struct ami_iocmd), BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
641 
642 	sc->sc_mbox->acc_busy = 1;
643 	sc->sc_mbox->acc_poll = 0;
644 	sc->sc_mbox->acc_ack = 0;
645 
646 	ami_write(sc, AMI_QIDB, sc->sc_mbox_pa | htole32(AMI_QIDB_EXEC));
647 
648 	return (0);
649 }
650 
651 int
652 ami_quartz_done(struct ami_softc *sc, struct ami_iocmd *mbox)
653 {
654 	u_int32_t i, n;
655 	u_int8_t nstat, status;
656 	u_int8_t completed[AMI_MAXSTATACK];
657 
658 	if (ami_read(sc, AMI_QODB) != AMI_QODB_READY)
659 		return (0); /* nothing to do */
660 
661 	ami_write(sc, AMI_QODB, AMI_QODB_READY);
662 
663 	/*
664 	 * The following sequence is not supposed to have a timeout clause
665 	 * since the firmware has a "guarantee" that all commands will
666 	 * complete.  The choice is either panic or hoping for a miracle
667 	 * and that the IOs will complete much later.
668 	 */
669 	i = 0;
670 	while ((nstat = sc->sc_mbox->acc_nstat) == 0xff) {
671 		bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,
672 		    sizeof(struct ami_iocmd), BUS_DMASYNC_POSTREAD);
673 		delay(1);
674 		if (i++ > 1000000)
675 			return (0); /* nothing to do */
676 	}
677 	sc->sc_mbox->acc_nstat = 0xff;
678 	bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,
679 	    sizeof(struct ami_iocmd), BUS_DMASYNC_POSTWRITE);
680 
681 	/* wait until fw wrote out all completions */
682 	i = 0;
683 	AMI_DPRINTF(AMI_D_CMD, ("aqd %d ", nstat));
684 	for (n = 0; n < nstat; n++) {
685 		bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,
686 		    sizeof(struct ami_iocmd), BUS_DMASYNC_PREREAD);
687 		while ((completed[n] = sc->sc_mbox->acc_cmplidl[n]) == 0xff) {
688 			delay(1);
689 			if (i++ > 1000000)
690 				return (0); /* nothing to do */
691 		}
692 		sc->sc_mbox->acc_cmplidl[n] = 0xff;
693 		bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,
694 		    sizeof(struct ami_iocmd), BUS_DMASYNC_POSTWRITE);
695 	}
696 
697 	/* this should never happen, someone screwed up the completion status */
698 	if ((status = sc->sc_mbox->acc_status) == 0xff)
699 		panic("%s: status 0xff from the firmware", DEVNAME(sc));
700 
701 	sc->sc_mbox->acc_status = 0xff;
702 
703 	/* copy mailbox to temporary one and fixup other changed values */
704 	bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 16,
705 	    BUS_DMASYNC_POSTWRITE);
706 	memcpy(mbox, (struct ami_iocmd *)sc->sc_mbox, 16);
707 	mbox->acc_nstat = nstat;
708 	mbox->acc_status = status;
709 	for (n = 0; n < nstat; n++)
710 		mbox->acc_cmplidl[n] = completed[n];
711 
712 	/* ack interrupt */
713 	ami_write(sc, AMI_QIDB, AMI_QIDB_ACK);
714 
715 	return (1);	/* ready to complete all IOs in acc_cmplidl */
716 }
717 
718 int
719 ami_quartz_poll(struct ami_softc *sc, struct ami_iocmd *cmd)
720 {
721 	/* struct scsi_xfer *xs = ccb->ccb_xs; */
722 	u_int32_t i;
723 	u_int8_t status;
724 
725 	splassert(IPL_BIO);
726 
727 	if (sc->sc_dis_poll)
728 		return (-1); /* fail */
729 
730 	i = 0;
731 	while (sc->sc_mbox->acc_busy && (i < AMI_MAX_BUSYWAIT)) {
732 		delay(1);
733 		i++;
734 	}
735 	if (sc->sc_mbox->acc_busy) {
736 		AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
737 		return (-1);
738 	}
739 
740 	memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16);
741 	bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 16,
742 	    BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
743 
744 	sc->sc_mbox->acc_id = 0xfe;
745 	sc->sc_mbox->acc_busy = 1;
746 	sc->sc_mbox->acc_poll = 0;
747 	sc->sc_mbox->acc_ack = 0;
748 	sc->sc_mbox->acc_nstat = 0xff;
749 	sc->sc_mbox->acc_status = 0xff;
750 
751 	/* send command to firmware */
752 	ami_write(sc, AMI_QIDB, sc->sc_mbox_pa | htole32(AMI_QIDB_EXEC));
753 
754 	i = 0;
755 	while ((sc->sc_mbox->acc_nstat == 0xff) && (i < AMI_MAX_POLLWAIT)) {
756 		delay(1);
757 		i++;
758 	}
759 	if (i >= AMI_MAX_POLLWAIT) {
760 		printf("%s: command not accepted, polling disabled\n",
761 		    DEVNAME(sc));
762 		sc->sc_dis_poll = 1;
763 		return (-1);
764 	}
765 
766 	/* poll firmware */
767 	i = 0;
768 	while ((sc->sc_mbox->acc_poll != 0x77) && (i < AMI_MAX_POLLWAIT)) {
769 		delay(1);
770 		i++;
771 	}
772 	if (i >= AMI_MAX_POLLWAIT) {
773 		printf("%s: firmware didn't reply, polling disabled\n",
774 		    DEVNAME(sc));
775 		sc->sc_dis_poll = 1;
776 		return (-1);
777 	}
778 
779 	/* ack */
780 	ami_write(sc, AMI_QIDB, sc->sc_mbox_pa | htole32(AMI_QIDB_ACK));
781 
782 	i = 0;
783 	while((ami_read(sc, AMI_QIDB) & AMI_QIDB_ACK) &&
784 	    (i < AMI_MAX_POLLWAIT)) {
785 		delay(1);
786 		i++;
787 	}
788 	if (i >= AMI_MAX_POLLWAIT) {
789 		printf("%s: firmware didn't ack the ack, polling disabled\n",
790 		    DEVNAME(sc));
791 		sc->sc_dis_poll = 1;
792 		return (-1);
793 	}
794 
795 	sc->sc_mbox->acc_poll = 0;
796 	sc->sc_mbox->acc_ack = 0x77;
797 	status = sc->sc_mbox->acc_status;
798 	sc->sc_mbox->acc_nstat = 0xff;
799 	sc->sc_mbox->acc_status = 0xff;
800 
801 	for (i = 0; i < AMI_MAXSTATACK; i++)
802 		sc->sc_mbox->acc_cmplidl[i] = 0xff;
803 
804 	return (status);
805 }
806 
807 int
808 ami_schwartz_init(struct ami_softc *sc)
809 {
810 	u_int32_t a = (u_int32_t)sc->sc_mbox_pa;
811 
812 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, AMI_SMBADDR, a);
813 	/* XXX 40bit address ??? */
814 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SMBENA, 0);
815 
816 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_ACK);
817 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SIEM, AMI_SEIM_ENA |
818 	    bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SIEM));
819 
820 	return (0);
821 }
822 
823 int
824 ami_schwartz_exec(struct ami_softc *sc, struct ami_iocmd *cmd)
825 {
826 	if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT) &
827 	    AMI_SMBST_BUSY) {
828 		AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
829 		return (EBUSY);
830 	}
831 
832 	memcpy((struct ami_iocmd *)sc->sc_mbox, cmd, 16);
833 	sc->sc_mbox->acc_busy = 1;
834 	sc->sc_mbox->acc_poll = 0;
835 	sc->sc_mbox->acc_ack = 0;
836 
837 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_EXEC);
838 	return (0);
839 }
840 
841 int
842 ami_schwartz_done(struct ami_softc *sc, struct ami_iocmd *mbox)
843 {
844 	u_int8_t stat;
845 
846 #if 0
847 	/* do not scramble the busy mailbox */
848 	if (sc->sc_mbox->acc_busy)
849 		return (0);
850 #endif
851 	if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT) &
852 	    AMI_SMBST_BUSY)
853 		return (0);
854 
855 	stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT);
856 	if (stat & AMI_ISTAT_PEND) {
857 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT, stat);
858 
859 		*mbox = *sc->sc_mbox;
860 		AMI_DPRINTF(AMI_D_CMD, ("asd %d ", mbox->acc_nstat));
861 
862 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD,
863 		    AMI_SCMD_ACK);
864 
865 		return (1);
866 	}
867 
868 	return (0);
869 }
870 
871 int
872 ami_schwartz_poll(struct ami_softc *sc, struct ami_iocmd *mbox)
873 {
874 	u_int8_t status;
875 	u_int32_t i;
876 	int rv;
877 
878 	splassert(IPL_BIO);
879 
880 	if (sc->sc_dis_poll)
881 		return (-1); /* fail */
882 
883 	for (i = 0; i < AMI_MAX_POLLWAIT; i++) {
884 		if (!(bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT) &
885 		    AMI_SMBST_BUSY))
886 			break;
887 		delay(1);
888 	}
889 	if (i >= AMI_MAX_POLLWAIT) {
890 		AMI_DPRINTF(AMI_D_CMD, ("mbox_busy "));
891 		return (-1);
892 	}
893 
894 	memcpy((struct ami_iocmd *)sc->sc_mbox, mbox, 16);
895 	bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0, 16,
896 	    BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
897 
898 	sc->sc_mbox->acc_busy = 1;
899 	sc->sc_mbox->acc_poll = 0;
900 	sc->sc_mbox->acc_ack = 0;
901 	/* send command to firmware */
902 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_EXEC);
903 
904 	/* wait until no longer busy */
905 	for (i = 0; i < AMI_MAX_POLLWAIT; i++) {
906 		if (!(bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_SMBSTAT) &
907 		    AMI_SMBST_BUSY))
908 			break;
909 		delay(1);
910 	}
911 	if (i >= AMI_MAX_POLLWAIT) {
912 		printf("%s: command not accepted, polling disabled\n",
913 		    DEVNAME(sc));
914 		sc->sc_dis_poll = 1;
915 		return (-1);
916 	}
917 
918 	/* wait for interrupt bit */
919 	for (i = 0; i < AMI_MAX_POLLWAIT; i++) {
920 		status = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT);
921 		if (status & AMI_ISTAT_PEND)
922 			break;
923 		delay(1);
924 	}
925 	if (i >= AMI_MAX_POLLWAIT) {
926 		printf("%s: interrupt didn't arrive, polling disabled\n",
927 		    DEVNAME(sc));
928 		sc->sc_dis_poll = 1;
929 		return (-1);
930 	}
931 
932 	/* write ststus back to firmware */
933 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_ISTAT, status);
934 
935 	/* copy mailbox and status back */
936 	bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_mbox_am), 0,
937 	    sizeof(struct ami_iocmd), BUS_DMASYNC_PREREAD);
938 	*mbox = *sc->sc_mbox;
939 	rv = sc->sc_mbox->acc_status;
940 
941 	/* ack interrupt */
942 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AMI_SCMD, AMI_SCMD_ACK);
943 
944 	return (rv);
945 }
946 
947 void
948 ami_start_xs(struct ami_softc *sc, struct ami_ccb *ccb, struct scsi_xfer *xs)
949 {
950 	if (xs->flags & SCSI_POLL)
951 		ami_complete(sc, ccb, xs->timeout);
952 	else
953 		ami_start(sc, ccb);
954 }
955 
956 void
957 ami_start(struct ami_softc *sc, struct ami_ccb *ccb)
958 {
959 	mtx_enter(&sc->sc_cmd_mtx);
960 	ccb->ccb_state = AMI_CCB_PREQUEUED;
961 	TAILQ_INSERT_TAIL(&sc->sc_ccb_preq, ccb, ccb_link);
962 	mtx_leave(&sc->sc_cmd_mtx);
963 
964 	ami_runqueue(sc);
965 }
966 
967 void
968 ami_runqueue_tick(void *arg)
969 {
970 	ami_runqueue(arg);
971 }
972 
973 void
974 ami_runqueue(struct ami_softc *sc)
975 {
976 	struct ami_ccb *ccb;
977 	int add = 0;
978 
979 	mtx_enter(&sc->sc_cmd_mtx);
980 	if (!sc->sc_drainio) {
981 		while ((ccb = TAILQ_FIRST(&sc->sc_ccb_preq)) != NULL) {
982 			if (sc->sc_exec(sc, &ccb->ccb_cmd) != 0) {
983 				add = 1;
984 				break;
985 			}
986 
987 			TAILQ_REMOVE(&sc->sc_ccb_preq, ccb, ccb_link);
988 			ccb->ccb_state = AMI_CCB_QUEUED;
989 			TAILQ_INSERT_TAIL(&sc->sc_ccb_runq, ccb, ccb_link);
990 		}
991 	}
992 	mtx_leave(&sc->sc_cmd_mtx);
993 
994 	if (add)
995 		timeout_add(&sc->sc_run_tmo, 1);
996 }
997 
998 int
999 ami_poll(struct ami_softc *sc, struct ami_ccb *ccb)
1000 {
1001 	int error;
1002 
1003 	mtx_enter(&sc->sc_cmd_mtx);
1004 	error = sc->sc_poll(sc, &ccb->ccb_cmd);
1005 	if (error == -1)
1006 		ccb->ccb_flags |= AMI_CCB_F_ERR;
1007 	mtx_leave(&sc->sc_cmd_mtx);
1008 
1009 	ccb->ccb_done(sc, ccb);
1010 
1011 	return (error);
1012 }
1013 
1014 void
1015 ami_complete(struct ami_softc *sc, struct ami_ccb *ccb, int timeout)
1016 {
1017 	void (*done)(struct ami_softc *, struct ami_ccb *);
1018 	int ready;
1019 	int i = 0;
1020 	int s;
1021 
1022 	done = ccb->ccb_done;
1023 	ccb->ccb_done = ami_done_dummy;
1024 
1025 	/*
1026 	 * since exec will return if the mbox is busy we have to busy wait
1027 	 * ourselves. once its in, jam it into the runq.
1028 	 */
1029 	mtx_enter(&sc->sc_cmd_mtx);
1030 	while (i < AMI_MAX_BUSYWAIT) {
1031 		if (sc->sc_exec(sc, &ccb->ccb_cmd) == 0) {
1032 			ccb->ccb_state = AMI_CCB_QUEUED;
1033 			TAILQ_INSERT_TAIL(&sc->sc_ccb_runq, ccb, ccb_link);
1034 			break;
1035 		}
1036 		DELAY(1000);
1037 		i++;
1038 	}
1039 	ready = (ccb->ccb_state == AMI_CCB_QUEUED);
1040 	mtx_leave(&sc->sc_cmd_mtx);
1041 
1042 	if (!ready) {
1043 		ccb->ccb_flags |= AMI_CCB_F_ERR;
1044 		ccb->ccb_state = AMI_CCB_READY;
1045 		goto done;
1046 	}
1047 
1048 	/*
1049 	 * Override timeout for PERC3.  The first command triggers a chip
1050 	 * reset on the QL12160 chip which causes the firmware to reload.
1051 	 * 30000 is slightly less than double of how long it takes for the
1052 	 * firmware to be up again.  After the first two commands the
1053 	 * timeouts are as expected.
1054 	 */
1055 	timeout = MAX(30000, timeout); /* timeout */
1056 
1057 	while (ccb->ccb_state == AMI_CCB_QUEUED) {
1058 		s = splbio(); /* interrupt handlers are called at their IPL */
1059 		ready = ami_intr(sc);
1060 		splx(s);
1061 
1062 		if (ready == 0) {
1063 			if (timeout-- == 0) {
1064 				/* XXX */
1065 				printf("%s: timeout\n", DEVNAME(sc));
1066 				return;
1067 			}
1068 
1069 			delay(1000);
1070 			continue;
1071 		}
1072 	}
1073 
1074 done:
1075 	done(sc, ccb);
1076 }
1077 
1078 void
1079 ami_done_pt(struct ami_softc *sc, struct ami_ccb *ccb)
1080 {
1081 	struct scsi_xfer *xs = ccb->ccb_xs;
1082 	struct scsi_link *link = xs->sc_link;
1083 	struct ami_rawsoftc *rsc = link->bus->sb_adapter_softc;
1084 	u_int8_t target = link->target, type;
1085 
1086 	bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am),
1087 	    ccb->ccb_offset, sizeof(struct ami_ccbmem),
1088 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1089 
1090 	if (xs->data != NULL) {
1091 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
1092 		    ccb->ccb_dmamap->dm_mapsize,
1093 		    (xs->flags & SCSI_DATA_IN) ?
1094 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1095 
1096 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
1097 	}
1098 
1099 	xs->resid = 0;
1100 
1101 	if (ccb->ccb_flags & AMI_CCB_F_ERR)
1102 		xs->error = XS_DRIVER_STUFFUP;
1103  	else if (ccb->ccb_status != 0x00)
1104 		xs->error = XS_DRIVER_STUFFUP;
1105 	else if (xs->flags & SCSI_POLL && xs->cmd->opcode == INQUIRY) {
1106 		type = ((struct scsi_inquiry_data *)xs->data)->device &
1107 		    SID_TYPE;
1108 		if (!(type == T_PROCESSOR || type == T_ENCLOSURE))
1109 			xs->error = XS_DRIVER_STUFFUP;
1110 		else
1111 			rsc->sc_proctarget = target;
1112 	}
1113 
1114 	scsi_done(xs);
1115 }
1116 
1117 void
1118 ami_done_xs(struct ami_softc *sc, struct ami_ccb *ccb)
1119 {
1120 	struct scsi_xfer *xs = ccb->ccb_xs;
1121 
1122 	if (xs->data != NULL) {
1123 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
1124 		    ccb->ccb_dmamap->dm_mapsize,
1125 		    (xs->flags & SCSI_DATA_IN) ?
1126 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1127 
1128 		bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am),
1129 		    ccb->ccb_offset, sizeof(struct ami_ccbmem),
1130 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1131 
1132 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
1133 	}
1134 
1135 	xs->resid = 0;
1136 
1137 	if (ccb->ccb_flags & AMI_CCB_F_ERR)
1138 		xs->error = XS_DRIVER_STUFFUP;
1139 
1140 	scsi_done(xs);
1141 }
1142 
1143 void
1144 ami_done_flush(struct ami_softc *sc, struct ami_ccb *ccb)
1145 {
1146 	struct scsi_xfer *xs = ccb->ccb_xs;
1147 	struct ami_iocmd *cmd = &ccb->ccb_cmd;
1148 
1149 	if (ccb->ccb_flags & AMI_CCB_F_ERR) {
1150 		xs->error = XS_DRIVER_STUFFUP;
1151 		xs->resid = 0;
1152 
1153 		scsi_done(xs);
1154 		return;
1155 	}
1156 
1157 	/* reuse the ccb for the sysflush command */
1158 	ccb->ccb_done = ami_done_sysflush;
1159 	cmd->acc_cmd = AMI_SYSFLUSH;
1160 
1161 	ami_start_xs(sc, ccb, xs);
1162 }
1163 
1164 void
1165 ami_done_sysflush(struct ami_softc *sc, struct ami_ccb *ccb)
1166 {
1167 	struct scsi_xfer *xs = ccb->ccb_xs;
1168 
1169 	xs->resid = 0;
1170 	if (ccb->ccb_flags & AMI_CCB_F_ERR)
1171 		xs->error = XS_DRIVER_STUFFUP;
1172 
1173 	scsi_done(xs);
1174 }
1175 
1176 void
1177 ami_done_dummy(struct ami_softc *sc, struct ami_ccb *ccb)
1178 {
1179 }
1180 
1181 void
1182 ami_done_ioctl(struct ami_softc *sc, struct ami_ccb *ccb)
1183 {
1184 	wakeup(ccb);
1185 }
1186 
1187 void
1188 ami_done_init(struct ami_softc *sc, struct ami_ccb *ccb)
1189 {
1190 	/* the ccb is going to be reused, so do nothing with it */
1191 }
1192 
1193 void
1194 ami_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size)
1195 {
1196 	size_t copy_cnt;
1197 
1198 	AMI_DPRINTF(AMI_D_MISC, ("ami_copy_internal_data "));
1199 
1200 	if (!xs->datalen)
1201 		printf("uio move not yet supported\n");
1202 	else {
1203 		copy_cnt = MIN(size, xs->datalen);
1204 		bcopy(v, xs->data, copy_cnt);
1205 	}
1206 }
1207 
1208 void
1209 ami_scsi_raw_cmd(struct scsi_xfer *xs)
1210 {
1211 	struct scsi_link *link = xs->sc_link;
1212 	struct ami_rawsoftc *rsc = link->bus->sb_adapter_softc;
1213 	struct ami_softc *sc = rsc->sc_softc;
1214 	u_int8_t channel = rsc->sc_channel, target = link->target;
1215 	struct ami_ccb *ccb;
1216 
1217 	AMI_DPRINTF(AMI_D_CMD, ("ami_scsi_raw_cmd "));
1218 
1219 	if (xs->cmdlen > AMI_MAX_CDB) {
1220 		AMI_DPRINTF(AMI_D_CMD, ("CDB too big %p ", xs));
1221 		bzero(&xs->sense, sizeof(xs->sense));
1222 		xs->sense.error_code = SSD_ERRCODE_VALID | SSD_ERRCODE_CURRENT;
1223 		xs->sense.flags = SKEY_ILLEGAL_REQUEST;
1224 		xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */
1225 		xs->error = XS_SENSE;
1226 		scsi_done(xs);
1227 		return;
1228 	}
1229 
1230 	xs->error = XS_NOERROR;
1231 
1232 	ccb = xs->io;
1233 
1234 	memset(ccb->ccb_pt, 0, sizeof(struct ami_passthrough));
1235 
1236 	ccb->ccb_xs = xs;
1237 	ccb->ccb_done = ami_done_pt;
1238 
1239 	ccb->ccb_cmd.acc_cmd = AMI_PASSTHRU;
1240 	ccb->ccb_cmd.acc_passthru.apt_data = ccb->ccb_ptpa;
1241 
1242 	ccb->ccb_pt->apt_param = AMI_PTPARAM(AMI_TIMEOUT_6,1,0);
1243 	ccb->ccb_pt->apt_channel = channel;
1244 	ccb->ccb_pt->apt_target = target;
1245 	bcopy(xs->cmd, ccb->ccb_pt->apt_cdb, AMI_MAX_CDB);
1246 	ccb->ccb_pt->apt_ncdb = xs->cmdlen;
1247 	ccb->ccb_pt->apt_nsense = AMI_MAX_SENSE;
1248 	ccb->ccb_pt->apt_datalen = xs->datalen;
1249 	ccb->ccb_pt->apt_data = 0;
1250 
1251 	if (ami_load_ptmem(sc, ccb, xs->data, xs->datalen,
1252 	    xs->flags & SCSI_DATA_IN, xs->flags & SCSI_NOSLEEP) != 0) {
1253 		xs->error = XS_DRIVER_STUFFUP;
1254 		scsi_done(xs);
1255 		return;
1256 	}
1257 
1258 	ami_start_xs(sc, ccb, xs);
1259 }
1260 
1261 int
1262 ami_load_ptmem(struct ami_softc *sc, struct ami_ccb *ccb, void *data,
1263     size_t len, int read, int nowait)
1264 {
1265 	bus_dmamap_t dmap = ccb->ccb_dmamap;
1266 	bus_dma_segment_t *sgd;
1267 	int error, i;
1268 
1269 	if (data != NULL) {
1270 		error = bus_dmamap_load(sc->sc_dmat, dmap, data, len, NULL,
1271 		    nowait ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
1272 		if (error) {
1273 			if (error == EFBIG)
1274 				printf("more than %d dma segs\n",
1275 				    AMI_MAXOFFSETS);
1276 			else
1277 				printf("error %d loading dma map\n", error);
1278 
1279 			return (1);
1280 		}
1281 
1282 		sgd = dmap->dm_segs;
1283 		if (dmap->dm_nsegs > 1) {
1284 			struct ami_sgent *sgl = ccb->ccb_sglist;
1285 
1286 			ccb->ccb_pt->apt_nsge = dmap->dm_nsegs;
1287 			ccb->ccb_pt->apt_data = ccb->ccb_sglistpa;
1288 
1289 			for (i = 0; i < dmap->dm_nsegs; i++) {
1290 				sgl[i].asg_addr = htole32(sgd[i].ds_addr);
1291 				sgl[i].asg_len = htole32(sgd[i].ds_len);
1292 			}
1293 		} else {
1294 			ccb->ccb_pt->apt_nsge = 0;
1295 			ccb->ccb_pt->apt_data = htole32(sgd->ds_addr);
1296 		}
1297 
1298 		bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
1299 		    read ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
1300 	}
1301 
1302 	bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am),
1303 	    ccb->ccb_offset, sizeof(struct ami_ccbmem),
1304 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1305 
1306 	return (0);
1307 }
1308 
1309 void
1310 ami_scsi_cmd(struct scsi_xfer *xs)
1311 {
1312 	struct scsi_link *link = xs->sc_link;
1313 	struct ami_softc *sc = link->bus->sb_adapter_softc;
1314 	struct device *dev = link->device_softc;
1315 	struct ami_ccb *ccb;
1316 	struct ami_iocmd *cmd;
1317 	struct scsi_inquiry_data inq;
1318 	struct scsi_sense_data sd;
1319 	struct scsi_read_cap_data rcd;
1320 	u_int8_t target = link->target;
1321 	u_int32_t blockno, blockcnt;
1322 	struct scsi_rw *rw;
1323 	struct scsi_rw_big *rwb;
1324 	bus_dma_segment_t *sgd;
1325 	int error;
1326 	int i;
1327 
1328 	AMI_DPRINTF(AMI_D_CMD, ("ami_scsi_cmd "));
1329 
1330 	if (target >= sc->sc_nunits || !sc->sc_hdr[target].hd_present ||
1331 	    link->lun != 0) {
1332 		AMI_DPRINTF(AMI_D_CMD, ("no target %d ", target));
1333 		/* XXX should be XS_SENSE and sense filled out */
1334 		xs->error = XS_DRIVER_STUFFUP;
1335 		scsi_done(xs);
1336 		return;
1337 	}
1338 
1339 	xs->error = XS_NOERROR;
1340 
1341 	switch (xs->cmd->opcode) {
1342 	case READ_COMMAND:
1343 	case READ_BIG:
1344 	case WRITE_COMMAND:
1345 	case WRITE_BIG:
1346 		/* deal with io outside the switch */
1347 		break;
1348 
1349 	case SYNCHRONIZE_CACHE:
1350 		ccb = xs->io;
1351 
1352 		ccb->ccb_xs = xs;
1353 		ccb->ccb_done = ami_done_flush;
1354 		if (xs->timeout < 30000)
1355 			xs->timeout = 30000;	/* at least 30sec */
1356 
1357 		cmd = &ccb->ccb_cmd;
1358 		cmd->acc_cmd = AMI_FLUSH;
1359 
1360 		ami_start_xs(sc, ccb, xs);
1361 		return;
1362 
1363 	case TEST_UNIT_READY:
1364 		/* save off sd? after autoconf */
1365 		if (!cold)	/* XXX bogus */
1366 			strlcpy(sc->sc_hdr[target].dev, dev->dv_xname,
1367 			    sizeof(sc->sc_hdr[target].dev));
1368 	case START_STOP:
1369 #if 0
1370 	case VERIFY:
1371 #endif
1372 	case PREVENT_ALLOW:
1373 		AMI_DPRINTF(AMI_D_CMD, ("opc %d tgt %d ", xs->cmd->opcode,
1374 		    target));
1375 		xs->error = XS_NOERROR;
1376 		scsi_done(xs);
1377 		return;
1378 
1379 	case REQUEST_SENSE:
1380 		AMI_DPRINTF(AMI_D_CMD, ("REQUEST SENSE tgt %d ", target));
1381 		bzero(&sd, sizeof(sd));
1382 		sd.error_code = SSD_ERRCODE_CURRENT;
1383 		sd.segment = 0;
1384 		sd.flags = SKEY_NO_SENSE;
1385 		*(u_int32_t*)sd.info = htole32(0);
1386 		sd.extra_len = 0;
1387 		ami_copy_internal_data(xs, &sd, sizeof(sd));
1388 
1389 		xs->error = XS_NOERROR;
1390 		scsi_done(xs);
1391 		return;
1392 
1393 	case INQUIRY:
1394 		if (ISSET(((struct scsi_inquiry *)xs->cmd)->flags, SI_EVPD)) {
1395 			xs->error = XS_DRIVER_STUFFUP;
1396 			scsi_done(xs);
1397 			return;
1398 		}
1399 
1400 		AMI_DPRINTF(AMI_D_CMD, ("INQUIRY tgt %d ", target));
1401 		bzero(&inq, sizeof(inq));
1402 		inq.device = T_DIRECT;
1403 		inq.dev_qual2 = 0;
1404 		inq.version = 2;
1405 		inq.response_format = 2;
1406 		inq.additional_length = 32;
1407 		inq.flags |= SID_CmdQue;
1408 		strlcpy(inq.vendor, "AMI    ", sizeof(inq.vendor));
1409 		snprintf(inq.product, sizeof(inq.product),
1410 		    "Host drive  #%02d", target);
1411 		strlcpy(inq.revision, "   ", sizeof(inq.revision));
1412 		ami_copy_internal_data(xs, &inq, sizeof(inq));
1413 
1414 		xs->error = XS_NOERROR;
1415 		scsi_done(xs);
1416 		return;
1417 
1418 	case READ_CAPACITY:
1419 		AMI_DPRINTF(AMI_D_CMD, ("READ CAPACITY tgt %d ", target));
1420 		bzero(&rcd, sizeof(rcd));
1421 		_lto4b(sc->sc_hdr[target].hd_size - 1, rcd.addr);
1422 		_lto4b(AMI_SECTOR_SIZE, rcd.length);
1423 		ami_copy_internal_data(xs, &rcd, sizeof(rcd));
1424 
1425 		xs->error = XS_NOERROR;
1426 		scsi_done(xs);
1427 		return;
1428 
1429 	default:
1430 		AMI_DPRINTF(AMI_D_CMD, ("unsupported scsi command %#x tgt %d ",
1431 		    xs->cmd->opcode, target));
1432 
1433 		xs->error = XS_DRIVER_STUFFUP;
1434 		scsi_done(xs);
1435 		return;
1436 	}
1437 
1438 	/* A read or write operation. */
1439 	if (xs->cmdlen == 6) {
1440 		rw = (struct scsi_rw *)xs->cmd;
1441 		blockno = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff);
1442 		blockcnt = rw->length ? rw->length : 0x100;
1443 	} else {
1444 		rwb = (struct scsi_rw_big *)xs->cmd;
1445 		blockno = _4btol(rwb->addr);
1446 		blockcnt = _2btol(rwb->length);
1447 	}
1448 
1449 	if (blockno >= sc->sc_hdr[target].hd_size ||
1450 	    blockno + blockcnt > sc->sc_hdr[target].hd_size) {
1451 		printf("%s: out of bounds %u-%u >= %u\n", DEVNAME(sc),
1452 		    blockno, blockcnt, sc->sc_hdr[target].hd_size);
1453 		xs->error = XS_DRIVER_STUFFUP;
1454 		scsi_done(xs);
1455 		return;
1456 	}
1457 
1458 	ccb = xs->io;
1459 
1460 	ccb->ccb_xs = xs;
1461 	ccb->ccb_done = ami_done_xs;
1462 
1463 	cmd = &ccb->ccb_cmd;
1464 	cmd->acc_cmd = (xs->flags & SCSI_DATA_IN) ? AMI_READ : AMI_WRITE;
1465 	cmd->acc_mbox.amb_nsect = htole16(blockcnt);
1466 	cmd->acc_mbox.amb_lba = htole32(blockno);
1467 	cmd->acc_mbox.amb_ldn = target;
1468 
1469 	error = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap,
1470 	    xs->data, xs->datalen, NULL,
1471 	    (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
1472 	if (error) {
1473 		if (error == EFBIG)
1474 			printf("more than %d dma segs\n", AMI_MAXOFFSETS);
1475 		else
1476 			printf("error %d loading dma map\n", error);
1477 
1478 		xs->error = XS_DRIVER_STUFFUP;
1479 		scsi_done(xs);
1480 		return;
1481 	}
1482 
1483 	sgd = ccb->ccb_dmamap->dm_segs;
1484 	if (ccb->ccb_dmamap->dm_nsegs > 1) {
1485 		struct ami_sgent *sgl = ccb->ccb_sglist;
1486 
1487 		cmd->acc_mbox.amb_nsge = ccb->ccb_dmamap->dm_nsegs;
1488 		cmd->acc_mbox.amb_data = ccb->ccb_sglistpa;
1489 
1490 		for (i = 0; i < ccb->ccb_dmamap->dm_nsegs; i++) {
1491 			sgl[i].asg_addr = htole32(sgd[i].ds_addr);
1492 			sgl[i].asg_len = htole32(sgd[i].ds_len);
1493 		}
1494 	} else {
1495 		cmd->acc_mbox.amb_nsge = 0;
1496 		cmd->acc_mbox.amb_data = htole32(sgd->ds_addr);
1497 	}
1498 
1499 	bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am),
1500 	    ccb->ccb_offset, sizeof(struct ami_ccbmem),
1501 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1502 
1503 	bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
1504 	    ccb->ccb_dmamap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?
1505 	    BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
1506 
1507 	ami_start_xs(sc, ccb, xs);
1508 }
1509 
1510 int
1511 ami_intr(void *v)
1512 {
1513 	struct ami_iocmd mbox;
1514 	struct ami_softc *sc = v;
1515 	struct ami_ccb *ccb;
1516 	int i, rv = 0, ready;
1517 
1518 	mtx_enter(&sc->sc_cmd_mtx);
1519 	while (!TAILQ_EMPTY(&sc->sc_ccb_runq) && sc->sc_done(sc, &mbox)) {
1520 		AMI_DPRINTF(AMI_D_CMD, ("got#%d ", mbox.acc_nstat));
1521 		for (i = 0; i < mbox.acc_nstat; i++ ) {
1522 			ready = mbox.acc_cmplidl[i] - 1;
1523 			AMI_DPRINTF(AMI_D_CMD, ("ready=%d ", ready));
1524 
1525 			ccb = &sc->sc_ccbs[ready];
1526 			ccb->ccb_status = mbox.acc_status;
1527 			ccb->ccb_state = AMI_CCB_READY;
1528 			TAILQ_REMOVE(&ccb->ccb_sc->sc_ccb_runq, ccb, ccb_link);
1529 
1530 			mtx_leave(&sc->sc_cmd_mtx);
1531 			ccb->ccb_done(sc, ccb);
1532 			mtx_enter(&sc->sc_cmd_mtx);
1533 
1534 			rv = 1;
1535 		}
1536 	}
1537 	ready = (sc->sc_drainio && TAILQ_EMPTY(&sc->sc_ccb_runq));
1538 	mtx_leave(&sc->sc_cmd_mtx);
1539 
1540 	if (ready)
1541 		wakeup(sc);
1542 	else if (rv)
1543 		ami_runqueue(sc);
1544 
1545 	AMI_DPRINTF(AMI_D_INTR, ("exit "));
1546 	return (rv);
1547 }
1548 
1549 int
1550 ami_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag)
1551 {
1552 	struct ami_softc *sc = link->bus->sb_adapter_softc;
1553 	/* struct device *dev = (struct device *)link->device_softc; */
1554 	/* u_int8_t target = link->target; */
1555 
1556 	if (sc->sc_ioctl)
1557 		return (sc->sc_ioctl(&sc->sc_dev, cmd, addr));
1558 	else
1559 		return (ENOTTY);
1560 }
1561 
1562 #if NBIO > 0
1563 int
1564 ami_ioctl(struct device *dev, u_long cmd, caddr_t addr)
1565 {
1566 	struct ami_softc *sc = (struct ami_softc *)dev;
1567 	int error = 0;
1568 
1569 	AMI_DPRINTF(AMI_D_IOCTL, ("%s: ioctl ", DEVNAME(sc)));
1570 
1571 	if (sc->sc_flags & AMI_BROKEN)
1572 		return (ENODEV); /* can't do this to broken device for now */
1573 
1574 	switch (cmd) {
1575 	case BIOCINQ:
1576 		AMI_DPRINTF(AMI_D_IOCTL, ("inq "));
1577 		error = ami_ioctl_inq(sc, (struct bioc_inq *)addr);
1578 		break;
1579 
1580 	case BIOCVOL:
1581 		AMI_DPRINTF(AMI_D_IOCTL, ("vol "));
1582 		error = ami_ioctl_vol(sc, (struct bioc_vol *)addr);
1583 		break;
1584 
1585 	case BIOCDISK:
1586 		AMI_DPRINTF(AMI_D_IOCTL, ("disk "));
1587 		error = ami_ioctl_disk(sc, (struct bioc_disk *)addr);
1588 		break;
1589 
1590 	case BIOCALARM:
1591 		AMI_DPRINTF(AMI_D_IOCTL, ("alarm "));
1592 		error = ami_ioctl_alarm(sc, (struct bioc_alarm *)addr);
1593 		break;
1594 
1595 	case BIOCSETSTATE:
1596 		AMI_DPRINTF(AMI_D_IOCTL, ("setstate "));
1597 		error = ami_ioctl_setstate(sc, (struct bioc_setstate *)addr);
1598 		break;
1599 
1600 	default:
1601 		AMI_DPRINTF(AMI_D_IOCTL, (" invalid ioctl\n"));
1602 		error = ENOTTY;
1603 	}
1604 
1605 	return (error);
1606 }
1607 
1608 int
1609 ami_drv_pt(struct ami_softc *sc, u_int8_t ch, u_int8_t tg, u_int8_t *cmd,
1610     int clen, int blen, void *buf)
1611 {
1612 	struct ami_ccb *ccb;
1613 	struct ami_passthrough *pt;
1614 	int error = 0;
1615 
1616 	rw_enter_write(&sc->sc_lock);
1617 
1618 	ccb = scsi_io_get(&sc->sc_iopool, 0);
1619 	if (ccb == NULL) {
1620 		error = ENOMEM;
1621 		goto err;
1622 	}
1623 
1624 	ccb->ccb_done = ami_done_ioctl;
1625 
1626 	ccb->ccb_cmd.acc_cmd = AMI_PASSTHRU;
1627 	ccb->ccb_cmd.acc_passthru.apt_data = ccb->ccb_ptpa;
1628 
1629 	pt = ccb->ccb_pt;
1630 	memset(pt, 0, sizeof *pt);
1631 	pt->apt_channel = ch;
1632 	pt->apt_target = tg;
1633 	pt->apt_ncdb = clen;
1634 	pt->apt_nsense = sizeof(struct scsi_sense_data);
1635 	pt->apt_datalen = blen;
1636 	pt->apt_data = 0;
1637 
1638 	bcopy(cmd, pt->apt_cdb, clen);
1639 
1640 	if (ami_load_ptmem(sc, ccb, buf, blen, 1, 0) != 0) {
1641 		error = ENOMEM;
1642 		goto ptmemerr;
1643 	}
1644 
1645 	ami_start(sc, ccb);
1646 
1647 	while (ccb->ccb_state != AMI_CCB_READY)
1648 		tsleep_nsec(ccb, PRIBIO, "ami_drv_pt", INFSLP);
1649 
1650 	bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
1651 	    ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
1652 	bus_dmamap_sync(sc->sc_dmat, AMIMEM_MAP(sc->sc_ccbmem_am),
1653 	    ccb->ccb_offset, sizeof(struct ami_ccbmem),
1654 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1655 	bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
1656 
1657 	if (ccb->ccb_flags & AMI_CCB_F_ERR)
1658 		error = EIO;
1659 	else if (pt->apt_scsistat != 0x00)
1660 		error = EIO;
1661 
1662 ptmemerr:
1663 	scsi_io_put(&sc->sc_iopool, ccb);
1664 
1665 err:
1666 	rw_exit_write(&sc->sc_lock);
1667 	return (error);
1668 }
1669 
1670 int
1671 ami_drv_inq(struct ami_softc *sc, u_int8_t ch, u_int8_t tg, u_int8_t page,
1672     void *inqbuf)
1673 {
1674 	struct scsi_inquiry_data *inq = inqbuf;
1675 	u_int8_t cdb[6];
1676 	int error = 0;
1677 
1678 	bzero(&cdb, sizeof cdb);
1679 
1680 	cdb[0] = INQUIRY;
1681 	cdb[1] = 0;
1682 	cdb[2] = 0;
1683 	cdb[3] = 0;
1684 	cdb[4] = sizeof(struct scsi_inquiry_data);
1685 	cdb[5] = 0;
1686 	if (page != 0) {
1687 		cdb[1] = SI_EVPD;
1688 		cdb[2] = page;
1689 	}
1690 
1691 	error = ami_drv_pt(sc, ch, tg, cdb, 6, sizeof *inq, inqbuf);
1692 	if (error)
1693 		return (error);
1694 
1695 	if ((inq->device & SID_TYPE) != T_DIRECT)
1696 		error = EINVAL;
1697 
1698 	return (error);
1699 }
1700 
1701 int
1702 ami_drv_readcap(struct ami_softc *sc, u_int8_t ch, u_int8_t tg, daddr_t *sz)
1703 {
1704 	struct scsi_read_cap_data *rcd = NULL;
1705 	struct scsi_read_cap_data_16 *rcd16 = NULL;
1706 	u_int8_t cdb[16];
1707 	u_int32_t blksz;
1708 	daddr_t noblk;
1709 	int error = 0;
1710 
1711 	bzero(&cdb, sizeof cdb);
1712 	cdb[0] = READ_CAPACITY;
1713 	rcd = dma_alloc(sizeof(*rcd), PR_WAITOK);
1714 
1715 	error = ami_drv_pt(sc, ch, tg, cdb, 10, sizeof(*rcd), rcd);
1716 	if (error)
1717 		goto fail;
1718 
1719 	noblk = _4btol(rcd->addr);
1720 	if (noblk == 0xffffffffllu) {
1721 		/* huge disk */
1722 		bzero(&cdb, sizeof cdb);
1723 		cdb[0] = READ_CAPACITY_16;
1724 		rcd16 = dma_alloc(sizeof(*rcd16), PR_WAITOK);
1725 
1726 		error = ami_drv_pt(sc, ch, tg, cdb, 16, sizeof(*rcd16), rcd16);
1727 		if (error)
1728 			goto fail;
1729 
1730 		noblk = _8btol(rcd16->addr);
1731 		blksz = _4btol(rcd16->length);
1732 	} else
1733 		blksz = _4btol(rcd->length);
1734 
1735 	if (blksz == 0)
1736 		blksz = 512;
1737 	*sz = noblk * blksz;
1738 
1739 fail:
1740 	if (rcd16)
1741 		dma_free(rcd16, sizeof(*rcd16));
1742 	dma_free(rcd, sizeof(*rcd));
1743 	return (error);
1744 }
1745 
1746 int
1747 ami_mgmt(struct ami_softc *sc, u_int8_t opcode, u_int8_t par1, u_int8_t par2,
1748     u_int8_t par3, size_t size, void *buffer)
1749 {
1750 	struct ami_ccb *ccb;
1751 	struct ami_iocmd *cmd;
1752 	struct ami_mem *am = NULL;
1753 	char *idata = NULL;
1754 	int error = 0;
1755 
1756 	rw_enter_write(&sc->sc_lock);
1757 
1758 	if (opcode != AMI_CHSTATE) {
1759 		ccb = scsi_io_get(&sc->sc_iopool, 0);
1760 		if (ccb == NULL) {
1761 			error = ENOMEM;
1762 			goto err;
1763 		}
1764 		ccb->ccb_done = ami_done_ioctl;
1765 	} else
1766 		ccb = sc->sc_mgmtccb;
1767 
1768 	if (size) {
1769 		if ((am = ami_allocmem(sc, size)) == NULL) {
1770 			error = ENOMEM;
1771 			goto memerr;
1772 		}
1773 		idata = AMIMEM_KVA(am);
1774 	}
1775 
1776 	cmd = &ccb->ccb_cmd;
1777 	cmd->acc_cmd = opcode;
1778 
1779 	/*
1780 	 * some commands require data to be written to idata before sending
1781 	 * command to fw
1782 	 */
1783 	switch (opcode) {
1784 	case AMI_SPEAKER:
1785 		*idata = par1;
1786 		break;
1787 	default:
1788 		cmd->acc_io.aio_channel = par1;
1789 		cmd->acc_io.aio_param = par2;
1790 		cmd->acc_io.aio_pad[0] = par3;
1791 		break;
1792 	};
1793 
1794 	cmd->acc_io.aio_data = am ? htole32(AMIMEM_DVA(am)) : 0;
1795 
1796 	if (opcode != AMI_CHSTATE) {
1797 		ami_start(sc, ccb);
1798 		mtx_enter(&sc->sc_cmd_mtx);
1799 		while (ccb->ccb_state != AMI_CCB_READY)
1800 			msleep_nsec(ccb, &sc->sc_cmd_mtx, PRIBIO, "ami_mgmt",
1801 			    INFSLP);
1802 		mtx_leave(&sc->sc_cmd_mtx);
1803 	} else {
1804 		/* change state must be run with id 0xfe and MUST be polled */
1805 		mtx_enter(&sc->sc_cmd_mtx);
1806 		sc->sc_drainio = 1;
1807 		while (!TAILQ_EMPTY(&sc->sc_ccb_runq)) {
1808 			if (msleep_nsec(sc, &sc->sc_cmd_mtx, PRIBIO,
1809 			    "amimgmt", SEC_TO_NSEC(60)) == EWOULDBLOCK) {
1810 				printf("%s: drain io timeout\n", DEVNAME(sc));
1811 				ccb->ccb_flags |= AMI_CCB_F_ERR;
1812 				goto restartio;
1813 			}
1814 		}
1815 
1816 		error = sc->sc_poll(sc, &ccb->ccb_cmd);
1817 		if (error == -1)
1818 			ccb->ccb_flags |= AMI_CCB_F_ERR;
1819 
1820 restartio:
1821 		/* restart io */
1822 		sc->sc_drainio = 0;
1823 		mtx_leave(&sc->sc_cmd_mtx);
1824 		ami_runqueue(sc);
1825 	}
1826 
1827 	if (ccb->ccb_flags & AMI_CCB_F_ERR)
1828 		error = EIO;
1829 	else if (buffer && size)
1830 		memcpy(buffer, idata, size);
1831 
1832 	if (am)
1833 		ami_freemem(sc, am);
1834 memerr:
1835 	if (opcode != AMI_CHSTATE) {
1836 		scsi_io_put(&sc->sc_iopool, ccb);
1837 	} else {
1838 		ccb->ccb_flags = 0;
1839 		ccb->ccb_state = AMI_CCB_FREE;
1840 	}
1841 
1842 err:
1843 	rw_exit_write(&sc->sc_lock);
1844 	return (error);
1845 }
1846 
1847 int
1848 ami_ioctl_inq(struct ami_softc *sc, struct bioc_inq *bi)
1849 {
1850 	struct ami_big_diskarray *p; /* struct too large for stack */
1851 	struct scsi_inquiry_data *inqbuf;
1852 	struct ami_fc_einquiry einq;
1853 	int ch, tg;
1854 	int i, s, t, off;
1855 	int error = 0, changes = 0;
1856 
1857 	if ((error = ami_mgmt(sc, AMI_FCOP, AMI_FC_EINQ3,
1858 	    AMI_FC_EINQ3_SOLICITED_FULL, 0, sizeof einq, &einq)))
1859 		return (EINVAL);
1860 
1861 	inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK);
1862 
1863 	if (einq.ain_drvinscnt == sc->sc_drvinscnt) {
1864 		/* poke existing known drives to make sure they aren't gone */
1865 		for(i = 0; i < sc->sc_channels * 16; i++) {
1866 			if (sc->sc_plist[i] == 0)
1867 				continue;
1868 
1869 			ch = (i & 0xf0) >> 4;
1870 			tg = i & 0x0f;
1871 			if (ami_drv_inq(sc, ch, tg, 0, inqbuf)) {
1872 				/* drive is gone, force rescan */
1873 				changes = 1;
1874 				break;
1875 			}
1876 		}
1877 		if (changes == 0) {
1878 			bcopy(&sc->sc_bi, bi, sizeof *bi);
1879 			goto done;
1880 		}
1881 	}
1882 
1883 	sc->sc_drvinscnt = einq.ain_drvinscnt;
1884 
1885 	p = malloc(sizeof *p, M_DEVBUF, M_NOWAIT);
1886 	if (!p) {
1887 		error = ENOMEM;
1888 		goto done;
1889 	}
1890 
1891 	if ((error = ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, 0, sizeof *p,
1892 	    p))) {
1893 		error = EINVAL;
1894 		goto bail;
1895 	}
1896 
1897 	bzero(sc->sc_plist, sizeof sc->sc_plist);
1898 
1899 	bi->bi_novol = p->ada_nld;
1900 	bi->bi_nodisk = 0;
1901 	strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
1902 
1903 	/* count used disks, including failed ones */
1904 	for (i = 0; i < p->ada_nld; i++)
1905 		for (s = 0; s < p->ald[i].adl_spandepth; s++)
1906 			for (t = 0; t < p->ald[i].adl_nstripes; t++) {
1907 				off = p->ald[i].asp[s].adv[t].add_channel *
1908 				    AMI_MAX_TARGET +
1909 				    p->ald[i].asp[s].adv[t].add_target;
1910 
1911 				/* account for multi raid vol on same disk */
1912 				if (!sc->sc_plist[off]) {
1913 					sc->sc_plist[off] = 1;
1914 					bi->bi_nodisk++;
1915 				}
1916 			}
1917 
1918 	/* count unsued disks */
1919 	for(i = 0; i < sc->sc_channels * 16; i++) {
1920 	    	if (sc->sc_plist[i])
1921 			continue; /* skip claimed drives */
1922 
1923 		/*
1924 		 * hack to invalidate device type, needed for initiator id
1925 		 * on an unconnected channel.
1926 		 * XXX find out if we can determine this differently
1927 		 */
1928 		memset(inqbuf, 0xff, sizeof(*inqbuf));
1929 
1930 		ch = (i & 0xf0) >> 4;
1931 		tg = i & 0x0f;
1932 		if (!ami_drv_inq(sc, ch, tg, 0, inqbuf)) {
1933 			if ((inqbuf->device & SID_TYPE) != T_DIRECT)
1934 				continue;
1935 			bi->bi_novol++;
1936 			bi->bi_nodisk++;
1937 			sc->sc_plist[i] = 2;
1938 		} else
1939 			sc->sc_plist[i] = 0;
1940 	}
1941 
1942 	bcopy(bi, &sc->sc_bi, sizeof sc->sc_bi);
1943 	error = 0;
1944 bail:
1945 	free(p, M_DEVBUF, sizeof *p);
1946 done:
1947 	dma_free(inqbuf, sizeof(*inqbuf));
1948 	return (error);
1949 }
1950 
1951 int
1952 ami_vol(struct ami_softc *sc, struct bioc_vol *bv, struct ami_big_diskarray *p)
1953 {
1954 	int i, ld = p->ada_nld, error = EINVAL;
1955 
1956 	for(i = 0; i < sc->sc_channels * 16; i++) {
1957 	    	/* skip claimed/unused drives */
1958 	    	if (sc->sc_plist[i] != 2)
1959 			continue;
1960 
1961 		/* are we it? */
1962 		if (ld != bv->bv_volid) {
1963 			ld++;
1964 			continue;
1965 		}
1966 
1967 		bv->bv_status = BIOC_SVONLINE;
1968 		bv->bv_size = (uint64_t)p->apd[i].adp_size *
1969 		    (uint64_t)512;
1970 		bv->bv_nodisk = 1;
1971 		strlcpy(bv->bv_dev,
1972 		    sc->sc_hdr[bv->bv_volid].dev,
1973 		    sizeof(bv->bv_dev));
1974 
1975 		if (p->apd[i].adp_ostatus == AMI_PD_HOTSPARE
1976 		    && p->apd[i].adp_type == 0)
1977 			bv->bv_level = -1;
1978 		else
1979 			bv->bv_level = -2;
1980 
1981 		error = 0;
1982 		goto bail;
1983 	}
1984 
1985 bail:
1986 	return (error);
1987 }
1988 
1989 int
1990 ami_disk(struct ami_softc *sc, struct bioc_disk *bd,
1991     struct ami_big_diskarray *p)
1992 {
1993 	char vend[8+16+4+1], *vendp;
1994 	char ser[32 + 1];
1995 	struct scsi_inquiry_data *inqbuf;
1996 	struct scsi_vpd_serial *vpdbuf;
1997 	int i, ld = p->ada_nld, error = EINVAL;
1998 	u_int8_t ch, tg;
1999 	daddr_t sz = 0;
2000 
2001 	inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK);
2002 	vpdbuf = dma_alloc(sizeof(*vpdbuf), PR_WAITOK);
2003 
2004 	for(i = 0; i < sc->sc_channels * 16; i++) {
2005 	    	/* skip claimed/unused drives */
2006 	    	if (sc->sc_plist[i] != 2)
2007 			continue;
2008 
2009 		/* are we it? */
2010 		if (ld != bd->bd_volid) {
2011 			ld++;
2012 			continue;
2013 		}
2014 
2015 		ch = (i & 0xf0) >> 4;
2016 		tg = i & 0x0f;
2017 		if (ami_drv_inq(sc, ch, tg, 0, inqbuf))
2018 			goto bail;
2019 
2020 		vendp = inqbuf->vendor;
2021 		bcopy(vendp, vend, sizeof vend - 1);
2022 
2023 		vend[sizeof vend - 1] = '\0';
2024 		strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor));
2025 
2026 		if (!ami_drv_inq(sc, ch, tg, 0x80, vpdbuf)) {
2027 			bcopy(vpdbuf->serial, ser, sizeof ser - 1);
2028 			ser[sizeof ser - 1] = '\0';
2029 			if (_2btol(vpdbuf->hdr.page_length) < sizeof ser)
2030 				ser[_2btol(vpdbuf->hdr.page_length)] = '\0';
2031 			strlcpy(bd->bd_serial, ser, sizeof(bd->bd_serial));
2032 		}
2033 
2034 		error = ami_drv_readcap(sc, ch, tg, &sz);
2035 		if (error)
2036 			goto bail;
2037 
2038 		bd->bd_size = sz;
2039 		bd->bd_channel = ch;
2040 		bd->bd_target = tg;
2041 
2042 		strlcpy(bd->bd_procdev, sc->sc_rawsoftcs[ch].sc_procdev,
2043 		    sizeof(bd->bd_procdev));
2044 
2045 		if (p->apd[i].adp_ostatus == AMI_PD_HOTSPARE)
2046 			bd->bd_status = BIOC_SDHOTSPARE;
2047 		else
2048 			bd->bd_status = BIOC_SDUNUSED;
2049 
2050 #ifdef AMI_DEBUG
2051 		if (p->apd[i].adp_type != 0)
2052 			printf("invalid disk type: %d %d %x inquiry type: %x\n",
2053 			    ch, tg, p->apd[i].adp_type, inqbuf->device);
2054 #endif /* AMI_DEBUG */
2055 
2056 		error = 0;
2057 		goto bail;
2058 	}
2059 
2060 bail:
2061 	dma_free(inqbuf, sizeof(*inqbuf));
2062 	dma_free(vpdbuf, sizeof(*vpdbuf));
2063 	return (error);
2064 }
2065 
2066 int
2067 ami_ioctl_vol(struct ami_softc *sc, struct bioc_vol *bv)
2068 {
2069 	struct ami_big_diskarray *p; /* struct too large for stack */
2070 	int i, s, t, off;
2071 	int error = 0;
2072 	struct ami_progress perc;
2073 	u_int8_t bgi[5]; /* 40 LD, 1 bit per LD if BGI is active */
2074 
2075 	p = malloc(sizeof *p, M_DEVBUF, M_NOWAIT);
2076 	if (!p)
2077 		return (ENOMEM);
2078 
2079 	if ((error = ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, 0, sizeof *p, p)))
2080 		goto bail;
2081 
2082 	if (bv->bv_volid >= p->ada_nld) {
2083 		error = ami_vol(sc, bv, p);
2084 		goto bail;
2085 	}
2086 
2087 	i = bv->bv_volid;
2088 
2089 	switch (p->ald[i].adl_status) {
2090 	case AMI_RDRV_OFFLINE:
2091 		bv->bv_status = BIOC_SVOFFLINE;
2092 		break;
2093 
2094 	case AMI_RDRV_DEGRADED:
2095 		bv->bv_status = BIOC_SVDEGRADED;
2096 		break;
2097 
2098 	case AMI_RDRV_OPTIMAL:
2099 		bv->bv_status = BIOC_SVONLINE;
2100 		bv->bv_percent = -1;
2101 
2102 		/* get BGI progress here and over-ride status if so */
2103 		memset(bgi, 0, sizeof bgi);
2104 		if (ami_mgmt(sc, AMI_MISC, AMI_GET_BGI, 0, 0, sizeof bgi, &bgi))
2105 			break;
2106 
2107 		if ((bgi[i / 8] & (1 << i % 8)) == 0)
2108 			break;
2109 
2110 		if (!ami_mgmt(sc, AMI_GCHECKPROGR, i, 0, 0, sizeof perc, &perc))
2111 		    	if (perc.apr_progress < 100) {
2112 				bv->bv_status = BIOC_SVSCRUB;
2113 				bv->bv_percent = perc.apr_progress >= 100 ? -1 :
2114 				    perc.apr_progress;
2115 			}
2116 		break;
2117 
2118 	default:
2119 		bv->bv_status = BIOC_SVINVALID;
2120 	}
2121 
2122 	/* over-ride status if a pd is in rebuild status for this ld */
2123 	for (s = 0; s < p->ald[i].adl_spandepth; s++)
2124 		for (t = 0; t < p->ald[i].adl_nstripes; t++) {
2125 			off = p->ald[i].asp[s].adv[t].add_channel *
2126 			    AMI_MAX_TARGET +
2127 			    p->ald[i].asp[s].adv[t].add_target;
2128 
2129 			if (p->apd[off].adp_ostatus != AMI_PD_RBLD)
2130 				continue;
2131 
2132 			/* get rebuild progress from pd 0 */
2133 			bv->bv_status = BIOC_SVREBUILD;
2134 			if (ami_mgmt(sc, AMI_GRBLDPROGR,
2135 			    p->ald[i].asp[s].adv[t].add_channel,
2136 			    p->ald[i].asp[s].adv[t].add_target, 0,
2137 			    sizeof perc, &perc))
2138 				bv->bv_percent = -1;
2139 			else
2140 				bv->bv_percent = perc.apr_progress >= 100 ? -1 :
2141 				    perc.apr_progress;
2142 			break;
2143 		}
2144 
2145 	bv->bv_size = 0;
2146 	bv->bv_level = p->ald[i].adl_raidlvl;
2147 	bv->bv_nodisk = 0;
2148 
2149 	for (s = 0; s < p->ald[i].adl_spandepth; s++) {
2150 		for (t = 0; t < p->ald[i].adl_nstripes; t++)
2151 			bv->bv_nodisk++;
2152 
2153 		switch (bv->bv_level) {
2154 		case 0:
2155 			bv->bv_size += p->ald[i].asp[s].ads_length *
2156 			    p->ald[i].adl_nstripes;
2157 			break;
2158 
2159 		case 1:
2160 			bv->bv_size += p->ald[i].asp[s].ads_length;
2161 			break;
2162 
2163 		case 5:
2164 			bv->bv_size += p->ald[i].asp[s].ads_length *
2165 			    (p->ald[i].adl_nstripes - 1);
2166 			break;
2167 		}
2168 	}
2169 
2170 	if (p->ald[i].adl_spandepth > 1)
2171 		bv->bv_level *= 10;
2172 
2173 	bv->bv_size *= (uint64_t)512;
2174 
2175 	strlcpy(bv->bv_dev, sc->sc_hdr[i].dev, sizeof(bv->bv_dev));
2176 
2177 bail:
2178 	free(p, M_DEVBUF, sizeof *p);
2179 
2180 	return (error);
2181 }
2182 
2183 int
2184 ami_ioctl_disk(struct ami_softc *sc, struct bioc_disk *bd)
2185 {
2186 	struct scsi_inquiry_data *inqbuf;
2187 	struct scsi_vpd_serial *vpdbuf;
2188 	struct ami_big_diskarray *p; /* struct too large for stack */
2189 	int i, s, t, d;
2190 	int off;
2191 	int error = EINVAL;
2192 	u_int16_t ch, tg;
2193 	char vend[8+16+4+1], *vendp;
2194 	char ser[32 + 1];
2195 
2196 	inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK);
2197 	vpdbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK);
2198 	p = malloc(sizeof *p, M_DEVBUF, M_WAITOK);
2199 
2200 	if ((error = ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, 0, sizeof *p, p)))
2201 		goto bail;
2202 
2203 	if (bd->bd_volid >= p->ada_nld) {
2204 		error = ami_disk(sc, bd, p);
2205 		goto bail;
2206 	}
2207 
2208 	i = bd->bd_volid;
2209 	for (s = 0, d = 0; s < p->ald[i].adl_spandepth; s++)
2210 		for (t = 0; t < p->ald[i].adl_nstripes; t++) {
2211 			if (d != bd->bd_diskid) {
2212 				d++;
2213 				continue;
2214 			}
2215 
2216 			off = p->ald[i].asp[s].adv[t].add_channel *
2217 			    AMI_MAX_TARGET +
2218 			    p->ald[i].asp[s].adv[t].add_target;
2219 
2220 			bd->bd_size = (uint64_t)p->apd[off].adp_size *
2221 			    (uint64_t)512;
2222 
2223 			switch (p->apd[off].adp_ostatus) {
2224 			case AMI_PD_UNCNF:
2225 				bd->bd_status = BIOC_SDUNUSED;
2226 				break;
2227 
2228 			case AMI_PD_ONLINE:
2229 				bd->bd_status = BIOC_SDONLINE;
2230 				break;
2231 
2232 			case AMI_PD_FAILED:
2233 				bd->bd_status = BIOC_SDFAILED;
2234 				bd->bd_size = 0;
2235 				break;
2236 
2237 			case AMI_PD_RBLD:
2238 				bd->bd_status = BIOC_SDREBUILD;
2239 				break;
2240 
2241 			case AMI_PD_HOTSPARE:
2242 				bd->bd_status = BIOC_SDHOTSPARE;
2243 				break;
2244 
2245 			default:
2246 				bd->bd_status = BIOC_SDINVALID;
2247 				bd->bd_size = 0;
2248 			}
2249 
2250 
2251 			ch = p->ald[i].asp[s].adv[t].add_target >> 4;
2252 			tg = p->ald[i].asp[s].adv[t].add_target & 0x0f;
2253 
2254 			bd->bd_channel = ch;
2255 			bd->bd_target = tg;
2256 			strlcpy(bd->bd_procdev, sc->sc_rawsoftcs[ch].sc_procdev,
2257 			    sizeof(bd->bd_procdev));
2258 
2259 			/* if we are failed don't query drive */
2260 			if (bd->bd_size == 0) {
2261 				bzero(&bd->bd_vendor, sizeof(bd->bd_vendor));
2262 				bzero(&bd->bd_serial, sizeof(bd->bd_serial));
2263 				goto done;
2264 			}
2265 
2266 			if (!ami_drv_inq(sc, ch, tg, 0, inqbuf)) {
2267 				vendp = inqbuf->vendor;
2268 				bcopy(vendp, vend, sizeof vend - 1);
2269 				vend[sizeof vend - 1] = '\0';
2270 				strlcpy(bd->bd_vendor, vend,
2271 				    sizeof(bd->bd_vendor));
2272 			}
2273 
2274 			if (!ami_drv_inq(sc, ch, tg, 0x80, vpdbuf)) {
2275 				bcopy(vpdbuf->serial, ser, sizeof ser - 1);
2276 				ser[sizeof ser - 1] = '\0';
2277 				if (_2btol(vpdbuf->hdr.page_length) <
2278 				    sizeof(ser))
2279 					ser[_2btol(vpdbuf->hdr.page_length)] =
2280 					    '\0';
2281 				strlcpy(bd->bd_serial, ser,
2282 				    sizeof(bd->bd_serial));
2283 			}
2284 			goto done;
2285 		}
2286 
2287 done:
2288 	error = 0;
2289 bail:
2290 	free(p, M_DEVBUF, sizeof *p);
2291 	dma_free(vpdbuf, sizeof(*vpdbuf));
2292 	dma_free(inqbuf, sizeof(*inqbuf));
2293 
2294 	return (error);
2295 }
2296 
2297 int ami_ioctl_alarm(struct ami_softc *sc, struct bioc_alarm *ba)
2298 {
2299 	int error = 0;
2300 	u_int8_t func, ret;
2301 
2302 	switch(ba->ba_opcode) {
2303 	case BIOC_SADISABLE:
2304 		func = AMI_SPKR_OFF;
2305 		break;
2306 
2307 	case BIOC_SAENABLE:
2308 		func = AMI_SPKR_ON;
2309 		break;
2310 
2311 	case BIOC_SASILENCE:
2312 		func = AMI_SPKR_SHUT;
2313 		break;
2314 
2315 	case BIOC_GASTATUS:
2316 		func = AMI_SPKR_GVAL;
2317 		break;
2318 
2319 	case BIOC_SATEST:
2320 		func = AMI_SPKR_TEST;
2321 		break;
2322 
2323 	default:
2324 		AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocalarm invalid opcode %x\n",
2325 		    DEVNAME(sc), ba->ba_opcode));
2326 		return (EINVAL);
2327 	}
2328 
2329 	if (!(error = ami_mgmt(sc, AMI_SPEAKER, func, 0, 0, sizeof ret,
2330 	    &ret))) {
2331 		if (ba->ba_opcode == BIOC_GASTATUS)
2332 			ba->ba_status = ret;
2333 		else
2334 			ba->ba_status = 0;
2335 	}
2336 
2337 	return (error);
2338 }
2339 
2340 int
2341 ami_ioctl_setstate(struct ami_softc *sc, struct bioc_setstate *bs)
2342 {
2343 	struct scsi_inquiry_data *inqbuf;
2344 	int func, error = 0;
2345 
2346 	inqbuf = dma_alloc(sizeof(*inqbuf), PR_WAITOK);
2347 
2348 	switch (bs->bs_status) {
2349 	case BIOC_SSONLINE:
2350 		func = AMI_STATE_ON;
2351 		break;
2352 
2353 	case BIOC_SSOFFLINE:
2354 		func = AMI_STATE_FAIL;
2355 		break;
2356 
2357 	case BIOC_SSHOTSPARE:
2358 		if (ami_drv_inq(sc, bs->bs_channel, bs->bs_target, 0,
2359 		    inqbuf)) {
2360 			error = EINVAL;
2361 			goto done;
2362 		}
2363 
2364 		func = AMI_STATE_SPARE;
2365 		break;
2366 
2367 	default:
2368 		AMI_DPRINTF(AMI_D_IOCTL, ("%s: biocsetstate invalid opcode %x\n"
2369 		    , DEVNAME(sc), bs->bs_status));
2370 		error = EINVAL;
2371 		goto done;
2372 	}
2373 
2374 	if ((error = ami_mgmt(sc, AMI_CHSTATE, bs->bs_channel, bs->bs_target,
2375 	    func, 0, NULL)))
2376 		goto done;
2377 
2378 done:
2379 	dma_free(inqbuf, sizeof(*inqbuf));
2380 	return (error);
2381 }
2382 
2383 #ifndef SMALL_KERNEL
2384 int
2385 ami_create_sensors(struct ami_softc *sc)
2386 {
2387 	struct device *dev;
2388 	struct scsibus_softc *ssc = NULL;
2389 	struct scsi_link *link;
2390 	int i;
2391 
2392 	TAILQ_FOREACH(dev, &alldevs, dv_list) {
2393 		if (dev->dv_parent != &sc->sc_dev)
2394 			continue;
2395 
2396 		/* check if this is the scsibus for the logical disks */
2397 		ssc = (struct scsibus_softc *)dev;
2398 		if (ssc == sc->sc_scsibus)
2399 			break;
2400 	}
2401 
2402 	if (ssc == NULL)
2403 		return (1);
2404 
2405 	sc->sc_sensors = mallocarray(sc->sc_nunits, sizeof(struct ksensor),
2406 	    M_DEVBUF, M_WAITOK|M_CANFAIL|M_ZERO);
2407 	if (sc->sc_sensors == NULL)
2408 		return (1);
2409 
2410 	strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
2411 	    sizeof(sc->sc_sensordev.xname));
2412 
2413 	for (i = 0; i < sc->sc_nunits; i++) {
2414 		link = scsi_get_link(ssc, i, 0);
2415 		if (link == NULL)
2416 			goto bad;
2417 
2418 		dev = link->device_softc;
2419 
2420 		sc->sc_sensors[i].type = SENSOR_DRIVE;
2421 		sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
2422 
2423 		strlcpy(sc->sc_sensors[i].desc, dev->dv_xname,
2424 		    sizeof(sc->sc_sensors[i].desc));
2425 
2426 		sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
2427 	}
2428 
2429 	sc->sc_bd = malloc(sizeof(*sc->sc_bd), M_DEVBUF, M_WAITOK|M_CANFAIL);
2430 	if (sc->sc_bd == NULL)
2431 		goto bad;
2432 
2433 	if (sensor_task_register(sc, ami_refresh_sensors, 10) == NULL)
2434 		goto freebd;
2435 
2436 	sensordev_install(&sc->sc_sensordev);
2437 
2438 	return (0);
2439 
2440 freebd:
2441 	free(sc->sc_bd, M_DEVBUF, sizeof(*sc->sc_bd));
2442 bad:
2443 	free(sc->sc_sensors, M_DEVBUF, sc->sc_nunits * sizeof(struct ksensor));
2444 
2445 	return (1);
2446 }
2447 
2448 void
2449 ami_refresh_sensors(void *arg)
2450 {
2451 	struct ami_softc *sc = arg;
2452 	int i;
2453 
2454 	if (ami_mgmt(sc, AMI_FCOP, AMI_FC_RDCONF, 0, 0, sizeof(*sc->sc_bd),
2455 	    sc->sc_bd)) {
2456 		for (i = 0; i < sc->sc_nunits; i++) {
2457 			sc->sc_sensors[i].value = 0; /* unknown */
2458 			sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
2459 		}
2460 		return;
2461 	}
2462 
2463 	for (i = 0; i < sc->sc_nunits; i++) {
2464 		switch (sc->sc_bd->ald[i].adl_status) {
2465 		case AMI_RDRV_OFFLINE:
2466 			sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL;
2467 			sc->sc_sensors[i].status = SENSOR_S_CRIT;
2468 			break;
2469 
2470 		case AMI_RDRV_DEGRADED:
2471 			sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL;
2472 			sc->sc_sensors[i].status = SENSOR_S_WARN;
2473 			break;
2474 
2475 		case AMI_RDRV_OPTIMAL:
2476 			sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE;
2477 			sc->sc_sensors[i].status = SENSOR_S_OK;
2478 			break;
2479 
2480 		default:
2481 			sc->sc_sensors[i].value = 0; /* unknown */
2482 			sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
2483 		}
2484 	}
2485 }
2486 #endif /* SMALL_KERNEL */
2487 #endif /* NBIO > 0 */
2488 
2489 #ifdef AMI_DEBUG
2490 void
2491 ami_print_mbox(struct ami_iocmd *mbox)
2492 {
2493 	int i;
2494 
2495 	printf("acc_cmd: %d  aac_id: %d  acc_busy: %d  acc_nstat: %d  ",
2496 	    mbox->acc_cmd, mbox->acc_id, mbox->acc_busy, mbox->acc_nstat);
2497 	printf("acc_status: %d  acc_poll: %d  acc_ack: %d\n",
2498 	    mbox->acc_status, mbox->acc_poll, mbox->acc_ack);
2499 
2500 	printf("acc_cmplidl: ");
2501 	for (i = 0; i < AMI_MAXSTATACK; i++) {
2502 		printf("[%d] = %d  ", i, mbox->acc_cmplidl[i]);
2503 	}
2504 
2505 	printf("\n");
2506 }
2507 #endif /* AMI_DEBUG */
2508