1 /* 2 * Copyright 2009 Solarflare Communications Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include "efsys.h" 27 #include "efx.h" 28 #include "efx_types.h" 29 #include "efx_regs.h" 30 #include "efx_impl.h" 31 32 #if EFSYS_OPT_NVRAM 33 34 #if EFSYS_OPT_FALCON 35 36 static efx_nvram_ops_t __cs __efx_nvram_falcon_ops = { 37 #if EFSYS_OPT_DIAG 38 falcon_nvram_test, /* envo_test */ 39 #endif /* EFSYS_OPT_DIAG */ 40 falcon_nvram_size, /* envo_size */ 41 falcon_nvram_get_version, /* envo_get_version */ 42 falcon_nvram_rw_start, /* envo_rw_start */ 43 falcon_nvram_read_chunk, /* envo_read_chunk */ 44 falcon_nvram_erase, /* envo_erase */ 45 falcon_nvram_write_chunk, /* envo_write_chunk */ 46 falcon_nvram_rw_finish, /* envo_rw_finish */ 47 falcon_nvram_set_version, /* envo_set_version */ 48 }; 49 50 #endif /* EFSYS_OPT_FALCON */ 51 52 #if EFSYS_OPT_SIENA 53 54 static efx_nvram_ops_t __cs __efx_nvram_siena_ops = { 55 #if EFSYS_OPT_DIAG 56 siena_nvram_test, /* envo_test */ 57 #endif /* EFSYS_OPT_DIAG */ 58 siena_nvram_size, /* envo_size */ 59 siena_nvram_get_version, /* envo_get_version */ 60 siena_nvram_rw_start, /* envo_rw_start */ 61 siena_nvram_read_chunk, /* envo_read_chunk */ 62 siena_nvram_erase, /* envo_erase */ 63 siena_nvram_write_chunk, /* envo_write_chunk */ 64 siena_nvram_rw_finish, /* envo_rw_finish */ 65 siena_nvram_set_version, /* envo_set_version */ 66 }; 67 68 #endif /* EFSYS_OPT_SIENA */ 69 70 __checkReturn int 71 efx_nvram_init( 72 __in efx_nic_t *enp) 73 { 74 efx_nvram_ops_t *envop; 75 int rc; 76 77 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 78 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 79 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM)); 80 81 switch (enp->en_family) { 82 #if EFSYS_OPT_FALCON 83 case EFX_FAMILY_FALCON: 84 envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops; 85 break; 86 #endif /* EFSYS_OPT_FALCON */ 87 88 #if EFSYS_OPT_SIENA 89 case EFX_FAMILY_SIENA: 90 envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops; 91 break; 92 #endif /* EFSYS_OPT_SIENA */ 93 94 default: 95 EFSYS_ASSERT(0); 96 rc = ENOTSUP; 97 goto fail1; 98 } 99 100 enp->en_envop = envop; 101 enp->en_mod_flags |= EFX_MOD_NVRAM; 102 103 return (0); 104 105 fail1: 106 EFSYS_PROBE1(fail1, int, rc); 107 108 return (rc); 109 } 110 111 #if EFSYS_OPT_DIAG 112 113 __checkReturn int 114 efx_nvram_test( 115 __in efx_nic_t *enp) 116 { 117 efx_nvram_ops_t *envop = enp->en_envop; 118 int rc; 119 120 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 121 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 122 123 if ((rc = envop->envo_test(enp)) != 0) 124 goto fail1; 125 126 return (0); 127 128 fail1: 129 EFSYS_PROBE1(fail1, int, rc); 130 131 return (rc); 132 } 133 134 #endif /* EFSYS_OPT_DIAG */ 135 136 __checkReturn int 137 efx_nvram_size( 138 __in efx_nic_t *enp, 139 __in efx_nvram_type_t type, 140 __out size_t *sizep) 141 { 142 efx_nvram_ops_t *envop = enp->en_envop; 143 int rc; 144 145 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 146 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 147 148 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 149 150 if ((rc = envop->envo_size(enp, type, sizep)) != 0) 151 goto fail1; 152 153 return (0); 154 155 fail1: 156 EFSYS_PROBE1(fail1, int, rc); 157 158 return (rc); 159 } 160 161 __checkReturn int 162 efx_nvram_get_version( 163 __in efx_nic_t *enp, 164 __in efx_nvram_type_t type, 165 __out uint32_t *subtypep, 166 __out_ecount(4) uint16_t version[4]) 167 { 168 efx_nvram_ops_t *envop = enp->en_envop; 169 int rc; 170 171 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 172 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 173 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 174 175 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 176 177 if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0) 178 goto fail1; 179 180 return (0); 181 182 fail1: 183 EFSYS_PROBE1(fail1, int, rc); 184 185 return (rc); 186 } 187 188 __checkReturn int 189 efx_nvram_rw_start( 190 __in efx_nic_t *enp, 191 __in efx_nvram_type_t type, 192 __out_opt size_t *chunk_sizep) 193 { 194 efx_nvram_ops_t *envop = enp->en_envop; 195 int rc; 196 197 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 198 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 199 200 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 201 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 202 203 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 204 205 if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0) 206 goto fail1; 207 208 enp->en_nvram_locked = type; 209 210 return (0); 211 212 fail1: 213 EFSYS_PROBE1(fail1, int, rc); 214 215 return (rc); 216 } 217 218 __checkReturn int 219 efx_nvram_read_chunk( 220 __in efx_nic_t *enp, 221 __in efx_nvram_type_t type, 222 __in unsigned int offset, 223 __out_bcount(size) caddr_t data, 224 __in size_t size) 225 { 226 efx_nvram_ops_t *envop = enp->en_envop; 227 int rc; 228 229 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 230 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 231 232 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 233 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 234 235 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 236 237 if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0) 238 goto fail1; 239 240 return (0); 241 242 fail1: 243 EFSYS_PROBE1(fail1, int, rc); 244 245 return (rc); 246 } 247 248 __checkReturn int 249 efx_nvram_erase( 250 __in efx_nic_t *enp, 251 __in efx_nvram_type_t type) 252 { 253 efx_nvram_ops_t *envop = enp->en_envop; 254 int rc; 255 256 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 257 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 258 259 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 260 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 261 262 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 263 264 if ((rc = envop->envo_erase(enp, type)) != 0) 265 goto fail1; 266 267 return (0); 268 269 fail1: 270 EFSYS_PROBE1(fail1, int, rc); 271 272 return (rc); 273 } 274 275 __checkReturn int 276 efx_nvram_write_chunk( 277 __in efx_nic_t *enp, 278 __in efx_nvram_type_t type, 279 __in unsigned int offset, 280 __in_bcount(size) caddr_t data, 281 __in size_t size) 282 { 283 efx_nvram_ops_t *envop = enp->en_envop; 284 int rc; 285 286 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 287 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 288 289 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 290 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 291 292 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 293 294 if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0) 295 goto fail1; 296 297 return (0); 298 299 fail1: 300 EFSYS_PROBE1(fail1, int, rc); 301 302 return (rc); 303 } 304 305 void 306 efx_nvram_rw_finish( 307 __in efx_nic_t *enp, 308 __in efx_nvram_type_t type) 309 { 310 efx_nvram_ops_t *envop = enp->en_envop; 311 312 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 313 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 314 315 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 316 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 317 318 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 319 320 envop->envo_rw_finish(enp, type); 321 322 enp->en_nvram_locked = EFX_NVRAM_INVALID; 323 } 324 325 __checkReturn int 326 efx_nvram_set_version( 327 __in efx_nic_t *enp, 328 __in efx_nvram_type_t type, 329 __out uint16_t version[4]) 330 { 331 efx_nvram_ops_t *envop = enp->en_envop; 332 int rc; 333 334 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 335 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 336 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 337 338 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 339 340 /* 341 * The Siena implementation of envo_set_version() will attempt to 342 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector. 343 * Therefore, you can't have already acquired the NVRAM_UPDATE lock. 344 */ 345 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 346 347 if ((rc = envop->envo_set_version(enp, type, version)) != 0) 348 goto fail1; 349 350 return (0); 351 352 fail1: 353 EFSYS_PROBE1(fail1, int, rc); 354 355 return (rc); 356 } 357 358 void 359 efx_nvram_fini( 360 __in efx_nic_t *enp) 361 { 362 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 363 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 364 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 365 366 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 367 368 enp->en_envop = NULL; 369 enp->en_mod_flags &= ~EFX_MOD_NVRAM; 370 } 371 372 #endif /* EFSYS_OPT_NVRAM */