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