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