xref: /freebsd/sys/dev/mpr/mpr_config.c (revision d9b3bba2f3022f1b577fb7a18c523c92551d8257)
1991554f2SKenneth D. Merry /*-
2a2c14879SStephen McConnell  * Copyright (c) 2011-2015 LSI Corp.
37a2a6a1aSStephen McConnell  * Copyright (c) 2013-2016 Avago Technologies
446b23587SKashyap D Desai  * Copyright 2000-2020 Broadcom Inc.
5991554f2SKenneth D. Merry  * All rights reserved.
6991554f2SKenneth D. Merry  *
7991554f2SKenneth D. Merry  * Redistribution and use in source and binary forms, with or without
8991554f2SKenneth D. Merry  * modification, are permitted provided that the following conditions
9991554f2SKenneth D. Merry  * are met:
10991554f2SKenneth D. Merry  * 1. Redistributions of source code must retain the above copyright
11991554f2SKenneth D. Merry  *    notice, this list of conditions and the following disclaimer.
12991554f2SKenneth D. Merry  * 2. Redistributions in binary form must reproduce the above copyright
13991554f2SKenneth D. Merry  *    notice, this list of conditions and the following disclaimer in the
14991554f2SKenneth D. Merry  *    documentation and/or other materials provided with the distribution.
15991554f2SKenneth D. Merry  *
16991554f2SKenneth D. Merry  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17991554f2SKenneth D. Merry  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18991554f2SKenneth D. Merry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19991554f2SKenneth D. Merry  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20991554f2SKenneth D. Merry  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21991554f2SKenneth D. Merry  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22991554f2SKenneth D. Merry  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23991554f2SKenneth D. Merry  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24991554f2SKenneth D. Merry  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25991554f2SKenneth D. Merry  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26991554f2SKenneth D. Merry  * SUCH DAMAGE.
27991554f2SKenneth D. Merry  *
2846b23587SKashyap D Desai  * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD
29991554f2SKenneth D. Merry  */
30991554f2SKenneth D. Merry 
31991554f2SKenneth D. Merry #include <sys/cdefs.h>
32991554f2SKenneth D. Merry /* TODO Move headers to mprvar */
33991554f2SKenneth D. Merry #include <sys/types.h>
34991554f2SKenneth D. Merry #include <sys/param.h>
35991554f2SKenneth D. Merry #include <sys/lock.h>
36991554f2SKenneth D. Merry #include <sys/mutex.h>
37991554f2SKenneth D. Merry #include <sys/systm.h>
38991554f2SKenneth D. Merry #include <sys/kernel.h>
39991554f2SKenneth D. Merry #include <sys/malloc.h>
40991554f2SKenneth D. Merry #include <sys/kthread.h>
41991554f2SKenneth D. Merry #include <sys/taskqueue.h>
42991554f2SKenneth D. Merry #include <sys/bus.h>
43991554f2SKenneth D. Merry #include <sys/endian.h>
44991554f2SKenneth D. Merry #include <sys/sysctl.h>
45991554f2SKenneth D. Merry #include <sys/eventhandler.h>
46991554f2SKenneth D. Merry #include <sys/uio.h>
47991554f2SKenneth D. Merry #include <machine/bus.h>
48991554f2SKenneth D. Merry #include <machine/resource.h>
49991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_type.h>
50991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2.h>
51991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_ioc.h>
52991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_sas.h>
5367feec50SStephen McConnell #include <dev/mpr/mpi/mpi2_pci.h>
54991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_cnfg.h>
55991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_init.h>
56991554f2SKenneth D. Merry #include <dev/mpr/mpi/mpi2_tool.h>
57991554f2SKenneth D. Merry #include <dev/mpr/mpr_ioctl.h>
58991554f2SKenneth D. Merry #include <dev/mpr/mprvar.h>
59991554f2SKenneth D. Merry 
60991554f2SKenneth D. Merry /**
61991554f2SKenneth D. Merry  * mpr_config_get_ioc_pg8 - obtain ioc page 8
62991554f2SKenneth D. Merry  * @sc: per adapter object
63991554f2SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
64991554f2SKenneth D. Merry  * @config_page: contents of the config page
65991554f2SKenneth D. Merry  * Context: sleep.
66991554f2SKenneth D. Merry  *
67991554f2SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
68991554f2SKenneth D. Merry  */
69991554f2SKenneth D. Merry int
mpr_config_get_ioc_pg8(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2IOCPage8_t * config_page)70991554f2SKenneth D. Merry mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
71991554f2SKenneth D. Merry     Mpi2IOCPage8_t *config_page)
72991554f2SKenneth D. Merry {
73991554f2SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
74991554f2SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply;
75991554f2SKenneth D. Merry 	struct mpr_command *cm;
76991554f2SKenneth D. Merry 	MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
77991554f2SKenneth D. Merry 	int error = 0;
78991554f2SKenneth D. Merry 	u16 ioc_status;
79991554f2SKenneth D. Merry 
80991554f2SKenneth D. Merry 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
81991554f2SKenneth D. Merry 
82991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
83991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
84991554f2SKenneth D. Merry 		    __LINE__);
85991554f2SKenneth D. Merry 		error = EBUSY;
86991554f2SKenneth D. Merry 		goto out;
87991554f2SKenneth D. Merry 	}
88991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
89991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
90991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
91991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
92991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
93991554f2SKenneth D. Merry 	request->Header.PageNumber = 8;
9467feec50SStephen McConnell 	request->Header.PageLength = request->Header.PageVersion = 0;
95991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
96991554f2SKenneth D. Merry 	cm->cm_data = NULL;
976d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
986d4ffcb4SKenneth D. Merry 	if (cm != NULL)
99991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
100991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
101991554f2SKenneth D. Merry 		/* FIXME */
102991554f2SKenneth D. Merry 		/*
103991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
104991554f2SKenneth D. Merry 		 * reset
105991554f2SKenneth D. Merry 		 */
106074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
107991554f2SKenneth D. Merry 		    __func__, error);
108991554f2SKenneth D. Merry 		error = ENXIO;
109991554f2SKenneth D. Merry 		goto out;
110991554f2SKenneth D. Merry 	}
111991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
112991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
113991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
114991554f2SKenneth D. Merry 		/* FIXME */
115991554f2SKenneth D. Merry 		/*
116991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
117991554f2SKenneth D. Merry 		 * reset
118991554f2SKenneth D. Merry 		 */
119991554f2SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
120991554f2SKenneth D. Merry 		    __func__, ioc_status);
121991554f2SKenneth D. Merry 		error = ENXIO;
122991554f2SKenneth D. Merry 		goto out;
123991554f2SKenneth D. Merry 	}
124991554f2SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
125991554f2SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
126991554f2SKenneth D. Merry 	 */
127991554f2SKenneth D. Merry 	mpr_free_command(sc, cm);
128991554f2SKenneth D. Merry 
129991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
130991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
131991554f2SKenneth D. Merry 		    __LINE__);
132991554f2SKenneth D. Merry 		error = EBUSY;
133991554f2SKenneth D. Merry 		goto out;
134991554f2SKenneth D. Merry 	}
135991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
136991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
137991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
138991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
139991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
140991554f2SKenneth D. Merry 	request->Header.PageNumber = 8;
14167feec50SStephen McConnell 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
142991554f2SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
14371900a79SAlfredo Dal'Ava Junior 	cm->cm_length = mpi_reply->Header.PageLength * 4;
144991554f2SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
145991554f2SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
146991554f2SKenneth D. Merry 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
147991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
148991554f2SKenneth D. Merry 	page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
149991554f2SKenneth D. Merry 	if (!page) {
150991554f2SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
151991554f2SKenneth D. Merry 		error = ENOMEM;
152991554f2SKenneth D. Merry 		goto out;
153991554f2SKenneth D. Merry 	}
154991554f2SKenneth D. Merry 	cm->cm_data = page;
155991554f2SKenneth D. Merry 
1566d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1576d4ffcb4SKenneth D. Merry 	if (cm != NULL)
158991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
159991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
160991554f2SKenneth D. Merry 		/* FIXME */
161991554f2SKenneth D. Merry 		/*
162991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
163991554f2SKenneth D. Merry 		 * reset
164991554f2SKenneth D. Merry 		 */
165074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
166991554f2SKenneth D. Merry 		    __func__, error);
167991554f2SKenneth D. Merry 		error = ENXIO;
168991554f2SKenneth D. Merry 		goto out;
169991554f2SKenneth D. Merry 	}
170991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
171991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
172991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
173991554f2SKenneth D. Merry 		/* FIXME */
174991554f2SKenneth D. Merry 		/*
175991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
176991554f2SKenneth D. Merry 		 * reset
177991554f2SKenneth D. Merry 		 */
178991554f2SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
179991554f2SKenneth D. Merry 		    __func__, ioc_status);
180991554f2SKenneth D. Merry 		error = ENXIO;
181991554f2SKenneth D. Merry 		goto out;
182991554f2SKenneth D. Merry 	}
183991554f2SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
184991554f2SKenneth D. Merry 
185991554f2SKenneth D. Merry out:
186991554f2SKenneth D. Merry 	free(page, M_MPR);
187991554f2SKenneth D. Merry 	if (cm)
188991554f2SKenneth D. Merry 		mpr_free_command(sc, cm);
189991554f2SKenneth D. Merry 	return (error);
190991554f2SKenneth D. Merry }
191991554f2SKenneth D. Merry 
192991554f2SKenneth D. Merry /**
193991554f2SKenneth D. Merry  * mpr_config_get_iounit_pg8 - obtain iounit page 8
194991554f2SKenneth D. Merry  * @sc: per adapter object
195991554f2SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
196991554f2SKenneth D. Merry  * @config_page: contents of the config page
197991554f2SKenneth D. Merry  * Context: sleep.
198991554f2SKenneth D. Merry  *
199991554f2SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
200991554f2SKenneth D. Merry  */
201991554f2SKenneth D. Merry int
mpr_config_get_iounit_pg8(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2IOUnitPage8_t * config_page)202991554f2SKenneth D. Merry mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
203991554f2SKenneth D. Merry     Mpi2IOUnitPage8_t *config_page)
204991554f2SKenneth D. Merry {
205991554f2SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
206991554f2SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply;
207991554f2SKenneth D. Merry 	struct mpr_command *cm;
208991554f2SKenneth D. Merry 	MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL;
209991554f2SKenneth D. Merry 	int error = 0;
210991554f2SKenneth D. Merry 	u16 ioc_status;
211991554f2SKenneth D. Merry 
212991554f2SKenneth D. Merry 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
213991554f2SKenneth D. Merry 
214991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
215991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
216991554f2SKenneth D. Merry 		    __LINE__);
217991554f2SKenneth D. Merry 		error = EBUSY;
218991554f2SKenneth D. Merry 		goto out;
219991554f2SKenneth D. Merry 	}
220991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
221991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
222991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
223991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
224991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
225991554f2SKenneth D. Merry 	request->Header.PageNumber = 8;
22667feec50SStephen McConnell 	request->Header.PageLength = request->Header.PageVersion = 0;
227991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
228991554f2SKenneth D. Merry 	cm->cm_data = NULL;
2296d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
2306d4ffcb4SKenneth D. Merry 	if (cm != NULL)
231991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
232991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
233991554f2SKenneth D. Merry 		/* FIXME */
234991554f2SKenneth D. Merry 		/*
235991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
236991554f2SKenneth D. Merry 		 * reset
237991554f2SKenneth D. Merry 		 */
238074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
239991554f2SKenneth D. Merry 		    __func__, error);
240991554f2SKenneth D. Merry 		error = ENXIO;
241991554f2SKenneth D. Merry 		goto out;
242991554f2SKenneth D. Merry 	}
243991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
244991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
245991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
246991554f2SKenneth D. Merry 		/* FIXME */
247991554f2SKenneth D. Merry 		/*
248991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
249991554f2SKenneth D. Merry 		 * reset
250991554f2SKenneth D. Merry 		 */
251991554f2SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
252991554f2SKenneth D. Merry 		    __func__, ioc_status);
253991554f2SKenneth D. Merry 		error = ENXIO;
254991554f2SKenneth D. Merry 		goto out;
255991554f2SKenneth D. Merry 	}
256991554f2SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
257991554f2SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
258991554f2SKenneth D. Merry 	 */
259991554f2SKenneth D. Merry 	mpr_free_command(sc, cm);
260991554f2SKenneth D. Merry 
261991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
262991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
263991554f2SKenneth D. Merry 		    __LINE__);
264991554f2SKenneth D. Merry 		error = EBUSY;
265991554f2SKenneth D. Merry 		goto out;
266991554f2SKenneth D. Merry 	}
267991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
268991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
269991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
270991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
271991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
272991554f2SKenneth D. Merry 	request->Header.PageNumber = 8;
27367feec50SStephen McConnell 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
274991554f2SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
27571900a79SAlfredo Dal'Ava Junior 	cm->cm_length = mpi_reply->Header.PageLength * 4;
276991554f2SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
277991554f2SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
278991554f2SKenneth D. Merry 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
279991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
280991554f2SKenneth D. Merry 	page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
281991554f2SKenneth D. Merry 	if (!page) {
282991554f2SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
283991554f2SKenneth D. Merry 		error = ENOMEM;
284991554f2SKenneth D. Merry 		goto out;
285991554f2SKenneth D. Merry 	}
286991554f2SKenneth D. Merry 	cm->cm_data = page;
287991554f2SKenneth D. Merry 
2886d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
2896d4ffcb4SKenneth D. Merry 	if (cm != NULL)
290991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
291991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
292991554f2SKenneth D. Merry 		/* FIXME */
293991554f2SKenneth D. Merry 		/*
294991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
295991554f2SKenneth D. Merry 		 * reset
296991554f2SKenneth D. Merry 		 */
297074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
298991554f2SKenneth D. Merry 		    __func__, error);
299991554f2SKenneth D. Merry 		error = ENXIO;
300991554f2SKenneth D. Merry 		goto out;
301991554f2SKenneth D. Merry 	}
302991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
303991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
304991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
305991554f2SKenneth D. Merry 		/* FIXME */
306991554f2SKenneth D. Merry 		/*
307991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
308991554f2SKenneth D. Merry 		 * reset
309991554f2SKenneth D. Merry 		 */
310991554f2SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
311991554f2SKenneth D. Merry 		    __func__, ioc_status);
312991554f2SKenneth D. Merry 		error = ENXIO;
313991554f2SKenneth D. Merry 		goto out;
314991554f2SKenneth D. Merry 	}
315991554f2SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length,
316991554f2SKenneth D. Merry 	    (sizeof(Mpi2IOUnitPage8_t))));
317991554f2SKenneth D. Merry 
318991554f2SKenneth D. Merry out:
319991554f2SKenneth D. Merry 	free(page, M_MPR);
320991554f2SKenneth D. Merry 	if (cm)
321991554f2SKenneth D. Merry 		mpr_free_command(sc, cm);
322991554f2SKenneth D. Merry 	return (error);
323991554f2SKenneth D. Merry }
324991554f2SKenneth D. Merry 
325991554f2SKenneth D. Merry /**
32689d1c21fSKashyap D Desai  * mpr_config_get_man_pg11 - obtain manufacturing page 11
32789d1c21fSKashyap D Desai  * @sc: per adapter object
32889d1c21fSKashyap D Desai  * @mpi_reply: reply mf payload returned from firmware
32989d1c21fSKashyap D Desai  * @config_page: contents of the config page
33089d1c21fSKashyap D Desai  * Context: sleep.
33189d1c21fSKashyap D Desai  *
33289d1c21fSKashyap D Desai  * Returns 0 for success, non-zero for failure.
33389d1c21fSKashyap D Desai  */
33489d1c21fSKashyap D Desai int
mpr_config_get_man_pg11(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2ManufacturingPage11_t * config_page)33589d1c21fSKashyap D Desai mpr_config_get_man_pg11(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
33689d1c21fSKashyap D Desai     Mpi2ManufacturingPage11_t *config_page)
33789d1c21fSKashyap D Desai {
33889d1c21fSKashyap D Desai 	MPI2_CONFIG_REQUEST *request;
33989d1c21fSKashyap D Desai 	MPI2_CONFIG_REPLY *reply;
34089d1c21fSKashyap D Desai 	struct mpr_command *cm;
34189d1c21fSKashyap D Desai 	MPI2_CONFIG_PAGE_MAN_11 *page = NULL;
34289d1c21fSKashyap D Desai 	int error = 0;
34389d1c21fSKashyap D Desai 	u16 ioc_status;
34489d1c21fSKashyap D Desai 
34589d1c21fSKashyap D Desai 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
34689d1c21fSKashyap D Desai 
34789d1c21fSKashyap D Desai 	if ((cm = mpr_alloc_command(sc)) == NULL) {
34889d1c21fSKashyap D Desai 		printf("%s: command alloc failed @ line %d\n", __func__,
34989d1c21fSKashyap D Desai 		    __LINE__);
35089d1c21fSKashyap D Desai 		error = EBUSY;
35189d1c21fSKashyap D Desai 		goto out;
35289d1c21fSKashyap D Desai 	}
35389d1c21fSKashyap D Desai 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
35489d1c21fSKashyap D Desai 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
35589d1c21fSKashyap D Desai 	request->Function = MPI2_FUNCTION_CONFIG;
35689d1c21fSKashyap D Desai 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
35789d1c21fSKashyap D Desai 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
35889d1c21fSKashyap D Desai 	request->Header.PageNumber = 11;
35989d1c21fSKashyap D Desai 	request->Header.PageLength = request->Header.PageVersion = 0;
36089d1c21fSKashyap D Desai 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
36189d1c21fSKashyap D Desai 	cm->cm_data = NULL;
36289d1c21fSKashyap D Desai 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
36389d1c21fSKashyap D Desai 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
36489d1c21fSKashyap D Desai 	if (error || (reply == NULL)) {
36589d1c21fSKashyap D Desai 		/* FIXME */
36689d1c21fSKashyap D Desai 		/*
36789d1c21fSKashyap D Desai 		 * If the request returns an error then we need to do a diag
36889d1c21fSKashyap D Desai 		 * reset
36989d1c21fSKashyap D Desai 		 */
370074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
37189d1c21fSKashyap D Desai 		    __func__, error);
37289d1c21fSKashyap D Desai 		error = ENXIO;
37389d1c21fSKashyap D Desai 		goto out;
37489d1c21fSKashyap D Desai 	}
37589d1c21fSKashyap D Desai 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
37689d1c21fSKashyap D Desai 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
37789d1c21fSKashyap D Desai 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
37889d1c21fSKashyap D Desai 		/* FIXME */
37989d1c21fSKashyap D Desai 		/*
38089d1c21fSKashyap D Desai 		 * If the request returns an error then we need to do a diag
38189d1c21fSKashyap D Desai 		 * reset
38289d1c21fSKashyap D Desai 		 */
38389d1c21fSKashyap D Desai 		printf("%s: header read with error; iocstatus = 0x%x\n",
38489d1c21fSKashyap D Desai 		    __func__, ioc_status);
38589d1c21fSKashyap D Desai 		error = ENXIO;
38689d1c21fSKashyap D Desai 		goto out;
38789d1c21fSKashyap D Desai 	}
38889d1c21fSKashyap D Desai 	/* We have to do free and alloc for the reply-free and reply-post
38989d1c21fSKashyap D Desai 	 * counters to match - Need to review the reply FIFO handling.
39089d1c21fSKashyap D Desai 	 */
39189d1c21fSKashyap D Desai 	mpr_free_command(sc, cm);
39289d1c21fSKashyap D Desai 
39389d1c21fSKashyap D Desai 	if ((cm = mpr_alloc_command(sc)) == NULL) {
39489d1c21fSKashyap D Desai 		printf("%s: command alloc failed @ line %d\n", __func__,
39589d1c21fSKashyap D Desai 		    __LINE__);
39689d1c21fSKashyap D Desai 		error = EBUSY;
39789d1c21fSKashyap D Desai 		goto out;
39889d1c21fSKashyap D Desai 	}
39989d1c21fSKashyap D Desai 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
40089d1c21fSKashyap D Desai 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
40189d1c21fSKashyap D Desai 	request->Function = MPI2_FUNCTION_CONFIG;
40289d1c21fSKashyap D Desai 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
40389d1c21fSKashyap D Desai 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
40489d1c21fSKashyap D Desai 	request->Header.PageNumber = 11;
40589d1c21fSKashyap D Desai 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
40689d1c21fSKashyap D Desai 	request->Header.PageLength = mpi_reply->Header.PageLength;
40771900a79SAlfredo Dal'Ava Junior 	cm->cm_length = mpi_reply->Header.PageLength * 4;
40889d1c21fSKashyap D Desai 	cm->cm_sge = &request->PageBufferSGE;
40989d1c21fSKashyap D Desai 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
41089d1c21fSKashyap D Desai 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
41189d1c21fSKashyap D Desai 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
41289d1c21fSKashyap D Desai 	page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
41389d1c21fSKashyap D Desai 	if (!page) {
41489d1c21fSKashyap D Desai 		printf("%s: page alloc failed\n", __func__);
41589d1c21fSKashyap D Desai 		error = ENOMEM;
41689d1c21fSKashyap D Desai 		goto out;
41789d1c21fSKashyap D Desai 	}
41889d1c21fSKashyap D Desai 	cm->cm_data = page;
41989d1c21fSKashyap D Desai 
42089d1c21fSKashyap D Desai 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
42189d1c21fSKashyap D Desai 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
42289d1c21fSKashyap D Desai 	if (error || (reply == NULL)) {
42389d1c21fSKashyap D Desai 		/* FIXME */
42489d1c21fSKashyap D Desai 		/*
42589d1c21fSKashyap D Desai 		 * If the request returns an error then we need to do a diag
42689d1c21fSKashyap D Desai 		 * reset
42789d1c21fSKashyap D Desai 		 */
428074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
42989d1c21fSKashyap D Desai 		    __func__, error);
43089d1c21fSKashyap D Desai 		error = ENXIO;
43189d1c21fSKashyap D Desai 		goto out;
43289d1c21fSKashyap D Desai 	}
43389d1c21fSKashyap D Desai 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
43489d1c21fSKashyap D Desai 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
43589d1c21fSKashyap D Desai 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
43689d1c21fSKashyap D Desai 		/* FIXME */
43789d1c21fSKashyap D Desai 		/*
43889d1c21fSKashyap D Desai 		 * If the request returns an error then we need to do a diag
43989d1c21fSKashyap D Desai 		 * reset
44089d1c21fSKashyap D Desai 		 */
44189d1c21fSKashyap D Desai 		printf("%s: page read with error; iocstatus = 0x%x\n",
44289d1c21fSKashyap D Desai 		    __func__, ioc_status);
44389d1c21fSKashyap D Desai 		error = ENXIO;
44489d1c21fSKashyap D Desai 		goto out;
44589d1c21fSKashyap D Desai 	}
44689d1c21fSKashyap D Desai 	bcopy(page, config_page, MIN(cm->cm_length,
44789d1c21fSKashyap D Desai 	    (sizeof(Mpi2ManufacturingPage11_t))));
44889d1c21fSKashyap D Desai 
44989d1c21fSKashyap D Desai out:
45089d1c21fSKashyap D Desai 	free(page, M_MPR);
45189d1c21fSKashyap D Desai 	if (cm)
45289d1c21fSKashyap D Desai 		mpr_free_command(sc, cm);
45389d1c21fSKashyap D Desai 	return (error);
45489d1c21fSKashyap D Desai }
45589d1c21fSKashyap D Desai 
45689d1c21fSKashyap D Desai /**
457991554f2SKenneth D. Merry  * mpr_base_static_config_pages - static start of day config pages.
458991554f2SKenneth D. Merry  * @sc: per adapter object
459991554f2SKenneth D. Merry  *
460991554f2SKenneth D. Merry  * Return nothing.
461991554f2SKenneth D. Merry  */
462991554f2SKenneth D. Merry void
mpr_base_static_config_pages(struct mpr_softc * sc)463991554f2SKenneth D. Merry mpr_base_static_config_pages(struct mpr_softc *sc)
464991554f2SKenneth D. Merry {
465991554f2SKenneth D. Merry 	Mpi2ConfigReply_t		mpi_reply;
46689d1c21fSKashyap D Desai 	Mpi2ManufacturingPage11_t	man_pg11;
46789d1c21fSKashyap D Desai 	int				retry, rc;
468991554f2SKenneth D. Merry 
469991554f2SKenneth D. Merry 	retry = 0;
470991554f2SKenneth D. Merry 	while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
471991554f2SKenneth D. Merry 		retry++;
472991554f2SKenneth D. Merry 		if (retry > 5) {
473991554f2SKenneth D. Merry 			/* We need to Handle this situation */
474991554f2SKenneth D. Merry 			/*FIXME*/
475991554f2SKenneth D. Merry 			break;
476991554f2SKenneth D. Merry 		}
477991554f2SKenneth D. Merry 	}
478991554f2SKenneth D. Merry 	retry = 0;
479991554f2SKenneth D. Merry 	while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) {
480991554f2SKenneth D. Merry 		retry++;
481991554f2SKenneth D. Merry 		if (retry > 5) {
482991554f2SKenneth D. Merry 			/* We need to Handle this situation */
483991554f2SKenneth D. Merry 			/*FIXME*/
484991554f2SKenneth D. Merry 			break;
485991554f2SKenneth D. Merry 		}
486991554f2SKenneth D. Merry 	}
48789d1c21fSKashyap D Desai 	retry = 0;
48889d1c21fSKashyap D Desai 	while ((rc = mpr_config_get_man_pg11(sc, &mpi_reply, &man_pg11))) {
48989d1c21fSKashyap D Desai 		retry++;
49089d1c21fSKashyap D Desai 		if (retry > 5) {
49189d1c21fSKashyap D Desai 			/* We need to Handle this situation */
49289d1c21fSKashyap D Desai 			/*FIXME*/
49389d1c21fSKashyap D Desai 			break;
49489d1c21fSKashyap D Desai 		}
49589d1c21fSKashyap D Desai 	}
49689d1c21fSKashyap D Desai 
49789d1c21fSKashyap D Desai 	if (!rc) {
49889d1c21fSKashyap D Desai 		sc->custom_nvme_tm_handling = (le16toh(man_pg11.AddlFlags2) &
49989d1c21fSKashyap D Desai 		    MPI2_MAN_PG11_ADDLFLAGS2_CUSTOM_TM_HANDLING_MASK);
50089d1c21fSKashyap D Desai 		sc->nvme_abort_timeout = man_pg11.NVMeAbortTO;
50189d1c21fSKashyap D Desai 
50289d1c21fSKashyap D Desai 		/* Minimum NVMe Abort timeout value should be 6 seconds &
50389d1c21fSKashyap D Desai 		 * maximum value should be 60 seconds.
50489d1c21fSKashyap D Desai 		 */
50589d1c21fSKashyap D Desai 		if (sc->nvme_abort_timeout < 6)
50689d1c21fSKashyap D Desai 			sc->nvme_abort_timeout = 6;
50789d1c21fSKashyap D Desai 		if (sc->nvme_abort_timeout > 60)
50889d1c21fSKashyap D Desai 			sc->nvme_abort_timeout = 60;
50989d1c21fSKashyap D Desai 	}
510991554f2SKenneth D. Merry }
511991554f2SKenneth D. Merry 
512991554f2SKenneth D. Merry /**
513991554f2SKenneth D. Merry  * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0
514991554f2SKenneth D. Merry  * @sc: per adapter object
515991554f2SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
516991554f2SKenneth D. Merry  * @config_page: contents of the config page
517991554f2SKenneth D. Merry  * @sz: size of buffer passed in config_page
518991554f2SKenneth D. Merry  * Context: sleep.
519991554f2SKenneth D. Merry  *
520991554f2SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
521991554f2SKenneth D. Merry  */
522991554f2SKenneth D. Merry int
mpr_config_get_dpm_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 sz)523991554f2SKenneth D. Merry mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
524991554f2SKenneth D. Merry     Mpi2DriverMappingPage0_t *config_page, u16 sz)
525991554f2SKenneth D. Merry {
526991554f2SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
527991554f2SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply;
528991554f2SKenneth D. Merry 	struct mpr_command *cm;
529991554f2SKenneth D. Merry 	Mpi2DriverMappingPage0_t *page = NULL;
530991554f2SKenneth D. Merry 	int error = 0;
531991554f2SKenneth D. Merry 	u16 ioc_status;
532991554f2SKenneth D. Merry 
533991554f2SKenneth D. Merry 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
534991554f2SKenneth D. Merry 
535991554f2SKenneth D. Merry 	memset(config_page, 0, sz);
536991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
537991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
538991554f2SKenneth D. Merry 		    __LINE__);
539991554f2SKenneth D. Merry 		error = EBUSY;
540991554f2SKenneth D. Merry 		goto out;
541991554f2SKenneth D. Merry 	}
542991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
543991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
544991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
545991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
546991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
547991554f2SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
548991554f2SKenneth D. Merry 	request->Header.PageNumber = 0;
54967feec50SStephen McConnell 	request->ExtPageLength = request->Header.PageVersion = 0;
550*d9b3bba2SRobert Wing 	request->PageAddress = htole32(sc->max_dpm_entries <<
551*d9b3bba2SRobert Wing 	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT);
552991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
553991554f2SKenneth D. Merry 	cm->cm_data = NULL;
5546d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
5556d4ffcb4SKenneth D. Merry 	if (cm != NULL)
556991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
557991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
558991554f2SKenneth D. Merry 		/* FIXME */
559991554f2SKenneth D. Merry 		/*
560991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
561991554f2SKenneth D. Merry 		 * reset
562991554f2SKenneth D. Merry 		 */
563074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
564991554f2SKenneth D. Merry 		    __func__, error);
565991554f2SKenneth D. Merry 		error = ENXIO;
566991554f2SKenneth D. Merry 		goto out;
567991554f2SKenneth D. Merry 	}
568991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
569991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
570991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
571991554f2SKenneth D. Merry 		/* FIXME */
572991554f2SKenneth D. Merry 		/*
573991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
574991554f2SKenneth D. Merry 		 * reset
575991554f2SKenneth D. Merry 		 */
576991554f2SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
577991554f2SKenneth D. Merry 		    __func__, ioc_status);
578991554f2SKenneth D. Merry 		error = ENXIO;
579991554f2SKenneth D. Merry 		goto out;
580991554f2SKenneth D. Merry 	}
581991554f2SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
582991554f2SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
583991554f2SKenneth D. Merry 	 */
584991554f2SKenneth D. Merry 	mpr_free_command(sc, cm);
585991554f2SKenneth D. Merry 
586991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
587991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
588991554f2SKenneth D. Merry 		    __LINE__);
589991554f2SKenneth D. Merry 		error = EBUSY;
590991554f2SKenneth D. Merry 		goto out;
591991554f2SKenneth D. Merry 	}
592991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
593991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
594991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
595991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
596991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
597991554f2SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
598991554f2SKenneth D. Merry 	request->Header.PageNumber = 0;
59967feec50SStephen McConnell 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
600*d9b3bba2SRobert Wing 	request->PageAddress = htole32(sc->max_dpm_entries <<
601*d9b3bba2SRobert Wing 	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT);
602991554f2SKenneth D. Merry 	request->ExtPageLength = mpi_reply->ExtPageLength;
603991554f2SKenneth D. Merry 	cm->cm_length = le16toh(request->ExtPageLength) * 4;
604991554f2SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
605991554f2SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
606991554f2SKenneth D. Merry 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
607991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
608991554f2SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT);
609991554f2SKenneth D. Merry 	if (!page) {
610991554f2SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
611991554f2SKenneth D. Merry 		error = ENOMEM;
612991554f2SKenneth D. Merry 		goto out;
613991554f2SKenneth D. Merry 	}
614991554f2SKenneth D. Merry 	cm->cm_data = page;
6156d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
6166d4ffcb4SKenneth D. Merry 	if (cm != NULL)
617991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
618991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
619991554f2SKenneth D. Merry 		/* FIXME */
620991554f2SKenneth D. Merry 		/*
621991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
622991554f2SKenneth D. Merry 		 * reset
623991554f2SKenneth D. Merry 		 */
624074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
625991554f2SKenneth D. Merry 		    __func__, error);
626991554f2SKenneth D. Merry 		error = ENXIO;
627991554f2SKenneth D. Merry 		goto out;
628991554f2SKenneth D. Merry 	}
629991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
630991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
631991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
632991554f2SKenneth D. Merry 		/* FIXME */
633991554f2SKenneth D. Merry 		/*
634991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
635991554f2SKenneth D. Merry 		 * reset
636991554f2SKenneth D. Merry 		 */
637991554f2SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
638991554f2SKenneth D. Merry 		    __func__, ioc_status);
639991554f2SKenneth D. Merry 		error = ENXIO;
640991554f2SKenneth D. Merry 		goto out;
641991554f2SKenneth D. Merry 	}
642991554f2SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length, sz));
643991554f2SKenneth D. Merry out:
644991554f2SKenneth D. Merry 	free(page, M_MPR);
645991554f2SKenneth D. Merry 	if (cm)
646991554f2SKenneth D. Merry 		mpr_free_command(sc, cm);
647991554f2SKenneth D. Merry 	return (error);
648991554f2SKenneth D. Merry }
649991554f2SKenneth D. Merry 
650991554f2SKenneth D. Merry /**
651991554f2SKenneth D. Merry  * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
652991554f2SKenneth D. Merry  * @sc: per adapter object
653991554f2SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
654991554f2SKenneth D. Merry  * @config_page: contents of the config page
655991554f2SKenneth D. Merry  * @entry_idx: entry index in DPM Page0 to be modified
656991554f2SKenneth D. Merry  * Context: sleep.
657991554f2SKenneth D. Merry  *
658991554f2SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
659991554f2SKenneth D. Merry  */
660991554f2SKenneth D. Merry 
mpr_config_set_dpm_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 entry_idx)661991554f2SKenneth D. Merry int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
662991554f2SKenneth D. Merry     Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
663991554f2SKenneth D. Merry {
664991554f2SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
665991554f2SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply;
666991554f2SKenneth D. Merry 	struct mpr_command *cm;
667991554f2SKenneth D. Merry 	MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
668991554f2SKenneth D. Merry 	int error = 0;
669991554f2SKenneth D. Merry 	u16 ioc_status;
670991554f2SKenneth D. Merry 
671991554f2SKenneth D. Merry 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
672991554f2SKenneth D. Merry 
673991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
674991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
675991554f2SKenneth D. Merry 		    __LINE__);
676991554f2SKenneth D. Merry 		error = EBUSY;
677991554f2SKenneth D. Merry 		goto out;
678991554f2SKenneth D. Merry 	}
679991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
680991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
681991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
682991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
683991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
684991554f2SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
685991554f2SKenneth D. Merry 	request->Header.PageNumber = 0;
68667feec50SStephen McConnell 	request->ExtPageLength = request->Header.PageVersion = 0;
687*d9b3bba2SRobert Wing 	request->PageAddress = htole32(
688*d9b3bba2SRobert Wing 		(1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT) | entry_idx);
689991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
690991554f2SKenneth D. Merry 	cm->cm_data = NULL;
6916d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
6926d4ffcb4SKenneth D. Merry 	if (cm != NULL)
693991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
694991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
695991554f2SKenneth D. Merry 		/* FIXME */
696991554f2SKenneth D. Merry 		/*
697991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
698991554f2SKenneth D. Merry 		 * reset
699991554f2SKenneth D. Merry 		 */
700074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
701991554f2SKenneth D. Merry 		    __func__, error);
702991554f2SKenneth D. Merry 		error = ENXIO;
703991554f2SKenneth D. Merry 		goto out;
704991554f2SKenneth D. Merry 	}
705991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
706991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
707991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
708991554f2SKenneth D. Merry 		/* FIXME */
709991554f2SKenneth D. Merry 		/*
710991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
711991554f2SKenneth D. Merry 		 * reset
712991554f2SKenneth D. Merry 		 */
713991554f2SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
714991554f2SKenneth D. Merry 		    __func__, ioc_status);
715991554f2SKenneth D. Merry 		error = ENXIO;
716991554f2SKenneth D. Merry 		goto out;
717991554f2SKenneth D. Merry 	}
718991554f2SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
719991554f2SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
720991554f2SKenneth D. Merry 	 */
721991554f2SKenneth D. Merry 	mpr_free_command(sc, cm);
722991554f2SKenneth D. Merry 
723991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
724991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
725991554f2SKenneth D. Merry 		    __LINE__);
726991554f2SKenneth D. Merry 		error = EBUSY;
727991554f2SKenneth D. Merry 		goto out;
728991554f2SKenneth D. Merry 	}
729991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
730991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
731991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
732991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
733991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
734991554f2SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
735991554f2SKenneth D. Merry 	request->Header.PageNumber = 0;
73667feec50SStephen McConnell 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
737991554f2SKenneth D. Merry 	request->ExtPageLength = mpi_reply->ExtPageLength;
738*d9b3bba2SRobert Wing 	request->PageAddress = htole32(
739*d9b3bba2SRobert Wing 		(1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT) | entry_idx);
740991554f2SKenneth D. Merry 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
741991554f2SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
742991554f2SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
743991554f2SKenneth D. Merry 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT;
744991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
745991554f2SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
746991554f2SKenneth D. Merry 	if (!page) {
747991554f2SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
748991554f2SKenneth D. Merry 		error = ENOMEM;
749991554f2SKenneth D. Merry 		goto out;
750991554f2SKenneth D. Merry 	}
751991554f2SKenneth D. Merry 	bcopy(config_page, page, MIN(cm->cm_length,
752991554f2SKenneth D. Merry 	    (sizeof(Mpi2DriverMappingPage0_t))));
753991554f2SKenneth D. Merry 	cm->cm_data = page;
7546d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
7556d4ffcb4SKenneth D. Merry 	if (cm != NULL)
756991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
757991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
758991554f2SKenneth D. Merry 		/* FIXME */
759991554f2SKenneth D. Merry 		/*
760991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
761991554f2SKenneth D. Merry 		 * reset
762991554f2SKenneth D. Merry 		 */
763074bed4fSAlexander Motin 		printf("%s: request to write page completed with error %d\n",
764991554f2SKenneth D. Merry 		    __func__, error);
765991554f2SKenneth D. Merry 		error = ENXIO;
766991554f2SKenneth D. Merry 		goto out;
767991554f2SKenneth D. Merry 	}
768991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
769991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
770991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
771991554f2SKenneth D. Merry 		/* FIXME */
772991554f2SKenneth D. Merry 		/*
773991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
774991554f2SKenneth D. Merry 		 * reset
775991554f2SKenneth D. Merry 		 */
776991554f2SKenneth D. Merry 		printf("%s: page written with error; iocstatus = 0x%x\n",
777991554f2SKenneth D. Merry 		    __func__, ioc_status);
778991554f2SKenneth D. Merry 		error = ENXIO;
779991554f2SKenneth D. Merry 		goto out;
780991554f2SKenneth D. Merry 	}
781991554f2SKenneth D. Merry out:
782991554f2SKenneth D. Merry 	free(page, M_MPR);
783991554f2SKenneth D. Merry 	if (cm)
784991554f2SKenneth D. Merry 		mpr_free_command(sc, cm);
785991554f2SKenneth D. Merry 	return (error);
786991554f2SKenneth D. Merry }
787991554f2SKenneth D. Merry 
788991554f2SKenneth D. Merry /**
789991554f2SKenneth D. Merry  * mpr_config_get_sas_device_pg0 - obtain sas device page 0
790991554f2SKenneth D. Merry  * @sc: per adapter object
791991554f2SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
792991554f2SKenneth D. Merry  * @config_page: contents of the config page
793991554f2SKenneth D. Merry  * @form: GET_NEXT_HANDLE or HANDLE
794991554f2SKenneth D. Merry  * @handle: device handle
795991554f2SKenneth D. Merry  * Context: sleep.
796991554f2SKenneth D. Merry  *
797991554f2SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
798991554f2SKenneth D. Merry  */
799991554f2SKenneth D. Merry int
mpr_config_get_sas_device_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2SasDevicePage0_t * config_page,u32 form,u16 handle)800991554f2SKenneth D. Merry mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
801991554f2SKenneth D. Merry     *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
802991554f2SKenneth D. Merry {
803991554f2SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
804991554f2SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply;
805991554f2SKenneth D. Merry 	struct mpr_command *cm;
806991554f2SKenneth D. Merry 	Mpi2SasDevicePage0_t *page = NULL;
807991554f2SKenneth D. Merry 	int error = 0;
808991554f2SKenneth D. Merry 	u16 ioc_status;
809991554f2SKenneth D. Merry 
810991554f2SKenneth D. Merry 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
811991554f2SKenneth D. Merry 
812991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
813991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
814991554f2SKenneth D. Merry 		    __LINE__);
815991554f2SKenneth D. Merry 		error = EBUSY;
816991554f2SKenneth D. Merry 		goto out;
817991554f2SKenneth D. Merry 	}
818991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
819991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
820991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
821991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
822991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
823991554f2SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
824991554f2SKenneth D. Merry 	request->Header.PageNumber = 0;
82567feec50SStephen McConnell 	request->ExtPageLength = request->Header.PageVersion = 0;
826991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
827991554f2SKenneth D. Merry 	cm->cm_data = NULL;
8286d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
8296d4ffcb4SKenneth D. Merry 	if (cm != NULL)
830991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
831991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
832991554f2SKenneth D. Merry 		/* FIXME */
833991554f2SKenneth D. Merry 		/*
834991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
835991554f2SKenneth D. Merry 		 * reset
836991554f2SKenneth D. Merry 		 */
837074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
838991554f2SKenneth D. Merry 		    __func__, error);
839991554f2SKenneth D. Merry 		error = ENXIO;
840991554f2SKenneth D. Merry 		goto out;
841991554f2SKenneth D. Merry 	}
842991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
843991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
844991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
845991554f2SKenneth D. Merry 		/* FIXME */
846991554f2SKenneth D. Merry 		/*
847991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
848991554f2SKenneth D. Merry 		 * reset
849991554f2SKenneth D. Merry 		 */
850991554f2SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
851991554f2SKenneth D. Merry 		    __func__, ioc_status);
852991554f2SKenneth D. Merry 		error = ENXIO;
853991554f2SKenneth D. Merry 		goto out;
854991554f2SKenneth D. Merry 	}
855991554f2SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
856991554f2SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
857991554f2SKenneth D. Merry 	 */
858991554f2SKenneth D. Merry 	mpr_free_command(sc, cm);
859991554f2SKenneth D. Merry 
860991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
861991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
862991554f2SKenneth D. Merry 		    __LINE__);
863991554f2SKenneth D. Merry 		error = EBUSY;
864991554f2SKenneth D. Merry 		goto out;
865991554f2SKenneth D. Merry 	}
866991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
867991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
868991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
869991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
870991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
871991554f2SKenneth D. Merry 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
872991554f2SKenneth D. Merry 	request->Header.PageNumber = 0;
87367feec50SStephen McConnell 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
874991554f2SKenneth D. Merry 	request->ExtPageLength = mpi_reply->ExtPageLength;
875991554f2SKenneth D. Merry 	request->PageAddress = htole32(form | handle);
876991554f2SKenneth D. Merry 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
877991554f2SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
878991554f2SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
879991554f2SKenneth D. Merry 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
880991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
881991554f2SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
882991554f2SKenneth D. Merry 	if (!page) {
883991554f2SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
884991554f2SKenneth D. Merry 		error = ENOMEM;
885991554f2SKenneth D. Merry 		goto out;
886991554f2SKenneth D. Merry 	}
887991554f2SKenneth D. Merry 	cm->cm_data = page;
888991554f2SKenneth D. Merry 
8896d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
8906d4ffcb4SKenneth D. Merry 	if (cm != NULL)
891991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
892991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
893991554f2SKenneth D. Merry 		/* FIXME */
894991554f2SKenneth D. Merry 		/*
895991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
896991554f2SKenneth D. Merry 		 * reset
897991554f2SKenneth D. Merry 		 */
898074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
899991554f2SKenneth D. Merry 		    __func__, error);
900991554f2SKenneth D. Merry 		error = ENXIO;
901991554f2SKenneth D. Merry 		goto out;
902991554f2SKenneth D. Merry 	}
903991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
904991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
905991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
906991554f2SKenneth D. Merry 		/* FIXME */
907991554f2SKenneth D. Merry 		/*
908991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
909991554f2SKenneth D. Merry 		 * reset
910991554f2SKenneth D. Merry 		 */
911991554f2SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
912991554f2SKenneth D. Merry 		    __func__, ioc_status);
913991554f2SKenneth D. Merry 		error = ENXIO;
914991554f2SKenneth D. Merry 		goto out;
915991554f2SKenneth D. Merry 	}
916991554f2SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length,
917991554f2SKenneth D. Merry 	    sizeof(Mpi2SasDevicePage0_t)));
918991554f2SKenneth D. Merry out:
919991554f2SKenneth D. Merry 	free(page, M_MPR);
920991554f2SKenneth D. Merry 	if (cm)
921991554f2SKenneth D. Merry 		mpr_free_command(sc, cm);
922991554f2SKenneth D. Merry 	return (error);
923991554f2SKenneth D. Merry }
924991554f2SKenneth D. Merry 
925991554f2SKenneth D. Merry /**
92667feec50SStephen McConnell  * mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0
92767feec50SStephen McConnell  * @sc: per adapter object
92867feec50SStephen McConnell  * @mpi_reply: reply mf payload returned from firmware
92967feec50SStephen McConnell  * @config_page: contents of the config page
93067feec50SStephen McConnell  * @form: GET_NEXT_HANDLE or HANDLE
93167feec50SStephen McConnell  * @handle: device handle
93267feec50SStephen McConnell  * Context: sleep.
93367feec50SStephen McConnell  *
93467feec50SStephen McConnell  * Returns 0 for success, non-zero for failure.
93567feec50SStephen McConnell  */
93667feec50SStephen McConnell int
mpr_config_get_pcie_device_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi26PCIeDevicePage0_t * config_page,u32 form,u16 handle)93767feec50SStephen McConnell mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
93867feec50SStephen McConnell     *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle)
93967feec50SStephen McConnell {
94067feec50SStephen McConnell 	MPI2_CONFIG_REQUEST *request;
94167feec50SStephen McConnell 	MPI2_CONFIG_REPLY *reply;
94267feec50SStephen McConnell 	struct mpr_command *cm;
94367feec50SStephen McConnell 	Mpi26PCIeDevicePage0_t *page = NULL;
94467feec50SStephen McConnell 	int error = 0;
94567feec50SStephen McConnell 	u16 ioc_status;
94667feec50SStephen McConnell 
94767feec50SStephen McConnell 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
94867feec50SStephen McConnell 
94967feec50SStephen McConnell 	if ((cm = mpr_alloc_command(sc)) == NULL) {
95067feec50SStephen McConnell 		printf("%s: command alloc failed @ line %d\n", __func__,
95167feec50SStephen McConnell 		    __LINE__);
95267feec50SStephen McConnell 		error = EBUSY;
95367feec50SStephen McConnell 		goto out;
95467feec50SStephen McConnell 	}
95567feec50SStephen McConnell 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
95667feec50SStephen McConnell 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
95767feec50SStephen McConnell 	request->Function = MPI2_FUNCTION_CONFIG;
95867feec50SStephen McConnell 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
95967feec50SStephen McConnell 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
96067feec50SStephen McConnell 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
96167feec50SStephen McConnell 	request->Header.PageNumber = 0;
96267feec50SStephen McConnell 	request->ExtPageLength = request->Header.PageVersion = 0;
96367feec50SStephen McConnell 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
96467feec50SStephen McConnell 	cm->cm_data = NULL;
9656d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
9666d4ffcb4SKenneth D. Merry 	if (cm != NULL)
96767feec50SStephen McConnell 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
96867feec50SStephen McConnell 	if (error || (reply == NULL)) {
96967feec50SStephen McConnell 		/* FIXME */
97067feec50SStephen McConnell 		/*
97167feec50SStephen McConnell 		 * If the request returns an error then we need to do a diag
97267feec50SStephen McConnell 		 * reset
97367feec50SStephen McConnell 		 */
974074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
97567feec50SStephen McConnell 		    __func__, error);
97667feec50SStephen McConnell 		error = ENXIO;
97767feec50SStephen McConnell 		goto out;
97867feec50SStephen McConnell 	}
97967feec50SStephen McConnell 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
98067feec50SStephen McConnell 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
98167feec50SStephen McConnell 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
98267feec50SStephen McConnell 		/* FIXME */
98367feec50SStephen McConnell 		/*
98467feec50SStephen McConnell 		 * If the request returns an error then we need to do a diag
98567feec50SStephen McConnell 		 * reset
98667feec50SStephen McConnell 		 */
98767feec50SStephen McConnell 		printf("%s: header read with error; iocstatus = 0x%x\n",
98867feec50SStephen McConnell 		    __func__, ioc_status);
98967feec50SStephen McConnell 		error = ENXIO;
99067feec50SStephen McConnell 		goto out;
99167feec50SStephen McConnell 	}
99267feec50SStephen McConnell 	/* We have to do free and alloc for the reply-free and reply-post
99367feec50SStephen McConnell 	 * counters to match - Need to review the reply FIFO handling.
99467feec50SStephen McConnell 	 */
99567feec50SStephen McConnell 	mpr_free_command(sc, cm);
99667feec50SStephen McConnell 
99767feec50SStephen McConnell 	if ((cm = mpr_alloc_command(sc)) == NULL) {
99867feec50SStephen McConnell 		printf("%s: command alloc failed @ line %d\n", __func__,
99967feec50SStephen McConnell 		    __LINE__);
100067feec50SStephen McConnell 		error = EBUSY;
100167feec50SStephen McConnell 		goto out;
100267feec50SStephen McConnell 	}
100367feec50SStephen McConnell 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
100467feec50SStephen McConnell 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
100567feec50SStephen McConnell 	request->Function = MPI2_FUNCTION_CONFIG;
100667feec50SStephen McConnell 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
100767feec50SStephen McConnell 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
100867feec50SStephen McConnell 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
100967feec50SStephen McConnell 	request->Header.PageNumber = 0;
101067feec50SStephen McConnell 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
101167feec50SStephen McConnell 	request->ExtPageLength = mpi_reply->ExtPageLength;
101267feec50SStephen McConnell 	request->PageAddress = htole32(form | handle);
101367feec50SStephen McConnell 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
101467feec50SStephen McConnell 	cm->cm_sge = &request->PageBufferSGE;
101567feec50SStephen McConnell 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
101667feec50SStephen McConnell 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
101767feec50SStephen McConnell 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
101867feec50SStephen McConnell 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
101967feec50SStephen McConnell 	if (!page) {
102067feec50SStephen McConnell 		printf("%s: page alloc failed\n", __func__);
102167feec50SStephen McConnell 		error = ENOMEM;
102267feec50SStephen McConnell 		goto out;
102367feec50SStephen McConnell 	}
102467feec50SStephen McConnell 	cm->cm_data = page;
102567feec50SStephen McConnell 
10266d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
10276d4ffcb4SKenneth D. Merry 	if (cm != NULL)
102867feec50SStephen McConnell 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
102967feec50SStephen McConnell 	if (error || (reply == NULL)) {
103067feec50SStephen McConnell 		/* FIXME */
103167feec50SStephen McConnell 		/*
103267feec50SStephen McConnell 		 * If the request returns an error then we need to do a diag
103367feec50SStephen McConnell 		 * reset
103467feec50SStephen McConnell 		 */
1035074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
103667feec50SStephen McConnell 		    __func__, error);
103767feec50SStephen McConnell 		error = ENXIO;
103867feec50SStephen McConnell 		goto out;
103967feec50SStephen McConnell 	}
104067feec50SStephen McConnell 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
104167feec50SStephen McConnell 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
104267feec50SStephen McConnell 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
104367feec50SStephen McConnell 		/* FIXME */
104467feec50SStephen McConnell 		/*
104567feec50SStephen McConnell 		 * If the request returns an error then we need to do a diag
104667feec50SStephen McConnell 		 * reset
104767feec50SStephen McConnell 		 */
104867feec50SStephen McConnell 		printf("%s: page read with error; iocstatus = 0x%x\n",
104967feec50SStephen McConnell 		    __func__, ioc_status);
105067feec50SStephen McConnell 		error = ENXIO;
105167feec50SStephen McConnell 		goto out;
105267feec50SStephen McConnell 	}
105367feec50SStephen McConnell 	bcopy(page, config_page, MIN(cm->cm_length,
105467feec50SStephen McConnell 	    sizeof(Mpi26PCIeDevicePage0_t)));
105567feec50SStephen McConnell out:
105667feec50SStephen McConnell 	free(page, M_MPR);
105767feec50SStephen McConnell 	if (cm)
105867feec50SStephen McConnell 		mpr_free_command(sc, cm);
105967feec50SStephen McConnell 	return (error);
106067feec50SStephen McConnell }
106167feec50SStephen McConnell 
106267feec50SStephen McConnell /**
106367feec50SStephen McConnell  * mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2
106467feec50SStephen McConnell  * @sc: per adapter object
106567feec50SStephen McConnell  * @mpi_reply: reply mf payload returned from firmware
106667feec50SStephen McConnell  * @config_page: contents of the config page
106767feec50SStephen McConnell  * @form: GET_NEXT_HANDLE or HANDLE
106867feec50SStephen McConnell  * @handle: device handle
106967feec50SStephen McConnell  * Context: sleep.
107067feec50SStephen McConnell  *
107167feec50SStephen McConnell  * Returns 0 for success, non-zero for failure.
107267feec50SStephen McConnell  */
107367feec50SStephen McConnell int
mpr_config_get_pcie_device_pg2(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi26PCIeDevicePage2_t * config_page,u32 form,u16 handle)107467feec50SStephen McConnell mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t
107567feec50SStephen McConnell     *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle)
107667feec50SStephen McConnell {
107767feec50SStephen McConnell 	MPI2_CONFIG_REQUEST *request;
107867feec50SStephen McConnell 	MPI2_CONFIG_REPLY *reply;
107967feec50SStephen McConnell 	struct mpr_command *cm;
108067feec50SStephen McConnell 	Mpi26PCIeDevicePage2_t *page = NULL;
108167feec50SStephen McConnell 	int error = 0;
108267feec50SStephen McConnell 	u16 ioc_status;
108367feec50SStephen McConnell 
108467feec50SStephen McConnell 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
108567feec50SStephen McConnell 
108667feec50SStephen McConnell 	if ((cm = mpr_alloc_command(sc)) == NULL) {
108767feec50SStephen McConnell 		printf("%s: command alloc failed @ line %d\n", __func__,
108867feec50SStephen McConnell 		    __LINE__);
108967feec50SStephen McConnell 		error = EBUSY;
109067feec50SStephen McConnell 		goto out;
109167feec50SStephen McConnell 	}
109267feec50SStephen McConnell 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
109367feec50SStephen McConnell 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
109467feec50SStephen McConnell 	request->Function = MPI2_FUNCTION_CONFIG;
109567feec50SStephen McConnell 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
109667feec50SStephen McConnell 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
109767feec50SStephen McConnell 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
109867feec50SStephen McConnell 	request->Header.PageNumber = 2;
109967feec50SStephen McConnell 	request->ExtPageLength = request->Header.PageVersion = 0;
110067feec50SStephen McConnell 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
110167feec50SStephen McConnell 	cm->cm_data = NULL;
11026d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
11036d4ffcb4SKenneth D. Merry 	if (cm != NULL)
110467feec50SStephen McConnell 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
110567feec50SStephen McConnell 	if (error || (reply == NULL)) {
110667feec50SStephen McConnell 		/* FIXME */
110767feec50SStephen McConnell 		/*
110867feec50SStephen McConnell 		 * If the request returns an error then we need to do a diag
110967feec50SStephen McConnell 		 * reset
111067feec50SStephen McConnell 		 */
1111074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
111267feec50SStephen McConnell 		    __func__, error);
111367feec50SStephen McConnell 		error = ENXIO;
111467feec50SStephen McConnell 		goto out;
111567feec50SStephen McConnell 	}
111667feec50SStephen McConnell 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
111767feec50SStephen McConnell 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
111867feec50SStephen McConnell 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
111967feec50SStephen McConnell 		/* FIXME */
112067feec50SStephen McConnell 		/*
112167feec50SStephen McConnell 		 * If the request returns an error then we need to do a diag
112267feec50SStephen McConnell 		 * reset
112367feec50SStephen McConnell 		 */
112467feec50SStephen McConnell 		printf("%s: header read with error; iocstatus = 0x%x\n",
112567feec50SStephen McConnell 		    __func__, ioc_status);
112667feec50SStephen McConnell 		error = ENXIO;
112767feec50SStephen McConnell 		goto out;
112867feec50SStephen McConnell 	}
112967feec50SStephen McConnell 	/* We have to do free and alloc for the reply-free and reply-post
113067feec50SStephen McConnell 	 * counters to match - Need to review the reply FIFO handling.
113167feec50SStephen McConnell 	 */
113267feec50SStephen McConnell 	mpr_free_command(sc, cm);
113367feec50SStephen McConnell 
113467feec50SStephen McConnell 	if ((cm = mpr_alloc_command(sc)) == NULL) {
113567feec50SStephen McConnell 		printf("%s: command alloc failed @ line %d\n", __func__,
113667feec50SStephen McConnell 		    __LINE__);
113767feec50SStephen McConnell 		error = EBUSY;
113867feec50SStephen McConnell 		goto out;
113967feec50SStephen McConnell 	}
114067feec50SStephen McConnell 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
114167feec50SStephen McConnell 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
114267feec50SStephen McConnell 	request->Function = MPI2_FUNCTION_CONFIG;
114367feec50SStephen McConnell 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
114467feec50SStephen McConnell 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
114567feec50SStephen McConnell 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
114667feec50SStephen McConnell 	request->Header.PageNumber = 2;
114767feec50SStephen McConnell 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
114867feec50SStephen McConnell 	request->ExtPageLength = mpi_reply->ExtPageLength;
114967feec50SStephen McConnell 	request->PageAddress = htole32(form | handle);
115067feec50SStephen McConnell 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
115167feec50SStephen McConnell 	cm->cm_sge = &request->PageBufferSGE;
115267feec50SStephen McConnell 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
115367feec50SStephen McConnell 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
115467feec50SStephen McConnell 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
115567feec50SStephen McConnell 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
115667feec50SStephen McConnell 	if (!page) {
115767feec50SStephen McConnell 		printf("%s: page alloc failed\n", __func__);
115867feec50SStephen McConnell 		error = ENOMEM;
115967feec50SStephen McConnell 		goto out;
116067feec50SStephen McConnell 	}
116167feec50SStephen McConnell 	cm->cm_data = page;
116267feec50SStephen McConnell 
11636d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
11646d4ffcb4SKenneth D. Merry 	if (cm != NULL)
116567feec50SStephen McConnell 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
116667feec50SStephen McConnell 	if (error || (reply == NULL)) {
116767feec50SStephen McConnell 		/* FIXME */
116867feec50SStephen McConnell 		/*
116967feec50SStephen McConnell 		 * If the request returns an error then we need to do a diag
117067feec50SStephen McConnell 		 * reset
117167feec50SStephen McConnell 		 */
1172074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
117367feec50SStephen McConnell 		    __func__, error);
117467feec50SStephen McConnell 		error = ENXIO;
117567feec50SStephen McConnell 		goto out;
117667feec50SStephen McConnell 	}
117767feec50SStephen McConnell 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
117867feec50SStephen McConnell 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
117967feec50SStephen McConnell 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
118067feec50SStephen McConnell 		/* FIXME */
118167feec50SStephen McConnell 		/*
118267feec50SStephen McConnell 		 * If the request returns an error then we need to do a diag
118367feec50SStephen McConnell 		 * reset
118467feec50SStephen McConnell 		 */
118567feec50SStephen McConnell 		printf("%s: page read with error; iocstatus = 0x%x\n",
118667feec50SStephen McConnell 		    __func__, ioc_status);
118767feec50SStephen McConnell 		error = ENXIO;
118867feec50SStephen McConnell 		goto out;
118967feec50SStephen McConnell 	}
119067feec50SStephen McConnell 	bcopy(page, config_page, MIN(cm->cm_length,
119167feec50SStephen McConnell 	    sizeof(Mpi26PCIeDevicePage2_t)));
119267feec50SStephen McConnell out:
119367feec50SStephen McConnell 	free(page, M_MPR);
119467feec50SStephen McConnell 	if (cm)
119567feec50SStephen McConnell 		mpr_free_command(sc, cm);
119667feec50SStephen McConnell 	return (error);
119767feec50SStephen McConnell }
119867feec50SStephen McConnell 
119967feec50SStephen McConnell /**
1200991554f2SKenneth D. Merry  * mpr_config_get_bios_pg3 - obtain BIOS page 3
1201991554f2SKenneth D. Merry  * @sc: per adapter object
1202991554f2SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
1203991554f2SKenneth D. Merry  * @config_page: contents of the config page
1204991554f2SKenneth D. Merry  * Context: sleep.
1205991554f2SKenneth D. Merry  *
1206991554f2SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
1207991554f2SKenneth D. Merry  */
1208991554f2SKenneth D. Merry int
mpr_config_get_bios_pg3(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2BiosPage3_t * config_page)1209991554f2SKenneth D. Merry mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1210991554f2SKenneth D. Merry     Mpi2BiosPage3_t *config_page)
1211991554f2SKenneth D. Merry {
1212991554f2SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
1213991554f2SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply;
1214991554f2SKenneth D. Merry 	struct mpr_command *cm;
1215991554f2SKenneth D. Merry 	Mpi2BiosPage3_t *page = NULL;
1216991554f2SKenneth D. Merry 	int error = 0;
1217991554f2SKenneth D. Merry 	u16 ioc_status;
1218991554f2SKenneth D. Merry 
1219991554f2SKenneth D. Merry 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1220991554f2SKenneth D. Merry 
1221991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1222991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1223991554f2SKenneth D. Merry 		    __LINE__);
1224991554f2SKenneth D. Merry 		error = EBUSY;
1225991554f2SKenneth D. Merry 		goto out;
1226991554f2SKenneth D. Merry 	}
1227991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1228991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1229991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1230991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1231991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1232991554f2SKenneth D. Merry 	request->Header.PageNumber = 3;
123367feec50SStephen McConnell 	request->Header.PageLength = request->Header.PageVersion = 0;
1234991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1235991554f2SKenneth D. Merry 	cm->cm_data = NULL;
12366d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
12376d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1238991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1239991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
1240991554f2SKenneth D. Merry 		/* FIXME */
1241991554f2SKenneth D. Merry 		/*
1242991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1243991554f2SKenneth D. Merry 		 * reset
1244991554f2SKenneth D. Merry 		 */
1245074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
1246991554f2SKenneth D. Merry 		    __func__, error);
1247991554f2SKenneth D. Merry 		error = ENXIO;
1248991554f2SKenneth D. Merry 		goto out;
1249991554f2SKenneth D. Merry 	}
1250991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1251991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1252991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1253991554f2SKenneth D. Merry 		/* FIXME */
1254991554f2SKenneth D. Merry 		/*
1255991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1256991554f2SKenneth D. Merry 		 * reset
1257991554f2SKenneth D. Merry 		 */
1258991554f2SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
1259991554f2SKenneth D. Merry 		    __func__, ioc_status);
1260991554f2SKenneth D. Merry 		error = ENXIO;
1261991554f2SKenneth D. Merry 		goto out;
1262991554f2SKenneth D. Merry 	}
1263991554f2SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
1264991554f2SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
1265991554f2SKenneth D. Merry 	 */
1266991554f2SKenneth D. Merry 	mpr_free_command(sc, cm);
1267991554f2SKenneth D. Merry 
1268991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1269991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1270991554f2SKenneth D. Merry 		    __LINE__);
1271991554f2SKenneth D. Merry 		error = EBUSY;
1272991554f2SKenneth D. Merry 		goto out;
1273991554f2SKenneth D. Merry 	}
1274991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1275991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1276991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1277991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1278991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1279991554f2SKenneth D. Merry 	request->Header.PageNumber = 3;
128067feec50SStephen McConnell 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1281991554f2SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
128271900a79SAlfredo Dal'Ava Junior 	cm->cm_length = mpi_reply->Header.PageLength * 4;
1283991554f2SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
1284991554f2SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1285991554f2SKenneth D. Merry 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1286991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1287991554f2SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1288991554f2SKenneth D. Merry 	if (!page) {
1289991554f2SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
1290991554f2SKenneth D. Merry 		error = ENOMEM;
1291991554f2SKenneth D. Merry 		goto out;
1292991554f2SKenneth D. Merry 	}
1293991554f2SKenneth D. Merry 	cm->cm_data = page;
1294991554f2SKenneth D. Merry 
12956d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
12966d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1297991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1298991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
1299991554f2SKenneth D. Merry 		/* FIXME */
1300991554f2SKenneth D. Merry 		/*
1301991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1302991554f2SKenneth D. Merry 		 * reset
1303991554f2SKenneth D. Merry 		 */
1304074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
1305991554f2SKenneth D. Merry 		    __func__, error);
1306991554f2SKenneth D. Merry 		error = ENXIO;
1307991554f2SKenneth D. Merry 		goto out;
1308991554f2SKenneth D. Merry 	}
1309991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1310991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1311991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1312991554f2SKenneth D. Merry 		/* FIXME */
1313991554f2SKenneth D. Merry 		/*
1314991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1315991554f2SKenneth D. Merry 		 * reset
1316991554f2SKenneth D. Merry 		 */
1317991554f2SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
1318991554f2SKenneth D. Merry 		    __func__, ioc_status);
1319991554f2SKenneth D. Merry 		error = ENXIO;
1320991554f2SKenneth D. Merry 		goto out;
1321991554f2SKenneth D. Merry 	}
1322991554f2SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1323991554f2SKenneth D. Merry out:
1324991554f2SKenneth D. Merry 	free(page, M_MPR);
1325991554f2SKenneth D. Merry 	if (cm)
1326991554f2SKenneth D. Merry 		mpr_free_command(sc, cm);
1327991554f2SKenneth D. Merry 	return (error);
1328991554f2SKenneth D. Merry }
1329991554f2SKenneth D. Merry 
1330991554f2SKenneth D. Merry /**
1331991554f2SKenneth D. Merry  * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0
1332991554f2SKenneth D. Merry  * @sc: per adapter object
1333991554f2SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
1334991554f2SKenneth D. Merry  * @config_page: contents of the config page
1335991554f2SKenneth D. Merry  * @page_address: form and handle value used to get page
1336991554f2SKenneth D. Merry  * Context: sleep.
1337991554f2SKenneth D. Merry  *
1338991554f2SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
1339991554f2SKenneth D. Merry  */
1340991554f2SKenneth D. Merry int
mpr_config_get_raid_volume_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage0_t * config_page,u32 page_address)1341991554f2SKenneth D. Merry mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
1342991554f2SKenneth D. Merry     *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1343991554f2SKenneth D. Merry {
1344991554f2SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
13456d4ffcb4SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply = NULL;
1346991554f2SKenneth D. Merry 	struct mpr_command *cm;
1347991554f2SKenneth D. Merry 	Mpi2RaidVolPage0_t *page = NULL;
1348991554f2SKenneth D. Merry 	int error = 0;
1349991554f2SKenneth D. Merry 	u16 ioc_status;
1350991554f2SKenneth D. Merry 
1351991554f2SKenneth D. Merry 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1352991554f2SKenneth D. Merry 
1353991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1354991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1355991554f2SKenneth D. Merry 		    __LINE__);
1356991554f2SKenneth D. Merry 		error = EBUSY;
1357991554f2SKenneth D. Merry 		goto out;
1358991554f2SKenneth D. Merry 	}
1359991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1360991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1361991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1362991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1363991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1364991554f2SKenneth D. Merry 	request->Header.PageNumber = 0;
136567feec50SStephen McConnell 	request->Header.PageLength = request->Header.PageVersion = 0;
1366991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1367991554f2SKenneth D. Merry 	cm->cm_data = NULL;
1368991554f2SKenneth D. Merry 
1369991554f2SKenneth D. Merry 	/*
1370991554f2SKenneth D. Merry 	 * This page must be polled because the IOC isn't ready yet when this
1371991554f2SKenneth D. Merry 	 * page is needed.
1372991554f2SKenneth D. Merry 	 */
13736d4ffcb4SKenneth D. Merry 	error = mpr_request_polled(sc, &cm);
13746d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1375991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1376991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
1377991554f2SKenneth D. Merry 		/* FIXME */
1378991554f2SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1379074bed4fSAlexander Motin 		printf("%s: poll for header completed with error %d\n",
1380991554f2SKenneth D. Merry 		    __func__, error);
1381991554f2SKenneth D. Merry 		error = ENXIO;
1382991554f2SKenneth D. Merry 		goto out;
1383991554f2SKenneth D. Merry 	}
1384991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1385991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1386991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1387991554f2SKenneth D. Merry 		/* FIXME */
1388991554f2SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1389991554f2SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
1390991554f2SKenneth D. Merry 		    __func__, ioc_status);
1391991554f2SKenneth D. Merry 		error = ENXIO;
1392991554f2SKenneth D. Merry 		goto out;
1393991554f2SKenneth D. Merry 	}
1394991554f2SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
1395991554f2SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
1396991554f2SKenneth D. Merry 	 */
1397991554f2SKenneth D. Merry 	mpr_free_command(sc, cm);
1398991554f2SKenneth D. Merry 
1399991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1400991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1401991554f2SKenneth D. Merry 		    __LINE__);
1402991554f2SKenneth D. Merry 		error = EBUSY;
1403991554f2SKenneth D. Merry 		goto out;
1404991554f2SKenneth D. Merry 	}
1405991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1406991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1407991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1408991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1409991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1410991554f2SKenneth D. Merry 	request->Header.PageNumber = 0;
1411991554f2SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
1412991554f2SKenneth D. Merry 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1413991554f2SKenneth D. Merry 	request->PageAddress = page_address;
141471900a79SAlfredo Dal'Ava Junior 	cm->cm_length = mpi_reply->Header.PageLength * 4;
1415991554f2SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
1416991554f2SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1417991554f2SKenneth D. Merry 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1418991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1419991554f2SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1420991554f2SKenneth D. Merry 	if (!page) {
1421991554f2SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
1422991554f2SKenneth D. Merry 		error = ENOMEM;
1423991554f2SKenneth D. Merry 		goto out;
1424991554f2SKenneth D. Merry 	}
1425991554f2SKenneth D. Merry 	cm->cm_data = page;
1426991554f2SKenneth D. Merry 
1427991554f2SKenneth D. Merry 	/*
1428991554f2SKenneth D. Merry 	 * This page must be polled because the IOC isn't ready yet when this
1429991554f2SKenneth D. Merry 	 * page is needed.
1430991554f2SKenneth D. Merry 	 */
14316d4ffcb4SKenneth D. Merry 	error = mpr_request_polled(sc, &cm);
14326d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1433991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1434991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
1435991554f2SKenneth D. Merry 		/* FIXME */
1436991554f2SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1437074bed4fSAlexander Motin 		printf("%s: poll for page completed with error %d\n",
1438991554f2SKenneth D. Merry 		    __func__, error);
1439991554f2SKenneth D. Merry 		error = ENXIO;
1440991554f2SKenneth D. Merry 		goto out;
1441991554f2SKenneth D. Merry 	}
1442991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1443991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1444991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1445991554f2SKenneth D. Merry 		/* FIXME */
1446991554f2SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1447991554f2SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
1448991554f2SKenneth D. Merry 		    __func__, ioc_status);
1449991554f2SKenneth D. Merry 		error = ENXIO;
1450991554f2SKenneth D. Merry 		goto out;
1451991554f2SKenneth D. Merry 	}
1452991554f2SKenneth D. Merry 	bcopy(page, config_page, cm->cm_length);
1453991554f2SKenneth D. Merry out:
1454991554f2SKenneth D. Merry 	free(page, M_MPR);
1455991554f2SKenneth D. Merry 	if (cm)
1456991554f2SKenneth D. Merry 		mpr_free_command(sc, cm);
1457991554f2SKenneth D. Merry 	return (error);
1458991554f2SKenneth D. Merry }
1459991554f2SKenneth D. Merry 
1460991554f2SKenneth D. Merry /**
1461991554f2SKenneth D. Merry  * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1
1462991554f2SKenneth D. Merry  * @sc: per adapter object
1463991554f2SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
1464991554f2SKenneth D. Merry  * @config_page: contents of the config page
1465991554f2SKenneth D. Merry  * @form: GET_NEXT_HANDLE or HANDLE
1466991554f2SKenneth D. Merry  * @handle: volume handle
1467991554f2SKenneth D. Merry  * Context: sleep.
1468991554f2SKenneth D. Merry  *
1469991554f2SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
1470991554f2SKenneth D. Merry  */
1471991554f2SKenneth D. Merry int
mpr_config_get_raid_volume_pg1(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage1_t * config_page,u32 form,u16 handle)1472991554f2SKenneth D. Merry mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t
1473991554f2SKenneth D. Merry     *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1474991554f2SKenneth D. Merry {
1475991554f2SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
1476991554f2SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply;
1477991554f2SKenneth D. Merry 	struct mpr_command *cm;
1478991554f2SKenneth D. Merry 	Mpi2RaidVolPage1_t *page = NULL;
1479991554f2SKenneth D. Merry 	int error = 0;
1480991554f2SKenneth D. Merry 	u16 ioc_status;
1481991554f2SKenneth D. Merry 
1482991554f2SKenneth D. Merry 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1483991554f2SKenneth D. Merry 
1484991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1485991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1486991554f2SKenneth D. Merry 		    __LINE__);
1487991554f2SKenneth D. Merry 		error = EBUSY;
1488991554f2SKenneth D. Merry 		goto out;
1489991554f2SKenneth D. Merry 	}
1490991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1491991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1492991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1493991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1494991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1495991554f2SKenneth D. Merry 	request->Header.PageNumber = 1;
149667feec50SStephen McConnell 	request->Header.PageLength = request->Header.PageVersion = 0;
1497991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1498991554f2SKenneth D. Merry 	cm->cm_data = NULL;
14996d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
15006d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1501991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1502991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
1503991554f2SKenneth D. Merry 		/* FIXME */
1504991554f2SKenneth D. Merry 		/*
1505991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1506991554f2SKenneth D. Merry 		 * reset
1507991554f2SKenneth D. Merry 		 */
1508074bed4fSAlexander Motin 		printf("%s: request for header completed with error %d\n",
1509991554f2SKenneth D. Merry 		    __func__, error);
1510991554f2SKenneth D. Merry 		error = ENXIO;
1511991554f2SKenneth D. Merry 		goto out;
1512991554f2SKenneth D. Merry 	}
1513991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1514991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1515991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1516991554f2SKenneth D. Merry 		/* FIXME */
1517991554f2SKenneth D. Merry 		/*
1518991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1519991554f2SKenneth D. Merry 		 * reset
1520991554f2SKenneth D. Merry 		 */
1521991554f2SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
1522991554f2SKenneth D. Merry 		    __func__, ioc_status);
1523991554f2SKenneth D. Merry 		error = ENXIO;
1524991554f2SKenneth D. Merry 		goto out;
1525991554f2SKenneth D. Merry 	}
1526991554f2SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
1527991554f2SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
1528991554f2SKenneth D. Merry 	 */
1529991554f2SKenneth D. Merry 	mpr_free_command(sc, cm);
1530991554f2SKenneth D. Merry 
1531991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1532991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1533991554f2SKenneth D. Merry 		    __LINE__);
1534991554f2SKenneth D. Merry 		error = EBUSY;
1535991554f2SKenneth D. Merry 		goto out;
1536991554f2SKenneth D. Merry 	}
1537991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1538991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1539991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1540991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1541991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1542991554f2SKenneth D. Merry 	request->Header.PageNumber = 1;
1543991554f2SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
1544991554f2SKenneth D. Merry 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1545991554f2SKenneth D. Merry 	request->PageAddress = htole32(form | handle);
154671900a79SAlfredo Dal'Ava Junior 	cm->cm_length = mpi_reply->Header.PageLength * 4;
1547991554f2SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
1548991554f2SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1549991554f2SKenneth D. Merry 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1550991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1551991554f2SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1552991554f2SKenneth D. Merry 	if (!page) {
1553991554f2SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
1554991554f2SKenneth D. Merry 		error = ENOMEM;
1555991554f2SKenneth D. Merry 		goto out;
1556991554f2SKenneth D. Merry 	}
1557991554f2SKenneth D. Merry 	cm->cm_data = page;
1558991554f2SKenneth D. Merry 
15596d4ffcb4SKenneth D. Merry 	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
15606d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1561991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1562991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
1563991554f2SKenneth D. Merry 		/* FIXME */
1564991554f2SKenneth D. Merry 		/*
1565991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1566991554f2SKenneth D. Merry 		 * reset
1567991554f2SKenneth D. Merry 		 */
1568074bed4fSAlexander Motin 		printf("%s: request for page completed with error %d\n",
1569991554f2SKenneth D. Merry 		    __func__, error);
1570991554f2SKenneth D. Merry 		error = ENXIO;
1571991554f2SKenneth D. Merry 		goto out;
1572991554f2SKenneth D. Merry 	}
1573991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1574991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1575991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1576991554f2SKenneth D. Merry 		/* FIXME */
1577991554f2SKenneth D. Merry 		/*
1578991554f2SKenneth D. Merry 		 * If the request returns an error then we need to do a diag
1579991554f2SKenneth D. Merry 		 * reset
1580991554f2SKenneth D. Merry 		 */
1581991554f2SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
1582991554f2SKenneth D. Merry 		    __func__, ioc_status);
1583991554f2SKenneth D. Merry 		error = ENXIO;
1584991554f2SKenneth D. Merry 		goto out;
1585991554f2SKenneth D. Merry 	}
1586991554f2SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length,
1587991554f2SKenneth D. Merry 	    sizeof(Mpi2RaidVolPage1_t)));
1588991554f2SKenneth D. Merry out:
1589991554f2SKenneth D. Merry 	free(page, M_MPR);
1590991554f2SKenneth D. Merry 	if (cm)
1591991554f2SKenneth D. Merry 		mpr_free_command(sc, cm);
1592991554f2SKenneth D. Merry 	return (error);
1593991554f2SKenneth D. Merry }
1594991554f2SKenneth D. Merry 
1595991554f2SKenneth D. Merry /**
1596991554f2SKenneth D. Merry  * mpr_config_get_volume_wwid - returns wwid given the volume handle
1597991554f2SKenneth D. Merry  * @sc: per adapter object
1598991554f2SKenneth D. Merry  * @volume_handle: volume handle
1599991554f2SKenneth D. Merry  * @wwid: volume wwid
1600991554f2SKenneth D. Merry  * Context: sleep.
1601991554f2SKenneth D. Merry  *
1602991554f2SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
1603991554f2SKenneth D. Merry  */
1604991554f2SKenneth D. Merry int
mpr_config_get_volume_wwid(struct mpr_softc * sc,u16 volume_handle,u64 * wwid)1605991554f2SKenneth D. Merry mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid)
1606991554f2SKenneth D. Merry {
1607991554f2SKenneth D. Merry 	Mpi2ConfigReply_t mpi_reply;
1608991554f2SKenneth D. Merry 	Mpi2RaidVolPage1_t raid_vol_pg1;
1609991554f2SKenneth D. Merry 
1610991554f2SKenneth D. Merry 	*wwid = 0;
1611991554f2SKenneth D. Merry 	if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1612991554f2SKenneth D. Merry 	    MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1613991554f2SKenneth D. Merry 		*wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1614991554f2SKenneth D. Merry 		    raid_vol_pg1.WWID.Low);
1615991554f2SKenneth D. Merry 		return 0;
1616991554f2SKenneth D. Merry 	} else
1617991554f2SKenneth D. Merry 		return -1;
1618991554f2SKenneth D. Merry }
1619991554f2SKenneth D. Merry 
1620991554f2SKenneth D. Merry /**
1621991554f2SKenneth D. Merry  * mpr_config_get_pd_pg0 - obtain raid phys disk page 0
1622991554f2SKenneth D. Merry  * @sc: per adapter object
1623991554f2SKenneth D. Merry  * @mpi_reply: reply mf payload returned from firmware
1624991554f2SKenneth D. Merry  * @config_page: contents of the config page
1625991554f2SKenneth D. Merry  * @page_address: form and handle value used to get page
1626991554f2SKenneth D. Merry  * Context: sleep.
1627991554f2SKenneth D. Merry  *
1628991554f2SKenneth D. Merry  * Returns 0 for success, non-zero for failure.
1629991554f2SKenneth D. Merry  */
1630991554f2SKenneth D. Merry int
mpr_config_get_raid_pd_pg0(struct mpr_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidPhysDiskPage0_t * config_page,u32 page_address)1631991554f2SKenneth D. Merry mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1632991554f2SKenneth D. Merry     Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1633991554f2SKenneth D. Merry {
1634991554f2SKenneth D. Merry 	MPI2_CONFIG_REQUEST *request;
16356d4ffcb4SKenneth D. Merry 	MPI2_CONFIG_REPLY *reply = NULL;
1636991554f2SKenneth D. Merry 	struct mpr_command *cm;
1637991554f2SKenneth D. Merry 	Mpi2RaidPhysDiskPage0_t *page = NULL;
1638991554f2SKenneth D. Merry 	int error = 0;
1639991554f2SKenneth D. Merry 	u16 ioc_status;
1640991554f2SKenneth D. Merry 
1641991554f2SKenneth D. Merry 	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1642991554f2SKenneth D. Merry 
1643991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1644991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1645991554f2SKenneth D. Merry 		    __LINE__);
1646991554f2SKenneth D. Merry 		error = EBUSY;
1647991554f2SKenneth D. Merry 		goto out;
1648991554f2SKenneth D. Merry 	}
1649991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1650991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1651991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1652991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1653991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1654991554f2SKenneth D. Merry 	request->Header.PageNumber = 0;
165567feec50SStephen McConnell 	request->Header.PageLength = request->Header.PageVersion = 0;
1656991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1657991554f2SKenneth D. Merry 	cm->cm_data = NULL;
1658991554f2SKenneth D. Merry 
1659991554f2SKenneth D. Merry 	/*
1660991554f2SKenneth D. Merry 	 * This page must be polled because the IOC isn't ready yet when this
1661991554f2SKenneth D. Merry 	 * page is needed.
1662991554f2SKenneth D. Merry 	 */
16636d4ffcb4SKenneth D. Merry 	error = mpr_request_polled(sc, &cm);
16646d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1665991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1666991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
1667991554f2SKenneth D. Merry 		/* FIXME */
1668991554f2SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1669074bed4fSAlexander Motin 		printf("%s: poll for header completed with error %d\n",
1670991554f2SKenneth D. Merry 		    __func__, error);
1671991554f2SKenneth D. Merry 		error = ENXIO;
1672991554f2SKenneth D. Merry 		goto out;
1673991554f2SKenneth D. Merry 	}
1674991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1675991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1676991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1677991554f2SKenneth D. Merry 		/* FIXME */
1678991554f2SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1679991554f2SKenneth D. Merry 		printf("%s: header read with error; iocstatus = 0x%x\n",
1680991554f2SKenneth D. Merry 		    __func__, ioc_status);
1681991554f2SKenneth D. Merry 		error = ENXIO;
1682991554f2SKenneth D. Merry 		goto out;
1683991554f2SKenneth D. Merry 	}
1684991554f2SKenneth D. Merry 	/* We have to do free and alloc for the reply-free and reply-post
1685991554f2SKenneth D. Merry 	 * counters to match - Need to review the reply FIFO handling.
1686991554f2SKenneth D. Merry 	 */
1687991554f2SKenneth D. Merry 	mpr_free_command(sc, cm);
1688991554f2SKenneth D. Merry 
1689991554f2SKenneth D. Merry 	if ((cm = mpr_alloc_command(sc)) == NULL) {
1690991554f2SKenneth D. Merry 		printf("%s: command alloc failed @ line %d\n", __func__,
1691991554f2SKenneth D. Merry 		    __LINE__);
1692991554f2SKenneth D. Merry 		error = EBUSY;
1693991554f2SKenneth D. Merry 		goto out;
1694991554f2SKenneth D. Merry 	}
1695991554f2SKenneth D. Merry 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1696991554f2SKenneth D. Merry 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1697991554f2SKenneth D. Merry 	request->Function = MPI2_FUNCTION_CONFIG;
1698991554f2SKenneth D. Merry 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1699991554f2SKenneth D. Merry 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1700991554f2SKenneth D. Merry 	request->Header.PageNumber = 0;
1701991554f2SKenneth D. Merry 	request->Header.PageLength = mpi_reply->Header.PageLength;
1702991554f2SKenneth D. Merry 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1703991554f2SKenneth D. Merry 	request->PageAddress = page_address;
170471900a79SAlfredo Dal'Ava Junior 	cm->cm_length = mpi_reply->Header.PageLength * 4;
1705991554f2SKenneth D. Merry 	cm->cm_sge = &request->PageBufferSGE;
1706991554f2SKenneth D. Merry 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1707991554f2SKenneth D. Merry 	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1708991554f2SKenneth D. Merry 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1709991554f2SKenneth D. Merry 	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1710991554f2SKenneth D. Merry 	if (!page) {
1711991554f2SKenneth D. Merry 		printf("%s: page alloc failed\n", __func__);
1712991554f2SKenneth D. Merry 		error = ENOMEM;
1713991554f2SKenneth D. Merry 		goto out;
1714991554f2SKenneth D. Merry 	}
1715991554f2SKenneth D. Merry 	cm->cm_data = page;
1716991554f2SKenneth D. Merry 
1717991554f2SKenneth D. Merry 	/*
1718991554f2SKenneth D. Merry 	 * This page must be polled because the IOC isn't ready yet when this
1719991554f2SKenneth D. Merry 	 * page is needed.
1720991554f2SKenneth D. Merry 	 */
17216d4ffcb4SKenneth D. Merry 	error = mpr_request_polled(sc, &cm);
17226d4ffcb4SKenneth D. Merry 	if (cm != NULL)
1723991554f2SKenneth D. Merry 		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1724991554f2SKenneth D. Merry 	if (error || (reply == NULL)) {
1725991554f2SKenneth D. Merry 		/* FIXME */
1726991554f2SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1727074bed4fSAlexander Motin 		printf("%s: poll for page completed with error %d\n",
1728991554f2SKenneth D. Merry 		    __func__, error);
1729991554f2SKenneth D. Merry 		error = ENXIO;
1730991554f2SKenneth D. Merry 		goto out;
1731991554f2SKenneth D. Merry 	}
1732991554f2SKenneth D. Merry 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1733991554f2SKenneth D. Merry 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1734991554f2SKenneth D. Merry 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1735991554f2SKenneth D. Merry 		/* FIXME */
1736991554f2SKenneth D. Merry 		/* If the poll returns error then we need to do diag reset */
1737991554f2SKenneth D. Merry 		printf("%s: page read with error; iocstatus = 0x%x\n",
1738991554f2SKenneth D. Merry 		    __func__, ioc_status);
1739991554f2SKenneth D. Merry 		error = ENXIO;
1740991554f2SKenneth D. Merry 		goto out;
1741991554f2SKenneth D. Merry 	}
1742991554f2SKenneth D. Merry 	bcopy(page, config_page, MIN(cm->cm_length,
1743991554f2SKenneth D. Merry 	    sizeof(Mpi2RaidPhysDiskPage0_t)));
1744991554f2SKenneth D. Merry out:
1745991554f2SKenneth D. Merry 	free(page, M_MPR);
1746991554f2SKenneth D. Merry 	if (cm)
1747991554f2SKenneth D. Merry 		mpr_free_command(sc, cm);
1748991554f2SKenneth D. Merry 	return (error);
1749991554f2SKenneth D. Merry }
1750