Line data Source code
1 : /* $OpenBSD: if_mue.c,v 1.4 2018/08/15 07:13:51 kevlo Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2018 Kevin Lo <kevlo@openbsd.org>
5 : *
6 : * Permission to use, copy, modify, and distribute this software for any
7 : * purpose with or without fee is hereby granted, provided that the above
8 : * copyright notice and this permission notice appear in all copies.
9 : *
10 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 : */
18 :
19 : /* Driver for Microchip LAN7500/LAN7800 chipsets. */
20 :
21 : #include "bpfilter.h"
22 :
23 : #include <sys/param.h>
24 : #include <sys/systm.h>
25 : #include <sys/sockio.h>
26 : #include <sys/rwlock.h>
27 : #include <sys/mbuf.h>
28 : #include <sys/kernel.h>
29 : #include <sys/socket.h>
30 :
31 : #include <sys/device.h>
32 :
33 : #include <machine/bus.h>
34 :
35 : #include <net/if.h>
36 : #include <net/if_dl.h>
37 : #include <net/if_media.h>
38 :
39 : #if NBPFILTER > 0
40 : #include <net/bpf.h>
41 : #endif
42 :
43 : #include <netinet/in.h>
44 : #include <netinet/if_ether.h>
45 :
46 : #include <dev/mii/miivar.h>
47 :
48 : #include <dev/usb/usb.h>
49 : #include <dev/usb/usbdi.h>
50 : #include <dev/usb/usbdi_util.h>
51 : #include <dev/usb/usbdivar.h>
52 : #include <dev/usb/usbdevs.h>
53 :
54 : #include <dev/usb/if_muereg.h>
55 :
56 : #ifdef MUE_DEBUG
57 : #define DPRINTF(x) do { if (muedebug) printf x; } while (0)
58 : #define DPRINTFN(n,x) do { if (muedebug >= (n)) printf x; } while (0)
59 : int muedebug = 0;
60 : #else
61 : #define DPRINTF(x)
62 : #define DPRINTFN(n,x)
63 : #endif
64 :
65 : /*
66 : * Various supported device vendors/products.
67 : */
68 : struct mue_type {
69 : struct usb_devno mue_dev;
70 : uint16_t mue_flags;
71 : #define LAN7500 0x0001 /* LAN7500 */
72 : };
73 :
74 : const struct mue_type mue_devs[] = {
75 : { { USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7500 }, LAN7500 },
76 : { { USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7505 }, LAN7500 },
77 : { { USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7800 }, 0 },
78 : { { USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7801 }, 0 },
79 : { { USB_VENDOR_SMC2, USB_PRODUCT_SMC2_LAN7850 }, 0 }
80 : };
81 :
82 : #define mue_lookup(v, p) ((struct mue_type *)usb_lookup(mue_devs, v, p))
83 :
84 : int mue_match(struct device *, void *, void *);
85 : void mue_attach(struct device *, struct device *, void *);
86 : int mue_detach(struct device *, int);
87 :
88 : struct cfdriver mue_cd = {
89 : NULL, "mue", DV_IFNET
90 : };
91 :
92 : const struct cfattach mue_ca = {
93 : sizeof(struct mue_softc), mue_match, mue_attach, mue_detach
94 : };
95 :
96 : uint32_t mue_csr_read(struct mue_softc *, uint32_t);
97 : int mue_csr_write(struct mue_softc *, uint32_t, uint32_t);
98 :
99 : void mue_lock_mii(struct mue_softc *);
100 : void mue_unlock_mii(struct mue_softc *);
101 :
102 : int mue_mii_wait(struct mue_softc *);
103 : int mue_miibus_readreg(struct device *, int, int);
104 : void mue_miibus_writereg(struct device *, int, int, int);
105 : void mue_miibus_statchg(struct device *);
106 : int mue_ifmedia_upd(struct ifnet *);
107 : void mue_ifmedia_sts(struct ifnet *, struct ifmediareq *);
108 :
109 : int mue_eeprom_wait(struct mue_softc *);
110 : uint8_t mue_eeprom_getbyte(struct mue_softc *, int, uint8_t *);
111 : int mue_read_eeprom(struct mue_softc *, caddr_t, int, int);
112 : int mue_dataport_wait(struct mue_softc *);
113 : void mue_dataport_write(struct mue_softc *, uint32_t, uint32_t,
114 : uint32_t, uint32_t *);
115 : void mue_init_ltm(struct mue_softc *);
116 : int mue_chip_init(struct mue_softc *);
117 : void mue_set_macaddr(struct mue_softc *);
118 :
119 : int mue_rx_list_init(struct mue_softc *);
120 : int mue_tx_list_init(struct mue_softc *);
121 : int mue_open_pipes(struct mue_softc *);
122 : int mue_encap(struct mue_softc *, struct mbuf *, int);
123 : void mue_iff(struct mue_softc *);
124 : void mue_rxeof(struct usbd_xfer *, void *, usbd_status);
125 : void mue_txeof(struct usbd_xfer *, void *, usbd_status);
126 :
127 : void mue_init(void *);
128 : int mue_ioctl(struct ifnet *, u_long, caddr_t);
129 : void mue_watchdog(struct ifnet *);
130 : void mue_reset(struct mue_softc *);
131 : void mue_start(struct ifnet *);
132 : void mue_stop(struct mue_softc *);
133 : void mue_tick(void *);
134 : void mue_tick_task(void *);
135 :
136 : #define MUE_SETBIT(sc, reg, x) \
137 : mue_csr_write(sc, reg, mue_csr_read(sc, reg) | (x))
138 :
139 : #define MUE_CLRBIT(sc, reg, x) \
140 : mue_csr_write(sc, reg, mue_csr_read(sc, reg) & ~(x))
141 :
142 : #if defined(__arm__) || defined(__arm64__)
143 :
144 : #include <dev/ofw/openfirm.h>
145 :
146 : void
147 : mue_enaddr_OF(struct mue_softc *sc)
148 : {
149 : char *device = "/axi/usb/hub/ethernet";
150 : char prop[64];
151 : int node;
152 :
153 : if (sc->mue_dev.dv_unit != 0)
154 : return;
155 :
156 : /* Get the Raspberry Pi MAC address from FDT. */
157 : if ((node = OF_finddevice("/aliases")) == -1)
158 : return;
159 : if (OF_getprop(node, "ethernet0", prop, sizeof(prop)) > 0 ||
160 : OF_getprop(node, "ethernet", prop, sizeof(prop)) > 0)
161 : device = prop;
162 :
163 : if ((node = OF_finddevice(device)) == -1)
164 : return;
165 : if (OF_getprop(node, "local-mac-address", sc->arpcom.ac_enaddr,
166 : sizeof(sc->arpcom.ac_enaddr)) != sizeof(sc->arpcom.ac_enaddr)) {
167 : OF_getprop(node, "mac-address", sc->arpcom.ac_enaddr,
168 : sizeof(sc->arpcom.ac_enaddr));
169 : }
170 : }
171 : #else
172 : #define mue_enaddr_OF(x) do {} while(0)
173 : #endif
174 :
175 : uint32_t
176 0 : mue_csr_read(struct mue_softc *sc, uint32_t reg)
177 : {
178 0 : usb_device_request_t req;
179 : usbd_status err;
180 0 : uDWord val;
181 :
182 0 : if (usbd_is_dying(sc->mue_udev))
183 0 : return (0);
184 :
185 0 : USETDW(val, 0);
186 0 : req.bmRequestType = UT_READ_VENDOR_DEVICE;
187 0 : req.bRequest = MUE_UR_READREG;
188 0 : USETW(req.wValue, 0);
189 0 : USETW(req.wIndex, reg);
190 0 : USETW(req.wLength, 4);
191 :
192 0 : err = usbd_do_request(sc->mue_udev, &req, &val);
193 0 : if (err) {
194 : DPRINTF(("%s: mue_csr_read: reg=0x%x err=%s\n",
195 : sc->mue_dev.dv_xname, reg, usbd_errstr(err)));
196 0 : return (0);
197 : }
198 :
199 0 : return (UGETDW(val));
200 0 : }
201 :
202 : int
203 0 : mue_csr_write(struct mue_softc *sc, uint32_t reg, uint32_t aval)
204 : {
205 0 : usb_device_request_t req;
206 : usbd_status err;
207 0 : uDWord val;
208 :
209 0 : if (usbd_is_dying(sc->mue_udev))
210 0 : return (0);
211 :
212 0 : USETDW(val, aval);
213 0 : req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
214 0 : req.bRequest = MUE_UR_WRITEREG;
215 0 : USETW(req.wValue, 0);
216 0 : USETW(req.wIndex, reg);
217 0 : USETW(req.wLength, 4);
218 :
219 0 : err = usbd_do_request(sc->mue_udev, &req, &val);
220 0 : if (err) {
221 : DPRINTF(("%s: mue_csr_write: reg=0x%x err=%s\n",
222 : sc->mue_dev.dv_xname, reg, usbd_errstr(err)));
223 0 : return (-1);
224 : }
225 :
226 0 : return (0);
227 0 : }
228 :
229 : /*
230 : * Get exclusive access to the MII registers.
231 : */
232 : void
233 0 : mue_lock_mii(struct mue_softc *sc)
234 : {
235 0 : sc->mue_refcnt++;
236 0 : rw_enter_write(&sc->mue_mii_lock);
237 0 : }
238 :
239 : void
240 0 : mue_unlock_mii(struct mue_softc *sc)
241 : {
242 0 : rw_exit_write(&sc->mue_mii_lock);
243 0 : if (--sc->mue_refcnt < 0)
244 0 : usb_detach_wakeup(&sc->mue_dev);
245 0 : }
246 :
247 : /*
248 : * Wait for the MII to become ready.
249 : */
250 : int
251 0 : mue_mii_wait(struct mue_softc *sc)
252 : {
253 : int ntries;
254 :
255 0 : for (ntries = 0; ntries < 100; ntries++) {
256 0 : if (!(mue_csr_read(sc, MUE_MII_ACCESS) & MUE_MII_ACCESS_BUSY))
257 0 : return (0);
258 0 : DELAY(5);
259 : }
260 :
261 0 : printf("%s: MII timed out\n", sc->mue_dev.dv_xname);
262 0 : return (1);
263 0 : }
264 :
265 : int
266 0 : mue_miibus_readreg(struct device *dev, int phy, int reg)
267 : {
268 0 : struct mue_softc *sc = (void *)dev;
269 : uint32_t val;
270 :
271 0 : if (usbd_is_dying(sc->mue_udev))
272 0 : return (0);
273 :
274 0 : if (sc->mue_phyno != phy)
275 0 : return (0);
276 :
277 0 : mue_lock_mii(sc);
278 0 : if (mue_mii_wait(sc) != 0)
279 0 : return (0);
280 :
281 0 : mue_csr_write(sc, MUE_MII_ACCESS, MUE_MII_ACCESS_READ |
282 0 : MUE_MII_ACCESS_BUSY | MUE_MII_ACCESS_REGADDR(reg) |
283 0 : MUE_MII_ACCESS_PHYADDR(phy));
284 :
285 0 : if (mue_mii_wait(sc) != 0)
286 0 : printf("%s: MII read timed out\n", sc->mue_dev.dv_xname);
287 :
288 0 : val = mue_csr_read(sc, MUE_MII_DATA);
289 0 : mue_unlock_mii(sc);
290 0 : return (val & 0xffff);
291 0 : }
292 :
293 : void
294 0 : mue_miibus_writereg(struct device *dev, int phy, int reg, int data)
295 : {
296 0 : struct mue_softc *sc = (void *)dev;
297 :
298 0 : if (usbd_is_dying(sc->mue_udev))
299 0 : return;
300 :
301 0 : if (sc->mue_phyno != phy)
302 0 : return;
303 :
304 0 : mue_lock_mii(sc);
305 0 : if (mue_mii_wait(sc) != 0)
306 0 : return;
307 :
308 0 : mue_csr_write(sc, MUE_MII_DATA, data);
309 0 : mue_csr_write(sc, MUE_MII_ACCESS, MUE_MII_ACCESS_WRITE |
310 0 : MUE_MII_ACCESS_BUSY | MUE_MII_ACCESS_REGADDR(reg) |
311 0 : MUE_MII_ACCESS_PHYADDR(phy));
312 :
313 0 : if (mue_mii_wait(sc) != 0)
314 0 : printf("%s: MII write timed out\n", sc->mue_dev.dv_xname);
315 :
316 0 : mue_unlock_mii(sc);
317 0 : }
318 :
319 : void
320 0 : mue_miibus_statchg(struct device *dev)
321 : {
322 0 : struct mue_softc *sc = (void *)dev;
323 0 : struct mii_data *mii = GET_MII(sc);
324 0 : struct ifnet *ifp = GET_IFP(sc);
325 : uint32_t flow, threshold;
326 :
327 0 : if (mii == NULL || ifp == NULL ||
328 0 : (ifp->if_flags & IFF_RUNNING) == 0)
329 0 : return;
330 :
331 0 : sc->mue_link = 0;
332 0 : if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
333 : (IFM_ACTIVE | IFM_AVALID)) {
334 0 : switch (IFM_SUBTYPE(mii->mii_media_active)) {
335 : case IFM_10_T:
336 : case IFM_100_TX:
337 : case IFM_1000_T:
338 0 : sc->mue_link++;
339 0 : break;
340 : default:
341 : break;
342 : }
343 : }
344 :
345 : /* Lost link, do nothing. */
346 0 : if (sc->mue_link == 0)
347 0 : return;
348 :
349 0 : if (!(sc->mue_flags & LAN7500)) {
350 0 : if (sc->mue_udev->speed == USB_SPEED_SUPER) {
351 0 : if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
352 : /* Disable U2 and enable U1. */
353 0 : MUE_CLRBIT(sc, MUE_USB_CFG1,
354 : MUE_USB_CFG1_DEV_U2_INIT_EN);
355 0 : MUE_SETBIT(sc, MUE_USB_CFG1,
356 : MUE_USB_CFG1_DEV_U1_INIT_EN);
357 0 : } else {
358 : /* Enable U1 and U2. */
359 0 : MUE_SETBIT(sc, MUE_USB_CFG1,
360 : MUE_USB_CFG1_DEV_U1_INIT_EN |
361 : MUE_USB_CFG1_DEV_U2_INIT_EN);
362 : }
363 : }
364 : }
365 :
366 : threshold = 0;
367 : flow = 0;
368 0 : if (IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) {
369 0 : if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) {
370 : flow |= MUE_FLOW_TX_FCEN | MUE_FLOW_PAUSE_TIME;
371 :
372 : /* XXX magic numbers come from Linux driver. */
373 0 : if (sc->mue_flags & LAN7500) {
374 : threshold = 0x820;
375 0 : } else {
376 : threshold =
377 0 : (sc->mue_udev->speed == USB_SPEED_SUPER) ?
378 : 0x817 : 0x211;
379 : }
380 : }
381 0 : if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE)
382 0 : flow |= MUE_FLOW_RX_FCEN;
383 : }
384 0 : mue_csr_write(sc, (sc->mue_flags & LAN7500) ?
385 : MUE_FCT_FLOW : MUE_7800_FCT_FLOW, threshold);
386 :
387 : /* Threshold value should be set before enabling flow. */
388 0 : mue_csr_write(sc, MUE_FLOW, flow);
389 0 : }
390 :
391 : /*
392 : * Set media options.
393 : */
394 : int
395 0 : mue_ifmedia_upd(struct ifnet *ifp)
396 : {
397 0 : struct mue_softc *sc = ifp->if_softc;
398 0 : struct mii_data *mii = GET_MII(sc);
399 :
400 0 : if (mii->mii_instance) {
401 : struct mii_softc *miisc;
402 0 : LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
403 0 : mii_phy_reset(miisc);
404 0 : }
405 0 : return (mii_mediachg(mii));
406 : }
407 :
408 : /*
409 : * Report current media status.
410 : */
411 : void
412 0 : mue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
413 : {
414 0 : struct mue_softc *sc = ifp->if_softc;
415 0 : struct mii_data *mii = GET_MII(sc);
416 :
417 0 : mii_pollstat(mii);
418 0 : ifmr->ifm_active = mii->mii_media_active;
419 0 : ifmr->ifm_status = mii->mii_media_status;
420 0 : }
421 :
422 : int
423 0 : mue_eeprom_wait(struct mue_softc *sc)
424 : {
425 : uint32_t val;
426 : int ntries;
427 :
428 0 : for (ntries = 0; ntries < 100; ntries++) {
429 0 : val = mue_csr_read(sc, MUE_E2P_CMD);
430 0 : if (!(val & MUE_E2P_CMD_BUSY) || (val & MUE_E2P_CMD_TIMEOUT))
431 0 : return (0);
432 0 : DELAY(5);
433 : }
434 :
435 0 : return (1);
436 0 : }
437 :
438 : uint8_t
439 0 : mue_eeprom_getbyte(struct mue_softc *sc, int addr, uint8_t *dest)
440 : {
441 : uint32_t byte = 0;
442 : int ntries;
443 :
444 0 : for (ntries = 0; ntries < 100; ntries++) {
445 0 : if (!(mue_csr_read(sc, MUE_E2P_CMD) & MUE_E2P_CMD_BUSY))
446 : break;
447 0 : DELAY(5);
448 : }
449 :
450 0 : if (ntries == 100) {
451 0 : printf("%s: EEPROM failed to come ready\n",
452 0 : sc->mue_dev.dv_xname);
453 0 : return (ETIMEDOUT);
454 : }
455 :
456 0 : mue_csr_write(sc, MUE_E2P_CMD, MUE_E2P_CMD_READ | MUE_E2P_CMD_BUSY |
457 0 : (addr & MUE_E2P_CMD_ADDR_MASK));
458 :
459 0 : if (mue_eeprom_wait(sc) != 0) {
460 0 : printf("%s: EEPROM read timed out\n", sc->mue_dev.dv_xname);
461 0 : return (ETIMEDOUT);
462 : }
463 :
464 0 : byte = mue_csr_read(sc, MUE_E2P_DATA);
465 0 : *dest = byte & 0xff;
466 :
467 0 : return (0);
468 0 : }
469 :
470 : int
471 0 : mue_read_eeprom(struct mue_softc *sc, caddr_t dest, int off, int cnt)
472 : {
473 : uint32_t val;
474 0 : uint8_t byte = 0;
475 : int i, err = 0;
476 :
477 : /*
478 : * EEPROM pins are muxed with the LED function on LAN7800 device.
479 : */
480 0 : val = mue_csr_read(sc, MUE_HW_CFG);
481 0 : if (sc->mue_product == USB_PRODUCT_SMC2_LAN7800) {
482 0 : MUE_CLRBIT(sc, MUE_HW_CFG,
483 : MUE_HW_CFG_LED0_EN | MUE_HW_CFG_LED1_EN);
484 0 : }
485 :
486 0 : for (i = 0; i < cnt; i++) {
487 0 : err = mue_eeprom_getbyte(sc, off + i, &byte);
488 0 : if (err)
489 : break;
490 0 : *(dest + i) = byte;
491 : }
492 :
493 0 : if (sc->mue_product == USB_PRODUCT_SMC2_LAN7800)
494 0 : mue_csr_write(sc, MUE_HW_CFG, val);
495 :
496 0 : return (err ? 1 : 0);
497 0 : }
498 :
499 : int
500 0 : mue_dataport_wait(struct mue_softc *sc)
501 : {
502 : int ntries;
503 :
504 0 : for (ntries = 0; ntries < 100; ntries++) {
505 0 : if (mue_csr_read(sc, MUE_DP_SEL) & MUE_DP_SEL_DPRDY)
506 0 : return (0);
507 0 : DELAY(5);
508 : }
509 :
510 0 : printf("%s: dataport timed out\n", sc->mue_dev.dv_xname);
511 0 : return (1);
512 0 : }
513 :
514 : void
515 0 : mue_dataport_write(struct mue_softc *sc, uint32_t sel, uint32_t addr,
516 : uint32_t cnt, uint32_t *data)
517 : {
518 : int i;
519 :
520 0 : if (mue_dataport_wait(sc) != 0)
521 0 : return;
522 :
523 0 : mue_csr_write(sc, MUE_DP_SEL,
524 0 : (mue_csr_read(sc, MUE_DP_SEL) & ~MUE_DP_SEL_RSEL_MASK) | sel);
525 :
526 0 : for (i = 0; i < cnt; i++) {
527 0 : mue_csr_write(sc, MUE_DP_ADDR, addr + i);
528 0 : mue_csr_write(sc, MUE_DP_DATA, data[i]);
529 0 : mue_csr_write(sc, MUE_DP_CMD, MUE_DP_CMD_WRITE);
530 0 : if (mue_dataport_wait(sc) != 0)
531 0 : return;
532 : }
533 0 : }
534 :
535 : void
536 0 : mue_init_ltm(struct mue_softc *sc)
537 : {
538 0 : uint8_t idx[6] = { 0 };
539 : int i;
540 :
541 0 : if (mue_csr_read(sc, MUE_USB_CFG1) & MUE_USB_CFG1_LTM_ENABLE) {
542 0 : uint8_t temp[2];
543 :
544 0 : if (mue_read_eeprom(sc, (caddr_t)&temp, MUE_EE_LTM_OFFSET, 2)) {
545 0 : if (temp[0] != 24)
546 0 : goto done;
547 0 : mue_read_eeprom(sc, (caddr_t)&idx, temp[1] << 1, 24);
548 0 : }
549 0 : }
550 : done:
551 0 : for (i = 0; i < sizeof(idx); i++)
552 0 : mue_csr_write(sc, MUE_LTM_INDEX(i), idx[i]);
553 0 : }
554 :
555 : int
556 0 : mue_chip_init(struct mue_softc *sc)
557 : {
558 : uint32_t val;
559 : int ntries;
560 :
561 0 : if (sc->mue_flags & LAN7500) {
562 0 : for (ntries = 0; ntries < 100; ntries++) {
563 0 : if (mue_csr_read(sc, MUE_PMT_CTL) & MUE_PMT_CTL_READY)
564 : break;
565 0 : DELAY(1000); /* 1 msec */
566 : }
567 0 : if (ntries == 100) {
568 0 : printf("%s: timeout waiting for device ready\n",
569 0 : sc->mue_dev.dv_xname);
570 0 : return (ETIMEDOUT);
571 : }
572 : }
573 :
574 0 : MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_LRST);
575 :
576 0 : for (ntries = 0; ntries < 1000; ntries++) {
577 0 : if (!(mue_csr_read(sc, MUE_HW_CFG) & MUE_HW_CFG_LRST))
578 : break;
579 0 : DELAY(5);
580 : }
581 0 : if (ntries == 1000) {
582 0 : printf("%s: timeout on lite software reset\n",
583 0 : sc->mue_dev.dv_xname);
584 0 : return (ETIMEDOUT);
585 : }
586 :
587 : /* Respond to the IN token with a NAK. */
588 0 : if (sc->mue_flags & LAN7500)
589 0 : MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_BIR);
590 : else
591 0 : MUE_SETBIT(sc, MUE_USB_CFG0, MUE_USB_CFG0_BIR);
592 :
593 0 : if (sc->mue_flags & LAN7500) {
594 0 : mue_csr_write(sc, MUE_BURST_CAP,
595 0 : (sc->mue_udev->speed == USB_SPEED_HIGH) ?
596 : MUE_BURST_MIN_BUFSZ : MUE_BURST_MAX_BUFSZ);
597 0 : mue_csr_write(sc, MUE_BULK_IN_DELAY, MUE_DEFAULT_BULKIN_DELAY);
598 :
599 0 : MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_BCE | MUE_HW_CFG_MEF);
600 :
601 : /* Set undocumented FIFO sizes. */
602 0 : mue_csr_write(sc, MUE_FCT_RX_FIFO_END, 0x27);
603 0 : mue_csr_write(sc, MUE_FCT_TX_FIFO_END, 0x17);
604 0 : } else {
605 : /* Init LTM. */
606 0 : mue_init_ltm(sc);
607 :
608 0 : val = (sc->mue_udev->speed == USB_SPEED_SUPER) ?
609 : MUE_7800_BURST_MIN_BUFSZ : MUE_7800_BURST_MAX_BUFSZ;
610 0 : mue_csr_write(sc, MUE_7800_BURST_CAP, val);
611 0 : mue_csr_write(sc, MUE_7800_BULK_IN_DELAY,
612 : MUE_7800_DEFAULT_BULKIN_DELAY);
613 :
614 0 : MUE_SETBIT(sc, MUE_HW_CFG, MUE_HW_CFG_MEF);
615 0 : MUE_SETBIT(sc, MUE_USB_CFG0, MUE_USB_CFG0_BCE);
616 : }
617 :
618 0 : mue_csr_write(sc, MUE_INT_STATUS, 0xffffffff);
619 0 : mue_csr_write(sc, (sc->mue_flags & LAN7500) ?
620 : MUE_FCT_FLOW : MUE_7800_FCT_FLOW, 0);
621 0 : mue_csr_write(sc, MUE_FLOW, 0);
622 :
623 : /* Reset PHY. */
624 0 : MUE_SETBIT(sc, MUE_PMT_CTL, MUE_PMT_CTL_PHY_RST);
625 0 : for (ntries = 0; ntries < 100; ntries++) {
626 0 : val = mue_csr_read(sc, MUE_PMT_CTL);
627 0 : if (!(val & MUE_PMT_CTL_PHY_RST) && (val & MUE_PMT_CTL_READY))
628 : break;
629 0 : DELAY(10000);
630 : }
631 0 : if (ntries == 100) {
632 0 : printf("%s: timeout waiting for PHY reset\n",
633 0 : sc->mue_dev.dv_xname);
634 0 : return (ETIMEDOUT);
635 : }
636 :
637 : /* LAN7801 only has RGMII mode. */
638 0 : if (sc->mue_product == USB_PRODUCT_SMC2_LAN7801)
639 0 : MUE_CLRBIT(sc, MUE_MAC_CR, MUE_MAC_CR_GMII_EN);
640 :
641 0 : if (sc->mue_flags & LAN7500 || !sc->mue_eeprom_present) {
642 : /* Allow MAC to detect speed and duplex from PHY. */
643 0 : MUE_SETBIT(sc, MUE_MAC_CR, MUE_MAC_CR_AUTO_SPEED |
644 : MUE_MAC_CR_AUTO_DUPLEX);
645 0 : }
646 :
647 0 : MUE_SETBIT(sc, MUE_MAC_TX, MUE_MAC_TX_TXEN);
648 0 : MUE_SETBIT(sc, (sc->mue_flags & LAN7500) ?
649 : MUE_FCT_TX_CTL : MUE_7800_FCT_TX_CTL, MUE_FCT_TX_CTL_EN);
650 :
651 : /* Set the maximum frame size. */
652 0 : MUE_CLRBIT(sc, MUE_MAC_RX, MUE_MAC_RX_RXEN);
653 0 : MUE_SETBIT(sc, MUE_MAC_RX, MUE_MAC_RX_MAX_LEN(ETHER_MAX_LEN));
654 0 : MUE_SETBIT(sc, MUE_MAC_RX, MUE_MAC_RX_RXEN);
655 :
656 0 : MUE_SETBIT(sc, (sc->mue_flags & LAN7500) ?
657 : MUE_FCT_RX_CTL : MUE_7800_FCT_RX_CTL, MUE_FCT_RX_CTL_EN);
658 :
659 0 : return (0);
660 0 : }
661 :
662 : void
663 0 : mue_set_macaddr(struct mue_softc *sc)
664 : {
665 0 : struct ifnet *ifp = &sc->arpcom.ac_if;
666 0 : const uint8_t *eaddr = LLADDR(ifp->if_sadl);
667 : uint32_t val, reg;
668 :
669 0 : reg = (sc->mue_flags & LAN7500) ? MUE_ADDR_FILTX : MUE_7800_ADDR_FILTX;
670 :
671 0 : val = (eaddr[3] << 24) | (eaddr[2] << 16) | (eaddr[1] << 8) | eaddr[0];
672 0 : mue_csr_write(sc, MUE_RX_ADDRL, val);
673 0 : mue_csr_write(sc, reg + 4, val);
674 0 : val = (eaddr[5] << 8) | eaddr[4];
675 0 : mue_csr_write(sc, MUE_RX_ADDRH, val);
676 0 : mue_csr_write(sc, reg, val | MUE_ADDR_FILTX_VALID);
677 0 : }
678 :
679 : /*
680 : * Probe for a Microchip chip.
681 : */
682 : int
683 0 : mue_match(struct device *parent, void *match, void *aux)
684 : {
685 0 : struct usb_attach_arg *uaa = aux;
686 :
687 0 : if (uaa->iface == NULL || uaa->configno != 1)
688 0 : return (UMATCH_NONE);
689 :
690 0 : return (mue_lookup(uaa->vendor, uaa->product) != NULL ?
691 : UMATCH_VENDOR_PRODUCT_CONF_IFACE : UMATCH_NONE);
692 0 : }
693 :
694 : void
695 0 : mue_attach(struct device *parent, struct device *self, void *aux)
696 : {
697 0 : struct mue_softc *sc = (struct mue_softc *)self;
698 0 : struct usb_attach_arg *uaa = aux;
699 : usb_interface_descriptor_t *id;
700 : usb_endpoint_descriptor_t *ed;
701 : struct mii_data *mii;
702 : struct ifnet *ifp;
703 0 : int i, s;
704 :
705 0 : sc->mue_udev = uaa->device;
706 0 : sc->mue_iface = uaa->iface;
707 0 : sc->mue_product = uaa->product;
708 0 : sc->mue_flags = mue_lookup(uaa->vendor, uaa->product)->mue_flags;
709 :
710 0 : usb_init_task(&sc->mue_tick_task, mue_tick_task, sc,
711 : USB_TASK_TYPE_GENERIC);
712 0 : rw_init(&sc->mue_mii_lock, "muemii");
713 0 : usb_init_task(&sc->mue_stop_task, (void (*)(void *))mue_stop, sc,
714 : USB_TASK_TYPE_GENERIC);
715 :
716 : /* Decide on what our bufsize will be. */
717 0 : if (sc->mue_flags & LAN7500)
718 0 : sc->mue_bufsz = (sc->mue_udev->speed == USB_SPEED_HIGH) ?
719 : MUE_MAX_BUFSZ : MUE_MIN_BUFSZ;
720 : else
721 0 : sc->mue_bufsz = MUE_7800_BUFSZ;
722 :
723 : /* Find endpoints. */
724 0 : id = usbd_get_interface_descriptor(sc->mue_iface);
725 0 : for (i = 0; i < id->bNumEndpoints; i++) {
726 0 : ed = usbd_interface2endpoint_descriptor(sc->mue_iface, i);
727 0 : if (ed == NULL) {
728 0 : printf("%s: couldn't get ep %d\n",
729 0 : sc->mue_dev.dv_xname, i);
730 0 : return;
731 : }
732 0 : if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
733 0 : UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
734 0 : sc->mue_ed[MUE_ENDPT_RX] = ed->bEndpointAddress;
735 0 : } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
736 0 : UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
737 0 : sc->mue_ed[MUE_ENDPT_TX] = ed->bEndpointAddress;
738 0 : } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
739 0 : UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
740 0 : sc->mue_ed[MUE_ENDPT_INTR] = ed->bEndpointAddress;
741 0 : }
742 : }
743 :
744 0 : s = splnet();
745 :
746 0 : sc->mue_phyno = 1;
747 :
748 : /* Check if the EEPROM programmed indicator is present. */
749 0 : mue_read_eeprom(sc, (caddr_t)&i, MUE_EE_IND_OFFSET, 1);
750 0 : sc->mue_eeprom_present = (i == MUE_EEPROM_INDICATOR) ? 1 : 0;
751 :
752 0 : if (mue_chip_init(sc) != 0) {
753 0 : printf("%s: chip initialization failed\n",
754 0 : sc->mue_dev.dv_xname);
755 0 : splx(s);
756 0 : return;
757 : }
758 :
759 : /* Get station address from the EEPROM. */
760 0 : if (sc->mue_eeprom_present) {
761 0 : if (mue_read_eeprom(sc, (caddr_t)&sc->arpcom.ac_enaddr,
762 : MUE_EE_MAC_OFFSET, ETHER_ADDR_LEN)) {
763 0 : printf("%s: failed to read station address\n",
764 0 : sc->mue_dev.dv_xname);
765 0 : splx(s);
766 0 : return;
767 : }
768 : } else
769 : mue_enaddr_OF(sc);
770 :
771 : /* A Microchip chip was detected. Inform the world. */
772 0 : printf("%s:", sc->mue_dev.dv_xname);
773 0 : if (sc->mue_flags & LAN7500)
774 0 : printf(" LAN7500");
775 : else
776 0 : printf(" LAN7800");
777 0 : printf(", address %s\n", ether_sprintf(sc->arpcom.ac_enaddr));
778 :
779 : /* Initialize interface info.*/
780 0 : ifp = GET_IFP(sc);
781 0 : ifp->if_softc = sc;
782 0 : ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
783 0 : ifp->if_ioctl = mue_ioctl;
784 0 : ifp->if_start = mue_start;
785 0 : ifp->if_watchdog = mue_watchdog;
786 0 : strlcpy(ifp->if_xname, sc->mue_dev.dv_xname, IFNAMSIZ);
787 :
788 0 : ifp->if_capabilities = IFCAP_VLAN_MTU;
789 :
790 : /* Initialize MII/media info. */
791 0 : mii = GET_MII(sc);
792 0 : mii->mii_ifp = ifp;
793 0 : mii->mii_readreg = mue_miibus_readreg;
794 0 : mii->mii_writereg = mue_miibus_writereg;
795 0 : mii->mii_statchg = mue_miibus_statchg;
796 0 : mii->mii_flags = MIIF_AUTOTSLEEP;
797 :
798 0 : ifmedia_init(&mii->mii_media, 0, mue_ifmedia_upd, mue_ifmedia_sts);
799 0 : mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
800 : MIIF_DOPAUSE);
801 :
802 0 : if (LIST_FIRST(&mii->mii_phys) == NULL) {
803 0 : ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
804 0 : ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
805 0 : } else
806 0 : ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
807 :
808 : /* Attach the interface. */
809 0 : if_attach(ifp);
810 0 : ether_ifattach(ifp);
811 :
812 0 : timeout_set(&sc->mue_stat_ch, mue_tick, sc);
813 :
814 0 : splx(s);
815 0 : }
816 :
817 : int
818 0 : mue_detach(struct device *self, int flags)
819 : {
820 0 : struct mue_softc *sc = (struct mue_softc *)self;
821 0 : struct ifnet *ifp = GET_IFP(sc);
822 : int s;
823 :
824 0 : if (timeout_initialized(&sc->mue_stat_ch))
825 0 : timeout_del(&sc->mue_stat_ch);
826 :
827 0 : if (sc->mue_ep[MUE_ENDPT_TX] != NULL)
828 0 : usbd_abort_pipe(sc->mue_ep[MUE_ENDPT_TX]);
829 0 : if (sc->mue_ep[MUE_ENDPT_RX] != NULL)
830 0 : usbd_abort_pipe(sc->mue_ep[MUE_ENDPT_RX]);
831 0 : if (sc->mue_ep[MUE_ENDPT_INTR] != NULL)
832 0 : usbd_abort_pipe(sc->mue_ep[MUE_ENDPT_INTR]);
833 :
834 : /*
835 : * Remove any pending tasks. They cannot be executing because they run
836 : * in the same thread as detach.
837 : */
838 0 : usb_rem_task(sc->mue_udev, &sc->mue_tick_task);
839 0 : usb_rem_task(sc->mue_udev, &sc->mue_stop_task);
840 :
841 0 : s = splusb();
842 :
843 0 : if (--sc->mue_refcnt >= 0) {
844 : /* Wait for processes to go away */
845 0 : usb_detach_wait(&sc->mue_dev);
846 0 : }
847 :
848 0 : if (ifp->if_flags & IFF_RUNNING)
849 0 : mue_stop(sc);
850 :
851 0 : mii_detach(&sc->mue_mii, MII_PHY_ANY, MII_OFFSET_ANY);
852 0 : ifmedia_delete_instance(&sc->mue_mii.mii_media, IFM_INST_ANY);
853 0 : if (ifp->if_softc != NULL) {
854 0 : ether_ifdetach(ifp);
855 0 : if_detach(ifp);
856 0 : }
857 :
858 0 : if (--sc->mue_refcnt >= 0) {
859 : /* Wait for processes to go away. */
860 0 : usb_detach_wait(&sc->mue_dev);
861 0 : }
862 0 : splx(s);
863 :
864 0 : return (0);
865 : }
866 :
867 : int
868 0 : mue_rx_list_init(struct mue_softc *sc)
869 : {
870 : struct mue_cdata *cd;
871 : struct mue_chain *c;
872 : int i;
873 :
874 : DPRINTF(("%s: %s: enter\n", sc->mue_dev.dv_xname, __func__));
875 :
876 0 : cd = &sc->mue_cdata;
877 0 : for (i = 0; i < MUE_RX_LIST_CNT; i++) {
878 0 : c = &cd->mue_rx_chain[i];
879 0 : c->mue_sc = sc;
880 0 : c->mue_idx = i;
881 0 : c->mue_mbuf = NULL;
882 0 : if (c->mue_xfer == NULL) {
883 0 : c->mue_xfer = usbd_alloc_xfer(sc->mue_udev);
884 0 : if (c->mue_xfer == NULL)
885 0 : return (ENOBUFS);
886 0 : c->mue_buf = usbd_alloc_buffer(c->mue_xfer,
887 0 : sc->mue_bufsz);
888 0 : if (c->mue_buf == NULL) {
889 0 : usbd_free_xfer(c->mue_xfer);
890 0 : return (ENOBUFS);
891 : }
892 : }
893 : }
894 :
895 0 : return (0);
896 0 : }
897 :
898 : int
899 0 : mue_tx_list_init(struct mue_softc *sc)
900 : {
901 : struct mue_cdata *cd;
902 : struct mue_chain *c;
903 : int i;
904 :
905 : DPRINTF(("%s: %s: enter\n", sc->mue_dev.dv_xname, __func__));
906 :
907 0 : cd = &sc->mue_cdata;
908 0 : for (i = 0; i < MUE_TX_LIST_CNT; i++) {
909 0 : c = &cd->mue_tx_chain[i];
910 0 : c->mue_sc = sc;
911 0 : c->mue_idx = i;
912 0 : c->mue_mbuf = NULL;
913 0 : if (c->mue_xfer == NULL) {
914 0 : c->mue_xfer = usbd_alloc_xfer(sc->mue_udev);
915 0 : if (c->mue_xfer == NULL)
916 0 : return (ENOBUFS);
917 0 : c->mue_buf = usbd_alloc_buffer(c->mue_xfer,
918 0 : sc->mue_bufsz);
919 0 : if (c->mue_buf == NULL) {
920 0 : usbd_free_xfer(c->mue_xfer);
921 0 : return (ENOBUFS);
922 : }
923 : }
924 : }
925 :
926 0 : return (0);
927 0 : }
928 :
929 : int
930 0 : mue_open_pipes(struct mue_softc *sc)
931 : {
932 : struct mue_chain *c;
933 : usbd_status err;
934 : int i;
935 :
936 : /* Open RX and TX pipes. */
937 0 : err = usbd_open_pipe(sc->mue_iface, sc->mue_ed[MUE_ENDPT_RX],
938 0 : USBD_EXCLUSIVE_USE, &sc->mue_ep[MUE_ENDPT_RX]);
939 0 : if (err) {
940 0 : printf("%s: open rx pipe failed: %s\n",
941 0 : sc->mue_dev.dv_xname, usbd_errstr(err));
942 0 : return (EIO);
943 : }
944 0 : err = usbd_open_pipe(sc->mue_iface, sc->mue_ed[MUE_ENDPT_TX],
945 0 : USBD_EXCLUSIVE_USE, &sc->mue_ep[MUE_ENDPT_TX]);
946 0 : if (err) {
947 0 : printf("%s: open tx pipe failed: %s\n",
948 0 : sc->mue_dev.dv_xname, usbd_errstr(err));
949 0 : return (EIO);
950 : }
951 :
952 : /* Start up the receive pipe. */
953 0 : for (i = 0; i < MUE_RX_LIST_CNT; i++) {
954 0 : c = &sc->mue_cdata.mue_rx_chain[i];
955 0 : usbd_setup_xfer(c->mue_xfer, sc->mue_ep[MUE_ENDPT_RX],
956 0 : c, c->mue_buf, sc->mue_bufsz,
957 : USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
958 : mue_rxeof);
959 0 : usbd_transfer(c->mue_xfer);
960 : }
961 :
962 0 : return (0);
963 0 : }
964 :
965 : int
966 0 : mue_encap(struct mue_softc *sc, struct mbuf *m, int idx)
967 : {
968 : struct mue_chain *c;
969 : usbd_status err;
970 : struct mue_txbuf_hdr hdr;
971 : int length;
972 :
973 0 : c = &sc->mue_cdata.mue_tx_chain[idx];
974 :
975 0 : hdr.tx_cmd_a = htole32((m->m_pkthdr.len & MUE_TX_CMD_A_LEN_MASK) |
976 : MUE_TX_CMD_A_FCS);
977 : /* Disable segmentation offload. */
978 : hdr.tx_cmd_b = htole32(0);
979 0 : memcpy(c->mue_buf, &hdr, sizeof(hdr));
980 : length = sizeof(hdr);
981 :
982 0 : m_copydata(m, 0, m->m_pkthdr.len, c->mue_buf + length);
983 0 : length += m->m_pkthdr.len;
984 :
985 0 : c->mue_mbuf = m;
986 :
987 0 : usbd_setup_xfer(c->mue_xfer, sc->mue_ep[MUE_ENDPT_TX],
988 0 : c, c->mue_buf, length, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
989 : 10000, mue_txeof);
990 :
991 : /* Transmit */
992 0 : err = usbd_transfer(c->mue_xfer);
993 0 : if (err != USBD_IN_PROGRESS) {
994 0 : mue_stop(sc);
995 0 : return(EIO);
996 : }
997 :
998 0 : sc->mue_cdata.mue_tx_cnt++;
999 :
1000 0 : return(0);
1001 0 : }
1002 :
1003 : void
1004 0 : mue_iff(struct mue_softc *sc)
1005 : {
1006 0 : struct ifnet *ifp = GET_IFP(sc);
1007 : struct arpcom *ac = &sc->arpcom;
1008 : struct ether_multi *enm;
1009 : struct ether_multistep step;
1010 0 : uint32_t h = 0, hashtbl[MUE_DP_SEL_VHF_HASH_LEN], reg, rxfilt;
1011 :
1012 0 : if (usbd_is_dying(sc->mue_udev))
1013 0 : return;
1014 :
1015 0 : reg = (sc->mue_flags & LAN7500) ? MUE_RFE_CTL : MUE_7800_RFE_CTL;
1016 0 : rxfilt = mue_csr_read(sc, reg);
1017 0 : rxfilt &= ~(MUE_RFE_CTL_PERFECT | MUE_RFE_CTL_MULTICAST_HASH |
1018 : MUE_RFE_CTL_UNICAST | MUE_RFE_CTL_MULTICAST);
1019 0 : ifp->if_flags &= ~IFF_ALLMULTI;
1020 :
1021 : /* Always accept broadcast frames. */
1022 0 : rxfilt |= MUE_RFE_CTL_BROADCAST;
1023 :
1024 0 : if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
1025 0 : ifp->if_flags |= IFF_ALLMULTI;
1026 0 : rxfilt |= MUE_RFE_CTL_MULTICAST;
1027 0 : if (ifp->if_flags & IFF_PROMISC)
1028 0 : rxfilt |= MUE_RFE_CTL_UNICAST | MUE_RFE_CTL_MULTICAST;
1029 : } else {
1030 0 : rxfilt |= MUE_RFE_CTL_PERFECT | MUE_RFE_CTL_MULTICAST_HASH;
1031 :
1032 : /* Clear hash table. */
1033 0 : memset(hashtbl, 0, sizeof(hashtbl));
1034 :
1035 : /* Now program new ones. */
1036 0 : ETHER_FIRST_MULTI(step, ac, enm);
1037 0 : while (enm != NULL) {
1038 0 : h = ether_crc32_be(enm->enm_addrlo,
1039 0 : ETHER_ADDR_LEN) >> 23;
1040 0 : hashtbl[h / 32] |= 1 << (h % 32);
1041 0 : ETHER_NEXT_MULTI(step, enm);
1042 : }
1043 : }
1044 :
1045 0 : mue_dataport_write(sc, MUE_DP_SEL_VHF, MUE_DP_SEL_VHF_VLAN_LEN,
1046 0 : MUE_DP_SEL_VHF_HASH_LEN, hashtbl);
1047 0 : mue_csr_write(sc, reg, rxfilt);
1048 0 : }
1049 :
1050 : void
1051 0 : mue_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1052 : {
1053 0 : struct mue_chain *c = (struct mue_chain *)priv;
1054 0 : struct mue_softc *sc = c->mue_sc;
1055 0 : struct ifnet *ifp = GET_IFP(sc);
1056 0 : struct mbuf_list ml = MBUF_LIST_INITIALIZER();
1057 : struct mbuf *m;
1058 0 : struct mue_rxbuf_hdr hdr;
1059 0 : u_char *buf = c->mue_buf;
1060 0 : uint32_t total_len;
1061 : int pktlen = 0;
1062 : int s;
1063 :
1064 0 : if (usbd_is_dying(sc->mue_udev))
1065 0 : return;
1066 :
1067 0 : if (!(ifp->if_flags & IFF_RUNNING))
1068 0 : return;
1069 :
1070 0 : if (status != USBD_NORMAL_COMPLETION) {
1071 0 : if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1072 0 : return;
1073 0 : if (usbd_ratecheck(&sc->mue_rx_notice)) {
1074 0 : printf("%s: usb errors on rx: %s\n",
1075 0 : sc->mue_dev.dv_xname, usbd_errstr(status));
1076 0 : }
1077 0 : if (status == USBD_STALLED)
1078 0 : usbd_clear_endpoint_stall_async(sc->mue_ep[MUE_ENDPT_RX]);
1079 : goto done;
1080 : }
1081 :
1082 0 : usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
1083 :
1084 0 : do {
1085 0 : if (total_len < sizeof(hdr)) {
1086 0 : ifp->if_ierrors++;
1087 0 : goto done;
1088 : }
1089 :
1090 0 : buf += pktlen;
1091 :
1092 0 : memcpy(&hdr, buf, sizeof(hdr));
1093 0 : total_len -= sizeof(hdr);
1094 :
1095 0 : if (letoh32(hdr.rx_cmd_a) & MUE_RX_CMD_A_RED) {
1096 0 : ifp->if_ierrors++;
1097 0 : goto done;
1098 : }
1099 :
1100 0 : pktlen = letoh32(hdr.rx_cmd_a) & MUE_RX_CMD_A_LEN_MASK;
1101 0 : if (sc->mue_flags & LAN7500)
1102 0 : pktlen -= 2;
1103 :
1104 0 : if (pktlen > total_len) {
1105 0 : ifp->if_ierrors++;
1106 0 : goto done;
1107 : }
1108 :
1109 0 : buf += sizeof(hdr);
1110 :
1111 0 : if (total_len < pktlen)
1112 0 : total_len = 0;
1113 : else
1114 0 : total_len -= pktlen;
1115 :
1116 0 : m = m_devget(buf, pktlen - ETHER_CRC_LEN, ETHER_ALIGN);
1117 0 : if (m == NULL) {
1118 : DPRINTF(("unable to allocate mbuf for next packet\n"));
1119 0 : ifp->if_ierrors++;
1120 0 : goto done;
1121 : }
1122 0 : ml_enqueue(&ml, m);
1123 0 : } while (total_len > 0);
1124 :
1125 : done:
1126 0 : s = splnet();
1127 0 : if_input(ifp, &ml);
1128 0 : splx(s);
1129 :
1130 0 : memset(c->mue_buf, 0, sc->mue_bufsz);
1131 :
1132 : /* Setup new transfer. */
1133 0 : usbd_setup_xfer(xfer, sc->mue_ep[MUE_ENDPT_RX],
1134 0 : c, c->mue_buf, sc->mue_bufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY,
1135 : USBD_NO_TIMEOUT, mue_rxeof);
1136 0 : usbd_transfer(xfer);
1137 :
1138 : DPRINTFN(10,("%s: %s: start rx\n", sc->mue_dev.dv_xname, __func__));
1139 0 : }
1140 :
1141 : void
1142 0 : mue_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1143 : {
1144 0 : struct mue_chain *c = priv;
1145 0 : struct mue_softc *sc = c->mue_sc;
1146 0 : struct ifnet *ifp = GET_IFP(sc);
1147 : int s;
1148 :
1149 0 : if (usbd_is_dying(sc->mue_udev))
1150 0 : return;
1151 :
1152 0 : s = splnet();
1153 :
1154 : DPRINTFN(10,("%s: %s: enter status=%d\n", sc->mue_dev.dv_xname,
1155 : __func__, status));
1156 :
1157 0 : if (status != USBD_NORMAL_COMPLETION) {
1158 0 : if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1159 0 : splx(s);
1160 0 : return;
1161 : }
1162 0 : ifp->if_oerrors++;
1163 0 : printf("%s: usb error on tx: %s\n", sc->mue_dev.dv_xname,
1164 0 : usbd_errstr(status));
1165 0 : if (status == USBD_STALLED)
1166 0 : usbd_clear_endpoint_stall_async(sc->mue_ep[MUE_ENDPT_TX]);
1167 0 : splx(s);
1168 0 : return;
1169 : }
1170 :
1171 0 : ifp->if_timer = 0;
1172 0 : ifq_clr_oactive(&ifp->if_snd);
1173 :
1174 0 : m_freem(c->mue_mbuf);
1175 0 : c->mue_mbuf = NULL;
1176 :
1177 0 : if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
1178 0 : mue_start(ifp);
1179 :
1180 0 : splx(s);
1181 0 : }
1182 :
1183 : void
1184 0 : mue_init(void *xsc)
1185 : {
1186 0 : struct mue_softc *sc = xsc;
1187 0 : struct ifnet *ifp = GET_IFP(sc);
1188 : int s;
1189 :
1190 0 : s = splnet();
1191 :
1192 : /* Cancel pending I/O and free all TX/RX buffers. */
1193 0 : mue_reset(sc);
1194 :
1195 : /* Set MAC address. */
1196 0 : mue_set_macaddr(sc);
1197 :
1198 : /* Init RX ring. */
1199 0 : if (mue_rx_list_init(sc) == ENOBUFS) {
1200 0 : printf("%s: rx list init failed\n", sc->mue_dev.dv_xname);
1201 0 : splx(s);
1202 0 : return;
1203 : }
1204 :
1205 : /* Init TX ring. */
1206 0 : if (mue_tx_list_init(sc) == ENOBUFS) {
1207 0 : printf("%s: tx list init failed\n", sc->mue_dev.dv_xname);
1208 0 : splx(s);
1209 0 : return;
1210 : }
1211 :
1212 : /* Program promiscuous mode and multicast filters. */
1213 0 : mue_iff(sc);
1214 :
1215 0 : if (mue_open_pipes(sc) != 0) {
1216 0 : splx(s);
1217 0 : return;
1218 : }
1219 :
1220 0 : sc->mue_link = 0;
1221 0 : ifp->if_flags |= IFF_RUNNING;
1222 0 : ifq_clr_oactive(&ifp->if_snd);
1223 :
1224 0 : splx(s);
1225 :
1226 0 : timeout_add_sec(&sc->mue_stat_ch, 1);
1227 0 : }
1228 :
1229 : int
1230 0 : mue_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1231 : {
1232 0 : struct mue_softc *sc = ifp->if_softc;
1233 0 : struct ifreq *ifr = (struct ifreq *)data;
1234 : int s, error = 0;
1235 :
1236 0 : s = splnet();
1237 :
1238 0 : switch(cmd) {
1239 : case SIOCSIFADDR:
1240 0 : ifp->if_flags |= IFF_UP;
1241 0 : if (!(ifp->if_flags & IFF_RUNNING))
1242 0 : mue_init(sc);
1243 : break;
1244 : case SIOCSIFFLAGS:
1245 0 : if (ifp->if_flags & IFF_UP) {
1246 0 : if (ifp->if_flags & IFF_RUNNING)
1247 0 : error = ENETRESET;
1248 : else
1249 0 : mue_init(sc);
1250 : } else {
1251 0 : if (ifp->if_flags & IFF_RUNNING)
1252 0 : mue_stop(sc);
1253 : }
1254 : break;
1255 : case SIOCGIFMEDIA:
1256 : case SIOCSIFMEDIA:
1257 0 : error = ifmedia_ioctl(ifp, ifr, &sc->mue_mii.mii_media, cmd);
1258 0 : break;
1259 : default:
1260 0 : error = ether_ioctl(ifp, &sc->arpcom, cmd, data);
1261 0 : }
1262 :
1263 0 : if (error == ENETRESET) {
1264 0 : if (ifp->if_flags & IFF_RUNNING)
1265 0 : mue_iff(sc);
1266 : error = 0;
1267 0 : }
1268 :
1269 0 : splx(s);
1270 :
1271 0 : return(error);
1272 : }
1273 :
1274 : void
1275 0 : mue_watchdog(struct ifnet *ifp)
1276 : {
1277 0 : struct mue_softc *sc = ifp->if_softc;
1278 : struct mue_chain *c;
1279 0 : usbd_status stat;
1280 : int s;
1281 :
1282 0 : ifp->if_oerrors++;
1283 0 : printf("%s: watchdog timeout\n", sc->mue_dev.dv_xname);
1284 :
1285 0 : s = splusb();
1286 0 : c = &sc->mue_cdata.mue_tx_chain[0];
1287 0 : usbd_get_xfer_status(c->mue_xfer, NULL, NULL, NULL, &stat);
1288 0 : mue_txeof(c->mue_xfer, c, stat);
1289 :
1290 0 : if (!IFQ_IS_EMPTY(&ifp->if_snd))
1291 0 : mue_start(ifp);
1292 0 : splx(s);
1293 0 : }
1294 :
1295 : void
1296 0 : mue_reset(struct mue_softc *sc)
1297 : {
1298 0 : if (usbd_is_dying(sc->mue_udev))
1299 : return;
1300 :
1301 : /* Wait a little while for the chip to get its brains in order. */
1302 0 : DELAY(1000);
1303 0 : }
1304 :
1305 : void
1306 0 : mue_start(struct ifnet *ifp)
1307 : {
1308 0 : struct mue_softc *sc = ifp->if_softc;
1309 : struct mbuf *m_head = NULL;
1310 :
1311 0 : if (!sc->mue_link)
1312 0 : return;
1313 :
1314 0 : if (ifq_is_oactive(&ifp->if_snd))
1315 0 : return;
1316 :
1317 0 : m_head = ifq_deq_begin(&ifp->if_snd);
1318 0 : if (m_head == NULL)
1319 0 : return;
1320 :
1321 0 : if (mue_encap(sc, m_head, 0)) {
1322 0 : ifq_deq_rollback(&ifp->if_snd, m_head);
1323 0 : ifq_set_oactive(&ifp->if_snd);
1324 0 : return;
1325 : }
1326 0 : ifq_deq_commit(&ifp->if_snd, m_head);
1327 :
1328 : /* If there's a BPF listener, bounce a copy of this frame to him. */
1329 : #if NBPFILTER > 0
1330 0 : if (ifp->if_bpf)
1331 0 : bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
1332 : #endif
1333 :
1334 0 : ifq_set_oactive(&ifp->if_snd);
1335 :
1336 : /* Set a timeout in case the chip goes out to lunch. */
1337 0 : ifp->if_timer = 5;
1338 0 : }
1339 :
1340 : void
1341 0 : mue_stop(struct mue_softc *sc)
1342 : {
1343 : struct ifnet *ifp;
1344 :
1345 0 : ifp = GET_IFP(sc);
1346 0 : ifp->if_timer = 0;
1347 0 : ifp->if_flags &= ~IFF_RUNNING;
1348 0 : ifq_clr_oactive(&ifp->if_snd);
1349 :
1350 0 : timeout_del(&sc->mue_stat_ch);
1351 :
1352 0 : sc->mue_link = 0;
1353 0 : }
1354 :
1355 : void
1356 0 : mue_tick(void *xsc)
1357 : {
1358 0 : struct mue_softc *sc = xsc;
1359 :
1360 0 : if (sc == NULL)
1361 0 : return;
1362 :
1363 0 : if (usbd_is_dying(sc->mue_udev))
1364 0 : return;
1365 :
1366 : /* Perform periodic stuff in process context. */
1367 0 : usb_add_task(sc->mue_udev, &sc->mue_tick_task);
1368 0 : }
1369 :
1370 : void
1371 0 : mue_tick_task(void *xsc)
1372 : {
1373 0 : struct mue_softc *sc =xsc;
1374 : struct mii_data *mii;
1375 : int s;
1376 :
1377 0 : if (sc == NULL)
1378 0 : return;
1379 :
1380 0 : if (usbd_is_dying(sc->mue_udev))
1381 0 : return;
1382 :
1383 0 : mii = GET_MII(sc);
1384 :
1385 0 : s = splnet();
1386 0 : mii_tick(mii);
1387 0 : if (sc->mue_link == 0)
1388 0 : mue_miibus_statchg(&sc->mue_dev);
1389 0 : timeout_add_sec(&sc->mue_stat_ch, 1);
1390 0 : splx(s);
1391 0 : }
|