1 1.98 riastrad /* $NetBSD: if_url.c,v 1.98 2024/06/30 16:35:19 riastradh Exp $ */ 2 1.43 mrg 3 1.1 ichiro /* 4 1.1 ichiro * Copyright (c) 2001, 2002 5 1.1 ichiro * Shingo WATANABE <nabe (at) nabechan.org>. All rights reserved. 6 1.1 ichiro * 7 1.1 ichiro * Redistribution and use in source and binary forms, with or without 8 1.1 ichiro * modification, are permitted provided that the following conditions 9 1.1 ichiro * are met: 10 1.1 ichiro * 1. Redistributions of source code must retain the above copyright 11 1.1 ichiro * notice, this list of conditions and the following disclaimer. 12 1.1 ichiro * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 ichiro * notice, this list of conditions and the following disclaimer in the 14 1.1 ichiro * documentation and/or other materials provided with the distribution. 15 1.8 tsutsui * 3. Neither the name of the author nor the names of any co-contributors 16 1.1 ichiro * may be used to endorse or promote products derived from this software 17 1.1 ichiro * without specific prior written permission. 18 1.1 ichiro * 19 1.1 ichiro * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 1.1 ichiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 ichiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 ichiro * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 1.1 ichiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 ichiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 ichiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 ichiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 ichiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 ichiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 ichiro * SUCH DAMAGE. 30 1.1 ichiro * 31 1.1 ichiro */ 32 1.1 ichiro 33 1.1 ichiro /* 34 1.1 ichiro * The RTL8150L(Realtek USB to fast ethernet controller) spec can be found at 35 1.1 ichiro * ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/8150v14.pdf 36 1.1 ichiro * ftp://152.104.125.40/lancard/data_sheet/8150/8150v14.pdf 37 1.1 ichiro */ 38 1.1 ichiro 39 1.1 ichiro /* 40 1.1 ichiro * TODO: 41 1.1 ichiro * Interrupt Endpoint support 42 1.1 ichiro * External PHYs 43 1.1 ichiro * powerhook() support? 44 1.1 ichiro */ 45 1.1 ichiro 46 1.1 ichiro #include <sys/cdefs.h> 47 1.98 riastrad __KERNEL_RCSID(0, "$NetBSD: if_url.c,v 1.98 2024/06/30 16:35:19 riastradh Exp $"); 48 1.1 ichiro 49 1.46 christos #ifdef _KERNEL_OPT 50 1.1 ichiro #include "opt_inet.h" 51 1.54 skrll #include "opt_usb.h" 52 1.46 christos #endif 53 1.1 ichiro 54 1.1 ichiro #include <sys/param.h> 55 1.1 ichiro 56 1.1 ichiro #include <net/if_ether.h> 57 1.1 ichiro #ifdef INET 58 1.1 ichiro #include <netinet/in.h> 59 1.1 ichiro #include <netinet/if_inarp.h> 60 1.1 ichiro #endif 61 1.1 ichiro 62 1.1 ichiro #include <dev/mii/urlphyreg.h> 63 1.1 ichiro 64 1.68 mrg #include <dev/usb/usbnet.h> 65 1.1 ichiro 66 1.1 ichiro #include <dev/usb/if_urlreg.h> 67 1.1 ichiro 68 1.1 ichiro /* Function declarations */ 69 1.72 maxv static int url_match(device_t, cfdata_t, void *); 70 1.72 maxv static void url_attach(device_t, device_t, void *); 71 1.63 mrg 72 1.68 mrg CFATTACH_DECL_NEW(url, sizeof(struct usbnet), url_match, url_attach, 73 1.68 mrg usbnet_detach, usbnet_activate); 74 1.1 ichiro 75 1.76 thorpej static unsigned url_uno_tx_prepare(struct usbnet *, struct mbuf *, 76 1.76 thorpej struct usbnet_chain *); 77 1.76 thorpej static void url_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); 78 1.76 thorpej static int url_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); 79 1.76 thorpej static int url_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); 80 1.76 thorpej static void url_uno_stop(struct ifnet *, int); 81 1.76 thorpej static void url_uno_mii_statchg(struct ifnet *); 82 1.76 thorpej static int url_uno_init(struct ifnet *); 83 1.87 riastrad static void url_uno_mcast(struct ifnet *); 84 1.68 mrg static void url_reset(struct usbnet *); 85 1.68 mrg 86 1.68 mrg static int url_csr_read_1(struct usbnet *, int); 87 1.68 mrg static int url_csr_read_2(struct usbnet *, int); 88 1.68 mrg static int url_csr_write_1(struct usbnet *, int, int); 89 1.68 mrg static int url_csr_write_2(struct usbnet *, int, int); 90 1.68 mrg static int url_csr_write_4(struct usbnet *, int, int); 91 1.68 mrg static int url_mem(struct usbnet *, int, int, void *, int); 92 1.68 mrg 93 1.72 maxv static const struct usbnet_ops url_ops = { 94 1.76 thorpej .uno_stop = url_uno_stop, 95 1.81 riastrad .uno_mcast = url_uno_mcast, 96 1.76 thorpej .uno_read_reg = url_uno_mii_read_reg, 97 1.76 thorpej .uno_write_reg = url_uno_mii_write_reg, 98 1.76 thorpej .uno_statchg = url_uno_mii_statchg, 99 1.76 thorpej .uno_tx_prepare = url_uno_tx_prepare, 100 1.76 thorpej .uno_rx_loop = url_uno_rx_loop, 101 1.76 thorpej .uno_init = url_uno_init, 102 1.68 mrg }; 103 1.1 ichiro 104 1.1 ichiro /* Macros */ 105 1.1 ichiro #ifdef URL_DEBUG 106 1.38 dyoung #define DPRINTF(x) if (urldebug) printf x 107 1.64 msaitoh #define DPRINTFN(n, x) if (urldebug >= (n)) printf x 108 1.2 ichiro int urldebug = 0; 109 1.1 ichiro #else 110 1.1 ichiro #define DPRINTF(x) 111 1.64 msaitoh #define DPRINTFN(n, x) 112 1.1 ichiro #endif 113 1.1 ichiro 114 1.68 mrg #define URL_SETBIT(un, reg, x) \ 115 1.68 mrg url_csr_write_1(un, reg, url_csr_read_1(un, reg) | (x)) 116 1.1 ichiro 117 1.68 mrg #define URL_SETBIT2(un, reg, x) \ 118 1.68 mrg url_csr_write_2(un, reg, url_csr_read_2(un, reg) | (x)) 119 1.1 ichiro 120 1.68 mrg #define URL_CLRBIT(un, reg, x) \ 121 1.68 mrg url_csr_write_1(un, reg, url_csr_read_1(un, reg) & ~(x)) 122 1.1 ichiro 123 1.68 mrg #define URL_CLRBIT2(un, reg, x) \ 124 1.68 mrg url_csr_write_2(un, reg, url_csr_read_2(un, reg) & ~(x)) 125 1.1 ichiro 126 1.1 ichiro static const struct url_type { 127 1.1 ichiro struct usb_devno url_dev; 128 1.51 skrll uint16_t url_flags; 129 1.1 ichiro #define URL_EXT_PHY 0x0001 130 1.1 ichiro } url_devs [] = { 131 1.1 ichiro /* MELCO LUA-KTX */ 132 1.1 ichiro {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX }, 0}, 133 1.10 mycroft /* Realtek RTL8150L Generic (GREEN HOUSE USBKR100) */ 134 1.11 augustss {{ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8150L}, 0}, 135 1.11 augustss /* Longshine LCS-8138TX */ 136 1.11 augustss {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_LCS8138TX}, 0}, 137 1.11 augustss /* Micronet SP128AR */ 138 1.11 augustss {{ USB_VENDOR_MICRONET, USB_PRODUCT_MICRONET_SP128AR}, 0}, 139 1.13 itojun /* OQO model 01 */ 140 1.13 itojun {{ USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01}, 0}, 141 1.1 ichiro }; 142 1.17 christos #define url_lookup(v, p) ((const struct url_type *)usb_lookup(url_devs, v, p)) 143 1.1 ichiro 144 1.1 ichiro 145 1.1 ichiro /* Probe */ 146 1.72 maxv static int 147 1.38 dyoung url_match(device_t parent, cfdata_t match, void *aux) 148 1.1 ichiro { 149 1.38 dyoung struct usb_attach_arg *uaa = aux; 150 1.1 ichiro 151 1.51 skrll return url_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ? 152 1.51 skrll UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 153 1.1 ichiro } 154 1.1 ichiro /* Attach */ 155 1.72 maxv static void 156 1.38 dyoung url_attach(device_t parent, device_t self, void *aux) 157 1.1 ichiro { 158 1.70 mrg USBNET_MII_DECL_DEFAULT(unm); 159 1.68 mrg struct usbnet * const un = device_private(self); 160 1.38 dyoung struct usb_attach_arg *uaa = aux; 161 1.51 skrll struct usbd_device *dev = uaa->uaa_device; 162 1.51 skrll struct usbd_interface *iface; 163 1.1 ichiro usbd_status err; 164 1.1 ichiro usb_interface_descriptor_t *id; 165 1.1 ichiro usb_endpoint_descriptor_t *ed; 166 1.16 augustss char *devinfop; 167 1.68 mrg int i; 168 1.32 cube 169 1.34 plunky aprint_naive("\n"); 170 1.34 plunky aprint_normal("\n"); 171 1.16 augustss devinfop = usbd_devinfo_alloc(dev, 0); 172 1.32 cube aprint_normal_dev(self, "%s\n", devinfop); 173 1.16 augustss usbd_devinfo_free(devinfop); 174 1.1 ichiro 175 1.68 mrg un->un_dev = self; 176 1.68 mrg un->un_udev = dev; 177 1.68 mrg un->un_sc = un; 178 1.68 mrg un->un_ops = &url_ops; 179 1.68 mrg un->un_rx_xfer_flags = USBD_SHORT_XFER_OK; 180 1.68 mrg un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER; 181 1.68 mrg un->un_rx_list_cnt = URL_RX_LIST_CNT; 182 1.68 mrg un->un_tx_list_cnt = URL_TX_LIST_CNT; 183 1.68 mrg un->un_rx_bufsz = URL_BUFSZ; 184 1.68 mrg un->un_tx_bufsz = URL_BUFSZ; 185 1.68 mrg 186 1.1 ichiro /* Move the device into the configured state. */ 187 1.1 ichiro err = usbd_set_config_no(dev, URL_CONFIG_NO, 1); 188 1.1 ichiro if (err) { 189 1.45 skrll aprint_error_dev(self, "failed to set configuration" 190 1.45 skrll ", err=%s\n", usbd_errstr(err)); 191 1.71 mrg return; 192 1.1 ichiro } 193 1.1 ichiro 194 1.1 ichiro /* get control interface */ 195 1.1 ichiro err = usbd_device2interface_handle(dev, URL_IFACE_INDEX, &iface); 196 1.1 ichiro if (err) { 197 1.32 cube aprint_error_dev(self, "failed to get interface, err=%s\n", 198 1.1 ichiro usbd_errstr(err)); 199 1.71 mrg return; 200 1.1 ichiro } 201 1.1 ichiro 202 1.68 mrg un->un_iface = iface; 203 1.68 mrg un->un_flags = url_lookup(uaa->uaa_vendor, uaa->uaa_product)->url_flags; 204 1.68 mrg #if 0 205 1.68 mrg if (un->un_flags & URL_EXT_PHY) { 206 1.68 mrg un->un_read_reg_cb = url_ext_mii_read_reg; 207 1.68 mrg un->un_write_reg_cb = url_ext_mii_write_reg; 208 1.68 mrg } 209 1.68 mrg #endif 210 1.1 ichiro 211 1.1 ichiro /* get interface descriptor */ 212 1.68 mrg id = usbd_get_interface_descriptor(un->un_iface); 213 1.1 ichiro 214 1.1 ichiro /* find endpoints */ 215 1.68 mrg un->un_ed[USBNET_ENDPT_RX] = un->un_ed[USBNET_ENDPT_TX] = 216 1.68 mrg un->un_ed[USBNET_ENDPT_INTR] = 0; 217 1.1 ichiro for (i = 0; i < id->bNumEndpoints; i++) { 218 1.68 mrg ed = usbd_interface2endpoint_descriptor(un->un_iface, i); 219 1.1 ichiro if (ed == NULL) { 220 1.32 cube aprint_error_dev(self, 221 1.32 cube "couldn't get endpoint %d\n", i); 222 1.71 mrg return; 223 1.1 ichiro } 224 1.1 ichiro if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && 225 1.1 ichiro UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) 226 1.68 mrg un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress; 227 1.1 ichiro else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && 228 1.1 ichiro UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) 229 1.68 mrg un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress; 230 1.1 ichiro else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT && 231 1.1 ichiro UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) 232 1.68 mrg un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress; 233 1.1 ichiro } 234 1.1 ichiro 235 1.68 mrg if (un->un_ed[USBNET_ENDPT_RX] == 0 || 236 1.68 mrg un->un_ed[USBNET_ENDPT_TX] == 0 || 237 1.68 mrg un->un_ed[USBNET_ENDPT_INTR] == 0) { 238 1.32 cube aprint_error_dev(self, "missing endpoint\n"); 239 1.71 mrg return; 240 1.1 ichiro } 241 1.1 ichiro 242 1.68 mrg /* Set these up now for url_mem(). */ 243 1.96 riastrad usbnet_attach(un); 244 1.1 ichiro 245 1.1 ichiro /* reset the adapter */ 246 1.68 mrg url_reset(un); 247 1.1 ichiro 248 1.1 ichiro /* Get Ethernet Address */ 249 1.68 mrg err = url_mem(un, URL_CMD_READMEM, URL_IDR0, (void *)un->un_eaddr, 250 1.1 ichiro ETHER_ADDR_LEN); 251 1.1 ichiro if (err) { 252 1.32 cube aprint_error_dev(self, "read MAC address failed\n"); 253 1.78 riastrad return; 254 1.1 ichiro } 255 1.1 ichiro 256 1.19 wiz /* initialize interface information */ 257 1.69 mrg usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 258 1.69 mrg 0, &unm); 259 1.1 ichiro } 260 1.1 ichiro 261 1.1 ichiro /* read/write memory */ 262 1.68 mrg static int 263 1.68 mrg url_mem(struct usbnet *un, int cmd, int offset, void *buf, int len) 264 1.1 ichiro { 265 1.1 ichiro usb_device_request_t req; 266 1.1 ichiro usbd_status err; 267 1.1 ichiro 268 1.1 ichiro DPRINTFN(0x200, 269 1.68 mrg ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 270 1.1 ichiro 271 1.90 riastrad if (usbnet_isdying(un)) { 272 1.90 riastrad if (cmd == URL_CMD_READMEM) 273 1.90 riastrad memset(buf, 0, len); 274 1.51 skrll return 0; 275 1.90 riastrad } 276 1.1 ichiro 277 1.1 ichiro if (cmd == URL_CMD_READMEM) 278 1.1 ichiro req.bmRequestType = UT_READ_VENDOR_DEVICE; 279 1.1 ichiro else 280 1.1 ichiro req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 281 1.1 ichiro req.bRequest = URL_REQ_MEM; 282 1.1 ichiro USETW(req.wValue, offset); 283 1.1 ichiro USETW(req.wIndex, 0x0000); 284 1.1 ichiro USETW(req.wLength, len); 285 1.1 ichiro 286 1.68 mrg err = usbd_do_request(un->un_udev, &req, buf); 287 1.1 ichiro if (err) { 288 1.1 ichiro DPRINTF(("%s: url_mem(): %s failed. off=%04x, err=%d\n", 289 1.68 mrg device_xname(un->un_dev), 290 1.1 ichiro cmd == URL_CMD_READMEM ? "read" : "write", 291 1.1 ichiro offset, err)); 292 1.90 riastrad if (cmd == URL_CMD_READMEM) 293 1.90 riastrad memset(buf, 0, len); 294 1.5 augustss } 295 1.1 ichiro 296 1.51 skrll return err; 297 1.1 ichiro } 298 1.1 ichiro 299 1.1 ichiro /* read 1byte from register */ 300 1.68 mrg static int 301 1.68 mrg url_csr_read_1(struct usbnet *un, int reg) 302 1.1 ichiro { 303 1.51 skrll uint8_t val = 0; 304 1.1 ichiro 305 1.1 ichiro DPRINTFN(0x100, 306 1.68 mrg ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 307 1.5 augustss 308 1.68 mrg return url_mem(un, URL_CMD_READMEM, reg, &val, 1) ? 0 : val; 309 1.1 ichiro } 310 1.1 ichiro 311 1.1 ichiro /* read 2bytes from register */ 312 1.68 mrg static int 313 1.68 mrg url_csr_read_2(struct usbnet *un, int reg) 314 1.1 ichiro { 315 1.1 ichiro uWord val; 316 1.1 ichiro 317 1.1 ichiro DPRINTFN(0x100, 318 1.68 mrg ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 319 1.5 augustss 320 1.1 ichiro USETW(val, 0); 321 1.68 mrg return url_mem(un, URL_CMD_READMEM, reg, &val, 2) ? 0 : UGETW(val); 322 1.1 ichiro } 323 1.1 ichiro 324 1.1 ichiro /* write 1byte to register */ 325 1.68 mrg static int 326 1.68 mrg url_csr_write_1(struct usbnet *un, int reg, int aval) 327 1.1 ichiro { 328 1.51 skrll uint8_t val = aval; 329 1.1 ichiro 330 1.1 ichiro DPRINTFN(0x100, 331 1.68 mrg ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 332 1.1 ichiro 333 1.68 mrg return url_mem(un, URL_CMD_WRITEMEM, reg, &val, 1) ? -1 : 0; 334 1.1 ichiro } 335 1.1 ichiro 336 1.1 ichiro /* write 2bytes to register */ 337 1.68 mrg static int 338 1.68 mrg url_csr_write_2(struct usbnet *un, int reg, int aval) 339 1.1 ichiro { 340 1.1 ichiro uWord val; 341 1.1 ichiro 342 1.1 ichiro DPRINTFN(0x100, 343 1.68 mrg ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 344 1.1 ichiro 345 1.1 ichiro USETW(val, aval); 346 1.1 ichiro 347 1.68 mrg return url_mem(un, URL_CMD_WRITEMEM, reg, &val, 2) ? -1 : 0; 348 1.1 ichiro } 349 1.1 ichiro 350 1.1 ichiro /* write 4bytes to register */ 351 1.68 mrg static int 352 1.68 mrg url_csr_write_4(struct usbnet *un, int reg, int aval) 353 1.1 ichiro { 354 1.1 ichiro uDWord val; 355 1.1 ichiro 356 1.1 ichiro DPRINTFN(0x100, 357 1.68 mrg ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 358 1.1 ichiro 359 1.1 ichiro USETDW(val, aval); 360 1.1 ichiro 361 1.68 mrg return url_mem(un, URL_CMD_WRITEMEM, reg, &val, 4) ? -1 : 0; 362 1.1 ichiro } 363 1.1 ichiro 364 1.68 mrg static int 365 1.85 riastrad url_uno_init(struct ifnet *ifp) 366 1.1 ichiro { 367 1.68 mrg struct usbnet * const un = ifp->if_softc; 368 1.29 dyoung const u_char *eaddr; 369 1.68 mrg int i; 370 1.1 ichiro 371 1.68 mrg DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 372 1.5 augustss 373 1.94 riastrad url_reset(un); 374 1.1 ichiro 375 1.29 dyoung eaddr = CLLADDR(ifp->if_sadl); 376 1.1 ichiro for (i = 0; i < ETHER_ADDR_LEN; i++) 377 1.68 mrg url_csr_write_1(un, URL_IDR0 + i, eaddr[i]); 378 1.1 ichiro 379 1.1 ichiro /* Init transmission control register */ 380 1.68 mrg URL_CLRBIT(un, URL_TCR, 381 1.1 ichiro URL_TCR_TXRR1 | URL_TCR_TXRR0 | 382 1.1 ichiro URL_TCR_IFG1 | URL_TCR_IFG0 | 383 1.1 ichiro URL_TCR_NOCRC); 384 1.1 ichiro 385 1.1 ichiro /* Init receive control register */ 386 1.77 nisimura URL_SETBIT2(un, URL_RCR, URL_RCR_TAIL | URL_RCR_AD | URL_RCR_AB); 387 1.5 augustss 388 1.1 ichiro /* Enable RX and TX */ 389 1.68 mrg URL_SETBIT(un, URL_CR, URL_CR_TE | URL_CR_RE); 390 1.51 skrll 391 1.95 riastrad return 0; 392 1.68 mrg } 393 1.1 ichiro 394 1.68 mrg static void 395 1.68 mrg url_reset(struct usbnet *un) 396 1.1 ichiro { 397 1.1 ichiro int i; 398 1.5 augustss 399 1.68 mrg DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 400 1.1 ichiro 401 1.68 mrg if (usbnet_isdying(un)) 402 1.1 ichiro return; 403 1.1 ichiro 404 1.68 mrg URL_SETBIT(un, URL_CR, URL_CR_SOFT_RST); 405 1.1 ichiro 406 1.1 ichiro for (i = 0; i < URL_TX_TIMEOUT; i++) { 407 1.80 riastrad if (usbnet_isdying(un)) 408 1.80 riastrad return; 409 1.68 mrg if (!(url_csr_read_1(un, URL_CR) & URL_CR_SOFT_RST)) 410 1.1 ichiro break; 411 1.1 ichiro delay(10); /* XXX */ 412 1.1 ichiro } 413 1.1 ichiro 414 1.1 ichiro delay(10000); /* XXX */ 415 1.1 ichiro } 416 1.1 ichiro 417 1.68 mrg static void 418 1.87 riastrad url_uno_mcast(struct ifnet *ifp) 419 1.1 ichiro { 420 1.87 riastrad struct usbnet * const un = ifp->if_softc; 421 1.68 mrg struct ethercom *ec = usbnet_ec(un); 422 1.1 ichiro struct ether_multi *enm; 423 1.1 ichiro struct ether_multistep step; 424 1.77 nisimura uint32_t mchash[2] = { 0, 0 }; 425 1.98 riastrad uint32_t h = 0, rcr; 426 1.1 ichiro 427 1.68 mrg DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 428 1.1 ichiro 429 1.68 mrg if (usbnet_isdying(un)) 430 1.1 ichiro return; 431 1.1 ichiro 432 1.77 nisimura rcr = url_csr_read_2(un, URL_RCR); 433 1.77 nisimura rcr &= ~(URL_RCR_AAP | URL_RCR_AAM | URL_RCR_AM); 434 1.77 nisimura 435 1.77 nisimura ETHER_LOCK(ec); 436 1.97 riastrad if (usbnet_ispromisc(un)) { 437 1.77 nisimura ec->ec_flags |= ETHER_F_ALLMULTI; 438 1.77 nisimura ETHER_UNLOCK(ec); 439 1.77 nisimura /* run promisc. mode */ 440 1.77 nisimura rcr |= URL_RCR_AAM; /* ??? */ 441 1.77 nisimura rcr |= URL_RCR_AAP; 442 1.77 nisimura goto update; 443 1.1 ichiro } 444 1.77 nisimura ec->ec_flags &= ~ETHER_F_ALLMULTI; 445 1.65 msaitoh ETHER_FIRST_MULTI(step, ec, enm); 446 1.1 ichiro while (enm != NULL) { 447 1.77 nisimura if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { 448 1.77 nisimura ec->ec_flags |= ETHER_F_ALLMULTI; 449 1.65 msaitoh ETHER_UNLOCK(ec); 450 1.77 nisimura /* accept all multicast frames */ 451 1.77 nisimura rcr |= URL_RCR_AAM; 452 1.77 nisimura goto update; 453 1.65 msaitoh } 454 1.77 nisimura h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN); 455 1.77 nisimura /* 1(31) and 5(30:26) bit sampling */ 456 1.77 nisimura mchash[h >> 31] |= 1 << ((h >> 26) & 0x1f); 457 1.1 ichiro ETHER_NEXT_MULTI(step, enm); 458 1.1 ichiro } 459 1.65 msaitoh ETHER_UNLOCK(ec); 460 1.77 nisimura if (h != 0) 461 1.77 nisimura rcr |= URL_RCR_AM; /* activate mcast hash filter */ 462 1.77 nisimura url_csr_write_4(un, URL_MAR0, mchash[0]); 463 1.77 nisimura url_csr_write_4(un, URL_MAR4, mchash[1]); 464 1.77 nisimura update: 465 1.77 nisimura url_csr_write_2(un, URL_RCR, rcr); 466 1.1 ichiro } 467 1.1 ichiro 468 1.68 mrg static unsigned 469 1.76 thorpej url_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) 470 1.1 ichiro { 471 1.68 mrg int total_len; 472 1.1 ichiro 473 1.68 mrg DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev),__func__)); 474 1.5 augustss 475 1.68 mrg KASSERT(un->un_tx_bufsz >= URL_MIN_FRAME_LEN); 476 1.68 mrg if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz) 477 1.68 mrg return 0; 478 1.1 ichiro 479 1.1 ichiro /* Copy the mbuf data into a contiguous buffer */ 480 1.68 mrg m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf); 481 1.1 ichiro total_len = m->m_pkthdr.len; 482 1.1 ichiro 483 1.7 bouyer if (total_len < URL_MIN_FRAME_LEN) { 484 1.68 mrg memset(c->unc_buf + total_len, 0, 485 1.7 bouyer URL_MIN_FRAME_LEN - total_len); 486 1.1 ichiro total_len = URL_MIN_FRAME_LEN; 487 1.7 bouyer } 488 1.1 ichiro 489 1.68 mrg DPRINTF(("%s: %s: send %d bytes\n", device_xname(un->un_dev), 490 1.4 augustss __func__, total_len)); 491 1.1 ichiro 492 1.68 mrg return total_len; 493 1.1 ichiro } 494 1.1 ichiro 495 1.68 mrg static void 496 1.76 thorpej url_uno_rx_loop(struct usbnet *un, struct usbnet_chain *c, uint32_t total_len) 497 1.1 ichiro { 498 1.68 mrg struct ifnet *ifp = usbnet_ifp(un); 499 1.1 ichiro url_rxhdr_t rxhdr; 500 1.1 ichiro 501 1.68 mrg DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev),__func__)); 502 1.1 ichiro 503 1.68 mrg if (total_len <= ETHER_CRC_LEN || total_len <= sizeof(rxhdr)) { 504 1.73 thorpej if_statinc(ifp, if_ierrors); 505 1.68 mrg return; 506 1.1 ichiro } 507 1.1 ichiro 508 1.68 mrg memcpy(&rxhdr, c->unc_buf + total_len - ETHER_CRC_LEN, sizeof(rxhdr)); 509 1.1 ichiro 510 1.1 ichiro DPRINTF(("%s: RX Status: %dbytes%s%s%s%s packets\n", 511 1.68 mrg device_xname(un->un_dev), 512 1.1 ichiro UGETW(rxhdr) & URL_RXHDR_BYTEC_MASK, 513 1.1 ichiro UGETW(rxhdr) & URL_RXHDR_VALID_MASK ? ", Valid" : "", 514 1.1 ichiro UGETW(rxhdr) & URL_RXHDR_RUNTPKT_MASK ? ", Runt" : "", 515 1.1 ichiro UGETW(rxhdr) & URL_RXHDR_PHYPKT_MASK ? ", Physical match" : "", 516 1.1 ichiro UGETW(rxhdr) & URL_RXHDR_MCASTPKT_MASK ? ", Multicast" : "")); 517 1.1 ichiro 518 1.1 ichiro if ((UGETW(rxhdr) & URL_RXHDR_VALID_MASK) == 0) { 519 1.73 thorpej if_statinc(ifp, if_ierrors); 520 1.68 mrg return; 521 1.1 ichiro } 522 1.1 ichiro 523 1.1 ichiro total_len -= ETHER_CRC_LEN; 524 1.1 ichiro 525 1.68 mrg DPRINTF(("%s: %s: deliver %d\n", device_xname(un->un_dev), 526 1.68 mrg __func__, total_len)); 527 1.68 mrg usbnet_enqueue(un, c->unc_buf, total_len, 0, 0, 0); 528 1.1 ichiro } 529 1.1 ichiro 530 1.1 ichiro #if 0 531 1.68 mrg static void url_intr(void) 532 1.1 ichiro { 533 1.1 ichiro } 534 1.1 ichiro #endif 535 1.1 ichiro 536 1.1 ichiro /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ 537 1.68 mrg static void 538 1.76 thorpej url_uno_stop(struct ifnet *ifp, int disable) 539 1.1 ichiro { 540 1.68 mrg struct usbnet * const un = ifp->if_softc; 541 1.1 ichiro 542 1.68 mrg DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 543 1.1 ichiro 544 1.68 mrg url_reset(un); 545 1.1 ichiro } 546 1.1 ichiro 547 1.69 mrg static int 548 1.76 thorpej url_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) 549 1.1 ichiro { 550 1.61 msaitoh uint16_t data; 551 1.68 mrg usbd_status err = USBD_NORMAL_COMPLETION; 552 1.1 ichiro 553 1.75 christos DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n", 554 1.68 mrg device_xname(un->un_dev), __func__, phy, reg)); 555 1.1 ichiro 556 1.1 ichiro /* XXX: one PHY only for the RTL8150 internal PHY */ 557 1.1 ichiro if (phy != 0) { 558 1.1 ichiro DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", 559 1.68 mrg device_xname(un->un_dev), __func__, phy)); 560 1.90 riastrad *val = 0; 561 1.69 mrg return EINVAL; 562 1.1 ichiro } 563 1.1 ichiro 564 1.1 ichiro switch (reg) { 565 1.1 ichiro case MII_BMCR: /* Control Register */ 566 1.1 ichiro reg = URL_BMCR; 567 1.1 ichiro break; 568 1.1 ichiro case MII_BMSR: /* Status Register */ 569 1.1 ichiro reg = URL_BMSR; 570 1.1 ichiro break; 571 1.1 ichiro case MII_PHYIDR1: 572 1.1 ichiro case MII_PHYIDR2: 573 1.61 msaitoh *val = 0; 574 1.1 ichiro goto R_DONE; 575 1.1 ichiro break; 576 1.1 ichiro case MII_ANAR: /* Autonegotiation advertisement */ 577 1.1 ichiro reg = URL_ANAR; 578 1.1 ichiro break; 579 1.1 ichiro case MII_ANLPAR: /* Autonegotiation link partner abilities */ 580 1.1 ichiro reg = URL_ANLP; 581 1.1 ichiro break; 582 1.1 ichiro case URLPHY_MSR: /* Media Status Register */ 583 1.1 ichiro reg = URL_MSR; 584 1.1 ichiro break; 585 1.1 ichiro default: 586 1.1 ichiro printf("%s: %s: bad register %04x\n", 587 1.68 mrg device_xname(un->un_dev), __func__, reg); 588 1.69 mrg return EINVAL; 589 1.1 ichiro } 590 1.1 ichiro 591 1.1 ichiro if (reg == URL_MSR) 592 1.68 mrg data = url_csr_read_1(un, reg); 593 1.1 ichiro else 594 1.68 mrg data = url_csr_read_2(un, reg); 595 1.61 msaitoh *val = data; 596 1.1 ichiro 597 1.1 ichiro R_DONE: 598 1.75 christos DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04hx\n", 599 1.68 mrg device_xname(un->un_dev), __func__, phy, reg, *val)); 600 1.1 ichiro 601 1.68 mrg return err; 602 1.1 ichiro } 603 1.1 ichiro 604 1.69 mrg static int 605 1.76 thorpej url_uno_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val) 606 1.1 ichiro { 607 1.1 ichiro 608 1.75 christos DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x val=0x%04hx\n", 609 1.68 mrg device_xname(un->un_dev), __func__, phy, reg, val)); 610 1.1 ichiro 611 1.1 ichiro /* XXX: one PHY only for the RTL8150 internal PHY */ 612 1.1 ichiro if (phy != 0) { 613 1.1 ichiro DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", 614 1.68 mrg device_xname(un->un_dev), __func__, phy)); 615 1.69 mrg return EINVAL; 616 1.1 ichiro } 617 1.1 ichiro 618 1.1 ichiro switch (reg) { 619 1.1 ichiro case MII_BMCR: /* Control Register */ 620 1.1 ichiro reg = URL_BMCR; 621 1.1 ichiro break; 622 1.1 ichiro case MII_BMSR: /* Status Register */ 623 1.1 ichiro reg = URL_BMSR; 624 1.1 ichiro break; 625 1.1 ichiro case MII_PHYIDR1: 626 1.1 ichiro case MII_PHYIDR2: 627 1.69 mrg return 0; 628 1.1 ichiro case MII_ANAR: /* Autonegotiation advertisement */ 629 1.1 ichiro reg = URL_ANAR; 630 1.1 ichiro break; 631 1.1 ichiro case MII_ANLPAR: /* Autonegotiation link partner abilities */ 632 1.1 ichiro reg = URL_ANLP; 633 1.1 ichiro break; 634 1.1 ichiro case URLPHY_MSR: /* Media Status Register */ 635 1.1 ichiro reg = URL_MSR; 636 1.1 ichiro break; 637 1.1 ichiro default: 638 1.1 ichiro printf("%s: %s: bad register %04x\n", 639 1.68 mrg device_xname(un->un_dev), __func__, reg); 640 1.69 mrg return EINVAL; 641 1.1 ichiro } 642 1.1 ichiro 643 1.1 ichiro if (reg == URL_MSR) 644 1.68 mrg url_csr_write_1(un, reg, val); 645 1.1 ichiro else 646 1.68 mrg url_csr_write_2(un, reg, val); 647 1.1 ichiro 648 1.69 mrg return 0; 649 1.1 ichiro } 650 1.1 ichiro 651 1.68 mrg static void 652 1.76 thorpej url_uno_mii_statchg(struct ifnet *ifp) 653 1.1 ichiro { 654 1.68 mrg struct usbnet * const un = ifp->if_softc; 655 1.1 ichiro 656 1.44 matt DPRINTF(("%s: %s: enter\n", ifp->if_xname, __func__)); 657 1.68 mrg 658 1.68 mrg /* XXX */ 659 1.68 mrg usbnet_set_link(un, true); 660 1.1 ichiro } 661 1.1 ichiro 662 1.1 ichiro #if 0 663 1.1 ichiro /* 664 1.1 ichiro * external PHYs support, but not test. 665 1.1 ichiro */ 666 1.68 mrg static usbd_status 667 1.68 mrg url_ext_mii_read_reg(struct usbnet *un, int phy, int reg) 668 1.1 ichiro { 669 1.51 skrll uint16_t val; 670 1.1 ichiro 671 1.75 christos DPRINTF(("%s: %s: enter, phy=%d reg=0x%04x\n", 672 1.68 mrg device_xname(un->un_dev), __func__, phy, reg)); 673 1.1 ichiro 674 1.68 mrg url_csr_write_1(un, URL_PHYADD, phy & URL_PHYADD_MASK); 675 1.1 ichiro /* 676 1.1 ichiro * RTL8150L will initiate a MII management data transaction 677 1.1 ichiro * if PHYCNT_OWN bit is set 1 by software. After transaction, 678 1.1 ichiro * this bit is auto cleared by TRL8150L. 679 1.1 ichiro */ 680 1.68 mrg url_csr_write_1(un, URL_PHYCNT, 681 1.1 ichiro (reg | URL_PHYCNT_PHYOWN) & ~URL_PHYCNT_RWCR); 682 1.1 ichiro for (i = 0; i < URL_TIMEOUT; i++) { 683 1.68 mrg if ((url_csr_read_1(un, URL_PHYCNT) & URL_PHYCNT_PHYOWN) == 0) 684 1.1 ichiro break; 685 1.1 ichiro } 686 1.1 ichiro if (i == URL_TIMEOUT) { 687 1.68 mrg printf("%s: MII read timed out\n", device_xname(un->un_dev)); 688 1.1 ichiro } 689 1.5 augustss 690 1.68 mrg val = url_csr_read_2(un, URL_PHYDAT); 691 1.1 ichiro 692 1.75 christos DPRINTF(("%s: %s: phy=%d reg=0x%04x => 0x%04x\n", 693 1.68 mrg device_xname(un->un_dev), __func__, phy, reg, val)); 694 1.1 ichiro 695 1.68 mrg return USBD_NORMAL_COMPLETION; 696 1.1 ichiro } 697 1.1 ichiro 698 1.68 mrg static usbd_status 699 1.68 mrg url_ext_mii_write_reg(struct usbnet *un, int phy, int reg, int data) 700 1.1 ichiro { 701 1.1 ichiro 702 1.75 christos DPRINTF(("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n", 703 1.68 mrg device_xname(un->un_dev), __func__, phy, reg, data)); 704 1.1 ichiro 705 1.68 mrg url_csr_write_2(un, URL_PHYDAT, data); 706 1.68 mrg url_csr_write_1(un, URL_PHYADD, phy); 707 1.68 mrg url_csr_write_1(un, URL_PHYCNT, reg | URL_PHYCNT_RWCR); /* Write */ 708 1.1 ichiro 709 1.1 ichiro for (i=0; i < URL_TIMEOUT; i++) { 710 1.68 mrg if (url_csr_read_1(un, URL_PHYCNT) & URL_PHYCNT_PHYOWN) 711 1.1 ichiro break; 712 1.1 ichiro } 713 1.1 ichiro 714 1.1 ichiro if (i == URL_TIMEOUT) { 715 1.1 ichiro printf("%s: MII write timed out\n", 716 1.68 mrg device_xname(un->un_dev)); 717 1.68 mrg return USBD_TIMEOUT; 718 1.1 ichiro } 719 1.1 ichiro 720 1.68 mrg return USBD_NORMAL_COMPLETION; 721 1.1 ichiro } 722 1.1 ichiro #endif 723 1.68 mrg 724 1.68 mrg #ifdef _MODULE 725 1.68 mrg #include "ioconf.c" 726 1.68 mrg #endif 727 1.68 mrg 728 1.68 mrg USBNET_MODULE(url) 729