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