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