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