1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at
9 * http://www.opensource.org/licenses/cddl1.txt.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2004-2012 Emulex. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
26 */
27
28 #define EMLXS_FW_TABLE_DEF
29 #define EMLXS_MODEL_DEF
30
31 #include <emlxs.h>
32
33 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
34 EMLXS_MSG_DEF(EMLXS_HBA_C);
35
36
37 static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp,
38 IOCBQ *iocbq);
39
40 static void emlxs_pci_cap_offsets(emlxs_hba_t *hba);
41
42 #ifdef MSI_SUPPORT
43 uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] =
44 {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8};
45 uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] =
46 {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4,
47 EMLXS_MSI0_MASK8};
48 #endif /* MSI_SUPPORT */
49
50 emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE;
51 int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t);
52
53 emlxs_table_t emlxs_pci_cap[] = {
54 {PCI_CAP_ID_PM, "PCI_CAP_ID_PM"},
55 {PCI_CAP_ID_AGP, "PCI_CAP_ID_AGP"},
56 {PCI_CAP_ID_VPD, "PCI_CAP_ID_VPD"},
57 {PCI_CAP_ID_SLOT_ID, "PCI_CAP_ID_SLOT_ID"},
58 {PCI_CAP_ID_MSI, "PCI_CAP_ID_MSI"},
59 {PCI_CAP_ID_cPCI_HS, "PCI_CAP_ID_cPCI_HS"},
60 {PCI_CAP_ID_PCIX, "PCI_CAP_ID_PCIX"},
61 {PCI_CAP_ID_HT, "PCI_CAP_ID_HT"},
62 {PCI_CAP_ID_VS, "PCI_CAP_ID_VS"},
63 {PCI_CAP_ID_DEBUG_PORT, "PCI_CAP_ID_DEBUG_PORT"},
64 {PCI_CAP_ID_cPCI_CRC, "PCI_CAP_ID_cPCI_CRC"},
65 {PCI_CAP_ID_PCI_HOTPLUG, "PCI_CAP_ID_PCI_HOTPLUG"},
66 {PCI_CAP_ID_P2P_SUBSYS, "PCI_CAP_ID_P2P_SUBSYS"},
67 {PCI_CAP_ID_AGP_8X, "PCI_CAP_ID_AGP_8X"},
68 {PCI_CAP_ID_SECURE_DEV, "PCI_CAP_ID_SECURE_DEV"},
69 {PCI_CAP_ID_PCI_E, "PCI_CAP_ID_PCI_E"},
70 {PCI_CAP_ID_MSI_X, "PCI_CAP_ID_MSI_X"},
71 {PCI_CAP_ID_SATA, "PCI_CAP_ID_SATA"},
72 {PCI_CAP_ID_FLR, "PCI_CAP_ID_FLR"}
73
74 }; /* emlxs_pci_cap */
75
76 emlxs_table_t emlxs_pci_ecap[] = {
77 {PCIE_EXT_CAP_ID_AER, "PCIE_EXT_CAP_ID_AER"},
78 {PCIE_EXT_CAP_ID_VC, "PCIE_EXT_CAP_ID_VC"},
79 {PCIE_EXT_CAP_ID_SER, "PCIE_EXT_CAP_ID_SER"},
80 {PCIE_EXT_CAP_ID_PWR_BUDGET, "PCIE_EXT_CAP_ID_PWR_BUDGET"},
81 {PCIE_EXT_CAP_ID_RC_LINK_DECL, "PCIE_EXT_CAP_ID_RC_LINK_DECL"},
82 {PCIE_EXT_CAP_ID_RC_INT_LINKCTRL, "PCIE_EXT_CAP_ID_RC_INT_LINKCTRL"},
83 {PCIE_EXT_CAP_ID_RC_EVNT_CEA, "PCIE_EXT_CAP_ID_RC_EVNT_CEA"},
84 {PCIE_EXT_CAP_ID_MFVC, "PCIE_EXT_CAP_ID_MFVC"},
85 {PCIE_EXT_CAP_ID_VC_WITH_MFVC, "PCIE_EXT_CAP_ID_VC_WITH_MFVC"},
86 {PCIE_EXT_CAP_ID_RCRB, "PCIE_EXT_CAP_ID_RCRB"},
87 {PCIE_EXT_CAP_ID_VS, "PCIE_EXT_CAP_ID_VS"},
88 {PCIE_EXT_CAP_ID_CAC, "PCIE_EXT_CAP_ID_CAC"},
89 {PCIE_EXT_CAP_ID_ACS, "PCIE_EXT_CAP_ID_ACS"},
90 {PCIE_EXT_CAP_ID_ARI, "PCIE_EXT_CAP_ID_ARI"},
91 {PCIE_EXT_CAP_ID_ATS, "PCIE_EXT_CAP_ID_ATS"},
92 {PCI_EXT_CAP_ID_SRIOV, "PCI_EXT_CAP_ID_SRIOV"},
93 {PCI_EXT_CAP_ID_TPH, "PCI_EXT_CAP_ID_TPH"},
94 {PCI_EXT_CAP_ID_SEC_PCI, "PCI_EXT_CAP_ID_SEC_PCI"}
95
96 }; /* emlxs_pci_ecap */
97
98
99 emlxs_table_t emlxs_ring_table[] = {
100 {FC_FCP_RING, "FCP Ring"},
101 {FC_IP_RING, "IP Ring"},
102 {FC_ELS_RING, "ELS Ring"},
103 {FC_CT_RING, "CT Ring"}
104
105 }; /* emlxs_ring_table */
106
107 emlxs_table_t emlxs_ffstate_table[] = {
108 {0, "NULL"},
109 {FC_ERROR, "ERROR"},
110 {FC_KILLED, "KILLED"},
111 {FC_WARM_START, "WARM_START"},
112 {FC_INIT_START, "INIT_START"},
113 {FC_INIT_NVPARAMS, "INIT_NVPARAMS"},
114 {FC_INIT_REV, "INIT_REV"},
115 {FC_INIT_CFGPORT, "INIT_CFGPORT"},
116 {FC_INIT_CFGRING, "INIT_CFGRING"},
117 {FC_INIT_INITLINK, "INIT_INITLINK"},
118 {FC_LINK_DOWN, "LINK_DOWN"},
119 {FC_LINK_UP, "LINK_UP"},
120 {FC_CLEAR_LA, "CLEAR_LA"},
121 {FC_READY, "READY"}
122
123 }; /* emlxs_ffstate_table */
124
125
126 #ifdef MSI_SUPPORT
127 /* EMLXS_INTR_INIT */
128 int32_t
129 emlxs_msi_init(emlxs_hba_t *hba, uint32_t max)
130 {
131 emlxs_port_t *port = &PPORT;
132 int32_t pass = 0;
133 int32_t type = 0;
134 char s_type[16];
135 int32_t types;
136 int32_t count;
137 int32_t nintrs;
138 int32_t mode;
139 int32_t actual;
140 int32_t new_actual;
141 int32_t i;
142 int32_t ret;
143 ddi_intr_handle_t *htable = NULL;
144 ddi_intr_handle_t *new_htable = NULL;
145 uint32_t *intr_pri = NULL;
146 int32_t *intr_cap = NULL;
147 int32_t hilevel_pri;
148 emlxs_config_t *cfg = &CFG;
149
150 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
151 return (emlxs_intx_init(hba, max));
152 }
153
154 if (hba->intr_flags & EMLXS_MSI_INITED) {
155 return (DDI_SUCCESS);
156 }
157
158 /* Set max interrupt count if not specified */
159 if (max == 0) {
160 if ((cfg[CFG_MSI_MODE].current == 2) ||
161 (cfg[CFG_MSI_MODE].current == 3)) {
162 max = EMLXS_MSI_MAX_INTRS;
163 } else {
164 max = 1;
165 }
166 }
167
168 /* Filter max interrupt count with adapter model specification */
169 if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) {
170 max = hba->model_info.intr_limit;
171 }
172
173 /* Get the available interrupt types from the kernel */
174 types = 0;
175 ret = ddi_intr_get_supported_types(hba->dip, &types);
176
177 if ((ret != DDI_SUCCESS)) {
178 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
179 "MSI: ddi_intr_get_supported_types failed. ret=%d", ret);
180
181 /* Default to fixed type */
182 types = DDI_INTR_TYPE_FIXED;
183 }
184
185 /* Check if fixed interrupts are being forced */
186 if (cfg[CFG_MSI_MODE].current == 0) {
187 types &= DDI_INTR_TYPE_FIXED;
188 }
189
190 /* Check if MSI interrupts are being forced */
191 else if ((cfg[CFG_MSI_MODE].current == 1) ||
192 (cfg[CFG_MSI_MODE].current == 2)) {
193 types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
194 }
195
196 begin:
197
198 /* Set interrupt type and interrupt count */
199 type = 0;
200
201 /* Check if MSIX is fully supported */
202 if ((types & DDI_INTR_TYPE_MSIX) &&
203 (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) {
204 /* Get the max interrupt count from the adapter */
205 nintrs = 0;
206 ret =
207 ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX,
208 &nintrs);
209
210 if (ret == DDI_SUCCESS && nintrs) {
211 type = DDI_INTR_TYPE_MSIX;
212 (void) strlcpy(s_type, "TYPE_MSIX", sizeof (s_type));
213 goto initialize;
214 }
215 }
216
217 /* Check if MSI is fully supported */
218 if ((types & DDI_INTR_TYPE_MSI) &&
219 (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) {
220 /* Get the max interrupt count from the adapter */
221 nintrs = 0;
222 ret =
223 ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs);
224
225 if (ret == DDI_SUCCESS && nintrs) {
226 type = DDI_INTR_TYPE_MSI;
227 (void) strlcpy(s_type, "TYPE_MSI", sizeof (s_type));
228 goto initialize;
229 }
230 }
231
232 /* Check if fixed interrupts are fully supported */
233 if ((types & DDI_INTR_TYPE_FIXED) &&
234 (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
235 /* Get the max interrupt count from the adapter */
236 nintrs = 0;
237 ret =
238 ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED,
239 &nintrs);
240
241 if (ret == DDI_SUCCESS) {
242 type = DDI_INTR_TYPE_FIXED;
243 (void) strlcpy(s_type, "TYPE_FIXED", sizeof (s_type));
244 goto initialize;
245 }
246 }
247
248 goto init_failed;
249
250
251 initialize:
252
253 pass++;
254 mode = 0;
255 actual = 0;
256 htable = NULL;
257 intr_pri = NULL;
258 intr_cap = NULL;
259 hilevel_pri = 0;
260
261 if (pass == 1) {
262 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
263 "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type,
264 cfg[CFG_MSI_MODE].current, types, nintrs);
265 }
266
267 /* Validate interrupt count */
268 count = min(nintrs, max);
269
270 if (count >= 8) {
271 count = 8;
272 } else if (count >= 4) {
273 count = 4;
274 } else if (count >= 2) {
275 count = 2;
276 } else {
277 count = 1;
278 }
279
280 /* Allocate an array of interrupt handles */
281 htable =
282 kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)),
283 KM_SLEEP);
284
285 /* Allocate 'count' interrupts */
286 ret =
287 ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count,
288 &actual, DDI_INTR_ALLOC_NORMAL);
289
290 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
291 "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret);
292
293 if ((ret != DDI_SUCCESS) || (actual == 0)) {
294 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
295 "MSI: Unable to allocate interrupts. error=%d", ret);
296
297 actual = 0;
298 goto init_failed;
299 }
300
301 if (actual != count) {
302 /* Validate actual count */
303 if (actual >= 8) {
304 new_actual = 8;
305 } else if (actual >= 4) {
306 new_actual = 4;
307 } else if (actual >= 2) {
308 new_actual = 2;
309 } else {
310 new_actual = 1;
311 }
312
313 if (new_actual < actual) {
314 /* Free extra handles */
315 for (i = new_actual; i < actual; i++) {
316 (void) ddi_intr_free(htable[i]);
317 }
318
319 actual = new_actual;
320 }
321
322 /* Allocate a new array of interrupt handles */
323 new_htable =
324 kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)),
325 KM_SLEEP);
326
327 /* Copy old array to new array */
328 bcopy((uint8_t *)htable, (uint8_t *)new_htable,
329 (actual * sizeof (ddi_intr_handle_t)));
330
331 /* Free the old array */
332 kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
333
334 htable = new_htable;
335 count = actual;
336 }
337
338 /* Allocate interrupt priority table */
339 intr_pri =
340 (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)),
341 KM_SLEEP);
342
343 /* Allocate interrupt capability table */
344 intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP);
345
346 /* Get minimum hilevel priority */
347 hilevel_pri = ddi_intr_get_hilevel_pri();
348
349 /* Fill the priority and capability tables */
350 for (i = 0; i < count; ++i) {
351 ret = ddi_intr_get_pri(htable[i], &intr_pri[i]);
352
353 if (ret != DDI_SUCCESS) {
354 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
355 "MSI: ddi_intr_get_pri(%d) failed. "
356 "handle=%p ret=%d",
357 i, &htable[i], ret);
358
359 /* Clean up the interrupts */
360 goto init_failed;
361 }
362
363 if (intr_pri[i] >= hilevel_pri) {
364 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
365 "MSI: Interrupt(%d) level too high. "
366 "pri=0x%x hilevel=0x%x",
367 i, intr_pri[i], hilevel_pri);
368
369 /* Clean up the interrupts */
370 goto init_failed;
371 }
372
373 ret = ddi_intr_get_cap(htable[i], &intr_cap[i]);
374
375 if (ret != DDI_SUCCESS) {
376 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
377 "MSI: ddi_intr_get_cap(%d) failed. "
378 "handle=%p ret=%d",
379 i, &htable[i], ret);
380
381 /* Clean up the interrupts */
382 goto init_failed;
383 }
384
385 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
386 "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i,
387 intr_cap[i], intr_pri[i], hilevel_pri);
388
389 }
390
391 /* Set mode */
392 switch (count) {
393 case 8:
394 mode = EMLXS_MSI_MODE8;
395 break;
396
397 case 4:
398 mode = EMLXS_MSI_MODE4;
399 break;
400
401 case 2:
402 mode = EMLXS_MSI_MODE2;
403 break;
404
405 default:
406 mode = EMLXS_MSI_MODE1;
407 }
408
409 /* Save the info */
410 hba->intr_htable = htable;
411 hba->intr_count = count;
412 hba->intr_pri = intr_pri;
413 hba->intr_cap = intr_cap;
414 hba->intr_type = type;
415 hba->intr_arg = (void *)((unsigned long)intr_pri[0]);
416 hba->intr_mask = emlxs_msi_mask[mode];
417
418 hba->intr_cond = 0;
419
420 /* Adjust number of channels based on intr_count */
421 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
422 hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
423 }
424
425 for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
426 hba->intr_map[i] = emlxs_msi_map[mode][i];
427 hba->intr_cond |= emlxs_msi_map[mode][i];
428
429 mutex_init(&hba->intr_lock[i], NULL, MUTEX_DRIVER,
430 DDI_INTR_PRI(hba->intr_arg));
431 }
432
433 /* Set flag to indicate support */
434 hba->intr_flags |= EMLXS_MSI_INITED;
435
436 /* Create the interrupt threads */
437 for (i = 0; i < hba->chan_count; i++) {
438 mutex_init(&hba->chan[i].rsp_lock, NULL, MUTEX_DRIVER,
439 DDI_INTR_PRI(hba->intr_arg));
440
441 emlxs_thread_create(hba, &hba->chan[i].intr_thread);
442 }
443
444 return (DDI_SUCCESS);
445
446 init_failed:
447
448 if (intr_cap) {
449 kmem_free(intr_cap, (count * sizeof (int32_t)));
450 }
451
452 if (intr_pri) {
453 kmem_free(intr_pri, (count * sizeof (int32_t)));
454 }
455
456 if (htable) {
457 /* Process the interrupt handlers */
458 for (i = 0; i < actual; i++) {
459 /* Free the handle[i] */
460 (void) ddi_intr_free(htable[i]);
461 }
462
463 kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
464 }
465
466 /* Initialize */
467 hba->intr_htable = NULL;
468 hba->intr_count = 0;
469 hba->intr_pri = NULL;
470 hba->intr_cap = NULL;
471 hba->intr_type = 0;
472 hba->intr_arg = NULL;
473 hba->intr_cond = 0;
474 bzero(hba->intr_map, sizeof (hba->intr_map));
475 bzero(hba->intr_lock, sizeof (hba->intr_lock));
476
477 if (type == DDI_INTR_TYPE_MSIX) {
478 types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
479 goto begin;
480 } else if (type == DDI_INTR_TYPE_MSI) {
481 types &= DDI_INTR_TYPE_FIXED;
482 goto begin;
483 }
484
485 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
486 "MSI: Unable to initialize interrupts");
487
488 return (DDI_FAILURE);
489
490
491 } /* emlxs_msi_init() */
492
493
494 /* EMLXS_INTR_UNINIT */
495 int32_t
496 emlxs_msi_uninit(emlxs_hba_t *hba)
497 {
498 uint32_t count;
499 int32_t i;
500 ddi_intr_handle_t *htable;
501 uint32_t *intr_pri;
502 int32_t *intr_cap;
503 int32_t ret;
504
505 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
506 return (emlxs_intx_uninit(hba));
507 }
508
509 /*
510 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
511 * "MSI: msi_uninit called. flags=%x",
512 * hba->intr_flags);
513 */
514
515 /* Make sure interrupts have been removed first */
516 if ((hba->intr_flags & EMLXS_MSI_ADDED)) {
517 ret = emlxs_msi_remove(hba);
518
519 if (ret != DDI_SUCCESS) {
520 return (ret);
521 }
522 }
523
524 /* Check if the interrupts are still initialized */
525 if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
526 return (DDI_SUCCESS);
527 }
528 hba->intr_flags &= ~EMLXS_MSI_INITED;
529
530 /* Get handle table parameters */
531 htable = hba->intr_htable;
532 count = hba->intr_count;
533 intr_pri = hba->intr_pri;
534 intr_cap = hba->intr_cap;
535
536 /* Clean up */
537 hba->intr_count = 0;
538 hba->intr_htable = NULL;
539 hba->intr_pri = NULL;
540 hba->intr_cap = NULL;
541 hba->intr_type = 0;
542 hba->intr_arg = NULL;
543 hba->intr_cond = 0;
544 bzero(hba->intr_map, sizeof (hba->intr_map));
545
546 if (intr_cap) {
547 kmem_free(intr_cap, (count * sizeof (int32_t)));
548 }
549
550 if (intr_pri) {
551 kmem_free(intr_pri, (count * sizeof (int32_t)));
552 }
553
554 if (htable) {
555 /* Process the interrupt handlers */
556 for (i = 0; i < count; ++i) {
557 /* Free the handle[i] */
558 ret = ddi_intr_free(htable[i]);
559 }
560
561 kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
562 }
563
564 /* Destroy the intr locks */
565 for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
566 mutex_destroy(&hba->intr_lock[i]);
567 }
568
569 /* Destroy the interrupt threads */
570 for (i = 0; i < hba->chan_count; i++) {
571 emlxs_thread_destroy(&hba->chan[i].intr_thread);
572 mutex_destroy(&hba->chan[i].rsp_lock);
573 }
574
575 /*
576 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
577 * "MSI: msi_uninit done. flags=%x",
578 * hba->intr_flags);
579 */
580
581 return (DDI_SUCCESS);
582
583 } /* emlxs_msi_uninit() */
584
585
586 /* EMLXS_INTR_ADD */
587 int32_t
588 emlxs_msi_add(emlxs_hba_t *hba)
589 {
590 emlxs_port_t *port = &PPORT;
591 int32_t count;
592 int32_t i;
593 int32_t ret;
594 ddi_intr_handle_t *htable = NULL;
595 int32_t *intr_cap = NULL;
596
597 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
598 return (emlxs_intx_add(hba));
599 }
600
601 /* Check if interrupts have already been added */
602 if (hba->intr_flags & EMLXS_MSI_ADDED) {
603 return (DDI_SUCCESS);
604 }
605
606 /* Check if interrupts have been initialized */
607 if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
608 ret = emlxs_msi_init(hba, 0);
609
610 if (ret != DDI_SUCCESS) {
611 return (ret);
612 }
613 }
614
615 /* Get handle table parameters */
616 htable = hba->intr_htable;
617 count = hba->intr_count;
618 intr_cap = hba->intr_cap;
619
620 /* Add the interrupt handlers */
621 for (i = 0; i < count; ++i) {
622 /* add handler for handle[i] */
623 ret =
624 ddi_intr_add_handler(htable[i], EMLXS_SLI_MSI_INTR,
625 (char *)hba, (char *)((unsigned long)i));
626
627 if (ret != DDI_SUCCESS) {
628 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
629 "MSI: ddi_intr_add_handler(%d) failed. "
630 "handle=%p ret=%d",
631 i, &htable[i], ret);
632
633 /* Process the remaining interrupt handlers */
634 while (i) {
635 /* Decrement i */
636 i--;
637
638 /* Remove the handler */
639 ret = ddi_intr_remove_handler(htable[i]);
640
641 }
642
643 return (DDI_FAILURE);
644 }
645 }
646
647 /* Enable the interrupts */
648 if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
649 ret = ddi_intr_block_enable(htable, count);
650
651 if (ret != DDI_SUCCESS) {
652 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
653 "MSI: ddi_intr_block_enable(%d) failed. ret=%d",
654 count, ret);
655
656 for (i = 0; i < count; ++i) {
657 ret = ddi_intr_enable(htable[i]);
658
659 if (ret != DDI_SUCCESS) {
660 EMLXS_MSGF(EMLXS_CONTEXT,
661 &emlxs_init_debug_msg,
662 "MSI: ddi_intr_enable(%d) failed. "
663 "ret=%d",
664 i, ret);
665 }
666 }
667 }
668 } else {
669 for (i = 0; i < count; ++i) {
670 ret = ddi_intr_enable(htable[i]);
671
672 if (ret != DDI_SUCCESS) {
673 EMLXS_MSGF(EMLXS_CONTEXT,
674 &emlxs_init_debug_msg,
675 "MSI: ddi_intr_enable(%d) failed. ret=%d",
676 i, ret);
677 }
678 }
679 }
680
681
682 /* Set flag to indicate support */
683 hba->intr_flags |= EMLXS_MSI_ADDED;
684
685 return (DDI_SUCCESS);
686
687 } /* emlxs_msi_add() */
688
689
690
691 /* EMLXS_INTR_REMOVE */
692 int32_t
693 emlxs_msi_remove(emlxs_hba_t *hba)
694 {
695 emlxs_port_t *port = &PPORT;
696 uint32_t count;
697 int32_t i;
698 ddi_intr_handle_t *htable;
699 int32_t *intr_cap;
700 int32_t ret;
701
702 if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
703 return (emlxs_intx_remove(hba));
704 }
705
706 /*
707 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
708 * "MSI: msi_remove called. flags=%x",
709 * hba->intr_flags);
710 */
711
712 /* Check if interrupts have already been removed */
713 if (!(hba->intr_flags & EMLXS_MSI_ADDED)) {
714 return (DDI_SUCCESS);
715 }
716 hba->intr_flags &= ~EMLXS_MSI_ADDED;
717
718 /* Disable all adapter interrupts */
719 EMLXS_SLI_DISABLE_INTR(hba, 0);
720
721 /* Get handle table parameters */
722 htable = hba->intr_htable;
723 count = hba->intr_count;
724 intr_cap = hba->intr_cap;
725
726 /* Disable the interrupts */
727 if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
728 ret = ddi_intr_block_disable(htable, count);
729
730 if (ret != DDI_SUCCESS) {
731 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
732 "MSI: ddi_intr_block_disable(%d) failed. ret=%d",
733 count, ret);
734
735 for (i = 0; i < count; i++) {
736 ret = ddi_intr_disable(htable[i]);
737
738 if (ret != DDI_SUCCESS) {
739 EMLXS_MSGF(EMLXS_CONTEXT,
740 &emlxs_init_debug_msg,
741 "MSI: ddi_intr_disable(%d) failed. "
742 "ret=%d",
743 i, ret);
744 }
745 }
746 }
747 } else {
748 for (i = 0; i < count; i++) {
749 ret = ddi_intr_disable(htable[i]);
750
751 if (ret != DDI_SUCCESS) {
752 EMLXS_MSGF(EMLXS_CONTEXT,
753 &emlxs_init_debug_msg,
754 "MSI: ddi_intr_disable(%d) failed. ret=%d",
755 i, ret);
756 }
757 }
758 }
759
760 /* Process the interrupt handlers */
761 for (i = 0; i < count; i++) {
762 /* Remove the handler */
763 ret = ddi_intr_remove_handler(htable[i]);
764
765
766 }
767
768 return (DDI_SUCCESS);
769
770 } /* emlxs_msi_remove() */
771
772 #endif /* MSI_SUPPORT */
773
774
775 /* EMLXS_INTR_INIT */
776 /* ARGSUSED */
777 int32_t
778 emlxs_intx_init(emlxs_hba_t *hba, uint32_t max)
779 {
780 emlxs_port_t *port = &PPORT;
781 emlxs_config_t *cfg = &CFG;
782 int32_t ret;
783 uint32_t i;
784
785 /* Check if interrupts have already been initialized */
786 if (hba->intr_flags & EMLXS_INTX_INITED) {
787 return (DDI_SUCCESS);
788 }
789
790 /* Check if adapter is flagged for INTX support */
791 if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
792 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
793 "INTX: %s does not support INTX. flags=0x%x",
794 hba->model_info.model, hba->model_info.flags);
795
796 return (DDI_FAILURE);
797 }
798
799 /*
800 * Interrupt number '0' is a high-level interrupt. This driver
801 * does not support having its interrupts mapped above scheduler
802 * priority; i.e., we always expect to be able to call general
803 * kernel routines that may invoke the scheduler.
804 */
805 if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) {
806 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
807 "INTX: High-level interrupt not supported.");
808
809 return (DDI_FAILURE);
810 }
811
812 /* Get an iblock cookie */
813 ret =
814 ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER,
815 (ddi_iblock_cookie_t *)&hba->intr_arg);
816 if (ret != DDI_SUCCESS) {
817 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
818 "INTX: ddi_get_iblock_cookie failed. ret=%d", ret);
819
820 return (ret);
821 }
822
823 hba->intr_flags |= EMLXS_INTX_INITED;
824
825 hba->intr_count = 1;
826 /* Adjust number of channels based on intr_count */
827 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
828 hba->chan_count = cfg[CFG_NUM_WQ].current;
829 }
830
831 /* Create the interrupt threads */
832 for (i = 0; i < hba->chan_count; i++) {
833 mutex_init(&hba->chan[i].rsp_lock, NULL, MUTEX_DRIVER,
834 DDI_INTR_PRI(hba->intr_arg));
835
836 emlxs_thread_create(hba, &hba->chan[i].intr_thread);
837 }
838
839 return (DDI_SUCCESS);
840
841 } /* emlxs_intx_init() */
842
843
844 /* EMLXS_INTR_UNINIT */
845 int32_t
846 emlxs_intx_uninit(emlxs_hba_t *hba)
847 {
848 int32_t ret;
849 uint32_t i;
850
851 /* Make sure interrupts have been removed */
852 if ((hba->intr_flags & EMLXS_INTX_ADDED)) {
853 ret = emlxs_intx_remove(hba);
854
855 if (ret != DDI_SUCCESS) {
856 return (ret);
857 }
858 }
859
860 /* Check if the interrupts are still initialized */
861 if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
862 return (DDI_SUCCESS);
863 }
864 hba->intr_flags &= ~EMLXS_INTX_INITED;
865
866 hba->intr_arg = NULL;
867
868 /* Create the interrupt threads */
869 for (i = 0; i < hba->chan_count; i++) {
870 emlxs_thread_destroy(&hba->chan[i].intr_thread);
871 mutex_destroy(&hba->chan[i].rsp_lock);
872 }
873
874 return (DDI_SUCCESS);
875
876 } /* emlxs_intx_uninit() */
877
878
879 /*
880 * This is the legacy method for adding interrupts in Solaris
881 * EMLXS_INTR_ADD
882 */
883 int32_t
884 emlxs_intx_add(emlxs_hba_t *hba)
885 {
886 emlxs_port_t *port = &PPORT;
887 int32_t ret;
888
889 /* Check if interrupts have already been added */
890 if (hba->intr_flags & EMLXS_INTX_ADDED) {
891 return (DDI_SUCCESS);
892 }
893
894 /* Check if interrupts have been initialized */
895 if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
896 ret = emlxs_intx_init(hba, 0);
897
898 if (ret != DDI_SUCCESS) {
899 return (ret);
900 }
901 }
902
903 /* add intrrupt handler routine */
904 ret = ddi_add_intr((void *)hba->dip,
905 (uint_t)EMLXS_INUMBER,
906 (ddi_iblock_cookie_t *)&hba->intr_arg,
907 (ddi_idevice_cookie_t *)0,
908 (uint_t(*)())EMLXS_SLI_INTX_INTR, (caddr_t)hba);
909
910 if (ret != DDI_SUCCESS) {
911 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
912 "INTX: ddi_add_intr failed. ret=%d", ret);
913
914 return (ret);
915 }
916
917 hba->intr_flags |= EMLXS_INTX_ADDED;
918
919 return (DDI_SUCCESS);
920
921 } /* emlxs_intx_add() */
922
923
924 /* EMLXS_INTR_REMOVE */
925 int32_t
926 emlxs_intx_remove(emlxs_hba_t *hba)
927 {
928 /* Check if interrupts have already been removed */
929 if (!(hba->intr_flags & EMLXS_INTX_ADDED)) {
930 return (DDI_SUCCESS);
931 }
932 hba->intr_flags &= ~EMLXS_INTX_ADDED;
933
934 /* Diable all adapter interrupts */
935 EMLXS_SLI_DISABLE_INTR(hba, 0);
936
937 /* Remove the interrupt */
938 (void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER,
939 hba->intr_arg);
940
941 return (DDI_SUCCESS);
942
943 } /* emlxs_intx_remove() */
944
945
946 extern void
947 emlxs_process_link_speed(emlxs_hba_t *hba)
948 {
949 emlxs_vpd_t *vpd;
950 emlxs_config_t *cfg;
951 uint32_t hi;
952
953 /*
954 * This routine modifies the link-speed config parameter entry
955 * based on adapter capabilities
956 */
957 vpd = &VPD;
958 cfg = &hba->config[CFG_LINK_SPEED];
959
960 (void) strlcpy(cfg->help, "Select link speed. [0=Auto",
961 EMLXS_CFG_HELP_SIZE);
962 hi = 0;
963
964 if (vpd->link_speed & LMT_1GB_CAPABLE) {
965 (void) strlcat(cfg->help, ", 1=1Gb", EMLXS_CFG_HELP_SIZE);
966 hi = 1;
967 }
968
969 if (vpd->link_speed & LMT_2GB_CAPABLE) {
970 (void) strlcat(cfg->help, ", 2=2Gb", EMLXS_CFG_HELP_SIZE);
971 hi = 2;
972 }
973
974 if (vpd->link_speed & LMT_4GB_CAPABLE) {
975 (void) strlcat(cfg->help, ", 4=4Gb", EMLXS_CFG_HELP_SIZE);
976 hi = 4;
977 }
978
979 if (vpd->link_speed & LMT_8GB_CAPABLE) {
980 (void) strlcat(cfg->help, ", 8=8Gb", EMLXS_CFG_HELP_SIZE);
981 hi = 8;
982 }
983
984 if (vpd->link_speed & LMT_10GB_CAPABLE) {
985 (void) strlcat(cfg->help, ", 10=10Gb", EMLXS_CFG_HELP_SIZE);
986 hi = 10;
987 }
988
989 if (vpd->link_speed & LMT_16GB_CAPABLE) {
990 (void) strlcat(cfg->help, ", 16=16Gb", EMLXS_CFG_HELP_SIZE);
991 hi = 16;
992 }
993
994 (void) strlcat(cfg->help, "]", EMLXS_CFG_HELP_SIZE);
995 cfg->hi = hi;
996
997 /* Now revalidate the current parameter setting */
998 cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current);
999
1000 return;
1001
1002 } /* emlxs_process_link_speed() */
1003
1004
1005 /*
1006 * emlxs_parse_vpd()
1007 *
1008 * This routine will parse the VPD data
1009 */
1010 extern int
1011 emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size)
1012 {
1013 emlxs_port_t *port = &PPORT;
1014 char tag[3];
1015 uint8_t lenlo, lenhi;
1016 uint32_t n;
1017 uint16_t block_size;
1018 uint32_t block_index = 0;
1019 uint8_t sub_size;
1020 uint32_t sub_index;
1021 int32_t finished = 0;
1022 int32_t index = 0;
1023 char buffer[128];
1024 emlxs_vpd_t *vpd;
1025
1026 vpd = &VPD;
1027
1028
1029 while (!finished && (block_index < size)) {
1030 /*
1031 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1032 * "block_index = %x", block_index);
1033 */
1034
1035 switch (vpd_buf[block_index]) {
1036 case 0x82:
1037 index = block_index;
1038 index += 1;
1039 lenlo = vpd_buf[index];
1040 index += 1;
1041 lenhi = vpd_buf[index];
1042 index += 1;
1043 block_index = index;
1044
1045 block_size = ((((uint16_t)lenhi) << 8) + lenlo);
1046 block_index += block_size;
1047
1048 /*
1049 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1050 * "block_size = %x", block_size);
1051 */
1052
1053 n = sizeof (buffer);
1054 bzero(buffer, n);
1055 bcopy(&vpd_buf[index], buffer,
1056 (block_size < (n - 1)) ? block_size : (n - 1));
1057
1058 (void) strncpy(vpd->id, buffer, (sizeof (vpd->id)-1));
1059 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s",
1060 vpd->id);
1061
1062 break;
1063
1064 case 0x90:
1065 index = block_index;
1066 index += 1;
1067 lenlo = vpd_buf[index];
1068 index += 1;
1069 lenhi = vpd_buf[index];
1070 index += 1;
1071 block_index = index;
1072 sub_index = index;
1073
1074 block_size = ((((uint16_t)lenhi) << 8) + lenlo);
1075 block_index += block_size;
1076
1077 /*
1078 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1079 * "block_size = %x", block_size);
1080 */
1081
1082 /* Scan for sub-blocks */
1083 while ((sub_index < block_index) &&
1084 (sub_index < size)) {
1085 /*
1086 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1087 * "sub_index = %x", sub_index);
1088 */
1089
1090 index = sub_index;
1091 tag[0] = vpd_buf[index++];
1092 tag[1] = vpd_buf[index++];
1093 tag[2] = 0;
1094 sub_size = vpd_buf[index++];
1095
1096 /*
1097 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1098 * "sub_size = %x", sub_size);
1099 */
1100
1101 sub_index = (index + sub_size);
1102
1103 n = sizeof (buffer);
1104 bzero(buffer, n);
1105 bcopy(&vpd_buf[index], buffer,
1106 (sub_size < (n - 1)) ? sub_size : (n - 1));
1107
1108 /*
1109 * Look for Engineering Change (EC)
1110 */
1111 if (strcmp(tag, "EC") == 0) {
1112 (void) strncpy(vpd->eng_change, buffer,
1113 (sizeof (vpd->eng_change)-1));
1114 EMLXS_MSGF(EMLXS_CONTEXT,
1115 &emlxs_vpd_msg, "EC: %s",
1116 vpd->eng_change);
1117 }
1118 /*
1119 * Look for Manufacturer (MN)
1120 */
1121 else if (strcmp(tag, "MN") == 0) {
1122 (void) strncpy(vpd->manufacturer,
1123 buffer,
1124 (sizeof (vpd->manufacturer)-1));
1125 EMLXS_MSGF(EMLXS_CONTEXT,
1126 &emlxs_vpd_msg, "MN: %s",
1127 vpd->manufacturer);
1128 }
1129 /*
1130 * Look for Serial Number (SN)
1131 */
1132 else if (strcmp(tag, "SN") == 0) {
1133 (void) strncpy(vpd->serial_num, buffer,
1134 (sizeof (vpd->serial_num)-1));
1135 EMLXS_MSGF(EMLXS_CONTEXT,
1136 &emlxs_vpd_msg, "SN: %s",
1137 vpd->serial_num);
1138
1139 /* Validate the serial number */
1140 if (strncmp(buffer, "FFFFFFFFFF", 10) ==
1141 0 ||
1142 strncmp(buffer, "0000000000", 10) ==
1143 0) {
1144 vpd->serial_num[0] = 0;
1145 }
1146 }
1147 /*
1148 * Look for Part Number (PN)
1149 */
1150 else if (strcmp(tag, "PN") == 0) {
1151 (void) strncpy(vpd->part_num, buffer,
1152 (sizeof (vpd->part_num)-1));
1153 EMLXS_MSGF(EMLXS_CONTEXT,
1154 &emlxs_vpd_msg, "PN: %s",
1155 vpd->part_num);
1156 }
1157 /*
1158 * Look for (V0)
1159 */
1160 else if (strcmp(tag, "V0") == 0) {
1161 /* Not used */
1162 EMLXS_MSGF(EMLXS_CONTEXT,
1163 &emlxs_vpd_msg, "V0: %s", buffer);
1164 }
1165 /*
1166 * Look for model description (V1)
1167 */
1168 else if (strcmp(tag, "V1") == 0) {
1169 (void) strncpy(vpd->model_desc, buffer,
1170 (sizeof (vpd->model_desc)-1));
1171 EMLXS_MSGF(EMLXS_CONTEXT,
1172 &emlxs_vpd_msg, "Desc: %s",
1173 vpd->model_desc);
1174 }
1175 /*
1176 * Look for model (V2)
1177 */
1178 else if (strcmp(tag, "V2") == 0) {
1179 (void) strncpy(vpd->model, buffer,
1180 (sizeof (vpd->model)-1));
1181 EMLXS_MSGF(EMLXS_CONTEXT,
1182 &emlxs_vpd_msg, "Model: %s",
1183 vpd->model);
1184 }
1185 /*
1186 * Look for program type (V3)
1187 */
1188
1189 else if (strcmp(tag, "V3") == 0) {
1190 (void) strncpy(vpd->prog_types,
1191 buffer,
1192 (sizeof (vpd->prog_types)-1));
1193 EMLXS_MSGF(EMLXS_CONTEXT,
1194 &emlxs_vpd_msg, "Prog Types: %s",
1195 vpd->prog_types);
1196 }
1197 /*
1198 * Look for port number (V4)
1199 */
1200 else if (strcmp(tag, "V4") == 0) {
1201 (void) strncpy(vpd->port_num, buffer,
1202 (sizeof (vpd->port_num)-1));
1203 vpd->port_index =
1204 emlxs_strtol(vpd->port_num, 10);
1205
1206 EMLXS_MSGF(EMLXS_CONTEXT,
1207 &emlxs_vpd_msg, "Port: %s",
1208 (vpd->port_num[0]) ? vpd->
1209 port_num : "not applicable");
1210 }
1211 /*
1212 * Look for checksum (RV)
1213 */
1214 else if (strcmp(tag, "RV") == 0) {
1215 /* Not used */
1216 EMLXS_MSGF(EMLXS_CONTEXT,
1217 &emlxs_vpd_msg, "Checksum: 0x%x",
1218 buffer[0]);
1219 }
1220
1221 else {
1222 /* Generic */
1223 EMLXS_MSGF(EMLXS_CONTEXT,
1224 &emlxs_vpd_msg, "Tag: %s: %s",
1225 tag, buffer);
1226 }
1227 }
1228
1229 break;
1230
1231 case 0x78:
1232 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag.");
1233 finished = 1;
1234 break;
1235
1236 default:
1237 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1238 "Unknown block: %x %x %x %x %x %x %x %x",
1239 vpd_buf[index], vpd_buf[index + 1],
1240 vpd_buf[index + 2], vpd_buf[index + 3],
1241 vpd_buf[index + 4], vpd_buf[index + 5],
1242 vpd_buf[index + 6], vpd_buf[index + 7]);
1243 return (0);
1244 }
1245 }
1246
1247 return (1);
1248
1249 } /* emlxs_parse_vpd */
1250
1251
1252 /*
1253 * emlxs_parse_fcoe()
1254 *
1255 * This routine will parse the VPD data
1256 */
1257 extern int
1258 emlxs_parse_fcoe(emlxs_hba_t *hba, uint8_t *fcoep, uint32_t size)
1259 {
1260 emlxs_port_t *port = &PPORT;
1261 tlv_fcoe_t *fcoelist;
1262 tlv_fcfconnectlist_t *fcflist;
1263 int i;
1264 uint32_t flags;
1265 uint32_t entry_count;
1266 char FabricName[32];
1267 char SwitchName[32];
1268
1269 /* Validate the config region 23 signature */
1270 if ((*fcoep != 'R') || (*(fcoep+1) != 'G') ||
1271 (*(fcoep+2) != '2') || (*(fcoep+3) != '3')) {
1272 return (0);
1273 }
1274
1275 /* Search the config region 23, for FCOE Parameters record */
1276 i = 4;
1277 while ((i < size) && (*(fcoep+i) != 0xA0) && (*(fcoep+i) != 0xff)) {
1278 i += fcoep[i+1] * sizeof (uint32_t) + 2;
1279 }
1280
1281 if (*(fcoep+i) == 0xA0) {
1282 fcoelist = (tlv_fcoe_t *)(fcoep+i);
1283 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1284 "Found FCOE Params (A0):%d x%x",
1285 fcoelist->length, fcoelist->fip_flags);
1286 bcopy((uint8_t *)fcoelist, (uint8_t *)&hba->sli.sli4.cfgFCOE,
1287 sizeof (tlv_fcoe_t));
1288 }
1289
1290
1291 /* Search the config region 23, for FCF record */
1292 i = 4;
1293 while ((i < size) && (*(fcoep+i) != 0xA1) && (*(fcoep+i) != 0xff)) {
1294 i += fcoep[i+1] * sizeof (uint32_t) + 2;
1295 }
1296
1297 if (*(fcoep+i) == 0xA1) {
1298 fcflist = (tlv_fcfconnectlist_t *)(fcoep+i);
1299 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1300 "Found FCF ConnectList (A1):%d", fcflist->length);
1301
1302 bcopy((uint8_t *)fcflist, (uint8_t *)&hba->sli.sli4.cfgFCF,
1303 sizeof (tlv_fcfconnectlist_t));
1304
1305 /* Display the list */
1306 entry_count = (hba->sli.sli4.cfgFCF.length *
1307 sizeof (uint32_t)) / sizeof (tlv_fcfconnectentry_t);
1308
1309 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1310 "FCF List: %d entries", entry_count);
1311
1312 for (i = 0; i < entry_count; i++) {
1313 flags = *(uint32_t *)&hba->sli.sli4.cfgFCF.entry[i];
1314 (void) emlxs_wwn_xlate(FabricName, sizeof (FabricName),
1315 hba->sli.sli4.cfgFCF.entry[i].FabricName);
1316 (void) emlxs_wwn_xlate(SwitchName, sizeof (SwitchName),
1317 hba->sli.sli4.cfgFCF.entry[i].SwitchName);
1318
1319 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1320 "FCF List:%02d %08x %s %s",
1321 i, flags, FabricName, SwitchName);
1322 }
1323 }
1324
1325 return (1);
1326
1327 } /* emlxs_parse_fcoe */
1328
1329
1330 extern void
1331 emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd)
1332 {
1333 if (vpd->rBit) {
1334 switch (hba->sli_mode) {
1335 case EMLXS_HBA_SLI4_MODE:
1336 (void) strncpy(vpd->fw_version, vpd->sli4FwName,
1337 (sizeof (vpd->fw_version)-1));
1338 (void) strncpy(vpd->fw_label, vpd->sli4FwLabel,
1339 (sizeof (vpd->fw_label)-1));
1340 break;
1341 case EMLXS_HBA_SLI3_MODE:
1342 (void) strncpy(vpd->fw_version, vpd->sli3FwName,
1343 (sizeof (vpd->fw_version)-1));
1344 (void) strncpy(vpd->fw_label, vpd->sli3FwLabel,
1345 (sizeof (vpd->fw_label)-1));
1346 break;
1347 case EMLXS_HBA_SLI2_MODE:
1348 (void) strncpy(vpd->fw_version, vpd->sli2FwName,
1349 (sizeof (vpd->fw_version)-1));
1350 (void) strncpy(vpd->fw_label, vpd->sli2FwLabel,
1351 (sizeof (vpd->fw_label)-1));
1352 break;
1353 case EMLXS_HBA_SLI1_MODE:
1354 (void) strncpy(vpd->fw_version, vpd->sli1FwName,
1355 (sizeof (vpd->fw_version)-1));
1356 (void) strncpy(vpd->fw_label, vpd->sli1FwLabel,
1357 (sizeof (vpd->fw_label)-1));
1358 break;
1359 default:
1360 (void) strncpy(vpd->fw_version, "unknown",
1361 (sizeof (vpd->fw_version)-1));
1362 (void) strncpy(vpd->fw_label, vpd->fw_version,
1363 (sizeof (vpd->fw_label)-1));
1364 }
1365 } else {
1366 emlxs_decode_version(vpd->smFwRev, vpd->fw_version,
1367 sizeof (vpd->fw_version));
1368 (void) strncpy(vpd->fw_label, vpd->fw_version,
1369 (sizeof (vpd->fw_label)-1));
1370 }
1371
1372 return;
1373
1374 } /* emlxs_decode_firmware_rev() */
1375
1376
1377
1378 extern void
1379 emlxs_decode_version(uint32_t version, char *buffer, size_t len)
1380 {
1381 uint32_t b1, b2, b3, b4;
1382 char c;
1383
1384 b1 = (version & 0x0000f000) >> 12;
1385 b2 = (version & 0x00000f00) >> 8;
1386 b3 = (version & 0x000000c0) >> 6;
1387 b4 = (version & 0x00000030) >> 4;
1388
1389 if (b1 == 0 && b2 == 0) {
1390 (void) snprintf(buffer, len, "none");
1391 return;
1392 }
1393
1394 c = 0;
1395 switch (b4) {
1396 case 0:
1397 c = 'n';
1398 break;
1399 case 1:
1400 c = 'a';
1401 break;
1402 case 2:
1403 c = 'b';
1404 break;
1405 case 3:
1406 if ((version & 0x0000000f)) {
1407 c = 'x';
1408 }
1409 break;
1410
1411 }
1412 b4 = (version & 0x0000000f);
1413
1414 if (c == 0) {
1415 (void) snprintf(buffer, len, "%d.%d%d", b1, b2, b3);
1416 } else {
1417 (void) snprintf(buffer, len, "%d.%d%d%c%d", b1, b2, b3, c, b4);
1418 }
1419
1420 return;
1421
1422 } /* emlxs_decode_version() */
1423
1424
1425 extern void
1426 emlxs_decode_label(char *label, char *buffer, int bige, size_t len)
1427 {
1428 uint32_t i;
1429 char name[16];
1430
1431 bzero(name, sizeof (name));
1432 bcopy(label, name, MIN(sizeof (name), len));
1433 /* bige is TRUE if the data format is big endian */
1434
1435 if (bige) {
1436 /* Data format big Endian */
1437 LE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
1438
1439 for (i = 0; i < sizeof (name); i++) {
1440 if (name[i] == 0x20) {
1441 name[i] = 0;
1442 }
1443 }
1444 } else {
1445 /* Data format little Endian */
1446 BE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
1447
1448 for (i = 0; i < sizeof (name); i++) {
1449 if (name[i] == 0x20) {
1450 name[i] = 0;
1451 }
1452 }
1453 }
1454
1455 (void) strlcpy(buffer, name, len);
1456
1457 return;
1458
1459 } /* emlxs_decode_label() */
1460
1461
1462 extern uint32_t
1463 emlxs_strtol(char *str, uint32_t base)
1464 {
1465 uint32_t value = 0;
1466 char *ptr;
1467 uint32_t factor = 1;
1468 uint32_t digits;
1469
1470 if (*str == 0) {
1471 return (0);
1472 }
1473
1474 if (base != 10 && base != 16) {
1475 return (0);
1476 }
1477
1478 /* Get max digits of value */
1479 digits = (base == 10) ? 9 : 8;
1480
1481 /* Position pointer to end of string */
1482 ptr = str + strlen(str);
1483
1484 /* Process string backwards */
1485 while ((ptr-- > str) && digits) {
1486 /* check for base 10 numbers */
1487 if (*ptr >= '0' && *ptr <= '9') {
1488 value += ((uint32_t)(*ptr - '0')) * factor;
1489 factor *= base;
1490 digits--;
1491 } else if (base == 16) {
1492 /* Check for base 16 numbers */
1493 if (*ptr >= 'a' && *ptr <= 'f') {
1494 value +=
1495 ((uint32_t)(*ptr - 'a') + 10) * factor;
1496 factor *= base;
1497 digits--;
1498 } else if (*ptr >= 'A' && *ptr <= 'F') {
1499 value +=
1500 ((uint32_t)(*ptr - 'A') + 10) * factor;
1501 factor *= base;
1502 digits--;
1503 } else if (factor > 1) {
1504 break;
1505 }
1506 } else if (factor > 1) {
1507 break;
1508 }
1509 }
1510
1511 return (value);
1512
1513 } /* emlxs_strtol() */
1514
1515
1516 extern uint64_t
1517 emlxs_strtoll(char *str, uint32_t base)
1518 {
1519 uint64_t value = 0;
1520 char *ptr;
1521 uint32_t factor = 1;
1522 uint32_t digits;
1523
1524 if (*str == 0) {
1525 return (0);
1526 }
1527
1528 if (base != 10 && base != 16) {
1529 return (0);
1530 }
1531
1532 /* Get max digits of value */
1533 digits = (base == 10) ? 19 : 16;
1534
1535 /* Position pointer to end of string */
1536 ptr = str + strlen(str);
1537
1538 /* Process string backwards */
1539 while ((ptr-- > str) && digits) {
1540 /* check for base 10 numbers */
1541 if (*ptr >= '0' && *ptr <= '9') {
1542 value += ((uint32_t)(*ptr - '0')) * factor;
1543 factor *= base;
1544 digits--;
1545 } else if (base == 16) {
1546 /* Check for base 16 numbers */
1547 if (*ptr >= 'a' && *ptr <= 'f') {
1548 value +=
1549 ((uint32_t)(*ptr - 'a') + 10) * factor;
1550 factor *= base;
1551 digits--;
1552 } else if (*ptr >= 'A' && *ptr <= 'F') {
1553 value +=
1554 ((uint32_t)(*ptr - 'A') + 10) * factor;
1555 factor *= base;
1556 digits--;
1557 } else if (factor > 1) {
1558 break;
1559 }
1560 } else if (factor > 1) {
1561 break;
1562 }
1563 }
1564
1565 return (value);
1566
1567 } /* emlxs_strtoll() */
1568
1569 extern void
1570 emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types)
1571 {
1572 emlxs_port_t *port = &PPORT;
1573 uint32_t i;
1574 char *ptr;
1575 emlxs_model_t *model;
1576 char types_buffer[256];
1577 char *types;
1578
1579 bcopy(prog_types, types_buffer, 256);
1580 types = types_buffer;
1581
1582 model = &hba->model_info;
1583
1584 while (*types) {
1585 if (strncmp(types, "T2:", 3) == 0) {
1586 bzero(model->pt_2, sizeof (model->pt_2));
1587 types += 3;
1588
1589 i = 0;
1590 while (*types && *types != 'T') {
1591 /* Null terminate the next value */
1592 ptr = types;
1593 while (*ptr && (*ptr != ','))
1594 ptr++;
1595 *ptr = 0;
1596
1597 /* Save the value */
1598 model->pt_2[i++] =
1599 (uint8_t)emlxs_strtol(types, 16);
1600
1601 /*
1602 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1603 * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]);
1604 */
1605
1606 /* Move the str pointer */
1607 types = ptr + 1;
1608 }
1609
1610 } else if (strncmp(types, "T3:", 3) == 0) {
1611 bzero(model->pt_3, sizeof (model->pt_3));
1612 types += 3;
1613
1614 i = 0;
1615 while (*types && *types != 'T') {
1616 /* Null terminate the next value */
1617 ptr = types;
1618 while (*ptr && (*ptr != ','))
1619 ptr++;
1620 *ptr = 0;
1621
1622 /* Save the value */
1623 model->pt_3[i++] =
1624 (uint8_t)emlxs_strtol(types, 16);
1625
1626 /*
1627 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1628 * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]);
1629 */
1630
1631 /* Move the str pointer */
1632 types = ptr + 1;
1633 }
1634 } else if (strncmp(types, "T6:", 3) == 0) {
1635 bzero(model->pt_6, sizeof (model->pt_6));
1636 types += 3;
1637
1638 i = 0;
1639 while (*types && *types != 'T') {
1640 /* Null terminate the next value */
1641 ptr = types;
1642 while (*ptr && (*ptr != ','))
1643 ptr++;
1644 *ptr = 0;
1645
1646 /* Save the value */
1647 model->pt_6[i++] =
1648 (uint8_t)emlxs_strtol(types, 16);
1649 model->pt_6[i] = 0;
1650
1651 /*
1652 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1653 * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]);
1654 */
1655
1656 /* Move the str pointer */
1657 types = ptr + 1;
1658 }
1659 } else if (strncmp(types, "T7:", 3) == 0) {
1660 bzero(model->pt_7, sizeof (model->pt_7));
1661 types += 3;
1662
1663 i = 0;
1664 while (*types && *types != 'T') {
1665 /* Null terminate the next value */
1666 ptr = types;
1667 while (*ptr && (*ptr != ','))
1668 ptr++;
1669 *ptr = 0;
1670
1671 /* Save the value */
1672 model->pt_7[i++] =
1673 (uint8_t)emlxs_strtol(types, 16);
1674 model->pt_7[i] = 0;
1675
1676 /*
1677 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1678 * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]);
1679 */
1680
1681 /* Move the str pointer */
1682 types = ptr + 1;
1683 }
1684 } else if (strncmp(types, "TA:", 3) == 0) {
1685 bzero(model->pt_A, sizeof (model->pt_A));
1686 types += 3;
1687
1688 i = 0;
1689 while (*types && *types != 'T') {
1690 /* Null terminate the next value */
1691 ptr = types;
1692 while (*ptr && (*ptr != ','))
1693 ptr++;
1694 *ptr = 0;
1695
1696 /* Save the value */
1697 model->pt_A[i++] =
1698 (uint8_t)emlxs_strtol(types, 16);
1699
1700 /*
1701 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1702 * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]);
1703 */
1704
1705 /* Move the str pointer */
1706 types = ptr + 1;
1707 }
1708 } else if (strncmp(types, "TB:", 3) == 0) {
1709 bzero(model->pt_B, sizeof (model->pt_B));
1710 types += 3;
1711
1712 i = 0;
1713 while (*types && *types != 'T') {
1714 /* Null terminate the next value */
1715 ptr = types;
1716 while (*ptr && (*ptr != ','))
1717 ptr++;
1718 *ptr = 0;
1719
1720 /* Save the value */
1721 model->pt_B[i++] =
1722 (uint8_t)emlxs_strtol(types, 16);
1723
1724 /*
1725 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1726 * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]);
1727 */
1728
1729 /* Move the str pointer */
1730 types = ptr + 1;
1731 }
1732 } else if (strncmp(types, "TFF:", 4) == 0) {
1733 bzero(model->pt_FF, sizeof (model->pt_FF));
1734 types += 4;
1735
1736 i = 0;
1737 while (*types && *types != 'T') {
1738 /* Null terminate the next value */
1739 ptr = types;
1740 while (*ptr && (*ptr != ','))
1741 ptr++;
1742 *ptr = 0;
1743
1744 /* Save the value */
1745 model->pt_FF[i++] =
1746 (uint8_t)emlxs_strtol(types, 16);
1747
1748 /*
1749 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1750 * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]);
1751 */
1752
1753 /* Move the str pointer */
1754 types = ptr + 1;
1755 }
1756 } else if (strncmp(types, "T20:", 4) == 0) {
1757 bzero(model->pt_20, sizeof (model->pt_20));
1758 types += 4;
1759
1760 i = 0;
1761 while (*types && *types != 'T') {
1762 /* Null terminate the next value */
1763 ptr = types;
1764 while (*ptr && (*ptr != ','))
1765 ptr++;
1766 *ptr = 0;
1767
1768 /* Save the value */
1769 model->pt_20[i++] =
1770 (uint8_t)emlxs_strtol(types, 16);
1771 model->pt_20[i] = 0;
1772
1773 /*
1774 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1775 * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]);
1776 */
1777
1778 /* Move the str pointer */
1779 types = ptr + 1;
1780 }
1781 } else {
1782 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1783 "Unknown prog type string = %s", types);
1784 break;
1785 }
1786 }
1787
1788 return;
1789
1790 } /* emlxs_parse_prog_types() */
1791
1792
1793 extern void
1794 emlxs_build_prog_types(emlxs_hba_t *hba, emlxs_vpd_t *vpd)
1795 {
1796 uint32_t i;
1797 uint32_t found = 0;
1798 char buffer[256];
1799
1800 bzero(vpd->prog_types, sizeof (vpd->prog_types));
1801
1802 /* Rebuild the prog type string */
1803 if (hba->model_info.pt_2[0]) {
1804 (void) strlcat(vpd->prog_types, "T2:",
1805 sizeof (vpd->prog_types));
1806 found = 1;
1807
1808 i = 0;
1809 while ((i < 8) && (hba->model_info.pt_2[i])) {
1810 (void) snprintf(buffer, sizeof (buffer), "%X,",
1811 hba->model_info.pt_2[i]);
1812 (void) strlcat(vpd->prog_types, buffer,
1813 sizeof (vpd->prog_types));
1814 i++;
1815 }
1816 }
1817
1818 if (hba->model_info.pt_3[0]) {
1819 (void) strlcat(vpd->prog_types, "T3:",
1820 sizeof (vpd->prog_types));
1821 found = 1;
1822
1823 i = 0;
1824 while ((i < 8) && (hba->model_info.pt_3[i])) {
1825 (void) snprintf(buffer, sizeof (buffer), "%X,",
1826 hba->model_info.pt_3[i]);
1827 (void) strlcat(vpd->prog_types, buffer,
1828 sizeof (vpd->prog_types));
1829 i++;
1830
1831 }
1832 }
1833
1834 if (hba->model_info.pt_6[0]) {
1835 (void) strlcat(vpd->prog_types, "T6:",
1836 sizeof (vpd->prog_types));
1837 found = 1;
1838
1839 i = 0;
1840 while ((i < 8) && (hba->model_info.pt_6[i])) {
1841 (void) snprintf(buffer, sizeof (buffer), "%X,",
1842 hba->model_info.pt_6[i]);
1843 (void) strlcat(vpd->prog_types, buffer,
1844 sizeof (vpd->prog_types));
1845 i++;
1846 }
1847 }
1848
1849 if (hba->model_info.pt_7[0]) {
1850 (void) strlcat(vpd->prog_types, "T7:",
1851 sizeof (vpd->prog_types));
1852 found = 1;
1853
1854 i = 0;
1855 while ((i < 8) && (hba->model_info.pt_7[i])) {
1856 (void) snprintf(buffer, sizeof (buffer), "%X,",
1857 hba->model_info.pt_7[i]);
1858 (void) strlcat(vpd->prog_types, buffer,
1859 sizeof (vpd->prog_types));
1860 i++;
1861 }
1862 }
1863
1864 if (hba->model_info.pt_A[0]) {
1865 (void) strlcat(vpd->prog_types, "TA:",
1866 sizeof (vpd->prog_types));
1867 found = 1;
1868
1869 i = 0;
1870 while ((i < 8) && (hba->model_info.pt_A[i])) {
1871 (void) snprintf(buffer, sizeof (buffer), "%X,",
1872 hba->model_info.pt_A[i]);
1873 (void) strlcat(vpd->prog_types, buffer,
1874 sizeof (vpd->prog_types));
1875 i++;
1876 }
1877 }
1878
1879
1880 if (hba->model_info.pt_B[0]) {
1881 (void) strlcat(vpd->prog_types, "TB:",
1882 sizeof (vpd->prog_types));
1883 found = 1;
1884
1885 i = 0;
1886 while ((i < 8) && (hba->model_info.pt_B[i])) {
1887 (void) snprintf(buffer, sizeof (buffer), "%X,",
1888 hba->model_info.pt_B[i]);
1889 (void) strlcat(vpd->prog_types, buffer,
1890 sizeof (vpd->prog_types));
1891 i++;
1892 }
1893 }
1894
1895 if (hba->model_info.pt_20[0]) {
1896 (void) strlcat(vpd->prog_types, "T20:",
1897 sizeof (vpd->prog_types));
1898 found = 1;
1899
1900 i = 0;
1901 while ((i < 8) && (hba->model_info.pt_20[i])) {
1902 (void) snprintf(buffer, sizeof (buffer), "%X,",
1903 hba->model_info.pt_20[i]);
1904 (void) strlcat(vpd->prog_types, buffer,
1905 sizeof (vpd->prog_types));
1906 i++;
1907 }
1908 }
1909
1910 if (hba->model_info.pt_FF[0]) {
1911 (void) strlcat(vpd->prog_types, "TFF:",
1912 sizeof (vpd->prog_types));
1913 found = 1;
1914
1915 i = 0;
1916 while ((i < 8) && (hba->model_info.pt_FF[i])) {
1917 (void) snprintf(buffer, sizeof (buffer), "%X,",
1918 hba->model_info.pt_FF[i]);
1919 (void) strlcat(vpd->prog_types, buffer,
1920 sizeof (vpd->prog_types));
1921 i++;
1922 }
1923 }
1924
1925 if (found) {
1926 /* Terminate at the last comma in string */
1927 vpd->prog_types[(strlen(vpd->prog_types) - 1)] = 0;
1928 }
1929
1930 return;
1931
1932 } /* emlxs_build_prog_types() */
1933
1934
1935 extern uint32_t
1936 emlxs_init_adapter_info(emlxs_hba_t *hba)
1937 {
1938 emlxs_port_t *port = &PPORT;
1939 uint32_t pci_id;
1940 uint32_t cache_line;
1941 uint32_t channels;
1942 uint16_t device_id;
1943 uint16_t ssdid;
1944 uint32_t i;
1945 uint32_t found = 0;
1946 int32_t *prop;
1947 uint32_t num_prop;
1948
1949 if (hba->bus_type == SBUS_FC) {
1950 if (hba->pci_acc_handle == NULL) {
1951 bcopy(&emlxs_sbus_model[0], &hba->model_info,
1952 sizeof (emlxs_model_t));
1953
1954 hba->model_info.device_id = 0;
1955
1956 return (0);
1957 }
1958
1959 /* Read the PCI device id */
1960 pci_id =
1961 ddi_get32(hba->pci_acc_handle,
1962 (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER));
1963 device_id = (uint16_t)(pci_id >> 16);
1964
1965 /* Find matching adapter model */
1966 for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) {
1967 if (emlxs_sbus_model[i].device_id == device_id) {
1968 bcopy(&emlxs_sbus_model[i], &hba->model_info,
1969 sizeof (emlxs_model_t));
1970 found = 1;
1971 break;
1972 }
1973 }
1974
1975 /* If not found then use the unknown model */
1976 if (!found) {
1977 bcopy(&emlxs_sbus_model[0], &hba->model_info,
1978 sizeof (emlxs_model_t));
1979
1980 hba->model_info.device_id = device_id;
1981
1982 return (0);
1983 }
1984 } else { /* PCI model */
1985
1986 if (hba->pci_acc_handle == NULL) {
1987 bcopy(&emlxs_pci_model[0], &hba->model_info,
1988 sizeof (emlxs_model_t));
1989
1990 hba->model_info.device_id = 0;
1991
1992 return (0);
1993 }
1994
1995 /* Read the PCI device id */
1996 device_id =
1997 ddi_get16(hba->pci_acc_handle,
1998 (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER));
1999
2000 /* Read the PCI Subsystem id */
2001 ssdid =
2002 ddi_get16(hba->pci_acc_handle,
2003 (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER));
2004
2005 if (ssdid == 0 || ssdid == 0xffff) {
2006 ssdid = device_id;
2007 }
2008
2009 /* Read the Cache Line reg */
2010 cache_line =
2011 ddi_get32(hba->pci_acc_handle,
2012 (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER));
2013
2014 EMLXS_MSGF(EMLXS_CONTEXT,
2015 &emlxs_init_debug_msg, "Device IDs: %x/%x/%x",
2016 device_id, ssdid, cache_line);
2017
2018 /* Check for the multifunction bit being set */
2019 if ((cache_line & 0x00ff0000) == 0x00800000) {
2020 channels = EMLXS_MULTI_CHANNEL;
2021 } else {
2022 channels = EMLXS_SINGLE_CHANNEL;
2023 }
2024
2025 /* If device ids are unique, then use them for search */
2026 if (device_id != ssdid) {
2027 /*
2028 * Find matching adapter model using
2029 * device_id, ssdid, and channels
2030 */
2031 for (i = 1; i < emlxs_pci_model_count; i++) {
2032 if (emlxs_pci_model[i].device_id ==
2033 device_id &&
2034 emlxs_pci_model[i].ssdid == ssdid &&
2035 emlxs_pci_model[i].channels ==
2036 channels) {
2037 bcopy(&emlxs_pci_model[i],
2038 &hba->model_info,
2039 sizeof (emlxs_model_t));
2040 found = 1;
2041 break;
2042 }
2043 }
2044 }
2045
2046 /* If adapter not found, try again */
2047 if (!found) {
2048 /*
2049 * Find matching adapter model using
2050 * device_id and channels
2051 */
2052 for (i = 1; i < emlxs_pci_model_count; i++) {
2053 if (emlxs_pci_model[i].device_id == device_id &&
2054 emlxs_pci_model[i].channels == channels) {
2055 bcopy(&emlxs_pci_model[i],
2056 &hba->model_info,
2057 sizeof (emlxs_model_t));
2058 found = 1;
2059 break;
2060 }
2061 }
2062 }
2063
2064 /* If adapter not found, try one last time */
2065 if (!found) {
2066 /*
2067 * Find matching adapter model using
2068 * device_id only
2069 */
2070 for (i = 1; i < emlxs_pci_model_count; i++) {
2071 if (emlxs_pci_model[i].device_id == device_id) {
2072 bcopy(&emlxs_pci_model[i],
2073 &hba->model_info,
2074 sizeof (emlxs_model_t));
2075 found = 1;
2076 break;
2077 }
2078 }
2079 }
2080
2081 /* If not found, set adapter to unknown */
2082 if (!found) {
2083 bcopy(&emlxs_pci_model[0], &hba->model_info,
2084 sizeof (emlxs_model_t));
2085
2086 hba->model_info.device_id = device_id;
2087 hba->model_info.ssdid = ssdid;
2088
2089 return (0);
2090 }
2091
2092 #ifndef SATURN_MSI_SUPPORT
2093 /*
2094 * This will disable MSI support for Saturn adapter's
2095 * due to a PCI bus issue
2096 */
2097 if (hba->model_info.chip == EMLXS_SATURN_CHIP) {
2098 hba->model_info.flags &=
2099 ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED);
2100 }
2101 #endif /* !SATURN_MSI_SUPPORT */
2102
2103 /* Scan the PCI capabilities */
2104 emlxs_pci_cap_offsets(hba);
2105
2106 #ifdef MSI_SUPPORT
2107 /* Verify MSI support */
2108 if ((hba->model_info.flags & EMLXS_MSI_SUPPORTED) &&
2109 !hba->pci_cap_offset[PCI_CAP_ID_MSI]) {
2110 hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED;
2111 }
2112
2113 /* Verify MSI-X support */
2114 if ((hba->model_info.flags & EMLXS_MSIX_SUPPORTED) &&
2115 !hba->pci_cap_offset[PCI_CAP_ID_MSI_X]) {
2116 hba->model_info.flags &= ~EMLXS_MSIX_SUPPORTED;
2117 }
2118 #endif /* MSI_SUPPORT */
2119
2120 /* Set the sli_intf value */
2121 if (hba->pci_cap_offset[PCI_CAP_ID_VS]) {
2122 /* Save the SLI_INTF register, this contains */
2123 /* information about the BAR register layout */
2124 /* and other HBA information. */
2125 hba->sli_intf =
2126 ddi_get32(hba->pci_acc_handle,
2127 (uint32_t *)(hba->pci_addr +
2128 hba->pci_cap_offset[PCI_CAP_ID_VS] +
2129 PCI_VS_SLI_INTF_OFFSET));
2130
2131 EMLXS_MSGF(EMLXS_CONTEXT,
2132 &emlxs_init_debug_msg, "PCI_CAP_ID_VS: "
2133 "SLI_INTF:%08x",
2134 hba->sli_intf);
2135
2136 /* Check validity */
2137 if ((hba->sli_intf & SLI_INTF_VALID_MASK) !=
2138 SLI_INTF_VALID) {
2139 hba->sli_intf = 0;
2140 }
2141 }
2142 }
2143
2144 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0,
2145 "reg", &prop, &num_prop) == DDI_PROP_SUCCESS) {
2146 /* Parse the property for PCI function, device and bus no. */
2147 hba->pci_function_number =
2148 (uint8_t)((prop[0] & 0x00000700) >> 8);
2149 hba->pci_device_number =
2150 (uint8_t)((prop[0] & 0x0000f800) >> 11);
2151 hba->pci_bus_number = (uint8_t)((prop[0] & 0x00ff0000) >> 16);
2152 ddi_prop_free((void *)prop);
2153 }
2154
2155 switch (hba->sli_intf & SLI_INTF_SLI_REV_MASK) {
2156 case SLI_INTF_SLI_REV_NONE: /* Legacy support */
2157 if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
2158 hba->sli_api = emlxs_sli4_api;
2159 } else {
2160 hba->sli_api = emlxs_sli3_api;
2161 }
2162 break;
2163
2164 case SLI_INTF_SLI_REV_3:
2165 if (!(hba->model_info.sli_mask & EMLXS_SLI3_MASK)) {
2166 EMLXS_MSGF(EMLXS_CONTEXT,
2167 &emlxs_init_failed_msg,
2168 "Adapter does not support SLI3 interface. "
2169 "sli_intf=%08x sli_mask=%08x",
2170 hba->sli_intf, hba->model_info.sli_mask);
2171 return (0);
2172 }
2173 hba->sli_api = emlxs_sli3_api;
2174 break;
2175
2176 case SLI_INTF_SLI_REV_4:
2177 if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK)) {
2178 EMLXS_MSGF(EMLXS_CONTEXT,
2179 &emlxs_init_failed_msg,
2180 "Adapter does not support SLI4 interface. "
2181 "sli_intf=%08x sli_mask=%08x",
2182 hba->sli_intf, hba->model_info.sli_mask);
2183 return (0);
2184 }
2185 hba->sli_api = emlxs_sli4_api;
2186 break;
2187
2188 default:
2189 EMLXS_MSGF(EMLXS_CONTEXT,
2190 &emlxs_init_failed_msg,
2191 "Invalid SLI interface specified. "
2192 "sli_intf=%08x sli_mask=%08x",
2193 hba->sli_intf, hba->model_info.sli_mask);
2194 return (0);
2195 }
2196
2197 #ifdef FMA_SUPPORT
2198 if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
2199 != DDI_FM_OK) {
2200 EMLXS_MSGF(EMLXS_CONTEXT,
2201 &emlxs_invalid_access_handle_msg, NULL);
2202 return (0);
2203 }
2204 #endif /* FMA_SUPPORT */
2205
2206 return (1);
2207
2208 } /* emlxs_init_adapter_info() */
2209
2210
2211 /* ARGSUSED */
2212 static void
2213 emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2214 {
2215 emlxs_port_t *port = &PPORT;
2216 IOCB *iocb;
2217 uint32_t *w;
2218 int i, j;
2219
2220 iocb = &iocbq->iocb;
2221
2222 if (iocb->ULPSTATUS != 0) {
2223 return;
2224 }
2225
2226 switch (iocb->un.astat.EventCode) {
2227 case 0x0100: /* Temp Warning */
2228
2229 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg,
2230 "Adapter is very hot (%d °C). Take corrective action.",
2231 iocb->ULPCONTEXT);
2232
2233 hba->temperature = iocb->ULPCONTEXT;
2234 emlxs_log_temp_event(port, 0x02, iocb->ULPCONTEXT);
2235
2236
2237 break;
2238
2239
2240 case 0x0101: /* Temp Safe */
2241
2242 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg,
2243 "Adapter temperature now safe (%d °C).",
2244 iocb->ULPCONTEXT);
2245
2246 hba->temperature = iocb->ULPCONTEXT;
2247 emlxs_log_temp_event(port, 0x03, iocb->ULPCONTEXT);
2248
2249 break;
2250
2251 default:
2252
2253 w = (uint32_t *)iocb;
2254 for (i = 0, j = 0; i < 8; i++, j += 2) {
2255 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg,
2256 "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1,
2257 w[j + 1]);
2258 }
2259
2260 emlxs_log_async_event(port, iocb);
2261 }
2262
2263 return;
2264
2265 } /* emlxs_handle_async_event() */
2266
2267
2268 /* ARGSUSED */
2269 extern void
2270 emlxs_reset_link_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2271 {
2272 emlxs_port_t *port = &PPORT;
2273
2274 /* Attempt a link reset to recover */
2275 (void) emlxs_reset(port, FC_FCA_LINK_RESET);
2276
2277 return;
2278
2279 } /* emlxs_reset_link_thread() */
2280
2281
2282 /* ARGSUSED */
2283 extern void
2284 emlxs_restart_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2285 {
2286 emlxs_port_t *port = &PPORT;
2287
2288 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting...");
2289
2290 /* Attempt a full hardware reset to recover */
2291 if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) {
2292 EMLXS_STATE_CHANGE(hba, FC_ERROR);
2293
2294 emlxs_shutdown_thread(hba, arg1, arg2);
2295 }
2296
2297 return;
2298
2299 } /* emlxs_restart_thread() */
2300
2301
2302 /* ARGSUSED */
2303 extern void
2304 emlxs_shutdown_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2305 {
2306 emlxs_port_t *port = &PPORT;
2307
2308 mutex_enter(&EMLXS_PORT_LOCK);
2309 if (hba->flag & FC_SHUTDOWN) {
2310 mutex_exit(&EMLXS_PORT_LOCK);
2311 return;
2312 }
2313 hba->flag |= FC_SHUTDOWN;
2314 mutex_exit(&EMLXS_PORT_LOCK);
2315
2316 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
2317 "Shutting down...");
2318
2319 /* Take adapter offline and leave it there */
2320 (void) emlxs_offline(hba, 0);
2321
2322 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2323 /*
2324 * Dump is not defined for SLI4, so just
2325 * reset the HBA for now.
2326 */
2327 EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
2328
2329 } else {
2330 if (hba->flag & FC_OVERTEMP_EVENT) {
2331 emlxs_log_temp_event(port, 0x01,
2332 hba->temperature);
2333 } else {
2334 emlxs_log_dump_event(port, NULL, 0);
2335 }
2336 }
2337
2338 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required.");
2339
2340 return;
2341
2342 } /* emlxs_shutdown_thread() */
2343
2344
2345 /* ARGSUSED */
2346 extern void
2347 emlxs_proc_channel(emlxs_hba_t *hba, CHANNEL *cp, void *arg2)
2348 {
2349 IOCBQ *iocbq;
2350 IOCBQ *rsp_head;
2351
2352 /*
2353 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2354 * "proc_channel: channel=%d", cp->channelno);
2355 */
2356
2357 mutex_enter(&cp->rsp_lock);
2358
2359 while ((rsp_head = cp->rsp_head) != NULL) {
2360 cp->rsp_head = NULL;
2361 cp->rsp_tail = NULL;
2362
2363 mutex_exit(&cp->rsp_lock);
2364
2365 while ((iocbq = rsp_head) != NULL) {
2366 rsp_head = (IOCBQ *) iocbq->next;
2367
2368 emlxs_proc_channel_event(hba, cp, iocbq);
2369 }
2370
2371 mutex_enter(&cp->rsp_lock);
2372 }
2373
2374 mutex_exit(&cp->rsp_lock);
2375
2376 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0);
2377
2378 return;
2379
2380 } /* emlxs_proc_channel() */
2381
2382
2383 /*
2384 * Called from SLI ring event routines to process a rsp ring IOCB.
2385 */
2386 void
2387 emlxs_proc_channel_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2388 {
2389 emlxs_port_t *port = &PPORT;
2390 char buffer[MAX_MSG_DATA + 1];
2391 IOCB *iocb;
2392 emlxs_buf_t *sbp;
2393 fc_packet_t *pkt;
2394
2395 iocb = &iocbq->iocb;
2396
2397 #ifdef DEBUG_CMPL_IOCB
2398 emlxs_data_dump(port, "CMPL_IOCB", (uint32_t *)iocb, 8, 0);
2399 #endif
2400
2401 sbp = (emlxs_buf_t *)iocbq->sbp;
2402 if (sbp) {
2403 if (!(sbp->pkt_flags & PACKET_VALID) ||
2404 (sbp->pkt_flags & (PACKET_ULP_OWNED |
2405 PACKET_IN_COMPLETION))) {
2406 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg,
2407 "Duplicate: iocb=%p cmd=%x status=%x "
2408 "error=%x iotag=%d context=%x info=%x",
2409 iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND,
2410 iocbq->iocb.ULPSTATUS,
2411 (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError,
2412 (uint16_t)iocbq->iocb.ULPIOTAG,
2413 (uint16_t)iocbq->iocb.ULPCONTEXT,
2414 (uint8_t)iocbq->iocb.ULPRSVDBYTE);
2415
2416 /* Drop this IO immediately */
2417 return;
2418 }
2419
2420 if (sbp->pkt_flags & PACKET_IN_TIMEOUT) {
2421 /*
2422 * If the packet is tagged for timeout then set the
2423 * return codes appropriately
2424 */
2425 iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
2426 iocb->un.grsp.perr.statLocalError = IOERR_ABORT_TIMEOUT;
2427 } else if (sbp->pkt_flags &
2428 (PACKET_IN_FLUSH | PACKET_IN_ABORT)) {
2429 /*
2430 * If the packet is tagged for abort then set the
2431 * return codes appropriately
2432 */
2433 iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
2434 iocb->un.grsp.perr.statLocalError =
2435 IOERR_ABORT_REQUESTED;
2436 }
2437 }
2438
2439 /* Check for IOCB local error */
2440 if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) {
2441 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg,
2442 "Local reject. ringno=%d iocb=%p cmd=%x "
2443 "iotag=%d context=%x info=%x error=%x",
2444 cp->channelno, iocb, (uint8_t)iocb->ULPCOMMAND,
2445 (uint16_t)iocb->ULPIOTAG, (uint16_t)iocb->ULPCONTEXT,
2446 (uint8_t)iocb->ULPRSVDBYTE,
2447 (uint8_t)iocb->un.grsp.perr.statLocalError);
2448 }
2449
2450 switch (iocb->ULPCOMMAND) {
2451 /* RING 0 FCP commands */
2452 case CMD_FCP_ICMND_CR:
2453 case CMD_FCP_ICMND_CX:
2454 case CMD_FCP_IREAD_CR:
2455 case CMD_FCP_IREAD_CX:
2456 case CMD_FCP_IWRITE_CR:
2457 case CMD_FCP_IWRITE_CX:
2458 case CMD_FCP_ICMND64_CR:
2459 case CMD_FCP_ICMND64_CX:
2460 case CMD_FCP_IREAD64_CR:
2461 case CMD_FCP_IREAD64_CX:
2462 case CMD_FCP_IWRITE64_CR:
2463 case CMD_FCP_IWRITE64_CX:
2464 emlxs_handle_fcp_event(hba, cp, iocbq);
2465 break;
2466
2467 #ifdef SFCT_SUPPORT
2468 case CMD_FCP_TSEND_CX: /* FCP_TARGET IOCB command */
2469 case CMD_FCP_TSEND64_CX: /* FCP_TARGET IOCB command */
2470 case CMD_FCP_TRECEIVE_CX: /* FCP_TARGET IOCB command */
2471 case CMD_FCP_TRECEIVE64_CX: /* FCP_TARGET IOCB command */
2472 case CMD_FCP_TRSP_CX: /* FCP_TARGET IOCB command */
2473 case CMD_FCP_TRSP64_CX: /* FCP_TARGET IOCB command */
2474 if (port->mode == MODE_TARGET) {
2475 (void) emlxs_fct_handle_fcp_event(hba, cp, iocbq);
2476 }
2477 break;
2478 #endif /* SFCT_SUPPORT */
2479
2480 /* RING 1 IP commands */
2481 case CMD_XMIT_BCAST_CN:
2482 case CMD_XMIT_BCAST_CX:
2483 case CMD_XMIT_BCAST64_CN:
2484 case CMD_XMIT_BCAST64_CX:
2485 (void) emlxs_ip_handle_event(hba, cp, iocbq);
2486 break;
2487
2488 case CMD_XMIT_SEQUENCE_CX:
2489 case CMD_XMIT_SEQUENCE_CR:
2490 case CMD_XMIT_SEQUENCE64_CX:
2491 case CMD_XMIT_SEQUENCE64_CR:
2492 switch (iocb->un.rcvseq64.w5.hcsw.Type) {
2493 case FC_TYPE_IS8802_SNAP:
2494 (void) emlxs_ip_handle_event(hba, cp, iocbq);
2495 break;
2496
2497 case FC_TYPE_FC_SERVICES:
2498 (void) emlxs_ct_handle_event(hba, cp, iocbq);
2499 break;
2500
2501 default:
2502 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2503 "cmd=%x type=%x status=%x iotag=%d context=%x ",
2504 iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
2505 iocb->ULPSTATUS, iocb->ULPIOTAG,
2506 iocb->ULPCONTEXT);
2507 }
2508 break;
2509
2510 case CMD_RCV_SEQUENCE_CX:
2511 case CMD_RCV_SEQUENCE64_CX:
2512 case CMD_RCV_SEQ64_CX:
2513 case CMD_RCV_ELS_REQ_CX: /* Unsolicited ELS frame */
2514 case CMD_RCV_ELS_REQ64_CX: /* Unsolicited ELS frame */
2515 case CMD_RCV_ELS64_CX: /* Unsolicited ELS frame */
2516 if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
2517 (void) emlxs_handle_rcv_seq(hba, cp, iocbq);
2518 }
2519 break;
2520
2521 case CMD_RCV_SEQ_LIST64_CX:
2522 (void) emlxs_ip_handle_rcv_seq_list(hba, cp, iocbq);
2523 break;
2524
2525 case CMD_CREATE_XRI_CR:
2526 case CMD_CREATE_XRI_CX:
2527 (void) emlxs_handle_create_xri(hba, cp, iocbq);
2528 break;
2529
2530 /* RING 2 ELS commands */
2531 case CMD_ELS_REQUEST_CR:
2532 case CMD_ELS_REQUEST_CX:
2533 case CMD_XMIT_ELS_RSP_CX:
2534 case CMD_ELS_REQUEST64_CR:
2535 case CMD_ELS_REQUEST64_CX:
2536 case CMD_XMIT_ELS_RSP64_CX:
2537 (void) emlxs_els_handle_event(hba, cp, iocbq);
2538 break;
2539
2540 /* RING 3 CT commands */
2541 case CMD_GEN_REQUEST64_CR:
2542 case CMD_GEN_REQUEST64_CX:
2543 switch (iocb->un.rcvseq64.w5.hcsw.Type) {
2544 #ifdef MENLO_SUPPORT
2545 case EMLXS_MENLO_TYPE:
2546 (void) emlxs_menlo_handle_event(hba, cp, iocbq);
2547 break;
2548 #endif /* MENLO_SUPPORT */
2549
2550 case FC_TYPE_FC_SERVICES:
2551 (void) emlxs_ct_handle_event(hba, cp, iocbq);
2552 break;
2553
2554 default:
2555 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2556 "cmd=%x type=%x status=%x iotag=%d context=%x ",
2557 iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
2558 iocb->ULPSTATUS, iocb->ULPIOTAG,
2559 iocb->ULPCONTEXT);
2560 }
2561 break;
2562
2563 case CMD_ABORT_XRI_CN: /* Abort fcp command */
2564
2565 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2566 "ABORT_XRI_CN: rpi=%d iotag=%d status=%x parm=%x",
2567 (uint32_t)iocb->un.acxri.abortContextTag,
2568 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2569 iocb->un.acxri.parm);
2570
2571 #ifdef SFCT_SUPPORT
2572 if (port->mode == MODE_TARGET) {
2573 (void) emlxs_fct_handle_abort(hba, cp, iocbq);
2574 }
2575 #endif /* SFCT_SUPPORT */
2576 break;
2577
2578 case CMD_ABORT_XRI_CX: /* Abort command */
2579
2580 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2581 "ABORT_XRI_CX: rpi=%d iotag=%d status=%x parm=%x sbp=%p",
2582 (uint32_t)iocb->un.acxri.abortContextTag,
2583 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2584 iocb->un.acxri.parm, iocbq->sbp);
2585
2586 #ifdef SFCT_SUPPORT
2587 if (port->mode == MODE_TARGET) {
2588 (void) emlxs_fct_handle_abort(hba, cp, iocbq);
2589 }
2590 #endif /* SFCT_SUPPORT */
2591 break;
2592
2593 case CMD_XRI_ABORTED_CX: /* Handle ABORT condition */
2594
2595 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2596 "XRI_ABORTED_CX: rpi=%d iotag=%d status=%x parm=%x",
2597 (uint32_t)iocb->un.acxri.abortContextTag,
2598 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2599 iocb->un.acxri.parm);
2600
2601 #ifdef SFCT_SUPPORT
2602 if (port->mode == MODE_TARGET) {
2603 (void) emlxs_fct_handle_abort(hba, cp, iocbq);
2604 }
2605 #endif /* SFCT_SUPPORT */
2606 break;
2607
2608 case CMD_CLOSE_XRI_CN: /* Handle CLOSE condition */
2609
2610 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2611 "CLOSE_XRI_CN: rpi=%d iotag=%d status=%x parm=%x",
2612 (uint32_t)iocb->un.acxri.abortContextTag,
2613 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2614 iocb->un.acxri.parm);
2615
2616 #ifdef SFCT_SUPPORT
2617 if (port->mode == MODE_TARGET) {
2618 (void) emlxs_fct_handle_abort(hba, cp, iocbq);
2619 }
2620 #endif /* SFCT_SUPPORT */
2621 break;
2622
2623 case CMD_CLOSE_XRI_CX: /* Handle CLOSE condition */
2624
2625 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2626 "CLOSE_XRI_CX: rpi=%d iotag=%d status=%x parm=%x sbp=%p",
2627 (uint32_t)iocb->un.acxri.abortContextTag,
2628 (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2629 iocb->un.acxri.parm, iocbq->sbp);
2630
2631 #ifdef SFCT_SUPPORT
2632 if (port->mode == MODE_TARGET) {
2633 (void) emlxs_fct_handle_abort(hba, cp, iocbq);
2634 }
2635 #endif /* SFCT_SUPPORT */
2636 break;
2637
2638 case CMD_ADAPTER_MSG:
2639 /* Allows debug adapter firmware messages to print on host */
2640 bzero(buffer, sizeof (buffer));
2641 bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA);
2642
2643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer);
2644
2645 break;
2646
2647 case CMD_QUE_RING_LIST64_CN:
2648 case CMD_QUE_RING_BUF64_CN:
2649 break;
2650
2651 case CMD_ASYNC_STATUS:
2652 emlxs_handle_async_event(hba, cp, iocbq);
2653 break;
2654
2655 case CMD_XMIT_BLS_RSP64_CX:
2656 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
2657 "CMD_XMIT_BLS_RSP64_CX: sbp = %p", sbp);
2658
2659 /*
2660 * The exchange should have been already freed in the wqe_cmpl
2661 * so just free up the pkt here.
2662 */
2663 pkt = PRIV2PKT(sbp);
2664 emlxs_pkt_free(pkt);
2665 break;
2666
2667 default:
2668 if (iocb->ULPCOMMAND == 0) {
2669 break;
2670 }
2671
2672 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
2673 "cmd=%x status=%x iotag=%d context=%x", iocb->ULPCOMMAND,
2674 iocb->ULPSTATUS, iocb->ULPIOTAG, iocb->ULPCONTEXT);
2675
2676 break;
2677 } /* switch(entry->ULPCOMMAND) */
2678
2679 return;
2680
2681 } /* emlxs_proc_channel_event() */
2682
2683
2684 extern char *
2685 emlxs_ffstate_xlate(uint32_t state)
2686 {
2687 static char buffer[32];
2688 uint32_t i;
2689 uint32_t count;
2690
2691 count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t);
2692 for (i = 0; i < count; i++) {
2693 if (state == emlxs_ffstate_table[i].code) {
2694 return (emlxs_ffstate_table[i].string);
2695 }
2696 }
2697
2698 (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
2699 return (buffer);
2700
2701 } /* emlxs_ffstate_xlate() */
2702
2703
2704 extern char *
2705 emlxs_ring_xlate(uint32_t ringno)
2706 {
2707 static char buffer[32];
2708 uint32_t i;
2709 uint32_t count;
2710
2711 count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t);
2712 for (i = 0; i < count; i++) {
2713 if (ringno == emlxs_ring_table[i].code) {
2714 return (emlxs_ring_table[i].string);
2715 }
2716 }
2717
2718 (void) snprintf(buffer, sizeof (buffer), "ring=0x%x", ringno);
2719 return (buffer);
2720
2721 } /* emlxs_ring_xlate() */
2722
2723
2724 extern char *
2725 emlxs_pci_cap_xlate(uint32_t id)
2726 {
2727 static char buffer[32];
2728 uint32_t i;
2729 uint32_t count;
2730
2731 count = sizeof (emlxs_pci_cap) / sizeof (emlxs_table_t);
2732 for (i = 0; i < count; i++) {
2733 if (id == emlxs_pci_cap[i].code) {
2734 return (emlxs_pci_cap[i].string);
2735 }
2736 }
2737
2738 (void) snprintf(buffer, sizeof (buffer), "PCI_CAP_ID_%02X", id);
2739 return (buffer);
2740
2741 } /* emlxs_pci_cap_xlate() */
2742
2743
2744 extern char *
2745 emlxs_pci_ecap_xlate(uint32_t id)
2746 {
2747 static char buffer[32];
2748 uint32_t i;
2749 uint32_t count;
2750
2751 count = sizeof (emlxs_pci_ecap) / sizeof (emlxs_table_t);
2752 for (i = 0; i < count; i++) {
2753 if (id == emlxs_pci_ecap[i].code) {
2754 return (emlxs_pci_ecap[i].string);
2755 }
2756 }
2757
2758 (void) snprintf(buffer, sizeof (buffer), "PCI_EXT_CAP_ID_%02X", id);
2759 return (buffer);
2760
2761 } /* emlxs_pci_ecap_xlate() */
2762
2763
2764 extern void
2765 emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose)
2766 {
2767 emlxs_port_t *port = &PPORT;
2768 MAILBOXQ *mbq;
2769 MAILBOX *mb;
2770 emlxs_config_t *cfg;
2771 uint32_t value;
2772
2773 cfg = &CFG;
2774
2775 xlate:
2776
2777 switch (cfg[CFG_PCI_MAX_READ].current) {
2778 case 512:
2779 value = 0;
2780 break;
2781
2782 case 1024:
2783 value = 1;
2784 break;
2785
2786 case 2048:
2787 value = 2;
2788 break;
2789
2790 case 4096:
2791 value = 3;
2792 break;
2793
2794 default:
2795 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2796 "PCI_MAX_READ: Invalid parameter value. old=%d new=%d",
2797 cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def);
2798
2799 cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def;
2800 goto xlate;
2801 }
2802
2803 if ((mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)),
2804 KM_SLEEP)) == 0) {
2805 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2806 "PCI_MAX_READ: Unable to allocate mailbox buffer.");
2807 return;
2808 }
2809 mb = (MAILBOX *)mbq;
2810
2811 emlxs_mb_set_var(hba, mbq, 0x00100506, value);
2812
2813 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2814 if (verbose || (mb->mbxStatus != 0x12)) {
2815 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2816 "PCI_MAX_READ: Unable to update. "
2817 "status=%x value=%d (%d bytes)",
2818 mb->mbxStatus, value,
2819 cfg[CFG_PCI_MAX_READ].current);
2820 }
2821 } else {
2822 if (verbose &&
2823 (cfg[CFG_PCI_MAX_READ].current !=
2824 cfg[CFG_PCI_MAX_READ].def)) {
2825 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2826 "PCI_MAX_READ: Updated. %d bytes",
2827 cfg[CFG_PCI_MAX_READ].current);
2828 }
2829 }
2830
2831 (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
2832
2833 return;
2834
2835 } /* emlxs_pcix_mxr_update */
2836
2837
2838
2839 extern uint32_t
2840 emlxs_get_key(emlxs_hba_t *hba, MAILBOXQ *mbq)
2841 {
2842 emlxs_port_t *port = &PPORT;
2843 MAILBOX *mb = (MAILBOX *)mbq;
2844 uint32_t npname0, npname1;
2845 uint32_t tmpkey, theKey;
2846 uint16_t key850;
2847 uint32_t t1, t2, t3, t4;
2848 uint32_t ts;
2849
2850 #define SEED 0x876EDC21
2851
2852 /* This key is only used currently for SBUS adapters */
2853 if (hba->bus_type != SBUS_FC) {
2854 return (0);
2855 }
2856
2857 tmpkey = mb->un.varWords[30];
2858 EMLXS_STATE_CHANGE(hba, FC_INIT_NVPARAMS);
2859
2860 emlxs_mb_read_nv(hba, mbq);
2861 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2862 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2863 "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand,
2864 mb->mbxStatus);
2865
2866 return (0);
2867 }
2868 npname0 = mb->un.varRDnvp.portname[0];
2869 npname1 = mb->un.varRDnvp.portname[1];
2870
2871 key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8);
2872 ts = (uint16_t)(npname1 + 1);
2873 t1 = ts * key850;
2874 ts = (uint16_t)((npname1 >> 16) + 1);
2875 t2 = ts * key850;
2876 ts = (uint16_t)(npname0 + 1);
2877 t3 = ts * key850;
2878 ts = (uint16_t)((npname0 >> 16) + 1);
2879 t4 = ts * key850;
2880 theKey = SEED + t1 + t2 + t3 + t4;
2881
2882 return (theKey);
2883
2884 } /* emlxs_get_key() */
2885
2886
2887 extern void
2888 emlxs_fw_show(emlxs_hba_t *hba)
2889 {
2890 emlxs_port_t *port = &PPORT;
2891 uint32_t i;
2892
2893 /* Display firmware library one time */
2894 for (i = 0; i < emlxs_fw_count; i++) {
2895 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s",
2896 emlxs_fw_table[i].label);
2897 }
2898
2899 return;
2900
2901 } /* emlxs_fw_show() */
2902
2903
2904 #ifdef MODFW_SUPPORT
2905 extern void
2906 emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw)
2907 {
2908 emlxs_port_t *port = &PPORT;
2909 int (*emlxs_fw_get)(emlxs_firmware_t *);
2910 int err;
2911 char name[64];
2912
2913 /* Make sure image is unloaded and image buffer pointer is clear */
2914 emlxs_fw_unload(hba, fw);
2915
2916 err = 0;
2917 hba->fw_modhandle =
2918 ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err);
2919 if (!hba->fw_modhandle) {
2920 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2921 "Unable to load firmware module. error=%d", err);
2922
2923 return;
2924 } else {
2925 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2926 "Firmware module loaded.");
2927 }
2928
2929 (void) snprintf(name, sizeof (name), "%s_fw_get", DRIVER_NAME);
2930 err = 0;
2931 emlxs_fw_get =
2932 (int (*)())ddi_modsym(hba->fw_modhandle, name, &err);
2933 if ((void *)emlxs_fw_get == NULL) {
2934 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2935 "%s not present. error=%d", name, err);
2936
2937 emlxs_fw_unload(hba, fw);
2938 return;
2939 }
2940
2941 if (emlxs_fw_get(fw)) {
2942 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2943 "Invalid firmware image module found. %s", fw->label);
2944
2945 emlxs_fw_unload(hba, fw);
2946 return;
2947 }
2948
2949 return;
2950
2951 } /* emlxs_fw_load() */
2952
2953
2954 extern void
2955 emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw)
2956 {
2957 emlxs_port_t *port = &PPORT;
2958
2959 /* Clear the firmware image */
2960 fw->image = NULL;
2961 fw->size = 0;
2962
2963 if (hba->fw_modhandle) {
2964 /* Close the module */
2965 (void) ddi_modclose(hba->fw_modhandle);
2966 hba->fw_modhandle = NULL;
2967
2968 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2969 "Firmware module unloaded.");
2970 }
2971
2972 return;
2973
2974 } /* emlxs_fw_unload() */
2975 #endif /* MODFW_SUPPORT */
2976
2977
2978 static void
2979 emlxs_pci_cap_offsets(emlxs_hba_t *hba)
2980 {
2981 emlxs_port_t *port = &PPORT;
2982 uint32_t reg;
2983 uint8_t offset;
2984 uint8_t next;
2985 uint8_t id;
2986 uint16_t eoffset;
2987 uint16_t enext;
2988 uint8_t eversion;
2989 uint16_t eid;
2990
2991 /* Read PCI capbabilities */
2992
2993 bzero(hba->pci_cap_offset, sizeof (hba->pci_cap_offset));
2994
2995 /* Read first offset */
2996 offset = PCI_CAP_POINTER;
2997 offset = ddi_get8(hba->pci_acc_handle,
2998 (uint8_t *)(hba->pci_addr + offset));
2999
3000 while (offset >= PCI_CAP_PTR_OFF) {
3001 /* Read the cap */
3002 reg = ddi_get32(hba->pci_acc_handle,
3003 (uint32_t *)(hba->pci_addr + offset));
3004
3005 id = ((reg >> PCI_CAP_ID_SHIFT) & PCI_CAP_ID_MASK);
3006 next = ((reg >> PCI_CAP_NEXT_PTR_SHIFT) &
3007 PCI_CAP_NEXT_PTR_MASK);
3008
3009 if ((id < PCI_CAP_MAX_PTR) &&
3010 (hba->pci_cap_offset[id] == 0)) {
3011 hba->pci_cap_offset[id] = offset;
3012 }
3013
3014 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3015 "%s: offset=0x%x next=0x%x",
3016 emlxs_pci_cap_xlate(id), offset, next);
3017
3018 offset = next;
3019 }
3020
3021 /* Workaround for BE adapters */
3022 if ((hba->pci_cap_offset[PCI_CAP_ID_VS] == 0) &&
3023 (hba->model_info.chip & EMLXS_BE_CHIPS)) {
3024 hba->pci_cap_offset[PCI_CAP_ID_VS] = 0x54;
3025
3026 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3027 "%s: offset=0x%x Added.",
3028 emlxs_pci_cap_xlate(PCI_CAP_ID_VS),
3029 hba->pci_cap_offset[PCI_CAP_ID_VS]);
3030 }
3031
3032 if (! hba->pci_cap_offset[PCI_CAP_ID_PCI_E]) {
3033 /* It's not a PCIE adapter. */
3034 return;
3035 }
3036
3037 /* Read PCI Extended capbabilities */
3038
3039 bzero(hba->pci_ecap_offset, sizeof (hba->pci_ecap_offset));
3040
3041 /* Set first offset */
3042 eoffset = PCIE_EXT_CAP;
3043
3044 while (eoffset >= PCIE_EXT_CAP) {
3045 /* Read the cap */
3046 reg = ddi_get32(hba->pci_acc_handle,
3047 (uint32_t *)(hba->pci_addr + eoffset));
3048
3049 eid = ((reg >> PCIE_EXT_CAP_ID_SHIFT) & PCIE_EXT_CAP_ID_MASK);
3050 eversion = ((reg >> PCIE_EXT_CAP_VER_SHIFT) &
3051 PCIE_EXT_CAP_VER_MASK);
3052 enext = ((reg >> PCIE_EXT_CAP_NEXT_PTR_SHIFT) &
3053 PCIE_EXT_CAP_NEXT_PTR_MASK);
3054
3055 if ((eid < PCI_EXT_CAP_MAX_PTR) &&
3056 (hba->pci_ecap_offset[eid] == 0)) {
3057 hba->pci_ecap_offset[eid] = eoffset;
3058 }
3059
3060 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3061 "%s: offset=0x%x version=0x%x next=0x%x",
3062 emlxs_pci_ecap_xlate(eid),
3063 eoffset, eversion, enext);
3064
3065 eoffset = enext;
3066 }
3067
3068 return;
3069
3070 } /* emlxs_pci_cap_offsets() */