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