xref: /dragonfly/sys/dev/raid/mps/mps_config.c (revision f23afe8b)
1c12c399aSSascha Wildner /*-
2c12c399aSSascha Wildner  * Copyright (c) 2011 LSI Corp.
3c12c399aSSascha Wildner  * All rights reserved.
4c12c399aSSascha Wildner  *
5c12c399aSSascha Wildner  * Redistribution and use in source and binary forms, with or without
6c12c399aSSascha Wildner  * modification, are permitted provided that the following conditions
7c12c399aSSascha Wildner  * are met:
8c12c399aSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
9c12c399aSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
10c12c399aSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
11c12c399aSSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
12c12c399aSSascha Wildner  *    documentation and/or other materials provided with the distribution.
13c12c399aSSascha Wildner  *
14c12c399aSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15c12c399aSSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16c12c399aSSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17c12c399aSSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18c12c399aSSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c12c399aSSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20c12c399aSSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21c12c399aSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22c12c399aSSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23c12c399aSSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24c12c399aSSascha Wildner  * SUCH DAMAGE.
25c12c399aSSascha Wildner  *
26c12c399aSSascha Wildner  * LSI MPT-Fusion Host Adapter FreeBSD
27c12c399aSSascha Wildner  *
28c12c399aSSascha Wildner  * $FreeBSD: src/sys/dev/mps/mps_config.c,v 1.1 2012/01/26 18:17:21 ken Exp $
29c12c399aSSascha Wildner  */
30c12c399aSSascha Wildner 
31c12c399aSSascha Wildner /* TODO Move headers to mpsvar */
32c12c399aSSascha Wildner #include <sys/types.h>
33c12c399aSSascha Wildner #include <sys/param.h>
34c12c399aSSascha Wildner #include <sys/lock.h>
35c12c399aSSascha Wildner #include <sys/systm.h>
36c12c399aSSascha Wildner #include <sys/kernel.h>
37c12c399aSSascha Wildner #include <sys/malloc.h>
38c12c399aSSascha Wildner #include <sys/kthread.h>
39c12c399aSSascha Wildner #include <sys/taskqueue.h>
40c12c399aSSascha Wildner #include <sys/bus.h>
41c12c399aSSascha Wildner #include <sys/endian.h>
42c12c399aSSascha Wildner #include <sys/sysctl.h>
43c12c399aSSascha Wildner #include <sys/eventhandler.h>
44c12c399aSSascha Wildner #include <sys/uio.h>
45c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_type.h>
46c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2.h>
47c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_ioc.h>
48c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_sas.h>
49c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_cnfg.h>
50c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_init.h>
51c12c399aSSascha Wildner #include <dev/raid/mps/mpi/mpi2_tool.h>
52c12c399aSSascha Wildner #include <dev/raid/mps/mps_ioctl.h>
53c12c399aSSascha Wildner #include <dev/raid/mps/mpsvar.h>
54c12c399aSSascha Wildner 
55c12c399aSSascha Wildner /**
56c12c399aSSascha Wildner  * mps_config_get_ioc_pg8 - obtain ioc page 8
57c12c399aSSascha Wildner  * @sc: per adapter object
58c12c399aSSascha Wildner  * @mpi_reply: reply mf payload returned from firmware
59c12c399aSSascha Wildner  * @config_page: contents of the config page
60c12c399aSSascha Wildner  * Context: sleep.
61c12c399aSSascha Wildner  *
62c12c399aSSascha Wildner  * Returns 0 for success, non-zero for failure.
63c12c399aSSascha Wildner  */
64c12c399aSSascha Wildner int
mps_config_get_ioc_pg8(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2IOCPage8_t * config_page)65c12c399aSSascha Wildner mps_config_get_ioc_pg8(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
66c12c399aSSascha Wildner     Mpi2IOCPage8_t *config_page)
67c12c399aSSascha Wildner {
68c12c399aSSascha Wildner 	MPI2_CONFIG_REQUEST *request;
69c12c399aSSascha Wildner 	MPI2_CONFIG_REPLY *reply;
70c12c399aSSascha Wildner 	struct mps_command *cm;
71c12c399aSSascha Wildner 	MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
72c12c399aSSascha Wildner 	int error = 0;
73c12c399aSSascha Wildner 	u16 ioc_status;
74c12c399aSSascha Wildner 
75c12c399aSSascha Wildner 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
76c12c399aSSascha Wildner 
77c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
78c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
79c12c399aSSascha Wildner 		    __LINE__);
80c12c399aSSascha Wildner 		error = EBUSY;
81c12c399aSSascha Wildner 		goto out;
82c12c399aSSascha Wildner 	}
83c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
84c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
85c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
86c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
87c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
88c12c399aSSascha Wildner 	request->Header.PageNumber = 8;
89c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
90c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
91c12c399aSSascha Wildner 	cm->cm_data = NULL;
92c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
93c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
94c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
95c12c399aSSascha Wildner 		/* FIXME */
96c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
97c12c399aSSascha Wildner 		kprintf("%s: poll for header completed with error %d",
98c12c399aSSascha Wildner 		    __func__, error);
99c12c399aSSascha Wildner 		error = ENXIO;
100c12c399aSSascha Wildner 		goto out;
101c12c399aSSascha Wildner 	}
102c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
103c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
104c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
105c12c399aSSascha Wildner 		/* FIXME */
106c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
107c12c399aSSascha Wildner 		kprintf("%s: header read with error; iocstatus = 0x%x\n",
108c12c399aSSascha Wildner 		    __func__, ioc_status);
109c12c399aSSascha Wildner 		error = ENXIO;
110c12c399aSSascha Wildner 		goto out;
111c12c399aSSascha Wildner 	}
112c12c399aSSascha Wildner 	/* We have to do free and alloc for the reply-free and reply-post
113c12c399aSSascha Wildner 	 * counters to match - Need to review the reply FIFO handling.
114c12c399aSSascha Wildner 	 */
115c12c399aSSascha Wildner 	mps_free_command(sc, cm);
116c12c399aSSascha Wildner 
117c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
118c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
119c12c399aSSascha Wildner 		    __LINE__);
120c12c399aSSascha Wildner 		error = EBUSY;
121c12c399aSSascha Wildner 		goto out;
122c12c399aSSascha Wildner 	}
123c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
124c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
125c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
126c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
127c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
128c12c399aSSascha Wildner 	request->Header.PageNumber = 8;
129c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
130c12c399aSSascha Wildner 	request->Header.PageLength = mpi_reply->Header.PageLength;
131c12c399aSSascha Wildner 	cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
132c12c399aSSascha Wildner 	cm->cm_sge = &request->PageBufferSGE;
133c12c399aSSascha Wildner 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
134c12c399aSSascha Wildner 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
135c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
136*3eb4d33cSMatthew Dillon 	page = kmalloc((cm->cm_length), M_MPT2, M_ZERO | M_INTWAIT);
137c12c399aSSascha Wildner 	if (!page) {
138c12c399aSSascha Wildner 		kprintf("%s: page alloc failed\n", __func__);
139c12c399aSSascha Wildner 		error = ENOMEM;
140c12c399aSSascha Wildner 		goto out;
141c12c399aSSascha Wildner 	}
142c12c399aSSascha Wildner 	cm->cm_data = page;
143c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
144c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
145c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
146c12c399aSSascha Wildner 		/* FIXME */
147c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
148c12c399aSSascha Wildner 		kprintf("%s: poll for page completed with error %d",
149c12c399aSSascha Wildner 		    __func__, error);
150c12c399aSSascha Wildner 		error = ENXIO;
151c12c399aSSascha Wildner 		goto out;
152c12c399aSSascha Wildner 	}
153c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
154c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
155c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
156c12c399aSSascha Wildner 		/* FIXME */
157c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
158c12c399aSSascha Wildner 		kprintf("%s: page read with error; iocstatus = 0x%x\n",
159c12c399aSSascha Wildner 		    __func__, ioc_status);
160c12c399aSSascha Wildner 		error = ENXIO;
161c12c399aSSascha Wildner 		goto out;
162c12c399aSSascha Wildner 	}
163c12c399aSSascha Wildner 	bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
164c12c399aSSascha Wildner 
165c12c399aSSascha Wildner out:
166c12c399aSSascha Wildner 	kfree(page, M_MPT2);
167c12c399aSSascha Wildner 	if (cm)
168c12c399aSSascha Wildner 		mps_free_command(sc, cm);
169c12c399aSSascha Wildner 	return (error);
170c12c399aSSascha Wildner }
171c12c399aSSascha Wildner 
172c12c399aSSascha Wildner /**
173c12c399aSSascha Wildner  * mps_config_get_man_pg10 - obtain Manufacturing Page 10 data and set flags
174c12c399aSSascha Wildner  *   accordingly.  Currently, this page does not need to return to caller.
175c12c399aSSascha Wildner  * @sc: per adapter object
176c12c399aSSascha Wildner  * @mpi_reply: reply mf payload returned from firmware
177c12c399aSSascha Wildner  * Context: sleep.
178c12c399aSSascha Wildner  *
179c12c399aSSascha Wildner  * Returns 0 for success, non-zero for failure.
180c12c399aSSascha Wildner  */
181c12c399aSSascha Wildner int
mps_config_get_man_pg10(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply)182c12c399aSSascha Wildner mps_config_get_man_pg10(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply)
183c12c399aSSascha Wildner {
184c12c399aSSascha Wildner 	MPI2_CONFIG_REQUEST *request;
185c12c399aSSascha Wildner 	MPI2_CONFIG_REPLY *reply;
186c12c399aSSascha Wildner 	struct mps_command *cm;
187c12c399aSSascha Wildner 	pMpi2ManufacturingPagePS_t page = NULL;
188c12c399aSSascha Wildner 	uint32_t *pPS_info;
189c12c399aSSascha Wildner 	uint8_t OEM_Value = 0;
190c12c399aSSascha Wildner 	int error = 0;
191c12c399aSSascha Wildner 	u16 ioc_status;
192c12c399aSSascha Wildner 
193c12c399aSSascha Wildner 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
194c12c399aSSascha Wildner 
195c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
196c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
197c12c399aSSascha Wildner 		    __LINE__);
198c12c399aSSascha Wildner 		error = EBUSY;
199c12c399aSSascha Wildner 		goto out;
200c12c399aSSascha Wildner 	}
201c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
202c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
203c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
204c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
205c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
206c12c399aSSascha Wildner 	request->Header.PageNumber = 10;
207c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
208c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
209c12c399aSSascha Wildner 	cm->cm_data = NULL;
210c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
211c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
212c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
213c12c399aSSascha Wildner 		/* FIXME */
214c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
215c12c399aSSascha Wildner 		kprintf("%s: poll for header completed with error %d",
216c12c399aSSascha Wildner 		    __func__, error);
217c12c399aSSascha Wildner 		error = ENXIO;
218c12c399aSSascha Wildner 		goto out;
219c12c399aSSascha Wildner 	}
220c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
221c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
222c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
223c12c399aSSascha Wildner 		/* FIXME */
224c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
225c12c399aSSascha Wildner 		kprintf("%s: header read with error; iocstatus = 0x%x\n",
226c12c399aSSascha Wildner 		    __func__, ioc_status);
227c12c399aSSascha Wildner 		error = ENXIO;
228c12c399aSSascha Wildner 		goto out;
229c12c399aSSascha Wildner 	}
230c12c399aSSascha Wildner 	/* We have to do free and alloc for the reply-free and reply-post
231c12c399aSSascha Wildner 	 * counters to match - Need to review the reply FIFO handling.
232c12c399aSSascha Wildner 	 */
233c12c399aSSascha Wildner 	mps_free_command(sc, cm);
234c12c399aSSascha Wildner 
235c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
236c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
237c12c399aSSascha Wildner 		    __LINE__);
238c12c399aSSascha Wildner 		error = EBUSY;
239c12c399aSSascha Wildner 		goto out;
240c12c399aSSascha Wildner 	}
241c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
242c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
243c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
244c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
245c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
246c12c399aSSascha Wildner 	request->Header.PageNumber = 10;
247c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_MANUFACTURING10_PAGEVERSION;
248c12c399aSSascha Wildner 	request->Header.PageLength = mpi_reply->Header.PageLength;
249c12c399aSSascha Wildner 	cm->cm_length =  le16toh(mpi_reply->Header.PageLength) * 4;
250c12c399aSSascha Wildner 	cm->cm_sge = &request->PageBufferSGE;
251c12c399aSSascha Wildner 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
252c12c399aSSascha Wildner 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
253c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
254*3eb4d33cSMatthew Dillon 	page = kmalloc(MPS_MAN_PAGE10_SIZE, M_MPT2, M_ZERO | M_INTWAIT);
255c12c399aSSascha Wildner 	if (!page) {
256c12c399aSSascha Wildner 		kprintf("%s: page alloc failed\n", __func__);
257c12c399aSSascha Wildner 		error = ENOMEM;
258c12c399aSSascha Wildner 		goto out;
259c12c399aSSascha Wildner 	}
260c12c399aSSascha Wildner 	cm->cm_data = page;
261c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
262c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
263c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
264c12c399aSSascha Wildner 		/* FIXME */
265c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
266c12c399aSSascha Wildner 		kprintf("%s: poll for page completed with error %d",
267c12c399aSSascha Wildner 		    __func__, error);
268c12c399aSSascha Wildner 		error = ENXIO;
269c12c399aSSascha Wildner 		goto out;
270c12c399aSSascha Wildner 	}
271c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
272c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
273c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
274c12c399aSSascha Wildner 		/* FIXME */
275c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
276c12c399aSSascha Wildner 		kprintf("%s: page read with error; iocstatus = 0x%x\n",
277c12c399aSSascha Wildner 		    __func__, ioc_status);
278c12c399aSSascha Wildner 		error = ENXIO;
279c12c399aSSascha Wildner 		goto out;
280c12c399aSSascha Wildner 	}
281c12c399aSSascha Wildner 
282c12c399aSSascha Wildner 	/*
283c12c399aSSascha Wildner 	 * If OEM ID is unknown, fail the request.
284c12c399aSSascha Wildner 	 */
285c12c399aSSascha Wildner 	sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
286c12c399aSSascha Wildner 	OEM_Value = (uint8_t)(page->ProductSpecificInfo & 0x000000FF);
287c12c399aSSascha Wildner 	if (OEM_Value != MPS_WD_LSI_OEM) {
288c12c399aSSascha Wildner 		mps_dprint(sc, MPS_FAULT, "Unknown OEM value for WarpDrive "
289c12c399aSSascha Wildner 		    "(0x%x)\n", OEM_Value);
290c12c399aSSascha Wildner 		error = ENXIO;
291c12c399aSSascha Wildner 		goto out;
292c12c399aSSascha Wildner 	}
293c12c399aSSascha Wildner 
294c12c399aSSascha Wildner 	/*
295c12c399aSSascha Wildner 	 * Set the phys disks hide/expose value.
296c12c399aSSascha Wildner 	 */
29790ff74f1SSascha Wildner 	pPS_info = &page->ProductSpecificInfo;
298c12c399aSSascha Wildner 	sc->WD_hide_expose = (uint8_t)(pPS_info[5]);
299c12c399aSSascha Wildner 	sc->WD_hide_expose &= MPS_WD_HIDE_EXPOSE_MASK;
300c12c399aSSascha Wildner 	if ((sc->WD_hide_expose != MPS_WD_HIDE_ALWAYS) &&
301c12c399aSSascha Wildner 	    (sc->WD_hide_expose != MPS_WD_EXPOSE_ALWAYS) &&
302c12c399aSSascha Wildner 	    (sc->WD_hide_expose != MPS_WD_HIDE_IF_VOLUME)) {
303c12c399aSSascha Wildner 		mps_dprint(sc, MPS_FAULT, "Unknown value for WarpDrive "
304c12c399aSSascha Wildner 		    "hide/expose: 0x%x\n", sc->WD_hide_expose);
305c12c399aSSascha Wildner 		error = ENXIO;
306c12c399aSSascha Wildner 		goto out;
307c12c399aSSascha Wildner 	}
308c12c399aSSascha Wildner 
309c12c399aSSascha Wildner out:
310c12c399aSSascha Wildner 	kfree(page, M_MPT2);
311c12c399aSSascha Wildner 	if (cm)
312c12c399aSSascha Wildner 		mps_free_command(sc, cm);
313c12c399aSSascha Wildner 	return (error);
314c12c399aSSascha Wildner }
315c12c399aSSascha Wildner 
316c12c399aSSascha Wildner /**
317c12c399aSSascha Wildner  * mps_base_static_config_pages - static start of day config pages.
318c12c399aSSascha Wildner  * @sc: per adapter object
319c12c399aSSascha Wildner  *
320c12c399aSSascha Wildner  * Return nothing.
321c12c399aSSascha Wildner  */
322c12c399aSSascha Wildner void
mps_base_static_config_pages(struct mps_softc * sc)323c12c399aSSascha Wildner mps_base_static_config_pages(struct mps_softc *sc)
324c12c399aSSascha Wildner {
325c12c399aSSascha Wildner 	Mpi2ConfigReply_t	mpi_reply;
326c12c399aSSascha Wildner 	int			retry;
327c12c399aSSascha Wildner 
328c12c399aSSascha Wildner 	retry = 0;
329c12c399aSSascha Wildner 	while (mps_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
330c12c399aSSascha Wildner 		retry++;
331c12c399aSSascha Wildner 		if (retry > 5) {
332c12c399aSSascha Wildner 			/* We need to Handle this situation */
333c12c399aSSascha Wildner 			/*FIXME*/
334c12c399aSSascha Wildner 			break;
335c12c399aSSascha Wildner 		}
336c12c399aSSascha Wildner 	}
337c12c399aSSascha Wildner }
338c12c399aSSascha Wildner 
339c12c399aSSascha Wildner /**
340c12c399aSSascha Wildner  * mps_wd_config_pages - get info required to support WarpDrive.  This needs to
341c12c399aSSascha Wildner  *    be called after discovery is complete to guarentee that IR info is there.
342c12c399aSSascha Wildner  * @sc: per adapter object
343c12c399aSSascha Wildner  *
344c12c399aSSascha Wildner  * Return nothing.
345c12c399aSSascha Wildner  */
346c12c399aSSascha Wildner void
mps_wd_config_pages(struct mps_softc * sc)347c12c399aSSascha Wildner mps_wd_config_pages(struct mps_softc *sc)
348c12c399aSSascha Wildner {
349c12c399aSSascha Wildner 	Mpi2ConfigReply_t	mpi_reply;
350c12c399aSSascha Wildner 	pMpi2RaidVolPage0_t	raid_vol_pg0 = NULL;
351c12c399aSSascha Wildner 	Mpi2RaidPhysDiskPage0_t	phys_disk_pg0;
352c12c399aSSascha Wildner 	pMpi2RaidVol0PhysDisk_t	pRVPD;
353c12c399aSSascha Wildner 	uint32_t		stripe_size, phys_disk_page_address;
354c12c399aSSascha Wildner 	uint16_t		block_size;
355c12c399aSSascha Wildner 	uint8_t			index, stripe_exp = 0, block_exp = 0;
356c12c399aSSascha Wildner 
357c12c399aSSascha Wildner 	/*
358c12c399aSSascha Wildner 	 * Get the WD settings from manufacturing page 10 if using a WD HBA.
359c12c399aSSascha Wildner 	 * This will be used to determine if phys disks should always be
360c12c399aSSascha Wildner 	 * hidden, hidden only if part of a WD volume, or never hidden.  Also,
361c12c399aSSascha Wildner 	 * get the WD RAID Volume info and fail if volume does not exist or if
362c12c399aSSascha Wildner 	 * volume does not meet the requirements for a WD volume.  No retry
363c12c399aSSascha Wildner 	 * here.  Just default to HIDE ALWAYS if man Page10 fails, or clear WD
364c12c399aSSascha Wildner 	 * Valid flag if Volume info fails.
365c12c399aSSascha Wildner 	 */
366c12c399aSSascha Wildner 	sc->WD_valid_config = FALSE;
367c12c399aSSascha Wildner 	if (sc->mps_flags & MPS_FLAGS_WD_AVAILABLE) {
368c12c399aSSascha Wildner 		if (mps_config_get_man_pg10(sc, &mpi_reply)) {
369c12c399aSSascha Wildner 			mps_dprint(sc, MPS_FAULT,
370c12c399aSSascha Wildner 			    "mps_config_get_man_pg10 failed! Using 0 (Hide "
371c12c399aSSascha Wildner 			    "Always) for WarpDrive hide/expose value.\n");
372c12c399aSSascha Wildner 			sc->WD_hide_expose = MPS_WD_HIDE_ALWAYS;
373c12c399aSSascha Wildner 		}
374c12c399aSSascha Wildner 
375c12c399aSSascha Wildner 		/*
376c12c399aSSascha Wildner 		 * Get first RAID Volume Page0 using GET_NEXT_HANDLE.
377c12c399aSSascha Wildner 		 */
378c12c399aSSascha Wildner 		raid_vol_pg0 = kmalloc(sizeof(Mpi2RaidVolPage0_t) +
379c12c399aSSascha Wildner 		    (sizeof(Mpi2RaidVol0PhysDisk_t) * MPS_MAX_DISKS_IN_VOL),
380*3eb4d33cSMatthew Dillon 		    M_MPT2, M_ZERO | M_INTWAIT);
381c12c399aSSascha Wildner 		if (!raid_vol_pg0) {
382c12c399aSSascha Wildner 			kprintf("%s: page alloc failed\n", __func__);
383c12c399aSSascha Wildner 			goto out;
384c12c399aSSascha Wildner 		}
385c12c399aSSascha Wildner 
386c12c399aSSascha Wildner 		if (mps_config_get_raid_volume_pg0(sc, &mpi_reply, raid_vol_pg0,
387c12c399aSSascha Wildner 		    0x0000FFFF)) {
388c12c399aSSascha Wildner 			mps_dprint(sc, MPS_INFO,
389c12c399aSSascha Wildner 			    "mps_config_get_raid_volume_pg0 failed! Assuming "
390c12c399aSSascha Wildner 			    "WarpDrive IT mode.\n");
391c12c399aSSascha Wildner 			goto out;
392c12c399aSSascha Wildner 		}
393c12c399aSSascha Wildner 
394c12c399aSSascha Wildner 		/*
395c12c399aSSascha Wildner 		 * Check for valid WD configuration:
396c12c399aSSascha Wildner 		 *   volume type is RAID0
397c12c399aSSascha Wildner 		 *   number of phys disks in the volume is no more than 8
398c12c399aSSascha Wildner 		 */
399c12c399aSSascha Wildner 		if ((raid_vol_pg0->VolumeType != MPI2_RAID_VOL_TYPE_RAID0) ||
400c12c399aSSascha Wildner 		    (raid_vol_pg0->NumPhysDisks > 8)) {
401c12c399aSSascha Wildner 			mps_dprint(sc, MPS_FAULT,
402c12c399aSSascha Wildner 			    "Invalid WarpDrive configuration. Direct Drive I/O "
403c12c399aSSascha Wildner 			    "will not be used.\n");
404c12c399aSSascha Wildner 			goto out;
405c12c399aSSascha Wildner 		}
406c12c399aSSascha Wildner 
407c12c399aSSascha Wildner 		/*
408c12c399aSSascha Wildner 		 * Save the WD RAID data to be used during WD I/O.
409c12c399aSSascha Wildner 		 */
410c12c399aSSascha Wildner 		sc->DD_max_lba = le64toh((uint64_t)raid_vol_pg0->MaxLBA.High <<
411c12c399aSSascha Wildner 		    32 | (uint64_t)raid_vol_pg0->MaxLBA.Low);
412c12c399aSSascha Wildner 		sc->DD_num_phys_disks = raid_vol_pg0->NumPhysDisks;
413c12c399aSSascha Wildner 		sc->DD_dev_handle = raid_vol_pg0->DevHandle;
414c12c399aSSascha Wildner 		sc->DD_stripe_size = raid_vol_pg0->StripeSize;
415c12c399aSSascha Wildner 		sc->DD_block_size = raid_vol_pg0->BlockSize;
416c12c399aSSascha Wildner 
417c12c399aSSascha Wildner 		/*
418c12c399aSSascha Wildner 		 * Find power of 2 of stripe size and set this as the exponent.
419c12c399aSSascha Wildner 		 * Fail if stripe size is 0.
420c12c399aSSascha Wildner 		 */
421c12c399aSSascha Wildner 		stripe_size = raid_vol_pg0->StripeSize;
422c12c399aSSascha Wildner 		for (index = 0; index < 32; index++) {
423c12c399aSSascha Wildner 			if (stripe_size & 1)
424c12c399aSSascha Wildner 				break;
425c12c399aSSascha Wildner 			stripe_exp++;
426c12c399aSSascha Wildner 			stripe_size >>= 1;
427c12c399aSSascha Wildner 		}
428c12c399aSSascha Wildner 		if (index == 32) {
429c12c399aSSascha Wildner 			mps_dprint(sc, MPS_FAULT,
430c12c399aSSascha Wildner 			    "RAID Volume's stripe size is 0. Direct Drive I/O "
431c12c399aSSascha Wildner 			    "will not be used.\n");
432c12c399aSSascha Wildner 			goto out;
433c12c399aSSascha Wildner 		}
434c12c399aSSascha Wildner 		sc->DD_stripe_exponent = stripe_exp;
435c12c399aSSascha Wildner 
436c12c399aSSascha Wildner 		/*
437c12c399aSSascha Wildner 		 * Find power of 2 of block size and set this as the exponent.
438c12c399aSSascha Wildner 		 * Fail if block size is 0.
439c12c399aSSascha Wildner 		 */
440c12c399aSSascha Wildner 		block_size = raid_vol_pg0->BlockSize;
441c12c399aSSascha Wildner 		for (index = 0; index < 16; index++) {
442c12c399aSSascha Wildner 			if (block_size & 1)
443c12c399aSSascha Wildner 				break;
444c12c399aSSascha Wildner 			block_exp++;
445c12c399aSSascha Wildner 			block_size >>= 1;
446c12c399aSSascha Wildner 		}
447c12c399aSSascha Wildner 		if (index == 16) {
448c12c399aSSascha Wildner 			mps_dprint(sc, MPS_FAULT,
449c12c399aSSascha Wildner 			    "RAID Volume's block size is 0. Direct Drive I/O "
450c12c399aSSascha Wildner 			    "will not be used.\n");
451c12c399aSSascha Wildner 			goto out;
452c12c399aSSascha Wildner 		}
453c12c399aSSascha Wildner 		sc->DD_block_exponent = block_exp;
454c12c399aSSascha Wildner 
455c12c399aSSascha Wildner 		/*
456c12c399aSSascha Wildner 		 * Loop through all of the volume's Phys Disks to map the phys
457c12c399aSSascha Wildner 		 * disk number into the columm map.  This is used during Direct
458c12c399aSSascha Wildner 		 * Drive I/O to send the request to the correct SSD.
459c12c399aSSascha Wildner 		 */
460c12c399aSSascha Wildner 		pRVPD = (pMpi2RaidVol0PhysDisk_t)&raid_vol_pg0->PhysDisk;
461c12c399aSSascha Wildner 		for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
462c12c399aSSascha Wildner 			sc->DD_column_map[pRVPD->PhysDiskMap].phys_disk_num =
463c12c399aSSascha Wildner 			    pRVPD->PhysDiskNum;
464c12c399aSSascha Wildner 			pRVPD++;
465c12c399aSSascha Wildner 		}
466c12c399aSSascha Wildner 
467c12c399aSSascha Wildner 		/*
468c12c399aSSascha Wildner 		 * Get second RAID Volume Page0 using previous handle.  This
469c12c399aSSascha Wildner 		 * page should not exist.  If it does, must not proceed with WD
470c12c399aSSascha Wildner 		 * handling.
471c12c399aSSascha Wildner 		 */
472c12c399aSSascha Wildner 		if (mps_config_get_raid_volume_pg0(sc, &mpi_reply,
473c12c399aSSascha Wildner 		    raid_vol_pg0, (u32)raid_vol_pg0->DevHandle)) {
474c12c399aSSascha Wildner 			if (mpi_reply.IOCStatus !=
475c12c399aSSascha Wildner 			    MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
476c12c399aSSascha Wildner 				mps_dprint(sc, MPS_FAULT,
477c12c399aSSascha Wildner 				    "Multiple RAID Volume Page0! Direct Drive "
478c12c399aSSascha Wildner 				    "I/O will not be used.\n");
479c12c399aSSascha Wildner 				goto out;
480c12c399aSSascha Wildner 			}
481c12c399aSSascha Wildner 		} else {
482c12c399aSSascha Wildner 			mps_dprint(sc, MPS_FAULT,
483c12c399aSSascha Wildner 			    "Multiple volumes! Direct Drive I/O will not be "
484c12c399aSSascha Wildner 			    "used.\n");
485c12c399aSSascha Wildner 			goto out;
486c12c399aSSascha Wildner 		}
487c12c399aSSascha Wildner 
488c12c399aSSascha Wildner 		/*
489c12c399aSSascha Wildner 		 * Get RAID Volume Phys Disk Page 0 for all SSDs in the volume.
490c12c399aSSascha Wildner 		 */
491c12c399aSSascha Wildner 		for (index = 0; index < raid_vol_pg0->NumPhysDisks; index++) {
492c12c399aSSascha Wildner 			phys_disk_page_address =
493c12c399aSSascha Wildner 			    MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM +
494c12c399aSSascha Wildner 			    sc->DD_column_map[index].phys_disk_num;
495c12c399aSSascha Wildner 			if (mps_config_get_raid_pd_pg0(sc, &mpi_reply,
496c12c399aSSascha Wildner 			    &phys_disk_pg0, phys_disk_page_address)) {
497c12c399aSSascha Wildner 				mps_dprint(sc, MPS_FAULT,
498c12c399aSSascha Wildner 				    "mps_config_get_raid_pd_pg0 failed! Direct "
499c12c399aSSascha Wildner 				    "Drive I/O will not be used.\n");
500c12c399aSSascha Wildner 				goto out;
501c12c399aSSascha Wildner 			}
502c12c399aSSascha Wildner 			if (phys_disk_pg0.DevHandle == 0xFFFF) {
503c12c399aSSascha Wildner 				mps_dprint(sc, MPS_FAULT,
504c12c399aSSascha Wildner 				    "Invalid Phys Disk DevHandle! Direct Drive "
505c12c399aSSascha Wildner 				    "I/O will not be used.\n");
506c12c399aSSascha Wildner 				goto out;
507c12c399aSSascha Wildner 			}
508c12c399aSSascha Wildner 			sc->DD_column_map[index].dev_handle =
509c12c399aSSascha Wildner 			    phys_disk_pg0.DevHandle;
510c12c399aSSascha Wildner 		}
511c12c399aSSascha Wildner 		sc->WD_valid_config = TRUE;
512c12c399aSSascha Wildner out:
513c12c399aSSascha Wildner 		if (raid_vol_pg0)
514c12c399aSSascha Wildner 			kfree(raid_vol_pg0, M_MPT2);
515c12c399aSSascha Wildner 	}
516c12c399aSSascha Wildner }
517c12c399aSSascha Wildner 
518c12c399aSSascha Wildner /**
519c12c399aSSascha Wildner  * mps_config_get_dpm_pg0 - obtain driver persistent mapping page0
520c12c399aSSascha Wildner  * @sc: per adapter object
521c12c399aSSascha Wildner  * @mpi_reply: reply mf payload returned from firmware
522c12c399aSSascha Wildner  * @config_page: contents of the config page
523c12c399aSSascha Wildner  * @sz: size of buffer passed in config_page
524c12c399aSSascha Wildner  * Context: sleep.
525c12c399aSSascha Wildner  *
526c12c399aSSascha Wildner  * Returns 0 for success, non-zero for failure.
527c12c399aSSascha Wildner  */
528c12c399aSSascha Wildner int
mps_config_get_dpm_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 sz)529c12c399aSSascha Wildner mps_config_get_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
530c12c399aSSascha Wildner     Mpi2DriverMappingPage0_t *config_page, u16 sz)
531c12c399aSSascha Wildner {
532c12c399aSSascha Wildner 	MPI2_CONFIG_REQUEST *request;
533c12c399aSSascha Wildner 	MPI2_CONFIG_REPLY *reply;
534c12c399aSSascha Wildner 	struct mps_command *cm;
535c12c399aSSascha Wildner 	Mpi2DriverMappingPage0_t *page = NULL;
536c12c399aSSascha Wildner 	int error = 0;
537c12c399aSSascha Wildner 	u16 ioc_status;
538c12c399aSSascha Wildner 
539c12c399aSSascha Wildner 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
540c12c399aSSascha Wildner 
541c12c399aSSascha Wildner 	memset(config_page, 0, sz);
542c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
543c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
544c12c399aSSascha Wildner 		    __LINE__);
545c12c399aSSascha Wildner 		error = EBUSY;
546c12c399aSSascha Wildner 		goto out;
547c12c399aSSascha Wildner 	}
548c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
549c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
550c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
551c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
552c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
553c12c399aSSascha Wildner 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
554c12c399aSSascha Wildner 	request->Header.PageNumber = 0;
555c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
556c12c399aSSascha Wildner 	request->PageAddress = sc->max_dpm_entries <<
557c12c399aSSascha Wildner 	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
558c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
559c12c399aSSascha Wildner 	cm->cm_data = NULL;
560c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
561c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
562c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
563c12c399aSSascha Wildner 		/* FIXME */
564c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
565c12c399aSSascha Wildner 		kprintf("%s: poll for header completed with error %d",
566c12c399aSSascha Wildner 		    __func__, error);
567c12c399aSSascha Wildner 		error = ENXIO;
568c12c399aSSascha Wildner 		goto out;
569c12c399aSSascha Wildner 	}
570c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
571c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
572c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
573c12c399aSSascha Wildner 		/* FIXME */
574c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
575c12c399aSSascha Wildner 		kprintf("%s: header read with error; iocstatus = 0x%x\n",
576c12c399aSSascha Wildner 		    __func__, ioc_status);
577c12c399aSSascha Wildner 		error = ENXIO;
578c12c399aSSascha Wildner 		goto out;
579c12c399aSSascha Wildner 	}
580c12c399aSSascha Wildner 	/* We have to do free and alloc for the reply-free and reply-post
581c12c399aSSascha Wildner 	 * counters to match - Need to review the reply FIFO handling.
582c12c399aSSascha Wildner 	 */
583c12c399aSSascha Wildner 	mps_free_command(sc, cm);
584c12c399aSSascha Wildner 
585c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
586c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
587c12c399aSSascha Wildner 		    __LINE__);
588c12c399aSSascha Wildner 		error = EBUSY;
589c12c399aSSascha Wildner 		goto out;
590c12c399aSSascha Wildner 	}
591c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
592c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
593c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
594c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
595c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
596c12c399aSSascha Wildner 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
597c12c399aSSascha Wildner 	request->Header.PageNumber = 0;
598c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
599c12c399aSSascha Wildner 	request->PageAddress = sc->max_dpm_entries <<
600c12c399aSSascha Wildner 	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
601c12c399aSSascha Wildner 	request->ExtPageLength = mpi_reply->ExtPageLength;
602c12c399aSSascha Wildner 	cm->cm_length =  le16toh(request->ExtPageLength) * 4;
603c12c399aSSascha Wildner 	cm->cm_sge = &request->PageBufferSGE;
604c12c399aSSascha Wildner 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
605c12c399aSSascha Wildner 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
606c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
607*3eb4d33cSMatthew Dillon 	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO|M_INTWAIT);
608c12c399aSSascha Wildner 	if (!page) {
609c12c399aSSascha Wildner 		kprintf("%s: page alloc failed\n", __func__);
610c12c399aSSascha Wildner 		error = ENOMEM;
611c12c399aSSascha Wildner 		goto out;
612c12c399aSSascha Wildner 	}
613c12c399aSSascha Wildner 	cm->cm_data = page;
614c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
615c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
616c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
617c12c399aSSascha Wildner 		/* FIXME */
618c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
619c12c399aSSascha Wildner 		kprintf("%s: poll for page completed with error %d",
620c12c399aSSascha Wildner 		    __func__, error);
621c12c399aSSascha Wildner 		error = ENXIO;
622c12c399aSSascha Wildner 		goto out;
623c12c399aSSascha Wildner 	}
624c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
625c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
626c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
627c12c399aSSascha Wildner 		/* FIXME */
628c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
629c12c399aSSascha Wildner 		kprintf("%s: page read with error; iocstatus = 0x%x\n",
630c12c399aSSascha Wildner 		    __func__, ioc_status);
631c12c399aSSascha Wildner 		error = ENXIO;
632c12c399aSSascha Wildner 		goto out;
633c12c399aSSascha Wildner 	}
634c12c399aSSascha Wildner 	bcopy(page, config_page, MIN(cm->cm_length, sz));
635c12c399aSSascha Wildner out:
636c12c399aSSascha Wildner 	kfree(page, M_MPT2);
637c12c399aSSascha Wildner 	if (cm)
638c12c399aSSascha Wildner 		mps_free_command(sc, cm);
639c12c399aSSascha Wildner 	return (error);
640c12c399aSSascha Wildner }
641c12c399aSSascha Wildner 
642c12c399aSSascha Wildner /**
643c12c399aSSascha Wildner  * mps_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
644c12c399aSSascha Wildner  * @sc: per adapter object
645c12c399aSSascha Wildner  * @mpi_reply: reply mf payload returned from firmware
646c12c399aSSascha Wildner  * @config_page: contents of the config page
647c12c399aSSascha Wildner  * @entry_idx: entry index in DPM Page0 to be modified
648c12c399aSSascha Wildner  * Context: sleep.
649c12c399aSSascha Wildner  *
650c12c399aSSascha Wildner  * Returns 0 for success, non-zero for failure.
651c12c399aSSascha Wildner  */
652c12c399aSSascha Wildner 
mps_config_set_dpm_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2DriverMappingPage0_t * config_page,u16 entry_idx)653c12c399aSSascha Wildner int mps_config_set_dpm_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
654c12c399aSSascha Wildner     Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
655c12c399aSSascha Wildner {
656c12c399aSSascha Wildner 	MPI2_CONFIG_REQUEST *request;
657c12c399aSSascha Wildner 	MPI2_CONFIG_REPLY *reply;
658c12c399aSSascha Wildner 	struct mps_command *cm;
659c12c399aSSascha Wildner 	MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
660c12c399aSSascha Wildner 	int error = 0;
661c12c399aSSascha Wildner 	u16 ioc_status;
662c12c399aSSascha Wildner 
663c12c399aSSascha Wildner 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
664c12c399aSSascha Wildner 
665c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
666c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
667c12c399aSSascha Wildner 		    __LINE__);
668c12c399aSSascha Wildner 		error = EBUSY;
669c12c399aSSascha Wildner 		goto out;
670c12c399aSSascha Wildner 	}
671c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
672c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
673c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
674c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
675c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
676c12c399aSSascha Wildner 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
677c12c399aSSascha Wildner 	request->Header.PageNumber = 0;
678c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
679c12c399aSSascha Wildner 	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
680c12c399aSSascha Wildner 	request->PageAddress |= htole16(entry_idx);
681c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
682c12c399aSSascha Wildner 	cm->cm_data = NULL;
683c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
684c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
685c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
686c12c399aSSascha Wildner 		/* FIXME */
687c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
688c12c399aSSascha Wildner 		kprintf("%s: poll for header completed with error %d",
689c12c399aSSascha Wildner 		    __func__, error);
690c12c399aSSascha Wildner 		error = ENXIO;
691c12c399aSSascha Wildner 		goto out;
692c12c399aSSascha Wildner 	}
693c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
694c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
695c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
696c12c399aSSascha Wildner 		/* FIXME */
697c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
698c12c399aSSascha Wildner 		kprintf("%s: header read with error; iocstatus = 0x%x\n",
699c12c399aSSascha Wildner 		    __func__, ioc_status);
700c12c399aSSascha Wildner 		error = ENXIO;
701c12c399aSSascha Wildner 		goto out;
702c12c399aSSascha Wildner 	}
703c12c399aSSascha Wildner 	/* We have to do free and alloc for the reply-free and reply-post
704c12c399aSSascha Wildner 	 * counters to match - Need to review the reply FIFO handling.
705c12c399aSSascha Wildner 	 */
706c12c399aSSascha Wildner 	mps_free_command(sc, cm);
707c12c399aSSascha Wildner 
708c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
709c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
710c12c399aSSascha Wildner 		    __LINE__);
711c12c399aSSascha Wildner 		error = EBUSY;
712c12c399aSSascha Wildner 		goto out;
713c12c399aSSascha Wildner 	}
714c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
715c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
716c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
717c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
718c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
719c12c399aSSascha Wildner 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
720c12c399aSSascha Wildner 	request->Header.PageNumber = 0;
721c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_DRIVERMAPPING0_PAGEVERSION;
722c12c399aSSascha Wildner 	request->ExtPageLength = mpi_reply->ExtPageLength;
723c12c399aSSascha Wildner 	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
724c12c399aSSascha Wildner 	request->PageAddress |= htole16(entry_idx);
725c12c399aSSascha Wildner 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
726c12c399aSSascha Wildner 	cm->cm_sge = &request->PageBufferSGE;
727c12c399aSSascha Wildner 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
728c12c399aSSascha Wildner 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
729c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
730*3eb4d33cSMatthew Dillon 	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
731c12c399aSSascha Wildner 	if (!page) {
732c12c399aSSascha Wildner 		kprintf("%s: page alloc failed\n", __func__);
733c12c399aSSascha Wildner 		error = ENOMEM;
734c12c399aSSascha Wildner 		goto out;
735c12c399aSSascha Wildner 	}
736c12c399aSSascha Wildner 	bcopy(config_page, page, MIN(cm->cm_length,
737c12c399aSSascha Wildner 	    (sizeof(Mpi2DriverMappingPage0_t))));
738c12c399aSSascha Wildner 	cm->cm_data = page;
739c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
740c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
741c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
742c12c399aSSascha Wildner 		/* FIXME */
743c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
744c12c399aSSascha Wildner 		kprintf("%s: poll for page completed with error %d",
745c12c399aSSascha Wildner 		    __func__, error);
746c12c399aSSascha Wildner 		error = ENXIO;
747c12c399aSSascha Wildner 		goto out;
748c12c399aSSascha Wildner 	}
749c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
750c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
751c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
752c12c399aSSascha Wildner 		/* FIXME */
753c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
754c12c399aSSascha Wildner 		kprintf("%s: page written with error; iocstatus = 0x%x\n",
755c12c399aSSascha Wildner 		    __func__, ioc_status);
756c12c399aSSascha Wildner 		error = ENXIO;
757c12c399aSSascha Wildner 		goto out;
758c12c399aSSascha Wildner 	}
759c12c399aSSascha Wildner out:
760c12c399aSSascha Wildner 	kfree(page, M_MPT2);
761c12c399aSSascha Wildner 	if (cm)
762c12c399aSSascha Wildner 		mps_free_command(sc, cm);
763c12c399aSSascha Wildner 	return (error);
764c12c399aSSascha Wildner }
765c12c399aSSascha Wildner 
766c12c399aSSascha Wildner /**
767c12c399aSSascha Wildner  * mps_config_get_sas_device_pg0 - obtain sas device page 0
768c12c399aSSascha Wildner  * @sc: per adapter object
769c12c399aSSascha Wildner  * @mpi_reply: reply mf payload returned from firmware
770c12c399aSSascha Wildner  * @config_page: contents of the config page
771c12c399aSSascha Wildner  * @form: GET_NEXT_HANDLE or HANDLE
772c12c399aSSascha Wildner  * @handle: device handle
773c12c399aSSascha Wildner  * Context: sleep.
774c12c399aSSascha Wildner  *
775c12c399aSSascha Wildner  * Returns 0 for success, non-zero for failure.
776c12c399aSSascha Wildner  */
777c12c399aSSascha Wildner int
mps_config_get_sas_device_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2SasDevicePage0_t * config_page,u32 form,u16 handle)778c12c399aSSascha Wildner mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
779c12c399aSSascha Wildner     *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
780c12c399aSSascha Wildner {
781c12c399aSSascha Wildner 	MPI2_CONFIG_REQUEST *request;
782c12c399aSSascha Wildner 	MPI2_CONFIG_REPLY *reply;
783c12c399aSSascha Wildner 	struct mps_command *cm;
784c12c399aSSascha Wildner 	Mpi2SasDevicePage0_t *page = NULL;
785c12c399aSSascha Wildner 	int error = 0;
786c12c399aSSascha Wildner 	u16 ioc_status;
787c12c399aSSascha Wildner 
788c12c399aSSascha Wildner 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
789c12c399aSSascha Wildner 
790c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
791c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
792c12c399aSSascha Wildner 		    __LINE__);
793c12c399aSSascha Wildner 		error = EBUSY;
794c12c399aSSascha Wildner 		goto out;
795c12c399aSSascha Wildner 	}
796c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
797c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
798c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
799c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
800c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
801c12c399aSSascha Wildner 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
802c12c399aSSascha Wildner 	request->Header.PageNumber = 0;
803c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
804c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
805c12c399aSSascha Wildner 	cm->cm_data = NULL;
806c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
807c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
808c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
809c12c399aSSascha Wildner 		/* FIXME */
810c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
811c12c399aSSascha Wildner 		kprintf("%s: poll for header completed with error %d",
812c12c399aSSascha Wildner 		    __func__, error);
813c12c399aSSascha Wildner 		error = ENXIO;
814c12c399aSSascha Wildner 		goto out;
815c12c399aSSascha Wildner 	}
816c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
817c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
818c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
819c12c399aSSascha Wildner 		/* FIXME */
820c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
821c12c399aSSascha Wildner 		kprintf("%s: header read with error; iocstatus = 0x%x\n",
822c12c399aSSascha Wildner 		    __func__, ioc_status);
823c12c399aSSascha Wildner 		error = ENXIO;
824c12c399aSSascha Wildner 		goto out;
825c12c399aSSascha Wildner 	}
826c12c399aSSascha Wildner 	/* We have to do free and alloc for the reply-free and reply-post
827c12c399aSSascha Wildner 	 * counters to match - Need to review the reply FIFO handling.
828c12c399aSSascha Wildner 	 */
829c12c399aSSascha Wildner 	mps_free_command(sc, cm);
830c12c399aSSascha Wildner 
831c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
832c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
833c12c399aSSascha Wildner 		    __LINE__);
834c12c399aSSascha Wildner 		error = EBUSY;
835c12c399aSSascha Wildner 		goto out;
836c12c399aSSascha Wildner 	}
837c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
838c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
839c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
840c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
841c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
842c12c399aSSascha Wildner 	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
843c12c399aSSascha Wildner 	request->Header.PageNumber = 0;
844c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
845c12c399aSSascha Wildner 	request->ExtPageLength = mpi_reply->ExtPageLength;
846c12c399aSSascha Wildner 	request->PageAddress = htole32(form | handle);
847c12c399aSSascha Wildner 	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
848c12c399aSSascha Wildner 	cm->cm_sge = &request->PageBufferSGE;
849c12c399aSSascha Wildner 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
850c12c399aSSascha Wildner 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
851c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
852*3eb4d33cSMatthew Dillon 	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
853c12c399aSSascha Wildner 	if (!page) {
854c12c399aSSascha Wildner 		kprintf("%s: page alloc failed\n", __func__);
855c12c399aSSascha Wildner 		error = ENOMEM;
856c12c399aSSascha Wildner 		goto out;
857c12c399aSSascha Wildner 	}
858c12c399aSSascha Wildner 	cm->cm_data = page;
859c12c399aSSascha Wildner 
860c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
861c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
862c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
863c12c399aSSascha Wildner 		/* FIXME */
864c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
865c12c399aSSascha Wildner 		kprintf("%s: poll for page completed with error %d",
866c12c399aSSascha Wildner 		    __func__, error);
867c12c399aSSascha Wildner 		error = ENXIO;
868c12c399aSSascha Wildner 		goto out;
869c12c399aSSascha Wildner 	}
870c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
871c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
872c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
873c12c399aSSascha Wildner 		/* FIXME */
874c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
875c12c399aSSascha Wildner 		kprintf("%s: page read with error; iocstatus = 0x%x\n",
876c12c399aSSascha Wildner 		    __func__, ioc_status);
877c12c399aSSascha Wildner 		error = ENXIO;
878c12c399aSSascha Wildner 		goto out;
879c12c399aSSascha Wildner 	}
880c12c399aSSascha Wildner 	bcopy(page, config_page, MIN(cm->cm_length,
881c12c399aSSascha Wildner 	    sizeof(Mpi2SasDevicePage0_t)));
882c12c399aSSascha Wildner out:
883c12c399aSSascha Wildner 	kfree(page, M_MPT2);
884c12c399aSSascha Wildner 	if (cm)
885c12c399aSSascha Wildner 		mps_free_command(sc, cm);
886c12c399aSSascha Wildner 	return (error);
887c12c399aSSascha Wildner }
888c12c399aSSascha Wildner 
889c12c399aSSascha Wildner /**
890c12c399aSSascha Wildner  * mps_config_get_bios_pg3 - obtain BIOS page 3
891c12c399aSSascha Wildner  * @sc: per adapter object
892c12c399aSSascha Wildner  * @mpi_reply: reply mf payload returned from firmware
893c12c399aSSascha Wildner  * @config_page: contents of the config page
894c12c399aSSascha Wildner  * Context: sleep.
895c12c399aSSascha Wildner  *
896c12c399aSSascha Wildner  * Returns 0 for success, non-zero for failure.
897c12c399aSSascha Wildner  */
898c12c399aSSascha Wildner int
mps_config_get_bios_pg3(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2BiosPage3_t * config_page)899c12c399aSSascha Wildner mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
900c12c399aSSascha Wildner     Mpi2BiosPage3_t *config_page)
901c12c399aSSascha Wildner {
902c12c399aSSascha Wildner 	MPI2_CONFIG_REQUEST *request;
903c12c399aSSascha Wildner 	MPI2_CONFIG_REPLY *reply;
904c12c399aSSascha Wildner 	struct mps_command *cm;
905c12c399aSSascha Wildner 	Mpi2BiosPage3_t *page = NULL;
906c12c399aSSascha Wildner 	int error = 0;
907c12c399aSSascha Wildner 	u16 ioc_status;
908c12c399aSSascha Wildner 
909c12c399aSSascha Wildner 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
910c12c399aSSascha Wildner 
911c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
912c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
913c12c399aSSascha Wildner 		    __LINE__);
914c12c399aSSascha Wildner 		error = EBUSY;
915c12c399aSSascha Wildner 		goto out;
916c12c399aSSascha Wildner 	}
917c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
918c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
919c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
920c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
921c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
922c12c399aSSascha Wildner 	request->Header.PageNumber = 3;
923c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
924c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
925c12c399aSSascha Wildner 	cm->cm_data = NULL;
926c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
927c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
928c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
929c12c399aSSascha Wildner 		/* FIXME */
930c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
931c12c399aSSascha Wildner 		kprintf("%s: poll for header completed with error %d",
932c12c399aSSascha Wildner 		    __func__, error);
933c12c399aSSascha Wildner 		error = ENXIO;
934c12c399aSSascha Wildner 		goto out;
935c12c399aSSascha Wildner 	}
936c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
937c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
938c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
939c12c399aSSascha Wildner 		/* FIXME */
940c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
941c12c399aSSascha Wildner 		kprintf("%s: header read with error; iocstatus = 0x%x\n",
942c12c399aSSascha Wildner 		    __func__, ioc_status);
943c12c399aSSascha Wildner 		error = ENXIO;
944c12c399aSSascha Wildner 		goto out;
945c12c399aSSascha Wildner 	}
946c12c399aSSascha Wildner 	/* We have to do free and alloc for the reply-free and reply-post
947c12c399aSSascha Wildner 	 * counters to match - Need to review the reply FIFO handling.
948c12c399aSSascha Wildner 	 */
949c12c399aSSascha Wildner 	mps_free_command(sc, cm);
950c12c399aSSascha Wildner 
951c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
952c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
953c12c399aSSascha Wildner 		    __LINE__);
954c12c399aSSascha Wildner 		error = EBUSY;
955c12c399aSSascha Wildner 		goto out;
956c12c399aSSascha Wildner 	}
957c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
958c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
959c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
960c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
961c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
962c12c399aSSascha Wildner 	request->Header.PageNumber = 3;
963c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
964c12c399aSSascha Wildner 	request->Header.PageLength = mpi_reply->Header.PageLength;
965c12c399aSSascha Wildner 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
966c12c399aSSascha Wildner 	cm->cm_sge = &request->PageBufferSGE;
967c12c399aSSascha Wildner 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
968c12c399aSSascha Wildner 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
969c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
970*3eb4d33cSMatthew Dillon 	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
971c12c399aSSascha Wildner 	if (!page) {
972c12c399aSSascha Wildner 		kprintf("%s: page alloc failed\n", __func__);
973c12c399aSSascha Wildner 		error = ENOMEM;
974c12c399aSSascha Wildner 		goto out;
975c12c399aSSascha Wildner 	}
976c12c399aSSascha Wildner 	cm->cm_data = page;
977c12c399aSSascha Wildner 
978c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
979c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
980c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
981c12c399aSSascha Wildner 		/* FIXME */
982c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
983c12c399aSSascha Wildner 		kprintf("%s: poll for page completed with error %d",
984c12c399aSSascha Wildner 		    __func__, error);
985c12c399aSSascha Wildner 		error = ENXIO;
986c12c399aSSascha Wildner 		goto out;
987c12c399aSSascha Wildner 	}
988c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
989c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
990c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
991c12c399aSSascha Wildner 		/* FIXME */
992c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
993c12c399aSSascha Wildner 		kprintf("%s: page read with error; iocstatus = 0x%x\n",
994c12c399aSSascha Wildner 		    __func__, ioc_status);
995c12c399aSSascha Wildner 		error = ENXIO;
996c12c399aSSascha Wildner 		goto out;
997c12c399aSSascha Wildner 	}
998c12c399aSSascha Wildner 	bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
999c12c399aSSascha Wildner out:
1000c12c399aSSascha Wildner 	kfree(page, M_MPT2);
1001c12c399aSSascha Wildner 	if (cm)
1002c12c399aSSascha Wildner 		mps_free_command(sc, cm);
1003c12c399aSSascha Wildner 	return (error);
1004c12c399aSSascha Wildner }
1005c12c399aSSascha Wildner 
1006c12c399aSSascha Wildner /**
1007c12c399aSSascha Wildner  * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1008c12c399aSSascha Wildner  * @sc: per adapter object
1009c12c399aSSascha Wildner  * @mpi_reply: reply mf payload returned from firmware
1010c12c399aSSascha Wildner  * @config_page: contents of the config page
1011c12c399aSSascha Wildner  * @page_address: form and handle value used to get page
1012c12c399aSSascha Wildner  * Context: sleep.
1013c12c399aSSascha Wildner  *
1014c12c399aSSascha Wildner  * Returns 0 for success, non-zero for failure.
1015c12c399aSSascha Wildner  */
1016c12c399aSSascha Wildner int
mps_config_get_raid_volume_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage0_t * config_page,u32 page_address)1017c12c399aSSascha Wildner mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1018c12c399aSSascha Wildner     *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1019c12c399aSSascha Wildner {
1020c12c399aSSascha Wildner 	MPI2_CONFIG_REQUEST *request;
1021c12c399aSSascha Wildner 	MPI2_CONFIG_REPLY *reply;
1022c12c399aSSascha Wildner 	struct mps_command *cm;
1023c12c399aSSascha Wildner 	Mpi2RaidVolPage0_t *page = NULL;
1024c12c399aSSascha Wildner 	int error = 0;
1025c12c399aSSascha Wildner 	u16 ioc_status;
1026c12c399aSSascha Wildner 
1027c12c399aSSascha Wildner 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1028c12c399aSSascha Wildner 
1029c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
1030c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
1031c12c399aSSascha Wildner 		    __LINE__);
1032c12c399aSSascha Wildner 		error = EBUSY;
1033c12c399aSSascha Wildner 		goto out;
1034c12c399aSSascha Wildner 	}
1035c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1036c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1037c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
1038c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1039c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1040c12c399aSSascha Wildner 	request->Header.PageNumber = 0;
1041c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1042c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1043c12c399aSSascha Wildner 	cm->cm_data = NULL;
1044c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
1045c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1046c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
1047c12c399aSSascha Wildner 		/* FIXME */
1048c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1049c12c399aSSascha Wildner 		kprintf("%s: poll for header completed with error %d",
1050c12c399aSSascha Wildner 		    __func__, error);
1051c12c399aSSascha Wildner 		error = ENXIO;
1052c12c399aSSascha Wildner 		goto out;
1053c12c399aSSascha Wildner 	}
1054c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1055c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1056c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1057c12c399aSSascha Wildner 		/* FIXME */
1058c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1059c12c399aSSascha Wildner 		kprintf("%s: header read with error; iocstatus = 0x%x\n",
1060c12c399aSSascha Wildner 		    __func__, ioc_status);
1061c12c399aSSascha Wildner 		error = ENXIO;
1062c12c399aSSascha Wildner 		goto out;
1063c12c399aSSascha Wildner 	}
1064c12c399aSSascha Wildner 	/* We have to do free and alloc for the reply-free and reply-post
1065c12c399aSSascha Wildner 	 * counters to match - Need to review the reply FIFO handling.
1066c12c399aSSascha Wildner 	 */
1067c12c399aSSascha Wildner 	mps_free_command(sc, cm);
1068c12c399aSSascha Wildner 
1069c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
1070c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
1071c12c399aSSascha Wildner 		    __LINE__);
1072c12c399aSSascha Wildner 		error = EBUSY;
1073c12c399aSSascha Wildner 		goto out;
1074c12c399aSSascha Wildner 	}
1075c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1076c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1077c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
1078c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1079c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1080c12c399aSSascha Wildner 	request->Header.PageNumber = 0;
1081c12c399aSSascha Wildner 	request->Header.PageLength = mpi_reply->Header.PageLength;
1082c12c399aSSascha Wildner 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1083c12c399aSSascha Wildner 	request->PageAddress = page_address;
1084c12c399aSSascha Wildner 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1085c12c399aSSascha Wildner 	cm->cm_sge = &request->PageBufferSGE;
1086c12c399aSSascha Wildner 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1087c12c399aSSascha Wildner 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1088c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1089*3eb4d33cSMatthew Dillon 	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
1090c12c399aSSascha Wildner 	if (!page) {
1091c12c399aSSascha Wildner 		kprintf("%s: page alloc failed\n", __func__);
1092c12c399aSSascha Wildner 		error = ENOMEM;
1093c12c399aSSascha Wildner 		goto out;
1094c12c399aSSascha Wildner 	}
1095c12c399aSSascha Wildner 	cm->cm_data = page;
1096c12c399aSSascha Wildner 
1097c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
1098c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1099c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
1100c12c399aSSascha Wildner 		/* FIXME */
1101c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1102c12c399aSSascha Wildner 		kprintf("%s: poll for page completed with error %d",
1103c12c399aSSascha Wildner 		    __func__, error);
1104c12c399aSSascha Wildner 		error = ENXIO;
1105c12c399aSSascha Wildner 		goto out;
1106c12c399aSSascha Wildner 	}
1107c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1108c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1109c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1110c12c399aSSascha Wildner 		/* FIXME */
1111c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1112c12c399aSSascha Wildner 		kprintf("%s: page read with error; iocstatus = 0x%x\n",
1113c12c399aSSascha Wildner 		    __func__, ioc_status);
1114c12c399aSSascha Wildner 		error = ENXIO;
1115c12c399aSSascha Wildner 		goto out;
1116c12c399aSSascha Wildner 	}
1117c12c399aSSascha Wildner 	bcopy(page, config_page, cm->cm_length);
1118c12c399aSSascha Wildner out:
1119c12c399aSSascha Wildner 	kfree(page, M_MPT2);
1120c12c399aSSascha Wildner 	if (cm)
1121c12c399aSSascha Wildner 		mps_free_command(sc, cm);
1122c12c399aSSascha Wildner 	return (error);
1123c12c399aSSascha Wildner }
1124c12c399aSSascha Wildner 
1125c12c399aSSascha Wildner /**
1126c12c399aSSascha Wildner  * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1127c12c399aSSascha Wildner  * @sc: per adapter object
1128c12c399aSSascha Wildner  * @mpi_reply: reply mf payload returned from firmware
1129c12c399aSSascha Wildner  * @config_page: contents of the config page
1130c12c399aSSascha Wildner  * @form: GET_NEXT_HANDLE or HANDLE
1131c12c399aSSascha Wildner  * @handle: volume handle
1132c12c399aSSascha Wildner  * Context: sleep.
1133c12c399aSSascha Wildner  *
1134c12c399aSSascha Wildner  * Returns 0 for success, non-zero for failure.
1135c12c399aSSascha Wildner  */
1136c12c399aSSascha Wildner int
mps_config_get_raid_volume_pg1(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidVolPage1_t * config_page,u32 form,u16 handle)1137c12c399aSSascha Wildner mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1138c12c399aSSascha Wildner     *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1139c12c399aSSascha Wildner {
1140c12c399aSSascha Wildner 	MPI2_CONFIG_REQUEST *request;
1141c12c399aSSascha Wildner 	MPI2_CONFIG_REPLY *reply;
1142c12c399aSSascha Wildner 	struct mps_command *cm;
1143c12c399aSSascha Wildner 	Mpi2RaidVolPage1_t *page = NULL;
1144c12c399aSSascha Wildner 	int error = 0;
1145c12c399aSSascha Wildner 	u16 ioc_status;
1146c12c399aSSascha Wildner 
1147c12c399aSSascha Wildner 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1148c12c399aSSascha Wildner 
1149c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
1150c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
1151c12c399aSSascha Wildner 		    __LINE__);
1152c12c399aSSascha Wildner 		error = EBUSY;
1153c12c399aSSascha Wildner 		goto out;
1154c12c399aSSascha Wildner 	}
1155c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1156c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1157c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
1158c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1159c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1160c12c399aSSascha Wildner 	request->Header.PageNumber = 1;
1161c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1162c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1163c12c399aSSascha Wildner 	cm->cm_data = NULL;
1164c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
1165c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1166c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
1167c12c399aSSascha Wildner 		/* FIXME */
1168c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1169c12c399aSSascha Wildner 		kprintf("%s: poll for header completed with error %d",
1170c12c399aSSascha Wildner 		    __func__, error);
1171c12c399aSSascha Wildner 		error = ENXIO;
1172c12c399aSSascha Wildner 		goto out;
1173c12c399aSSascha Wildner 	}
1174c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1175c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1176c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1177c12c399aSSascha Wildner 		/* FIXME */
1178c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1179c12c399aSSascha Wildner 		kprintf("%s: header read with error; iocstatus = 0x%x\n",
1180c12c399aSSascha Wildner 		    __func__, ioc_status);
1181c12c399aSSascha Wildner 		error = ENXIO;
1182c12c399aSSascha Wildner 		goto out;
1183c12c399aSSascha Wildner 	}
1184c12c399aSSascha Wildner 	/* We have to do free and alloc for the reply-free and reply-post
1185c12c399aSSascha Wildner 	 * counters to match - Need to review the reply FIFO handling.
1186c12c399aSSascha Wildner 	 */
1187c12c399aSSascha Wildner 	mps_free_command(sc, cm);
1188c12c399aSSascha Wildner 
1189c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
1190c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
1191c12c399aSSascha Wildner 		    __LINE__);
1192c12c399aSSascha Wildner 		error = EBUSY;
1193c12c399aSSascha Wildner 		goto out;
1194c12c399aSSascha Wildner 	}
1195c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1196c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1197c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
1198c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1199c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1200c12c399aSSascha Wildner 	request->Header.PageNumber = 1;
1201c12c399aSSascha Wildner 	request->Header.PageLength = mpi_reply->Header.PageLength;
1202c12c399aSSascha Wildner 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1203c12c399aSSascha Wildner 	request->PageAddress = htole32(form | handle);
1204c12c399aSSascha Wildner 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1205c12c399aSSascha Wildner 	cm->cm_sge = &request->PageBufferSGE;
1206c12c399aSSascha Wildner 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1207c12c399aSSascha Wildner 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1208c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1209*3eb4d33cSMatthew Dillon 	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
1210c12c399aSSascha Wildner 	if (!page) {
1211c12c399aSSascha Wildner 		kprintf("%s: page alloc failed\n", __func__);
1212c12c399aSSascha Wildner 		error = ENOMEM;
1213c12c399aSSascha Wildner 		goto out;
1214c12c399aSSascha Wildner 	}
1215c12c399aSSascha Wildner 	cm->cm_data = page;
1216c12c399aSSascha Wildner 
1217c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
1218c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1219c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
1220c12c399aSSascha Wildner 		/* FIXME */
1221c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1222c12c399aSSascha Wildner 		kprintf("%s: poll for page completed with error %d",
1223c12c399aSSascha Wildner 		    __func__, error);
1224c12c399aSSascha Wildner 		error = ENXIO;
1225c12c399aSSascha Wildner 		goto out;
1226c12c399aSSascha Wildner 	}
1227c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1228c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1229c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1230c12c399aSSascha Wildner 		/* FIXME */
1231c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1232c12c399aSSascha Wildner 		kprintf("%s: page read with error; iocstatus = 0x%x\n",
1233c12c399aSSascha Wildner 		    __func__, ioc_status);
1234c12c399aSSascha Wildner 		error = ENXIO;
1235c12c399aSSascha Wildner 		goto out;
1236c12c399aSSascha Wildner 	}
1237c12c399aSSascha Wildner 	bcopy(page, config_page, MIN(cm->cm_length,
1238c12c399aSSascha Wildner 	    sizeof(Mpi2RaidVolPage1_t)));
1239c12c399aSSascha Wildner out:
1240c12c399aSSascha Wildner 	kfree(page, M_MPT2);
1241c12c399aSSascha Wildner 	if (cm)
1242c12c399aSSascha Wildner 		mps_free_command(sc, cm);
1243c12c399aSSascha Wildner 	return (error);
1244c12c399aSSascha Wildner }
1245c12c399aSSascha Wildner 
1246c12c399aSSascha Wildner /**
1247c12c399aSSascha Wildner  * mps_config_get_volume_wwid - returns wwid given the volume handle
1248c12c399aSSascha Wildner  * @sc: per adapter object
1249c12c399aSSascha Wildner  * @volume_handle: volume handle
1250c12c399aSSascha Wildner  * @wwid: volume wwid
1251c12c399aSSascha Wildner  * Context: sleep.
1252c12c399aSSascha Wildner  *
1253c12c399aSSascha Wildner  * Returns 0 for success, non-zero for failure.
1254c12c399aSSascha Wildner  */
1255c12c399aSSascha Wildner int
mps_config_get_volume_wwid(struct mps_softc * sc,u16 volume_handle,u64 * wwid)1256c12c399aSSascha Wildner mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1257c12c399aSSascha Wildner {
1258c12c399aSSascha Wildner 	Mpi2ConfigReply_t mpi_reply;
1259c12c399aSSascha Wildner 	Mpi2RaidVolPage1_t raid_vol_pg1;
1260c12c399aSSascha Wildner 
1261c12c399aSSascha Wildner 	*wwid = 0;
1262c12c399aSSascha Wildner 	if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1263c12c399aSSascha Wildner 	    MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1264c12c399aSSascha Wildner 		*wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1265c12c399aSSascha Wildner 		    raid_vol_pg1.WWID.Low);
1266c12c399aSSascha Wildner 		return 0;
1267c12c399aSSascha Wildner 	} else
1268c12c399aSSascha Wildner 		return -1;
1269c12c399aSSascha Wildner }
1270c12c399aSSascha Wildner 
1271c12c399aSSascha Wildner /**
1272c12c399aSSascha Wildner  * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1273c12c399aSSascha Wildner  * @sc: per adapter object
1274c12c399aSSascha Wildner  * @mpi_reply: reply mf payload returned from firmware
1275c12c399aSSascha Wildner  * @config_page: contents of the config page
1276c12c399aSSascha Wildner  * @page_address: form and handle value used to get page
1277c12c399aSSascha Wildner  * Context: sleep.
1278c12c399aSSascha Wildner  *
1279c12c399aSSascha Wildner  * Returns 0 for success, non-zero for failure.
1280c12c399aSSascha Wildner  */
1281c12c399aSSascha Wildner int
mps_config_get_raid_pd_pg0(struct mps_softc * sc,Mpi2ConfigReply_t * mpi_reply,Mpi2RaidPhysDiskPage0_t * config_page,u32 page_address)1282c12c399aSSascha Wildner mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1283c12c399aSSascha Wildner     Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1284c12c399aSSascha Wildner {
1285c12c399aSSascha Wildner 	MPI2_CONFIG_REQUEST *request;
1286c12c399aSSascha Wildner 	MPI2_CONFIG_REPLY *reply;
1287c12c399aSSascha Wildner 	struct mps_command *cm;
1288c12c399aSSascha Wildner 	Mpi2RaidPhysDiskPage0_t *page = NULL;
1289c12c399aSSascha Wildner 	int error = 0;
1290c12c399aSSascha Wildner 	u16 ioc_status;
1291c12c399aSSascha Wildner 
1292c12c399aSSascha Wildner 	mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1293c12c399aSSascha Wildner 
1294c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
1295c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
1296c12c399aSSascha Wildner 		    __LINE__);
1297c12c399aSSascha Wildner 		error = EBUSY;
1298c12c399aSSascha Wildner 		goto out;
1299c12c399aSSascha Wildner 	}
1300c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1301c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1302c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
1303c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1304c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1305c12c399aSSascha Wildner 	request->Header.PageNumber = 0;
1306c12c399aSSascha Wildner 	request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1307c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1308c12c399aSSascha Wildner 	cm->cm_data = NULL;
1309c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
1310c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1311c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
1312c12c399aSSascha Wildner 		/* FIXME */
1313c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1314c12c399aSSascha Wildner 		kprintf("%s: poll for header completed with error %d",
1315c12c399aSSascha Wildner 		    __func__, error);
1316c12c399aSSascha Wildner 		error = ENXIO;
1317c12c399aSSascha Wildner 		goto out;
1318c12c399aSSascha Wildner 	}
1319c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1320c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1321c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1322c12c399aSSascha Wildner 		/* FIXME */
1323c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1324c12c399aSSascha Wildner 		kprintf("%s: header read with error; iocstatus = 0x%x\n",
1325c12c399aSSascha Wildner 		    __func__, ioc_status);
1326c12c399aSSascha Wildner 		error = ENXIO;
1327c12c399aSSascha Wildner 		goto out;
1328c12c399aSSascha Wildner 	}
1329c12c399aSSascha Wildner 	/* We have to do free and alloc for the reply-free and reply-post
1330c12c399aSSascha Wildner 	 * counters to match - Need to review the reply FIFO handling.
1331c12c399aSSascha Wildner 	 */
1332c12c399aSSascha Wildner 	mps_free_command(sc, cm);
1333c12c399aSSascha Wildner 
1334c12c399aSSascha Wildner 	if ((cm = mps_alloc_command(sc)) == NULL) {
1335c12c399aSSascha Wildner 		kprintf("%s: command alloc failed @ line %d\n", __func__,
1336c12c399aSSascha Wildner 		    __LINE__);
1337c12c399aSSascha Wildner 		error = EBUSY;
1338c12c399aSSascha Wildner 		goto out;
1339c12c399aSSascha Wildner 	}
1340c12c399aSSascha Wildner 	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1341c12c399aSSascha Wildner 	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1342c12c399aSSascha Wildner 	request->Function = MPI2_FUNCTION_CONFIG;
1343c12c399aSSascha Wildner 	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1344c12c399aSSascha Wildner 	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1345c12c399aSSascha Wildner 	request->Header.PageNumber = 0;
1346c12c399aSSascha Wildner 	request->Header.PageLength = mpi_reply->Header.PageLength;
1347c12c399aSSascha Wildner 	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1348c12c399aSSascha Wildner 	request->PageAddress = page_address;
1349c12c399aSSascha Wildner 	cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1350c12c399aSSascha Wildner 	cm->cm_sge = &request->PageBufferSGE;
1351c12c399aSSascha Wildner 	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1352c12c399aSSascha Wildner 	cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1353c12c399aSSascha Wildner 	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1354*3eb4d33cSMatthew Dillon 	page = kmalloc(cm->cm_length, M_MPT2, M_ZERO | M_INTWAIT);
1355c12c399aSSascha Wildner 	if (!page) {
1356c12c399aSSascha Wildner 		kprintf("%s: page alloc failed\n", __func__);
1357c12c399aSSascha Wildner 		error = ENOMEM;
1358c12c399aSSascha Wildner 		goto out;
1359c12c399aSSascha Wildner 	}
1360c12c399aSSascha Wildner 	cm->cm_data = page;
1361c12c399aSSascha Wildner 
1362c12c399aSSascha Wildner 	error = mps_request_polled(sc, cm);
1363c12c399aSSascha Wildner 	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1364c12c399aSSascha Wildner 	if (error || (reply == NULL)) {
1365c12c399aSSascha Wildner 		/* FIXME */
1366c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1367c12c399aSSascha Wildner 		kprintf("%s: poll for page completed with error %d",
1368c12c399aSSascha Wildner 		    __func__, error);
1369c12c399aSSascha Wildner 		error = ENXIO;
1370c12c399aSSascha Wildner 		goto out;
1371c12c399aSSascha Wildner 	}
1372c12c399aSSascha Wildner 	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1373c12c399aSSascha Wildner 	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1374c12c399aSSascha Wildner 	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1375c12c399aSSascha Wildner 		/* FIXME */
1376c12c399aSSascha Wildner 		/* If the poll returns error then we need to do diag reset */
1377c12c399aSSascha Wildner 		kprintf("%s: page read with error; iocstatus = 0x%x\n",
1378c12c399aSSascha Wildner 		    __func__, ioc_status);
1379c12c399aSSascha Wildner 		error = ENXIO;
1380c12c399aSSascha Wildner 		goto out;
1381c12c399aSSascha Wildner 	}
1382c12c399aSSascha Wildner 	bcopy(page, config_page, MIN(cm->cm_length,
1383c12c399aSSascha Wildner 	    sizeof(Mpi2RaidPhysDiskPage0_t)));
1384c12c399aSSascha Wildner out:
1385c12c399aSSascha Wildner 	kfree(page, M_MPT2);
1386c12c399aSSascha Wildner 	if (cm)
1387c12c399aSSascha Wildner 		mps_free_command(sc, cm);
1388c12c399aSSascha Wildner 	return (error);
1389c12c399aSSascha Wildner }
1390