xref: /openbsd-src/sys/dev/ic/mpi.c (revision 696a249da7aee455c48eb2f0ec348d2894318db5)
1 /*	$OpenBSD: mpi.c,v 1.100 2008/10/28 11:27:53 marco Exp $ */
2 
3 /*
4  * Copyright (c) 2005, 2006 David Gwynne <dlg@openbsd.org>
5  * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "bio.h"
21 
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/buf.h>
25 #include <sys/device.h>
26 #include <sys/ioctl.h>
27 #include <sys/proc.h>
28 #include <sys/malloc.h>
29 #include <sys/kernel.h>
30 #include <sys/rwlock.h>
31 #include <sys/sensors.h>
32 
33 #include <machine/bus.h>
34 
35 #include <scsi/scsi_all.h>
36 #include <scsi/scsiconf.h>
37 
38 #include <dev/biovar.h>
39 #include <dev/ic/mpireg.h>
40 #include <dev/ic/mpivar.h>
41 
42 #ifdef MPI_DEBUG
43 uint32_t	mpi_debug = 0
44 /*		    | MPI_D_CMD */
45 /*		    | MPI_D_INTR */
46 /*		    | MPI_D_MISC */
47 /*		    | MPI_D_DMA */
48 /*		    | MPI_D_IOCTL */
49 /*		    | MPI_D_RW */
50 /*		    | MPI_D_MEM */
51 /*		    | MPI_D_CCB */
52 /*		    | MPI_D_PPR */
53 /*		    | MPI_D_RAID */
54 /*		    | MPI_D_EVT */
55 		;
56 #endif
57 
58 struct cfdriver mpi_cd = {
59 	NULL,
60 	"mpi",
61 	DV_DULL
62 };
63 
64 int			mpi_scsi_cmd(struct scsi_xfer *);
65 void			mpi_scsi_cmd_done(struct mpi_ccb *);
66 void			mpi_minphys(struct buf *bp);
67 int			mpi_scsi_probe(struct scsi_link *);
68 int			mpi_scsi_ioctl(struct scsi_link *, u_long, caddr_t,
69 			    int, struct proc *);
70 
71 struct scsi_adapter mpi_switch = {
72 	mpi_scsi_cmd,
73 	mpi_minphys,
74 	mpi_scsi_probe,
75 	NULL,
76 	mpi_scsi_ioctl
77 };
78 
79 struct scsi_device mpi_dev = {
80 	NULL,
81 	NULL,
82 	NULL,
83 	NULL
84 };
85 
86 struct mpi_dmamem	*mpi_dmamem_alloc(struct mpi_softc *, size_t);
87 void			mpi_dmamem_free(struct mpi_softc *,
88 			    struct mpi_dmamem *);
89 int			mpi_alloc_ccbs(struct mpi_softc *);
90 struct mpi_ccb		*mpi_get_ccb(struct mpi_softc *);
91 void			mpi_put_ccb(struct mpi_softc *, struct mpi_ccb *);
92 int			mpi_alloc_replies(struct mpi_softc *);
93 void			mpi_push_replies(struct mpi_softc *);
94 
95 void			mpi_start(struct mpi_softc *, struct mpi_ccb *);
96 int			mpi_complete(struct mpi_softc *, struct mpi_ccb *, int);
97 int			mpi_poll(struct mpi_softc *, struct mpi_ccb *, int);
98 int			mpi_reply(struct mpi_softc *, u_int32_t);
99 
100 int			mpi_cfg_spi_port(struct mpi_softc *);
101 void			mpi_squash_ppr(struct mpi_softc *);
102 void			mpi_run_ppr(struct mpi_softc *);
103 int			mpi_ppr(struct mpi_softc *, struct scsi_link *,
104 			    struct mpi_cfg_raid_physdisk *, int, int, int);
105 int			mpi_inq(struct mpi_softc *, u_int16_t, int);
106 
107 void			mpi_timeout_xs(void *);
108 int			mpi_load_xs(struct mpi_ccb *);
109 
110 u_int32_t		mpi_read(struct mpi_softc *, bus_size_t);
111 void			mpi_write(struct mpi_softc *, bus_size_t, u_int32_t);
112 int			mpi_wait_eq(struct mpi_softc *, bus_size_t, u_int32_t,
113 			    u_int32_t);
114 int			mpi_wait_ne(struct mpi_softc *, bus_size_t, u_int32_t,
115 			    u_int32_t);
116 
117 int			mpi_init(struct mpi_softc *);
118 int			mpi_reset_soft(struct mpi_softc *);
119 int			mpi_reset_hard(struct mpi_softc *);
120 
121 int			mpi_handshake_send(struct mpi_softc *, void *, size_t);
122 int			mpi_handshake_recv_dword(struct mpi_softc *,
123 			    u_int32_t *);
124 int			mpi_handshake_recv(struct mpi_softc *, void *, size_t);
125 
126 void			mpi_empty_done(struct mpi_ccb *);
127 
128 int			mpi_iocinit(struct mpi_softc *);
129 int			mpi_iocfacts(struct mpi_softc *);
130 int			mpi_portfacts(struct mpi_softc *);
131 int			mpi_portenable(struct mpi_softc *);
132 void			mpi_get_raid(struct mpi_softc *);
133 int			mpi_fwupload(struct mpi_softc *);
134 
135 int			mpi_eventnotify(struct mpi_softc *);
136 void			mpi_eventnotify_done(struct mpi_ccb *);
137 void			mpi_eventack(struct mpi_softc *,
138 			    struct mpi_msg_event_reply *);
139 void			mpi_eventack_done(struct mpi_ccb *);
140 void			mpi_evt_sas(void *, void *);
141 
142 int			mpi_req_cfg_header(struct mpi_softc *, u_int8_t,
143 			    u_int8_t, u_int32_t, int, void *);
144 int			mpi_req_cfg_page(struct mpi_softc *, u_int32_t, int,
145 			    void *, int, void *, size_t);
146 
147 #if NBIO > 0
148 int		mpi_ioctl(struct device *, u_long, caddr_t);
149 int		mpi_ioctl_inq(struct mpi_softc *, struct bioc_inq *);
150 int		mpi_ioctl_vol(struct mpi_softc *, struct bioc_vol *);
151 int		mpi_ioctl_disk(struct mpi_softc *, struct bioc_disk *);
152 int		mpi_ioctl_setstate(struct mpi_softc *, struct bioc_setstate *);
153 #ifndef SMALL_KERNEL
154 int		mpi_create_sensors(struct mpi_softc *);
155 void		mpi_refresh_sensors(void *);
156 #endif /* SMALL_KERNEL */
157 #endif /* NBIO > 0 */
158 
159 #define DEVNAME(s)		((s)->sc_dev.dv_xname)
160 
161 #define	dwordsof(s)		(sizeof(s) / sizeof(u_int32_t))
162 #define	sizeofa(s)		(sizeof(s) / sizeof((s)[0]))
163 
164 #define mpi_read_db(s)		mpi_read((s), MPI_DOORBELL)
165 #define mpi_write_db(s, v)	mpi_write((s), MPI_DOORBELL, (v))
166 #define mpi_read_intr(s)	mpi_read((s), MPI_INTR_STATUS)
167 #define mpi_write_intr(s, v)	mpi_write((s), MPI_INTR_STATUS, (v))
168 #define mpi_pop_reply(s)	mpi_read((s), MPI_REPLY_QUEUE)
169 #define mpi_push_reply(s, v)	mpi_write((s), MPI_REPLY_QUEUE, (v))
170 
171 #define mpi_wait_db_int(s)	mpi_wait_ne((s), MPI_INTR_STATUS, \
172 				    MPI_INTR_STATUS_DOORBELL, 0)
173 #define mpi_wait_db_ack(s)	mpi_wait_eq((s), MPI_INTR_STATUS, \
174 				    MPI_INTR_STATUS_IOCDOORBELL, 0)
175 
176 #define mpi_cfg_header(_s, _t, _n, _a, _h) \
177 	mpi_req_cfg_header((_s), (_t), (_n), (_a), 0, (_h))
178 #define mpi_ecfg_header(_s, _t, _n, _a, _h) \
179 	mpi_req_cfg_header((_s), (_t), (_n), (_a), 1, (_h))
180 
181 #define mpi_cfg_page(_s, _a, _h, _r, _p, _l) \
182 	mpi_req_cfg_page((_s), (_a), 0, (_h), (_r), (_p), (_l))
183 #define mpi_ecfg_page(_s, _a, _h, _r, _p, _l) \
184 	mpi_req_cfg_page((_s), (_a), 1, (_h), (_r), (_p), (_l))
185 
186 int
187 mpi_attach(struct mpi_softc *sc)
188 {
189 	struct scsibus_attach_args	saa;
190 	struct mpi_ccb			*ccb;
191 
192 	printf("\n");
193 
194 	/* disable interrupts */
195 	mpi_write(sc, MPI_INTR_MASK,
196 	    MPI_INTR_MASK_REPLY | MPI_INTR_MASK_DOORBELL);
197 
198 	if (mpi_init(sc) != 0) {
199 		printf("%s: unable to initialise\n", DEVNAME(sc));
200 		return (1);
201 	}
202 
203 	if (mpi_iocfacts(sc) != 0) {
204 		printf("%s: unable to get iocfacts\n", DEVNAME(sc));
205 		return (1);
206 	}
207 
208 	if (mpi_alloc_ccbs(sc) != 0) {
209 		/* error already printed */
210 		return (1);
211 	}
212 
213 	if (mpi_alloc_replies(sc) != 0) {
214 		printf("%s: unable to allocate reply space\n", DEVNAME(sc));
215 		goto free_ccbs;
216 	}
217 
218 	if (mpi_iocinit(sc) != 0) {
219 		printf("%s: unable to send iocinit\n", DEVNAME(sc));
220 		goto free_ccbs;
221 	}
222 
223 	/* spin until we're operational */
224 	if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
225 	    MPI_DOORBELL_STATE_OPER) != 0) {
226 		printf("%s: state: 0x%08x\n", DEVNAME(sc),
227 		    mpi_read_db(sc) & MPI_DOORBELL_STATE);
228 		printf("%s: operational state timeout\n", DEVNAME(sc));
229 		goto free_ccbs;
230 	}
231 
232 	mpi_push_replies(sc);
233 
234 	if (mpi_portfacts(sc) != 0) {
235 		printf("%s: unable to get portfacts\n", DEVNAME(sc));
236 		goto free_replies;
237 	}
238 
239 #ifdef notyet
240 	if (mpi_eventnotify(sc) != 0) {
241 		printf("%s: unable to get portfacts\n", DEVNAME(sc));
242 		goto free_replies;
243 	}
244 #endif
245 
246 	if (mpi_portenable(sc) != 0) {
247 		printf("%s: unable to enable port\n", DEVNAME(sc));
248 		goto free_replies;
249 	}
250 
251 	if (mpi_fwupload(sc) != 0) {
252 		printf("%s: unable to upload firmware\n", DEVNAME(sc));
253 		goto free_replies;
254 	}
255 
256 	if (sc->sc_porttype == MPI_PORTFACTS_PORTTYPE_SCSI) {
257 		if (mpi_cfg_spi_port(sc) != 0)
258 			goto free_replies;
259 		mpi_squash_ppr(sc);
260 	}
261 
262 	rw_init(&sc->sc_lock, "mpi_lock");
263 
264 	/* we should be good to go now, attach scsibus */
265 	sc->sc_link.device = &mpi_dev;
266 	sc->sc_link.adapter = &mpi_switch;
267 	sc->sc_link.adapter_softc = sc;
268 	sc->sc_link.adapter_target = sc->sc_target;
269 	sc->sc_link.adapter_buswidth = sc->sc_buswidth;
270 	sc->sc_link.openings = sc->sc_maxcmds / sc->sc_buswidth;
271 
272 	bzero(&saa, sizeof(saa));
273 	saa.saa_sc_link = &sc->sc_link;
274 
275 	/* config_found() returns the scsibus attached to us */
276 	sc->sc_scsibus = (struct scsibus_softc *) config_found(&sc->sc_dev,
277 	    &saa, scsiprint);
278 
279 	/* get raid pages */
280 	mpi_get_raid(sc);
281 
282 	/* do domain validation */
283 	if (sc->sc_porttype == MPI_PORTFACTS_PORTTYPE_SCSI)
284 		mpi_run_ppr(sc);
285 
286 	/* enable interrupts */
287 	mpi_write(sc, MPI_INTR_MASK, MPI_INTR_MASK_DOORBELL);
288 
289 #ifdef notyet
290 #if NBIO > 0
291 	if (bio_register(&sc->sc_dev, mpi_ioctl) != 0)
292 		panic("%s: controller registration failed", DEVNAME(sc));
293 	else {
294 		if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_IOC, 2, 0,
295 		    &sc->sc_cfg_hdr) != 0) {
296 			printf("%s: can't get IOC page 2 hdr, bio disabled\n",
297 			    DEVNAME(sc));
298 			goto done;
299 		}
300 		sc->sc_vol_page = malloc(sc->sc_cfg_hdr.page_length * 4, M_TEMP,
301 		    M_WAITOK | M_CANFAIL);
302 		if (sc->sc_vol_page == NULL) {
303 			printf("%s: can't get memory for IOC page 2, "
304 			    "bio disabled\n", DEVNAME(sc));
305 			goto done;
306 		}
307 		sc->sc_vol_list = (struct mpi_cfg_raid_vol *)
308 		    (sc->sc_vol_page + 1);
309 
310 		sc->sc_ioctl = mpi_ioctl;
311 	}
312 #ifndef SMALL_KERNEL
313 	if (mpi_create_sensors(sc) != 0)
314 		printf("%s: unable to create sensors\n", DEVNAME(sc));
315 #endif /* SMALL_KERNEL */
316 done:
317 #endif /* NBIO > 0 */
318 #endif /* notyet */
319 
320 	return (0);
321 
322 free_replies:
323 	bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies),
324 	    0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
325 	mpi_dmamem_free(sc, sc->sc_replies);
326 free_ccbs:
327 	while ((ccb = mpi_get_ccb(sc)) != NULL)
328 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
329 	mpi_dmamem_free(sc, sc->sc_requests);
330 	free(sc->sc_ccbs, M_DEVBUF);
331 
332 	return(1);
333 }
334 
335 int
336 mpi_cfg_spi_port(struct mpi_softc *sc)
337 {
338 	struct mpi_cfg_hdr		hdr;
339 	struct mpi_cfg_spi_port_pg1	port;
340 
341 	if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_PORT, 1, 0x0,
342 	    &hdr) != 0)
343 		return (1);
344 
345 	if (mpi_cfg_page(sc, 0x0, &hdr, 1, &port, sizeof(port)) != 0)
346 		return (1);
347 
348 	DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_spi_port_pg1\n", DEVNAME(sc));
349 	DNPRINTF(MPI_D_MISC, "%s:  port_scsi_id: %d port_resp_ids 0x%04x\n",
350 	    DEVNAME(sc), port.port_scsi_id, letoh16(port.port_resp_ids));
351 	DNPRINTF(MPI_D_MISC, "%s:  on_bus_timer_value: 0x%08x\n", DEVNAME(sc),
352 	    letoh32(port.port_scsi_id));
353 	DNPRINTF(MPI_D_MISC, "%s:  target_config: 0x%02x id_config: 0x%04x\n",
354 	    DEVNAME(sc), port.target_config, letoh16(port.id_config));
355 
356 	if (port.port_scsi_id == sc->sc_target &&
357 	    port.port_resp_ids == htole16(1 << sc->sc_target) &&
358 	    port.on_bus_timer_value != htole32(0x0))
359 		return (0);
360 
361 	DNPRINTF(MPI_D_MISC, "%s: setting port scsi id to %d\n", DEVNAME(sc),
362 	    sc->sc_target);
363 	port.port_scsi_id = sc->sc_target;
364 	port.port_resp_ids = htole16(1 << sc->sc_target);
365 	port.on_bus_timer_value = htole32(0x07000000); /* XXX magic */
366 
367 	if (mpi_cfg_page(sc, 0x0, &hdr, 0, &port, sizeof(port)) != 0) {
368 		printf("%s: unable to configure port scsi id\n", DEVNAME(sc));
369 		return (1);
370 	}
371 
372 	return (0);
373 }
374 
375 void
376 mpi_squash_ppr(struct mpi_softc *sc)
377 {
378 	struct mpi_cfg_hdr		hdr;
379 	struct mpi_cfg_spi_dev_pg1	page;
380 	int				i;
381 
382 	DNPRINTF(MPI_D_PPR, "%s: mpi_squash_ppr\n", DEVNAME(sc));
383 
384 	for (i = 0; i < sc->sc_buswidth; i++) {
385 		if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV,
386 		    1, i, &hdr) != 0)
387 			return;
388 
389 		if (mpi_cfg_page(sc, i, &hdr, 1, &page, sizeof(page)) != 0)
390 			return;
391 
392 		DNPRINTF(MPI_D_PPR, "%s:  target: %d req_params1: 0x%02x "
393 		    "req_offset: 0x%02x req_period: 0x%02x "
394 		    "req_params2: 0x%02x conf: 0x%08x\n", DEVNAME(sc), i,
395 		    page.req_params1, page.req_offset, page.req_period,
396 		    page.req_params2, letoh32(page.configuration));
397 
398 		page.req_params1 = 0x0;
399 		page.req_offset = 0x0;
400 		page.req_period = 0x0;
401 		page.req_params2 = 0x0;
402 		page.configuration = htole32(0x0);
403 
404 		if (mpi_cfg_page(sc, i, &hdr, 0, &page, sizeof(page)) != 0)
405 			return;
406 	}
407 }
408 
409 void
410 mpi_run_ppr(struct mpi_softc *sc)
411 {
412 	struct mpi_cfg_hdr		hdr;
413 	struct mpi_cfg_spi_port_pg0	port_pg;
414 	struct mpi_cfg_ioc_pg3		*physdisk_pg;
415 	struct mpi_cfg_raid_physdisk	*physdisk_list, *physdisk;
416 	size_t				pagelen;
417 	struct scsi_link		*link;
418 	int				i, tries;
419 
420 	if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_PORT, 0, 0x0,
421 	    &hdr) != 0) {
422 		DNPRINTF(MPI_D_PPR, "%s: mpi_run_ppr unable to fetch header\n",
423 		    DEVNAME(sc));
424 		return;
425 	}
426 
427 	if (mpi_cfg_page(sc, 0x0, &hdr, 1, &port_pg, sizeof(port_pg)) != 0) {
428 		DNPRINTF(MPI_D_PPR, "%s: mpi_run_ppr unable to fetch page\n",
429 		    DEVNAME(sc));
430 		return;
431 	}
432 
433 	for (i = 0; i < sc->sc_buswidth; i++) {
434 		link = sc->sc_scsibus->sc_link[i][0];
435 		if (link == NULL)
436 			continue;
437 
438 		/* do not ppr volumes */
439 		if (link->flags & SDEV_VIRTUAL)
440 			continue;
441 
442 		tries = 0;
443 		while (mpi_ppr(sc, link, NULL, port_pg.min_period,
444 		    port_pg.max_offset, tries) == EAGAIN)
445 			tries++;
446 	}
447 
448 	if ((sc->sc_flags & MPI_F_RAID) == 0)
449 		return;
450 
451 	if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_IOC, 3, 0x0,
452 	    &hdr) != 0) {
453 		DNPRINTF(MPI_D_RAID|MPI_D_PPR, "%s: mpi_run_ppr unable to "
454 		    "fetch ioc pg 3 header\n", DEVNAME(sc));
455 		return;
456 	}
457 
458 	pagelen = hdr.page_length * 4; /* dwords to bytes */
459 	physdisk_pg = malloc(pagelen, M_TEMP, M_WAITOK|M_CANFAIL);
460 	if (physdisk_pg == NULL) {
461 		DNPRINTF(MPI_D_RAID|MPI_D_PPR, "%s: mpi_run_ppr unable to "
462 		    "allocate ioc pg 3\n", DEVNAME(sc));
463 		return;
464 	}
465 	physdisk_list = (struct mpi_cfg_raid_physdisk *)(physdisk_pg + 1);
466 
467 	if (mpi_cfg_page(sc, 0, &hdr, 1, physdisk_pg, pagelen) != 0) {
468 		DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s: mpi_run_ppr unable to "
469 		    "fetch ioc page 3\n", DEVNAME(sc));
470 		goto out;
471 	}
472 
473 	DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s:  no_phys_disks: %d\n", DEVNAME(sc),
474 	    physdisk_pg->no_phys_disks);
475 
476 	for (i = 0; i < physdisk_pg->no_phys_disks; i++) {
477 		physdisk = &physdisk_list[i];
478 
479 		DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s:  id: %d bus: %d ioc: %d "
480 		    "num: %d\n", DEVNAME(sc), physdisk->phys_disk_id,
481 		    physdisk->phys_disk_bus, physdisk->phys_disk_ioc,
482 		    physdisk->phys_disk_num);
483 
484 		if (physdisk->phys_disk_ioc != sc->sc_ioc_number)
485 			continue;
486 
487 		tries = 0;
488 		while (mpi_ppr(sc, NULL, physdisk, port_pg.min_period,
489 		    port_pg.max_offset, tries) == EAGAIN)
490 			tries++;
491 	}
492 
493 out:
494 	free(physdisk_pg, M_TEMP);
495 }
496 
497 int
498 mpi_ppr(struct mpi_softc *sc, struct scsi_link *link,
499     struct mpi_cfg_raid_physdisk *physdisk, int period, int offset, int try)
500 {
501 	struct mpi_cfg_hdr		hdr0, hdr1;
502 	struct mpi_cfg_spi_dev_pg0	pg0;
503 	struct mpi_cfg_spi_dev_pg1	pg1;
504 	u_int32_t			address;
505 	int				id;
506 	int				raid = 0;
507 
508 	DNPRINTF(MPI_D_PPR, "%s: mpi_ppr period: %d offset: %d try: %d "
509 	    "link quirks: 0x%x\n", DEVNAME(sc), period, offset, try,
510 	    link->quirks);
511 
512 	if (try >= 3)
513 		return (EIO);
514 
515 	if (physdisk == NULL) {
516 		if ((link->inqdata.device & SID_TYPE) == T_PROCESSOR)
517 			return (EIO);
518 
519 		address = link->target;
520 		id = link->target;
521 	} else {
522 		raid = 1;
523 		address = (physdisk->phys_disk_bus << 8) |
524 		    (physdisk->phys_disk_id);
525 		id = physdisk->phys_disk_num;
526 	}
527 
528 	if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV, 0,
529 	    address, &hdr0) != 0) {
530 		DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch header 0\n",
531 		    DEVNAME(sc));
532 		return (EIO);
533 	}
534 
535 	if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV, 1,
536 	    address, &hdr1) != 0) {
537 		DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch header 1\n",
538 		    DEVNAME(sc));
539 		return (EIO);
540 	}
541 
542 #ifdef MPI_DEBUG
543 	if (mpi_cfg_page(sc, address, &hdr0, 1, &pg0, sizeof(pg0)) != 0) {
544 		DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch page 0\n",
545 		    DEVNAME(sc));
546 		return (EIO);
547 	}
548 
549 	DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 0 neg_params1: 0x%02x "
550 	    "neg_offset: %d neg_period: 0x%02x neg_params2: 0x%02x "
551 	    "info: 0x%08x\n", DEVNAME(sc), pg0.neg_params1, pg0.neg_offset,
552 	    pg0.neg_period, pg0.neg_params2, letoh32(pg0.information));
553 #endif
554 
555 	if (mpi_cfg_page(sc, address, &hdr1, 1, &pg1, sizeof(pg1)) != 0) {
556 		DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch page 1\n",
557 		    DEVNAME(sc));
558 		return (EIO);
559 	}
560 
561 	DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x "
562 	    "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x "
563 	    "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset,
564 	    pg1.req_period, pg1.req_params2, letoh32(pg1.configuration));
565 
566 	pg1.req_params1 = 0;
567 	pg1.req_offset = offset;
568 	pg1.req_period = period;
569 	pg1.req_params2 &= ~MPI_CFG_SPI_DEV_1_REQPARAMS_WIDTH;
570 
571 	if (raid || !(link->quirks & SDEV_NOSYNC)) {
572 		pg1.req_params2 |= MPI_CFG_SPI_DEV_1_REQPARAMS_WIDTH_WIDE;
573 
574 		switch (try) {
575 		case 0: /* U320 */
576 			break;
577 		case 1: /* U160 */
578 			pg1.req_period = 0x09;
579 			break;
580 		case 2: /* U80 */
581 			pg1.req_period = 0x0a;
582 			break;
583 		}
584 
585 		if (pg1.req_period < 0x09) {
586 			/* Ultra320: enable QAS & PACKETIZED */
587 			pg1.req_params1 |= MPI_CFG_SPI_DEV_1_REQPARAMS_QAS |
588 			    MPI_CFG_SPI_DEV_1_REQPARAMS_PACKETIZED;
589 		}
590 		if (pg1.req_period < 0xa) {
591 			/* >= Ultra160: enable dual xfers */
592 			pg1.req_params1 |=
593 			    MPI_CFG_SPI_DEV_1_REQPARAMS_DUALXFERS;
594 		}
595 	}
596 
597 	DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x "
598 	    "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x "
599 	    "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset,
600 	    pg1.req_period, pg1.req_params2, letoh32(pg1.configuration));
601 
602 	if (mpi_cfg_page(sc, address, &hdr1, 0, &pg1, sizeof(pg1)) != 0) {
603 		DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to write page 1\n",
604 		    DEVNAME(sc));
605 		return (EIO);
606 	}
607 
608 	if (mpi_cfg_page(sc, address, &hdr1, 1, &pg1, sizeof(pg1)) != 0) {
609 		DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to read page 1\n",
610 		    DEVNAME(sc));
611 		return (EIO);
612 	}
613 
614 	DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x "
615 	    "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x "
616 	    "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset,
617 	    pg1.req_period, pg1.req_params2, letoh32(pg1.configuration));
618 
619 	if (mpi_inq(sc, id, raid) != 0) {
620 		DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to do inquiry against "
621 		    "target %d\n", DEVNAME(sc), link->target);
622 		return (EIO);
623 	}
624 
625 	if (mpi_cfg_page(sc, address, &hdr0, 1, &pg0, sizeof(pg0)) != 0) {
626 		DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to read page 0 after "
627 		    "inquiry\n", DEVNAME(sc));
628 		return (EIO);
629 	}
630 
631 	DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 0 neg_params1: 0x%02x "
632 	    "neg_offset: %d neg_period: 0x%02x neg_params2: 0x%02x "
633 	    "info: 0x%08x\n", DEVNAME(sc), pg0.neg_params1, pg0.neg_offset,
634 	    pg0.neg_period, pg0.neg_params2, letoh32(pg0.information));
635 
636 	if (!(letoh32(pg0.information) & 0x07) && (try == 0)) {
637 		DNPRINTF(MPI_D_PPR, "%s: mpi_ppr U320 ppr rejected\n",
638 		    DEVNAME(sc));
639 		return (EAGAIN);
640 	}
641 
642 	if ((((letoh32(pg0.information) >> 8) & 0xff) > 0x09) && (try == 1)) {
643 		DNPRINTF(MPI_D_PPR, "%s: mpi_ppr U160 ppr rejected\n",
644 		    DEVNAME(sc));
645 		return (EAGAIN);
646 	}
647 
648 	if (letoh32(pg0.information) & 0x0e) {
649 		DNPRINTF(MPI_D_PPR, "%s: mpi_ppr ppr rejected: %0x\n",
650 		    DEVNAME(sc), letoh32(pg0.information));
651 		return (EAGAIN);
652 	}
653 
654 	switch(pg0.neg_period) {
655 	case 0x08:
656 		period = 160;
657 		break;
658 	case 0x09:
659 		period = 80;
660 		break;
661 	case 0x0a:
662 		period = 40;
663 		break;
664 	case 0x0b:
665 		period = 20;
666 		break;
667 	case 0x0c:
668 		period = 10;
669 		break;
670 	default:
671 		period = 0;
672 		break;
673 	}
674 
675 	printf("%s: %s %d %s at %dMHz width %dbit offset %d "
676 	    "QAS %d DT %d IU %d\n", DEVNAME(sc), raid ? "phys disk" : "target",
677 	    id, period ? "Sync" : "Async", period,
678 	    (pg0.neg_params2 & MPI_CFG_SPI_DEV_0_NEGPARAMS_WIDTH_WIDE) ? 16 : 8,
679 	    pg0.neg_offset,
680 	    (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_QAS) ? 1 : 0,
681 	    (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_DUALXFERS) ? 1 : 0,
682 	    (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_PACKETIZED) ? 1 : 0);
683 
684 	return (0);
685 }
686 
687 int
688 mpi_inq(struct mpi_softc *sc, u_int16_t target, int physdisk)
689 {
690 	struct mpi_ccb			*ccb;
691 	struct scsi_inquiry		inq;
692 	struct {
693 		struct mpi_msg_scsi_io		io;
694 		struct mpi_sge			sge;
695 		struct scsi_inquiry_data	inqbuf;
696 		struct scsi_sense_data		sense;
697 	} __packed			*bundle;
698 	struct mpi_msg_scsi_io		*io;
699 	struct mpi_sge			*sge;
700 	u_int64_t			addr;
701 
702 	DNPRINTF(MPI_D_PPR, "%s: mpi_inq\n", DEVNAME(sc));
703 
704 	bzero(&inq, sizeof(inq));
705 	inq.opcode = INQUIRY;
706 	_lto2b(sizeof(struct scsi_inquiry_data), inq.length);
707 
708 	ccb = mpi_get_ccb(sc);
709 	if (ccb == NULL)
710 		return (1);
711 
712 	ccb->ccb_done = mpi_empty_done;
713 
714 	bundle = ccb->ccb_cmd;
715 	io = &bundle->io;
716 	sge = &bundle->sge;
717 
718 	io->function = physdisk ? MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH :
719 	    MPI_FUNCTION_SCSI_IO_REQUEST;
720 	/*
721 	 * bus is always 0
722 	 * io->bus = htole16(sc->sc_bus);
723 	 */
724 	io->target_id = target;
725 
726 	io->cdb_length = sizeof(inq);
727 	io->sense_buf_len = sizeof(struct scsi_sense_data);
728 	io->msg_flags = MPI_SCSIIO_SENSE_BUF_ADDR_WIDTH_64;
729 
730 	io->msg_context = htole32(ccb->ccb_id);
731 
732 	/*
733 	 * always lun 0
734 	 * io->lun[0] = htobe16(link->lun);
735 	 */
736 
737 	io->direction = MPI_SCSIIO_DIR_READ;
738 	io->tagging = MPI_SCSIIO_ATTR_NO_DISCONNECT;
739 
740 	bcopy(&inq, io->cdb, sizeof(inq));
741 
742 	io->data_length = htole32(sizeof(struct scsi_inquiry_data));
743 
744 	io->sense_buf_low_addr = htole32(ccb->ccb_cmd_dva +
745 	    ((u_int8_t *)&bundle->sense - (u_int8_t *)bundle));
746 
747 	sge->sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_SIZE_64 |
748 	    MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL |
749 	    (u_int32_t)sizeof(inq));
750 
751 	addr = ccb->ccb_cmd_dva +
752 	    ((u_int8_t *)&bundle->inqbuf - (u_int8_t *)bundle);
753 	sge->sg_hi_addr = htole32((u_int32_t)(addr >> 32));
754 	sge->sg_lo_addr = htole32((u_int32_t)addr);
755 
756 	if (mpi_poll(sc, ccb, 5000) != 0)
757 		return (1);
758 
759 	if (ccb->ccb_rcb != NULL)
760 		mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
761 
762 	mpi_put_ccb(sc, ccb);
763 
764 	return (0);
765 }
766 
767 void
768 mpi_detach(struct mpi_softc *sc)
769 {
770 
771 }
772 
773 int
774 mpi_intr(void *arg)
775 {
776 	struct mpi_softc		*sc = arg;
777 	u_int32_t			reg;
778 	int				rv = 0;
779 
780 	while ((reg = mpi_pop_reply(sc)) != 0xffffffff) {
781 		mpi_reply(sc, reg);
782 		rv = 1;
783 	}
784 
785 	return (rv);
786 }
787 
788 int
789 mpi_reply(struct mpi_softc *sc, u_int32_t reg)
790 {
791 	struct mpi_ccb			*ccb;
792 	struct mpi_rcb			*rcb = NULL;
793 	struct mpi_msg_reply		*reply = NULL;
794 	u_int32_t			reply_dva;
795 	int				id;
796 	int				i;
797 
798 	DNPRINTF(MPI_D_INTR, "%s: mpi_reply reg: 0x%08x\n", DEVNAME(sc), reg);
799 
800 	if (reg & MPI_REPLY_QUEUE_ADDRESS) {
801 		bus_dmamap_sync(sc->sc_dmat,
802 		    MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE,
803 		    BUS_DMASYNC_POSTREAD);
804 
805 		reply_dva = (reg & MPI_REPLY_QUEUE_ADDRESS_MASK) << 1;
806 
807 		i = (reply_dva - (u_int32_t)MPI_DMA_DVA(sc->sc_replies)) /
808 		    MPI_REPLY_SIZE;
809 		rcb = &sc->sc_rcbs[i];
810 		reply = rcb->rcb_reply;
811 
812 		id = letoh32(reply->msg_context);
813 
814 		bus_dmamap_sync(sc->sc_dmat,
815 		    MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE,
816 		    BUS_DMASYNC_PREREAD);
817 	} else {
818 		switch (reg & MPI_REPLY_QUEUE_TYPE_MASK) {
819 		case MPI_REPLY_QUEUE_TYPE_INIT:
820 			id = reg & MPI_REPLY_QUEUE_CONTEXT;
821 			break;
822 
823 		default:
824 			panic("%s: unsupported context reply\n",
825 			    DEVNAME(sc));
826 		}
827 	}
828 
829 	DNPRINTF(MPI_D_INTR, "%s: mpi_reply id: %d reply: %p\n",
830 	    DEVNAME(sc), id, reply);
831 
832 	ccb = &sc->sc_ccbs[id];
833 
834 	bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests),
835 	    ccb->ccb_offset, MPI_REQUEST_SIZE,
836 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
837 	ccb->ccb_state = MPI_CCB_READY;
838 	ccb->ccb_rcb = rcb;
839 
840 	ccb->ccb_done(ccb);
841 
842 	return (id);
843 }
844 
845 struct mpi_dmamem *
846 mpi_dmamem_alloc(struct mpi_softc *sc, size_t size)
847 {
848 	struct mpi_dmamem		*mdm;
849 	int				nsegs;
850 
851 	mdm = malloc(sizeof(struct mpi_dmamem), M_DEVBUF, M_NOWAIT | M_ZERO);
852 	if (mdm == NULL)
853 		return (NULL);
854 
855 	mdm->mdm_size = size;
856 
857 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
858 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0)
859 		goto mdmfree;
860 
861 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mdm->mdm_seg,
862 	    1, &nsegs, BUS_DMA_NOWAIT) != 0)
863 		goto destroy;
864 
865 	if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size,
866 	    &mdm->mdm_kva, BUS_DMA_NOWAIT) != 0)
867 		goto free;
868 
869 	if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size,
870 	    NULL, BUS_DMA_NOWAIT) != 0)
871 		goto unmap;
872 
873 	bzero(mdm->mdm_kva, size);
874 
875 	DNPRINTF(MPI_D_MEM, "%s: mpi_dmamem_alloc size: %d mdm: %#x "
876 	    "map: %#x nsegs: %d segs: %#x kva: %x\n",
877 	    DEVNAME(sc), size, mdm->mdm_map, nsegs, mdm->mdm_seg, mdm->mdm_kva);
878 
879 	return (mdm);
880 
881 unmap:
882 	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size);
883 free:
884 	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
885 destroy:
886 	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
887 mdmfree:
888 	free(mdm, M_DEVBUF);
889 
890 	return (NULL);
891 }
892 
893 void
894 mpi_dmamem_free(struct mpi_softc *sc, struct mpi_dmamem *mdm)
895 {
896 	DNPRINTF(MPI_D_MEM, "%s: mpi_dmamem_free %#x\n", DEVNAME(sc), mdm);
897 
898 	bus_dmamap_unload(sc->sc_dmat, mdm->mdm_map);
899 	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size);
900 	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
901 	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
902 	free(mdm, M_DEVBUF);
903 }
904 
905 int
906 mpi_alloc_ccbs(struct mpi_softc *sc)
907 {
908 	struct mpi_ccb			*ccb;
909 	u_int8_t			*cmd;
910 	int				i;
911 
912 	TAILQ_INIT(&sc->sc_ccb_free);
913 
914 	sc->sc_ccbs = malloc(sizeof(struct mpi_ccb) * sc->sc_maxcmds,
915 	    M_DEVBUF, M_WAITOK | M_CANFAIL | M_ZERO);
916 	if (sc->sc_ccbs == NULL) {
917 		printf("%s: unable to allocate ccbs\n", DEVNAME(sc));
918 		return (1);
919 	}
920 
921 	sc->sc_requests = mpi_dmamem_alloc(sc,
922 	    MPI_REQUEST_SIZE * sc->sc_maxcmds);
923 	if (sc->sc_requests == NULL) {
924 		printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
925 		goto free_ccbs;
926 	}
927 	cmd = MPI_DMA_KVA(sc->sc_requests);
928 	bzero(cmd, MPI_REQUEST_SIZE * sc->sc_maxcmds);
929 
930 	for (i = 0; i < sc->sc_maxcmds; i++) {
931 		ccb = &sc->sc_ccbs[i];
932 
933 		if (bus_dmamap_create(sc->sc_dmat, MAXPHYS,
934 		    sc->sc_max_sgl_len, MAXPHYS, 0,
935 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
936 		    &ccb->ccb_dmamap) != 0) {
937 			printf("%s: unable to create dma map\n", DEVNAME(sc));
938 			goto free_maps;
939 		}
940 
941 		ccb->ccb_sc = sc;
942 		ccb->ccb_id = i;
943 		ccb->ccb_offset = MPI_REQUEST_SIZE * i;
944 
945 		ccb->ccb_cmd = &cmd[ccb->ccb_offset];
946 		ccb->ccb_cmd_dva = (u_int32_t)MPI_DMA_DVA(sc->sc_requests) +
947 		    ccb->ccb_offset;
948 
949 		DNPRINTF(MPI_D_CCB, "%s: mpi_alloc_ccbs(%d) ccb: %#x map: %#x "
950 		    "sc: %#x id: %#x offs: %#x cmd: %#x dva: %#x\n",
951 		    DEVNAME(sc), i, ccb, ccb->ccb_dmamap, ccb->ccb_sc,
952 		    ccb->ccb_id, ccb->ccb_offset, ccb->ccb_cmd,
953 		    ccb->ccb_cmd_dva);
954 
955 		mpi_put_ccb(sc, ccb);
956 	}
957 
958 	return (0);
959 
960 free_maps:
961 	while ((ccb = mpi_get_ccb(sc)) != NULL)
962 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
963 
964 	mpi_dmamem_free(sc, sc->sc_requests);
965 free_ccbs:
966 	free(sc->sc_ccbs, M_DEVBUF);
967 
968 	return (1);
969 }
970 
971 struct mpi_ccb *
972 mpi_get_ccb(struct mpi_softc *sc)
973 {
974 	struct mpi_ccb			*ccb;
975 
976 	ccb = TAILQ_FIRST(&sc->sc_ccb_free);
977 	if (ccb == NULL) {
978 		DNPRINTF(MPI_D_CCB, "%s: mpi_get_ccb == NULL\n", DEVNAME(sc));
979 		return (NULL);
980 	}
981 
982 	TAILQ_REMOVE(&sc->sc_ccb_free, ccb, ccb_link);
983 
984 	ccb->ccb_state = MPI_CCB_READY;
985 
986 	DNPRINTF(MPI_D_CCB, "%s: mpi_get_ccb %#x\n", DEVNAME(sc), ccb);
987 
988 	return (ccb);
989 }
990 
991 void
992 mpi_put_ccb(struct mpi_softc *sc, struct mpi_ccb *ccb)
993 {
994 	DNPRINTF(MPI_D_CCB, "%s: mpi_put_ccb %#x\n", DEVNAME(sc), ccb);
995 
996 	ccb->ccb_state = MPI_CCB_FREE;
997 	ccb->ccb_xs = NULL;
998 	ccb->ccb_done = NULL;
999 	bzero(ccb->ccb_cmd, MPI_REQUEST_SIZE);
1000 	TAILQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_link);
1001 }
1002 
1003 int
1004 mpi_alloc_replies(struct mpi_softc *sc)
1005 {
1006 	DNPRINTF(MPI_D_MISC, "%s: mpi_alloc_replies\n", DEVNAME(sc));
1007 
1008 	sc->sc_rcbs = malloc(MPI_REPLY_COUNT * sizeof(struct mpi_rcb),
1009 	    M_DEVBUF, M_WAITOK|M_CANFAIL);
1010 	if (sc->sc_rcbs == NULL)
1011 		return (1);
1012 
1013 	sc->sc_replies = mpi_dmamem_alloc(sc, PAGE_SIZE);
1014 	if (sc->sc_replies == NULL) {
1015 		free(sc->sc_rcbs, M_DEVBUF);
1016 		return (1);
1017 	}
1018 
1019 	return (0);
1020 }
1021 
1022 void
1023 mpi_push_replies(struct mpi_softc *sc)
1024 {
1025 	struct mpi_rcb			*rcb;
1026 	char				*kva = MPI_DMA_KVA(sc->sc_replies);
1027 	int				i;
1028 
1029 	bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies),
1030 	    0, PAGE_SIZE, BUS_DMASYNC_PREREAD);
1031 
1032 	for (i = 0; i < MPI_REPLY_COUNT; i++) {
1033 		rcb = &sc->sc_rcbs[i];
1034 
1035 		rcb->rcb_reply = kva + MPI_REPLY_SIZE * i;
1036 		rcb->rcb_reply_dva = (u_int32_t)MPI_DMA_DVA(sc->sc_replies) +
1037 		    MPI_REPLY_SIZE * i;
1038 		mpi_push_reply(sc, rcb->rcb_reply_dva);
1039 	}
1040 }
1041 
1042 void
1043 mpi_start(struct mpi_softc *sc, struct mpi_ccb *ccb)
1044 {
1045 	DNPRINTF(MPI_D_RW, "%s: mpi_start %#x\n", DEVNAME(sc),
1046 	    ccb->ccb_cmd_dva);
1047 
1048 	bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests),
1049 	    ccb->ccb_offset, MPI_REQUEST_SIZE,
1050 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1051 
1052 	ccb->ccb_state = MPI_CCB_QUEUED;
1053 	mpi_write(sc, MPI_REQ_QUEUE, ccb->ccb_cmd_dva);
1054 }
1055 
1056 int
1057 mpi_complete(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout)
1058 {
1059 	u_int32_t			reg;
1060 	int				id = -1;
1061 
1062 	DNPRINTF(MPI_D_INTR, "%s: mpi_complete timeout %d\n", DEVNAME(sc),
1063 	    timeout);
1064 
1065 	do {
1066 		reg = mpi_pop_reply(sc);
1067 		if (reg == 0xffffffff) {
1068 			if (timeout-- == 0)
1069 				return (1);
1070 
1071 			delay(1000);
1072 			continue;
1073 		}
1074 
1075 		id = mpi_reply(sc, reg);
1076 
1077 	} while (ccb->ccb_id != id);
1078 
1079 	return (0);
1080 }
1081 
1082 int
1083 mpi_poll(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout)
1084 {
1085 	int				error;
1086 	int				s;
1087 
1088 	DNPRINTF(MPI_D_CMD, "%s: mpi_poll\n", DEVNAME(sc));
1089 
1090 	s = splbio();
1091 	mpi_start(sc, ccb);
1092 	error = mpi_complete(sc, ccb, timeout);
1093 	splx(s);
1094 
1095 	return (error);
1096 }
1097 
1098 int
1099 mpi_scsi_cmd(struct scsi_xfer *xs)
1100 {
1101 	struct scsi_link		*link = xs->sc_link;
1102 	struct mpi_softc		*sc = link->adapter_softc;
1103 	struct mpi_ccb			*ccb;
1104 	struct mpi_ccb_bundle		*mcb;
1105 	struct mpi_msg_scsi_io		*io;
1106 	int				s;
1107 
1108 	DNPRINTF(MPI_D_CMD, "%s: mpi_scsi_cmd\n", DEVNAME(sc));
1109 
1110 	if (xs->cmdlen > MPI_CDB_LEN) {
1111 		DNPRINTF(MPI_D_CMD, "%s: CBD too big %d\n",
1112 		    DEVNAME(sc), xs->cmdlen);
1113 		bzero(&xs->sense, sizeof(xs->sense));
1114 		xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
1115 		xs->sense.flags = SKEY_ILLEGAL_REQUEST;
1116 		xs->sense.add_sense_code = 0x20;
1117 		xs->error = XS_SENSE;
1118 		s = splbio();
1119 		scsi_done(xs);
1120 		splx(s);
1121 		return (COMPLETE);
1122 	}
1123 
1124 	s = splbio();
1125 	ccb = mpi_get_ccb(sc);
1126 	splx(s);
1127 	if (ccb == NULL) {
1128 		xs->error = XS_DRIVER_STUFFUP;
1129 		s = splbio();
1130 		scsi_done(xs);
1131 		splx(s);
1132 		return (COMPLETE);
1133 	}
1134 	DNPRINTF(MPI_D_CMD, "%s: ccb_id: %d xs->flags: 0x%x\n",
1135 	    DEVNAME(sc), ccb->ccb_id, xs->flags);
1136 
1137 	ccb->ccb_xs = xs;
1138 	ccb->ccb_done = mpi_scsi_cmd_done;
1139 
1140 	mcb = ccb->ccb_cmd;
1141 	io = &mcb->mcb_io;
1142 
1143 	io->function = MPI_FUNCTION_SCSI_IO_REQUEST;
1144 	/*
1145 	 * bus is always 0
1146 	 * io->bus = htole16(sc->sc_bus);
1147 	 */
1148 	io->target_id = link->target;
1149 
1150 	io->cdb_length = xs->cmdlen;
1151 	io->sense_buf_len = sizeof(xs->sense);
1152 	io->msg_flags = MPI_SCSIIO_SENSE_BUF_ADDR_WIDTH_64;
1153 
1154 	io->msg_context = htole32(ccb->ccb_id);
1155 
1156 	io->lun[0] = htobe16(link->lun);
1157 
1158 	switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1159 	case SCSI_DATA_IN:
1160 		io->direction = MPI_SCSIIO_DIR_READ;
1161 		break;
1162 	case SCSI_DATA_OUT:
1163 		io->direction = MPI_SCSIIO_DIR_WRITE;
1164 		break;
1165 	default:
1166 		io->direction = MPI_SCSIIO_DIR_NONE;
1167 		break;
1168 	}
1169 
1170 	if (sc->sc_porttype != MPI_PORTFACTS_PORTTYPE_SCSI &&
1171 	    (link->quirks & SDEV_NOTAGS))
1172 		io->tagging = MPI_SCSIIO_ATTR_UNTAGGED;
1173 	else
1174 		io->tagging = MPI_SCSIIO_ATTR_SIMPLE_Q;
1175 
1176 	bcopy(xs->cmd, io->cdb, xs->cmdlen);
1177 
1178 	io->data_length = htole32(xs->datalen);
1179 
1180 	io->sense_buf_low_addr = htole32(ccb->ccb_cmd_dva +
1181 	    ((u_int8_t *)&mcb->mcb_sense - (u_int8_t *)mcb));
1182 
1183 	if (mpi_load_xs(ccb) != 0) {
1184 		xs->error = XS_DRIVER_STUFFUP;
1185 		s = splbio();
1186 		mpi_put_ccb(sc, ccb);
1187 		scsi_done(xs);
1188 		splx(s);
1189 		return (COMPLETE);
1190 	}
1191 
1192 	timeout_set(&xs->stimeout, mpi_timeout_xs, ccb);
1193 
1194 	if (xs->flags & SCSI_POLL) {
1195 		if (mpi_poll(sc, ccb, xs->timeout) != 0)
1196 			xs->error = XS_DRIVER_STUFFUP;
1197 		return (COMPLETE);
1198 	}
1199 
1200 	s = splbio();
1201 	mpi_start(sc, ccb);
1202 	splx(s);
1203 	return (SUCCESSFULLY_QUEUED);
1204 }
1205 
1206 void
1207 mpi_scsi_cmd_done(struct mpi_ccb *ccb)
1208 {
1209 	struct mpi_softc		*sc = ccb->ccb_sc;
1210 	struct scsi_xfer		*xs = ccb->ccb_xs;
1211 	struct mpi_ccb_bundle		*mcb = ccb->ccb_cmd;
1212 	bus_dmamap_t			dmap = ccb->ccb_dmamap;
1213 	struct mpi_msg_scsi_io_error	*sie;
1214 
1215 	if (xs->datalen != 0) {
1216 		bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
1217 		    (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
1218 		    BUS_DMASYNC_POSTWRITE);
1219 
1220 		bus_dmamap_unload(sc->sc_dmat, dmap);
1221 	}
1222 
1223 	/* timeout_del */
1224 	xs->error = XS_NOERROR;
1225 	xs->resid = 0;
1226 	xs->flags |= ITSDONE;
1227 
1228 	if (ccb->ccb_rcb == NULL) {
1229 		/* no scsi error, we're ok so drop out early */
1230 		xs->status = SCSI_OK;
1231 		mpi_put_ccb(sc, ccb);
1232 		scsi_done(xs);
1233 		return;
1234 	}
1235 
1236 	sie = ccb->ccb_rcb->rcb_reply;
1237 
1238 	DNPRINTF(MPI_D_CMD, "%s: mpi_scsi_cmd_done xs cmd: 0x%02x len: %d "
1239 	    "flags 0x%x\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen,
1240 	    xs->flags);
1241 	DNPRINTF(MPI_D_CMD, "%s:  target_id: %d bus: %d msg_length: %d "
1242 	    "function: 0x%02x\n", DEVNAME(sc), sie->target_id, sie->bus,
1243 	    sie->msg_length, sie->function);
1244 	DNPRINTF(MPI_D_CMD, "%s:  cdb_length: %d sense_buf_length: %d "
1245 	    "msg_flags: 0x%02x\n", DEVNAME(sc), sie->cdb_length,
1246 	    sie->sense_buf_len, sie->msg_flags);
1247 	DNPRINTF(MPI_D_CMD, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
1248 	    letoh32(sie->msg_context));
1249 	DNPRINTF(MPI_D_CMD, "%s:  scsi_status: 0x%02x scsi_state: 0x%02x "
1250 	    "ioc_status: 0x%04x\n", DEVNAME(sc), sie->scsi_status,
1251 	    sie->scsi_state, letoh16(sie->ioc_status));
1252 	DNPRINTF(MPI_D_CMD, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1253 	    letoh32(sie->ioc_loginfo));
1254 	DNPRINTF(MPI_D_CMD, "%s:  transfer_count: %d\n", DEVNAME(sc),
1255 	    letoh32(sie->transfer_count));
1256 	DNPRINTF(MPI_D_CMD, "%s:  sense_count: %d\n", DEVNAME(sc),
1257 	    letoh32(sie->sense_count));
1258 	DNPRINTF(MPI_D_CMD, "%s:  response_info: 0x%08x\n", DEVNAME(sc),
1259 	    letoh32(sie->response_info));
1260 	DNPRINTF(MPI_D_CMD, "%s:  tag: 0x%04x\n", DEVNAME(sc),
1261 	    letoh16(sie->tag));
1262 
1263 	xs->status = sie->scsi_status;
1264 	switch (letoh16(sie->ioc_status)) {
1265 	case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
1266 		xs->resid = xs->datalen - letoh32(sie->transfer_count);
1267 		if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_NO_SCSI_STATUS) {
1268 			xs->error = XS_DRIVER_STUFFUP;
1269 			break;
1270 		}
1271 		/* FALLTHROUGH */
1272 	case MPI_IOCSTATUS_SUCCESS:
1273 	case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:
1274 		switch (xs->status) {
1275 		case SCSI_OK:
1276 			xs->resid = 0;
1277 			break;
1278 
1279 		case SCSI_CHECK:
1280 			xs->error = XS_SENSE;
1281 			break;
1282 
1283 		case SCSI_BUSY:
1284 		case SCSI_QUEUE_FULL:
1285 			xs->error = XS_BUSY;
1286 			break;
1287 
1288 		default:
1289 			xs->error = XS_DRIVER_STUFFUP;
1290 			break;
1291 		}
1292 		break;
1293 
1294 	case MPI_IOCSTATUS_BUSY:
1295 	case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
1296 		xs->error = XS_BUSY;
1297 		break;
1298 
1299 	case MPI_IOCSTATUS_SCSI_INVALID_BUS:
1300 	case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
1301 	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
1302 		xs->error = XS_SELTIMEOUT;
1303 		break;
1304 
1305 	default:
1306 		xs->error = XS_DRIVER_STUFFUP;
1307 		break;
1308 	}
1309 
1310 	if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_AUTOSENSE_VALID)
1311 		bcopy(&mcb->mcb_sense, &xs->sense, sizeof(xs->sense));
1312 
1313 	DNPRINTF(MPI_D_CMD, "%s:  xs err: 0x%02x status: %d\n", DEVNAME(sc),
1314 	    xs->error, xs->status);
1315 
1316 	mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
1317 	mpi_put_ccb(sc, ccb);
1318 	scsi_done(xs);
1319 }
1320 
1321 void
1322 mpi_timeout_xs(void *arg)
1323 {
1324 	/* XXX */
1325 }
1326 
1327 int
1328 mpi_load_xs(struct mpi_ccb *ccb)
1329 {
1330 	struct mpi_softc		*sc = ccb->ccb_sc;
1331 	struct scsi_xfer		*xs = ccb->ccb_xs;
1332 	struct mpi_ccb_bundle		*mcb = ccb->ccb_cmd;
1333 	struct mpi_msg_scsi_io		*io = &mcb->mcb_io;
1334 	struct mpi_sge			*sge, *nsge = &mcb->mcb_sgl[0];
1335 	struct mpi_sge			*ce = NULL, *nce;
1336 	u_int64_t			ce_dva;
1337 	bus_dmamap_t			dmap = ccb->ccb_dmamap;
1338 	u_int32_t			addr, flags;
1339 	int				i, error;
1340 
1341 	if (xs->datalen == 0) {
1342 		nsge->sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
1343 		    MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL);
1344 		return (0);
1345 	}
1346 
1347 	error = bus_dmamap_load(sc->sc_dmat, dmap,
1348 	    xs->data, xs->datalen, NULL,
1349 	    (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
1350 	if (error) {
1351 		printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
1352 		return (1);
1353 	}
1354 
1355 	flags = MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_SIZE_64;
1356 	if (xs->flags & SCSI_DATA_OUT)
1357 		flags |= MPI_SGE_FL_DIR_OUT;
1358 
1359 	if (dmap->dm_nsegs > sc->sc_first_sgl_len) {
1360 		ce = &mcb->mcb_sgl[sc->sc_first_sgl_len - 1];
1361 		io->chain_offset = ((u_int8_t *)ce - (u_int8_t *)io) / 4;
1362 	}
1363 
1364 	for (i = 0; i < dmap->dm_nsegs; i++) {
1365 
1366 		if (nsge == ce) {
1367 			nsge++;
1368 			sge->sg_hdr |= htole32(MPI_SGE_FL_LAST);
1369 
1370 			DNPRINTF(MPI_D_DMA, "%s:   - 0x%08x 0x%08x 0x%08x\n",
1371 			    DEVNAME(sc), sge->sg_hdr,
1372 			    sge->sg_hi_addr, sge->sg_lo_addr);
1373 
1374 			if ((dmap->dm_nsegs - i) > sc->sc_chain_len) {
1375 				nce = &nsge[sc->sc_chain_len - 1];
1376 				addr = ((u_int8_t *)nce - (u_int8_t *)nsge) / 4;
1377 				addr = addr << 16 |
1378 				    sizeof(struct mpi_sge) * sc->sc_chain_len;
1379 			} else {
1380 				nce = NULL;
1381 				addr = sizeof(struct mpi_sge) *
1382 				    (dmap->dm_nsegs - i);
1383 			}
1384 
1385 			ce->sg_hdr = htole32(MPI_SGE_FL_TYPE_CHAIN |
1386 			    MPI_SGE_FL_SIZE_64 | addr);
1387 
1388 			ce_dva = ccb->ccb_cmd_dva +
1389 			    ((u_int8_t *)nsge - (u_int8_t *)mcb);
1390 
1391 			addr = (u_int32_t)(ce_dva >> 32);
1392 			ce->sg_hi_addr = htole32(addr);
1393 			addr = (u_int32_t)ce_dva;
1394 			ce->sg_lo_addr = htole32(addr);
1395 
1396 			DNPRINTF(MPI_D_DMA, "%s:  ce: 0x%08x 0x%08x 0x%08x\n",
1397 			    DEVNAME(sc), ce->sg_hdr, ce->sg_hi_addr,
1398 			    ce->sg_lo_addr);
1399 
1400 			ce = nce;
1401 		}
1402 
1403 		DNPRINTF(MPI_D_DMA, "%s:  %d: %d 0x%016llx\n", DEVNAME(sc),
1404 		    i, dmap->dm_segs[i].ds_len,
1405 		    (u_int64_t)dmap->dm_segs[i].ds_addr);
1406 
1407 		sge = nsge;
1408 
1409 		sge->sg_hdr = htole32(flags | dmap->dm_segs[i].ds_len);
1410 		addr = (u_int32_t)((u_int64_t)dmap->dm_segs[i].ds_addr >> 32);
1411 		sge->sg_hi_addr = htole32(addr);
1412 		addr = (u_int32_t)dmap->dm_segs[i].ds_addr;
1413 		sge->sg_lo_addr = htole32(addr);
1414 
1415 		DNPRINTF(MPI_D_DMA, "%s:  %d: 0x%08x 0x%08x 0x%08x\n",
1416 		    DEVNAME(sc), i, sge->sg_hdr, sge->sg_hi_addr,
1417 		    sge->sg_lo_addr);
1418 
1419 		nsge = sge + 1;
1420 	}
1421 
1422 	/* terminate list */
1423 	sge->sg_hdr |= htole32(MPI_SGE_FL_LAST | MPI_SGE_FL_EOB |
1424 	    MPI_SGE_FL_EOL);
1425 
1426 	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
1427 	    (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1428 	    BUS_DMASYNC_PREWRITE);
1429 
1430 	return (0);
1431 }
1432 
1433 void
1434 mpi_minphys(struct buf *bp)
1435 {
1436 	/* XXX */
1437 	if (bp->b_bcount > MAXPHYS)
1438 		bp->b_bcount = MAXPHYS;
1439 	minphys(bp);
1440 }
1441 
1442 int
1443 mpi_scsi_probe(struct scsi_link *link)
1444 {
1445 	struct mpi_softc		*sc = link->adapter_softc;
1446 	struct mpi_ecfg_hdr		ehdr;
1447 	struct mpi_cfg_sas_dev_pg0	pg0;
1448 	u_int32_t			address;
1449 
1450 	if (sc->sc_porttype != MPI_PORTFACTS_PORTTYPE_SAS)
1451 		return (0);
1452 
1453 	address = MPI_CFG_SAS_DEV_ADDR_BUS | link->target;
1454 
1455 	if (mpi_ecfg_header(sc, MPI_CONFIG_REQ_EXTPAGE_TYPE_SAS_DEVICE, 0,
1456 	    address, &ehdr) != 0)
1457 		return (EIO);
1458 
1459 	if (mpi_ecfg_page(sc, address, &ehdr, 1, &pg0, sizeof(pg0)) != 0)
1460 		return (0);
1461 
1462 	DNPRINTF(MPI_D_MISC, "%s: mpi_scsi_probe sas dev pg 0 for target %d:\n",
1463 	    DEVNAME(sc), link->target);
1464 	DNPRINTF(MPI_D_MISC, "%s:  slot: 0x%04x enc_handle: 0x%04x\n",
1465 	    DEVNAME(sc), letoh16(pg0.slot), letoh16(pg0.enc_handle));
1466 	DNPRINTF(MPI_D_MISC, "%s:  sas_addr: 0x%016llx\n", DEVNAME(sc),
1467 	    letoh64(pg0.sas_addr));
1468 	DNPRINTF(MPI_D_MISC, "%s:  parent_dev_handle: 0x%04x phy_num: 0x%02x "
1469 	    "access_status: 0x%02x\n", DEVNAME(sc),
1470 	    letoh16(pg0.parent_dev_handle), pg0.phy_num, pg0.access_status);
1471 	DNPRINTF(MPI_D_MISC, "%s:  dev_handle: 0x%04x "
1472 	    "bus: 0x%02x target: 0x%02x\n", DEVNAME(sc),
1473 	    letoh16(pg0.dev_handle), pg0.bus, pg0.target);
1474 	DNPRINTF(MPI_D_MISC, "%s:  device_info: 0x%08x\n", DEVNAME(sc),
1475 	    letoh32(pg0.device_info));
1476 	DNPRINTF(MPI_D_MISC, "%s:  flags: 0x%04x physical_port: 0x%02x\n",
1477 	    DEVNAME(sc), letoh16(pg0.flags), pg0.physical_port);
1478 
1479 	if (ISSET(letoh32(pg0.device_info),
1480 	    MPI_CFG_SAS_DEV_0_DEVINFO_ATAPI_DEVICE)) {
1481 		DNPRINTF(MPI_D_MISC, "%s: target %d is an ATAPI device\n",
1482 		    DEVNAME(sc), link->target);
1483 		link->flags |= SDEV_ATAPI;
1484 		link->quirks |= SDEV_ONLYBIG;
1485 	}
1486 
1487 	return (0);
1488 }
1489 
1490 u_int32_t
1491 mpi_read(struct mpi_softc *sc, bus_size_t r)
1492 {
1493 	u_int32_t			rv;
1494 
1495 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1496 	    BUS_SPACE_BARRIER_READ);
1497 	rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
1498 
1499 	DNPRINTF(MPI_D_RW, "%s: mpi_read %#x %#x\n", DEVNAME(sc), r, rv);
1500 
1501 	return (rv);
1502 }
1503 
1504 void
1505 mpi_write(struct mpi_softc *sc, bus_size_t r, u_int32_t v)
1506 {
1507 	DNPRINTF(MPI_D_RW, "%s: mpi_write %#x %#x\n", DEVNAME(sc), r, v);
1508 
1509 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
1510 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1511 	    BUS_SPACE_BARRIER_WRITE);
1512 }
1513 
1514 int
1515 mpi_wait_eq(struct mpi_softc *sc, bus_size_t r, u_int32_t mask,
1516     u_int32_t target)
1517 {
1518 	int				i;
1519 
1520 	DNPRINTF(MPI_D_RW, "%s: mpi_wait_eq %#x %#x %#x\n", DEVNAME(sc), r,
1521 	    mask, target);
1522 
1523 	for (i = 0; i < 10000; i++) {
1524 		if ((mpi_read(sc, r) & mask) == target)
1525 			return (0);
1526 		delay(1000);
1527 	}
1528 
1529 	return (1);
1530 }
1531 
1532 int
1533 mpi_wait_ne(struct mpi_softc *sc, bus_size_t r, u_int32_t mask,
1534     u_int32_t target)
1535 {
1536 	int				i;
1537 
1538 	DNPRINTF(MPI_D_RW, "%s: mpi_wait_ne %#x %#x %#x\n", DEVNAME(sc), r,
1539 	    mask, target);
1540 
1541 	for (i = 0; i < 10000; i++) {
1542 		if ((mpi_read(sc, r) & mask) != target)
1543 			return (0);
1544 		delay(1000);
1545 	}
1546 
1547 	return (1);
1548 }
1549 
1550 int
1551 mpi_init(struct mpi_softc *sc)
1552 {
1553 	u_int32_t			db;
1554 	int				i;
1555 
1556 	/* spin until the IOC leaves the RESET state */
1557 	if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
1558 	    MPI_DOORBELL_STATE_RESET) != 0) {
1559 		DNPRINTF(MPI_D_MISC, "%s: mpi_init timeout waiting to leave "
1560 		    "reset state\n", DEVNAME(sc));
1561 		return (1);
1562 	}
1563 
1564 	/* check current ownership */
1565 	db = mpi_read_db(sc);
1566 	if ((db & MPI_DOORBELL_WHOINIT) == MPI_DOORBELL_WHOINIT_PCIPEER) {
1567 		DNPRINTF(MPI_D_MISC, "%s: mpi_init initialised by pci peer\n",
1568 		    DEVNAME(sc));
1569 		return (0);
1570 	}
1571 
1572 	for (i = 0; i < 5; i++) {
1573 		switch (db & MPI_DOORBELL_STATE) {
1574 		case MPI_DOORBELL_STATE_READY:
1575 			DNPRINTF(MPI_D_MISC, "%s: mpi_init ioc is ready\n",
1576 			    DEVNAME(sc));
1577 			return (0);
1578 
1579 		case MPI_DOORBELL_STATE_OPER:
1580 		case MPI_DOORBELL_STATE_FAULT:
1581 			DNPRINTF(MPI_D_MISC, "%s: mpi_init ioc is being "
1582 			    "reset\n" , DEVNAME(sc));
1583 			if (mpi_reset_soft(sc) != 0)
1584 				mpi_reset_hard(sc);
1585 			break;
1586 
1587 		case MPI_DOORBELL_STATE_RESET:
1588 			DNPRINTF(MPI_D_MISC, "%s: mpi_init waiting to come "
1589 			    "out of reset\n", DEVNAME(sc));
1590 			if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
1591 			    MPI_DOORBELL_STATE_RESET) != 0)
1592 				return (1);
1593 			break;
1594 		}
1595 		db = mpi_read_db(sc);
1596 	}
1597 
1598 	return (1);
1599 }
1600 
1601 int
1602 mpi_reset_soft(struct mpi_softc *sc)
1603 {
1604 	DNPRINTF(MPI_D_MISC, "%s: mpi_reset_soft\n", DEVNAME(sc));
1605 
1606 	if (mpi_read_db(sc) & MPI_DOORBELL_INUSE)
1607 		return (1);
1608 
1609 	mpi_write_db(sc,
1610 	    MPI_DOORBELL_FUNCTION(MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET));
1611 	if (mpi_wait_eq(sc, MPI_INTR_STATUS,
1612 	    MPI_INTR_STATUS_IOCDOORBELL, 0) != 0)
1613 		return (1);
1614 
1615 	if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
1616 	    MPI_DOORBELL_STATE_READY) != 0)
1617 		return (1);
1618 
1619 	return (0);
1620 }
1621 
1622 int
1623 mpi_reset_hard(struct mpi_softc *sc)
1624 {
1625 	DNPRINTF(MPI_D_MISC, "%s: mpi_reset_hard\n", DEVNAME(sc));
1626 
1627 	/* enable diagnostic register */
1628 	mpi_write(sc, MPI_WRITESEQ, 0xff);
1629 	mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_1);
1630 	mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_2);
1631 	mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_3);
1632 	mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_4);
1633 	mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_5);
1634 
1635 	/* reset ioc */
1636 	mpi_write(sc, MPI_HOSTDIAG, MPI_HOSTDIAG_RESET_ADAPTER);
1637 
1638 	delay(10000);
1639 
1640 	/* disable diagnostic register */
1641 	mpi_write(sc, MPI_WRITESEQ, 0xff);
1642 
1643 	/* restore pci bits? */
1644 
1645 	/* firmware bits? */
1646 	return (0);
1647 }
1648 
1649 int
1650 mpi_handshake_send(struct mpi_softc *sc, void *buf, size_t dwords)
1651 {
1652 	u_int32_t				*query = buf;
1653 	int					i;
1654 
1655 	/* make sure the doorbell is not in use. */
1656 	if (mpi_read_db(sc) & MPI_DOORBELL_INUSE)
1657 		return (1);
1658 
1659 	/* clear pending doorbell interrupts */
1660 	if (mpi_read_intr(sc) & MPI_INTR_STATUS_DOORBELL)
1661 		mpi_write_intr(sc, 0);
1662 
1663 	/*
1664 	 * first write the doorbell with the handshake function and the
1665 	 * dword count.
1666 	 */
1667 	mpi_write_db(sc, MPI_DOORBELL_FUNCTION(MPI_FUNCTION_HANDSHAKE) |
1668 	    MPI_DOORBELL_DWORDS(dwords));
1669 
1670 	/*
1671 	 * the doorbell used bit will be set because a doorbell function has
1672 	 * started. Wait for the interrupt and then ack it.
1673 	 */
1674 	if (mpi_wait_db_int(sc) != 0)
1675 		return (1);
1676 	mpi_write_intr(sc, 0);
1677 
1678 	/* poll for the acknowledgement. */
1679 	if (mpi_wait_db_ack(sc) != 0)
1680 		return (1);
1681 
1682 	/* write the query through the doorbell. */
1683 	for (i = 0; i < dwords; i++) {
1684 		mpi_write_db(sc, htole32(query[i]));
1685 		if (mpi_wait_db_ack(sc) != 0)
1686 			return (1);
1687 	}
1688 
1689 	return (0);
1690 }
1691 
1692 int
1693 mpi_handshake_recv_dword(struct mpi_softc *sc, u_int32_t *dword)
1694 {
1695 	u_int16_t				*words = (u_int16_t *)dword;
1696 	int					i;
1697 
1698 	for (i = 0; i < 2; i++) {
1699 		if (mpi_wait_db_int(sc) != 0)
1700 			return (1);
1701 		words[i] = letoh16(mpi_read_db(sc) & MPI_DOORBELL_DATA_MASK);
1702 		mpi_write_intr(sc, 0);
1703 	}
1704 
1705 	return (0);
1706 }
1707 
1708 int
1709 mpi_handshake_recv(struct mpi_softc *sc, void *buf, size_t dwords)
1710 {
1711 	struct mpi_msg_reply			*reply = buf;
1712 	u_int32_t				*dbuf = buf, dummy;
1713 	int					i;
1714 
1715 	/* get the first dword so we can read the length out of the header. */
1716 	if (mpi_handshake_recv_dword(sc, &dbuf[0]) != 0)
1717 		return (1);
1718 
1719 	DNPRINTF(MPI_D_CMD, "%s: mpi_handshake_recv dwords: %d reply: %d\n",
1720 	    DEVNAME(sc), dwords, reply->msg_length);
1721 
1722 	/*
1723 	 * the total length, in dwords, is in the message length field of the
1724 	 * reply header.
1725 	 */
1726 	for (i = 1; i < MIN(dwords, reply->msg_length); i++) {
1727 		if (mpi_handshake_recv_dword(sc, &dbuf[i]) != 0)
1728 			return (1);
1729 	}
1730 
1731 	/* if there's extra stuff to come off the ioc, discard it */
1732 	while (i++ < reply->msg_length) {
1733 		if (mpi_handshake_recv_dword(sc, &dummy) != 0)
1734 			return (1);
1735 		DNPRINTF(MPI_D_CMD, "%s: mpi_handshake_recv dummy read: "
1736 		    "0x%08x\n", DEVNAME(sc), dummy);
1737 	}
1738 
1739 	/* wait for the doorbell used bit to be reset and clear the intr */
1740 	if (mpi_wait_db_int(sc) != 0)
1741 		return (1);
1742 	mpi_write_intr(sc, 0);
1743 
1744 	return (0);
1745 }
1746 
1747 void
1748 mpi_empty_done(struct mpi_ccb *ccb)
1749 {
1750 	/* nothing to do */
1751 }
1752 
1753 int
1754 mpi_iocfacts(struct mpi_softc *sc)
1755 {
1756 	struct mpi_msg_iocfacts_request		ifq;
1757 	struct mpi_msg_iocfacts_reply		ifp;
1758 
1759 	DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts\n", DEVNAME(sc));
1760 
1761 	bzero(&ifq, sizeof(ifq));
1762 	bzero(&ifp, sizeof(ifp));
1763 
1764 	ifq.function = MPI_FUNCTION_IOC_FACTS;
1765 	ifq.chain_offset = 0;
1766 	ifq.msg_flags = 0;
1767 	ifq.msg_context = htole32(0xdeadbeef);
1768 
1769 	if (mpi_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) {
1770 		DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts send failed\n",
1771 		    DEVNAME(sc));
1772 		return (1);
1773 	}
1774 
1775 	if (mpi_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) {
1776 		DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts recv failed\n",
1777 		    DEVNAME(sc));
1778 		return (1);
1779 	}
1780 
1781 	DNPRINTF(MPI_D_MISC, "%s:  func: 0x%02x len: %d msgver: %d.%d\n",
1782 	    DEVNAME(sc), ifp.function, ifp.msg_length,
1783 	    ifp.msg_version_maj, ifp.msg_version_min);
1784 	DNPRINTF(MPI_D_MISC, "%s:  msgflags: 0x%02x iocnumber: 0x%02x "
1785 	    "hdrver: %d.%d\n", DEVNAME(sc), ifp.msg_flags,
1786 	    ifp.ioc_number, ifp.header_version_maj,
1787 	    ifp.header_version_min);
1788 	DNPRINTF(MPI_D_MISC, "%s:  message context: 0x%08x\n", DEVNAME(sc),
1789 	    letoh32(ifp.msg_context));
1790 	DNPRINTF(MPI_D_MISC, "%s:  iocstatus: 0x%04x ioexcept: 0x%04x\n",
1791 	    DEVNAME(sc), letoh16(ifp.ioc_status),
1792 	    letoh16(ifp.ioc_exceptions));
1793 	DNPRINTF(MPI_D_MISC, "%s:  iocloginfo: 0x%08x\n", DEVNAME(sc),
1794 	    letoh32(ifp.ioc_loginfo));
1795 	DNPRINTF(MPI_D_MISC, "%s:  flags: 0x%02x blocksize: %d whoinit: 0x%02x "
1796 	    "maxchdepth: %d\n", DEVNAME(sc), ifp.flags,
1797 	    ifp.block_size, ifp.whoinit, ifp.max_chain_depth);
1798 	DNPRINTF(MPI_D_MISC, "%s:  reqfrsize: %d replyqdepth: %d\n",
1799 	    DEVNAME(sc), letoh16(ifp.request_frame_size),
1800 	    letoh16(ifp.reply_queue_depth));
1801 	DNPRINTF(MPI_D_MISC, "%s:  productid: 0x%04x\n", DEVNAME(sc),
1802 	    letoh16(ifp.product_id));
1803 	DNPRINTF(MPI_D_MISC, "%s:  hostmfahiaddr: 0x%08x\n", DEVNAME(sc),
1804 	    letoh32(ifp.current_host_mfa_hi_addr));
1805 	DNPRINTF(MPI_D_MISC, "%s:  event_state: 0x%02x number_of_ports: %d "
1806 	    "global_credits: %d\n",
1807 	    DEVNAME(sc), ifp.event_state, ifp.number_of_ports,
1808 	    letoh16(ifp.global_credits));
1809 	DNPRINTF(MPI_D_MISC, "%s:  sensebufhiaddr: 0x%08x\n", DEVNAME(sc),
1810 	    letoh32(ifp.current_sense_buffer_hi_addr));
1811 	DNPRINTF(MPI_D_MISC, "%s:  maxbus: %d maxdev: %d replyfrsize: %d\n",
1812 	    DEVNAME(sc), ifp.max_buses, ifp.max_devices,
1813 	    letoh16(ifp.current_reply_frame_size));
1814 	DNPRINTF(MPI_D_MISC, "%s:  fw_image_size: %d\n", DEVNAME(sc),
1815 	    letoh32(ifp.fw_image_size));
1816 	DNPRINTF(MPI_D_MISC, "%s:  ioc_capabilities: 0x%08x\n", DEVNAME(sc),
1817 	    letoh32(ifp.ioc_capabilities));
1818 	DNPRINTF(MPI_D_MISC, "%s:  fw_version: %d.%d fw_version_unit: 0x%02x "
1819 	    "fw_version_dev: 0x%02x\n", DEVNAME(sc),
1820 	    ifp.fw_version_maj, ifp.fw_version_min,
1821 	    ifp.fw_version_unit, ifp.fw_version_dev);
1822 	DNPRINTF(MPI_D_MISC, "%s:  hi_priority_queue_depth: 0x%04x\n",
1823 	    DEVNAME(sc), letoh16(ifp.hi_priority_queue_depth));
1824 	DNPRINTF(MPI_D_MISC, "%s:  host_page_buffer_sge: hdr: 0x%08x "
1825 	    "addr 0x%08x %08x\n", DEVNAME(sc),
1826 	    letoh32(ifp.host_page_buffer_sge.sg_hdr),
1827 	    letoh32(ifp.host_page_buffer_sge.sg_hi_addr),
1828 	    letoh32(ifp.host_page_buffer_sge.sg_lo_addr));
1829 
1830 	sc->sc_maxcmds = letoh16(ifp.global_credits);
1831 	sc->sc_maxchdepth = ifp.max_chain_depth;
1832 	sc->sc_ioc_number = ifp.ioc_number;
1833 	if (sc->sc_flags & MPI_F_SPI)
1834 		sc->sc_buswidth = 16;
1835 	else
1836 		sc->sc_buswidth =
1837 		    (ifp.max_devices == 0) ? 256 : ifp.max_devices;
1838 	if (ifp.flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
1839 		sc->sc_fw_len = letoh32(ifp.fw_image_size);
1840 
1841 	/*
1842 	 * you can fit sg elements on the end of the io cmd if they fit in the
1843 	 * request frame size.
1844 	 */
1845 	sc->sc_first_sgl_len = ((letoh16(ifp.request_frame_size) * 4) -
1846 	    sizeof(struct mpi_msg_scsi_io)) / sizeof(struct mpi_sge);
1847 	DNPRINTF(MPI_D_MISC, "%s:   first sgl len: %d\n", DEVNAME(sc),
1848 	    sc->sc_first_sgl_len);
1849 
1850 	sc->sc_chain_len = (letoh16(ifp.request_frame_size) * 4) /
1851 	    sizeof(struct mpi_sge);
1852 	DNPRINTF(MPI_D_MISC, "%s:   chain len: %d\n", DEVNAME(sc),
1853 	    sc->sc_chain_len);
1854 
1855 	/* the sgl tailing the io cmd loses an entry to the chain element. */
1856 	sc->sc_max_sgl_len = MPI_MAX_SGL - 1;
1857 	/* the sgl chains lose an entry for each chain element */
1858 	sc->sc_max_sgl_len -= (MPI_MAX_SGL - sc->sc_first_sgl_len) /
1859 	    sc->sc_chain_len;
1860 	DNPRINTF(MPI_D_MISC, "%s:   max sgl len: %d\n", DEVNAME(sc),
1861 	    sc->sc_max_sgl_len);
1862 
1863 	/* XXX we're ignoring the max chain depth */
1864 
1865 	return (0);
1866 }
1867 
1868 int
1869 mpi_iocinit(struct mpi_softc *sc)
1870 {
1871 	struct mpi_msg_iocinit_request		iiq;
1872 	struct mpi_msg_iocinit_reply		iip;
1873 	u_int32_t				hi_addr;
1874 
1875 	DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit\n", DEVNAME(sc));
1876 
1877 	bzero(&iiq, sizeof(iiq));
1878 	bzero(&iip, sizeof(iip));
1879 
1880 	iiq.function = MPI_FUNCTION_IOC_INIT;
1881 	iiq.whoinit = MPI_WHOINIT_HOST_DRIVER;
1882 
1883 	iiq.max_devices = (sc->sc_buswidth == 256) ? 0 : sc->sc_buswidth;
1884 	iiq.max_buses = 1;
1885 
1886 	iiq.msg_context = htole32(0xd00fd00f);
1887 
1888 	iiq.reply_frame_size = htole16(MPI_REPLY_SIZE);
1889 
1890 	hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_requests) >> 32);
1891 	iiq.host_mfa_hi_addr = htole32(hi_addr);
1892 	iiq.sense_buffer_hi_addr = htole32(hi_addr);
1893 
1894 	hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_replies) >> 32);
1895 	iiq.reply_fifo_host_signalling_addr = htole32(hi_addr);
1896 
1897 	iiq.msg_version_maj = 0x01;
1898 	iiq.msg_version_min = 0x02;
1899 
1900 	iiq.hdr_version_unit = 0x0d;
1901 	iiq.hdr_version_dev = 0x00;
1902 
1903 	if (mpi_handshake_send(sc, &iiq, dwordsof(iiq)) != 0) {
1904 		DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit send failed\n",
1905 		    DEVNAME(sc));
1906 		return (1);
1907 	}
1908 
1909 	if (mpi_handshake_recv(sc, &iip, dwordsof(iip)) != 0) {
1910 		DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit recv failed\n",
1911 		    DEVNAME(sc));
1912 		return (1);
1913 	}
1914 
1915 	DNPRINTF(MPI_D_MISC, "%s:  function: 0x%02x msg_length: %d "
1916 	    "whoinit: 0x%02x\n", DEVNAME(sc), iip.function,
1917 	    iip.msg_length, iip.whoinit);
1918 	DNPRINTF(MPI_D_MISC, "%s:  msg_flags: 0x%02x max_buses: %d "
1919 	    "max_devices: %d flags: 0x%02x\n", DEVNAME(sc), iip.msg_flags,
1920 	    iip.max_buses, iip.max_devices, iip.flags);
1921 	DNPRINTF(MPI_D_MISC, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
1922 	    letoh32(iip.msg_context));
1923 	DNPRINTF(MPI_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
1924 	    letoh16(iip.ioc_status));
1925 	DNPRINTF(MPI_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1926 	    letoh32(iip.ioc_loginfo));
1927 
1928 	return (0);
1929 }
1930 
1931 int
1932 mpi_portfacts(struct mpi_softc *sc)
1933 {
1934 	struct mpi_ccb				*ccb;
1935 	struct mpi_msg_portfacts_request	*pfq;
1936 	volatile struct mpi_msg_portfacts_reply	*pfp;
1937 	int					s, rv = 1;
1938 
1939 	DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts\n", DEVNAME(sc));
1940 
1941 	s = splbio();
1942 	ccb = mpi_get_ccb(sc);
1943 	splx(s);
1944 	if (ccb == NULL) {
1945 		DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts ccb_get\n",
1946 		    DEVNAME(sc));
1947 		return (rv);
1948 	}
1949 
1950 	ccb->ccb_done = mpi_empty_done;
1951 	pfq = ccb->ccb_cmd;
1952 
1953 	pfq->function = MPI_FUNCTION_PORT_FACTS;
1954 	pfq->chain_offset = 0;
1955 	pfq->msg_flags = 0;
1956 	pfq->port_number = 0;
1957 	pfq->msg_context = htole32(ccb->ccb_id);
1958 
1959 	if (mpi_poll(sc, ccb, 50000) != 0) {
1960 		DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts poll\n", DEVNAME(sc));
1961 		goto err;
1962 	}
1963 
1964 	if (ccb->ccb_rcb == NULL) {
1965 		DNPRINTF(MPI_D_MISC, "%s: empty portfacts reply\n",
1966 		    DEVNAME(sc));
1967 		goto err;
1968 	}
1969 	pfp = ccb->ccb_rcb->rcb_reply;
1970 
1971 	DNPRINTF(MPI_D_MISC, "%s:  function: 0x%02x msg_length: %d\n",
1972 	    DEVNAME(sc), pfp->function, pfp->msg_length);
1973 	DNPRINTF(MPI_D_MISC, "%s:  msg_flags: 0x%02x port_number: %d\n",
1974 	    DEVNAME(sc), pfp->msg_flags, pfp->port_number);
1975 	DNPRINTF(MPI_D_MISC, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
1976 	    letoh32(pfp->msg_context));
1977 	DNPRINTF(MPI_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
1978 	    letoh16(pfp->ioc_status));
1979 	DNPRINTF(MPI_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1980 	    letoh32(pfp->ioc_loginfo));
1981 	DNPRINTF(MPI_D_MISC, "%s:  max_devices: %d port_type: 0x%02x\n",
1982 	    DEVNAME(sc), letoh16(pfp->max_devices), pfp->port_type);
1983 	DNPRINTF(MPI_D_MISC, "%s:  protocol_flags: 0x%04x port_scsi_id: %d\n",
1984 	    DEVNAME(sc), letoh16(pfp->protocol_flags),
1985 	    letoh16(pfp->port_scsi_id));
1986 	DNPRINTF(MPI_D_MISC, "%s:  max_persistent_ids: %d "
1987 	    "max_posted_cmd_buffers: %d\n", DEVNAME(sc),
1988 	    letoh16(pfp->max_persistent_ids),
1989 	    letoh16(pfp->max_posted_cmd_buffers));
1990 	DNPRINTF(MPI_D_MISC, "%s:  max_lan_buckets: %d\n", DEVNAME(sc),
1991 	    letoh16(pfp->max_lan_buckets));
1992 
1993 	sc->sc_porttype = pfp->port_type;
1994 	if (sc->sc_target == -1)
1995 		sc->sc_target = letoh16(pfp->port_scsi_id);
1996 
1997 	mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
1998 	rv = 0;
1999 err:
2000 	mpi_put_ccb(sc, ccb);
2001 
2002 	return (rv);
2003 }
2004 
2005 int
2006 mpi_eventnotify(struct mpi_softc *sc)
2007 {
2008 	struct mpi_ccb				*ccb;
2009 	struct mpi_msg_event_request		*enq;
2010 	int					s;
2011 
2012 	s = splbio();
2013 	ccb = mpi_get_ccb(sc);
2014 	splx(s);
2015 	if (ccb == NULL) {
2016 		DNPRINTF(MPI_D_MISC, "%s: mpi_eventnotify ccb_get\n",
2017 		    DEVNAME(sc));
2018 		return (1);
2019 	}
2020 
2021 	ccb->ccb_done = mpi_eventnotify_done;
2022 	enq = ccb->ccb_cmd;
2023 
2024 	enq->function = MPI_FUNCTION_EVENT_NOTIFICATION;
2025 	enq->chain_offset = 0;
2026 	enq->event_switch = MPI_EVENT_SWITCH_ON;
2027 	enq->msg_context = htole32(ccb->ccb_id);
2028 
2029 	mpi_start(sc, ccb);
2030 	return (0);
2031 }
2032 
2033 void
2034 mpi_eventnotify_done(struct mpi_ccb *ccb)
2035 {
2036 	struct mpi_softc			*sc = ccb->ccb_sc;
2037 	struct mpi_msg_event_reply		*enp = ccb->ccb_rcb->rcb_reply;
2038 	int					deferred = 0;
2039 
2040 	DNPRINTF(MPI_D_EVT, "%s: mpi_eventnotify_done\n", DEVNAME(sc));
2041 
2042 	DNPRINTF(MPI_D_EVT, "%s:  function: 0x%02x msg_length: %d "
2043 	    "data_length: %d\n", DEVNAME(sc), enp->function, enp->msg_length,
2044 	    letoh16(enp->data_length));
2045 	DNPRINTF(MPI_D_EVT, "%s:  ack_required: %d msg_flags 0x%02x\n",
2046 	    DEVNAME(sc), enp->ack_required, enp->msg_flags);
2047 	DNPRINTF(MPI_D_EVT, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
2048 	    letoh32(enp->msg_context));
2049 	DNPRINTF(MPI_D_EVT, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
2050 	    letoh16(enp->ioc_status));
2051 	DNPRINTF(MPI_D_EVT, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
2052 	    letoh32(enp->ioc_loginfo));
2053 	DNPRINTF(MPI_D_EVT, "%s:  event: 0x%08x\n", DEVNAME(sc),
2054 	    letoh32(enp->event));
2055 	DNPRINTF(MPI_D_EVT, "%s:  event_context: 0x%08x\n", DEVNAME(sc),
2056 	    letoh32(enp->event_context));
2057 
2058 	switch (letoh32(enp->event)) {
2059 	/* ignore these */
2060 	case MPI_EVENT_EVENT_CHANGE:
2061 	case MPI_EVENT_SAS_PHY_LINK_STATUS:
2062 		break;
2063 
2064 	case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
2065 		if (sc->sc_scsibus == NULL)
2066 			break;
2067 
2068 		if (scsi_task(mpi_evt_sas, sc, ccb->ccb_rcb, 0) != 0) {
2069 			printf("%s: unable to run SAS device status change\n",
2070 			    DEVNAME(sc));
2071 			break;
2072 		}
2073 		deferred = 1;
2074 		break;
2075 
2076 	default:
2077 		printf("%s: unhandled event 0x%02x\n", DEVNAME(sc),
2078 		    letoh32(enp->event));
2079 		break;
2080 	}
2081 
2082 	if (!deferred) {
2083 		if (enp->ack_required)
2084 			mpi_eventack(sc, enp);
2085 		mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
2086 	}
2087 
2088 	if ((enp->msg_flags & MPI_EVENT_FLAGS_REPLY_KEPT) == 0) {
2089 		/* XXX this shouldnt happen till shutdown */
2090 		mpi_put_ccb(sc, ccb);
2091 	}
2092 }
2093 
2094 void
2095 mpi_evt_sas(void *xsc, void *arg)
2096 {
2097 	struct mpi_softc			*sc = xsc;
2098 	struct mpi_rcb				*rcb = arg;
2099 	struct mpi_msg_event_reply		*enp = rcb->rcb_reply;
2100 	struct mpi_evt_sas_change		*ch;
2101 	u_int8_t				*data;
2102 	int					s;
2103 
2104 	data = rcb->rcb_reply;
2105 	data += sizeof(struct mpi_msg_event_reply);
2106 	ch = (struct mpi_evt_sas_change *)data;
2107 
2108 	if (ch->bus != 0)
2109 		return;
2110 
2111 	switch (ch->reason) {
2112 	case MPI_EVT_SASCH_REASON_ADDED:
2113 	case MPI_EVT_SASCH_REASON_NO_PERSIST_ADDED:
2114 		scsi_probe_target(sc->sc_scsibus, ch->target);
2115 		break;
2116 
2117 	case MPI_EVT_SASCH_REASON_NOT_RESPONDING:
2118 		scsi_detach_target(sc->sc_scsibus, ch->target, DETACH_FORCE);
2119 		break;
2120 
2121 	case MPI_EVT_SASCH_REASON_SMART_DATA:
2122 	case MPI_EVT_SASCH_REASON_UNSUPPORTED:
2123 	case MPI_EVT_SASCH_REASON_INTERNAL_RESET:
2124 		break;
2125 	default:
2126 		printf("%s: unknown reason for SAS device status change: "
2127 		    "0x%02x\n", DEVNAME(sc), ch->reason);
2128 		break;
2129 	}
2130 
2131 	s = splbio();
2132 	mpi_push_reply(sc, rcb->rcb_reply_dva);
2133 	if (enp->ack_required)
2134 		mpi_eventack(sc, enp);
2135 	splx(s);
2136 }
2137 
2138 void
2139 mpi_eventack(struct mpi_softc *sc, struct mpi_msg_event_reply *enp)
2140 {
2141 	struct mpi_ccb				*ccb;
2142 	struct mpi_msg_eventack_request		*eaq;
2143 
2144 	ccb = mpi_get_ccb(sc);
2145 	if (ccb == NULL) {
2146 		DNPRINTF(MPI_D_EVT, "%s: mpi_eventack ccb_get\n", DEVNAME(sc));
2147 		return;
2148 	}
2149 
2150 	ccb->ccb_done = mpi_eventack_done;
2151 	eaq = ccb->ccb_cmd;
2152 
2153 	eaq->function = MPI_FUNCTION_EVENT_ACK;
2154 	eaq->msg_context = htole32(ccb->ccb_id);
2155 
2156 	eaq->event = enp->event;
2157 	eaq->event_context = enp->event_context;
2158 
2159 	mpi_start(sc, ccb);
2160 	return;
2161 }
2162 
2163 void
2164 mpi_eventack_done(struct mpi_ccb *ccb)
2165 {
2166 	struct mpi_softc			*sc = ccb->ccb_sc;
2167 
2168 	DNPRINTF(MPI_D_EVT, "%s: event ack done\n", DEVNAME(sc));
2169 
2170 	mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
2171 	mpi_put_ccb(sc, ccb);
2172 }
2173 
2174 int
2175 mpi_portenable(struct mpi_softc *sc)
2176 {
2177 	struct mpi_ccb				*ccb;
2178 	struct mpi_msg_portenable_request	*peq;
2179 	struct mpi_msg_portenable_repy		*pep;
2180 	int					s;
2181 
2182 	DNPRINTF(MPI_D_MISC, "%s: mpi_portenable\n", DEVNAME(sc));
2183 
2184 	s = splbio();
2185 	ccb = mpi_get_ccb(sc);
2186 	splx(s);
2187 	if (ccb == NULL) {
2188 		DNPRINTF(MPI_D_MISC, "%s: mpi_portenable ccb_get\n",
2189 		    DEVNAME(sc));
2190 		return (1);
2191 	}
2192 
2193 	ccb->ccb_done = mpi_empty_done;
2194 	peq = ccb->ccb_cmd;
2195 
2196 	peq->function = MPI_FUNCTION_PORT_ENABLE;
2197 	peq->port_number = 0;
2198 	peq->msg_context = htole32(ccb->ccb_id);
2199 
2200 	if (mpi_poll(sc, ccb, 50000) != 0) {
2201 		DNPRINTF(MPI_D_MISC, "%s: mpi_portenable poll\n", DEVNAME(sc));
2202 		return (1);
2203 	}
2204 
2205 	if (ccb->ccb_rcb == NULL) {
2206 		DNPRINTF(MPI_D_MISC, "%s: empty portenable reply\n",
2207 		    DEVNAME(sc));
2208 		return (1);
2209 	}
2210 	pep = ccb->ccb_rcb->rcb_reply;
2211 
2212 	mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
2213 	mpi_put_ccb(sc, ccb);
2214 
2215 	return (0);
2216 }
2217 
2218 int
2219 mpi_fwupload(struct mpi_softc *sc)
2220 {
2221 	struct mpi_ccb				*ccb;
2222 	struct {
2223 		struct mpi_msg_fwupload_request		req;
2224 		struct mpi_sge				sge;
2225 	} __packed				*bundle;
2226 	struct mpi_msg_fwupload_reply		*upp;
2227 	u_int64_t				addr;
2228 	int					s;
2229 	int					rv = 0;
2230 
2231 	if (sc->sc_fw_len == 0)
2232 		return (0);
2233 
2234 	DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload\n", DEVNAME(sc));
2235 
2236 	sc->sc_fw = mpi_dmamem_alloc(sc, sc->sc_fw_len);
2237 	if (sc->sc_fw == NULL) {
2238 		DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload unable to allocate %d\n",
2239 		    DEVNAME(sc), sc->sc_fw_len);
2240 		return (1);
2241 	}
2242 
2243 	s = splbio();
2244 	ccb = mpi_get_ccb(sc);
2245 	splx(s);
2246 	if (ccb == NULL) {
2247 		DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload ccb_get\n",
2248 		    DEVNAME(sc));
2249 		goto err;
2250 	}
2251 
2252 	ccb->ccb_done = mpi_empty_done;
2253 	bundle = ccb->ccb_cmd;
2254 
2255 	bundle->req.function = MPI_FUNCTION_FW_UPLOAD;
2256 	bundle->req.msg_context = htole32(ccb->ccb_id);
2257 
2258 	bundle->req.image_type = MPI_FWUPLOAD_IMAGETYPE_IOC_FW;
2259 
2260 	bundle->req.tce.details_length = 12;
2261 	bundle->req.tce.image_size = htole32(sc->sc_fw_len);
2262 
2263 	bundle->sge.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
2264 	    MPI_SGE_FL_SIZE_64 | MPI_SGE_FL_LAST | MPI_SGE_FL_EOB |
2265 	    MPI_SGE_FL_EOL | (u_int32_t)sc->sc_fw_len);
2266 	addr = MPI_DMA_DVA(sc->sc_fw);
2267 	bundle->sge.sg_hi_addr = htole32((u_int32_t)(addr >> 32));
2268 	bundle->sge.sg_lo_addr = htole32((u_int32_t)addr);
2269 
2270 	if (mpi_poll(sc, ccb, 50000) != 0) {
2271 		DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header poll\n", DEVNAME(sc));
2272 		goto err;
2273 	}
2274 
2275 	if (ccb->ccb_rcb == NULL)
2276 		panic("%s: unable to do fw upload\n", DEVNAME(sc));
2277 	upp = ccb->ccb_rcb->rcb_reply;
2278 
2279 	if (letoh16(upp->ioc_status) != MPI_IOCSTATUS_SUCCESS)
2280 		rv = 1;
2281 
2282 	mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
2283 	mpi_put_ccb(sc, ccb);
2284 
2285 	return (rv);
2286 
2287 err:
2288 	mpi_dmamem_free(sc, sc->sc_fw);
2289 	return (1);
2290 }
2291 
2292 void
2293 mpi_get_raid(struct mpi_softc *sc)
2294 {
2295 	struct mpi_cfg_hdr		hdr;
2296 	struct mpi_cfg_ioc_pg2		*vol_page;
2297 	struct mpi_cfg_raid_vol		*vol_list, *vol;
2298 	size_t				pagelen;
2299 	u_int32_t			capabilities;
2300 	struct scsi_link		*link;
2301 	int				i;
2302 
2303 	DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid\n", DEVNAME(sc));
2304 
2305 	if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_IOC, 2, 0, &hdr) != 0) {
2306 		DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to fetch header"
2307 		    "for IOC page 2\n", DEVNAME(sc));
2308 		return;
2309 	}
2310 
2311 	pagelen = hdr.page_length * 4; /* dwords to bytes */
2312 	vol_page = malloc(pagelen, M_TEMP, M_WAITOK|M_CANFAIL);
2313 	if (vol_page == NULL) {
2314 		DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to allocate "
2315 		    "space for ioc config page 2\n", DEVNAME(sc));
2316 		return;
2317 	}
2318 	vol_list = (struct mpi_cfg_raid_vol *)(vol_page + 1);
2319 
2320 	if (mpi_cfg_page(sc, 0, &hdr, 1, vol_page, pagelen) != 0) {
2321 		DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to fetch IOC "
2322 		    "page 2\n", DEVNAME(sc));
2323 		goto out;
2324 	}
2325 
2326 	capabilities = letoh32(vol_page->capabilities);
2327 
2328 	DNPRINTF(MPI_D_RAID, "%s:  capabilities: 0x08%x\n", DEVNAME(sc),
2329 	    letoh32(vol_page->capabilities));
2330 	DNPRINTF(MPI_D_RAID, "%s:  active_vols: %d max_vols: %d "
2331 	    "active_physdisks: %d max_physdisks: %d\n", DEVNAME(sc),
2332 	    vol_page->active_vols, vol_page->max_vols,
2333 	    vol_page->active_physdisks, vol_page->max_physdisks);
2334 
2335 	/* don't walk list if there are no RAID capability */
2336 	if (capabilities == 0xdeadbeef) {
2337 		printf("%s: deadbeef in raid configuration\n", DEVNAME(sc));
2338 		goto out;
2339 	}
2340 
2341 	if ((capabilities & MPI_CFG_IOC_2_CAPABILITIES_RAID) == 0 ||
2342 	    (vol_page->active_vols == 0))
2343 		goto out;
2344 
2345 	sc->sc_flags |= MPI_F_RAID;
2346 
2347 	for (i = 0; i < vol_page->active_vols; i++) {
2348 		vol = &vol_list[i];
2349 
2350 		DNPRINTF(MPI_D_RAID, "%s:   id: %d bus: %d ioc: %d pg: %d\n",
2351 		    DEVNAME(sc), vol->vol_id, vol->vol_bus, vol->vol_ioc,
2352 		    vol->vol_page);
2353 		DNPRINTF(MPI_D_RAID, "%s:   type: 0x%02x flags: 0x%02x\n",
2354 		    DEVNAME(sc), vol->vol_type, vol->flags);
2355 
2356 		if (vol->vol_ioc != sc->sc_ioc_number || vol->vol_bus != 0)
2357 			continue;
2358 
2359 		link = sc->sc_scsibus->sc_link[vol->vol_id][0];
2360 		if (link == NULL)
2361 			continue;
2362 
2363 		link->flags |= SDEV_VIRTUAL;
2364 	}
2365 
2366 out:
2367 	free(vol_page, M_TEMP);
2368 }
2369 
2370 int
2371 mpi_req_cfg_header(struct mpi_softc *sc, u_int8_t type, u_int8_t number,
2372     u_int32_t address, int extended, void *p)
2373 {
2374 	struct mpi_ccb				*ccb;
2375 	struct mpi_msg_config_request		*cq;
2376 	struct mpi_msg_config_reply		*cp;
2377 	struct mpi_cfg_hdr			*hdr = p;
2378 	struct mpi_ecfg_hdr			*ehdr = p;
2379 	int					etype = 0;
2380 	int					rv = 0;
2381 	int					s;
2382 
2383 	DNPRINTF(MPI_D_MISC, "%s: mpi_req_cfg_header type: %#x number: %x "
2384 	    "address: 0x%08x extended: %d\n", DEVNAME(sc), type, number,
2385 	    address, extended);
2386 
2387 	s = splbio();
2388 	ccb = mpi_get_ccb(sc);
2389 	splx(s);
2390 	if (ccb == NULL) {
2391 		DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header ccb_get\n",
2392 		    DEVNAME(sc));
2393 		return (1);
2394 	}
2395 
2396 	if (extended) {
2397 		etype = type;
2398 		type = MPI_CONFIG_REQ_PAGE_TYPE_EXTENDED;
2399 	}
2400 
2401 	ccb->ccb_done = mpi_empty_done;
2402 	cq = ccb->ccb_cmd;
2403 
2404 	cq->function = MPI_FUNCTION_CONFIG;
2405 	cq->msg_context = htole32(ccb->ccb_id);
2406 
2407 	cq->action = MPI_CONFIG_REQ_ACTION_PAGE_HEADER;
2408 
2409 	cq->config_header.page_number = number;
2410 	cq->config_header.page_type = type;
2411 	cq->ext_page_type = etype;
2412 	cq->page_address = htole32(address);
2413 	cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
2414 	    MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL);
2415 
2416 	if (mpi_poll(sc, ccb, 50000) != 0) {
2417 		DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header poll\n", DEVNAME(sc));
2418 		return (1);
2419 	}
2420 
2421 	if (ccb->ccb_rcb == NULL)
2422 		panic("%s: unable to fetch config header\n", DEVNAME(sc));
2423 	cp = ccb->ccb_rcb->rcb_reply;
2424 
2425 	DNPRINTF(MPI_D_MISC, "%s:  action: 0x%02x msg_length: %d function: "
2426 	    "0x%02x\n", DEVNAME(sc), cp->action, cp->msg_length, cp->function);
2427 	DNPRINTF(MPI_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
2428 	    "msg_flags: 0x%02x\n", DEVNAME(sc),
2429 	    letoh16(cp->ext_page_length), cp->ext_page_type,
2430 	    cp->msg_flags);
2431 	DNPRINTF(MPI_D_MISC, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
2432 	    letoh32(cp->msg_context));
2433 	DNPRINTF(MPI_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
2434 	    letoh16(cp->ioc_status));
2435 	DNPRINTF(MPI_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
2436 	    letoh32(cp->ioc_loginfo));
2437 	DNPRINTF(MPI_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
2438 	    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
2439 	    cp->config_header.page_version,
2440 	    cp->config_header.page_length,
2441 	    cp->config_header.page_number,
2442 	    cp->config_header.page_type);
2443 
2444 	if (letoh16(cp->ioc_status) != MPI_IOCSTATUS_SUCCESS)
2445 		rv = 1;
2446 	else if (extended) {
2447 		bzero(ehdr, sizeof(*ehdr));
2448 		ehdr->page_version = cp->config_header.page_version;
2449 		ehdr->page_number = cp->config_header.page_number;
2450 		ehdr->page_type = cp->config_header.page_type;
2451 		ehdr->ext_page_length = cp->ext_page_length;
2452 		ehdr->ext_page_type = cp->ext_page_type;
2453 	} else
2454 		*hdr = cp->config_header;
2455 
2456 	mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
2457 	mpi_put_ccb(sc, ccb);
2458 
2459 	return (rv);
2460 }
2461 
2462 int
2463 mpi_req_cfg_page(struct mpi_softc *sc, u_int32_t address, int extended,
2464     void *p, int read, void *page, size_t len)
2465 {
2466 	struct mpi_ccb				*ccb;
2467 	struct mpi_msg_config_request		*cq;
2468 	struct mpi_msg_config_reply		*cp;
2469 	struct mpi_cfg_hdr			*hdr = p;
2470 	struct mpi_ecfg_hdr			*ehdr = p;
2471 	u_int64_t				dva;
2472 	char					*kva;
2473 	int					page_length;
2474 	int					rv = 0;
2475 	int					s;
2476 
2477 	DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page address: %d read: %d type: %x\n",
2478 	    DEVNAME(sc), address, read, hdr->page_type);
2479 
2480 	page_length = extended ?
2481 	    letoh16(ehdr->ext_page_length) : hdr->page_length;
2482 
2483 	if (len > MPI_REQUEST_SIZE - sizeof(struct mpi_msg_config_request) ||
2484 	    len < page_length * 4)
2485 		return (1);
2486 
2487 	s = splbio();
2488 	ccb = mpi_get_ccb(sc);
2489 	splx(s);
2490 	if (ccb == NULL) {
2491 		DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page ccb_get\n", DEVNAME(sc));
2492 		return (1);
2493 	}
2494 
2495 	ccb->ccb_done = mpi_empty_done;
2496 	cq = ccb->ccb_cmd;
2497 
2498 	cq->function = MPI_FUNCTION_CONFIG;
2499 	cq->msg_context = htole32(ccb->ccb_id);
2500 
2501 	cq->action = (read ? MPI_CONFIG_REQ_ACTION_PAGE_READ_CURRENT :
2502 	    MPI_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT);
2503 
2504 	if (extended) {
2505 		cq->config_header.page_version = ehdr->page_version;
2506 		cq->config_header.page_number = ehdr->page_number;
2507 		cq->config_header.page_type = ehdr->page_type;
2508 		cq->ext_page_len = ehdr->ext_page_length;
2509 		cq->ext_page_type = ehdr->ext_page_type;
2510 	} else
2511 		cq->config_header = *hdr;
2512 	cq->config_header.page_type &= MPI_CONFIG_REQ_PAGE_TYPE_MASK;
2513 	cq->page_address = htole32(address);
2514 	cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
2515 	    MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL |
2516 	    (page_length * 4) |
2517 	    (read ? MPI_SGE_FL_DIR_IN : MPI_SGE_FL_DIR_OUT));
2518 
2519 	/* bounce the page via the request space to avoid more bus_dma games */
2520 	dva = ccb->ccb_cmd_dva + sizeof(struct mpi_msg_config_request);
2521 
2522 	cq->page_buffer.sg_hi_addr = htole32((u_int32_t)(dva >> 32));
2523 	cq->page_buffer.sg_lo_addr = htole32((u_int32_t)dva);
2524 
2525 	kva = ccb->ccb_cmd;
2526 	kva += sizeof(struct mpi_msg_config_request);
2527 	if (!read)
2528 		bcopy(page, kva, len);
2529 
2530 	if (mpi_poll(sc, ccb, 50000) != 0) {
2531 		DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page poll\n", DEVNAME(sc));
2532 		return (1);
2533 	}
2534 
2535 	if (ccb->ccb_rcb == NULL) {
2536 		mpi_put_ccb(sc, ccb);
2537 		return (1);
2538 	}
2539 	cp = ccb->ccb_rcb->rcb_reply;
2540 
2541 	DNPRINTF(MPI_D_MISC, "%s:  action: 0x%02x msg_length: %d function: "
2542 	    "0x%02x\n", DEVNAME(sc), cp->action, cp->msg_length, cp->function);
2543 	DNPRINTF(MPI_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
2544 	    "msg_flags: 0x%02x\n", DEVNAME(sc),
2545 	    letoh16(cp->ext_page_length), cp->ext_page_type,
2546 	    cp->msg_flags);
2547 	DNPRINTF(MPI_D_MISC, "%s:  msg_context: 0x%08x\n", DEVNAME(sc),
2548 	    letoh32(cp->msg_context));
2549 	DNPRINTF(MPI_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
2550 	    letoh16(cp->ioc_status));
2551 	DNPRINTF(MPI_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
2552 	    letoh32(cp->ioc_loginfo));
2553 	DNPRINTF(MPI_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
2554 	    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
2555 	    cp->config_header.page_version,
2556 	    cp->config_header.page_length,
2557 	    cp->config_header.page_number,
2558 	    cp->config_header.page_type);
2559 
2560 	if (letoh16(cp->ioc_status) != MPI_IOCSTATUS_SUCCESS)
2561 		rv = 1;
2562 	else if (read)
2563 		bcopy(kva, page, len);
2564 
2565 	mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva);
2566 	mpi_put_ccb(sc, ccb);
2567 
2568 	return (rv);
2569 }
2570 
2571 int
2572 mpi_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag,
2573     struct proc *p)
2574 {
2575 	struct mpi_softc	*sc = (struct mpi_softc *)link->adapter_softc;
2576 
2577 	DNPRINTF(MPI_D_IOCTL, "%s: mpi_scsi_ioctl\n", DEVNAME(sc));
2578 
2579 	if (sc->sc_ioctl)
2580 		return (sc->sc_ioctl(link->adapter_softc, cmd, addr));
2581 	else
2582 		return (ENOTTY);
2583 }
2584 
2585 #if NBIO > 0
2586 int
2587 mpi_ioctl(struct device *dev, u_long cmd, caddr_t addr)
2588 {
2589 	struct mpi_softc	*sc = (struct mpi_softc *)dev;
2590 	int error = 0;
2591 
2592 	DNPRINTF(MPI_D_IOCTL, "%s: mpi_ioctl ", DEVNAME(sc));
2593 
2594 	if (!(sc->sc_flags & MPI_F_RAID))
2595 		return (EINVAL);
2596 
2597 	/* make sure we have bio enabled */
2598 	if (sc->sc_ioctl != mpi_ioctl)
2599 		return (EINVAL);
2600 
2601 	rw_enter_write(&sc->sc_lock);
2602 
2603 	switch (cmd) {
2604 	case BIOCINQ:
2605 		DNPRINTF(MPI_D_IOCTL, "inq\n");
2606 		error = mpi_ioctl_inq(sc, (struct bioc_inq *)addr);
2607 		break;
2608 
2609 	case BIOCVOL:
2610 		DNPRINTF(MPI_D_IOCTL, "vol\n");
2611 		error = mpi_ioctl_vol(sc, (struct bioc_vol *)addr);
2612 		break;
2613 
2614 	case BIOCDISK:
2615 		DNPRINTF(MPI_D_IOCTL, "disk\n");
2616 		error = mpi_ioctl_disk(sc, (struct bioc_disk *)addr);
2617 		break;
2618 
2619 	case BIOCALARM:
2620 		DNPRINTF(MPI_D_IOCTL, "alarm\n");
2621 		break;
2622 
2623 	case BIOCBLINK:
2624 		DNPRINTF(MPI_D_IOCTL, "blink\n");
2625 		break;
2626 
2627 	case BIOCSETSTATE:
2628 		DNPRINTF(MPI_D_IOCTL, "setstate\n");
2629 		error = mpi_ioctl_setstate(sc, (struct bioc_setstate *)addr);
2630 		break;
2631 
2632 	default:
2633 		DNPRINTF(MPI_D_IOCTL, " invalid ioctl\n");
2634 		error = EINVAL;
2635 	}
2636 
2637 	rw_exit_write(&sc->sc_lock);
2638 
2639 	return (error);
2640 }
2641 
2642 int
2643 mpi_ioctl_inq(struct mpi_softc *sc, struct bioc_inq *bi)
2644 {
2645 	if (mpi_cfg_page(sc, 0, &sc->sc_cfg_hdr, 1, sc->sc_vol_page,
2646 	    sc->sc_cfg_hdr.page_length * 4) != 0) {
2647 		DNPRINTF(MPI_D_IOCTL, "%s: mpi_get_raid unable to fetch IOC "
2648 		    "page 2\n", DEVNAME(sc));
2649 		return (EINVAL);
2650 	}
2651 
2652 	DNPRINTF(MPI_D_IOCTL, "%s:  active_vols: %d max_vols: %d "
2653 	    "active_physdisks: %d max_physdisks: %d\n", DEVNAME(sc),
2654 	    sc->sc_vol_page->active_vols, sc->sc_vol_page->max_vols,
2655 	    sc->sc_vol_page->active_physdisks, sc->sc_vol_page->max_physdisks);
2656 
2657 	bi->bi_novol = sc->sc_vol_page->active_vols;
2658 	bi->bi_nodisk = sc->sc_vol_page->active_physdisks;
2659 	strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
2660 
2661 	return (0);
2662 }
2663 
2664 int
2665 mpi_ioctl_vol(struct mpi_softc *sc, struct bioc_vol *bv)
2666 {
2667 	int			i, vol, id, len, rv = EINVAL;
2668 	u_int32_t		address;
2669 	struct device		*dev;
2670 	struct scsi_link	*link;
2671 	struct mpi_cfg_hdr	hdr;;
2672 	struct mpi_cfg_raid_vol_pg0 *rpg0;
2673 	struct mpi_cfg_raid_vol_pg0_physdisk *physdisk;
2674 
2675 	if (mpi_cfg_page(sc, 0, &sc->sc_cfg_hdr, 1, sc->sc_vol_page,
2676 	    sc->sc_cfg_hdr.page_length * 4) != 0) {
2677 		DNPRINTF(MPI_D_IOCTL, "%s: mpi_get_raid unable to fetch IOC "
2678 		    "page 2\n", DEVNAME(sc));
2679 		return (EINVAL);
2680 	}
2681 
2682 	id = bv->bv_volid;
2683 	if (id > sc->sc_vol_page->active_vols)
2684 		return (EINVAL); /* XXX deal with hot spares */
2685 
2686 	len = sizeof *rpg0 + sc->sc_vol_page->max_physdisks * sizeof *physdisk;
2687 	rpg0 = malloc(len, M_TEMP, M_WAITOK | M_CANFAIL);
2688 	if (rpg0 == NULL) {
2689 		printf("%s: can't get memory for RAID page 0, "
2690 		    "bio disabled\n", DEVNAME(sc));
2691 		goto done;
2692 	}
2693 	physdisk = (struct mpi_cfg_raid_vol_pg0_physdisk *)(rpg0 + 1);
2694 
2695 	/* get raid vol page 0 */
2696 	address = sc->sc_vol_list[id].vol_id |
2697 	    (sc->sc_vol_list[id].vol_bus << 8);
2698 	if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
2699 	    address, &hdr) != 0)
2700 		goto done;
2701 	if (mpi_cfg_page(sc, address, &hdr, 1, rpg0, len)) {
2702 		printf("%s: can't get RAID vol cfg page 0\n", DEVNAME(sc));
2703 		goto done;
2704 	}
2705 
2706 	/* determine status */
2707 	switch (rpg0->volume_state) {
2708 	case MPI_CFG_RAID_VOL_0_STATE_OPTIMAL:
2709 		bv->bv_status = BIOC_SVONLINE;
2710 		break;
2711 	case MPI_CFG_RAID_VOL_0_STATE_DEGRADED:
2712 		bv->bv_status = BIOC_SVDEGRADED;
2713 		break;
2714 	case MPI_CFG_RAID_VOL_0_STATE_FAILED:
2715 	case MPI_CFG_RAID_VOL_0_STATE_MISSING:
2716 		bv->bv_status = BIOC_SVOFFLINE;
2717 		break;
2718 	default:
2719 		bv->bv_status = BIOC_SVINVALID;
2720 	}
2721 
2722 	/* override status if scrubbing or something */
2723 	if (rpg0->volume_status == MPI_CFG_RAID_VOL_0_STATUS_RESYNCING)
2724 		bv->bv_status = BIOC_SVREBUILD;
2725 
2726 	bv->bv_size = (u_quad_t)letoh32(rpg0->max_lba);
2727 
2728 	switch (sc->sc_vol_list[id].vol_type) {
2729 	case MPI_CFG_RAID_TYPE_RAID_IS:
2730 		bv->bv_level = 0;
2731 		break;
2732 	case MPI_CFG_RAID_TYPE_RAID_IME:
2733 	case MPI_CFG_RAID_TYPE_RAID_IM:
2734 		bv->bv_level = 1;
2735 		break;
2736 	case MPI_CFG_RAID_TYPE_RAID_5:
2737 		bv->bv_level = 5;
2738 		break;
2739 	case MPI_CFG_RAID_TYPE_RAID_6:
2740 		bv->bv_level = 6;
2741 		break;
2742 	case MPI_CFG_RAID_TYPE_RAID_10:
2743 		bv->bv_level = 10;
2744 		break;
2745 	case MPI_CFG_RAID_TYPE_RAID_50:
2746 		bv->bv_level = 50;
2747 		break;
2748 	default:
2749 		bv->bv_level = -1;
2750 	}
2751 
2752 	bv->bv_nodisk = rpg0->num_phys_disks;
2753 
2754 	for (i = 0, vol = -1; i < sc->sc_buswidth; i++) {
2755 		link = sc->sc_scsibus->sc_link[i][0];
2756 		if (link == NULL)
2757 			continue;
2758 
2759 		/* skip if not a virtual disk */
2760 		if (!(link->flags & SDEV_VIRTUAL))
2761 			continue;
2762 
2763 		vol++;
2764 		/* are we it? */
2765 		if (vol == bv->bv_volid) {
2766 			dev = link->device_softc;
2767 			memcpy(bv->bv_vendor, link->inqdata.vendor,
2768 			    sizeof bv->bv_vendor);
2769 			bv->bv_vendor[sizeof(bv->bv_vendor) - 1] = '\0';
2770 			strlcpy(bv->bv_dev, dev->dv_xname, sizeof bv->bv_dev);
2771 			break;
2772 		}
2773 	}
2774 	rv = 0;
2775 done:
2776 	free(rpg0, M_DEVBUF);
2777 	return (rv);
2778 }
2779 
2780 int
2781 mpi_ioctl_disk(struct mpi_softc *sc, struct bioc_disk *bd)
2782 {
2783 	return (ENOTTY);
2784 }
2785 
2786 int
2787 mpi_ioctl_setstate(struct mpi_softc *sc, struct bioc_setstate *bs)
2788 {
2789 	return (ENOTTY);
2790 }
2791 
2792 #ifndef SMALL_KERNEL
2793 int
2794 mpi_create_sensors(struct mpi_softc *sc)
2795 {
2796 	return (1);
2797 }
2798 #endif /* SMALL_KERNEL */
2799 #endif /* NBIO > 0 */
2800