if_aue.c revision 212122
1139734Simp/*- 2139734Simp * Copyright (c) 1997, 1998, 1999, 2000 317773Swosch * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved. 417773Swosch * 517773Swosch * Copyright (c) 2006 617773Swosch * Alfred Perlstein <alfred@FreeBSD.org>. All rights reserved. 717773Swosch * 817773Swosch * Redistribution and use in source and binary forms, with or without 917773Swosch * modification, are permitted provided that the following conditions 1017773Swosch * are met: 1117773Swosch * 1. Redistributions of source code must retain the above copyright 1217773Swosch * notice, this list of conditions and the following disclaimer. 1317773Swosch * 2. Redistributions in binary form must reproduce the above copyright 1417773Swosch * notice, this list of conditions and the following disclaimer in the 1517773Swosch * documentation and/or other materials provided with the distribution. 1617773Swosch * 3. All advertising materials mentioning features or use of this software 1717773Swosch * must display the following acknowledgement: 1817773Swosch * This product includes software developed by Bill Paul. 1917773Swosch * 4. Neither the name of the author nor the names of any co-contributors 2017773Swosch * may be used to endorse or promote products derived from this software 2117773Swosch * without specific prior written permission. 2217773Swosch * 2317773Swosch * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2417773Swosch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2517773Swosch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26146319Sru * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 27141580Sru * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28141580Sru * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29291754Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3012823Sphk * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3179538Sru * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3212823Sphk * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3314003Smpp * THE POSSIBILITY OF SUCH DAMAGE. 3475670Sru */ 3512823Sphk 3626192Speter#include <sys/cdefs.h> 3768716Sru__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_aue.c 212122 2010-09-01 23:47:53Z thompsa $"); 3887529Sru 3987774Simp/* 4087773Simp * ADMtek AN986 Pegasus and AN8511 Pegasus II USB to ethernet driver. 4187773Simp * Datasheet is available from http://www.admtek.com.tw. 4287858Sru * 4387773Simp * Written by Bill Paul <wpaul@ee.columbia.edu> 4471895Sru * Electrical Engineering Department 4512823Sphk * Columbia University, New York City 4675820Sobrien * 4775820Sobrien * SMP locking by Alfred Perlstein <alfred@FreeBSD.org>. 4875820Sobrien * RED Inc. 4975820Sobrien */ 5012823Sphk 5112823Sphk/* 5212823Sphk * The Pegasus chip uses four USB "endpoints" to provide 10/100 ethernet 5312823Sphk * support: the control endpoint for reading/writing registers, burst 5412823Sphk * read endpoint for packet reception, burst write for packet transmission 5512823Sphk * and one for "interrupts." The chip uses the same RX filter scheme 5612823Sphk * as the other ADMtek ethernet parts: one perfect filter entry for the 5712823Sphk * the station address and a 64-bit multicast hash table. The chip supports 5812823Sphk * both MII and HomePNA attachments. 5912951Sphk * 6012951Sphk * Since the maximum data transfer speed of USB is supposed to be 12Mbps, 6112823Sphk * you're never really going to get 100Mbps speeds from this device. I 6214966Sjoerg * think the idea is to allow the device to connect to 10 or 100Mbps 6314966Sjoerg * networks, not necessarily to provide 100Mbps performance. Also, since 64139947Skeramida * the controller uses an external PHY chip, it's possible that board 65139725Simp * designers might simply choose a 10Mbps PHY. 66139725Simp * 67139725Simp * Registers are accessed using uether_do_request(). Packet 68166323Sjoel * transfers are done using usbd_transfer() and friends. 69166323Sjoel */ 70139725Simp 71175108Sgrog#include <sys/stdint.h> 72139725Simp#include <sys/stddef.h> 73139725Simp#include <sys/param.h> 74139947Skeramida#include <sys/queue.h> 75139734Simp#include <sys/types.h> 76139734Simp#include <sys/systm.h> 77139734Simp#include <sys/kernel.h> 78139734Simp#include <sys/bus.h> 79140173Sru#include <sys/linker_set.h> 80139734Simp#include <sys/module.h> 81139734Simp#include <sys/lock.h> 82139734Simp#include <sys/mutex.h> 83146307Skeramida#include <sys/condvar.h> 84139734Simp#include <sys/sysctl.h> 85139725Simp#include <sys/sx.h> 8675820Sobrien#include <sys/unistd.h> 87146319Sru#include <sys/callout.h> 88146323Sobrien#include <sys/malloc.h> 8975820Sobrien#include <sys/priv.h> 9090018Sbde 9183041Sgrog#include <dev/usb/usb.h> 9283041Sgrog#include <dev/usb/usbdi.h> 9390018Sbde#include <dev/usb/usbdi_util.h> 9483041Sgrog#include "usbdevs.h" 9576708Sobrien 9690042Sobrien#define USB_DEBUG_VAR aue_debug 9792569Sru#include <dev/usb/usb_debug.h> 9892569Sru#include <dev/usb/usb_process.h> 9990018Sbde 10090018Sbde#include <dev/usb/net/usb_ethernet.h> 10190018Sbde#include <dev/usb/net/if_auereg.h> 10290018Sbde 10390018Sbde#ifdef USB_DEBUG 10490018Sbdestatic int aue_debug = 0; 10590018Sbde 10675820SobrienSYSCTL_NODE(_hw_usb, OID_AUTO, aue, CTLFLAG_RW, 0, "USB aue"); 10790018SbdeSYSCTL_INT(_hw_usb_aue, OID_AUTO, debug, CTLFLAG_RW, &aue_debug, 0, 10890018Sbde "Debug level"); 10990018Sbde#endif 110112629Sjhb 11190018Sbde/* 112131132Sbde * Various supported device vendors/products. 11383517Sobrien */ 11484307Srustatic const struct usb_device_id aue_devs[] = { 11575820Sobrien#define AUE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } 11675820Sobrien AUE_DEV(3COM, 3C460B, AUE_FLAG_PII), 11783041Sgrog AUE_DEV(ABOCOM, DSB650TX_PNA, 0), 11875820Sobrien AUE_DEV(ABOCOM, UFE1000, AUE_FLAG_LSYS), 11987529Sru AUE_DEV(ABOCOM, XX10, 0), 12087529Sru AUE_DEV(ABOCOM, XX1, AUE_FLAG_PNA | AUE_FLAG_PII), 12187529Sru AUE_DEV(ABOCOM, XX2, AUE_FLAG_PII), 122119893Sru AUE_DEV(ABOCOM, XX4, AUE_FLAG_PNA), 12387529Sru AUE_DEV(ABOCOM, XX5, AUE_FLAG_PNA), 124119893Sru AUE_DEV(ABOCOM, XX6, AUE_FLAG_PII), 12587529Sru AUE_DEV(ABOCOM, XX7, AUE_FLAG_PII), 126119893Sru AUE_DEV(ABOCOM, XX8, AUE_FLAG_PII), 12787529Sru AUE_DEV(ABOCOM, XX9, AUE_FLAG_PNA), 128119893Sru AUE_DEV(ACCTON, SS1001, AUE_FLAG_PII), 12987529Sru AUE_DEV(ACCTON, USB320_EC, 0), 13071895Sru AUE_DEV(ADMTEK, PEGASUSII_2, AUE_FLAG_PII), 13163324Sben AUE_DEV(ADMTEK, PEGASUSII_3, AUE_FLAG_PII), 13214966Sjoerg AUE_DEV(ADMTEK, PEGASUSII_4, AUE_FLAG_PII), 13314966Sjoerg AUE_DEV(ADMTEK, PEGASUSII, AUE_FLAG_PII), 13483041Sgrog AUE_DEV(ADMTEK, PEGASUS, AUE_FLAG_PNA | AUE_FLAG_DUAL_PHY), 13571895Sru AUE_DEV(AEI, FASTETHERNET, AUE_FLAG_PII), 13612823Sphk AUE_DEV(ALLIEDTELESYN, ATUSB100, AUE_FLAG_PII), 13712823Sphk AUE_DEV(ATEN, UC110T, AUE_FLAG_PII), 13812823Sphk AUE_DEV(BELKIN, USB2LAN, AUE_FLAG_PII), 13912823Sphk AUE_DEV(BILLIONTON, USB100, 0), 14012823Sphk AUE_DEV(BILLIONTON, USBE100, AUE_FLAG_PII), 14114966Sjoerg AUE_DEV(BILLIONTON, USBEL100, 0), 14214966Sjoerg AUE_DEV(BILLIONTON, USBLP100, AUE_FLAG_PNA), 14387773Simp AUE_DEV(COREGA, FETHER_USB_TXS, AUE_FLAG_PII), 14487773Simp AUE_DEV(COREGA, FETHER_USB_TX, 0), 14587773Simp AUE_DEV(DLINK, DSB650TX1, AUE_FLAG_LSYS), 14687773Simp AUE_DEV(DLINK, DSB650TX2, AUE_FLAG_LSYS | AUE_FLAG_PII), 14787529Sru AUE_DEV(DLINK, DSB650TX3, AUE_FLAG_LSYS | AUE_FLAG_PII), 148130582Sru AUE_DEV(DLINK, DSB650TX4, AUE_FLAG_LSYS | AUE_FLAG_PII), 149120530Simp AUE_DEV(DLINK, DSB650TX_PNA, AUE_FLAG_PNA), 15083041Sgrog AUE_DEV(DLINK, DSB650TX, AUE_FLAG_LSYS), 15171895Sru AUE_DEV(DLINK, DSB650, AUE_FLAG_LSYS), 15212823Sphk AUE_DEV(ELCON, PLAN, AUE_FLAG_PNA | AUE_FLAG_PII), 15314966Sjoerg AUE_DEV(ELECOM, LDUSB20, AUE_FLAG_PII), 15414966Sjoerg AUE_DEV(ELECOM, LDUSBLTX, AUE_FLAG_PII), 15587529Sru AUE_DEV(ELECOM, LDUSBTX0, 0), 156119893Sru AUE_DEV(ELECOM, LDUSBTX1, AUE_FLAG_LSYS), 15787529Sru AUE_DEV(ELECOM, LDUSBTX2, 0), 15887529Sru AUE_DEV(ELECOM, LDUSBTX3, AUE_FLAG_LSYS), 15987529Sru AUE_DEV(ELSA, USB2ETHERNET, 0), 16087529Sru AUE_DEV(GIGABYTE, GNBR402W, 0), 16171895Sru AUE_DEV(HAWKING, UF100, AUE_FLAG_PII), 16212823Sphk AUE_DEV(HP, HN210E, AUE_FLAG_PII), 16314966Sjoerg AUE_DEV(IODATA, USBETTXS, AUE_FLAG_PII), 16414966Sjoerg AUE_DEV(IODATA, USBETTX, 0), 16583041Sgrog AUE_DEV(KINGSTON, KNU101TX, 0), 16671895Sru AUE_DEV(LINKSYS, USB100H1, AUE_FLAG_LSYS | AUE_FLAG_PNA), 16712951Sphk AUE_DEV(LINKSYS, USB100TX, AUE_FLAG_LSYS), 16814966Sjoerg AUE_DEV(LINKSYS, USB10TA, AUE_FLAG_LSYS), 16914966Sjoerg AUE_DEV(LINKSYS, USB10TX1, AUE_FLAG_LSYS | AUE_FLAG_PII), 17087529Sru AUE_DEV(LINKSYS, USB10TX2, AUE_FLAG_LSYS | AUE_FLAG_PII), 17187529Sru AUE_DEV(LINKSYS, USB10T, AUE_FLAG_LSYS), 17287529Sru AUE_DEV(MELCO, LUA2TX5, AUE_FLAG_PII), 17364395Ssheldonh AUE_DEV(MELCO, LUATX1, 0), 17464395Ssheldonh AUE_DEV(MELCO, LUATX5, 0), 17564395Ssheldonh AUE_DEV(MICROSOFT, MN110, AUE_FLAG_PII), 17686725Sru AUE_DEV(NETGEAR, FA101, AUE_FLAG_PII), 17764395Ssheldonh AUE_DEV(SIEMENS, SPEEDSTREAM, AUE_FLAG_PII), 17864395Ssheldonh AUE_DEV(SIIG2, USBTOETHER, AUE_FLAG_PII), 17964395Ssheldonh AUE_DEV(SMARTBRIDGES, SMARTNIC, AUE_FLAG_PII), 18064395Ssheldonh AUE_DEV(SMC, 2202USB, 0), 18179727Sschweikh AUE_DEV(SMC, 2206USB, AUE_FLAG_PII), 18287529Sru AUE_DEV(SOHOWARE, NUB100, 0), 18379727Sschweikh AUE_DEV(SOHOWARE, NUB110, AUE_FLAG_PII), 18464395Ssheldonh#undef AUE_DEV 18564395Ssheldonh}; 18664395Ssheldonh 18764395Ssheldonh/* prototypes */ 18864395Ssheldonh 18964395Ssheldonhstatic device_probe_t aue_probe; 19063427Sbenstatic device_attach_t aue_attach; 19149363Shoekstatic device_detach_t aue_detach; 19231613Swollmanstatic miibus_readreg_t aue_miibus_readreg; 19387529Srustatic miibus_writereg_t aue_miibus_writereg; 19431613Swollmanstatic miibus_statchg_t aue_miibus_statchg; 19579727Sschweikh 19687529Srustatic usb_callback_t aue_intr_callback; 19731613Swollmanstatic usb_callback_t aue_bulk_read_callback; 19831614Swollmanstatic usb_callback_t aue_bulk_write_callback; 19931613Swollman 20031613Swollmanstatic uether_fn_t aue_attach_post; 20171895Srustatic uether_fn_t aue_init; 20231613Swollmanstatic uether_fn_t aue_stop; 20312951Sphkstatic uether_fn_t aue_start; 20412951Sphkstatic uether_fn_t aue_tick; 20591436Simpstatic uether_fn_t aue_setmulti; 20614966Sjoergstatic uether_fn_t aue_setpromisc; 20714966Sjoerg 208106302Srwatsonstatic uint8_t aue_csr_read_1(struct aue_softc *, uint16_t); 209106092Srwatsonstatic uint16_t aue_csr_read_2(struct aue_softc *, uint16_t); 210106092Srwatsonstatic void aue_csr_write_1(struct aue_softc *, uint16_t, uint8_t); 211106092Srwatsonstatic void aue_csr_write_2(struct aue_softc *, uint16_t, uint16_t); 212106092Srwatsonstatic void aue_eeprom_getword(struct aue_softc *, int, uint16_t *); 213106092Srwatsonstatic void aue_read_eeprom(struct aue_softc *, uint8_t *, uint16_t, 214106092Srwatson uint16_t); 215106092Srwatsonstatic void aue_reset(struct aue_softc *); 216106302Srwatsonstatic void aue_reset_pegasus_II(struct aue_softc *); 217106092Srwatson 218106092Srwatsonstatic int aue_ifmedia_upd(struct ifnet *); 219106092Srwatsonstatic void aue_ifmedia_sts(struct ifnet *, struct ifmediareq *); 220106092Srwatson 221106092Srwatsonstatic const struct usb_config aue_config[AUE_N_TRANSFER] = { 222106302Srwatson 223107383Sru [AUE_BULK_DT_WR] = { 224107383Sru .type = UE_BULK, 225107383Sru .endpoint = UE_ADDR_ANY, 226106302Srwatson .direction = UE_DIR_OUT, 227106092Srwatson .bufsize = (MCLBYTES + 2), 228106092Srwatson .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 229106092Srwatson .callback = aue_bulk_write_callback, 230106092Srwatson .timeout = 10000, /* 10 seconds */ 231106302Srwatson }, 232106092Srwatson 233106092Srwatson [AUE_BULK_DT_RD] = { 234106092Srwatson .type = UE_BULK, 235106092Srwatson .endpoint = UE_ADDR_ANY, 236106302Srwatson .direction = UE_DIR_IN, 237106092Srwatson .bufsize = (MCLBYTES + 4 + ETHER_CRC_LEN), 238106092Srwatson .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 239106092Srwatson .callback = aue_bulk_read_callback, 240106092Srwatson }, 241106092Srwatson 242106302Srwatson [AUE_INTR_DT_RD] = { 243106302Srwatson .type = UE_INTERRUPT, 244106302Srwatson .endpoint = UE_ADDR_ANY, 245106092Srwatson .direction = UE_DIR_IN, 246106302Srwatson .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 247106302Srwatson .bufsize = 0, /* use wMaxPacketSize */ 248106302Srwatson .callback = aue_intr_callback, 249106092Srwatson }, 250106092Srwatson}; 251106092Srwatson 252106092Srwatsonstatic device_method_t aue_methods[] = { 253106092Srwatson /* Device interface */ 254106092Srwatson DEVMETHOD(device_probe, aue_probe), 255106092Srwatson DEVMETHOD(device_attach, aue_attach), 256106092Srwatson DEVMETHOD(device_detach, aue_detach), 257106092Srwatson 258106092Srwatson /* bus interface */ 259106092Srwatson DEVMETHOD(bus_print_child, bus_generic_print_child), 260106092Srwatson DEVMETHOD(bus_driver_added, bus_generic_driver_added), 261106092Srwatson 262106092Srwatson /* MII interface */ 263106302Srwatson DEVMETHOD(miibus_readreg, aue_miibus_readreg), 264106092Srwatson DEVMETHOD(miibus_writereg, aue_miibus_writereg), 265106092Srwatson DEVMETHOD(miibus_statchg, aue_miibus_statchg), 266106092Srwatson 267106092Srwatson {0, 0} 268106092Srwatson}; 269106302Srwatson 270106092Srwatsonstatic driver_t aue_driver = { 271106092Srwatson .name = "aue", 272130432Sle .methods = aue_methods, 273106092Srwatson .size = sizeof(struct aue_softc) 274106092Srwatson}; 275130582Sru 276130582Srustatic devclass_t aue_devclass; 277120530Simp 278130582SruDRIVER_MODULE(aue, uhub, aue_driver, aue_devclass, NULL, 0); 279130582SruDRIVER_MODULE(miibus, aue, miibus_driver, miibus_devclass, 0, 0); 280130582SruMODULE_DEPEND(aue, uether, 1, 1, 1); 281130582SruMODULE_DEPEND(aue, usb, 1, 1, 1); 282130582SruMODULE_DEPEND(aue, ether, 1, 1, 1); 283120530SimpMODULE_DEPEND(aue, miibus, 1, 1, 1); 284120530SimpMODULE_VERSION(aue, 1); 285130582Sru 286130582Srustatic const struct usb_ether_methods aue_ue_methods = { 287120530Simp .ue_attach_post = aue_attach_post, 288130582Sru .ue_start = aue_start, 289120530Simp .ue_init = aue_init, 290120530Simp .ue_stop = aue_stop, 29131613Swollman .ue_tick = aue_tick, 29271895Sru .ue_setmulti = aue_setmulti, 29312823Sphk .ue_setpromisc = aue_setpromisc, 29414966Sjoerg .ue_mii_upd = aue_ifmedia_upd, 29514966Sjoerg .ue_mii_sts = aue_ifmedia_sts, 296209546Scperciva}; 297209546Scperciva 298209546Scperciva#define AUE_SETBIT(sc, reg, x) \ 299103189Srobert aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) | (x)) 300103189Srobert 301107383Sru#define AUE_CLRBIT(sc, reg, x) \ 302107383Sru aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) & ~(x)) 303107383Sru 304107383Srustatic uint8_t 305107383Sruaue_csr_read_1(struct aue_softc *sc, uint16_t reg) 306108317Sschweikh{ 307103189Srobert struct usb_device_request req; 30814966Sjoerg usb_error_t err; 309138327Sdds uint8_t val; 31087529Sru 31187529Sru req.bmRequestType = UT_READ_VENDOR_DEVICE; 31285367Sjulian req.bRequest = AUE_UR_READREG; 31385445Sjulian USETW(req.wValue, 0); 31485480Sbde USETW(req.wIndex, reg); 31599240Simp USETW(req.wLength, 1); 31699240Simp 31785445Sjulian err = uether_do_request(&sc->sc_ue, &req, &val, 1000); 31885480Sbde if (err) 31914966Sjoerg return (0); 32014966Sjoerg return (val); 32149363Shoek} 32287529Sru 32387529Srustatic uint16_t 32487529Sruaue_csr_read_2(struct aue_softc *sc, uint16_t reg) 32587529Sru{ 32687529Sru struct usb_device_request req; 32771895Sru usb_error_t err; 32812823Sphk uint16_t val; 32985445Sjulian 33085445Sjulian req.bmRequestType = UT_READ_VENDOR_DEVICE; 33185445Sjulian req.bRequest = AUE_UR_READREG; 33285445Sjulian USETW(req.wValue, 0); 33312823Sphk USETW(req.wIndex, reg); 33485445Sjulian USETW(req.wLength, 2); 33531612Swollman 33631613Swollman err = uether_do_request(&sc->sc_ue, &req, &val, 1000); 33731612Swollman if (err) 33831612Swollman return (0); 33987529Sru return (le16toh(val)); 34087529Sru} 34131612Swollman 34271895Srustatic void 34331612Swollmanaue_csr_write_1(struct aue_softc *sc, uint16_t reg, uint8_t val) 34487529Sru{ 34582952Sobrien struct usb_device_request req; 34685480Sbde 34785445Sjulian req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 34885445Sjulian req.bRequest = AUE_UR_WRITEREG; 34985445Sjulian req.wValue[0] = val; 35031612Swollman req.wValue[1] = 0; 35185445Sjulian USETW(req.wIndex, reg); 35231612Swollman USETW(req.wLength, 1); 35331612Swollman 35487529Sru if (uether_do_request(&sc->sc_ue, &req, &val, 1000)) { 355122424Sfanf /* error ignored */ 356122424Sfanf } 357122424Sfanf} 358122424Sfanf 359122424Sfanfstatic void 360122424Sfanfaue_csr_write_2(struct aue_softc *sc, uint16_t reg, uint16_t val) 361122424Sfanf{ 362122554Sfanf struct usb_device_request req; 363122424Sfanf 364122424Sfanf req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 365122424Sfanf req.bRequest = AUE_UR_WRITEREG; 366122424Sfanf USETW(req.wValue, val); 36787529Sru USETW(req.wIndex, reg); 36887529Sru USETW(req.wLength, 2); 36987529Sru 37087529Sru val = htole16(val); 37187529Sru 372107282Sru if (uether_do_request(&sc->sc_ue, &req, &val, 1000)) { 373107282Sru /* error ignored */ 37471895Sru } 37512823Sphk} 37687569Sobrien 37712951Sphk/* 37812823Sphk * Read a word of data stored in the EEPROM at address 'addr.' 37987569Sobrien */ 38087569Sobrienstatic void 38114966Sjoergaue_eeprom_getword(struct aue_softc *sc, int addr, uint16_t *dest) 38214966Sjoerg{ 38314966Sjoerg int i; 38414966Sjoerg uint16_t word = 0; 385131530Sru 38687529Sru aue_csr_write_1(sc, AUE_EE_REG, addr); 38787529Sru aue_csr_write_1(sc, AUE_EE_CTL, AUE_EECTL_READ); 38814966Sjoerg 38987529Sru for (i = 0; i != AUE_TIMEOUT; i++) { 39014966Sjoerg if (aue_csr_read_1(sc, AUE_EE_CTL) & AUE_EECTL_DONE) 39114966Sjoerg break; 39214966Sjoerg if (uether_pause(&sc->sc_ue, hz / 100)) 393102212Simp break; 394103011Srobert } 395102212Simp 39614966Sjoerg if (i == AUE_TIMEOUT) 39714966Sjoerg device_printf(sc->sc_ue.ue_dev, "EEPROM read timed out\n"); 39881449Sru 39987529Sru word = aue_csr_read_2(sc, AUE_EE_DATA); 40014966Sjoerg *dest = word; 40190043Simp} 40287529Sru 40390043Simp/* 40414966Sjoerg * Read a sequence of words from the EEPROM. 40526192Speter */ 40687529Srustatic void 40787529Sruaue_read_eeprom(struct aue_softc *sc, uint8_t *dest, 40887529Sru uint16_t off, uint16_t len) 40987529Sru{ 41087529Sru uint16_t *ptr = (uint16_t *)dest; 41187529Sru int i; 41226192Speter 41326192Speter for (i = 0; i != len; i++, ptr++) 41414966Sjoerg aue_eeprom_getword(sc, off + i, ptr); 41571895Sru} 41626192Speter 41714966Sjoergstatic int 41814966Sjoergaue_miibus_readreg(device_t dev, int phy, int reg) 41949363Shoek{ 42084408Sobrien struct aue_softc *sc = device_get_softc(dev); 42186725Sru int i, locked; 42287529Sru uint16_t val = 0; 42387529Sru 42484408Sobrien locked = mtx_owned(&sc->sc_mtx); 42581449Sru if (!locked) 42671895Sru AUE_LOCK(sc); 42726192Speter 42826192Speter /* 42926192Speter * The Am79C901 HomePNA PHY actually contains two transceivers: a 1Mbps 43026192Speter * HomePNA PHY and a 10Mbps full/half duplex ethernet PHY with NWAY 43171895Sru * autoneg. However in the ADMtek adapter, only the 1Mbps PHY is 43226192Speter * actually connected to anything, so we ignore the 10Mbps one. It 43326192Speter * happens to be configured for MII address 3, so we filter that out. 43426192Speter */ 43526192Speter if (sc->sc_flags & AUE_FLAG_DUAL_PHY) { 43626192Speter if (phy == 3) 43771895Sru goto done; 43826192Speter#if 0 43975819Sobrien if (phy != 1) 44026192Speter goto done; 44112951Sphk#endif 44212823Sphk } 44312823Sphk aue_csr_write_1(sc, AUE_PHY_ADDR, phy); 44412823Sphk aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_READ); 44512823Sphk 44612823Sphk for (i = 0; i != AUE_TIMEOUT; i++) { 44712823Sphk if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE) 44826192Speter break; 44912823Sphk if (uether_pause(&sc->sc_ue, hz / 100)) 45093107Sobrien break; 45112951Sphk } 45212951Sphk 45314966Sjoerg if (i == AUE_TIMEOUT) 45414966Sjoerg device_printf(sc->sc_ue.ue_dev, "MII read timed out\n"); 45587529Sru 45687529Sru val = aue_csr_read_2(sc, AUE_PHY_DATA); 45787529Sru 45887529Srudone: 45987529Sru if (!locked) 46087529Sru AUE_UNLOCK(sc); 46187529Sru return (val); 46287529Sru} 46387529Sru 46487529Srustatic int 46587529Sruaue_miibus_writereg(device_t dev, int phy, int reg, int data) 46687529Sru{ 46787529Sru struct aue_softc *sc = device_get_softc(dev); 46887529Sru int i; 46987529Sru int locked; 47087529Sru 47187529Sru if (phy == 3) 47287529Sru return (0); 473217087Strasz 474217087Strasz locked = mtx_owned(&sc->sc_mtx); 475217087Strasz if (!locked) 47671895Sru AUE_LOCK(sc); 477131127Sobrien 47812951Sphk aue_csr_write_2(sc, AUE_PHY_DATA, data); 47912951Sphk aue_csr_write_1(sc, AUE_PHY_ADDR, phy); 480164639Sobrien aue_csr_write_1(sc, AUE_PHY_CTL, reg | AUE_PHYCTL_WRITE); 48112951Sphk 48212951Sphk for (i = 0; i != AUE_TIMEOUT; i++) { 48312951Sphk if (aue_csr_read_1(sc, AUE_PHY_CTL) & AUE_PHYCTL_DONE) 48412951Sphk break; 485131127Sobrien if (uether_pause(&sc->sc_ue, hz / 100)) 486131127Sobrien break; 487131127Sobrien } 48812951Sphk 48912951Sphk if (i == AUE_TIMEOUT) 49049361Shoek device_printf(sc->sc_ue.ue_dev, "MII write timed out\n"); 49149361Shoek 49249361Shoek if (!locked) 49349361Shoek AUE_UNLOCK(sc); 49449361Shoek return (0); 49512951Sphk} 49617812Swosch 49712951Sphkstatic void 49812951Sphkaue_miibus_statchg(device_t dev) 49912951Sphk{ 50012951Sphk struct aue_softc *sc = device_get_softc(dev); 50112951Sphk struct mii_data *mii = GET_MII(sc); 50214966Sjoerg int locked; 50314966Sjoerg 50487529Sru locked = mtx_owned(&sc->sc_mtx); 50587529Sru if (!locked) 506291754Sngie AUE_LOCK(sc); 507103179Sfanf 508103179Sfanf AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_RX_ENB | AUE_CTL0_TX_ENB); 509103179Sfanf if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) 510291754Sngie AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_SPEEDSEL); 511291754Sngie else 512291754Sngie AUE_CLRBIT(sc, AUE_CTL1, AUE_CTL1_SPEEDSEL); 513291754Sngie 51487529Sru if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) 51587529Sru AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_DUPLEX); 51687529Sru else 51787529Sru AUE_CLRBIT(sc, AUE_CTL1, AUE_CTL1_DUPLEX); 51871895Sru 51926192Speter AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_RX_ENB | AUE_CTL0_TX_ENB); 52026192Speter 52112951Sphk /* 52212951Sphk * Set the LED modes on the LinkSys adapter. 52343406Sjulian * This turns on the 'dual link LED' bin in the auxmode 52443406Sjulian * register of the Broadcom PHY. 52594682Sasmodai */ 52643406Sjulian if (sc->sc_flags & AUE_FLAG_LSYS) { 52743406Sjulian uint16_t auxmode; 52843406Sjulian 52943406Sjulian auxmode = aue_miibus_readreg(dev, 0, 0x1b); 53043406Sjulian aue_miibus_writereg(dev, 0, 0x1b, auxmode | 0x04); 53143406Sjulian } 53226192Speter if (!locked) 53326192Speter AUE_UNLOCK(sc); 53414966Sjoerg} 53514966Sjoerg 53687529Sru#define AUE_BITS 6 53787529Srustatic void 53887529Sruaue_setmulti(struct usb_ether *ue) 53987529Sru{ 54014966Sjoerg struct aue_softc *sc = uether_getsc(ue); 54171895Sru struct ifnet *ifp = uether_getifp(ue); 54212951Sphk struct ifmultiaddr *ifma; 54312951Sphk uint32_t h = 0; 54412951Sphk uint32_t i; 54512951Sphk uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 54614966Sjoerg 54714966Sjoerg AUE_LOCK_ASSERT(sc, MA_OWNED); 54826192Speter 54914966Sjoerg if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 55080139Sdd AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI); 55180139Sdd return; 55271895Sru } 55394682Sasmodai 55480139Sdd AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI); 55515095Smpp 55694682Sasmodai /* now program new ones */ 55778432Sdd if_maddr_rlock(ifp); 55814966Sjoerg TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 55914966Sjoerg if (ifma->ifma_addr->sa_family != AF_LINK) 56049363Shoek continue; 56149363Shoek h = ether_crc32_le(LLADDR((struct sockaddr_dl *) 56287529Sru ifma->ifma_addr), ETHER_ADDR_LEN) & ((1 << AUE_BITS) - 1); 56387529Sru hashtbl[(h >> 3)] |= 1 << (h & 0x7); 56426192Speter } 56526192Speter if_maddr_runlock(ifp); 56687529Sru 56787529Sru /* write the hashtable */ 56887529Sru for (i = 0; i != 8; i++) 56971895Sru aue_csr_write_1(sc, AUE_MAR0 + i, hashtbl[i]); 57012951Sphk} 57112951Sphk 57212951Sphkstatic void 57312951Sphkaue_reset_pegasus_II(struct aue_softc *sc) 57412951Sphk{ 57512951Sphk /* Magic constants taken from Linux driver. */ 57612951Sphk aue_csr_write_1(sc, AUE_REG_1D, 0); 57714966Sjoerg aue_csr_write_1(sc, AUE_REG_7B, 2); 57814966Sjoerg#if 0 57987529Sru if ((sc->sc_flags & HAS_HOME_PNA) && mii_mode) 58087529Sru aue_csr_write_1(sc, AUE_REG_81, 6); 58187529Sru else 58226192Speter#endif 58387529Sru aue_csr_write_1(sc, AUE_REG_81, 2); 58426192Speter} 58587529Sru 58626192Speterstatic void 58787529Sruaue_reset(struct aue_softc *sc) 58826192Speter{ 58987529Sru int i; 59026192Speter 59171895Sru AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_RESETMAC); 59272810Sben 59372810Sben for (i = 0; i != AUE_TIMEOUT; i++) { 59412951Sphk if (!(aue_csr_read_1(sc, AUE_CTL1) & AUE_CTL1_RESETMAC)) 59514966Sjoerg break; 59614966Sjoerg if (uether_pause(&sc->sc_ue, hz / 100)) 59787529Sru break; 59887529Sru } 59987529Sru 60087529Sru if (i == AUE_TIMEOUT) 60187529Sru device_printf(sc->sc_ue.ue_dev, "reset failed\n"); 60287529Sru 60371895Sru /* 60412951Sphk * The PHY(s) attached to the Pegasus chip may be held 60512951Sphk * in reset until we flip on the GPIO outputs. Make sure 60614966Sjoerg * to set the GPIO pins high so that the PHY(s) will 60714966Sjoerg * be enabled. 608186224Sdes * 60971895Sru * NOTE: We used to force all of the GPIO pins low first and then 610186224Sdes * enable the ones we want. This has been changed to better 61114966Sjoerg * match the ADMtek's reference design to avoid setting the 61214966Sjoerg * power-down configuration line of the PHY at the same time 61314966Sjoerg * it is reset. 61412823Sphk */ 61514966Sjoerg aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_SEL0|AUE_GPIO_SEL1); 61614966Sjoerg aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_SEL0|AUE_GPIO_SEL1|AUE_GPIO_OUT0); 61714966Sjoerg 61815095Smpp if (sc->sc_flags & AUE_FLAG_LSYS) { 61988545Salfred /* Grrr. LinkSys has to be different from everyone else. */ 62088545Salfred aue_csr_write_1(sc, AUE_GPIO0, AUE_GPIO_SEL0|AUE_GPIO_SEL1); 62171895Sru aue_csr_write_1(sc, AUE_GPIO0, 62212823Sphk AUE_GPIO_SEL0|AUE_GPIO_SEL1|AUE_GPIO_OUT0); 62326192Speter } 62412823Sphk if (sc->sc_flags & AUE_FLAG_PII) 62514966Sjoerg aue_reset_pegasus_II(sc); 62614966Sjoerg 62714966Sjoerg /* Wait a little while for the chip to get its brains in order: */ 62814966Sjoerg uether_pause(&sc->sc_ue, hz / 100); 62971917Snik} 63014966Sjoerg 63114966Sjoergstatic void 63287529Sruaue_attach_post(struct usb_ether *ue) 63387529Sru{ 63483041Sgrog struct aue_softc *sc = uether_getsc(ue); 63571895Sru 63626192Speter /* reset the adapter */ 63726192Speter aue_reset(sc); 63826192Speter 63926192Speter /* get station address from the EEPROM */ 64026192Speter aue_read_eeprom(sc, ue->ue_eaddr, 0, 3); 64126192Speter} 64214966Sjoerg 64314966Sjoerg/* 644180424Sdanger * Probe for a Pegasus chip. 645180424Sdanger */ 646180424Sdangerstatic int 647180424Sdangeraue_probe(device_t dev) 648180424Sdanger{ 64917196Sbde struct usb_attach_arg *uaa = device_get_ivars(dev); 65087529Sru 65187529Sru if (uaa->usb_mode != USB_MODE_HOST) 65287529Sru return (ENXIO); 65387529Sru if (uaa->info.bConfigIndex != AUE_CONFIG_INDEX) 65426192Speter return (ENXIO); 65526192Speter if (uaa->info.bIfaceIndex != AUE_IFACE_IDX) 656100649Simp return (ENXIO); 657100649Simp /* 658100649Simp * Belkin USB Bluetooth dongles of the F8T012xx1 model series conflict 659101819Sru * with older Belkin USB2LAN adapters. Skip if_aue if we detect one of 660100649Simp * the devices that look like Bluetooth adapters. 66126192Speter */ 66287529Sru if (uaa->info.idVendor == USB_VENDOR_BELKIN && 66387529Sru uaa->info.idProduct == USB_PRODUCT_BELKIN_F8T012 && 66487529Sru uaa->info.bcdDevice == 0x0413) 66587529Sru return (ENXIO); 66687529Sru 66787529Sru return (usbd_lookup_id_by_uaa(aue_devs, sizeof(aue_devs), uaa)); 66887529Sru} 66987529Sru 67087529Sru/* 67187529Sru * Attach the interface. Allocate softc structures, do ifmedia 67287529Sru * setup and ethernet/BPF attach. 67387529Sru */ 67487529Srustatic int 67587529Sruaue_attach(device_t dev) 67687529Sru{ 67749363Shoek struct usb_attach_arg *uaa = device_get_ivars(dev); 67826192Speter struct aue_softc *sc = device_get_softc(dev); 67987529Sru struct usb_ether *ue = &sc->sc_ue; 68087529Sru uint8_t iface_index; 68187529Sru int error; 68271895Sru 68352085Scpiazza sc->sc_flags = USB_GET_DRIVER_INFO(uaa); 68414966Sjoerg 68514966Sjoerg if (uaa->info.bcdDevice >= 0x0201) { 68614966Sjoerg /* XXX currently undocumented */ 68771895Sru sc->sc_flags |= AUE_FLAG_VER_2; 68814966Sjoerg } 68914966Sjoerg 69014966Sjoerg device_set_usb_desc(dev); 69187529Sru mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 69287529Sru 693140873Sru iface_index = AUE_IFACE_IDX; 69471895Sru error = usbd_transfer_setup(uaa->device, &iface_index, 69514966Sjoerg sc->sc_xfer, aue_config, AUE_N_TRANSFER, 69614966Sjoerg sc, &sc->sc_mtx); 69714966Sjoerg if (error) { 698140873Sru device_printf(dev, "allocating USB transfers failed\n"); 69971895Sru goto detach; 70014966Sjoerg } 70114966Sjoerg 70214966Sjoerg ue->ue_sc = sc; 70387529Sru ue->ue_dev = dev; 70487529Sru ue->ue_udev = uaa->device; 70587529Sru ue->ue_mtx = &sc->sc_mtx; 70614966Sjoerg ue->ue_methods = &aue_ue_methods; 70714966Sjoerg 70887529Sru error = uether_ifattach(ue); 70987529Sru if (error) { 71087529Sru device_printf(dev, "could not attach interface\n"); 71187486Simp goto detach; 71214966Sjoerg } 71315082Smpp return (0); /* success */ 71415082Smpp 71515082Smppdetach: 71687529Sru aue_detach(dev); 71771895Sru return (ENXIO); /* failure */ 71812951Sphk} 719185362Srwatson 72012951Sphkstatic int 721185362Srwatsonaue_detach(device_t dev) 72212951Sphk{ 72312823Sphk struct aue_softc *sc = device_get_softc(dev); 72414966Sjoerg struct usb_ether *ue = &sc->sc_ue; 72514966Sjoerg 72626192Speter usbd_transfer_unsetup(sc->sc_xfer, AUE_N_TRANSFER); 72771895Sru uether_ifdetach(ue); 72826192Speter mtx_destroy(&sc->sc_mtx); 72926192Speter 73026192Speter return (0); 73126192Speter} 73226192Speter 73312823Sphkstatic void 73414966Sjoergaue_intr_callback(struct usb_xfer *xfer, usb_error_t error) 73514966Sjoerg{ 73648264Smpp struct aue_softc *sc = usbd_xfer_softc(xfer); 73775819Sobrien struct ifnet *ifp = uether_getifp(&sc->sc_ue); 73826192Speter struct aue_intrpkt pkt; 739140873Sru struct usb_page_cache *pc; 74071895Sru int actlen; 74112823Sphk 74212823Sphk usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 74312823Sphk 74412823Sphk switch (USB_GET_STATE(xfer)) { 74512823Sphk case USB_ST_TRANSFERRED: 74612951Sphk 74726192Speter if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && 74812951Sphk actlen >= sizeof(pkt)) { 74912951Sphk 75026192Speter pc = usbd_xfer_get_frame(xfer, 0); 75126192Speter usbd_copy_out(pc, 0, &pkt, sizeof(pkt)); 75212823Sphk 75312823Sphk if (pkt.aue_txstat0) 75412823Sphk ifp->if_oerrors++; 75512823Sphk if (pkt.aue_txstat0 & (AUE_TXSTAT0_LATECOLL & 75614966Sjoerg AUE_TXSTAT0_EXCESSCOLL)) 75714966Sjoerg ifp->if_collisions++; 75814966Sjoerg } 75914966Sjoerg /* FALLTHROUGH */ 76014966Sjoerg case USB_ST_SETUP: 76114966Sjoergtr_setup: 76287529Sru usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 76387529Sru usbd_transfer_submit(xfer); 76487529Sru return; 76587529Sru 76687529Sru default: /* Error */ 76714966Sjoerg if (error != USB_ERR_CANCELLED) { 76814966Sjoerg /* try to clear stall first */ 76987529Sru usbd_xfer_set_stall(xfer); 77087529Sru goto tr_setup; 77163279Sben } 77270466Sru return; 77363279Sben } 77463279Sben} 77563279Sben 77663427Sbenstatic void 77787529Sruaue_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 77863427Sben{ 77987529Sru struct aue_softc *sc = usbd_xfer_softc(xfer); 78063279Sben struct usb_ether *ue = &sc->sc_ue; 78163279Sben struct ifnet *ifp = uether_getifp(ue); 78263279Sben struct aue_rxpkt stat; 78363279Sben struct usb_page_cache *pc; 78463279Sben int actlen; 78563279Sben 78681248Sru usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 78763279Sben pc = usbd_xfer_get_frame(xfer, 0); 78887529Sru 78963279Sben switch (USB_GET_STATE(xfer)) { 79063279Sben case USB_ST_TRANSFERRED: 79163279Sben DPRINTFN(11, "received %d bytes\n", actlen); 79263279Sben 79363279Sben if (sc->sc_flags & AUE_FLAG_VER_2) { 79463279Sben 79563279Sben if (actlen == 0) { 79663279Sben ifp->if_ierrors++; 79787529Sru goto tr_setup; 79887529Sru } 79987529Sru } else { 80087529Sru 80114966Sjoerg if (actlen <= sizeof(stat) + ETHER_CRC_LEN) { 80263279Sben ifp->if_ierrors++; 80387529Sru goto tr_setup; 80454676Sobrien } 80554676Sobrien usbd_copy_out(pc, actlen - sizeof(stat), &stat, 80614966Sjoerg sizeof(stat)); 80771895Sru 80812951Sphk /* 809186224Sdes * turn off all the non-error bits in the rx status 81012823Sphk * word: 81112823Sphk */ 81214966Sjoerg stat.aue_rxstat &= AUE_RXSTAT_MASK; 81379982Sobrien if (stat.aue_rxstat) { 81479982Sobrien ifp->if_ierrors++; 81581248Sru goto tr_setup; 81679982Sobrien } 81779982Sobrien /* No errors; receive the packet. */ 81879982Sobrien actlen -= (sizeof(stat) + ETHER_CRC_LEN); 81987529Sru } 82087529Sru uether_rxbuf(ue, pc, 0, actlen); 82187529Sru 82226192Speter /* FALLTHROUGH */ 82348264Smpp case USB_ST_SETUP: 82426192Spetertr_setup: 82526192Speter usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 82687529Sru usbd_transfer_submit(xfer); 82787529Sru uether_rxflush(ue); 82881248Sru return; 82981248Sru 83087529Sru default: /* Error */ 83156049Speter DPRINTF("bulk read error, %s\n", 83243406Sjulian usbd_errstr(error)); 83343406Sjulian 83468681Sdwmalone if (error != USB_ERR_CANCELLED) { 83568681Sdwmalone /* try to clear stall first */ 83668681Sdwmalone usbd_xfer_set_stall(xfer); 837291754Sngie goto tr_setup; 83887529Sru } 83914966Sjoerg return; 84026192Speter } 84168681Sdwmalone} 84214966Sjoerg 843114068Strhodesstatic void 844114068Strhodesaue_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 84512823Sphk{ 846147647Shmp struct aue_softc *sc = usbd_xfer_softc(xfer); 84787529Sru struct ifnet *ifp = uether_getifp(&sc->sc_ue); 84887529Sru struct usb_page_cache *pc; 84981622Sru struct mbuf *m; 85085367Sjulian uint8_t buf[2]; 85126192Speter int actlen; 85268716Sru 85324091Smpp usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 854175710Sobrien pc = usbd_xfer_get_frame(xfer, 0); 855175710Sobrien 856175710Sobrien switch (USB_GET_STATE(xfer)) { 857175710Sobrien case USB_ST_TRANSFERRED: 858 DPRINTFN(11, "transfer of %d bytes complete\n", actlen); 859 ifp->if_opackets++; 860 861 /* FALLTHROUGH */ 862 case USB_ST_SETUP: 863tr_setup: 864 if ((sc->sc_flags & AUE_FLAG_LINK) == 0) { 865 /* 866 * don't send anything if there is no link ! 867 */ 868 return; 869 } 870 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 871 872 if (m == NULL) 873 return; 874 if (m->m_pkthdr.len > MCLBYTES) 875 m->m_pkthdr.len = MCLBYTES; 876 if (sc->sc_flags & AUE_FLAG_VER_2) { 877 878 usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len); 879 880 usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len); 881 882 } else { 883 884 usbd_xfer_set_frame_len(xfer, 0, (m->m_pkthdr.len + 2)); 885 886 /* 887 * The ADMtek documentation says that the 888 * packet length is supposed to be specified 889 * in the first two bytes of the transfer, 890 * however it actually seems to ignore this 891 * info and base the frame size on the bulk 892 * transfer length. 893 */ 894 buf[0] = (uint8_t)(m->m_pkthdr.len); 895 buf[1] = (uint8_t)(m->m_pkthdr.len >> 8); 896 897 usbd_copy_in(pc, 0, buf, 2); 898 usbd_m_copy_in(pc, 2, m, 0, m->m_pkthdr.len); 899 } 900 901 /* 902 * if there's a BPF listener, bounce a copy 903 * of this frame to him: 904 */ 905 BPF_MTAP(ifp, m); 906 907 m_freem(m); 908 909 usbd_transfer_submit(xfer); 910 return; 911 912 default: /* Error */ 913 DPRINTFN(11, "transfer error, %s\n", 914 usbd_errstr(error)); 915 916 ifp->if_oerrors++; 917 918 if (error != USB_ERR_CANCELLED) { 919 /* try to clear stall first */ 920 usbd_xfer_set_stall(xfer); 921 goto tr_setup; 922 } 923 return; 924 } 925} 926 927static void 928aue_tick(struct usb_ether *ue) 929{ 930 struct aue_softc *sc = uether_getsc(ue); 931 struct mii_data *mii = GET_MII(sc); 932 933 AUE_LOCK_ASSERT(sc, MA_OWNED); 934 935 mii_tick(mii); 936 if ((sc->sc_flags & AUE_FLAG_LINK) == 0 937 && mii->mii_media_status & IFM_ACTIVE && 938 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 939 sc->sc_flags |= AUE_FLAG_LINK; 940 aue_start(ue); 941 } 942} 943 944static void 945aue_start(struct usb_ether *ue) 946{ 947 struct aue_softc *sc = uether_getsc(ue); 948 949 /* 950 * start the USB transfers, if not already started: 951 */ 952 usbd_transfer_start(sc->sc_xfer[AUE_INTR_DT_RD]); 953 usbd_transfer_start(sc->sc_xfer[AUE_BULK_DT_RD]); 954 usbd_transfer_start(sc->sc_xfer[AUE_BULK_DT_WR]); 955} 956 957static void 958aue_init(struct usb_ether *ue) 959{ 960 struct aue_softc *sc = uether_getsc(ue); 961 struct ifnet *ifp = uether_getifp(ue); 962 int i; 963 964 AUE_LOCK_ASSERT(sc, MA_OWNED); 965 966 /* 967 * Cancel pending I/O 968 */ 969 aue_reset(sc); 970 971 /* Set MAC address */ 972 for (i = 0; i != ETHER_ADDR_LEN; i++) 973 aue_csr_write_1(sc, AUE_PAR0 + i, IF_LLADDR(ifp)[i]); 974 975 /* update promiscuous setting */ 976 aue_setpromisc(ue); 977 978 /* Load the multicast filter. */ 979 aue_setmulti(ue); 980 981 /* Enable RX and TX */ 982 aue_csr_write_1(sc, AUE_CTL0, AUE_CTL0_RXSTAT_APPEND | AUE_CTL0_RX_ENB); 983 AUE_SETBIT(sc, AUE_CTL0, AUE_CTL0_TX_ENB); 984 AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_EP3_CLR); 985 986 usbd_xfer_set_stall(sc->sc_xfer[AUE_BULK_DT_WR]); 987 988 ifp->if_drv_flags |= IFF_DRV_RUNNING; 989 aue_start(ue); 990} 991 992static void 993aue_setpromisc(struct usb_ether *ue) 994{ 995 struct aue_softc *sc = uether_getsc(ue); 996 struct ifnet *ifp = uether_getifp(ue); 997 998 AUE_LOCK_ASSERT(sc, MA_OWNED); 999 1000 /* if we want promiscuous mode, set the allframes bit: */ 1001 if (ifp->if_flags & IFF_PROMISC) 1002 AUE_SETBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC); 1003 else 1004 AUE_CLRBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC); 1005} 1006 1007/* 1008 * Set media options. 1009 */ 1010static int 1011aue_ifmedia_upd(struct ifnet *ifp) 1012{ 1013 struct aue_softc *sc = ifp->if_softc; 1014 struct mii_data *mii = GET_MII(sc); 1015 1016 AUE_LOCK_ASSERT(sc, MA_OWNED); 1017 1018 sc->sc_flags &= ~AUE_FLAG_LINK; 1019 if (mii->mii_instance) { 1020 struct mii_softc *miisc; 1021 1022 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 1023 mii_phy_reset(miisc); 1024 } 1025 mii_mediachg(mii); 1026 return (0); 1027} 1028 1029/* 1030 * Report current media status. 1031 */ 1032static void 1033aue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 1034{ 1035 struct aue_softc *sc = ifp->if_softc; 1036 struct mii_data *mii = GET_MII(sc); 1037 1038 AUE_LOCK(sc); 1039 mii_pollstat(mii); 1040 AUE_UNLOCK(sc); 1041 ifmr->ifm_active = mii->mii_media_active; 1042 ifmr->ifm_status = mii->mii_media_status; 1043} 1044 1045/* 1046 * Stop the adapter and free any mbufs allocated to the 1047 * RX and TX lists. 1048 */ 1049static void 1050aue_stop(struct usb_ether *ue) 1051{ 1052 struct aue_softc *sc = uether_getsc(ue); 1053 struct ifnet *ifp = uether_getifp(ue); 1054 1055 AUE_LOCK_ASSERT(sc, MA_OWNED); 1056 1057 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1058 sc->sc_flags &= ~AUE_FLAG_LINK; 1059 1060 /* 1061 * stop all the transfers, if not already stopped: 1062 */ 1063 usbd_transfer_stop(sc->sc_xfer[AUE_BULK_DT_WR]); 1064 usbd_transfer_stop(sc->sc_xfer[AUE_BULK_DT_RD]); 1065 usbd_transfer_stop(sc->sc_xfer[AUE_INTR_DT_RD]); 1066 1067 aue_csr_write_1(sc, AUE_CTL0, 0); 1068 aue_csr_write_1(sc, AUE_CTL1, 0); 1069 aue_reset(sc); 1070} 1071