Deleted Added
full compact
etherswitch.c (235288) etherswitch.c (241578)
1/*-
2 * Copyright (c) 2011-2012 Stefan Bethke.
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
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 2011-2012 Stefan Bethke.
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
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/etherswitch/etherswitch.c 235288 2012-05-11 20:53:20Z adrian $
26 * $FreeBSD: head/sys/dev/etherswitch/etherswitch.c 241578 2012-10-15 12:20:40Z ray $
27 */
28
29#include <sys/param.h>
30#include <sys/bus.h>
31#include <sys/conf.h>
32#include <sys/fcntl.h>
33#include <sys/lock.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37#include <sys/socket.h>
38#include <sys/sx.h>
39#include <sys/systm.h>
40#include <sys/uio.h>
41
42#include <net/if.h>
43
44#include <dev/etherswitch/etherswitch.h>
45
46#include "etherswitch_if.h"
47
48#define BUFSIZE 1024
49
50struct etherswitch_softc {
51 device_t sc_dev;
52 int sc_count;
53
54 struct cdev *sc_devnode;
55 struct sx sc_lock;
56};
57
58#define SWITCH_LOCK(sc) sx_xlock(&(sc)->sc_lock)
59#define SWITCH_UNLOCK(sc) sx_xunlock(&(sc)->sc_lock)
60
61static int etherswitch_probe(device_t);
62static int etherswitch_attach(device_t);
63static int etherswitch_detach(device_t);
64static void etherswitch_identify(driver_t *driver, device_t parent);
65
66devclass_t etherswitch_devclass;
67
68static device_method_t etherswitch_methods[] = {
69 /* device interface */
70 DEVMETHOD(device_identify, etherswitch_identify),
71 DEVMETHOD(device_probe, etherswitch_probe),
72 DEVMETHOD(device_attach, etherswitch_attach),
73 DEVMETHOD(device_detach, etherswitch_detach),
74
75 { 0, 0 }
76};
77
78driver_t etherswitch_driver = {
79 "etherswitch",
80 etherswitch_methods,
81 sizeof(struct etherswitch_softc),
82};
83
84static d_open_t etherswitchopen;
85static d_close_t etherswitchclose;
86static d_write_t etherswitchwrite;
87static d_read_t etherswitchread;
88static d_ioctl_t etherswitchioctl;
89
90static struct cdevsw etherswitch_cdevsw = {
91 .d_version = D_VERSION,
92 .d_flags = D_TRACKCLOSE,
93 .d_open = etherswitchopen,
94 .d_close = etherswitchclose,
95 .d_read = etherswitchread,
96 .d_write = etherswitchwrite,
97 .d_ioctl = etherswitchioctl,
98 .d_name = "etherswitch",
99};
100
101static void
102etherswitch_identify(driver_t *driver, device_t parent)
103{
104 if (device_find_child(parent, "etherswitch", -1) == NULL)
105 BUS_ADD_CHILD(parent, 0, "etherswitch", -1);
106}
107
108static int
109etherswitch_probe(device_t dev)
110{
111 device_set_desc(dev, "Switch controller");
112
113 return (0);
114}
115
116static int
117etherswitch_attach(device_t dev)
118{
119 struct etherswitch_softc *sc = (struct etherswitch_softc *)device_get_softc(dev);
120
121 sc->sc_dev = dev;
122 sx_init(&sc->sc_lock, "etherswitch");
123 sc->sc_devnode = make_dev(&etherswitch_cdevsw, device_get_unit(dev),
124 UID_ROOT, GID_WHEEL,
125 0600, "etherswitch%d", device_get_unit(dev));
126 if (sc->sc_devnode == NULL) {
127 device_printf(dev, "failed to create character device\n");
128 sx_destroy(&sc->sc_lock);
129 return (ENXIO);
130 }
131 sc->sc_devnode->si_drv1 = sc;
132
133 return (0);
134}
135
136static int
137etherswitch_detach(device_t dev)
138{
139 struct etherswitch_softc *sc = (struct etherswitch_softc *)device_get_softc(dev);
140
141 if (sc->sc_devnode)
142 destroy_dev(sc->sc_devnode);
143 sx_destroy(&sc->sc_lock);
144
145 return (0);
146}
147
148static int
149etherswitchopen(struct cdev *dev, int flags, int fmt, struct thread *td)
150{
151 struct etherswitch_softc *sc = dev->si_drv1;
152
153 SWITCH_LOCK(sc);
154 if (sc->sc_count > 0) {
155 SWITCH_UNLOCK(sc);
156 return (EBUSY);
157 }
158
159 sc->sc_count++;
160 SWITCH_UNLOCK(sc);
161
162 return (0);
163}
164
165static int
166etherswitchclose(struct cdev *dev, int flags, int fmt, struct thread *td)
167{
168 struct etherswitch_softc *sc = dev->si_drv1;
169
170 SWITCH_LOCK(sc);
171 if (sc->sc_count == 0) {
172 SWITCH_UNLOCK(sc);
173 return (EINVAL);
174 }
175
176 sc->sc_count--;
177
178 if (sc->sc_count < 0)
179 panic("%s: etherswitch_count < 0!", __func__);
180 SWITCH_UNLOCK(sc);
181
182 return (0);
183}
184
185static int
186etherswitchwrite(struct cdev *dev, struct uio * uio, int ioflag)
187{
188 return (EINVAL);
189}
190
191static int
192etherswitchread(struct cdev *dev, struct uio * uio, int ioflag)
193{
194 return (EINVAL);
195}
196
197static int
198etherswitchioctl(struct cdev *cdev, u_long cmd, caddr_t data, int flags, struct thread *td)
199{
200 struct etherswitch_softc *sc = cdev->si_drv1;
201 device_t dev = sc->sc_dev;
202 device_t etherswitch = device_get_parent(dev);
203 etherswitch_info_t *info;
204 etherswitch_reg_t *reg;
205 etherswitch_phyreg_t *phyreg;
206 int error = 0;
207
208 switch (cmd) {
209 case IOETHERSWITCHGETINFO:
210 info = ETHERSWITCH_GETINFO(etherswitch);
211 bcopy(info, data, sizeof(etherswitch_info_t));
212 break;
213
214 case IOETHERSWITCHGETREG:
215 reg = (etherswitch_reg_t *)data;
27 */
28
29#include <sys/param.h>
30#include <sys/bus.h>
31#include <sys/conf.h>
32#include <sys/fcntl.h>
33#include <sys/lock.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37#include <sys/socket.h>
38#include <sys/sx.h>
39#include <sys/systm.h>
40#include <sys/uio.h>
41
42#include <net/if.h>
43
44#include <dev/etherswitch/etherswitch.h>
45
46#include "etherswitch_if.h"
47
48#define BUFSIZE 1024
49
50struct etherswitch_softc {
51 device_t sc_dev;
52 int sc_count;
53
54 struct cdev *sc_devnode;
55 struct sx sc_lock;
56};
57
58#define SWITCH_LOCK(sc) sx_xlock(&(sc)->sc_lock)
59#define SWITCH_UNLOCK(sc) sx_xunlock(&(sc)->sc_lock)
60
61static int etherswitch_probe(device_t);
62static int etherswitch_attach(device_t);
63static int etherswitch_detach(device_t);
64static void etherswitch_identify(driver_t *driver, device_t parent);
65
66devclass_t etherswitch_devclass;
67
68static device_method_t etherswitch_methods[] = {
69 /* device interface */
70 DEVMETHOD(device_identify, etherswitch_identify),
71 DEVMETHOD(device_probe, etherswitch_probe),
72 DEVMETHOD(device_attach, etherswitch_attach),
73 DEVMETHOD(device_detach, etherswitch_detach),
74
75 { 0, 0 }
76};
77
78driver_t etherswitch_driver = {
79 "etherswitch",
80 etherswitch_methods,
81 sizeof(struct etherswitch_softc),
82};
83
84static d_open_t etherswitchopen;
85static d_close_t etherswitchclose;
86static d_write_t etherswitchwrite;
87static d_read_t etherswitchread;
88static d_ioctl_t etherswitchioctl;
89
90static struct cdevsw etherswitch_cdevsw = {
91 .d_version = D_VERSION,
92 .d_flags = D_TRACKCLOSE,
93 .d_open = etherswitchopen,
94 .d_close = etherswitchclose,
95 .d_read = etherswitchread,
96 .d_write = etherswitchwrite,
97 .d_ioctl = etherswitchioctl,
98 .d_name = "etherswitch",
99};
100
101static void
102etherswitch_identify(driver_t *driver, device_t parent)
103{
104 if (device_find_child(parent, "etherswitch", -1) == NULL)
105 BUS_ADD_CHILD(parent, 0, "etherswitch", -1);
106}
107
108static int
109etherswitch_probe(device_t dev)
110{
111 device_set_desc(dev, "Switch controller");
112
113 return (0);
114}
115
116static int
117etherswitch_attach(device_t dev)
118{
119 struct etherswitch_softc *sc = (struct etherswitch_softc *)device_get_softc(dev);
120
121 sc->sc_dev = dev;
122 sx_init(&sc->sc_lock, "etherswitch");
123 sc->sc_devnode = make_dev(&etherswitch_cdevsw, device_get_unit(dev),
124 UID_ROOT, GID_WHEEL,
125 0600, "etherswitch%d", device_get_unit(dev));
126 if (sc->sc_devnode == NULL) {
127 device_printf(dev, "failed to create character device\n");
128 sx_destroy(&sc->sc_lock);
129 return (ENXIO);
130 }
131 sc->sc_devnode->si_drv1 = sc;
132
133 return (0);
134}
135
136static int
137etherswitch_detach(device_t dev)
138{
139 struct etherswitch_softc *sc = (struct etherswitch_softc *)device_get_softc(dev);
140
141 if (sc->sc_devnode)
142 destroy_dev(sc->sc_devnode);
143 sx_destroy(&sc->sc_lock);
144
145 return (0);
146}
147
148static int
149etherswitchopen(struct cdev *dev, int flags, int fmt, struct thread *td)
150{
151 struct etherswitch_softc *sc = dev->si_drv1;
152
153 SWITCH_LOCK(sc);
154 if (sc->sc_count > 0) {
155 SWITCH_UNLOCK(sc);
156 return (EBUSY);
157 }
158
159 sc->sc_count++;
160 SWITCH_UNLOCK(sc);
161
162 return (0);
163}
164
165static int
166etherswitchclose(struct cdev *dev, int flags, int fmt, struct thread *td)
167{
168 struct etherswitch_softc *sc = dev->si_drv1;
169
170 SWITCH_LOCK(sc);
171 if (sc->sc_count == 0) {
172 SWITCH_UNLOCK(sc);
173 return (EINVAL);
174 }
175
176 sc->sc_count--;
177
178 if (sc->sc_count < 0)
179 panic("%s: etherswitch_count < 0!", __func__);
180 SWITCH_UNLOCK(sc);
181
182 return (0);
183}
184
185static int
186etherswitchwrite(struct cdev *dev, struct uio * uio, int ioflag)
187{
188 return (EINVAL);
189}
190
191static int
192etherswitchread(struct cdev *dev, struct uio * uio, int ioflag)
193{
194 return (EINVAL);
195}
196
197static int
198etherswitchioctl(struct cdev *cdev, u_long cmd, caddr_t data, int flags, struct thread *td)
199{
200 struct etherswitch_softc *sc = cdev->si_drv1;
201 device_t dev = sc->sc_dev;
202 device_t etherswitch = device_get_parent(dev);
203 etherswitch_info_t *info;
204 etherswitch_reg_t *reg;
205 etherswitch_phyreg_t *phyreg;
206 int error = 0;
207
208 switch (cmd) {
209 case IOETHERSWITCHGETINFO:
210 info = ETHERSWITCH_GETINFO(etherswitch);
211 bcopy(info, data, sizeof(etherswitch_info_t));
212 break;
213
214 case IOETHERSWITCHGETREG:
215 reg = (etherswitch_reg_t *)data;
216 ETHERSWITCH_LOCK(etherswitch);
216 reg->val = ETHERSWITCH_READREG(etherswitch, reg->reg);
217 reg->val = ETHERSWITCH_READREG(etherswitch, reg->reg);
218 ETHERSWITCH_UNLOCK(etherswitch);
217 break;
218
219 case IOETHERSWITCHSETREG:
220 reg = (etherswitch_reg_t *)data;
219 break;
220
221 case IOETHERSWITCHSETREG:
222 reg = (etherswitch_reg_t *)data;
223 ETHERSWITCH_LOCK(etherswitch);
221 error = ETHERSWITCH_WRITEREG(etherswitch, reg->reg, reg->val);
224 error = ETHERSWITCH_WRITEREG(etherswitch, reg->reg, reg->val);
225 ETHERSWITCH_UNLOCK(etherswitch);
222 break;
223
224 case IOETHERSWITCHGETPORT:
225 error = ETHERSWITCH_GETPORT(etherswitch, (etherswitch_port_t *)data);
226 break;
227
228 case IOETHERSWITCHSETPORT:
229 error = ETHERSWITCH_SETPORT(etherswitch, (etherswitch_port_t *)data);
230 break;
231
232 case IOETHERSWITCHGETVLANGROUP:
233 error = ETHERSWITCH_GETVGROUP(etherswitch, (etherswitch_vlangroup_t *)data);
234 break;
235
236 case IOETHERSWITCHSETVLANGROUP:
237 error = ETHERSWITCH_SETVGROUP(etherswitch, (etherswitch_vlangroup_t *)data);
238 break;
239
240 case IOETHERSWITCHGETPHYREG:
241 phyreg = (etherswitch_phyreg_t *)data;
242 phyreg->val = ETHERSWITCH_READPHYREG(etherswitch, phyreg->phy, phyreg->reg);
243 break;
244
245 case IOETHERSWITCHSETPHYREG:
246 phyreg = (etherswitch_phyreg_t *)data;
247 error = ETHERSWITCH_WRITEPHYREG(etherswitch, phyreg->phy, phyreg->reg, phyreg->val);
248 break;
249
250 default:
251 error = ENOTTY;
252 }
253
254 return (error);
255}
256
257MODULE_VERSION(etherswitch, 1);
226 break;
227
228 case IOETHERSWITCHGETPORT:
229 error = ETHERSWITCH_GETPORT(etherswitch, (etherswitch_port_t *)data);
230 break;
231
232 case IOETHERSWITCHSETPORT:
233 error = ETHERSWITCH_SETPORT(etherswitch, (etherswitch_port_t *)data);
234 break;
235
236 case IOETHERSWITCHGETVLANGROUP:
237 error = ETHERSWITCH_GETVGROUP(etherswitch, (etherswitch_vlangroup_t *)data);
238 break;
239
240 case IOETHERSWITCHSETVLANGROUP:
241 error = ETHERSWITCH_SETVGROUP(etherswitch, (etherswitch_vlangroup_t *)data);
242 break;
243
244 case IOETHERSWITCHGETPHYREG:
245 phyreg = (etherswitch_phyreg_t *)data;
246 phyreg->val = ETHERSWITCH_READPHYREG(etherswitch, phyreg->phy, phyreg->reg);
247 break;
248
249 case IOETHERSWITCHSETPHYREG:
250 phyreg = (etherswitch_phyreg_t *)data;
251 error = ETHERSWITCH_WRITEPHYREG(etherswitch, phyreg->phy, phyreg->reg, phyreg->val);
252 break;
253
254 default:
255 error = ENOTTY;
256 }
257
258 return (error);
259}
260
261MODULE_VERSION(etherswitch, 1);