1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /* Copyright 2010 QLogic Corporation */
23
24 /*
25 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26 */
27
28 #pragma ident "Copyright 2010 QLogic Corporation; ql_ioctl.c"
29
30 /*
31 * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
32 * Fibre Channel Adapter (FCA) driver IOCTL source file.
33 *
34 * ***********************************************************************
35 * * **
36 * * NOTICE **
37 * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION **
38 * * ALL RIGHTS RESERVED **
39 * * **
40 * ***********************************************************************
41 *
42 */
43
44 #include <ql_apps.h>
45 #include <ql_api.h>
46 #include <ql_debug.h>
47 #include <ql_init.h>
48 #include <ql_ioctl.h>
49 #include <ql_mbx.h>
50 #include <ql_xioctl.h>
51
52 /*
53 * Local Function Prototypes.
54 */
55 static int ql_busy_notification(ql_adapter_state_t *);
56 static int ql_idle_notification(ql_adapter_state_t *);
57 static int ql_get_feature_bits(ql_adapter_state_t *ha, uint16_t *features);
58 static int ql_set_feature_bits(ql_adapter_state_t *ha, uint16_t features);
59 static int ql_set_nvram_adapter_defaults(ql_adapter_state_t *ha);
60 static void ql_load_nvram(ql_adapter_state_t *ha, uint8_t addr,
61 uint16_t value);
62 static int ql_24xx_load_nvram(ql_adapter_state_t *, uint32_t, uint32_t);
63 static int ql_adm_op(ql_adapter_state_t *, void *, int);
64 static int ql_adm_adapter_info(ql_adapter_state_t *, ql_adm_op_t *, int);
65 static int ql_adm_extended_logging(ql_adapter_state_t *, ql_adm_op_t *);
66 static int ql_adm_device_list(ql_adapter_state_t *, ql_adm_op_t *, int);
67 static int ql_adm_update_properties(ql_adapter_state_t *);
68 static int ql_adm_prop_update_int(ql_adapter_state_t *, ql_adm_op_t *, int);
69 static int ql_adm_loop_reset(ql_adapter_state_t *);
70 static int ql_adm_fw_dump(ql_adapter_state_t *, ql_adm_op_t *, void *, int);
71 static int ql_adm_nvram_dump(ql_adapter_state_t *, ql_adm_op_t *, int);
72 static int ql_adm_nvram_load(ql_adapter_state_t *, ql_adm_op_t *, int);
73 static int ql_adm_flash_load(ql_adapter_state_t *, ql_adm_op_t *, int);
74 static int ql_adm_vpd_dump(ql_adapter_state_t *, ql_adm_op_t *, int);
75 static int ql_adm_vpd_load(ql_adapter_state_t *, ql_adm_op_t *, int);
76 static int ql_adm_vpd_gettag(ql_adapter_state_t *, ql_adm_op_t *, int);
77 static int ql_adm_updfwmodule(ql_adapter_state_t *, ql_adm_op_t *, int);
78 static uint8_t *ql_vpd_findtag(ql_adapter_state_t *, uint8_t *, int8_t *);
79
80 /* ************************************************************************ */
81 /* cb_ops functions */
82 /* ************************************************************************ */
83
84 /*
85 * ql_open
86 * opens device
87 *
88 * Input:
89 * dev_p = device pointer
90 * flags = open flags
91 * otype = open type
92 * cred_p = credentials pointer
93 *
94 * Returns:
95 * 0 = success
96 *
97 * Context:
98 * Kernel context.
99 */
100 /* ARGSUSED */
101 int
102 ql_open(dev_t *dev_p, int flags, int otyp, cred_t *cred_p)
103 {
104 ql_adapter_state_t *ha;
105 int rval = 0;
106
107 ha = ddi_get_soft_state(ql_state, (int32_t)getminor(*dev_p));
108 if (ha == NULL) {
109 QL_PRINT_2(CE_CONT, "failed, no adapter\n");
110 return (ENXIO);
111 }
112
113 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
114
115 /* Allow only character opens */
116 if (otyp != OTYP_CHR) {
117 QL_PRINT_2(CE_CONT, "(%d): failed, open type\n",
118 ha->instance);
119 return (EINVAL);
120 }
121
122 ADAPTER_STATE_LOCK(ha);
123 if (flags & FEXCL && ha->flags & QL_OPENED) {
124 ADAPTER_STATE_UNLOCK(ha);
125 rval = EBUSY;
126 } else {
127 ha->flags |= QL_OPENED;
128 ADAPTER_STATE_UNLOCK(ha);
129 }
130
131 if (rval != 0) {
132 EL(ha, "failed, rval = %xh\n", rval);
133 } else {
134 /*EMPTY*/
135 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
136 }
137 return (rval);
138 }
139
140 /*
141 * ql_close
142 * opens device
143 *
144 * Input:
145 * dev_p = device pointer
146 * flags = open flags
147 * otype = open type
148 * cred_p = credentials pointer
149 *
150 * Returns:
151 * 0 = success
152 *
153 * Context:
154 * Kernel context.
155 */
156 /* ARGSUSED */
157 int
158 ql_close(dev_t dev, int flags, int otyp, cred_t *cred_p)
159 {
160 ql_adapter_state_t *ha;
161 int rval = 0;
162
163 ha = ddi_get_soft_state(ql_state, (int32_t)getminor(dev));
164 if (ha == NULL) {
165 QL_PRINT_2(CE_CONT, "failed, no adapter\n");
166 return (ENXIO);
167 }
168
169 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
170
171 if (otyp != OTYP_CHR) {
172 QL_PRINT_2(CE_CONT, "(%d): failed, open type\n",
173 ha->instance);
174 return (EINVAL);
175 }
176
177 ADAPTER_STATE_LOCK(ha);
178 ha->flags &= ~QL_OPENED;
179 ADAPTER_STATE_UNLOCK(ha);
180
181 if (rval != 0) {
182 EL(ha, "failed, rval = %xh\n", rval);
183 } else {
184 /*EMPTY*/
185 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
186 }
187 return (rval);
188 }
189
190 /*
191 * ql_ioctl
192 * control a character device
193 *
194 * Input:
195 * dev = device number
196 * cmd = function to perform
197 * arg = data type varies with request
198 * mode = flags
199 * cred_p = credentials pointer
200 * rval_p = pointer to result value
201 *
202 * Returns:
203 * 0 = success
204 *
205 * Context:
206 * Kernel context.
207 */
208 /* ARGSUSED */
209 int
210 ql_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p,
211 int *rval_p)
212 {
213 ql_adapter_state_t *ha;
214 int rval = 0;
215
216 if (ddi_in_panic()) {
217 QL_PRINT_2(CE_CONT, "ql_ioctl: ddi_in_panic exit\n");
218 return (ENOPROTOOPT);
219 }
220
221 ha = ddi_get_soft_state(ql_state, (int32_t)getminor(dev));
222 if (ha == NULL) {
223 QL_PRINT_2(CE_CONT, "failed, no adapter\n");
224 return (ENXIO);
225 }
226
227 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
228
229 /*
230 * Quick clean exit for qla2x00 foapi calls which are
231 * not supported in qlc.
232 */
233 if (cmd >= QL_FOAPI_START && cmd <= QL_FOAPI_END) {
234 QL_PRINT_9(CE_CONT, "failed, fo api not supported\n");
235 return (ENOTTY);
236 }
237
238 /* PWR management busy. */
239 rval = ql_busy_notification(ha);
240 if (rval != FC_SUCCESS) {
241 EL(ha, "failed, ql_busy_notification\n");
242 return (ENXIO);
243 }
244
245 rval = ql_xioctl(ha, cmd, arg, mode, cred_p, rval_p);
246 if (rval == ENOPROTOOPT || rval == EINVAL) {
247 switch (cmd) {
248 case QL_GET_ADAPTER_FEATURE_BITS: {
249 uint16_t bits;
250
251 rval = ql_get_feature_bits(ha, &bits);
252
253 if (!rval && ddi_copyout((void *)&bits, (void *)arg,
254 sizeof (bits), mode)) {
255 rval = EFAULT;
256 }
257 break;
258 }
259
260 case QL_SET_ADAPTER_FEATURE_BITS: {
261 uint16_t bits;
262
263 if (ddi_copyin((void *)arg, (void *)&bits,
264 sizeof (bits), mode)) {
265 rval = EFAULT;
266 break;
267 }
268
269 rval = ql_set_feature_bits(ha, bits);
270 break;
271 }
272
273 case QL_SET_ADAPTER_NVRAM_DEFAULTS:
274 rval = ql_set_nvram_adapter_defaults(ha);
275 break;
276
277 case QL_UTIL_LOAD:
278 rval = ql_nv_util_load(ha, (void *)arg, mode);
279 break;
280
281 case QL_UTIL_DUMP:
282 rval = ql_nv_util_dump(ha, (void *)arg, mode);
283 break;
284
285 case QL_ADM_OP:
286 rval = ql_adm_op(ha, (void *)arg, mode);
287 break;
288
289 default:
290 EL(ha, "unknown command = %d\n", cmd);
291 rval = ENOTTY;
292 break;
293 }
294 }
295
296 /* PWR management idle. */
297 (void) ql_idle_notification(ha);
298
299 if (rval != 0) {
300 /*
301 * Don't show failures caused by pps polling for
302 * non-existant virtual ports.
303 */
304 if (cmd != EXT_CC_VPORT_CMD) {
305 EL(ha, "failed, cmd=%d rval=%d\n", cmd, rval);
306 }
307 } else {
308 /*EMPTY*/
309 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
310 }
311 return (rval);
312 }
313
314 /*
315 * ql_busy_notification
316 * Adapter busy notification.
317 *
318 * Input:
319 * ha = adapter state pointer.
320 *
321 * Returns:
322 * FC_SUCCESS
323 * FC_FAILURE
324 *
325 * Context:
326 * Kernel context.
327 */
328 static int
329 ql_busy_notification(ql_adapter_state_t *ha)
330 {
331 if (!ha->pm_capable) {
332 return (FC_SUCCESS);
333 }
334
335 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
336
337 QL_PM_LOCK(ha);
338 ha->busy++;
339 QL_PM_UNLOCK(ha);
340
341 if (pm_busy_component(ha->dip, 0) != DDI_SUCCESS) {
342 QL_PM_LOCK(ha);
343 ha->busy--;
344 QL_PM_UNLOCK(ha);
345
346 EL(ha, "pm_busy_component failed = %xh\n", FC_FAILURE);
347 return (FC_FAILURE);
348 }
349
350 QL_PM_LOCK(ha);
351 if (ha->power_level != PM_LEVEL_D0) {
352 QL_PM_UNLOCK(ha);
353 if (pm_raise_power(ha->dip, 0, 1) != DDI_SUCCESS) {
354 QL_PM_LOCK(ha);
355 ha->busy--;
356 QL_PM_UNLOCK(ha);
357 return (FC_FAILURE);
358 }
359 } else {
360 QL_PM_UNLOCK(ha);
361 }
362
363 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
364
365 return (FC_SUCCESS);
366 }
367
368 /*
369 * ql_idle_notification
370 * Adapter idle notification.
371 *
372 * Input:
373 * ha = adapter state pointer.
374 *
375 * Returns:
376 * FC_SUCCESS
377 * FC_FAILURE
378 *
379 * Context:
380 * Kernel context.
381 */
382 static int
383 ql_idle_notification(ql_adapter_state_t *ha)
384 {
385 if (!ha->pm_capable) {
386 return (FC_SUCCESS);
387 }
388
389 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
390
391 if (pm_idle_component(ha->dip, 0) != DDI_SUCCESS) {
392 EL(ha, "pm_idle_component failed = %xh\n", FC_FAILURE);
393 return (FC_FAILURE);
394 }
395
396 QL_PM_LOCK(ha);
397 ha->busy--;
398 QL_PM_UNLOCK(ha);
399
400 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
401
402 return (FC_SUCCESS);
403 }
404
405 /*
406 * Get adapter feature bits from NVRAM
407 */
408 static int
409 ql_get_feature_bits(ql_adapter_state_t *ha, uint16_t *features)
410 {
411 int count;
412 volatile uint16_t data;
413 uint32_t nv_cmd;
414 uint32_t start_addr;
415 int rval;
416 uint32_t offset = offsetof(nvram_t, adapter_features);
417
418 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
419
420 if (CFG_IST(ha, CFG_CTRL_24258081)) {
421 EL(ha, "Not supported for 24xx\n");
422 return (EINVAL);
423 }
424
425 /*
426 * The offset can't be greater than max of 8 bits and
427 * the following code breaks if the offset isn't at
428 * 2 byte boundary.
429 */
430 rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
431 if (rval != QL_SUCCESS) {
432 EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
433 return (EIO);
434 }
435
436 /*
437 * Have the most significant 3 bits represent the read operation
438 * followed by the 8 bits representing the offset at which we
439 * are going to perform the read operation
440 */
441 offset >>= 1;
442 offset += start_addr;
443 nv_cmd = (offset << 16) | NV_READ_OP;
444 nv_cmd <<= 5;
445
446 /*
447 * Select the chip and feed the command and address
448 */
449 for (count = 0; count < 11; count++) {
450 if (nv_cmd & BIT_31) {
451 ql_nv_write(ha, NV_DATA_OUT);
452 } else {
453 ql_nv_write(ha, 0);
454 }
455 nv_cmd <<= 1;
456 }
457
458 *features = 0;
459 for (count = 0; count < 16; count++) {
460 WRT16_IO_REG(ha, nvram, NV_SELECT | NV_CLOCK);
461 ql_nv_delay();
462
463 data = RD16_IO_REG(ha, nvram);
464 *features <<= 1;
465 if (data & NV_DATA_IN) {
466 *features = (uint16_t)(*features | 0x1);
467 }
468
469 WRT16_IO_REG(ha, nvram, NV_SELECT);
470 ql_nv_delay();
471 }
472
473 /*
474 * Deselect the chip
475 */
476 WRT16_IO_REG(ha, nvram, NV_DESELECT);
477
478 ql_release_nvram(ha);
479
480 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
481
482 return (0);
483 }
484
485 /*
486 * Set adapter feature bits in NVRAM
487 */
488 static int
489 ql_set_feature_bits(ql_adapter_state_t *ha, uint16_t features)
490 {
491 int rval;
492 uint32_t count;
493 nvram_t *nv;
494 uint16_t *wptr;
495 uint8_t *bptr;
496 uint8_t csum;
497 uint32_t start_addr;
498
499 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
500
501 if (CFG_IST(ha, CFG_CTRL_24258081)) {
502 EL(ha, "Not supported for 24xx\n");
503 return (EINVAL);
504 }
505
506 nv = kmem_zalloc(sizeof (*nv), KM_SLEEP);
507
508 rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
509 if (rval != QL_SUCCESS) {
510 EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
511 kmem_free(nv, sizeof (*nv));
512 return (EIO);
513 }
514 rval = 0;
515
516 /*
517 * Read off the whole NVRAM
518 */
519 wptr = (uint16_t *)nv;
520 csum = 0;
521 for (count = 0; count < sizeof (nvram_t) / 2; count++) {
522 *wptr = (uint16_t)ql_get_nvram_word(ha, count + start_addr);
523 csum = (uint8_t)(csum + (uint8_t)*wptr);
524 csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8));
525 wptr++;
526 }
527
528 /*
529 * If the checksum is BAD then fail it right here.
530 */
531 if (csum) {
532 kmem_free(nv, sizeof (*nv));
533 ql_release_nvram(ha);
534 return (EBADF);
535 }
536
537 nv->adapter_features[0] = (uint8_t)((features & 0xFF00) >> 8);
538 nv->adapter_features[1] = (uint8_t)(features & 0xFF);
539
540 /*
541 * Recompute the chesksum now
542 */
543 bptr = (uint8_t *)nv;
544 for (count = 0; count < sizeof (nvram_t) - 1; count++) {
545 csum = (uint8_t)(csum + *bptr++);
546 }
547 csum = (uint8_t)(~csum + 1);
548 nv->checksum = csum;
549
550 /*
551 * Now load the NVRAM
552 */
553 wptr = (uint16_t *)nv;
554 for (count = 0; count < sizeof (nvram_t) / 2; count++) {
555 ql_load_nvram(ha, (uint8_t)(count + start_addr), *wptr++);
556 }
557
558 /*
559 * Read NVRAM and verify the contents
560 */
561 wptr = (uint16_t *)nv;
562 csum = 0;
563 for (count = 0; count < sizeof (nvram_t) / 2; count++) {
564 if (ql_get_nvram_word(ha, count + start_addr) != *wptr) {
565 rval = EIO;
566 break;
567 }
568 csum = (uint8_t)(csum + (uint8_t)*wptr);
569 csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8));
570 wptr++;
571 }
572
573 if (csum) {
574 rval = EINVAL;
575 }
576
577 kmem_free(nv, sizeof (*nv));
578 ql_release_nvram(ha);
579
580 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
581
582 return (rval);
583 }
584
585 /*
586 * Fix this function to update just feature bits and checksum in NVRAM
587 */
588 static int
589 ql_set_nvram_adapter_defaults(ql_adapter_state_t *ha)
590 {
591 int rval;
592 uint32_t count;
593 uint32_t start_addr;
594
595 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
596
597 rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
598 if (rval != QL_SUCCESS) {
599 EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
600 return (EIO);
601 }
602 rval = 0;
603
604 if (CFG_IST(ha, CFG_CTRL_24258081)) {
605 nvram_24xx_t *nv;
606 uint32_t *longptr;
607 uint32_t csum = 0;
608
609 nv = kmem_zalloc(sizeof (*nv), KM_SLEEP);
610
611 nv->nvram_version[0] = LSB(ICB_24XX_VERSION);
612 nv->nvram_version[1] = MSB(ICB_24XX_VERSION);
613
614 nv->version[0] = 1;
615 nv->max_frame_length[1] = 8;
616 nv->execution_throttle[0] = 16;
617 nv->login_retry_count[0] = 8;
618
619 nv->firmware_options_1[0] = BIT_2 | BIT_1;
620 nv->firmware_options_1[1] = BIT_5;
621 nv->firmware_options_2[0] = BIT_5;
622 nv->firmware_options_2[1] = BIT_4;
623 nv->firmware_options_3[1] = BIT_6;
624
625 /*
626 * Set default host adapter parameters
627 */
628 nv->host_p[0] = BIT_4 | BIT_1;
629 nv->host_p[1] = BIT_3 | BIT_2;
630 nv->reset_delay = 5;
631 nv->max_luns_per_target[0] = 128;
632 nv->port_down_retry_count[0] = 30;
633 nv->link_down_timeout[0] = 30;
634
635 /*
636 * compute the chesksum now
637 */
638 longptr = (uint32_t *)nv;
639 csum = 0;
640 for (count = 0; count < (sizeof (nvram_24xx_t)/4)-1; count++) {
641 csum += *longptr;
642 longptr++;
643 }
644 csum = (uint32_t)(~csum + 1);
645 LITTLE_ENDIAN_32((long)csum);
646 *longptr = csum;
647
648 /*
649 * Now load the NVRAM
650 */
651 longptr = (uint32_t *)nv;
652 for (count = 0; count < sizeof (nvram_24xx_t) / 4; count++) {
653 (void) ql_24xx_load_nvram(ha,
654 (uint32_t)(count + start_addr), *longptr++);
655 }
656
657 /*
658 * Read NVRAM and verify the contents
659 */
660 csum = 0;
661 longptr = (uint32_t *)nv;
662 for (count = 0; count < sizeof (nvram_24xx_t) / 4; count++) {
663 rval = ql_24xx_read_flash(ha, count + start_addr,
664 longptr);
665 if (rval != QL_SUCCESS) {
666 EL(ha, "24xx_read_flash failed=%xh\n", rval);
667 break;
668 }
669 csum += *longptr;
670 }
671
672 if (csum) {
673 rval = EINVAL;
674 }
675 kmem_free(nv, sizeof (nvram_24xx_t));
676 } else {
677 nvram_t *nv;
678 uint16_t *wptr;
679 uint8_t *bptr;
680 uint8_t csum;
681
682 nv = kmem_zalloc(sizeof (*nv), KM_SLEEP);
683 /*
684 * Set default initialization control block.
685 */
686 nv->parameter_block_version = ICB_VERSION;
687 nv->firmware_options[0] = BIT_4 | BIT_3 | BIT_2 | BIT_1;
688 nv->firmware_options[1] = BIT_7 | BIT_5 | BIT_2;
689
690 nv->max_frame_length[1] = 4;
691 nv->max_iocb_allocation[1] = 1;
692 nv->execution_throttle[0] = 16;
693 nv->login_retry_count = 8;
694 nv->port_name[0] = 33;
695 nv->port_name[3] = 224;
696 nv->port_name[4] = 139;
697 nv->login_timeout = 4;
698
699 /*
700 * Set default host adapter parameters
701 */
702 nv->host_p[0] = BIT_1;
703 nv->host_p[1] = BIT_2;
704 nv->reset_delay = 5;
705 nv->port_down_retry_count = 8;
706 nv->maximum_luns_per_target[0] = 8;
707
708 /*
709 * compute the chesksum now
710 */
711 bptr = (uint8_t *)nv;
712 csum = 0;
713 for (count = 0; count < sizeof (nvram_t) - 1; count++) {
714 csum = (uint8_t)(csum + *bptr++);
715 }
716 csum = (uint8_t)(~csum + 1);
717 nv->checksum = csum;
718
719 /*
720 * Now load the NVRAM
721 */
722 wptr = (uint16_t *)nv;
723 for (count = 0; count < sizeof (nvram_t) / 2; count++) {
724 ql_load_nvram(ha, (uint8_t)(count + start_addr),
725 *wptr++);
726 }
727
728 /*
729 * Read NVRAM and verify the contents
730 */
731 wptr = (uint16_t *)nv;
732 csum = 0;
733 for (count = 0; count < sizeof (nvram_t) / 2; count++) {
734 if (ql_get_nvram_word(ha, count + start_addr) !=
735 *wptr) {
736 rval = EIO;
737 break;
738 }
739 csum = (uint8_t)(csum + (uint8_t)*wptr);
740 csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8));
741 wptr++;
742 }
743 if (csum) {
744 rval = EINVAL;
745 }
746 kmem_free(nv, sizeof (*nv));
747 }
748 ql_release_nvram(ha);
749
750 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
751
752 return (rval);
753 }
754
755 static void
756 ql_load_nvram(ql_adapter_state_t *ha, uint8_t addr, uint16_t value)
757 {
758 int count;
759 volatile uint16_t word;
760 volatile uint32_t nv_cmd;
761
762 ql_nv_write(ha, NV_DATA_OUT);
763 ql_nv_write(ha, 0);
764 ql_nv_write(ha, 0);
765
766 for (word = 0; word < 8; word++) {
767 ql_nv_write(ha, NV_DATA_OUT);
768 }
769
770 /*
771 * Deselect the chip
772 */
773 WRT16_IO_REG(ha, nvram, NV_DESELECT);
774 ql_nv_delay();
775
776 /*
777 * Erase Location
778 */
779 nv_cmd = (addr << 16) | NV_ERASE_OP;
780 nv_cmd <<= 5;
781 for (count = 0; count < 11; count++) {
782 if (nv_cmd & BIT_31) {
783 ql_nv_write(ha, NV_DATA_OUT);
784 } else {
785 ql_nv_write(ha, 0);
786 }
787 nv_cmd <<= 1;
788 }
789
790 /*
791 * Wait for Erase to Finish
792 */
793 WRT16_IO_REG(ha, nvram, NV_DESELECT);
794 ql_nv_delay();
795 WRT16_IO_REG(ha, nvram, NV_SELECT);
796 word = 0;
797 while ((word & NV_DATA_IN) == 0) {
798 ql_nv_delay();
799 word = RD16_IO_REG(ha, nvram);
800 }
801 WRT16_IO_REG(ha, nvram, NV_DESELECT);
802 ql_nv_delay();
803
804 /*
805 * Write data now
806 */
807 nv_cmd = (addr << 16) | NV_WRITE_OP;
808 nv_cmd |= value;
809 nv_cmd <<= 5;
810 for (count = 0; count < 27; count++) {
811 if (nv_cmd & BIT_31) {
812 ql_nv_write(ha, NV_DATA_OUT);
813 } else {
814 ql_nv_write(ha, 0);
815 }
816 nv_cmd <<= 1;
817 }
818
819 /*
820 * Wait for NVRAM to become ready
821 */
822 WRT16_IO_REG(ha, nvram, NV_DESELECT);
823 ql_nv_delay();
824 WRT16_IO_REG(ha, nvram, NV_SELECT);
825 word = 0;
826 while ((word & NV_DATA_IN) == 0) {
827 ql_nv_delay();
828 word = RD16_IO_REG(ha, nvram);
829 }
830 WRT16_IO_REG(ha, nvram, NV_DESELECT);
831 ql_nv_delay();
832
833 /*
834 * Disable writes
835 */
836 ql_nv_write(ha, NV_DATA_OUT);
837 for (count = 0; count < 10; count++) {
838 ql_nv_write(ha, 0);
839 }
840
841 /*
842 * Deselect the chip now
843 */
844 WRT16_IO_REG(ha, nvram, NV_DESELECT);
845 }
846
847 /*
848 * ql_24xx_load_nvram
849 * Enable NVRAM and writes a 32bit word to ISP24xx NVRAM.
850 *
851 * Input:
852 * ha: adapter state pointer.
853 * addr: NVRAM address.
854 * value: data.
855 *
856 * Returns:
857 * ql local function return status code.
858 *
859 * Context:
860 * Kernel context.
861 */
862 static int
863 ql_24xx_load_nvram(ql_adapter_state_t *ha, uint32_t addr, uint32_t value)
864 {
865 int rval;
866
867 /* Enable flash write. */
868 if (!(CFG_IST(ha, CFG_CTRL_8081))) {
869 WRT32_IO_REG(ha, ctrl_status,
870 RD32_IO_REG(ha, ctrl_status) | ISP_FLASH_ENABLE);
871 RD32_IO_REG(ha, ctrl_status); /* PCI Posting. */
872 }
873
874 /* Disable NVRAM write-protection. */
875 if (CFG_IST(ha, CFG_CTRL_2422)) {
876 (void) ql_24xx_write_flash(ha, NVRAM_CONF_ADDR | 0x101, 0);
877 } else {
878 if ((rval = ql_24xx_unprotect_flash(ha)) != QL_SUCCESS) {
879 EL(ha, "unprotect_flash failed, rval=%xh\n", rval);
880 return (rval);
881 }
882 }
883
884 /* Write to flash. */
885 rval = ql_24xx_write_flash(ha, addr, value);
886
887 /* Enable NVRAM write-protection. */
888 if (CFG_IST(ha, CFG_CTRL_2422)) {
889 /* TODO: Check if 0x8c is correct -- sb: 0x9c ? */
890 (void) ql_24xx_write_flash(ha, NVRAM_CONF_ADDR | 0x101, 0x8c);
891 } else {
892 ql_24xx_protect_flash(ha);
893 }
894
895 /* Disable flash write. */
896 if (!(CFG_IST(ha, CFG_CTRL_81XX))) {
897 WRT32_IO_REG(ha, ctrl_status,
898 RD32_IO_REG(ha, ctrl_status) & ~ISP_FLASH_ENABLE);
899 RD32_IO_REG(ha, ctrl_status); /* PCI Posting. */
900 }
901
902 return (rval);
903 }
904
905 /*
906 * ql_nv_util_load
907 * Loads NVRAM from application.
908 *
909 * Input:
910 * ha = adapter state pointer.
911 * bp = user buffer address.
912 *
913 * Returns:
914 *
915 * Context:
916 * Kernel context.
917 */
918 int
919 ql_nv_util_load(ql_adapter_state_t *ha, void *bp, int mode)
920 {
921 uint8_t cnt;
922 void *nv;
923 uint16_t *wptr;
924 uint16_t data;
925 uint32_t start_addr, *lptr, data32;
926 nvram_t *nptr;
927 int rval;
928
929 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
930
931 nv = kmem_zalloc(ha->nvram_cache->size, KM_SLEEP);
932
933 if (ddi_copyin(bp, nv, ha->nvram_cache->size, mode) != 0) {
934 EL(ha, "Buffer copy failed\n");
935 kmem_free(nv, ha->nvram_cache->size);
936 return (EFAULT);
937 }
938
939 /* See if the buffer passed to us looks sane */
940 nptr = (nvram_t *)nv;
941 if (nptr->id[0] != 'I' || nptr->id[1] != 'S' || nptr->id[2] != 'P' ||
942 nptr->id[3] != ' ') {
943 EL(ha, "failed, buffer sanity check\n");
944 kmem_free(nv, ha->nvram_cache->size);
945 return (EINVAL);
946 }
947
948 /* Quiesce I/O */
949 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
950 EL(ha, "ql_stall_driver failed\n");
951 kmem_free(nv, ha->nvram_cache->size);
952 return (EBUSY);
953 }
954
955 rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
956 if (rval != QL_SUCCESS) {
957 EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
958 kmem_free(nv, ha->nvram_cache->size);
959 ql_restart_driver(ha);
960 return (EIO);
961 }
962
963 /* Load NVRAM. */
964 if (CFG_IST(ha, CFG_CTRL_258081)) {
965 GLOBAL_HW_UNLOCK();
966 start_addr &= ~ha->flash_data_addr;
967 start_addr <<= 2;
968 if ((rval = ql_r_m_w_flash(ha, bp, ha->nvram_cache->size,
969 start_addr, mode)) != QL_SUCCESS) {
970 EL(ha, "nvram load failed, rval = %0xh\n", rval);
971 }
972 GLOBAL_HW_LOCK();
973 } else if (CFG_IST(ha, CFG_CTRL_2422)) {
974 lptr = (uint32_t *)nv;
975 for (cnt = 0; cnt < ha->nvram_cache->size / 4; cnt++) {
976 data32 = *lptr++;
977 LITTLE_ENDIAN_32(&data32);
978 rval = ql_24xx_load_nvram(ha, cnt + start_addr,
979 data32);
980 if (rval != QL_SUCCESS) {
981 EL(ha, "failed, 24xx_load_nvram=%xh\n", rval);
982 break;
983 }
984 }
985 } else {
986 wptr = (uint16_t *)nv;
987 for (cnt = 0; cnt < ha->nvram_cache->size / 2; cnt++) {
988 data = *wptr++;
989 LITTLE_ENDIAN_16(&data);
990 ql_load_nvram(ha, (uint8_t)(cnt + start_addr), data);
991 }
992 }
993 /* switch to the new one */
994 NVRAM_CACHE_LOCK(ha);
995
996 kmem_free(ha->nvram_cache->cache, ha->nvram_cache->size);
997 ha->nvram_cache->cache = (void *)nptr;
998
999 NVRAM_CACHE_UNLOCK(ha);
1000
1001 ql_release_nvram(ha);
1002 ql_restart_driver(ha);
1003
1004 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1005
1006 if (rval == QL_SUCCESS) {
1007 return (0);
1008 }
1009
1010 return (EFAULT);
1011 }
1012
1013 /*
1014 * ql_nv_util_dump
1015 * Dumps NVRAM to application.
1016 *
1017 * Input:
1018 * ha = adapter state pointer.
1019 * bp = user buffer address.
1020 *
1021 * Returns:
1022 *
1023 * Context:
1024 * Kernel context.
1025 */
1026 int
1027 ql_nv_util_dump(ql_adapter_state_t *ha, void *bp, int mode)
1028 {
1029 uint32_t start_addr;
1030 int rval2, rval = 0;
1031
1032 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1033
1034 if (ha->nvram_cache == NULL ||
1035 ha->nvram_cache->size == NULL ||
1036 ha->nvram_cache->cache == NULL) {
1037 EL(ha, "failed, kmem_zalloc\n");
1038 return (ENOMEM);
1039 } else if (ha->nvram_cache->valid != 1) {
1040
1041 /* Quiesce I/O */
1042 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1043 EL(ha, "ql_stall_driver failed\n");
1044 return (EBUSY);
1045 }
1046
1047 rval2 = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
1048 if (rval2 != QL_SUCCESS) {
1049 EL(ha, "failed, ql_lock_nvram=%xh\n", rval2);
1050 ql_restart_driver(ha);
1051 return (EIO);
1052 }
1053 NVRAM_CACHE_LOCK(ha);
1054
1055 rval2 = ql_get_nvram(ha, ha->nvram_cache->cache,
1056 start_addr, ha->nvram_cache->size);
1057 if (rval2 != QL_SUCCESS) {
1058 rval = rval2;
1059 } else {
1060 ha->nvram_cache->valid = 1;
1061 EL(ha, "nvram cache now valid.");
1062 }
1063
1064 NVRAM_CACHE_UNLOCK(ha);
1065
1066 ql_release_nvram(ha);
1067 ql_restart_driver(ha);
1068
1069 if (rval != 0) {
1070 EL(ha, "failed to dump nvram, rval=%x\n", rval);
1071 return (rval);
1072 }
1073 }
1074
1075 if (ddi_copyout(ha->nvram_cache->cache, bp,
1076 ha->nvram_cache->size, mode) != 0) {
1077 EL(ha, "Buffer copy failed\n");
1078 return (EFAULT);
1079 }
1080
1081 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1082
1083 return (0);
1084 }
1085
1086 int
1087 ql_get_nvram(ql_adapter_state_t *ha, void *dest_addr, uint32_t src_addr,
1088 uint32_t size)
1089 {
1090 int rval = QL_SUCCESS;
1091 int cnt;
1092 /* Dump NVRAM. */
1093 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1094 uint32_t *lptr = (uint32_t *)dest_addr;
1095
1096 for (cnt = 0; cnt < size / 4; cnt++) {
1097 rval = ql_24xx_read_flash(ha, src_addr++, lptr);
1098 if (rval != QL_SUCCESS) {
1099 EL(ha, "read_flash failed=%xh\n", rval);
1100 rval = EAGAIN;
1101 break;
1102 }
1103 LITTLE_ENDIAN_32(lptr);
1104 lptr++;
1105 }
1106 } else {
1107 uint16_t data;
1108 uint16_t *wptr = (uint16_t *)dest_addr;
1109
1110 for (cnt = 0; cnt < size / 2; cnt++) {
1111 data = (uint16_t)ql_get_nvram_word(ha, cnt +
1112 src_addr);
1113 LITTLE_ENDIAN_16(&data);
1114 *wptr++ = data;
1115 }
1116 }
1117 return (rval);
1118 }
1119
1120 /*
1121 * ql_vpd_load
1122 * Loads VPD from application.
1123 *
1124 * Input:
1125 * ha = adapter state pointer.
1126 * bp = user buffer address.
1127 *
1128 * Returns:
1129 *
1130 * Context:
1131 * Kernel context.
1132 */
1133 int
1134 ql_vpd_load(ql_adapter_state_t *ha, void *bp, int mode)
1135 {
1136 uint8_t cnt;
1137 uint8_t *vpd, *vpdptr, *vbuf;
1138 uint32_t start_addr, vpd_size, *lptr, data32;
1139 int rval;
1140
1141 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1142
1143 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
1144 EL(ha, "unsupported adapter feature\n");
1145 return (ENOTSUP);
1146 }
1147
1148 vpd_size = QL_24XX_VPD_SIZE;
1149
1150 vpd = kmem_zalloc(vpd_size, KM_SLEEP);
1151
1152 if (ddi_copyin(bp, vpd, vpd_size, mode) != 0) {
1153 EL(ha, "Buffer copy failed\n");
1154 kmem_free(vpd, vpd_size);
1155 return (EFAULT);
1156 }
1157
1158 /* Sanity check the user supplied data via checksum */
1159 if ((vpdptr = ql_vpd_findtag(ha, vpd, "RV")) == NULL) {
1160 EL(ha, "vpd RV tag missing\n");
1161 kmem_free(vpd, vpd_size);
1162 return (EINVAL);
1163 }
1164
1165 vpdptr += 3;
1166 cnt = 0;
1167 vbuf = vpd;
1168 while (vbuf <= vpdptr) {
1169 cnt += *vbuf++;
1170 }
1171 if (cnt != 0) {
1172 EL(ha, "mismatched checksum, cal=%xh, passed=%xh\n",
1173 (uint8_t)cnt, (uintptr_t)vpdptr);
1174 kmem_free(vpd, vpd_size);
1175 return (EINVAL);
1176 }
1177
1178 /* Quiesce I/O */
1179 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1180 EL(ha, "ql_stall_driver failed\n");
1181 kmem_free(vpd, vpd_size);
1182 return (EBUSY);
1183 }
1184
1185 rval = ql_lock_nvram(ha, &start_addr, LNF_VPD_DATA);
1186 if (rval != QL_SUCCESS) {
1187 EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
1188 kmem_free(vpd, vpd_size);
1189 ql_restart_driver(ha);
1190 return (EIO);
1191 }
1192
1193 /* Load VPD. */
1194 if (CFG_IST(ha, CFG_CTRL_258081)) {
1195 GLOBAL_HW_UNLOCK();
1196 start_addr &= ~ha->flash_data_addr;
1197 start_addr <<= 2;
1198 if ((rval = ql_r_m_w_flash(ha, bp, vpd_size, start_addr,
1199 mode)) != QL_SUCCESS) {
1200 EL(ha, "vpd load error: %xh\n", rval);
1201 }
1202 GLOBAL_HW_LOCK();
1203 } else {
1204 lptr = (uint32_t *)vpd;
1205 for (cnt = 0; cnt < vpd_size / 4; cnt++) {
1206 data32 = *lptr++;
1207 LITTLE_ENDIAN_32(&data32);
1208 rval = ql_24xx_load_nvram(ha, cnt + start_addr,
1209 data32);
1210 if (rval != QL_SUCCESS) {
1211 EL(ha, "failed, 24xx_load_nvram=%xh\n", rval);
1212 break;
1213 }
1214 }
1215 }
1216
1217 kmem_free(vpd, vpd_size);
1218
1219 /* Update the vcache */
1220 CACHE_LOCK(ha);
1221
1222 if (rval != QL_SUCCESS) {
1223 EL(ha, "failed, load\n");
1224 } else if ((ha->vcache == NULL) && ((ha->vcache =
1225 kmem_zalloc(vpd_size, KM_SLEEP)) == NULL)) {
1226 EL(ha, "failed, kmem_zalloc2\n");
1227 } else if (ddi_copyin(bp, ha->vcache, vpd_size, mode) != 0) {
1228 EL(ha, "Buffer copy2 failed\n");
1229 kmem_free(ha->vcache, vpd_size);
1230 ha->vcache = NULL;
1231 }
1232
1233 CACHE_UNLOCK(ha);
1234
1235 ql_release_nvram(ha);
1236 ql_restart_driver(ha);
1237
1238 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1239
1240 if (rval == QL_SUCCESS) {
1241 return (0);
1242 }
1243
1244 return (EFAULT);
1245 }
1246
1247 /*
1248 * ql_vpd_dump
1249 * Dumps VPD to application buffer.
1250 *
1251 * Input:
1252 * ha = adapter state pointer.
1253 * bp = user buffer address.
1254 *
1255 * Returns:
1256 *
1257 * Context:
1258 * Kernel context.
1259 */
1260 int
1261 ql_vpd_dump(ql_adapter_state_t *ha, void *bp, int mode)
1262 {
1263 uint8_t cnt;
1264 void *vpd;
1265 uint32_t start_addr, vpd_size, *lptr;
1266 int rval = 0;
1267
1268 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1269
1270 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
1271 EL(ha, "unsupported adapter feature\n");
1272 return (EACCES);
1273 }
1274
1275 vpd_size = QL_24XX_VPD_SIZE;
1276
1277 CACHE_LOCK(ha);
1278
1279 if (ha->vcache != NULL) {
1280 /* copy back the vpd cache data */
1281 if (ddi_copyout(ha->vcache, bp, vpd_size, mode) != 0) {
1282 EL(ha, "Buffer copy failed\n");
1283 rval = EFAULT;
1284 }
1285 CACHE_UNLOCK(ha);
1286 return (rval);
1287 }
1288
1289 vpd = kmem_zalloc(vpd_size, KM_SLEEP);
1290
1291 /* Quiesce I/O */
1292 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1293 CACHE_UNLOCK(ha);
1294 EL(ha, "ql_stall_driver failed\n");
1295 kmem_free(vpd, vpd_size);
1296 return (EBUSY);
1297 }
1298
1299 rval = ql_lock_nvram(ha, &start_addr, LNF_VPD_DATA);
1300 if (rval != QL_SUCCESS) {
1301 CACHE_UNLOCK(ha);
1302 EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
1303 kmem_free(vpd, vpd_size);
1304 ql_restart_driver(ha);
1305 return (EIO);
1306 }
1307
1308 /* Dump VPD. */
1309 lptr = (uint32_t *)vpd;
1310
1311 for (cnt = 0; cnt < vpd_size / 4; cnt++) {
1312 rval = ql_24xx_read_flash(ha, start_addr++, lptr);
1313 if (rval != QL_SUCCESS) {
1314 EL(ha, "read_flash failed=%xh\n", rval);
1315 rval = EAGAIN;
1316 break;
1317 }
1318 LITTLE_ENDIAN_32(lptr);
1319 lptr++;
1320 }
1321
1322 ql_release_nvram(ha);
1323 ql_restart_driver(ha);
1324
1325 if (ddi_copyout(vpd, bp, vpd_size, mode) != 0) {
1326 CACHE_UNLOCK(ha);
1327 EL(ha, "Buffer copy failed\n");
1328 kmem_free(vpd, vpd_size);
1329 return (EFAULT);
1330 }
1331
1332 ha->vcache = vpd;
1333
1334 CACHE_UNLOCK(ha);
1335
1336 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1337
1338 if (rval != QL_SUCCESS) {
1339 return (EFAULT);
1340 } else {
1341 return (0);
1342 }
1343 }
1344
1345 /*
1346 * ql_vpd_findtag
1347 * Search the passed vpd buffer for the requested VPD tag type.
1348 *
1349 * Input:
1350 * ha = adapter state pointer.
1351 * vpdbuf = Pointer to start of the buffer to search
1352 * op = VPD opcode to find (must be NULL terminated).
1353 *
1354 * Returns:
1355 * Pointer to the opcode in the buffer if opcode found.
1356 * NULL if opcode is not found.
1357 *
1358 * Context:
1359 * Kernel context.
1360 */
1361 static uint8_t *
1362 ql_vpd_findtag(ql_adapter_state_t *ha, uint8_t *vpdbuf, int8_t *opcode)
1363 {
1364 uint8_t *vpd = vpdbuf;
1365 uint8_t *end = vpdbuf + QL_24XX_VPD_SIZE;
1366 uint32_t found = 0;
1367
1368 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1369
1370 if (vpdbuf == NULL || opcode == NULL) {
1371 EL(ha, "null parameter passed!\n");
1372 return (NULL);
1373 }
1374
1375 while (vpd < end) {
1376
1377 /* check for end of vpd */
1378 if (vpd[0] == VPD_TAG_END) {
1379 if (opcode[0] == VPD_TAG_END) {
1380 found = 1;
1381 } else {
1382 found = 0;
1383 }
1384 break;
1385 }
1386
1387 /* check opcode */
1388 if (bcmp(opcode, vpd, strlen(opcode)) == 0) {
1389 /* found opcode requested */
1390 found = 1;
1391 break;
1392 }
1393
1394 /*
1395 * Didn't find the opcode, so calculate start of
1396 * next tag. Depending on the current tag type,
1397 * the length field can be 1 or 2 bytes
1398 */
1399 if (!(strncmp((char *)vpd, (char *)VPD_TAG_PRODID, 1))) {
1400 vpd += (vpd[2] << 8) + vpd[1] + 3;
1401 } else if (*vpd == VPD_TAG_LRT || *vpd == VPD_TAG_LRTC) {
1402 vpd += 3;
1403 } else {
1404 vpd += vpd[2] +3;
1405 }
1406 }
1407
1408 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1409
1410 return (found == 1 ? vpd : NULL);
1411 }
1412
1413 /*
1414 * ql_vpd_lookup
1415 * Return the VPD data for the request VPD tag
1416 *
1417 * Input:
1418 * ha = adapter state pointer.
1419 * opcode = VPD opcode to find (must be NULL terminated).
1420 * bp = Pointer to returned data buffer.
1421 * bplen = Length of returned data buffer.
1422 *
1423 * Returns:
1424 * Length of data copied into returned data buffer.
1425 * >0 = VPD data field (NULL terminated)
1426 * 0 = no data.
1427 * -1 = Could not find opcode in vpd buffer / error.
1428 *
1429 * Context:
1430 * Kernel context.
1431 *
1432 * NB: The opcode buffer and the bp buffer *could* be the same buffer!
1433 *
1434 */
1435 int32_t
1436 ql_vpd_lookup(ql_adapter_state_t *ha, uint8_t *opcode, uint8_t *bp,
1437 int32_t bplen)
1438 {
1439 uint8_t *vpd;
1440 uint8_t *vpdbuf;
1441 int32_t len = -1;
1442
1443 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1444
1445 if (opcode == NULL || bp == NULL || bplen < 1) {
1446 EL(ha, "invalid parameter passed: opcode=%ph, "
1447 "bp=%ph, bplen=%xh\n", opcode, bp, bplen);
1448 return (len);
1449 }
1450
1451 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
1452 return (len);
1453 }
1454
1455 if ((vpdbuf = (uint8_t *)kmem_zalloc(QL_24XX_VPD_SIZE,
1456 KM_SLEEP)) == NULL) {
1457 EL(ha, "unable to allocate vpd memory\n");
1458 return (len);
1459 }
1460
1461 if ((ql_vpd_dump(ha, vpdbuf, (int)FKIOCTL)) != 0) {
1462 kmem_free(vpdbuf, QL_24XX_VPD_SIZE);
1463 EL(ha, "unable to retrieve VPD data\n");
1464 return (len);
1465 }
1466
1467 if ((vpd = ql_vpd_findtag(ha, vpdbuf, (int8_t *)opcode)) != NULL) {
1468 /*
1469 * Found the tag
1470 */
1471 if (*opcode == VPD_TAG_END || *opcode == VPD_TAG_LRT ||
1472 *opcode == VPD_TAG_LRTC) {
1473 /*
1474 * we found it, but the tag doesn't have a data
1475 * field.
1476 */
1477 len = 0;
1478 } else if (!(strncmp((char *)vpd, (char *)
1479 VPD_TAG_PRODID, 1))) {
1480 len = vpd[2] << 8;
1481 len += vpd[1];
1482 } else {
1483 len = vpd[2];
1484 }
1485
1486 /*
1487 * make sure that the vpd len doesn't exceed the
1488 * vpd end
1489 */
1490 if (vpd+len > vpdbuf + QL_24XX_VPD_SIZE) {
1491 EL(ha, "vpd tag len (%xh) exceeds vpd buffer "
1492 "length\n", len);
1493 len = -1;
1494 }
1495 }
1496
1497 if (len >= 0) {
1498 /*
1499 * make sure we don't exceed callers buffer space len
1500 */
1501 if (len > bplen) {
1502 len = bplen-1;
1503 }
1504
1505 /* copy the data back */
1506 (void) strncpy((int8_t *)bp, (int8_t *)(vpd+3), (int64_t)len);
1507 bp[len] = NULL;
1508 } else {
1509 /* error -- couldn't find tag */
1510 bp[0] = NULL;
1511 if (opcode[1] != NULL) {
1512 EL(ha, "unable to find tag '%s'\n", opcode);
1513 } else {
1514 EL(ha, "unable to find tag '%xh'\n", opcode[0]);
1515 }
1516 }
1517
1518 kmem_free(vpdbuf, QL_24XX_VPD_SIZE);
1519
1520 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1521
1522 return (len);
1523 }
1524
1525 /*
1526 * ql_r_m_w_flash
1527 * Read modify write from user space to flash.
1528 *
1529 * Input:
1530 * ha: adapter state pointer.
1531 * dp: source byte pointer.
1532 * bc: byte count.
1533 * faddr: flash byte address.
1534 * mode: flags.
1535 *
1536 * Returns:
1537 * ql local function return status code.
1538 *
1539 * Context:
1540 * Kernel context.
1541 */
1542 int
1543 ql_r_m_w_flash(ql_adapter_state_t *ha, caddr_t dp, uint32_t bc, uint32_t faddr,
1544 int mode)
1545 {
1546 uint8_t *bp;
1547 uint32_t xfer, bsize, saddr, ofst;
1548 int rval = 0;
1549
1550 QL_PRINT_9(CE_CONT, "(%d): started, dp=%ph, faddr=%xh, bc=%xh\n",
1551 ha->instance, (void *)dp, faddr, bc);
1552
1553 bsize = ha->xioctl->fdesc.block_size;
1554 saddr = faddr & ~(bsize - 1);
1555 ofst = faddr & (bsize - 1);
1556
1557 bp = kmem_zalloc(bsize, KM_SLEEP);
1558
1559 while (bc) {
1560 xfer = bc > bsize ? bsize : bc;
1561 if (ofst + xfer > bsize) {
1562 xfer = bsize - ofst;
1563 }
1564 QL_PRINT_9(CE_CONT, "(%d): dp=%ph, saddr=%xh, bc=%xh, "
1565 "ofst=%xh, xfer=%xh\n", ha->instance, (void *)dp, saddr,
1566 bc, ofst, xfer);
1567
1568 if (ofst || xfer < bsize) {
1569 /* Dump Flash sector. */
1570 if ((rval = ql_dump_fcode(ha, bp, bsize, saddr)) !=
1571 QL_SUCCESS) {
1572 EL(ha, "dump_flash status=%x\n", rval);
1573 break;
1574 }
1575 }
1576
1577 /* Set new data. */
1578 if ((rval = ddi_copyin(dp, (caddr_t)(bp + ofst), xfer,
1579 mode)) != 0) {
1580 EL(ha, "ddi_copyin status=%xh, dp=%ph, ofst=%xh, "
1581 "xfer=%xh\n", rval, (void *)dp, ofst, xfer);
1582 rval = QL_FUNCTION_FAILED;
1583 break;
1584 }
1585
1586 /* Write to flash. */
1587 if ((rval = ql_load_fcode(ha, bp, bsize, saddr)) !=
1588 QL_SUCCESS) {
1589 EL(ha, "load_flash status=%x\n", rval);
1590 break;
1591 }
1592 bc -= xfer;
1593 dp += xfer;
1594 saddr += bsize;
1595 ofst = 0;
1596 }
1597
1598 kmem_free(bp, bsize);
1599
1600 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1601
1602 return (rval);
1603 }
1604
1605 /*
1606 * ql_adm_op
1607 * Performs qladm utility operations
1608 *
1609 * Input:
1610 * ha: adapter state pointer.
1611 * arg: driver_op_t structure pointer.
1612 * mode: flags.
1613 *
1614 * Returns:
1615 *
1616 * Context:
1617 * Kernel context.
1618 */
1619 static int
1620 ql_adm_op(ql_adapter_state_t *ha, void *arg, int mode)
1621 {
1622 ql_adm_op_t dop;
1623 int rval = 0;
1624
1625 if (ddi_copyin(arg, &dop, sizeof (ql_adm_op_t), mode) != 0) {
1626 EL(ha, "failed, driver_op_t ddi_copyin\n");
1627 return (EFAULT);
1628 }
1629
1630 QL_PRINT_9(CE_CONT, "(%d): started, cmd=%xh, buffer=%llx,"
1631 " length=%xh, option=%xh\n", ha->instance, dop.cmd, dop.buffer,
1632 dop.length, dop.option);
1633
1634 switch (dop.cmd) {
1635 case QL_ADAPTER_INFO:
1636 rval = ql_adm_adapter_info(ha, &dop, mode);
1637 break;
1638
1639 case QL_EXTENDED_LOGGING:
1640 rval = ql_adm_extended_logging(ha, &dop);
1641 break;
1642
1643 case QL_LOOP_RESET:
1644 rval = ql_adm_loop_reset(ha);
1645 break;
1646
1647 case QL_DEVICE_LIST:
1648 rval = ql_adm_device_list(ha, &dop, mode);
1649 break;
1650
1651 case QL_PROP_UPDATE_INT:
1652 rval = ql_adm_prop_update_int(ha, &dop, mode);
1653 break;
1654
1655 case QL_UPDATE_PROPERTIES:
1656 rval = ql_adm_update_properties(ha);
1657 break;
1658
1659 case QL_FW_DUMP:
1660 rval = ql_adm_fw_dump(ha, &dop, arg, mode);
1661 break;
1662
1663 case QL_NVRAM_LOAD:
1664 rval = ql_adm_nvram_load(ha, &dop, mode);
1665 break;
1666
1667 case QL_NVRAM_DUMP:
1668 rval = ql_adm_nvram_dump(ha, &dop, mode);
1669 break;
1670
1671 case QL_FLASH_LOAD:
1672 rval = ql_adm_flash_load(ha, &dop, mode);
1673 break;
1674
1675 case QL_VPD_LOAD:
1676 rval = ql_adm_vpd_load(ha, &dop, mode);
1677 break;
1678
1679 case QL_VPD_DUMP:
1680 rval = ql_adm_vpd_dump(ha, &dop, mode);
1681 break;
1682
1683 case QL_VPD_GETTAG:
1684 rval = ql_adm_vpd_gettag(ha, &dop, mode);
1685 break;
1686
1687 case QL_UPD_FWMODULE:
1688 rval = ql_adm_updfwmodule(ha, &dop, mode);
1689 break;
1690
1691 default:
1692 EL(ha, "unsupported driver op cmd: %x\n", dop.cmd);
1693 return (EINVAL);
1694 }
1695
1696 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1697
1698 return (rval);
1699 }
1700
1701 /*
1702 * ql_adm_adapter_info
1703 * Performs qladm QL_ADAPTER_INFO command
1704 *
1705 * Input:
1706 * ha: adapter state pointer.
1707 * dop: ql_adm_op_t structure pointer.
1708 * mode: flags.
1709 *
1710 * Returns:
1711 *
1712 * Context:
1713 * Kernel context.
1714 */
1715 static int
1716 ql_adm_adapter_info(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
1717 {
1718 ql_adapter_info_t hba;
1719 uint8_t *dp;
1720 uint32_t length;
1721 int rval, i;
1722
1723 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1724
1725 hba.device_id = ha->device_id;
1726
1727 dp = CFG_IST(ha, CFG_CTRL_24258081) ?
1728 &ha->init_ctrl_blk.cb24.port_name[0] :
1729 &ha->init_ctrl_blk.cb.port_name[0];
1730 bcopy(dp, hba.wwpn, 8);
1731
1732 hba.d_id = ha->d_id.b24;
1733
1734 if (ha->xioctl->fdesc.flash_size == 0 &&
1735 !(CFG_IST(ha, CFG_CTRL_2200) && !ha->subven_id)) {
1736 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1737 EL(ha, "ql_stall_driver failed\n");
1738 return (EBUSY);
1739 }
1740
1741 if ((rval = ql_setup_fcache(ha)) != QL_SUCCESS) {
1742 EL(ha, "ql_setup_flash failed=%xh\n", rval);
1743 if (rval == QL_FUNCTION_TIMEOUT) {
1744 return (EBUSY);
1745 }
1746 return (EIO);
1747 }
1748
1749 /* Resume I/O */
1750 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1751 ql_restart_driver(ha);
1752 } else {
1753 EL(ha, "isp_abort_needed for restart\n");
1754 ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED,
1755 DRIVER_STALL);
1756 }
1757 }
1758 hba.flash_size = ha->xioctl->fdesc.flash_size;
1759
1760 (void) strcpy(hba.driver_ver, QL_VERSION);
1761
1762 (void) sprintf(hba.fw_ver, "%d.%d.%d", ha->fw_major_version,
1763 ha->fw_minor_version, ha->fw_subminor_version);
1764
1765 bzero(hba.fcode_ver, sizeof (hba.fcode_ver));
1766
1767 /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
1768 rval = ddi_getlongprop(DDI_DEV_T_ANY, ha->dip,
1769 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version", (caddr_t)&dp, &i);
1770 length = i;
1771 if (rval != DDI_PROP_SUCCESS) {
1772 EL(ha, "failed, ddi_getlongprop=%xh\n", rval);
1773 } else {
1774 if (length > (uint32_t)sizeof (hba.fcode_ver)) {
1775 length = sizeof (hba.fcode_ver) - 1;
1776 }
1777 bcopy((void *)dp, (void *)hba.fcode_ver, length);
1778 kmem_free(dp, length);
1779 }
1780
1781 if (ddi_copyout((void *)&hba, (void *)(uintptr_t)dop->buffer,
1782 dop->length, mode) != 0) {
1783 EL(ha, "failed, ddi_copyout\n");
1784 return (EFAULT);
1785 }
1786
1787 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1788
1789 return (0);
1790 }
1791
1792 /*
1793 * ql_adm_extended_logging
1794 * Performs qladm QL_EXTENDED_LOGGING command
1795 *
1796 * Input:
1797 * ha: adapter state pointer.
1798 * dop: ql_adm_op_t structure pointer.
1799 *
1800 * Returns:
1801 *
1802 * Context:
1803 * Kernel context.
1804 */
1805 static int
1806 ql_adm_extended_logging(ql_adapter_state_t *ha, ql_adm_op_t *dop)
1807 {
1808 char prop_name[MAX_PROP_LENGTH];
1809 int rval;
1810
1811 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1812
1813 (void) sprintf(prop_name, "hba%d-extended-logging", ha->instance);
1814
1815 /*LINTED [Solaris DDI_DEV_T_NONE Lint warning]*/
1816 rval = ddi_prop_update_int(DDI_DEV_T_NONE, ha->dip, prop_name,
1817 (int)dop->option);
1818 if (rval != DDI_PROP_SUCCESS) {
1819 EL(ha, "failed, prop_update = %xh\n", rval);
1820 return (EINVAL);
1821 } else {
1822 dop->option ?
1823 (ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING) :
1824 (ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING);
1825 }
1826
1827 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1828
1829 return (0);
1830 }
1831
1832 /*
1833 * ql_adm_loop_reset
1834 * Performs qladm QL_LOOP_RESET command
1835 *
1836 * Input:
1837 * ha: adapter state pointer.
1838 *
1839 * Returns:
1840 *
1841 * Context:
1842 * Kernel context.
1843 */
1844 static int
1845 ql_adm_loop_reset(ql_adapter_state_t *ha)
1846 {
1847 int rval;
1848
1849 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1850
1851 if (ha->task_daemon_flags & LOOP_DOWN) {
1852 (void) ql_full_login_lip(ha);
1853 } else if ((rval = ql_full_login_lip(ha)) != QL_SUCCESS) {
1854 EL(ha, "failed, ql_initiate_lip=%xh\n", rval);
1855 return (EIO);
1856 }
1857
1858 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1859
1860 return (0);
1861 }
1862
1863 /*
1864 * ql_adm_device_list
1865 * Performs qladm QL_DEVICE_LIST command
1866 *
1867 * Input:
1868 * ha: adapter state pointer.
1869 * dop: ql_adm_op_t structure pointer.
1870 * mode: flags.
1871 *
1872 * Returns:
1873 *
1874 * Context:
1875 * Kernel context.
1876 */
1877 static int
1878 ql_adm_device_list(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
1879 {
1880 ql_device_info_t dev;
1881 ql_link_t *link;
1882 ql_tgt_t *tq;
1883 uint32_t index, cnt;
1884
1885 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1886
1887 cnt = 0;
1888 dev.address = 0xffffffff;
1889
1890 /* Scan port list for requested target and fill in the values */
1891 for (link = NULL, index = 0;
1892 index < DEVICE_HEAD_LIST_SIZE && link == NULL; index++) {
1893 for (link = ha->dev[index].first; link != NULL;
1894 link = link->next) {
1895 tq = link->base_address;
1896
1897 if (!VALID_TARGET_ID(ha, tq->loop_id)) {
1898 continue;
1899 }
1900 if (cnt != dop->option) {
1901 cnt++;
1902 continue;
1903 }
1904 /* fill in the values */
1905 bcopy(tq->port_name, dev.wwpn, 8);
1906 dev.address = tq->d_id.b24;
1907 dev.loop_id = tq->loop_id;
1908 if (tq->flags & TQF_TAPE_DEVICE) {
1909 dev.type = FCT_TAPE;
1910 } else if (tq->flags & TQF_INITIATOR_DEVICE) {
1911 dev.type = FCT_INITIATOR;
1912 } else {
1913 dev.type = FCT_TARGET;
1914 }
1915 break;
1916 }
1917 }
1918
1919 if (ddi_copyout((void *)&dev, (void *)(uintptr_t)dop->buffer,
1920 dop->length, mode) != 0) {
1921 EL(ha, "failed, ddi_copyout\n");
1922 return (EFAULT);
1923 }
1924
1925 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1926
1927 return (0);
1928 }
1929
1930 /*
1931 * ql_adm_update_properties
1932 * Performs qladm QL_UPDATE_PROPERTIES command
1933 *
1934 * Input:
1935 * ha: adapter state pointer.
1936 *
1937 * Returns:
1938 *
1939 * Context:
1940 * Kernel context.
1941 */
1942 static int
1943 ql_adm_update_properties(ql_adapter_state_t *ha)
1944 {
1945 ql_comb_init_cb_t init_ctrl_blk;
1946 ql_comb_ip_init_cb_t ip_init_ctrl_blk;
1947
1948 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1949
1950 /* Stall driver instance. */
1951 (void) ql_stall_driver(ha, 0);
1952
1953 /* Save init control blocks. */
1954 bcopy(&ha->init_ctrl_blk, &init_ctrl_blk, sizeof (ql_comb_init_cb_t));
1955 bcopy(&ha->ip_init_ctrl_blk, &ip_init_ctrl_blk,
1956 sizeof (ql_comb_ip_init_cb_t));
1957
1958 /* Update PCI configration. */
1959 (void) ql_pci_sbus_config(ha);
1960
1961 /* Get configuration properties. */
1962 (void) ql_nvram_config(ha);
1963
1964 /* Check for init firmware required. */
1965 if (bcmp(&ha->init_ctrl_blk, &init_ctrl_blk,
1966 sizeof (ql_comb_init_cb_t)) != 0 ||
1967 bcmp(&ha->ip_init_ctrl_blk, &ip_init_ctrl_blk,
1968 sizeof (ql_comb_ip_init_cb_t)) != 0) {
1969
1970 EL(ha, "isp_abort_needed\n");
1971 ha->loop_down_timer = LOOP_DOWN_TIMER_START;
1972 TASK_DAEMON_LOCK(ha);
1973 ha->task_daemon_flags |= LOOP_DOWN | ISP_ABORT_NEEDED;
1974 TASK_DAEMON_UNLOCK(ha);
1975 }
1976
1977 /* Update AEN queue. */
1978 if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
1979 ql_enqueue_aen(ha, MBA_PORT_UPDATE, NULL);
1980 }
1981
1982 /* Restart driver instance. */
1983 ql_restart_driver(ha);
1984
1985 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1986
1987 return (0);
1988 }
1989
1990 /*
1991 * ql_adm_prop_update_int
1992 * Performs qladm QL_PROP_UPDATE_INT command
1993 *
1994 * Input:
1995 * ha: adapter state pointer.
1996 * dop: ql_adm_op_t structure pointer.
1997 * mode: flags.
1998 *
1999 * Returns:
2000 *
2001 * Context:
2002 * Kernel context.
2003 */
2004 static int
2005 ql_adm_prop_update_int(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2006 {
2007 char *prop_name;
2008 int rval;
2009
2010 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2011
2012 prop_name = kmem_zalloc(dop->length, KM_SLEEP);
2013
2014 if (ddi_copyin((void *)(uintptr_t)dop->buffer, prop_name, dop->length,
2015 mode) != 0) {
2016 EL(ha, "failed, prop_name ddi_copyin\n");
2017 kmem_free(prop_name, dop->length);
2018 return (EFAULT);
2019 }
2020
2021 /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
2022 if ((rval = ddi_prop_update_int(DDI_DEV_T_NONE, ha->dip, prop_name,
2023 (int)dop->option)) != DDI_PROP_SUCCESS) {
2024 EL(ha, "failed, prop_update=%xh\n", rval);
2025 kmem_free(prop_name, dop->length);
2026 return (EINVAL);
2027 }
2028
2029 kmem_free(prop_name, dop->length);
2030
2031 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2032
2033 return (0);
2034 }
2035
2036 /*
2037 * ql_adm_fw_dump
2038 * Performs qladm QL_FW_DUMP command
2039 *
2040 * Input:
2041 * ha: adapter state pointer.
2042 * dop: ql_adm_op_t structure pointer.
2043 * udop: user space ql_adm_op_t structure pointer.
2044 * mode: flags.
2045 *
2046 * Returns:
2047 *
2048 * Context:
2049 * Kernel context.
2050 */
2051 static int
2052 ql_adm_fw_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, void *udop, int mode)
2053 {
2054 caddr_t dmp;
2055
2056 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2057
2058 if (dop->length < ha->risc_dump_size) {
2059 EL(ha, "failed, incorrect length=%xh, size=%xh\n",
2060 dop->length, ha->risc_dump_size);
2061 return (EINVAL);
2062 }
2063
2064 if (ha->ql_dump_state & QL_DUMP_VALID) {
2065 dmp = kmem_zalloc(ha->risc_dump_size, KM_SLEEP);
2066
2067 dop->length = (uint32_t)ql_ascii_fw_dump(ha, dmp);
2068 if (ddi_copyout((void *)dmp, (void *)(uintptr_t)dop->buffer,
2069 dop->length, mode) != 0) {
2070 EL(ha, "failed, ddi_copyout\n");
2071 kmem_free(dmp, ha->risc_dump_size);
2072 return (EFAULT);
2073 }
2074
2075 kmem_free(dmp, ha->risc_dump_size);
2076 ha->ql_dump_state |= QL_DUMP_UPLOADED;
2077
2078 } else {
2079 EL(ha, "failed, no dump file\n");
2080 dop->length = 0;
2081 }
2082
2083 if (ddi_copyout(dop, udop, sizeof (ql_adm_op_t), mode) != 0) {
2084 EL(ha, "failed, driver_op_t ddi_copyout\n");
2085 return (EFAULT);
2086 }
2087
2088 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2089
2090 return (0);
2091 }
2092
2093 /*
2094 * ql_adm_nvram_dump
2095 * Performs qladm QL_NVRAM_DUMP command
2096 *
2097 * Input:
2098 * ha: adapter state pointer.
2099 * dop: ql_adm_op_t structure pointer.
2100 * mode: flags.
2101 *
2102 * Returns:
2103 *
2104 * Context:
2105 * Kernel context.
2106 */
2107 static int
2108 ql_adm_nvram_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2109 {
2110 int rval;
2111
2112 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2113
2114 if (dop->length < ha->nvram_cache->size) {
2115 EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
2116 ha->nvram_cache->size);
2117 return (EINVAL);
2118 }
2119
2120 if ((rval = ql_nv_util_dump(ha, (void *)(uintptr_t)dop->buffer,
2121 mode)) != 0) {
2122 EL(ha, "failed, ql_nv_util_dump\n");
2123 } else {
2124 /*EMPTY*/
2125 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2126 }
2127
2128 return (rval);
2129 }
2130
2131 /*
2132 * ql_adm_nvram_load
2133 * Performs qladm QL_NVRAM_LOAD command
2134 *
2135 * Input:
2136 * ha: adapter state pointer.
2137 * dop: ql_adm_op_t structure pointer.
2138 * mode: flags.
2139 *
2140 * Returns:
2141 *
2142 * Context:
2143 * Kernel context.
2144 */
2145 static int
2146 ql_adm_nvram_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2147 {
2148 int rval;
2149
2150 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2151
2152 if (dop->length < ha->nvram_cache->size) {
2153 EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
2154 ha->nvram_cache->size);
2155 return (EINVAL);
2156 }
2157
2158 if ((rval = ql_nv_util_load(ha, (void *)(uintptr_t)dop->buffer,
2159 mode)) != 0) {
2160 EL(ha, "failed, ql_nv_util_dump\n");
2161 } else {
2162 /*EMPTY*/
2163 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2164 }
2165
2166 return (rval);
2167 }
2168
2169 /*
2170 * ql_adm_flash_load
2171 * Performs qladm QL_FLASH_LOAD command
2172 *
2173 * Input:
2174 * ha: adapter state pointer.
2175 * dop: ql_adm_op_t structure pointer.
2176 * mode: flags.
2177 *
2178 * Returns:
2179 *
2180 * Context:
2181 * Kernel context.
2182 */
2183 static int
2184 ql_adm_flash_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2185 {
2186 uint8_t *dp;
2187 int rval;
2188
2189 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2190
2191 dp = kmem_zalloc(dop->length, KM_SLEEP);
2192
2193 if (ddi_copyin((void *)(uintptr_t)dop->buffer, dp, dop->length,
2194 mode) != 0) {
2195 EL(ha, "ddi_copyin failed\n");
2196 kmem_free(dp, dop->length);
2197 return (EFAULT);
2198 }
2199
2200 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
2201 EL(ha, "ql_stall_driver failed\n");
2202 kmem_free(dp, dop->length);
2203 return (EBUSY);
2204 }
2205
2206 rval = (CFG_IST(ha, CFG_CTRL_24258081) ?
2207 ql_24xx_load_flash(ha, dp, dop->length, dop->option) :
2208 ql_load_flash(ha, dp, dop->length));
2209
2210 ql_restart_driver(ha);
2211
2212 kmem_free(dp, dop->length);
2213
2214 if (rval != QL_SUCCESS) {
2215 EL(ha, "failed\n");
2216 return (EIO);
2217 }
2218
2219 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2220
2221 return (0);
2222 }
2223
2224 /*
2225 * ql_adm_vpd_dump
2226 * Performs qladm QL_VPD_DUMP command
2227 *
2228 * Input:
2229 * ha: adapter state pointer.
2230 * dop: ql_adm_op_t structure pointer.
2231 * mode: flags.
2232 *
2233 * Returns:
2234 *
2235 * Context:
2236 * Kernel context.
2237 */
2238 static int
2239 ql_adm_vpd_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2240 {
2241 int rval;
2242
2243 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2244
2245 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
2246 EL(ha, "hba does not support VPD\n");
2247 return (EINVAL);
2248 }
2249
2250 if (dop->length < QL_24XX_VPD_SIZE) {
2251 EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
2252 QL_24XX_VPD_SIZE);
2253 return (EINVAL);
2254 }
2255
2256 if ((rval = ql_vpd_dump(ha, (void *)(uintptr_t)dop->buffer, mode))
2257 != 0) {
2258 EL(ha, "failed, ql_vpd_dump\n");
2259 } else {
2260 /*EMPTY*/
2261 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2262 }
2263
2264 return (rval);
2265 }
2266
2267 /*
2268 * ql_adm_vpd_load
2269 * Performs qladm QL_VPD_LOAD command
2270 *
2271 * Input:
2272 * ha: adapter state pointer.
2273 * dop: ql_adm_op_t structure pointer.
2274 * mode: flags.
2275 *
2276 * Returns:
2277 *
2278 * Context:
2279 * Kernel context.
2280 */
2281 static int
2282 ql_adm_vpd_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2283 {
2284 int rval;
2285
2286 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2287
2288 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
2289 EL(ha, "hba does not support VPD\n");
2290 return (EINVAL);
2291 }
2292
2293 if (dop->length < QL_24XX_VPD_SIZE) {
2294 EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
2295 QL_24XX_VPD_SIZE);
2296 return (EINVAL);
2297 }
2298
2299 if ((rval = ql_vpd_load(ha, (void *)(uintptr_t)dop->buffer, mode))
2300 != 0) {
2301 EL(ha, "failed, ql_vpd_dump\n");
2302 } else {
2303 /*EMPTY*/
2304 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2305 }
2306
2307 return (rval);
2308 }
2309
2310 /*
2311 * ql_adm_vpd_gettag
2312 * Performs qladm QL_VPD_GETTAG command
2313 *
2314 * Input:
2315 * ha: adapter state pointer.
2316 * dop: ql_adm_op_t structure pointer.
2317 * mode: flags.
2318 *
2319 * Returns:
2320 *
2321 * Context:
2322 * Kernel context.
2323 */
2324 static int
2325 ql_adm_vpd_gettag(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2326 {
2327 int rval = 0;
2328 uint8_t *lbuf;
2329
2330 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2331
2332 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
2333 EL(ha, "hba does not support VPD\n");
2334 return (EINVAL);
2335 }
2336
2337 if ((lbuf = (uint8_t *)kmem_zalloc(dop->length, KM_SLEEP)) == NULL) {
2338 EL(ha, "mem alloc failure of %xh bytes\n", dop->length);
2339 rval = EFAULT;
2340 } else {
2341 if (ddi_copyin((void *)(uintptr_t)dop->buffer, lbuf,
2342 dop->length, mode) != 0) {
2343 EL(ha, "ddi_copyin failed\n");
2344 kmem_free(lbuf, dop->length);
2345 return (EFAULT);
2346 }
2347
2348 if ((rval = ql_vpd_lookup(ha, lbuf, lbuf, (int32_t)
2349 dop->length)) < 0) {
2350 EL(ha, "failed vpd_lookup\n");
2351 } else {
2352 if (ddi_copyout(lbuf, (void *)(uintptr_t)dop->buffer,
2353 strlen((int8_t *)lbuf)+1, mode) != 0) {
2354 EL(ha, "failed, ddi_copyout\n");
2355 rval = EFAULT;
2356 } else {
2357 rval = 0;
2358 }
2359 }
2360 kmem_free(lbuf, dop->length);
2361 }
2362
2363 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2364
2365 return (rval);
2366 }
2367
2368 /*
2369 * ql_adm_updfwmodule
2370 * Performs qladm QL_UPD_FWMODULE command
2371 *
2372 * Input:
2373 * ha: adapter state pointer.
2374 * dop: ql_adm_op_t structure pointer.
2375 * mode: flags.
2376 *
2377 * Returns:
2378 *
2379 * Context:
2380 * Kernel context.
2381 */
2382 /* ARGSUSED */
2383 static int
2384 ql_adm_updfwmodule(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2385 {
2386 int rval = DDI_SUCCESS;
2387 ql_link_t *link;
2388 ql_adapter_state_t *ha2 = NULL;
2389 uint16_t fw_class = (uint16_t)dop->option;
2390
2391 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2392
2393 /* zero the firmware module reference count */
2394 for (link = ql_hba.first; link != NULL; link = link->next) {
2395 ha2 = link->base_address;
2396 if (fw_class == ha2->fw_class) {
2397 if ((rval = ddi_modclose(ha2->fw_module)) !=
2398 DDI_SUCCESS) {
2399 EL(ha2, "modclose rval=%xh\n", rval);
2400 break;
2401 }
2402 ha2->fw_module = NULL;
2403 }
2404 }
2405
2406 /* reload the f/w modules */
2407 for (link = ql_hba.first; link != NULL; link = link->next) {
2408 ha2 = link->base_address;
2409
2410 if ((fw_class == ha2->fw_class) && (ha2->fw_class == NULL)) {
2411 if ((rval = (int32_t)ql_fwmodule_resolve(ha2)) !=
2412 QL_SUCCESS) {
2413 EL(ha2, "unable to load f/w module: '%x' "
2414 "(rval=%xh)\n", ha2->fw_class, rval);
2415 rval = EFAULT;
2416 } else {
2417 EL(ha2, "f/w module updated: '%x'\n",
2418 ha2->fw_class);
2419 }
2420
2421 EL(ha2, "isp abort needed (%d)\n", ha->instance);
2422
2423 ql_awaken_task_daemon(ha2, NULL, ISP_ABORT_NEEDED, 0);
2424
2425 rval = 0;
2426 }
2427 }
2428
2429 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2430
2431 return (rval);
2432 }