1331722Seadler/*
2284741Sdavidcs * Copyright (c) 2013-2016 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: stable/11/sys/dev/qlxgbe/ql_misc.c 331722 2018-03-29 02:50:57Z eadler $");
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);
80330555Sdavidcs		QL_INITIATE_RECOVERY(ha);
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
213330555Sdavidcs	QL_INITIATE_RECOVERY(ha);
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
664284741Sdavidcs#ifdef QL_LDFLASH_FW
665250661Sdavidcs/*
666250661Sdavidcs * Name: qla_load_fw_from_flash
667250661Sdavidcs * Function: Reads the Bootloader from Flash and Loads into Offchip Memory
668250661Sdavidcs */
669250661Sdavidcsstatic void
670250661Sdavidcsqla_load_fw_from_flash(qla_host_t *ha)
671250661Sdavidcs{
672250661Sdavidcs	uint32_t flash_off	= 0x10000;
673250661Sdavidcs	uint64_t mem_off;
674250661Sdavidcs	uint32_t count, mem_size;
675250661Sdavidcs	q80_offchip_mem_val_t val;
676250661Sdavidcs
677250661Sdavidcs	mem_off = (uint64_t)(READ_REG32(ha, Q8_BOOTLD_ADDR));
678250661Sdavidcs	mem_size = READ_REG32(ha, Q8_BOOTLD_SIZE);
679250661Sdavidcs
680250661Sdavidcs	device_printf(ha->pci_dev, "%s: [0x%08x][0x%08x]\n",
681250661Sdavidcs		__func__, (uint32_t)mem_off, mem_size);
682250661Sdavidcs
683250661Sdavidcs	/* only bootloader needs to be loaded into memory */
684250661Sdavidcs	for (count = 0; count < mem_size ; ) {
685250661Sdavidcs		ql_rd_flash32(ha, flash_off, &val.data_lo);
686250661Sdavidcs		count = count + 4;
687250661Sdavidcs		flash_off = flash_off + 4;
688250661Sdavidcs
689250661Sdavidcs		ql_rd_flash32(ha, flash_off, &val.data_hi);
690250661Sdavidcs		count = count + 4;
691250661Sdavidcs		flash_off = flash_off + 4;
692250661Sdavidcs
693250661Sdavidcs		ql_rd_flash32(ha, flash_off, &val.data_ulo);
694250661Sdavidcs		count = count + 4;
695250661Sdavidcs		flash_off = flash_off + 4;
696250661Sdavidcs
697250661Sdavidcs		ql_rd_flash32(ha, flash_off, &val.data_uhi);
698250661Sdavidcs		count = count + 4;
699250661Sdavidcs		flash_off = flash_off + 4;
700250661Sdavidcs
701250661Sdavidcs		ql_rdwr_offchip_mem(ha, mem_off, &val, 0);
702250661Sdavidcs
703250661Sdavidcs		mem_off = mem_off + 16;
704250661Sdavidcs	}
705250661Sdavidcs
706250661Sdavidcs	return;
707250661Sdavidcs}
708284741Sdavidcs#endif /* #ifdef QL_LDFLASH_FW */
709250661Sdavidcs
710250661Sdavidcs/*
711250661Sdavidcs * Name: qla_init_from_flash
712250661Sdavidcs * Function: Performs Initialization which consists of the following sequence
713250661Sdavidcs *	- reset
714250661Sdavidcs *	- CRB Init
715250661Sdavidcs *	- Peg Init
716250661Sdavidcs *	- Read the Bootloader from Flash and Load into Offchip Memory
717250661Sdavidcs *	- Kick start the bootloader which loads the rest of the firmware
718250661Sdavidcs *		and performs the remaining steps in the initialization process.
719250661Sdavidcs */
720250661Sdavidcsstatic int
721250661Sdavidcsqla_init_from_flash(qla_host_t *ha)
722250661Sdavidcs{
723250661Sdavidcs	uint32_t delay = 300;
724250661Sdavidcs	uint32_t data;
725250661Sdavidcs
726250661Sdavidcs	qla_ld_fw_init(ha);
727250661Sdavidcs
728250661Sdavidcs	do {
729250661Sdavidcs		data = READ_REG32(ha, Q8_CMDPEG_STATE);
730250661Sdavidcs
731250661Sdavidcs		QL_DPRINT2(ha,
732250661Sdavidcs			(ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
733250661Sdavidcs				__func__, ha->pci_func, data));
734250661Sdavidcs		if (data == 0xFF01) {
735250661Sdavidcs			QL_DPRINT2(ha, (ha->pci_dev,
736250661Sdavidcs				"%s: func[%d] init complete\n",
737250661Sdavidcs				__func__, ha->pci_func));
738250661Sdavidcs			return(0);
739250661Sdavidcs		}
740250661Sdavidcs		qla_mdelay(__func__, 100);
741250661Sdavidcs	} while (delay--);
742250661Sdavidcs
743250661Sdavidcs	return (-1);
744250661Sdavidcs}
745250661Sdavidcs
746250661Sdavidcs/*
747250661Sdavidcs * Name: ql_init_hw
748250661Sdavidcs * Function: Initializes P3+ hardware.
749250661Sdavidcs */
750250661Sdavidcsint
751250661Sdavidcsql_init_hw(qla_host_t *ha)
752250661Sdavidcs{
753250661Sdavidcs        device_t dev;
754250661Sdavidcs        int ret = 0;
755250661Sdavidcs        uint32_t val, delay = 300;
756250661Sdavidcs
757250661Sdavidcs        dev = ha->pci_dev;
758250661Sdavidcs
759250661Sdavidcs        QL_DPRINT1(ha, (dev, "%s: enter\n", __func__));
760250661Sdavidcs
761250661Sdavidcs	if (ha->pci_func & 0x1) {
762250661Sdavidcs
763250661Sdavidcs        	while ((ha->pci_func & 0x1) && delay--) {
764250661Sdavidcs
765250661Sdavidcs			val = READ_REG32(ha, Q8_CMDPEG_STATE);
766250661Sdavidcs
767250661Sdavidcs			if (val == 0xFF01) {
768250661Sdavidcs				QL_DPRINT2(ha, (dev,
769250661Sdavidcs					"%s: func = %d init complete\n",
770250661Sdavidcs					__func__, ha->pci_func));
771250661Sdavidcs				qla_mdelay(__func__, 100);
772250661Sdavidcs				goto qla_init_exit;
773250661Sdavidcs			}
774250661Sdavidcs			qla_mdelay(__func__, 100);
775250661Sdavidcs		}
776330555Sdavidcs		ret = -1;
777330555Sdavidcs		goto ql_init_hw_exit;
778250661Sdavidcs	}
779250661Sdavidcs
780250661Sdavidcs
781250661Sdavidcs	val = READ_REG32(ha, Q8_CMDPEG_STATE);
782330555Sdavidcs	if (!cold || (val != 0xFF01) || ha->qla_initiate_recovery) {
783250661Sdavidcs        	ret = qla_init_from_flash(ha);
784250661Sdavidcs		qla_mdelay(__func__, 100);
785250661Sdavidcs	}
786250661Sdavidcs
787250661Sdavidcsqla_init_exit:
788250661Sdavidcs        ha->fw_ver_major = READ_REG32(ha, Q8_FW_VER_MAJOR);
789250661Sdavidcs        ha->fw_ver_minor = READ_REG32(ha, Q8_FW_VER_MINOR);
790250661Sdavidcs        ha->fw_ver_sub = READ_REG32(ha, Q8_FW_VER_SUB);
791250661Sdavidcs
792250661Sdavidcs	if (qla_get_fdt(ha) != 0) {
793250661Sdavidcs		device_printf(dev, "%s: qla_get_fdt failed\n", __func__);
794250661Sdavidcs	} else {
795250661Sdavidcs		ha->hw.flags.fdt_valid = 1;
796250661Sdavidcs	}
797250661Sdavidcs
798330555Sdavidcsql_init_hw_exit:
799330555Sdavidcs
800330555Sdavidcs	if (ret) {
801330555Sdavidcs		if (ha->hw.sp_log_stop_events & Q8_SP_LOG_STOP_HW_INIT_FAILURE)
802330555Sdavidcs			ha->hw.sp_log_stop = -1;
803330555Sdavidcs	}
804330555Sdavidcs
805250661Sdavidcs        return (ret);
806250661Sdavidcs}
807250661Sdavidcs
808250661Sdavidcsvoid
809250661Sdavidcsql_read_mac_addr(qla_host_t *ha)
810250661Sdavidcs{
811250661Sdavidcs	uint8_t *macp;
812250661Sdavidcs	uint32_t mac_lo;
813250661Sdavidcs	uint32_t mac_hi;
814250661Sdavidcs	uint32_t flash_off;
815250661Sdavidcs
816250661Sdavidcs	flash_off = Q8_BOARD_CONFIG_OFFSET + Q8_BOARD_CONFIG_MAC0_LO +
817250661Sdavidcs			(ha->pci_func << 3);
818250661Sdavidcs	ql_rd_flash32(ha, flash_off, &mac_lo);
819250661Sdavidcs
820250661Sdavidcs	flash_off += 4;
821250661Sdavidcs	ql_rd_flash32(ha, flash_off, &mac_hi);
822250661Sdavidcs
823250661Sdavidcs	macp = (uint8_t *)&mac_lo;
824250661Sdavidcs	ha->hw.mac_addr[5] = macp[0];
825250661Sdavidcs	ha->hw.mac_addr[4] = macp[1];
826250661Sdavidcs	ha->hw.mac_addr[3] = macp[2];
827250661Sdavidcs	ha->hw.mac_addr[2] = macp[3];
828250661Sdavidcs
829250661Sdavidcs	macp = (uint8_t *)&mac_hi;
830250661Sdavidcs	ha->hw.mac_addr[1] = macp[0];
831250661Sdavidcs	ha->hw.mac_addr[0] = macp[1];
832250661Sdavidcs
833250661Sdavidcs	//device_printf(ha->pci_dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
834250661Sdavidcs	//	__func__, ha->hw.mac_addr[0], ha->hw.mac_addr[1],
835250661Sdavidcs	//	ha->hw.mac_addr[2], ha->hw.mac_addr[3],
836250661Sdavidcs	//	ha->hw.mac_addr[4], ha->hw.mac_addr[5]);
837250661Sdavidcs
838250661Sdavidcs        return;
839250661Sdavidcs}
840250661Sdavidcs
841250661Sdavidcs/*
842250661Sdavidcs * Stop/Start/Initialization Handling
843250661Sdavidcs */
844250661Sdavidcs
845250661Sdavidcsstatic uint16_t
846250661Sdavidcsqla_tmplt_16bit_checksum(qla_host_t *ha, uint16_t *buf, uint32_t size)
847250661Sdavidcs{
848250661Sdavidcs	uint32_t sum = 0;
849250661Sdavidcs	uint32_t count = size >> 1; /* size in 16 bit words */
850250661Sdavidcs
851250661Sdavidcs	while (count-- > 0)
852250661Sdavidcs		sum += *buf++;
853250661Sdavidcs
854250661Sdavidcs	while (sum >> 16)
855250661Sdavidcs		sum = (sum & 0xFFFF) + (sum >> 16);
856250661Sdavidcs
857250661Sdavidcs	return (~sum);
858250661Sdavidcs}
859250661Sdavidcs
860250661Sdavidcsstatic int
861250661Sdavidcsqla_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
862250661Sdavidcs{
863250661Sdavidcs	q8_wrl_e_t *wr_l;
864250661Sdavidcs	int i;
865250661Sdavidcs
866250661Sdavidcs	wr_l = (q8_wrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
867250661Sdavidcs
868250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, wr_l++) {
869250661Sdavidcs
870250661Sdavidcs		if (ql_rdwr_indreg32(ha, wr_l->addr, &wr_l->value, 0)) {
871250661Sdavidcs			device_printf(ha->pci_dev,
872250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
873250661Sdavidcs				wr_l->addr, wr_l->value);
874250661Sdavidcs			return -1;
875250661Sdavidcs		}
876250661Sdavidcs		if (ce_hdr->delay_to) {
877250661Sdavidcs			DELAY(ce_hdr->delay_to);
878250661Sdavidcs		}
879250661Sdavidcs	}
880250661Sdavidcs	return 0;
881250661Sdavidcs}
882250661Sdavidcs
883250661Sdavidcsstatic int
884250661Sdavidcsqla_rd_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
885250661Sdavidcs{
886250661Sdavidcs	q8_rdwrl_e_t *rd_wr_l;
887250661Sdavidcs	uint32_t data;
888250661Sdavidcs	int i;
889250661Sdavidcs
890250661Sdavidcs	rd_wr_l = (q8_rdwrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
891250661Sdavidcs
892250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, rd_wr_l++) {
893250661Sdavidcs
894250661Sdavidcs		if (ql_rdwr_indreg32(ha, rd_wr_l->rd_addr, &data, 1)) {
895250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
896250661Sdavidcs				__func__, rd_wr_l->rd_addr);
897250661Sdavidcs
898250661Sdavidcs			return -1;
899250661Sdavidcs		}
900250661Sdavidcs
901250661Sdavidcs		if (ql_rdwr_indreg32(ha, rd_wr_l->wr_addr, &data, 0)) {
902250661Sdavidcs			device_printf(ha->pci_dev,
903250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
904250661Sdavidcs				rd_wr_l->wr_addr, data);
905250661Sdavidcs			return -1;
906250661Sdavidcs		}
907250661Sdavidcs		if (ce_hdr->delay_to) {
908250661Sdavidcs			DELAY(ce_hdr->delay_to);
909250661Sdavidcs		}
910250661Sdavidcs	}
911250661Sdavidcs	return 0;
912250661Sdavidcs}
913250661Sdavidcs
914250661Sdavidcsstatic int
915250661Sdavidcsqla_poll_reg(qla_host_t *ha, uint32_t addr, uint32_t ms_to, uint32_t tmask,
916250661Sdavidcs	uint32_t tvalue)
917250661Sdavidcs{
918250661Sdavidcs	uint32_t data;
919250661Sdavidcs
920250661Sdavidcs	while (ms_to) {
921250661Sdavidcs
922250661Sdavidcs		if (ql_rdwr_indreg32(ha, addr, &data, 1)) {
923250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
924250661Sdavidcs				__func__, addr);
925250661Sdavidcs			return -1;
926250661Sdavidcs		}
927250661Sdavidcs
928250661Sdavidcs		if ((data & tmask) != tvalue) {
929250661Sdavidcs			ms_to--;
930250661Sdavidcs		} else
931250661Sdavidcs			break;
932250661Sdavidcs
933250661Sdavidcs		qla_mdelay(__func__, 1);
934250661Sdavidcs	}
935250661Sdavidcs	return ((ms_to ? 0: -1));
936250661Sdavidcs}
937250661Sdavidcs
938250661Sdavidcsstatic int
939250661Sdavidcsqla_poll_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
940250661Sdavidcs{
941250661Sdavidcs	int		i;
942250661Sdavidcs	q8_poll_hdr_t	*phdr;
943250661Sdavidcs	q8_poll_e_t	*pe;
944250661Sdavidcs	uint32_t	data;
945250661Sdavidcs
946250661Sdavidcs	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
947250661Sdavidcs	pe = (q8_poll_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
948250661Sdavidcs
949250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, pe++) {
950250661Sdavidcs		if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
951250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
952250661Sdavidcs				__func__, pe->addr);
953250661Sdavidcs			return -1;
954250661Sdavidcs		}
955250661Sdavidcs
956250661Sdavidcs		if (ce_hdr->delay_to)  {
957250661Sdavidcs			if ((data & phdr->tmask) == phdr->tvalue)
958250661Sdavidcs				break;
959250661Sdavidcs			if (qla_poll_reg(ha, pe->addr, ce_hdr->delay_to,
960250661Sdavidcs				phdr->tmask, phdr->tvalue)) {
961250661Sdavidcs
962250661Sdavidcs				if (ql_rdwr_indreg32(ha, pe->to_addr, &data,
963250661Sdavidcs					1)) {
964250661Sdavidcs					device_printf(ha->pci_dev,
965250661Sdavidcs						"%s: [0x%08x] error\n",
966250661Sdavidcs						__func__, pe->to_addr);
967250661Sdavidcs					return -1;
968250661Sdavidcs				}
969250661Sdavidcs
970250661Sdavidcs				if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
971250661Sdavidcs					device_printf(ha->pci_dev,
972250661Sdavidcs						"%s: [0x%08x] error\n",
973250661Sdavidcs						__func__, pe->addr);
974250661Sdavidcs					return -1;
975250661Sdavidcs				}
976250661Sdavidcs			}
977250661Sdavidcs		}
978250661Sdavidcs	}
979250661Sdavidcs	return 0;
980250661Sdavidcs}
981250661Sdavidcs
982250661Sdavidcsstatic int
983250661Sdavidcsqla_poll_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
984250661Sdavidcs{
985250661Sdavidcs	int		i;
986250661Sdavidcs	q8_poll_hdr_t	*phdr;
987250661Sdavidcs	q8_poll_wr_e_t	*wr_e;
988250661Sdavidcs
989250661Sdavidcs	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
990250661Sdavidcs	wr_e = (q8_poll_wr_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
991250661Sdavidcs
992250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, wr_e++) {
993250661Sdavidcs
994250661Sdavidcs		if (ql_rdwr_indreg32(ha, wr_e->dr_addr, &wr_e->dr_value, 0)) {
995250661Sdavidcs			device_printf(ha->pci_dev,
996250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
997250661Sdavidcs				wr_e->dr_addr, wr_e->dr_value);
998250661Sdavidcs			return -1;
999250661Sdavidcs		}
1000250661Sdavidcs		if (ql_rdwr_indreg32(ha, wr_e->ar_addr, &wr_e->ar_value, 0)) {
1001250661Sdavidcs			device_printf(ha->pci_dev,
1002250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
1003250661Sdavidcs				wr_e->ar_addr, wr_e->ar_value);
1004250661Sdavidcs			return -1;
1005250661Sdavidcs		}
1006250661Sdavidcs		if (ce_hdr->delay_to)  {
1007250661Sdavidcs			if (qla_poll_reg(ha, wr_e->ar_addr, ce_hdr->delay_to,
1008250661Sdavidcs				phdr->tmask, phdr->tvalue))
1009250661Sdavidcs				device_printf(ha->pci_dev, "%s: "
1010250661Sdavidcs					"[ar_addr, ar_value, delay, tmask,"
1011250661Sdavidcs					"tvalue] [0x%08x 0x%08x 0x%08x 0x%08x"
1012250661Sdavidcs					" 0x%08x]\n",
1013250661Sdavidcs					__func__, wr_e->ar_addr, wr_e->ar_value,
1014250661Sdavidcs					ce_hdr->delay_to, phdr->tmask,
1015250661Sdavidcs					phdr->tvalue);
1016250661Sdavidcs		}
1017250661Sdavidcs	}
1018250661Sdavidcs	return 0;
1019250661Sdavidcs}
1020250661Sdavidcs
1021250661Sdavidcsstatic int
1022250661Sdavidcsqla_poll_read_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1023250661Sdavidcs{
1024250661Sdavidcs	int		i;
1025250661Sdavidcs	q8_poll_hdr_t	*phdr;
1026250661Sdavidcs	q8_poll_rd_e_t	*rd_e;
1027250661Sdavidcs	uint32_t	value;
1028250661Sdavidcs
1029250661Sdavidcs	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
1030250661Sdavidcs	rd_e = (q8_poll_rd_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
1031250661Sdavidcs
1032250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, rd_e++) {
1033250661Sdavidcs		if (ql_rdwr_indreg32(ha, rd_e->ar_addr, &rd_e->ar_value, 0)) {
1034250661Sdavidcs			device_printf(ha->pci_dev,
1035250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
1036250661Sdavidcs				rd_e->ar_addr, rd_e->ar_value);
1037250661Sdavidcs			return -1;
1038250661Sdavidcs		}
1039250661Sdavidcs
1040250661Sdavidcs		if (ce_hdr->delay_to)  {
1041250661Sdavidcs			if (qla_poll_reg(ha, rd_e->ar_addr, ce_hdr->delay_to,
1042250661Sdavidcs				phdr->tmask, phdr->tvalue)) {
1043250661Sdavidcs				return (-1);
1044250661Sdavidcs			} else {
1045250661Sdavidcs				if (ql_rdwr_indreg32(ha, rd_e->dr_addr,
1046250661Sdavidcs					&value, 1)) {
1047250661Sdavidcs					device_printf(ha->pci_dev,
1048250661Sdavidcs						"%s: [0x%08x] error\n",
1049250661Sdavidcs						__func__, rd_e->ar_addr);
1050250661Sdavidcs					return -1;
1051250661Sdavidcs				}
1052250661Sdavidcs
1053250661Sdavidcs				ha->hw.rst_seq[ha->hw.rst_seq_idx++] = value;
1054250661Sdavidcs				if (ha->hw.rst_seq_idx == Q8_MAX_RESET_SEQ_IDX)
1055250661Sdavidcs					ha->hw.rst_seq_idx = 1;
1056250661Sdavidcs			}
1057250661Sdavidcs		}
1058250661Sdavidcs	}
1059250661Sdavidcs	return 0;
1060250661Sdavidcs}
1061250661Sdavidcs
1062250661Sdavidcsstatic int
1063250661Sdavidcsqla_rdmwr(qla_host_t *ha, uint32_t raddr, uint32_t waddr, q8_rdmwr_hdr_t *hdr)
1064250661Sdavidcs{
1065250661Sdavidcs	uint32_t value;
1066250661Sdavidcs
1067250661Sdavidcs	if (hdr->index_a >= Q8_MAX_RESET_SEQ_IDX) {
1068250661Sdavidcs		device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1069250661Sdavidcs			hdr->index_a);
1070250661Sdavidcs		return -1;
1071250661Sdavidcs	}
1072250661Sdavidcs
1073250661Sdavidcs	if (hdr->index_a) {
1074250661Sdavidcs		value = ha->hw.rst_seq[hdr->index_a];
1075250661Sdavidcs	} else {
1076250661Sdavidcs		if (ql_rdwr_indreg32(ha, raddr, &value, 1)) {
1077250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
1078250661Sdavidcs						__func__, raddr);
1079250661Sdavidcs			return -1;
1080250661Sdavidcs		}
1081250661Sdavidcs	}
1082250661Sdavidcs
1083250661Sdavidcs	value &= hdr->and_value;
1084250661Sdavidcs	value <<= hdr->shl;
1085250661Sdavidcs	value >>= hdr->shr;
1086250661Sdavidcs	value |= hdr->or_value;
1087250661Sdavidcs	value ^= hdr->xor_value;
1088250661Sdavidcs
1089250661Sdavidcs	if (ql_rdwr_indreg32(ha, waddr, &value, 0)) {
1090250661Sdavidcs		device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1091250661Sdavidcs			raddr);
1092250661Sdavidcs		return -1;
1093250661Sdavidcs	}
1094250661Sdavidcs	return 0;
1095250661Sdavidcs}
1096250661Sdavidcs
1097250661Sdavidcsstatic int
1098250661Sdavidcsqla_read_modify_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1099250661Sdavidcs{
1100250661Sdavidcs	int		i;
1101250661Sdavidcs	q8_rdmwr_hdr_t	*rdmwr_hdr;
1102250661Sdavidcs	q8_rdmwr_e_t	*rdmwr_e;
1103250661Sdavidcs
1104250661Sdavidcs	rdmwr_hdr = (q8_rdmwr_hdr_t *)((uint8_t *)ce_hdr +
1105250661Sdavidcs						sizeof (q8_ce_hdr_t));
1106250661Sdavidcs	rdmwr_e = (q8_rdmwr_e_t *)((uint8_t *)rdmwr_hdr +
1107250661Sdavidcs					sizeof(q8_rdmwr_hdr_t));
1108250661Sdavidcs
1109250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, rdmwr_e++) {
1110250661Sdavidcs
1111250661Sdavidcs		if (qla_rdmwr(ha, rdmwr_e->rd_addr, rdmwr_e->wr_addr,
1112250661Sdavidcs			rdmwr_hdr)) {
1113250661Sdavidcs			return -1;
1114250661Sdavidcs		}
1115250661Sdavidcs		if (ce_hdr->delay_to) {
1116250661Sdavidcs			DELAY(ce_hdr->delay_to);
1117250661Sdavidcs		}
1118250661Sdavidcs	}
1119250661Sdavidcs	return 0;
1120250661Sdavidcs}
1121250661Sdavidcs
1122250661Sdavidcsstatic int
1123250661Sdavidcsqla_tmplt_execute(qla_host_t *ha, uint8_t *buf, int start_idx, int *end_idx,
1124250661Sdavidcs	uint32_t nentries)
1125250661Sdavidcs{
1126250661Sdavidcs	int i, ret = 0, proc_end = 0;
1127250661Sdavidcs	q8_ce_hdr_t	*ce_hdr;
1128250661Sdavidcs
1129250661Sdavidcs	for (i = start_idx; ((i < nentries) && (!proc_end)); i++) {
1130250661Sdavidcs		ce_hdr = (q8_ce_hdr_t *)buf;
1131250661Sdavidcs		ret = 0;
1132250661Sdavidcs
1133250661Sdavidcs		switch (ce_hdr->opcode) {
1134250661Sdavidcs		case Q8_CE_OPCODE_NOP:
1135250661Sdavidcs			break;
1136250661Sdavidcs
1137250661Sdavidcs		case Q8_CE_OPCODE_WRITE_LIST:
1138250661Sdavidcs			ret = qla_wr_list(ha, ce_hdr);
1139250661Sdavidcs			//printf("qla_wr_list %d\n", ret);
1140250661Sdavidcs			break;
1141250661Sdavidcs
1142250661Sdavidcs		case Q8_CE_OPCODE_READ_WRITE_LIST:
1143250661Sdavidcs			ret = qla_rd_wr_list(ha, ce_hdr);
1144250661Sdavidcs			//printf("qla_rd_wr_list %d\n", ret);
1145250661Sdavidcs			break;
1146250661Sdavidcs
1147250661Sdavidcs		case Q8_CE_OPCODE_POLL_LIST:
1148250661Sdavidcs			ret = qla_poll_list(ha, ce_hdr);
1149250661Sdavidcs			//printf("qla_poll_list %d\n", ret);
1150250661Sdavidcs			break;
1151250661Sdavidcs
1152250661Sdavidcs		case Q8_CE_OPCODE_POLL_WRITE_LIST:
1153250661Sdavidcs			ret = qla_poll_write_list(ha, ce_hdr);
1154250661Sdavidcs			//printf("qla_poll_write_list %d\n", ret);
1155250661Sdavidcs			break;
1156250661Sdavidcs
1157250661Sdavidcs		case Q8_CE_OPCODE_POLL_RD_LIST:
1158250661Sdavidcs			ret = qla_poll_read_list(ha, ce_hdr);
1159250661Sdavidcs			//printf("qla_poll_read_list %d\n", ret);
1160250661Sdavidcs			break;
1161250661Sdavidcs
1162250661Sdavidcs		case Q8_CE_OPCODE_READ_MODIFY_WRITE:
1163250661Sdavidcs			ret = qla_read_modify_write_list(ha, ce_hdr);
1164250661Sdavidcs			//printf("qla_read_modify_write_list %d\n", ret);
1165250661Sdavidcs			break;
1166250661Sdavidcs
1167250661Sdavidcs		case Q8_CE_OPCODE_SEQ_PAUSE:
1168250661Sdavidcs			if (ce_hdr->delay_to) {
1169250661Sdavidcs				qla_mdelay(__func__, ce_hdr->delay_to);
1170250661Sdavidcs			}
1171250661Sdavidcs			break;
1172250661Sdavidcs
1173250661Sdavidcs		case Q8_CE_OPCODE_SEQ_END:
1174250661Sdavidcs			proc_end = 1;
1175250661Sdavidcs			break;
1176250661Sdavidcs
1177250661Sdavidcs		case Q8_CE_OPCODE_TMPLT_END:
1178250661Sdavidcs			*end_idx = i;
1179250661Sdavidcs			return 0;
1180250661Sdavidcs		}
1181250661Sdavidcs
1182250661Sdavidcs		if (ret)
1183250661Sdavidcs			break;
1184250661Sdavidcs
1185250661Sdavidcs		buf += ce_hdr->size;
1186250661Sdavidcs	}
1187250661Sdavidcs	*end_idx = i;
1188250661Sdavidcs
1189250661Sdavidcs	return (ret);
1190250661Sdavidcs}
1191250661Sdavidcs
1192284741Sdavidcs#ifndef QL_LDFLASH_FW
1193284741Sdavidcsstatic int
1194284741Sdavidcsqla_load_offchip_mem(qla_host_t *ha, uint64_t addr, uint32_t *data32,
1195284741Sdavidcs        uint32_t len32)
1196284741Sdavidcs{
1197284741Sdavidcs        q80_offchip_mem_val_t val;
1198284741Sdavidcs        int             ret = 0;
1199250661Sdavidcs
1200284741Sdavidcs        while (len32) {
1201284741Sdavidcs                if (len32 > 4) {
1202284741Sdavidcs                        val.data_lo = *data32++;
1203284741Sdavidcs                        val.data_hi = *data32++;
1204284741Sdavidcs                        val.data_ulo = *data32++;
1205284741Sdavidcs                        val.data_uhi = *data32++;
1206284741Sdavidcs                        len32 -= 4;
1207284741Sdavidcs                        if (ql_rdwr_offchip_mem(ha, addr, &val, 0))
1208284741Sdavidcs                                return -1;
1209284741Sdavidcs
1210284741Sdavidcs                        addr += (uint64_t)16;
1211284741Sdavidcs                } else {
1212284741Sdavidcs                        break;
1213284741Sdavidcs                }
1214284741Sdavidcs        }
1215284741Sdavidcs
1216284741Sdavidcs        bzero(&val, sizeof(q80_offchip_mem_val_t));
1217284741Sdavidcs
1218284741Sdavidcs        switch (len32) {
1219284741Sdavidcs        case 3:
1220284741Sdavidcs                val.data_lo = *data32++;
1221284741Sdavidcs                val.data_hi = *data32++;
1222284741Sdavidcs                val.data_ulo = *data32++;
1223284741Sdavidcs                 ret = ql_rdwr_offchip_mem(ha, addr, &val, 0);
1224284741Sdavidcs                break;
1225284741Sdavidcs
1226284741Sdavidcs        case 2:
1227284741Sdavidcs                val.data_lo = *data32++;
1228284741Sdavidcs                val.data_hi = *data32++;
1229284741Sdavidcs                 ret = ql_rdwr_offchip_mem(ha, addr, &val, 0);
1230284741Sdavidcs                break;
1231284741Sdavidcs
1232284741Sdavidcs        case 1:
1233284741Sdavidcs                val.data_lo = *data32++;
1234284741Sdavidcs                ret = ql_rdwr_offchip_mem(ha, addr, &val, 0);
1235284741Sdavidcs                break;
1236284741Sdavidcs
1237284741Sdavidcs        default:
1238284741Sdavidcs                break;
1239284741Sdavidcs
1240284741Sdavidcs        }
1241284741Sdavidcs        return ret;
1242284741Sdavidcs}
1243284741Sdavidcs
1244284741Sdavidcs
1245250661Sdavidcsstatic int
1246284741Sdavidcsqla_load_bootldr(qla_host_t *ha)
1247284741Sdavidcs{
1248284741Sdavidcs        uint64_t        addr;
1249284741Sdavidcs        uint32_t        *data32;
1250284741Sdavidcs        uint32_t        len32;
1251284741Sdavidcs        int             ret;
1252284741Sdavidcs
1253284741Sdavidcs        addr = (uint64_t)(READ_REG32(ha, Q8_BOOTLD_ADDR));
1254284741Sdavidcs        data32 = (uint32_t *)ql83xx_bootloader;
1255284741Sdavidcs        len32 = ql83xx_bootloader_len >> 2;
1256284741Sdavidcs
1257284741Sdavidcs        ret = qla_load_offchip_mem(ha, addr, data32, len32);
1258284741Sdavidcs
1259284741Sdavidcs        return (ret);
1260284741Sdavidcs}
1261284741Sdavidcs
1262284741Sdavidcsstatic int
1263284741Sdavidcsqla_load_fwimage(qla_host_t *ha)
1264284741Sdavidcs{
1265284741Sdavidcs        uint64_t        addr;
1266284741Sdavidcs        uint32_t        *data32;
1267284741Sdavidcs        uint32_t        len32;
1268284741Sdavidcs        int             ret;
1269284741Sdavidcs
1270284741Sdavidcs        addr = (uint64_t)(READ_REG32(ha, Q8_FW_IMAGE_ADDR));
1271284741Sdavidcs        data32 = (uint32_t *)ql83xx_firmware;
1272284741Sdavidcs        len32 = ql83xx_firmware_len >> 2;
1273284741Sdavidcs
1274284741Sdavidcs        ret = qla_load_offchip_mem(ha, addr, data32, len32);
1275284741Sdavidcs
1276284741Sdavidcs        return (ret);
1277284741Sdavidcs}
1278284741Sdavidcs#endif /* #ifndef QL_LDFLASH_FW */
1279284741Sdavidcs
1280284741Sdavidcsstatic int
1281250661Sdavidcsqla_ld_fw_init(qla_host_t *ha)
1282250661Sdavidcs{
1283250661Sdavidcs	uint8_t *buf;
1284250661Sdavidcs	uint32_t index = 0, end_idx;
1285250661Sdavidcs	q8_tmplt_hdr_t *hdr;
1286250661Sdavidcs
1287250661Sdavidcs	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1288250661Sdavidcs
1289250661Sdavidcs	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1290250661Sdavidcs
1291330555Sdavidcs	device_printf(ha->pci_dev, "%s: reset sequence\n", __func__);
1292250661Sdavidcs	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1293250661Sdavidcs		(uint32_t)hdr->size)) {
1294250661Sdavidcs		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1295250661Sdavidcs			__func__);
1296250661Sdavidcs		return -1;
1297250661Sdavidcs	}
1298250661Sdavidcs
1299250661Sdavidcs
1300250661Sdavidcs	buf = ql83xx_resetseq + hdr->stop_seq_off;
1301250661Sdavidcs
1302330555Sdavidcs	device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1303250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1304250661Sdavidcs		device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1305250661Sdavidcs		return -1;
1306250661Sdavidcs	}
1307250661Sdavidcs
1308250661Sdavidcs	index = end_idx;
1309250661Sdavidcs
1310250661Sdavidcs	buf = ql83xx_resetseq + hdr->init_seq_off;
1311250661Sdavidcs
1312330555Sdavidcs	device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1313250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1314250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1315250661Sdavidcs		return -1;
1316250661Sdavidcs	}
1317250661Sdavidcs
1318284741Sdavidcs#ifdef QL_LDFLASH_FW
1319250661Sdavidcs	qla_load_fw_from_flash(ha);
1320250661Sdavidcs	WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
1321284741Sdavidcs#else
1322284741Sdavidcs        if (qla_load_bootldr(ha))
1323284741Sdavidcs                return -1;
1324250661Sdavidcs
1325284741Sdavidcs        if (qla_load_fwimage(ha))
1326284741Sdavidcs                return -1;
1327284741Sdavidcs
1328284741Sdavidcs        WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0x12345678);
1329284741Sdavidcs#endif /* #ifdef QL_LDFLASH_FW */
1330284741Sdavidcs
1331250661Sdavidcs	index = end_idx;
1332250661Sdavidcs	buf = ql83xx_resetseq + hdr->start_seq_off;
1333250661Sdavidcs
1334330555Sdavidcs	device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1335250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1336250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1337250661Sdavidcs		return -1;
1338250661Sdavidcs	}
1339250661Sdavidcs
1340250661Sdavidcs	return 0;
1341250661Sdavidcs}
1342250661Sdavidcs
1343250661Sdavidcsint
1344250661Sdavidcsql_stop_sequence(qla_host_t *ha)
1345250661Sdavidcs{
1346250661Sdavidcs	uint8_t *buf;
1347250661Sdavidcs	uint32_t index = 0, end_idx;
1348250661Sdavidcs	q8_tmplt_hdr_t *hdr;
1349250661Sdavidcs
1350250661Sdavidcs	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1351250661Sdavidcs
1352250661Sdavidcs	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1353250661Sdavidcs
1354250661Sdavidcs	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1355250661Sdavidcs		(uint32_t)hdr->size)) {
1356250661Sdavidcs		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1357250661Sdavidcs		__func__);
1358250661Sdavidcs		return (-1);
1359250661Sdavidcs	}
1360250661Sdavidcs
1361250661Sdavidcs	buf = ql83xx_resetseq + hdr->stop_seq_off;
1362250661Sdavidcs
1363250661Sdavidcs	device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1364250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1365250661Sdavidcs		device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1366250661Sdavidcs		return (-1);
1367250661Sdavidcs	}
1368250661Sdavidcs
1369250661Sdavidcs	return end_idx;
1370250661Sdavidcs}
1371250661Sdavidcs
1372250661Sdavidcsint
1373250661Sdavidcsql_start_sequence(qla_host_t *ha, uint16_t index)
1374250661Sdavidcs{
1375250661Sdavidcs	uint8_t *buf;
1376250661Sdavidcs	uint32_t end_idx;
1377250661Sdavidcs	q8_tmplt_hdr_t *hdr;
1378250661Sdavidcs
1379250661Sdavidcs	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1380250661Sdavidcs
1381250661Sdavidcs	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1382250661Sdavidcs
1383250661Sdavidcs	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1384250661Sdavidcs		(uint32_t)hdr->size)) {
1385250661Sdavidcs		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1386250661Sdavidcs		__func__);
1387250661Sdavidcs		return (-1);
1388250661Sdavidcs	}
1389250661Sdavidcs
1390250661Sdavidcs	buf = ql83xx_resetseq + hdr->init_seq_off;
1391250661Sdavidcs
1392250661Sdavidcs	device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1393250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1394250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1395250661Sdavidcs		return (-1);
1396250661Sdavidcs	}
1397250661Sdavidcs
1398284741Sdavidcs#ifdef QL_LDFLASH_FW
1399250661Sdavidcs	qla_load_fw_from_flash(ha);
1400250661Sdavidcs	WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
1401284741Sdavidcs#else
1402284741Sdavidcs        if (qla_load_bootldr(ha))
1403284741Sdavidcs                return -1;
1404250661Sdavidcs
1405284741Sdavidcs        if (qla_load_fwimage(ha))
1406284741Sdavidcs                return -1;
1407284741Sdavidcs
1408284741Sdavidcs        WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0x12345678);
1409284741Sdavidcs#endif /* #ifdef QL_LDFLASH_FW */
1410284741Sdavidcs
1411284741Sdavidcs
1412250661Sdavidcs	index = end_idx;
1413250661Sdavidcs	buf = ql83xx_resetseq + hdr->start_seq_off;
1414250661Sdavidcs
1415250661Sdavidcs	device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1416250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1417250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1418250661Sdavidcs		return -1;
1419250661Sdavidcs	}
1420250661Sdavidcs
1421250661Sdavidcs	return (0);
1422250661Sdavidcs}
1423250661Sdavidcs
1424