ql_misc.c revision 254976
1250661Sdavidcs/*
2250661Sdavidcs * Copyright (c) 2013-2014 Qlogic Corporation
3250661Sdavidcs * All rights reserved.
4250661Sdavidcs *
5250661Sdavidcs *  Redistribution and use in source and binary forms, with or without
6250661Sdavidcs *  modification, are permitted provided that the following conditions
7250661Sdavidcs *  are met:
8250661Sdavidcs *
9250661Sdavidcs *  1. Redistributions of source code must retain the above copyright
10250661Sdavidcs *     notice, this list of conditions and the following disclaimer.
11250661Sdavidcs *  2. Redistributions in binary form must reproduce the above copyright
12250661Sdavidcs *     notice, this list of conditions and the following disclaimer in the
13250661Sdavidcs *     documentation and/or other materials provided with the distribution.
14250661Sdavidcs *
15250661Sdavidcs *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16250661Sdavidcs *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17250661Sdavidcs *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18250661Sdavidcs *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19250661Sdavidcs *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20250661Sdavidcs *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21250661Sdavidcs *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22250661Sdavidcs *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23250661Sdavidcs *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24250661Sdavidcs *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25250661Sdavidcs *  POSSIBILITY OF SUCH DAMAGE.
26250661Sdavidcs */
27250661Sdavidcs/*
28250661Sdavidcs * File : ql_misc.c
29250661Sdavidcs * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
30250661Sdavidcs */
31250661Sdavidcs
32250661Sdavidcs#include <sys/cdefs.h>
33250661Sdavidcs__FBSDID("$FreeBSD: head/sys/dev/qlxgbe/ql_misc.c 254976 2013-08-27 21:29:21Z davidcs $");
34250661Sdavidcs
35250661Sdavidcs#include "ql_os.h"
36250661Sdavidcs#include "ql_hw.h"
37250661Sdavidcs#include "ql_def.h"
38250661Sdavidcs#include "ql_inline.h"
39250661Sdavidcs#include "ql_glbl.h"
40250661Sdavidcs#include "ql_dbg.h"
41250661Sdavidcs#include "ql_tmplt.h"
42250661Sdavidcs
43250661Sdavidcs#define	QL_FDT_OFFSET		0x3F0000
44250661Sdavidcs#define Q8_FLASH_SECTOR_SIZE	0x10000
45250661Sdavidcs
46250661Sdavidcsstatic int qla_ld_fw_init(qla_host_t *ha);
47250661Sdavidcs
48250661Sdavidcs/*
49250661Sdavidcs * structure encapsulating the value to read/write to offchip memory
50250661Sdavidcs */
51250661Sdavidcstypedef struct _offchip_mem_val {
52250661Sdavidcs        uint32_t data_lo;
53250661Sdavidcs        uint32_t data_hi;
54250661Sdavidcs        uint32_t data_ulo;
55250661Sdavidcs        uint32_t data_uhi;
56250661Sdavidcs} offchip_mem_val_t;
57250661Sdavidcs
58250661Sdavidcs/*
59250661Sdavidcs * Name: ql_rdwr_indreg32
60250661Sdavidcs * Function: Read/Write an Indirect Register
61250661Sdavidcs */
62250661Sdavidcsint
63250661Sdavidcsql_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd)
64250661Sdavidcs{
65250661Sdavidcs	uint32_t wnd_reg;
66250661Sdavidcs	uint32_t count = 100;
67250661Sdavidcs
68250661Sdavidcs	wnd_reg = (Q8_CRB_WINDOW_PF0 | (ha->pci_func << 2));
69250661Sdavidcs
70250661Sdavidcs	WRITE_REG32(ha, wnd_reg, addr);
71250661Sdavidcs
72250661Sdavidcs	while (count--) {
73250661Sdavidcs		if (READ_REG32(ha, wnd_reg) == addr)
74250661Sdavidcs			break;
75250661Sdavidcs		qla_mdelay(__func__, 1);
76250661Sdavidcs	}
77250661Sdavidcs	if (!count || QL_ERR_INJECT(ha, INJCT_RDWR_INDREG_FAILURE)) {
78250661Sdavidcs		device_printf(ha->pci_dev, "%s: [0x%08x, 0x%08x, %d] failed\n",
79250661Sdavidcs			__func__, addr, *val, rd);
80250661Sdavidcs		ha->qla_initiate_recovery = 1;
81250661Sdavidcs		return -1;
82250661Sdavidcs	}
83250661Sdavidcs
84250661Sdavidcs	if (rd) {
85250661Sdavidcs		*val = READ_REG32(ha, Q8_WILD_CARD);
86250661Sdavidcs	} else {
87250661Sdavidcs		WRITE_REG32(ha, Q8_WILD_CARD, *val);
88250661Sdavidcs	}
89250661Sdavidcs
90250661Sdavidcs	return 0;
91250661Sdavidcs}
92250661Sdavidcs
93250661Sdavidcs/*
94250661Sdavidcs * Name: ql_rdwr_offchip_mem
95250661Sdavidcs * Function: Read/Write OffChip Memory
96250661Sdavidcs */
97250661Sdavidcsint
98250661Sdavidcsql_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, q80_offchip_mem_val_t *val,
99250661Sdavidcs	uint32_t rd)
100250661Sdavidcs{
101250661Sdavidcs	uint32_t count = 100;
102250661Sdavidcs	uint32_t data, step = 0;
103250661Sdavidcs
104250661Sdavidcs
105250661Sdavidcs	if (QL_ERR_INJECT(ha, INJCT_RDWR_OFFCHIPMEM_FAILURE))
106250661Sdavidcs		goto exit_ql_rdwr_offchip_mem;
107250661Sdavidcs
108250661Sdavidcs	data = (uint32_t)addr;
109250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_MS_ADDR_LO, &data, 0)) {
110250661Sdavidcs		step = 1;
111250661Sdavidcs		goto exit_ql_rdwr_offchip_mem;
112250661Sdavidcs	}
113250661Sdavidcs
114250661Sdavidcs	data = (uint32_t)(addr >> 32);
115250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_MS_ADDR_HI, &data, 0)) {
116250661Sdavidcs		step = 2;
117250661Sdavidcs		goto exit_ql_rdwr_offchip_mem;
118250661Sdavidcs	}
119250661Sdavidcs
120250661Sdavidcs	data = BIT_1;
121250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
122250661Sdavidcs		step = 3;
123250661Sdavidcs		goto exit_ql_rdwr_offchip_mem;
124250661Sdavidcs	}
125250661Sdavidcs
126250661Sdavidcs	if (!rd) {
127250661Sdavidcs		data = val->data_lo;
128250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_0_31, &data, 0)) {
129250661Sdavidcs			step = 4;
130250661Sdavidcs			goto exit_ql_rdwr_offchip_mem;
131250661Sdavidcs		}
132250661Sdavidcs
133250661Sdavidcs		data = val->data_hi;
134250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_32_63, &data, 0)) {
135250661Sdavidcs			step = 5;
136250661Sdavidcs			goto exit_ql_rdwr_offchip_mem;
137250661Sdavidcs		}
138250661Sdavidcs
139250661Sdavidcs		data = val->data_ulo;
140250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_64_95, &data, 0)) {
141250661Sdavidcs			step = 6;
142250661Sdavidcs			goto exit_ql_rdwr_offchip_mem;
143250661Sdavidcs		}
144250661Sdavidcs
145250661Sdavidcs		data = val->data_uhi;
146250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_96_127, &data, 0)) {
147250661Sdavidcs			step = 7;
148250661Sdavidcs			goto exit_ql_rdwr_offchip_mem;
149250661Sdavidcs		}
150250661Sdavidcs
151250661Sdavidcs		data = (BIT_2|BIT_1|BIT_0);
152250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
153250661Sdavidcs			step = 7;
154250661Sdavidcs			goto exit_ql_rdwr_offchip_mem;
155250661Sdavidcs		}
156250661Sdavidcs	} else {
157250661Sdavidcs		data = (BIT_1|BIT_0);
158250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
159250661Sdavidcs			step = 8;
160250661Sdavidcs			goto exit_ql_rdwr_offchip_mem;
161250661Sdavidcs		}
162250661Sdavidcs	}
163250661Sdavidcs
164250661Sdavidcs	while (count--) {
165250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 1)) {
166250661Sdavidcs			step = 9;
167250661Sdavidcs			goto exit_ql_rdwr_offchip_mem;
168250661Sdavidcs		}
169250661Sdavidcs
170250661Sdavidcs		if (!(data & BIT_3)) {
171250661Sdavidcs			if (rd) {
172250661Sdavidcs				if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_0_31,
173250661Sdavidcs					&data, 1)) {
174250661Sdavidcs					step = 10;
175250661Sdavidcs					goto exit_ql_rdwr_offchip_mem;
176250661Sdavidcs				}
177250661Sdavidcs				val->data_lo = data;
178250661Sdavidcs
179250661Sdavidcs				if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_32_63,
180250661Sdavidcs					&data, 1)) {
181250661Sdavidcs					step = 11;
182250661Sdavidcs					goto exit_ql_rdwr_offchip_mem;
183250661Sdavidcs				}
184250661Sdavidcs				val->data_hi = data;
185250661Sdavidcs
186250661Sdavidcs				if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_64_95,
187250661Sdavidcs					&data, 1)) {
188250661Sdavidcs					step = 12;
189250661Sdavidcs					goto exit_ql_rdwr_offchip_mem;
190250661Sdavidcs				}
191250661Sdavidcs				val->data_ulo = data;
192250661Sdavidcs
193250661Sdavidcs				if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_96_127,
194250661Sdavidcs					&data, 1)) {
195250661Sdavidcs					step = 13;
196250661Sdavidcs					goto exit_ql_rdwr_offchip_mem;
197250661Sdavidcs				}
198250661Sdavidcs				val->data_uhi = data;
199250661Sdavidcs			}
200250661Sdavidcs			return 0;
201250661Sdavidcs		} else
202250661Sdavidcs			qla_mdelay(__func__, 1);
203250661Sdavidcs	}
204250661Sdavidcs
205250661Sdavidcsexit_ql_rdwr_offchip_mem:
206250661Sdavidcs
207250661Sdavidcs	device_printf(ha->pci_dev,
208250661Sdavidcs		"%s: [0x%08x 0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x]"
209250661Sdavidcs		" [%d] [%d] failed\n", __func__, (uint32_t)(addr >> 32),
210250661Sdavidcs		(uint32_t)(addr), val->data_lo, val->data_hi, val->data_ulo,
211250661Sdavidcs		val->data_uhi, rd, step);
212250661Sdavidcs
213250661Sdavidcs	ha->qla_initiate_recovery = 1;
214250661Sdavidcs
215250661Sdavidcs	return (-1);
216250661Sdavidcs}
217250661Sdavidcs
218250661Sdavidcs/*
219250661Sdavidcs * Name: ql_rd_flash32
220250661Sdavidcs * Function: Read Flash Memory
221250661Sdavidcs */
222250661Sdavidcsint
223250661Sdavidcsql_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
224250661Sdavidcs{
225250661Sdavidcs	uint32_t data32;
226250661Sdavidcs
227250661Sdavidcs	if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID, 0xABCDABCD)) {
228250661Sdavidcs		device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
229250661Sdavidcs			__func__);
230250661Sdavidcs		return (-1);
231250661Sdavidcs	}
232250661Sdavidcs
233250661Sdavidcs	data32 = addr;
234250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_DIRECT_WINDOW, &data32, 0)) {
235250661Sdavidcs		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
236250661Sdavidcs		device_printf(ha->pci_dev,
237250661Sdavidcs			"%s: Q8_FLASH_DIRECT_WINDOW[0x%08x] failed\n",
238250661Sdavidcs			__func__, data32);
239250661Sdavidcs		return (-1);
240250661Sdavidcs	}
241250661Sdavidcs
242250661Sdavidcs	data32 = Q8_FLASH_DIRECT_DATA | (addr & 0xFFFF);
243250661Sdavidcs	if (ql_rdwr_indreg32(ha, data32, data, 1)) {
244250661Sdavidcs		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
245250661Sdavidcs		device_printf(ha->pci_dev,
246250661Sdavidcs			"%s: data32:data [0x%08x] failed\n",
247250661Sdavidcs			__func__, data32);
248250661Sdavidcs		return (-1);
249250661Sdavidcs	}
250250661Sdavidcs
251250661Sdavidcs	qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
252250661Sdavidcs	return 0;
253250661Sdavidcs}
254250661Sdavidcs
255250661Sdavidcsstatic int
256250661Sdavidcsqla_get_fdt(qla_host_t *ha)
257250661Sdavidcs{
258250661Sdavidcs	uint32_t data32;
259250661Sdavidcs	int count;
260250661Sdavidcs	qla_hw_t *hw;
261250661Sdavidcs
262250661Sdavidcs	hw = &ha->hw;
263250661Sdavidcs
264250661Sdavidcs	for (count = 0; count < sizeof(qla_flash_desc_table_t); count+=4) {
265250661Sdavidcs		if (ql_rd_flash32(ha, QL_FDT_OFFSET + count,
266250661Sdavidcs			(uint32_t *)&hw->fdt + (count >> 2))) {
267250661Sdavidcs				device_printf(ha->pci_dev,
268250661Sdavidcs					"%s: Read QL_FDT_OFFSET + %d failed\n",
269250661Sdavidcs					__func__, count);
270250661Sdavidcs				return (-1);
271250661Sdavidcs		}
272250661Sdavidcs	}
273250661Sdavidcs
274250661Sdavidcs	if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
275250661Sdavidcs		Q8_FDT_LOCK_MAGIC_ID)) {
276250661Sdavidcs		device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
277250661Sdavidcs			__func__);
278250661Sdavidcs		return (-1);
279250661Sdavidcs	}
280250661Sdavidcs
281250661Sdavidcs	data32 = Q8_FDT_FLASH_ADDR_VAL;
282250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
283250661Sdavidcs		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
284250661Sdavidcs		device_printf(ha->pci_dev,
285250661Sdavidcs			"%s: Write to Q8_FLASH_ADDRESS failed\n",
286250661Sdavidcs			__func__);
287250661Sdavidcs		return (-1);
288250661Sdavidcs	}
289250661Sdavidcs
290250661Sdavidcs	data32 = Q8_FDT_FLASH_CTRL_VAL;
291250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
292250661Sdavidcs		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
293250661Sdavidcs		device_printf(ha->pci_dev,
294250661Sdavidcs			"%s: Write to Q8_FLASH_CONTROL failed\n",
295250661Sdavidcs			__func__);
296250661Sdavidcs		return (-1);
297250661Sdavidcs	}
298250661Sdavidcs
299250661Sdavidcs	count = 0;
300250661Sdavidcs
301250661Sdavidcs	do {
302250661Sdavidcs		if (count < 1000) {
303250661Sdavidcs			QLA_USEC_DELAY(10);
304250661Sdavidcs			count += 10;
305250661Sdavidcs		} else {
306250661Sdavidcs			qla_mdelay(__func__, 1);
307250661Sdavidcs			count += 1000;
308250661Sdavidcs		}
309250661Sdavidcs
310250661Sdavidcs		data32 = 0;
311250661Sdavidcs
312250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
313250661Sdavidcs			qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
314250661Sdavidcs			device_printf(ha->pci_dev,
315250661Sdavidcs				"%s: Read Q8_FLASH_STATUS failed\n",
316250661Sdavidcs				__func__);
317250661Sdavidcs			return (-1);
318250661Sdavidcs		}
319250661Sdavidcs
320250661Sdavidcs		data32 &= 0x6;
321250661Sdavidcs
322250661Sdavidcs	} while ((count < 10000) && (data32 != 0x6));
323250661Sdavidcs
324254976Sdavidcs	if (data32 != 0x6) {
325250661Sdavidcs		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
326250661Sdavidcs		device_printf(ha->pci_dev,
327250661Sdavidcs			"%s: Poll Q8_FLASH_STATUS failed\n",
328250661Sdavidcs			__func__);
329250661Sdavidcs		return (-1);
330250661Sdavidcs	}
331250661Sdavidcs
332250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_RD_DATA, &data32, 1)) {
333250661Sdavidcs		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
334250661Sdavidcs		device_printf(ha->pci_dev,
335250661Sdavidcs			"%s: Read Q8_FLASH_RD_DATA failed\n",
336250661Sdavidcs			__func__);
337250661Sdavidcs		return (-1);
338250661Sdavidcs	}
339250661Sdavidcs
340250661Sdavidcs	qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
341250661Sdavidcs
342250661Sdavidcs	data32 &= Q8_FDT_MASK_VAL;
343250661Sdavidcs	if (hw->fdt.flash_manuf == data32)
344250661Sdavidcs		return (0);
345250661Sdavidcs	else
346250661Sdavidcs		return (-1);
347250661Sdavidcs}
348250661Sdavidcs
349250661Sdavidcsstatic int
350250661Sdavidcsqla_flash_write_enable(qla_host_t *ha, int enable)
351250661Sdavidcs{
352250661Sdavidcs	uint32_t data32;
353250661Sdavidcs	int count = 0;
354250661Sdavidcs
355250661Sdavidcs	data32 = Q8_WR_ENABLE_FL_ADDR | ha->hw.fdt.write_statusreg_cmd;
356250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
357250661Sdavidcs		device_printf(ha->pci_dev,
358250661Sdavidcs			"%s: Write to Q8_FLASH_ADDRESS failed\n",
359250661Sdavidcs			__func__);
360250661Sdavidcs		return (-1);
361250661Sdavidcs	}
362250661Sdavidcs
363250661Sdavidcs	if (enable)
364250661Sdavidcs		data32 = ha->hw.fdt.write_enable_bits;
365250661Sdavidcs	else
366250661Sdavidcs		data32 = ha->hw.fdt.write_disable_bits;
367250661Sdavidcs
368250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, &data32, 0)) {
369250661Sdavidcs		device_printf(ha->pci_dev,
370250661Sdavidcs			"%s: Write to Q8_FLASH_WR_DATA failed\n",
371250661Sdavidcs			__func__);
372250661Sdavidcs		return (-1);
373250661Sdavidcs	}
374250661Sdavidcs
375250661Sdavidcs	data32 = Q8_WR_ENABLE_FL_CTRL;
376250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
377250661Sdavidcs		device_printf(ha->pci_dev,
378250661Sdavidcs			"%s: Write to Q8_FLASH_CONTROL failed\n",
379250661Sdavidcs			__func__);
380250661Sdavidcs		return (-1);
381250661Sdavidcs	}
382250661Sdavidcs
383250661Sdavidcs	do {
384250661Sdavidcs		if (count < 1000) {
385250661Sdavidcs			QLA_USEC_DELAY(10);
386250661Sdavidcs			count += 10;
387250661Sdavidcs		} else {
388250661Sdavidcs			qla_mdelay(__func__, 1);
389250661Sdavidcs			count += 1000;
390250661Sdavidcs		}
391250661Sdavidcs
392250661Sdavidcs		data32 = 0;
393250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
394250661Sdavidcs			device_printf(ha->pci_dev,
395250661Sdavidcs				"%s: Read Q8_FLASH_STATUS failed\n",
396250661Sdavidcs				__func__);
397250661Sdavidcs			return (-1);
398250661Sdavidcs		}
399250661Sdavidcs
400250661Sdavidcs		data32 &= 0x6;
401250661Sdavidcs
402250661Sdavidcs	} while ((count < 10000) && (data32 != 0x6));
403250661Sdavidcs
404254976Sdavidcs	if (data32 != 0x6) {
405250661Sdavidcs		device_printf(ha->pci_dev,
406250661Sdavidcs			"%s: Poll Q8_FLASH_STATUS failed\n",
407250661Sdavidcs			__func__);
408250661Sdavidcs		return (-1);
409250661Sdavidcs	}
410250661Sdavidcs
411250661Sdavidcs	return 0;
412250661Sdavidcs}
413250661Sdavidcs
414250661Sdavidcsstatic int
415250661Sdavidcsqla_erase_flash_sector(qla_host_t *ha, uint32_t start)
416250661Sdavidcs{
417250661Sdavidcs	uint32_t data32;
418250661Sdavidcs	int count = 0;
419250661Sdavidcs
420250661Sdavidcs	do {
421250661Sdavidcs		qla_mdelay(__func__, 1);
422250661Sdavidcs
423250661Sdavidcs		data32 = 0;
424250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
425250661Sdavidcs			device_printf(ha->pci_dev,
426250661Sdavidcs				"%s: Read Q8_FLASH_STATUS failed\n",
427250661Sdavidcs				__func__);
428250661Sdavidcs			return (-1);
429250661Sdavidcs		}
430250661Sdavidcs
431250661Sdavidcs		data32 &= 0x6;
432250661Sdavidcs
433250661Sdavidcs	} while (((count++) < 1000) && (data32 != 0x6));
434250661Sdavidcs
435254976Sdavidcs	if (data32 != 0x6) {
436250661Sdavidcs		device_printf(ha->pci_dev,
437250661Sdavidcs			"%s: Poll Q8_FLASH_STATUS failed\n",
438250661Sdavidcs			__func__);
439250661Sdavidcs		return (-1);
440250661Sdavidcs	}
441250661Sdavidcs
442250661Sdavidcs	data32 = (start >> 16) & 0xFF;
443250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, &data32, 0)) {
444250661Sdavidcs		device_printf(ha->pci_dev,
445250661Sdavidcs			"%s: Write to Q8_FLASH_WR_DATA failed\n",
446250661Sdavidcs			__func__);
447250661Sdavidcs		return (-1);
448250661Sdavidcs	}
449250661Sdavidcs
450250661Sdavidcs	data32 = Q8_ERASE_FL_ADDR_MASK | ha->hw.fdt.erase_cmd;
451250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
452250661Sdavidcs		device_printf(ha->pci_dev,
453250661Sdavidcs			"%s: Write to Q8_FLASH_ADDRESS failed\n",
454250661Sdavidcs			__func__);
455250661Sdavidcs		return (-1);
456250661Sdavidcs	}
457250661Sdavidcs
458250661Sdavidcs	data32 = Q8_ERASE_FL_CTRL_MASK;
459250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
460250661Sdavidcs		device_printf(ha->pci_dev,
461250661Sdavidcs			"%s: Write to Q8_FLASH_CONTROL failed\n",
462250661Sdavidcs			__func__);
463250661Sdavidcs		return (-1);
464250661Sdavidcs	}
465250661Sdavidcs
466250661Sdavidcs	count = 0;
467250661Sdavidcs	do {
468250661Sdavidcs		qla_mdelay(__func__, 1);
469250661Sdavidcs
470250661Sdavidcs		data32 = 0;
471250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
472250661Sdavidcs			device_printf(ha->pci_dev,
473250661Sdavidcs				"%s: Read Q8_FLASH_STATUS failed\n",
474250661Sdavidcs				__func__);
475250661Sdavidcs			return (-1);
476250661Sdavidcs		}
477250661Sdavidcs
478250661Sdavidcs		data32 &= 0x6;
479250661Sdavidcs
480250661Sdavidcs	} while (((count++) < 1000) && (data32 != 0x6));
481250661Sdavidcs
482254976Sdavidcs	if (data32 != 0x6) {
483250661Sdavidcs		device_printf(ha->pci_dev,
484250661Sdavidcs			"%s: Poll Q8_FLASH_STATUS failed\n",
485250661Sdavidcs			__func__);
486250661Sdavidcs		return (-1);
487250661Sdavidcs	}
488250661Sdavidcs
489250661Sdavidcs	return 0;
490250661Sdavidcs}
491250661Sdavidcs
492250661Sdavidcsint
493250661Sdavidcsql_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size)
494250661Sdavidcs{
495250661Sdavidcs	int rval = 0;
496250661Sdavidcs	uint32_t start;
497250661Sdavidcs
498250661Sdavidcs	if (off & (Q8_FLASH_SECTOR_SIZE -1))
499250661Sdavidcs		return (-1);
500250661Sdavidcs
501250661Sdavidcs	if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
502250661Sdavidcs		Q8_ERASE_LOCK_MAGIC_ID)) {
503250661Sdavidcs		device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
504250661Sdavidcs			__func__);
505250661Sdavidcs		return (-1);
506250661Sdavidcs	}
507250661Sdavidcs
508250661Sdavidcs	if (qla_flash_write_enable(ha, 1) != 0) {
509250661Sdavidcs		rval = -1;
510250661Sdavidcs		goto ql_erase_flash_exit;
511250661Sdavidcs	}
512250661Sdavidcs
513250661Sdavidcs	for (start = off; start < (off + size); start = start +
514250661Sdavidcs		Q8_FLASH_SECTOR_SIZE) {
515250661Sdavidcs			if (qla_erase_flash_sector(ha, start)) {
516250661Sdavidcs				rval = -1;
517250661Sdavidcs				break;
518250661Sdavidcs			}
519250661Sdavidcs	}
520250661Sdavidcs
521250661Sdavidcs	rval = qla_flash_write_enable(ha, 0);
522250661Sdavidcs
523250661Sdavidcsql_erase_flash_exit:
524250661Sdavidcs	qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
525250661Sdavidcs	return (rval);
526250661Sdavidcs}
527250661Sdavidcs
528250661Sdavidcsstatic int
529250661Sdavidcsqla_wr_flash32(qla_host_t *ha, uint32_t off, uint32_t *data)
530250661Sdavidcs{
531250661Sdavidcs	uint32_t data32;
532250661Sdavidcs	int count = 0;
533250661Sdavidcs
534250661Sdavidcs	data32 = Q8_WR_FL_ADDR_MASK | (off >> 2);
535250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
536250661Sdavidcs		device_printf(ha->pci_dev,
537250661Sdavidcs			"%s: Write to Q8_FLASH_ADDRESS failed\n",
538250661Sdavidcs			__func__);
539250661Sdavidcs		return (-1);
540250661Sdavidcs	}
541250661Sdavidcs
542250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, data, 0)) {
543250661Sdavidcs		device_printf(ha->pci_dev,
544250661Sdavidcs			"%s: Write to Q8_FLASH_WR_DATA failed\n",
545250661Sdavidcs			__func__);
546250661Sdavidcs		return (-1);
547250661Sdavidcs	}
548250661Sdavidcs
549250661Sdavidcs	data32 = Q8_WR_FL_CTRL_MASK;
550250661Sdavidcs	if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
551250661Sdavidcs		device_printf(ha->pci_dev,
552250661Sdavidcs			"%s: Write to Q8_FLASH_CONTROL failed\n",
553250661Sdavidcs			__func__);
554250661Sdavidcs		return (-1);
555250661Sdavidcs	}
556250661Sdavidcs
557250661Sdavidcs	do {
558250661Sdavidcs		if (count < 1000) {
559250661Sdavidcs			QLA_USEC_DELAY(10);
560250661Sdavidcs			count += 10;
561250661Sdavidcs		} else {
562250661Sdavidcs			qla_mdelay(__func__, 1);
563250661Sdavidcs			count += 1000;
564250661Sdavidcs		}
565250661Sdavidcs
566250661Sdavidcs		data32 = 0;
567250661Sdavidcs		if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
568250661Sdavidcs			device_printf(ha->pci_dev,
569250661Sdavidcs				"%s: Read Q8_FLASH_STATUS failed\n",
570250661Sdavidcs				__func__);
571250661Sdavidcs			return (-1);
572250661Sdavidcs		}
573250661Sdavidcs
574250661Sdavidcs		data32 &= 0x6;
575250661Sdavidcs
576250661Sdavidcs	} while ((count < 10000) && (data32 != 0x6));
577250661Sdavidcs
578254976Sdavidcs	if (data32 != 0x6) {
579250661Sdavidcs		device_printf(ha->pci_dev,
580250661Sdavidcs			"%s: Poll Q8_FLASH_STATUS failed\n",
581250661Sdavidcs			__func__);
582250661Sdavidcs		return (-1);
583250661Sdavidcs	}
584250661Sdavidcs
585250661Sdavidcs	return 0;
586250661Sdavidcs}
587250661Sdavidcs
588250661Sdavidcsstatic int
589250661Sdavidcsqla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size,
590250661Sdavidcs        void *data)
591250661Sdavidcs{
592250661Sdavidcs	int rval = 0;
593250661Sdavidcs	uint32_t start;
594250661Sdavidcs	uint32_t *data32 = data;
595250661Sdavidcs
596250661Sdavidcs	if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
597250661Sdavidcs		Q8_WR_FL_LOCK_MAGIC_ID)) {
598250661Sdavidcs			device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
599250661Sdavidcs				__func__);
600250661Sdavidcs			rval = -1;
601250661Sdavidcs			goto qla_flash_write_data_exit;
602250661Sdavidcs	}
603250661Sdavidcs
604250661Sdavidcs	if ((qla_flash_write_enable(ha, 1) != 0)) {
605250661Sdavidcs		device_printf(ha->pci_dev, "%s: failed\n",
606250661Sdavidcs			__func__);
607250661Sdavidcs		rval = -1;
608250661Sdavidcs		goto qla_flash_write_data_unlock_exit;
609250661Sdavidcs	}
610250661Sdavidcs
611250661Sdavidcs	for (start = off; start < (off + size); start = start + 4) {
612250661Sdavidcs		if (*data32 != 0xFFFFFFFF) {
613250661Sdavidcs			if (qla_wr_flash32(ha, start, data32)) {
614250661Sdavidcs				rval = -1;
615250661Sdavidcs				break;
616250661Sdavidcs			}
617250661Sdavidcs		}
618250661Sdavidcs		data32++;
619250661Sdavidcs	}
620250661Sdavidcs
621250661Sdavidcs	rval = qla_flash_write_enable(ha, 0);
622250661Sdavidcs
623250661Sdavidcsqla_flash_write_data_unlock_exit:
624250661Sdavidcs	qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
625250661Sdavidcs
626250661Sdavidcsqla_flash_write_data_exit:
627250661Sdavidcs	return (rval);
628250661Sdavidcs}
629250661Sdavidcs
630250661Sdavidcsint
631250661Sdavidcsql_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf)
632250661Sdavidcs{
633250661Sdavidcs	int rval = 0;
634250661Sdavidcs	void *data;
635250661Sdavidcs
636250661Sdavidcs	if (size == 0)
637250661Sdavidcs		return 0;
638250661Sdavidcs
639250661Sdavidcs	size = size << 2;
640250661Sdavidcs
641250661Sdavidcs	if (buf == NULL)
642250661Sdavidcs		return -1;
643250661Sdavidcs
644250661Sdavidcs	if ((data = malloc(size, M_QLA83XXBUF, M_NOWAIT)) == NULL) {
645250661Sdavidcs		device_printf(ha->pci_dev, "%s: malloc failed \n", __func__);
646250661Sdavidcs		rval = -1;
647250661Sdavidcs		goto ql_wr_flash_buffer_exit;
648250661Sdavidcs	}
649250661Sdavidcs
650250661Sdavidcs	if ((rval = copyin(buf, data, size))) {
651250661Sdavidcs		device_printf(ha->pci_dev, "%s copyin failed\n", __func__);
652250661Sdavidcs		goto ql_wr_flash_buffer_free_exit;
653250661Sdavidcs	}
654250661Sdavidcs
655250661Sdavidcs	rval = qla_flash_write_data(ha, off, size, data);
656250661Sdavidcs
657250661Sdavidcsql_wr_flash_buffer_free_exit:
658250661Sdavidcs	free(data, M_QLA83XXBUF);
659250661Sdavidcs
660250661Sdavidcsql_wr_flash_buffer_exit:
661250661Sdavidcs	return (rval);
662250661Sdavidcs}
663250661Sdavidcs
664250661Sdavidcs/*
665250661Sdavidcs * Name: qla_load_fw_from_flash
666250661Sdavidcs * Function: Reads the Bootloader from Flash and Loads into Offchip Memory
667250661Sdavidcs */
668250661Sdavidcsstatic void
669250661Sdavidcsqla_load_fw_from_flash(qla_host_t *ha)
670250661Sdavidcs{
671250661Sdavidcs	uint32_t flash_off	= 0x10000;
672250661Sdavidcs	uint64_t mem_off;
673250661Sdavidcs	uint32_t count, mem_size;
674250661Sdavidcs	q80_offchip_mem_val_t val;
675250661Sdavidcs
676250661Sdavidcs	mem_off = (uint64_t)(READ_REG32(ha, Q8_BOOTLD_ADDR));
677250661Sdavidcs	mem_size = READ_REG32(ha, Q8_BOOTLD_SIZE);
678250661Sdavidcs
679250661Sdavidcs	device_printf(ha->pci_dev, "%s: [0x%08x][0x%08x]\n",
680250661Sdavidcs		__func__, (uint32_t)mem_off, mem_size);
681250661Sdavidcs
682250661Sdavidcs	/* only bootloader needs to be loaded into memory */
683250661Sdavidcs	for (count = 0; count < mem_size ; ) {
684250661Sdavidcs		ql_rd_flash32(ha, flash_off, &val.data_lo);
685250661Sdavidcs		count = count + 4;
686250661Sdavidcs		flash_off = flash_off + 4;
687250661Sdavidcs
688250661Sdavidcs		ql_rd_flash32(ha, flash_off, &val.data_hi);
689250661Sdavidcs		count = count + 4;
690250661Sdavidcs		flash_off = flash_off + 4;
691250661Sdavidcs
692250661Sdavidcs		ql_rd_flash32(ha, flash_off, &val.data_ulo);
693250661Sdavidcs		count = count + 4;
694250661Sdavidcs		flash_off = flash_off + 4;
695250661Sdavidcs
696250661Sdavidcs		ql_rd_flash32(ha, flash_off, &val.data_uhi);
697250661Sdavidcs		count = count + 4;
698250661Sdavidcs		flash_off = flash_off + 4;
699250661Sdavidcs
700250661Sdavidcs		ql_rdwr_offchip_mem(ha, mem_off, &val, 0);
701250661Sdavidcs
702250661Sdavidcs		mem_off = mem_off + 16;
703250661Sdavidcs	}
704250661Sdavidcs
705250661Sdavidcs	return;
706250661Sdavidcs}
707250661Sdavidcs
708250661Sdavidcs/*
709250661Sdavidcs * Name: qla_init_from_flash
710250661Sdavidcs * Function: Performs Initialization which consists of the following sequence
711250661Sdavidcs *	- reset
712250661Sdavidcs *	- CRB Init
713250661Sdavidcs *	- Peg Init
714250661Sdavidcs *	- Read the Bootloader from Flash and Load into Offchip Memory
715250661Sdavidcs *	- Kick start the bootloader which loads the rest of the firmware
716250661Sdavidcs *		and performs the remaining steps in the initialization process.
717250661Sdavidcs */
718250661Sdavidcsstatic int
719250661Sdavidcsqla_init_from_flash(qla_host_t *ha)
720250661Sdavidcs{
721250661Sdavidcs	uint32_t delay = 300;
722250661Sdavidcs	uint32_t data;
723250661Sdavidcs
724250661Sdavidcs	qla_ld_fw_init(ha);
725250661Sdavidcs
726250661Sdavidcs	do {
727250661Sdavidcs		data = READ_REG32(ha, Q8_CMDPEG_STATE);
728250661Sdavidcs
729250661Sdavidcs		QL_DPRINT2(ha,
730250661Sdavidcs			(ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
731250661Sdavidcs				__func__, ha->pci_func, data));
732250661Sdavidcs		if (data == 0xFF01) {
733250661Sdavidcs			QL_DPRINT2(ha, (ha->pci_dev,
734250661Sdavidcs				"%s: func[%d] init complete\n",
735250661Sdavidcs				__func__, ha->pci_func));
736250661Sdavidcs			return(0);
737250661Sdavidcs		}
738250661Sdavidcs		qla_mdelay(__func__, 100);
739250661Sdavidcs	} while (delay--);
740250661Sdavidcs
741250661Sdavidcs	return (-1);
742250661Sdavidcs}
743250661Sdavidcs
744250661Sdavidcs/*
745250661Sdavidcs * Name: ql_init_hw
746250661Sdavidcs * Function: Initializes P3+ hardware.
747250661Sdavidcs */
748250661Sdavidcsint
749250661Sdavidcsql_init_hw(qla_host_t *ha)
750250661Sdavidcs{
751250661Sdavidcs        device_t dev;
752250661Sdavidcs        int ret = 0;
753250661Sdavidcs        uint32_t val, delay = 300;
754250661Sdavidcs
755250661Sdavidcs        dev = ha->pci_dev;
756250661Sdavidcs
757250661Sdavidcs        QL_DPRINT1(ha, (dev, "%s: enter\n", __func__));
758250661Sdavidcs
759250661Sdavidcs	if (ha->pci_func & 0x1) {
760250661Sdavidcs
761250661Sdavidcs        	while ((ha->pci_func & 0x1) && delay--) {
762250661Sdavidcs
763250661Sdavidcs			val = READ_REG32(ha, Q8_CMDPEG_STATE);
764250661Sdavidcs
765250661Sdavidcs			if (val == 0xFF01) {
766250661Sdavidcs				QL_DPRINT2(ha, (dev,
767250661Sdavidcs					"%s: func = %d init complete\n",
768250661Sdavidcs					__func__, ha->pci_func));
769250661Sdavidcs				qla_mdelay(__func__, 100);
770250661Sdavidcs				goto qla_init_exit;
771250661Sdavidcs			}
772250661Sdavidcs			qla_mdelay(__func__, 100);
773250661Sdavidcs		}
774250661Sdavidcs		return (-1);
775250661Sdavidcs	}
776250661Sdavidcs
777250661Sdavidcs
778250661Sdavidcs	val = READ_REG32(ha, Q8_CMDPEG_STATE);
779250661Sdavidcs	if (!cold || (val != 0xFF01)) {
780250661Sdavidcs        	ret = qla_init_from_flash(ha);
781250661Sdavidcs		qla_mdelay(__func__, 100);
782250661Sdavidcs	}
783250661Sdavidcs
784250661Sdavidcsqla_init_exit:
785250661Sdavidcs        ha->fw_ver_major = READ_REG32(ha, Q8_FW_VER_MAJOR);
786250661Sdavidcs        ha->fw_ver_minor = READ_REG32(ha, Q8_FW_VER_MINOR);
787250661Sdavidcs        ha->fw_ver_sub = READ_REG32(ha, Q8_FW_VER_SUB);
788250661Sdavidcs
789250661Sdavidcs	if (qla_get_fdt(ha) != 0) {
790250661Sdavidcs		device_printf(dev, "%s: qla_get_fdt failed\n", __func__);
791250661Sdavidcs	} else {
792250661Sdavidcs		ha->hw.flags.fdt_valid = 1;
793250661Sdavidcs	}
794250661Sdavidcs
795250661Sdavidcs        return (ret);
796250661Sdavidcs}
797250661Sdavidcs
798250661Sdavidcsvoid
799250661Sdavidcsql_read_mac_addr(qla_host_t *ha)
800250661Sdavidcs{
801250661Sdavidcs	uint8_t *macp;
802250661Sdavidcs	uint32_t mac_lo;
803250661Sdavidcs	uint32_t mac_hi;
804250661Sdavidcs	uint32_t flash_off;
805250661Sdavidcs
806250661Sdavidcs	flash_off = Q8_BOARD_CONFIG_OFFSET + Q8_BOARD_CONFIG_MAC0_LO +
807250661Sdavidcs			(ha->pci_func << 3);
808250661Sdavidcs	ql_rd_flash32(ha, flash_off, &mac_lo);
809250661Sdavidcs
810250661Sdavidcs	flash_off += 4;
811250661Sdavidcs	ql_rd_flash32(ha, flash_off, &mac_hi);
812250661Sdavidcs
813250661Sdavidcs	macp = (uint8_t *)&mac_lo;
814250661Sdavidcs	ha->hw.mac_addr[5] = macp[0];
815250661Sdavidcs	ha->hw.mac_addr[4] = macp[1];
816250661Sdavidcs	ha->hw.mac_addr[3] = macp[2];
817250661Sdavidcs	ha->hw.mac_addr[2] = macp[3];
818250661Sdavidcs
819250661Sdavidcs	macp = (uint8_t *)&mac_hi;
820250661Sdavidcs	ha->hw.mac_addr[1] = macp[0];
821250661Sdavidcs	ha->hw.mac_addr[0] = macp[1];
822250661Sdavidcs
823250661Sdavidcs	//device_printf(ha->pci_dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
824250661Sdavidcs	//	__func__, ha->hw.mac_addr[0], ha->hw.mac_addr[1],
825250661Sdavidcs	//	ha->hw.mac_addr[2], ha->hw.mac_addr[3],
826250661Sdavidcs	//	ha->hw.mac_addr[4], ha->hw.mac_addr[5]);
827250661Sdavidcs
828250661Sdavidcs        return;
829250661Sdavidcs}
830250661Sdavidcs
831250661Sdavidcs/*
832250661Sdavidcs * Stop/Start/Initialization Handling
833250661Sdavidcs */
834250661Sdavidcs
835250661Sdavidcsstatic uint16_t
836250661Sdavidcsqla_tmplt_16bit_checksum(qla_host_t *ha, uint16_t *buf, uint32_t size)
837250661Sdavidcs{
838250661Sdavidcs	uint32_t sum = 0;
839250661Sdavidcs	uint32_t count = size >> 1; /* size in 16 bit words */
840250661Sdavidcs
841250661Sdavidcs	while (count-- > 0)
842250661Sdavidcs		sum += *buf++;
843250661Sdavidcs
844250661Sdavidcs	while (sum >> 16)
845250661Sdavidcs		sum = (sum & 0xFFFF) + (sum >> 16);
846250661Sdavidcs
847250661Sdavidcs	return (~sum);
848250661Sdavidcs}
849250661Sdavidcs
850250661Sdavidcsstatic int
851250661Sdavidcsqla_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
852250661Sdavidcs{
853250661Sdavidcs	q8_wrl_e_t *wr_l;
854250661Sdavidcs	int i;
855250661Sdavidcs
856250661Sdavidcs	wr_l = (q8_wrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
857250661Sdavidcs
858250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, wr_l++) {
859250661Sdavidcs
860250661Sdavidcs		if (ql_rdwr_indreg32(ha, wr_l->addr, &wr_l->value, 0)) {
861250661Sdavidcs			device_printf(ha->pci_dev,
862250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
863250661Sdavidcs				wr_l->addr, wr_l->value);
864250661Sdavidcs			return -1;
865250661Sdavidcs		}
866250661Sdavidcs		if (ce_hdr->delay_to) {
867250661Sdavidcs			DELAY(ce_hdr->delay_to);
868250661Sdavidcs		}
869250661Sdavidcs	}
870250661Sdavidcs	return 0;
871250661Sdavidcs}
872250661Sdavidcs
873250661Sdavidcsstatic int
874250661Sdavidcsqla_rd_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
875250661Sdavidcs{
876250661Sdavidcs	q8_rdwrl_e_t *rd_wr_l;
877250661Sdavidcs	uint32_t data;
878250661Sdavidcs	int i;
879250661Sdavidcs
880250661Sdavidcs	rd_wr_l = (q8_rdwrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
881250661Sdavidcs
882250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, rd_wr_l++) {
883250661Sdavidcs
884250661Sdavidcs		if (ql_rdwr_indreg32(ha, rd_wr_l->rd_addr, &data, 1)) {
885250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
886250661Sdavidcs				__func__, rd_wr_l->rd_addr);
887250661Sdavidcs
888250661Sdavidcs			return -1;
889250661Sdavidcs		}
890250661Sdavidcs
891250661Sdavidcs		if (ql_rdwr_indreg32(ha, rd_wr_l->wr_addr, &data, 0)) {
892250661Sdavidcs			device_printf(ha->pci_dev,
893250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
894250661Sdavidcs				rd_wr_l->wr_addr, data);
895250661Sdavidcs			return -1;
896250661Sdavidcs		}
897250661Sdavidcs		if (ce_hdr->delay_to) {
898250661Sdavidcs			DELAY(ce_hdr->delay_to);
899250661Sdavidcs		}
900250661Sdavidcs	}
901250661Sdavidcs	return 0;
902250661Sdavidcs}
903250661Sdavidcs
904250661Sdavidcsstatic int
905250661Sdavidcsqla_poll_reg(qla_host_t *ha, uint32_t addr, uint32_t ms_to, uint32_t tmask,
906250661Sdavidcs	uint32_t tvalue)
907250661Sdavidcs{
908250661Sdavidcs	uint32_t data;
909250661Sdavidcs
910250661Sdavidcs	while (ms_to) {
911250661Sdavidcs
912250661Sdavidcs		if (ql_rdwr_indreg32(ha, addr, &data, 1)) {
913250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
914250661Sdavidcs				__func__, addr);
915250661Sdavidcs			return -1;
916250661Sdavidcs		}
917250661Sdavidcs
918250661Sdavidcs		if ((data & tmask) != tvalue) {
919250661Sdavidcs			ms_to--;
920250661Sdavidcs		} else
921250661Sdavidcs			break;
922250661Sdavidcs
923250661Sdavidcs		qla_mdelay(__func__, 1);
924250661Sdavidcs	}
925250661Sdavidcs	return ((ms_to ? 0: -1));
926250661Sdavidcs}
927250661Sdavidcs
928250661Sdavidcsstatic int
929250661Sdavidcsqla_poll_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
930250661Sdavidcs{
931250661Sdavidcs	int		i;
932250661Sdavidcs	q8_poll_hdr_t	*phdr;
933250661Sdavidcs	q8_poll_e_t	*pe;
934250661Sdavidcs	uint32_t	data;
935250661Sdavidcs
936250661Sdavidcs	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
937250661Sdavidcs	pe = (q8_poll_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
938250661Sdavidcs
939250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, pe++) {
940250661Sdavidcs		if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
941250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
942250661Sdavidcs				__func__, pe->addr);
943250661Sdavidcs			return -1;
944250661Sdavidcs		}
945250661Sdavidcs
946250661Sdavidcs		if (ce_hdr->delay_to)  {
947250661Sdavidcs			if ((data & phdr->tmask) == phdr->tvalue)
948250661Sdavidcs				break;
949250661Sdavidcs			if (qla_poll_reg(ha, pe->addr, ce_hdr->delay_to,
950250661Sdavidcs				phdr->tmask, phdr->tvalue)) {
951250661Sdavidcs
952250661Sdavidcs				if (ql_rdwr_indreg32(ha, pe->to_addr, &data,
953250661Sdavidcs					1)) {
954250661Sdavidcs					device_printf(ha->pci_dev,
955250661Sdavidcs						"%s: [0x%08x] error\n",
956250661Sdavidcs						__func__, pe->to_addr);
957250661Sdavidcs					return -1;
958250661Sdavidcs				}
959250661Sdavidcs
960250661Sdavidcs				if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
961250661Sdavidcs					device_printf(ha->pci_dev,
962250661Sdavidcs						"%s: [0x%08x] error\n",
963250661Sdavidcs						__func__, pe->addr);
964250661Sdavidcs					return -1;
965250661Sdavidcs				}
966250661Sdavidcs			}
967250661Sdavidcs		}
968250661Sdavidcs	}
969250661Sdavidcs	return 0;
970250661Sdavidcs}
971250661Sdavidcs
972250661Sdavidcsstatic int
973250661Sdavidcsqla_poll_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
974250661Sdavidcs{
975250661Sdavidcs	int		i;
976250661Sdavidcs	q8_poll_hdr_t	*phdr;
977250661Sdavidcs	q8_poll_wr_e_t	*wr_e;
978250661Sdavidcs
979250661Sdavidcs	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
980250661Sdavidcs	wr_e = (q8_poll_wr_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
981250661Sdavidcs
982250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, wr_e++) {
983250661Sdavidcs
984250661Sdavidcs		if (ql_rdwr_indreg32(ha, wr_e->dr_addr, &wr_e->dr_value, 0)) {
985250661Sdavidcs			device_printf(ha->pci_dev,
986250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
987250661Sdavidcs				wr_e->dr_addr, wr_e->dr_value);
988250661Sdavidcs			return -1;
989250661Sdavidcs		}
990250661Sdavidcs		if (ql_rdwr_indreg32(ha, wr_e->ar_addr, &wr_e->ar_value, 0)) {
991250661Sdavidcs			device_printf(ha->pci_dev,
992250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
993250661Sdavidcs				wr_e->ar_addr, wr_e->ar_value);
994250661Sdavidcs			return -1;
995250661Sdavidcs		}
996250661Sdavidcs		if (ce_hdr->delay_to)  {
997250661Sdavidcs			if (qla_poll_reg(ha, wr_e->ar_addr, ce_hdr->delay_to,
998250661Sdavidcs				phdr->tmask, phdr->tvalue))
999250661Sdavidcs				device_printf(ha->pci_dev, "%s: "
1000250661Sdavidcs					"[ar_addr, ar_value, delay, tmask,"
1001250661Sdavidcs					"tvalue] [0x%08x 0x%08x 0x%08x 0x%08x"
1002250661Sdavidcs					" 0x%08x]\n",
1003250661Sdavidcs					__func__, wr_e->ar_addr, wr_e->ar_value,
1004250661Sdavidcs					ce_hdr->delay_to, phdr->tmask,
1005250661Sdavidcs					phdr->tvalue);
1006250661Sdavidcs		}
1007250661Sdavidcs	}
1008250661Sdavidcs	return 0;
1009250661Sdavidcs}
1010250661Sdavidcs
1011250661Sdavidcsstatic int
1012250661Sdavidcsqla_poll_read_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1013250661Sdavidcs{
1014250661Sdavidcs	int		i;
1015250661Sdavidcs	q8_poll_hdr_t	*phdr;
1016250661Sdavidcs	q8_poll_rd_e_t	*rd_e;
1017250661Sdavidcs	uint32_t	value;
1018250661Sdavidcs
1019250661Sdavidcs	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
1020250661Sdavidcs	rd_e = (q8_poll_rd_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
1021250661Sdavidcs
1022250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, rd_e++) {
1023250661Sdavidcs		if (ql_rdwr_indreg32(ha, rd_e->ar_addr, &rd_e->ar_value, 0)) {
1024250661Sdavidcs			device_printf(ha->pci_dev,
1025250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
1026250661Sdavidcs				rd_e->ar_addr, rd_e->ar_value);
1027250661Sdavidcs			return -1;
1028250661Sdavidcs		}
1029250661Sdavidcs
1030250661Sdavidcs		if (ce_hdr->delay_to)  {
1031250661Sdavidcs			if (qla_poll_reg(ha, rd_e->ar_addr, ce_hdr->delay_to,
1032250661Sdavidcs				phdr->tmask, phdr->tvalue)) {
1033250661Sdavidcs				return (-1);
1034250661Sdavidcs			} else {
1035250661Sdavidcs				if (ql_rdwr_indreg32(ha, rd_e->dr_addr,
1036250661Sdavidcs					&value, 1)) {
1037250661Sdavidcs					device_printf(ha->pci_dev,
1038250661Sdavidcs						"%s: [0x%08x] error\n",
1039250661Sdavidcs						__func__, rd_e->ar_addr);
1040250661Sdavidcs					return -1;
1041250661Sdavidcs				}
1042250661Sdavidcs
1043250661Sdavidcs				ha->hw.rst_seq[ha->hw.rst_seq_idx++] = value;
1044250661Sdavidcs				if (ha->hw.rst_seq_idx == Q8_MAX_RESET_SEQ_IDX)
1045250661Sdavidcs					ha->hw.rst_seq_idx = 1;
1046250661Sdavidcs			}
1047250661Sdavidcs		}
1048250661Sdavidcs	}
1049250661Sdavidcs	return 0;
1050250661Sdavidcs}
1051250661Sdavidcs
1052250661Sdavidcsstatic int
1053250661Sdavidcsqla_rdmwr(qla_host_t *ha, uint32_t raddr, uint32_t waddr, q8_rdmwr_hdr_t *hdr)
1054250661Sdavidcs{
1055250661Sdavidcs	uint32_t value;
1056250661Sdavidcs
1057250661Sdavidcs	if (hdr->index_a >= Q8_MAX_RESET_SEQ_IDX) {
1058250661Sdavidcs		device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1059250661Sdavidcs			hdr->index_a);
1060250661Sdavidcs		return -1;
1061250661Sdavidcs	}
1062250661Sdavidcs
1063250661Sdavidcs	if (hdr->index_a) {
1064250661Sdavidcs		value = ha->hw.rst_seq[hdr->index_a];
1065250661Sdavidcs	} else {
1066250661Sdavidcs		if (ql_rdwr_indreg32(ha, raddr, &value, 1)) {
1067250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
1068250661Sdavidcs						__func__, raddr);
1069250661Sdavidcs			return -1;
1070250661Sdavidcs		}
1071250661Sdavidcs	}
1072250661Sdavidcs
1073250661Sdavidcs	value &= hdr->and_value;
1074250661Sdavidcs	value <<= hdr->shl;
1075250661Sdavidcs	value >>= hdr->shr;
1076250661Sdavidcs	value |= hdr->or_value;
1077250661Sdavidcs	value ^= hdr->xor_value;
1078250661Sdavidcs
1079250661Sdavidcs	if (ql_rdwr_indreg32(ha, waddr, &value, 0)) {
1080250661Sdavidcs		device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1081250661Sdavidcs			raddr);
1082250661Sdavidcs		return -1;
1083250661Sdavidcs	}
1084250661Sdavidcs	return 0;
1085250661Sdavidcs}
1086250661Sdavidcs
1087250661Sdavidcsstatic int
1088250661Sdavidcsqla_read_modify_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1089250661Sdavidcs{
1090250661Sdavidcs	int		i;
1091250661Sdavidcs	q8_rdmwr_hdr_t	*rdmwr_hdr;
1092250661Sdavidcs	q8_rdmwr_e_t	*rdmwr_e;
1093250661Sdavidcs
1094250661Sdavidcs	rdmwr_hdr = (q8_rdmwr_hdr_t *)((uint8_t *)ce_hdr +
1095250661Sdavidcs						sizeof (q8_ce_hdr_t));
1096250661Sdavidcs	rdmwr_e = (q8_rdmwr_e_t *)((uint8_t *)rdmwr_hdr +
1097250661Sdavidcs					sizeof(q8_rdmwr_hdr_t));
1098250661Sdavidcs
1099250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, rdmwr_e++) {
1100250661Sdavidcs
1101250661Sdavidcs		if (qla_rdmwr(ha, rdmwr_e->rd_addr, rdmwr_e->wr_addr,
1102250661Sdavidcs			rdmwr_hdr)) {
1103250661Sdavidcs			return -1;
1104250661Sdavidcs		}
1105250661Sdavidcs		if (ce_hdr->delay_to) {
1106250661Sdavidcs			DELAY(ce_hdr->delay_to);
1107250661Sdavidcs		}
1108250661Sdavidcs	}
1109250661Sdavidcs	return 0;
1110250661Sdavidcs}
1111250661Sdavidcs
1112250661Sdavidcsstatic int
1113250661Sdavidcsqla_tmplt_execute(qla_host_t *ha, uint8_t *buf, int start_idx, int *end_idx,
1114250661Sdavidcs	uint32_t nentries)
1115250661Sdavidcs{
1116250661Sdavidcs	int i, ret = 0, proc_end = 0;
1117250661Sdavidcs	q8_ce_hdr_t	*ce_hdr;
1118250661Sdavidcs
1119250661Sdavidcs	for (i = start_idx; ((i < nentries) && (!proc_end)); i++) {
1120250661Sdavidcs		ce_hdr = (q8_ce_hdr_t *)buf;
1121250661Sdavidcs		ret = 0;
1122250661Sdavidcs
1123250661Sdavidcs		switch (ce_hdr->opcode) {
1124250661Sdavidcs		case Q8_CE_OPCODE_NOP:
1125250661Sdavidcs			break;
1126250661Sdavidcs
1127250661Sdavidcs		case Q8_CE_OPCODE_WRITE_LIST:
1128250661Sdavidcs			ret = qla_wr_list(ha, ce_hdr);
1129250661Sdavidcs			//printf("qla_wr_list %d\n", ret);
1130250661Sdavidcs			break;
1131250661Sdavidcs
1132250661Sdavidcs		case Q8_CE_OPCODE_READ_WRITE_LIST:
1133250661Sdavidcs			ret = qla_rd_wr_list(ha, ce_hdr);
1134250661Sdavidcs			//printf("qla_rd_wr_list %d\n", ret);
1135250661Sdavidcs			break;
1136250661Sdavidcs
1137250661Sdavidcs		case Q8_CE_OPCODE_POLL_LIST:
1138250661Sdavidcs			ret = qla_poll_list(ha, ce_hdr);
1139250661Sdavidcs			//printf("qla_poll_list %d\n", ret);
1140250661Sdavidcs			break;
1141250661Sdavidcs
1142250661Sdavidcs		case Q8_CE_OPCODE_POLL_WRITE_LIST:
1143250661Sdavidcs			ret = qla_poll_write_list(ha, ce_hdr);
1144250661Sdavidcs			//printf("qla_poll_write_list %d\n", ret);
1145250661Sdavidcs			break;
1146250661Sdavidcs
1147250661Sdavidcs		case Q8_CE_OPCODE_POLL_RD_LIST:
1148250661Sdavidcs			ret = qla_poll_read_list(ha, ce_hdr);
1149250661Sdavidcs			//printf("qla_poll_read_list %d\n", ret);
1150250661Sdavidcs			break;
1151250661Sdavidcs
1152250661Sdavidcs		case Q8_CE_OPCODE_READ_MODIFY_WRITE:
1153250661Sdavidcs			ret = qla_read_modify_write_list(ha, ce_hdr);
1154250661Sdavidcs			//printf("qla_read_modify_write_list %d\n", ret);
1155250661Sdavidcs			break;
1156250661Sdavidcs
1157250661Sdavidcs		case Q8_CE_OPCODE_SEQ_PAUSE:
1158250661Sdavidcs			if (ce_hdr->delay_to) {
1159250661Sdavidcs				qla_mdelay(__func__, ce_hdr->delay_to);
1160250661Sdavidcs			}
1161250661Sdavidcs			break;
1162250661Sdavidcs
1163250661Sdavidcs		case Q8_CE_OPCODE_SEQ_END:
1164250661Sdavidcs			proc_end = 1;
1165250661Sdavidcs			break;
1166250661Sdavidcs
1167250661Sdavidcs		case Q8_CE_OPCODE_TMPLT_END:
1168250661Sdavidcs			*end_idx = i;
1169250661Sdavidcs			return 0;
1170250661Sdavidcs		}
1171250661Sdavidcs
1172250661Sdavidcs		if (ret)
1173250661Sdavidcs			break;
1174250661Sdavidcs
1175250661Sdavidcs		buf += ce_hdr->size;
1176250661Sdavidcs	}
1177250661Sdavidcs	*end_idx = i;
1178250661Sdavidcs
1179250661Sdavidcs	return (ret);
1180250661Sdavidcs}
1181250661Sdavidcs
1182250661Sdavidcs
1183250661Sdavidcsstatic int
1184250661Sdavidcsqla_ld_fw_init(qla_host_t *ha)
1185250661Sdavidcs{
1186250661Sdavidcs	uint8_t *buf;
1187250661Sdavidcs	uint32_t index = 0, end_idx;
1188250661Sdavidcs	q8_tmplt_hdr_t *hdr;
1189250661Sdavidcs
1190250661Sdavidcs	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1191250661Sdavidcs
1192250661Sdavidcs	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1193250661Sdavidcs
1194250661Sdavidcs	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1195250661Sdavidcs		(uint32_t)hdr->size)) {
1196250661Sdavidcs		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1197250661Sdavidcs			__func__);
1198250661Sdavidcs		return -1;
1199250661Sdavidcs	}
1200250661Sdavidcs
1201250661Sdavidcs
1202250661Sdavidcs	buf = ql83xx_resetseq + hdr->stop_seq_off;
1203250661Sdavidcs
1204250661Sdavidcs//	device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1205250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1206250661Sdavidcs		device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1207250661Sdavidcs		return -1;
1208250661Sdavidcs	}
1209250661Sdavidcs
1210250661Sdavidcs	index = end_idx;
1211250661Sdavidcs
1212250661Sdavidcs	buf = ql83xx_resetseq + hdr->init_seq_off;
1213250661Sdavidcs
1214250661Sdavidcs//	device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1215250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1216250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1217250661Sdavidcs		return -1;
1218250661Sdavidcs	}
1219250661Sdavidcs
1220250661Sdavidcs	qla_load_fw_from_flash(ha);
1221250661Sdavidcs	WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
1222250661Sdavidcs
1223250661Sdavidcs	index = end_idx;
1224250661Sdavidcs	buf = ql83xx_resetseq + hdr->start_seq_off;
1225250661Sdavidcs
1226250661Sdavidcs//	device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1227250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1228250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1229250661Sdavidcs		return -1;
1230250661Sdavidcs	}
1231250661Sdavidcs
1232250661Sdavidcs	return 0;
1233250661Sdavidcs}
1234250661Sdavidcs
1235250661Sdavidcsint
1236250661Sdavidcsql_stop_sequence(qla_host_t *ha)
1237250661Sdavidcs{
1238250661Sdavidcs	uint8_t *buf;
1239250661Sdavidcs	uint32_t index = 0, end_idx;
1240250661Sdavidcs	q8_tmplt_hdr_t *hdr;
1241250661Sdavidcs
1242250661Sdavidcs	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1243250661Sdavidcs
1244250661Sdavidcs	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1245250661Sdavidcs
1246250661Sdavidcs	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1247250661Sdavidcs		(uint32_t)hdr->size)) {
1248250661Sdavidcs		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1249250661Sdavidcs		__func__);
1250250661Sdavidcs		return (-1);
1251250661Sdavidcs	}
1252250661Sdavidcs
1253250661Sdavidcs	buf = ql83xx_resetseq + hdr->stop_seq_off;
1254250661Sdavidcs
1255250661Sdavidcs	device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1256250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1257250661Sdavidcs		device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1258250661Sdavidcs		return (-1);
1259250661Sdavidcs	}
1260250661Sdavidcs
1261250661Sdavidcs	return end_idx;
1262250661Sdavidcs}
1263250661Sdavidcs
1264250661Sdavidcsint
1265250661Sdavidcsql_start_sequence(qla_host_t *ha, uint16_t index)
1266250661Sdavidcs{
1267250661Sdavidcs	uint8_t *buf;
1268250661Sdavidcs	uint32_t end_idx;
1269250661Sdavidcs	q8_tmplt_hdr_t *hdr;
1270250661Sdavidcs
1271250661Sdavidcs	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1272250661Sdavidcs
1273250661Sdavidcs	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1274250661Sdavidcs
1275250661Sdavidcs	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1276250661Sdavidcs		(uint32_t)hdr->size)) {
1277250661Sdavidcs		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1278250661Sdavidcs		__func__);
1279250661Sdavidcs		return (-1);
1280250661Sdavidcs	}
1281250661Sdavidcs
1282250661Sdavidcs	buf = ql83xx_resetseq + hdr->init_seq_off;
1283250661Sdavidcs
1284250661Sdavidcs	device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1285250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1286250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1287250661Sdavidcs		return (-1);
1288250661Sdavidcs	}
1289250661Sdavidcs
1290250661Sdavidcs	qla_load_fw_from_flash(ha);
1291250661Sdavidcs	WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
1292250661Sdavidcs
1293250661Sdavidcs	index = end_idx;
1294250661Sdavidcs	buf = ql83xx_resetseq + hdr->start_seq_off;
1295250661Sdavidcs
1296250661Sdavidcs	device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1297250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1298250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1299250661Sdavidcs		return -1;
1300250661Sdavidcs	}
1301250661Sdavidcs
1302250661Sdavidcs	return (0);
1303250661Sdavidcs}
1304250661Sdavidcs
1305