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