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