1/*
2 * Copyright (c) 2011-2013 Qlogic Corporation
3 * All rights reserved.
4 *
5 *  Redistribution and use in source and binary forms, with or without
6 *  modification, are permitted provided that the following conditions
7 *  are met:
8 *
9 *  1. Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 *  2. Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 *
15 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 *  POSSIBILITY OF SUCH DAMAGE.
26 */
27/*
28 * File : qla_misc.c
29 * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD$");
34
35#include "qla_os.h"
36#include "qla_reg.h"
37#include "qla_hw.h"
38#include "qla_def.h"
39#include "qla_reg.h"
40#include "qla_inline.h"
41#include "qla_glbl.h"
42#include "qla_dbg.h"
43
44/*
45 * structure encapsulating the value to read/write to offchip memory
46 */
47typedef struct _offchip_mem_val {
48        uint32_t data_lo;
49        uint32_t data_hi;
50        uint32_t data_ulo;
51        uint32_t data_uhi;
52} offchip_mem_val_t;
53
54#define Q8_ADDR_UNDEFINED		0xFFFFFFFF
55
56/*
57 * The index to this table is Bits 20-27 of the indirect register address
58 */
59static uint32_t indirect_to_base_map[] =
60	{
61		Q8_ADDR_UNDEFINED,	/* 0x00 */
62		0x77300000,		/* 0x01 */
63		0x29500000,		/* 0x02 */
64		0x2A500000,		/* 0x03 */
65		Q8_ADDR_UNDEFINED,	/* 0x04 */
66		0x0D000000,		/* 0x05 */
67		0x1B100000,		/* 0x06 */
68		0x0E600000,		/* 0x07 */
69		0x0E000000,		/* 0x08 */
70		0x0E100000,		/* 0x09 */
71		0x0E200000,		/* 0x0A */
72		0x0E300000,		/* 0x0B */
73		0x42000000,		/* 0x0C */
74		0x41700000,		/* 0x0D */
75		0x42100000,		/* 0x0E */
76		0x34B00000,		/* 0x0F */
77		0x40500000,		/* 0x10 */
78		0x34000000,		/* 0x11 */
79		0x34100000,		/* 0x12 */
80		0x34200000,		/* 0x13 */
81		0x34300000,		/* 0x14 */
82		0x34500000,		/* 0x15 */
83		0x34400000,		/* 0x16 */
84		0x3C000000,		/* 0x17 */
85		0x3C100000,		/* 0x18 */
86		0x3C200000,		/* 0x19 */
87		0x3C300000,		/* 0x1A */
88		Q8_ADDR_UNDEFINED,	/* 0x1B */
89		0x3C400000,		/* 0x1C */
90		0x41000000,		/* 0x1D */
91		Q8_ADDR_UNDEFINED,	/* 0x1E */
92		0x0D100000,		/* 0x1F */
93		Q8_ADDR_UNDEFINED,	/* 0x20 */
94		0x77300000,		/* 0x21 */
95		0x41600000,		/* 0x22 */
96		Q8_ADDR_UNDEFINED,	/* 0x23 */
97		Q8_ADDR_UNDEFINED,	/* 0x24 */
98		Q8_ADDR_UNDEFINED,	/* 0x25 */
99		Q8_ADDR_UNDEFINED,	/* 0x26 */
100		Q8_ADDR_UNDEFINED,	/* 0x27 */
101		0x41700000,		/* 0x28 */
102		Q8_ADDR_UNDEFINED,	/* 0x29 */
103		0x08900000,		/* 0x2A */
104		0x70A00000,		/* 0x2B */
105		0x70B00000,		/* 0x2C */
106		0x70C00000,		/* 0x2D */
107		0x08D00000,		/* 0x2E */
108		0x08E00000,		/* 0x2F */
109		0x70F00000,		/* 0x30 */
110		0x40500000,		/* 0x31 */
111		0x42000000,		/* 0x32 */
112		0x42100000,		/* 0x33 */
113		Q8_ADDR_UNDEFINED,	/* 0x34 */
114		0x08800000,		/* 0x35 */
115		0x09100000,		/* 0x36 */
116		0x71200000,		/* 0x37 */
117		0x40600000,		/* 0x38 */
118		Q8_ADDR_UNDEFINED,	/* 0x39 */
119		0x71800000,		/* 0x3A */
120		0x19900000,		/* 0x3B */
121		0x1A900000,		/* 0x3C */
122		Q8_ADDR_UNDEFINED,	/* 0x3D */
123		0x34600000,		/* 0x3E */
124		Q8_ADDR_UNDEFINED,	/* 0x3F */
125	};
126
127/*
128 * Address Translation Table for CRB to offsets from PCI BAR0
129 */
130typedef struct _crb_to_pci {
131	uint32_t crb_addr;
132	uint32_t pci_addr;
133} crb_to_pci_t;
134
135static crb_to_pci_t crbinit_to_pciaddr[] = {
136	{(0x088 << 20), (0x035 << 20)},
137	{(0x089 << 20), (0x02A << 20)},
138	{(0x08D << 20), (0x02E << 20)},
139	{(0x08E << 20), (0x02F << 20)},
140	{(0x0C6 << 20), (0x023 << 20)},
141	{(0x0C7 << 20), (0x024 << 20)},
142	{(0x0C8 << 20), (0x025 << 20)},
143	{(0x0D0 << 20), (0x005 << 20)},
144	{(0x0D1 << 20), (0x01F << 20)},
145	{(0x0E0 << 20), (0x008 << 20)},
146	{(0x0E1 << 20), (0x009 << 20)},
147	{(0x0E2 << 20), (0x00A << 20)},
148	{(0x0E3 << 20), (0x00B << 20)},
149	{(0x0E6 << 20), (0x007 << 20)},
150	{(0x199 << 20), (0x03B << 20)},
151	{(0x1B1 << 20), (0x006 << 20)},
152	{(0x295 << 20), (0x002 << 20)},
153	{(0x29A << 20), (0x000 << 20)},
154	{(0x2A5 << 20), (0x003 << 20)},
155	{(0x340 << 20), (0x011 << 20)},
156	{(0x341 << 20), (0x012 << 20)},
157	{(0x342 << 20), (0x013 << 20)},
158	{(0x343 << 20), (0x014 << 20)},
159	{(0x344 << 20), (0x016 << 20)},
160	{(0x345 << 20), (0x015 << 20)},
161	{(0x3C0 << 20), (0x017 << 20)},
162	{(0x3C1 << 20), (0x018 << 20)},
163	{(0x3C2 << 20), (0x019 << 20)},
164	{(0x3C3 << 20), (0x01A << 20)},
165	{(0x3C4 << 20), (0x01C << 20)},
166	{(0x3C5 << 20), (0x01B << 20)},
167	{(0x405 << 20), (0x031 << 20)},
168	{(0x406 << 20), (0x038 << 20)},
169	{(0x410 << 20), (0x01D << 20)},
170	{(0x416 << 20), (0x022 << 20)},
171	{(0x417 << 20), (0x028 << 20)},
172	{(0x420 << 20), (0x032 << 20)},
173	{(0x421 << 20), (0x033 << 20)},
174	{(0x700 << 20), (0x00C << 20)},
175	{(0x701 << 20), (0x00D << 20)},
176	{(0x702 << 20), (0x00E << 20)},
177	{(0x703 << 20), (0x00F << 20)},
178	{(0x704 << 20), (0x010 << 20)},
179	{(0x70A << 20), (0x02B << 20)},
180	{(0x70B << 20), (0x02C << 20)},
181	{(0x70C << 20), (0x02D << 20)},
182	{(0x70F << 20), (0x030 << 20)},
183	{(0x718 << 20), (0x03A << 20)},
184	{(0x758 << 20), (0x026 << 20)},
185	{(0x759 << 20), (0x027 << 20)},
186	{(0x773 << 20), (0x001 << 20)}
187};
188
189#define Q8_INVALID_ADDRESS	(-1)
190#define Q8_ADDR_MASK		(0xFFF << 20)
191
192typedef struct _addr_val {
193	uint32_t addr;
194	uint32_t value;
195	uint32_t pci_addr;
196	uint32_t ind_addr;
197} addr_val_t;
198
199/*
200 * Name: qla_rdwr_indreg32
201 * Function: Read/Write an Indirect Register
202 */
203int
204qla_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd)
205{
206	uint32_t offset;
207	int count = 100;
208
209	offset = (addr & 0xFFF00000) >> 20;
210
211	if (offset > 0x3F) {
212		device_printf(ha->pci_dev, "%s: invalid addr 0x%08x\n",
213			__func__, addr);
214		return -1;
215	}
216
217	offset = indirect_to_base_map[offset];
218	if (offset == Q8_ADDR_UNDEFINED) {
219		device_printf(ha->pci_dev, "%s: undefined map 0x%08x\n",
220			__func__, addr);
221		return -1;
222	}
223
224	offset = offset | (addr & 0x000F0000);
225
226	if (qla_sem_lock(ha, Q8_SEM7_LOCK, 0, 0)) {
227		device_printf(ha->pci_dev, "%s: SEM7_LOCK failed\n", __func__);
228		return (-1);
229	}
230
231	WRITE_OFFSET32(ha, Q8_CRB_WINDOW_2M, offset);
232
233	while (offset != (READ_OFFSET32(ha, Q8_CRB_WINDOW_2M))) {
234		count--;
235		if (!count) {
236			qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
237			return -1;
238		}
239
240		qla_mdelay(__func__, 1);
241	}
242
243	if (rd) {
244		*val = READ_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000));
245	} else {
246		WRITE_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000), *val);
247	}
248
249	qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
250	return 0;
251}
252
253/*
254 * Name: qla_rdwr_offchip_mem
255 * Function: Read/Write OffChip Memory
256 */
257static int
258qla_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, offchip_mem_val_t *val,
259	uint32_t rd)
260{
261	uint32_t count = 100;
262	uint32_t data;
263
264	WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_LO, (uint32_t)addr);
265	WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_HI, (uint32_t)(addr >> 32));
266
267	if (!rd) {
268		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_LO, val->data_lo);
269		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_HI, val->data_hi);
270		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_ULO, val->data_ulo);
271		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_UHI, val->data_uhi);
272		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x07); /* Write */
273	} else {
274		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x03); /* Read */
275	}
276
277	while (count--) {
278		data = READ_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL);
279		if (!(data & BIT_3)) {
280			if (rd) {
281				val->data_lo = READ_OFFSET32(ha, \
282						Q8_MIU_TEST_AGT_RDDATA_LO);
283				val->data_hi = READ_OFFSET32(ha, \
284						Q8_MIU_TEST_AGT_RDDATA_HI);
285				val->data_ulo = READ_OFFSET32(ha, \
286						Q8_MIU_TEST_AGT_RDDATA_ULO);
287				val->data_uhi = READ_OFFSET32(ha, \
288						Q8_MIU_TEST_AGT_RDDATA_UHI);
289			}
290			return 0;
291		} else
292			qla_mdelay(__func__, 1);
293	}
294
295	device_printf(ha->pci_dev, "%s: failed[0x%08x]\n", __func__, data);
296	return (-1);
297}
298
299/*
300 * Name: qla_rd_flash32
301 * Function: Read Flash Memory
302 */
303int
304qla_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
305{
306	uint32_t val;
307	uint32_t count = 100;
308
309	if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
310		device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
311		return (-1);
312	}
313	WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
314
315	val = addr;
316	qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
317	val = 0;
318	qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
319	val = 3;
320	qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
321
322	QLA_USEC_DELAY(100);
323
324	val = ROM_OPCODE_FAST_RD;
325	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
326
327	while (!((val = READ_OFFSET32(ha, Q8_ROM_STATUS)) & BIT_1)) {
328		count--;
329		if (!count) {
330			qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
331			return -1;
332		}
333	}
334
335	val = 0;
336	qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
337	qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
338
339	QLA_USEC_DELAY(100);
340
341	qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, data, 1);
342
343	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
344	return 0;
345}
346
347static int
348qla_p3p_sem_lock2(qla_host_t *ha)
349{
350        if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
351                device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
352                return (-1);
353        }
354        WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
355        return (0);
356}
357
358/*
359 * Name: qla_int_to_pci_addr_map
360 * Function: Convert's Internal(CRB) Address to Indirect Address
361 */
362static uint32_t
363qla_int_to_pci_addr_map(qla_host_t *ha, uint32_t int_addr)
364{
365	uint32_t crb_to_pci_table_size, i;
366	uint32_t addr;
367
368	crb_to_pci_table_size = sizeof(crbinit_to_pciaddr)/sizeof(crb_to_pci_t);
369	addr = int_addr & Q8_ADDR_MASK;
370
371	for (i = 0; i < crb_to_pci_table_size; i++) {
372		if (crbinit_to_pciaddr[i].crb_addr == addr) {
373			addr = (int_addr & ~Q8_ADDR_MASK) |
374					crbinit_to_pciaddr[i].pci_addr;
375			return (addr);
376		}
377	}
378	return (Q8_INVALID_ADDRESS);
379}
380
381/*
382 * Name: qla_filter_pci_addr
383 * Function: Filter's out Indirect Addresses which are not writeable
384 */
385static uint32_t
386qla_filter_pci_addr(qla_host_t *ha, uint32_t addr)
387{
388	if ((addr == Q8_INVALID_ADDRESS) ||
389		(addr == 0x00112040) ||
390		(addr == 0x00112048) ||
391		((addr & 0xFFFF0FFF) == 0x001100C4) ||
392		((addr & 0xFFFF0FFF) == 0x001100C8) ||
393		((addr & 0x0FF00000) == 0x00200000) ||
394		(addr == 0x022021FC) ||
395		(addr == 0x0330001C) ||
396		(addr == 0x03300024) ||
397		(addr == 0x033000A8) ||
398		(addr == 0x033000C8) ||
399		(addr == 0x033000BC) ||
400		((addr & 0x0FF00000) == 0x03A00000) ||
401		(addr == 0x03B0001C))
402		return (Q8_INVALID_ADDRESS);
403	else
404		return (addr);
405}
406
407/*
408 * Name: qla_crb_init
409 * Function: CRB Initialization - first step in the initialization after reset
410 *	Essentially reads the address/value pairs from address = 0x00 and
411 *	writes the value into address in the addr/value pair.
412 */
413static int
414qla_crb_init(qla_host_t *ha)
415{
416	uint32_t val = 0, sig = 0;
417	uint32_t offset, count, i;
418	addr_val_t *addr_val_map, *avmap;
419
420	qla_rd_flash32(ha, 0, &sig);
421	QL_DPRINT2((ha->pci_dev, "%s: val[0] = 0x%08x\n", __func__, sig));
422
423	qla_rd_flash32(ha, 4, &val);
424	QL_DPRINT2((ha->pci_dev, "%s: val[4] = 0x%08x\n", __func__, val));
425
426	count = val >> 16;
427	offset = val & 0xFFFF;
428	offset = offset << 2;
429
430	QL_DPRINT2((ha->pci_dev, "%s: [sig,val]=[0x%08x, 0x%08x] %d pairs\n",
431		__func__, sig, val, count));
432
433	addr_val_map = avmap = malloc((sizeof(addr_val_t) * count),
434					M_QLA8XXXBUF, M_NOWAIT);
435
436	if (addr_val_map == NULL) {
437		device_printf(ha->pci_dev, "%s: malloc failed\n", __func__);
438		return (-1);
439	}
440	memset(avmap, 0, (sizeof(addr_val_t) * count));
441
442	count = count << 1;
443	for (i = 0; i < count; ) {
444		qla_rd_flash32(ha, (offset + (i * 4)), &avmap->value);
445		i++;
446		qla_rd_flash32(ha, (offset + (i * 4)), &avmap->addr);
447		i++;
448
449		avmap->pci_addr = qla_int_to_pci_addr_map(ha, avmap->addr);
450		avmap->ind_addr = qla_filter_pci_addr(ha, avmap->pci_addr);
451
452		QL_DPRINT2((ha->pci_dev,
453			"%s: [0x%02x][0x%08x:0x%08x:0x%08x] 0x%08x\n",
454			__func__, (i >> 1), avmap->addr, avmap->pci_addr,
455			avmap->ind_addr, avmap->value));
456
457		if (avmap->ind_addr != Q8_INVALID_ADDRESS) {
458			qla_rdwr_indreg32(ha, avmap->ind_addr, &avmap->value,0);
459			qla_mdelay(__func__, 1);
460		}
461		avmap++;
462	}
463
464	free (addr_val_map, M_QLA8XXXBUF);
465	return (0);
466}
467
468/*
469 * Name: qla_init_peg_regs
470 * Function: Protocol Engine Register Initialization
471 */
472static void
473qla_init_peg_regs(qla_host_t *ha)
474{
475	WRITE_OFFSET32(ha, Q8_PEG_D_RESET1, 0x001E);
476	WRITE_OFFSET32(ha, Q8_PEG_D_RESET2, 0x0008);
477	WRITE_OFFSET32(ha, Q8_PEG_I_RESET, 0x0008);
478	WRITE_OFFSET32(ha, Q8_PEG_0_CLR1, 0x0000);
479	WRITE_OFFSET32(ha, Q8_PEG_0_CLR2, 0x0000);
480	WRITE_OFFSET32(ha, Q8_PEG_1_CLR1, 0x0000);
481	WRITE_OFFSET32(ha, Q8_PEG_1_CLR2, 0x0000);
482	WRITE_OFFSET32(ha, Q8_PEG_2_CLR1, 0x0000);
483	WRITE_OFFSET32(ha, Q8_PEG_2_CLR2, 0x0000);
484	WRITE_OFFSET32(ha, Q8_PEG_3_CLR1, 0x0000);
485	WRITE_OFFSET32(ha, Q8_PEG_3_CLR2, 0x0000);
486	WRITE_OFFSET32(ha, Q8_PEG_4_CLR1, 0x0000);
487	WRITE_OFFSET32(ha, Q8_PEG_4_CLR2, 0x0000);
488}
489
490/*
491 * Name: qla_load_fw_from_flash
492 * Function: Reads the Bootloader from Flash and Loads into Offchip Memory
493 */
494static void
495qla_load_fw_from_flash(qla_host_t *ha)
496{
497	uint64_t mem_off	= 0x10000;
498	uint32_t flash_off	= 0x10000;
499	uint32_t count;
500	offchip_mem_val_t val;
501
502
503	/* only bootloader needs to be loaded into memory */
504	for (count = 0; count < 0x20000 ; ) {
505		qla_rd_flash32(ha, flash_off, &val.data_lo);
506		count = count + 4;
507		flash_off = flash_off + 4;
508
509		qla_rd_flash32(ha, flash_off, &val.data_hi);
510		count = count + 4;
511		flash_off = flash_off + 4;
512
513		qla_rd_flash32(ha, flash_off, &val.data_ulo);
514		count = count + 4;
515		flash_off = flash_off + 4;
516
517		qla_rd_flash32(ha, flash_off, &val.data_uhi);
518		count = count + 4;
519		flash_off = flash_off + 4;
520
521		qla_rdwr_offchip_mem(ha, mem_off, &val, 0);
522
523		mem_off = mem_off + 16;
524	}
525	return;
526}
527
528/*
529 * Name: qla_init_from_flash
530 * Function: Performs Initialization which consists of the following sequence
531 *	- reset
532 *	- CRB Init
533 *	- Peg Init
534 *	- Read the Bootloader from Flash and Load into Offchip Memory
535 *	- Kick start the bootloader which loads the rest of the firmware
536 *		and performs the remaining steps in the initialization process.
537 */
538static int
539qla_init_from_flash(qla_host_t *ha)
540{
541	uint32_t delay = 300;
542	uint32_t data;
543
544	qla_hw_reset(ha);
545	qla_mdelay(__func__, 100);
546
547	qla_crb_init(ha);
548	qla_mdelay(__func__, 10);
549
550	qla_init_peg_regs(ha);
551	qla_mdelay(__func__, 10);
552
553	qla_load_fw_from_flash(ha);
554
555	WRITE_OFFSET32(ha, Q8_CMDPEG_STATE, 0x00000000);
556	WRITE_OFFSET32(ha, Q8_PEG_0_RESET, 0x00001020);
557	WRITE_OFFSET32(ha, Q8_ASIC_RESET, 0x0080001E);
558	qla_mdelay(__func__, 100);
559
560	do {
561		data = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
562
563		QL_DPRINT2((ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
564				__func__, ha->pci_func, data));
565		if (data == CMDPEG_PHAN_INIT_COMPLETE) {
566			QL_DPRINT2((ha->pci_dev,
567				"%s: func[%d] init complete\n",
568				__func__, ha->pci_func));
569			return(0);
570		}
571		qla_mdelay(__func__, 100);
572	} while (delay--);
573
574	device_printf(ha->pci_dev,
575		"%s: func[%d] Q8_PEG_HALT_STATUS1[0x%08x] STATUS2[0x%08x]"
576		" HEARTBEAT[0x%08x] RCVPEG_STATE[0x%08x]"
577		" CMDPEG_STATE[0x%08x]\n",
578		__func__, ha->pci_func,
579		(READ_OFFSET32(ha, Q8_PEG_HALT_STATUS1)),
580		(READ_OFFSET32(ha, Q8_PEG_HALT_STATUS2)),
581		(READ_OFFSET32(ha, Q8_FIRMWARE_HEARTBEAT)),
582		(READ_OFFSET32(ha, Q8_RCVPEG_STATE)), data);
583
584	return (-1);
585}
586
587/*
588 * Name: qla_init_hw
589 * Function: Initializes P3+ hardware.
590 */
591int
592qla_init_hw(qla_host_t *ha)
593{
594        device_t dev;
595        int ret = 0;
596        uint32_t val, delay = 300;
597
598        dev = ha->pci_dev;
599
600        QL_DPRINT1((dev, "%s: enter\n", __func__));
601
602	qla_mdelay(__func__, 100);
603
604	if (ha->pci_func & 0x1) {
605        	while ((ha->pci_func & 0x1) && delay--) {
606			val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
607
608			if (val == CMDPEG_PHAN_INIT_COMPLETE) {
609				QL_DPRINT2((dev,
610					"%s: func = %d init complete\n",
611					__func__, ha->pci_func));
612				qla_mdelay(__func__, 100);
613				goto qla_init_exit;
614			}
615			qla_mdelay(__func__, 100);
616		}
617		return (-1);
618	}
619
620	val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
621
622	if (val != CMDPEG_PHAN_INIT_COMPLETE) {
623        	ret = qla_init_from_flash(ha);
624		qla_mdelay(__func__, 100);
625	} else {
626        	ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
627        	ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
628		ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
629
630		if (qla_rd_flash32(ha, 0x100004, &val) == 0) {
631
632			if (((val & 0xFF) != ha->fw_ver_major) ||
633				(((val >> 8) & 0xFF) != ha->fw_ver_minor) ||
634				(((val >> 16) & 0xFF) != ha->fw_ver_sub)) {
635
636        			ret = qla_init_from_flash(ha);
637				qla_mdelay(__func__, 100);
638			}
639		}
640	}
641
642qla_init_exit:
643        ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
644        ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
645        ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
646        ha->fw_ver_build = READ_OFFSET32(ha, Q8_FW_VER_BUILD);
647
648        return (ret);
649}
650
651static int
652qla_wait_for_flash_busy(qla_host_t *ha)
653{
654	uint32_t count = 100;
655	uint32_t val;
656
657	QLA_USEC_DELAY(100);
658
659	while (count--) {
660		val = READ_OFFSET32(ha, Q8_ROM_STATUS);
661
662		if (val & BIT_1)
663			return 0;
664		qla_mdelay(__func__, 1);
665	}
666	return -1;
667}
668
669static int
670qla_flash_write_enable(qla_host_t *ha)
671{
672	uint32_t val, rval;
673
674	val = 0;
675	qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
676
677	val = ROM_OPCODE_WR_ENABLE;
678	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
679
680	rval = qla_wait_for_flash_busy(ha);
681
682	if (rval)
683		device_printf(ha->pci_dev, "%s: failed \n", __func__);
684
685	return (rval);
686}
687
688static int
689qla_flash_unprotect(qla_host_t *ha)
690{
691	uint32_t val, rval;
692
693	if (qla_flash_write_enable(ha) != 0)
694		return(-1);
695
696	val = 0;
697	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
698
699	val = ROM_OPCODE_WR_STATUS_REG;
700	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
701
702	rval = qla_wait_for_flash_busy(ha);
703
704	if (rval) {
705		device_printf(ha->pci_dev, "%s: failed \n", __func__);
706		return rval;
707	}
708
709	if (qla_flash_write_enable(ha) != 0)
710		return(-1);
711
712	val = 0;
713	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
714
715	val = ROM_OPCODE_WR_STATUS_REG;
716	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
717
718	rval = qla_wait_for_flash_busy(ha);
719
720	if (rval)
721		device_printf(ha->pci_dev, "%s: failed \n", __func__);
722
723	return rval;
724}
725
726static int
727qla_flash_protect(qla_host_t *ha)
728{
729	uint32_t val, rval;
730
731	if (qla_flash_write_enable(ha) != 0)
732		return(-1);
733
734	val = 0x9C;
735	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
736
737	val = ROM_OPCODE_WR_STATUS_REG;
738	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
739
740	rval = qla_wait_for_flash_busy(ha);
741
742	if (rval)
743		device_printf(ha->pci_dev, "%s: failed \n", __func__);
744
745	return rval;
746}
747
748static uint32_t
749qla_flash_get_status(qla_host_t *ha)
750{
751	uint32_t count = 1000;
752	uint32_t val, rval;
753
754	while (count--) {
755		val = 0;
756		qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
757
758		val = ROM_OPCODE_RD_STATUS_REG;
759		qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
760
761		rval = qla_wait_for_flash_busy(ha);
762
763		if (rval == 0) {
764			qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
765
766			if ((val & BIT_0) == 0)
767				return (val);
768		}
769		qla_mdelay(__func__, 1);
770	}
771	return -1;
772}
773
774static int
775qla_wait_for_flash_unprotect(qla_host_t *ha)
776{
777	uint32_t delay = 1000;
778
779	while (delay--) {
780
781		if (qla_flash_get_status(ha) == 0)
782			return 0;
783
784		qla_mdelay(__func__, 1);
785	}
786
787	return -1;
788}
789
790static int
791qla_wait_for_flash_protect(qla_host_t *ha)
792{
793	uint32_t delay = 1000;
794
795	while (delay--) {
796
797		if (qla_flash_get_status(ha) == 0x9C)
798			return 0;
799
800		qla_mdelay(__func__, 1);
801	}
802
803	return -1;
804}
805
806static int
807qla_erase_flash_sector(qla_host_t *ha, uint32_t start)
808{
809	uint32_t val;
810	int rval;
811
812	if (qla_flash_write_enable(ha) != 0)
813		return(-1);
814
815        val = start;
816        qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
817
818        val = 3;
819        qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
820
821        val = ROM_OPCODE_SECTOR_ERASE;
822        qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
823
824	rval = qla_wait_for_flash_busy(ha);
825
826	if (rval)
827		device_printf(ha->pci_dev, "%s: failed \n", __func__);
828	return rval;
829}
830
831#define Q8_FLASH_SECTOR_SIZE 0x10000
832int
833qla_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size)
834{
835	int rval = 0;
836	uint32_t start;
837
838	if (off & (Q8_FLASH_SECTOR_SIZE -1))
839		return -1;
840
841	if ((rval = qla_p3p_sem_lock2(ha)))
842		goto qla_erase_flash_exit;
843
844	if ((rval = qla_flash_unprotect(ha)))
845		goto qla_erase_flash_unlock_exit;
846
847	if ((rval = qla_wait_for_flash_unprotect(ha)))
848		goto qla_erase_flash_unlock_exit;
849
850	for (start = off; start < (off + size); start = start + 0x10000) {
851		if (qla_erase_flash_sector(ha, start)) {
852			rval = -1;
853			break;
854		}
855	}
856
857	rval = qla_flash_protect(ha);
858
859qla_erase_flash_unlock_exit:
860	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
861
862qla_erase_flash_exit:
863	return (rval);
864}
865
866static int
867qla_flash_write32(qla_host_t *ha, uint32_t off, uint32_t data)
868{
869	uint32_t val;
870	int rval = 0;
871
872        val = data;
873        qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
874
875        val = off;
876        qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
877
878        val = 3;
879        qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
880
881        val = ROM_OPCODE_PROG_PAGE;
882        qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
883
884	rval = qla_wait_for_flash_busy(ha);
885
886	if (rval)
887		device_printf(ha->pci_dev, "%s: failed \n", __func__);
888
889	return rval;
890}
891
892static int
893qla_flash_wait_for_write_complete(qla_host_t *ha)
894{
895	uint32_t val, count = 1000;
896	int rval = 0;
897
898	while (count--) {
899
900		val = 0;
901		qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
902
903		val = ROM_OPCODE_RD_STATUS_REG;
904		qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
905
906
907		rval = qla_wait_for_flash_busy(ha);
908
909		if (rval == 0) {
910			qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
911
912			if ((val & BIT_0) == 0)
913				return (0);
914		}
915		qla_mdelay(__func__, 1);
916	}
917	return -1;
918}
919
920static int
921qla_flash_write(qla_host_t *ha, uint32_t off, uint32_t data)
922{
923	if (qla_flash_write_enable(ha) != 0)
924		return(-1);
925
926	if (qla_flash_write32(ha, off, data) != 0)
927		return -1;
928
929	if (qla_flash_wait_for_write_complete(ha))
930		return -1;
931
932	return 0;
933}
934
935
936static int
937qla_flash_write_pattern(qla_host_t *ha, uint32_t off, uint32_t size,
938	uint32_t pattern)
939{
940	int rval = 0;
941	uint32_t start;
942
943
944	if ((rval = qla_p3p_sem_lock2(ha)))
945		goto qla_wr_pattern_exit;
946
947	if ((rval = qla_flash_unprotect(ha)))
948		goto qla_wr_pattern_unlock_exit;
949
950	if ((rval = qla_wait_for_flash_unprotect(ha)))
951		goto qla_wr_pattern_unlock_exit;
952
953	for (start = off; start < (off + size); start = start + 4) {
954		if (qla_flash_write(ha, start, pattern)) {
955			rval = -1;
956			break;
957		}
958	}
959
960	rval = qla_flash_protect(ha);
961
962	if (rval == 0)
963		rval = qla_wait_for_flash_protect(ha);
964
965qla_wr_pattern_unlock_exit:
966	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
967
968qla_wr_pattern_exit:
969	return (rval);
970}
971
972static int
973qla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size,
974	void *data)
975{
976	int rval = 0;
977	uint32_t start;
978	uint32_t *data32 = data;
979
980
981	if ((rval = qla_p3p_sem_lock2(ha)))
982		goto qla_wr_pattern_exit;
983
984	if ((rval = qla_flash_unprotect(ha)))
985		goto qla_wr_pattern_unlock_exit;
986
987	if ((rval = qla_wait_for_flash_unprotect(ha)))
988		goto qla_wr_pattern_unlock_exit;
989
990	for (start = off; start < (off + size); start = start + 4) {
991
992		if (*data32 != 0xFFFFFFFF) {
993			if (qla_flash_write(ha, start, *data32)) {
994				rval = -1;
995				break;
996			}
997		}
998		data32++;
999	}
1000
1001	rval = qla_flash_protect(ha);
1002
1003	if (rval == 0)
1004		rval = qla_wait_for_flash_protect(ha);
1005
1006qla_wr_pattern_unlock_exit:
1007	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
1008
1009qla_wr_pattern_exit:
1010	return (rval);
1011}
1012
1013int
1014qla_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf,
1015	uint32_t pattern)
1016{
1017	int rval = 0;
1018	void *data;
1019
1020
1021	if (size == 0)
1022		return 0;
1023
1024	size = size << 2;
1025
1026	if (buf == NULL) {
1027		rval = qla_flash_write_pattern(ha, off, size, pattern);
1028		return (rval);
1029	}
1030
1031	if ((data = malloc(size, M_QLA8XXXBUF, M_NOWAIT)) == NULL) {
1032		device_printf(ha->pci_dev, "%s: malloc failed \n", __func__);
1033		rval = -1;
1034		goto qla_wr_flash_buffer_exit;
1035	}
1036
1037	if ((rval = copyin(buf, data, size))) {
1038		device_printf(ha->pci_dev, "%s copyin failed\n", __func__);
1039		goto qla_wr_flash_buffer_free_exit;
1040	}
1041
1042	rval = qla_flash_write_data(ha, off, size, data);
1043
1044qla_wr_flash_buffer_free_exit:
1045	free(data, M_QLA8XXXBUF);
1046
1047qla_wr_flash_buffer_exit:
1048	return (rval);
1049}
1050
1051