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