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