1*49ef7e06SGarrett D'Amore /*
2*49ef7e06SGarrett D'Amore * Copyright (c) 2009-2016 Solarflare Communications Inc.
3*49ef7e06SGarrett D'Amore * All rights reserved.
4*49ef7e06SGarrett D'Amore *
5*49ef7e06SGarrett D'Amore * Redistribution and use in source and binary forms, with or without
6*49ef7e06SGarrett D'Amore * modification, are permitted provided that the following conditions are met:
7*49ef7e06SGarrett D'Amore *
8*49ef7e06SGarrett D'Amore * 1. Redistributions of source code must retain the above copyright notice,
9*49ef7e06SGarrett D'Amore * this list of conditions and the following disclaimer.
10*49ef7e06SGarrett D'Amore * 2. Redistributions in binary form must reproduce the above copyright notice,
11*49ef7e06SGarrett D'Amore * this list of conditions and the following disclaimer in the documentation
12*49ef7e06SGarrett D'Amore * and/or other materials provided with the distribution.
13*49ef7e06SGarrett D'Amore *
14*49ef7e06SGarrett D'Amore * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15*49ef7e06SGarrett D'Amore * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16*49ef7e06SGarrett D'Amore * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17*49ef7e06SGarrett D'Amore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18*49ef7e06SGarrett D'Amore * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*49ef7e06SGarrett D'Amore * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*49ef7e06SGarrett D'Amore * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21*49ef7e06SGarrett D'Amore * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22*49ef7e06SGarrett D'Amore * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23*49ef7e06SGarrett D'Amore * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24*49ef7e06SGarrett D'Amore * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*49ef7e06SGarrett D'Amore *
26*49ef7e06SGarrett D'Amore * The views and conclusions contained in the software and documentation are
27*49ef7e06SGarrett D'Amore * those of the authors and should not be interpreted as representing official
28*49ef7e06SGarrett D'Amore * policies, either expressed or implied, of the FreeBSD Project.
29*49ef7e06SGarrett D'Amore */
30*49ef7e06SGarrett D'Amore
31*49ef7e06SGarrett D'Amore #include <sys/types.h>
32*49ef7e06SGarrett D'Amore #include <sys/ddi.h>
33*49ef7e06SGarrett D'Amore #include <sys/sunddi.h>
34*49ef7e06SGarrett D'Amore #include <sys/stream.h>
35*49ef7e06SGarrett D'Amore #include <sys/dlpi.h>
36*49ef7e06SGarrett D'Amore
37*49ef7e06SGarrett D'Amore #include "sfxge.h"
38*49ef7e06SGarrett D'Amore
39*49ef7e06SGarrett D'Amore static int
sfxge_nvram_rw(sfxge_t * sp,sfxge_nvram_ioc_t * snip,efx_nvram_type_t type,boolean_t write)40*49ef7e06SGarrett D'Amore sfxge_nvram_rw(sfxge_t *sp, sfxge_nvram_ioc_t *snip, efx_nvram_type_t type,
41*49ef7e06SGarrett D'Amore boolean_t write)
42*49ef7e06SGarrett D'Amore {
43*49ef7e06SGarrett D'Amore int (*op)(efx_nic_t *, efx_nvram_type_t, unsigned int, caddr_t, size_t);
44*49ef7e06SGarrett D'Amore efx_nic_t *enp = sp->s_enp;
45*49ef7e06SGarrett D'Amore size_t chunk_size;
46*49ef7e06SGarrett D'Amore off_t off;
47*49ef7e06SGarrett D'Amore int rc;
48*49ef7e06SGarrett D'Amore
49*49ef7e06SGarrett D'Amore op = (write) ? efx_nvram_write_chunk : efx_nvram_read_chunk;
50*49ef7e06SGarrett D'Amore
51*49ef7e06SGarrett D'Amore if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
52*49ef7e06SGarrett D'Amore goto fail1;
53*49ef7e06SGarrett D'Amore
54*49ef7e06SGarrett D'Amore off = 0;
55*49ef7e06SGarrett D'Amore while (snip->sni_size) {
56*49ef7e06SGarrett D'Amore size_t len = MIN(chunk_size, snip->sni_size);
57*49ef7e06SGarrett D'Amore caddr_t buf = (caddr_t)(&snip->sni_data[off]);
58*49ef7e06SGarrett D'Amore
59*49ef7e06SGarrett D'Amore if ((rc = op(enp, type, snip->sni_offset + off, buf, len)) != 0)
60*49ef7e06SGarrett D'Amore goto fail2;
61*49ef7e06SGarrett D'Amore
62*49ef7e06SGarrett D'Amore snip->sni_size -= len;
63*49ef7e06SGarrett D'Amore off += len;
64*49ef7e06SGarrett D'Amore }
65*49ef7e06SGarrett D'Amore
66*49ef7e06SGarrett D'Amore efx_nvram_rw_finish(enp, type);
67*49ef7e06SGarrett D'Amore return (0);
68*49ef7e06SGarrett D'Amore
69*49ef7e06SGarrett D'Amore fail2:
70*49ef7e06SGarrett D'Amore DTRACE_PROBE(fail2);
71*49ef7e06SGarrett D'Amore efx_nvram_rw_finish(enp, type);
72*49ef7e06SGarrett D'Amore fail1:
73*49ef7e06SGarrett D'Amore DTRACE_PROBE1(fail1, int, rc);
74*49ef7e06SGarrett D'Amore return (rc);
75*49ef7e06SGarrett D'Amore }
76*49ef7e06SGarrett D'Amore
77*49ef7e06SGarrett D'Amore
78*49ef7e06SGarrett D'Amore static int
sfxge_nvram_erase(sfxge_t * sp,sfxge_nvram_ioc_t * snip,efx_nvram_type_t type)79*49ef7e06SGarrett D'Amore sfxge_nvram_erase(sfxge_t *sp, sfxge_nvram_ioc_t *snip, efx_nvram_type_t type)
80*49ef7e06SGarrett D'Amore {
81*49ef7e06SGarrett D'Amore efx_nic_t *enp = sp->s_enp;
82*49ef7e06SGarrett D'Amore size_t chunk_size;
83*49ef7e06SGarrett D'Amore int rc;
84*49ef7e06SGarrett D'Amore _NOTE(ARGUNUSED(snip));
85*49ef7e06SGarrett D'Amore
86*49ef7e06SGarrett D'Amore if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
87*49ef7e06SGarrett D'Amore goto fail1;
88*49ef7e06SGarrett D'Amore
89*49ef7e06SGarrett D'Amore if ((rc = efx_nvram_erase(enp, type)) != 0)
90*49ef7e06SGarrett D'Amore goto fail2;
91*49ef7e06SGarrett D'Amore
92*49ef7e06SGarrett D'Amore efx_nvram_rw_finish(enp, type);
93*49ef7e06SGarrett D'Amore return (0);
94*49ef7e06SGarrett D'Amore
95*49ef7e06SGarrett D'Amore fail2:
96*49ef7e06SGarrett D'Amore DTRACE_PROBE(fail2);
97*49ef7e06SGarrett D'Amore efx_nvram_rw_finish(enp, type);
98*49ef7e06SGarrett D'Amore fail1:
99*49ef7e06SGarrett D'Amore DTRACE_PROBE1(fail1, int, rc);
100*49ef7e06SGarrett D'Amore return (rc);
101*49ef7e06SGarrett D'Amore }
102*49ef7e06SGarrett D'Amore
103*49ef7e06SGarrett D'Amore int
sfxge_nvram_ioctl(sfxge_t * sp,sfxge_nvram_ioc_t * snip)104*49ef7e06SGarrett D'Amore sfxge_nvram_ioctl(sfxge_t *sp, sfxge_nvram_ioc_t *snip)
105*49ef7e06SGarrett D'Amore {
106*49ef7e06SGarrett D'Amore efx_nic_t *enp = sp->s_enp;
107*49ef7e06SGarrett D'Amore efx_nvram_type_t type;
108*49ef7e06SGarrett D'Amore int rc;
109*49ef7e06SGarrett D'Amore
110*49ef7e06SGarrett D'Amore switch (snip->sni_type) {
111*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_TYPE_BOOTROM:
112*49ef7e06SGarrett D'Amore type = EFX_NVRAM_BOOTROM;
113*49ef7e06SGarrett D'Amore break;
114*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_TYPE_BOOTROM_CFG:
115*49ef7e06SGarrett D'Amore type = EFX_NVRAM_BOOTROM_CFG;
116*49ef7e06SGarrett D'Amore break;
117*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_TYPE_MC:
118*49ef7e06SGarrett D'Amore type = EFX_NVRAM_MC_FIRMWARE;
119*49ef7e06SGarrett D'Amore break;
120*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_TYPE_MC_GOLDEN:
121*49ef7e06SGarrett D'Amore type = EFX_NVRAM_MC_GOLDEN;
122*49ef7e06SGarrett D'Amore if (snip->sni_op == SFXGE_NVRAM_OP_WRITE ||
123*49ef7e06SGarrett D'Amore snip->sni_op == SFXGE_NVRAM_OP_ERASE ||
124*49ef7e06SGarrett D'Amore snip->sni_op == SFXGE_NVRAM_OP_SET_VER) {
125*49ef7e06SGarrett D'Amore rc = ENOTSUP;
126*49ef7e06SGarrett D'Amore goto fail1;
127*49ef7e06SGarrett D'Amore }
128*49ef7e06SGarrett D'Amore break;
129*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_TYPE_PHY:
130*49ef7e06SGarrett D'Amore type = EFX_NVRAM_PHY;
131*49ef7e06SGarrett D'Amore break;
132*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_TYPE_NULL_PHY:
133*49ef7e06SGarrett D'Amore type = EFX_NVRAM_NULLPHY;
134*49ef7e06SGarrett D'Amore break;
135*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_TYPE_FPGA: /* PTP timestamping FPGA */
136*49ef7e06SGarrett D'Amore type = EFX_NVRAM_FPGA;
137*49ef7e06SGarrett D'Amore break;
138*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_TYPE_FCFW:
139*49ef7e06SGarrett D'Amore type = EFX_NVRAM_FCFW;
140*49ef7e06SGarrett D'Amore break;
141*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_TYPE_CPLD:
142*49ef7e06SGarrett D'Amore type = EFX_NVRAM_CPLD;
143*49ef7e06SGarrett D'Amore break;
144*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_TYPE_FPGA_BACKUP:
145*49ef7e06SGarrett D'Amore type = EFX_NVRAM_FPGA_BACKUP;
146*49ef7e06SGarrett D'Amore break;
147*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_TYPE_DYNAMIC_CFG:
148*49ef7e06SGarrett D'Amore type = EFX_NVRAM_DYNAMIC_CFG;
149*49ef7e06SGarrett D'Amore break;
150*49ef7e06SGarrett D'Amore default:
151*49ef7e06SGarrett D'Amore rc = EINVAL;
152*49ef7e06SGarrett D'Amore goto fail2;
153*49ef7e06SGarrett D'Amore }
154*49ef7e06SGarrett D'Amore
155*49ef7e06SGarrett D'Amore if (snip->sni_size > sizeof (snip->sni_data)) {
156*49ef7e06SGarrett D'Amore rc = ENOSPC;
157*49ef7e06SGarrett D'Amore goto fail3;
158*49ef7e06SGarrett D'Amore }
159*49ef7e06SGarrett D'Amore
160*49ef7e06SGarrett D'Amore switch (snip->sni_op) {
161*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_OP_SIZE:
162*49ef7e06SGarrett D'Amore {
163*49ef7e06SGarrett D'Amore size_t size;
164*49ef7e06SGarrett D'Amore if ((rc = efx_nvram_size(enp, type, &size)) != 0)
165*49ef7e06SGarrett D'Amore goto fail4;
166*49ef7e06SGarrett D'Amore snip->sni_size = (uint32_t)size;
167*49ef7e06SGarrett D'Amore break;
168*49ef7e06SGarrett D'Amore }
169*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_OP_READ:
170*49ef7e06SGarrett D'Amore if ((rc = sfxge_nvram_rw(sp, snip, type, B_FALSE)) != 0)
171*49ef7e06SGarrett D'Amore goto fail4;
172*49ef7e06SGarrett D'Amore break;
173*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_OP_WRITE:
174*49ef7e06SGarrett D'Amore if ((rc = sfxge_nvram_rw(sp, snip, type, B_TRUE)) != 0)
175*49ef7e06SGarrett D'Amore goto fail4;
176*49ef7e06SGarrett D'Amore break;
177*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_OP_ERASE:
178*49ef7e06SGarrett D'Amore if ((rc = sfxge_nvram_erase(sp, snip, type)) != 0)
179*49ef7e06SGarrett D'Amore goto fail4;
180*49ef7e06SGarrett D'Amore break;
181*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_OP_GET_VER:
182*49ef7e06SGarrett D'Amore if ((rc = efx_nvram_get_version(enp, type, &snip->sni_subtype,
183*49ef7e06SGarrett D'Amore &snip->sni_version[0])) != 0)
184*49ef7e06SGarrett D'Amore goto fail4;
185*49ef7e06SGarrett D'Amore break;
186*49ef7e06SGarrett D'Amore case SFXGE_NVRAM_OP_SET_VER:
187*49ef7e06SGarrett D'Amore if ((rc = efx_nvram_set_version(enp, type,
188*49ef7e06SGarrett D'Amore &snip->sni_version[0])) != 0)
189*49ef7e06SGarrett D'Amore goto fail4;
190*49ef7e06SGarrett D'Amore break;
191*49ef7e06SGarrett D'Amore default:
192*49ef7e06SGarrett D'Amore rc = ENOTSUP;
193*49ef7e06SGarrett D'Amore goto fail5;
194*49ef7e06SGarrett D'Amore }
195*49ef7e06SGarrett D'Amore
196*49ef7e06SGarrett D'Amore return (0);
197*49ef7e06SGarrett D'Amore
198*49ef7e06SGarrett D'Amore fail5:
199*49ef7e06SGarrett D'Amore DTRACE_PROBE(fail5);
200*49ef7e06SGarrett D'Amore fail4:
201*49ef7e06SGarrett D'Amore DTRACE_PROBE(fail4);
202*49ef7e06SGarrett D'Amore fail3:
203*49ef7e06SGarrett D'Amore DTRACE_PROBE(fail3);
204*49ef7e06SGarrett D'Amore fail2:
205*49ef7e06SGarrett D'Amore DTRACE_PROBE(fail2);
206*49ef7e06SGarrett D'Amore fail1:
207*49ef7e06SGarrett D'Amore DTRACE_PROBE1(fail1, int, rc);
208*49ef7e06SGarrett D'Amore
209*49ef7e06SGarrett D'Amore return (rc);
210*49ef7e06SGarrett D'Amore }
211