Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_xioctl.c
+++ new/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_xioctl.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 usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
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.
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 /* Copyright 2010 QLogic Corporation */
23 23
24 24 /*
25 25 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26 26 */
27 27
28 28 /*
29 29 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
30 30 */
31 31
32 32 #pragma ident "Copyright 2010 QLogic Corporation; ql_xioctl.c"
33 33
34 34 /*
35 35 * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
36 36 *
37 37 * ***********************************************************************
38 38 * * **
39 39 * * NOTICE **
40 40 * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION **
41 41 * * ALL RIGHTS RESERVED **
42 42 * * **
43 43 * ***********************************************************************
44 44 *
45 45 */
46 46
47 47 #include <ql_apps.h>
48 48 #include <ql_api.h>
49 49 #include <ql_debug.h>
50 50 #include <ql_init.h>
51 51 #include <ql_iocb.h>
52 52 #include <ql_ioctl.h>
53 53 #include <ql_mbx.h>
54 54 #include <ql_xioctl.h>
55 55
56 56 /*
57 57 * Local data
58 58 */
59 59
60 60 /*
61 61 * Local prototypes
62 62 */
63 63 static int ql_sdm_ioctl(ql_adapter_state_t *, int, void *, int);
64 64 static int ql_sdm_setup(ql_adapter_state_t *, EXT_IOCTL **, void *, int,
65 65 boolean_t (*)(EXT_IOCTL *));
66 66 static boolean_t ql_validate_signature(EXT_IOCTL *);
67 67 static int ql_sdm_return(ql_adapter_state_t *, EXT_IOCTL *, void *, int);
68 68 static void ql_query(ql_adapter_state_t *, EXT_IOCTL *, int);
69 69 static void ql_qry_hba_node(ql_adapter_state_t *, EXT_IOCTL *, int);
70 70 static void ql_qry_hba_port(ql_adapter_state_t *, EXT_IOCTL *, int);
71 71 static void ql_qry_disc_port(ql_adapter_state_t *, EXT_IOCTL *, int);
72 72 static void ql_qry_disc_tgt(ql_adapter_state_t *, EXT_IOCTL *, int);
73 73 static void ql_qry_fw(ql_adapter_state_t *, EXT_IOCTL *, int);
74 74 static void ql_qry_chip(ql_adapter_state_t *, EXT_IOCTL *, int);
75 75 static void ql_qry_driver(ql_adapter_state_t *, EXT_IOCTL *, int);
76 76 static void ql_fcct(ql_adapter_state_t *, EXT_IOCTL *, int);
77 77 static void ql_aen_reg(ql_adapter_state_t *, EXT_IOCTL *, int);
78 78 static void ql_aen_get(ql_adapter_state_t *, EXT_IOCTL *, int);
79 79 static void ql_scsi_passthru(ql_adapter_state_t *, EXT_IOCTL *, int);
80 80 static void ql_wwpn_to_scsiaddr(ql_adapter_state_t *, EXT_IOCTL *, int);
81 81 static void ql_host_idx(ql_adapter_state_t *, EXT_IOCTL *, int);
82 82 static void ql_host_drvname(ql_adapter_state_t *, EXT_IOCTL *, int);
83 83 static void ql_read_nvram(ql_adapter_state_t *, EXT_IOCTL *, int);
84 84 static void ql_write_nvram(ql_adapter_state_t *, EXT_IOCTL *, int);
85 85 static void ql_read_flash(ql_adapter_state_t *, EXT_IOCTL *, int);
86 86 static void ql_write_flash(ql_adapter_state_t *, EXT_IOCTL *, int);
87 87 static void ql_write_vpd(ql_adapter_state_t *, EXT_IOCTL *, int);
88 88 static void ql_read_vpd(ql_adapter_state_t *, EXT_IOCTL *, int);
89 89 static void ql_diagnostic_loopback(ql_adapter_state_t *, EXT_IOCTL *, int);
90 90 static void ql_send_els_rnid(ql_adapter_state_t *, EXT_IOCTL *, int);
91 91 static void ql_set_host_data(ql_adapter_state_t *, EXT_IOCTL *, int);
92 92 static void ql_get_host_data(ql_adapter_state_t *, EXT_IOCTL *, int);
93 93 static void ql_qry_cna_port(ql_adapter_state_t *, EXT_IOCTL *, int);
94 94
95 95 static int ql_lun_count(ql_adapter_state_t *, ql_tgt_t *);
96 96 static int ql_report_lun(ql_adapter_state_t *, ql_tgt_t *);
97 97 static int ql_inq_scan(ql_adapter_state_t *, ql_tgt_t *, int);
98 98 static int ql_inq(ql_adapter_state_t *, ql_tgt_t *, int, ql_mbx_iocb_t *,
99 99 uint8_t);
100 100 static uint32_t ql_get_buffer_data(caddr_t, caddr_t, uint32_t, int);
101 101 static uint32_t ql_send_buffer_data(caddr_t, caddr_t, uint32_t, int);
102 102 static int ql_24xx_flash_desc(ql_adapter_state_t *);
103 103 static int ql_setup_flash(ql_adapter_state_t *);
104 104 static ql_tgt_t *ql_find_port(ql_adapter_state_t *, uint8_t *, uint16_t);
105 105 static int ql_flash_fcode_load(ql_adapter_state_t *, void *, uint32_t, int);
106 106 static int ql_flash_fcode_dump(ql_adapter_state_t *, void *, uint32_t,
107 107 uint32_t, int);
108 108 static int ql_program_flash_address(ql_adapter_state_t *, uint32_t,
109 109 uint8_t);
110 110 static void ql_set_rnid_parameters(ql_adapter_state_t *, EXT_IOCTL *, int);
111 111 static void ql_get_rnid_parameters(ql_adapter_state_t *, EXT_IOCTL *, int);
112 112 static int ql_reset_statistics(ql_adapter_state_t *, EXT_IOCTL *);
113 113 static void ql_get_statistics(ql_adapter_state_t *, EXT_IOCTL *, int);
114 114 static void ql_get_statistics_fc(ql_adapter_state_t *, EXT_IOCTL *, int);
115 115 static void ql_get_statistics_fc4(ql_adapter_state_t *, EXT_IOCTL *, int);
116 116 static void ql_set_led_state(ql_adapter_state_t *, EXT_IOCTL *, int);
117 117 static void ql_get_led_state(ql_adapter_state_t *, EXT_IOCTL *, int);
118 118 static void ql_drive_led(ql_adapter_state_t *, uint32_t);
119 119 static uint32_t ql_setup_led(ql_adapter_state_t *);
120 120 static uint32_t ql_wrapup_led(ql_adapter_state_t *);
121 121 static void ql_get_port_summary(ql_adapter_state_t *, EXT_IOCTL *, int);
122 122 static void ql_get_target_id(ql_adapter_state_t *, EXT_IOCTL *, int);
123 123 static void ql_get_sfp(ql_adapter_state_t *, EXT_IOCTL *, int);
124 124 static int ql_dump_sfp(ql_adapter_state_t *, void *, int);
125 125 static ql_fcache_t *ql_setup_fnode(ql_adapter_state_t *);
126 126 static void ql_get_fcache(ql_adapter_state_t *, EXT_IOCTL *, int);
127 127 static void ql_get_fcache_ex(ql_adapter_state_t *, EXT_IOCTL *, int);
128 128 void ql_update_fcache(ql_adapter_state_t *, uint8_t *, uint32_t);
129 129 static int ql_check_pci(ql_adapter_state_t *, ql_fcache_t *, uint32_t *);
130 130 static void ql_flash_layout_table(ql_adapter_state_t *, uint32_t);
131 131 static void ql_process_flt(ql_adapter_state_t *, uint32_t);
132 132 static void ql_flash_nvram_defaults(ql_adapter_state_t *);
133 133 static void ql_port_param(ql_adapter_state_t *, EXT_IOCTL *, int);
134 134 static int ql_check_pci(ql_adapter_state_t *, ql_fcache_t *, uint32_t *);
135 135 static void ql_get_pci_data(ql_adapter_state_t *, EXT_IOCTL *, int);
136 136 static void ql_get_fwfcetrace(ql_adapter_state_t *, EXT_IOCTL *, int);
137 137 static void ql_get_fwexttrace(ql_adapter_state_t *, EXT_IOCTL *, int);
138 138 static void ql_menlo_reset(ql_adapter_state_t *, EXT_IOCTL *, int);
139 139 static void ql_menlo_get_fw_version(ql_adapter_state_t *, EXT_IOCTL *, int);
140 140 static void ql_menlo_update_fw(ql_adapter_state_t *, EXT_IOCTL *, int);
141 141 static void ql_menlo_manage_info(ql_adapter_state_t *, EXT_IOCTL *, int);
142 142 static int ql_suspend_hba(ql_adapter_state_t *, uint32_t);
143 143 static void ql_restart_hba(ql_adapter_state_t *);
144 144 static void ql_get_vp_cnt_id(ql_adapter_state_t *, EXT_IOCTL *, int);
145 145 static void ql_vp_ioctl(ql_adapter_state_t *, EXT_IOCTL *, int);
146 146 static void ql_qry_vport(ql_adapter_state_t *, EXT_IOCTL *, int);
147 147 static void ql_access_flash(ql_adapter_state_t *, EXT_IOCTL *, int);
148 148 static void ql_reset_cmd(ql_adapter_state_t *, EXT_IOCTL *);
149 149 static void ql_update_flash_caches(ql_adapter_state_t *);
150 150 static void ql_get_dcbx_parameters(ql_adapter_state_t *, EXT_IOCTL *, int);
151 151 static void ql_get_xgmac_statistics(ql_adapter_state_t *, EXT_IOCTL *, int);
152 152 static void ql_get_fcf_list(ql_adapter_state_t *, EXT_IOCTL *, int);
153 153 static void ql_get_resource_counts(ql_adapter_state_t *, EXT_IOCTL *, int);
154 154 static void ql_qry_adapter_versions(ql_adapter_state_t *, EXT_IOCTL *, int);
155 155 static int ql_set_loop_point(ql_adapter_state_t *, uint16_t);
156 156
157 157 /* ******************************************************************** */
158 158 /* External IOCTL support. */
159 159 /* ******************************************************************** */
160 160
161 161 /*
162 162 * ql_alloc_xioctl_resource
163 163 * Allocates resources needed by module code.
164 164 *
165 165 * Input:
166 166 * ha: adapter state pointer.
167 167 *
168 168 * Returns:
169 169 * SYS_ERRNO
170 170 *
171 171 * Context:
172 172 * Kernel context.
173 173 */
174 174 int
175 175 ql_alloc_xioctl_resource(ql_adapter_state_t *ha)
176 176 {
177 177 ql_xioctl_t *xp;
178 178
179 179 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
180 180
181 181 if (ha->xioctl != NULL) {
182 182 QL_PRINT_9(CE_CONT, "(%d): already allocated done\n",
183 183 ha->instance);
184 184 return (0);
185 185 }
186 186
187 187 xp = kmem_zalloc(sizeof (ql_xioctl_t), KM_SLEEP);
188 188 if (xp == NULL) {
189 189 EL(ha, "failed, kmem_zalloc\n");
190 190 return (ENOMEM);
191 191 }
192 192 ha->xioctl = xp;
193 193
194 194 /* Allocate AEN tracking buffer */
195 195 xp->aen_tracking_queue = kmem_zalloc(EXT_DEF_MAX_AEN_QUEUE *
196 196 sizeof (EXT_ASYNC_EVENT), KM_SLEEP);
197 197 if (xp->aen_tracking_queue == NULL) {
198 198 EL(ha, "failed, kmem_zalloc-2\n");
199 199 ql_free_xioctl_resource(ha);
200 200 return (ENOMEM);
201 201 }
202 202
203 203 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
204 204
205 205 return (0);
206 206 }
207 207
208 208 /*
209 209 * ql_free_xioctl_resource
210 210 * Frees resources used by module code.
211 211 *
212 212 * Input:
213 213 * ha: adapter state pointer.
214 214 *
215 215 * Context:
216 216 * Kernel context.
217 217 */
218 218 void
219 219 ql_free_xioctl_resource(ql_adapter_state_t *ha)
220 220 {
221 221 ql_xioctl_t *xp = ha->xioctl;
222 222
223 223 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
224 224
225 225 if (xp == NULL) {
226 226 QL_PRINT_9(CE_CONT, "(%d): already freed\n", ha->instance);
227 227 return;
228 228 }
229 229
230 230 if (xp->aen_tracking_queue != NULL) {
231 231 kmem_free(xp->aen_tracking_queue, EXT_DEF_MAX_AEN_QUEUE *
232 232 sizeof (EXT_ASYNC_EVENT));
233 233 xp->aen_tracking_queue = NULL;
234 234 }
235 235
236 236 kmem_free(xp, sizeof (ql_xioctl_t));
237 237 ha->xioctl = NULL;
238 238
239 239 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
240 240 }
241 241
242 242 /*
243 243 * ql_xioctl
244 244 * External IOCTL processing.
245 245 *
246 246 * Input:
247 247 * ha: adapter state pointer.
248 248 * cmd: function to perform
249 249 * arg: data type varies with request
250 250 * mode: flags
251 251 * cred_p: credentials pointer
252 252 * rval_p: pointer to result value
253 253 *
254 254 * Returns:
255 255 * 0: success
256 256 * ENXIO: No such device or address
257 257 * ENOPROTOOPT: Protocol not available
258 258 *
259 259 * Context:
260 260 * Kernel context.
261 261 */
262 262 /* ARGSUSED */
263 263 int
264 264 ql_xioctl(ql_adapter_state_t *ha, int cmd, intptr_t arg, int mode,
265 265 cred_t *cred_p, int *rval_p)
266 266 {
267 267 int rval;
268 268
269 269 QL_PRINT_9(CE_CONT, "(%d): started, cmd=%d\n", ha->instance, cmd);
270 270
271 271 if (ha->xioctl == NULL) {
272 272 QL_PRINT_9(CE_CONT, "(%d): no context\n", ha->instance);
273 273 return (ENXIO);
274 274 }
275 275
276 276 switch (cmd) {
277 277 case EXT_CC_QUERY:
278 278 case EXT_CC_SEND_FCCT_PASSTHRU:
279 279 case EXT_CC_REG_AEN:
280 280 case EXT_CC_GET_AEN:
281 281 case EXT_CC_SEND_SCSI_PASSTHRU:
282 282 case EXT_CC_WWPN_TO_SCSIADDR:
283 283 case EXT_CC_SEND_ELS_RNID:
284 284 case EXT_CC_SET_DATA:
285 285 case EXT_CC_GET_DATA:
286 286 case EXT_CC_HOST_IDX:
287 287 case EXT_CC_READ_NVRAM:
288 288 case EXT_CC_UPDATE_NVRAM:
289 289 case EXT_CC_READ_OPTION_ROM:
290 290 case EXT_CC_READ_OPTION_ROM_EX:
291 291 case EXT_CC_UPDATE_OPTION_ROM:
292 292 case EXT_CC_UPDATE_OPTION_ROM_EX:
293 293 case EXT_CC_GET_VPD:
294 294 case EXT_CC_SET_VPD:
295 295 case EXT_CC_LOOPBACK:
296 296 case EXT_CC_GET_FCACHE:
297 297 case EXT_CC_GET_FCACHE_EX:
298 298 case EXT_CC_HOST_DRVNAME:
299 299 case EXT_CC_GET_SFP_DATA:
300 300 case EXT_CC_PORT_PARAM:
301 301 case EXT_CC_GET_PCI_DATA:
302 302 case EXT_CC_GET_FWEXTTRACE:
303 303 case EXT_CC_GET_FWFCETRACE:
304 304 case EXT_CC_GET_VP_CNT_ID:
305 305 case EXT_CC_VPORT_CMD:
306 306 case EXT_CC_ACCESS_FLASH:
307 307 case EXT_CC_RESET_FW:
308 308 case EXT_CC_MENLO_MANAGE_INFO:
309 309 rval = ql_sdm_ioctl(ha, cmd, (void *)arg, mode);
310 310 break;
311 311 default:
312 312 /* function not supported. */
313 313 EL(ha, "function=%d not supported\n", cmd);
314 314 rval = ENOPROTOOPT;
315 315 }
316 316
317 317 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
318 318
319 319 return (rval);
320 320 }
321 321
322 322 /*
323 323 * ql_sdm_ioctl
324 324 * Provides ioctl functions for SAN/Device Management functions
325 325 * AKA External Ioctl functions.
326 326 *
327 327 * Input:
328 328 * ha: adapter state pointer.
329 329 * ioctl_code: ioctl function to perform
330 330 * arg: Pointer to EXT_IOCTL cmd data in application land.
331 331 * mode: flags
332 332 *
333 333 * Returns:
334 334 * 0: success
335 335 * ENOMEM: Alloc of local EXT_IOCTL struct failed.
336 336 * EFAULT: Copyin of caller's EXT_IOCTL struct failed or
337 337 * copyout of EXT_IOCTL status info failed.
338 338 * EINVAL: Signature or version of caller's EXT_IOCTL invalid.
339 339 * EBUSY: Device busy
340 340 *
341 341 * Context:
342 342 * Kernel context.
343 343 */
344 344 static int
345 345 ql_sdm_ioctl(ql_adapter_state_t *ha, int ioctl_code, void *arg, int mode)
346 346 {
347 347 EXT_IOCTL *cmd;
348 348 int rval;
349 349 ql_adapter_state_t *vha;
350 350
351 351 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
352 352
353 353 /* Copy argument structure (EXT_IOCTL) from application land. */
354 354 if ((rval = ql_sdm_setup(ha, &cmd, arg, mode,
355 355 ql_validate_signature)) != 0) {
356 356 /*
357 357 * a non-zero value at this time means a problem getting
358 358 * the requested information from application land, just
359 359 * return the error code and hope for the best.
360 360 */
361 361 EL(ha, "failed, sdm_setup\n");
362 362 return (rval);
363 363 }
364 364
365 365 /*
366 366 * Map the physical ha ptr (which the ioctl is called with)
367 367 * to the virtual ha that the caller is addressing.
368 368 */
369 369 if (ha->flags & VP_ENABLED) {
370 370 /* Check that it is within range. */
371 371 if (cmd->HbaSelect > (CFG_IST(ha, CFG_CTRL_2422) ?
372 372 MAX_24_VIRTUAL_PORTS : MAX_25_VIRTUAL_PORTS)) {
373 373 EL(ha, "Invalid HbaSelect vp index: %xh\n",
374 374 cmd->HbaSelect);
375 375 cmd->Status = EXT_STATUS_INVALID_VPINDEX;
376 376 cmd->ResponseLen = 0;
377 377 return (EFAULT);
378 378 }
379 379 /*
380 380 * Special case: HbaSelect == 0 is physical ha
381 381 */
382 382 if (cmd->HbaSelect != 0) {
383 383 vha = ha->vp_next;
384 384 while (vha != NULL) {
385 385 if (vha->vp_index == cmd->HbaSelect) {
386 386 ha = vha;
387 387 break;
388 388 }
389 389 vha = vha->vp_next;
390 390 }
391 391 /*
392 392 * The specified vp index may be valid(within range)
393 393 * but it's not in the list. Currently this is all
394 394 * we can say.
395 395 */
396 396 if (vha == NULL) {
397 397 cmd->Status = EXT_STATUS_INVALID_VPINDEX;
398 398 cmd->ResponseLen = 0;
399 399 return (EFAULT);
400 400 }
401 401 }
402 402 }
403 403
404 404 /*
405 405 * If driver is suspended, stalled, or powered down rtn BUSY
406 406 */
407 407 if (ha->flags & ADAPTER_SUSPENDED ||
408 408 ha->task_daemon_flags & DRIVER_STALL ||
409 409 ha->power_level != PM_LEVEL_D0) {
410 410 EL(ha, " %s\n", ha->flags & ADAPTER_SUSPENDED ?
411 411 "driver suspended" :
412 412 (ha->task_daemon_flags & DRIVER_STALL ? "driver stalled" :
413 413 "FCA powered down"));
414 414 cmd->Status = EXT_STATUS_BUSY;
415 415 cmd->ResponseLen = 0;
416 416 rval = EBUSY;
417 417
418 418 /* Return results to caller */
419 419 if ((ql_sdm_return(ha, cmd, arg, mode)) == -1) {
420 420 EL(ha, "failed, sdm_return\n");
421 421 rval = EFAULT;
422 422 }
423 423 return (rval);
424 424 }
425 425
426 426 switch (ioctl_code) {
427 427 case EXT_CC_QUERY_OS:
428 428 ql_query(ha, cmd, mode);
429 429 break;
430 430 case EXT_CC_SEND_FCCT_PASSTHRU_OS:
431 431 ql_fcct(ha, cmd, mode);
432 432 break;
433 433 case EXT_CC_REG_AEN_OS:
434 434 ql_aen_reg(ha, cmd, mode);
435 435 break;
436 436 case EXT_CC_GET_AEN_OS:
437 437 ql_aen_get(ha, cmd, mode);
438 438 break;
439 439 case EXT_CC_GET_DATA_OS:
440 440 ql_get_host_data(ha, cmd, mode);
441 441 break;
442 442 case EXT_CC_SET_DATA_OS:
443 443 ql_set_host_data(ha, cmd, mode);
444 444 break;
445 445 case EXT_CC_SEND_ELS_RNID_OS:
446 446 ql_send_els_rnid(ha, cmd, mode);
447 447 break;
448 448 case EXT_CC_SCSI_PASSTHRU_OS:
449 449 ql_scsi_passthru(ha, cmd, mode);
450 450 break;
451 451 case EXT_CC_WWPN_TO_SCSIADDR_OS:
452 452 ql_wwpn_to_scsiaddr(ha, cmd, mode);
453 453 break;
454 454 case EXT_CC_HOST_IDX_OS:
455 455 ql_host_idx(ha, cmd, mode);
456 456 break;
457 457 case EXT_CC_HOST_DRVNAME_OS:
458 458 ql_host_drvname(ha, cmd, mode);
459 459 break;
460 460 case EXT_CC_READ_NVRAM_OS:
461 461 ql_read_nvram(ha, cmd, mode);
462 462 break;
463 463 case EXT_CC_UPDATE_NVRAM_OS:
464 464 ql_write_nvram(ha, cmd, mode);
465 465 break;
466 466 case EXT_CC_READ_OPTION_ROM_OS:
467 467 case EXT_CC_READ_OPTION_ROM_EX_OS:
468 468 ql_read_flash(ha, cmd, mode);
469 469 break;
470 470 case EXT_CC_UPDATE_OPTION_ROM_OS:
471 471 case EXT_CC_UPDATE_OPTION_ROM_EX_OS:
472 472 ql_write_flash(ha, cmd, mode);
473 473 break;
474 474 case EXT_CC_LOOPBACK_OS:
475 475 ql_diagnostic_loopback(ha, cmd, mode);
476 476 break;
477 477 case EXT_CC_GET_VPD_OS:
478 478 ql_read_vpd(ha, cmd, mode);
479 479 break;
480 480 case EXT_CC_SET_VPD_OS:
481 481 ql_write_vpd(ha, cmd, mode);
482 482 break;
483 483 case EXT_CC_GET_FCACHE_OS:
484 484 ql_get_fcache(ha, cmd, mode);
485 485 break;
486 486 case EXT_CC_GET_FCACHE_EX_OS:
487 487 ql_get_fcache_ex(ha, cmd, mode);
488 488 break;
489 489 case EXT_CC_GET_SFP_DATA_OS:
490 490 ql_get_sfp(ha, cmd, mode);
491 491 break;
492 492 case EXT_CC_PORT_PARAM_OS:
493 493 ql_port_param(ha, cmd, mode);
494 494 break;
495 495 case EXT_CC_GET_PCI_DATA_OS:
496 496 ql_get_pci_data(ha, cmd, mode);
497 497 break;
498 498 case EXT_CC_GET_FWEXTTRACE_OS:
499 499 ql_get_fwexttrace(ha, cmd, mode);
500 500 break;
501 501 case EXT_CC_GET_FWFCETRACE_OS:
502 502 ql_get_fwfcetrace(ha, cmd, mode);
503 503 break;
504 504 case EXT_CC_MENLO_RESET:
505 505 ql_menlo_reset(ha, cmd, mode);
506 506 break;
507 507 case EXT_CC_MENLO_GET_FW_VERSION:
508 508 ql_menlo_get_fw_version(ha, cmd, mode);
509 509 break;
510 510 case EXT_CC_MENLO_UPDATE_FW:
511 511 ql_menlo_update_fw(ha, cmd, mode);
512 512 break;
513 513 case EXT_CC_MENLO_MANAGE_INFO:
514 514 ql_menlo_manage_info(ha, cmd, mode);
515 515 break;
516 516 case EXT_CC_GET_VP_CNT_ID_OS:
517 517 ql_get_vp_cnt_id(ha, cmd, mode);
518 518 break;
519 519 case EXT_CC_VPORT_CMD_OS:
520 520 ql_vp_ioctl(ha, cmd, mode);
521 521 break;
522 522 case EXT_CC_ACCESS_FLASH_OS:
523 523 ql_access_flash(ha, cmd, mode);
524 524 break;
525 525 case EXT_CC_RESET_FW_OS:
526 526 ql_reset_cmd(ha, cmd);
527 527 break;
528 528 default:
529 529 /* function not supported. */
530 530 EL(ha, "failed, function not supported=%d\n", ioctl_code);
531 531
532 532 cmd->Status = EXT_STATUS_INVALID_REQUEST;
533 533 cmd->ResponseLen = 0;
534 534 break;
535 535 }
536 536
537 537 /* Return results to caller */
538 538 if (ql_sdm_return(ha, cmd, arg, mode) == -1) {
539 539 EL(ha, "failed, sdm_return\n");
540 540 return (EFAULT);
541 541 }
542 542
543 543 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
544 544
545 545 return (0);
546 546 }
547 547
548 548 /*
549 549 * ql_sdm_setup
550 550 * Make a local copy of the EXT_IOCTL struct and validate it.
551 551 *
552 552 * Input:
553 553 * ha: adapter state pointer.
554 554 * cmd_struct: Pointer to location to store local adrs of EXT_IOCTL.
555 555 * arg: Address of application EXT_IOCTL cmd data
556 556 * mode: flags
557 557 * val_sig: Pointer to a function to validate the ioctl signature.
558 558 *
559 559 * Returns:
560 560 * 0: success
561 561 * EFAULT: Copy in error of application EXT_IOCTL struct.
562 562 * EINVAL: Invalid version, signature.
563 563 * ENOMEM: Local allocation of EXT_IOCTL failed.
564 564 *
565 565 * Context:
566 566 * Kernel context.
567 567 */
568 568 static int
569 569 ql_sdm_setup(ql_adapter_state_t *ha, EXT_IOCTL **cmd_struct, void *arg,
570 570 int mode, boolean_t (*val_sig)(EXT_IOCTL *))
571 571 {
572 572 int rval;
573 573 EXT_IOCTL *cmd;
574 574
575 575 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
576 576
577 577 /* Allocate local memory for EXT_IOCTL. */
578 578 *cmd_struct = NULL;
579 579 cmd = (EXT_IOCTL *)kmem_zalloc(sizeof (EXT_IOCTL), KM_SLEEP);
580 580 if (cmd == NULL) {
581 581 EL(ha, "failed, kmem_zalloc\n");
582 582 return (ENOMEM);
583 583 }
584 584 /* Get argument structure. */
585 585 rval = ddi_copyin(arg, (void *)cmd, sizeof (EXT_IOCTL), mode);
586 586 if (rval != 0) {
587 587 EL(ha, "failed, ddi_copyin\n");
588 588 rval = EFAULT;
589 589 } else {
590 590 /*
591 591 * Check signature and the version.
592 592 * If either are not valid then neither is the
593 593 * structure so don't attempt to return any error status
594 594 * because we can't trust what caller's arg points to.
595 595 * Just return the errno.
596 596 */
597 597 if (val_sig(cmd) == 0) {
598 598 EL(ha, "failed, signature\n");
599 599 rval = EINVAL;
600 600 } else if (cmd->Version > EXT_VERSION) {
601 601 EL(ha, "failed, version\n");
602 602 rval = EINVAL;
603 603 }
604 604 }
605 605
606 606 if (rval == 0) {
607 607 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
608 608 *cmd_struct = cmd;
609 609 cmd->Status = EXT_STATUS_OK;
610 610 cmd->DetailStatus = 0;
611 611 } else {
612 612 kmem_free((void *)cmd, sizeof (EXT_IOCTL));
613 613 }
614 614
615 615 return (rval);
616 616 }
617 617
618 618 /*
619 619 * ql_validate_signature
620 620 * Validate the signature string for an external ioctl call.
621 621 *
622 622 * Input:
623 623 * sg: Pointer to EXT_IOCTL signature to validate.
624 624 *
625 625 * Returns:
626 626 * B_TRUE: Signature is valid.
627 627 * B_FALSE: Signature is NOT valid.
628 628 *
629 629 * Context:
630 630 * Kernel context.
631 631 */
632 632 static boolean_t
633 633 ql_validate_signature(EXT_IOCTL *cmd_struct)
634 634 {
635 635 /*
636 636 * Check signature.
637 637 *
638 638 * If signature is not valid then neither is the rest of
639 639 * the structure (e.g., can't trust it), so don't attempt
640 640 * to return any error status other than the errno.
641 641 */
642 642 if (bcmp(&cmd_struct->Signature, "QLOGIC", 6) != 0) {
643 643 QL_PRINT_2(CE_CONT, "failed,\n");
644 644 return (B_FALSE);
645 645 }
646 646
647 647 return (B_TRUE);
648 648 }
649 649
650 650 /*
651 651 * ql_sdm_return
652 652 * Copies return data/status to application land for
653 653 * ioctl call using the SAN/Device Management EXT_IOCTL call interface.
654 654 *
655 655 * Input:
656 656 * ha: adapter state pointer.
657 657 * cmd: Pointer to kernel copy of requestor's EXT_IOCTL struct.
658 658 * ioctl_code: ioctl function to perform
659 659 * arg: EXT_IOCTL cmd data in application land.
660 660 * mode: flags
661 661 *
662 662 * Returns:
663 663 * 0: success
664 664 * EFAULT: Copy out error.
665 665 *
666 666 * Context:
667 667 * Kernel context.
668 668 */
669 669 /* ARGSUSED */
670 670 static int
671 671 ql_sdm_return(ql_adapter_state_t *ha, EXT_IOCTL *cmd, void *arg, int mode)
672 672 {
673 673 int rval = 0;
674 674
675 675 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
676 676
677 677 rval |= ddi_copyout((void *)&cmd->ResponseLen,
678 678 (void *)&(((EXT_IOCTL*)arg)->ResponseLen), sizeof (uint32_t),
679 679 mode);
680 680
681 681 rval |= ddi_copyout((void *)&cmd->Status,
682 682 (void *)&(((EXT_IOCTL*)arg)->Status),
683 683 sizeof (cmd->Status), mode);
684 684 rval |= ddi_copyout((void *)&cmd->DetailStatus,
685 685 (void *)&(((EXT_IOCTL*)arg)->DetailStatus),
686 686 sizeof (cmd->DetailStatus), mode);
687 687
688 688 kmem_free((void *)cmd, sizeof (EXT_IOCTL));
689 689
690 690 if (rval != 0) {
691 691 /* Some copyout operation failed */
692 692 EL(ha, "failed, ddi_copyout\n");
693 693 return (EFAULT);
694 694 }
695 695
696 696 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
697 697
698 698 return (0);
699 699 }
700 700
701 701 /*
702 702 * ql_query
703 703 * Performs all EXT_CC_QUERY functions.
704 704 *
705 705 * Input:
706 706 * ha: adapter state pointer.
707 707 * cmd: Local EXT_IOCTL cmd struct pointer.
708 708 * mode: flags.
709 709 *
710 710 * Returns:
711 711 * None, request status indicated in cmd->Status.
712 712 *
713 713 * Context:
714 714 * Kernel context.
715 715 */
716 716 static void
717 717 ql_query(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
718 718 {
719 719 QL_PRINT_9(CE_CONT, "(%d): started, cmd=%d\n", ha->instance,
720 720 cmd->SubCode);
721 721
722 722 /* case off on command subcode */
723 723 switch (cmd->SubCode) {
724 724 case EXT_SC_QUERY_HBA_NODE:
725 725 ql_qry_hba_node(ha, cmd, mode);
726 726 break;
727 727 case EXT_SC_QUERY_HBA_PORT:
728 728 ql_qry_hba_port(ha, cmd, mode);
729 729 break;
730 730 case EXT_SC_QUERY_DISC_PORT:
731 731 ql_qry_disc_port(ha, cmd, mode);
732 732 break;
733 733 case EXT_SC_QUERY_DISC_TGT:
734 734 ql_qry_disc_tgt(ha, cmd, mode);
735 735 break;
736 736 case EXT_SC_QUERY_DRIVER:
737 737 ql_qry_driver(ha, cmd, mode);
738 738 break;
739 739 case EXT_SC_QUERY_FW:
740 740 ql_qry_fw(ha, cmd, mode);
741 741 break;
742 742 case EXT_SC_QUERY_CHIP:
743 743 ql_qry_chip(ha, cmd, mode);
744 744 break;
745 745 case EXT_SC_QUERY_CNA_PORT:
746 746 ql_qry_cna_port(ha, cmd, mode);
747 747 break;
748 748 case EXT_SC_QUERY_ADAPTER_VERSIONS:
749 749 ql_qry_adapter_versions(ha, cmd, mode);
750 750 break;
751 751 case EXT_SC_QUERY_DISC_LUN:
752 752 default:
753 753 /* function not supported. */
754 754 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE;
755 755 EL(ha, "failed, Unsupported Subcode=%xh\n",
756 756 cmd->SubCode);
757 757 break;
758 758 }
759 759
760 760 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
761 761 }
762 762
763 763 /*
764 764 * ql_qry_hba_node
765 765 * Performs EXT_SC_QUERY_HBA_NODE subfunction.
766 766 *
767 767 * Input:
768 768 * ha: adapter state pointer.
769 769 * cmd: EXT_IOCTL cmd struct pointer.
770 770 * mode: flags.
771 771 *
772 772 * Returns:
773 773 * None, request status indicated in cmd->Status.
774 774 *
775 775 * Context:
776 776 * Kernel context.
777 777 */
778 778 static void
779 779 ql_qry_hba_node(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
780 780 {
781 781 EXT_HBA_NODE tmp_node = {0};
782 782 uint_t len;
783 783 caddr_t bufp;
784 784
785 785 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
786 786
787 787 if (cmd->ResponseLen < sizeof (EXT_HBA_NODE)) {
788 788 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
789 789 cmd->DetailStatus = sizeof (EXT_HBA_NODE);
790 790 EL(ha, "failed, ResponseLen < EXT_HBA_NODE, "
791 791 "Len=%xh\n", cmd->ResponseLen);
792 792 cmd->ResponseLen = 0;
793 793 return;
794 794 }
795 795
796 796 /* fill in the values */
797 797
798 798 bcopy(ha->loginparams.node_ww_name.raw_wwn, tmp_node.WWNN,
799 799 EXT_DEF_WWN_NAME_SIZE);
800 800
801 801 (void) sprintf((char *)(tmp_node.Manufacturer), "QLogic Corporation");
802 802
803 803 (void) sprintf((char *)(tmp_node.Model), "%x", ha->device_id);
804 804
805 805 bcopy(&tmp_node.WWNN[5], tmp_node.SerialNum, 3);
806 806
807 807 (void) sprintf((char *)(tmp_node.DriverVersion), QL_VERSION);
808 808
809 809 if (CFG_IST(ha, CFG_SBUS_CARD)) {
810 810 size_t verlen;
811 811 uint16_t w;
812 812 char *tmpptr;
813 813
814 814 verlen = strlen((char *)(tmp_node.DriverVersion));
815 815 if (verlen + 5 > EXT_DEF_MAX_STR_SIZE) {
816 816 EL(ha, "failed, No room for fpga version string\n");
817 817 } else {
818 818 w = (uint16_t)ddi_get16(ha->sbus_fpga_dev_handle,
819 819 (uint16_t *)
820 820 (ha->sbus_fpga_iobase + FPGA_REVISION));
821 821
822 822 tmpptr = (char *)&(tmp_node.DriverVersion[verlen+1]);
823 823 if (tmpptr == NULL) {
824 824 EL(ha, "Unable to insert fpga version str\n");
825 825 } else {
826 826 (void) sprintf(tmpptr, "%d.%d",
827 827 ((w & 0xf0) >> 4), (w & 0x0f));
828 828 tmp_node.DriverAttr |= EXT_CC_HBA_NODE_SBUS;
829 829 }
830 830 }
831 831 }
832 832
833 833 (void) sprintf((char *)(tmp_node.FWVersion), "%01d.%02d.%02d",
834 834 ha->fw_major_version, ha->fw_minor_version,
835 835 ha->fw_subminor_version);
836 836
837 837 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
838 838 switch (ha->fw_attributes) {
839 839 case FWATTRIB_EF:
840 840 (void) strcat((char *)(tmp_node.FWVersion), " EF");
841 841 break;
842 842 case FWATTRIB_TP:
843 843 (void) strcat((char *)(tmp_node.FWVersion), " TP");
844 844 break;
845 845 case FWATTRIB_IP:
846 846 (void) strcat((char *)(tmp_node.FWVersion), " IP");
847 847 break;
848 848 case FWATTRIB_IPX:
849 849 (void) strcat((char *)(tmp_node.FWVersion), " IPX");
850 850 break;
851 851 case FWATTRIB_FL:
852 852 (void) strcat((char *)(tmp_node.FWVersion), " FL");
853 853 break;
854 854 case FWATTRIB_FPX:
855 855 (void) strcat((char *)(tmp_node.FWVersion), " FLX");
856 856 break;
857 857 default:
858 858 break;
859 859 }
860 860 }
861 861
862 862 /* FCode version. */
863 863 /*LINTED [Solaris DDI_DEV_T_ANY Lint error]*/
864 864 if (ddi_getlongprop(DDI_DEV_T_ANY, ha->dip, PROP_LEN_AND_VAL_ALLOC |
865 865 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version", (caddr_t)&bufp,
866 866 (int *)&len) == DDI_PROP_SUCCESS) {
867 867 if (len < EXT_DEF_MAX_STR_SIZE) {
868 868 bcopy(bufp, tmp_node.OptRomVersion, len);
869 869 } else {
870 870 bcopy(bufp, tmp_node.OptRomVersion,
871 871 EXT_DEF_MAX_STR_SIZE - 1);
872 872 tmp_node.OptRomVersion[EXT_DEF_MAX_STR_SIZE - 1] =
873 873 '\0';
874 874 }
875 875 kmem_free(bufp, len);
876 876 } else {
877 877 (void) sprintf((char *)tmp_node.OptRomVersion, "0");
878 878 }
879 879 tmp_node.PortCount = 1;
880 880 tmp_node.InterfaceType = EXT_DEF_FC_INTF_TYPE;
881 881
882 882 if (ddi_copyout((void *)&tmp_node,
883 883 (void *)(uintptr_t)(cmd->ResponseAdr),
884 884 sizeof (EXT_HBA_NODE), mode) != 0) {
885 885 cmd->Status = EXT_STATUS_COPY_ERR;
886 886 cmd->ResponseLen = 0;
887 887 EL(ha, "failed, ddi_copyout\n");
888 888 } else {
889 889 cmd->ResponseLen = sizeof (EXT_HBA_NODE);
890 890 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
891 891 }
892 892 }
893 893
894 894 /*
895 895 * ql_qry_hba_port
896 896 * Performs EXT_SC_QUERY_HBA_PORT subfunction.
897 897 *
898 898 * Input:
899 899 * ha: adapter state pointer.
900 900 * cmd: EXT_IOCTL cmd struct pointer.
901 901 * mode: flags.
902 902 *
903 903 * Returns:
904 904 * None, request status indicated in cmd->Status.
905 905 *
906 906 * Context:
907 907 * Kernel context.
908 908 */
909 909 static void
910 910 ql_qry_hba_port(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
911 911 {
912 912 ql_link_t *link;
913 913 ql_tgt_t *tq;
914 914 ql_mbx_data_t mr;
915 915 EXT_HBA_PORT tmp_port = {0};
916 916 int rval;
917 917 uint16_t port_cnt, tgt_cnt, index;
918 918
919 919 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
920 920
921 921 if (cmd->ResponseLen < sizeof (EXT_HBA_PORT)) {
922 922 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
923 923 cmd->DetailStatus = sizeof (EXT_HBA_PORT);
924 924 EL(ha, "failed, ResponseLen < EXT_HBA_NODE, Len=%xh\n",
925 925 cmd->ResponseLen);
926 926 cmd->ResponseLen = 0;
927 927 return;
928 928 }
929 929
930 930 /* fill in the values */
931 931
932 932 bcopy(ha->loginparams.nport_ww_name.raw_wwn, tmp_port.WWPN,
933 933 EXT_DEF_WWN_NAME_SIZE);
934 934 tmp_port.Id[0] = 0;
935 935 tmp_port.Id[1] = ha->d_id.b.domain;
936 936 tmp_port.Id[2] = ha->d_id.b.area;
937 937 tmp_port.Id[3] = ha->d_id.b.al_pa;
938 938
939 939 /* For now we are initiator only driver */
940 940 tmp_port.Type = EXT_DEF_INITIATOR_DEV;
941 941
942 942 if (ha->task_daemon_flags & LOOP_DOWN) {
943 943 tmp_port.State = EXT_DEF_HBA_LOOP_DOWN;
944 944 } else if (DRIVER_SUSPENDED(ha)) {
945 945 tmp_port.State = EXT_DEF_HBA_SUSPENDED;
946 946 } else {
947 947 tmp_port.State = EXT_DEF_HBA_OK;
948 948 }
949 949
950 950 if (ha->flags & POINT_TO_POINT) {
951 951 tmp_port.Mode = EXT_DEF_P2P_MODE;
952 952 } else {
953 953 tmp_port.Mode = EXT_DEF_LOOP_MODE;
954 954 }
955 955 /*
956 956 * fill in the portspeed values.
957 957 *
958 958 * default to not yet negotiated state
959 959 */
960 960 tmp_port.PortSpeed = EXT_PORTSPEED_NOT_NEGOTIATED;
961 961
962 962 if (tmp_port.State == EXT_DEF_HBA_OK) {
963 963 switch (ha->iidma_rate) {
964 964 case IIDMA_RATE_1GB:
965 965 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_1GBIT;
966 966 break;
967 967 case IIDMA_RATE_2GB:
968 968 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_2GBIT;
969 969 break;
970 970 case IIDMA_RATE_4GB:
971 971 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_4GBIT;
972 972 break;
973 973 case IIDMA_RATE_8GB:
974 974 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_8GBIT;
975 975 break;
976 976 case IIDMA_RATE_10GB:
977 977 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_10GBIT;
978 978 break;
979 979 default:
980 980 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_UNKNOWN;
981 981 EL(ha, "failed, data rate=%xh\n", mr.mb[1]);
982 982 break;
983 983 }
984 984 }
985 985
986 986 /* Report all supported port speeds */
987 987 if (CFG_IST(ha, CFG_CTRL_25XX)) {
988 988 tmp_port.PortSupportedSpeed = (EXT_DEF_PORTSPEED_8GBIT |
989 989 EXT_DEF_PORTSPEED_4GBIT | EXT_DEF_PORTSPEED_2GBIT |
990 990 EXT_DEF_PORTSPEED_1GBIT);
991 991 /*
992 992 * Correct supported speeds based on type of
993 993 * sfp that is present
994 994 */
995 995 switch (ha->sfp_stat) {
996 996 case 1:
997 997 /* no sfp detected */
998 998 break;
999 999 case 2:
1000 1000 case 4:
1001 1001 /* 4GB sfp */
1002 1002 tmp_port.PortSupportedSpeed &=
1003 1003 ~EXT_DEF_PORTSPEED_8GBIT;
1004 1004 break;
1005 1005 case 3:
1006 1006 case 5:
1007 1007 /* 8GB sfp */
1008 1008 tmp_port.PortSupportedSpeed &=
1009 1009 ~EXT_DEF_PORTSPEED_1GBIT;
1010 1010 break;
1011 1011 default:
1012 1012 EL(ha, "sfp_stat: %xh\n", ha->sfp_stat);
1013 1013 break;
1014 1014
1015 1015 }
1016 1016 } else if (CFG_IST(ha, CFG_CTRL_8081)) {
1017 1017 tmp_port.PortSupportedSpeed = EXT_DEF_PORTSPEED_10GBIT;
1018 1018 } else if (CFG_IST(ha, CFG_CTRL_2422)) {
1019 1019 tmp_port.PortSupportedSpeed = (EXT_DEF_PORTSPEED_4GBIT |
1020 1020 EXT_DEF_PORTSPEED_2GBIT | EXT_DEF_PORTSPEED_1GBIT);
1021 1021 } else if (CFG_IST(ha, CFG_CTRL_2300)) {
1022 1022 tmp_port.PortSupportedSpeed = (EXT_DEF_PORTSPEED_2GBIT |
1023 1023 EXT_DEF_PORTSPEED_1GBIT);
1024 1024 } else if (CFG_IST(ha, CFG_CTRL_6322)) {
1025 1025 tmp_port.PortSupportedSpeed = EXT_DEF_PORTSPEED_2GBIT;
1026 1026 } else if (CFG_IST(ha, CFG_CTRL_2200)) {
1027 1027 tmp_port.PortSupportedSpeed = EXT_DEF_PORTSPEED_1GBIT;
1028 1028 } else {
1029 1029 tmp_port.PortSupportedSpeed = EXT_DEF_PORTSPEED_UNKNOWN;
1030 1030 EL(ha, "unknown HBA type: %xh\n", ha->device_id);
1031 1031 }
1032 1032 tmp_port.LinkState2 = LSB(ha->sfp_stat);
1033 1033 port_cnt = 0;
1034 1034 tgt_cnt = 0;
1035 1035
1036 1036 for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
1037 1037 for (link = ha->dev[index].first; link != NULL;
1038 1038 link = link->next) {
1039 1039 tq = link->base_address;
1040 1040
1041 1041 if (!VALID_TARGET_ID(ha, tq->loop_id)) {
1042 1042 continue;
1043 1043 }
1044 1044
1045 1045 port_cnt++;
1046 1046 if ((tq->flags & TQF_INITIATOR_DEVICE) == 0) {
1047 1047 tgt_cnt++;
1048 1048 }
1049 1049 }
1050 1050 }
1051 1051
1052 1052 tmp_port.DiscPortCount = port_cnt;
1053 1053 tmp_port.DiscTargetCount = tgt_cnt;
1054 1054
1055 1055 tmp_port.DiscPortNameType = EXT_DEF_USE_NODE_NAME;
1056 1056
1057 1057 rval = ddi_copyout((void *)&tmp_port,
1058 1058 (void *)(uintptr_t)(cmd->ResponseAdr),
1059 1059 sizeof (EXT_HBA_PORT), mode);
1060 1060 if (rval != 0) {
1061 1061 cmd->Status = EXT_STATUS_COPY_ERR;
1062 1062 cmd->ResponseLen = 0;
1063 1063 EL(ha, "failed, ddi_copyout\n");
1064 1064 } else {
1065 1065 cmd->ResponseLen = sizeof (EXT_HBA_PORT);
1066 1066 QL_PRINT_9(CE_CONT, "(%d): done, ports=%d, targets=%d\n",
1067 1067 ha->instance, port_cnt, tgt_cnt);
1068 1068 }
1069 1069 }
1070 1070
1071 1071 /*
1072 1072 * ql_qry_disc_port
1073 1073 * Performs EXT_SC_QUERY_DISC_PORT subfunction.
1074 1074 *
1075 1075 * Input:
1076 1076 * ha: adapter state pointer.
1077 1077 * cmd: EXT_IOCTL cmd struct pointer.
1078 1078 * mode: flags.
1079 1079 *
1080 1080 * cmd->Instance = Port instance in fcport chain.
1081 1081 *
1082 1082 * Returns:
1083 1083 * None, request status indicated in cmd->Status.
1084 1084 *
1085 1085 * Context:
1086 1086 * Kernel context.
1087 1087 */
1088 1088 static void
1089 1089 ql_qry_disc_port(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
1090 1090 {
1091 1091 EXT_DISC_PORT tmp_port = {0};
1092 1092 ql_link_t *link;
1093 1093 ql_tgt_t *tq;
1094 1094 uint16_t index;
1095 1095 uint16_t inst = 0;
1096 1096
1097 1097 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1098 1098
1099 1099 if (cmd->ResponseLen < sizeof (EXT_DISC_PORT)) {
1100 1100 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
1101 1101 cmd->DetailStatus = sizeof (EXT_DISC_PORT);
1102 1102 EL(ha, "failed, ResponseLen < EXT_DISC_PORT, Len=%xh\n",
1103 1103 cmd->ResponseLen);
1104 1104 cmd->ResponseLen = 0;
1105 1105 return;
1106 1106 }
1107 1107
1108 1108 for (link = NULL, index = 0;
1109 1109 index < DEVICE_HEAD_LIST_SIZE && link == NULL; index++) {
1110 1110 for (link = ha->dev[index].first; link != NULL;
1111 1111 link = link->next) {
1112 1112 tq = link->base_address;
1113 1113
1114 1114 if (!VALID_TARGET_ID(ha, tq->loop_id)) {
1115 1115 continue;
1116 1116 }
1117 1117 if (inst != cmd->Instance) {
1118 1118 inst++;
1119 1119 continue;
1120 1120 }
1121 1121
1122 1122 /* fill in the values */
1123 1123 bcopy(tq->node_name, tmp_port.WWNN,
1124 1124 EXT_DEF_WWN_NAME_SIZE);
1125 1125 bcopy(tq->port_name, tmp_port.WWPN,
1126 1126 EXT_DEF_WWN_NAME_SIZE);
1127 1127
1128 1128 break;
1129 1129 }
1130 1130 }
1131 1131
1132 1132 if (link == NULL) {
1133 1133 /* no matching device */
1134 1134 cmd->Status = EXT_STATUS_DEV_NOT_FOUND;
1135 1135 EL(ha, "failed, port not found port=%d\n", cmd->Instance);
1136 1136 cmd->ResponseLen = 0;
1137 1137 return;
1138 1138 }
1139 1139
1140 1140 tmp_port.Id[0] = 0;
1141 1141 tmp_port.Id[1] = tq->d_id.b.domain;
1142 1142 tmp_port.Id[2] = tq->d_id.b.area;
1143 1143 tmp_port.Id[3] = tq->d_id.b.al_pa;
1144 1144
1145 1145 tmp_port.Type = 0;
1146 1146 if (tq->flags & TQF_INITIATOR_DEVICE) {
1147 1147 tmp_port.Type = (uint16_t)(tmp_port.Type |
1148 1148 EXT_DEF_INITIATOR_DEV);
1149 1149 } else if ((tq->flags & TQF_TAPE_DEVICE) == 0) {
1150 1150 (void) ql_inq_scan(ha, tq, 1);
1151 1151 } else if (tq->flags & TQF_TAPE_DEVICE) {
1152 1152 tmp_port.Type = (uint16_t)(tmp_port.Type | EXT_DEF_TAPE_DEV);
1153 1153 }
1154 1154
1155 1155 if (tq->flags & TQF_FABRIC_DEVICE) {
1156 1156 tmp_port.Type = (uint16_t)(tmp_port.Type | EXT_DEF_FABRIC_DEV);
1157 1157 } else {
1158 1158 tmp_port.Type = (uint16_t)(tmp_port.Type | EXT_DEF_TARGET_DEV);
1159 1159 }
1160 1160
1161 1161 tmp_port.Status = 0;
1162 1162 tmp_port.Bus = 0; /* Hard-coded for Solaris */
1163 1163
1164 1164 bcopy(tq->port_name, &tmp_port.TargetId, 8);
1165 1165
1166 1166 if (ddi_copyout((void *)&tmp_port,
1167 1167 (void *)(uintptr_t)(cmd->ResponseAdr),
1168 1168 sizeof (EXT_DISC_PORT), mode) != 0) {
1169 1169 cmd->Status = EXT_STATUS_COPY_ERR;
1170 1170 cmd->ResponseLen = 0;
1171 1171 EL(ha, "failed, ddi_copyout\n");
1172 1172 } else {
1173 1173 cmd->ResponseLen = sizeof (EXT_DISC_PORT);
1174 1174 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1175 1175 }
1176 1176 }
1177 1177
1178 1178 /*
1179 1179 * ql_qry_disc_tgt
1180 1180 * Performs EXT_SC_QUERY_DISC_TGT subfunction.
1181 1181 *
1182 1182 * Input:
1183 1183 * ha: adapter state pointer.
1184 1184 * cmd: EXT_IOCTL cmd struct pointer.
1185 1185 * mode: flags.
1186 1186 *
1187 1187 * cmd->Instance = Port instance in fcport chain.
1188 1188 *
1189 1189 * Returns:
1190 1190 * None, request status indicated in cmd->Status.
1191 1191 *
1192 1192 * Context:
1193 1193 * Kernel context.
1194 1194 */
1195 1195 static void
1196 1196 ql_qry_disc_tgt(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
1197 1197 {
1198 1198 EXT_DISC_TARGET tmp_tgt = {0};
1199 1199 ql_link_t *link;
1200 1200 ql_tgt_t *tq;
1201 1201 uint16_t index;
1202 1202 uint16_t inst = 0;
1203 1203
1204 1204 QL_PRINT_9(CE_CONT, "(%d): started, target=%d\n", ha->instance,
1205 1205 cmd->Instance);
1206 1206
1207 1207 if (cmd->ResponseLen < sizeof (EXT_DISC_TARGET)) {
1208 1208 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
1209 1209 cmd->DetailStatus = sizeof (EXT_DISC_TARGET);
1210 1210 EL(ha, "failed, ResponseLen < EXT_DISC_TARGET, Len=%xh\n",
1211 1211 cmd->ResponseLen);
1212 1212 cmd->ResponseLen = 0;
1213 1213 return;
1214 1214 }
1215 1215
1216 1216 /* Scan port list for requested target and fill in the values */
1217 1217 for (link = NULL, index = 0;
1218 1218 index < DEVICE_HEAD_LIST_SIZE && link == NULL; index++) {
1219 1219 for (link = ha->dev[index].first; link != NULL;
1220 1220 link = link->next) {
1221 1221 tq = link->base_address;
1222 1222
1223 1223 if (!VALID_TARGET_ID(ha, tq->loop_id) ||
1224 1224 tq->flags & TQF_INITIATOR_DEVICE) {
1225 1225 continue;
1226 1226 }
1227 1227 if (inst != cmd->Instance) {
1228 1228 inst++;
1229 1229 continue;
1230 1230 }
1231 1231
1232 1232 /* fill in the values */
1233 1233 bcopy(tq->node_name, tmp_tgt.WWNN,
1234 1234 EXT_DEF_WWN_NAME_SIZE);
1235 1235 bcopy(tq->port_name, tmp_tgt.WWPN,
1236 1236 EXT_DEF_WWN_NAME_SIZE);
1237 1237
1238 1238 break;
1239 1239 }
1240 1240 }
1241 1241
1242 1242 if (link == NULL) {
1243 1243 /* no matching device */
1244 1244 cmd->Status = EXT_STATUS_DEV_NOT_FOUND;
1245 1245 cmd->DetailStatus = EXT_DSTATUS_TARGET;
1246 1246 EL(ha, "failed, not found target=%d\n", cmd->Instance);
1247 1247 cmd->ResponseLen = 0;
1248 1248 return;
1249 1249 }
1250 1250 tmp_tgt.Id[0] = 0;
1251 1251 tmp_tgt.Id[1] = tq->d_id.b.domain;
1252 1252 tmp_tgt.Id[2] = tq->d_id.b.area;
1253 1253 tmp_tgt.Id[3] = tq->d_id.b.al_pa;
1254 1254
1255 1255 tmp_tgt.LunCount = (uint16_t)ql_lun_count(ha, tq);
1256 1256
1257 1257 if ((tq->flags & TQF_TAPE_DEVICE) == 0) {
1258 1258 (void) ql_inq_scan(ha, tq, 1);
1259 1259 }
1260 1260
1261 1261 tmp_tgt.Type = 0;
1262 1262 if (tq->flags & TQF_TAPE_DEVICE) {
1263 1263 tmp_tgt.Type = (uint16_t)(tmp_tgt.Type | EXT_DEF_TAPE_DEV);
1264 1264 }
1265 1265
1266 1266 if (tq->flags & TQF_FABRIC_DEVICE) {
1267 1267 tmp_tgt.Type = (uint16_t)(tmp_tgt.Type | EXT_DEF_FABRIC_DEV);
1268 1268 } else {
1269 1269 tmp_tgt.Type = (uint16_t)(tmp_tgt.Type | EXT_DEF_TARGET_DEV);
1270 1270 }
1271 1271
1272 1272 tmp_tgt.Status = 0;
1273 1273
1274 1274 tmp_tgt.Bus = 0; /* Hard-coded for Solaris. */
1275 1275
1276 1276 bcopy(tq->port_name, &tmp_tgt.TargetId, 8);
1277 1277
1278 1278 if (ddi_copyout((void *)&tmp_tgt,
1279 1279 (void *)(uintptr_t)(cmd->ResponseAdr),
1280 1280 sizeof (EXT_DISC_TARGET), mode) != 0) {
1281 1281 cmd->Status = EXT_STATUS_COPY_ERR;
1282 1282 cmd->ResponseLen = 0;
1283 1283 EL(ha, "failed, ddi_copyout\n");
1284 1284 } else {
1285 1285 cmd->ResponseLen = sizeof (EXT_DISC_TARGET);
1286 1286 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1287 1287 }
1288 1288 }
1289 1289
1290 1290 /*
1291 1291 * ql_qry_fw
1292 1292 * Performs EXT_SC_QUERY_FW subfunction.
1293 1293 *
1294 1294 * Input:
1295 1295 * ha: adapter state pointer.
1296 1296 * cmd: EXT_IOCTL cmd struct pointer.
1297 1297 * mode: flags.
1298 1298 *
1299 1299 * Returns:
1300 1300 * None, request status indicated in cmd->Status.
1301 1301 *
1302 1302 * Context:
1303 1303 * Kernel context.
1304 1304 */
1305 1305 static void
1306 1306 ql_qry_fw(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
1307 1307 {
1308 1308 EXT_FW fw_info = {0};
1309 1309
1310 1310 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1311 1311
1312 1312 if (cmd->ResponseLen < sizeof (EXT_FW)) {
1313 1313 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
1314 1314 cmd->DetailStatus = sizeof (EXT_FW);
1315 1315 EL(ha, "failed, ResponseLen < EXT_FW, Len=%xh\n",
1316 1316 cmd->ResponseLen);
1317 1317 cmd->ResponseLen = 0;
1318 1318 return;
1319 1319 }
1320 1320
1321 1321 (void) sprintf((char *)(fw_info.Version), "%d.%02d.%02d",
1322 1322 ha->fw_major_version, ha->fw_minor_version,
1323 1323 ha->fw_subminor_version);
1324 1324
1325 1325 fw_info.Attrib = ha->fw_attributes;
1326 1326
1327 1327 if (ddi_copyout((void *)&fw_info,
1328 1328 (void *)(uintptr_t)(cmd->ResponseAdr),
1329 1329 sizeof (EXT_FW), mode) != 0) {
1330 1330 cmd->Status = EXT_STATUS_COPY_ERR;
1331 1331 cmd->ResponseLen = 0;
1332 1332 EL(ha, "failed, ddi_copyout\n");
1333 1333 return;
1334 1334 } else {
1335 1335 cmd->ResponseLen = sizeof (EXT_FW);
1336 1336 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1337 1337 }
1338 1338 }
1339 1339
1340 1340 /*
1341 1341 * ql_qry_chip
1342 1342 * Performs EXT_SC_QUERY_CHIP subfunction.
1343 1343 *
1344 1344 * Input:
1345 1345 * ha: adapter state pointer.
1346 1346 * cmd: EXT_IOCTL cmd struct pointer.
1347 1347 * mode: flags.
1348 1348 *
1349 1349 * Returns:
1350 1350 * None, request status indicated in cmd->Status.
1351 1351 *
1352 1352 * Context:
1353 1353 * Kernel context.
1354 1354 */
1355 1355 static void
1356 1356 ql_qry_chip(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
1357 1357 {
1358 1358 EXT_CHIP chip = {0};
1359 1359
1360 1360 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1361 1361
1362 1362 if (cmd->ResponseLen < sizeof (EXT_CHIP)) {
1363 1363 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
1364 1364 cmd->DetailStatus = sizeof (EXT_CHIP);
1365 1365 EL(ha, "failed, ResponseLen < EXT_CHIP, Len=%xh\n",
1366 1366 cmd->ResponseLen);
1367 1367 cmd->ResponseLen = 0;
1368 1368 return;
1369 1369 }
1370 1370
1371 1371 chip.VendorId = ha->ven_id;
1372 1372 chip.DeviceId = ha->device_id;
1373 1373 chip.SubVendorId = ha->subven_id;
1374 1374 chip.SubSystemId = ha->subsys_id;
1375 1375 chip.IoAddr = ql_pci_config_get32(ha, PCI_CONF_BASE0);
1376 1376 chip.IoAddrLen = 0x100;
1377 1377 chip.MemAddr = ql_pci_config_get32(ha, PCI_CONF_BASE1);
1378 1378 chip.MemAddrLen = 0x100;
1379 1379 chip.ChipRevID = ha->rev_id;
1380 1380 if (ha->flags & FUNCTION_1) {
1381 1381 chip.FuncNo = 1;
1382 1382 }
1383 1383
1384 1384 if (ddi_copyout((void *)&chip,
1385 1385 (void *)(uintptr_t)(cmd->ResponseAdr),
1386 1386 sizeof (EXT_CHIP), mode) != 0) {
1387 1387 cmd->Status = EXT_STATUS_COPY_ERR;
1388 1388 cmd->ResponseLen = 0;
1389 1389 EL(ha, "failed, ddi_copyout\n");
1390 1390 } else {
1391 1391 cmd->ResponseLen = sizeof (EXT_CHIP);
1392 1392 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1393 1393 }
1394 1394 }
1395 1395
1396 1396 /*
1397 1397 * ql_qry_driver
1398 1398 * Performs EXT_SC_QUERY_DRIVER subfunction.
1399 1399 *
1400 1400 * Input:
1401 1401 * ha: adapter state pointer.
1402 1402 * cmd: EXT_IOCTL cmd struct pointer.
1403 1403 * mode: flags.
1404 1404 *
1405 1405 * Returns:
1406 1406 * None, request status indicated in cmd->Status.
1407 1407 *
1408 1408 * Context:
1409 1409 * Kernel context.
1410 1410 */
1411 1411 static void
1412 1412 ql_qry_driver(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
1413 1413 {
1414 1414 EXT_DRIVER qd = {0};
1415 1415
1416 1416 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1417 1417
1418 1418 if (cmd->ResponseLen < sizeof (EXT_DRIVER)) {
1419 1419 cmd->Status = EXT_STATUS_DATA_OVERRUN;
1420 1420 cmd->DetailStatus = sizeof (EXT_DRIVER);
1421 1421 EL(ha, "failed, ResponseLen < EXT_DRIVER, Len=%xh\n",
1422 1422 cmd->ResponseLen);
1423 1423 cmd->ResponseLen = 0;
1424 1424 return;
1425 1425 }
1426 1426
1427 1427 (void) strcpy((void *)&qd.Version[0], QL_VERSION);
1428 1428 qd.NumOfBus = 1; /* Fixed for Solaris */
1429 1429 qd.TargetsPerBus = (uint16_t)
1430 1430 (CFG_IST(ha, (CFG_CTRL_24258081 | CFG_EXT_FW_INTERFACE)) ?
1431 1431 MAX_24_FIBRE_DEVICES : MAX_22_FIBRE_DEVICES);
1432 1432 qd.LunsPerTarget = 2030;
1433 1433 qd.MaxTransferLen = QL_DMA_MAX_XFER_SIZE;
1434 1434 qd.MaxDataSegments = QL_DMA_SG_LIST_LENGTH;
1435 1435
1436 1436 if (ddi_copyout((void *)&qd, (void *)(uintptr_t)cmd->ResponseAdr,
1437 1437 sizeof (EXT_DRIVER), mode) != 0) {
1438 1438 cmd->Status = EXT_STATUS_COPY_ERR;
1439 1439 cmd->ResponseLen = 0;
1440 1440 EL(ha, "failed, ddi_copyout\n");
1441 1441 } else {
1442 1442 cmd->ResponseLen = sizeof (EXT_DRIVER);
1443 1443 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1444 1444 }
1445 1445 }
1446 1446
1447 1447 /*
1448 1448 * ql_fcct
1449 1449 * IOCTL management server FC-CT passthrough.
1450 1450 *
1451 1451 * Input:
1452 1452 * ha: adapter state pointer.
1453 1453 * cmd: User space CT arguments pointer.
1454 1454 * mode: flags.
1455 1455 *
1456 1456 * Returns:
1457 1457 * None, request status indicated in cmd->Status.
1458 1458 *
1459 1459 * Context:
1460 1460 * Kernel context.
1461 1461 */
1462 1462 static void
1463 1463 ql_fcct(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
1464 1464 {
1465 1465 ql_mbx_iocb_t *pkt;
1466 1466 ql_mbx_data_t mr;
1467 1467 dma_mem_t *dma_mem;
1468 1468 caddr_t pld;
1469 1469 uint32_t pkt_size, pld_byte_cnt, *long_ptr;
1470 1470 int rval;
1471 1471 ql_ct_iu_preamble_t *ct;
1472 1472 ql_xioctl_t *xp = ha->xioctl;
1473 1473 ql_tgt_t tq;
1474 1474 uint16_t comp_status, loop_id;
1475 1475
1476 1476 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1477 1477
1478 1478 /* Get CT argument structure. */
1479 1479 if ((ha->topology & QL_SNS_CONNECTION) == 0) {
1480 1480 EL(ha, "failed, No switch\n");
1481 1481 cmd->Status = EXT_STATUS_DEV_NOT_FOUND;
1482 1482 cmd->ResponseLen = 0;
1483 1483 return;
1484 1484 }
1485 1485
1486 1486 if (DRIVER_SUSPENDED(ha)) {
1487 1487 EL(ha, "failed, LOOP_NOT_READY\n");
1488 1488 cmd->Status = EXT_STATUS_BUSY;
1489 1489 cmd->ResponseLen = 0;
1490 1490 return;
1491 1491 }
1492 1492
1493 1493 /* Login management server device. */
1494 1494 if ((xp->flags & QL_MGMT_SERVER_LOGIN) == 0) {
1495 1495 tq.d_id.b.al_pa = 0xfa;
1496 1496 tq.d_id.b.area = 0xff;
1497 1497 tq.d_id.b.domain = 0xff;
1498 1498 tq.loop_id = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
1499 1499 MANAGEMENT_SERVER_24XX_LOOP_ID :
1500 1500 MANAGEMENT_SERVER_LOOP_ID);
1501 1501 rval = ql_login_fport(ha, &tq, tq.loop_id, LFF_NO_PRLI, &mr);
1502 1502 if (rval != QL_SUCCESS) {
1503 1503 EL(ha, "failed, server login\n");
1504 1504 cmd->Status = EXT_STATUS_DEV_NOT_FOUND;
1505 1505 cmd->ResponseLen = 0;
1506 1506 return;
1507 1507 } else {
1508 1508 xp->flags |= QL_MGMT_SERVER_LOGIN;
1509 1509 }
1510 1510 }
1511 1511
1512 1512 QL_PRINT_9(CE_CONT, "(%d): cmd\n", ha->instance);
1513 1513 QL_DUMP_9(cmd, 8, sizeof (EXT_IOCTL));
1514 1514
1515 1515 /* Allocate a DMA Memory Descriptor */
1516 1516 dma_mem = (dma_mem_t *)kmem_zalloc(sizeof (dma_mem_t), KM_SLEEP);
1517 1517 if (dma_mem == NULL) {
1518 1518 EL(ha, "failed, kmem_zalloc\n");
1519 1519 cmd->Status = EXT_STATUS_NO_MEMORY;
1520 1520 cmd->ResponseLen = 0;
1521 1521 return;
1522 1522 }
1523 1523 /* Determine maximum buffer size. */
1524 1524 if (cmd->RequestLen < cmd->ResponseLen) {
1525 1525 pld_byte_cnt = cmd->ResponseLen;
1526 1526 } else {
1527 1527 pld_byte_cnt = cmd->RequestLen;
1528 1528 }
1529 1529
1530 1530 /* Allocate command block. */
1531 1531 pkt_size = (uint32_t)(sizeof (ql_mbx_iocb_t) + pld_byte_cnt);
1532 1532 pkt = kmem_zalloc(pkt_size, KM_SLEEP);
1533 1533 if (pkt == NULL) {
1534 1534 EL(ha, "failed, kmem_zalloc\n");
1535 1535 cmd->Status = EXT_STATUS_NO_MEMORY;
1536 1536 cmd->ResponseLen = 0;
1537 1537 return;
1538 1538 }
1539 1539 pld = (caddr_t)pkt + sizeof (ql_mbx_iocb_t);
1540 1540
1541 1541 /* Get command payload data. */
1542 1542 if (ql_get_buffer_data((caddr_t)(uintptr_t)cmd->RequestAdr, pld,
1543 1543 cmd->RequestLen, mode) != cmd->RequestLen) {
1544 1544 EL(ha, "failed, get_buffer_data\n");
1545 1545 kmem_free(pkt, pkt_size);
1546 1546 cmd->Status = EXT_STATUS_COPY_ERR;
1547 1547 cmd->ResponseLen = 0;
1548 1548 return;
1549 1549 }
1550 1550
1551 1551 /* Get DMA memory for the IOCB */
1552 1552 if (ql_get_dma_mem(ha, dma_mem, pkt_size, LITTLE_ENDIAN_DMA,
1553 1553 QL_DMA_RING_ALIGN) != QL_SUCCESS) {
1554 1554 cmn_err(CE_WARN, "%s(%d): DMA memory "
1555 1555 "alloc failed", QL_NAME, ha->instance);
1556 1556 kmem_free(pkt, pkt_size);
1557 1557 kmem_free(dma_mem, sizeof (dma_mem_t));
1558 1558 cmd->Status = EXT_STATUS_MS_NO_RESPONSE;
1559 1559 cmd->ResponseLen = 0;
1560 1560 return;
1561 1561 }
1562 1562
1563 1563 /* Copy out going payload data to IOCB DMA buffer. */
1564 1564 ddi_rep_put8(dma_mem->acc_handle, (uint8_t *)pld,
1565 1565 (uint8_t *)dma_mem->bp, pld_byte_cnt, DDI_DEV_AUTOINCR);
1566 1566
1567 1567 /* Sync IOCB DMA buffer. */
1568 1568 (void) ddi_dma_sync(dma_mem->dma_handle, 0, pld_byte_cnt,
1569 1569 DDI_DMA_SYNC_FORDEV);
1570 1570
1571 1571 /*
1572 1572 * Setup IOCB
1573 1573 */
1574 1574 ct = (ql_ct_iu_preamble_t *)pld;
1575 1575 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1576 1576 pkt->ms24.entry_type = CT_PASSTHRU_TYPE;
1577 1577 pkt->ms24.entry_count = 1;
1578 1578
1579 1579 pkt->ms24.vp_index = ha->vp_index;
1580 1580
1581 1581 /* Set loop ID */
1582 1582 pkt->ms24.n_port_hdl = (uint16_t)
1583 1583 (ct->gs_type == GS_TYPE_DIR_SERVER ?
1584 1584 LE_16(SNS_24XX_HDL) :
1585 1585 LE_16(MANAGEMENT_SERVER_24XX_LOOP_ID));
1586 1586
1587 1587 /* Set ISP command timeout. */
1588 1588 pkt->ms24.timeout = LE_16(120);
1589 1589
1590 1590 /* Set cmd/response data segment counts. */
1591 1591 pkt->ms24.cmd_dseg_count = LE_16(1);
1592 1592 pkt->ms24.resp_dseg_count = LE_16(1);
1593 1593
1594 1594 /* Load ct cmd byte count. */
1595 1595 pkt->ms24.cmd_byte_count = LE_32(cmd->RequestLen);
1596 1596
1597 1597 /* Load ct rsp byte count. */
1598 1598 pkt->ms24.resp_byte_count = LE_32(cmd->ResponseLen);
1599 1599
1600 1600 long_ptr = (uint32_t *)&pkt->ms24.dseg_0_address;
1601 1601
1602 1602 /* Load MS command entry data segments. */
1603 1603 *long_ptr++ = (uint32_t)
1604 1604 LE_32(LSD(dma_mem->cookie.dmac_laddress));
1605 1605 *long_ptr++ = (uint32_t)
1606 1606 LE_32(MSD(dma_mem->cookie.dmac_laddress));
1607 1607 *long_ptr++ = (uint32_t)(LE_32(cmd->RequestLen));
1608 1608
1609 1609 /* Load MS response entry data segments. */
1610 1610 *long_ptr++ = (uint32_t)
1611 1611 LE_32(LSD(dma_mem->cookie.dmac_laddress));
1612 1612 *long_ptr++ = (uint32_t)
1613 1613 LE_32(MSD(dma_mem->cookie.dmac_laddress));
1614 1614 *long_ptr = (uint32_t)LE_32(cmd->ResponseLen);
1615 1615
1616 1616 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt,
1617 1617 sizeof (ql_mbx_iocb_t));
1618 1618
1619 1619 comp_status = (uint16_t)LE_16(pkt->sts24.comp_status);
1620 1620 if (comp_status == CS_DATA_UNDERRUN) {
1621 1621 if ((BE_16(ct->max_residual_size)) == 0) {
1622 1622 comp_status = CS_COMPLETE;
1623 1623 }
1624 1624 }
1625 1625
1626 1626 if (rval != QL_SUCCESS || (pkt->sts24.entry_status & 0x3c) !=
1627 1627 0) {
1628 1628 EL(ha, "failed, I/O timeout or "
1629 1629 "es=%xh, ss_l=%xh, rval=%xh\n",
1630 1630 pkt->sts24.entry_status,
1631 1631 pkt->sts24.scsi_status_l, rval);
1632 1632 kmem_free(pkt, pkt_size);
1633 1633 ql_free_dma_resource(ha, dma_mem);
1634 1634 kmem_free(dma_mem, sizeof (dma_mem_t));
1635 1635 cmd->Status = EXT_STATUS_MS_NO_RESPONSE;
1636 1636 cmd->ResponseLen = 0;
1637 1637 return;
1638 1638 }
1639 1639 } else {
1640 1640 pkt->ms.entry_type = MS_TYPE;
1641 1641 pkt->ms.entry_count = 1;
1642 1642
1643 1643 /* Set loop ID */
1644 1644 loop_id = (uint16_t)(ct->gs_type == GS_TYPE_DIR_SERVER ?
1645 1645 SIMPLE_NAME_SERVER_LOOP_ID : MANAGEMENT_SERVER_LOOP_ID);
1646 1646 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1647 1647 pkt->ms.loop_id_l = LSB(loop_id);
1648 1648 pkt->ms.loop_id_h = MSB(loop_id);
1649 1649 } else {
1650 1650 pkt->ms.loop_id_h = LSB(loop_id);
1651 1651 }
1652 1652
1653 1653 /* Set ISP command timeout. */
1654 1654 pkt->ms.timeout = LE_16(120);
1655 1655
1656 1656 /* Set data segment counts. */
1657 1657 pkt->ms.cmd_dseg_count_l = 1;
1658 1658 pkt->ms.total_dseg_count = LE_16(2);
1659 1659
1660 1660 /* Response total byte count. */
1661 1661 pkt->ms.resp_byte_count = LE_32(cmd->ResponseLen);
1662 1662 pkt->ms.dseg_1_length = LE_32(cmd->ResponseLen);
1663 1663
1664 1664 /* Command total byte count. */
1665 1665 pkt->ms.cmd_byte_count = LE_32(cmd->RequestLen);
1666 1666 pkt->ms.dseg_0_length = LE_32(cmd->RequestLen);
1667 1667
1668 1668 /* Load command/response data segments. */
1669 1669 pkt->ms.dseg_0_address[0] = (uint32_t)
1670 1670 LE_32(LSD(dma_mem->cookie.dmac_laddress));
1671 1671 pkt->ms.dseg_0_address[1] = (uint32_t)
1672 1672 LE_32(MSD(dma_mem->cookie.dmac_laddress));
1673 1673 pkt->ms.dseg_1_address[0] = (uint32_t)
1674 1674 LE_32(LSD(dma_mem->cookie.dmac_laddress));
1675 1675 pkt->ms.dseg_1_address[1] = (uint32_t)
1676 1676 LE_32(MSD(dma_mem->cookie.dmac_laddress));
1677 1677
1678 1678 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt,
1679 1679 sizeof (ql_mbx_iocb_t));
1680 1680
1681 1681 comp_status = (uint16_t)LE_16(pkt->sts.comp_status);
1682 1682 if (comp_status == CS_DATA_UNDERRUN) {
1683 1683 if ((BE_16(ct->max_residual_size)) == 0) {
1684 1684 comp_status = CS_COMPLETE;
1685 1685 }
1686 1686 }
1687 1687 if (rval != QL_SUCCESS || (pkt->sts.entry_status & 0x7e) != 0) {
1688 1688 EL(ha, "failed, I/O timeout or "
1689 1689 "es=%xh, rval=%xh\n", pkt->sts.entry_status, rval);
1690 1690 kmem_free(pkt, pkt_size);
1691 1691 ql_free_dma_resource(ha, dma_mem);
1692 1692 kmem_free(dma_mem, sizeof (dma_mem_t));
1693 1693 cmd->Status = EXT_STATUS_MS_NO_RESPONSE;
1694 1694 cmd->ResponseLen = 0;
1695 1695 return;
1696 1696 }
1697 1697 }
1698 1698
1699 1699 /* Sync in coming DMA buffer. */
1700 1700 (void) ddi_dma_sync(dma_mem->dma_handle, 0,
1701 1701 pld_byte_cnt, DDI_DMA_SYNC_FORKERNEL);
1702 1702 /* Copy in coming DMA data. */
1703 1703 ddi_rep_get8(dma_mem->acc_handle, (uint8_t *)pld,
1704 1704 (uint8_t *)dma_mem->bp, pld_byte_cnt,
1705 1705 DDI_DEV_AUTOINCR);
1706 1706
1707 1707 /* Copy response payload from DMA buffer to application. */
1708 1708 if (cmd->ResponseLen != 0) {
1709 1709 QL_PRINT_9(CE_CONT, "(%d): ResponseLen=%d\n", ha->instance,
1710 1710 cmd->ResponseLen);
1711 1711 QL_DUMP_9(pld, 8, cmd->ResponseLen);
1712 1712
1713 1713 /* Send response payload. */
1714 1714 if (ql_send_buffer_data(pld,
1715 1715 (caddr_t)(uintptr_t)cmd->ResponseAdr,
1716 1716 cmd->ResponseLen, mode) != cmd->ResponseLen) {
1717 1717 EL(ha, "failed, send_buffer_data\n");
1718 1718 cmd->Status = EXT_STATUS_COPY_ERR;
1719 1719 cmd->ResponseLen = 0;
1720 1720 }
1721 1721 }
1722 1722
1723 1723 kmem_free(pkt, pkt_size);
1724 1724 ql_free_dma_resource(ha, dma_mem);
1725 1725 kmem_free(dma_mem, sizeof (dma_mem_t));
1726 1726
1727 1727 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1728 1728 }
1729 1729
1730 1730 /*
1731 1731 * ql_aen_reg
1732 1732 * IOCTL management server Asynchronous Event Tracking Enable/Disable.
1733 1733 *
1734 1734 * Input:
1735 1735 * ha: adapter state pointer.
1736 1736 * cmd: EXT_IOCTL cmd struct pointer.
1737 1737 * mode: flags.
1738 1738 *
1739 1739 * Returns:
1740 1740 * None, request status indicated in cmd->Status.
1741 1741 *
1742 1742 * Context:
1743 1743 * Kernel context.
1744 1744 */
1745 1745 static void
1746 1746 ql_aen_reg(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
1747 1747 {
1748 1748 EXT_REG_AEN reg_struct;
1749 1749 int rval = 0;
1750 1750 ql_xioctl_t *xp = ha->xioctl;
1751 1751
1752 1752 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1753 1753
1754 1754 rval = ddi_copyin((void*)(uintptr_t)cmd->RequestAdr, ®_struct,
1755 1755 cmd->RequestLen, mode);
1756 1756
1757 1757 if (rval == 0) {
1758 1758 if (reg_struct.Enable) {
1759 1759 xp->flags |= QL_AEN_TRACKING_ENABLE;
1760 1760 } else {
1761 1761 xp->flags &= ~QL_AEN_TRACKING_ENABLE;
1762 1762 /* Empty the queue. */
1763 1763 INTR_LOCK(ha);
1764 1764 xp->aen_q_head = 0;
1765 1765 xp->aen_q_tail = 0;
1766 1766 INTR_UNLOCK(ha);
1767 1767 }
1768 1768 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1769 1769 } else {
1770 1770 cmd->Status = EXT_STATUS_COPY_ERR;
1771 1771 EL(ha, "failed, ddi_copyin\n");
1772 1772 }
1773 1773 }
1774 1774
1775 1775 /*
1776 1776 * ql_aen_get
1777 1777 * IOCTL management server Asynchronous Event Record Transfer.
1778 1778 *
1779 1779 * Input:
1780 1780 * ha: adapter state pointer.
1781 1781 * cmd: EXT_IOCTL cmd struct pointer.
1782 1782 * mode: flags.
1783 1783 *
1784 1784 * Returns:
1785 1785 * None, request status indicated in cmd->Status.
1786 1786 *
1787 1787 * Context:
1788 1788 * Kernel context.
1789 1789 */
1790 1790 static void
1791 1791 ql_aen_get(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
1792 1792 {
1793 1793 uint32_t out_size;
1794 1794 EXT_ASYNC_EVENT *tmp_q;
1795 1795 EXT_ASYNC_EVENT aen[EXT_DEF_MAX_AEN_QUEUE];
1796 1796 uint8_t i;
1797 1797 uint8_t queue_cnt;
1798 1798 uint8_t request_cnt;
1799 1799 ql_xioctl_t *xp = ha->xioctl;
1800 1800
1801 1801 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1802 1802
1803 1803 /* Compute the number of events that can be returned */
1804 1804 request_cnt = (uint8_t)(cmd->ResponseLen / sizeof (EXT_ASYNC_EVENT));
1805 1805
1806 1806 if (request_cnt < EXT_DEF_MAX_AEN_QUEUE) {
1807 1807 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
1808 1808 cmd->DetailStatus = EXT_DEF_MAX_AEN_QUEUE;
1809 1809 EL(ha, "failed, request_cnt < EXT_DEF_MAX_AEN_QUEUE, "
1810 1810 "Len=%xh\n", request_cnt);
1811 1811 cmd->ResponseLen = 0;
1812 1812 return;
1813 1813 }
1814 1814
1815 1815 /* 1st: Make a local copy of the entire queue content. */
1816 1816 tmp_q = (EXT_ASYNC_EVENT *)xp->aen_tracking_queue;
1817 1817 queue_cnt = 0;
1818 1818
1819 1819 INTR_LOCK(ha);
1820 1820 i = xp->aen_q_head;
1821 1821
1822 1822 for (; queue_cnt < EXT_DEF_MAX_AEN_QUEUE; ) {
1823 1823 if (tmp_q[i].AsyncEventCode != 0) {
1824 1824 bcopy(&tmp_q[i], &aen[queue_cnt],
1825 1825 sizeof (EXT_ASYNC_EVENT));
1826 1826 queue_cnt++;
1827 1827 tmp_q[i].AsyncEventCode = 0; /* empty out the slot */
1828 1828 }
1829 1829 if (i == xp->aen_q_tail) {
1830 1830 /* done. */
1831 1831 break;
1832 1832 }
1833 1833 i++;
1834 1834 if (i == EXT_DEF_MAX_AEN_QUEUE) {
1835 1835 i = 0;
1836 1836 }
1837 1837 }
1838 1838
1839 1839 /* Empty the queue. */
1840 1840 xp->aen_q_head = 0;
1841 1841 xp->aen_q_tail = 0;
1842 1842
1843 1843 INTR_UNLOCK(ha);
1844 1844
1845 1845 /* 2nd: Now transfer the queue content to user buffer */
1846 1846 /* Copy the entire queue to user's buffer. */
1847 1847 out_size = (uint32_t)(queue_cnt * sizeof (EXT_ASYNC_EVENT));
1848 1848 if (queue_cnt == 0) {
1849 1849 cmd->ResponseLen = 0;
1850 1850 } else if (ddi_copyout((void *)&aen[0],
1851 1851 (void *)(uintptr_t)(cmd->ResponseAdr),
1852 1852 out_size, mode) != 0) {
1853 1853 cmd->Status = EXT_STATUS_COPY_ERR;
1854 1854 cmd->ResponseLen = 0;
1855 1855 EL(ha, "failed, ddi_copyout\n");
1856 1856 } else {
1857 1857 cmd->ResponseLen = out_size;
1858 1858 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1859 1859 }
1860 1860 }
1861 1861
1862 1862 /*
1863 1863 * ql_enqueue_aen
1864 1864 *
1865 1865 * Input:
1866 1866 * ha: adapter state pointer.
1867 1867 * event_code: async event code of the event to add to queue.
1868 1868 * payload: event payload for the queue.
1869 1869 * INTR_LOCK must be already obtained.
1870 1870 *
1871 1871 * Context:
1872 1872 * Interrupt or Kernel context, no mailbox commands allowed.
1873 1873 */
1874 1874 void
1875 1875 ql_enqueue_aen(ql_adapter_state_t *ha, uint16_t event_code, void *payload)
1876 1876 {
1877 1877 uint8_t new_entry; /* index to current entry */
1878 1878 uint16_t *mbx;
1879 1879 EXT_ASYNC_EVENT *aen_queue;
1880 1880 ql_xioctl_t *xp = ha->xioctl;
1881 1881
1882 1882 QL_PRINT_9(CE_CONT, "(%d): started, event_code=%d\n", ha->instance,
1883 1883 event_code);
1884 1884
1885 1885 if (xp == NULL) {
1886 1886 QL_PRINT_9(CE_CONT, "(%d): no context\n", ha->instance);
1887 1887 return;
1888 1888 }
1889 1889 aen_queue = (EXT_ASYNC_EVENT *)xp->aen_tracking_queue;
1890 1890
1891 1891 if (aen_queue[xp->aen_q_tail].AsyncEventCode != NULL) {
1892 1892 /* Need to change queue pointers to make room. */
1893 1893
1894 1894 /* Increment tail for adding new entry. */
1895 1895 xp->aen_q_tail++;
1896 1896 if (xp->aen_q_tail == EXT_DEF_MAX_AEN_QUEUE) {
1897 1897 xp->aen_q_tail = 0;
1898 1898 }
1899 1899 if (xp->aen_q_head == xp->aen_q_tail) {
1900 1900 /*
1901 1901 * We're overwriting the oldest entry, so need to
1902 1902 * update the head pointer.
1903 1903 */
1904 1904 xp->aen_q_head++;
1905 1905 if (xp->aen_q_head == EXT_DEF_MAX_AEN_QUEUE) {
1906 1906 xp->aen_q_head = 0;
1907 1907 }
1908 1908 }
1909 1909 }
1910 1910
1911 1911 new_entry = xp->aen_q_tail;
1912 1912 aen_queue[new_entry].AsyncEventCode = event_code;
1913 1913
1914 1914 /* Update payload */
1915 1915 if (payload != NULL) {
1916 1916 switch (event_code) {
1917 1917 case MBA_LIP_OCCURRED:
1918 1918 case MBA_LOOP_UP:
1919 1919 case MBA_LOOP_DOWN:
1920 1920 case MBA_LIP_F8:
1921 1921 case MBA_LIP_RESET:
1922 1922 case MBA_PORT_UPDATE:
1923 1923 break;
1924 1924 case MBA_RSCN_UPDATE:
1925 1925 mbx = (uint16_t *)payload;
1926 1926 /* al_pa */
1927 1927 aen_queue[new_entry].Payload.RSCN.RSCNInfo[0] =
1928 1928 LSB(mbx[2]);
1929 1929 /* area */
1930 1930 aen_queue[new_entry].Payload.RSCN.RSCNInfo[1] =
1931 1931 MSB(mbx[2]);
1932 1932 /* domain */
1933 1933 aen_queue[new_entry].Payload.RSCN.RSCNInfo[2] =
1934 1934 LSB(mbx[1]);
1935 1935 /* save in big endian */
1936 1936 BIG_ENDIAN_24(&aen_queue[new_entry].
1937 1937 Payload.RSCN.RSCNInfo[0]);
1938 1938
1939 1939 aen_queue[new_entry].Payload.RSCN.AddrFormat =
1940 1940 MSB(mbx[1]);
1941 1941
1942 1942 break;
1943 1943 default:
1944 1944 /* Not supported */
1945 1945 EL(ha, "failed, event code not supported=%xh\n",
1946 1946 event_code);
1947 1947 aen_queue[new_entry].AsyncEventCode = 0;
1948 1948 break;
1949 1949 }
1950 1950 }
1951 1951
1952 1952 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1953 1953 }
1954 1954
1955 1955 /*
1956 1956 * ql_scsi_passthru
1957 1957 * IOCTL SCSI passthrough.
1958 1958 *
1959 1959 * Input:
1960 1960 * ha: adapter state pointer.
1961 1961 * cmd: User space SCSI command pointer.
1962 1962 * mode: flags.
1963 1963 *
1964 1964 * Returns:
1965 1965 * None, request status indicated in cmd->Status.
1966 1966 *
1967 1967 * Context:
1968 1968 * Kernel context.
1969 1969 */
1970 1970 static void
1971 1971 ql_scsi_passthru(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
1972 1972 {
1973 1973 ql_mbx_iocb_t *pkt;
1974 1974 ql_mbx_data_t mr;
1975 1975 dma_mem_t *dma_mem;
1976 1976 caddr_t pld;
1977 1977 uint32_t pkt_size, pld_size;
1978 1978 uint16_t qlnt, retries, cnt, cnt2;
1979 1979 uint8_t *name;
1980 1980 EXT_FC_SCSI_PASSTHRU *ufc_req;
1981 1981 EXT_SCSI_PASSTHRU *usp_req;
1982 1982 int rval;
1983 1983 union _passthru {
1984 1984 EXT_SCSI_PASSTHRU sp_cmd;
1985 1985 EXT_FC_SCSI_PASSTHRU fc_cmd;
1986 1986 } pt_req; /* Passthru request */
1987 1987 uint32_t status, sense_sz = 0;
1988 1988 ql_tgt_t *tq = NULL;
1989 1989 EXT_SCSI_PASSTHRU *sp_req = &pt_req.sp_cmd;
1990 1990 EXT_FC_SCSI_PASSTHRU *fc_req = &pt_req.fc_cmd;
1991 1991
1992 1992 /* SCSI request struct for SCSI passthrough IOs. */
1993 1993 struct {
1994 1994 uint16_t lun;
1995 1995 uint16_t sense_length; /* Sense buffer size */
1996 1996 size_t resid; /* Residual */
1997 1997 uint8_t *cdbp; /* Requestor's CDB */
1998 1998 uint8_t *u_sense; /* Requestor's sense buffer */
1999 1999 uint8_t cdb_len; /* Requestor's CDB length */
2000 2000 uint8_t direction;
2001 2001 } scsi_req;
2002 2002
2003 2003 struct {
2004 2004 uint8_t *rsp_info;
2005 2005 uint8_t *req_sense_data;
2006 2006 uint32_t residual_length;
2007 2007 uint32_t rsp_info_length;
2008 2008 uint32_t req_sense_length;
2009 2009 uint16_t comp_status;
2010 2010 uint8_t state_flags_l;
2011 2011 uint8_t state_flags_h;
2012 2012 uint8_t scsi_status_l;
2013 2013 uint8_t scsi_status_h;
2014 2014 } sts;
2015 2015
2016 2016 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2017 2017
2018 2018 /* Verify Sub Code and set cnt to needed request size. */
2019 2019 if (cmd->SubCode == EXT_SC_SEND_SCSI_PASSTHRU) {
2020 2020 pld_size = sizeof (EXT_SCSI_PASSTHRU);
2021 2021 } else if (cmd->SubCode == EXT_SC_SEND_FC_SCSI_PASSTHRU) {
2022 2022 pld_size = sizeof (EXT_FC_SCSI_PASSTHRU);
2023 2023 } else {
2024 2024 EL(ha, "failed, invalid SubCode=%xh\n", cmd->SubCode);
2025 2025 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE;
2026 2026 cmd->ResponseLen = 0;
2027 2027 return;
2028 2028 }
2029 2029
2030 2030 dma_mem = (dma_mem_t *)kmem_zalloc(sizeof (dma_mem_t), KM_SLEEP);
2031 2031 if (dma_mem == NULL) {
2032 2032 EL(ha, "failed, kmem_zalloc\n");
2033 2033 cmd->Status = EXT_STATUS_NO_MEMORY;
2034 2034 cmd->ResponseLen = 0;
2035 2035 return;
2036 2036 }
2037 2037 /* Verify the size of and copy in the passthru request structure. */
2038 2038 if (cmd->RequestLen != pld_size) {
2039 2039 /* Return error */
2040 2040 EL(ha, "failed, RequestLen != cnt, is=%xh, expected=%xh\n",
2041 2041 cmd->RequestLen, pld_size);
2042 2042 cmd->Status = EXT_STATUS_INVALID_PARAM;
2043 2043 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN;
2044 2044 cmd->ResponseLen = 0;
2045 2045 return;
2046 2046 }
2047 2047
2048 2048 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr, &pt_req,
2049 2049 pld_size, mode) != 0) {
2050 2050 EL(ha, "failed, ddi_copyin\n");
2051 2051 cmd->Status = EXT_STATUS_COPY_ERR;
2052 2052 cmd->ResponseLen = 0;
2053 2053 return;
2054 2054 }
2055 2055
2056 2056 /*
2057 2057 * Find fc_port from SCSI PASSTHRU structure fill in the scsi_req
2058 2058 * request data structure.
2059 2059 */
2060 2060 if (cmd->SubCode == EXT_SC_SEND_SCSI_PASSTHRU) {
2061 2061 scsi_req.lun = sp_req->TargetAddr.Lun;
2062 2062 scsi_req.sense_length = sizeof (sp_req->SenseData);
2063 2063 scsi_req.cdbp = &sp_req->Cdb[0];
2064 2064 scsi_req.cdb_len = sp_req->CdbLength;
2065 2065 scsi_req.direction = sp_req->Direction;
2066 2066 usp_req = (EXT_SCSI_PASSTHRU *)(uintptr_t)cmd->RequestAdr;
2067 2067 scsi_req.u_sense = &usp_req->SenseData[0];
2068 2068 cmd->DetailStatus = EXT_DSTATUS_TARGET;
2069 2069
2070 2070 qlnt = QLNT_PORT;
2071 2071 name = (uint8_t *)&sp_req->TargetAddr.Target;
2072 2072 QL_PRINT_9(CE_CONT, "(%d): SubCode=%xh, Target=%lld\n",
2073 2073 ha->instance, cmd->SubCode, sp_req->TargetAddr.Target);
2074 2074 tq = ql_find_port(ha, name, qlnt);
2075 2075 } else {
2076 2076 /*
2077 2077 * Must be FC PASSTHRU, verified above.
2078 2078 */
2079 2079 if (fc_req->FCScsiAddr.DestType == EXT_DEF_DESTTYPE_WWPN) {
2080 2080 qlnt = QLNT_PORT;
2081 2081 name = &fc_req->FCScsiAddr.DestAddr.WWPN[0];
2082 2082 QL_PRINT_9(CE_CONT, "(%d): SubCode=%xh, "
2083 2083 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
2084 2084 ha->instance, cmd->SubCode, name[0], name[1],
2085 2085 name[2], name[3], name[4], name[5], name[6],
2086 2086 name[7]);
2087 2087 tq = ql_find_port(ha, name, qlnt);
2088 2088 } else if (fc_req->FCScsiAddr.DestType ==
2089 2089 EXT_DEF_DESTTYPE_WWNN) {
2090 2090 qlnt = QLNT_NODE;
2091 2091 name = &fc_req->FCScsiAddr.DestAddr.WWNN[0];
2092 2092 QL_PRINT_9(CE_CONT, "(%d): SubCode=%xh, "
2093 2093 "wwnn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
2094 2094 ha->instance, cmd->SubCode, name[0], name[1],
2095 2095 name[2], name[3], name[4], name[5], name[6],
2096 2096 name[7]);
2097 2097 tq = ql_find_port(ha, name, qlnt);
2098 2098 } else if (fc_req->FCScsiAddr.DestType ==
2099 2099 EXT_DEF_DESTTYPE_PORTID) {
2100 2100 qlnt = QLNT_PID;
2101 2101 name = &fc_req->FCScsiAddr.DestAddr.Id[0];
2102 2102 QL_PRINT_9(CE_CONT, "(%d): SubCode=%xh, PID="
2103 2103 "%02x%02x%02x\n", ha->instance, cmd->SubCode,
2104 2104 name[0], name[1], name[2]);
2105 2105 tq = ql_find_port(ha, name, qlnt);
2106 2106 } else {
2107 2107 EL(ha, "failed, SubCode=%xh invalid DestType=%xh\n",
2108 2108 cmd->SubCode, fc_req->FCScsiAddr.DestType);
2109 2109 cmd->Status = EXT_STATUS_INVALID_PARAM;
2110 2110 cmd->ResponseLen = 0;
2111 2111 return;
2112 2112 }
2113 2113 scsi_req.lun = fc_req->FCScsiAddr.Lun;
2114 2114 scsi_req.sense_length = sizeof (fc_req->SenseData);
2115 2115 scsi_req.cdbp = &sp_req->Cdb[0];
2116 2116 scsi_req.cdb_len = sp_req->CdbLength;
2117 2117 ufc_req = (EXT_FC_SCSI_PASSTHRU *)(uintptr_t)cmd->RequestAdr;
2118 2118 scsi_req.u_sense = &ufc_req->SenseData[0];
2119 2119 scsi_req.direction = fc_req->Direction;
2120 2120 }
2121 2121
2122 2122 if (tq == NULL || !VALID_TARGET_ID(ha, tq->loop_id)) {
2123 2123 EL(ha, "failed, fc_port not found\n");
2124 2124 cmd->Status = EXT_STATUS_DEV_NOT_FOUND;
2125 2125 cmd->ResponseLen = 0;
2126 2126 return;
2127 2127 }
2128 2128
2129 2129 if (tq->flags & TQF_NEED_AUTHENTICATION) {
2130 2130 EL(ha, "target not available; loopid=%xh\n", tq->loop_id);
2131 2131 cmd->Status = EXT_STATUS_DEVICE_OFFLINE;
2132 2132 cmd->ResponseLen = 0;
2133 2133 return;
2134 2134 }
2135 2135
2136 2136 /* Allocate command block. */
2137 2137 if ((scsi_req.direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN ||
2138 2138 scsi_req.direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) &&
2139 2139 cmd->ResponseLen) {
2140 2140 pld_size = cmd->ResponseLen;
2141 2141 pkt_size = (uint32_t)(sizeof (ql_mbx_iocb_t) + pld_size);
2142 2142 pkt = kmem_zalloc(pkt_size, KM_SLEEP);
2143 2143 if (pkt == NULL) {
2144 2144 EL(ha, "failed, kmem_zalloc\n");
2145 2145 cmd->Status = EXT_STATUS_NO_MEMORY;
2146 2146 cmd->ResponseLen = 0;
2147 2147 return;
2148 2148 }
2149 2149 pld = (caddr_t)pkt + sizeof (ql_mbx_iocb_t);
2150 2150
2151 2151 /* Get DMA memory for the IOCB */
2152 2152 if (ql_get_dma_mem(ha, dma_mem, pld_size, LITTLE_ENDIAN_DMA,
2153 2153 QL_DMA_DATA_ALIGN) != QL_SUCCESS) {
2154 2154 cmn_err(CE_WARN, "%s(%d): request queue DMA memory "
2155 2155 "alloc failed", QL_NAME, ha->instance);
2156 2156 kmem_free(pkt, pkt_size);
2157 2157 cmd->Status = EXT_STATUS_MS_NO_RESPONSE;
2158 2158 cmd->ResponseLen = 0;
2159 2159 return;
2160 2160 }
2161 2161
2162 2162 if (scsi_req.direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) {
2163 2163 scsi_req.direction = (uint8_t)
2164 2164 (CFG_IST(ha, CFG_CTRL_24258081) ?
2165 2165 CF_RD : CF_DATA_IN | CF_STAG);
2166 2166 } else {
2167 2167 scsi_req.direction = (uint8_t)
2168 2168 (CFG_IST(ha, CFG_CTRL_24258081) ?
2169 2169 CF_WR : CF_DATA_OUT | CF_STAG);
2170 2170 cmd->ResponseLen = 0;
2171 2171
2172 2172 /* Get command payload. */
2173 2173 if (ql_get_buffer_data(
2174 2174 (caddr_t)(uintptr_t)cmd->ResponseAdr,
2175 2175 pld, pld_size, mode) != pld_size) {
2176 2176 EL(ha, "failed, get_buffer_data\n");
2177 2177 cmd->Status = EXT_STATUS_COPY_ERR;
2178 2178
2179 2179 kmem_free(pkt, pkt_size);
2180 2180 ql_free_dma_resource(ha, dma_mem);
2181 2181 kmem_free(dma_mem, sizeof (dma_mem_t));
2182 2182 return;
2183 2183 }
2184 2184
2185 2185 /* Copy out going data to DMA buffer. */
2186 2186 ddi_rep_put8(dma_mem->acc_handle, (uint8_t *)pld,
2187 2187 (uint8_t *)dma_mem->bp, pld_size,
2188 2188 DDI_DEV_AUTOINCR);
2189 2189
2190 2190 /* Sync DMA buffer. */
2191 2191 (void) ddi_dma_sync(dma_mem->dma_handle, 0,
2192 2192 dma_mem->size, DDI_DMA_SYNC_FORDEV);
2193 2193 }
2194 2194 } else {
2195 2195 scsi_req.direction = (uint8_t)
2196 2196 (CFG_IST(ha, CFG_CTRL_24258081) ? 0 : CF_STAG);
2197 2197 cmd->ResponseLen = 0;
2198 2198
2199 2199 pkt_size = sizeof (ql_mbx_iocb_t);
2200 2200 pkt = kmem_zalloc(pkt_size, KM_SLEEP);
2201 2201 if (pkt == NULL) {
2202 2202 EL(ha, "failed, kmem_zalloc-2\n");
2203 2203 cmd->Status = EXT_STATUS_NO_MEMORY;
2204 2204 return;
2205 2205 }
2206 2206 pld = NULL;
2207 2207 pld_size = 0;
2208 2208 }
2209 2209
2210 2210 /* retries = ha->port_down_retry_count; */
2211 2211 retries = 1;
2212 2212 cmd->Status = EXT_STATUS_OK;
2213 2213 cmd->DetailStatus = EXT_DSTATUS_NOADNL_INFO;
2214 2214
2215 2215 QL_PRINT_9(CE_CONT, "(%d): SCSI cdb\n", ha->instance);
2216 2216 QL_DUMP_9(scsi_req.cdbp, 8, scsi_req.cdb_len);
2217 2217
2218 2218 do {
2219 2219 if (DRIVER_SUSPENDED(ha)) {
2220 2220 sts.comp_status = CS_LOOP_DOWN_ABORT;
2221 2221 break;
2222 2222 }
2223 2223
2224 2224 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2225 2225 pkt->cmd24.entry_type = IOCB_CMD_TYPE_7;
2226 2226 pkt->cmd24.entry_count = 1;
2227 2227
2228 2228 /* Set LUN number */
2229 2229 pkt->cmd24.fcp_lun[2] = LSB(scsi_req.lun);
2230 2230 pkt->cmd24.fcp_lun[3] = MSB(scsi_req.lun);
2231 2231
2232 2232 /* Set N_port handle */
2233 2233 pkt->cmd24.n_port_hdl = (uint16_t)LE_16(tq->loop_id);
2234 2234
2235 2235 /* Set VP Index */
2236 2236 pkt->cmd24.vp_index = ha->vp_index;
2237 2237
2238 2238 /* Set target ID */
2239 2239 pkt->cmd24.target_id[0] = tq->d_id.b.al_pa;
2240 2240 pkt->cmd24.target_id[1] = tq->d_id.b.area;
2241 2241 pkt->cmd24.target_id[2] = tq->d_id.b.domain;
2242 2242
2243 2243 /* Set ISP command timeout. */
2244 2244 pkt->cmd24.timeout = (uint16_t)LE_16(15);
2245 2245
2246 2246 /* Load SCSI CDB */
2247 2247 ddi_rep_put8(ha->hba_buf.acc_handle, scsi_req.cdbp,
2248 2248 pkt->cmd24.scsi_cdb, scsi_req.cdb_len,
2249 2249 DDI_DEV_AUTOINCR);
2250 2250 for (cnt = 0; cnt < MAX_CMDSZ;
2251 2251 cnt = (uint16_t)(cnt + 4)) {
2252 2252 ql_chg_endian((uint8_t *)&pkt->cmd24.scsi_cdb
2253 2253 + cnt, 4);
2254 2254 }
2255 2255
2256 2256 /* Set tag queue control flags */
2257 2257 pkt->cmd24.task = TA_STAG;
2258 2258
2259 2259 if (pld_size) {
2260 2260 /* Set transfer direction. */
2261 2261 pkt->cmd24.control_flags = scsi_req.direction;
2262 2262
2263 2263 /* Set data segment count. */
2264 2264 pkt->cmd24.dseg_count = LE_16(1);
2265 2265
2266 2266 /* Load total byte count. */
2267 2267 pkt->cmd24.total_byte_count = LE_32(pld_size);
2268 2268
2269 2269 /* Load data descriptor. */
2270 2270 pkt->cmd24.dseg_0_address[0] = (uint32_t)
2271 2271 LE_32(LSD(dma_mem->cookie.dmac_laddress));
2272 2272 pkt->cmd24.dseg_0_address[1] = (uint32_t)
2273 2273 LE_32(MSD(dma_mem->cookie.dmac_laddress));
2274 2274 pkt->cmd24.dseg_0_length = LE_32(pld_size);
2275 2275 }
2276 2276 } else if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
2277 2277 pkt->cmd3.entry_type = IOCB_CMD_TYPE_3;
2278 2278 pkt->cmd3.entry_count = 1;
2279 2279 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2280 2280 pkt->cmd3.target_l = LSB(tq->loop_id);
2281 2281 pkt->cmd3.target_h = MSB(tq->loop_id);
2282 2282 } else {
2283 2283 pkt->cmd3.target_h = LSB(tq->loop_id);
2284 2284 }
2285 2285 pkt->cmd3.lun_l = LSB(scsi_req.lun);
2286 2286 pkt->cmd3.lun_h = MSB(scsi_req.lun);
2287 2287 pkt->cmd3.control_flags_l = scsi_req.direction;
2288 2288 pkt->cmd3.timeout = LE_16(15);
2289 2289 for (cnt = 0; cnt < scsi_req.cdb_len; cnt++) {
2290 2290 pkt->cmd3.scsi_cdb[cnt] = scsi_req.cdbp[cnt];
2291 2291 }
2292 2292 if (pld_size) {
2293 2293 pkt->cmd3.dseg_count = LE_16(1);
2294 2294 pkt->cmd3.byte_count = LE_32(pld_size);
2295 2295 pkt->cmd3.dseg_0_address[0] = (uint32_t)
2296 2296 LE_32(LSD(dma_mem->cookie.dmac_laddress));
2297 2297 pkt->cmd3.dseg_0_address[1] = (uint32_t)
2298 2298 LE_32(MSD(dma_mem->cookie.dmac_laddress));
2299 2299 pkt->cmd3.dseg_0_length = LE_32(pld_size);
2300 2300 }
2301 2301 } else {
2302 2302 pkt->cmd.entry_type = IOCB_CMD_TYPE_2;
2303 2303 pkt->cmd.entry_count = 1;
2304 2304 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2305 2305 pkt->cmd.target_l = LSB(tq->loop_id);
2306 2306 pkt->cmd.target_h = MSB(tq->loop_id);
2307 2307 } else {
2308 2308 pkt->cmd.target_h = LSB(tq->loop_id);
2309 2309 }
2310 2310 pkt->cmd.lun_l = LSB(scsi_req.lun);
2311 2311 pkt->cmd.lun_h = MSB(scsi_req.lun);
2312 2312 pkt->cmd.control_flags_l = scsi_req.direction;
2313 2313 pkt->cmd.timeout = LE_16(15);
2314 2314 for (cnt = 0; cnt < scsi_req.cdb_len; cnt++) {
2315 2315 pkt->cmd.scsi_cdb[cnt] = scsi_req.cdbp[cnt];
2316 2316 }
2317 2317 if (pld_size) {
2318 2318 pkt->cmd.dseg_count = LE_16(1);
2319 2319 pkt->cmd.byte_count = LE_32(pld_size);
2320 2320 pkt->cmd.dseg_0_address = (uint32_t)
2321 2321 LE_32(LSD(dma_mem->cookie.dmac_laddress));
2322 2322 pkt->cmd.dseg_0_length = LE_32(pld_size);
2323 2323 }
2324 2324 }
2325 2325 /* Go issue command and wait for completion. */
2326 2326 QL_PRINT_9(CE_CONT, "(%d): request pkt\n", ha->instance);
2327 2327 QL_DUMP_9(pkt, 8, pkt_size);
2328 2328
2329 2329 status = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
2330 2330
2331 2331 if (pld_size) {
2332 2332 /* Sync in coming DMA buffer. */
2333 2333 (void) ddi_dma_sync(dma_mem->dma_handle, 0,
2334 2334 dma_mem->size, DDI_DMA_SYNC_FORKERNEL);
2335 2335 /* Copy in coming DMA data. */
2336 2336 ddi_rep_get8(dma_mem->acc_handle, (uint8_t *)pld,
2337 2337 (uint8_t *)dma_mem->bp, pld_size,
2338 2338 DDI_DEV_AUTOINCR);
2339 2339 }
2340 2340
2341 2341 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2342 2342 pkt->sts24.entry_status = (uint8_t)
2343 2343 (pkt->sts24.entry_status & 0x3c);
2344 2344 } else {
2345 2345 pkt->sts.entry_status = (uint8_t)
2346 2346 (pkt->sts.entry_status & 0x7e);
2347 2347 }
2348 2348
2349 2349 if (status == QL_SUCCESS && pkt->sts.entry_status != 0) {
2350 2350 EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
2351 2351 pkt->sts.entry_status, tq->d_id.b24);
2352 2352 status = QL_FUNCTION_PARAMETER_ERROR;
2353 2353 }
2354 2354
2355 2355 sts.comp_status = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
2356 2356 LE_16(pkt->sts24.comp_status) :
2357 2357 LE_16(pkt->sts.comp_status));
2358 2358
2359 2359 /*
2360 2360 * We have verified about all the request that can be so far.
2361 2361 * Now we need to start verification of our ability to
2362 2362 * actually issue the CDB.
2363 2363 */
2364 2364 if (DRIVER_SUSPENDED(ha)) {
2365 2365 sts.comp_status = CS_LOOP_DOWN_ABORT;
2366 2366 break;
2367 2367 } else if (status == QL_SUCCESS &&
2368 2368 (sts.comp_status == CS_PORT_LOGGED_OUT ||
2369 2369 sts.comp_status == CS_PORT_UNAVAILABLE)) {
2370 2370 EL(ha, "login retry d_id=%xh\n", tq->d_id.b24);
2371 2371 if (tq->flags & TQF_FABRIC_DEVICE) {
2372 2372 rval = ql_login_fport(ha, tq, tq->loop_id,
2373 2373 LFF_NO_PLOGI, &mr);
2374 2374 if (rval != QL_SUCCESS) {
2375 2375 EL(ha, "failed, login_fport=%xh, "
2376 2376 "d_id=%xh\n", rval, tq->d_id.b24);
2377 2377 }
2378 2378 } else {
2379 2379 rval = ql_login_lport(ha, tq, tq->loop_id,
2380 2380 LLF_NONE);
2381 2381 if (rval != QL_SUCCESS) {
2382 2382 EL(ha, "failed, login_lport=%xh, "
2383 2383 "d_id=%xh\n", rval, tq->d_id.b24);
2384 2384 }
2385 2385 }
2386 2386 } else {
2387 2387 break;
2388 2388 }
2389 2389
2390 2390 bzero((caddr_t)pkt, sizeof (ql_mbx_iocb_t));
2391 2391
2392 2392 } while (retries--);
2393 2393
2394 2394 if (sts.comp_status == CS_LOOP_DOWN_ABORT) {
2395 2395 /* Cannot issue command now, maybe later */
2396 2396 EL(ha, "failed, suspended\n");
2397 2397 kmem_free(pkt, pkt_size);
2398 2398 ql_free_dma_resource(ha, dma_mem);
2399 2399 kmem_free(dma_mem, sizeof (dma_mem_t));
2400 2400 cmd->Status = EXT_STATUS_SUSPENDED;
2401 2401 cmd->ResponseLen = 0;
2402 2402 return;
2403 2403 }
2404 2404
2405 2405 if (status != QL_SUCCESS) {
2406 2406 /* Command error */
2407 2407 EL(ha, "failed, I/O\n");
2408 2408 kmem_free(pkt, pkt_size);
2409 2409 ql_free_dma_resource(ha, dma_mem);
2410 2410 kmem_free(dma_mem, sizeof (dma_mem_t));
2411 2411 cmd->Status = EXT_STATUS_ERR;
2412 2412 cmd->DetailStatus = status;
2413 2413 cmd->ResponseLen = 0;
2414 2414 return;
2415 2415 }
2416 2416
2417 2417 /* Setup status. */
2418 2418 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2419 2419 sts.scsi_status_l = pkt->sts24.scsi_status_l;
2420 2420 sts.scsi_status_h = pkt->sts24.scsi_status_h;
2421 2421
2422 2422 /* Setup residuals. */
2423 2423 sts.residual_length = LE_32(pkt->sts24.residual_length);
2424 2424
2425 2425 /* Setup state flags. */
2426 2426 sts.state_flags_l = pkt->sts24.state_flags_l;
2427 2427 sts.state_flags_h = pkt->sts24.state_flags_h;
2428 2428 if (pld_size && sts.comp_status != CS_DATA_UNDERRUN) {
2429 2429 sts.state_flags_h = (uint8_t)(sts.state_flags_h |
2430 2430 SF_GOT_BUS | SF_GOT_TARGET | SF_SENT_CMD |
2431 2431 SF_XFERRED_DATA | SF_GOT_STATUS);
2432 2432 } else {
2433 2433 sts.state_flags_h = (uint8_t)(sts.state_flags_h |
2434 2434 SF_GOT_BUS | SF_GOT_TARGET | SF_SENT_CMD |
2435 2435 SF_GOT_STATUS);
2436 2436 }
2437 2437 if (scsi_req.direction & CF_WR) {
2438 2438 sts.state_flags_l = (uint8_t)(sts.state_flags_l |
2439 2439 SF_DATA_OUT);
2440 2440 } else if (scsi_req.direction & CF_RD) {
2441 2441 sts.state_flags_l = (uint8_t)(sts.state_flags_l |
2442 2442 SF_DATA_IN);
2443 2443 }
2444 2444 sts.state_flags_l = (uint8_t)(sts.state_flags_l | SF_SIMPLE_Q);
2445 2445
2446 2446 /* Setup FCP response info. */
2447 2447 sts.rsp_info_length = sts.scsi_status_h & FCP_RSP_LEN_VALID ?
2448 2448 LE_32(pkt->sts24.fcp_rsp_data_length) : 0;
2449 2449 sts.rsp_info = &pkt->sts24.rsp_sense_data[0];
2450 2450 for (cnt = 0; cnt < sts.rsp_info_length;
2451 2451 cnt = (uint16_t)(cnt + 4)) {
2452 2452 ql_chg_endian(sts.rsp_info + cnt, 4);
2453 2453 }
2454 2454
2455 2455 /* Setup sense data. */
2456 2456 if (sts.scsi_status_h & FCP_SNS_LEN_VALID) {
2457 2457 sts.req_sense_length =
2458 2458 LE_32(pkt->sts24.fcp_sense_length);
2459 2459 sts.state_flags_h = (uint8_t)(sts.state_flags_h |
2460 2460 SF_ARQ_DONE);
2461 2461 } else {
2462 2462 sts.req_sense_length = 0;
2463 2463 }
2464 2464 sts.req_sense_data =
2465 2465 &pkt->sts24.rsp_sense_data[sts.rsp_info_length];
2466 2466 cnt2 = (uint16_t)(((uintptr_t)pkt + sizeof (sts_24xx_entry_t)) -
2467 2467 (uintptr_t)sts.req_sense_data);
2468 2468 for (cnt = 0; cnt < cnt2; cnt = (uint16_t)(cnt + 4)) {
2469 2469 ql_chg_endian(sts.req_sense_data + cnt, 4);
2470 2470 }
2471 2471 } else {
2472 2472 sts.scsi_status_l = pkt->sts.scsi_status_l;
2473 2473 sts.scsi_status_h = pkt->sts.scsi_status_h;
2474 2474
2475 2475 /* Setup residuals. */
2476 2476 sts.residual_length = LE_32(pkt->sts.residual_length);
2477 2477
2478 2478 /* Setup state flags. */
2479 2479 sts.state_flags_l = pkt->sts.state_flags_l;
2480 2480 sts.state_flags_h = pkt->sts.state_flags_h;
2481 2481
2482 2482 /* Setup FCP response info. */
2483 2483 sts.rsp_info_length = sts.scsi_status_h & FCP_RSP_LEN_VALID ?
2484 2484 LE_16(pkt->sts.rsp_info_length) : 0;
2485 2485 sts.rsp_info = &pkt->sts.rsp_info[0];
2486 2486
2487 2487 /* Setup sense data. */
2488 2488 sts.req_sense_length = sts.scsi_status_h & FCP_SNS_LEN_VALID ?
2489 2489 LE_16(pkt->sts.req_sense_length) : 0;
2490 2490 sts.req_sense_data = &pkt->sts.req_sense_data[0];
2491 2491 }
2492 2492
2493 2493 QL_PRINT_9(CE_CONT, "(%d): response pkt\n", ha->instance);
2494 2494 QL_DUMP_9(&pkt->sts, 8, sizeof (sts_entry_t));
2495 2495
2496 2496 switch (sts.comp_status) {
2497 2497 case CS_INCOMPLETE:
2498 2498 case CS_ABORTED:
2499 2499 case CS_DEVICE_UNAVAILABLE:
2500 2500 case CS_PORT_UNAVAILABLE:
2501 2501 case CS_PORT_LOGGED_OUT:
2502 2502 case CS_PORT_CONFIG_CHG:
2503 2503 case CS_PORT_BUSY:
2504 2504 case CS_LOOP_DOWN_ABORT:
2505 2505 cmd->Status = EXT_STATUS_BUSY;
2506 2506 break;
2507 2507 case CS_RESET:
2508 2508 case CS_QUEUE_FULL:
2509 2509 cmd->Status = EXT_STATUS_ERR;
2510 2510 break;
2511 2511 case CS_TIMEOUT:
2512 2512 cmd->Status = EXT_STATUS_ERR;
2513 2513 break;
2514 2514 case CS_DATA_OVERRUN:
2515 2515 cmd->Status = EXT_STATUS_DATA_OVERRUN;
2516 2516 break;
2517 2517 case CS_DATA_UNDERRUN:
2518 2518 cmd->Status = EXT_STATUS_DATA_UNDERRUN;
2519 2519 break;
2520 2520 }
2521 2521
2522 2522 /*
2523 2523 * If non data transfer commands fix tranfer counts.
2524 2524 */
2525 2525 if (scsi_req.cdbp[0] == SCMD_TEST_UNIT_READY ||
2526 2526 scsi_req.cdbp[0] == SCMD_REZERO_UNIT ||
2527 2527 scsi_req.cdbp[0] == SCMD_SEEK ||
2528 2528 scsi_req.cdbp[0] == SCMD_SEEK_G1 ||
2529 2529 scsi_req.cdbp[0] == SCMD_RESERVE ||
2530 2530 scsi_req.cdbp[0] == SCMD_RELEASE ||
2531 2531 scsi_req.cdbp[0] == SCMD_START_STOP ||
2532 2532 scsi_req.cdbp[0] == SCMD_DOORLOCK ||
2533 2533 scsi_req.cdbp[0] == SCMD_VERIFY ||
2534 2534 scsi_req.cdbp[0] == SCMD_WRITE_FILE_MARK ||
2535 2535 scsi_req.cdbp[0] == SCMD_VERIFY_G0 ||
2536 2536 scsi_req.cdbp[0] == SCMD_SPACE ||
2537 2537 scsi_req.cdbp[0] == SCMD_ERASE ||
2538 2538 (scsi_req.cdbp[0] == SCMD_FORMAT &&
2539 2539 (scsi_req.cdbp[1] & FPB_DATA) == 0)) {
2540 2540 /*
2541 2541 * Non data transfer command, clear sts_entry residual
2542 2542 * length.
2543 2543 */
2544 2544 sts.residual_length = 0;
2545 2545 cmd->ResponseLen = 0;
2546 2546 if (sts.comp_status == CS_DATA_UNDERRUN) {
2547 2547 sts.comp_status = CS_COMPLETE;
2548 2548 cmd->Status = EXT_STATUS_OK;
2549 2549 }
2550 2550 } else {
2551 2551 cmd->ResponseLen = pld_size;
2552 2552 }
2553 2553
2554 2554 /* Correct ISP completion status */
2555 2555 if (sts.comp_status == CS_COMPLETE && sts.scsi_status_l == 0 &&
2556 2556 (sts.scsi_status_h & FCP_RSP_MASK) == 0) {
2557 2557 QL_PRINT_9(CE_CONT, "(%d): Correct completion\n",
2558 2558 ha->instance);
2559 2559 scsi_req.resid = 0;
2560 2560 } else if (sts.comp_status == CS_DATA_UNDERRUN) {
2561 2561 QL_PRINT_9(CE_CONT, "(%d): Correct UNDERRUN\n",
2562 2562 ha->instance);
2563 2563 scsi_req.resid = sts.residual_length;
2564 2564 if (sts.scsi_status_h & FCP_RESID_UNDER) {
2565 2565 cmd->Status = (uint32_t)EXT_STATUS_OK;
2566 2566
2567 2567 cmd->ResponseLen = (uint32_t)
2568 2568 (pld_size - scsi_req.resid);
2569 2569 } else {
2570 2570 EL(ha, "failed, Transfer ERROR\n");
2571 2571 cmd->Status = EXT_STATUS_ERR;
2572 2572 cmd->ResponseLen = 0;
2573 2573 }
2574 2574 } else {
2575 2575 QL_PRINT_9(CE_CONT, "(%d): error d_id=%xh, comp_status=%xh, "
2576 2576 "scsi_status_h=%xh, scsi_status_l=%xh\n", ha->instance,
2577 2577 tq->d_id.b24, sts.comp_status, sts.scsi_status_h,
2578 2578 sts.scsi_status_l);
2579 2579
2580 2580 scsi_req.resid = pld_size;
2581 2581 /*
2582 2582 * Handle residual count on SCSI check
2583 2583 * condition.
2584 2584 *
2585 2585 * - If Residual Under / Over is set, use the
2586 2586 * Residual Transfer Length field in IOCB.
2587 2587 * - If Residual Under / Over is not set, and
2588 2588 * Transferred Data bit is set in State Flags
2589 2589 * field of IOCB, report residual value of 0
2590 2590 * (you may want to do this for tape
2591 2591 * Write-type commands only). This takes care
2592 2592 * of logical end of tape problem and does
2593 2593 * not break Unit Attention.
2594 2594 * - If Residual Under / Over is not set, and
2595 2595 * Transferred Data bit is not set in State
2596 2596 * Flags, report residual value equal to
2597 2597 * original data transfer length.
2598 2598 */
2599 2599 if (sts.scsi_status_l & STATUS_CHECK) {
2600 2600 cmd->Status = EXT_STATUS_SCSI_STATUS;
2601 2601 cmd->DetailStatus = sts.scsi_status_l;
2602 2602 if (sts.scsi_status_h &
2603 2603 (FCP_RESID_OVER | FCP_RESID_UNDER)) {
2604 2604 scsi_req.resid = sts.residual_length;
2605 2605 } else if (sts.state_flags_h &
2606 2606 STATE_XFERRED_DATA) {
2607 2607 scsi_req.resid = 0;
2608 2608 }
2609 2609 }
2610 2610 }
2611 2611
2612 2612 if (sts.scsi_status_l & STATUS_CHECK &&
2613 2613 sts.scsi_status_h & FCP_SNS_LEN_VALID &&
2614 2614 sts.req_sense_length) {
2615 2615 /*
2616 2616 * Check condition with vaild sense data flag set and sense
2617 2617 * length != 0
2618 2618 */
2619 2619 if (sts.req_sense_length > scsi_req.sense_length) {
2620 2620 sense_sz = scsi_req.sense_length;
2621 2621 } else {
2622 2622 sense_sz = sts.req_sense_length;
2623 2623 }
2624 2624
2625 2625 EL(ha, "failed, Check Condition Status, d_id=%xh\n",
2626 2626 tq->d_id.b24);
2627 2627 QL_DUMP_2(sts.req_sense_data, 8, sts.req_sense_length);
2628 2628
2629 2629 if (ddi_copyout(sts.req_sense_data, scsi_req.u_sense,
2630 2630 (size_t)sense_sz, mode) != 0) {
2631 2631 EL(ha, "failed, request sense ddi_copyout\n");
2632 2632 }
2633 2633
2634 2634 cmd->Status = EXT_STATUS_SCSI_STATUS;
2635 2635 cmd->DetailStatus = sts.scsi_status_l;
2636 2636 }
2637 2637
2638 2638 /* Copy response payload from DMA buffer to application. */
2639 2639 if (scsi_req.direction & (CF_RD | CF_DATA_IN) &&
2640 2640 cmd->ResponseLen != 0) {
2641 2641 QL_PRINT_9(CE_CONT, "(%d): Data Return resid=%lu, "
2642 2642 "byte_count=%u, ResponseLen=%xh\n", ha->instance,
2643 2643 scsi_req.resid, pld_size, cmd->ResponseLen);
2644 2644 QL_DUMP_9(pld, 8, cmd->ResponseLen);
2645 2645
2646 2646 /* Send response payload. */
2647 2647 if (ql_send_buffer_data(pld,
2648 2648 (caddr_t)(uintptr_t)cmd->ResponseAdr,
2649 2649 cmd->ResponseLen, mode) != cmd->ResponseLen) {
2650 2650 EL(ha, "failed, send_buffer_data\n");
2651 2651 cmd->Status = EXT_STATUS_COPY_ERR;
2652 2652 cmd->ResponseLen = 0;
2653 2653 }
2654 2654 }
2655 2655
2656 2656 if (cmd->Status != EXT_STATUS_OK) {
2657 2657 EL(ha, "failed, cmd->Status=%xh, comp_status=%xh, "
2658 2658 "d_id=%xh\n", cmd->Status, sts.comp_status, tq->d_id.b24);
2659 2659 } else {
2660 2660 /*EMPTY*/
2661 2661 QL_PRINT_9(CE_CONT, "(%d): done, ResponseLen=%d\n",
2662 2662 ha->instance, cmd->ResponseLen);
2663 2663 }
2664 2664
2665 2665 kmem_free(pkt, pkt_size);
2666 2666 ql_free_dma_resource(ha, dma_mem);
2667 2667 kmem_free(dma_mem, sizeof (dma_mem_t));
2668 2668 }
2669 2669
2670 2670 /*
2671 2671 * ql_wwpn_to_scsiaddr
2672 2672 *
2673 2673 * Input:
2674 2674 * ha: adapter state pointer.
2675 2675 * cmd: EXT_IOCTL cmd struct pointer.
2676 2676 * mode: flags.
2677 2677 *
2678 2678 * Context:
2679 2679 * Kernel context.
2680 2680 */
2681 2681 static void
2682 2682 ql_wwpn_to_scsiaddr(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
2683 2683 {
2684 2684 int status;
2685 2685 uint8_t wwpn[EXT_DEF_WWN_NAME_SIZE];
2686 2686 EXT_SCSI_ADDR *tmp_addr;
2687 2687 ql_tgt_t *tq;
2688 2688
2689 2689 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2690 2690
2691 2691 if (cmd->RequestLen != EXT_DEF_WWN_NAME_SIZE) {
2692 2692 /* Return error */
2693 2693 EL(ha, "incorrect RequestLen\n");
2694 2694 cmd->Status = EXT_STATUS_INVALID_PARAM;
2695 2695 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN;
2696 2696 return;
2697 2697 }
2698 2698
2699 2699 status = ddi_copyin((void*)(uintptr_t)cmd->RequestAdr, wwpn,
2700 2700 cmd->RequestLen, mode);
2701 2701
2702 2702 if (status != 0) {
2703 2703 cmd->Status = EXT_STATUS_COPY_ERR;
2704 2704 EL(ha, "failed, ddi_copyin\n");
2705 2705 return;
2706 2706 }
2707 2707
2708 2708 tq = ql_find_port(ha, wwpn, QLNT_PORT);
2709 2709
2710 2710 if (tq == NULL || tq->flags & TQF_INITIATOR_DEVICE) {
2711 2711 /* no matching device */
2712 2712 cmd->Status = EXT_STATUS_DEV_NOT_FOUND;
2713 2713 EL(ha, "failed, device not found\n");
2714 2714 return;
2715 2715 }
2716 2716
2717 2717 /* Copy out the IDs found. For now we can only return target ID. */
2718 2718 tmp_addr = (EXT_SCSI_ADDR *)(uintptr_t)cmd->ResponseAdr;
2719 2719
2720 2720 status = ddi_copyout((void *)wwpn, (void *)&tmp_addr->Target, 8, mode);
2721 2721
2722 2722 if (status != 0) {
2723 2723 cmd->Status = EXT_STATUS_COPY_ERR;
2724 2724 EL(ha, "failed, ddi_copyout\n");
2725 2725 } else {
2726 2726 cmd->Status = EXT_STATUS_OK;
2727 2727 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2728 2728 }
2729 2729 }
2730 2730
2731 2731 /*
2732 2732 * ql_host_idx
2733 2733 * Gets host order index.
2734 2734 *
2735 2735 * Input:
2736 2736 * ha: adapter state pointer.
2737 2737 * cmd: EXT_IOCTL cmd struct pointer.
2738 2738 * mode: flags.
2739 2739 *
2740 2740 * Returns:
2741 2741 * None, request status indicated in cmd->Status.
2742 2742 *
2743 2743 * Context:
2744 2744 * Kernel context.
2745 2745 */
2746 2746 static void
2747 2747 ql_host_idx(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
2748 2748 {
2749 2749 uint16_t idx;
2750 2750
2751 2751 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2752 2752
2753 2753 if (cmd->ResponseLen < sizeof (uint16_t)) {
2754 2754 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
2755 2755 cmd->DetailStatus = sizeof (uint16_t);
2756 2756 EL(ha, "failed, ResponseLen < Len=%xh\n", cmd->ResponseLen);
2757 2757 cmd->ResponseLen = 0;
2758 2758 return;
2759 2759 }
2760 2760
2761 2761 idx = (uint16_t)ha->instance;
2762 2762
2763 2763 if (ddi_copyout((void *)&idx, (void *)(uintptr_t)(cmd->ResponseAdr),
2764 2764 sizeof (uint16_t), mode) != 0) {
2765 2765 cmd->Status = EXT_STATUS_COPY_ERR;
2766 2766 cmd->ResponseLen = 0;
2767 2767 EL(ha, "failed, ddi_copyout\n");
2768 2768 } else {
2769 2769 cmd->ResponseLen = sizeof (uint16_t);
2770 2770 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2771 2771 }
2772 2772 }
2773 2773
2774 2774 /*
2775 2775 * ql_host_drvname
2776 2776 * Gets host driver name
2777 2777 *
2778 2778 * Input:
2779 2779 * ha: adapter state pointer.
2780 2780 * cmd: EXT_IOCTL cmd struct pointer.
2781 2781 * mode: flags.
2782 2782 *
2783 2783 * Returns:
2784 2784 * None, request status indicated in cmd->Status.
2785 2785 *
2786 2786 * Context:
2787 2787 * Kernel context.
2788 2788 */
2789 2789 static void
2790 2790 ql_host_drvname(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
2791 2791 {
2792 2792
2793 2793 char drvname[] = QL_NAME;
2794 2794 uint32_t qlnamelen;
2795 2795
2796 2796 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2797 2797
2798 2798 qlnamelen = (uint32_t)(strlen(QL_NAME)+1);
2799 2799
2800 2800 if (cmd->ResponseLen < qlnamelen) {
2801 2801 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
2802 2802 cmd->DetailStatus = qlnamelen;
2803 2803 EL(ha, "failed, ResponseLen: %xh, needed: %xh\n",
2804 2804 cmd->ResponseLen, qlnamelen);
2805 2805 cmd->ResponseLen = 0;
2806 2806 return;
2807 2807 }
2808 2808
2809 2809 if (ddi_copyout((void *)&drvname,
2810 2810 (void *)(uintptr_t)(cmd->ResponseAdr),
2811 2811 qlnamelen, mode) != 0) {
2812 2812 cmd->Status = EXT_STATUS_COPY_ERR;
2813 2813 cmd->ResponseLen = 0;
2814 2814 EL(ha, "failed, ddi_copyout\n");
2815 2815 } else {
2816 2816 cmd->ResponseLen = qlnamelen-1;
2817 2817 }
2818 2818
2819 2819 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2820 2820 }
2821 2821
2822 2822 /*
2823 2823 * ql_read_nvram
2824 2824 * Get NVRAM contents.
2825 2825 *
2826 2826 * Input:
2827 2827 * ha: adapter state pointer.
2828 2828 * cmd: EXT_IOCTL cmd struct pointer.
2829 2829 * mode: flags.
2830 2830 *
2831 2831 * Returns:
2832 2832 * None, request status indicated in cmd->Status.
2833 2833 *
2834 2834 * Context:
2835 2835 * Kernel context.
2836 2836 */
2837 2837 static void
2838 2838 ql_read_nvram(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
2839 2839 {
2840 2840
2841 2841 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2842 2842
2843 2843 if (cmd->ResponseLen < ha->nvram_cache->size) {
2844 2844 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
2845 2845 cmd->DetailStatus = ha->nvram_cache->size;
2846 2846 EL(ha, "failed, ResponseLen != NVRAM, Len=%xh\n",
2847 2847 cmd->ResponseLen);
2848 2848 cmd->ResponseLen = 0;
2849 2849 return;
2850 2850 }
2851 2851
2852 2852 /* Get NVRAM data. */
2853 2853 if (ql_nv_util_dump(ha, (void *)(uintptr_t)(cmd->ResponseAdr),
2854 2854 mode) != 0) {
2855 2855 cmd->Status = EXT_STATUS_COPY_ERR;
2856 2856 cmd->ResponseLen = 0;
2857 2857 EL(ha, "failed, copy error\n");
2858 2858 } else {
2859 2859 cmd->ResponseLen = ha->nvram_cache->size;
2860 2860 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2861 2861 }
2862 2862 }
2863 2863
2864 2864 /*
2865 2865 * ql_write_nvram
2866 2866 * Loads NVRAM contents.
2867 2867 *
2868 2868 * Input:
2869 2869 * ha: adapter state pointer.
2870 2870 * cmd: EXT_IOCTL cmd struct pointer.
2871 2871 * mode: flags.
2872 2872 *
2873 2873 * Returns:
2874 2874 * None, request status indicated in cmd->Status.
2875 2875 *
2876 2876 * Context:
2877 2877 * Kernel context.
2878 2878 */
2879 2879 static void
2880 2880 ql_write_nvram(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
2881 2881 {
2882 2882
2883 2883 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2884 2884
2885 2885 if (cmd->RequestLen < ha->nvram_cache->size) {
2886 2886 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
2887 2887 cmd->DetailStatus = ha->nvram_cache->size;
2888 2888 EL(ha, "failed, RequestLen != NVRAM, Len=%xh\n",
2889 2889 cmd->RequestLen);
2890 2890 return;
2891 2891 }
2892 2892
2893 2893 /* Load NVRAM data. */
2894 2894 if (ql_nv_util_load(ha, (void *)(uintptr_t)(cmd->RequestAdr),
2895 2895 mode) != 0) {
2896 2896 cmd->Status = EXT_STATUS_COPY_ERR;
2897 2897 EL(ha, "failed, copy error\n");
2898 2898 } else {
2899 2899 /*EMPTY*/
2900 2900 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2901 2901 }
2902 2902 }
2903 2903
2904 2904 /*
2905 2905 * ql_write_vpd
2906 2906 * Loads VPD contents.
2907 2907 *
2908 2908 * Input:
2909 2909 * ha: adapter state pointer.
2910 2910 * cmd: EXT_IOCTL cmd struct pointer.
2911 2911 * mode: flags.
2912 2912 *
2913 2913 * Returns:
2914 2914 * None, request status indicated in cmd->Status.
2915 2915 *
2916 2916 * Context:
2917 2917 * Kernel context.
2918 2918 */
2919 2919 static void
2920 2920 ql_write_vpd(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
2921 2921 {
2922 2922 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2923 2923
2924 2924 int32_t rval = 0;
2925 2925
2926 2926 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
2927 2927 cmd->Status = EXT_STATUS_INVALID_REQUEST;
2928 2928 EL(ha, "failed, invalid request for HBA\n");
2929 2929 return;
2930 2930 }
2931 2931
2932 2932 if (cmd->RequestLen < QL_24XX_VPD_SIZE) {
2933 2933 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
2934 2934 cmd->DetailStatus = QL_24XX_VPD_SIZE;
2935 2935 EL(ha, "failed, RequestLen != VPD len, len passed=%xh\n",
2936 2936 cmd->RequestLen);
2937 2937 return;
2938 2938 }
2939 2939
2940 2940 /* Load VPD data. */
2941 2941 if ((rval = ql_vpd_load(ha, (void *)(uintptr_t)(cmd->RequestAdr),
2942 2942 mode)) != 0) {
2943 2943 cmd->Status = EXT_STATUS_COPY_ERR;
2944 2944 cmd->DetailStatus = rval;
2945 2945 EL(ha, "failed, errno=%x\n", rval);
2946 2946 } else {
2947 2947 /*EMPTY*/
2948 2948 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2949 2949 }
2950 2950 }
2951 2951
2952 2952 /*
2953 2953 * ql_read_vpd
2954 2954 * Dumps VPD contents.
2955 2955 *
2956 2956 * Input:
2957 2957 * ha: adapter state pointer.
2958 2958 * cmd: EXT_IOCTL cmd struct pointer.
2959 2959 * mode: flags.
2960 2960 *
2961 2961 * Returns:
2962 2962 * None, request status indicated in cmd->Status.
2963 2963 *
2964 2964 * Context:
2965 2965 * Kernel context.
2966 2966 */
2967 2967 static void
2968 2968 ql_read_vpd(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
2969 2969 {
2970 2970 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2971 2971
2972 2972 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
2973 2973 cmd->Status = EXT_STATUS_INVALID_REQUEST;
2974 2974 EL(ha, "failed, invalid request for HBA\n");
2975 2975 return;
2976 2976 }
2977 2977
2978 2978 if (cmd->ResponseLen < QL_24XX_VPD_SIZE) {
2979 2979 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
2980 2980 cmd->DetailStatus = QL_24XX_VPD_SIZE;
2981 2981 EL(ha, "failed, ResponseLen < VPD len, len passed=%xh\n",
2982 2982 cmd->ResponseLen);
2983 2983 return;
2984 2984 }
2985 2985
2986 2986 /* Dump VPD data. */
2987 2987 if ((ql_vpd_dump(ha, (void *)(uintptr_t)(cmd->ResponseAdr),
2988 2988 mode)) != 0) {
2989 2989 cmd->Status = EXT_STATUS_COPY_ERR;
2990 2990 EL(ha, "failed,\n");
2991 2991 } else {
2992 2992 /*EMPTY*/
2993 2993 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2994 2994 }
2995 2995 }
2996 2996
2997 2997 /*
2998 2998 * ql_get_fcache
2999 2999 * Dumps flash cache contents.
3000 3000 *
3001 3001 * Input:
3002 3002 * ha: adapter state pointer.
3003 3003 * cmd: EXT_IOCTL cmd struct pointer.
3004 3004 * mode: flags.
3005 3005 *
3006 3006 * Returns:
3007 3007 * None, request status indicated in cmd->Status.
3008 3008 *
3009 3009 * Context:
3010 3010 * Kernel context.
3011 3011 */
3012 3012 static void
3013 3013 ql_get_fcache(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
3014 3014 {
3015 3015 uint32_t bsize, boff, types, cpsize, hsize;
3016 3016 ql_fcache_t *fptr;
3017 3017
3018 3018 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
3019 3019
3020 3020 CACHE_LOCK(ha);
3021 3021
3022 3022 if (ha->fcache == NULL) {
3023 3023 CACHE_UNLOCK(ha);
3024 3024 cmd->Status = EXT_STATUS_ERR;
3025 3025 EL(ha, "failed, adapter fcache not setup\n");
3026 3026 return;
3027 3027 }
3028 3028
3029 3029 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
3030 3030 bsize = 100;
3031 3031 } else {
3032 3032 bsize = 400;
3033 3033 }
3034 3034
3035 3035 if (cmd->ResponseLen < bsize) {
3036 3036 CACHE_UNLOCK(ha);
3037 3037 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
3038 3038 cmd->DetailStatus = bsize;
3039 3039 EL(ha, "failed, ResponseLen < %d, len passed=%xh\n",
3040 3040 bsize, cmd->ResponseLen);
3041 3041 return;
3042 3042 }
3043 3043
3044 3044 boff = 0;
3045 3045 bsize = 0;
3046 3046 fptr = ha->fcache;
3047 3047
3048 3048 /*
3049 3049 * For backwards compatibility, get one of each image type
3050 3050 */
3051 3051 types = (FTYPE_BIOS | FTYPE_FCODE | FTYPE_EFI);
3052 3052 while ((fptr != NULL) && (fptr->buf != NULL) && (types != 0)) {
3053 3053 /* Get the next image */
3054 3054 if ((fptr = ql_get_fbuf(ha->fcache, types)) != NULL) {
3055 3055
3056 3056 cpsize = (fptr->buflen < 100 ? fptr->buflen : 100);
3057 3057
3058 3058 if (ddi_copyout(fptr->buf,
3059 3059 (void *)(uintptr_t)(cmd->ResponseAdr + boff),
3060 3060 cpsize, mode) != 0) {
3061 3061 CACHE_UNLOCK(ha);
3062 3062 EL(ha, "ddicopy failed, done\n");
3063 3063 cmd->Status = EXT_STATUS_COPY_ERR;
3064 3064 cmd->DetailStatus = 0;
3065 3065 return;
3066 3066 }
3067 3067 boff += 100;
3068 3068 bsize += cpsize;
3069 3069 types &= ~(fptr->type);
3070 3070 }
3071 3071 }
3072 3072
3073 3073 /*
3074 3074 * Get the firmware image -- it needs to be last in the
3075 3075 * buffer at offset 300 for backwards compatibility. Also for
3076 3076 * backwards compatibility, the pci header is stripped off.
3077 3077 */
3078 3078 if ((fptr = ql_get_fbuf(ha->fcache, FTYPE_FW)) != NULL) {
3079 3079
3080 3080 hsize = sizeof (pci_header_t) + sizeof (pci_data_t);
3081 3081 if (hsize > fptr->buflen) {
3082 3082 CACHE_UNLOCK(ha);
3083 3083 EL(ha, "header size (%xh) exceeds buflen (%xh)\n",
3084 3084 hsize, fptr->buflen);
3085 3085 cmd->Status = EXT_STATUS_COPY_ERR;
3086 3086 cmd->DetailStatus = 0;
3087 3087 return;
3088 3088 }
3089 3089
3090 3090 cpsize = ((fptr->buflen - hsize) < 100 ?
3091 3091 fptr->buflen - hsize : 100);
3092 3092
3093 3093 if (ddi_copyout(fptr->buf+hsize,
3094 3094 (void *)(uintptr_t)(cmd->ResponseAdr + 300),
3095 3095 cpsize, mode) != 0) {
3096 3096 CACHE_UNLOCK(ha);
3097 3097 EL(ha, "fw ddicopy failed, done\n");
3098 3098 cmd->Status = EXT_STATUS_COPY_ERR;
3099 3099 cmd->DetailStatus = 0;
3100 3100 return;
3101 3101 }
3102 3102 bsize += 100;
3103 3103 }
3104 3104
3105 3105 CACHE_UNLOCK(ha);
3106 3106 cmd->Status = EXT_STATUS_OK;
3107 3107 cmd->DetailStatus = bsize;
3108 3108
3109 3109 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3110 3110 }
3111 3111
3112 3112 /*
3113 3113 * ql_get_fcache_ex
3114 3114 * Dumps flash cache contents.
3115 3115 *
3116 3116 * Input:
3117 3117 * ha: adapter state pointer.
3118 3118 * cmd: EXT_IOCTL cmd struct pointer.
3119 3119 * mode: flags.
3120 3120 *
3121 3121 * Returns:
3122 3122 * None, request status indicated in cmd->Status.
3123 3123 *
3124 3124 * Context:
3125 3125 * Kernel context.
3126 3126 */
3127 3127 static void
3128 3128 ql_get_fcache_ex(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
3129 3129 {
3130 3130 uint32_t bsize = 0;
3131 3131 uint32_t boff = 0;
3132 3132 ql_fcache_t *fptr;
3133 3133
3134 3134 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
3135 3135
3136 3136 CACHE_LOCK(ha);
3137 3137 if (ha->fcache == NULL) {
3138 3138 CACHE_UNLOCK(ha);
3139 3139 cmd->Status = EXT_STATUS_ERR;
3140 3140 EL(ha, "failed, adapter fcache not setup\n");
3141 3141 return;
3142 3142 }
3143 3143
3144 3144 /* Make sure user passed enough buffer space */
3145 3145 for (fptr = ha->fcache; fptr != NULL; fptr = fptr->next) {
3146 3146 bsize += FBUFSIZE;
3147 3147 }
3148 3148
3149 3149 if (cmd->ResponseLen < bsize) {
3150 3150 CACHE_UNLOCK(ha);
3151 3151 if (cmd->ResponseLen != 0) {
3152 3152 EL(ha, "failed, ResponseLen < %d, len passed=%xh\n",
3153 3153 bsize, cmd->ResponseLen);
3154 3154 }
3155 3155 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
3156 3156 cmd->DetailStatus = bsize;
3157 3157 return;
3158 3158 }
3159 3159
3160 3160 boff = 0;
3161 3161 fptr = ha->fcache;
3162 3162 while ((fptr != NULL) && (fptr->buf != NULL)) {
3163 3163 /* Get the next image */
3164 3164 if (ddi_copyout(fptr->buf,
3165 3165 (void *)(uintptr_t)(cmd->ResponseAdr + boff),
3166 3166 (fptr->buflen < FBUFSIZE ? fptr->buflen : FBUFSIZE),
3167 3167 mode) != 0) {
3168 3168 CACHE_UNLOCK(ha);
3169 3169 EL(ha, "failed, ddicopy at %xh, done\n", boff);
3170 3170 cmd->Status = EXT_STATUS_COPY_ERR;
3171 3171 cmd->DetailStatus = 0;
3172 3172 return;
3173 3173 }
3174 3174 boff += FBUFSIZE;
3175 3175 fptr = fptr->next;
3176 3176 }
3177 3177
3178 3178 CACHE_UNLOCK(ha);
3179 3179 cmd->Status = EXT_STATUS_OK;
3180 3180 cmd->DetailStatus = bsize;
3181 3181
3182 3182 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3183 3183 }
3184 3184
3185 3185 /*
3186 3186 * ql_read_flash
3187 3187 * Get flash contents.
3188 3188 *
3189 3189 * Input:
3190 3190 * ha: adapter state pointer.
3191 3191 * cmd: EXT_IOCTL cmd struct pointer.
3192 3192 * mode: flags.
3193 3193 *
3194 3194 * Returns:
3195 3195 * None, request status indicated in cmd->Status.
3196 3196 *
3197 3197 * Context:
3198 3198 * Kernel context.
3199 3199 */
3200 3200 static void
3201 3201 ql_read_flash(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
3202 3202 {
3203 3203 ql_xioctl_t *xp = ha->xioctl;
3204 3204
3205 3205 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
3206 3206
3207 3207 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
3208 3208 EL(ha, "ql_stall_driver failed\n");
3209 3209 cmd->Status = EXT_STATUS_BUSY;
3210 3210 cmd->DetailStatus = xp->fdesc.flash_size;
3211 3211 cmd->ResponseLen = 0;
3212 3212 return;
3213 3213 }
3214 3214
3215 3215 if (ql_setup_fcache(ha) != QL_SUCCESS) {
3216 3216 cmd->Status = EXT_STATUS_ERR;
3217 3217 cmd->DetailStatus = xp->fdesc.flash_size;
3218 3218 EL(ha, "failed, ResponseLen=%xh, flash size=%xh\n",
3219 3219 cmd->ResponseLen, xp->fdesc.flash_size);
3220 3220 cmd->ResponseLen = 0;
3221 3221 } else {
3222 3222 /* adjust read size to flash size */
3223 3223 if (cmd->ResponseLen > xp->fdesc.flash_size) {
3224 3224 EL(ha, "adjusting req=%xh, max=%xh\n",
3225 3225 cmd->ResponseLen, xp->fdesc.flash_size);
3226 3226 cmd->ResponseLen = xp->fdesc.flash_size;
3227 3227 }
3228 3228
3229 3229 /* Get flash data. */
3230 3230 if (ql_flash_fcode_dump(ha,
3231 3231 (void *)(uintptr_t)(cmd->ResponseAdr),
3232 3232 (size_t)(cmd->ResponseLen), 0, mode) != 0) {
3233 3233 cmd->Status = EXT_STATUS_COPY_ERR;
3234 3234 cmd->ResponseLen = 0;
3235 3235 EL(ha, "failed,\n");
3236 3236 }
3237 3237 }
3238 3238
3239 3239 /* Resume I/O */
3240 3240 if (CFG_IST(ha, CFG_CTRL_24258081)) {
3241 3241 ql_restart_driver(ha);
3242 3242 } else {
3243 3243 EL(ha, "isp_abort_needed for restart\n");
3244 3244 ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED,
3245 3245 DRIVER_STALL);
3246 3246 }
3247 3247
3248 3248 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3249 3249 }
3250 3250
3251 3251 /*
3252 3252 * ql_write_flash
3253 3253 * Loads flash contents.
3254 3254 *
3255 3255 * Input:
3256 3256 * ha: adapter state pointer.
3257 3257 * cmd: EXT_IOCTL cmd struct pointer.
3258 3258 * mode: flags.
3259 3259 *
3260 3260 * Returns:
3261 3261 * None, request status indicated in cmd->Status.
3262 3262 *
3263 3263 * Context:
3264 3264 * Kernel context.
3265 3265 */
3266 3266 static void
3267 3267 ql_write_flash(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
3268 3268 {
3269 3269 ql_xioctl_t *xp = ha->xioctl;
3270 3270
3271 3271 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
3272 3272
3273 3273 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
3274 3274 EL(ha, "ql_stall_driver failed\n");
3275 3275 cmd->Status = EXT_STATUS_BUSY;
3276 3276 cmd->DetailStatus = xp->fdesc.flash_size;
3277 3277 cmd->ResponseLen = 0;
3278 3278 return;
3279 3279 }
3280 3280
3281 3281 if (ql_setup_fcache(ha) != QL_SUCCESS) {
3282 3282 cmd->Status = EXT_STATUS_ERR;
3283 3283 cmd->DetailStatus = xp->fdesc.flash_size;
3284 3284 EL(ha, "failed, RequestLen=%xh, size=%xh\n",
3285 3285 cmd->RequestLen, xp->fdesc.flash_size);
3286 3286 cmd->ResponseLen = 0;
3287 3287 } else {
3288 3288 /* Load flash data. */
3289 3289 if (cmd->RequestLen > xp->fdesc.flash_size) {
3290 3290 cmd->Status = EXT_STATUS_ERR;
3291 3291 cmd->DetailStatus = xp->fdesc.flash_size;
3292 3292 EL(ha, "failed, RequestLen=%xh, flash size=%xh\n",
3293 3293 cmd->RequestLen, xp->fdesc.flash_size);
3294 3294 } else if (ql_flash_fcode_load(ha,
3295 3295 (void *)(uintptr_t)(cmd->RequestAdr),
3296 3296 (size_t)(cmd->RequestLen), mode) != 0) {
3297 3297 cmd->Status = EXT_STATUS_COPY_ERR;
3298 3298 EL(ha, "failed,\n");
3299 3299 }
3300 3300 }
3301 3301
3302 3302 /* Resume I/O */
3303 3303 if (CFG_IST(ha, CFG_CTRL_24258081)) {
3304 3304 ql_restart_driver(ha);
3305 3305 } else {
3306 3306 EL(ha, "isp_abort_needed for restart\n");
3307 3307 ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED,
3308 3308 DRIVER_STALL);
3309 3309 }
3310 3310
3311 3311 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3312 3312 }
3313 3313
3314 3314 /*
3315 3315 * ql_diagnostic_loopback
3316 3316 * Performs EXT_CC_LOOPBACK Command
3317 3317 *
3318 3318 * Input:
3319 3319 * ha: adapter state pointer.
3320 3320 * cmd: Local EXT_IOCTL cmd struct pointer.
3321 3321 * mode: flags.
3322 3322 *
3323 3323 * Returns:
3324 3324 * None, request status indicated in cmd->Status.
3325 3325 *
3326 3326 * Context:
3327 3327 * Kernel context.
3328 3328 */
3329 3329 static void
3330 3330 ql_diagnostic_loopback(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
3331 3331 {
3332 3332 EXT_LOOPBACK_REQ plbreq;
3333 3333 EXT_LOOPBACK_RSP plbrsp;
3334 3334 ql_mbx_data_t mr;
3335 3335 uint32_t rval;
3336 3336 caddr_t bp;
3337 3337 uint16_t opt;
3338 3338
3339 3339 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
3340 3340
3341 3341 /* Get loop back request. */
3342 3342 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr,
3343 3343 (void *)&plbreq, sizeof (EXT_LOOPBACK_REQ), mode) != 0) {
3344 3344 EL(ha, "failed, ddi_copyin\n");
3345 3345 cmd->Status = EXT_STATUS_COPY_ERR;
3346 3346 cmd->ResponseLen = 0;
3347 3347 return;
3348 3348 }
3349 3349
3350 3350 opt = (uint16_t)(plbreq.Options & MBC_LOOPBACK_POINT_MASK);
3351 3351
3352 3352 /* Check transfer length fits in buffer. */
3353 3353 if (plbreq.BufferLength < plbreq.TransferCount &&
3354 3354 plbreq.TransferCount < MAILBOX_BUFFER_SIZE) {
3355 3355 EL(ha, "failed, BufferLength=%d, xfercnt=%d, "
3356 3356 "mailbox_buffer_size=%d\n", plbreq.BufferLength,
3357 3357 plbreq.TransferCount, MAILBOX_BUFFER_SIZE);
3358 3358 cmd->Status = EXT_STATUS_INVALID_PARAM;
3359 3359 cmd->ResponseLen = 0;
3360 3360 return;
3361 3361 }
3362 3362
3363 3363 /* Allocate command memory. */
3364 3364 bp = kmem_zalloc(plbreq.TransferCount, KM_SLEEP);
3365 3365 if (bp == NULL) {
3366 3366 EL(ha, "failed, kmem_zalloc\n");
3367 3367 cmd->Status = EXT_STATUS_NO_MEMORY;
3368 3368 cmd->ResponseLen = 0;
3369 3369 return;
3370 3370 }
3371 3371
3372 3372 /* Get loopback data. */
3373 3373 if (ql_get_buffer_data((caddr_t)(uintptr_t)plbreq.BufferAddress,
3374 3374 bp, plbreq.TransferCount, mode) != plbreq.TransferCount) {
3375 3375 EL(ha, "failed, ddi_copyin-2\n");
3376 3376 kmem_free(bp, plbreq.TransferCount);
3377 3377 cmd->Status = EXT_STATUS_COPY_ERR;
3378 3378 cmd->ResponseLen = 0;
3379 3379 return;
3380 3380 }
3381 3381
3382 3382 if ((ha->task_daemon_flags & (QL_LOOP_TRANSITION | DRIVER_STALL)) ||
3383 3383 ql_stall_driver(ha, 0) != QL_SUCCESS) {
3384 3384 EL(ha, "failed, LOOP_NOT_READY\n");
3385 3385 kmem_free(bp, plbreq.TransferCount);
3386 3386 cmd->Status = EXT_STATUS_BUSY;
3387 3387 cmd->ResponseLen = 0;
3388 3388 return;
3389 3389 }
3390 3390
3391 3391 /* Shutdown IP. */
3392 3392 if (ha->flags & IP_INITIALIZED) {
3393 3393 (void) ql_shutdown_ip(ha);
3394 3394 }
3395 3395
3396 3396 /* determine topology so we can send the loopback or the echo */
3397 3397 /* Echo is supported on 2300's only and above */
3398 3398
3399 3399 if (CFG_IST(ha, CFG_CTRL_8081)) {
3400 3400 if (!(ha->task_daemon_flags & LOOP_DOWN) && opt ==
3401 3401 MBC_LOOPBACK_POINT_EXTERNAL) {
3402 3402 if (plbreq.TransferCount > 252) {
3403 3403 EL(ha, "transfer count (%d) > 252\n",
3404 3404 plbreq.TransferCount);
3405 3405 kmem_free(bp, plbreq.TransferCount);
3406 3406 cmd->Status = EXT_STATUS_INVALID_PARAM;
3407 3407 cmd->ResponseLen = 0;
3408 3408 return;
3409 3409 }
3410 3410 plbrsp.CommandSent = INT_DEF_LB_ECHO_CMD;
3411 3411 rval = ql_diag_echo(ha, 0, bp, plbreq.TransferCount,
3412 3412 MBC_ECHO_ELS, &mr);
3413 3413 } else {
3414 3414 if (CFG_IST(ha, CFG_CTRL_81XX)) {
3415 3415 (void) ql_set_loop_point(ha, opt);
3416 3416 }
3417 3417 plbrsp.CommandSent = INT_DEF_LB_LOOPBACK_CMD;
3418 3418 rval = ql_diag_loopback(ha, 0, bp, plbreq.TransferCount,
3419 3419 opt, plbreq.IterationCount, &mr);
3420 3420 if (CFG_IST(ha, CFG_CTRL_81XX)) {
3421 3421 (void) ql_set_loop_point(ha, 0);
3422 3422 }
3423 3423 }
3424 3424 } else {
3425 3425 if (!(ha->task_daemon_flags & LOOP_DOWN) &&
3426 3426 (ha->topology & QL_F_PORT) &&
3427 3427 ha->device_id >= 0x2300) {
3428 3428 QL_PRINT_9(CE_CONT, "(%d): F_PORT topology -- using "
3429 3429 "echo\n", ha->instance);
3430 3430 plbrsp.CommandSent = INT_DEF_LB_ECHO_CMD;
3431 3431 rval = ql_diag_echo(ha, 0, bp, plbreq.TransferCount,
3432 3432 (uint16_t)(CFG_IST(ha, CFG_CTRL_8081) ?
3433 3433 MBC_ECHO_ELS : MBC_ECHO_64BIT), &mr);
3434 3434 } else {
3435 3435 plbrsp.CommandSent = INT_DEF_LB_LOOPBACK_CMD;
3436 3436 rval = ql_diag_loopback(ha, 0, bp, plbreq.TransferCount,
3437 3437 opt, plbreq.IterationCount, &mr);
3438 3438 }
3439 3439 }
3440 3440
3441 3441 ql_restart_driver(ha);
3442 3442
3443 3443 /* Restart IP if it was shutdown. */
3444 3444 if (ha->flags & IP_ENABLED && !(ha->flags & IP_INITIALIZED)) {
3445 3445 (void) ql_initialize_ip(ha);
3446 3446 ql_isp_rcvbuf(ha);
3447 3447 }
3448 3448
3449 3449 if (rval != QL_SUCCESS) {
3450 3450 EL(ha, "failed, diagnostic_loopback_mbx=%xh\n", rval);
3451 3451 kmem_free(bp, plbreq.TransferCount);
3452 3452 cmd->Status = EXT_STATUS_MAILBOX;
3453 3453 cmd->DetailStatus = rval;
3454 3454 cmd->ResponseLen = 0;
3455 3455 return;
3456 3456 }
3457 3457
3458 3458 /* Return loopback data. */
3459 3459 if (ql_send_buffer_data(bp, (caddr_t)(uintptr_t)plbreq.BufferAddress,
3460 3460 plbreq.TransferCount, mode) != plbreq.TransferCount) {
3461 3461 EL(ha, "failed, ddi_copyout\n");
3462 3462 kmem_free(bp, plbreq.TransferCount);
3463 3463 cmd->Status = EXT_STATUS_COPY_ERR;
3464 3464 cmd->ResponseLen = 0;
3465 3465 return;
3466 3466 }
3467 3467 kmem_free(bp, plbreq.TransferCount);
3468 3468
3469 3469 /* Return loopback results. */
3470 3470 plbrsp.BufferAddress = plbreq.BufferAddress;
3471 3471 plbrsp.BufferLength = plbreq.TransferCount;
3472 3472 plbrsp.CompletionStatus = mr.mb[0];
3473 3473
3474 3474 if (plbrsp.CommandSent == INT_DEF_LB_ECHO_CMD) {
3475 3475 plbrsp.CrcErrorCount = 0;
3476 3476 plbrsp.DisparityErrorCount = 0;
3477 3477 plbrsp.FrameLengthErrorCount = 0;
3478 3478 plbrsp.IterationCountLastError = 0;
3479 3479 } else {
3480 3480 plbrsp.CrcErrorCount = mr.mb[1];
3481 3481 plbrsp.DisparityErrorCount = mr.mb[2];
3482 3482 plbrsp.FrameLengthErrorCount = mr.mb[3];
3483 3483 plbrsp.IterationCountLastError = (mr.mb[19] >> 16) | mr.mb[18];
3484 3484 }
3485 3485
3486 3486 rval = ddi_copyout((void *)&plbrsp,
3487 3487 (void *)(uintptr_t)cmd->ResponseAdr,
3488 3488 sizeof (EXT_LOOPBACK_RSP), mode);
3489 3489 if (rval != 0) {
3490 3490 EL(ha, "failed, ddi_copyout-2\n");
3491 3491 cmd->Status = EXT_STATUS_COPY_ERR;
3492 3492 cmd->ResponseLen = 0;
3493 3493 return;
3494 3494 }
3495 3495 cmd->ResponseLen = sizeof (EXT_LOOPBACK_RSP);
3496 3496
3497 3497 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3498 3498 }
3499 3499
3500 3500 /*
3501 3501 * ql_set_loop_point
3502 3502 * Setup loop point for port configuration.
3503 3503 *
3504 3504 * Input:
3505 3505 * ha: adapter state structure.
3506 3506 * opt: loop point option.
3507 3507 *
3508 3508 * Returns:
3509 3509 * ql local function return status code.
3510 3510 *
3511 3511 * Context:
3512 3512 * Kernel context.
3513 3513 */
3514 3514 static int
3515 3515 ql_set_loop_point(ql_adapter_state_t *ha, uint16_t opt)
3516 3516 {
3517 3517 ql_mbx_data_t mr;
3518 3518 int rval;
3519 3519 uint32_t timer;
3520 3520
3521 3521 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
3522 3522
3523 3523 /*
3524 3524 * We get the current port config, modify the loopback field and
3525 3525 * write it back out.
3526 3526 */
3527 3527 if ((rval = ql_get_port_config(ha, &mr)) != QL_SUCCESS) {
3528 3528 EL(ha, "get_port_config status=%xh\n", rval);
3529 3529 return (rval);
3530 3530 }
3531 3531 /*
3532 3532 * Set the loopback mode field while maintaining the others.
3533 3533 * Currently only internal or none are supported.
3534 3534 */
3535 3535 mr.mb[1] = (uint16_t)(mr.mb[1] &~LOOPBACK_MODE_FIELD_MASK);
3536 3536 if (opt == MBC_LOOPBACK_POINT_INTERNAL) {
3537 3537 mr.mb[1] = (uint16_t)(mr.mb[1] |
3538 3538 LOOPBACK_MODE(LOOPBACK_MODE_INTERNAL));
3539 3539 }
3540 3540 /*
3541 3541 * Changing the port configuration will cause the port state to cycle
3542 3542 * down and back up. The indication that this has happened is that
3543 3543 * the point to point flag gets set.
3544 3544 */
3545 3545 ADAPTER_STATE_LOCK(ha);
3546 3546 ha->flags &= ~POINT_TO_POINT;
3547 3547 ADAPTER_STATE_UNLOCK(ha);
3548 3548 if ((rval = ql_set_port_config(ha, &mr)) != QL_SUCCESS) {
3549 3549 EL(ha, "set_port_config status=%xh\n", rval);
3550 3550 }
3551 3551
3552 3552 /* wait for a while */
3553 3553 for (timer = opt ? 10 : 0; timer; timer--) {
3554 3554 if (ha->flags & POINT_TO_POINT) {
3555 3555 break;
3556 3556 }
3557 3557 /* Delay for 1000000 usec (1 second). */
3558 3558 ql_delay(ha, 1000000);
3559 3559 }
3560 3560
3561 3561 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3562 3562
3563 3563 return (rval);
3564 3564 }
3565 3565
3566 3566 /*
3567 3567 * ql_send_els_rnid
3568 3568 * IOCTL for extended link service RNID command.
3569 3569 *
3570 3570 * Input:
3571 3571 * ha: adapter state pointer.
3572 3572 * cmd: User space CT arguments pointer.
3573 3573 * mode: flags.
3574 3574 *
3575 3575 * Returns:
3576 3576 * None, request status indicated in cmd->Status.
3577 3577 *
3578 3578 * Context:
3579 3579 * Kernel context.
3580 3580 */
3581 3581 static void
3582 3582 ql_send_els_rnid(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
3583 3583 {
3584 3584 EXT_RNID_REQ tmp_rnid;
3585 3585 port_id_t tmp_fcid;
3586 3586 caddr_t tmp_buf, bptr;
3587 3587 uint32_t copy_len;
3588 3588 ql_tgt_t *tq;
3589 3589 EXT_RNID_DATA rnid_data;
3590 3590 uint32_t loop_ready_wait = 10 * 60 * 10;
3591 3591 int rval = 0;
3592 3592 uint32_t local_hba = 0;
3593 3593
3594 3594 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
3595 3595
3596 3596 if (DRIVER_SUSPENDED(ha)) {
3597 3597 EL(ha, "failed, LOOP_NOT_READY\n");
3598 3598 cmd->Status = EXT_STATUS_BUSY;
3599 3599 cmd->ResponseLen = 0;
3600 3600 return;
3601 3601 }
3602 3602
3603 3603 if (cmd->RequestLen != sizeof (EXT_RNID_REQ)) {
3604 3604 /* parameter error */
3605 3605 EL(ha, "failed, RequestLen < EXT_RNID_REQ, Len=%xh\n",
3606 3606 cmd->RequestLen);
3607 3607 cmd->Status = EXT_STATUS_INVALID_PARAM;
3608 3608 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN;
3609 3609 cmd->ResponseLen = 0;
3610 3610 return;
3611 3611 }
3612 3612
3613 3613 if (ddi_copyin((void*)(uintptr_t)cmd->RequestAdr,
3614 3614 &tmp_rnid, cmd->RequestLen, mode) != 0) {
3615 3615 EL(ha, "failed, ddi_copyin\n");
3616 3616 cmd->Status = EXT_STATUS_COPY_ERR;
3617 3617 cmd->ResponseLen = 0;
3618 3618 return;
3619 3619 }
3620 3620
3621 3621 /* Find loop ID of the device */
3622 3622 if (tmp_rnid.Addr.Type == EXT_DEF_TYPE_WWNN) {
3623 3623 bptr = CFG_IST(ha, CFG_CTRL_24258081) ?
3624 3624 (caddr_t)&ha->init_ctrl_blk.cb24.node_name :
3625 3625 (caddr_t)&ha->init_ctrl_blk.cb.node_name;
3626 3626 if (bcmp((void *)bptr, (void *)tmp_rnid.Addr.FcAddr.WWNN,
3627 3627 EXT_DEF_WWN_NAME_SIZE) == 0) {
3628 3628 local_hba = 1;
3629 3629 } else {
3630 3630 tq = ql_find_port(ha,
3631 3631 (uint8_t *)tmp_rnid.Addr.FcAddr.WWNN, QLNT_NODE);
3632 3632 }
3633 3633 } else if (tmp_rnid.Addr.Type == EXT_DEF_TYPE_WWPN) {
3634 3634 bptr = CFG_IST(ha, CFG_CTRL_24258081) ?
3635 3635 (caddr_t)&ha->init_ctrl_blk.cb24.port_name :
3636 3636 (caddr_t)&ha->init_ctrl_blk.cb.port_name;
3637 3637 if (bcmp((void *)bptr, (void *)tmp_rnid.Addr.FcAddr.WWPN,
3638 3638 EXT_DEF_WWN_NAME_SIZE) == 0) {
3639 3639 local_hba = 1;
3640 3640 } else {
3641 3641 tq = ql_find_port(ha,
3642 3642 (uint8_t *)tmp_rnid.Addr.FcAddr.WWPN, QLNT_PORT);
3643 3643 }
3644 3644 } else if (tmp_rnid.Addr.Type == EXT_DEF_TYPE_PORTID) {
3645 3645 /*
3646 3646 * Copy caller's d_id to tmp space.
3647 3647 */
3648 3648 bcopy(&tmp_rnid.Addr.FcAddr.Id[1], tmp_fcid.r.d_id,
3649 3649 EXT_DEF_PORTID_SIZE_ACTUAL);
3650 3650 BIG_ENDIAN_24(&tmp_fcid.r.d_id[0]);
3651 3651
3652 3652 if (bcmp((void *)&ha->d_id, (void *)tmp_fcid.r.d_id,
3653 3653 EXT_DEF_PORTID_SIZE_ACTUAL) == 0) {
3654 3654 local_hba = 1;
3655 3655 } else {
3656 3656 tq = ql_find_port(ha, (uint8_t *)tmp_fcid.r.d_id,
3657 3657 QLNT_PID);
3658 3658 }
3659 3659 }
3660 3660
3661 3661 /* Allocate memory for command. */
3662 3662 tmp_buf = kmem_zalloc(SEND_RNID_RSP_SIZE, KM_SLEEP);
3663 3663 if (tmp_buf == NULL) {
3664 3664 EL(ha, "failed, kmem_zalloc\n");
3665 3665 cmd->Status = EXT_STATUS_NO_MEMORY;
3666 3666 cmd->ResponseLen = 0;
3667 3667 return;
3668 3668 }
3669 3669
3670 3670 if (local_hba) {
3671 3671 rval = ql_get_rnid_params(ha, SEND_RNID_RSP_SIZE, tmp_buf);
3672 3672 if (rval != QL_SUCCESS) {
3673 3673 EL(ha, "failed, get_rnid_params_mbx=%xh\n", rval);
3674 3674 kmem_free(tmp_buf, SEND_RNID_RSP_SIZE);
3675 3675 cmd->Status = EXT_STATUS_ERR;
3676 3676 cmd->ResponseLen = 0;
3677 3677 return;
3678 3678 }
3679 3679
3680 3680 /* Save gotten RNID data. */
3681 3681 bcopy(tmp_buf, &rnid_data, sizeof (EXT_RNID_DATA));
3682 3682
3683 3683 /* Now build the Send RNID response */
3684 3684 tmp_buf[0] = (char)(EXT_DEF_RNID_DFORMAT_TOPO_DISC);
3685 3685 tmp_buf[1] = (2 * EXT_DEF_WWN_NAME_SIZE);
3686 3686 tmp_buf[2] = 0;
3687 3687 tmp_buf[3] = sizeof (EXT_RNID_DATA);
3688 3688
3689 3689 if (CFG_IST(ha, CFG_CTRL_24258081)) {
3690 3690 bcopy(ha->init_ctrl_blk.cb24.port_name, &tmp_buf[4],
3691 3691 EXT_DEF_WWN_NAME_SIZE);
3692 3692 bcopy(ha->init_ctrl_blk.cb24.node_name,
3693 3693 &tmp_buf[4 + EXT_DEF_WWN_NAME_SIZE],
3694 3694 EXT_DEF_WWN_NAME_SIZE);
3695 3695 } else {
3696 3696 bcopy(ha->init_ctrl_blk.cb.port_name, &tmp_buf[4],
3697 3697 EXT_DEF_WWN_NAME_SIZE);
3698 3698 bcopy(ha->init_ctrl_blk.cb.node_name,
3699 3699 &tmp_buf[4 + EXT_DEF_WWN_NAME_SIZE],
3700 3700 EXT_DEF_WWN_NAME_SIZE);
3701 3701 }
3702 3702
3703 3703 bcopy((uint8_t *)&rnid_data,
3704 3704 &tmp_buf[4 + 2 * EXT_DEF_WWN_NAME_SIZE],
3705 3705 sizeof (EXT_RNID_DATA));
3706 3706 } else {
3707 3707 if (tq == NULL) {
3708 3708 /* no matching device */
3709 3709 EL(ha, "failed, device not found\n");
3710 3710 kmem_free(tmp_buf, SEND_RNID_RSP_SIZE);
3711 3711 cmd->Status = EXT_STATUS_DEV_NOT_FOUND;
3712 3712 cmd->DetailStatus = EXT_DSTATUS_TARGET;
3713 3713 cmd->ResponseLen = 0;
3714 3714 return;
3715 3715 }
3716 3716
3717 3717 /* Send command */
3718 3718 rval = ql_send_rnid_els(ha, tq->loop_id,
3719 3719 (uint8_t)tmp_rnid.DataFormat, SEND_RNID_RSP_SIZE, tmp_buf);
3720 3720 if (rval != QL_SUCCESS) {
3721 3721 EL(ha, "failed, send_rnid_mbx=%xh, id=%xh\n",
3722 3722 rval, tq->loop_id);
3723 3723 while (LOOP_NOT_READY(ha)) {
3724 3724 ql_delay(ha, 100000);
3725 3725 if (loop_ready_wait-- == 0) {
3726 3726 EL(ha, "failed, loop not ready\n");
3727 3727 cmd->Status = EXT_STATUS_ERR;
3728 3728 cmd->ResponseLen = 0;
3729 3729 }
3730 3730 }
3731 3731 rval = ql_send_rnid_els(ha, tq->loop_id,
3732 3732 (uint8_t)tmp_rnid.DataFormat, SEND_RNID_RSP_SIZE,
3733 3733 tmp_buf);
3734 3734 if (rval != QL_SUCCESS) {
3735 3735 /* error */
3736 3736 EL(ha, "failed, send_rnid_mbx=%xh, id=%xh\n",
3737 3737 rval, tq->loop_id);
3738 3738 kmem_free(tmp_buf, SEND_RNID_RSP_SIZE);
3739 3739 cmd->Status = EXT_STATUS_ERR;
3740 3740 cmd->ResponseLen = 0;
3741 3741 return;
3742 3742 }
3743 3743 }
3744 3744 }
3745 3745
3746 3746 /* Copy the response */
3747 3747 copy_len = (cmd->ResponseLen > SEND_RNID_RSP_SIZE) ?
3748 3748 SEND_RNID_RSP_SIZE : cmd->ResponseLen;
3749 3749
3750 3750 if (ql_send_buffer_data(tmp_buf, (caddr_t)(uintptr_t)cmd->ResponseAdr,
3751 3751 copy_len, mode) != copy_len) {
3752 3752 cmd->Status = EXT_STATUS_COPY_ERR;
3753 3753 EL(ha, "failed, ddi_copyout\n");
3754 3754 } else {
3755 3755 cmd->ResponseLen = copy_len;
3756 3756 if (copy_len < SEND_RNID_RSP_SIZE) {
3757 3757 cmd->Status = EXT_STATUS_DATA_OVERRUN;
3758 3758 EL(ha, "failed, EXT_STATUS_DATA_OVERRUN\n");
3759 3759
3760 3760 } else if (cmd->ResponseLen > SEND_RNID_RSP_SIZE) {
3761 3761 cmd->Status = EXT_STATUS_DATA_UNDERRUN;
3762 3762 EL(ha, "failed, EXT_STATUS_DATA_UNDERRUN\n");
3763 3763 } else {
3764 3764 cmd->Status = EXT_STATUS_OK;
3765 3765 QL_PRINT_9(CE_CONT, "(%d): done\n",
3766 3766 ha->instance);
3767 3767 }
3768 3768 }
3769 3769
3770 3770 kmem_free(tmp_buf, SEND_RNID_RSP_SIZE);
3771 3771 }
3772 3772
3773 3773 /*
3774 3774 * ql_set_host_data
3775 3775 * Process IOCTL subcommand to set host/adapter related data.
3776 3776 *
3777 3777 * Input:
3778 3778 * ha: adapter state pointer.
3779 3779 * cmd: User space CT arguments pointer.
3780 3780 * mode: flags.
3781 3781 *
3782 3782 * Returns:
3783 3783 * None, request status indicated in cmd->Status.
3784 3784 *
3785 3785 * Context:
3786 3786 * Kernel context.
3787 3787 */
3788 3788 static void
3789 3789 ql_set_host_data(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
3790 3790 {
3791 3791 QL_PRINT_9(CE_CONT, "(%d): started, SubCode=%d\n", ha->instance,
3792 3792 cmd->SubCode);
3793 3793
3794 3794 /*
3795 3795 * case off on command subcode
3796 3796 */
3797 3797 switch (cmd->SubCode) {
3798 3798 case EXT_SC_SET_RNID:
3799 3799 ql_set_rnid_parameters(ha, cmd, mode);
3800 3800 break;
3801 3801 case EXT_SC_RST_STATISTICS:
3802 3802 (void) ql_reset_statistics(ha, cmd);
3803 3803 break;
3804 3804 case EXT_SC_SET_BEACON_STATE:
3805 3805 ql_set_led_state(ha, cmd, mode);
3806 3806 break;
3807 3807 case EXT_SC_SET_PARMS:
3808 3808 case EXT_SC_SET_BUS_MODE:
3809 3809 case EXT_SC_SET_DR_DUMP_BUF:
3810 3810 case EXT_SC_SET_RISC_CODE:
3811 3811 case EXT_SC_SET_FLASH_RAM:
3812 3812 case EXT_SC_SET_LUN_BITMASK:
3813 3813 case EXT_SC_SET_RETRY_CNT:
3814 3814 case EXT_SC_SET_RTIN:
3815 3815 case EXT_SC_SET_FC_LUN_BITMASK:
3816 3816 case EXT_SC_ADD_TARGET_DEVICE:
3817 3817 case EXT_SC_SWAP_TARGET_DEVICE:
3818 3818 case EXT_SC_SET_SEL_TIMEOUT:
3819 3819 default:
3820 3820 /* function not supported. */
3821 3821 EL(ha, "failed, function not supported=%d\n", cmd->SubCode);
3822 3822 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE;
3823 3823 break;
3824 3824 }
3825 3825
3826 3826 if (cmd->Status != EXT_STATUS_OK) {
3827 3827 EL(ha, "failed, Status=%d\n", cmd->Status);
3828 3828 } else {
3829 3829 /*EMPTY*/
3830 3830 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3831 3831 }
3832 3832 }
3833 3833
3834 3834 /*
3835 3835 * ql_get_host_data
3836 3836 * Performs EXT_CC_GET_DATA subcommands.
3837 3837 *
3838 3838 * Input:
3839 3839 * ha: adapter state pointer.
3840 3840 * cmd: Local EXT_IOCTL cmd struct pointer.
3841 3841 * mode: flags.
3842 3842 *
3843 3843 * Returns:
3844 3844 * None, request status indicated in cmd->Status.
3845 3845 *
3846 3846 * Context:
3847 3847 * Kernel context.
3848 3848 */
3849 3849 static void
3850 3850 ql_get_host_data(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
3851 3851 {
3852 3852 int out_size = 0;
3853 3853
3854 3854 QL_PRINT_9(CE_CONT, "(%d): started, SubCode=%d\n", ha->instance,
3855 3855 cmd->SubCode);
3856 3856
3857 3857 /* case off on command subcode */
3858 3858 switch (cmd->SubCode) {
3859 3859 case EXT_SC_GET_STATISTICS:
3860 3860 out_size = sizeof (EXT_HBA_PORT_STAT);
3861 3861 break;
3862 3862 case EXT_SC_GET_FC_STATISTICS:
3863 3863 out_size = sizeof (EXT_HBA_PORT_STAT);
3864 3864 break;
3865 3865 case EXT_SC_GET_PORT_SUMMARY:
3866 3866 out_size = sizeof (EXT_DEVICEDATA);
3867 3867 break;
3868 3868 case EXT_SC_GET_RNID:
3869 3869 out_size = sizeof (EXT_RNID_DATA);
3870 3870 break;
3871 3871 case EXT_SC_GET_TARGET_ID:
3872 3872 out_size = sizeof (EXT_DEST_ADDR);
3873 3873 break;
3874 3874 case EXT_SC_GET_BEACON_STATE:
3875 3875 out_size = sizeof (EXT_BEACON_CONTROL);
3876 3876 break;
3877 3877 case EXT_SC_GET_FC4_STATISTICS:
3878 3878 out_size = sizeof (EXT_HBA_FC4STATISTICS);
3879 3879 break;
3880 3880 case EXT_SC_GET_DCBX_PARAM:
3881 3881 out_size = EXT_DEF_DCBX_PARAM_BUF_SIZE;
3882 3882 break;
3883 3883 case EXT_SC_GET_RESOURCE_CNTS:
3884 3884 out_size = sizeof (EXT_RESOURCE_CNTS);
3885 3885 break;
3886 3886 case EXT_SC_GET_FCF_LIST:
3887 3887 out_size = sizeof (EXT_FCF_LIST);
3888 3888 break;
3889 3889 case EXT_SC_GET_SCSI_ADDR:
3890 3890 case EXT_SC_GET_ERR_DETECTIONS:
3891 3891 case EXT_SC_GET_BUS_MODE:
3892 3892 case EXT_SC_GET_DR_DUMP_BUF:
3893 3893 case EXT_SC_GET_RISC_CODE:
3894 3894 case EXT_SC_GET_FLASH_RAM:
3895 3895 case EXT_SC_GET_LINK_STATUS:
3896 3896 case EXT_SC_GET_LOOP_ID:
3897 3897 case EXT_SC_GET_LUN_BITMASK:
3898 3898 case EXT_SC_GET_PORT_DATABASE:
3899 3899 case EXT_SC_GET_PORT_DATABASE_MEM:
3900 3900 case EXT_SC_GET_POSITION_MAP:
3901 3901 case EXT_SC_GET_RETRY_CNT:
3902 3902 case EXT_SC_GET_RTIN:
3903 3903 case EXT_SC_GET_FC_LUN_BITMASK:
3904 3904 case EXT_SC_GET_SEL_TIMEOUT:
3905 3905 default:
3906 3906 /* function not supported. */
3907 3907 EL(ha, "failed, function not supported=%d\n", cmd->SubCode);
3908 3908 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE;
3909 3909 cmd->ResponseLen = 0;
3910 3910 return;
3911 3911 }
3912 3912
3913 3913 if (cmd->ResponseLen < out_size) {
3914 3914 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
3915 3915 cmd->DetailStatus = out_size;
3916 3916 EL(ha, "failed, ResponseLen=%xh, size=%xh\n",
3917 3917 cmd->ResponseLen, out_size);
3918 3918 cmd->ResponseLen = 0;
3919 3919 return;
3920 3920 }
3921 3921
3922 3922 switch (cmd->SubCode) {
3923 3923 case EXT_SC_GET_RNID:
3924 3924 ql_get_rnid_parameters(ha, cmd, mode);
3925 3925 break;
3926 3926 case EXT_SC_GET_STATISTICS:
3927 3927 ql_get_statistics(ha, cmd, mode);
3928 3928 break;
3929 3929 case EXT_SC_GET_FC_STATISTICS:
3930 3930 ql_get_statistics_fc(ha, cmd, mode);
3931 3931 break;
3932 3932 case EXT_SC_GET_FC4_STATISTICS:
3933 3933 ql_get_statistics_fc4(ha, cmd, mode);
3934 3934 break;
3935 3935 case EXT_SC_GET_PORT_SUMMARY:
3936 3936 ql_get_port_summary(ha, cmd, mode);
3937 3937 break;
3938 3938 case EXT_SC_GET_TARGET_ID:
3939 3939 ql_get_target_id(ha, cmd, mode);
3940 3940 break;
3941 3941 case EXT_SC_GET_BEACON_STATE:
3942 3942 ql_get_led_state(ha, cmd, mode);
3943 3943 break;
3944 3944 case EXT_SC_GET_DCBX_PARAM:
3945 3945 ql_get_dcbx_parameters(ha, cmd, mode);
3946 3946 break;
3947 3947 case EXT_SC_GET_FCF_LIST:
3948 3948 ql_get_fcf_list(ha, cmd, mode);
3949 3949 break;
3950 3950 case EXT_SC_GET_RESOURCE_CNTS:
3951 3951 ql_get_resource_counts(ha, cmd, mode);
3952 3952 break;
3953 3953 }
3954 3954
3955 3955 if (cmd->Status != EXT_STATUS_OK) {
3956 3956 EL(ha, "failed, Status=%d\n", cmd->Status);
3957 3957 } else {
3958 3958 /*EMPTY*/
3959 3959 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3960 3960 }
3961 3961 }
3962 3962
3963 3963 /* ******************************************************************** */
3964 3964 /* Helper Functions */
3965 3965 /* ******************************************************************** */
3966 3966
3967 3967 /*
3968 3968 * ql_lun_count
3969 3969 * Get numbers of LUNS on target.
3970 3970 *
3971 3971 * Input:
3972 3972 * ha: adapter state pointer.
3973 3973 * q: device queue pointer.
3974 3974 *
3975 3975 * Returns:
3976 3976 * Number of LUNs.
3977 3977 *
3978 3978 * Context:
3979 3979 * Kernel context.
3980 3980 */
3981 3981 static int
3982 3982 ql_lun_count(ql_adapter_state_t *ha, ql_tgt_t *tq)
3983 3983 {
3984 3984 int cnt;
3985 3985
3986 3986 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
3987 3987
3988 3988 /* Bypass LUNs that failed. */
3989 3989 cnt = ql_report_lun(ha, tq);
3990 3990 if (cnt == 0) {
3991 3991 cnt = ql_inq_scan(ha, tq, ha->maximum_luns_per_target);
3992 3992 }
3993 3993
3994 3994 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3995 3995
3996 3996 return (cnt);
3997 3997 }
3998 3998
3999 3999 /*
4000 4000 * ql_report_lun
4001 4001 * Get numbers of LUNS using report LUN command.
4002 4002 *
4003 4003 * Input:
4004 4004 * ha: adapter state pointer.
4005 4005 * q: target queue pointer.
4006 4006 *
4007 4007 * Returns:
4008 4008 * Number of LUNs.
4009 4009 *
4010 4010 * Context:
4011 4011 * Kernel context.
4012 4012 */
4013 4013 static int
4014 4014 ql_report_lun(ql_adapter_state_t *ha, ql_tgt_t *tq)
4015 4015 {
4016 4016 int rval;
4017 4017 uint8_t retries;
4018 4018 ql_mbx_iocb_t *pkt;
4019 4019 ql_rpt_lun_lst_t *rpt;
4020 4020 dma_mem_t dma_mem;
4021 4021 uint32_t pkt_size, cnt;
4022 4022 uint16_t comp_status;
4023 4023 uint8_t scsi_status_h, scsi_status_l, *reqs;
4024 4024
4025 4025 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
4026 4026
4027 4027 if (DRIVER_SUSPENDED(ha)) {
4028 4028 EL(ha, "failed, LOOP_NOT_READY\n");
4029 4029 return (0);
4030 4030 }
4031 4031
4032 4032 pkt_size = sizeof (ql_mbx_iocb_t) + sizeof (ql_rpt_lun_lst_t);
4033 4033 pkt = kmem_zalloc(pkt_size, KM_SLEEP);
4034 4034 if (pkt == NULL) {
4035 4035 EL(ha, "failed, kmem_zalloc\n");
4036 4036 return (0);
4037 4037 }
4038 4038 rpt = (ql_rpt_lun_lst_t *)((caddr_t)pkt + sizeof (ql_mbx_iocb_t));
4039 4039
4040 4040 /* Get DMA memory for the IOCB */
4041 4041 if (ql_get_dma_mem(ha, &dma_mem, sizeof (ql_rpt_lun_lst_t),
4042 4042 LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN) != QL_SUCCESS) {
4043 4043 cmn_err(CE_WARN, "%s(%d): DMA memory "
4044 4044 "alloc failed", QL_NAME, ha->instance);
4045 4045 kmem_free(pkt, pkt_size);
4046 4046 return (0);
4047 4047 }
4048 4048
4049 4049 for (retries = 0; retries < 4; retries++) {
4050 4050 if (CFG_IST(ha, CFG_CTRL_24258081)) {
4051 4051 pkt->cmd24.entry_type = IOCB_CMD_TYPE_7;
4052 4052 pkt->cmd24.entry_count = 1;
4053 4053
4054 4054 /* Set N_port handle */
4055 4055 pkt->cmd24.n_port_hdl = (uint16_t)LE_16(tq->loop_id);
4056 4056
4057 4057 /* Set target ID */
4058 4058 pkt->cmd24.target_id[0] = tq->d_id.b.al_pa;
4059 4059 pkt->cmd24.target_id[1] = tq->d_id.b.area;
4060 4060 pkt->cmd24.target_id[2] = tq->d_id.b.domain;
4061 4061
4062 4062 /* Set Virtual Port ID */
4063 4063 pkt->cmd24.vp_index = ha->vp_index;
4064 4064
4065 4065 /* Set ISP command timeout. */
4066 4066 pkt->cmd24.timeout = LE_16(15);
4067 4067
4068 4068 /* Load SCSI CDB */
4069 4069 pkt->cmd24.scsi_cdb[0] = SCMD_REPORT_LUNS;
4070 4070 pkt->cmd24.scsi_cdb[6] =
4071 4071 MSB(MSW(sizeof (ql_rpt_lun_lst_t)));
4072 4072 pkt->cmd24.scsi_cdb[7] =
4073 4073 LSB(MSW(sizeof (ql_rpt_lun_lst_t)));
4074 4074 pkt->cmd24.scsi_cdb[8] =
4075 4075 MSB(LSW(sizeof (ql_rpt_lun_lst_t)));
4076 4076 pkt->cmd24.scsi_cdb[9] =
4077 4077 LSB(LSW(sizeof (ql_rpt_lun_lst_t)));
4078 4078 for (cnt = 0; cnt < MAX_CMDSZ; cnt += 4) {
4079 4079 ql_chg_endian((uint8_t *)&pkt->cmd24.scsi_cdb
4080 4080 + cnt, 4);
4081 4081 }
4082 4082
4083 4083 /* Set tag queue control flags */
4084 4084 pkt->cmd24.task = TA_STAG;
4085 4085
4086 4086 /* Set transfer direction. */
4087 4087 pkt->cmd24.control_flags = CF_RD;
4088 4088
4089 4089 /* Set data segment count. */
4090 4090 pkt->cmd24.dseg_count = LE_16(1);
4091 4091
4092 4092 /* Load total byte count. */
4093 4093 /* Load data descriptor. */
4094 4094 pkt->cmd24.dseg_0_address[0] = (uint32_t)
4095 4095 LE_32(LSD(dma_mem.cookie.dmac_laddress));
4096 4096 pkt->cmd24.dseg_0_address[1] = (uint32_t)
4097 4097 LE_32(MSD(dma_mem.cookie.dmac_laddress));
4098 4098 pkt->cmd24.total_byte_count =
4099 4099 LE_32(sizeof (ql_rpt_lun_lst_t));
4100 4100 pkt->cmd24.dseg_0_length =
4101 4101 LE_32(sizeof (ql_rpt_lun_lst_t));
4102 4102 } else if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
4103 4103 pkt->cmd3.entry_type = IOCB_CMD_TYPE_3;
4104 4104 pkt->cmd3.entry_count = 1;
4105 4105 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
4106 4106 pkt->cmd3.target_l = LSB(tq->loop_id);
4107 4107 pkt->cmd3.target_h = MSB(tq->loop_id);
4108 4108 } else {
4109 4109 pkt->cmd3.target_h = LSB(tq->loop_id);
4110 4110 }
4111 4111 pkt->cmd3.control_flags_l = CF_DATA_IN | CF_STAG;
4112 4112 pkt->cmd3.timeout = LE_16(15);
4113 4113 pkt->cmd3.dseg_count = LE_16(1);
4114 4114 pkt->cmd3.scsi_cdb[0] = SCMD_REPORT_LUNS;
4115 4115 pkt->cmd3.scsi_cdb[6] =
4116 4116 MSB(MSW(sizeof (ql_rpt_lun_lst_t)));
4117 4117 pkt->cmd3.scsi_cdb[7] =
4118 4118 LSB(MSW(sizeof (ql_rpt_lun_lst_t)));
4119 4119 pkt->cmd3.scsi_cdb[8] =
4120 4120 MSB(LSW(sizeof (ql_rpt_lun_lst_t)));
4121 4121 pkt->cmd3.scsi_cdb[9] =
4122 4122 LSB(LSW(sizeof (ql_rpt_lun_lst_t)));
4123 4123 pkt->cmd3.byte_count =
4124 4124 LE_32(sizeof (ql_rpt_lun_lst_t));
4125 4125 pkt->cmd3.dseg_0_address[0] = (uint32_t)
4126 4126 LE_32(LSD(dma_mem.cookie.dmac_laddress));
4127 4127 pkt->cmd3.dseg_0_address[1] = (uint32_t)
4128 4128 LE_32(MSD(dma_mem.cookie.dmac_laddress));
4129 4129 pkt->cmd3.dseg_0_length =
4130 4130 LE_32(sizeof (ql_rpt_lun_lst_t));
4131 4131 } else {
4132 4132 pkt->cmd.entry_type = IOCB_CMD_TYPE_2;
4133 4133 pkt->cmd.entry_count = 1;
4134 4134 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
4135 4135 pkt->cmd.target_l = LSB(tq->loop_id);
4136 4136 pkt->cmd.target_h = MSB(tq->loop_id);
4137 4137 } else {
4138 4138 pkt->cmd.target_h = LSB(tq->loop_id);
4139 4139 }
4140 4140 pkt->cmd.control_flags_l = CF_DATA_IN | CF_STAG;
4141 4141 pkt->cmd.timeout = LE_16(15);
4142 4142 pkt->cmd.dseg_count = LE_16(1);
4143 4143 pkt->cmd.scsi_cdb[0] = SCMD_REPORT_LUNS;
4144 4144 pkt->cmd.scsi_cdb[6] =
4145 4145 MSB(MSW(sizeof (ql_rpt_lun_lst_t)));
4146 4146 pkt->cmd.scsi_cdb[7] =
4147 4147 LSB(MSW(sizeof (ql_rpt_lun_lst_t)));
4148 4148 pkt->cmd.scsi_cdb[8] =
4149 4149 MSB(LSW(sizeof (ql_rpt_lun_lst_t)));
4150 4150 pkt->cmd.scsi_cdb[9] =
4151 4151 LSB(LSW(sizeof (ql_rpt_lun_lst_t)));
4152 4152 pkt->cmd.byte_count =
4153 4153 LE_32(sizeof (ql_rpt_lun_lst_t));
4154 4154 pkt->cmd.dseg_0_address = (uint32_t)
4155 4155 LE_32(LSD(dma_mem.cookie.dmac_laddress));
4156 4156 pkt->cmd.dseg_0_length =
4157 4157 LE_32(sizeof (ql_rpt_lun_lst_t));
4158 4158 }
4159 4159
4160 4160 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt,
4161 4161 sizeof (ql_mbx_iocb_t));
4162 4162
4163 4163 /* Sync in coming DMA buffer. */
4164 4164 (void) ddi_dma_sync(dma_mem.dma_handle, 0, dma_mem.size,
4165 4165 DDI_DMA_SYNC_FORKERNEL);
4166 4166 /* Copy in coming DMA data. */
4167 4167 ddi_rep_get8(dma_mem.acc_handle, (uint8_t *)rpt,
4168 4168 (uint8_t *)dma_mem.bp, dma_mem.size, DDI_DEV_AUTOINCR);
4169 4169
4170 4170 if (CFG_IST(ha, CFG_CTRL_24258081)) {
4171 4171 pkt->sts24.entry_status = (uint8_t)
4172 4172 (pkt->sts24.entry_status & 0x3c);
4173 4173 comp_status = (uint16_t)LE_16(pkt->sts24.comp_status);
4174 4174 scsi_status_h = pkt->sts24.scsi_status_h;
4175 4175 scsi_status_l = pkt->sts24.scsi_status_l;
4176 4176 cnt = scsi_status_h & FCP_RSP_LEN_VALID ?
4177 4177 LE_32(pkt->sts24.fcp_rsp_data_length) : 0;
4178 4178 reqs = &pkt->sts24.rsp_sense_data[cnt];
4179 4179 } else {
4180 4180 pkt->sts.entry_status = (uint8_t)
4181 4181 (pkt->sts.entry_status & 0x7e);
4182 4182 comp_status = (uint16_t)LE_16(pkt->sts.comp_status);
4183 4183 scsi_status_h = pkt->sts.scsi_status_h;
4184 4184 scsi_status_l = pkt->sts.scsi_status_l;
4185 4185 reqs = &pkt->sts.req_sense_data[0];
4186 4186 }
4187 4187 if (rval == QL_SUCCESS && pkt->sts.entry_status != 0) {
4188 4188 EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
4189 4189 pkt->sts.entry_status, tq->d_id.b24);
4190 4190 rval = QL_FUNCTION_PARAMETER_ERROR;
4191 4191 }
4192 4192
4193 4193 if (rval != QL_SUCCESS || comp_status != CS_COMPLETE ||
4194 4194 scsi_status_l & STATUS_CHECK) {
4195 4195 /* Device underrun, treat as OK. */
4196 4196 if (rval == QL_SUCCESS &&
4197 4197 comp_status == CS_DATA_UNDERRUN &&
4198 4198 scsi_status_h & FCP_RESID_UNDER) {
4199 4199 break;
4200 4200 }
4201 4201
4202 4202 EL(ha, "failed, issue_iocb=%xh, d_id=%xh, cs=%xh, "
4203 4203 "ss_h=%xh, ss_l=%xh\n", rval, tq->d_id.b24,
4204 4204 comp_status, scsi_status_h, scsi_status_l);
4205 4205
4206 4206 if (rval == QL_SUCCESS) {
4207 4207 if ((comp_status == CS_TIMEOUT) ||
4208 4208 (comp_status == CS_PORT_UNAVAILABLE) ||
4209 4209 (comp_status == CS_PORT_LOGGED_OUT)) {
4210 4210 rval = QL_FUNCTION_TIMEOUT;
4211 4211 break;
4212 4212 }
4213 4213 rval = QL_FUNCTION_FAILED;
4214 4214 } else if (rval == QL_ABORTED) {
4215 4215 break;
4216 4216 }
4217 4217
4218 4218 if (scsi_status_l & STATUS_CHECK) {
4219 4219 EL(ha, "STATUS_CHECK Sense Data\n%2xh%3xh"
4220 4220 "%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh"
4221 4221 "%3xh%3xh%3xh%3xh%3xh%3xh%3xh\n", reqs[0],
4222 4222 reqs[1], reqs[2], reqs[3], reqs[4],
4223 4223 reqs[5], reqs[6], reqs[7], reqs[8],
4224 4224 reqs[9], reqs[10], reqs[11], reqs[12],
4225 4225 reqs[13], reqs[14], reqs[15], reqs[16],
4226 4226 reqs[17]);
4227 4227 }
4228 4228 } else {
4229 4229 break;
4230 4230 }
4231 4231 bzero((caddr_t)pkt, pkt_size);
4232 4232 }
4233 4233
4234 4234 if (rval != QL_SUCCESS) {
4235 4235 EL(ha, "failed=%xh\n", rval);
4236 4236 rval = 0;
4237 4237 } else {
4238 4238 QL_PRINT_9(CE_CONT, "(%d): LUN list\n", ha->instance);
4239 4239 QL_DUMP_9(rpt, 8, rpt->hdr.len + 8);
4240 4240 rval = (int)(BE_32(rpt->hdr.len) / 8);
4241 4241 }
4242 4242
4243 4243 kmem_free(pkt, pkt_size);
4244 4244 ql_free_dma_resource(ha, &dma_mem);
4245 4245
4246 4246 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
4247 4247
4248 4248 return (rval);
4249 4249 }
4250 4250
4251 4251 /*
4252 4252 * ql_inq_scan
4253 4253 * Get numbers of LUNS using inquiry command.
4254 4254 *
4255 4255 * Input:
4256 4256 * ha: adapter state pointer.
4257 4257 * tq: target queue pointer.
4258 4258 * count: scan for the number of existing LUNs.
4259 4259 *
4260 4260 * Returns:
4261 4261 * Number of LUNs.
4262 4262 *
4263 4263 * Context:
4264 4264 * Kernel context.
4265 4265 */
4266 4266 static int
4267 4267 ql_inq_scan(ql_adapter_state_t *ha, ql_tgt_t *tq, int count)
4268 4268 {
4269 4269 int lun, cnt, rval;
4270 4270 ql_mbx_iocb_t *pkt;
4271 4271 uint8_t *inq;
4272 4272 uint32_t pkt_size;
4273 4273
4274 4274 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
4275 4275
4276 4276 pkt_size = sizeof (ql_mbx_iocb_t) + INQ_DATA_SIZE;
4277 4277 pkt = kmem_zalloc(pkt_size, KM_SLEEP);
4278 4278 if (pkt == NULL) {
4279 4279 EL(ha, "failed, kmem_zalloc\n");
4280 4280 return (0);
4281 4281 }
4282 4282 inq = (uint8_t *)((caddr_t)pkt + sizeof (ql_mbx_iocb_t));
4283 4283
4284 4284 cnt = 0;
4285 4285 for (lun = 0; lun < MAX_LUNS; lun++) {
4286 4286
4287 4287 if (DRIVER_SUSPENDED(ha)) {
4288 4288 rval = QL_LOOP_DOWN;
4289 4289 cnt = 0;
4290 4290 break;
4291 4291 }
4292 4292
4293 4293 rval = ql_inq(ha, tq, lun, pkt, INQ_DATA_SIZE);
4294 4294 if (rval == QL_SUCCESS) {
4295 4295 switch (*inq) {
4296 4296 case DTYPE_DIRECT:
4297 4297 case DTYPE_PROCESSOR: /* Appliance. */
4298 4298 case DTYPE_WORM:
4299 4299 case DTYPE_RODIRECT:
4300 4300 case DTYPE_SCANNER:
4301 4301 case DTYPE_OPTICAL:
4302 4302 case DTYPE_CHANGER:
4303 4303 case DTYPE_ESI:
4304 4304 cnt++;
4305 4305 break;
4306 4306 case DTYPE_SEQUENTIAL:
4307 4307 cnt++;
4308 4308 tq->flags |= TQF_TAPE_DEVICE;
4309 4309 break;
4310 4310 default:
4311 4311 QL_PRINT_9(CE_CONT, "(%d): failed, "
4312 4312 "unsupported device id=%xh, lun=%d, "
4313 4313 "type=%xh\n", ha->instance, tq->loop_id,
4314 4314 lun, *inq);
4315 4315 break;
4316 4316 }
4317 4317
4318 4318 if (*inq == DTYPE_ESI || cnt >= count) {
4319 4319 break;
4320 4320 }
4321 4321 } else if (rval == QL_ABORTED || rval == QL_FUNCTION_TIMEOUT) {
4322 4322 cnt = 0;
4323 4323 break;
4324 4324 }
4325 4325 }
4326 4326
4327 4327 kmem_free(pkt, pkt_size);
4328 4328
4329 4329 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
4330 4330
4331 4331 return (cnt);
4332 4332 }
4333 4333
4334 4334 /*
4335 4335 * ql_inq
4336 4336 * Issue inquiry command.
4337 4337 *
4338 4338 * Input:
4339 4339 * ha: adapter state pointer.
4340 4340 * tq: target queue pointer.
4341 4341 * lun: LUN number.
4342 4342 * pkt: command and buffer pointer.
4343 4343 * inq_len: amount of inquiry data.
4344 4344 *
4345 4345 * Returns:
4346 4346 * ql local function return status code.
4347 4347 *
4348 4348 * Context:
4349 4349 * Kernel context.
4350 4350 */
4351 4351 static int
4352 4352 ql_inq(ql_adapter_state_t *ha, ql_tgt_t *tq, int lun, ql_mbx_iocb_t *pkt,
4353 4353 uint8_t inq_len)
4354 4354 {
4355 4355 dma_mem_t dma_mem;
4356 4356 int rval, retries;
4357 4357 uint32_t pkt_size, cnt;
4358 4358 uint16_t comp_status;
4359 4359 uint8_t scsi_status_h, scsi_status_l, *reqs;
4360 4360 caddr_t inq_data;
4361 4361
4362 4362 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
4363 4363
4364 4364 if (DRIVER_SUSPENDED(ha)) {
4365 4365 EL(ha, "failed, loop down\n");
4366 4366 return (QL_FUNCTION_TIMEOUT);
4367 4367 }
4368 4368
4369 4369 pkt_size = (uint32_t)(sizeof (ql_mbx_iocb_t) + inq_len);
4370 4370 bzero((caddr_t)pkt, pkt_size);
4371 4371
4372 4372 inq_data = (caddr_t)pkt + sizeof (ql_mbx_iocb_t);
4373 4373
4374 4374 /* Get DMA memory for the IOCB */
4375 4375 if (ql_get_dma_mem(ha, &dma_mem, inq_len,
4376 4376 LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN) != QL_SUCCESS) {
4377 4377 cmn_err(CE_WARN, "%s(%d): DMA memory "
4378 4378 "alloc failed", QL_NAME, ha->instance);
4379 4379 return (0);
4380 4380 }
4381 4381
4382 4382 for (retries = 0; retries < 4; retries++) {
4383 4383 if (CFG_IST(ha, CFG_CTRL_24258081)) {
4384 4384 pkt->cmd24.entry_type = IOCB_CMD_TYPE_7;
4385 4385 pkt->cmd24.entry_count = 1;
4386 4386
4387 4387 /* Set LUN number */
4388 4388 pkt->cmd24.fcp_lun[2] = LSB(lun);
4389 4389 pkt->cmd24.fcp_lun[3] = MSB(lun);
4390 4390
4391 4391 /* Set N_port handle */
4392 4392 pkt->cmd24.n_port_hdl = (uint16_t)LE_16(tq->loop_id);
4393 4393
4394 4394 /* Set target ID */
4395 4395 pkt->cmd24.target_id[0] = tq->d_id.b.al_pa;
4396 4396 pkt->cmd24.target_id[1] = tq->d_id.b.area;
4397 4397 pkt->cmd24.target_id[2] = tq->d_id.b.domain;
4398 4398
4399 4399 /* Set Virtual Port ID */
4400 4400 pkt->cmd24.vp_index = ha->vp_index;
4401 4401
4402 4402 /* Set ISP command timeout. */
4403 4403 pkt->cmd24.timeout = LE_16(15);
4404 4404
4405 4405 /* Load SCSI CDB */
4406 4406 pkt->cmd24.scsi_cdb[0] = SCMD_INQUIRY;
4407 4407 pkt->cmd24.scsi_cdb[4] = inq_len;
4408 4408 for (cnt = 0; cnt < MAX_CMDSZ; cnt += 4) {
4409 4409 ql_chg_endian((uint8_t *)&pkt->cmd24.scsi_cdb
4410 4410 + cnt, 4);
4411 4411 }
4412 4412
4413 4413 /* Set tag queue control flags */
4414 4414 pkt->cmd24.task = TA_STAG;
4415 4415
4416 4416 /* Set transfer direction. */
4417 4417 pkt->cmd24.control_flags = CF_RD;
4418 4418
4419 4419 /* Set data segment count. */
4420 4420 pkt->cmd24.dseg_count = LE_16(1);
4421 4421
4422 4422 /* Load total byte count. */
4423 4423 pkt->cmd24.total_byte_count = LE_32(inq_len);
4424 4424
4425 4425 /* Load data descriptor. */
4426 4426 pkt->cmd24.dseg_0_address[0] = (uint32_t)
4427 4427 LE_32(LSD(dma_mem.cookie.dmac_laddress));
4428 4428 pkt->cmd24.dseg_0_address[1] = (uint32_t)
4429 4429 LE_32(MSD(dma_mem.cookie.dmac_laddress));
4430 4430 pkt->cmd24.dseg_0_length = LE_32(inq_len);
4431 4431 } else if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
4432 4432 pkt->cmd3.entry_type = IOCB_CMD_TYPE_3;
4433 4433 cnt = CMD_TYPE_3_DATA_SEGMENTS;
4434 4434
4435 4435 pkt->cmd3.entry_count = 1;
4436 4436 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
4437 4437 pkt->cmd3.target_l = LSB(tq->loop_id);
4438 4438 pkt->cmd3.target_h = MSB(tq->loop_id);
4439 4439 } else {
4440 4440 pkt->cmd3.target_h = LSB(tq->loop_id);
4441 4441 }
4442 4442 pkt->cmd3.lun_l = LSB(lun);
4443 4443 pkt->cmd3.lun_h = MSB(lun);
4444 4444 pkt->cmd3.control_flags_l = CF_DATA_IN | CF_STAG;
4445 4445 pkt->cmd3.timeout = LE_16(15);
4446 4446 pkt->cmd3.scsi_cdb[0] = SCMD_INQUIRY;
4447 4447 pkt->cmd3.scsi_cdb[4] = inq_len;
4448 4448 pkt->cmd3.dseg_count = LE_16(1);
4449 4449 pkt->cmd3.byte_count = LE_32(inq_len);
4450 4450 pkt->cmd3.dseg_0_address[0] = (uint32_t)
4451 4451 LE_32(LSD(dma_mem.cookie.dmac_laddress));
4452 4452 pkt->cmd3.dseg_0_address[1] = (uint32_t)
4453 4453 LE_32(MSD(dma_mem.cookie.dmac_laddress));
4454 4454 pkt->cmd3.dseg_0_length = LE_32(inq_len);
4455 4455 } else {
4456 4456 pkt->cmd.entry_type = IOCB_CMD_TYPE_2;
4457 4457 cnt = CMD_TYPE_2_DATA_SEGMENTS;
4458 4458
4459 4459 pkt->cmd.entry_count = 1;
4460 4460 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
4461 4461 pkt->cmd.target_l = LSB(tq->loop_id);
4462 4462 pkt->cmd.target_h = MSB(tq->loop_id);
4463 4463 } else {
4464 4464 pkt->cmd.target_h = LSB(tq->loop_id);
4465 4465 }
4466 4466 pkt->cmd.lun_l = LSB(lun);
4467 4467 pkt->cmd.lun_h = MSB(lun);
4468 4468 pkt->cmd.control_flags_l = CF_DATA_IN | CF_STAG;
4469 4469 pkt->cmd.timeout = LE_16(15);
4470 4470 pkt->cmd.scsi_cdb[0] = SCMD_INQUIRY;
4471 4471 pkt->cmd.scsi_cdb[4] = inq_len;
4472 4472 pkt->cmd.dseg_count = LE_16(1);
4473 4473 pkt->cmd.byte_count = LE_32(inq_len);
4474 4474 pkt->cmd.dseg_0_address = (uint32_t)
4475 4475 LE_32(LSD(dma_mem.cookie.dmac_laddress));
4476 4476 pkt->cmd.dseg_0_length = LE_32(inq_len);
4477 4477 }
4478 4478
4479 4479 /* rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size); */
4480 4480 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt,
4481 4481 sizeof (ql_mbx_iocb_t));
4482 4482
4483 4483 /* Sync in coming IOCB DMA buffer. */
4484 4484 (void) ddi_dma_sync(dma_mem.dma_handle, 0, dma_mem.size,
4485 4485 DDI_DMA_SYNC_FORKERNEL);
4486 4486 /* Copy in coming DMA data. */
4487 4487 ddi_rep_get8(dma_mem.acc_handle, (uint8_t *)inq_data,
4488 4488 (uint8_t *)dma_mem.bp, dma_mem.size, DDI_DEV_AUTOINCR);
4489 4489
4490 4490 if (CFG_IST(ha, CFG_CTRL_24258081)) {
4491 4491 pkt->sts24.entry_status = (uint8_t)
4492 4492 (pkt->sts24.entry_status & 0x3c);
4493 4493 comp_status = (uint16_t)LE_16(pkt->sts24.comp_status);
4494 4494 scsi_status_h = pkt->sts24.scsi_status_h;
4495 4495 scsi_status_l = pkt->sts24.scsi_status_l;
4496 4496 cnt = scsi_status_h & FCP_RSP_LEN_VALID ?
4497 4497 LE_32(pkt->sts24.fcp_rsp_data_length) : 0;
4498 4498 reqs = &pkt->sts24.rsp_sense_data[cnt];
4499 4499 } else {
4500 4500 pkt->sts.entry_status = (uint8_t)
4501 4501 (pkt->sts.entry_status & 0x7e);
4502 4502 comp_status = (uint16_t)LE_16(pkt->sts.comp_status);
4503 4503 scsi_status_h = pkt->sts.scsi_status_h;
4504 4504 scsi_status_l = pkt->sts.scsi_status_l;
4505 4505 reqs = &pkt->sts.req_sense_data[0];
4506 4506 }
4507 4507 if (rval == QL_SUCCESS && pkt->sts.entry_status != 0) {
4508 4508 EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
4509 4509 pkt->sts.entry_status, tq->d_id.b24);
4510 4510 rval = QL_FUNCTION_PARAMETER_ERROR;
4511 4511 }
4512 4512
4513 4513 if (rval != QL_SUCCESS || comp_status != CS_COMPLETE ||
4514 4514 scsi_status_l & STATUS_CHECK) {
4515 4515 EL(ha, "failed, issue_iocb=%xh, d_id=%xh, cs=%xh, "
4516 4516 "ss_h=%xh, ss_l=%xh\n", rval, tq->d_id.b24,
4517 4517 comp_status, scsi_status_h, scsi_status_l);
4518 4518
4519 4519 if (rval == QL_SUCCESS) {
4520 4520 if ((comp_status == CS_TIMEOUT) ||
4521 4521 (comp_status == CS_PORT_UNAVAILABLE) ||
4522 4522 (comp_status == CS_PORT_LOGGED_OUT)) {
4523 4523 rval = QL_FUNCTION_TIMEOUT;
4524 4524 break;
4525 4525 }
4526 4526 rval = QL_FUNCTION_FAILED;
4527 4527 }
4528 4528
4529 4529 if (scsi_status_l & STATUS_CHECK) {
4530 4530 EL(ha, "STATUS_CHECK Sense Data\n%2xh%3xh"
4531 4531 "%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh"
4532 4532 "%3xh%3xh%3xh%3xh%3xh%3xh%3xh\n", reqs[0],
4533 4533 reqs[1], reqs[2], reqs[3], reqs[4],
4534 4534 reqs[5], reqs[6], reqs[7], reqs[8],
4535 4535 reqs[9], reqs[10], reqs[11], reqs[12],
4536 4536 reqs[13], reqs[14], reqs[15], reqs[16],
4537 4537 reqs[17]);
4538 4538 }
4539 4539 } else {
4540 4540 break;
4541 4541 }
4542 4542 }
4543 4543 ql_free_dma_resource(ha, &dma_mem);
4544 4544
4545 4545 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
4546 4546
4547 4547 return (rval);
4548 4548 }
4549 4549
4550 4550 /*
4551 4551 * ql_get_buffer_data
4552 4552 * Copies data from user space to kernal buffer.
4553 4553 *
4554 4554 * Input:
4555 4555 * src: User source buffer address.
4556 4556 * dst: Kernal destination buffer address.
4557 4557 * size: Amount of data.
4558 4558 * mode: flags.
4559 4559 *
4560 4560 * Returns:
4561 4561 * Returns number of bytes transferred.
4562 4562 *
4563 4563 * Context:
4564 4564 * Kernel context.
4565 4565 */
4566 4566 static uint32_t
4567 4567 ql_get_buffer_data(caddr_t src, caddr_t dst, uint32_t size, int mode)
4568 4568 {
4569 4569 uint32_t cnt;
4570 4570
4571 4571 for (cnt = 0; cnt < size; cnt++) {
4572 4572 if (ddi_copyin(src++, dst++, 1, mode) != 0) {
4573 4573 QL_PRINT_2(CE_CONT, "failed, ddi_copyin\n");
4574 4574 break;
4575 4575 }
4576 4576 }
4577 4577
4578 4578 return (cnt);
4579 4579 }
4580 4580
4581 4581 /*
4582 4582 * ql_send_buffer_data
4583 4583 * Copies data from kernal buffer to user space.
4584 4584 *
4585 4585 * Input:
4586 4586 * src: Kernal source buffer address.
4587 4587 * dst: User destination buffer address.
4588 4588 * size: Amount of data.
4589 4589 * mode: flags.
4590 4590 *
4591 4591 * Returns:
4592 4592 * Returns number of bytes transferred.
4593 4593 *
4594 4594 * Context:
4595 4595 * Kernel context.
4596 4596 */
4597 4597 static uint32_t
4598 4598 ql_send_buffer_data(caddr_t src, caddr_t dst, uint32_t size, int mode)
4599 4599 {
4600 4600 uint32_t cnt;
4601 4601
4602 4602 for (cnt = 0; cnt < size; cnt++) {
4603 4603 if (ddi_copyout(src++, dst++, 1, mode) != 0) {
4604 4604 QL_PRINT_2(CE_CONT, "failed, ddi_copyin\n");
4605 4605 break;
4606 4606 }
4607 4607 }
4608 4608
4609 4609 return (cnt);
4610 4610 }
4611 4611
4612 4612 /*
4613 4613 * ql_find_port
4614 4614 * Locates device queue.
4615 4615 *
4616 4616 * Input:
4617 4617 * ha: adapter state pointer.
4618 4618 * name: device port name.
4619 4619 *
4620 4620 * Returns:
4621 4621 * Returns target queue pointer.
4622 4622 *
4623 4623 * Context:
4624 4624 * Kernel context.
4625 4625 */
4626 4626 static ql_tgt_t *
4627 4627 ql_find_port(ql_adapter_state_t *ha, uint8_t *name, uint16_t type)
4628 4628 {
4629 4629 ql_link_t *link;
4630 4630 ql_tgt_t *tq;
4631 4631 uint16_t index;
4632 4632
4633 4633 /* Scan port list for requested target */
4634 4634 for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
4635 4635 for (link = ha->dev[index].first; link != NULL;
4636 4636 link = link->next) {
4637 4637 tq = link->base_address;
4638 4638
4639 4639 switch (type) {
4640 4640 case QLNT_LOOP_ID:
4641 4641 if (bcmp(name, &tq->loop_id,
4642 4642 sizeof (uint16_t)) == 0) {
4643 4643 return (tq);
4644 4644 }
4645 4645 break;
4646 4646 case QLNT_PORT:
4647 4647 if (bcmp(name, tq->port_name, 8) == 0) {
4648 4648 return (tq);
4649 4649 }
4650 4650 break;
4651 4651 case QLNT_NODE:
4652 4652 if (bcmp(name, tq->node_name, 8) == 0) {
4653 4653 return (tq);
4654 4654 }
4655 4655 break;
4656 4656 case QLNT_PID:
4657 4657 if (bcmp(name, tq->d_id.r.d_id,
4658 4658 sizeof (tq->d_id.r.d_id)) == 0) {
4659 4659 return (tq);
4660 4660 }
4661 4661 break;
4662 4662 default:
4663 4663 EL(ha, "failed, invalid type=%d\n", type);
4664 4664 return (NULL);
4665 4665 }
4666 4666 }
4667 4667 }
4668 4668
4669 4669 return (NULL);
4670 4670 }
4671 4671
4672 4672 /*
4673 4673 * ql_24xx_flash_desc
4674 4674 * Get flash descriptor table.
4675 4675 *
4676 4676 * Input:
4677 4677 * ha: adapter state pointer.
4678 4678 *
4679 4679 * Returns:
4680 4680 * ql local function return status code.
4681 4681 *
4682 4682 * Context:
4683 4683 * Kernel context.
4684 4684 */
4685 4685 static int
4686 4686 ql_24xx_flash_desc(ql_adapter_state_t *ha)
4687 4687 {
4688 4688 uint32_t cnt;
4689 4689 uint16_t chksum, *bp, data;
4690 4690 int rval;
4691 4691 flash_desc_t *fdesc;
4692 4692 ql_xioctl_t *xp = ha->xioctl;
4693 4693
4694 4694 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
4695 4695
4696 4696 if (ha->flash_desc_addr == 0) {
4697 4697 QL_PRINT_9(CE_CONT, "(%d): desc ptr=0\n", ha->instance);
4698 4698 return (QL_FUNCTION_FAILED);
4699 4699 }
4700 4700
4701 4701 if ((fdesc = kmem_zalloc(sizeof (flash_desc_t), KM_SLEEP)) == NULL) {
4702 4702 EL(ha, "kmem_zalloc=null\n");
4703 4703 return (QL_MEMORY_ALLOC_FAILED);
4704 4704 }
4705 4705 rval = ql_dump_fcode(ha, (uint8_t *)fdesc, sizeof (flash_desc_t),
4706 4706 ha->flash_desc_addr << 2);
4707 4707 if (rval != QL_SUCCESS) {
4708 4708 EL(ha, "read status=%xh\n", rval);
4709 4709 kmem_free(fdesc, sizeof (flash_desc_t));
4710 4710 return (rval);
4711 4711 }
4712 4712
4713 4713 chksum = 0;
4714 4714 bp = (uint16_t *)fdesc;
4715 4715 for (cnt = 0; cnt < (sizeof (flash_desc_t)) / 2; cnt++) {
4716 4716 data = *bp++;
4717 4717 LITTLE_ENDIAN_16(&data);
4718 4718 chksum += data;
4719 4719 }
4720 4720
4721 4721 LITTLE_ENDIAN_32(&fdesc->flash_valid);
4722 4722 LITTLE_ENDIAN_16(&fdesc->flash_version);
4723 4723 LITTLE_ENDIAN_16(&fdesc->flash_len);
4724 4724 LITTLE_ENDIAN_16(&fdesc->flash_checksum);
4725 4725 LITTLE_ENDIAN_16(&fdesc->flash_manuf);
4726 4726 LITTLE_ENDIAN_16(&fdesc->flash_id);
4727 4727 LITTLE_ENDIAN_32(&fdesc->block_size);
4728 4728 LITTLE_ENDIAN_32(&fdesc->alt_block_size);
4729 4729 LITTLE_ENDIAN_32(&fdesc->flash_size);
4730 4730 LITTLE_ENDIAN_32(&fdesc->write_enable_data);
4731 4731 LITTLE_ENDIAN_32(&fdesc->read_timeout);
4732 4732
4733 4733 /* flash size in desc table is in 1024 bytes */
4734 4734 fdesc->flash_size = fdesc->flash_size * 0x400;
4735 4735
4736 4736 if (chksum != 0 || fdesc->flash_valid != FLASH_DESC_VAILD ||
4737 4737 fdesc->flash_version != FLASH_DESC_VERSION) {
4738 4738 EL(ha, "invalid descriptor table\n");
4739 4739 kmem_free(fdesc, sizeof (flash_desc_t));
4740 4740 return (QL_FUNCTION_FAILED);
4741 4741 }
4742 4742
4743 4743 bcopy(fdesc, &xp->fdesc, sizeof (flash_desc_t));
4744 4744 kmem_free(fdesc, sizeof (flash_desc_t));
4745 4745
4746 4746 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
4747 4747
4748 4748 return (QL_SUCCESS);
4749 4749 }
4750 4750
4751 4751 /*
4752 4752 * ql_setup_flash
4753 4753 * Gets the manufacturer and id number of the flash chip, and
4754 4754 * sets up the size parameter.
4755 4755 *
4756 4756 * Input:
4757 4757 * ha: adapter state pointer.
4758 4758 *
4759 4759 * Returns:
4760 4760 * int: ql local function return status code.
4761 4761 *
4762 4762 * Context:
4763 4763 * Kernel context.
4764 4764 */
4765 4765 static int
4766 4766 ql_setup_flash(ql_adapter_state_t *ha)
4767 4767 {
4768 4768 ql_xioctl_t *xp = ha->xioctl;
4769 4769 int rval = QL_SUCCESS;
4770 4770
4771 4771 if (xp->fdesc.flash_size != 0) {
4772 4772 return (rval);
4773 4773 }
4774 4774
4775 4775 if (CFG_IST(ha, CFG_CTRL_2200) && !ha->subven_id) {
4776 4776 return (QL_FUNCTION_FAILED);
4777 4777 }
4778 4778
4779 4779 if (CFG_IST(ha, CFG_CTRL_258081)) {
4780 4780 /*
4781 4781 * Temporarily set the ha->xioctl->fdesc.flash_size to
4782 4782 * 25xx flash size to avoid failing of ql_dump_focde.
4783 4783 */
4784 4784 if (CFG_IST(ha, CFG_CTRL_8021)) {
4785 4785 ha->xioctl->fdesc.flash_size = 0x800000;
4786 4786 } else if (CFG_IST(ha, CFG_CTRL_25XX)) {
4787 4787 ha->xioctl->fdesc.flash_size = 0x200000;
4788 4788 } else {
4789 4789 ha->xioctl->fdesc.flash_size = 0x400000;
4790 4790 }
4791 4791
4792 4792 if (ql_24xx_flash_desc(ha) == QL_SUCCESS) {
4793 4793 EL(ha, "flash desc table ok, exit\n");
4794 4794 return (rval);
4795 4795 }
4796 4796 if (CFG_IST(ha, CFG_CTRL_8021)) {
4797 4797 xp->fdesc.flash_manuf = WINBOND_FLASH;
4798 4798 xp->fdesc.flash_id = WINBOND_FLASHID;
4799 4799 xp->fdesc.flash_len = 0x17;
4800 4800 } else {
4801 4801 (void) ql_24xx_flash_id(ha);
4802 4802 }
4803 4803
4804 4804 } else if (CFG_IST(ha, CFG_CTRL_2422)) {
4805 4805 (void) ql_24xx_flash_id(ha);
4806 4806 } else {
4807 4807 ql_flash_enable(ha);
4808 4808
4809 4809 ql_write_flash_byte(ha, 0x5555, 0xaa);
4810 4810 ql_write_flash_byte(ha, 0x2aaa, 0x55);
4811 4811 ql_write_flash_byte(ha, 0x5555, 0x90);
4812 4812 xp->fdesc.flash_manuf = (uint8_t)ql_read_flash_byte(ha, 0x0000);
4813 4813
4814 4814 if (CFG_IST(ha, CFG_SBUS_CARD)) {
4815 4815 ql_write_flash_byte(ha, 0xaaaa, 0xaa);
4816 4816 ql_write_flash_byte(ha, 0x5555, 0x55);
4817 4817 ql_write_flash_byte(ha, 0xaaaa, 0x90);
4818 4818 xp->fdesc.flash_id = (uint16_t)
4819 4819 ql_read_flash_byte(ha, 0x0002);
4820 4820 } else {
4821 4821 ql_write_flash_byte(ha, 0x5555, 0xaa);
4822 4822 ql_write_flash_byte(ha, 0x2aaa, 0x55);
4823 4823 ql_write_flash_byte(ha, 0x5555, 0x90);
4824 4824 xp->fdesc.flash_id = (uint16_t)
4825 4825 ql_read_flash_byte(ha, 0x0001);
4826 4826 }
4827 4827
4828 4828 ql_write_flash_byte(ha, 0x5555, 0xaa);
4829 4829 ql_write_flash_byte(ha, 0x2aaa, 0x55);
4830 4830 ql_write_flash_byte(ha, 0x5555, 0xf0);
4831 4831
4832 4832 ql_flash_disable(ha);
4833 4833 }
4834 4834
4835 4835 /* Default flash descriptor table. */
4836 4836 xp->fdesc.write_statusreg_cmd = 1;
4837 4837 xp->fdesc.write_enable_bits = 0;
4838 4838 xp->fdesc.unprotect_sector_cmd = 0;
4839 4839 xp->fdesc.protect_sector_cmd = 0;
4840 4840 xp->fdesc.write_disable_bits = 0x9c;
4841 4841 xp->fdesc.block_size = 0x10000;
4842 4842 xp->fdesc.erase_cmd = 0xd8;
4843 4843
4844 4844 switch (xp->fdesc.flash_manuf) {
4845 4845 case AMD_FLASH:
4846 4846 switch (xp->fdesc.flash_id) {
4847 4847 case SPAN_FLASHID_2048K:
4848 4848 xp->fdesc.flash_size = 0x200000;
4849 4849 break;
4850 4850 case AMD_FLASHID_1024K:
4851 4851 xp->fdesc.flash_size = 0x100000;
4852 4852 break;
4853 4853 case AMD_FLASHID_512K:
4854 4854 case AMD_FLASHID_512Kt:
4855 4855 case AMD_FLASHID_512Kb:
4856 4856 if (CFG_IST(ha, CFG_SBUS_CARD)) {
4857 4857 xp->fdesc.flash_size = QL_SBUS_FCODE_SIZE;
4858 4858 } else {
4859 4859 xp->fdesc.flash_size = 0x80000;
4860 4860 }
4861 4861 break;
4862 4862 case AMD_FLASHID_128K:
4863 4863 xp->fdesc.flash_size = 0x20000;
4864 4864 break;
4865 4865 default:
4866 4866 rval = QL_FUNCTION_FAILED;
4867 4867 break;
4868 4868 }
4869 4869 break;
4870 4870 case ST_FLASH:
4871 4871 switch (xp->fdesc.flash_id) {
4872 4872 case ST_FLASHID_128K:
4873 4873 xp->fdesc.flash_size = 0x20000;
4874 4874 break;
4875 4875 case ST_FLASHID_512K:
4876 4876 xp->fdesc.flash_size = 0x80000;
4877 4877 break;
4878 4878 case ST_FLASHID_M25PXX:
4879 4879 if (xp->fdesc.flash_len == 0x14) {
4880 4880 xp->fdesc.flash_size = 0x100000;
4881 4881 } else if (xp->fdesc.flash_len == 0x15) {
4882 4882 xp->fdesc.flash_size = 0x200000;
4883 4883 } else {
4884 4884 rval = QL_FUNCTION_FAILED;
4885 4885 }
4886 4886 break;
4887 4887 default:
4888 4888 rval = QL_FUNCTION_FAILED;
4889 4889 break;
4890 4890 }
4891 4891 break;
4892 4892 case SST_FLASH:
4893 4893 switch (xp->fdesc.flash_id) {
4894 4894 case SST_FLASHID_128K:
4895 4895 xp->fdesc.flash_size = 0x20000;
4896 4896 break;
4897 4897 case SST_FLASHID_1024K_A:
4898 4898 xp->fdesc.flash_size = 0x100000;
4899 4899 xp->fdesc.block_size = 0x8000;
4900 4900 xp->fdesc.erase_cmd = 0x52;
4901 4901 break;
4902 4902 case SST_FLASHID_1024K:
4903 4903 case SST_FLASHID_1024K_B:
4904 4904 xp->fdesc.flash_size = 0x100000;
4905 4905 break;
4906 4906 case SST_FLASHID_2048K:
4907 4907 xp->fdesc.flash_size = 0x200000;
4908 4908 break;
4909 4909 default:
4910 4910 rval = QL_FUNCTION_FAILED;
4911 4911 break;
4912 4912 }
4913 4913 break;
4914 4914 case MXIC_FLASH:
4915 4915 switch (xp->fdesc.flash_id) {
4916 4916 case MXIC_FLASHID_512K:
4917 4917 xp->fdesc.flash_size = 0x80000;
4918 4918 break;
4919 4919 case MXIC_FLASHID_1024K:
4920 4920 xp->fdesc.flash_size = 0x100000;
4921 4921 break;
4922 4922 case MXIC_FLASHID_25LXX:
4923 4923 if (xp->fdesc.flash_len == 0x14) {
4924 4924 xp->fdesc.flash_size = 0x100000;
4925 4925 } else if (xp->fdesc.flash_len == 0x15) {
4926 4926 xp->fdesc.flash_size = 0x200000;
4927 4927 } else {
4928 4928 rval = QL_FUNCTION_FAILED;
4929 4929 }
4930 4930 break;
4931 4931 default:
4932 4932 rval = QL_FUNCTION_FAILED;
4933 4933 break;
4934 4934 }
4935 4935 break;
4936 4936 case ATMEL_FLASH:
4937 4937 switch (xp->fdesc.flash_id) {
4938 4938 case ATMEL_FLASHID_1024K:
4939 4939 xp->fdesc.flash_size = 0x100000;
4940 4940 xp->fdesc.write_disable_bits = 0xbc;
4941 4941 xp->fdesc.unprotect_sector_cmd = 0x39;
4942 4942 xp->fdesc.protect_sector_cmd = 0x36;
4943 4943 break;
4944 4944 default:
4945 4945 rval = QL_FUNCTION_FAILED;
4946 4946 break;
4947 4947 }
4948 4948 break;
4949 4949 case WINBOND_FLASH:
4950 4950 switch (xp->fdesc.flash_id) {
4951 4951 case WINBOND_FLASHID:
4952 4952 if (xp->fdesc.flash_len == 0x15) {
4953 4953 xp->fdesc.flash_size = 0x200000;
4954 4954 } else if (xp->fdesc.flash_len == 0x16) {
4955 4955 xp->fdesc.flash_size = 0x400000;
4956 4956 } else if (xp->fdesc.flash_len == 0x17) {
4957 4957 xp->fdesc.flash_size = 0x800000;
4958 4958 } else {
4959 4959 rval = QL_FUNCTION_FAILED;
4960 4960 }
4961 4961 break;
4962 4962 default:
4963 4963 rval = QL_FUNCTION_FAILED;
4964 4964 break;
4965 4965 }
4966 4966 break;
4967 4967 case INTEL_FLASH:
4968 4968 switch (xp->fdesc.flash_id) {
4969 4969 case INTEL_FLASHID:
4970 4970 if (xp->fdesc.flash_len == 0x11) {
4971 4971 xp->fdesc.flash_size = 0x200000;
4972 4972 } else if (xp->fdesc.flash_len == 0x12) {
4973 4973 xp->fdesc.flash_size = 0x400000;
4974 4974 } else if (xp->fdesc.flash_len == 0x13) {
4975 4975 xp->fdesc.flash_size = 0x800000;
4976 4976 } else {
4977 4977 rval = QL_FUNCTION_FAILED;
4978 4978 }
4979 4979 break;
4980 4980 default:
4981 4981 rval = QL_FUNCTION_FAILED;
4982 4982 break;
4983 4983 }
4984 4984 break;
4985 4985 default:
4986 4986 rval = QL_FUNCTION_FAILED;
4987 4987 break;
4988 4988 }
4989 4989
4990 4990 /* Try flash table later. */
4991 4991 if (rval != QL_SUCCESS && CFG_IST(ha, CFG_CTRL_24258081)) {
4992 4992 EL(ha, "no default id\n");
4993 4993 return (QL_SUCCESS);
4994 4994 }
4995 4995
4996 4996 /*
4997 4997 * hack for non std 2312 and 6312 boards. hardware people need to
4998 4998 * use either the 128k flash chip (original), or something larger.
4999 4999 * For driver purposes, we'll treat it as a 128k flash chip.
5000 5000 */
5001 5001 if ((ha->device_id == 0x2312 || ha->device_id == 0x6312 ||
5002 5002 ha->device_id == 0x2322 || ha->device_id == 0x6322) &&
5003 5003 (xp->fdesc.flash_size > 0x20000) &&
5004 5004 (CFG_IST(ha, CFG_SBUS_CARD) == 0)) {
5005 5005 EL(ha, "chip exceeds max size: %xh, using 128k\n",
5006 5006 xp->fdesc.flash_size);
5007 5007 xp->fdesc.flash_size = 0x20000;
5008 5008 }
5009 5009
5010 5010 if (rval == QL_SUCCESS) {
5011 5011 EL(ha, "man_id=%xh, flash_id=%xh, size=%xh\n",
5012 5012 xp->fdesc.flash_manuf, xp->fdesc.flash_id,
5013 5013 xp->fdesc.flash_size);
5014 5014 } else {
5015 5015 EL(ha, "unsupported mfr / type: man_id=%xh, flash_id=%xh\n",
5016 5016 xp->fdesc.flash_manuf, xp->fdesc.flash_id);
5017 5017 }
5018 5018
5019 5019 return (rval);
5020 5020 }
5021 5021
5022 5022 /*
5023 5023 * ql_flash_fcode_load
5024 5024 * Loads fcode data into flash from application.
5025 5025 *
5026 5026 * Input:
5027 5027 * ha: adapter state pointer.
5028 5028 * bp: user buffer address.
5029 5029 * size: user buffer size.
5030 5030 * mode: flags
5031 5031 *
5032 5032 * Returns:
5033 5033 *
5034 5034 * Context:
5035 5035 * Kernel context.
5036 5036 */
5037 5037 static int
5038 5038 ql_flash_fcode_load(ql_adapter_state_t *ha, void *bp, uint32_t bsize,
5039 5039 int mode)
5040 5040 {
5041 5041 uint8_t *bfp;
5042 5042 ql_xioctl_t *xp = ha->xioctl;
5043 5043 int rval = 0;
5044 5044
5045 5045 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5046 5046
5047 5047 if (bsize > xp->fdesc.flash_size) {
5048 5048 EL(ha, "failed, bufsize: %xh, flash size: %xh\n", bsize,
5049 5049 xp->fdesc.flash_size);
5050 5050 return (ENOMEM);
5051 5051 }
5052 5052
5053 5053 if ((bfp = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP)) == NULL) {
5054 5054 EL(ha, "failed, kmem_zalloc\n");
5055 5055 rval = ENOMEM;
5056 5056 } else {
5057 5057 if (ddi_copyin(bp, bfp, bsize, mode) != 0) {
5058 5058 EL(ha, "failed, ddi_copyin\n");
5059 5059 rval = EFAULT;
5060 5060 } else if (ql_load_fcode(ha, bfp, bsize, 0) != QL_SUCCESS) {
5061 5061 EL(ha, "failed, load_fcode\n");
5062 5062 rval = EFAULT;
5063 5063 } else {
5064 5064 /* Reset caches on all adapter instances. */
5065 5065 ql_update_flash_caches(ha);
5066 5066 rval = 0;
5067 5067 }
5068 5068 kmem_free(bfp, bsize);
5069 5069 }
5070 5070
5071 5071 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5072 5072
5073 5073 return (rval);
5074 5074 }
5075 5075
5076 5076 /*
5077 5077 * ql_load_fcode
5078 5078 * Loads fcode in to flash.
5079 5079 *
5080 5080 * Input:
5081 5081 * ha: adapter state pointer.
5082 5082 * dp: data pointer.
5083 5083 * size: data length.
5084 5084 * addr: flash byte address.
5085 5085 *
5086 5086 * Returns:
5087 5087 * ql local function return status code.
5088 5088 *
5089 5089 * Context:
5090 5090 * Kernel context.
5091 5091 */
5092 5092 int
5093 5093 ql_load_fcode(ql_adapter_state_t *ha, uint8_t *dp, uint32_t size, uint32_t addr)
5094 5094 {
5095 5095 uint32_t cnt;
5096 5096 int rval;
5097 5097
5098 5098 if (CFG_IST(ha, CFG_CTRL_24258081)) {
5099 5099 return (ql_24xx_load_flash(ha, dp, size, addr));
5100 5100 }
5101 5101
5102 5102 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5103 5103
5104 5104 if (CFG_IST(ha, CFG_SBUS_CARD)) {
5105 5105 /*
5106 5106 * sbus has an additional check to make
5107 5107 * sure they don't brick the HBA.
5108 5108 */
5109 5109 if (dp[0] != 0xf1) {
5110 5110 EL(ha, "failed, incorrect fcode for sbus\n");
5111 5111 return (QL_FUNCTION_PARAMETER_ERROR);
5112 5112 }
5113 5113 }
5114 5114
5115 5115 GLOBAL_HW_LOCK();
5116 5116
5117 5117 /* Enable Flash Read/Write. */
5118 5118 ql_flash_enable(ha);
5119 5119
5120 5120 /* Erase flash prior to write. */
5121 5121 rval = ql_erase_flash(ha, 0);
5122 5122
5123 5123 if (rval == QL_SUCCESS) {
5124 5124 /* Write fcode data to flash. */
5125 5125 for (cnt = 0; cnt < (uint32_t)size; cnt++) {
5126 5126 /* Allow other system activity. */
5127 5127 if (cnt % 0x1000 == 0) {
5128 5128 drv_usecwait(1);
5129 5129 }
5130 5130 rval = ql_program_flash_address(ha, addr++, *dp++);
5131 5131 if (rval != QL_SUCCESS)
5132 5132 break;
5133 5133 }
5134 5134 }
5135 5135
5136 5136 ql_flash_disable(ha);
5137 5137
5138 5138 GLOBAL_HW_UNLOCK();
5139 5139
5140 5140 if (rval != QL_SUCCESS) {
5141 5141 EL(ha, "failed, rval=%xh\n", rval);
5142 5142 } else {
5143 5143 /*EMPTY*/
5144 5144 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5145 5145 }
5146 5146 return (rval);
5147 5147 }
5148 5148
5149 5149 /*
5150 5150 * ql_flash_fcode_dump
5151 5151 * Dumps FLASH to application.
5152 5152 *
5153 5153 * Input:
5154 5154 * ha: adapter state pointer.
5155 5155 * bp: user buffer address.
5156 5156 * bsize: user buffer size
5157 5157 * faddr: flash byte address
5158 5158 * mode: flags
5159 5159 *
5160 5160 * Returns:
5161 5161 *
5162 5162 * Context:
5163 5163 * Kernel context.
5164 5164 */
5165 5165 static int
5166 5166 ql_flash_fcode_dump(ql_adapter_state_t *ha, void *bp, uint32_t bsize,
5167 5167 uint32_t faddr, int mode)
5168 5168 {
5169 5169 uint8_t *bfp;
5170 5170 int rval;
5171 5171 ql_xioctl_t *xp = ha->xioctl;
5172 5172
5173 5173 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5174 5174
5175 5175 /* adjust max read size to flash size */
5176 5176 if (bsize > xp->fdesc.flash_size) {
5177 5177 EL(ha, "adjusting req=%xh, max=%xh\n", bsize,
5178 5178 xp->fdesc.flash_size);
5179 5179 bsize = xp->fdesc.flash_size;
5180 5180 }
5181 5181
5182 5182 if ((bfp = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP)) == NULL) {
5183 5183 EL(ha, "failed, kmem_zalloc\n");
5184 5184 rval = ENOMEM;
5185 5185 } else {
5186 5186 /* Dump Flash fcode. */
5187 5187 rval = ql_dump_fcode(ha, bfp, bsize, faddr);
5188 5188
5189 5189 if (rval != QL_SUCCESS) {
5190 5190 EL(ha, "failed, dump_fcode = %x\n", rval);
5191 5191 rval = EFAULT;
5192 5192 } else if (ddi_copyout(bfp, bp, bsize, mode) != 0) {
5193 5193 EL(ha, "failed, ddi_copyout\n");
5194 5194 rval = EFAULT;
5195 5195 } else {
5196 5196 rval = 0;
5197 5197 }
5198 5198 kmem_free(bfp, bsize);
5199 5199 }
5200 5200
5201 5201 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5202 5202
5203 5203 return (rval);
5204 5204 }
5205 5205
5206 5206 /*
5207 5207 * ql_dump_fcode
5208 5208 * Dumps fcode from flash.
5209 5209 *
5210 5210 * Input:
5211 5211 * ha: adapter state pointer.
5212 5212 * dp: data pointer.
5213 5213 * size: data length in bytes.
5214 5214 * startpos: starting position in flash (byte address).
5215 5215 *
5216 5216 * Returns:
5217 5217 * ql local function return status code.
5218 5218 *
5219 5219 * Context:
5220 5220 * Kernel context.
5221 5221 *
5222 5222 */
5223 5223 int
5224 5224 ql_dump_fcode(ql_adapter_state_t *ha, uint8_t *dp, uint32_t size,
5225 5225 uint32_t startpos)
5226 5226 {
5227 5227 uint32_t cnt, data, addr;
5228 5228 uint8_t bp[4], *src;
5229 5229 int fp_rval, rval = QL_SUCCESS;
5230 5230 dma_mem_t mem;
5231 5231
5232 5232 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5233 5233
5234 5234 /* make sure startpos+size doesn't exceed flash */
5235 5235 if (size + startpos > ha->xioctl->fdesc.flash_size) {
5236 5236 EL(ha, "exceeded flash range, sz=%xh, stp=%xh, flsz=%xh\n",
5237 5237 size, startpos, ha->xioctl->fdesc.flash_size);
5238 5238 return (QL_FUNCTION_PARAMETER_ERROR);
5239 5239 }
5240 5240
5241 5241 if (CFG_IST(ha, CFG_CTRL_24258081)) {
5242 5242 /* check start addr is 32 bit aligned for 24xx */
5243 5243 if ((startpos & 0x3) != 0) {
5244 5244 rval = ql_24xx_read_flash(ha,
5245 5245 ha->flash_data_addr | startpos >> 2, &data);
5246 5246 if (rval != QL_SUCCESS) {
5247 5247 EL(ha, "failed2, rval = %xh\n", rval);
5248 5248 return (rval);
5249 5249 }
5250 5250 bp[0] = LSB(LSW(data));
5251 5251 bp[1] = MSB(LSW(data));
5252 5252 bp[2] = LSB(MSW(data));
5253 5253 bp[3] = MSB(MSW(data));
5254 5254 while (size && startpos & 0x3) {
5255 5255 *dp++ = bp[startpos & 0x3];
5256 5256 startpos++;
5257 5257 size--;
5258 5258 }
5259 5259 if (size == 0) {
5260 5260 QL_PRINT_9(CE_CONT, "(%d): done2\n",
5261 5261 ha->instance);
5262 5262 return (rval);
5263 5263 }
5264 5264 }
5265 5265
5266 5266 /* adjust 24xx start addr for 32 bit words */
5267 5267 addr = startpos / 4 | ha->flash_data_addr;
5268 5268 }
5269 5269
5270 5270 bzero(&mem, sizeof (dma_mem_t));
5271 5271 /* Check for Fast page is supported */
5272 5272 if ((ha->pha->task_daemon_flags & FIRMWARE_UP) &&
5273 5273 (CFG_IST(ha, CFG_CTRL_2581))) {
5274 5274 fp_rval = QL_SUCCESS;
5275 5275 /* Setup DMA buffer. */
5276 5276 rval = ql_get_dma_mem(ha, &mem, size,
5277 5277 LITTLE_ENDIAN_DMA, QL_DMA_DATA_ALIGN);
5278 5278 if (rval != QL_SUCCESS) {
5279 5279 EL(ha, "failed, ql_get_dma_mem=%xh\n",
5280 5280 rval);
5281 5281 return (ENOMEM);
5282 5282 }
5283 5283 } else {
5284 5284 fp_rval = QL_NOT_SUPPORTED;
5285 5285 }
5286 5286
5287 5287 GLOBAL_HW_LOCK();
5288 5288
5289 5289 /* Enable Flash Read/Write. */
5290 5290 if (CFG_IST(ha, CFG_CTRL_24258081) == 0) {
5291 5291 ql_flash_enable(ha);
5292 5292 }
5293 5293
5294 5294 /* Read fcode data from flash. */
5295 5295 while (size) {
5296 5296 /* Allow other system activity. */
5297 5297 if (size % 0x1000 == 0) {
5298 5298 ql_delay(ha, 100000);
5299 5299 }
5300 5300 if (CFG_IST(ha, CFG_CTRL_24258081)) {
5301 5301 if (fp_rval == QL_SUCCESS && (addr & 0x3f) == 0) {
5302 5302 cnt = (size + 3) >> 2;
5303 5303 fp_rval = ql_rd_risc_ram(ha, addr,
5304 5304 mem.cookie.dmac_laddress, cnt);
5305 5305 if (fp_rval == QL_SUCCESS) {
5306 5306 for (src = mem.bp; size; size--) {
5307 5307 *dp++ = *src++;
5308 5308 }
5309 5309 addr += cnt;
5310 5310 continue;
5311 5311 }
5312 5312 }
5313 5313 rval = ql_24xx_read_flash(ha, addr++,
5314 5314 &data);
5315 5315 if (rval != QL_SUCCESS) {
5316 5316 break;
5317 5317 }
5318 5318 bp[0] = LSB(LSW(data));
5319 5319 bp[1] = MSB(LSW(data));
5320 5320 bp[2] = LSB(MSW(data));
5321 5321 bp[3] = MSB(MSW(data));
5322 5322 for (cnt = 0; size && cnt < 4; size--) {
5323 5323 *dp++ = bp[cnt++];
5324 5324 }
5325 5325 } else {
5326 5326 *dp++ = (uint8_t)ql_read_flash_byte(ha, startpos++);
5327 5327 size--;
5328 5328 }
5329 5329 }
5330 5330
5331 5331 if (CFG_IST(ha, CFG_CTRL_24258081) == 0) {
5332 5332 ql_flash_disable(ha);
5333 5333 }
5334 5334
5335 5335 GLOBAL_HW_UNLOCK();
5336 5336
5337 5337 if (mem.dma_handle != NULL) {
5338 5338 ql_free_dma_resource(ha, &mem);
5339 5339 }
5340 5340
5341 5341 if (rval != QL_SUCCESS) {
5342 5342 EL(ha, "failed, rval = %xh\n", rval);
5343 5343 } else {
5344 5344 /*EMPTY*/
5345 5345 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5346 5346 }
5347 5347 return (rval);
5348 5348 }
5349 5349
5350 5350 /*
5351 5351 * ql_program_flash_address
5352 5352 * Program flash address.
5353 5353 *
5354 5354 * Input:
5355 5355 * ha: adapter state pointer.
5356 5356 * addr: flash byte address.
5357 5357 * data: data to be written to flash.
5358 5358 *
5359 5359 * Returns:
5360 5360 * ql local function return status code.
5361 5361 *
5362 5362 * Context:
5363 5363 * Kernel context.
5364 5364 */
5365 5365 static int
5366 5366 ql_program_flash_address(ql_adapter_state_t *ha, uint32_t addr,
5367 5367 uint8_t data)
5368 5368 {
5369 5369 int rval;
5370 5370
5371 5371 /* Write Program Command Sequence */
5372 5372 if (CFG_IST(ha, CFG_SBUS_CARD)) {
5373 5373 ql_write_flash_byte(ha, 0x5555, 0xa0);
5374 5374 ql_write_flash_byte(ha, addr, data);
5375 5375 } else {
5376 5376 ql_write_flash_byte(ha, 0x5555, 0xaa);
5377 5377 ql_write_flash_byte(ha, 0x2aaa, 0x55);
5378 5378 ql_write_flash_byte(ha, 0x5555, 0xa0);
5379 5379 ql_write_flash_byte(ha, addr, data);
5380 5380 }
5381 5381
5382 5382 /* Wait for write to complete. */
5383 5383 rval = ql_poll_flash(ha, addr, data);
5384 5384
5385 5385 if (rval != QL_SUCCESS) {
5386 5386 EL(ha, "failed, rval=%xh\n", rval);
5387 5387 }
5388 5388 return (rval);
5389 5389 }
5390 5390
5391 5391 /*
5392 5392 * ql_set_rnid_parameters
5393 5393 * Set RNID parameters.
5394 5394 *
5395 5395 * Input:
5396 5396 * ha: adapter state pointer.
5397 5397 * cmd: User space CT arguments pointer.
5398 5398 * mode: flags.
5399 5399 */
5400 5400 static void
5401 5401 ql_set_rnid_parameters(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
5402 5402 {
5403 5403 EXT_SET_RNID_REQ tmp_set;
5404 5404 EXT_RNID_DATA *tmp_buf;
5405 5405 int rval = 0;
5406 5406
5407 5407 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5408 5408
5409 5409 if (DRIVER_SUSPENDED(ha)) {
5410 5410 EL(ha, "failed, LOOP_NOT_READY\n");
5411 5411 cmd->Status = EXT_STATUS_BUSY;
5412 5412 cmd->ResponseLen = 0;
5413 5413 return;
5414 5414 }
5415 5415
5416 5416 cmd->ResponseLen = 0; /* NO response to caller. */
5417 5417 if (cmd->RequestLen != sizeof (EXT_SET_RNID_REQ)) {
5418 5418 /* parameter error */
5419 5419 EL(ha, "failed, RequestLen < EXT_SET_RNID_REQ, Len=%xh\n",
5420 5420 cmd->RequestLen);
5421 5421 cmd->Status = EXT_STATUS_INVALID_PARAM;
5422 5422 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN;
5423 5423 cmd->ResponseLen = 0;
5424 5424 return;
5425 5425 }
5426 5426
5427 5427 rval = ddi_copyin((void*)(uintptr_t)cmd->RequestAdr, &tmp_set,
5428 5428 cmd->RequestLen, mode);
5429 5429 if (rval != 0) {
5430 5430 EL(ha, "failed, ddi_copyin\n");
5431 5431 cmd->Status = EXT_STATUS_COPY_ERR;
5432 5432 cmd->ResponseLen = 0;
5433 5433 return;
5434 5434 }
5435 5435
5436 5436 /* Allocate memory for command. */
5437 5437 tmp_buf = kmem_zalloc(sizeof (EXT_RNID_DATA), KM_SLEEP);
5438 5438 if (tmp_buf == NULL) {
5439 5439 EL(ha, "failed, kmem_zalloc\n");
5440 5440 cmd->Status = EXT_STATUS_NO_MEMORY;
5441 5441 cmd->ResponseLen = 0;
5442 5442 return;
5443 5443 }
5444 5444
5445 5445 rval = ql_get_rnid_params(ha, sizeof (EXT_RNID_DATA),
5446 5446 (caddr_t)tmp_buf);
5447 5447 if (rval != QL_SUCCESS) {
5448 5448 /* error */
5449 5449 EL(ha, "failed, get_rnid_params_mbx=%xh\n", rval);
5450 5450 kmem_free(tmp_buf, sizeof (EXT_RNID_DATA));
5451 5451 cmd->Status = EXT_STATUS_ERR;
5452 5452 cmd->ResponseLen = 0;
5453 5453 return;
5454 5454 }
5455 5455
5456 5456 /* Now set the requested params. */
5457 5457 bcopy(tmp_set.IPVersion, tmp_buf->IPVersion, 2);
5458 5458 bcopy(tmp_set.UDPPortNumber, tmp_buf->UDPPortNumber, 2);
5459 5459 bcopy(tmp_set.IPAddress, tmp_buf->IPAddress, 16);
5460 5460
5461 5461 rval = ql_set_rnid_params(ha, sizeof (EXT_RNID_DATA),
5462 5462 (caddr_t)tmp_buf);
5463 5463 if (rval != QL_SUCCESS) {
5464 5464 /* error */
5465 5465 EL(ha, "failed, set_rnid_params_mbx=%xh\n", rval);
5466 5466 cmd->Status = EXT_STATUS_ERR;
5467 5467 cmd->ResponseLen = 0;
5468 5468 }
5469 5469
5470 5470 kmem_free(tmp_buf, sizeof (EXT_RNID_DATA));
5471 5471
5472 5472 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5473 5473 }
5474 5474
5475 5475 /*
5476 5476 * ql_get_rnid_parameters
5477 5477 * Get RNID parameters.
5478 5478 *
5479 5479 * Input:
5480 5480 * ha: adapter state pointer.
5481 5481 * cmd: User space CT arguments pointer.
5482 5482 * mode: flags.
5483 5483 */
5484 5484 static void
5485 5485 ql_get_rnid_parameters(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
5486 5486 {
5487 5487 EXT_RNID_DATA *tmp_buf;
5488 5488 uint32_t rval;
5489 5489
5490 5490 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5491 5491
5492 5492 if (DRIVER_SUSPENDED(ha)) {
5493 5493 EL(ha, "failed, LOOP_NOT_READY\n");
5494 5494 cmd->Status = EXT_STATUS_BUSY;
5495 5495 cmd->ResponseLen = 0;
5496 5496 return;
5497 5497 }
5498 5498
5499 5499 /* Allocate memory for command. */
5500 5500 tmp_buf = kmem_zalloc(sizeof (EXT_RNID_DATA), KM_SLEEP);
5501 5501 if (tmp_buf == NULL) {
5502 5502 EL(ha, "failed, kmem_zalloc\n");
5503 5503 cmd->Status = EXT_STATUS_NO_MEMORY;
5504 5504 cmd->ResponseLen = 0;
5505 5505 return;
5506 5506 }
5507 5507
5508 5508 /* Send command */
5509 5509 rval = ql_get_rnid_params(ha, sizeof (EXT_RNID_DATA),
5510 5510 (caddr_t)tmp_buf);
5511 5511 if (rval != QL_SUCCESS) {
5512 5512 /* error */
5513 5513 EL(ha, "failed, get_rnid_params_mbx=%xh\n", rval);
5514 5514 kmem_free(tmp_buf, sizeof (EXT_RNID_DATA));
5515 5515 cmd->Status = EXT_STATUS_ERR;
5516 5516 cmd->ResponseLen = 0;
5517 5517 return;
5518 5518 }
5519 5519
5520 5520 /* Copy the response */
5521 5521 if (ql_send_buffer_data((caddr_t)tmp_buf,
5522 5522 (caddr_t)(uintptr_t)cmd->ResponseAdr,
5523 5523 sizeof (EXT_RNID_DATA), mode) != sizeof (EXT_RNID_DATA)) {
5524 5524 EL(ha, "failed, ddi_copyout\n");
5525 5525 cmd->Status = EXT_STATUS_COPY_ERR;
5526 5526 cmd->ResponseLen = 0;
5527 5527 } else {
5528 5528 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5529 5529 cmd->ResponseLen = sizeof (EXT_RNID_DATA);
5530 5530 }
5531 5531
5532 5532 kmem_free(tmp_buf, sizeof (EXT_RNID_DATA));
5533 5533 }
5534 5534
5535 5535 /*
5536 5536 * ql_reset_statistics
5537 5537 * Performs EXT_SC_RST_STATISTICS subcommand. of EXT_CC_SET_DATA.
5538 5538 *
5539 5539 * Input:
5540 5540 * ha: adapter state pointer.
5541 5541 * cmd: Local EXT_IOCTL cmd struct pointer.
5542 5542 *
5543 5543 * Returns:
5544 5544 * None, request status indicated in cmd->Status.
5545 5545 *
5546 5546 * Context:
5547 5547 * Kernel context.
5548 5548 */
5549 5549 static int
5550 5550 ql_reset_statistics(ql_adapter_state_t *ha, EXT_IOCTL *cmd)
5551 5551 {
5552 5552 ql_xioctl_t *xp = ha->xioctl;
5553 5553 int rval = 0;
5554 5554
5555 5555 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5556 5556
5557 5557 if (DRIVER_SUSPENDED(ha)) {
5558 5558 EL(ha, "failed, LOOP_NOT_READY\n");
5559 5559 cmd->Status = EXT_STATUS_BUSY;
5560 5560 cmd->ResponseLen = 0;
5561 5561 return (QL_FUNCTION_SUSPENDED);
5562 5562 }
5563 5563
5564 5564 rval = ql_reset_link_status(ha);
5565 5565 if (rval != QL_SUCCESS) {
5566 5566 EL(ha, "failed, reset_link_status_mbx=%xh\n", rval);
5567 5567 cmd->Status = EXT_STATUS_MAILBOX;
5568 5568 cmd->DetailStatus = rval;
5569 5569 cmd->ResponseLen = 0;
5570 5570 }
5571 5571
5572 5572 TASK_DAEMON_LOCK(ha);
5573 5573 xp->IosRequested = 0;
5574 5574 xp->BytesRequested = 0;
5575 5575 xp->IOInputRequests = 0;
5576 5576 xp->IOOutputRequests = 0;
5577 5577 xp->IOControlRequests = 0;
5578 5578 xp->IOInputMByteCnt = 0;
5579 5579 xp->IOOutputMByteCnt = 0;
5580 5580 xp->IOOutputByteCnt = 0;
5581 5581 xp->IOInputByteCnt = 0;
5582 5582 TASK_DAEMON_UNLOCK(ha);
5583 5583
5584 5584 INTR_LOCK(ha);
5585 5585 xp->ControllerErrorCount = 0;
5586 5586 xp->DeviceErrorCount = 0;
5587 5587 xp->TotalLipResets = 0;
5588 5588 xp->TotalInterrupts = 0;
5589 5589 INTR_UNLOCK(ha);
5590 5590
5591 5591 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5592 5592
5593 5593 return (rval);
5594 5594 }
5595 5595
5596 5596 /*
5597 5597 * ql_get_statistics
5598 5598 * Performs EXT_SC_GET_STATISTICS subcommand. of EXT_CC_GET_DATA.
5599 5599 *
5600 5600 * Input:
5601 5601 * ha: adapter state pointer.
5602 5602 * cmd: Local EXT_IOCTL cmd struct pointer.
5603 5603 * mode: flags.
5604 5604 *
5605 5605 * Returns:
5606 5606 * None, request status indicated in cmd->Status.
5607 5607 *
5608 5608 * Context:
5609 5609 * Kernel context.
5610 5610 */
5611 5611 static void
5612 5612 ql_get_statistics(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
5613 5613 {
5614 5614 EXT_HBA_PORT_STAT ps = {0};
5615 5615 ql_link_stats_t *ls;
5616 5616 int rval;
5617 5617 ql_xioctl_t *xp = ha->xioctl;
5618 5618 int retry = 10;
5619 5619
5620 5620 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5621 5621
5622 5622 while (ha->task_daemon_flags &
5623 5623 (ABORT_ISP_ACTIVE | LOOP_RESYNC_ACTIVE | DRIVER_STALL)) {
5624 5624 ql_delay(ha, 10000000); /* 10 second delay */
5625 5625
5626 5626 retry--;
5627 5627
5628 5628 if (retry == 0) { /* effectively 100 seconds */
5629 5629 EL(ha, "failed, LOOP_NOT_READY\n");
5630 5630 cmd->Status = EXT_STATUS_BUSY;
5631 5631 cmd->ResponseLen = 0;
5632 5632 return;
5633 5633 }
5634 5634 }
5635 5635
5636 5636 /* Allocate memory for command. */
5637 5637 ls = kmem_zalloc(sizeof (ql_link_stats_t), KM_SLEEP);
5638 5638 if (ls == NULL) {
5639 5639 EL(ha, "failed, kmem_zalloc\n");
5640 5640 cmd->Status = EXT_STATUS_NO_MEMORY;
5641 5641 cmd->ResponseLen = 0;
5642 5642 return;
5643 5643 }
5644 5644
5645 5645 /*
5646 5646 * I think these are supposed to be port statistics
5647 5647 * the loop ID or port ID should be in cmd->Instance.
5648 5648 */
5649 5649 rval = ql_get_status_counts(ha, (uint16_t)
5650 5650 (ha->task_daemon_flags & LOOP_DOWN ? 0xFF : ha->loop_id),
5651 5651 sizeof (ql_link_stats_t), (caddr_t)ls, 0);
5652 5652 if (rval != QL_SUCCESS) {
5653 5653 EL(ha, "failed, get_link_status=%xh, id=%xh\n", rval,
5654 5654 ha->loop_id);
5655 5655 cmd->Status = EXT_STATUS_MAILBOX;
5656 5656 cmd->DetailStatus = rval;
5657 5657 cmd->ResponseLen = 0;
5658 5658 } else {
5659 5659 ps.ControllerErrorCount = xp->ControllerErrorCount;
5660 5660 ps.DeviceErrorCount = xp->DeviceErrorCount;
5661 5661 ps.IoCount = (uint32_t)(xp->IOInputRequests +
5662 5662 xp->IOOutputRequests + xp->IOControlRequests);
5663 5663 ps.MBytesCount = (uint32_t)(xp->IOInputMByteCnt +
5664 5664 xp->IOOutputMByteCnt);
5665 5665 ps.LipResetCount = xp->TotalLipResets;
5666 5666 ps.InterruptCount = xp->TotalInterrupts;
5667 5667 ps.LinkFailureCount = LE_32(ls->link_fail_cnt);
5668 5668 ps.LossOfSyncCount = LE_32(ls->sync_loss_cnt);
5669 5669 ps.LossOfSignalsCount = LE_32(ls->signal_loss_cnt);
5670 5670 ps.PrimitiveSeqProtocolErrorCount = LE_32(ls->prot_err_cnt);
5671 5671 ps.InvalidTransmissionWordCount = LE_32(ls->inv_xmit_cnt);
5672 5672 ps.InvalidCRCCount = LE_32(ls->inv_crc_cnt);
5673 5673
5674 5674 rval = ddi_copyout((void *)&ps,
5675 5675 (void *)(uintptr_t)cmd->ResponseAdr,
5676 5676 sizeof (EXT_HBA_PORT_STAT), mode);
5677 5677 if (rval != 0) {
5678 5678 EL(ha, "failed, ddi_copyout\n");
5679 5679 cmd->Status = EXT_STATUS_COPY_ERR;
5680 5680 cmd->ResponseLen = 0;
5681 5681 } else {
5682 5682 cmd->ResponseLen = sizeof (EXT_HBA_PORT_STAT);
5683 5683 }
5684 5684 }
5685 5685
5686 5686 kmem_free(ls, sizeof (ql_link_stats_t));
5687 5687
5688 5688 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5689 5689 }
5690 5690
5691 5691 /*
5692 5692 * ql_get_statistics_fc
5693 5693 * Performs EXT_SC_GET_FC_STATISTICS subcommand. of EXT_CC_GET_DATA.
5694 5694 *
5695 5695 * Input:
5696 5696 * ha: adapter state pointer.
5697 5697 * cmd: Local EXT_IOCTL cmd struct pointer.
5698 5698 * mode: flags.
5699 5699 *
5700 5700 * Returns:
5701 5701 * None, request status indicated in cmd->Status.
5702 5702 *
5703 5703 * Context:
5704 5704 * Kernel context.
5705 5705 */
5706 5706 static void
5707 5707 ql_get_statistics_fc(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
5708 5708 {
5709 5709 EXT_HBA_PORT_STAT ps = {0};
5710 5710 ql_link_stats_t *ls;
5711 5711 int rval;
5712 5712 uint16_t qlnt;
5713 5713 EXT_DEST_ADDR pextdestaddr;
5714 5714 uint8_t *name;
5715 5715 ql_tgt_t *tq = NULL;
5716 5716 int retry = 10;
5717 5717
5718 5718 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5719 5719
5720 5720 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr,
5721 5721 (void *)&pextdestaddr, sizeof (EXT_DEST_ADDR), mode) != 0) {
5722 5722 EL(ha, "failed, ddi_copyin\n");
5723 5723 cmd->Status = EXT_STATUS_COPY_ERR;
5724 5724 cmd->ResponseLen = 0;
5725 5725 return;
5726 5726 }
5727 5727
5728 5728 qlnt = QLNT_PORT;
5729 5729 name = pextdestaddr.DestAddr.WWPN;
5730 5730
5731 5731 QL_PRINT_9(CE_CONT, "(%d): wwpn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
5732 5732 ha->instance, name[0], name[1], name[2], name[3], name[4],
5733 5733 name[5], name[6], name[7]);
5734 5734
5735 5735 tq = ql_find_port(ha, name, qlnt);
5736 5736
5737 5737 if (tq == NULL || !VALID_TARGET_ID(ha, tq->loop_id)) {
5738 5738 EL(ha, "failed, fc_port not found\n");
5739 5739 cmd->Status = EXT_STATUS_DEV_NOT_FOUND;
5740 5740 cmd->ResponseLen = 0;
5741 5741 return;
5742 5742 }
5743 5743
5744 5744 while (ha->task_daemon_flags &
5745 5745 (ABORT_ISP_ACTIVE | LOOP_RESYNC_ACTIVE | DRIVER_STALL)) {
5746 5746 ql_delay(ha, 10000000); /* 10 second delay */
5747 5747
5748 5748 retry--;
5749 5749
5750 5750 if (retry == 0) { /* effectively 100 seconds */
5751 5751 EL(ha, "failed, LOOP_NOT_READY\n");
5752 5752 cmd->Status = EXT_STATUS_BUSY;
5753 5753 cmd->ResponseLen = 0;
5754 5754 return;
5755 5755 }
5756 5756 }
5757 5757
5758 5758 /* Allocate memory for command. */
5759 5759 ls = kmem_zalloc(sizeof (ql_link_stats_t), KM_SLEEP);
5760 5760 if (ls == NULL) {
5761 5761 EL(ha, "failed, kmem_zalloc\n");
5762 5762 cmd->Status = EXT_STATUS_NO_MEMORY;
5763 5763 cmd->ResponseLen = 0;
5764 5764 return;
5765 5765 }
5766 5766
5767 5767 rval = ql_get_link_status(ha, tq->loop_id, sizeof (ql_link_stats_t),
5768 5768 (caddr_t)ls, 0);
5769 5769 if (rval != QL_SUCCESS) {
5770 5770 EL(ha, "failed, get_link_status=%xh, d_id=%xh\n", rval,
5771 5771 tq->d_id.b24);
5772 5772 cmd->Status = EXT_STATUS_MAILBOX;
5773 5773 cmd->DetailStatus = rval;
5774 5774 cmd->ResponseLen = 0;
5775 5775 } else {
5776 5776 ps.LinkFailureCount = LE_32(ls->link_fail_cnt);
5777 5777 ps.LossOfSyncCount = LE_32(ls->sync_loss_cnt);
5778 5778 ps.LossOfSignalsCount = LE_32(ls->signal_loss_cnt);
5779 5779 ps.PrimitiveSeqProtocolErrorCount = LE_32(ls->prot_err_cnt);
5780 5780 ps.InvalidTransmissionWordCount = LE_32(ls->inv_xmit_cnt);
5781 5781 ps.InvalidCRCCount = LE_32(ls->inv_crc_cnt);
5782 5782
5783 5783 rval = ddi_copyout((void *)&ps,
5784 5784 (void *)(uintptr_t)cmd->ResponseAdr,
5785 5785 sizeof (EXT_HBA_PORT_STAT), mode);
5786 5786
5787 5787 if (rval != 0) {
5788 5788 EL(ha, "failed, ddi_copyout\n");
5789 5789 cmd->Status = EXT_STATUS_COPY_ERR;
5790 5790 cmd->ResponseLen = 0;
5791 5791 } else {
5792 5792 cmd->ResponseLen = sizeof (EXT_HBA_PORT_STAT);
5793 5793 }
5794 5794 }
5795 5795
5796 5796 kmem_free(ls, sizeof (ql_link_stats_t));
5797 5797
5798 5798 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5799 5799 }
5800 5800
5801 5801 /*
5802 5802 * ql_get_statistics_fc4
5803 5803 * Performs EXT_SC_GET_FC_STATISTICS subcommand. of EXT_CC_GET_DATA.
5804 5804 *
5805 5805 * Input:
5806 5806 * ha: adapter state pointer.
5807 5807 * cmd: Local EXT_IOCTL cmd struct pointer.
5808 5808 * mode: flags.
5809 5809 *
5810 5810 * Returns:
5811 5811 * None, request status indicated in cmd->Status.
5812 5812 *
5813 5813 * Context:
5814 5814 * Kernel context.
5815 5815 */
5816 5816 static void
5817 5817 ql_get_statistics_fc4(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
5818 5818 {
5819 5819 uint32_t rval;
5820 5820 EXT_HBA_FC4STATISTICS fc4stats = {0};
5821 5821 ql_xioctl_t *xp = ha->xioctl;
5822 5822
5823 5823 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5824 5824
5825 5825 fc4stats.InputRequests = xp->IOInputRequests;
5826 5826 fc4stats.OutputRequests = xp->IOOutputRequests;
5827 5827 fc4stats.ControlRequests = xp->IOControlRequests;
5828 5828 fc4stats.InputMegabytes = xp->IOInputMByteCnt;
5829 5829 fc4stats.OutputMegabytes = xp->IOOutputMByteCnt;
5830 5830
5831 5831 rval = ddi_copyout((void *)&fc4stats,
5832 5832 (void *)(uintptr_t)cmd->ResponseAdr,
5833 5833 sizeof (EXT_HBA_FC4STATISTICS), mode);
5834 5834
5835 5835 if (rval != 0) {
5836 5836 EL(ha, "failed, ddi_copyout\n");
5837 5837 cmd->Status = EXT_STATUS_COPY_ERR;
5838 5838 cmd->ResponseLen = 0;
5839 5839 } else {
5840 5840 cmd->ResponseLen = sizeof (EXT_HBA_FC4STATISTICS);
5841 5841 }
5842 5842
5843 5843 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5844 5844 }
5845 5845
5846 5846 /*
5847 5847 * ql_set_led_state
5848 5848 * Performs EXT_SET_BEACON_STATE subcommand of EXT_CC_SET_DATA.
5849 5849 *
5850 5850 * Input:
5851 5851 * ha: adapter state pointer.
5852 5852 * cmd: Local EXT_IOCTL cmd struct pointer.
5853 5853 * mode: flags.
5854 5854 *
5855 5855 * Returns:
5856 5856 * None, request status indicated in cmd->Status.
5857 5857 *
5858 5858 * Context:
5859 5859 * Kernel context.
5860 5860 */
5861 5861 static void
5862 5862 ql_set_led_state(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
5863 5863 {
5864 5864 EXT_BEACON_CONTROL bstate;
5865 5865 uint32_t rval;
5866 5866 ql_xioctl_t *xp = ha->xioctl;
5867 5867
5868 5868 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5869 5869
5870 5870 if (cmd->RequestLen < sizeof (EXT_BEACON_CONTROL)) {
5871 5871 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
5872 5872 cmd->DetailStatus = sizeof (EXT_BEACON_CONTROL);
5873 5873 EL(ha, "done - failed, RequestLen < EXT_BEACON_CONTROL,"
5874 5874 " Len=%xh\n", cmd->RequestLen);
5875 5875 cmd->ResponseLen = 0;
5876 5876 return;
5877 5877 }
5878 5878
5879 5879 if (ha->device_id < 0x2300) {
5880 5880 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE;
5881 5881 cmd->DetailStatus = 0;
5882 5882 EL(ha, "done - failed, Invalid function for HBA model\n");
5883 5883 cmd->ResponseLen = 0;
5884 5884 return;
5885 5885 }
5886 5886
5887 5887 rval = ddi_copyin((void*)(uintptr_t)cmd->RequestAdr, &bstate,
5888 5888 cmd->RequestLen, mode);
5889 5889
5890 5890 if (rval != 0) {
5891 5891 cmd->Status = EXT_STATUS_COPY_ERR;
5892 5892 EL(ha, "done - failed, ddi_copyin\n");
5893 5893 return;
5894 5894 }
5895 5895
5896 5896 switch (bstate.State) {
5897 5897 case EXT_DEF_GRN_BLINK_OFF: /* turn beacon off */
5898 5898 if (xp->ledstate.BeaconState == BEACON_OFF) {
5899 5899 /* not quite an error -- LED state is already off */
5900 5900 cmd->Status = EXT_STATUS_OK;
5901 5901 EL(ha, "LED off request -- LED is already off\n");
5902 5902 break;
5903 5903 }
5904 5904
5905 5905 xp->ledstate.BeaconState = BEACON_OFF;
5906 5906 xp->ledstate.LEDflags = LED_ALL_OFF;
5907 5907
5908 5908 if ((rval = ql_wrapup_led(ha)) != QL_SUCCESS) {
5909 5909 cmd->Status = EXT_STATUS_MAILBOX;
5910 5910 } else {
5911 5911 cmd->Status = EXT_STATUS_OK;
5912 5912 }
5913 5913 break;
5914 5914
5915 5915 case EXT_DEF_GRN_BLINK_ON: /* turn beacon on */
5916 5916 if (xp->ledstate.BeaconState == BEACON_ON) {
5917 5917 /* not quite an error -- LED state is already on */
5918 5918 cmd->Status = EXT_STATUS_OK;
5919 5919 EL(ha, "LED on request - LED is already on\n");
5920 5920 break;
5921 5921 }
5922 5922
5923 5923 if ((rval = ql_setup_led(ha)) != QL_SUCCESS) {
5924 5924 cmd->Status = EXT_STATUS_MAILBOX;
5925 5925 break;
5926 5926 }
5927 5927
5928 5928 if (CFG_IST(ha, CFG_CTRL_24258081)) {
5929 5929 xp->ledstate.LEDflags = LED_YELLOW_24 | LED_AMBER_24;
5930 5930 } else {
5931 5931 xp->ledstate.LEDflags = LED_GREEN;
5932 5932 }
5933 5933 xp->ledstate.BeaconState = BEACON_ON;
5934 5934
5935 5935 cmd->Status = EXT_STATUS_OK;
5936 5936 break;
5937 5937 default:
5938 5938 cmd->Status = EXT_STATUS_ERR;
5939 5939 EL(ha, "failed, unknown state request %xh\n", bstate.State);
5940 5940 break;
5941 5941 }
5942 5942
5943 5943 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5944 5944 }
5945 5945
5946 5946 /*
5947 5947 * ql_get_led_state
5948 5948 * Performs EXT_GET_BEACON_STATE subcommand of EXT_CC_GET_DATA.
5949 5949 *
5950 5950 * Input:
5951 5951 * ha: adapter state pointer.
5952 5952 * cmd: Local EXT_IOCTL cmd struct pointer.
5953 5953 * mode: flags.
5954 5954 *
5955 5955 * Returns:
5956 5956 * None, request status indicated in cmd->Status.
5957 5957 *
5958 5958 * Context:
5959 5959 * Kernel context.
5960 5960 */
5961 5961 static void
5962 5962 ql_get_led_state(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
5963 5963 {
5964 5964 EXT_BEACON_CONTROL bstate = {0};
5965 5965 uint32_t rval;
5966 5966 ql_xioctl_t *xp = ha->xioctl;
5967 5967
5968 5968 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5969 5969
5970 5970 if (cmd->ResponseLen < sizeof (EXT_BEACON_CONTROL)) {
5971 5971 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
5972 5972 cmd->DetailStatus = sizeof (EXT_BEACON_CONTROL);
5973 5973 EL(ha, "done - failed, ResponseLen < EXT_BEACON_CONTROL,"
5974 5974 "Len=%xh\n", cmd->ResponseLen);
5975 5975 cmd->ResponseLen = 0;
5976 5976 return;
5977 5977 }
5978 5978
5979 5979 if (ha->device_id < 0x2300) {
5980 5980 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE;
5981 5981 cmd->DetailStatus = 0;
5982 5982 EL(ha, "done - failed, Invalid function for HBA model\n");
5983 5983 cmd->ResponseLen = 0;
5984 5984 return;
5985 5985 }
5986 5986
5987 5987 if (ha->task_daemon_flags & ABORT_ISP_ACTIVE) {
5988 5988 cmd->Status = EXT_STATUS_BUSY;
5989 5989 EL(ha, "done - failed, isp abort active\n");
5990 5990 cmd->ResponseLen = 0;
5991 5991 return;
5992 5992 }
5993 5993
5994 5994 /* inform the user of the current beacon state (off or on) */
5995 5995 bstate.State = xp->ledstate.BeaconState;
5996 5996
5997 5997 rval = ddi_copyout((void *)&bstate,
5998 5998 (void *)(uintptr_t)cmd->ResponseAdr,
5999 5999 sizeof (EXT_BEACON_CONTROL), mode);
6000 6000
6001 6001 if (rval != 0) {
6002 6002 EL(ha, "failed, ddi_copyout\n");
6003 6003 cmd->Status = EXT_STATUS_COPY_ERR;
6004 6004 cmd->ResponseLen = 0;
6005 6005 } else {
6006 6006 cmd->Status = EXT_STATUS_OK;
6007 6007 cmd->ResponseLen = sizeof (EXT_BEACON_CONTROL);
6008 6008 }
6009 6009
6010 6010 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
6011 6011 }
6012 6012
6013 6013 /*
6014 6014 * ql_blink_led
6015 6015 * Determine the next state of the LED and drive it
6016 6016 *
6017 6017 * Input:
6018 6018 * ha: adapter state pointer.
6019 6019 *
6020 6020 * Context:
6021 6021 * Interrupt context.
6022 6022 */
6023 6023 void
6024 6024 ql_blink_led(ql_adapter_state_t *ha)
6025 6025 {
6026 6026 uint32_t nextstate;
6027 6027 ql_xioctl_t *xp = ha->xioctl;
6028 6028
6029 6029 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
6030 6030
6031 6031 if (xp->ledstate.BeaconState == BEACON_ON) {
6032 6032 /* determine the next led state */
6033 6033 if (CFG_IST(ha, CFG_CTRL_24258081)) {
6034 6034 nextstate = (xp->ledstate.LEDflags) &
6035 6035 (~(RD32_IO_REG(ha, gpiod)));
6036 6036 } else {
6037 6037 nextstate = (xp->ledstate.LEDflags) &
6038 6038 (~(RD16_IO_REG(ha, gpiod)));
6039 6039 }
6040 6040
6041 6041 /* turn the led on or off */
6042 6042 ql_drive_led(ha, nextstate);
6043 6043 }
6044 6044
6045 6045 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
6046 6046 }
6047 6047
6048 6048 /*
6049 6049 * ql_drive_led
6050 6050 * drive the led's as determined by LEDflags
6051 6051 *
6052 6052 * Input:
6053 6053 * ha: adapter state pointer.
6054 6054 * LEDflags: LED flags
6055 6055 *
6056 6056 * Context:
6057 6057 * Kernel/Interrupt context.
6058 6058 */
6059 6059 static void
6060 6060 ql_drive_led(ql_adapter_state_t *ha, uint32_t LEDflags)
6061 6061 {
6062 6062
6063 6063 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
6064 6064
6065 6065 if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
6066 6066
6067 6067 uint16_t gpio_enable, gpio_data;
6068 6068
6069 6069 /* setup to send new data */
6070 6070 gpio_enable = (uint16_t)RD16_IO_REG(ha, gpioe);
6071 6071 gpio_enable = (uint16_t)(gpio_enable | LED_MASK);
6072 6072 WRT16_IO_REG(ha, gpioe, gpio_enable);
6073 6073
6074 6074 /* read current data and clear out old led data */
6075 6075 gpio_data = (uint16_t)RD16_IO_REG(ha, gpiod);
6076 6076 gpio_data = (uint16_t)(gpio_data & ~LED_MASK);
6077 6077
6078 6078 /* set in the new led data. */
6079 6079 gpio_data = (uint16_t)(gpio_data | LEDflags);
6080 6080
6081 6081 /* write out the new led data */
6082 6082 WRT16_IO_REG(ha, gpiod, gpio_data);
6083 6083
6084 6084 } else if (CFG_IST(ha, CFG_CTRL_24258081)) {
6085 6085
6086 6086 uint32_t gpio_data;
6087 6087
6088 6088 /* setup to send new data */
6089 6089 gpio_data = RD32_IO_REG(ha, gpiod);
6090 6090 gpio_data |= LED_MASK_UPDATE_24;
6091 6091 WRT32_IO_REG(ha, gpiod, gpio_data);
6092 6092
6093 6093 /* read current data and clear out old led data */
6094 6094 gpio_data = RD32_IO_REG(ha, gpiod);
6095 6095 gpio_data &= ~LED_MASK_COLORS_24;
6096 6096
6097 6097 /* set in the new led data */
6098 6098 gpio_data |= LEDflags;
6099 6099
6100 6100 /* write out the new led data */
6101 6101 WRT32_IO_REG(ha, gpiod, gpio_data);
6102 6102
6103 6103 } else {
6104 6104 EL(ha, "unsupported HBA: %xh", ha->device_id);
6105 6105 }
6106 6106
6107 6107 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
6108 6108 }
6109 6109
6110 6110 /*
6111 6111 * ql_setup_led
6112 6112 * Setup LED for driver control
6113 6113 *
6114 6114 * Input:
6115 6115 * ha: adapter state pointer.
6116 6116 *
6117 6117 * Context:
6118 6118 * Kernel/Interrupt context.
6119 6119 */
6120 6120 static uint32_t
6121 6121 ql_setup_led(ql_adapter_state_t *ha)
6122 6122 {
6123 6123 uint32_t rval;
6124 6124 ql_mbx_data_t mr;
6125 6125
6126 6126 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
6127 6127
6128 6128 /* decouple the LED control from the fw */
6129 6129 rval = ql_get_firmware_option(ha, &mr);
6130 6130 if (rval != QL_SUCCESS) {
6131 6131 EL(ha, "failed, get_firmware_option=%xh\n", rval);
6132 6132 return (rval);
6133 6133 }
6134 6134
6135 6135 /* set the appropriate options */
6136 6136 mr.mb[1] = (uint16_t)(mr.mb[1] | FO1_DISABLE_GPIO);
6137 6137
6138 6138 /* send it back to the firmware */
6139 6139 rval = ql_set_firmware_option(ha, &mr);
6140 6140 if (rval != QL_SUCCESS) {
6141 6141 EL(ha, "failed, set_firmware_option=%xh\n", rval);
6142 6142 return (rval);
6143 6143 }
6144 6144
6145 6145 /* initally, turn the LED's off */
6146 6146 ql_drive_led(ha, LED_ALL_OFF);
6147 6147
6148 6148 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
6149 6149
6150 6150 return (rval);
6151 6151 }
6152 6152
6153 6153 /*
6154 6154 * ql_wrapup_led
6155 6155 * Return LED control to the firmware
6156 6156 *
6157 6157 * Input:
6158 6158 * ha: adapter state pointer.
6159 6159 *
6160 6160 * Context:
6161 6161 * Kernel/Interrupt context.
6162 6162 */
6163 6163 static uint32_t
6164 6164 ql_wrapup_led(ql_adapter_state_t *ha)
6165 6165 {
6166 6166 uint32_t rval;
6167 6167 ql_mbx_data_t mr;
6168 6168
6169 6169 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
6170 6170
6171 6171 /* Turn all LED's off */
6172 6172 ql_drive_led(ha, LED_ALL_OFF);
6173 6173
6174 6174 if (CFG_IST(ha, CFG_CTRL_24258081)) {
6175 6175
6176 6176 uint32_t gpio_data;
6177 6177
6178 6178 /* disable the LED update mask */
6179 6179 gpio_data = RD32_IO_REG(ha, gpiod);
6180 6180 gpio_data &= ~LED_MASK_UPDATE_24;
6181 6181
6182 6182 /* write out the data */
6183 6183 WRT32_IO_REG(ha, gpiod, gpio_data);
6184 6184 }
6185 6185
6186 6186 /* give LED control back to the f/w */
6187 6187 rval = ql_get_firmware_option(ha, &mr);
6188 6188 if (rval != QL_SUCCESS) {
6189 6189 EL(ha, "failed, get_firmware_option=%xh\n", rval);
6190 6190 return (rval);
6191 6191 }
6192 6192
6193 6193 mr.mb[1] = (uint16_t)(mr.mb[1] & ~FO1_DISABLE_GPIO);
6194 6194
6195 6195 rval = ql_set_firmware_option(ha, &mr);
6196 6196 if (rval != QL_SUCCESS) {
6197 6197 EL(ha, "failed, set_firmware_option=%xh\n", rval);
6198 6198 return (rval);
6199 6199 }
6200 6200
6201 6201 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
6202 6202
6203 6203 return (rval);
6204 6204 }
6205 6205
6206 6206 /*
6207 6207 * ql_get_port_summary
6208 6208 * Performs EXT_SC_GET_PORT_SUMMARY subcommand. of EXT_CC_GET_DATA.
6209 6209 *
6210 6210 * The EXT_IOCTL->RequestAdr points to a single
6211 6211 * UINT32 which identifies the device type.
6212 6212 *
6213 6213 * Input:
6214 6214 * ha: adapter state pointer.
6215 6215 * cmd: Local EXT_IOCTL cmd struct pointer.
6216 6216 * mode: flags.
6217 6217 *
6218 6218 * Returns:
6219 6219 * None, request status indicated in cmd->Status.
6220 6220 *
6221 6221 * Context:
6222 6222 * Kernel context.
6223 6223 */
6224 6224 static void
6225 6225 ql_get_port_summary(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
6226 6226 {
6227 6227 EXT_DEVICEDATA dd = {0};
6228 6228 EXT_DEVICEDATA *uddp;
6229 6229 ql_link_t *link;
6230 6230 ql_tgt_t *tq;
6231 6231 uint32_t rlen, dev_type, index;
6232 6232 int rval = 0;
6233 6233 EXT_DEVICEDATAENTRY *uddep, *ddep;
6234 6234
6235 6235 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
6236 6236
6237 6237 ddep = &dd.EntryList[0];
6238 6238
6239 6239 /*
6240 6240 * Get the type of device the requestor is looking for.
6241 6241 *
6242 6242 * We ignore this for now.
6243 6243 */
6244 6244 rval = ddi_copyin((void *)(uintptr_t)cmd->RequestAdr,
6245 6245 (void *)&dev_type, sizeof (dev_type), mode);
6246 6246 if (rval != 0) {
6247 6247 cmd->Status = EXT_STATUS_COPY_ERR;
6248 6248 cmd->ResponseLen = 0;
6249 6249 EL(ha, "failed, ddi_copyin\n");
6250 6250 return;
6251 6251 }
6252 6252 /*
6253 6253 * Count the number of entries to be returned. Count devices
6254 6254 * that are offlline, but have been persistently bound.
6255 6255 */
6256 6256 for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
6257 6257 for (link = ha->dev[index].first; link != NULL;
6258 6258 link = link->next) {
6259 6259 tq = link->base_address;
6260 6260 if (tq->flags & TQF_INITIATOR_DEVICE ||
6261 6261 !VALID_TARGET_ID(ha, tq->loop_id)) {
6262 6262 continue; /* Skip this one */
6263 6263 }
6264 6264 dd.TotalDevices++;
6265 6265 }
6266 6266 }
6267 6267 /*
6268 6268 * Compute the number of entries that can be returned
6269 6269 * based upon the size of caller's response buffer.
6270 6270 */
6271 6271 dd.ReturnListEntryCount = 0;
6272 6272 if (dd.TotalDevices == 0) {
6273 6273 rlen = sizeof (EXT_DEVICEDATA) - sizeof (EXT_DEVICEDATAENTRY);
6274 6274 } else {
6275 6275 rlen = (uint32_t)(sizeof (EXT_DEVICEDATA) +
6276 6276 (sizeof (EXT_DEVICEDATAENTRY) * (dd.TotalDevices - 1)));
6277 6277 }
6278 6278 if (rlen > cmd->ResponseLen) {
6279 6279 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
6280 6280 cmd->DetailStatus = rlen;
6281 6281 EL(ha, "failed, rlen > ResponseLen, rlen=%d, Len=%d\n",
6282 6282 rlen, cmd->ResponseLen);
6283 6283 cmd->ResponseLen = 0;
6284 6284 return;
6285 6285 }
6286 6286 cmd->ResponseLen = 0;
6287 6287 uddp = (EXT_DEVICEDATA *)(uintptr_t)cmd->ResponseAdr;
6288 6288 uddep = &uddp->EntryList[0];
6289 6289 for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
6290 6290 for (link = ha->dev[index].first; link != NULL;
6291 6291 link = link->next) {
6292 6292 tq = link->base_address;
6293 6293 if (tq->flags & TQF_INITIATOR_DEVICE ||
6294 6294 !VALID_TARGET_ID(ha, tq->loop_id)) {
6295 6295 continue; /* Skip this one */
6296 6296 }
6297 6297
6298 6298 bzero((void *)ddep, sizeof (EXT_DEVICEDATAENTRY));
6299 6299
6300 6300 bcopy(tq->node_name, ddep->NodeWWN, 8);
6301 6301 bcopy(tq->port_name, ddep->PortWWN, 8);
6302 6302
6303 6303 ddep->PortID[0] = tq->d_id.b.domain;
6304 6304 ddep->PortID[1] = tq->d_id.b.area;
6305 6305 ddep->PortID[2] = tq->d_id.b.al_pa;
6306 6306
6307 6307 bcopy(tq->port_name,
6308 6308 (caddr_t)&ddep->TargetAddress.Target, 8);
6309 6309
6310 6310 ddep->DeviceFlags = tq->flags;
6311 6311 ddep->LoopID = tq->loop_id;
6312 6312 QL_PRINT_9(CE_CONT, "(%d): Tgt=%lld, loop=%xh, "
6313 6313 "wwnn=%02x%02x%02x%02x%02x%02x%02x%02x, "
6314 6314 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
6315 6315 ha->instance, ddep->TargetAddress.Target,
6316 6316 ddep->LoopID, ddep->NodeWWN[0], ddep->NodeWWN[1],
6317 6317 ddep->NodeWWN[2], ddep->NodeWWN[3],
6318 6318 ddep->NodeWWN[4], ddep->NodeWWN[5],
6319 6319 ddep->NodeWWN[6], ddep->NodeWWN[7],
6320 6320 ddep->PortWWN[0], ddep->PortWWN[1],
6321 6321 ddep->PortWWN[2], ddep->PortWWN[3],
6322 6322 ddep->PortWWN[4], ddep->PortWWN[5],
6323 6323 ddep->PortWWN[6], ddep->PortWWN[7]);
6324 6324 rval = ddi_copyout((void *)ddep, (void *)uddep,
6325 6325 sizeof (EXT_DEVICEDATAENTRY), mode);
6326 6326
6327 6327 if (rval != 0) {
6328 6328 cmd->Status = EXT_STATUS_COPY_ERR;
6329 6329 cmd->ResponseLen = 0;
6330 6330 EL(ha, "failed, ddi_copyout\n");
6331 6331 break;
6332 6332 }
6333 6333 dd.ReturnListEntryCount++;
6334 6334 uddep++;
6335 6335 cmd->ResponseLen += (uint32_t)
6336 6336 sizeof (EXT_DEVICEDATAENTRY);
6337 6337 }
6338 6338 }
6339 6339 rval = ddi_copyout((void *)&dd, (void *)uddp,
6340 6340 sizeof (EXT_DEVICEDATA) - sizeof (EXT_DEVICEDATAENTRY), mode);
6341 6341
6342 6342 if (rval != 0) {
6343 6343 cmd->Status = EXT_STATUS_COPY_ERR;
6344 6344 cmd->ResponseLen = 0;
6345 6345 EL(ha, "failed, ddi_copyout-2\n");
6346 6346 } else {
6347 6347 cmd->ResponseLen += (uint32_t)sizeof (EXT_DEVICEDATAENTRY);
6348 6348 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
6349 6349 }
6350 6350 }
6351 6351
6352 6352 /*
6353 6353 * ql_get_target_id
6354 6354 * Performs EXT_SC_GET_TARGET_ID subcommand. of EXT_CC_GET_DATA.
6355 6355 *
6356 6356 * Input:
6357 6357 * ha: adapter state pointer.
6358 6358 * cmd: Local EXT_IOCTL cmd struct pointer.
6359 6359 * mode: flags.
6360 6360 *
6361 6361 * Returns:
↓ open down ↓ |
6361 lines elided |
↑ open up ↑ |
6362 6362 * None, request status indicated in cmd->Status.
6363 6363 *
6364 6364 * Context:
6365 6365 * Kernel context.
6366 6366 */
6367 6367 static void
6368 6368 ql_get_target_id(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
6369 6369 {
6370 6370 uint32_t rval;
6371 6371 uint16_t qlnt;
6372 - EXT_DEST_ADDR extdestaddr = {0};
6372 + EXT_DEST_ADDR extdestaddr = {{{0}}};
6373 6373 uint8_t *name;
6374 6374 uint8_t wwpn[EXT_DEF_WWN_NAME_SIZE];
6375 6375 ql_tgt_t *tq;
6376 6376
6377 6377 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
6378 6378
6379 6379 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr,
6380 6380 (void*)wwpn, sizeof (EXT_DEST_ADDR), mode) != 0) {
6381 6381 EL(ha, "failed, ddi_copyin\n");
6382 6382 cmd->Status = EXT_STATUS_COPY_ERR;
6383 6383 cmd->ResponseLen = 0;
6384 6384 return;
6385 6385 }
6386 6386
6387 6387 qlnt = QLNT_PORT;
6388 6388 name = wwpn;
6389 6389 QL_PRINT_9(CE_CONT, "(%d): wwpn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
6390 6390 ha->instance, name[0], name[1], name[2], name[3], name[4],
6391 6391 name[5], name[6], name[7]);
6392 6392
6393 6393 tq = ql_find_port(ha, name, qlnt);
6394 6394 if (tq == NULL || !VALID_TARGET_ID(ha, tq->loop_id)) {
6395 6395 EL(ha, "failed, fc_port not found\n");
6396 6396 cmd->Status = EXT_STATUS_DEV_NOT_FOUND;
6397 6397 cmd->ResponseLen = 0;
6398 6398 return;
6399 6399 }
6400 6400
6401 6401 bcopy(tq->port_name, (caddr_t)&extdestaddr.DestAddr.ScsiAddr.Target, 8);
6402 6402
6403 6403 rval = ddi_copyout((void *)&extdestaddr,
6404 6404 (void *)(uintptr_t)cmd->ResponseAdr, sizeof (EXT_DEST_ADDR), mode);
6405 6405 if (rval != 0) {
6406 6406 EL(ha, "failed, ddi_copyout\n");
6407 6407 cmd->Status = EXT_STATUS_COPY_ERR;
6408 6408 cmd->ResponseLen = 0;
6409 6409 }
6410 6410
6411 6411 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
6412 6412 }
6413 6413
6414 6414 /*
6415 6415 * ql_setup_fcache
6416 6416 * Populates selected flash sections into the cache
6417 6417 *
6418 6418 * Input:
6419 6419 * ha = adapter state pointer.
6420 6420 *
6421 6421 * Returns:
6422 6422 * ql local function return status code.
6423 6423 *
6424 6424 * Context:
6425 6425 * Kernel context.
6426 6426 *
6427 6427 * Note:
6428 6428 * Driver must be in stalled state prior to entering or
6429 6429 * add code to this function prior to calling ql_setup_flash()
6430 6430 */
6431 6431 int
6432 6432 ql_setup_fcache(ql_adapter_state_t *ha)
6433 6433 {
6434 6434 int rval;
6435 6435 uint32_t freadpos = 0;
6436 6436 uint32_t fw_done = 0;
6437 6437 ql_fcache_t *head = NULL;
6438 6438 ql_fcache_t *tail = NULL;
6439 6439 ql_fcache_t *ftmp;
6440 6440
6441 6441 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
6442 6442
6443 6443 CACHE_LOCK(ha);
6444 6444
6445 6445 /* If we already have populated it, rtn */
6446 6446 if (ha->fcache != NULL) {
6447 6447 CACHE_UNLOCK(ha);
6448 6448 EL(ha, "buffer already populated\n");
6449 6449 return (QL_SUCCESS);
6450 6450 }
6451 6451
6452 6452 ql_flash_nvram_defaults(ha);
6453 6453
6454 6454 if ((rval = ql_setup_flash(ha)) != QL_SUCCESS) {
6455 6455 CACHE_UNLOCK(ha);
6456 6456 EL(ha, "unable to setup flash; rval=%xh\n", rval);
6457 6457 return (rval);
6458 6458 }
6459 6459
6460 6460 while (freadpos != 0xffffffff) {
6461 6461 /* Allocate & populate this node */
6462 6462 if ((ftmp = ql_setup_fnode(ha)) == NULL) {
6463 6463 EL(ha, "node alloc failed\n");
6464 6464 rval = QL_FUNCTION_FAILED;
6465 6465 break;
6466 6466 }
6467 6467
6468 6468 /* link in the new node */
6469 6469 if (head == NULL) {
6470 6470 head = tail = ftmp;
6471 6471 } else {
6472 6472 tail->next = ftmp;
6473 6473 tail = ftmp;
6474 6474 }
6475 6475
6476 6476 /* Do the firmware node first for 24xx/25xx's */
6477 6477 if (fw_done == 0) {
6478 6478 if (CFG_IST(ha, CFG_CTRL_24258081)) {
6479 6479 freadpos = ha->flash_fw_addr << 2;
6480 6480 }
6481 6481 fw_done = 1;
6482 6482 }
6483 6483
6484 6484 if ((rval = ql_dump_fcode(ha, ftmp->buf, FBUFSIZE,
6485 6485 freadpos)) != QL_SUCCESS) {
6486 6486 EL(ha, "failed, 24xx dump_fcode"
6487 6487 " pos=%xh rval=%xh\n", freadpos, rval);
6488 6488 rval = QL_FUNCTION_FAILED;
6489 6489 break;
6490 6490 }
6491 6491
6492 6492 /* checkout the pci data / format */
6493 6493 if (ql_check_pci(ha, ftmp, &freadpos)) {
6494 6494 EL(ha, "flash header incorrect\n");
6495 6495 rval = QL_FUNCTION_FAILED;
6496 6496 break;
6497 6497 }
6498 6498 }
6499 6499
6500 6500 if (rval != QL_SUCCESS) {
6501 6501 /* release all resources we have */
6502 6502 ftmp = head;
6503 6503 while (ftmp != NULL) {
6504 6504 tail = ftmp->next;
6505 6505 kmem_free(ftmp->buf, FBUFSIZE);
6506 6506 kmem_free(ftmp, sizeof (ql_fcache_t));
6507 6507 ftmp = tail;
6508 6508 }
6509 6509
6510 6510 EL(ha, "failed, done\n");
6511 6511 } else {
6512 6512 ha->fcache = head;
6513 6513 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
6514 6514 }
6515 6515 CACHE_UNLOCK(ha);
6516 6516
6517 6517 return (rval);
6518 6518 }
6519 6519
6520 6520 /*
6521 6521 * ql_update_fcache
6522 6522 * re-populates updated flash into the fcache. If
6523 6523 * fcache does not exist (e.g., flash was empty/invalid on
6524 6524 * boot), this routine will create and the populate it.
6525 6525 *
6526 6526 * Input:
6527 6527 * ha = adapter state pointer.
6528 6528 * *bpf = Pointer to flash buffer.
6529 6529 * bsize = Size of flash buffer.
6530 6530 *
6531 6531 * Returns:
6532 6532 *
6533 6533 * Context:
6534 6534 * Kernel context.
6535 6535 */
6536 6536 void
6537 6537 ql_update_fcache(ql_adapter_state_t *ha, uint8_t *bfp, uint32_t bsize)
6538 6538 {
6539 6539 int rval = QL_SUCCESS;
6540 6540 uint32_t freadpos = 0;
6541 6541 uint32_t fw_done = 0;
6542 6542 ql_fcache_t *head = NULL;
6543 6543 ql_fcache_t *tail = NULL;
6544 6544 ql_fcache_t *ftmp;
6545 6545
6546 6546 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
6547 6547
6548 6548 while (freadpos != 0xffffffff) {
6549 6549
6550 6550 /* Allocate & populate this node */
6551 6551
6552 6552 if ((ftmp = ql_setup_fnode(ha)) == NULL) {
6553 6553 EL(ha, "node alloc failed\n");
6554 6554 rval = QL_FUNCTION_FAILED;
6555 6555 break;
6556 6556 }
6557 6557
6558 6558 /* link in the new node */
6559 6559 if (head == NULL) {
6560 6560 head = tail = ftmp;
6561 6561 } else {
6562 6562 tail->next = ftmp;
6563 6563 tail = ftmp;
6564 6564 }
6565 6565
6566 6566 /* Do the firmware node first for 24xx's */
6567 6567 if (fw_done == 0) {
6568 6568 if (CFG_IST(ha, CFG_CTRL_24258081)) {
6569 6569 freadpos = ha->flash_fw_addr << 2;
6570 6570 }
6571 6571 fw_done = 1;
6572 6572 }
6573 6573
6574 6574 /* read in first FBUFSIZE bytes of this flash section */
6575 6575 if (freadpos+FBUFSIZE > bsize) {
6576 6576 EL(ha, "passed buffer too small; fr=%xh, bsize=%xh\n",
6577 6577 freadpos, bsize);
6578 6578 rval = QL_FUNCTION_FAILED;
6579 6579 break;
6580 6580 }
6581 6581 bcopy(bfp+freadpos, ftmp->buf, FBUFSIZE);
6582 6582
6583 6583 /* checkout the pci data / format */
6584 6584 if (ql_check_pci(ha, ftmp, &freadpos)) {
6585 6585 EL(ha, "flash header incorrect\n");
6586 6586 rval = QL_FUNCTION_FAILED;
6587 6587 break;
6588 6588 }
6589 6589 }
6590 6590
6591 6591 if (rval != QL_SUCCESS) {
6592 6592 /*
6593 6593 * release all resources we have
6594 6594 */
6595 6595 ql_fcache_rel(head);
6596 6596 EL(ha, "failed, done\n");
6597 6597 } else {
6598 6598 /*
6599 6599 * Release previous fcache resources and update with new
6600 6600 */
6601 6601 CACHE_LOCK(ha);
6602 6602 ql_fcache_rel(ha->fcache);
6603 6603 ha->fcache = head;
6604 6604 CACHE_UNLOCK(ha);
6605 6605
6606 6606 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
6607 6607 }
6608 6608 }
6609 6609
6610 6610 /*
6611 6611 * ql_setup_fnode
6612 6612 * Allocates fcache node
6613 6613 *
6614 6614 * Input:
6615 6615 * ha = adapter state pointer.
6616 6616 * node = point to allocated fcache node (NULL = failed)
6617 6617 *
6618 6618 * Returns:
6619 6619 *
6620 6620 * Context:
6621 6621 * Kernel context.
6622 6622 *
6623 6623 * Note:
6624 6624 * Driver must be in stalled state prior to entering or
6625 6625 * add code to this function prior to calling ql_setup_flash()
6626 6626 */
6627 6627 static ql_fcache_t *
6628 6628 ql_setup_fnode(ql_adapter_state_t *ha)
6629 6629 {
6630 6630 ql_fcache_t *fnode = NULL;
6631 6631
6632 6632 if ((fnode = (ql_fcache_t *)(kmem_zalloc(sizeof (ql_fcache_t),
6633 6633 KM_SLEEP))) == NULL) {
6634 6634 EL(ha, "fnode alloc failed\n");
6635 6635 fnode = NULL;
6636 6636 } else if ((fnode->buf = (uint8_t *)(kmem_zalloc(FBUFSIZE,
6637 6637 KM_SLEEP))) == NULL) {
6638 6638 EL(ha, "buf alloc failed\n");
6639 6639 kmem_free(fnode, sizeof (ql_fcache_t));
6640 6640 fnode = NULL;
6641 6641 } else {
6642 6642 fnode->buflen = FBUFSIZE;
6643 6643 }
6644 6644
6645 6645 return (fnode);
6646 6646 }
6647 6647
6648 6648 /*
6649 6649 * ql_fcache_rel
6650 6650 * Releases the fcache resources
6651 6651 *
6652 6652 * Input:
6653 6653 * ha = adapter state pointer.
6654 6654 * head = Pointer to fcache linked list
6655 6655 *
6656 6656 * Returns:
6657 6657 *
6658 6658 * Context:
6659 6659 * Kernel context.
6660 6660 *
6661 6661 */
6662 6662 void
6663 6663 ql_fcache_rel(ql_fcache_t *head)
6664 6664 {
6665 6665 ql_fcache_t *ftmp = head;
6666 6666 ql_fcache_t *tail;
6667 6667
6668 6668 /* release all resources we have */
6669 6669 while (ftmp != NULL) {
6670 6670 tail = ftmp->next;
6671 6671 kmem_free(ftmp->buf, FBUFSIZE);
6672 6672 kmem_free(ftmp, sizeof (ql_fcache_t));
6673 6673 ftmp = tail;
6674 6674 }
6675 6675 }
6676 6676
6677 6677 /*
6678 6678 * ql_update_flash_caches
6679 6679 * Updates driver flash caches
6680 6680 *
6681 6681 * Input:
6682 6682 * ha: adapter state pointer.
6683 6683 *
6684 6684 * Context:
6685 6685 * Kernel context.
6686 6686 */
6687 6687 static void
6688 6688 ql_update_flash_caches(ql_adapter_state_t *ha)
6689 6689 {
6690 6690 uint32_t len;
6691 6691 ql_link_t *link;
6692 6692 ql_adapter_state_t *ha2;
6693 6693
6694 6694 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
6695 6695
6696 6696 /* Get base path length. */
6697 6697 for (len = (uint32_t)strlen(ha->devpath); len; len--) {
6698 6698 if (ha->devpath[len] == ',' ||
6699 6699 ha->devpath[len] == '@') {
6700 6700 break;
6701 6701 }
6702 6702 }
6703 6703
6704 6704 /* Reset fcache on all adapter instances. */
6705 6705 for (link = ql_hba.first; link != NULL; link = link->next) {
6706 6706 ha2 = link->base_address;
6707 6707
6708 6708 if (strncmp(ha->devpath, ha2->devpath, len) != 0) {
6709 6709 continue;
6710 6710 }
6711 6711
6712 6712 CACHE_LOCK(ha2);
6713 6713 ql_fcache_rel(ha2->fcache);
6714 6714 ha2->fcache = NULL;
6715 6715
6716 6716 if (CFG_IST(ha, CFG_CTRL_24258081)) {
6717 6717 if (ha2->vcache != NULL) {
6718 6718 kmem_free(ha2->vcache, QL_24XX_VPD_SIZE);
6719 6719 ha2->vcache = NULL;
6720 6720 }
6721 6721 }
6722 6722 CACHE_UNLOCK(ha2);
6723 6723
6724 6724 (void) ql_setup_fcache(ha2);
6725 6725 }
6726 6726
6727 6727 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
6728 6728 }
6729 6729
6730 6730 /*
6731 6731 * ql_get_fbuf
6732 6732 * Search the fcache list for the type specified
6733 6733 *
6734 6734 * Input:
6735 6735 * fptr = Pointer to fcache linked list
6736 6736 * ftype = Type of image to be returned.
6737 6737 *
6738 6738 * Returns:
6739 6739 * Pointer to ql_fcache_t.
6740 6740 * NULL means not found.
6741 6741 *
6742 6742 * Context:
6743 6743 * Kernel context.
6744 6744 *
6745 6745 *
6746 6746 */
6747 6747 ql_fcache_t *
6748 6748 ql_get_fbuf(ql_fcache_t *fptr, uint32_t ftype)
6749 6749 {
6750 6750 while (fptr != NULL) {
6751 6751 /* does this image meet criteria? */
6752 6752 if (ftype & fptr->type) {
6753 6753 break;
6754 6754 }
6755 6755 fptr = fptr->next;
6756 6756 }
6757 6757 return (fptr);
6758 6758 }
6759 6759
6760 6760 /*
6761 6761 * ql_check_pci
6762 6762 *
6763 6763 * checks the passed buffer for a valid pci signature and
6764 6764 * expected (and in range) pci length values.
6765 6765 *
6766 6766 * For firmware type, a pci header is added since the image in
6767 6767 * the flash does not have one (!!!).
6768 6768 *
6769 6769 * On successful pci check, nextpos adjusted to next pci header.
6770 6770 *
6771 6771 * Returns:
6772 6772 * -1 --> last pci image
6773 6773 * 0 --> pci header valid
6774 6774 * 1 --> pci header invalid.
6775 6775 *
6776 6776 * Context:
6777 6777 * Kernel context.
6778 6778 */
6779 6779 static int
6780 6780 ql_check_pci(ql_adapter_state_t *ha, ql_fcache_t *fcache, uint32_t *nextpos)
6781 6781 {
6782 6782 pci_header_t *pcih;
6783 6783 pci_data_t *pcid;
6784 6784 uint32_t doff;
6785 6785 uint8_t *pciinfo;
6786 6786
6787 6787 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
6788 6788
6789 6789 if (fcache != NULL) {
6790 6790 pciinfo = fcache->buf;
6791 6791 } else {
6792 6792 EL(ha, "failed, null fcache ptr passed\n");
6793 6793 return (1);
6794 6794 }
6795 6795
6796 6796 if (pciinfo == NULL) {
6797 6797 EL(ha, "failed, null pciinfo ptr passed\n");
6798 6798 return (1);
6799 6799 }
6800 6800
6801 6801 if (CFG_IST(ha, CFG_SBUS_CARD)) {
6802 6802 caddr_t bufp;
6803 6803 uint_t len;
6804 6804
6805 6805 if (pciinfo[0] != SBUS_CODE_FCODE) {
6806 6806 EL(ha, "failed, unable to detect sbus fcode\n");
6807 6807 return (1);
6808 6808 }
6809 6809 fcache->type = FTYPE_FCODE;
6810 6810
6811 6811 /*LINTED [Solaris DDI_DEV_T_ANY Lint error]*/
6812 6812 if (ddi_getlongprop(DDI_DEV_T_ANY, ha->dip,
6813 6813 PROP_LEN_AND_VAL_ALLOC | DDI_PROP_DONTPASS |
6814 6814 DDI_PROP_CANSLEEP, "version", (caddr_t)&bufp,
6815 6815 (int *)&len) == DDI_PROP_SUCCESS) {
6816 6816
6817 6817 (void) snprintf(fcache->verstr,
6818 6818 FCHBA_OPTION_ROM_VERSION_LEN, "%s", bufp);
6819 6819 kmem_free(bufp, len);
6820 6820 }
6821 6821
↓ open down ↓ |
439 lines elided |
↑ open up ↑ |
6822 6822 *nextpos = 0xffffffff;
6823 6823
6824 6824 QL_PRINT_9(CE_CONT, "(%d): CFG_SBUS_CARD, done\n",
6825 6825 ha->instance);
6826 6826
6827 6827 return (0);
6828 6828 }
6829 6829
6830 6830 if (*nextpos == ha->flash_fw_addr << 2) {
6831 6831
6832 - pci_header_t fwh = {0};
6833 - pci_data_t fwd = {0};
6832 + pci_header_t fwh = {{0}};
6833 + pci_data_t fwd = {{0}};
6834 6834 uint8_t *buf, *bufp;
6835 6835
6836 6836 /*
6837 6837 * Build a pci header for the firmware module
6838 6838 */
6839 6839 if ((buf = (uint8_t *)(kmem_zalloc(FBUFSIZE, KM_SLEEP))) ==
6840 6840 NULL) {
6841 6841 EL(ha, "failed, unable to allocate buffer\n");
6842 6842 return (1);
6843 6843 }
6844 6844
6845 6845 fwh.signature[0] = PCI_HEADER0;
6846 6846 fwh.signature[1] = PCI_HEADER1;
6847 6847 fwh.dataoffset[0] = LSB(sizeof (pci_header_t));
6848 6848 fwh.dataoffset[1] = MSB(sizeof (pci_header_t));
6849 6849
6850 6850 fwd.signature[0] = 'P';
6851 6851 fwd.signature[1] = 'C';
6852 6852 fwd.signature[2] = 'I';
6853 6853 fwd.signature[3] = 'R';
6854 6854 fwd.codetype = PCI_CODE_FW;
6855 6855 fwd.pcidatalen[0] = LSB(sizeof (pci_data_t));
6856 6856 fwd.pcidatalen[1] = MSB(sizeof (pci_data_t));
6857 6857
6858 6858 bufp = buf;
6859 6859 bcopy(&fwh, bufp, sizeof (pci_header_t));
6860 6860 bufp += sizeof (pci_header_t);
6861 6861 bcopy(&fwd, bufp, sizeof (pci_data_t));
6862 6862 bufp += sizeof (pci_data_t);
6863 6863
6864 6864 bcopy(fcache->buf, bufp, (FBUFSIZE - sizeof (pci_header_t) -
6865 6865 sizeof (pci_data_t)));
6866 6866 bcopy(buf, fcache->buf, FBUFSIZE);
6867 6867
6868 6868 fcache->type = FTYPE_FW;
6869 6869
6870 6870 (void) snprintf(fcache->verstr, FCHBA_OPTION_ROM_VERSION_LEN,
6871 6871 "%d.%02d.%02d", fcache->buf[19], fcache->buf[23],
6872 6872 fcache->buf[27]);
6873 6873
6874 6874 if (CFG_IST(ha, CFG_CTRL_81XX)) {
6875 6875 *nextpos = 0x200000;
6876 6876 } else if (CFG_IST(ha, CFG_CTRL_8021)) {
6877 6877 *nextpos = 0x80000;
6878 6878 } else {
6879 6879 *nextpos = 0;
6880 6880 }
6881 6881 kmem_free(buf, FBUFSIZE);
6882 6882
6883 6883 QL_PRINT_9(CE_CONT, "(%d): FTYPE_FW, done\n", ha->instance);
6884 6884
6885 6885 return (0);
6886 6886 }
6887 6887
6888 6888 /* get to the pci header image length */
6889 6889 pcih = (pci_header_t *)pciinfo;
6890 6890
6891 6891 doff = pcih->dataoffset[0] | (pcih->dataoffset[1] << 8);
6892 6892
6893 6893 /* some header section sanity check */
6894 6894 if (pcih->signature[0] != PCI_HEADER0 ||
6895 6895 pcih->signature[1] != PCI_HEADER1 || doff > 50) {
6896 6896 EL(ha, "buffer format error: s0=%xh, s1=%xh, off=%xh\n",
6897 6897 pcih->signature[0], pcih->signature[1], doff);
6898 6898 return (1);
6899 6899 }
6900 6900
6901 6901 pcid = (pci_data_t *)(pciinfo + doff);
6902 6902
6903 6903 /* a slight sanity data section check */
6904 6904 if (pcid->signature[0] != 'P' || pcid->signature[1] != 'C' ||
6905 6905 pcid->signature[2] != 'I' || pcid->signature[3] != 'R') {
6906 6906 EL(ha, "failed, data sig mismatch!\n");
6907 6907 return (1);
6908 6908 }
6909 6909
6910 6910 if (pcid->indicator == PCI_IND_LAST_IMAGE) {
6911 6911 QL_PRINT_9(CE_CONT, "(%d): last image\n", ha->instance);
6912 6912 if (CFG_IST(ha, CFG_CTRL_24258081)) {
6913 6913 ql_flash_layout_table(ha, *nextpos +
6914 6914 (pcid->imagelength[0] | (pcid->imagelength[1] <<
6915 6915 8)) * PCI_SECTOR_SIZE);
6916 6916 (void) ql_24xx_flash_desc(ha);
6917 6917 }
6918 6918 *nextpos = 0xffffffff;
6919 6919 } else {
6920 6920 /* adjust the next flash read start position */
6921 6921 *nextpos += (pcid->imagelength[0] |
6922 6922 (pcid->imagelength[1] << 8)) * PCI_SECTOR_SIZE;
6923 6923 }
6924 6924
6925 6925 switch (pcid->codetype) {
6926 6926 case PCI_CODE_X86PC:
6927 6927 fcache->type = FTYPE_BIOS;
6928 6928 break;
6929 6929 case PCI_CODE_FCODE:
6930 6930 fcache->type = FTYPE_FCODE;
6931 6931 break;
6932 6932 case PCI_CODE_EFI:
6933 6933 fcache->type = FTYPE_EFI;
6934 6934 break;
6935 6935 case PCI_CODE_HPPA:
6936 6936 fcache->type = FTYPE_HPPA;
6937 6937 break;
6938 6938 default:
6939 6939 fcache->type = FTYPE_UNKNOWN;
6940 6940 break;
6941 6941 }
6942 6942
6943 6943 (void) snprintf(fcache->verstr, FCHBA_OPTION_ROM_VERSION_LEN,
6944 6944 "%d.%02d", pcid->revisionlevel[1], pcid->revisionlevel[0]);
6945 6945
6946 6946 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
6947 6947
6948 6948 return (0);
6949 6949 }
6950 6950
6951 6951 /*
6952 6952 * ql_flash_layout_table
6953 6953 * Obtains flash addresses from table
6954 6954 *
6955 6955 * Input:
6956 6956 * ha: adapter state pointer.
6957 6957 * flt_paddr: flash layout pointer address.
6958 6958 *
6959 6959 * Context:
6960 6960 * Kernel context.
6961 6961 */
6962 6962 static void
6963 6963 ql_flash_layout_table(ql_adapter_state_t *ha, uint32_t flt_paddr)
6964 6964 {
6965 6965 ql_flt_ptr_t *fptr;
6966 6966 uint8_t *bp;
6967 6967 int rval;
6968 6968 uint32_t len, faddr, cnt;
6969 6969 uint16_t chksum, w16;
6970 6970
6971 6971 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
6972 6972
6973 6973 /* Process flash layout table header */
6974 6974 len = sizeof (ql_flt_ptr_t);
6975 6975 if ((bp = kmem_zalloc(len, KM_SLEEP)) == NULL) {
6976 6976 EL(ha, "kmem_zalloc=null\n");
6977 6977 return;
6978 6978 }
6979 6979
6980 6980 /* Process pointer to flash layout table */
6981 6981 if ((rval = ql_dump_fcode(ha, bp, len, flt_paddr)) != QL_SUCCESS) {
6982 6982 EL(ha, "fptr dump_flash pos=%xh, status=%xh\n", flt_paddr,
6983 6983 rval);
6984 6984 kmem_free(bp, len);
6985 6985 return;
6986 6986 }
6987 6987 fptr = (ql_flt_ptr_t *)bp;
6988 6988
6989 6989 /* Verify pointer to flash layout table. */
6990 6990 for (chksum = 0, cnt = 0; cnt < len; cnt += 2) {
6991 6991 w16 = (uint16_t)CHAR_TO_SHORT(bp[cnt], bp[cnt + 1]);
6992 6992 chksum += w16;
6993 6993 }
6994 6994 if (chksum != 0 || fptr->sig[0] != 'Q' || fptr->sig[1] != 'F' ||
6995 6995 fptr->sig[2] != 'L' || fptr->sig[3] != 'T') {
6996 6996 EL(ha, "ptr chksum=%xh, sig=%c%c%c%c\n", chksum, fptr->sig[0],
6997 6997 fptr->sig[1], fptr->sig[2], fptr->sig[3]);
6998 6998 kmem_free(bp, len);
6999 6999 return;
7000 7000 }
7001 7001 faddr = CHAR_TO_LONG(fptr->addr[0], fptr->addr[1], fptr->addr[2],
7002 7002 fptr->addr[3]);
7003 7003
7004 7004 kmem_free(bp, len);
7005 7005
7006 7006 ql_process_flt(ha, faddr);
7007 7007
7008 7008 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
7009 7009 }
7010 7010
7011 7011 /*
7012 7012 * ql_process_flt
7013 7013 * Obtains flash addresses from flash layout table
7014 7014 *
7015 7015 * Input:
7016 7016 * ha: adapter state pointer.
7017 7017 * faddr: flash layout table byte address.
7018 7018 *
7019 7019 * Context:
7020 7020 * Kernel context.
7021 7021 */
7022 7022 static void
7023 7023 ql_process_flt(ql_adapter_state_t *ha, uint32_t faddr)
7024 7024 {
7025 7025 ql_flt_hdr_t *fhdr;
7026 7026 ql_flt_region_t *frgn;
7027 7027 uint8_t *bp, *eaddr, nv_rg, vpd_rg;
7028 7028 int rval;
7029 7029 uint32_t len, cnt, fe_addr;
7030 7030 uint16_t chksum, w16;
7031 7031
7032 7032 QL_PRINT_9(CE_CONT, "(%d): started faddr=%xh\n", ha->instance, faddr);
7033 7033
7034 7034 /* Process flash layout table header */
7035 7035 if ((bp = kmem_zalloc(FLASH_LAYOUT_TABLE_SIZE, KM_SLEEP)) == NULL) {
7036 7036 EL(ha, "kmem_zalloc=null\n");
7037 7037 return;
7038 7038 }
7039 7039 fhdr = (ql_flt_hdr_t *)bp;
7040 7040
7041 7041 /* Process flash layout table. */
7042 7042 if ((rval = ql_dump_fcode(ha, bp, FLASH_LAYOUT_TABLE_SIZE, faddr)) !=
7043 7043 QL_SUCCESS) {
7044 7044 EL(ha, "fhdr dump_flash pos=%xh, status=%xh\n", faddr, rval);
7045 7045 kmem_free(bp, FLASH_LAYOUT_TABLE_SIZE);
7046 7046 return;
7047 7047 }
7048 7048
7049 7049 /* Verify flash layout table. */
7050 7050 len = (uint32_t)(CHAR_TO_SHORT(fhdr->len[0], fhdr->len[1]) +
7051 7051 sizeof (ql_flt_hdr_t) + sizeof (ql_flt_region_t));
7052 7052 if (len > FLASH_LAYOUT_TABLE_SIZE) {
7053 7053 chksum = 0xffff;
7054 7054 } else {
7055 7055 for (chksum = 0, cnt = 0; cnt < len; cnt += 2) {
7056 7056 w16 = (uint16_t)CHAR_TO_SHORT(bp[cnt], bp[cnt + 1]);
7057 7057 chksum += w16;
7058 7058 }
7059 7059 }
7060 7060 w16 = CHAR_TO_SHORT(fhdr->version[0], fhdr->version[1]);
7061 7061 if (chksum != 0 || w16 != 1) {
7062 7062 EL(ha, "table chksum=%xh, version=%d\n", chksum, w16);
7063 7063 kmem_free(bp, FLASH_LAYOUT_TABLE_SIZE);
7064 7064 return;
7065 7065 }
7066 7066 eaddr = bp + len;
7067 7067
7068 7068 /* Process Function/Port Configuration Map. */
7069 7069 nv_rg = vpd_rg = 0;
7070 7070 if (CFG_IST(ha, CFG_CTRL_8021)) {
7071 7071 uint16_t i;
7072 7072 uint8_t *mbp = eaddr;
7073 7073 ql_fp_cfg_map_t *cmp = (ql_fp_cfg_map_t *)mbp;
7074 7074
7075 7075 len = (uint32_t)(CHAR_TO_SHORT(cmp->hdr.len[0],
7076 7076 cmp->hdr.len[1]));
7077 7077 if (len > FLASH_LAYOUT_TABLE_SIZE) {
7078 7078 chksum = 0xffff;
7079 7079 } else {
7080 7080 for (chksum = 0, cnt = 0; cnt < len; cnt += 2) {
7081 7081 w16 = (uint16_t)CHAR_TO_SHORT(mbp[cnt],
7082 7082 mbp[cnt + 1]);
7083 7083 chksum += w16;
7084 7084 }
7085 7085 }
7086 7086 w16 = CHAR_TO_SHORT(cmp->hdr.version[0], cmp->hdr.version[1]);
7087 7087 if (chksum != 0 || w16 != 1 ||
7088 7088 cmp->hdr.Signature[0] != 'F' ||
7089 7089 cmp->hdr.Signature[1] != 'P' ||
7090 7090 cmp->hdr.Signature[2] != 'C' ||
7091 7091 cmp->hdr.Signature[3] != 'M') {
7092 7092 EL(ha, "cfg_map chksum=%xh, version=%d, "
7093 7093 "sig=%c%c%c%c\n", chksum, w16,
7094 7094 cmp->hdr.Signature[0], cmp->hdr.Signature[1],
7095 7095 cmp->hdr.Signature[2], cmp->hdr.Signature[3]);
7096 7096 } else {
7097 7097 cnt = (uint16_t)
7098 7098 (CHAR_TO_SHORT(cmp->hdr.NumberEntries[0],
7099 7099 cmp->hdr.NumberEntries[1]));
7100 7100 /* Locate entry for function. */
7101 7101 for (i = 0; i < cnt; i++) {
7102 7102 if (cmp->cfg[i].FunctionType == FT_FC &&
7103 7103 cmp->cfg[i].FunctionNumber[0] ==
7104 7104 ha->function_number &&
7105 7105 cmp->cfg[i].FunctionNumber[1] == 0) {
7106 7106 nv_rg = cmp->cfg[i].ConfigRegion;
7107 7107 vpd_rg = cmp->cfg[i].VpdRegion;
7108 7108 break;
7109 7109 }
7110 7110 }
7111 7111
7112 7112 if (nv_rg == 0 || vpd_rg == 0) {
7113 7113 EL(ha, "cfg_map nv_rg=%d, vpd_rg=%d\n", nv_rg,
7114 7114 vpd_rg);
7115 7115 nv_rg = vpd_rg = 0;
7116 7116 }
7117 7117 }
7118 7118 }
7119 7119
7120 7120 /* Process flash layout table regions */
7121 7121 for (frgn = (ql_flt_region_t *)(bp + sizeof (ql_flt_hdr_t));
7122 7122 (uint8_t *)frgn < eaddr; frgn++) {
7123 7123 faddr = CHAR_TO_LONG(frgn->beg_addr[0], frgn->beg_addr[1],
7124 7124 frgn->beg_addr[2], frgn->beg_addr[3]);
7125 7125 faddr >>= 2;
7126 7126 fe_addr = CHAR_TO_LONG(frgn->end_addr[0], frgn->end_addr[1],
7127 7127 frgn->end_addr[2], frgn->end_addr[3]);
7128 7128 fe_addr >>= 2;
7129 7129
7130 7130 switch (frgn->region) {
7131 7131 case FLASH_8021_BOOTLOADER_REGION:
7132 7132 ha->bootloader_addr = faddr;
7133 7133 ha->bootloader_size = (fe_addr - faddr) + 1;
7134 7134 QL_PRINT_9(CE_CONT, "(%d): bootloader_addr=%xh, "
7135 7135 "size=%xh\n", ha->instance, faddr,
7136 7136 ha->bootloader_size);
7137 7137 break;
7138 7138 case FLASH_FW_REGION:
7139 7139 case FLASH_8021_FW_REGION:
7140 7140 ha->flash_fw_addr = faddr;
7141 7141 ha->flash_fw_size = (fe_addr - faddr) + 1;
7142 7142 QL_PRINT_9(CE_CONT, "(%d): flash_fw_addr=%xh, "
7143 7143 "size=%xh\n", ha->instance, faddr,
7144 7144 ha->flash_fw_size);
7145 7145 break;
7146 7146 case FLASH_GOLDEN_FW_REGION:
7147 7147 case FLASH_8021_GOLDEN_FW_REGION:
7148 7148 ha->flash_golden_fw_addr = faddr;
7149 7149 QL_PRINT_9(CE_CONT, "(%d): flash_golden_fw_addr=%xh\n",
7150 7150 ha->instance, faddr);
7151 7151 break;
7152 7152 case FLASH_8021_VPD_REGION:
7153 7153 if (!vpd_rg || vpd_rg == FLASH_8021_VPD_REGION) {
7154 7154 ha->flash_vpd_addr = faddr;
7155 7155 QL_PRINT_9(CE_CONT, "(%d): 8021_flash_vpd_"
7156 7156 "addr=%xh\n", ha->instance, faddr);
7157 7157 }
7158 7158 break;
7159 7159 case FLASH_VPD_0_REGION:
7160 7160 if (vpd_rg) {
7161 7161 if (vpd_rg == FLASH_VPD_0_REGION) {
7162 7162 ha->flash_vpd_addr = faddr;
7163 7163 QL_PRINT_9(CE_CONT, "(%d): vpd_rg "
7164 7164 "flash_vpd_addr=%xh\n",
7165 7165 ha->instance, faddr);
7166 7166 }
7167 7167 } else if (!(ha->flags & FUNCTION_1) &&
7168 7168 !(CFG_IST(ha, CFG_CTRL_8021))) {
7169 7169 ha->flash_vpd_addr = faddr;
7170 7170 QL_PRINT_9(CE_CONT, "(%d): flash_vpd_addr=%xh"
7171 7171 "\n", ha->instance, faddr);
7172 7172 }
7173 7173 break;
7174 7174 case FLASH_NVRAM_0_REGION:
7175 7175 if (nv_rg) {
7176 7176 if (nv_rg == FLASH_NVRAM_0_REGION) {
7177 7177 ADAPTER_STATE_LOCK(ha);
7178 7178 ha->flags &= ~FUNCTION_1;
7179 7179 ADAPTER_STATE_UNLOCK(ha);
7180 7180 ha->flash_nvram_addr = faddr;
7181 7181 QL_PRINT_9(CE_CONT, "(%d): nv_rg "
7182 7182 "flash_nvram_addr=%xh\n",
7183 7183 ha->instance, faddr);
7184 7184 }
7185 7185 } else if (!(ha->flags & FUNCTION_1)) {
7186 7186 ha->flash_nvram_addr = faddr;
7187 7187 QL_PRINT_9(CE_CONT, "(%d): flash_nvram_addr="
7188 7188 "%xh\n", ha->instance, faddr);
7189 7189 }
7190 7190 break;
7191 7191 case FLASH_VPD_1_REGION:
7192 7192 if (vpd_rg) {
7193 7193 if (vpd_rg == FLASH_VPD_1_REGION) {
7194 7194 ha->flash_vpd_addr = faddr;
7195 7195 QL_PRINT_9(CE_CONT, "(%d): vpd_rg "
7196 7196 "flash_vpd_addr=%xh\n",
7197 7197 ha->instance, faddr);
7198 7198 }
7199 7199 } else if (ha->flags & FUNCTION_1 &&
7200 7200 !(CFG_IST(ha, CFG_CTRL_8021))) {
7201 7201 ha->flash_vpd_addr = faddr;
7202 7202 QL_PRINT_9(CE_CONT, "(%d): flash_vpd_addr=%xh"
7203 7203 "\n", ha->instance, faddr);
7204 7204 }
7205 7205 break;
7206 7206 case FLASH_NVRAM_1_REGION:
7207 7207 if (nv_rg) {
7208 7208 if (nv_rg == FLASH_NVRAM_1_REGION) {
7209 7209 ADAPTER_STATE_LOCK(ha);
7210 7210 ha->flags |= FUNCTION_1;
7211 7211 ADAPTER_STATE_UNLOCK(ha);
7212 7212 ha->flash_nvram_addr = faddr;
7213 7213 QL_PRINT_9(CE_CONT, "(%d): nv_rg "
7214 7214 "flash_nvram_addr=%xh\n",
7215 7215 ha->instance, faddr);
7216 7216 }
7217 7217 } else if (ha->flags & FUNCTION_1) {
7218 7218 ha->flash_nvram_addr = faddr;
7219 7219 QL_PRINT_9(CE_CONT, "(%d): flash_nvram_addr="
7220 7220 "%xh\n", ha->instance, faddr);
7221 7221 }
7222 7222 break;
7223 7223 case FLASH_DESC_TABLE_REGION:
7224 7224 if (!(CFG_IST(ha, CFG_CTRL_8021))) {
7225 7225 ha->flash_desc_addr = faddr;
7226 7226 QL_PRINT_9(CE_CONT, "(%d): flash_desc_addr="
7227 7227 "%xh\n", ha->instance, faddr);
7228 7228 }
7229 7229 break;
7230 7230 case FLASH_ERROR_LOG_0_REGION:
7231 7231 if (!(ha->flags & FUNCTION_1)) {
7232 7232 ha->flash_errlog_start = faddr;
7233 7233 QL_PRINT_9(CE_CONT, "(%d): flash_errlog_addr="
7234 7234 "%xh\n", ha->instance, faddr);
7235 7235 }
7236 7236 break;
7237 7237 case FLASH_ERROR_LOG_1_REGION:
7238 7238 if (ha->flags & FUNCTION_1) {
7239 7239 ha->flash_errlog_start = faddr;
7240 7240 QL_PRINT_9(CE_CONT, "(%d): flash_errlog_addr="
7241 7241 "%xh\n", ha->instance, faddr);
7242 7242 }
7243 7243 break;
7244 7244 default:
7245 7245 break;
7246 7246 }
7247 7247 }
7248 7248 kmem_free(bp, FLASH_LAYOUT_TABLE_SIZE);
7249 7249
7250 7250 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
7251 7251 }
7252 7252
7253 7253 /*
7254 7254 * ql_flash_nvram_defaults
7255 7255 * Flash default addresses.
7256 7256 *
7257 7257 * Input:
7258 7258 * ha: adapter state pointer.
7259 7259 *
7260 7260 * Returns:
7261 7261 * ql local function return status code.
7262 7262 *
7263 7263 * Context:
7264 7264 * Kernel context.
7265 7265 */
7266 7266 static void
7267 7267 ql_flash_nvram_defaults(ql_adapter_state_t *ha)
7268 7268 {
7269 7269 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
7270 7270
7271 7271 if (ha->flags & FUNCTION_1) {
7272 7272 if (CFG_IST(ha, CFG_CTRL_2300)) {
7273 7273 ha->flash_nvram_addr = NVRAM_2300_FUNC1_ADDR;
7274 7274 ha->flash_fw_addr = FLASH_2300_FIRMWARE_ADDR;
7275 7275 } else if (CFG_IST(ha, CFG_CTRL_2422)) {
7276 7276 ha->flash_data_addr = FLASH_24_25_DATA_ADDR;
7277 7277 ha->flash_nvram_addr = NVRAM_2400_FUNC1_ADDR;
7278 7278 ha->flash_vpd_addr = VPD_2400_FUNC1_ADDR;
7279 7279 ha->flash_errlog_start = FLASH_2400_ERRLOG_START_ADDR_1;
7280 7280 ha->flash_desc_addr = FLASH_2400_DESCRIPTOR_TABLE;
7281 7281 ha->flash_fw_addr = FLASH_2400_FIRMWARE_ADDR;
7282 7282 } else if (CFG_IST(ha, CFG_CTRL_25XX)) {
7283 7283 ha->flash_data_addr = FLASH_24_25_DATA_ADDR;
7284 7284 ha->flash_nvram_addr = NVRAM_2500_FUNC1_ADDR;
7285 7285 ha->flash_vpd_addr = VPD_2500_FUNC1_ADDR;
7286 7286 ha->flash_errlog_start = FLASH_2500_ERRLOG_START_ADDR_1;
7287 7287 ha->flash_desc_addr = FLASH_2500_DESCRIPTOR_TABLE;
7288 7288 ha->flash_fw_addr = FLASH_2500_FIRMWARE_ADDR;
7289 7289 } else if (CFG_IST(ha, CFG_CTRL_81XX)) {
7290 7290 ha->flash_data_addr = FLASH_8100_DATA_ADDR;
7291 7291 ha->flash_nvram_addr = NVRAM_8100_FUNC1_ADDR;
7292 7292 ha->flash_vpd_addr = VPD_8100_FUNC1_ADDR;
7293 7293 ha->flash_errlog_start = FLASH_8100_ERRLOG_START_ADDR_1;
7294 7294 ha->flash_desc_addr = FLASH_8100_DESCRIPTOR_TABLE;
7295 7295 ha->flash_fw_addr = FLASH_8100_FIRMWARE_ADDR;
7296 7296 } else if (CFG_IST(ha, CFG_CTRL_8021)) {
7297 7297 ha->flash_data_addr = 0;
7298 7298 ha->flash_nvram_addr = NVRAM_8021_FUNC1_ADDR;
7299 7299 ha->flash_vpd_addr = VPD_8021_FUNC1_ADDR;
7300 7300 ha->flash_errlog_start = 0;
7301 7301 ha->flash_desc_addr = FLASH_8021_DESCRIPTOR_TABLE;
7302 7302 ha->flash_fw_addr = FLASH_8021_FIRMWARE_ADDR;
7303 7303 ha->flash_fw_size = FLASH_8021_FIRMWARE_SIZE;
7304 7304 ha->bootloader_addr = FLASH_8021_BOOTLOADER_ADDR;
7305 7305 ha->bootloader_size = FLASH_8021_BOOTLOADER_SIZE;
7306 7306 }
7307 7307 } else {
7308 7308 if (CFG_IST(ha, CFG_CTRL_2200)) {
7309 7309 ha->flash_nvram_addr = NVRAM_2200_FUNC0_ADDR;
7310 7310 ha->flash_fw_addr = FLASH_2200_FIRMWARE_ADDR;
7311 7311 } else if (CFG_IST(ha, CFG_CTRL_2300) ||
7312 7312 (CFG_IST(ha, CFG_CTRL_6322))) {
7313 7313 ha->flash_nvram_addr = NVRAM_2300_FUNC0_ADDR;
7314 7314 ha->flash_fw_addr = FLASH_2300_FIRMWARE_ADDR;
7315 7315 } else if (CFG_IST(ha, CFG_CTRL_2422)) {
7316 7316 ha->flash_data_addr = FLASH_24_25_DATA_ADDR;
7317 7317 ha->flash_nvram_addr = NVRAM_2400_FUNC0_ADDR;
7318 7318 ha->flash_vpd_addr = VPD_2400_FUNC0_ADDR;
7319 7319 ha->flash_errlog_start = FLASH_2400_ERRLOG_START_ADDR_0;
7320 7320 ha->flash_desc_addr = FLASH_2400_DESCRIPTOR_TABLE;
7321 7321 ha->flash_fw_addr = FLASH_2400_FIRMWARE_ADDR;
7322 7322 } else if (CFG_IST(ha, CFG_CTRL_25XX)) {
7323 7323 ha->flash_data_addr = FLASH_24_25_DATA_ADDR;
7324 7324 ha->flash_nvram_addr = NVRAM_2500_FUNC0_ADDR;
7325 7325 ha->flash_vpd_addr = VPD_2500_FUNC0_ADDR;
7326 7326 ha->flash_errlog_start = FLASH_2500_ERRLOG_START_ADDR_0;
7327 7327 ha->flash_desc_addr = FLASH_2500_DESCRIPTOR_TABLE;
7328 7328 ha->flash_fw_addr = FLASH_2500_FIRMWARE_ADDR;
7329 7329 } else if (CFG_IST(ha, CFG_CTRL_81XX)) {
7330 7330 ha->flash_data_addr = FLASH_8100_DATA_ADDR;
7331 7331 ha->flash_nvram_addr = NVRAM_8100_FUNC0_ADDR;
7332 7332 ha->flash_vpd_addr = VPD_8100_FUNC0_ADDR;
7333 7333 ha->flash_errlog_start = FLASH_8100_ERRLOG_START_ADDR_0;
7334 7334 ha->flash_desc_addr = FLASH_8100_DESCRIPTOR_TABLE;
7335 7335 ha->flash_fw_addr = FLASH_8100_FIRMWARE_ADDR;
7336 7336 } else if (CFG_IST(ha, CFG_CTRL_8021)) {
7337 7337 ha->flash_data_addr = 0;
7338 7338 ha->flash_nvram_addr = NVRAM_8021_FUNC0_ADDR;
7339 7339 ha->flash_vpd_addr = VPD_8021_FUNC0_ADDR;
7340 7340 ha->flash_errlog_start = 0;
7341 7341 ha->flash_desc_addr = FLASH_8021_DESCRIPTOR_TABLE;
7342 7342 ha->flash_fw_addr = FLASH_8021_FIRMWARE_ADDR;
7343 7343 ha->flash_fw_size = FLASH_8021_FIRMWARE_SIZE;
7344 7344 ha->bootloader_addr = FLASH_8021_BOOTLOADER_ADDR;
7345 7345 ha->bootloader_size = FLASH_8021_BOOTLOADER_SIZE;
7346 7346 } else {
7347 7347 EL(ha, "unassigned flash fn0 addr: %x\n",
7348 7348 ha->device_id);
7349 7349 }
7350 7350 }
7351 7351 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
7352 7352 }
7353 7353
7354 7354 /*
7355 7355 * ql_get_sfp
7356 7356 * Returns sfp data to sdmapi caller
7357 7357 *
7358 7358 * Input:
7359 7359 * ha: adapter state pointer.
7360 7360 * cmd: Local EXT_IOCTL cmd struct pointer.
7361 7361 * mode: flags.
7362 7362 *
7363 7363 * Returns:
7364 7364 * None, request status indicated in cmd->Status.
7365 7365 *
7366 7366 * Context:
7367 7367 * Kernel context.
7368 7368 */
7369 7369 static void
7370 7370 ql_get_sfp(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
7371 7371 {
7372 7372 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
7373 7373
7374 7374 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
7375 7375 cmd->Status = EXT_STATUS_INVALID_REQUEST;
7376 7376 EL(ha, "failed, invalid request for HBA\n");
7377 7377 return;
7378 7378 }
7379 7379
7380 7380 if (cmd->ResponseLen < QL_24XX_SFP_SIZE) {
7381 7381 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
7382 7382 cmd->DetailStatus = QL_24XX_SFP_SIZE;
7383 7383 EL(ha, "failed, ResponseLen < SFP len, len passed=%xh\n",
7384 7384 cmd->ResponseLen);
7385 7385 return;
7386 7386 }
7387 7387
7388 7388 /* Dump SFP data in user buffer */
7389 7389 if ((ql_dump_sfp(ha, (void *)(uintptr_t)(cmd->ResponseAdr),
7390 7390 mode)) != 0) {
7391 7391 cmd->Status = EXT_STATUS_COPY_ERR;
7392 7392 EL(ha, "failed, copy error\n");
7393 7393 } else {
7394 7394 cmd->Status = EXT_STATUS_OK;
7395 7395 }
7396 7396
7397 7397 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
7398 7398 }
7399 7399
7400 7400 /*
7401 7401 * ql_dump_sfp
7402 7402 * Dumps SFP.
7403 7403 *
7404 7404 * Input:
7405 7405 * ha: adapter state pointer.
7406 7406 * bp: buffer address.
7407 7407 * mode: flags
7408 7408 *
7409 7409 * Returns:
7410 7410 *
7411 7411 * Context:
7412 7412 * Kernel context.
7413 7413 */
7414 7414 static int
7415 7415 ql_dump_sfp(ql_adapter_state_t *ha, void *bp, int mode)
7416 7416 {
7417 7417 dma_mem_t mem;
7418 7418 uint32_t cnt;
7419 7419 int rval2, rval = 0;
7420 7420 uint32_t dxfer;
7421 7421
7422 7422 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
7423 7423
7424 7424 /* Get memory for SFP. */
7425 7425
7426 7426 if ((rval2 = ql_get_dma_mem(ha, &mem, 64, LITTLE_ENDIAN_DMA,
7427 7427 QL_DMA_DATA_ALIGN)) != QL_SUCCESS) {
7428 7428 EL(ha, "failed, ql_get_dma_mem=%xh\n", rval2);
7429 7429 return (ENOMEM);
7430 7430 }
7431 7431
7432 7432 for (cnt = 0; cnt < QL_24XX_SFP_SIZE; cnt += mem.size) {
7433 7433 rval2 = ql_read_sfp(ha, &mem,
7434 7434 (uint16_t)(cnt < 256 ? 0xA0 : 0xA2),
7435 7435 (uint16_t)(cnt & 0xff));
7436 7436 if (rval2 != QL_SUCCESS) {
7437 7437 EL(ha, "failed, read_sfp=%xh\n", rval2);
7438 7438 rval = EFAULT;
7439 7439 break;
7440 7440 }
7441 7441
7442 7442 /* copy the data back */
7443 7443 if ((dxfer = ql_send_buffer_data(mem.bp, bp, mem.size,
7444 7444 mode)) != mem.size) {
7445 7445 /* ddi copy error */
7446 7446 EL(ha, "failed, ddi copy; byte cnt = %xh", dxfer);
7447 7447 rval = EFAULT;
7448 7448 break;
7449 7449 }
7450 7450
7451 7451 /* adjust the buffer pointer */
7452 7452 bp = (caddr_t)bp + mem.size;
7453 7453 }
7454 7454
7455 7455 ql_free_phys(ha, &mem);
7456 7456
7457 7457 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
7458 7458
7459 7459 return (rval);
7460 7460 }
7461 7461
7462 7462 /*
7463 7463 * ql_port_param
7464 7464 * Retrieves or sets the firmware port speed settings
7465 7465 *
7466 7466 * Input:
7467 7467 * ha: adapter state pointer.
7468 7468 * cmd: Local EXT_IOCTL cmd struct pointer.
7469 7469 * mode: flags.
7470 7470 *
7471 7471 * Returns:
7472 7472 * None, request status indicated in cmd->Status.
↓ open down ↓ |
629 lines elided |
↑ open up ↑ |
7473 7473 *
7474 7474 * Context:
7475 7475 * Kernel context.
7476 7476 *
7477 7477 */
7478 7478 static void
7479 7479 ql_port_param(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
7480 7480 {
7481 7481 uint8_t *name;
7482 7482 ql_tgt_t *tq;
7483 - EXT_PORT_PARAM port_param = {0};
7483 + EXT_PORT_PARAM port_param = {{{{0}}}};
7484 7484 uint32_t rval = QL_SUCCESS;
7485 7485 uint32_t idma_rate;
7486 7486
7487 7487 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
7488 7488
7489 7489 if (CFG_IST(ha, CFG_CTRL_242581) == 0) {
7490 7490 EL(ha, "invalid request for this HBA\n");
7491 7491 cmd->Status = EXT_STATUS_INVALID_REQUEST;
7492 7492 cmd->ResponseLen = 0;
7493 7493 return;
7494 7494 }
7495 7495
7496 7496 if (LOOP_NOT_READY(ha)) {
7497 7497 EL(ha, "failed, loop not ready\n");
7498 7498 cmd->Status = EXT_STATUS_DEVICE_OFFLINE;
7499 7499 cmd->ResponseLen = 0;
7500 7500 return;
7501 7501 }
7502 7502
7503 7503 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr,
7504 7504 (void*)&port_param, sizeof (EXT_PORT_PARAM), mode) != 0) {
7505 7505 EL(ha, "failed, ddi_copyin\n");
7506 7506 cmd->Status = EXT_STATUS_COPY_ERR;
7507 7507 cmd->ResponseLen = 0;
7508 7508 return;
7509 7509 }
7510 7510
7511 7511 if (port_param.FCScsiAddr.DestType != EXT_DEF_DESTTYPE_WWPN) {
7512 7512 EL(ha, "Unsupported dest lookup type: %xh\n",
7513 7513 port_param.FCScsiAddr.DestType);
7514 7514 cmd->Status = EXT_STATUS_DEV_NOT_FOUND;
7515 7515 cmd->ResponseLen = 0;
7516 7516 return;
7517 7517 }
7518 7518
7519 7519 name = port_param.FCScsiAddr.DestAddr.WWPN;
7520 7520
7521 7521 QL_PRINT_9(CE_CONT, "(%d): wwpn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
7522 7522 ha->instance, name[0], name[1], name[2], name[3], name[4],
7523 7523 name[5], name[6], name[7]);
7524 7524
7525 7525 tq = ql_find_port(ha, name, (uint16_t)QLNT_PORT);
7526 7526 if (tq == NULL || !VALID_TARGET_ID(ha, tq->loop_id)) {
7527 7527 EL(ha, "failed, fc_port not found\n");
7528 7528 cmd->Status = EXT_STATUS_DEV_NOT_FOUND;
7529 7529 cmd->ResponseLen = 0;
7530 7530 return;
7531 7531 }
7532 7532
7533 7533 cmd->Status = EXT_STATUS_OK;
7534 7534 cmd->DetailStatus = EXT_STATUS_OK;
7535 7535
7536 7536 switch (port_param.Mode) {
7537 7537 case EXT_IIDMA_MODE_GET:
7538 7538 /*
7539 7539 * Report the firmware's port rate for the wwpn
7540 7540 */
7541 7541 rval = ql_iidma_rate(ha, tq->loop_id, &idma_rate,
7542 7542 port_param.Mode);
7543 7543
7544 7544 if (rval != QL_SUCCESS) {
7545 7545 EL(ha, "iidma get failed: %xh\n", rval);
7546 7546 cmd->Status = EXT_STATUS_MAILBOX;
7547 7547 cmd->DetailStatus = rval;
7548 7548 cmd->ResponseLen = 0;
7549 7549 } else {
7550 7550 switch (idma_rate) {
7551 7551 case IIDMA_RATE_1GB:
7552 7552 port_param.Speed =
7553 7553 EXT_DEF_PORTSPEED_1GBIT;
7554 7554 break;
7555 7555 case IIDMA_RATE_2GB:
7556 7556 port_param.Speed =
7557 7557 EXT_DEF_PORTSPEED_2GBIT;
7558 7558 break;
7559 7559 case IIDMA_RATE_4GB:
7560 7560 port_param.Speed =
7561 7561 EXT_DEF_PORTSPEED_4GBIT;
7562 7562 break;
7563 7563 case IIDMA_RATE_8GB:
7564 7564 port_param.Speed =
7565 7565 EXT_DEF_PORTSPEED_8GBIT;
7566 7566 break;
7567 7567 case IIDMA_RATE_10GB:
7568 7568 port_param.Speed =
7569 7569 EXT_DEF_PORTSPEED_10GBIT;
7570 7570 break;
7571 7571 default:
7572 7572 port_param.Speed =
7573 7573 EXT_DEF_PORTSPEED_UNKNOWN;
7574 7574 EL(ha, "failed, Port speed rate=%xh\n",
7575 7575 idma_rate);
7576 7576 break;
7577 7577 }
7578 7578
7579 7579 /* Copy back the data */
7580 7580 rval = ddi_copyout((void *)&port_param,
7581 7581 (void *)(uintptr_t)cmd->ResponseAdr,
7582 7582 sizeof (EXT_PORT_PARAM), mode);
7583 7583
7584 7584 if (rval != 0) {
7585 7585 cmd->Status = EXT_STATUS_COPY_ERR;
7586 7586 cmd->ResponseLen = 0;
7587 7587 EL(ha, "failed, ddi_copyout\n");
7588 7588 } else {
7589 7589 cmd->ResponseLen = (uint32_t)
7590 7590 sizeof (EXT_PORT_PARAM);
7591 7591 }
7592 7592 }
7593 7593 break;
7594 7594
7595 7595 case EXT_IIDMA_MODE_SET:
7596 7596 /*
7597 7597 * Set the firmware's port rate for the wwpn
7598 7598 */
7599 7599 switch (port_param.Speed) {
7600 7600 case EXT_DEF_PORTSPEED_1GBIT:
7601 7601 idma_rate = IIDMA_RATE_1GB;
7602 7602 break;
7603 7603 case EXT_DEF_PORTSPEED_2GBIT:
7604 7604 idma_rate = IIDMA_RATE_2GB;
7605 7605 break;
7606 7606 case EXT_DEF_PORTSPEED_4GBIT:
7607 7607 idma_rate = IIDMA_RATE_4GB;
7608 7608 break;
7609 7609 case EXT_DEF_PORTSPEED_8GBIT:
7610 7610 idma_rate = IIDMA_RATE_8GB;
7611 7611 break;
7612 7612 case EXT_DEF_PORTSPEED_10GBIT:
7613 7613 port_param.Speed = IIDMA_RATE_10GB;
7614 7614 break;
7615 7615 default:
7616 7616 EL(ha, "invalid set iidma rate: %x\n",
7617 7617 port_param.Speed);
7618 7618 cmd->Status = EXT_STATUS_INVALID_PARAM;
7619 7619 cmd->ResponseLen = 0;
7620 7620 rval = QL_PARAMETER_ERROR;
7621 7621 break;
7622 7622 }
7623 7623
7624 7624 if (rval == QL_SUCCESS) {
7625 7625 rval = ql_iidma_rate(ha, tq->loop_id, &idma_rate,
7626 7626 port_param.Mode);
7627 7627 if (rval != QL_SUCCESS) {
7628 7628 EL(ha, "iidma set failed: %xh\n", rval);
7629 7629 cmd->Status = EXT_STATUS_MAILBOX;
7630 7630 cmd->DetailStatus = rval;
7631 7631 cmd->ResponseLen = 0;
7632 7632 }
7633 7633 }
7634 7634 break;
7635 7635 default:
7636 7636 EL(ha, "invalid mode specified: %x\n", port_param.Mode);
7637 7637 cmd->Status = EXT_STATUS_INVALID_PARAM;
7638 7638 cmd->ResponseLen = 0;
7639 7639 cmd->DetailStatus = 0;
7640 7640 break;
7641 7641 }
7642 7642
7643 7643 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
7644 7644 }
7645 7645
7646 7646 /*
7647 7647 * ql_get_fwexttrace
7648 7648 * Dumps f/w extended trace buffer
7649 7649 *
7650 7650 * Input:
7651 7651 * ha: adapter state pointer.
7652 7652 * bp: buffer address.
7653 7653 * mode: flags
7654 7654 *
7655 7655 * Returns:
7656 7656 *
7657 7657 * Context:
7658 7658 * Kernel context.
7659 7659 */
7660 7660 /* ARGSUSED */
7661 7661 static void
7662 7662 ql_get_fwexttrace(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
7663 7663 {
7664 7664 int rval;
7665 7665 caddr_t payload;
7666 7666
7667 7667 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
7668 7668
7669 7669 if (CFG_IST(ha, CFG_CTRL_24258081) == 0) {
7670 7670 EL(ha, "invalid request for this HBA\n");
7671 7671 cmd->Status = EXT_STATUS_INVALID_REQUEST;
7672 7672 cmd->ResponseLen = 0;
7673 7673 return;
7674 7674 }
7675 7675
7676 7676 if ((CFG_IST(ha, CFG_ENABLE_FWEXTTRACE) == 0) ||
7677 7677 (ha->fwexttracebuf.bp == NULL)) {
7678 7678 EL(ha, "f/w extended trace is not enabled\n");
7679 7679 cmd->Status = EXT_STATUS_INVALID_REQUEST;
7680 7680 cmd->ResponseLen = 0;
7681 7681 return;
7682 7682 }
7683 7683
7684 7684 if (cmd->ResponseLen < FWEXTSIZE) {
7685 7685 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
7686 7686 cmd->DetailStatus = FWEXTSIZE;
7687 7687 EL(ha, "failed, ResponseLen (%xh) < %xh (FWEXTSIZE)\n",
7688 7688 cmd->ResponseLen, FWEXTSIZE);
7689 7689 cmd->ResponseLen = 0;
7690 7690 return;
7691 7691 }
7692 7692
7693 7693 /* Time Stamp */
7694 7694 rval = ql_fw_etrace(ha, &ha->fwexttracebuf, FTO_INSERT_TIME_STAMP);
7695 7695 if (rval != QL_SUCCESS) {
7696 7696 EL(ha, "f/w extended trace insert"
7697 7697 "time stamp failed: %xh\n", rval);
7698 7698 cmd->Status = EXT_STATUS_ERR;
7699 7699 cmd->ResponseLen = 0;
7700 7700 return;
7701 7701 }
7702 7702
7703 7703 /* Disable Tracing */
7704 7704 rval = ql_fw_etrace(ha, &ha->fwexttracebuf, FTO_EXT_TRACE_DISABLE);
7705 7705 if (rval != QL_SUCCESS) {
7706 7706 EL(ha, "f/w extended trace disable failed: %xh\n", rval);
7707 7707 cmd->Status = EXT_STATUS_ERR;
7708 7708 cmd->ResponseLen = 0;
7709 7709 return;
7710 7710 }
7711 7711
7712 7712 /* Allocate payload buffer */
7713 7713 payload = kmem_zalloc(FWEXTSIZE, KM_SLEEP);
7714 7714 if (payload == NULL) {
7715 7715 EL(ha, "failed, kmem_zalloc\n");
7716 7716 cmd->Status = EXT_STATUS_NO_MEMORY;
7717 7717 cmd->ResponseLen = 0;
7718 7718 return;
7719 7719 }
7720 7720
7721 7721 /* Sync DMA buffer. */
7722 7722 (void) ddi_dma_sync(ha->fwexttracebuf.dma_handle, 0,
7723 7723 FWEXTSIZE, DDI_DMA_SYNC_FORKERNEL);
7724 7724
7725 7725 /* Copy trace buffer data. */
7726 7726 ddi_rep_get8(ha->fwexttracebuf.acc_handle, (uint8_t *)payload,
7727 7727 (uint8_t *)ha->fwexttracebuf.bp, FWEXTSIZE,
7728 7728 DDI_DEV_AUTOINCR);
7729 7729
7730 7730 /* Send payload to application. */
7731 7731 if (ql_send_buffer_data(payload, (caddr_t)(uintptr_t)cmd->ResponseAdr,
7732 7732 cmd->ResponseLen, mode) != cmd->ResponseLen) {
7733 7733 EL(ha, "failed, send_buffer_data\n");
7734 7734 cmd->Status = EXT_STATUS_COPY_ERR;
7735 7735 cmd->ResponseLen = 0;
7736 7736 } else {
7737 7737 cmd->Status = EXT_STATUS_OK;
7738 7738 }
7739 7739
7740 7740 kmem_free(payload, FWEXTSIZE);
7741 7741
7742 7742 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
7743 7743 }
7744 7744
7745 7745 /*
7746 7746 * ql_get_fwfcetrace
7747 7747 * Dumps f/w fibre channel event trace buffer
7748 7748 *
7749 7749 * Input:
7750 7750 * ha: adapter state pointer.
7751 7751 * bp: buffer address.
7752 7752 * mode: flags
7753 7753 *
7754 7754 * Returns:
7755 7755 *
7756 7756 * Context:
7757 7757 * Kernel context.
7758 7758 */
7759 7759 /* ARGSUSED */
7760 7760 static void
7761 7761 ql_get_fwfcetrace(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
7762 7762 {
7763 7763 int rval;
7764 7764 caddr_t payload;
7765 7765
7766 7766 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
7767 7767
7768 7768 if (CFG_IST(ha, CFG_CTRL_24258081) == 0) {
7769 7769 EL(ha, "invalid request for this HBA\n");
7770 7770 cmd->Status = EXT_STATUS_INVALID_REQUEST;
7771 7771 cmd->ResponseLen = 0;
7772 7772 return;
7773 7773 }
7774 7774
7775 7775 if ((CFG_IST(ha, CFG_ENABLE_FWFCETRACE) == 0) ||
7776 7776 (ha->fwfcetracebuf.bp == NULL)) {
7777 7777 EL(ha, "f/w FCE trace is not enabled\n");
7778 7778 cmd->Status = EXT_STATUS_INVALID_REQUEST;
7779 7779 cmd->ResponseLen = 0;
7780 7780 return;
7781 7781 }
7782 7782
7783 7783 if (cmd->ResponseLen < FWFCESIZE) {
7784 7784 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
7785 7785 cmd->DetailStatus = FWFCESIZE;
7786 7786 EL(ha, "failed, ResponseLen (%xh) < %xh (FWFCESIZE)\n",
7787 7787 cmd->ResponseLen, FWFCESIZE);
7788 7788 cmd->ResponseLen = 0;
7789 7789 return;
7790 7790 }
7791 7791
7792 7792 /* Disable Tracing */
7793 7793 rval = ql_fw_etrace(ha, &ha->fwfcetracebuf, FTO_FCE_TRACE_DISABLE);
7794 7794 if (rval != QL_SUCCESS) {
7795 7795 EL(ha, "f/w FCE trace disable failed: %xh\n", rval);
7796 7796 cmd->Status = EXT_STATUS_ERR;
7797 7797 cmd->ResponseLen = 0;
7798 7798 return;
7799 7799 }
7800 7800
7801 7801 /* Allocate payload buffer */
7802 7802 payload = kmem_zalloc(FWEXTSIZE, KM_SLEEP);
7803 7803 if (payload == NULL) {
7804 7804 EL(ha, "failed, kmem_zalloc\n");
7805 7805 cmd->Status = EXT_STATUS_NO_MEMORY;
7806 7806 cmd->ResponseLen = 0;
7807 7807 return;
7808 7808 }
7809 7809
7810 7810 /* Sync DMA buffer. */
7811 7811 (void) ddi_dma_sync(ha->fwfcetracebuf.dma_handle, 0,
7812 7812 FWFCESIZE, DDI_DMA_SYNC_FORKERNEL);
7813 7813
7814 7814 /* Copy trace buffer data. */
7815 7815 ddi_rep_get8(ha->fwfcetracebuf.acc_handle, (uint8_t *)payload,
7816 7816 (uint8_t *)ha->fwfcetracebuf.bp, FWFCESIZE,
7817 7817 DDI_DEV_AUTOINCR);
7818 7818
7819 7819 /* Send payload to application. */
7820 7820 if (ql_send_buffer_data(payload, (caddr_t)(uintptr_t)cmd->ResponseAdr,
7821 7821 cmd->ResponseLen, mode) != cmd->ResponseLen) {
7822 7822 EL(ha, "failed, send_buffer_data\n");
7823 7823 cmd->Status = EXT_STATUS_COPY_ERR;
7824 7824 cmd->ResponseLen = 0;
7825 7825 } else {
7826 7826 cmd->Status = EXT_STATUS_OK;
7827 7827 }
7828 7828
7829 7829 kmem_free(payload, FWFCESIZE);
7830 7830
7831 7831 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
7832 7832 }
7833 7833
7834 7834 /*
7835 7835 * ql_get_pci_data
7836 7836 * Retrieves pci config space data
7837 7837 *
7838 7838 * Input:
7839 7839 * ha: adapter state pointer.
7840 7840 * cmd: Local EXT_IOCTL cmd struct pointer.
7841 7841 * mode: flags.
7842 7842 *
7843 7843 * Returns:
7844 7844 * None, request status indicated in cmd->Status.
7845 7845 *
7846 7846 * Context:
7847 7847 * Kernel context.
7848 7848 *
7849 7849 */
7850 7850 static void
7851 7851 ql_get_pci_data(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
7852 7852 {
7853 7853 uint8_t cap_ptr;
7854 7854 uint8_t cap_id;
7855 7855 uint32_t buf_size = 256;
7856 7856
7857 7857 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
7858 7858
7859 7859 /*
7860 7860 * First check the "Capabilities List" bit of the status register.
7861 7861 */
7862 7862 if (ql_pci_config_get16(ha, PCI_CONF_STAT) & PCI_STAT_CAP) {
7863 7863 /*
7864 7864 * Now get the capability pointer
7865 7865 */
7866 7866 cap_ptr = (uint8_t)ql_pci_config_get8(ha, PCI_CONF_CAP_PTR);
7867 7867 while (cap_ptr != PCI_CAP_NEXT_PTR_NULL) {
7868 7868 /*
7869 7869 * Check for the pcie capability.
7870 7870 */
7871 7871 cap_id = (uint8_t)ql_pci_config_get8(ha, cap_ptr);
7872 7872 if (cap_id == PCI_CAP_ID_PCI_E) {
7873 7873 buf_size = 4096;
7874 7874 break;
7875 7875 }
7876 7876 cap_ptr = (uint8_t)ql_pci_config_get8(ha,
7877 7877 (cap_ptr + PCI_CAP_NEXT_PTR));
7878 7878 }
7879 7879 }
7880 7880
7881 7881 if (cmd->ResponseLen < buf_size) {
7882 7882 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
7883 7883 cmd->DetailStatus = buf_size;
7884 7884 EL(ha, "failed ResponseLen < buf_size, len passed=%xh\n",
7885 7885 cmd->ResponseLen);
7886 7886 return;
7887 7887 }
7888 7888
7889 7889 /* Dump PCI config data. */
7890 7890 if ((ql_pci_dump(ha, (void *)(uintptr_t)(cmd->ResponseAdr),
7891 7891 buf_size, mode)) != 0) {
7892 7892 cmd->Status = EXT_STATUS_COPY_ERR;
7893 7893 cmd->DetailStatus = 0;
7894 7894 EL(ha, "failed, copy err pci_dump\n");
7895 7895 } else {
7896 7896 cmd->Status = EXT_STATUS_OK;
7897 7897 cmd->DetailStatus = buf_size;
7898 7898 }
7899 7899
7900 7900 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
7901 7901 }
7902 7902
7903 7903 /*
7904 7904 * ql_pci_dump
7905 7905 * Dumps PCI config data to application buffer.
7906 7906 *
7907 7907 * Input:
7908 7908 * ha = adapter state pointer.
7909 7909 * bp = user buffer address.
7910 7910 *
7911 7911 * Returns:
7912 7912 *
7913 7913 * Context:
7914 7914 * Kernel context.
7915 7915 */
7916 7916 int
7917 7917 ql_pci_dump(ql_adapter_state_t *ha, uint32_t *bp, uint32_t pci_size, int mode)
7918 7918 {
7919 7919 uint32_t pci_os;
7920 7920 uint32_t *ptr32, *org_ptr32;
7921 7921
7922 7922 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
7923 7923
7924 7924 ptr32 = kmem_zalloc(pci_size, KM_SLEEP);
7925 7925 if (ptr32 == NULL) {
7926 7926 EL(ha, "failed kmem_zalloc\n");
7927 7927 return (ENOMEM);
7928 7928 }
7929 7929
7930 7930 /* store the initial value of ptr32 */
7931 7931 org_ptr32 = ptr32;
7932 7932 for (pci_os = 0; pci_os < pci_size; pci_os += 4) {
7933 7933 *ptr32 = (uint32_t)ql_pci_config_get32(ha, pci_os);
7934 7934 LITTLE_ENDIAN_32(ptr32);
7935 7935 ptr32++;
7936 7936 }
7937 7937
7938 7938 if (ddi_copyout((void *)org_ptr32, (void *)bp, pci_size, mode) !=
7939 7939 0) {
7940 7940 EL(ha, "failed ddi_copyout\n");
7941 7941 kmem_free(org_ptr32, pci_size);
7942 7942 return (EFAULT);
7943 7943 }
7944 7944
7945 7945 QL_DUMP_9(org_ptr32, 8, pci_size);
7946 7946
7947 7947 kmem_free(org_ptr32, pci_size);
7948 7948
7949 7949 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
7950 7950
7951 7951 return (0);
7952 7952 }
7953 7953
7954 7954 /*
7955 7955 * ql_menlo_reset
7956 7956 * Reset Menlo
7957 7957 *
7958 7958 * Input:
7959 7959 * ha: adapter state pointer.
7960 7960 * bp: buffer address.
7961 7961 * mode: flags
7962 7962 *
7963 7963 * Returns:
7964 7964 *
7965 7965 * Context:
7966 7966 * Kernel context.
7967 7967 */
7968 7968 static void
7969 7969 ql_menlo_reset(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
7970 7970 {
7971 7971 EXT_MENLO_RESET rst;
7972 7972 ql_mbx_data_t mr;
7973 7973 int rval;
7974 7974
7975 7975 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
7976 7976
7977 7977 if ((CFG_IST(ha, CFG_CTRL_MENLO)) == 0) {
7978 7978 EL(ha, "failed, invalid request for HBA\n");
7979 7979 cmd->Status = EXT_STATUS_INVALID_REQUEST;
7980 7980 cmd->ResponseLen = 0;
7981 7981 return;
7982 7982 }
7983 7983
7984 7984 /*
7985 7985 * TODO: only vp_index 0 can do this (?)
7986 7986 */
7987 7987
7988 7988 /* Verify the size of request structure. */
7989 7989 if (cmd->RequestLen < sizeof (EXT_MENLO_RESET)) {
7990 7990 /* Return error */
7991 7991 EL(ha, "RequestLen=%d < %d\n", cmd->RequestLen,
7992 7992 sizeof (EXT_MENLO_RESET));
7993 7993 cmd->Status = EXT_STATUS_INVALID_PARAM;
7994 7994 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN;
7995 7995 cmd->ResponseLen = 0;
7996 7996 return;
7997 7997 }
7998 7998
7999 7999 /* Get reset request. */
8000 8000 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr,
8001 8001 (void *)&rst, sizeof (EXT_MENLO_RESET), mode) != 0) {
8002 8002 EL(ha, "failed, ddi_copyin\n");
8003 8003 cmd->Status = EXT_STATUS_COPY_ERR;
8004 8004 cmd->ResponseLen = 0;
8005 8005 return;
8006 8006 }
8007 8007
8008 8008 /* Wait for I/O to stop and daemon to stall. */
8009 8009 if (ql_suspend_hba(ha, 0) != QL_SUCCESS) {
8010 8010 EL(ha, "ql_stall_driver failed\n");
8011 8011 ql_restart_hba(ha);
8012 8012 cmd->Status = EXT_STATUS_BUSY;
8013 8013 cmd->ResponseLen = 0;
8014 8014 return;
8015 8015 }
8016 8016
8017 8017 rval = ql_reset_menlo(ha, &mr, rst.Flags);
8018 8018 if (rval != QL_SUCCESS) {
8019 8019 EL(ha, "failed, status=%xh\n", rval);
8020 8020 cmd->Status = EXT_STATUS_MAILBOX;
8021 8021 cmd->DetailStatus = rval;
8022 8022 cmd->ResponseLen = 0;
8023 8023 } else if (mr.mb[1] != 0) {
8024 8024 EL(ha, "failed, substatus=%d\n", mr.mb[1]);
8025 8025 cmd->Status = EXT_STATUS_ERR;
8026 8026 cmd->DetailStatus = mr.mb[1];
8027 8027 cmd->ResponseLen = 0;
8028 8028 }
8029 8029
8030 8030 ql_restart_hba(ha);
8031 8031
8032 8032 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
8033 8033 }
8034 8034
8035 8035 /*
8036 8036 * ql_menlo_get_fw_version
8037 8037 * Get Menlo firmware version.
8038 8038 *
8039 8039 * Input:
8040 8040 * ha: adapter state pointer.
8041 8041 * bp: buffer address.
8042 8042 * mode: flags
8043 8043 *
8044 8044 * Returns:
8045 8045 *
8046 8046 * Context:
8047 8047 * Kernel context.
8048 8048 */
8049 8049 static void
8050 8050 ql_menlo_get_fw_version(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
8051 8051 {
8052 8052 int rval;
8053 8053 ql_mbx_iocb_t *pkt;
8054 8054 EXT_MENLO_GET_FW_VERSION ver = {0};
8055 8055
8056 8056 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
8057 8057
8058 8058 if ((CFG_IST(ha, CFG_CTRL_MENLO)) == 0) {
8059 8059 EL(ha, "failed, invalid request for HBA\n");
8060 8060 cmd->Status = EXT_STATUS_INVALID_REQUEST;
8061 8061 cmd->ResponseLen = 0;
8062 8062 return;
8063 8063 }
8064 8064
8065 8065 if (cmd->ResponseLen < sizeof (EXT_MENLO_GET_FW_VERSION)) {
8066 8066 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
8067 8067 cmd->DetailStatus = sizeof (EXT_MENLO_GET_FW_VERSION);
8068 8068 EL(ha, "ResponseLen=%d < %d\n", cmd->ResponseLen,
8069 8069 sizeof (EXT_MENLO_GET_FW_VERSION));
8070 8070 cmd->ResponseLen = 0;
8071 8071 return;
8072 8072 }
8073 8073
8074 8074 /* Allocate packet. */
8075 8075 pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP);
8076 8076 if (pkt == NULL) {
8077 8077 EL(ha, "failed, kmem_zalloc\n");
8078 8078 cmd->Status = EXT_STATUS_NO_MEMORY;
8079 8079 cmd->ResponseLen = 0;
8080 8080 return;
8081 8081 }
8082 8082
8083 8083 pkt->mvfy.entry_type = VERIFY_MENLO_TYPE;
8084 8084 pkt->mvfy.entry_count = 1;
8085 8085 pkt->mvfy.options_status = LE_16(VMF_DO_NOT_UPDATE_FW);
8086 8086
8087 8087 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, sizeof (ql_mbx_iocb_t));
8088 8088 LITTLE_ENDIAN_16(&pkt->mvfy.options_status);
8089 8089 LITTLE_ENDIAN_16(&pkt->mvfy.failure_code);
8090 8090 ver.FwVersion = LE_32(pkt->mvfy.fw_version);
8091 8091
8092 8092 if (rval != QL_SUCCESS || (pkt->mvfy.entry_status & 0x3c) != 0 ||
8093 8093 pkt->mvfy.options_status != CS_COMPLETE) {
8094 8094 /* Command error */
8095 8095 EL(ha, "failed, status=%xh, es=%xh, cs=%xh, fc=%xh\n", rval,
8096 8096 pkt->mvfy.entry_status & 0x3c, pkt->mvfy.options_status,
8097 8097 pkt->mvfy.failure_code);
8098 8098 cmd->Status = EXT_STATUS_ERR;
8099 8099 cmd->DetailStatus = rval != QL_SUCCESS ? rval :
8100 8100 QL_FUNCTION_FAILED;
8101 8101 cmd->ResponseLen = 0;
8102 8102 } else if (ddi_copyout((void *)&ver,
8103 8103 (void *)(uintptr_t)cmd->ResponseAdr,
8104 8104 sizeof (EXT_MENLO_GET_FW_VERSION), mode) != 0) {
8105 8105 EL(ha, "failed, ddi_copyout\n");
8106 8106 cmd->Status = EXT_STATUS_COPY_ERR;
8107 8107 cmd->ResponseLen = 0;
8108 8108 } else {
8109 8109 cmd->ResponseLen = sizeof (EXT_MENLO_GET_FW_VERSION);
8110 8110 }
8111 8111
8112 8112 kmem_free(pkt, sizeof (ql_mbx_iocb_t));
8113 8113
8114 8114 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
8115 8115 }
8116 8116
8117 8117 /*
8118 8118 * ql_menlo_update_fw
8119 8119 * Get Menlo update firmware.
8120 8120 *
8121 8121 * Input:
8122 8122 * ha: adapter state pointer.
8123 8123 * bp: buffer address.
8124 8124 * mode: flags
8125 8125 *
8126 8126 * Returns:
8127 8127 *
8128 8128 * Context:
8129 8129 * Kernel context.
8130 8130 */
8131 8131 static void
8132 8132 ql_menlo_update_fw(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
8133 8133 {
8134 8134 ql_mbx_iocb_t *pkt;
8135 8135 dma_mem_t *dma_mem;
8136 8136 EXT_MENLO_UPDATE_FW fw;
8137 8137 uint32_t *ptr32;
8138 8138 int rval;
8139 8139
8140 8140 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
8141 8141
8142 8142 if ((CFG_IST(ha, CFG_CTRL_MENLO)) == 0) {
8143 8143 EL(ha, "failed, invalid request for HBA\n");
8144 8144 cmd->Status = EXT_STATUS_INVALID_REQUEST;
8145 8145 cmd->ResponseLen = 0;
8146 8146 return;
8147 8147 }
8148 8148
8149 8149 /*
8150 8150 * TODO: only vp_index 0 can do this (?)
8151 8151 */
8152 8152
8153 8153 /* Verify the size of request structure. */
8154 8154 if (cmd->RequestLen < sizeof (EXT_MENLO_UPDATE_FW)) {
8155 8155 /* Return error */
8156 8156 EL(ha, "RequestLen=%d < %d\n", cmd->RequestLen,
8157 8157 sizeof (EXT_MENLO_UPDATE_FW));
8158 8158 cmd->Status = EXT_STATUS_INVALID_PARAM;
8159 8159 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN;
8160 8160 cmd->ResponseLen = 0;
8161 8161 return;
8162 8162 }
8163 8163
8164 8164 /* Get update fw request. */
8165 8165 if (ddi_copyin((caddr_t)(uintptr_t)cmd->RequestAdr, (caddr_t)&fw,
8166 8166 sizeof (EXT_MENLO_UPDATE_FW), mode) != 0) {
8167 8167 EL(ha, "failed, ddi_copyin\n");
8168 8168 cmd->Status = EXT_STATUS_COPY_ERR;
8169 8169 cmd->ResponseLen = 0;
8170 8170 return;
8171 8171 }
8172 8172
8173 8173 /* Wait for I/O to stop and daemon to stall. */
8174 8174 if (ql_suspend_hba(ha, 0) != QL_SUCCESS) {
8175 8175 EL(ha, "ql_stall_driver failed\n");
8176 8176 ql_restart_hba(ha);
8177 8177 cmd->Status = EXT_STATUS_BUSY;
8178 8178 cmd->ResponseLen = 0;
8179 8179 return;
8180 8180 }
8181 8181
8182 8182 /* Allocate packet. */
8183 8183 dma_mem = (dma_mem_t *)kmem_zalloc(sizeof (dma_mem_t), KM_SLEEP);
8184 8184 if (dma_mem == NULL) {
8185 8185 EL(ha, "failed, kmem_zalloc\n");
8186 8186 cmd->Status = EXT_STATUS_NO_MEMORY;
8187 8187 cmd->ResponseLen = 0;
8188 8188 return;
8189 8189 }
8190 8190 pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP);
8191 8191 if (pkt == NULL) {
8192 8192 EL(ha, "failed, kmem_zalloc\n");
8193 8193 kmem_free(dma_mem, sizeof (dma_mem_t));
8194 8194 ql_restart_hba(ha);
8195 8195 cmd->Status = EXT_STATUS_NO_MEMORY;
8196 8196 cmd->ResponseLen = 0;
8197 8197 return;
8198 8198 }
8199 8199
8200 8200 /* Get DMA memory for the IOCB */
8201 8201 if (ql_get_dma_mem(ha, dma_mem, fw.TotalByteCount, LITTLE_ENDIAN_DMA,
8202 8202 QL_DMA_DATA_ALIGN) != QL_SUCCESS) {
8203 8203 cmn_err(CE_WARN, "%s(%d): request queue DMA memory "
8204 8204 "alloc failed", QL_NAME, ha->instance);
8205 8205 kmem_free(pkt, sizeof (ql_mbx_iocb_t));
8206 8206 kmem_free(dma_mem, sizeof (dma_mem_t));
8207 8207 ql_restart_hba(ha);
8208 8208 cmd->Status = EXT_STATUS_MS_NO_RESPONSE;
8209 8209 cmd->ResponseLen = 0;
8210 8210 return;
8211 8211 }
8212 8212
8213 8213 /* Get firmware data. */
8214 8214 if (ql_get_buffer_data((caddr_t)(uintptr_t)fw.pFwDataBytes, dma_mem->bp,
8215 8215 fw.TotalByteCount, mode) != fw.TotalByteCount) {
8216 8216 EL(ha, "failed, get_buffer_data\n");
8217 8217 ql_free_dma_resource(ha, dma_mem);
8218 8218 kmem_free(pkt, sizeof (ql_mbx_iocb_t));
8219 8219 kmem_free(dma_mem, sizeof (dma_mem_t));
8220 8220 ql_restart_hba(ha);
8221 8221 cmd->Status = EXT_STATUS_COPY_ERR;
8222 8222 cmd->ResponseLen = 0;
8223 8223 return;
8224 8224 }
8225 8225
8226 8226 /* Sync DMA buffer. */
8227 8227 (void) ddi_dma_sync(dma_mem->dma_handle, 0, dma_mem->size,
8228 8228 DDI_DMA_SYNC_FORDEV);
8229 8229
8230 8230 pkt->mvfy.entry_type = VERIFY_MENLO_TYPE;
8231 8231 pkt->mvfy.entry_count = 1;
8232 8232 pkt->mvfy.options_status = (uint16_t)LE_16(fw.Flags);
8233 8233 ptr32 = dma_mem->bp;
8234 8234 pkt->mvfy.fw_version = LE_32(ptr32[2]);
8235 8235 pkt->mvfy.fw_size = LE_32(fw.TotalByteCount);
8236 8236 pkt->mvfy.fw_sequence_size = LE_32(fw.TotalByteCount);
8237 8237 pkt->mvfy.dseg_count = LE_16(1);
8238 8238 pkt->mvfy.dseg_0_address[0] = (uint32_t)
8239 8239 LE_32(LSD(dma_mem->cookie.dmac_laddress));
8240 8240 pkt->mvfy.dseg_0_address[1] = (uint32_t)
8241 8241 LE_32(MSD(dma_mem->cookie.dmac_laddress));
8242 8242 pkt->mvfy.dseg_0_length = LE_32(fw.TotalByteCount);
8243 8243
8244 8244 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, sizeof (ql_mbx_iocb_t));
8245 8245 LITTLE_ENDIAN_16(&pkt->mvfy.options_status);
8246 8246 LITTLE_ENDIAN_16(&pkt->mvfy.failure_code);
8247 8247
8248 8248 if (rval != QL_SUCCESS || (pkt->mvfy.entry_status & 0x3c) != 0 ||
8249 8249 pkt->mvfy.options_status != CS_COMPLETE) {
8250 8250 /* Command error */
8251 8251 EL(ha, "failed, status=%xh, es=%xh, cs=%xh, fc=%xh\n", rval,
8252 8252 pkt->mvfy.entry_status & 0x3c, pkt->mvfy.options_status,
8253 8253 pkt->mvfy.failure_code);
8254 8254 cmd->Status = EXT_STATUS_ERR;
8255 8255 cmd->DetailStatus = rval != QL_SUCCESS ? rval :
8256 8256 QL_FUNCTION_FAILED;
8257 8257 cmd->ResponseLen = 0;
8258 8258 }
8259 8259
8260 8260 ql_free_dma_resource(ha, dma_mem);
8261 8261 kmem_free(pkt, sizeof (ql_mbx_iocb_t));
8262 8262 kmem_free(dma_mem, sizeof (dma_mem_t));
8263 8263 ql_restart_hba(ha);
8264 8264
8265 8265 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
8266 8266 }
8267 8267
8268 8268 /*
8269 8269 * ql_menlo_manage_info
8270 8270 * Get Menlo manage info.
8271 8271 *
8272 8272 * Input:
8273 8273 * ha: adapter state pointer.
8274 8274 * bp: buffer address.
8275 8275 * mode: flags
8276 8276 *
8277 8277 * Returns:
8278 8278 *
8279 8279 * Context:
8280 8280 * Kernel context.
8281 8281 */
8282 8282 static void
8283 8283 ql_menlo_manage_info(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
8284 8284 {
8285 8285 ql_mbx_iocb_t *pkt;
8286 8286 dma_mem_t *dma_mem = NULL;
8287 8287 EXT_MENLO_MANAGE_INFO info;
8288 8288 int rval;
8289 8289
8290 8290 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
8291 8291
8292 8292
8293 8293 /* The call is only supported for Schultz right now */
8294 8294 if (CFG_IST(ha, CFG_CTRL_8081)) {
8295 8295 ql_get_xgmac_statistics(ha, cmd, mode);
8296 8296 QL_PRINT_9(CE_CONT, "(%d): CFG_CTRL_81XX done\n",
8297 8297 ha->instance);
8298 8298 return;
8299 8299 }
8300 8300
8301 8301 if (!CFG_IST(ha, CFG_CTRL_8081) || !CFG_IST(ha, CFG_CTRL_MENLO)) {
8302 8302 EL(ha, "failed, invalid request for HBA\n");
8303 8303 cmd->Status = EXT_STATUS_INVALID_REQUEST;
8304 8304 cmd->ResponseLen = 0;
8305 8305 return;
8306 8306 }
8307 8307
8308 8308 /* Verify the size of request structure. */
8309 8309 if (cmd->RequestLen < sizeof (EXT_MENLO_MANAGE_INFO)) {
8310 8310 /* Return error */
8311 8311 EL(ha, "RequestLen=%d < %d\n", cmd->RequestLen,
8312 8312 sizeof (EXT_MENLO_MANAGE_INFO));
8313 8313 cmd->Status = EXT_STATUS_INVALID_PARAM;
8314 8314 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN;
8315 8315 cmd->ResponseLen = 0;
8316 8316 return;
8317 8317 }
8318 8318
8319 8319 /* Get manage info request. */
8320 8320 if (ddi_copyin((caddr_t)(uintptr_t)cmd->RequestAdr,
8321 8321 (caddr_t)&info, sizeof (EXT_MENLO_MANAGE_INFO), mode) != 0) {
8322 8322 EL(ha, "failed, ddi_copyin\n");
8323 8323 cmd->Status = EXT_STATUS_COPY_ERR;
8324 8324 cmd->ResponseLen = 0;
8325 8325 return;
8326 8326 }
8327 8327
8328 8328 /* Allocate packet. */
8329 8329 pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP);
8330 8330 if (pkt == NULL) {
8331 8331 EL(ha, "failed, kmem_zalloc\n");
8332 8332 ql_restart_driver(ha);
8333 8333 cmd->Status = EXT_STATUS_NO_MEMORY;
8334 8334 cmd->ResponseLen = 0;
8335 8335 return;
8336 8336 }
8337 8337
8338 8338 pkt->mdata.entry_type = MENLO_DATA_TYPE;
8339 8339 pkt->mdata.entry_count = 1;
8340 8340 pkt->mdata.options_status = (uint16_t)LE_16(info.Operation);
8341 8341
8342 8342 /* Get DMA memory for the IOCB */
8343 8343 if (info.Operation == MENLO_OP_READ_MEM ||
8344 8344 info.Operation == MENLO_OP_WRITE_MEM) {
8345 8345 pkt->mdata.total_byte_count = LE_32(info.TotalByteCount);
8346 8346 pkt->mdata.parameter_1 =
8347 8347 LE_32(info.Parameters.ap.MenloMemory.StartingAddr);
8348 8348 dma_mem = (dma_mem_t *)kmem_zalloc(sizeof (dma_mem_t),
8349 8349 KM_SLEEP);
8350 8350 if (dma_mem == NULL) {
8351 8351 EL(ha, "failed, kmem_zalloc\n");
8352 8352 kmem_free(pkt, sizeof (ql_mbx_iocb_t));
8353 8353 cmd->Status = EXT_STATUS_NO_MEMORY;
8354 8354 cmd->ResponseLen = 0;
8355 8355 return;
8356 8356 }
8357 8357 if (ql_get_dma_mem(ha, dma_mem, info.TotalByteCount,
8358 8358 LITTLE_ENDIAN_DMA, QL_DMA_DATA_ALIGN) != QL_SUCCESS) {
8359 8359 cmn_err(CE_WARN, "%s(%d): request queue DMA memory "
8360 8360 "alloc failed", QL_NAME, ha->instance);
8361 8361 kmem_free(dma_mem, sizeof (dma_mem_t));
8362 8362 kmem_free(pkt, sizeof (ql_mbx_iocb_t));
8363 8363 cmd->Status = EXT_STATUS_MS_NO_RESPONSE;
8364 8364 cmd->ResponseLen = 0;
8365 8365 return;
8366 8366 }
8367 8367 if (info.Operation == MENLO_OP_WRITE_MEM) {
8368 8368 /* Get data. */
8369 8369 if (ql_get_buffer_data(
8370 8370 (caddr_t)(uintptr_t)info.pDataBytes,
8371 8371 dma_mem->bp, info.TotalByteCount, mode) !=
8372 8372 info.TotalByteCount) {
8373 8373 EL(ha, "failed, get_buffer_data\n");
8374 8374 ql_free_dma_resource(ha, dma_mem);
8375 8375 kmem_free(dma_mem, sizeof (dma_mem_t));
8376 8376 kmem_free(pkt, sizeof (ql_mbx_iocb_t));
8377 8377 cmd->Status = EXT_STATUS_COPY_ERR;
8378 8378 cmd->ResponseLen = 0;
8379 8379 return;
8380 8380 }
8381 8381 (void) ddi_dma_sync(dma_mem->dma_handle, 0,
8382 8382 dma_mem->size, DDI_DMA_SYNC_FORDEV);
8383 8383 }
8384 8384 pkt->mdata.dseg_count = LE_16(1);
8385 8385 pkt->mdata.dseg_0_address[0] = (uint32_t)
8386 8386 LE_32(LSD(dma_mem->cookie.dmac_laddress));
8387 8387 pkt->mdata.dseg_0_address[1] = (uint32_t)
8388 8388 LE_32(MSD(dma_mem->cookie.dmac_laddress));
8389 8389 pkt->mdata.dseg_0_length = LE_32(info.TotalByteCount);
8390 8390 } else if (info.Operation & MENLO_OP_CHANGE_CONFIG) {
8391 8391 pkt->mdata.parameter_1 =
8392 8392 LE_32(info.Parameters.ap.MenloConfig.ConfigParamID);
8393 8393 pkt->mdata.parameter_2 =
8394 8394 LE_32(info.Parameters.ap.MenloConfig.ConfigParamData0);
8395 8395 pkt->mdata.parameter_3 =
8396 8396 LE_32(info.Parameters.ap.MenloConfig.ConfigParamData1);
8397 8397 } else if (info.Operation & MENLO_OP_GET_INFO) {
8398 8398 pkt->mdata.parameter_1 =
8399 8399 LE_32(info.Parameters.ap.MenloInfo.InfoDataType);
8400 8400 pkt->mdata.parameter_2 =
8401 8401 LE_32(info.Parameters.ap.MenloInfo.InfoContext);
8402 8402 }
8403 8403
8404 8404 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, sizeof (ql_mbx_iocb_t));
8405 8405 LITTLE_ENDIAN_16(&pkt->mdata.options_status);
8406 8406 LITTLE_ENDIAN_16(&pkt->mdata.failure_code);
8407 8407
8408 8408 if (rval != QL_SUCCESS || (pkt->mdata.entry_status & 0x3c) != 0 ||
8409 8409 pkt->mdata.options_status != CS_COMPLETE) {
8410 8410 /* Command error */
8411 8411 EL(ha, "failed, status=%xh, es=%xh, cs=%xh, fc=%xh\n", rval,
8412 8412 pkt->mdata.entry_status & 0x3c, pkt->mdata.options_status,
8413 8413 pkt->mdata.failure_code);
8414 8414 cmd->Status = EXT_STATUS_ERR;
8415 8415 cmd->DetailStatus = rval != QL_SUCCESS ? rval :
8416 8416 QL_FUNCTION_FAILED;
8417 8417 cmd->ResponseLen = 0;
8418 8418 } else if (info.Operation == MENLO_OP_READ_MEM) {
8419 8419 (void) ddi_dma_sync(dma_mem->dma_handle, 0, dma_mem->size,
8420 8420 DDI_DMA_SYNC_FORKERNEL);
8421 8421 if (ql_send_buffer_data((caddr_t)(uintptr_t)info.pDataBytes,
8422 8422 dma_mem->bp, info.TotalByteCount, mode) !=
8423 8423 info.TotalByteCount) {
8424 8424 cmd->Status = EXT_STATUS_COPY_ERR;
8425 8425 cmd->ResponseLen = 0;
8426 8426 }
8427 8427 }
8428 8428
8429 8429 ql_free_dma_resource(ha, dma_mem);
8430 8430 kmem_free(dma_mem, sizeof (dma_mem_t));
8431 8431 kmem_free(pkt, sizeof (ql_mbx_iocb_t));
8432 8432
8433 8433 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
8434 8434 }
8435 8435
8436 8436 /*
8437 8437 * ql_suspend_hba
8438 8438 * Suspends all adapter ports.
8439 8439 *
8440 8440 * Input:
8441 8441 * ha: adapter state pointer.
8442 8442 * options: BIT_0 --> leave driver stalled on exit if
8443 8443 * failed.
8444 8444 *
8445 8445 * Returns:
8446 8446 * ql local function return status code.
8447 8447 *
8448 8448 * Context:
8449 8449 * Kernel context.
8450 8450 */
8451 8451 static int
8452 8452 ql_suspend_hba(ql_adapter_state_t *ha, uint32_t opt)
8453 8453 {
8454 8454 ql_adapter_state_t *ha2;
8455 8455 ql_link_t *link;
8456 8456 int rval = QL_SUCCESS;
8457 8457
8458 8458 /* Quiesce I/O on all adapter ports */
8459 8459 for (link = ql_hba.first; link != NULL; link = link->next) {
8460 8460 ha2 = link->base_address;
8461 8461
8462 8462 if (ha2->fru_hba_index != ha->fru_hba_index) {
8463 8463 continue;
8464 8464 }
8465 8465
8466 8466 if ((rval = ql_stall_driver(ha2, opt)) != QL_SUCCESS) {
8467 8467 EL(ha, "ql_stall_driver status=%xh\n", rval);
8468 8468 break;
8469 8469 }
8470 8470 }
8471 8471
8472 8472 return (rval);
8473 8473 }
8474 8474
8475 8475 /*
8476 8476 * ql_restart_hba
8477 8477 * Restarts adapter.
8478 8478 *
8479 8479 * Input:
8480 8480 * ha: adapter state pointer.
8481 8481 *
8482 8482 * Context:
8483 8483 * Kernel context.
8484 8484 */
8485 8485 static void
8486 8486 ql_restart_hba(ql_adapter_state_t *ha)
8487 8487 {
8488 8488 ql_adapter_state_t *ha2;
8489 8489 ql_link_t *link;
8490 8490
8491 8491 /* Resume I/O on all adapter ports */
8492 8492 for (link = ql_hba.first; link != NULL; link = link->next) {
8493 8493 ha2 = link->base_address;
8494 8494
8495 8495 if (ha2->fru_hba_index != ha->fru_hba_index) {
8496 8496 continue;
8497 8497 }
8498 8498
8499 8499 ql_restart_driver(ha2);
8500 8500 }
8501 8501 }
8502 8502
8503 8503 /*
8504 8504 * ql_get_vp_cnt_id
8505 8505 * Retrieves pci config space data
8506 8506 *
8507 8507 * Input:
8508 8508 * ha: adapter state pointer.
8509 8509 * cmd: Local EXT_IOCTL cmd struct pointer.
8510 8510 * mode: flags.
8511 8511 *
8512 8512 * Returns:
8513 8513 * None, request status indicated in cmd->Status.
8514 8514 *
8515 8515 * Context:
8516 8516 * Kernel context.
8517 8517 *
8518 8518 */
8519 8519 static void
8520 8520 ql_get_vp_cnt_id(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
8521 8521 {
8522 8522 ql_adapter_state_t *vha;
8523 8523 PEXT_VPORT_ID_CNT ptmp_vp;
8524 8524 int id = 0;
8525 8525 int rval;
8526 8526 char name[MAXPATHLEN];
8527 8527
8528 8528 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
8529 8529
8530 8530 /*
8531 8531 * To be backward compatible with older API
8532 8532 * check for the size of old EXT_VPORT_ID_CNT
8533 8533 */
8534 8534 if (cmd->ResponseLen < sizeof (EXT_VPORT_ID_CNT) &&
8535 8535 (cmd->ResponseLen != EXT_OLD_VPORT_ID_CNT_SIZE)) {
8536 8536 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
8537 8537 cmd->DetailStatus = sizeof (EXT_VPORT_ID_CNT);
8538 8538 EL(ha, "failed, ResponseLen < EXT_VPORT_ID_CNT, Len=%xh\n",
8539 8539 cmd->ResponseLen);
8540 8540 cmd->ResponseLen = 0;
8541 8541 return;
8542 8542 }
8543 8543
8544 8544 ptmp_vp = (EXT_VPORT_ID_CNT *)
8545 8545 kmem_zalloc(sizeof (EXT_VPORT_ID_CNT), KM_SLEEP);
8546 8546 if (ptmp_vp == NULL) {
8547 8547 EL(ha, "failed, kmem_zalloc\n");
8548 8548 cmd->ResponseLen = 0;
8549 8549 return;
8550 8550 }
8551 8551 vha = ha->vp_next;
8552 8552 while (vha != NULL) {
8553 8553 ptmp_vp->VpCnt++;
8554 8554 ptmp_vp->VpId[id] = vha->vp_index;
8555 8555 (void) ddi_pathname(vha->dip, name);
8556 8556 (void) strcpy((char *)ptmp_vp->vp_path[id], name);
8557 8557 ptmp_vp->VpDrvInst[id] = (int32_t)vha->instance;
8558 8558 id++;
8559 8559 vha = vha->vp_next;
8560 8560 }
8561 8561 rval = ddi_copyout((void *)ptmp_vp,
8562 8562 (void *)(uintptr_t)(cmd->ResponseAdr),
8563 8563 cmd->ResponseLen, mode);
8564 8564 if (rval != 0) {
8565 8565 cmd->Status = EXT_STATUS_COPY_ERR;
8566 8566 cmd->ResponseLen = 0;
8567 8567 EL(ha, "failed, ddi_copyout\n");
8568 8568 } else {
8569 8569 cmd->ResponseLen = sizeof (EXT_VPORT_ID_CNT);
8570 8570 QL_PRINT_9(CE_CONT, "(%d): done, vport_cnt=%d\n",
8571 8571 ha->instance, ptmp_vp->VpCnt);
8572 8572 }
8573 8573
8574 8574 }
8575 8575
8576 8576 /*
8577 8577 * ql_vp_ioctl
8578 8578 * Performs all EXT_CC_VPORT_CMD functions.
8579 8579 *
8580 8580 * Input:
8581 8581 * ha: adapter state pointer.
8582 8582 * cmd: Local EXT_IOCTL cmd struct pointer.
8583 8583 * mode: flags.
8584 8584 *
8585 8585 * Returns:
8586 8586 * None, request status indicated in cmd->Status.
8587 8587 *
8588 8588 * Context:
8589 8589 * Kernel context.
8590 8590 */
8591 8591 static void
8592 8592 ql_vp_ioctl(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
8593 8593 {
8594 8594 QL_PRINT_9(CE_CONT, "(%d): started, cmd=%d\n", ha->instance,
8595 8595 cmd->SubCode);
8596 8596
8597 8597 /* case off on command subcode */
8598 8598 switch (cmd->SubCode) {
8599 8599 case EXT_VF_SC_VPORT_GETINFO:
8600 8600 ql_qry_vport(ha, cmd, mode);
8601 8601 break;
8602 8602 default:
8603 8603 /* function not supported. */
8604 8604 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE;
8605 8605 EL(ha, "failed, Unsupported Subcode=%xh\n",
8606 8606 cmd->SubCode);
8607 8607 break;
8608 8608 }
8609 8609
8610 8610 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
8611 8611 }
8612 8612
8613 8613 /*
8614 8614 * ql_qry_vport
8615 8615 * Performs EXT_VF_SC_VPORT_GETINFO subfunction.
8616 8616 *
8617 8617 * Input:
8618 8618 * ha: adapter state pointer.
8619 8619 * cmd: EXT_IOCTL cmd struct pointer.
8620 8620 * mode: flags.
8621 8621 *
8622 8622 * Returns:
8623 8623 * None, request status indicated in cmd->Status.
8624 8624 *
8625 8625 * Context:
8626 8626 * Kernel context.
8627 8627 */
8628 8628 static void
8629 8629 ql_qry_vport(ql_adapter_state_t *vha, EXT_IOCTL *cmd, int mode)
8630 8630 {
8631 8631 ql_adapter_state_t *tmp_vha;
8632 8632 EXT_VPORT_INFO tmp_vport = {0};
8633 8633 int max_vport;
8634 8634
8635 8635 QL_PRINT_9(CE_CONT, "(%d): started\n", vha->instance);
8636 8636
8637 8637 if (cmd->ResponseLen < sizeof (EXT_VPORT_INFO)) {
8638 8638 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
8639 8639 cmd->DetailStatus = sizeof (EXT_VPORT_INFO);
8640 8640 EL(vha, "failed, ResponseLen < EXT_VPORT_INFO, Len=%xh\n",
8641 8641 cmd->ResponseLen);
8642 8642 cmd->ResponseLen = 0;
8643 8643 return;
8644 8644 }
8645 8645
8646 8646 /* Fill in the vport information. */
8647 8647 bcopy(vha->loginparams.node_ww_name.raw_wwn, tmp_vport.wwnn,
8648 8648 EXT_DEF_WWN_NAME_SIZE);
8649 8649 bcopy(vha->loginparams.nport_ww_name.raw_wwn, tmp_vport.wwpn,
8650 8650 EXT_DEF_WWN_NAME_SIZE);
8651 8651 tmp_vport.state = vha->state;
8652 8652 tmp_vport.id = vha->vp_index;
8653 8653
8654 8654 tmp_vha = vha->pha->vp_next;
8655 8655 while (tmp_vha != NULL) {
8656 8656 tmp_vport.used++;
8657 8657 tmp_vha = tmp_vha->vp_next;
8658 8658 }
8659 8659
8660 8660 max_vport = (CFG_IST(vha, CFG_CTRL_2422) ? MAX_24_VIRTUAL_PORTS :
8661 8661 MAX_25_VIRTUAL_PORTS);
8662 8662 if (max_vport > tmp_vport.used) {
8663 8663 tmp_vport.free = max_vport - tmp_vport.used;
8664 8664 }
8665 8665
8666 8666 if (ddi_copyout((void *)&tmp_vport,
8667 8667 (void *)(uintptr_t)(cmd->ResponseAdr),
8668 8668 sizeof (EXT_VPORT_INFO), mode) != 0) {
8669 8669 cmd->Status = EXT_STATUS_COPY_ERR;
8670 8670 cmd->ResponseLen = 0;
8671 8671 EL(vha, "failed, ddi_copyout\n");
8672 8672 } else {
8673 8673 cmd->ResponseLen = sizeof (EXT_VPORT_INFO);
8674 8674 QL_PRINT_9(CE_CONT, "(%d): done\n", vha->instance);
8675 8675 }
8676 8676 }
8677 8677
8678 8678 /*
8679 8679 * ql_access_flash
8680 8680 * Performs all EXT_CC_ACCESS_FLASH_OS functions.
8681 8681 *
8682 8682 * Input:
8683 8683 * pi: port info pointer.
8684 8684 * cmd: Local EXT_IOCTL cmd struct pointer.
8685 8685 * mode: flags.
8686 8686 *
8687 8687 * Returns:
8688 8688 * None, request status indicated in cmd->Status.
8689 8689 *
8690 8690 * Context:
8691 8691 * Kernel context.
8692 8692 */
8693 8693 static void
8694 8694 ql_access_flash(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
8695 8695 {
8696 8696 int rval;
8697 8697
8698 8698 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
8699 8699
8700 8700 switch (cmd->SubCode) {
8701 8701 case EXT_SC_FLASH_READ:
8702 8702 if ((rval = ql_flash_fcode_dump(ha,
8703 8703 (void *)(uintptr_t)(cmd->ResponseAdr),
8704 8704 (size_t)(cmd->ResponseLen), cmd->Reserved1, mode)) != 0) {
8705 8705 cmd->Status = EXT_STATUS_COPY_ERR;
8706 8706 cmd->ResponseLen = 0;
8707 8707 EL(ha, "flash_fcode_dump status=%xh\n", rval);
8708 8708 }
8709 8709 break;
8710 8710 case EXT_SC_FLASH_WRITE:
8711 8711 if ((rval = ql_r_m_w_flash(ha,
8712 8712 (void *)(uintptr_t)(cmd->RequestAdr),
8713 8713 (size_t)(cmd->RequestLen), cmd->Reserved1, mode)) !=
8714 8714 QL_SUCCESS) {
8715 8715 cmd->Status = EXT_STATUS_COPY_ERR;
8716 8716 cmd->ResponseLen = 0;
8717 8717 EL(ha, "r_m_w_flash status=%xh\n", rval);
8718 8718 } else {
8719 8719 /* Reset caches on all adapter instances. */
8720 8720 ql_update_flash_caches(ha);
8721 8721 }
8722 8722 break;
8723 8723 default:
8724 8724 EL(ha, "unknown subcode=%xh\n", cmd->SubCode);
8725 8725 cmd->Status = EXT_STATUS_ERR;
8726 8726 cmd->ResponseLen = 0;
8727 8727 break;
8728 8728 }
8729 8729
8730 8730 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
8731 8731 }
8732 8732
8733 8733 /*
8734 8734 * ql_reset_cmd
8735 8735 * Performs all EXT_CC_RESET_FW_OS functions.
8736 8736 *
8737 8737 * Input:
8738 8738 * ha: adapter state pointer.
8739 8739 * cmd: Local EXT_IOCTL cmd struct pointer.
8740 8740 *
8741 8741 * Returns:
8742 8742 * None, request status indicated in cmd->Status.
8743 8743 *
8744 8744 * Context:
8745 8745 * Kernel context.
8746 8746 */
8747 8747 static void
8748 8748 ql_reset_cmd(ql_adapter_state_t *ha, EXT_IOCTL *cmd)
8749 8749 {
8750 8750 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
8751 8751
8752 8752 switch (cmd->SubCode) {
8753 8753 case EXT_SC_RESET_FC_FW:
8754 8754 EL(ha, "isp_abort_needed\n");
8755 8755 ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0);
8756 8756 break;
8757 8757 case EXT_SC_RESET_MPI_FW:
8758 8758 if (!(CFG_IST(ha, CFG_CTRL_81XX))) {
8759 8759 EL(ha, "invalid request for HBA\n");
8760 8760 cmd->Status = EXT_STATUS_INVALID_REQUEST;
8761 8761 cmd->ResponseLen = 0;
8762 8762 } else {
8763 8763 /* Wait for I/O to stop and daemon to stall. */
8764 8764 if (ql_suspend_hba(ha, 0) != QL_SUCCESS) {
8765 8765 EL(ha, "ql_suspend_hba failed\n");
8766 8766 cmd->Status = EXT_STATUS_BUSY;
8767 8767 cmd->ResponseLen = 0;
8768 8768 } else if (ql_restart_mpi(ha) != QL_SUCCESS) {
8769 8769 cmd->Status = EXT_STATUS_ERR;
8770 8770 cmd->ResponseLen = 0;
8771 8771 } else {
8772 8772 uint8_t timer;
8773 8773 /*
8774 8774 * While the restart_mpi mailbox cmd may be
8775 8775 * done the MPI is not. Wait at least 6 sec. or
8776 8776 * exit if the loop comes up.
8777 8777 */
8778 8778 for (timer = 6; timer; timer--) {
8779 8779 if (!(ha->task_daemon_flags &
8780 8780 LOOP_DOWN)) {
8781 8781 break;
8782 8782 }
8783 8783 /* Delay for 1 second. */
8784 8784 ql_delay(ha, 1000000);
8785 8785 }
8786 8786 }
8787 8787 ql_restart_hba(ha);
8788 8788 }
8789 8789 break;
8790 8790 default:
8791 8791 EL(ha, "unknown subcode=%xh\n", cmd->SubCode);
8792 8792 cmd->Status = EXT_STATUS_ERR;
8793 8793 cmd->ResponseLen = 0;
8794 8794 break;
8795 8795 }
8796 8796
8797 8797 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
8798 8798 }
8799 8799
8800 8800 /*
8801 8801 * ql_get_dcbx_parameters
8802 8802 * Get DCBX parameters.
8803 8803 *
8804 8804 * Input:
8805 8805 * ha: adapter state pointer.
8806 8806 * cmd: User space CT arguments pointer.
8807 8807 * mode: flags.
8808 8808 */
8809 8809 static void
8810 8810 ql_get_dcbx_parameters(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
8811 8811 {
8812 8812 uint8_t *tmp_buf;
8813 8813 int rval;
8814 8814
8815 8815 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
8816 8816
8817 8817 if (!(CFG_IST(ha, CFG_CTRL_8081))) {
8818 8818 EL(ha, "invalid request for HBA\n");
8819 8819 cmd->Status = EXT_STATUS_INVALID_REQUEST;
8820 8820 cmd->ResponseLen = 0;
8821 8821 return;
8822 8822 }
8823 8823
8824 8824 /* Allocate memory for command. */
8825 8825 tmp_buf = kmem_zalloc(EXT_DEF_DCBX_PARAM_BUF_SIZE, KM_SLEEP);
8826 8826 if (tmp_buf == NULL) {
8827 8827 EL(ha, "failed, kmem_zalloc\n");
8828 8828 cmd->Status = EXT_STATUS_NO_MEMORY;
8829 8829 cmd->ResponseLen = 0;
8830 8830 return;
8831 8831 }
8832 8832 /* Send command */
8833 8833 rval = ql_get_dcbx_params(ha, EXT_DEF_DCBX_PARAM_BUF_SIZE,
8834 8834 (caddr_t)tmp_buf);
8835 8835 if (rval != QL_SUCCESS) {
8836 8836 /* error */
8837 8837 EL(ha, "failed, get_dcbx_params_mbx=%xh\n", rval);
8838 8838 kmem_free(tmp_buf, EXT_DEF_DCBX_PARAM_BUF_SIZE);
8839 8839 cmd->Status = EXT_STATUS_ERR;
8840 8840 cmd->ResponseLen = 0;
8841 8841 return;
8842 8842 }
8843 8843
8844 8844 /* Copy the response */
8845 8845 if (ql_send_buffer_data((caddr_t)tmp_buf,
8846 8846 (caddr_t)(uintptr_t)cmd->ResponseAdr,
8847 8847 EXT_DEF_DCBX_PARAM_BUF_SIZE, mode) != EXT_DEF_DCBX_PARAM_BUF_SIZE) {
8848 8848 EL(ha, "failed, ddi_copyout\n");
8849 8849 cmd->Status = EXT_STATUS_COPY_ERR;
8850 8850 cmd->ResponseLen = 0;
8851 8851 } else {
8852 8852 cmd->ResponseLen = EXT_DEF_DCBX_PARAM_BUF_SIZE;
8853 8853 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
8854 8854 }
8855 8855 kmem_free(tmp_buf, EXT_DEF_DCBX_PARAM_BUF_SIZE);
8856 8856
8857 8857 }
8858 8858
8859 8859 /*
8860 8860 * ql_qry_cna_port
8861 8861 * Performs EXT_SC_QUERY_CNA_PORT subfunction.
8862 8862 *
8863 8863 * Input:
8864 8864 * ha: adapter state pointer.
8865 8865 * cmd: EXT_IOCTL cmd struct pointer.
8866 8866 * mode: flags.
8867 8867 *
8868 8868 * Returns:
8869 8869 * None, request status indicated in cmd->Status.
8870 8870 *
8871 8871 * Context:
8872 8872 * Kernel context.
8873 8873 */
8874 8874 static void
8875 8875 ql_qry_cna_port(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
8876 8876 {
8877 8877 EXT_CNA_PORT cna_port = {0};
8878 8878
8879 8879 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
8880 8880
8881 8881 if (!(CFG_IST(ha, CFG_CTRL_8081))) {
8882 8882 EL(ha, "invalid request for HBA\n");
8883 8883 cmd->Status = EXT_STATUS_INVALID_REQUEST;
8884 8884 cmd->ResponseLen = 0;
8885 8885 return;
8886 8886 }
8887 8887
8888 8888 if (cmd->ResponseLen < sizeof (EXT_CNA_PORT)) {
8889 8889 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
8890 8890 cmd->DetailStatus = sizeof (EXT_CNA_PORT);
8891 8891 EL(ha, "failed, ResponseLen < EXT_CNA_PORT, Len=%xh\n",
8892 8892 cmd->ResponseLen);
8893 8893 cmd->ResponseLen = 0;
8894 8894 return;
8895 8895 }
8896 8896
8897 8897 cna_port.VLanId = ha->fcoe_vlan_id;
8898 8898 cna_port.FabricParam = ha->fabric_params;
8899 8899 bcopy(ha->fcoe_vnport_mac, cna_port.VNPortMACAddress,
8900 8900 EXT_DEF_MAC_ADDRESS_SIZE);
8901 8901
8902 8902 if (ddi_copyout((void *)&cna_port,
8903 8903 (void *)(uintptr_t)(cmd->ResponseAdr),
8904 8904 sizeof (EXT_CNA_PORT), mode) != 0) {
8905 8905 cmd->Status = EXT_STATUS_COPY_ERR;
8906 8906 cmd->ResponseLen = 0;
8907 8907 EL(ha, "failed, ddi_copyout\n");
8908 8908 } else {
8909 8909 cmd->ResponseLen = sizeof (EXT_CNA_PORT);
8910 8910 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
8911 8911 }
8912 8912 }
8913 8913
8914 8914 /*
8915 8915 * ql_qry_adapter_versions
8916 8916 * Performs EXT_SC_QUERY_ADAPTER_VERSIONS subfunction.
8917 8917 *
8918 8918 * Input:
8919 8919 * ha: adapter state pointer.
8920 8920 * cmd: EXT_IOCTL cmd struct pointer.
8921 8921 * mode: flags.
8922 8922 *
8923 8923 * Returns:
8924 8924 * None, request status indicated in cmd->Status.
8925 8925 *
8926 8926 * Context:
8927 8927 * Kernel context.
8928 8928 */
8929 8929 static void
8930 8930 ql_qry_adapter_versions(ql_adapter_state_t *ha, EXT_IOCTL *cmd,
8931 8931 int mode)
8932 8932 {
8933 8933 uint8_t is_8142, mpi_cap;
8934 8934 uint32_t ver_len, transfer_size;
8935 8935 PEXT_ADAPTERREGIONVERSION padapter_ver = NULL;
8936 8936
8937 8937 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
8938 8938
8939 8939 /* 8142s do not have a EDC PHY firmware. */
8940 8940 mpi_cap = (uint8_t)(ha->mpi_capability_list >> 8);
8941 8941
8942 8942 is_8142 = 0;
8943 8943 /* Sizeof (Length + Reserved) = 8 Bytes */
8944 8944 if (mpi_cap == 0x02 || mpi_cap == 0x04) {
8945 8945 ver_len = (sizeof (EXT_REGIONVERSION) * (NO_OF_VERSIONS - 1))
8946 8946 + 8;
8947 8947 is_8142 = 1;
8948 8948 } else {
8949 8949 ver_len = (sizeof (EXT_REGIONVERSION) * NO_OF_VERSIONS) + 8;
8950 8950 }
8951 8951
8952 8952 /* Allocate local memory for EXT_ADAPTERREGIONVERSION */
8953 8953 padapter_ver = (EXT_ADAPTERREGIONVERSION *)kmem_zalloc(ver_len,
8954 8954 KM_SLEEP);
8955 8955
8956 8956 if (padapter_ver == NULL) {
8957 8957 EL(ha, "failed, kmem_zalloc\n");
8958 8958 cmd->Status = EXT_STATUS_NO_MEMORY;
8959 8959 cmd->ResponseLen = 0;
8960 8960 return;
8961 8961 }
8962 8962
8963 8963 padapter_ver->Length = 1;
8964 8964 /* Copy MPI version */
8965 8965 padapter_ver->RegionVersion[0].Region =
8966 8966 EXT_OPT_ROM_REGION_MPI_RISC_FW;
8967 8967 padapter_ver->RegionVersion[0].Version[0] =
8968 8968 ha->mpi_fw_major_version;
8969 8969 padapter_ver->RegionVersion[0].Version[1] =
8970 8970 ha->mpi_fw_minor_version;
8971 8971 padapter_ver->RegionVersion[0].Version[2] =
8972 8972 ha->mpi_fw_subminor_version;
8973 8973 padapter_ver->RegionVersion[0].VersionLength = 3;
8974 8974 padapter_ver->RegionVersion[0].Location = RUNNING_VERSION;
8975 8975
8976 8976 if (!is_8142) {
8977 8977 padapter_ver->RegionVersion[1].Region =
8978 8978 EXT_OPT_ROM_REGION_EDC_PHY_FW;
8979 8979 padapter_ver->RegionVersion[1].Version[0] =
8980 8980 ha->phy_fw_major_version;
8981 8981 padapter_ver->RegionVersion[1].Version[1] =
8982 8982 ha->phy_fw_minor_version;
8983 8983 padapter_ver->RegionVersion[1].Version[2] =
8984 8984 ha->phy_fw_subminor_version;
8985 8985 padapter_ver->RegionVersion[1].VersionLength = 3;
8986 8986 padapter_ver->RegionVersion[1].Location = RUNNING_VERSION;
8987 8987 padapter_ver->Length = NO_OF_VERSIONS;
8988 8988 }
8989 8989
8990 8990 if (cmd->ResponseLen < ver_len) {
8991 8991 EL(ha, "failed, ResponseLen < ver_len, ",
8992 8992 "RespLen=%xh ver_len=%xh\n", cmd->ResponseLen, ver_len);
8993 8993 /* Calculate the No. of valid versions being returned. */
8994 8994 padapter_ver->Length = (uint32_t)
8995 8995 ((cmd->ResponseLen - 8) / sizeof (EXT_REGIONVERSION));
8996 8996 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
8997 8997 cmd->DetailStatus = ver_len;
8998 8998 transfer_size = cmd->ResponseLen;
8999 8999 } else {
9000 9000 transfer_size = ver_len;
9001 9001 }
9002 9002
9003 9003 if (ddi_copyout((void *)padapter_ver,
9004 9004 (void *)(uintptr_t)(cmd->ResponseAdr),
9005 9005 transfer_size, mode) != 0) {
9006 9006 cmd->Status = EXT_STATUS_COPY_ERR;
9007 9007 cmd->ResponseLen = 0;
9008 9008 EL(ha, "failed, ddi_copyout\n");
9009 9009 } else {
9010 9010 cmd->ResponseLen = ver_len;
9011 9011 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
9012 9012 }
9013 9013
9014 9014 kmem_free(padapter_ver, ver_len);
9015 9015 }
9016 9016
9017 9017 /*
9018 9018 * ql_get_xgmac_statistics
9019 9019 * Get XgMac information
9020 9020 *
9021 9021 * Input:
9022 9022 * ha: adapter state pointer.
9023 9023 * cmd: EXT_IOCTL cmd struct pointer.
9024 9024 * mode: flags.
9025 9025 *
9026 9026 * Returns:
9027 9027 * None, request status indicated in cmd->Status.
9028 9028 *
9029 9029 * Context:
9030 9030 * Kernel context.
9031 9031 */
9032 9032 static void
9033 9033 ql_get_xgmac_statistics(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
9034 9034 {
9035 9035 int rval;
9036 9036 uint32_t size;
9037 9037 int8_t *tmp_buf;
9038 9038 EXT_MENLO_MANAGE_INFO info;
9039 9039
9040 9040 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
9041 9041
9042 9042 /* Verify the size of request structure. */
9043 9043 if (cmd->RequestLen < sizeof (EXT_MENLO_MANAGE_INFO)) {
9044 9044 /* Return error */
9045 9045 EL(ha, "RequestLen=%d < %d\n", cmd->RequestLen,
9046 9046 sizeof (EXT_MENLO_MANAGE_INFO));
9047 9047 cmd->Status = EXT_STATUS_INVALID_PARAM;
9048 9048 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN;
9049 9049 cmd->ResponseLen = 0;
9050 9050 return;
9051 9051 }
9052 9052
9053 9053 /* Get manage info request. */
9054 9054 if (ddi_copyin((caddr_t)(uintptr_t)cmd->RequestAdr,
9055 9055 (caddr_t)&info, sizeof (EXT_MENLO_MANAGE_INFO), mode) != 0) {
9056 9056 EL(ha, "failed, ddi_copyin\n");
9057 9057 cmd->Status = EXT_STATUS_COPY_ERR;
9058 9058 cmd->ResponseLen = 0;
9059 9059 return;
9060 9060 }
9061 9061
9062 9062 size = info.TotalByteCount;
9063 9063 if (!size) {
9064 9064 /* parameter error */
9065 9065 cmd->Status = EXT_STATUS_INVALID_PARAM;
9066 9066 cmd->DetailStatus = 0;
9067 9067 EL(ha, "failed, size=%xh\n", size);
9068 9068 cmd->ResponseLen = 0;
9069 9069 return;
9070 9070 }
9071 9071
9072 9072 /* Allocate memory for command. */
9073 9073 tmp_buf = kmem_zalloc(size, KM_SLEEP);
9074 9074 if (tmp_buf == NULL) {
9075 9075 EL(ha, "failed, kmem_zalloc\n");
9076 9076 cmd->Status = EXT_STATUS_NO_MEMORY;
9077 9077 cmd->ResponseLen = 0;
9078 9078 return;
9079 9079 }
9080 9080
9081 9081 if (!(info.Operation & MENLO_OP_GET_INFO)) {
9082 9082 EL(ha, "Invalid request for 81XX\n");
9083 9083 kmem_free(tmp_buf, size);
9084 9084 cmd->Status = EXT_STATUS_ERR;
9085 9085 cmd->ResponseLen = 0;
9086 9086 return;
9087 9087 }
9088 9088
9089 9089 rval = ql_get_xgmac_stats(ha, size, (caddr_t)tmp_buf);
9090 9090
9091 9091 if (rval != QL_SUCCESS) {
9092 9092 /* error */
9093 9093 EL(ha, "failed, get_xgmac_stats =%xh\n", rval);
9094 9094 kmem_free(tmp_buf, size);
9095 9095 cmd->Status = EXT_STATUS_ERR;
9096 9096 cmd->ResponseLen = 0;
9097 9097 return;
9098 9098 }
9099 9099
9100 9100 if (ql_send_buffer_data(tmp_buf, (caddr_t)(uintptr_t)info.pDataBytes,
9101 9101 size, mode) != size) {
9102 9102 EL(ha, "failed, ddi_copyout\n");
9103 9103 cmd->Status = EXT_STATUS_COPY_ERR;
9104 9104 cmd->ResponseLen = 0;
9105 9105 } else {
9106 9106 cmd->ResponseLen = info.TotalByteCount;
9107 9107 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
9108 9108 }
9109 9109 kmem_free(tmp_buf, size);
9110 9110 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
9111 9111 }
9112 9112
9113 9113 /*
9114 9114 * ql_get_fcf_list
9115 9115 * Get FCF list.
9116 9116 *
9117 9117 * Input:
9118 9118 * ha: adapter state pointer.
9119 9119 * cmd: User space CT arguments pointer.
9120 9120 * mode: flags.
9121 9121 */
9122 9122 static void
9123 9123 ql_get_fcf_list(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
9124 9124 {
9125 9125 uint8_t *tmp_buf;
9126 9126 int rval;
9127 9127 EXT_FCF_LIST fcf_list = {0};
9128 9128 ql_fcf_list_desc_t mb_fcf_list = {0};
9129 9129
9130 9130 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
9131 9131
9132 9132 if (!(CFG_IST(ha, CFG_CTRL_81XX))) {
9133 9133 EL(ha, "invalid request for HBA\n");
9134 9134 cmd->Status = EXT_STATUS_INVALID_REQUEST;
9135 9135 cmd->ResponseLen = 0;
9136 9136 return;
9137 9137 }
9138 9138 /* Get manage info request. */
9139 9139 if (ddi_copyin((caddr_t)(uintptr_t)cmd->RequestAdr,
9140 9140 (caddr_t)&fcf_list, sizeof (EXT_FCF_LIST), mode) != 0) {
9141 9141 EL(ha, "failed, ddi_copyin\n");
9142 9142 cmd->Status = EXT_STATUS_COPY_ERR;
9143 9143 cmd->ResponseLen = 0;
9144 9144 return;
9145 9145 }
9146 9146
9147 9147 if (!(fcf_list.BufSize)) {
9148 9148 /* Return error */
9149 9149 EL(ha, "failed, fcf_list BufSize is=%xh\n",
9150 9150 fcf_list.BufSize);
9151 9151 cmd->Status = EXT_STATUS_INVALID_PARAM;
9152 9152 cmd->ResponseLen = 0;
9153 9153 return;
9154 9154 }
9155 9155 /* Allocate memory for command. */
9156 9156 tmp_buf = kmem_zalloc(fcf_list.BufSize, KM_SLEEP);
9157 9157 if (tmp_buf == NULL) {
9158 9158 EL(ha, "failed, kmem_zalloc\n");
9159 9159 cmd->Status = EXT_STATUS_NO_MEMORY;
9160 9160 cmd->ResponseLen = 0;
9161 9161 return;
9162 9162 }
9163 9163 /* build the descriptor */
9164 9164 if (fcf_list.Options) {
9165 9165 mb_fcf_list.options = FCF_LIST_RETURN_ONE;
9166 9166 } else {
9167 9167 mb_fcf_list.options = FCF_LIST_RETURN_ALL;
9168 9168 }
9169 9169 mb_fcf_list.fcf_index = (uint16_t)fcf_list.FcfIndex;
9170 9170 mb_fcf_list.buffer_size = fcf_list.BufSize;
9171 9171
9172 9172 /* Send command */
9173 9173 rval = ql_get_fcf_list_mbx(ha, &mb_fcf_list, (caddr_t)tmp_buf);
9174 9174 if (rval != QL_SUCCESS) {
9175 9175 /* error */
9176 9176 EL(ha, "failed, get_fcf_list_mbx=%xh\n", rval);
9177 9177 kmem_free(tmp_buf, fcf_list.BufSize);
9178 9178 cmd->Status = EXT_STATUS_ERR;
9179 9179 cmd->ResponseLen = 0;
9180 9180 return;
9181 9181 }
9182 9182
9183 9183 /* Copy the response */
9184 9184 if (ql_send_buffer_data((caddr_t)tmp_buf,
9185 9185 (caddr_t)(uintptr_t)cmd->ResponseAdr,
9186 9186 fcf_list.BufSize, mode) != fcf_list.BufSize) {
9187 9187 EL(ha, "failed, ddi_copyout\n");
9188 9188 cmd->Status = EXT_STATUS_COPY_ERR;
9189 9189 cmd->ResponseLen = 0;
9190 9190 } else {
9191 9191 cmd->ResponseLen = mb_fcf_list.buffer_size;
9192 9192 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
9193 9193 }
9194 9194
9195 9195 kmem_free(tmp_buf, fcf_list.BufSize);
9196 9196 }
9197 9197
9198 9198 /*
9199 9199 * ql_get_resource_counts
9200 9200 * Get Resource counts:
9201 9201 *
9202 9202 * Input:
9203 9203 * ha: adapter state pointer.
9204 9204 * cmd: User space CT arguments pointer.
9205 9205 * mode: flags.
9206 9206 */
9207 9207 static void
9208 9208 ql_get_resource_counts(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode)
9209 9209 {
9210 9210 int rval;
9211 9211 ql_mbx_data_t mr;
9212 9212 EXT_RESOURCE_CNTS tmp_rc_cnt = {0};
9213 9213
9214 9214 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
9215 9215
9216 9216 if (!(CFG_IST(ha, CFG_CTRL_242581))) {
9217 9217 EL(ha, "invalid request for HBA\n");
9218 9218 cmd->Status = EXT_STATUS_INVALID_REQUEST;
9219 9219 cmd->ResponseLen = 0;
9220 9220 return;
9221 9221 }
9222 9222
9223 9223 if (cmd->ResponseLen < sizeof (EXT_RESOURCE_CNTS)) {
9224 9224 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL;
9225 9225 cmd->DetailStatus = sizeof (EXT_RESOURCE_CNTS);
9226 9226 EL(ha, "failed, ResponseLen < EXT_RESOURCE_CNTS, "
9227 9227 "Len=%xh\n", cmd->ResponseLen);
9228 9228 cmd->ResponseLen = 0;
9229 9229 return;
9230 9230 }
9231 9231
9232 9232 rval = ql_get_resource_cnts(ha, &mr);
9233 9233 if (rval != QL_SUCCESS) {
9234 9234 EL(ha, "resource cnt mbx failed\n");
9235 9235 cmd->Status = EXT_STATUS_ERR;
9236 9236 cmd->ResponseLen = 0;
9237 9237 return;
9238 9238 }
9239 9239
9240 9240 tmp_rc_cnt.OrgTgtXchgCtrlCnt = (uint32_t)mr.mb[1];
9241 9241 tmp_rc_cnt.CurTgtXchgCtrlCnt = (uint32_t)mr.mb[2];
9242 9242 tmp_rc_cnt.CurXchgCtrlCnt = (uint32_t)mr.mb[3];
9243 9243 tmp_rc_cnt.OrgXchgCtrlCnt = (uint32_t)mr.mb[6];
9244 9244 tmp_rc_cnt.CurIocbBufCnt = (uint32_t)mr.mb[7];
9245 9245 tmp_rc_cnt.OrgIocbBufCnt = (uint32_t)mr.mb[10];
9246 9246 tmp_rc_cnt.NoOfSupVPs = (uint32_t)mr.mb[11];
9247 9247 tmp_rc_cnt.NoOfSupFCFs = (uint32_t)mr.mb[12];
9248 9248
9249 9249 rval = ddi_copyout((void *)&tmp_rc_cnt,
9250 9250 (void *)(uintptr_t)(cmd->ResponseAdr),
9251 9251 sizeof (EXT_RESOURCE_CNTS), mode);
9252 9252 if (rval != 0) {
9253 9253 cmd->Status = EXT_STATUS_COPY_ERR;
9254 9254 cmd->ResponseLen = 0;
9255 9255 EL(ha, "failed, ddi_copyout\n");
9256 9256 } else {
9257 9257 cmd->ResponseLen = sizeof (EXT_RESOURCE_CNTS);
9258 9258 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
9259 9259 }
9260 9260 }
↓ open down ↓ |
1767 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX