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