1250661Sdavidcs/*
2284982Sdavidcs * 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: releng/10.3/sys/dev/qlxgbe/ql_misc.c 284982 2015-06-30 20:59:07Z 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
664284982Sdavidcs#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}
708284982Sdavidcs#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		}
776250661Sdavidcs		return (-1);
777250661Sdavidcs	}
778250661Sdavidcs
779250661Sdavidcs
780250661Sdavidcs	val = READ_REG32(ha, Q8_CMDPEG_STATE);
781250661Sdavidcs	if (!cold || (val != 0xFF01)) {
782250661Sdavidcs        	ret = qla_init_from_flash(ha);
783250661Sdavidcs		qla_mdelay(__func__, 100);
784250661Sdavidcs	}
785250661Sdavidcs
786250661Sdavidcsqla_init_exit:
787250661Sdavidcs        ha->fw_ver_major = READ_REG32(ha, Q8_FW_VER_MAJOR);
788250661Sdavidcs        ha->fw_ver_minor = READ_REG32(ha, Q8_FW_VER_MINOR);
789250661Sdavidcs        ha->fw_ver_sub = READ_REG32(ha, Q8_FW_VER_SUB);
790250661Sdavidcs
791250661Sdavidcs	if (qla_get_fdt(ha) != 0) {
792250661Sdavidcs		device_printf(dev, "%s: qla_get_fdt failed\n", __func__);
793250661Sdavidcs	} else {
794250661Sdavidcs		ha->hw.flags.fdt_valid = 1;
795250661Sdavidcs	}
796250661Sdavidcs
797250661Sdavidcs        return (ret);
798250661Sdavidcs}
799250661Sdavidcs
800250661Sdavidcsvoid
801250661Sdavidcsql_read_mac_addr(qla_host_t *ha)
802250661Sdavidcs{
803250661Sdavidcs	uint8_t *macp;
804250661Sdavidcs	uint32_t mac_lo;
805250661Sdavidcs	uint32_t mac_hi;
806250661Sdavidcs	uint32_t flash_off;
807250661Sdavidcs
808250661Sdavidcs	flash_off = Q8_BOARD_CONFIG_OFFSET + Q8_BOARD_CONFIG_MAC0_LO +
809250661Sdavidcs			(ha->pci_func << 3);
810250661Sdavidcs	ql_rd_flash32(ha, flash_off, &mac_lo);
811250661Sdavidcs
812250661Sdavidcs	flash_off += 4;
813250661Sdavidcs	ql_rd_flash32(ha, flash_off, &mac_hi);
814250661Sdavidcs
815250661Sdavidcs	macp = (uint8_t *)&mac_lo;
816250661Sdavidcs	ha->hw.mac_addr[5] = macp[0];
817250661Sdavidcs	ha->hw.mac_addr[4] = macp[1];
818250661Sdavidcs	ha->hw.mac_addr[3] = macp[2];
819250661Sdavidcs	ha->hw.mac_addr[2] = macp[3];
820250661Sdavidcs
821250661Sdavidcs	macp = (uint8_t *)&mac_hi;
822250661Sdavidcs	ha->hw.mac_addr[1] = macp[0];
823250661Sdavidcs	ha->hw.mac_addr[0] = macp[1];
824250661Sdavidcs
825250661Sdavidcs	//device_printf(ha->pci_dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
826250661Sdavidcs	//	__func__, ha->hw.mac_addr[0], ha->hw.mac_addr[1],
827250661Sdavidcs	//	ha->hw.mac_addr[2], ha->hw.mac_addr[3],
828250661Sdavidcs	//	ha->hw.mac_addr[4], ha->hw.mac_addr[5]);
829250661Sdavidcs
830250661Sdavidcs        return;
831250661Sdavidcs}
832250661Sdavidcs
833250661Sdavidcs/*
834250661Sdavidcs * Stop/Start/Initialization Handling
835250661Sdavidcs */
836250661Sdavidcs
837250661Sdavidcsstatic uint16_t
838250661Sdavidcsqla_tmplt_16bit_checksum(qla_host_t *ha, uint16_t *buf, uint32_t size)
839250661Sdavidcs{
840250661Sdavidcs	uint32_t sum = 0;
841250661Sdavidcs	uint32_t count = size >> 1; /* size in 16 bit words */
842250661Sdavidcs
843250661Sdavidcs	while (count-- > 0)
844250661Sdavidcs		sum += *buf++;
845250661Sdavidcs
846250661Sdavidcs	while (sum >> 16)
847250661Sdavidcs		sum = (sum & 0xFFFF) + (sum >> 16);
848250661Sdavidcs
849250661Sdavidcs	return (~sum);
850250661Sdavidcs}
851250661Sdavidcs
852250661Sdavidcsstatic int
853250661Sdavidcsqla_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
854250661Sdavidcs{
855250661Sdavidcs	q8_wrl_e_t *wr_l;
856250661Sdavidcs	int i;
857250661Sdavidcs
858250661Sdavidcs	wr_l = (q8_wrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
859250661Sdavidcs
860250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, wr_l++) {
861250661Sdavidcs
862250661Sdavidcs		if (ql_rdwr_indreg32(ha, wr_l->addr, &wr_l->value, 0)) {
863250661Sdavidcs			device_printf(ha->pci_dev,
864250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
865250661Sdavidcs				wr_l->addr, wr_l->value);
866250661Sdavidcs			return -1;
867250661Sdavidcs		}
868250661Sdavidcs		if (ce_hdr->delay_to) {
869250661Sdavidcs			DELAY(ce_hdr->delay_to);
870250661Sdavidcs		}
871250661Sdavidcs	}
872250661Sdavidcs	return 0;
873250661Sdavidcs}
874250661Sdavidcs
875250661Sdavidcsstatic int
876250661Sdavidcsqla_rd_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
877250661Sdavidcs{
878250661Sdavidcs	q8_rdwrl_e_t *rd_wr_l;
879250661Sdavidcs	uint32_t data;
880250661Sdavidcs	int i;
881250661Sdavidcs
882250661Sdavidcs	rd_wr_l = (q8_rdwrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
883250661Sdavidcs
884250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, rd_wr_l++) {
885250661Sdavidcs
886250661Sdavidcs		if (ql_rdwr_indreg32(ha, rd_wr_l->rd_addr, &data, 1)) {
887250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
888250661Sdavidcs				__func__, rd_wr_l->rd_addr);
889250661Sdavidcs
890250661Sdavidcs			return -1;
891250661Sdavidcs		}
892250661Sdavidcs
893250661Sdavidcs		if (ql_rdwr_indreg32(ha, rd_wr_l->wr_addr, &data, 0)) {
894250661Sdavidcs			device_printf(ha->pci_dev,
895250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
896250661Sdavidcs				rd_wr_l->wr_addr, data);
897250661Sdavidcs			return -1;
898250661Sdavidcs		}
899250661Sdavidcs		if (ce_hdr->delay_to) {
900250661Sdavidcs			DELAY(ce_hdr->delay_to);
901250661Sdavidcs		}
902250661Sdavidcs	}
903250661Sdavidcs	return 0;
904250661Sdavidcs}
905250661Sdavidcs
906250661Sdavidcsstatic int
907250661Sdavidcsqla_poll_reg(qla_host_t *ha, uint32_t addr, uint32_t ms_to, uint32_t tmask,
908250661Sdavidcs	uint32_t tvalue)
909250661Sdavidcs{
910250661Sdavidcs	uint32_t data;
911250661Sdavidcs
912250661Sdavidcs	while (ms_to) {
913250661Sdavidcs
914250661Sdavidcs		if (ql_rdwr_indreg32(ha, addr, &data, 1)) {
915250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
916250661Sdavidcs				__func__, addr);
917250661Sdavidcs			return -1;
918250661Sdavidcs		}
919250661Sdavidcs
920250661Sdavidcs		if ((data & tmask) != tvalue) {
921250661Sdavidcs			ms_to--;
922250661Sdavidcs		} else
923250661Sdavidcs			break;
924250661Sdavidcs
925250661Sdavidcs		qla_mdelay(__func__, 1);
926250661Sdavidcs	}
927250661Sdavidcs	return ((ms_to ? 0: -1));
928250661Sdavidcs}
929250661Sdavidcs
930250661Sdavidcsstatic int
931250661Sdavidcsqla_poll_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
932250661Sdavidcs{
933250661Sdavidcs	int		i;
934250661Sdavidcs	q8_poll_hdr_t	*phdr;
935250661Sdavidcs	q8_poll_e_t	*pe;
936250661Sdavidcs	uint32_t	data;
937250661Sdavidcs
938250661Sdavidcs	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
939250661Sdavidcs	pe = (q8_poll_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
940250661Sdavidcs
941250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, pe++) {
942250661Sdavidcs		if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
943250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
944250661Sdavidcs				__func__, pe->addr);
945250661Sdavidcs			return -1;
946250661Sdavidcs		}
947250661Sdavidcs
948250661Sdavidcs		if (ce_hdr->delay_to)  {
949250661Sdavidcs			if ((data & phdr->tmask) == phdr->tvalue)
950250661Sdavidcs				break;
951250661Sdavidcs			if (qla_poll_reg(ha, pe->addr, ce_hdr->delay_to,
952250661Sdavidcs				phdr->tmask, phdr->tvalue)) {
953250661Sdavidcs
954250661Sdavidcs				if (ql_rdwr_indreg32(ha, pe->to_addr, &data,
955250661Sdavidcs					1)) {
956250661Sdavidcs					device_printf(ha->pci_dev,
957250661Sdavidcs						"%s: [0x%08x] error\n",
958250661Sdavidcs						__func__, pe->to_addr);
959250661Sdavidcs					return -1;
960250661Sdavidcs				}
961250661Sdavidcs
962250661Sdavidcs				if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
963250661Sdavidcs					device_printf(ha->pci_dev,
964250661Sdavidcs						"%s: [0x%08x] error\n",
965250661Sdavidcs						__func__, pe->addr);
966250661Sdavidcs					return -1;
967250661Sdavidcs				}
968250661Sdavidcs			}
969250661Sdavidcs		}
970250661Sdavidcs	}
971250661Sdavidcs	return 0;
972250661Sdavidcs}
973250661Sdavidcs
974250661Sdavidcsstatic int
975250661Sdavidcsqla_poll_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
976250661Sdavidcs{
977250661Sdavidcs	int		i;
978250661Sdavidcs	q8_poll_hdr_t	*phdr;
979250661Sdavidcs	q8_poll_wr_e_t	*wr_e;
980250661Sdavidcs
981250661Sdavidcs	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
982250661Sdavidcs	wr_e = (q8_poll_wr_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
983250661Sdavidcs
984250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, wr_e++) {
985250661Sdavidcs
986250661Sdavidcs		if (ql_rdwr_indreg32(ha, wr_e->dr_addr, &wr_e->dr_value, 0)) {
987250661Sdavidcs			device_printf(ha->pci_dev,
988250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
989250661Sdavidcs				wr_e->dr_addr, wr_e->dr_value);
990250661Sdavidcs			return -1;
991250661Sdavidcs		}
992250661Sdavidcs		if (ql_rdwr_indreg32(ha, wr_e->ar_addr, &wr_e->ar_value, 0)) {
993250661Sdavidcs			device_printf(ha->pci_dev,
994250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
995250661Sdavidcs				wr_e->ar_addr, wr_e->ar_value);
996250661Sdavidcs			return -1;
997250661Sdavidcs		}
998250661Sdavidcs		if (ce_hdr->delay_to)  {
999250661Sdavidcs			if (qla_poll_reg(ha, wr_e->ar_addr, ce_hdr->delay_to,
1000250661Sdavidcs				phdr->tmask, phdr->tvalue))
1001250661Sdavidcs				device_printf(ha->pci_dev, "%s: "
1002250661Sdavidcs					"[ar_addr, ar_value, delay, tmask,"
1003250661Sdavidcs					"tvalue] [0x%08x 0x%08x 0x%08x 0x%08x"
1004250661Sdavidcs					" 0x%08x]\n",
1005250661Sdavidcs					__func__, wr_e->ar_addr, wr_e->ar_value,
1006250661Sdavidcs					ce_hdr->delay_to, phdr->tmask,
1007250661Sdavidcs					phdr->tvalue);
1008250661Sdavidcs		}
1009250661Sdavidcs	}
1010250661Sdavidcs	return 0;
1011250661Sdavidcs}
1012250661Sdavidcs
1013250661Sdavidcsstatic int
1014250661Sdavidcsqla_poll_read_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1015250661Sdavidcs{
1016250661Sdavidcs	int		i;
1017250661Sdavidcs	q8_poll_hdr_t	*phdr;
1018250661Sdavidcs	q8_poll_rd_e_t	*rd_e;
1019250661Sdavidcs	uint32_t	value;
1020250661Sdavidcs
1021250661Sdavidcs	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
1022250661Sdavidcs	rd_e = (q8_poll_rd_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
1023250661Sdavidcs
1024250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, rd_e++) {
1025250661Sdavidcs		if (ql_rdwr_indreg32(ha, rd_e->ar_addr, &rd_e->ar_value, 0)) {
1026250661Sdavidcs			device_printf(ha->pci_dev,
1027250661Sdavidcs				"%s: [0x%08x 0x%08x] error\n", __func__,
1028250661Sdavidcs				rd_e->ar_addr, rd_e->ar_value);
1029250661Sdavidcs			return -1;
1030250661Sdavidcs		}
1031250661Sdavidcs
1032250661Sdavidcs		if (ce_hdr->delay_to)  {
1033250661Sdavidcs			if (qla_poll_reg(ha, rd_e->ar_addr, ce_hdr->delay_to,
1034250661Sdavidcs				phdr->tmask, phdr->tvalue)) {
1035250661Sdavidcs				return (-1);
1036250661Sdavidcs			} else {
1037250661Sdavidcs				if (ql_rdwr_indreg32(ha, rd_e->dr_addr,
1038250661Sdavidcs					&value, 1)) {
1039250661Sdavidcs					device_printf(ha->pci_dev,
1040250661Sdavidcs						"%s: [0x%08x] error\n",
1041250661Sdavidcs						__func__, rd_e->ar_addr);
1042250661Sdavidcs					return -1;
1043250661Sdavidcs				}
1044250661Sdavidcs
1045250661Sdavidcs				ha->hw.rst_seq[ha->hw.rst_seq_idx++] = value;
1046250661Sdavidcs				if (ha->hw.rst_seq_idx == Q8_MAX_RESET_SEQ_IDX)
1047250661Sdavidcs					ha->hw.rst_seq_idx = 1;
1048250661Sdavidcs			}
1049250661Sdavidcs		}
1050250661Sdavidcs	}
1051250661Sdavidcs	return 0;
1052250661Sdavidcs}
1053250661Sdavidcs
1054250661Sdavidcsstatic int
1055250661Sdavidcsqla_rdmwr(qla_host_t *ha, uint32_t raddr, uint32_t waddr, q8_rdmwr_hdr_t *hdr)
1056250661Sdavidcs{
1057250661Sdavidcs	uint32_t value;
1058250661Sdavidcs
1059250661Sdavidcs	if (hdr->index_a >= Q8_MAX_RESET_SEQ_IDX) {
1060250661Sdavidcs		device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1061250661Sdavidcs			hdr->index_a);
1062250661Sdavidcs		return -1;
1063250661Sdavidcs	}
1064250661Sdavidcs
1065250661Sdavidcs	if (hdr->index_a) {
1066250661Sdavidcs		value = ha->hw.rst_seq[hdr->index_a];
1067250661Sdavidcs	} else {
1068250661Sdavidcs		if (ql_rdwr_indreg32(ha, raddr, &value, 1)) {
1069250661Sdavidcs			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
1070250661Sdavidcs						__func__, raddr);
1071250661Sdavidcs			return -1;
1072250661Sdavidcs		}
1073250661Sdavidcs	}
1074250661Sdavidcs
1075250661Sdavidcs	value &= hdr->and_value;
1076250661Sdavidcs	value <<= hdr->shl;
1077250661Sdavidcs	value >>= hdr->shr;
1078250661Sdavidcs	value |= hdr->or_value;
1079250661Sdavidcs	value ^= hdr->xor_value;
1080250661Sdavidcs
1081250661Sdavidcs	if (ql_rdwr_indreg32(ha, waddr, &value, 0)) {
1082250661Sdavidcs		device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1083250661Sdavidcs			raddr);
1084250661Sdavidcs		return -1;
1085250661Sdavidcs	}
1086250661Sdavidcs	return 0;
1087250661Sdavidcs}
1088250661Sdavidcs
1089250661Sdavidcsstatic int
1090250661Sdavidcsqla_read_modify_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1091250661Sdavidcs{
1092250661Sdavidcs	int		i;
1093250661Sdavidcs	q8_rdmwr_hdr_t	*rdmwr_hdr;
1094250661Sdavidcs	q8_rdmwr_e_t	*rdmwr_e;
1095250661Sdavidcs
1096250661Sdavidcs	rdmwr_hdr = (q8_rdmwr_hdr_t *)((uint8_t *)ce_hdr +
1097250661Sdavidcs						sizeof (q8_ce_hdr_t));
1098250661Sdavidcs	rdmwr_e = (q8_rdmwr_e_t *)((uint8_t *)rdmwr_hdr +
1099250661Sdavidcs					sizeof(q8_rdmwr_hdr_t));
1100250661Sdavidcs
1101250661Sdavidcs	for (i = 0; i < ce_hdr->opcount; i++, rdmwr_e++) {
1102250661Sdavidcs
1103250661Sdavidcs		if (qla_rdmwr(ha, rdmwr_e->rd_addr, rdmwr_e->wr_addr,
1104250661Sdavidcs			rdmwr_hdr)) {
1105250661Sdavidcs			return -1;
1106250661Sdavidcs		}
1107250661Sdavidcs		if (ce_hdr->delay_to) {
1108250661Sdavidcs			DELAY(ce_hdr->delay_to);
1109250661Sdavidcs		}
1110250661Sdavidcs	}
1111250661Sdavidcs	return 0;
1112250661Sdavidcs}
1113250661Sdavidcs
1114250661Sdavidcsstatic int
1115250661Sdavidcsqla_tmplt_execute(qla_host_t *ha, uint8_t *buf, int start_idx, int *end_idx,
1116250661Sdavidcs	uint32_t nentries)
1117250661Sdavidcs{
1118250661Sdavidcs	int i, ret = 0, proc_end = 0;
1119250661Sdavidcs	q8_ce_hdr_t	*ce_hdr;
1120250661Sdavidcs
1121250661Sdavidcs	for (i = start_idx; ((i < nentries) && (!proc_end)); i++) {
1122250661Sdavidcs		ce_hdr = (q8_ce_hdr_t *)buf;
1123250661Sdavidcs		ret = 0;
1124250661Sdavidcs
1125250661Sdavidcs		switch (ce_hdr->opcode) {
1126250661Sdavidcs		case Q8_CE_OPCODE_NOP:
1127250661Sdavidcs			break;
1128250661Sdavidcs
1129250661Sdavidcs		case Q8_CE_OPCODE_WRITE_LIST:
1130250661Sdavidcs			ret = qla_wr_list(ha, ce_hdr);
1131250661Sdavidcs			//printf("qla_wr_list %d\n", ret);
1132250661Sdavidcs			break;
1133250661Sdavidcs
1134250661Sdavidcs		case Q8_CE_OPCODE_READ_WRITE_LIST:
1135250661Sdavidcs			ret = qla_rd_wr_list(ha, ce_hdr);
1136250661Sdavidcs			//printf("qla_rd_wr_list %d\n", ret);
1137250661Sdavidcs			break;
1138250661Sdavidcs
1139250661Sdavidcs		case Q8_CE_OPCODE_POLL_LIST:
1140250661Sdavidcs			ret = qla_poll_list(ha, ce_hdr);
1141250661Sdavidcs			//printf("qla_poll_list %d\n", ret);
1142250661Sdavidcs			break;
1143250661Sdavidcs
1144250661Sdavidcs		case Q8_CE_OPCODE_POLL_WRITE_LIST:
1145250661Sdavidcs			ret = qla_poll_write_list(ha, ce_hdr);
1146250661Sdavidcs			//printf("qla_poll_write_list %d\n", ret);
1147250661Sdavidcs			break;
1148250661Sdavidcs
1149250661Sdavidcs		case Q8_CE_OPCODE_POLL_RD_LIST:
1150250661Sdavidcs			ret = qla_poll_read_list(ha, ce_hdr);
1151250661Sdavidcs			//printf("qla_poll_read_list %d\n", ret);
1152250661Sdavidcs			break;
1153250661Sdavidcs
1154250661Sdavidcs		case Q8_CE_OPCODE_READ_MODIFY_WRITE:
1155250661Sdavidcs			ret = qla_read_modify_write_list(ha, ce_hdr);
1156250661Sdavidcs			//printf("qla_read_modify_write_list %d\n", ret);
1157250661Sdavidcs			break;
1158250661Sdavidcs
1159250661Sdavidcs		case Q8_CE_OPCODE_SEQ_PAUSE:
1160250661Sdavidcs			if (ce_hdr->delay_to) {
1161250661Sdavidcs				qla_mdelay(__func__, ce_hdr->delay_to);
1162250661Sdavidcs			}
1163250661Sdavidcs			break;
1164250661Sdavidcs
1165250661Sdavidcs		case Q8_CE_OPCODE_SEQ_END:
1166250661Sdavidcs			proc_end = 1;
1167250661Sdavidcs			break;
1168250661Sdavidcs
1169250661Sdavidcs		case Q8_CE_OPCODE_TMPLT_END:
1170250661Sdavidcs			*end_idx = i;
1171250661Sdavidcs			return 0;
1172250661Sdavidcs		}
1173250661Sdavidcs
1174250661Sdavidcs		if (ret)
1175250661Sdavidcs			break;
1176250661Sdavidcs
1177250661Sdavidcs		buf += ce_hdr->size;
1178250661Sdavidcs	}
1179250661Sdavidcs	*end_idx = i;
1180250661Sdavidcs
1181250661Sdavidcs	return (ret);
1182250661Sdavidcs}
1183250661Sdavidcs
1184284982Sdavidcs#ifndef QL_LDFLASH_FW
1185284982Sdavidcsstatic int
1186284982Sdavidcsqla_load_offchip_mem(qla_host_t *ha, uint64_t addr, uint32_t *data32,
1187284982Sdavidcs        uint32_t len32)
1188284982Sdavidcs{
1189284982Sdavidcs        q80_offchip_mem_val_t val;
1190284982Sdavidcs        int             ret = 0;
1191250661Sdavidcs
1192284982Sdavidcs        while (len32) {
1193284982Sdavidcs                if (len32 > 4) {
1194284982Sdavidcs                        val.data_lo = *data32++;
1195284982Sdavidcs                        val.data_hi = *data32++;
1196284982Sdavidcs                        val.data_ulo = *data32++;
1197284982Sdavidcs                        val.data_uhi = *data32++;
1198284982Sdavidcs                        len32 -= 4;
1199284982Sdavidcs                        if (ql_rdwr_offchip_mem(ha, addr, &val, 0))
1200284982Sdavidcs                                return -1;
1201284982Sdavidcs
1202284982Sdavidcs                        addr += (uint64_t)16;
1203284982Sdavidcs                } else {
1204284982Sdavidcs                        break;
1205284982Sdavidcs                }
1206284982Sdavidcs        }
1207284982Sdavidcs
1208284982Sdavidcs        bzero(&val, sizeof(q80_offchip_mem_val_t));
1209284982Sdavidcs
1210284982Sdavidcs        switch (len32) {
1211284982Sdavidcs        case 3:
1212284982Sdavidcs                val.data_lo = *data32++;
1213284982Sdavidcs                val.data_hi = *data32++;
1214284982Sdavidcs                val.data_ulo = *data32++;
1215284982Sdavidcs                 ret = ql_rdwr_offchip_mem(ha, addr, &val, 0);
1216284982Sdavidcs                break;
1217284982Sdavidcs
1218284982Sdavidcs        case 2:
1219284982Sdavidcs                val.data_lo = *data32++;
1220284982Sdavidcs                val.data_hi = *data32++;
1221284982Sdavidcs                 ret = ql_rdwr_offchip_mem(ha, addr, &val, 0);
1222284982Sdavidcs                break;
1223284982Sdavidcs
1224284982Sdavidcs        case 1:
1225284982Sdavidcs                val.data_lo = *data32++;
1226284982Sdavidcs                ret = ql_rdwr_offchip_mem(ha, addr, &val, 0);
1227284982Sdavidcs                break;
1228284982Sdavidcs
1229284982Sdavidcs        default:
1230284982Sdavidcs                break;
1231284982Sdavidcs
1232284982Sdavidcs        }
1233284982Sdavidcs        return ret;
1234284982Sdavidcs}
1235284982Sdavidcs
1236284982Sdavidcs
1237250661Sdavidcsstatic int
1238284982Sdavidcsqla_load_bootldr(qla_host_t *ha)
1239284982Sdavidcs{
1240284982Sdavidcs        uint64_t        addr;
1241284982Sdavidcs        uint32_t        *data32;
1242284982Sdavidcs        uint32_t        len32;
1243284982Sdavidcs        int             ret;
1244284982Sdavidcs
1245284982Sdavidcs        addr = (uint64_t)(READ_REG32(ha, Q8_BOOTLD_ADDR));
1246284982Sdavidcs        data32 = (uint32_t *)ql83xx_bootloader;
1247284982Sdavidcs        len32 = ql83xx_bootloader_len >> 2;
1248284982Sdavidcs
1249284982Sdavidcs        ret = qla_load_offchip_mem(ha, addr, data32, len32);
1250284982Sdavidcs
1251284982Sdavidcs        return (ret);
1252284982Sdavidcs}
1253284982Sdavidcs
1254284982Sdavidcsstatic int
1255284982Sdavidcsqla_load_fwimage(qla_host_t *ha)
1256284982Sdavidcs{
1257284982Sdavidcs        uint64_t        addr;
1258284982Sdavidcs        uint32_t        *data32;
1259284982Sdavidcs        uint32_t        len32;
1260284982Sdavidcs        int             ret;
1261284982Sdavidcs
1262284982Sdavidcs        addr = (uint64_t)(READ_REG32(ha, Q8_FW_IMAGE_ADDR));
1263284982Sdavidcs        data32 = (uint32_t *)ql83xx_firmware;
1264284982Sdavidcs        len32 = ql83xx_firmware_len >> 2;
1265284982Sdavidcs
1266284982Sdavidcs        ret = qla_load_offchip_mem(ha, addr, data32, len32);
1267284982Sdavidcs
1268284982Sdavidcs        return (ret);
1269284982Sdavidcs}
1270284982Sdavidcs#endif /* #ifndef QL_LDFLASH_FW */
1271284982Sdavidcs
1272284982Sdavidcsstatic int
1273250661Sdavidcsqla_ld_fw_init(qla_host_t *ha)
1274250661Sdavidcs{
1275250661Sdavidcs	uint8_t *buf;
1276250661Sdavidcs	uint32_t index = 0, end_idx;
1277250661Sdavidcs	q8_tmplt_hdr_t *hdr;
1278250661Sdavidcs
1279250661Sdavidcs	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1280250661Sdavidcs
1281250661Sdavidcs	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1282250661Sdavidcs
1283250661Sdavidcs	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1284250661Sdavidcs		(uint32_t)hdr->size)) {
1285250661Sdavidcs		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1286250661Sdavidcs			__func__);
1287250661Sdavidcs		return -1;
1288250661Sdavidcs	}
1289250661Sdavidcs
1290250661Sdavidcs
1291250661Sdavidcs	buf = ql83xx_resetseq + hdr->stop_seq_off;
1292250661Sdavidcs
1293250661Sdavidcs//	device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1294250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1295250661Sdavidcs		device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1296250661Sdavidcs		return -1;
1297250661Sdavidcs	}
1298250661Sdavidcs
1299250661Sdavidcs	index = end_idx;
1300250661Sdavidcs
1301250661Sdavidcs	buf = ql83xx_resetseq + hdr->init_seq_off;
1302250661Sdavidcs
1303250661Sdavidcs//	device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1304250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1305250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1306250661Sdavidcs		return -1;
1307250661Sdavidcs	}
1308250661Sdavidcs
1309284982Sdavidcs#ifdef QL_LDFLASH_FW
1310250661Sdavidcs	qla_load_fw_from_flash(ha);
1311250661Sdavidcs	WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
1312284982Sdavidcs#else
1313284982Sdavidcs        if (qla_load_bootldr(ha))
1314284982Sdavidcs                return -1;
1315250661Sdavidcs
1316284982Sdavidcs        if (qla_load_fwimage(ha))
1317284982Sdavidcs                return -1;
1318284982Sdavidcs
1319284982Sdavidcs        WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0x12345678);
1320284982Sdavidcs#endif /* #ifdef QL_LDFLASH_FW */
1321284982Sdavidcs
1322250661Sdavidcs	index = end_idx;
1323250661Sdavidcs	buf = ql83xx_resetseq + hdr->start_seq_off;
1324250661Sdavidcs
1325250661Sdavidcs//	device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1326250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1327250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1328250661Sdavidcs		return -1;
1329250661Sdavidcs	}
1330250661Sdavidcs
1331250661Sdavidcs	return 0;
1332250661Sdavidcs}
1333250661Sdavidcs
1334250661Sdavidcsint
1335250661Sdavidcsql_stop_sequence(qla_host_t *ha)
1336250661Sdavidcs{
1337250661Sdavidcs	uint8_t *buf;
1338250661Sdavidcs	uint32_t index = 0, end_idx;
1339250661Sdavidcs	q8_tmplt_hdr_t *hdr;
1340250661Sdavidcs
1341250661Sdavidcs	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1342250661Sdavidcs
1343250661Sdavidcs	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1344250661Sdavidcs
1345250661Sdavidcs	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1346250661Sdavidcs		(uint32_t)hdr->size)) {
1347250661Sdavidcs		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1348250661Sdavidcs		__func__);
1349250661Sdavidcs		return (-1);
1350250661Sdavidcs	}
1351250661Sdavidcs
1352250661Sdavidcs	buf = ql83xx_resetseq + hdr->stop_seq_off;
1353250661Sdavidcs
1354250661Sdavidcs	device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1355250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1356250661Sdavidcs		device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1357250661Sdavidcs		return (-1);
1358250661Sdavidcs	}
1359250661Sdavidcs
1360250661Sdavidcs	return end_idx;
1361250661Sdavidcs}
1362250661Sdavidcs
1363250661Sdavidcsint
1364250661Sdavidcsql_start_sequence(qla_host_t *ha, uint16_t index)
1365250661Sdavidcs{
1366250661Sdavidcs	uint8_t *buf;
1367250661Sdavidcs	uint32_t end_idx;
1368250661Sdavidcs	q8_tmplt_hdr_t *hdr;
1369250661Sdavidcs
1370250661Sdavidcs	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1371250661Sdavidcs
1372250661Sdavidcs	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1373250661Sdavidcs
1374250661Sdavidcs	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1375250661Sdavidcs		(uint32_t)hdr->size)) {
1376250661Sdavidcs		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1377250661Sdavidcs		__func__);
1378250661Sdavidcs		return (-1);
1379250661Sdavidcs	}
1380250661Sdavidcs
1381250661Sdavidcs	buf = ql83xx_resetseq + hdr->init_seq_off;
1382250661Sdavidcs
1383250661Sdavidcs	device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1384250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1385250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1386250661Sdavidcs		return (-1);
1387250661Sdavidcs	}
1388250661Sdavidcs
1389284982Sdavidcs#ifdef QL_LDFLASH_FW
1390250661Sdavidcs	qla_load_fw_from_flash(ha);
1391250661Sdavidcs	WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
1392284982Sdavidcs#else
1393284982Sdavidcs        if (qla_load_bootldr(ha))
1394284982Sdavidcs                return -1;
1395250661Sdavidcs
1396284982Sdavidcs        if (qla_load_fwimage(ha))
1397284982Sdavidcs                return -1;
1398284982Sdavidcs
1399284982Sdavidcs        WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0x12345678);
1400284982Sdavidcs#endif /* #ifdef QL_LDFLASH_FW */
1401284982Sdavidcs
1402284982Sdavidcs
1403250661Sdavidcs	index = end_idx;
1404250661Sdavidcs	buf = ql83xx_resetseq + hdr->start_seq_off;
1405250661Sdavidcs
1406250661Sdavidcs	device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1407250661Sdavidcs	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1408250661Sdavidcs		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1409250661Sdavidcs		return -1;
1410250661Sdavidcs	}
1411250661Sdavidcs
1412250661Sdavidcs	return (0);
1413250661Sdavidcs}
1414250661Sdavidcs
1415