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