1 /*
2 * Copyright 2007-2013 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 "falcon_nvram.h"
29 #include "efx_types.h"
30 #include "efx_impl.h"
31
32 #if EFSYS_OPT_FALCON
33
34 #if EFSYS_OPT_MON_LM87
35 #include "lm87.h"
36 #endif
37
38 #if EFSYS_OPT_MON_MAX6647
39 #include "max6647.h"
40 #endif
41
42 #if EFSYS_OPT_NVRAM_SFX7101
43 #include "sfx7101.h"
44 #endif
45
46 #if EFSYS_OPT_NVRAM_SFT9001
47 #include "sft9001.h"
48 #endif
49
50 #define FALCON_NVRAM_INIT_LOWEST_REG \
51 MIN(CFG_VERSION_REG_SF_OFST, \
52 MIN(CFG_FLASH_DEV_REG_SF_OFST, \
53 CFG_EEPROM_DEV_REG_SF_OFST))
54
55 #define FALCON_NVRAM_INIT_HIGHEST_REG \
56 MAX(CFG_VERSION_REG_SF_OFST, \
57 MAX(CFG_FLASH_DEV_REG_SF_OFST, \
58 CFG_EEPROM_DEV_REG_SF_OFST))
59
60 #define FALCON_NVRAM_INIT_NEEDED_CFG_SIZE \
61 (FALCON_NVRAM_INIT_HIGHEST_REG + sizeof (efx_oword_t) \
62 - FALCON_NVRAM_INIT_LOWEST_REG)
63
64 __checkReturn int
65 falcon_nvram_init(
66 __in efx_nic_t *enp)
67 {
68 falcon_spi_dev_t *fsdp;
69 efx_oword_t oword;
70 uint16_t version;
71 int rc;
72 uint8_t cfg[FALCON_NVRAM_INIT_NEEDED_CFG_SIZE];
73 uint8_t *origin = cfg - FALCON_NVRAM_INIT_LOWEST_REG;
74
75 /* All boards have flash and EEPROM */
76 EFX_BAR_READO(enp, FR_AB_NIC_STAT_REG, &oword);
77 EFX_SET_OWORD_FIELD(oword, FRF_AB_SF_PRST, 1);
78 EFX_SET_OWORD_FIELD(oword, FRF_AB_EE_PRST, 1);
79 EFX_BAR_WRITEO(enp, FR_AB_NIC_STAT_REG, &oword);
80
81 /* Set up partial flash parameters */
82 fsdp = &(enp->en_u.falcon.enu_fsd[FALCON_SPI_FLASH]);
83 fsdp->fsd_sf_sel = 1;
84 fsdp->fsd_adbcnt = 3;
85 fsdp->fsd_munge = B_FALSE;
86
87 if ((rc = falcon_nic_cfg_raw_read_verify(enp,
88 FALCON_NVRAM_INIT_LOWEST_REG,
89 FALCON_NVRAM_INIT_NEEDED_CFG_SIZE, cfg)) != 0)
90 goto fail1;
91
92 version = EFX_WORD_FIELD(
93 *(efx_word_t *)(origin + CFG_VERSION_REG_SF_OFST), VERSION);
94
95 if (version < 3) {
96 fsdp->fsd_size = (size_t)1 << 17;
97 fsdp->fsd_erase_cmd = 0x52;
98 fsdp->fsd_erase_size = (size_t)1 << 15;
99 fsdp->fsd_write_size = (size_t)1 << 8;
100 } else {
101 efx_dword_t *dwordp =
102 (efx_dword_t *)(origin + CFG_FLASH_DEV_REG_SF_OFST);
103
104 if (EFX_DWORD_FIELD(*dwordp, SPI_DEV_ADBCNT) != 3 ||
105 EFX_DWORD_FIELD(*dwordp, SPI_DEV_SIZE) >= 24) {
106 rc = EINVAL;
107 goto fail2;
108 }
109
110 fsdp->fsd_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
111 SPI_DEV_SIZE);
112 fsdp->fsd_erase_cmd = EFX_DWORD_FIELD(*dwordp,
113 SPI_DEV_ERASE_CMD);
114 fsdp->fsd_erase_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
115 SPI_DEV_ERASE_SIZE);
116 fsdp->fsd_write_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
117 SPI_DEV_WRITE_SIZE);
118 }
119
120 /* Configure the EEPROM */
121 fsdp = &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
122
123 fsdp->fsd_sf_sel = 0;
124 if (version < 3) {
125 fsdp->fsd_adbcnt = 1;
126 fsdp->fsd_size = (size_t)1 << 9;
127 fsdp->fsd_munge = B_TRUE;
128 fsdp->fsd_erase_cmd = 0;
129 fsdp->fsd_erase_size = 1;
130 fsdp->fsd_write_size = (size_t)1 << 3;
131 } else {
132 efx_dword_t *dwordp =
133 (efx_dword_t *)(origin + CFG_EEPROM_DEV_REG_SF_OFST);
134
135 fsdp->fsd_adbcnt = EFX_DWORD_FIELD(*dwordp, SPI_DEV_ADBCNT);
136 fsdp->fsd_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
137 SPI_DEV_SIZE);
138 fsdp->fsd_munge = (EFX_DWORD_FIELD(*dwordp, SPI_DEV_SIZE) >
139 fsdp->fsd_adbcnt * 8);
140 fsdp->fsd_erase_cmd = EFX_DWORD_FIELD(*dwordp,
141 SPI_DEV_ERASE_CMD);
142 fsdp->fsd_erase_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
143 SPI_DEV_ERASE_SIZE);
144 fsdp->fsd_write_size = (size_t)1 << EFX_DWORD_FIELD(*dwordp,
145 SPI_DEV_WRITE_SIZE);
146 }
147
148 return (0);
149
150 fail2:
151 EFSYS_PROBE(fail2);
152 fail1:
153 EFSYS_PROBE1(fail1, int, rc);
154
155 (void) memset(enp->en_u.falcon.enu_fsd, 0,
156 sizeof (enp->en_u.falcon.enu_fsd));
157
158 return (rc);
159 }
160
161 #if EFSYS_OPT_NVRAM
162
163 typedef struct falcon_nvram_ops_s {
164 int (*fnvo_size)(efx_nic_t *, size_t *);
165 int (*fnvo_get_version)(efx_nic_t *, uint32_t *, uint16_t *);
166 int (*fnvo_rw_start)(efx_nic_t *, size_t *);
167 int (*fnvo_read_chunk)(efx_nic_t *, unsigned int,
168 caddr_t, size_t);
169 int (*fnvo_erase)(efx_nic_t *);
170 int (*fnvo_write_chunk)(efx_nic_t *, unsigned int,
171 caddr_t, size_t);
172 void (*fnvo_rw_finish)(efx_nic_t *);
173 } falcon_nvram_ops_t;
174
175 #if EFSYS_OPT_NVRAM_FALCON_BOOTROM
176
177 #define FALCON_GPXE_IMAGE_OFFSET 0x8000
178 #define FALCON_GPXE_IMAGE_SIZE 0x18000
179
180 static __checkReturn int
181 falcon_nvram_bootrom_size(
182 __in efx_nic_t *enp,
183 __out size_t *sizep)
184 {
185 _NOTE(ARGUNUSED(enp))
186 EFSYS_ASSERT(sizep != NULL);
187 *sizep = FALCON_GPXE_IMAGE_SIZE;
188
189 return (0);
190 }
191
192 static __checkReturn int
193 falcon_nvram_bootrom_get_version(
194 __in efx_nic_t *enp,
195 __out uint32_t *subtypep,
196 __out_ecount(4) uint16_t version[4])
197 {
198 const char prefix[] = "Solarstorm Boot Manager (v";
199 char buf[16], p;
200 size_t current, needle;
201 uint16_t *versionp;
202 int rc;
203
204 version[0] = version[1] = version[2] = version[3] = 0;
205 versionp = NULL;
206 needle = 0;
207
208 /*
209 * Search from [current, end) for prefix, and return the
210 * trailing four decimal number.
211 */
212 for (current = 0; current < 0x600; current++) {
213 if (current % sizeof (buf) == 0) {
214 if ((rc = falcon_spi_dev_read(enp, FALCON_SPI_FLASH,
215 FALCON_GPXE_IMAGE_OFFSET + current, buf,
216 sizeof (buf))) != 0)
217 break;
218 }
219
220 p = buf[current % sizeof (buf)];
221 if (versionp == NULL) {
222 if (prefix[needle] == p) {
223 ++needle;
224 if (needle == sizeof (prefix) - 1)
225 versionp = version;
226 } else
227 needle = 0;
228 } else {
229 if (p == ')' && versionp == version + 3)
230 goto done;
231 else if (p >= '0' && p <= '9')
232 *versionp = (*versionp * 10) + (p - '0');
233 else if (p == '.' && versionp != version + 3)
234 ++versionp;
235 else
236 /* Invalid format */
237 break;
238 }
239 }
240
241 version[0] = version[1] = version[2] = version[3] = 0;
242
243 done:
244 *subtypep = 0; /* Falcon bootrom is type 0 */
245
246 return (0);
247 }
248
249 static __checkReturn int
250 falcon_nvram_bootrom_rw_start(
251 __in efx_nic_t *enp,
252 __out size_t *chunk_sizep)
253 {
254 _NOTE(ARGUNUSED(enp))
255 if (chunk_sizep != NULL)
256 *chunk_sizep = sizeof (efx_oword_t);
257
258 return (0);
259 }
260
261 static __checkReturn int
262 falcon_nvram_bootrom_read_chunk(
263 __in efx_nic_t *enp,
264 __in unsigned int offset,
265 __out_bcount(size) caddr_t data,
266 __in size_t size)
267 {
268 int rc;
269
270 EFSYS_ASSERT3U(size + offset, <=, FALCON_GPXE_IMAGE_SIZE);
271
272 if ((rc = falcon_spi_dev_read(enp, FALCON_SPI_FLASH,
273 FALCON_GPXE_IMAGE_OFFSET + offset, data, size)) != 0)
274 goto fail1;
275
276 return (0);
277
278 fail1:
279 EFSYS_PROBE1(fail1, int, rc);
280
281 return (rc);
282 }
283
284 static __checkReturn int
285 falcon_nvram_bootrom_erase(
286 __in efx_nic_t *enp)
287 {
288 int rc;
289
290 if ((rc = falcon_spi_dev_erase(enp, FALCON_SPI_FLASH,
291 FALCON_GPXE_IMAGE_OFFSET, FALCON_GPXE_IMAGE_SIZE)) != 0)
292 goto fail1;
293
294 return (0);
295
296 fail1:
297 EFSYS_PROBE1(fail1, int, rc);
298
299 return (rc);
300 }
301
302 static __checkReturn int
303 falcon_nvram_bootrom_write_chunk(
304 __in efx_nic_t *enp,
305 __in unsigned int offset,
306 __out_bcount(size) caddr_t base,
307 __in size_t size)
308 {
309 int rc;
310
311 if ((rc = falcon_spi_dev_write(enp, FALCON_SPI_FLASH,
312 FALCON_GPXE_IMAGE_OFFSET + offset, base, size)) != 0)
313 goto fail1;
314
315 return (0);
316
317 fail1:
318 EFSYS_PROBE1(fail1, int, rc);
319
320 return (rc);
321 }
322
323 static falcon_nvram_ops_t __cs __falcon_nvram_bootrom_ops = {
324 falcon_nvram_bootrom_size, /* fnvo_size */
325 falcon_nvram_bootrom_get_version, /* fnvo_get_version */
326 falcon_nvram_bootrom_rw_start, /* fnvo_rw_start */
327 falcon_nvram_bootrom_read_chunk, /* fnvo_read_chunk */
328 falcon_nvram_bootrom_erase, /* fnvo_erase */
329 falcon_nvram_bootrom_write_chunk, /* fnvo_write_chunk */
330 NULL, /* fnvo_rw_finish */
331 };
332
333 #define FALCON_GPXE_CFG_OFFSET 0x800
334
335 static __checkReturn int
336 falcon_nvram_bootrom_cfg_size(
337 __in efx_nic_t *enp,
338 __out size_t *sizep)
339 {
340 falcon_spi_dev_t *fsdp =
341 &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
342 int rc;
343
344 EFSYS_ASSERT(sizep != NULL);
345 EFSYS_ASSERT(fsdp != NULL);
346
347 if (fsdp->fsd_size < FALCON_GPXE_CFG_OFFSET) {
348 *sizep = 0;
349 rc = ENOTSUP;
350 goto fail1;
351 }
352
353 *sizep = fsdp->fsd_size - FALCON_GPXE_CFG_OFFSET;
354
355 return (0);
356
357 fail1:
358 EFSYS_PROBE1(fail1, int, rc);
359
360 return (rc);
361 }
362
363 static __checkReturn int
364 falcon_nvram_bootrom_cfg_get_version(
365 __in efx_nic_t *enp,
366 __out uint32_t *subtypep,
367 __out_ecount(4) uint16_t version[4])
368 {
369 falcon_spi_dev_t *fsdp =
370 &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
371 int rc;
372
373 EFSYS_ASSERT(fsdp != NULL);
374 if (fsdp->fsd_size < FALCON_GPXE_CFG_OFFSET) {
375 rc = ENOTSUP;
376 goto fail1;
377 }
378
379 /* gpxecfg is not versioned */
380 *subtypep = 0;
381 version[0] = version[1] = version[2] = version[3];
382
383 return (0);
384
385 fail1:
386 EFSYS_PROBE1(fail1, int, rc);
387
388 return (rc);
389 }
390
391 static __checkReturn int
392 falcon_nvram_bootrom_cfg_rw_start(
393 __in efx_nic_t *enp,
394 __out size_t *chunk_sizep)
395 {
396 falcon_spi_dev_t *fsdp =
397 &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
398 int rc;
399
400 EFSYS_ASSERT(fsdp != NULL);
401 if (fsdp->fsd_size < FALCON_GPXE_CFG_OFFSET) {
402 rc = ENOTSUP;
403 goto fail1;
404 }
405
406 if (chunk_sizep != NULL)
407 *chunk_sizep = sizeof (efx_oword_t);
408
409 return (0);
410
411 fail1:
412 EFSYS_PROBE1(fail1, int, rc);
413
414 return (rc);
415 }
416
417
418 static __checkReturn int
419 falcon_nvram_bootrom_cfg_read_chunk(
420 __in efx_nic_t *enp,
421 __in unsigned int offset,
422 __out_bcount(size) caddr_t data,
423 __in size_t size)
424 {
425 falcon_spi_dev_t *fsdp =
426 &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
427 int rc;
428
429 EFSYS_ASSERT(fsdp != NULL);
430 EFSYS_ASSERT3U(fsdp->fsd_size, >=, FALCON_GPXE_CFG_OFFSET);
431 EFSYS_ASSERT3U(offset + size, <=,
432 fsdp->fsd_size - FALCON_GPXE_CFG_OFFSET);
433
434 if ((rc = falcon_spi_dev_read(enp, FALCON_SPI_EEPROM,
435 FALCON_GPXE_CFG_OFFSET + offset, data, size)) != 0)
436 goto fail1;
437
438 return (0);
439
440 fail1:
441 EFSYS_PROBE1(fail1, int, rc);
442
443 return (rc);
444 }
445
446 static __checkReturn int
447 falcon_nvram_bootrom_cfg_write_chunk(
448 __in efx_nic_t *enp,
449 __in unsigned int offset,
450 __in_bcount(size) caddr_t base,
451 __in size_t size)
452 {
453 falcon_spi_dev_t *fsdp =
454 &(enp->en_u.falcon.enu_fsd[FALCON_SPI_EEPROM]);
455 int rc;
456
457 EFSYS_ASSERT(fsdp != NULL);
458 EFSYS_ASSERT3U(fsdp->fsd_size, >=, FALCON_GPXE_CFG_OFFSET);
459 EFSYS_ASSERT3U(offset + size, <=,
460 fsdp->fsd_size - FALCON_GPXE_CFG_OFFSET);
461
462 if ((rc = falcon_spi_dev_write(enp, FALCON_SPI_EEPROM,
463 FALCON_GPXE_CFG_OFFSET + offset, base, size)) != 0)
464 goto fail1;
465
466 return (0);
467
468 fail1:
469 EFSYS_PROBE1(fail1, int, rc);
470
471 return (rc);
472 }
473
474 static falcon_nvram_ops_t __cs __falcon_nvram_bootrom_cfg_ops = {
475 falcon_nvram_bootrom_cfg_size, /* fnvo_size */
476 falcon_nvram_bootrom_cfg_get_version, /* fnvo_get_version */
477 falcon_nvram_bootrom_cfg_rw_start, /* fnvo_rw_start */
478 falcon_nvram_bootrom_cfg_read_chunk, /* fnvo_read_chunk */
479 NULL, /* fnvo_erase */
480 falcon_nvram_bootrom_cfg_write_chunk, /* fnvo_write_chunk */
481 NULL, /* fnvo_rw_finish */
482 };
483
484 #endif /* EFSYS_OPT_NVRAM_FALCON_BOOTROM */
485
486 #if EFSYS_OPT_NVRAM_SFX7101
487
488 static falcon_nvram_ops_t __cs __falcon_sfx7101_ops = {
489 sfx7101_nvram_size, /* fnvo_size */
490 sfx7101_nvram_get_version, /* fnvo_get_version */
491 sfx7101_nvram_rw_start, /* fnvo_rw_start */
492 sfx7101_nvram_read_chunk, /* fnvo_read_chunk */
493 sfx7101_nvram_erase, /* fnvo_erase */
494 sfx7101_nvram_write_chunk, /* fnvo_write_chunk */
495 sfx7101_nvram_rw_finish, /* fnvo_rw_finish */
496 };
497
498 #endif /* EFSYS_OPT_NVRAM_SFX7101 */
499
500 #if EFSYS_OPT_NVRAM_SFT9001
501
502 static falcon_nvram_ops_t __cs __falcon_sft9001_ops = {
503 sft9001_nvram_size, /* fnvo_size */
504 sft9001_nvram_get_version, /* fnvo_get_version */
505 sft9001_nvram_rw_start, /* fnvo_rw_start */
506 sft9001_nvram_read_chunk, /* fnvo_read_chunk */
507 sft9001_nvram_erase, /* fnvo_erase */
508 sft9001_nvram_write_chunk, /* fnvo_write_chunk */
509 sft9001_nvram_rw_finish, /* fnvo_rw_finish */
510 };
511
512 #endif /* EFSYS_OPT_NVRAM_SFT9001 */
513
514 static __checkReturn int
515 falcon_nvram_get_ops(
516 __in efx_nic_t *enp,
517 __in efx_nvram_type_t type,
518 __out falcon_nvram_ops_t **fnvopp)
519 {
520 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
521 falcon_nvram_ops_t *fnvop;
522 int rc;
523
524 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
525
526 switch (type) {
527 #if EFSYS_OPT_NVRAM_FALCON_BOOTROM
528 case EFX_NVRAM_BOOTROM_CFG:
529 fnvop = (falcon_nvram_ops_t *)&__falcon_nvram_bootrom_cfg_ops;
530 goto done;
531
532 case EFX_NVRAM_BOOTROM:
533 fnvop = (falcon_nvram_ops_t *)&__falcon_nvram_bootrom_ops;
534 goto done;
535 #endif
536 case EFX_NVRAM_PHY:
537 switch (encp->enc_phy_type) {
538 #if EFSYS_OPT_NVRAM_SFX7101
539 case EFX_PHY_SFX7101:
540 fnvop = (falcon_nvram_ops_t *)&__falcon_sfx7101_ops;
541 goto done;
542 #endif /* EFSYS_OPT_NVRAM_SFX7101 */
543
544 #if EFSYS_OPT_NVRAM_SFT9001
545 case EFX_PHY_SFT9001B:
546 fnvop = (falcon_nvram_ops_t *)&__falcon_sft9001_ops;
547 goto done;
548 #endif /* EFSYS_OPT_NVRAM_SFT9001 */
549
550 default:
551 break;
552 }
553
554 break;
555
556 default:
557 break;
558 }
559
560 rc = ENOTSUP;
561 goto fail1;
562
563 done:
564 *fnvopp = fnvop;
565
566 return (0);
567
568 fail1:
569 EFSYS_PROBE1(fail1, int, rc);
570
571 return (rc);
572 }
573
574 #if EFSYS_OPT_DIAG
575
576 __checkReturn int
577 falcon_nvram_test(
578 __in efx_nic_t *enp)
579 {
580 efx_nic_cfg_t enc;
581 int rc;
582
583 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
584 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
585
586 if ((rc = falcon_nic_cfg_build(enp, &enc)) != 0)
587 goto fail1;
588
589 return (0);
590
591 fail1:
592 EFSYS_PROBE1(fail1, int, rc);
593
594 return (rc);
595 }
596
597 #endif /* EFSYS_OPT_DIAG */
598
599 __checkReturn int
600 falcon_nvram_size(
601 __in efx_nic_t *enp,
602 __in efx_nvram_type_t type,
603 __out size_t *sizep)
604 {
605 falcon_nvram_ops_t *fnvop;
606 int rc;
607
608 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
609 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
610
611 if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
612 goto fail1;
613
614 if ((rc = fnvop->fnvo_size(enp, sizep)) != 0)
615 goto fail2;
616
617 return (0);
618
619 fail2:
620 EFSYS_PROBE(fail2);
621 fail1:
622 EFSYS_PROBE1(fail1, int, rc);
623
624 return (rc);
625 }
626
627 __checkReturn int
628 falcon_nvram_get_version(
629 __in efx_nic_t *enp,
630 __in efx_nvram_type_t type,
631 __out uint32_t *subtypep,
632 __out_ecount(4) uint16_t version[4])
633 {
634 falcon_nvram_ops_t *fnvop;
635 int rc;
636
637 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
638 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
639
640 if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
641 goto fail1;
642
643 if ((rc = fnvop->fnvo_get_version(enp, subtypep, version)) != 0)
644 goto fail2;
645
646 return (0);
647
648 fail2:
649 EFSYS_PROBE(fail2);
650 fail1:
651 EFSYS_PROBE1(fail1, int, rc);
652
653 return (rc);
654 }
655
656 __checkReturn int
657 falcon_nvram_rw_start(
658 __in efx_nic_t *enp,
659 __in efx_nvram_type_t type,
660 __out size_t *chunk_sizep)
661 {
662 falcon_nvram_ops_t *fnvop;
663 int rc;
664
665 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
666 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
667
668 if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
669 goto fail1;
670
671 if ((rc = fnvop->fnvo_rw_start(enp, chunk_sizep)) != 0)
672 goto fail2;
673
674 return (0);
675
676 fail2:
677 EFSYS_PROBE(fail2);
678 fail1:
679 EFSYS_PROBE1(fail1, int, rc);
680
681 return (rc);
682 }
683
684 __checkReturn int
685 falcon_nvram_read_chunk(
686 __in efx_nic_t *enp,
687 __in efx_nvram_type_t type,
688 __in unsigned int offset,
689 __out_bcount(size) caddr_t data,
690 __in size_t size)
691 {
692 falcon_nvram_ops_t *fnvop;
693 int rc;
694
695 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
696 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
697
698 if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
699 goto fail1;
700
701 if ((rc = fnvop->fnvo_read_chunk(enp, offset, data, size)) != 0)
702 goto fail2;
703
704 return (0);
705
706 fail2:
707 EFSYS_PROBE(fail2);
708 fail1:
709 EFSYS_PROBE1(fail1, int, rc);
710
711 return (rc);
712 }
713
714 __checkReturn int
715 falcon_nvram_erase(
716 __in efx_nic_t *enp,
717 __in efx_nvram_type_t type)
718 {
719 falcon_nvram_ops_t *fnvop;
720 int rc;
721
722 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
723 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
724
725 if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
726 goto fail1;
727
728 if (fnvop->fnvo_erase != NULL) {
729 if ((rc = fnvop->fnvo_erase(enp)) != 0)
730 goto fail2;
731 }
732
733 return (0);
734
735 fail2:
736 EFSYS_PROBE(fail2);
737 fail1:
738 EFSYS_PROBE1(fail1, int, rc);
739
740 return (rc);
741 }
742
743 __checkReturn int
744 falcon_nvram_write_chunk(
745 __in efx_nic_t *enp,
746 __in efx_nvram_type_t type,
747 __in unsigned int offset,
748 __in_bcount(size) caddr_t data,
749 __in size_t size)
750 {
751 falcon_nvram_ops_t *fnvop;
752 int rc;
753
754 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
755 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
756
757 if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
758 goto fail1;
759
760 if ((rc = fnvop->fnvo_write_chunk(enp, offset, data, size)) != 0)
761 goto fail2;
762
763 return (0);
764
765 fail2:
766 EFSYS_PROBE(fail2);
767 fail1:
768 EFSYS_PROBE1(fail1, int, rc);
769
770 return (rc);
771 }
772
773 void
774 falcon_nvram_rw_finish(
775 __in efx_nic_t *enp,
776 __in efx_nvram_type_t type)
777 {
778 falcon_nvram_ops_t *fnvop;
779 int rc;
780
781 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
782 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
783
784 rc = falcon_nvram_get_ops(enp, type, &fnvop);
785 EFSYS_ASSERT(rc == 0);
786 if (rc == 0) {
787 if (fnvop->fnvo_rw_finish != NULL)
788 fnvop->fnvo_rw_finish(enp);
789 }
790 }
791
792 __checkReturn int
793 falcon_nvram_set_version(
794 __in efx_nic_t *enp,
795 __in efx_nvram_type_t type,
796 __out uint16_t version[4])
797 {
798 falcon_nvram_ops_t *fnvop;
799 uint32_t subtype;
800 uint16_t old_version[4];
801 int rc;
802
803 _NOTE(ARGUNUSED(enp))
804 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
805 EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_FALCON);
806
807 /*
808 * There is no room on Falcon to version anything, so it's
809 * inferred where possible from the underlying entity.
810 */
811 if ((rc = falcon_nvram_get_ops(enp, type, &fnvop)) != 0)
812 goto fail1;
813
814 /*
815 * The user *really should be setting the version correctly
816 */
817 if ((rc = fnvop->fnvo_get_version(enp, &subtype, old_version)) != 0)
818 goto fail2;
819 EFSYS_ASSERT(memcmp(old_version, version, sizeof (old_version)) == 0);
820
821 return (0);
822
823 fail2:
824 EFSYS_PROBE(fail2);
825 fail1:
826 EFSYS_PROBE1(fail1, int, rc);
827
828 return (rc);
829 }
830
831 #endif /* EFSYS_OPT_NVRAM */
832
833 void
834 falcon_nvram_fini(
835 __in efx_nic_t *enp)
836 {
837 (void) memset(&enp->en_u.falcon.enu_fsd, 0,
838 sizeof (enp->en_u.falcon.enu_fsd));
839 }
840
841 #endif /* EFSYS_OPT_FALCON */