1f9f848faSopenharmony_ci/*- 2f9f848faSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 3f9f848faSopenharmony_ci * 4f9f848faSopenharmony_ci * Copyright (c) 2013-2014 Kevin Lo 5f9f848faSopenharmony_ci * All rights reserved. 6f9f848faSopenharmony_ci * 7f9f848faSopenharmony_ci * Redistribution and use in source and binary forms, with or without 8f9f848faSopenharmony_ci * modification, are permitted provided that the following conditions 9f9f848faSopenharmony_ci * are met: 10f9f848faSopenharmony_ci * 1. Redistributions of source code must retain the above copyright 11f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer. 12f9f848faSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 13f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer in the 14f9f848faSopenharmony_ci * documentation and/or other materials provided with the distribution. 15f9f848faSopenharmony_ci * 16f9f848faSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17f9f848faSopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18f9f848faSopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19f9f848faSopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20f9f848faSopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21f9f848faSopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22f9f848faSopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23f9f848faSopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24f9f848faSopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25f9f848faSopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26f9f848faSopenharmony_ci * SUCH DAMAGE. 27f9f848faSopenharmony_ci */ 28f9f848faSopenharmony_ci 29f9f848faSopenharmony_ci#include <sys/cdefs.h> 30f9f848faSopenharmony_ci/* 31f9f848faSopenharmony_ci * ASIX Electronics AX88178A/AX88179/AX88179A USB 2.0/3.0 gigabit ethernet 32f9f848faSopenharmony_ci * driver. 33f9f848faSopenharmony_ci */ 34f9f848faSopenharmony_ci 35f9f848faSopenharmony_ci#include <lwip/netif.h> 36f9f848faSopenharmony_ci#include <lwip/dhcp.h> 37f9f848faSopenharmony_ci#include <lwip/netifapi.h> 38f9f848faSopenharmony_ci#include <lwip/inet.h> 39f9f848faSopenharmony_ci 40f9f848faSopenharmony_ci#include "implementation/global_implementation.h" 41f9f848faSopenharmony_ci#include "usb_ethernet.h" 42f9f848faSopenharmony_ci#include "if_axgereg.h" 43f9f848faSopenharmony_ci 44f9f848faSopenharmony_cistatic void axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen); 45f9f848faSopenharmony_cistatic void axge_miibus_statchg(struct axge_softc *sc, uint8_t link_status); 46f9f848faSopenharmony_ci 47f9f848faSopenharmony_ci#define IFF_DRV_OACTIVE IFF_MASTER 48f9f848faSopenharmony_ci#define IFF_SIMPLEX IFF_SLAVE 49f9f848faSopenharmony_ci 50f9f848faSopenharmony_ci#undef USB_DEBUG_VAR 51f9f848faSopenharmony_ci#define USB_DEBUG_VAR axge_debug 52f9f848faSopenharmony_ci#ifdef LOSCFG_USB_DEBUG 53f9f848faSopenharmony_cistatic int axge_debug = 0; 54f9f848faSopenharmony_civoid 55f9f848faSopenharmony_ciusb_axge_debug_func(int level) 56f9f848faSopenharmony_ci{ 57f9f848faSopenharmony_ci axge_debug = level; 58f9f848faSopenharmony_ci PRINTK("The level of usb axge debug is %d\n", level); 59f9f848faSopenharmony_ci} 60f9f848faSopenharmony_ciDEBUG_MODULE(axge, usb_axge_debug_func); 61f9f848faSopenharmony_ci#endif 62f9f848faSopenharmony_ci 63f9f848faSopenharmony_ci/* 64f9f848faSopenharmony_ci * Various supported device vendors/products. 65f9f848faSopenharmony_ci */ 66f9f848faSopenharmony_cistatic const STRUCT_USB_HOST_ID axge_devs[] = { 67f9f848faSopenharmony_ci { USB_VPI(0x0B95, 0x178A, AXE_FLAG_178A) }, 68f9f848faSopenharmony_ci}; 69f9f848faSopenharmony_ci 70f9f848faSopenharmony_cistatic device_probe_t axge_probe; 71f9f848faSopenharmony_cistatic device_attach_t axge_attach; 72f9f848faSopenharmony_cistatic device_detach_t axge_detach; 73f9f848faSopenharmony_ci 74f9f848faSopenharmony_cistatic usb_callback_t axge_bulk_read_callback; 75f9f848faSopenharmony_cistatic usb_callback_t axge_bulk_write_callback; 76f9f848faSopenharmony_ci 77f9f848faSopenharmony_cistatic uether_fn_t axge_attach_post; 78f9f848faSopenharmony_cistatic uether_fn_t axge_init; 79f9f848faSopenharmony_cistatic uether_fn_t axge_stop; 80f9f848faSopenharmony_cistatic uether_fn_t axge_start; 81f9f848faSopenharmony_cistatic uether_fn_t axge_setmulti; 82f9f848faSopenharmony_cistatic uether_fn_t axge_setpromisc; 83f9f848faSopenharmony_cistatic uether_fn_t axge_tick; 84f9f848faSopenharmony_ci 85f9f848faSopenharmony_cistatic const struct usb_config axge_config[AXGE_N_TRANSFER] = { 86f9f848faSopenharmony_ci { /* [AXGE_BULK_DT_WR] = */ 87f9f848faSopenharmony_ci .type = UE_BULK, 88f9f848faSopenharmony_ci .endpoint = UE_ADDR_ANY, 89f9f848faSopenharmony_ci .direction = UE_DIR_OUT, 90f9f848faSopenharmony_ci .frames = 16, 91f9f848faSopenharmony_ci .bufsize = 16 * MCLBYTES, 92f9f848faSopenharmony_ci .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 93f9f848faSopenharmony_ci .callback = axge_bulk_write_callback, 94f9f848faSopenharmony_ci .timeout = 10000, /* 10 seconds */ 95f9f848faSopenharmony_ci }, 96f9f848faSopenharmony_ci { /* [AXGE_BULK_DT_RD] = */ 97f9f848faSopenharmony_ci .type = UE_BULK, 98f9f848faSopenharmony_ci .endpoint = UE_ADDR_ANY, 99f9f848faSopenharmony_ci .direction = UE_DIR_IN, 100f9f848faSopenharmony_ci .bufsize = 16 * MCLBYTES, /* bytes */ 101f9f848faSopenharmony_ci .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 102f9f848faSopenharmony_ci .callback = axge_bulk_read_callback, 103f9f848faSopenharmony_ci .timeout = 0, /* no timeout */ 104f9f848faSopenharmony_ci }, 105f9f848faSopenharmony_ci}; 106f9f848faSopenharmony_ci 107f9f848faSopenharmony_cistatic const struct { 108f9f848faSopenharmony_ci uint8_t ctrl; 109f9f848faSopenharmony_ci uint8_t timer_l; 110f9f848faSopenharmony_ci uint8_t timer_h; 111f9f848faSopenharmony_ci uint8_t size; 112f9f848faSopenharmony_ci uint8_t ifg; 113f9f848faSopenharmony_ci}__packed axge_bulk_size[] = { 114f9f848faSopenharmony_ci { 7, 0x4f, 0x00, 0x12, 0xff }, 115f9f848faSopenharmony_ci { 7, 0x20, 0x03, 0x16, 0xff }, 116f9f848faSopenharmony_ci { 7, 0xae, 0x07, 0x18, 0xff }, 117f9f848faSopenharmony_ci { 7, 0xcc, 0x4c, 0x18, 0x08 } 118f9f848faSopenharmony_ci}; 119f9f848faSopenharmony_ci 120f9f848faSopenharmony_cistatic device_method_t axge_methods[] = { 121f9f848faSopenharmony_ci /* Device interface */ 122f9f848faSopenharmony_ci DEVMETHOD(device_probe, axge_probe), 123f9f848faSopenharmony_ci DEVMETHOD(device_attach, axge_attach), 124f9f848faSopenharmony_ci DEVMETHOD(device_detach, axge_detach), 125f9f848faSopenharmony_ci DEVMETHOD_END 126f9f848faSopenharmony_ci}; 127f9f848faSopenharmony_ci 128f9f848faSopenharmony_cistatic driver_t axge_driver = { 129f9f848faSopenharmony_ci .name = "USB_AXGE", 130f9f848faSopenharmony_ci .methods = axge_methods, 131f9f848faSopenharmony_ci .size = sizeof(struct axge_softc), 132f9f848faSopenharmony_ci}; 133f9f848faSopenharmony_ci 134f9f848faSopenharmony_cistatic devclass_t axge_devclass; 135f9f848faSopenharmony_ciDRIVER_MODULE(axge, uhub, axge_driver, axge_devclass, 0, 0); 136f9f848faSopenharmony_ci 137f9f848faSopenharmony_cistatic const struct usb_ether_methods axge_ue_methods = { 138f9f848faSopenharmony_ci .ue_attach_post = axge_attach_post, 139f9f848faSopenharmony_ci .ue_start = axge_start, 140f9f848faSopenharmony_ci .ue_init = axge_init, 141f9f848faSopenharmony_ci .ue_stop = axge_stop, 142f9f848faSopenharmony_ci .ue_setmulti = axge_setmulti, 143f9f848faSopenharmony_ci .ue_setpromisc = axge_setpromisc, 144f9f848faSopenharmony_ci .ue_tick = axge_tick, 145f9f848faSopenharmony_ci}; 146f9f848faSopenharmony_ci 147f9f848faSopenharmony_cistatic void 148f9f848faSopenharmony_ciaxge_write_mem(struct axge_softc *sc, uint8_t cmd, uint16_t index, 149f9f848faSopenharmony_ci uint16_t val, void *buf, unsigned int len) 150f9f848faSopenharmony_ci{ 151f9f848faSopenharmony_ci struct usb_device_request req; 152f9f848faSopenharmony_ci 153f9f848faSopenharmony_ci req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 154f9f848faSopenharmony_ci req.bRequest = cmd; 155f9f848faSopenharmony_ci USETW(req.wValue, val); 156f9f848faSopenharmony_ci USETW(req.wIndex, index); 157f9f848faSopenharmony_ci USETW(req.wLength, len); 158f9f848faSopenharmony_ci 159f9f848faSopenharmony_ci if (uether_do_request(&sc->sc_ue, &req, buf, 1000)) { 160f9f848faSopenharmony_ci /* Error ignored. */ 161f9f848faSopenharmony_ci } 162f9f848faSopenharmony_ci} 163f9f848faSopenharmony_ci 164f9f848faSopenharmony_cistatic void 165f9f848faSopenharmony_ciaxge_write_cmd_1(struct axge_softc *sc, uint8_t cmd, uint16_t reg, uint8_t val) 166f9f848faSopenharmony_ci{ 167f9f848faSopenharmony_ci axge_write_mem(sc, cmd, 1, reg, &val, 1); 168f9f848faSopenharmony_ci} 169f9f848faSopenharmony_ci 170f9f848faSopenharmony_cistatic void 171f9f848faSopenharmony_ciaxge_write_cmd_2(struct axge_softc *sc, uint8_t cmd, uint16_t index, 172f9f848faSopenharmony_ci uint16_t reg, uint16_t val) 173f9f848faSopenharmony_ci{ 174f9f848faSopenharmony_ci uint8_t temp[2]; 175f9f848faSopenharmony_ci 176f9f848faSopenharmony_ci USETW(temp, val); 177f9f848faSopenharmony_ci axge_write_mem(sc, cmd, index, reg, &temp, 2); 178f9f848faSopenharmony_ci} 179f9f848faSopenharmony_ci 180f9f848faSopenharmony_ci 181f9f848faSopenharmony_cistatic int 182f9f848faSopenharmony_ciaxge_read_mem(struct axge_softc *sc, uint8_t cmd, uint16_t index, 183f9f848faSopenharmony_ci uint16_t val, void *buf, int len) 184f9f848faSopenharmony_ci{ 185f9f848faSopenharmony_ci struct usb_device_request req; 186f9f848faSopenharmony_ci 187f9f848faSopenharmony_ci AXGE_LOCK_ASSERT(sc, MA_OWNED); 188f9f848faSopenharmony_ci 189f9f848faSopenharmony_ci req.bmRequestType = UT_READ_VENDOR_DEVICE; 190f9f848faSopenharmony_ci req.bRequest = cmd; 191f9f848faSopenharmony_ci USETW(req.wValue, val); 192f9f848faSopenharmony_ci USETW(req.wIndex, index); 193f9f848faSopenharmony_ci USETW(req.wLength, len); 194f9f848faSopenharmony_ci 195f9f848faSopenharmony_ci return (uether_do_request(&sc->sc_ue, &req, buf, 1000)); 196f9f848faSopenharmony_ci} 197f9f848faSopenharmony_ci 198f9f848faSopenharmony_cistatic uint8_t 199f9f848faSopenharmony_ciaxge_read_cmd_1(struct axge_softc *sc, uint8_t cmd, uint16_t reg) 200f9f848faSopenharmony_ci{ 201f9f848faSopenharmony_ci uint8_t val; 202f9f848faSopenharmony_ci 203f9f848faSopenharmony_ci (void)axge_read_mem(sc, cmd, 1, reg, &val, 1); 204f9f848faSopenharmony_ci return (val); 205f9f848faSopenharmony_ci} 206f9f848faSopenharmony_ci 207f9f848faSopenharmony_cistatic uint16_t 208f9f848faSopenharmony_ciaxge_read_cmd_2(struct axge_softc *sc, uint8_t cmd, uint16_t index, uint16_t reg) 209f9f848faSopenharmony_ci{ 210f9f848faSopenharmony_ci uint8_t val[2]; 211f9f848faSopenharmony_ci 212f9f848faSopenharmony_ci (void)axge_read_mem(sc, cmd, index, reg, &val, 2); 213f9f848faSopenharmony_ci return (UGETW(val)); 214f9f848faSopenharmony_ci} 215f9f848faSopenharmony_ci 216f9f848faSopenharmony_cistatic void 217f9f848faSopenharmony_ciaxge_chip_init(struct axge_softc *sc) 218f9f848faSopenharmony_ci{ 219f9f848faSopenharmony_ci /* Power up ethernet PHY. */ 220f9f848faSopenharmony_ci axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_EPPRCR, 0); 221f9f848faSopenharmony_ci axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_EPPRCR, EPPRCR_IPRL); 222f9f848faSopenharmony_ci (void)uether_pause(&sc->sc_ue, hz / 4); 223f9f848faSopenharmony_ci axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_CLK_SELECT, 224f9f848faSopenharmony_ci AXGE_CLK_SELECT_ACS | AXGE_CLK_SELECT_BCS); 225f9f848faSopenharmony_ci (void)uether_pause(&sc->sc_ue, hz / 10); 226f9f848faSopenharmony_ci} 227f9f848faSopenharmony_ci 228f9f848faSopenharmony_cistatic void 229f9f848faSopenharmony_ciaxge_csum_cfg(struct usb_ether *ue) 230f9f848faSopenharmony_ci{ 231f9f848faSopenharmony_ci struct axge_softc *sc = ue->ue_sc; 232f9f848faSopenharmony_ci uint8_t csum; 233f9f848faSopenharmony_ci 234f9f848faSopenharmony_ci csum = 0; 235f9f848faSopenharmony_ci csum |= CTCR_IP | CTCR_TCP | CTCR_UDP; 236f9f848faSopenharmony_ci axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_CTCR, csum); 237f9f848faSopenharmony_ci 238f9f848faSopenharmony_ci csum = 0; 239f9f848faSopenharmony_ci csum |= CRCR_IP | CRCR_TCP | CRCR_UDP; 240f9f848faSopenharmony_ci axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_CRCR, csum); 241f9f848faSopenharmony_ci} 242f9f848faSopenharmony_ci 243f9f848faSopenharmony_cistatic void 244f9f848faSopenharmony_ciaxge_setmulti(struct usb_ether *ue) 245f9f848faSopenharmony_ci{ 246f9f848faSopenharmony_ci struct axge_softc *sc = ue->ue_sc; 247f9f848faSopenharmony_ci struct los_eth_driver *ifp = ue->ue_drv_sc; 248f9f848faSopenharmony_ci uint16_t rxmode; 249f9f848faSopenharmony_ci 250f9f848faSopenharmony_ci rxmode = axge_read_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR); 251f9f848faSopenharmony_ci if (ifp->ac_if.flags & (IFF_ALLMULTI | IFF_PROMISC)) { 252f9f848faSopenharmony_ci rxmode |= RCR_AMALL; 253f9f848faSopenharmony_ci axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode); 254f9f848faSopenharmony_ci return; 255f9f848faSopenharmony_ci } 256f9f848faSopenharmony_ci 257f9f848faSopenharmony_ci rxmode &= ~RCR_AMALL; 258f9f848faSopenharmony_ci axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode); 259f9f848faSopenharmony_ci} 260f9f848faSopenharmony_ci 261f9f848faSopenharmony_cistatic void 262f9f848faSopenharmony_ciaxge_setpromisc(struct usb_ether *ue) 263f9f848faSopenharmony_ci{ 264f9f848faSopenharmony_ci struct axge_softc *sc = uether_getsc(ue); 265f9f848faSopenharmony_ci struct los_eth_driver *ifp = ue->ue_drv_sc; 266f9f848faSopenharmony_ci uint16_t rxmode; 267f9f848faSopenharmony_ci 268f9f848faSopenharmony_ci rxmode = axge_read_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR); 269f9f848faSopenharmony_ci 270f9f848faSopenharmony_ci if (ifp->ac_if.flags & IFF_PROMISC) 271f9f848faSopenharmony_ci rxmode |= RCR_PRO; 272f9f848faSopenharmony_ci else 273f9f848faSopenharmony_ci rxmode &= ~RCR_PRO; 274f9f848faSopenharmony_ci 275f9f848faSopenharmony_ci axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode); 276f9f848faSopenharmony_ci axge_setmulti(ue); 277f9f848faSopenharmony_ci} 278f9f848faSopenharmony_ci 279f9f848faSopenharmony_cistatic void 280f9f848faSopenharmony_ciaxge_tick(struct usb_ether *ue) 281f9f848faSopenharmony_ci{ 282f9f848faSopenharmony_ci struct axge_softc *sc = uether_getsc(ue); 283f9f848faSopenharmony_ci uint8_t link_status; 284f9f848faSopenharmony_ci 285f9f848faSopenharmony_ci AXGE_LOCK_ASSERT(sc, MA_OWNED); 286f9f848faSopenharmony_ci 287f9f848faSopenharmony_ci link_status = axge_read_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_PLSR); 288f9f848faSopenharmony_ci 289f9f848faSopenharmony_ci if (sc->sc_link_status != (link_status & AXGE_LINK_MASK)) { 290f9f848faSopenharmony_ci axge_miibus_statchg(sc, link_status); 291f9f848faSopenharmony_ci sc->sc_link_status = link_status & AXGE_LINK_MASK; 292f9f848faSopenharmony_ci } 293f9f848faSopenharmony_ci} 294f9f848faSopenharmony_ci 295f9f848faSopenharmony_cistatic void 296f9f848faSopenharmony_ciaxge_reset(struct axge_softc *sc) 297f9f848faSopenharmony_ci{ 298f9f848faSopenharmony_ci struct usb_config_descriptor *cd; 299f9f848faSopenharmony_ci usb_error_t err; 300f9f848faSopenharmony_ci 301f9f848faSopenharmony_ci cd = usbd_get_config_descriptor(sc->sc_ue.ue_udev); 302f9f848faSopenharmony_ci 303f9f848faSopenharmony_ci err = usbd_req_set_config(sc->sc_ue.ue_udev, &sc->sc_mtx, 304f9f848faSopenharmony_ci cd->bConfigurationValue); 305f9f848faSopenharmony_ci if (err) 306f9f848faSopenharmony_ci DPRINTF("reset failed (ignored)\n"); 307f9f848faSopenharmony_ci 308f9f848faSopenharmony_ci /* Wait a little while for the chip to get its brains in order. */ 309f9f848faSopenharmony_ci (void)uether_pause(&sc->sc_ue, hz / 100); 310f9f848faSopenharmony_ci 311f9f848faSopenharmony_ci axge_chip_init(sc); 312f9f848faSopenharmony_ci} 313f9f848faSopenharmony_ci 314f9f848faSopenharmony_cistatic void 315f9f848faSopenharmony_ciaxge_attach_post(struct usb_ether *ue) 316f9f848faSopenharmony_ci{ 317f9f848faSopenharmony_ci struct axge_softc *sc = uether_getsc(ue); 318f9f848faSopenharmony_ci 319f9f848faSopenharmony_ci /* Initialize controller and get station address. */ 320f9f848faSopenharmony_ci axge_chip_init(sc); 321f9f848faSopenharmony_ci (void)axge_read_mem(sc, AXGE_ACCESS_MAC, NETIF_MAX_HWADDR_LEN, AXGE_NIDR, 322f9f848faSopenharmony_ci ue->ue_eaddr, NETIF_MAX_HWADDR_LEN); 323f9f848faSopenharmony_ci} 324f9f848faSopenharmony_ci/* 325f9f848faSopenharmony_ci * Probe for a AX88172 chip. 326f9f848faSopenharmony_ci */ 327f9f848faSopenharmony_cistatic int 328f9f848faSopenharmony_ciaxge_probe(device_t dev) 329f9f848faSopenharmony_ci{ 330f9f848faSopenharmony_ci struct usb_attach_arg *uaa = device_get_ivars(dev); 331f9f848faSopenharmony_ci 332f9f848faSopenharmony_ci if (uaa->usb_mode != USB_MODE_HOST) 333f9f848faSopenharmony_ci return (ENXIO); 334f9f848faSopenharmony_ci if (uaa->info.bConfigIndex != AXGE_CONFIG_IDX) 335f9f848faSopenharmony_ci return (ENXIO); 336f9f848faSopenharmony_ci if (uaa->info.bIfaceIndex != AXGE_IFACE_IDX) 337f9f848faSopenharmony_ci return (ENXIO); 338f9f848faSopenharmony_ci 339f9f848faSopenharmony_ci return (usbd_lookup_id_by_uaa(axge_devs, sizeof(axge_devs), uaa)); 340f9f848faSopenharmony_ci} 341f9f848faSopenharmony_ci 342f9f848faSopenharmony_ci/* 343f9f848faSopenharmony_ci * Attach the interface. Allocate softc structures, do ifmedia 344f9f848faSopenharmony_ci * setup and ethernet/BPF attach. 345f9f848faSopenharmony_ci */ 346f9f848faSopenharmony_cistatic int 347f9f848faSopenharmony_ciaxge_attach(device_t dev) 348f9f848faSopenharmony_ci{ 349f9f848faSopenharmony_ci struct usb_attach_arg *uaa = device_get_ivars(dev); 350f9f848faSopenharmony_ci struct axge_softc *sc = device_get_softc(dev); 351f9f848faSopenharmony_ci struct usb_ether *ue = &sc->sc_ue; 352f9f848faSopenharmony_ci uint8_t iface_index; 353f9f848faSopenharmony_ci int error; 354f9f848faSopenharmony_ci sc->sc_flags = USB_GET_DRIVER_INFO(uaa); 355f9f848faSopenharmony_ci sc->sc_link_status = AXGE_LINK_MASK; 356f9f848faSopenharmony_ci 357f9f848faSopenharmony_ci device_set_usb_desc(dev); 358f9f848faSopenharmony_ci mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_RECURSE); 359f9f848faSopenharmony_ci 360f9f848faSopenharmony_ci iface_index = AXGE_IFACE_IDX; 361f9f848faSopenharmony_ci error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, 362f9f848faSopenharmony_ci axge_config, AXGE_N_TRANSFER, sc, &sc->sc_mtx); 363f9f848faSopenharmony_ci if (error) { 364f9f848faSopenharmony_ci device_printf(dev, "allocating USB transfers failed\n"); 365f9f848faSopenharmony_ci goto detach; 366f9f848faSopenharmony_ci } 367f9f848faSopenharmony_ci ue->ue_sc = sc; 368f9f848faSopenharmony_ci ue->ue_dev = dev; 369f9f848faSopenharmony_ci ue->ue_udev = uaa->device; 370f9f848faSopenharmony_ci ue->ue_mtx = &sc->sc_mtx; 371f9f848faSopenharmony_ci ue->ue_methods = &axge_ue_methods; 372f9f848faSopenharmony_ci error = uether_ifattach(ue); 373f9f848faSopenharmony_ci if (error) { 374f9f848faSopenharmony_ci device_printf(dev, "could not attach interface\n"); 375f9f848faSopenharmony_ci goto detach; 376f9f848faSopenharmony_ci } 377f9f848faSopenharmony_ci return (0); /* success */ 378f9f848faSopenharmony_ci 379f9f848faSopenharmony_cidetach: 380f9f848faSopenharmony_ci (void) axge_detach(dev); 381f9f848faSopenharmony_ci return (ENXIO); /* failure */ 382f9f848faSopenharmony_ci} 383f9f848faSopenharmony_ci 384f9f848faSopenharmony_cistatic int 385f9f848faSopenharmony_ciaxge_detach(device_t dev) 386f9f848faSopenharmony_ci{ 387f9f848faSopenharmony_ci struct axge_softc *sc = device_get_softc(dev); 388f9f848faSopenharmony_ci struct usb_ether *ue = &sc->sc_ue; 389f9f848faSopenharmony_ci 390f9f848faSopenharmony_ci usbd_transfer_unsetup(sc->sc_xfer, AXGE_N_TRANSFER); 391f9f848faSopenharmony_ci uether_ifdetach(ue); 392f9f848faSopenharmony_ci mtx_destroy(&sc->sc_mtx); 393f9f848faSopenharmony_ci 394f9f848faSopenharmony_ci return (0); 395f9f848faSopenharmony_ci} 396f9f848faSopenharmony_ci 397f9f848faSopenharmony_cistatic void 398f9f848faSopenharmony_ciaxge_miibus_statchg(struct axge_softc *sc, uint8_t link_status) 399f9f848faSopenharmony_ci{ 400f9f848faSopenharmony_ci struct usb_ether *ue = &sc->sc_ue; 401f9f848faSopenharmony_ci struct los_eth_driver *ifp = ue->ue_drv_sc; 402f9f848faSopenharmony_ci uint8_t tmp[5]; 403f9f848faSopenharmony_ci uint16_t val = 0; 404f9f848faSopenharmony_ci 405f9f848faSopenharmony_ci if (link_status & AXGE_LINK_MASK) { 406f9f848faSopenharmony_ci val = MSR_RE; 407f9f848faSopenharmony_ci if (link_status & IFM_1000_T) { 408f9f848faSopenharmony_ci val |= MSR_GM | MSR_EN_125MHZ; 409f9f848faSopenharmony_ci if (link_status & PLSR_USB_SS) 410f9f848faSopenharmony_ci (void)memcpy_s(tmp, sizeof(tmp), &axge_bulk_size[0], sizeof(axge_bulk_size[0])); 411f9f848faSopenharmony_ci else if (link_status & PLSR_USB_HS) 412f9f848faSopenharmony_ci (void)memcpy_s(tmp, sizeof(tmp), &axge_bulk_size[1], sizeof(axge_bulk_size[1])); 413f9f848faSopenharmony_ci else 414f9f848faSopenharmony_ci (void)memcpy_s(tmp, sizeof(tmp), &axge_bulk_size[3], sizeof(axge_bulk_size[3])); 415f9f848faSopenharmony_ci } 416f9f848faSopenharmony_ci else if (link_status & IFM_100_TX) { 417f9f848faSopenharmony_ci val |= MSR_PS; 418f9f848faSopenharmony_ci if (link_status & (PLSR_USB_SS | PLSR_USB_HS)) 419f9f848faSopenharmony_ci (void)memcpy_s(tmp, sizeof(tmp), &axge_bulk_size[2], sizeof(axge_bulk_size[2])); 420f9f848faSopenharmony_ci else 421f9f848faSopenharmony_ci (void)memcpy_s(tmp, sizeof(tmp), &axge_bulk_size[3], sizeof(axge_bulk_size[3])); 422f9f848faSopenharmony_ci } 423f9f848faSopenharmony_ci else if (link_status & IFM_10_T) { 424f9f848faSopenharmony_ci (void)memcpy_s(tmp, sizeof(tmp), &axge_bulk_size[3], sizeof(axge_bulk_size[3])); 425f9f848faSopenharmony_ci } 426f9f848faSopenharmony_ci else { 427f9f848faSopenharmony_ci PRINT_WARN("%s, link_status:%x\n", __FUNCTION__, link_status); 428f9f848faSopenharmony_ci return; 429f9f848faSopenharmony_ci } 430f9f848faSopenharmony_ci 431f9f848faSopenharmony_ci /* Rx bulk configuration. */ 432f9f848faSopenharmony_ci axge_write_mem(sc, AXGE_ACCESS_MAC, 5, AXGE_RX_BULKIN_QCTRL, tmp, 5); 433f9f848faSopenharmony_ci axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_MSR, val); 434f9f848faSopenharmony_ci 435f9f848faSopenharmony_ci ifp->ac_if.flags |= NETIF_FLAG_LINK_UP; 436f9f848faSopenharmony_ci 437f9f848faSopenharmony_ci (void)netifapi_netif_set_up(&ifp->ac_if); 438f9f848faSopenharmony_ci PRINTK("AX88178A Link Up\n"); 439f9f848faSopenharmony_ci } 440f9f848faSopenharmony_ci else { 441f9f848faSopenharmony_ci ifp->ac_if.flags &= ~NETIF_FLAG_LINK_UP; 442f9f848faSopenharmony_ci PRINTK("AX88178A Link Down\n"); 443f9f848faSopenharmony_ci } 444f9f848faSopenharmony_ci} 445f9f848faSopenharmony_ci 446f9f848faSopenharmony_cistatic void 447f9f848faSopenharmony_ciaxge_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 448f9f848faSopenharmony_ci{ 449f9f848faSopenharmony_ci struct axge_softc *sc = usbd_xfer_softc(xfer); 450f9f848faSopenharmony_ci struct usb_ether *ue = &sc->sc_ue; 451f9f848faSopenharmony_ci struct usb_page_cache *pc; 452f9f848faSopenharmony_ci int actlen; 453f9f848faSopenharmony_ci 454f9f848faSopenharmony_ci usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 455f9f848faSopenharmony_ci switch (USB_GET_STATE(xfer)) { 456f9f848faSopenharmony_ci case USB_ST_TRANSFERRED: 457f9f848faSopenharmony_ci pc = usbd_xfer_get_frame(xfer, 0); 458f9f848faSopenharmony_ci axge_rx_frame(ue, pc, actlen); 459f9f848faSopenharmony_ci /* FALLTHROUGH */ 460f9f848faSopenharmony_ci case USB_ST_SETUP: 461f9f848faSopenharmony_citr_setup: 462f9f848faSopenharmony_ci usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 463f9f848faSopenharmony_ci usbd_transfer_submit(xfer); 464f9f848faSopenharmony_ci uether_rxflush(ue); 465f9f848faSopenharmony_ci return; 466f9f848faSopenharmony_ci 467f9f848faSopenharmony_ci default: /* Error */ 468f9f848faSopenharmony_ci DPRINTF("bulk read error, %s\n", usbd_errstr(error)); 469f9f848faSopenharmony_ci 470f9f848faSopenharmony_ci if (error != USB_ERR_CANCELLED) { 471f9f848faSopenharmony_ci /* try to clear stall first */ 472f9f848faSopenharmony_ci usbd_xfer_set_stall(xfer); 473f9f848faSopenharmony_ci goto tr_setup; 474f9f848faSopenharmony_ci } 475f9f848faSopenharmony_ci return; 476f9f848faSopenharmony_ci } 477f9f848faSopenharmony_ci} 478f9f848faSopenharmony_ci 479f9f848faSopenharmony_cistatic int 480f9f848faSopenharmony_ciaxge_rxeof(struct usb_ether *ue, struct usb_page_cache *pc, unsigned int offset, 481f9f848faSopenharmony_ci unsigned int len, uint32_t pkt_hdr) 482f9f848faSopenharmony_ci{ 483f9f848faSopenharmony_ci struct los_eth_driver *ifp = ue->ue_drv_sc; 484f9f848faSopenharmony_ci struct pbuf *m = pbuf_alloc(PBUF_RAW, len+ETH_PAD_SIZE, PBUF_RAM); 485f9f848faSopenharmony_ci struct pbuf *p; 486f9f848faSopenharmony_ci 487f9f848faSopenharmony_ci if (len < ETHER_HDR_LEN) { 488f9f848faSopenharmony_ci (void)pbuf_free(m); 489f9f848faSopenharmony_ci return (EINVAL); 490f9f848faSopenharmony_ci } 491f9f848faSopenharmony_ci 492f9f848faSopenharmony_ci#if ETH_PAD_SIZE 493f9f848faSopenharmony_ci /* drop the padding word */ 494f9f848faSopenharmony_ci if (pbuf_header(m, -ETH_PAD_SIZE)) { 495f9f848faSopenharmony_ci PRINTK("[AXE_ERROR]axe_rxeof : pbuf_header drop failed\n"); 496f9f848faSopenharmony_ci (void)pbuf_free(m); 497f9f848faSopenharmony_ci return (EINVAL); 498f9f848faSopenharmony_ci } 499f9f848faSopenharmony_ci#endif 500f9f848faSopenharmony_ci 501f9f848faSopenharmony_ci for (p = m; p != NULL; p = p->next) 502f9f848faSopenharmony_ci usbd_copy_out(pc, offset, p->payload, p->len); 503f9f848faSopenharmony_ci 504f9f848faSopenharmony_ci#if ETH_PAD_SIZE 505f9f848faSopenharmony_ci /* reclaim the padding word */ 506f9f848faSopenharmony_ci if (pbuf_header(m, ETH_PAD_SIZE)) { 507f9f848faSopenharmony_ci PRINTK("[AXE_ERROR]axe_rxeof : pbuf_header drop failed\n"); 508f9f848faSopenharmony_ci (void)pbuf_free(m); 509f9f848faSopenharmony_ci return (EINVAL); 510f9f848faSopenharmony_ci } 511f9f848faSopenharmony_ci#endif 512f9f848faSopenharmony_ci 513f9f848faSopenharmony_ci driverif_input(&ifp->ac_if, m); 514f9f848faSopenharmony_ci return (0); 515f9f848faSopenharmony_ci} 516f9f848faSopenharmony_ci 517f9f848faSopenharmony_cistatic void 518f9f848faSopenharmony_ciaxge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen) 519f9f848faSopenharmony_ci{ 520f9f848faSopenharmony_ci uint32_t pos; 521f9f848faSopenharmony_ci uint32_t pkt_cnt; 522f9f848faSopenharmony_ci uint32_t rxhdr; 523f9f848faSopenharmony_ci uint32_t pkt_hdr; 524f9f848faSopenharmony_ci uint32_t hdr_off; 525f9f848faSopenharmony_ci uint32_t pktlen; 526f9f848faSopenharmony_ci 527f9f848faSopenharmony_ci /* verify we have enough data */ 528f9f848faSopenharmony_ci if (actlen < (int)sizeof(rxhdr)) 529f9f848faSopenharmony_ci return; 530f9f848faSopenharmony_ci 531f9f848faSopenharmony_ci pos = 0; 532f9f848faSopenharmony_ci 533f9f848faSopenharmony_ci usbd_copy_out(pc, actlen - sizeof(rxhdr), &rxhdr, sizeof(rxhdr)); 534f9f848faSopenharmony_ci rxhdr = le32toh(rxhdr); 535f9f848faSopenharmony_ci 536f9f848faSopenharmony_ci pkt_cnt = (uint16_t)rxhdr; 537f9f848faSopenharmony_ci hdr_off = (uint16_t)(rxhdr >> 16); 538f9f848faSopenharmony_ci 539f9f848faSopenharmony_ci while (pkt_cnt--) { 540f9f848faSopenharmony_ci /* verify the header offset */ 541f9f848faSopenharmony_ci if ((int)(hdr_off + sizeof(pkt_hdr)) > actlen) { 542f9f848faSopenharmony_ci DPRINTF("End of packet headers\n"); 543f9f848faSopenharmony_ci break; 544f9f848faSopenharmony_ci } 545f9f848faSopenharmony_ci if ((int)pos >= actlen) { 546f9f848faSopenharmony_ci DPRINTF("Data position reached end\n"); 547f9f848faSopenharmony_ci break; 548f9f848faSopenharmony_ci } 549f9f848faSopenharmony_ci usbd_copy_out(pc, hdr_off, &pkt_hdr, sizeof(pkt_hdr)); 550f9f848faSopenharmony_ci 551f9f848faSopenharmony_ci pkt_hdr = le32toh(pkt_hdr); 552f9f848faSopenharmony_ci pktlen = (pkt_hdr >> 16) & 0x1fff; 553f9f848faSopenharmony_ci if (pkt_hdr & (AXGE_RXHDR_CRC_ERR | AXGE_RXHDR_DROP_ERR)) { 554f9f848faSopenharmony_ci DPRINTF("Dropped a packet\n"); 555f9f848faSopenharmony_ci } 556f9f848faSopenharmony_ci if (pktlen >= 6 && (int)(pos + pktlen) <= actlen) { 557f9f848faSopenharmony_ci (void)axge_rxeof(ue, pc, pos, pktlen, pkt_hdr); 558f9f848faSopenharmony_ci } else { 559f9f848faSopenharmony_ci DPRINTF("Invalid packet pos=%d len=%d\n", 560f9f848faSopenharmony_ci (int)pos, (int)pktlen); 561f9f848faSopenharmony_ci } 562f9f848faSopenharmony_ci pos += (pktlen + 7) & ~7; 563f9f848faSopenharmony_ci hdr_off += sizeof(pkt_hdr); 564f9f848faSopenharmony_ci } 565f9f848faSopenharmony_ci} 566f9f848faSopenharmony_ci 567f9f848faSopenharmony_cistatic void 568f9f848faSopenharmony_ciaxge_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 569f9f848faSopenharmony_ci{ 570f9f848faSopenharmony_ci struct axge_softc *sc = usbd_xfer_softc(xfer); 571f9f848faSopenharmony_ci struct usb_ether *ue = &(sc->sc_ue); 572f9f848faSopenharmony_ci struct los_eth_driver *ifp = ue->ue_drv_sc; 573f9f848faSopenharmony_ci struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)ifp->driver_context; 574f9f848faSopenharmony_ci struct usb_page_cache *pc; 575f9f848faSopenharmony_ci uint16_t txlen; 576f9f848faSopenharmony_ci uint32_t nframes, pos; 577f9f848faSopenharmony_ci struct pbuf *p; 578f9f848faSopenharmony_ci uint8_t ustat; 579f9f848faSopenharmony_ci uint32_t txhdr; 580f9f848faSopenharmony_ci 581f9f848faSopenharmony_ci ustat = USB_GET_STATE(xfer); 582f9f848faSopenharmony_citr_setup: 583f9f848faSopenharmony_ci switch (ustat) { 584f9f848faSopenharmony_ci case USB_ST_TRANSFERRED: 585f9f848faSopenharmony_ci drv_sc->state &= ~IFF_DRV_OACTIVE; 586f9f848faSopenharmony_ci /* FALLTHROUGH */ 587f9f848faSopenharmony_ci 588f9f848faSopenharmony_ci case USB_ST_SETUP: 589f9f848faSopenharmony_ci if (drv_sc->state & IFF_DRV_OACTIVE) 590f9f848faSopenharmony_ci return; 591f9f848faSopenharmony_ci 592f9f848faSopenharmony_ci UE_LOCK(ue); 593f9f848faSopenharmony_ci IF_DEQUEUE(&(ue->ue_txq), p); 594f9f848faSopenharmony_ci UE_UNLOCK(ue); 595f9f848faSopenharmony_ci 596f9f848faSopenharmony_ci nframes = 0; 597f9f848faSopenharmony_ci while (p) { 598f9f848faSopenharmony_ci txlen = p->len; 599f9f848faSopenharmony_ci if (txlen <= 0) 600f9f848faSopenharmony_ci break; 601f9f848faSopenharmony_ci 602f9f848faSopenharmony_ci usbd_xfer_set_frame_offset(xfer, nframes * MCLBYTES, nframes); 603f9f848faSopenharmony_ci pos = 0; 604f9f848faSopenharmony_ci pc = usbd_xfer_get_frame(xfer, nframes); 605f9f848faSopenharmony_ci 606f9f848faSopenharmony_ci txhdr = htole32(txlen); 607f9f848faSopenharmony_ci usbd_copy_in(pc, 0, &txhdr, sizeof(txhdr)); 608f9f848faSopenharmony_ci txhdr = 0; 609f9f848faSopenharmony_ci txhdr = htole32(txhdr); 610f9f848faSopenharmony_ci usbd_copy_in(pc, 4, &txhdr, sizeof(txhdr)); 611f9f848faSopenharmony_ci pos += 8; 612f9f848faSopenharmony_ci usbd_copy_in(pc, pos, p->payload, txlen); 613f9f848faSopenharmony_ci pos += txlen; 614f9f848faSopenharmony_ci if ((pos % usbd_xfer_max_framelen(xfer)) == 0) 615f9f848faSopenharmony_ci txhdr |= 0x80008000; 616f9f848faSopenharmony_ci 617f9f848faSopenharmony_ci /* Set frame length. */ 618f9f848faSopenharmony_ci usbd_xfer_set_frame_len(xfer, nframes, pos); 619f9f848faSopenharmony_ci 620f9f848faSopenharmony_ci uether_freebuf(p); 621f9f848faSopenharmony_ci nframes++; 622f9f848faSopenharmony_ci if (nframes >= 16) 623f9f848faSopenharmony_ci break; 624f9f848faSopenharmony_ci 625f9f848faSopenharmony_ci UE_LOCK(ue); 626f9f848faSopenharmony_ci IF_DEQUEUE(&(ue->ue_txq), p); 627f9f848faSopenharmony_ci UE_UNLOCK(ue); 628f9f848faSopenharmony_ci } 629f9f848faSopenharmony_ci if (nframes != 0) { 630f9f848faSopenharmony_ci usbd_xfer_set_frames(xfer, nframes); 631f9f848faSopenharmony_ci usbd_transfer_submit(xfer); 632f9f848faSopenharmony_ci drv_sc->state |= IFF_DRV_OACTIVE; 633f9f848faSopenharmony_ci } 634f9f848faSopenharmony_ci break; 635f9f848faSopenharmony_ci 636f9f848faSopenharmony_ci default: /* Error */ 637f9f848faSopenharmony_ci drv_sc->state &= ~IFF_DRV_OACTIVE; 638f9f848faSopenharmony_ci if (error != USB_ERR_CANCELLED) { 639f9f848faSopenharmony_ci /* try to clear stall first */ 640f9f848faSopenharmony_ci usbd_xfer_set_stall(xfer); 641f9f848faSopenharmony_ci ustat = USB_ST_SETUP; 642f9f848faSopenharmony_ci goto tr_setup; 643f9f848faSopenharmony_ci } 644f9f848faSopenharmony_ci break; 645f9f848faSopenharmony_ci } 646f9f848faSopenharmony_ci} 647f9f848faSopenharmony_ci 648f9f848faSopenharmony_cistatic void 649f9f848faSopenharmony_ciaxge_start(struct usb_ether *ue) 650f9f848faSopenharmony_ci{ 651f9f848faSopenharmony_ci struct axge_softc *sc = ue->ue_sc; 652f9f848faSopenharmony_ci 653f9f848faSopenharmony_ci /* 654f9f848faSopenharmony_ci * start the USB transfers, if not already started: 655f9f848faSopenharmony_ci */ 656f9f848faSopenharmony_ci usbd_transfer_start(sc->sc_xfer[AXGE_BULK_DT_WR]); 657f9f848faSopenharmony_ci usbd_transfer_start(sc->sc_xfer[AXGE_BULK_DT_RD]); 658f9f848faSopenharmony_ci} 659f9f848faSopenharmony_ci 660f9f848faSopenharmony_cistatic void 661f9f848faSopenharmony_ciaxge_init(struct usb_ether *ue) 662f9f848faSopenharmony_ci{ 663f9f848faSopenharmony_ci struct axge_softc *sc = uether_getsc(ue); 664f9f848faSopenharmony_ci struct los_eth_driver *ifp = ue->ue_drv_sc; 665f9f848faSopenharmony_ci struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)ifp->driver_context; 666f9f848faSopenharmony_ci uint16_t rxmode; 667f9f848faSopenharmony_ci 668f9f848faSopenharmony_ci drv_sc->state = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 669f9f848faSopenharmony_ci 670f9f848faSopenharmony_ci AXGE_LOCK_ASSERT(sc, MA_OWNED); 671f9f848faSopenharmony_ci if ((drv_sc->state & IFF_DRV_RUNNING) != 0) 672f9f848faSopenharmony_ci return; 673f9f848faSopenharmony_ci 674f9f848faSopenharmony_ci /* Cancel pending I/O */ 675f9f848faSopenharmony_ci axge_stop(ue); 676f9f848faSopenharmony_ci axge_reset(sc); 677f9f848faSopenharmony_ci 678f9f848faSopenharmony_ci /* Set MAC address. */ 679f9f848faSopenharmony_ci ifp->ac_if.hwaddr_len = NETIF_MAX_HWADDR_LEN; 680f9f848faSopenharmony_ci (void)axge_read_mem(sc, AXGE_ACCESS_MAC, 6, AXGE_NIDR, ifp ->ac_if.hwaddr, 6); 681f9f848faSopenharmony_ci 682f9f848faSopenharmony_ci axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_PWLLR, 0x34); 683f9f848faSopenharmony_ci axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_PWLHR, 0x52); 684f9f848faSopenharmony_ci 685f9f848faSopenharmony_ci ifp->ac_if.flags |= NETIF_FLAG_UP | NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET; 686f9f848faSopenharmony_ci 687f9f848faSopenharmony_ci /* Configure TX/RX checksum offloading. */ 688f9f848faSopenharmony_ci axge_csum_cfg(ue); 689f9f848faSopenharmony_ci 690f9f848faSopenharmony_ci /* Configure RX settings. */ 691f9f848faSopenharmony_ci rxmode = (RCR_AM | RCR_SO | RCR_DROP_CRCE); 692f9f848faSopenharmony_ci 693f9f848faSopenharmony_ci /* If we want promiscuous mode, set the allframes bit. */ 694f9f848faSopenharmony_ci if (ifp->ac_if.flags & IFF_PROMISC) 695f9f848faSopenharmony_ci rxmode |= RCR_PRO; 696f9f848faSopenharmony_ci 697f9f848faSopenharmony_ci if (ifp->ac_if.flags & IFF_BROADCAST) 698f9f848faSopenharmony_ci rxmode |= RCR_AB; 699f9f848faSopenharmony_ci 700f9f848faSopenharmony_ci axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode); 701f9f848faSopenharmony_ci 702f9f848faSopenharmony_ci axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_MMSR, 703f9f848faSopenharmony_ci MMSR_PME_TYPE | MMSR_PME_POL | MMSR_RWMP); 704f9f848faSopenharmony_ci 705f9f848faSopenharmony_ci /* Load the multicast filter. */ 706f9f848faSopenharmony_ci axge_setmulti(ue); 707f9f848faSopenharmony_ci 708f9f848faSopenharmony_ci drv_sc->state |= IFF_DRV_RUNNING; 709f9f848faSopenharmony_ci} 710f9f848faSopenharmony_ci 711f9f848faSopenharmony_cistatic void 712f9f848faSopenharmony_ciaxge_stop(struct usb_ether *ue) 713f9f848faSopenharmony_ci{ 714f9f848faSopenharmony_ci struct axge_softc *sc = uether_getsc(ue); 715f9f848faSopenharmony_ci struct los_eth_driver *ifp = ue->ue_drv_sc; 716f9f848faSopenharmony_ci struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)ifp->driver_context; 717f9f848faSopenharmony_ci 718f9f848faSopenharmony_ci AXGE_LOCK_ASSERT(sc, MA_OWNED); 719f9f848faSopenharmony_ci drv_sc->state &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 720f9f848faSopenharmony_ci sc->sc_flags &= ~AXE_FLAG_LINK; 721f9f848faSopenharmony_ci /* 722f9f848faSopenharmony_ci * stop all the transfers, if not already stopped: 723f9f848faSopenharmony_ci */ 724f9f848faSopenharmony_ci usbd_transfer_stop(sc->sc_xfer[AXGE_BULK_DT_WR]); 725f9f848faSopenharmony_ci usbd_transfer_stop(sc->sc_xfer[AXGE_BULK_DT_RD]); 726f9f848faSopenharmony_ci} 727f9f848faSopenharmony_ci 728f9f848faSopenharmony_ci#undef USB_DEBUG_VAR 729