| @@ -1,1709 +1,1709 @@ | | | @@ -1,1709 +1,1709 @@ |
1 | /* $NetBSD: if_bnx.c,v 1.45 2011/09/22 08:42:53 jym Exp $ */ | | 1 | /* $NetBSD: if_bnx.c,v 1.46 2012/03/06 18:29:23 bouyer Exp $ */ |
2 | /* $OpenBSD: if_bnx.c,v 1.85 2009/11/09 14:32:41 dlg Exp $ */ | | 2 | /* $OpenBSD: if_bnx.c,v 1.85 2009/11/09 14:32:41 dlg Exp $ */ |
3 | | | 3 | |
4 | /*- | | 4 | /*- |
5 | * Copyright (c) 2006 Broadcom Corporation | | 5 | * Copyright (c) 2006 Broadcom Corporation |
6 | * David Christensen <davidch@broadcom.com>. All rights reserved. | | 6 | * David Christensen <davidch@broadcom.com>. All rights reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * | | 11 | * |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the | | 15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. | | 16 | * documentation and/or other materials provided with the distribution. |
17 | * 3. Neither the name of Broadcom Corporation nor the name of its contributors | | 17 | * 3. Neither the name of Broadcom Corporation nor the name of its contributors |
18 | * may be used to endorse or promote products derived from this software | | 18 | * may be used to endorse or promote products derived from this software |
19 | * without specific prior written consent. | | 19 | * without specific prior written consent. |
20 | * | | 20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' | | 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' |
22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS | | 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
31 | * THE POSSIBILITY OF SUCH DAMAGE. | | 31 | * THE POSSIBILITY OF SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | #if 0 | | 35 | #if 0 |
36 | __FBSDID("$FreeBSD: src/sys/dev/bce/if_bce.c,v 1.3 2006/04/13 14:12:26 ru Exp $"); | | 36 | __FBSDID("$FreeBSD: src/sys/dev/bce/if_bce.c,v 1.3 2006/04/13 14:12:26 ru Exp $"); |
37 | #endif | | 37 | #endif |
38 | __KERNEL_RCSID(0, "$NetBSD: if_bnx.c,v 1.45 2011/09/22 08:42:53 jym Exp $"); | | 38 | __KERNEL_RCSID(0, "$NetBSD: if_bnx.c,v 1.46 2012/03/06 18:29:23 bouyer Exp $"); |
39 | | | 39 | |
40 | /* | | 40 | /* |
41 | * The following controllers are supported by this driver: | | 41 | * The following controllers are supported by this driver: |
42 | * BCM5706C A2, A3 | | 42 | * BCM5706C A2, A3 |
43 | * BCM5706S A2, A3 | | 43 | * BCM5706S A2, A3 |
44 | * BCM5708C B1, B2 | | 44 | * BCM5708C B1, B2 |
45 | * BCM5708S B1, B2 | | 45 | * BCM5708S B1, B2 |
46 | * BCM5709C A1, C0 | | 46 | * BCM5709C A1, C0 |
47 | * BCM5709S A1, C0 | | 47 | * BCM5709S A1, C0 |
48 | * BCM5716 C0 | | 48 | * BCM5716 C0 |
49 | * | | 49 | * |
50 | * The following controllers are not supported by this driver: | | 50 | * The following controllers are not supported by this driver: |
51 | * | | 51 | * |
52 | * BCM5706C A0, A1 | | 52 | * BCM5706C A0, A1 |
53 | * BCM5706S A0, A1 | | 53 | * BCM5706S A0, A1 |
54 | * BCM5708C A0, B0 | | 54 | * BCM5708C A0, B0 |
55 | * BCM5708S A0, B0 | | 55 | * BCM5708S A0, B0 |
56 | * BCM5709C A0 B0, B1, B2 (pre-production) | | 56 | * BCM5709C A0 B0, B1, B2 (pre-production) |
57 | * BCM5709S A0, B0, B1, B2 (pre-production) | | 57 | * BCM5709S A0, B0, B1, B2 (pre-production) |
58 | */ | | 58 | */ |
59 | | | 59 | |
60 | #include <sys/callout.h> | | 60 | #include <sys/callout.h> |
61 | #include <sys/mutex.h> | | 61 | #include <sys/mutex.h> |
62 | | | 62 | |
63 | #include <dev/pci/if_bnxreg.h> | | 63 | #include <dev/pci/if_bnxreg.h> |
64 | #include <dev/pci/if_bnxvar.h> | | 64 | #include <dev/pci/if_bnxvar.h> |
65 | | | 65 | |
66 | #include <dev/microcode/bnx/bnxfw.h> | | 66 | #include <dev/microcode/bnx/bnxfw.h> |
67 | | | 67 | |
68 | /****************************************************************************/ | | 68 | /****************************************************************************/ |
69 | /* BNX Driver Version */ | | 69 | /* BNX Driver Version */ |
70 | /****************************************************************************/ | | 70 | /****************************************************************************/ |
71 | #define BNX_DRIVER_VERSION "v0.9.6" | | 71 | #define BNX_DRIVER_VERSION "v0.9.6" |
72 | | | 72 | |
73 | /****************************************************************************/ | | 73 | /****************************************************************************/ |
74 | /* BNX Debug Options */ | | 74 | /* BNX Debug Options */ |
75 | /****************************************************************************/ | | 75 | /****************************************************************************/ |
76 | #ifdef BNX_DEBUG | | 76 | #ifdef BNX_DEBUG |
77 | u_int32_t bnx_debug = /*BNX_WARN*/ BNX_VERBOSE_SEND; | | 77 | u_int32_t bnx_debug = /*BNX_WARN*/ BNX_VERBOSE_SEND; |
78 | | | 78 | |
79 | /* 0 = Never */ | | 79 | /* 0 = Never */ |
80 | /* 1 = 1 in 2,147,483,648 */ | | 80 | /* 1 = 1 in 2,147,483,648 */ |
81 | /* 256 = 1 in 8,388,608 */ | | 81 | /* 256 = 1 in 8,388,608 */ |
82 | /* 2048 = 1 in 1,048,576 */ | | 82 | /* 2048 = 1 in 1,048,576 */ |
83 | /* 65536 = 1 in 32,768 */ | | 83 | /* 65536 = 1 in 32,768 */ |
84 | /* 1048576 = 1 in 2,048 */ | | 84 | /* 1048576 = 1 in 2,048 */ |
85 | /* 268435456 = 1 in 8 */ | | 85 | /* 268435456 = 1 in 8 */ |
86 | /* 536870912 = 1 in 4 */ | | 86 | /* 536870912 = 1 in 4 */ |
87 | /* 1073741824 = 1 in 2 */ | | 87 | /* 1073741824 = 1 in 2 */ |
88 | | | 88 | |
89 | /* Controls how often the l2_fhdr frame error check will fail. */ | | 89 | /* Controls how often the l2_fhdr frame error check will fail. */ |
90 | int bnx_debug_l2fhdr_status_check = 0; | | 90 | int bnx_debug_l2fhdr_status_check = 0; |
91 | | | 91 | |
92 | /* Controls how often the unexpected attention check will fail. */ | | 92 | /* Controls how often the unexpected attention check will fail. */ |
93 | int bnx_debug_unexpected_attention = 0; | | 93 | int bnx_debug_unexpected_attention = 0; |
94 | | | 94 | |
95 | /* Controls how often to simulate an mbuf allocation failure. */ | | 95 | /* Controls how often to simulate an mbuf allocation failure. */ |
96 | int bnx_debug_mbuf_allocation_failure = 0; | | 96 | int bnx_debug_mbuf_allocation_failure = 0; |
97 | | | 97 | |
98 | /* Controls how often to simulate a DMA mapping failure. */ | | 98 | /* Controls how often to simulate a DMA mapping failure. */ |
99 | int bnx_debug_dma_map_addr_failure = 0; | | 99 | int bnx_debug_dma_map_addr_failure = 0; |
100 | | | 100 | |
101 | /* Controls how often to simulate a bootcode failure. */ | | 101 | /* Controls how often to simulate a bootcode failure. */ |
102 | int bnx_debug_bootcode_running_failure = 0; | | 102 | int bnx_debug_bootcode_running_failure = 0; |
103 | #endif | | 103 | #endif |
104 | | | 104 | |
105 | /****************************************************************************/ | | 105 | /****************************************************************************/ |
106 | /* PCI Device ID Table */ | | 106 | /* PCI Device ID Table */ |
107 | /* */ | | 107 | /* */ |
108 | /* Used by bnx_probe() to identify the devices supported by this driver. */ | | 108 | /* Used by bnx_probe() to identify the devices supported by this driver. */ |
109 | /****************************************************************************/ | | 109 | /****************************************************************************/ |
110 | static const struct bnx_product { | | 110 | static const struct bnx_product { |
111 | pci_vendor_id_t bp_vendor; | | 111 | pci_vendor_id_t bp_vendor; |
112 | pci_product_id_t bp_product; | | 112 | pci_product_id_t bp_product; |
113 | pci_vendor_id_t bp_subvendor; | | 113 | pci_vendor_id_t bp_subvendor; |
114 | pci_product_id_t bp_subproduct; | | 114 | pci_product_id_t bp_subproduct; |
115 | const char *bp_name; | | 115 | const char *bp_name; |
116 | } bnx_devices[] = { | | 116 | } bnx_devices[] = { |
117 | #ifdef PCI_SUBPRODUCT_HP_NC370T | | 117 | #ifdef PCI_SUBPRODUCT_HP_NC370T |
118 | { | | 118 | { |
119 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706, | | 119 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706, |
120 | PCI_VENDOR_HP, PCI_SUBPRODUCT_HP_NC370T, | | 120 | PCI_VENDOR_HP, PCI_SUBPRODUCT_HP_NC370T, |
121 | "HP NC370T Multifunction Gigabit Server Adapter" | | 121 | "HP NC370T Multifunction Gigabit Server Adapter" |
122 | }, | | 122 | }, |
123 | #endif | | 123 | #endif |
124 | #ifdef PCI_SUBPRODUCT_HP_NC370i | | 124 | #ifdef PCI_SUBPRODUCT_HP_NC370i |
125 | { | | 125 | { |
126 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706, | | 126 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706, |
127 | PCI_VENDOR_HP, PCI_SUBPRODUCT_HP_NC370i, | | 127 | PCI_VENDOR_HP, PCI_SUBPRODUCT_HP_NC370i, |
128 | "HP NC370i Multifunction Gigabit Server Adapter" | | 128 | "HP NC370i Multifunction Gigabit Server Adapter" |
129 | }, | | 129 | }, |
130 | #endif | | 130 | #endif |
131 | { | | 131 | { |
132 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706, | | 132 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706, |
133 | 0, 0, | | 133 | 0, 0, |
134 | "Broadcom NetXtreme II BCM5706 1000Base-T" | | 134 | "Broadcom NetXtreme II BCM5706 1000Base-T" |
135 | }, | | 135 | }, |
136 | #ifdef PCI_SUBPRODUCT_HP_NC370F | | 136 | #ifdef PCI_SUBPRODUCT_HP_NC370F |
137 | { | | 137 | { |
138 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706S, | | 138 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706S, |
139 | PCI_VENDOR_HP, PCI_SUBPRODUCT_HP_NC370F, | | 139 | PCI_VENDOR_HP, PCI_SUBPRODUCT_HP_NC370F, |
140 | "HP NC370F Multifunction Gigabit Server Adapter" | | 140 | "HP NC370F Multifunction Gigabit Server Adapter" |
141 | }, | | 141 | }, |
142 | #endif | | 142 | #endif |
143 | { | | 143 | { |
144 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706S, | | 144 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706S, |
145 | 0, 0, | | 145 | 0, 0, |
146 | "Broadcom NetXtreme II BCM5706 1000Base-SX" | | 146 | "Broadcom NetXtreme II BCM5706 1000Base-SX" |
147 | }, | | 147 | }, |
148 | { | | 148 | { |
149 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5708, | | 149 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5708, |
150 | 0, 0, | | 150 | 0, 0, |
151 | "Broadcom NetXtreme II BCM5708 1000Base-T" | | 151 | "Broadcom NetXtreme II BCM5708 1000Base-T" |
152 | }, | | 152 | }, |
153 | { | | 153 | { |
154 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5708S, | | 154 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5708S, |
155 | 0, 0, | | 155 | 0, 0, |
156 | "Broadcom NetXtreme II BCM5708 1000Base-SX" | | 156 | "Broadcom NetXtreme II BCM5708 1000Base-SX" |
157 | }, | | 157 | }, |
158 | { | | 158 | { |
159 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5709, | | 159 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5709, |
160 | 0, 0, | | 160 | 0, 0, |
161 | "Broadcom NetXtreme II BCM5709 1000Base-T" | | 161 | "Broadcom NetXtreme II BCM5709 1000Base-T" |
162 | }, | | 162 | }, |
163 | { | | 163 | { |
164 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5709S, | | 164 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5709S, |
165 | 0, 0, | | 165 | 0, 0, |
166 | "Broadcom NetXtreme II BCM5709 1000Base-SX" | | 166 | "Broadcom NetXtreme II BCM5709 1000Base-SX" |
167 | }, | | 167 | }, |
168 | { | | 168 | { |
169 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5716, | | 169 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5716, |
170 | 0, 0, | | 170 | 0, 0, |
171 | "Broadcom NetXtreme II BCM5716 1000Base-T" | | 171 | "Broadcom NetXtreme II BCM5716 1000Base-T" |
172 | }, | | 172 | }, |
173 | { | | 173 | { |
174 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5716S, | | 174 | PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5716S, |
175 | 0, 0, | | 175 | 0, 0, |
176 | "Broadcom NetXtreme II BCM5716 1000Base-SX" | | 176 | "Broadcom NetXtreme II BCM5716 1000Base-SX" |
177 | }, | | 177 | }, |
178 | }; | | 178 | }; |
179 | | | 179 | |
180 | /****************************************************************************/ | | 180 | /****************************************************************************/ |
181 | /* Supported Flash NVRAM device data. */ | | 181 | /* Supported Flash NVRAM device data. */ |
182 | /****************************************************************************/ | | 182 | /****************************************************************************/ |
183 | static struct flash_spec flash_table[] = | | 183 | static struct flash_spec flash_table[] = |
184 | { | | 184 | { |
185 | #define BUFFERED_FLAGS (BNX_NV_BUFFERED | BNX_NV_TRANSLATE) | | 185 | #define BUFFERED_FLAGS (BNX_NV_BUFFERED | BNX_NV_TRANSLATE) |
186 | #define NONBUFFERED_FLAGS (BNX_NV_WREN) | | 186 | #define NONBUFFERED_FLAGS (BNX_NV_WREN) |
187 | /* Slow EEPROM */ | | 187 | /* Slow EEPROM */ |
188 | {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400, | | 188 | {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400, |
189 | BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, | | 189 | BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, |
190 | SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, | | 190 | SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, |
191 | "EEPROM - slow"}, | | 191 | "EEPROM - slow"}, |
192 | /* Expansion entry 0001 */ | | 192 | /* Expansion entry 0001 */ |
193 | {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406, | | 193 | {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406, |
194 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, | | 194 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, |
195 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, | | 195 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, |
196 | "Entry 0001"}, | | 196 | "Entry 0001"}, |
197 | /* Saifun SA25F010 (non-buffered flash) */ | | 197 | /* Saifun SA25F010 (non-buffered flash) */ |
198 | /* strap, cfg1, & write1 need updates */ | | 198 | /* strap, cfg1, & write1 need updates */ |
199 | {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406, | | 199 | {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406, |
200 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, | | 200 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, |
201 | SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2, | | 201 | SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2, |
202 | "Non-buffered flash (128kB)"}, | | 202 | "Non-buffered flash (128kB)"}, |
203 | /* Saifun SA25F020 (non-buffered flash) */ | | 203 | /* Saifun SA25F020 (non-buffered flash) */ |
204 | /* strap, cfg1, & write1 need updates */ | | 204 | /* strap, cfg1, & write1 need updates */ |
205 | {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406, | | 205 | {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406, |
206 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, | | 206 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, |
207 | SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4, | | 207 | SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4, |
208 | "Non-buffered flash (256kB)"}, | | 208 | "Non-buffered flash (256kB)"}, |
209 | /* Expansion entry 0100 */ | | 209 | /* Expansion entry 0100 */ |
210 | {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406, | | 210 | {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406, |
211 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, | | 211 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, |
212 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, | | 212 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, |
213 | "Entry 0100"}, | | 213 | "Entry 0100"}, |
214 | /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */ | | 214 | /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */ |
215 | {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406, | | 215 | {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406, |
216 | NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, | | 216 | NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, |
217 | ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2, | | 217 | ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2, |
218 | "Entry 0101: ST M45PE10 (128kB non-bufferred)"}, | | 218 | "Entry 0101: ST M45PE10 (128kB non-bufferred)"}, |
219 | /* Entry 0110: ST M45PE20 (non-buffered flash)*/ | | 219 | /* Entry 0110: ST M45PE20 (non-buffered flash)*/ |
220 | {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406, | | 220 | {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406, |
221 | NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, | | 221 | NONBUFFERED_FLAGS, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, |
222 | ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4, | | 222 | ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4, |
223 | "Entry 0110: ST M45PE20 (256kB non-bufferred)"}, | | 223 | "Entry 0110: ST M45PE20 (256kB non-bufferred)"}, |
224 | /* Saifun SA25F005 (non-buffered flash) */ | | 224 | /* Saifun SA25F005 (non-buffered flash) */ |
225 | /* strap, cfg1, & write1 need updates */ | | 225 | /* strap, cfg1, & write1 need updates */ |
226 | {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406, | | 226 | {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406, |
227 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, | | 227 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, |
228 | SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE, | | 228 | SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE, |
229 | "Non-buffered flash (64kB)"}, | | 229 | "Non-buffered flash (64kB)"}, |
230 | /* Fast EEPROM */ | | 230 | /* Fast EEPROM */ |
231 | {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400, | | 231 | {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400, |
232 | BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, | | 232 | BUFFERED_FLAGS, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE, |
233 | SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, | | 233 | SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE, |
234 | "EEPROM - fast"}, | | 234 | "EEPROM - fast"}, |
235 | /* Expansion entry 1001 */ | | 235 | /* Expansion entry 1001 */ |
236 | {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406, | | 236 | {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406, |
237 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, | | 237 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, |
238 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, | | 238 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, |
239 | "Entry 1001"}, | | 239 | "Entry 1001"}, |
240 | /* Expansion entry 1010 */ | | 240 | /* Expansion entry 1010 */ |
241 | {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406, | | 241 | {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406, |
242 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, | | 242 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, |
243 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, | | 243 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, |
244 | "Entry 1010"}, | | 244 | "Entry 1010"}, |
245 | /* ATMEL AT45DB011B (buffered flash) */ | | 245 | /* ATMEL AT45DB011B (buffered flash) */ |
246 | {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400, | | 246 | {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400, |
247 | BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, | | 247 | BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, |
248 | BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE, | | 248 | BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE, |
249 | "Buffered flash (128kB)"}, | | 249 | "Buffered flash (128kB)"}, |
250 | /* Expansion entry 1100 */ | | 250 | /* Expansion entry 1100 */ |
251 | {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406, | | 251 | {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406, |
252 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, | | 252 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, |
253 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, | | 253 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, |
254 | "Entry 1100"}, | | 254 | "Entry 1100"}, |
255 | /* Expansion entry 1101 */ | | 255 | /* Expansion entry 1101 */ |
256 | {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406, | | 256 | {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406, |
257 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, | | 257 | NONBUFFERED_FLAGS, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE, |
258 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, | | 258 | SAIFUN_FLASH_BYTE_ADDR_MASK, 0, |
259 | "Entry 1101"}, | | 259 | "Entry 1101"}, |
260 | /* Ateml Expansion entry 1110 */ | | 260 | /* Ateml Expansion entry 1110 */ |
261 | {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400, | | 261 | {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400, |
262 | BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, | | 262 | BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, |
263 | BUFFERED_FLASH_BYTE_ADDR_MASK, 0, | | 263 | BUFFERED_FLASH_BYTE_ADDR_MASK, 0, |
264 | "Entry 1110 (Atmel)"}, | | 264 | "Entry 1110 (Atmel)"}, |
265 | /* ATMEL AT45DB021B (buffered flash) */ | | 265 | /* ATMEL AT45DB021B (buffered flash) */ |
266 | {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400, | | 266 | {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400, |
267 | BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, | | 267 | BUFFERED_FLAGS, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE, |
268 | BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2, | | 268 | BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2, |
269 | "Buffered flash (256kB)"}, | | 269 | "Buffered flash (256kB)"}, |
270 | }; | | 270 | }; |
271 | | | 271 | |
272 | /* | | 272 | /* |
273 | * The BCM5709 controllers transparently handle the | | 273 | * The BCM5709 controllers transparently handle the |
274 | * differences between Atmel 264 byte pages and all | | 274 | * differences between Atmel 264 byte pages and all |
275 | * flash devices which use 256 byte pages, so no | | 275 | * flash devices which use 256 byte pages, so no |
276 | * logical-to-physical mapping is required in the | | 276 | * logical-to-physical mapping is required in the |
277 | * driver. | | 277 | * driver. |
278 | */ | | 278 | */ |
279 | static struct flash_spec flash_5709 = { | | 279 | static struct flash_spec flash_5709 = { |
280 | .flags = BNX_NV_BUFFERED, | | 280 | .flags = BNX_NV_BUFFERED, |
281 | .page_bits = BCM5709_FLASH_PAGE_BITS, | | 281 | .page_bits = BCM5709_FLASH_PAGE_BITS, |
282 | .page_size = BCM5709_FLASH_PAGE_SIZE, | | 282 | .page_size = BCM5709_FLASH_PAGE_SIZE, |
283 | .addr_mask = BCM5709_FLASH_BYTE_ADDR_MASK, | | 283 | .addr_mask = BCM5709_FLASH_BYTE_ADDR_MASK, |
284 | .total_size = BUFFERED_FLASH_TOTAL_SIZE * 2, | | 284 | .total_size = BUFFERED_FLASH_TOTAL_SIZE * 2, |
285 | .name = "5709 buffered flash (256kB)", | | 285 | .name = "5709 buffered flash (256kB)", |
286 | }; | | 286 | }; |
287 | | | 287 | |
288 | /****************************************************************************/ | | 288 | /****************************************************************************/ |
289 | /* OpenBSD device entry points. */ | | 289 | /* OpenBSD device entry points. */ |
290 | /****************************************************************************/ | | 290 | /****************************************************************************/ |
291 | static int bnx_probe(device_t, cfdata_t, void *); | | 291 | static int bnx_probe(device_t, cfdata_t, void *); |
292 | void bnx_attach(device_t, device_t, void *); | | 292 | void bnx_attach(device_t, device_t, void *); |
293 | int bnx_detach(device_t, int); | | 293 | int bnx_detach(device_t, int); |
294 | | | 294 | |
295 | /****************************************************************************/ | | 295 | /****************************************************************************/ |
296 | /* BNX Debug Data Structure Dump Routines */ | | 296 | /* BNX Debug Data Structure Dump Routines */ |
297 | /****************************************************************************/ | | 297 | /****************************************************************************/ |
298 | #ifdef BNX_DEBUG | | 298 | #ifdef BNX_DEBUG |
299 | void bnx_dump_mbuf(struct bnx_softc *, struct mbuf *); | | 299 | void bnx_dump_mbuf(struct bnx_softc *, struct mbuf *); |
300 | void bnx_dump_tx_mbuf_chain(struct bnx_softc *, int, int); | | 300 | void bnx_dump_tx_mbuf_chain(struct bnx_softc *, int, int); |
301 | void bnx_dump_rx_mbuf_chain(struct bnx_softc *, int, int); | | 301 | void bnx_dump_rx_mbuf_chain(struct bnx_softc *, int, int); |
302 | void bnx_dump_txbd(struct bnx_softc *, int, struct tx_bd *); | | 302 | void bnx_dump_txbd(struct bnx_softc *, int, struct tx_bd *); |
303 | void bnx_dump_rxbd(struct bnx_softc *, int, struct rx_bd *); | | 303 | void bnx_dump_rxbd(struct bnx_softc *, int, struct rx_bd *); |
304 | void bnx_dump_l2fhdr(struct bnx_softc *, int, struct l2_fhdr *); | | 304 | void bnx_dump_l2fhdr(struct bnx_softc *, int, struct l2_fhdr *); |
305 | void bnx_dump_tx_chain(struct bnx_softc *, int, int); | | 305 | void bnx_dump_tx_chain(struct bnx_softc *, int, int); |
306 | void bnx_dump_rx_chain(struct bnx_softc *, int, int); | | 306 | void bnx_dump_rx_chain(struct bnx_softc *, int, int); |
307 | void bnx_dump_status_block(struct bnx_softc *); | | 307 | void bnx_dump_status_block(struct bnx_softc *); |
308 | void bnx_dump_stats_block(struct bnx_softc *); | | 308 | void bnx_dump_stats_block(struct bnx_softc *); |
309 | void bnx_dump_driver_state(struct bnx_softc *); | | 309 | void bnx_dump_driver_state(struct bnx_softc *); |
310 | void bnx_dump_hw_state(struct bnx_softc *); | | 310 | void bnx_dump_hw_state(struct bnx_softc *); |
311 | void bnx_breakpoint(struct bnx_softc *); | | 311 | void bnx_breakpoint(struct bnx_softc *); |
312 | #endif | | 312 | #endif |
313 | | | 313 | |
314 | /****************************************************************************/ | | 314 | /****************************************************************************/ |
315 | /* BNX Register/Memory Access Routines */ | | 315 | /* BNX Register/Memory Access Routines */ |
316 | /****************************************************************************/ | | 316 | /****************************************************************************/ |
317 | u_int32_t bnx_reg_rd_ind(struct bnx_softc *, u_int32_t); | | 317 | u_int32_t bnx_reg_rd_ind(struct bnx_softc *, u_int32_t); |
318 | void bnx_reg_wr_ind(struct bnx_softc *, u_int32_t, u_int32_t); | | 318 | void bnx_reg_wr_ind(struct bnx_softc *, u_int32_t, u_int32_t); |
319 | void bnx_ctx_wr(struct bnx_softc *, u_int32_t, u_int32_t, u_int32_t); | | 319 | void bnx_ctx_wr(struct bnx_softc *, u_int32_t, u_int32_t, u_int32_t); |
320 | int bnx_miibus_read_reg(device_t, int, int); | | 320 | int bnx_miibus_read_reg(device_t, int, int); |
321 | void bnx_miibus_write_reg(device_t, int, int, int); | | 321 | void bnx_miibus_write_reg(device_t, int, int, int); |
322 | void bnx_miibus_statchg(device_t); | | 322 | void bnx_miibus_statchg(device_t); |
323 | | | 323 | |
324 | /****************************************************************************/ | | 324 | /****************************************************************************/ |
325 | /* BNX NVRAM Access Routines */ | | 325 | /* BNX NVRAM Access Routines */ |
326 | /****************************************************************************/ | | 326 | /****************************************************************************/ |
327 | int bnx_acquire_nvram_lock(struct bnx_softc *); | | 327 | int bnx_acquire_nvram_lock(struct bnx_softc *); |
328 | int bnx_release_nvram_lock(struct bnx_softc *); | | 328 | int bnx_release_nvram_lock(struct bnx_softc *); |
329 | void bnx_enable_nvram_access(struct bnx_softc *); | | 329 | void bnx_enable_nvram_access(struct bnx_softc *); |
330 | void bnx_disable_nvram_access(struct bnx_softc *); | | 330 | void bnx_disable_nvram_access(struct bnx_softc *); |
331 | int bnx_nvram_read_dword(struct bnx_softc *, u_int32_t, u_int8_t *, | | 331 | int bnx_nvram_read_dword(struct bnx_softc *, u_int32_t, u_int8_t *, |
332 | u_int32_t); | | 332 | u_int32_t); |
333 | int bnx_init_nvram(struct bnx_softc *); | | 333 | int bnx_init_nvram(struct bnx_softc *); |
334 | int bnx_nvram_read(struct bnx_softc *, u_int32_t, u_int8_t *, int); | | 334 | int bnx_nvram_read(struct bnx_softc *, u_int32_t, u_int8_t *, int); |
335 | int bnx_nvram_test(struct bnx_softc *); | | 335 | int bnx_nvram_test(struct bnx_softc *); |
336 | #ifdef BNX_NVRAM_WRITE_SUPPORT | | 336 | #ifdef BNX_NVRAM_WRITE_SUPPORT |
337 | int bnx_enable_nvram_write(struct bnx_softc *); | | 337 | int bnx_enable_nvram_write(struct bnx_softc *); |
338 | void bnx_disable_nvram_write(struct bnx_softc *); | | 338 | void bnx_disable_nvram_write(struct bnx_softc *); |
339 | int bnx_nvram_erase_page(struct bnx_softc *, u_int32_t); | | 339 | int bnx_nvram_erase_page(struct bnx_softc *, u_int32_t); |
340 | int bnx_nvram_write_dword(struct bnx_softc *, u_int32_t, u_int8_t *, | | 340 | int bnx_nvram_write_dword(struct bnx_softc *, u_int32_t, u_int8_t *, |
341 | u_int32_t); | | 341 | u_int32_t); |
342 | int bnx_nvram_write(struct bnx_softc *, u_int32_t, u_int8_t *, int); | | 342 | int bnx_nvram_write(struct bnx_softc *, u_int32_t, u_int8_t *, int); |
343 | #endif | | 343 | #endif |
344 | | | 344 | |
345 | /****************************************************************************/ | | 345 | /****************************************************************************/ |
346 | /* */ | | 346 | /* */ |
347 | /****************************************************************************/ | | 347 | /****************************************************************************/ |
348 | void bnx_get_media(struct bnx_softc *); | | 348 | void bnx_get_media(struct bnx_softc *); |
349 | void bnx_init_media(struct bnx_softc *); | | 349 | void bnx_init_media(struct bnx_softc *); |
350 | int bnx_dma_alloc(struct bnx_softc *); | | 350 | int bnx_dma_alloc(struct bnx_softc *); |
351 | void bnx_dma_free(struct bnx_softc *); | | 351 | void bnx_dma_free(struct bnx_softc *); |
352 | void bnx_release_resources(struct bnx_softc *); | | 352 | void bnx_release_resources(struct bnx_softc *); |
353 | | | 353 | |
354 | /****************************************************************************/ | | 354 | /****************************************************************************/ |
355 | /* BNX Firmware Synchronization and Load */ | | 355 | /* BNX Firmware Synchronization and Load */ |
356 | /****************************************************************************/ | | 356 | /****************************************************************************/ |
357 | int bnx_fw_sync(struct bnx_softc *, u_int32_t); | | 357 | int bnx_fw_sync(struct bnx_softc *, u_int32_t); |
358 | void bnx_load_rv2p_fw(struct bnx_softc *, u_int32_t *, u_int32_t, | | 358 | void bnx_load_rv2p_fw(struct bnx_softc *, u_int32_t *, u_int32_t, |
359 | u_int32_t); | | 359 | u_int32_t); |
360 | void bnx_load_cpu_fw(struct bnx_softc *, struct cpu_reg *, | | 360 | void bnx_load_cpu_fw(struct bnx_softc *, struct cpu_reg *, |
361 | struct fw_info *); | | 361 | struct fw_info *); |
362 | void bnx_init_cpus(struct bnx_softc *); | | 362 | void bnx_init_cpus(struct bnx_softc *); |
363 | | | 363 | |
364 | void bnx_stop(struct ifnet *, int); | | 364 | void bnx_stop(struct ifnet *, int); |
365 | int bnx_reset(struct bnx_softc *, u_int32_t); | | 365 | int bnx_reset(struct bnx_softc *, u_int32_t); |
366 | int bnx_chipinit(struct bnx_softc *); | | 366 | int bnx_chipinit(struct bnx_softc *); |
367 | int bnx_blockinit(struct bnx_softc *); | | 367 | int bnx_blockinit(struct bnx_softc *); |
368 | static int bnx_add_buf(struct bnx_softc *, struct mbuf *, u_int16_t *, | | 368 | static int bnx_add_buf(struct bnx_softc *, struct mbuf *, u_int16_t *, |
369 | u_int16_t *, u_int32_t *); | | 369 | u_int16_t *, u_int32_t *); |
370 | int bnx_get_buf(struct bnx_softc *, u_int16_t *, u_int16_t *, u_int32_t *); | | 370 | int bnx_get_buf(struct bnx_softc *, u_int16_t *, u_int16_t *, u_int32_t *); |
371 | | | 371 | |
372 | int bnx_init_tx_chain(struct bnx_softc *); | | 372 | int bnx_init_tx_chain(struct bnx_softc *); |
373 | void bnx_init_tx_context(struct bnx_softc *); | | 373 | void bnx_init_tx_context(struct bnx_softc *); |
374 | int bnx_init_rx_chain(struct bnx_softc *); | | 374 | int bnx_init_rx_chain(struct bnx_softc *); |
375 | void bnx_init_rx_context(struct bnx_softc *); | | 375 | void bnx_init_rx_context(struct bnx_softc *); |
376 | void bnx_free_rx_chain(struct bnx_softc *); | | 376 | void bnx_free_rx_chain(struct bnx_softc *); |
377 | void bnx_free_tx_chain(struct bnx_softc *); | | 377 | void bnx_free_tx_chain(struct bnx_softc *); |
378 | | | 378 | |
379 | int bnx_tx_encap(struct bnx_softc *, struct mbuf *); | | 379 | int bnx_tx_encap(struct bnx_softc *, struct mbuf *); |
380 | void bnx_start(struct ifnet *); | | 380 | void bnx_start(struct ifnet *); |
381 | int bnx_ioctl(struct ifnet *, u_long, void *); | | 381 | int bnx_ioctl(struct ifnet *, u_long, void *); |
382 | void bnx_watchdog(struct ifnet *); | | 382 | void bnx_watchdog(struct ifnet *); |
383 | int bnx_init(struct ifnet *); | | 383 | int bnx_init(struct ifnet *); |
384 | | | 384 | |
385 | void bnx_init_context(struct bnx_softc *); | | 385 | void bnx_init_context(struct bnx_softc *); |
386 | void bnx_get_mac_addr(struct bnx_softc *); | | 386 | void bnx_get_mac_addr(struct bnx_softc *); |
387 | void bnx_set_mac_addr(struct bnx_softc *); | | 387 | void bnx_set_mac_addr(struct bnx_softc *); |
388 | void bnx_phy_intr(struct bnx_softc *); | | 388 | void bnx_phy_intr(struct bnx_softc *); |
389 | void bnx_rx_intr(struct bnx_softc *); | | 389 | void bnx_rx_intr(struct bnx_softc *); |
390 | void bnx_tx_intr(struct bnx_softc *); | | 390 | void bnx_tx_intr(struct bnx_softc *); |
391 | void bnx_disable_intr(struct bnx_softc *); | | 391 | void bnx_disable_intr(struct bnx_softc *); |
392 | void bnx_enable_intr(struct bnx_softc *); | | 392 | void bnx_enable_intr(struct bnx_softc *); |
393 | | | 393 | |
394 | int bnx_intr(void *); | | 394 | int bnx_intr(void *); |
395 | void bnx_iff(struct bnx_softc *); | | 395 | void bnx_iff(struct bnx_softc *); |
396 | void bnx_stats_update(struct bnx_softc *); | | 396 | void bnx_stats_update(struct bnx_softc *); |
397 | void bnx_tick(void *); | | 397 | void bnx_tick(void *); |
398 | | | 398 | |
399 | struct pool *bnx_tx_pool = NULL; | | 399 | struct pool *bnx_tx_pool = NULL; |
400 | void bnx_alloc_pkts(struct work *, void *); | | 400 | void bnx_alloc_pkts(struct work *, void *); |
401 | | | 401 | |
402 | /****************************************************************************/ | | 402 | /****************************************************************************/ |
403 | /* OpenBSD device dispatch table. */ | | 403 | /* OpenBSD device dispatch table. */ |
404 | /****************************************************************************/ | | 404 | /****************************************************************************/ |
405 | CFATTACH_DECL3_NEW(bnx, sizeof(struct bnx_softc), | | 405 | CFATTACH_DECL3_NEW(bnx, sizeof(struct bnx_softc), |
406 | bnx_probe, bnx_attach, bnx_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); | | 406 | bnx_probe, bnx_attach, bnx_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); |
407 | | | 407 | |
408 | /****************************************************************************/ | | 408 | /****************************************************************************/ |
409 | /* Device probe function. */ | | 409 | /* Device probe function. */ |
410 | /* */ | | 410 | /* */ |
411 | /* Compares the device to the driver's list of supported devices and */ | | 411 | /* Compares the device to the driver's list of supported devices and */ |
412 | /* reports back to the OS whether this is the right driver for the device. */ | | 412 | /* reports back to the OS whether this is the right driver for the device. */ |
413 | /* */ | | 413 | /* */ |
414 | /* Returns: */ | | 414 | /* Returns: */ |
415 | /* BUS_PROBE_DEFAULT on success, positive value on failure. */ | | 415 | /* BUS_PROBE_DEFAULT on success, positive value on failure. */ |
416 | /****************************************************************************/ | | 416 | /****************************************************************************/ |
417 | static const struct bnx_product * | | 417 | static const struct bnx_product * |
418 | bnx_lookup(const struct pci_attach_args *pa) | | 418 | bnx_lookup(const struct pci_attach_args *pa) |
419 | { | | 419 | { |
420 | int i; | | 420 | int i; |
421 | pcireg_t subid; | | 421 | pcireg_t subid; |
422 | | | 422 | |
423 | for (i = 0; i < __arraycount(bnx_devices); i++) { | | 423 | for (i = 0; i < __arraycount(bnx_devices); i++) { |
424 | if (PCI_VENDOR(pa->pa_id) != bnx_devices[i].bp_vendor || | | 424 | if (PCI_VENDOR(pa->pa_id) != bnx_devices[i].bp_vendor || |
425 | PCI_PRODUCT(pa->pa_id) != bnx_devices[i].bp_product) | | 425 | PCI_PRODUCT(pa->pa_id) != bnx_devices[i].bp_product) |
426 | continue; | | 426 | continue; |
427 | if (!bnx_devices[i].bp_subvendor) | | 427 | if (!bnx_devices[i].bp_subvendor) |
428 | return &bnx_devices[i]; | | 428 | return &bnx_devices[i]; |
429 | subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); | | 429 | subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); |
430 | if (PCI_VENDOR(subid) == bnx_devices[i].bp_subvendor && | | 430 | if (PCI_VENDOR(subid) == bnx_devices[i].bp_subvendor && |
431 | PCI_PRODUCT(subid) == bnx_devices[i].bp_subproduct) | | 431 | PCI_PRODUCT(subid) == bnx_devices[i].bp_subproduct) |
432 | return &bnx_devices[i]; | | 432 | return &bnx_devices[i]; |
433 | } | | 433 | } |
434 | | | 434 | |
435 | return NULL; | | 435 | return NULL; |
436 | } | | 436 | } |
437 | static int | | 437 | static int |
438 | bnx_probe(device_t parent, cfdata_t match, void *aux) | | 438 | bnx_probe(device_t parent, cfdata_t match, void *aux) |
439 | { | | 439 | { |
440 | struct pci_attach_args *pa = (struct pci_attach_args *)aux; | | 440 | struct pci_attach_args *pa = (struct pci_attach_args *)aux; |
441 | | | 441 | |
442 | if (bnx_lookup(pa) != NULL) | | 442 | if (bnx_lookup(pa) != NULL) |
443 | return (1); | | 443 | return (1); |
444 | | | 444 | |
445 | return (0); | | 445 | return (0); |
446 | } | | 446 | } |
447 | | | 447 | |
448 | /****************************************************************************/ | | 448 | /****************************************************************************/ |
449 | /* Device attach function. */ | | 449 | /* Device attach function. */ |
450 | /* */ | | 450 | /* */ |
451 | /* Allocates device resources, performs secondary chip identification, */ | | 451 | /* Allocates device resources, performs secondary chip identification, */ |
452 | /* resets and initializes the hardware, and initializes driver instance */ | | 452 | /* resets and initializes the hardware, and initializes driver instance */ |
453 | /* variables. */ | | 453 | /* variables. */ |
454 | /* */ | | 454 | /* */ |
455 | /* Returns: */ | | 455 | /* Returns: */ |
456 | /* 0 on success, positive value on failure. */ | | 456 | /* 0 on success, positive value on failure. */ |
457 | /****************************************************************************/ | | 457 | /****************************************************************************/ |
458 | void | | 458 | void |
459 | bnx_attach(device_t parent, device_t self, void *aux) | | 459 | bnx_attach(device_t parent, device_t self, void *aux) |
460 | { | | 460 | { |
461 | const struct bnx_product *bp; | | 461 | const struct bnx_product *bp; |
462 | struct bnx_softc *sc = device_private(self); | | 462 | struct bnx_softc *sc = device_private(self); |
463 | prop_dictionary_t dict; | | 463 | prop_dictionary_t dict; |
464 | struct pci_attach_args *pa = aux; | | 464 | struct pci_attach_args *pa = aux; |
465 | pci_chipset_tag_t pc = pa->pa_pc; | | 465 | pci_chipset_tag_t pc = pa->pa_pc; |
466 | pci_intr_handle_t ih; | | 466 | pci_intr_handle_t ih; |
467 | const char *intrstr = NULL; | | 467 | const char *intrstr = NULL; |
468 | u_int32_t command; | | 468 | u_int32_t command; |
469 | struct ifnet *ifp; | | 469 | struct ifnet *ifp; |
470 | u_int32_t val; | | 470 | u_int32_t val; |
471 | int mii_flags = MIIF_FORCEANEG; | | 471 | int mii_flags = MIIF_FORCEANEG; |
472 | pcireg_t memtype; | | 472 | pcireg_t memtype; |
473 | | | 473 | |
474 | if (bnx_tx_pool == NULL) { | | 474 | if (bnx_tx_pool == NULL) { |
475 | bnx_tx_pool = malloc(sizeof(*bnx_tx_pool), M_DEVBUF, M_NOWAIT); | | 475 | bnx_tx_pool = malloc(sizeof(*bnx_tx_pool), M_DEVBUF, M_NOWAIT); |
476 | if (bnx_tx_pool != NULL) { | | 476 | if (bnx_tx_pool != NULL) { |
477 | pool_init(bnx_tx_pool, sizeof(struct bnx_pkt), | | 477 | pool_init(bnx_tx_pool, sizeof(struct bnx_pkt), |
478 | 0, 0, 0, "bnxpkts", NULL, IPL_NET); | | 478 | 0, 0, 0, "bnxpkts", NULL, IPL_NET); |
479 | } else { | | 479 | } else { |
480 | aprint_error(": can't alloc bnx_tx_pool\n"); | | 480 | aprint_error(": can't alloc bnx_tx_pool\n"); |
481 | return; | | 481 | return; |
482 | } | | 482 | } |
483 | } | | 483 | } |
484 | | | 484 | |
485 | bp = bnx_lookup(pa); | | 485 | bp = bnx_lookup(pa); |
486 | if (bp == NULL) | | 486 | if (bp == NULL) |
487 | panic("unknown device"); | | 487 | panic("unknown device"); |
488 | | | 488 | |
489 | sc->bnx_dev = self; | | 489 | sc->bnx_dev = self; |
490 | | | 490 | |
491 | aprint_naive("\n"); | | 491 | aprint_naive("\n"); |
492 | aprint_normal(": %s\n", bp->bp_name); | | 492 | aprint_normal(": %s\n", bp->bp_name); |
493 | | | 493 | |
494 | sc->bnx_pa = *pa; | | 494 | sc->bnx_pa = *pa; |
495 | | | 495 | |
496 | /* | | 496 | /* |
497 | * Map control/status registers. | | 497 | * Map control/status registers. |
498 | */ | | 498 | */ |
499 | command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | | 499 | command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); |
500 | command |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; | | 500 | command |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; |
501 | pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); | | 501 | pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); |
502 | command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | | 502 | command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); |
503 | | | 503 | |
504 | if (!(command & PCI_COMMAND_MEM_ENABLE)) { | | 504 | if (!(command & PCI_COMMAND_MEM_ENABLE)) { |
505 | aprint_error_dev(sc->bnx_dev, | | 505 | aprint_error_dev(sc->bnx_dev, |
506 | "failed to enable memory mapping!\n"); | | 506 | "failed to enable memory mapping!\n"); |
507 | return; | | 507 | return; |
508 | } | | 508 | } |
509 | | | 509 | |
510 | memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BNX_PCI_BAR0); | | 510 | memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BNX_PCI_BAR0); |
511 | if (pci_mapreg_map(pa, BNX_PCI_BAR0, memtype, 0, &sc->bnx_btag, | | 511 | if (pci_mapreg_map(pa, BNX_PCI_BAR0, memtype, 0, &sc->bnx_btag, |
512 | &sc->bnx_bhandle, NULL, &sc->bnx_size)) { | | 512 | &sc->bnx_bhandle, NULL, &sc->bnx_size)) { |
513 | aprint_error_dev(sc->bnx_dev, "can't find mem space\n"); | | 513 | aprint_error_dev(sc->bnx_dev, "can't find mem space\n"); |
514 | return; | | 514 | return; |
515 | } | | 515 | } |
516 | | | 516 | |
517 | if (pci_intr_map(pa, &ih)) { | | 517 | if (pci_intr_map(pa, &ih)) { |
518 | aprint_error_dev(sc->bnx_dev, "couldn't map interrupt\n"); | | 518 | aprint_error_dev(sc->bnx_dev, "couldn't map interrupt\n"); |
519 | goto bnx_attach_fail; | | 519 | goto bnx_attach_fail; |
520 | } | | 520 | } |
521 | | | 521 | |
522 | intrstr = pci_intr_string(pc, ih); | | 522 | intrstr = pci_intr_string(pc, ih); |
523 | | | 523 | |
524 | /* | | 524 | /* |
525 | * Configure byte swap and enable indirect register access. | | 525 | * Configure byte swap and enable indirect register access. |
526 | * Rely on CPU to do target byte swapping on big endian systems. | | 526 | * Rely on CPU to do target byte swapping on big endian systems. |
527 | * Access to registers outside of PCI configurtion space are not | | 527 | * Access to registers outside of PCI configurtion space are not |
528 | * valid until this is done. | | 528 | * valid until this is done. |
529 | */ | | 529 | */ |
530 | pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_MISC_CONFIG, | | 530 | pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_MISC_CONFIG, |
531 | BNX_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | | | 531 | BNX_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | |
532 | BNX_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP); | | 532 | BNX_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP); |
533 | | | 533 | |
534 | /* Save ASIC revsion info. */ | | 534 | /* Save ASIC revsion info. */ |
535 | sc->bnx_chipid = REG_RD(sc, BNX_MISC_ID); | | 535 | sc->bnx_chipid = REG_RD(sc, BNX_MISC_ID); |
536 | | | 536 | |
537 | /* | | 537 | /* |
538 | * Find the base address for shared memory access. | | 538 | * Find the base address for shared memory access. |
539 | * Newer versions of bootcode use a signature and offset | | 539 | * Newer versions of bootcode use a signature and offset |
540 | * while older versions use a fixed address. | | 540 | * while older versions use a fixed address. |
541 | */ | | 541 | */ |
542 | val = REG_RD_IND(sc, BNX_SHM_HDR_SIGNATURE); | | 542 | val = REG_RD_IND(sc, BNX_SHM_HDR_SIGNATURE); |
543 | if ((val & BNX_SHM_HDR_SIGNATURE_SIG_MASK) == BNX_SHM_HDR_SIGNATURE_SIG) | | 543 | if ((val & BNX_SHM_HDR_SIGNATURE_SIG_MASK) == BNX_SHM_HDR_SIGNATURE_SIG) |
544 | sc->bnx_shmem_base = REG_RD_IND(sc, BNX_SHM_HDR_ADDR_0 + | | 544 | sc->bnx_shmem_base = REG_RD_IND(sc, BNX_SHM_HDR_ADDR_0 + |
545 | (sc->bnx_pa.pa_function << 2)); | | 545 | (sc->bnx_pa.pa_function << 2)); |
546 | else | | 546 | else |
547 | sc->bnx_shmem_base = HOST_VIEW_SHMEM_BASE; | | 547 | sc->bnx_shmem_base = HOST_VIEW_SHMEM_BASE; |
548 | | | 548 | |
549 | DBPRINT(sc, BNX_INFO, "bnx_shmem_base = 0x%08X\n", sc->bnx_shmem_base); | | 549 | DBPRINT(sc, BNX_INFO, "bnx_shmem_base = 0x%08X\n", sc->bnx_shmem_base); |
550 | | | 550 | |
551 | /* Set initial device and PHY flags */ | | 551 | /* Set initial device and PHY flags */ |
552 | sc->bnx_flags = 0; | | 552 | sc->bnx_flags = 0; |
553 | sc->bnx_phy_flags = 0; | | 553 | sc->bnx_phy_flags = 0; |
554 | | | 554 | |
555 | /* Get PCI bus information (speed and type). */ | | 555 | /* Get PCI bus information (speed and type). */ |
556 | val = REG_RD(sc, BNX_PCICFG_MISC_STATUS); | | 556 | val = REG_RD(sc, BNX_PCICFG_MISC_STATUS); |
557 | if (val & BNX_PCICFG_MISC_STATUS_PCIX_DET) { | | 557 | if (val & BNX_PCICFG_MISC_STATUS_PCIX_DET) { |
558 | u_int32_t clkreg; | | 558 | u_int32_t clkreg; |
559 | | | 559 | |
560 | sc->bnx_flags |= BNX_PCIX_FLAG; | | 560 | sc->bnx_flags |= BNX_PCIX_FLAG; |
561 | | | 561 | |
562 | clkreg = REG_RD(sc, BNX_PCICFG_PCI_CLOCK_CONTROL_BITS); | | 562 | clkreg = REG_RD(sc, BNX_PCICFG_PCI_CLOCK_CONTROL_BITS); |
563 | | | 563 | |
564 | clkreg &= BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET; | | 564 | clkreg &= BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET; |
565 | switch (clkreg) { | | 565 | switch (clkreg) { |
566 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ: | | 566 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ: |
567 | sc->bus_speed_mhz = 133; | | 567 | sc->bus_speed_mhz = 133; |
568 | break; | | 568 | break; |
569 | | | 569 | |
570 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ: | | 570 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ: |
571 | sc->bus_speed_mhz = 100; | | 571 | sc->bus_speed_mhz = 100; |
572 | break; | | 572 | break; |
573 | | | 573 | |
574 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ: | | 574 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ: |
575 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ: | | 575 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ: |
576 | sc->bus_speed_mhz = 66; | | 576 | sc->bus_speed_mhz = 66; |
577 | break; | | 577 | break; |
578 | | | 578 | |
579 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ: | | 579 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ: |
580 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ: | | 580 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ: |
581 | sc->bus_speed_mhz = 50; | | 581 | sc->bus_speed_mhz = 50; |
582 | break; | | 582 | break; |
583 | | | 583 | |
584 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW: | | 584 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW: |
585 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ: | | 585 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ: |
586 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ: | | 586 | case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ: |
587 | sc->bus_speed_mhz = 33; | | 587 | sc->bus_speed_mhz = 33; |
588 | break; | | 588 | break; |
589 | } | | 589 | } |
590 | } else if (val & BNX_PCICFG_MISC_STATUS_M66EN) | | 590 | } else if (val & BNX_PCICFG_MISC_STATUS_M66EN) |
591 | sc->bus_speed_mhz = 66; | | 591 | sc->bus_speed_mhz = 66; |
592 | else | | 592 | else |
593 | sc->bus_speed_mhz = 33; | | 593 | sc->bus_speed_mhz = 33; |
594 | | | 594 | |
595 | if (val & BNX_PCICFG_MISC_STATUS_32BIT_DET) | | 595 | if (val & BNX_PCICFG_MISC_STATUS_32BIT_DET) |
596 | sc->bnx_flags |= BNX_PCI_32BIT_FLAG; | | 596 | sc->bnx_flags |= BNX_PCI_32BIT_FLAG; |
597 | | | 597 | |
598 | /* Reset the controller. */ | | 598 | /* Reset the controller. */ |
599 | if (bnx_reset(sc, BNX_DRV_MSG_CODE_RESET)) | | 599 | if (bnx_reset(sc, BNX_DRV_MSG_CODE_RESET)) |
600 | goto bnx_attach_fail; | | 600 | goto bnx_attach_fail; |
601 | | | 601 | |
602 | /* Initialize the controller. */ | | 602 | /* Initialize the controller. */ |
603 | if (bnx_chipinit(sc)) { | | 603 | if (bnx_chipinit(sc)) { |
604 | aprint_error_dev(sc->bnx_dev, | | 604 | aprint_error_dev(sc->bnx_dev, |
605 | "Controller initialization failed!\n"); | | 605 | "Controller initialization failed!\n"); |
606 | goto bnx_attach_fail; | | 606 | goto bnx_attach_fail; |
607 | } | | 607 | } |
608 | | | 608 | |
609 | /* Perform NVRAM test. */ | | 609 | /* Perform NVRAM test. */ |
610 | if (bnx_nvram_test(sc)) { | | 610 | if (bnx_nvram_test(sc)) { |
611 | aprint_error_dev(sc->bnx_dev, "NVRAM test failed!\n"); | | 611 | aprint_error_dev(sc->bnx_dev, "NVRAM test failed!\n"); |
612 | goto bnx_attach_fail; | | 612 | goto bnx_attach_fail; |
613 | } | | 613 | } |
614 | | | 614 | |
615 | /* Fetch the permanent Ethernet MAC address. */ | | 615 | /* Fetch the permanent Ethernet MAC address. */ |
616 | bnx_get_mac_addr(sc); | | 616 | bnx_get_mac_addr(sc); |
617 | aprint_normal_dev(sc->bnx_dev, "Ethernet address %s\n", | | 617 | aprint_normal_dev(sc->bnx_dev, "Ethernet address %s\n", |
618 | ether_sprintf(sc->eaddr)); | | 618 | ether_sprintf(sc->eaddr)); |
619 | | | 619 | |
620 | /* | | 620 | /* |
621 | * Trip points control how many BDs | | 621 | * Trip points control how many BDs |
622 | * should be ready before generating an | | 622 | * should be ready before generating an |
623 | * interrupt while ticks control how long | | 623 | * interrupt while ticks control how long |
624 | * a BD can sit in the chain before | | 624 | * a BD can sit in the chain before |
625 | * generating an interrupt. Set the default | | 625 | * generating an interrupt. Set the default |
626 | * values for the RX and TX rings. | | 626 | * values for the RX and TX rings. |
627 | */ | | 627 | */ |
628 | | | 628 | |
629 | #ifdef BNX_DEBUG | | 629 | #ifdef BNX_DEBUG |
630 | /* Force more frequent interrupts. */ | | 630 | /* Force more frequent interrupts. */ |
631 | sc->bnx_tx_quick_cons_trip_int = 1; | | 631 | sc->bnx_tx_quick_cons_trip_int = 1; |
632 | sc->bnx_tx_quick_cons_trip = 1; | | 632 | sc->bnx_tx_quick_cons_trip = 1; |
633 | sc->bnx_tx_ticks_int = 0; | | 633 | sc->bnx_tx_ticks_int = 0; |
634 | sc->bnx_tx_ticks = 0; | | 634 | sc->bnx_tx_ticks = 0; |
635 | | | 635 | |
636 | sc->bnx_rx_quick_cons_trip_int = 1; | | 636 | sc->bnx_rx_quick_cons_trip_int = 1; |
637 | sc->bnx_rx_quick_cons_trip = 1; | | 637 | sc->bnx_rx_quick_cons_trip = 1; |
638 | sc->bnx_rx_ticks_int = 0; | | 638 | sc->bnx_rx_ticks_int = 0; |
639 | sc->bnx_rx_ticks = 0; | | 639 | sc->bnx_rx_ticks = 0; |
640 | #else | | 640 | #else |
641 | sc->bnx_tx_quick_cons_trip_int = 20; | | 641 | sc->bnx_tx_quick_cons_trip_int = 20; |
642 | sc->bnx_tx_quick_cons_trip = 20; | | 642 | sc->bnx_tx_quick_cons_trip = 20; |
643 | sc->bnx_tx_ticks_int = 80; | | 643 | sc->bnx_tx_ticks_int = 80; |
644 | sc->bnx_tx_ticks = 80; | | 644 | sc->bnx_tx_ticks = 80; |
645 | | | 645 | |
646 | sc->bnx_rx_quick_cons_trip_int = 6; | | 646 | sc->bnx_rx_quick_cons_trip_int = 6; |
647 | sc->bnx_rx_quick_cons_trip = 6; | | 647 | sc->bnx_rx_quick_cons_trip = 6; |
648 | sc->bnx_rx_ticks_int = 18; | | 648 | sc->bnx_rx_ticks_int = 18; |
649 | sc->bnx_rx_ticks = 18; | | 649 | sc->bnx_rx_ticks = 18; |
650 | #endif | | 650 | #endif |
651 | | | 651 | |
652 | /* Update statistics once every second. */ | | 652 | /* Update statistics once every second. */ |
653 | sc->bnx_stats_ticks = 1000000 & 0xffff00; | | 653 | sc->bnx_stats_ticks = 1000000 & 0xffff00; |
654 | | | 654 | |
655 | /* Find the media type for the adapter. */ | | 655 | /* Find the media type for the adapter. */ |
656 | bnx_get_media(sc); | | 656 | bnx_get_media(sc); |
657 | | | 657 | |
658 | /* | | 658 | /* |
659 | * Store config data needed by the PHY driver for | | 659 | * Store config data needed by the PHY driver for |
660 | * backplane applications | | 660 | * backplane applications |
661 | */ | | 661 | */ |
662 | sc->bnx_shared_hw_cfg = REG_RD_IND(sc, sc->bnx_shmem_base + | | 662 | sc->bnx_shared_hw_cfg = REG_RD_IND(sc, sc->bnx_shmem_base + |
663 | BNX_SHARED_HW_CFG_CONFIG); | | 663 | BNX_SHARED_HW_CFG_CONFIG); |
664 | sc->bnx_port_hw_cfg = REG_RD_IND(sc, sc->bnx_shmem_base + | | 664 | sc->bnx_port_hw_cfg = REG_RD_IND(sc, sc->bnx_shmem_base + |
665 | BNX_PORT_HW_CFG_CONFIG); | | 665 | BNX_PORT_HW_CFG_CONFIG); |
666 | | | 666 | |
667 | /* Allocate DMA memory resources. */ | | 667 | /* Allocate DMA memory resources. */ |
668 | sc->bnx_dmatag = pa->pa_dmat; | | 668 | sc->bnx_dmatag = pa->pa_dmat; |
669 | if (bnx_dma_alloc(sc)) { | | 669 | if (bnx_dma_alloc(sc)) { |
670 | aprint_error_dev(sc->bnx_dev, | | 670 | aprint_error_dev(sc->bnx_dev, |
671 | "DMA resource allocation failed!\n"); | | 671 | "DMA resource allocation failed!\n"); |
672 | goto bnx_attach_fail; | | 672 | goto bnx_attach_fail; |
673 | } | | 673 | } |
674 | | | 674 | |
675 | /* Initialize the ifnet interface. */ | | 675 | /* Initialize the ifnet interface. */ |
676 | ifp = &sc->bnx_ec.ec_if; | | 676 | ifp = &sc->bnx_ec.ec_if; |
677 | ifp->if_softc = sc; | | 677 | ifp->if_softc = sc; |
678 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | | 678 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; |
679 | ifp->if_ioctl = bnx_ioctl; | | 679 | ifp->if_ioctl = bnx_ioctl; |
680 | ifp->if_stop = bnx_stop; | | 680 | ifp->if_stop = bnx_stop; |
681 | ifp->if_start = bnx_start; | | 681 | ifp->if_start = bnx_start; |
682 | ifp->if_init = bnx_init; | | 682 | ifp->if_init = bnx_init; |
683 | ifp->if_timer = 0; | | 683 | ifp->if_timer = 0; |
684 | ifp->if_watchdog = bnx_watchdog; | | 684 | ifp->if_watchdog = bnx_watchdog; |
685 | IFQ_SET_MAXLEN(&ifp->if_snd, USABLE_TX_BD - 1); | | 685 | IFQ_SET_MAXLEN(&ifp->if_snd, USABLE_TX_BD - 1); |
686 | IFQ_SET_READY(&ifp->if_snd); | | 686 | IFQ_SET_READY(&ifp->if_snd); |
687 | memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); | | 687 | memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); |
688 | | | 688 | |
689 | sc->bnx_ec.ec_capabilities |= ETHERCAP_JUMBO_MTU | | | 689 | sc->bnx_ec.ec_capabilities |= ETHERCAP_JUMBO_MTU | |
690 | ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING; | | 690 | ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING; |
691 | | | 691 | |
692 | ifp->if_capabilities |= | | 692 | ifp->if_capabilities |= |
693 | IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx | | | 693 | IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx | |
694 | IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx | | | 694 | IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx | |
695 | IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx; | | 695 | IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx; |
696 | | | 696 | |
697 | /* Hookup IRQ last. */ | | 697 | /* Hookup IRQ last. */ |
698 | sc->bnx_intrhand = pci_intr_establish(pc, ih, IPL_NET, bnx_intr, sc); | | 698 | sc->bnx_intrhand = pci_intr_establish(pc, ih, IPL_NET, bnx_intr, sc); |
699 | if (sc->bnx_intrhand == NULL) { | | 699 | if (sc->bnx_intrhand == NULL) { |
700 | aprint_error_dev(self, "couldn't establish interrupt"); | | 700 | aprint_error_dev(self, "couldn't establish interrupt"); |
701 | if (intrstr != NULL) | | 701 | if (intrstr != NULL) |
702 | aprint_error(" at %s", intrstr); | | 702 | aprint_error(" at %s", intrstr); |
703 | aprint_error("\n"); | | 703 | aprint_error("\n"); |
704 | goto bnx_attach_fail; | | 704 | goto bnx_attach_fail; |
705 | } | | 705 | } |
706 | aprint_normal_dev(sc->bnx_dev, "interrupting at %s\n", intrstr); | | 706 | aprint_normal_dev(sc->bnx_dev, "interrupting at %s\n", intrstr); |
707 | | | 707 | |
708 | /* create workqueue to handle packet allocations */ | | 708 | /* create workqueue to handle packet allocations */ |
709 | if (workqueue_create(&sc->bnx_wq, device_xname(self), | | 709 | if (workqueue_create(&sc->bnx_wq, device_xname(self), |
710 | bnx_alloc_pkts, sc, PRI_NONE, IPL_NET, WQ_MPSAFE) != 0) { | | 710 | bnx_alloc_pkts, sc, PRI_NONE, IPL_NET, 0) != 0) { |
711 | aprint_error_dev(self, "failed to create workqueue\n"); | | 711 | aprint_error_dev(self, "failed to create workqueue\n"); |
712 | goto bnx_attach_fail; | | 712 | goto bnx_attach_fail; |
713 | } | | 713 | } |
714 | | | 714 | |
715 | sc->bnx_mii.mii_ifp = ifp; | | 715 | sc->bnx_mii.mii_ifp = ifp; |
716 | sc->bnx_mii.mii_readreg = bnx_miibus_read_reg; | | 716 | sc->bnx_mii.mii_readreg = bnx_miibus_read_reg; |
717 | sc->bnx_mii.mii_writereg = bnx_miibus_write_reg; | | 717 | sc->bnx_mii.mii_writereg = bnx_miibus_write_reg; |
718 | sc->bnx_mii.mii_statchg = bnx_miibus_statchg; | | 718 | sc->bnx_mii.mii_statchg = bnx_miibus_statchg; |
719 | | | 719 | |
720 | /* Handle any special PHY initialization for SerDes PHYs. */ | | 720 | /* Handle any special PHY initialization for SerDes PHYs. */ |
721 | bnx_init_media(sc); | | 721 | bnx_init_media(sc); |
722 | | | 722 | |
723 | sc->bnx_ec.ec_mii = &sc->bnx_mii; | | 723 | sc->bnx_ec.ec_mii = &sc->bnx_mii; |
724 | ifmedia_init(&sc->bnx_mii.mii_media, 0, ether_mediachange, | | 724 | ifmedia_init(&sc->bnx_mii.mii_media, 0, ether_mediachange, |
725 | ether_mediastatus); | | 725 | ether_mediastatus); |
726 | | | 726 | |
727 | /* set phyflags and chipid before mii_attach() */ | | 727 | /* set phyflags and chipid before mii_attach() */ |
728 | dict = device_properties(self); | | 728 | dict = device_properties(self); |
729 | prop_dictionary_set_uint32(dict, "phyflags", sc->bnx_phy_flags); | | 729 | prop_dictionary_set_uint32(dict, "phyflags", sc->bnx_phy_flags); |
730 | prop_dictionary_set_uint32(dict, "chipid", sc->bnx_chipid); | | 730 | prop_dictionary_set_uint32(dict, "chipid", sc->bnx_chipid); |
731 | | | 731 | |
732 | if (sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG) | | 732 | if (sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG) |
733 | mii_flags |= MIIF_HAVEFIBER; | | 733 | mii_flags |= MIIF_HAVEFIBER; |
734 | mii_attach(self, &sc->bnx_mii, 0xffffffff, | | 734 | mii_attach(self, &sc->bnx_mii, 0xffffffff, |
735 | MII_PHY_ANY, MII_OFFSET_ANY, mii_flags); | | 735 | MII_PHY_ANY, MII_OFFSET_ANY, mii_flags); |
736 | | | 736 | |
737 | if (LIST_EMPTY(&sc->bnx_mii.mii_phys)) { | | 737 | if (LIST_EMPTY(&sc->bnx_mii.mii_phys)) { |
738 | aprint_error_dev(self, "no PHY found!\n"); | | 738 | aprint_error_dev(self, "no PHY found!\n"); |
739 | ifmedia_add(&sc->bnx_mii.mii_media, | | 739 | ifmedia_add(&sc->bnx_mii.mii_media, |
740 | IFM_ETHER|IFM_MANUAL, 0, NULL); | | 740 | IFM_ETHER|IFM_MANUAL, 0, NULL); |
741 | ifmedia_set(&sc->bnx_mii.mii_media, | | 741 | ifmedia_set(&sc->bnx_mii.mii_media, |
742 | IFM_ETHER|IFM_MANUAL); | | 742 | IFM_ETHER|IFM_MANUAL); |
743 | } else { | | 743 | } else { |
744 | ifmedia_set(&sc->bnx_mii.mii_media, | | 744 | ifmedia_set(&sc->bnx_mii.mii_media, |
745 | IFM_ETHER|IFM_AUTO); | | 745 | IFM_ETHER|IFM_AUTO); |
746 | } | | 746 | } |
747 | | | 747 | |
748 | /* Attach to the Ethernet interface list. */ | | 748 | /* Attach to the Ethernet interface list. */ |
749 | if_attach(ifp); | | 749 | if_attach(ifp); |
750 | ether_ifattach(ifp,sc->eaddr); | | 750 | ether_ifattach(ifp,sc->eaddr); |
751 | | | 751 | |
752 | callout_init(&sc->bnx_timeout, 0); | | 752 | callout_init(&sc->bnx_timeout, 0); |
753 | | | 753 | |
754 | if (pmf_device_register(self, NULL, NULL)) | | 754 | if (pmf_device_register(self, NULL, NULL)) |
755 | pmf_class_network_register(self, ifp); | | 755 | pmf_class_network_register(self, ifp); |
756 | else | | 756 | else |
757 | aprint_error_dev(self, "couldn't establish power handler\n"); | | 757 | aprint_error_dev(self, "couldn't establish power handler\n"); |
758 | | | 758 | |
759 | /* Print some important debugging info. */ | | 759 | /* Print some important debugging info. */ |
760 | DBRUN(BNX_INFO, bnx_dump_driver_state(sc)); | | 760 | DBRUN(BNX_INFO, bnx_dump_driver_state(sc)); |
761 | | | 761 | |
762 | goto bnx_attach_exit; | | 762 | goto bnx_attach_exit; |
763 | | | 763 | |
764 | bnx_attach_fail: | | 764 | bnx_attach_fail: |
765 | bnx_release_resources(sc); | | 765 | bnx_release_resources(sc); |
766 | | | 766 | |
767 | bnx_attach_exit: | | 767 | bnx_attach_exit: |
768 | DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __func__); | | 768 | DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __func__); |
769 | } | | 769 | } |
770 | | | 770 | |
771 | /****************************************************************************/ | | 771 | /****************************************************************************/ |
772 | /* Device detach function. */ | | 772 | /* Device detach function. */ |
773 | /* */ | | 773 | /* */ |
774 | /* Stops the controller, resets the controller, and releases resources. */ | | 774 | /* Stops the controller, resets the controller, and releases resources. */ |
775 | /* */ | | 775 | /* */ |
776 | /* Returns: */ | | 776 | /* Returns: */ |
777 | /* 0 on success, positive value on failure. */ | | 777 | /* 0 on success, positive value on failure. */ |
778 | /****************************************************************************/ | | 778 | /****************************************************************************/ |
779 | int | | 779 | int |
780 | bnx_detach(device_t dev, int flags) | | 780 | bnx_detach(device_t dev, int flags) |
781 | { | | 781 | { |
782 | int s; | | 782 | int s; |
783 | struct bnx_softc *sc; | | 783 | struct bnx_softc *sc; |
784 | struct ifnet *ifp; | | 784 | struct ifnet *ifp; |
785 | | | 785 | |
786 | sc = device_private(dev); | | 786 | sc = device_private(dev); |
787 | ifp = &sc->bnx_ec.ec_if; | | 787 | ifp = &sc->bnx_ec.ec_if; |
788 | | | 788 | |
789 | DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __func__); | | 789 | DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __func__); |
790 | | | 790 | |
791 | /* Stop and reset the controller. */ | | 791 | /* Stop and reset the controller. */ |
792 | s = splnet(); | | 792 | s = splnet(); |
793 | if (ifp->if_flags & IFF_RUNNING) | | 793 | if (ifp->if_flags & IFF_RUNNING) |
794 | bnx_stop(ifp, 1); | | 794 | bnx_stop(ifp, 1); |
795 | else { | | 795 | else { |
796 | /* Disable the transmit/receive blocks. */ | | 796 | /* Disable the transmit/receive blocks. */ |
797 | REG_WR(sc, BNX_MISC_ENABLE_CLR_BITS, 0x5ffffff); | | 797 | REG_WR(sc, BNX_MISC_ENABLE_CLR_BITS, 0x5ffffff); |
798 | REG_RD(sc, BNX_MISC_ENABLE_CLR_BITS); | | 798 | REG_RD(sc, BNX_MISC_ENABLE_CLR_BITS); |
799 | DELAY(20); | | 799 | DELAY(20); |
800 | bnx_disable_intr(sc); | | 800 | bnx_disable_intr(sc); |
801 | bnx_reset(sc, BNX_DRV_MSG_CODE_RESET); | | 801 | bnx_reset(sc, BNX_DRV_MSG_CODE_RESET); |
802 | } | | 802 | } |
803 | | | 803 | |
804 | splx(s); | | 804 | splx(s); |
805 | | | 805 | |
806 | pmf_device_deregister(dev); | | 806 | pmf_device_deregister(dev); |
807 | callout_destroy(&sc->bnx_timeout); | | 807 | callout_destroy(&sc->bnx_timeout); |
808 | ether_ifdetach(ifp); | | 808 | ether_ifdetach(ifp); |
809 | workqueue_destroy(sc->bnx_wq); | | 809 | workqueue_destroy(sc->bnx_wq); |
810 | | | 810 | |
811 | /* Delete all remaining media. */ | | 811 | /* Delete all remaining media. */ |
812 | ifmedia_delete_instance(&sc->bnx_mii.mii_media, IFM_INST_ANY); | | 812 | ifmedia_delete_instance(&sc->bnx_mii.mii_media, IFM_INST_ANY); |
813 | | | 813 | |
814 | if_detach(ifp); | | 814 | if_detach(ifp); |
815 | mii_detach(&sc->bnx_mii, MII_PHY_ANY, MII_OFFSET_ANY); | | 815 | mii_detach(&sc->bnx_mii, MII_PHY_ANY, MII_OFFSET_ANY); |
816 | | | 816 | |
817 | /* Release all remaining resources. */ | | 817 | /* Release all remaining resources. */ |
818 | bnx_release_resources(sc); | | 818 | bnx_release_resources(sc); |
819 | | | 819 | |
820 | DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __func__); | | 820 | DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __func__); |
821 | | | 821 | |
822 | return(0); | | 822 | return(0); |
823 | } | | 823 | } |
824 | | | 824 | |
825 | /****************************************************************************/ | | 825 | /****************************************************************************/ |
826 | /* Indirect register read. */ | | 826 | /* Indirect register read. */ |
827 | /* */ | | 827 | /* */ |
828 | /* Reads NetXtreme II registers using an index/data register pair in PCI */ | | 828 | /* Reads NetXtreme II registers using an index/data register pair in PCI */ |
829 | /* configuration space. Using this mechanism avoids issues with posted */ | | 829 | /* configuration space. Using this mechanism avoids issues with posted */ |
830 | /* reads but is much slower than memory-mapped I/O. */ | | 830 | /* reads but is much slower than memory-mapped I/O. */ |
831 | /* */ | | 831 | /* */ |
832 | /* Returns: */ | | 832 | /* Returns: */ |
833 | /* The value of the register. */ | | 833 | /* The value of the register. */ |
834 | /****************************************************************************/ | | 834 | /****************************************************************************/ |
835 | u_int32_t | | 835 | u_int32_t |
836 | bnx_reg_rd_ind(struct bnx_softc *sc, u_int32_t offset) | | 836 | bnx_reg_rd_ind(struct bnx_softc *sc, u_int32_t offset) |
837 | { | | 837 | { |
838 | struct pci_attach_args *pa = &(sc->bnx_pa); | | 838 | struct pci_attach_args *pa = &(sc->bnx_pa); |
839 | | | 839 | |
840 | pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW_ADDRESS, | | 840 | pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW_ADDRESS, |
841 | offset); | | 841 | offset); |
842 | #ifdef BNX_DEBUG | | 842 | #ifdef BNX_DEBUG |
843 | { | | 843 | { |
844 | u_int32_t val; | | 844 | u_int32_t val; |
845 | val = pci_conf_read(pa->pa_pc, pa->pa_tag, | | 845 | val = pci_conf_read(pa->pa_pc, pa->pa_tag, |
846 | BNX_PCICFG_REG_WINDOW); | | 846 | BNX_PCICFG_REG_WINDOW); |
847 | DBPRINT(sc, BNX_EXCESSIVE, "%s(); offset = 0x%08X, " | | 847 | DBPRINT(sc, BNX_EXCESSIVE, "%s(); offset = 0x%08X, " |
848 | "val = 0x%08X\n", __func__, offset, val); | | 848 | "val = 0x%08X\n", __func__, offset, val); |
849 | return (val); | | 849 | return (val); |
850 | } | | 850 | } |
851 | #else | | 851 | #else |
852 | return pci_conf_read(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW); | | 852 | return pci_conf_read(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW); |
853 | #endif | | 853 | #endif |
854 | } | | 854 | } |
855 | | | 855 | |
856 | /****************************************************************************/ | | 856 | /****************************************************************************/ |
857 | /* Indirect register write. */ | | 857 | /* Indirect register write. */ |
858 | /* */ | | 858 | /* */ |
859 | /* Writes NetXtreme II registers using an index/data register pair in PCI */ | | 859 | /* Writes NetXtreme II registers using an index/data register pair in PCI */ |
860 | /* configuration space. Using this mechanism avoids issues with posted */ | | 860 | /* configuration space. Using this mechanism avoids issues with posted */ |
861 | /* writes but is muchh slower than memory-mapped I/O. */ | | 861 | /* writes but is muchh slower than memory-mapped I/O. */ |
862 | /* */ | | 862 | /* */ |
863 | /* Returns: */ | | 863 | /* Returns: */ |
864 | /* Nothing. */ | | 864 | /* Nothing. */ |
865 | /****************************************************************************/ | | 865 | /****************************************************************************/ |
866 | void | | 866 | void |
867 | bnx_reg_wr_ind(struct bnx_softc *sc, u_int32_t offset, u_int32_t val) | | 867 | bnx_reg_wr_ind(struct bnx_softc *sc, u_int32_t offset, u_int32_t val) |
868 | { | | 868 | { |
869 | struct pci_attach_args *pa = &(sc->bnx_pa); | | 869 | struct pci_attach_args *pa = &(sc->bnx_pa); |
870 | | | 870 | |
871 | DBPRINT(sc, BNX_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n", | | 871 | DBPRINT(sc, BNX_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n", |
872 | __func__, offset, val); | | 872 | __func__, offset, val); |
873 | | | 873 | |
874 | pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW_ADDRESS, | | 874 | pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW_ADDRESS, |
875 | offset); | | 875 | offset); |
876 | pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW, val); | | 876 | pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW, val); |
877 | } | | 877 | } |
878 | | | 878 | |
879 | /****************************************************************************/ | | 879 | /****************************************************************************/ |
880 | /* Context memory write. */ | | 880 | /* Context memory write. */ |
881 | /* */ | | 881 | /* */ |
882 | /* The NetXtreme II controller uses context memory to track connection */ | | 882 | /* The NetXtreme II controller uses context memory to track connection */ |
883 | /* information for L2 and higher network protocols. */ | | 883 | /* information for L2 and higher network protocols. */ |
884 | /* */ | | 884 | /* */ |
885 | /* Returns: */ | | 885 | /* Returns: */ |
886 | /* Nothing. */ | | 886 | /* Nothing. */ |
887 | /****************************************************************************/ | | 887 | /****************************************************************************/ |
888 | void | | 888 | void |
889 | bnx_ctx_wr(struct bnx_softc *sc, u_int32_t cid_addr, u_int32_t ctx_offset, | | 889 | bnx_ctx_wr(struct bnx_softc *sc, u_int32_t cid_addr, u_int32_t ctx_offset, |
890 | u_int32_t ctx_val) | | 890 | u_int32_t ctx_val) |
891 | { | | 891 | { |
892 | u_int32_t idx, offset = ctx_offset + cid_addr; | | 892 | u_int32_t idx, offset = ctx_offset + cid_addr; |
893 | u_int32_t val, retry_cnt = 5; | | 893 | u_int32_t val, retry_cnt = 5; |
894 | | | 894 | |
895 | if (BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5709) { | | 895 | if (BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5709) { |
896 | REG_WR(sc, BNX_CTX_CTX_DATA, ctx_val); | | 896 | REG_WR(sc, BNX_CTX_CTX_DATA, ctx_val); |
897 | REG_WR(sc, BNX_CTX_CTX_CTRL, | | 897 | REG_WR(sc, BNX_CTX_CTX_CTRL, |
898 | (offset | BNX_CTX_CTX_CTRL_WRITE_REQ)); | | 898 | (offset | BNX_CTX_CTX_CTRL_WRITE_REQ)); |
899 | | | 899 | |
900 | for (idx = 0; idx < retry_cnt; idx++) { | | 900 | for (idx = 0; idx < retry_cnt; idx++) { |
901 | val = REG_RD(sc, BNX_CTX_CTX_CTRL); | | 901 | val = REG_RD(sc, BNX_CTX_CTX_CTRL); |
902 | if ((val & BNX_CTX_CTX_CTRL_WRITE_REQ) == 0) | | 902 | if ((val & BNX_CTX_CTX_CTRL_WRITE_REQ) == 0) |
903 | break; | | 903 | break; |
904 | DELAY(5); | | 904 | DELAY(5); |
905 | } | | 905 | } |
906 | | | 906 | |
907 | #if 0 | | 907 | #if 0 |
908 | if (val & BNX_CTX_CTX_CTRL_WRITE_REQ) | | 908 | if (val & BNX_CTX_CTX_CTRL_WRITE_REQ) |
909 | BNX_PRINTF("%s(%d); Unable to write CTX memory: " | | 909 | BNX_PRINTF("%s(%d); Unable to write CTX memory: " |
910 | "cid_addr = 0x%08X, offset = 0x%08X!\n", | | 910 | "cid_addr = 0x%08X, offset = 0x%08X!\n", |
911 | __FILE__, __LINE__, cid_addr, ctx_offset); | | 911 | __FILE__, __LINE__, cid_addr, ctx_offset); |
912 | #endif | | 912 | #endif |
913 | | | 913 | |
914 | } else { | | 914 | } else { |
915 | REG_WR(sc, BNX_CTX_DATA_ADR, offset); | | 915 | REG_WR(sc, BNX_CTX_DATA_ADR, offset); |
916 | REG_WR(sc, BNX_CTX_DATA, ctx_val); | | 916 | REG_WR(sc, BNX_CTX_DATA, ctx_val); |
917 | } | | 917 | } |
918 | } | | 918 | } |
919 | | | 919 | |
920 | /****************************************************************************/ | | 920 | /****************************************************************************/ |
921 | /* PHY register read. */ | | 921 | /* PHY register read. */ |
922 | /* */ | | 922 | /* */ |
923 | /* Implements register reads on the MII bus. */ | | 923 | /* Implements register reads on the MII bus. */ |
924 | /* */ | | 924 | /* */ |
925 | /* Returns: */ | | 925 | /* Returns: */ |
926 | /* The value of the register. */ | | 926 | /* The value of the register. */ |
927 | /****************************************************************************/ | | 927 | /****************************************************************************/ |
928 | int | | 928 | int |
929 | bnx_miibus_read_reg(device_t dev, int phy, int reg) | | 929 | bnx_miibus_read_reg(device_t dev, int phy, int reg) |
930 | { | | 930 | { |
931 | struct bnx_softc *sc = device_private(dev); | | 931 | struct bnx_softc *sc = device_private(dev); |
932 | u_int32_t val; | | 932 | u_int32_t val; |
933 | int i; | | 933 | int i; |
934 | | | 934 | |
935 | /* Make sure we are accessing the correct PHY address. */ | | 935 | /* Make sure we are accessing the correct PHY address. */ |
936 | if (phy != sc->bnx_phy_addr) { | | 936 | if (phy != sc->bnx_phy_addr) { |
937 | DBPRINT(sc, BNX_VERBOSE, | | 937 | DBPRINT(sc, BNX_VERBOSE, |
938 | "Invalid PHY address %d for PHY read!\n", phy); | | 938 | "Invalid PHY address %d for PHY read!\n", phy); |
939 | return(0); | | 939 | return(0); |
940 | } | | 940 | } |
941 | | | 941 | |
942 | /* | | 942 | /* |
943 | * The BCM5709S PHY is an IEEE Clause 45 PHY | | 943 | * The BCM5709S PHY is an IEEE Clause 45 PHY |
944 | * with special mappings to work with IEEE | | 944 | * with special mappings to work with IEEE |
945 | * Clause 22 register accesses. | | 945 | * Clause 22 register accesses. |
946 | */ | | 946 | */ |
947 | if ((sc->bnx_phy_flags & BNX_PHY_IEEE_CLAUSE_45_FLAG) != 0) { | | 947 | if ((sc->bnx_phy_flags & BNX_PHY_IEEE_CLAUSE_45_FLAG) != 0) { |
948 | if (reg >= MII_BMCR && reg <= MII_ANLPRNP) | | 948 | if (reg >= MII_BMCR && reg <= MII_ANLPRNP) |
949 | reg += 0x10; | | 949 | reg += 0x10; |
950 | } | | 950 | } |
951 | | | 951 | |
952 | if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { | | 952 | if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { |
953 | val = REG_RD(sc, BNX_EMAC_MDIO_MODE); | | 953 | val = REG_RD(sc, BNX_EMAC_MDIO_MODE); |
954 | val &= ~BNX_EMAC_MDIO_MODE_AUTO_POLL; | | 954 | val &= ~BNX_EMAC_MDIO_MODE_AUTO_POLL; |
955 | | | 955 | |
956 | REG_WR(sc, BNX_EMAC_MDIO_MODE, val); | | 956 | REG_WR(sc, BNX_EMAC_MDIO_MODE, val); |
957 | REG_RD(sc, BNX_EMAC_MDIO_MODE); | | 957 | REG_RD(sc, BNX_EMAC_MDIO_MODE); |
958 | | | 958 | |
959 | DELAY(40); | | 959 | DELAY(40); |
960 | } | | 960 | } |
961 | | | 961 | |
962 | val = BNX_MIPHY(phy) | BNX_MIREG(reg) | | | 962 | val = BNX_MIPHY(phy) | BNX_MIREG(reg) | |
963 | BNX_EMAC_MDIO_COMM_COMMAND_READ | BNX_EMAC_MDIO_COMM_DISEXT | | | 963 | BNX_EMAC_MDIO_COMM_COMMAND_READ | BNX_EMAC_MDIO_COMM_DISEXT | |
964 | BNX_EMAC_MDIO_COMM_START_BUSY; | | 964 | BNX_EMAC_MDIO_COMM_START_BUSY; |
965 | REG_WR(sc, BNX_EMAC_MDIO_COMM, val); | | 965 | REG_WR(sc, BNX_EMAC_MDIO_COMM, val); |
966 | | | 966 | |
967 | for (i = 0; i < BNX_PHY_TIMEOUT; i++) { | | 967 | for (i = 0; i < BNX_PHY_TIMEOUT; i++) { |
968 | DELAY(10); | | 968 | DELAY(10); |
969 | | | 969 | |
970 | val = REG_RD(sc, BNX_EMAC_MDIO_COMM); | | 970 | val = REG_RD(sc, BNX_EMAC_MDIO_COMM); |
971 | if (!(val & BNX_EMAC_MDIO_COMM_START_BUSY)) { | | 971 | if (!(val & BNX_EMAC_MDIO_COMM_START_BUSY)) { |
972 | DELAY(5); | | 972 | DELAY(5); |
973 | | | 973 | |
974 | val = REG_RD(sc, BNX_EMAC_MDIO_COMM); | | 974 | val = REG_RD(sc, BNX_EMAC_MDIO_COMM); |
975 | val &= BNX_EMAC_MDIO_COMM_DATA; | | 975 | val &= BNX_EMAC_MDIO_COMM_DATA; |
976 | | | 976 | |
977 | break; | | 977 | break; |
978 | } | | 978 | } |
979 | } | | 979 | } |
980 | | | 980 | |
981 | if (val & BNX_EMAC_MDIO_COMM_START_BUSY) { | | 981 | if (val & BNX_EMAC_MDIO_COMM_START_BUSY) { |
982 | BNX_PRINTF(sc, "%s(%d): Error: PHY read timeout! phy = %d, " | | 982 | BNX_PRINTF(sc, "%s(%d): Error: PHY read timeout! phy = %d, " |
983 | "reg = 0x%04X\n", __FILE__, __LINE__, phy, reg); | | 983 | "reg = 0x%04X\n", __FILE__, __LINE__, phy, reg); |
984 | val = 0x0; | | 984 | val = 0x0; |
985 | } else | | 985 | } else |
986 | val = REG_RD(sc, BNX_EMAC_MDIO_COMM); | | 986 | val = REG_RD(sc, BNX_EMAC_MDIO_COMM); |
987 | | | 987 | |
988 | DBPRINT(sc, BNX_EXCESSIVE, | | 988 | DBPRINT(sc, BNX_EXCESSIVE, |
989 | "%s(): phy = %d, reg = 0x%04X, val = 0x%04X\n", __func__, phy, | | 989 | "%s(): phy = %d, reg = 0x%04X, val = 0x%04X\n", __func__, phy, |
990 | (u_int16_t) reg & 0xffff, (u_int16_t) val & 0xffff); | | 990 | (u_int16_t) reg & 0xffff, (u_int16_t) val & 0xffff); |
991 | | | 991 | |
992 | if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { | | 992 | if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { |
993 | val = REG_RD(sc, BNX_EMAC_MDIO_MODE); | | 993 | val = REG_RD(sc, BNX_EMAC_MDIO_MODE); |
994 | val |= BNX_EMAC_MDIO_MODE_AUTO_POLL; | | 994 | val |= BNX_EMAC_MDIO_MODE_AUTO_POLL; |
995 | | | 995 | |
996 | REG_WR(sc, BNX_EMAC_MDIO_MODE, val); | | 996 | REG_WR(sc, BNX_EMAC_MDIO_MODE, val); |
997 | REG_RD(sc, BNX_EMAC_MDIO_MODE); | | 997 | REG_RD(sc, BNX_EMAC_MDIO_MODE); |
998 | | | 998 | |
999 | DELAY(40); | | 999 | DELAY(40); |
1000 | } | | 1000 | } |
1001 | | | 1001 | |
1002 | return (val & 0xffff); | | 1002 | return (val & 0xffff); |
1003 | } | | 1003 | } |
1004 | | | 1004 | |
1005 | /****************************************************************************/ | | 1005 | /****************************************************************************/ |
1006 | /* PHY register write. */ | | 1006 | /* PHY register write. */ |
1007 | /* */ | | 1007 | /* */ |
1008 | /* Implements register writes on the MII bus. */ | | 1008 | /* Implements register writes on the MII bus. */ |
1009 | /* */ | | 1009 | /* */ |
1010 | /* Returns: */ | | 1010 | /* Returns: */ |
1011 | /* The value of the register. */ | | 1011 | /* The value of the register. */ |
1012 | /****************************************************************************/ | | 1012 | /****************************************************************************/ |
1013 | void | | 1013 | void |
1014 | bnx_miibus_write_reg(device_t dev, int phy, int reg, int val) | | 1014 | bnx_miibus_write_reg(device_t dev, int phy, int reg, int val) |
1015 | { | | 1015 | { |
1016 | struct bnx_softc *sc = device_private(dev); | | 1016 | struct bnx_softc *sc = device_private(dev); |
1017 | u_int32_t val1; | | 1017 | u_int32_t val1; |
1018 | int i; | | 1018 | int i; |
1019 | | | 1019 | |
1020 | /* Make sure we are accessing the correct PHY address. */ | | 1020 | /* Make sure we are accessing the correct PHY address. */ |
1021 | if (phy != sc->bnx_phy_addr) { | | 1021 | if (phy != sc->bnx_phy_addr) { |
1022 | DBPRINT(sc, BNX_WARN, "Invalid PHY address %d for PHY write!\n", | | 1022 | DBPRINT(sc, BNX_WARN, "Invalid PHY address %d for PHY write!\n", |
1023 | phy); | | 1023 | phy); |
1024 | return; | | 1024 | return; |
1025 | } | | 1025 | } |
1026 | | | 1026 | |
1027 | DBPRINT(sc, BNX_EXCESSIVE, "%s(): phy = %d, reg = 0x%04X, " | | 1027 | DBPRINT(sc, BNX_EXCESSIVE, "%s(): phy = %d, reg = 0x%04X, " |
1028 | "val = 0x%04X\n", __func__, | | 1028 | "val = 0x%04X\n", __func__, |
1029 | phy, (u_int16_t) reg & 0xffff, (u_int16_t) val & 0xffff); | | 1029 | phy, (u_int16_t) reg & 0xffff, (u_int16_t) val & 0xffff); |
1030 | | | 1030 | |
1031 | /* | | 1031 | /* |
1032 | * The BCM5709S PHY is an IEEE Clause 45 PHY | | 1032 | * The BCM5709S PHY is an IEEE Clause 45 PHY |
1033 | * with special mappings to work with IEEE | | 1033 | * with special mappings to work with IEEE |
1034 | * Clause 22 register accesses. | | 1034 | * Clause 22 register accesses. |
1035 | */ | | 1035 | */ |
1036 | if ((sc->bnx_phy_flags & BNX_PHY_IEEE_CLAUSE_45_FLAG) != 0) { | | 1036 | if ((sc->bnx_phy_flags & BNX_PHY_IEEE_CLAUSE_45_FLAG) != 0) { |
1037 | if (reg >= MII_BMCR && reg <= MII_ANLPRNP) | | 1037 | if (reg >= MII_BMCR && reg <= MII_ANLPRNP) |
1038 | reg += 0x10; | | 1038 | reg += 0x10; |
1039 | } | | 1039 | } |
1040 | | | 1040 | |
1041 | if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { | | 1041 | if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { |
1042 | val1 = REG_RD(sc, BNX_EMAC_MDIO_MODE); | | 1042 | val1 = REG_RD(sc, BNX_EMAC_MDIO_MODE); |
1043 | val1 &= ~BNX_EMAC_MDIO_MODE_AUTO_POLL; | | 1043 | val1 &= ~BNX_EMAC_MDIO_MODE_AUTO_POLL; |
1044 | | | 1044 | |
1045 | REG_WR(sc, BNX_EMAC_MDIO_MODE, val1); | | 1045 | REG_WR(sc, BNX_EMAC_MDIO_MODE, val1); |
1046 | REG_RD(sc, BNX_EMAC_MDIO_MODE); | | 1046 | REG_RD(sc, BNX_EMAC_MDIO_MODE); |
1047 | | | 1047 | |
1048 | DELAY(40); | | 1048 | DELAY(40); |
1049 | } | | 1049 | } |
1050 | | | 1050 | |
1051 | val1 = BNX_MIPHY(phy) | BNX_MIREG(reg) | val | | | 1051 | val1 = BNX_MIPHY(phy) | BNX_MIREG(reg) | val | |
1052 | BNX_EMAC_MDIO_COMM_COMMAND_WRITE | | | 1052 | BNX_EMAC_MDIO_COMM_COMMAND_WRITE | |
1053 | BNX_EMAC_MDIO_COMM_START_BUSY | BNX_EMAC_MDIO_COMM_DISEXT; | | 1053 | BNX_EMAC_MDIO_COMM_START_BUSY | BNX_EMAC_MDIO_COMM_DISEXT; |
1054 | REG_WR(sc, BNX_EMAC_MDIO_COMM, val1); | | 1054 | REG_WR(sc, BNX_EMAC_MDIO_COMM, val1); |
1055 | | | 1055 | |
1056 | for (i = 0; i < BNX_PHY_TIMEOUT; i++) { | | 1056 | for (i = 0; i < BNX_PHY_TIMEOUT; i++) { |
1057 | DELAY(10); | | 1057 | DELAY(10); |
1058 | | | 1058 | |
1059 | val1 = REG_RD(sc, BNX_EMAC_MDIO_COMM); | | 1059 | val1 = REG_RD(sc, BNX_EMAC_MDIO_COMM); |
1060 | if (!(val1 & BNX_EMAC_MDIO_COMM_START_BUSY)) { | | 1060 | if (!(val1 & BNX_EMAC_MDIO_COMM_START_BUSY)) { |
1061 | DELAY(5); | | 1061 | DELAY(5); |
1062 | break; | | 1062 | break; |
1063 | } | | 1063 | } |
1064 | } | | 1064 | } |
1065 | | | 1065 | |
1066 | if (val1 & BNX_EMAC_MDIO_COMM_START_BUSY) { | | 1066 | if (val1 & BNX_EMAC_MDIO_COMM_START_BUSY) { |
1067 | BNX_PRINTF(sc, "%s(%d): PHY write timeout!\n", __FILE__, | | 1067 | BNX_PRINTF(sc, "%s(%d): PHY write timeout!\n", __FILE__, |
1068 | __LINE__); | | 1068 | __LINE__); |
1069 | } | | 1069 | } |
1070 | | | 1070 | |
1071 | if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { | | 1071 | if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { |
1072 | val1 = REG_RD(sc, BNX_EMAC_MDIO_MODE); | | 1072 | val1 = REG_RD(sc, BNX_EMAC_MDIO_MODE); |
1073 | val1 |= BNX_EMAC_MDIO_MODE_AUTO_POLL; | | 1073 | val1 |= BNX_EMAC_MDIO_MODE_AUTO_POLL; |
1074 | | | 1074 | |
1075 | REG_WR(sc, BNX_EMAC_MDIO_MODE, val1); | | 1075 | REG_WR(sc, BNX_EMAC_MDIO_MODE, val1); |
1076 | REG_RD(sc, BNX_EMAC_MDIO_MODE); | | 1076 | REG_RD(sc, BNX_EMAC_MDIO_MODE); |
1077 | | | 1077 | |
1078 | DELAY(40); | | 1078 | DELAY(40); |
1079 | } | | 1079 | } |
1080 | } | | 1080 | } |
1081 | | | 1081 | |
1082 | /****************************************************************************/ | | 1082 | /****************************************************************************/ |
1083 | /* MII bus status change. */ | | 1083 | /* MII bus status change. */ |
1084 | /* */ | | 1084 | /* */ |
1085 | /* Called by the MII bus driver when the PHY establishes link to set the */ | | 1085 | /* Called by the MII bus driver when the PHY establishes link to set the */ |
1086 | /* MAC interface registers. */ | | 1086 | /* MAC interface registers. */ |
1087 | /* */ | | 1087 | /* */ |
1088 | /* Returns: */ | | 1088 | /* Returns: */ |
1089 | /* Nothing. */ | | 1089 | /* Nothing. */ |
1090 | /****************************************************************************/ | | 1090 | /****************************************************************************/ |
1091 | void | | 1091 | void |
1092 | bnx_miibus_statchg(device_t dev) | | 1092 | bnx_miibus_statchg(device_t dev) |
1093 | { | | 1093 | { |
1094 | struct bnx_softc *sc = device_private(dev); | | 1094 | struct bnx_softc *sc = device_private(dev); |
1095 | struct mii_data *mii = &sc->bnx_mii; | | 1095 | struct mii_data *mii = &sc->bnx_mii; |
1096 | int val; | | 1096 | int val; |
1097 | | | 1097 | |
1098 | val = REG_RD(sc, BNX_EMAC_MODE); | | 1098 | val = REG_RD(sc, BNX_EMAC_MODE); |
1099 | val &= ~(BNX_EMAC_MODE_PORT | BNX_EMAC_MODE_HALF_DUPLEX | | | 1099 | val &= ~(BNX_EMAC_MODE_PORT | BNX_EMAC_MODE_HALF_DUPLEX | |
1100 | BNX_EMAC_MODE_MAC_LOOP | BNX_EMAC_MODE_FORCE_LINK | | | 1100 | BNX_EMAC_MODE_MAC_LOOP | BNX_EMAC_MODE_FORCE_LINK | |
1101 | BNX_EMAC_MODE_25G); | | 1101 | BNX_EMAC_MODE_25G); |
1102 | | | 1102 | |
1103 | /* Set MII or GMII interface based on the speed | | 1103 | /* Set MII or GMII interface based on the speed |
1104 | * negotiated by the PHY. | | 1104 | * negotiated by the PHY. |
1105 | */ | | 1105 | */ |
1106 | switch (IFM_SUBTYPE(mii->mii_media_active)) { | | 1106 | switch (IFM_SUBTYPE(mii->mii_media_active)) { |
1107 | case IFM_10_T: | | 1107 | case IFM_10_T: |
1108 | if (BNX_CHIP_NUM(sc) != BNX_CHIP_NUM_5706) { | | 1108 | if (BNX_CHIP_NUM(sc) != BNX_CHIP_NUM_5706) { |
1109 | DBPRINT(sc, BNX_INFO, "Enabling 10Mb interface.\n"); | | 1109 | DBPRINT(sc, BNX_INFO, "Enabling 10Mb interface.\n"); |
1110 | val |= BNX_EMAC_MODE_PORT_MII_10; | | 1110 | val |= BNX_EMAC_MODE_PORT_MII_10; |
1111 | break; | | 1111 | break; |
1112 | } | | 1112 | } |
1113 | /* FALLTHROUGH */ | | 1113 | /* FALLTHROUGH */ |
1114 | case IFM_100_TX: | | 1114 | case IFM_100_TX: |
1115 | DBPRINT(sc, BNX_INFO, "Enabling MII interface.\n"); | | 1115 | DBPRINT(sc, BNX_INFO, "Enabling MII interface.\n"); |
1116 | val |= BNX_EMAC_MODE_PORT_MII; | | 1116 | val |= BNX_EMAC_MODE_PORT_MII; |
1117 | break; | | 1117 | break; |
1118 | case IFM_2500_SX: | | 1118 | case IFM_2500_SX: |
1119 | DBPRINT(sc, BNX_INFO, "Enabling 2.5G MAC mode.\n"); | | 1119 | DBPRINT(sc, BNX_INFO, "Enabling 2.5G MAC mode.\n"); |
1120 | val |= BNX_EMAC_MODE_25G; | | 1120 | val |= BNX_EMAC_MODE_25G; |
1121 | /* FALLTHROUGH */ | | 1121 | /* FALLTHROUGH */ |
1122 | case IFM_1000_T: | | 1122 | case IFM_1000_T: |
1123 | case IFM_1000_SX: | | 1123 | case IFM_1000_SX: |
1124 | DBPRINT(sc, BNX_INFO, "Enabling GMII interface.\n"); | | 1124 | DBPRINT(sc, BNX_INFO, "Enabling GMII interface.\n"); |
1125 | val |= BNX_EMAC_MODE_PORT_GMII; | | 1125 | val |= BNX_EMAC_MODE_PORT_GMII; |
1126 | break; | | 1126 | break; |
1127 | default: | | 1127 | default: |
1128 | val |= BNX_EMAC_MODE_PORT_GMII; | | 1128 | val |= BNX_EMAC_MODE_PORT_GMII; |
1129 | break; | | 1129 | break; |
1130 | } | | 1130 | } |
1131 | | | 1131 | |
1132 | /* Set half or full duplex based on the duplicity | | 1132 | /* Set half or full duplex based on the duplicity |
1133 | * negotiated by the PHY. | | 1133 | * negotiated by the PHY. |
1134 | */ | | 1134 | */ |
1135 | if ((mii->mii_media_active & IFM_GMASK) == IFM_HDX) { | | 1135 | if ((mii->mii_media_active & IFM_GMASK) == IFM_HDX) { |
1136 | DBPRINT(sc, BNX_INFO, "Setting Half-Duplex interface.\n"); | | 1136 | DBPRINT(sc, BNX_INFO, "Setting Half-Duplex interface.\n"); |
1137 | val |= BNX_EMAC_MODE_HALF_DUPLEX; | | 1137 | val |= BNX_EMAC_MODE_HALF_DUPLEX; |
1138 | } else { | | 1138 | } else { |
1139 | DBPRINT(sc, BNX_INFO, "Setting Full-Duplex interface.\n"); | | 1139 | DBPRINT(sc, BNX_INFO, "Setting Full-Duplex interface.\n"); |
1140 | } | | 1140 | } |
1141 | | | 1141 | |
1142 | REG_WR(sc, BNX_EMAC_MODE, val); | | 1142 | REG_WR(sc, BNX_EMAC_MODE, val); |
1143 | } | | 1143 | } |
1144 | | | 1144 | |
1145 | /****************************************************************************/ | | 1145 | /****************************************************************************/ |
1146 | /* Acquire NVRAM lock. */ | | 1146 | /* Acquire NVRAM lock. */ |
1147 | /* */ | | 1147 | /* */ |
1148 | /* Before the NVRAM can be accessed the caller must acquire an NVRAM lock. */ | | 1148 | /* Before the NVRAM can be accessed the caller must acquire an NVRAM lock. */ |
1149 | /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is */ | | 1149 | /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is */ |
1150 | /* for use by the driver. */ | | 1150 | /* for use by the driver. */ |
1151 | /* */ | | 1151 | /* */ |
1152 | /* Returns: */ | | 1152 | /* Returns: */ |
1153 | /* 0 on success, positive value on failure. */ | | 1153 | /* 0 on success, positive value on failure. */ |
1154 | /****************************************************************************/ | | 1154 | /****************************************************************************/ |
1155 | int | | 1155 | int |
1156 | bnx_acquire_nvram_lock(struct bnx_softc *sc) | | 1156 | bnx_acquire_nvram_lock(struct bnx_softc *sc) |
1157 | { | | 1157 | { |
1158 | u_int32_t val; | | 1158 | u_int32_t val; |
1159 | int j; | | 1159 | int j; |
1160 | | | 1160 | |
1161 | DBPRINT(sc, BNX_VERBOSE, "Acquiring NVRAM lock.\n"); | | 1161 | DBPRINT(sc, BNX_VERBOSE, "Acquiring NVRAM lock.\n"); |
1162 | | | 1162 | |
1163 | /* Request access to the flash interface. */ | | 1163 | /* Request access to the flash interface. */ |
1164 | REG_WR(sc, BNX_NVM_SW_ARB, BNX_NVM_SW_ARB_ARB_REQ_SET2); | | 1164 | REG_WR(sc, BNX_NVM_SW_ARB, BNX_NVM_SW_ARB_ARB_REQ_SET2); |
1165 | for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { | | 1165 | for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { |
1166 | val = REG_RD(sc, BNX_NVM_SW_ARB); | | 1166 | val = REG_RD(sc, BNX_NVM_SW_ARB); |
1167 | if (val & BNX_NVM_SW_ARB_ARB_ARB2) | | 1167 | if (val & BNX_NVM_SW_ARB_ARB_ARB2) |
1168 | break; | | 1168 | break; |
1169 | | | 1169 | |
1170 | DELAY(5); | | 1170 | DELAY(5); |
1171 | } | | 1171 | } |
1172 | | | 1172 | |
1173 | if (j >= NVRAM_TIMEOUT_COUNT) { | | 1173 | if (j >= NVRAM_TIMEOUT_COUNT) { |
1174 | DBPRINT(sc, BNX_WARN, "Timeout acquiring NVRAM lock!\n"); | | 1174 | DBPRINT(sc, BNX_WARN, "Timeout acquiring NVRAM lock!\n"); |
1175 | return (EBUSY); | | 1175 | return (EBUSY); |
1176 | } | | 1176 | } |
1177 | | | 1177 | |
1178 | return (0); | | 1178 | return (0); |
1179 | } | | 1179 | } |
1180 | | | 1180 | |
1181 | /****************************************************************************/ | | 1181 | /****************************************************************************/ |
1182 | /* Release NVRAM lock. */ | | 1182 | /* Release NVRAM lock. */ |
1183 | /* */ | | 1183 | /* */ |
1184 | /* When the caller is finished accessing NVRAM the lock must be released. */ | | 1184 | /* When the caller is finished accessing NVRAM the lock must be released. */ |
1185 | /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is */ | | 1185 | /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is */ |
1186 | /* for use by the driver. */ | | 1186 | /* for use by the driver. */ |
1187 | /* */ | | 1187 | /* */ |
1188 | /* Returns: */ | | 1188 | /* Returns: */ |
1189 | /* 0 on success, positive value on failure. */ | | 1189 | /* 0 on success, positive value on failure. */ |
1190 | /****************************************************************************/ | | 1190 | /****************************************************************************/ |
1191 | int | | 1191 | int |
1192 | bnx_release_nvram_lock(struct bnx_softc *sc) | | 1192 | bnx_release_nvram_lock(struct bnx_softc *sc) |
1193 | { | | 1193 | { |
1194 | int j; | | 1194 | int j; |
1195 | u_int32_t val; | | 1195 | u_int32_t val; |
1196 | | | 1196 | |
1197 | DBPRINT(sc, BNX_VERBOSE, "Releasing NVRAM lock.\n"); | | 1197 | DBPRINT(sc, BNX_VERBOSE, "Releasing NVRAM lock.\n"); |
1198 | | | 1198 | |
1199 | /* Relinquish nvram interface. */ | | 1199 | /* Relinquish nvram interface. */ |
1200 | REG_WR(sc, BNX_NVM_SW_ARB, BNX_NVM_SW_ARB_ARB_REQ_CLR2); | | 1200 | REG_WR(sc, BNX_NVM_SW_ARB, BNX_NVM_SW_ARB_ARB_REQ_CLR2); |
1201 | | | 1201 | |
1202 | for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { | | 1202 | for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { |
1203 | val = REG_RD(sc, BNX_NVM_SW_ARB); | | 1203 | val = REG_RD(sc, BNX_NVM_SW_ARB); |
1204 | if (!(val & BNX_NVM_SW_ARB_ARB_ARB2)) | | 1204 | if (!(val & BNX_NVM_SW_ARB_ARB_ARB2)) |
1205 | break; | | 1205 | break; |
1206 | | | 1206 | |
1207 | DELAY(5); | | 1207 | DELAY(5); |
1208 | } | | 1208 | } |
1209 | | | 1209 | |
1210 | if (j >= NVRAM_TIMEOUT_COUNT) { | | 1210 | if (j >= NVRAM_TIMEOUT_COUNT) { |
1211 | DBPRINT(sc, BNX_WARN, "Timeout reeasing NVRAM lock!\n"); | | 1211 | DBPRINT(sc, BNX_WARN, "Timeout reeasing NVRAM lock!\n"); |
1212 | return (EBUSY); | | 1212 | return (EBUSY); |
1213 | } | | 1213 | } |
1214 | | | 1214 | |
1215 | return (0); | | 1215 | return (0); |
1216 | } | | 1216 | } |
1217 | | | 1217 | |
1218 | #ifdef BNX_NVRAM_WRITE_SUPPORT | | 1218 | #ifdef BNX_NVRAM_WRITE_SUPPORT |
1219 | /****************************************************************************/ | | 1219 | /****************************************************************************/ |
1220 | /* Enable NVRAM write access. */ | | 1220 | /* Enable NVRAM write access. */ |
1221 | /* */ | | 1221 | /* */ |
1222 | /* Before writing to NVRAM the caller must enable NVRAM writes. */ | | 1222 | /* Before writing to NVRAM the caller must enable NVRAM writes. */ |
1223 | /* */ | | 1223 | /* */ |
1224 | /* Returns: */ | | 1224 | /* Returns: */ |
1225 | /* 0 on success, positive value on failure. */ | | 1225 | /* 0 on success, positive value on failure. */ |
1226 | /****************************************************************************/ | | 1226 | /****************************************************************************/ |
1227 | int | | 1227 | int |
1228 | bnx_enable_nvram_write(struct bnx_softc *sc) | | 1228 | bnx_enable_nvram_write(struct bnx_softc *sc) |
1229 | { | | 1229 | { |
1230 | u_int32_t val; | | 1230 | u_int32_t val; |
1231 | | | 1231 | |
1232 | DBPRINT(sc, BNX_VERBOSE, "Enabling NVRAM write.\n"); | | 1232 | DBPRINT(sc, BNX_VERBOSE, "Enabling NVRAM write.\n"); |
1233 | | | 1233 | |
1234 | val = REG_RD(sc, BNX_MISC_CFG); | | 1234 | val = REG_RD(sc, BNX_MISC_CFG); |
1235 | REG_WR(sc, BNX_MISC_CFG, val | BNX_MISC_CFG_NVM_WR_EN_PCI); | | 1235 | REG_WR(sc, BNX_MISC_CFG, val | BNX_MISC_CFG_NVM_WR_EN_PCI); |
1236 | | | 1236 | |
1237 | if (!ISSET(sc->bnx_flash_info->flags, BNX_NV_BUFFERED)) { | | 1237 | if (!ISSET(sc->bnx_flash_info->flags, BNX_NV_BUFFERED)) { |
1238 | int j; | | 1238 | int j; |
1239 | | | 1239 | |
1240 | REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE); | | 1240 | REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE); |
1241 | REG_WR(sc, BNX_NVM_COMMAND, | | 1241 | REG_WR(sc, BNX_NVM_COMMAND, |
1242 | BNX_NVM_COMMAND_WREN | BNX_NVM_COMMAND_DOIT); | | 1242 | BNX_NVM_COMMAND_WREN | BNX_NVM_COMMAND_DOIT); |
1243 | | | 1243 | |
1244 | for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { | | 1244 | for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { |
1245 | DELAY(5); | | 1245 | DELAY(5); |
1246 | | | 1246 | |
1247 | val = REG_RD(sc, BNX_NVM_COMMAND); | | 1247 | val = REG_RD(sc, BNX_NVM_COMMAND); |
1248 | if (val & BNX_NVM_COMMAND_DONE) | | 1248 | if (val & BNX_NVM_COMMAND_DONE) |
1249 | break; | | 1249 | break; |
1250 | } | | 1250 | } |
1251 | | | 1251 | |
1252 | if (j >= NVRAM_TIMEOUT_COUNT) { | | 1252 | if (j >= NVRAM_TIMEOUT_COUNT) { |
1253 | DBPRINT(sc, BNX_WARN, "Timeout writing NVRAM!\n"); | | 1253 | DBPRINT(sc, BNX_WARN, "Timeout writing NVRAM!\n"); |
1254 | return (EBUSY); | | 1254 | return (EBUSY); |
1255 | } | | 1255 | } |
1256 | } | | 1256 | } |
1257 | | | 1257 | |
1258 | return (0); | | 1258 | return (0); |
1259 | } | | 1259 | } |
1260 | | | 1260 | |
1261 | /****************************************************************************/ | | 1261 | /****************************************************************************/ |
1262 | /* Disable NVRAM write access. */ | | 1262 | /* Disable NVRAM write access. */ |
1263 | /* */ | | 1263 | /* */ |
1264 | /* When the caller is finished writing to NVRAM write access must be */ | | 1264 | /* When the caller is finished writing to NVRAM write access must be */ |
1265 | /* disabled. */ | | 1265 | /* disabled. */ |
1266 | /* */ | | 1266 | /* */ |
1267 | /* Returns: */ | | 1267 | /* Returns: */ |
1268 | /* Nothing. */ | | 1268 | /* Nothing. */ |
1269 | /****************************************************************************/ | | 1269 | /****************************************************************************/ |
1270 | void | | 1270 | void |
1271 | bnx_disable_nvram_write(struct bnx_softc *sc) | | 1271 | bnx_disable_nvram_write(struct bnx_softc *sc) |
1272 | { | | 1272 | { |
1273 | u_int32_t val; | | 1273 | u_int32_t val; |
1274 | | | 1274 | |
1275 | DBPRINT(sc, BNX_VERBOSE, "Disabling NVRAM write.\n"); | | 1275 | DBPRINT(sc, BNX_VERBOSE, "Disabling NVRAM write.\n"); |
1276 | | | 1276 | |
1277 | val = REG_RD(sc, BNX_MISC_CFG); | | 1277 | val = REG_RD(sc, BNX_MISC_CFG); |
1278 | REG_WR(sc, BNX_MISC_CFG, val & ~BNX_MISC_CFG_NVM_WR_EN); | | 1278 | REG_WR(sc, BNX_MISC_CFG, val & ~BNX_MISC_CFG_NVM_WR_EN); |
1279 | } | | 1279 | } |
1280 | #endif | | 1280 | #endif |
1281 | | | 1281 | |
1282 | /****************************************************************************/ | | 1282 | /****************************************************************************/ |
1283 | /* Enable NVRAM access. */ | | 1283 | /* Enable NVRAM access. */ |
1284 | /* */ | | 1284 | /* */ |
1285 | /* Before accessing NVRAM for read or write operations the caller must */ | | 1285 | /* Before accessing NVRAM for read or write operations the caller must */ |
1286 | /* enabled NVRAM access. */ | | 1286 | /* enabled NVRAM access. */ |
1287 | /* */ | | 1287 | /* */ |
1288 | /* Returns: */ | | 1288 | /* Returns: */ |
1289 | /* Nothing. */ | | 1289 | /* Nothing. */ |
1290 | /****************************************************************************/ | | 1290 | /****************************************************************************/ |
1291 | void | | 1291 | void |
1292 | bnx_enable_nvram_access(struct bnx_softc *sc) | | 1292 | bnx_enable_nvram_access(struct bnx_softc *sc) |
1293 | { | | 1293 | { |
1294 | u_int32_t val; | | 1294 | u_int32_t val; |
1295 | | | 1295 | |
1296 | DBPRINT(sc, BNX_VERBOSE, "Enabling NVRAM access.\n"); | | 1296 | DBPRINT(sc, BNX_VERBOSE, "Enabling NVRAM access.\n"); |
1297 | | | 1297 | |
1298 | val = REG_RD(sc, BNX_NVM_ACCESS_ENABLE); | | 1298 | val = REG_RD(sc, BNX_NVM_ACCESS_ENABLE); |
1299 | /* Enable both bits, even on read. */ | | 1299 | /* Enable both bits, even on read. */ |
1300 | REG_WR(sc, BNX_NVM_ACCESS_ENABLE, | | 1300 | REG_WR(sc, BNX_NVM_ACCESS_ENABLE, |
1301 | val | BNX_NVM_ACCESS_ENABLE_EN | BNX_NVM_ACCESS_ENABLE_WR_EN); | | 1301 | val | BNX_NVM_ACCESS_ENABLE_EN | BNX_NVM_ACCESS_ENABLE_WR_EN); |
1302 | } | | 1302 | } |
1303 | | | 1303 | |
1304 | /****************************************************************************/ | | 1304 | /****************************************************************************/ |
1305 | /* Disable NVRAM access. */ | | 1305 | /* Disable NVRAM access. */ |
1306 | /* */ | | 1306 | /* */ |
1307 | /* When the caller is finished accessing NVRAM access must be disabled. */ | | 1307 | /* When the caller is finished accessing NVRAM access must be disabled. */ |
1308 | /* */ | | 1308 | /* */ |
1309 | /* Returns: */ | | 1309 | /* Returns: */ |
1310 | /* Nothing. */ | | 1310 | /* Nothing. */ |
1311 | /****************************************************************************/ | | 1311 | /****************************************************************************/ |
1312 | void | | 1312 | void |
1313 | bnx_disable_nvram_access(struct bnx_softc *sc) | | 1313 | bnx_disable_nvram_access(struct bnx_softc *sc) |
1314 | { | | 1314 | { |
1315 | u_int32_t val; | | 1315 | u_int32_t val; |
1316 | | | 1316 | |
1317 | DBPRINT(sc, BNX_VERBOSE, "Disabling NVRAM access.\n"); | | 1317 | DBPRINT(sc, BNX_VERBOSE, "Disabling NVRAM access.\n"); |
1318 | | | 1318 | |
1319 | val = REG_RD(sc, BNX_NVM_ACCESS_ENABLE); | | 1319 | val = REG_RD(sc, BNX_NVM_ACCESS_ENABLE); |
1320 | | | 1320 | |
1321 | /* Disable both bits, even after read. */ | | 1321 | /* Disable both bits, even after read. */ |
1322 | REG_WR(sc, BNX_NVM_ACCESS_ENABLE, | | 1322 | REG_WR(sc, BNX_NVM_ACCESS_ENABLE, |
1323 | val & ~(BNX_NVM_ACCESS_ENABLE_EN | BNX_NVM_ACCESS_ENABLE_WR_EN)); | | 1323 | val & ~(BNX_NVM_ACCESS_ENABLE_EN | BNX_NVM_ACCESS_ENABLE_WR_EN)); |
1324 | } | | 1324 | } |
1325 | | | 1325 | |
1326 | #ifdef BNX_NVRAM_WRITE_SUPPORT | | 1326 | #ifdef BNX_NVRAM_WRITE_SUPPORT |
1327 | /****************************************************************************/ | | 1327 | /****************************************************************************/ |
1328 | /* Erase NVRAM page before writing. */ | | 1328 | /* Erase NVRAM page before writing. */ |
1329 | /* */ | | 1329 | /* */ |
1330 | /* Non-buffered flash parts require that a page be erased before it is */ | | 1330 | /* Non-buffered flash parts require that a page be erased before it is */ |
1331 | /* written. */ | | 1331 | /* written. */ |
1332 | /* */ | | 1332 | /* */ |
1333 | /* Returns: */ | | 1333 | /* Returns: */ |
1334 | /* 0 on success, positive value on failure. */ | | 1334 | /* 0 on success, positive value on failure. */ |
1335 | /****************************************************************************/ | | 1335 | /****************************************************************************/ |
1336 | int | | 1336 | int |
1337 | bnx_nvram_erase_page(struct bnx_softc *sc, u_int32_t offset) | | 1337 | bnx_nvram_erase_page(struct bnx_softc *sc, u_int32_t offset) |
1338 | { | | 1338 | { |
1339 | u_int32_t cmd; | | 1339 | u_int32_t cmd; |
1340 | int j; | | 1340 | int j; |
1341 | | | 1341 | |
1342 | /* Buffered flash doesn't require an erase. */ | | 1342 | /* Buffered flash doesn't require an erase. */ |
1343 | if (ISSET(sc->bnx_flash_info->flags, BNX_NV_BUFFERED)) | | 1343 | if (ISSET(sc->bnx_flash_info->flags, BNX_NV_BUFFERED)) |
1344 | return (0); | | 1344 | return (0); |
1345 | | | 1345 | |
1346 | DBPRINT(sc, BNX_VERBOSE, "Erasing NVRAM page.\n"); | | 1346 | DBPRINT(sc, BNX_VERBOSE, "Erasing NVRAM page.\n"); |
1347 | | | 1347 | |
1348 | /* Build an erase command. */ | | 1348 | /* Build an erase command. */ |
1349 | cmd = BNX_NVM_COMMAND_ERASE | BNX_NVM_COMMAND_WR | | | 1349 | cmd = BNX_NVM_COMMAND_ERASE | BNX_NVM_COMMAND_WR | |
1350 | BNX_NVM_COMMAND_DOIT; | | 1350 | BNX_NVM_COMMAND_DOIT; |
1351 | | | 1351 | |
1352 | /* | | 1352 | /* |
1353 | * Clear the DONE bit separately, set the NVRAM adress to erase, | | 1353 | * Clear the DONE bit separately, set the NVRAM adress to erase, |
1354 | * and issue the erase command. | | 1354 | * and issue the erase command. |
1355 | */ | | 1355 | */ |
1356 | REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE); | | 1356 | REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE); |
1357 | REG_WR(sc, BNX_NVM_ADDR, offset & BNX_NVM_ADDR_NVM_ADDR_VALUE); | | 1357 | REG_WR(sc, BNX_NVM_ADDR, offset & BNX_NVM_ADDR_NVM_ADDR_VALUE); |
1358 | REG_WR(sc, BNX_NVM_COMMAND, cmd); | | 1358 | REG_WR(sc, BNX_NVM_COMMAND, cmd); |
1359 | | | 1359 | |
1360 | /* Wait for completion. */ | | 1360 | /* Wait for completion. */ |
1361 | for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { | | 1361 | for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { |
1362 | u_int32_t val; | | 1362 | u_int32_t val; |
1363 | | | 1363 | |
1364 | DELAY(5); | | 1364 | DELAY(5); |
1365 | | | 1365 | |
1366 | val = REG_RD(sc, BNX_NVM_COMMAND); | | 1366 | val = REG_RD(sc, BNX_NVM_COMMAND); |
1367 | if (val & BNX_NVM_COMMAND_DONE) | | 1367 | if (val & BNX_NVM_COMMAND_DONE) |
1368 | break; | | 1368 | break; |
1369 | } | | 1369 | } |
1370 | | | 1370 | |
1371 | if (j >= NVRAM_TIMEOUT_COUNT) { | | 1371 | if (j >= NVRAM_TIMEOUT_COUNT) { |
1372 | DBPRINT(sc, BNX_WARN, "Timeout erasing NVRAM.\n"); | | 1372 | DBPRINT(sc, BNX_WARN, "Timeout erasing NVRAM.\n"); |
1373 | return (EBUSY); | | 1373 | return (EBUSY); |
1374 | } | | 1374 | } |
1375 | | | 1375 | |
1376 | return (0); | | 1376 | return (0); |
1377 | } | | 1377 | } |
1378 | #endif /* BNX_NVRAM_WRITE_SUPPORT */ | | 1378 | #endif /* BNX_NVRAM_WRITE_SUPPORT */ |
1379 | | | 1379 | |
1380 | /****************************************************************************/ | | 1380 | /****************************************************************************/ |
1381 | /* Read a dword (32 bits) from NVRAM. */ | | 1381 | /* Read a dword (32 bits) from NVRAM. */ |
1382 | /* */ | | 1382 | /* */ |
1383 | /* Read a 32 bit word from NVRAM. The caller is assumed to have already */ | | 1383 | /* Read a 32 bit word from NVRAM. The caller is assumed to have already */ |
1384 | /* obtained the NVRAM lock and enabled the controller for NVRAM access. */ | | 1384 | /* obtained the NVRAM lock and enabled the controller for NVRAM access. */ |
1385 | /* */ | | 1385 | /* */ |
1386 | /* Returns: */ | | 1386 | /* Returns: */ |
1387 | /* 0 on success and the 32 bit value read, positive value on failure. */ | | 1387 | /* 0 on success and the 32 bit value read, positive value on failure. */ |
1388 | /****************************************************************************/ | | 1388 | /****************************************************************************/ |
1389 | int | | 1389 | int |
1390 | bnx_nvram_read_dword(struct bnx_softc *sc, u_int32_t offset, | | 1390 | bnx_nvram_read_dword(struct bnx_softc *sc, u_int32_t offset, |
1391 | u_int8_t *ret_val, u_int32_t cmd_flags) | | 1391 | u_int8_t *ret_val, u_int32_t cmd_flags) |
1392 | { | | 1392 | { |
1393 | u_int32_t cmd; | | 1393 | u_int32_t cmd; |
1394 | int i, rc = 0; | | 1394 | int i, rc = 0; |
1395 | | | 1395 | |
1396 | /* Build the command word. */ | | 1396 | /* Build the command word. */ |
1397 | cmd = BNX_NVM_COMMAND_DOIT | cmd_flags; | | 1397 | cmd = BNX_NVM_COMMAND_DOIT | cmd_flags; |
1398 | | | 1398 | |
1399 | /* Calculate the offset for buffered flash if translation is used. */ | | 1399 | /* Calculate the offset for buffered flash if translation is used. */ |
1400 | if (ISSET(sc->bnx_flash_info->flags, BNX_NV_TRANSLATE)) { | | 1400 | if (ISSET(sc->bnx_flash_info->flags, BNX_NV_TRANSLATE)) { |
1401 | offset = ((offset / sc->bnx_flash_info->page_size) << | | 1401 | offset = ((offset / sc->bnx_flash_info->page_size) << |
1402 | sc->bnx_flash_info->page_bits) + | | 1402 | sc->bnx_flash_info->page_bits) + |
1403 | (offset % sc->bnx_flash_info->page_size); | | 1403 | (offset % sc->bnx_flash_info->page_size); |
1404 | } | | 1404 | } |
1405 | | | 1405 | |
1406 | /* | | 1406 | /* |
1407 | * Clear the DONE bit separately, set the address to read, | | 1407 | * Clear the DONE bit separately, set the address to read, |
1408 | * and issue the read. | | 1408 | * and issue the read. |
1409 | */ | | 1409 | */ |
1410 | REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE); | | 1410 | REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE); |
1411 | REG_WR(sc, BNX_NVM_ADDR, offset & BNX_NVM_ADDR_NVM_ADDR_VALUE); | | 1411 | REG_WR(sc, BNX_NVM_ADDR, offset & BNX_NVM_ADDR_NVM_ADDR_VALUE); |
1412 | REG_WR(sc, BNX_NVM_COMMAND, cmd); | | 1412 | REG_WR(sc, BNX_NVM_COMMAND, cmd); |
1413 | | | 1413 | |
1414 | /* Wait for completion. */ | | 1414 | /* Wait for completion. */ |
1415 | for (i = 0; i < NVRAM_TIMEOUT_COUNT; i++) { | | 1415 | for (i = 0; i < NVRAM_TIMEOUT_COUNT; i++) { |
1416 | u_int32_t val; | | 1416 | u_int32_t val; |
1417 | | | 1417 | |
1418 | DELAY(5); | | 1418 | DELAY(5); |
1419 | | | 1419 | |
1420 | val = REG_RD(sc, BNX_NVM_COMMAND); | | 1420 | val = REG_RD(sc, BNX_NVM_COMMAND); |
1421 | if (val & BNX_NVM_COMMAND_DONE) { | | 1421 | if (val & BNX_NVM_COMMAND_DONE) { |
1422 | val = REG_RD(sc, BNX_NVM_READ); | | 1422 | val = REG_RD(sc, BNX_NVM_READ); |
1423 | | | 1423 | |
1424 | val = bnx_be32toh(val); | | 1424 | val = bnx_be32toh(val); |
1425 | memcpy(ret_val, &val, 4); | | 1425 | memcpy(ret_val, &val, 4); |
1426 | break; | | 1426 | break; |
1427 | } | | 1427 | } |
1428 | } | | 1428 | } |
1429 | | | 1429 | |
1430 | /* Check for errors. */ | | 1430 | /* Check for errors. */ |
1431 | if (i >= NVRAM_TIMEOUT_COUNT) { | | 1431 | if (i >= NVRAM_TIMEOUT_COUNT) { |
1432 | BNX_PRINTF(sc, "%s(%d): Timeout error reading NVRAM at " | | 1432 | BNX_PRINTF(sc, "%s(%d): Timeout error reading NVRAM at " |
1433 | "offset 0x%08X!\n", __FILE__, __LINE__, offset); | | 1433 | "offset 0x%08X!\n", __FILE__, __LINE__, offset); |
1434 | rc = EBUSY; | | 1434 | rc = EBUSY; |
1435 | } | | 1435 | } |
1436 | | | 1436 | |
1437 | return(rc); | | 1437 | return(rc); |
1438 | } | | 1438 | } |
1439 | | | 1439 | |
1440 | #ifdef BNX_NVRAM_WRITE_SUPPORT | | 1440 | #ifdef BNX_NVRAM_WRITE_SUPPORT |
1441 | /****************************************************************************/ | | 1441 | /****************************************************************************/ |
1442 | /* Write a dword (32 bits) to NVRAM. */ | | 1442 | /* Write a dword (32 bits) to NVRAM. */ |
1443 | /* */ | | 1443 | /* */ |
1444 | /* Write a 32 bit word to NVRAM. The caller is assumed to have already */ | | 1444 | /* Write a 32 bit word to NVRAM. The caller is assumed to have already */ |
1445 | /* obtained the NVRAM lock, enabled the controller for NVRAM access, and */ | | 1445 | /* obtained the NVRAM lock, enabled the controller for NVRAM access, and */ |
1446 | /* enabled NVRAM write access. */ | | 1446 | /* enabled NVRAM write access. */ |
1447 | /* */ | | 1447 | /* */ |
1448 | /* Returns: */ | | 1448 | /* Returns: */ |
1449 | /* 0 on success, positive value on failure. */ | | 1449 | /* 0 on success, positive value on failure. */ |
1450 | /****************************************************************************/ | | 1450 | /****************************************************************************/ |
1451 | int | | 1451 | int |
1452 | bnx_nvram_write_dword(struct bnx_softc *sc, u_int32_t offset, u_int8_t *val, | | 1452 | bnx_nvram_write_dword(struct bnx_softc *sc, u_int32_t offset, u_int8_t *val, |
1453 | u_int32_t cmd_flags) | | 1453 | u_int32_t cmd_flags) |
1454 | { | | 1454 | { |
1455 | u_int32_t cmd, val32; | | 1455 | u_int32_t cmd, val32; |
1456 | int j; | | 1456 | int j; |
1457 | | | 1457 | |
1458 | /* Build the command word. */ | | 1458 | /* Build the command word. */ |
1459 | cmd = BNX_NVM_COMMAND_DOIT | BNX_NVM_COMMAND_WR | cmd_flags; | | 1459 | cmd = BNX_NVM_COMMAND_DOIT | BNX_NVM_COMMAND_WR | cmd_flags; |
1460 | | | 1460 | |
1461 | /* Calculate the offset for buffered flash if translation is used. */ | | 1461 | /* Calculate the offset for buffered flash if translation is used. */ |
1462 | if (ISSET(sc->bnx_flash_info->flags, BNX_NV_TRANSLATE)) { | | 1462 | if (ISSET(sc->bnx_flash_info->flags, BNX_NV_TRANSLATE)) { |
1463 | offset = ((offset / sc->bnx_flash_info->page_size) << | | 1463 | offset = ((offset / sc->bnx_flash_info->page_size) << |
1464 | sc->bnx_flash_info->page_bits) + | | 1464 | sc->bnx_flash_info->page_bits) + |
1465 | (offset % sc->bnx_flash_info->page_size); | | 1465 | (offset % sc->bnx_flash_info->page_size); |
1466 | } | | 1466 | } |
1467 | | | 1467 | |
1468 | /* | | 1468 | /* |
1469 | * Clear the DONE bit separately, convert NVRAM data to big-endian, | | 1469 | * Clear the DONE bit separately, convert NVRAM data to big-endian, |
1470 | * set the NVRAM address to write, and issue the write command | | 1470 | * set the NVRAM address to write, and issue the write command |
1471 | */ | | 1471 | */ |
1472 | REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE); | | 1472 | REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE); |
1473 | memcpy(&val32, val, 4); | | 1473 | memcpy(&val32, val, 4); |
1474 | val32 = htobe32(val32); | | 1474 | val32 = htobe32(val32); |
1475 | REG_WR(sc, BNX_NVM_WRITE, val32); | | 1475 | REG_WR(sc, BNX_NVM_WRITE, val32); |
1476 | REG_WR(sc, BNX_NVM_ADDR, offset & BNX_NVM_ADDR_NVM_ADDR_VALUE); | | 1476 | REG_WR(sc, BNX_NVM_ADDR, offset & BNX_NVM_ADDR_NVM_ADDR_VALUE); |
1477 | REG_WR(sc, BNX_NVM_COMMAND, cmd); | | 1477 | REG_WR(sc, BNX_NVM_COMMAND, cmd); |
1478 | | | 1478 | |
1479 | /* Wait for completion. */ | | 1479 | /* Wait for completion. */ |
1480 | for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { | | 1480 | for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) { |
1481 | DELAY(5); | | 1481 | DELAY(5); |
1482 | | | 1482 | |
1483 | if (REG_RD(sc, BNX_NVM_COMMAND) & BNX_NVM_COMMAND_DONE) | | 1483 | if (REG_RD(sc, BNX_NVM_COMMAND) & BNX_NVM_COMMAND_DONE) |
1484 | break; | | 1484 | break; |
1485 | } | | 1485 | } |
1486 | if (j >= NVRAM_TIMEOUT_COUNT) { | | 1486 | if (j >= NVRAM_TIMEOUT_COUNT) { |
1487 | BNX_PRINTF(sc, "%s(%d): Timeout error writing NVRAM at " | | 1487 | BNX_PRINTF(sc, "%s(%d): Timeout error writing NVRAM at " |
1488 | "offset 0x%08X\n", __FILE__, __LINE__, offset); | | 1488 | "offset 0x%08X\n", __FILE__, __LINE__, offset); |
1489 | return (EBUSY); | | 1489 | return (EBUSY); |
1490 | } | | 1490 | } |
1491 | | | 1491 | |
1492 | return (0); | | 1492 | return (0); |
1493 | } | | 1493 | } |
1494 | #endif /* BNX_NVRAM_WRITE_SUPPORT */ | | 1494 | #endif /* BNX_NVRAM_WRITE_SUPPORT */ |
1495 | | | 1495 | |
1496 | /****************************************************************************/ | | 1496 | /****************************************************************************/ |
1497 | /* Initialize NVRAM access. */ | | 1497 | /* Initialize NVRAM access. */ |
1498 | /* */ | | 1498 | /* */ |
1499 | /* Identify the NVRAM device in use and prepare the NVRAM interface to */ | | 1499 | /* Identify the NVRAM device in use and prepare the NVRAM interface to */ |
1500 | /* access that device. */ | | 1500 | /* access that device. */ |
1501 | /* */ | | 1501 | /* */ |
1502 | /* Returns: */ | | 1502 | /* Returns: */ |
1503 | /* 0 on success, positive value on failure. */ | | 1503 | /* 0 on success, positive value on failure. */ |
1504 | /****************************************************************************/ | | 1504 | /****************************************************************************/ |
1505 | int | | 1505 | int |
1506 | bnx_init_nvram(struct bnx_softc *sc) | | 1506 | bnx_init_nvram(struct bnx_softc *sc) |
1507 | { | | 1507 | { |
1508 | u_int32_t val; | | 1508 | u_int32_t val; |
1509 | int j, entry_count, rc = 0; | | 1509 | int j, entry_count, rc = 0; |
1510 | struct flash_spec *flash; | | 1510 | struct flash_spec *flash; |
1511 | | | 1511 | |
1512 | DBPRINT(sc,BNX_VERBOSE_RESET, "Entering %s()\n", __func__); | | 1512 | DBPRINT(sc,BNX_VERBOSE_RESET, "Entering %s()\n", __func__); |
1513 | | | 1513 | |
1514 | if (BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5709) { | | 1514 | if (BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5709) { |
1515 | sc->bnx_flash_info = &flash_5709; | | 1515 | sc->bnx_flash_info = &flash_5709; |
1516 | goto bnx_init_nvram_get_flash_size; | | 1516 | goto bnx_init_nvram_get_flash_size; |
1517 | } | | 1517 | } |
1518 | | | 1518 | |
1519 | /* Determine the selected interface. */ | | 1519 | /* Determine the selected interface. */ |
1520 | val = REG_RD(sc, BNX_NVM_CFG1); | | 1520 | val = REG_RD(sc, BNX_NVM_CFG1); |
1521 | | | 1521 | |
1522 | entry_count = sizeof(flash_table) / sizeof(struct flash_spec); | | 1522 | entry_count = sizeof(flash_table) / sizeof(struct flash_spec); |
1523 | | | 1523 | |
1524 | /* | | 1524 | /* |
1525 | * Flash reconfiguration is required to support additional | | 1525 | * Flash reconfiguration is required to support additional |
1526 | * NVRAM devices not directly supported in hardware. | | 1526 | * NVRAM devices not directly supported in hardware. |
1527 | * Check if the flash interface was reconfigured | | 1527 | * Check if the flash interface was reconfigured |
1528 | * by the bootcode. | | 1528 | * by the bootcode. |
1529 | */ | | 1529 | */ |
1530 | | | 1530 | |
1531 | if (val & 0x40000000) { | | 1531 | if (val & 0x40000000) { |
1532 | /* Flash interface reconfigured by bootcode. */ | | 1532 | /* Flash interface reconfigured by bootcode. */ |
1533 | | | 1533 | |
1534 | DBPRINT(sc,BNX_INFO_LOAD, | | 1534 | DBPRINT(sc,BNX_INFO_LOAD, |
1535 | "bnx_init_nvram(): Flash WAS reconfigured.\n"); | | 1535 | "bnx_init_nvram(): Flash WAS reconfigured.\n"); |
1536 | | | 1536 | |
1537 | for (j = 0, flash = &flash_table[0]; j < entry_count; | | 1537 | for (j = 0, flash = &flash_table[0]; j < entry_count; |
1538 | j++, flash++) { | | 1538 | j++, flash++) { |
1539 | if ((val & FLASH_BACKUP_STRAP_MASK) == | | 1539 | if ((val & FLASH_BACKUP_STRAP_MASK) == |
1540 | (flash->config1 & FLASH_BACKUP_STRAP_MASK)) { | | 1540 | (flash->config1 & FLASH_BACKUP_STRAP_MASK)) { |
1541 | sc->bnx_flash_info = flash; | | 1541 | sc->bnx_flash_info = flash; |
1542 | break; | | 1542 | break; |
1543 | } | | 1543 | } |
1544 | } | | 1544 | } |
1545 | } else { | | 1545 | } else { |
1546 | /* Flash interface not yet reconfigured. */ | | 1546 | /* Flash interface not yet reconfigured. */ |
1547 | u_int32_t mask; | | 1547 | u_int32_t mask; |
1548 | | | 1548 | |
1549 | DBPRINT(sc,BNX_INFO_LOAD, | | 1549 | DBPRINT(sc,BNX_INFO_LOAD, |
1550 | "bnx_init_nvram(): Flash was NOT reconfigured.\n"); | | 1550 | "bnx_init_nvram(): Flash was NOT reconfigured.\n"); |
1551 | | | 1551 | |
1552 | if (val & (1 << 23)) | | 1552 | if (val & (1 << 23)) |
1553 | mask = FLASH_BACKUP_STRAP_MASK; | | 1553 | mask = FLASH_BACKUP_STRAP_MASK; |
1554 | else | | 1554 | else |
1555 | mask = FLASH_STRAP_MASK; | | 1555 | mask = FLASH_STRAP_MASK; |
1556 | | | 1556 | |
1557 | /* Look for the matching NVRAM device configuration data. */ | | 1557 | /* Look for the matching NVRAM device configuration data. */ |
1558 | for (j = 0, flash = &flash_table[0]; j < entry_count; | | 1558 | for (j = 0, flash = &flash_table[0]; j < entry_count; |
1559 | j++, flash++) { | | 1559 | j++, flash++) { |
1560 | /* Check if the dev matches any of the known devices. */ | | 1560 | /* Check if the dev matches any of the known devices. */ |
1561 | if ((val & mask) == (flash->strapping & mask)) { | | 1561 | if ((val & mask) == (flash->strapping & mask)) { |
1562 | /* Found a device match. */ | | 1562 | /* Found a device match. */ |
1563 | sc->bnx_flash_info = flash; | | 1563 | sc->bnx_flash_info = flash; |
1564 | | | 1564 | |
1565 | /* Request access to the flash interface. */ | | 1565 | /* Request access to the flash interface. */ |
1566 | if ((rc = bnx_acquire_nvram_lock(sc)) != 0) | | 1566 | if ((rc = bnx_acquire_nvram_lock(sc)) != 0) |
1567 | return (rc); | | 1567 | return (rc); |
1568 | | | 1568 | |
1569 | /* Reconfigure the flash interface. */ | | 1569 | /* Reconfigure the flash interface. */ |
1570 | bnx_enable_nvram_access(sc); | | 1570 | bnx_enable_nvram_access(sc); |
1571 | REG_WR(sc, BNX_NVM_CFG1, flash->config1); | | 1571 | REG_WR(sc, BNX_NVM_CFG1, flash->config1); |
1572 | REG_WR(sc, BNX_NVM_CFG2, flash->config2); | | 1572 | REG_WR(sc, BNX_NVM_CFG2, flash->config2); |
1573 | REG_WR(sc, BNX_NVM_CFG3, flash->config3); | | 1573 | REG_WR(sc, BNX_NVM_CFG3, flash->config3); |
1574 | REG_WR(sc, BNX_NVM_WRITE1, flash->write1); | | 1574 | REG_WR(sc, BNX_NVM_WRITE1, flash->write1); |
1575 | bnx_disable_nvram_access(sc); | | 1575 | bnx_disable_nvram_access(sc); |
1576 | bnx_release_nvram_lock(sc); | | 1576 | bnx_release_nvram_lock(sc); |
1577 | | | 1577 | |
1578 | break; | | 1578 | break; |
1579 | } | | 1579 | } |
1580 | } | | 1580 | } |
1581 | } | | 1581 | } |
1582 | | | 1582 | |
1583 | /* Check if a matching device was found. */ | | 1583 | /* Check if a matching device was found. */ |
1584 | if (j == entry_count) { | | 1584 | if (j == entry_count) { |
1585 | sc->bnx_flash_info = NULL; | | 1585 | sc->bnx_flash_info = NULL; |
1586 | BNX_PRINTF(sc, "%s(%d): Unknown Flash NVRAM found!\n", | | 1586 | BNX_PRINTF(sc, "%s(%d): Unknown Flash NVRAM found!\n", |
1587 | __FILE__, __LINE__); | | 1587 | __FILE__, __LINE__); |
1588 | rc = ENODEV; | | 1588 | rc = ENODEV; |
1589 | } | | 1589 | } |
1590 | | | 1590 | |
1591 | bnx_init_nvram_get_flash_size: | | 1591 | bnx_init_nvram_get_flash_size: |
1592 | /* Write the flash config data to the shared memory interface. */ | | 1592 | /* Write the flash config data to the shared memory interface. */ |
1593 | val = REG_RD_IND(sc, sc->bnx_shmem_base + BNX_SHARED_HW_CFG_CONFIG2); | | 1593 | val = REG_RD_IND(sc, sc->bnx_shmem_base + BNX_SHARED_HW_CFG_CONFIG2); |
1594 | val &= BNX_SHARED_HW_CFG2_NVM_SIZE_MASK; | | 1594 | val &= BNX_SHARED_HW_CFG2_NVM_SIZE_MASK; |
1595 | if (val) | | 1595 | if (val) |
1596 | sc->bnx_flash_size = val; | | 1596 | sc->bnx_flash_size = val; |
1597 | else | | 1597 | else |
1598 | sc->bnx_flash_size = sc->bnx_flash_info->total_size; | | 1598 | sc->bnx_flash_size = sc->bnx_flash_info->total_size; |
1599 | | | 1599 | |
1600 | DBPRINT(sc, BNX_INFO_LOAD, "bnx_init_nvram() flash->total_size = " | | 1600 | DBPRINT(sc, BNX_INFO_LOAD, "bnx_init_nvram() flash->total_size = " |
1601 | "0x%08X\n", sc->bnx_flash_info->total_size); | | 1601 | "0x%08X\n", sc->bnx_flash_info->total_size); |
1602 | | | 1602 | |
1603 | DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __func__); | | 1603 | DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __func__); |
1604 | | | 1604 | |
1605 | return (rc); | | 1605 | return (rc); |
1606 | } | | 1606 | } |
1607 | | | 1607 | |
1608 | /****************************************************************************/ | | 1608 | /****************************************************************************/ |
1609 | /* Read an arbitrary range of data from NVRAM. */ | | 1609 | /* Read an arbitrary range of data from NVRAM. */ |
1610 | /* */ | | 1610 | /* */ |
1611 | /* Prepares the NVRAM interface for access and reads the requested data */ | | 1611 | /* Prepares the NVRAM interface for access and reads the requested data */ |
1612 | /* into the supplied buffer. */ | | 1612 | /* into the supplied buffer. */ |
1613 | /* */ | | 1613 | /* */ |
1614 | /* Returns: */ | | 1614 | /* Returns: */ |
1615 | /* 0 on success and the data read, positive value on failure. */ | | 1615 | /* 0 on success and the data read, positive value on failure. */ |
1616 | /****************************************************************************/ | | 1616 | /****************************************************************************/ |
1617 | int | | 1617 | int |
1618 | bnx_nvram_read(struct bnx_softc *sc, u_int32_t offset, u_int8_t *ret_buf, | | 1618 | bnx_nvram_read(struct bnx_softc *sc, u_int32_t offset, u_int8_t *ret_buf, |
1619 | int buf_size) | | 1619 | int buf_size) |
1620 | { | | 1620 | { |
1621 | int rc = 0; | | 1621 | int rc = 0; |
1622 | u_int32_t cmd_flags, offset32, len32, extra; | | 1622 | u_int32_t cmd_flags, offset32, len32, extra; |
1623 | | | 1623 | |
1624 | if (buf_size == 0) | | 1624 | if (buf_size == 0) |
1625 | return (0); | | 1625 | return (0); |
1626 | | | 1626 | |
1627 | /* Request access to the flash interface. */ | | 1627 | /* Request access to the flash interface. */ |
1628 | if ((rc = bnx_acquire_nvram_lock(sc)) != 0) | | 1628 | if ((rc = bnx_acquire_nvram_lock(sc)) != 0) |
1629 | return (rc); | | 1629 | return (rc); |
1630 | | | 1630 | |
1631 | /* Enable access to flash interface */ | | 1631 | /* Enable access to flash interface */ |
1632 | bnx_enable_nvram_access(sc); | | 1632 | bnx_enable_nvram_access(sc); |
1633 | | | 1633 | |
1634 | len32 = buf_size; | | 1634 | len32 = buf_size; |
1635 | offset32 = offset; | | 1635 | offset32 = offset; |
1636 | extra = 0; | | 1636 | extra = 0; |
1637 | | | 1637 | |
1638 | cmd_flags = 0; | | 1638 | cmd_flags = 0; |
1639 | | | 1639 | |
1640 | if (offset32 & 3) { | | 1640 | if (offset32 & 3) { |
1641 | u_int8_t buf[4]; | | 1641 | u_int8_t buf[4]; |
1642 | u_int32_t pre_len; | | 1642 | u_int32_t pre_len; |
1643 | | | 1643 | |
1644 | offset32 &= ~3; | | 1644 | offset32 &= ~3; |
1645 | pre_len = 4 - (offset & 3); | | 1645 | pre_len = 4 - (offset & 3); |
1646 | | | 1646 | |
1647 | if (pre_len >= len32) { | | 1647 | if (pre_len >= len32) { |
1648 | pre_len = len32; | | 1648 | pre_len = len32; |
1649 | cmd_flags = | | 1649 | cmd_flags = |
1650 | BNX_NVM_COMMAND_FIRST | BNX_NVM_COMMAND_LAST; | | 1650 | BNX_NVM_COMMAND_FIRST | BNX_NVM_COMMAND_LAST; |
1651 | } else | | 1651 | } else |
1652 | cmd_flags = BNX_NVM_COMMAND_FIRST; | | 1652 | cmd_flags = BNX_NVM_COMMAND_FIRST; |
1653 | | | 1653 | |
1654 | rc = bnx_nvram_read_dword(sc, offset32, buf, cmd_flags); | | 1654 | rc = bnx_nvram_read_dword(sc, offset32, buf, cmd_flags); |
1655 | | | 1655 | |
1656 | if (rc) | | 1656 | if (rc) |
1657 | return (rc); | | 1657 | return (rc); |
1658 | | | 1658 | |
1659 | memcpy(ret_buf, buf + (offset & 3), pre_len); | | 1659 | memcpy(ret_buf, buf + (offset & 3), pre_len); |
1660 | | | 1660 | |
1661 | offset32 += 4; | | 1661 | offset32 += 4; |
1662 | ret_buf += pre_len; | | 1662 | ret_buf += pre_len; |
1663 | len32 -= pre_len; | | 1663 | len32 -= pre_len; |
1664 | } | | 1664 | } |
1665 | | | 1665 | |
1666 | if (len32 & 3) { | | 1666 | if (len32 & 3) { |
1667 | extra = 4 - (len32 & 3); | | 1667 | extra = 4 - (len32 & 3); |
1668 | len32 = (len32 + 4) & ~3; | | 1668 | len32 = (len32 + 4) & ~3; |
1669 | } | | 1669 | } |
1670 | | | 1670 | |
1671 | if (len32 == 4) { | | 1671 | if (len32 == 4) { |
1672 | u_int8_t buf[4]; | | 1672 | u_int8_t buf[4]; |
1673 | | | 1673 | |
1674 | if (cmd_flags) | | 1674 | if (cmd_flags) |
1675 | cmd_flags = BNX_NVM_COMMAND_LAST; | | 1675 | cmd_flags = BNX_NVM_COMMAND_LAST; |
1676 | else | | 1676 | else |
1677 | cmd_flags = | | 1677 | cmd_flags = |
1678 | BNX_NVM_COMMAND_FIRST | BNX_NVM_COMMAND_LAST; | | 1678 | BNX_NVM_COMMAND_FIRST | BNX_NVM_COMMAND_LAST; |
1679 | | | 1679 | |
1680 | rc = bnx_nvram_read_dword(sc, offset32, buf, cmd_flags); | | 1680 | rc = bnx_nvram_read_dword(sc, offset32, buf, cmd_flags); |
1681 | | | 1681 | |
1682 | memcpy(ret_buf, buf, 4 - extra); | | 1682 | memcpy(ret_buf, buf, 4 - extra); |
1683 | } else if (len32 > 0) { | | 1683 | } else if (len32 > 0) { |
1684 | u_int8_t buf[4]; | | 1684 | u_int8_t buf[4]; |
1685 | | | 1685 | |
1686 | /* Read the first word. */ | | 1686 | /* Read the first word. */ |
1687 | if (cmd_flags) | | 1687 | if (cmd_flags) |
1688 | cmd_flags = 0; | | 1688 | cmd_flags = 0; |
1689 | else | | 1689 | else |
1690 | cmd_flags = BNX_NVM_COMMAND_FIRST; | | 1690 | cmd_flags = BNX_NVM_COMMAND_FIRST; |
1691 | | | 1691 | |
1692 | rc = bnx_nvram_read_dword(sc, offset32, ret_buf, cmd_flags); | | 1692 | rc = bnx_nvram_read_dword(sc, offset32, ret_buf, cmd_flags); |
1693 | | | 1693 | |
1694 | /* Advance to the next dword. */ | | 1694 | /* Advance to the next dword. */ |
1695 | offset32 += 4; | | 1695 | offset32 += 4; |
1696 | ret_buf += 4; | | 1696 | ret_buf += 4; |
1697 | len32 -= 4; | | 1697 | len32 -= 4; |
1698 | | | 1698 | |
1699 | while (len32 > 4 && rc == 0) { | | 1699 | while (len32 > 4 && rc == 0) { |
1700 | rc = bnx_nvram_read_dword(sc, offset32, ret_buf, 0); | | 1700 | rc = bnx_nvram_read_dword(sc, offset32, ret_buf, 0); |
1701 | | | 1701 | |
1702 | /* Advance to the next dword. */ | | 1702 | /* Advance to the next dword. */ |
1703 | offset32 += 4; | | 1703 | offset32 += 4; |
1704 | ret_buf += 4; | | 1704 | ret_buf += 4; |
1705 | len32 -= 4; | | 1705 | len32 -= 4; |
1706 | } | | 1706 | } |
1707 | | | 1707 | |
1708 | if (rc) | | 1708 | if (rc) |
1709 | return (rc); | | 1709 | return (rc); |