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