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