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
ql_open(dev_t * dev_p,int flags,int otyp,cred_t * cred_p)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
ql_close(dev_t dev,int flags,int otyp,cred_t * cred_p)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
ql_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cred_p,int * rval_p)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
ql_busy_notification(ql_adapter_state_t * ha)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
ql_idle_notification(ql_adapter_state_t * ha)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
ql_get_feature_bits(ql_adapter_state_t * ha,uint16_t * features)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
ql_set_feature_bits(ql_adapter_state_t * ha,uint16_t features)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 if (nv == NULL) {
508 EL(ha, "failed, kmem_zalloc\n");
509 return (ENOMEM);
510 }
511
512 rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
513 if (rval != QL_SUCCESS) {
514 EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
515 kmem_free(nv, sizeof (*nv));
516 return (EIO);
517 }
518 rval = 0;
519
520 /*
521 * Read off the whole NVRAM
522 */
523 wptr = (uint16_t *)nv;
524 csum = 0;
525 for (count = 0; count < sizeof (nvram_t) / 2; count++) {
526 *wptr = (uint16_t)ql_get_nvram_word(ha, count + start_addr);
527 csum = (uint8_t)(csum + (uint8_t)*wptr);
528 csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8));
529 wptr++;
530 }
531
532 /*
533 * If the checksum is BAD then fail it right here.
534 */
535 if (csum) {
536 kmem_free(nv, sizeof (*nv));
537 ql_release_nvram(ha);
538 return (EBADF);
539 }
540
541 nv->adapter_features[0] = (uint8_t)((features & 0xFF00) >> 8);
542 nv->adapter_features[1] = (uint8_t)(features & 0xFF);
543
544 /*
545 * Recompute the chesksum now
546 */
547 bptr = (uint8_t *)nv;
548 for (count = 0; count < sizeof (nvram_t) - 1; count++) {
549 csum = (uint8_t)(csum + *bptr++);
550 }
551 csum = (uint8_t)(~csum + 1);
552 nv->checksum = csum;
553
554 /*
555 * Now load the NVRAM
556 */
557 wptr = (uint16_t *)nv;
558 for (count = 0; count < sizeof (nvram_t) / 2; count++) {
559 ql_load_nvram(ha, (uint8_t)(count + start_addr), *wptr++);
560 }
561
562 /*
563 * Read NVRAM and verify the contents
564 */
565 wptr = (uint16_t *)nv;
566 csum = 0;
567 for (count = 0; count < sizeof (nvram_t) / 2; count++) {
568 if (ql_get_nvram_word(ha, count + start_addr) != *wptr) {
569 rval = EIO;
570 break;
571 }
572 csum = (uint8_t)(csum + (uint8_t)*wptr);
573 csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8));
574 wptr++;
575 }
576
577 if (csum) {
578 rval = EINVAL;
579 }
580
581 kmem_free(nv, sizeof (*nv));
582 ql_release_nvram(ha);
583
584 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
585
586 return (rval);
587 }
588
589 /*
590 * Fix this function to update just feature bits and checksum in NVRAM
591 */
592 static int
ql_set_nvram_adapter_defaults(ql_adapter_state_t * ha)593 ql_set_nvram_adapter_defaults(ql_adapter_state_t *ha)
594 {
595 int rval;
596 uint32_t count;
597 uint32_t start_addr;
598
599 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
600
601 rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
602 if (rval != QL_SUCCESS) {
603 EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
604 return (EIO);
605 }
606 rval = 0;
607
608 if (CFG_IST(ha, CFG_CTRL_24258081)) {
609 nvram_24xx_t *nv;
610 uint32_t *longptr;
611 uint32_t csum = 0;
612
613 nv = kmem_zalloc(sizeof (*nv), KM_SLEEP);
614 if (nv == NULL) {
615 EL(ha, "failed, kmem_zalloc\n");
616 return (ENOMEM);
617 }
618
619 nv->nvram_version[0] = LSB(ICB_24XX_VERSION);
620 nv->nvram_version[1] = MSB(ICB_24XX_VERSION);
621
622 nv->version[0] = 1;
623 nv->max_frame_length[1] = 8;
624 nv->execution_throttle[0] = 16;
625 nv->login_retry_count[0] = 8;
626
627 nv->firmware_options_1[0] = BIT_2 | BIT_1;
628 nv->firmware_options_1[1] = BIT_5;
629 nv->firmware_options_2[0] = BIT_5;
630 nv->firmware_options_2[1] = BIT_4;
631 nv->firmware_options_3[1] = BIT_6;
632
633 /*
634 * Set default host adapter parameters
635 */
636 nv->host_p[0] = BIT_4 | BIT_1;
637 nv->host_p[1] = BIT_3 | BIT_2;
638 nv->reset_delay = 5;
639 nv->max_luns_per_target[0] = 128;
640 nv->port_down_retry_count[0] = 30;
641 nv->link_down_timeout[0] = 30;
642
643 /*
644 * compute the chesksum now
645 */
646 longptr = (uint32_t *)nv;
647 csum = 0;
648 for (count = 0; count < (sizeof (nvram_24xx_t)/4)-1; count++) {
649 csum += *longptr;
650 longptr++;
651 }
652 csum = (uint32_t)(~csum + 1);
653 LITTLE_ENDIAN_32((long)csum);
654 *longptr = csum;
655
656 /*
657 * Now load the NVRAM
658 */
659 longptr = (uint32_t *)nv;
660 for (count = 0; count < sizeof (nvram_24xx_t) / 4; count++) {
661 (void) ql_24xx_load_nvram(ha,
662 (uint32_t)(count + start_addr), *longptr++);
663 }
664
665 /*
666 * Read NVRAM and verify the contents
667 */
668 csum = 0;
669 longptr = (uint32_t *)nv;
670 for (count = 0; count < sizeof (nvram_24xx_t) / 4; count++) {
671 rval = ql_24xx_read_flash(ha, count + start_addr,
672 longptr);
673 if (rval != QL_SUCCESS) {
674 EL(ha, "24xx_read_flash failed=%xh\n", rval);
675 break;
676 }
677 csum += *longptr;
678 }
679
680 if (csum) {
681 rval = EINVAL;
682 }
683 kmem_free(nv, sizeof (nvram_24xx_t));
684 } else {
685 nvram_t *nv;
686 uint16_t *wptr;
687 uint8_t *bptr;
688 uint8_t csum;
689
690 nv = kmem_zalloc(sizeof (*nv), KM_SLEEP);
691 if (nv == NULL) {
692 EL(ha, "failed, kmem_zalloc\n");
693 return (ENOMEM);
694 }
695 /*
696 * Set default initialization control block.
697 */
698 nv->parameter_block_version = ICB_VERSION;
699 nv->firmware_options[0] = BIT_4 | BIT_3 | BIT_2 | BIT_1;
700 nv->firmware_options[1] = BIT_7 | BIT_5 | BIT_2;
701
702 nv->max_frame_length[1] = 4;
703 nv->max_iocb_allocation[1] = 1;
704 nv->execution_throttle[0] = 16;
705 nv->login_retry_count = 8;
706 nv->port_name[0] = 33;
707 nv->port_name[3] = 224;
708 nv->port_name[4] = 139;
709 nv->login_timeout = 4;
710
711 /*
712 * Set default host adapter parameters
713 */
714 nv->host_p[0] = BIT_1;
715 nv->host_p[1] = BIT_2;
716 nv->reset_delay = 5;
717 nv->port_down_retry_count = 8;
718 nv->maximum_luns_per_target[0] = 8;
719
720 /*
721 * compute the chesksum now
722 */
723 bptr = (uint8_t *)nv;
724 csum = 0;
725 for (count = 0; count < sizeof (nvram_t) - 1; count++) {
726 csum = (uint8_t)(csum + *bptr++);
727 }
728 csum = (uint8_t)(~csum + 1);
729 nv->checksum = csum;
730
731 /*
732 * Now load the NVRAM
733 */
734 wptr = (uint16_t *)nv;
735 for (count = 0; count < sizeof (nvram_t) / 2; count++) {
736 ql_load_nvram(ha, (uint8_t)(count + start_addr),
737 *wptr++);
738 }
739
740 /*
741 * Read NVRAM and verify the contents
742 */
743 wptr = (uint16_t *)nv;
744 csum = 0;
745 for (count = 0; count < sizeof (nvram_t) / 2; count++) {
746 if (ql_get_nvram_word(ha, count + start_addr) !=
747 *wptr) {
748 rval = EIO;
749 break;
750 }
751 csum = (uint8_t)(csum + (uint8_t)*wptr);
752 csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8));
753 wptr++;
754 }
755 if (csum) {
756 rval = EINVAL;
757 }
758 kmem_free(nv, sizeof (*nv));
759 }
760 ql_release_nvram(ha);
761
762 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
763
764 return (rval);
765 }
766
767 static void
ql_load_nvram(ql_adapter_state_t * ha,uint8_t addr,uint16_t value)768 ql_load_nvram(ql_adapter_state_t *ha, uint8_t addr, uint16_t value)
769 {
770 int count;
771 volatile uint16_t word;
772 volatile uint32_t nv_cmd;
773
774 ql_nv_write(ha, NV_DATA_OUT);
775 ql_nv_write(ha, 0);
776 ql_nv_write(ha, 0);
777
778 for (word = 0; word < 8; word++) {
779 ql_nv_write(ha, NV_DATA_OUT);
780 }
781
782 /*
783 * Deselect the chip
784 */
785 WRT16_IO_REG(ha, nvram, NV_DESELECT);
786 ql_nv_delay();
787
788 /*
789 * Erase Location
790 */
791 nv_cmd = (addr << 16) | NV_ERASE_OP;
792 nv_cmd <<= 5;
793 for (count = 0; count < 11; count++) {
794 if (nv_cmd & BIT_31) {
795 ql_nv_write(ha, NV_DATA_OUT);
796 } else {
797 ql_nv_write(ha, 0);
798 }
799 nv_cmd <<= 1;
800 }
801
802 /*
803 * Wait for Erase to Finish
804 */
805 WRT16_IO_REG(ha, nvram, NV_DESELECT);
806 ql_nv_delay();
807 WRT16_IO_REG(ha, nvram, NV_SELECT);
808 word = 0;
809 while ((word & NV_DATA_IN) == 0) {
810 ql_nv_delay();
811 word = RD16_IO_REG(ha, nvram);
812 }
813 WRT16_IO_REG(ha, nvram, NV_DESELECT);
814 ql_nv_delay();
815
816 /*
817 * Write data now
818 */
819 nv_cmd = (addr << 16) | NV_WRITE_OP;
820 nv_cmd |= value;
821 nv_cmd <<= 5;
822 for (count = 0; count < 27; count++) {
823 if (nv_cmd & BIT_31) {
824 ql_nv_write(ha, NV_DATA_OUT);
825 } else {
826 ql_nv_write(ha, 0);
827 }
828 nv_cmd <<= 1;
829 }
830
831 /*
832 * Wait for NVRAM to become ready
833 */
834 WRT16_IO_REG(ha, nvram, NV_DESELECT);
835 ql_nv_delay();
836 WRT16_IO_REG(ha, nvram, NV_SELECT);
837 word = 0;
838 while ((word & NV_DATA_IN) == 0) {
839 ql_nv_delay();
840 word = RD16_IO_REG(ha, nvram);
841 }
842 WRT16_IO_REG(ha, nvram, NV_DESELECT);
843 ql_nv_delay();
844
845 /*
846 * Disable writes
847 */
848 ql_nv_write(ha, NV_DATA_OUT);
849 for (count = 0; count < 10; count++) {
850 ql_nv_write(ha, 0);
851 }
852
853 /*
854 * Deselect the chip now
855 */
856 WRT16_IO_REG(ha, nvram, NV_DESELECT);
857 }
858
859 /*
860 * ql_24xx_load_nvram
861 * Enable NVRAM and writes a 32bit word to ISP24xx NVRAM.
862 *
863 * Input:
864 * ha: adapter state pointer.
865 * addr: NVRAM address.
866 * value: data.
867 *
868 * Returns:
869 * ql local function return status code.
870 *
871 * Context:
872 * Kernel context.
873 */
874 static int
ql_24xx_load_nvram(ql_adapter_state_t * ha,uint32_t addr,uint32_t value)875 ql_24xx_load_nvram(ql_adapter_state_t *ha, uint32_t addr, uint32_t value)
876 {
877 int rval;
878
879 /* Enable flash write. */
880 if (!(CFG_IST(ha, CFG_CTRL_8081))) {
881 WRT32_IO_REG(ha, ctrl_status,
882 RD32_IO_REG(ha, ctrl_status) | ISP_FLASH_ENABLE);
883 RD32_IO_REG(ha, ctrl_status); /* PCI Posting. */
884 }
885
886 /* Disable NVRAM write-protection. */
887 if (CFG_IST(ha, CFG_CTRL_2422)) {
888 (void) ql_24xx_write_flash(ha, NVRAM_CONF_ADDR | 0x101, 0);
889 } else {
890 if ((rval = ql_24xx_unprotect_flash(ha)) != QL_SUCCESS) {
891 EL(ha, "unprotect_flash failed, rval=%xh\n", rval);
892 return (rval);
893 }
894 }
895
896 /* Write to flash. */
897 rval = ql_24xx_write_flash(ha, addr, value);
898
899 /* Enable NVRAM write-protection. */
900 if (CFG_IST(ha, CFG_CTRL_2422)) {
901 /* TODO: Check if 0x8c is correct -- sb: 0x9c ? */
902 (void) ql_24xx_write_flash(ha, NVRAM_CONF_ADDR | 0x101, 0x8c);
903 } else {
904 ql_24xx_protect_flash(ha);
905 }
906
907 /* Disable flash write. */
908 if (!(CFG_IST(ha, CFG_CTRL_81XX))) {
909 WRT32_IO_REG(ha, ctrl_status,
910 RD32_IO_REG(ha, ctrl_status) & ~ISP_FLASH_ENABLE);
911 RD32_IO_REG(ha, ctrl_status); /* PCI Posting. */
912 }
913
914 return (rval);
915 }
916
917 /*
918 * ql_nv_util_load
919 * Loads NVRAM from application.
920 *
921 * Input:
922 * ha = adapter state pointer.
923 * bp = user buffer address.
924 *
925 * Returns:
926 *
927 * Context:
928 * Kernel context.
929 */
930 int
ql_nv_util_load(ql_adapter_state_t * ha,void * bp,int mode)931 ql_nv_util_load(ql_adapter_state_t *ha, void *bp, int mode)
932 {
933 uint8_t cnt;
934 void *nv;
935 uint16_t *wptr;
936 uint16_t data;
937 uint32_t start_addr, *lptr, data32;
938 nvram_t *nptr;
939 int rval;
940
941 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
942
943 if ((nv = kmem_zalloc(ha->nvram_cache->size, KM_SLEEP)) == NULL) {
944 EL(ha, "failed, kmem_zalloc\n");
945 return (ENOMEM);
946 }
947
948 if (ddi_copyin(bp, nv, ha->nvram_cache->size, mode) != 0) {
949 EL(ha, "Buffer copy failed\n");
950 kmem_free(nv, ha->nvram_cache->size);
951 return (EFAULT);
952 }
953
954 /* See if the buffer passed to us looks sane */
955 nptr = (nvram_t *)nv;
956 if (nptr->id[0] != 'I' || nptr->id[1] != 'S' || nptr->id[2] != 'P' ||
957 nptr->id[3] != ' ') {
958 EL(ha, "failed, buffer sanity check\n");
959 kmem_free(nv, ha->nvram_cache->size);
960 return (EINVAL);
961 }
962
963 /* Quiesce I/O */
964 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
965 EL(ha, "ql_stall_driver failed\n");
966 kmem_free(nv, ha->nvram_cache->size);
967 return (EBUSY);
968 }
969
970 rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
971 if (rval != QL_SUCCESS) {
972 EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
973 kmem_free(nv, ha->nvram_cache->size);
974 ql_restart_driver(ha);
975 return (EIO);
976 }
977
978 /* Load NVRAM. */
979 if (CFG_IST(ha, CFG_CTRL_258081)) {
980 GLOBAL_HW_UNLOCK();
981 start_addr &= ~ha->flash_data_addr;
982 start_addr <<= 2;
983 if ((rval = ql_r_m_w_flash(ha, bp, ha->nvram_cache->size,
984 start_addr, mode)) != QL_SUCCESS) {
985 EL(ha, "nvram load failed, rval = %0xh\n", rval);
986 }
987 GLOBAL_HW_LOCK();
988 } else if (CFG_IST(ha, CFG_CTRL_2422)) {
989 lptr = (uint32_t *)nv;
990 for (cnt = 0; cnt < ha->nvram_cache->size / 4; cnt++) {
991 data32 = *lptr++;
992 LITTLE_ENDIAN_32(&data32);
993 rval = ql_24xx_load_nvram(ha, cnt + start_addr,
994 data32);
995 if (rval != QL_SUCCESS) {
996 EL(ha, "failed, 24xx_load_nvram=%xh\n", rval);
997 break;
998 }
999 }
1000 } else {
1001 wptr = (uint16_t *)nv;
1002 for (cnt = 0; cnt < ha->nvram_cache->size / 2; cnt++) {
1003 data = *wptr++;
1004 LITTLE_ENDIAN_16(&data);
1005 ql_load_nvram(ha, (uint8_t)(cnt + start_addr), data);
1006 }
1007 }
1008 /* switch to the new one */
1009 NVRAM_CACHE_LOCK(ha);
1010
1011 kmem_free(ha->nvram_cache->cache, ha->nvram_cache->size);
1012 ha->nvram_cache->cache = (void *)nptr;
1013
1014 NVRAM_CACHE_UNLOCK(ha);
1015
1016 ql_release_nvram(ha);
1017 ql_restart_driver(ha);
1018
1019 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1020
1021 if (rval == QL_SUCCESS) {
1022 return (0);
1023 }
1024
1025 return (EFAULT);
1026 }
1027
1028 /*
1029 * ql_nv_util_dump
1030 * Dumps NVRAM to application.
1031 *
1032 * Input:
1033 * ha = adapter state pointer.
1034 * bp = user buffer address.
1035 *
1036 * Returns:
1037 *
1038 * Context:
1039 * Kernel context.
1040 */
1041 int
ql_nv_util_dump(ql_adapter_state_t * ha,void * bp,int mode)1042 ql_nv_util_dump(ql_adapter_state_t *ha, void *bp, int mode)
1043 {
1044 uint32_t start_addr;
1045 int rval2, rval = 0;
1046
1047 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1048
1049 if (ha->nvram_cache == NULL ||
1050 ha->nvram_cache->size == NULL ||
1051 ha->nvram_cache->cache == NULL) {
1052 EL(ha, "failed, kmem_zalloc\n");
1053 return (ENOMEM);
1054 } else if (ha->nvram_cache->valid != 1) {
1055
1056 /* Quiesce I/O */
1057 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1058 EL(ha, "ql_stall_driver failed\n");
1059 return (EBUSY);
1060 }
1061
1062 rval2 = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
1063 if (rval2 != QL_SUCCESS) {
1064 EL(ha, "failed, ql_lock_nvram=%xh\n", rval2);
1065 ql_restart_driver(ha);
1066 return (EIO);
1067 }
1068 NVRAM_CACHE_LOCK(ha);
1069
1070 rval2 = ql_get_nvram(ha, ha->nvram_cache->cache,
1071 start_addr, ha->nvram_cache->size);
1072 if (rval2 != QL_SUCCESS) {
1073 rval = rval2;
1074 } else {
1075 ha->nvram_cache->valid = 1;
1076 EL(ha, "nvram cache now valid.");
1077 }
1078
1079 NVRAM_CACHE_UNLOCK(ha);
1080
1081 ql_release_nvram(ha);
1082 ql_restart_driver(ha);
1083
1084 if (rval != 0) {
1085 EL(ha, "failed to dump nvram, rval=%x\n", rval);
1086 return (rval);
1087 }
1088 }
1089
1090 if (ddi_copyout(ha->nvram_cache->cache, bp,
1091 ha->nvram_cache->size, mode) != 0) {
1092 EL(ha, "Buffer copy failed\n");
1093 return (EFAULT);
1094 }
1095
1096 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1097
1098 return (0);
1099 }
1100
1101 int
ql_get_nvram(ql_adapter_state_t * ha,void * dest_addr,uint32_t src_addr,uint32_t size)1102 ql_get_nvram(ql_adapter_state_t *ha, void *dest_addr, uint32_t src_addr,
1103 uint32_t size)
1104 {
1105 int rval = QL_SUCCESS;
1106 int cnt;
1107 /* Dump NVRAM. */
1108 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1109 uint32_t *lptr = (uint32_t *)dest_addr;
1110
1111 for (cnt = 0; cnt < size / 4; cnt++) {
1112 rval = ql_24xx_read_flash(ha, src_addr++, lptr);
1113 if (rval != QL_SUCCESS) {
1114 EL(ha, "read_flash failed=%xh\n", rval);
1115 rval = EAGAIN;
1116 break;
1117 }
1118 LITTLE_ENDIAN_32(lptr);
1119 lptr++;
1120 }
1121 } else {
1122 uint16_t data;
1123 uint16_t *wptr = (uint16_t *)dest_addr;
1124
1125 for (cnt = 0; cnt < size / 2; cnt++) {
1126 data = (uint16_t)ql_get_nvram_word(ha, cnt +
1127 src_addr);
1128 LITTLE_ENDIAN_16(&data);
1129 *wptr++ = data;
1130 }
1131 }
1132 return (rval);
1133 }
1134
1135 /*
1136 * ql_vpd_load
1137 * Loads VPD from application.
1138 *
1139 * Input:
1140 * ha = adapter state pointer.
1141 * bp = user buffer address.
1142 *
1143 * Returns:
1144 *
1145 * Context:
1146 * Kernel context.
1147 */
1148 int
ql_vpd_load(ql_adapter_state_t * ha,void * bp,int mode)1149 ql_vpd_load(ql_adapter_state_t *ha, void *bp, int mode)
1150 {
1151 uint8_t cnt;
1152 uint8_t *vpd, *vpdptr, *vbuf;
1153 uint32_t start_addr, vpd_size, *lptr, data32;
1154 int rval;
1155
1156 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1157
1158 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
1159 EL(ha, "unsupported adapter feature\n");
1160 return (ENOTSUP);
1161 }
1162
1163 vpd_size = QL_24XX_VPD_SIZE;
1164
1165 if ((vpd = kmem_zalloc(vpd_size, KM_SLEEP)) == NULL) {
1166 EL(ha, "failed, kmem_zalloc\n");
1167 return (ENOMEM);
1168 }
1169
1170 if (ddi_copyin(bp, vpd, vpd_size, mode) != 0) {
1171 EL(ha, "Buffer copy failed\n");
1172 kmem_free(vpd, vpd_size);
1173 return (EFAULT);
1174 }
1175
1176 /* Sanity check the user supplied data via checksum */
1177 if ((vpdptr = ql_vpd_findtag(ha, vpd, "RV")) == NULL) {
1178 EL(ha, "vpd RV tag missing\n");
1179 kmem_free(vpd, vpd_size);
1180 return (EINVAL);
1181 }
1182
1183 vpdptr += 3;
1184 cnt = 0;
1185 vbuf = vpd;
1186 while (vbuf <= vpdptr) {
1187 cnt += *vbuf++;
1188 }
1189 if (cnt != 0) {
1190 EL(ha, "mismatched checksum, cal=%xh, passed=%xh\n",
1191 (uint8_t)cnt, (uintptr_t)vpdptr);
1192 kmem_free(vpd, vpd_size);
1193 return (EINVAL);
1194 }
1195
1196 /* Quiesce I/O */
1197 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1198 EL(ha, "ql_stall_driver failed\n");
1199 kmem_free(vpd, vpd_size);
1200 return (EBUSY);
1201 }
1202
1203 rval = ql_lock_nvram(ha, &start_addr, LNF_VPD_DATA);
1204 if (rval != QL_SUCCESS) {
1205 EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
1206 kmem_free(vpd, vpd_size);
1207 ql_restart_driver(ha);
1208 return (EIO);
1209 }
1210
1211 /* Load VPD. */
1212 if (CFG_IST(ha, CFG_CTRL_258081)) {
1213 GLOBAL_HW_UNLOCK();
1214 start_addr &= ~ha->flash_data_addr;
1215 start_addr <<= 2;
1216 if ((rval = ql_r_m_w_flash(ha, bp, vpd_size, start_addr,
1217 mode)) != QL_SUCCESS) {
1218 EL(ha, "vpd load error: %xh\n", rval);
1219 }
1220 GLOBAL_HW_LOCK();
1221 } else {
1222 lptr = (uint32_t *)vpd;
1223 for (cnt = 0; cnt < vpd_size / 4; cnt++) {
1224 data32 = *lptr++;
1225 LITTLE_ENDIAN_32(&data32);
1226 rval = ql_24xx_load_nvram(ha, cnt + start_addr,
1227 data32);
1228 if (rval != QL_SUCCESS) {
1229 EL(ha, "failed, 24xx_load_nvram=%xh\n", rval);
1230 break;
1231 }
1232 }
1233 }
1234
1235 kmem_free(vpd, vpd_size);
1236
1237 /* Update the vcache */
1238 CACHE_LOCK(ha);
1239
1240 if (rval != QL_SUCCESS) {
1241 EL(ha, "failed, load\n");
1242 } else if ((ha->vcache == NULL) && ((ha->vcache =
1243 kmem_zalloc(vpd_size, KM_SLEEP)) == NULL)) {
1244 EL(ha, "failed, kmem_zalloc2\n");
1245 } else if (ddi_copyin(bp, ha->vcache, vpd_size, mode) != 0) {
1246 EL(ha, "Buffer copy2 failed\n");
1247 kmem_free(ha->vcache, vpd_size);
1248 ha->vcache = NULL;
1249 }
1250
1251 CACHE_UNLOCK(ha);
1252
1253 ql_release_nvram(ha);
1254 ql_restart_driver(ha);
1255
1256 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1257
1258 if (rval == QL_SUCCESS) {
1259 return (0);
1260 }
1261
1262 return (EFAULT);
1263 }
1264
1265 /*
1266 * ql_vpd_dump
1267 * Dumps VPD to application buffer.
1268 *
1269 * Input:
1270 * ha = adapter state pointer.
1271 * bp = user buffer address.
1272 *
1273 * Returns:
1274 *
1275 * Context:
1276 * Kernel context.
1277 */
1278 int
ql_vpd_dump(ql_adapter_state_t * ha,void * bp,int mode)1279 ql_vpd_dump(ql_adapter_state_t *ha, void *bp, int mode)
1280 {
1281 uint8_t cnt;
1282 void *vpd;
1283 uint32_t start_addr, vpd_size, *lptr;
1284 int rval = 0;
1285
1286 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1287
1288 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
1289 EL(ha, "unsupported adapter feature\n");
1290 return (EACCES);
1291 }
1292
1293 vpd_size = QL_24XX_VPD_SIZE;
1294
1295 CACHE_LOCK(ha);
1296
1297 if (ha->vcache != NULL) {
1298 /* copy back the vpd cache data */
1299 if (ddi_copyout(ha->vcache, bp, vpd_size, mode) != 0) {
1300 EL(ha, "Buffer copy failed\n");
1301 rval = EFAULT;
1302 }
1303 CACHE_UNLOCK(ha);
1304 return (rval);
1305 }
1306
1307 if ((vpd = kmem_zalloc(vpd_size, KM_SLEEP)) == NULL) {
1308 CACHE_UNLOCK(ha);
1309 EL(ha, "failed, kmem_zalloc\n");
1310 return (ENOMEM);
1311 }
1312
1313 /* Quiesce I/O */
1314 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1315 CACHE_UNLOCK(ha);
1316 EL(ha, "ql_stall_driver failed\n");
1317 kmem_free(vpd, vpd_size);
1318 return (EBUSY);
1319 }
1320
1321 rval = ql_lock_nvram(ha, &start_addr, LNF_VPD_DATA);
1322 if (rval != QL_SUCCESS) {
1323 CACHE_UNLOCK(ha);
1324 EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
1325 kmem_free(vpd, vpd_size);
1326 ql_restart_driver(ha);
1327 return (EIO);
1328 }
1329
1330 /* Dump VPD. */
1331 lptr = (uint32_t *)vpd;
1332
1333 for (cnt = 0; cnt < vpd_size / 4; cnt++) {
1334 rval = ql_24xx_read_flash(ha, start_addr++, lptr);
1335 if (rval != QL_SUCCESS) {
1336 EL(ha, "read_flash failed=%xh\n", rval);
1337 rval = EAGAIN;
1338 break;
1339 }
1340 LITTLE_ENDIAN_32(lptr);
1341 lptr++;
1342 }
1343
1344 ql_release_nvram(ha);
1345 ql_restart_driver(ha);
1346
1347 if (ddi_copyout(vpd, bp, vpd_size, mode) != 0) {
1348 CACHE_UNLOCK(ha);
1349 EL(ha, "Buffer copy failed\n");
1350 kmem_free(vpd, vpd_size);
1351 return (EFAULT);
1352 }
1353
1354 ha->vcache = vpd;
1355
1356 CACHE_UNLOCK(ha);
1357
1358 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1359
1360 if (rval != QL_SUCCESS) {
1361 return (EFAULT);
1362 } else {
1363 return (0);
1364 }
1365 }
1366
1367 /*
1368 * ql_vpd_findtag
1369 * Search the passed vpd buffer for the requested VPD tag type.
1370 *
1371 * Input:
1372 * ha = adapter state pointer.
1373 * vpdbuf = Pointer to start of the buffer to search
1374 * op = VPD opcode to find (must be NULL terminated).
1375 *
1376 * Returns:
1377 * Pointer to the opcode in the buffer if opcode found.
1378 * NULL if opcode is not found.
1379 *
1380 * Context:
1381 * Kernel context.
1382 */
1383 static uint8_t *
ql_vpd_findtag(ql_adapter_state_t * ha,uint8_t * vpdbuf,int8_t * opcode)1384 ql_vpd_findtag(ql_adapter_state_t *ha, uint8_t *vpdbuf, int8_t *opcode)
1385 {
1386 uint8_t *vpd = vpdbuf;
1387 uint8_t *end = vpdbuf + QL_24XX_VPD_SIZE;
1388 uint32_t found = 0;
1389
1390 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1391
1392 if (vpdbuf == NULL || opcode == NULL) {
1393 EL(ha, "null parameter passed!\n");
1394 return (NULL);
1395 }
1396
1397 while (vpd < end) {
1398
1399 /* check for end of vpd */
1400 if (vpd[0] == VPD_TAG_END) {
1401 if (opcode[0] == VPD_TAG_END) {
1402 found = 1;
1403 } else {
1404 found = 0;
1405 }
1406 break;
1407 }
1408
1409 /* check opcode */
1410 if (bcmp(opcode, vpd, strlen(opcode)) == 0) {
1411 /* found opcode requested */
1412 found = 1;
1413 break;
1414 }
1415
1416 /*
1417 * Didn't find the opcode, so calculate start of
1418 * next tag. Depending on the current tag type,
1419 * the length field can be 1 or 2 bytes
1420 */
1421 if (!(strncmp((char *)vpd, (char *)VPD_TAG_PRODID, 1))) {
1422 vpd += (vpd[2] << 8) + vpd[1] + 3;
1423 } else if (*vpd == VPD_TAG_LRT || *vpd == VPD_TAG_LRTC) {
1424 vpd += 3;
1425 } else {
1426 vpd += vpd[2] +3;
1427 }
1428 }
1429
1430 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1431
1432 return (found == 1 ? vpd : NULL);
1433 }
1434
1435 /*
1436 * ql_vpd_lookup
1437 * Return the VPD data for the request VPD tag
1438 *
1439 * Input:
1440 * ha = adapter state pointer.
1441 * opcode = VPD opcode to find (must be NULL terminated).
1442 * bp = Pointer to returned data buffer.
1443 * bplen = Length of returned data buffer.
1444 *
1445 * Returns:
1446 * Length of data copied into returned data buffer.
1447 * >0 = VPD data field (NULL terminated)
1448 * 0 = no data.
1449 * -1 = Could not find opcode in vpd buffer / error.
1450 *
1451 * Context:
1452 * Kernel context.
1453 *
1454 * NB: The opcode buffer and the bp buffer *could* be the same buffer!
1455 *
1456 */
1457 int32_t
ql_vpd_lookup(ql_adapter_state_t * ha,uint8_t * opcode,uint8_t * bp,int32_t bplen)1458 ql_vpd_lookup(ql_adapter_state_t *ha, uint8_t *opcode, uint8_t *bp,
1459 int32_t bplen)
1460 {
1461 uint8_t *vpd;
1462 uint8_t *vpdbuf;
1463 int32_t len = -1;
1464
1465 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1466
1467 if (opcode == NULL || bp == NULL || bplen < 1) {
1468 EL(ha, "invalid parameter passed: opcode=%ph, "
1469 "bp=%ph, bplen=%xh\n", opcode, bp, bplen);
1470 return (len);
1471 }
1472
1473 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
1474 return (len);
1475 }
1476
1477 if ((vpdbuf = (uint8_t *)kmem_zalloc(QL_24XX_VPD_SIZE,
1478 KM_SLEEP)) == NULL) {
1479 EL(ha, "unable to allocate vpd memory\n");
1480 return (len);
1481 }
1482
1483 if ((ql_vpd_dump(ha, vpdbuf, (int)FKIOCTL)) != 0) {
1484 kmem_free(vpdbuf, QL_24XX_VPD_SIZE);
1485 EL(ha, "unable to retrieve VPD data\n");
1486 return (len);
1487 }
1488
1489 if ((vpd = ql_vpd_findtag(ha, vpdbuf, (int8_t *)opcode)) != NULL) {
1490 /*
1491 * Found the tag
1492 */
1493 if (*opcode == VPD_TAG_END || *opcode == VPD_TAG_LRT ||
1494 *opcode == VPD_TAG_LRTC) {
1495 /*
1496 * we found it, but the tag doesn't have a data
1497 * field.
1498 */
1499 len = 0;
1500 } else if (!(strncmp((char *)vpd, (char *)
1501 VPD_TAG_PRODID, 1))) {
1502 len = vpd[2] << 8;
1503 len += vpd[1];
1504 } else {
1505 len = vpd[2];
1506 }
1507
1508 /*
1509 * make sure that the vpd len doesn't exceed the
1510 * vpd end
1511 */
1512 if (vpd+len > vpdbuf + QL_24XX_VPD_SIZE) {
1513 EL(ha, "vpd tag len (%xh) exceeds vpd buffer "
1514 "length\n", len);
1515 len = -1;
1516 }
1517 }
1518
1519 if (len >= 0) {
1520 /*
1521 * make sure we don't exceed callers buffer space len
1522 */
1523 if (len > bplen) {
1524 len = bplen-1;
1525 }
1526
1527 /* copy the data back */
1528 (void) strncpy((int8_t *)bp, (int8_t *)(vpd+3), (int64_t)len);
1529 bp[len] = NULL;
1530 } else {
1531 /* error -- couldn't find tag */
1532 bp[0] = NULL;
1533 if (opcode[1] != NULL) {
1534 EL(ha, "unable to find tag '%s'\n", opcode);
1535 } else {
1536 EL(ha, "unable to find tag '%xh'\n", opcode[0]);
1537 }
1538 }
1539
1540 kmem_free(vpdbuf, QL_24XX_VPD_SIZE);
1541
1542 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1543
1544 return (len);
1545 }
1546
1547 /*
1548 * ql_r_m_w_flash
1549 * Read modify write from user space to flash.
1550 *
1551 * Input:
1552 * ha: adapter state pointer.
1553 * dp: source byte pointer.
1554 * bc: byte count.
1555 * faddr: flash byte address.
1556 * mode: flags.
1557 *
1558 * Returns:
1559 * ql local function return status code.
1560 *
1561 * Context:
1562 * Kernel context.
1563 */
1564 int
ql_r_m_w_flash(ql_adapter_state_t * ha,caddr_t dp,uint32_t bc,uint32_t faddr,int mode)1565 ql_r_m_w_flash(ql_adapter_state_t *ha, caddr_t dp, uint32_t bc, uint32_t faddr,
1566 int mode)
1567 {
1568 uint8_t *bp;
1569 uint32_t xfer, bsize, saddr, ofst;
1570 int rval = 0;
1571
1572 QL_PRINT_9(CE_CONT, "(%d): started, dp=%ph, faddr=%xh, bc=%xh\n",
1573 ha->instance, (void *)dp, faddr, bc);
1574
1575 bsize = ha->xioctl->fdesc.block_size;
1576 saddr = faddr & ~(bsize - 1);
1577 ofst = faddr & (bsize - 1);
1578
1579 if ((bp = kmem_zalloc(bsize, KM_SLEEP)) == NULL) {
1580 EL(ha, "kmem_zalloc=null\n");
1581 return (QL_MEMORY_ALLOC_FAILED);
1582 }
1583
1584 while (bc) {
1585 xfer = bc > bsize ? bsize : bc;
1586 if (ofst + xfer > bsize) {
1587 xfer = bsize - ofst;
1588 }
1589 QL_PRINT_9(CE_CONT, "(%d): dp=%ph, saddr=%xh, bc=%xh, "
1590 "ofst=%xh, xfer=%xh\n", ha->instance, (void *)dp, saddr,
1591 bc, ofst, xfer);
1592
1593 if (ofst || xfer < bsize) {
1594 /* Dump Flash sector. */
1595 if ((rval = ql_dump_fcode(ha, bp, bsize, saddr)) !=
1596 QL_SUCCESS) {
1597 EL(ha, "dump_flash status=%x\n", rval);
1598 break;
1599 }
1600 }
1601
1602 /* Set new data. */
1603 if ((rval = ddi_copyin(dp, (caddr_t)(bp + ofst), xfer,
1604 mode)) != 0) {
1605 EL(ha, "ddi_copyin status=%xh, dp=%ph, ofst=%xh, "
1606 "xfer=%xh\n", rval, (void *)dp, ofst, xfer);
1607 rval = QL_FUNCTION_FAILED;
1608 break;
1609 }
1610
1611 /* Write to flash. */
1612 if ((rval = ql_load_fcode(ha, bp, bsize, saddr)) !=
1613 QL_SUCCESS) {
1614 EL(ha, "load_flash status=%x\n", rval);
1615 break;
1616 }
1617 bc -= xfer;
1618 dp += xfer;
1619 saddr += bsize;
1620 ofst = 0;
1621 }
1622
1623 kmem_free(bp, bsize);
1624
1625 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1626
1627 return (rval);
1628 }
1629
1630 /*
1631 * ql_adm_op
1632 * Performs qladm utility operations
1633 *
1634 * Input:
1635 * ha: adapter state pointer.
1636 * arg: driver_op_t structure pointer.
1637 * mode: flags.
1638 *
1639 * Returns:
1640 *
1641 * Context:
1642 * Kernel context.
1643 */
1644 static int
ql_adm_op(ql_adapter_state_t * ha,void * arg,int mode)1645 ql_adm_op(ql_adapter_state_t *ha, void *arg, int mode)
1646 {
1647 ql_adm_op_t dop;
1648 int rval = 0;
1649
1650 if (ddi_copyin(arg, &dop, sizeof (ql_adm_op_t), mode) != 0) {
1651 EL(ha, "failed, driver_op_t ddi_copyin\n");
1652 return (EFAULT);
1653 }
1654
1655 QL_PRINT_9(CE_CONT, "(%d): started, cmd=%xh, buffer=%llx,"
1656 " length=%xh, option=%xh\n", ha->instance, dop.cmd, dop.buffer,
1657 dop.length, dop.option);
1658
1659 switch (dop.cmd) {
1660 case QL_ADAPTER_INFO:
1661 rval = ql_adm_adapter_info(ha, &dop, mode);
1662 break;
1663
1664 case QL_EXTENDED_LOGGING:
1665 rval = ql_adm_extended_logging(ha, &dop);
1666 break;
1667
1668 case QL_LOOP_RESET:
1669 rval = ql_adm_loop_reset(ha);
1670 break;
1671
1672 case QL_DEVICE_LIST:
1673 rval = ql_adm_device_list(ha, &dop, mode);
1674 break;
1675
1676 case QL_PROP_UPDATE_INT:
1677 rval = ql_adm_prop_update_int(ha, &dop, mode);
1678 break;
1679
1680 case QL_UPDATE_PROPERTIES:
1681 rval = ql_adm_update_properties(ha);
1682 break;
1683
1684 case QL_FW_DUMP:
1685 rval = ql_adm_fw_dump(ha, &dop, arg, mode);
1686 break;
1687
1688 case QL_NVRAM_LOAD:
1689 rval = ql_adm_nvram_load(ha, &dop, mode);
1690 break;
1691
1692 case QL_NVRAM_DUMP:
1693 rval = ql_adm_nvram_dump(ha, &dop, mode);
1694 break;
1695
1696 case QL_FLASH_LOAD:
1697 rval = ql_adm_flash_load(ha, &dop, mode);
1698 break;
1699
1700 case QL_VPD_LOAD:
1701 rval = ql_adm_vpd_load(ha, &dop, mode);
1702 break;
1703
1704 case QL_VPD_DUMP:
1705 rval = ql_adm_vpd_dump(ha, &dop, mode);
1706 break;
1707
1708 case QL_VPD_GETTAG:
1709 rval = ql_adm_vpd_gettag(ha, &dop, mode);
1710 break;
1711
1712 case QL_UPD_FWMODULE:
1713 rval = ql_adm_updfwmodule(ha, &dop, mode);
1714 break;
1715
1716 default:
1717 EL(ha, "unsupported driver op cmd: %x\n", dop.cmd);
1718 return (EINVAL);
1719 }
1720
1721 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1722
1723 return (rval);
1724 }
1725
1726 /*
1727 * ql_adm_adapter_info
1728 * Performs qladm QL_ADAPTER_INFO command
1729 *
1730 * Input:
1731 * ha: adapter state pointer.
1732 * dop: ql_adm_op_t structure pointer.
1733 * mode: flags.
1734 *
1735 * Returns:
1736 *
1737 * Context:
1738 * Kernel context.
1739 */
1740 static int
ql_adm_adapter_info(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)1741 ql_adm_adapter_info(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
1742 {
1743 ql_adapter_info_t hba;
1744 uint8_t *dp;
1745 uint32_t length;
1746 int rval, i;
1747
1748 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1749
1750 hba.device_id = ha->device_id;
1751
1752 dp = CFG_IST(ha, CFG_CTRL_24258081) ?
1753 &ha->init_ctrl_blk.cb24.port_name[0] :
1754 &ha->init_ctrl_blk.cb.port_name[0];
1755 bcopy(dp, hba.wwpn, 8);
1756
1757 hba.d_id = ha->d_id.b24;
1758
1759 if (ha->xioctl->fdesc.flash_size == 0 &&
1760 !(CFG_IST(ha, CFG_CTRL_2200) && !ha->subven_id)) {
1761 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1762 EL(ha, "ql_stall_driver failed\n");
1763 return (EBUSY);
1764 }
1765
1766 if ((rval = ql_setup_fcache(ha)) != QL_SUCCESS) {
1767 EL(ha, "ql_setup_flash failed=%xh\n", rval);
1768 if (rval == QL_FUNCTION_TIMEOUT) {
1769 return (EBUSY);
1770 }
1771 return (EIO);
1772 }
1773
1774 /* Resume I/O */
1775 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1776 ql_restart_driver(ha);
1777 } else {
1778 EL(ha, "isp_abort_needed for restart\n");
1779 ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED,
1780 DRIVER_STALL);
1781 }
1782 }
1783 hba.flash_size = ha->xioctl->fdesc.flash_size;
1784
1785 (void) strcpy(hba.driver_ver, QL_VERSION);
1786
1787 (void) sprintf(hba.fw_ver, "%d.%d.%d", ha->fw_major_version,
1788 ha->fw_minor_version, ha->fw_subminor_version);
1789
1790 bzero(hba.fcode_ver, sizeof (hba.fcode_ver));
1791
1792 /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
1793 rval = ddi_getlongprop(DDI_DEV_T_ANY, ha->dip,
1794 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version", (caddr_t)&dp, &i);
1795 length = i;
1796 if (rval != DDI_PROP_SUCCESS) {
1797 EL(ha, "failed, ddi_getlongprop=%xh\n", rval);
1798 } else {
1799 if (length > (uint32_t)sizeof (hba.fcode_ver)) {
1800 length = sizeof (hba.fcode_ver) - 1;
1801 }
1802 bcopy((void *)dp, (void *)hba.fcode_ver, length);
1803 kmem_free(dp, length);
1804 }
1805
1806 if (ddi_copyout((void *)&hba, (void *)(uintptr_t)dop->buffer,
1807 dop->length, mode) != 0) {
1808 EL(ha, "failed, ddi_copyout\n");
1809 return (EFAULT);
1810 }
1811
1812 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1813
1814 return (0);
1815 }
1816
1817 /*
1818 * ql_adm_extended_logging
1819 * Performs qladm QL_EXTENDED_LOGGING command
1820 *
1821 * Input:
1822 * ha: adapter state pointer.
1823 * dop: ql_adm_op_t structure pointer.
1824 *
1825 * Returns:
1826 *
1827 * Context:
1828 * Kernel context.
1829 */
1830 static int
ql_adm_extended_logging(ql_adapter_state_t * ha,ql_adm_op_t * dop)1831 ql_adm_extended_logging(ql_adapter_state_t *ha, ql_adm_op_t *dop)
1832 {
1833 char prop_name[MAX_PROP_LENGTH];
1834 int rval;
1835
1836 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1837
1838 (void) sprintf(prop_name, "hba%d-extended-logging", ha->instance);
1839
1840 /*LINTED [Solaris DDI_DEV_T_NONE Lint warning]*/
1841 rval = ddi_prop_update_int(DDI_DEV_T_NONE, ha->dip, prop_name,
1842 (int)dop->option);
1843 if (rval != DDI_PROP_SUCCESS) {
1844 EL(ha, "failed, prop_update = %xh\n", rval);
1845 return (EINVAL);
1846 } else {
1847 dop->option ?
1848 (ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING) :
1849 (ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING);
1850 }
1851
1852 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1853
1854 return (0);
1855 }
1856
1857 /*
1858 * ql_adm_loop_reset
1859 * Performs qladm QL_LOOP_RESET command
1860 *
1861 * Input:
1862 * ha: adapter state pointer.
1863 *
1864 * Returns:
1865 *
1866 * Context:
1867 * Kernel context.
1868 */
1869 static int
ql_adm_loop_reset(ql_adapter_state_t * ha)1870 ql_adm_loop_reset(ql_adapter_state_t *ha)
1871 {
1872 int rval;
1873
1874 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1875
1876 if (ha->task_daemon_flags & LOOP_DOWN) {
1877 (void) ql_full_login_lip(ha);
1878 } else if ((rval = ql_full_login_lip(ha)) != QL_SUCCESS) {
1879 EL(ha, "failed, ql_initiate_lip=%xh\n", rval);
1880 return (EIO);
1881 }
1882
1883 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1884
1885 return (0);
1886 }
1887
1888 /*
1889 * ql_adm_device_list
1890 * Performs qladm QL_DEVICE_LIST command
1891 *
1892 * Input:
1893 * ha: adapter state pointer.
1894 * dop: ql_adm_op_t structure pointer.
1895 * mode: flags.
1896 *
1897 * Returns:
1898 *
1899 * Context:
1900 * Kernel context.
1901 */
1902 static int
ql_adm_device_list(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)1903 ql_adm_device_list(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
1904 {
1905 ql_device_info_t dev;
1906 ql_link_t *link;
1907 ql_tgt_t *tq;
1908 uint32_t index, cnt;
1909
1910 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1911
1912 cnt = 0;
1913 dev.address = 0xffffffff;
1914
1915 /* Scan port list for requested target and fill in the values */
1916 for (link = NULL, index = 0;
1917 index < DEVICE_HEAD_LIST_SIZE && link == NULL; index++) {
1918 for (link = ha->dev[index].first; link != NULL;
1919 link = link->next) {
1920 tq = link->base_address;
1921
1922 if (!VALID_TARGET_ID(ha, tq->loop_id)) {
1923 continue;
1924 }
1925 if (cnt != dop->option) {
1926 cnt++;
1927 continue;
1928 }
1929 /* fill in the values */
1930 bcopy(tq->port_name, dev.wwpn, 8);
1931 dev.address = tq->d_id.b24;
1932 dev.loop_id = tq->loop_id;
1933 if (tq->flags & TQF_TAPE_DEVICE) {
1934 dev.type = FCT_TAPE;
1935 } else if (tq->flags & TQF_INITIATOR_DEVICE) {
1936 dev.type = FCT_INITIATOR;
1937 } else {
1938 dev.type = FCT_TARGET;
1939 }
1940 break;
1941 }
1942 }
1943
1944 if (ddi_copyout((void *)&dev, (void *)(uintptr_t)dop->buffer,
1945 dop->length, mode) != 0) {
1946 EL(ha, "failed, ddi_copyout\n");
1947 return (EFAULT);
1948 }
1949
1950 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1951
1952 return (0);
1953 }
1954
1955 /*
1956 * ql_adm_update_properties
1957 * Performs qladm QL_UPDATE_PROPERTIES command
1958 *
1959 * Input:
1960 * ha: adapter state pointer.
1961 *
1962 * Returns:
1963 *
1964 * Context:
1965 * Kernel context.
1966 */
1967 static int
ql_adm_update_properties(ql_adapter_state_t * ha)1968 ql_adm_update_properties(ql_adapter_state_t *ha)
1969 {
1970 ql_comb_init_cb_t init_ctrl_blk;
1971 ql_comb_ip_init_cb_t ip_init_ctrl_blk;
1972
1973 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1974
1975 /* Stall driver instance. */
1976 (void) ql_stall_driver(ha, 0);
1977
1978 /* Save init control blocks. */
1979 bcopy(&ha->init_ctrl_blk, &init_ctrl_blk, sizeof (ql_comb_init_cb_t));
1980 bcopy(&ha->ip_init_ctrl_blk, &ip_init_ctrl_blk,
1981 sizeof (ql_comb_ip_init_cb_t));
1982
1983 /* Update PCI configration. */
1984 (void) ql_pci_sbus_config(ha);
1985
1986 /* Get configuration properties. */
1987 (void) ql_nvram_config(ha);
1988
1989 /* Check for init firmware required. */
1990 if (bcmp(&ha->init_ctrl_blk, &init_ctrl_blk,
1991 sizeof (ql_comb_init_cb_t)) != 0 ||
1992 bcmp(&ha->ip_init_ctrl_blk, &ip_init_ctrl_blk,
1993 sizeof (ql_comb_ip_init_cb_t)) != 0) {
1994
1995 EL(ha, "isp_abort_needed\n");
1996 ha->loop_down_timer = LOOP_DOWN_TIMER_START;
1997 TASK_DAEMON_LOCK(ha);
1998 ha->task_daemon_flags |= LOOP_DOWN | ISP_ABORT_NEEDED;
1999 TASK_DAEMON_UNLOCK(ha);
2000 }
2001
2002 /* Update AEN queue. */
2003 if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
2004 ql_enqueue_aen(ha, MBA_PORT_UPDATE, NULL);
2005 }
2006
2007 /* Restart driver instance. */
2008 ql_restart_driver(ha);
2009
2010 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2011
2012 return (0);
2013 }
2014
2015 /*
2016 * ql_adm_prop_update_int
2017 * Performs qladm QL_PROP_UPDATE_INT command
2018 *
2019 * Input:
2020 * ha: adapter state pointer.
2021 * dop: ql_adm_op_t structure pointer.
2022 * mode: flags.
2023 *
2024 * Returns:
2025 *
2026 * Context:
2027 * Kernel context.
2028 */
2029 static int
ql_adm_prop_update_int(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)2030 ql_adm_prop_update_int(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2031 {
2032 char *prop_name;
2033 int rval;
2034
2035 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2036
2037 prop_name = kmem_zalloc(dop->length, KM_SLEEP);
2038 if (prop_name == NULL) {
2039 EL(ha, "failed, kmem_zalloc\n");
2040 return (ENOMEM);
2041 }
2042
2043 if (ddi_copyin((void *)(uintptr_t)dop->buffer, prop_name, dop->length,
2044 mode) != 0) {
2045 EL(ha, "failed, prop_name ddi_copyin\n");
2046 kmem_free(prop_name, dop->length);
2047 return (EFAULT);
2048 }
2049
2050 /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
2051 if ((rval = ddi_prop_update_int(DDI_DEV_T_NONE, ha->dip, prop_name,
2052 (int)dop->option)) != DDI_PROP_SUCCESS) {
2053 EL(ha, "failed, prop_update=%xh\n", rval);
2054 kmem_free(prop_name, dop->length);
2055 return (EINVAL);
2056 }
2057
2058 kmem_free(prop_name, dop->length);
2059
2060 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2061
2062 return (0);
2063 }
2064
2065 /*
2066 * ql_adm_fw_dump
2067 * Performs qladm QL_FW_DUMP command
2068 *
2069 * Input:
2070 * ha: adapter state pointer.
2071 * dop: ql_adm_op_t structure pointer.
2072 * udop: user space ql_adm_op_t structure pointer.
2073 * mode: flags.
2074 *
2075 * Returns:
2076 *
2077 * Context:
2078 * Kernel context.
2079 */
2080 static int
ql_adm_fw_dump(ql_adapter_state_t * ha,ql_adm_op_t * dop,void * udop,int mode)2081 ql_adm_fw_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, void *udop, int mode)
2082 {
2083 caddr_t dmp;
2084
2085 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2086
2087 if (dop->length < ha->risc_dump_size) {
2088 EL(ha, "failed, incorrect length=%xh, size=%xh\n",
2089 dop->length, ha->risc_dump_size);
2090 return (EINVAL);
2091 }
2092
2093 if (ha->ql_dump_state & QL_DUMP_VALID) {
2094 dmp = kmem_zalloc(ha->risc_dump_size, KM_SLEEP);
2095 if (dmp == NULL) {
2096 EL(ha, "failed, kmem_zalloc\n");
2097 return (ENOMEM);
2098 }
2099
2100 dop->length = (uint32_t)ql_ascii_fw_dump(ha, dmp);
2101 if (ddi_copyout((void *)dmp, (void *)(uintptr_t)dop->buffer,
2102 dop->length, mode) != 0) {
2103 EL(ha, "failed, ddi_copyout\n");
2104 kmem_free(dmp, ha->risc_dump_size);
2105 return (EFAULT);
2106 }
2107
2108 kmem_free(dmp, ha->risc_dump_size);
2109 ha->ql_dump_state |= QL_DUMP_UPLOADED;
2110
2111 } else {
2112 EL(ha, "failed, no dump file\n");
2113 dop->length = 0;
2114 }
2115
2116 if (ddi_copyout(dop, udop, sizeof (ql_adm_op_t), mode) != 0) {
2117 EL(ha, "failed, driver_op_t ddi_copyout\n");
2118 return (EFAULT);
2119 }
2120
2121 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2122
2123 return (0);
2124 }
2125
2126 /*
2127 * ql_adm_nvram_dump
2128 * Performs qladm QL_NVRAM_DUMP command
2129 *
2130 * Input:
2131 * ha: adapter state pointer.
2132 * dop: ql_adm_op_t structure pointer.
2133 * mode: flags.
2134 *
2135 * Returns:
2136 *
2137 * Context:
2138 * Kernel context.
2139 */
2140 static int
ql_adm_nvram_dump(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)2141 ql_adm_nvram_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2142 {
2143 int rval;
2144
2145 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2146
2147 if (dop->length < ha->nvram_cache->size) {
2148 EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
2149 ha->nvram_cache->size);
2150 return (EINVAL);
2151 }
2152
2153 if ((rval = ql_nv_util_dump(ha, (void *)(uintptr_t)dop->buffer,
2154 mode)) != 0) {
2155 EL(ha, "failed, ql_nv_util_dump\n");
2156 } else {
2157 /*EMPTY*/
2158 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2159 }
2160
2161 return (rval);
2162 }
2163
2164 /*
2165 * ql_adm_nvram_load
2166 * Performs qladm QL_NVRAM_LOAD command
2167 *
2168 * Input:
2169 * ha: adapter state pointer.
2170 * dop: ql_adm_op_t structure pointer.
2171 * mode: flags.
2172 *
2173 * Returns:
2174 *
2175 * Context:
2176 * Kernel context.
2177 */
2178 static int
ql_adm_nvram_load(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)2179 ql_adm_nvram_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2180 {
2181 int rval;
2182
2183 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2184
2185 if (dop->length < ha->nvram_cache->size) {
2186 EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
2187 ha->nvram_cache->size);
2188 return (EINVAL);
2189 }
2190
2191 if ((rval = ql_nv_util_load(ha, (void *)(uintptr_t)dop->buffer,
2192 mode)) != 0) {
2193 EL(ha, "failed, ql_nv_util_dump\n");
2194 } else {
2195 /*EMPTY*/
2196 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2197 }
2198
2199 return (rval);
2200 }
2201
2202 /*
2203 * ql_adm_flash_load
2204 * Performs qladm QL_FLASH_LOAD command
2205 *
2206 * Input:
2207 * ha: adapter state pointer.
2208 * dop: ql_adm_op_t structure pointer.
2209 * mode: flags.
2210 *
2211 * Returns:
2212 *
2213 * Context:
2214 * Kernel context.
2215 */
2216 static int
ql_adm_flash_load(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)2217 ql_adm_flash_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2218 {
2219 uint8_t *dp;
2220 int rval;
2221
2222 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2223
2224 if ((dp = kmem_zalloc(dop->length, KM_SLEEP)) == NULL) {
2225 EL(ha, "failed, kmem_zalloc\n");
2226 return (ENOMEM);
2227 }
2228
2229 if (ddi_copyin((void *)(uintptr_t)dop->buffer, dp, dop->length,
2230 mode) != 0) {
2231 EL(ha, "ddi_copyin failed\n");
2232 kmem_free(dp, dop->length);
2233 return (EFAULT);
2234 }
2235
2236 if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
2237 EL(ha, "ql_stall_driver failed\n");
2238 kmem_free(dp, dop->length);
2239 return (EBUSY);
2240 }
2241
2242 rval = (CFG_IST(ha, CFG_CTRL_24258081) ?
2243 ql_24xx_load_flash(ha, dp, dop->length, dop->option) :
2244 ql_load_flash(ha, dp, dop->length));
2245
2246 ql_restart_driver(ha);
2247
2248 kmem_free(dp, dop->length);
2249
2250 if (rval != QL_SUCCESS) {
2251 EL(ha, "failed\n");
2252 return (EIO);
2253 }
2254
2255 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2256
2257 return (0);
2258 }
2259
2260 /*
2261 * ql_adm_vpd_dump
2262 * Performs qladm QL_VPD_DUMP command
2263 *
2264 * Input:
2265 * ha: adapter state pointer.
2266 * dop: ql_adm_op_t structure pointer.
2267 * mode: flags.
2268 *
2269 * Returns:
2270 *
2271 * Context:
2272 * Kernel context.
2273 */
2274 static int
ql_adm_vpd_dump(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)2275 ql_adm_vpd_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2276 {
2277 int rval;
2278
2279 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2280
2281 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
2282 EL(ha, "hba does not support VPD\n");
2283 return (EINVAL);
2284 }
2285
2286 if (dop->length < QL_24XX_VPD_SIZE) {
2287 EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
2288 QL_24XX_VPD_SIZE);
2289 return (EINVAL);
2290 }
2291
2292 if ((rval = ql_vpd_dump(ha, (void *)(uintptr_t)dop->buffer, mode))
2293 != 0) {
2294 EL(ha, "failed, ql_vpd_dump\n");
2295 } else {
2296 /*EMPTY*/
2297 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2298 }
2299
2300 return (rval);
2301 }
2302
2303 /*
2304 * ql_adm_vpd_load
2305 * Performs qladm QL_VPD_LOAD command
2306 *
2307 * Input:
2308 * ha: adapter state pointer.
2309 * dop: ql_adm_op_t structure pointer.
2310 * mode: flags.
2311 *
2312 * Returns:
2313 *
2314 * Context:
2315 * Kernel context.
2316 */
2317 static int
ql_adm_vpd_load(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)2318 ql_adm_vpd_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2319 {
2320 int rval;
2321
2322 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2323
2324 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
2325 EL(ha, "hba does not support VPD\n");
2326 return (EINVAL);
2327 }
2328
2329 if (dop->length < QL_24XX_VPD_SIZE) {
2330 EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
2331 QL_24XX_VPD_SIZE);
2332 return (EINVAL);
2333 }
2334
2335 if ((rval = ql_vpd_load(ha, (void *)(uintptr_t)dop->buffer, mode))
2336 != 0) {
2337 EL(ha, "failed, ql_vpd_dump\n");
2338 } else {
2339 /*EMPTY*/
2340 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2341 }
2342
2343 return (rval);
2344 }
2345
2346 /*
2347 * ql_adm_vpd_gettag
2348 * Performs qladm QL_VPD_GETTAG command
2349 *
2350 * Input:
2351 * ha: adapter state pointer.
2352 * dop: ql_adm_op_t structure pointer.
2353 * mode: flags.
2354 *
2355 * Returns:
2356 *
2357 * Context:
2358 * Kernel context.
2359 */
2360 static int
ql_adm_vpd_gettag(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)2361 ql_adm_vpd_gettag(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2362 {
2363 int rval = 0;
2364 uint8_t *lbuf;
2365
2366 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2367
2368 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
2369 EL(ha, "hba does not support VPD\n");
2370 return (EINVAL);
2371 }
2372
2373 if ((lbuf = (uint8_t *)kmem_zalloc(dop->length, KM_SLEEP)) == NULL) {
2374 EL(ha, "mem alloc failure of %xh bytes\n", dop->length);
2375 rval = EFAULT;
2376 } else {
2377 if (ddi_copyin((void *)(uintptr_t)dop->buffer, lbuf,
2378 dop->length, mode) != 0) {
2379 EL(ha, "ddi_copyin failed\n");
2380 kmem_free(lbuf, dop->length);
2381 return (EFAULT);
2382 }
2383
2384 if ((rval = ql_vpd_lookup(ha, lbuf, lbuf, (int32_t)
2385 dop->length)) < 0) {
2386 EL(ha, "failed vpd_lookup\n");
2387 } else {
2388 if (ddi_copyout(lbuf, (void *)(uintptr_t)dop->buffer,
2389 strlen((int8_t *)lbuf)+1, mode) != 0) {
2390 EL(ha, "failed, ddi_copyout\n");
2391 rval = EFAULT;
2392 } else {
2393 rval = 0;
2394 }
2395 }
2396 kmem_free(lbuf, dop->length);
2397 }
2398
2399 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2400
2401 return (rval);
2402 }
2403
2404 /*
2405 * ql_adm_updfwmodule
2406 * Performs qladm QL_UPD_FWMODULE command
2407 *
2408 * Input:
2409 * ha: adapter state pointer.
2410 * dop: ql_adm_op_t structure pointer.
2411 * mode: flags.
2412 *
2413 * Returns:
2414 *
2415 * Context:
2416 * Kernel context.
2417 */
2418 /* ARGSUSED */
2419 static int
ql_adm_updfwmodule(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)2420 ql_adm_updfwmodule(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2421 {
2422 int rval = DDI_SUCCESS;
2423 ql_link_t *link;
2424 ql_adapter_state_t *ha2 = NULL;
2425 uint16_t fw_class = (uint16_t)dop->option;
2426
2427 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2428
2429 /* zero the firmware module reference count */
2430 for (link = ql_hba.first; link != NULL; link = link->next) {
2431 ha2 = link->base_address;
2432 if (fw_class == ha2->fw_class) {
2433 if ((rval = ddi_modclose(ha2->fw_module)) !=
2434 DDI_SUCCESS) {
2435 EL(ha2, "modclose rval=%xh\n", rval);
2436 break;
2437 }
2438 ha2->fw_module = NULL;
2439 }
2440 }
2441
2442 /* reload the f/w modules */
2443 for (link = ql_hba.first; link != NULL; link = link->next) {
2444 ha2 = link->base_address;
2445
2446 if ((fw_class == ha2->fw_class) && (ha2->fw_class == NULL)) {
2447 if ((rval = (int32_t)ql_fwmodule_resolve(ha2)) !=
2448 QL_SUCCESS) {
2449 EL(ha2, "unable to load f/w module: '%x' "
2450 "(rval=%xh)\n", ha2->fw_class, rval);
2451 rval = EFAULT;
2452 } else {
2453 EL(ha2, "f/w module updated: '%x'\n",
2454 ha2->fw_class);
2455 }
2456
2457 EL(ha2, "isp abort needed (%d)\n", ha->instance);
2458
2459 ql_awaken_task_daemon(ha2, NULL, ISP_ABORT_NEEDED, 0);
2460
2461 rval = 0;
2462 }
2463 }
2464
2465 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2466
2467 return (rval);
2468 }
2469