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