]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/mpr/mpr_config.c
Free the arm64 bootparams memory after initarm
[FreeBSD/FreeBSD.git] / sys / dev / mpr / mpr_config.c
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  */
71 int
72 mpr_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 =  le16toh(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
187 out:
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  */
203 int
204 mpr_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 =  le16toh(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
320 out:
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  */
336 int
337 mpr_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 =  le16toh(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
451 out:
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  */
464 void
465 mpr_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  */
524 int
525 mpr_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));
645 out:
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
663 int 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         }
784 out:
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  */
802 int
803 mpr_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)));
921 out:
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  */
939 int
940 mpr_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)));
1058 out:
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  */
1076 int
1077 mpr_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)));
1195 out:
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  */
1211 int
1212 mpr_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 = le16toh(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)));
1326 out:
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  */
1343 int
1344 mpr_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 = le16toh(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);
1456 out:
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  */
1474 int
1475 mpr_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 = le16toh(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)));
1591 out:
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  */
1607 int
1608 mpr_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  */
1633 int
1634 mpr_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 = le16toh(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)));
1747 out:
1748         free(page, M_MPR);
1749         if (cm)
1750                 mpr_free_command(sc, cm);
1751         return (error);
1752 }