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