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