2 * Copyright (c) 2011, 2012 LSI Corp.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * LSI MPT-Fusion Host Adapter FreeBSD
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 /* TODO Move headers to mpsvar */
33 #include <sys/types.h>
34 #include <sys/param.h>
36 #include <sys/mutex.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
40 #include <sys/kthread.h>
41 #include <sys/taskqueue.h>
43 #include <sys/endian.h>
44 #include <sys/sysctl.h>
45 #include <sys/eventhandler.h>
47 #include <machine/bus.h>
48 #include <machine/resource.h>
49 #include <dev/mps/mpi/mpi2_type.h>
50 #include <dev/mps/mpi/mpi2.h>
51 #include <dev/mps/mpi/mpi2_ioc.h>
52 #include <dev/mps/mpi/mpi2_sas.h>
53 #include <dev/mps/mpi/mpi2_cnfg.h>
54 #include <dev/mps/mpi/mpi2_init.h>
55 #include <dev/mps/mpi/mpi2_tool.h>
56 #include <dev/mps/mps_ioctl.h>
57 #include <dev/mps/mpsvar.h>
60 * mps_config_get_ioc_pg8 - obtain ioc page 8
61 * @sc: per adapter object
62 * @mpi_reply: reply mf payload returned from firmware
63 * @config_page: contents of the config page
66 * Returns 0 for success, non-zero for failure.
69 mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
70 Mpi2IOCPage8_t *config_page)
72 MPI2_CONFIG_REQUEST *request;
73 MPI2_CONFIG_REPLY *reply;
74 struct mps_command *cm;
75 MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
79 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
81 if ((cm = mps_alloc_command(sc)) == NULL) {
82 printf("%s: command alloc failed @ line %d\n", __func__,
87 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
88 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
89 request->Function = MPI2_FUNCTION_CONFIG;
90 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
91 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
92 request->Header.PageNumber = 8;
93 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
94 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
96 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
97 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
98 if (error || (reply == NULL)) {
101 * If the request returns an error then we need to do a diag
104 printf("%s: request for header completed with error %d",
109 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
110 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
111 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
114 * If the request returns an error then we need to do a diag
117 printf("%s: header read with error; iocstatus = 0x%x\n",
118 __func__, ioc_status);
122 /* We have to do free and alloc for the reply-free and reply-post
123 * counters to match - Need to review the reply FIFO handling.
125 mps_free_command(sc, cm);
127 if ((cm = mps_alloc_command(sc)) == NULL) {
128 printf("%s: command alloc failed @ line %d\n", __func__,
133 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
134 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
135 request->Function = MPI2_FUNCTION_CONFIG;
136 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
137 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
138 request->Header.PageNumber = 8;
139 request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
140 request->Header.PageLength = mpi_reply->Header.PageLength;
141 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
142 cm->cm_sge = &request->PageBufferSGE;
143 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
144 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
145 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
146 page = malloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT);
148 printf("%s: page alloc failed\n", __func__);
154 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
155 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
156 if (error || (reply == NULL)) {
159 * If the request returns an error then we need to do a diag
162 printf("%s: request for page completed with error %d",
167 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
168 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
169 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
172 * If the request returns an error then we need to do a diag
175 printf("%s: page read with error; iocstatus = 0x%x\n",
176 __func__, ioc_status);
180 bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
185 mps_free_command(sc, cm);
190 * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
191 * accordingly. Currently, this page does not need to return to caller.
192 * @sc: per adapter object
193 * @mpi_reply: reply mf payload returned from firmware
196 * Returns 0 for success, non-zero for failure.
199 mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
201 MPI2_CONFIG_REQUEST *request;
202 MPI2_CONFIG_REPLY *reply;
203 struct mps_command *cm;
204 pMpi2ManufacturingPagePS_t page = NULL;
206 uint8_t OEM_Value = 0;
210 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
212 if ((cm = mps_alloc_command(sc)) == NULL) {
213 printf("%s: command alloc failed @ line %d\n", __func__,
218 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
219 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
220 request->Function = MPI2_FUNCTION_CONFIG;
221 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
222 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
223 request->Header.PageNumber = 10;
224 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
225 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
229 * This page must be polled because the IOC isn't ready yet when this
232 error = mps_request_polled(sc, cm);
233 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
234 if (error || (reply == NULL)) {
236 /* If the poll returns error then we need to do diag reset */
237 printf("%s: poll for header completed with error %d",
242 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
243 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
244 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
246 /* If the poll returns error then we need to do diag reset */
247 printf("%s: header read with error; iocstatus = 0x%x\n",
248 __func__, ioc_status);
252 /* We have to do free and alloc for the reply-free and reply-post
253 * counters to match - Need to review the reply FIFO handling.
255 mps_free_command(sc, cm);
257 if ((cm = mps_alloc_command(sc)) == NULL) {
258 printf("%s: command alloc failed @ line %d\n", __func__,
263 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
264 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
265 request->Function = MPI2_FUNCTION_CONFIG;
266 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
267 request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
268 request->Header.PageNumber = 10;
269 request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
270 request->Header.PageLength = mpi_reply->Header.PageLength;
271 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
272 cm->cm_sge = &request->PageBufferSGE;
273 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
274 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
275 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
276 page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT);
278 printf("%s: page alloc failed\n", __func__);
285 * This page must be polled because the IOC isn't ready yet when this
288 error = mps_request_polled(sc, cm);
289 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
290 if (error || (reply == NULL)) {
292 /* If the poll returns error then we need to do diag reset */
293 printf("%s: poll for page completed with error %d",
298 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
299 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
300 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
302 /* If the poll returns error then we need to do diag reset */
303 printf("%s: page read with error; iocstatus = 0x%x\n",
304 __func__, ioc_status);
310 * If OEM ID is unknown, fail the request.
312 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
313 OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
314 if (OEM_Value != MPS_WD_LSI_OEM) {
315 mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
316 "(0x%x)\n", OEM_Value);
322 * Set the phys disks hide/expose value.
324 pPS_info = &page->ProductSpecificInfo;
325 sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
326 sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
327 if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
328 (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
329 (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
330 mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
331 "hide/expose: 0x%x\n", sc->WD_hide_expose);
339 mps_free_command(sc, cm);
344 * mps_base_static_config_pages - static start of day config pages.
345 * @sc: per adapter object
350 mps_base_static_config_pages(struct mps_softc *sc)
352 Mpi2ConfigReply_t mpi_reply;
356 while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
359 /* We need to Handle this situation */
367 * mps_wd_config_pages - get info required to support WarpDrive. This needs to
368 * be called after discovery is complete to guarentee that IR info is there.
369 * @sc: per adapter object
374 mps_wd_config_pages(struct mps_softc *sc)
376 Mpi2ConfigReply_t mpi_reply;
377 pMpi2RaidVolPage0_t raid_vol_pg0 = NULL;
378 Mpi2RaidPhysDiskPage0_t phys_disk_pg0;
379 pMpi2RaidVol0PhysDisk_t pRVPD;
380 uint32_t stripe_size, phys_disk_page_address;
382 uint8_t index, stripe_exp = 0, block_exp = 0;
385 * Get the WD settings from manufacturing page 10 if using a WD HBA.
386 * This will be used to determine if phys disks should always be
387 * hidden, hidden only if part of a WD volume, or never hidden. Also,
388 * get the WD RAID Volume info and fail if volume does not exist or if
389 * volume does not meet the requirements for a WD volume. No retry
390 * here. Just default to HIDE ALWAYS if man Page10 fails, or clear WD
391 * Valid flag if Volume info fails.
393 sc->WD_valid_config = FALSE;
394 if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) {
395 if (mps_config_get_man_pg10(sc, &mpi_reply)) {
396 mps_dprint(sc, MPS_FAULT,
397 "mps_config_get_man_pg10 failed! Using 0 (Hide "
398 "Always) for WarpDrive hide/expose value.\n");
399 sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
403 * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
405 raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) +
406 (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
407 M_MPT2, M_ZERO | M_NOWAIT);
409 printf("%s: page alloc failed\n", __func__);
413 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
415 mps_dprint(sc, MPS_INFO,
416 "mps_config_get_raid_volume_pg0 failed! Assuming "
417 "WarpDrive IT mode.\n");
422 * Check for valid WD configuration:
423 * volume type is RAID0
424 * number of phys disks in the volume is no more than 8
426 if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) ||
427 (raid_vol_pg0->NumPhysDisks > 8)) {
428 mps_dprint(sc, MPS_FAULT,
429 "Invalid WarpDrive configuration. Direct Drive I/O "
430 "will not be used.\n");
435 * Save the WD RAID data to be used during WD I/O.
437 sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High <<
438 32 | (uint64_t)raid_vol_pg0->MaxLBA.Low);
439 sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks;
440 sc->DD_dev_handle = raid_vol_pg0->DevHandle;
441 sc->DD_stripe_size = raid_vol_pg0->StripeSize;
442 sc->DD_block_size = raid_vol_pg0->BlockSize;
445 * Find power of 2 of stripe size and set this as the exponent.
446 * Fail if stripe size is 0.
448 stripe_size = raid_vol_pg0->StripeSize;
449 for (index = 0; index < 32; index++) {
456 mps_dprint(sc, MPS_FAULT,
457 "RAID Volume's stripe size is 0. Direct Drive I/O "
458 "will not be used.\n");
461 sc->DD_stripe_exponent = stripe_exp;
464 * Find power of 2 of block size and set this as the exponent.
465 * Fail if block size is 0.
467 block_size = raid_vol_pg0->BlockSize;
468 for (index = 0; index < 16; index++) {
475 mps_dprint(sc, MPS_FAULT,
476 "RAID Volume's block size is 0. Direct Drive I/O "
477 "will not be used.\n");
480 sc->DD_block_exponent = block_exp;
483 * Loop through all of the volume's Phys Disks to map the phys
484 * disk number into the columm map. This is used during Direct
485 * Drive I/O to send the request to the correct SSD.
487 pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk;
488 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
489 sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num =
495 * Get second RAID Volume Page0 using previous handle. This
496 * page should not exist. If it does, must not proceed with WD
499 if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
500 raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
501 if (mpi_reply.IOCStatus !=
502 MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
503 mps_dprint(sc, MPS_FAULT,
504 "Multiple RAID Volume Page0! Direct Drive "
505 "I/O will not be used.\n");
509 mps_dprint(sc, MPS_FAULT,
510 "Multiple volumes! Direct Drive I/O will not be "
516 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
518 for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
519 phys_disk_page_address =
520 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
521 sc->DD_column_map[index].phys_disk_num;
522 if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
523 &phys_disk_pg0, phys_disk_page_address)) {
524 mps_dprint(sc, MPS_FAULT,
525 "mps_config_get_raid_pd_pg0 failed! Direct "
526 "Drive I/O will not be used.\n");
529 if (phys_disk_pg0.DevHandle == 0xFFFF) {
530 mps_dprint(sc, MPS_FAULT,
531 "Invalid Phys Disk DevHandle! Direct Drive "
532 "I/O will not be used.\n");
535 sc->DD_column_map[index].dev_handle =
536 phys_disk_pg0.DevHandle;
538 sc->WD_valid_config = TRUE;
541 free(raid_vol_pg0, M_MPT2);
546 * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
547 * @sc: per adapter object
548 * @mpi_reply: reply mf payload returned from firmware
549 * @config_page: contents of the config page
550 * @sz: size of buffer passed in config_page
553 * Returns 0 for success, non-zero for failure.
556 mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
557 Mpi2DriverMappingPage0_t *config_page, u16 sz)
559 MPI2_CONFIG_REQUEST *request;
560 MPI2_CONFIG_REPLY *reply;
561 struct mps_command *cm;
562 Mpi2DriverMappingPage0_t *page = NULL;
566 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
568 memset(config_page, 0, sz);
569 if ((cm = mps_alloc_command(sc)) == NULL) {
570 printf("%s: command alloc failed @ line %d\n", __func__,
575 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
576 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
577 request->Function = MPI2_FUNCTION_CONFIG;
578 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
579 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
580 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
581 request->Header.PageNumber = 0;
582 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
583 request->PageAddress = sc->max_dpm_entries <<
584 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
585 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
587 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
588 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
589 if (error || (reply == NULL)) {
592 * If the request returns an error then we need to do a diag
595 printf("%s: request for header completed with error %d",
600 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
601 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
602 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
605 * If the request returns an error then we need to do a diag
608 printf("%s: header read with error; iocstatus = 0x%x\n",
609 __func__, ioc_status);
613 /* We have to do free and alloc for the reply-free and reply-post
614 * counters to match - Need to review the reply FIFO handling.
616 mps_free_command(sc, cm);
618 if ((cm = mps_alloc_command(sc)) == NULL) {
619 printf("%s: command alloc failed @ line %d\n", __func__,
624 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
625 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
626 request->Function = MPI2_FUNCTION_CONFIG;
627 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
628 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
629 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
630 request->Header.PageNumber = 0;
631 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
632 request->PageAddress = sc->max_dpm_entries <<
633 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
634 request->ExtPageLength = mpi_reply->ExtPageLength;
635 cm->cm_length = le16toh(request->ExtPageLength) * 4;
636 cm->cm_sge = &request->PageBufferSGE;
637 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
638 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
639 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
640 page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT);
642 printf("%s: page alloc failed\n", __func__);
647 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
648 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
649 if (error || (reply == NULL)) {
652 * If the request returns an error then we need to do a diag
655 printf("%s: request for page completed with error %d",
660 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
661 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
662 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
665 * If the request returns an error then we need to do a diag
668 printf("%s: page read with error; iocstatus = 0x%x\n",
669 __func__, ioc_status);
673 bcopy(page, config_page, MIN(cm->cm_length, sz));
677 mps_free_command(sc, cm);
682 * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
683 * @sc: per adapter object
684 * @mpi_reply: reply mf payload returned from firmware
685 * @config_page: contents of the config page
686 * @entry_idx: entry index in DPM Page0 to be modified
689 * Returns 0 for success, non-zero for failure.
692 int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
693 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
695 MPI2_CONFIG_REQUEST *request;
696 MPI2_CONFIG_REPLY *reply;
697 struct mps_command *cm;
698 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
702 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
704 if ((cm = mps_alloc_command(sc)) == NULL) {
705 printf("%s: command alloc failed @ line %d\n", __func__,
710 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
711 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
712 request->Function = MPI2_FUNCTION_CONFIG;
713 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
714 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
715 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
716 request->Header.PageNumber = 0;
717 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
718 /* We can remove below two lines ????*/
719 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
720 request->PageAddress |= htole16(entry_idx);
721 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
723 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
724 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
725 if (error || (reply == NULL)) {
728 * If the request returns an error then we need to do a diag
731 printf("%s: request for header completed with error %d",
736 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
737 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
738 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
741 * If the request returns an error then we need to do a diag
744 printf("%s: header read with error; iocstatus = 0x%x\n",
745 __func__, ioc_status);
749 /* We have to do free and alloc for the reply-free and reply-post
750 * counters to match - Need to review the reply FIFO handling.
752 mps_free_command(sc, cm);
754 if ((cm = mps_alloc_command(sc)) == NULL) {
755 printf("%s: command alloc failed @ line %d\n", __func__,
760 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
761 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
762 request->Function = MPI2_FUNCTION_CONFIG;
763 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
764 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
765 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
766 request->Header.PageNumber = 0;
767 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
768 request->ExtPageLength = mpi_reply->ExtPageLength;
769 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
770 request->PageAddress |= htole16(entry_idx);
771 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
772 cm->cm_sge = &request->PageBufferSGE;
773 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
774 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
775 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
776 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
778 printf("%s: page alloc failed\n", __func__);
782 bcopy(config_page, page, MIN(cm->cm_length,
783 (sizeof(Mpi2DriverMappingPage0_t))));
785 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
786 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
787 if (error || (reply == NULL)) {
790 * If the request returns an error then we need to do a diag
793 printf("%s: request to write page completed with error %d",
798 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
799 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
800 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
803 * If the request returns an error then we need to do a diag
806 printf("%s: page written with error; iocstatus = 0x%x\n",
807 __func__, ioc_status);
814 mps_free_command(sc, cm);
819 * mps_config_get_sas_device_pg0 - obtain sas device page 0
820 * @sc: per adapter object
821 * @mpi_reply: reply mf payload returned from firmware
822 * @config_page: contents of the config page
823 * @form: GET_NEXT_HANDLE or HANDLE
824 * @handle: device handle
827 * Returns 0 for success, non-zero for failure.
830 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
831 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
833 MPI2_CONFIG_REQUEST *request;
834 MPI2_CONFIG_REPLY *reply;
835 struct mps_command *cm;
836 Mpi2SasDevicePage0_t *page = NULL;
840 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
842 if ((cm = mps_alloc_command(sc)) == NULL) {
843 printf("%s: command alloc failed @ line %d\n", __func__,
848 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
849 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
850 request->Function = MPI2_FUNCTION_CONFIG;
851 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
852 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
853 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
854 request->Header.PageNumber = 0;
855 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
856 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
858 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
859 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
860 if (error || (reply == NULL)) {
863 * If the request returns an error then we need to do a diag
866 printf("%s: request for header completed with error %d",
871 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
872 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
873 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
876 * If the request returns an error then we need to do a diag
879 printf("%s: header read with error; iocstatus = 0x%x\n",
880 __func__, ioc_status);
884 /* We have to do free and alloc for the reply-free and reply-post
885 * counters to match - Need to review the reply FIFO handling.
887 mps_free_command(sc, cm);
889 if ((cm = mps_alloc_command(sc)) == NULL) {
890 printf("%s: command alloc failed @ line %d\n", __func__,
895 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
896 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
897 request->Function = MPI2_FUNCTION_CONFIG;
898 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
899 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
900 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
901 request->Header.PageNumber = 0;
902 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
903 request->ExtPageLength = mpi_reply->ExtPageLength;
904 request->PageAddress = htole32(form | handle);
905 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
906 cm->cm_sge = &request->PageBufferSGE;
907 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
908 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
909 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
910 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
912 printf("%s: page alloc failed\n", __func__);
918 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
919 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
920 if (error || (reply == NULL)) {
923 * If the request returns an error then we need to do a diag
926 printf("%s: request for page completed with error %d",
931 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
932 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
933 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
936 * If the request returns an error then we need to do a diag
939 printf("%s: page read with error; iocstatus = 0x%x\n",
940 __func__, ioc_status);
944 bcopy(page, config_page, MIN(cm->cm_length,
945 sizeof(Mpi2SasDevicePage0_t)));
949 mps_free_command(sc, cm);
954 * mps_config_get_bios_pg3 - obtain BIOS page 3
955 * @sc: per adapter object
956 * @mpi_reply: reply mf payload returned from firmware
957 * @config_page: contents of the config page
960 * Returns 0 for success, non-zero for failure.
963 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
964 Mpi2BiosPage3_t *config_page)
966 MPI2_CONFIG_REQUEST *request;
967 MPI2_CONFIG_REPLY *reply;
968 struct mps_command *cm;
969 Mpi2BiosPage3_t *page = NULL;
973 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
975 if ((cm = mps_alloc_command(sc)) == NULL) {
976 printf("%s: command alloc failed @ line %d\n", __func__,
981 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
982 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
983 request->Function = MPI2_FUNCTION_CONFIG;
984 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
985 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
986 request->Header.PageNumber = 3;
987 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
988 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
990 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
991 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
992 if (error || (reply == NULL)) {
995 * If the request returns an error then we need to do a diag
998 printf("%s: request for header completed with error %d",
1003 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1004 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1005 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1008 * If the request returns an error then we need to do a diag
1011 printf("%s: header read with error; iocstatus = 0x%x\n",
1012 __func__, ioc_status);
1016 /* We have to do free and alloc for the reply-free and reply-post
1017 * counters to match - Need to review the reply FIFO handling.
1019 mps_free_command(sc, cm);
1021 if ((cm = mps_alloc_command(sc)) == NULL) {
1022 printf("%s: command alloc failed @ line %d\n", __func__,
1027 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1028 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1029 request->Function = MPI2_FUNCTION_CONFIG;
1030 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1031 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1032 request->Header.PageNumber = 3;
1033 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1034 request->Header.PageLength = mpi_reply->Header.PageLength;
1035 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1036 cm->cm_sge = &request->PageBufferSGE;
1037 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1038 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1039 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1040 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1042 printf("%s: page alloc failed\n", __func__);
1048 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1049 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1050 if (error || (reply == NULL)) {
1053 * If the request returns an error then we need to do a diag
1056 printf("%s: request for page completed with error %d",
1061 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1062 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1063 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1066 * If the request returns an error then we need to do a diag
1069 printf("%s: page read with error; iocstatus = 0x%x\n",
1070 __func__, ioc_status);
1074 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1078 mps_free_command(sc, cm);
1083 * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1084 * @sc: per adapter object
1085 * @mpi_reply: reply mf payload returned from firmware
1086 * @config_page: contents of the config page
1087 * @page_address: form and handle value used to get page
1090 * Returns 0 for success, non-zero for failure.
1093 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1094 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1096 MPI2_CONFIG_REQUEST *request;
1097 MPI2_CONFIG_REPLY *reply;
1098 struct mps_command *cm;
1099 Mpi2RaidVolPage0_t *page = NULL;
1103 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1105 if ((cm = mps_alloc_command(sc)) == NULL) {
1106 printf("%s: command alloc failed @ line %d\n", __func__,
1111 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1112 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1113 request->Function = MPI2_FUNCTION_CONFIG;
1114 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1115 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1116 request->Header.PageNumber = 0;
1117 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1118 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1122 * This page must be polled because the IOC isn't ready yet when this
1125 error = mps_request_polled(sc, cm);
1126 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1127 if (error || (reply == NULL)) {
1129 /* If the poll returns error then we need to do diag reset */
1130 printf("%s: poll for header completed with error %d",
1135 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1136 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1137 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1139 /* If the poll returns error then we need to do diag reset */
1140 printf("%s: header read with error; iocstatus = 0x%x\n",
1141 __func__, ioc_status);
1145 /* We have to do free and alloc for the reply-free and reply-post
1146 * counters to match - Need to review the reply FIFO handling.
1148 mps_free_command(sc, cm);
1150 if ((cm = mps_alloc_command(sc)) == NULL) {
1151 printf("%s: command alloc failed @ line %d\n", __func__,
1156 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1157 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1158 request->Function = MPI2_FUNCTION_CONFIG;
1159 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1160 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1161 request->Header.PageNumber = 0;
1162 request->Header.PageLength = mpi_reply->Header.PageLength;
1163 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1164 request->PageAddress = page_address;
1165 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1166 cm->cm_sge = &request->PageBufferSGE;
1167 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1168 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1169 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1170 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1172 printf("%s: page alloc failed\n", __func__);
1179 * This page must be polled because the IOC isn't ready yet when this
1182 error = mps_request_polled(sc, cm);
1183 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1184 if (error || (reply == NULL)) {
1186 /* If the poll returns error then we need to do diag reset */
1187 printf("%s: poll for page completed with error %d",
1192 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1193 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1194 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1196 /* If the poll returns error then we need to do diag reset */
1197 printf("%s: page read with error; iocstatus = 0x%x\n",
1198 __func__, ioc_status);
1202 bcopy(page, config_page, cm->cm_length);
1206 mps_free_command(sc, cm);
1211 * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1212 * @sc: per adapter object
1213 * @mpi_reply: reply mf payload returned from firmware
1214 * @config_page: contents of the config page
1215 * @form: GET_NEXT_HANDLE or HANDLE
1216 * @handle: volume handle
1219 * Returns 0 for success, non-zero for failure.
1222 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1223 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1225 MPI2_CONFIG_REQUEST *request;
1226 MPI2_CONFIG_REPLY *reply;
1227 struct mps_command *cm;
1228 Mpi2RaidVolPage1_t *page = NULL;
1232 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1234 if ((cm = mps_alloc_command(sc)) == NULL) {
1235 printf("%s: command alloc failed @ line %d\n", __func__,
1240 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1241 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1242 request->Function = MPI2_FUNCTION_CONFIG;
1243 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1244 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1245 request->Header.PageNumber = 1;
1246 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1247 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1249 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1250 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1251 if (error || (reply == NULL)) {
1254 * If the request returns an error then we need to do a diag
1257 printf("%s: request for header completed with error %d",
1262 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1263 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1264 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1267 * If the request returns an error then we need to do a diag
1270 printf("%s: header read with error; iocstatus = 0x%x\n",
1271 __func__, ioc_status);
1275 /* We have to do free and alloc for the reply-free and reply-post
1276 * counters to match - Need to review the reply FIFO handling.
1278 mps_free_command(sc, cm);
1280 if ((cm = mps_alloc_command(sc)) == NULL) {
1281 printf("%s: command alloc failed @ line %d\n", __func__,
1286 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1287 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1288 request->Function = MPI2_FUNCTION_CONFIG;
1289 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1290 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1291 request->Header.PageNumber = 1;
1292 request->Header.PageLength = mpi_reply->Header.PageLength;
1293 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1294 request->PageAddress = htole32(form | handle);
1295 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1296 cm->cm_sge = &request->PageBufferSGE;
1297 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1298 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1299 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1300 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1302 printf("%s: page alloc failed\n", __func__);
1308 error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
1309 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1310 if (error || (reply == NULL)) {
1313 * If the request returns an error then we need to do a diag
1316 printf("%s: request for page completed with error %d",
1321 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1322 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1323 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1326 * If the request returns an error then we need to do a diag
1329 printf("%s: page read with error; iocstatus = 0x%x\n",
1330 __func__, ioc_status);
1334 bcopy(page, config_page, MIN(cm->cm_length,
1335 sizeof(Mpi2RaidVolPage1_t)));
1339 mps_free_command(sc, cm);
1344 * mps_config_get_volume_wwid - returns wwid given the volume handle
1345 * @sc: per adapter object
1346 * @volume_handle: volume handle
1347 * @wwid: volume wwid
1350 * Returns 0 for success, non-zero for failure.
1353 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1355 Mpi2ConfigReply_t mpi_reply;
1356 Mpi2RaidVolPage1_t raid_vol_pg1;
1359 if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1360 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1361 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1362 raid_vol_pg1.WWID.Low);
1369 * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1370 * @sc: per adapter object
1371 * @mpi_reply: reply mf payload returned from firmware
1372 * @config_page: contents of the config page
1373 * @page_address: form and handle value used to get page
1376 * Returns 0 for success, non-zero for failure.
1379 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1380 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1382 MPI2_CONFIG_REQUEST *request;
1383 MPI2_CONFIG_REPLY *reply;
1384 struct mps_command *cm;
1385 Mpi2RaidPhysDiskPage0_t *page = NULL;
1389 mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1391 if ((cm = mps_alloc_command(sc)) == NULL) {
1392 printf("%s: command alloc failed @ line %d\n", __func__,
1397 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1398 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1399 request->Function = MPI2_FUNCTION_CONFIG;
1400 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1401 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1402 request->Header.PageNumber = 0;
1403 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1404 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1408 * This page must be polled because the IOC isn't ready yet when this
1411 error = mps_request_polled(sc, cm);
1412 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1413 if (error || (reply == NULL)) {
1415 /* If the poll returns error then we need to do diag reset */
1416 printf("%s: poll for header completed with error %d",
1421 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1422 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1423 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1425 /* If the poll returns error then we need to do diag reset */
1426 printf("%s: header read with error; iocstatus = 0x%x\n",
1427 __func__, ioc_status);
1431 /* We have to do free and alloc for the reply-free and reply-post
1432 * counters to match - Need to review the reply FIFO handling.
1434 mps_free_command(sc, cm);
1436 if ((cm = mps_alloc_command(sc)) == NULL) {
1437 printf("%s: command alloc failed @ line %d\n", __func__,
1442 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1443 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1444 request->Function = MPI2_FUNCTION_CONFIG;
1445 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1446 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1447 request->Header.PageNumber = 0;
1448 request->Header.PageLength = mpi_reply->Header.PageLength;
1449 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1450 request->PageAddress = page_address;
1451 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1452 cm->cm_sge = &request->PageBufferSGE;
1453 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1454 cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1455 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1456 page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1458 printf("%s: page alloc failed\n", __func__);
1465 * This page must be polled because the IOC isn't ready yet when this
1468 error = mps_request_polled(sc, cm);
1469 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1470 if (error || (reply == NULL)) {
1472 /* If the poll returns error then we need to do diag reset */
1473 printf("%s: poll for page completed with error %d",
1478 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1479 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1480 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1482 /* If the poll returns error then we need to do diag reset */
1483 printf("%s: page read with error; iocstatus = 0x%x\n",
1484 __func__, ioc_status);
1488 bcopy(page, config_page, MIN(cm->cm_length,
1489 sizeof(Mpi2RaidPhysDiskPage0_t)));
1493 mps_free_command(sc, cm);