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 <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 #include "efsys.h" 30 #include "efx.h" 31 #include "efx_types.h" 32 #include "efx_regs.h" 33 #include "efx_impl.h" 34 35 #if EFSYS_OPT_NVRAM 36 37 #if EFSYS_OPT_FALCON 38 39 static efx_nvram_ops_t __cs __efx_nvram_falcon_ops = { 40 #if EFSYS_OPT_DIAG 41 falcon_nvram_test, /* envo_test */ 42 #endif /* EFSYS_OPT_DIAG */ 43 falcon_nvram_size, /* envo_size */ 44 falcon_nvram_get_version, /* envo_get_version */ 45 falcon_nvram_rw_start, /* envo_rw_start */ 46 falcon_nvram_read_chunk, /* envo_read_chunk */ 47 falcon_nvram_erase, /* envo_erase */ 48 falcon_nvram_write_chunk, /* envo_write_chunk */ 49 falcon_nvram_rw_finish, /* envo_rw_finish */ 50 falcon_nvram_set_version, /* envo_set_version */ 51 }; 52 53 #endif /* EFSYS_OPT_FALCON */ 54 55 #if EFSYS_OPT_SIENA 56 57 static efx_nvram_ops_t __cs __efx_nvram_siena_ops = { 58 #if EFSYS_OPT_DIAG 59 siena_nvram_test, /* envo_test */ 60 #endif /* EFSYS_OPT_DIAG */ 61 siena_nvram_size, /* envo_size */ 62 siena_nvram_get_version, /* envo_get_version */ 63 siena_nvram_rw_start, /* envo_rw_start */ 64 siena_nvram_read_chunk, /* envo_read_chunk */ 65 siena_nvram_erase, /* envo_erase */ 66 siena_nvram_write_chunk, /* envo_write_chunk */ 67 siena_nvram_rw_finish, /* envo_rw_finish */ 68 siena_nvram_set_version, /* envo_set_version */ 69 }; 70 71 #endif /* EFSYS_OPT_SIENA */ 72 73 __checkReturn int 74 efx_nvram_init( 75 __in efx_nic_t *enp) 76 { 77 efx_nvram_ops_t *envop; 78 int rc; 79 80 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 81 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 82 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM)); 83 84 switch (enp->en_family) { 85 #if EFSYS_OPT_FALCON 86 case EFX_FAMILY_FALCON: 87 envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops; 88 break; 89 #endif /* EFSYS_OPT_FALCON */ 90 91 #if EFSYS_OPT_SIENA 92 case EFX_FAMILY_SIENA: 93 envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops; 94 break; 95 #endif /* EFSYS_OPT_SIENA */ 96 97 default: 98 EFSYS_ASSERT(0); 99 rc = ENOTSUP; 100 goto fail1; 101 } 102 103 enp->en_envop = envop; 104 enp->en_mod_flags |= EFX_MOD_NVRAM; 105 106 return (0); 107 108 fail1: 109 EFSYS_PROBE1(fail1, int, rc); 110 111 return (rc); 112 } 113 114 #if EFSYS_OPT_DIAG 115 116 __checkReturn int 117 efx_nvram_test( 118 __in efx_nic_t *enp) 119 { 120 efx_nvram_ops_t *envop = enp->en_envop; 121 int rc; 122 123 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 124 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 125 126 if ((rc = envop->envo_test(enp)) != 0) 127 goto fail1; 128 129 return (0); 130 131 fail1: 132 EFSYS_PROBE1(fail1, int, rc); 133 134 return (rc); 135 } 136 137 #endif /* EFSYS_OPT_DIAG */ 138 139 __checkReturn int 140 efx_nvram_size( 141 __in efx_nic_t *enp, 142 __in efx_nvram_type_t type, 143 __out size_t *sizep) 144 { 145 efx_nvram_ops_t *envop = enp->en_envop; 146 int rc; 147 148 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 149 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 150 151 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 152 153 if ((rc = envop->envo_size(enp, type, sizep)) != 0) 154 goto fail1; 155 156 return (0); 157 158 fail1: 159 EFSYS_PROBE1(fail1, int, rc); 160 161 return (rc); 162 } 163 164 __checkReturn int 165 efx_nvram_get_version( 166 __in efx_nic_t *enp, 167 __in efx_nvram_type_t type, 168 __out uint32_t *subtypep, 169 __out_ecount(4) uint16_t version[4]) 170 { 171 efx_nvram_ops_t *envop = enp->en_envop; 172 int rc; 173 174 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 175 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 176 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 177 178 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 179 180 if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0) 181 goto fail1; 182 183 return (0); 184 185 fail1: 186 EFSYS_PROBE1(fail1, int, rc); 187 188 return (rc); 189 } 190 191 __checkReturn int 192 efx_nvram_rw_start( 193 __in efx_nic_t *enp, 194 __in efx_nvram_type_t type, 195 __out_opt size_t *chunk_sizep) 196 { 197 efx_nvram_ops_t *envop = enp->en_envop; 198 int rc; 199 200 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 201 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 202 203 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 204 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 205 206 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 207 208 if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0) 209 goto fail1; 210 211 enp->en_nvram_locked = type; 212 213 return (0); 214 215 fail1: 216 EFSYS_PROBE1(fail1, int, rc); 217 218 return (rc); 219 } 220 221 __checkReturn int 222 efx_nvram_read_chunk( 223 __in efx_nic_t *enp, 224 __in efx_nvram_type_t type, 225 __in unsigned int offset, 226 __out_bcount(size) caddr_t data, 227 __in size_t size) 228 { 229 efx_nvram_ops_t *envop = enp->en_envop; 230 int rc; 231 232 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 233 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 234 235 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 236 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 237 238 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 239 240 if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0) 241 goto fail1; 242 243 return (0); 244 245 fail1: 246 EFSYS_PROBE1(fail1, int, rc); 247 248 return (rc); 249 } 250 251 __checkReturn int 252 efx_nvram_erase( 253 __in efx_nic_t *enp, 254 __in efx_nvram_type_t type) 255 { 256 efx_nvram_ops_t *envop = enp->en_envop; 257 int rc; 258 259 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 260 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 261 262 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 263 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 264 265 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 266 267 if ((rc = envop->envo_erase(enp, type)) != 0) 268 goto fail1; 269 270 return (0); 271 272 fail1: 273 EFSYS_PROBE1(fail1, int, rc); 274 275 return (rc); 276 } 277 278 __checkReturn int 279 efx_nvram_write_chunk( 280 __in efx_nic_t *enp, 281 __in efx_nvram_type_t type, 282 __in unsigned int offset, 283 __in_bcount(size) caddr_t data, 284 __in size_t size) 285 { 286 efx_nvram_ops_t *envop = enp->en_envop; 287 int rc; 288 289 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 290 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 291 292 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 293 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 294 295 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 296 297 if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0) 298 goto fail1; 299 300 return (0); 301 302 fail1: 303 EFSYS_PROBE1(fail1, int, rc); 304 305 return (rc); 306 } 307 308 void 309 efx_nvram_rw_finish( 310 __in efx_nic_t *enp, 311 __in efx_nvram_type_t type) 312 { 313 efx_nvram_ops_t *envop = enp->en_envop; 314 315 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 316 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 317 318 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 319 EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 320 321 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 322 323 envop->envo_rw_finish(enp, type); 324 325 enp->en_nvram_locked = EFX_NVRAM_INVALID; 326 } 327 328 __checkReturn int 329 efx_nvram_set_version( 330 __in efx_nic_t *enp, 331 __in efx_nvram_type_t type, 332 __out uint16_t version[4]) 333 { 334 efx_nvram_ops_t *envop = enp->en_envop; 335 int rc; 336 337 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 338 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 339 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 340 341 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 342 343 /* 344 * The Siena implementation of envo_set_version() will attempt to 345 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector. 346 * Therefore, you can't have already acquired the NVRAM_UPDATE lock. 347 */ 348 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 349 350 if ((rc = envop->envo_set_version(enp, type, version)) != 0) 351 goto fail1; 352 353 return (0); 354 355 fail1: 356 EFSYS_PROBE1(fail1, int, rc); 357 358 return (rc); 359 } 360 361 void 362 efx_nvram_fini( 363 __in efx_nic_t *enp) 364 { 365 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 366 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 367 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 368 369 EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 370 371 enp->en_envop = NULL; 372 enp->en_mod_flags &= ~EFX_MOD_NVRAM; 373 } 374 375 #endif /* EFSYS_OPT_NVRAM */ 376