xref: /freebsd/sys/dev/mps/mps_config.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1d043c564SKenneth D. Merry /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
4ef065d89SStephen McConnell  * Copyright (c) 2011-2015 LSI Corp.
5ef065d89SStephen McConnell  * Copyright (c) 2013-2015 Avago Technologies
6d043c564SKenneth D. Merry  * All rights reserved.
7d043c564SKenneth D. Merry  *
8d043c564SKenneth D. Merry  * Redistribution and use in source and binary forms, with or without
9d043c564SKenneth D. Merry  * modification, are permitted provided that the following conditions
10d043c564SKenneth D. Merry  * are met:
11d043c564SKenneth D. Merry  * 1. Redistributions of source code must retain the above copyright
12d043c564SKenneth D. Merry  *    notice, this list of conditions and the following disclaimer.
13d043c564SKenneth D. Merry  * 2. Redistributions in binary form must reproduce the above copyright
14d043c564SKenneth D. Merry  *    notice, this list of conditions and the following disclaimer in the
15d043c564SKenneth D. Merry  *    documentation and/or other materials provided with the distribution.
16d043c564SKenneth D. Merry  *
17d043c564SKenneth D. Merry  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18d043c564SKenneth D. Merry  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19d043c564SKenneth D. Merry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20d043c564SKenneth D. Merry  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21d043c564SKenneth D. Merry  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22d043c564SKenneth D. Merry  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23d043c564SKenneth D. Merry  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24d043c564SKenneth D. Merry  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25d043c564SKenneth D. Merry  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26d043c564SKenneth D. Merry  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27d043c564SKenneth D. Merry  * SUCH DAMAGE.
28d043c564SKenneth D. Merry  *
29ef065d89SStephen McConnell  * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
30d043c564SKenneth D. Merry  */
31d043c564SKenneth D. Merry 
32d043c564SKenneth D. Merry #include <sys/cdefs.h>
33d043c564SKenneth D. Merry /* TODO Move headers to mpsvar */
34d043c564SKenneth D. Merry #include <sys/types.h>
35d043c564SKenneth D. Merry #include <sys/param.h>
36d043c564SKenneth D. Merry #include <sys/lock.h>
37d043c564SKenneth D. Merry #include <sys/mutex.h>
38d043c564SKenneth D. Merry #include <sys/systm.h>
39d043c564SKenneth D. Merry #include <sys/kernel.h>
40d043c564SKenneth D. Merry #include <sys/malloc.h>
41d043c564SKenneth D. Merry #include <sys/kthread.h>
42d043c564SKenneth D. Merry #include <sys/taskqueue.h>
43d043c564SKenneth D. Merry #include <sys/bus.h>
44d043c564SKenneth D. Merry #include <sys/endian.h>
45d043c564SKenneth D. Merry #include <sys/sysctl.h>
46d043c564SKenneth D. Merry #include <sys/eventhandler.h>
47d043c564SKenneth D. Merry #include <sys/uio.h>
48d043c564SKenneth D. Merry #include <machine/bus.h>
49d043c564SKenneth D. Merry #include <machine/resource.h>
50d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_type.h>
51d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2.h>
52d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_ioc.h>
53d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_sas.h>
54d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_cnfg.h>
55d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_init.h>
56d043c564SKenneth D. Merry #include <dev/mps/mpi/mpi2_tool.h>
57d043c564SKenneth D. Merry #include <dev/mps/mps_ioctl.h>
58d043c564SKenneth D. Merry #include <dev/mps/mpsvar.h>
59d043c564SKenneth D. Merry 
60d043c564SKenneth D. Merry /**
61d043c564SKenneth D. Merry  * mps_config_get_ioc_pg8 - obtain ioc page 8
62d043c564SKenneth D. Merry  * @sc: per adapter object
63d043c564SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
64d043c564SKenneth D. Merry  * @config_page: contents of the config page
65d043c564SKenneth D. Merry  * Context: sleep.
66d043c564SKenneth D. Merry  *
67d043c564SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
68d043c564SKenneth D. Merry  */
69d043c564SKenneth D. Merry int
mps_config_get_ioc_pg8(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2IOCPage8_t * config_page)70d043c564SKenneth D. Merry mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
71d043c564SKenneth D. Merry     Mpi2IOCPage8_t *config_page)
72d043c564SKenneth D. Merry {
73d043c564SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
746d4ffcb4SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply = NULL;
75d043c564SKenneth D. Merry 	struct mps_command *cm;
76d043c564SKenneth D. Merry 	MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
77d043c564SKenneth D. Merry 	int error = 0;
78d043c564SKenneth D. Merry 	u16 ioc_status;
79d043c564SKenneth D. Merry 
80d043c564SKenneth D. Merry 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
81d043c564SKenneth D. Merry 
82d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
83d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
84d043c564SKenneth D. Merry 		    __LINE__);
85d043c564SKenneth D. Merry 		error = EBUSY;
86d043c564SKenneth D. Merry 		goto out;
87d043c564SKenneth D. Merry 	}
88d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
89d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
90d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
91d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
92d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
93d043c564SKenneth D. Merry 	request->Header.PageNumber = 8;
94d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
95d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
96d043c564SKenneth D. Merry 	cm->cm_data = NULL;
976d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
986d4ffcb4SKenneth D. Merry 	if (cm != NULL)
99d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
100d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
101d043c564SKenneth D. Merry 		/* FIXME */
1029b91b192SKenneth D. Merry 		/*
1039b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1049b91b192SKenneth D. Merry 		 * reset
1059b91b192SKenneth D. Merry 		 */
106074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
107d043c564SKenneth D. Merry 		    __func__, error);
108d043c564SKenneth D. Merry 		error = ENXIO;
109d043c564SKenneth D. Merry 		goto out;
110d043c564SKenneth D. Merry 	}
111d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
112d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
113d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
114d043c564SKenneth D. Merry 		/* FIXME */
1159b91b192SKenneth D. Merry 		/*
1169b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1179b91b192SKenneth D. Merry 		 * reset
1189b91b192SKenneth D. Merry 		 */
119d043c564SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
120d043c564SKenneth D. Merry 		    __func__, ioc_status);
121d043c564SKenneth D. Merry 		error = ENXIO;
122d043c564SKenneth D. Merry 		goto out;
123d043c564SKenneth D. Merry 	}
124d043c564SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
125d043c564SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
126d043c564SKenneth D. Merry 	 */
127d043c564SKenneth D. Merry 	mps_free_command(sc, cm);
128d043c564SKenneth D. Merry 
129d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
130d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
131d043c564SKenneth D. Merry 		    __LINE__);
132d043c564SKenneth D. Merry 		error = EBUSY;
133d043c564SKenneth D. Merry 		goto out;
134d043c564SKenneth D. Merry 	}
135d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
136d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
137d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
138d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
139d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
140d043c564SKenneth D. Merry 	request->Header.PageNumber = 8;
141d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
142d043c564SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
143d043c564SKenneth D. Merry 	cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
144d043c564SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
145d043c564SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
146d043c564SKenneth D. Merry 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
147d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
148d043c564SKenneth D. Merry 	page = malloc((cm->cm_length), M_MPT2, M_ZERO | M_NOWAIT);
149d043c564SKenneth D. Merry 	if (!page) {
150d043c564SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
151d043c564SKenneth D. Merry 		error = ENOMEM;
152d043c564SKenneth D. Merry 		goto out;
153d043c564SKenneth D. Merry 	}
154d043c564SKenneth D. Merry 	cm->cm_data = page;
1559b91b192SKenneth D. Merry 
1566d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
1576d4ffcb4SKenneth D. Merry 	if (cm != NULL)
158d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
159d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
160d043c564SKenneth D. Merry 		/* FIXME */
1619b91b192SKenneth D. Merry 		/*
1629b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1639b91b192SKenneth D. Merry 		 * reset
1649b91b192SKenneth D. Merry 		 */
165074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
166d043c564SKenneth D. Merry 		    __func__, error);
167d043c564SKenneth D. Merry 		error = ENXIO;
168d043c564SKenneth D. Merry 		goto out;
169d043c564SKenneth D. Merry 	}
170d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
171d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
172d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
173d043c564SKenneth D. Merry 		/* FIXME */
1749b91b192SKenneth D. Merry 		/*
1759b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1769b91b192SKenneth D. Merry 		 * reset
1779b91b192SKenneth D. Merry 		 */
178d043c564SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
179d043c564SKenneth D. Merry 		    __func__, ioc_status);
180d043c564SKenneth D. Merry 		error = ENXIO;
181d043c564SKenneth D. Merry 		goto out;
182d043c564SKenneth D. Merry 	}
183d043c564SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
184d043c564SKenneth D. Merry 
185d043c564SKenneth D. Merry out:
186d043c564SKenneth D. Merry 	free(page, M_MPT2);
187d043c564SKenneth D. Merry 	if (cm)
188d043c564SKenneth D. Merry 		mps_free_command(sc, cm);
189d043c564SKenneth D. Merry 	return (error);
190d043c564SKenneth D. Merry }
191d043c564SKenneth D. Merry 
192d043c564SKenneth D. Merry /**
193d043c564SKenneth D. Merry  * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
194d043c564SKenneth D. Merry  *   accordingly.  Currently, this page does not need to return to caller.
195d043c564SKenneth D. Merry  * @sc: per adapter object
196d043c564SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
197d043c564SKenneth D. Merry  * Context: sleep.
198d043c564SKenneth D. Merry  *
199d043c564SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
200d043c564SKenneth D. Merry  */
201d043c564SKenneth D. Merry int
mps_config_get_man_pg10(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply)202d043c564SKenneth D. Merry mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
203d043c564SKenneth D. Merry {
204d043c564SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
2056d4ffcb4SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply = NULL;
206d043c564SKenneth D. Merry 	struct mps_command *cm;
207d043c564SKenneth D. Merry 	pMpi2ManufacturingPagePS_t page = NULL;
208d043c564SKenneth D. Merry 	uint32_t *pPS_info;
209d043c564SKenneth D. Merry 	uint8_t OEM_Value = 0;
210d043c564SKenneth D. Merry 	int error = 0;
211d043c564SKenneth D. Merry 	u16 ioc_status;
212d043c564SKenneth D. Merry 
213d043c564SKenneth D. Merry 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
214d043c564SKenneth D. Merry 
215d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
216d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
217d043c564SKenneth D. Merry 		    __LINE__);
218d043c564SKenneth D. Merry 		error = EBUSY;
219d043c564SKenneth D. Merry 		goto out;
220d043c564SKenneth D. Merry 	}
221d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
222d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
223d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
224d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
225d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
226d043c564SKenneth D. Merry 	request->Header.PageNumber = 10;
227d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
228d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
229d043c564SKenneth D. Merry 	cm->cm_data = NULL;
2309b91b192SKenneth D. Merry 
2319b91b192SKenneth D. Merry 	/*
2329b91b192SKenneth D. Merry 	 * This page must be polled because the IOC isn't ready yet when this
2339b91b192SKenneth D. Merry 	 * page is needed.
2349b91b192SKenneth D. Merry 	 */
2356d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, 0);
2366d4ffcb4SKenneth D. Merry 	if (cm != NULL)
237d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
238d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
239d043c564SKenneth D. Merry 		/* FIXME */
240d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
241074bed4fSAlexander Motin 		printf("%s: poll for header completed with error %d\n",
242d043c564SKenneth D. Merry 		    __func__, error);
243d043c564SKenneth D. Merry 		error = ENXIO;
244d043c564SKenneth D. Merry 		goto out;
245d043c564SKenneth D. Merry 	}
246d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
247d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
248d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
249d043c564SKenneth D. Merry 		/* FIXME */
250d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
251d043c564SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
252d043c564SKenneth D. Merry 		    __func__, ioc_status);
253d043c564SKenneth D. Merry 		error = ENXIO;
254d043c564SKenneth D. Merry 		goto out;
255d043c564SKenneth D. Merry 	}
256d043c564SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
257d043c564SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
258d043c564SKenneth D. Merry 	 */
259d043c564SKenneth D. Merry 	mps_free_command(sc, cm);
260d043c564SKenneth D. Merry 
261d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
262d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
263d043c564SKenneth D. Merry 		    __LINE__);
264d043c564SKenneth D. Merry 		error = EBUSY;
265d043c564SKenneth D. Merry 		goto out;
266d043c564SKenneth D. Merry 	}
267d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
268d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
269d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
270d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
271d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
272d043c564SKenneth D. Merry 	request->Header.PageNumber = 10;
273d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
274d043c564SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
275d043c564SKenneth D. Merry 	cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
276d043c564SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
277d043c564SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
278d043c564SKenneth D. Merry 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
279d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
280d043c564SKenneth D. Merry 	page = malloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_NOWAIT);
281d043c564SKenneth D. Merry 	if (!page) {
282d043c564SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
283d043c564SKenneth D. Merry 		error = ENOMEM;
284d043c564SKenneth D. Merry 		goto out;
285d043c564SKenneth D. Merry 	}
286d043c564SKenneth D. Merry 	cm->cm_data = page;
2879b91b192SKenneth D. Merry 
2889b91b192SKenneth D. Merry 	/*
2899b91b192SKenneth D. Merry 	 * This page must be polled because the IOC isn't ready yet when this
2909b91b192SKenneth D. Merry 	 * page is needed.
2919b91b192SKenneth D. Merry 	 */
2926d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, 0);
2936d4ffcb4SKenneth D. Merry 	if (cm != NULL)
294d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
295d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
296d043c564SKenneth D. Merry 		/* FIXME */
297d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
298074bed4fSAlexander Motin 		printf("%s: poll for page completed with error %d\n",
299d043c564SKenneth D. Merry 		    __func__, error);
300d043c564SKenneth D. Merry 		error = ENXIO;
301d043c564SKenneth D. Merry 		goto out;
302d043c564SKenneth D. Merry 	}
303d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
304d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
305d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
306d043c564SKenneth D. Merry 		/* FIXME */
307d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
308d043c564SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
309d043c564SKenneth D. Merry 		    __func__, ioc_status);
310d043c564SKenneth D. Merry 		error = ENXIO;
311d043c564SKenneth D. Merry 		goto out;
312d043c564SKenneth D. Merry 	}
313d043c564SKenneth D. Merry 
314d043c564SKenneth D. Merry 	/*
315d043c564SKenneth D. Merry 	 * If OEM ID is unknown, fail the request.
316d043c564SKenneth D. Merry 	 */
317d043c564SKenneth D. Merry 	sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
318d043c564SKenneth D. Merry 	OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
319d043c564SKenneth D. Merry 	if (OEM_Value != MPS_WD_LSI_OEM) {
320d043c564SKenneth D. Merry 		mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
321d043c564SKenneth D. Merry 		    "(0x%x)\n", OEM_Value);
322d043c564SKenneth D. Merry 		error = ENXIO;
323d043c564SKenneth D. Merry 		goto out;
324d043c564SKenneth D. Merry 	}
325d043c564SKenneth D. Merry 
326d043c564SKenneth D. Merry 	/*
327d043c564SKenneth D. Merry 	 * Set the phys disks hide/expose value.
328d043c564SKenneth D. Merry 	 */
329d043c564SKenneth D. Merry 	pPS_info = &page->ProductSpecificInfo;
330d043c564SKenneth D. Merry 	sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
331d043c564SKenneth D. Merry 	sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
332d043c564SKenneth D. Merry 	if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
333d043c564SKenneth D. Merry 	    (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
334d043c564SKenneth D. Merry 	    (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
335d043c564SKenneth D. Merry 		mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
336d043c564SKenneth D. Merry 		    "hide/expose: 0x%x\n", sc->WD_hide_expose);
337d043c564SKenneth D. Merry 		error = ENXIO;
338d043c564SKenneth D. Merry 		goto out;
339d043c564SKenneth D. Merry 	}
340d043c564SKenneth D. Merry 
341d043c564SKenneth D. Merry out:
342d043c564SKenneth D. Merry 	free(page, M_MPT2);
343d043c564SKenneth D. Merry 	if (cm)
344d043c564SKenneth D. Merry 		mps_free_command(sc, cm);
345d043c564SKenneth D. Merry 	return (error);
346d043c564SKenneth D. Merry }
347d043c564SKenneth D. Merry 
348d043c564SKenneth D. Merry /**
349d043c564SKenneth D. Merry  * mps_base_static_config_pages - static start of day config pages.
350d043c564SKenneth D. Merry  * @sc: per adapter object
351d043c564SKenneth D. Merry  *
352d043c564SKenneth D. Merry  * Return nothing.
353d043c564SKenneth D. Merry  */
354d043c564SKenneth D. Merry void
mps_base_static_config_pages(struct mps_softc * sc)355d043c564SKenneth D. Merry mps_base_static_config_pages(struct mps_softc *sc)
356d043c564SKenneth D. Merry {
357d043c564SKenneth D. Merry 	Mpi2ConfigReply_t	mpi_reply;
358d043c564SKenneth D. Merry 	int			retry;
359d043c564SKenneth D. Merry 
360d043c564SKenneth D. Merry 	retry = 0;
361d043c564SKenneth D. Merry 	while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
362d043c564SKenneth D. Merry 		retry++;
363d043c564SKenneth D. Merry 		if (retry > 5) {
364d043c564SKenneth D. Merry 			/* We need to Handle this situation */
365d043c564SKenneth D. Merry 			/*FIXME*/
366d043c564SKenneth D. Merry 			break;
367d043c564SKenneth D. Merry 		}
368d043c564SKenneth D. Merry 	}
369d043c564SKenneth D. Merry }
370d043c564SKenneth D. Merry 
371d043c564SKenneth D. Merry /**
372d043c564SKenneth D. Merry  * mps_wd_config_pages - get info required to support WarpDrive.  This needs to
373453130d9SPedro F. Giffuni  *    be called after discovery is complete to guarantee that IR info is there.
374d043c564SKenneth D. Merry  * @sc: per adapter object
375d043c564SKenneth D. Merry  *
376d043c564SKenneth D. Merry  * Return nothing.
377d043c564SKenneth D. Merry  */
378d043c564SKenneth D. Merry void
mps_wd_config_pages(struct mps_softc * sc)379d043c564SKenneth D. Merry mps_wd_config_pages(struct mps_softc *sc)
380d043c564SKenneth D. Merry {
381d043c564SKenneth D. Merry 	Mpi2ConfigReply_t	mpi_reply;
382d043c564SKenneth D. Merry 	pMpi2RaidVolPage0_t	raid_vol_pg0 = NULL;
383d043c564SKenneth D. Merry 	Mpi2RaidPhysDiskPage0_t	phys_disk_pg0;
384d043c564SKenneth D. Merry 	pMpi2RaidVol0PhysDisk_t	pRVPD;
385d043c564SKenneth D. Merry 	uint32_t		stripe_size, phys_disk_page_address;
386d043c564SKenneth D. Merry 	uint16_t		block_size;
387d043c564SKenneth D. Merry 	uint8_t			index, stripe_exp = 0, block_exp = 0;
388d043c564SKenneth D. Merry 
389d043c564SKenneth D. Merry 	/*
390d043c564SKenneth D. Merry 	 * Get the WD settings from manufacturing page 10 if using a WD HBA.
391d043c564SKenneth D. Merry 	 * This will be used to determine if phys disks should always be
392d043c564SKenneth D. Merry 	 * hidden, hidden only if part of a WD volume, or never hidden.  Also,
393d043c564SKenneth D. Merry 	 * get the WD RAID Volume info and fail if volume does not exist or if
394d043c564SKenneth D. Merry 	 * volume does not meet the requirements for a WD volume.  No retry
395d043c564SKenneth D. Merry 	 * here.  Just default to HIDE ALWAYS if man Page10 fails, or clear WD
396d043c564SKenneth D. Merry 	 * Valid flag if Volume info fails.
397d043c564SKenneth D. Merry 	 */
398d043c564SKenneth D. Merry 	sc->WD_valid_config = FALSE;
399d043c564SKenneth D. Merry 	if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) {
400d043c564SKenneth D. Merry 		if (mps_config_get_man_pg10(sc, &mpi_reply)) {
401d043c564SKenneth D. Merry 			mps_dprint(sc, MPS_FAULT,
402d043c564SKenneth D. Merry 			    "mps_config_get_man_pg10 failed! Using 0 (Hide "
403d043c564SKenneth D. Merry 			    "Always) for WarpDrive hide/expose value.\n");
404d043c564SKenneth D. Merry 			sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
405d043c564SKenneth D. Merry 		}
406d043c564SKenneth D. Merry 
407d043c564SKenneth D. Merry 		/*
408d043c564SKenneth D. Merry 		 * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
409d043c564SKenneth D. Merry 		 */
410d043c564SKenneth D. Merry 		raid_vol_pg0 = malloc(sizeof(Mpi2RaidVolPage0_t) +
411d043c564SKenneth D. Merry 		    (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
412d043c564SKenneth D. Merry 		    M_MPT2, M_ZERO | M_NOWAIT);
413d043c564SKenneth D. Merry 		if (!raid_vol_pg0) {
414d043c564SKenneth D. Merry 			printf("%s: page alloc failed\n", __func__);
415d043c564SKenneth D. Merry 			goto out;
416d043c564SKenneth D. Merry 		}
417d043c564SKenneth D. Merry 
418d043c564SKenneth D. Merry 		if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
419d043c564SKenneth D. Merry 		    0x0000FFFF)) {
420d043c564SKenneth D. Merry 			mps_dprint(sc, MPS_INFO,
421d043c564SKenneth D. Merry 			    "mps_config_get_raid_volume_pg0 failed! Assuming "
422d043c564SKenneth D. Merry 			    "WarpDrive IT mode.\n");
423d043c564SKenneth D. Merry 			goto out;
424d043c564SKenneth D. Merry 		}
425d043c564SKenneth D. Merry 
426d043c564SKenneth D. Merry 		/*
427d043c564SKenneth D. Merry 		 * Check for valid WD configuration:
428d043c564SKenneth D. Merry 		 *   volume type is RAID0
429d043c564SKenneth D. Merry 		 *   number of phys disks in the volume is no more than 8
430d043c564SKenneth D. Merry 		 */
431d043c564SKenneth D. Merry 		if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) ||
432d043c564SKenneth D. Merry 		    (raid_vol_pg0->NumPhysDisks > 8)) {
433d043c564SKenneth D. Merry 			mps_dprint(sc, MPS_FAULT,
434d043c564SKenneth D. Merry 			    "Invalid WarpDrive configuration. Direct Drive I/O "
435d043c564SKenneth D. Merry 			    "will not be used.\n");
436d043c564SKenneth D. Merry 			goto out;
437d043c564SKenneth D. Merry 		}
438d043c564SKenneth D. Merry 
439d043c564SKenneth D. Merry 		/*
440d043c564SKenneth D. Merry 		 * Save the WD RAID data to be used during WD I/O.
441d043c564SKenneth D. Merry 		 */
442d043c564SKenneth D. Merry 		sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High <<
443d043c564SKenneth D. Merry 		    32 | (uint64_t)raid_vol_pg0->MaxLBA.Low);
444d043c564SKenneth D. Merry 		sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks;
445d043c564SKenneth D. Merry 		sc->DD_dev_handle = raid_vol_pg0->DevHandle;
446d043c564SKenneth D. Merry 		sc->DD_stripe_size = raid_vol_pg0->StripeSize;
447d043c564SKenneth D. Merry 		sc->DD_block_size = raid_vol_pg0->BlockSize;
448d043c564SKenneth D. Merry 
449d043c564SKenneth D. Merry 		/*
450d043c564SKenneth D. Merry 		 * Find power of 2 of stripe size and set this as the exponent.
451d043c564SKenneth D. Merry 		 * Fail if stripe size is 0.
452d043c564SKenneth D. Merry 		 */
453d043c564SKenneth D. Merry 		stripe_size = raid_vol_pg0->StripeSize;
454d043c564SKenneth D. Merry 		for (index = 0; index < 32; index++) {
455d043c564SKenneth D. Merry 			if (stripe_size & 1)
456d043c564SKenneth D. Merry 				break;
457d043c564SKenneth D. Merry 			stripe_exp++;
458d043c564SKenneth D. Merry 			stripe_size >>= 1;
459d043c564SKenneth D. Merry 		}
460d043c564SKenneth D. Merry 		if (index == 32) {
461d043c564SKenneth D. Merry 			mps_dprint(sc, MPS_FAULT,
462d043c564SKenneth D. Merry 			    "RAID Volume's stripe size is 0. Direct Drive I/O "
463d043c564SKenneth D. Merry 			    "will not be used.\n");
464d043c564SKenneth D. Merry 			goto out;
465d043c564SKenneth D. Merry 		}
466d043c564SKenneth D. Merry 		sc->DD_stripe_exponent = stripe_exp;
467d043c564SKenneth D. Merry 
468d043c564SKenneth D. Merry 		/*
469d043c564SKenneth D. Merry 		 * Find power of 2 of block size and set this as the exponent.
470d043c564SKenneth D. Merry 		 * Fail if block size is 0.
471d043c564SKenneth D. Merry 		 */
472d043c564SKenneth D. Merry 		block_size = raid_vol_pg0->BlockSize;
473d043c564SKenneth D. Merry 		for (index = 0; index < 16; index++) {
474d043c564SKenneth D. Merry 			if (block_size & 1)
475d043c564SKenneth D. Merry 				break;
476d043c564SKenneth D. Merry 			block_exp++;
477d043c564SKenneth D. Merry 			block_size >>= 1;
478d043c564SKenneth D. Merry 		}
479d043c564SKenneth D. Merry 		if (index == 16) {
480d043c564SKenneth D. Merry 			mps_dprint(sc, MPS_FAULT,
481d043c564SKenneth D. Merry 			    "RAID Volume's block size is 0. Direct Drive I/O "
482d043c564SKenneth D. Merry 			    "will not be used.\n");
483d043c564SKenneth D. Merry 			goto out;
484d043c564SKenneth D. Merry 		}
485d043c564SKenneth D. Merry 		sc->DD_block_exponent = block_exp;
486d043c564SKenneth D. Merry 
487d043c564SKenneth D. Merry 		/*
488d043c564SKenneth D. Merry 		 * Loop through all of the volume's Phys Disks to map the phys
489d043c564SKenneth D. Merry 		 * disk number into the columm map.  This is used during Direct
490d043c564SKenneth D. Merry 		 * Drive I/O to send the request to the correct SSD.
491d043c564SKenneth D. Merry 		 */
492d043c564SKenneth D. Merry 		pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk;
493d043c564SKenneth D. Merry 		for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
494d043c564SKenneth D. Merry 			sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num =
495d043c564SKenneth D. Merry 			    pRVPD->PhysDiskNum;
496d043c564SKenneth D. Merry 			pRVPD++;
497d043c564SKenneth D. Merry 		}
498d043c564SKenneth D. Merry 
499d043c564SKenneth D. Merry 		/*
500d043c564SKenneth D. Merry 		 * Get second RAID Volume Page0 using previous handle.  This
501d043c564SKenneth D. Merry 		 * page should not exist.  If it does, must not proceed with WD
502d043c564SKenneth D. Merry 		 * handling.
503d043c564SKenneth D. Merry 		 */
504d043c564SKenneth D. Merry 		if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
505d043c564SKenneth D. Merry 		    raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
506f4e69c98SStephen McConnell 			if ((le16toh(mpi_reply.IOCStatus) &
507f4e69c98SStephen McConnell 			    MPI2_IOCSTATUS_MASK) !=
508d043c564SKenneth D. Merry 			    MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
509d043c564SKenneth D. Merry 				mps_dprint(sc, MPS_FAULT,
510d043c564SKenneth D. Merry 				    "Multiple RAID Volume Page0! Direct Drive "
511d043c564SKenneth D. Merry 				    "I/O will not be used.\n");
512d043c564SKenneth D. Merry 				goto out;
513d043c564SKenneth D. Merry 			}
514d043c564SKenneth D. Merry 		} else {
515d043c564SKenneth D. Merry 			mps_dprint(sc, MPS_FAULT,
516d043c564SKenneth D. Merry 			    "Multiple volumes! Direct Drive I/O will not be "
517d043c564SKenneth D. Merry 			    "used.\n");
518d043c564SKenneth D. Merry 			goto out;
519d043c564SKenneth D. Merry 		}
520d043c564SKenneth D. Merry 
521d043c564SKenneth D. Merry 		/*
522d043c564SKenneth D. Merry 		 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
523d043c564SKenneth D. Merry 		 */
524d043c564SKenneth D. Merry 		for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
525d043c564SKenneth D. Merry 			phys_disk_page_address =
526d043c564SKenneth D. Merry 			    MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
527d043c564SKenneth D. Merry 			    sc->DD_column_map[index].phys_disk_num;
528d043c564SKenneth D. Merry 			if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
529d043c564SKenneth D. Merry 			    &phys_disk_pg0, phys_disk_page_address)) {
530d043c564SKenneth D. Merry 				mps_dprint(sc, MPS_FAULT,
531d043c564SKenneth D. Merry 				    "mps_config_get_raid_pd_pg0 failed! Direct "
532d043c564SKenneth D. Merry 				    "Drive I/O will not be used.\n");
533d043c564SKenneth D. Merry 				goto out;
534d043c564SKenneth D. Merry 			}
535d043c564SKenneth D. Merry 			if (phys_disk_pg0.DevHandle == 0xFFFF) {
536d043c564SKenneth D. Merry 				mps_dprint(sc, MPS_FAULT,
537d043c564SKenneth D. Merry 				    "Invalid Phys Disk DevHandle! Direct Drive "
538d043c564SKenneth D. Merry 				    "I/O will not be used.\n");
539d043c564SKenneth D. Merry 				goto out;
540d043c564SKenneth D. Merry 			}
541d043c564SKenneth D. Merry 			sc->DD_column_map[index].dev_handle =
542d043c564SKenneth D. Merry 			    phys_disk_pg0.DevHandle;
543d043c564SKenneth D. Merry 		}
544d043c564SKenneth D. Merry 		sc->WD_valid_config = TRUE;
545d043c564SKenneth D. Merry out:
546d043c564SKenneth D. Merry 		if (raid_vol_pg0)
547d043c564SKenneth D. Merry 			free(raid_vol_pg0, M_MPT2);
548d043c564SKenneth D. Merry 	}
549d043c564SKenneth D. Merry }
550d043c564SKenneth D. Merry 
551d043c564SKenneth D. Merry /**
552d043c564SKenneth D. Merry  * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
553d043c564SKenneth D. Merry  * @sc: per adapter object
554d043c564SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
555d043c564SKenneth D. Merry  * @config_page: contents of the config page
556d043c564SKenneth D. Merry  * @sz: size of buffer passed in config_page
557d043c564SKenneth D. Merry  * Context: sleep.
558d043c564SKenneth D. Merry  *
559d043c564SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
560d043c564SKenneth D. Merry  */
561d043c564SKenneth D. Merry int
mps_config_get_dpm_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 sz)562d043c564SKenneth D. Merry mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
563d043c564SKenneth D. Merry     Mpi2DriverMappingPage0_t *config_page, u16 sz)
564d043c564SKenneth D. Merry {
565d043c564SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
5666d4ffcb4SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply = NULL;
567d043c564SKenneth D. Merry 	struct mps_command *cm;
568d043c564SKenneth D. Merry 	Mpi2DriverMappingPage0_t *page = NULL;
569d043c564SKenneth D. Merry 	int error = 0;
570d043c564SKenneth D. Merry 	u16 ioc_status;
571d043c564SKenneth D. Merry 
572d043c564SKenneth D. Merry 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
573d043c564SKenneth D. Merry 
574d043c564SKenneth D. Merry 	memset(config_page, 0, sz);
575d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
576d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
577d043c564SKenneth D. Merry 		    __LINE__);
578d043c564SKenneth D. Merry 		error = EBUSY;
579d043c564SKenneth D. Merry 		goto out;
580d043c564SKenneth D. Merry 	}
581d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
582d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
583d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
584d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
585d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
586d043c564SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
587d043c564SKenneth D. Merry 	request->Header.PageNumber = 0;
588d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
589d043c564SKenneth D. Merry 	request->PageAddress = sc->max_dpm_entries <<
590d043c564SKenneth D. Merry 	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
591d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
592d043c564SKenneth D. Merry 	cm->cm_data = NULL;
5936d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
5946d4ffcb4SKenneth D. Merry 	if (cm != NULL)
595d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
596d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
597d043c564SKenneth D. Merry 		/* FIXME */
5989b91b192SKenneth D. Merry 		/*
5999b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
6009b91b192SKenneth D. Merry 		 * reset
6019b91b192SKenneth D. Merry 		 */
602074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
603d043c564SKenneth D. Merry 		    __func__, error);
604d043c564SKenneth D. Merry 		error = ENXIO;
605d043c564SKenneth D. Merry 		goto out;
606d043c564SKenneth D. Merry 	}
607d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
608d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
609d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
610d043c564SKenneth D. Merry 		/* FIXME */
6119b91b192SKenneth D. Merry 		/*
6129b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
6139b91b192SKenneth D. Merry 		 * reset
6149b91b192SKenneth D. Merry 		 */
615d043c564SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
616d043c564SKenneth D. Merry 		    __func__, ioc_status);
617d043c564SKenneth D. Merry 		error = ENXIO;
618d043c564SKenneth D. Merry 		goto out;
619d043c564SKenneth D. Merry 	}
620d043c564SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
621d043c564SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
622d043c564SKenneth D. Merry 	 */
623d043c564SKenneth D. Merry 	mps_free_command(sc, cm);
624d043c564SKenneth D. Merry 
625d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
626d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
627d043c564SKenneth D. Merry 		    __LINE__);
628d043c564SKenneth D. Merry 		error = EBUSY;
629d043c564SKenneth D. Merry 		goto out;
630d043c564SKenneth D. Merry 	}
631d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
632d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
633d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
634d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
635d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
636d043c564SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
637d043c564SKenneth D. Merry 	request->Header.PageNumber = 0;
638d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
639d043c564SKenneth D. Merry 	request->PageAddress = sc->max_dpm_entries <<
640d043c564SKenneth D. Merry 	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
641d043c564SKenneth D. Merry 	request->ExtPageLength = mpi_reply->ExtPageLength;
642d043c564SKenneth D. Merry 	cm->cm_length =  le16toh(request->ExtPageLength) * 4;
643d043c564SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
644d043c564SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
645d043c564SKenneth D. Merry 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
646d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
647d043c564SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPT2, M_ZERO|M_NOWAIT);
648d043c564SKenneth D. Merry 	if (!page) {
649d043c564SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
650d043c564SKenneth D. Merry 		error = ENOMEM;
651d043c564SKenneth D. Merry 		goto out;
652d043c564SKenneth D. Merry 	}
653d043c564SKenneth D. Merry 	cm->cm_data = page;
6546d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
6556d4ffcb4SKenneth D. Merry 	if (cm != NULL)
656d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
657d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
658d043c564SKenneth D. Merry 		/* FIXME */
6599b91b192SKenneth D. Merry 		/*
6609b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
6619b91b192SKenneth D. Merry 		 * reset
6629b91b192SKenneth D. Merry 		 */
663074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
664d043c564SKenneth D. Merry 		    __func__, error);
665d043c564SKenneth D. Merry 		error = ENXIO;
666d043c564SKenneth D. Merry 		goto out;
667d043c564SKenneth D. Merry 	}
668d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
669d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
670d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
671d043c564SKenneth D. Merry 		/* FIXME */
6729b91b192SKenneth D. Merry 		/*
6739b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
6749b91b192SKenneth D. Merry 		 * reset
6759b91b192SKenneth D. Merry 		 */
676d043c564SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
677d043c564SKenneth D. Merry 		    __func__, ioc_status);
678d043c564SKenneth D. Merry 		error = ENXIO;
679d043c564SKenneth D. Merry 		goto out;
680d043c564SKenneth D. Merry 	}
681d043c564SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length, sz));
682d043c564SKenneth D. Merry out:
683d043c564SKenneth D. Merry 	free(page, M_MPT2);
684d043c564SKenneth D. Merry 	if (cm)
685d043c564SKenneth D. Merry 		mps_free_command(sc, cm);
686d043c564SKenneth D. Merry 	return (error);
687d043c564SKenneth D. Merry }
688d043c564SKenneth D. Merry 
689d043c564SKenneth D. Merry /**
690d043c564SKenneth D. Merry  * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
691d043c564SKenneth D. Merry  * @sc: per adapter object
692d043c564SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
693d043c564SKenneth D. Merry  * @config_page: contents of the config page
694d043c564SKenneth D. Merry  * @entry_idx: entry index in DPM Page0 to be modified
695d043c564SKenneth D. Merry  * Context: sleep.
696d043c564SKenneth D. Merry  *
697d043c564SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
698d043c564SKenneth D. Merry  */
699d043c564SKenneth D. Merry 
mps_config_set_dpm_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 entry_idx)700d043c564SKenneth D. Merry int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
701d043c564SKenneth D. Merry     Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
702d043c564SKenneth D. Merry {
703d043c564SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
7046d4ffcb4SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply = NULL;
705d043c564SKenneth D. Merry 	struct mps_command *cm;
706d043c564SKenneth D. Merry 	MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
707d043c564SKenneth D. Merry 	int error = 0;
708d043c564SKenneth D. Merry 	u16 ioc_status;
709d043c564SKenneth D. Merry 
710d043c564SKenneth D. Merry 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
711d043c564SKenneth D. Merry 
712d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
713d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
714d043c564SKenneth D. Merry 		    __LINE__);
715d043c564SKenneth D. Merry 		error = EBUSY;
716d043c564SKenneth D. Merry 		goto out;
717d043c564SKenneth D. Merry 	}
718d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
719d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
720d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
721d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
722d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
723d043c564SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
724d043c564SKenneth D. Merry 	request->Header.PageNumber = 0;
725d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
726be4aa869SKenneth D. Merry 	/* We can remove below two lines ????*/
727d043c564SKenneth D. Merry 	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
728d043c564SKenneth D. Merry 	request->PageAddress |= htole16(entry_idx);
729d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
730d043c564SKenneth D. Merry 	cm->cm_data = NULL;
7316d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
7326d4ffcb4SKenneth D. Merry 	if (cm != NULL)
733d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
734d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
735d043c564SKenneth D. Merry 		/* FIXME */
7369b91b192SKenneth D. Merry 		/*
7379b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
7389b91b192SKenneth D. Merry 		 * reset
7399b91b192SKenneth D. Merry 		 */
740074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
741d043c564SKenneth D. Merry 		    __func__, error);
742d043c564SKenneth D. Merry 		error = ENXIO;
743d043c564SKenneth D. Merry 		goto out;
744d043c564SKenneth D. Merry 	}
745d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
746d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
747d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
748d043c564SKenneth D. Merry 		/* FIXME */
7499b91b192SKenneth D. Merry 		/*
7509b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
7519b91b192SKenneth D. Merry 		 * reset
7529b91b192SKenneth D. Merry 		 */
753d043c564SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
754d043c564SKenneth D. Merry 		    __func__, ioc_status);
755d043c564SKenneth D. Merry 		error = ENXIO;
756d043c564SKenneth D. Merry 		goto out;
757d043c564SKenneth D. Merry 	}
758d043c564SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
759d043c564SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
760d043c564SKenneth D. Merry 	 */
761d043c564SKenneth D. Merry 	mps_free_command(sc, cm);
762d043c564SKenneth D. Merry 
763d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
764d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
765d043c564SKenneth D. Merry 		    __LINE__);
766d043c564SKenneth D. Merry 		error = EBUSY;
767d043c564SKenneth D. Merry 		goto out;
768d043c564SKenneth D. Merry 	}
769d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
770d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
771d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
772d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
773d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
774d043c564SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
775d043c564SKenneth D. Merry 	request->Header.PageNumber = 0;
776d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
777d043c564SKenneth D. Merry 	request->ExtPageLength = mpi_reply->ExtPageLength;
778d043c564SKenneth D. Merry 	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
779d043c564SKenneth D. Merry 	request->PageAddress |= htole16(entry_idx);
780d043c564SKenneth D. Merry 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
781d043c564SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
782d043c564SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
783d043c564SKenneth D. Merry 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
784d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
785d043c564SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
786d043c564SKenneth D. Merry 	if (!page) {
787d043c564SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
788d043c564SKenneth D. Merry 		error = ENOMEM;
789d043c564SKenneth D. Merry 		goto out;
790d043c564SKenneth D. Merry 	}
791d043c564SKenneth D. Merry 	bcopy(config_page, page, MIN(cm->cm_length,
792d043c564SKenneth D. Merry 	    (sizeof(Mpi2DriverMappingPage0_t))));
793d043c564SKenneth D. Merry 	cm->cm_data = page;
7946d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
7956d4ffcb4SKenneth D. Merry 	if (cm != NULL)
796d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
797d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
798d043c564SKenneth D. Merry 		/* FIXME */
7999b91b192SKenneth D. Merry 		/*
8009b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
8019b91b192SKenneth D. Merry 		 * reset
8029b91b192SKenneth D. Merry 		 */
803074bed4fSAlexander Motin 		printf("%s: request to write page completed with error %d\n",
804d043c564SKenneth D. Merry 		    __func__, error);
805d043c564SKenneth D. Merry 		error = ENXIO;
806d043c564SKenneth D. Merry 		goto out;
807d043c564SKenneth D. Merry 	}
808d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
809d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
810d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
811d043c564SKenneth D. Merry 		/* FIXME */
8129b91b192SKenneth D. Merry 		/*
8139b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
8149b91b192SKenneth D. Merry 		 * reset
8159b91b192SKenneth D. Merry 		 */
816d043c564SKenneth D. Merry 		printf("%s: page written with error; iocstatus = 0x%x\n",
817d043c564SKenneth D. Merry 		    __func__, ioc_status);
818d043c564SKenneth D. Merry 		error = ENXIO;
819d043c564SKenneth D. Merry 		goto out;
820d043c564SKenneth D. Merry 	}
821d043c564SKenneth D. Merry out:
822d043c564SKenneth D. Merry 	free(page, M_MPT2);
823d043c564SKenneth D. Merry 	if (cm)
824d043c564SKenneth D. Merry 		mps_free_command(sc, cm);
825d043c564SKenneth D. Merry 	return (error);
826d043c564SKenneth D. Merry }
827d043c564SKenneth D. Merry 
828d043c564SKenneth D. Merry /**
829d043c564SKenneth D. Merry  * mps_config_get_sas_device_pg0 - obtain sas device page 0
830d043c564SKenneth D. Merry  * @sc: per adapter object
831d043c564SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
832d043c564SKenneth D. Merry  * @config_page: contents of the config page
833d043c564SKenneth D. Merry  * @form: GET_NEXT_HANDLE or HANDLE
834d043c564SKenneth D. Merry  * @handle: device handle
835d043c564SKenneth D. Merry  * Context: sleep.
836d043c564SKenneth D. Merry  *
837d043c564SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
838d043c564SKenneth D. Merry  */
839d043c564SKenneth D. Merry int
mps_config_get_sas_device_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2SasDevicePage0_t * config_page,u32 form,u16 handle)840d043c564SKenneth D. Merry mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
841d043c564SKenneth D. Merry     *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
842d043c564SKenneth D. Merry {
843d043c564SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
8446d4ffcb4SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply = NULL;
845d043c564SKenneth D. Merry 	struct mps_command *cm;
846d043c564SKenneth D. Merry 	Mpi2SasDevicePage0_t *page = NULL;
847d043c564SKenneth D. Merry 	int error = 0;
848d043c564SKenneth D. Merry 	u16 ioc_status;
849d043c564SKenneth D. Merry 
850d043c564SKenneth D. Merry 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
851d043c564SKenneth D. Merry 
852d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
853d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
854d043c564SKenneth D. Merry 		    __LINE__);
855d043c564SKenneth D. Merry 		error = EBUSY;
856d043c564SKenneth D. Merry 		goto out;
857d043c564SKenneth D. Merry 	}
858d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
859d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
860d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
861d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
862d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
863d043c564SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
864d043c564SKenneth D. Merry 	request->Header.PageNumber = 0;
865d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
866d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
867d043c564SKenneth D. Merry 	cm->cm_data = NULL;
8686d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
8696d4ffcb4SKenneth D. Merry 	if (cm != NULL)
870d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
871d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
872d043c564SKenneth D. Merry 		/* FIXME */
8739b91b192SKenneth D. Merry 		/*
8749b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
8759b91b192SKenneth D. Merry 		 * reset
8769b91b192SKenneth D. Merry 		 */
877074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
878d043c564SKenneth D. Merry 		    __func__, error);
879d043c564SKenneth D. Merry 		error = ENXIO;
880d043c564SKenneth D. Merry 		goto out;
881d043c564SKenneth D. Merry 	}
882d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
883d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
884d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
885d043c564SKenneth D. Merry 		/* FIXME */
8869b91b192SKenneth D. Merry 		/*
8879b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
8889b91b192SKenneth D. Merry 		 * reset
8899b91b192SKenneth D. Merry 		 */
890d043c564SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
891d043c564SKenneth D. Merry 		    __func__, ioc_status);
892d043c564SKenneth D. Merry 		error = ENXIO;
893d043c564SKenneth D. Merry 		goto out;
894d043c564SKenneth D. Merry 	}
895d043c564SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
896d043c564SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
897d043c564SKenneth D. Merry 	 */
898d043c564SKenneth D. Merry 	mps_free_command(sc, cm);
899d043c564SKenneth D. Merry 
900d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
901d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
902d043c564SKenneth D. Merry 		    __LINE__);
903d043c564SKenneth D. Merry 		error = EBUSY;
904d043c564SKenneth D. Merry 		goto out;
905d043c564SKenneth D. Merry 	}
906d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
907d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
908d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
909d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
910d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
911d043c564SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
912d043c564SKenneth D. Merry 	request->Header.PageNumber = 0;
913d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
914d043c564SKenneth D. Merry 	request->ExtPageLength = mpi_reply->ExtPageLength;
915d043c564SKenneth D. Merry 	request->PageAddress = htole32(form | handle);
916d043c564SKenneth D. Merry 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
917d043c564SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
918d043c564SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
919d043c564SKenneth D. Merry 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
920d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
921d043c564SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
922d043c564SKenneth D. Merry 	if (!page) {
923d043c564SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
924d043c564SKenneth D. Merry 		error = ENOMEM;
925d043c564SKenneth D. Merry 		goto out;
926d043c564SKenneth D. Merry 	}
927d043c564SKenneth D. Merry 	cm->cm_data = page;
928d043c564SKenneth D. Merry 
9296d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
9306d4ffcb4SKenneth D. Merry 	if (cm != NULL)
931d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
932d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
933d043c564SKenneth D. Merry 		/* FIXME */
9349b91b192SKenneth D. Merry 		/*
9359b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
9369b91b192SKenneth D. Merry 		 * reset
9379b91b192SKenneth D. Merry 		 */
938074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
939d043c564SKenneth D. Merry 		    __func__, error);
940d043c564SKenneth D. Merry 		error = ENXIO;
941d043c564SKenneth D. Merry 		goto out;
942d043c564SKenneth D. Merry 	}
943d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
944d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
945d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
946d043c564SKenneth D. Merry 		/* FIXME */
9479b91b192SKenneth D. Merry 		/*
9489b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
9499b91b192SKenneth D. Merry 		 * reset
9509b91b192SKenneth D. Merry 		 */
951d043c564SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
952d043c564SKenneth D. Merry 		    __func__, ioc_status);
953d043c564SKenneth D. Merry 		error = ENXIO;
954d043c564SKenneth D. Merry 		goto out;
955d043c564SKenneth D. Merry 	}
956d043c564SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length,
957d043c564SKenneth D. Merry 	    sizeof(Mpi2SasDevicePage0_t)));
958d043c564SKenneth D. Merry out:
959d043c564SKenneth D. Merry 	free(page, M_MPT2);
960d043c564SKenneth D. Merry 	if (cm)
961d043c564SKenneth D. Merry 		mps_free_command(sc, cm);
962d043c564SKenneth D. Merry 	return (error);
963d043c564SKenneth D. Merry }
964d043c564SKenneth D. Merry 
965d043c564SKenneth D. Merry /**
966d043c564SKenneth D. Merry  * mps_config_get_bios_pg3 - obtain BIOS page 3
967d043c564SKenneth D. Merry  * @sc: per adapter object
968d043c564SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
969d043c564SKenneth D. Merry  * @config_page: contents of the config page
970d043c564SKenneth D. Merry  * Context: sleep.
971d043c564SKenneth D. Merry  *
972d043c564SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
973d043c564SKenneth D. Merry  */
974d043c564SKenneth D. Merry int
mps_config_get_bios_pg3(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2BiosPage3_t * config_page)975d043c564SKenneth D. Merry mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
976d043c564SKenneth D. Merry     Mpi2BiosPage3_t *config_page)
977d043c564SKenneth D. Merry {
978d043c564SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
9796d4ffcb4SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply = NULL;
980d043c564SKenneth D. Merry 	struct mps_command *cm;
981d043c564SKenneth D. Merry 	Mpi2BiosPage3_t *page = NULL;
982d043c564SKenneth D. Merry 	int error = 0;
983d043c564SKenneth D. Merry 	u16 ioc_status;
984d043c564SKenneth D. Merry 
985d043c564SKenneth D. Merry 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
986d043c564SKenneth D. Merry 
987d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
988d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
989d043c564SKenneth D. Merry 		    __LINE__);
990d043c564SKenneth D. Merry 		error = EBUSY;
991d043c564SKenneth D. Merry 		goto out;
992d043c564SKenneth D. Merry 	}
993d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
994d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
995d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
996d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
997d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
998d043c564SKenneth D. Merry 	request->Header.PageNumber = 3;
999d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1000d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1001d043c564SKenneth D. Merry 	cm->cm_data = NULL;
10026d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
10036d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1004d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1005d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
1006d043c564SKenneth D. Merry 		/* FIXME */
10079b91b192SKenneth D. Merry 		/*
10089b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
10099b91b192SKenneth D. Merry 		 * reset
10109b91b192SKenneth D. Merry 		 */
1011074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
1012d043c564SKenneth D. Merry 		    __func__, error);
1013d043c564SKenneth D. Merry 		error = ENXIO;
1014d043c564SKenneth D. Merry 		goto out;
1015d043c564SKenneth D. Merry 	}
1016d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1017d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1018d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1019d043c564SKenneth D. Merry 		/* FIXME */
10209b91b192SKenneth D. Merry 		/*
10219b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
10229b91b192SKenneth D. Merry 		 * reset
10239b91b192SKenneth D. Merry 		 */
1024d043c564SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
1025d043c564SKenneth D. Merry 		    __func__, ioc_status);
1026d043c564SKenneth D. Merry 		error = ENXIO;
1027d043c564SKenneth D. Merry 		goto out;
1028d043c564SKenneth D. Merry 	}
1029d043c564SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
1030d043c564SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
1031d043c564SKenneth D. Merry 	 */
1032d043c564SKenneth D. Merry 	mps_free_command(sc, cm);
1033d043c564SKenneth D. Merry 
1034d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
1035d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1036d043c564SKenneth D. Merry 		    __LINE__);
1037d043c564SKenneth D. Merry 		error = EBUSY;
1038d043c564SKenneth D. Merry 		goto out;
1039d043c564SKenneth D. Merry 	}
1040d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1041d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1042d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1043d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1044d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1045d043c564SKenneth D. Merry 	request->Header.PageNumber = 3;
1046d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
1047d043c564SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
1048d043c564SKenneth D. Merry 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1049d043c564SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
1050d043c564SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1051d043c564SKenneth D. Merry 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1052d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1053d043c564SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1054d043c564SKenneth D. Merry 	if (!page) {
1055d043c564SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
1056d043c564SKenneth D. Merry 		error = ENOMEM;
1057d043c564SKenneth D. Merry 		goto out;
1058d043c564SKenneth D. Merry 	}
1059d043c564SKenneth D. Merry 	cm->cm_data = page;
1060d043c564SKenneth D. Merry 
10616d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
10626d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1063d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1064d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
1065d043c564SKenneth D. Merry 		/* FIXME */
10669b91b192SKenneth D. Merry 		/*
10679b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
10689b91b192SKenneth D. Merry 		 * reset
10699b91b192SKenneth D. Merry 		 */
1070074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
1071d043c564SKenneth D. Merry 		    __func__, error);
1072d043c564SKenneth D. Merry 		error = ENXIO;
1073d043c564SKenneth D. Merry 		goto out;
1074d043c564SKenneth D. Merry 	}
1075d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1076d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1077d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1078d043c564SKenneth D. Merry 		/* FIXME */
10799b91b192SKenneth D. Merry 		/*
10809b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
10819b91b192SKenneth D. Merry 		 * reset
10829b91b192SKenneth D. Merry 		 */
1083d043c564SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
1084d043c564SKenneth D. Merry 		    __func__, ioc_status);
1085d043c564SKenneth D. Merry 		error = ENXIO;
1086d043c564SKenneth D. Merry 		goto out;
1087d043c564SKenneth D. Merry 	}
1088d043c564SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1089d043c564SKenneth D. Merry out:
1090d043c564SKenneth D. Merry 	free(page, M_MPT2);
1091d043c564SKenneth D. Merry 	if (cm)
1092d043c564SKenneth D. Merry 		mps_free_command(sc, cm);
1093d043c564SKenneth D. Merry 	return (error);
1094d043c564SKenneth D. Merry }
1095d043c564SKenneth D. Merry 
1096d043c564SKenneth D. Merry /**
1097d043c564SKenneth D. Merry  * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1098d043c564SKenneth D. Merry  * @sc: per adapter object
1099d043c564SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
1100d043c564SKenneth D. Merry  * @config_page: contents of the config page
1101d043c564SKenneth D. Merry  * @page_address: form and handle value used to get page
1102d043c564SKenneth D. Merry  * Context: sleep.
1103d043c564SKenneth D. Merry  *
1104d043c564SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
1105d043c564SKenneth D. Merry  */
1106d043c564SKenneth D. Merry int
mps_config_get_raid_volume_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage0_t * config_page,u32 page_address)1107d043c564SKenneth D. Merry mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1108d043c564SKenneth D. Merry     *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1109d043c564SKenneth D. Merry {
1110d043c564SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
11116d4ffcb4SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply = NULL;
1112d043c564SKenneth D. Merry 	struct mps_command *cm;
1113d043c564SKenneth D. Merry 	Mpi2RaidVolPage0_t *page = NULL;
1114d043c564SKenneth D. Merry 	int error = 0;
1115d043c564SKenneth D. Merry 	u16 ioc_status;
1116d043c564SKenneth D. Merry 
1117d043c564SKenneth D. Merry 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1118d043c564SKenneth D. Merry 
1119d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
1120d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1121d043c564SKenneth D. Merry 		    __LINE__);
1122d043c564SKenneth D. Merry 		error = EBUSY;
1123d043c564SKenneth D. Merry 		goto out;
1124d043c564SKenneth D. Merry 	}
1125d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1126d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1127d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1128d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1129d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1130d043c564SKenneth D. Merry 	request->Header.PageNumber = 0;
1131d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1132d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1133d043c564SKenneth D. Merry 	cm->cm_data = NULL;
11349b91b192SKenneth D. Merry 
11359b91b192SKenneth D. Merry 	/*
11369b91b192SKenneth D. Merry 	 * This page must be polled because the IOC isn't ready yet when this
11379b91b192SKenneth D. Merry 	 * page is needed.
11389b91b192SKenneth D. Merry 	 */
11396d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, 0);
11406d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1141d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1142d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
1143d043c564SKenneth D. Merry 		/* FIXME */
1144d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1145074bed4fSAlexander Motin 		printf("%s: poll for header completed with error %d\n",
1146d043c564SKenneth D. Merry 		    __func__, error);
1147d043c564SKenneth D. Merry 		error = ENXIO;
1148d043c564SKenneth D. Merry 		goto out;
1149d043c564SKenneth D. Merry 	}
1150d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1151d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1152d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1153d043c564SKenneth D. Merry 		/* FIXME */
1154d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1155d043c564SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
1156d043c564SKenneth D. Merry 		    __func__, ioc_status);
1157d043c564SKenneth D. Merry 		error = ENXIO;
1158d043c564SKenneth D. Merry 		goto out;
1159d043c564SKenneth D. Merry 	}
1160d043c564SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
1161d043c564SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
1162d043c564SKenneth D. Merry 	 */
1163d043c564SKenneth D. Merry 	mps_free_command(sc, cm);
1164d043c564SKenneth D. Merry 
1165d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
1166d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1167d043c564SKenneth D. Merry 		    __LINE__);
1168d043c564SKenneth D. Merry 		error = EBUSY;
1169d043c564SKenneth D. Merry 		goto out;
1170d043c564SKenneth D. Merry 	}
1171d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1172d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1173d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1174d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1175d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1176d043c564SKenneth D. Merry 	request->Header.PageNumber = 0;
1177d043c564SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
1178d043c564SKenneth D. Merry 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1179d043c564SKenneth D. Merry 	request->PageAddress = page_address;
1180d043c564SKenneth D. Merry 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1181d043c564SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
1182d043c564SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1183d043c564SKenneth D. Merry 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1184d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1185d043c564SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1186d043c564SKenneth D. Merry 	if (!page) {
1187d043c564SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
1188d043c564SKenneth D. Merry 		error = ENOMEM;
1189d043c564SKenneth D. Merry 		goto out;
1190d043c564SKenneth D. Merry 	}
1191d043c564SKenneth D. Merry 	cm->cm_data = page;
1192d043c564SKenneth D. Merry 
11939b91b192SKenneth D. Merry 	/*
11949b91b192SKenneth D. Merry 	 * This page must be polled because the IOC isn't ready yet when this
11959b91b192SKenneth D. Merry 	 * page is needed.
11969b91b192SKenneth D. Merry 	 */
11976d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, 0);
11986d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1199d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1200d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
1201d043c564SKenneth D. Merry 		/* FIXME */
1202d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1203074bed4fSAlexander Motin 		printf("%s: poll for page completed with error %d\n",
1204d043c564SKenneth D. Merry 		    __func__, error);
1205d043c564SKenneth D. Merry 		error = ENXIO;
1206d043c564SKenneth D. Merry 		goto out;
1207d043c564SKenneth D. Merry 	}
1208d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1209d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1210d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1211d043c564SKenneth D. Merry 		/* FIXME */
1212d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1213d043c564SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
1214d043c564SKenneth D. Merry 		    __func__, ioc_status);
1215d043c564SKenneth D. Merry 		error = ENXIO;
1216d043c564SKenneth D. Merry 		goto out;
1217d043c564SKenneth D. Merry 	}
1218d043c564SKenneth D. Merry 	bcopy(page, config_page, cm->cm_length);
1219d043c564SKenneth D. Merry out:
1220d043c564SKenneth D. Merry 	free(page, M_MPT2);
1221d043c564SKenneth D. Merry 	if (cm)
1222d043c564SKenneth D. Merry 		mps_free_command(sc, cm);
1223d043c564SKenneth D. Merry 	return (error);
1224d043c564SKenneth D. Merry }
1225d043c564SKenneth D. Merry 
1226d043c564SKenneth D. Merry /**
1227d043c564SKenneth D. Merry  * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1228d043c564SKenneth D. Merry  * @sc: per adapter object
1229d043c564SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
1230d043c564SKenneth D. Merry  * @config_page: contents of the config page
1231d043c564SKenneth D. Merry  * @form: GET_NEXT_HANDLE or HANDLE
1232d043c564SKenneth D. Merry  * @handle: volume handle
1233d043c564SKenneth D. Merry  * Context: sleep.
1234d043c564SKenneth D. Merry  *
1235d043c564SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
1236d043c564SKenneth D. Merry  */
1237d043c564SKenneth D. Merry int
mps_config_get_raid_volume_pg1(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage1_t * config_page,u32 form,u16 handle)1238d043c564SKenneth D. Merry mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1239d043c564SKenneth D. Merry     *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1240d043c564SKenneth D. Merry {
1241d043c564SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
12426d4ffcb4SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply = NULL;
1243d043c564SKenneth D. Merry 	struct mps_command *cm;
1244d043c564SKenneth D. Merry 	Mpi2RaidVolPage1_t *page = NULL;
1245d043c564SKenneth D. Merry 	int error = 0;
1246d043c564SKenneth D. Merry 	u16 ioc_status;
1247d043c564SKenneth D. Merry 
1248d043c564SKenneth D. Merry 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1249d043c564SKenneth D. Merry 
1250d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
1251d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1252d043c564SKenneth D. Merry 		    __LINE__);
1253d043c564SKenneth D. Merry 		error = EBUSY;
1254d043c564SKenneth D. Merry 		goto out;
1255d043c564SKenneth D. Merry 	}
1256d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1257d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1258d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1259d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1260d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1261d043c564SKenneth D. Merry 	request->Header.PageNumber = 1;
1262d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1263d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1264d043c564SKenneth D. Merry 	cm->cm_data = NULL;
12656d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
12666d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1267d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1268d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
1269d043c564SKenneth D. Merry 		/* FIXME */
12709b91b192SKenneth D. Merry 		/*
12719b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
12729b91b192SKenneth D. Merry 		 * reset
12739b91b192SKenneth D. Merry 		 */
1274074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
1275d043c564SKenneth D. Merry 		    __func__, error);
1276d043c564SKenneth D. Merry 		error = ENXIO;
1277d043c564SKenneth D. Merry 		goto out;
1278d043c564SKenneth D. Merry 	}
1279d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1280d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1281d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1282d043c564SKenneth D. Merry 		/* FIXME */
12839b91b192SKenneth D. Merry 		/*
12849b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
12859b91b192SKenneth D. Merry 		 * reset
12869b91b192SKenneth D. Merry 		 */
1287d043c564SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
1288d043c564SKenneth D. Merry 		    __func__, ioc_status);
1289d043c564SKenneth D. Merry 		error = ENXIO;
1290d043c564SKenneth D. Merry 		goto out;
1291d043c564SKenneth D. Merry 	}
1292d043c564SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
1293d043c564SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
1294d043c564SKenneth D. Merry 	 */
1295d043c564SKenneth D. Merry 	mps_free_command(sc, cm);
1296d043c564SKenneth D. Merry 
1297d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
1298d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1299d043c564SKenneth D. Merry 		    __LINE__);
1300d043c564SKenneth D. Merry 		error = EBUSY;
1301d043c564SKenneth D. Merry 		goto out;
1302d043c564SKenneth D. Merry 	}
1303d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1304d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1305d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1306d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1307d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1308d043c564SKenneth D. Merry 	request->Header.PageNumber = 1;
1309d043c564SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
1310d043c564SKenneth D. Merry 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1311d043c564SKenneth D. Merry 	request->PageAddress = htole32(form | handle);
1312d043c564SKenneth D. Merry 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1313d043c564SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
1314d043c564SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1315d043c564SKenneth D. Merry 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1316d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1317d043c564SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1318d043c564SKenneth D. Merry 	if (!page) {
1319d043c564SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
1320d043c564SKenneth D. Merry 		error = ENOMEM;
1321d043c564SKenneth D. Merry 		goto out;
1322d043c564SKenneth D. Merry 	}
1323d043c564SKenneth D. Merry 	cm->cm_data = page;
1324d043c564SKenneth D. Merry 
13256d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, CAN_SLEEP);
13266d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1327d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1328d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
1329d043c564SKenneth D. Merry 		/* FIXME */
13309b91b192SKenneth D. Merry 		/*
13319b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
13329b91b192SKenneth D. Merry 		 * reset
13339b91b192SKenneth D. Merry 		 */
1334074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
1335d043c564SKenneth D. Merry 		    __func__, error);
1336d043c564SKenneth D. Merry 		error = ENXIO;
1337d043c564SKenneth D. Merry 		goto out;
1338d043c564SKenneth D. Merry 	}
1339d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1340d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1341d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1342d043c564SKenneth D. Merry 		/* FIXME */
13439b91b192SKenneth D. Merry 		/*
13449b91b192SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
13459b91b192SKenneth D. Merry 		 * reset
13469b91b192SKenneth D. Merry 		 */
1347d043c564SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
1348d043c564SKenneth D. Merry 		    __func__, ioc_status);
1349d043c564SKenneth D. Merry 		error = ENXIO;
1350d043c564SKenneth D. Merry 		goto out;
1351d043c564SKenneth D. Merry 	}
1352d043c564SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length,
1353d043c564SKenneth D. Merry 	    sizeof(Mpi2RaidVolPage1_t)));
1354d043c564SKenneth D. Merry out:
1355d043c564SKenneth D. Merry 	free(page, M_MPT2);
1356d043c564SKenneth D. Merry 	if (cm)
1357d043c564SKenneth D. Merry 		mps_free_command(sc, cm);
1358d043c564SKenneth D. Merry 	return (error);
1359d043c564SKenneth D. Merry }
1360d043c564SKenneth D. Merry 
1361d043c564SKenneth D. Merry /**
1362d043c564SKenneth D. Merry  * mps_config_get_volume_wwid - returns wwid given the volume handle
1363d043c564SKenneth D. Merry  * @sc: per adapter object
1364d043c564SKenneth D. Merry  * @volume_handle: volume handle
1365d043c564SKenneth D. Merry  * @wwid: volume wwid
1366d043c564SKenneth D. Merry  * Context: sleep.
1367d043c564SKenneth D. Merry  *
1368d043c564SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
1369d043c564SKenneth D. Merry  */
1370d043c564SKenneth D. Merry int
mps_config_get_volume_wwid(struct mps_softc * sc,u16 volume_handle,u64 * wwid)1371d043c564SKenneth D. Merry mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1372d043c564SKenneth D. Merry {
1373d043c564SKenneth D. Merry 	Mpi2ConfigReply_t mpi_reply;
1374d043c564SKenneth D. Merry 	Mpi2RaidVolPage1_t raid_vol_pg1;
1375d043c564SKenneth D. Merry 
1376d043c564SKenneth D. Merry 	*wwid = 0;
1377d043c564SKenneth D. Merry 	if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1378d043c564SKenneth D. Merry 	    MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1379d043c564SKenneth D. Merry 		*wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1380d043c564SKenneth D. Merry 		    raid_vol_pg1.WWID.Low);
1381d043c564SKenneth D. Merry 		return 0;
1382d043c564SKenneth D. Merry 	} else
1383d043c564SKenneth D. Merry 		return -1;
1384d043c564SKenneth D. Merry }
1385d043c564SKenneth D. Merry 
1386d043c564SKenneth D. Merry /**
1387d043c564SKenneth D. Merry  * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1388d043c564SKenneth D. Merry  * @sc: per adapter object
1389d043c564SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
1390d043c564SKenneth D. Merry  * @config_page: contents of the config page
1391d043c564SKenneth D. Merry  * @page_address: form and handle value used to get page
1392d043c564SKenneth D. Merry  * Context: sleep.
1393d043c564SKenneth D. Merry  *
1394d043c564SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
1395d043c564SKenneth D. Merry  */
1396d043c564SKenneth D. Merry int
mps_config_get_raid_pd_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidPhysDiskPage0_t * config_page,u32 page_address)1397d043c564SKenneth D. Merry mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1398d043c564SKenneth D. Merry     Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1399d043c564SKenneth D. Merry {
1400d043c564SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
14016d4ffcb4SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply = NULL;
1402d043c564SKenneth D. Merry 	struct mps_command *cm;
1403d043c564SKenneth D. Merry 	Mpi2RaidPhysDiskPage0_t *page = NULL;
1404d043c564SKenneth D. Merry 	int error = 0;
1405d043c564SKenneth D. Merry 	u16 ioc_status;
1406d043c564SKenneth D. Merry 
1407d043c564SKenneth D. Merry 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1408d043c564SKenneth D. Merry 
1409d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
1410d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1411d043c564SKenneth D. Merry 		    __LINE__);
1412d043c564SKenneth D. Merry 		error = EBUSY;
1413d043c564SKenneth D. Merry 		goto out;
1414d043c564SKenneth D. Merry 	}
1415d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1416d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1417d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1418d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1419d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1420d043c564SKenneth D. Merry 	request->Header.PageNumber = 0;
1421d043c564SKenneth D. Merry 	request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1422d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1423d043c564SKenneth D. Merry 	cm->cm_data = NULL;
14249b91b192SKenneth D. Merry 
14259b91b192SKenneth D. Merry 	/*
14269b91b192SKenneth D. Merry 	 * This page must be polled because the IOC isn't ready yet when this
14279b91b192SKenneth D. Merry 	 * page is needed.
14289b91b192SKenneth D. Merry 	 */
14296d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, 0);
14306d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1431d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1432d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
1433d043c564SKenneth D. Merry 		/* FIXME */
1434d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1435074bed4fSAlexander Motin 		printf("%s: poll for header completed with error %d\n",
1436d043c564SKenneth D. Merry 		    __func__, error);
1437d043c564SKenneth D. Merry 		error = ENXIO;
1438d043c564SKenneth D. Merry 		goto out;
1439d043c564SKenneth D. Merry 	}
1440d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1441d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1442d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1443d043c564SKenneth D. Merry 		/* FIXME */
1444d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1445d043c564SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
1446d043c564SKenneth D. Merry 		    __func__, ioc_status);
1447d043c564SKenneth D. Merry 		error = ENXIO;
1448d043c564SKenneth D. Merry 		goto out;
1449d043c564SKenneth D. Merry 	}
1450d043c564SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
1451d043c564SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
1452d043c564SKenneth D. Merry 	 */
1453d043c564SKenneth D. Merry 	mps_free_command(sc, cm);
1454d043c564SKenneth D. Merry 
1455d043c564SKenneth D. Merry 	if ((cm = mps_alloc_command(sc)) == NULL) {
1456d043c564SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1457d043c564SKenneth D. Merry 		    __LINE__);
1458d043c564SKenneth D. Merry 		error = EBUSY;
1459d043c564SKenneth D. Merry 		goto out;
1460d043c564SKenneth D. Merry 	}
1461d043c564SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1462d043c564SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1463d043c564SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1464d043c564SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1465d043c564SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1466d043c564SKenneth D. Merry 	request->Header.PageNumber = 0;
1467d043c564SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
1468d043c564SKenneth D. Merry 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1469d043c564SKenneth D. Merry 	request->PageAddress = page_address;
1470d043c564SKenneth D. Merry 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1471d043c564SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
1472d043c564SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1473d043c564SKenneth D. Merry 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1474d043c564SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1475d043c564SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1476d043c564SKenneth D. Merry 	if (!page) {
1477d043c564SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
1478d043c564SKenneth D. Merry 		error = ENOMEM;
1479d043c564SKenneth D. Merry 		goto out;
1480d043c564SKenneth D. Merry 	}
1481d043c564SKenneth D. Merry 	cm->cm_data = page;
1482d043c564SKenneth D. Merry 
14839b91b192SKenneth D. Merry 	/*
14849b91b192SKenneth D. Merry 	 * This page must be polled because the IOC isn't ready yet when this
14859b91b192SKenneth D. Merry 	 * page is needed.
14869b91b192SKenneth D. Merry 	 */
14876d4ffcb4SKenneth D. Merry 	error = mps_wait_command(sc, &cm, 60, 0);
14886d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1489d043c564SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1490d043c564SKenneth D. Merry 	if (error || (reply == NULL)) {
1491d043c564SKenneth D. Merry 		/* FIXME */
1492d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1493074bed4fSAlexander Motin 		printf("%s: poll for page completed with error %d\n",
1494d043c564SKenneth D. Merry 		    __func__, error);
1495d043c564SKenneth D. Merry 		error = ENXIO;
1496d043c564SKenneth D. Merry 		goto out;
1497d043c564SKenneth D. Merry 	}
1498d043c564SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1499d043c564SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1500d043c564SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1501d043c564SKenneth D. Merry 		/* FIXME */
1502d043c564SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1503d043c564SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
1504d043c564SKenneth D. Merry 		    __func__, ioc_status);
1505d043c564SKenneth D. Merry 		error = ENXIO;
1506d043c564SKenneth D. Merry 		goto out;
1507d043c564SKenneth D. Merry 	}
1508d043c564SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length,
1509d043c564SKenneth D. Merry 	    sizeof(Mpi2RaidPhysDiskPage0_t)));
1510d043c564SKenneth D. Merry out:
1511d043c564SKenneth D. Merry 	free(page, M_MPT2);
1512d043c564SKenneth D. Merry 	if (cm)
1513d043c564SKenneth D. Merry 		mps_free_command(sc, cm);
1514d043c564SKenneth D. Merry 	return (error);
1515d043c564SKenneth D. Merry }
1516