xref: /freebsd/sys/dev/mpr/mpr_config.c (revision f126890ac5386406dadf7c4cfa9566cbb56537c5)
1 /*-
2  * Copyright (c) 2011-2015 LSI Corp.
3  * Copyright (c) 2013-2016 Avago Technologies
4  * Copyright 2000-2020 Broadcom Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD
29  */
30 
31 #include <sys/cdefs.h>
32 /* TODO Move headers to mprvar */
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/lock.h>
36 #include <sys/mutex.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
40 #include <sys/kthread.h>
41 #include <sys/taskqueue.h>
42 #include <sys/bus.h>
43 #include <sys/endian.h>
44 #include <sys/sysctl.h>
45 #include <sys/eventhandler.h>
46 #include <sys/uio.h>
47 #include <machine/bus.h>
48 #include <machine/resource.h>
49 #include <dev/mpr/mpi/mpi2_type.h>
50 #include <dev/mpr/mpi/mpi2.h>
51 #include <dev/mpr/mpi/mpi2_ioc.h>
52 #include <dev/mpr/mpi/mpi2_sas.h>
53 #include <dev/mpr/mpi/mpi2_pci.h>
54 #include <dev/mpr/mpi/mpi2_cnfg.h>
55 #include <dev/mpr/mpi/mpi2_init.h>
56 #include <dev/mpr/mpi/mpi2_tool.h>
57 #include <dev/mpr/mpr_ioctl.h>
58 #include <dev/mpr/mprvar.h>
59 
60 /**
61  * mpr_config_get_ioc_pg8 - obtain ioc page 8
62  * @sc: per adapter object
63  * @mpi_reply: reply mf payload returned from firmware
64  * @config_page: contents of the config page
65  * Context: sleep.
66  *
67  * Returns 0 for success, non-zero for failure.
68  */
69 int
70 mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
71     Mpi2IOCPage8_t *config_page)
72 {
73 	MPI2_CONFIG_REQUEST *request;
74 	MPI2_CONFIG_REPLY *reply;
75 	struct mpr_command *cm;
76 	MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
77 	int error = 0;
78 	u16 ioc_status;
79 
80 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
81 
82 	if ((cm = mpr_alloc_command(sc)) == NULL) {
83 		printf("%s: command alloc failed @ line %d\n", __func__,
84 		    __LINE__);
85 		error = EBUSY;
86 		goto out;
87 	}
88 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
89 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
90 	request->Function = MPI2_FUNCTION_CONFIG;
91 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
92 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
93 	request->Header.PageNumber = 8;
94 	request->Header.PageLength = request->Header.PageVersion = 0;
95 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
96 	cm->cm_data = NULL;
97 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
98 	if (cm != NULL)
99 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
100 	if (error || (reply == NULL)) {
101 		/* FIXME */
102 		/*
103 		 * If the request returns an error then we need to do a diag
104 		 * reset
105 		 */
106 		printf("%s: request for header completed with error %d\n",
107 		    __func__, error);
108 		error = ENXIO;
109 		goto out;
110 	}
111 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
112 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
113 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
114 		/* FIXME */
115 		/*
116 		 * If the request returns an error then we need to do a diag
117 		 * reset
118 		 */
119 		printf("%s: header read with error; iocstatus = 0x%x\n",
120 		    __func__, ioc_status);
121 		error = ENXIO;
122 		goto out;
123 	}
124 	/* We have to do free and alloc for the reply-free and reply-post
125 	 * counters to match - Need to review the reply FIFO handling.
126 	 */
127 	mpr_free_command(sc, cm);
128 
129 	if ((cm = mpr_alloc_command(sc)) == NULL) {
130 		printf("%s: command alloc failed @ line %d\n", __func__,
131 		    __LINE__);
132 		error = EBUSY;
133 		goto out;
134 	}
135 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
136 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
137 	request->Function = MPI2_FUNCTION_CONFIG;
138 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
139 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
140 	request->Header.PageNumber = 8;
141 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
142 	request->Header.PageLength = mpi_reply->Header.PageLength;
143 	cm->cm_length = mpi_reply->Header.PageLength * 4;
144 	cm->cm_sge = &request->PageBufferSGE;
145 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
146 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
147 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
148 	page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
149 	if (!page) {
150 		printf("%s: page alloc failed\n", __func__);
151 		error = ENOMEM;
152 		goto out;
153 	}
154 	cm->cm_data = page;
155 
156 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
157 	if (cm != NULL)
158 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
159 	if (error || (reply == NULL)) {
160 		/* FIXME */
161 		/*
162 		 * If the request returns an error then we need to do a diag
163 		 * reset
164 		 */
165 		printf("%s: request for page completed with error %d\n",
166 		    __func__, error);
167 		error = ENXIO;
168 		goto out;
169 	}
170 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
171 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
172 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
173 		/* FIXME */
174 		/*
175 		 * If the request returns an error then we need to do a diag
176 		 * reset
177 		 */
178 		printf("%s: page read with error; iocstatus = 0x%x\n",
179 		    __func__, ioc_status);
180 		error = ENXIO;
181 		goto out;
182 	}
183 	bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
184 
185 out:
186 	free(page, M_MPR);
187 	if (cm)
188 		mpr_free_command(sc, cm);
189 	return (error);
190 }
191 
192 /**
193  * mpr_config_get_iounit_pg8 - obtain iounit page 8
194  * @sc: per adapter object
195  * @mpi_reply: reply mf payload returned from firmware
196  * @config_page: contents of the config page
197  * Context: sleep.
198  *
199  * Returns 0 for success, non-zero for failure.
200  */
201 int
202 mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
203     Mpi2IOUnitPage8_t *config_page)
204 {
205 	MPI2_CONFIG_REQUEST *request;
206 	MPI2_CONFIG_REPLY *reply;
207 	struct mpr_command *cm;
208 	MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL;
209 	int error = 0;
210 	u16 ioc_status;
211 
212 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
213 
214 	if ((cm = mpr_alloc_command(sc)) == NULL) {
215 		printf("%s: command alloc failed @ line %d\n", __func__,
216 		    __LINE__);
217 		error = EBUSY;
218 		goto out;
219 	}
220 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
221 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
222 	request->Function = MPI2_FUNCTION_CONFIG;
223 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
224 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
225 	request->Header.PageNumber = 8;
226 	request->Header.PageLength = request->Header.PageVersion = 0;
227 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
228 	cm->cm_data = NULL;
229 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
230 	if (cm != NULL)
231 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
232 	if (error || (reply == NULL)) {
233 		/* FIXME */
234 		/*
235 		 * If the request returns an error then we need to do a diag
236 		 * reset
237 		 */
238 		printf("%s: request for header completed with error %d\n",
239 		    __func__, error);
240 		error = ENXIO;
241 		goto out;
242 	}
243 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
244 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
245 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
246 		/* FIXME */
247 		/*
248 		 * If the request returns an error then we need to do a diag
249 		 * reset
250 		 */
251 		printf("%s: header read with error; iocstatus = 0x%x\n",
252 		    __func__, ioc_status);
253 		error = ENXIO;
254 		goto out;
255 	}
256 	/* We have to do free and alloc for the reply-free and reply-post
257 	 * counters to match - Need to review the reply FIFO handling.
258 	 */
259 	mpr_free_command(sc, cm);
260 
261 	if ((cm = mpr_alloc_command(sc)) == NULL) {
262 		printf("%s: command alloc failed @ line %d\n", __func__,
263 		    __LINE__);
264 		error = EBUSY;
265 		goto out;
266 	}
267 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
268 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
269 	request->Function = MPI2_FUNCTION_CONFIG;
270 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
271 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
272 	request->Header.PageNumber = 8;
273 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
274 	request->Header.PageLength = mpi_reply->Header.PageLength;
275 	cm->cm_length = mpi_reply->Header.PageLength * 4;
276 	cm->cm_sge = &request->PageBufferSGE;
277 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
278 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
279 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
280 	page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
281 	if (!page) {
282 		printf("%s: page alloc failed\n", __func__);
283 		error = ENOMEM;
284 		goto out;
285 	}
286 	cm->cm_data = page;
287 
288 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
289 	if (cm != NULL)
290 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
291 	if (error || (reply == NULL)) {
292 		/* FIXME */
293 		/*
294 		 * If the request returns an error then we need to do a diag
295 		 * reset
296 		 */
297 		printf("%s: request for page completed with error %d\n",
298 		    __func__, error);
299 		error = ENXIO;
300 		goto out;
301 	}
302 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
303 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
304 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
305 		/* FIXME */
306 		/*
307 		 * If the request returns an error then we need to do a diag
308 		 * reset
309 		 */
310 		printf("%s: page read with error; iocstatus = 0x%x\n",
311 		    __func__, ioc_status);
312 		error = ENXIO;
313 		goto out;
314 	}
315 	bcopy(page, config_page, MIN(cm->cm_length,
316 	    (sizeof(Mpi2IOUnitPage8_t))));
317 
318 out:
319 	free(page, M_MPR);
320 	if (cm)
321 		mpr_free_command(sc, cm);
322 	return (error);
323 }
324 
325 /**
326  * mpr_config_get_man_pg11 - obtain manufacturing page 11
327  * @sc: per adapter object
328  * @mpi_reply: reply mf payload returned from firmware
329  * @config_page: contents of the config page
330  * Context: sleep.
331  *
332  * Returns 0 for success, non-zero for failure.
333  */
334 int
335 mpr_config_get_man_pg11(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
336     Mpi2ManufacturingPage11_t *config_page)
337 {
338 	MPI2_CONFIG_REQUEST *request;
339 	MPI2_CONFIG_REPLY *reply;
340 	struct mpr_command *cm;
341 	MPI2_CONFIG_PAGE_MAN_11 *page = NULL;
342 	int error = 0;
343 	u16 ioc_status;
344 
345 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
346 
347 	if ((cm = mpr_alloc_command(sc)) == NULL) {
348 		printf("%s: command alloc failed @ line %d\n", __func__,
349 		    __LINE__);
350 		error = EBUSY;
351 		goto out;
352 	}
353 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
354 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
355 	request->Function = MPI2_FUNCTION_CONFIG;
356 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
357 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
358 	request->Header.PageNumber = 11;
359 	request->Header.PageLength = request->Header.PageVersion = 0;
360 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
361 	cm->cm_data = NULL;
362 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
363 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
364 	if (error || (reply == NULL)) {
365 		/* FIXME */
366 		/*
367 		 * If the request returns an error then we need to do a diag
368 		 * reset
369 		 */
370 		printf("%s: request for header completed with error %d\n",
371 		    __func__, error);
372 		error = ENXIO;
373 		goto out;
374 	}
375 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
376 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
377 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
378 		/* FIXME */
379 		/*
380 		 * If the request returns an error then we need to do a diag
381 		 * reset
382 		 */
383 		printf("%s: header read with error; iocstatus = 0x%x\n",
384 		    __func__, ioc_status);
385 		error = ENXIO;
386 		goto out;
387 	}
388 	/* We have to do free and alloc for the reply-free and reply-post
389 	 * counters to match - Need to review the reply FIFO handling.
390 	 */
391 	mpr_free_command(sc, cm);
392 
393 	if ((cm = mpr_alloc_command(sc)) == NULL) {
394 		printf("%s: command alloc failed @ line %d\n", __func__,
395 		    __LINE__);
396 		error = EBUSY;
397 		goto out;
398 	}
399 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
400 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
401 	request->Function = MPI2_FUNCTION_CONFIG;
402 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
403 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
404 	request->Header.PageNumber = 11;
405 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
406 	request->Header.PageLength = mpi_reply->Header.PageLength;
407 	cm->cm_length = mpi_reply->Header.PageLength * 4;
408 	cm->cm_sge = &request->PageBufferSGE;
409 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
410 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
411 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
412 	page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
413 	if (!page) {
414 		printf("%s: page alloc failed\n", __func__);
415 		error = ENOMEM;
416 		goto out;
417 	}
418 	cm->cm_data = page;
419 
420 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
421 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
422 	if (error || (reply == NULL)) {
423 		/* FIXME */
424 		/*
425 		 * If the request returns an error then we need to do a diag
426 		 * reset
427 		 */
428 		printf("%s: request for page completed with error %d\n",
429 		    __func__, error);
430 		error = ENXIO;
431 		goto out;
432 	}
433 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
434 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
435 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
436 		/* FIXME */
437 		/*
438 		 * If the request returns an error then we need to do a diag
439 		 * reset
440 		 */
441 		printf("%s: page read with error; iocstatus = 0x%x\n",
442 		    __func__, ioc_status);
443 		error = ENXIO;
444 		goto out;
445 	}
446 	bcopy(page, config_page, MIN(cm->cm_length,
447 	    (sizeof(Mpi2ManufacturingPage11_t))));
448 
449 out:
450 	free(page, M_MPR);
451 	if (cm)
452 		mpr_free_command(sc, cm);
453 	return (error);
454 }
455 
456 /**
457  * mpr_base_static_config_pages - static start of day config pages.
458  * @sc: per adapter object
459  *
460  * Return nothing.
461  */
462 void
463 mpr_base_static_config_pages(struct mpr_softc *sc)
464 {
465 	Mpi2ConfigReply_t		mpi_reply;
466 	Mpi2ManufacturingPage11_t	man_pg11;
467 	int				retry, rc;
468 
469 	retry = 0;
470 	while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
471 		retry++;
472 		if (retry > 5) {
473 			/* We need to Handle this situation */
474 			/*FIXME*/
475 			break;
476 		}
477 	}
478 	retry = 0;
479 	while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) {
480 		retry++;
481 		if (retry > 5) {
482 			/* We need to Handle this situation */
483 			/*FIXME*/
484 			break;
485 		}
486 	}
487 	retry = 0;
488 	while ((rc = mpr_config_get_man_pg11(sc, &mpi_reply, &man_pg11))) {
489 		retry++;
490 		if (retry > 5) {
491 			/* We need to Handle this situation */
492 			/*FIXME*/
493 			break;
494 		}
495 	}
496 
497 	if (!rc) {
498 		sc->custom_nvme_tm_handling = (le16toh(man_pg11.AddlFlags2) &
499 		    MPI2_MAN_PG11_ADDLFLAGS2_CUSTOM_TM_HANDLING_MASK);
500 		sc->nvme_abort_timeout = man_pg11.NVMeAbortTO;
501 
502 		/* Minimum NVMe Abort timeout value should be 6 seconds &
503 		 * maximum value should be 60 seconds.
504 		 */
505 		if (sc->nvme_abort_timeout < 6)
506 			sc->nvme_abort_timeout = 6;
507 		if (sc->nvme_abort_timeout > 60)
508 			sc->nvme_abort_timeout = 60;
509 	}
510 }
511 
512 /**
513  * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0
514  * @sc: per adapter object
515  * @mpi_reply: reply mf payload returned from firmware
516  * @config_page: contents of the config page
517  * @sz: size of buffer passed in config_page
518  * Context: sleep.
519  *
520  * Returns 0 for success, non-zero for failure.
521  */
522 int
523 mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
524     Mpi2DriverMappingPage0_t *config_page, u16 sz)
525 {
526 	MPI2_CONFIG_REQUEST *request;
527 	MPI2_CONFIG_REPLY *reply;
528 	struct mpr_command *cm;
529 	Mpi2DriverMappingPage0_t *page = NULL;
530 	int error = 0;
531 	u16 ioc_status;
532 
533 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
534 
535 	memset(config_page, 0, sz);
536 	if ((cm = mpr_alloc_command(sc)) == NULL) {
537 		printf("%s: command alloc failed @ line %d\n", __func__,
538 		    __LINE__);
539 		error = EBUSY;
540 		goto out;
541 	}
542 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
543 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
544 	request->Function = MPI2_FUNCTION_CONFIG;
545 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
546 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
547 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
548 	request->Header.PageNumber = 0;
549 	request->ExtPageLength = request->Header.PageVersion = 0;
550 	request->PageAddress = htole32(sc->max_dpm_entries <<
551 	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT);
552 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
553 	cm->cm_data = NULL;
554 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
555 	if (cm != NULL)
556 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
557 	if (error || (reply == NULL)) {
558 		/* FIXME */
559 		/*
560 		 * If the request returns an error then we need to do a diag
561 		 * reset
562 		 */
563 		printf("%s: request for header completed with error %d\n",
564 		    __func__, error);
565 		error = ENXIO;
566 		goto out;
567 	}
568 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
569 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
570 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
571 		/* FIXME */
572 		/*
573 		 * If the request returns an error then we need to do a diag
574 		 * reset
575 		 */
576 		printf("%s: header read with error; iocstatus = 0x%x\n",
577 		    __func__, ioc_status);
578 		error = ENXIO;
579 		goto out;
580 	}
581 	/* We have to do free and alloc for the reply-free and reply-post
582 	 * counters to match - Need to review the reply FIFO handling.
583 	 */
584 	mpr_free_command(sc, cm);
585 
586 	if ((cm = mpr_alloc_command(sc)) == NULL) {
587 		printf("%s: command alloc failed @ line %d\n", __func__,
588 		    __LINE__);
589 		error = EBUSY;
590 		goto out;
591 	}
592 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
593 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
594 	request->Function = MPI2_FUNCTION_CONFIG;
595 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
596 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
597 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
598 	request->Header.PageNumber = 0;
599 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
600 	request->PageAddress = htole32(sc->max_dpm_entries <<
601 	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT);
602 	request->ExtPageLength = mpi_reply->ExtPageLength;
603 	cm->cm_length = le16toh(request->ExtPageLength) * 4;
604 	cm->cm_sge = &request->PageBufferSGE;
605 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
606 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
607 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
608 	page = malloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT);
609 	if (!page) {
610 		printf("%s: page alloc failed\n", __func__);
611 		error = ENOMEM;
612 		goto out;
613 	}
614 	cm->cm_data = page;
615 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
616 	if (cm != NULL)
617 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
618 	if (error || (reply == NULL)) {
619 		/* FIXME */
620 		/*
621 		 * If the request returns an error then we need to do a diag
622 		 * reset
623 		 */
624 		printf("%s: request for page completed with error %d\n",
625 		    __func__, error);
626 		error = ENXIO;
627 		goto out;
628 	}
629 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
630 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
631 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
632 		/* FIXME */
633 		/*
634 		 * If the request returns an error then we need to do a diag
635 		 * reset
636 		 */
637 		printf("%s: page read with error; iocstatus = 0x%x\n",
638 		    __func__, ioc_status);
639 		error = ENXIO;
640 		goto out;
641 	}
642 	bcopy(page, config_page, MIN(cm->cm_length, sz));
643 out:
644 	free(page, M_MPR);
645 	if (cm)
646 		mpr_free_command(sc, cm);
647 	return (error);
648 }
649 
650 /**
651  * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
652  * @sc: per adapter object
653  * @mpi_reply: reply mf payload returned from firmware
654  * @config_page: contents of the config page
655  * @entry_idx: entry index in DPM Page0 to be modified
656  * Context: sleep.
657  *
658  * Returns 0 for success, non-zero for failure.
659  */
660 
661 int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
662     Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
663 {
664 	MPI2_CONFIG_REQUEST *request;
665 	MPI2_CONFIG_REPLY *reply;
666 	struct mpr_command *cm;
667 	MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
668 	int error = 0;
669 	u16 ioc_status;
670 
671 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
672 
673 	if ((cm = mpr_alloc_command(sc)) == NULL) {
674 		printf("%s: command alloc failed @ line %d\n", __func__,
675 		    __LINE__);
676 		error = EBUSY;
677 		goto out;
678 	}
679 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
680 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
681 	request->Function = MPI2_FUNCTION_CONFIG;
682 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
683 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
684 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
685 	request->Header.PageNumber = 0;
686 	request->ExtPageLength = request->Header.PageVersion = 0;
687 	request->PageAddress = htole32(
688 		(1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT) | entry_idx);
689 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
690 	cm->cm_data = NULL;
691 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
692 	if (cm != NULL)
693 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
694 	if (error || (reply == NULL)) {
695 		/* FIXME */
696 		/*
697 		 * If the request returns an error then we need to do a diag
698 		 * reset
699 		 */
700 		printf("%s: request for header completed with error %d\n",
701 		    __func__, error);
702 		error = ENXIO;
703 		goto out;
704 	}
705 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
706 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
707 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
708 		/* FIXME */
709 		/*
710 		 * If the request returns an error then we need to do a diag
711 		 * reset
712 		 */
713 		printf("%s: header read with error; iocstatus = 0x%x\n",
714 		    __func__, ioc_status);
715 		error = ENXIO;
716 		goto out;
717 	}
718 	/* We have to do free and alloc for the reply-free and reply-post
719 	 * counters to match - Need to review the reply FIFO handling.
720 	 */
721 	mpr_free_command(sc, cm);
722 
723 	if ((cm = mpr_alloc_command(sc)) == NULL) {
724 		printf("%s: command alloc failed @ line %d\n", __func__,
725 		    __LINE__);
726 		error = EBUSY;
727 		goto out;
728 	}
729 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
730 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
731 	request->Function = MPI2_FUNCTION_CONFIG;
732 	request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
733 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
734 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
735 	request->Header.PageNumber = 0;
736 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
737 	request->ExtPageLength = mpi_reply->ExtPageLength;
738 	request->PageAddress = htole32(
739 		(1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT) | entry_idx);
740 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
741 	cm->cm_sge = &request->PageBufferSGE;
742 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
743 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT;
744 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
745 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
746 	if (!page) {
747 		printf("%s: page alloc failed\n", __func__);
748 		error = ENOMEM;
749 		goto out;
750 	}
751 	bcopy(config_page, page, MIN(cm->cm_length,
752 	    (sizeof(Mpi2DriverMappingPage0_t))));
753 	cm->cm_data = page;
754 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
755 	if (cm != NULL)
756 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
757 	if (error || (reply == NULL)) {
758 		/* FIXME */
759 		/*
760 		 * If the request returns an error then we need to do a diag
761 		 * reset
762 		 */
763 		printf("%s: request to write page completed with error %d\n",
764 		    __func__, error);
765 		error = ENXIO;
766 		goto out;
767 	}
768 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
769 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
770 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
771 		/* FIXME */
772 		/*
773 		 * If the request returns an error then we need to do a diag
774 		 * reset
775 		 */
776 		printf("%s: page written with error; iocstatus = 0x%x\n",
777 		    __func__, ioc_status);
778 		error = ENXIO;
779 		goto out;
780 	}
781 out:
782 	free(page, M_MPR);
783 	if (cm)
784 		mpr_free_command(sc, cm);
785 	return (error);
786 }
787 
788 /**
789  * mpr_config_get_sas_device_pg0 - obtain sas device page 0
790  * @sc: per adapter object
791  * @mpi_reply: reply mf payload returned from firmware
792  * @config_page: contents of the config page
793  * @form: GET_NEXT_HANDLE or HANDLE
794  * @handle: device handle
795  * Context: sleep.
796  *
797  * Returns 0 for success, non-zero for failure.
798  */
799 int
800 mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
801     *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
802 {
803 	MPI2_CONFIG_REQUEST *request;
804 	MPI2_CONFIG_REPLY *reply;
805 	struct mpr_command *cm;
806 	Mpi2SasDevicePage0_t *page = NULL;
807 	int error = 0;
808 	u16 ioc_status;
809 
810 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
811 
812 	if ((cm = mpr_alloc_command(sc)) == NULL) {
813 		printf("%s: command alloc failed @ line %d\n", __func__,
814 		    __LINE__);
815 		error = EBUSY;
816 		goto out;
817 	}
818 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
819 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
820 	request->Function = MPI2_FUNCTION_CONFIG;
821 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
822 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
823 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
824 	request->Header.PageNumber = 0;
825 	request->ExtPageLength = request->Header.PageVersion = 0;
826 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
827 	cm->cm_data = NULL;
828 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
829 	if (cm != NULL)
830 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
831 	if (error || (reply == NULL)) {
832 		/* FIXME */
833 		/*
834 		 * If the request returns an error then we need to do a diag
835 		 * reset
836 		 */
837 		printf("%s: request for header completed with error %d\n",
838 		    __func__, error);
839 		error = ENXIO;
840 		goto out;
841 	}
842 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
843 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
844 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
845 		/* FIXME */
846 		/*
847 		 * If the request returns an error then we need to do a diag
848 		 * reset
849 		 */
850 		printf("%s: header read with error; iocstatus = 0x%x\n",
851 		    __func__, ioc_status);
852 		error = ENXIO;
853 		goto out;
854 	}
855 	/* We have to do free and alloc for the reply-free and reply-post
856 	 * counters to match - Need to review the reply FIFO handling.
857 	 */
858 	mpr_free_command(sc, cm);
859 
860 	if ((cm = mpr_alloc_command(sc)) == NULL) {
861 		printf("%s: command alloc failed @ line %d\n", __func__,
862 		    __LINE__);
863 		error = EBUSY;
864 		goto out;
865 	}
866 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
867 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
868 	request->Function = MPI2_FUNCTION_CONFIG;
869 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
870 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
871 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
872 	request->Header.PageNumber = 0;
873 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
874 	request->ExtPageLength = mpi_reply->ExtPageLength;
875 	request->PageAddress = htole32(form | handle);
876 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
877 	cm->cm_sge = &request->PageBufferSGE;
878 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
879 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
880 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
881 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
882 	if (!page) {
883 		printf("%s: page alloc failed\n", __func__);
884 		error = ENOMEM;
885 		goto out;
886 	}
887 	cm->cm_data = page;
888 
889 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
890 	if (cm != NULL)
891 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
892 	if (error || (reply == NULL)) {
893 		/* FIXME */
894 		/*
895 		 * If the request returns an error then we need to do a diag
896 		 * reset
897 		 */
898 		printf("%s: request for page completed with error %d\n",
899 		    __func__, error);
900 		error = ENXIO;
901 		goto out;
902 	}
903 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
904 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
905 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
906 		/* FIXME */
907 		/*
908 		 * If the request returns an error then we need to do a diag
909 		 * reset
910 		 */
911 		printf("%s: page read with error; iocstatus = 0x%x\n",
912 		    __func__, ioc_status);
913 		error = ENXIO;
914 		goto out;
915 	}
916 	bcopy(page, config_page, MIN(cm->cm_length,
917 	    sizeof(Mpi2SasDevicePage0_t)));
918 out:
919 	free(page, M_MPR);
920 	if (cm)
921 		mpr_free_command(sc, cm);
922 	return (error);
923 }
924 
925 /**
926  * mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0
927  * @sc: per adapter object
928  * @mpi_reply: reply mf payload returned from firmware
929  * @config_page: contents of the config page
930  * @form: GET_NEXT_HANDLE or HANDLE
931  * @handle: device handle
932  * Context: sleep.
933  *
934  * Returns 0 for success, non-zero for failure.
935  */
936 int
937 mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
938     *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle)
939 {
940 	MPI2_CONFIG_REQUEST *request;
941 	MPI2_CONFIG_REPLY *reply;
942 	struct mpr_command *cm;
943 	Mpi26PCIeDevicePage0_t *page = NULL;
944 	int error = 0;
945 	u16 ioc_status;
946 
947 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
948 
949 	if ((cm = mpr_alloc_command(sc)) == NULL) {
950 		printf("%s: command alloc failed @ line %d\n", __func__,
951 		    __LINE__);
952 		error = EBUSY;
953 		goto out;
954 	}
955 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
956 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
957 	request->Function = MPI2_FUNCTION_CONFIG;
958 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
959 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
960 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
961 	request->Header.PageNumber = 0;
962 	request->ExtPageLength = request->Header.PageVersion = 0;
963 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
964 	cm->cm_data = NULL;
965 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
966 	if (cm != NULL)
967 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
968 	if (error || (reply == NULL)) {
969 		/* FIXME */
970 		/*
971 		 * If the request returns an error then we need to do a diag
972 		 * reset
973 		 */
974 		printf("%s: request for header completed with error %d\n",
975 		    __func__, error);
976 		error = ENXIO;
977 		goto out;
978 	}
979 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
980 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
981 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
982 		/* FIXME */
983 		/*
984 		 * If the request returns an error then we need to do a diag
985 		 * reset
986 		 */
987 		printf("%s: header read with error; iocstatus = 0x%x\n",
988 		    __func__, ioc_status);
989 		error = ENXIO;
990 		goto out;
991 	}
992 	/* We have to do free and alloc for the reply-free and reply-post
993 	 * counters to match - Need to review the reply FIFO handling.
994 	 */
995 	mpr_free_command(sc, cm);
996 
997 	if ((cm = mpr_alloc_command(sc)) == NULL) {
998 		printf("%s: command alloc failed @ line %d\n", __func__,
999 		    __LINE__);
1000 		error = EBUSY;
1001 		goto out;
1002 	}
1003 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1004 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1005 	request->Function = MPI2_FUNCTION_CONFIG;
1006 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1007 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1008 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1009 	request->Header.PageNumber = 0;
1010 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1011 	request->ExtPageLength = mpi_reply->ExtPageLength;
1012 	request->PageAddress = htole32(form | handle);
1013 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
1014 	cm->cm_sge = &request->PageBufferSGE;
1015 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1016 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1017 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1018 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1019 	if (!page) {
1020 		printf("%s: page alloc failed\n", __func__);
1021 		error = ENOMEM;
1022 		goto out;
1023 	}
1024 	cm->cm_data = page;
1025 
1026 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1027 	if (cm != NULL)
1028 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1029 	if (error || (reply == NULL)) {
1030 		/* FIXME */
1031 		/*
1032 		 * If the request returns an error then we need to do a diag
1033 		 * reset
1034 		 */
1035 		printf("%s: request for page completed with error %d\n",
1036 		    __func__, error);
1037 		error = ENXIO;
1038 		goto out;
1039 	}
1040 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1041 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1042 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1043 		/* FIXME */
1044 		/*
1045 		 * If the request returns an error then we need to do a diag
1046 		 * reset
1047 		 */
1048 		printf("%s: page read with error; iocstatus = 0x%x\n",
1049 		    __func__, ioc_status);
1050 		error = ENXIO;
1051 		goto out;
1052 	}
1053 	bcopy(page, config_page, MIN(cm->cm_length,
1054 	    sizeof(Mpi26PCIeDevicePage0_t)));
1055 out:
1056 	free(page, M_MPR);
1057 	if (cm)
1058 		mpr_free_command(sc, cm);
1059 	return (error);
1060 }
1061 
1062 /**
1063  * mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2
1064  * @sc: per adapter object
1065  * @mpi_reply: reply mf payload returned from firmware
1066  * @config_page: contents of the config page
1067  * @form: GET_NEXT_HANDLE or HANDLE
1068  * @handle: device handle
1069  * Context: sleep.
1070  *
1071  * Returns 0 for success, non-zero for failure.
1072  */
1073 int
1074 mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t
1075     *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle)
1076 {
1077 	MPI2_CONFIG_REQUEST *request;
1078 	MPI2_CONFIG_REPLY *reply;
1079 	struct mpr_command *cm;
1080 	Mpi26PCIeDevicePage2_t *page = NULL;
1081 	int error = 0;
1082 	u16 ioc_status;
1083 
1084 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1085 
1086 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1087 		printf("%s: command alloc failed @ line %d\n", __func__,
1088 		    __LINE__);
1089 		error = EBUSY;
1090 		goto out;
1091 	}
1092 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1093 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1094 	request->Function = MPI2_FUNCTION_CONFIG;
1095 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1096 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1097 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1098 	request->Header.PageNumber = 2;
1099 	request->ExtPageLength = request->Header.PageVersion = 0;
1100 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1101 	cm->cm_data = NULL;
1102 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1103 	if (cm != NULL)
1104 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1105 	if (error || (reply == NULL)) {
1106 		/* FIXME */
1107 		/*
1108 		 * If the request returns an error then we need to do a diag
1109 		 * reset
1110 		 */
1111 		printf("%s: request for header completed with error %d\n",
1112 		    __func__, error);
1113 		error = ENXIO;
1114 		goto out;
1115 	}
1116 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1117 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1118 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1119 		/* FIXME */
1120 		/*
1121 		 * If the request returns an error then we need to do a diag
1122 		 * reset
1123 		 */
1124 		printf("%s: header read with error; iocstatus = 0x%x\n",
1125 		    __func__, ioc_status);
1126 		error = ENXIO;
1127 		goto out;
1128 	}
1129 	/* We have to do free and alloc for the reply-free and reply-post
1130 	 * counters to match - Need to review the reply FIFO handling.
1131 	 */
1132 	mpr_free_command(sc, cm);
1133 
1134 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1135 		printf("%s: command alloc failed @ line %d\n", __func__,
1136 		    __LINE__);
1137 		error = EBUSY;
1138 		goto out;
1139 	}
1140 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1141 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1142 	request->Function = MPI2_FUNCTION_CONFIG;
1143 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1144 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1145 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1146 	request->Header.PageNumber = 2;
1147 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1148 	request->ExtPageLength = mpi_reply->ExtPageLength;
1149 	request->PageAddress = htole32(form | handle);
1150 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
1151 	cm->cm_sge = &request->PageBufferSGE;
1152 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1153 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1154 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1155 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1156 	if (!page) {
1157 		printf("%s: page alloc failed\n", __func__);
1158 		error = ENOMEM;
1159 		goto out;
1160 	}
1161 	cm->cm_data = page;
1162 
1163 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1164 	if (cm != NULL)
1165 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1166 	if (error || (reply == NULL)) {
1167 		/* FIXME */
1168 		/*
1169 		 * If the request returns an error then we need to do a diag
1170 		 * reset
1171 		 */
1172 		printf("%s: request for page completed with error %d\n",
1173 		    __func__, error);
1174 		error = ENXIO;
1175 		goto out;
1176 	}
1177 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1178 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1179 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1180 		/* FIXME */
1181 		/*
1182 		 * If the request returns an error then we need to do a diag
1183 		 * reset
1184 		 */
1185 		printf("%s: page read with error; iocstatus = 0x%x\n",
1186 		    __func__, ioc_status);
1187 		error = ENXIO;
1188 		goto out;
1189 	}
1190 	bcopy(page, config_page, MIN(cm->cm_length,
1191 	    sizeof(Mpi26PCIeDevicePage2_t)));
1192 out:
1193 	free(page, M_MPR);
1194 	if (cm)
1195 		mpr_free_command(sc, cm);
1196 	return (error);
1197 }
1198 
1199 /**
1200  * mpr_config_get_bios_pg3 - obtain BIOS page 3
1201  * @sc: per adapter object
1202  * @mpi_reply: reply mf payload returned from firmware
1203  * @config_page: contents of the config page
1204  * Context: sleep.
1205  *
1206  * Returns 0 for success, non-zero for failure.
1207  */
1208 int
1209 mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1210     Mpi2BiosPage3_t *config_page)
1211 {
1212 	MPI2_CONFIG_REQUEST *request;
1213 	MPI2_CONFIG_REPLY *reply;
1214 	struct mpr_command *cm;
1215 	Mpi2BiosPage3_t *page = NULL;
1216 	int error = 0;
1217 	u16 ioc_status;
1218 
1219 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1220 
1221 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1222 		printf("%s: command alloc failed @ line %d\n", __func__,
1223 		    __LINE__);
1224 		error = EBUSY;
1225 		goto out;
1226 	}
1227 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1228 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1229 	request->Function = MPI2_FUNCTION_CONFIG;
1230 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1231 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1232 	request->Header.PageNumber = 3;
1233 	request->Header.PageLength = request->Header.PageVersion = 0;
1234 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1235 	cm->cm_data = NULL;
1236 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1237 	if (cm != NULL)
1238 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1239 	if (error || (reply == NULL)) {
1240 		/* FIXME */
1241 		/*
1242 		 * If the request returns an error then we need to do a diag
1243 		 * reset
1244 		 */
1245 		printf("%s: request for header completed with error %d\n",
1246 		    __func__, error);
1247 		error = ENXIO;
1248 		goto out;
1249 	}
1250 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1251 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1252 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1253 		/* FIXME */
1254 		/*
1255 		 * If the request returns an error then we need to do a diag
1256 		 * reset
1257 		 */
1258 		printf("%s: header read with error; iocstatus = 0x%x\n",
1259 		    __func__, ioc_status);
1260 		error = ENXIO;
1261 		goto out;
1262 	}
1263 	/* We have to do free and alloc for the reply-free and reply-post
1264 	 * counters to match - Need to review the reply FIFO handling.
1265 	 */
1266 	mpr_free_command(sc, cm);
1267 
1268 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1269 		printf("%s: command alloc failed @ line %d\n", __func__,
1270 		    __LINE__);
1271 		error = EBUSY;
1272 		goto out;
1273 	}
1274 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1275 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1276 	request->Function = MPI2_FUNCTION_CONFIG;
1277 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1278 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1279 	request->Header.PageNumber = 3;
1280 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1281 	request->Header.PageLength = mpi_reply->Header.PageLength;
1282 	cm->cm_length = mpi_reply->Header.PageLength * 4;
1283 	cm->cm_sge = &request->PageBufferSGE;
1284 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1285 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1286 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1287 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1288 	if (!page) {
1289 		printf("%s: page alloc failed\n", __func__);
1290 		error = ENOMEM;
1291 		goto out;
1292 	}
1293 	cm->cm_data = page;
1294 
1295 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1296 	if (cm != NULL)
1297 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1298 	if (error || (reply == NULL)) {
1299 		/* FIXME */
1300 		/*
1301 		 * If the request returns an error then we need to do a diag
1302 		 * reset
1303 		 */
1304 		printf("%s: request for page completed with error %d\n",
1305 		    __func__, error);
1306 		error = ENXIO;
1307 		goto out;
1308 	}
1309 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1310 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1311 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1312 		/* FIXME */
1313 		/*
1314 		 * If the request returns an error then we need to do a diag
1315 		 * reset
1316 		 */
1317 		printf("%s: page read with error; iocstatus = 0x%x\n",
1318 		    __func__, ioc_status);
1319 		error = ENXIO;
1320 		goto out;
1321 	}
1322 	bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1323 out:
1324 	free(page, M_MPR);
1325 	if (cm)
1326 		mpr_free_command(sc, cm);
1327 	return (error);
1328 }
1329 
1330 /**
1331  * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0
1332  * @sc: per adapter object
1333  * @mpi_reply: reply mf payload returned from firmware
1334  * @config_page: contents of the config page
1335  * @page_address: form and handle value used to get page
1336  * Context: sleep.
1337  *
1338  * Returns 0 for success, non-zero for failure.
1339  */
1340 int
1341 mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
1342     *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1343 {
1344 	MPI2_CONFIG_REQUEST *request;
1345 	MPI2_CONFIG_REPLY *reply = NULL;
1346 	struct mpr_command *cm;
1347 	Mpi2RaidVolPage0_t *page = NULL;
1348 	int error = 0;
1349 	u16 ioc_status;
1350 
1351 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1352 
1353 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1354 		printf("%s: command alloc failed @ line %d\n", __func__,
1355 		    __LINE__);
1356 		error = EBUSY;
1357 		goto out;
1358 	}
1359 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1360 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1361 	request->Function = MPI2_FUNCTION_CONFIG;
1362 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1363 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1364 	request->Header.PageNumber = 0;
1365 	request->Header.PageLength = request->Header.PageVersion = 0;
1366 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1367 	cm->cm_data = NULL;
1368 
1369 	/*
1370 	 * This page must be polled because the IOC isn't ready yet when this
1371 	 * page is needed.
1372 	 */
1373 	error = mpr_request_polled(sc, &cm);
1374 	if (cm != NULL)
1375 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1376 	if (error || (reply == NULL)) {
1377 		/* FIXME */
1378 		/* If the poll returns error then we need to do diag reset */
1379 		printf("%s: poll for header completed with error %d\n",
1380 		    __func__, error);
1381 		error = ENXIO;
1382 		goto out;
1383 	}
1384 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1385 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1386 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1387 		/* FIXME */
1388 		/* If the poll returns error then we need to do diag reset */
1389 		printf("%s: header read with error; iocstatus = 0x%x\n",
1390 		    __func__, ioc_status);
1391 		error = ENXIO;
1392 		goto out;
1393 	}
1394 	/* We have to do free and alloc for the reply-free and reply-post
1395 	 * counters to match - Need to review the reply FIFO handling.
1396 	 */
1397 	mpr_free_command(sc, cm);
1398 
1399 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1400 		printf("%s: command alloc failed @ line %d\n", __func__,
1401 		    __LINE__);
1402 		error = EBUSY;
1403 		goto out;
1404 	}
1405 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1406 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1407 	request->Function = MPI2_FUNCTION_CONFIG;
1408 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1409 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1410 	request->Header.PageNumber = 0;
1411 	request->Header.PageLength = mpi_reply->Header.PageLength;
1412 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1413 	request->PageAddress = page_address;
1414 	cm->cm_length = mpi_reply->Header.PageLength * 4;
1415 	cm->cm_sge = &request->PageBufferSGE;
1416 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1417 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1418 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1419 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1420 	if (!page) {
1421 		printf("%s: page alloc failed\n", __func__);
1422 		error = ENOMEM;
1423 		goto out;
1424 	}
1425 	cm->cm_data = page;
1426 
1427 	/*
1428 	 * This page must be polled because the IOC isn't ready yet when this
1429 	 * page is needed.
1430 	 */
1431 	error = mpr_request_polled(sc, &cm);
1432 	if (cm != NULL)
1433 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1434 	if (error || (reply == NULL)) {
1435 		/* FIXME */
1436 		/* If the poll returns error then we need to do diag reset */
1437 		printf("%s: poll for page completed with error %d\n",
1438 		    __func__, error);
1439 		error = ENXIO;
1440 		goto out;
1441 	}
1442 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1443 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1444 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1445 		/* FIXME */
1446 		/* If the poll returns error then we need to do diag reset */
1447 		printf("%s: page read with error; iocstatus = 0x%x\n",
1448 		    __func__, ioc_status);
1449 		error = ENXIO;
1450 		goto out;
1451 	}
1452 	bcopy(page, config_page, cm->cm_length);
1453 out:
1454 	free(page, M_MPR);
1455 	if (cm)
1456 		mpr_free_command(sc, cm);
1457 	return (error);
1458 }
1459 
1460 /**
1461  * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1
1462  * @sc: per adapter object
1463  * @mpi_reply: reply mf payload returned from firmware
1464  * @config_page: contents of the config page
1465  * @form: GET_NEXT_HANDLE or HANDLE
1466  * @handle: volume handle
1467  * Context: sleep.
1468  *
1469  * Returns 0 for success, non-zero for failure.
1470  */
1471 int
1472 mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t
1473     *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1474 {
1475 	MPI2_CONFIG_REQUEST *request;
1476 	MPI2_CONFIG_REPLY *reply;
1477 	struct mpr_command *cm;
1478 	Mpi2RaidVolPage1_t *page = NULL;
1479 	int error = 0;
1480 	u16 ioc_status;
1481 
1482 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1483 
1484 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1485 		printf("%s: command alloc failed @ line %d\n", __func__,
1486 		    __LINE__);
1487 		error = EBUSY;
1488 		goto out;
1489 	}
1490 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1491 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1492 	request->Function = MPI2_FUNCTION_CONFIG;
1493 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1494 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1495 	request->Header.PageNumber = 1;
1496 	request->Header.PageLength = request->Header.PageVersion = 0;
1497 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1498 	cm->cm_data = NULL;
1499 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1500 	if (cm != NULL)
1501 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1502 	if (error || (reply == NULL)) {
1503 		/* FIXME */
1504 		/*
1505 		 * If the request returns an error then we need to do a diag
1506 		 * reset
1507 		 */
1508 		printf("%s: request for header completed with error %d\n",
1509 		    __func__, error);
1510 		error = ENXIO;
1511 		goto out;
1512 	}
1513 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1514 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1515 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1516 		/* FIXME */
1517 		/*
1518 		 * If the request returns an error then we need to do a diag
1519 		 * reset
1520 		 */
1521 		printf("%s: header read with error; iocstatus = 0x%x\n",
1522 		    __func__, ioc_status);
1523 		error = ENXIO;
1524 		goto out;
1525 	}
1526 	/* We have to do free and alloc for the reply-free and reply-post
1527 	 * counters to match - Need to review the reply FIFO handling.
1528 	 */
1529 	mpr_free_command(sc, cm);
1530 
1531 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1532 		printf("%s: command alloc failed @ line %d\n", __func__,
1533 		    __LINE__);
1534 		error = EBUSY;
1535 		goto out;
1536 	}
1537 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1538 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1539 	request->Function = MPI2_FUNCTION_CONFIG;
1540 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1541 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1542 	request->Header.PageNumber = 1;
1543 	request->Header.PageLength = mpi_reply->Header.PageLength;
1544 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1545 	request->PageAddress = htole32(form | handle);
1546 	cm->cm_length = mpi_reply->Header.PageLength * 4;
1547 	cm->cm_sge = &request->PageBufferSGE;
1548 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1549 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1550 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1551 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1552 	if (!page) {
1553 		printf("%s: page alloc failed\n", __func__);
1554 		error = ENOMEM;
1555 		goto out;
1556 	}
1557 	cm->cm_data = page;
1558 
1559 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1560 	if (cm != NULL)
1561 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1562 	if (error || (reply == NULL)) {
1563 		/* FIXME */
1564 		/*
1565 		 * If the request returns an error then we need to do a diag
1566 		 * reset
1567 		 */
1568 		printf("%s: request for page completed with error %d\n",
1569 		    __func__, error);
1570 		error = ENXIO;
1571 		goto out;
1572 	}
1573 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1574 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1575 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1576 		/* FIXME */
1577 		/*
1578 		 * If the request returns an error then we need to do a diag
1579 		 * reset
1580 		 */
1581 		printf("%s: page read with error; iocstatus = 0x%x\n",
1582 		    __func__, ioc_status);
1583 		error = ENXIO;
1584 		goto out;
1585 	}
1586 	bcopy(page, config_page, MIN(cm->cm_length,
1587 	    sizeof(Mpi2RaidVolPage1_t)));
1588 out:
1589 	free(page, M_MPR);
1590 	if (cm)
1591 		mpr_free_command(sc, cm);
1592 	return (error);
1593 }
1594 
1595 /**
1596  * mpr_config_get_volume_wwid - returns wwid given the volume handle
1597  * @sc: per adapter object
1598  * @volume_handle: volume handle
1599  * @wwid: volume wwid
1600  * Context: sleep.
1601  *
1602  * Returns 0 for success, non-zero for failure.
1603  */
1604 int
1605 mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid)
1606 {
1607 	Mpi2ConfigReply_t mpi_reply;
1608 	Mpi2RaidVolPage1_t raid_vol_pg1;
1609 
1610 	*wwid = 0;
1611 	if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1612 	    MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1613 		*wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1614 		    raid_vol_pg1.WWID.Low);
1615 		return 0;
1616 	} else
1617 		return -1;
1618 }
1619 
1620 /**
1621  * mpr_config_get_pd_pg0 - obtain raid phys disk page 0
1622  * @sc: per adapter object
1623  * @mpi_reply: reply mf payload returned from firmware
1624  * @config_page: contents of the config page
1625  * @page_address: form and handle value used to get page
1626  * Context: sleep.
1627  *
1628  * Returns 0 for success, non-zero for failure.
1629  */
1630 int
1631 mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1632     Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1633 {
1634 	MPI2_CONFIG_REQUEST *request;
1635 	MPI2_CONFIG_REPLY *reply = NULL;
1636 	struct mpr_command *cm;
1637 	Mpi2RaidPhysDiskPage0_t *page = NULL;
1638 	int error = 0;
1639 	u16 ioc_status;
1640 
1641 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1642 
1643 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1644 		printf("%s: command alloc failed @ line %d\n", __func__,
1645 		    __LINE__);
1646 		error = EBUSY;
1647 		goto out;
1648 	}
1649 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1650 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1651 	request->Function = MPI2_FUNCTION_CONFIG;
1652 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1653 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1654 	request->Header.PageNumber = 0;
1655 	request->Header.PageLength = request->Header.PageVersion = 0;
1656 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1657 	cm->cm_data = NULL;
1658 
1659 	/*
1660 	 * This page must be polled because the IOC isn't ready yet when this
1661 	 * page is needed.
1662 	 */
1663 	error = mpr_request_polled(sc, &cm);
1664 	if (cm != NULL)
1665 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1666 	if (error || (reply == NULL)) {
1667 		/* FIXME */
1668 		/* If the poll returns error then we need to do diag reset */
1669 		printf("%s: poll for header completed with error %d\n",
1670 		    __func__, error);
1671 		error = ENXIO;
1672 		goto out;
1673 	}
1674 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1675 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1676 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1677 		/* FIXME */
1678 		/* If the poll returns error then we need to do diag reset */
1679 		printf("%s: header read with error; iocstatus = 0x%x\n",
1680 		    __func__, ioc_status);
1681 		error = ENXIO;
1682 		goto out;
1683 	}
1684 	/* We have to do free and alloc for the reply-free and reply-post
1685 	 * counters to match - Need to review the reply FIFO handling.
1686 	 */
1687 	mpr_free_command(sc, cm);
1688 
1689 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1690 		printf("%s: command alloc failed @ line %d\n", __func__,
1691 		    __LINE__);
1692 		error = EBUSY;
1693 		goto out;
1694 	}
1695 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1696 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1697 	request->Function = MPI2_FUNCTION_CONFIG;
1698 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1699 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1700 	request->Header.PageNumber = 0;
1701 	request->Header.PageLength = mpi_reply->Header.PageLength;
1702 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1703 	request->PageAddress = page_address;
1704 	cm->cm_length = mpi_reply->Header.PageLength * 4;
1705 	cm->cm_sge = &request->PageBufferSGE;
1706 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1707 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1708 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1709 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1710 	if (!page) {
1711 		printf("%s: page alloc failed\n", __func__);
1712 		error = ENOMEM;
1713 		goto out;
1714 	}
1715 	cm->cm_data = page;
1716 
1717 	/*
1718 	 * This page must be polled because the IOC isn't ready yet when this
1719 	 * page is needed.
1720 	 */
1721 	error = mpr_request_polled(sc, &cm);
1722 	if (cm != NULL)
1723 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1724 	if (error || (reply == NULL)) {
1725 		/* FIXME */
1726 		/* If the poll returns error then we need to do diag reset */
1727 		printf("%s: poll for page completed with error %d\n",
1728 		    __func__, error);
1729 		error = ENXIO;
1730 		goto out;
1731 	}
1732 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1733 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1734 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1735 		/* FIXME */
1736 		/* If the poll returns error then we need to do diag reset */
1737 		printf("%s: page read with error; iocstatus = 0x%x\n",
1738 		    __func__, ioc_status);
1739 		error = ENXIO;
1740 		goto out;
1741 	}
1742 	bcopy(page, config_page, MIN(cm->cm_length,
1743 	    sizeof(Mpi2RaidPhysDiskPage0_t)));
1744 out:
1745 	free(page, M_MPR);
1746 	if (cm)
1747 		mpr_free_command(sc, cm);
1748 	return (error);
1749 }
1750