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