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