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