]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/dev/mps/mps_config.c
MFC 230592:
[FreeBSD/stable/8.git] / sys / dev / mps / mps_config.c
1 /*-
2  * Copyright (c) 2011 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         request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
684         request->PageAddress |= htole16(entry_idx);
685         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
686         cm->cm_data = NULL;
687         error = mps_request_polled(sc, cm);
688         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
689         if (error || (reply == NULL)) {
690                 /* FIXME */
691                 /* If the poll returns error then we need to do diag reset */ 
692                 printf("%s: poll for header completed with error %d",
693                     __func__, error);
694                 error = ENXIO;
695                 goto out;
696         }
697         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
698         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
699         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
700                 /* FIXME */
701                 /* If the poll returns error then we need to do diag reset */ 
702                 printf("%s: header read with error; iocstatus = 0x%x\n",
703                     __func__, ioc_status);
704                 error = ENXIO;
705                 goto out;
706         }
707         /* We have to do free and alloc for the reply-free and reply-post
708          * counters to match - Need to review the reply FIFO handling.
709          */     
710         mps_free_command(sc, cm);
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_WRITE_NVRAM;
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         request->ExtPageLength = mpi_reply->ExtPageLength;
727         request->PageAddress = 1 << MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT;
728         request->PageAddress |= htole16(entry_idx);
729         cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
730         cm->cm_sge = &request->PageBufferSGE;
731         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
732         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAOUT;
733         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
734         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
735         if (!page) {
736                 printf("%s: page alloc failed\n", __func__);
737                 error = ENOMEM;
738                 goto out;
739         }
740         bcopy(config_page, page, MIN(cm->cm_length, 
741             (sizeof(Mpi2DriverMappingPage0_t))));
742         cm->cm_data = page;
743         error = mps_request_polled(sc, cm);
744         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
745         if (error || (reply == NULL)) {
746                 /* FIXME */
747                 /* If the poll returns error then we need to do diag reset */ 
748                 printf("%s: poll for page completed with error %d",
749                     __func__, error);
750                 error = ENXIO;
751                 goto out;
752         }
753         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
754         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
755         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
756                 /* FIXME */
757                 /* If the poll returns error then we need to do diag reset */ 
758                 printf("%s: page written with error; iocstatus = 0x%x\n",
759                     __func__, ioc_status);
760                 error = ENXIO;
761                 goto out;
762         }
763 out:
764         free(page, M_MPT2);
765         if (cm)
766                 mps_free_command(sc, cm);
767         return (error);
768 }
769
770 /**
771  * mps_config_get_sas_device_pg0 - obtain sas device page 0
772  * @sc: per adapter object
773  * @mpi_reply: reply mf payload returned from firmware
774  * @config_page: contents of the config page
775  * @form: GET_NEXT_HANDLE or HANDLE
776  * @handle: device handle
777  * Context: sleep.
778  *
779  * Returns 0 for success, non-zero for failure.
780  */
781 int
782 mps_config_get_sas_device_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
783     *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u16 handle)
784 {
785         MPI2_CONFIG_REQUEST *request;
786         MPI2_CONFIG_REPLY *reply;
787         struct mps_command *cm;
788         Mpi2SasDevicePage0_t *page = NULL;
789         int error = 0;
790         u16 ioc_status;
791
792         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
793
794         if ((cm = mps_alloc_command(sc)) == NULL) {
795                 printf("%s: command alloc failed @ line %d\n", __func__,
796                     __LINE__);
797                 error = EBUSY;
798                 goto out;
799         }
800         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
801         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
802         request->Function = MPI2_FUNCTION_CONFIG;
803         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
804         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
805         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
806         request->Header.PageNumber = 0;
807         request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
808         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
809         cm->cm_data = NULL;
810         error = mps_request_polled(sc, cm);
811         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
812         if (error || (reply == NULL)) {
813                 /* FIXME */
814                 /* If the poll returns error then we need to do diag reset */ 
815                 printf("%s: poll for header completed with error %d",
816                     __func__, error);
817                 error = ENXIO;
818                 goto out;
819         }
820         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
821         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
822         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
823                 /* FIXME */
824                 /* If the poll returns error then we need to do diag reset */ 
825                 printf("%s: header read with error; iocstatus = 0x%x\n",
826                     __func__, ioc_status);
827                 error = ENXIO;
828                 goto out;
829         }
830         /* We have to do free and alloc for the reply-free and reply-post
831          * counters to match - Need to review the reply FIFO handling.
832          */
833         mps_free_command(sc, cm);
834
835         if ((cm = mps_alloc_command(sc)) == NULL) {
836                 printf("%s: command alloc failed @ line %d\n", __func__,
837                     __LINE__);
838                 error = EBUSY;
839                 goto out;
840         }
841         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
842         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
843         request->Function = MPI2_FUNCTION_CONFIG;
844         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
845         request->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
846         request->ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
847         request->Header.PageNumber = 0;
848         request->Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
849         request->ExtPageLength = mpi_reply->ExtPageLength;
850         request->PageAddress = htole32(form | handle);
851         cm->cm_length = le16toh(mpi_reply->ExtPageLength) * 4;
852         cm->cm_sge = &request->PageBufferSGE;
853         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
854         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
855         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
856         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
857         if (!page) {
858                 printf("%s: page alloc failed\n", __func__);
859                 error = ENOMEM;
860                 goto out;
861         }
862         cm->cm_data = page;
863
864         error = mps_request_polled(sc, cm);
865         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
866         if (error || (reply == NULL)) {
867                 /* FIXME */
868                 /* If the poll returns error then we need to do diag reset */ 
869                 printf("%s: poll for page completed with error %d",
870                     __func__, error);
871                 error = ENXIO;
872                 goto out;
873         }
874         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
875         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
876         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
877                 /* FIXME */
878                 /* If the poll returns error then we need to do diag reset */ 
879                 printf("%s: page read with error; iocstatus = 0x%x\n",
880                     __func__, ioc_status);
881                 error = ENXIO;
882                 goto out;
883         }
884         bcopy(page, config_page, MIN(cm->cm_length, 
885             sizeof(Mpi2SasDevicePage0_t)));
886 out:
887         free(page, M_MPT2);
888         if (cm)
889                 mps_free_command(sc, cm);
890         return (error);
891 }
892
893 /**
894  * mps_config_get_bios_pg3 - obtain BIOS page 3
895  * @sc: per adapter object
896  * @mpi_reply: reply mf payload returned from firmware
897  * @config_page: contents of the config page
898  * Context: sleep.
899  *
900  * Returns 0 for success, non-zero for failure.
901  */
902 int
903 mps_config_get_bios_pg3(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
904     Mpi2BiosPage3_t *config_page)
905 {
906         MPI2_CONFIG_REQUEST *request;
907         MPI2_CONFIG_REPLY *reply;
908         struct mps_command *cm;
909         Mpi2BiosPage3_t *page = NULL;
910         int error = 0;
911         u16 ioc_status;
912
913         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
914
915         if ((cm = mps_alloc_command(sc)) == NULL) {
916                 printf("%s: command alloc failed @ line %d\n", __func__,
917                     __LINE__);
918                 error = EBUSY;
919                 goto out;
920         }
921         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
922         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
923         request->Function = MPI2_FUNCTION_CONFIG;
924         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
925         request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
926         request->Header.PageNumber = 3;
927         request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
928         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
929         cm->cm_data = NULL;
930         error = mps_request_polled(sc, cm);
931         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
932         if (error || (reply == NULL)) {
933                 /* FIXME */
934                 /* If the poll returns error then we need to do diag reset */ 
935                 printf("%s: poll for header completed with error %d",
936                     __func__, error);
937                 error = ENXIO;
938                 goto out;
939         }
940         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
941         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
942         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
943                 /* FIXME */
944                 /* If the poll returns error then we need to do diag reset */ 
945                 printf("%s: header read with error; iocstatus = 0x%x\n",
946                     __func__, ioc_status);
947                 error = ENXIO;
948                 goto out;
949         }
950         /* We have to do free and alloc for the reply-free and reply-post
951          * counters to match - Need to review the reply FIFO handling.
952          */
953         mps_free_command(sc, cm);
954
955         if ((cm = mps_alloc_command(sc)) == NULL) {
956                 printf("%s: command alloc failed @ line %d\n", __func__,
957                     __LINE__);
958                 error = EBUSY;
959                 goto out;
960         }
961         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
962         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
963         request->Function = MPI2_FUNCTION_CONFIG;
964         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
965         request->Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
966         request->Header.PageNumber = 3;
967         request->Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
968         request->Header.PageLength = mpi_reply->Header.PageLength;
969         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
970         cm->cm_sge = &request->PageBufferSGE;
971         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
972         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
973         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
974         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
975         if (!page) {
976                 printf("%s: page alloc failed\n", __func__);
977                 error = ENOMEM;
978                 goto out;
979         }
980         cm->cm_data = page;
981
982         error = mps_request_polled(sc, cm);
983         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
984         if (error || (reply == NULL)) {
985                 /* FIXME */
986                 /* If the poll returns error then we need to do diag reset */ 
987                 printf("%s: poll for page completed with error %d",
988                     __func__, error);
989                 error = ENXIO;
990                 goto out;
991         }
992         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
993         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
994         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
995                 /* FIXME */
996                 /* If the poll returns error then we need to do diag reset */ 
997                 printf("%s: page read with error; iocstatus = 0x%x\n",
998                     __func__, ioc_status);
999                 error = ENXIO;
1000                 goto out;
1001         }
1002         bcopy(page, config_page, MIN(cm->cm_length, sizeof(Mpi2BiosPage3_t)));
1003 out:
1004         free(page, M_MPT2);
1005         if (cm)
1006                 mps_free_command(sc, cm);
1007         return (error);
1008 }
1009
1010 /**
1011  * mps_config_get_raid_volume_pg0 - obtain raid volume page 0
1012  * @sc: per adapter object
1013  * @mpi_reply: reply mf payload returned from firmware
1014  * @config_page: contents of the config page
1015  * @page_address: form and handle value used to get page
1016  * Context: sleep.
1017  *
1018  * Returns 0 for success, non-zero for failure.
1019  */
1020 int
1021 mps_config_get_raid_volume_pg0(struct mps_softc *sc, Mpi2ConfigReply_t
1022     *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address)
1023 {
1024         MPI2_CONFIG_REQUEST *request;
1025         MPI2_CONFIG_REPLY *reply;
1026         struct mps_command *cm;
1027         Mpi2RaidVolPage0_t *page = NULL;
1028         int error = 0;
1029         u16 ioc_status;
1030
1031         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1032
1033         if ((cm = mps_alloc_command(sc)) == NULL) {
1034                 printf("%s: command alloc failed @ line %d\n", __func__,
1035                     __LINE__);
1036                 error = EBUSY;
1037                 goto out;
1038         }
1039         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1040         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1041         request->Function = MPI2_FUNCTION_CONFIG;
1042         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1043         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1044         request->Header.PageNumber = 0;
1045         request->Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
1046         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1047         cm->cm_data = NULL;
1048         error = mps_request_polled(sc, cm);
1049         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1050         if (error || (reply == NULL)) {
1051                 /* FIXME */
1052                 /* If the poll returns error then we need to do diag reset */ 
1053                 printf("%s: poll for header completed with error %d",
1054                     __func__, error);
1055                 error = ENXIO;
1056                 goto out;
1057         }
1058         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1059         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1060         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1061                 /* FIXME */
1062                 /* If the poll returns error then we need to do diag reset */ 
1063                 printf("%s: header read with error; iocstatus = 0x%x\n",
1064                     __func__, ioc_status);
1065                 error = ENXIO;
1066                 goto out;
1067         }
1068         /* We have to do free and alloc for the reply-free and reply-post
1069          * counters to match - Need to review the reply FIFO handling.
1070          */
1071         mps_free_command(sc, cm);
1072
1073         if ((cm = mps_alloc_command(sc)) == NULL) {
1074                 printf("%s: command alloc failed @ line %d\n", __func__,
1075                     __LINE__);
1076                 error = EBUSY;
1077                 goto out;
1078         }
1079         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1080         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1081         request->Function = MPI2_FUNCTION_CONFIG;
1082         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1083         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1084         request->Header.PageNumber = 0;
1085         request->Header.PageLength = mpi_reply->Header.PageLength;
1086         request->Header.PageVersion = mpi_reply->Header.PageVersion;
1087         request->PageAddress = page_address;
1088         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1089         cm->cm_sge = &request->PageBufferSGE;
1090         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1091         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1092         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1093         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1094         if (!page) {
1095                 printf("%s: page alloc failed\n", __func__);
1096                 error = ENOMEM;
1097                 goto out;
1098         }
1099         cm->cm_data = page;
1100
1101         error = mps_request_polled(sc, cm);
1102         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1103         if (error || (reply == NULL)) {
1104                 /* FIXME */
1105                 /* If the poll returns error then we need to do diag reset */ 
1106                 printf("%s: poll for page completed with error %d",
1107                     __func__, error);
1108                 error = ENXIO;
1109                 goto out;
1110         }
1111         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1112         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1113         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1114                 /* FIXME */
1115                 /* If the poll returns error then we need to do diag reset */ 
1116                 printf("%s: page read with error; iocstatus = 0x%x\n",
1117                     __func__, ioc_status);
1118                 error = ENXIO;
1119                 goto out;
1120         }
1121         bcopy(page, config_page, cm->cm_length);
1122 out:
1123         free(page, M_MPT2);
1124         if (cm)
1125                 mps_free_command(sc, cm);
1126         return (error);
1127 }
1128
1129 /**
1130  * mps_config_get_raid_volume_pg1 - obtain raid volume page 1
1131  * @sc: per adapter object
1132  * @mpi_reply: reply mf payload returned from firmware
1133  * @config_page: contents of the config page
1134  * @form: GET_NEXT_HANDLE or HANDLE
1135  * @handle: volume handle
1136  * Context: sleep.
1137  *
1138  * Returns 0 for success, non-zero for failure.
1139  */
1140 int
1141 mps_config_get_raid_volume_pg1(struct mps_softc *sc, Mpi2ConfigReply_t
1142     *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle)
1143 {
1144         MPI2_CONFIG_REQUEST *request;
1145         MPI2_CONFIG_REPLY *reply;
1146         struct mps_command *cm;
1147         Mpi2RaidVolPage1_t *page = NULL;
1148         int error = 0;
1149         u16 ioc_status;
1150
1151         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1152
1153         if ((cm = mps_alloc_command(sc)) == NULL) {
1154                 printf("%s: command alloc failed @ line %d\n", __func__,
1155                     __LINE__);
1156                 error = EBUSY;
1157                 goto out;
1158         }
1159         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1160         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1161         request->Function = MPI2_FUNCTION_CONFIG;
1162         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1163         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1164         request->Header.PageNumber = 1;
1165         request->Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
1166         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1167         cm->cm_data = NULL;
1168         error = mps_request_polled(sc, cm);
1169         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1170         if (error || (reply == NULL)) {
1171                 /* FIXME */
1172                 /* If the poll returns error then we need to do diag reset */ 
1173                 printf("%s: poll for header completed with error %d",
1174                     __func__, error);
1175                 error = ENXIO;
1176                 goto out;
1177         }
1178         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1179         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1180         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1181                 /* FIXME */
1182                 /* If the poll returns error then we need to do diag reset */ 
1183                 printf("%s: header read with error; iocstatus = 0x%x\n",
1184                     __func__, ioc_status);
1185                 error = ENXIO;
1186                 goto out;
1187         }
1188         /* We have to do free and alloc for the reply-free and reply-post
1189          * counters to match - Need to review the reply FIFO handling.
1190          */
1191         mps_free_command(sc, cm);
1192
1193         if ((cm = mps_alloc_command(sc)) == NULL) {
1194                 printf("%s: command alloc failed @ line %d\n", __func__,
1195                     __LINE__);
1196                 error = EBUSY;
1197                 goto out;
1198         }
1199         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1200         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1201         request->Function = MPI2_FUNCTION_CONFIG;
1202         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1203         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
1204         request->Header.PageNumber = 1;
1205         request->Header.PageLength = mpi_reply->Header.PageLength;
1206         request->Header.PageVersion = mpi_reply->Header.PageVersion;
1207         request->PageAddress = htole32(form | handle);
1208         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1209         cm->cm_sge = &request->PageBufferSGE;
1210         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1211         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1212         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1213         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1214         if (!page) {
1215                 printf("%s: page alloc failed\n", __func__);
1216                 error = ENOMEM;
1217                 goto out;
1218         }
1219         cm->cm_data = page;
1220
1221         error = mps_request_polled(sc, cm);
1222         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1223         if (error || (reply == NULL)) {
1224                 /* FIXME */
1225                 /* If the poll returns error then we need to do diag reset */ 
1226                 printf("%s: poll for page completed with error %d",
1227                     __func__, error);
1228                 error = ENXIO;
1229                 goto out;
1230         }
1231         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1232         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1233         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1234                 /* FIXME */
1235                 /* If the poll returns error then we need to do diag reset */ 
1236                 printf("%s: page read with error; iocstatus = 0x%x\n",
1237                     __func__, ioc_status);
1238                 error = ENXIO;
1239                 goto out;
1240         }
1241         bcopy(page, config_page, MIN(cm->cm_length,
1242             sizeof(Mpi2RaidVolPage1_t)));
1243 out:
1244         free(page, M_MPT2);
1245         if (cm)
1246                 mps_free_command(sc, cm);
1247         return (error);
1248 }
1249
1250 /**
1251  * mps_config_get_volume_wwid - returns wwid given the volume handle
1252  * @sc: per adapter object
1253  * @volume_handle: volume handle
1254  * @wwid: volume wwid
1255  * Context: sleep.
1256  *
1257  * Returns 0 for success, non-zero for failure.
1258  */
1259 int
1260 mps_config_get_volume_wwid(struct mps_softc *sc, u16 volume_handle, u64 *wwid)
1261 {
1262         Mpi2ConfigReply_t mpi_reply;
1263         Mpi2RaidVolPage1_t raid_vol_pg1;
1264
1265         *wwid = 0;
1266         if (!(mps_config_get_raid_volume_pg1(sc, &mpi_reply, &raid_vol_pg1,
1267             MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, volume_handle))) {
1268                 *wwid = le64toh((u64)raid_vol_pg1.WWID.High << 32 |
1269                     raid_vol_pg1.WWID.Low);
1270                 return 0;
1271         } else
1272                 return -1;
1273 }
1274
1275 /**
1276  * mps_config_get_pd_pg0 - obtain raid phys disk page 0
1277  * @sc: per adapter object
1278  * @mpi_reply: reply mf payload returned from firmware
1279  * @config_page: contents of the config page
1280  * @page_address: form and handle value used to get page
1281  * Context: sleep.
1282  *
1283  * Returns 0 for success, non-zero for failure.
1284  */
1285 int
1286 mps_config_get_raid_pd_pg0(struct mps_softc *sc, Mpi2ConfigReply_t *mpi_reply,
1287     Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address)
1288 {
1289         MPI2_CONFIG_REQUEST *request;
1290         MPI2_CONFIG_REPLY *reply;
1291         struct mps_command *cm;
1292         Mpi2RaidPhysDiskPage0_t *page = NULL;
1293         int error = 0;
1294         u16 ioc_status;
1295
1296         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1297
1298         if ((cm = mps_alloc_command(sc)) == NULL) {
1299                 printf("%s: command alloc failed @ line %d\n", __func__,
1300                     __LINE__);
1301                 error = EBUSY;
1302                 goto out;
1303         }
1304         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1305         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1306         request->Function = MPI2_FUNCTION_CONFIG;
1307         request->Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
1308         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1309         request->Header.PageNumber = 0;
1310         request->Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
1311         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1312         cm->cm_data = NULL;
1313         error = mps_request_polled(sc, cm);
1314         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1315         if (error || (reply == NULL)) {
1316                 /* FIXME */
1317                 /* If the poll returns error then we need to do diag reset */ 
1318                 printf("%s: poll for header completed with error %d",
1319                     __func__, error);
1320                 error = ENXIO;
1321                 goto out;
1322         }
1323         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1324         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1325         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1326                 /* FIXME */
1327                 /* If the poll returns error then we need to do diag reset */ 
1328                 printf("%s: header read with error; iocstatus = 0x%x\n",
1329                     __func__, ioc_status);
1330                 error = ENXIO;
1331                 goto out;
1332         }
1333         /* We have to do free and alloc for the reply-free and reply-post
1334          * counters to match - Need to review the reply FIFO handling.
1335          */
1336         mps_free_command(sc, cm);
1337
1338         if ((cm = mps_alloc_command(sc)) == NULL) {
1339                 printf("%s: command alloc failed @ line %d\n", __func__,
1340                     __LINE__);
1341                 error = EBUSY;
1342                 goto out;
1343         }
1344         request = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1345         bzero(request, sizeof(MPI2_CONFIG_REQUEST));
1346         request->Function = MPI2_FUNCTION_CONFIG;
1347         request->Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
1348         request->Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
1349         request->Header.PageNumber = 0;
1350         request->Header.PageLength = mpi_reply->Header.PageLength;
1351         request->Header.PageVersion = mpi_reply->Header.PageVersion;
1352         request->PageAddress = page_address;
1353         cm->cm_length = le16toh(mpi_reply->Header.PageLength) * 4;
1354         cm->cm_sge = &request->PageBufferSGE;
1355         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1356         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1357         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1358         page = malloc(cm->cm_length, M_MPT2, M_ZERO | M_NOWAIT);
1359         if (!page) {
1360                 printf("%s: page alloc failed\n", __func__);
1361                 error = ENOMEM;
1362                 goto out;
1363         }
1364         cm->cm_data = page;
1365
1366         error = mps_request_polled(sc, cm);
1367         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1368         if (error || (reply == NULL)) {
1369                 /* FIXME */
1370                 /* If the poll returns error then we need to do diag reset */ 
1371                 printf("%s: poll for page completed with error %d",
1372                     __func__, error);
1373                 error = ENXIO;
1374                 goto out;
1375         }
1376         ioc_status = le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
1377         bcopy(reply, mpi_reply, sizeof(MPI2_CONFIG_REPLY));
1378         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1379                 /* FIXME */
1380                 /* If the poll returns error then we need to do diag reset */ 
1381                 printf("%s: page read with error; iocstatus = 0x%x\n",
1382                     __func__, ioc_status);
1383                 error = ENXIO;
1384                 goto out;
1385         }
1386         bcopy(page, config_page, MIN(cm->cm_length,
1387             sizeof(Mpi2RaidPhysDiskPage0_t)));
1388 out:
1389         free(page, M_MPT2);
1390         if (cm)
1391                 mps_free_command(sc, cm);
1392         return (error);
1393 }