1 | /*-
|
---|
2 | * Copyright (c) 2011 Rick van der Zwet <info@rickvanderzwet.nl>
|
---|
3 | *
|
---|
4 | * Permission to use, copy, modify, and distribute this software for any
|
---|
5 | * purpose with or without fee is hereby granted, provided that the above
|
---|
6 | * copyright notice and this permission notice appear in all copies.
|
---|
7 | *
|
---|
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
---|
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
---|
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
---|
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
---|
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
---|
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
---|
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
---|
15 | */
|
---|
16 |
|
---|
17 | /*-
|
---|
18 | * Copyright (c) 2001-2003, Shunsuke Akiyama <akiyama@FreeBSD.org>.
|
---|
19 | * Copyright (c) 1997, 1998, 1999, 2000 Bill Paul <wpaul@ee.columbia.edu>.
|
---|
20 | * All rights reserved.
|
---|
21 | *
|
---|
22 | * Redistribution and use in source and binary forms, with or without
|
---|
23 | * modification, are permitted provided that the following conditions
|
---|
24 | * are met:
|
---|
25 | * 1. Redistributions of source code must retain the above copyright
|
---|
26 | * notice, this list of conditions and the following disclaimer.
|
---|
27 | * 2. Redistributions in binary form must reproduce the above copyright
|
---|
28 | * notice, this list of conditions and the following disclaimer in the
|
---|
29 | * documentation and/or other materials provided with the distribution.
|
---|
30 | *
|
---|
31 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
---|
32 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
---|
33 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
---|
34 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
---|
35 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
---|
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
---|
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
---|
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
---|
39 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
---|
40 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
---|
41 | * SUCH DAMAGE.
|
---|
42 | */
|
---|
43 | /*-
|
---|
44 | * Copyright (c) 1997, 1998, 1999, 2000
|
---|
45 | * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
|
---|
46 | *
|
---|
47 | * Redistribution and use in source and binary forms, with or without
|
---|
48 | * modification, are permitted provided that the following conditions
|
---|
49 | * are met:
|
---|
50 | * 1. Redistributions of source code must retain the above copyright
|
---|
51 | * notice, this list of conditions and the following disclaimer.
|
---|
52 | * 2. Redistributions in binary form must reproduce the above copyright
|
---|
53 | * notice, this list of conditions and the following disclaimer in the
|
---|
54 | * documentation and/or other materials provided with the distribution.
|
---|
55 | * 3. All advertising materials mentioning features or use of this software
|
---|
56 | * must display the following acknowledgement:
|
---|
57 | * This product includes software developed by Bill Paul.
|
---|
58 | * 4. Neither the name of the author nor the names of any co-contributors
|
---|
59 | * may be used to endorse or promote products derived from this software
|
---|
60 | * without specific prior written permission.
|
---|
61 | *
|
---|
62 | * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
|
---|
63 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
---|
64 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
---|
65 | * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
|
---|
66 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
---|
67 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
---|
68 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
---|
69 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
---|
70 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
---|
71 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
---|
72 | * THE POSSIBILITY OF SUCH DAMAGE.
|
---|
73 | */
|
---|
74 |
|
---|
75 | #include <sys/cdefs.h>
|
---|
76 | __FBSDID("$FreeBSD: release/10.1.0/sys/dev/usb/net/if_rtl.c 251734 2013-06-14 05:36:47Z kevlo $");
|
---|
77 |
|
---|
78 | /*
|
---|
79 | * RealTek RTL8152 USB to fast ethernet controller driver.
|
---|
80 | * http://www.realtek.com.tw/products/productsView.aspx?Langid=1&PFid=55&Level=5&Conn=4&ProdID=323
|
---|
81 | *
|
---|
82 | * /TODO: With some modification the RealTek RTL8153 USB to fast ethernet
|
---|
83 | * controller driver. should also be supported, but yet no hardware to test it
|
---|
84 | * http://www.realtek.com.tw/products/productsView.aspx?Langid=1&PFid=56&Level=5&Conn=4&ProdID=326
|
---|
85 | *
|
---|
86 | */
|
---|
87 |
|
---|
88 | #include <sys/stdint.h>
|
---|
89 | #include <sys/stddef.h>
|
---|
90 | #include <sys/param.h>
|
---|
91 | #include <sys/queue.h>
|
---|
92 | #include <sys/types.h>
|
---|
93 | #include <sys/systm.h>
|
---|
94 | #include <sys/kernel.h>
|
---|
95 | #include <sys/bus.h>
|
---|
96 | #include <sys/module.h>
|
---|
97 | #include <sys/lock.h>
|
---|
98 | #include <sys/mutex.h>
|
---|
99 | #include <sys/condvar.h>
|
---|
100 | #include <sys/sysctl.h>
|
---|
101 | #include <sys/sx.h>
|
---|
102 | #include <sys/unistd.h>
|
---|
103 | #include <sys/callout.h>
|
---|
104 | #include <sys/malloc.h>
|
---|
105 | #include <sys/priv.h>
|
---|
106 |
|
---|
107 | #include <dev/usb/usb.h>
|
---|
108 | #include <dev/usb/usbdi.h>
|
---|
109 | #include <dev/usb/usbdi_util.h>
|
---|
110 | #include "usbdevs.h"
|
---|
111 |
|
---|
112 | #define USB_DEBUG_VAR rtl_debug
|
---|
113 | #include <dev/usb/usb_debug.h>
|
---|
114 | #include <dev/usb/usb_process.h>
|
---|
115 |
|
---|
116 | #include <dev/usb/net/usb_ethernet.h>
|
---|
117 | #include <dev/usb/net/if_rtlreg.h>
|
---|
118 |
|
---|
119 | #ifdef USB_DEBUG
|
---|
120 | static int rtl_debug = 1;
|
---|
121 |
|
---|
122 | static SYSCTL_NODE(_hw_usb, OID_AUTO, rtl, CTLFLAG_RW, 0, "USB rtl");
|
---|
123 | SYSCTL_INT(_hw_usb_rtl, OID_AUTO, debug, CTLFLAG_RW,
|
---|
124 | &rtl_debug, 0, "Debug level");
|
---|
125 | #endif
|
---|
126 |
|
---|
127 | /*
|
---|
128 | * Various supported device vendors/products.
|
---|
129 | */
|
---|
130 |
|
---|
131 | static const STRUCT_USB_HOST_ID rtl_devs[] = {
|
---|
132 | {USB_VPI(USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8152, 0)},
|
---|
133 | };
|
---|
134 |
|
---|
135 | /* prototypes */
|
---|
136 |
|
---|
137 | static device_probe_t rtl_probe;
|
---|
138 | static device_attach_t rtl_attach;
|
---|
139 | static device_detach_t rtl_detach;
|
---|
140 |
|
---|
141 | static miibus_readreg_t rtl_miibus_readreg;
|
---|
142 | static miibus_writereg_t rtl_miibus_writereg;
|
---|
143 | static miibus_statchg_t rtl_miibus_statchg;
|
---|
144 |
|
---|
145 | static usb_callback_t rtl_intr_callback;
|
---|
146 | static usb_callback_t rtl_bulk_read_callback;
|
---|
147 | static usb_callback_t rtl_bulk_write_callback;
|
---|
148 |
|
---|
149 | static uether_fn_t rtl_attach_post;
|
---|
150 | static uether_fn_t rtl_init;
|
---|
151 | static uether_fn_t rtl_stop;
|
---|
152 | static uether_fn_t rtl_start;
|
---|
153 | static uether_fn_t rtl_tick;
|
---|
154 | static uether_fn_t rtl_setpromisc_and_multi;
|
---|
155 |
|
---|
156 | static void rtl_reset(struct rtl_softc *);
|
---|
157 | static int rtl_ifmedia_upd(struct ifnet *);
|
---|
158 | static void rtl_ifmedia_sts(struct ifnet *, struct ifmediareq *);
|
---|
159 |
|
---|
160 | static const struct usb_config rtl_config[RTL_N_TRANSFER] = {
|
---|
161 |
|
---|
162 | [RTL_BULK_DT_RD] = {
|
---|
163 | .type = UE_BULK,
|
---|
164 | .endpoint = UE_ADDR_ANY,
|
---|
165 | .direction = UE_DIR_IN,
|
---|
166 | .bufsize = 16384,
|
---|
167 | .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
|
---|
168 | .callback = rtl_bulk_read_callback,
|
---|
169 | .timeout = 0, /* no timeout */
|
---|
170 | },
|
---|
171 |
|
---|
172 | [RTL_BULK_DT_WR] = {
|
---|
173 | .type = UE_BULK,
|
---|
174 | .endpoint = UE_ADDR_ANY,
|
---|
175 | .direction = UE_DIR_OUT,
|
---|
176 | .bufsize = 16384,
|
---|
177 | .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
|
---|
178 | .callback = rtl_bulk_write_callback,
|
---|
179 | .timeout = 1000, /* 1 seconds */
|
---|
180 | },
|
---|
181 |
|
---|
182 | [RTL_INTR_DT_RD] = {
|
---|
183 | .type = UE_INTERRUPT,
|
---|
184 | .endpoint = UE_ADDR_ANY,
|
---|
185 | .direction = UE_DIR_IN,
|
---|
186 | .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
|
---|
187 | .bufsize = 0, /* use wMaxPacketSize */
|
---|
188 | .callback = rtl_intr_callback,
|
---|
189 | },
|
---|
190 | };
|
---|
191 |
|
---|
192 | static device_method_t rtl_methods[] = {
|
---|
193 | /* Device interface */
|
---|
194 | DEVMETHOD(device_probe, rtl_probe),
|
---|
195 | DEVMETHOD(device_attach, rtl_attach),
|
---|
196 | DEVMETHOD(device_detach, rtl_detach),
|
---|
197 |
|
---|
198 | /* MII interface */
|
---|
199 | DEVMETHOD(miibus_readreg, rtl_miibus_readreg),
|
---|
200 | DEVMETHOD(miibus_writereg, rtl_miibus_writereg),
|
---|
201 | DEVMETHOD(miibus_statchg, rtl_miibus_statchg),
|
---|
202 |
|
---|
203 | DEVMETHOD_END
|
---|
204 | };
|
---|
205 |
|
---|
206 | static driver_t rtl_driver = {
|
---|
207 | .name = "rtl",
|
---|
208 | .methods = rtl_methods,
|
---|
209 | .size = sizeof(struct rtl_softc),
|
---|
210 | };
|
---|
211 |
|
---|
212 | static devclass_t rtl_devclass;
|
---|
213 |
|
---|
214 | DRIVER_MODULE_ORDERED(rtl, uhub, rtl_driver, rtl_devclass, NULL, NULL,
|
---|
215 | SI_ORDER_ANY);
|
---|
216 | DRIVER_MODULE(miibus, rtl, miibus_driver, miibus_devclass, NULL, NULL);
|
---|
217 | MODULE_DEPEND(rtl, uether, 1, 1, 1);
|
---|
218 | MODULE_DEPEND(rtl, usb, 1, 1, 1);
|
---|
219 | MODULE_DEPEND(rtl, ether, 1, 1, 1);
|
---|
220 | MODULE_DEPEND(rtl, miibus, 1, 1, 1);
|
---|
221 | MODULE_VERSION(rtl, 1);
|
---|
222 |
|
---|
223 | static const struct usb_ether_methods rtl_ue_methods = {
|
---|
224 | .ue_attach_post = rtl_attach_post,
|
---|
225 | .ue_start = rtl_start,
|
---|
226 | .ue_init = rtl_init,
|
---|
227 | .ue_stop = rtl_stop,
|
---|
228 | .ue_tick = rtl_tick,
|
---|
229 | .ue_setmulti = rtl_setpromisc_and_multi,
|
---|
230 | .ue_setpromisc = rtl_setpromisc_and_multi,
|
---|
231 | .ue_mii_upd = rtl_ifmedia_upd,
|
---|
232 | .ue_mii_sts = rtl_ifmedia_sts,
|
---|
233 | };
|
---|
234 |
|
---|
235 | static int
|
---|
236 | generic_ocp_read(struct rtl_softc *sc, uint16_t index, uint16_t addr, void *buf, int len)
|
---|
237 | {
|
---|
238 | struct usb_device_request req;
|
---|
239 | // TODO: This seems to be a global defined variable
|
---|
240 | uint16_t limit = 64;
|
---|
241 | int ret = 0;
|
---|
242 |
|
---|
243 | /* both size and indix must be 4 bytes align */
|
---|
244 | // TODO: Argue whether are supposed to be non-fatal values
|
---|
245 | if ((len & 3) || !len || (index & 3) || (!buf)) {
|
---|
246 | printf("[foo] generic_ocp_read(len=%x index=%x): not alligned error\n",
|
---|
247 | len, index);
|
---|
248 | return (ENXIO);
|
---|
249 | }
|
---|
250 |
|
---|
251 | if ((uint32_t)index + (uint32_t)addr > 0xffff) {
|
---|
252 | printf("[foo] generic_ocp_read(index=%x addr=%x): overflow error\n",
|
---|
253 | len, index);
|
---|
254 | return (ENXIO);
|
---|
255 | }
|
---|
256 |
|
---|
257 | //TODO: Deal with the fact if len > limit (block fetching)
|
---|
258 | if (len > limit) {
|
---|
259 | printf("[foo] generic_ocp_read(len=%x limit=%x): size overflow\n",
|
---|
260 | len, limit);
|
---|
261 | return (ENXIO);
|
---|
262 | }
|
---|
263 |
|
---|
264 | req.bmRequestType = UT_READ_VENDOR_DEVICE;
|
---|
265 | req.bRequest = UR_SET_ADDRESS;
|
---|
266 | USETW(req.wIndex, index);
|
---|
267 | USETW(req.wValue, addr);
|
---|
268 | USETW(req.wLength, len);
|
---|
269 |
|
---|
270 | ret = uether_do_request(&sc->sc_ue, &req, buf, 500);
|
---|
271 | return ret;
|
---|
272 | }
|
---|
273 |
|
---|
274 | static int
|
---|
275 | set_registers(struct rtl_softc *sc, uint16_t index, uint16_t addr, void *buf, int len) {
|
---|
276 | struct usb_device_request req;
|
---|
277 |
|
---|
278 | req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
|
---|
279 | req.bRequest = UR_SET_ADDRESS;
|
---|
280 | USETW(req.wIndex, index);
|
---|
281 | USETW(req.wValue, addr);
|
---|
282 | USETW(req.wLength, len);
|
---|
283 |
|
---|
284 | //TODO: Make timeout some kind of define global?
|
---|
285 | return (uether_do_request(&sc->sc_ue, &req, buf, 500));
|
---|
286 | }
|
---|
287 |
|
---|
288 | static int
|
---|
289 | ocp_write(struct rtl_softc *sc, uint16_t index, uint16_t addr,
|
---|
290 | uint16_t byteen, void *buf, int len)
|
---|
291 | {
|
---|
292 | uint16_t byteen_start, byteen_end, byen;
|
---|
293 | uint16_t limit = 512;
|
---|
294 | int ret;
|
---|
295 |
|
---|
296 | /* both size and indix must be 4 bytes align */
|
---|
297 | // TODO: Argue whether are supposed to be non-fatal values
|
---|
298 | if ((len & 3) || !len || (index & 3) || (!buf)) {
|
---|
299 | printf("[foo] ocp_write(len=%x index=%x): not alligned error\n",
|
---|
300 | len, index);
|
---|
301 | return (ENXIO);
|
---|
302 | }
|
---|
303 |
|
---|
304 | if ((uint32_t)index + (uint32_t)addr > 0xffff) {
|
---|
305 | printf("[foo] ocp_write(index=%x addr=%x): overflow error\n",
|
---|
306 | len, index);
|
---|
307 | return (ENXIO);
|
---|
308 | }
|
---|
309 |
|
---|
310 | //TODO: Deal with the fact if len > limit (block fetching)
|
---|
311 | if (len > limit) {
|
---|
312 | printf("[foo] ocp_write(len=%x limit=%x): size overflow\n",
|
---|
313 | len, limit);
|
---|
314 | return (ENXIO);
|
---|
315 | }
|
---|
316 |
|
---|
317 | byteen_start = byteen & BYTE_EN_START_MASK;
|
---|
318 | byteen_end = byteen & BYTE_EN_END_MASK;
|
---|
319 |
|
---|
320 | byen = byteen_start | (byteen_start << 4);
|
---|
321 |
|
---|
322 | ret = set_registers(sc, index, addr | byen , buf, 4);
|
---|
323 | if (ret < 0)
|
---|
324 | return ret;
|
---|
325 |
|
---|
326 | //TODO: Implement if size > limit
|
---|
327 | return ret;
|
---|
328 | }
|
---|
329 |
|
---|
330 | static uint8_t
|
---|
331 | ocp_read_1(struct rtl_softc *sc, uint16_t index, uint16_t addr)
|
---|
332 | {
|
---|
333 | uint32_t data;
|
---|
334 | //TODO: __le32 tmp;
|
---|
335 | uint32_t tmp;
|
---|
336 |
|
---|
337 | generic_ocp_read(sc, index, addr & ~3, &tmp, 4);
|
---|
338 |
|
---|
339 | //TODO: data = __le32_to_cpu(tmp);
|
---|
340 | data = tmp;
|
---|
341 | data >>= ((addr & 3) * 8);
|
---|
342 | data &= 0xff;
|
---|
343 |
|
---|
344 | //printf("[foo] ocp_read_1(index=%x, addr=%x) => 0x%x\n", index, addr, data);
|
---|
345 |
|
---|
346 | return (uint8_t)data;
|
---|
347 | }
|
---|
348 |
|
---|
349 | static uint16_t
|
---|
350 | ocp_read_2(struct rtl_softc *sc, uint16_t index, uint16_t addr)
|
---|
351 | {
|
---|
352 | uint32_t data;
|
---|
353 | //TODO: __le32 tmp;
|
---|
354 | uint32_t tmp;
|
---|
355 |
|
---|
356 | generic_ocp_read(sc, index, addr & ~3, &tmp, 4);
|
---|
357 |
|
---|
358 | //TODO: data = __le32_to_cpu(tmp);
|
---|
359 | data = tmp;
|
---|
360 | data >>= ((addr & 2) * 8);
|
---|
361 | data &= 0xffff;
|
---|
362 |
|
---|
363 | //printf("[foo] ocp_read_2(index=%x, addr=%x) => tmp=%x data=%x\n", index, addr, tmp, data);
|
---|
364 |
|
---|
365 | return (uint16_t)data;
|
---|
366 | }
|
---|
367 |
|
---|
368 | static uint32_t
|
---|
369 | ocp_read_4(struct rtl_softc *sc, uint16_t index, uint16_t addr)
|
---|
370 | {
|
---|
371 | uint32_t data;
|
---|
372 | //TODO: __le32 tmp;
|
---|
373 | uint32_t tmp;
|
---|
374 |
|
---|
375 | generic_ocp_read(sc, index, addr, &tmp, 4);
|
---|
376 |
|
---|
377 | //TODO: data = __le32_to_cpu(tmp);
|
---|
378 | data = tmp;
|
---|
379 |
|
---|
380 | return data;
|
---|
381 | }
|
---|
382 |
|
---|
383 | static int
|
---|
384 | ocp_write_1(struct rtl_softc *sc, uint16_t index, uint16_t addr, uint8_t val)
|
---|
385 | {
|
---|
386 | uint32_t mask = 0xff;
|
---|
387 | //TODO: __le32 tmp;
|
---|
388 | uint32_t tmp;
|
---|
389 | uint16_t byten = BYTE_EN_BYTE;
|
---|
390 | uint8_t shift = addr & 3;
|
---|
391 | uint32_t data = val;
|
---|
392 | int ret;
|
---|
393 |
|
---|
394 | data &= mask;
|
---|
395 |
|
---|
396 | //printf("[foo] ocp_write_1(index=%x, addr=%x, val=%x)\n", index, addr, val);
|
---|
397 |
|
---|
398 | if (index & 3) {
|
---|
399 | byten <<= shift;
|
---|
400 | mask <<= (shift * 8);
|
---|
401 | data <<= (shift * 8);
|
---|
402 | addr &= ~3;
|
---|
403 | }
|
---|
404 |
|
---|
405 | ret = generic_ocp_read(sc, index, addr, &tmp, 4);
|
---|
406 | if (ret < 0)
|
---|
407 | return ret;
|
---|
408 |
|
---|
409 | //TODO: data |= __le32_to_cpu(tmp) & ~mask;
|
---|
410 | data |= tmp & ~mask;
|
---|
411 | //TODO: tmp = __cpu_to_le32(data);
|
---|
412 | tmp = data;
|
---|
413 |
|
---|
414 | return (ocp_write(sc, index, addr, byten, &tmp, 4));
|
---|
415 | }
|
---|
416 |
|
---|
417 | static int
|
---|
418 | ocp_write_2(struct rtl_softc *sc, uint16_t index, uint16_t addr, uint16_t val)
|
---|
419 | {
|
---|
420 | uint32_t mask = 0xffff;
|
---|
421 | //TODO: __le32 tmp;
|
---|
422 | uint32_t tmp;
|
---|
423 | uint16_t byten = BYTE_EN_WORD;
|
---|
424 | uint8_t shift = addr & 2;
|
---|
425 | uint32_t data = val;
|
---|
426 | int ret;
|
---|
427 |
|
---|
428 | printf("[foo] ocp_write_2(index=%x, addr=%x, val=%x)\n", index, addr, val);
|
---|
429 |
|
---|
430 | data &= mask;
|
---|
431 |
|
---|
432 | if (index & 2) {
|
---|
433 | byten <<= shift;
|
---|
434 | mask <<= (shift * 8);
|
---|
435 | data <<= (shift * 8);
|
---|
436 | addr &= ~3;
|
---|
437 | }
|
---|
438 |
|
---|
439 | ret = generic_ocp_read(sc, index, addr, &tmp, 4);
|
---|
440 | if (ret < 0)
|
---|
441 | return ret;
|
---|
442 |
|
---|
443 |
|
---|
444 | //TODO: data |= __le32_to_cpu(tmp) & ~mask;
|
---|
445 | data |= tmp & ~mask;
|
---|
446 | //TODO: tmp = __cpu_to_le32(data);
|
---|
447 | tmp = data;
|
---|
448 |
|
---|
449 | return (ocp_write(sc, index, addr, byten, &tmp, 4));
|
---|
450 | }
|
---|
451 |
|
---|
452 |
|
---|
453 | static int
|
---|
454 | ocp_write_4(struct rtl_softc *sc, uint16_t index, uint16_t addr, uint32_t val)
|
---|
455 | {
|
---|
456 | //TODO: __le32 tmp;
|
---|
457 | uint32_t tmp;
|
---|
458 |
|
---|
459 | //TODO: tmp = __le32_to_cpu(data);
|
---|
460 | tmp = val;
|
---|
461 |
|
---|
462 | //printf("[foo] ocp_write_4(index=%x, addr=%x, val=%x)\n", index, addr, tmp);
|
---|
463 | return (ocp_write(sc, index, addr, BYTE_EN_DWORD, &tmp, 4));
|
---|
464 | }
|
---|
465 |
|
---|
466 | static uint16_t
|
---|
467 | ocp_reg_read(struct rtl_softc *sc, uint16_t addr)
|
---|
468 | {
|
---|
469 | uint16_t ocp_base = addr & 0xf000;
|
---|
470 | uint16_t ocp_index = (addr & 0x0fff) | 0xb000;
|
---|
471 |
|
---|
472 | if (ocp_base != sc->ocp_base) {
|
---|
473 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
|
---|
474 | sc->ocp_base = ocp_base;
|
---|
475 | }
|
---|
476 |
|
---|
477 | return ocp_read_2(sc, MCU_TYPE_PLA, ocp_index);
|
---|
478 | }
|
---|
479 |
|
---|
480 | static void
|
---|
481 | ocp_reg_write(struct rtl_softc *sc, uint16_t addr, uint16_t val)
|
---|
482 | {
|
---|
483 | uint16_t ocp_base = addr & 0xf000;
|
---|
484 | uint16_t ocp_index = (addr & 0x0fff) | 0xb000;
|
---|
485 |
|
---|
486 | if (ocp_base != sc->ocp_base) {
|
---|
487 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
|
---|
488 | sc->ocp_base = ocp_base;
|
---|
489 | }
|
---|
490 |
|
---|
491 | ocp_write_2(sc, MCU_TYPE_PLA, ocp_index, val);
|
---|
492 | }
|
---|
493 |
|
---|
494 | static inline void
|
---|
495 | r8152_mdio_write(struct rtl_softc *sc, uint32_t addr, uint32_t val)
|
---|
496 | {
|
---|
497 | ocp_reg_write(sc, OCP_BASE_MII + addr * 2, val);
|
---|
498 | }
|
---|
499 |
|
---|
500 | static inline uint32_t
|
---|
501 | r8152_mdio_read(struct rtl_softc *sc, uint32_t addr)
|
---|
502 | {
|
---|
503 | return ocp_reg_read(sc, OCP_BASE_MII + addr * 2);
|
---|
504 | }
|
---|
505 |
|
---|
506 | static int
|
---|
507 | rtl_miibus_readreg(device_t dev, int phy, int reg)
|
---|
508 | {
|
---|
509 | //printf("[foo] rtl_miibus_readreg(phy=%x, reg=%x)\n", phy, reg);
|
---|
510 | struct rtl_softc *sc = device_get_softc(dev);
|
---|
511 | uint16_t rval;
|
---|
512 | int locked;
|
---|
513 |
|
---|
514 | if (phy != 0) /* RTL8152 supports PHY == 0, only */
|
---|
515 | return (0);
|
---|
516 |
|
---|
517 | locked = mtx_owned(&sc->sc_mtx);
|
---|
518 | if (!locked)
|
---|
519 | RTL_LOCK(sc);
|
---|
520 |
|
---|
521 | rval = r8152_mdio_read(sc, reg);
|
---|
522 |
|
---|
523 | if (!locked)
|
---|
524 | RTL_UNLOCK(sc);
|
---|
525 | //printf("[foo] rtl_miibus_readreg(phy=%x, reg=%x) => rval=%x\n", phy, reg, rval);
|
---|
526 | return (rval);
|
---|
527 | }
|
---|
528 |
|
---|
529 | static int
|
---|
530 | rtl_miibus_writereg(device_t dev, int phy, int reg, int data)
|
---|
531 | {
|
---|
532 | printf("[foo] rtl_miibus_writereg(phy=%x reg=%x data=%x\n", phy, reg, data);
|
---|
533 | return (0);
|
---|
534 | struct rtl_softc *sc = device_get_softc(dev);
|
---|
535 | int locked;
|
---|
536 |
|
---|
537 | if (phy != 0) /* RTL8152 supports PHY == 0, only */
|
---|
538 | return (0);
|
---|
539 |
|
---|
540 | locked = mtx_owned(&sc->sc_mtx);
|
---|
541 | if (!locked)
|
---|
542 | RTL_LOCK(sc);
|
---|
543 |
|
---|
544 | r8152_mdio_write(sc, reg, data);
|
---|
545 |
|
---|
546 | if (!locked)
|
---|
547 | RTL_UNLOCK(sc);
|
---|
548 | return (0);
|
---|
549 | }
|
---|
550 |
|
---|
551 | static void
|
---|
552 | rtl_miibus_statchg(device_t dev)
|
---|
553 | {
|
---|
554 | printf("[foo] %s\n", __func__);
|
---|
555 | #if 0
|
---|
556 | struct rtl_softc *sc = device_get_softc(dev);
|
---|
557 | struct mii_data *mii = GET_MII(sc);
|
---|
558 | uint16_t bmcr;
|
---|
559 | int locked;
|
---|
560 |
|
---|
561 | locked = mtx_owned(&sc->sc_mtx);
|
---|
562 | if (!locked)
|
---|
563 | RTL_LOCK(sc);
|
---|
564 |
|
---|
565 | RTL_CLRBIT(sc, RTL_CR, (RTL_CR_RE | RTL_CR_TE));
|
---|
566 |
|
---|
567 | bmcr = rtl_csr_read_2(sc, RTL_BMCR);
|
---|
568 |
|
---|
569 | if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX)
|
---|
570 | bmcr |= RTL_BMCR_SPD_SET;
|
---|
571 | else
|
---|
572 | bmcr &= ~RTL_BMCR_SPD_SET;
|
---|
573 |
|
---|
574 | if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
|
---|
575 | bmcr |= RTL_BMCR_DUPLEX;
|
---|
576 | else
|
---|
577 | bmcr &= ~RTL_BMCR_DUPLEX;
|
---|
578 |
|
---|
579 | rtl_csr_write_2(sc, RTL_BMCR, bmcr);
|
---|
580 |
|
---|
581 | RTL_SETBIT(sc, RTL_CR, (RTL_CR_RE | RTL_CR_TE));
|
---|
582 |
|
---|
583 | if (!locked)
|
---|
584 | RTL_UNLOCK(sc);
|
---|
585 | #endif
|
---|
586 | }
|
---|
587 |
|
---|
588 | //TODO: Make global defines
|
---|
589 | static const int multicast_filter_limit = 32;
|
---|
590 | //static const unsigned int agg_buf_sz = 16384;
|
---|
591 |
|
---|
592 |
|
---|
593 | /*
|
---|
594 | * Program the 64-bit multicast hash filter and promiscuous mode
|
---|
595 | */
|
---|
596 | static void
|
---|
597 | rtl_setpromisc_and_multi(struct usb_ether *ue)
|
---|
598 | {
|
---|
599 | printf("[foo] %s\n", __func__);
|
---|
600 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
601 | struct ifnet *ifp = uether_getifp(ue);
|
---|
602 | int h = 0;
|
---|
603 | uint32_t hashes[2] = { 0, 0 };
|
---|
604 | uint32_t tmp[2];
|
---|
605 | uint32_t ocp_data;
|
---|
606 | struct ifmultiaddr *ifma;
|
---|
607 | int mcnt = 0;
|
---|
608 |
|
---|
609 | RTL_LOCK_ASSERT(sc, MA_OWNED);
|
---|
610 |
|
---|
611 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_RCR);
|
---|
612 | ocp_data &= ~RCR_ACPT_ALL;
|
---|
613 | ocp_data |= RCR_AB | RCR_APM;
|
---|
614 |
|
---|
615 |
|
---|
616 | /* Make multicast filter */
|
---|
617 | if_maddr_rlock(ifp);
|
---|
618 | TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link)
|
---|
619 | {
|
---|
620 | if (ifma->ifma_addr->sa_family != AF_LINK)
|
---|
621 | continue;
|
---|
622 | h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
|
---|
623 | ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
|
---|
624 |
|
---|
625 | hashes[h >> 5] |= 1 << (h & 31);
|
---|
626 | mcnt++;
|
---|
627 | }
|
---|
628 | if_maddr_runlock(ifp);
|
---|
629 |
|
---|
630 |
|
---|
631 | if (ifp->if_flags & IFF_PROMISC) {
|
---|
632 | ocp_data |= RCR_AM | RCR_AAP;
|
---|
633 | hashes[0] = 0xffffffff;
|
---|
634 | hashes[1] = 0xffffffff;
|
---|
635 | } else if ((mcnt > multicast_filter_limit) ||
|
---|
636 | (ifp->if_flags & IFF_ALLMULTI)) {
|
---|
637 | /* Too many to filter perfectly -- accept all multicasts. */
|
---|
638 | ocp_data |= RCR_AM;
|
---|
639 | hashes[0] = 0xffffffff;
|
---|
640 | hashes[1] = 0xffffffff;
|
---|
641 | } else if (mcnt > 0) {
|
---|
642 | ocp_data |= RCR_AM;
|
---|
643 | }
|
---|
644 |
|
---|
645 | //TODO: tmp[0] = __cpu_to_le32(swab32(mc_filter[1]));
|
---|
646 | //TODO: tmp[1] = __cpu_to_le32(swab32(mc_filter[0]));
|
---|
647 | tmp[0] = hashes[0];
|
---|
648 | tmp[1] = hashes[1];
|
---|
649 |
|
---|
650 | ocp_write(sc, MCU_TYPE_PLA, PLA_MAR, BYTE_EN_DWORD, tmp, sizeof(tmp));
|
---|
651 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RCR, ocp_data);
|
---|
652 | }
|
---|
653 |
|
---|
654 | static void
|
---|
655 | rtl_reset(struct rtl_softc *sc)
|
---|
656 | {
|
---|
657 | printf("[foo] %s\n", __func__);
|
---|
658 | int i;
|
---|
659 |
|
---|
660 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CR, CR_RST);
|
---|
661 |
|
---|
662 | for (i = 0; i != RTL_TIMEOUT; i++) {
|
---|
663 | if (uether_pause(&sc->sc_ue, hz / 1000))
|
---|
664 | break;
|
---|
665 | if (!(ocp_read_1(sc, MCU_TYPE_PLA, PLA_CR) & CR_RST))
|
---|
666 | break;
|
---|
667 | }
|
---|
668 |
|
---|
669 | if (i == RTL_TIMEOUT)
|
---|
670 | device_printf(sc->sc_ue.ue_dev, "reset never completed\n");
|
---|
671 |
|
---|
672 | uether_pause(&sc->sc_ue, hz / 100);
|
---|
673 | }
|
---|
674 |
|
---|
675 | static void
|
---|
676 | rtl_attach_post(struct usb_ether *ue)
|
---|
677 | {
|
---|
678 | printf("[foo] %s\n", __func__);
|
---|
679 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
680 | int ret;
|
---|
681 |
|
---|
682 | /* reset the adapter */
|
---|
683 | rtl_reset(sc);
|
---|
684 |
|
---|
685 | uint32_t ocp_data;
|
---|
686 | uint16_t version;
|
---|
687 |
|
---|
688 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_TCR1);
|
---|
689 | version = (uint16_t)(ocp_data & VERSION_MASK);
|
---|
690 | switch (version) {
|
---|
691 | case 0x4c00:
|
---|
692 | sc->version = RTL_VER_01;
|
---|
693 | break;
|
---|
694 | case 0x4c10:
|
---|
695 | sc->version = RTL_VER_02;
|
---|
696 | break;
|
---|
697 | case 0x5c00:
|
---|
698 | sc->version = RTL_VER_03;
|
---|
699 | break;
|
---|
700 | case 0x5c10:
|
---|
701 | sc->version = RTL_VER_04;
|
---|
702 | break;
|
---|
703 | case 0x5c20:
|
---|
704 | sc->version = RTL_VER_05;
|
---|
705 | break;
|
---|
706 | default:
|
---|
707 | printf("[foo] Unknown version 0x%04x\n", version);
|
---|
708 | break;
|
---|
709 | }
|
---|
710 | printf("[foo] ocp_data=%x version=%x\n", ocp_data, version);
|
---|
711 |
|
---|
712 | /* Get station address from the EEPROM which needs to be aligned */
|
---|
713 | //TODO: Allign automatically(?)
|
---|
714 | if (sc->version == RTL_VER_01)
|
---|
715 | ret = generic_ocp_read(sc, MCU_TYPE_PLA, PLA_IDR, ue->ue_eaddr, 8);
|
---|
716 | else
|
---|
717 | ret = generic_ocp_read(sc, MCU_TYPE_PLA, PLA_BACKUP,ue->ue_eaddr, 8);
|
---|
718 |
|
---|
719 | printf("[foo] attach_post: Read MAC address (version=%x ret=%x mac=%s\n", sc->version, ret, ue->ue_eaddr);
|
---|
720 |
|
---|
721 | if (ret < 0) {
|
---|
722 | //TODO: How-to handle failures and/or invalid MAC addresses
|
---|
723 | printf("[foo] attach_post: Get ether addr fail\n");
|
---|
724 | //TODO: should we make a random MAC address?
|
---|
725 | // } else if (!is_valid_ether_addr(ue->ue_eaddr)) {
|
---|
726 | // TODO: If no MAC is returned the device is crashed and needs to be
|
---|
727 | // power-cycled, how-to inform user?
|
---|
728 | } else {
|
---|
729 | /* Later versions needs to have the MAC copied to the working location */
|
---|
730 | if (sc->version != RTL_VER_01) {
|
---|
731 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
|
---|
732 | ocp_write(sc, MCU_TYPE_PLA, PLA_IDR, BYTE_EN_SIX_BYTES,
|
---|
733 | ue->ue_eaddr, 8);
|
---|
734 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
|
---|
735 | }
|
---|
736 | }
|
---|
737 | }
|
---|
738 |
|
---|
739 | /*
|
---|
740 | * Probe for a RTL8150 chip.
|
---|
741 | */
|
---|
742 | static int
|
---|
743 | rtl_probe(device_t dev)
|
---|
744 | {
|
---|
745 | printf("[foo] %s\n", __func__);
|
---|
746 | struct usb_attach_arg *uaa = device_get_ivars(dev);
|
---|
747 |
|
---|
748 | if (uaa->usb_mode != USB_MODE_HOST)
|
---|
749 | return (ENXIO);
|
---|
750 | if (uaa->info.bConfigIndex != RTL_CONFIG_IDX)
|
---|
751 | return (ENXIO);
|
---|
752 | if (uaa->info.bIfaceIndex != RTL_IFACE_IDX)
|
---|
753 | return (ENXIO);
|
---|
754 |
|
---|
755 | return (usbd_lookup_id_by_uaa(rtl_devs, sizeof(rtl_devs), uaa));
|
---|
756 | }
|
---|
757 |
|
---|
758 | /*
|
---|
759 | * Attach the interface. Allocate softc structures, do ifmedia
|
---|
760 | * setup and ethernet/BPF attach.
|
---|
761 | */
|
---|
762 | static int
|
---|
763 | rtl_attach(device_t dev)
|
---|
764 | {
|
---|
765 | printf("[foo] %s\n", __func__);
|
---|
766 | struct usb_attach_arg *uaa = device_get_ivars(dev);
|
---|
767 | struct rtl_softc *sc = device_get_softc(dev);
|
---|
768 | struct usb_ether *ue = &sc->sc_ue;
|
---|
769 | uint8_t iface_index;
|
---|
770 | int error;
|
---|
771 |
|
---|
772 | device_set_usb_desc(dev);
|
---|
773 | mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
|
---|
774 |
|
---|
775 | iface_index = RTL_IFACE_IDX;
|
---|
776 | error = usbd_transfer_setup(uaa->device, &iface_index,
|
---|
777 | sc->sc_xfer, rtl_config, RTL_N_TRANSFER,
|
---|
778 | sc, &sc->sc_mtx);
|
---|
779 | if (error) {
|
---|
780 | device_printf(dev, "allocating USB transfers failed\n");
|
---|
781 | goto detach;
|
---|
782 | }
|
---|
783 |
|
---|
784 | ue->ue_sc = sc;
|
---|
785 | ue->ue_dev = dev;
|
---|
786 | ue->ue_udev = uaa->device;
|
---|
787 | ue->ue_mtx = &sc->sc_mtx;
|
---|
788 | ue->ue_methods = &rtl_ue_methods;
|
---|
789 |
|
---|
790 | error = uether_ifattach(ue);
|
---|
791 | if (error) {
|
---|
792 | device_printf(dev, "could not attach interface\n");
|
---|
793 | goto detach;
|
---|
794 | }
|
---|
795 | return (0); /* success */
|
---|
796 |
|
---|
797 | detach:
|
---|
798 | rtl_detach(dev);
|
---|
799 | return (ENXIO); /* failure */
|
---|
800 | }
|
---|
801 |
|
---|
802 | static int
|
---|
803 | rtl_detach(device_t dev)
|
---|
804 | {
|
---|
805 | printf("[foo] %s\n", __func__);
|
---|
806 | struct rtl_softc *sc = device_get_softc(dev);
|
---|
807 | struct usb_ether *ue = &sc->sc_ue;
|
---|
808 |
|
---|
809 | usbd_transfer_unsetup(sc->sc_xfer, RTL_N_TRANSFER);
|
---|
810 | uether_ifdetach(ue);
|
---|
811 | mtx_destroy(&sc->sc_mtx);
|
---|
812 |
|
---|
813 | return (0);
|
---|
814 | }
|
---|
815 |
|
---|
816 | static void
|
---|
817 | rtl_intr_callback(struct usb_xfer *xfer, usb_error_t error)
|
---|
818 | {
|
---|
819 | //struct rtl_softc *sc = usbd_xfer_softc(xfer);
|
---|
820 | //struct ifnet *ifp = uether_getifp(&sc->sc_ue);
|
---|
821 | //struct rtl_intrpkt pkt;
|
---|
822 | uint32_t pkt;
|
---|
823 | struct usb_page_cache *pc;
|
---|
824 | int actlen;
|
---|
825 |
|
---|
826 | usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
|
---|
827 |
|
---|
828 | //printf("[foo] rtl_intr_callback USB_STATE=%i\n", USB_GET_STATE(xfer));
|
---|
829 | switch (USB_GET_STATE(xfer)) {
|
---|
830 | case USB_ST_TRANSFERRED:
|
---|
831 |
|
---|
832 | //if (ifp && (ifp->if_drv_flags & IFF_DRV_RUNNING) &&
|
---|
833 | // actlen >= (int)sizeof(pkt)) {
|
---|
834 | //if (ifp && (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
---|
835 |
|
---|
836 | pc = usbd_xfer_get_frame(xfer, 0);
|
---|
837 | usbd_copy_out(pc, 0, &pkt, sizeof(pkt));
|
---|
838 | //printf("[foo] rtl_intr_callback pkt=%x actlen=%i\n", pkt, actlen);
|
---|
839 |
|
---|
840 | //ifp->if_ierrors += pkt.rtl_rxlost_cnt;
|
---|
841 | //ifp->if_ierrors += pkt.rtl_crcerr_cnt;
|
---|
842 | //ifp->if_collisions += pkt.rtl_col_cnt;
|
---|
843 | //}
|
---|
844 | /* FALLTHROUGH */
|
---|
845 | case USB_ST_SETUP:
|
---|
846 | tr_setup:
|
---|
847 | usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
|
---|
848 | usbd_transfer_submit(xfer);
|
---|
849 | return;
|
---|
850 |
|
---|
851 | default:
|
---|
852 | if (error != USB_ERR_CANCELLED) {
|
---|
853 | usbd_xfer_set_stall(xfer);
|
---|
854 | goto tr_setup;
|
---|
855 | }
|
---|
856 | return;
|
---|
857 | }
|
---|
858 | }
|
---|
859 |
|
---|
860 | static void
|
---|
861 | rtl_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
---|
862 | {
|
---|
863 | struct rtl_softc *sc = usbd_xfer_softc(xfer);
|
---|
864 | struct usb_ether *ue = &sc->sc_ue;
|
---|
865 | //struct ifnet *ifp = uether_getifp(ue);
|
---|
866 | struct usb_page_cache *pc;
|
---|
867 | struct rx_desc rx_desc;
|
---|
868 | //uint16_t status;
|
---|
869 | int actlen;
|
---|
870 | int pos = 0;
|
---|
871 | unsigned int pkt_len;
|
---|
872 |
|
---|
873 | usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
|
---|
874 |
|
---|
875 | printf("[foo] rtl_bulk_read_callback USB_STATE=%i actlen=%d\n", USB_GET_STATE(xfer), actlen);
|
---|
876 | switch (USB_GET_STATE(xfer)) {
|
---|
877 | case USB_ST_TRANSFERRED:
|
---|
878 | pc = usbd_xfer_get_frame(xfer, 0);
|
---|
879 |
|
---|
880 | while (actlen > pos) {
|
---|
881 | usbd_copy_out(pc, pos, &rx_desc, sizeof(rx_desc));
|
---|
882 | pos += (sizeof rx_desc);
|
---|
883 |
|
---|
884 | pkt_len = rx_desc.opts1 & RX_LEN_MASK;
|
---|
885 | printf("[foo] pkt_len=%d\n", pkt_len);
|
---|
886 |
|
---|
887 | //ETH_ZLEN (Min. octents in frame sans FCS)
|
---|
888 | if (pkt_len < 60)
|
---|
889 | break;
|
---|
890 |
|
---|
891 | // TODO: Should we flag this as errors
|
---|
892 | if (actlen < (pos + pkt_len))
|
---|
893 | break;
|
---|
894 |
|
---|
895 | // TODO: Chipset supports CRC and VLAN tagging
|
---|
896 | uether_rxbuf(ue, pc, pos, pkt_len - CRC_SIZE);
|
---|
897 |
|
---|
898 | pos += pkt_len;
|
---|
899 | //TODO: Data get aligned?
|
---|
900 | }
|
---|
901 | /* FALLTHROUGH */
|
---|
902 | case USB_ST_SETUP:
|
---|
903 | tr_setup:
|
---|
904 | usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
|
---|
905 | usbd_transfer_submit(xfer);
|
---|
906 | uether_rxflush(ue);
|
---|
907 | return;
|
---|
908 |
|
---|
909 | default: /* Error */
|
---|
910 | printf("[foo] bulk read error, %s\n",
|
---|
911 | usbd_errstr(error));
|
---|
912 |
|
---|
913 | if (error != USB_ERR_CANCELLED) {
|
---|
914 | /* try to clear stall first */
|
---|
915 | usbd_xfer_set_stall(xfer);
|
---|
916 | goto tr_setup;
|
---|
917 | }
|
---|
918 | return;
|
---|
919 | }
|
---|
920 | }
|
---|
921 |
|
---|
922 | static void
|
---|
923 | rtl_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
---|
924 | {
|
---|
925 | struct rtl_softc *sc = usbd_xfer_softc(xfer);
|
---|
926 | struct ifnet *ifp = uether_getifp(&sc->sc_ue);
|
---|
927 | struct usb_page_cache *pc;
|
---|
928 | struct mbuf *m;
|
---|
929 | int pos;
|
---|
930 | struct tx_desc tx_desc;
|
---|
931 |
|
---|
932 | printf("[foo] rtl_bulk_write_callback USB_STATE=%i\n", USB_GET_STATE(xfer));
|
---|
933 | switch (USB_GET_STATE(xfer)) {
|
---|
934 | case USB_ST_TRANSFERRED:
|
---|
935 | printf("[foo] rtl_bulk_write_callback: transfer complete\n");
|
---|
936 | DPRINTFN(11, "transfer complete\n");
|
---|
937 | ifp->if_opackets++;
|
---|
938 |
|
---|
939 | /* FALLTHROUGH */
|
---|
940 | case USB_ST_SETUP:
|
---|
941 | tr_setup:
|
---|
942 | //if ((sc->sc_flags & RTL_FLAG_LINK) == 0) {
|
---|
943 | // printf("[foo] rtl_bulk_write_callback: error no link!\n");
|
---|
944 | // /*
|
---|
945 | // * don't send anything if there is no link !
|
---|
946 | // */
|
---|
947 | // return;
|
---|
948 | //}
|
---|
949 | IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
---|
950 | if (m == NULL)
|
---|
951 | return;
|
---|
952 |
|
---|
953 | //if (m->m_pkthdr.len > MCLBYTES)
|
---|
954 | // m->m_pkthdr.len = MCLBYTES;
|
---|
955 | //temp_len = m->m_pkthdr.len;
|
---|
956 |
|
---|
957 | pos = 0;
|
---|
958 | pc = usbd_xfer_get_frame(xfer, 0);
|
---|
959 |
|
---|
960 | // Header description
|
---|
961 | // //TODO: Complete CRC
|
---|
962 | int transport_offset = 0;
|
---|
963 | tx_desc.opts1 = m->m_pkthdr.len | TX_FS | TX_LS;
|
---|
964 | tx_desc.opts1 |= transport_offset << GTTCPHO_SHIFT;
|
---|
965 | tx_desc.opts1 |= GTSENDV4;
|
---|
966 |
|
---|
967 | usbd_copy_in(pc, pos, &tx_desc, sizeof(tx_desc));
|
---|
968 | pos += sizeof(tx_desc);
|
---|
969 |
|
---|
970 | // Content
|
---|
971 | usbd_m_copy_in(pc, pos, m, 0, m->m_pkthdr.len);
|
---|
972 | pos += m->m_pkthdr.len;
|
---|
973 |
|
---|
974 |
|
---|
975 | printf("[foo] rtl_bulk_write_callback len=%i\n", m->m_pkthdr.len);
|
---|
976 | int i;
|
---|
977 | for (i = 0; i < m->m_pkthdr.len; i++)
|
---|
978 | printf("%x", m->m_data[i]);
|
---|
979 | printf("\n");
|
---|
980 |
|
---|
981 | usbd_xfer_set_frame_len(xfer, 0, pos);
|
---|
982 |
|
---|
983 | /*
|
---|
984 | * if there's a BPF listener, bounce a copy
|
---|
985 | * of this frame to him:
|
---|
986 | */
|
---|
987 | BPF_MTAP(ifp, m);
|
---|
988 |
|
---|
989 | m_freem(m);
|
---|
990 |
|
---|
991 | usbd_transfer_submit(xfer);
|
---|
992 |
|
---|
993 | return;
|
---|
994 |
|
---|
995 | default: /* Error */
|
---|
996 | printf("[foo] bulk write: transfer error, %s\n", usbd_errstr(error));
|
---|
997 | ifp->if_oerrors++;
|
---|
998 |
|
---|
999 | if (error != USB_ERR_CANCELLED) {
|
---|
1000 | /* try to clear stall first */
|
---|
1001 | usbd_xfer_set_stall(xfer);
|
---|
1002 | goto tr_setup;
|
---|
1003 | }
|
---|
1004 | return;
|
---|
1005 | }
|
---|
1006 | }
|
---|
1007 |
|
---|
1008 | static void
|
---|
1009 | rtl_tick(struct usb_ether *ue)
|
---|
1010 | {
|
---|
1011 | printf("[foo] %s\n", __func__);
|
---|
1012 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
1013 | struct mii_data *mii = GET_MII(sc);
|
---|
1014 |
|
---|
1015 | RTL_LOCK_ASSERT(sc, MA_OWNED);
|
---|
1016 |
|
---|
1017 | mii_tick(mii);
|
---|
1018 | if ((sc->sc_flags & RTL_FLAG_LINK) == 0
|
---|
1019 | && mii->mii_media_status & IFM_ACTIVE &&
|
---|
1020 | IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
|
---|
1021 | sc->sc_flags |= RTL_FLAG_LINK;
|
---|
1022 | rtl_start(ue);
|
---|
1023 | }
|
---|
1024 | }
|
---|
1025 |
|
---|
1026 | static void
|
---|
1027 | rtl8152_set_mac_address(struct usb_ether *ue)
|
---|
1028 | {
|
---|
1029 | printf("[foo] %s\n", __func__);
|
---|
1030 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
1031 |
|
---|
1032 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
|
---|
1033 | ocp_write(sc, MCU_TYPE_PLA, PLA_IDR, BYTE_EN_SIX_BYTES, ue->ue_eaddr, 8);
|
---|
1034 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
|
---|
1035 | }
|
---|
1036 |
|
---|
1037 | static void
|
---|
1038 | r8152b_reset_packet_filter(struct rtl_softc *sc)
|
---|
1039 | {
|
---|
1040 | printf("[foo] %s\n", __func__);
|
---|
1041 | uint32_t ocp_data;
|
---|
1042 |
|
---|
1043 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_FMC);
|
---|
1044 | ocp_data &= ~FMC_FCR_MCU_EN;
|
---|
1045 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_FMC, ocp_data);
|
---|
1046 | ocp_data |= FMC_FCR_MCU_EN;
|
---|
1047 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_FMC, ocp_data);
|
---|
1048 | }
|
---|
1049 |
|
---|
1050 | static void
|
---|
1051 | rtl8152_nic_reset(struct rtl_softc *sc)
|
---|
1052 | {
|
---|
1053 | printf("[foo] %s\n", __func__);
|
---|
1054 | int i;
|
---|
1055 |
|
---|
1056 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CR, CR_RST);
|
---|
1057 |
|
---|
1058 | for (i = 0; i < 1000; i++) {
|
---|
1059 | if (!(ocp_read_1(sc, MCU_TYPE_PLA, PLA_CR) & CR_RST))
|
---|
1060 | break;
|
---|
1061 | uether_pause(&sc->sc_ue, hz / 100);
|
---|
1062 | }
|
---|
1063 | }
|
---|
1064 |
|
---|
1065 | static inline uint8_t
|
---|
1066 | rtl8152_get_speed(struct rtl_softc* sc)
|
---|
1067 | {
|
---|
1068 | printf("[foo] %s\n", __func__);
|
---|
1069 | return ocp_read_1(sc, MCU_TYPE_PLA, PLA_PHYSTATUS);
|
---|
1070 | }
|
---|
1071 |
|
---|
1072 | static void
|
---|
1073 | rtl_set_eee_plus(struct rtl_softc *sc)
|
---|
1074 | {
|
---|
1075 | printf("[foo] %s\n", __func__);
|
---|
1076 | uint32_t ocp_data;
|
---|
1077 | uint8_t speed;
|
---|
1078 |
|
---|
1079 | speed = rtl8152_get_speed(sc);
|
---|
1080 | //TODO: Find out which bits represent which speed
|
---|
1081 | //if (speed & _10bps) {
|
---|
1082 | // ocp_data = ocp_read_2(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
|
---|
1083 | // ocp_data |= EEEP_CR_EEEP_TX;
|
---|
1084 | // ocp_write_2(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
|
---|
1085 | //} else {
|
---|
1086 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_EEEP_CR);
|
---|
1087 | ocp_data &= ~EEEP_CR_EEEP_TX;
|
---|
1088 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
|
---|
1089 | //}
|
---|
1090 | }
|
---|
1091 |
|
---|
1092 | static void
|
---|
1093 | rxdy_gated_en(struct rtl_softc *sc, bool enable)
|
---|
1094 | {
|
---|
1095 | printf("[foo] %s\n", __func__);
|
---|
1096 | uint32_t ocp_data;
|
---|
1097 |
|
---|
1098 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_MISC_1);
|
---|
1099 | if (enable)
|
---|
1100 | ocp_data |= RXDY_GATED_EN;
|
---|
1101 | else
|
---|
1102 | ocp_data &= ~RXDY_GATED_EN;
|
---|
1103 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
|
---|
1104 | }
|
---|
1105 |
|
---|
1106 | static int
|
---|
1107 | rtl_enable(struct rtl_softc *sc)
|
---|
1108 | {
|
---|
1109 | printf("[foo] %s\n", __func__);
|
---|
1110 | uint32_t ocp_data;
|
---|
1111 |
|
---|
1112 | r8152b_reset_packet_filter(sc);
|
---|
1113 |
|
---|
1114 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_CR);
|
---|
1115 | ocp_data |= CR_RE | CR_TE;
|
---|
1116 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CR, ocp_data);
|
---|
1117 |
|
---|
1118 | rxdy_gated_en(sc, false);
|
---|
1119 |
|
---|
1120 | return 0;
|
---|
1121 | }
|
---|
1122 |
|
---|
1123 |
|
---|
1124 | static int
|
---|
1125 | rtl8152_enable(struct rtl_softc *sc)
|
---|
1126 | {
|
---|
1127 | printf("[foo] %s\n", __func__);
|
---|
1128 | //set_tx_qlen(sc);
|
---|
1129 | rtl_set_eee_plus(sc);
|
---|
1130 |
|
---|
1131 | return rtl_enable(sc);
|
---|
1132 | }
|
---|
1133 |
|
---|
1134 | static void
|
---|
1135 | rtl_disable(struct rtl_softc *sc)
|
---|
1136 | {
|
---|
1137 | printf("[foo] %s\n", __func__);
|
---|
1138 | uint32_t ocp_data;
|
---|
1139 | int i;
|
---|
1140 |
|
---|
1141 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_RCR);
|
---|
1142 | ocp_data &= ~RCR_ACPT_ALL;
|
---|
1143 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RCR, ocp_data);
|
---|
1144 |
|
---|
1145 | rxdy_gated_en(sc, true);
|
---|
1146 |
|
---|
1147 | for (i = 0; i < 1000; i++) {
|
---|
1148 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
1149 | if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
|
---|
1150 | break;
|
---|
1151 | uether_pause(&sc->sc_ue, hz / 100);
|
---|
1152 | }
|
---|
1153 |
|
---|
1154 | for (i = 0; i < 1000; i++) {
|
---|
1155 | if (ocp_read_2(sc, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
|
---|
1156 | break;
|
---|
1157 | uether_pause(&sc->sc_ue, hz / 100);
|
---|
1158 | }
|
---|
1159 |
|
---|
1160 | rtl8152_nic_reset(sc);
|
---|
1161 | }
|
---|
1162 |
|
---|
1163 | static void
|
---|
1164 | r8152_power_cut_en(struct rtl_softc *sc, bool enable)
|
---|
1165 | {
|
---|
1166 | printf("[foo] %s\n", __func__);
|
---|
1167 | uint32_t ocp_data;
|
---|
1168 |
|
---|
1169 | ocp_data = ocp_read_2(sc, MCU_TYPE_USB, USB_UPS_CTRL);
|
---|
1170 | if (enable)
|
---|
1171 | ocp_data |= POWER_CUT;
|
---|
1172 | else
|
---|
1173 | ocp_data &= ~POWER_CUT;
|
---|
1174 | ocp_write_2(sc, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
|
---|
1175 |
|
---|
1176 | ocp_data = ocp_read_2(sc, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
|
---|
1177 | ocp_data &= ~RESUME_INDICATE;
|
---|
1178 | ocp_write_2(sc, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
|
---|
1179 | }
|
---|
1180 |
|
---|
1181 | static void
|
---|
1182 | rtl_rx_vlan_en(struct rtl_softc *sc, bool enable)
|
---|
1183 | {
|
---|
1184 | printf("[foo] %s\n", __func__);
|
---|
1185 | uint32_t ocp_data;
|
---|
1186 |
|
---|
1187 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CPCR);
|
---|
1188 | if (enable)
|
---|
1189 | ocp_data |= CPCR_RX_VLAN;
|
---|
1190 | else
|
---|
1191 | ocp_data &= ~CPCR_RX_VLAN;
|
---|
1192 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
|
---|
1193 | }
|
---|
1194 |
|
---|
1195 | //TODO convert
|
---|
1196 | //#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
|
---|
1197 |
|
---|
1198 | static uint32_t
|
---|
1199 | __rtl_get_wol(struct rtl_softc *sc)
|
---|
1200 | {
|
---|
1201 | printf("[foo] %s\n", __func__);
|
---|
1202 | uint32_t ocp_data;
|
---|
1203 | uint32_t wolopts = 0;
|
---|
1204 |
|
---|
1205 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_CONFIG5);
|
---|
1206 | if (!(ocp_data & LAN_WAKE_EN))
|
---|
1207 | return 0;
|
---|
1208 |
|
---|
1209 | // ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CONFIG34);
|
---|
1210 | // if (ocp_data & LINK_ON_WAKE_EN)
|
---|
1211 | // wolopts |= WAKE_PHY;
|
---|
1212 | //
|
---|
1213 | // ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CONFIG5);
|
---|
1214 | // if (ocp_data & UWF_EN)
|
---|
1215 | // wolopts |= WAKE_UCAST;
|
---|
1216 | // if (ocp_data & BWF_EN)
|
---|
1217 | // wolopts |= WAKE_BCAST;
|
---|
1218 | // if (ocp_data & MWF_EN)
|
---|
1219 | // wolopts |= WAKE_MCAST;
|
---|
1220 | //
|
---|
1221 | // ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CFG_WOL);
|
---|
1222 | // if (ocp_data & MAGIC_EN)
|
---|
1223 | // wolopts |= WAKE_MAGIC;
|
---|
1224 |
|
---|
1225 | return wolopts;
|
---|
1226 | }
|
---|
1227 |
|
---|
1228 | static void
|
---|
1229 | __rtl_set_wol(struct rtl_softc *sc, uint32_t wolopts)
|
---|
1230 | {
|
---|
1231 | printf("[foo] %s\n", __func__);
|
---|
1232 | uint32_t ocp_data;
|
---|
1233 |
|
---|
1234 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
|
---|
1235 |
|
---|
1236 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CONFIG34);
|
---|
1237 | ocp_data &= ~LINK_ON_WAKE_EN;
|
---|
1238 | // if (wolopts & WAKE_PHY)
|
---|
1239 | // ocp_data |= LINK_ON_WAKE_EN;
|
---|
1240 | // ocp_write_2(sc, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data);
|
---|
1241 | //
|
---|
1242 | // ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CONFIG5);
|
---|
1243 | // ocp_data &= ~(UWF_EN | BWF_EN | MWF_EN | LAN_WAKE_EN);
|
---|
1244 | // if (wolopts & WAKE_UCAST)
|
---|
1245 | // ocp_data |= UWF_EN;
|
---|
1246 | // if (wolopts & WAKE_BCAST)
|
---|
1247 | // ocp_data |= BWF_EN;
|
---|
1248 | // if (wolopts & WAKE_MCAST)
|
---|
1249 | // ocp_data |= MWF_EN;
|
---|
1250 | // if (wolopts & WAKE_ANY)
|
---|
1251 | // ocp_data |= LAN_WAKE_EN;
|
---|
1252 | // ocp_write_2(sc, MCU_TYPE_PLA, PLA_CONFIG5, ocp_data);
|
---|
1253 | //
|
---|
1254 | // ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
|
---|
1255 | //
|
---|
1256 | // ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CFG_WOL);
|
---|
1257 | // ocp_data &= ~MAGIC_EN;
|
---|
1258 | // if (wolopts & WAKE_MAGIC)
|
---|
1259 | // ocp_data |= MAGIC_EN;
|
---|
1260 | // ocp_write_2(sc, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
|
---|
1261 | }
|
---|
1262 |
|
---|
1263 | static void
|
---|
1264 | rtl_runtime_suspend_enable(struct rtl_softc *sc, bool enable)
|
---|
1265 | {
|
---|
1266 | printf("[foo] %s\n", __func__);
|
---|
1267 | uint32_t ocp_data;
|
---|
1268 |
|
---|
1269 | if (enable) {
|
---|
1270 | //__rtl_set_wol(sc, WAKE_ANY);
|
---|
1271 |
|
---|
1272 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
|
---|
1273 |
|
---|
1274 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CONFIG34);
|
---|
1275 | ocp_data |= LINK_OFF_WAKE_EN;
|
---|
1276 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data);
|
---|
1277 |
|
---|
1278 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
|
---|
1279 | } else {
|
---|
1280 | __rtl_set_wol(sc, sc->saved_wolopts);
|
---|
1281 | }
|
---|
1282 | }
|
---|
1283 |
|
---|
1284 | static void
|
---|
1285 | rtl_phy_reset(struct rtl_softc *sc)
|
---|
1286 | {
|
---|
1287 | printf("[foo] %s\n", __func__);
|
---|
1288 | uint32_t data;
|
---|
1289 | int i;
|
---|
1290 |
|
---|
1291 | data = r8152_mdio_read(sc, MII_BMCR);
|
---|
1292 |
|
---|
1293 | /* don't reset again before the previous one complete */
|
---|
1294 | if (data & BMCR_RESET)
|
---|
1295 | return;
|
---|
1296 |
|
---|
1297 | data |= BMCR_RESET;
|
---|
1298 | r8152_mdio_write(sc, MII_BMCR, data);
|
---|
1299 |
|
---|
1300 | for (i = 0; i < 50; i++) {
|
---|
1301 | uether_pause(&sc->sc_ue, hz / 1000);
|
---|
1302 | if ((r8152_mdio_read(sc, MII_BMCR) & BMCR_RESET) == 0)
|
---|
1303 | break;
|
---|
1304 | }
|
---|
1305 | }
|
---|
1306 |
|
---|
1307 | static void
|
---|
1308 | r8153_teredo_off(struct rtl_softc *sc)
|
---|
1309 | {
|
---|
1310 | printf("[foo] %s\n", __func__);
|
---|
1311 | uint32_t ocp_data;
|
---|
1312 |
|
---|
1313 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_TEREDO_CFG);
|
---|
1314 | ocp_data &= ~(TEREDO_SEL | TEREDO_RS_EVENT_MASK | OOB_TEREDO_EN);
|
---|
1315 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
|
---|
1316 |
|
---|
1317 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE);
|
---|
1318 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_REALWOW_TIMER, 0);
|
---|
1319 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_TEREDO_TIMER, 0);
|
---|
1320 | }
|
---|
1321 |
|
---|
1322 | static void
|
---|
1323 | r8152b_disable_aldps(struct rtl_softc *sc)
|
---|
1324 | {
|
---|
1325 | printf("[foo] %s\n", __func__);
|
---|
1326 | ocp_reg_write(sc, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
|
---|
1327 | uether_pause(&sc->sc_ue, hz / 100);
|
---|
1328 | }
|
---|
1329 |
|
---|
1330 | static inline void
|
---|
1331 | r8152b_enable_aldps(struct rtl_softc *sc)
|
---|
1332 | {
|
---|
1333 | printf("[foo] %s\n", __func__);
|
---|
1334 | ocp_reg_write(sc, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS |
|
---|
1335 | LINKENA | DIS_SDSAVE);
|
---|
1336 | }
|
---|
1337 |
|
---|
1338 | static void rtl8152_disable(struct rtl_softc *sc)
|
---|
1339 | {
|
---|
1340 | printf("[foo] %s\n", __func__);
|
---|
1341 | r8152b_disable_aldps(sc);
|
---|
1342 | rtl_disable(sc);
|
---|
1343 | r8152b_enable_aldps(sc);
|
---|
1344 | }
|
---|
1345 |
|
---|
1346 | static void r8152b_hw_phy_cfg(struct rtl_softc *sc)
|
---|
1347 | {
|
---|
1348 | printf("[foo] %s\n", __func__);
|
---|
1349 | uint16_t data;
|
---|
1350 |
|
---|
1351 | data = r8152_mdio_read(sc, MII_BMCR);
|
---|
1352 | if (data & BMCR_PDOWN) {
|
---|
1353 | data &= ~BMCR_PDOWN;
|
---|
1354 | r8152_mdio_write(sc, MII_BMCR, data);
|
---|
1355 | }
|
---|
1356 | }
|
---|
1357 |
|
---|
1358 | static void
|
---|
1359 | r8152b_exit_oob(struct rtl_softc *sc)
|
---|
1360 | {
|
---|
1361 | printf("[foo] %s\n", __func__);
|
---|
1362 | uint32_t ocp_data;
|
---|
1363 | int i;
|
---|
1364 |
|
---|
1365 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_RCR);
|
---|
1366 | ocp_data &= ~RCR_ACPT_ALL;
|
---|
1367 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RCR, ocp_data);
|
---|
1368 |
|
---|
1369 | rxdy_gated_en(sc, true);
|
---|
1370 | r8153_teredo_off(sc);
|
---|
1371 | r8152b_hw_phy_cfg(sc);
|
---|
1372 |
|
---|
1373 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
|
---|
1374 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CR, 0x00);
|
---|
1375 |
|
---|
1376 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
1377 | ocp_data &= ~NOW_IS_OOB;
|
---|
1378 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
|
---|
1379 |
|
---|
1380 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7);
|
---|
1381 | ocp_data &= ~MCU_BORW_EN;
|
---|
1382 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
---|
1383 |
|
---|
1384 | for (i = 0; i < 1000; i++) {
|
---|
1385 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
1386 | if (ocp_data & LINK_LIST_READY)
|
---|
1387 | break;
|
---|
1388 | uether_pause(&sc->sc_ue, hz / 10);
|
---|
1389 | }
|
---|
1390 |
|
---|
1391 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7);
|
---|
1392 | ocp_data |= RE_INIT_LL;
|
---|
1393 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
---|
1394 |
|
---|
1395 | for (i = 0; i < 1000; i++) {
|
---|
1396 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
1397 | if (ocp_data & LINK_LIST_READY)
|
---|
1398 | break;
|
---|
1399 | uether_pause(&sc->sc_ue, hz / 10);
|
---|
1400 | }
|
---|
1401 |
|
---|
1402 | rtl8152_nic_reset(sc);
|
---|
1403 |
|
---|
1404 | /* rx share fifo credit full threshold */
|
---|
1405 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
|
---|
1406 |
|
---|
1407 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
|
---|
1408 | RXFIFO_THR2_FULL);
|
---|
1409 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
|
---|
1410 | RXFIFO_THR3_FULL);
|
---|
1411 | //if (tp->udev->speed == USB_SPEED_FULL ||
|
---|
1412 | // tp->udev->speed == USB_SPEED_LOW) {
|
---|
1413 | // /* rx share fifo credit near full threshold */
|
---|
1414 | // ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
|
---|
1415 | // RXFIFO_THR2_FULL);
|
---|
1416 | // ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
|
---|
1417 | // RXFIFO_THR3_FULL);
|
---|
1418 | //} else {
|
---|
1419 | // /* rx share fifo credit near full threshold */
|
---|
1420 | // ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
|
---|
1421 | // RXFIFO_THR2_HIGH);
|
---|
1422 | // ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
|
---|
1423 | // RXFIFO_THR3_HIGH);
|
---|
1424 | //}
|
---|
1425 |
|
---|
1426 | /* TX share fifo free credit full threshold */
|
---|
1427 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL);
|
---|
1428 |
|
---|
1429 | ocp_write_1(sc, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD);
|
---|
1430 | ocp_write_4(sc, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH);
|
---|
1431 | ocp_write_4(sc, MCU_TYPE_USB, USB_TX_DMA,
|
---|
1432 | TEST_MODE_DISABLE | TX_SIZE_ADJUST1);
|
---|
1433 |
|
---|
1434 | //rtl_rx_vlan_en(sc, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
|
---|
1435 |
|
---|
1436 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
|
---|
1437 |
|
---|
1438 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_TCR0);
|
---|
1439 | ocp_data |= TCR0_AUTO_FIFO;
|
---|
1440 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_TCR0, ocp_data);
|
---|
1441 | }
|
---|
1442 |
|
---|
1443 | static void
|
---|
1444 | r8152b_enter_oob(struct rtl_softc *sc)
|
---|
1445 | {
|
---|
1446 | printf("[foo] %s\n", __func__);
|
---|
1447 | uint32_t ocp_data;
|
---|
1448 | int i;
|
---|
1449 |
|
---|
1450 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
1451 | ocp_data &= ~NOW_IS_OOB;
|
---|
1452 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
|
---|
1453 |
|
---|
1454 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_OOB);
|
---|
1455 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB);
|
---|
1456 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB);
|
---|
1457 |
|
---|
1458 | rtl_disable(sc);
|
---|
1459 |
|
---|
1460 | for (i = 0; i < 1000; i++) {
|
---|
1461 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
1462 | if (ocp_data & LINK_LIST_READY)
|
---|
1463 | break;
|
---|
1464 | uether_pause(&sc->sc_ue, hz / 10);
|
---|
1465 | }
|
---|
1466 |
|
---|
1467 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7);
|
---|
1468 | ocp_data |= RE_INIT_LL;
|
---|
1469 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
---|
1470 |
|
---|
1471 | for (i = 0; i < 1000; i++) {
|
---|
1472 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
1473 | if (ocp_data & LINK_LIST_READY)
|
---|
1474 | break;
|
---|
1475 | uether_pause(&sc->sc_ue, hz / 10);
|
---|
1476 | }
|
---|
1477 |
|
---|
1478 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
|
---|
1479 |
|
---|
1480 | rtl_rx_vlan_en(sc, true);
|
---|
1481 |
|
---|
1482 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PAL_BDC_CR);
|
---|
1483 | ocp_data |= ALDPS_PROXY_MODE;
|
---|
1484 | ocp_write_2(sc, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
|
---|
1485 |
|
---|
1486 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
1487 | ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
|
---|
1488 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
|
---|
1489 |
|
---|
1490 | rxdy_gated_en(sc, false);
|
---|
1491 |
|
---|
1492 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_RCR);
|
---|
1493 | ocp_data |= RCR_APM | RCR_AM | RCR_AB;
|
---|
1494 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RCR, ocp_data);
|
---|
1495 | }
|
---|
1496 |
|
---|
1497 | static void
|
---|
1498 | rtl8152_up(struct rtl_softc *sc)
|
---|
1499 | {
|
---|
1500 | printf("[foo] %s\n", __func__);
|
---|
1501 | r8152b_disable_aldps(sc);
|
---|
1502 | r8152b_exit_oob(sc);
|
---|
1503 | r8152b_enable_aldps(sc);
|
---|
1504 | }
|
---|
1505 |
|
---|
1506 | static void
|
---|
1507 | rtl8152_down(struct rtl_softc *sc)
|
---|
1508 | {
|
---|
1509 | printf("[foo] %s\n", __func__);
|
---|
1510 | r8152_power_cut_en(sc, false);
|
---|
1511 | r8152b_disable_aldps(sc);
|
---|
1512 | r8152b_enter_oob(sc);
|
---|
1513 | r8152b_enable_aldps(sc);
|
---|
1514 | }
|
---|
1515 |
|
---|
1516 | static inline void
|
---|
1517 | r8152_mmd_indirect(struct rtl_softc *sc, uint16_t dev, uint16_t reg)
|
---|
1518 | {
|
---|
1519 | printf("[foo] %s\n", __func__);
|
---|
1520 | ocp_reg_write(sc, OCP_EEE_AR, FUN_ADDR | dev);
|
---|
1521 | ocp_reg_write(sc, OCP_EEE_DATA, reg);
|
---|
1522 | ocp_reg_write(sc, OCP_EEE_AR, FUN_DATA | dev);
|
---|
1523 | }
|
---|
1524 |
|
---|
1525 | static uint16_t
|
---|
1526 | r8152_mmd_read(struct rtl_softc *sc, uint16_t dev, uint16_t reg)
|
---|
1527 | {
|
---|
1528 | printf("[foo] %s\n", __func__);
|
---|
1529 | uint16_t data;
|
---|
1530 |
|
---|
1531 | r8152_mmd_indirect(sc, dev, reg);
|
---|
1532 | data = ocp_reg_read(sc, OCP_EEE_DATA);
|
---|
1533 | ocp_reg_write(sc, OCP_EEE_AR, 0x0000);
|
---|
1534 |
|
---|
1535 | return data;
|
---|
1536 | }
|
---|
1537 |
|
---|
1538 | static void
|
---|
1539 | r8152_mmd_write(struct rtl_softc *sc, uint16_t dev, uint16_t reg, uint16_t data)
|
---|
1540 | {
|
---|
1541 | printf("[foo] %s\n", __func__);
|
---|
1542 | r8152_mmd_indirect(sc, dev, reg);
|
---|
1543 | ocp_reg_write(sc, OCP_EEE_DATA, data);
|
---|
1544 | ocp_reg_write(sc, OCP_EEE_AR, 0x0000);
|
---|
1545 | }
|
---|
1546 |
|
---|
1547 | static void
|
---|
1548 | r8152_eee_en(struct rtl_softc *sc, bool enable)
|
---|
1549 | {
|
---|
1550 | printf("[foo] %s\n", __func__);
|
---|
1551 | uint16_t config1, config2, config3;
|
---|
1552 | uint32_t ocp_data;
|
---|
1553 |
|
---|
1554 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_EEE_CR);
|
---|
1555 | config1 = ocp_reg_read(sc, OCP_EEE_CONFIG1) & ~sd_rise_time_mask;
|
---|
1556 | config2 = ocp_reg_read(sc, OCP_EEE_CONFIG2);
|
---|
1557 | config3 = ocp_reg_read(sc, OCP_EEE_CONFIG3) & ~fast_snr_mask;
|
---|
1558 |
|
---|
1559 | if (enable) {
|
---|
1560 | ocp_data |= EEE_RX_EN | EEE_TX_EN;
|
---|
1561 | config1 |= EEE_10_CAP | EEE_NWAY_EN | TX_QUIET_EN | RX_QUIET_EN;
|
---|
1562 | //TODO: config1 |= sd_rise_time(1);
|
---|
1563 | config2 |= RG_DACQUIET_EN | RG_LDVQUIET_EN;
|
---|
1564 | //TODO: config3 |= fast_snr(42);
|
---|
1565 | } else {
|
---|
1566 | ocp_data &= ~(EEE_RX_EN | EEE_TX_EN);
|
---|
1567 | config1 &= ~(EEE_10_CAP | EEE_NWAY_EN | TX_QUIET_EN |
|
---|
1568 | RX_QUIET_EN);
|
---|
1569 | //TODO: config1 |= sd_rise_time(7);
|
---|
1570 | config2 &= ~(RG_DACQUIET_EN | RG_LDVQUIET_EN);
|
---|
1571 | //TODO: config3 |= fast_snr(511);
|
---|
1572 | }
|
---|
1573 |
|
---|
1574 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data);
|
---|
1575 | ocp_reg_write(sc, OCP_EEE_CONFIG1, config1);
|
---|
1576 | ocp_reg_write(sc, OCP_EEE_CONFIG2, config2);
|
---|
1577 | ocp_reg_write(sc, OCP_EEE_CONFIG3, config3);
|
---|
1578 | }
|
---|
1579 |
|
---|
1580 | static void
|
---|
1581 | r8152b_enable_eee(struct rtl_softc *sc)
|
---|
1582 | {
|
---|
1583 | printf("[foo] %s\n", __func__);
|
---|
1584 | #define MDIO_MMD_AN 7 /* Auto-Negotiation */
|
---|
1585 | #define MDIO_AN_EEE_ADV 60 /* EEE advertisement */
|
---|
1586 | #define MDIO_EEE_100TX 0x0002 /* Advertise 100TX EEE cap */
|
---|
1587 | r8152_eee_en(sc, true);
|
---|
1588 | r8152_mmd_write(sc, MDIO_MMD_AN, MDIO_AN_EEE_ADV, MDIO_EEE_100TX);
|
---|
1589 | }
|
---|
1590 |
|
---|
1591 | static void
|
---|
1592 | r8152b_enable_fc(struct rtl_softc *sc)
|
---|
1593 | {
|
---|
1594 | uint16_t anar;
|
---|
1595 |
|
---|
1596 | anar = r8152_mdio_read(sc, MII_ANAR);
|
---|
1597 | anar |= ANAR_FC | ANAR_X_PAUSE_ASYM;
|
---|
1598 | r8152_mdio_write(sc, MII_ANAR, anar);
|
---|
1599 | }
|
---|
1600 |
|
---|
1601 | static void
|
---|
1602 | rtl_tally_reset(struct rtl_softc *sc)
|
---|
1603 | {
|
---|
1604 | printf("[foo] %s\n", __func__);
|
---|
1605 | uint32_t ocp_data;
|
---|
1606 |
|
---|
1607 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_RSTTALLY);
|
---|
1608 | ocp_data |= TALLY_RESET;
|
---|
1609 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data);
|
---|
1610 | }
|
---|
1611 |
|
---|
1612 |
|
---|
1613 | static void
|
---|
1614 | rtl_init(struct usb_ether *ue)
|
---|
1615 | {
|
---|
1616 | printf("[foo] %s\n", __func__);
|
---|
1617 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
1618 | struct ifnet *ifp = uether_getifp(ue);
|
---|
1619 | uint32_t ocp_data;
|
---|
1620 |
|
---|
1621 | RTL_LOCK_ASSERT(sc, MA_OWNED);
|
---|
1622 |
|
---|
1623 | /*
|
---|
1624 | * Cancel pending I/O
|
---|
1625 | */
|
---|
1626 | //rtl_stop(ue);
|
---|
1627 |
|
---|
1628 | /* Load the promiscuous & multicast filter */
|
---|
1629 | rtl_setpromisc_and_multi(ue);
|
---|
1630 |
|
---|
1631 | /*
|
---|
1632 | * Set the initial TX and RX configuration.
|
---|
1633 | */
|
---|
1634 | r8152b_disable_aldps(sc);
|
---|
1635 |
|
---|
1636 | if (sc->version == RTL_VER_01) {
|
---|
1637 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_LED_FEATURE);
|
---|
1638 | ocp_data &= ~LED_MODE_MASK;
|
---|
1639 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
|
---|
1640 | }
|
---|
1641 |
|
---|
1642 | /*
|
---|
1643 | * Enable RX and TX
|
---|
1644 | */
|
---|
1645 | r8152_power_cut_en(sc, false);
|
---|
1646 |
|
---|
1647 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_PHY_PWR);
|
---|
1648 | ocp_data |= TX_10M_IDLE_EN | PFM_PWM_SWITCH;
|
---|
1649 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
|
---|
1650 |
|
---|
1651 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL);
|
---|
1652 | ocp_data &= ~MCU_CLK_RATIO_MASK;
|
---|
1653 | ocp_data |= MCU_CLK_RATIO | D3_CLK_GATED_EN;
|
---|
1654 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ocp_data);
|
---|
1655 |
|
---|
1656 | ocp_data = GPHY_STS_MSK | SPEED_DOWN_MSK |
|
---|
1657 | SPDWN_RXDV_MSK | SPDWN_LINKCHG_MSK;
|
---|
1658 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_GPHY_INTR_IMR, ocp_data);
|
---|
1659 |
|
---|
1660 | //r8152b_enable_eee(sc);
|
---|
1661 | r8152b_enable_aldps(sc);
|
---|
1662 | r8152b_enable_fc(sc);
|
---|
1663 | rtl_tally_reset(sc);
|
---|
1664 |
|
---|
1665 | /* enable rx aggregation */
|
---|
1666 | ocp_data = ocp_read_2(sc, MCU_TYPE_USB, USB_USB_CTRL);
|
---|
1667 | ocp_data &= ~RX_AGG_DISABLE;
|
---|
1668 | ocp_write_2(sc, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
|
---|
1669 |
|
---|
1670 | ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
---|
1671 |
|
---|
1672 | rtl8152_up(sc);
|
---|
1673 |
|
---|
1674 | rtl_start(ue);
|
---|
1675 | }
|
---|
1676 |
|
---|
1677 | /*
|
---|
1678 | * Set media options.
|
---|
1679 | */
|
---|
1680 | static int
|
---|
1681 | rtl_ifmedia_upd(struct ifnet *ifp)
|
---|
1682 | {
|
---|
1683 | printf("[foo] %s\n", __func__);
|
---|
1684 | struct rtl_softc *sc = ifp->if_softc;
|
---|
1685 | struct mii_data *mii = GET_MII(sc);
|
---|
1686 | struct mii_softc *miisc;
|
---|
1687 | int error;
|
---|
1688 |
|
---|
1689 | RTL_LOCK_ASSERT(sc, MA_OWNED);
|
---|
1690 |
|
---|
1691 | sc->sc_flags &= ~RTL_FLAG_LINK;
|
---|
1692 | LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
|
---|
1693 | PHY_RESET(miisc);
|
---|
1694 | error = mii_mediachg(mii);
|
---|
1695 | return (error);
|
---|
1696 | }
|
---|
1697 |
|
---|
1698 | /*
|
---|
1699 | * Report current media status.
|
---|
1700 | */
|
---|
1701 | static void
|
---|
1702 | rtl_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
|
---|
1703 | {
|
---|
1704 | printf("[foo] %s\n", __func__);
|
---|
1705 | struct rtl_softc *sc = ifp->if_softc;
|
---|
1706 | struct mii_data *mii = GET_MII(sc);
|
---|
1707 |
|
---|
1708 | RTL_LOCK(sc);
|
---|
1709 | mii_pollstat(mii);
|
---|
1710 | ifmr->ifm_active = mii->mii_media_active;
|
---|
1711 | ifmr->ifm_status = mii->mii_media_status;
|
---|
1712 | RTL_UNLOCK(sc);
|
---|
1713 | }
|
---|
1714 |
|
---|
1715 | static void
|
---|
1716 | rtl_start(struct usb_ether *ue)
|
---|
1717 | {
|
---|
1718 | printf("[foo] %s\n", __func__);
|
---|
1719 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
1720 |
|
---|
1721 | /*
|
---|
1722 | * start the USB transfers, if not already started:
|
---|
1723 | */
|
---|
1724 | usbd_transfer_start(sc->sc_xfer[RTL_INTR_DT_RD]);
|
---|
1725 | usbd_transfer_start(sc->sc_xfer[RTL_BULK_DT_RD]);
|
---|
1726 | usbd_transfer_start(sc->sc_xfer[RTL_BULK_DT_WR]);
|
---|
1727 | }
|
---|
1728 |
|
---|
1729 | static void
|
---|
1730 | rtl_stop(struct usb_ether *ue)
|
---|
1731 | {
|
---|
1732 | printf("[foo] %s\n", __func__);
|
---|
1733 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
1734 | struct ifnet *ifp = uether_getifp(ue);
|
---|
1735 |
|
---|
1736 | RTL_LOCK_ASSERT(sc, MA_OWNED);
|
---|
1737 |
|
---|
1738 | ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
|
---|
1739 | sc->sc_flags &= ~RTL_FLAG_LINK;
|
---|
1740 |
|
---|
1741 | /*
|
---|
1742 | * stop all the transfers, if not already stopped:
|
---|
1743 | */
|
---|
1744 | usbd_transfer_stop(sc->sc_xfer[RTL_BULK_DT_WR]);
|
---|
1745 | usbd_transfer_stop(sc->sc_xfer[RTL_BULK_DT_RD]);
|
---|
1746 | usbd_transfer_stop(sc->sc_xfer[RTL_INTR_DT_RD]);
|
---|
1747 |
|
---|
1748 | rtl8152_down(sc);
|
---|
1749 |
|
---|
1750 | rtl_reset(sc);
|
---|
1751 | }
|
---|