1265236Sken/*-
2283990Sslm * Copyright (c) 2011-2015 LSI Corp.
3299962Sslm * Copyright (c) 2013-2016 Avago Technologies
4265236Sken * All rights reserved.
5265236Sken *
6265236Sken * Redistribution and use in source and binary forms, with or without
7265236Sken * modification, are permitted provided that the following conditions
8265236Sken * are met:
9265236Sken * 1. Redistributions of source code must retain the above copyright
10265236Sken *    notice, this list of conditions and the following disclaimer.
11265236Sken * 2. Redistributions in binary form must reproduce the above copyright
12265236Sken *    notice, this list of conditions and the following disclaimer in the
13265236Sken *    documentation and/or other materials provided with the distribution.
14265236Sken *
15265236Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16265236Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17265236Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18265236Sken * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19265236Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20265236Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21265236Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22265236Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23265236Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24265236Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25265236Sken * SUCH DAMAGE.
26265236Sken *
27283990Sslm * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
28265236Sken */
29265236Sken
30265236Sken#include <sys/cdefs.h>
31265236Sken__FBSDID("$FreeBSD: stable/10/sys/dev/mpr/mpr_config.c 322661 2017-08-18 15:38:08Z ken $");
32265236Sken
33265236Sken/* TODO Move headers to mprvar */
34265236Sken#include <sys/types.h>
35265236Sken#include <sys/param.h>
36265236Sken#include <sys/lock.h>
37265236Sken#include <sys/mutex.h>
38265236Sken#include <sys/systm.h>
39265236Sken#include <sys/kernel.h>
40265236Sken#include <sys/malloc.h>
41265236Sken#include <sys/kthread.h>
42265236Sken#include <sys/taskqueue.h>
43265236Sken#include <sys/bus.h>
44265236Sken#include <sys/endian.h>
45265236Sken#include <sys/sysctl.h>
46265236Sken#include <sys/eventhandler.h>
47265236Sken#include <sys/uio.h>
48265236Sken#include <machine/bus.h>
49265236Sken#include <machine/resource.h>
50265236Sken#include <dev/mpr/mpi/mpi2_type.h>
51265236Sken#include <dev/mpr/mpi/mpi2.h>
52265236Sken#include <dev/mpr/mpi/mpi2_ioc.h>
53265236Sken#include <dev/mpr/mpi/mpi2_sas.h>
54319436Sslm#include <dev/mpr/mpi/mpi2_pci.h>
55265236Sken#include <dev/mpr/mpi/mpi2_cnfg.h>
56265236Sken#include <dev/mpr/mpi/mpi2_init.h>
57265236Sken#include <dev/mpr/mpi/mpi2_tool.h>
58265236Sken#include <dev/mpr/mpr_ioctl.h>
59265236Sken#include <dev/mpr/mprvar.h>
60265236Sken
61265236Sken/**
62265236Sken * mpr_config_get_ioc_pg8 - obtain ioc page 8
63265236Sken * @sc: per adapter object
64265236Sken * @mpi_reply: reply mf payload returned from firmware
65265236Sken * @config_page: contents of the config page
66265236Sken * Context: sleep.
67265236Sken *
68265236Sken * Returns 0 for success, non-zero for failure.
69265236Sken */
70265236Skenint
71265236Skenmpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
72265236Sken    Mpi2IOCPage8_t *config_page)
73265236Sken{
74265236Sken	MPI2_CONFIG_REQUEST *request;
75265236Sken	MPI2_CONFIG_REPLY *reply;
76265236Sken	struct mpr_command *cm;
77265236Sken	MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
78265236Sken	int error = 0;
79265236Sken	u16 ioc_status;
80265236Sken
81265236Sken	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
82265236Sken
83265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
84265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
85265236Sken		    __LINE__);
86265236Sken		error = EBUSY;
87265236Sken		goto out;
88265236Sken	}
89265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
90265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
91265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
92265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
93265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
94265236Sken	request->Header.PageNumber = 8;
95319436Sslm	request->Header.PageLength = request->Header.PageVersion = 0;
96265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
97265236Sken	cm->cm_data = NULL;
98322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
99322661Sken	if (cm != NULL)
100322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
101265236Sken	if (error || (reply == NULL)) {
102265236Sken		/* FIXME */
103265236Sken		/*
104265236Sken		 * If the request returns an error then we need to do a diag
105265236Sken		 * reset
106265236Sken		 */
107265236Sken		printf("%s: request for header completed with error %d",
108265236Sken		    __func__, error);
109265236Sken		error = ENXIO;
110265236Sken		goto out;
111265236Sken	}
112265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
113265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
114265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
115265236Sken		/* FIXME */
116265236Sken		/*
117265236Sken		 * If the request returns an error then we need to do a diag
118265236Sken		 * reset
119265236Sken		 */
120265236Sken		printf("%s: header read with error; iocstatus = 0x%x\n",
121265236Sken		    __func__, ioc_status);
122265236Sken		error = ENXIO;
123265236Sken		goto out;
124265236Sken	}
125265236Sken	/* We have to do free and alloc for the reply-free and reply-post
126265236Sken	 * counters to match - Need to review the reply FIFO handling.
127265236Sken	 */
128265236Sken	mpr_free_command(sc, cm);
129265236Sken
130265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
131265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
132265236Sken		    __LINE__);
133265236Sken		error = EBUSY;
134265236Sken		goto out;
135265236Sken	}
136265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
137265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
138265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
139265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
140265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
141265236Sken	request->Header.PageNumber = 8;
142319436Sslm	request->Header.PageVersion = mpi_reply->Header.PageVersion;
143265236Sken	request->Header.PageLength = mpi_reply->Header.PageLength;
144265236Sken	cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
145265236Sken	cm->cm_sge = &request->PageBufferSGE;
146265236Sken	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
147265236Sken	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
148265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
149265236Sken	page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
150265236Sken	if (!page) {
151265236Sken		printf("%s: page alloc failed\n", __func__);
152265236Sken		error = ENOMEM;
153265236Sken		goto out;
154265236Sken	}
155265236Sken	cm->cm_data = page;
156265236Sken
157322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
158322661Sken	if (cm != NULL)
159322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
160265236Sken	if (error || (reply == NULL)) {
161265236Sken		/* FIXME */
162265236Sken		/*
163265236Sken		 * If the request returns an error then we need to do a diag
164265236Sken		 * reset
165265236Sken		 */
166265236Sken		printf("%s: request for page completed with error %d",
167265236Sken		    __func__, error);
168265236Sken		error = ENXIO;
169265236Sken		goto out;
170265236Sken	}
171265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
172265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
173265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
174265236Sken		/* FIXME */
175265236Sken		/*
176265236Sken		 * If the request returns an error then we need to do a diag
177265236Sken		 * reset
178265236Sken		 */
179265236Sken		printf("%s: page read with error; iocstatus = 0x%x\n",
180265236Sken		    __func__, ioc_status);
181265236Sken		error = ENXIO;
182265236Sken		goto out;
183265236Sken	}
184265236Sken	bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
185265236Sken
186265236Skenout:
187265236Sken	free(page, M_MPR);
188265236Sken	if (cm)
189265236Sken		mpr_free_command(sc, cm);
190265236Sken	return (error);
191265236Sken}
192265236Sken
193265236Sken/**
194265236Sken * mpr_config_get_iounit_pg8 - obtain iounit page 8
195265236Sken * @sc: per adapter object
196265236Sken * @mpi_reply: reply mf payload returned from firmware
197265236Sken * @config_page: contents of the config page
198265236Sken * Context: sleep.
199265236Sken *
200265236Sken * Returns 0 for success, non-zero for failure.
201265236Sken */
202265236Skenint
203265236Skenmpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
204265236Sken    Mpi2IOUnitPage8_t *config_page)
205265236Sken{
206265236Sken	MPI2_CONFIG_REQUEST *request;
207265236Sken	MPI2_CONFIG_REPLY *reply;
208265236Sken	struct mpr_command *cm;
209265236Sken	MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL;
210265236Sken	int error = 0;
211265236Sken	u16 ioc_status;
212265236Sken
213265236Sken	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
214265236Sken
215265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
216265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
217265236Sken		    __LINE__);
218265236Sken		error = EBUSY;
219265236Sken		goto out;
220265236Sken	}
221265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
222265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
223265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
224265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
225265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
226265236Sken	request->Header.PageNumber = 8;
227319436Sslm	request->Header.PageLength = request->Header.PageVersion = 0;
228265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
229265236Sken	cm->cm_data = NULL;
230322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
231322661Sken	if (cm != NULL)
232322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
233265236Sken	if (error || (reply == NULL)) {
234265236Sken		/* FIXME */
235265236Sken		/*
236265236Sken		 * If the request returns an error then we need to do a diag
237265236Sken		 * reset
238265236Sken		 */
239265236Sken		printf("%s: request for header completed with error %d",
240265236Sken		    __func__, error);
241265236Sken		error = ENXIO;
242265236Sken		goto out;
243265236Sken	}
244265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
245265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
246265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
247265236Sken		/* FIXME */
248265236Sken		/*
249265236Sken		 * If the request returns an error then we need to do a diag
250265236Sken		 * reset
251265236Sken		 */
252265236Sken		printf("%s: header read with error; iocstatus = 0x%x\n",
253265236Sken		    __func__, ioc_status);
254265236Sken		error = ENXIO;
255265236Sken		goto out;
256265236Sken	}
257265236Sken	/* We have to do free and alloc for the reply-free and reply-post
258265236Sken	 * counters to match - Need to review the reply FIFO handling.
259265236Sken	 */
260265236Sken	mpr_free_command(sc, cm);
261265236Sken
262265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
263265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
264265236Sken		    __LINE__);
265265236Sken		error = EBUSY;
266265236Sken		goto out;
267265236Sken	}
268265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
269265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
270265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
271265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
272265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
273265236Sken	request->Header.PageNumber = 8;
274319436Sslm	request->Header.PageVersion = mpi_reply->Header.PageVersion;
275265236Sken	request->Header.PageLength = mpi_reply->Header.PageLength;
276265236Sken	cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
277265236Sken	cm->cm_sge = &request->PageBufferSGE;
278265236Sken	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
279265236Sken	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
280265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
281265236Sken	page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
282265236Sken	if (!page) {
283265236Sken		printf("%s: page alloc failed\n", __func__);
284265236Sken		error = ENOMEM;
285265236Sken		goto out;
286265236Sken	}
287265236Sken	cm->cm_data = page;
288265236Sken
289322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
290322661Sken	if (cm != NULL)
291322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
292265236Sken	if (error || (reply == NULL)) {
293265236Sken		/* FIXME */
294265236Sken		/*
295265236Sken		 * If the request returns an error then we need to do a diag
296265236Sken		 * reset
297265236Sken		 */
298265236Sken		printf("%s: request for page completed with error %d",
299265236Sken		    __func__, error);
300265236Sken		error = ENXIO;
301265236Sken		goto out;
302265236Sken	}
303265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
304265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
305265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
306265236Sken		/* FIXME */
307265236Sken		/*
308265236Sken		 * If the request returns an error then we need to do a diag
309265236Sken		 * reset
310265236Sken		 */
311265236Sken		printf("%s: page read with error; iocstatus = 0x%x\n",
312265236Sken		    __func__, ioc_status);
313265236Sken		error = ENXIO;
314265236Sken		goto out;
315265236Sken	}
316265236Sken	bcopy(page, config_page, MIN(cm->cm_length,
317265236Sken	    (sizeof(Mpi2IOUnitPage8_t))));
318265236Sken
319265236Skenout:
320265236Sken	free(page, M_MPR);
321265236Sken	if (cm)
322265236Sken		mpr_free_command(sc, cm);
323265236Sken	return (error);
324265236Sken}
325265236Sken
326265236Sken/**
327265236Sken * mpr_base_static_config_pages - static start of day config pages.
328265236Sken * @sc: per adapter object
329265236Sken *
330265236Sken * Return nothing.
331265236Sken */
332265236Skenvoid
333265236Skenmpr_base_static_config_pages(struct mpr_softc *sc)
334265236Sken{
335265236Sken	Mpi2ConfigReply_t	mpi_reply;
336265236Sken	int			retry;
337265236Sken
338265236Sken	retry = 0;
339265236Sken	while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
340265236Sken		retry++;
341265236Sken		if (retry > 5) {
342265236Sken			/* We need to Handle this situation */
343265236Sken			/*FIXME*/
344265236Sken			break;
345265236Sken		}
346265236Sken	}
347265236Sken	retry = 0;
348265236Sken	while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) {
349265236Sken		retry++;
350265236Sken		if (retry > 5) {
351265236Sken			/* We need to Handle this situation */
352265236Sken			/*FIXME*/
353265236Sken			break;
354265236Sken		}
355265236Sken	}
356265236Sken}
357265236Sken
358265236Sken/**
359265236Sken * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0
360265236Sken * @sc: per adapter object
361265236Sken * @mpi_reply: reply mf payload returned from firmware
362265236Sken * @config_page: contents of the config page
363265236Sken * @sz: size of buffer passed in config_page
364265236Sken * Context: sleep.
365265236Sken *
366265236Sken * Returns 0 for success, non-zero for failure.
367265236Sken */
368265236Skenint
369265236Skenmpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
370265236Sken    Mpi2DriverMappingPage0_t *config_page, u16 sz)
371265236Sken{
372265236Sken	MPI2_CONFIG_REQUEST *request;
373265236Sken	MPI2_CONFIG_REPLY *reply;
374265236Sken	struct mpr_command *cm;
375265236Sken	Mpi2DriverMappingPage0_t *page = NULL;
376265236Sken	int error = 0;
377265236Sken	u16 ioc_status;
378265236Sken
379265236Sken	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
380265236Sken
381265236Sken	memset(config_page, 0, sz);
382265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
383265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
384265236Sken		    __LINE__);
385265236Sken		error = EBUSY;
386265236Sken		goto out;
387265236Sken	}
388265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
389265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
390265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
391265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
392265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
393265236Sken	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
394265236Sken	request->Header.PageNumber = 0;
395319436Sslm	request->ExtPageLength = request->Header.PageVersion = 0;
396265236Sken	request->PageAddress = sc->max_dpm_entries <<
397265236Sken	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
398265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
399265236Sken	cm->cm_data = NULL;
400322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
401322661Sken	if (cm != NULL)
402322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
403265236Sken	if (error || (reply == NULL)) {
404265236Sken		/* FIXME */
405265236Sken		/*
406265236Sken		 * If the request returns an error then we need to do a diag
407265236Sken		 * reset
408265236Sken		 */
409265236Sken		printf("%s: request for header completed with error %d",
410265236Sken		    __func__, error);
411265236Sken		error = ENXIO;
412265236Sken		goto out;
413265236Sken	}
414265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
415265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
416265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
417265236Sken		/* FIXME */
418265236Sken		/*
419265236Sken		 * If the request returns an error then we need to do a diag
420265236Sken		 * reset
421265236Sken		 */
422265236Sken		printf("%s: header read with error; iocstatus = 0x%x\n",
423265236Sken		    __func__, ioc_status);
424265236Sken		error = ENXIO;
425265236Sken		goto out;
426265236Sken	}
427265236Sken	/* We have to do free and alloc for the reply-free and reply-post
428265236Sken	 * counters to match - Need to review the reply FIFO handling.
429265236Sken	 */
430265236Sken	mpr_free_command(sc, cm);
431265236Sken
432265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
433265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
434265236Sken		    __LINE__);
435265236Sken		error = EBUSY;
436265236Sken		goto out;
437265236Sken	}
438265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
439265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
440265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
441265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
442265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
443265236Sken	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
444265236Sken	request->Header.PageNumber = 0;
445319436Sslm	request->Header.PageVersion = mpi_reply->Header.PageVersion;
446265236Sken	request->PageAddress = sc->max_dpm_entries <<
447265236Sken	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
448265236Sken	request->ExtPageLength = mpi_reply->ExtPageLength;
449265236Sken	cm->cm_length =  le16toh(request->ExtPageLength) * 4;
450265236Sken	cm->cm_sge = &request->PageBufferSGE;
451265236Sken	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
452265236Sken	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
453265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
454265236Sken	page = malloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT);
455265236Sken	if (!page) {
456265236Sken		printf("%s: page alloc failed\n", __func__);
457265236Sken		error = ENOMEM;
458265236Sken		goto out;
459265236Sken	}
460265236Sken	cm->cm_data = page;
461322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
462322661Sken	if (cm != NULL)
463322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
464265236Sken	if (error || (reply == NULL)) {
465265236Sken		/* FIXME */
466265236Sken		/*
467265236Sken		 * If the request returns an error then we need to do a diag
468265236Sken		 * reset
469265236Sken		 */
470265236Sken		printf("%s: request for page completed with error %d",
471265236Sken		    __func__, error);
472265236Sken		error = ENXIO;
473265236Sken		goto out;
474265236Sken	}
475265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
476265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
477265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
478265236Sken		/* FIXME */
479265236Sken		/*
480265236Sken		 * If the request returns an error then we need to do a diag
481265236Sken		 * reset
482265236Sken		 */
483265236Sken		printf("%s: page read with error; iocstatus = 0x%x\n",
484265236Sken		    __func__, ioc_status);
485265236Sken		error = ENXIO;
486265236Sken		goto out;
487265236Sken	}
488265236Sken	bcopy(page, config_page, MIN(cm->cm_length, sz));
489265236Skenout:
490265236Sken	free(page, M_MPR);
491265236Sken	if (cm)
492265236Sken		mpr_free_command(sc, cm);
493265236Sken	return (error);
494265236Sken}
495265236Sken
496265236Sken/**
497265236Sken * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
498265236Sken * @sc: per adapter object
499265236Sken * @mpi_reply: reply mf payload returned from firmware
500265236Sken * @config_page: contents of the config page
501265236Sken * @entry_idx: entry index in DPM Page0 to be modified
502265236Sken * Context: sleep.
503265236Sken *
504265236Sken * Returns 0 for success, non-zero for failure.
505265236Sken */
506265236Sken
507265236Skenint mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
508265236Sken    Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
509265236Sken{
510265236Sken	MPI2_CONFIG_REQUEST *request;
511265236Sken	MPI2_CONFIG_REPLY *reply;
512265236Sken	struct mpr_command *cm;
513265236Sken	MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
514265236Sken	int error = 0;
515265236Sken	u16 ioc_status;
516265236Sken
517265236Sken	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
518265236Sken
519265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
520265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
521265236Sken		    __LINE__);
522265236Sken		error = EBUSY;
523265236Sken		goto out;
524265236Sken	}
525265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
526265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
527265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
528265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
529265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
530265236Sken	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
531265236Sken	request->Header.PageNumber = 0;
532319436Sslm	request->ExtPageLength = request->Header.PageVersion = 0;
533265236Sken	/* We can remove below two lines ????*/
534265236Sken	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
535265236Sken	request->PageAddress |= htole16(entry_idx);
536265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
537265236Sken	cm->cm_data = NULL;
538322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
539322661Sken	if (cm != NULL)
540322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
541265236Sken	if (error || (reply == NULL)) {
542265236Sken		/* FIXME */
543265236Sken		/*
544265236Sken		 * If the request returns an error then we need to do a diag
545265236Sken		 * reset
546265236Sken		 */
547265236Sken		printf("%s: request for header completed with error %d",
548265236Sken		    __func__, error);
549265236Sken		error = ENXIO;
550265236Sken		goto out;
551265236Sken	}
552265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
553265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
554265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
555265236Sken		/* FIXME */
556265236Sken		/*
557265236Sken		 * If the request returns an error then we need to do a diag
558265236Sken		 * reset
559265236Sken		 */
560265236Sken		printf("%s: header read with error; iocstatus = 0x%x\n",
561265236Sken		    __func__, ioc_status);
562265236Sken		error = ENXIO;
563265236Sken		goto out;
564265236Sken	}
565265236Sken	/* We have to do free and alloc for the reply-free and reply-post
566265236Sken	 * counters to match - Need to review the reply FIFO handling.
567265236Sken	 */
568265236Sken	mpr_free_command(sc, cm);
569265236Sken
570265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
571265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
572265236Sken		    __LINE__);
573265236Sken		error = EBUSY;
574265236Sken		goto out;
575265236Sken	}
576265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
577265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
578265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
579265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
580265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
581265236Sken	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
582265236Sken	request->Header.PageNumber = 0;
583319436Sslm	request->Header.PageVersion = mpi_reply->Header.PageVersion;
584265236Sken	request->ExtPageLength = mpi_reply->ExtPageLength;
585265236Sken	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
586265236Sken	request->PageAddress |= htole16(entry_idx);
587265236Sken	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
588265236Sken	cm->cm_sge = &request->PageBufferSGE;
589265236Sken	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
590265236Sken	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT;
591265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
592265236Sken	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
593265236Sken	if (!page) {
594265236Sken		printf("%s: page alloc failed\n", __func__);
595265236Sken		error = ENOMEM;
596265236Sken		goto out;
597265236Sken	}
598265236Sken	bcopy(config_page, page, MIN(cm->cm_length,
599265236Sken	    (sizeof(Mpi2DriverMappingPage0_t))));
600265236Sken	cm->cm_data = page;
601322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
602322661Sken	if (cm != NULL)
603322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
604265236Sken	if (error || (reply == NULL)) {
605265236Sken		/* FIXME */
606265236Sken		/*
607265236Sken		 * If the request returns an error then we need to do a diag
608265236Sken		 * reset
609265236Sken		 */
610265236Sken		printf("%s: request to write page completed with error %d",
611265236Sken		    __func__, error);
612265236Sken		error = ENXIO;
613265236Sken		goto out;
614265236Sken	}
615265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
616265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
617265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
618265236Sken		/* FIXME */
619265236Sken		/*
620265236Sken		 * If the request returns an error then we need to do a diag
621265236Sken		 * reset
622265236Sken		 */
623265236Sken		printf("%s: page written with error; iocstatus = 0x%x\n",
624265236Sken		    __func__, ioc_status);
625265236Sken		error = ENXIO;
626265236Sken		goto out;
627265236Sken	}
628265236Skenout:
629265236Sken	free(page, M_MPR);
630265236Sken	if (cm)
631265236Sken		mpr_free_command(sc, cm);
632265236Sken	return (error);
633265236Sken}
634265236Sken
635265236Sken/**
636265236Sken * mpr_config_get_sas_device_pg0 - obtain sas device page 0
637265236Sken * @sc: per adapter object
638265236Sken * @mpi_reply: reply mf payload returned from firmware
639265236Sken * @config_page: contents of the config page
640265236Sken * @form: GET_NEXT_HANDLE or HANDLE
641265236Sken * @handle: device handle
642265236Sken * Context: sleep.
643265236Sken *
644265236Sken * Returns 0 for success, non-zero for failure.
645265236Sken */
646265236Skenint
647265236Skenmpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
648265236Sken    *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
649265236Sken{
650265236Sken	MPI2_CONFIG_REQUEST *request;
651265236Sken	MPI2_CONFIG_REPLY *reply;
652265236Sken	struct mpr_command *cm;
653265236Sken	Mpi2SasDevicePage0_t *page = NULL;
654265236Sken	int error = 0;
655265236Sken	u16 ioc_status;
656265236Sken
657265236Sken	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
658265236Sken
659265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
660265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
661265236Sken		    __LINE__);
662265236Sken		error = EBUSY;
663265236Sken		goto out;
664265236Sken	}
665265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
666265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
667265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
668265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
669265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
670265236Sken	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
671265236Sken	request->Header.PageNumber = 0;
672319436Sslm	request->ExtPageLength = request->Header.PageVersion = 0;
673265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
674265236Sken	cm->cm_data = NULL;
675322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
676322661Sken	if (cm != NULL)
677322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
678265236Sken	if (error || (reply == NULL)) {
679265236Sken		/* FIXME */
680265236Sken		/*
681265236Sken		 * If the request returns an error then we need to do a diag
682265236Sken		 * reset
683265236Sken		 */
684265236Sken		printf("%s: request for header completed with error %d",
685265236Sken		    __func__, error);
686265236Sken		error = ENXIO;
687265236Sken		goto out;
688265236Sken	}
689265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
690265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
691265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
692265236Sken		/* FIXME */
693265236Sken		/*
694265236Sken		 * If the request returns an error then we need to do a diag
695265236Sken		 * reset
696265236Sken		 */
697265236Sken		printf("%s: header read with error; iocstatus = 0x%x\n",
698265236Sken		    __func__, ioc_status);
699265236Sken		error = ENXIO;
700265236Sken		goto out;
701265236Sken	}
702265236Sken	/* We have to do free and alloc for the reply-free and reply-post
703265236Sken	 * counters to match - Need to review the reply FIFO handling.
704265236Sken	 */
705265236Sken	mpr_free_command(sc, cm);
706265236Sken
707265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
708265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
709265236Sken		    __LINE__);
710265236Sken		error = EBUSY;
711265236Sken		goto out;
712265236Sken	}
713265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
714265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
715265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
716265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
717265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
718265236Sken	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
719265236Sken	request->Header.PageNumber = 0;
720319436Sslm	request->Header.PageVersion = mpi_reply->Header.PageVersion;
721265236Sken	request->ExtPageLength = mpi_reply->ExtPageLength;
722265236Sken	request->PageAddress = htole32(form | handle);
723265236Sken	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
724265236Sken	cm->cm_sge = &request->PageBufferSGE;
725265236Sken	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
726265236Sken	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
727265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
728265236Sken	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
729265236Sken	if (!page) {
730265236Sken		printf("%s: page alloc failed\n", __func__);
731265236Sken		error = ENOMEM;
732265236Sken		goto out;
733265236Sken	}
734265236Sken	cm->cm_data = page;
735265236Sken
736322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
737322661Sken	if (cm != NULL)
738322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
739265236Sken	if (error || (reply == NULL)) {
740265236Sken		/* FIXME */
741265236Sken		/*
742265236Sken		 * If the request returns an error then we need to do a diag
743265236Sken		 * reset
744265236Sken		 */
745265236Sken		printf("%s: request for page completed with error %d",
746265236Sken		    __func__, error);
747265236Sken		error = ENXIO;
748265236Sken		goto out;
749265236Sken	}
750265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
751265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
752265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
753265236Sken		/* FIXME */
754265236Sken		/*
755265236Sken		 * If the request returns an error then we need to do a diag
756265236Sken		 * reset
757265236Sken		 */
758265236Sken		printf("%s: page read with error; iocstatus = 0x%x\n",
759265236Sken		    __func__, ioc_status);
760265236Sken		error = ENXIO;
761265236Sken		goto out;
762265236Sken	}
763265236Sken	bcopy(page, config_page, MIN(cm->cm_length,
764265236Sken	    sizeof(Mpi2SasDevicePage0_t)));
765265236Skenout:
766265236Sken	free(page, M_MPR);
767265236Sken	if (cm)
768265236Sken		mpr_free_command(sc, cm);
769265236Sken	return (error);
770265236Sken}
771265236Sken
772265236Sken/**
773319436Sslm * mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0
774319436Sslm * @sc: per adapter object
775319436Sslm * @mpi_reply: reply mf payload returned from firmware
776319436Sslm * @config_page: contents of the config page
777319436Sslm * @form: GET_NEXT_HANDLE or HANDLE
778319436Sslm * @handle: device handle
779319436Sslm * Context: sleep.
780319436Sslm *
781319436Sslm * Returns 0 for success, non-zero for failure.
782319436Sslm */
783319436Sslmint
784319436Sslmmpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
785319436Sslm    *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle)
786319436Sslm{
787319436Sslm	MPI2_CONFIG_REQUEST *request;
788319436Sslm	MPI2_CONFIG_REPLY *reply;
789319436Sslm	struct mpr_command *cm;
790319436Sslm	Mpi26PCIeDevicePage0_t *page = NULL;
791319436Sslm	int error = 0;
792319436Sslm	u16 ioc_status;
793319436Sslm
794319436Sslm	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
795319436Sslm
796319436Sslm	if ((cm = mpr_alloc_command(sc)) == NULL) {
797319436Sslm		printf("%s: command alloc failed @ line %d\n", __func__,
798319436Sslm		    __LINE__);
799319436Sslm		error = EBUSY;
800319436Sslm		goto out;
801319436Sslm	}
802319436Sslm	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
803319436Sslm	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
804319436Sslm	request->Function = MPI2_FUNCTION_CONFIG;
805319436Sslm	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
806319436Sslm	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
807319436Sslm	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
808319436Sslm	request->Header.PageNumber = 0;
809319436Sslm	request->ExtPageLength = request->Header.PageVersion = 0;
810319436Sslm	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
811319436Sslm	cm->cm_data = NULL;
812322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
813322661Sken	if (cm != NULL)
814322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
815319436Sslm	if (error || (reply == NULL)) {
816319436Sslm		/* FIXME */
817319436Sslm		/*
818319436Sslm		 * If the request returns an error then we need to do a diag
819319436Sslm		 * reset
820319436Sslm		 */
821319436Sslm		printf("%s: request for header completed with error %d",
822319436Sslm		    __func__, error);
823319436Sslm		error = ENXIO;
824319436Sslm		goto out;
825319436Sslm	}
826319436Sslm	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
827319436Sslm	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
828319436Sslm	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
829319436Sslm		/* FIXME */
830319436Sslm		/*
831319436Sslm		 * If the request returns an error then we need to do a diag
832319436Sslm		 * reset
833319436Sslm		 */
834319436Sslm		printf("%s: header read with error; iocstatus = 0x%x\n",
835319436Sslm		    __func__, ioc_status);
836319436Sslm		error = ENXIO;
837319436Sslm		goto out;
838319436Sslm	}
839319436Sslm	/* We have to do free and alloc for the reply-free and reply-post
840319436Sslm	 * counters to match - Need to review the reply FIFO handling.
841319436Sslm	 */
842319436Sslm	mpr_free_command(sc, cm);
843319436Sslm
844319436Sslm	if ((cm = mpr_alloc_command(sc)) == NULL) {
845319436Sslm		printf("%s: command alloc failed @ line %d\n", __func__,
846319436Sslm		    __LINE__);
847319436Sslm		error = EBUSY;
848319436Sslm		goto out;
849319436Sslm	}
850319436Sslm	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
851319436Sslm	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
852319436Sslm	request->Function = MPI2_FUNCTION_CONFIG;
853319436Sslm	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
854319436Sslm	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
855319436Sslm	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
856319436Sslm	request->Header.PageNumber = 0;
857319436Sslm	request->Header.PageVersion = mpi_reply->Header.PageVersion;
858319436Sslm	request->ExtPageLength = mpi_reply->ExtPageLength;
859319436Sslm	request->PageAddress = htole32(form | handle);
860319436Sslm	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
861319436Sslm	cm->cm_sge = &request->PageBufferSGE;
862319436Sslm	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
863319436Sslm	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
864319436Sslm	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
865319436Sslm	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
866319436Sslm	if (!page) {
867319436Sslm		printf("%s: page alloc failed\n", __func__);
868319436Sslm		error = ENOMEM;
869319436Sslm		goto out;
870319436Sslm	}
871319436Sslm	cm->cm_data = page;
872319436Sslm
873322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
874322661Sken	if (cm != NULL)
875322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
876319436Sslm	if (error || (reply == NULL)) {
877319436Sslm		/* FIXME */
878319436Sslm		/*
879319436Sslm		 * If the request returns an error then we need to do a diag
880319436Sslm		 * reset
881319436Sslm		 */
882319436Sslm		printf("%s: request for page completed with error %d",
883319436Sslm		    __func__, error);
884319436Sslm		error = ENXIO;
885319436Sslm		goto out;
886319436Sslm	}
887319436Sslm	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
888319436Sslm	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
889319436Sslm	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
890319436Sslm		/* FIXME */
891319436Sslm		/*
892319436Sslm		 * If the request returns an error then we need to do a diag
893319436Sslm		 * reset
894319436Sslm		 */
895319436Sslm		printf("%s: page read with error; iocstatus = 0x%x\n",
896319436Sslm		    __func__, ioc_status);
897319436Sslm		error = ENXIO;
898319436Sslm		goto out;
899319436Sslm	}
900319436Sslm	bcopy(page, config_page, MIN(cm->cm_length,
901319436Sslm	    sizeof(Mpi26PCIeDevicePage0_t)));
902319436Sslmout:
903319436Sslm	free(page, M_MPR);
904319436Sslm	if (cm)
905319436Sslm		mpr_free_command(sc, cm);
906319436Sslm	return (error);
907319436Sslm}
908319436Sslm
909319436Sslm/**
910319436Sslm * mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2
911319436Sslm * @sc: per adapter object
912319436Sslm * @mpi_reply: reply mf payload returned from firmware
913319436Sslm * @config_page: contents of the config page
914319436Sslm * @form: GET_NEXT_HANDLE or HANDLE
915319436Sslm * @handle: device handle
916319436Sslm * Context: sleep.
917319436Sslm *
918319436Sslm * Returns 0 for success, non-zero for failure.
919319436Sslm */
920319436Sslmint
921319436Sslmmpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t
922319436Sslm    *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle)
923319436Sslm{
924319436Sslm	MPI2_CONFIG_REQUEST *request;
925319436Sslm	MPI2_CONFIG_REPLY *reply;
926319436Sslm	struct mpr_command *cm;
927319436Sslm	Mpi26PCIeDevicePage2_t *page = NULL;
928319436Sslm	int error = 0;
929319436Sslm	u16 ioc_status;
930319436Sslm
931319436Sslm	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
932319436Sslm
933319436Sslm	if ((cm = mpr_alloc_command(sc)) == NULL) {
934319436Sslm		printf("%s: command alloc failed @ line %d\n", __func__,
935319436Sslm		    __LINE__);
936319436Sslm		error = EBUSY;
937319436Sslm		goto out;
938319436Sslm	}
939319436Sslm	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
940319436Sslm	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
941319436Sslm	request->Function = MPI2_FUNCTION_CONFIG;
942319436Sslm	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
943319436Sslm	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
944319436Sslm	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
945319436Sslm	request->Header.PageNumber = 2;
946319436Sslm	request->ExtPageLength = request->Header.PageVersion = 0;
947319436Sslm	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
948319436Sslm	cm->cm_data = NULL;
949322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
950322661Sken	if (cm != NULL)
951322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
952319436Sslm	if (error || (reply == NULL)) {
953319436Sslm		/* FIXME */
954319436Sslm		/*
955319436Sslm		 * If the request returns an error then we need to do a diag
956319436Sslm		 * reset
957319436Sslm		 */
958319436Sslm		printf("%s: request for header completed with error %d",
959319436Sslm		    __func__, error);
960319436Sslm		error = ENXIO;
961319436Sslm		goto out;
962319436Sslm	}
963319436Sslm	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
964319436Sslm	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
965319436Sslm	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
966319436Sslm		/* FIXME */
967319436Sslm		/*
968319436Sslm		 * If the request returns an error then we need to do a diag
969319436Sslm		 * reset
970319436Sslm		 */
971319436Sslm		printf("%s: header read with error; iocstatus = 0x%x\n",
972319436Sslm		    __func__, ioc_status);
973319436Sslm		error = ENXIO;
974319436Sslm		goto out;
975319436Sslm	}
976319436Sslm	/* We have to do free and alloc for the reply-free and reply-post
977319436Sslm	 * counters to match - Need to review the reply FIFO handling.
978319436Sslm	 */
979319436Sslm	mpr_free_command(sc, cm);
980319436Sslm
981319436Sslm	if ((cm = mpr_alloc_command(sc)) == NULL) {
982319436Sslm		printf("%s: command alloc failed @ line %d\n", __func__,
983319436Sslm		    __LINE__);
984319436Sslm		error = EBUSY;
985319436Sslm		goto out;
986319436Sslm	}
987319436Sslm	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
988319436Sslm	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
989319436Sslm	request->Function = MPI2_FUNCTION_CONFIG;
990319436Sslm	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
991319436Sslm	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
992319436Sslm	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
993319436Sslm	request->Header.PageNumber = 2;
994319436Sslm	request->Header.PageVersion = mpi_reply->Header.PageVersion;
995319436Sslm	request->ExtPageLength = mpi_reply->ExtPageLength;
996319436Sslm	request->PageAddress = htole32(form | handle);
997319436Sslm	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
998319436Sslm	cm->cm_sge = &request->PageBufferSGE;
999319436Sslm	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1000319436Sslm	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1001319436Sslm	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1002319436Sslm	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1003319436Sslm	if (!page) {
1004319436Sslm		printf("%s: page alloc failed\n", __func__);
1005319436Sslm		error = ENOMEM;
1006319436Sslm		goto out;
1007319436Sslm	}
1008319436Sslm	cm->cm_data = page;
1009319436Sslm
1010322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1011322661Sken	if (cm != NULL)
1012322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1013319436Sslm	if (error || (reply == NULL)) {
1014319436Sslm		/* FIXME */
1015319436Sslm		/*
1016319436Sslm		 * If the request returns an error then we need to do a diag
1017319436Sslm		 * reset
1018319436Sslm		 */
1019319436Sslm		printf("%s: request for page completed with error %d",
1020319436Sslm		    __func__, error);
1021319436Sslm		error = ENXIO;
1022319436Sslm		goto out;
1023319436Sslm	}
1024319436Sslm	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1025319436Sslm	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1026319436Sslm	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1027319436Sslm		/* FIXME */
1028319436Sslm		/*
1029319436Sslm		 * If the request returns an error then we need to do a diag
1030319436Sslm		 * reset
1031319436Sslm		 */
1032319436Sslm		printf("%s: page read with error; iocstatus = 0x%x\n",
1033319436Sslm		    __func__, ioc_status);
1034319436Sslm		error = ENXIO;
1035319436Sslm		goto out;
1036319436Sslm	}
1037319436Sslm	bcopy(page, config_page, MIN(cm->cm_length,
1038319436Sslm	    sizeof(Mpi26PCIeDevicePage2_t)));
1039319436Sslmout:
1040319436Sslm	free(page, M_MPR);
1041319436Sslm	if (cm)
1042319436Sslm		mpr_free_command(sc, cm);
1043319436Sslm	return (error);
1044319436Sslm}
1045319436Sslm
1046319436Sslm/**
1047265236Sken * mpr_config_get_bios_pg3 - obtain BIOS page 3
1048265236Sken * @sc: per adapter object
1049265236Sken * @mpi_reply: reply mf payload returned from firmware
1050265236Sken * @config_page: contents of the config page
1051265236Sken * Context: sleep.
1052265236Sken *
1053265236Sken * Returns 0 for success, non-zero for failure.
1054265236Sken */
1055265236Skenint
1056265236Skenmpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1057265236Sken    Mpi2BiosPage3_t *config_page)
1058265236Sken{
1059265236Sken	MPI2_CONFIG_REQUEST *request;
1060265236Sken	MPI2_CONFIG_REPLY *reply;
1061265236Sken	struct mpr_command *cm;
1062265236Sken	Mpi2BiosPage3_t *page = NULL;
1063265236Sken	int error = 0;
1064265236Sken	u16 ioc_status;
1065265236Sken
1066265236Sken	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1067265236Sken
1068265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
1069265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
1070265236Sken		    __LINE__);
1071265236Sken		error = EBUSY;
1072265236Sken		goto out;
1073265236Sken	}
1074265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1075265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1076265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
1077265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1078265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1079265236Sken	request->Header.PageNumber = 3;
1080319436Sslm	request->Header.PageLength = request->Header.PageVersion = 0;
1081265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1082265236Sken	cm->cm_data = NULL;
1083322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1084322661Sken	if (cm != NULL)
1085322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1086265236Sken	if (error || (reply == NULL)) {
1087265236Sken		/* FIXME */
1088265236Sken		/*
1089265236Sken		 * If the request returns an error then we need to do a diag
1090265236Sken		 * reset
1091265236Sken		 */
1092265236Sken		printf("%s: request for header completed with error %d",
1093265236Sken		    __func__, error);
1094265236Sken		error = ENXIO;
1095265236Sken		goto out;
1096265236Sken	}
1097265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1098265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1099265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1100265236Sken		/* FIXME */
1101265236Sken		/*
1102265236Sken		 * If the request returns an error then we need to do a diag
1103265236Sken		 * reset
1104265236Sken		 */
1105265236Sken		printf("%s: header read with error; iocstatus = 0x%x\n",
1106265236Sken		    __func__, ioc_status);
1107265236Sken		error = ENXIO;
1108265236Sken		goto out;
1109265236Sken	}
1110265236Sken	/* We have to do free and alloc for the reply-free and reply-post
1111265236Sken	 * counters to match - Need to review the reply FIFO handling.
1112265236Sken	 */
1113265236Sken	mpr_free_command(sc, cm);
1114265236Sken
1115265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
1116265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
1117265236Sken		    __LINE__);
1118265236Sken		error = EBUSY;
1119265236Sken		goto out;
1120265236Sken	}
1121265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1122265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1123265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
1124265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1125265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1126265236Sken	request->Header.PageNumber = 3;
1127319436Sslm	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1128265236Sken	request->Header.PageLength = mpi_reply->Header.PageLength;
1129265236Sken	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1130265236Sken	cm->cm_sge = &request->PageBufferSGE;
1131265236Sken	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1132265236Sken	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1133265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1134265236Sken	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1135265236Sken	if (!page) {
1136265236Sken		printf("%s: page alloc failed\n", __func__);
1137265236Sken		error = ENOMEM;
1138265236Sken		goto out;
1139265236Sken	}
1140265236Sken	cm->cm_data = page;
1141265236Sken
1142322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1143322661Sken	if (cm != NULL)
1144322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1145265236Sken	if (error || (reply == NULL)) {
1146265236Sken		/* FIXME */
1147265236Sken		/*
1148265236Sken		 * If the request returns an error then we need to do a diag
1149265236Sken		 * reset
1150265236Sken		 */
1151265236Sken		printf("%s: request for page completed with error %d",
1152265236Sken		    __func__, error);
1153265236Sken		error = ENXIO;
1154265236Sken		goto out;
1155265236Sken	}
1156265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1157265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1158265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1159265236Sken		/* FIXME */
1160265236Sken		/*
1161265236Sken		 * If the request returns an error then we need to do a diag
1162265236Sken		 * reset
1163265236Sken		 */
1164265236Sken		printf("%s: page read with error; iocstatus = 0x%x\n",
1165265236Sken		    __func__, ioc_status);
1166265236Sken		error = ENXIO;
1167265236Sken		goto out;
1168265236Sken	}
1169265236Sken	bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1170265236Skenout:
1171265236Sken	free(page, M_MPR);
1172265236Sken	if (cm)
1173265236Sken		mpr_free_command(sc, cm);
1174265236Sken	return (error);
1175265236Sken}
1176265236Sken
1177265236Sken/**
1178265236Sken * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0
1179265236Sken * @sc: per adapter object
1180265236Sken * @mpi_reply: reply mf payload returned from firmware
1181265236Sken * @config_page: contents of the config page
1182265236Sken * @page_address: form and handle value used to get page
1183265236Sken * Context: sleep.
1184265236Sken *
1185265236Sken * Returns 0 for success, non-zero for failure.
1186265236Sken */
1187265236Skenint
1188265236Skenmpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
1189265236Sken    *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1190265236Sken{
1191265236Sken	MPI2_CONFIG_REQUEST *request;
1192322661Sken	MPI2_CONFIG_REPLY *reply = NULL;
1193265236Sken	struct mpr_command *cm;
1194265236Sken	Mpi2RaidVolPage0_t *page = NULL;
1195265236Sken	int error = 0;
1196265236Sken	u16 ioc_status;
1197265236Sken
1198265236Sken	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1199265236Sken
1200265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
1201265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
1202265236Sken		    __LINE__);
1203265236Sken		error = EBUSY;
1204265236Sken		goto out;
1205265236Sken	}
1206265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1207265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1208265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
1209265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1210265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1211265236Sken	request->Header.PageNumber = 0;
1212319436Sslm	request->Header.PageLength = request->Header.PageVersion = 0;
1213265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1214265236Sken	cm->cm_data = NULL;
1215265236Sken
1216265236Sken	/*
1217265236Sken	 * This page must be polled because the IOC isn't ready yet when this
1218265236Sken	 * page is needed.
1219265236Sken	 */
1220322661Sken	error = mpr_request_polled(sc, &cm);
1221322661Sken	if (cm != NULL)
1222322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1223265236Sken	if (error || (reply == NULL)) {
1224265236Sken		/* FIXME */
1225265236Sken		/* If the poll returns error then we need to do diag reset */
1226265236Sken		printf("%s: poll for header completed with error %d",
1227265236Sken		    __func__, error);
1228265236Sken		error = ENXIO;
1229265236Sken		goto out;
1230265236Sken	}
1231265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1232265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1233265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1234265236Sken		/* FIXME */
1235265236Sken		/* If the poll returns error then we need to do diag reset */
1236265236Sken		printf("%s: header read with error; iocstatus = 0x%x\n",
1237265236Sken		    __func__, ioc_status);
1238265236Sken		error = ENXIO;
1239265236Sken		goto out;
1240265236Sken	}
1241265236Sken	/* We have to do free and alloc for the reply-free and reply-post
1242265236Sken	 * counters to match - Need to review the reply FIFO handling.
1243265236Sken	 */
1244265236Sken	mpr_free_command(sc, cm);
1245265236Sken
1246265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
1247265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
1248265236Sken		    __LINE__);
1249265236Sken		error = EBUSY;
1250265236Sken		goto out;
1251265236Sken	}
1252265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1253265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1254265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
1255265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1256265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1257265236Sken	request->Header.PageNumber = 0;
1258265236Sken	request->Header.PageLength = mpi_reply->Header.PageLength;
1259265236Sken	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1260265236Sken	request->PageAddress = page_address;
1261265236Sken	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1262265236Sken	cm->cm_sge = &request->PageBufferSGE;
1263265236Sken	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1264265236Sken	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1265265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1266265236Sken	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1267265236Sken	if (!page) {
1268265236Sken		printf("%s: page alloc failed\n", __func__);
1269265236Sken		error = ENOMEM;
1270265236Sken		goto out;
1271265236Sken	}
1272265236Sken	cm->cm_data = page;
1273265236Sken
1274265236Sken	/*
1275265236Sken	 * This page must be polled because the IOC isn't ready yet when this
1276265236Sken	 * page is needed.
1277265236Sken	 */
1278322661Sken	error = mpr_request_polled(sc, &cm);
1279322661Sken	if (cm != NULL)
1280322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1281265236Sken	if (error || (reply == NULL)) {
1282265236Sken		/* FIXME */
1283265236Sken		/* If the poll returns error then we need to do diag reset */
1284265236Sken		printf("%s: poll for page completed with error %d",
1285265236Sken		    __func__, error);
1286265236Sken		error = ENXIO;
1287265236Sken		goto out;
1288265236Sken	}
1289265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1290265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1291265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1292265236Sken		/* FIXME */
1293265236Sken		/* If the poll returns error then we need to do diag reset */
1294265236Sken		printf("%s: page read with error; iocstatus = 0x%x\n",
1295265236Sken		    __func__, ioc_status);
1296265236Sken		error = ENXIO;
1297265236Sken		goto out;
1298265236Sken	}
1299265236Sken	bcopy(page, config_page, cm->cm_length);
1300265236Skenout:
1301265236Sken	free(page, M_MPR);
1302265236Sken	if (cm)
1303265236Sken		mpr_free_command(sc, cm);
1304265236Sken	return (error);
1305265236Sken}
1306265236Sken
1307265236Sken/**
1308265236Sken * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1
1309265236Sken * @sc: per adapter object
1310265236Sken * @mpi_reply: reply mf payload returned from firmware
1311265236Sken * @config_page: contents of the config page
1312265236Sken * @form: GET_NEXT_HANDLE or HANDLE
1313265236Sken * @handle: volume handle
1314265236Sken * Context: sleep.
1315265236Sken *
1316265236Sken * Returns 0 for success, non-zero for failure.
1317265236Sken */
1318265236Skenint
1319265236Skenmpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t
1320265236Sken    *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1321265236Sken{
1322265236Sken	MPI2_CONFIG_REQUEST *request;
1323265236Sken	MPI2_CONFIG_REPLY *reply;
1324265236Sken	struct mpr_command *cm;
1325265236Sken	Mpi2RaidVolPage1_t *page = NULL;
1326265236Sken	int error = 0;
1327265236Sken	u16 ioc_status;
1328265236Sken
1329265236Sken	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1330265236Sken
1331265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
1332265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
1333265236Sken		    __LINE__);
1334265236Sken		error = EBUSY;
1335265236Sken		goto out;
1336265236Sken	}
1337265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1338265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1339265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
1340265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1341265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1342265236Sken	request->Header.PageNumber = 1;
1343319436Sslm	request->Header.PageLength = request->Header.PageVersion = 0;
1344265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1345265236Sken	cm->cm_data = NULL;
1346322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1347322661Sken	if (cm != NULL)
1348322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1349265236Sken	if (error || (reply == NULL)) {
1350265236Sken		/* FIXME */
1351265236Sken		/*
1352265236Sken		 * If the request returns an error then we need to do a diag
1353265236Sken		 * reset
1354265236Sken		 */
1355265236Sken		printf("%s: request for header completed with error %d",
1356265236Sken		    __func__, error);
1357265236Sken		error = ENXIO;
1358265236Sken		goto out;
1359265236Sken	}
1360265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1361265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1362265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1363265236Sken		/* FIXME */
1364265236Sken		/*
1365265236Sken		 * If the request returns an error then we need to do a diag
1366265236Sken		 * reset
1367265236Sken		 */
1368265236Sken		printf("%s: header read with error; iocstatus = 0x%x\n",
1369265236Sken		    __func__, ioc_status);
1370265236Sken		error = ENXIO;
1371265236Sken		goto out;
1372265236Sken	}
1373265236Sken	/* We have to do free and alloc for the reply-free and reply-post
1374265236Sken	 * counters to match - Need to review the reply FIFO handling.
1375265236Sken	 */
1376265236Sken	mpr_free_command(sc, cm);
1377265236Sken
1378265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
1379265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
1380265236Sken		    __LINE__);
1381265236Sken		error = EBUSY;
1382265236Sken		goto out;
1383265236Sken	}
1384265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1385265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1386265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
1387265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1388265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1389265236Sken	request->Header.PageNumber = 1;
1390265236Sken	request->Header.PageLength = mpi_reply->Header.PageLength;
1391265236Sken	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1392265236Sken	request->PageAddress = htole32(form | handle);
1393265236Sken	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1394265236Sken	cm->cm_sge = &request->PageBufferSGE;
1395265236Sken	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1396265236Sken	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1397265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1398265236Sken	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1399265236Sken	if (!page) {
1400265236Sken		printf("%s: page alloc failed\n", __func__);
1401265236Sken		error = ENOMEM;
1402265236Sken		goto out;
1403265236Sken	}
1404265236Sken	cm->cm_data = page;
1405265236Sken
1406322661Sken	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1407322661Sken	if (cm != NULL)
1408322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1409265236Sken	if (error || (reply == NULL)) {
1410265236Sken		/* FIXME */
1411265236Sken		/*
1412265236Sken		 * If the request returns an error then we need to do a diag
1413265236Sken		 * reset
1414265236Sken		 */
1415265236Sken		printf("%s: request for page completed with error %d",
1416265236Sken		    __func__, error);
1417265236Sken		error = ENXIO;
1418265236Sken		goto out;
1419265236Sken	}
1420265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1421265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1422265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1423265236Sken		/* FIXME */
1424265236Sken		/*
1425265236Sken		 * If the request returns an error then we need to do a diag
1426265236Sken		 * reset
1427265236Sken		 */
1428265236Sken		printf("%s: page read with error; iocstatus = 0x%x\n",
1429265236Sken		    __func__, ioc_status);
1430265236Sken		error = ENXIO;
1431265236Sken		goto out;
1432265236Sken	}
1433265236Sken	bcopy(page, config_page, MIN(cm->cm_length,
1434265236Sken	    sizeof(Mpi2RaidVolPage1_t)));
1435265236Skenout:
1436265236Sken	free(page, M_MPR);
1437265236Sken	if (cm)
1438265236Sken		mpr_free_command(sc, cm);
1439265236Sken	return (error);
1440265236Sken}
1441265236Sken
1442265236Sken/**
1443265236Sken * mpr_config_get_volume_wwid - returns wwid given the volume handle
1444265236Sken * @sc: per adapter object
1445265236Sken * @volume_handle: volume handle
1446265236Sken * @wwid: volume wwid
1447265236Sken * Context: sleep.
1448265236Sken *
1449265236Sken * Returns 0 for success, non-zero for failure.
1450265236Sken */
1451265236Skenint
1452265236Skenmpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid)
1453265236Sken{
1454265236Sken	Mpi2ConfigReply_t mpi_reply;
1455265236Sken	Mpi2RaidVolPage1_t raid_vol_pg1;
1456265236Sken
1457265236Sken	*wwid = 0;
1458265236Sken	if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1459265236Sken	    MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1460265236Sken		*wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1461265236Sken		    raid_vol_pg1.WWID.Low);
1462265236Sken		return 0;
1463265236Sken	} else
1464265236Sken		return -1;
1465265236Sken}
1466265236Sken
1467265236Sken/**
1468265236Sken * mpr_config_get_pd_pg0 - obtain raid phys disk page 0
1469265236Sken * @sc: per adapter object
1470265236Sken * @mpi_reply: reply mf payload returned from firmware
1471265236Sken * @config_page: contents of the config page
1472265236Sken * @page_address: form and handle value used to get page
1473265236Sken * Context: sleep.
1474265236Sken *
1475265236Sken * Returns 0 for success, non-zero for failure.
1476265236Sken */
1477265236Skenint
1478265236Skenmpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1479265236Sken    Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1480265236Sken{
1481265236Sken	MPI2_CONFIG_REQUEST *request;
1482322661Sken	MPI2_CONFIG_REPLY *reply = NULL;
1483265236Sken	struct mpr_command *cm;
1484265236Sken	Mpi2RaidPhysDiskPage0_t *page = NULL;
1485265236Sken	int error = 0;
1486265236Sken	u16 ioc_status;
1487265236Sken
1488265236Sken	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1489265236Sken
1490265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
1491265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
1492265236Sken		    __LINE__);
1493265236Sken		error = EBUSY;
1494265236Sken		goto out;
1495265236Sken	}
1496265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1497265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1498265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
1499265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1500265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1501265236Sken	request->Header.PageNumber = 0;
1502319436Sslm	request->Header.PageLength = request->Header.PageVersion = 0;
1503265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1504265236Sken	cm->cm_data = NULL;
1505265236Sken
1506265236Sken	/*
1507265236Sken	 * This page must be polled because the IOC isn't ready yet when this
1508265236Sken	 * page is needed.
1509265236Sken	 */
1510322661Sken	error = mpr_request_polled(sc, &cm);
1511322661Sken	if (cm != NULL)
1512322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1513265236Sken	if (error || (reply == NULL)) {
1514265236Sken		/* FIXME */
1515265236Sken		/* If the poll returns error then we need to do diag reset */
1516265236Sken		printf("%s: poll for header completed with error %d",
1517265236Sken		    __func__, error);
1518265236Sken		error = ENXIO;
1519265236Sken		goto out;
1520265236Sken	}
1521265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1522265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1523265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1524265236Sken		/* FIXME */
1525265236Sken		/* If the poll returns error then we need to do diag reset */
1526265236Sken		printf("%s: header read with error; iocstatus = 0x%x\n",
1527265236Sken		    __func__, ioc_status);
1528265236Sken		error = ENXIO;
1529265236Sken		goto out;
1530265236Sken	}
1531265236Sken	/* We have to do free and alloc for the reply-free and reply-post
1532265236Sken	 * counters to match - Need to review the reply FIFO handling.
1533265236Sken	 */
1534265236Sken	mpr_free_command(sc, cm);
1535265236Sken
1536265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL) {
1537265236Sken		printf("%s: command alloc failed @ line %d\n", __func__,
1538265236Sken		    __LINE__);
1539265236Sken		error = EBUSY;
1540265236Sken		goto out;
1541265236Sken	}
1542265236Sken	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1543265236Sken	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1544265236Sken	request->Function = MPI2_FUNCTION_CONFIG;
1545265236Sken	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1546265236Sken	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1547265236Sken	request->Header.PageNumber = 0;
1548265236Sken	request->Header.PageLength = mpi_reply->Header.PageLength;
1549265236Sken	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1550265236Sken	request->PageAddress = page_address;
1551265236Sken	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1552265236Sken	cm->cm_sge = &request->PageBufferSGE;
1553265236Sken	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1554265236Sken	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1555265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1556265236Sken	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1557265236Sken	if (!page) {
1558265236Sken		printf("%s: page alloc failed\n", __func__);
1559265236Sken		error = ENOMEM;
1560265236Sken		goto out;
1561265236Sken	}
1562265236Sken	cm->cm_data = page;
1563265236Sken
1564265236Sken	/*
1565265236Sken	 * This page must be polled because the IOC isn't ready yet when this
1566265236Sken	 * page is needed.
1567265236Sken	 */
1568322661Sken	error = mpr_request_polled(sc, &cm);
1569322661Sken	if (cm != NULL)
1570322661Sken		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1571265236Sken	if (error || (reply == NULL)) {
1572265236Sken		/* FIXME */
1573265236Sken		/* If the poll returns error then we need to do diag reset */
1574265236Sken		printf("%s: poll for page completed with error %d",
1575265236Sken		    __func__, error);
1576265236Sken		error = ENXIO;
1577265236Sken		goto out;
1578265236Sken	}
1579265236Sken	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1580265236Sken	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1581265236Sken	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1582265236Sken		/* FIXME */
1583265236Sken		/* If the poll returns error then we need to do diag reset */
1584265236Sken		printf("%s: page read with error; iocstatus = 0x%x\n",
1585265236Sken		    __func__, ioc_status);
1586265236Sken		error = ENXIO;
1587265236Sken		goto out;
1588265236Sken	}
1589265236Sken	bcopy(page, config_page, MIN(cm->cm_length,
1590265236Sken	    sizeof(Mpi2RaidPhysDiskPage0_t)));
1591265236Skenout:
1592265236Sken	free(page, M_MPR);
1593265236Sken	if (cm)
1594265236Sken		mpr_free_command(sc, cm);
1595265236Sken	return (error);
1596265236Sken}
1597