xref: /onnv-gate/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_nx.c (revision 12279:f13874aa8143)
111924SDaniel.Beauregard@Sun.COM /*
211924SDaniel.Beauregard@Sun.COM  * CDDL HEADER START
311924SDaniel.Beauregard@Sun.COM  *
411924SDaniel.Beauregard@Sun.COM  * The contents of this file are subject to the terms of the
511924SDaniel.Beauregard@Sun.COM  * Common Development and Distribution License (the "License").
611924SDaniel.Beauregard@Sun.COM  * You may not use this file except in compliance with the License.
711924SDaniel.Beauregard@Sun.COM  *
811924SDaniel.Beauregard@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911924SDaniel.Beauregard@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1011924SDaniel.Beauregard@Sun.COM  * See the License for the specific language governing permissions
1111924SDaniel.Beauregard@Sun.COM  * and limitations under the License.
1211924SDaniel.Beauregard@Sun.COM  *
1311924SDaniel.Beauregard@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1411924SDaniel.Beauregard@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511924SDaniel.Beauregard@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1611924SDaniel.Beauregard@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1711924SDaniel.Beauregard@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1811924SDaniel.Beauregard@Sun.COM  *
1911924SDaniel.Beauregard@Sun.COM  * CDDL HEADER END
2011924SDaniel.Beauregard@Sun.COM  */
2111924SDaniel.Beauregard@Sun.COM 
2211924SDaniel.Beauregard@Sun.COM /*
2311924SDaniel.Beauregard@Sun.COM  * Copyright 2010 QLogic Corporation.  All rights reserved.
2411924SDaniel.Beauregard@Sun.COM  * Use is subject to license terms.
2511924SDaniel.Beauregard@Sun.COM  */
2611924SDaniel.Beauregard@Sun.COM 
2711924SDaniel.Beauregard@Sun.COM #pragma ident	"Copyright 2010 QLogic Corporation; ql_nx.c"
2811924SDaniel.Beauregard@Sun.COM 
2911924SDaniel.Beauregard@Sun.COM /*
3011924SDaniel.Beauregard@Sun.COM  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
3111924SDaniel.Beauregard@Sun.COM  *
3211924SDaniel.Beauregard@Sun.COM  * ***********************************************************************
3311924SDaniel.Beauregard@Sun.COM  * *									**
3411924SDaniel.Beauregard@Sun.COM  * *				NOTICE					**
3511924SDaniel.Beauregard@Sun.COM  * *		COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION		**
3611924SDaniel.Beauregard@Sun.COM  * *			ALL RIGHTS RESERVED				**
3711924SDaniel.Beauregard@Sun.COM  * *									**
3811924SDaniel.Beauregard@Sun.COM  * ***********************************************************************
3911924SDaniel.Beauregard@Sun.COM  *
4011924SDaniel.Beauregard@Sun.COM  */
4111924SDaniel.Beauregard@Sun.COM 
4211924SDaniel.Beauregard@Sun.COM #include <ql_apps.h>
4311924SDaniel.Beauregard@Sun.COM #include <ql_api.h>
4411924SDaniel.Beauregard@Sun.COM #include <ql_debug.h>
4511924SDaniel.Beauregard@Sun.COM #include <ql_mbx.h>
4611924SDaniel.Beauregard@Sun.COM #include <ql_nx.h>
4711924SDaniel.Beauregard@Sun.COM 
4811924SDaniel.Beauregard@Sun.COM /*
4911924SDaniel.Beauregard@Sun.COM  *  Local Function Prototypes.
5011924SDaniel.Beauregard@Sun.COM  */
5111924SDaniel.Beauregard@Sun.COM static void *ql_8021_pci_base_offsetfset(ql_adapter_state_t *, uint64_t);
5211924SDaniel.Beauregard@Sun.COM static void ql_crb_addr_transform_setup(ql_adapter_state_t *);
5311924SDaniel.Beauregard@Sun.COM static void ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t *, uint64_t *);
5411924SDaniel.Beauregard@Sun.COM static void ql_8021_wr_32(ql_adapter_state_t *, uint64_t, uint32_t);
5511924SDaniel.Beauregard@Sun.COM static void ql_8021_rd_32(ql_adapter_state_t *, uint64_t, uint32_t *);
5611924SDaniel.Beauregard@Sun.COM static int ql_8021_crb_win_lock(ql_adapter_state_t *);
5711924SDaniel.Beauregard@Sun.COM static void ql_8021_crb_win_unlock(ql_adapter_state_t *);
5811924SDaniel.Beauregard@Sun.COM static int ql_8021_pci_get_crb_addr_2M(ql_adapter_state_t *, uint64_t *);
5911924SDaniel.Beauregard@Sun.COM static uint32_t ql_8021_pci_mem_bound_check(ql_adapter_state_t *, uint64_t,
6011924SDaniel.Beauregard@Sun.COM     uint32_t);
6111924SDaniel.Beauregard@Sun.COM static uint64_t ql_8021_pci_set_window(ql_adapter_state_t *, uint64_t);
6211924SDaniel.Beauregard@Sun.COM static int ql_8021_pci_is_same_window(ql_adapter_state_t *, uint64_t);
6311924SDaniel.Beauregard@Sun.COM static int ql_8021_pci_mem_read_direct(ql_adapter_state_t *, uint64_t, void *,
6411924SDaniel.Beauregard@Sun.COM     uint32_t);
6511924SDaniel.Beauregard@Sun.COM static int ql_8021_pci_mem_write_direct(ql_adapter_state_t *, uint64_t, void *,
6611924SDaniel.Beauregard@Sun.COM     uint32_t);
6711924SDaniel.Beauregard@Sun.COM static int ql_8021_pci_mem_read_2M(ql_adapter_state_t *, uint64_t, void *,
6811924SDaniel.Beauregard@Sun.COM     uint32_t);
6911924SDaniel.Beauregard@Sun.COM static int ql_8021_pci_mem_write_2M(ql_adapter_state_t *, uint64_t, void *,
7011924SDaniel.Beauregard@Sun.COM     uint32_t);
7111924SDaniel.Beauregard@Sun.COM static uint32_t ql_8021_decode_crb_addr(ql_adapter_state_t *, uint32_t);
7211924SDaniel.Beauregard@Sun.COM static int ql_8021_rom_lock(ql_adapter_state_t *);
7311924SDaniel.Beauregard@Sun.COM static void ql_8021_rom_unlock(ql_adapter_state_t *);
7411924SDaniel.Beauregard@Sun.COM static int ql_8021_wait_rom_done(ql_adapter_state_t *);
7511924SDaniel.Beauregard@Sun.COM static int ql_8021_wait_flash_done(ql_adapter_state_t *);
7611924SDaniel.Beauregard@Sun.COM static int ql_8021_do_rom_fast_read(ql_adapter_state_t *, uint32_t, uint32_t *);
7711924SDaniel.Beauregard@Sun.COM static int ql_8021_rom_fast_read(ql_adapter_state_t *, uint32_t, uint32_t *);
7811924SDaniel.Beauregard@Sun.COM static int ql_8021_do_rom_write(ql_adapter_state_t *, uint32_t, uint32_t);
7911924SDaniel.Beauregard@Sun.COM static int ql_8021_do_rom_erase(ql_adapter_state_t *, uint32_t);
8011924SDaniel.Beauregard@Sun.COM static int ql_8021_phantom_init(ql_adapter_state_t *);
8111924SDaniel.Beauregard@Sun.COM static int ql_8021_pinit_from_rom(ql_adapter_state_t *);
8211924SDaniel.Beauregard@Sun.COM static int ql_8021_load_from_flash(ql_adapter_state_t *);
8311924SDaniel.Beauregard@Sun.COM static int ql_8021_load_firmware(ql_adapter_state_t *);
8411924SDaniel.Beauregard@Sun.COM static int ql_8021_reset_hw(ql_adapter_state_t *, int);
8511924SDaniel.Beauregard@Sun.COM static int ql_8021_init_p3p(ql_adapter_state_t *);
8611924SDaniel.Beauregard@Sun.COM static int ql_8021_hw_lock(ql_adapter_state_t *, uint32_t);
8711924SDaniel.Beauregard@Sun.COM static void ql_8021_hw_unlock(ql_adapter_state_t *);
8811924SDaniel.Beauregard@Sun.COM static void ql_8021_need_reset_handler(ql_adapter_state_t *);
8911924SDaniel.Beauregard@Sun.COM 
9011924SDaniel.Beauregard@Sun.COM /*
9111924SDaniel.Beauregard@Sun.COM  * Local Data.
9211924SDaniel.Beauregard@Sun.COM  */
9311924SDaniel.Beauregard@Sun.COM static uint32_t	crb_addr_xform[MAX_CRB_XFORM];
9411924SDaniel.Beauregard@Sun.COM static int	crb_table_initialized = 0;
9511924SDaniel.Beauregard@Sun.COM static int	pci_set_window_warning_count = 0;
9611924SDaniel.Beauregard@Sun.COM 
9711924SDaniel.Beauregard@Sun.COM static struct legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
9811924SDaniel.Beauregard@Sun.COM 
9911924SDaniel.Beauregard@Sun.COM static crb_128M_2M_block_map_t crb_128M_2M_map[64] = {
10011924SDaniel.Beauregard@Sun.COM 	{{{0, 0,	 0,	 0}}},			/* 0: PCI */
10111924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0100000, 0x0102000, 0x120000},		/* 1: PCIE */
10211924SDaniel.Beauregard@Sun.COM 	    {1, 0x0110000, 0x0120000, 0x130000},
10311924SDaniel.Beauregard@Sun.COM 	    {1, 0x0120000, 0x0122000, 0x124000},
10411924SDaniel.Beauregard@Sun.COM 	    {1, 0x0130000, 0x0132000, 0x126000},
10511924SDaniel.Beauregard@Sun.COM 	    {1, 0x0140000, 0x0142000, 0x128000},
10611924SDaniel.Beauregard@Sun.COM 	    {1, 0x0150000, 0x0152000, 0x12a000},
10711924SDaniel.Beauregard@Sun.COM 	    {1, 0x0160000, 0x0170000, 0x110000},
10811924SDaniel.Beauregard@Sun.COM 	    {1, 0x0170000, 0x0172000, 0x12e000},
10911924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
11011924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
11111924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
11211924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
11311924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
11411924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
11511924SDaniel.Beauregard@Sun.COM 	    {1, 0x01e0000, 0x01e0800, 0x122000},
11611924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000}}},
11711924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0200000, 0x0210000, 0x180000}}},	/* 2: MN */
11811924SDaniel.Beauregard@Sun.COM 	{{{0, 0,	 0,	 0}}},			/* 3: */
11911924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0400000, 0x0401000, 0x169000}}},	/* 4: P2NR1 */
12011924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0500000, 0x0510000, 0x140000}}},	/* 5: SRE   */
12111924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0600000, 0x0610000, 0x1c0000}}},	/* 6: NIU   */
12211924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0700000, 0x0704000, 0x1b8000}}},	/* 7: QM    */
12311924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0800000, 0x0802000, 0x170000},  	/* 8: SQM0  */
12411924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
12511924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
12611924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
12711924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
12811924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
12911924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
13011924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
13111924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
13211924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
13311924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
13411924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
13511924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
13611924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
13711924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
13811924SDaniel.Beauregard@Sun.COM 	    {1, 0x08f0000, 0x08f2000, 0x172000}}},
13911924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0900000, 0x0902000, 0x174000},		/* 9: SQM1 */
14011924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
14111924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
14211924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
14311924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
14411924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
14511924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
14611924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
14711924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
14811924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
14911924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
15011924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
15111924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
15211924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
15311924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
15411924SDaniel.Beauregard@Sun.COM 	    {1, 0x09f0000, 0x09f2000, 0x176000}}},
15511924SDaniel.Beauregard@Sun.COM 	{{{0, 0x0a00000, 0x0a02000, 0x178000},		/* 10: SQM2 */
15611924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
15711924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
15811924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
15911924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
16011924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
16111924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
16211924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
16311924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
16411924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
16511924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
16611924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
16711924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
16811924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
16911924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
17011924SDaniel.Beauregard@Sun.COM 	    {1, 0x0af0000, 0x0af2000, 0x17a000}}},
17111924SDaniel.Beauregard@Sun.COM 	{{{0, 0x0b00000, 0x0b02000, 0x17c000},		/* 11: SQM3 */
17211924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
17311924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
17411924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
17511924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
17611924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
17711924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
17811924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
17911924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
18011924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
18111924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
18211924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
18311924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
18411924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
18511924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
18611924SDaniel.Beauregard@Sun.COM 	    {1, 0x0bf0000, 0x0bf2000, 0x17e000}}},
18711924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0c00000, 0x0c04000, 0x1d4000}}},	/* 12: I2Q */
18811924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0d00000, 0x0d04000, 0x1a4000}}},	/* 13: TMR */
18911924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0e00000, 0x0e04000, 0x1a0000}}},	/* 14: ROMUSB */
19011924SDaniel.Beauregard@Sun.COM 	{{{1, 0x0f00000, 0x0f01000, 0x164000}}},	/* 15: PEG4 */
19111924SDaniel.Beauregard@Sun.COM 	{{{0, 0x1000000, 0x1004000, 0x1a8000}}},	/* 16: XDMA */
19211924SDaniel.Beauregard@Sun.COM 	{{{1, 0x1100000, 0x1101000, 0x160000}}},	/* 17: PEG0 */
19311924SDaniel.Beauregard@Sun.COM 	{{{1, 0x1200000, 0x1201000, 0x161000}}},	/* 18: PEG1 */
19411924SDaniel.Beauregard@Sun.COM 	{{{1, 0x1300000, 0x1301000, 0x162000}}},	/* 19: PEG2 */
19511924SDaniel.Beauregard@Sun.COM 	{{{1, 0x1400000, 0x1401000, 0x163000}}},	/* 20: PEG3 */
19611924SDaniel.Beauregard@Sun.COM 	{{{1, 0x1500000, 0x1501000, 0x165000}}},	/* 21: P2ND */
19711924SDaniel.Beauregard@Sun.COM 	{{{1, 0x1600000, 0x1601000, 0x166000}}},	/* 22: P2NI */
19811924SDaniel.Beauregard@Sun.COM 	{{{0, 0,	 0,	 0}}},			/* 23: */
19911924SDaniel.Beauregard@Sun.COM 	{{{0, 0,	 0,	 0}}},			/* 24: */
20011924SDaniel.Beauregard@Sun.COM 	{{{0, 0,	 0,	 0}}},			/* 25: */
20111924SDaniel.Beauregard@Sun.COM 	{{{0, 0,	 0,	 0}}},			/* 26: */
20211924SDaniel.Beauregard@Sun.COM 	{{{0, 0,	 0,	 0}}},			/* 27: */
20311924SDaniel.Beauregard@Sun.COM 	{{{0, 0,	 0,	 0}}},			/* 28: */
20411924SDaniel.Beauregard@Sun.COM 	{{{1, 0x1d00000, 0x1d10000, 0x190000}}},	/* 29: MS */
20511924SDaniel.Beauregard@Sun.COM 	{{{1, 0x1e00000, 0x1e01000, 0x16a000}}},	/* 30: P2NR2 */
20611924SDaniel.Beauregard@Sun.COM 	{{{1, 0x1f00000, 0x1f10000, 0x150000}}},	/* 31: EPG */
20711924SDaniel.Beauregard@Sun.COM 	{{{0}}},					/* 32: PCI */
20811924SDaniel.Beauregard@Sun.COM 	{{{1, 0x2100000, 0x2102000, 0x120000},		/* 33: PCIE */
20911924SDaniel.Beauregard@Sun.COM 	    {1, 0x2110000, 0x2120000, 0x130000},
21011924SDaniel.Beauregard@Sun.COM 	    {1, 0x2120000, 0x2122000, 0x124000},
21111924SDaniel.Beauregard@Sun.COM 	    {1, 0x2130000, 0x2132000, 0x126000},
21211924SDaniel.Beauregard@Sun.COM 	    {1, 0x2140000, 0x2142000, 0x128000},
21311924SDaniel.Beauregard@Sun.COM 	    {1, 0x2150000, 0x2152000, 0x12a000},
21411924SDaniel.Beauregard@Sun.COM 	    {1, 0x2160000, 0x2170000, 0x110000},
21511924SDaniel.Beauregard@Sun.COM 	    {1, 0x2170000, 0x2172000, 0x12e000},
21611924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
21711924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
21811924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
21911924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
22011924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
22111924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
22211924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000},
22311924SDaniel.Beauregard@Sun.COM 	    {0, 0x0000000, 0x0000000, 0x000000}}},
22411924SDaniel.Beauregard@Sun.COM 	{{{1, 0x2200000, 0x2204000, 0x1b0000}}},	/* 34: CAM */
22511924SDaniel.Beauregard@Sun.COM 	{{{0}}},					/* 35: */
22611924SDaniel.Beauregard@Sun.COM 	{{{0}}},					/* 36: */
22711924SDaniel.Beauregard@Sun.COM 	{{{0}}},					/* 37: */
22811924SDaniel.Beauregard@Sun.COM 	{{{0}}},					/* 38: */
22911924SDaniel.Beauregard@Sun.COM 	{{{0}}},					/* 39: */
23011924SDaniel.Beauregard@Sun.COM 	{{{1, 0x2800000, 0x2804000, 0x1a4000}}},	/* 40: TMR */
23111924SDaniel.Beauregard@Sun.COM 	{{{1, 0x2900000, 0x2901000, 0x16b000}}},	/* 41: P2NR3 */
23211924SDaniel.Beauregard@Sun.COM 	{{{1, 0x2a00000, 0x2a00400, 0x1ac400}}},	/* 42: RPMX1 */
23311924SDaniel.Beauregard@Sun.COM 	{{{1, 0x2b00000, 0x2b00400, 0x1ac800}}},	/* 43: RPMX2 */
23411924SDaniel.Beauregard@Sun.COM 	{{{1, 0x2c00000, 0x2c00400, 0x1acc00}}},	/* 44: RPMX3 */
23511924SDaniel.Beauregard@Sun.COM 	{{{1, 0x2d00000, 0x2d00400, 0x1ad000}}},	/* 45: RPMX4 */
23611924SDaniel.Beauregard@Sun.COM 	{{{1, 0x2e00000, 0x2e00400, 0x1ad400}}},	/* 46: RPMX5 */
23711924SDaniel.Beauregard@Sun.COM 	{{{1, 0x2f00000, 0x2f00400, 0x1ad800}}},	/* 47: RPMX6 */
23811924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3000000, 0x3000400, 0x1adc00}}},	/* 48: RPMX7 */
23911924SDaniel.Beauregard@Sun.COM 	{{{0, 0x3100000, 0x3104000, 0x1a8000}}},	/* 49: XDMA */
24011924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3200000, 0x3204000, 0x1d4000}}},	/* 50: I2Q */
24111924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3300000, 0x3304000, 0x1a0000}}},	/* 51: ROMUSB */
24211924SDaniel.Beauregard@Sun.COM 	{{{0}}},					/* 52: */
24311924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3500000, 0x3500400, 0x1ac000}}},	/* 53: RPMX0 */
24411924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3600000, 0x3600400, 0x1ae000}}},	/* 54: RPMX8 */
24511924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3700000, 0x3700400, 0x1ae400}}},	/* 55: RPMX9 */
24611924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3800000, 0x3804000, 0x1d0000}}},	/* 56: OCM0 */
24711924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3900000, 0x3904000, 0x1b4000}}},	/* 57: CRYPTO */
24811924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3a00000, 0x3a04000, 0x1d8000}}},	/* 58: SMB */
24911924SDaniel.Beauregard@Sun.COM 	{{{0}}},					/* 59: I2C0 */
25011924SDaniel.Beauregard@Sun.COM 	{{{0}}},					/* 60: I2C1 */
25111924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3d00000, 0x3d04000, 0x1dc000}}},	/* 61: LPC */
25211924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3e00000, 0x3e01000, 0x167000}}},	/* 62: P2NC */
25311924SDaniel.Beauregard@Sun.COM 	{{{1, 0x3f00000, 0x3f01000, 0x168000}}}		/* 63: P2NR0 */
25411924SDaniel.Beauregard@Sun.COM };
25511924SDaniel.Beauregard@Sun.COM 
25611924SDaniel.Beauregard@Sun.COM /*
25711924SDaniel.Beauregard@Sun.COM  * top 12 bits of crb internal address (hub, agent)
25811924SDaniel.Beauregard@Sun.COM  */
25911924SDaniel.Beauregard@Sun.COM static uint32_t crb_hub_agt[64] = {
26011924SDaniel.Beauregard@Sun.COM 	0,
26111924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PS,
26211924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_MN,
26311924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_MS,
26411924SDaniel.Beauregard@Sun.COM 	0,
26511924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_SRE,
26611924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_NIU,
26711924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_QMN,
26811924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_SQN0,
26911924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_SQN1,
27011924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_SQN2,
27111924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_SQN3,
27211924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_I2Q,
27311924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_TIMR,
27411924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_ROMUSB,
27511924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGN4,
27611924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_XDMA,
27711924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGN0,
27811924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGN1,
27911924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGN2,
28011924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGN3,
28111924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGND,
28211924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGNI,
28311924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGS0,
28411924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGS1,
28511924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGS2,
28611924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGS3,
28711924SDaniel.Beauregard@Sun.COM 	0,
28811924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGSI,
28911924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_SN,
29011924SDaniel.Beauregard@Sun.COM 	0,
29111924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_EG,
29211924SDaniel.Beauregard@Sun.COM 	0,
29311924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PS,
29411924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_CAM,
29511924SDaniel.Beauregard@Sun.COM 	0,
29611924SDaniel.Beauregard@Sun.COM 	0,
29711924SDaniel.Beauregard@Sun.COM 	0,
29811924SDaniel.Beauregard@Sun.COM 	0,
29911924SDaniel.Beauregard@Sun.COM 	0,
30011924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_TIMR,
30111924SDaniel.Beauregard@Sun.COM 	0,
30211924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_RPMX1,
30311924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_RPMX2,
30411924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_RPMX3,
30511924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_RPMX4,
30611924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_RPMX5,
30711924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_RPMX6,
30811924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_RPMX7,
30911924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_XDMA,
31011924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_I2Q,
31111924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_ROMUSB,
31211924SDaniel.Beauregard@Sun.COM 	0,
31311924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_RPMX0,
31411924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_RPMX8,
31511924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_RPMX9,
31611924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_OCM0,
31711924SDaniel.Beauregard@Sun.COM 	0,
31811924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_SMB,
31911924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_I2C0,
32011924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_I2C1,
32111924SDaniel.Beauregard@Sun.COM 	0,
32211924SDaniel.Beauregard@Sun.COM 	UNM_HW_CRB_HUB_AGT_ADR_PGNC,
32311924SDaniel.Beauregard@Sun.COM 	0,
32411924SDaniel.Beauregard@Sun.COM };
32511924SDaniel.Beauregard@Sun.COM 
32611924SDaniel.Beauregard@Sun.COM static void *
ql_8021_pci_base_offsetfset(ql_adapter_state_t * ha,uint64_t off)32711924SDaniel.Beauregard@Sun.COM ql_8021_pci_base_offsetfset(ql_adapter_state_t *ha, uint64_t off)
32811924SDaniel.Beauregard@Sun.COM {
32911924SDaniel.Beauregard@Sun.COM 	if ((off < ha->first_page_group_end) &&
33011924SDaniel.Beauregard@Sun.COM 	    (off >= ha->first_page_group_start)) {
33111924SDaniel.Beauregard@Sun.COM 		return ((void *)(ha->nx_pcibase + off));
33211924SDaniel.Beauregard@Sun.COM 	}
33311924SDaniel.Beauregard@Sun.COM 
33411924SDaniel.Beauregard@Sun.COM 	return (NULL);
33511924SDaniel.Beauregard@Sun.COM }
33611924SDaniel.Beauregard@Sun.COM 
33711924SDaniel.Beauregard@Sun.COM /* ARGSUSED */
33811924SDaniel.Beauregard@Sun.COM static void
ql_crb_addr_transform_setup(ql_adapter_state_t * ha)33911924SDaniel.Beauregard@Sun.COM ql_crb_addr_transform_setup(ql_adapter_state_t *ha)
34011924SDaniel.Beauregard@Sun.COM {
34111924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(XDMA);
34211924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(TIMR);
34311924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(SRE);
34411924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(SQN3);
34511924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(SQN2);
34611924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(SQN1);
34711924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(SQN0);
34811924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(SQS3);
34911924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(SQS2);
35011924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(SQS1);
35111924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(SQS0);
35211924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(RPMX7);
35311924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(RPMX6);
35411924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(RPMX5);
35511924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(RPMX4);
35611924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(RPMX3);
35711924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(RPMX2);
35811924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(RPMX1);
35911924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(RPMX0);
36011924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(ROMUSB);
36111924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(SN);
36211924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(QMN);
36311924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(QMS);
36411924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGNI);
36511924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGND);
36611924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGN3);
36711924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGN2);
36811924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGN1);
36911924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGN0);
37011924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGSI);
37111924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGSD);
37211924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGS3);
37311924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGS2);
37411924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGS1);
37511924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PGS0);
37611924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PS);
37711924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(PH);
37811924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(NIU);
37911924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(I2Q);
38011924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(EG);
38111924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(MN);
38211924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(MS);
38311924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(CAS2);
38411924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(CAS1);
38511924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(CAS0);
38611924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(CAM);
38711924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(C2C1);
38811924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(C2C0);
38911924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(SMB);
39011924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(OCM0);
39111924SDaniel.Beauregard@Sun.COM 	/*
39211924SDaniel.Beauregard@Sun.COM 	 * Used only in P3 just define it for P2 also.
39311924SDaniel.Beauregard@Sun.COM 	 */
39411924SDaniel.Beauregard@Sun.COM 	crb_addr_transform(I2C0);
39511924SDaniel.Beauregard@Sun.COM 
39611924SDaniel.Beauregard@Sun.COM 	crb_table_initialized = 1;
39711924SDaniel.Beauregard@Sun.COM }
39811924SDaniel.Beauregard@Sun.COM 
39911924SDaniel.Beauregard@Sun.COM /*
40011924SDaniel.Beauregard@Sun.COM  * In: 'off' is offset from CRB space in 128M pci map
40111924SDaniel.Beauregard@Sun.COM  * Out: 'off' is 2M pci map addr
40211924SDaniel.Beauregard@Sun.COM  * side effect: lock crb window
40311924SDaniel.Beauregard@Sun.COM  */
40411924SDaniel.Beauregard@Sun.COM static void
ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t * ha,uint64_t * off)40511924SDaniel.Beauregard@Sun.COM ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t *ha, uint64_t *off)
40611924SDaniel.Beauregard@Sun.COM {
40711924SDaniel.Beauregard@Sun.COM 	uint32_t	win_read;
40811924SDaniel.Beauregard@Sun.COM 
40911924SDaniel.Beauregard@Sun.COM 	ha->crb_win = (uint32_t)CRB_HI(*off);
41011924SDaniel.Beauregard@Sun.COM 	WRT_REG_DWORD(ha, CRB_WINDOW_2M + ha->nx_pcibase, ha->crb_win);
41111924SDaniel.Beauregard@Sun.COM 
41211924SDaniel.Beauregard@Sun.COM 	/*
41311924SDaniel.Beauregard@Sun.COM 	 * Read back value to make sure write has gone through before trying
41411924SDaniel.Beauregard@Sun.COM 	 * to use it.
41511924SDaniel.Beauregard@Sun.COM 	 */
41611924SDaniel.Beauregard@Sun.COM 	win_read = RD_REG_DWORD(ha, CRB_WINDOW_2M + ha->nx_pcibase);
41711924SDaniel.Beauregard@Sun.COM 	if (win_read != ha->crb_win) {
41811924SDaniel.Beauregard@Sun.COM 		EL(ha, "Written crbwin (0x%x) != Read crbwin (0x%x), "
41911924SDaniel.Beauregard@Sun.COM 		    "off=0x%llx\n", ha->crb_win, win_read, *off);
42011924SDaniel.Beauregard@Sun.COM 	}
42111924SDaniel.Beauregard@Sun.COM 	*off = (*off & MASK(16)) + CRB_INDIRECT_2M + (uintptr_t)ha->nx_pcibase;
42211924SDaniel.Beauregard@Sun.COM }
42311924SDaniel.Beauregard@Sun.COM 
42411924SDaniel.Beauregard@Sun.COM static void
ql_8021_wr_32(ql_adapter_state_t * ha,uint64_t off,uint32_t data)42511924SDaniel.Beauregard@Sun.COM ql_8021_wr_32(ql_adapter_state_t *ha, uint64_t off, uint32_t data)
42611924SDaniel.Beauregard@Sun.COM {
42711924SDaniel.Beauregard@Sun.COM 	int	rv;
42811924SDaniel.Beauregard@Sun.COM 
42911924SDaniel.Beauregard@Sun.COM 	rv = ql_8021_pci_get_crb_addr_2M(ha, &off);
43011924SDaniel.Beauregard@Sun.COM 	if (rv == -1) {
43111924SDaniel.Beauregard@Sun.COM 		cmn_err(CE_PANIC, "ql_8021_wr_32, ql_8021_pci_get_crb_addr_"
43211924SDaniel.Beauregard@Sun.COM 		    "2M=-1\n");
43311924SDaniel.Beauregard@Sun.COM 	}
43411924SDaniel.Beauregard@Sun.COM 	if (rv == 1) {
43511924SDaniel.Beauregard@Sun.COM 		(void) ql_8021_crb_win_lock(ha);
43611924SDaniel.Beauregard@Sun.COM 		ql_8021_pci_set_crbwindow_2M(ha, &off);
43711924SDaniel.Beauregard@Sun.COM 	}
43811924SDaniel.Beauregard@Sun.COM 
43911924SDaniel.Beauregard@Sun.COM 	WRT_REG_DWORD(ha, (uintptr_t)off, data);
44011924SDaniel.Beauregard@Sun.COM 
44111924SDaniel.Beauregard@Sun.COM 	if (rv == 1) {
44211924SDaniel.Beauregard@Sun.COM 		ql_8021_crb_win_unlock(ha);
44311924SDaniel.Beauregard@Sun.COM 	}
44411924SDaniel.Beauregard@Sun.COM }
44511924SDaniel.Beauregard@Sun.COM 
44611924SDaniel.Beauregard@Sun.COM static void
ql_8021_rd_32(ql_adapter_state_t * ha,uint64_t off,uint32_t * data)44711924SDaniel.Beauregard@Sun.COM ql_8021_rd_32(ql_adapter_state_t *ha, uint64_t off, uint32_t *data)
44811924SDaniel.Beauregard@Sun.COM {
44911924SDaniel.Beauregard@Sun.COM 	int		rv;
45011924SDaniel.Beauregard@Sun.COM 	uint32_t	n;
45111924SDaniel.Beauregard@Sun.COM 
45211924SDaniel.Beauregard@Sun.COM 	rv = ql_8021_pci_get_crb_addr_2M(ha, &off);
45311924SDaniel.Beauregard@Sun.COM 	if (rv == -1) {
45411924SDaniel.Beauregard@Sun.COM 		cmn_err(CE_PANIC, "ql_8021_rd_32, ql_8021_pci_get_crb_addr_"
45511924SDaniel.Beauregard@Sun.COM 		    "2M=-1\n");
45611924SDaniel.Beauregard@Sun.COM 	}
45711924SDaniel.Beauregard@Sun.COM 
45811924SDaniel.Beauregard@Sun.COM 	if (rv == 1) {
45911924SDaniel.Beauregard@Sun.COM 		(void) ql_8021_crb_win_lock(ha);
46011924SDaniel.Beauregard@Sun.COM 		ql_8021_pci_set_crbwindow_2M(ha, &off);
46111924SDaniel.Beauregard@Sun.COM 	}
46211924SDaniel.Beauregard@Sun.COM 	n = RD_REG_DWORD(ha, (uintptr_t)off);
46311924SDaniel.Beauregard@Sun.COM 
46411924SDaniel.Beauregard@Sun.COM 	if (data != NULL) {
46511924SDaniel.Beauregard@Sun.COM 		*data = n;
46611924SDaniel.Beauregard@Sun.COM 	}
46711924SDaniel.Beauregard@Sun.COM 
46811924SDaniel.Beauregard@Sun.COM 	if (rv == 1) {
46911924SDaniel.Beauregard@Sun.COM 		ql_8021_crb_win_unlock(ha);
47011924SDaniel.Beauregard@Sun.COM 	}
47111924SDaniel.Beauregard@Sun.COM }
47211924SDaniel.Beauregard@Sun.COM 
47311924SDaniel.Beauregard@Sun.COM static int
ql_8021_crb_win_lock(ql_adapter_state_t * ha)47411924SDaniel.Beauregard@Sun.COM ql_8021_crb_win_lock(ql_adapter_state_t *ha)
47511924SDaniel.Beauregard@Sun.COM {
47611924SDaniel.Beauregard@Sun.COM 	uint32_t	done = 0, timeout = 0;
47711924SDaniel.Beauregard@Sun.COM 
47811924SDaniel.Beauregard@Sun.COM 	while (!done) {
47911924SDaniel.Beauregard@Sun.COM 		/* acquire semaphore3 from PCI HW block */
48011924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM7_LOCK), &done);
48111924SDaniel.Beauregard@Sun.COM 		if (done == 1) {
48211924SDaniel.Beauregard@Sun.COM 			break;
48311924SDaniel.Beauregard@Sun.COM 		}
48411924SDaniel.Beauregard@Sun.COM 		if (timeout >= CRB_WIN_LOCK_TIMEOUT) {
48511924SDaniel.Beauregard@Sun.COM 			EL(ha, "timeout\n");
48611924SDaniel.Beauregard@Sun.COM 			return (-1);
48711924SDaniel.Beauregard@Sun.COM 		}
48811924SDaniel.Beauregard@Sun.COM 		timeout++;
48911924SDaniel.Beauregard@Sun.COM 
49011924SDaniel.Beauregard@Sun.COM 		/* Yield CPU */
49111924SDaniel.Beauregard@Sun.COM 		delay(1);
49211924SDaniel.Beauregard@Sun.COM 	}
49311924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_WIN_LOCK_ID, ha->function_number);
49411924SDaniel.Beauregard@Sun.COM 
49511924SDaniel.Beauregard@Sun.COM 	return (0);
49611924SDaniel.Beauregard@Sun.COM }
49711924SDaniel.Beauregard@Sun.COM 
49811924SDaniel.Beauregard@Sun.COM static void
ql_8021_crb_win_unlock(ql_adapter_state_t * ha)49911924SDaniel.Beauregard@Sun.COM ql_8021_crb_win_unlock(ql_adapter_state_t *ha)
50011924SDaniel.Beauregard@Sun.COM {
50111924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM7_UNLOCK), NULL);
50211924SDaniel.Beauregard@Sun.COM }
50311924SDaniel.Beauregard@Sun.COM 
50411924SDaniel.Beauregard@Sun.COM static int
ql_8021_pci_get_crb_addr_2M(ql_adapter_state_t * ha,uint64_t * off)50511924SDaniel.Beauregard@Sun.COM ql_8021_pci_get_crb_addr_2M(ql_adapter_state_t *ha, uint64_t *off)
50611924SDaniel.Beauregard@Sun.COM {
50711924SDaniel.Beauregard@Sun.COM 	crb_128M_2M_sub_block_map_t	*m;
50811924SDaniel.Beauregard@Sun.COM 
50911924SDaniel.Beauregard@Sun.COM 	if (*off >= UNM_CRB_MAX) {
51011924SDaniel.Beauregard@Sun.COM 		EL(ha, "%llx >= %llx\n", *off, UNM_CRB_MAX);
51111924SDaniel.Beauregard@Sun.COM 		return (-1);
51211924SDaniel.Beauregard@Sun.COM 	}
51311924SDaniel.Beauregard@Sun.COM 
51411924SDaniel.Beauregard@Sun.COM 	if (*off >= UNM_PCI_CAMQM && (*off < UNM_PCI_CAMQM_2M_END)) {
51511924SDaniel.Beauregard@Sun.COM 		*off = (*off - UNM_PCI_CAMQM) + UNM_PCI_CAMQM_2M_BASE +
51611924SDaniel.Beauregard@Sun.COM 		    (uintptr_t)ha->nx_pcibase;
51711924SDaniel.Beauregard@Sun.COM 		return (0);
51811924SDaniel.Beauregard@Sun.COM 	}
51911924SDaniel.Beauregard@Sun.COM 
52011924SDaniel.Beauregard@Sun.COM 	if (*off < UNM_PCI_CRBSPACE) {
52111924SDaniel.Beauregard@Sun.COM 		EL(ha, "%llx < %llx\n", *off, UNM_PCI_CRBSPACE);
52211924SDaniel.Beauregard@Sun.COM 		return (-1);
52311924SDaniel.Beauregard@Sun.COM 	}
52411924SDaniel.Beauregard@Sun.COM 
52511924SDaniel.Beauregard@Sun.COM 	*off -= UNM_PCI_CRBSPACE;
52611924SDaniel.Beauregard@Sun.COM 	/*
52711924SDaniel.Beauregard@Sun.COM 	 * Try direct map
52811924SDaniel.Beauregard@Sun.COM 	 */
52911924SDaniel.Beauregard@Sun.COM 
53011924SDaniel.Beauregard@Sun.COM 	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
53111924SDaniel.Beauregard@Sun.COM 
53211924SDaniel.Beauregard@Sun.COM 	if (m->valid && ((uint64_t)m->start_128M <= *off) &&
53311924SDaniel.Beauregard@Sun.COM 	    ((uint64_t)m->end_128M > *off)) {
53411924SDaniel.Beauregard@Sun.COM 		*off = (uint64_t)(*off + m->start_2M - m->start_128M +
53511924SDaniel.Beauregard@Sun.COM 		    (uintptr_t)ha->nx_pcibase);
53611924SDaniel.Beauregard@Sun.COM 		return (0);
53711924SDaniel.Beauregard@Sun.COM 	}
53811924SDaniel.Beauregard@Sun.COM 
53911924SDaniel.Beauregard@Sun.COM 	/*
54011924SDaniel.Beauregard@Sun.COM 	 * Not in direct map, use crb window
54111924SDaniel.Beauregard@Sun.COM 	 */
54211924SDaniel.Beauregard@Sun.COM 	return (1);
54311924SDaniel.Beauregard@Sun.COM }
54411924SDaniel.Beauregard@Sun.COM 
54511924SDaniel.Beauregard@Sun.COM /*
54611924SDaniel.Beauregard@Sun.COM  * check memory access boundary.
54711924SDaniel.Beauregard@Sun.COM  * used by test agent. support ddr access only for now
54811924SDaniel.Beauregard@Sun.COM  */
54911924SDaniel.Beauregard@Sun.COM /* ARGSUSED */
55011924SDaniel.Beauregard@Sun.COM static uint32_t
ql_8021_pci_mem_bound_check(ql_adapter_state_t * ha,uint64_t addr,uint32_t size)55111924SDaniel.Beauregard@Sun.COM ql_8021_pci_mem_bound_check(ql_adapter_state_t *ha, uint64_t addr,
55211924SDaniel.Beauregard@Sun.COM     uint32_t size)
55311924SDaniel.Beauregard@Sun.COM {
55411924SDaniel.Beauregard@Sun.COM 	/*LINTED suspicious 0 comparison*/
55511924SDaniel.Beauregard@Sun.COM 	if (!QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET,
55611924SDaniel.Beauregard@Sun.COM 	    UNM_ADDR_DDR_NET_MAX) ||
55711924SDaniel.Beauregard@Sun.COM 	    /*LINTED suspicious 0 comparison*/
55811924SDaniel.Beauregard@Sun.COM 	    !QL_8021_ADDR_IN_RANGE(addr + size - 1, UNM_ADDR_DDR_NET,
55911924SDaniel.Beauregard@Sun.COM 	    UNM_ADDR_DDR_NET_MAX) ||
56011924SDaniel.Beauregard@Sun.COM 	    ((size != 1) && (size != 2) && (size != 4) && (size != 8))) {
56111924SDaniel.Beauregard@Sun.COM 		return (0);
56211924SDaniel.Beauregard@Sun.COM 	}
56311924SDaniel.Beauregard@Sun.COM 
56411924SDaniel.Beauregard@Sun.COM 	return (1);
56511924SDaniel.Beauregard@Sun.COM }
56611924SDaniel.Beauregard@Sun.COM 
56711924SDaniel.Beauregard@Sun.COM static uint64_t
ql_8021_pci_set_window(ql_adapter_state_t * ha,uint64_t addr)56811924SDaniel.Beauregard@Sun.COM ql_8021_pci_set_window(ql_adapter_state_t *ha, uint64_t addr)
56911924SDaniel.Beauregard@Sun.COM {
57011924SDaniel.Beauregard@Sun.COM 	uint32_t	window, win_read;
57111924SDaniel.Beauregard@Sun.COM 
57211924SDaniel.Beauregard@Sun.COM 	/*LINTED suspicious 0 comparison*/
57311924SDaniel.Beauregard@Sun.COM 	if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET,
57411924SDaniel.Beauregard@Sun.COM 	    UNM_ADDR_DDR_NET_MAX)) {
57511924SDaniel.Beauregard@Sun.COM 		/* DDR network side */
57611924SDaniel.Beauregard@Sun.COM 		window = (uint32_t)MN_WIN(addr);
57711924SDaniel.Beauregard@Sun.COM 		ha->ddr_mn_window = window;
57811924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window);
57911924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE,
58011924SDaniel.Beauregard@Sun.COM 		    &win_read);
58111924SDaniel.Beauregard@Sun.COM 		if ((win_read << 17) != window) {
58211924SDaniel.Beauregard@Sun.COM 			EL(ha, "Warning, Written MNwin (0x%x) != Read MNwin "
58311924SDaniel.Beauregard@Sun.COM 			    "(0x%x)\n", window, win_read);
58411924SDaniel.Beauregard@Sun.COM 		}
58511924SDaniel.Beauregard@Sun.COM 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_DDR_NET;
58611924SDaniel.Beauregard@Sun.COM 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM0,
58711924SDaniel.Beauregard@Sun.COM 	    UNM_ADDR_OCM0_MAX)) {
58811924SDaniel.Beauregard@Sun.COM 		uint32_t	temp1;
58911924SDaniel.Beauregard@Sun.COM 
59011924SDaniel.Beauregard@Sun.COM 		if ((addr & 0x00ff800) == 0xff800) {
59111924SDaniel.Beauregard@Sun.COM 			/* if bits 19:18&17:11 are on */
59211924SDaniel.Beauregard@Sun.COM 			EL(ha, "QM access not handled\n");
59311924SDaniel.Beauregard@Sun.COM 			addr = -1UL;
59411924SDaniel.Beauregard@Sun.COM 		}
59511924SDaniel.Beauregard@Sun.COM 
59611924SDaniel.Beauregard@Sun.COM 		window = (uint32_t)OCM_WIN(addr);
59711924SDaniel.Beauregard@Sun.COM 		ha->ddr_mn_window = window;
59811924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window);
59911924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE,
60011924SDaniel.Beauregard@Sun.COM 		    &win_read);
60111924SDaniel.Beauregard@Sun.COM 		temp1 = ((window & 0x1FF) << 7) |
60211924SDaniel.Beauregard@Sun.COM 		    ((window & 0x0FFFE0000) >> 17);
60311924SDaniel.Beauregard@Sun.COM 		if (win_read != temp1) {
60411924SDaniel.Beauregard@Sun.COM 			EL(ha, "Written OCMwin (0x%x) != Read OCMwin (0x%x)\n",
60511924SDaniel.Beauregard@Sun.COM 			    temp1, win_read);
60611924SDaniel.Beauregard@Sun.COM 		}
60711924SDaniel.Beauregard@Sun.COM 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_OCM0_2M;
60811924SDaniel.Beauregard@Sun.COM 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET,
60911924SDaniel.Beauregard@Sun.COM 	    NX_P3_ADDR_QDR_NET_MAX)) {
61011924SDaniel.Beauregard@Sun.COM 		/* QDR network side */
61111924SDaniel.Beauregard@Sun.COM 		window = (uint32_t)MS_WIN(addr);
61211924SDaniel.Beauregard@Sun.COM 		ha->qdr_sn_window = window;
61311924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window);
61411924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE,
61511924SDaniel.Beauregard@Sun.COM 		    &win_read);
61611924SDaniel.Beauregard@Sun.COM 		if (win_read != window) {
61711924SDaniel.Beauregard@Sun.COM 			EL(ha, "Written MSwin (0x%x) != Read MSwin (0x%x)\n",
61811924SDaniel.Beauregard@Sun.COM 			    window, win_read);
61911924SDaniel.Beauregard@Sun.COM 		}
62011924SDaniel.Beauregard@Sun.COM 		addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_QDR_NET;
62111924SDaniel.Beauregard@Sun.COM 	} else {
62211924SDaniel.Beauregard@Sun.COM 		/*
62311924SDaniel.Beauregard@Sun.COM 		 * peg gdb frequently accesses memory that doesn't exist,
62411924SDaniel.Beauregard@Sun.COM 		 * this limits the chit chat so debugging isn't slowed down.
62511924SDaniel.Beauregard@Sun.COM 		 */
62611924SDaniel.Beauregard@Sun.COM 		if ((pci_set_window_warning_count++ < 8) ||
62711924SDaniel.Beauregard@Sun.COM 		    (pci_set_window_warning_count % 64 == 0)) {
62811924SDaniel.Beauregard@Sun.COM 			EL(ha, "Unknown address range\n");
62911924SDaniel.Beauregard@Sun.COM 		}
63011924SDaniel.Beauregard@Sun.COM 		addr = -1UL;
63111924SDaniel.Beauregard@Sun.COM 	}
63211924SDaniel.Beauregard@Sun.COM 
63311924SDaniel.Beauregard@Sun.COM 	return (addr);
63411924SDaniel.Beauregard@Sun.COM }
63511924SDaniel.Beauregard@Sun.COM 
63611924SDaniel.Beauregard@Sun.COM /* check if address is in the same windows as the previous access */
63711924SDaniel.Beauregard@Sun.COM static int
ql_8021_pci_is_same_window(ql_adapter_state_t * ha,uint64_t addr)63811924SDaniel.Beauregard@Sun.COM ql_8021_pci_is_same_window(ql_adapter_state_t *ha, uint64_t addr)
63911924SDaniel.Beauregard@Sun.COM {
64011924SDaniel.Beauregard@Sun.COM 	uint32_t	window;
64111924SDaniel.Beauregard@Sun.COM 	uint64_t	qdr_max;
64211924SDaniel.Beauregard@Sun.COM 
64311924SDaniel.Beauregard@Sun.COM 	qdr_max = NX_P3_ADDR_QDR_NET_MAX;
64411924SDaniel.Beauregard@Sun.COM 
64511924SDaniel.Beauregard@Sun.COM 	/*LINTED suspicious 0 comparison*/
64611924SDaniel.Beauregard@Sun.COM 	if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET,
64711924SDaniel.Beauregard@Sun.COM 	    UNM_ADDR_DDR_NET_MAX)) {
64811924SDaniel.Beauregard@Sun.COM 		/* DDR network side */
64911924SDaniel.Beauregard@Sun.COM 		EL(ha, "DDR network side\n");
65011924SDaniel.Beauregard@Sun.COM 		return (0);	/* MN access can not come here */
65111924SDaniel.Beauregard@Sun.COM 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM0,
65211924SDaniel.Beauregard@Sun.COM 	    UNM_ADDR_OCM0_MAX)) {
65311924SDaniel.Beauregard@Sun.COM 		return (1);
65411924SDaniel.Beauregard@Sun.COM 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM1,
65511924SDaniel.Beauregard@Sun.COM 	    UNM_ADDR_OCM1_MAX)) {
65611924SDaniel.Beauregard@Sun.COM 		return (1);
65711924SDaniel.Beauregard@Sun.COM 	} else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET, qdr_max)) {
65811924SDaniel.Beauregard@Sun.COM 		/* QDR network side */
65911924SDaniel.Beauregard@Sun.COM 		window = (uint32_t)(((addr - UNM_ADDR_QDR_NET) >> 22) & 0x3f);
66011924SDaniel.Beauregard@Sun.COM 		if (ha->qdr_sn_window == window) {
66111924SDaniel.Beauregard@Sun.COM 			return (1);
66211924SDaniel.Beauregard@Sun.COM 		}
66311924SDaniel.Beauregard@Sun.COM 	}
66411924SDaniel.Beauregard@Sun.COM 
66511924SDaniel.Beauregard@Sun.COM 	return (0);
66611924SDaniel.Beauregard@Sun.COM }
66711924SDaniel.Beauregard@Sun.COM 
66811924SDaniel.Beauregard@Sun.COM static int
ql_8021_pci_mem_read_direct(ql_adapter_state_t * ha,uint64_t off,void * data,uint32_t size)66911924SDaniel.Beauregard@Sun.COM ql_8021_pci_mem_read_direct(ql_adapter_state_t *ha, uint64_t off, void *data,
67011924SDaniel.Beauregard@Sun.COM     uint32_t size)
67111924SDaniel.Beauregard@Sun.COM {
67211924SDaniel.Beauregard@Sun.COM 	void		*addr;
67311924SDaniel.Beauregard@Sun.COM 	int		ret = 0;
67411924SDaniel.Beauregard@Sun.COM 	uint64_t	start;
67511924SDaniel.Beauregard@Sun.COM 
67611924SDaniel.Beauregard@Sun.COM 	/*
67711924SDaniel.Beauregard@Sun.COM 	 * If attempting to access unknown address or straddle hw windows,
67811924SDaniel.Beauregard@Sun.COM 	 * do not access.
67911924SDaniel.Beauregard@Sun.COM 	 */
68011924SDaniel.Beauregard@Sun.COM 	if (((start = ql_8021_pci_set_window(ha, off)) == -1UL) ||
68111924SDaniel.Beauregard@Sun.COM 	    (ql_8021_pci_is_same_window(ha, off + size - 1) == 0)) {
68211924SDaniel.Beauregard@Sun.COM 		EL(ha, "out of bound pci memory access. offset is 0x%llx\n",
68311924SDaniel.Beauregard@Sun.COM 		    off);
68411924SDaniel.Beauregard@Sun.COM 		return (-1);
68511924SDaniel.Beauregard@Sun.COM 	}
68611924SDaniel.Beauregard@Sun.COM 
68711924SDaniel.Beauregard@Sun.COM 	addr = ql_8021_pci_base_offsetfset(ha, start);
68811924SDaniel.Beauregard@Sun.COM 	if (!addr) {
68911924SDaniel.Beauregard@Sun.COM 		addr = (void *)((uint8_t *)ha->nx_pcibase + start);
69011924SDaniel.Beauregard@Sun.COM 	}
69111924SDaniel.Beauregard@Sun.COM 
69211924SDaniel.Beauregard@Sun.COM 	switch (size) {
69311924SDaniel.Beauregard@Sun.COM 	case 1:
69411924SDaniel.Beauregard@Sun.COM 		*(uint8_t  *)data = RD_REG_BYTE(ha, addr);
69511924SDaniel.Beauregard@Sun.COM 		break;
69611924SDaniel.Beauregard@Sun.COM 	case 2:
69711924SDaniel.Beauregard@Sun.COM 		*(uint16_t  *)data = RD_REG_WORD(ha, addr);
69811924SDaniel.Beauregard@Sun.COM 		break;
69911924SDaniel.Beauregard@Sun.COM 	case 4:
70011924SDaniel.Beauregard@Sun.COM 		*(uint32_t  *)data = RD_REG_DWORD(ha, addr);
70111924SDaniel.Beauregard@Sun.COM 		break;
70211924SDaniel.Beauregard@Sun.COM 	case 8:
70311924SDaniel.Beauregard@Sun.COM 		*(uint64_t  *)data = RD_REG_DDWORD(ha, addr);
70411924SDaniel.Beauregard@Sun.COM 		break;
70511924SDaniel.Beauregard@Sun.COM 	default:
70611924SDaniel.Beauregard@Sun.COM 		EL(ha, "invalid size=%x\n", size);
70711924SDaniel.Beauregard@Sun.COM 		ret = -1;
70811924SDaniel.Beauregard@Sun.COM 		break;
70911924SDaniel.Beauregard@Sun.COM 	}
71011924SDaniel.Beauregard@Sun.COM 
71111924SDaniel.Beauregard@Sun.COM 	return (ret);
71211924SDaniel.Beauregard@Sun.COM }
71311924SDaniel.Beauregard@Sun.COM 
71411924SDaniel.Beauregard@Sun.COM static int
ql_8021_pci_mem_write_direct(ql_adapter_state_t * ha,uint64_t off,void * data,uint32_t size)71511924SDaniel.Beauregard@Sun.COM ql_8021_pci_mem_write_direct(ql_adapter_state_t *ha, uint64_t off, void *data,
71611924SDaniel.Beauregard@Sun.COM     uint32_t size)
71711924SDaniel.Beauregard@Sun.COM {
71811924SDaniel.Beauregard@Sun.COM 	void		*addr;
71911924SDaniel.Beauregard@Sun.COM 	int		ret = 0;
72011924SDaniel.Beauregard@Sun.COM 	uint64_t	start;
72111924SDaniel.Beauregard@Sun.COM 
72211924SDaniel.Beauregard@Sun.COM 	/*
72311924SDaniel.Beauregard@Sun.COM 	 * If attempting to access unknown address or straddle hw windows,
72411924SDaniel.Beauregard@Sun.COM 	 * do not access.
72511924SDaniel.Beauregard@Sun.COM 	 */
72611924SDaniel.Beauregard@Sun.COM 	if (((start = ql_8021_pci_set_window(ha, off)) == -1UL) ||
72711924SDaniel.Beauregard@Sun.COM 	    (ql_8021_pci_is_same_window(ha, off + size -1) == 0)) {
72811924SDaniel.Beauregard@Sun.COM 		EL(ha, "out of bound pci memory access. offset is 0x%llx\n",
72911924SDaniel.Beauregard@Sun.COM 		    off);
73011924SDaniel.Beauregard@Sun.COM 		return (-1);
73111924SDaniel.Beauregard@Sun.COM 	}
73211924SDaniel.Beauregard@Sun.COM 
73311924SDaniel.Beauregard@Sun.COM 	addr = ql_8021_pci_base_offsetfset(ha, start);
73411924SDaniel.Beauregard@Sun.COM 	if (!addr) {
73511924SDaniel.Beauregard@Sun.COM 		addr = (void *)((uint8_t *)ha->nx_pcibase + start);
73611924SDaniel.Beauregard@Sun.COM 	}
73711924SDaniel.Beauregard@Sun.COM 
73811924SDaniel.Beauregard@Sun.COM 	switch (size) {
73911924SDaniel.Beauregard@Sun.COM 	case 1:
74011924SDaniel.Beauregard@Sun.COM 		WRT_REG_BYTE(ha, addr, *(uint8_t *)data);
74111924SDaniel.Beauregard@Sun.COM 		break;
74211924SDaniel.Beauregard@Sun.COM 	case 2:
74311924SDaniel.Beauregard@Sun.COM 		WRT_REG_WORD(ha, addr, *(uint16_t *)data);
74411924SDaniel.Beauregard@Sun.COM 		break;
74511924SDaniel.Beauregard@Sun.COM 	case 4:
74611924SDaniel.Beauregard@Sun.COM 		WRT_REG_DWORD(ha, addr, *(uint32_t *)data);
74711924SDaniel.Beauregard@Sun.COM 		break;
74811924SDaniel.Beauregard@Sun.COM 	case 8:
74911924SDaniel.Beauregard@Sun.COM 		WRT_REG_DDWORD(ha, addr, *(uint64_t *)data);
75011924SDaniel.Beauregard@Sun.COM 		break;
75111924SDaniel.Beauregard@Sun.COM 	default:
75211924SDaniel.Beauregard@Sun.COM 		EL(ha, "invalid size=%x\n", size);
75311924SDaniel.Beauregard@Sun.COM 		ret = -1;
75411924SDaniel.Beauregard@Sun.COM 		break;
75511924SDaniel.Beauregard@Sun.COM 	}
75611924SDaniel.Beauregard@Sun.COM 
75711924SDaniel.Beauregard@Sun.COM 	return (ret);
75811924SDaniel.Beauregard@Sun.COM }
75911924SDaniel.Beauregard@Sun.COM 
76011924SDaniel.Beauregard@Sun.COM static int
ql_8021_pci_mem_read_2M(ql_adapter_state_t * ha,uint64_t off,void * data,uint32_t size)76111924SDaniel.Beauregard@Sun.COM ql_8021_pci_mem_read_2M(ql_adapter_state_t *ha, uint64_t off, void *data,
76211924SDaniel.Beauregard@Sun.COM     uint32_t size)
76311924SDaniel.Beauregard@Sun.COM {
76411924SDaniel.Beauregard@Sun.COM 	int		j = 0;
76511924SDaniel.Beauregard@Sun.COM 	uint32_t	i, temp, sz[2], loop, shift_amount;
76611924SDaniel.Beauregard@Sun.COM 	uint64_t	start, end, k;
76711924SDaniel.Beauregard@Sun.COM 	uint64_t	off8, off0[2], val, mem_crb, word[2] = {0, 0};
76811924SDaniel.Beauregard@Sun.COM 
76911924SDaniel.Beauregard@Sun.COM 	/*
77011924SDaniel.Beauregard@Sun.COM 	 * If not MN, go check for MS or invalid.
77111924SDaniel.Beauregard@Sun.COM 	 */
77211924SDaniel.Beauregard@Sun.COM 
77311924SDaniel.Beauregard@Sun.COM 	if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
77411924SDaniel.Beauregard@Sun.COM 		mem_crb = UNM_CRB_QDR_NET;
77511924SDaniel.Beauregard@Sun.COM 	} else {
77611924SDaniel.Beauregard@Sun.COM 		mem_crb = UNM_CRB_DDR_NET;
77711924SDaniel.Beauregard@Sun.COM 		if (ql_8021_pci_mem_bound_check(ha, off, size) == 0) {
77811924SDaniel.Beauregard@Sun.COM 			return (ql_8021_pci_mem_read_direct(ha, off, data,
77911924SDaniel.Beauregard@Sun.COM 			    size));
78011924SDaniel.Beauregard@Sun.COM 		}
78111924SDaniel.Beauregard@Sun.COM 	}
78211924SDaniel.Beauregard@Sun.COM 
78311924SDaniel.Beauregard@Sun.COM 	if (NX_IS_REVISION_P3PLUS(ha->rev_id)) {
78411924SDaniel.Beauregard@Sun.COM 		off8 = off & 0xfffffff0;
78511924SDaniel.Beauregard@Sun.COM 		off0[0] = off & 0xf;
78611924SDaniel.Beauregard@Sun.COM 		sz[0] = (uint32_t)(((uint64_t)size < (16 - off0[0])) ? size :
78711924SDaniel.Beauregard@Sun.COM 		    (16 - off0[0]));
78811924SDaniel.Beauregard@Sun.COM 		shift_amount = 4;
78911924SDaniel.Beauregard@Sun.COM 	} else {
79011924SDaniel.Beauregard@Sun.COM 		off8 = off & 0xfffffff8;
79111924SDaniel.Beauregard@Sun.COM 		off0[0] = off & 0x7;
79211924SDaniel.Beauregard@Sun.COM 		sz[0] = (uint32_t)(((uint64_t)size < (8 - off0[0])) ? size :
79311924SDaniel.Beauregard@Sun.COM 		    (8 - off0[0]));
79411924SDaniel.Beauregard@Sun.COM 		shift_amount = 3;
79511924SDaniel.Beauregard@Sun.COM 	}
79611924SDaniel.Beauregard@Sun.COM 	loop = (uint32_t)(((off0[0] + size - 1) >> shift_amount) + 1);
79711924SDaniel.Beauregard@Sun.COM 	off0[1] = 0;
79811924SDaniel.Beauregard@Sun.COM 	sz[1] = size - sz[0];
79911924SDaniel.Beauregard@Sun.COM 
80011924SDaniel.Beauregard@Sun.COM 	/*
80111924SDaniel.Beauregard@Sun.COM 	 * don't lock here - write_wx gets the lock if each time
80211924SDaniel.Beauregard@Sun.COM 	 * write_lock_irqsave(&adapter->adapter_lock, flags);
80311924SDaniel.Beauregard@Sun.COM 	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
80411924SDaniel.Beauregard@Sun.COM 	 */
80511924SDaniel.Beauregard@Sun.COM 
80611924SDaniel.Beauregard@Sun.COM 	for (i = 0; i < loop; i++) {
80711924SDaniel.Beauregard@Sun.COM 		temp = (uint32_t)(off8 + (i << shift_amount));
80811924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);
80911924SDaniel.Beauregard@Sun.COM 		temp = 0;
81011924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp);
81111924SDaniel.Beauregard@Sun.COM 		temp = MIU_TA_CTL_ENABLE;
81211924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
81311924SDaniel.Beauregard@Sun.COM 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
81411924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
81511924SDaniel.Beauregard@Sun.COM 
81611924SDaniel.Beauregard@Sun.COM 		for (j = 0; j < MAX_CTL_CHECK; j++) {
81711924SDaniel.Beauregard@Sun.COM 			ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL, &temp);
81811924SDaniel.Beauregard@Sun.COM 			if ((temp & MIU_TA_CTL_BUSY) == 0) {
81911924SDaniel.Beauregard@Sun.COM 				break;
82011924SDaniel.Beauregard@Sun.COM 			}
82111924SDaniel.Beauregard@Sun.COM 		}
82211924SDaniel.Beauregard@Sun.COM 
82311924SDaniel.Beauregard@Sun.COM 		if (j >= MAX_CTL_CHECK) {
82411924SDaniel.Beauregard@Sun.COM 			EL(ha, "failed to read through agent\n");
82511924SDaniel.Beauregard@Sun.COM 			break;
82611924SDaniel.Beauregard@Sun.COM 		}
82711924SDaniel.Beauregard@Sun.COM 
82811924SDaniel.Beauregard@Sun.COM 		start = off0[i] >> 2;
82911924SDaniel.Beauregard@Sun.COM 		end = (off0[i] + sz[i] - 1) >> 2;
83011924SDaniel.Beauregard@Sun.COM 		for (k = start; k <= end; k++) {
83111924SDaniel.Beauregard@Sun.COM 			ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_RDDATA(k),
83211924SDaniel.Beauregard@Sun.COM 			    &temp);
83311924SDaniel.Beauregard@Sun.COM 			word[i] |= ((uint64_t)temp << (32 * (k & 1)));
83411924SDaniel.Beauregard@Sun.COM 		}
83511924SDaniel.Beauregard@Sun.COM 	}
83611924SDaniel.Beauregard@Sun.COM 
83711924SDaniel.Beauregard@Sun.COM 	/*
83811924SDaniel.Beauregard@Sun.COM 	 * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
83911924SDaniel.Beauregard@Sun.COM 	 * write_unlock_irqrestore(&adapter->adapter_lock, flags);
84011924SDaniel.Beauregard@Sun.COM 	 */
84111924SDaniel.Beauregard@Sun.COM 
84211924SDaniel.Beauregard@Sun.COM 	if (j >= MAX_CTL_CHECK) {
84311924SDaniel.Beauregard@Sun.COM 		return (-1);
84411924SDaniel.Beauregard@Sun.COM 	}
84511924SDaniel.Beauregard@Sun.COM 
84611924SDaniel.Beauregard@Sun.COM 	if ((off0[0] & 7) == 0) {
84711924SDaniel.Beauregard@Sun.COM 		val = word[0];
84811924SDaniel.Beauregard@Sun.COM 	} else {
84911924SDaniel.Beauregard@Sun.COM 		val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
85011924SDaniel.Beauregard@Sun.COM 		    ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
85111924SDaniel.Beauregard@Sun.COM 	}
85211924SDaniel.Beauregard@Sun.COM 
85311924SDaniel.Beauregard@Sun.COM 	switch (size) {
85411924SDaniel.Beauregard@Sun.COM 	case 1:
85511924SDaniel.Beauregard@Sun.COM 		*(uint8_t *)data = (uint8_t)val;
85611924SDaniel.Beauregard@Sun.COM 		break;
85711924SDaniel.Beauregard@Sun.COM 	case 2:
85811924SDaniel.Beauregard@Sun.COM 		*(uint16_t *)data = (uint16_t)val;
85911924SDaniel.Beauregard@Sun.COM 		break;
86011924SDaniel.Beauregard@Sun.COM 	case 4:
86111924SDaniel.Beauregard@Sun.COM 		*(uint32_t *)data = (uint32_t)val;
86211924SDaniel.Beauregard@Sun.COM 		break;
86311924SDaniel.Beauregard@Sun.COM 	case 8:
86411924SDaniel.Beauregard@Sun.COM 		*(uint64_t *)data = val;
86511924SDaniel.Beauregard@Sun.COM 		break;
86611924SDaniel.Beauregard@Sun.COM 	}
86711924SDaniel.Beauregard@Sun.COM 
86811924SDaniel.Beauregard@Sun.COM 	return (0);
86911924SDaniel.Beauregard@Sun.COM }
87011924SDaniel.Beauregard@Sun.COM 
87111924SDaniel.Beauregard@Sun.COM static int
ql_8021_pci_mem_write_2M(ql_adapter_state_t * ha,uint64_t off,void * data,uint32_t size)87211924SDaniel.Beauregard@Sun.COM ql_8021_pci_mem_write_2M(ql_adapter_state_t *ha, uint64_t off, void *data,
87311924SDaniel.Beauregard@Sun.COM     uint32_t size)
87411924SDaniel.Beauregard@Sun.COM {
87511924SDaniel.Beauregard@Sun.COM 	int		j, ret = 0;
87611924SDaniel.Beauregard@Sun.COM 	uint32_t	i, temp, loop, sz[2];
87711924SDaniel.Beauregard@Sun.COM 	uint32_t	scale, shift_amount, p3p, startword;
87811924SDaniel.Beauregard@Sun.COM 	uint64_t	off8, off0, mem_crb, tmpw, word[2] = {0, 0};
87911924SDaniel.Beauregard@Sun.COM 
88011924SDaniel.Beauregard@Sun.COM 	/*
88111924SDaniel.Beauregard@Sun.COM 	 * If not MN, go check for MS or invalid.
88211924SDaniel.Beauregard@Sun.COM 	 */
88311924SDaniel.Beauregard@Sun.COM 	if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) {
88411924SDaniel.Beauregard@Sun.COM 		mem_crb = UNM_CRB_QDR_NET;
88511924SDaniel.Beauregard@Sun.COM 	} else {
88611924SDaniel.Beauregard@Sun.COM 		mem_crb = UNM_CRB_DDR_NET;
88711924SDaniel.Beauregard@Sun.COM 		if (ql_8021_pci_mem_bound_check(ha, off, size) == 0) {
88811924SDaniel.Beauregard@Sun.COM 			return (ql_8021_pci_mem_write_direct(ha, off, data,
88911924SDaniel.Beauregard@Sun.COM 			    size));
89011924SDaniel.Beauregard@Sun.COM 		}
89111924SDaniel.Beauregard@Sun.COM 	}
89211924SDaniel.Beauregard@Sun.COM 
89311924SDaniel.Beauregard@Sun.COM 	off0 = off & 0x7;
89411924SDaniel.Beauregard@Sun.COM 	sz[0] = (uint32_t)(((uint64_t)size < (8 - off0)) ? size : (8 - off0));
89511924SDaniel.Beauregard@Sun.COM 	sz[1] = size - sz[0];
89611924SDaniel.Beauregard@Sun.COM 
89711924SDaniel.Beauregard@Sun.COM 	if (NX_IS_REVISION_P3PLUS(ha->rev_id)) {
89811924SDaniel.Beauregard@Sun.COM 		off8 = off & 0xfffffff0;
89911924SDaniel.Beauregard@Sun.COM 		loop = (uint32_t)((((off & 0xf) + size - 1) >> 4) + 1);
90011924SDaniel.Beauregard@Sun.COM 		shift_amount = 4;
90111924SDaniel.Beauregard@Sun.COM 		scale = 2;
90211924SDaniel.Beauregard@Sun.COM 		p3p = 1;
90311924SDaniel.Beauregard@Sun.COM 		startword = (uint32_t)((off & 0xf) / 8);
90411924SDaniel.Beauregard@Sun.COM 	} else {
90511924SDaniel.Beauregard@Sun.COM 		off8 = off & 0xfffffff8;
90611924SDaniel.Beauregard@Sun.COM 		loop = (uint32_t)(((off0 + size - 1) >> 3) + 1);
90711924SDaniel.Beauregard@Sun.COM 		shift_amount = 3;
90811924SDaniel.Beauregard@Sun.COM 		scale = 1;
90911924SDaniel.Beauregard@Sun.COM 		p3p = 0;
91011924SDaniel.Beauregard@Sun.COM 		startword = 0;
91111924SDaniel.Beauregard@Sun.COM 	}
91211924SDaniel.Beauregard@Sun.COM 
91311924SDaniel.Beauregard@Sun.COM 	if (p3p || (size != 8) || (off0 != 0)) {
91411924SDaniel.Beauregard@Sun.COM 		for (i = 0; i < loop; i++) {
91511924SDaniel.Beauregard@Sun.COM 			if (ql_8021_pci_mem_read_2M(ha, off8 +
91611924SDaniel.Beauregard@Sun.COM 			    (i << shift_amount), &word[i * scale], 8)) {
91711924SDaniel.Beauregard@Sun.COM 				EL(ha, "8021_pci_mem_read_2M != 0\n");
91811924SDaniel.Beauregard@Sun.COM 				return (-1);
91911924SDaniel.Beauregard@Sun.COM 			}
92011924SDaniel.Beauregard@Sun.COM 		}
92111924SDaniel.Beauregard@Sun.COM 	}
92211924SDaniel.Beauregard@Sun.COM 
92311924SDaniel.Beauregard@Sun.COM 	switch (size) {
92411924SDaniel.Beauregard@Sun.COM 	case 1:
92511924SDaniel.Beauregard@Sun.COM 		tmpw = (uint64_t)(*((uint8_t *)data));
92611924SDaniel.Beauregard@Sun.COM 		break;
92711924SDaniel.Beauregard@Sun.COM 	case 2:
92811924SDaniel.Beauregard@Sun.COM 		tmpw = (uint64_t)(*((uint16_t *)data));
92911924SDaniel.Beauregard@Sun.COM 		break;
93011924SDaniel.Beauregard@Sun.COM 	case 4:
93111924SDaniel.Beauregard@Sun.COM 		tmpw = (uint64_t)(*((uint32_t *)data));
93211924SDaniel.Beauregard@Sun.COM 		break;
93311924SDaniel.Beauregard@Sun.COM 	case 8:
93411924SDaniel.Beauregard@Sun.COM 	default:
93511924SDaniel.Beauregard@Sun.COM 		tmpw = *((uint64_t *)data);
93611924SDaniel.Beauregard@Sun.COM 		break;
93711924SDaniel.Beauregard@Sun.COM 	}
93811924SDaniel.Beauregard@Sun.COM 
93911924SDaniel.Beauregard@Sun.COM 	if (p3p) {
94011924SDaniel.Beauregard@Sun.COM 		if (sz[0] == 8) {
94111924SDaniel.Beauregard@Sun.COM 			word[startword] = tmpw;
94211924SDaniel.Beauregard@Sun.COM 		} else {
94311924SDaniel.Beauregard@Sun.COM 			word[startword] &= ~((~(~0ULL << (sz[0] * 8))) <<
94411924SDaniel.Beauregard@Sun.COM 			    (off0 * 8));
94511924SDaniel.Beauregard@Sun.COM 			word[startword] |= tmpw << (off0 * 8);
94611924SDaniel.Beauregard@Sun.COM 		}
94711924SDaniel.Beauregard@Sun.COM 		if (sz[1] != 0) {
94811924SDaniel.Beauregard@Sun.COM 			word[startword+1] &= ~(~0ULL << (sz[1] * 8));
94911924SDaniel.Beauregard@Sun.COM 			word[startword+1] |= tmpw >> (sz[0] * 8);
95011924SDaniel.Beauregard@Sun.COM 		}
95111924SDaniel.Beauregard@Sun.COM 	} else {
95211924SDaniel.Beauregard@Sun.COM 		word[startword] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
95311924SDaniel.Beauregard@Sun.COM 		word[startword] |= tmpw << (off0 * 8);
95411924SDaniel.Beauregard@Sun.COM 
95511924SDaniel.Beauregard@Sun.COM 		if (loop == 2) {
95611924SDaniel.Beauregard@Sun.COM 			word[1] &= ~(~0ULL << (sz[1] * 8));
95711924SDaniel.Beauregard@Sun.COM 			word[1] |= tmpw >> (sz[0] * 8);
95811924SDaniel.Beauregard@Sun.COM 		}
95911924SDaniel.Beauregard@Sun.COM 	}
96011924SDaniel.Beauregard@Sun.COM 
96111924SDaniel.Beauregard@Sun.COM 	/*
96211924SDaniel.Beauregard@Sun.COM 	 * don't lock here - write_wx gets the lock if each time
96311924SDaniel.Beauregard@Sun.COM 	 * write_lock_irqsave(&adapter->adapter_lock, flags);
96411924SDaniel.Beauregard@Sun.COM 	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
96511924SDaniel.Beauregard@Sun.COM 	 */
96611924SDaniel.Beauregard@Sun.COM 
96711924SDaniel.Beauregard@Sun.COM 	for (i = 0; i < loop; i++) {
96811924SDaniel.Beauregard@Sun.COM 		temp = (uint32_t)(off8 + (i << shift_amount));
96911924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp);
97011924SDaniel.Beauregard@Sun.COM 		temp = 0;
97111924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp);
97211924SDaniel.Beauregard@Sun.COM 		temp = (uint32_t)(word[i * scale] & 0xffffffff);
97311924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_LO, temp);
97411924SDaniel.Beauregard@Sun.COM 		temp = (uint32_t)((word[i * scale] >> 32) & 0xffffffff);
97511924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_HI, temp);
97611924SDaniel.Beauregard@Sun.COM 		if (p3p) {
97711924SDaniel.Beauregard@Sun.COM 			temp = (uint32_t)(word[i * scale + 1] & 0xffffffff);
97811924SDaniel.Beauregard@Sun.COM 			ql_8021_wr_32(ha,
97911924SDaniel.Beauregard@Sun.COM 			    mem_crb + MIU_TEST_AGT_WRDATA_UPPER_LO, temp);
98011924SDaniel.Beauregard@Sun.COM 			temp = (uint32_t)((word[i * scale + 1] >> 32) &
98111924SDaniel.Beauregard@Sun.COM 			    0xffffffff);
98211924SDaniel.Beauregard@Sun.COM 			ql_8021_wr_32(ha,
98311924SDaniel.Beauregard@Sun.COM 			    mem_crb + MIU_TEST_AGT_WRDATA_UPPER_HI, temp);
98411924SDaniel.Beauregard@Sun.COM 		}
98511924SDaniel.Beauregard@Sun.COM 		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
98611924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
98711924SDaniel.Beauregard@Sun.COM 		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
98811924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp);
98911924SDaniel.Beauregard@Sun.COM 
99011924SDaniel.Beauregard@Sun.COM 		for (j = 0; j < MAX_CTL_CHECK; j++) {
99111924SDaniel.Beauregard@Sun.COM 			ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL, &temp);
99211924SDaniel.Beauregard@Sun.COM 			if ((temp & MIU_TA_CTL_BUSY) == 0)
99311924SDaniel.Beauregard@Sun.COM 				break;
99411924SDaniel.Beauregard@Sun.COM 		}
99511924SDaniel.Beauregard@Sun.COM 
99611924SDaniel.Beauregard@Sun.COM 		if (j >= MAX_CTL_CHECK) {
99711924SDaniel.Beauregard@Sun.COM 			EL(ha, "failed to write through agent\n");
99811924SDaniel.Beauregard@Sun.COM 			ret = -1;
99911924SDaniel.Beauregard@Sun.COM 			break;
100011924SDaniel.Beauregard@Sun.COM 		}
100111924SDaniel.Beauregard@Sun.COM 	}
100211924SDaniel.Beauregard@Sun.COM 
100311924SDaniel.Beauregard@Sun.COM 	return (ret);
100411924SDaniel.Beauregard@Sun.COM }
100511924SDaniel.Beauregard@Sun.COM 
100611924SDaniel.Beauregard@Sun.COM static uint32_t
ql_8021_decode_crb_addr(ql_adapter_state_t * ha,uint32_t addr)100711924SDaniel.Beauregard@Sun.COM ql_8021_decode_crb_addr(ql_adapter_state_t *ha, uint32_t addr)
100811924SDaniel.Beauregard@Sun.COM {
100911924SDaniel.Beauregard@Sun.COM 	int		i;
101011924SDaniel.Beauregard@Sun.COM 	uint32_t	base_addr, offset, pci_base;
101111924SDaniel.Beauregard@Sun.COM 
101211924SDaniel.Beauregard@Sun.COM 	if (!crb_table_initialized) {
101311924SDaniel.Beauregard@Sun.COM 		ql_crb_addr_transform_setup(ha);
101411924SDaniel.Beauregard@Sun.COM 	}
101511924SDaniel.Beauregard@Sun.COM 
101611924SDaniel.Beauregard@Sun.COM 	pci_base = ADDR_ERROR;
101711924SDaniel.Beauregard@Sun.COM 	base_addr = addr & 0xfff00000;
101811924SDaniel.Beauregard@Sun.COM 	offset = addr & 0x000fffff;
101911924SDaniel.Beauregard@Sun.COM 
102011924SDaniel.Beauregard@Sun.COM 	for (i = 0; i < MAX_CRB_XFORM; i++) {
102111924SDaniel.Beauregard@Sun.COM 		if (crb_addr_xform[i] == base_addr) {
102211924SDaniel.Beauregard@Sun.COM 			pci_base = i << 20;
102311924SDaniel.Beauregard@Sun.COM 			break;
102411924SDaniel.Beauregard@Sun.COM 		}
102511924SDaniel.Beauregard@Sun.COM 	}
102611924SDaniel.Beauregard@Sun.COM 	if (pci_base == ADDR_ERROR) {
102711924SDaniel.Beauregard@Sun.COM 		return (pci_base);
102811924SDaniel.Beauregard@Sun.COM 	} else {
102911924SDaniel.Beauregard@Sun.COM 		return (pci_base + offset);
103011924SDaniel.Beauregard@Sun.COM 	}
103111924SDaniel.Beauregard@Sun.COM }
103211924SDaniel.Beauregard@Sun.COM 
103311924SDaniel.Beauregard@Sun.COM static int
ql_8021_hw_lock(ql_adapter_state_t * ha,uint32_t timer)103411924SDaniel.Beauregard@Sun.COM ql_8021_hw_lock(ql_adapter_state_t *ha, uint32_t timer)
103511924SDaniel.Beauregard@Sun.COM {
103611924SDaniel.Beauregard@Sun.COM 	uint32_t	done = 0, timeout = 0;
103711924SDaniel.Beauregard@Sun.COM 
103811924SDaniel.Beauregard@Sun.COM 	while (!done) {
103911924SDaniel.Beauregard@Sun.COM 		/* acquire semaphore5 from PCI HW block */
104011924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM5_LOCK), &done);
104111924SDaniel.Beauregard@Sun.COM 		if (done == 1) {
104211924SDaniel.Beauregard@Sun.COM 			break;
104311924SDaniel.Beauregard@Sun.COM 		}
104411924SDaniel.Beauregard@Sun.COM 		if (timeout >= timer) {
104511924SDaniel.Beauregard@Sun.COM 			EL(ha, "timeout\n");
104611924SDaniel.Beauregard@Sun.COM 			return (-1);
104711924SDaniel.Beauregard@Sun.COM 		}
104811924SDaniel.Beauregard@Sun.COM 		timeout++;
104911924SDaniel.Beauregard@Sun.COM 
105011924SDaniel.Beauregard@Sun.COM 		/*
105111924SDaniel.Beauregard@Sun.COM 		 * Yield CPU
105211924SDaniel.Beauregard@Sun.COM 		 */
105311924SDaniel.Beauregard@Sun.COM 		delay(1);
105411924SDaniel.Beauregard@Sun.COM 	}
105511924SDaniel.Beauregard@Sun.COM 
105611924SDaniel.Beauregard@Sun.COM 	return (0);
105711924SDaniel.Beauregard@Sun.COM }
105811924SDaniel.Beauregard@Sun.COM 
105911924SDaniel.Beauregard@Sun.COM static void
ql_8021_hw_unlock(ql_adapter_state_t * ha)106011924SDaniel.Beauregard@Sun.COM ql_8021_hw_unlock(ql_adapter_state_t *ha)
106111924SDaniel.Beauregard@Sun.COM {
106211924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM5_UNLOCK), NULL);
106311924SDaniel.Beauregard@Sun.COM }
106411924SDaniel.Beauregard@Sun.COM 
106511924SDaniel.Beauregard@Sun.COM static int
ql_8021_rom_lock(ql_adapter_state_t * ha)106611924SDaniel.Beauregard@Sun.COM ql_8021_rom_lock(ql_adapter_state_t *ha)
106711924SDaniel.Beauregard@Sun.COM {
106811924SDaniel.Beauregard@Sun.COM 	uint32_t	done = 0, timeout = 0;
106911924SDaniel.Beauregard@Sun.COM 
107011924SDaniel.Beauregard@Sun.COM 	while (!done) {
107111924SDaniel.Beauregard@Sun.COM 		/* acquire semaphore2 from PCI HW block */
107211924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM2_LOCK), &done);
107311924SDaniel.Beauregard@Sun.COM 		if (done == 1) {
107411924SDaniel.Beauregard@Sun.COM 			break;
107511924SDaniel.Beauregard@Sun.COM 		}
107611924SDaniel.Beauregard@Sun.COM 		if (timeout >= ROM_LOCK_TIMEOUT) {
107711924SDaniel.Beauregard@Sun.COM 			EL(ha, "timeout\n");
107811924SDaniel.Beauregard@Sun.COM 			return (-1);
107911924SDaniel.Beauregard@Sun.COM 		}
108011924SDaniel.Beauregard@Sun.COM 		timeout++;
108111924SDaniel.Beauregard@Sun.COM 
108211924SDaniel.Beauregard@Sun.COM 		/*
108311924SDaniel.Beauregard@Sun.COM 		 * Yield CPU
108411924SDaniel.Beauregard@Sun.COM 		 */
108511924SDaniel.Beauregard@Sun.COM 		delay(1);
108611924SDaniel.Beauregard@Sun.COM 	}
108711924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROM_LOCK_ID, ROM_LOCK_DRIVER);
108811924SDaniel.Beauregard@Sun.COM 
108911924SDaniel.Beauregard@Sun.COM 	return (0);
109011924SDaniel.Beauregard@Sun.COM }
109111924SDaniel.Beauregard@Sun.COM 
109211924SDaniel.Beauregard@Sun.COM static void
ql_8021_rom_unlock(ql_adapter_state_t * ha)109311924SDaniel.Beauregard@Sun.COM ql_8021_rom_unlock(ql_adapter_state_t *ha)
109411924SDaniel.Beauregard@Sun.COM {
109511924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM2_UNLOCK), NULL);
109611924SDaniel.Beauregard@Sun.COM }
109711924SDaniel.Beauregard@Sun.COM 
109811924SDaniel.Beauregard@Sun.COM static int
ql_8021_wait_rom_done(ql_adapter_state_t * ha)109911924SDaniel.Beauregard@Sun.COM ql_8021_wait_rom_done(ql_adapter_state_t *ha)
110011924SDaniel.Beauregard@Sun.COM {
110111924SDaniel.Beauregard@Sun.COM 	uint32_t	timeout = 0, done = 0;
110211924SDaniel.Beauregard@Sun.COM 
110311924SDaniel.Beauregard@Sun.COM 	while (done == 0) {
110411924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, UNM_ROMUSB_GLB_STATUS, &done);
110511924SDaniel.Beauregard@Sun.COM 		done &= 2;
110611924SDaniel.Beauregard@Sun.COM 		timeout++;
110711924SDaniel.Beauregard@Sun.COM 		if (timeout >= ROM_MAX_TIMEOUT) {
110811924SDaniel.Beauregard@Sun.COM 			EL(ha, "Timeout reached waiting for rom done\n");
110911924SDaniel.Beauregard@Sun.COM 			return (-1);
111011924SDaniel.Beauregard@Sun.COM 		}
111111924SDaniel.Beauregard@Sun.COM 	}
111211924SDaniel.Beauregard@Sun.COM 
111311924SDaniel.Beauregard@Sun.COM 	return (0);
111411924SDaniel.Beauregard@Sun.COM }
111511924SDaniel.Beauregard@Sun.COM 
111611924SDaniel.Beauregard@Sun.COM static int
ql_8021_wait_flash_done(ql_adapter_state_t * ha)111711924SDaniel.Beauregard@Sun.COM ql_8021_wait_flash_done(ql_adapter_state_t *ha)
111811924SDaniel.Beauregard@Sun.COM {
111911924SDaniel.Beauregard@Sun.COM 	clock_t		timer;
112011924SDaniel.Beauregard@Sun.COM 	uint32_t	status;
112111924SDaniel.Beauregard@Sun.COM 
112211924SDaniel.Beauregard@Sun.COM 	for (timer = 30 * drv_usectohz(1000000); timer; timer--) {
112311924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
112411924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
112511924SDaniel.Beauregard@Sun.COM 		    UNM_ROMUSB_ROM_RDSR_INSTR);
112611924SDaniel.Beauregard@Sun.COM 		if (ql_8021_wait_rom_done(ha)) {
112711924SDaniel.Beauregard@Sun.COM 			EL(ha, "Error waiting for rom done2\n");
112811924SDaniel.Beauregard@Sun.COM 			return (-1);
112911924SDaniel.Beauregard@Sun.COM 		}
113011924SDaniel.Beauregard@Sun.COM 
113111924SDaniel.Beauregard@Sun.COM 		/* Get status. */
113211924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, UNM_ROMUSB_ROM_RDATA, &status);
113311924SDaniel.Beauregard@Sun.COM 		if (!(status & BIT_0)) {
113411924SDaniel.Beauregard@Sun.COM 			return (0);
113511924SDaniel.Beauregard@Sun.COM 		}
113611924SDaniel.Beauregard@Sun.COM 		delay(1);
113711924SDaniel.Beauregard@Sun.COM 	}
113811924SDaniel.Beauregard@Sun.COM 
113911924SDaniel.Beauregard@Sun.COM 	EL(ha, "timeout status=%x\n", status);
114011924SDaniel.Beauregard@Sun.COM 	return (-1);
114111924SDaniel.Beauregard@Sun.COM }
114211924SDaniel.Beauregard@Sun.COM 
114311924SDaniel.Beauregard@Sun.COM static int
ql_8021_do_rom_fast_read(ql_adapter_state_t * ha,uint32_t addr,uint32_t * valp)114411924SDaniel.Beauregard@Sun.COM ql_8021_do_rom_fast_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *valp)
114511924SDaniel.Beauregard@Sun.COM {
114611924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr);
114711924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
114811924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
114911924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
115011924SDaniel.Beauregard@Sun.COM 	    UNM_ROMUSB_ROM_FAST_RD_INSTR);
115111924SDaniel.Beauregard@Sun.COM 	if (ql_8021_wait_rom_done(ha)) {
115211924SDaniel.Beauregard@Sun.COM 		EL(ha, "Error waiting for rom done\n");
115311924SDaniel.Beauregard@Sun.COM 		return (-1);
115411924SDaniel.Beauregard@Sun.COM 	}
115511924SDaniel.Beauregard@Sun.COM 	/* reset abyte_cnt and dummy_byte_cnt */
115611924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
115711924SDaniel.Beauregard@Sun.COM 	drv_usecwait(10);
115811924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
115911924SDaniel.Beauregard@Sun.COM 
116011924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, UNM_ROMUSB_ROM_RDATA, valp);
116111924SDaniel.Beauregard@Sun.COM 
116211924SDaniel.Beauregard@Sun.COM 	return (0);
116311924SDaniel.Beauregard@Sun.COM }
116411924SDaniel.Beauregard@Sun.COM 
116511924SDaniel.Beauregard@Sun.COM int
ql_8021_rom_fast_read(ql_adapter_state_t * ha,uint32_t addr,uint32_t * valp)116611924SDaniel.Beauregard@Sun.COM ql_8021_rom_fast_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *valp)
116711924SDaniel.Beauregard@Sun.COM {
116811924SDaniel.Beauregard@Sun.COM 	int	ret, loops = 0;
116911924SDaniel.Beauregard@Sun.COM 
117011924SDaniel.Beauregard@Sun.COM 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
117111924SDaniel.Beauregard@Sun.COM 		drv_usecwait(100);
117211924SDaniel.Beauregard@Sun.COM 		loops++;
117311924SDaniel.Beauregard@Sun.COM 	}
117411924SDaniel.Beauregard@Sun.COM 	if (loops >= 50000) {
117511924SDaniel.Beauregard@Sun.COM 		EL(ha, "rom_lock failed\n");
117611924SDaniel.Beauregard@Sun.COM 		return (-1);
117711924SDaniel.Beauregard@Sun.COM 	}
117811924SDaniel.Beauregard@Sun.COM 	ret = ql_8021_do_rom_fast_read(ha, addr, valp);
117911924SDaniel.Beauregard@Sun.COM 	ql_8021_rom_unlock(ha);
118011924SDaniel.Beauregard@Sun.COM 
118111924SDaniel.Beauregard@Sun.COM 	return (ret);
118211924SDaniel.Beauregard@Sun.COM }
118311924SDaniel.Beauregard@Sun.COM 
118411924SDaniel.Beauregard@Sun.COM static int
ql_8021_do_rom_write(ql_adapter_state_t * ha,uint32_t addr,uint32_t data)118511924SDaniel.Beauregard@Sun.COM ql_8021_do_rom_write(ql_adapter_state_t *ha, uint32_t addr, uint32_t data)
118611924SDaniel.Beauregard@Sun.COM {
118711924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
118811924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
118911924SDaniel.Beauregard@Sun.COM 	    UNM_ROMUSB_ROM_WREN_INSTR);
119011924SDaniel.Beauregard@Sun.COM 	if (ql_8021_wait_rom_done(ha)) {
119111924SDaniel.Beauregard@Sun.COM 		EL(ha, "Error waiting for rom done\n");
119211924SDaniel.Beauregard@Sun.COM 		return (-1);
119311924SDaniel.Beauregard@Sun.COM 	}
119411924SDaniel.Beauregard@Sun.COM 
119511924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_WDATA, data);
119611924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr);
119711924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
119811924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
119911924SDaniel.Beauregard@Sun.COM 	    UNM_ROMUSB_ROM_PP_INSTR);
120011924SDaniel.Beauregard@Sun.COM 	if (ql_8021_wait_rom_done(ha)) {
120111924SDaniel.Beauregard@Sun.COM 		EL(ha, "Error waiting for rom done1\n");
120211924SDaniel.Beauregard@Sun.COM 		return (-1);
120311924SDaniel.Beauregard@Sun.COM 	}
120411924SDaniel.Beauregard@Sun.COM 
120511924SDaniel.Beauregard@Sun.COM 	if (ql_8021_wait_flash_done(ha)) {
120611924SDaniel.Beauregard@Sun.COM 		EL(ha, "Error waiting for flash done\n");
120711924SDaniel.Beauregard@Sun.COM 		return (-1);
120811924SDaniel.Beauregard@Sun.COM 	}
120911924SDaniel.Beauregard@Sun.COM 
121011924SDaniel.Beauregard@Sun.COM 	return (0);
121111924SDaniel.Beauregard@Sun.COM }
121211924SDaniel.Beauregard@Sun.COM 
121311924SDaniel.Beauregard@Sun.COM static int
ql_8021_do_rom_erase(ql_adapter_state_t * ha,uint32_t addr)121411924SDaniel.Beauregard@Sun.COM ql_8021_do_rom_erase(ql_adapter_state_t *ha, uint32_t addr)
121511924SDaniel.Beauregard@Sun.COM {
121611924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
121711924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
121811924SDaniel.Beauregard@Sun.COM 	    UNM_ROMUSB_ROM_WREN_INSTR);
121911924SDaniel.Beauregard@Sun.COM 	if (ql_8021_wait_rom_done(ha)) {
122011924SDaniel.Beauregard@Sun.COM 		EL(ha, "Error waiting for rom done\n");
122111924SDaniel.Beauregard@Sun.COM 		return (-1);
122211924SDaniel.Beauregard@Sun.COM 	}
122311924SDaniel.Beauregard@Sun.COM 
122411924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr);
122511924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
122611924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
122711924SDaniel.Beauregard@Sun.COM 	    UNM_ROMUSB_ROM_SE_INSTR);
122811924SDaniel.Beauregard@Sun.COM 	if (ql_8021_wait_rom_done(ha)) {
122911924SDaniel.Beauregard@Sun.COM 		EL(ha, "Error waiting for rom done1\n");
123011924SDaniel.Beauregard@Sun.COM 		return (-1);
123111924SDaniel.Beauregard@Sun.COM 	}
123211924SDaniel.Beauregard@Sun.COM 
123311924SDaniel.Beauregard@Sun.COM 	if (ql_8021_wait_flash_done(ha)) {
123411924SDaniel.Beauregard@Sun.COM 		EL(ha, "Error waiting for flash done\n");
123511924SDaniel.Beauregard@Sun.COM 		return (-1);
123611924SDaniel.Beauregard@Sun.COM 	}
123711924SDaniel.Beauregard@Sun.COM 
123811924SDaniel.Beauregard@Sun.COM 	return (0);
123911924SDaniel.Beauregard@Sun.COM }
124011924SDaniel.Beauregard@Sun.COM 
124111924SDaniel.Beauregard@Sun.COM int
ql_8021_rom_read(ql_adapter_state_t * ha,uint32_t addr,uint32_t * bp)124211924SDaniel.Beauregard@Sun.COM ql_8021_rom_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *bp)
124311924SDaniel.Beauregard@Sun.COM {
124411924SDaniel.Beauregard@Sun.COM 	int	ret;
124511924SDaniel.Beauregard@Sun.COM 
124611924SDaniel.Beauregard@Sun.COM 	ret = ql_8021_rom_fast_read(ha, addr << 2, bp) == 0 ? QL_SUCCESS :
124711924SDaniel.Beauregard@Sun.COM 	    QL_FUNCTION_FAILED;
124811924SDaniel.Beauregard@Sun.COM 
124911924SDaniel.Beauregard@Sun.COM 	return (ret);
125011924SDaniel.Beauregard@Sun.COM }
125111924SDaniel.Beauregard@Sun.COM 
125211924SDaniel.Beauregard@Sun.COM int
ql_8021_rom_write(ql_adapter_state_t * ha,uint32_t addr,uint32_t data)125311924SDaniel.Beauregard@Sun.COM ql_8021_rom_write(ql_adapter_state_t *ha, uint32_t addr, uint32_t data)
125411924SDaniel.Beauregard@Sun.COM {
125511924SDaniel.Beauregard@Sun.COM 	int	ret, loops = 0;
125611924SDaniel.Beauregard@Sun.COM 
125711924SDaniel.Beauregard@Sun.COM 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
125811924SDaniel.Beauregard@Sun.COM 		drv_usecwait(100);
125911924SDaniel.Beauregard@Sun.COM 		loops++;
126011924SDaniel.Beauregard@Sun.COM 	}
126111924SDaniel.Beauregard@Sun.COM 	if (loops >= 50000) {
126211924SDaniel.Beauregard@Sun.COM 		EL(ha, "rom_lock failed\n");
126311924SDaniel.Beauregard@Sun.COM 		ret = QL_FUNCTION_TIMEOUT;
126411924SDaniel.Beauregard@Sun.COM 	} else {
126511924SDaniel.Beauregard@Sun.COM 		ret = ql_8021_do_rom_write(ha, addr << 2, data) == 0 ?
126611924SDaniel.Beauregard@Sun.COM 		    QL_SUCCESS : QL_FUNCTION_FAILED;
126711924SDaniel.Beauregard@Sun.COM 		ql_8021_rom_unlock(ha);
126811924SDaniel.Beauregard@Sun.COM 	}
126911924SDaniel.Beauregard@Sun.COM 
127011924SDaniel.Beauregard@Sun.COM 	return (ret);
127111924SDaniel.Beauregard@Sun.COM }
127211924SDaniel.Beauregard@Sun.COM 
127311924SDaniel.Beauregard@Sun.COM int
ql_8021_rom_erase(ql_adapter_state_t * ha,uint32_t addr)127411924SDaniel.Beauregard@Sun.COM ql_8021_rom_erase(ql_adapter_state_t *ha, uint32_t addr)
127511924SDaniel.Beauregard@Sun.COM {
127611924SDaniel.Beauregard@Sun.COM 	int	ret, loops = 0;
127711924SDaniel.Beauregard@Sun.COM 
127811924SDaniel.Beauregard@Sun.COM 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
127911924SDaniel.Beauregard@Sun.COM 		drv_usecwait(100);
128011924SDaniel.Beauregard@Sun.COM 		loops++;
128111924SDaniel.Beauregard@Sun.COM 	}
128211924SDaniel.Beauregard@Sun.COM 	if (loops >= 50000) {
128311924SDaniel.Beauregard@Sun.COM 		EL(ha, "rom_lock failed\n");
128411924SDaniel.Beauregard@Sun.COM 		ret = QL_FUNCTION_TIMEOUT;
128511924SDaniel.Beauregard@Sun.COM 	} else {
128611924SDaniel.Beauregard@Sun.COM 		ret = ql_8021_do_rom_erase(ha, addr << 2) == 0 ? QL_SUCCESS :
128711924SDaniel.Beauregard@Sun.COM 		    QL_FUNCTION_FAILED;
128811924SDaniel.Beauregard@Sun.COM 		ql_8021_rom_unlock(ha);
128911924SDaniel.Beauregard@Sun.COM 	}
129011924SDaniel.Beauregard@Sun.COM 
129111924SDaniel.Beauregard@Sun.COM 	return (ret);
129211924SDaniel.Beauregard@Sun.COM }
129311924SDaniel.Beauregard@Sun.COM 
129411924SDaniel.Beauregard@Sun.COM int
ql_8021_rom_wrsr(ql_adapter_state_t * ha,uint32_t data)129511924SDaniel.Beauregard@Sun.COM ql_8021_rom_wrsr(ql_adapter_state_t *ha, uint32_t data)
129611924SDaniel.Beauregard@Sun.COM {
129711924SDaniel.Beauregard@Sun.COM 	int	ret = QL_SUCCESS, loops = 0;
129811924SDaniel.Beauregard@Sun.COM 
129911924SDaniel.Beauregard@Sun.COM 	while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
130011924SDaniel.Beauregard@Sun.COM 		drv_usecwait(100);
130111924SDaniel.Beauregard@Sun.COM 		loops++;
130211924SDaniel.Beauregard@Sun.COM 	}
130311924SDaniel.Beauregard@Sun.COM 	if (loops >= 50000) {
130411924SDaniel.Beauregard@Sun.COM 		EL(ha, "rom_lock failed\n");
130511924SDaniel.Beauregard@Sun.COM 		ret = QL_FUNCTION_TIMEOUT;
130611924SDaniel.Beauregard@Sun.COM 	} else {
130711924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
130811924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
130911924SDaniel.Beauregard@Sun.COM 		    UNM_ROMUSB_ROM_WREN_INSTR);
131011924SDaniel.Beauregard@Sun.COM 		if (ql_8021_wait_rom_done(ha)) {
131111924SDaniel.Beauregard@Sun.COM 			EL(ha, "Error waiting for rom done\n");
131211924SDaniel.Beauregard@Sun.COM 			ret = QL_FUNCTION_FAILED;
131311924SDaniel.Beauregard@Sun.COM 		} else {
131411924SDaniel.Beauregard@Sun.COM 			ql_8021_wr_32(ha, UNM_ROMUSB_ROM_WDATA, data);
131511924SDaniel.Beauregard@Sun.COM 			ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
131611924SDaniel.Beauregard@Sun.COM 			ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
131711924SDaniel.Beauregard@Sun.COM 			    UNM_ROMUSB_ROM_WRSR_INSTR);
131811924SDaniel.Beauregard@Sun.COM 			if (ql_8021_wait_rom_done(ha)) {
131911924SDaniel.Beauregard@Sun.COM 				EL(ha, "Error waiting for rom done1\n");
132011924SDaniel.Beauregard@Sun.COM 				ret = QL_FUNCTION_FAILED;
132111924SDaniel.Beauregard@Sun.COM 			} else if (ql_8021_wait_flash_done(ha)) {
132211924SDaniel.Beauregard@Sun.COM 				EL(ha, "Error waiting for flash done\n");
132311924SDaniel.Beauregard@Sun.COM 				ret = QL_FUNCTION_FAILED;
132411924SDaniel.Beauregard@Sun.COM 			}
132511924SDaniel.Beauregard@Sun.COM 		}
132611924SDaniel.Beauregard@Sun.COM 		ql_8021_rom_unlock(ha);
132711924SDaniel.Beauregard@Sun.COM 	}
132811924SDaniel.Beauregard@Sun.COM 
132911924SDaniel.Beauregard@Sun.COM 	return (ret);
133011924SDaniel.Beauregard@Sun.COM }
133111924SDaniel.Beauregard@Sun.COM 
133211924SDaniel.Beauregard@Sun.COM static int
ql_8021_phantom_init(ql_adapter_state_t * ha)133311924SDaniel.Beauregard@Sun.COM ql_8021_phantom_init(ql_adapter_state_t *ha)
133411924SDaniel.Beauregard@Sun.COM {
133511924SDaniel.Beauregard@Sun.COM 	uint32_t	val = 0, err = 0;
133611924SDaniel.Beauregard@Sun.COM 	int		retries = 60;
133711924SDaniel.Beauregard@Sun.COM 
133811924SDaniel.Beauregard@Sun.COM 	do {
133911924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, CRB_CMDPEG_STATE, &val);
134011924SDaniel.Beauregard@Sun.COM 
134111924SDaniel.Beauregard@Sun.COM 		switch (val) {
134211924SDaniel.Beauregard@Sun.COM 		case PHAN_INITIALIZE_COMPLETE:
134311924SDaniel.Beauregard@Sun.COM 		case PHAN_INITIALIZE_ACK:
134411924SDaniel.Beauregard@Sun.COM 			EL(ha, "success=%xh\n", val);
134511924SDaniel.Beauregard@Sun.COM 			return (0);
134611924SDaniel.Beauregard@Sun.COM 		case PHAN_INITIALIZE_FAILED:
134711924SDaniel.Beauregard@Sun.COM 			EL(ha, "PHAN_INITIALIZE_FAILED\n");
134811924SDaniel.Beauregard@Sun.COM 			err = 1;
134911924SDaniel.Beauregard@Sun.COM 			break;
135011924SDaniel.Beauregard@Sun.COM 		default:
135111924SDaniel.Beauregard@Sun.COM 			break;
135211924SDaniel.Beauregard@Sun.COM 		}
135311924SDaniel.Beauregard@Sun.COM 
135411924SDaniel.Beauregard@Sun.COM 		if (err) {
135511924SDaniel.Beauregard@Sun.COM 			break;
135611924SDaniel.Beauregard@Sun.COM 		}
135711924SDaniel.Beauregard@Sun.COM 		/* 500 msec wait */
135811924SDaniel.Beauregard@Sun.COM 		delay(50);
135911924SDaniel.Beauregard@Sun.COM 
136011924SDaniel.Beauregard@Sun.COM 	} while (--retries);
136111924SDaniel.Beauregard@Sun.COM 
136211924SDaniel.Beauregard@Sun.COM 	if (!err) {
136311924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
136411924SDaniel.Beauregard@Sun.COM 	}
136511924SDaniel.Beauregard@Sun.COM 
136611924SDaniel.Beauregard@Sun.COM 	EL(ha, "firmware init failed=%x\n", val);
136711924SDaniel.Beauregard@Sun.COM 	return (-1);
136811924SDaniel.Beauregard@Sun.COM }
136911924SDaniel.Beauregard@Sun.COM 
137011924SDaniel.Beauregard@Sun.COM static int
ql_8021_pinit_from_rom(ql_adapter_state_t * ha)137111924SDaniel.Beauregard@Sun.COM ql_8021_pinit_from_rom(ql_adapter_state_t *ha)
137211924SDaniel.Beauregard@Sun.COM {
137311924SDaniel.Beauregard@Sun.COM 	int			init_delay = 0;
137411924SDaniel.Beauregard@Sun.COM 	struct crb_addr_pair	*buf;
137511924SDaniel.Beauregard@Sun.COM 	uint32_t		offset, off, i, n, addr, val;
137611924SDaniel.Beauregard@Sun.COM 
137711924SDaniel.Beauregard@Sun.COM 	/* Grab the lock so that no one can read flash when we reset the chip */
137811924SDaniel.Beauregard@Sun.COM 	(void) ql_8021_rom_lock(ha);
137911924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, 0xffffffff);
138011924SDaniel.Beauregard@Sun.COM 	/* Just in case it was held when we reset the chip */
138111924SDaniel.Beauregard@Sun.COM 	ql_8021_rom_unlock(ha);
138211924SDaniel.Beauregard@Sun.COM 
138311924SDaniel.Beauregard@Sun.COM 	if (ql_8021_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafe ||
138411924SDaniel.Beauregard@Sun.COM 	    ql_8021_rom_fast_read(ha, 4, &n) != 0) {
138511924SDaniel.Beauregard@Sun.COM 		EL(ha, "ERROR Reading crb_init area: n: %08x\n", n);
138611924SDaniel.Beauregard@Sun.COM 		return (-1);
138711924SDaniel.Beauregard@Sun.COM 	}
138811924SDaniel.Beauregard@Sun.COM 	offset = n & 0xffff;
138911924SDaniel.Beauregard@Sun.COM 	n = (n >> 16) & 0xffff;
139011924SDaniel.Beauregard@Sun.COM 	if (n >= 1024) {
139111924SDaniel.Beauregard@Sun.COM 		EL(ha, "n=0x%x Error! NetXen card flash not initialized\n", n);
139211924SDaniel.Beauregard@Sun.COM 		return (-1);
139311924SDaniel.Beauregard@Sun.COM 	}
139411924SDaniel.Beauregard@Sun.COM 
139511924SDaniel.Beauregard@Sun.COM 	buf = kmem_zalloc(n * sizeof (struct crb_addr_pair), KM_SLEEP);
139611924SDaniel.Beauregard@Sun.COM 	if (buf == NULL) {
139711924SDaniel.Beauregard@Sun.COM 		EL(ha, "Unable to zalloc memory\n");
139811924SDaniel.Beauregard@Sun.COM 		return (-1);
139911924SDaniel.Beauregard@Sun.COM 	}
140011924SDaniel.Beauregard@Sun.COM 
140111924SDaniel.Beauregard@Sun.COM 	for (i = 0; i < n; i++) {
140211924SDaniel.Beauregard@Sun.COM 		if (ql_8021_rom_fast_read(ha, 8 * i + 4 * offset, &val) != 0 ||
140311924SDaniel.Beauregard@Sun.COM 		    ql_8021_rom_fast_read(ha, 8 * i + 4 * offset + 4, &addr) !=
140411924SDaniel.Beauregard@Sun.COM 		    0) {
140511924SDaniel.Beauregard@Sun.COM 			kmem_free(buf, n * sizeof (struct crb_addr_pair));
140611924SDaniel.Beauregard@Sun.COM 			EL(ha, "ql_8021_rom_fast_read != 0 to zalloc memory\n");
140711924SDaniel.Beauregard@Sun.COM 			return (-1);
140811924SDaniel.Beauregard@Sun.COM 		}
140911924SDaniel.Beauregard@Sun.COM 
141011924SDaniel.Beauregard@Sun.COM 		buf[i].addr = addr;
141111924SDaniel.Beauregard@Sun.COM 		buf[i].data = val;
141211924SDaniel.Beauregard@Sun.COM 	}
141311924SDaniel.Beauregard@Sun.COM 
141411924SDaniel.Beauregard@Sun.COM 	for (i = 0; i < n; i++) {
141511924SDaniel.Beauregard@Sun.COM 		off = ql_8021_decode_crb_addr(ha, buf[i].addr);
141611924SDaniel.Beauregard@Sun.COM 		if (off == ADDR_ERROR) {
141711924SDaniel.Beauregard@Sun.COM 			EL(ha, "Err: Unknown addr: 0x%lx\n", buf[i].addr);
141811924SDaniel.Beauregard@Sun.COM 			continue;
141911924SDaniel.Beauregard@Sun.COM 		}
142011924SDaniel.Beauregard@Sun.COM 		off += UNM_PCI_CRBSPACE;
142111924SDaniel.Beauregard@Sun.COM 
142211924SDaniel.Beauregard@Sun.COM 		if (off & 1) {
142311924SDaniel.Beauregard@Sun.COM 			continue;
142411924SDaniel.Beauregard@Sun.COM 		}
142511924SDaniel.Beauregard@Sun.COM 
142611924SDaniel.Beauregard@Sun.COM 		/* skipping cold reboot MAGIC */
142711924SDaniel.Beauregard@Sun.COM 		if (off == UNM_RAM_COLD_BOOT) {
142811924SDaniel.Beauregard@Sun.COM 			continue;
142911924SDaniel.Beauregard@Sun.COM 		}
143011924SDaniel.Beauregard@Sun.COM 		if (off == (UNM_CRB_I2C0 + 0x1c)) {
143111924SDaniel.Beauregard@Sun.COM 			continue;
143211924SDaniel.Beauregard@Sun.COM 		}
143311924SDaniel.Beauregard@Sun.COM 		/* do not reset PCI */
143411924SDaniel.Beauregard@Sun.COM 		if (off == (ROMUSB_GLB + 0xbc)) {
143511924SDaniel.Beauregard@Sun.COM 			continue;
143611924SDaniel.Beauregard@Sun.COM 		}
143711924SDaniel.Beauregard@Sun.COM 		if (off == (ROMUSB_GLB + 0xa8)) {
143811924SDaniel.Beauregard@Sun.COM 			continue;
143911924SDaniel.Beauregard@Sun.COM 		}
144011924SDaniel.Beauregard@Sun.COM 		if (off == (ROMUSB_GLB + 0xc8)) {	/* core clock */
144111924SDaniel.Beauregard@Sun.COM 			continue;
144211924SDaniel.Beauregard@Sun.COM 		}
144311924SDaniel.Beauregard@Sun.COM 		if (off == (ROMUSB_GLB + 0x24)) {	/* MN clock */
144411924SDaniel.Beauregard@Sun.COM 			continue;
144511924SDaniel.Beauregard@Sun.COM 		}
144611924SDaniel.Beauregard@Sun.COM 		if (off == (ROMUSB_GLB + 0x1c)) {	/* MS clock */
144711924SDaniel.Beauregard@Sun.COM 			continue;
144811924SDaniel.Beauregard@Sun.COM 		}
144911924SDaniel.Beauregard@Sun.COM 		if ((off & 0x0ff00000) == UNM_CRB_DDR_NET) {
145011924SDaniel.Beauregard@Sun.COM 			continue;
145111924SDaniel.Beauregard@Sun.COM 		}
145211924SDaniel.Beauregard@Sun.COM 		if (off == (UNM_CRB_PEG_NET_1 + 0x18) &&
145311924SDaniel.Beauregard@Sun.COM 		    !NX_IS_REVISION_P3PLUS(ha->rev_id)) {
145411924SDaniel.Beauregard@Sun.COM 			buf[i].data = 0x1020;
145511924SDaniel.Beauregard@Sun.COM 		}
145611924SDaniel.Beauregard@Sun.COM 		/* skip the function enable register */
145711924SDaniel.Beauregard@Sun.COM 		if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION)) {
145811924SDaniel.Beauregard@Sun.COM 			continue;
145911924SDaniel.Beauregard@Sun.COM 		}
146011924SDaniel.Beauregard@Sun.COM 		if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION2)) {
146111924SDaniel.Beauregard@Sun.COM 			continue;
146211924SDaniel.Beauregard@Sun.COM 		}
146311924SDaniel.Beauregard@Sun.COM 		if ((off & 0x0ff00000) == UNM_CRB_SMB) {
146411924SDaniel.Beauregard@Sun.COM 			continue;
146511924SDaniel.Beauregard@Sun.COM 		}
146611924SDaniel.Beauregard@Sun.COM 
146711924SDaniel.Beauregard@Sun.COM 		/* After writing this register, HW needs time for CRB */
146811924SDaniel.Beauregard@Sun.COM 		/* to quiet down (else crb_window returns 0xffffffff) */
146911924SDaniel.Beauregard@Sun.COM 		init_delay = 1;
147011924SDaniel.Beauregard@Sun.COM 		if (off == UNM_ROMUSB_GLB_SW_RESET) {
147111924SDaniel.Beauregard@Sun.COM 			init_delay = 100;	/* Sleep 1000 msecs */
147211924SDaniel.Beauregard@Sun.COM 		}
147311924SDaniel.Beauregard@Sun.COM 
147411924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, off, buf[i].data);
147511924SDaniel.Beauregard@Sun.COM 
147611924SDaniel.Beauregard@Sun.COM 		delay(init_delay);
147711924SDaniel.Beauregard@Sun.COM 	}
147811924SDaniel.Beauregard@Sun.COM 	kmem_free(buf, n * sizeof (struct crb_addr_pair));
147911924SDaniel.Beauregard@Sun.COM 
148011924SDaniel.Beauregard@Sun.COM 	/* disable_peg_cache_all */
148111924SDaniel.Beauregard@Sun.COM 
148211924SDaniel.Beauregard@Sun.COM 	/* p2dn replyCount */
148311924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_D + 0xec, 0x1e);
148411924SDaniel.Beauregard@Sun.COM 	/* disable_peg_cache 0 */
148511924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_D + 0x4c, 8);
148611924SDaniel.Beauregard@Sun.COM 	/* disable_peg_cache 1 */
148711924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_I + 0x4c, 8);
148811924SDaniel.Beauregard@Sun.COM 
148911924SDaniel.Beauregard@Sun.COM 	/* peg_clr_all */
149011924SDaniel.Beauregard@Sun.COM 	/* peg_clr 0 */
149111924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0x8, 0);
149211924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0xc, 0);
149311924SDaniel.Beauregard@Sun.COM 	/* peg_clr 1 */
149411924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_1 + 0x8, 0);
149511924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_1 + 0xc, 0);
149611924SDaniel.Beauregard@Sun.COM 	/* peg_clr 2 */
149711924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_2 + 0x8, 0);
149811924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_2 + 0xc, 0);
149911924SDaniel.Beauregard@Sun.COM 	/* peg_clr 3 */
150011924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_3 + 0x8, 0);
150111924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_3 + 0xc, 0);
150211924SDaniel.Beauregard@Sun.COM 
150311924SDaniel.Beauregard@Sun.COM 	return (0);
150411924SDaniel.Beauregard@Sun.COM }
150511924SDaniel.Beauregard@Sun.COM 
150611924SDaniel.Beauregard@Sun.COM static int
ql_8021_load_from_flash(ql_adapter_state_t * ha)150711924SDaniel.Beauregard@Sun.COM ql_8021_load_from_flash(ql_adapter_state_t *ha)
150811924SDaniel.Beauregard@Sun.COM {
150911924SDaniel.Beauregard@Sun.COM 	int		i;
151011924SDaniel.Beauregard@Sun.COM 	uint32_t	flashaddr, memaddr;
151111924SDaniel.Beauregard@Sun.COM 	uint32_t	high, low, size;
151211924SDaniel.Beauregard@Sun.COM 	uint64_t	data;
151311924SDaniel.Beauregard@Sun.COM 
151411924SDaniel.Beauregard@Sun.COM 	size = ha->bootloader_size / 2;
151511924SDaniel.Beauregard@Sun.COM 	flashaddr = ha->bootloader_addr << 2;
151611924SDaniel.Beauregard@Sun.COM 	memaddr = BOOTLD_START;
151711924SDaniel.Beauregard@Sun.COM 
151811924SDaniel.Beauregard@Sun.COM 	for (i = 0; i < size; i++) {
151911924SDaniel.Beauregard@Sun.COM 		if ((ql_8021_rom_fast_read(ha, flashaddr, &low)) ||
152011924SDaniel.Beauregard@Sun.COM 		    (ql_8021_rom_fast_read(ha, flashaddr + 4, &high))) {
152111924SDaniel.Beauregard@Sun.COM 			EL(ha, "ql_8021_rom_fast_read != 0\n");
152211924SDaniel.Beauregard@Sun.COM 			return (-1);
152311924SDaniel.Beauregard@Sun.COM 		}
152411924SDaniel.Beauregard@Sun.COM 		data = ((uint64_t)high << 32) | low;
152511924SDaniel.Beauregard@Sun.COM 		(void) ql_8021_pci_mem_write_2M(ha, memaddr, &data, 8);
152611924SDaniel.Beauregard@Sun.COM 		flashaddr += 8;
152711924SDaniel.Beauregard@Sun.COM 		memaddr += 8;
152811924SDaniel.Beauregard@Sun.COM 	}
152911924SDaniel.Beauregard@Sun.COM 
153011924SDaniel.Beauregard@Sun.COM 	size = ha->flash_fw_size / 2;
153111924SDaniel.Beauregard@Sun.COM 	flashaddr = ha->flash_fw_addr << 2;
153211924SDaniel.Beauregard@Sun.COM 	memaddr = IMAGE_START;
153311924SDaniel.Beauregard@Sun.COM 
153411924SDaniel.Beauregard@Sun.COM 	for (i = 0; i < size; i++) {
153511924SDaniel.Beauregard@Sun.COM 		if ((ql_8021_rom_fast_read(ha, flashaddr, &low)) ||
153611924SDaniel.Beauregard@Sun.COM 		    (ql_8021_rom_fast_read(ha, flashaddr + 4, &high))) {
153711924SDaniel.Beauregard@Sun.COM 			EL(ha, "ql_8021_rom_fast_read3 != 0\n");
153811924SDaniel.Beauregard@Sun.COM 			return (-1);
153911924SDaniel.Beauregard@Sun.COM 		}
154011924SDaniel.Beauregard@Sun.COM 		data = ((uint64_t)high << 32) | low;
154111924SDaniel.Beauregard@Sun.COM 		(void) ql_8021_pci_mem_write_2M(ha, memaddr, &data, 8);
154211924SDaniel.Beauregard@Sun.COM 		flashaddr += 8;
154311924SDaniel.Beauregard@Sun.COM 		memaddr += 8;
154411924SDaniel.Beauregard@Sun.COM 	}
154511924SDaniel.Beauregard@Sun.COM 
154611924SDaniel.Beauregard@Sun.COM 	return (0);
154711924SDaniel.Beauregard@Sun.COM }
154811924SDaniel.Beauregard@Sun.COM 
154911924SDaniel.Beauregard@Sun.COM static int
ql_8021_load_firmware(ql_adapter_state_t * ha)155011924SDaniel.Beauregard@Sun.COM ql_8021_load_firmware(ql_adapter_state_t *ha)
155111924SDaniel.Beauregard@Sun.COM {
155211924SDaniel.Beauregard@Sun.COM 	uint64_t	data;
155311924SDaniel.Beauregard@Sun.COM 	uint32_t	i, flashaddr, size;
155411924SDaniel.Beauregard@Sun.COM 	uint8_t		*bp, n, *dp;
155511924SDaniel.Beauregard@Sun.COM 
155611924SDaniel.Beauregard@Sun.COM 	bp = (uint8_t *)(ha->risc_fw[0].code);
155711924SDaniel.Beauregard@Sun.COM 	dp = (uint8_t *)&size;
155811924SDaniel.Beauregard@Sun.COM 	for (n = 0; n < 4; n++) {
155911924SDaniel.Beauregard@Sun.COM 		dp[n] = *bp++;
156011924SDaniel.Beauregard@Sun.COM 	}
156111924SDaniel.Beauregard@Sun.COM 	LITTLE_ENDIAN_32(&size);
156211924SDaniel.Beauregard@Sun.COM 	EL(ha, "signature=%x\n", size);
156311924SDaniel.Beauregard@Sun.COM 
156411924SDaniel.Beauregard@Sun.COM 	size = (IMAGE_START - BOOTLD_START) / 8;
156511924SDaniel.Beauregard@Sun.COM 
156611924SDaniel.Beauregard@Sun.COM 	bp = (uint8_t *)(ha->risc_fw[0].code + BOOTLD_START);
156711924SDaniel.Beauregard@Sun.COM 	flashaddr = BOOTLD_START;
156811924SDaniel.Beauregard@Sun.COM 
156911924SDaniel.Beauregard@Sun.COM 	dp = (uint8_t *)&data;
157011924SDaniel.Beauregard@Sun.COM 	for (i = 0; i < size; i++) {
157111924SDaniel.Beauregard@Sun.COM 		for (n = 0; n < 8; n++) {
157211924SDaniel.Beauregard@Sun.COM 			dp[n] = *bp++;
157311924SDaniel.Beauregard@Sun.COM 		}
157411924SDaniel.Beauregard@Sun.COM 		LITTLE_ENDIAN_64(&data);
157511924SDaniel.Beauregard@Sun.COM 		(void) ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8);
157611924SDaniel.Beauregard@Sun.COM 		flashaddr += 8;
157711924SDaniel.Beauregard@Sun.COM 	}
157811924SDaniel.Beauregard@Sun.COM 
157911924SDaniel.Beauregard@Sun.COM 	bp = (uint8_t *)(ha->risc_fw[0].code + FW_SIZE_OFFSET);
158011924SDaniel.Beauregard@Sun.COM 	dp = (uint8_t *)&size;
158111924SDaniel.Beauregard@Sun.COM 	for (n = 0; n < 4; n++) {
158211924SDaniel.Beauregard@Sun.COM 		dp[n] = *bp++;
158311924SDaniel.Beauregard@Sun.COM 	}
158411924SDaniel.Beauregard@Sun.COM 	LITTLE_ENDIAN_32(&size);
158511924SDaniel.Beauregard@Sun.COM 	EL(ha, "IMAGE_START size=%llx\n", size);
158611924SDaniel.Beauregard@Sun.COM 	size = (size + 7) / 8;
158711924SDaniel.Beauregard@Sun.COM 
158811924SDaniel.Beauregard@Sun.COM 	bp = (uint8_t *)(ha->risc_fw[0].code + IMAGE_START);
158911924SDaniel.Beauregard@Sun.COM 	flashaddr = IMAGE_START;
159011924SDaniel.Beauregard@Sun.COM 
159111924SDaniel.Beauregard@Sun.COM 	dp = (uint8_t *)&data;
159211924SDaniel.Beauregard@Sun.COM 	for (i = 0; i < size; i++) {
159311924SDaniel.Beauregard@Sun.COM 		for (n = 0; n < 8; n++) {
159411924SDaniel.Beauregard@Sun.COM 			dp[n] = *bp++;
159511924SDaniel.Beauregard@Sun.COM 		}
159611924SDaniel.Beauregard@Sun.COM 		LITTLE_ENDIAN_64(&data);
159711924SDaniel.Beauregard@Sun.COM 		(void) ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8);
159811924SDaniel.Beauregard@Sun.COM 		flashaddr += 8;
159911924SDaniel.Beauregard@Sun.COM 	}
160011924SDaniel.Beauregard@Sun.COM 
160111924SDaniel.Beauregard@Sun.COM 	return (0);
160211924SDaniel.Beauregard@Sun.COM }
160311924SDaniel.Beauregard@Sun.COM 
160411924SDaniel.Beauregard@Sun.COM static int
ql_8021_init_p3p(ql_adapter_state_t * ha)160511924SDaniel.Beauregard@Sun.COM ql_8021_init_p3p(ql_adapter_state_t *ha)
160611924SDaniel.Beauregard@Sun.COM {
160711924SDaniel.Beauregard@Sun.COM 	uint32_t	data;
160811924SDaniel.Beauregard@Sun.COM 
160911924SDaniel.Beauregard@Sun.COM 	/* ??? */
161011924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_PORT_MODE_ADDR, UNM_PORT_MODE_AUTO_NEG);
161111924SDaniel.Beauregard@Sun.COM 	delay(drv_usectohz(1000000));
161211924SDaniel.Beauregard@Sun.COM 
161311924SDaniel.Beauregard@Sun.COM 	/* CAM RAM Cold Boot Register */
161411924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, UNM_RAM_COLD_BOOT, &data);
161511924SDaniel.Beauregard@Sun.COM 	if (data == 0x55555555) {
161611924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, UNM_ROMUSB_GLB_SW_RESET, &data);
161711924SDaniel.Beauregard@Sun.COM 		if (data != 0x80000f) {
161811924SDaniel.Beauregard@Sun.COM 			EL(ha, "CRB_UNM_GLB_SW_RST=%x exit\n", data);
161911924SDaniel.Beauregard@Sun.COM 			return (-1);
162011924SDaniel.Beauregard@Sun.COM 		}
162111924SDaniel.Beauregard@Sun.COM 		ql_8021_wr_32(ha, UNM_RAM_COLD_BOOT, 0);
162211924SDaniel.Beauregard@Sun.COM 	}
162311924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, UNM_ROMUSB_GLB_PEGTUNE_DONE, &data);
162411924SDaniel.Beauregard@Sun.COM 	data |= 1;
162511924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_PEGTUNE_DONE, data);
162611924SDaniel.Beauregard@Sun.COM 
162711924SDaniel.Beauregard@Sun.COM 	/*
162811924SDaniel.Beauregard@Sun.COM 	 * ???
162911924SDaniel.Beauregard@Sun.COM 	 * data = ha->pci_bus_addr | BIT_31;
163011924SDaniel.Beauregard@Sun.COM 	 * ql_8021_wr_32(ha, UNM_BUS_DEV_NO, data);
163111924SDaniel.Beauregard@Sun.COM 	 */
163211924SDaniel.Beauregard@Sun.COM 
163311924SDaniel.Beauregard@Sun.COM 	return (0);
163411924SDaniel.Beauregard@Sun.COM }
163511924SDaniel.Beauregard@Sun.COM 
163611924SDaniel.Beauregard@Sun.COM /* ARGSUSED */
163711924SDaniel.Beauregard@Sun.COM void
ql_8021_reset_chip(ql_adapter_state_t * ha)163811924SDaniel.Beauregard@Sun.COM ql_8021_reset_chip(ql_adapter_state_t *ha)
163911924SDaniel.Beauregard@Sun.COM {
1640*12279SDaniel.Beauregard@Sun.COM 	/*
1641*12279SDaniel.Beauregard@Sun.COM 	 * Disable interrupts does not work on a per function bases
1642*12279SDaniel.Beauregard@Sun.COM 	 * leave them enabled
1643*12279SDaniel.Beauregard@Sun.COM 	 */
164411924SDaniel.Beauregard@Sun.COM 	ql_8021_enable_intrs(ha);
164511924SDaniel.Beauregard@Sun.COM 
164611924SDaniel.Beauregard@Sun.COM 	ADAPTER_STATE_LOCK(ha);
164711924SDaniel.Beauregard@Sun.COM 	ha->flags |= INTERRUPTS_ENABLED;
164811924SDaniel.Beauregard@Sun.COM 	ADAPTER_STATE_UNLOCK(ha);
1649*12279SDaniel.Beauregard@Sun.COM 
1650*12279SDaniel.Beauregard@Sun.COM 	(void) ql_stop_firmware(ha);
165111924SDaniel.Beauregard@Sun.COM }
165211924SDaniel.Beauregard@Sun.COM 
165311924SDaniel.Beauregard@Sun.COM static int
ql_8021_reset_hw(ql_adapter_state_t * ha,int type)165411924SDaniel.Beauregard@Sun.COM ql_8021_reset_hw(ql_adapter_state_t *ha, int type)
165511924SDaniel.Beauregard@Sun.COM {
165611924SDaniel.Beauregard@Sun.COM 	int		ret;
165711924SDaniel.Beauregard@Sun.COM 	uint32_t	rst;
165811924SDaniel.Beauregard@Sun.COM 
165911924SDaniel.Beauregard@Sun.COM 	/* scrub dma mask expansion register */
166011924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
166111924SDaniel.Beauregard@Sun.COM 
166211924SDaniel.Beauregard@Sun.COM 	/* Overwrite stale initialization register values */
166311924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, CRB_CMDPEG_STATE, 0);
166411924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, CRB_RCVPEG_STATE, 0);
166511924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS1, 0);
166611924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS2, 0);
166711924SDaniel.Beauregard@Sun.COM 
166811924SDaniel.Beauregard@Sun.COM 	(void) ql_8021_pinit_from_rom(ha);
166911924SDaniel.Beauregard@Sun.COM 	delay(1);
167011924SDaniel.Beauregard@Sun.COM 
167111924SDaniel.Beauregard@Sun.COM 	/* Bring QM and CAMRAM out of reset */
167211924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, UNM_ROMUSB_GLB_SW_RESET, &rst);
167311924SDaniel.Beauregard@Sun.COM 	rst &= ~((1 << 28) | (1 << 24));
167411924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, rst);
167511924SDaniel.Beauregard@Sun.COM 
167611924SDaniel.Beauregard@Sun.COM 	switch (type) {
167711924SDaniel.Beauregard@Sun.COM 	case 0:
167811924SDaniel.Beauregard@Sun.COM 		ret = ql_8021_init_p3p(ha);
167911924SDaniel.Beauregard@Sun.COM 		break;
168011924SDaniel.Beauregard@Sun.COM 	case 1:
168111924SDaniel.Beauregard@Sun.COM 		ret = ql_8021_load_from_flash(ha);
168211924SDaniel.Beauregard@Sun.COM 		break;
168311924SDaniel.Beauregard@Sun.COM 	case 2:
168411924SDaniel.Beauregard@Sun.COM 		ret = ql_8021_load_firmware(ha);
168511924SDaniel.Beauregard@Sun.COM 		break;
168611924SDaniel.Beauregard@Sun.COM 	}
168711924SDaniel.Beauregard@Sun.COM 	delay(1);
168811924SDaniel.Beauregard@Sun.COM 
168911924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0x18, 0x1020);
169011924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, 0x80001e);
169111924SDaniel.Beauregard@Sun.COM 
169211924SDaniel.Beauregard@Sun.COM 	if (ret) {
169311924SDaniel.Beauregard@Sun.COM 		EL(ha, "type=%d, ret=%d\n", type, ret);
169411924SDaniel.Beauregard@Sun.COM 	} else {
169511924SDaniel.Beauregard@Sun.COM 		ret = ql_8021_phantom_init(ha);
169611924SDaniel.Beauregard@Sun.COM 	}
169711924SDaniel.Beauregard@Sun.COM 	return (ret);
169811924SDaniel.Beauregard@Sun.COM }
169911924SDaniel.Beauregard@Sun.COM 
170011924SDaniel.Beauregard@Sun.COM int
ql_8021_load_risc(ql_adapter_state_t * ha)170111924SDaniel.Beauregard@Sun.COM ql_8021_load_risc(ql_adapter_state_t *ha)
170211924SDaniel.Beauregard@Sun.COM {
170311924SDaniel.Beauregard@Sun.COM 	int		rv = 0;
170411924SDaniel.Beauregard@Sun.COM 	static int	ql_8021_fw_loaded = 0;
170511924SDaniel.Beauregard@Sun.COM 
170611924SDaniel.Beauregard@Sun.COM 	GLOBAL_HW_LOCK();
170711924SDaniel.Beauregard@Sun.COM 	if (!ql_8021_fw_loaded) {
170811924SDaniel.Beauregard@Sun.COM 		if (ha->risc_fw[0].code) {
170911924SDaniel.Beauregard@Sun.COM 			EL(ha, "from driver\n");
171011924SDaniel.Beauregard@Sun.COM 			rv = ql_8021_reset_hw(ha, 2);
171111924SDaniel.Beauregard@Sun.COM 		} else {
171211924SDaniel.Beauregard@Sun.COM 			/*
171311924SDaniel.Beauregard@Sun.COM 			 * BIOS method
171411924SDaniel.Beauregard@Sun.COM 			 * ql_8021_reset_hw(ha, 0)
171511924SDaniel.Beauregard@Sun.COM 			 */
171611924SDaniel.Beauregard@Sun.COM 			EL(ha, "from flash\n");
171711924SDaniel.Beauregard@Sun.COM 			rv = ql_8021_reset_hw(ha, 1);
171811924SDaniel.Beauregard@Sun.COM 		}
171911924SDaniel.Beauregard@Sun.COM 		if (rv == 0) {
172011924SDaniel.Beauregard@Sun.COM 			ql_8021_fw_loaded = 1;
172111924SDaniel.Beauregard@Sun.COM 
172211924SDaniel.Beauregard@Sun.COM 			ql_8021_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
172311924SDaniel.Beauregard@Sun.COM 			ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS1, 0x0);
172411924SDaniel.Beauregard@Sun.COM 			ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS2, 0x0);
172511924SDaniel.Beauregard@Sun.COM 
172611924SDaniel.Beauregard@Sun.COM 			GLOBAL_HW_UNLOCK();
172711924SDaniel.Beauregard@Sun.COM 
172811924SDaniel.Beauregard@Sun.COM 			ADAPTER_STATE_LOCK(ha);
172911924SDaniel.Beauregard@Sun.COM 			ha->flags &= ~INTERRUPTS_ENABLED;
173011924SDaniel.Beauregard@Sun.COM 			ADAPTER_STATE_UNLOCK(ha);
173111924SDaniel.Beauregard@Sun.COM 
173211924SDaniel.Beauregard@Sun.COM 			(void) ql_8021_enable_intrs(ha);
173311924SDaniel.Beauregard@Sun.COM 
173411924SDaniel.Beauregard@Sun.COM 			ADAPTER_STATE_LOCK(ha);
173511924SDaniel.Beauregard@Sun.COM 			ha->flags |= INTERRUPTS_ENABLED;
173611924SDaniel.Beauregard@Sun.COM 			ADAPTER_STATE_UNLOCK(ha);
173711924SDaniel.Beauregard@Sun.COM 		} else {
173811924SDaniel.Beauregard@Sun.COM 			GLOBAL_HW_UNLOCK();
173911924SDaniel.Beauregard@Sun.COM 		}
174011924SDaniel.Beauregard@Sun.COM 	} else {
174111924SDaniel.Beauregard@Sun.COM 		GLOBAL_HW_UNLOCK();
174211924SDaniel.Beauregard@Sun.COM 		EL(ha, "Firmware loaded by other function\n");
174311924SDaniel.Beauregard@Sun.COM 	}
174411924SDaniel.Beauregard@Sun.COM 
174511924SDaniel.Beauregard@Sun.COM 	if (rv == 0) {
174611924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, UNM_FW_VERSION_MAJOR, &ha->fw_major_version);
174711924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, UNM_FW_VERSION_MINOR, &ha->fw_minor_version);
174811924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, UNM_FW_VERSION_SUB, &ha->fw_subminor_version);
174911924SDaniel.Beauregard@Sun.COM 		EL(ha, "fw v%d.%02d.%02d\n", ha->fw_major_version,
175011924SDaniel.Beauregard@Sun.COM 		    ha->fw_minor_version, ha->fw_subminor_version);
175111924SDaniel.Beauregard@Sun.COM 	} else {
175211924SDaniel.Beauregard@Sun.COM 		EL(ha, "status = -1\n");
175311924SDaniel.Beauregard@Sun.COM 		return (QL_FUNCTION_FAILED);
175411924SDaniel.Beauregard@Sun.COM 	}
175511924SDaniel.Beauregard@Sun.COM 
175611924SDaniel.Beauregard@Sun.COM 	return (QL_SUCCESS);
175711924SDaniel.Beauregard@Sun.COM }
175811924SDaniel.Beauregard@Sun.COM 
175911924SDaniel.Beauregard@Sun.COM void
ql_8021_clr_hw_intr(ql_adapter_state_t * ha)176011924SDaniel.Beauregard@Sun.COM ql_8021_clr_hw_intr(ql_adapter_state_t *ha)
176111924SDaniel.Beauregard@Sun.COM {
176211924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff);
176311924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, ISR_INT_VECTOR, NULL);
176411924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, ISR_INT_VECTOR, NULL);
176511924SDaniel.Beauregard@Sun.COM }
176611924SDaniel.Beauregard@Sun.COM 
176711924SDaniel.Beauregard@Sun.COM void
ql_8021_clr_fw_intr(ql_adapter_state_t * ha)176811924SDaniel.Beauregard@Sun.COM ql_8021_clr_fw_intr(ql_adapter_state_t *ha)
176911924SDaniel.Beauregard@Sun.COM {
177011924SDaniel.Beauregard@Sun.COM 	WRT32_IO_REG(ha, nx_risc_int, 0);
177111924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xfbff);
177211924SDaniel.Beauregard@Sun.COM }
177311924SDaniel.Beauregard@Sun.COM 
177411924SDaniel.Beauregard@Sun.COM void
ql_8021_enable_intrs(ql_adapter_state_t * ha)177511924SDaniel.Beauregard@Sun.COM ql_8021_enable_intrs(ql_adapter_state_t *ha)
177611924SDaniel.Beauregard@Sun.COM {
177711924SDaniel.Beauregard@Sun.COM 	GLOBAL_HW_LOCK();
177811924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff);
177911924SDaniel.Beauregard@Sun.COM 	GLOBAL_HW_UNLOCK();
178011924SDaniel.Beauregard@Sun.COM 	(void) ql_toggle_interrupt(ha, 1);
178111924SDaniel.Beauregard@Sun.COM }
178211924SDaniel.Beauregard@Sun.COM 
178311924SDaniel.Beauregard@Sun.COM void
ql_8021_disable_intrs(ql_adapter_state_t * ha)178411924SDaniel.Beauregard@Sun.COM ql_8021_disable_intrs(ql_adapter_state_t *ha)
178511924SDaniel.Beauregard@Sun.COM {
178611924SDaniel.Beauregard@Sun.COM 	(void) ql_toggle_interrupt(ha, 0);
178711924SDaniel.Beauregard@Sun.COM 	GLOBAL_HW_LOCK();
178811924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400);
178911924SDaniel.Beauregard@Sun.COM 	GLOBAL_HW_UNLOCK();
179011924SDaniel.Beauregard@Sun.COM }
179111924SDaniel.Beauregard@Sun.COM 
179211924SDaniel.Beauregard@Sun.COM void
ql_8021_update_crb_int_ptr(ql_adapter_state_t * ha)179311924SDaniel.Beauregard@Sun.COM ql_8021_update_crb_int_ptr(ql_adapter_state_t *ha)
179411924SDaniel.Beauregard@Sun.COM {
179511924SDaniel.Beauregard@Sun.COM 	struct legacy_intr_set	*nx_legacy_intr;
179611924SDaniel.Beauregard@Sun.COM 
179711924SDaniel.Beauregard@Sun.COM 	ha->qdr_sn_window = (uint32_t)-1;
179811924SDaniel.Beauregard@Sun.COM 	ha->ddr_mn_window = (uint32_t)-1;
179911924SDaniel.Beauregard@Sun.COM 	nx_legacy_intr = &legacy_intr[ha->function_number];
180011924SDaniel.Beauregard@Sun.COM 
180111924SDaniel.Beauregard@Sun.COM 	ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit;
180211924SDaniel.Beauregard@Sun.COM 	ha->nx_legacy_intr.tgt_status_reg = nx_legacy_intr->tgt_status_reg;
180311924SDaniel.Beauregard@Sun.COM 	ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg;
180411924SDaniel.Beauregard@Sun.COM 	ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
180511924SDaniel.Beauregard@Sun.COM }
180611924SDaniel.Beauregard@Sun.COM 
180711924SDaniel.Beauregard@Sun.COM void
ql_8021_set_drv_active(ql_adapter_state_t * ha)180811924SDaniel.Beauregard@Sun.COM ql_8021_set_drv_active(ql_adapter_state_t *ha)
180911924SDaniel.Beauregard@Sun.COM {
181011924SDaniel.Beauregard@Sun.COM 	uint32_t	val;
181111924SDaniel.Beauregard@Sun.COM 
181211924SDaniel.Beauregard@Sun.COM 	if (ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT)) {
181311924SDaniel.Beauregard@Sun.COM 		return;
181411924SDaniel.Beauregard@Sun.COM 	}
181511924SDaniel.Beauregard@Sun.COM 
181611924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &val);
181711924SDaniel.Beauregard@Sun.COM 	if (val == 0xffffffff) {
181811924SDaniel.Beauregard@Sun.COM 		val = (1 << (ha->function_number * 4));
181911924SDaniel.Beauregard@Sun.COM 	} else {
182011924SDaniel.Beauregard@Sun.COM 		val |= (1 << (ha->function_number * 4));
182111924SDaniel.Beauregard@Sun.COM 	}
182211924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, CRB_DRV_ACTIVE, val);
182311924SDaniel.Beauregard@Sun.COM 
182411924SDaniel.Beauregard@Sun.COM 	ql_8021_hw_unlock(ha);
182511924SDaniel.Beauregard@Sun.COM }
182611924SDaniel.Beauregard@Sun.COM 
182711924SDaniel.Beauregard@Sun.COM void
ql_8021_clr_drv_active(ql_adapter_state_t * ha)182811924SDaniel.Beauregard@Sun.COM ql_8021_clr_drv_active(ql_adapter_state_t *ha)
182911924SDaniel.Beauregard@Sun.COM {
183011924SDaniel.Beauregard@Sun.COM 	uint32_t	val;
183111924SDaniel.Beauregard@Sun.COM 
183211924SDaniel.Beauregard@Sun.COM 	if (ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT)) {
183311924SDaniel.Beauregard@Sun.COM 		return;
183411924SDaniel.Beauregard@Sun.COM 	}
183511924SDaniel.Beauregard@Sun.COM 
183611924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &val);
183711924SDaniel.Beauregard@Sun.COM 	val &= ~(1 << (ha->function_number * 4));
183811924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, CRB_DRV_ACTIVE, val);
183911924SDaniel.Beauregard@Sun.COM 
184011924SDaniel.Beauregard@Sun.COM 	ql_8021_hw_unlock(ha);
184111924SDaniel.Beauregard@Sun.COM }
184211924SDaniel.Beauregard@Sun.COM 
184311924SDaniel.Beauregard@Sun.COM static void
ql_8021_need_reset_handler(ql_adapter_state_t * ha)184411924SDaniel.Beauregard@Sun.COM ql_8021_need_reset_handler(ql_adapter_state_t *ha)
184511924SDaniel.Beauregard@Sun.COM {
184611924SDaniel.Beauregard@Sun.COM 	uint32_t	drv_state, drv_active;
184711924SDaniel.Beauregard@Sun.COM 	clock_t		timer;
184811924SDaniel.Beauregard@Sun.COM 
184911924SDaniel.Beauregard@Sun.COM 	(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
185011924SDaniel.Beauregard@Sun.COM 
185111924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
185211924SDaniel.Beauregard@Sun.COM 	drv_state |= (1 << (ha->function_number * 4));
185311924SDaniel.Beauregard@Sun.COM 	ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
185411924SDaniel.Beauregard@Sun.COM 
185511924SDaniel.Beauregard@Sun.COM 	ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &drv_active);
185611924SDaniel.Beauregard@Sun.COM 
185711924SDaniel.Beauregard@Sun.COM 	ql_8021_hw_unlock(ha);
185811924SDaniel.Beauregard@Sun.COM 
185911924SDaniel.Beauregard@Sun.COM 	for (timer = 30; timer && drv_state != drv_active; timer--) {
186011924SDaniel.Beauregard@Sun.COM 		delay(100);
186111924SDaniel.Beauregard@Sun.COM 
186211924SDaniel.Beauregard@Sun.COM 		(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
186311924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
186411924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &drv_active);
186511924SDaniel.Beauregard@Sun.COM 		ql_8021_hw_unlock(ha);
186611924SDaniel.Beauregard@Sun.COM 	}
186711924SDaniel.Beauregard@Sun.COM }
186811924SDaniel.Beauregard@Sun.COM 
186911924SDaniel.Beauregard@Sun.COM uint32_t
ql_8021_idc_handler(ql_adapter_state_t * ha)187011924SDaniel.Beauregard@Sun.COM ql_8021_idc_handler(ql_adapter_state_t *ha)
187111924SDaniel.Beauregard@Sun.COM {
187211924SDaniel.Beauregard@Sun.COM 	uint32_t	dev_state, drv_state, rval;
187311924SDaniel.Beauregard@Sun.COM 	clock_t		timer;
187411924SDaniel.Beauregard@Sun.COM 	ql_mbx_data_t	mr;
187511924SDaniel.Beauregard@Sun.COM 	boolean_t	stalled = B_FALSE, lock = B_FALSE;
187611924SDaniel.Beauregard@Sun.COM 
187711924SDaniel.Beauregard@Sun.COM 	/* wait for 30 seconds for device to go ready */
187811924SDaniel.Beauregard@Sun.COM 	timer = 30;
187911924SDaniel.Beauregard@Sun.COM 	while (timer) {
188011924SDaniel.Beauregard@Sun.COM 		if (lock == B_FALSE) {
188111924SDaniel.Beauregard@Sun.COM 			(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
188211924SDaniel.Beauregard@Sun.COM 			lock = B_TRUE;
188311924SDaniel.Beauregard@Sun.COM 		}
188411924SDaniel.Beauregard@Sun.COM 		ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state);
188511924SDaniel.Beauregard@Sun.COM 
188611924SDaniel.Beauregard@Sun.COM 		switch (dev_state) {
188711924SDaniel.Beauregard@Sun.COM 		case 0xffffffff:
188811924SDaniel.Beauregard@Sun.COM 		case NX_DEV_COLD:
188911924SDaniel.Beauregard@Sun.COM 			EL(ha, "dev_state=NX_DEV_COLD\n");
189011924SDaniel.Beauregard@Sun.COM 			rval = NX_DEV_COLD;
189111924SDaniel.Beauregard@Sun.COM 			ql_8021_wr_32(ha, CRB_DEV_STATE, NX_DEV_INITIALIZING);
189211924SDaniel.Beauregard@Sun.COM 			ql_8021_wr_32(ha, CRB_DRV_IDC_VERSION, NX_IDC_VERSION);
189311924SDaniel.Beauregard@Sun.COM 			(void) ql_8021_hw_unlock(ha);
189411924SDaniel.Beauregard@Sun.COM 			if (ql_get_fw_version(ha, &mr, 2) == QL_SUCCESS &&
189511924SDaniel.Beauregard@Sun.COM 			    (mr.mb[1] | mr.mb[2] | mr.mb[3])) {
189611924SDaniel.Beauregard@Sun.COM 				ql_8021_rd_32(ha, UNM_FW_VERSION_MAJOR,
189711924SDaniel.Beauregard@Sun.COM 				    &ha->fw_major_version);
189811924SDaniel.Beauregard@Sun.COM 				ql_8021_rd_32(ha, UNM_FW_VERSION_MINOR,
189911924SDaniel.Beauregard@Sun.COM 				    &ha->fw_minor_version);
190011924SDaniel.Beauregard@Sun.COM 				ql_8021_rd_32(ha, UNM_FW_VERSION_SUB,
190111924SDaniel.Beauregard@Sun.COM 				    &ha->fw_subminor_version);
190211924SDaniel.Beauregard@Sun.COM 				rval = NX_DEV_READY;
190311924SDaniel.Beauregard@Sun.COM 			} else if (ql_8021_load_risc(ha) == QL_SUCCESS) {
190411924SDaniel.Beauregard@Sun.COM 				rval = NX_DEV_READY;
190511924SDaniel.Beauregard@Sun.COM 			}
190611924SDaniel.Beauregard@Sun.COM 			(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
190711924SDaniel.Beauregard@Sun.COM 			ql_8021_wr_32(ha, CRB_DEV_STATE, rval);
190811924SDaniel.Beauregard@Sun.COM 			break;
190911924SDaniel.Beauregard@Sun.COM 		case NX_DEV_READY:
191011924SDaniel.Beauregard@Sun.COM 			rval = NX_DEV_READY;
191111924SDaniel.Beauregard@Sun.COM 			timer = 0;
191211924SDaniel.Beauregard@Sun.COM 			break;
191311924SDaniel.Beauregard@Sun.COM 		case NX_DEV_FAILED:
191411924SDaniel.Beauregard@Sun.COM 			EL(ha, "dev_state=NX_DEV_FAILED\n");
191511924SDaniel.Beauregard@Sun.COM 			rval = NX_DEV_FAILED;
191611924SDaniel.Beauregard@Sun.COM 			timer = 0;
191711924SDaniel.Beauregard@Sun.COM 			break;
191811924SDaniel.Beauregard@Sun.COM 
191911924SDaniel.Beauregard@Sun.COM 		case NX_DEV_NEED_RESET:
192011924SDaniel.Beauregard@Sun.COM 			EL(ha, "dev_state=NX_DEV_NEED_RESET\n");
192111924SDaniel.Beauregard@Sun.COM 			rval = NX_DEV_NEED_RESET;
192211924SDaniel.Beauregard@Sun.COM 			(void) ql_8021_hw_unlock(ha);
192311924SDaniel.Beauregard@Sun.COM 			lock = B_FALSE;
192411924SDaniel.Beauregard@Sun.COM 			if (ql_stall_driver(ha, 0) == QL_SUCCESS) {
192511924SDaniel.Beauregard@Sun.COM 				stalled = B_TRUE;
192611924SDaniel.Beauregard@Sun.COM 				ql_8021_need_reset_handler(ha);
192711924SDaniel.Beauregard@Sun.COM 			}
192811924SDaniel.Beauregard@Sun.COM 			break;
192911924SDaniel.Beauregard@Sun.COM 
193011924SDaniel.Beauregard@Sun.COM 		case NX_DEV_NEED_QUIESCENT:
193111924SDaniel.Beauregard@Sun.COM 			EL(ha, "dev_state=NX_DEV_NEED_QUIESCENT\n");
193211924SDaniel.Beauregard@Sun.COM 			(void) ql_8021_hw_unlock(ha);
193311924SDaniel.Beauregard@Sun.COM 			lock = B_FALSE;
193411924SDaniel.Beauregard@Sun.COM 			rval = ql_stall_driver(ha, 0);
193511924SDaniel.Beauregard@Sun.COM 			if (rval == QL_SUCCESS) {
193611924SDaniel.Beauregard@Sun.COM 				stalled = B_TRUE;
193711924SDaniel.Beauregard@Sun.COM 				(void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
193811924SDaniel.Beauregard@Sun.COM 				lock = B_TRUE;
193911924SDaniel.Beauregard@Sun.COM 				ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
194011924SDaniel.Beauregard@Sun.COM 				drv_state |=
194111924SDaniel.Beauregard@Sun.COM 				    (2 << (ha->function_number * 4));
194211924SDaniel.Beauregard@Sun.COM 				ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
194311924SDaniel.Beauregard@Sun.COM 			}
194411924SDaniel.Beauregard@Sun.COM 			break;
194511924SDaniel.Beauregard@Sun.COM 
194611924SDaniel.Beauregard@Sun.COM 		case NX_DEV_INITIALIZING:
194711924SDaniel.Beauregard@Sun.COM 			EL(ha, "dev_state=NX_DEV_INITIALIZING\n");
194811924SDaniel.Beauregard@Sun.COM 			break;
194911924SDaniel.Beauregard@Sun.COM 		case NX_DEV_QUIESCENT:
195011924SDaniel.Beauregard@Sun.COM 			EL(ha, "dev_state=NX_DEV_QUIESCENT\n");
195111924SDaniel.Beauregard@Sun.COM 			break;
195211924SDaniel.Beauregard@Sun.COM 		default:
195311924SDaniel.Beauregard@Sun.COM 			EL(ha, "dev_state=%x, default\n", dev_state);
195411924SDaniel.Beauregard@Sun.COM 			break;
195511924SDaniel.Beauregard@Sun.COM 		}
195611924SDaniel.Beauregard@Sun.COM 		if (lock == B_TRUE) {
195711924SDaniel.Beauregard@Sun.COM 			(void) ql_8021_hw_unlock(ha);
195811924SDaniel.Beauregard@Sun.COM 			lock = B_FALSE;
195911924SDaniel.Beauregard@Sun.COM 		}
196011924SDaniel.Beauregard@Sun.COM 
196111924SDaniel.Beauregard@Sun.COM 		if (timer) {
196211924SDaniel.Beauregard@Sun.COM 			delay(100);
196311924SDaniel.Beauregard@Sun.COM 			timer--;
196411924SDaniel.Beauregard@Sun.COM 		}
196511924SDaniel.Beauregard@Sun.COM 	}
196611924SDaniel.Beauregard@Sun.COM 
196711924SDaniel.Beauregard@Sun.COM 	if (stalled) {
196811924SDaniel.Beauregard@Sun.COM 		ql_restart_driver(ha);
196911924SDaniel.Beauregard@Sun.COM 	}
197011924SDaniel.Beauregard@Sun.COM 	return (rval);
197111924SDaniel.Beauregard@Sun.COM }
1972