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