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 2009 QLogic Corporation */
23 
24 /*
25  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
26  * Use is subject to license terms.
27  */
28 
29 #pragma ident	"Copyright 2009 QLogic Corporation; ql_ioctl.c"
30 
31 /*
32  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
33  * Fibre Channel Adapter (FCA) driver IOCTL source file.
34  *
35  * ***********************************************************************
36  * *									**
37  * *				NOTICE					**
38  * *		COPYRIGHT (C) 1996-2009 QLOGIC CORPORATION		**
39  * *			ALL RIGHTS RESERVED				**
40  * *									**
41  * ***********************************************************************
42  *
43  */
44 
45 #include <ql_apps.h>
46 #include <ql_api.h>
47 #include <ql_debug.h>
48 #include <ql_init.h>
49 #include <ql_ioctl.h>
50 #include <ql_mbx.h>
51 #include <ql_xioctl.h>
52 
53 /*
54  * Local Function Prototypes.
55  */
56 static int ql_busy_notification(ql_adapter_state_t *);
57 static int ql_idle_notification(ql_adapter_state_t *);
58 static int ql_get_feature_bits(ql_adapter_state_t *ha, uint16_t *features);
59 static int ql_set_feature_bits(ql_adapter_state_t *ha, uint16_t features);
60 static int ql_set_nvram_adapter_defaults(ql_adapter_state_t *ha);
61 static void ql_load_nvram(ql_adapter_state_t *ha, uint8_t addr,
62     uint16_t value);
63 static int ql_24xx_load_nvram(ql_adapter_state_t *, uint32_t, uint32_t);
64 static int ql_adm_op(ql_adapter_state_t *, void *, int);
65 static int ql_adm_adapter_info(ql_adapter_state_t *, ql_adm_op_t *, int);
66 static int ql_adm_extended_logging(ql_adapter_state_t *, ql_adm_op_t *);
67 static int ql_adm_device_list(ql_adapter_state_t *, ql_adm_op_t *, int);
68 static int ql_adm_update_properties(ql_adapter_state_t *);
69 static int ql_adm_prop_update_int(ql_adapter_state_t *, ql_adm_op_t *, int);
70 static int ql_adm_loop_reset(ql_adapter_state_t *);
71 static int ql_adm_fw_dump(ql_adapter_state_t *, ql_adm_op_t *, void *, int);
72 static int ql_adm_nvram_dump(ql_adapter_state_t *, ql_adm_op_t *, int);
73 static int ql_adm_nvram_load(ql_adapter_state_t *, ql_adm_op_t *, int);
74 static int ql_adm_flash_load(ql_adapter_state_t *, ql_adm_op_t *, int);
75 static int ql_adm_vpd_dump(ql_adapter_state_t *, ql_adm_op_t *, int);
76 static int ql_adm_vpd_load(ql_adapter_state_t *, ql_adm_op_t *, int);
77 static int ql_adm_vpd_gettag(ql_adapter_state_t *, ql_adm_op_t *, int);
78 static int ql_adm_updfwmodule(ql_adapter_state_t *, ql_adm_op_t *, int);
79 static uint8_t *ql_vpd_findtag(ql_adapter_state_t *, uint8_t *, int8_t *);
80 
81 /* ************************************************************************ */
82 /*				cb_ops functions			    */
83 /* ************************************************************************ */
84 
85 /*
86  * ql_open
87  *	opens device
88  *
89  * Input:
90  *	dev_p = device pointer
91  *	flags = open flags
92  *	otype = open type
93  *	cred_p = credentials pointer
94  *
95  * Returns:
96  *	0 = success
97  *
98  * Context:
99  *	Kernel context.
100  */
101 /* ARGSUSED */
102 int
103 ql_open(dev_t *dev_p, int flags, int otyp, cred_t *cred_p)
104 {
105 	ql_adapter_state_t	*ha;
106 	int			rval = 0;
107 
108 	ha = ddi_get_soft_state(ql_state, (int32_t)getminor(*dev_p));
109 	if (ha == NULL) {
110 		QL_PRINT_2(CE_CONT, "failed, no adapter\n");
111 		return (ENXIO);
112 	}
113 
114 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
115 
116 	/* Allow only character opens */
117 	if (otyp != OTYP_CHR) {
118 		QL_PRINT_2(CE_CONT, "(%d): failed, open type\n",
119 		    ha->instance);
120 		return (EINVAL);
121 	}
122 
123 	ADAPTER_STATE_LOCK(ha);
124 	if (flags & FEXCL && ha->flags & QL_OPENED) {
125 		ADAPTER_STATE_UNLOCK(ha);
126 		rval = EBUSY;
127 	} else {
128 		ha->flags |= QL_OPENED;
129 		ADAPTER_STATE_UNLOCK(ha);
130 	}
131 
132 	if (rval != 0) {
133 		EL(ha, "failed, rval = %xh\n", rval);
134 	} else {
135 		/*EMPTY*/
136 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
137 	}
138 	return (rval);
139 }
140 
141 /*
142  * ql_close
143  *	opens device
144  *
145  * Input:
146  *	dev_p = device pointer
147  *	flags = open flags
148  *	otype = open type
149  *	cred_p = credentials pointer
150  *
151  * Returns:
152  *	0 = success
153  *
154  * Context:
155  *	Kernel context.
156  */
157 /* ARGSUSED */
158 int
159 ql_close(dev_t dev, int flags, int otyp, cred_t *cred_p)
160 {
161 	ql_adapter_state_t	*ha;
162 	int			rval = 0;
163 
164 	ha = ddi_get_soft_state(ql_state, (int32_t)getminor(dev));
165 	if (ha == NULL) {
166 		QL_PRINT_2(CE_CONT, "failed, no adapter\n");
167 		return (ENXIO);
168 	}
169 
170 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
171 
172 	if (otyp != OTYP_CHR) {
173 		QL_PRINT_2(CE_CONT, "(%d): failed, open type\n",
174 		    ha->instance);
175 		return (EINVAL);
176 	}
177 
178 	ADAPTER_STATE_LOCK(ha);
179 	ha->flags &= ~QL_OPENED;
180 	ADAPTER_STATE_UNLOCK(ha);
181 
182 	if (rval != 0) {
183 		EL(ha, "failed, rval = %xh\n", rval);
184 	} else {
185 		/*EMPTY*/
186 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
187 	}
188 	return (rval);
189 }
190 
191 /*
192  * ql_ioctl
193  *	control a character device
194  *
195  * Input:
196  *	dev = device number
197  *	cmd = function to perform
198  *	arg = data type varies with request
199  *	mode = flags
200  *	cred_p = credentials pointer
201  *	rval_p = pointer to result value
202  *
203  * Returns:
204  *	0 = success
205  *
206  * Context:
207  *	Kernel context.
208  */
209 /* ARGSUSED */
210 int
211 ql_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p,
212     int *rval_p)
213 {
214 	ql_adapter_state_t	*ha;
215 	int			rval = 0;
216 
217 	if (ddi_in_panic()) {
218 		QL_PRINT_2(CE_CONT, "ql_ioctl: ddi_in_panic exit\n");
219 		return (ENOPROTOOPT);
220 	}
221 
222 	ha = ddi_get_soft_state(ql_state, (int32_t)getminor(dev));
223 	if (ha == NULL)	{
224 		QL_PRINT_2(CE_CONT, "failed, no adapter\n");
225 		return (ENXIO);
226 	}
227 
228 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
229 
230 	/*
231 	 * Quick clean exit for qla2x00 foapi calls which are
232 	 * not supported in qlc.
233 	 */
234 	if (cmd >= QL_FOAPI_START && cmd <= QL_FOAPI_END) {
235 		QL_PRINT_9(CE_CONT, "failed, fo api not supported\n");
236 		return (ENOTTY);
237 	}
238 
239 	/* PWR management busy. */
240 	rval = ql_busy_notification(ha);
241 	if (rval != FC_SUCCESS)	 {
242 		EL(ha, "failed, ql_busy_notification\n");
243 		return (ENXIO);
244 	}
245 
246 	rval = ql_xioctl(ha, cmd, arg, mode, cred_p, rval_p);
247 	if (rval == ENOPROTOOPT || rval == EINVAL) {
248 		switch (cmd) {
249 		case QL_GET_ADAPTER_FEATURE_BITS: {
250 			uint16_t bits;
251 
252 			rval = ql_get_feature_bits(ha, &bits);
253 
254 			if (!rval && ddi_copyout((void *)&bits, (void *)arg,
255 			    sizeof (bits), mode)) {
256 				rval = EFAULT;
257 			}
258 			break;
259 		}
260 
261 		case QL_SET_ADAPTER_FEATURE_BITS: {
262 			uint16_t bits;
263 
264 			if (ddi_copyin((void *)arg, (void *)&bits,
265 			    sizeof (bits), mode)) {
266 				rval = EFAULT;
267 				break;
268 			}
269 
270 			rval = ql_set_feature_bits(ha, bits);
271 			break;
272 		}
273 
274 		case QL_SET_ADAPTER_NVRAM_DEFAULTS:
275 			rval = ql_set_nvram_adapter_defaults(ha);
276 			break;
277 
278 		case QL_UTIL_LOAD:
279 			rval = ql_nv_util_load(ha, (void *)arg, mode);
280 			break;
281 
282 		case QL_UTIL_DUMP:
283 			rval = ql_nv_util_dump(ha, (void *)arg, mode);
284 			break;
285 
286 		case QL_ADM_OP:
287 			rval = ql_adm_op(ha, (void *)arg, mode);
288 			break;
289 
290 		default:
291 			EL(ha, "unknown command = %d\n", cmd);
292 			rval = ENOTTY;
293 			break;
294 		}
295 	}
296 
297 	/* PWR management idle. */
298 	(void) ql_idle_notification(ha);
299 
300 	if (rval != 0) {
301 		EL(ha, "failed, rval = %d\n", rval);
302 	} else {
303 		/*EMPTY*/
304 		QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
305 	}
306 	return (rval);
307 }
308 
309 /*
310  * ql_busy_notification
311  *	Adapter busy notification.
312  *
313  * Input:
314  *	ha = adapter state pointer.
315  *
316  * Returns:
317  *	FC_SUCCESS
318  *	FC_FAILURE
319  *
320  * Context:
321  *	Kernel context.
322  */
323 static int
324 ql_busy_notification(ql_adapter_state_t *ha)
325 {
326 	if (!ha->pm_capable) {
327 		return (FC_SUCCESS);
328 	}
329 
330 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
331 
332 	QL_PM_LOCK(ha);
333 	ha->busy++;
334 	QL_PM_UNLOCK(ha);
335 
336 	if (pm_busy_component(ha->dip, 0) != DDI_SUCCESS) {
337 		QL_PM_LOCK(ha);
338 		ha->busy--;
339 		QL_PM_UNLOCK(ha);
340 
341 		EL(ha, "pm_busy_component failed = %xh\n", FC_FAILURE);
342 		return (FC_FAILURE);
343 	}
344 
345 	QL_PM_LOCK(ha);
346 	if (ha->power_level != PM_LEVEL_D0) {
347 		ASSERT(ha->power_level == PM_LEVEL_D3);
348 
349 		QL_PM_UNLOCK(ha);
350 		if (pm_raise_power(ha->dip, 0, 1) != DDI_SUCCESS) {
351 			QL_PM_LOCK(ha);
352 			ha->busy--;
353 			QL_PM_UNLOCK(ha);
354 			return (FC_FAILURE);
355 		}
356 	} else {
357 		QL_PM_UNLOCK(ha);
358 	}
359 
360 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
361 
362 	return (FC_SUCCESS);
363 }
364 
365 /*
366  * ql_idle_notification
367  *	Adapter idle notification.
368  *
369  * Input:
370  *	ha = adapter state pointer.
371  *
372  * Returns:
373  *	FC_SUCCESS
374  *	FC_FAILURE
375  *
376  * Context:
377  *	Kernel context.
378  */
379 static int
380 ql_idle_notification(ql_adapter_state_t *ha)
381 {
382 	if (!ha->pm_capable) {
383 		return (FC_SUCCESS);
384 	}
385 
386 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
387 
388 	if (pm_idle_component(ha->dip, 0) != DDI_SUCCESS) {
389 		EL(ha, "pm_idle_component failed = %xh\n", FC_FAILURE);
390 		return (FC_FAILURE);
391 	}
392 
393 	QL_PM_LOCK(ha);
394 	ASSERT(ha->busy > 0);
395 	ha->busy--;
396 	QL_PM_UNLOCK(ha);
397 
398 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
399 
400 	return (FC_SUCCESS);
401 }
402 
403 /*
404  * Get adapter feature bits from NVRAM
405  */
406 static int
407 ql_get_feature_bits(ql_adapter_state_t *ha, uint16_t *features)
408 {
409 	int			count;
410 	volatile uint16_t	data;
411 	uint32_t		nv_cmd;
412 	uint32_t		start_addr;
413 	int			rval;
414 	uint32_t		offset = offsetof(nvram_t, adapter_features);
415 
416 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
417 
418 	if ((CFG_IST(ha, CFG_CTRL_242581)) == 0) {
419 		EL(ha, "Not supported for 24xx\n");
420 		return (EINVAL);
421 	}
422 
423 	/*
424 	 * The offset can't be greater than max of 8 bits and
425 	 * the following code breaks if the offset isn't at
426 	 * 2 byte boundary.
427 	 */
428 	ASSERT(offset <= 0xFF && (offset & 0x1) == 0);
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_242581)) {
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
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_242581)) {
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
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
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_81XX))) {
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
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, nv_size, *lptr, data32;
938 	nvram_t		*nptr;
939 	int		rval;
940 
941 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
942 
943 	nv_size = (uint32_t)(CFG_IST(ha, CFG_CTRL_242581) ?
944 	    sizeof (nvram_24xx_t) : sizeof (nvram_t));
945 
946 	if ((nv = kmem_zalloc(nv_size, KM_SLEEP)) == NULL) {
947 		EL(ha, "failed, kmem_zalloc\n");
948 		return (ENOMEM);
949 	}
950 
951 	if (ddi_copyin(bp, nv, nv_size, mode) != 0) {
952 		EL(ha, "Buffer copy failed\n");
953 		kmem_free(nv, nv_size);
954 		return (EFAULT);
955 	}
956 
957 	/* See if the buffer passed to us looks sane */
958 	nptr = (nvram_t *)nv;
959 	if (nptr->id[0] != 'I' || nptr->id[1] != 'S' || nptr->id[2] != 'P' ||
960 	    nptr->id[3] != ' ') {
961 		EL(ha, "failed, buffer sanity check\n");
962 		kmem_free(nv, nv_size);
963 		return (EINVAL);
964 	}
965 
966 	/* Quiesce I/O */
967 	if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
968 		EL(ha, "ql_stall_driver failed\n");
969 		kmem_free(nv, nv_size);
970 		return (EBUSY);
971 	}
972 
973 	rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
974 	if (rval != QL_SUCCESS) {
975 		EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
976 		kmem_free(nv, nv_size);
977 		ql_restart_driver(ha);
978 		return (EIO);
979 	}
980 
981 	/* Load NVRAM. */
982 	if (CFG_IST(ha, CFG_CTRL_2581)) {
983 		GLOBAL_HW_UNLOCK();
984 		start_addr &= ~ha->flash_data_addr;
985 		start_addr <<= 2;
986 		if ((rval = ql_r_m_w_flash(ha, bp, nv_size, start_addr,
987 		    mode)) != QL_SUCCESS) {
988 			EL(ha, "nvram load failed, rval = %0xh\n", rval);
989 		}
990 		GLOBAL_HW_LOCK();
991 	} else if (CFG_IST(ha, CFG_CTRL_2422)) {
992 		lptr = (uint32_t *)nv;
993 		for (cnt = 0; cnt < nv_size / 4; cnt++) {
994 			data32 = *lptr++;
995 			LITTLE_ENDIAN_32(&data32);
996 			rval = ql_24xx_load_nvram(ha, cnt + start_addr,
997 			    data32);
998 			if (rval != QL_SUCCESS) {
999 				EL(ha, "failed, 24xx_load_nvram=%xh\n", rval);
1000 				break;
1001 			}
1002 		}
1003 	} else {
1004 		wptr = (uint16_t *)nv;
1005 		for (cnt = 0; cnt < nv_size / 2; cnt++) {
1006 			data = *wptr++;
1007 			LITTLE_ENDIAN_16(&data);
1008 			ql_load_nvram(ha, (uint8_t)(cnt + start_addr), data);
1009 		}
1010 	}
1011 
1012 	kmem_free(nv, nv_size);
1013 	ql_release_nvram(ha);
1014 	ql_restart_driver(ha);
1015 
1016 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1017 
1018 	if (rval == QL_SUCCESS) {
1019 		return (0);
1020 	}
1021 
1022 	return (EFAULT);
1023 }
1024 
1025 /*
1026  * ql_nv_util_dump
1027  *	Dumps NVRAM to application.
1028  *
1029  * Input:
1030  *	ha = adapter state pointer.
1031  *	bp = user buffer address.
1032  *
1033  * Returns:
1034  *
1035  * Context:
1036  *	Kernel context.
1037  */
1038 int
1039 ql_nv_util_dump(ql_adapter_state_t *ha, void *bp, int mode)
1040 {
1041 	uint32_t	cnt, nv_size;
1042 	void		*nv;
1043 	uint32_t	start_addr;
1044 	int		rval2, rval = 0;
1045 
1046 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1047 
1048 	nv_size = (uint32_t)(CFG_IST(ha, CFG_CTRL_242581) ?
1049 	    sizeof (nvram_24xx_t) : sizeof (nvram_t));
1050 
1051 	if ((nv = kmem_zalloc(nv_size, KM_SLEEP)) == NULL) {
1052 		EL(ha, "failed, kmem_zalloc\n");
1053 		return (ENOMEM);
1054 	}
1055 
1056 	/* Quiesce I/O */
1057 	if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1058 		EL(ha, "ql_stall_driver failed\n");
1059 		kmem_free(nv, nv_size);
1060 		return (EBUSY);
1061 	}
1062 
1063 	if ((rval2 = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA)) !=
1064 	    QL_SUCCESS) {
1065 		EL(ha, "failed, ql_lock_nvram=%xh\n", rval2);
1066 		kmem_free(nv, nv_size);
1067 		ql_restart_driver(ha);
1068 		return (EIO);
1069 	}
1070 
1071 	/* Dump NVRAM. */
1072 	if (CFG_IST(ha, CFG_CTRL_242581)) {
1073 
1074 		uint32_t	*lptr = (uint32_t *)nv;
1075 
1076 		for (cnt = 0; cnt < nv_size / 4; cnt++) {
1077 			rval2 = ql_24xx_read_flash(ha, start_addr++, lptr);
1078 			if (rval2 != QL_SUCCESS) {
1079 				EL(ha, "read_flash failed=%xh\n", rval2);
1080 				rval = EAGAIN;
1081 				break;
1082 			}
1083 
1084 			LITTLE_ENDIAN_32(lptr);
1085 			lptr++;
1086 		}
1087 	} else {
1088 		uint16_t	data;
1089 		uint16_t	*wptr = (uint16_t *)nv;
1090 
1091 		for (cnt = 0; cnt < nv_size / 2; cnt++) {
1092 			data = (uint16_t)ql_get_nvram_word(ha, cnt +
1093 			    start_addr);
1094 			LITTLE_ENDIAN_16(&data);
1095 			*wptr++ = data;
1096 		}
1097 	}
1098 
1099 	ql_release_nvram(ha);
1100 	ql_restart_driver(ha);
1101 
1102 	if (rval != 0) {
1103 		EL(ha, "failed to dump nvram\n");
1104 		kmem_free(nv, nv_size);
1105 		return (rval);
1106 	}
1107 
1108 	if (ddi_copyout(nv, bp, nv_size, mode) != 0) {
1109 		EL(ha, "Buffer copy failed\n");
1110 		kmem_free(nv, nv_size);
1111 		return (EFAULT);
1112 	}
1113 
1114 	kmem_free(nv, nv_size);
1115 
1116 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1117 
1118 	return (0);
1119 }
1120 
1121 /*
1122  * ql_vpd_load
1123  *	Loads VPD from application.
1124  *
1125  * Input:
1126  *	ha = adapter state pointer.
1127  *	bp = user buffer address.
1128  *
1129  * Returns:
1130  *
1131  * Context:
1132  *	Kernel context.
1133  */
1134 int
1135 ql_vpd_load(ql_adapter_state_t *ha, void *bp, int mode)
1136 {
1137 	uint8_t		cnt;
1138 	uint8_t		*vpd, *vpdptr, *vbuf;
1139 	uint32_t	start_addr, vpd_size, *lptr, data32;
1140 	int		rval;
1141 
1142 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1143 
1144 	if ((CFG_IST(ha, CFG_CTRL_242581)) == 0) {
1145 		EL(ha, "unsupported adapter feature\n");
1146 		return (ENOTSUP);
1147 	}
1148 
1149 	vpd_size = QL_24XX_VPD_SIZE;
1150 
1151 	if ((vpd = kmem_zalloc(vpd_size, KM_SLEEP)) == NULL) {
1152 		EL(ha, "failed, kmem_zalloc\n");
1153 		return (ENOMEM);
1154 	}
1155 
1156 	if (ddi_copyin(bp, vpd, vpd_size, mode) != 0) {
1157 		EL(ha, "Buffer copy failed\n");
1158 		kmem_free(vpd, vpd_size);
1159 		return (EFAULT);
1160 	}
1161 
1162 	/* Sanity check the user supplied data via checksum */
1163 	if ((vpdptr = ql_vpd_findtag(ha, vpd, "RV")) == NULL) {
1164 		EL(ha, "vpd RV tag missing\n");
1165 		kmem_free(vpd, vpd_size);
1166 		return (EINVAL);
1167 	}
1168 
1169 	vpdptr += 3;
1170 	cnt = 0;
1171 	vbuf = vpd;
1172 	while (vbuf <= vpdptr) {
1173 		cnt += *vbuf++;
1174 	}
1175 	if (cnt != 0) {
1176 		EL(ha, "mismatched checksum, cal=%xh, passed=%xh\n",
1177 		    (uint8_t)cnt, (uintptr_t)vpdptr);
1178 		kmem_free(vpd, vpd_size);
1179 		return (EINVAL);
1180 	}
1181 
1182 	/* Quiesce I/O */
1183 	if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1184 		EL(ha, "ql_stall_driver failed\n");
1185 		kmem_free(vpd, vpd_size);
1186 		return (EBUSY);
1187 	}
1188 
1189 	rval = ql_lock_nvram(ha, &start_addr, LNF_VPD_DATA);
1190 	if (rval != QL_SUCCESS) {
1191 		EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
1192 		kmem_free(vpd, vpd_size);
1193 		ql_restart_driver(ha);
1194 		return (EIO);
1195 	}
1196 
1197 	/* Load VPD. */
1198 	if (CFG_IST(ha, CFG_CTRL_2581)) {
1199 		GLOBAL_HW_UNLOCK();
1200 		start_addr &= ~ha->flash_data_addr;
1201 		start_addr <<= 2;
1202 		if ((rval = ql_r_m_w_flash(ha, bp, vpd_size, start_addr,
1203 		    mode)) != QL_SUCCESS) {
1204 			EL(ha, "vpd load error: %xh\n", rval);
1205 		}
1206 		GLOBAL_HW_LOCK();
1207 	} else {
1208 		lptr = (uint32_t *)vpd;
1209 		for (cnt = 0; cnt < vpd_size / 4; cnt++) {
1210 			data32 = *lptr++;
1211 			LITTLE_ENDIAN_32(&data32);
1212 			rval = ql_24xx_load_nvram(ha, cnt + start_addr,
1213 			    data32);
1214 			if (rval != QL_SUCCESS) {
1215 				EL(ha, "failed, 24xx_load_nvram=%xh\n", rval);
1216 				break;
1217 			}
1218 		}
1219 	}
1220 
1221 	kmem_free(vpd, vpd_size);
1222 
1223 	/* Update the vcache */
1224 	CACHE_LOCK(ha);
1225 
1226 	if (rval != QL_SUCCESS) {
1227 		EL(ha, "failed, load\n");
1228 	} else if ((ha->vcache == NULL) && ((ha->vcache =
1229 	    kmem_zalloc(vpd_size, KM_SLEEP)) == NULL)) {
1230 		EL(ha, "failed, kmem_zalloc2\n");
1231 	} else if (ddi_copyin(bp, ha->vcache, vpd_size, mode) != 0) {
1232 		EL(ha, "Buffer copy2 failed\n");
1233 		kmem_free(ha->vcache, vpd_size);
1234 		ha->vcache = NULL;
1235 	}
1236 
1237 	CACHE_UNLOCK(ha);
1238 
1239 	ql_release_nvram(ha);
1240 	ql_restart_driver(ha);
1241 
1242 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1243 
1244 	if (rval == QL_SUCCESS) {
1245 		return (0);
1246 	}
1247 
1248 	return (EFAULT);
1249 }
1250 
1251 /*
1252  * ql_vpd_dump
1253  *	Dumps VPD to application buffer.
1254  *
1255  * Input:
1256  *	ha = adapter state pointer.
1257  *	bp = user buffer address.
1258  *
1259  * Returns:
1260  *
1261  * Context:
1262  *	Kernel context.
1263  */
1264 int
1265 ql_vpd_dump(ql_adapter_state_t *ha, void *bp, int mode)
1266 {
1267 	uint8_t		cnt;
1268 	void		*vpd;
1269 	uint32_t	start_addr, vpd_size, *lptr;
1270 	int		rval = 0;
1271 
1272 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1273 
1274 	if ((CFG_IST(ha, CFG_CTRL_242581)) == 0) {
1275 		EL(ha, "unsupported adapter feature\n");
1276 		return (EACCES);
1277 	}
1278 
1279 	vpd_size = QL_24XX_VPD_SIZE;
1280 
1281 	CACHE_LOCK(ha);
1282 
1283 	if (ha->vcache != NULL) {
1284 		/* copy back the vpd cache data */
1285 		if (ddi_copyout(ha->vcache, bp, vpd_size, mode) != 0) {
1286 			EL(ha, "Buffer copy failed\n");
1287 			rval = EFAULT;
1288 		}
1289 		CACHE_UNLOCK(ha);
1290 		return (rval);
1291 	}
1292 
1293 	if ((vpd = kmem_zalloc(vpd_size, KM_SLEEP)) == NULL) {
1294 		CACHE_UNLOCK(ha);
1295 		EL(ha, "failed, kmem_zalloc\n");
1296 		return (ENOMEM);
1297 	}
1298 
1299 	/* Quiesce I/O */
1300 	if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1301 		CACHE_UNLOCK(ha);
1302 		EL(ha, "ql_stall_driver failed\n");
1303 		kmem_free(vpd, vpd_size);
1304 		return (EBUSY);
1305 	}
1306 
1307 	rval = ql_lock_nvram(ha, &start_addr, LNF_VPD_DATA);
1308 	if (rval != QL_SUCCESS) {
1309 		CACHE_UNLOCK(ha);
1310 		EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
1311 		kmem_free(vpd, vpd_size);
1312 		ql_restart_driver(ha);
1313 		return (EIO);
1314 	}
1315 
1316 	/* Dump VPD. */
1317 	lptr = (uint32_t *)vpd;
1318 
1319 	for (cnt = 0; cnt < vpd_size / 4; cnt++) {
1320 		rval = ql_24xx_read_flash(ha, start_addr++, lptr);
1321 		if (rval != QL_SUCCESS) {
1322 			EL(ha, "read_flash failed=%xh\n", rval);
1323 			rval = EAGAIN;
1324 			break;
1325 		}
1326 		LITTLE_ENDIAN_32(lptr);
1327 		lptr++;
1328 	}
1329 
1330 	ql_release_nvram(ha);
1331 	ql_restart_driver(ha);
1332 
1333 	if (ddi_copyout(vpd, bp, vpd_size, mode) != 0) {
1334 		CACHE_UNLOCK(ha);
1335 		EL(ha, "Buffer copy failed\n");
1336 		kmem_free(vpd, vpd_size);
1337 		return (EFAULT);
1338 	}
1339 
1340 	ha->vcache = vpd;
1341 
1342 	CACHE_UNLOCK(ha);
1343 
1344 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1345 
1346 	if (rval != QL_SUCCESS) {
1347 		return (EFAULT);
1348 	} else {
1349 		return (0);
1350 	}
1351 }
1352 
1353 /*
1354  * ql_vpd_findtag
1355  *	Search the passed vpd buffer for the requested VPD tag type.
1356  *
1357  * Input:
1358  *	ha	= adapter state pointer.
1359  *	vpdbuf	= Pointer to start of the buffer to search
1360  *	op	= VPD opcode to find (must be NULL terminated).
1361  *
1362  * Returns:
1363  *	Pointer to the opcode in the buffer if opcode found.
1364  *	NULL if opcode is not found.
1365  *
1366  * Context:
1367  *	Kernel context.
1368  */
1369 static uint8_t *
1370 ql_vpd_findtag(ql_adapter_state_t *ha, uint8_t *vpdbuf, int8_t *opcode)
1371 {
1372 	uint8_t		*vpd = vpdbuf;
1373 	uint8_t		*end = vpdbuf + QL_24XX_VPD_SIZE;
1374 	uint32_t	found = 0;
1375 
1376 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1377 
1378 	if (vpdbuf == NULL || opcode == NULL) {
1379 		EL(ha, "null parameter passed!\n");
1380 		return (NULL);
1381 	}
1382 
1383 	while (vpd < end) {
1384 
1385 		/* check for end of vpd */
1386 		if (vpd[0] == VPD_TAG_END) {
1387 			if (opcode[0] == VPD_TAG_END) {
1388 				found = 1;
1389 			} else {
1390 				found = 0;
1391 			}
1392 			break;
1393 		}
1394 
1395 		/* check opcode */
1396 		if (bcmp(opcode, vpd, strlen(opcode)) == 0) {
1397 			/* found opcode requested */
1398 			found = 1;
1399 			break;
1400 		}
1401 
1402 		/*
1403 		 * Didn't find the opcode, so calculate start of
1404 		 * next tag. Depending on the current tag type,
1405 		 * the length field can be 1 or 2 bytes
1406 		 */
1407 		if (!(strncmp((char *)vpd, (char *)VPD_TAG_PRODID, 1))) {
1408 			vpd += (vpd[2] << 8) + vpd[1] + 3;
1409 		} else if (*vpd == VPD_TAG_LRT || *vpd == VPD_TAG_LRTC) {
1410 			vpd += 3;
1411 		} else {
1412 			vpd += vpd[2] +3;
1413 		}
1414 	}
1415 
1416 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1417 
1418 	return (found == 1 ? vpd : NULL);
1419 }
1420 
1421 /*
1422  * ql_vpd_lookup
1423  *	Return the VPD data for the request VPD tag
1424  *
1425  * Input:
1426  *	ha	= adapter state pointer.
1427  *	opcode	= VPD opcode to find (must be NULL terminated).
1428  *	bp	= Pointer to returned data buffer.
1429  *	bplen	= Length of returned data buffer.
1430  *
1431  * Returns:
1432  *	Length of data copied into returned data buffer.
1433  *		>0 = VPD data field (NULL terminated)
1434  *		 0 = no data.
1435  *		-1 = Could not find opcode in vpd buffer / error.
1436  *
1437  * Context:
1438  *	Kernel context.
1439  *
1440  * NB: The opcode buffer and the bp buffer *could* be the same buffer!
1441  *
1442  */
1443 int32_t
1444 ql_vpd_lookup(ql_adapter_state_t *ha, uint8_t *opcode, uint8_t *bp,
1445     int32_t bplen)
1446 {
1447 	uint8_t		*vpd;
1448 	uint8_t		*vpdbuf;
1449 	int32_t		len = -1;
1450 
1451 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1452 
1453 	if (opcode == NULL || bp == NULL || bplen < 1) {
1454 		EL(ha, "invalid parameter passed: opcode=%ph, "
1455 		    "bp=%ph, bplen=%xh\n", opcode, bp, bplen);
1456 		return (len);
1457 	}
1458 
1459 	if ((CFG_IST(ha, CFG_CTRL_242581)) == 0) {
1460 		return (len);
1461 	}
1462 
1463 	if ((vpdbuf = (uint8_t *)kmem_zalloc(QL_24XX_VPD_SIZE,
1464 	    KM_SLEEP)) == NULL) {
1465 		EL(ha, "unable to allocate vpd memory\n");
1466 		return (len);
1467 	}
1468 
1469 	if ((ql_vpd_dump(ha, vpdbuf, (int)FKIOCTL)) != 0) {
1470 		kmem_free(vpdbuf, QL_24XX_VPD_SIZE);
1471 		EL(ha, "unable to retrieve VPD data\n");
1472 		return (len);
1473 	}
1474 
1475 	if ((vpd = ql_vpd_findtag(ha, vpdbuf, (int8_t *)opcode)) != NULL) {
1476 		/*
1477 		 * Found the tag
1478 		 */
1479 		if (*opcode == VPD_TAG_END || *opcode == VPD_TAG_LRT ||
1480 		    *opcode == VPD_TAG_LRTC) {
1481 			/*
1482 			 * we found it, but the tag doesn't have a data
1483 			 * field.
1484 			 */
1485 			len = 0;
1486 		} else if (!(strncmp((char *)vpd, (char *)
1487 		    VPD_TAG_PRODID, 1))) {
1488 			len = vpd[2] << 8;
1489 			len += vpd[1];
1490 		} else {
1491 			len = vpd[2];
1492 		}
1493 
1494 		/*
1495 		 * make sure that the vpd len doesn't exceed the
1496 		 * vpd end
1497 		 */
1498 		if (vpd+len > vpdbuf + QL_24XX_VPD_SIZE) {
1499 			EL(ha, "vpd tag len (%xh) exceeds vpd buffer "
1500 			    "length\n", len);
1501 			len = -1;
1502 		}
1503 	}
1504 
1505 	if (len >= 0) {
1506 		/*
1507 		 * make sure we don't exceed callers buffer space len
1508 		 */
1509 		if (len > bplen) {
1510 			len = bplen-1;
1511 		}
1512 
1513 		/* copy the data back */
1514 		(void) strncpy((int8_t *)bp, (int8_t *)(vpd+3), (int64_t)len);
1515 		bp[len] = NULL;
1516 	} else {
1517 		/* error -- couldn't find tag */
1518 		bp[0] = NULL;
1519 		if (opcode[1] != NULL) {
1520 			EL(ha, "unable to find tag '%s'\n", opcode);
1521 		} else {
1522 			EL(ha, "unable to find tag '%xh'\n", opcode[0]);
1523 		}
1524 	}
1525 
1526 	kmem_free(vpdbuf, QL_24XX_VPD_SIZE);
1527 
1528 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1529 
1530 	return (len);
1531 }
1532 
1533 /*
1534  * ql_r_m_w_flash
1535  *	Read modify write from user space to flash.
1536  *
1537  * Input:
1538  *	ha:	adapter state pointer.
1539  *	dp:	source byte pointer.
1540  *	bc:	byte count.
1541  *	faddr:	flash byte address.
1542  *	mode:	flags.
1543  *
1544  * Returns:
1545  *	ql local function return status code.
1546  *
1547  * Context:
1548  *	Kernel context.
1549  */
1550 int
1551 ql_r_m_w_flash(ql_adapter_state_t *ha, caddr_t dp, uint32_t bc, uint32_t faddr,
1552     int mode)
1553 {
1554 	uint8_t		*bp;
1555 	uint32_t	xfer, bsize, saddr, ofst;
1556 	int		rval = 0;
1557 
1558 	QL_PRINT_9(CE_CONT, "(%d): started, dp=%ph, faddr=%xh, bc=%xh\n",
1559 	    ha->instance, (void *)dp, faddr, bc);
1560 
1561 	bsize = ha->xioctl->fdesc.block_size;
1562 	saddr = faddr & ~(bsize - 1);
1563 	ofst = faddr & (bsize - 1);
1564 
1565 	if ((bp = kmem_zalloc(bsize, KM_SLEEP)) == NULL) {
1566 		EL(ha, "kmem_zalloc=null\n");
1567 		return (QL_MEMORY_ALLOC_FAILED);
1568 	}
1569 
1570 	while (bc) {
1571 		xfer = bc > bsize ? bsize : bc;
1572 		if (ofst + xfer > bsize) {
1573 			xfer = bsize - ofst;
1574 		}
1575 		QL_PRINT_9(CE_CONT, "(%d): dp=%ph, saddr=%xh, bc=%xh, "
1576 		    "ofst=%xh, xfer=%xh\n", ha->instance, (void *)dp, saddr,
1577 		    bc, ofst, xfer);
1578 
1579 		if (ofst || xfer < bsize) {
1580 			/* Dump Flash sector. */
1581 			if ((rval = ql_dump_fcode(ha, bp, bsize, saddr)) !=
1582 			    QL_SUCCESS) {
1583 				EL(ha, "dump_flash status=%x\n", rval);
1584 				break;
1585 			}
1586 		}
1587 
1588 		/* Set new data. */
1589 		if ((rval = ddi_copyin(dp, (caddr_t)(bp + ofst), xfer,
1590 		    mode)) != 0) {
1591 			EL(ha, "ddi_copyin status=%xh, dp=%ph, ofst=%xh, "
1592 			    "xfer=%xh\n", rval, (void *)dp, ofst, xfer);
1593 			rval = QL_FUNCTION_FAILED;
1594 			break;
1595 		}
1596 
1597 		/* Write to flash. */
1598 		if ((rval = ql_load_fcode(ha, bp, bsize, saddr)) !=
1599 		    QL_SUCCESS) {
1600 			EL(ha, "load_flash status=%x\n", rval);
1601 			break;
1602 		}
1603 		bc -= xfer;
1604 		dp += xfer;
1605 		saddr += bsize;
1606 		ofst = 0;
1607 	}
1608 
1609 	kmem_free(bp, bsize);
1610 
1611 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1612 
1613 	return (rval);
1614 }
1615 
1616 /*
1617  * ql_adm_op
1618  *	Performs qladm utility operations
1619  *
1620  * Input:
1621  *	ha:	adapter state pointer.
1622  *	arg:	driver_op_t structure pointer.
1623  *	mode:	flags.
1624  *
1625  * Returns:
1626  *
1627  * Context:
1628  *	Kernel context.
1629  */
1630 static int
1631 ql_adm_op(ql_adapter_state_t *ha, void *arg, int mode)
1632 {
1633 	ql_adm_op_t		dop;
1634 	int			rval = 0;
1635 
1636 	if (ddi_copyin(arg, &dop, sizeof (ql_adm_op_t), mode) != 0) {
1637 		EL(ha, "failed, driver_op_t ddi_copyin\n");
1638 		return (EFAULT);
1639 	}
1640 
1641 	QL_PRINT_9(CE_CONT, "(%d): started, cmd=%xh, buffer=%llx,"
1642 	    " length=%xh, option=%xh\n", ha->instance, dop.cmd, dop.buffer,
1643 	    dop.length, dop.option);
1644 
1645 	switch (dop.cmd) {
1646 	case QL_ADAPTER_INFO:
1647 		rval = ql_adm_adapter_info(ha, &dop, mode);
1648 		break;
1649 
1650 	case QL_EXTENDED_LOGGING:
1651 		rval = ql_adm_extended_logging(ha, &dop);
1652 		break;
1653 
1654 	case QL_LOOP_RESET:
1655 		rval = ql_adm_loop_reset(ha);
1656 		break;
1657 
1658 	case QL_DEVICE_LIST:
1659 		rval = ql_adm_device_list(ha, &dop, mode);
1660 		break;
1661 
1662 	case QL_PROP_UPDATE_INT:
1663 		rval = ql_adm_prop_update_int(ha, &dop, mode);
1664 		break;
1665 
1666 	case QL_UPDATE_PROPERTIES:
1667 		rval = ql_adm_update_properties(ha);
1668 		break;
1669 
1670 	case QL_FW_DUMP:
1671 		rval = ql_adm_fw_dump(ha, &dop, arg, mode);
1672 		break;
1673 
1674 	case QL_NVRAM_LOAD:
1675 		rval = ql_adm_nvram_load(ha, &dop, mode);
1676 		break;
1677 
1678 	case QL_NVRAM_DUMP:
1679 		rval = ql_adm_nvram_dump(ha, &dop, mode);
1680 		break;
1681 
1682 	case QL_FLASH_LOAD:
1683 		rval = ql_adm_flash_load(ha, &dop, mode);
1684 		break;
1685 
1686 	case QL_VPD_LOAD:
1687 		rval = ql_adm_vpd_load(ha, &dop, mode);
1688 		break;
1689 
1690 	case QL_VPD_DUMP:
1691 		rval = ql_adm_vpd_dump(ha, &dop, mode);
1692 		break;
1693 
1694 	case QL_VPD_GETTAG:
1695 		rval = ql_adm_vpd_gettag(ha, &dop, mode);
1696 		break;
1697 
1698 	case QL_UPD_FWMODULE:
1699 		rval = ql_adm_updfwmodule(ha, &dop, mode);
1700 		break;
1701 
1702 	default:
1703 		EL(ha, "unsupported driver op cmd: %x\n", dop.cmd);
1704 		return (EINVAL);
1705 	}
1706 
1707 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1708 
1709 	return (rval);
1710 }
1711 
1712 /*
1713  * ql_adm_adapter_info
1714  *	Performs qladm QL_ADAPTER_INFO command
1715  *
1716  * Input:
1717  *	ha:	adapter state pointer.
1718  *	dop:	ql_adm_op_t structure pointer.
1719  *	mode:	flags.
1720  *
1721  * Returns:
1722  *
1723  * Context:
1724  *	Kernel context.
1725  */
1726 static int
1727 ql_adm_adapter_info(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
1728 {
1729 	ql_adapter_info_t	hba;
1730 	uint8_t			*dp;
1731 	uint32_t		length;
1732 	int			rval, i;
1733 
1734 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1735 
1736 	hba.device_id = ha->device_id;
1737 
1738 	dp = CFG_IST(ha, CFG_CTRL_242581) ?
1739 	    &ha->init_ctrl_blk.cb24.port_name[0] :
1740 	    &ha->init_ctrl_blk.cb.port_name[0];
1741 	bcopy(dp, hba.wwpn, 8);
1742 
1743 	hba.d_id = ha->d_id.b24;
1744 
1745 	if (ha->xioctl->fdesc.flash_size == 0 &&
1746 	    !(CFG_IST(ha, CFG_CTRL_2200) && !ha->subven_id)) {
1747 		if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
1748 			EL(ha, "ql_stall_driver failed\n");
1749 			return (EBUSY);
1750 		}
1751 
1752 		if ((rval = ql_setup_fcache(ha)) != QL_SUCCESS) {
1753 			EL(ha, "ql_setup_flash failed=%xh\n", rval);
1754 			if (rval == QL_FUNCTION_TIMEOUT) {
1755 				return (EBUSY);
1756 			}
1757 			return (EIO);
1758 		}
1759 
1760 		/* Resume I/O */
1761 		if (CFG_IST(ha, CFG_CTRL_242581)) {
1762 			ql_restart_driver(ha);
1763 		} else {
1764 			EL(ha, "isp_abort_needed for restart\n");
1765 			ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED,
1766 			    DRIVER_STALL);
1767 		}
1768 	}
1769 	hba.flash_size = ha->xioctl->fdesc.flash_size;
1770 
1771 	(void) strcpy(hba.driver_ver, QL_VERSION);
1772 
1773 	(void) sprintf(hba.fw_ver, "%d.%d.%d", ha->fw_major_version,
1774 	    ha->fw_minor_version, ha->fw_subminor_version);
1775 
1776 	bzero(hba.fcode_ver, sizeof (hba.fcode_ver));
1777 
1778 	/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
1779 	rval = ddi_getlongprop(DDI_DEV_T_ANY, ha->dip,
1780 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version", (caddr_t)&dp, &i);
1781 	length = i;
1782 	if (rval != DDI_PROP_SUCCESS) {
1783 		EL(ha, "failed, ddi_getlongprop=%xh\n", rval);
1784 	} else {
1785 		if (length > (uint32_t)sizeof (hba.fcode_ver)) {
1786 			length = sizeof (hba.fcode_ver) - 1;
1787 		}
1788 		bcopy((void *)dp, (void *)hba.fcode_ver, length);
1789 		kmem_free(dp, length);
1790 	}
1791 
1792 	if (ddi_copyout((void *)&hba, (void *)(uintptr_t)dop->buffer,
1793 	    dop->length, mode) != 0) {
1794 		EL(ha, "failed, ddi_copyout\n");
1795 		return (EFAULT);
1796 	}
1797 
1798 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1799 
1800 	return (0);
1801 }
1802 
1803 /*
1804  * ql_adm_extended_logging
1805  *	Performs qladm QL_EXTENDED_LOGGING command
1806  *
1807  * Input:
1808  *	ha:	adapter state pointer.
1809  *	dop:	ql_adm_op_t structure pointer.
1810  *
1811  * Returns:
1812  *
1813  * Context:
1814  *	Kernel context.
1815  */
1816 static int
1817 ql_adm_extended_logging(ql_adapter_state_t *ha, ql_adm_op_t *dop)
1818 {
1819 	char	prop_name[MAX_PROP_LENGTH];
1820 	int	rval;
1821 
1822 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1823 
1824 	(void) sprintf(prop_name, "hba%d-extended-logging", ha->instance);
1825 
1826 	/*LINTED [Solaris DDI_DEV_T_NONE Lint warning]*/
1827 	rval = ddi_prop_update_int(DDI_DEV_T_NONE, ha->dip, prop_name,
1828 	    (int)dop->option);
1829 	if (rval != DDI_PROP_SUCCESS) {
1830 		EL(ha, "failed, prop_update = %xh\n", rval);
1831 		return (EINVAL);
1832 	} else {
1833 		dop->option ?
1834 		    (ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING) :
1835 		    (ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING);
1836 	}
1837 
1838 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1839 
1840 	return (0);
1841 }
1842 
1843 /*
1844  * ql_adm_loop_reset
1845  *	Performs qladm QL_LOOP_RESET command
1846  *
1847  * Input:
1848  *	ha:	adapter state pointer.
1849  *
1850  * Returns:
1851  *
1852  * Context:
1853  *	Kernel context.
1854  */
1855 static int
1856 ql_adm_loop_reset(ql_adapter_state_t *ha)
1857 {
1858 	int	rval;
1859 
1860 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1861 
1862 	if (ha->task_daemon_flags & LOOP_DOWN) {
1863 		(void) ql_full_login_lip(ha);
1864 	} else if ((rval = ql_full_login_lip(ha)) != QL_SUCCESS) {
1865 		EL(ha, "failed, ql_initiate_lip=%xh\n", rval);
1866 		return (EIO);
1867 	}
1868 
1869 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1870 
1871 	return (0);
1872 }
1873 
1874 /*
1875  * ql_adm_device_list
1876  *	Performs qladm QL_DEVICE_LIST command
1877  *
1878  * Input:
1879  *	ha:	adapter state pointer.
1880  *	dop:	ql_adm_op_t structure pointer.
1881  *	mode:	flags.
1882  *
1883  * Returns:
1884  *
1885  * Context:
1886  *	Kernel context.
1887  */
1888 static int
1889 ql_adm_device_list(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
1890 {
1891 	ql_device_info_t	dev;
1892 	ql_link_t		*link;
1893 	ql_tgt_t		*tq;
1894 	uint32_t		index, cnt;
1895 
1896 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1897 
1898 	cnt = 0;
1899 	dev.address = 0xffffffff;
1900 
1901 	/* Scan port list for requested target and fill in the values */
1902 	for (link = NULL, index = 0;
1903 	    index < DEVICE_HEAD_LIST_SIZE && link == NULL; index++) {
1904 		for (link = ha->dev[index].first; link != NULL;
1905 		    link = link->next) {
1906 			tq = link->base_address;
1907 
1908 			if (!VALID_TARGET_ID(ha, tq->loop_id)) {
1909 				continue;
1910 			}
1911 			if (cnt != dop->option) {
1912 				cnt++;
1913 				continue;
1914 			}
1915 			/* fill in the values */
1916 			bcopy(tq->port_name, dev.wwpn, 8);
1917 			dev.address = tq->d_id.b24;
1918 			dev.loop_id = tq->loop_id;
1919 			if (tq->flags & TQF_TAPE_DEVICE) {
1920 				dev.type = FCT_TAPE;
1921 			} else if (tq->flags & TQF_INITIATOR_DEVICE) {
1922 				dev.type = FCT_INITIATOR;
1923 			} else {
1924 				dev.type = FCT_TARGET;
1925 			}
1926 			break;
1927 		}
1928 	}
1929 
1930 	if (ddi_copyout((void *)&dev, (void *)(uintptr_t)dop->buffer,
1931 	    dop->length, mode) != 0) {
1932 		EL(ha, "failed, ddi_copyout\n");
1933 		return (EFAULT);
1934 	}
1935 
1936 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1937 
1938 	return (0);
1939 }
1940 
1941 /*
1942  * ql_adm_update_properties
1943  *	Performs qladm QL_UPDATE_PROPERTIES command
1944  *
1945  * Input:
1946  *	ha:	adapter state pointer.
1947  *
1948  * Returns:
1949  *
1950  * Context:
1951  *	Kernel context.
1952  */
1953 static int
1954 ql_adm_update_properties(ql_adapter_state_t *ha)
1955 {
1956 	ql_comb_init_cb_t	init_ctrl_blk;
1957 	ql_comb_ip_init_cb_t	ip_init_ctrl_blk;
1958 
1959 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
1960 
1961 	/* Stall driver instance. */
1962 	(void) ql_stall_driver(ha, 0);
1963 
1964 	/* Save init control blocks. */
1965 	bcopy(&ha->init_ctrl_blk, &init_ctrl_blk, sizeof (ql_comb_init_cb_t));
1966 	bcopy(&ha->ip_init_ctrl_blk, &ip_init_ctrl_blk,
1967 	    sizeof (ql_comb_ip_init_cb_t));
1968 
1969 	/* Update PCI configration. */
1970 	(void) ql_pci_sbus_config(ha);
1971 
1972 	/* Get configuration properties. */
1973 	(void) ql_nvram_config(ha);
1974 
1975 	/* Check for init firmware required. */
1976 	if (bcmp(&ha->init_ctrl_blk, &init_ctrl_blk,
1977 	    sizeof (ql_comb_init_cb_t)) != 0 ||
1978 	    bcmp(&ha->ip_init_ctrl_blk, &ip_init_ctrl_blk,
1979 	    sizeof (ql_comb_ip_init_cb_t)) != 0) {
1980 
1981 		EL(ha, "isp_abort_needed\n");
1982 		ha->loop_down_timer = LOOP_DOWN_TIMER_START;
1983 		TASK_DAEMON_LOCK(ha);
1984 		ha->task_daemon_flags |= LOOP_DOWN | ISP_ABORT_NEEDED;
1985 		TASK_DAEMON_UNLOCK(ha);
1986 	}
1987 
1988 	/* Update AEN queue. */
1989 	if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
1990 		ql_enqueue_aen(ha, MBA_PORT_UPDATE, NULL);
1991 	}
1992 
1993 	/* Restart driver instance. */
1994 	ql_restart_driver(ha);
1995 
1996 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
1997 
1998 	return (0);
1999 }
2000 
2001 /*
2002  * ql_adm_prop_update_int
2003  *	Performs qladm QL_PROP_UPDATE_INT command
2004  *
2005  * Input:
2006  *	ha:	adapter state pointer.
2007  *	dop:	ql_adm_op_t structure pointer.
2008  *	mode:	flags.
2009  *
2010  * Returns:
2011  *
2012  * Context:
2013  *	Kernel context.
2014  */
2015 static int
2016 ql_adm_prop_update_int(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2017 {
2018 	char	*prop_name;
2019 	int	rval;
2020 
2021 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2022 
2023 	prop_name = kmem_zalloc(dop->length, KM_SLEEP);
2024 	if (prop_name == NULL) {
2025 		EL(ha, "failed, kmem_zalloc\n");
2026 		return (ENOMEM);
2027 	}
2028 
2029 	if (ddi_copyin((void *)(uintptr_t)dop->buffer, prop_name, dop->length,
2030 	    mode) != 0) {
2031 		EL(ha, "failed, prop_name ddi_copyin\n");
2032 		kmem_free(prop_name, dop->length);
2033 		return (EFAULT);
2034 	}
2035 
2036 	/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
2037 	if ((rval = ddi_prop_update_int(DDI_DEV_T_NONE, ha->dip, prop_name,
2038 	    (int)dop->option)) != DDI_PROP_SUCCESS) {
2039 		EL(ha, "failed, prop_update=%xh\n", rval);
2040 		kmem_free(prop_name, dop->length);
2041 		return (EINVAL);
2042 	}
2043 
2044 	kmem_free(prop_name, dop->length);
2045 
2046 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2047 
2048 	return (0);
2049 }
2050 
2051 /*
2052  * ql_adm_fw_dump
2053  *	Performs qladm QL_FW_DUMP command
2054  *
2055  * Input:
2056  *	ha:	adapter state pointer.
2057  *	dop:	ql_adm_op_t structure pointer.
2058  *	udop:	user space ql_adm_op_t structure pointer.
2059  *	mode:	flags.
2060  *
2061  * Returns:
2062  *
2063  * Context:
2064  *	Kernel context.
2065  */
2066 static int
2067 ql_adm_fw_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, void *udop, int mode)
2068 {
2069 	caddr_t	dmp;
2070 
2071 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2072 
2073 	if (dop->length < ha->risc_dump_size) {
2074 		EL(ha, "failed, incorrect length=%xh, size=%xh\n",
2075 		    dop->length, ha->risc_dump_size);
2076 		return (EINVAL);
2077 	}
2078 
2079 	if (ha->ql_dump_state & QL_DUMP_VALID) {
2080 		dmp = kmem_zalloc(ha->risc_dump_size, KM_SLEEP);
2081 		if (dmp == NULL) {
2082 			EL(ha, "failed, kmem_zalloc\n");
2083 			return (ENOMEM);
2084 		}
2085 
2086 		dop->length = (uint32_t)ql_ascii_fw_dump(ha, dmp);
2087 		if (ddi_copyout((void *)dmp, (void *)(uintptr_t)dop->buffer,
2088 		    dop->length, mode) != 0) {
2089 			EL(ha, "failed, ddi_copyout\n");
2090 			kmem_free(dmp, ha->risc_dump_size);
2091 			return (EFAULT);
2092 		}
2093 
2094 		kmem_free(dmp, ha->risc_dump_size);
2095 		ha->ql_dump_state |= QL_DUMP_UPLOADED;
2096 
2097 	} else {
2098 		EL(ha, "failed, no dump file\n");
2099 		dop->length = 0;
2100 	}
2101 
2102 	if (ddi_copyout(dop, udop, sizeof (ql_adm_op_t), mode) != 0) {
2103 		EL(ha, "failed, driver_op_t ddi_copyout\n");
2104 		return (EFAULT);
2105 	}
2106 
2107 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2108 
2109 	return (0);
2110 }
2111 
2112 /*
2113  * ql_adm_nvram_dump
2114  *	Performs qladm QL_NVRAM_DUMP command
2115  *
2116  * Input:
2117  *	ha:	adapter state pointer.
2118  *	dop:	ql_adm_op_t structure pointer.
2119  *	mode:	flags.
2120  *
2121  * Returns:
2122  *
2123  * Context:
2124  *	Kernel context.
2125  */
2126 static int
2127 ql_adm_nvram_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2128 {
2129 	uint32_t	nv_size;
2130 	int		rval;
2131 
2132 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2133 
2134 	nv_size = (uint32_t)(CFG_IST(ha, CFG_CTRL_242581) ?
2135 	    sizeof (nvram_24xx_t) : sizeof (nvram_t));
2136 
2137 	if (dop->length < nv_size) {
2138 		EL(ha, "failed, length=%xh, size=%xh\n", dop->length, nv_size);
2139 		return (EINVAL);
2140 	}
2141 
2142 	if ((rval = ql_nv_util_dump(ha, (void *)(uintptr_t)dop->buffer,
2143 	    mode)) != 0) {
2144 		EL(ha, "failed, ql_nv_util_dump\n");
2145 	} else {
2146 		/*EMPTY*/
2147 		QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2148 	}
2149 
2150 	return (rval);
2151 }
2152 
2153 /*
2154  * ql_adm_nvram_load
2155  *	Performs qladm QL_NVRAM_LOAD command
2156  *
2157  * Input:
2158  *	ha:	adapter state pointer.
2159  *	dop:	ql_adm_op_t structure pointer.
2160  *	mode:	flags.
2161  *
2162  * Returns:
2163  *
2164  * Context:
2165  *	Kernel context.
2166  */
2167 static int
2168 ql_adm_nvram_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2169 {
2170 	uint32_t	nv_size;
2171 	int		rval;
2172 
2173 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2174 
2175 	nv_size = (uint32_t)(CFG_IST(ha, CFG_CTRL_242581) ?
2176 	    sizeof (nvram_24xx_t) : sizeof (nvram_t));
2177 
2178 	if (dop->length < nv_size) {
2179 		EL(ha, "failed, length=%xh, size=%xh\n", dop->length, nv_size);
2180 		return (EINVAL);
2181 	}
2182 
2183 	if ((rval = ql_nv_util_load(ha, (void *)(uintptr_t)dop->buffer,
2184 	    mode)) != 0) {
2185 		EL(ha, "failed, ql_nv_util_dump\n");
2186 	} else {
2187 		/*EMPTY*/
2188 		QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2189 	}
2190 
2191 	return (rval);
2192 }
2193 
2194 /*
2195  * ql_adm_flash_load
2196  *	Performs qladm QL_FLASH_LOAD command
2197  *
2198  * Input:
2199  *	ha:	adapter state pointer.
2200  *	dop:	ql_adm_op_t structure pointer.
2201  *	mode:	flags.
2202  *
2203  * Returns:
2204  *
2205  * Context:
2206  *	Kernel context.
2207  */
2208 static int
2209 ql_adm_flash_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2210 {
2211 	uint8_t	*dp;
2212 	int	rval;
2213 
2214 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2215 
2216 	if ((dp = kmem_zalloc(dop->length, KM_SLEEP)) == NULL) {
2217 		EL(ha, "failed, kmem_zalloc\n");
2218 		return (ENOMEM);
2219 	}
2220 
2221 	if (ddi_copyin((void *)(uintptr_t)dop->buffer, dp, dop->length,
2222 	    mode) != 0) {
2223 		EL(ha, "ddi_copyin failed\n");
2224 		kmem_free(dp, dop->length);
2225 		return (EFAULT);
2226 	}
2227 
2228 	if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
2229 		EL(ha, "ql_stall_driver failed\n");
2230 		kmem_free(dp, dop->length);
2231 		return (EBUSY);
2232 	}
2233 
2234 	rval = (CFG_IST(ha, CFG_CTRL_242581) ?
2235 	    ql_24xx_load_flash(ha, dp, dop->length, dop->option) :
2236 	    ql_load_flash(ha, dp, dop->length));
2237 
2238 	ql_restart_driver(ha);
2239 
2240 	kmem_free(dp, dop->length);
2241 
2242 	if (rval != QL_SUCCESS) {
2243 		EL(ha, "failed\n");
2244 		return (EIO);
2245 	}
2246 
2247 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2248 
2249 	return (0);
2250 }
2251 
2252 /*
2253  * ql_adm_vpd_dump
2254  *	Performs qladm QL_VPD_DUMP command
2255  *
2256  * Input:
2257  *	ha:	adapter state pointer.
2258  *	dop:	ql_adm_op_t structure pointer.
2259  *	mode:	flags.
2260  *
2261  * Returns:
2262  *
2263  * Context:
2264  *	Kernel context.
2265  */
2266 static int
2267 ql_adm_vpd_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2268 {
2269 	int		rval;
2270 
2271 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2272 
2273 	if ((CFG_IST(ha, CFG_CTRL_242581)) == 0) {
2274 		EL(ha, "hba does not support VPD\n");
2275 		return (EINVAL);
2276 	}
2277 
2278 	if (dop->length < QL_24XX_VPD_SIZE) {
2279 		EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
2280 		    QL_24XX_VPD_SIZE);
2281 		return (EINVAL);
2282 	}
2283 
2284 	if ((rval = ql_vpd_dump(ha, (void *)(uintptr_t)dop->buffer, mode))
2285 	    != 0) {
2286 		EL(ha, "failed, ql_vpd_dump\n");
2287 	} else {
2288 		/*EMPTY*/
2289 		QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2290 	}
2291 
2292 	return (rval);
2293 }
2294 
2295 /*
2296  * ql_adm_vpd_load
2297  *	Performs qladm QL_VPD_LOAD command
2298  *
2299  * Input:
2300  *	ha:	adapter state pointer.
2301  *	dop:	ql_adm_op_t structure pointer.
2302  *	mode:	flags.
2303  *
2304  * Returns:
2305  *
2306  * Context:
2307  *	Kernel context.
2308  */
2309 static int
2310 ql_adm_vpd_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2311 {
2312 	int		rval;
2313 
2314 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2315 
2316 	if ((CFG_IST(ha, CFG_CTRL_242581)) == 0) {
2317 		EL(ha, "hba does not support VPD\n");
2318 		return (EINVAL);
2319 	}
2320 
2321 	if (dop->length < QL_24XX_VPD_SIZE) {
2322 		EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
2323 		    QL_24XX_VPD_SIZE);
2324 		return (EINVAL);
2325 	}
2326 
2327 	if ((rval = ql_vpd_load(ha, (void *)(uintptr_t)dop->buffer, mode))
2328 	    != 0) {
2329 		EL(ha, "failed, ql_vpd_dump\n");
2330 	} else {
2331 		/*EMPTY*/
2332 		QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2333 	}
2334 
2335 	return (rval);
2336 }
2337 
2338 /*
2339  * ql_adm_vpd_gettag
2340  *	Performs qladm QL_VPD_GETTAG command
2341  *
2342  * Input:
2343  *	ha:	adapter state pointer.
2344  *	dop:	ql_adm_op_t structure pointer.
2345  *	mode:	flags.
2346  *
2347  * Returns:
2348  *
2349  * Context:
2350  *	Kernel context.
2351  */
2352 static int
2353 ql_adm_vpd_gettag(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2354 {
2355 	int		rval = 0;
2356 	uint8_t		*lbuf;
2357 
2358 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2359 
2360 	if ((CFG_IST(ha, CFG_CTRL_242581)) == 0) {
2361 		EL(ha, "hba does not support VPD\n");
2362 		return (EINVAL);
2363 	}
2364 
2365 	if ((lbuf = (uint8_t *)kmem_zalloc(dop->length, KM_SLEEP)) == NULL) {
2366 		EL(ha, "mem alloc failure of %xh bytes\n", dop->length);
2367 		rval = EFAULT;
2368 	} else {
2369 		if (ddi_copyin((void *)(uintptr_t)dop->buffer, lbuf,
2370 		    dop->length, mode) != 0) {
2371 			EL(ha, "ddi_copyin failed\n");
2372 			kmem_free(lbuf, dop->length);
2373 			return (EFAULT);
2374 		}
2375 
2376 		if ((rval = ql_vpd_lookup(ha, lbuf, lbuf, (int32_t)
2377 		    dop->length)) < 0) {
2378 			EL(ha, "failed vpd_lookup\n");
2379 		} else {
2380 			if (ddi_copyout(lbuf, (void *)(uintptr_t)dop->buffer,
2381 			    strlen((int8_t *)lbuf)+1, mode) != 0) {
2382 				EL(ha, "failed, ddi_copyout\n");
2383 				rval = EFAULT;
2384 			} else {
2385 				rval = 0;
2386 			}
2387 		}
2388 		kmem_free(lbuf, dop->length);
2389 	}
2390 
2391 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2392 
2393 	return (rval);
2394 }
2395 
2396 /*
2397  * ql_adm_updfwmodule
2398  *	Performs qladm QL_UPD_FWMODULE command
2399  *
2400  * Input:
2401  *	ha:	adapter state pointer.
2402  *	dop:	ql_adm_op_t structure pointer.
2403  *	mode:	flags.
2404  *
2405  * Returns:
2406  *
2407  * Context:
2408  *	Kernel context.
2409  */
2410 /* ARGSUSED */
2411 static int
2412 ql_adm_updfwmodule(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
2413 {
2414 	int			rval = DDI_SUCCESS;
2415 	ql_link_t		*link;
2416 	ql_adapter_state_t	*ha2 = NULL;
2417 	uint16_t		fw_class = (uint16_t)dop->option;
2418 
2419 	QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
2420 
2421 	/* zero the firmware module reference count */
2422 	for (link = ql_hba.first; link != NULL; link = link->next) {
2423 		ha2 = link->base_address;
2424 		if (fw_class == ha2->fw_class) {
2425 			if ((rval = ddi_modclose(ha2->fw_module)) !=
2426 			    DDI_SUCCESS) {
2427 				EL(ha2, "modclose rval=%xh\n", rval);
2428 				break;
2429 			}
2430 			ha2->fw_module = NULL;
2431 		}
2432 	}
2433 
2434 	/* reload the f/w modules */
2435 	for (link = ql_hba.first; link != NULL; link = link->next) {
2436 		ha2 = link->base_address;
2437 
2438 		if ((fw_class == ha2->fw_class) && (ha2->fw_class == NULL)) {
2439 			if ((rval = (int32_t)ql_fwmodule_resolve(ha2)) !=
2440 			    QL_SUCCESS) {
2441 				EL(ha2, "unable to load f/w module: '%x' "
2442 				    "(rval=%xh)\n", ha2->fw_class, rval);
2443 				rval = EFAULT;
2444 			} else {
2445 				EL(ha2, "f/w module updated: '%x'\n",
2446 				    ha2->fw_class);
2447 			}
2448 
2449 			EL(ha2, "isp abort needed (%d)\n", ha->instance);
2450 
2451 			ql_awaken_task_daemon(ha2, NULL, ISP_ABORT_NEEDED, 0);
2452 
2453 			rval = 0;
2454 		}
2455 	}
2456 
2457 	QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
2458 
2459 	return (rval);
2460 }
2461