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