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