]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sfxge/sfxge_nvram.c
Connect the installation page to the build.
[FreeBSD/FreeBSD.git] / sys / dev / sfxge / sfxge_nvram.c
1 /*-
2  * Copyright (c) 2010-2016 Solarflare Communications, Inc.
3  * All rights reserved.
4  *
5  * This software was developed in part by OKTET Labs Ltd. under contract for
6  * Solarflare Communications, Inc.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33
34 #include <sys/types.h>
35 #include <sys/malloc.h>
36
37 #include "common/efx.h"
38 #include "sfxge.h"
39
40 /* These data make no real sense, they are here just to make sfupdate happy.
41  * Any code that would rely on it is broken.
42  */
43 static const uint8_t fake_dynamic_cfg_nvram[] = {
44         0x7a, 0xda, 0x10, 0xef, 0x0c, 0x00, 0x00, 0x00,
45         0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
46         0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10,
47         0x08, 0x00, 0x00, 0x00, 0x90, 0x04, 0x00, 0x52,
48         0x56, 0x01, 0xc3, 0x78, 0x01, 0x00, 0x03, 0x10,
49         0x08, 0x00, 0x00, 0x00, 0x90, 0x04, 0x00, 0x52,
50         0x56, 0x01, 0xc3, 0x78, 0x57, 0x1a, 0x10, 0xef,
51         0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
52         0x02, 0x0b, 0x64, 0x7d, 0xee, 0xee, 0xee, 0xee
53 };
54
55 static int
56 sfxge_nvram_rw(struct sfxge_softc *sc, sfxge_ioc_t *ip, efx_nvram_type_t type,
57                boolean_t write)
58 {
59         efx_nic_t *enp = sc->enp;
60         size_t total_size = ip->u.nvram.size;
61         size_t chunk_size;
62         off_t off;
63         int rc = 0;
64         uint8_t *buf;
65
66         if (type == EFX_NVRAM_DYNAMIC_CFG && sc->family == EFX_FAMILY_SIENA) {
67                 if (write)
68                         return (0);
69                 rc = copyout(fake_dynamic_cfg_nvram, ip->u.nvram.data,
70                              MIN(total_size, sizeof(fake_dynamic_cfg_nvram)));
71                 return (rc);
72         }
73
74         if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
75                 goto fail1;
76
77         buf = malloc(chunk_size, M_TEMP, M_WAITOK);
78
79         off = 0;
80         while (total_size) {
81                 size_t len = MIN(chunk_size, total_size);
82
83                 if (write) {
84                         rc = copyin(ip->u.nvram.data + off, buf, len);
85                         if (rc != 0)
86                                 goto fail3;
87                         rc = efx_nvram_write_chunk(enp, type,
88                                                    ip->u.nvram.offset + off, buf, len);
89                         if (rc != 0)
90                                 goto fail3;
91                 } else {
92                         rc = efx_nvram_read_chunk(enp, type,
93                                                   ip->u.nvram.offset + off, buf, len);
94                         if (rc != 0)
95                                 goto fail3;
96                         rc = copyout(buf, ip->u.nvram.data + off, len);
97                         if (rc != 0)
98                                 goto fail3;
99                 }
100
101                 total_size -= len;
102                 off += len;
103         }
104
105 fail3:
106         free(buf, M_TEMP);
107         efx_nvram_rw_finish(enp, type);
108 fail1:
109         return (rc);
110 }
111
112
113 static int
114 sfxge_nvram_erase(struct sfxge_softc *sc, efx_nvram_type_t type)
115 {
116         efx_nic_t *enp = sc->enp;
117         size_t chunk_size;
118         int rc = 0;
119
120         if (type == EFX_NVRAM_DYNAMIC_CFG && sc->family == EFX_FAMILY_SIENA)
121                 return (0);
122
123         if ((rc = efx_nvram_rw_start(enp, type, &chunk_size)) != 0)
124                 return (rc);
125
126         rc = efx_nvram_erase(enp, type);
127
128         efx_nvram_rw_finish(enp, type);
129         return (rc);
130 }
131
132 int
133 sfxge_nvram_ioctl(struct sfxge_softc *sc, sfxge_ioc_t *ip)
134 {
135         static const efx_nvram_type_t nvram_types[] = {
136                 [SFXGE_NVRAM_TYPE_BOOTROM]  = EFX_NVRAM_BOOTROM,
137                 [SFXGE_NVRAM_TYPE_BOOTROM_CFG]  = EFX_NVRAM_BOOTROM_CFG,
138                 [SFXGE_NVRAM_TYPE_MC]  = EFX_NVRAM_MC_FIRMWARE,
139                 [SFXGE_NVRAM_TYPE_MC_GOLDEN]  = EFX_NVRAM_MC_GOLDEN,
140                 [SFXGE_NVRAM_TYPE_PHY]  = EFX_NVRAM_PHY,
141                 [SFXGE_NVRAM_TYPE_NULL_PHY]  = EFX_NVRAM_NULLPHY,
142                 [SFXGE_NVRAM_TYPE_FPGA]  = EFX_NVRAM_FPGA,
143                 [SFXGE_NVRAM_TYPE_FCFW]  = EFX_NVRAM_FCFW,
144                 [SFXGE_NVRAM_TYPE_CPLD]  = EFX_NVRAM_CPLD,
145                 [SFXGE_NVRAM_TYPE_FPGA_BACKUP]  = EFX_NVRAM_FPGA_BACKUP,
146                 [SFXGE_NVRAM_TYPE_DYNAMIC_CFG]  = EFX_NVRAM_DYNAMIC_CFG,
147         };
148
149         efx_nic_t *enp = sc->enp;
150         efx_nvram_type_t type;
151         int rc = 0;
152
153         if (ip->u.nvram.type > SFXGE_NVRAM_TYPE_DYNAMIC_CFG)
154                 return (EINVAL);
155         type = nvram_types[ip->u.nvram.type];
156         if (type == EFX_NVRAM_MC_GOLDEN &&
157             (ip->u.nvram.op == SFXGE_NVRAM_OP_WRITE ||
158              ip->u.nvram.op == SFXGE_NVRAM_OP_ERASE ||
159              ip->u.nvram.op == SFXGE_NVRAM_OP_SET_VER))
160                 return (EOPNOTSUPP);
161
162         switch (ip->u.nvram.op) {
163         case SFXGE_NVRAM_OP_SIZE:
164         {
165                 size_t size;
166
167                 if (type == EFX_NVRAM_DYNAMIC_CFG && sc->family == EFX_FAMILY_SIENA) {
168                         ip->u.nvram.size = sizeof(fake_dynamic_cfg_nvram);
169                 } else {
170                         if ((rc = efx_nvram_size(enp, type, &size)) != 0)
171                                 return (rc);
172                         ip->u.nvram.size = size;
173                 }
174                 break;
175         }
176         case SFXGE_NVRAM_OP_READ:
177                 rc = sfxge_nvram_rw(sc, ip, type, B_FALSE);
178                 break;
179         case SFXGE_NVRAM_OP_WRITE:
180                 rc = sfxge_nvram_rw(sc, ip, type, B_TRUE);
181                 break;
182         case SFXGE_NVRAM_OP_ERASE:
183                 rc = sfxge_nvram_erase(sc, type);
184                 break;
185         case SFXGE_NVRAM_OP_GET_VER:
186                 rc = efx_nvram_get_version(enp, type, &ip->u.nvram.subtype,
187                                            &ip->u.nvram.version[0]);
188                 break;
189         case SFXGE_NVRAM_OP_SET_VER:
190                 rc = efx_nvram_set_version(enp, type, &ip->u.nvram.version[0]);
191                 break;
192         default:
193                 rc = EOPNOTSUPP;
194                 break;
195         }
196
197         return (rc);
198 }