2 * Copyright (c) 2011 LSI Corp.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * LSI MPT-Fusion Host Adapter FreeBSD
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 /* TODO Move headers to mpsvar */
33 #include <sys/types.h>
34 #include <sys/param.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>
43 #include <sys/endian.h>
44 #include <sys/sysctl.h>
45 #include <sys/eventhandler.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>
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
66 * Returns 0 for success, non-zero for failure.
69 mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
70 Mpi2IOCPage8_t *config_page)
72 MPI2_CONFIG_REQUEST *request;
73 MPI2_CONFIG_REPLY *reply;
74 struct mps_command *cm;
75 MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
79 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
81 if ((cm = mps_alloc_command(sc)) == NULL) {
82 printf("%s: command alloc failed @ line %d\n", __func__,
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;
96 error = mps_request_polled(sc, cm);
97 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
98 if (error || (reply == NULL)) {
100 /* If the poll returns error then we need to do diag reset */
101 printf("%s: poll for header completed with error %d",
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) {
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);
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.
119 mps_free_command(sc, cm);
121 if ((cm = mps_alloc_command(sc)) == NULL) {
122 printf("%s: command alloc failed @ line %d\n", __func__,
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);
142 printf("%s: page alloc failed\n", __func__);
147 error = mps_request_polled(sc, cm);
148 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
149 if (error || (reply == NULL)) {
151 /* If the poll returns error then we need to do diag reset */
152 printf("%s: poll for page completed with error %d",
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) {
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);
167 bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
172 mps_free_command(sc, cm);
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
183 * Returns 0 for success, non-zero for failure.
186 mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
188 MPI2_CONFIG_REQUEST *request;
189 MPI2_CONFIG_REPLY *reply;
190 struct mps_command *cm;
191 pMpi2ManufacturingPagePS_t page = NULL;
193 uint8_t OEM_Value = 0;
197 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
199 if ((cm = mps_alloc_command(sc)) == NULL) {
200 printf("%s: command alloc failed @ line %d\n", __func__,
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;
214 error = mps_request_polled(sc, cm);
215 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
216 if (error || (reply == NULL)) {
218 /* If the poll returns error then we need to do diag reset */
219 printf("%s: poll for header completed with error %d",
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) {
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);
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.
237 mps_free_command(sc, cm);
239 if ((cm = mps_alloc_command(sc)) == NULL) {
240 printf("%s: command alloc failed @ line %d\n", __func__,
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);
260 printf("%s: page alloc failed\n", __func__);
265 error = mps_request_polled(sc, cm);
266 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
267 if (error || (reply == NULL)) {
269 /* If the poll returns error then we need to do diag reset */
270 printf("%s: poll for page completed with error %d",
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) {
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);
287 * If OEM ID is unknown, fail the request.
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);
299 * Set the phys disks hide/expose value.
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);
316 mps_free_command(sc, cm);
321 * mps_base_static_config_pages - static start of day config pages.
322 * @sc: per adapter object
327 mps_base_static_config_pages(struct mps_softc *sc)
329 Mpi2ConfigReply_t mpi_reply;
333 while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
336 /* We need to Handle this situation */
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
351 mps_wd_config_pages(struct mps_softc *sc)
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;
359 uint8_t index, stripe_exp = 0, block_exp = 0;
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.
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;
380 * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
382 raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) +
383 (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
384 M_MPT2, M_ZERO | M_NOWAIT);
386 printf("%s: page alloc failed\n", __func__);
390 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
392 mps_dprint(sc, MPS_INFO,
393 "mps_config_get_raid_volume_pg0 failed! Assuming "
394 "WarpDrive IT mode.\n");
399 * Check for valid WD configuration:
400 * volume type is RAID0
401 * number of phys disks in the volume is no more than 8
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");
412 * Save the WD RAID data to be used during WD I/O.
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;
422 * Find power of 2 of stripe size and set this as the exponent.
423 * Fail if stripe size is 0.
425 stripe_size = raid_vol_pg0->StripeSize;
426 for (index = 0; index < 32; index++) {
433 mps_dprint(sc, MPS_FAULT,
434 "RAID Volume's stripe size is 0. Direct Drive I/O "
435 "will not be used.\n");
438 sc->DD_stripe_exponent = stripe_exp;
441 * Find power of 2 of block size and set this as the exponent.
442 * Fail if block size is 0.
444 block_size = raid_vol_pg0->BlockSize;
445 for (index = 0; index < 16; index++) {
452 mps_dprint(sc, MPS_FAULT,
453 "RAID Volume's block size is 0. Direct Drive I/O "
454 "will not be used.\n");
457 sc->DD_block_exponent = block_exp;
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.
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 =
472 * Get second RAID Volume Page0 using previous handle. This
473 * page should not exist. If it does, must not proceed with WD
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");
486 mps_dprint(sc, MPS_FAULT,
487 "Multiple volumes! Direct Drive I/O will not be "
493 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
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");
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");
512 sc->DD_column_map[index].dev_handle =
513 phys_disk_pg0.DevHandle;
515 sc->WD_valid_config = TRUE;
518 free(raid_vol_pg0, M_MPT2);
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
530 * Returns 0 for success, non-zero for failure.
533 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
534 Mpi2DriverMappingPage0_t *config_page, u16 sz)
536 MPI2_CONFIG_REQUEST *request;
537 MPI2_CONFIG_REPLY *reply;
538 struct mps_command *cm;
539 Mpi2DriverMappingPage0_t *page = NULL;
543 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
545 memset(config_page, 0, sz);
546 if ((cm = mps_alloc_command(sc)) == NULL) {
547 printf("%s: command alloc failed @ line %d\n", __func__,
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;
564 error = mps_request_polled(sc, cm);
565 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
566 if (error || (reply == NULL)) {
568 /* If the poll returns error then we need to do diag reset */
569 printf("%s: poll for header completed with error %d",
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) {
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);
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.
587 mps_free_command(sc, cm);
589 if ((cm = mps_alloc_command(sc)) == NULL) {
590 printf("%s: command alloc failed @ line %d\n", __func__,
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);
613 printf("%s: page alloc failed\n", __func__);
618 error = mps_request_polled(sc, cm);
619 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
620 if (error || (reply == NULL)) {
622 /* If the poll returns error then we need to do diag reset */
623 printf("%s: poll for page completed with error %d",
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) {
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);
638 bcopy(page, config_page, MIN(cm->cm_length, sz));
642 mps_free_command(sc, cm);
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
654 * Returns 0 for success, non-zero for failure.
657 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
658 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
660 MPI2_CONFIG_REQUEST *request;
661 MPI2_CONFIG_REPLY *reply;
662 struct mps_command *cm;
663 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
667 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
669 if ((cm = mps_alloc_command(sc)) == NULL) {
670 printf("%s: command alloc failed @ line %d\n", __func__,
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 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
684 request->PageAddress |= htole16(entry_idx);
685 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
687 error = mps_request_polled(sc, cm);
688 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
689 if (error || (reply == NULL)) {
691 /* If the poll returns error then we need to do diag reset */
692 printf("%s: poll for header completed with error %d",
697 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
698 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
699 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
701 /* If the poll returns error then we need to do diag reset */
702 printf("%s: header read with error; iocstatus = 0x%x\n",
703 __func__, ioc_status);
707 /* We have to do free and alloc for the reply-free and reply-post
708 * counters to match - Need to review the reply FIFO handling.
710 mps_free_command(sc, cm);
712 if ((cm = mps_alloc_command(sc)) == NULL) {
713 printf("%s: command alloc failed @ line %d\n", __func__,
718 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
719 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
720 request->Function = MPI2_FUNCTION_CONFIG;
721 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
722 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
723 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
724 request->Header.PageNumber = 0;
725 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
726 request->ExtPageLength = mpi_reply->ExtPageLength;
727 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
728 request->PageAddress |= htole16(entry_idx);
729 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
730 cm->cm_sge = &request->PageBufferSGE;
731 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
732 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
733 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
734 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
736 printf("%s: page alloc failed\n", __func__);
740 bcopy(config_page, page, MIN(cm->cm_length,
741 (sizeof(Mpi2DriverMappingPage0_t))));
743 error = mps_request_polled(sc, cm);
744 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
745 if (error || (reply == NULL)) {
747 /* If the poll returns error then we need to do diag reset */
748 printf("%s: poll for page completed with error %d",
753 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
754 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
755 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
757 /* If the poll returns error then we need to do diag reset */
758 printf("%s: page written with error; iocstatus = 0x%x\n",
759 __func__, ioc_status);
766 mps_free_command(sc, cm);
771 * mps_config_get_sas_device_pg0 - obtain sas device page 0
772 * @sc: per adapter object
773 * @mpi_reply: reply mf payload returned from firmware
774 * @config_page: contents of the config page
775 * @form: GET_NEXT_HANDLE or HANDLE
776 * @handle: device handle
779 * Returns 0 for success, non-zero for failure.
782 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
783 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
785 MPI2_CONFIG_REQUEST *request;
786 MPI2_CONFIG_REPLY *reply;
787 struct mps_command *cm;
788 Mpi2SasDevicePage0_t *page = NULL;
792 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
794 if ((cm = mps_alloc_command(sc)) == NULL) {
795 printf("%s: command alloc failed @ line %d\n", __func__,
800 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
801 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
802 request->Function = MPI2_FUNCTION_CONFIG;
803 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
804 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
805 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
806 request->Header.PageNumber = 0;
807 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
808 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
810 error = mps_request_polled(sc, cm);
811 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
812 if (error || (reply == NULL)) {
814 /* If the poll returns error then we need to do diag reset */
815 printf("%s: poll for header completed with error %d",
820 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
821 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
822 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
824 /* If the poll returns error then we need to do diag reset */
825 printf("%s: header read with error; iocstatus = 0x%x\n",
826 __func__, ioc_status);
830 /* We have to do free and alloc for the reply-free and reply-post
831 * counters to match - Need to review the reply FIFO handling.
833 mps_free_command(sc, cm);
835 if ((cm = mps_alloc_command(sc)) == NULL) {
836 printf("%s: command alloc failed @ line %d\n", __func__,
841 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
842 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
843 request->Function = MPI2_FUNCTION_CONFIG;
844 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
845 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
846 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
847 request->Header.PageNumber = 0;
848 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
849 request->ExtPageLength = mpi_reply->ExtPageLength;
850 request->PageAddress = htole32(form | handle);
851 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
852 cm->cm_sge = &request->PageBufferSGE;
853 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
854 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
855 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
856 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
858 printf("%s: page alloc failed\n", __func__);
864 error = mps_request_polled(sc, cm);
865 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
866 if (error || (reply == NULL)) {
868 /* If the poll returns error then we need to do diag reset */
869 printf("%s: poll for page completed with error %d",
874 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
875 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
876 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
878 /* If the poll returns error then we need to do diag reset */
879 printf("%s: page read with error; iocstatus = 0x%x\n",
880 __func__, ioc_status);
884 bcopy(page, config_page, MIN(cm->cm_length,
885 sizeof(Mpi2SasDevicePage0_t)));
889 mps_free_command(sc, cm);
894 * mps_config_get_bios_pg3 - obtain BIOS page 3
895 * @sc: per adapter object
896 * @mpi_reply: reply mf payload returned from firmware
897 * @config_page: contents of the config page
900 * Returns 0 for success, non-zero for failure.
903 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
904 Mpi2BiosPage3_t *config_page)
906 MPI2_CONFIG_REQUEST *request;
907 MPI2_CONFIG_REPLY *reply;
908 struct mps_command *cm;
909 Mpi2BiosPage3_t *page = NULL;
913 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
915 if ((cm = mps_alloc_command(sc)) == NULL) {
916 printf("%s: command alloc failed @ line %d\n", __func__,
921 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
922 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
923 request->Function = MPI2_FUNCTION_CONFIG;
924 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
925 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
926 request->Header.PageNumber = 3;
927 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
928 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
930 error = mps_request_polled(sc, cm);
931 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
932 if (error || (reply == NULL)) {
934 /* If the poll returns error then we need to do diag reset */
935 printf("%s: poll for header completed with error %d",
940 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
941 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
942 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
944 /* If the poll returns error then we need to do diag reset */
945 printf("%s: header read with error; iocstatus = 0x%x\n",
946 __func__, ioc_status);
950 /* We have to do free and alloc for the reply-free and reply-post
951 * counters to match - Need to review the reply FIFO handling.
953 mps_free_command(sc, cm);
955 if ((cm = mps_alloc_command(sc)) == NULL) {
956 printf("%s: command alloc failed @ line %d\n", __func__,
961 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
962 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
963 request->Function = MPI2_FUNCTION_CONFIG;
964 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
965 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
966 request->Header.PageNumber = 3;
967 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
968 request->Header.PageLength = mpi_reply->Header.PageLength;
969 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
970 cm->cm_sge = &request->PageBufferSGE;
971 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
972 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
973 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
974 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
976 printf("%s: page alloc failed\n", __func__);
982 error = mps_request_polled(sc, cm);
983 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
984 if (error || (reply == NULL)) {
986 /* If the poll returns error then we need to do diag reset */
987 printf("%s: poll for page completed with error %d",
992 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
993 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
994 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
996 /* If the poll returns error then we need to do diag reset */
997 printf("%s: page read with error; iocstatus = 0x%x\n",
998 __func__, ioc_status);
1002 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1006 mps_free_command(sc, cm);
1011 * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1012 * @sc: per adapter object
1013 * @mpi_reply: reply mf payload returned from firmware
1014 * @config_page: contents of the config page
1015 * @page_address: form and handle value used to get page
1018 * Returns 0 for success, non-zero for failure.
1021 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1022 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1024 MPI2_CONFIG_REQUEST *request;
1025 MPI2_CONFIG_REPLY *reply;
1026 struct mps_command *cm;
1027 Mpi2RaidVolPage0_t *page = NULL;
1031 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1033 if ((cm = mps_alloc_command(sc)) == NULL) {
1034 printf("%s: command alloc failed @ line %d\n", __func__,
1039 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1040 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1041 request->Function = MPI2_FUNCTION_CONFIG;
1042 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1043 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1044 request->Header.PageNumber = 0;
1045 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1046 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1048 error = mps_request_polled(sc, cm);
1049 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1050 if (error || (reply == NULL)) {
1052 /* If the poll returns error then we need to do diag reset */
1053 printf("%s: poll for header completed with error %d",
1058 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1059 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1060 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1062 /* If the poll returns error then we need to do diag reset */
1063 printf("%s: header read with error; iocstatus = 0x%x\n",
1064 __func__, ioc_status);
1068 /* We have to do free and alloc for the reply-free and reply-post
1069 * counters to match - Need to review the reply FIFO handling.
1071 mps_free_command(sc, cm);
1073 if ((cm = mps_alloc_command(sc)) == NULL) {
1074 printf("%s: command alloc failed @ line %d\n", __func__,
1079 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1080 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1081 request->Function = MPI2_FUNCTION_CONFIG;
1082 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1083 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1084 request->Header.PageNumber = 0;
1085 request->Header.PageLength = mpi_reply->Header.PageLength;
1086 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1087 request->PageAddress = page_address;
1088 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1089 cm->cm_sge = &request->PageBufferSGE;
1090 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1091 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1092 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1093 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1095 printf("%s: page alloc failed\n", __func__);
1101 error = mps_request_polled(sc, cm);
1102 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1103 if (error || (reply == NULL)) {
1105 /* If the poll returns error then we need to do diag reset */
1106 printf("%s: poll for page completed with error %d",
1111 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1112 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1113 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1115 /* If the poll returns error then we need to do diag reset */
1116 printf("%s: page read with error; iocstatus = 0x%x\n",
1117 __func__, ioc_status);
1121 bcopy(page, config_page, cm->cm_length);
1125 mps_free_command(sc, cm);
1130 * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1131 * @sc: per adapter object
1132 * @mpi_reply: reply mf payload returned from firmware
1133 * @config_page: contents of the config page
1134 * @form: GET_NEXT_HANDLE or HANDLE
1135 * @handle: volume handle
1138 * Returns 0 for success, non-zero for failure.
1141 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1142 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1144 MPI2_CONFIG_REQUEST *request;
1145 MPI2_CONFIG_REPLY *reply;
1146 struct mps_command *cm;
1147 Mpi2RaidVolPage1_t *page = NULL;
1151 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1153 if ((cm = mps_alloc_command(sc)) == NULL) {
1154 printf("%s: command alloc failed @ line %d\n", __func__,
1159 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1160 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1161 request->Function = MPI2_FUNCTION_CONFIG;
1162 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1163 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1164 request->Header.PageNumber = 1;
1165 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1166 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1168 error = mps_request_polled(sc, cm);
1169 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1170 if (error || (reply == NULL)) {
1172 /* If the poll returns error then we need to do diag reset */
1173 printf("%s: poll for header completed with error %d",
1178 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1179 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1180 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1182 /* If the poll returns error then we need to do diag reset */
1183 printf("%s: header read with error; iocstatus = 0x%x\n",
1184 __func__, ioc_status);
1188 /* We have to do free and alloc for the reply-free and reply-post
1189 * counters to match - Need to review the reply FIFO handling.
1191 mps_free_command(sc, cm);
1193 if ((cm = mps_alloc_command(sc)) == NULL) {
1194 printf("%s: command alloc failed @ line %d\n", __func__,
1199 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1200 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1201 request->Function = MPI2_FUNCTION_CONFIG;
1202 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1203 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1204 request->Header.PageNumber = 1;
1205 request->Header.PageLength = mpi_reply->Header.PageLength;
1206 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1207 request->PageAddress = htole32(form | handle);
1208 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1209 cm->cm_sge = &request->PageBufferSGE;
1210 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1211 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1212 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1213 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1215 printf("%s: page alloc failed\n", __func__);
1221 error = mps_request_polled(sc, cm);
1222 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1223 if (error || (reply == NULL)) {
1225 /* If the poll returns error then we need to do diag reset */
1226 printf("%s: poll for page completed with error %d",
1231 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1232 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1233 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1235 /* If the poll returns error then we need to do diag reset */
1236 printf("%s: page read with error; iocstatus = 0x%x\n",
1237 __func__, ioc_status);
1241 bcopy(page, config_page, MIN(cm->cm_length,
1242 sizeof(Mpi2RaidVolPage1_t)));
1246 mps_free_command(sc, cm);
1251 * mps_config_get_volume_wwid - returns wwid given the volume handle
1252 * @sc: per adapter object
1253 * @volume_handle: volume handle
1254 * @wwid: volume wwid
1257 * Returns 0 for success, non-zero for failure.
1260 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1262 Mpi2ConfigReply_t mpi_reply;
1263 Mpi2RaidVolPage1_t raid_vol_pg1;
1266 if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1267 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1268 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1269 raid_vol_pg1.WWID.Low);
1276 * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1277 * @sc: per adapter object
1278 * @mpi_reply: reply mf payload returned from firmware
1279 * @config_page: contents of the config page
1280 * @page_address: form and handle value used to get page
1283 * Returns 0 for success, non-zero for failure.
1286 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1287 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1289 MPI2_CONFIG_REQUEST *request;
1290 MPI2_CONFIG_REPLY *reply;
1291 struct mps_command *cm;
1292 Mpi2RaidPhysDiskPage0_t *page = NULL;
1296 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1298 if ((cm = mps_alloc_command(sc)) == NULL) {
1299 printf("%s: command alloc failed @ line %d\n", __func__,
1304 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1305 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1306 request->Function = MPI2_FUNCTION_CONFIG;
1307 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1308 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1309 request->Header.PageNumber = 0;
1310 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1311 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1313 error = mps_request_polled(sc, cm);
1314 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1315 if (error || (reply == NULL)) {
1317 /* If the poll returns error then we need to do diag reset */
1318 printf("%s: poll for header completed with error %d",
1323 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1324 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1325 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1327 /* If the poll returns error then we need to do diag reset */
1328 printf("%s: header read with error; iocstatus = 0x%x\n",
1329 __func__, ioc_status);
1333 /* We have to do free and alloc for the reply-free and reply-post
1334 * counters to match - Need to review the reply FIFO handling.
1336 mps_free_command(sc, cm);
1338 if ((cm = mps_alloc_command(sc)) == NULL) {
1339 printf("%s: command alloc failed @ line %d\n", __func__,
1344 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1345 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1346 request->Function = MPI2_FUNCTION_CONFIG;
1347 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1348 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1349 request->Header.PageNumber = 0;
1350 request->Header.PageLength = mpi_reply->Header.PageLength;
1351 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1352 request->PageAddress = page_address;
1353 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1354 cm->cm_sge = &request->PageBufferSGE;
1355 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1356 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1357 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1358 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1360 printf("%s: page alloc failed\n", __func__);
1366 error = mps_request_polled(sc, cm);
1367 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1368 if (error || (reply == NULL)) {
1370 /* If the poll returns error then we need to do diag reset */
1371 printf("%s: poll for page completed with error %d",
1376 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1377 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1378 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1380 /* If the poll returns error then we need to do diag reset */
1381 printf("%s: page read with error; iocstatus = 0x%x\n",
1382 __func__, ioc_status);
1386 bcopy(page, config_page, MIN(cm->cm_length,
1387 sizeof(Mpi2RaidPhysDiskPage0_t)));
1391 mps_free_command(sc, cm);