1eb82ff87SDaniel Beauregard /* 2eb82ff87SDaniel Beauregard * CDDL HEADER START 3eb82ff87SDaniel Beauregard * 4eb82ff87SDaniel Beauregard * The contents of this file are subject to the terms of the 5eb82ff87SDaniel Beauregard * Common Development and Distribution License (the "License"). 6eb82ff87SDaniel Beauregard * You may not use this file except in compliance with the License. 7eb82ff87SDaniel Beauregard * 8eb82ff87SDaniel Beauregard * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9eb82ff87SDaniel Beauregard * or http://www.opensolaris.org/os/licensing. 10eb82ff87SDaniel Beauregard * See the License for the specific language governing permissions 11eb82ff87SDaniel Beauregard * and limitations under the License. 12eb82ff87SDaniel Beauregard * 13eb82ff87SDaniel Beauregard * When distributing Covered Code, include this CDDL HEADER in each 14eb82ff87SDaniel Beauregard * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eb82ff87SDaniel Beauregard * If applicable, add the following below this CDDL HEADER, with the 16eb82ff87SDaniel Beauregard * fields enclosed by brackets "[]" replaced with your own identifying 17eb82ff87SDaniel Beauregard * information: Portions Copyright [yyyy] [name of copyright owner] 18eb82ff87SDaniel Beauregard * 19eb82ff87SDaniel Beauregard * CDDL HEADER END 20eb82ff87SDaniel Beauregard */ 21eb82ff87SDaniel Beauregard 22eb82ff87SDaniel Beauregard /* 23eb82ff87SDaniel Beauregard * Copyright 2010 QLogic Corporation. All rights reserved. 24eb82ff87SDaniel Beauregard * Use is subject to license terms. 25eb82ff87SDaniel Beauregard */ 26eb82ff87SDaniel Beauregard 27eb82ff87SDaniel Beauregard #pragma ident "Copyright 2010 QLogic Corporation; ql_nx.c" 28eb82ff87SDaniel Beauregard 29eb82ff87SDaniel Beauregard /* 30eb82ff87SDaniel Beauregard * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file. 31eb82ff87SDaniel Beauregard * 32eb82ff87SDaniel Beauregard * *********************************************************************** 33eb82ff87SDaniel Beauregard * * ** 34eb82ff87SDaniel Beauregard * * NOTICE ** 35eb82ff87SDaniel Beauregard * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION ** 36eb82ff87SDaniel Beauregard * * ALL RIGHTS RESERVED ** 37eb82ff87SDaniel Beauregard * * ** 38eb82ff87SDaniel Beauregard * *********************************************************************** 39eb82ff87SDaniel Beauregard * 40eb82ff87SDaniel Beauregard */ 41eb82ff87SDaniel Beauregard 42eb82ff87SDaniel Beauregard #include <ql_apps.h> 43eb82ff87SDaniel Beauregard #include <ql_api.h> 44eb82ff87SDaniel Beauregard #include <ql_debug.h> 45eb82ff87SDaniel Beauregard #include <ql_mbx.h> 46eb82ff87SDaniel Beauregard #include <ql_nx.h> 47eb82ff87SDaniel Beauregard 48eb82ff87SDaniel Beauregard /* 49eb82ff87SDaniel Beauregard * Local Function Prototypes. 50eb82ff87SDaniel Beauregard */ 51eb82ff87SDaniel Beauregard static void *ql_8021_pci_base_offsetfset(ql_adapter_state_t *, uint64_t); 52eb82ff87SDaniel Beauregard static void ql_crb_addr_transform_setup(ql_adapter_state_t *); 53eb82ff87SDaniel Beauregard static void ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t *, uint64_t *); 54eb82ff87SDaniel Beauregard static void ql_8021_wr_32(ql_adapter_state_t *, uint64_t, uint32_t); 55eb82ff87SDaniel Beauregard static void ql_8021_rd_32(ql_adapter_state_t *, uint64_t, uint32_t *); 56eb82ff87SDaniel Beauregard static int ql_8021_crb_win_lock(ql_adapter_state_t *); 57eb82ff87SDaniel Beauregard static void ql_8021_crb_win_unlock(ql_adapter_state_t *); 58eb82ff87SDaniel Beauregard static int ql_8021_pci_get_crb_addr_2M(ql_adapter_state_t *, uint64_t *); 59eb82ff87SDaniel Beauregard static uint32_t ql_8021_pci_mem_bound_check(ql_adapter_state_t *, uint64_t, 60eb82ff87SDaniel Beauregard uint32_t); 61eb82ff87SDaniel Beauregard static uint64_t ql_8021_pci_set_window(ql_adapter_state_t *, uint64_t); 62eb82ff87SDaniel Beauregard static int ql_8021_pci_is_same_window(ql_adapter_state_t *, uint64_t); 63eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_read_direct(ql_adapter_state_t *, uint64_t, void *, 64eb82ff87SDaniel Beauregard uint32_t); 65eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_write_direct(ql_adapter_state_t *, uint64_t, void *, 66eb82ff87SDaniel Beauregard uint32_t); 67eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_read_2M(ql_adapter_state_t *, uint64_t, void *, 68eb82ff87SDaniel Beauregard uint32_t); 69eb82ff87SDaniel Beauregard static int ql_8021_pci_mem_write_2M(ql_adapter_state_t *, uint64_t, void *, 70eb82ff87SDaniel Beauregard uint32_t); 71eb82ff87SDaniel Beauregard static uint32_t ql_8021_decode_crb_addr(ql_adapter_state_t *, uint32_t); 72eb82ff87SDaniel Beauregard static int ql_8021_rom_lock(ql_adapter_state_t *); 73eb82ff87SDaniel Beauregard static void ql_8021_rom_unlock(ql_adapter_state_t *); 74eb82ff87SDaniel Beauregard static int ql_8021_wait_rom_done(ql_adapter_state_t *); 75eb82ff87SDaniel Beauregard static int ql_8021_wait_flash_done(ql_adapter_state_t *); 76eb82ff87SDaniel Beauregard static int ql_8021_do_rom_fast_read(ql_adapter_state_t *, uint32_t, uint32_t *); 77eb82ff87SDaniel Beauregard static int ql_8021_rom_fast_read(ql_adapter_state_t *, uint32_t, uint32_t *); 78eb82ff87SDaniel Beauregard static int ql_8021_do_rom_write(ql_adapter_state_t *, uint32_t, uint32_t); 79eb82ff87SDaniel Beauregard static int ql_8021_do_rom_erase(ql_adapter_state_t *, uint32_t); 80eb82ff87SDaniel Beauregard static int ql_8021_phantom_init(ql_adapter_state_t *); 81eb82ff87SDaniel Beauregard static int ql_8021_pinit_from_rom(ql_adapter_state_t *); 82eb82ff87SDaniel Beauregard static int ql_8021_load_from_flash(ql_adapter_state_t *); 83eb82ff87SDaniel Beauregard static int ql_8021_load_firmware(ql_adapter_state_t *); 84eb82ff87SDaniel Beauregard static int ql_8021_reset_hw(ql_adapter_state_t *, int); 85eb82ff87SDaniel Beauregard static int ql_8021_init_p3p(ql_adapter_state_t *); 86eb82ff87SDaniel Beauregard static int ql_8021_hw_lock(ql_adapter_state_t *, uint32_t); 87eb82ff87SDaniel Beauregard static void ql_8021_hw_unlock(ql_adapter_state_t *); 88eb82ff87SDaniel Beauregard static void ql_8021_need_reset_handler(ql_adapter_state_t *); 89eb82ff87SDaniel Beauregard 90eb82ff87SDaniel Beauregard /* 91eb82ff87SDaniel Beauregard * Local Data. 92eb82ff87SDaniel Beauregard */ 93eb82ff87SDaniel Beauregard static uint32_t crb_addr_xform[MAX_CRB_XFORM]; 94eb82ff87SDaniel Beauregard static int crb_table_initialized = 0; 95eb82ff87SDaniel Beauregard static int pci_set_window_warning_count = 0; 96eb82ff87SDaniel Beauregard 97eb82ff87SDaniel Beauregard static struct legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG; 98eb82ff87SDaniel Beauregard 99eb82ff87SDaniel Beauregard static crb_128M_2M_block_map_t crb_128M_2M_map[64] = { 100eb82ff87SDaniel Beauregard {{{0, 0, 0, 0}}}, /* 0: PCI */ 101eb82ff87SDaniel Beauregard {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */ 102eb82ff87SDaniel Beauregard {1, 0x0110000, 0x0120000, 0x130000}, 103eb82ff87SDaniel Beauregard {1, 0x0120000, 0x0122000, 0x124000}, 104eb82ff87SDaniel Beauregard {1, 0x0130000, 0x0132000, 0x126000}, 105eb82ff87SDaniel Beauregard {1, 0x0140000, 0x0142000, 0x128000}, 106eb82ff87SDaniel Beauregard {1, 0x0150000, 0x0152000, 0x12a000}, 107eb82ff87SDaniel Beauregard {1, 0x0160000, 0x0170000, 0x110000}, 108eb82ff87SDaniel Beauregard {1, 0x0170000, 0x0172000, 0x12e000}, 109eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 110eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 111eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 112eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 113eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 114eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 115eb82ff87SDaniel Beauregard {1, 0x01e0000, 0x01e0800, 0x122000}, 116eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}}}, 117eb82ff87SDaniel Beauregard {{{1, 0x0200000, 0x0210000, 0x180000}}}, /* 2: MN */ 118eb82ff87SDaniel Beauregard {{{0, 0, 0, 0}}}, /* 3: */ 119eb82ff87SDaniel Beauregard {{{1, 0x0400000, 0x0401000, 0x169000}}}, /* 4: P2NR1 */ 120eb82ff87SDaniel Beauregard {{{1, 0x0500000, 0x0510000, 0x140000}}}, /* 5: SRE */ 121eb82ff87SDaniel Beauregard {{{1, 0x0600000, 0x0610000, 0x1c0000}}}, /* 6: NIU */ 122eb82ff87SDaniel Beauregard {{{1, 0x0700000, 0x0704000, 0x1b8000}}}, /* 7: QM */ 123eb82ff87SDaniel Beauregard {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */ 124eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 125eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 126eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 127eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 128eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 129eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 130eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 131eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 132eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 133eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 134eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 135eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 136eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 137eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 138eb82ff87SDaniel Beauregard {1, 0x08f0000, 0x08f2000, 0x172000}}}, 139eb82ff87SDaniel Beauregard {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1 */ 140eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 141eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 142eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 143eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 144eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 145eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 146eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 147eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 148eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 149eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 150eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 151eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 152eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 153eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 154eb82ff87SDaniel Beauregard {1, 0x09f0000, 0x09f2000, 0x176000}}}, 155eb82ff87SDaniel Beauregard {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2 */ 156eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 157eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 158eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 159eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 160eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 161eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 162eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 163eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 164eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 165eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 166eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 167eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 168eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 169eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 170eb82ff87SDaniel Beauregard {1, 0x0af0000, 0x0af2000, 0x17a000}}}, 171eb82ff87SDaniel Beauregard {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3 */ 172eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 173eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 174eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 175eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 176eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 177eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 178eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 179eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 180eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 181eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 182eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 183eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 184eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 185eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 186eb82ff87SDaniel Beauregard {1, 0x0bf0000, 0x0bf2000, 0x17e000}}}, 187eb82ff87SDaniel Beauregard {{{1, 0x0c00000, 0x0c04000, 0x1d4000}}}, /* 12: I2Q */ 188eb82ff87SDaniel Beauregard {{{1, 0x0d00000, 0x0d04000, 0x1a4000}}}, /* 13: TMR */ 189eb82ff87SDaniel Beauregard {{{1, 0x0e00000, 0x0e04000, 0x1a0000}}}, /* 14: ROMUSB */ 190eb82ff87SDaniel Beauregard {{{1, 0x0f00000, 0x0f01000, 0x164000}}}, /* 15: PEG4 */ 191eb82ff87SDaniel Beauregard {{{0, 0x1000000, 0x1004000, 0x1a8000}}}, /* 16: XDMA */ 192eb82ff87SDaniel Beauregard {{{1, 0x1100000, 0x1101000, 0x160000}}}, /* 17: PEG0 */ 193eb82ff87SDaniel Beauregard {{{1, 0x1200000, 0x1201000, 0x161000}}}, /* 18: PEG1 */ 194eb82ff87SDaniel Beauregard {{{1, 0x1300000, 0x1301000, 0x162000}}}, /* 19: PEG2 */ 195eb82ff87SDaniel Beauregard {{{1, 0x1400000, 0x1401000, 0x163000}}}, /* 20: PEG3 */ 196eb82ff87SDaniel Beauregard {{{1, 0x1500000, 0x1501000, 0x165000}}}, /* 21: P2ND */ 197eb82ff87SDaniel Beauregard {{{1, 0x1600000, 0x1601000, 0x166000}}}, /* 22: P2NI */ 198eb82ff87SDaniel Beauregard {{{0, 0, 0, 0}}}, /* 23: */ 199eb82ff87SDaniel Beauregard {{{0, 0, 0, 0}}}, /* 24: */ 200eb82ff87SDaniel Beauregard {{{0, 0, 0, 0}}}, /* 25: */ 201eb82ff87SDaniel Beauregard {{{0, 0, 0, 0}}}, /* 26: */ 202eb82ff87SDaniel Beauregard {{{0, 0, 0, 0}}}, /* 27: */ 203eb82ff87SDaniel Beauregard {{{0, 0, 0, 0}}}, /* 28: */ 204eb82ff87SDaniel Beauregard {{{1, 0x1d00000, 0x1d10000, 0x190000}}}, /* 29: MS */ 205eb82ff87SDaniel Beauregard {{{1, 0x1e00000, 0x1e01000, 0x16a000}}}, /* 30: P2NR2 */ 206eb82ff87SDaniel Beauregard {{{1, 0x1f00000, 0x1f10000, 0x150000}}}, /* 31: EPG */ 207eb82ff87SDaniel Beauregard {{{0}}}, /* 32: PCI */ 208eb82ff87SDaniel Beauregard {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */ 209eb82ff87SDaniel Beauregard {1, 0x2110000, 0x2120000, 0x130000}, 210eb82ff87SDaniel Beauregard {1, 0x2120000, 0x2122000, 0x124000}, 211eb82ff87SDaniel Beauregard {1, 0x2130000, 0x2132000, 0x126000}, 212eb82ff87SDaniel Beauregard {1, 0x2140000, 0x2142000, 0x128000}, 213eb82ff87SDaniel Beauregard {1, 0x2150000, 0x2152000, 0x12a000}, 214eb82ff87SDaniel Beauregard {1, 0x2160000, 0x2170000, 0x110000}, 215eb82ff87SDaniel Beauregard {1, 0x2170000, 0x2172000, 0x12e000}, 216eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 217eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 218eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 219eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 220eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 221eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 222eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}, 223eb82ff87SDaniel Beauregard {0, 0x0000000, 0x0000000, 0x000000}}}, 224eb82ff87SDaniel Beauregard {{{1, 0x2200000, 0x2204000, 0x1b0000}}}, /* 34: CAM */ 225eb82ff87SDaniel Beauregard {{{0}}}, /* 35: */ 226eb82ff87SDaniel Beauregard {{{0}}}, /* 36: */ 227eb82ff87SDaniel Beauregard {{{0}}}, /* 37: */ 228eb82ff87SDaniel Beauregard {{{0}}}, /* 38: */ 229eb82ff87SDaniel Beauregard {{{0}}}, /* 39: */ 230eb82ff87SDaniel Beauregard {{{1, 0x2800000, 0x2804000, 0x1a4000}}}, /* 40: TMR */ 231eb82ff87SDaniel Beauregard {{{1, 0x2900000, 0x2901000, 0x16b000}}}, /* 41: P2NR3 */ 232eb82ff87SDaniel Beauregard {{{1, 0x2a00000, 0x2a00400, 0x1ac400}}}, /* 42: RPMX1 */ 233eb82ff87SDaniel Beauregard {{{1, 0x2b00000, 0x2b00400, 0x1ac800}}}, /* 43: RPMX2 */ 234eb82ff87SDaniel Beauregard {{{1, 0x2c00000, 0x2c00400, 0x1acc00}}}, /* 44: RPMX3 */ 235eb82ff87SDaniel Beauregard {{{1, 0x2d00000, 0x2d00400, 0x1ad000}}}, /* 45: RPMX4 */ 236eb82ff87SDaniel Beauregard {{{1, 0x2e00000, 0x2e00400, 0x1ad400}}}, /* 46: RPMX5 */ 237eb82ff87SDaniel Beauregard {{{1, 0x2f00000, 0x2f00400, 0x1ad800}}}, /* 47: RPMX6 */ 238eb82ff87SDaniel Beauregard {{{1, 0x3000000, 0x3000400, 0x1adc00}}}, /* 48: RPMX7 */ 239eb82ff87SDaniel Beauregard {{{0, 0x3100000, 0x3104000, 0x1a8000}}}, /* 49: XDMA */ 240eb82ff87SDaniel Beauregard {{{1, 0x3200000, 0x3204000, 0x1d4000}}}, /* 50: I2Q */ 241eb82ff87SDaniel Beauregard {{{1, 0x3300000, 0x3304000, 0x1a0000}}}, /* 51: ROMUSB */ 242eb82ff87SDaniel Beauregard {{{0}}}, /* 52: */ 243eb82ff87SDaniel Beauregard {{{1, 0x3500000, 0x3500400, 0x1ac000}}}, /* 53: RPMX0 */ 244eb82ff87SDaniel Beauregard {{{1, 0x3600000, 0x3600400, 0x1ae000}}}, /* 54: RPMX8 */ 245eb82ff87SDaniel Beauregard {{{1, 0x3700000, 0x3700400, 0x1ae400}}}, /* 55: RPMX9 */ 246eb82ff87SDaniel Beauregard {{{1, 0x3800000, 0x3804000, 0x1d0000}}}, /* 56: OCM0 */ 247eb82ff87SDaniel Beauregard {{{1, 0x3900000, 0x3904000, 0x1b4000}}}, /* 57: CRYPTO */ 248eb82ff87SDaniel Beauregard {{{1, 0x3a00000, 0x3a04000, 0x1d8000}}}, /* 58: SMB */ 249eb82ff87SDaniel Beauregard {{{0}}}, /* 59: I2C0 */ 250eb82ff87SDaniel Beauregard {{{0}}}, /* 60: I2C1 */ 251eb82ff87SDaniel Beauregard {{{1, 0x3d00000, 0x3d04000, 0x1dc000}}}, /* 61: LPC */ 252eb82ff87SDaniel Beauregard {{{1, 0x3e00000, 0x3e01000, 0x167000}}}, /* 62: P2NC */ 253eb82ff87SDaniel Beauregard {{{1, 0x3f00000, 0x3f01000, 0x168000}}} /* 63: P2NR0 */ 254eb82ff87SDaniel Beauregard }; 255eb82ff87SDaniel Beauregard 256eb82ff87SDaniel Beauregard /* 257eb82ff87SDaniel Beauregard * top 12 bits of crb internal address (hub, agent) 258eb82ff87SDaniel Beauregard */ 259eb82ff87SDaniel Beauregard static uint32_t crb_hub_agt[64] = { 260eb82ff87SDaniel Beauregard 0, 261eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PS, 262eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_MN, 263eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_MS, 264eb82ff87SDaniel Beauregard 0, 265eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_SRE, 266eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_NIU, 267eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_QMN, 268eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_SQN0, 269eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_SQN1, 270eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_SQN2, 271eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_SQN3, 272eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_I2Q, 273eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_TIMR, 274eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_ROMUSB, 275eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGN4, 276eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_XDMA, 277eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGN0, 278eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGN1, 279eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGN2, 280eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGN3, 281eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGND, 282eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGNI, 283eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGS0, 284eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGS1, 285eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGS2, 286eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGS3, 287eb82ff87SDaniel Beauregard 0, 288eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGSI, 289eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_SN, 290eb82ff87SDaniel Beauregard 0, 291eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_EG, 292eb82ff87SDaniel Beauregard 0, 293eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PS, 294eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_CAM, 295eb82ff87SDaniel Beauregard 0, 296eb82ff87SDaniel Beauregard 0, 297eb82ff87SDaniel Beauregard 0, 298eb82ff87SDaniel Beauregard 0, 299eb82ff87SDaniel Beauregard 0, 300eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_TIMR, 301eb82ff87SDaniel Beauregard 0, 302eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_RPMX1, 303eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_RPMX2, 304eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_RPMX3, 305eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_RPMX4, 306eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_RPMX5, 307eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_RPMX6, 308eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_RPMX7, 309eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_XDMA, 310eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_I2Q, 311eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_ROMUSB, 312eb82ff87SDaniel Beauregard 0, 313eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_RPMX0, 314eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_RPMX8, 315eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_RPMX9, 316eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_OCM0, 317eb82ff87SDaniel Beauregard 0, 318eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_SMB, 319eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_I2C0, 320eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_I2C1, 321eb82ff87SDaniel Beauregard 0, 322eb82ff87SDaniel Beauregard UNM_HW_CRB_HUB_AGT_ADR_PGNC, 323eb82ff87SDaniel Beauregard 0, 324eb82ff87SDaniel Beauregard }; 325eb82ff87SDaniel Beauregard 326eb82ff87SDaniel Beauregard static void * 327eb82ff87SDaniel Beauregard ql_8021_pci_base_offsetfset(ql_adapter_state_t *ha, uint64_t off) 328eb82ff87SDaniel Beauregard { 329eb82ff87SDaniel Beauregard if ((off < ha->first_page_group_end) && 330eb82ff87SDaniel Beauregard (off >= ha->first_page_group_start)) { 331eb82ff87SDaniel Beauregard return ((void *)(ha->nx_pcibase + off)); 332eb82ff87SDaniel Beauregard } 333eb82ff87SDaniel Beauregard 334eb82ff87SDaniel Beauregard return (NULL); 335eb82ff87SDaniel Beauregard } 336eb82ff87SDaniel Beauregard 337eb82ff87SDaniel Beauregard /* ARGSUSED */ 338eb82ff87SDaniel Beauregard static void 339eb82ff87SDaniel Beauregard ql_crb_addr_transform_setup(ql_adapter_state_t *ha) 340eb82ff87SDaniel Beauregard { 341eb82ff87SDaniel Beauregard crb_addr_transform(XDMA); 342eb82ff87SDaniel Beauregard crb_addr_transform(TIMR); 343eb82ff87SDaniel Beauregard crb_addr_transform(SRE); 344eb82ff87SDaniel Beauregard crb_addr_transform(SQN3); 345eb82ff87SDaniel Beauregard crb_addr_transform(SQN2); 346eb82ff87SDaniel Beauregard crb_addr_transform(SQN1); 347eb82ff87SDaniel Beauregard crb_addr_transform(SQN0); 348eb82ff87SDaniel Beauregard crb_addr_transform(SQS3); 349eb82ff87SDaniel Beauregard crb_addr_transform(SQS2); 350eb82ff87SDaniel Beauregard crb_addr_transform(SQS1); 351eb82ff87SDaniel Beauregard crb_addr_transform(SQS0); 352eb82ff87SDaniel Beauregard crb_addr_transform(RPMX7); 353eb82ff87SDaniel Beauregard crb_addr_transform(RPMX6); 354eb82ff87SDaniel Beauregard crb_addr_transform(RPMX5); 355eb82ff87SDaniel Beauregard crb_addr_transform(RPMX4); 356eb82ff87SDaniel Beauregard crb_addr_transform(RPMX3); 357eb82ff87SDaniel Beauregard crb_addr_transform(RPMX2); 358eb82ff87SDaniel Beauregard crb_addr_transform(RPMX1); 359eb82ff87SDaniel Beauregard crb_addr_transform(RPMX0); 360eb82ff87SDaniel Beauregard crb_addr_transform(ROMUSB); 361eb82ff87SDaniel Beauregard crb_addr_transform(SN); 362eb82ff87SDaniel Beauregard crb_addr_transform(QMN); 363eb82ff87SDaniel Beauregard crb_addr_transform(QMS); 364eb82ff87SDaniel Beauregard crb_addr_transform(PGNI); 365eb82ff87SDaniel Beauregard crb_addr_transform(PGND); 366eb82ff87SDaniel Beauregard crb_addr_transform(PGN3); 367eb82ff87SDaniel Beauregard crb_addr_transform(PGN2); 368eb82ff87SDaniel Beauregard crb_addr_transform(PGN1); 369eb82ff87SDaniel Beauregard crb_addr_transform(PGN0); 370eb82ff87SDaniel Beauregard crb_addr_transform(PGSI); 371eb82ff87SDaniel Beauregard crb_addr_transform(PGSD); 372eb82ff87SDaniel Beauregard crb_addr_transform(PGS3); 373eb82ff87SDaniel Beauregard crb_addr_transform(PGS2); 374eb82ff87SDaniel Beauregard crb_addr_transform(PGS1); 375eb82ff87SDaniel Beauregard crb_addr_transform(PGS0); 376eb82ff87SDaniel Beauregard crb_addr_transform(PS); 377eb82ff87SDaniel Beauregard crb_addr_transform(PH); 378eb82ff87SDaniel Beauregard crb_addr_transform(NIU); 379eb82ff87SDaniel Beauregard crb_addr_transform(I2Q); 380eb82ff87SDaniel Beauregard crb_addr_transform(EG); 381eb82ff87SDaniel Beauregard crb_addr_transform(MN); 382eb82ff87SDaniel Beauregard crb_addr_transform(MS); 383eb82ff87SDaniel Beauregard crb_addr_transform(CAS2); 384eb82ff87SDaniel Beauregard crb_addr_transform(CAS1); 385eb82ff87SDaniel Beauregard crb_addr_transform(CAS0); 386eb82ff87SDaniel Beauregard crb_addr_transform(CAM); 387eb82ff87SDaniel Beauregard crb_addr_transform(C2C1); 388eb82ff87SDaniel Beauregard crb_addr_transform(C2C0); 389eb82ff87SDaniel Beauregard crb_addr_transform(SMB); 390eb82ff87SDaniel Beauregard crb_addr_transform(OCM0); 391eb82ff87SDaniel Beauregard /* 392eb82ff87SDaniel Beauregard * Used only in P3 just define it for P2 also. 393eb82ff87SDaniel Beauregard */ 394eb82ff87SDaniel Beauregard crb_addr_transform(I2C0); 395eb82ff87SDaniel Beauregard 396eb82ff87SDaniel Beauregard crb_table_initialized = 1; 397eb82ff87SDaniel Beauregard } 398eb82ff87SDaniel Beauregard 399eb82ff87SDaniel Beauregard /* 400eb82ff87SDaniel Beauregard * In: 'off' is offset from CRB space in 128M pci map 401eb82ff87SDaniel Beauregard * Out: 'off' is 2M pci map addr 402eb82ff87SDaniel Beauregard * side effect: lock crb window 403eb82ff87SDaniel Beauregard */ 404eb82ff87SDaniel Beauregard static void 405eb82ff87SDaniel Beauregard ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t *ha, uint64_t *off) 406eb82ff87SDaniel Beauregard { 407eb82ff87SDaniel Beauregard uint32_t win_read; 408eb82ff87SDaniel Beauregard 409eb82ff87SDaniel Beauregard ha->crb_win = (uint32_t)CRB_HI(*off); 410eb82ff87SDaniel Beauregard WRT_REG_DWORD(ha, CRB_WINDOW_2M + ha->nx_pcibase, ha->crb_win); 411eb82ff87SDaniel Beauregard 412eb82ff87SDaniel Beauregard /* 413eb82ff87SDaniel Beauregard * Read back value to make sure write has gone through before trying 414eb82ff87SDaniel Beauregard * to use it. 415eb82ff87SDaniel Beauregard */ 416eb82ff87SDaniel Beauregard win_read = RD_REG_DWORD(ha, CRB_WINDOW_2M + ha->nx_pcibase); 417eb82ff87SDaniel Beauregard if (win_read != ha->crb_win) { 418eb82ff87SDaniel Beauregard EL(ha, "Written crbwin (0x%x) != Read crbwin (0x%x), " 419eb82ff87SDaniel Beauregard "off=0x%llx\n", ha->crb_win, win_read, *off); 420eb82ff87SDaniel Beauregard } 421eb82ff87SDaniel Beauregard *off = (*off & MASK(16)) + CRB_INDIRECT_2M + (uintptr_t)ha->nx_pcibase; 422eb82ff87SDaniel Beauregard } 423eb82ff87SDaniel Beauregard 424eb82ff87SDaniel Beauregard static void 425eb82ff87SDaniel Beauregard ql_8021_wr_32(ql_adapter_state_t *ha, uint64_t off, uint32_t data) 426eb82ff87SDaniel Beauregard { 427eb82ff87SDaniel Beauregard int rv; 428eb82ff87SDaniel Beauregard 429eb82ff87SDaniel Beauregard rv = ql_8021_pci_get_crb_addr_2M(ha, &off); 430eb82ff87SDaniel Beauregard if (rv == -1) { 431eb82ff87SDaniel Beauregard cmn_err(CE_PANIC, "ql_8021_wr_32, ql_8021_pci_get_crb_addr_" 432eb82ff87SDaniel Beauregard "2M=-1\n"); 433eb82ff87SDaniel Beauregard } 434eb82ff87SDaniel Beauregard if (rv == 1) { 435eb82ff87SDaniel Beauregard (void) ql_8021_crb_win_lock(ha); 436eb82ff87SDaniel Beauregard ql_8021_pci_set_crbwindow_2M(ha, &off); 437eb82ff87SDaniel Beauregard } 438eb82ff87SDaniel Beauregard 439eb82ff87SDaniel Beauregard WRT_REG_DWORD(ha, (uintptr_t)off, data); 440eb82ff87SDaniel Beauregard 441eb82ff87SDaniel Beauregard if (rv == 1) { 442eb82ff87SDaniel Beauregard ql_8021_crb_win_unlock(ha); 443eb82ff87SDaniel Beauregard } 444eb82ff87SDaniel Beauregard } 445eb82ff87SDaniel Beauregard 446eb82ff87SDaniel Beauregard static void 447eb82ff87SDaniel Beauregard ql_8021_rd_32(ql_adapter_state_t *ha, uint64_t off, uint32_t *data) 448eb82ff87SDaniel Beauregard { 449eb82ff87SDaniel Beauregard int rv; 450eb82ff87SDaniel Beauregard uint32_t n; 451eb82ff87SDaniel Beauregard 452eb82ff87SDaniel Beauregard rv = ql_8021_pci_get_crb_addr_2M(ha, &off); 453eb82ff87SDaniel Beauregard if (rv == -1) { 454eb82ff87SDaniel Beauregard cmn_err(CE_PANIC, "ql_8021_rd_32, ql_8021_pci_get_crb_addr_" 455eb82ff87SDaniel Beauregard "2M=-1\n"); 456eb82ff87SDaniel Beauregard } 457eb82ff87SDaniel Beauregard 458eb82ff87SDaniel Beauregard if (rv == 1) { 459eb82ff87SDaniel Beauregard (void) ql_8021_crb_win_lock(ha); 460eb82ff87SDaniel Beauregard ql_8021_pci_set_crbwindow_2M(ha, &off); 461eb82ff87SDaniel Beauregard } 462eb82ff87SDaniel Beauregard n = RD_REG_DWORD(ha, (uintptr_t)off); 463eb82ff87SDaniel Beauregard 464eb82ff87SDaniel Beauregard if (data != NULL) { 465eb82ff87SDaniel Beauregard *data = n; 466eb82ff87SDaniel Beauregard } 467eb82ff87SDaniel Beauregard 468eb82ff87SDaniel Beauregard if (rv == 1) { 469eb82ff87SDaniel Beauregard ql_8021_crb_win_unlock(ha); 470eb82ff87SDaniel Beauregard } 471eb82ff87SDaniel Beauregard } 472eb82ff87SDaniel Beauregard 473eb82ff87SDaniel Beauregard static int 474eb82ff87SDaniel Beauregard ql_8021_crb_win_lock(ql_adapter_state_t *ha) 475eb82ff87SDaniel Beauregard { 476eb82ff87SDaniel Beauregard uint32_t done = 0, timeout = 0; 477eb82ff87SDaniel Beauregard 478eb82ff87SDaniel Beauregard while (!done) { 479eb82ff87SDaniel Beauregard /* acquire semaphore3 from PCI HW block */ 480eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM7_LOCK), &done); 481eb82ff87SDaniel Beauregard if (done == 1) { 482eb82ff87SDaniel Beauregard break; 483eb82ff87SDaniel Beauregard } 484eb82ff87SDaniel Beauregard if (timeout >= CRB_WIN_LOCK_TIMEOUT) { 485eb82ff87SDaniel Beauregard EL(ha, "timeout\n"); 486eb82ff87SDaniel Beauregard return (-1); 487eb82ff87SDaniel Beauregard } 488eb82ff87SDaniel Beauregard timeout++; 489eb82ff87SDaniel Beauregard 490eb82ff87SDaniel Beauregard /* Yield CPU */ 491eb82ff87SDaniel Beauregard delay(1); 492eb82ff87SDaniel Beauregard } 493eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_WIN_LOCK_ID, ha->function_number); 494eb82ff87SDaniel Beauregard 495eb82ff87SDaniel Beauregard return (0); 496eb82ff87SDaniel Beauregard } 497eb82ff87SDaniel Beauregard 498eb82ff87SDaniel Beauregard static void 499eb82ff87SDaniel Beauregard ql_8021_crb_win_unlock(ql_adapter_state_t *ha) 500eb82ff87SDaniel Beauregard { 501eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM7_UNLOCK), NULL); 502eb82ff87SDaniel Beauregard } 503eb82ff87SDaniel Beauregard 504eb82ff87SDaniel Beauregard static int 505eb82ff87SDaniel Beauregard ql_8021_pci_get_crb_addr_2M(ql_adapter_state_t *ha, uint64_t *off) 506eb82ff87SDaniel Beauregard { 507eb82ff87SDaniel Beauregard crb_128M_2M_sub_block_map_t *m; 508eb82ff87SDaniel Beauregard 509eb82ff87SDaniel Beauregard if (*off >= UNM_CRB_MAX) { 510eb82ff87SDaniel Beauregard EL(ha, "%llx >= %llx\n", *off, UNM_CRB_MAX); 511eb82ff87SDaniel Beauregard return (-1); 512eb82ff87SDaniel Beauregard } 513eb82ff87SDaniel Beauregard 514eb82ff87SDaniel Beauregard if (*off >= UNM_PCI_CAMQM && (*off < UNM_PCI_CAMQM_2M_END)) { 515eb82ff87SDaniel Beauregard *off = (*off - UNM_PCI_CAMQM) + UNM_PCI_CAMQM_2M_BASE + 516eb82ff87SDaniel Beauregard (uintptr_t)ha->nx_pcibase; 517eb82ff87SDaniel Beauregard return (0); 518eb82ff87SDaniel Beauregard } 519eb82ff87SDaniel Beauregard 520eb82ff87SDaniel Beauregard if (*off < UNM_PCI_CRBSPACE) { 521eb82ff87SDaniel Beauregard EL(ha, "%llx < %llx\n", *off, UNM_PCI_CRBSPACE); 522eb82ff87SDaniel Beauregard return (-1); 523eb82ff87SDaniel Beauregard } 524eb82ff87SDaniel Beauregard 525eb82ff87SDaniel Beauregard *off -= UNM_PCI_CRBSPACE; 526eb82ff87SDaniel Beauregard /* 527eb82ff87SDaniel Beauregard * Try direct map 528eb82ff87SDaniel Beauregard */ 529eb82ff87SDaniel Beauregard 530eb82ff87SDaniel Beauregard m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; 531eb82ff87SDaniel Beauregard 532eb82ff87SDaniel Beauregard if (m->valid && ((uint64_t)m->start_128M <= *off) && 533eb82ff87SDaniel Beauregard ((uint64_t)m->end_128M > *off)) { 534eb82ff87SDaniel Beauregard *off = (uint64_t)(*off + m->start_2M - m->start_128M + 535eb82ff87SDaniel Beauregard (uintptr_t)ha->nx_pcibase); 536eb82ff87SDaniel Beauregard return (0); 537eb82ff87SDaniel Beauregard } 538eb82ff87SDaniel Beauregard 539eb82ff87SDaniel Beauregard /* 540eb82ff87SDaniel Beauregard * Not in direct map, use crb window 541eb82ff87SDaniel Beauregard */ 542eb82ff87SDaniel Beauregard return (1); 543eb82ff87SDaniel Beauregard } 544eb82ff87SDaniel Beauregard 545eb82ff87SDaniel Beauregard /* 546eb82ff87SDaniel Beauregard * check memory access boundary. 547eb82ff87SDaniel Beauregard * used by test agent. support ddr access only for now 548eb82ff87SDaniel Beauregard */ 549eb82ff87SDaniel Beauregard /* ARGSUSED */ 550eb82ff87SDaniel Beauregard static uint32_t 551eb82ff87SDaniel Beauregard ql_8021_pci_mem_bound_check(ql_adapter_state_t *ha, uint64_t addr, 552eb82ff87SDaniel Beauregard uint32_t size) 553eb82ff87SDaniel Beauregard { 554eb82ff87SDaniel Beauregard /*LINTED suspicious 0 comparison*/ 555eb82ff87SDaniel Beauregard if (!QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, 556eb82ff87SDaniel Beauregard UNM_ADDR_DDR_NET_MAX) || 557eb82ff87SDaniel Beauregard /*LINTED suspicious 0 comparison*/ 558eb82ff87SDaniel Beauregard !QL_8021_ADDR_IN_RANGE(addr + size - 1, UNM_ADDR_DDR_NET, 559eb82ff87SDaniel Beauregard UNM_ADDR_DDR_NET_MAX) || 560eb82ff87SDaniel Beauregard ((size != 1) && (size != 2) && (size != 4) && (size != 8))) { 561eb82ff87SDaniel Beauregard return (0); 562eb82ff87SDaniel Beauregard } 563eb82ff87SDaniel Beauregard 564eb82ff87SDaniel Beauregard return (1); 565eb82ff87SDaniel Beauregard } 566eb82ff87SDaniel Beauregard 567eb82ff87SDaniel Beauregard static uint64_t 568eb82ff87SDaniel Beauregard ql_8021_pci_set_window(ql_adapter_state_t *ha, uint64_t addr) 569eb82ff87SDaniel Beauregard { 570eb82ff87SDaniel Beauregard uint32_t window, win_read; 571eb82ff87SDaniel Beauregard 572eb82ff87SDaniel Beauregard /*LINTED suspicious 0 comparison*/ 573eb82ff87SDaniel Beauregard if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, 574eb82ff87SDaniel Beauregard UNM_ADDR_DDR_NET_MAX)) { 575eb82ff87SDaniel Beauregard /* DDR network side */ 576eb82ff87SDaniel Beauregard window = (uint32_t)MN_WIN(addr); 577eb82ff87SDaniel Beauregard ha->ddr_mn_window = window; 578eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window); 579eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, 580eb82ff87SDaniel Beauregard &win_read); 581eb82ff87SDaniel Beauregard if ((win_read << 17) != window) { 582eb82ff87SDaniel Beauregard EL(ha, "Warning, Written MNwin (0x%x) != Read MNwin " 583eb82ff87SDaniel Beauregard "(0x%x)\n", window, win_read); 584eb82ff87SDaniel Beauregard } 585eb82ff87SDaniel Beauregard addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_DDR_NET; 586eb82ff87SDaniel Beauregard } else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM0, 587eb82ff87SDaniel Beauregard UNM_ADDR_OCM0_MAX)) { 588eb82ff87SDaniel Beauregard uint32_t temp1; 589eb82ff87SDaniel Beauregard 590eb82ff87SDaniel Beauregard if ((addr & 0x00ff800) == 0xff800) { 591eb82ff87SDaniel Beauregard /* if bits 19:18&17:11 are on */ 592eb82ff87SDaniel Beauregard EL(ha, "QM access not handled\n"); 593eb82ff87SDaniel Beauregard addr = -1UL; 594eb82ff87SDaniel Beauregard } 595eb82ff87SDaniel Beauregard 596eb82ff87SDaniel Beauregard window = (uint32_t)OCM_WIN(addr); 597eb82ff87SDaniel Beauregard ha->ddr_mn_window = window; 598eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window); 599eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, 600eb82ff87SDaniel Beauregard &win_read); 601eb82ff87SDaniel Beauregard temp1 = ((window & 0x1FF) << 7) | 602eb82ff87SDaniel Beauregard ((window & 0x0FFFE0000) >> 17); 603eb82ff87SDaniel Beauregard if (win_read != temp1) { 604eb82ff87SDaniel Beauregard EL(ha, "Written OCMwin (0x%x) != Read OCMwin (0x%x)\n", 605eb82ff87SDaniel Beauregard temp1, win_read); 606eb82ff87SDaniel Beauregard } 607eb82ff87SDaniel Beauregard addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_OCM0_2M; 608eb82ff87SDaniel Beauregard } else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET, 609eb82ff87SDaniel Beauregard NX_P3_ADDR_QDR_NET_MAX)) { 610eb82ff87SDaniel Beauregard /* QDR network side */ 611eb82ff87SDaniel Beauregard window = (uint32_t)MS_WIN(addr); 612eb82ff87SDaniel Beauregard ha->qdr_sn_window = window; 613eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window); 614eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, 615eb82ff87SDaniel Beauregard &win_read); 616eb82ff87SDaniel Beauregard if (win_read != window) { 617eb82ff87SDaniel Beauregard EL(ha, "Written MSwin (0x%x) != Read MSwin (0x%x)\n", 618eb82ff87SDaniel Beauregard window, win_read); 619eb82ff87SDaniel Beauregard } 620eb82ff87SDaniel Beauregard addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_QDR_NET; 621eb82ff87SDaniel Beauregard } else { 622eb82ff87SDaniel Beauregard /* 623eb82ff87SDaniel Beauregard * peg gdb frequently accesses memory that doesn't exist, 624eb82ff87SDaniel Beauregard * this limits the chit chat so debugging isn't slowed down. 625eb82ff87SDaniel Beauregard */ 626eb82ff87SDaniel Beauregard if ((pci_set_window_warning_count++ < 8) || 627eb82ff87SDaniel Beauregard (pci_set_window_warning_count % 64 == 0)) { 628eb82ff87SDaniel Beauregard EL(ha, "Unknown address range\n"); 629eb82ff87SDaniel Beauregard } 630eb82ff87SDaniel Beauregard addr = -1UL; 631eb82ff87SDaniel Beauregard } 632eb82ff87SDaniel Beauregard 633eb82ff87SDaniel Beauregard return (addr); 634eb82ff87SDaniel Beauregard } 635eb82ff87SDaniel Beauregard 636eb82ff87SDaniel Beauregard /* check if address is in the same windows as the previous access */ 637eb82ff87SDaniel Beauregard static int 638eb82ff87SDaniel Beauregard ql_8021_pci_is_same_window(ql_adapter_state_t *ha, uint64_t addr) 639eb82ff87SDaniel Beauregard { 640eb82ff87SDaniel Beauregard uint32_t window; 641eb82ff87SDaniel Beauregard uint64_t qdr_max; 642eb82ff87SDaniel Beauregard 643eb82ff87SDaniel Beauregard qdr_max = NX_P3_ADDR_QDR_NET_MAX; 644eb82ff87SDaniel Beauregard 645eb82ff87SDaniel Beauregard /*LINTED suspicious 0 comparison*/ 646eb82ff87SDaniel Beauregard if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET, 647eb82ff87SDaniel Beauregard UNM_ADDR_DDR_NET_MAX)) { 648eb82ff87SDaniel Beauregard /* DDR network side */ 649eb82ff87SDaniel Beauregard EL(ha, "DDR network side\n"); 650eb82ff87SDaniel Beauregard return (0); /* MN access can not come here */ 651eb82ff87SDaniel Beauregard } else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM0, 652eb82ff87SDaniel Beauregard UNM_ADDR_OCM0_MAX)) { 653eb82ff87SDaniel Beauregard return (1); 654eb82ff87SDaniel Beauregard } else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM1, 655eb82ff87SDaniel Beauregard UNM_ADDR_OCM1_MAX)) { 656eb82ff87SDaniel Beauregard return (1); 657eb82ff87SDaniel Beauregard } else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET, qdr_max)) { 658eb82ff87SDaniel Beauregard /* QDR network side */ 659eb82ff87SDaniel Beauregard window = (uint32_t)(((addr - UNM_ADDR_QDR_NET) >> 22) & 0x3f); 660eb82ff87SDaniel Beauregard if (ha->qdr_sn_window == window) { 661eb82ff87SDaniel Beauregard return (1); 662eb82ff87SDaniel Beauregard } 663eb82ff87SDaniel Beauregard } 664eb82ff87SDaniel Beauregard 665eb82ff87SDaniel Beauregard return (0); 666eb82ff87SDaniel Beauregard } 667eb82ff87SDaniel Beauregard 668eb82ff87SDaniel Beauregard static int 669eb82ff87SDaniel Beauregard ql_8021_pci_mem_read_direct(ql_adapter_state_t *ha, uint64_t off, void *data, 670eb82ff87SDaniel Beauregard uint32_t size) 671eb82ff87SDaniel Beauregard { 672eb82ff87SDaniel Beauregard void *addr; 673eb82ff87SDaniel Beauregard int ret = 0; 674eb82ff87SDaniel Beauregard uint64_t start; 675eb82ff87SDaniel Beauregard 676eb82ff87SDaniel Beauregard /* 677eb82ff87SDaniel Beauregard * If attempting to access unknown address or straddle hw windows, 678eb82ff87SDaniel Beauregard * do not access. 679eb82ff87SDaniel Beauregard */ 680eb82ff87SDaniel Beauregard if (((start = ql_8021_pci_set_window(ha, off)) == -1UL) || 681eb82ff87SDaniel Beauregard (ql_8021_pci_is_same_window(ha, off + size - 1) == 0)) { 682eb82ff87SDaniel Beauregard EL(ha, "out of bound pci memory access. offset is 0x%llx\n", 683eb82ff87SDaniel Beauregard off); 684eb82ff87SDaniel Beauregard return (-1); 685eb82ff87SDaniel Beauregard } 686eb82ff87SDaniel Beauregard 687eb82ff87SDaniel Beauregard addr = ql_8021_pci_base_offsetfset(ha, start); 688eb82ff87SDaniel Beauregard if (!addr) { 689eb82ff87SDaniel Beauregard addr = (void *)((uint8_t *)ha->nx_pcibase + start); 690eb82ff87SDaniel Beauregard } 691eb82ff87SDaniel Beauregard 692eb82ff87SDaniel Beauregard switch (size) { 693eb82ff87SDaniel Beauregard case 1: 694eb82ff87SDaniel Beauregard *(uint8_t *)data = RD_REG_BYTE(ha, addr); 695eb82ff87SDaniel Beauregard break; 696eb82ff87SDaniel Beauregard case 2: 697eb82ff87SDaniel Beauregard *(uint16_t *)data = RD_REG_WORD(ha, addr); 698eb82ff87SDaniel Beauregard break; 699eb82ff87SDaniel Beauregard case 4: 700eb82ff87SDaniel Beauregard *(uint32_t *)data = RD_REG_DWORD(ha, addr); 701eb82ff87SDaniel Beauregard break; 702eb82ff87SDaniel Beauregard case 8: 703eb82ff87SDaniel Beauregard *(uint64_t *)data = RD_REG_DDWORD(ha, addr); 704eb82ff87SDaniel Beauregard break; 705eb82ff87SDaniel Beauregard default: 706eb82ff87SDaniel Beauregard EL(ha, "invalid size=%x\n", size); 707eb82ff87SDaniel Beauregard ret = -1; 708eb82ff87SDaniel Beauregard break; 709eb82ff87SDaniel Beauregard } 710eb82ff87SDaniel Beauregard 711eb82ff87SDaniel Beauregard return (ret); 712eb82ff87SDaniel Beauregard } 713eb82ff87SDaniel Beauregard 714eb82ff87SDaniel Beauregard static int 715eb82ff87SDaniel Beauregard ql_8021_pci_mem_write_direct(ql_adapter_state_t *ha, uint64_t off, void *data, 716eb82ff87SDaniel Beauregard uint32_t size) 717eb82ff87SDaniel Beauregard { 718eb82ff87SDaniel Beauregard void *addr; 719eb82ff87SDaniel Beauregard int ret = 0; 720eb82ff87SDaniel Beauregard uint64_t start; 721eb82ff87SDaniel Beauregard 722eb82ff87SDaniel Beauregard /* 723eb82ff87SDaniel Beauregard * If attempting to access unknown address or straddle hw windows, 724eb82ff87SDaniel Beauregard * do not access. 725eb82ff87SDaniel Beauregard */ 726eb82ff87SDaniel Beauregard if (((start = ql_8021_pci_set_window(ha, off)) == -1UL) || 727eb82ff87SDaniel Beauregard (ql_8021_pci_is_same_window(ha, off + size -1) == 0)) { 728eb82ff87SDaniel Beauregard EL(ha, "out of bound pci memory access. offset is 0x%llx\n", 729eb82ff87SDaniel Beauregard off); 730eb82ff87SDaniel Beauregard return (-1); 731eb82ff87SDaniel Beauregard } 732eb82ff87SDaniel Beauregard 733eb82ff87SDaniel Beauregard addr = ql_8021_pci_base_offsetfset(ha, start); 734eb82ff87SDaniel Beauregard if (!addr) { 735eb82ff87SDaniel Beauregard addr = (void *)((uint8_t *)ha->nx_pcibase + start); 736eb82ff87SDaniel Beauregard } 737eb82ff87SDaniel Beauregard 738eb82ff87SDaniel Beauregard switch (size) { 739eb82ff87SDaniel Beauregard case 1: 740eb82ff87SDaniel Beauregard WRT_REG_BYTE(ha, addr, *(uint8_t *)data); 741eb82ff87SDaniel Beauregard break; 742eb82ff87SDaniel Beauregard case 2: 743eb82ff87SDaniel Beauregard WRT_REG_WORD(ha, addr, *(uint16_t *)data); 744eb82ff87SDaniel Beauregard break; 745eb82ff87SDaniel Beauregard case 4: 746eb82ff87SDaniel Beauregard WRT_REG_DWORD(ha, addr, *(uint32_t *)data); 747eb82ff87SDaniel Beauregard break; 748eb82ff87SDaniel Beauregard case 8: 749eb82ff87SDaniel Beauregard WRT_REG_DDWORD(ha, addr, *(uint64_t *)data); 750eb82ff87SDaniel Beauregard break; 751eb82ff87SDaniel Beauregard default: 752eb82ff87SDaniel Beauregard EL(ha, "invalid size=%x\n", size); 753eb82ff87SDaniel Beauregard ret = -1; 754eb82ff87SDaniel Beauregard break; 755eb82ff87SDaniel Beauregard } 756eb82ff87SDaniel Beauregard 757eb82ff87SDaniel Beauregard return (ret); 758eb82ff87SDaniel Beauregard } 759eb82ff87SDaniel Beauregard 760eb82ff87SDaniel Beauregard static int 761eb82ff87SDaniel Beauregard ql_8021_pci_mem_read_2M(ql_adapter_state_t *ha, uint64_t off, void *data, 762eb82ff87SDaniel Beauregard uint32_t size) 763eb82ff87SDaniel Beauregard { 764eb82ff87SDaniel Beauregard int j = 0; 765eb82ff87SDaniel Beauregard uint32_t i, temp, sz[2], loop, shift_amount; 766eb82ff87SDaniel Beauregard uint64_t start, end, k; 767eb82ff87SDaniel Beauregard uint64_t off8, off0[2], val, mem_crb, word[2] = {0, 0}; 768eb82ff87SDaniel Beauregard 769eb82ff87SDaniel Beauregard /* 770eb82ff87SDaniel Beauregard * If not MN, go check for MS or invalid. 771eb82ff87SDaniel Beauregard */ 772eb82ff87SDaniel Beauregard 773eb82ff87SDaniel Beauregard if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) { 774eb82ff87SDaniel Beauregard mem_crb = UNM_CRB_QDR_NET; 775eb82ff87SDaniel Beauregard } else { 776eb82ff87SDaniel Beauregard mem_crb = UNM_CRB_DDR_NET; 777eb82ff87SDaniel Beauregard if (ql_8021_pci_mem_bound_check(ha, off, size) == 0) { 778eb82ff87SDaniel Beauregard return (ql_8021_pci_mem_read_direct(ha, off, data, 779eb82ff87SDaniel Beauregard size)); 780eb82ff87SDaniel Beauregard } 781eb82ff87SDaniel Beauregard } 782eb82ff87SDaniel Beauregard 783eb82ff87SDaniel Beauregard if (NX_IS_REVISION_P3PLUS(ha->rev_id)) { 784eb82ff87SDaniel Beauregard off8 = off & 0xfffffff0; 785eb82ff87SDaniel Beauregard off0[0] = off & 0xf; 786eb82ff87SDaniel Beauregard sz[0] = (uint32_t)(((uint64_t)size < (16 - off0[0])) ? size : 787eb82ff87SDaniel Beauregard (16 - off0[0])); 788eb82ff87SDaniel Beauregard shift_amount = 4; 789eb82ff87SDaniel Beauregard } else { 790eb82ff87SDaniel Beauregard off8 = off & 0xfffffff8; 791eb82ff87SDaniel Beauregard off0[0] = off & 0x7; 792eb82ff87SDaniel Beauregard sz[0] = (uint32_t)(((uint64_t)size < (8 - off0[0])) ? size : 793eb82ff87SDaniel Beauregard (8 - off0[0])); 794eb82ff87SDaniel Beauregard shift_amount = 3; 795eb82ff87SDaniel Beauregard } 796eb82ff87SDaniel Beauregard loop = (uint32_t)(((off0[0] + size - 1) >> shift_amount) + 1); 797eb82ff87SDaniel Beauregard off0[1] = 0; 798eb82ff87SDaniel Beauregard sz[1] = size - sz[0]; 799eb82ff87SDaniel Beauregard 800eb82ff87SDaniel Beauregard /* 801eb82ff87SDaniel Beauregard * don't lock here - write_wx gets the lock if each time 802eb82ff87SDaniel Beauregard * write_lock_irqsave(&adapter->adapter_lock, flags); 803eb82ff87SDaniel Beauregard * netxen_nic_pci_change_crbwindow_128M(adapter, 0); 804eb82ff87SDaniel Beauregard */ 805eb82ff87SDaniel Beauregard 806eb82ff87SDaniel Beauregard for (i = 0; i < loop; i++) { 807eb82ff87SDaniel Beauregard temp = (uint32_t)(off8 + (i << shift_amount)); 808eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); 809eb82ff87SDaniel Beauregard temp = 0; 810eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp); 811eb82ff87SDaniel Beauregard temp = MIU_TA_CTL_ENABLE; 812eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); 813eb82ff87SDaniel Beauregard temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; 814eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); 815eb82ff87SDaniel Beauregard 816eb82ff87SDaniel Beauregard for (j = 0; j < MAX_CTL_CHECK; j++) { 817eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL, &temp); 818eb82ff87SDaniel Beauregard if ((temp & MIU_TA_CTL_BUSY) == 0) { 819eb82ff87SDaniel Beauregard break; 820eb82ff87SDaniel Beauregard } 821eb82ff87SDaniel Beauregard } 822eb82ff87SDaniel Beauregard 823eb82ff87SDaniel Beauregard if (j >= MAX_CTL_CHECK) { 824eb82ff87SDaniel Beauregard EL(ha, "failed to read through agent\n"); 825eb82ff87SDaniel Beauregard break; 826eb82ff87SDaniel Beauregard } 827eb82ff87SDaniel Beauregard 828eb82ff87SDaniel Beauregard start = off0[i] >> 2; 829eb82ff87SDaniel Beauregard end = (off0[i] + sz[i] - 1) >> 2; 830eb82ff87SDaniel Beauregard for (k = start; k <= end; k++) { 831eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_RDDATA(k), 832eb82ff87SDaniel Beauregard &temp); 833eb82ff87SDaniel Beauregard word[i] |= ((uint64_t)temp << (32 * (k & 1))); 834eb82ff87SDaniel Beauregard } 835eb82ff87SDaniel Beauregard } 836eb82ff87SDaniel Beauregard 837eb82ff87SDaniel Beauregard /* 838eb82ff87SDaniel Beauregard * netxen_nic_pci_change_crbwindow_128M(adapter, 1); 839eb82ff87SDaniel Beauregard * write_unlock_irqrestore(&adapter->adapter_lock, flags); 840eb82ff87SDaniel Beauregard */ 841eb82ff87SDaniel Beauregard 842eb82ff87SDaniel Beauregard if (j >= MAX_CTL_CHECK) { 843eb82ff87SDaniel Beauregard return (-1); 844eb82ff87SDaniel Beauregard } 845eb82ff87SDaniel Beauregard 846eb82ff87SDaniel Beauregard if ((off0[0] & 7) == 0) { 847eb82ff87SDaniel Beauregard val = word[0]; 848eb82ff87SDaniel Beauregard } else { 849eb82ff87SDaniel Beauregard val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | 850eb82ff87SDaniel Beauregard ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); 851eb82ff87SDaniel Beauregard } 852eb82ff87SDaniel Beauregard 853eb82ff87SDaniel Beauregard switch (size) { 854eb82ff87SDaniel Beauregard case 1: 855eb82ff87SDaniel Beauregard *(uint8_t *)data = (uint8_t)val; 856eb82ff87SDaniel Beauregard break; 857eb82ff87SDaniel Beauregard case 2: 858eb82ff87SDaniel Beauregard *(uint16_t *)data = (uint16_t)val; 859eb82ff87SDaniel Beauregard break; 860eb82ff87SDaniel Beauregard case 4: 861eb82ff87SDaniel Beauregard *(uint32_t *)data = (uint32_t)val; 862eb82ff87SDaniel Beauregard break; 863eb82ff87SDaniel Beauregard case 8: 864eb82ff87SDaniel Beauregard *(uint64_t *)data = val; 865eb82ff87SDaniel Beauregard break; 866eb82ff87SDaniel Beauregard } 867eb82ff87SDaniel Beauregard 868eb82ff87SDaniel Beauregard return (0); 869eb82ff87SDaniel Beauregard } 870eb82ff87SDaniel Beauregard 871eb82ff87SDaniel Beauregard static int 872eb82ff87SDaniel Beauregard ql_8021_pci_mem_write_2M(ql_adapter_state_t *ha, uint64_t off, void *data, 873eb82ff87SDaniel Beauregard uint32_t size) 874eb82ff87SDaniel Beauregard { 875eb82ff87SDaniel Beauregard int j, ret = 0; 876eb82ff87SDaniel Beauregard uint32_t i, temp, loop, sz[2]; 877eb82ff87SDaniel Beauregard uint32_t scale, shift_amount, p3p, startword; 878eb82ff87SDaniel Beauregard uint64_t off8, off0, mem_crb, tmpw, word[2] = {0, 0}; 879eb82ff87SDaniel Beauregard 880eb82ff87SDaniel Beauregard /* 881eb82ff87SDaniel Beauregard * If not MN, go check for MS or invalid. 882eb82ff87SDaniel Beauregard */ 883eb82ff87SDaniel Beauregard if (off >= UNM_ADDR_QDR_NET && off <= NX_P3_ADDR_QDR_NET_MAX) { 884eb82ff87SDaniel Beauregard mem_crb = UNM_CRB_QDR_NET; 885eb82ff87SDaniel Beauregard } else { 886eb82ff87SDaniel Beauregard mem_crb = UNM_CRB_DDR_NET; 887eb82ff87SDaniel Beauregard if (ql_8021_pci_mem_bound_check(ha, off, size) == 0) { 888eb82ff87SDaniel Beauregard return (ql_8021_pci_mem_write_direct(ha, off, data, 889eb82ff87SDaniel Beauregard size)); 890eb82ff87SDaniel Beauregard } 891eb82ff87SDaniel Beauregard } 892eb82ff87SDaniel Beauregard 893eb82ff87SDaniel Beauregard off0 = off & 0x7; 894eb82ff87SDaniel Beauregard sz[0] = (uint32_t)(((uint64_t)size < (8 - off0)) ? size : (8 - off0)); 895eb82ff87SDaniel Beauregard sz[1] = size - sz[0]; 896eb82ff87SDaniel Beauregard 897eb82ff87SDaniel Beauregard if (NX_IS_REVISION_P3PLUS(ha->rev_id)) { 898eb82ff87SDaniel Beauregard off8 = off & 0xfffffff0; 899eb82ff87SDaniel Beauregard loop = (uint32_t)((((off & 0xf) + size - 1) >> 4) + 1); 900eb82ff87SDaniel Beauregard shift_amount = 4; 901eb82ff87SDaniel Beauregard scale = 2; 902eb82ff87SDaniel Beauregard p3p = 1; 903eb82ff87SDaniel Beauregard startword = (uint32_t)((off & 0xf) / 8); 904eb82ff87SDaniel Beauregard } else { 905eb82ff87SDaniel Beauregard off8 = off & 0xfffffff8; 906eb82ff87SDaniel Beauregard loop = (uint32_t)(((off0 + size - 1) >> 3) + 1); 907eb82ff87SDaniel Beauregard shift_amount = 3; 908eb82ff87SDaniel Beauregard scale = 1; 909eb82ff87SDaniel Beauregard p3p = 0; 910eb82ff87SDaniel Beauregard startword = 0; 911eb82ff87SDaniel Beauregard } 912eb82ff87SDaniel Beauregard 913eb82ff87SDaniel Beauregard if (p3p || (size != 8) || (off0 != 0)) { 914eb82ff87SDaniel Beauregard for (i = 0; i < loop; i++) { 915eb82ff87SDaniel Beauregard if (ql_8021_pci_mem_read_2M(ha, off8 + 916eb82ff87SDaniel Beauregard (i << shift_amount), &word[i * scale], 8)) { 917eb82ff87SDaniel Beauregard EL(ha, "8021_pci_mem_read_2M != 0\n"); 918eb82ff87SDaniel Beauregard return (-1); 919eb82ff87SDaniel Beauregard } 920eb82ff87SDaniel Beauregard } 921eb82ff87SDaniel Beauregard } 922eb82ff87SDaniel Beauregard 923eb82ff87SDaniel Beauregard switch (size) { 924eb82ff87SDaniel Beauregard case 1: 925eb82ff87SDaniel Beauregard tmpw = (uint64_t)(*((uint8_t *)data)); 926eb82ff87SDaniel Beauregard break; 927eb82ff87SDaniel Beauregard case 2: 928eb82ff87SDaniel Beauregard tmpw = (uint64_t)(*((uint16_t *)data)); 929eb82ff87SDaniel Beauregard break; 930eb82ff87SDaniel Beauregard case 4: 931eb82ff87SDaniel Beauregard tmpw = (uint64_t)(*((uint32_t *)data)); 932eb82ff87SDaniel Beauregard break; 933eb82ff87SDaniel Beauregard case 8: 934eb82ff87SDaniel Beauregard default: 935eb82ff87SDaniel Beauregard tmpw = *((uint64_t *)data); 936eb82ff87SDaniel Beauregard break; 937eb82ff87SDaniel Beauregard } 938eb82ff87SDaniel Beauregard 939eb82ff87SDaniel Beauregard if (p3p) { 940eb82ff87SDaniel Beauregard if (sz[0] == 8) { 941eb82ff87SDaniel Beauregard word[startword] = tmpw; 942eb82ff87SDaniel Beauregard } else { 943eb82ff87SDaniel Beauregard word[startword] &= ~((~(~0ULL << (sz[0] * 8))) << 944eb82ff87SDaniel Beauregard (off0 * 8)); 945eb82ff87SDaniel Beauregard word[startword] |= tmpw << (off0 * 8); 946eb82ff87SDaniel Beauregard } 947eb82ff87SDaniel Beauregard if (sz[1] != 0) { 948eb82ff87SDaniel Beauregard word[startword+1] &= ~(~0ULL << (sz[1] * 8)); 949eb82ff87SDaniel Beauregard word[startword+1] |= tmpw >> (sz[0] * 8); 950eb82ff87SDaniel Beauregard } 951eb82ff87SDaniel Beauregard } else { 952eb82ff87SDaniel Beauregard word[startword] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); 953eb82ff87SDaniel Beauregard word[startword] |= tmpw << (off0 * 8); 954eb82ff87SDaniel Beauregard 955eb82ff87SDaniel Beauregard if (loop == 2) { 956eb82ff87SDaniel Beauregard word[1] &= ~(~0ULL << (sz[1] * 8)); 957eb82ff87SDaniel Beauregard word[1] |= tmpw >> (sz[0] * 8); 958eb82ff87SDaniel Beauregard } 959eb82ff87SDaniel Beauregard } 960eb82ff87SDaniel Beauregard 961eb82ff87SDaniel Beauregard /* 962eb82ff87SDaniel Beauregard * don't lock here - write_wx gets the lock if each time 963eb82ff87SDaniel Beauregard * write_lock_irqsave(&adapter->adapter_lock, flags); 964eb82ff87SDaniel Beauregard * netxen_nic_pci_change_crbwindow_128M(adapter, 0); 965eb82ff87SDaniel Beauregard */ 966eb82ff87SDaniel Beauregard 967eb82ff87SDaniel Beauregard for (i = 0; i < loop; i++) { 968eb82ff87SDaniel Beauregard temp = (uint32_t)(off8 + (i << shift_amount)); 969eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); 970eb82ff87SDaniel Beauregard temp = 0; 971eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_ADDR_HI, temp); 972eb82ff87SDaniel Beauregard temp = (uint32_t)(word[i * scale] & 0xffffffff); 973eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_LO, temp); 974eb82ff87SDaniel Beauregard temp = (uint32_t)((word[i * scale] >> 32) & 0xffffffff); 975eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_WRDATA_HI, temp); 976eb82ff87SDaniel Beauregard if (p3p) { 977eb82ff87SDaniel Beauregard temp = (uint32_t)(word[i * scale + 1] & 0xffffffff); 978eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, 979eb82ff87SDaniel Beauregard mem_crb + MIU_TEST_AGT_WRDATA_UPPER_LO, temp); 980eb82ff87SDaniel Beauregard temp = (uint32_t)((word[i * scale + 1] >> 32) & 981eb82ff87SDaniel Beauregard 0xffffffff); 982eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, 983eb82ff87SDaniel Beauregard mem_crb + MIU_TEST_AGT_WRDATA_UPPER_HI, temp); 984eb82ff87SDaniel Beauregard } 985eb82ff87SDaniel Beauregard temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; 986eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); 987eb82ff87SDaniel Beauregard temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; 988eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, mem_crb + MIU_TEST_AGT_CTRL, temp); 989eb82ff87SDaniel Beauregard 990eb82ff87SDaniel Beauregard for (j = 0; j < MAX_CTL_CHECK; j++) { 991eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, mem_crb + MIU_TEST_AGT_CTRL, &temp); 992eb82ff87SDaniel Beauregard if ((temp & MIU_TA_CTL_BUSY) == 0) 993eb82ff87SDaniel Beauregard break; 994eb82ff87SDaniel Beauregard } 995eb82ff87SDaniel Beauregard 996eb82ff87SDaniel Beauregard if (j >= MAX_CTL_CHECK) { 997eb82ff87SDaniel Beauregard EL(ha, "failed to write through agent\n"); 998eb82ff87SDaniel Beauregard ret = -1; 999eb82ff87SDaniel Beauregard break; 1000eb82ff87SDaniel Beauregard } 1001eb82ff87SDaniel Beauregard } 1002eb82ff87SDaniel Beauregard 1003eb82ff87SDaniel Beauregard return (ret); 1004eb82ff87SDaniel Beauregard } 1005eb82ff87SDaniel Beauregard 1006eb82ff87SDaniel Beauregard static uint32_t 1007eb82ff87SDaniel Beauregard ql_8021_decode_crb_addr(ql_adapter_state_t *ha, uint32_t addr) 1008eb82ff87SDaniel Beauregard { 1009eb82ff87SDaniel Beauregard int i; 1010eb82ff87SDaniel Beauregard uint32_t base_addr, offset, pci_base; 1011eb82ff87SDaniel Beauregard 1012eb82ff87SDaniel Beauregard if (!crb_table_initialized) { 1013eb82ff87SDaniel Beauregard ql_crb_addr_transform_setup(ha); 1014eb82ff87SDaniel Beauregard } 1015eb82ff87SDaniel Beauregard 1016eb82ff87SDaniel Beauregard pci_base = ADDR_ERROR; 1017eb82ff87SDaniel Beauregard base_addr = addr & 0xfff00000; 1018eb82ff87SDaniel Beauregard offset = addr & 0x000fffff; 1019eb82ff87SDaniel Beauregard 1020eb82ff87SDaniel Beauregard for (i = 0; i < MAX_CRB_XFORM; i++) { 1021eb82ff87SDaniel Beauregard if (crb_addr_xform[i] == base_addr) { 1022eb82ff87SDaniel Beauregard pci_base = i << 20; 1023eb82ff87SDaniel Beauregard break; 1024eb82ff87SDaniel Beauregard } 1025eb82ff87SDaniel Beauregard } 1026eb82ff87SDaniel Beauregard if (pci_base == ADDR_ERROR) { 1027eb82ff87SDaniel Beauregard return (pci_base); 1028eb82ff87SDaniel Beauregard } else { 1029eb82ff87SDaniel Beauregard return (pci_base + offset); 1030eb82ff87SDaniel Beauregard } 1031eb82ff87SDaniel Beauregard } 1032eb82ff87SDaniel Beauregard 1033eb82ff87SDaniel Beauregard static int 1034eb82ff87SDaniel Beauregard ql_8021_hw_lock(ql_adapter_state_t *ha, uint32_t timer) 1035eb82ff87SDaniel Beauregard { 1036eb82ff87SDaniel Beauregard uint32_t done = 0, timeout = 0; 1037eb82ff87SDaniel Beauregard 1038eb82ff87SDaniel Beauregard while (!done) { 1039eb82ff87SDaniel Beauregard /* acquire semaphore5 from PCI HW block */ 1040eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM5_LOCK), &done); 1041eb82ff87SDaniel Beauregard if (done == 1) { 1042eb82ff87SDaniel Beauregard break; 1043eb82ff87SDaniel Beauregard } 1044eb82ff87SDaniel Beauregard if (timeout >= timer) { 1045eb82ff87SDaniel Beauregard EL(ha, "timeout\n"); 1046eb82ff87SDaniel Beauregard return (-1); 1047eb82ff87SDaniel Beauregard } 1048eb82ff87SDaniel Beauregard timeout++; 1049eb82ff87SDaniel Beauregard 1050eb82ff87SDaniel Beauregard /* 1051eb82ff87SDaniel Beauregard * Yield CPU 1052eb82ff87SDaniel Beauregard */ 1053eb82ff87SDaniel Beauregard delay(1); 1054eb82ff87SDaniel Beauregard } 1055eb82ff87SDaniel Beauregard 1056eb82ff87SDaniel Beauregard return (0); 1057eb82ff87SDaniel Beauregard } 1058eb82ff87SDaniel Beauregard 1059eb82ff87SDaniel Beauregard static void 1060eb82ff87SDaniel Beauregard ql_8021_hw_unlock(ql_adapter_state_t *ha) 1061eb82ff87SDaniel Beauregard { 1062eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM5_UNLOCK), NULL); 1063eb82ff87SDaniel Beauregard } 1064eb82ff87SDaniel Beauregard 1065eb82ff87SDaniel Beauregard static int 1066eb82ff87SDaniel Beauregard ql_8021_rom_lock(ql_adapter_state_t *ha) 1067eb82ff87SDaniel Beauregard { 1068eb82ff87SDaniel Beauregard uint32_t done = 0, timeout = 0; 1069eb82ff87SDaniel Beauregard 1070eb82ff87SDaniel Beauregard while (!done) { 1071eb82ff87SDaniel Beauregard /* acquire semaphore2 from PCI HW block */ 1072eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM2_LOCK), &done); 1073eb82ff87SDaniel Beauregard if (done == 1) { 1074eb82ff87SDaniel Beauregard break; 1075eb82ff87SDaniel Beauregard } 1076eb82ff87SDaniel Beauregard if (timeout >= ROM_LOCK_TIMEOUT) { 1077eb82ff87SDaniel Beauregard EL(ha, "timeout\n"); 1078eb82ff87SDaniel Beauregard return (-1); 1079eb82ff87SDaniel Beauregard } 1080eb82ff87SDaniel Beauregard timeout++; 1081eb82ff87SDaniel Beauregard 1082eb82ff87SDaniel Beauregard /* 1083eb82ff87SDaniel Beauregard * Yield CPU 1084eb82ff87SDaniel Beauregard */ 1085eb82ff87SDaniel Beauregard delay(1); 1086eb82ff87SDaniel Beauregard } 1087eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROM_LOCK_ID, ROM_LOCK_DRIVER); 1088eb82ff87SDaniel Beauregard 1089eb82ff87SDaniel Beauregard return (0); 1090eb82ff87SDaniel Beauregard } 1091eb82ff87SDaniel Beauregard 1092eb82ff87SDaniel Beauregard static void 1093eb82ff87SDaniel Beauregard ql_8021_rom_unlock(ql_adapter_state_t *ha) 1094eb82ff87SDaniel Beauregard { 1095eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM2_UNLOCK), NULL); 1096eb82ff87SDaniel Beauregard } 1097eb82ff87SDaniel Beauregard 1098eb82ff87SDaniel Beauregard static int 1099eb82ff87SDaniel Beauregard ql_8021_wait_rom_done(ql_adapter_state_t *ha) 1100eb82ff87SDaniel Beauregard { 1101eb82ff87SDaniel Beauregard uint32_t timeout = 0, done = 0; 1102eb82ff87SDaniel Beauregard 1103eb82ff87SDaniel Beauregard while (done == 0) { 1104eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_ROMUSB_GLB_STATUS, &done); 1105eb82ff87SDaniel Beauregard done &= 2; 1106eb82ff87SDaniel Beauregard timeout++; 1107eb82ff87SDaniel Beauregard if (timeout >= ROM_MAX_TIMEOUT) { 1108eb82ff87SDaniel Beauregard EL(ha, "Timeout reached waiting for rom done\n"); 1109eb82ff87SDaniel Beauregard return (-1); 1110eb82ff87SDaniel Beauregard } 1111eb82ff87SDaniel Beauregard } 1112eb82ff87SDaniel Beauregard 1113eb82ff87SDaniel Beauregard return (0); 1114eb82ff87SDaniel Beauregard } 1115eb82ff87SDaniel Beauregard 1116eb82ff87SDaniel Beauregard static int 1117eb82ff87SDaniel Beauregard ql_8021_wait_flash_done(ql_adapter_state_t *ha) 1118eb82ff87SDaniel Beauregard { 1119eb82ff87SDaniel Beauregard clock_t timer; 1120eb82ff87SDaniel Beauregard uint32_t status; 1121eb82ff87SDaniel Beauregard 1122eb82ff87SDaniel Beauregard for (timer = 30 * drv_usectohz(1000000); timer; timer--) { 1123eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0); 1124eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE, 1125eb82ff87SDaniel Beauregard UNM_ROMUSB_ROM_RDSR_INSTR); 1126eb82ff87SDaniel Beauregard if (ql_8021_wait_rom_done(ha)) { 1127eb82ff87SDaniel Beauregard EL(ha, "Error waiting for rom done2\n"); 1128eb82ff87SDaniel Beauregard return (-1); 1129eb82ff87SDaniel Beauregard } 1130eb82ff87SDaniel Beauregard 1131eb82ff87SDaniel Beauregard /* Get status. */ 1132eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_ROMUSB_ROM_RDATA, &status); 1133eb82ff87SDaniel Beauregard if (!(status & BIT_0)) { 1134eb82ff87SDaniel Beauregard return (0); 1135eb82ff87SDaniel Beauregard } 1136eb82ff87SDaniel Beauregard delay(1); 1137eb82ff87SDaniel Beauregard } 1138eb82ff87SDaniel Beauregard 1139eb82ff87SDaniel Beauregard EL(ha, "timeout status=%x\n", status); 1140eb82ff87SDaniel Beauregard return (-1); 1141eb82ff87SDaniel Beauregard } 1142eb82ff87SDaniel Beauregard 1143eb82ff87SDaniel Beauregard static int 1144eb82ff87SDaniel Beauregard ql_8021_do_rom_fast_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *valp) 1145eb82ff87SDaniel Beauregard { 1146eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr); 1147eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); 1148eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3); 1149eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE, 1150eb82ff87SDaniel Beauregard UNM_ROMUSB_ROM_FAST_RD_INSTR); 1151eb82ff87SDaniel Beauregard if (ql_8021_wait_rom_done(ha)) { 1152eb82ff87SDaniel Beauregard EL(ha, "Error waiting for rom done\n"); 1153eb82ff87SDaniel Beauregard return (-1); 1154eb82ff87SDaniel Beauregard } 1155eb82ff87SDaniel Beauregard /* reset abyte_cnt and dummy_byte_cnt */ 1156eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); 1157eb82ff87SDaniel Beauregard drv_usecwait(10); 1158eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0); 1159eb82ff87SDaniel Beauregard 1160eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_ROMUSB_ROM_RDATA, valp); 1161eb82ff87SDaniel Beauregard 1162eb82ff87SDaniel Beauregard return (0); 1163eb82ff87SDaniel Beauregard } 1164eb82ff87SDaniel Beauregard 1165eb82ff87SDaniel Beauregard int 1166eb82ff87SDaniel Beauregard ql_8021_rom_fast_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *valp) 1167eb82ff87SDaniel Beauregard { 1168eb82ff87SDaniel Beauregard int ret, loops = 0; 1169eb82ff87SDaniel Beauregard 1170eb82ff87SDaniel Beauregard while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) { 1171eb82ff87SDaniel Beauregard drv_usecwait(100); 1172eb82ff87SDaniel Beauregard loops++; 1173eb82ff87SDaniel Beauregard } 1174eb82ff87SDaniel Beauregard if (loops >= 50000) { 1175eb82ff87SDaniel Beauregard EL(ha, "rom_lock failed\n"); 1176eb82ff87SDaniel Beauregard return (-1); 1177eb82ff87SDaniel Beauregard } 1178eb82ff87SDaniel Beauregard ret = ql_8021_do_rom_fast_read(ha, addr, valp); 1179eb82ff87SDaniel Beauregard ql_8021_rom_unlock(ha); 1180eb82ff87SDaniel Beauregard 1181eb82ff87SDaniel Beauregard return (ret); 1182eb82ff87SDaniel Beauregard } 1183eb82ff87SDaniel Beauregard 1184eb82ff87SDaniel Beauregard static int 1185eb82ff87SDaniel Beauregard ql_8021_do_rom_write(ql_adapter_state_t *ha, uint32_t addr, uint32_t data) 1186eb82ff87SDaniel Beauregard { 1187eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0); 1188eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE, 1189eb82ff87SDaniel Beauregard UNM_ROMUSB_ROM_WREN_INSTR); 1190eb82ff87SDaniel Beauregard if (ql_8021_wait_rom_done(ha)) { 1191eb82ff87SDaniel Beauregard EL(ha, "Error waiting for rom done\n"); 1192eb82ff87SDaniel Beauregard return (-1); 1193eb82ff87SDaniel Beauregard } 1194eb82ff87SDaniel Beauregard 1195eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_WDATA, data); 1196eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr); 1197eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3); 1198eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE, 1199eb82ff87SDaniel Beauregard UNM_ROMUSB_ROM_PP_INSTR); 1200eb82ff87SDaniel Beauregard if (ql_8021_wait_rom_done(ha)) { 1201eb82ff87SDaniel Beauregard EL(ha, "Error waiting for rom done1\n"); 1202eb82ff87SDaniel Beauregard return (-1); 1203eb82ff87SDaniel Beauregard } 1204eb82ff87SDaniel Beauregard 1205eb82ff87SDaniel Beauregard if (ql_8021_wait_flash_done(ha)) { 1206eb82ff87SDaniel Beauregard EL(ha, "Error waiting for flash done\n"); 1207eb82ff87SDaniel Beauregard return (-1); 1208eb82ff87SDaniel Beauregard } 1209eb82ff87SDaniel Beauregard 1210eb82ff87SDaniel Beauregard return (0); 1211eb82ff87SDaniel Beauregard } 1212eb82ff87SDaniel Beauregard 1213eb82ff87SDaniel Beauregard static int 1214eb82ff87SDaniel Beauregard ql_8021_do_rom_erase(ql_adapter_state_t *ha, uint32_t addr) 1215eb82ff87SDaniel Beauregard { 1216eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0); 1217eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE, 1218eb82ff87SDaniel Beauregard UNM_ROMUSB_ROM_WREN_INSTR); 1219eb82ff87SDaniel Beauregard if (ql_8021_wait_rom_done(ha)) { 1220eb82ff87SDaniel Beauregard EL(ha, "Error waiting for rom done\n"); 1221eb82ff87SDaniel Beauregard return (-1); 1222eb82ff87SDaniel Beauregard } 1223eb82ff87SDaniel Beauregard 1224eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr); 1225eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 3); 1226eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE, 1227eb82ff87SDaniel Beauregard UNM_ROMUSB_ROM_SE_INSTR); 1228eb82ff87SDaniel Beauregard if (ql_8021_wait_rom_done(ha)) { 1229eb82ff87SDaniel Beauregard EL(ha, "Error waiting for rom done1\n"); 1230eb82ff87SDaniel Beauregard return (-1); 1231eb82ff87SDaniel Beauregard } 1232eb82ff87SDaniel Beauregard 1233eb82ff87SDaniel Beauregard if (ql_8021_wait_flash_done(ha)) { 1234eb82ff87SDaniel Beauregard EL(ha, "Error waiting for flash done\n"); 1235eb82ff87SDaniel Beauregard return (-1); 1236eb82ff87SDaniel Beauregard } 1237eb82ff87SDaniel Beauregard 1238eb82ff87SDaniel Beauregard return (0); 1239eb82ff87SDaniel Beauregard } 1240eb82ff87SDaniel Beauregard 1241eb82ff87SDaniel Beauregard int 1242eb82ff87SDaniel Beauregard ql_8021_rom_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *bp) 1243eb82ff87SDaniel Beauregard { 1244eb82ff87SDaniel Beauregard int ret; 1245eb82ff87SDaniel Beauregard 1246eb82ff87SDaniel Beauregard ret = ql_8021_rom_fast_read(ha, addr << 2, bp) == 0 ? QL_SUCCESS : 1247eb82ff87SDaniel Beauregard QL_FUNCTION_FAILED; 1248eb82ff87SDaniel Beauregard 1249eb82ff87SDaniel Beauregard return (ret); 1250eb82ff87SDaniel Beauregard } 1251eb82ff87SDaniel Beauregard 1252eb82ff87SDaniel Beauregard int 1253eb82ff87SDaniel Beauregard ql_8021_rom_write(ql_adapter_state_t *ha, uint32_t addr, uint32_t data) 1254eb82ff87SDaniel Beauregard { 1255eb82ff87SDaniel Beauregard int ret, loops = 0; 1256eb82ff87SDaniel Beauregard 1257eb82ff87SDaniel Beauregard while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) { 1258eb82ff87SDaniel Beauregard drv_usecwait(100); 1259eb82ff87SDaniel Beauregard loops++; 1260eb82ff87SDaniel Beauregard } 1261eb82ff87SDaniel Beauregard if (loops >= 50000) { 1262eb82ff87SDaniel Beauregard EL(ha, "rom_lock failed\n"); 1263eb82ff87SDaniel Beauregard ret = QL_FUNCTION_TIMEOUT; 1264eb82ff87SDaniel Beauregard } else { 1265eb82ff87SDaniel Beauregard ret = ql_8021_do_rom_write(ha, addr << 2, data) == 0 ? 1266eb82ff87SDaniel Beauregard QL_SUCCESS : QL_FUNCTION_FAILED; 1267eb82ff87SDaniel Beauregard ql_8021_rom_unlock(ha); 1268eb82ff87SDaniel Beauregard } 1269eb82ff87SDaniel Beauregard 1270eb82ff87SDaniel Beauregard return (ret); 1271eb82ff87SDaniel Beauregard } 1272eb82ff87SDaniel Beauregard 1273eb82ff87SDaniel Beauregard int 1274eb82ff87SDaniel Beauregard ql_8021_rom_erase(ql_adapter_state_t *ha, uint32_t addr) 1275eb82ff87SDaniel Beauregard { 1276eb82ff87SDaniel Beauregard int ret, loops = 0; 1277eb82ff87SDaniel Beauregard 1278eb82ff87SDaniel Beauregard while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) { 1279eb82ff87SDaniel Beauregard drv_usecwait(100); 1280eb82ff87SDaniel Beauregard loops++; 1281eb82ff87SDaniel Beauregard } 1282eb82ff87SDaniel Beauregard if (loops >= 50000) { 1283eb82ff87SDaniel Beauregard EL(ha, "rom_lock failed\n"); 1284eb82ff87SDaniel Beauregard ret = QL_FUNCTION_TIMEOUT; 1285eb82ff87SDaniel Beauregard } else { 1286eb82ff87SDaniel Beauregard ret = ql_8021_do_rom_erase(ha, addr << 2) == 0 ? QL_SUCCESS : 1287eb82ff87SDaniel Beauregard QL_FUNCTION_FAILED; 1288eb82ff87SDaniel Beauregard ql_8021_rom_unlock(ha); 1289eb82ff87SDaniel Beauregard } 1290eb82ff87SDaniel Beauregard 1291eb82ff87SDaniel Beauregard return (ret); 1292eb82ff87SDaniel Beauregard } 1293eb82ff87SDaniel Beauregard 1294eb82ff87SDaniel Beauregard int 1295eb82ff87SDaniel Beauregard ql_8021_rom_wrsr(ql_adapter_state_t *ha, uint32_t data) 1296eb82ff87SDaniel Beauregard { 1297eb82ff87SDaniel Beauregard int ret = QL_SUCCESS, loops = 0; 1298eb82ff87SDaniel Beauregard 1299eb82ff87SDaniel Beauregard while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) { 1300eb82ff87SDaniel Beauregard drv_usecwait(100); 1301eb82ff87SDaniel Beauregard loops++; 1302eb82ff87SDaniel Beauregard } 1303eb82ff87SDaniel Beauregard if (loops >= 50000) { 1304eb82ff87SDaniel Beauregard EL(ha, "rom_lock failed\n"); 1305eb82ff87SDaniel Beauregard ret = QL_FUNCTION_TIMEOUT; 1306eb82ff87SDaniel Beauregard } else { 1307eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0); 1308eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE, 1309eb82ff87SDaniel Beauregard UNM_ROMUSB_ROM_WREN_INSTR); 1310eb82ff87SDaniel Beauregard if (ql_8021_wait_rom_done(ha)) { 1311eb82ff87SDaniel Beauregard EL(ha, "Error waiting for rom done\n"); 1312eb82ff87SDaniel Beauregard ret = QL_FUNCTION_FAILED; 1313eb82ff87SDaniel Beauregard } else { 1314eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_WDATA, data); 1315eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0); 1316eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE, 1317eb82ff87SDaniel Beauregard UNM_ROMUSB_ROM_WRSR_INSTR); 1318eb82ff87SDaniel Beauregard if (ql_8021_wait_rom_done(ha)) { 1319eb82ff87SDaniel Beauregard EL(ha, "Error waiting for rom done1\n"); 1320eb82ff87SDaniel Beauregard ret = QL_FUNCTION_FAILED; 1321eb82ff87SDaniel Beauregard } else if (ql_8021_wait_flash_done(ha)) { 1322eb82ff87SDaniel Beauregard EL(ha, "Error waiting for flash done\n"); 1323eb82ff87SDaniel Beauregard ret = QL_FUNCTION_FAILED; 1324eb82ff87SDaniel Beauregard } 1325eb82ff87SDaniel Beauregard } 1326eb82ff87SDaniel Beauregard ql_8021_rom_unlock(ha); 1327eb82ff87SDaniel Beauregard } 1328eb82ff87SDaniel Beauregard 1329eb82ff87SDaniel Beauregard return (ret); 1330eb82ff87SDaniel Beauregard } 1331eb82ff87SDaniel Beauregard 1332eb82ff87SDaniel Beauregard static int 1333eb82ff87SDaniel Beauregard ql_8021_phantom_init(ql_adapter_state_t *ha) 1334eb82ff87SDaniel Beauregard { 1335eb82ff87SDaniel Beauregard uint32_t val = 0, err = 0; 1336eb82ff87SDaniel Beauregard int retries = 60; 1337eb82ff87SDaniel Beauregard 1338eb82ff87SDaniel Beauregard do { 1339eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, CRB_CMDPEG_STATE, &val); 1340eb82ff87SDaniel Beauregard 1341eb82ff87SDaniel Beauregard switch (val) { 1342eb82ff87SDaniel Beauregard case PHAN_INITIALIZE_COMPLETE: 1343eb82ff87SDaniel Beauregard case PHAN_INITIALIZE_ACK: 1344eb82ff87SDaniel Beauregard EL(ha, "success=%xh\n", val); 1345eb82ff87SDaniel Beauregard return (0); 1346eb82ff87SDaniel Beauregard case PHAN_INITIALIZE_FAILED: 1347eb82ff87SDaniel Beauregard EL(ha, "PHAN_INITIALIZE_FAILED\n"); 1348eb82ff87SDaniel Beauregard err = 1; 1349eb82ff87SDaniel Beauregard break; 1350eb82ff87SDaniel Beauregard default: 1351eb82ff87SDaniel Beauregard break; 1352eb82ff87SDaniel Beauregard } 1353eb82ff87SDaniel Beauregard 1354eb82ff87SDaniel Beauregard if (err) { 1355eb82ff87SDaniel Beauregard break; 1356eb82ff87SDaniel Beauregard } 1357eb82ff87SDaniel Beauregard /* 500 msec wait */ 1358eb82ff87SDaniel Beauregard delay(50); 1359eb82ff87SDaniel Beauregard 1360eb82ff87SDaniel Beauregard } while (--retries); 1361eb82ff87SDaniel Beauregard 1362eb82ff87SDaniel Beauregard if (!err) { 1363eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED); 1364eb82ff87SDaniel Beauregard } 1365eb82ff87SDaniel Beauregard 1366eb82ff87SDaniel Beauregard EL(ha, "firmware init failed=%x\n", val); 1367eb82ff87SDaniel Beauregard return (-1); 1368eb82ff87SDaniel Beauregard } 1369eb82ff87SDaniel Beauregard 1370eb82ff87SDaniel Beauregard static int 1371eb82ff87SDaniel Beauregard ql_8021_pinit_from_rom(ql_adapter_state_t *ha) 1372eb82ff87SDaniel Beauregard { 1373eb82ff87SDaniel Beauregard int init_delay = 0; 1374eb82ff87SDaniel Beauregard struct crb_addr_pair *buf; 1375eb82ff87SDaniel Beauregard uint32_t offset, off, i, n, addr, val; 1376eb82ff87SDaniel Beauregard 1377eb82ff87SDaniel Beauregard /* Grab the lock so that no one can read flash when we reset the chip */ 1378eb82ff87SDaniel Beauregard (void) ql_8021_rom_lock(ha); 1379eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, 0xffffffff); 1380eb82ff87SDaniel Beauregard /* Just in case it was held when we reset the chip */ 1381eb82ff87SDaniel Beauregard ql_8021_rom_unlock(ha); 1382eb82ff87SDaniel Beauregard 1383eb82ff87SDaniel Beauregard if (ql_8021_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafe || 1384eb82ff87SDaniel Beauregard ql_8021_rom_fast_read(ha, 4, &n) != 0) { 1385eb82ff87SDaniel Beauregard EL(ha, "ERROR Reading crb_init area: n: %08x\n", n); 1386eb82ff87SDaniel Beauregard return (-1); 1387eb82ff87SDaniel Beauregard } 1388eb82ff87SDaniel Beauregard offset = n & 0xffff; 1389eb82ff87SDaniel Beauregard n = (n >> 16) & 0xffff; 1390eb82ff87SDaniel Beauregard if (n >= 1024) { 1391eb82ff87SDaniel Beauregard EL(ha, "n=0x%x Error! NetXen card flash not initialized\n", n); 1392eb82ff87SDaniel Beauregard return (-1); 1393eb82ff87SDaniel Beauregard } 1394eb82ff87SDaniel Beauregard 1395eb82ff87SDaniel Beauregard buf = kmem_zalloc(n * sizeof (struct crb_addr_pair), KM_SLEEP); 1396eb82ff87SDaniel Beauregard if (buf == NULL) { 1397eb82ff87SDaniel Beauregard EL(ha, "Unable to zalloc memory\n"); 1398eb82ff87SDaniel Beauregard return (-1); 1399eb82ff87SDaniel Beauregard } 1400eb82ff87SDaniel Beauregard 1401eb82ff87SDaniel Beauregard for (i = 0; i < n; i++) { 1402eb82ff87SDaniel Beauregard if (ql_8021_rom_fast_read(ha, 8 * i + 4 * offset, &val) != 0 || 1403eb82ff87SDaniel Beauregard ql_8021_rom_fast_read(ha, 8 * i + 4 * offset + 4, &addr) != 1404eb82ff87SDaniel Beauregard 0) { 1405eb82ff87SDaniel Beauregard kmem_free(buf, n * sizeof (struct crb_addr_pair)); 1406eb82ff87SDaniel Beauregard EL(ha, "ql_8021_rom_fast_read != 0 to zalloc memory\n"); 1407eb82ff87SDaniel Beauregard return (-1); 1408eb82ff87SDaniel Beauregard } 1409eb82ff87SDaniel Beauregard 1410eb82ff87SDaniel Beauregard buf[i].addr = addr; 1411eb82ff87SDaniel Beauregard buf[i].data = val; 1412eb82ff87SDaniel Beauregard } 1413eb82ff87SDaniel Beauregard 1414eb82ff87SDaniel Beauregard for (i = 0; i < n; i++) { 1415eb82ff87SDaniel Beauregard off = ql_8021_decode_crb_addr(ha, buf[i].addr); 1416eb82ff87SDaniel Beauregard if (off == ADDR_ERROR) { 1417eb82ff87SDaniel Beauregard EL(ha, "Err: Unknown addr: 0x%lx\n", buf[i].addr); 1418eb82ff87SDaniel Beauregard continue; 1419eb82ff87SDaniel Beauregard } 1420eb82ff87SDaniel Beauregard off += UNM_PCI_CRBSPACE; 1421eb82ff87SDaniel Beauregard 1422eb82ff87SDaniel Beauregard if (off & 1) { 1423eb82ff87SDaniel Beauregard continue; 1424eb82ff87SDaniel Beauregard } 1425eb82ff87SDaniel Beauregard 1426eb82ff87SDaniel Beauregard /* skipping cold reboot MAGIC */ 1427eb82ff87SDaniel Beauregard if (off == UNM_RAM_COLD_BOOT) { 1428eb82ff87SDaniel Beauregard continue; 1429eb82ff87SDaniel Beauregard } 1430eb82ff87SDaniel Beauregard if (off == (UNM_CRB_I2C0 + 0x1c)) { 1431eb82ff87SDaniel Beauregard continue; 1432eb82ff87SDaniel Beauregard } 1433eb82ff87SDaniel Beauregard /* do not reset PCI */ 1434eb82ff87SDaniel Beauregard if (off == (ROMUSB_GLB + 0xbc)) { 1435eb82ff87SDaniel Beauregard continue; 1436eb82ff87SDaniel Beauregard } 1437eb82ff87SDaniel Beauregard if (off == (ROMUSB_GLB + 0xa8)) { 1438eb82ff87SDaniel Beauregard continue; 1439eb82ff87SDaniel Beauregard } 1440eb82ff87SDaniel Beauregard if (off == (ROMUSB_GLB + 0xc8)) { /* core clock */ 1441eb82ff87SDaniel Beauregard continue; 1442eb82ff87SDaniel Beauregard } 1443eb82ff87SDaniel Beauregard if (off == (ROMUSB_GLB + 0x24)) { /* MN clock */ 1444eb82ff87SDaniel Beauregard continue; 1445eb82ff87SDaniel Beauregard } 1446eb82ff87SDaniel Beauregard if (off == (ROMUSB_GLB + 0x1c)) { /* MS clock */ 1447eb82ff87SDaniel Beauregard continue; 1448eb82ff87SDaniel Beauregard } 1449eb82ff87SDaniel Beauregard if ((off & 0x0ff00000) == UNM_CRB_DDR_NET) { 1450eb82ff87SDaniel Beauregard continue; 1451eb82ff87SDaniel Beauregard } 1452eb82ff87SDaniel Beauregard if (off == (UNM_CRB_PEG_NET_1 + 0x18) && 1453eb82ff87SDaniel Beauregard !NX_IS_REVISION_P3PLUS(ha->rev_id)) { 1454eb82ff87SDaniel Beauregard buf[i].data = 0x1020; 1455eb82ff87SDaniel Beauregard } 1456eb82ff87SDaniel Beauregard /* skip the function enable register */ 1457eb82ff87SDaniel Beauregard if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION)) { 1458eb82ff87SDaniel Beauregard continue; 1459eb82ff87SDaniel Beauregard } 1460eb82ff87SDaniel Beauregard if (off == UNM_PCIE_REG(PCIE_SETUP_FUNCTION2)) { 1461eb82ff87SDaniel Beauregard continue; 1462eb82ff87SDaniel Beauregard } 1463eb82ff87SDaniel Beauregard if ((off & 0x0ff00000) == UNM_CRB_SMB) { 1464eb82ff87SDaniel Beauregard continue; 1465eb82ff87SDaniel Beauregard } 1466eb82ff87SDaniel Beauregard 1467eb82ff87SDaniel Beauregard /* After writing this register, HW needs time for CRB */ 1468eb82ff87SDaniel Beauregard /* to quiet down (else crb_window returns 0xffffffff) */ 1469eb82ff87SDaniel Beauregard init_delay = 1; 1470eb82ff87SDaniel Beauregard if (off == UNM_ROMUSB_GLB_SW_RESET) { 1471eb82ff87SDaniel Beauregard init_delay = 100; /* Sleep 1000 msecs */ 1472eb82ff87SDaniel Beauregard } 1473eb82ff87SDaniel Beauregard 1474eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, off, buf[i].data); 1475eb82ff87SDaniel Beauregard 1476eb82ff87SDaniel Beauregard delay(init_delay); 1477eb82ff87SDaniel Beauregard } 1478eb82ff87SDaniel Beauregard kmem_free(buf, n * sizeof (struct crb_addr_pair)); 1479eb82ff87SDaniel Beauregard 1480eb82ff87SDaniel Beauregard /* disable_peg_cache_all */ 1481eb82ff87SDaniel Beauregard 1482eb82ff87SDaniel Beauregard /* p2dn replyCount */ 1483eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_D + 0xec, 0x1e); 1484eb82ff87SDaniel Beauregard /* disable_peg_cache 0 */ 1485eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_D + 0x4c, 8); 1486eb82ff87SDaniel Beauregard /* disable_peg_cache 1 */ 1487eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_I + 0x4c, 8); 1488eb82ff87SDaniel Beauregard 1489eb82ff87SDaniel Beauregard /* peg_clr_all */ 1490eb82ff87SDaniel Beauregard /* peg_clr 0 */ 1491eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0x8, 0); 1492eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0xc, 0); 1493eb82ff87SDaniel Beauregard /* peg_clr 1 */ 1494eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_1 + 0x8, 0); 1495eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_1 + 0xc, 0); 1496eb82ff87SDaniel Beauregard /* peg_clr 2 */ 1497eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_2 + 0x8, 0); 1498eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_2 + 0xc, 0); 1499eb82ff87SDaniel Beauregard /* peg_clr 3 */ 1500eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_3 + 0x8, 0); 1501eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_3 + 0xc, 0); 1502eb82ff87SDaniel Beauregard 1503eb82ff87SDaniel Beauregard return (0); 1504eb82ff87SDaniel Beauregard } 1505eb82ff87SDaniel Beauregard 1506eb82ff87SDaniel Beauregard static int 1507eb82ff87SDaniel Beauregard ql_8021_load_from_flash(ql_adapter_state_t *ha) 1508eb82ff87SDaniel Beauregard { 1509eb82ff87SDaniel Beauregard int i; 1510eb82ff87SDaniel Beauregard uint32_t flashaddr, memaddr; 1511eb82ff87SDaniel Beauregard uint32_t high, low, size; 1512eb82ff87SDaniel Beauregard uint64_t data; 1513eb82ff87SDaniel Beauregard 1514eb82ff87SDaniel Beauregard size = ha->bootloader_size / 2; 1515eb82ff87SDaniel Beauregard flashaddr = ha->bootloader_addr << 2; 1516eb82ff87SDaniel Beauregard memaddr = BOOTLD_START; 1517eb82ff87SDaniel Beauregard 1518eb82ff87SDaniel Beauregard for (i = 0; i < size; i++) { 1519eb82ff87SDaniel Beauregard if ((ql_8021_rom_fast_read(ha, flashaddr, &low)) || 1520eb82ff87SDaniel Beauregard (ql_8021_rom_fast_read(ha, flashaddr + 4, &high))) { 1521eb82ff87SDaniel Beauregard EL(ha, "ql_8021_rom_fast_read != 0\n"); 1522eb82ff87SDaniel Beauregard return (-1); 1523eb82ff87SDaniel Beauregard } 1524eb82ff87SDaniel Beauregard data = ((uint64_t)high << 32) | low; 1525eb82ff87SDaniel Beauregard (void) ql_8021_pci_mem_write_2M(ha, memaddr, &data, 8); 1526eb82ff87SDaniel Beauregard flashaddr += 8; 1527eb82ff87SDaniel Beauregard memaddr += 8; 1528eb82ff87SDaniel Beauregard } 1529eb82ff87SDaniel Beauregard 1530eb82ff87SDaniel Beauregard size = ha->flash_fw_size / 2; 1531eb82ff87SDaniel Beauregard flashaddr = ha->flash_fw_addr << 2; 1532eb82ff87SDaniel Beauregard memaddr = IMAGE_START; 1533eb82ff87SDaniel Beauregard 1534eb82ff87SDaniel Beauregard for (i = 0; i < size; i++) { 1535eb82ff87SDaniel Beauregard if ((ql_8021_rom_fast_read(ha, flashaddr, &low)) || 1536eb82ff87SDaniel Beauregard (ql_8021_rom_fast_read(ha, flashaddr + 4, &high))) { 1537eb82ff87SDaniel Beauregard EL(ha, "ql_8021_rom_fast_read3 != 0\n"); 1538eb82ff87SDaniel Beauregard return (-1); 1539eb82ff87SDaniel Beauregard } 1540eb82ff87SDaniel Beauregard data = ((uint64_t)high << 32) | low; 1541eb82ff87SDaniel Beauregard (void) ql_8021_pci_mem_write_2M(ha, memaddr, &data, 8); 1542eb82ff87SDaniel Beauregard flashaddr += 8; 1543eb82ff87SDaniel Beauregard memaddr += 8; 1544eb82ff87SDaniel Beauregard } 1545eb82ff87SDaniel Beauregard 1546eb82ff87SDaniel Beauregard return (0); 1547eb82ff87SDaniel Beauregard } 1548eb82ff87SDaniel Beauregard 1549eb82ff87SDaniel Beauregard static int 1550eb82ff87SDaniel Beauregard ql_8021_load_firmware(ql_adapter_state_t *ha) 1551eb82ff87SDaniel Beauregard { 1552eb82ff87SDaniel Beauregard uint64_t data; 1553eb82ff87SDaniel Beauregard uint32_t i, flashaddr, size; 1554eb82ff87SDaniel Beauregard uint8_t *bp, n, *dp; 1555eb82ff87SDaniel Beauregard 1556eb82ff87SDaniel Beauregard bp = (uint8_t *)(ha->risc_fw[0].code); 1557eb82ff87SDaniel Beauregard dp = (uint8_t *)&size; 1558eb82ff87SDaniel Beauregard for (n = 0; n < 4; n++) { 1559eb82ff87SDaniel Beauregard dp[n] = *bp++; 1560eb82ff87SDaniel Beauregard } 1561eb82ff87SDaniel Beauregard LITTLE_ENDIAN_32(&size); 1562eb82ff87SDaniel Beauregard EL(ha, "signature=%x\n", size); 1563eb82ff87SDaniel Beauregard 1564eb82ff87SDaniel Beauregard size = (IMAGE_START - BOOTLD_START) / 8; 1565eb82ff87SDaniel Beauregard 1566eb82ff87SDaniel Beauregard bp = (uint8_t *)(ha->risc_fw[0].code + BOOTLD_START); 1567eb82ff87SDaniel Beauregard flashaddr = BOOTLD_START; 1568eb82ff87SDaniel Beauregard 1569eb82ff87SDaniel Beauregard dp = (uint8_t *)&data; 1570eb82ff87SDaniel Beauregard for (i = 0; i < size; i++) { 1571eb82ff87SDaniel Beauregard for (n = 0; n < 8; n++) { 1572eb82ff87SDaniel Beauregard dp[n] = *bp++; 1573eb82ff87SDaniel Beauregard } 1574eb82ff87SDaniel Beauregard LITTLE_ENDIAN_64(&data); 1575eb82ff87SDaniel Beauregard (void) ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8); 1576eb82ff87SDaniel Beauregard flashaddr += 8; 1577eb82ff87SDaniel Beauregard } 1578eb82ff87SDaniel Beauregard 1579eb82ff87SDaniel Beauregard bp = (uint8_t *)(ha->risc_fw[0].code + FW_SIZE_OFFSET); 1580eb82ff87SDaniel Beauregard dp = (uint8_t *)&size; 1581eb82ff87SDaniel Beauregard for (n = 0; n < 4; n++) { 1582eb82ff87SDaniel Beauregard dp[n] = *bp++; 1583eb82ff87SDaniel Beauregard } 1584eb82ff87SDaniel Beauregard LITTLE_ENDIAN_32(&size); 1585eb82ff87SDaniel Beauregard EL(ha, "IMAGE_START size=%llx\n", size); 1586eb82ff87SDaniel Beauregard size = (size + 7) / 8; 1587eb82ff87SDaniel Beauregard 1588eb82ff87SDaniel Beauregard bp = (uint8_t *)(ha->risc_fw[0].code + IMAGE_START); 1589eb82ff87SDaniel Beauregard flashaddr = IMAGE_START; 1590eb82ff87SDaniel Beauregard 1591eb82ff87SDaniel Beauregard dp = (uint8_t *)&data; 1592eb82ff87SDaniel Beauregard for (i = 0; i < size; i++) { 1593eb82ff87SDaniel Beauregard for (n = 0; n < 8; n++) { 1594eb82ff87SDaniel Beauregard dp[n] = *bp++; 1595eb82ff87SDaniel Beauregard } 1596eb82ff87SDaniel Beauregard LITTLE_ENDIAN_64(&data); 1597eb82ff87SDaniel Beauregard (void) ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8); 1598eb82ff87SDaniel Beauregard flashaddr += 8; 1599eb82ff87SDaniel Beauregard } 1600eb82ff87SDaniel Beauregard 1601eb82ff87SDaniel Beauregard return (0); 1602eb82ff87SDaniel Beauregard } 1603eb82ff87SDaniel Beauregard 1604eb82ff87SDaniel Beauregard static int 1605eb82ff87SDaniel Beauregard ql_8021_init_p3p(ql_adapter_state_t *ha) 1606eb82ff87SDaniel Beauregard { 1607eb82ff87SDaniel Beauregard uint32_t data; 1608eb82ff87SDaniel Beauregard 1609eb82ff87SDaniel Beauregard /* ??? */ 1610eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_PORT_MODE_ADDR, UNM_PORT_MODE_AUTO_NEG); 1611eb82ff87SDaniel Beauregard delay(drv_usectohz(1000000)); 1612eb82ff87SDaniel Beauregard 1613eb82ff87SDaniel Beauregard /* CAM RAM Cold Boot Register */ 1614eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_RAM_COLD_BOOT, &data); 1615eb82ff87SDaniel Beauregard if (data == 0x55555555) { 1616eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_ROMUSB_GLB_SW_RESET, &data); 1617eb82ff87SDaniel Beauregard if (data != 0x80000f) { 1618eb82ff87SDaniel Beauregard EL(ha, "CRB_UNM_GLB_SW_RST=%x exit\n", data); 1619eb82ff87SDaniel Beauregard return (-1); 1620eb82ff87SDaniel Beauregard } 1621eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_RAM_COLD_BOOT, 0); 1622eb82ff87SDaniel Beauregard } 1623eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_ROMUSB_GLB_PEGTUNE_DONE, &data); 1624eb82ff87SDaniel Beauregard data |= 1; 1625eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_GLB_PEGTUNE_DONE, data); 1626eb82ff87SDaniel Beauregard 1627eb82ff87SDaniel Beauregard /* 1628eb82ff87SDaniel Beauregard * ??? 1629eb82ff87SDaniel Beauregard * data = ha->pci_bus_addr | BIT_31; 1630eb82ff87SDaniel Beauregard * ql_8021_wr_32(ha, UNM_BUS_DEV_NO, data); 1631eb82ff87SDaniel Beauregard */ 1632eb82ff87SDaniel Beauregard 1633eb82ff87SDaniel Beauregard return (0); 1634eb82ff87SDaniel Beauregard } 1635eb82ff87SDaniel Beauregard 1636eb82ff87SDaniel Beauregard /* ARGSUSED */ 1637eb82ff87SDaniel Beauregard void 1638eb82ff87SDaniel Beauregard ql_8021_reset_chip(ql_adapter_state_t *ha) 1639eb82ff87SDaniel Beauregard { 1640*f885d00fSDaniel Beauregard /* 1641*f885d00fSDaniel Beauregard * Disable interrupts does not work on a per function bases 1642*f885d00fSDaniel Beauregard * leave them enabled 1643*f885d00fSDaniel Beauregard */ 1644eb82ff87SDaniel Beauregard ql_8021_enable_intrs(ha); 1645eb82ff87SDaniel Beauregard 1646eb82ff87SDaniel Beauregard ADAPTER_STATE_LOCK(ha); 1647eb82ff87SDaniel Beauregard ha->flags |= INTERRUPTS_ENABLED; 1648eb82ff87SDaniel Beauregard ADAPTER_STATE_UNLOCK(ha); 1649*f885d00fSDaniel Beauregard 1650*f885d00fSDaniel Beauregard (void) ql_stop_firmware(ha); 1651eb82ff87SDaniel Beauregard } 1652eb82ff87SDaniel Beauregard 1653eb82ff87SDaniel Beauregard static int 1654eb82ff87SDaniel Beauregard ql_8021_reset_hw(ql_adapter_state_t *ha, int type) 1655eb82ff87SDaniel Beauregard { 1656eb82ff87SDaniel Beauregard int ret; 1657eb82ff87SDaniel Beauregard uint32_t rst; 1658eb82ff87SDaniel Beauregard 1659eb82ff87SDaniel Beauregard /* scrub dma mask expansion register */ 1660eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_DMA_SHIFT, 0x55555555); 1661eb82ff87SDaniel Beauregard 1662eb82ff87SDaniel Beauregard /* Overwrite stale initialization register values */ 1663eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_CMDPEG_STATE, 0); 1664eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_RCVPEG_STATE, 0); 1665eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS1, 0); 1666eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS2, 0); 1667eb82ff87SDaniel Beauregard 1668eb82ff87SDaniel Beauregard (void) ql_8021_pinit_from_rom(ha); 1669eb82ff87SDaniel Beauregard delay(1); 1670eb82ff87SDaniel Beauregard 1671eb82ff87SDaniel Beauregard /* Bring QM and CAMRAM out of reset */ 1672eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_ROMUSB_GLB_SW_RESET, &rst); 1673eb82ff87SDaniel Beauregard rst &= ~((1 << 28) | (1 << 24)); 1674eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, rst); 1675eb82ff87SDaniel Beauregard 1676eb82ff87SDaniel Beauregard switch (type) { 1677eb82ff87SDaniel Beauregard case 0: 1678eb82ff87SDaniel Beauregard ret = ql_8021_init_p3p(ha); 1679eb82ff87SDaniel Beauregard break; 1680eb82ff87SDaniel Beauregard case 1: 1681eb82ff87SDaniel Beauregard ret = ql_8021_load_from_flash(ha); 1682eb82ff87SDaniel Beauregard break; 1683eb82ff87SDaniel Beauregard case 2: 1684eb82ff87SDaniel Beauregard ret = ql_8021_load_firmware(ha); 1685eb82ff87SDaniel Beauregard break; 1686eb82ff87SDaniel Beauregard } 1687eb82ff87SDaniel Beauregard delay(1); 1688eb82ff87SDaniel Beauregard 1689eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0x18, 0x1020); 1690eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, 0x80001e); 1691eb82ff87SDaniel Beauregard 1692eb82ff87SDaniel Beauregard if (ret) { 1693eb82ff87SDaniel Beauregard EL(ha, "type=%d, ret=%d\n", type, ret); 1694eb82ff87SDaniel Beauregard } else { 1695eb82ff87SDaniel Beauregard ret = ql_8021_phantom_init(ha); 1696eb82ff87SDaniel Beauregard } 1697eb82ff87SDaniel Beauregard return (ret); 1698eb82ff87SDaniel Beauregard } 1699eb82ff87SDaniel Beauregard 1700eb82ff87SDaniel Beauregard int 1701eb82ff87SDaniel Beauregard ql_8021_load_risc(ql_adapter_state_t *ha) 1702eb82ff87SDaniel Beauregard { 1703eb82ff87SDaniel Beauregard int rv = 0; 1704eb82ff87SDaniel Beauregard static int ql_8021_fw_loaded = 0; 1705eb82ff87SDaniel Beauregard 1706eb82ff87SDaniel Beauregard GLOBAL_HW_LOCK(); 1707eb82ff87SDaniel Beauregard if (!ql_8021_fw_loaded) { 1708eb82ff87SDaniel Beauregard if (ha->risc_fw[0].code) { 1709eb82ff87SDaniel Beauregard EL(ha, "from driver\n"); 1710eb82ff87SDaniel Beauregard rv = ql_8021_reset_hw(ha, 2); 1711eb82ff87SDaniel Beauregard } else { 1712eb82ff87SDaniel Beauregard /* 1713eb82ff87SDaniel Beauregard * BIOS method 1714eb82ff87SDaniel Beauregard * ql_8021_reset_hw(ha, 0) 1715eb82ff87SDaniel Beauregard */ 1716eb82ff87SDaniel Beauregard EL(ha, "from flash\n"); 1717eb82ff87SDaniel Beauregard rv = ql_8021_reset_hw(ha, 1); 1718eb82ff87SDaniel Beauregard } 1719eb82ff87SDaniel Beauregard if (rv == 0) { 1720eb82ff87SDaniel Beauregard ql_8021_fw_loaded = 1; 1721eb82ff87SDaniel Beauregard 1722eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_DMA_SHIFT, 0x55555555); 1723eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS1, 0x0); 1724eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS2, 0x0); 1725eb82ff87SDaniel Beauregard 1726eb82ff87SDaniel Beauregard GLOBAL_HW_UNLOCK(); 1727eb82ff87SDaniel Beauregard 1728eb82ff87SDaniel Beauregard ADAPTER_STATE_LOCK(ha); 1729eb82ff87SDaniel Beauregard ha->flags &= ~INTERRUPTS_ENABLED; 1730eb82ff87SDaniel Beauregard ADAPTER_STATE_UNLOCK(ha); 1731eb82ff87SDaniel Beauregard 1732eb82ff87SDaniel Beauregard (void) ql_8021_enable_intrs(ha); 1733eb82ff87SDaniel Beauregard 1734eb82ff87SDaniel Beauregard ADAPTER_STATE_LOCK(ha); 1735eb82ff87SDaniel Beauregard ha->flags |= INTERRUPTS_ENABLED; 1736eb82ff87SDaniel Beauregard ADAPTER_STATE_UNLOCK(ha); 1737eb82ff87SDaniel Beauregard } else { 1738eb82ff87SDaniel Beauregard GLOBAL_HW_UNLOCK(); 1739eb82ff87SDaniel Beauregard } 1740eb82ff87SDaniel Beauregard } else { 1741eb82ff87SDaniel Beauregard GLOBAL_HW_UNLOCK(); 1742eb82ff87SDaniel Beauregard EL(ha, "Firmware loaded by other function\n"); 1743eb82ff87SDaniel Beauregard } 1744eb82ff87SDaniel Beauregard 1745eb82ff87SDaniel Beauregard if (rv == 0) { 1746eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_FW_VERSION_MAJOR, &ha->fw_major_version); 1747eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_FW_VERSION_MINOR, &ha->fw_minor_version); 1748eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_FW_VERSION_SUB, &ha->fw_subminor_version); 1749eb82ff87SDaniel Beauregard EL(ha, "fw v%d.%02d.%02d\n", ha->fw_major_version, 1750eb82ff87SDaniel Beauregard ha->fw_minor_version, ha->fw_subminor_version); 1751eb82ff87SDaniel Beauregard } else { 1752eb82ff87SDaniel Beauregard EL(ha, "status = -1\n"); 1753eb82ff87SDaniel Beauregard return (QL_FUNCTION_FAILED); 1754eb82ff87SDaniel Beauregard } 1755eb82ff87SDaniel Beauregard 1756eb82ff87SDaniel Beauregard return (QL_SUCCESS); 1757eb82ff87SDaniel Beauregard } 1758eb82ff87SDaniel Beauregard 1759eb82ff87SDaniel Beauregard void 1760eb82ff87SDaniel Beauregard ql_8021_clr_hw_intr(ql_adapter_state_t *ha) 1761eb82ff87SDaniel Beauregard { 1762eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff); 1763eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, ISR_INT_VECTOR, NULL); 1764eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, ISR_INT_VECTOR, NULL); 1765eb82ff87SDaniel Beauregard } 1766eb82ff87SDaniel Beauregard 1767eb82ff87SDaniel Beauregard void 1768eb82ff87SDaniel Beauregard ql_8021_clr_fw_intr(ql_adapter_state_t *ha) 1769eb82ff87SDaniel Beauregard { 1770eb82ff87SDaniel Beauregard WRT32_IO_REG(ha, nx_risc_int, 0); 1771eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xfbff); 1772eb82ff87SDaniel Beauregard } 1773eb82ff87SDaniel Beauregard 1774eb82ff87SDaniel Beauregard void 1775eb82ff87SDaniel Beauregard ql_8021_enable_intrs(ql_adapter_state_t *ha) 1776eb82ff87SDaniel Beauregard { 1777eb82ff87SDaniel Beauregard GLOBAL_HW_LOCK(); 1778eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); 1779eb82ff87SDaniel Beauregard GLOBAL_HW_UNLOCK(); 1780eb82ff87SDaniel Beauregard (void) ql_toggle_interrupt(ha, 1); 1781eb82ff87SDaniel Beauregard } 1782eb82ff87SDaniel Beauregard 1783eb82ff87SDaniel Beauregard void 1784eb82ff87SDaniel Beauregard ql_8021_disable_intrs(ql_adapter_state_t *ha) 1785eb82ff87SDaniel Beauregard { 1786eb82ff87SDaniel Beauregard (void) ql_toggle_interrupt(ha, 0); 1787eb82ff87SDaniel Beauregard GLOBAL_HW_LOCK(); 1788eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400); 1789eb82ff87SDaniel Beauregard GLOBAL_HW_UNLOCK(); 1790eb82ff87SDaniel Beauregard } 1791eb82ff87SDaniel Beauregard 1792eb82ff87SDaniel Beauregard void 1793eb82ff87SDaniel Beauregard ql_8021_update_crb_int_ptr(ql_adapter_state_t *ha) 1794eb82ff87SDaniel Beauregard { 1795eb82ff87SDaniel Beauregard struct legacy_intr_set *nx_legacy_intr; 1796eb82ff87SDaniel Beauregard 1797eb82ff87SDaniel Beauregard ha->qdr_sn_window = (uint32_t)-1; 1798eb82ff87SDaniel Beauregard ha->ddr_mn_window = (uint32_t)-1; 1799eb82ff87SDaniel Beauregard nx_legacy_intr = &legacy_intr[ha->function_number]; 1800eb82ff87SDaniel Beauregard 1801eb82ff87SDaniel Beauregard ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit; 1802eb82ff87SDaniel Beauregard ha->nx_legacy_intr.tgt_status_reg = nx_legacy_intr->tgt_status_reg; 1803eb82ff87SDaniel Beauregard ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg; 1804eb82ff87SDaniel Beauregard ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg; 1805eb82ff87SDaniel Beauregard } 1806eb82ff87SDaniel Beauregard 1807eb82ff87SDaniel Beauregard void 1808eb82ff87SDaniel Beauregard ql_8021_set_drv_active(ql_adapter_state_t *ha) 1809eb82ff87SDaniel Beauregard { 1810eb82ff87SDaniel Beauregard uint32_t val; 1811eb82ff87SDaniel Beauregard 1812eb82ff87SDaniel Beauregard if (ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT)) { 1813eb82ff87SDaniel Beauregard return; 1814eb82ff87SDaniel Beauregard } 1815eb82ff87SDaniel Beauregard 1816eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &val); 1817eb82ff87SDaniel Beauregard if (val == 0xffffffff) { 1818eb82ff87SDaniel Beauregard val = (1 << (ha->function_number * 4)); 1819eb82ff87SDaniel Beauregard } else { 1820eb82ff87SDaniel Beauregard val |= (1 << (ha->function_number * 4)); 1821eb82ff87SDaniel Beauregard } 1822eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_DRV_ACTIVE, val); 1823eb82ff87SDaniel Beauregard 1824eb82ff87SDaniel Beauregard ql_8021_hw_unlock(ha); 1825eb82ff87SDaniel Beauregard } 1826eb82ff87SDaniel Beauregard 1827eb82ff87SDaniel Beauregard void 1828eb82ff87SDaniel Beauregard ql_8021_clr_drv_active(ql_adapter_state_t *ha) 1829eb82ff87SDaniel Beauregard { 1830eb82ff87SDaniel Beauregard uint32_t val; 1831eb82ff87SDaniel Beauregard 1832eb82ff87SDaniel Beauregard if (ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT)) { 1833eb82ff87SDaniel Beauregard return; 1834eb82ff87SDaniel Beauregard } 1835eb82ff87SDaniel Beauregard 1836eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &val); 1837eb82ff87SDaniel Beauregard val &= ~(1 << (ha->function_number * 4)); 1838eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_DRV_ACTIVE, val); 1839eb82ff87SDaniel Beauregard 1840eb82ff87SDaniel Beauregard ql_8021_hw_unlock(ha); 1841eb82ff87SDaniel Beauregard } 1842eb82ff87SDaniel Beauregard 1843eb82ff87SDaniel Beauregard static void 1844eb82ff87SDaniel Beauregard ql_8021_need_reset_handler(ql_adapter_state_t *ha) 1845eb82ff87SDaniel Beauregard { 1846eb82ff87SDaniel Beauregard uint32_t drv_state, drv_active; 1847eb82ff87SDaniel Beauregard clock_t timer; 1848eb82ff87SDaniel Beauregard 1849eb82ff87SDaniel Beauregard (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT); 1850eb82ff87SDaniel Beauregard 1851eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state); 1852eb82ff87SDaniel Beauregard drv_state |= (1 << (ha->function_number * 4)); 1853eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state); 1854eb82ff87SDaniel Beauregard 1855eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &drv_active); 1856eb82ff87SDaniel Beauregard 1857eb82ff87SDaniel Beauregard ql_8021_hw_unlock(ha); 1858eb82ff87SDaniel Beauregard 1859eb82ff87SDaniel Beauregard for (timer = 30; timer && drv_state != drv_active; timer--) { 1860eb82ff87SDaniel Beauregard delay(100); 1861eb82ff87SDaniel Beauregard 1862eb82ff87SDaniel Beauregard (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT); 1863eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state); 1864eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &drv_active); 1865eb82ff87SDaniel Beauregard ql_8021_hw_unlock(ha); 1866eb82ff87SDaniel Beauregard } 1867eb82ff87SDaniel Beauregard } 1868eb82ff87SDaniel Beauregard 1869eb82ff87SDaniel Beauregard uint32_t 1870eb82ff87SDaniel Beauregard ql_8021_idc_handler(ql_adapter_state_t *ha) 1871eb82ff87SDaniel Beauregard { 1872eb82ff87SDaniel Beauregard uint32_t dev_state, drv_state, rval; 1873eb82ff87SDaniel Beauregard clock_t timer; 1874eb82ff87SDaniel Beauregard ql_mbx_data_t mr; 1875eb82ff87SDaniel Beauregard boolean_t stalled = B_FALSE, lock = B_FALSE; 1876eb82ff87SDaniel Beauregard 1877eb82ff87SDaniel Beauregard /* wait for 30 seconds for device to go ready */ 1878eb82ff87SDaniel Beauregard timer = 30; 1879eb82ff87SDaniel Beauregard while (timer) { 1880eb82ff87SDaniel Beauregard if (lock == B_FALSE) { 1881eb82ff87SDaniel Beauregard (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT); 1882eb82ff87SDaniel Beauregard lock = B_TRUE; 1883eb82ff87SDaniel Beauregard } 1884eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state); 1885eb82ff87SDaniel Beauregard 1886eb82ff87SDaniel Beauregard switch (dev_state) { 1887eb82ff87SDaniel Beauregard case 0xffffffff: 1888eb82ff87SDaniel Beauregard case NX_DEV_COLD: 1889eb82ff87SDaniel Beauregard EL(ha, "dev_state=NX_DEV_COLD\n"); 1890eb82ff87SDaniel Beauregard rval = NX_DEV_COLD; 1891eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_DEV_STATE, NX_DEV_INITIALIZING); 1892eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_DRV_IDC_VERSION, NX_IDC_VERSION); 1893eb82ff87SDaniel Beauregard (void) ql_8021_hw_unlock(ha); 1894eb82ff87SDaniel Beauregard if (ql_get_fw_version(ha, &mr, 2) == QL_SUCCESS && 1895eb82ff87SDaniel Beauregard (mr.mb[1] | mr.mb[2] | mr.mb[3])) { 1896eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_FW_VERSION_MAJOR, 1897eb82ff87SDaniel Beauregard &ha->fw_major_version); 1898eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_FW_VERSION_MINOR, 1899eb82ff87SDaniel Beauregard &ha->fw_minor_version); 1900eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, UNM_FW_VERSION_SUB, 1901eb82ff87SDaniel Beauregard &ha->fw_subminor_version); 1902eb82ff87SDaniel Beauregard rval = NX_DEV_READY; 1903eb82ff87SDaniel Beauregard } else if (ql_8021_load_risc(ha) == QL_SUCCESS) { 1904eb82ff87SDaniel Beauregard rval = NX_DEV_READY; 1905eb82ff87SDaniel Beauregard } 1906eb82ff87SDaniel Beauregard (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT); 1907eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_DEV_STATE, rval); 1908eb82ff87SDaniel Beauregard break; 1909eb82ff87SDaniel Beauregard case NX_DEV_READY: 1910eb82ff87SDaniel Beauregard rval = NX_DEV_READY; 1911eb82ff87SDaniel Beauregard timer = 0; 1912eb82ff87SDaniel Beauregard break; 1913eb82ff87SDaniel Beauregard case NX_DEV_FAILED: 1914eb82ff87SDaniel Beauregard EL(ha, "dev_state=NX_DEV_FAILED\n"); 1915eb82ff87SDaniel Beauregard rval = NX_DEV_FAILED; 1916eb82ff87SDaniel Beauregard timer = 0; 1917eb82ff87SDaniel Beauregard break; 1918eb82ff87SDaniel Beauregard 1919eb82ff87SDaniel Beauregard case NX_DEV_NEED_RESET: 1920eb82ff87SDaniel Beauregard EL(ha, "dev_state=NX_DEV_NEED_RESET\n"); 1921eb82ff87SDaniel Beauregard rval = NX_DEV_NEED_RESET; 1922eb82ff87SDaniel Beauregard (void) ql_8021_hw_unlock(ha); 1923eb82ff87SDaniel Beauregard lock = B_FALSE; 1924eb82ff87SDaniel Beauregard if (ql_stall_driver(ha, 0) == QL_SUCCESS) { 1925eb82ff87SDaniel Beauregard stalled = B_TRUE; 1926eb82ff87SDaniel Beauregard ql_8021_need_reset_handler(ha); 1927eb82ff87SDaniel Beauregard } 1928eb82ff87SDaniel Beauregard break; 1929eb82ff87SDaniel Beauregard 1930eb82ff87SDaniel Beauregard case NX_DEV_NEED_QUIESCENT: 1931eb82ff87SDaniel Beauregard EL(ha, "dev_state=NX_DEV_NEED_QUIESCENT\n"); 1932eb82ff87SDaniel Beauregard (void) ql_8021_hw_unlock(ha); 1933eb82ff87SDaniel Beauregard lock = B_FALSE; 1934eb82ff87SDaniel Beauregard rval = ql_stall_driver(ha, 0); 1935eb82ff87SDaniel Beauregard if (rval == QL_SUCCESS) { 1936eb82ff87SDaniel Beauregard stalled = B_TRUE; 1937eb82ff87SDaniel Beauregard (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT); 1938eb82ff87SDaniel Beauregard lock = B_TRUE; 1939eb82ff87SDaniel Beauregard ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state); 1940eb82ff87SDaniel Beauregard drv_state |= 1941eb82ff87SDaniel Beauregard (2 << (ha->function_number * 4)); 1942eb82ff87SDaniel Beauregard ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state); 1943eb82ff87SDaniel Beauregard } 1944eb82ff87SDaniel Beauregard break; 1945eb82ff87SDaniel Beauregard 1946eb82ff87SDaniel Beauregard case NX_DEV_INITIALIZING: 1947eb82ff87SDaniel Beauregard EL(ha, "dev_state=NX_DEV_INITIALIZING\n"); 1948eb82ff87SDaniel Beauregard break; 1949eb82ff87SDaniel Beauregard case NX_DEV_QUIESCENT: 1950eb82ff87SDaniel Beauregard EL(ha, "dev_state=NX_DEV_QUIESCENT\n"); 1951eb82ff87SDaniel Beauregard break; 1952eb82ff87SDaniel Beauregard default: 1953eb82ff87SDaniel Beauregard EL(ha, "dev_state=%x, default\n", dev_state); 1954eb82ff87SDaniel Beauregard break; 1955eb82ff87SDaniel Beauregard } 1956eb82ff87SDaniel Beauregard if (lock == B_TRUE) { 1957eb82ff87SDaniel Beauregard (void) ql_8021_hw_unlock(ha); 1958eb82ff87SDaniel Beauregard lock = B_FALSE; 1959eb82ff87SDaniel Beauregard } 1960eb82ff87SDaniel Beauregard 1961eb82ff87SDaniel Beauregard if (timer) { 1962eb82ff87SDaniel Beauregard delay(100); 1963eb82ff87SDaniel Beauregard timer--; 1964eb82ff87SDaniel Beauregard } 1965eb82ff87SDaniel Beauregard } 1966eb82ff87SDaniel Beauregard 1967eb82ff87SDaniel Beauregard if (stalled) { 1968eb82ff87SDaniel Beauregard ql_restart_driver(ha); 1969eb82ff87SDaniel Beauregard } 1970eb82ff87SDaniel Beauregard return (rval); 1971eb82ff87SDaniel Beauregard } 1972