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_request_polled(sc, cm);
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_request_polled(sc, cm);
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 guarentee 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 (mpi_reply.IOCStatus !=
503 MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
504 mps_dprint(sc, MPS_FAULT,
505 "Multiple RAID Volume Page0! Direct Drive "
506 "I/O will not be used.\n");
510 mps_dprint(sc, MPS_FAULT,
511 "Multiple volumes! Direct Drive I/O will not be "
517 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
519 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
520 phys_disk_page_address =
521 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
522 sc->DD_column_map[index].phys_disk_num;
523 if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
524 &phys_disk_pg0, phys_disk_page_address)) {
525 mps_dprint(sc, MPS_FAULT,
526 "mps_config_get_raid_pd_pg0 failed! Direct "
527 "Drive I/O will not be used.\n");
530 if (phys_disk_pg0.DevHandle == 0xFFFF) {
531 mps_dprint(sc, MPS_FAULT,
532 "Invalid Phys Disk DevHandle! Direct Drive "
533 "I/O will not be used.\n");
536 sc->DD_column_map[index].dev_handle =
537 phys_disk_pg0.DevHandle;
539 sc->WD_valid_config = TRUE;
542 free(raid_vol_pg0, M_MPT2);
547 * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
548 * @sc: per adapter object
549 * @mpi_reply: reply mf payload returned from firmware
550 * @config_page: contents of the config page
551 * @sz: size of buffer passed in config_page
554 * Returns 0 for success, non-zero for failure.
557 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
558 Mpi2DriverMappingPage0_t *config_page, u16 sz)
560 MPI2_CONFIG_REQUEST *request;
561 MPI2_CONFIG_REPLY *reply;
562 struct mps_command *cm;
563 Mpi2DriverMappingPage0_t *page = NULL;
567 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
569 memset(config_page, 0, sz);
570 if ((cm = mps_alloc_command(sc)) == NULL) {
571 printf("%s: command alloc failed @ line %d\n", __func__,
576 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
577 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
578 request->Function = MPI2_FUNCTION_CONFIG;
579 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
580 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
581 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
582 request->Header.PageNumber = 0;
583 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
584 request->PageAddress = sc->max_dpm_entries <<
585 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
586 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
588 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
589 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
590 if (error || (reply == NULL)) {
593 * If the request returns an error then we need to do a diag
596 printf("%s: request for header completed with error %d",
601 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
602 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
603 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
606 * If the request returns an error then we need to do a diag
609 printf("%s: header read with error; iocstatus = 0x%x\n",
610 __func__, ioc_status);
614 /* We have to do free and alloc for the reply-free and reply-post
615 * counters to match - Need to review the reply FIFO handling.
617 mps_free_command(sc, cm);
619 if ((cm = mps_alloc_command(sc)) == NULL) {
620 printf("%s: command alloc failed @ line %d\n", __func__,
625 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
626 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
627 request->Function = MPI2_FUNCTION_CONFIG;
628 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
629 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
630 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
631 request->Header.PageNumber = 0;
632 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
633 request->PageAddress = sc->max_dpm_entries <<
634 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
635 request->ExtPageLength = mpi_reply->ExtPageLength;
636 cm->cm_length = le16toh(request->ExtPageLength) * 4;
637 cm->cm_sge = &request->PageBufferSGE;
638 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
639 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
640 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
641 page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT);
643 printf("%s: page alloc failed\n", __func__);
648 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
649 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
650 if (error || (reply == NULL)) {
653 * If the request returns an error then we need to do a diag
656 printf("%s: request for page completed with error %d",
661 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
662 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
663 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
666 * If the request returns an error then we need to do a diag
669 printf("%s: page read with error; iocstatus = 0x%x\n",
670 __func__, ioc_status);
674 bcopy(page, config_page, MIN(cm->cm_length, sz));
678 mps_free_command(sc, cm);
683 * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
684 * @sc: per adapter object
685 * @mpi_reply: reply mf payload returned from firmware
686 * @config_page: contents of the config page
687 * @entry_idx: entry index in DPM Page0 to be modified
690 * Returns 0 for success, non-zero for failure.
693 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
694 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
696 MPI2_CONFIG_REQUEST *request;
697 MPI2_CONFIG_REPLY *reply;
698 struct mps_command *cm;
699 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
703 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
705 if ((cm = mps_alloc_command(sc)) == NULL) {
706 printf("%s: command alloc failed @ line %d\n", __func__,
711 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
712 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
713 request->Function = MPI2_FUNCTION_CONFIG;
714 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
715 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
716 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
717 request->Header.PageNumber = 0;
718 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
719 /* We can remove below two lines ????*/
720 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
721 request->PageAddress |= htole16(entry_idx);
722 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
724 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
725 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
726 if (error || (reply == NULL)) {
729 * If the request returns an error then we need to do a diag
732 printf("%s: request for header completed with error %d",
737 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
738 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
739 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
742 * If the request returns an error then we need to do a diag
745 printf("%s: header read with error; iocstatus = 0x%x\n",
746 __func__, ioc_status);
750 /* We have to do free and alloc for the reply-free and reply-post
751 * counters to match - Need to review the reply FIFO handling.
753 mps_free_command(sc, cm);
755 if ((cm = mps_alloc_command(sc)) == NULL) {
756 printf("%s: command alloc failed @ line %d\n", __func__,
761 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
762 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
763 request->Function = MPI2_FUNCTION_CONFIG;
764 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
765 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
766 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
767 request->Header.PageNumber = 0;
768 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
769 request->ExtPageLength = mpi_reply->ExtPageLength;
770 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
771 request->PageAddress |= htole16(entry_idx);
772 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
773 cm->cm_sge = &request->PageBufferSGE;
774 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
775 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
776 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
777 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
779 printf("%s: page alloc failed\n", __func__);
783 bcopy(config_page, page, MIN(cm->cm_length,
784 (sizeof(Mpi2DriverMappingPage0_t))));
786 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
787 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
788 if (error || (reply == NULL)) {
791 * If the request returns an error then we need to do a diag
794 printf("%s: request to write page completed with error %d",
799 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
800 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
801 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
804 * If the request returns an error then we need to do a diag
807 printf("%s: page written with error; iocstatus = 0x%x\n",
808 __func__, ioc_status);
815 mps_free_command(sc, cm);
820 * mps_config_get_sas_device_pg0 - obtain sas device page 0
821 * @sc: per adapter object
822 * @mpi_reply: reply mf payload returned from firmware
823 * @config_page: contents of the config page
824 * @form: GET_NEXT_HANDLE or HANDLE
825 * @handle: device handle
828 * Returns 0 for success, non-zero for failure.
831 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
832 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
834 MPI2_CONFIG_REQUEST *request;
835 MPI2_CONFIG_REPLY *reply;
836 struct mps_command *cm;
837 Mpi2SasDevicePage0_t *page = NULL;
841 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
843 if ((cm = mps_alloc_command(sc)) == NULL) {
844 printf("%s: command alloc failed @ line %d\n", __func__,
849 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
850 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
851 request->Function = MPI2_FUNCTION_CONFIG;
852 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
853 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
854 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
855 request->Header.PageNumber = 0;
856 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
857 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
859 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
860 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
861 if (error || (reply == NULL)) {
864 * If the request returns an error then we need to do a diag
867 printf("%s: request for header completed with error %d",
872 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
873 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
874 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
877 * If the request returns an error then we need to do a diag
880 printf("%s: header read with error; iocstatus = 0x%x\n",
881 __func__, ioc_status);
885 /* We have to do free and alloc for the reply-free and reply-post
886 * counters to match - Need to review the reply FIFO handling.
888 mps_free_command(sc, cm);
890 if ((cm = mps_alloc_command(sc)) == NULL) {
891 printf("%s: command alloc failed @ line %d\n", __func__,
896 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
897 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
898 request->Function = MPI2_FUNCTION_CONFIG;
899 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
900 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
901 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
902 request->Header.PageNumber = 0;
903 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
904 request->ExtPageLength = mpi_reply->ExtPageLength;
905 request->PageAddress = htole32(form | handle);
906 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
907 cm->cm_sge = &request->PageBufferSGE;
908 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
909 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
910 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
911 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
913 printf("%s: page alloc failed\n", __func__);
919 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
920 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
921 if (error || (reply == NULL)) {
924 * If the request returns an error then we need to do a diag
927 printf("%s: request for page completed with error %d",
932 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
933 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
934 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
937 * If the request returns an error then we need to do a diag
940 printf("%s: page read with error; iocstatus = 0x%x\n",
941 __func__, ioc_status);
945 bcopy(page, config_page, MIN(cm->cm_length,
946 sizeof(Mpi2SasDevicePage0_t)));
950 mps_free_command(sc, cm);
955 * mps_config_get_bios_pg3 - obtain BIOS page 3
956 * @sc: per adapter object
957 * @mpi_reply: reply mf payload returned from firmware
958 * @config_page: contents of the config page
961 * Returns 0 for success, non-zero for failure.
964 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
965 Mpi2BiosPage3_t *config_page)
967 MPI2_CONFIG_REQUEST *request;
968 MPI2_CONFIG_REPLY *reply;
969 struct mps_command *cm;
970 Mpi2BiosPage3_t *page = NULL;
974 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
976 if ((cm = mps_alloc_command(sc)) == NULL) {
977 printf("%s: command alloc failed @ line %d\n", __func__,
982 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
983 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
984 request->Function = MPI2_FUNCTION_CONFIG;
985 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
986 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
987 request->Header.PageNumber = 3;
988 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
989 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
991 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
992 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
993 if (error || (reply == NULL)) {
996 * If the request returns an error then we need to do a diag
999 printf("%s: request for header completed with error %d",
1004 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1005 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1006 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1009 * If the request returns an error then we need to do a diag
1012 printf("%s: header read with error; iocstatus = 0x%x\n",
1013 __func__, ioc_status);
1017 /* We have to do free and alloc for the reply-free and reply-post
1018 * counters to match - Need to review the reply FIFO handling.
1020 mps_free_command(sc, cm);
1022 if ((cm = mps_alloc_command(sc)) == NULL) {
1023 printf("%s: command alloc failed @ line %d\n", __func__,
1028 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1029 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1030 request->Function = MPI2_FUNCTION_CONFIG;
1031 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1032 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1033 request->Header.PageNumber = 3;
1034 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1035 request->Header.PageLength = mpi_reply->Header.PageLength;
1036 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1037 cm->cm_sge = &request->PageBufferSGE;
1038 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1039 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1040 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1041 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1043 printf("%s: page alloc failed\n", __func__);
1049 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1050 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1051 if (error || (reply == NULL)) {
1054 * If the request returns an error then we need to do a diag
1057 printf("%s: request for page completed with error %d",
1062 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1063 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1064 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1067 * If the request returns an error then we need to do a diag
1070 printf("%s: page read with error; iocstatus = 0x%x\n",
1071 __func__, ioc_status);
1075 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1079 mps_free_command(sc, cm);
1084 * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1085 * @sc: per adapter object
1086 * @mpi_reply: reply mf payload returned from firmware
1087 * @config_page: contents of the config page
1088 * @page_address: form and handle value used to get page
1091 * Returns 0 for success, non-zero for failure.
1094 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1095 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1097 MPI2_CONFIG_REQUEST *request;
1098 MPI2_CONFIG_REPLY *reply;
1099 struct mps_command *cm;
1100 Mpi2RaidVolPage0_t *page = NULL;
1104 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1106 if ((cm = mps_alloc_command(sc)) == NULL) {
1107 printf("%s: command alloc failed @ line %d\n", __func__,
1112 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1113 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1114 request->Function = MPI2_FUNCTION_CONFIG;
1115 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1116 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1117 request->Header.PageNumber = 0;
1118 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1119 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1123 * This page must be polled because the IOC isn't ready yet when this
1126 error = mps_request_polled(sc, cm);
1127 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1128 if (error || (reply == NULL)) {
1130 /* If the poll returns error then we need to do diag reset */
1131 printf("%s: poll for header completed with error %d",
1136 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1137 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1138 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1140 /* If the poll returns error then we need to do diag reset */
1141 printf("%s: header read with error; iocstatus = 0x%x\n",
1142 __func__, ioc_status);
1146 /* We have to do free and alloc for the reply-free and reply-post
1147 * counters to match - Need to review the reply FIFO handling.
1149 mps_free_command(sc, cm);
1151 if ((cm = mps_alloc_command(sc)) == NULL) {
1152 printf("%s: command alloc failed @ line %d\n", __func__,
1157 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1158 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1159 request->Function = MPI2_FUNCTION_CONFIG;
1160 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1161 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1162 request->Header.PageNumber = 0;
1163 request->Header.PageLength = mpi_reply->Header.PageLength;
1164 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1165 request->PageAddress = page_address;
1166 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1167 cm->cm_sge = &request->PageBufferSGE;
1168 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1169 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1170 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1171 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1173 printf("%s: page alloc failed\n", __func__);
1180 * This page must be polled because the IOC isn't ready yet when this
1183 error = mps_request_polled(sc, cm);
1184 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1185 if (error || (reply == NULL)) {
1187 /* If the poll returns error then we need to do diag reset */
1188 printf("%s: poll for page completed with error %d",
1193 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1194 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1195 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1197 /* If the poll returns error then we need to do diag reset */
1198 printf("%s: page read with error; iocstatus = 0x%x\n",
1199 __func__, ioc_status);
1203 bcopy(page, config_page, cm->cm_length);
1207 mps_free_command(sc, cm);
1212 * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1213 * @sc: per adapter object
1214 * @mpi_reply: reply mf payload returned from firmware
1215 * @config_page: contents of the config page
1216 * @form: GET_NEXT_HANDLE or HANDLE
1217 * @handle: volume handle
1220 * Returns 0 for success, non-zero for failure.
1223 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1224 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1226 MPI2_CONFIG_REQUEST *request;
1227 MPI2_CONFIG_REPLY *reply;
1228 struct mps_command *cm;
1229 Mpi2RaidVolPage1_t *page = NULL;
1233 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1235 if ((cm = mps_alloc_command(sc)) == NULL) {
1236 printf("%s: command alloc failed @ line %d\n", __func__,
1241 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1242 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1243 request->Function = MPI2_FUNCTION_CONFIG;
1244 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1245 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1246 request->Header.PageNumber = 1;
1247 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1248 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1250 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1251 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1252 if (error || (reply == NULL)) {
1255 * If the request returns an error then we need to do a diag
1258 printf("%s: request for header completed with error %d",
1263 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1264 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1265 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1268 * If the request returns an error then we need to do a diag
1271 printf("%s: header read with error; iocstatus = 0x%x\n",
1272 __func__, ioc_status);
1276 /* We have to do free and alloc for the reply-free and reply-post
1277 * counters to match - Need to review the reply FIFO handling.
1279 mps_free_command(sc, cm);
1281 if ((cm = mps_alloc_command(sc)) == NULL) {
1282 printf("%s: command alloc failed @ line %d\n", __func__,
1287 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1288 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1289 request->Function = MPI2_FUNCTION_CONFIG;
1290 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1291 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1292 request->Header.PageNumber = 1;
1293 request->Header.PageLength = mpi_reply->Header.PageLength;
1294 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1295 request->PageAddress = htole32(form | handle);
1296 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1297 cm->cm_sge = &request->PageBufferSGE;
1298 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1299 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1300 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1301 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1303 printf("%s: page alloc failed\n", __func__);
1309 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1310 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1311 if (error || (reply == NULL)) {
1314 * If the request returns an error then we need to do a diag
1317 printf("%s: request for page completed with error %d",
1322 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1323 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1324 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1327 * If the request returns an error then we need to do a diag
1330 printf("%s: page read with error; iocstatus = 0x%x\n",
1331 __func__, ioc_status);
1335 bcopy(page, config_page, MIN(cm->cm_length,
1336 sizeof(Mpi2RaidVolPage1_t)));
1340 mps_free_command(sc, cm);
1345 * mps_config_get_volume_wwid - returns wwid given the volume handle
1346 * @sc: per adapter object
1347 * @volume_handle: volume handle
1348 * @wwid: volume wwid
1351 * Returns 0 for success, non-zero for failure.
1354 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1356 Mpi2ConfigReply_t mpi_reply;
1357 Mpi2RaidVolPage1_t raid_vol_pg1;
1360 if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1361 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1362 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1363 raid_vol_pg1.WWID.Low);
1370 * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1371 * @sc: per adapter object
1372 * @mpi_reply: reply mf payload returned from firmware
1373 * @config_page: contents of the config page
1374 * @page_address: form and handle value used to get page
1377 * Returns 0 for success, non-zero for failure.
1380 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1381 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1383 MPI2_CONFIG_REQUEST *request;
1384 MPI2_CONFIG_REPLY *reply;
1385 struct mps_command *cm;
1386 Mpi2RaidPhysDiskPage0_t *page = NULL;
1390 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1392 if ((cm = mps_alloc_command(sc)) == NULL) {
1393 printf("%s: command alloc failed @ line %d\n", __func__,
1398 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1399 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1400 request->Function = MPI2_FUNCTION_CONFIG;
1401 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1402 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1403 request->Header.PageNumber = 0;
1404 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1405 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1409 * This page must be polled because the IOC isn't ready yet when this
1412 error = mps_request_polled(sc, cm);
1413 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1414 if (error || (reply == NULL)) {
1416 /* If the poll returns error then we need to do diag reset */
1417 printf("%s: poll for header completed with error %d",
1422 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1423 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1424 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1426 /* If the poll returns error then we need to do diag reset */
1427 printf("%s: header read with error; iocstatus = 0x%x\n",
1428 __func__, ioc_status);
1432 /* We have to do free and alloc for the reply-free and reply-post
1433 * counters to match - Need to review the reply FIFO handling.
1435 mps_free_command(sc, cm);
1437 if ((cm = mps_alloc_command(sc)) == NULL) {
1438 printf("%s: command alloc failed @ line %d\n", __func__,
1443 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1444 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1445 request->Function = MPI2_FUNCTION_CONFIG;
1446 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1447 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1448 request->Header.PageNumber = 0;
1449 request->Header.PageLength = mpi_reply->Header.PageLength;
1450 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1451 request->PageAddress = page_address;
1452 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1453 cm->cm_sge = &request->PageBufferSGE;
1454 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1455 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1456 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1457 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1459 printf("%s: page alloc failed\n", __func__);
1466 * This page must be polled because the IOC isn't ready yet when this
1469 error = mps_request_polled(sc, cm);
1470 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1471 if (error || (reply == NULL)) {
1473 /* If the poll returns error then we need to do diag reset */
1474 printf("%s: poll for page completed with error %d",
1479 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1480 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1481 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1483 /* If the poll returns error then we need to do diag reset */
1484 printf("%s: page read with error; iocstatus = 0x%x\n",
1485 __func__, ioc_status);
1489 bcopy(page, config_page, MIN(cm->cm_length,
1490 sizeof(Mpi2RaidPhysDiskPage0_t)));
1494 mps_free_command(sc, cm);