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