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