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 = NULL;
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);
99 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
100 if (error || (reply == NULL)) {
103 * If the request returns an error then we need to do a diag
106 printf("%s: request for header completed with error %d",
111 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
112 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
113 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
116 * If the request returns an error then we need to do a diag
119 printf("%s: header read with error; iocstatus = 0x%x\n",
120 __func__, ioc_status);
124 /* We have to do free and alloc for the reply-free and reply-post
125 * counters to match - Need to review the reply FIFO handling.
127 mps_free_command(sc, cm);
129 if ((cm = mps_alloc_command(sc)) == NULL) {
130 printf("%s: command alloc failed @ line %d\n", __func__,
135 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
136 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
137 request->Function = MPI2_FUNCTION_CONFIG;
138 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
139 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
140 request->Header.PageNumber = 8;
141 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
142 request->Header.PageLength = mpi_reply->Header.PageLength;
143 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
144 cm->cm_sge = &request->PageBufferSGE;
145 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
146 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
147 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
148 page = malloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT);
150 printf("%s: page alloc failed\n", __func__);
156 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
158 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
159 if (error || (reply == NULL)) {
162 * If the request returns an error then we need to do a diag
165 printf("%s: request for page completed with error %d",
170 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
171 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
172 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
175 * If the request returns an error then we need to do a diag
178 printf("%s: page read with error; iocstatus = 0x%x\n",
179 __func__, ioc_status);
183 bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
188 mps_free_command(sc, cm);
193 * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
194 * accordingly. Currently, this page does not need to return to caller.
195 * @sc: per adapter object
196 * @mpi_reply: reply mf payload returned from firmware
199 * Returns 0 for success, non-zero for failure.
202 mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
204 MPI2_CONFIG_REQUEST *request;
205 MPI2_CONFIG_REPLY *reply = NULL;
206 struct mps_command *cm;
207 pMpi2ManufacturingPagePS_t page = NULL;
209 uint8_t OEM_Value = 0;
213 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
215 if ((cm = mps_alloc_command(sc)) == NULL) {
216 printf("%s: command alloc failed @ line %d\n", __func__,
221 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
222 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
223 request->Function = MPI2_FUNCTION_CONFIG;
224 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
225 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
226 request->Header.PageNumber = 10;
227 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
228 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
232 * This page must be polled because the IOC isn't ready yet when this
235 error = mps_wait_command(sc, &cm, 60, 0);
237 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
238 if (error || (reply == NULL)) {
240 /* If the poll returns error then we need to do diag reset */
241 printf("%s: poll for header completed with error %d",
246 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
247 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
248 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
250 /* If the poll returns error then we need to do diag reset */
251 printf("%s: header read with error; iocstatus = 0x%x\n",
252 __func__, ioc_status);
256 /* We have to do free and alloc for the reply-free and reply-post
257 * counters to match - Need to review the reply FIFO handling.
259 mps_free_command(sc, cm);
261 if ((cm = mps_alloc_command(sc)) == NULL) {
262 printf("%s: command alloc failed @ line %d\n", __func__,
267 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
268 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
269 request->Function = MPI2_FUNCTION_CONFIG;
270 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
271 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
272 request->Header.PageNumber = 10;
273 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
274 request->Header.PageLength = mpi_reply->Header.PageLength;
275 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
276 cm->cm_sge = &request->PageBufferSGE;
277 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
278 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
279 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
280 page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT);
282 printf("%s: page alloc failed\n", __func__);
289 * This page must be polled because the IOC isn't ready yet when this
292 error = mps_wait_command(sc, &cm, 60, 0);
294 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
295 if (error || (reply == NULL)) {
297 /* If the poll returns error then we need to do diag reset */
298 printf("%s: poll for page completed with error %d",
303 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
304 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
305 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
307 /* If the poll returns error then we need to do diag reset */
308 printf("%s: page read with error; iocstatus = 0x%x\n",
309 __func__, ioc_status);
315 * If OEM ID is unknown, fail the request.
317 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
318 OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
319 if (OEM_Value != MPS_WD_LSI_OEM) {
320 mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
321 "(0x%x)\n", OEM_Value);
327 * Set the phys disks hide/expose value.
329 pPS_info = &page->ProductSpecificInfo;
330 sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
331 sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
332 if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
333 (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
334 (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
335 mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
336 "hide/expose: 0x%x\n", sc->WD_hide_expose);
344 mps_free_command(sc, cm);
349 * mps_base_static_config_pages - static start of day config pages.
350 * @sc: per adapter object
355 mps_base_static_config_pages(struct mps_softc *sc)
357 Mpi2ConfigReply_t mpi_reply;
361 while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
364 /* We need to Handle this situation */
372 * mps_wd_config_pages - get info required to support WarpDrive. This needs to
373 * be called after discovery is complete to guarentee that IR info is there.
374 * @sc: per adapter object
379 mps_wd_config_pages(struct mps_softc *sc)
381 Mpi2ConfigReply_t mpi_reply;
382 pMpi2RaidVolPage0_t raid_vol_pg0 = NULL;
383 Mpi2RaidPhysDiskPage0_t phys_disk_pg0;
384 pMpi2RaidVol0PhysDisk_t pRVPD;
385 uint32_t stripe_size, phys_disk_page_address;
387 uint8_t index, stripe_exp = 0, block_exp = 0;
390 * Get the WD settings from manufacturing page 10 if using a WD HBA.
391 * This will be used to determine if phys disks should always be
392 * hidden, hidden only if part of a WD volume, or never hidden. Also,
393 * get the WD RAID Volume info and fail if volume does not exist or if
394 * volume does not meet the requirements for a WD volume. No retry
395 * here. Just default to HIDE ALWAYS if man Page10 fails, or clear WD
396 * Valid flag if Volume info fails.
398 sc->WD_valid_config = FALSE;
399 if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) {
400 if (mps_config_get_man_pg10(sc, &mpi_reply)) {
401 mps_dprint(sc, MPS_FAULT,
402 "mps_config_get_man_pg10 failed! Using 0 (Hide "
403 "Always) for WarpDrive hide/expose value.\n");
404 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
408 * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
410 raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) +
411 (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
412 M_MPT2, M_ZERO | M_NOWAIT);
414 printf("%s: page alloc failed\n", __func__);
418 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
420 mps_dprint(sc, MPS_INFO,
421 "mps_config_get_raid_volume_pg0 failed! Assuming "
422 "WarpDrive IT mode.\n");
427 * Check for valid WD configuration:
428 * volume type is RAID0
429 * number of phys disks in the volume is no more than 8
431 if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) ||
432 (raid_vol_pg0->NumPhysDisks > 8)) {
433 mps_dprint(sc, MPS_FAULT,
434 "Invalid WarpDrive configuration. Direct Drive I/O "
435 "will not be used.\n");
440 * Save the WD RAID data to be used during WD I/O.
442 sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High <<
443 32 | (uint64_t)raid_vol_pg0->MaxLBA.Low);
444 sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks;
445 sc->DD_dev_handle = raid_vol_pg0->DevHandle;
446 sc->DD_stripe_size = raid_vol_pg0->StripeSize;
447 sc->DD_block_size = raid_vol_pg0->BlockSize;
450 * Find power of 2 of stripe size and set this as the exponent.
451 * Fail if stripe size is 0.
453 stripe_size = raid_vol_pg0->StripeSize;
454 for (index = 0; index < 32; index++) {
461 mps_dprint(sc, MPS_FAULT,
462 "RAID Volume's stripe size is 0. Direct Drive I/O "
463 "will not be used.\n");
466 sc->DD_stripe_exponent = stripe_exp;
469 * Find power of 2 of block size and set this as the exponent.
470 * Fail if block size is 0.
472 block_size = raid_vol_pg0->BlockSize;
473 for (index = 0; index < 16; index++) {
480 mps_dprint(sc, MPS_FAULT,
481 "RAID Volume's block size is 0. Direct Drive I/O "
482 "will not be used.\n");
485 sc->DD_block_exponent = block_exp;
488 * Loop through all of the volume's Phys Disks to map the phys
489 * disk number into the columm map. This is used during Direct
490 * Drive I/O to send the request to the correct SSD.
492 pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk;
493 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
494 sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num =
500 * Get second RAID Volume Page0 using previous handle. This
501 * page should not exist. If it does, must not proceed with WD
504 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
505 raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
506 if ((le16toh(mpi_reply.IOCStatus) &
507 MPI2_IOCSTATUS_MASK) !=
508 MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
509 mps_dprint(sc, MPS_FAULT,
510 "Multiple RAID Volume Page0! Direct Drive "
511 "I/O will not be used.\n");
515 mps_dprint(sc, MPS_FAULT,
516 "Multiple volumes! Direct Drive I/O will not be "
522 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
524 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
525 phys_disk_page_address =
526 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
527 sc->DD_column_map[index].phys_disk_num;
528 if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
529 &phys_disk_pg0, phys_disk_page_address)) {
530 mps_dprint(sc, MPS_FAULT,
531 "mps_config_get_raid_pd_pg0 failed! Direct "
532 "Drive I/O will not be used.\n");
535 if (phys_disk_pg0.DevHandle == 0xFFFF) {
536 mps_dprint(sc, MPS_FAULT,
537 "Invalid Phys Disk DevHandle! Direct Drive "
538 "I/O will not be used.\n");
541 sc->DD_column_map[index].dev_handle =
542 phys_disk_pg0.DevHandle;
544 sc->WD_valid_config = TRUE;
547 free(raid_vol_pg0, M_MPT2);
552 * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
553 * @sc: per adapter object
554 * @mpi_reply: reply mf payload returned from firmware
555 * @config_page: contents of the config page
556 * @sz: size of buffer passed in config_page
559 * Returns 0 for success, non-zero for failure.
562 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
563 Mpi2DriverMappingPage0_t *config_page, u16 sz)
565 MPI2_CONFIG_REQUEST *request;
566 MPI2_CONFIG_REPLY *reply = NULL;
567 struct mps_command *cm;
568 Mpi2DriverMappingPage0_t *page = NULL;
572 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
574 memset(config_page, 0, sz);
575 if ((cm = mps_alloc_command(sc)) == NULL) {
576 printf("%s: command alloc failed @ line %d\n", __func__,
581 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
582 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
583 request->Function = MPI2_FUNCTION_CONFIG;
584 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
585 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
586 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
587 request->Header.PageNumber = 0;
588 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
589 request->PageAddress = sc->max_dpm_entries <<
590 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
591 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
593 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
595 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
596 if (error || (reply == NULL)) {
599 * If the request returns an error then we need to do a diag
602 printf("%s: request for header completed with error %d",
607 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
608 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
609 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
612 * If the request returns an error then we need to do a diag
615 printf("%s: header read with error; iocstatus = 0x%x\n",
616 __func__, ioc_status);
620 /* We have to do free and alloc for the reply-free and reply-post
621 * counters to match - Need to review the reply FIFO handling.
623 mps_free_command(sc, cm);
625 if ((cm = mps_alloc_command(sc)) == NULL) {
626 printf("%s: command alloc failed @ line %d\n", __func__,
631 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
632 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
633 request->Function = MPI2_FUNCTION_CONFIG;
634 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
635 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
636 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
637 request->Header.PageNumber = 0;
638 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
639 request->PageAddress = sc->max_dpm_entries <<
640 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
641 request->ExtPageLength = mpi_reply->ExtPageLength;
642 cm->cm_length = le16toh(request->ExtPageLength) * 4;
643 cm->cm_sge = &request->PageBufferSGE;
644 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
645 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
646 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
647 page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT);
649 printf("%s: page alloc failed\n", __func__);
654 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
656 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
657 if (error || (reply == NULL)) {
660 * If the request returns an error then we need to do a diag
663 printf("%s: request for page completed with error %d",
668 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
669 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
670 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
673 * If the request returns an error then we need to do a diag
676 printf("%s: page read with error; iocstatus = 0x%x\n",
677 __func__, ioc_status);
681 bcopy(page, config_page, MIN(cm->cm_length, sz));
685 mps_free_command(sc, cm);
690 * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
691 * @sc: per adapter object
692 * @mpi_reply: reply mf payload returned from firmware
693 * @config_page: contents of the config page
694 * @entry_idx: entry index in DPM Page0 to be modified
697 * Returns 0 for success, non-zero for failure.
700 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
701 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
703 MPI2_CONFIG_REQUEST *request;
704 MPI2_CONFIG_REPLY *reply = NULL;
705 struct mps_command *cm;
706 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
710 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
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_HEADER;
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 /* We can remove below two lines ????*/
727 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
728 request->PageAddress |= htole16(entry_idx);
729 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
731 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
733 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
734 if (error || (reply == NULL)) {
737 * If the request returns an error then we need to do a diag
740 printf("%s: request for header completed with error %d",
745 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
746 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
747 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
750 * If the request returns an error then we need to do a diag
753 printf("%s: header read with error; iocstatus = 0x%x\n",
754 __func__, ioc_status);
758 /* We have to do free and alloc for the reply-free and reply-post
759 * counters to match - Need to review the reply FIFO handling.
761 mps_free_command(sc, cm);
763 if ((cm = mps_alloc_command(sc)) == NULL) {
764 printf("%s: command alloc failed @ line %d\n", __func__,
769 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
770 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
771 request->Function = MPI2_FUNCTION_CONFIG;
772 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
773 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
774 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
775 request->Header.PageNumber = 0;
776 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
777 request->ExtPageLength = mpi_reply->ExtPageLength;
778 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
779 request->PageAddress |= htole16(entry_idx);
780 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
781 cm->cm_sge = &request->PageBufferSGE;
782 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
783 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
784 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
785 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
787 printf("%s: page alloc failed\n", __func__);
791 bcopy(config_page, page, MIN(cm->cm_length,
792 (sizeof(Mpi2DriverMappingPage0_t))));
794 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
796 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
797 if (error || (reply == NULL)) {
800 * If the request returns an error then we need to do a diag
803 printf("%s: request to write page completed with error %d",
808 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
809 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
810 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
813 * If the request returns an error then we need to do a diag
816 printf("%s: page written with error; iocstatus = 0x%x\n",
817 __func__, ioc_status);
824 mps_free_command(sc, cm);
829 * mps_config_get_sas_device_pg0 - obtain sas device page 0
830 * @sc: per adapter object
831 * @mpi_reply: reply mf payload returned from firmware
832 * @config_page: contents of the config page
833 * @form: GET_NEXT_HANDLE or HANDLE
834 * @handle: device handle
837 * Returns 0 for success, non-zero for failure.
840 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
841 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
843 MPI2_CONFIG_REQUEST *request;
844 MPI2_CONFIG_REPLY *reply = NULL;
845 struct mps_command *cm;
846 Mpi2SasDevicePage0_t *page = NULL;
850 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
852 if ((cm = mps_alloc_command(sc)) == NULL) {
853 printf("%s: command alloc failed @ line %d\n", __func__,
858 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
859 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
860 request->Function = MPI2_FUNCTION_CONFIG;
861 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
862 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
863 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
864 request->Header.PageNumber = 0;
865 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
866 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
868 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
870 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
871 if (error || (reply == NULL)) {
874 * If the request returns an error then we need to do a diag
877 printf("%s: request for header completed with error %d",
882 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
883 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
884 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
887 * If the request returns an error then we need to do a diag
890 printf("%s: header read with error; iocstatus = 0x%x\n",
891 __func__, ioc_status);
895 /* We have to do free and alloc for the reply-free and reply-post
896 * counters to match - Need to review the reply FIFO handling.
898 mps_free_command(sc, cm);
900 if ((cm = mps_alloc_command(sc)) == NULL) {
901 printf("%s: command alloc failed @ line %d\n", __func__,
906 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
907 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
908 request->Function = MPI2_FUNCTION_CONFIG;
909 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
910 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
911 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
912 request->Header.PageNumber = 0;
913 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
914 request->ExtPageLength = mpi_reply->ExtPageLength;
915 request->PageAddress = htole32(form | handle);
916 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
917 cm->cm_sge = &request->PageBufferSGE;
918 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
919 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
920 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
921 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
923 printf("%s: page alloc failed\n", __func__);
929 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
931 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
932 if (error || (reply == NULL)) {
935 * If the request returns an error then we need to do a diag
938 printf("%s: request for page completed with error %d",
943 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
944 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
945 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
948 * If the request returns an error then we need to do a diag
951 printf("%s: page read with error; iocstatus = 0x%x\n",
952 __func__, ioc_status);
956 bcopy(page, config_page, MIN(cm->cm_length,
957 sizeof(Mpi2SasDevicePage0_t)));
961 mps_free_command(sc, cm);
966 * mps_config_get_bios_pg3 - obtain BIOS page 3
967 * @sc: per adapter object
968 * @mpi_reply: reply mf payload returned from firmware
969 * @config_page: contents of the config page
972 * Returns 0 for success, non-zero for failure.
975 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
976 Mpi2BiosPage3_t *config_page)
978 MPI2_CONFIG_REQUEST *request;
979 MPI2_CONFIG_REPLY *reply = NULL;
980 struct mps_command *cm;
981 Mpi2BiosPage3_t *page = NULL;
985 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
987 if ((cm = mps_alloc_command(sc)) == NULL) {
988 printf("%s: command alloc failed @ line %d\n", __func__,
993 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
994 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
995 request->Function = MPI2_FUNCTION_CONFIG;
996 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
997 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
998 request->Header.PageNumber = 3;
999 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1000 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1002 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1004 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1005 if (error || (reply == NULL)) {
1008 * If the request returns an error then we need to do a diag
1011 printf("%s: request for header completed with error %d",
1016 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1017 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1018 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1021 * If the request returns an error then we need to do a diag
1024 printf("%s: header read with error; iocstatus = 0x%x\n",
1025 __func__, ioc_status);
1029 /* We have to do free and alloc for the reply-free and reply-post
1030 * counters to match - Need to review the reply FIFO handling.
1032 mps_free_command(sc, cm);
1034 if ((cm = mps_alloc_command(sc)) == NULL) {
1035 printf("%s: command alloc failed @ line %d\n", __func__,
1040 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1041 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1042 request->Function = MPI2_FUNCTION_CONFIG;
1043 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1044 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1045 request->Header.PageNumber = 3;
1046 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1047 request->Header.PageLength = mpi_reply->Header.PageLength;
1048 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1049 cm->cm_sge = &request->PageBufferSGE;
1050 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1051 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1052 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1053 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1055 printf("%s: page alloc failed\n", __func__);
1061 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1063 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1064 if (error || (reply == NULL)) {
1067 * If the request returns an error then we need to do a diag
1070 printf("%s: request for page completed with error %d",
1075 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1076 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1077 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1080 * If the request returns an error then we need to do a diag
1083 printf("%s: page read with error; iocstatus = 0x%x\n",
1084 __func__, ioc_status);
1088 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1092 mps_free_command(sc, cm);
1097 * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1098 * @sc: per adapter object
1099 * @mpi_reply: reply mf payload returned from firmware
1100 * @config_page: contents of the config page
1101 * @page_address: form and handle value used to get page
1104 * Returns 0 for success, non-zero for failure.
1107 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1108 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1110 MPI2_CONFIG_REQUEST *request;
1111 MPI2_CONFIG_REPLY *reply = NULL;
1112 struct mps_command *cm;
1113 Mpi2RaidVolPage0_t *page = NULL;
1117 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1119 if ((cm = mps_alloc_command(sc)) == NULL) {
1120 printf("%s: command alloc failed @ line %d\n", __func__,
1125 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1126 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1127 request->Function = MPI2_FUNCTION_CONFIG;
1128 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1129 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1130 request->Header.PageNumber = 0;
1131 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1132 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1136 * This page must be polled because the IOC isn't ready yet when this
1139 error = mps_wait_command(sc, &cm, 60, 0);
1141 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1142 if (error || (reply == NULL)) {
1144 /* If the poll returns error then we need to do diag reset */
1145 printf("%s: poll for header completed with error %d",
1150 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1151 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1152 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1154 /* If the poll returns error then we need to do diag reset */
1155 printf("%s: header read with error; iocstatus = 0x%x\n",
1156 __func__, ioc_status);
1160 /* We have to do free and alloc for the reply-free and reply-post
1161 * counters to match - Need to review the reply FIFO handling.
1163 mps_free_command(sc, cm);
1165 if ((cm = mps_alloc_command(sc)) == NULL) {
1166 printf("%s: command alloc failed @ line %d\n", __func__,
1171 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1172 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1173 request->Function = MPI2_FUNCTION_CONFIG;
1174 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1175 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1176 request->Header.PageNumber = 0;
1177 request->Header.PageLength = mpi_reply->Header.PageLength;
1178 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1179 request->PageAddress = page_address;
1180 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1181 cm->cm_sge = &request->PageBufferSGE;
1182 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1183 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1184 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1185 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1187 printf("%s: page alloc failed\n", __func__);
1194 * This page must be polled because the IOC isn't ready yet when this
1197 error = mps_wait_command(sc, &cm, 60, 0);
1199 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1200 if (error || (reply == NULL)) {
1202 /* If the poll returns error then we need to do diag reset */
1203 printf("%s: poll for page completed with error %d",
1208 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1209 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1210 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1212 /* If the poll returns error then we need to do diag reset */
1213 printf("%s: page read with error; iocstatus = 0x%x\n",
1214 __func__, ioc_status);
1218 bcopy(page, config_page, cm->cm_length);
1222 mps_free_command(sc, cm);
1227 * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1228 * @sc: per adapter object
1229 * @mpi_reply: reply mf payload returned from firmware
1230 * @config_page: contents of the config page
1231 * @form: GET_NEXT_HANDLE or HANDLE
1232 * @handle: volume handle
1235 * Returns 0 for success, non-zero for failure.
1238 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1239 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1241 MPI2_CONFIG_REQUEST *request;
1242 MPI2_CONFIG_REPLY *reply = NULL;
1243 struct mps_command *cm;
1244 Mpi2RaidVolPage1_t *page = NULL;
1248 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1250 if ((cm = mps_alloc_command(sc)) == NULL) {
1251 printf("%s: command alloc failed @ line %d\n", __func__,
1256 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1257 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1258 request->Function = MPI2_FUNCTION_CONFIG;
1259 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1260 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1261 request->Header.PageNumber = 1;
1262 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1263 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1265 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1267 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1268 if (error || (reply == NULL)) {
1271 * If the request returns an error then we need to do a diag
1274 printf("%s: request for header completed with error %d",
1279 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1280 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1281 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1284 * If the request returns an error then we need to do a diag
1287 printf("%s: header read with error; iocstatus = 0x%x\n",
1288 __func__, ioc_status);
1292 /* We have to do free and alloc for the reply-free and reply-post
1293 * counters to match - Need to review the reply FIFO handling.
1295 mps_free_command(sc, cm);
1297 if ((cm = mps_alloc_command(sc)) == NULL) {
1298 printf("%s: command alloc failed @ line %d\n", __func__,
1303 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1304 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1305 request->Function = MPI2_FUNCTION_CONFIG;
1306 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1307 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1308 request->Header.PageNumber = 1;
1309 request->Header.PageLength = mpi_reply->Header.PageLength;
1310 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1311 request->PageAddress = htole32(form | handle);
1312 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1313 cm->cm_sge = &request->PageBufferSGE;
1314 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1315 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1316 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1317 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1319 printf("%s: page alloc failed\n", __func__);
1325 error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1327 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1328 if (error || (reply == NULL)) {
1331 * If the request returns an error then we need to do a diag
1334 printf("%s: request for page completed with error %d",
1339 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1340 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1341 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1344 * If the request returns an error then we need to do a diag
1347 printf("%s: page read with error; iocstatus = 0x%x\n",
1348 __func__, ioc_status);
1352 bcopy(page, config_page, MIN(cm->cm_length,
1353 sizeof(Mpi2RaidVolPage1_t)));
1357 mps_free_command(sc, cm);
1362 * mps_config_get_volume_wwid - returns wwid given the volume handle
1363 * @sc: per adapter object
1364 * @volume_handle: volume handle
1365 * @wwid: volume wwid
1368 * Returns 0 for success, non-zero for failure.
1371 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1373 Mpi2ConfigReply_t mpi_reply;
1374 Mpi2RaidVolPage1_t raid_vol_pg1;
1377 if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1378 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1379 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1380 raid_vol_pg1.WWID.Low);
1387 * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1388 * @sc: per adapter object
1389 * @mpi_reply: reply mf payload returned from firmware
1390 * @config_page: contents of the config page
1391 * @page_address: form and handle value used to get page
1394 * Returns 0 for success, non-zero for failure.
1397 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1398 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1400 MPI2_CONFIG_REQUEST *request;
1401 MPI2_CONFIG_REPLY *reply = NULL;
1402 struct mps_command *cm;
1403 Mpi2RaidPhysDiskPage0_t *page = NULL;
1407 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1409 if ((cm = mps_alloc_command(sc)) == NULL) {
1410 printf("%s: command alloc failed @ line %d\n", __func__,
1415 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1416 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1417 request->Function = MPI2_FUNCTION_CONFIG;
1418 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1419 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1420 request->Header.PageNumber = 0;
1421 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1422 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1426 * This page must be polled because the IOC isn't ready yet when this
1429 error = mps_wait_command(sc, &cm, 60, 0);
1431 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1432 if (error || (reply == NULL)) {
1434 /* If the poll returns error then we need to do diag reset */
1435 printf("%s: poll for header completed with error %d",
1440 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1441 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1442 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1444 /* If the poll returns error then we need to do diag reset */
1445 printf("%s: header read with error; iocstatus = 0x%x\n",
1446 __func__, ioc_status);
1450 /* We have to do free and alloc for the reply-free and reply-post
1451 * counters to match - Need to review the reply FIFO handling.
1453 mps_free_command(sc, cm);
1455 if ((cm = mps_alloc_command(sc)) == NULL) {
1456 printf("%s: command alloc failed @ line %d\n", __func__,
1461 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1462 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1463 request->Function = MPI2_FUNCTION_CONFIG;
1464 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1465 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1466 request->Header.PageNumber = 0;
1467 request->Header.PageLength = mpi_reply->Header.PageLength;
1468 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1469 request->PageAddress = page_address;
1470 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1471 cm->cm_sge = &request->PageBufferSGE;
1472 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1473 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1474 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1475 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1477 printf("%s: page alloc failed\n", __func__);
1484 * This page must be polled because the IOC isn't ready yet when this
1487 error = mps_wait_command(sc, &cm, 60, 0);
1489 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1490 if (error || (reply == NULL)) {
1492 /* If the poll returns error then we need to do diag reset */
1493 printf("%s: poll for page completed with error %d",
1498 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1499 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1500 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1502 /* If the poll returns error then we need to do diag reset */
1503 printf("%s: page read with error; iocstatus = 0x%x\n",
1504 __func__, ioc_status);
1508 bcopy(page, config_page, MIN(cm->cm_length,
1509 sizeof(Mpi2RaidPhysDiskPage0_t)));
1513 mps_free_command(sc, cm);