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