2 * Copyright (c) 2011-2014 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 mprvar */
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/mpr/mpi/mpi2_type.h>
50 #include <dev/mpr/mpi/mpi2.h>
51 #include <dev/mpr/mpi/mpi2_ioc.h>
52 #include <dev/mpr/mpi/mpi2_sas.h>
53 #include <dev/mpr/mpi/mpi2_cnfg.h>
54 #include <dev/mpr/mpi/mpi2_init.h>
55 #include <dev/mpr/mpi/mpi2_tool.h>
56 #include <dev/mpr/mpr_ioctl.h>
57 #include <dev/mpr/mprvar.h>
60 * mpr_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 mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
70 Mpi2IOCPage8_t *config_page)
72 MPI2_CONFIG_REQUEST *request;
73 MPI2_CONFIG_REPLY *reply;
74 struct mpr_command *cm;
75 MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
79 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
81 if ((cm = mpr_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 = mpr_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 mpr_free_command(sc, cm);
127 if ((cm = mpr_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 = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
145 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
146 page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
148 printf("%s: page alloc failed\n", __func__);
154 error = mpr_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 mpr_free_command(sc, cm);
190 * mpr_config_get_iounit_pg8 - obtain iounit page 8
191 * @sc: per adapter object
192 * @mpi_reply: reply mf payload returned from firmware
193 * @config_page: contents of the config page
196 * Returns 0 for success, non-zero for failure.
199 mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
200 Mpi2IOUnitPage8_t *config_page)
202 MPI2_CONFIG_REQUEST *request;
203 MPI2_CONFIG_REPLY *reply;
204 struct mpr_command *cm;
205 MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL;
209 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
211 if ((cm = mpr_alloc_command(sc)) == NULL) {
212 printf("%s: command alloc failed @ line %d\n", __func__,
217 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
218 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
219 request->Function = MPI2_FUNCTION_CONFIG;
220 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
221 request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
222 request->Header.PageNumber = 8;
223 request->Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
224 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
226 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
227 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
228 if (error || (reply == NULL)) {
231 * If the request returns an error then we need to do a diag
234 printf("%s: request for header completed with error %d",
239 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
240 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
241 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
244 * If the request returns an error then we need to do a diag
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 mpr_free_command(sc, cm);
257 if ((cm = mpr_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_IO_UNIT;
268 request->Header.PageNumber = 8;
269 request->Header.PageVersion = MPI2_IOUNITPAGE8_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 = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
275 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
276 page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
278 printf("%s: page alloc failed\n", __func__);
284 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
285 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
286 if (error || (reply == NULL)) {
289 * If the request returns an error then we need to do a diag
292 printf("%s: request for page completed with error %d",
297 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
298 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
299 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
302 * If the request returns an error then we need to do a diag
305 printf("%s: page read with error; iocstatus = 0x%x\n",
306 __func__, ioc_status);
310 bcopy(page, config_page, MIN(cm->cm_length,
311 (sizeof(Mpi2IOUnitPage8_t))));
316 mpr_free_command(sc, cm);
321 * mpr_base_static_config_pages - static start of day config pages.
322 * @sc: per adapter object
327 mpr_base_static_config_pages(struct mpr_softc *sc)
329 Mpi2ConfigReply_t mpi_reply;
333 while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
336 /* We need to Handle this situation */
342 while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) {
345 /* We need to Handle this situation */
353 * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0
354 * @sc: per adapter object
355 * @mpi_reply: reply mf payload returned from firmware
356 * @config_page: contents of the config page
357 * @sz: size of buffer passed in config_page
360 * Returns 0 for success, non-zero for failure.
363 mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
364 Mpi2DriverMappingPage0_t *config_page, u16 sz)
366 MPI2_CONFIG_REQUEST *request;
367 MPI2_CONFIG_REPLY *reply;
368 struct mpr_command *cm;
369 Mpi2DriverMappingPage0_t *page = NULL;
373 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
375 memset(config_page, 0, sz);
376 if ((cm = mpr_alloc_command(sc)) == NULL) {
377 printf("%s: command alloc failed @ line %d\n", __func__,
382 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
383 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
384 request->Function = MPI2_FUNCTION_CONFIG;
385 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
386 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
387 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
388 request->Header.PageNumber = 0;
389 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
390 request->PageAddress = sc->max_dpm_entries <<
391 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
392 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
394 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
395 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
396 if (error || (reply == NULL)) {
399 * If the request returns an error then we need to do a diag
402 printf("%s: request for header completed with error %d",
407 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
408 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
409 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
412 * If the request returns an error then we need to do a diag
415 printf("%s: header read with error; iocstatus = 0x%x\n",
416 __func__, ioc_status);
420 /* We have to do free and alloc for the reply-free and reply-post
421 * counters to match - Need to review the reply FIFO handling.
423 mpr_free_command(sc, cm);
425 if ((cm = mpr_alloc_command(sc)) == NULL) {
426 printf("%s: command alloc failed @ line %d\n", __func__,
431 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
432 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
433 request->Function = MPI2_FUNCTION_CONFIG;
434 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
435 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
436 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
437 request->Header.PageNumber = 0;
438 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
439 request->PageAddress = sc->max_dpm_entries <<
440 MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
441 request->ExtPageLength = mpi_reply->ExtPageLength;
442 cm->cm_length = le16toh(request->ExtPageLength) * 4;
443 cm->cm_sge = &request->PageBufferSGE;
444 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
445 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
446 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
447 page = malloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT);
449 printf("%s: page alloc failed\n", __func__);
454 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
455 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
456 if (error || (reply == NULL)) {
459 * If the request returns an error then we need to do a diag
462 printf("%s: request for page completed with error %d",
467 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
468 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
469 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
472 * If the request returns an error then we need to do a diag
475 printf("%s: page read with error; iocstatus = 0x%x\n",
476 __func__, ioc_status);
480 bcopy(page, config_page, MIN(cm->cm_length, sz));
484 mpr_free_command(sc, cm);
489 * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
490 * @sc: per adapter object
491 * @mpi_reply: reply mf payload returned from firmware
492 * @config_page: contents of the config page
493 * @entry_idx: entry index in DPM Page0 to be modified
496 * Returns 0 for success, non-zero for failure.
499 int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
500 Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
502 MPI2_CONFIG_REQUEST *request;
503 MPI2_CONFIG_REPLY *reply;
504 struct mpr_command *cm;
505 MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
509 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
511 if ((cm = mpr_alloc_command(sc)) == NULL) {
512 printf("%s: command alloc failed @ line %d\n", __func__,
517 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
518 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
519 request->Function = MPI2_FUNCTION_CONFIG;
520 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
521 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
522 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
523 request->Header.PageNumber = 0;
524 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
525 /* We can remove below two lines ????*/
526 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
527 request->PageAddress |= htole16(entry_idx);
528 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
530 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
531 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
532 if (error || (reply == NULL)) {
535 * If the request returns an error then we need to do a diag
538 printf("%s: request for header completed with error %d",
543 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
544 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
545 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
548 * If the request returns an error then we need to do a diag
551 printf("%s: header read with error; iocstatus = 0x%x\n",
552 __func__, ioc_status);
556 /* We have to do free and alloc for the reply-free and reply-post
557 * counters to match - Need to review the reply FIFO handling.
559 mpr_free_command(sc, cm);
561 if ((cm = mpr_alloc_command(sc)) == NULL) {
562 printf("%s: command alloc failed @ line %d\n", __func__,
567 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
568 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
569 request->Function = MPI2_FUNCTION_CONFIG;
570 request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
571 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
572 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
573 request->Header.PageNumber = 0;
574 request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
575 request->ExtPageLength = mpi_reply->ExtPageLength;
576 request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
577 request->PageAddress |= htole16(entry_idx);
578 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
579 cm->cm_sge = &request->PageBufferSGE;
580 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
581 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT;
582 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
583 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
585 printf("%s: page alloc failed\n", __func__);
589 bcopy(config_page, page, MIN(cm->cm_length,
590 (sizeof(Mpi2DriverMappingPage0_t))));
592 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
593 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
594 if (error || (reply == NULL)) {
597 * If the request returns an error then we need to do a diag
600 printf("%s: request to write page completed with error %d",
605 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
606 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
607 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
610 * If the request returns an error then we need to do a diag
613 printf("%s: page written with error; iocstatus = 0x%x\n",
614 __func__, ioc_status);
621 mpr_free_command(sc, cm);
626 * mpr_config_get_sas_device_pg0 - obtain sas device page 0
627 * @sc: per adapter object
628 * @mpi_reply: reply mf payload returned from firmware
629 * @config_page: contents of the config page
630 * @form: GET_NEXT_HANDLE or HANDLE
631 * @handle: device handle
634 * Returns 0 for success, non-zero for failure.
637 mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
638 *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
640 MPI2_CONFIG_REQUEST *request;
641 MPI2_CONFIG_REPLY *reply;
642 struct mpr_command *cm;
643 Mpi2SasDevicePage0_t *page = NULL;
647 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
649 if ((cm = mpr_alloc_command(sc)) == NULL) {
650 printf("%s: command alloc failed @ line %d\n", __func__,
655 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
656 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
657 request->Function = MPI2_FUNCTION_CONFIG;
658 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
659 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
660 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
661 request->Header.PageNumber = 0;
662 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
663 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
665 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
666 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
667 if (error || (reply == NULL)) {
670 * If the request returns an error then we need to do a diag
673 printf("%s: request for header completed with error %d",
678 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
679 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
680 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
683 * If the request returns an error then we need to do a diag
686 printf("%s: header read with error; iocstatus = 0x%x\n",
687 __func__, ioc_status);
691 /* We have to do free and alloc for the reply-free and reply-post
692 * counters to match - Need to review the reply FIFO handling.
694 mpr_free_command(sc, cm);
696 if ((cm = mpr_alloc_command(sc)) == NULL) {
697 printf("%s: command alloc failed @ line %d\n", __func__,
702 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
703 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
704 request->Function = MPI2_FUNCTION_CONFIG;
705 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
706 request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
707 request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
708 request->Header.PageNumber = 0;
709 request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
710 request->ExtPageLength = mpi_reply->ExtPageLength;
711 request->PageAddress = htole32(form | handle);
712 cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
713 cm->cm_sge = &request->PageBufferSGE;
714 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
715 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
716 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
717 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
719 printf("%s: page alloc failed\n", __func__);
725 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
726 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
727 if (error || (reply == NULL)) {
730 * If the request returns an error then we need to do a diag
733 printf("%s: request for page completed with error %d",
738 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
739 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
740 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
743 * If the request returns an error then we need to do a diag
746 printf("%s: page read with error; iocstatus = 0x%x\n",
747 __func__, ioc_status);
751 bcopy(page, config_page, MIN(cm->cm_length,
752 sizeof(Mpi2SasDevicePage0_t)));
756 mpr_free_command(sc, cm);
761 * mpr_config_get_bios_pg3 - obtain BIOS page 3
762 * @sc: per adapter object
763 * @mpi_reply: reply mf payload returned from firmware
764 * @config_page: contents of the config page
767 * Returns 0 for success, non-zero for failure.
770 mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
771 Mpi2BiosPage3_t *config_page)
773 MPI2_CONFIG_REQUEST *request;
774 MPI2_CONFIG_REPLY *reply;
775 struct mpr_command *cm;
776 Mpi2BiosPage3_t *page = NULL;
780 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
782 if ((cm = mpr_alloc_command(sc)) == NULL) {
783 printf("%s: command alloc failed @ line %d\n", __func__,
788 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
789 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
790 request->Function = MPI2_FUNCTION_CONFIG;
791 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
792 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
793 request->Header.PageNumber = 3;
794 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
795 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
797 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
798 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
799 if (error || (reply == NULL)) {
802 * If the request returns an error then we need to do a diag
805 printf("%s: request for header completed with error %d",
810 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
811 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
812 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
815 * If the request returns an error then we need to do a diag
818 printf("%s: header read with error; iocstatus = 0x%x\n",
819 __func__, ioc_status);
823 /* We have to do free and alloc for the reply-free and reply-post
824 * counters to match - Need to review the reply FIFO handling.
826 mpr_free_command(sc, cm);
828 if ((cm = mpr_alloc_command(sc)) == NULL) {
829 printf("%s: command alloc failed @ line %d\n", __func__,
834 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
835 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
836 request->Function = MPI2_FUNCTION_CONFIG;
837 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
838 request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
839 request->Header.PageNumber = 3;
840 request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
841 request->Header.PageLength = mpi_reply->Header.PageLength;
842 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
843 cm->cm_sge = &request->PageBufferSGE;
844 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
845 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
846 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
847 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
849 printf("%s: page alloc failed\n", __func__);
855 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
856 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
857 if (error || (reply == NULL)) {
860 * If the request returns an error then we need to do a diag
863 printf("%s: request for page completed with error %d",
868 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
869 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
870 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
873 * If the request returns an error then we need to do a diag
876 printf("%s: page read with error; iocstatus = 0x%x\n",
877 __func__, ioc_status);
881 bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
885 mpr_free_command(sc, cm);
890 * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0
891 * @sc: per adapter object
892 * @mpi_reply: reply mf payload returned from firmware
893 * @config_page: contents of the config page
894 * @page_address: form and handle value used to get page
897 * Returns 0 for success, non-zero for failure.
900 mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
901 *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
903 MPI2_CONFIG_REQUEST *request;
904 MPI2_CONFIG_REPLY *reply;
905 struct mpr_command *cm;
906 Mpi2RaidVolPage0_t *page = NULL;
910 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
912 if ((cm = mpr_alloc_command(sc)) == NULL) {
913 printf("%s: command alloc failed @ line %d\n", __func__,
918 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
919 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
920 request->Function = MPI2_FUNCTION_CONFIG;
921 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
922 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
923 request->Header.PageNumber = 0;
924 request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
925 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
929 * This page must be polled because the IOC isn't ready yet when this
932 error = mpr_request_polled(sc, cm);
933 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
934 if (error || (reply == NULL)) {
936 /* If the poll returns error then we need to do diag reset */
937 printf("%s: poll for header completed with error %d",
942 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
943 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
944 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
946 /* If the poll returns error then we need to do diag reset */
947 printf("%s: header read with error; iocstatus = 0x%x\n",
948 __func__, ioc_status);
952 /* We have to do free and alloc for the reply-free and reply-post
953 * counters to match - Need to review the reply FIFO handling.
955 mpr_free_command(sc, cm);
957 if ((cm = mpr_alloc_command(sc)) == NULL) {
958 printf("%s: command alloc failed @ line %d\n", __func__,
963 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
964 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
965 request->Function = MPI2_FUNCTION_CONFIG;
966 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
967 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
968 request->Header.PageNumber = 0;
969 request->Header.PageLength = mpi_reply->Header.PageLength;
970 request->Header.PageVersion = mpi_reply->Header.PageVersion;
971 request->PageAddress = page_address;
972 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
973 cm->cm_sge = &request->PageBufferSGE;
974 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
975 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
976 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
977 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
979 printf("%s: page alloc failed\n", __func__);
986 * This page must be polled because the IOC isn't ready yet when this
989 error = mpr_request_polled(sc, cm);
990 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
991 if (error || (reply == NULL)) {
993 /* If the poll returns error then we need to do diag reset */
994 printf("%s: poll for page completed with error %d",
999 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1000 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1001 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1003 /* If the poll returns error then we need to do diag reset */
1004 printf("%s: page read with error; iocstatus = 0x%x\n",
1005 __func__, ioc_status);
1009 bcopy(page, config_page, cm->cm_length);
1013 mpr_free_command(sc, cm);
1018 * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1
1019 * @sc: per adapter object
1020 * @mpi_reply: reply mf payload returned from firmware
1021 * @config_page: contents of the config page
1022 * @form: GET_NEXT_HANDLE or HANDLE
1023 * @handle: volume handle
1026 * Returns 0 for success, non-zero for failure.
1029 mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t
1030 *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1032 MPI2_CONFIG_REQUEST *request;
1033 MPI2_CONFIG_REPLY *reply;
1034 struct mpr_command *cm;
1035 Mpi2RaidVolPage1_t *page = NULL;
1039 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1041 if ((cm = mpr_alloc_command(sc)) == NULL) {
1042 printf("%s: command alloc failed @ line %d\n", __func__,
1047 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1048 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1049 request->Function = MPI2_FUNCTION_CONFIG;
1050 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1051 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1052 request->Header.PageNumber = 1;
1053 request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1054 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1056 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
1057 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1058 if (error || (reply == NULL)) {
1061 * If the request returns an error then we need to do a diag
1064 printf("%s: request for header completed with error %d",
1069 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1070 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1071 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1074 * If the request returns an error then we need to do a diag
1077 printf("%s: header read with error; iocstatus = 0x%x\n",
1078 __func__, ioc_status);
1082 /* We have to do free and alloc for the reply-free and reply-post
1083 * counters to match - Need to review the reply FIFO handling.
1085 mpr_free_command(sc, cm);
1087 if ((cm = mpr_alloc_command(sc)) == NULL) {
1088 printf("%s: command alloc failed @ line %d\n", __func__,
1093 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1094 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1095 request->Function = MPI2_FUNCTION_CONFIG;
1096 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1097 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1098 request->Header.PageNumber = 1;
1099 request->Header.PageLength = mpi_reply->Header.PageLength;
1100 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1101 request->PageAddress = htole32(form | handle);
1102 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1103 cm->cm_sge = &request->PageBufferSGE;
1104 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1105 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1106 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1107 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1109 printf("%s: page alloc failed\n", __func__);
1115 error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
1116 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1117 if (error || (reply == NULL)) {
1120 * If the request returns an error then we need to do a diag
1123 printf("%s: request for page completed with error %d",
1128 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1129 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1130 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1133 * If the request returns an error then we need to do a diag
1136 printf("%s: page read with error; iocstatus = 0x%x\n",
1137 __func__, ioc_status);
1141 bcopy(page, config_page, MIN(cm->cm_length,
1142 sizeof(Mpi2RaidVolPage1_t)));
1146 mpr_free_command(sc, cm);
1151 * mpr_config_get_volume_wwid - returns wwid given the volume handle
1152 * @sc: per adapter object
1153 * @volume_handle: volume handle
1154 * @wwid: volume wwid
1157 * Returns 0 for success, non-zero for failure.
1160 mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid)
1162 Mpi2ConfigReply_t mpi_reply;
1163 Mpi2RaidVolPage1_t raid_vol_pg1;
1166 if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1167 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1168 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1169 raid_vol_pg1.WWID.Low);
1176 * mpr_config_get_pd_pg0 - obtain raid phys disk page 0
1177 * @sc: per adapter object
1178 * @mpi_reply: reply mf payload returned from firmware
1179 * @config_page: contents of the config page
1180 * @page_address: form and handle value used to get page
1183 * Returns 0 for success, non-zero for failure.
1186 mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1187 Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1189 MPI2_CONFIG_REQUEST *request;
1190 MPI2_CONFIG_REPLY *reply;
1191 struct mpr_command *cm;
1192 Mpi2RaidPhysDiskPage0_t *page = NULL;
1196 mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1198 if ((cm = mpr_alloc_command(sc)) == NULL) {
1199 printf("%s: command alloc failed @ line %d\n", __func__,
1204 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1205 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1206 request->Function = MPI2_FUNCTION_CONFIG;
1207 request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1208 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1209 request->Header.PageNumber = 0;
1210 request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1211 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1215 * This page must be polled because the IOC isn't ready yet when this
1218 error = mpr_request_polled(sc, cm);
1219 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1220 if (error || (reply == NULL)) {
1222 /* If the poll returns error then we need to do diag reset */
1223 printf("%s: poll for header completed with error %d",
1228 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1229 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1230 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1232 /* If the poll returns error then we need to do diag reset */
1233 printf("%s: header read with error; iocstatus = 0x%x\n",
1234 __func__, ioc_status);
1238 /* We have to do free and alloc for the reply-free and reply-post
1239 * counters to match - Need to review the reply FIFO handling.
1241 mpr_free_command(sc, cm);
1243 if ((cm = mpr_alloc_command(sc)) == NULL) {
1244 printf("%s: command alloc failed @ line %d\n", __func__,
1249 request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1250 bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1251 request->Function = MPI2_FUNCTION_CONFIG;
1252 request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1253 request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1254 request->Header.PageNumber = 0;
1255 request->Header.PageLength = mpi_reply->Header.PageLength;
1256 request->Header.PageVersion = mpi_reply->Header.PageVersion;
1257 request->PageAddress = page_address;
1258 cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1259 cm->cm_sge = &request->PageBufferSGE;
1260 cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1261 cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1262 cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1263 page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1265 printf("%s: page alloc failed\n", __func__);
1272 * This page must be polled because the IOC isn't ready yet when this
1275 error = mpr_request_polled(sc, cm);
1276 reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1277 if (error || (reply == NULL)) {
1279 /* If the poll returns error then we need to do diag reset */
1280 printf("%s: poll for page completed with error %d",
1285 ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1286 bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1287 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1289 /* If the poll returns error then we need to do diag reset */
1290 printf("%s: page read with error; iocstatus = 0x%x\n",
1291 __func__, ioc_status);
1295 bcopy(page, config_page, MIN(cm->cm_length,
1296 sizeof(Mpi2RaidPhysDiskPage0_t)));
1300 mpr_free_command(sc, cm);