xref: /openbsd-src/sys/dev/ic/mpi.c (revision a3bd562f06875d2c57d4d3a7d732aa94d9865bf6)
1 /*	$OpenBSD: mpi.c,v 1.27 2006/06/08 12:27:59 dlg 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 <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/buf.h>
23 #include <sys/device.h>
24 #include <sys/proc.h>
25 #include <sys/malloc.h>
26 #include <sys/kernel.h>
27 
28 #include <machine/bus.h>
29 
30 #include <scsi/scsi_all.h>
31 #include <scsi/scsiconf.h>
32 
33 #include <dev/ic/mpireg.h>
34 #include <dev/ic/mpivar.h>
35 
36 #ifdef MPI_DEBUG
37 #define DPRINTF(x...)		do { if (mpidebug) printf(x); } while (0)
38 #define DPRINTFN(n, x...)	do { if (mpidebug > (n)) printf(x); } while (0)
39 int mpidebug = 11;
40 #else
41 #define DPRINTF(x...)		/* x */
42 #define DPRINTFN(n, x...)	/* n, x */
43 #endif
44 
45 struct cfdriver mpi_cd = {
46 	NULL, "mpi", DV_DULL
47 };
48 
49 int			mpi_scsi_cmd(struct scsi_xfer *);
50 void			mpi_scsi_cmd_done(struct mpi_ccb *);
51 void			mpi_minphys(struct buf *bp);
52 int			mpi_scsi_ioctl(struct scsi_link *, u_long, caddr_t,
53 			    int, struct proc *);
54 
55 struct scsi_adapter mpi_switch = {
56 	mpi_scsi_cmd, mpi_minphys, NULL, NULL, mpi_scsi_ioctl
57 };
58 
59 struct scsi_device mpi_dev = {
60 	NULL, NULL, NULL, NULL
61 };
62 
63 struct mpi_dmamem	*mpi_dmamem_alloc(struct mpi_softc *, size_t);
64 void			mpi_dmamem_free(struct mpi_softc *,
65 			    struct mpi_dmamem *);
66 int			mpi_alloc_ccbs(struct mpi_softc *);
67 struct mpi_ccb		*mpi_get_ccb(struct mpi_softc *);
68 void			mpi_put_ccb(struct mpi_softc *, struct mpi_ccb *);
69 int			mpi_alloc_replies(struct mpi_softc *);
70 void			mpi_push_replies(struct mpi_softc *);
71 
72 void			mpi_start(struct mpi_softc *, struct mpi_ccb *);
73 int			mpi_complete(struct mpi_softc *, struct mpi_ccb *, int);
74 int			mpi_poll(struct mpi_softc *, struct mpi_ccb *, int);
75 
76 void			mpi_timeout_xs(void *);
77 int			mpi_load_xs(struct mpi_ccb *);
78 
79 u_int32_t		mpi_read(struct mpi_softc *, bus_size_t);
80 void			mpi_write(struct mpi_softc *, bus_size_t, u_int32_t);
81 int			mpi_wait_eq(struct mpi_softc *, bus_size_t, u_int32_t,
82 			    u_int32_t);
83 int			mpi_wait_ne(struct mpi_softc *, bus_size_t, u_int32_t,
84 			    u_int32_t);
85 
86 int			mpi_init(struct mpi_softc *);
87 int			mpi_reset_soft(struct mpi_softc *);
88 int			mpi_reset_hard(struct mpi_softc *);
89 
90 int			mpi_handshake_send(struct mpi_softc *, void *, size_t);
91 int			mpi_handshake_recv_dword(struct mpi_softc *,
92 			    u_int32_t *);
93 int			mpi_handshake_recv(struct mpi_softc *, void *, size_t);
94 
95 void			mpi_empty_done(struct mpi_ccb *);
96 
97 int			mpi_iocinit(struct mpi_softc *);
98 int			mpi_iocfacts(struct mpi_softc *);
99 int			mpi_portfacts(struct mpi_softc *);
100 int			mpi_eventnotify(struct mpi_softc *);
101 void			mpi_eventnotify_done(struct mpi_ccb *);
102 int			mpi_portenable(struct mpi_softc *);
103 
104 int			mpi_cfg_hdr(struct mpi_softc *, u_int8_t, u_int8_t,
105 			    u_int32_t, struct mpi_cfg_hdr *);
106 int			mpi_cfg_page(struct mpi_softc *, u_int32_t,
107 			    struct mpi_cfg_hdr *, int, void *, size_t);
108 
109 #define DEVNAME(s)		((s)->sc_dev.dv_xname)
110 
111 #define	dwordsof(s)		(sizeof(s) / sizeof(u_int32_t))
112 #define	sizeofa(s)		(sizeof(s) / sizeof((s)[0]))
113 
114 #define mpi_read_db(s)		mpi_read((s), MPI_DOORBELL)
115 #define mpi_write_db(s, v)	mpi_write((s), MPI_DOORBELL, (v))
116 #define mpi_read_intr(s)	mpi_read((s), MPI_INTR_STATUS)
117 #define mpi_write_intr(s, v)	mpi_write((s), MPI_INTR_STATUS, (v))
118 #define mpi_pop_reply(s)	mpi_read((s), MPI_REPLY_QUEUE)
119 #define mpi_push_reply(s, v)	mpi_write((s), MPI_REPLY_QUEUE, (v))
120 
121 #define mpi_wait_db_int(s)	mpi_wait_ne((s), MPI_INTR_STATUS, \
122 				    MPI_INTR_STATUS_DOORBELL, 0)
123 #define mpi_wait_db_ack(s)	mpi_wait_eq((s), MPI_INTR_STATUS, \
124 				    MPI_INTR_STATUS_IOCDOORBELL, 0)
125 
126 int
127 mpi_attach(struct mpi_softc *sc)
128 {
129 	struct mpi_ccb			*ccb;
130 
131 	printf("\n");
132 
133 	/* disable interrupts */
134 	mpi_write(sc, MPI_INTR_MASK,
135 	    MPI_INTR_MASK_REPLY | MPI_INTR_MASK_DOORBELL);
136 
137 	if (mpi_init(sc) != 0) {
138 		printf("%s: unable to initialise\n", DEVNAME(sc));
139 		return (1);
140 	}
141 
142 	if (mpi_iocfacts(sc) != 0) {
143 		printf("%s: unable to get iocfacts\n", DEVNAME(sc));
144 		return (1);
145 	}
146 
147 	if (mpi_alloc_ccbs(sc) != 0) {
148 		/* error already printed */
149 		return (1);
150 	}
151 
152 	if (mpi_alloc_replies(sc) != 0) {
153 		printf("%s: unable to allocate reply space\n", DEVNAME(sc));
154 		goto free_ccbs;
155 	}
156 
157 	if (mpi_iocinit(sc) != 0) {
158 		printf("%s: unable to send iocinit\n", DEVNAME(sc));
159 		goto free_ccbs;
160 	}
161 
162 	/* spin until we're operational */
163 	if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
164 	    MPI_DOORBELL_STATE_OPER) != 0) {
165 		printf("%s: state: 0x%08x\n", DEVNAME(sc),
166 		    mpi_read_db(sc) & MPI_DOORBELL_STATE);
167 		printf("%s: operational state timeout\n", DEVNAME(sc));
168 		goto free_ccbs;
169 	}
170 
171 	mpi_push_replies(sc);
172 
173 	if (mpi_portfacts(sc) != 0) {
174 		printf("%s: unable to get portfacts\n", DEVNAME(sc));
175 		goto free_replies;
176 	}
177 
178 #if notyet
179 	if (mpi_eventnotify(sc) != 0) {
180 		printf("%s: unable to get portfacts\n", DEVNAME(sc));
181 		goto free_replies;
182 	}
183 #endif
184 
185 	if (mpi_portenable(sc) != 0) {
186 		printf("%s: unable to enable port\n", DEVNAME(sc));
187 		goto free_replies;
188 	}
189 
190 	/* we should be good to go now, attach scsibus */
191 	sc->sc_link.device = &mpi_dev;
192 	sc->sc_link.adapter = &mpi_switch;
193 	sc->sc_link.adapter_softc = sc;
194 	sc->sc_link.adapter_target = sc->sc_target;
195 	sc->sc_link.adapter_buswidth = sc->sc_buswidth;
196 	sc->sc_link.openings = sc->sc_maxcmds / sc->sc_buswidth;
197 
198 	config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
199 
200 	/* XXX enable interrupts */
201 	mpi_write(sc, MPI_INTR_MASK, MPI_INTR_MASK_DOORBELL);
202 
203 	return (0);
204 
205 free_replies:
206 	bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies),
207 	    0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
208 	mpi_dmamem_free(sc, sc->sc_replies);
209 free_ccbs:
210 	while ((ccb = mpi_get_ccb(sc)) != NULL)
211 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
212 	mpi_dmamem_free(sc, sc->sc_requests);
213 	free(sc->sc_ccbs, M_DEVBUF);
214 
215 	return(1);
216 }
217 
218 void
219 mpi_detach(struct mpi_softc *sc)
220 {
221 
222 }
223 
224 int
225 mpi_intr(void *arg)
226 {
227 	struct mpi_softc		*sc = arg;
228 	struct mpi_ccb			*ccb;
229 	struct mpi_msg_reply		*reply = NULL;
230 	u_int32_t			reply_dva;
231 	char				*reply_addr;
232 	u_int32_t			reg, id;
233 	int				rv = 0;
234 
235 	while ((reg = mpi_pop_reply(sc)) != 0xffffffff) {
236 
237 		DPRINTF("%s: %s reply_queue: 0x%08x\n", DEVNAME(sc), __func__,
238 		    reg);
239 
240 		if (reg & MPI_REPLY_QUEUE_ADDRESS) {
241 			bus_dmamap_sync(sc->sc_dmat,
242 			    MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE,
243 			    BUS_DMASYNC_POSTREAD);
244 
245 			reply_dva = (reg & MPI_REPLY_QUEUE_ADDRESS_MASK) << 1;
246 
247 			reply_addr = MPI_DMA_KVA(sc->sc_replies);
248 			reply_addr += reply_dva -
249 			    (u_int32_t)MPI_DMA_DVA(sc->sc_replies);
250 			reply = (struct mpi_msg_reply *)reply_addr;
251 
252 			id = letoh32(reply->msg_context);
253 
254 			bus_dmamap_sync(sc->sc_dmat,
255 			    MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE,
256 			    BUS_DMASYNC_PREREAD);
257 		} else {
258 			switch (reg & MPI_REPLY_QUEUE_TYPE_MASK) {
259 			case MPI_REPLY_QUEUE_TYPE_INIT:
260 				id = reg & MPI_REPLY_QUEUE_CONTEXT;
261 				break;
262 
263 			default:
264 				panic("%s: unsupported context reply\n",
265 				    DEVNAME(sc));
266 			}
267 		}
268 
269 		DPRINTF("%s: %s id: %d\n", DEVNAME(sc), __func__, id);
270 
271 		ccb = &sc->sc_ccbs[id];
272 
273 		bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests),
274 		    ccb->ccb_offset, MPI_REQUEST_SIZE, BUS_DMASYNC_POSTWRITE);
275 		ccb->ccb_state = MPI_CCB_READY;
276 		ccb->ccb_reply = reply;
277 		ccb->ccb_reply_dva = reply_dva;
278 
279 		ccb->ccb_done(ccb);
280 		rv = 1;
281 	}
282 
283 	return (rv);
284 }
285 
286 struct mpi_dmamem *
287 mpi_dmamem_alloc(struct mpi_softc *sc, size_t size)
288 {
289 	struct mpi_dmamem		*mdm;
290 	int				nsegs;
291 
292 	mdm = malloc(sizeof(struct mpi_dmamem), M_DEVBUF, M_NOWAIT);
293 	if (mdm == NULL)
294 		return (NULL);
295 
296 	bzero(mdm, sizeof(struct mpi_dmamem));
297 	mdm->mdm_size = size;
298 
299 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
300 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0)
301 		goto mdmfree;
302 
303 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mdm->mdm_seg,
304 	    1, &nsegs, BUS_DMA_NOWAIT) != 0)
305 		goto destroy;
306 
307 	if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size,
308 	    &mdm->mdm_kva, BUS_DMA_NOWAIT) != 0)
309 		goto free;
310 
311 	if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size,
312 	    NULL, BUS_DMA_NOWAIT) != 0)
313 		goto unmap;
314 
315 	bzero(mdm->mdm_kva, size);
316 	return (mdm);
317 
318 unmap:
319 	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size);
320 free:
321 	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
322 destroy:
323 	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
324 mdmfree:
325 	free(mdm, M_DEVBUF);
326 
327 	return (NULL);
328 }
329 
330 void
331 mpi_dmamem_free(struct mpi_softc *sc, struct mpi_dmamem *mdm)
332 {
333 	bus_dmamap_unload(sc->sc_dmat, mdm->mdm_map);
334 	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size);
335 	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
336 	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
337 	free(mdm, M_DEVBUF);
338 }
339 
340 int
341 mpi_alloc_ccbs(struct mpi_softc *sc)
342 {
343 	struct mpi_ccb			*ccb;
344 	u_int8_t			*cmd;
345 	int				i;
346 
347 	TAILQ_INIT(&sc->sc_ccb_free);
348 
349 	sc->sc_ccbs = malloc(sizeof(struct mpi_ccb) * sc->sc_maxcmds,
350 	    M_DEVBUF, M_WAITOK);
351 	if (sc->sc_ccbs == NULL) {
352 		printf("%s: unable to allocate ccbs\n", DEVNAME(sc));
353 		return (1);
354 	}
355 	bzero(sc->sc_ccbs, sizeof(struct mpi_ccb) * sc->sc_maxcmds);
356 
357 	sc->sc_requests = mpi_dmamem_alloc(sc,
358 	    MPI_REQUEST_SIZE * sc->sc_maxcmds);
359 	if (sc->sc_requests == NULL) {
360 		printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
361 		goto free_ccbs;
362 	}
363 	cmd = MPI_DMA_KVA(sc->sc_requests);
364 	bzero(cmd, MPI_REQUEST_SIZE * sc->sc_maxcmds);
365 
366 	for (i = 0; i < sc->sc_maxcmds; i++) {
367 		ccb = &sc->sc_ccbs[i];
368 
369 		if (bus_dmamap_create(sc->sc_dmat, MAXPHYS,
370 		    sc->sc_max_sgl_len, MAXPHYS, 0, 0,
371 		    &ccb->ccb_dmamap) != 0) {
372 			printf("%s: unable to create dma map\n", DEVNAME(sc));
373 			goto free_maps;
374 		}
375 
376 		ccb->ccb_sc = sc;
377 		ccb->ccb_id = i;
378 		ccb->ccb_offset = MPI_REQUEST_SIZE * i;
379 
380 		ccb->ccb_cmd = &cmd[ccb->ccb_offset];
381 		ccb->ccb_cmd_dva = (u_int32_t)MPI_DMA_DVA(sc->sc_requests) +
382 		    ccb->ccb_offset;
383 
384 		mpi_put_ccb(sc, ccb);
385 	}
386 
387 	return (0);
388 
389 free_maps:
390 	while ((ccb = mpi_get_ccb(sc)) != NULL)
391 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
392 
393 	mpi_dmamem_free(sc, sc->sc_requests);
394 free_ccbs:
395 	free(sc->sc_ccbs, M_DEVBUF);
396 
397 	return (1);
398 }
399 
400 struct mpi_ccb *
401 mpi_get_ccb(struct mpi_softc *sc)
402 {
403 	struct mpi_ccb			*ccb;
404 
405 	ccb = TAILQ_FIRST(&sc->sc_ccb_free);
406 	if (ccb == NULL)
407 		return (NULL);
408 
409 	TAILQ_REMOVE(&sc->sc_ccb_free, ccb, ccb_link);
410 
411 	ccb->ccb_state = MPI_CCB_READY;
412 
413 	return (ccb);
414 }
415 
416 void
417 mpi_put_ccb(struct mpi_softc *sc, struct mpi_ccb *ccb)
418 {
419 	ccb->ccb_state = MPI_CCB_FREE;
420 	ccb->ccb_xs = NULL;
421 	ccb->ccb_done = NULL;
422 	bzero(ccb->ccb_cmd, MPI_REQUEST_SIZE);
423 	TAILQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_link);
424 }
425 
426 int
427 mpi_alloc_replies(struct mpi_softc *sc)
428 {
429 	sc->sc_replies = mpi_dmamem_alloc(sc, PAGE_SIZE);
430 	if (sc->sc_replies == NULL)
431 		return (1);
432 
433 	return (0);
434 }
435 
436 void
437 mpi_push_replies(struct mpi_softc *sc)
438 {
439 	paddr_t				reply;
440 	int				i;
441 
442 	bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies),
443 	    0, PAGE_SIZE, BUS_DMASYNC_PREREAD);
444 
445 	for (i = 0; i < PAGE_SIZE / MPI_REPLY_SIZE; i++) {
446 		reply = (u_int32_t)MPI_DMA_DVA(sc->sc_replies) +
447 		    MPI_REPLY_SIZE * i;
448 		mpi_push_reply(sc, reply);
449 	}
450 }
451 
452 void
453 mpi_start(struct mpi_softc *sc, struct mpi_ccb *ccb)
454 {
455 	bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests),
456 	    ccb->ccb_offset, MPI_REQUEST_SIZE, BUS_DMASYNC_PREWRITE);
457 
458 	ccb->ccb_state = MPI_CCB_QUEUED;
459 	mpi_write(sc, MPI_REQ_QUEUE, ccb->ccb_cmd_dva);
460 }
461 
462 int
463 mpi_complete(struct mpi_softc *sc, struct mpi_ccb *nccb, int timeout)
464 {
465 	struct mpi_ccb			*ccb;
466 	struct mpi_msg_reply		*reply = NULL;
467 	u_int32_t			reply_dva;
468 	char				*reply_addr;
469 	u_int32_t			reg, id;
470 
471 	DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
472 
473 	do {
474 		reg = mpi_pop_reply(sc);
475 		if (reg == 0xffffffff) {
476 			if (timeout-- == 0)
477 				return (1);
478 
479 			delay(1000);
480 			continue;
481 		}
482 
483 		DPRINTF("%s: %s reply_queue: 0x%08x\n", DEVNAME(sc), __func__,
484 		    reg);
485 
486 		if (reg & MPI_REPLY_QUEUE_ADDRESS) {
487 			bus_dmamap_sync(sc->sc_dmat,
488 			    MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE,
489 			    BUS_DMASYNC_POSTREAD);
490 
491 			reply_dva = (reg & MPI_REPLY_QUEUE_ADDRESS_MASK) << 1;
492 
493 			reply_addr = MPI_DMA_KVA(sc->sc_replies);
494 			reply_addr += reply_dva -
495 			    (u_int32_t)MPI_DMA_DVA(sc->sc_replies);
496 			reply = (struct mpi_msg_reply *)reply_addr;
497 
498 			id = letoh32(reply->msg_context);
499 
500 			bus_dmamap_sync(sc->sc_dmat,
501 			    MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE,
502 			    BUS_DMASYNC_PREREAD);
503 		} else {
504 			switch (reg & MPI_REPLY_QUEUE_TYPE_MASK) {
505 			case MPI_REPLY_QUEUE_TYPE_INIT:
506 				id = reg & MPI_REPLY_QUEUE_CONTEXT;
507 				break;
508 
509 			default:
510 				panic("%s: unsupported context reply\n",
511 				    DEVNAME(sc));
512 			}
513 		}
514 
515 		DPRINTF("%s: %s id: %d\n", DEVNAME(sc), __func__, id);
516 
517 		ccb = &sc->sc_ccbs[id];
518 
519 		bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests),
520 		    ccb->ccb_offset, MPI_REQUEST_SIZE, BUS_DMASYNC_POSTWRITE);
521 		ccb->ccb_state = MPI_CCB_READY;
522 		ccb->ccb_reply = reply;
523 		ccb->ccb_reply_dva = reply_dva;
524 
525 		ccb->ccb_done(ccb);
526 
527 	} while (nccb->ccb_id != id);
528 
529 	return (0);
530 }
531 
532 int
533 mpi_poll(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout)
534 {
535 	int				error;
536 	int				s;
537 
538 	DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
539 
540 	s = splbio();
541 	mpi_start(sc, ccb);
542 	error = mpi_complete(sc, ccb, timeout);
543 	splx(s);
544 
545 	return (error);
546 }
547 
548 int
549 mpi_scsi_cmd(struct scsi_xfer *xs)
550 {
551 	struct scsi_link		*link = xs->sc_link;
552 	struct mpi_softc		*sc = link->adapter_softc;
553 	struct mpi_ccb			*ccb;
554 	struct mpi_ccb_bundle		*mcb;
555 	struct mpi_msg_scsi_io		*io;
556 	int				s;
557 
558 	DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
559 
560 	if (xs->cmdlen > MPI_CDB_LEN) {
561 		DPRINTF("%s: CBD too big %d", DEVNAME(sc), xs->cmdlen);
562 		bzero(&xs->sense, sizeof(xs->sense));
563 		xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
564 		xs->sense.flags = SKEY_ILLEGAL_REQUEST;
565 		xs->sense.add_sense_code = 0x20;
566 		xs->error = XS_SENSE;
567 		scsi_done(xs);
568 		return (COMPLETE);
569 	}
570 
571 	s = splbio();
572 	ccb = mpi_get_ccb(sc);
573 	splx(s);
574 	if (ccb == NULL) {
575 		xs->error = XS_DRIVER_STUFFUP;
576 		scsi_done(xs);
577 		return (COMPLETE);
578 	}
579 	DPRINTF("%s: ccb_id: %d xs->flags: 0x%x\n", DEVNAME(sc), ccb->ccb_id,
580 	    xs->flags);
581 
582 	ccb->ccb_xs = xs;
583 	ccb->ccb_done = mpi_scsi_cmd_done;
584 
585 	mcb = ccb->ccb_cmd;
586 	io = &mcb->mcb_io;
587 
588 	io->function = MPI_FUNCTION_SCSI_IO_REQUEST;
589 	/*
590 	 * bus is always 0
591 	 * io->bus = htole16(sc->sc_bus);
592 	 */
593 	io->target_id = link->target;
594 
595 	io->cdb_length = xs->cmdlen;
596 	io->sense_buf_len = sizeof(xs->sense);
597 	io->msg_flags = MPI_SCSIIO_SENSE_BUF_ADDR_WIDTH_64;
598 
599 	io->msg_context = htole32(ccb->ccb_id);
600 
601 	io->lun[0] = htobe16(link->lun);
602 
603 	switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
604 	case SCSI_DATA_IN:
605 		io->control = htole32(MPI_SCSIIO_DATA_DIR_READ);
606 		break;
607 	case SCSI_DATA_OUT:
608 		io->control = htole32(MPI_SCSIIO_DATA_DIR_WRITE);
609 		break;
610 	default:
611 		io->control = htole32(MPI_SCSIIO_DATA_DIR_NONE);
612 		break;
613 	}
614 
615 	bcopy(xs->cmd, io->cdb, xs->cmdlen);
616 
617 	io->data_length = htole32(xs->datalen);
618 
619 	io->sense_buf_low_addr = htole32(ccb->ccb_cmd_dva +
620 	    ((u_int8_t *)&mcb->mcb_sense - (u_int8_t *)mcb));
621 
622 	if (mpi_load_xs(ccb) != 0) {
623 		s = splbio();
624 		mpi_put_ccb(sc, ccb);
625 		splx(s);
626 		xs->error = XS_DRIVER_STUFFUP;
627 		scsi_done(xs);
628 		return (COMPLETE);
629 	}
630 
631 	timeout_set(&xs->stimeout, mpi_timeout_xs, ccb);
632 
633 	if (xs->flags & SCSI_POLL) {
634 		if (mpi_poll(sc, ccb, xs->timeout) != 0)
635 			xs->error = XS_DRIVER_STUFFUP;
636 		return (COMPLETE);
637 	}
638 
639 	mpi_start(sc, ccb);
640 	return (SUCCESSFULLY_QUEUED);
641 }
642 
643 void
644 mpi_scsi_cmd_done(struct mpi_ccb *ccb)
645 {
646 	struct mpi_softc		*sc = ccb->ccb_sc;
647 	struct scsi_xfer		*xs = ccb->ccb_xs;
648 	struct mpi_ccb_bundle		*mcb = ccb->ccb_cmd;
649 	bus_dmamap_t			dmap = ccb->ccb_dmamap;
650 	struct mpi_msg_scsi_io_error	*sie = ccb->ccb_reply;
651 
652 	if (xs->datalen != 0) {
653 		bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
654 		    (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
655 		    BUS_DMASYNC_POSTWRITE);
656 
657 		bus_dmamap_unload(sc->sc_dmat, dmap);
658 	}
659 
660 	/* timeout_del */
661 	xs->error = XS_NOERROR;
662 	xs->resid = 0;
663 	xs->flags |= ITSDONE;
664 	DPRINTFN(10, "%s:  xs cmd: 0x%02x len: %d error: 0x%02x flags 0x%x\n",
665 	    DEVNAME(sc), xs->cmd->opcode, xs->datalen, xs->error, xs->flags);
666 
667 	if (sie == NULL) {
668 		/* no scsi error, we're ok so drop out early */
669 		xs->status = SCSI_OK;
670 		mpi_put_ccb(sc, ccb);
671 		scsi_done(xs);
672 		return;
673 	}
674 
675 #ifdef MPI_DEBUG
676 	if (mpidebug > 10) {
677 		printf("%s:  target_id: %d bus: %d msg_length: %d "
678 		    "function: 0x%02x\n", DEVNAME(sc), sie->target_id,
679 		    sie->bus, sie->msg_length, sie->function);
680 
681 		printf("%s:  cdb_length: %d sense_buf_length: %d "
682 		    "msg_flags: 0x%02x\n", DEVNAME(sc), sie->cdb_length,
683 		    sie->bus, sie->msg_flags);
684 
685 		printf("%s:  msg_context: 0x%08x\n", DEVNAME(sc),
686 		    letoh32(sie->msg_context));
687 
688 		printf("%s:  scsi_status: 0x%02x scsi_state: 0x%02x "
689 		    "ioc_status: 0x%04x\n", DEVNAME(sc), sie->scsi_status,
690 		    sie->scsi_state, letoh16(sie->ioc_status));
691 
692 		printf("%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
693 		    letoh32(sie->ioc_loginfo));
694 
695 		printf("%s:  transfer_count: %d\n", DEVNAME(sc),
696 		    letoh32(sie->transfer_count));
697 
698 		printf("%s:  sense_count: %d\n", DEVNAME(sc),
699 		    letoh32(sie->sense_count));
700 
701 		printf("%s:  response_info: 0x%08x\n", DEVNAME(sc),
702 		    letoh32(sie->response_info));
703 
704 		printf("%s:  tag: 0x%04x\n", DEVNAME(sc), letoh16(sie->tag));
705 	}
706 #endif /* MPI_DEBUG */
707 
708 	xs->status = sie->scsi_status;
709 	switch (letoh16(sie->ioc_status)) {
710 	case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:
711 		xs->error = XS_DRIVER_STUFFUP;
712 		break;
713 
714         case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:
715                 /*
716                  * Yikes!  Tagged queue full comes through this path!
717                  *
718                  * So we'll change it to a status error and anything
719                  * that returns status should probably be a status
720                  * error as well.
721                  */
722 		xs->resid = xs->datalen - letoh32(sie->transfer_count);
723                 if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_NO_SCSI_STATUS) {
724 			xs->error = XS_DRIVER_STUFFUP;
725 			break;
726 		}
727                 /* FALLTHROUGH */
728 	case MPI_IOCSTATUS_SUCCESS:
729 	case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:
730 		switch (xs->status) {
731 		case SCSI_OK:
732 			xs->resid = 0;
733 			break;
734 
735 		case SCSI_CHECK:
736 			xs->error = XS_SENSE;
737 			break;
738 
739 		case SCSI_BUSY:
740 			xs->error = XS_BUSY;
741 			break;
742 
743 		case SCSI_QUEUE_FULL:
744 			xs->error = XS_TIMEOUT;
745 			xs->retries++;
746 			break;
747 		default:
748 			printf("%s: invalid status code %d\n", xs->status);
749 			xs->error = XS_DRIVER_STUFFUP;
750 			break;
751 		}
752 		break;
753 
754 	case MPI_IOCSTATUS_BUSY:
755 	case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:
756 		xs->error = XS_BUSY;
757 		break;
758 
759 	case MPI_IOCSTATUS_SCSI_INVALID_BUS:
760 	case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:
761         case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
762 		xs->error = XS_SELTIMEOUT;
763 		break;
764 
765 	case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
766 		xs->error = XS_DRIVER_STUFFUP;
767 		break;
768 
769 	case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:
770 		xs->error = XS_DRIVER_STUFFUP;
771 		break;
772 
773 	case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
774 		/* XXX */
775 		xs->error = XS_DRIVER_STUFFUP;
776 		break;
777 
778 	case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:
779 		/* XXX */
780 		xs->error = XS_DRIVER_STUFFUP;
781 		break;
782 
783 	case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:
784 		/* XXX This is a bus-reset */
785 		xs->error = XS_DRIVER_STUFFUP;
786 		break;
787 
788 	default:
789 		/* XXX unrecognized HBA error */
790 		xs->error = XS_DRIVER_STUFFUP;
791 		break;
792 	}
793 
794 	if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_AUTOSENSE_VALID) {
795 		bcopy(&mcb->mcb_sense, &xs->sense, sizeof(xs->sense));
796         } else if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_AUTOSENSE_FAILED) {
797                 /* This will cause the scsi layer to issue a REQUEST SENSE */
798                 if (xs->status == SCSI_CHECK)
799                         xs->error = XS_BUSY;
800         }
801 
802 	DPRINTFN(10, "%s:  xs error: 0x%02x len: %d\n", DEVNAME(sc),
803 	    xs->error, xs->status);
804 	mpi_push_reply(sc, ccb->ccb_reply_dva);
805 	mpi_put_ccb(sc, ccb);
806 	scsi_done(xs);
807 }
808 
809 void
810 mpi_timeout_xs(void *arg)
811 {
812 	/* XXX */
813 }
814 
815 int
816 mpi_load_xs(struct mpi_ccb *ccb)
817 {
818 	struct mpi_softc		*sc = ccb->ccb_sc;
819 	struct scsi_xfer		*xs = ccb->ccb_xs;
820 	struct mpi_ccb_bundle		*mcb = ccb->ccb_cmd;
821 	struct mpi_msg_scsi_io		*io = &mcb->mcb_io;
822 	struct mpi_sge			*sge, *nsge = &mcb->mcb_sgl[0];
823 	struct mpi_sge			*ce = NULL, *nce;
824 	u_int64_t			ce_dva;
825 	bus_dmamap_t			dmap = ccb->ccb_dmamap;
826 	u_int32_t			addr, flags;
827 	int				i, error;
828 
829 	if (xs->datalen == 0) {
830 		nsge->sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
831 		    MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL);
832 		return (0);
833 	}
834 
835 	error = bus_dmamap_load(sc->sc_dmat, dmap,
836 	    xs->data, xs->datalen, NULL,
837 	    (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
838 	if (error) {
839 		printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
840 		return (1);
841 	}
842 
843 	flags = MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_SIZE_64;
844 	if (xs->flags & SCSI_DATA_OUT)
845 		flags |= MPI_SGE_FL_DIR_OUT;
846 
847 	if (dmap->dm_nsegs > sc->sc_first_sgl_len) {
848 		ce = &mcb->mcb_sgl[sc->sc_first_sgl_len - 1];
849 		io->chain_offset = ((u_int8_t *)ce - (u_int8_t *)io) / 4;
850 	}
851 
852 	for (i = 0; i < dmap->dm_nsegs; i++) {
853 
854 		if (nsge == ce) {
855 			nsge++;
856 			sge->sg_hdr |= htole32(MPI_SGE_FL_LAST);
857 
858 			DPRINTFN(5, "%s:   - 0x%08x 0x%08x 0x%08x\n",
859 			    DEVNAME(sc), sge->sg_hdr,
860 			    sge->sg_hi_addr, sge->sg_lo_addr);
861 
862 			if ((dmap->dm_nsegs - i) > sc->sc_maxchdepth) {
863 				nce = &nsge[sc->sc_maxchdepth - 1];
864 				addr = ((u_int8_t *)nce - (u_int8_t *)ce) / 4;
865 				addr = addr << 16 |
866 				    sizeof(struct mpi_sge) * sc->sc_maxchdepth;
867 			} else {
868 				nce = NULL;
869 				addr = sizeof(struct mpi_sge) *
870 				    (dmap->dm_nsegs - i);
871 			}
872 
873 			ce->sg_hdr = htole32(MPI_SGE_FL_TYPE_CHAIN |
874 			    MPI_SGE_FL_SIZE_64 | addr);
875 
876 			ce_dva = MPI_DMA_DVA(sc->sc_requests) + ccb->ccb_offset;
877 			ce_dva += (u_int8_t *)nsge - (u_int8_t *)mcb;
878 
879 			addr = (u_int32_t)(ce_dva >> 32);
880 			ce->sg_hi_addr = htole32(addr);
881 			addr = (u_int32_t)ce_dva;
882 			ce->sg_lo_addr = htole32(addr);
883 
884 			DPRINTFN(5, "%s:  ce: 0x%08x 0x%08x 0x%08x\n",
885 			    DEVNAME(sc), ce->sg_hdr, ce->sg_hi_addr,
886 			    ce->sg_lo_addr);
887 
888 			ce = nce;
889 		}
890 
891 		DPRINTFN(5, "%s:  %d: %d 0x%016llx\n", DEVNAME(sc),
892 		    i, dmap->dm_segs[i].ds_len,
893 		    (unsigned long long)dmap->dm_segs[i].ds_addr);
894 
895 		sge = nsge;
896 
897 		sge->sg_hdr = htole32(flags | dmap->dm_segs[i].ds_len);
898 		addr = (u_int32_t)((unsigned long long)dmap->dm_segs[i].ds_addr >> 32);
899 		sge->sg_hi_addr = htole32(addr);
900 		addr = (u_int32_t)dmap->dm_segs[i].ds_addr;
901 		sge->sg_lo_addr = htole32(addr);
902 
903 		DPRINTFN(5, "%s:  %d: 0x%08x 0x%08x 0x%08x\n", DEVNAME(sc),
904 		    i, sge->sg_hdr, sge->sg_hi_addr, sge->sg_lo_addr);
905 
906 		nsge = sge + 1;
907 	}
908 
909 	/* terminate list */
910 	sge->sg_hdr |= htole32(MPI_SGE_FL_LAST | MPI_SGE_FL_EOB |
911 	    MPI_SGE_FL_EOL);
912 
913 	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
914 	    (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
915 	    BUS_DMASYNC_PREWRITE);
916 
917 	return (0);
918 }
919 
920 void
921 mpi_minphys(struct buf *bp)
922 {
923 	/* XXX */
924 	if (bp->b_bcount > MAXPHYS)
925 		bp->b_bcount = MAXPHYS;
926 	minphys(bp);
927 }
928 
929 int
930 mpi_scsi_ioctl(struct scsi_link *a, u_long b, caddr_t c, int d, struct proc *e)
931 {
932 	return (0);
933 }
934 
935 u_int32_t
936 mpi_read(struct mpi_softc *sc, bus_size_t r)
937 {
938         bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
939 	    BUS_SPACE_BARRIER_READ);
940         return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, r));
941 }
942 
943 void
944 mpi_write(struct mpi_softc *sc, bus_size_t r, u_int32_t v)
945 {
946         bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
947         bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
948             BUS_SPACE_BARRIER_WRITE);
949 }
950 
951 int
952 mpi_wait_eq(struct mpi_softc *sc, bus_size_t r, u_int32_t mask,
953     u_int32_t target)
954 {
955 	int				i;
956 
957 	for (i = 0; i < 10000; i++) {
958 		if ((mpi_read(sc, r) & mask) == target)
959 			return (0);
960 		delay(1000);
961 	}
962 
963 	return (1);
964 }
965 
966 int
967 mpi_wait_ne(struct mpi_softc *sc, bus_size_t r, u_int32_t mask,
968     u_int32_t target)
969 {
970 	int				i;
971 
972 	for (i = 0; i < 10000; i++) {
973 		if ((mpi_read(sc, r) & mask) != target)
974 			return (0);
975 		delay(1000);
976 	}
977 
978 	return (1);
979 }
980 
981 int
982 mpi_init(struct mpi_softc *sc)
983 {
984 	u_int32_t			db;
985 	int				i;
986 
987 	/* spin until the IOC leaves the RESET state */
988 	if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
989 	    MPI_DOORBELL_STATE_RESET) != 0) {
990 		DPRINTF("%s: %s timeout waiting to leave reset state\n",
991 		    DEVNAME(sc), __func__);
992 		return (1);
993 	}
994 
995 	/* check current ownership */
996 	db = mpi_read_db(sc);
997 	if ((db & MPI_DOORBELL_WHOINIT) == MPI_DOORBELL_WHOINIT_PCIPEER) {
998 		DPRINTF("%s: %s initialised by pci peer\n", DEVNAME(sc),
999 		    __func__);
1000 		return (0);
1001 	}
1002 
1003 	for (i = 0; i < 5; i++) {
1004 		switch (db & MPI_DOORBELL_STATE) {
1005 		case MPI_DOORBELL_STATE_READY:
1006 			DPRINTF("%s: %s ioc is ready\n", DEVNAME(sc),
1007 			    __func__);
1008 			return (0);
1009 
1010 		case MPI_DOORBELL_STATE_OPER:
1011 		case MPI_DOORBELL_STATE_FAULT:
1012 			DPRINTF("%s: %s ioc is being reset\n", DEVNAME(sc),
1013 			    __func__);
1014 			if (mpi_reset_soft(sc) != 0)
1015 				mpi_reset_hard(sc);
1016 			break;
1017 
1018 		case MPI_DOORBELL_STATE_RESET:
1019 			DPRINTF("%s: %s waiting to come out of reset\n",
1020 			    DEVNAME(sc), __func__);
1021 			if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
1022 			    MPI_DOORBELL_STATE_RESET) != 0)
1023 				return (1);
1024 			break;
1025 		}
1026 		db = mpi_read_db(sc);
1027 	}
1028 
1029 	return (1);
1030 }
1031 
1032 int
1033 mpi_reset_soft(struct mpi_softc *sc)
1034 {
1035 	DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
1036 
1037 	if (mpi_read_db(sc) & MPI_DOORBELL_INUSE)
1038 		return (1);
1039 
1040 	mpi_write_db(sc,
1041 	    MPI_DOORBELL_FUNCTION(MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET));
1042 	if (mpi_wait_eq(sc, MPI_INTR_STATUS,
1043 	    MPI_INTR_STATUS_IOCDOORBELL, 0) != 0)
1044 		return (1);
1045 
1046 	if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE,
1047 	    MPI_DOORBELL_STATE_READY) != 0)
1048 		return (1);
1049 
1050 	return (0);
1051 }
1052 
1053 int
1054 mpi_reset_hard(struct mpi_softc *sc)
1055 {
1056 	DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
1057 
1058 	/* enable diagnostic register */
1059 	mpi_write(sc, MPI_WRITESEQ, 0xff);
1060 	mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_1);
1061 	mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_2);
1062 	mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_3);
1063 	mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_4);
1064 	mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_5);
1065 
1066 	/* reset ioc */
1067 	mpi_write(sc, MPI_HOSTDIAG, MPI_HOSTDIAG_RESET_ADAPTER);
1068 
1069 	delay(10000);
1070 
1071 	/* disable diagnostic register */
1072 	mpi_write(sc, MPI_WRITESEQ, 0xff);
1073 
1074 	/* restore pci bits? */
1075 
1076 	/* firmware bits? */
1077 	return (0);
1078 }
1079 
1080 int
1081 mpi_handshake_send(struct mpi_softc *sc, void *buf, size_t dwords)
1082 {
1083 	u_int32_t				*query = buf;
1084 	int					i;
1085 
1086 	/* make sure the doorbell is not in use. */
1087 	if (mpi_read_db(sc) & MPI_DOORBELL_INUSE)
1088 		return (1);
1089 
1090 	/* clear pending doorbell interrupts */
1091 	if (mpi_read_intr(sc) & MPI_INTR_STATUS_DOORBELL)
1092 		mpi_write_intr(sc, 0);
1093 
1094 	/*
1095 	 * first write the doorbell with the handshake function and the
1096 	 * dword count.
1097 	 */
1098 	mpi_write_db(sc, MPI_DOORBELL_FUNCTION(MPI_FUNCTION_HANDSHAKE) |
1099 	    MPI_DOORBELL_DWORDS(dwords));
1100 
1101 	/*
1102 	 * the doorbell used bit will be set because a doorbell function has
1103 	 * started. Wait for the interrupt and then ack it.
1104 	 */
1105 	if (mpi_wait_db_int(sc) != 0)
1106 		return (1);
1107 	mpi_write_intr(sc, 0);
1108 
1109 	/* poll for the acknowledgement. */
1110 	if (mpi_wait_db_ack(sc) != 0)
1111 		return (1);
1112 
1113 	/* write the query through the doorbell. */
1114 	for (i = 0; i < dwords; i++) {
1115 		mpi_write_db(sc, htole32(query[i]));
1116 		if (mpi_wait_db_ack(sc) != 0)
1117 			return (1);
1118 	}
1119 
1120 	return (0);
1121 }
1122 
1123 int
1124 mpi_handshake_recv_dword(struct mpi_softc *sc, u_int32_t *dword)
1125 {
1126 	u_int16_t				*words = (u_int16_t *)dword;
1127 	int					i;
1128 
1129 	for (i = 0; i < 2; i++) {
1130 		if (mpi_wait_db_int(sc) != 0)
1131 			return (1);
1132 		words[i] = letoh16(mpi_read_db(sc) & MPI_DOORBELL_DATA_MASK);
1133 		mpi_write_intr(sc, 0);
1134 	}
1135 
1136 	return (0);
1137 }
1138 
1139 int
1140 mpi_handshake_recv(struct mpi_softc *sc, void *buf, size_t dwords)
1141 {
1142 	struct mpi_msg_reply			*reply = buf;
1143 	u_int32_t				*dbuf = buf, dummy;
1144 	int					i;
1145 
1146 	/* get the first dword so we can read the length out of the header. */
1147 	if (mpi_handshake_recv_dword(sc, &dbuf[0]) != 0)
1148 		return (1);
1149 
1150 	DPRINTFN(10, "%s: %s dwords: %d reply: %d\n", DEVNAME(sc), __func__,
1151 	    dwords, reply->msg_length);
1152 
1153 	/*
1154 	 * the total length, in dwords, is in the message length field of the
1155 	 * reply header.
1156 	 */
1157 	for (i = 1; i < MIN(dwords, reply->msg_length); i++) {
1158 		if (mpi_handshake_recv_dword(sc, &dbuf[i]) != 0)
1159 			return (1);
1160 	}
1161 
1162 	/* if there's extra stuff to come off the ioc, discard it */
1163 	while (i++ < reply->msg_length) {
1164 		if (mpi_handshake_recv_dword(sc, &dummy) != 0)
1165 			return (1);
1166 		DPRINTFN(10, "%s: %s dummy read: 0x%08x\n", DEVNAME(sc),
1167 		    __func__, dummy);
1168 	}
1169 
1170 	/* wait for the doorbell used bit to be reset and clear the intr */
1171 	if (mpi_wait_db_int(sc) != 0)
1172 		return (1);
1173 	mpi_write_intr(sc, 0);
1174 
1175 	return (0);
1176 }
1177 
1178 void
1179 mpi_empty_done(struct mpi_ccb *ccb)
1180 {
1181 	/* nothing to do */
1182 }
1183 
1184 int
1185 mpi_iocfacts(struct mpi_softc *sc)
1186 {
1187 	struct mpi_msg_iocfacts_request		ifq;
1188 	struct mpi_msg_iocfacts_reply		ifp;
1189 
1190 	DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
1191 
1192 	bzero(&ifq, sizeof(ifq));
1193 	bzero(&ifp, sizeof(ifp));
1194 
1195 	ifq.function = MPI_FUNCTION_IOC_FACTS;
1196 	ifq.chain_offset = 0;
1197 	ifq.msg_flags = 0;
1198 	ifq.msg_context = htole32(0xdeadbeef);
1199 
1200 	if (mpi_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) {
1201 		DPRINTF("%s: %s send failed\n", DEVNAME(sc), __func__);
1202 		return (1);
1203 	}
1204 
1205 	if (mpi_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) {
1206 		DPRINTF("%s: %s recv failed\n", DEVNAME(sc), __func__);
1207 		return (1);
1208 	}
1209 
1210 #ifdef MPI_DEBUG
1211 	if (mpidebug) {
1212 		printf("%s:  func: 0x%02x len: %d msgver: %d.%d\n",
1213 		    DEVNAME(sc), ifp.function, ifp.msg_length,
1214 		    ifp.msg_version_maj, ifp.msg_version_min);
1215 
1216 		printf("%s:  msgflags: 0x%02x iocnumber: 0x%02x "
1217 		    "hdrver: %d.%d\n", DEVNAME(sc), ifp.msg_flags,
1218 		    ifp.ioc_number, ifp.header_version_maj,
1219 		    ifp.header_version_min);
1220 
1221 		printf("%s:  message context: 0x%08x\n", DEVNAME(sc),
1222 		    letoh32(ifp.msg_context));
1223 
1224 		printf("%s:  iocstatus: 0x%04x ioexcept: 0x%04x\n",
1225 		    DEVNAME(sc), letoh16(ifp.ioc_status),
1226 		    letoh16(ifp.ioc_exceptions));
1227 
1228 		printf("%s:  iocloginfo: 0x%08x\n", DEVNAME(sc),
1229 		    letoh32(ifp.ioc_loginfo));
1230 
1231 		printf("%s:  flags: 0x%02x blocksize: %d whoinit: 0x%02x "
1232 		    "maxchdepth: %d\n", DEVNAME(sc), ifp.flags,
1233 		    ifp.block_size, ifp.whoinit, ifp.max_chain_depth);
1234 
1235 		printf("%s:  reqfrsize: %d replyqdepth: %d\n", DEVNAME(sc),
1236 		    letoh16(ifp.request_frame_size),
1237 		    letoh16(ifp.reply_queue_depth));
1238 
1239 		printf("%s:  productid: 0x%04x\n", DEVNAME(sc),
1240 		    letoh16(ifp.product_id));
1241 
1242 		printf("%s:  hostmfahiaddr: 0x%08x\n", DEVNAME(sc),
1243 		    letoh32(ifp.current_host_mfa_hi_addr));
1244 
1245 		printf("%s:  event_state: 0x%02x number_of_ports: %d "
1246 		    "global_credits: %d\n",
1247 		    DEVNAME(sc), ifp.event_state, ifp.number_of_ports,
1248 		    letoh16(ifp.global_credits));
1249 
1250 		printf("%s:  sensebufhiaddr: 0x%08x\n", DEVNAME(sc),
1251 		    letoh32(ifp.current_sense_buffer_hi_addr));
1252 
1253 		printf("%s:  maxbus: %d maxdev: %d replyfrsize: %d\n",
1254 		    DEVNAME(sc), ifp.max_buses, ifp.max_devices,
1255 		    letoh16(ifp.current_reply_frame_size));
1256 
1257 		printf("%s:  fw_image_size: %d\n", DEVNAME(sc),
1258 		    letoh32(ifp.fw_image_size));
1259 
1260 		printf("%s:  ioc_capabilities: 0x%08x\n", DEVNAME(sc),
1261 		    letoh32(ifp.ioc_capabilities));
1262 
1263 		printf("%s:  fw_version: %d.%d fw_version_unit: 0x%02x "
1264 		    "fw_version_dev: 0x%02x\n", DEVNAME(sc),
1265 		    ifp.fw_version_maj, ifp.fw_version_min,
1266 		    ifp.fw_version_unit, ifp.fw_version_dev);
1267 
1268 		printf("%s:  hi_priority_queue_depth: 0x%04x\n", DEVNAME(sc),
1269 		    letoh16(ifp.hi_priority_queue_depth));
1270 
1271 		printf("%s:  host_page_buffer_sge: hdr: 0x%08x "
1272 		    "addr 0x%08x %08x\n", DEVNAME(sc),
1273 		    letoh32(ifp.host_page_buffer_sge.sg_hdr),
1274 		    letoh32(ifp.host_page_buffer_sge.sg_hi_addr),
1275 		    letoh32(ifp.host_page_buffer_sge.sg_lo_addr));
1276 	}
1277 #endif /* MPI_DEBUG */
1278 
1279 	sc->sc_maxcmds = letoh16(ifp.global_credits);
1280 	sc->sc_buswidth = (ifp.max_devices == 0) ? 256 : ifp.max_devices;
1281 	sc->sc_maxchdepth = ifp.max_chain_depth;
1282 
1283 	/*
1284 	 * you can fit sg elements on the end of the io cmd if they fit in the
1285 	 * request frame size.
1286 	 */
1287 	sc->sc_first_sgl_len = ((letoh16(ifp.request_frame_size) * 4) -
1288 	    sizeof(struct mpi_msg_scsi_io)) / sizeof(struct mpi_sge);
1289 	DPRINTF("%s:   first sgl len: %d\n", DEVNAME(sc),
1290 	    sc->sc_first_sgl_len);
1291 
1292 	/* the sgl tailing the io cmd loses an entry to the chain element. */
1293 	sc->sc_max_sgl_len = MPI_MAX_SGL - 1;
1294 	/* the sgl chains lose an entry for each chain element */
1295 	sc->sc_max_sgl_len -= (MPI_MAX_SGL - sc->sc_first_sgl_len) /
1296 	    sc->sc_maxchdepth;
1297 	DPRINTF("%s:   max sgl len: %d\n", DEVNAME(sc), sc->sc_max_sgl_len);
1298 
1299 	return (0);
1300 }
1301 
1302 int
1303 mpi_iocinit(struct mpi_softc *sc)
1304 {
1305 	struct mpi_msg_iocinit_request		iiq;
1306 	struct mpi_msg_iocinit_reply		iip;
1307 	u_int32_t				hi_addr;
1308 
1309 	DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
1310 
1311 	bzero(&iiq, sizeof(iiq));
1312 	bzero(&iip, sizeof(iip));
1313 
1314 	iiq.function = MPI_FUNCTION_IOC_INIT;
1315 	iiq.whoinit = MPI_WHOINIT_HOST_DRIVER;
1316 
1317 	iiq.max_devices = (sc->sc_buswidth == 256) ? 0 : sc->sc_buswidth;
1318 	iiq.max_buses = 1;
1319 
1320 	iiq.msg_context = htole32(0xd00fd00f);
1321 
1322 	iiq.reply_frame_size = htole16(MPI_REPLY_SIZE);
1323 
1324 	hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_requests) >> 32);
1325 	iiq.host_mfa_hi_addr = htole32(hi_addr);
1326 	iiq.sense_buffer_hi_addr = htole32(hi_addr);
1327 
1328 	hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_replies) >> 32);
1329 	iiq.reply_fifo_host_signalling_addr = htole32(hi_addr);
1330 
1331 	iiq.msg_version_maj = 0x01;
1332 	iiq.msg_version_min = 0x02;
1333 
1334 	iiq.hdr_version_unit = 0x0d;
1335 	iiq.hdr_version_dev = 0x00;
1336 
1337 	if (mpi_handshake_send(sc, &iiq, dwordsof(iiq)) != 0) {
1338 		DPRINTF("%s: %s send failed\n", DEVNAME(sc), __func__);
1339 		return (1);
1340 	}
1341 
1342 	if (mpi_handshake_recv(sc, &iip, dwordsof(iip)) != 0) {
1343 		DPRINTF("%s: %s recv failed\n", DEVNAME(sc), __func__);
1344 		return (1);
1345 	}
1346 
1347 #ifdef MPI_DEBUG
1348 	if (mpidebug) {
1349 		printf("%s:  function: 0x%02x msg_length: %d "
1350 		    "whoinit: 0x%02x\n", DEVNAME(sc), iip.function,
1351 		    iip.msg_length, iip.whoinit);
1352 
1353 		printf("%s:  msg_flags: 0x%02x max_buses: %d max_devices: %d "
1354 		    "flags: 0x%02x\n", DEVNAME(sc), iip.msg_flags,
1355 		    iip.max_buses, iip.max_devices, iip.flags);
1356 
1357 		printf("%s:  msg_context: 0x%08x\n", DEVNAME(sc),
1358 		    letoh32(iip.msg_context));
1359 
1360 		printf("%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
1361 		    letoh16(iip.ioc_status));
1362 
1363 		printf("%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1364 		    letoh32(iip.ioc_loginfo));
1365 	}
1366 #endif /* MPI_DEBUG */
1367 
1368 	return (0);
1369 }
1370 
1371 int
1372 mpi_portfacts(struct mpi_softc *sc)
1373 {
1374 	struct mpi_ccb				*ccb;
1375 	struct mpi_msg_portfacts_request	*pfq;
1376 	struct mpi_msg_portfacts_reply		*pfp;
1377 	int					s;
1378 
1379 	DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
1380 
1381 	s = splbio();
1382 	ccb = mpi_get_ccb(sc);
1383 	splx(s);
1384 	if (ccb == NULL) {
1385 		DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__);
1386 		return (1);
1387 	}
1388 
1389 	ccb->ccb_done = mpi_empty_done;
1390 	pfq = ccb->ccb_cmd;
1391 
1392 	pfq->function = MPI_FUNCTION_PORT_FACTS;
1393 	pfq->chain_offset = 0;
1394 	pfq->msg_flags = 0;
1395 	pfq->port_number = 0;
1396 	pfq->msg_context = htole32(ccb->ccb_id);
1397 
1398 	if (mpi_poll(sc, ccb, 50000) != 0) {
1399 		DPRINTF("%s: %s poll\n", DEVNAME(sc), __func__);
1400 		return (1);
1401 	}
1402 
1403 	pfp = ccb->ccb_reply;
1404 	if (pfp == NULL) {
1405 		DPRINTF("%s: empty portfacts reply\n", DEVNAME(sc));
1406 		return (1);
1407 	}
1408 
1409 #ifdef MPI_DEBUG
1410 	if (mpidebug) {
1411 		printf("%s:  function: 0x%02x msg_length: %d\n", DEVNAME(sc),
1412 		    pfp->function, pfp->msg_length);
1413 
1414 		printf("%s:  msg_flags: 0x%02x port_number: %d\n", DEVNAME(sc),
1415 		    pfp->msg_flags, pfp->port_number);
1416 
1417 		printf("%s:  msg_context: 0x%08x\n", DEVNAME(sc),
1418 		    letoh32(pfp->msg_context));
1419 
1420 		printf("%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
1421 		    letoh16(pfp->ioc_status));
1422 
1423 		printf("%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1424 		    letoh32(pfp->ioc_loginfo));
1425 
1426 		printf("%s:  max_devices: %d port_type: 0x%02x\n", DEVNAME(sc),
1427 		    letoh16(pfp->max_devices), pfp->port_type);
1428 
1429 		printf("%s:  protocol_flags: 0x%04x port_scsi_id: %d\n",
1430 		    DEVNAME(sc), letoh16(pfp->protocol_flags),
1431 		    letoh16(pfp->port_scsi_id));
1432 
1433 		printf("%s:  max_persistent_ids: %d "
1434 		    "max_posted_cmd_buffers: %d\n", DEVNAME(sc),
1435 	 	    letoh16(pfp->max_persistent_ids),
1436 		    letoh16(pfp->max_posted_cmd_buffers));
1437 
1438 		printf("%s:  max_lan_buckets: %d\n", DEVNAME(sc),
1439 		    letoh16(pfp->max_lan_buckets));
1440 	}
1441 #endif /* MPI_DEBUG */
1442 
1443 	sc->sc_porttype = pfp->port_type;
1444 	sc->sc_target = letoh16(pfp->port_scsi_id);
1445 
1446 	mpi_push_reply(sc, ccb->ccb_reply_dva);
1447 	mpi_put_ccb(sc, ccb);
1448 
1449 	return (0);
1450 }
1451 
1452 int
1453 mpi_eventnotify(struct mpi_softc *sc)
1454 {
1455 	struct mpi_ccb				*ccb;
1456 	struct mpi_msg_event_request		*enq;
1457 	int					s;
1458 
1459 	s = splbio();
1460 	ccb = mpi_get_ccb(sc);
1461 	splx(s);
1462 	if (ccb == NULL) {
1463 		DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__);
1464 		return (1);
1465 	}
1466 
1467 	ccb->ccb_done = mpi_eventnotify_done;
1468 	enq = ccb->ccb_cmd;
1469 
1470 	enq->function = MPI_FUNCTION_EVENT_NOTIFICATION;
1471 	enq->chain_offset = 0;
1472 	enq->ev_switch = 1;
1473 	enq->msg_context = htole32(ccb->ccb_id);
1474 
1475 	mpi_start(sc, ccb);
1476 
1477 	return (0);
1478 }
1479 
1480 void
1481 mpi_eventnotify_done(struct mpi_ccb *ccb)
1482 {
1483 	struct mpi_softc			*sc = ccb->ccb_sc;
1484 	struct mpi_msg_event_reply		*enp = ccb->ccb_reply;
1485 	u_int32_t				*data;
1486 	int					i;
1487 
1488 	printf("%s: %s\n", DEVNAME(sc), __func__);
1489 
1490 	printf("%s:  function: 0x%02x msg_length: %d data_length: %d\n",
1491 	    DEVNAME(sc), enp->function, enp->msg_length,
1492 	    letoh16(enp->data_length));
1493 
1494 	printf("%s:  ack_required: %d msg_flags 0x%02x\n", DEVNAME(sc),
1495 	    enp->msg_flags, enp->msg_flags);
1496 
1497 	printf("%s:  msg_context: 0x%08x\n", DEVNAME(sc),
1498 	    letoh32(enp->msg_context));
1499 
1500 	printf("%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
1501 	    letoh16(enp->ioc_status));
1502 
1503 	printf("%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1504 	    letoh32(enp->ioc_loginfo));
1505 
1506 	data = ccb->ccb_reply;
1507 	data += dwordsof(struct mpi_msg_event_reply);
1508 	for (i = 0; i < letoh16(enp->data_length); i++) {
1509 		printf("%s:  data[%d]: 0x%08x\n", DEVNAME(sc), i, data[i]);
1510 	}
1511 }
1512 
1513 int
1514 mpi_portenable(struct mpi_softc *sc)
1515 {
1516 	struct mpi_ccb				*ccb;
1517 	struct mpi_msg_portenable_request	*peq;
1518 	struct mpi_msg_portenable_repy		*pep;
1519 	int					s;
1520 
1521 	DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
1522 
1523 	s = splbio();
1524 	ccb = mpi_get_ccb(sc);
1525 	splx(s);
1526 	if (ccb == NULL) {
1527 		DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__);
1528 		return (1);
1529 	}
1530 
1531 	ccb->ccb_done = mpi_empty_done;
1532 	peq = ccb->ccb_cmd;
1533 
1534 	peq->function = MPI_FUNCTION_PORT_ENABLE;
1535 	peq->port_number = 0;
1536 	peq->msg_context = htole32(ccb->ccb_id);
1537 
1538 	if (mpi_poll(sc, ccb, 50000) != 0) {
1539 		DPRINTF("%s: %s poll\n", DEVNAME(sc), __func__);
1540 		return (1);
1541 	}
1542 
1543 	pep = ccb->ccb_reply;
1544 	if (pep == NULL) {
1545 		DPRINTF("%s: empty portenable reply\n", DEVNAME(sc));
1546 		return (1);
1547 	}
1548 
1549 	mpi_push_reply(sc, ccb->ccb_reply_dva);
1550 	mpi_put_ccb(sc, ccb);
1551 
1552 	return (0);
1553 }
1554 
1555 int
1556 mpi_cfg_hdr(struct mpi_softc *sc, u_int8_t type, u_int8_t number,
1557     u_int32_t address, struct mpi_cfg_hdr *hdr)
1558 {
1559 	struct mpi_ccb				*ccb;
1560 	struct mpi_msg_config_request           *cq;
1561 	struct mpi_msg_config_reply             *cp;
1562 	int					s;
1563 
1564 	DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
1565 
1566 	s = splbio();
1567 	ccb = mpi_get_ccb(sc);
1568 	splx(s);
1569 	if (ccb == NULL) {
1570 		DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__);
1571 		return (1);
1572 	}
1573 
1574 	ccb->ccb_done = mpi_empty_done;
1575 	cq = ccb->ccb_cmd;
1576 
1577 	cq->function = MPI_FUNCTION_CONFIG;
1578 	cq->msg_context = htole32(ccb->ccb_id);
1579 
1580 	cq->action = MPI_CONFIG_REQ_ACTION_PAGE_HEADER;
1581 
1582 	cq->config_header.page_number = number;
1583 	cq->config_header.page_type = type;
1584 	cq->page_address = htole32(address);
1585 	cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
1586 	    MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL);
1587 
1588 	if (mpi_poll(sc, ccb, 50000) != 0) {
1589 		DPRINTF("%s: %s poll\n", DEVNAME(sc), __func__);
1590 		return (1);
1591 	}
1592 
1593 	cp = ccb->ccb_reply;
1594 	if (cp == NULL)
1595 		panic("%s: unable to fetch config header\n", DEVNAME(sc));
1596 
1597 #ifdef MPI_DEBUG
1598 	if (mpidebug) {
1599 		printf("%s:  action: 0x%02x msg_length: %d function: 0x%02x\n",
1600 		    DEVNAME(sc), cp->action, cp->msg_length, cp->function);
1601 
1602 		printf("%s:  ext_page_length: %d ext_page_type: 0x%02x "
1603 		    "msg_flags: 0x%02x\n", DEVNAME(sc),
1604 		    letoh16(cp->ext_page_length), cp->ext_page_type,
1605 		    cp->msg_flags);
1606 
1607 		printf("%s:  msg_context: 0x%08x\n", DEVNAME(sc),
1608 		    letoh32(cp->msg_context));
1609 
1610 		printf("%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
1611 		    letoh16(cp->ioc_status));
1612 
1613 		printf("%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1614 		    letoh32(cp->ioc_loginfo));
1615 
1616 		printf("%s:  page_version: 0x%02x page_length: %d "
1617 		    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
1618 		    cp->config_header.page_version,
1619 		    cp->config_header.page_length,
1620 		    cp->config_header.page_number,
1621 		    cp->config_header.page_type);
1622 	}
1623 #endif /* MPI_DEBUG */
1624 
1625 	*hdr = cp->config_header;
1626 
1627 	mpi_push_reply(sc, ccb->ccb_reply_dva);
1628 	mpi_put_ccb(sc, ccb);
1629 
1630 	return (0);
1631 }
1632 
1633 int
1634 mpi_cfg_page(struct mpi_softc *sc, u_int32_t address, struct mpi_cfg_hdr *hdr,
1635     int read, void *page, size_t len)
1636 {
1637 	struct mpi_ccb				*ccb;
1638 	struct mpi_msg_config_request		*cq;
1639 	struct mpi_msg_config_reply		*cp;
1640 	u_int64_t				dva;
1641 	char					*kva;
1642 	int					s;
1643 
1644 	DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
1645 
1646 	if (len > MPI_REQUEST_SIZE - sizeof(struct mpi_msg_config_request) ||
1647 	    len < hdr->page_length * 4)
1648 		return (1);
1649 
1650 	s = splbio();
1651 	ccb = mpi_get_ccb(sc);
1652 	splx(s);
1653 	if (ccb == NULL) {
1654 		DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__);
1655 		return (1);
1656 	}
1657 
1658 	ccb->ccb_done = mpi_empty_done;
1659 	cq = ccb->ccb_cmd;
1660 
1661 	cq->function = MPI_FUNCTION_CONFIG;
1662 	cq->msg_context = htole32(ccb->ccb_id);
1663 
1664 	cq->action = (read ? MPI_CONFIG_REQ_ACTION_PAGE_READ_CURRENT :
1665 	    MPI_CONFIG_REQ_ACTION_PAGE_READ_CURRENT);
1666 
1667 	cq->config_header = *hdr;
1668 	cq->config_header.page_type &= MPI_CONFIG_REQ_PAGE_TYPE_MASK;
1669 	cq->page_address = htole32(address);
1670 	cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
1671 	    MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL | len);
1672 
1673 	/* bounce the page via the request space to avoid more bus_dma games */
1674 	dva = MPI_DMA_DVA(sc->sc_requests) + ccb->ccb_offset +
1675 	    sizeof(struct mpi_msg_config_request);
1676 	cq->page_buffer.sg_hi_addr = htole32((u_int32_t)(dva >> 32));
1677 	cq->page_buffer.sg_lo_addr = htole32((u_int32_t)dva);
1678 
1679 	kva = MPI_DMA_KVA(sc->sc_requests);
1680 	kva += ccb->ccb_offset + sizeof(struct mpi_msg_config_request);
1681 	if (!read)
1682 		bcopy(page, kva, len);
1683 
1684 	if (mpi_poll(sc, ccb, 50000) != 0) {
1685 		DPRINTF("%s: %s poll\n", DEVNAME(sc), __func__);
1686 		return (1);
1687 	}
1688 
1689 	cp = ccb->ccb_reply;
1690 	if (cp == NULL) {
1691 		mpi_put_ccb(sc, ccb);
1692 		return (1);
1693 	}
1694 
1695 #ifdef MPI_DEBUG
1696 	if (mpidebug) {
1697 		printf("%s:  action: 0x%02x msg_length: %d function: 0x%02x\n",
1698 		    DEVNAME(sc), cp->action, cp->msg_length, cp->function);
1699 
1700 		printf("%s:  ext_page_length: %d ext_page_type: 0x%02x "
1701 		    "msg_flags: 0x%02x\n", DEVNAME(sc),
1702 		    letoh16(cp->ext_page_length), cp->ext_page_type,
1703 		    cp->msg_flags);
1704 
1705 		printf("%s:  msg_context: 0x%08x\n", DEVNAME(sc),
1706 		    letoh32(cp->msg_context));
1707 
1708 		printf("%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
1709 		    letoh16(cp->ioc_status));
1710 
1711 		printf("%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
1712 		    letoh32(cp->ioc_loginfo));
1713 
1714 		printf("%s:  page_version: 0x%02x page_length: %d "
1715 		    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
1716 		    cp->config_header.page_version,
1717 		    cp->config_header.page_length,
1718 		    cp->config_header.page_number,
1719 		    cp->config_header.page_type);
1720 	}
1721 #endif /* MPI_DEBUG */
1722 
1723 	if (read)
1724 		bcopy(kva, page, len);
1725 
1726 	mpi_push_reply(sc, ccb->ccb_reply_dva);
1727 	mpi_put_ccb(sc, ccb);
1728 
1729 	return (0);
1730 }
1731