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