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