1/*-
2 * Copyright (c) 2011-2015 LSI Corp.
3 * Copyright (c) 2013-2016 Avago Technologies
4 * Copyright 2000-2020 Broadcom Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD$");
33
34/* TODO Move headers to mprvar */
35#include <sys/types.h>
36#include <sys/param.h>
37#include <sys/lock.h>
38#include <sys/mutex.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/malloc.h>
42#include <sys/kthread.h>
43#include <sys/taskqueue.h>
44#include <sys/bus.h>
45#include <sys/endian.h>
46#include <sys/sysctl.h>
47#include <sys/eventhandler.h>
48#include <sys/uio.h>
49#include <machine/bus.h>
50#include <machine/resource.h>
51#include <dev/mpr/mpi/mpi2_type.h>
52#include <dev/mpr/mpi/mpi2.h>
53#include <dev/mpr/mpi/mpi2_ioc.h>
54#include <dev/mpr/mpi/mpi2_sas.h>
55#include <dev/mpr/mpi/mpi2_pci.h>
56#include <dev/mpr/mpi/mpi2_cnfg.h>
57#include <dev/mpr/mpi/mpi2_init.h>
58#include <dev/mpr/mpi/mpi2_tool.h>
59#include <dev/mpr/mpr_ioctl.h>
60#include <dev/mpr/mprvar.h>
61
62/**
63 * mpr_config_get_ioc_pg8 - obtain ioc page 8
64 * @sc: per adapter object
65 * @mpi_reply: reply mf payload returned from firmware
66 * @config_page: contents of the config page
67 * Context: sleep.
68 *
69 * Returns 0 for success, non-zero for failure.
70 */
71int
72mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
73    Mpi2IOCPage8_t *config_page)
74{
75	MPI2_CONFIG_REQUEST *request;
76	MPI2_CONFIG_REPLY *reply;
77	struct mpr_command *cm;
78	MPI2_CONFIG_PAGE_IOC_8 *page = NULL;
79	int error = 0;
80	u16 ioc_status;
81
82	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
83
84	if ((cm = mpr_alloc_command(sc)) == NULL) {
85		printf("%s: command alloc failed @ line %d\n", __func__,
86		    __LINE__);
87		error = EBUSY;
88		goto out;
89	}
90	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
91	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
92	request->Function = MPI2_FUNCTION_CONFIG;
93	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
94	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
95	request->Header.PageNumber = 8;
96	request->Header.PageLength = request->Header.PageVersion = 0;
97	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
98	cm->cm_data = NULL;
99	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
100	if (cm != NULL)
101		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
102	if (error || (reply == NULL)) {
103		/* FIXME */
104		/*
105		 * If the request returns an error then we need to do a diag
106		 * reset
107		 */
108		printf("%s: request for header completed with error %d",
109		    __func__, error);
110		error = ENXIO;
111		goto out;
112	}
113	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
114	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
115	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
116		/* FIXME */
117		/*
118		 * If the request returns an error then we need to do a diag
119		 * reset
120		 */
121		printf("%s: header read with error; iocstatus = 0x%x\n",
122		    __func__, ioc_status);
123		error = ENXIO;
124		goto out;
125	}
126	/* We have to do free and alloc for the reply-free and reply-post
127	 * counters to match - Need to review the reply FIFO handling.
128	 */
129	mpr_free_command(sc, cm);
130
131	if ((cm = mpr_alloc_command(sc)) == NULL) {
132		printf("%s: command alloc failed @ line %d\n", __func__,
133		    __LINE__);
134		error = EBUSY;
135		goto out;
136	}
137	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
138	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
139	request->Function = MPI2_FUNCTION_CONFIG;
140	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
141	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
142	request->Header.PageNumber = 8;
143	request->Header.PageVersion = mpi_reply->Header.PageVersion;
144	request->Header.PageLength = mpi_reply->Header.PageLength;
145	cm->cm_length = mpi_reply->Header.PageLength * 4;
146	cm->cm_sge = &request->PageBufferSGE;
147	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
148	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
149	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
150	page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
151	if (!page) {
152		printf("%s: page alloc failed\n", __func__);
153		error = ENOMEM;
154		goto out;
155	}
156	cm->cm_data = page;
157
158	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
159	if (cm != NULL)
160		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
161	if (error || (reply == NULL)) {
162		/* FIXME */
163		/*
164		 * If the request returns an error then we need to do a diag
165		 * reset
166		 */
167		printf("%s: request for page completed with error %d",
168		    __func__, error);
169		error = ENXIO;
170		goto out;
171	}
172	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
173	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
174	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
175		/* FIXME */
176		/*
177		 * If the request returns an error then we need to do a diag
178		 * reset
179		 */
180		printf("%s: page read with error; iocstatus = 0x%x\n",
181		    __func__, ioc_status);
182		error = ENXIO;
183		goto out;
184	}
185	bcopy(page, config_page, MIN(cm->cm_length, (sizeof(Mpi2IOCPage8_t))));
186
187out:
188	free(page, M_MPR);
189	if (cm)
190		mpr_free_command(sc, cm);
191	return (error);
192}
193
194/**
195 * mpr_config_get_iounit_pg8 - obtain iounit page 8
196 * @sc: per adapter object
197 * @mpi_reply: reply mf payload returned from firmware
198 * @config_page: contents of the config page
199 * Context: sleep.
200 *
201 * Returns 0 for success, non-zero for failure.
202 */
203int
204mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
205    Mpi2IOUnitPage8_t *config_page)
206{
207	MPI2_CONFIG_REQUEST *request;
208	MPI2_CONFIG_REPLY *reply;
209	struct mpr_command *cm;
210	MPI2_CONFIG_PAGE_IO_UNIT_8 *page = NULL;
211	int error = 0;
212	u16 ioc_status;
213
214	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
215
216	if ((cm = mpr_alloc_command(sc)) == NULL) {
217		printf("%s: command alloc failed @ line %d\n", __func__,
218		    __LINE__);
219		error = EBUSY;
220		goto out;
221	}
222	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
223	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
224	request->Function = MPI2_FUNCTION_CONFIG;
225	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
226	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
227	request->Header.PageNumber = 8;
228	request->Header.PageLength = request->Header.PageVersion = 0;
229	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
230	cm->cm_data = NULL;
231	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
232	if (cm != NULL)
233		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
234	if (error || (reply == NULL)) {
235		/* FIXME */
236		/*
237		 * If the request returns an error then we need to do a diag
238		 * reset
239		 */
240		printf("%s: request for header completed with error %d",
241		    __func__, error);
242		error = ENXIO;
243		goto out;
244	}
245	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
246	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
247	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
248		/* FIXME */
249		/*
250		 * If the request returns an error then we need to do a diag
251		 * reset
252		 */
253		printf("%s: header read with error; iocstatus = 0x%x\n",
254		    __func__, ioc_status);
255		error = ENXIO;
256		goto out;
257	}
258	/* We have to do free and alloc for the reply-free and reply-post
259	 * counters to match - Need to review the reply FIFO handling.
260	 */
261	mpr_free_command(sc, cm);
262
263	if ((cm = mpr_alloc_command(sc)) == NULL) {
264		printf("%s: command alloc failed @ line %d\n", __func__,
265		    __LINE__);
266		error = EBUSY;
267		goto out;
268	}
269	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
270	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
271	request->Function = MPI2_FUNCTION_CONFIG;
272	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
273	request->Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
274	request->Header.PageNumber = 8;
275	request->Header.PageVersion = mpi_reply->Header.PageVersion;
276	request->Header.PageLength = mpi_reply->Header.PageLength;
277	cm->cm_length = mpi_reply->Header.PageLength * 4;
278	cm->cm_sge = &request->PageBufferSGE;
279	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
280	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
281	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
282	page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
283	if (!page) {
284		printf("%s: page alloc failed\n", __func__);
285		error = ENOMEM;
286		goto out;
287	}
288	cm->cm_data = page;
289
290	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
291	if (cm != NULL)
292		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
293	if (error || (reply == NULL)) {
294		/* FIXME */
295		/*
296		 * If the request returns an error then we need to do a diag
297		 * reset
298		 */
299		printf("%s: request for page completed with error %d",
300		    __func__, error);
301		error = ENXIO;
302		goto out;
303	}
304	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
305	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
306	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
307		/* FIXME */
308		/*
309		 * If the request returns an error then we need to do a diag
310		 * reset
311		 */
312		printf("%s: page read with error; iocstatus = 0x%x\n",
313		    __func__, ioc_status);
314		error = ENXIO;
315		goto out;
316	}
317	bcopy(page, config_page, MIN(cm->cm_length,
318	    (sizeof(Mpi2IOUnitPage8_t))));
319
320out:
321	free(page, M_MPR);
322	if (cm)
323		mpr_free_command(sc, cm);
324	return (error);
325}
326
327/**
328 * mpr_config_get_man_pg11 - obtain manufacturing page 11
329 * @sc: per adapter object
330 * @mpi_reply: reply mf payload returned from firmware
331 * @config_page: contents of the config page
332 * Context: sleep.
333 *
334 * Returns 0 for success, non-zero for failure.
335 */
336int
337mpr_config_get_man_pg11(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
338    Mpi2ManufacturingPage11_t *config_page)
339{
340	MPI2_CONFIG_REQUEST *request;
341	MPI2_CONFIG_REPLY *reply;
342	struct mpr_command *cm;
343	MPI2_CONFIG_PAGE_MAN_11 *page = NULL;
344	int error = 0;
345	u16 ioc_status;
346
347	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
348
349	if ((cm = mpr_alloc_command(sc)) == NULL) {
350		printf("%s: command alloc failed @ line %d\n", __func__,
351		    __LINE__);
352		error = EBUSY;
353		goto out;
354	}
355	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
356	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
357	request->Function = MPI2_FUNCTION_CONFIG;
358	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
359	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
360	request->Header.PageNumber = 11;
361	request->Header.PageLength = request->Header.PageVersion = 0;
362	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
363	cm->cm_data = NULL;
364	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
365	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
366	if (error || (reply == NULL)) {
367		/* FIXME */
368		/*
369		 * If the request returns an error then we need to do a diag
370		 * reset
371		 */
372		printf("%s: request for header completed with error %d",
373		    __func__, error);
374		error = ENXIO;
375		goto out;
376	}
377	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
378	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
379	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
380		/* FIXME */
381		/*
382		 * If the request returns an error then we need to do a diag
383		 * reset
384		 */
385		printf("%s: header read with error; iocstatus = 0x%x\n",
386		    __func__, ioc_status);
387		error = ENXIO;
388		goto out;
389	}
390	/* We have to do free and alloc for the reply-free and reply-post
391	 * counters to match - Need to review the reply FIFO handling.
392	 */
393	mpr_free_command(sc, cm);
394
395	if ((cm = mpr_alloc_command(sc)) == NULL) {
396		printf("%s: command alloc failed @ line %d\n", __func__,
397		    __LINE__);
398		error = EBUSY;
399		goto out;
400	}
401	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
402	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
403	request->Function = MPI2_FUNCTION_CONFIG;
404	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
405	request->Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
406	request->Header.PageNumber = 11;
407	request->Header.PageVersion = mpi_reply->Header.PageVersion;
408	request->Header.PageLength = mpi_reply->Header.PageLength;
409	cm->cm_length = mpi_reply->Header.PageLength * 4;
410	cm->cm_sge = &request->PageBufferSGE;
411	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
412	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
413	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
414	page = malloc((cm->cm_length), M_MPR, M_ZERO | M_NOWAIT);
415	if (!page) {
416		printf("%s: page alloc failed\n", __func__);
417		error = ENOMEM;
418		goto out;
419	}
420	cm->cm_data = page;
421
422	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
423	reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
424	if (error || (reply == NULL)) {
425		/* FIXME */
426		/*
427		 * If the request returns an error then we need to do a diag
428		 * reset
429		 */
430		printf("%s: request for page completed with error %d",
431		    __func__, error);
432		error = ENXIO;
433		goto out;
434	}
435	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
436	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
437	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
438		/* FIXME */
439		/*
440		 * If the request returns an error then we need to do a diag
441		 * reset
442		 */
443		printf("%s: page read with error; iocstatus = 0x%x\n",
444		    __func__, ioc_status);
445		error = ENXIO;
446		goto out;
447	}
448	bcopy(page, config_page, MIN(cm->cm_length,
449	    (sizeof(Mpi2ManufacturingPage11_t))));
450
451out:
452	free(page, M_MPR);
453	if (cm)
454		mpr_free_command(sc, cm);
455	return (error);
456}
457
458/**
459 * mpr_base_static_config_pages - static start of day config pages.
460 * @sc: per adapter object
461 *
462 * Return nothing.
463 */
464void
465mpr_base_static_config_pages(struct mpr_softc *sc)
466{
467	Mpi2ConfigReply_t		mpi_reply;
468	Mpi2ManufacturingPage11_t	man_pg11;
469	int				retry, rc;
470
471	retry = 0;
472	while (mpr_config_get_ioc_pg8(sc, &mpi_reply, &sc->ioc_pg8)) {
473		retry++;
474		if (retry > 5) {
475			/* We need to Handle this situation */
476			/*FIXME*/
477			break;
478		}
479	}
480	retry = 0;
481	while (mpr_config_get_iounit_pg8(sc, &mpi_reply, &sc->iounit_pg8)) {
482		retry++;
483		if (retry > 5) {
484			/* We need to Handle this situation */
485			/*FIXME*/
486			break;
487		}
488	}
489	retry = 0;
490	while ((rc = mpr_config_get_man_pg11(sc, &mpi_reply, &man_pg11))) {
491		retry++;
492		if (retry > 5) {
493			/* We need to Handle this situation */
494			/*FIXME*/
495			break;
496		}
497	}
498
499	if (!rc) {
500		sc->custom_nvme_tm_handling = (le16toh(man_pg11.AddlFlags2) &
501		    MPI2_MAN_PG11_ADDLFLAGS2_CUSTOM_TM_HANDLING_MASK);
502		sc->nvme_abort_timeout = man_pg11.NVMeAbortTO;
503
504		/* Minimum NVMe Abort timeout value should be 6 seconds &
505		 * maximum value should be 60 seconds.
506		 */
507		if (sc->nvme_abort_timeout < 6)
508			sc->nvme_abort_timeout = 6;
509		if (sc->nvme_abort_timeout > 60)
510			sc->nvme_abort_timeout = 60;
511	}
512}
513
514/**
515 * mpr_config_get_dpm_pg0 - obtain driver persistent mapping page0
516 * @sc: per adapter object
517 * @mpi_reply: reply mf payload returned from firmware
518 * @config_page: contents of the config page
519 * @sz: size of buffer passed in config_page
520 * Context: sleep.
521 *
522 * Returns 0 for success, non-zero for failure.
523 */
524int
525mpr_config_get_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
526    Mpi2DriverMappingPage0_t *config_page, u16 sz)
527{
528	MPI2_CONFIG_REQUEST *request;
529	MPI2_CONFIG_REPLY *reply;
530	struct mpr_command *cm;
531	Mpi2DriverMappingPage0_t *page = NULL;
532	int error = 0;
533	u16 ioc_status;
534
535	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
536
537	memset(config_page, 0, sz);
538	if ((cm = mpr_alloc_command(sc)) == NULL) {
539		printf("%s: command alloc failed @ line %d\n", __func__,
540		    __LINE__);
541		error = EBUSY;
542		goto out;
543	}
544	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
545	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
546	request->Function = MPI2_FUNCTION_CONFIG;
547	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
548	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
549	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
550	request->Header.PageNumber = 0;
551	request->ExtPageLength = request->Header.PageVersion = 0;
552	request->PageAddress = sc->max_dpm_entries <<
553	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
554	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
555	cm->cm_data = NULL;
556	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
557	if (cm != NULL)
558		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
559	if (error || (reply == NULL)) {
560		/* FIXME */
561		/*
562		 * If the request returns an error then we need to do a diag
563		 * reset
564		 */
565		printf("%s: request for header completed with error %d",
566		    __func__, error);
567		error = ENXIO;
568		goto out;
569	}
570	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
571	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
572	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
573		/* FIXME */
574		/*
575		 * If the request returns an error then we need to do a diag
576		 * reset
577		 */
578		printf("%s: header read with error; iocstatus = 0x%x\n",
579		    __func__, ioc_status);
580		error = ENXIO;
581		goto out;
582	}
583	/* We have to do free and alloc for the reply-free and reply-post
584	 * counters to match - Need to review the reply FIFO handling.
585	 */
586	mpr_free_command(sc, cm);
587
588	if ((cm = mpr_alloc_command(sc)) == NULL) {
589		printf("%s: command alloc failed @ line %d\n", __func__,
590		    __LINE__);
591		error = EBUSY;
592		goto out;
593	}
594	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
595	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
596	request->Function = MPI2_FUNCTION_CONFIG;
597	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_NVRAM;
598	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
599	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
600	request->Header.PageNumber = 0;
601	request->Header.PageVersion = mpi_reply->Header.PageVersion;
602	request->PageAddress = sc->max_dpm_entries <<
603	    MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
604	request->ExtPageLength = mpi_reply->ExtPageLength;
605	cm->cm_length = le16toh(request->ExtPageLength) * 4;
606	cm->cm_sge = &request->PageBufferSGE;
607	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
608	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
609	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
610	page = malloc(cm->cm_length, M_MPR, M_ZERO|M_NOWAIT);
611	if (!page) {
612		printf("%s: page alloc failed\n", __func__);
613		error = ENOMEM;
614		goto out;
615	}
616	cm->cm_data = page;
617	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
618	if (cm != NULL)
619		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
620	if (error || (reply == NULL)) {
621		/* FIXME */
622		/*
623		 * If the request returns an error then we need to do a diag
624		 * reset
625		 */
626		printf("%s: request for page completed with error %d",
627		    __func__, error);
628		error = ENXIO;
629		goto out;
630	}
631	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
632	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
633	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
634		/* FIXME */
635		/*
636		 * If the request returns an error then we need to do a diag
637		 * reset
638		 */
639		printf("%s: page read with error; iocstatus = 0x%x\n",
640		    __func__, ioc_status);
641		error = ENXIO;
642		goto out;
643	}
644	bcopy(page, config_page, MIN(cm->cm_length, sz));
645out:
646	free(page, M_MPR);
647	if (cm)
648		mpr_free_command(sc, cm);
649	return (error);
650}
651
652/**
653 * mpr_config_set_dpm_pg0 - write an entry in driver persistent mapping page0
654 * @sc: per adapter object
655 * @mpi_reply: reply mf payload returned from firmware
656 * @config_page: contents of the config page
657 * @entry_idx: entry index in DPM Page0 to be modified
658 * Context: sleep.
659 *
660 * Returns 0 for success, non-zero for failure.
661 */
662
663int mpr_config_set_dpm_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
664    Mpi2DriverMappingPage0_t *config_page, u16 entry_idx)
665{
666	MPI2_CONFIG_REQUEST *request;
667	MPI2_CONFIG_REPLY *reply;
668	struct mpr_command *cm;
669	MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 *page = NULL;
670	int error = 0;
671	u16 ioc_status;
672
673	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
674
675	if ((cm = mpr_alloc_command(sc)) == NULL) {
676		printf("%s: command alloc failed @ line %d\n", __func__,
677		    __LINE__);
678		error = EBUSY;
679		goto out;
680	}
681	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
682	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
683	request->Function = MPI2_FUNCTION_CONFIG;
684	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
685	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
686	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
687	request->Header.PageNumber = 0;
688	request->ExtPageLength = request->Header.PageVersion = 0;
689	/* We can remove below two lines ????*/
690	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
691	request->PageAddress |= htole16(entry_idx);
692	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
693	cm->cm_data = NULL;
694	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
695	if (cm != NULL)
696		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
697	if (error || (reply == NULL)) {
698		/* FIXME */
699		/*
700		 * If the request returns an error then we need to do a diag
701		 * reset
702		 */
703		printf("%s: request for header completed with error %d",
704		    __func__, error);
705		error = ENXIO;
706		goto out;
707	}
708	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
709	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
710	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
711		/* FIXME */
712		/*
713		 * If the request returns an error then we need to do a diag
714		 * reset
715		 */
716		printf("%s: header read with error; iocstatus = 0x%x\n",
717		    __func__, ioc_status);
718		error = ENXIO;
719		goto out;
720	}
721	/* We have to do free and alloc for the reply-free and reply-post
722	 * counters to match - Need to review the reply FIFO handling.
723	 */
724	mpr_free_command(sc, cm);
725
726	if ((cm = mpr_alloc_command(sc)) == NULL) {
727		printf("%s: command alloc failed @ line %d\n", __func__,
728		    __LINE__);
729		error = EBUSY;
730		goto out;
731	}
732	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
733	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
734	request->Function = MPI2_FUNCTION_CONFIG;
735	request->Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
736	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
737	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING;
738	request->Header.PageNumber = 0;
739	request->Header.PageVersion = mpi_reply->Header.PageVersion;
740	request->ExtPageLength = mpi_reply->ExtPageLength;
741	request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
742	request->PageAddress |= htole16(entry_idx);
743	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
744	cm->cm_sge = &request->PageBufferSGE;
745	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
746	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAOUT;
747	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
748	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
749	if (!page) {
750		printf("%s: page alloc failed\n", __func__);
751		error = ENOMEM;
752		goto out;
753	}
754	bcopy(config_page, page, MIN(cm->cm_length,
755	    (sizeof(Mpi2DriverMappingPage0_t))));
756	cm->cm_data = page;
757	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
758	if (cm != NULL)
759		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
760	if (error || (reply == NULL)) {
761		/* FIXME */
762		/*
763		 * If the request returns an error then we need to do a diag
764		 * reset
765		 */
766		printf("%s: request to write page completed with error %d",
767		    __func__, error);
768		error = ENXIO;
769		goto out;
770	}
771	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
772	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
773	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
774		/* FIXME */
775		/*
776		 * If the request returns an error then we need to do a diag
777		 * reset
778		 */
779		printf("%s: page written with error; iocstatus = 0x%x\n",
780		    __func__, ioc_status);
781		error = ENXIO;
782		goto out;
783	}
784out:
785	free(page, M_MPR);
786	if (cm)
787		mpr_free_command(sc, cm);
788	return (error);
789}
790
791/**
792 * mpr_config_get_sas_device_pg0 - obtain sas device page 0
793 * @sc: per adapter object
794 * @mpi_reply: reply mf payload returned from firmware
795 * @config_page: contents of the config page
796 * @form: GET_NEXT_HANDLE or HANDLE
797 * @handle: device handle
798 * Context: sleep.
799 *
800 * Returns 0 for success, non-zero for failure.
801 */
802int
803mpr_config_get_sas_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
804    *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
805{
806	MPI2_CONFIG_REQUEST *request;
807	MPI2_CONFIG_REPLY *reply;
808	struct mpr_command *cm;
809	Mpi2SasDevicePage0_t *page = NULL;
810	int error = 0;
811	u16 ioc_status;
812
813	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
814
815	if ((cm = mpr_alloc_command(sc)) == NULL) {
816		printf("%s: command alloc failed @ line %d\n", __func__,
817		    __LINE__);
818		error = EBUSY;
819		goto out;
820	}
821	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
822	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
823	request->Function = MPI2_FUNCTION_CONFIG;
824	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
825	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
826	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
827	request->Header.PageNumber = 0;
828	request->ExtPageLength = request->Header.PageVersion = 0;
829	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
830	cm->cm_data = NULL;
831	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
832	if (cm != NULL)
833		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
834	if (error || (reply == NULL)) {
835		/* FIXME */
836		/*
837		 * If the request returns an error then we need to do a diag
838		 * reset
839		 */
840		printf("%s: request for header completed with error %d",
841		    __func__, error);
842		error = ENXIO;
843		goto out;
844	}
845	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
846	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
847	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
848		/* FIXME */
849		/*
850		 * If the request returns an error then we need to do a diag
851		 * reset
852		 */
853		printf("%s: header read with error; iocstatus = 0x%x\n",
854		    __func__, ioc_status);
855		error = ENXIO;
856		goto out;
857	}
858	/* We have to do free and alloc for the reply-free and reply-post
859	 * counters to match - Need to review the reply FIFO handling.
860	 */
861	mpr_free_command(sc, cm);
862
863	if ((cm = mpr_alloc_command(sc)) == NULL) {
864		printf("%s: command alloc failed @ line %d\n", __func__,
865		    __LINE__);
866		error = EBUSY;
867		goto out;
868	}
869	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
870	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
871	request->Function = MPI2_FUNCTION_CONFIG;
872	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
873	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
874	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
875	request->Header.PageNumber = 0;
876	request->Header.PageVersion = mpi_reply->Header.PageVersion;
877	request->ExtPageLength = mpi_reply->ExtPageLength;
878	request->PageAddress = htole32(form | handle);
879	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
880	cm->cm_sge = &request->PageBufferSGE;
881	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
882	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
883	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
884	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
885	if (!page) {
886		printf("%s: page alloc failed\n", __func__);
887		error = ENOMEM;
888		goto out;
889	}
890	cm->cm_data = page;
891
892	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
893	if (cm != NULL)
894		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
895	if (error || (reply == NULL)) {
896		/* FIXME */
897		/*
898		 * If the request returns an error then we need to do a diag
899		 * reset
900		 */
901		printf("%s: request for page completed with error %d",
902		    __func__, error);
903		error = ENXIO;
904		goto out;
905	}
906	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
907	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
908	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
909		/* FIXME */
910		/*
911		 * If the request returns an error then we need to do a diag
912		 * reset
913		 */
914		printf("%s: page read with error; iocstatus = 0x%x\n",
915		    __func__, ioc_status);
916		error = ENXIO;
917		goto out;
918	}
919	bcopy(page, config_page, MIN(cm->cm_length,
920	    sizeof(Mpi2SasDevicePage0_t)));
921out:
922	free(page, M_MPR);
923	if (cm)
924		mpr_free_command(sc, cm);
925	return (error);
926}
927
928/**
929 * mpr_config_get_pcie_device_pg0 - obtain PCIe device page 0
930 * @sc: per adapter object
931 * @mpi_reply: reply mf payload returned from firmware
932 * @config_page: contents of the config page
933 * @form: GET_NEXT_HANDLE or HANDLE
934 * @handle: device handle
935 * Context: sleep.
936 *
937 * Returns 0 for success, non-zero for failure.
938 */
939int
940mpr_config_get_pcie_device_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
941    *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, u32 form, u16 handle)
942{
943	MPI2_CONFIG_REQUEST *request;
944	MPI2_CONFIG_REPLY *reply;
945	struct mpr_command *cm;
946	Mpi26PCIeDevicePage0_t *page = NULL;
947	int error = 0;
948	u16 ioc_status;
949
950	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
951
952	if ((cm = mpr_alloc_command(sc)) == NULL) {
953		printf("%s: command alloc failed @ line %d\n", __func__,
954		    __LINE__);
955		error = EBUSY;
956		goto out;
957	}
958	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
959	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
960	request->Function = MPI2_FUNCTION_CONFIG;
961	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
962	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
963	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
964	request->Header.PageNumber = 0;
965	request->ExtPageLength = request->Header.PageVersion = 0;
966	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
967	cm->cm_data = NULL;
968	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
969	if (cm != NULL)
970		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
971	if (error || (reply == NULL)) {
972		/* FIXME */
973		/*
974		 * If the request returns an error then we need to do a diag
975		 * reset
976		 */
977		printf("%s: request for header completed with error %d",
978		    __func__, error);
979		error = ENXIO;
980		goto out;
981	}
982	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
983	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
984	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
985		/* FIXME */
986		/*
987		 * If the request returns an error then we need to do a diag
988		 * reset
989		 */
990		printf("%s: header read with error; iocstatus = 0x%x\n",
991		    __func__, ioc_status);
992		error = ENXIO;
993		goto out;
994	}
995	/* We have to do free and alloc for the reply-free and reply-post
996	 * counters to match - Need to review the reply FIFO handling.
997	 */
998	mpr_free_command(sc, cm);
999
1000	if ((cm = mpr_alloc_command(sc)) == NULL) {
1001		printf("%s: command alloc failed @ line %d\n", __func__,
1002		    __LINE__);
1003		error = EBUSY;
1004		goto out;
1005	}
1006	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1007	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1008	request->Function = MPI2_FUNCTION_CONFIG;
1009	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1010	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1011	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1012	request->Header.PageNumber = 0;
1013	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1014	request->ExtPageLength = mpi_reply->ExtPageLength;
1015	request->PageAddress = htole32(form | handle);
1016	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
1017	cm->cm_sge = &request->PageBufferSGE;
1018	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1019	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1020	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1021	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1022	if (!page) {
1023		printf("%s: page alloc failed\n", __func__);
1024		error = ENOMEM;
1025		goto out;
1026	}
1027	cm->cm_data = page;
1028
1029	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1030	if (cm != NULL)
1031		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1032	if (error || (reply == NULL)) {
1033		/* FIXME */
1034		/*
1035		 * If the request returns an error then we need to do a diag
1036		 * reset
1037		 */
1038		printf("%s: request for page completed with error %d",
1039		    __func__, error);
1040		error = ENXIO;
1041		goto out;
1042	}
1043	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1044	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1045	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1046		/* FIXME */
1047		/*
1048		 * If the request returns an error then we need to do a diag
1049		 * reset
1050		 */
1051		printf("%s: page read with error; iocstatus = 0x%x\n",
1052		    __func__, ioc_status);
1053		error = ENXIO;
1054		goto out;
1055	}
1056	bcopy(page, config_page, MIN(cm->cm_length,
1057	    sizeof(Mpi26PCIeDevicePage0_t)));
1058out:
1059	free(page, M_MPR);
1060	if (cm)
1061		mpr_free_command(sc, cm);
1062	return (error);
1063}
1064
1065/**
1066 * mpr_config_get_pcie_device_pg2 - obtain PCIe device page 2
1067 * @sc: per adapter object
1068 * @mpi_reply: reply mf payload returned from firmware
1069 * @config_page: contents of the config page
1070 * @form: GET_NEXT_HANDLE or HANDLE
1071 * @handle: device handle
1072 * Context: sleep.
1073 *
1074 * Returns 0 for success, non-zero for failure.
1075 */
1076int
1077mpr_config_get_pcie_device_pg2(struct mpr_softc *sc, Mpi2ConfigReply_t
1078    *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, u32 form, u16 handle)
1079{
1080	MPI2_CONFIG_REQUEST *request;
1081	MPI2_CONFIG_REPLY *reply;
1082	struct mpr_command *cm;
1083	Mpi26PCIeDevicePage2_t *page = NULL;
1084	int error = 0;
1085	u16 ioc_status;
1086
1087	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1088
1089	if ((cm = mpr_alloc_command(sc)) == NULL) {
1090		printf("%s: command alloc failed @ line %d\n", __func__,
1091		    __LINE__);
1092		error = EBUSY;
1093		goto out;
1094	}
1095	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1096	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1097	request->Function = MPI2_FUNCTION_CONFIG;
1098	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1099	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1100	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1101	request->Header.PageNumber = 2;
1102	request->ExtPageLength = request->Header.PageVersion = 0;
1103	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1104	cm->cm_data = NULL;
1105	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1106	if (cm != NULL)
1107		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1108	if (error || (reply == NULL)) {
1109		/* FIXME */
1110		/*
1111		 * If the request returns an error then we need to do a diag
1112		 * reset
1113		 */
1114		printf("%s: request for header completed with error %d",
1115		    __func__, error);
1116		error = ENXIO;
1117		goto out;
1118	}
1119	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1120	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1121	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1122		/* FIXME */
1123		/*
1124		 * If the request returns an error then we need to do a diag
1125		 * reset
1126		 */
1127		printf("%s: header read with error; iocstatus = 0x%x\n",
1128		    __func__, ioc_status);
1129		error = ENXIO;
1130		goto out;
1131	}
1132	/* We have to do free and alloc for the reply-free and reply-post
1133	 * counters to match - Need to review the reply FIFO handling.
1134	 */
1135	mpr_free_command(sc, cm);
1136
1137	if ((cm = mpr_alloc_command(sc)) == NULL) {
1138		printf("%s: command alloc failed @ line %d\n", __func__,
1139		    __LINE__);
1140		error = EBUSY;
1141		goto out;
1142	}
1143	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1144	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1145	request->Function = MPI2_FUNCTION_CONFIG;
1146	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1147	request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1148	request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
1149	request->Header.PageNumber = 2;
1150	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1151	request->ExtPageLength = mpi_reply->ExtPageLength;
1152	request->PageAddress = htole32(form | handle);
1153	cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
1154	cm->cm_sge = &request->PageBufferSGE;
1155	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1156	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1157	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1158	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1159	if (!page) {
1160		printf("%s: page alloc failed\n", __func__);
1161		error = ENOMEM;
1162		goto out;
1163	}
1164	cm->cm_data = page;
1165
1166	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1167	if (cm != NULL)
1168		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1169	if (error || (reply == NULL)) {
1170		/* FIXME */
1171		/*
1172		 * If the request returns an error then we need to do a diag
1173		 * reset
1174		 */
1175		printf("%s: request for page completed with error %d",
1176		    __func__, error);
1177		error = ENXIO;
1178		goto out;
1179	}
1180	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1181	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1182	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1183		/* FIXME */
1184		/*
1185		 * If the request returns an error then we need to do a diag
1186		 * reset
1187		 */
1188		printf("%s: page read with error; iocstatus = 0x%x\n",
1189		    __func__, ioc_status);
1190		error = ENXIO;
1191		goto out;
1192	}
1193	bcopy(page, config_page, MIN(cm->cm_length,
1194	    sizeof(Mpi26PCIeDevicePage2_t)));
1195out:
1196	free(page, M_MPR);
1197	if (cm)
1198		mpr_free_command(sc, cm);
1199	return (error);
1200}
1201
1202/**
1203 * mpr_config_get_bios_pg3 - obtain BIOS page 3
1204 * @sc: per adapter object
1205 * @mpi_reply: reply mf payload returned from firmware
1206 * @config_page: contents of the config page
1207 * Context: sleep.
1208 *
1209 * Returns 0 for success, non-zero for failure.
1210 */
1211int
1212mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1213    Mpi2BiosPage3_t *config_page)
1214{
1215	MPI2_CONFIG_REQUEST *request;
1216	MPI2_CONFIG_REPLY *reply;
1217	struct mpr_command *cm;
1218	Mpi2BiosPage3_t *page = NULL;
1219	int error = 0;
1220	u16 ioc_status;
1221
1222	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1223
1224	if ((cm = mpr_alloc_command(sc)) == NULL) {
1225		printf("%s: command alloc failed @ line %d\n", __func__,
1226		    __LINE__);
1227		error = EBUSY;
1228		goto out;
1229	}
1230	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1231	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1232	request->Function = MPI2_FUNCTION_CONFIG;
1233	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1234	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1235	request->Header.PageNumber = 3;
1236	request->Header.PageLength = request->Header.PageVersion = 0;
1237	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1238	cm->cm_data = NULL;
1239	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1240	if (cm != NULL)
1241		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1242	if (error || (reply == NULL)) {
1243		/* FIXME */
1244		/*
1245		 * If the request returns an error then we need to do a diag
1246		 * reset
1247		 */
1248		printf("%s: request for header completed with error %d",
1249		    __func__, error);
1250		error = ENXIO;
1251		goto out;
1252	}
1253	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1254	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1255	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1256		/* FIXME */
1257		/*
1258		 * If the request returns an error then we need to do a diag
1259		 * reset
1260		 */
1261		printf("%s: header read with error; iocstatus = 0x%x\n",
1262		    __func__, ioc_status);
1263		error = ENXIO;
1264		goto out;
1265	}
1266	/* We have to do free and alloc for the reply-free and reply-post
1267	 * counters to match - Need to review the reply FIFO handling.
1268	 */
1269	mpr_free_command(sc, cm);
1270
1271	if ((cm = mpr_alloc_command(sc)) == NULL) {
1272		printf("%s: command alloc failed @ line %d\n", __func__,
1273		    __LINE__);
1274		error = EBUSY;
1275		goto out;
1276	}
1277	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1278	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1279	request->Function = MPI2_FUNCTION_CONFIG;
1280	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1281	request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
1282	request->Header.PageNumber = 3;
1283	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1284	request->Header.PageLength = mpi_reply->Header.PageLength;
1285	cm->cm_length = mpi_reply->Header.PageLength * 4;
1286	cm->cm_sge = &request->PageBufferSGE;
1287	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1288	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1289	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1290	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1291	if (!page) {
1292		printf("%s: page alloc failed\n", __func__);
1293		error = ENOMEM;
1294		goto out;
1295	}
1296	cm->cm_data = page;
1297
1298	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1299	if (cm != NULL)
1300		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1301	if (error || (reply == NULL)) {
1302		/* FIXME */
1303		/*
1304		 * If the request returns an error then we need to do a diag
1305		 * reset
1306		 */
1307		printf("%s: request for page completed with error %d",
1308		    __func__, error);
1309		error = ENXIO;
1310		goto out;
1311	}
1312	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1313	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1314	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1315		/* FIXME */
1316		/*
1317		 * If the request returns an error then we need to do a diag
1318		 * reset
1319		 */
1320		printf("%s: page read with error; iocstatus = 0x%x\n",
1321		    __func__, ioc_status);
1322		error = ENXIO;
1323		goto out;
1324	}
1325	bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1326out:
1327	free(page, M_MPR);
1328	if (cm)
1329		mpr_free_command(sc, cm);
1330	return (error);
1331}
1332
1333/**
1334 * mpr_config_get_raid_volume_pg0 - obtain raid volume page 0
1335 * @sc: per adapter object
1336 * @mpi_reply: reply mf payload returned from firmware
1337 * @config_page: contents of the config page
1338 * @page_address: form and handle value used to get page
1339 * Context: sleep.
1340 *
1341 * Returns 0 for success, non-zero for failure.
1342 */
1343int
1344mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t
1345    *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1346{
1347	MPI2_CONFIG_REQUEST *request;
1348	MPI2_CONFIG_REPLY *reply = NULL;
1349	struct mpr_command *cm;
1350	Mpi2RaidVolPage0_t *page = NULL;
1351	int error = 0;
1352	u16 ioc_status;
1353
1354	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1355
1356	if ((cm = mpr_alloc_command(sc)) == NULL) {
1357		printf("%s: command alloc failed @ line %d\n", __func__,
1358		    __LINE__);
1359		error = EBUSY;
1360		goto out;
1361	}
1362	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1363	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1364	request->Function = MPI2_FUNCTION_CONFIG;
1365	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1366	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1367	request->Header.PageNumber = 0;
1368	request->Header.PageLength = request->Header.PageVersion = 0;
1369	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1370	cm->cm_data = NULL;
1371
1372	/*
1373	 * This page must be polled because the IOC isn't ready yet when this
1374	 * page is needed.
1375	 */
1376	error = mpr_request_polled(sc, &cm);
1377	if (cm != NULL)
1378		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1379	if (error || (reply == NULL)) {
1380		/* FIXME */
1381		/* If the poll returns error then we need to do diag reset */
1382		printf("%s: poll for header completed with error %d",
1383		    __func__, error);
1384		error = ENXIO;
1385		goto out;
1386	}
1387	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1388	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1389	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1390		/* FIXME */
1391		/* If the poll returns error then we need to do diag reset */
1392		printf("%s: header read with error; iocstatus = 0x%x\n",
1393		    __func__, ioc_status);
1394		error = ENXIO;
1395		goto out;
1396	}
1397	/* We have to do free and alloc for the reply-free and reply-post
1398	 * counters to match - Need to review the reply FIFO handling.
1399	 */
1400	mpr_free_command(sc, cm);
1401
1402	if ((cm = mpr_alloc_command(sc)) == NULL) {
1403		printf("%s: command alloc failed @ line %d\n", __func__,
1404		    __LINE__);
1405		error = EBUSY;
1406		goto out;
1407	}
1408	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1409	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1410	request->Function = MPI2_FUNCTION_CONFIG;
1411	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1412	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1413	request->Header.PageNumber = 0;
1414	request->Header.PageLength = mpi_reply->Header.PageLength;
1415	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1416	request->PageAddress = page_address;
1417	cm->cm_length = mpi_reply->Header.PageLength * 4;
1418	cm->cm_sge = &request->PageBufferSGE;
1419	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1420	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1421	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1422	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1423	if (!page) {
1424		printf("%s: page alloc failed\n", __func__);
1425		error = ENOMEM;
1426		goto out;
1427	}
1428	cm->cm_data = page;
1429
1430	/*
1431	 * This page must be polled because the IOC isn't ready yet when this
1432	 * page is needed.
1433	 */
1434	error = mpr_request_polled(sc, &cm);
1435	if (cm != NULL)
1436		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1437	if (error || (reply == NULL)) {
1438		/* FIXME */
1439		/* If the poll returns error then we need to do diag reset */
1440		printf("%s: poll for page completed with error %d",
1441		    __func__, error);
1442		error = ENXIO;
1443		goto out;
1444	}
1445	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1446	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1447	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1448		/* FIXME */
1449		/* If the poll returns error then we need to do diag reset */
1450		printf("%s: page read with error; iocstatus = 0x%x\n",
1451		    __func__, ioc_status);
1452		error = ENXIO;
1453		goto out;
1454	}
1455	bcopy(page, config_page, cm->cm_length);
1456out:
1457	free(page, M_MPR);
1458	if (cm)
1459		mpr_free_command(sc, cm);
1460	return (error);
1461}
1462
1463/**
1464 * mpr_config_get_raid_volume_pg1 - obtain raid volume page 1
1465 * @sc: per adapter object
1466 * @mpi_reply: reply mf payload returned from firmware
1467 * @config_page: contents of the config page
1468 * @form: GET_NEXT_HANDLE or HANDLE
1469 * @handle: volume handle
1470 * Context: sleep.
1471 *
1472 * Returns 0 for success, non-zero for failure.
1473 */
1474int
1475mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t
1476    *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1477{
1478	MPI2_CONFIG_REQUEST *request;
1479	MPI2_CONFIG_REPLY *reply;
1480	struct mpr_command *cm;
1481	Mpi2RaidVolPage1_t *page = NULL;
1482	int error = 0;
1483	u16 ioc_status;
1484
1485	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1486
1487	if ((cm = mpr_alloc_command(sc)) == NULL) {
1488		printf("%s: command alloc failed @ line %d\n", __func__,
1489		    __LINE__);
1490		error = EBUSY;
1491		goto out;
1492	}
1493	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1494	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1495	request->Function = MPI2_FUNCTION_CONFIG;
1496	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1497	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1498	request->Header.PageNumber = 1;
1499	request->Header.PageLength = request->Header.PageVersion = 0;
1500	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1501	cm->cm_data = NULL;
1502	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1503	if (cm != NULL)
1504		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1505	if (error || (reply == NULL)) {
1506		/* FIXME */
1507		/*
1508		 * If the request returns an error then we need to do a diag
1509		 * reset
1510		 */
1511		printf("%s: request for header completed with error %d",
1512		    __func__, error);
1513		error = ENXIO;
1514		goto out;
1515	}
1516	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1517	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1518	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1519		/* FIXME */
1520		/*
1521		 * If the request returns an error then we need to do a diag
1522		 * reset
1523		 */
1524		printf("%s: header read with error; iocstatus = 0x%x\n",
1525		    __func__, ioc_status);
1526		error = ENXIO;
1527		goto out;
1528	}
1529	/* We have to do free and alloc for the reply-free and reply-post
1530	 * counters to match - Need to review the reply FIFO handling.
1531	 */
1532	mpr_free_command(sc, cm);
1533
1534	if ((cm = mpr_alloc_command(sc)) == NULL) {
1535		printf("%s: command alloc failed @ line %d\n", __func__,
1536		    __LINE__);
1537		error = EBUSY;
1538		goto out;
1539	}
1540	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1541	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1542	request->Function = MPI2_FUNCTION_CONFIG;
1543	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1544	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1545	request->Header.PageNumber = 1;
1546	request->Header.PageLength = mpi_reply->Header.PageLength;
1547	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1548	request->PageAddress = htole32(form | handle);
1549	cm->cm_length = mpi_reply->Header.PageLength * 4;
1550	cm->cm_sge = &request->PageBufferSGE;
1551	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1552	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1553	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1554	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1555	if (!page) {
1556		printf("%s: page alloc failed\n", __func__);
1557		error = ENOMEM;
1558		goto out;
1559	}
1560	cm->cm_data = page;
1561
1562	error = mpr_wait_command(sc, &cm, 60, CAN_SLEEP);
1563	if (cm != NULL)
1564		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1565	if (error || (reply == NULL)) {
1566		/* FIXME */
1567		/*
1568		 * If the request returns an error then we need to do a diag
1569		 * reset
1570		 */
1571		printf("%s: request for page completed with error %d",
1572		    __func__, error);
1573		error = ENXIO;
1574		goto out;
1575	}
1576	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1577	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1578	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1579		/* FIXME */
1580		/*
1581		 * If the request returns an error then we need to do a diag
1582		 * reset
1583		 */
1584		printf("%s: page read with error; iocstatus = 0x%x\n",
1585		    __func__, ioc_status);
1586		error = ENXIO;
1587		goto out;
1588	}
1589	bcopy(page, config_page, MIN(cm->cm_length,
1590	    sizeof(Mpi2RaidVolPage1_t)));
1591out:
1592	free(page, M_MPR);
1593	if (cm)
1594		mpr_free_command(sc, cm);
1595	return (error);
1596}
1597
1598/**
1599 * mpr_config_get_volume_wwid - returns wwid given the volume handle
1600 * @sc: per adapter object
1601 * @volume_handle: volume handle
1602 * @wwid: volume wwid
1603 * Context: sleep.
1604 *
1605 * Returns 0 for success, non-zero for failure.
1606 */
1607int
1608mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid)
1609{
1610	Mpi2ConfigReply_t mpi_reply;
1611	Mpi2RaidVolPage1_t raid_vol_pg1;
1612
1613	*wwid = 0;
1614	if (!(mpr_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1615	    MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1616		*wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1617		    raid_vol_pg1.WWID.Low);
1618		return 0;
1619	} else
1620		return -1;
1621}
1622
1623/**
1624 * mpr_config_get_pd_pg0 - obtain raid phys disk page 0
1625 * @sc: per adapter object
1626 * @mpi_reply: reply mf payload returned from firmware
1627 * @config_page: contents of the config page
1628 * @page_address: form and handle value used to get page
1629 * Context: sleep.
1630 *
1631 * Returns 0 for success, non-zero for failure.
1632 */
1633int
1634mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1635    Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1636{
1637	MPI2_CONFIG_REQUEST *request;
1638	MPI2_CONFIG_REPLY *reply = NULL;
1639	struct mpr_command *cm;
1640	Mpi2RaidPhysDiskPage0_t *page = NULL;
1641	int error = 0;
1642	u16 ioc_status;
1643
1644	mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
1645
1646	if ((cm = mpr_alloc_command(sc)) == NULL) {
1647		printf("%s: command alloc failed @ line %d\n", __func__,
1648		    __LINE__);
1649		error = EBUSY;
1650		goto out;
1651	}
1652	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1653	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1654	request->Function = MPI2_FUNCTION_CONFIG;
1655	request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1656	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1657	request->Header.PageNumber = 0;
1658	request->Header.PageLength = request->Header.PageVersion = 0;
1659	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1660	cm->cm_data = NULL;
1661
1662	/*
1663	 * This page must be polled because the IOC isn't ready yet when this
1664	 * page is needed.
1665	 */
1666	error = mpr_request_polled(sc, &cm);
1667	if (cm != NULL)
1668		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1669	if (error || (reply == NULL)) {
1670		/* FIXME */
1671		/* If the poll returns error then we need to do diag reset */
1672		printf("%s: poll for header completed with error %d",
1673		    __func__, error);
1674		error = ENXIO;
1675		goto out;
1676	}
1677	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1678	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1679	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1680		/* FIXME */
1681		/* If the poll returns error then we need to do diag reset */
1682		printf("%s: header read with error; iocstatus = 0x%x\n",
1683		    __func__, ioc_status);
1684		error = ENXIO;
1685		goto out;
1686	}
1687	/* We have to do free and alloc for the reply-free and reply-post
1688	 * counters to match - Need to review the reply FIFO handling.
1689	 */
1690	mpr_free_command(sc, cm);
1691
1692	if ((cm = mpr_alloc_command(sc)) == NULL) {
1693		printf("%s: command alloc failed @ line %d\n", __func__,
1694		    __LINE__);
1695		error = EBUSY;
1696		goto out;
1697	}
1698	request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1699	bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1700	request->Function = MPI2_FUNCTION_CONFIG;
1701	request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1702	request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1703	request->Header.PageNumber = 0;
1704	request->Header.PageLength = mpi_reply->Header.PageLength;
1705	request->Header.PageVersion = mpi_reply->Header.PageVersion;
1706	request->PageAddress = page_address;
1707	cm->cm_length = mpi_reply->Header.PageLength * 4;
1708	cm->cm_sge = &request->PageBufferSGE;
1709	cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1710	cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
1711	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1712	page = malloc(cm->cm_length, M_MPR, M_ZERO | M_NOWAIT);
1713	if (!page) {
1714		printf("%s: page alloc failed\n", __func__);
1715		error = ENOMEM;
1716		goto out;
1717	}
1718	cm->cm_data = page;
1719
1720	/*
1721	 * This page must be polled because the IOC isn't ready yet when this
1722	 * page is needed.
1723	 */
1724	error = mpr_request_polled(sc, &cm);
1725	if (cm != NULL)
1726		reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1727	if (error || (reply == NULL)) {
1728		/* FIXME */
1729		/* If the poll returns error then we need to do diag reset */
1730		printf("%s: poll for page completed with error %d",
1731		    __func__, error);
1732		error = ENXIO;
1733		goto out;
1734	}
1735	ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1736	bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1737	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1738		/* FIXME */
1739		/* If the poll returns error then we need to do diag reset */
1740		printf("%s: page read with error; iocstatus = 0x%x\n",
1741		    __func__, ioc_status);
1742		error = ENXIO;
1743		goto out;
1744	}
1745	bcopy(page, config_page, MIN(cm->cm_length,
1746	    sizeof(Mpi2RaidPhysDiskPage0_t)));
1747out:
1748	free(page, M_MPR);
1749	if (cm)
1750		mpr_free_command(sc, cm);
1751	return (error);
1752}
1753