PageRenderTime 70ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_hba.c

https://bitbucket.org/buffyg/illumos-gate-1514
C | 2838 lines | 1935 code | 556 blank | 347 comment | 472 complexity | 1a0264f2a4fca20c3eef54eb84eaf7fe MD5 | raw file
Possible License(s): BSD-3-Clause-No-Nuclear-License-2014, MPL-2.0-no-copyleft-exception, AGPL-3.0, GPL-2.0, GPL-3.0, LGPL-3.0, 0BSD, AGPL-1.0, BSD-3-Clause, LGPL-2.1, LGPL-2.0, BSD-2-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License (the "License").
  6. * You may not use this file except in compliance with the License.
  7. *
  8. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  9. * or http://www.opensolaris.org/os/licensing.
  10. * See the License for the specific language governing permissions
  11. * and limitations under the License.
  12. *
  13. * When distributing Covered Code, include this CDDL HEADER in each
  14. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15. * If applicable, add the following below this CDDL HEADER, with the
  16. * fields enclosed by brackets "[]" replaced with your own identifying
  17. * information: Portions Copyright [yyyy] [name of copyright owner]
  18. *
  19. * CDDL HEADER END
  20. */
  21. /*
  22. * Copyright 2010 Emulex. All rights reserved.
  23. * Use is subject to license terms.
  24. */
  25. #define EMLXS_FW_TABLE_DEF
  26. #define EMLXS_MODEL_DEF
  27. #include <emlxs.h>
  28. /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
  29. EMLXS_MSG_DEF(EMLXS_HBA_C);
  30. static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp,
  31. IOCBQ *iocbq);
  32. static void emlxs_pci_cap_offsets(emlxs_hba_t *hba);
  33. #ifdef MSI_SUPPORT
  34. uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] =
  35. {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8};
  36. uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] =
  37. {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4,
  38. EMLXS_MSI0_MASK8};
  39. #endif /* MSI_SUPPORT */
  40. emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE;
  41. int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t);
  42. emlxs_table_t emlxs_pci_cap[] = {
  43. {PCI_CAP_ID_PM, "PCI_CAP_ID_PM"},
  44. {PCI_CAP_ID_AGP, "PCI_CAP_ID_AGP"},
  45. {PCI_CAP_ID_VPD, "PCI_CAP_ID_VPD"},
  46. {PCI_CAP_ID_SLOT_ID, "PCI_CAP_ID_SLOT_ID"},
  47. {PCI_CAP_ID_MSI, "PCI_CAP_ID_MSI"},
  48. {PCI_CAP_ID_cPCI_HS, "PCI_CAP_ID_cPCI_HS"},
  49. {PCI_CAP_ID_PCIX, "PCI_CAP_ID_PCIX"},
  50. {PCI_CAP_ID_HT, "PCI_CAP_ID_HT"},
  51. {PCI_CAP_ID_VS, "PCI_CAP_ID_VS"},
  52. {PCI_CAP_ID_DEBUG_PORT, "PCI_CAP_ID_DEBUG_PORT"},
  53. {PCI_CAP_ID_cPCI_CRC, "PCI_CAP_ID_cPCI_CRC"},
  54. {PCI_CAP_ID_PCI_HOTPLUG, "PCI_CAP_ID_PCI_HOTPLUG"},
  55. {PCI_CAP_ID_P2P_SUBSYS, "PCI_CAP_ID_P2P_SUBSYS"},
  56. {PCI_CAP_ID_AGP_8X, "PCI_CAP_ID_AGP_8X"},
  57. {PCI_CAP_ID_SECURE_DEV, "PCI_CAP_ID_SECURE_DEV"},
  58. {PCI_CAP_ID_PCI_E, "PCI_CAP_ID_PCI_E"},
  59. {PCI_CAP_ID_MSI_X, "PCI_CAP_ID_MSI_X"},
  60. {PCI_CAP_ID_SATA, "PCI_CAP_ID_SATA"},
  61. {PCI_CAP_ID_FLR, "PCI_CAP_ID_FLR"}
  62. }; /* emlxs_pci_cap */
  63. emlxs_table_t emlxs_ring_table[] = {
  64. {FC_FCP_RING, "FCP Ring"},
  65. {FC_IP_RING, "IP Ring"},
  66. {FC_ELS_RING, "ELS Ring"},
  67. {FC_CT_RING, "CT Ring"}
  68. }; /* emlxs_ring_table */
  69. emlxs_table_t emlxs_ffstate_table[] = {
  70. {0, "NULL"},
  71. {FC_ERROR, "ERROR"},
  72. {FC_KILLED, "KILLED"},
  73. {FC_WARM_START, "WARM_START"},
  74. {FC_INIT_START, "INIT_START"},
  75. {FC_INIT_NVPARAMS, "INIT_NVPARAMS"},
  76. {FC_INIT_REV, "INIT_REV"},
  77. {FC_INIT_CFGPORT, "INIT_CFGPORT"},
  78. {FC_INIT_CFGRING, "INIT_CFGRING"},
  79. {FC_INIT_INITLINK, "INIT_INITLINK"},
  80. {FC_LINK_DOWN, "LINK_DOWN"},
  81. {FC_LINK_UP, "LINK_UP"},
  82. {FC_CLEAR_LA, "CLEAR_LA"},
  83. {FC_READY, "READY"}
  84. }; /* emlxs_ffstate_table */
  85. #ifdef MSI_SUPPORT
  86. /* EMLXS_INTR_INIT */
  87. int32_t
  88. emlxs_msi_init(emlxs_hba_t *hba, uint32_t max)
  89. {
  90. emlxs_port_t *port = &PPORT;
  91. int32_t pass = 0;
  92. int32_t type = 0;
  93. char s_type[16];
  94. int32_t types;
  95. int32_t count;
  96. int32_t nintrs;
  97. int32_t mode;
  98. int32_t actual;
  99. int32_t new_actual;
  100. int32_t i;
  101. int32_t ret;
  102. ddi_intr_handle_t *htable = NULL;
  103. ddi_intr_handle_t *new_htable = NULL;
  104. uint32_t *intr_pri = NULL;
  105. int32_t *intr_cap = NULL;
  106. int32_t hilevel_pri;
  107. emlxs_config_t *cfg = &CFG;
  108. char buf[64];
  109. if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
  110. return (emlxs_intx_init(hba, max));
  111. }
  112. if (hba->intr_flags & EMLXS_MSI_INITED) {
  113. return (DDI_SUCCESS);
  114. }
  115. /* Set max interrupt count if not specified */
  116. if (max == 0) {
  117. if ((cfg[CFG_MSI_MODE].current == 2) ||
  118. (cfg[CFG_MSI_MODE].current == 3)) {
  119. max = EMLXS_MSI_MAX_INTRS;
  120. } else {
  121. max = 1;
  122. }
  123. }
  124. /* Filter max interrupt count with adapter model specification */
  125. if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) {
  126. max = hba->model_info.intr_limit;
  127. }
  128. /* Get the available interrupt types from the kernel */
  129. types = 0;
  130. ret = ddi_intr_get_supported_types(hba->dip, &types);
  131. if ((ret != DDI_SUCCESS)) {
  132. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  133. "MSI: ddi_intr_get_supported_types failed. ret=%d", ret);
  134. /* Default to fixed type */
  135. types = DDI_INTR_TYPE_FIXED;
  136. }
  137. /* Check if fixed interrupts are being forced */
  138. if (cfg[CFG_MSI_MODE].current == 0) {
  139. types &= DDI_INTR_TYPE_FIXED;
  140. }
  141. /* Check if MSI interrupts are being forced */
  142. else if ((cfg[CFG_MSI_MODE].current == 1) ||
  143. (cfg[CFG_MSI_MODE].current == 2)) {
  144. types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
  145. }
  146. begin:
  147. /* Set interrupt type and interrupt count */
  148. type = 0;
  149. /* Check if MSIX is fully supported */
  150. if ((types & DDI_INTR_TYPE_MSIX) &&
  151. (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) {
  152. /* Get the max interrupt count from the adapter */
  153. nintrs = 0;
  154. ret =
  155. ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX,
  156. &nintrs);
  157. if (ret == DDI_SUCCESS && nintrs) {
  158. type = DDI_INTR_TYPE_MSIX;
  159. (void) strcpy(s_type, "TYPE_MSIX");
  160. goto initialize;
  161. }
  162. }
  163. /* Check if MSI is fully supported */
  164. if ((types & DDI_INTR_TYPE_MSI) &&
  165. (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) {
  166. /* Get the max interrupt count from the adapter */
  167. nintrs = 0;
  168. ret =
  169. ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs);
  170. if (ret == DDI_SUCCESS && nintrs) {
  171. type = DDI_INTR_TYPE_MSI;
  172. (void) strcpy(s_type, "TYPE_MSI");
  173. goto initialize;
  174. }
  175. }
  176. /* Check if fixed interrupts are fully supported */
  177. if ((types & DDI_INTR_TYPE_FIXED) &&
  178. (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
  179. /* Get the max interrupt count from the adapter */
  180. nintrs = 0;
  181. ret =
  182. ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED,
  183. &nintrs);
  184. if (ret == DDI_SUCCESS) {
  185. type = DDI_INTR_TYPE_FIXED;
  186. (void) strcpy(s_type, "TYPE_FIXED");
  187. goto initialize;
  188. }
  189. }
  190. goto init_failed;
  191. initialize:
  192. pass++;
  193. mode = 0;
  194. actual = 0;
  195. htable = NULL;
  196. intr_pri = NULL;
  197. intr_cap = NULL;
  198. hilevel_pri = 0;
  199. if (pass == 1) {
  200. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  201. "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type,
  202. cfg[CFG_MSI_MODE].current, types, nintrs);
  203. }
  204. /* Validate interrupt count */
  205. count = min(nintrs, max);
  206. if (count >= 8) {
  207. count = 8;
  208. } else if (count >= 4) {
  209. count = 4;
  210. } else if (count >= 2) {
  211. count = 2;
  212. } else {
  213. count = 1;
  214. }
  215. /* Allocate an array of interrupt handles */
  216. htable =
  217. kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)),
  218. KM_SLEEP);
  219. /* Allocate 'count' interrupts */
  220. ret =
  221. ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count,
  222. &actual, DDI_INTR_ALLOC_NORMAL);
  223. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  224. "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret);
  225. if ((ret != DDI_SUCCESS) || (actual == 0)) {
  226. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  227. "MSI: Unable to allocate interrupts. error=%d", ret);
  228. actual = 0;
  229. goto init_failed;
  230. }
  231. if (actual != count) {
  232. /* Validate actual count */
  233. if (actual >= 8) {
  234. new_actual = 8;
  235. } else if (actual >= 4) {
  236. new_actual = 4;
  237. } else if (actual >= 2) {
  238. new_actual = 2;
  239. } else {
  240. new_actual = 1;
  241. }
  242. if (new_actual < actual) {
  243. /* Free extra handles */
  244. for (i = new_actual; i < actual; i++) {
  245. (void) ddi_intr_free(htable[i]);
  246. }
  247. actual = new_actual;
  248. }
  249. /* Allocate a new array of interrupt handles */
  250. new_htable =
  251. kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)),
  252. KM_SLEEP);
  253. /* Copy old array to new array */
  254. bcopy((uint8_t *)htable, (uint8_t *)new_htable,
  255. (actual * sizeof (ddi_intr_handle_t)));
  256. /* Free the old array */
  257. kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
  258. htable = new_htable;
  259. count = actual;
  260. }
  261. /* Allocate interrupt priority table */
  262. intr_pri =
  263. (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)),
  264. KM_SLEEP);
  265. /* Allocate interrupt capability table */
  266. intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP);
  267. /* Get minimum hilevel priority */
  268. hilevel_pri = ddi_intr_get_hilevel_pri();
  269. /* Fill the priority and capability tables */
  270. for (i = 0; i < count; ++i) {
  271. ret = ddi_intr_get_pri(htable[i], &intr_pri[i]);
  272. if (ret != DDI_SUCCESS) {
  273. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  274. "MSI: ddi_intr_get_pri(%d) failed. "
  275. "handle=%p ret=%d",
  276. i, &htable[i], ret);
  277. /* Clean up the interrupts */
  278. goto init_failed;
  279. }
  280. if (intr_pri[i] >= hilevel_pri) {
  281. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  282. "MSI: Interrupt(%d) level too high. "
  283. "pri=0x%x hilevel=0x%x",
  284. i, intr_pri[i], hilevel_pri);
  285. /* Clean up the interrupts */
  286. goto init_failed;
  287. }
  288. ret = ddi_intr_get_cap(htable[i], &intr_cap[i]);
  289. if (ret != DDI_SUCCESS) {
  290. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  291. "MSI: ddi_intr_get_cap(%d) failed. "
  292. "handle=%p ret=%d",
  293. i, &htable[i], ret);
  294. /* Clean up the interrupts */
  295. goto init_failed;
  296. }
  297. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  298. "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i,
  299. intr_cap[i], intr_pri[i], hilevel_pri);
  300. }
  301. /* Set mode */
  302. switch (count) {
  303. case 8:
  304. mode = EMLXS_MSI_MODE8;
  305. break;
  306. case 4:
  307. mode = EMLXS_MSI_MODE4;
  308. break;
  309. case 2:
  310. mode = EMLXS_MSI_MODE2;
  311. break;
  312. default:
  313. mode = EMLXS_MSI_MODE1;
  314. }
  315. /* Save the info */
  316. hba->intr_htable = htable;
  317. hba->intr_count = count;
  318. hba->intr_pri = intr_pri;
  319. hba->intr_cap = intr_cap;
  320. hba->intr_type = type;
  321. hba->intr_arg = (void *)((unsigned long)intr_pri[0]);
  322. hba->intr_mask = emlxs_msi_mask[mode];
  323. hba->intr_cond = 0;
  324. /* Adjust number of channels based on intr_count */
  325. if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
  326. hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
  327. }
  328. for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
  329. hba->intr_map[i] = emlxs_msi_map[mode][i];
  330. hba->intr_cond |= emlxs_msi_map[mode][i];
  331. (void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME,
  332. hba->ddiinst, i);
  333. mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER,
  334. DDI_INTR_PRI(hba->intr_arg));
  335. }
  336. /* Set flag to indicate support */
  337. hba->intr_flags |= EMLXS_MSI_INITED;
  338. /* Create the interrupt threads */
  339. for (i = 0; i < hba->chan_count; i++) {
  340. (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
  341. hba->ddiinst, i);
  342. mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
  343. DDI_INTR_PRI(hba->intr_arg));
  344. emlxs_thread_create(hba, &hba->chan[i].intr_thread);
  345. }
  346. return (DDI_SUCCESS);
  347. init_failed:
  348. if (intr_cap) {
  349. kmem_free(intr_cap, (count * sizeof (int32_t)));
  350. }
  351. if (intr_pri) {
  352. kmem_free(intr_pri, (count * sizeof (int32_t)));
  353. }
  354. if (htable) {
  355. /* Process the interrupt handlers */
  356. for (i = 0; i < actual; i++) {
  357. /* Free the handle[i] */
  358. (void) ddi_intr_free(htable[i]);
  359. }
  360. kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
  361. }
  362. /* Initialize */
  363. hba->intr_htable = NULL;
  364. hba->intr_count = 0;
  365. hba->intr_pri = NULL;
  366. hba->intr_cap = NULL;
  367. hba->intr_type = 0;
  368. hba->intr_arg = NULL;
  369. hba->intr_cond = 0;
  370. bzero(hba->intr_map, sizeof (hba->intr_map));
  371. bzero(hba->intr_lock, sizeof (hba->intr_lock));
  372. if (type == DDI_INTR_TYPE_MSIX) {
  373. types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
  374. goto begin;
  375. } else if (type == DDI_INTR_TYPE_MSI) {
  376. types &= DDI_INTR_TYPE_FIXED;
  377. goto begin;
  378. }
  379. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
  380. "MSI: Unable to initialize interrupts");
  381. return (DDI_FAILURE);
  382. } /* emlxs_msi_init() */
  383. /* EMLXS_INTR_UNINIT */
  384. int32_t
  385. emlxs_msi_uninit(emlxs_hba_t *hba)
  386. {
  387. uint32_t count;
  388. int32_t i;
  389. ddi_intr_handle_t *htable;
  390. uint32_t *intr_pri;
  391. int32_t *intr_cap;
  392. int32_t ret;
  393. if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
  394. return (emlxs_intx_uninit(hba));
  395. }
  396. /*
  397. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  398. * "MSI: emlxs_msi_uninit called. flags=%x",
  399. * hba->intr_flags);
  400. */
  401. /* Make sure interrupts have been removed first */
  402. if ((hba->intr_flags & EMLXS_MSI_ADDED)) {
  403. ret = emlxs_msi_remove(hba);
  404. if (ret != DDI_SUCCESS) {
  405. return (ret);
  406. }
  407. }
  408. /* Check if the interrupts are still initialized */
  409. if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
  410. return (DDI_SUCCESS);
  411. }
  412. hba->intr_flags &= ~EMLXS_MSI_INITED;
  413. /* Get handle table parameters */
  414. htable = hba->intr_htable;
  415. count = hba->intr_count;
  416. intr_pri = hba->intr_pri;
  417. intr_cap = hba->intr_cap;
  418. /* Clean up */
  419. hba->intr_count = 0;
  420. hba->intr_htable = NULL;
  421. hba->intr_pri = NULL;
  422. hba->intr_cap = NULL;
  423. hba->intr_type = 0;
  424. hba->intr_arg = NULL;
  425. hba->intr_cond = 0;
  426. bzero(hba->intr_map, sizeof (hba->intr_map));
  427. if (intr_cap) {
  428. kmem_free(intr_cap, (count * sizeof (int32_t)));
  429. }
  430. if (intr_pri) {
  431. kmem_free(intr_pri, (count * sizeof (int32_t)));
  432. }
  433. if (htable) {
  434. /* Process the interrupt handlers */
  435. for (i = 0; i < count; ++i) {
  436. /* Free the handle[i] */
  437. ret = ddi_intr_free(htable[i]);
  438. }
  439. kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
  440. }
  441. /* Destroy the intr locks */
  442. for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
  443. mutex_destroy(&hba->intr_lock[i]);
  444. }
  445. /* Destroy the interrupt threads */
  446. for (i = 0; i < hba->chan_count; i++) {
  447. emlxs_thread_destroy(&hba->chan[i].intr_thread);
  448. mutex_destroy(&hba->chan[i].rsp_lock);
  449. }
  450. /*
  451. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  452. * "MSI: emlxs_msi_uninit done. flags=%x",
  453. * hba->intr_flags);
  454. */
  455. return (DDI_SUCCESS);
  456. } /* emlxs_msi_uninit() */
  457. /* EMLXS_INTR_ADD */
  458. int32_t
  459. emlxs_msi_add(emlxs_hba_t *hba)
  460. {
  461. emlxs_port_t *port = &PPORT;
  462. int32_t count;
  463. int32_t i;
  464. int32_t ret;
  465. ddi_intr_handle_t *htable = NULL;
  466. int32_t *intr_cap = NULL;
  467. if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
  468. return (emlxs_intx_add(hba));
  469. }
  470. /* Check if interrupts have already been added */
  471. if (hba->intr_flags & EMLXS_MSI_ADDED) {
  472. return (DDI_SUCCESS);
  473. }
  474. /* Check if interrupts have been initialized */
  475. if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
  476. ret = emlxs_msi_init(hba, 0);
  477. if (ret != DDI_SUCCESS) {
  478. return (ret);
  479. }
  480. }
  481. /* Get handle table parameters */
  482. htable = hba->intr_htable;
  483. count = hba->intr_count;
  484. intr_cap = hba->intr_cap;
  485. /* Add the interrupt handlers */
  486. for (i = 0; i < count; ++i) {
  487. /* add handler for handle[i] */
  488. ret =
  489. ddi_intr_add_handler(htable[i], EMLXS_SLI_MSI_INTR,
  490. (char *)hba, (char *)((unsigned long)i));
  491. if (ret != DDI_SUCCESS) {
  492. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
  493. "MSI: ddi_intr_add_handler(%d) failed. "
  494. "handle=%p ret=%d",
  495. i, &htable[i], ret);
  496. /* Process the remaining interrupt handlers */
  497. while (i) {
  498. /* Decrement i */
  499. i--;
  500. /* Remove the handler */
  501. ret = ddi_intr_remove_handler(htable[i]);
  502. }
  503. return (DDI_FAILURE);
  504. }
  505. }
  506. /* Enable the interrupts */
  507. if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
  508. ret = ddi_intr_block_enable(htable, count);
  509. if (ret != DDI_SUCCESS) {
  510. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  511. "MSI: ddi_intr_block_enable(%d) failed. ret=%d",
  512. count, ret);
  513. for (i = 0; i < count; ++i) {
  514. ret = ddi_intr_enable(htable[i]);
  515. if (ret != DDI_SUCCESS) {
  516. EMLXS_MSGF(EMLXS_CONTEXT,
  517. &emlxs_init_debug_msg,
  518. "MSI: ddi_intr_enable(%d) failed. "
  519. "ret=%d",
  520. i, ret);
  521. }
  522. }
  523. }
  524. } else {
  525. for (i = 0; i < count; ++i) {
  526. ret = ddi_intr_enable(htable[i]);
  527. if (ret != DDI_SUCCESS) {
  528. EMLXS_MSGF(EMLXS_CONTEXT,
  529. &emlxs_init_debug_msg,
  530. "MSI: ddi_intr_enable(%d) failed. ret=%d",
  531. i, ret);
  532. }
  533. }
  534. }
  535. /* Set flag to indicate support */
  536. hba->intr_flags |= EMLXS_MSI_ADDED;
  537. return (DDI_SUCCESS);
  538. } /* emlxs_msi_add() */
  539. /* EMLXS_INTR_REMOVE */
  540. int32_t
  541. emlxs_msi_remove(emlxs_hba_t *hba)
  542. {
  543. emlxs_port_t *port = &PPORT;
  544. uint32_t count;
  545. int32_t i;
  546. ddi_intr_handle_t *htable;
  547. int32_t *intr_cap;
  548. int32_t ret;
  549. if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
  550. return (emlxs_intx_remove(hba));
  551. }
  552. /*
  553. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  554. * "MSI: emlxs_msi_remove called. flags=%x",
  555. * hba->intr_flags);
  556. */
  557. /* Check if interrupts have already been removed */
  558. if (!(hba->intr_flags & EMLXS_MSI_ADDED)) {
  559. return (DDI_SUCCESS);
  560. }
  561. hba->intr_flags &= ~EMLXS_MSI_ADDED;
  562. /* Disable all adapter interrupts */
  563. EMLXS_SLI_DISABLE_INTR(hba, 0);
  564. /* Get handle table parameters */
  565. htable = hba->intr_htable;
  566. count = hba->intr_count;
  567. intr_cap = hba->intr_cap;
  568. /* Disable the interrupts */
  569. if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
  570. ret = ddi_intr_block_disable(htable, count);
  571. if (ret != DDI_SUCCESS) {
  572. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
  573. "MSI: ddi_intr_block_disable(%d) failed. ret=%d",
  574. count, ret);
  575. for (i = 0; i < count; i++) {
  576. ret = ddi_intr_disable(htable[i]);
  577. if (ret != DDI_SUCCESS) {
  578. EMLXS_MSGF(EMLXS_CONTEXT,
  579. &emlxs_init_debug_msg,
  580. "MSI: ddi_intr_disable(%d) failed. "
  581. "ret=%d",
  582. i, ret);
  583. }
  584. }
  585. }
  586. } else {
  587. for (i = 0; i < count; i++) {
  588. ret = ddi_intr_disable(htable[i]);
  589. if (ret != DDI_SUCCESS) {
  590. EMLXS_MSGF(EMLXS_CONTEXT,
  591. &emlxs_init_debug_msg,
  592. "MSI: ddi_intr_disable(%d) failed. ret=%d",
  593. i, ret);
  594. }
  595. }
  596. }
  597. /* Process the interrupt handlers */
  598. for (i = 0; i < count; i++) {
  599. /* Remove the handler */
  600. ret = ddi_intr_remove_handler(htable[i]);
  601. }
  602. return (DDI_SUCCESS);
  603. } /* emlxs_msi_remove() */
  604. #endif /* MSI_SUPPORT */
  605. /* EMLXS_INTR_INIT */
  606. /* ARGSUSED */
  607. int32_t
  608. emlxs_intx_init(emlxs_hba_t *hba, uint32_t max)
  609. {
  610. emlxs_port_t *port = &PPORT;
  611. emlxs_config_t *cfg = &CFG;
  612. int32_t ret;
  613. uint32_t i;
  614. char buf[64];
  615. /* Check if interrupts have already been initialized */
  616. if (hba->intr_flags & EMLXS_INTX_INITED) {
  617. return (DDI_SUCCESS);
  618. }
  619. /* Check if adapter is flagged for INTX support */
  620. if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
  621. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
  622. "INTX: %s does not support INTX. flags=0x%x",
  623. hba->model_info.model, hba->model_info.flags);
  624. return (DDI_FAILURE);
  625. }
  626. /*
  627. * Interrupt number '0' is a high-level interrupt. This driver
  628. * does not support having its interrupts mapped above scheduler
  629. * priority; i.e., we always expect to be able to call general
  630. * kernel routines that may invoke the scheduler.
  631. */
  632. if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) {
  633. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
  634. "INTX: High-level interrupt not supported.");
  635. return (DDI_FAILURE);
  636. }
  637. /* Get an iblock cookie */
  638. ret =
  639. ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER,
  640. (ddi_iblock_cookie_t *)&hba->intr_arg);
  641. if (ret != DDI_SUCCESS) {
  642. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
  643. "INTX: ddi_get_iblock_cookie failed. ret=%d", ret);
  644. return (ret);
  645. }
  646. hba->intr_flags |= EMLXS_INTX_INITED;
  647. hba->intr_count = 1;
  648. /* Adjust number of channels based on intr_count */
  649. if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
  650. hba->chan_count = cfg[CFG_NUM_WQ].current;
  651. }
  652. /* Create the interrupt threads */
  653. for (i = 0; i < hba->chan_count; i++) {
  654. (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME,
  655. hba->ddiinst, i);
  656. mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER,
  657. DDI_INTR_PRI(hba->intr_arg));
  658. emlxs_thread_create(hba, &hba->chan[i].intr_thread);
  659. }
  660. return (DDI_SUCCESS);
  661. } /* emlxs_intx_init() */
  662. /* EMLXS_INTR_UNINIT */
  663. int32_t
  664. emlxs_intx_uninit(emlxs_hba_t *hba)
  665. {
  666. int32_t ret;
  667. uint32_t i;
  668. /* Make sure interrupts have been removed */
  669. if ((hba->intr_flags & EMLXS_INTX_ADDED)) {
  670. ret = emlxs_intx_remove(hba);
  671. if (ret != DDI_SUCCESS) {
  672. return (ret);
  673. }
  674. }
  675. /* Check if the interrupts are still initialized */
  676. if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
  677. return (DDI_SUCCESS);
  678. }
  679. hba->intr_flags &= ~EMLXS_INTX_INITED;
  680. hba->intr_arg = NULL;
  681. /* Create the interrupt threads */
  682. for (i = 0; i < hba->chan_count; i++) {
  683. emlxs_thread_destroy(&hba->chan[i].intr_thread);
  684. mutex_destroy(&hba->chan[i].rsp_lock);
  685. }
  686. return (DDI_SUCCESS);
  687. } /* emlxs_intx_uninit() */
  688. /*
  689. * This is the legacy method for adding interrupts in Solaris
  690. * EMLXS_INTR_ADD
  691. */
  692. int32_t
  693. emlxs_intx_add(emlxs_hba_t *hba)
  694. {
  695. emlxs_port_t *port = &PPORT;
  696. int32_t ret;
  697. /* Check if interrupts have already been added */
  698. if (hba->intr_flags & EMLXS_INTX_ADDED) {
  699. return (DDI_SUCCESS);
  700. }
  701. /* Check if interrupts have been initialized */
  702. if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
  703. ret = emlxs_intx_init(hba, 0);
  704. if (ret != DDI_SUCCESS) {
  705. return (ret);
  706. }
  707. }
  708. /* add intrrupt handler routine */
  709. ret = ddi_add_intr((void *)hba->dip,
  710. (uint_t)EMLXS_INUMBER,
  711. (ddi_iblock_cookie_t *)&hba->intr_arg,
  712. (ddi_idevice_cookie_t *)0,
  713. (uint_t(*)())EMLXS_SLI_INTX_INTR, (caddr_t)hba);
  714. if (ret != DDI_SUCCESS) {
  715. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
  716. "INTX: ddi_add_intr failed. ret=%d", ret);
  717. return (ret);
  718. }
  719. hba->intr_flags |= EMLXS_INTX_ADDED;
  720. return (DDI_SUCCESS);
  721. } /* emlxs_intx_add() */
  722. /* EMLXS_INTR_REMOVE */
  723. int32_t
  724. emlxs_intx_remove(emlxs_hba_t *hba)
  725. {
  726. /* Check if interrupts have already been removed */
  727. if (!(hba->intr_flags & EMLXS_INTX_ADDED)) {
  728. return (DDI_SUCCESS);
  729. }
  730. hba->intr_flags &= ~EMLXS_INTX_ADDED;
  731. /* Diable all adapter interrupts */
  732. EMLXS_SLI_DISABLE_INTR(hba, 0);
  733. /* Remove the interrupt */
  734. (void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER,
  735. hba->intr_arg);
  736. return (DDI_SUCCESS);
  737. } /* emlxs_intx_remove() */
  738. extern void
  739. emlxs_process_link_speed(emlxs_hba_t *hba)
  740. {
  741. emlxs_vpd_t *vpd;
  742. emlxs_config_t *cfg;
  743. char *cptr;
  744. uint32_t hi;
  745. /*
  746. * This routine modifies the link-speed config parameter entry
  747. * based on adapter capabilities
  748. */
  749. vpd = &VPD;
  750. cfg = &hba->config[CFG_LINK_SPEED];
  751. cptr = cfg->help;
  752. (void) strcpy(cptr, "Select link speed. [0=Auto");
  753. cptr += 26;
  754. hi = 0;
  755. if (vpd->link_speed & LMT_1GB_CAPABLE) {
  756. (void) strcpy(cptr, ", 1=1Gb");
  757. cptr += 7;
  758. hi = 1;
  759. }
  760. if (vpd->link_speed & LMT_2GB_CAPABLE) {
  761. (void) strcpy(cptr, ", 2=2Gb");
  762. cptr += 7;
  763. hi = 2;
  764. }
  765. if (vpd->link_speed & LMT_4GB_CAPABLE) {
  766. (void) strcpy(cptr, ", 4=4Gb");
  767. cptr += 7;
  768. hi = 4;
  769. }
  770. if (vpd->link_speed & LMT_8GB_CAPABLE) {
  771. (void) strcpy(cptr, ", 8=8Gb");
  772. cptr += 7;
  773. hi = 8;
  774. }
  775. if (vpd->link_speed & LMT_10GB_CAPABLE) {
  776. (void) strcpy(cptr, ", 10=10Gb");
  777. cptr += 9;
  778. hi = 10;
  779. }
  780. (void) strcpy(cptr, "]");
  781. cfg->hi = hi;
  782. /* Now revalidate the current parameter setting */
  783. cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current);
  784. return;
  785. } /* emlxs_process_link_speed() */
  786. /*
  787. * emlxs_parse_vpd()
  788. *
  789. * This routine will parse the VPD data
  790. */
  791. extern int
  792. emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size)
  793. {
  794. emlxs_port_t *port = &PPORT;
  795. char tag[3];
  796. uint8_t lenlo, lenhi;
  797. uint32_t n;
  798. uint16_t block_size;
  799. uint32_t block_index = 0;
  800. uint8_t sub_size;
  801. uint32_t sub_index;
  802. int32_t finished = 0;
  803. int32_t index = 0;
  804. char buffer[128];
  805. emlxs_vpd_t *vpd;
  806. vpd = &VPD;
  807. while (!finished && (block_index < size)) {
  808. /*
  809. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  810. * "block_index = %x", block_index);
  811. */
  812. switch (vpd_buf[block_index]) {
  813. case 0x82:
  814. index = block_index;
  815. index += 1;
  816. lenlo = vpd_buf[index];
  817. index += 1;
  818. lenhi = vpd_buf[index];
  819. index += 1;
  820. block_index = index;
  821. block_size = ((((uint16_t)lenhi) << 8) + lenlo);
  822. block_index += block_size;
  823. /*
  824. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  825. * "block_size = %x", block_size);
  826. */
  827. n = sizeof (buffer);
  828. bzero(buffer, n);
  829. bcopy(&vpd_buf[index], buffer,
  830. (block_size < (n - 1)) ? block_size : (n - 1));
  831. (void) strcpy(vpd->id, buffer);
  832. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s",
  833. vpd->id);
  834. break;
  835. case 0x90:
  836. index = block_index;
  837. index += 1;
  838. lenlo = vpd_buf[index];
  839. index += 1;
  840. lenhi = vpd_buf[index];
  841. index += 1;
  842. block_index = index;
  843. sub_index = index;
  844. block_size = ((((uint16_t)lenhi) << 8) + lenlo);
  845. block_index += block_size;
  846. /*
  847. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  848. * "block_size = %x", block_size);
  849. */
  850. /* Scan for sub-blocks */
  851. while ((sub_index < block_index) &&
  852. (sub_index < size)) {
  853. /*
  854. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  855. * "sub_index = %x", sub_index);
  856. */
  857. index = sub_index;
  858. tag[0] = vpd_buf[index++];
  859. tag[1] = vpd_buf[index++];
  860. tag[2] = 0;
  861. sub_size = vpd_buf[index++];
  862. /*
  863. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  864. * "sub_size = %x", sub_size);
  865. */
  866. sub_index = (index + sub_size);
  867. n = sizeof (buffer);
  868. bzero(buffer, n);
  869. bcopy(&vpd_buf[index], buffer,
  870. (sub_size < (n - 1)) ? sub_size : (n - 1));
  871. /*
  872. * Look for Engineering Change (EC)
  873. */
  874. if (strcmp(tag, "EC") == 0) {
  875. (void) strcpy(vpd->eng_change, buffer);
  876. EMLXS_MSGF(EMLXS_CONTEXT,
  877. &emlxs_vpd_msg, "EC: %s",
  878. vpd->eng_change);
  879. }
  880. /*
  881. * Look for Manufacturer (MN)
  882. */
  883. else if (strcmp(tag, "MN") == 0) {
  884. (void) strcpy(vpd->manufacturer,
  885. buffer);
  886. EMLXS_MSGF(EMLXS_CONTEXT,
  887. &emlxs_vpd_msg, "MN: %s",
  888. vpd->manufacturer);
  889. }
  890. /*
  891. * Look for Serial Number (SN)
  892. */
  893. else if (strcmp(tag, "SN") == 0) {
  894. (void) strcpy(vpd->serial_num, buffer);
  895. EMLXS_MSGF(EMLXS_CONTEXT,
  896. &emlxs_vpd_msg, "SN: %s",
  897. vpd->serial_num);
  898. /* Validate the serial number */
  899. if (strncmp(buffer, "FFFFFFFFFF", 10) ==
  900. 0 ||
  901. strncmp(buffer, "0000000000", 10) ==
  902. 0) {
  903. vpd->serial_num[0] = 0;
  904. }
  905. }
  906. /*
  907. * Look for Part Number (PN)
  908. */
  909. else if (strcmp(tag, "PN") == 0) {
  910. (void) strcpy(vpd->part_num, buffer);
  911. EMLXS_MSGF(EMLXS_CONTEXT,
  912. &emlxs_vpd_msg, "PN: %s",
  913. vpd->part_num);
  914. }
  915. /*
  916. * Look for (V0)
  917. */
  918. else if (strcmp(tag, "V0") == 0) {
  919. /* Not used */
  920. EMLXS_MSGF(EMLXS_CONTEXT,
  921. &emlxs_vpd_msg, "V0: %s", buffer);
  922. }
  923. /*
  924. * Look for model description (V1)
  925. */
  926. else if (strcmp(tag, "V1") == 0) {
  927. (void) strcpy(vpd->model_desc, buffer);
  928. EMLXS_MSGF(EMLXS_CONTEXT,
  929. &emlxs_vpd_msg, "Desc: %s",
  930. vpd->model_desc);
  931. }
  932. /*
  933. * Look for model (V2)
  934. */
  935. else if (strcmp(tag, "V2") == 0) {
  936. (void) strcpy(vpd->model, buffer);
  937. EMLXS_MSGF(EMLXS_CONTEXT,
  938. &emlxs_vpd_msg, "Model: %s",
  939. vpd->model);
  940. }
  941. /*
  942. * Look for program type (V3)
  943. */
  944. else if (strcmp(tag, "V3") == 0) {
  945. (void) strcpy(vpd->prog_types, buffer);
  946. EMLXS_MSGF(EMLXS_CONTEXT,
  947. &emlxs_vpd_msg, "Prog Types: %s",
  948. vpd->prog_types);
  949. }
  950. /*
  951. * Look for port number (V4)
  952. */
  953. else if (strcmp(tag, "V4") == 0) {
  954. (void) strcpy(vpd->port_num, buffer);
  955. vpd->port_index =
  956. emlxs_strtol(vpd->port_num, 10);
  957. EMLXS_MSGF(EMLXS_CONTEXT,
  958. &emlxs_vpd_msg, "Port: %s",
  959. (vpd->port_num[0]) ? vpd->
  960. port_num : "not applicable");
  961. }
  962. /*
  963. * Look for checksum (RV)
  964. */
  965. else if (strcmp(tag, "RV") == 0) {
  966. /* Not used */
  967. EMLXS_MSGF(EMLXS_CONTEXT,
  968. &emlxs_vpd_msg, "Checksum: 0x%x",
  969. buffer[0]);
  970. }
  971. else {
  972. /* Generic */
  973. EMLXS_MSGF(EMLXS_CONTEXT,
  974. &emlxs_vpd_msg, "Tag: %s: %s",
  975. tag, buffer);
  976. }
  977. }
  978. break;
  979. case 0x78:
  980. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag.");
  981. finished = 1;
  982. break;
  983. default:
  984. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  985. "Unknown block: %x %x %x %x %x %x %x %x",
  986. vpd_buf[index], vpd_buf[index + 1],
  987. vpd_buf[index + 2], vpd_buf[index + 3],
  988. vpd_buf[index + 4], vpd_buf[index + 5],
  989. vpd_buf[index + 6], vpd_buf[index + 7]);
  990. return (0);
  991. }
  992. }
  993. return (1);
  994. } /* emlxs_parse_vpd */
  995. /*
  996. * emlxs_parse_fcoe()
  997. *
  998. * This routine will parse the VPD data
  999. */
  1000. extern int
  1001. emlxs_parse_fcoe(emlxs_hba_t *hba, uint8_t *fcoep, uint32_t size)
  1002. {
  1003. emlxs_port_t *port = &PPORT;
  1004. tlv_fcoe_t *fcoelist;
  1005. tlv_fcfconnectlist_t *fcflist;
  1006. int i;
  1007. /* Validate the config region 23 signature */
  1008. if ((*fcoep != 'R') || (*(fcoep+1) != 'G') ||
  1009. (*(fcoep+2) != '2') || (*(fcoep+3) != '3')) {
  1010. return (0);
  1011. }
  1012. /* Search the config region 23, for FCOE Parameters record */
  1013. i = 4;
  1014. while ((i < size) && (*(fcoep+i) != 0xA0) && (*(fcoep+i) != 0xff)) {
  1015. i += fcoep[i+1] * sizeof (uint32_t) + 2;
  1016. }
  1017. if (*(fcoep+i) == 0xA0) {
  1018. fcoelist = (tlv_fcoe_t *)(fcoep+i);
  1019. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  1020. "Found FCOE Params (A0):%d x%x",
  1021. fcoelist->length, fcoelist->fip_flags);
  1022. bcopy((uint8_t *)fcoelist, (uint8_t *)&hba->sli.sli4.cfgFCOE,
  1023. sizeof (tlv_fcoe_t));
  1024. }
  1025. /* Search the config region 23, for FCF record */
  1026. i = 4;
  1027. while ((i < size) && (*(fcoep+i) != 0xA1) && (*(fcoep+i) != 0xff)) {
  1028. i += fcoep[i+1] * sizeof (uint32_t) + 2;
  1029. }
  1030. if (*(fcoep+i) == 0xA1) {
  1031. fcflist = (tlv_fcfconnectlist_t *)(fcoep+i);
  1032. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  1033. "Found FCF ConnectList (A1):%d", fcflist->length);
  1034. bcopy((uint8_t *)fcflist, (uint8_t *)&hba->sli.sli4.cfgFCF,
  1035. sizeof (tlv_fcfconnectlist_t));
  1036. }
  1037. return (1);
  1038. } /* emlxs_parse_fcoe */
  1039. extern void
  1040. emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd)
  1041. {
  1042. if (vpd->rBit) {
  1043. switch (hba->sli_mode) {
  1044. case EMLXS_HBA_SLI4_MODE:
  1045. (void) strcpy(vpd->fw_version, vpd->sli4FwName);
  1046. (void) strcpy(vpd->fw_label, vpd->sli4FwLabel);
  1047. break;
  1048. case EMLXS_HBA_SLI3_MODE:
  1049. (void) strcpy(vpd->fw_version, vpd->sli3FwName);
  1050. (void) strcpy(vpd->fw_label, vpd->sli3FwLabel);
  1051. break;
  1052. case EMLXS_HBA_SLI2_MODE:
  1053. (void) strcpy(vpd->fw_version, vpd->sli2FwName);
  1054. (void) strcpy(vpd->fw_label, vpd->sli2FwLabel);
  1055. break;
  1056. case EMLXS_HBA_SLI1_MODE:
  1057. (void) strcpy(vpd->fw_version, vpd->sli1FwName);
  1058. (void) strcpy(vpd->fw_label, vpd->sli1FwLabel);
  1059. break;
  1060. default:
  1061. (void) strcpy(vpd->fw_version, "unknown");
  1062. (void) strcpy(vpd->fw_label, vpd->fw_version);
  1063. }
  1064. } else {
  1065. emlxs_decode_version(vpd->smFwRev, vpd->fw_version);
  1066. (void) strcpy(vpd->fw_label, vpd->fw_version);
  1067. }
  1068. return;
  1069. } /* emlxs_decode_firmware_rev() */
  1070. extern void
  1071. emlxs_decode_version(uint32_t version, char *buffer)
  1072. {
  1073. uint32_t b1, b2, b3, b4;
  1074. char c;
  1075. b1 = (version & 0x0000f000) >> 12;
  1076. b2 = (version & 0x00000f00) >> 8;
  1077. b3 = (version & 0x000000c0) >> 6;
  1078. b4 = (version & 0x00000030) >> 4;
  1079. if (b1 == 0 && b2 == 0) {
  1080. (void) sprintf(buffer, "none");
  1081. return;
  1082. }
  1083. c = 0;
  1084. switch (b4) {
  1085. case 0:
  1086. c = 'n';
  1087. break;
  1088. case 1:
  1089. c = 'a';
  1090. break;
  1091. case 2:
  1092. c = 'b';
  1093. break;
  1094. case 3:
  1095. if ((version & 0x0000000f)) {
  1096. c = 'x';
  1097. }
  1098. break;
  1099. }
  1100. b4 = (version & 0x0000000f);
  1101. if (c == 0) {
  1102. (void) sprintf(buffer, "%d.%d%d", b1, b2, b3);
  1103. } else {
  1104. (void) sprintf(buffer, "%d.%d%d%c%d", b1, b2, b3, c, b4);
  1105. }
  1106. return;
  1107. } /* emlxs_decode_version() */
  1108. extern void
  1109. emlxs_decode_label(char *label, char *buffer, int bige)
  1110. {
  1111. uint32_t i;
  1112. char name[16];
  1113. bcopy(label, name, sizeof (name));
  1114. /* bige is TRUE if the data format is big endian */
  1115. if (bige) {
  1116. /* Data format big Endian */
  1117. LE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
  1118. for (i = 0; i < sizeof (name); i++) {
  1119. if (name[i] == 0x20) {
  1120. name[i] = 0;
  1121. }
  1122. }
  1123. } else {
  1124. /* Data format little Endian */
  1125. BE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
  1126. for (i = 0; i < sizeof (name); i++) {
  1127. if (name[i] == 0x20) {
  1128. name[i] = 0;
  1129. }
  1130. }
  1131. }
  1132. (void) strcpy(buffer, name);
  1133. return;
  1134. } /* emlxs_decode_label() */
  1135. extern uint32_t
  1136. emlxs_strtol(char *str, uint32_t base)
  1137. {
  1138. uint32_t value = 0;
  1139. char *ptr;
  1140. uint32_t factor = 1;
  1141. uint32_t digits;
  1142. if (*str == 0) {
  1143. return (0);
  1144. }
  1145. if (base != 10 && base != 16) {
  1146. return (0);
  1147. }
  1148. /* Get max digits of value */
  1149. digits = (base == 10) ? 9 : 8;
  1150. /* Position pointer to end of string */
  1151. ptr = str + strlen(str);
  1152. /* Process string backwards */
  1153. while ((ptr-- > str) && digits) {
  1154. /* check for base 10 numbers */
  1155. if (*ptr >= '0' && *ptr <= '9') {
  1156. value += ((uint32_t)(*ptr - '0')) * factor;
  1157. factor *= base;
  1158. digits--;
  1159. } else if (base == 16) {
  1160. /* Check for base 16 numbers */
  1161. if (*ptr >= 'a' && *ptr <= 'f') {
  1162. value +=
  1163. ((uint32_t)(*ptr - 'a') + 10) * factor;
  1164. factor *= base;
  1165. digits--;
  1166. } else if (*ptr >= 'A' && *ptr <= 'F') {
  1167. value +=
  1168. ((uint32_t)(*ptr - 'A') + 10) * factor;
  1169. factor *= base;
  1170. digits--;
  1171. } else if (factor > 1) {
  1172. break;
  1173. }
  1174. } else if (factor > 1) {
  1175. break;
  1176. }
  1177. }
  1178. return (value);
  1179. } /* emlxs_strtol() */
  1180. extern uint64_t
  1181. emlxs_strtoll(char *str, uint32_t base)
  1182. {
  1183. uint64_t value = 0;
  1184. char *ptr;
  1185. uint32_t factor = 1;
  1186. uint32_t digits;
  1187. if (*str == 0) {
  1188. return (0);
  1189. }
  1190. if (base != 10 && base != 16) {
  1191. return (0);
  1192. }
  1193. /* Get max digits of value */
  1194. digits = (base == 10) ? 19 : 16;
  1195. /* Position pointer to end of string */
  1196. ptr = str + strlen(str);
  1197. /* Process string backwards */
  1198. while ((ptr-- > str) && digits) {
  1199. /* check for base 10 numbers */
  1200. if (*ptr >= '0' && *ptr <= '9') {
  1201. value += ((uint32_t)(*ptr - '0')) * factor;
  1202. factor *= base;
  1203. digits--;
  1204. } else if (base == 16) {
  1205. /* Check for base 16 numbers */
  1206. if (*ptr >= 'a' && *ptr <= 'f') {
  1207. value +=
  1208. ((uint32_t)(*ptr - 'a') + 10) * factor;
  1209. factor *= base;
  1210. digits--;
  1211. } else if (*ptr >= 'A' && *ptr <= 'F') {
  1212. value +=
  1213. ((uint32_t)(*ptr - 'A') + 10) * factor;
  1214. factor *= base;
  1215. digits--;
  1216. } else if (factor > 1) {
  1217. break;
  1218. }
  1219. } else if (factor > 1) {
  1220. break;
  1221. }
  1222. }
  1223. return (value);
  1224. } /* emlxs_strtoll() */
  1225. extern void
  1226. emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types)
  1227. {
  1228. emlxs_port_t *port = &PPORT;
  1229. uint32_t i;
  1230. char *ptr;
  1231. emlxs_model_t *model;
  1232. char types_buffer[256];
  1233. char *types;
  1234. bcopy(prog_types, types_buffer, 256);
  1235. types = types_buffer;
  1236. model = &hba->model_info;
  1237. while (*types) {
  1238. if (strncmp(types, "T2:", 3) == 0) {
  1239. bzero(model->pt_2, sizeof (model->pt_2));
  1240. types += 3;
  1241. i = 0;
  1242. while (*types && *types != 'T') {
  1243. /* Null terminate the next value */
  1244. ptr = types;
  1245. while (*ptr && (*ptr != ','))
  1246. ptr++;
  1247. *ptr = 0;
  1248. /* Save the value */
  1249. model->pt_2[i++] =
  1250. (uint8_t)emlxs_strtol(types, 16);
  1251. /*
  1252. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  1253. * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]);
  1254. */
  1255. /* Move the str pointer */
  1256. types = ptr + 1;
  1257. }
  1258. } else if (strncmp(types, "T3:", 3) == 0) {
  1259. bzero(model->pt_3, sizeof (model->pt_3));
  1260. types += 3;
  1261. i = 0;
  1262. while (*types && *types != 'T') {
  1263. /* Null terminate the next value */
  1264. ptr = types;
  1265. while (*ptr && (*ptr != ','))
  1266. ptr++;
  1267. *ptr = 0;
  1268. /* Save the value */
  1269. model->pt_3[i++] =
  1270. (uint8_t)emlxs_strtol(types, 16);
  1271. /*
  1272. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  1273. * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]);
  1274. */
  1275. /* Move the str pointer */
  1276. types = ptr + 1;
  1277. }
  1278. } else if (strncmp(types, "T6:", 3) == 0) {
  1279. bzero(model->pt_6, sizeof (model->pt_6));
  1280. types += 3;
  1281. i = 0;
  1282. while (*types && *types != 'T') {
  1283. /* Null terminate the next value */
  1284. ptr = types;
  1285. while (*ptr && (*ptr != ','))
  1286. ptr++;
  1287. *ptr = 0;
  1288. /* Save the value */
  1289. model->pt_6[i++] =
  1290. (uint8_t)emlxs_strtol(types, 16);
  1291. model->pt_6[i] = 0;
  1292. /*
  1293. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  1294. * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]);
  1295. */
  1296. /* Move the str pointer */
  1297. types = ptr + 1;
  1298. }
  1299. } else if (strncmp(types, "T7:", 3) == 0) {
  1300. bzero(model->pt_7, sizeof (model->pt_7));
  1301. types += 3;
  1302. i = 0;
  1303. while (*types && *types != 'T') {
  1304. /* Null terminate the next value */
  1305. ptr = types;
  1306. while (*ptr && (*ptr != ','))
  1307. ptr++;
  1308. *ptr = 0;
  1309. /* Save the value */
  1310. model->pt_7[i++] =
  1311. (uint8_t)emlxs_strtol(types, 16);
  1312. model->pt_7[i] = 0;
  1313. /*
  1314. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  1315. * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]);
  1316. */
  1317. /* Move the str pointer */
  1318. types = ptr + 1;
  1319. }
  1320. } else if (strncmp(types, "TA:", 3) == 0) {
  1321. bzero(model->pt_A, sizeof (model->pt_A));
  1322. types += 3;
  1323. i = 0;
  1324. while (*types && *types != 'T') {
  1325. /* Null terminate the next value */
  1326. ptr = types;
  1327. while (*ptr && (*ptr != ','))
  1328. ptr++;
  1329. *ptr = 0;
  1330. /* Save the value */
  1331. model->pt_A[i++] =
  1332. (uint8_t)emlxs_strtol(types, 16);
  1333. /*
  1334. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  1335. * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]);
  1336. */
  1337. /* Move the str pointer */
  1338. types = ptr + 1;
  1339. }
  1340. } else if (strncmp(types, "TB:", 3) == 0) {
  1341. bzero(model->pt_B, sizeof (model->pt_B));
  1342. types += 3;
  1343. i = 0;
  1344. while (*types && *types != 'T') {
  1345. /* Null terminate the next value */
  1346. ptr = types;
  1347. while (*ptr && (*ptr != ','))
  1348. ptr++;
  1349. *ptr = 0;
  1350. /* Save the value */
  1351. model->pt_B[i++] =
  1352. (uint8_t)emlxs_strtol(types, 16);
  1353. /*
  1354. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  1355. * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]);
  1356. */
  1357. /* Move the str pointer */
  1358. types = ptr + 1;
  1359. }
  1360. } else if (strncmp(types, "TFF:", 4) == 0) {
  1361. bzero(model->pt_FF, sizeof (model->pt_FF));
  1362. types += 4;
  1363. i = 0;
  1364. while (*types && *types != 'T') {
  1365. /* Null terminate the next value */
  1366. ptr = types;
  1367. while (*ptr && (*ptr != ','))
  1368. ptr++;
  1369. *ptr = 0;
  1370. /* Save the value */
  1371. model->pt_FF[i++] =
  1372. (uint8_t)emlxs_strtol(types, 16);
  1373. /*
  1374. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  1375. * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]);
  1376. */
  1377. /* Move the str pointer */
  1378. types = ptr + 1;
  1379. }
  1380. } else if (strncmp(types, "T20:", 4) == 0) {
  1381. bzero(model->pt_20, sizeof (model->pt_20));
  1382. types += 4;
  1383. i = 0;
  1384. while (*types && *types != 'T') {
  1385. /* Null terminate the next value */
  1386. ptr = types;
  1387. while (*ptr && (*ptr != ','))
  1388. ptr++;
  1389. *ptr = 0;
  1390. /* Save the value */
  1391. model->pt_20[i++] =
  1392. (uint8_t)emlxs_strtol(types, 16);
  1393. model->pt_20[i] = 0;
  1394. /*
  1395. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  1396. * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]);
  1397. */
  1398. /* Move the str pointer */
  1399. types = ptr + 1;
  1400. }
  1401. } else {
  1402. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
  1403. "Unknown prog type string = %s", types);
  1404. break;
  1405. }
  1406. }
  1407. return;
  1408. } /* emlxs_parse_prog_types() */
  1409. extern void
  1410. emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types)
  1411. {
  1412. uint32_t i;
  1413. uint32_t found = 0;
  1414. char buffer[256];
  1415. bzero(prog_types, 256);
  1416. /* Rebuild the prog type string */
  1417. if (hba->model_info.pt_2[0]) {
  1418. (void) strcat(prog_types, "T2:");
  1419. found = 1;
  1420. i = 0;
  1421. while (hba->model_info.pt_2[i] && i < 8) {
  1422. (void) sprintf(buffer, "%X,", hba->model_info.pt_2[i]);
  1423. (void) strcat(prog_types, buffer);
  1424. i++;
  1425. }
  1426. }
  1427. if (hba->model_info.pt_3[0]) {
  1428. (void) strcat(prog_types, "T3:");
  1429. found = 1;
  1430. i = 0;
  1431. while (hba->model_info.pt_3[i] && i < 8) {
  1432. (void) sprintf(buffer, "%X,", hba->model_info.pt_3[i]);
  1433. (void) strcat(prog_types, buffer);
  1434. i++;
  1435. }
  1436. }
  1437. if (hba->model_info.pt_6[0]) {
  1438. (void) strcat(prog_types, "T6:");
  1439. found = 1;
  1440. i = 0;
  1441. while (hba->model_info.pt_6[i] && i < 8) {
  1442. (void) sprintf(buffer, "%X,", hba->model_info.pt_6[i]);
  1443. (void) strcat(prog_types, buffer);
  1444. i++;
  1445. }
  1446. }
  1447. if (hba->model_info.pt_7[0]) {
  1448. (void) strcat(prog_types, "T7:");
  1449. found = 1;
  1450. i = 0;
  1451. while (hba->model_info.pt_7[i] && i < 8) {
  1452. (void) sprintf(buffer, "%X,", hba->model_info.pt_7[i]);
  1453. (void) strcat(prog_types, buffer);
  1454. i++;
  1455. }
  1456. }
  1457. if (hba->model_info.pt_A[0]) {
  1458. (void) strcat(prog_types, "TA:");
  1459. found = 1;
  1460. i = 0;
  1461. while (hba->model_info.pt_A[i] && i < 8) {
  1462. (void) sprintf(buffer, "%X,", hba->model_info.pt_A[i]);
  1463. (void) strcat(prog_types, buffer);
  1464. i++;
  1465. }
  1466. }
  1467. if (hba->model_info.pt_B[0]) {
  1468. (void) strcat(prog_types, "TB:");
  1469. found = 1;
  1470. i = 0;
  1471. while (hba->model_info.pt_B[i] && i < 8) {
  1472. (void) sprintf(buffer, "%X,", hba->model_info.pt_B[i]);
  1473. (void) strcat(prog_types, buffer);
  1474. i++;
  1475. }
  1476. }
  1477. if (hba->model_info.pt_20[0]) {
  1478. (void) strcat(prog_types, "T20:");
  1479. found = 1;
  1480. i = 0;
  1481. while (hba->model_info.pt_20[i] && i < 8) {
  1482. (void) sprintf(buffer, "%X,", hba->model_info.pt_20[i]);
  1483. (void) strcat(prog_types, buffer);
  1484. i++;
  1485. }
  1486. }
  1487. if (hba->model_info.pt_FF[0]) {
  1488. (void) strcat(prog_types, "TFF:");
  1489. found = 1;
  1490. i = 0;
  1491. while (hba->model_info.pt_FF[i] && i < 8) {
  1492. (void) sprintf(buffer, "%X,", hba->model_info.pt_FF[i]);
  1493. (void) strcat(prog_types, buffer);
  1494. i++;
  1495. }
  1496. }
  1497. if (found) {
  1498. /* Terminate at the last comma in string */
  1499. prog_types[(strlen(prog_types) - 1)] = 0;
  1500. }
  1501. return;
  1502. } /* emlxs_build_prog_types() */
  1503. extern uint32_t
  1504. emlxs_init_adapter_info(emlxs_hba_t *hba)
  1505. {
  1506. emlxs_port_t *port = &PPORT;
  1507. uint32_t pci_id;
  1508. uint32_t cache_line;
  1509. uint32_t channels;
  1510. uint16_t device_id;
  1511. uint16_t ssdid;
  1512. uint32_t i;
  1513. uint32_t found = 0;
  1514. int32_t *prop;
  1515. uint32_t num_prop;
  1516. if (hba->bus_type == SBUS_FC) {
  1517. if (hba->pci_acc_handle == NULL) {
  1518. bcopy(&emlxs_sbus_model[0], &hba->model_info,
  1519. sizeof (emlxs_model_t));
  1520. hba->model_info.device_id = 0;
  1521. return (0);
  1522. }
  1523. /* Read the PCI device id */
  1524. pci_id =
  1525. ddi_get32(hba->pci_acc_handle,
  1526. (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER));
  1527. device_id = (uint16_t)(pci_id >> 16);
  1528. /* Find matching adapter model */
  1529. for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) {
  1530. if (emlxs_sbus_model[i].device_id == device_id) {
  1531. bcopy(&emlxs_sbus_model[i], &hba->model_info,
  1532. sizeof (emlxs_model_t));
  1533. found = 1;
  1534. break;
  1535. }
  1536. }
  1537. /* If not found then use the unknown model */
  1538. if (!found) {
  1539. bcopy(&emlxs_sbus_model[0], &hba->model_info,
  1540. sizeof (emlxs_model_t));
  1541. hba->model_info.device_id = device_id;
  1542. return (0);
  1543. }
  1544. } else { /* PCI model */
  1545. if (hba->pci_acc_handle == NULL) {
  1546. bcopy(&emlxs_pci_model[0], &hba->model_info,
  1547. sizeof (emlxs_model_t));
  1548. hba->model_info.device_id = 0;
  1549. return (0);
  1550. }
  1551. /* Read the PCI device id */
  1552. device_id =
  1553. ddi_get16(hba->pci_acc_handle,
  1554. (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER));
  1555. /* Read the PCI Subsystem id */
  1556. ssdid =
  1557. ddi_get16(hba->pci_acc_handle,
  1558. (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER));
  1559. if (ssdid == 0 || ssdid == 0xffff) {
  1560. ssdid = device_id;
  1561. }
  1562. /* Read the Cache Line reg */
  1563. cache_line =
  1564. ddi_get32(hba->pci_acc_handle,
  1565. (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER));
  1566. /* Check for the multifunction bit being set */
  1567. if ((cache_line & 0x00ff0000) == 0x00800000) {
  1568. channels = 2;
  1569. } else {
  1570. channels = 1;
  1571. }
  1572. /* If device ids are unique, then use them for search */
  1573. if (device_id != ssdid) {
  1574. if (channels > 1) {
  1575. /*
  1576. * Find matching adapter model using
  1577. * device_id, ssdid and channels
  1578. */
  1579. for (i = 1; i < emlxs_pci_model_count; i++) {
  1580. if (emlxs_pci_model[i].device_id ==
  1581. device_id &&
  1582. emlxs_pci_model[i].ssdid == ssdid &&
  1583. emlxs_pci_model[i].channels ==
  1584. channels) {
  1585. bcopy(&emlxs_pci_model[i],
  1586. &hba->model_info,
  1587. sizeof (emlxs_model_t));
  1588. found = 1;
  1589. break;
  1590. }
  1591. }
  1592. } else {
  1593. /*
  1594. * Find matching adapter model using
  1595. * device_id and ssdid
  1596. */
  1597. for (i = 1; i < emlxs_pci_model_count; i++) {
  1598. if (emlxs_pci_model[i].device_id ==
  1599. device_id &&
  1600. emlxs_pci_model[i].ssdid == ssdid) {
  1601. bcopy(&emlxs_pci_model[i],
  1602. &hba->model_info,
  1603. sizeof (emlxs_model_t));
  1604. found = 1;
  1605. break;
  1606. }
  1607. }
  1608. }
  1609. }
  1610. /* If adapter not found, try again */
  1611. if (!found) {
  1612. /* Find matching adapter model */
  1613. for (i = 1; i < emlxs_pci_model_count; i++) {
  1614. if (emlxs_pci_model[i].device_id == device_id &&
  1615. emlxs_pci_model[i].channels == channels) {
  1616. bcopy(&emlxs_pci_model[i],
  1617. &hba->model_info,
  1618. sizeof (emlxs_model_t));
  1619. found = 1;
  1620. break;
  1621. }
  1622. }
  1623. }
  1624. /* If adapter not found, try one last time */
  1625. if (!found) {
  1626. /* Find matching adapter model */
  1627. for (i = 1; i < emlxs_pci_model_count; i++) {
  1628. if (emlxs_pci_model[i].device_id == device_id) {
  1629. bcopy(&emlxs_pci_model[i],
  1630. &hba->model_info,
  1631. sizeof (emlxs_model_t));
  1632. found = 1;
  1633. break;
  1634. }
  1635. }
  1636. }
  1637. /* If not found, set adapter to unknown */
  1638. if (!found) {
  1639. bcopy(&emlxs_pci_model[0], &hba->model_info,
  1640. sizeof (emlxs_model_t));
  1641. hba->model_info.device_id = device_id;
  1642. hba->model_info.ssdid = ssdid;
  1643. return (0);
  1644. }
  1645. #ifndef SATURN_MSI_SUPPORT
  1646. /*
  1647. * This will disable MSI support for Saturn adapter's
  1648. * due to a PCI bus issue
  1649. */
  1650. if (hba->model_info.chip == EMLXS_SATURN_CHIP) {
  1651. hba->model_info.flags &=
  1652. ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED);
  1653. }
  1654. #endif /* !SATURN_MSI_SUPPORT */
  1655. /* Scan the PCI capabilities */
  1656. emlxs_pci_cap_offsets(hba);
  1657. #ifdef MSI_SUPPORT
  1658. /* Verify MSI support */
  1659. if ((hba->model_info.flags & EMLXS_MSI_SUPPORTED) &&
  1660. !hba->pci_cap_offset[PCI_CAP_ID_MSI]) {
  1661. hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED;
  1662. }
  1663. /* Verify MSI-X support */
  1664. if ((hba->model_info.flags & EMLXS_MSIX_SUPPORTED) &&
  1665. !hba->pci_cap_offset[PCI_CAP_ID_MSI_X]) {
  1666. hba->model_info.flags &= ~EMLXS_MSIX_SUPPORTED;
  1667. }
  1668. #endif /* MSI_SUPPORT */
  1669. }
  1670. if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0,
  1671. "reg", &prop, &num_prop) == DDI_PROP_SUCCESS) {
  1672. /* Parse the property for PCI function, device and bus no. */
  1673. hba->pci_function_number =
  1674. (uint8_t)((prop[0] & 0x00000700) >> 8);
  1675. hba->pci_device_number = (uint8_t)((prop[0] & 0x00008100) >> 8);
  1676. hba->pci_bus_number = (uint8_t)((prop[0] & 0x00ff0000) >> 16);
  1677. ddi_prop_free((void *)prop);
  1678. }
  1679. if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
  1680. hba->sli_api = emlxs_sli4_api;
  1681. } else {
  1682. hba->sli_api = emlxs_sli3_api;
  1683. }
  1684. #ifdef FMA_SUPPORT
  1685. if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
  1686. != DDI_FM_OK) {
  1687. EMLXS_MSGF(EMLXS_CONTEXT,
  1688. &emlxs_invalid_access_handle_msg, NULL);
  1689. return (0);
  1690. }
  1691. #endif /* FMA_SUPPORT */
  1692. return (1);
  1693. } /* emlxs_init_adapter_info() */
  1694. /* ARGSUSED */
  1695. static void
  1696. emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
  1697. {
  1698. emlxs_port_t *port = &PPORT;
  1699. IOCB *iocb;
  1700. uint32_t *w;
  1701. int i, j;
  1702. iocb = &iocbq->iocb;
  1703. if (iocb->ULPSTATUS != 0) {
  1704. return;
  1705. }
  1706. switch (iocb->un.astat.EventCode) {
  1707. case 0x0100: /* Temp Warning */
  1708. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg,
  1709. "Adapter is very hot (%d °C). Take corrective action.",
  1710. iocb->ULPCONTEXT);
  1711. hba->temperature = iocb->ULPCONTEXT;
  1712. emlxs_log_temp_event(port, 0x02, iocb->ULPCONTEXT);
  1713. break;
  1714. case 0x0101: /* Temp Safe */
  1715. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg,
  1716. "Adapter temperature now safe (%d °C).",
  1717. iocb->ULPCONTEXT);
  1718. hba->temperature = iocb->ULPCONTEXT;
  1719. emlxs_log_temp_event(port, 0x03, iocb->ULPCONTEXT);
  1720. break;
  1721. default:
  1722. w = (uint32_t *)iocb;
  1723. for (i = 0, j = 0; i < 8; i++, j += 2) {
  1724. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg,
  1725. "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1,
  1726. w[j + 1]);
  1727. }
  1728. emlxs_log_async_event(port, iocb);
  1729. }
  1730. return;
  1731. } /* emlxs_handle_async_event() */
  1732. /* ARGSUSED */
  1733. extern void
  1734. emlxs_reset_link_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
  1735. {
  1736. emlxs_port_t *port = &PPORT;
  1737. /* Attempt a link reset to recover */
  1738. (void) emlxs_reset(port, FC_FCA_LINK_RESET);
  1739. return;
  1740. } /* emlxs_reset_link_thread() */
  1741. /* ARGSUSED */
  1742. extern void
  1743. emlxs_restart_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
  1744. {
  1745. emlxs_port_t *port = &PPORT;
  1746. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting...");
  1747. /* Attempt a full hardware reset to recover */
  1748. if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) {
  1749. EMLXS_STATE_CHANGE(hba, FC_ERROR);
  1750. emlxs_shutdown_thread(hba, arg1, arg2);
  1751. }
  1752. return;
  1753. } /* emlxs_restart_thread() */
  1754. /* ARGSUSED */
  1755. extern void
  1756. emlxs_shutdown_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
  1757. {
  1758. emlxs_port_t *port = &PPORT;
  1759. mutex_enter(&EMLXS_PORT_LOCK);
  1760. if (hba->flag & FC_SHUTDOWN) {
  1761. mutex_exit(&EMLXS_PORT_LOCK);
  1762. return;
  1763. }
  1764. hba->flag |= FC_SHUTDOWN;
  1765. mutex_exit(&EMLXS_PORT_LOCK);
  1766. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
  1767. "Shutting down...");
  1768. /* Take adapter offline and leave it there */
  1769. (void) emlxs_offline(hba);
  1770. if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
  1771. /*
  1772. * Dump is not defined for SLI4, so just
  1773. * reset the HBA for now.
  1774. */
  1775. EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
  1776. } else {
  1777. if (hba->flag & FC_OVERTEMP_EVENT) {
  1778. emlxs_log_temp_event(port, 0x01,
  1779. hba->temperature);
  1780. } else {
  1781. emlxs_log_dump_event(port, NULL, 0);
  1782. }
  1783. }
  1784. EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required.");
  1785. return;
  1786. } /* emlxs_shutdown_thread() */
  1787. /* ARGSUSED */
  1788. extern void
  1789. emlxs_proc_channel(emlxs_hba_t *hba, CHANNEL *cp, void *arg2)
  1790. {
  1791. IOCBQ *iocbq;
  1792. IOCBQ *rsp_head;
  1793. /*
  1794. * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
  1795. * "emlxs_proc_channel: channel=%d", cp->channelno);
  1796. */
  1797. mutex_enter(&cp->rsp_lock);
  1798. while ((rsp_head = cp->rsp_head) != NULL) {
  1799. cp->rsp_head = NULL;
  1800. cp->rsp_tail = NULL;
  1801. mutex_exit(&cp->rsp_lock);
  1802. while ((iocbq = rsp_head) != NULL) {
  1803. rsp_head = (IOCBQ *) iocbq->next;
  1804. emlxs_proc_channel_event(hba, cp, iocbq);
  1805. }
  1806. mutex_enter(&cp->rsp_lock);
  1807. }
  1808. mutex_exit(&cp->rsp_lock);
  1809. EMLXS_SLI_ISSUE_I

Large files files are truncated, but you can click here to view the full file