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