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