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