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