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