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