2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2011-2015 LSI Corp.
5 * Copyright (c) 2013-2015 Avago Technologies
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 /* TODO Move headers to mpsvar */
36 #include <sys/types.h>
37 #include <sys/param.h>
39 #include <sys/mutex.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/kthread.h>
44 #include <sys/taskqueue.h>
46 #include <sys/endian.h>
47 #include <sys/sysctl.h>
48 #include <sys/eventhandler.h>
50 #include <machine/bus.h>
51 #include <machine/resource.h>
52 #include <dev/mps/mpi/mpi2_type.h>
53 #include <dev/mps/mpi/mpi2.h>
54 #include <dev/mps/mpi/mpi2_ioc.h>
55 #include <dev/mps/mpi/mpi2_sas.h>
56 #include <dev/mps/mpi/mpi2_cnfg.h>
57 #include <dev/mps/mpi/mpi2_init.h>
58 #include <dev/mps/mpi/mpi2_tool.h>
59 #include <dev/mps/mps_ioctl.h>
60 #include <dev/mps/mpsvar.h>
63 * mps_config_get_ioc_pg8 - obtain ioc page 8
64 * @sc: per adapter object
65 * @mpi_reply: reply mf payload returned from firmware
66 * @config_page: contents of the config page
69 * Returns 0 for success, non-zero for failure.
72 mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
73 Mpi2IOCPage8_t *config_page)
75 MPI2_CONFIG_REQUEST *request;
76 MPI2_CONFIG_REPLY *reply = NULL;
77 struct mps_command *cm;
78 MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
82 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
84 if ((cm = mps_alloc_command(sc)) == NULL) {
85 printf("%s: command alloc failed @ line %d\n", __func__,
90 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
91 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
92 request->Function = MPI2_FUNCTION_CONFIG;
93 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
94 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
95 request->Header.PageNumber = 8;
96 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
97 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
99 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
101 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
102 if (error || (reply == NULL)) {
105 * If the request returns an error then we need to do a diag
108 printf("%s: request for header completed with error %d",
113 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
114 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
115 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
118 * If the request returns an error then we need to do a diag
121 printf("%s: header read with error; iocstatus = 0x%x\n",
122 __func__, ioc_status);
126 /* We have to do free and alloc for the reply-free and reply-post
127 * counters to match - Need to review the reply FIFO handling.
129 mps_free_command(sc, cm);
131 if ((cm = mps_alloc_command(sc)) == NULL) {
132 printf("%s: command alloc failed @ line %d\n", __func__,
137 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
138 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
139 request->Function = MPI2_FUNCTION_CONFIG;
140 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
141 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
142 request->Header.PageNumber = 8;
143 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
144 request->Header.PageLength = mpi_reply->Header.PageLength;
145 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
146 cm->cm_sge = &request->PageBufferSGE;
147 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
148 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
149 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
150 page = malloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT);
152 printf("%s: page alloc failed\n", __func__);
158 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
160 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
161 if (error || (reply == NULL)) {
164 * If the request returns an error then we need to do a diag
167 printf("%s: request for page completed with error %d",
172 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
173 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
174 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
177 * If the request returns an error then we need to do a diag
180 printf("%s: page read with error; iocstatus = 0x%x\n",
181 __func__, ioc_status);
185 bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
190 mps_free_command(sc, cm);
195 * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
196 * accordingly. Currently, this page does not need to return to caller.
197 * @sc: per adapter object
198 * @mpi_reply: reply mf payload returned from firmware
201 * Returns 0 for success, non-zero for failure.
204 mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
206 MPI2_CONFIG_REQUEST *request;
207 MPI2_CONFIG_REPLY *reply = NULL;
208 struct mps_command *cm;
209 pMpi2ManufacturingPagePS_t page = NULL;
211 uint8_t OEM_Value = 0;
215 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
217 if ((cm = mps_alloc_command(sc)) == NULL) {
218 printf("%s: command alloc failed @ line %d\n", __func__,
223 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
224 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
225 request->Function = MPI2_FUNCTION_CONFIG;
226 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
227 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
228 request->Header.PageNumber = 10;
229 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
230 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
234 * This page must be polled because the IOC isn't ready yet when this
237 error = mps_wait_command(sc, &cm, 60, 0);
239 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
240 if (error || (reply == NULL)) {
242 /* If the poll returns error then we need to do diag reset */
243 printf("%s: poll for header completed with error %d",
248 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
249 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
250 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
252 /* If the poll returns error then we need to do diag reset */
253 printf("%s: header read with error; iocstatus = 0x%x\n",
254 __func__, ioc_status);
258 /* We have to do free and alloc for the reply-free and reply-post
259 * counters to match - Need to review the reply FIFO handling.
261 mps_free_command(sc, cm);
263 if ((cm = mps_alloc_command(sc)) == NULL) {
264 printf("%s: command alloc failed @ line %d\n", __func__,
269 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
270 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
271 request->Function = MPI2_FUNCTION_CONFIG;
272 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
273 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
274 request->Header.PageNumber = 10;
275 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
276 request->Header.PageLength = mpi_reply->Header.PageLength;
277 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
278 cm->cm_sge = &request->PageBufferSGE;
279 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
280 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
281 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
282 page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT);
284 printf("%s: page alloc failed\n", __func__);
291 * This page must be polled because the IOC isn't ready yet when this
294 error = mps_wait_command(sc, &cm, 60, 0);
296 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
297 if (error || (reply == NULL)) {
299 /* If the poll returns error then we need to do diag reset */
300 printf("%s: poll for page completed with error %d",
305 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
306 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
307 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
309 /* If the poll returns error then we need to do diag reset */
310 printf("%s: page read with error; iocstatus = 0x%x\n",
311 __func__, ioc_status);
317 * If OEM ID is unknown, fail the request.
319 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
320 OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
321 if (OEM_Value != MPS_WD_LSI_OEM) {
322 mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
323 "(0x%x)\n", OEM_Value);
329 * Set the phys disks hide/expose value.
331 pPS_info = &page->ProductSpecificInfo;
332 sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
333 sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
334 if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
335 (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
336 (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
337 mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
338 "hide/expose: 0x%x\n", sc->WD_hide_expose);
346 mps_free_command(sc, cm);
351 * mps_base_static_config_pages - static start of day config pages.
352 * @sc: per adapter object
357 mps_base_static_config_pages(struct mps_softc *sc)
359 Mpi2ConfigReply_t mpi_reply;
363 while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
366 /* We need to Handle this situation */
374 * mps_wd_config_pages - get info required to support WarpDrive. This needs to
375 * be called after discovery is complete to guarantee that IR info is there.
376 * @sc: per adapter object
381 mps_wd_config_pages(struct mps_softc *sc)
383 Mpi2ConfigReply_t mpi_reply;
384 pMpi2RaidVolPage0_t raid_vol_pg0 = NULL;
385 Mpi2RaidPhysDiskPage0_t phys_disk_pg0;
386 pMpi2RaidVol0PhysDisk_t pRVPD;
387 uint32_t stripe_size, phys_disk_page_address;
389 uint8_t index, stripe_exp = 0, block_exp = 0;
392 * Get the WD settings from manufacturing page 10 if using a WD HBA.
393 * This will be used to determine if phys disks should always be
394 * hidden, hidden only if part of a WD volume, or never hidden. Also,
395 * get the WD RAID Volume info and fail if volume does not exist or if
396 * volume does not meet the requirements for a WD volume. No retry
397 * here. Just default to HIDE ALWAYS if man Page10 fails, or clear WD
398 * Valid flag if Volume info fails.
400 sc->WD_valid_config = FALSE;
401 if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) {
402 if (mps_config_get_man_pg10(sc, &mpi_reply)) {
403 mps_dprint(sc, MPS_FAULT,
404 "mps_config_get_man_pg10 failed! Using 0 (Hide "
405 "Always) for WarpDrive hide/expose value.\n");
406 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
410 * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
412 raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) +
413 (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
414 M_MPT2, M_ZERO | M_NOWAIT);
416 printf("%s: page alloc failed\n", __func__);
420 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
422 mps_dprint(sc, MPS_INFO,
423 "mps_config_get_raid_volume_pg0 failed! Assuming "
424 "WarpDrive IT mode.\n");
429 * Check for valid WD configuration:
430 * volume type is RAID0
431 * number of phys disks in the volume is no more than 8
433 if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) ||
434 (raid_vol_pg0->NumPhysDisks > 8)) {
435 mps_dprint(sc, MPS_FAULT,
436 "Invalid WarpDrive configuration. Direct Drive I/O "
437 "will not be used.\n");
442 * Save the WD RAID data to be used during WD I/O.
444 sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High <<
445 32 | (uint64_t)raid_vol_pg0->MaxLBA.Low);
446 sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks;
447 sc->DD_dev_handle = raid_vol_pg0->DevHandle;
448 sc->DD_stripe_size = raid_vol_pg0->StripeSize;
449 sc->DD_block_size = raid_vol_pg0->BlockSize;
452 * Find power of 2 of stripe size and set this as the exponent.
453 * Fail if stripe size is 0.
455 stripe_size = raid_vol_pg0->StripeSize;
456 for (index = 0; index < 32; index++) {
463 mps_dprint(sc, MPS_FAULT,
464 "RAID Volume's stripe size is 0. Direct Drive I/O "
465 "will not be used.\n");
468 sc->DD_stripe_exponent = stripe_exp;
471 * Find power of 2 of block size and set this as the exponent.
472 * Fail if block size is 0.
474 block_size = raid_vol_pg0->BlockSize;
475 for (index = 0; index < 16; index++) {
482 mps_dprint(sc, MPS_FAULT,
483 "RAID Volume's block size is 0. Direct Drive I/O "
484 "will not be used.\n");
487 sc->DD_block_exponent = block_exp;
490 * Loop through all of the volume's Phys Disks to map the phys
491 * disk number into the columm map. This is used during Direct
492 * Drive I/O to send the request to the correct SSD.
494 pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk;
495 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
496 sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num =
502 * Get second RAID Volume Page0 using previous handle. This
503 * page should not exist. If it does, must not proceed with WD
506 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
507 raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
508 if ((le16toh(mpi_reply.IOCStatus) &
509 MPI2_IOCSTATUS_MASK) !=
510 MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
511 mps_dprint(sc, MPS_FAULT,
512 "Multiple RAID Volume Page0! Direct Drive "
513 "I/O will not be used.\n");
517 mps_dprint(sc, MPS_FAULT,
518 "Multiple volumes! Direct Drive I/O will not be "
524 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
526 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
527 phys_disk_page_address =
528 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
529 sc->DD_column_map[index].phys_disk_num;
530 if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
531 &phys_disk_pg0, phys_disk_page_address)) {
532 mps_dprint(sc, MPS_FAULT,
533 "mps_config_get_raid_pd_pg0 failed! Direct "
534 "Drive I/O will not be used.\n");
537 if (phys_disk_pg0.DevHandle == 0xFFFF) {
538 mps_dprint(sc, MPS_FAULT,
539 "Invalid Phys Disk DevHandle! Direct Drive "
540 "I/O will not be used.\n");
543 sc->DD_column_map[index].dev_handle =
544 phys_disk_pg0.DevHandle;
546 sc->WD_valid_config = TRUE;
549 free(raid_vol_pg0, M_MPT2);
554 * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
555 * @sc: per adapter object
556 * @mpi_reply: reply mf payload returned from firmware
557 * @config_page: contents of the config page
558 * @sz: size of buffer passed in config_page
561 * Returns 0 for success, non-zero for failure.
564 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
565 Mpi2DriverMappingPage0_t *config_page, u16 sz)
567 MPI2_CONFIG_REQUEST *request;
568 MPI2_CONFIG_REPLY *reply = NULL;
569 struct mps_command *cm;
570 Mpi2DriverMappingPage0_t *page = NULL;
574 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
576 memset(config_page, 0, sz);
577 if ((cm = mps_alloc_command(sc)) == NULL) {
578 printf("%s: command alloc failed @ line %d\n", __func__,
583 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
584 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
585 request->Function = MPI2_FUNCTION_CONFIG;
586 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
587 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
588 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
589 request->Header.PageNumber = 0;
590 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
591 request->PageAddress = sc->max_dpm_entries <<
592 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
593 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
595 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
597 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
598 if (error || (reply == NULL)) {
601 * If the request returns an error then we need to do a diag
604 printf("%s: request for header completed with error %d",
609 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
610 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
611 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
614 * If the request returns an error then we need to do a diag
617 printf("%s: header read with error; iocstatus = 0x%x\n",
618 __func__, ioc_status);
622 /* We have to do free and alloc for the reply-free and reply-post
623 * counters to match - Need to review the reply FIFO handling.
625 mps_free_command(sc, cm);
627 if ((cm = mps_alloc_command(sc)) == NULL) {
628 printf("%s: command alloc failed @ line %d\n", __func__,
633 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
634 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
635 request->Function = MPI2_FUNCTION_CONFIG;
636 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
637 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
638 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
639 request->Header.PageNumber = 0;
640 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
641 request->PageAddress = sc->max_dpm_entries <<
642 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
643 request->ExtPageLength = mpi_reply->ExtPageLength;
644 cm->cm_length = le16toh(request->ExtPageLength) * 4;
645 cm->cm_sge = &request->PageBufferSGE;
646 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
647 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
648 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
649 page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT);
651 printf("%s: page alloc failed\n", __func__);
656 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
658 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
659 if (error || (reply == NULL)) {
662 * If the request returns an error then we need to do a diag
665 printf("%s: request for page completed with error %d",
670 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
671 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
672 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
675 * If the request returns an error then we need to do a diag
678 printf("%s: page read with error; iocstatus = 0x%x\n",
679 __func__, ioc_status);
683 bcopy(page, config_page, MIN(cm->cm_length, sz));
687 mps_free_command(sc, cm);
692 * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
693 * @sc: per adapter object
694 * @mpi_reply: reply mf payload returned from firmware
695 * @config_page: contents of the config page
696 * @entry_idx: entry index in DPM Page0 to be modified
699 * Returns 0 for success, non-zero for failure.
702 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
703 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
705 MPI2_CONFIG_REQUEST *request;
706 MPI2_CONFIG_REPLY *reply = NULL;
707 struct mps_command *cm;
708 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
712 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
714 if ((cm = mps_alloc_command(sc)) == NULL) {
715 printf("%s: command alloc failed @ line %d\n", __func__,
720 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
721 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
722 request->Function = MPI2_FUNCTION_CONFIG;
723 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
724 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
725 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
726 request->Header.PageNumber = 0;
727 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
728 /* We can remove below two lines ????*/
729 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
730 request->PageAddress |= htole16(entry_idx);
731 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
733 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
735 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
736 if (error || (reply == NULL)) {
739 * If the request returns an error then we need to do a diag
742 printf("%s: request for header completed with error %d",
747 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
748 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
749 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
752 * If the request returns an error then we need to do a diag
755 printf("%s: header read with error; iocstatus = 0x%x\n",
756 __func__, ioc_status);
760 /* We have to do free and alloc for the reply-free and reply-post
761 * counters to match - Need to review the reply FIFO handling.
763 mps_free_command(sc, cm);
765 if ((cm = mps_alloc_command(sc)) == NULL) {
766 printf("%s: command alloc failed @ line %d\n", __func__,
771 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
772 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
773 request->Function = MPI2_FUNCTION_CONFIG;
774 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
775 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
776 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
777 request->Header.PageNumber = 0;
778 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
779 request->ExtPageLength = mpi_reply->ExtPageLength;
780 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
781 request->PageAddress |= htole16(entry_idx);
782 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
783 cm->cm_sge = &request->PageBufferSGE;
784 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
785 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
786 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
787 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
789 printf("%s: page alloc failed\n", __func__);
793 bcopy(config_page, page, MIN(cm->cm_length,
794 (sizeof(Mpi2DriverMappingPage0_t))));
796 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
798 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
799 if (error || (reply == NULL)) {
802 * If the request returns an error then we need to do a diag
805 printf("%s: request to write page completed with error %d",
810 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
811 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
812 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
815 * If the request returns an error then we need to do a diag
818 printf("%s: page written with error; iocstatus = 0x%x\n",
819 __func__, ioc_status);
826 mps_free_command(sc, cm);
831 * mps_config_get_sas_device_pg0 - obtain sas device page 0
832 * @sc: per adapter object
833 * @mpi_reply: reply mf payload returned from firmware
834 * @config_page: contents of the config page
835 * @form: GET_NEXT_HANDLE or HANDLE
836 * @handle: device handle
839 * Returns 0 for success, non-zero for failure.
842 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
843 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
845 MPI2_CONFIG_REQUEST *request;
846 MPI2_CONFIG_REPLY *reply = NULL;
847 struct mps_command *cm;
848 Mpi2SasDevicePage0_t *page = NULL;
852 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
854 if ((cm = mps_alloc_command(sc)) == NULL) {
855 printf("%s: command alloc failed @ line %d\n", __func__,
860 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
861 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
862 request->Function = MPI2_FUNCTION_CONFIG;
863 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
864 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
865 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
866 request->Header.PageNumber = 0;
867 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
868 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
870 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
872 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
873 if (error || (reply == NULL)) {
876 * If the request returns an error then we need to do a diag
879 printf("%s: request for header completed with error %d",
884 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
885 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
886 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
889 * If the request returns an error then we need to do a diag
892 printf("%s: header read with error; iocstatus = 0x%x\n",
893 __func__, ioc_status);
897 /* We have to do free and alloc for the reply-free and reply-post
898 * counters to match - Need to review the reply FIFO handling.
900 mps_free_command(sc, cm);
902 if ((cm = mps_alloc_command(sc)) == NULL) {
903 printf("%s: command alloc failed @ line %d\n", __func__,
908 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
909 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
910 request->Function = MPI2_FUNCTION_CONFIG;
911 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
912 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
913 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
914 request->Header.PageNumber = 0;
915 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
916 request->ExtPageLength = mpi_reply->ExtPageLength;
917 request->PageAddress = htole32(form | handle);
918 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
919 cm->cm_sge = &request->PageBufferSGE;
920 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
921 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
922 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
923 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
925 printf("%s: page alloc failed\n", __func__);
931 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
933 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
934 if (error || (reply == NULL)) {
937 * If the request returns an error then we need to do a diag
940 printf("%s: request for page completed with error %d",
945 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
946 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
947 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
950 * If the request returns an error then we need to do a diag
953 printf("%s: page read with error; iocstatus = 0x%x\n",
954 __func__, ioc_status);
958 bcopy(page, config_page, MIN(cm->cm_length,
959 sizeof(Mpi2SasDevicePage0_t)));
963 mps_free_command(sc, cm);
968 * mps_config_get_bios_pg3 - obtain BIOS page 3
969 * @sc: per adapter object
970 * @mpi_reply: reply mf payload returned from firmware
971 * @config_page: contents of the config page
974 * Returns 0 for success, non-zero for failure.
977 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
978 Mpi2BiosPage3_t *config_page)
980 MPI2_CONFIG_REQUEST *request;
981 MPI2_CONFIG_REPLY *reply = NULL;
982 struct mps_command *cm;
983 Mpi2BiosPage3_t *page = NULL;
987 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
989 if ((cm = mps_alloc_command(sc)) == NULL) {
990 printf("%s: command alloc failed @ line %d\n", __func__,
995 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
996 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
997 request->Function = MPI2_FUNCTION_CONFIG;
998 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
999 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1000 request->Header.PageNumber = 3;
1001 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1002 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1004 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1006 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1007 if (error || (reply == NULL)) {
1010 * If the request returns an error then we need to do a diag
1013 printf("%s: request for header completed with error %d",
1018 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1019 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1020 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1023 * If the request returns an error then we need to do a diag
1026 printf("%s: header read with error; iocstatus = 0x%x\n",
1027 __func__, ioc_status);
1031 /* We have to do free and alloc for the reply-free and reply-post
1032 * counters to match - Need to review the reply FIFO handling.
1034 mps_free_command(sc, cm);
1036 if ((cm = mps_alloc_command(sc)) == NULL) {
1037 printf("%s: command alloc failed @ line %d\n", __func__,
1042 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1043 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1044 request->Function = MPI2_FUNCTION_CONFIG;
1045 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1046 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1047 request->Header.PageNumber = 3;
1048 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1049 request->Header.PageLength = mpi_reply->Header.PageLength;
1050 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1051 cm->cm_sge = &request->PageBufferSGE;
1052 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1053 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1054 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1055 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1057 printf("%s: page alloc failed\n", __func__);
1063 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1065 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1066 if (error || (reply == NULL)) {
1069 * If the request returns an error then we need to do a diag
1072 printf("%s: request for page completed with error %d",
1077 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1078 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1079 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1082 * If the request returns an error then we need to do a diag
1085 printf("%s: page read with error; iocstatus = 0x%x\n",
1086 __func__, ioc_status);
1090 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1094 mps_free_command(sc, cm);
1099 * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1100 * @sc: per adapter object
1101 * @mpi_reply: reply mf payload returned from firmware
1102 * @config_page: contents of the config page
1103 * @page_address: form and handle value used to get page
1106 * Returns 0 for success, non-zero for failure.
1109 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1110 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1112 MPI2_CONFIG_REQUEST *request;
1113 MPI2_CONFIG_REPLY *reply = NULL;
1114 struct mps_command *cm;
1115 Mpi2RaidVolPage0_t *page = NULL;
1119 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1121 if ((cm = mps_alloc_command(sc)) == NULL) {
1122 printf("%s: command alloc failed @ line %d\n", __func__,
1127 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1128 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1129 request->Function = MPI2_FUNCTION_CONFIG;
1130 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1131 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1132 request->Header.PageNumber = 0;
1133 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1134 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1138 * This page must be polled because the IOC isn't ready yet when this
1141 error = mps_wait_command(sc, &cm, 60, 0);
1143 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1144 if (error || (reply == NULL)) {
1146 /* If the poll returns error then we need to do diag reset */
1147 printf("%s: poll for header completed with error %d",
1152 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1153 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1154 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1156 /* If the poll returns error then we need to do diag reset */
1157 printf("%s: header read with error; iocstatus = 0x%x\n",
1158 __func__, ioc_status);
1162 /* We have to do free and alloc for the reply-free and reply-post
1163 * counters to match - Need to review the reply FIFO handling.
1165 mps_free_command(sc, cm);
1167 if ((cm = mps_alloc_command(sc)) == NULL) {
1168 printf("%s: command alloc failed @ line %d\n", __func__,
1173 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1174 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1175 request->Function = MPI2_FUNCTION_CONFIG;
1176 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1177 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1178 request->Header.PageNumber = 0;
1179 request->Header.PageLength = mpi_reply->Header.PageLength;
1180 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1181 request->PageAddress = page_address;
1182 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1183 cm->cm_sge = &request->PageBufferSGE;
1184 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1185 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1186 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1187 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1189 printf("%s: page alloc failed\n", __func__);
1196 * This page must be polled because the IOC isn't ready yet when this
1199 error = mps_wait_command(sc, &cm, 60, 0);
1201 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1202 if (error || (reply == NULL)) {
1204 /* If the poll returns error then we need to do diag reset */
1205 printf("%s: poll for page completed with error %d",
1210 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1211 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1212 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1214 /* If the poll returns error then we need to do diag reset */
1215 printf("%s: page read with error; iocstatus = 0x%x\n",
1216 __func__, ioc_status);
1220 bcopy(page, config_page, cm->cm_length);
1224 mps_free_command(sc, cm);
1229 * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1230 * @sc: per adapter object
1231 * @mpi_reply: reply mf payload returned from firmware
1232 * @config_page: contents of the config page
1233 * @form: GET_NEXT_HANDLE or HANDLE
1234 * @handle: volume handle
1237 * Returns 0 for success, non-zero for failure.
1240 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1241 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1243 MPI2_CONFIG_REQUEST *request;
1244 MPI2_CONFIG_REPLY *reply = NULL;
1245 struct mps_command *cm;
1246 Mpi2RaidVolPage1_t *page = NULL;
1250 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1252 if ((cm = mps_alloc_command(sc)) == NULL) {
1253 printf("%s: command alloc failed @ line %d\n", __func__,
1258 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1259 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1260 request->Function = MPI2_FUNCTION_CONFIG;
1261 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1262 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1263 request->Header.PageNumber = 1;
1264 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1265 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1267 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1269 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1270 if (error || (reply == NULL)) {
1273 * If the request returns an error then we need to do a diag
1276 printf("%s: request for header completed with error %d",
1281 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1282 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1283 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1286 * If the request returns an error then we need to do a diag
1289 printf("%s: header read with error; iocstatus = 0x%x\n",
1290 __func__, ioc_status);
1294 /* We have to do free and alloc for the reply-free and reply-post
1295 * counters to match - Need to review the reply FIFO handling.
1297 mps_free_command(sc, cm);
1299 if ((cm = mps_alloc_command(sc)) == NULL) {
1300 printf("%s: command alloc failed @ line %d\n", __func__,
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_READ_CURRENT;
1309 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1310 request->Header.PageNumber = 1;
1311 request->Header.PageLength = mpi_reply->Header.PageLength;
1312 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1313 request->PageAddress = htole32(form | handle);
1314 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1315 cm->cm_sge = &request->PageBufferSGE;
1316 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1317 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1318 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1319 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1321 printf("%s: page alloc failed\n", __func__);
1327 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1329 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1330 if (error || (reply == NULL)) {
1333 * If the request returns an error then we need to do a diag
1336 printf("%s: request for page completed with error %d",
1341 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1342 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1343 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1346 * If the request returns an error then we need to do a diag
1349 printf("%s: page read with error; iocstatus = 0x%x\n",
1350 __func__, ioc_status);
1354 bcopy(page, config_page, MIN(cm->cm_length,
1355 sizeof(Mpi2RaidVolPage1_t)));
1359 mps_free_command(sc, cm);
1364 * mps_config_get_volume_wwid - returns wwid given the volume handle
1365 * @sc: per adapter object
1366 * @volume_handle: volume handle
1367 * @wwid: volume wwid
1370 * Returns 0 for success, non-zero for failure.
1373 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1375 Mpi2ConfigReply_t mpi_reply;
1376 Mpi2RaidVolPage1_t raid_vol_pg1;
1379 if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1380 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1381 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1382 raid_vol_pg1.WWID.Low);
1389 * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1390 * @sc: per adapter object
1391 * @mpi_reply: reply mf payload returned from firmware
1392 * @config_page: contents of the config page
1393 * @page_address: form and handle value used to get page
1396 * Returns 0 for success, non-zero for failure.
1399 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1400 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1402 MPI2_CONFIG_REQUEST *request;
1403 MPI2_CONFIG_REPLY *reply = NULL;
1404 struct mps_command *cm;
1405 Mpi2RaidPhysDiskPage0_t *page = NULL;
1409 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1411 if ((cm = mps_alloc_command(sc)) == NULL) {
1412 printf("%s: command alloc failed @ line %d\n", __func__,
1417 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1418 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1419 request->Function = MPI2_FUNCTION_CONFIG;
1420 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1421 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1422 request->Header.PageNumber = 0;
1423 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1424 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1428 * This page must be polled because the IOC isn't ready yet when this
1431 error = mps_wait_command(sc, &cm, 60, 0);
1433 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1434 if (error || (reply == NULL)) {
1436 /* If the poll returns error then we need to do diag reset */
1437 printf("%s: poll for header completed with error %d",
1442 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1443 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1444 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1446 /* If the poll returns error then we need to do diag reset */
1447 printf("%s: header read with error; iocstatus = 0x%x\n",
1448 __func__, ioc_status);
1452 /* We have to do free and alloc for the reply-free and reply-post
1453 * counters to match - Need to review the reply FIFO handling.
1455 mps_free_command(sc, cm);
1457 if ((cm = mps_alloc_command(sc)) == NULL) {
1458 printf("%s: command alloc failed @ line %d\n", __func__,
1463 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1464 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1465 request->Function = MPI2_FUNCTION_CONFIG;
1466 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1467 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1468 request->Header.PageNumber = 0;
1469 request->Header.PageLength = mpi_reply->Header.PageLength;
1470 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1471 request->PageAddress = page_address;
1472 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1473 cm->cm_sge = &request->PageBufferSGE;
1474 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1475 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1476 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1477 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1479 printf("%s: page alloc failed\n", __func__);
1486 * This page must be polled because the IOC isn't ready yet when this
1489 error = mps_wait_command(sc, &cm, 60, 0);
1491 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1492 if (error || (reply == NULL)) {
1494 /* If the poll returns error then we need to do diag reset */
1495 printf("%s: poll for page completed with error %d",
1500 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1501 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1502 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1504 /* If the poll returns error then we need to do diag reset */
1505 printf("%s: page read with error; iocstatus = 0x%x\n",
1506 __func__, ioc_status);
1510 bcopy(page, config_page, MIN(cm->cm_length,
1511 sizeof(Mpi2RaidPhysDiskPage0_t)));
1515 mps_free_command(sc, cm);