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