xref: /onnv-gate/usr/src/uts/common/io/ntxn/unm_nic_init.c (revision 8687:5dca9cd6354a)
17956Sxiuyan.wang@Sun.COM /*
27956Sxiuyan.wang@Sun.COM  * CDDL HEADER START
37956Sxiuyan.wang@Sun.COM  *
47956Sxiuyan.wang@Sun.COM  * The contents of this file are subject to the terms of the
57956Sxiuyan.wang@Sun.COM  * Common Development and Distribution License (the "License").
67956Sxiuyan.wang@Sun.COM  * You may not use this file except in compliance with the License.
77956Sxiuyan.wang@Sun.COM  *
87956Sxiuyan.wang@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97956Sxiuyan.wang@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107956Sxiuyan.wang@Sun.COM  * See the License for the specific language governing permissions
117956Sxiuyan.wang@Sun.COM  * and limitations under the License.
127956Sxiuyan.wang@Sun.COM  *
137956Sxiuyan.wang@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147956Sxiuyan.wang@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157956Sxiuyan.wang@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167956Sxiuyan.wang@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177956Sxiuyan.wang@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187956Sxiuyan.wang@Sun.COM  *
197956Sxiuyan.wang@Sun.COM  * CDDL HEADER END
207956Sxiuyan.wang@Sun.COM  */
21*8687SJing.Xiong@Sun.COM 
227956Sxiuyan.wang@Sun.COM /*
237956Sxiuyan.wang@Sun.COM  * Copyright 2008 NetXen, Inc.  All rights reserved.
247956Sxiuyan.wang@Sun.COM  * Use is subject to license terms.
257956Sxiuyan.wang@Sun.COM  */
26*8687SJing.Xiong@Sun.COM 
277956Sxiuyan.wang@Sun.COM #include <sys/types.h>
287956Sxiuyan.wang@Sun.COM #include <sys/conf.h>
297956Sxiuyan.wang@Sun.COM #include <sys/debug.h>
307956Sxiuyan.wang@Sun.COM #include <sys/stropts.h>
317956Sxiuyan.wang@Sun.COM #include <sys/stream.h>
327956Sxiuyan.wang@Sun.COM #include <sys/strlog.h>
337956Sxiuyan.wang@Sun.COM #include <sys/kmem.h>
347956Sxiuyan.wang@Sun.COM #include <sys/stat.h>
357956Sxiuyan.wang@Sun.COM #include <sys/kstat.h>
367956Sxiuyan.wang@Sun.COM #include <sys/vtrace.h>
377956Sxiuyan.wang@Sun.COM #include <sys/dlpi.h>
387956Sxiuyan.wang@Sun.COM #include <sys/strsun.h>
397956Sxiuyan.wang@Sun.COM #include <sys/ethernet.h>
407956Sxiuyan.wang@Sun.COM #include <sys/modctl.h>
417956Sxiuyan.wang@Sun.COM #include <sys/errno.h>
427956Sxiuyan.wang@Sun.COM #include <sys/dditypes.h>
437956Sxiuyan.wang@Sun.COM #include <sys/ddi.h>
447956Sxiuyan.wang@Sun.COM #include <sys/sunddi.h>
457956Sxiuyan.wang@Sun.COM #include <sys/sysmacros.h>
467956Sxiuyan.wang@Sun.COM #include <sys/pci.h>
477956Sxiuyan.wang@Sun.COM 
487956Sxiuyan.wang@Sun.COM #include "unm_nic.h"
497956Sxiuyan.wang@Sun.COM #include "unm_nic_hw.h"
507956Sxiuyan.wang@Sun.COM #include "nic_cmn.h"
517956Sxiuyan.wang@Sun.COM #include "unm_nic_ioctl.h"
527956Sxiuyan.wang@Sun.COM #include "nic_phan_reg.h"
537956Sxiuyan.wang@Sun.COM 
547956Sxiuyan.wang@Sun.COM struct crb_addr_pair {
557956Sxiuyan.wang@Sun.COM 	long	addr, data;
567956Sxiuyan.wang@Sun.COM };
577956Sxiuyan.wang@Sun.COM 
587956Sxiuyan.wang@Sun.COM #define	MAX_CRB_XFORM	60
597956Sxiuyan.wang@Sun.COM #define	ADDR_ERROR	((unsigned long)0xffffffff)
607956Sxiuyan.wang@Sun.COM 
617956Sxiuyan.wang@Sun.COM #define	crb_addr_transform(name)				\
627956Sxiuyan.wang@Sun.COM 		crb_addr_xform[UNM_HW_PX_MAP_CRB_##name] =		\
637956Sxiuyan.wang@Sun.COM 		UNM_HW_CRB_HUB_AGT_ADR_##name << 20
647956Sxiuyan.wang@Sun.COM 
657956Sxiuyan.wang@Sun.COM static unsigned int crb_addr_xform[MAX_CRB_XFORM];
667956Sxiuyan.wang@Sun.COM 
677956Sxiuyan.wang@Sun.COM static void
crb_addr_transform_setup(void)687956Sxiuyan.wang@Sun.COM crb_addr_transform_setup(void)
697956Sxiuyan.wang@Sun.COM {
707956Sxiuyan.wang@Sun.COM 		crb_addr_transform(XDMA);
717956Sxiuyan.wang@Sun.COM 		crb_addr_transform(TIMR);
727956Sxiuyan.wang@Sun.COM 		crb_addr_transform(SRE);
737956Sxiuyan.wang@Sun.COM 		crb_addr_transform(SQN3);
747956Sxiuyan.wang@Sun.COM 		crb_addr_transform(SQN2);
757956Sxiuyan.wang@Sun.COM 		crb_addr_transform(SQN1);
767956Sxiuyan.wang@Sun.COM 		crb_addr_transform(SQN0);
777956Sxiuyan.wang@Sun.COM 		crb_addr_transform(SQS3);
787956Sxiuyan.wang@Sun.COM 		crb_addr_transform(SQS2);
797956Sxiuyan.wang@Sun.COM 		crb_addr_transform(SQS1);
807956Sxiuyan.wang@Sun.COM 		crb_addr_transform(SQS0);
817956Sxiuyan.wang@Sun.COM 		crb_addr_transform(RPMX7);
827956Sxiuyan.wang@Sun.COM 		crb_addr_transform(RPMX6);
837956Sxiuyan.wang@Sun.COM 		crb_addr_transform(RPMX5);
847956Sxiuyan.wang@Sun.COM 		crb_addr_transform(RPMX4);
857956Sxiuyan.wang@Sun.COM 		crb_addr_transform(RPMX3);
867956Sxiuyan.wang@Sun.COM 		crb_addr_transform(RPMX2);
877956Sxiuyan.wang@Sun.COM 		crb_addr_transform(RPMX1);
887956Sxiuyan.wang@Sun.COM 		crb_addr_transform(RPMX0);
897956Sxiuyan.wang@Sun.COM 		crb_addr_transform(ROMUSB);
907956Sxiuyan.wang@Sun.COM 		crb_addr_transform(SN);
917956Sxiuyan.wang@Sun.COM 		crb_addr_transform(QMN);
927956Sxiuyan.wang@Sun.COM 		crb_addr_transform(QMS);
937956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGNI);
947956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGND);
957956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGN3);
967956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGN2);
977956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGN1);
987956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGN0);
997956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGSI);
1007956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGSD);
1017956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGS3);
1027956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGS2);
1037956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGS1);
1047956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PGS0);
1057956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PS);
1067956Sxiuyan.wang@Sun.COM 		crb_addr_transform(PH);
1077956Sxiuyan.wang@Sun.COM 		crb_addr_transform(NIU);
1087956Sxiuyan.wang@Sun.COM 		crb_addr_transform(I2Q);
1097956Sxiuyan.wang@Sun.COM 		crb_addr_transform(EG);
1107956Sxiuyan.wang@Sun.COM 		crb_addr_transform(MN);
1117956Sxiuyan.wang@Sun.COM 		crb_addr_transform(MS);
1127956Sxiuyan.wang@Sun.COM 		crb_addr_transform(CAS2);
1137956Sxiuyan.wang@Sun.COM 		crb_addr_transform(CAS1);
1147956Sxiuyan.wang@Sun.COM 		crb_addr_transform(CAS0);
1157956Sxiuyan.wang@Sun.COM 		crb_addr_transform(CAM);
1167956Sxiuyan.wang@Sun.COM 		crb_addr_transform(C2C1);
1177956Sxiuyan.wang@Sun.COM 		crb_addr_transform(C2C0);
1187956Sxiuyan.wang@Sun.COM 		crb_addr_transform(SMB);
1197956Sxiuyan.wang@Sun.COM 		crb_addr_transform(OCM0);
1207956Sxiuyan.wang@Sun.COM 
1217956Sxiuyan.wang@Sun.COM 	/*
1227956Sxiuyan.wang@Sun.COM 	 * Used only in P3 just define it for P2 also.
1237956Sxiuyan.wang@Sun.COM 	 */
1247956Sxiuyan.wang@Sun.COM 	crb_addr_transform(I2C0);
1257956Sxiuyan.wang@Sun.COM }
1267956Sxiuyan.wang@Sun.COM 
1277956Sxiuyan.wang@Sun.COM /*
1287956Sxiuyan.wang@Sun.COM  * decode_crb_addr(0 - utility to translate from internal Phantom CRB address
1297956Sxiuyan.wang@Sun.COM  * to external PCI CRB address.
1307956Sxiuyan.wang@Sun.COM  */
1317956Sxiuyan.wang@Sun.COM static unsigned long
decode_crb_addr(unsigned long addr)1327956Sxiuyan.wang@Sun.COM decode_crb_addr(unsigned long addr)
1337956Sxiuyan.wang@Sun.COM {
1347956Sxiuyan.wang@Sun.COM 	int i;
1357956Sxiuyan.wang@Sun.COM 	unsigned long base_addr, offset, pci_base;
1367956Sxiuyan.wang@Sun.COM 
1377956Sxiuyan.wang@Sun.COM 	crb_addr_transform_setup();
1387956Sxiuyan.wang@Sun.COM 
1397956Sxiuyan.wang@Sun.COM 	pci_base = ADDR_ERROR;
1407956Sxiuyan.wang@Sun.COM 	base_addr = addr & 0xfff00000;
1417956Sxiuyan.wang@Sun.COM 	offset = addr & 0x000fffff;
1427956Sxiuyan.wang@Sun.COM 
1437956Sxiuyan.wang@Sun.COM 	for (i = 0; i < MAX_CRB_XFORM; i++) {
1447956Sxiuyan.wang@Sun.COM 		if (crb_addr_xform[i] == base_addr) {
1457956Sxiuyan.wang@Sun.COM 			pci_base = i << 20;
1467956Sxiuyan.wang@Sun.COM 			break;
1477956Sxiuyan.wang@Sun.COM 		}
1487956Sxiuyan.wang@Sun.COM 	}
1497956Sxiuyan.wang@Sun.COM 
1507956Sxiuyan.wang@Sun.COM 	if (pci_base == ADDR_ERROR) {
1517956Sxiuyan.wang@Sun.COM 		return (pci_base);
1527956Sxiuyan.wang@Sun.COM 	} else {
1537956Sxiuyan.wang@Sun.COM 		return (pci_base + offset);
1547956Sxiuyan.wang@Sun.COM 	}
1557956Sxiuyan.wang@Sun.COM }
1567956Sxiuyan.wang@Sun.COM 
1577956Sxiuyan.wang@Sun.COM static long rom_max_timeout = 100;
1587956Sxiuyan.wang@Sun.COM static long rom_lock_timeout = 10000;
1597956Sxiuyan.wang@Sun.COM 
1607956Sxiuyan.wang@Sun.COM static int
rom_lock(unm_adapter * adapter)1617956Sxiuyan.wang@Sun.COM rom_lock(unm_adapter *adapter)
1627956Sxiuyan.wang@Sun.COM {
1637956Sxiuyan.wang@Sun.COM 	uint32_t done = 0;
1647956Sxiuyan.wang@Sun.COM 	long timeout = 0;
1657956Sxiuyan.wang@Sun.COM 
1667956Sxiuyan.wang@Sun.COM 	while (!done) {
1677956Sxiuyan.wang@Sun.COM 		/* acquire semaphore2 from PCI HW block */
1687956Sxiuyan.wang@Sun.COM 		unm_nic_read_w0(adapter, UNM_PCIE_REG(PCIE_SEM2_LOCK), &done);
1697956Sxiuyan.wang@Sun.COM 		if (done == 1)
1707956Sxiuyan.wang@Sun.COM 			break;
1717956Sxiuyan.wang@Sun.COM 		if (timeout >= rom_lock_timeout) {
1727956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "%s%d rom_lock timed out %d %ld\n",
1737956Sxiuyan.wang@Sun.COM 			    adapter->name, adapter->instance, done, timeout);
1747956Sxiuyan.wang@Sun.COM 			return (-1);
1757956Sxiuyan.wang@Sun.COM 		}
1767956Sxiuyan.wang@Sun.COM 		timeout++;
1777956Sxiuyan.wang@Sun.COM 	}
1787956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, UNM_ROM_LOCK_ID, ROM_LOCK_DRIVER);
1797956Sxiuyan.wang@Sun.COM 	return (0);
1807956Sxiuyan.wang@Sun.COM }
1817956Sxiuyan.wang@Sun.COM 
1827956Sxiuyan.wang@Sun.COM static void
rom_unlock(unm_adapter * adapter)1837956Sxiuyan.wang@Sun.COM rom_unlock(unm_adapter *adapter)
1847956Sxiuyan.wang@Sun.COM {
1857956Sxiuyan.wang@Sun.COM 	uint32_t val;
1867956Sxiuyan.wang@Sun.COM 
1877956Sxiuyan.wang@Sun.COM 	/* release semaphore2 */
1887956Sxiuyan.wang@Sun.COM 	unm_nic_read_w0(adapter, UNM_PCIE_REG(PCIE_SEM2_UNLOCK), &val);
1897956Sxiuyan.wang@Sun.COM }
1907956Sxiuyan.wang@Sun.COM 
1917956Sxiuyan.wang@Sun.COM static int
wait_rom_done(unm_adapter * adapter)1927956Sxiuyan.wang@Sun.COM wait_rom_done(unm_adapter *adapter)
1937956Sxiuyan.wang@Sun.COM {
1947956Sxiuyan.wang@Sun.COM 	long timeout = 0;
1957956Sxiuyan.wang@Sun.COM 	long done = 0;
1967956Sxiuyan.wang@Sun.COM 
1977956Sxiuyan.wang@Sun.COM 	while (done == 0) {
1987956Sxiuyan.wang@Sun.COM 		unm_nic_reg_read(adapter, UNM_ROMUSB_GLB_STATUS, &done);
1997956Sxiuyan.wang@Sun.COM 		done &= 2;
2007956Sxiuyan.wang@Sun.COM 		timeout++;
2017956Sxiuyan.wang@Sun.COM 		if (timeout >= rom_max_timeout) {
2027956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN,
2037956Sxiuyan.wang@Sun.COM 			    "Timeout reached waiting for rom done");
2047956Sxiuyan.wang@Sun.COM 			return (-1);
2057956Sxiuyan.wang@Sun.COM 		}
2067956Sxiuyan.wang@Sun.COM 	}
2077956Sxiuyan.wang@Sun.COM 	return (0);
2087956Sxiuyan.wang@Sun.COM }
2097956Sxiuyan.wang@Sun.COM 
2107956Sxiuyan.wang@Sun.COM static int
do_rom_fast_read(unm_adapter * adapter,int addr,int * valp)2117956Sxiuyan.wang@Sun.COM do_rom_fast_read(unm_adapter *adapter, int addr, int *valp)
2127956Sxiuyan.wang@Sun.COM {
2137956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_ADDRESS, addr);
2147956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_ABYTE_CNT, 3);
2157956Sxiuyan.wang@Sun.COM 	drv_usecwait(100);   /* prevent bursting on CRB */
2167956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
2177956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_INSTR_OPCODE, 0xb);
2187956Sxiuyan.wang@Sun.COM 	if (wait_rom_done(adapter) != DDI_SUCCESS) {
2197956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "Error waiting for rom done\n");
2207956Sxiuyan.wang@Sun.COM 		return (-1);
2217956Sxiuyan.wang@Sun.COM 	}
2227956Sxiuyan.wang@Sun.COM 
2237956Sxiuyan.wang@Sun.COM 	// reset abyte_cnt and dummy_byte_cnt
2247956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
2257956Sxiuyan.wang@Sun.COM 	drv_usecwait(100);   /* prevent bursting on CRB */
2267956Sxiuyan.wang@Sun.COM 	unm_nic_reg_write(adapter, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
2277956Sxiuyan.wang@Sun.COM 
2287956Sxiuyan.wang@Sun.COM 	unm_nic_reg_read(adapter, UNM_ROMUSB_ROM_RDATA, valp);
2297956Sxiuyan.wang@Sun.COM 	return (0);
2307956Sxiuyan.wang@Sun.COM }
2317956Sxiuyan.wang@Sun.COM 
2327956Sxiuyan.wang@Sun.COM int
rom_fast_read(struct unm_adapter_s * adapter,int addr,int * valp)2337956Sxiuyan.wang@Sun.COM rom_fast_read(struct unm_adapter_s *adapter, int addr, int *valp)
2347956Sxiuyan.wang@Sun.COM {
2357956Sxiuyan.wang@Sun.COM 	int ret;
2367956Sxiuyan.wang@Sun.COM 
2377956Sxiuyan.wang@Sun.COM 	if (rom_lock(adapter) != 0) {
2387956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s(%d)rom_lock failed\n",
2397956Sxiuyan.wang@Sun.COM 		    __FUNCTION__, __LINE__);
2407956Sxiuyan.wang@Sun.COM 		return (-1);
2417956Sxiuyan.wang@Sun.COM 	}
2427956Sxiuyan.wang@Sun.COM 
2437956Sxiuyan.wang@Sun.COM 	ret = do_rom_fast_read(adapter, addr, valp);
2447956Sxiuyan.wang@Sun.COM 	if (ret != 0) {
2457956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s do_rom_fast_read returned: %d\n",
2467956Sxiuyan.wang@Sun.COM 		    __FUNCTION__, __LINE__);
2477956Sxiuyan.wang@Sun.COM 		return (-1);
2487956Sxiuyan.wang@Sun.COM 	}
2497956Sxiuyan.wang@Sun.COM 	rom_unlock(adapter);
2507956Sxiuyan.wang@Sun.COM 	return (ret);
2517956Sxiuyan.wang@Sun.COM }
2527956Sxiuyan.wang@Sun.COM 
2537956Sxiuyan.wang@Sun.COM int
pinit_from_rom(struct unm_adapter_s * adapter,int verbose)2547956Sxiuyan.wang@Sun.COM pinit_from_rom(struct unm_adapter_s *adapter, int verbose)
2557956Sxiuyan.wang@Sun.COM {
2567956Sxiuyan.wang@Sun.COM 	int	addr, val, status, i, init_delay = 0, n;
2577956Sxiuyan.wang@Sun.COM 	struct crb_addr_pair	*buf;
2587956Sxiuyan.wang@Sun.COM 	unsigned long	off;
2597956Sxiuyan.wang@Sun.COM 	unsigned int	offset;
2607956Sxiuyan.wang@Sun.COM 
2617956Sxiuyan.wang@Sun.COM 	status = unm_nic_get_board_info(adapter);
2627956Sxiuyan.wang@Sun.COM 	if (status)
2637956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s: pinit_from_rom: Error getting brdinfo\n",
2647956Sxiuyan.wang@Sun.COM 		    unm_nic_driver_name);
2657956Sxiuyan.wang@Sun.COM 
2667956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_ROMUSB_GLB_SW_RESET, 0xffffffff, adapter);
2677956Sxiuyan.wang@Sun.COM 
2687956Sxiuyan.wang@Sun.COM 	if (verbose) {
2697956Sxiuyan.wang@Sun.COM 		int	val;
2707956Sxiuyan.wang@Sun.COM 		if (rom_fast_read(adapter, 0x4008, &val) == 0)
2717956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "P2 ROM board type: 0x%08x\n", val);
2727956Sxiuyan.wang@Sun.COM 		else
2737956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "Could not read board type\n");
2747956Sxiuyan.wang@Sun.COM 		if (rom_fast_read(adapter, 0x400c, &val) == 0)
2757956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "ROM board  num: 0x%08x\n", val);
2767956Sxiuyan.wang@Sun.COM 		else
2777956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "Could not read board number\n");
2787956Sxiuyan.wang@Sun.COM 		if (rom_fast_read(adapter, 0x4010, &val) == 0)
2797956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "ROM chip   num: 0x%08x\n", val);
2807956Sxiuyan.wang@Sun.COM 		else
2817956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "Could not read chip number\n");
2827956Sxiuyan.wang@Sun.COM 	}
2837956Sxiuyan.wang@Sun.COM 
2847956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
2857956Sxiuyan.wang@Sun.COM 		if (rom_fast_read(adapter, 0, &n) != 0 ||
2867956Sxiuyan.wang@Sun.COM 		    (unsigned int)n != 0xcafecafe ||
2877956Sxiuyan.wang@Sun.COM 		    rom_fast_read(adapter, 4, &n) != 0) {
2887956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "%s: ERROR Reading crb_init area: "
2897956Sxiuyan.wang@Sun.COM 			    "n: %08x\n", unm_nic_driver_name, n);
2907956Sxiuyan.wang@Sun.COM 			return (-1);
2917956Sxiuyan.wang@Sun.COM 		}
2927956Sxiuyan.wang@Sun.COM 
2937956Sxiuyan.wang@Sun.COM 		offset = n & 0xffffU;
2947956Sxiuyan.wang@Sun.COM 		n = (n >> 16) & 0xffffU;
2957956Sxiuyan.wang@Sun.COM 	} else {
2967956Sxiuyan.wang@Sun.COM 		if (rom_fast_read(adapter, 0, &n) != 0 ||
2977956Sxiuyan.wang@Sun.COM 		    !(n & 0x80000000)) {
2987956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "%s: ERROR Reading crb_init area: "
2997956Sxiuyan.wang@Sun.COM 			    "n: %08x\n", unm_nic_driver_name, n);
3007956Sxiuyan.wang@Sun.COM 			return (-1);
3017956Sxiuyan.wang@Sun.COM 		}
3027956Sxiuyan.wang@Sun.COM 		offset = 1;
3037956Sxiuyan.wang@Sun.COM 		n &= ~0x80000000;
3047956Sxiuyan.wang@Sun.COM 	}
3057956Sxiuyan.wang@Sun.COM 
3067956Sxiuyan.wang@Sun.COM 	if (n  >= 1024) {
3077956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s: %s:n=0x%x Card flash not initialized\n",
3087956Sxiuyan.wang@Sun.COM 		    unm_nic_driver_name, __FUNCTION__, n);
3097956Sxiuyan.wang@Sun.COM 		return (-1);
3107956Sxiuyan.wang@Sun.COM 	}
3117956Sxiuyan.wang@Sun.COM 
3127956Sxiuyan.wang@Sun.COM 	if (verbose)
3137956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s: %d CRB init values found in ROM.\n",
3147956Sxiuyan.wang@Sun.COM 		    unm_nic_driver_name, n);
3157956Sxiuyan.wang@Sun.COM 
3167956Sxiuyan.wang@Sun.COM 	buf = kmem_zalloc(n * sizeof (struct crb_addr_pair), KM_SLEEP);
3177956Sxiuyan.wang@Sun.COM 	if (buf == NULL) {
3187956Sxiuyan.wang@Sun.COM 		cmn_err(CE_WARN, "%s: pinit_from_rom: Unable to get memory\n",
3197956Sxiuyan.wang@Sun.COM 		    unm_nic_driver_name);
3207956Sxiuyan.wang@Sun.COM 		return (-1);
3217956Sxiuyan.wang@Sun.COM 	}
3227956Sxiuyan.wang@Sun.COM 
3237956Sxiuyan.wang@Sun.COM 	for (i = 0; i < n; i++) {
3247956Sxiuyan.wang@Sun.COM 		if (rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
3257956Sxiuyan.wang@Sun.COM 		    rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
3267956Sxiuyan.wang@Sun.COM 			kmem_free(buf, n * sizeof (struct crb_addr_pair));
3277956Sxiuyan.wang@Sun.COM 			return (-1);
3287956Sxiuyan.wang@Sun.COM 		}
3297956Sxiuyan.wang@Sun.COM 
3307956Sxiuyan.wang@Sun.COM 		buf[i].addr = addr;
3317956Sxiuyan.wang@Sun.COM 		buf[i].data = val;
3327956Sxiuyan.wang@Sun.COM 
3337956Sxiuyan.wang@Sun.COM 		if (verbose)
3347956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "%s: PCI:     0x%08x == 0x%08x\n",
3357956Sxiuyan.wang@Sun.COM 			    unm_nic_driver_name,
3367956Sxiuyan.wang@Sun.COM 			    (unsigned int)decode_crb_addr(
3377956Sxiuyan.wang@Sun.COM 			    (unsigned long)addr), val);
3387956Sxiuyan.wang@Sun.COM 	}
3397956Sxiuyan.wang@Sun.COM 
3407956Sxiuyan.wang@Sun.COM 	for (i = 0; i < n; i++) {
3417956Sxiuyan.wang@Sun.COM 		off = decode_crb_addr((unsigned long)buf[i].addr) +
3427956Sxiuyan.wang@Sun.COM 		    UNM_PCI_CRBSPACE;
3437956Sxiuyan.wang@Sun.COM 		/* skipping cold reboot MAGIC */
3447956Sxiuyan.wang@Sun.COM 		if (off == UNM_CAM_RAM(0x1fc)) {
3457956Sxiuyan.wang@Sun.COM 			continue;
3467956Sxiuyan.wang@Sun.COM 		}
3477956Sxiuyan.wang@Sun.COM 
3487956Sxiuyan.wang@Sun.COM 		if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
3497956Sxiuyan.wang@Sun.COM 			/* do not reset PCI */
3507956Sxiuyan.wang@Sun.COM 			if (off == (ROMUSB_GLB + 0xbc)) {
3517956Sxiuyan.wang@Sun.COM 				continue;
3527956Sxiuyan.wang@Sun.COM 			}
3537956Sxiuyan.wang@Sun.COM 			if (off == (ROMUSB_GLB + 0xc8))	/* core clock */
3547956Sxiuyan.wang@Sun.COM 				continue;
3557956Sxiuyan.wang@Sun.COM 			if (off == (ROMUSB_GLB + 0x24))	/* MN clock */
3567956Sxiuyan.wang@Sun.COM 				continue;
3577956Sxiuyan.wang@Sun.COM 			if (off == (ROMUSB_GLB + 0x1c))	/* MS clock */
3587956Sxiuyan.wang@Sun.COM 				continue;
3597956Sxiuyan.wang@Sun.COM 			if (off == (UNM_CRB_PEG_NET_1 + 0x18)) {
3607956Sxiuyan.wang@Sun.COM 				buf[i].data = 0x1020;
3617956Sxiuyan.wang@Sun.COM 			}
3627956Sxiuyan.wang@Sun.COM 			/* skip the function enable register */
3637956Sxiuyan.wang@Sun.COM 			if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION)) {
3647956Sxiuyan.wang@Sun.COM 				continue;
3657956Sxiuyan.wang@Sun.COM 			}
3667956Sxiuyan.wang@Sun.COM 			if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION2)) {
3677956Sxiuyan.wang@Sun.COM 				continue;
3687956Sxiuyan.wang@Sun.COM 			}
3697956Sxiuyan.wang@Sun.COM 
3707956Sxiuyan.wang@Sun.COM 			if ((off & 0x0ff00000) == UNM_CRB_SMB) {
3717956Sxiuyan.wang@Sun.COM 				continue;
3727956Sxiuyan.wang@Sun.COM 			}
3737956Sxiuyan.wang@Sun.COM 
3747956Sxiuyan.wang@Sun.COM 		}
3757956Sxiuyan.wang@Sun.COM 
3767956Sxiuyan.wang@Sun.COM 		if (off == ADDR_ERROR) {
3777956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "%s: Err: Unknown addr: 0x%08lx\n",
3787956Sxiuyan.wang@Sun.COM 			    unm_nic_driver_name, buf[i].addr);
3797956Sxiuyan.wang@Sun.COM 			continue;
3807956Sxiuyan.wang@Sun.COM 		}
3817956Sxiuyan.wang@Sun.COM 
3827956Sxiuyan.wang@Sun.COM 		/* After writing this register, HW needs time for CRB */
3837956Sxiuyan.wang@Sun.COM 		/* to quiet down (else crb_window returns 0xffffffff) */
3847956Sxiuyan.wang@Sun.COM 		if (off == UNM_ROMUSB_GLB_SW_RESET) {
3857956Sxiuyan.wang@Sun.COM 			init_delay = 1;
3867956Sxiuyan.wang@Sun.COM 
3877956Sxiuyan.wang@Sun.COM 			if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
3887956Sxiuyan.wang@Sun.COM 				/* hold xdma in reset also */
3897956Sxiuyan.wang@Sun.COM 				buf[i].data = 0x8000ff;
3907956Sxiuyan.wang@Sun.COM 			}
3917956Sxiuyan.wang@Sun.COM 		}
3927956Sxiuyan.wang@Sun.COM 
3937956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, off, &buf[i].data, 4);
3947956Sxiuyan.wang@Sun.COM 
3957956Sxiuyan.wang@Sun.COM 		if (init_delay == 1) {
3967956Sxiuyan.wang@Sun.COM 			nx_msleep(1000);	/* Sleep 1000 msecs */
3977956Sxiuyan.wang@Sun.COM 			init_delay = 0;
3987956Sxiuyan.wang@Sun.COM 		}
3997956Sxiuyan.wang@Sun.COM 
4007956Sxiuyan.wang@Sun.COM 		nx_msleep(1);			/* Sleep 1 msec */
4017956Sxiuyan.wang@Sun.COM 	}
4027956Sxiuyan.wang@Sun.COM 
4037956Sxiuyan.wang@Sun.COM 	kmem_free(buf, n * sizeof (struct crb_addr_pair));
4047956Sxiuyan.wang@Sun.COM 
4057956Sxiuyan.wang@Sun.COM 	// disable_peg_cache_all
4067956Sxiuyan.wang@Sun.COM 	// unreset_net_cache
4077956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
4087956Sxiuyan.wang@Sun.COM 		val = UNM_CRB_READ_VAL_ADAPTER(UNM_ROMUSB_GLB_SW_RESET,
4097956Sxiuyan.wang@Sun.COM 		    adapter);
4107956Sxiuyan.wang@Sun.COM 		UNM_CRB_WRITELIT_ADAPTER(UNM_ROMUSB_GLB_SW_RESET,
4117956Sxiuyan.wang@Sun.COM 		    (val & 0xffffff0f), adapter);
4127956Sxiuyan.wang@Sun.COM 	}
4137956Sxiuyan.wang@Sun.COM 
4147956Sxiuyan.wang@Sun.COM 	// p2dn replyCount
4157956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_D+0xec, 0x1e, adapter);
4167956Sxiuyan.wang@Sun.COM 	// disable_peg_cache 0
4177956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_D+0x4c, 8, adapter);
4187956Sxiuyan.wang@Sun.COM 	// disable_peg_cache 1
4197956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_I+0x4c, 8, adapter);
4207956Sxiuyan.wang@Sun.COM 
4217956Sxiuyan.wang@Sun.COM 	// peg_clr_all
4227956Sxiuyan.wang@Sun.COM 	// peg_clr 0
4237956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_0+0x8, 0, adapter);
4247956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_0+0xc, 0, adapter);
4257956Sxiuyan.wang@Sun.COM 	// peg_clr 1
4267956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_1+0x8, 0, adapter);
4277956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_1+0xc, 0, adapter);
4287956Sxiuyan.wang@Sun.COM 	// peg_clr 2
4297956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_2+0x8, 0, adapter);
4307956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_2+0xc, 0, adapter);
4317956Sxiuyan.wang@Sun.COM 	// peg_clr 3
4327956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_3+0x8, 0, adapter);
4337956Sxiuyan.wang@Sun.COM 	UNM_CRB_WRITELIT_ADAPTER(UNM_CRB_PEG_NET_3+0xc, 0, adapter);
4347956Sxiuyan.wang@Sun.COM 
4357956Sxiuyan.wang@Sun.COM 	return (0);
4367956Sxiuyan.wang@Sun.COM }
4377956Sxiuyan.wang@Sun.COM 
4387956Sxiuyan.wang@Sun.COM int
phantom_init(struct unm_adapter_s * adapter,int pegtune_val)4397956Sxiuyan.wang@Sun.COM phantom_init(struct unm_adapter_s *adapter, int pegtune_val)
4407956Sxiuyan.wang@Sun.COM {
4417956Sxiuyan.wang@Sun.COM 	u32	val = 0;
4427956Sxiuyan.wang@Sun.COM 	int	retries = 120;
4437956Sxiuyan.wang@Sun.COM 
4447956Sxiuyan.wang@Sun.COM 	if (!pegtune_val) {
4457956Sxiuyan.wang@Sun.COM 		do {
4467956Sxiuyan.wang@Sun.COM 			val = adapter->unm_nic_pci_read_normalize(adapter,
4477956Sxiuyan.wang@Sun.COM 			    CRB_CMDPEG_STATE);
4487956Sxiuyan.wang@Sun.COM 
4497956Sxiuyan.wang@Sun.COM 			if ((val == PHAN_INITIALIZE_COMPLETE) ||
4507956Sxiuyan.wang@Sun.COM 			    (val == PHAN_INITIALIZE_ACK))
4517956Sxiuyan.wang@Sun.COM 				return (DDI_SUCCESS);
4527956Sxiuyan.wang@Sun.COM 
4537956Sxiuyan.wang@Sun.COM 			/* 500 msec wait */
4547956Sxiuyan.wang@Sun.COM 			drv_usecwait(500000);
4557956Sxiuyan.wang@Sun.COM 		} while (--retries > 0);
4567956Sxiuyan.wang@Sun.COM 
4577956Sxiuyan.wang@Sun.COM 		if (!retries) {
4587956Sxiuyan.wang@Sun.COM 			val = adapter->unm_nic_pci_read_normalize(adapter,
4597956Sxiuyan.wang@Sun.COM 			    UNM_ROMUSB_GLB_PEGTUNE_DONE);
4607956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "WARNING: Initial boot wait loop"
4617956Sxiuyan.wang@Sun.COM 			    "failed...state:%d\n", val);
4627956Sxiuyan.wang@Sun.COM 			return (DDI_FAILURE);
4637956Sxiuyan.wang@Sun.COM 		}
4647956Sxiuyan.wang@Sun.COM 	}
4657956Sxiuyan.wang@Sun.COM 
4667956Sxiuyan.wang@Sun.COM 	return (DDI_SUCCESS);
4677956Sxiuyan.wang@Sun.COM }
4687956Sxiuyan.wang@Sun.COM 
4697956Sxiuyan.wang@Sun.COM int
load_from_flash(struct unm_adapter_s * adapter)4707956Sxiuyan.wang@Sun.COM load_from_flash(struct unm_adapter_s *adapter)
4717956Sxiuyan.wang@Sun.COM {
4727956Sxiuyan.wang@Sun.COM 	int  i;
4737956Sxiuyan.wang@Sun.COM 	long data, size = 0;
4747956Sxiuyan.wang@Sun.COM 	long flashaddr = BOOTLD_START, memaddr = BOOTLD_START;
4757956Sxiuyan.wang@Sun.COM 
4767956Sxiuyan.wang@Sun.COM 	size = (IMAGE_START - BOOTLD_START)/4;
4777956Sxiuyan.wang@Sun.COM 
4787956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
4797956Sxiuyan.wang@Sun.COM 		data = 1;
4807956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, UNM_ROMUSB_GLB_CAS_RST,
4817956Sxiuyan.wang@Sun.COM 		    &data, 4);
4827956Sxiuyan.wang@Sun.COM 	}
4837956Sxiuyan.wang@Sun.COM 
4847956Sxiuyan.wang@Sun.COM 	for (i = 0; i < size; i++) {
4857956Sxiuyan.wang@Sun.COM 		if (rom_fast_read(adapter, flashaddr, (int *)&data) != 0) {
4867956Sxiuyan.wang@Sun.COM 			cmn_err(CE_WARN, "Error in rom_fast_read: "
4877956Sxiuyan.wang@Sun.COM 			    "Will skip loading flash image\n");
4887956Sxiuyan.wang@Sun.COM 			return (DDI_FAILURE);
4897956Sxiuyan.wang@Sun.COM 		}
4907956Sxiuyan.wang@Sun.COM 
4917956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_pci_mem_write(adapter, memaddr, &data, 4);
4927956Sxiuyan.wang@Sun.COM 		flashaddr += 4;
4937956Sxiuyan.wang@Sun.COM 		memaddr += 4;
4947956Sxiuyan.wang@Sun.COM 	}
4957956Sxiuyan.wang@Sun.COM 
4967956Sxiuyan.wang@Sun.COM 	drv_usecwait(100);
4977956Sxiuyan.wang@Sun.COM 	UNM_READ_LOCK(&adapter->adapter_lock);
4987956Sxiuyan.wang@Sun.COM 
4997956Sxiuyan.wang@Sun.COM 	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
5007956Sxiuyan.wang@Sun.COM 		data = 0x80001d;
5017956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, UNM_ROMUSB_GLB_SW_RESET,
5027956Sxiuyan.wang@Sun.COM 		    &data, 4);
5037956Sxiuyan.wang@Sun.COM 	} else {
5047956Sxiuyan.wang@Sun.COM 		data = 0x3fff;
5057956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter,
5067956Sxiuyan.wang@Sun.COM 		    UNM_ROMUSB_GLB_CHIP_CLK_CTRL, &data, 4);
5077956Sxiuyan.wang@Sun.COM 		data = 0;
5087956Sxiuyan.wang@Sun.COM 		adapter->unm_nic_hw_write_wx(adapter, UNM_ROMUSB_GLB_CAS_RST,
5097956Sxiuyan.wang@Sun.COM 		    &data, 4);
5107956Sxiuyan.wang@Sun.COM 	}
5117956Sxiuyan.wang@Sun.COM 
5127956Sxiuyan.wang@Sun.COM 	UNM_READ_UNLOCK(&adapter->adapter_lock);
5137956Sxiuyan.wang@Sun.COM 	return (DDI_SUCCESS);
5147956Sxiuyan.wang@Sun.COM }
515