xref: /freebsd/sys/dev/mps/mps_config.c (revision 273c26a3c3bea87a241d6879abd4f991db180bf0)
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 mpsvar */
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/mps/mpi/mpi2_type.h>
51 #include <dev/mps/mpi/mpi2.h>
52 #include <dev/mps/mpi/mpi2_ioc.h>
53 #include <dev/mps/mpi/mpi2_sas.h>
54 #include <dev/mps/mpi/mpi2_cnfg.h>
55 #include <dev/mps/mpi/mpi2_init.h>
56 #include <dev/mps/mpi/mpi2_tool.h>
57 #include <dev/mps/mps_ioctl.h>
58 #include <dev/mps/mpsvar.h>
59 
60 /**
61  * mps_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 mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
71     Mpi2IOCPage8_t *config_page)
72 {
73 	MPI2_CONFIG_REQUEST *request;
74 	MPI2_CONFIG_REPLY *reply;
75 	struct mps_command *cm;
76 	MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
77 	int error = 0;
78 	u16 ioc_status;
79 
80 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
81 
82 	if ((cm = mps_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 = mps_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 	mps_free_command(sc, cm);
127 
128 	if ((cm = mps_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 = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
146 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
147 	page = malloc((cm->cm_length), M_MPT2, 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 = mps_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_MPT2);
185 	if (cm)
186 		mps_free_command(sc, cm);
187 	return (error);
188 }
189 
190 /**
191  * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
192  *   accordingly.  Currently, this page does not need to return to caller.
193  * @sc: per adapter object
194  * @mpi_reply: reply mf payload returned from firmware
195  * Context: sleep.
196  *
197  * Returns 0 for success, non-zero for failure.
198  */
199 int
200 mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
201 {
202 	MPI2_CONFIG_REQUEST *request;
203 	MPI2_CONFIG_REPLY *reply;
204 	struct mps_command *cm;
205 	pMpi2ManufacturingPagePS_t page = NULL;
206 	uint32_t *pPS_info;
207 	uint8_t OEM_Value = 0;
208 	int error = 0;
209 	u16 ioc_status;
210 
211 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
212 
213 	if ((cm = mps_alloc_command(sc)) == NULL) {
214 		printf("%s: command alloc failed @ line %d\n", __func__,
215 		    __LINE__);
216 		error = EBUSY;
217 		goto out;
218 	}
219 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
220 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
221 	request->Function = MPI2_FUNCTION_CONFIG;
222 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
223 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
224 	request->Header.PageNumber = 10;
225 	request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
226 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
227 	cm->cm_data = NULL;
228 
229 	/*
230 	 * This page must be polled because the IOC isn't ready yet when this
231 	 * page is needed.
232 	 */
233 	error = mps_wait_command(sc, cm, 60, 0);
234 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
235 	if (error || (reply == NULL)) {
236 		/* FIXME */
237 		/* If the poll returns error then we need to do diag reset */
238 		printf("%s: poll for header completed with error %d",
239 		    __func__, error);
240 		error = ENXIO;
241 		goto out;
242 	}
243 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
244 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
245 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
246 		/* FIXME */
247 		/* If the poll returns error then we need to do diag reset */
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 	mps_free_command(sc, cm);
257 
258 	if ((cm = mps_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_MANUFACTURING;
269 	request->Header.PageNumber = 10;
270 	request->Header.PageVersion = MPI2_MANUFACTURING10_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 = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
276 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
277 	page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, 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 	/*
286 	 * This page must be polled because the IOC isn't ready yet when this
287 	 * page is needed.
288 	 */
289 	error = mps_wait_command(sc, cm, 60, 0);
290 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
291 	if (error || (reply == NULL)) {
292 		/* FIXME */
293 		/* If the poll returns error then we need to do diag reset */
294 		printf("%s: poll 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 		/* If the poll returns error then we need to do diag reset */
304 		printf("%s: page read with error; iocstatus = 0x%x\n",
305 		    __func__, ioc_status);
306 		error = ENXIO;
307 		goto out;
308 	}
309 
310 	/*
311 	 * If OEM ID is unknown, fail the request.
312 	 */
313 	sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
314 	OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
315 	if (OEM_Value != MPS_WD_LSI_OEM) {
316 		mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
317 		    "(0x%x)\n", OEM_Value);
318 		error = ENXIO;
319 		goto out;
320 	}
321 
322 	/*
323 	 * Set the phys disks hide/expose value.
324 	 */
325 	pPS_info = &page->ProductSpecificInfo;
326 	sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
327 	sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
328 	if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
329 	    (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
330 	    (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
331 		mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
332 		    "hide/expose: 0x%x\n", sc->WD_hide_expose);
333 		error = ENXIO;
334 		goto out;
335 	}
336 
337 out:
338 	free(page, M_MPT2);
339 	if (cm)
340 		mps_free_command(sc, cm);
341 	return (error);
342 }
343 
344 /**
345  * mps_base_static_config_pages - static start of day config pages.
346  * @sc: per adapter object
347  *
348  * Return nothing.
349  */
350 void
351 mps_base_static_config_pages(struct mps_softc *sc)
352 {
353 	Mpi2ConfigReply_t	mpi_reply;
354 	int			retry;
355 
356 	retry = 0;
357 	while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
358 		retry++;
359 		if (retry > 5) {
360 			/* We need to Handle this situation */
361 			/*FIXME*/
362 			break;
363 		}
364 	}
365 }
366 
367 /**
368  * mps_wd_config_pages - get info required to support WarpDrive.  This needs to
369  *    be called after discovery is complete to guarantee that IR info is there.
370  * @sc: per adapter object
371  *
372  * Return nothing.
373  */
374 void
375 mps_wd_config_pages(struct mps_softc *sc)
376 {
377 	Mpi2ConfigReply_t	mpi_reply;
378 	pMpi2RaidVolPage0_t	raid_vol_pg0 = NULL;
379 	Mpi2RaidPhysDiskPage0_t	phys_disk_pg0;
380 	pMpi2RaidVol0PhysDisk_t	pRVPD;
381 	uint32_t		stripe_size, phys_disk_page_address;
382 	uint16_t		block_size;
383 	uint8_t			index, stripe_exp = 0, block_exp = 0;
384 
385 	/*
386 	 * Get the WD settings from manufacturing page 10 if using a WD HBA.
387 	 * This will be used to determine if phys disks should always be
388 	 * hidden, hidden only if part of a WD volume, or never hidden.  Also,
389 	 * get the WD RAID Volume info and fail if volume does not exist or if
390 	 * volume does not meet the requirements for a WD volume.  No retry
391 	 * here.  Just default to HIDE ALWAYS if man Page10 fails, or clear WD
392 	 * Valid flag if Volume info fails.
393 	 */
394 	sc->WD_valid_config = FALSE;
395 	if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) {
396 		if (mps_config_get_man_pg10(sc, &mpi_reply)) {
397 			mps_dprint(sc, MPS_FAULT,
398 			    "mps_config_get_man_pg10 failed! Using 0 (Hide "
399 			    "Always) for WarpDrive hide/expose value.\n");
400 			sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
401 		}
402 
403 		/*
404 		 * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
405 		 */
406 		raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) +
407 		    (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
408 		    M_MPT2, M_ZERO | M_NOWAIT);
409 		if (!raid_vol_pg0) {
410 			printf("%s: page alloc failed\n", __func__);
411 			goto out;
412 		}
413 
414 		if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
415 		    0x0000FFFF)) {
416 			mps_dprint(sc, MPS_INFO,
417 			    "mps_config_get_raid_volume_pg0 failed! Assuming "
418 			    "WarpDrive IT mode.\n");
419 			goto out;
420 		}
421 
422 		/*
423 		 * Check for valid WD configuration:
424 		 *   volume type is RAID0
425 		 *   number of phys disks in the volume is no more than 8
426 		 */
427 		if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) ||
428 		    (raid_vol_pg0->NumPhysDisks > 8)) {
429 			mps_dprint(sc, MPS_FAULT,
430 			    "Invalid WarpDrive configuration. Direct Drive I/O "
431 			    "will not be used.\n");
432 			goto out;
433 		}
434 
435 		/*
436 		 * Save the WD RAID data to be used during WD I/O.
437 		 */
438 		sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High <<
439 		    32 | (uint64_t)raid_vol_pg0->MaxLBA.Low);
440 		sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks;
441 		sc->DD_dev_handle = raid_vol_pg0->DevHandle;
442 		sc->DD_stripe_size = raid_vol_pg0->StripeSize;
443 		sc->DD_block_size = raid_vol_pg0->BlockSize;
444 
445 		/*
446 		 * Find power of 2 of stripe size and set this as the exponent.
447 		 * Fail if stripe size is 0.
448 		 */
449 		stripe_size = raid_vol_pg0->StripeSize;
450 		for (index = 0; index < 32; index++) {
451 			if (stripe_size & 1)
452 				break;
453 			stripe_exp++;
454 			stripe_size >>= 1;
455 		}
456 		if (index == 32) {
457 			mps_dprint(sc, MPS_FAULT,
458 			    "RAID Volume's stripe size is 0. Direct Drive I/O "
459 			    "will not be used.\n");
460 			goto out;
461 		}
462 		sc->DD_stripe_exponent = stripe_exp;
463 
464 		/*
465 		 * Find power of 2 of block size and set this as the exponent.
466 		 * Fail if block size is 0.
467 		 */
468 		block_size = raid_vol_pg0->BlockSize;
469 		for (index = 0; index < 16; index++) {
470 			if (block_size & 1)
471 				break;
472 			block_exp++;
473 			block_size >>= 1;
474 		}
475 		if (index == 16) {
476 			mps_dprint(sc, MPS_FAULT,
477 			    "RAID Volume's block size is 0. Direct Drive I/O "
478 			    "will not be used.\n");
479 			goto out;
480 		}
481 		sc->DD_block_exponent = block_exp;
482 
483 		/*
484 		 * Loop through all of the volume's Phys Disks to map the phys
485 		 * disk number into the columm map.  This is used during Direct
486 		 * Drive I/O to send the request to the correct SSD.
487 		 */
488 		pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk;
489 		for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
490 			sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num =
491 			    pRVPD->PhysDiskNum;
492 			pRVPD++;
493 		}
494 
495 		/*
496 		 * Get second RAID Volume Page0 using previous handle.  This
497 		 * page should not exist.  If it does, must not proceed with WD
498 		 * handling.
499 		 */
500 		if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
501 		    raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
502 			if ((le16toh(mpi_reply.IOCStatus) &
503 			    MPI2_IOCSTATUS_MASK) !=
504 			    MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
505 				mps_dprint(sc, MPS_FAULT,
506 				    "Multiple RAID Volume Page0! Direct Drive "
507 				    "I/O will not be used.\n");
508 				goto out;
509 			}
510 		} else {
511 			mps_dprint(sc, MPS_FAULT,
512 			    "Multiple volumes! Direct Drive I/O will not be "
513 			    "used.\n");
514 			goto out;
515 		}
516 
517 		/*
518 		 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
519 		 */
520 		for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
521 			phys_disk_page_address =
522 			    MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
523 			    sc->DD_column_map[index].phys_disk_num;
524 			if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
525 			    &phys_disk_pg0, phys_disk_page_address)) {
526 				mps_dprint(sc, MPS_FAULT,
527 				    "mps_config_get_raid_pd_pg0 failed! Direct "
528 				    "Drive I/O will not be used.\n");
529 				goto out;
530 			}
531 			if (phys_disk_pg0.DevHandle == 0xFFFF) {
532 				mps_dprint(sc, MPS_FAULT,
533 				    "Invalid Phys Disk DevHandle! Direct Drive "
534 				    "I/O will not be used.\n");
535 				goto out;
536 			}
537 			sc->DD_column_map[index].dev_handle =
538 			    phys_disk_pg0.DevHandle;
539 		}
540 		sc->WD_valid_config = TRUE;
541 out:
542 		if (raid_vol_pg0)
543 			free(raid_vol_pg0, M_MPT2);
544 	}
545 }
546 
547 /**
548  * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
549  * @sc: per adapter object
550  * @mpi_reply: reply mf payload returned from firmware
551  * @config_page: contents of the config page
552  * @sz: size of buffer passed in config_page
553  * Context: sleep.
554  *
555  * Returns 0 for success, non-zero for failure.
556  */
557 int
558 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
559     Mpi2DriverMappingPage0_t *config_page, u16 sz)
560 {
561 	MPI2_CONFIG_REQUEST *request;
562 	MPI2_CONFIG_REPLY *reply;
563 	struct mps_command *cm;
564 	Mpi2DriverMappingPage0_t *page = NULL;
565 	int error = 0;
566 	u16 ioc_status;
567 
568 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
569 
570 	memset(config_page, 0, sz);
571 	if ((cm = mps_alloc_command(sc)) == NULL) {
572 		printf("%s: command alloc failed @ line %d\n", __func__,
573 		    __LINE__);
574 		error = EBUSY;
575 		goto out;
576 	}
577 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
578 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
579 	request->Function = MPI2_FUNCTION_CONFIG;
580 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
581 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
582 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
583 	request->Header.PageNumber = 0;
584 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
585 	request->PageAddress = sc->max_dpm_entries <<
586 	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
587 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
588 	cm->cm_data = NULL;
589 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
590 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
591 	if (error || (reply == NULL)) {
592 		/* FIXME */
593 		/*
594 		 * If the request returns an error then we need to do a diag
595 		 * reset
596 		 */
597 		printf("%s: request for header completed with error %d",
598 		    __func__, error);
599 		error = ENXIO;
600 		goto out;
601 	}
602 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
603 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
604 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
605 		/* FIXME */
606 		/*
607 		 * If the request returns an error then we need to do a diag
608 		 * reset
609 		 */
610 		printf("%s: header read with error; iocstatus = 0x%x\n",
611 		    __func__, ioc_status);
612 		error = ENXIO;
613 		goto out;
614 	}
615 	/* We have to do free and alloc for the reply-free and reply-post
616 	 * counters to match - Need to review the reply FIFO handling.
617 	 */
618 	mps_free_command(sc, cm);
619 
620 	if ((cm = mps_alloc_command(sc)) == NULL) {
621 		printf("%s: command alloc failed @ line %d\n", __func__,
622 		    __LINE__);
623 		error = EBUSY;
624 		goto out;
625 	}
626 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
627 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
628 	request->Function = MPI2_FUNCTION_CONFIG;
629 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
630 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
631 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
632 	request->Header.PageNumber = 0;
633 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
634 	request->PageAddress = sc->max_dpm_entries <<
635 	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
636 	request->ExtPageLength = mpi_reply->ExtPageLength;
637 	cm->cm_length =  le16toh(request->ExtPageLength) * 4;
638 	cm->cm_sge = &request->PageBufferSGE;
639 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
640 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
641 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
642 	page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT);
643 	if (!page) {
644 		printf("%s: page alloc failed\n", __func__);
645 		error = ENOMEM;
646 		goto out;
647 	}
648 	cm->cm_data = page;
649 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
650 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
651 	if (error || (reply == NULL)) {
652 		/* FIXME */
653 		/*
654 		 * If the request returns an error then we need to do a diag
655 		 * reset
656 		 */
657 		printf("%s: request for page completed with error %d",
658 		    __func__, error);
659 		error = ENXIO;
660 		goto out;
661 	}
662 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
663 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
664 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
665 		/* FIXME */
666 		/*
667 		 * If the request returns an error then we need to do a diag
668 		 * reset
669 		 */
670 		printf("%s: page read with error; iocstatus = 0x%x\n",
671 		    __func__, ioc_status);
672 		error = ENXIO;
673 		goto out;
674 	}
675 	bcopy(page, config_page, MIN(cm->cm_length, sz));
676 out:
677 	free(page, M_MPT2);
678 	if (cm)
679 		mps_free_command(sc, cm);
680 	return (error);
681 }
682 
683 /**
684  * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
685  * @sc: per adapter object
686  * @mpi_reply: reply mf payload returned from firmware
687  * @config_page: contents of the config page
688  * @entry_idx: entry index in DPM Page0 to be modified
689  * Context: sleep.
690  *
691  * Returns 0 for success, non-zero for failure.
692  */
693 
694 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
695     Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
696 {
697 	MPI2_CONFIG_REQUEST *request;
698 	MPI2_CONFIG_REPLY *reply;
699 	struct mps_command *cm;
700 	MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
701 	int error = 0;
702 	u16 ioc_status;
703 
704 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
705 
706 	if ((cm = mps_alloc_command(sc)) == NULL) {
707 		printf("%s: command alloc failed @ line %d\n", __func__,
708 		    __LINE__);
709 		error = EBUSY;
710 		goto out;
711 	}
712 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
713 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
714 	request->Function = MPI2_FUNCTION_CONFIG;
715 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
716 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
717 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
718 	request->Header.PageNumber = 0;
719 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
720 	/* We can remove below two lines ????*/
721 	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
722 	request->PageAddress |= htole16(entry_idx);
723 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
724 	cm->cm_data = NULL;
725 	error = mps_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 header 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: header read with error; iocstatus = 0x%x\n",
747 		    __func__, ioc_status);
748 		error = ENXIO;
749 		goto out;
750 	}
751 	/* We have to do free and alloc for the reply-free and reply-post
752 	 * counters to match - Need to review the reply FIFO handling.
753 	 */
754 	mps_free_command(sc, cm);
755 
756 	if ((cm = mps_alloc_command(sc)) == NULL) {
757 		printf("%s: command alloc failed @ line %d\n", __func__,
758 		    __LINE__);
759 		error = EBUSY;
760 		goto out;
761 	}
762 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
763 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
764 	request->Function = MPI2_FUNCTION_CONFIG;
765 	request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
766 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
767 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
768 	request->Header.PageNumber = 0;
769 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
770 	request->ExtPageLength = mpi_reply->ExtPageLength;
771 	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
772 	request->PageAddress |= htole16(entry_idx);
773 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
774 	cm->cm_sge = &request->PageBufferSGE;
775 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
776 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
777 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
778 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
779 	if (!page) {
780 		printf("%s: page alloc failed\n", __func__);
781 		error = ENOMEM;
782 		goto out;
783 	}
784 	bcopy(config_page, page, MIN(cm->cm_length,
785 	    (sizeof(Mpi2DriverMappingPage0_t))));
786 	cm->cm_data = page;
787 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
788 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
789 	if (error || (reply == NULL)) {
790 		/* FIXME */
791 		/*
792 		 * If the request returns an error then we need to do a diag
793 		 * reset
794 		 */
795 		printf("%s: request to write page completed with error %d",
796 		    __func__, error);
797 		error = ENXIO;
798 		goto out;
799 	}
800 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
801 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
802 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
803 		/* FIXME */
804 		/*
805 		 * If the request returns an error then we need to do a diag
806 		 * reset
807 		 */
808 		printf("%s: page written with error; iocstatus = 0x%x\n",
809 		    __func__, ioc_status);
810 		error = ENXIO;
811 		goto out;
812 	}
813 out:
814 	free(page, M_MPT2);
815 	if (cm)
816 		mps_free_command(sc, cm);
817 	return (error);
818 }
819 
820 /**
821  * mps_config_get_sas_device_pg0 - obtain sas device page 0
822  * @sc: per adapter object
823  * @mpi_reply: reply mf payload returned from firmware
824  * @config_page: contents of the config page
825  * @form: GET_NEXT_HANDLE or HANDLE
826  * @handle: device handle
827  * Context: sleep.
828  *
829  * Returns 0 for success, non-zero for failure.
830  */
831 int
832 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
833     *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
834 {
835 	MPI2_CONFIG_REQUEST *request;
836 	MPI2_CONFIG_REPLY *reply;
837 	struct mps_command *cm;
838 	Mpi2SasDevicePage0_t *page = NULL;
839 	int error = 0;
840 	u16 ioc_status;
841 
842 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
843 
844 	if ((cm = mps_alloc_command(sc)) == NULL) {
845 		printf("%s: command alloc failed @ line %d\n", __func__,
846 		    __LINE__);
847 		error = EBUSY;
848 		goto out;
849 	}
850 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
851 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
852 	request->Function = MPI2_FUNCTION_CONFIG;
853 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
854 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
855 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
856 	request->Header.PageNumber = 0;
857 	request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
858 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
859 	cm->cm_data = NULL;
860 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
861 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
862 	if (error || (reply == NULL)) {
863 		/* FIXME */
864 		/*
865 		 * If the request returns an error then we need to do a diag
866 		 * reset
867 		 */
868 		printf("%s: request for header completed with error %d",
869 		    __func__, error);
870 		error = ENXIO;
871 		goto out;
872 	}
873 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
874 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
875 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
876 		/* FIXME */
877 		/*
878 		 * If the request returns an error then we need to do a diag
879 		 * reset
880 		 */
881 		printf("%s: header read with error; iocstatus = 0x%x\n",
882 		    __func__, ioc_status);
883 		error = ENXIO;
884 		goto out;
885 	}
886 	/* We have to do free and alloc for the reply-free and reply-post
887 	 * counters to match - Need to review the reply FIFO handling.
888 	 */
889 	mps_free_command(sc, cm);
890 
891 	if ((cm = mps_alloc_command(sc)) == NULL) {
892 		printf("%s: command alloc failed @ line %d\n", __func__,
893 		    __LINE__);
894 		error = EBUSY;
895 		goto out;
896 	}
897 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
898 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
899 	request->Function = MPI2_FUNCTION_CONFIG;
900 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
901 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
902 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
903 	request->Header.PageNumber = 0;
904 	request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
905 	request->ExtPageLength = mpi_reply->ExtPageLength;
906 	request->PageAddress = htole32(form | handle);
907 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
908 	cm->cm_sge = &request->PageBufferSGE;
909 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
910 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
911 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
912 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
913 	if (!page) {
914 		printf("%s: page alloc failed\n", __func__);
915 		error = ENOMEM;
916 		goto out;
917 	}
918 	cm->cm_data = page;
919 
920 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
921 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
922 	if (error || (reply == NULL)) {
923 		/* FIXME */
924 		/*
925 		 * If the request returns an error then we need to do a diag
926 		 * reset
927 		 */
928 		printf("%s: request for page completed with error %d",
929 		    __func__, error);
930 		error = ENXIO;
931 		goto out;
932 	}
933 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
934 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
935 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
936 		/* FIXME */
937 		/*
938 		 * If the request returns an error then we need to do a diag
939 		 * reset
940 		 */
941 		printf("%s: page read with error; iocstatus = 0x%x\n",
942 		    __func__, ioc_status);
943 		error = ENXIO;
944 		goto out;
945 	}
946 	bcopy(page, config_page, MIN(cm->cm_length,
947 	    sizeof(Mpi2SasDevicePage0_t)));
948 out:
949 	free(page, M_MPT2);
950 	if (cm)
951 		mps_free_command(sc, cm);
952 	return (error);
953 }
954 
955 /**
956  * mps_config_get_bios_pg3 - obtain BIOS page 3
957  * @sc: per adapter object
958  * @mpi_reply: reply mf payload returned from firmware
959  * @config_page: contents of the config page
960  * Context: sleep.
961  *
962  * Returns 0 for success, non-zero for failure.
963  */
964 int
965 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
966     Mpi2BiosPage3_t *config_page)
967 {
968 	MPI2_CONFIG_REQUEST *request;
969 	MPI2_CONFIG_REPLY *reply;
970 	struct mps_command *cm;
971 	Mpi2BiosPage3_t *page = NULL;
972 	int error = 0;
973 	u16 ioc_status;
974 
975 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
976 
977 	if ((cm = mps_alloc_command(sc)) == NULL) {
978 		printf("%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_HEADER;
987 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
988 	request->Header.PageNumber = 3;
989 	request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
990 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
991 	cm->cm_data = NULL;
992 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
993 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
994 	if (error || (reply == NULL)) {
995 		/* FIXME */
996 		/*
997 		 * If the request returns an error then we need to do a diag
998 		 * reset
999 		 */
1000 		printf("%s: request for header completed with error %d",
1001 		    __func__, error);
1002 		error = ENXIO;
1003 		goto out;
1004 	}
1005 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1006 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1007 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1008 		/* FIXME */
1009 		/*
1010 		 * If the request returns an error then we need to do a diag
1011 		 * reset
1012 		 */
1013 		printf("%s: header read with error; iocstatus = 0x%x\n",
1014 		    __func__, ioc_status);
1015 		error = ENXIO;
1016 		goto out;
1017 	}
1018 	/* We have to do free and alloc for the reply-free and reply-post
1019 	 * counters to match - Need to review the reply FIFO handling.
1020 	 */
1021 	mps_free_command(sc, cm);
1022 
1023 	if ((cm = mps_alloc_command(sc)) == NULL) {
1024 		printf("%s: command alloc failed @ line %d\n", __func__,
1025 		    __LINE__);
1026 		error = EBUSY;
1027 		goto out;
1028 	}
1029 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1030 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1031 	request->Function = MPI2_FUNCTION_CONFIG;
1032 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1033 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1034 	request->Header.PageNumber = 3;
1035 	request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1036 	request->Header.PageLength = mpi_reply->Header.PageLength;
1037 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1038 	cm->cm_sge = &request->PageBufferSGE;
1039 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1040 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1041 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1042 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1043 	if (!page) {
1044 		printf("%s: page alloc failed\n", __func__);
1045 		error = ENOMEM;
1046 		goto out;
1047 	}
1048 	cm->cm_data = page;
1049 
1050 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1051 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1052 	if (error || (reply == NULL)) {
1053 		/* FIXME */
1054 		/*
1055 		 * If the request returns an error then we need to do a diag
1056 		 * reset
1057 		 */
1058 		printf("%s: request for page completed with error %d",
1059 		    __func__, error);
1060 		error = ENXIO;
1061 		goto out;
1062 	}
1063 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1064 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1065 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1066 		/* FIXME */
1067 		/*
1068 		 * If the request returns an error then we need to do a diag
1069 		 * reset
1070 		 */
1071 		printf("%s: page read with error; iocstatus = 0x%x\n",
1072 		    __func__, ioc_status);
1073 		error = ENXIO;
1074 		goto out;
1075 	}
1076 	bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1077 out:
1078 	free(page, M_MPT2);
1079 	if (cm)
1080 		mps_free_command(sc, cm);
1081 	return (error);
1082 }
1083 
1084 /**
1085  * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1086  * @sc: per adapter object
1087  * @mpi_reply: reply mf payload returned from firmware
1088  * @config_page: contents of the config page
1089  * @page_address: form and handle value used to get page
1090  * Context: sleep.
1091  *
1092  * Returns 0 for success, non-zero for failure.
1093  */
1094 int
1095 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1096     *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1097 {
1098 	MPI2_CONFIG_REQUEST *request;
1099 	MPI2_CONFIG_REPLY *reply;
1100 	struct mps_command *cm;
1101 	Mpi2RaidVolPage0_t *page = NULL;
1102 	int error = 0;
1103 	u16 ioc_status;
1104 
1105 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1106 
1107 	if ((cm = mps_alloc_command(sc)) == NULL) {
1108 		printf("%s: command alloc failed @ line %d\n", __func__,
1109 		    __LINE__);
1110 		error = EBUSY;
1111 		goto out;
1112 	}
1113 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1114 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1115 	request->Function = MPI2_FUNCTION_CONFIG;
1116 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1117 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1118 	request->Header.PageNumber = 0;
1119 	request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1120 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1121 	cm->cm_data = NULL;
1122 
1123 	/*
1124 	 * This page must be polled because the IOC isn't ready yet when this
1125 	 * page is needed.
1126 	 */
1127 	error = mps_wait_command(sc, cm, 60, 0);
1128 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1129 	if (error || (reply == NULL)) {
1130 		/* FIXME */
1131 		/* If the poll returns error then we need to do diag reset */
1132 		printf("%s: poll for header completed with error %d",
1133 		    __func__, error);
1134 		error = ENXIO;
1135 		goto out;
1136 	}
1137 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1138 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1139 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1140 		/* FIXME */
1141 		/* If the poll returns error then we need to do diag reset */
1142 		printf("%s: header read with error; iocstatus = 0x%x\n",
1143 		    __func__, ioc_status);
1144 		error = ENXIO;
1145 		goto out;
1146 	}
1147 	/* We have to do free and alloc for the reply-free and reply-post
1148 	 * counters to match - Need to review the reply FIFO handling.
1149 	 */
1150 	mps_free_command(sc, cm);
1151 
1152 	if ((cm = mps_alloc_command(sc)) == NULL) {
1153 		printf("%s: command alloc failed @ line %d\n", __func__,
1154 		    __LINE__);
1155 		error = EBUSY;
1156 		goto out;
1157 	}
1158 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1159 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1160 	request->Function = MPI2_FUNCTION_CONFIG;
1161 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1162 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1163 	request->Header.PageNumber = 0;
1164 	request->Header.PageLength = mpi_reply->Header.PageLength;
1165 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1166 	request->PageAddress = page_address;
1167 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1168 	cm->cm_sge = &request->PageBufferSGE;
1169 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1170 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1171 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1172 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1173 	if (!page) {
1174 		printf("%s: page alloc failed\n", __func__);
1175 		error = ENOMEM;
1176 		goto out;
1177 	}
1178 	cm->cm_data = page;
1179 
1180 	/*
1181 	 * This page must be polled because the IOC isn't ready yet when this
1182 	 * page is needed.
1183 	 */
1184 	error = mps_wait_command(sc, cm, 60, 0);
1185 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1186 	if (error || (reply == NULL)) {
1187 		/* FIXME */
1188 		/* If the poll returns error then we need to do diag reset */
1189 		printf("%s: poll for page completed with error %d",
1190 		    __func__, error);
1191 		error = ENXIO;
1192 		goto out;
1193 	}
1194 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1195 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1196 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1197 		/* FIXME */
1198 		/* If the poll returns error then we need to do diag reset */
1199 		printf("%s: page read with error; iocstatus = 0x%x\n",
1200 		    __func__, ioc_status);
1201 		error = ENXIO;
1202 		goto out;
1203 	}
1204 	bcopy(page, config_page, cm->cm_length);
1205 out:
1206 	free(page, M_MPT2);
1207 	if (cm)
1208 		mps_free_command(sc, cm);
1209 	return (error);
1210 }
1211 
1212 /**
1213  * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1214  * @sc: per adapter object
1215  * @mpi_reply: reply mf payload returned from firmware
1216  * @config_page: contents of the config page
1217  * @form: GET_NEXT_HANDLE or HANDLE
1218  * @handle: volume handle
1219  * Context: sleep.
1220  *
1221  * Returns 0 for success, non-zero for failure.
1222  */
1223 int
1224 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1225     *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1226 {
1227 	MPI2_CONFIG_REQUEST *request;
1228 	MPI2_CONFIG_REPLY *reply;
1229 	struct mps_command *cm;
1230 	Mpi2RaidVolPage1_t *page = NULL;
1231 	int error = 0;
1232 	u16 ioc_status;
1233 
1234 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1235 
1236 	if ((cm = mps_alloc_command(sc)) == NULL) {
1237 		printf("%s: command alloc failed @ line %d\n", __func__,
1238 		    __LINE__);
1239 		error = EBUSY;
1240 		goto out;
1241 	}
1242 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1243 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1244 	request->Function = MPI2_FUNCTION_CONFIG;
1245 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1246 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1247 	request->Header.PageNumber = 1;
1248 	request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1249 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1250 	cm->cm_data = NULL;
1251 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1252 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1253 	if (error || (reply == NULL)) {
1254 		/* FIXME */
1255 		/*
1256 		 * If the request returns an error then we need to do a diag
1257 		 * reset
1258 		 */
1259 		printf("%s: request for header completed with error %d",
1260 		    __func__, error);
1261 		error = ENXIO;
1262 		goto out;
1263 	}
1264 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1265 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1266 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1267 		/* FIXME */
1268 		/*
1269 		 * If the request returns an error then we need to do a diag
1270 		 * reset
1271 		 */
1272 		printf("%s: header read with error; iocstatus = 0x%x\n",
1273 		    __func__, ioc_status);
1274 		error = ENXIO;
1275 		goto out;
1276 	}
1277 	/* We have to do free and alloc for the reply-free and reply-post
1278 	 * counters to match - Need to review the reply FIFO handling.
1279 	 */
1280 	mps_free_command(sc, cm);
1281 
1282 	if ((cm = mps_alloc_command(sc)) == NULL) {
1283 		printf("%s: command alloc failed @ line %d\n", __func__,
1284 		    __LINE__);
1285 		error = EBUSY;
1286 		goto out;
1287 	}
1288 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1289 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1290 	request->Function = MPI2_FUNCTION_CONFIG;
1291 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1292 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1293 	request->Header.PageNumber = 1;
1294 	request->Header.PageLength = mpi_reply->Header.PageLength;
1295 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1296 	request->PageAddress = htole32(form | handle);
1297 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1298 	cm->cm_sge = &request->PageBufferSGE;
1299 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1300 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1301 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1302 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1303 	if (!page) {
1304 		printf("%s: page alloc failed\n", __func__);
1305 		error = ENOMEM;
1306 		goto out;
1307 	}
1308 	cm->cm_data = page;
1309 
1310 	error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1311 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1312 	if (error || (reply == NULL)) {
1313 		/* FIXME */
1314 		/*
1315 		 * If the request returns an error then we need to do a diag
1316 		 * reset
1317 		 */
1318 		printf("%s: request for page completed with error %d",
1319 		    __func__, error);
1320 		error = ENXIO;
1321 		goto out;
1322 	}
1323 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1324 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1325 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1326 		/* FIXME */
1327 		/*
1328 		 * If the request returns an error then we need to do a diag
1329 		 * reset
1330 		 */
1331 		printf("%s: page read with error; iocstatus = 0x%x\n",
1332 		    __func__, ioc_status);
1333 		error = ENXIO;
1334 		goto out;
1335 	}
1336 	bcopy(page, config_page, MIN(cm->cm_length,
1337 	    sizeof(Mpi2RaidVolPage1_t)));
1338 out:
1339 	free(page, M_MPT2);
1340 	if (cm)
1341 		mps_free_command(sc, cm);
1342 	return (error);
1343 }
1344 
1345 /**
1346  * mps_config_get_volume_wwid - returns wwid given the volume handle
1347  * @sc: per adapter object
1348  * @volume_handle: volume handle
1349  * @wwid: volume wwid
1350  * Context: sleep.
1351  *
1352  * Returns 0 for success, non-zero for failure.
1353  */
1354 int
1355 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1356 {
1357 	Mpi2ConfigReply_t mpi_reply;
1358 	Mpi2RaidVolPage1_t raid_vol_pg1;
1359 
1360 	*wwid = 0;
1361 	if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1362 	    MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1363 		*wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1364 		    raid_vol_pg1.WWID.Low);
1365 		return 0;
1366 	} else
1367 		return -1;
1368 }
1369 
1370 /**
1371  * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1372  * @sc: per adapter object
1373  * @mpi_reply: reply mf payload returned from firmware
1374  * @config_page: contents of the config page
1375  * @page_address: form and handle value used to get page
1376  * Context: sleep.
1377  *
1378  * Returns 0 for success, non-zero for failure.
1379  */
1380 int
1381 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1382     Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1383 {
1384 	MPI2_CONFIG_REQUEST *request;
1385 	MPI2_CONFIG_REPLY *reply;
1386 	struct mps_command *cm;
1387 	Mpi2RaidPhysDiskPage0_t *page = NULL;
1388 	int error = 0;
1389 	u16 ioc_status;
1390 
1391 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1392 
1393 	if ((cm = mps_alloc_command(sc)) == NULL) {
1394 		printf("%s: command alloc failed @ line %d\n", __func__,
1395 		    __LINE__);
1396 		error = EBUSY;
1397 		goto out;
1398 	}
1399 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1400 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1401 	request->Function = MPI2_FUNCTION_CONFIG;
1402 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1403 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1404 	request->Header.PageNumber = 0;
1405 	request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1406 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1407 	cm->cm_data = NULL;
1408 
1409 	/*
1410 	 * This page must be polled because the IOC isn't ready yet when this
1411 	 * page is needed.
1412 	 */
1413 	error = mps_wait_command(sc, cm, 60, 0);
1414 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1415 	if (error || (reply == NULL)) {
1416 		/* FIXME */
1417 		/* If the poll returns error then we need to do diag reset */
1418 		printf("%s: poll for header completed with error %d",
1419 		    __func__, error);
1420 		error = ENXIO;
1421 		goto out;
1422 	}
1423 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1424 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1425 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1426 		/* FIXME */
1427 		/* If the poll returns error then we need to do diag reset */
1428 		printf("%s: header read with error; iocstatus = 0x%x\n",
1429 		    __func__, ioc_status);
1430 		error = ENXIO;
1431 		goto out;
1432 	}
1433 	/* We have to do free and alloc for the reply-free and reply-post
1434 	 * counters to match - Need to review the reply FIFO handling.
1435 	 */
1436 	mps_free_command(sc, cm);
1437 
1438 	if ((cm = mps_alloc_command(sc)) == NULL) {
1439 		printf("%s: command alloc failed @ line %d\n", __func__,
1440 		    __LINE__);
1441 		error = EBUSY;
1442 		goto out;
1443 	}
1444 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1445 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1446 	request->Function = MPI2_FUNCTION_CONFIG;
1447 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1448 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1449 	request->Header.PageNumber = 0;
1450 	request->Header.PageLength = mpi_reply->Header.PageLength;
1451 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1452 	request->PageAddress = page_address;
1453 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1454 	cm->cm_sge = &request->PageBufferSGE;
1455 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1456 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1457 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1458 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1459 	if (!page) {
1460 		printf("%s: page alloc failed\n", __func__);
1461 		error = ENOMEM;
1462 		goto out;
1463 	}
1464 	cm->cm_data = page;
1465 
1466 	/*
1467 	 * This page must be polled because the IOC isn't ready yet when this
1468 	 * page is needed.
1469 	 */
1470 	error = mps_wait_command(sc, cm, 60, 0);
1471 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1472 	if (error || (reply == NULL)) {
1473 		/* FIXME */
1474 		/* If the poll returns error then we need to do diag reset */
1475 		printf("%s: poll for page completed with error %d",
1476 		    __func__, error);
1477 		error = ENXIO;
1478 		goto out;
1479 	}
1480 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1481 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1482 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1483 		/* FIXME */
1484 		/* If the poll returns error then we need to do diag reset */
1485 		printf("%s: page read with error; iocstatus = 0x%x\n",
1486 		    __func__, ioc_status);
1487 		error = ENXIO;
1488 		goto out;
1489 	}
1490 	bcopy(page, config_page, MIN(cm->cm_length,
1491 	    sizeof(Mpi2RaidPhysDiskPage0_t)));
1492 out:
1493 	free(page, M_MPT2);
1494 	if (cm)
1495 		mps_free_command(sc, cm);
1496 	return (error);
1497 }
1498