2 * Copyright (c) 2011-2015 LSI Corp.
3 * Copyright (c) 2013-2015 Avago Technologies
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 /* TODO Move headers to mpsvar */
34 #include <sys/types.h>
35 #include <sys/param.h>
37 #include <sys/mutex.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/kthread.h>
42 #include <sys/taskqueue.h>
44 #include <sys/endian.h>
45 #include <sys/sysctl.h>
46 #include <sys/eventhandler.h>
48 #include <machine/bus.h>
49 #include <machine/resource.h>
50 #include <dev/mps/mpi/mpi2_type.h>
51 #include <dev/mps/mpi/mpi2.h>
52 #include <dev/mps/mpi/mpi2_ioc.h>
53 #include <dev/mps/mpi/mpi2_sas.h>
54 #include <dev/mps/mpi/mpi2_cnfg.h>
55 #include <dev/mps/mpi/mpi2_init.h>
56 #include <dev/mps/mpi/mpi2_tool.h>
57 #include <dev/mps/mps_ioctl.h>
58 #include <dev/mps/mpsvar.h>
61 * mps_config_get_ioc_pg8 - obtain ioc page 8
62 * @sc: per adapter object
63 * @mpi_reply: reply mf payload returned from firmware
64 * @config_page: contents of the config page
67 * Returns 0 for success, non-zero for failure.
70 mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
71 Mpi2IOCPage8_t *config_page)
73 MPI2_CONFIG_REQUEST *request;
74 MPI2_CONFIG_REPLY *reply;
75 struct mps_command *cm;
76 MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
80 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
82 if ((cm = mps_alloc_command(sc)) == NULL) {
83 printf("%s: command alloc failed @ line %d\n", __func__,
88 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
89 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
90 request->Function = MPI2_FUNCTION_CONFIG;
91 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
92 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
93 request->Header.PageNumber = 8;
94 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
95 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
97 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
98 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
99 if (error || (reply == NULL)) {
102 * If the request returns an error then we need to do a diag
105 printf("%s: request for header completed with error %d",
110 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
111 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
112 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
115 * If the request returns an error then we need to do a diag
118 printf("%s: header read with error; iocstatus = 0x%x\n",
119 __func__, ioc_status);
123 /* We have to do free and alloc for the reply-free and reply-post
124 * counters to match - Need to review the reply FIFO handling.
126 mps_free_command(sc, cm);
128 if ((cm = mps_alloc_command(sc)) == NULL) {
129 printf("%s: command alloc failed @ line %d\n", __func__,
134 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
135 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
136 request->Function = MPI2_FUNCTION_CONFIG;
137 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
138 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
139 request->Header.PageNumber = 8;
140 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
141 request->Header.PageLength = mpi_reply->Header.PageLength;
142 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
143 cm->cm_sge = &request->PageBufferSGE;
144 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
145 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
146 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
147 page = malloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT);
149 printf("%s: page alloc failed\n", __func__);
155 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
156 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
157 if (error || (reply == NULL)) {
160 * If the request returns an error then we need to do a diag
163 printf("%s: request for page completed with error %d",
168 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
169 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
170 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
173 * If the request returns an error then we need to do a diag
176 printf("%s: page read with error; iocstatus = 0x%x\n",
177 __func__, ioc_status);
181 bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
186 mps_free_command(sc, cm);
191 * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
192 * accordingly. Currently, this page does not need to return to caller.
193 * @sc: per adapter object
194 * @mpi_reply: reply mf payload returned from firmware
197 * Returns 0 for success, non-zero for failure.
200 mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
202 MPI2_CONFIG_REQUEST *request;
203 MPI2_CONFIG_REPLY *reply;
204 struct mps_command *cm;
205 pMpi2ManufacturingPagePS_t page = NULL;
207 uint8_t OEM_Value = 0;
211 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
213 if ((cm = mps_alloc_command(sc)) == NULL) {
214 printf("%s: command alloc failed @ line %d\n", __func__,
219 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
220 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
221 request->Function = MPI2_FUNCTION_CONFIG;
222 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
223 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
224 request->Header.PageNumber = 10;
225 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
226 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
230 * This page must be polled because the IOC isn't ready yet when this
233 error = mps_wait_command(sc, cm, 60, 0);
234 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
235 if (error || (reply == NULL)) {
237 /* If the poll returns error then we need to do diag reset */
238 printf("%s: poll for header completed with error %d",
243 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
244 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
245 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
247 /* If the poll returns error then we need to do diag reset */
248 printf("%s: header read with error; iocstatus = 0x%x\n",
249 __func__, ioc_status);
253 /* We have to do free and alloc for the reply-free and reply-post
254 * counters to match - Need to review the reply FIFO handling.
256 mps_free_command(sc, cm);
258 if ((cm = mps_alloc_command(sc)) == NULL) {
259 printf("%s: command alloc failed @ line %d\n", __func__,
264 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
265 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
266 request->Function = MPI2_FUNCTION_CONFIG;
267 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
268 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
269 request->Header.PageNumber = 10;
270 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
271 request->Header.PageLength = mpi_reply->Header.PageLength;
272 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
273 cm->cm_sge = &request->PageBufferSGE;
274 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
275 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
276 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
277 page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT);
279 printf("%s: page alloc failed\n", __func__);
286 * This page must be polled because the IOC isn't ready yet when this
289 error = mps_wait_command(sc, cm, 60, 0);
290 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
291 if (error || (reply == NULL)) {
293 /* If the poll returns error then we need to do diag reset */
294 printf("%s: poll for page completed with error %d",
299 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
300 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
301 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
303 /* If the poll returns error then we need to do diag reset */
304 printf("%s: page read with error; iocstatus = 0x%x\n",
305 __func__, ioc_status);
311 * If OEM ID is unknown, fail the request.
313 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
314 OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
315 if (OEM_Value != MPS_WD_LSI_OEM) {
316 mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
317 "(0x%x)\n", OEM_Value);
323 * Set the phys disks hide/expose value.
325 pPS_info = &page->ProductSpecificInfo;
326 sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
327 sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
328 if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
329 (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
330 (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
331 mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
332 "hide/expose: 0x%x\n", sc->WD_hide_expose);
340 mps_free_command(sc, cm);
345 * mps_base_static_config_pages - static start of day config pages.
346 * @sc: per adapter object
351 mps_base_static_config_pages(struct mps_softc *sc)
353 Mpi2ConfigReply_t mpi_reply;
357 while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
360 /* We need to Handle this situation */
368 * mps_wd_config_pages - get info required to support WarpDrive. This needs to
369 * be called after discovery is complete to guarantee that IR info is there.
370 * @sc: per adapter object
375 mps_wd_config_pages(struct mps_softc *sc)
377 Mpi2ConfigReply_t mpi_reply;
378 pMpi2RaidVolPage0_t raid_vol_pg0 = NULL;
379 Mpi2RaidPhysDiskPage0_t phys_disk_pg0;
380 pMpi2RaidVol0PhysDisk_t pRVPD;
381 uint32_t stripe_size, phys_disk_page_address;
383 uint8_t index, stripe_exp = 0, block_exp = 0;
386 * Get the WD settings from manufacturing page 10 if using a WD HBA.
387 * This will be used to determine if phys disks should always be
388 * hidden, hidden only if part of a WD volume, or never hidden. Also,
389 * get the WD RAID Volume info and fail if volume does not exist or if
390 * volume does not meet the requirements for a WD volume. No retry
391 * here. Just default to HIDE ALWAYS if man Page10 fails, or clear WD
392 * Valid flag if Volume info fails.
394 sc->WD_valid_config = FALSE;
395 if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) {
396 if (mps_config_get_man_pg10(sc, &mpi_reply)) {
397 mps_dprint(sc, MPS_FAULT,
398 "mps_config_get_man_pg10 failed! Using 0 (Hide "
399 "Always) for WarpDrive hide/expose value.\n");
400 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
404 * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
406 raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) +
407 (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
408 M_MPT2, M_ZERO | M_NOWAIT);
410 printf("%s: page alloc failed\n", __func__);
414 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
416 mps_dprint(sc, MPS_INFO,
417 "mps_config_get_raid_volume_pg0 failed! Assuming "
418 "WarpDrive IT mode.\n");
423 * Check for valid WD configuration:
424 * volume type is RAID0
425 * number of phys disks in the volume is no more than 8
427 if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) ||
428 (raid_vol_pg0->NumPhysDisks > 8)) {
429 mps_dprint(sc, MPS_FAULT,
430 "Invalid WarpDrive configuration. Direct Drive I/O "
431 "will not be used.\n");
436 * Save the WD RAID data to be used during WD I/O.
438 sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High <<
439 32 | (uint64_t)raid_vol_pg0->MaxLBA.Low);
440 sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks;
441 sc->DD_dev_handle = raid_vol_pg0->DevHandle;
442 sc->DD_stripe_size = raid_vol_pg0->StripeSize;
443 sc->DD_block_size = raid_vol_pg0->BlockSize;
446 * Find power of 2 of stripe size and set this as the exponent.
447 * Fail if stripe size is 0.
449 stripe_size = raid_vol_pg0->StripeSize;
450 for (index = 0; index < 32; index++) {
457 mps_dprint(sc, MPS_FAULT,
458 "RAID Volume's stripe size is 0. Direct Drive I/O "
459 "will not be used.\n");
462 sc->DD_stripe_exponent = stripe_exp;
465 * Find power of 2 of block size and set this as the exponent.
466 * Fail if block size is 0.
468 block_size = raid_vol_pg0->BlockSize;
469 for (index = 0; index < 16; index++) {
476 mps_dprint(sc, MPS_FAULT,
477 "RAID Volume's block size is 0. Direct Drive I/O "
478 "will not be used.\n");
481 sc->DD_block_exponent = block_exp;
484 * Loop through all of the volume's Phys Disks to map the phys
485 * disk number into the columm map. This is used during Direct
486 * Drive I/O to send the request to the correct SSD.
488 pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk;
489 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
490 sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num =
496 * Get second RAID Volume Page0 using previous handle. This
497 * page should not exist. If it does, must not proceed with WD
500 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
501 raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
502 if ((le16toh(mpi_reply.IOCStatus) &
503 MPI2_IOCSTATUS_MASK) !=
504 MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
505 mps_dprint(sc, MPS_FAULT,
506 "Multiple RAID Volume Page0! Direct Drive "
507 "I/O will not be used.\n");
511 mps_dprint(sc, MPS_FAULT,
512 "Multiple volumes! Direct Drive I/O will not be "
518 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
520 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
521 phys_disk_page_address =
522 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
523 sc->DD_column_map[index].phys_disk_num;
524 if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
525 &phys_disk_pg0, phys_disk_page_address)) {
526 mps_dprint(sc, MPS_FAULT,
527 "mps_config_get_raid_pd_pg0 failed! Direct "
528 "Drive I/O will not be used.\n");
531 if (phys_disk_pg0.DevHandle == 0xFFFF) {
532 mps_dprint(sc, MPS_FAULT,
533 "Invalid Phys Disk DevHandle! Direct Drive "
534 "I/O will not be used.\n");
537 sc->DD_column_map[index].dev_handle =
538 phys_disk_pg0.DevHandle;
540 sc->WD_valid_config = TRUE;
543 free(raid_vol_pg0, M_MPT2);
548 * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
549 * @sc: per adapter object
550 * @mpi_reply: reply mf payload returned from firmware
551 * @config_page: contents of the config page
552 * @sz: size of buffer passed in config_page
555 * Returns 0 for success, non-zero for failure.
558 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
559 Mpi2DriverMappingPage0_t *config_page, u16 sz)
561 MPI2_CONFIG_REQUEST *request;
562 MPI2_CONFIG_REPLY *reply;
563 struct mps_command *cm;
564 Mpi2DriverMappingPage0_t *page = NULL;
568 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
570 memset(config_page, 0, sz);
571 if ((cm = mps_alloc_command(sc)) == NULL) {
572 printf("%s: command alloc failed @ line %d\n", __func__,
577 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
578 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
579 request->Function = MPI2_FUNCTION_CONFIG;
580 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
581 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
582 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
583 request->Header.PageNumber = 0;
584 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
585 request->PageAddress = sc->max_dpm_entries <<
586 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
587 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
589 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
590 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
591 if (error || (reply == NULL)) {
594 * If the request returns an error then we need to do a diag
597 printf("%s: request for header completed with error %d",
602 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
603 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
604 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
607 * If the request returns an error then we need to do a diag
610 printf("%s: header read with error; iocstatus = 0x%x\n",
611 __func__, ioc_status);
615 /* We have to do free and alloc for the reply-free and reply-post
616 * counters to match - Need to review the reply FIFO handling.
618 mps_free_command(sc, cm);
620 if ((cm = mps_alloc_command(sc)) == NULL) {
621 printf("%s: command alloc failed @ line %d\n", __func__,
626 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
627 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
628 request->Function = MPI2_FUNCTION_CONFIG;
629 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
630 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
631 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
632 request->Header.PageNumber = 0;
633 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
634 request->PageAddress = sc->max_dpm_entries <<
635 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
636 request->ExtPageLength = mpi_reply->ExtPageLength;
637 cm->cm_length = le16toh(request->ExtPageLength) * 4;
638 cm->cm_sge = &request->PageBufferSGE;
639 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
640 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
641 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
642 page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT);
644 printf("%s: page alloc failed\n", __func__);
649 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
650 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
651 if (error || (reply == NULL)) {
654 * If the request returns an error then we need to do a diag
657 printf("%s: request for page completed with error %d",
662 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
663 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
664 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
667 * If the request returns an error then we need to do a diag
670 printf("%s: page read with error; iocstatus = 0x%x\n",
671 __func__, ioc_status);
675 bcopy(page, config_page, MIN(cm->cm_length, sz));
679 mps_free_command(sc, cm);
684 * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
685 * @sc: per adapter object
686 * @mpi_reply: reply mf payload returned from firmware
687 * @config_page: contents of the config page
688 * @entry_idx: entry index in DPM Page0 to be modified
691 * Returns 0 for success, non-zero for failure.
694 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
695 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
697 MPI2_CONFIG_REQUEST *request;
698 MPI2_CONFIG_REPLY *reply;
699 struct mps_command *cm;
700 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
704 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
706 if ((cm = mps_alloc_command(sc)) == NULL) {
707 printf("%s: command alloc failed @ line %d\n", __func__,
712 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
713 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
714 request->Function = MPI2_FUNCTION_CONFIG;
715 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
716 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
717 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
718 request->Header.PageNumber = 0;
719 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
720 /* We can remove below two lines ????*/
721 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
722 request->PageAddress |= htole16(entry_idx);
723 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
725 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
726 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
727 if (error || (reply == NULL)) {
730 * If the request returns an error then we need to do a diag
733 printf("%s: request for header completed with error %d",
738 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
739 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
740 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
743 * If the request returns an error then we need to do a diag
746 printf("%s: header read with error; iocstatus = 0x%x\n",
747 __func__, ioc_status);
751 /* We have to do free and alloc for the reply-free and reply-post
752 * counters to match - Need to review the reply FIFO handling.
754 mps_free_command(sc, cm);
756 if ((cm = mps_alloc_command(sc)) == NULL) {
757 printf("%s: command alloc failed @ line %d\n", __func__,
762 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
763 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
764 request->Function = MPI2_FUNCTION_CONFIG;
765 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
766 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
767 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
768 request->Header.PageNumber = 0;
769 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
770 request->ExtPageLength = mpi_reply->ExtPageLength;
771 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
772 request->PageAddress |= htole16(entry_idx);
773 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
774 cm->cm_sge = &request->PageBufferSGE;
775 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
776 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
777 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
778 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
780 printf("%s: page alloc failed\n", __func__);
784 bcopy(config_page, page, MIN(cm->cm_length,
785 (sizeof(Mpi2DriverMappingPage0_t))));
787 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
788 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
789 if (error || (reply == NULL)) {
792 * If the request returns an error then we need to do a diag
795 printf("%s: request to write page completed with error %d",
800 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
801 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
802 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
805 * If the request returns an error then we need to do a diag
808 printf("%s: page written with error; iocstatus = 0x%x\n",
809 __func__, ioc_status);
816 mps_free_command(sc, cm);
821 * mps_config_get_sas_device_pg0 - obtain sas device page 0
822 * @sc: per adapter object
823 * @mpi_reply: reply mf payload returned from firmware
824 * @config_page: contents of the config page
825 * @form: GET_NEXT_HANDLE or HANDLE
826 * @handle: device handle
829 * Returns 0 for success, non-zero for failure.
832 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
833 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
835 MPI2_CONFIG_REQUEST *request;
836 MPI2_CONFIG_REPLY *reply;
837 struct mps_command *cm;
838 Mpi2SasDevicePage0_t *page = NULL;
842 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
844 if ((cm = mps_alloc_command(sc)) == NULL) {
845 printf("%s: command alloc failed @ line %d\n", __func__,
850 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
851 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
852 request->Function = MPI2_FUNCTION_CONFIG;
853 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
854 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
855 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
856 request->Header.PageNumber = 0;
857 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
858 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
860 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
861 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
862 if (error || (reply == NULL)) {
865 * If the request returns an error then we need to do a diag
868 printf("%s: request for header completed with error %d",
873 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
874 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
875 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
878 * If the request returns an error then we need to do a diag
881 printf("%s: header read with error; iocstatus = 0x%x\n",
882 __func__, ioc_status);
886 /* We have to do free and alloc for the reply-free and reply-post
887 * counters to match - Need to review the reply FIFO handling.
889 mps_free_command(sc, cm);
891 if ((cm = mps_alloc_command(sc)) == NULL) {
892 printf("%s: command alloc failed @ line %d\n", __func__,
897 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
898 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
899 request->Function = MPI2_FUNCTION_CONFIG;
900 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
901 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
902 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
903 request->Header.PageNumber = 0;
904 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
905 request->ExtPageLength = mpi_reply->ExtPageLength;
906 request->PageAddress = htole32(form | handle);
907 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
908 cm->cm_sge = &request->PageBufferSGE;
909 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
910 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
911 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
912 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
914 printf("%s: page alloc failed\n", __func__);
920 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
921 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
922 if (error || (reply == NULL)) {
925 * If the request returns an error then we need to do a diag
928 printf("%s: request for page completed with error %d",
933 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
934 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
935 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
938 * If the request returns an error then we need to do a diag
941 printf("%s: page read with error; iocstatus = 0x%x\n",
942 __func__, ioc_status);
946 bcopy(page, config_page, MIN(cm->cm_length,
947 sizeof(Mpi2SasDevicePage0_t)));
951 mps_free_command(sc, cm);
956 * mps_config_get_bios_pg3 - obtain BIOS page 3
957 * @sc: per adapter object
958 * @mpi_reply: reply mf payload returned from firmware
959 * @config_page: contents of the config page
962 * Returns 0 for success, non-zero for failure.
965 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
966 Mpi2BiosPage3_t *config_page)
968 MPI2_CONFIG_REQUEST *request;
969 MPI2_CONFIG_REPLY *reply;
970 struct mps_command *cm;
971 Mpi2BiosPage3_t *page = NULL;
975 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
977 if ((cm = mps_alloc_command(sc)) == NULL) {
978 printf("%s: command alloc failed @ line %d\n", __func__,
983 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
984 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
985 request->Function = MPI2_FUNCTION_CONFIG;
986 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
987 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
988 request->Header.PageNumber = 3;
989 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
990 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
992 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
993 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
994 if (error || (reply == NULL)) {
997 * If the request returns an error then we need to do a diag
1000 printf("%s: request for header completed with error %d",
1005 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1006 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1007 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1010 * If the request returns an error then we need to do a diag
1013 printf("%s: header read with error; iocstatus = 0x%x\n",
1014 __func__, ioc_status);
1018 /* We have to do free and alloc for the reply-free and reply-post
1019 * counters to match - Need to review the reply FIFO handling.
1021 mps_free_command(sc, cm);
1023 if ((cm = mps_alloc_command(sc)) == NULL) {
1024 printf("%s: command alloc failed @ line %d\n", __func__,
1029 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1030 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1031 request->Function = MPI2_FUNCTION_CONFIG;
1032 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1033 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1034 request->Header.PageNumber = 3;
1035 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1036 request->Header.PageLength = mpi_reply->Header.PageLength;
1037 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1038 cm->cm_sge = &request->PageBufferSGE;
1039 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1040 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1041 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1042 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1044 printf("%s: page alloc failed\n", __func__);
1050 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1051 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1052 if (error || (reply == NULL)) {
1055 * If the request returns an error then we need to do a diag
1058 printf("%s: request for page completed with error %d",
1063 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1064 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1065 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1068 * If the request returns an error then we need to do a diag
1071 printf("%s: page read with error; iocstatus = 0x%x\n",
1072 __func__, ioc_status);
1076 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1080 mps_free_command(sc, cm);
1085 * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1086 * @sc: per adapter object
1087 * @mpi_reply: reply mf payload returned from firmware
1088 * @config_page: contents of the config page
1089 * @page_address: form and handle value used to get page
1092 * Returns 0 for success, non-zero for failure.
1095 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1096 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1098 MPI2_CONFIG_REQUEST *request;
1099 MPI2_CONFIG_REPLY *reply;
1100 struct mps_command *cm;
1101 Mpi2RaidVolPage0_t *page = NULL;
1105 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1107 if ((cm = mps_alloc_command(sc)) == NULL) {
1108 printf("%s: command alloc failed @ line %d\n", __func__,
1113 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1114 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1115 request->Function = MPI2_FUNCTION_CONFIG;
1116 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1117 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1118 request->Header.PageNumber = 0;
1119 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1120 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1124 * This page must be polled because the IOC isn't ready yet when this
1127 error = mps_wait_command(sc, cm, 60, 0);
1128 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1129 if (error || (reply == NULL)) {
1131 /* If the poll returns error then we need to do diag reset */
1132 printf("%s: poll for header completed with error %d",
1137 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1138 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1139 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1141 /* If the poll returns error then we need to do diag reset */
1142 printf("%s: header read with error; iocstatus = 0x%x\n",
1143 __func__, ioc_status);
1147 /* We have to do free and alloc for the reply-free and reply-post
1148 * counters to match - Need to review the reply FIFO handling.
1150 mps_free_command(sc, cm);
1152 if ((cm = mps_alloc_command(sc)) == NULL) {
1153 printf("%s: command alloc failed @ line %d\n", __func__,
1158 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1159 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1160 request->Function = MPI2_FUNCTION_CONFIG;
1161 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1162 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1163 request->Header.PageNumber = 0;
1164 request->Header.PageLength = mpi_reply->Header.PageLength;
1165 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1166 request->PageAddress = page_address;
1167 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1168 cm->cm_sge = &request->PageBufferSGE;
1169 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1170 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1171 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1172 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1174 printf("%s: page alloc failed\n", __func__);
1181 * This page must be polled because the IOC isn't ready yet when this
1184 error = mps_wait_command(sc, cm, 60, 0);
1185 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1186 if (error || (reply == NULL)) {
1188 /* If the poll returns error then we need to do diag reset */
1189 printf("%s: poll for page completed with error %d",
1194 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1195 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1196 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1198 /* If the poll returns error then we need to do diag reset */
1199 printf("%s: page read with error; iocstatus = 0x%x\n",
1200 __func__, ioc_status);
1204 bcopy(page, config_page, cm->cm_length);
1208 mps_free_command(sc, cm);
1213 * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1214 * @sc: per adapter object
1215 * @mpi_reply: reply mf payload returned from firmware
1216 * @config_page: contents of the config page
1217 * @form: GET_NEXT_HANDLE or HANDLE
1218 * @handle: volume handle
1221 * Returns 0 for success, non-zero for failure.
1224 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1225 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1227 MPI2_CONFIG_REQUEST *request;
1228 MPI2_CONFIG_REPLY *reply;
1229 struct mps_command *cm;
1230 Mpi2RaidVolPage1_t *page = NULL;
1234 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1236 if ((cm = mps_alloc_command(sc)) == NULL) {
1237 printf("%s: command alloc failed @ line %d\n", __func__,
1242 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1243 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1244 request->Function = MPI2_FUNCTION_CONFIG;
1245 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1246 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1247 request->Header.PageNumber = 1;
1248 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1249 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1251 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1252 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1253 if (error || (reply == NULL)) {
1256 * If the request returns an error then we need to do a diag
1259 printf("%s: request for header completed with error %d",
1264 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1265 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1266 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1269 * If the request returns an error then we need to do a diag
1272 printf("%s: header read with error; iocstatus = 0x%x\n",
1273 __func__, ioc_status);
1277 /* We have to do free and alloc for the reply-free and reply-post
1278 * counters to match - Need to review the reply FIFO handling.
1280 mps_free_command(sc, cm);
1282 if ((cm = mps_alloc_command(sc)) == NULL) {
1283 printf("%s: command alloc failed @ line %d\n", __func__,
1288 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1289 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1290 request->Function = MPI2_FUNCTION_CONFIG;
1291 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1292 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1293 request->Header.PageNumber = 1;
1294 request->Header.PageLength = mpi_reply->Header.PageLength;
1295 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1296 request->PageAddress = htole32(form | handle);
1297 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1298 cm->cm_sge = &request->PageBufferSGE;
1299 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1300 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1301 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1302 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1304 printf("%s: page alloc failed\n", __func__);
1310 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1311 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1312 if (error || (reply == NULL)) {
1315 * If the request returns an error then we need to do a diag
1318 printf("%s: request for page 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) {
1328 * If the request returns an error then we need to do a diag
1331 printf("%s: page read with error; iocstatus = 0x%x\n",
1332 __func__, ioc_status);
1336 bcopy(page, config_page, MIN(cm->cm_length,
1337 sizeof(Mpi2RaidVolPage1_t)));
1341 mps_free_command(sc, cm);
1346 * mps_config_get_volume_wwid - returns wwid given the volume handle
1347 * @sc: per adapter object
1348 * @volume_handle: volume handle
1349 * @wwid: volume wwid
1352 * Returns 0 for success, non-zero for failure.
1355 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1357 Mpi2ConfigReply_t mpi_reply;
1358 Mpi2RaidVolPage1_t raid_vol_pg1;
1361 if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1362 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1363 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1364 raid_vol_pg1.WWID.Low);
1371 * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1372 * @sc: per adapter object
1373 * @mpi_reply: reply mf payload returned from firmware
1374 * @config_page: contents of the config page
1375 * @page_address: form and handle value used to get page
1378 * Returns 0 for success, non-zero for failure.
1381 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1382 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1384 MPI2_CONFIG_REQUEST *request;
1385 MPI2_CONFIG_REPLY *reply;
1386 struct mps_command *cm;
1387 Mpi2RaidPhysDiskPage0_t *page = NULL;
1391 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1393 if ((cm = mps_alloc_command(sc)) == NULL) {
1394 printf("%s: command alloc failed @ line %d\n", __func__,
1399 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1400 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1401 request->Function = MPI2_FUNCTION_CONFIG;
1402 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1403 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1404 request->Header.PageNumber = 0;
1405 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1406 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1410 * This page must be polled because the IOC isn't ready yet when this
1413 error = mps_wait_command(sc, cm, 60, 0);
1414 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1415 if (error || (reply == NULL)) {
1417 /* If the poll returns error then we need to do diag reset */
1418 printf("%s: poll for header completed with error %d",
1423 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1424 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1425 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1427 /* If the poll returns error then we need to do diag reset */
1428 printf("%s: header read with error; iocstatus = 0x%x\n",
1429 __func__, ioc_status);
1433 /* We have to do free and alloc for the reply-free and reply-post
1434 * counters to match - Need to review the reply FIFO handling.
1436 mps_free_command(sc, cm);
1438 if ((cm = mps_alloc_command(sc)) == NULL) {
1439 printf("%s: command alloc failed @ line %d\n", __func__,
1444 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1445 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1446 request->Function = MPI2_FUNCTION_CONFIG;
1447 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1448 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1449 request->Header.PageNumber = 0;
1450 request->Header.PageLength = mpi_reply->Header.PageLength;
1451 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1452 request->PageAddress = page_address;
1453 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1454 cm->cm_sge = &request->PageBufferSGE;
1455 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1456 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1457 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1458 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1460 printf("%s: page alloc failed\n", __func__);
1467 * This page must be polled because the IOC isn't ready yet when this
1470 error = mps_wait_command(sc, cm, 60, 0);
1471 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1472 if (error || (reply == NULL)) {
1474 /* If the poll returns error then we need to do diag reset */
1475 printf("%s: poll for page completed with error %d",
1480 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1481 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1482 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1484 /* If the poll returns error then we need to do diag reset */
1485 printf("%s: page read with error; iocstatus = 0x%x\n",
1486 __func__, ioc_status);
1490 bcopy(page, config_page, MIN(cm->cm_length,
1491 sizeof(Mpi2RaidPhysDiskPage0_t)));
1495 mps_free_command(sc, cm);